../src/lowrisc_ibex_ibex_tracer_0.1/rtl/ibex_tracer.sv Cov: 100%

   1: // Copyright lowRISC contributors.
   2: // Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md.
   3: // Licensed under the Apache License, Version 2.0, see LICENSE for details.
   4: // SPDX-License-Identifier: Apache-2.0
   5: 
   6: /**
   7:  * Trace executed instructions in simulation
   8:  *
   9:  * This tracer takes execution information from the RISC-V Verification Interface (RVFI) and
  10:  * produces a text file with a human-readable trace.
  11:  *
  12:  * All traced instructions are written to a log file. By default, the log file is named
  13:  * trace_core_.log, with  being the 8 digit hart ID of the core being traced.
  14:  *
  15:  * The file name base, defaulting to "trace_core" can be set using the "ibex_tracer_file_base"
  16:  * plusarg passed to the simulation, e.g. "+ibex_tracer_file_base=ibex_my_trace". The exact syntax
  17:  * of passing plusargs to a simulation depends on the simulator.
  18:  *
  19:  * The trace contains six columns, separated by tabs:
  20:  * - The simulation time
  21:  * - The clock cycle count since reset
  22:  * - The program counter (PC)
  23:  * - The instruction
  24:  * - The decoded instruction in the same format as objdump, together with the accessed registers and
  25:  *   read/written memory values. Jumps and branches show the target address.
  26:  *   This column may be omitted if the instruction does not decode into a long form.
  27:  * - Accessed registers and memory locations.
  28:  *
  29:  * Significant effort is spent to make the decoding produced by this tracer as similar as possible
  30:  * to the one produced by objdump. This simplifies the correlation between the static program
  31:  * information from the objdump-generated disassembly, and the runtime information from this tracer.
  32:  */
  33: module ibex_tracer (
  34:   input logic        clk_i,
  35:   input logic        rst_ni,
  36: 
  37:   input logic [31:0] hart_id_i,
  38: 
  39:   // RVFI as described at https://github.com/SymbioticEDA/riscv-formal/blob/master/docs/rvfi.md
  40:   // The standard interface does not have _i/_o suffixes. For consistency with the standard the
  41:   // signals in this module don't have the suffixes either.
  42:   input logic        rvfi_valid,
  43:   input logic [63:0] rvfi_order,
  44:   input logic [31:0] rvfi_insn,
  45:   input logic        rvfi_trap,
  46:   input logic        rvfi_halt,
  47:   input logic        rvfi_intr,
  48:   input logic [ 1:0] rvfi_mode,
  49:   input logic [ 1:0] rvfi_ixl,
  50:   input logic [ 4:0] rvfi_rs1_addr,
  51:   input logic [ 4:0] rvfi_rs2_addr,
  52:   input logic [ 4:0] rvfi_rs3_addr,
  53:   input logic [31:0] rvfi_rs1_rdata,
  54:   input logic [31:0] rvfi_rs2_rdata,
  55:   input logic [31:0] rvfi_rs3_rdata,
  56:   input logic [ 4:0] rvfi_rd_addr,
  57:   input logic [31:0] rvfi_rd_wdata,
  58:   input logic [31:0] rvfi_pc_rdata,
  59:   input logic [31:0] rvfi_pc_wdata,
  60:   input logic [31:0] rvfi_mem_addr,
  61:   input logic [ 3:0] rvfi_mem_rmask,
  62:   input logic [ 3:0] rvfi_mem_wmask,
  63:   input logic [31:0] rvfi_mem_rdata,
  64:   input logic [31:0] rvfi_mem_wdata
  65: );
  66: 
  67:   // These signals are part of RVFI, but not used in this module currently.
  68:   // Keep them as part of the interface to change the tracer more easily in the future. Assigning
  69:   // these signals to unused_* signals marks them explicitly as unused, an annotation picked up by
  70:   // linters, including Verilator lint.
  71:   logic [63:0] unused_rvfi_order = rvfi_order;
  72:   logic        unused_rvfi_trap = rvfi_trap;
  73:   logic        unused_rvfi_halt = rvfi_halt;
  74:   logic        unused_rvfi_intr = rvfi_intr;
  75:   logic [ 1:0] unused_rvfi_mode = rvfi_mode;
  76:   logic [ 1:0] unused_rvfi_ixl = rvfi_ixl;
  77: 
  78:   import ibex_tracer_pkg::*;
  79: 
  80:   int          file_handle;
  81:   string       file_name;
  82: 
  83:   int unsigned cycle;
  84:   string       decoded_str;
  85:   logic        insn_is_compressed;
  86: 
  87:   // Data items accessed during this instruction
  88:   localparam RS1 = (1 << 0);
  89:   localparam RS2 = (1 << 1);
  90:   localparam RS3 = (1 << 2);
  91:   localparam RD  = (1 << 3);
  92:   localparam MEM = (1 << 4);
  93:   logic [4:0] data_accessed;
  94: 
  95:   function automatic void printbuffer_dumpline();
  96:     string rvfi_insn_str;
  97: 
  98:     if (file_handle == 32'h0) begin
  99:       string file_name_base = "trace_core";
 100:       $value$plusargs("ibex_tracer_file_base=%s", file_name_base);
 101:       $sformat(file_name, "%s_%h.log", file_name_base, hart_id_i);
 102: 
 103:       $display("%m: Writing execution trace to %s", file_name);
 104:       file_handle = $fopen(file_name, "w");
 105:       $fwrite(file_handle, "Time\tCycle\tPC\tInsn\tDecoded instruction\tRegister and memory contents\n");
 106:     end
 107: 
 108:     // Write compressed instructions as four hex digits (16 bit word), and
 109:     // uncompressed ones as 8 hex digits (32 bit words).
 110:     if (insn_is_compressed) begin
 111:       rvfi_insn_str = $sformatf("%h", rvfi_insn[15:0]);
 112:     end else begin
 113:       rvfi_insn_str = $sformatf("%h", rvfi_insn);
 114:     end
 115: 
 116:     $fwrite(file_handle, "%15t\t%d\t%h\t%s\t%s\t", $time, cycle, rvfi_pc_rdata, rvfi_insn_str, decoded_str);
 117: 
 118:     if ((data_accessed & RS1) != 0) begin
 119:       $fwrite(file_handle, " %s:0x%08x", reg_addr_to_str(rvfi_rs1_addr), rvfi_rs1_rdata);
 120:     end
 121:     if ((data_accessed & RS2) != 0) begin
 122:       $fwrite(file_handle, " %s:0x%08x", reg_addr_to_str(rvfi_rs2_addr), rvfi_rs2_rdata);
 123:     end
 124:     if ((data_accessed & RS3) != 0) begin
 125:       $fwrite(file_handle, " %s:0x%08x", reg_addr_to_str(rvfi_rs3_addr), rvfi_rs3_rdata);
 126:     end
 127:     if ((data_accessed & RD) != 0) begin
 128:       $fwrite(file_handle, " %s=0x%08x", reg_addr_to_str(rvfi_rd_addr), rvfi_rd_wdata);
 129:     end
 130:     if ((data_accessed & MEM) != 0) begin
 131:       $fwrite(file_handle, " PA:0x%08x", rvfi_mem_addr);
 132: 
 133:       if (rvfi_mem_rmask != 4'b000) begin
 134:         $fwrite(file_handle, " store:0x%08x", rvfi_mem_wdata);
 135:       end
 136:       if (rvfi_mem_wmask != 4'b000) begin
 137:         $fwrite(file_handle, " load:0x%08x", rvfi_mem_rdata);
 138:       end
 139:     end
 140: 
 141:     $fwrite(file_handle, "\n");
 142:   endfunction
 143: 
 144: 
 145:   // Format register address with "x" prefix, left-aligned to a fixed width of 3 characters.
 146:   function automatic string reg_addr_to_str(input logic [4:0] addr);
 147:     if (addr < 10) begin
 148:       return $sformatf(" x%0d", addr);
 149:     end else begin
 150:       return $sformatf("x%0d", addr);
 151:     end
 152:   endfunction
 153: 
 154:   // Get a CSR name for a CSR address.
 155:   function automatic string get_csr_name(input logic [11:0] csr_addr);
 156:     unique case (csr_addr)
 157:       12'd0: return "ustatus";
 158:       12'd4: return "uie";
 159:       12'd5: return "utvec";
 160:       12'd64: return "uscratch";
 161:       12'd65: return "uepc";
 162:       12'd66: return "ucause";
 163:       12'd67: return "utval";
 164:       12'd68: return "uip";
 165:       12'd1: return "fflags";
 166:       12'd2: return "frm";
 167:       12'd3: return "fcsr";
 168:       12'd3072: return "cycle";
 169:       12'd3073: return "time";
 170:       12'd3074: return "instret";
 171:       12'd3075: return "hpmcounter3";
 172:       12'd3076: return "hpmcounter4";
 173:       12'd3077: return "hpmcounter5";
 174:       12'd3078: return "hpmcounter6";
 175:       12'd3079: return "hpmcounter7";
 176:       12'd3080: return "hpmcounter8";
 177:       12'd3081: return "hpmcounter9";
 178:       12'd3082: return "hpmcounter10";
 179:       12'd3083: return "hpmcounter11";
 180:       12'd3084: return "hpmcounter12";
 181:       12'd3085: return "hpmcounter13";
 182:       12'd3086: return "hpmcounter14";
 183:       12'd3087: return "hpmcounter15";
 184:       12'd3088: return "hpmcounter16";
 185:       12'd3089: return "hpmcounter17";
 186:       12'd3090: return "hpmcounter18";
 187:       12'd3091: return "hpmcounter19";
 188:       12'd3092: return "hpmcounter20";
 189:       12'd3093: return "hpmcounter21";
 190:       12'd3094: return "hpmcounter22";
 191:       12'd3095: return "hpmcounter23";
 192:       12'd3096: return "hpmcounter24";
 193:       12'd3097: return "hpmcounter25";
 194:       12'd3098: return "hpmcounter26";
 195:       12'd3099: return "hpmcounter27";
 196:       12'd3100: return "hpmcounter28";
 197:       12'd3101: return "hpmcounter29";
 198:       12'd3102: return "hpmcounter30";
 199:       12'd3103: return "hpmcounter31";
 200:       12'd3200: return "cycleh";
 201:       12'd3201: return "timeh";
 202:       12'd3202: return "instreth";
 203:       12'd3203: return "hpmcounter3h";
 204:       12'd3204: return "hpmcounter4h";
 205:       12'd3205: return "hpmcounter5h";
 206:       12'd3206: return "hpmcounter6h";
 207:       12'd3207: return "hpmcounter7h";
 208:       12'd3208: return "hpmcounter8h";
 209:       12'd3209: return "hpmcounter9h";
 210:       12'd3210: return "hpmcounter10h";
 211:       12'd3211: return "hpmcounter11h";
 212:       12'd3212: return "hpmcounter12h";
 213:       12'd3213: return "hpmcounter13h";
 214:       12'd3214: return "hpmcounter14h";
 215:       12'd3215: return "hpmcounter15h";
 216:       12'd3216: return "hpmcounter16h";
 217:       12'd3217: return "hpmcounter17h";
 218:       12'd3218: return "hpmcounter18h";
 219:       12'd3219: return "hpmcounter19h";
 220:       12'd3220: return "hpmcounter20h";
 221:       12'd3221: return "hpmcounter21h";
 222:       12'd3222: return "hpmcounter22h";
 223:       12'd3223: return "hpmcounter23h";
 224:       12'd3224: return "hpmcounter24h";
 225:       12'd3225: return "hpmcounter25h";
 226:       12'd3226: return "hpmcounter26h";
 227:       12'd3227: return "hpmcounter27h";
 228:       12'd3228: return "hpmcounter28h";
 229:       12'd3229: return "hpmcounter29h";
 230:       12'd3230: return "hpmcounter30h";
 231:       12'd3231: return "hpmcounter31h";
 232:       12'd256: return "sstatus";
 233:       12'd258: return "sedeleg";
 234:       12'd259: return "sideleg";
 235:       12'd260: return "sie";
 236:       12'd261: return "stvec";
 237:       12'd262: return "scounteren";
 238:       12'd320: return "sscratch";
 239:       12'd321: return "sepc";
 240:       12'd322: return "scause";
 241:       12'd323: return "stval";
 242:       12'd324: return "sip";
 243:       12'd384: return "satp";
 244:       12'd3857: return "mvendorid";
 245:       12'd3858: return "marchid";
 246:       12'd3859: return "mimpid";
 247:       12'd3860: return "mhartid";
 248:       12'd768: return "mstatus";
 249:       12'd769: return "misa";
 250:       12'd770: return "medeleg";
 251:       12'd771: return "mideleg";
 252:       12'd772: return "mie";
 253:       12'd773: return "mtvec";
 254:       12'd774: return "mcounteren";
 255:       12'd832: return "mscratch";
 256:       12'd833: return "mepc";
 257:       12'd834: return "mcause";
 258:       12'd835: return "mtval";
 259:       12'd836: return "mip";
 260:       12'd928: return "pmpcfg0";
 261:       12'd929: return "pmpcfg1";
 262:       12'd930: return "pmpcfg2";
 263:       12'd931: return "pmpcfg3";
 264:       12'd944: return "pmpaddr0";
 265:       12'd945: return "pmpaddr1";
 266:       12'd946: return "pmpaddr2";
 267:       12'd947: return "pmpaddr3";
 268:       12'd948: return "pmpaddr4";
 269:       12'd949: return "pmpaddr5";
 270:       12'd950: return "pmpaddr6";
 271:       12'd951: return "pmpaddr7";
 272:       12'd952: return "pmpaddr8";
 273:       12'd953: return "pmpaddr9";
 274:       12'd954: return "pmpaddr10";
 275:       12'd955: return "pmpaddr11";
 276:       12'd956: return "pmpaddr12";
 277:       12'd957: return "pmpaddr13";
 278:       12'd958: return "pmpaddr14";
 279:       12'd959: return "pmpaddr15";
 280:       12'd2816: return "mcycle";
 281:       12'd2818: return "minstret";
 282:       12'd2819: return "mhpmcounter3";
 283:       12'd2820: return "mhpmcounter4";
 284:       12'd2821: return "mhpmcounter5";
 285:       12'd2822: return "mhpmcounter6";
 286:       12'd2823: return "mhpmcounter7";
 287:       12'd2824: return "mhpmcounter8";
 288:       12'd2825: return "mhpmcounter9";
 289:       12'd2826: return "mhpmcounter10";
 290:       12'd2827: return "mhpmcounter11";
 291:       12'd2828: return "mhpmcounter12";
 292:       12'd2829: return "mhpmcounter13";
 293:       12'd2830: return "mhpmcounter14";
 294:       12'd2831: return "mhpmcounter15";
 295:       12'd2832: return "mhpmcounter16";
 296:       12'd2833: return "mhpmcounter17";
 297:       12'd2834: return "mhpmcounter18";
 298:       12'd2835: return "mhpmcounter19";
 299:       12'd2836: return "mhpmcounter20";
 300:       12'd2837: return "mhpmcounter21";
 301:       12'd2838: return "mhpmcounter22";
 302:       12'd2839: return "mhpmcounter23";
 303:       12'd2840: return "mhpmcounter24";
 304:       12'd2841: return "mhpmcounter25";
 305:       12'd2842: return "mhpmcounter26";
 306:       12'd2843: return "mhpmcounter27";
 307:       12'd2844: return "mhpmcounter28";
 308:       12'd2845: return "mhpmcounter29";
 309:       12'd2846: return "mhpmcounter30";
 310:       12'd2847: return "mhpmcounter31";
 311:       12'd2944: return "mcycleh";
 312:       12'd2946: return "minstreth";
 313:       12'd2947: return "mhpmcounter3h";
 314:       12'd2948: return "mhpmcounter4h";
 315:       12'd2949: return "mhpmcounter5h";
 316:       12'd2950: return "mhpmcounter6h";
 317:       12'd2951: return "mhpmcounter7h";
 318:       12'd2952: return "mhpmcounter8h";
 319:       12'd2953: return "mhpmcounter9h";
 320:       12'd2954: return "mhpmcounter10h";
 321:       12'd2955: return "mhpmcounter11h";
 322:       12'd2956: return "mhpmcounter12h";
 323:       12'd2957: return "mhpmcounter13h";
 324:       12'd2958: return "mhpmcounter14h";
 325:       12'd2959: return "mhpmcounter15h";
 326:       12'd2960: return "mhpmcounter16h";
 327:       12'd2961: return "mhpmcounter17h";
 328:       12'd2962: return "mhpmcounter18h";
 329:       12'd2963: return "mhpmcounter19h";
 330:       12'd2964: return "mhpmcounter20h";
 331:       12'd2965: return "mhpmcounter21h";
 332:       12'd2966: return "mhpmcounter22h";
 333:       12'd2967: return "mhpmcounter23h";
 334:       12'd2968: return "mhpmcounter24h";
 335:       12'd2969: return "mhpmcounter25h";
 336:       12'd2970: return "mhpmcounter26h";
 337:       12'd2971: return "mhpmcounter27h";
 338:       12'd2972: return "mhpmcounter28h";
 339:       12'd2973: return "mhpmcounter29h";
 340:       12'd2974: return "mhpmcounter30h";
 341:       12'd2975: return "mhpmcounter31h";
 342:       12'd803: return "mhpmevent3";
 343:       12'd804: return "mhpmevent4";
 344:       12'd805: return "mhpmevent5";
 345:       12'd806: return "mhpmevent6";
 346:       12'd807: return "mhpmevent7";
 347:       12'd808: return "mhpmevent8";
 348:       12'd809: return "mhpmevent9";
 349:       12'd810: return "mhpmevent10";
 350:       12'd811: return "mhpmevent11";
 351:       12'd812: return "mhpmevent12";
 352:       12'd813: return "mhpmevent13";
 353:       12'd814: return "mhpmevent14";
 354:       12'd815: return "mhpmevent15";
 355:       12'd816: return "mhpmevent16";
 356:       12'd817: return "mhpmevent17";
 357:       12'd818: return "mhpmevent18";
 358:       12'd819: return "mhpmevent19";
 359:       12'd820: return "mhpmevent20";
 360:       12'd821: return "mhpmevent21";
 361:       12'd822: return "mhpmevent22";
 362:       12'd823: return "mhpmevent23";
 363:       12'd824: return "mhpmevent24";
 364:       12'd825: return "mhpmevent25";
 365:       12'd826: return "mhpmevent26";
 366:       12'd827: return "mhpmevent27";
 367:       12'd828: return "mhpmevent28";
 368:       12'd829: return "mhpmevent29";
 369:       12'd830: return "mhpmevent30";
 370:       12'd831: return "mhpmevent31";
 371:       12'd1952: return "tselect";
 372:       12'd1953: return "tdata1";
 373:       12'd1954: return "tdata2";
 374:       12'd1955: return "tdata3";
 375:       12'd1968: return "dcsr";
 376:       12'd1969: return "dpc";
 377:       12'd1970: return "dscratch";
 378:       12'd512: return "hstatus";
 379:       12'd514: return "hedeleg";
 380:       12'd515: return "hideleg";
 381:       12'd516: return "hie";
 382:       12'd517: return "htvec";
 383:       12'd576: return "hscratch";
 384:       12'd577: return "hepc";
 385:       12'd578: return "hcause";
 386:       12'd579: return "hbadaddr";
 387:       12'd580: return "hip";
 388:       12'd896: return "mbase";
 389:       12'd897: return "mbound";
 390:       12'd898: return "mibase";
 391:       12'd899: return "mibound";
 392:       12'd900: return "mdbase";
 393:       12'd901: return "mdbound";
 394:       12'd800: return "mucounteren";
 395:       12'd801: return "mscounteren";
 396:       12'd802: return "mhcounteren";
 397:       default: return $sformatf("0x%x", csr_addr);
 398:     endcase
 399:   endfunction
 400: 
 401:   function automatic void decode_mnemonic(input string mnemonic);
 402:     decoded_str = mnemonic;
 403:   endfunction
 404: 
 405:   function automatic void decode_r_insn(input string mnemonic);
 406:     data_accessed = RS1 | RS2 | RD;
 407:     decoded_str = $sformatf("%s\tx%0d,x%0d,x%0d", mnemonic, rvfi_rd_addr, rvfi_rs1_addr,
 408:         rvfi_rs2_addr);
 409:   endfunction
 410: 
 411:   function automatic void decode_r1_insn(input string mnemonic);
 412:     data_accessed = RS1 | RD;
 413:     decoded_str = $sformatf("%s\tx%0d,x%0d", mnemonic, rvfi_rd_addr, rvfi_rs1_addr);
 414:   endfunction
 415: 
 416:   function automatic void decode_r_cmixcmov_insn(input string mnemonic);
 417:     data_accessed = RS1 | RS2 | RS3 | RD;
 418:     decoded_str = $sformatf("%s\tx%0d,x%0d,x%0d,x%0d", mnemonic, rvfi_rd_addr, rvfi_rs2_addr,
 419:         rvfi_rs1_addr, rvfi_rs3_addr);
 420:   endfunction
 421: 
 422:   function automatic void decode_r_funnelshift_insn(input string mnemonic);
 423:     data_accessed = RS1 | RS2 | RS3 | RD;
 424:     decoded_str = $sformatf("%s\tx%0d,x%0d,x%0d,x%0d", mnemonic, rvfi_rd_addr, rvfi_rs1_addr,
 425:         rvfi_rs3_addr, rvfi_rs2_addr);
 426:   endfunction
 427: 
 428:   function automatic void decode_i_insn(input string mnemonic);
 429:     data_accessed = RS1 | RD;
 430:     decoded_str = $sformatf("%s\tx%0d,x%0d,%0d", mnemonic, rvfi_rd_addr, rvfi_rs1_addr,
 431:                     $signed({{20 {rvfi_insn[31]}}, rvfi_insn[31:20]}));
 432:   endfunction
 433: 
 434:   function automatic void decode_i_shift_insn(input string mnemonic);
 435:     // SLLI, SRLI, SRAI, SROI, SLOI, RORI
 436:     logic [4:0] shamt;
 437:     shamt = {rvfi_insn[24:20]};
 438:     data_accessed = RS1 | RD;
 439:     decoded_str = $sformatf("%s\tx%0d,x%0d,0x%0x", mnemonic, rvfi_rd_addr, rvfi_rs1_addr, shamt);
 440:   endfunction
 441: 
 442:   function automatic void decode_i_funnelshift_insn( input string mnemonic);
 443:     // fsri
 444:     logic [5:0] shamt;
 445:     shamt = {rvfi_insn[25:20]};
 446:     data_accessed = RS1 | RS3 | RD;
 447:     decoded_str = $sformatf("%s\tx%0d,x%0d,x%0d,0x%0x", mnemonic, rvfi_rd_addr, rvfi_rs1_addr,
 448:         rvfi_rs3_addr, shamt);
 449:   endfunction
 450: 
 451:   function automatic void decode_i_jalr_insn(input string mnemonic);
 452:     // JALR
 453:     data_accessed = RS1 | RD;
 454:     decoded_str = $sformatf("%s\tx%0d,%0d(x%0d)", mnemonic, rvfi_rd_addr,
 455:         $signed({{20 {rvfi_insn[31]}}, rvfi_insn[31:20]}), rvfi_rs1_addr);
 456:   endfunction
 457: 
 458:   function automatic void decode_u_insn(input string mnemonic);
 459:     data_accessed = RD;
 460:     decoded_str = $sformatf("%s\tx%0d,0x%0x", mnemonic, rvfi_rd_addr, {rvfi_insn[31:12]});
 461:   endfunction
 462: 
 463:   function automatic void decode_j_insn(input string mnemonic);
 464:     // JAL
 465:     data_accessed = RD;
 466:     decoded_str = $sformatf("%s\tx%0d,%0x", mnemonic, rvfi_rd_addr, rvfi_pc_wdata);
 467:   endfunction
 468: 
 469:   function automatic void decode_b_insn(input string mnemonic);
 470:     logic [31:0] branch_target;
 471:     logic [31:0] imm;
 472: 
 473:     // We cannot use rvfi_pc_wdata for conditional jumps.
 474:     imm = $signed({ {19 {rvfi_insn[31]}}, rvfi_insn[31], rvfi_insn[7],
 475:              rvfi_insn[30:25], rvfi_insn[11:8], 1'b0 });
 476:     branch_target = rvfi_pc_rdata + imm;
 477: 
 478:     data_accessed = RS1 | RS2 | RD;
 479:     decoded_str = $sformatf("%s\tx%0d,x%0d,%0x", mnemonic, rvfi_rs1_addr, rvfi_rs2_addr, branch_target);
 480:   endfunction
 481: 
 482:   function automatic void decode_csr_insn(input string mnemonic);
 483:     logic [11:0] csr;
 484:     string csr_name;
 485:     csr = rvfi_insn[31:20];
 486:     csr_name = get_csr_name(csr);
 487: 
 488:     data_accessed = RD;
 489: 
 490:     if (!rvfi_insn[14]) begin
 491:       data_accessed |= RS1;
 492:       decoded_str = $sformatf("%s\tx%0d,%s,x%0d", mnemonic, rvfi_rd_addr, csr_name, rvfi_rs1_addr);
 493:     end else begin
 494:       decoded_str = $sformatf("%s\tx%0d,%s,%0d", mnemonic, rvfi_rd_addr, csr_name, { 27'b0, rvfi_insn[19:15]});
 495:     end
 496:   endfunction
 497: 
 498:   function automatic void decode_cr_insn(input string mnemonic);
 499:     if (rvfi_rs2_addr == 5'b0) begin
 500:       if (rvfi_insn[12] == 1'b1) begin
 501:         // C.JALR
 502:         data_accessed = RS1 | RD;
 503:       end else begin
 504:         // C.JR
 505:         data_accessed = RS1;
 506:       end
 507:       decoded_str = $sformatf("%s\tx%0d", mnemonic, rvfi_rs1_addr);
 508:     end else begin
 509:       data_accessed = RS1 | RS2 | RD; // RS1 == RD
 510:       decoded_str = $sformatf("%s\tx%0d,x%0d", mnemonic, rvfi_rd_addr, rvfi_rs2_addr);
 511:     end
 512:   endfunction
 513: 
 514:   function automatic void decode_ci_cli_insn(input string mnemonic);
 515:     logic [5:0] imm;
 516:     imm = {rvfi_insn[12], rvfi_insn[6:2]};
 517:     data_accessed = RD;
 518:     decoded_str = $sformatf("%s\tx%0d,%0d", mnemonic, rvfi_rd_addr, $signed(imm));
 519:   endfunction
 520: 
 521:   function automatic void decode_ci_caddi_insn(input string mnemonic);
 522:     logic [5:0] nzimm;
 523:     nzimm = {rvfi_insn[12], rvfi_insn[6:2]};
 524:     data_accessed = RS1 | RD;
 525:     decoded_str = $sformatf("%s\tx%0d,%0d", mnemonic, rvfi_rd_addr, $signed(nzimm));
 526:   endfunction
 527: 
 528:   function automatic void decode_ci_caddi16sp_insn(input string mnemonic);
 529:     logic [9:0] nzimm;
 530:     nzimm = {rvfi_insn[12], rvfi_insn[4:3], rvfi_insn[5], rvfi_insn[2], rvfi_insn[6], 4'b0};
 531:     data_accessed = RS1 | RD;
 532:     decoded_str = $sformatf("%s\tx%0d,%0d", mnemonic, rvfi_rd_addr, $signed(nzimm));
 533:   endfunction
 534: 
 535:   function automatic void decode_ci_clui_insn(input string mnemonic);
 536:     logic [5:0] nzimm;
 537:     nzimm = {rvfi_insn[12], rvfi_insn[6:2]};
 538:     data_accessed = RD;
 539:     decoded_str = $sformatf("%s\tx%0d,0x%0x", mnemonic, rvfi_rd_addr, 20'($signed(nzimm)));
 540:   endfunction
 541: 
 542:   function automatic void decode_ci_cslli_insn(input string mnemonic);
 543:     logic [5:0] shamt;
 544:     shamt = {rvfi_insn[12], rvfi_insn[6:2]};
 545:     data_accessed = RS1 | RD;
 546:     decoded_str = $sformatf("%s\tx%0d,0x%0x", mnemonic, rvfi_rd_addr, shamt);
 547:   endfunction
 548: 
 549:   function automatic void decode_ciw_insn(input string mnemonic);
 550:     // C.ADDI4SPN
 551:     logic [9:0] nzuimm;
 552:     nzuimm = {rvfi_insn[10:7], rvfi_insn[12:11], rvfi_insn[5], rvfi_insn[6], 2'b00};
 553:     data_accessed = RD;
 554:     decoded_str = $sformatf("%s\tx%0d,x2,%0d", mnemonic, rvfi_rd_addr, nzuimm);
 555:   endfunction
 556: 
 557:   function automatic void decode_cb_sr_insn(input string mnemonic);
 558:     logic [5:0] shamt;
 559:     shamt = {rvfi_insn[12], rvfi_insn[6:2]};
 560:     data_accessed = RS1 | RD;
 561:     decoded_str = $sformatf("%s\tx%0d,0x%0x", mnemonic, rvfi_rs1_addr, shamt);
 562:   endfunction
 563: 
 564:   function automatic void decode_cb_insn(input string mnemonic);
 565:     logic [7:0] imm;
 566:     logic [31:0] jump_target;
 567:     if (rvfi_insn[15:13] == 3'b110 || rvfi_insn[15:13] == 3'b111) begin
 568:       // C.BNEZ and C.BEQZ
 569:       // We cannot use rvfi_pc_wdata for conditional jumps.
 570:       imm = {rvfi_insn[12], rvfi_insn[6:5], rvfi_insn[2], rvfi_insn[11:10], rvfi_insn[4:3]};
 571:       jump_target = rvfi_pc_rdata + 32'($signed({imm, 1'b0}));
 572:       data_accessed = RS1;
 573:       decoded_str = $sformatf("%s\tx%0d,%0x", mnemonic, rvfi_rs1_addr, jump_target);
 574:     end else if (rvfi_insn[15:13] == 3'b100) begin
 575:       // C.ANDI
 576:       imm = {{2{rvfi_insn[12]}}, rvfi_insn[12], rvfi_insn[6:2]};
 577:       data_accessed = RS1 | RD; // RS1 == RD
 578:       decoded_str = $sformatf("%s\tx%0d,%0d", mnemonic, rvfi_rd_addr, $signed(imm));
 579:     end else begin
 580:       imm = {rvfi_insn[12], rvfi_insn[6:2], 2'b00};
 581:       data_accessed = RS1;
 582:       decoded_str = $sformatf("%s\tx%0d,0x%0x", mnemonic, rvfi_rs1_addr, imm);
 583:     end
 584:   endfunction
 585: 
 586:   function automatic void decode_cs_insn(input string mnemonic);
 587:     data_accessed = RS1 | RS2 | RD; // RS1 == RD
 588:     decoded_str = $sformatf("%s\tx%0d,x%0d", mnemonic, rvfi_rd_addr, rvfi_rs2_addr);
 589:   endfunction
 590: 
 591:   function automatic void decode_cj_insn(input string mnemonic);
 592:     if (rvfi_insn[15:13] == 3'b001) begin
 593:       // C.JAL
 594:       data_accessed = RD;
 595:     end
 596:     decoded_str = $sformatf("%s\t%0x", mnemonic, rvfi_pc_wdata);
 597:   endfunction
 598: 
 599:   function automatic void decode_compressed_load_insn(input string mnemonic);
 600:     logic [7:0] imm;
 601: 
 602:     if (rvfi_insn[1:0] == OPCODE_C0) begin
 603:       // C.LW
 604:       imm = {1'b0, rvfi_insn[5], rvfi_insn[12:10], rvfi_insn[6], 2'b00};
 605:     end else begin
 606:       // C.LWSP
 607:       imm = {rvfi_insn[3:2], rvfi_insn[12], rvfi_insn[6:4], 2'b00};
 608:     end
 609:     data_accessed = RS1 | RD | MEM;
 610:     decoded_str = $sformatf("%s\tx%0d,%0d(x%0d)", mnemonic, rvfi_rd_addr, imm, rvfi_rs1_addr);
 611:   endfunction
 612: 
 613:   function automatic void decode_compressed_store_insn(input string mnemonic);
 614:     logic [7:0] imm;
 615:     if (rvfi_insn[1:0] == OPCODE_C0) begin
 616:       // C.SW
 617:       imm = {1'b0, rvfi_insn[5], rvfi_insn[12:10], rvfi_insn[6], 2'b00};
 618:     end else begin
 619:       // C.SWSP
 620:       imm = {rvfi_insn[8:7], rvfi_insn[12:9], 2'b00};
 621:     end
 622:     data_accessed = RS1 | RS2 | MEM;
 623:     decoded_str = $sformatf("%s\tx%0d,%0d(x%0d)", mnemonic, rvfi_rs2_addr, imm, rvfi_rs1_addr);
 624:   endfunction
 625: 
 626:   function automatic void decode_load_insn();
 627:     string      mnemonic;
 628: 
 629:     /*
 630:     Gives wrong results in Verilator < 4.020.
 631:     See https://github.com/lowRISC/ibex/issues/372 and
 632:     https://www.veripool.org/issues/1536-Verilator-Misoptimization-in-if-and-case-with-default-statement-inside-a-function
 633: 
 634:     unique case (rvfi_insn[14:12])
 635:       3'b000: mnemonic = "lb";
 636:       3'b001: mnemonic = "lh";
 637:       3'b010: mnemonic = "lw";
 638:       3'b100: mnemonic = "lbu";
 639:       3'b101: mnemonic = "lhu";
 640:       default: begin
 641:         decode_mnemonic("INVALID");
 642:         return;
 643:       end
 644:     endcase
 645:     */
 646:     logic [2:0] size;
 647:     size = rvfi_insn[14:12];
 648:     if (size == 3'b000) begin
 649:       mnemonic = "lb";
 650:     end else if (size == 3'b001) begin
 651:       mnemonic = "lh";
 652:     end else if (size == 3'b010) begin
 653:       mnemonic = "lw";
 654:     end else if (size == 3'b100) begin
 655:       mnemonic = "lbu";
 656:     end else if (size == 3'b101) begin
 657:       mnemonic = "lhu";
 658:     end else begin
 659:       decode_mnemonic("INVALID");
 660:       return;
 661:     end
 662: 
 663: 
 664:     data_accessed = RD | RS1 | MEM;
 665:     decoded_str = $sformatf("%s\tx%0d,%0d(x%0d)", mnemonic, rvfi_rd_addr,
 666:                     $signed({{20 {rvfi_insn[31]}}, rvfi_insn[31:20]}), rvfi_rs1_addr);
 667:   endfunction
 668: 
 669:   function automatic void decode_store_insn();
 670:     string    mnemonic;
 671: 
 672:     unique case (rvfi_insn[13:12])
 673:       2'b00:  mnemonic = "sb";
 674:       2'b01:  mnemonic = "sh";
 675:       2'b10:  mnemonic = "sw";
 676:       default: begin
 677:         decode_mnemonic("INVALID");
 678:         return;
 679:       end
 680:     endcase
 681: 
 682:     if (!rvfi_insn[14]) begin
 683:       // regular store
 684:       data_accessed = RS1 | RS2 | MEM;
 685:       decoded_str = $sformatf("%s\tx%0d,%0d(x%0d)", mnemonic, rvfi_rs2_addr,
 686:                       $signed({ {20 {rvfi_insn[31]}}, rvfi_insn[31:25], rvfi_insn[11:7] }), rvfi_rs1_addr);
 687:     end else begin
 688:       decode_mnemonic("INVALID");
 689:     end
 690:   endfunction
 691: 
 692:   function automatic string get_fence_description(logic [3:0] bits);
 693:     string desc = "";
 694:     if (bits[3]) begin
 695:       desc = {desc, "i"};
 696:     end
 697:     if (bits[2]) begin
 698:       desc = {desc, "o"};
 699:     end
 700:     if (bits[1]) begin
 701:       desc = {desc, "r"};
 702:     end
 703:     if (bits[0]) begin
 704:       desc = {desc, "w"};
 705:     end
 706:     return desc;
 707:   endfunction
 708: 
 709:   function automatic void decode_fence();
 710:     string predecessor;
 711:     string successor;
 712:     predecessor = get_fence_description(rvfi_insn[27:24]);
 713:     successor = get_fence_description(rvfi_insn[23:20]);
 714:     decoded_str = $sformatf("fence\t%s,%s", predecessor, successor);
 715:   endfunction
 716: 
 717:   // cycle counter
 718:   always_ff @(posedge clk_i or negedge rst_ni) begin
 719:     if (!rst_ni) begin
 720:       cycle <= 0;
 721:     end else begin
 722:       cycle <= cycle + 1;
 723:     end
 724:   end
 725: 
 726:   // close output file for writing
 727:   final begin
 728:     if (file_handle != 32'h0) begin
 729:       $fclose(file_handle);
 730:     end
 731:   end
 732: 
 733:   // log execution
 734:   always_ff @(posedge clk_i) begin
 735:     if (rvfi_valid) begin
 736:       printbuffer_dumpline();
 737:     end
 738:   end
 739: 
 740:   always_comb begin
 741:     decoded_str = "";
 742:     data_accessed = 5'h0;
 743:     insn_is_compressed = 0;
 744: 
 745:     // Check for compressed instructions
 746:     if (rvfi_insn[1:0] != 2'b11) begin
 747:       insn_is_compressed = 1;
 748:       // Separate case to avoid overlapping decoding
 749:       if (rvfi_insn[15:13] == 3'b100 && rvfi_insn[1:0] == 2'b10) begin
 750:         if (rvfi_insn[12]) begin
 751:           if (rvfi_insn[11:2] == 10'h0) begin
 752:             decode_mnemonic("c.ebreak");
 753:           end else if (rvfi_insn[6:2] == 5'b0) begin
 754:             decode_cr_insn("c.jalr");
 755:           end else begin
 756:             decode_cr_insn("c.add");
 757:           end
 758:         end else begin
 759:           if (rvfi_insn[6:2] == 5'h0) begin
 760:             decode_cr_insn("c.jr");
 761:           end else begin
 762:             decode_cr_insn("c.mv");
 763:           end
 764:         end
 765:       end else begin
 766:         unique casez (rvfi_insn[15:0])
 767:           // C0 Opcodes
 768:           INSN_CADDI4SPN: begin
 769:             if (rvfi_insn[12:2] == 11'h0) begin
 770:               // Align with pseudo-mnemonic used by GNU binutils and LLVM's MC layer
 771:               decode_mnemonic("c.unimp");
 772:             end else begin
 773:               decode_ciw_insn("c.addi4spn");
 774:             end
 775:           end
 776:           INSN_CLW:        decode_compressed_load_insn("c.lw");
 777:           INSN_CSW:        decode_compressed_store_insn("c.sw");
 778:           // C1 Opcodes
 779:           INSN_CADDI:      decode_ci_caddi_insn("c.addi");
 780:           INSN_CJAL:       decode_cj_insn("c.jal");
 781:           INSN_CJ:         decode_cj_insn("c.j");
 782:           INSN_CLI:        decode_ci_cli_insn("c.li");
 783:           INSN_CLUI: begin
 784:             // These two instructions share opcode
 785:             if (rvfi_insn[11:7] == 5'd2) begin
 786:               decode_ci_caddi16sp_insn("c.addi16sp");
 787:             end else begin
 788:               decode_ci_clui_insn("c.lui");
 789:             end
 790:           end
 791:           INSN_CSRLI:      decode_cb_sr_insn("c.srli");
 792:           INSN_CSRAI:      decode_cb_sr_insn("c.srai");
 793:           INSN_CANDI:      decode_cb_insn("c.andi");
 794:           INSN_CSUB:       decode_cs_insn("c.sub");
 795:           INSN_CXOR:       decode_cs_insn("c.xor");
 796:           INSN_COR:        decode_cs_insn("c.or");
 797:           INSN_CAND:       decode_cs_insn("c.and");
 798:           INSN_CBEQZ:      decode_cb_insn("c.beqz");
 799:           INSN_CBNEZ:      decode_cb_insn("c.bnez");
 800:           // C2 Opcodes
 801:           INSN_CSLLI:      decode_ci_cslli_insn("c.slli");
 802:           INSN_CLWSP:      decode_compressed_load_insn("c.lwsp");
 803:           INSN_SWSP:       decode_compressed_store_insn("c.swsp");
 804:           default:         decode_mnemonic("INVALID");
 805:         endcase
 806:       end
 807:     end else begin
 808:       unique casez (rvfi_insn)
 809:         // Regular opcodes
 810:         INSN_LUI:        decode_u_insn("lui");
 811:         INSN_AUIPC:      decode_u_insn("auipc");
 812:         INSN_JAL:        decode_j_insn("jal");
 813:         INSN_JALR:       decode_i_jalr_insn("jalr");
 814:         // BRANCH
 815:         INSN_BEQ:        decode_b_insn("beq");
 816:         INSN_BNE:        decode_b_insn("bne");
 817:         INSN_BLT:        decode_b_insn("blt");
 818:         INSN_BGE:        decode_b_insn("bge");
 819:         INSN_BLTU:       decode_b_insn("bltu");
 820:         INSN_BGEU:       decode_b_insn("bgeu");
 821:         // OPIMM
 822:         INSN_ADDI: begin
 823:           if (rvfi_insn == 32'h00_00_00_13) begin
 824:             // TODO: objdump doesn't decode this as nop currently, even though it would be helpful
 825:             // Decide what to do here: diverge from objdump, or make the trace less readable to
 826:             // users.
 827:             //decode_mnemonic("nop");
 828:             decode_i_insn("addi");
 829:           end else begin
 830:             decode_i_insn("addi");
 831:           end
 832:         end
 833:         INSN_SLTI:       decode_i_insn("slti");
 834:         INSN_SLTIU:      decode_i_insn("sltiu");
 835:         INSN_XORI:       decode_i_insn("xori");
 836:         INSN_ORI:        decode_i_insn("ori");
 837:         // Version 0.92 of the Bitmanip Extension defines the pseudo-instruction
 838:         // zext.b rd rs = andi rd, rs, 255.
 839:         // Currently instruction set simulators don't output this pseudo-instruction.
 840:         INSN_ANDI:       decode_i_insn("andi");
 841:         // INSN_ANDI:begin
 842:           // casez (rvfi_insn)
 843:             // INSN_ZEXTB:  decode_r1_insn("zext.b");
 844:             // default:     decode_i_insn("andi");
 845:           // endcase
 846:         // end
 847:         INSN_SLLI:       decode_i_shift_insn("slli");
 848:         INSN_SRLI:       decode_i_shift_insn("srli");
 849:         INSN_SRAI:       decode_i_shift_insn("srai");
 850:         // OP
 851:         INSN_ADD:        decode_r_insn("add");
 852:         INSN_SUB:        decode_r_insn("sub");
 853:         INSN_SLL:        decode_r_insn("sll");
 854:         INSN_SLT:        decode_r_insn("slt");
 855:         INSN_SLTU:       decode_r_insn("sltu");
 856:         INSN_XOR:        decode_r_insn("xor");
 857:         INSN_SRL:        decode_r_insn("srl");
 858:         INSN_SRA:        decode_r_insn("sra");
 859:         INSN_OR:         decode_r_insn("or");
 860:         INSN_AND:        decode_r_insn("and");
 861:         // SYSTEM (CSR manipulation)
 862:         INSN_CSRRW:      decode_csr_insn("csrrw");
 863:         INSN_CSRRS:      decode_csr_insn("csrrs");
 864:         INSN_CSRRC:      decode_csr_insn("csrrc");
 865:         INSN_CSRRWI:     decode_csr_insn("csrrwi");
 866:         INSN_CSRRSI:     decode_csr_insn("csrrsi");
 867:         INSN_CSRRCI:     decode_csr_insn("csrrci");
 868:         // SYSTEM (others)
 869:         INSN_ECALL:      decode_mnemonic("ecall");
 870:         INSN_EBREAK:     decode_mnemonic("ebreak");
 871:         INSN_MRET:       decode_mnemonic("mret");
 872:         INSN_DRET:       decode_mnemonic("dret");
 873:         INSN_WFI:        decode_mnemonic("wfi");
 874:         // RV32M
 875:         INSN_PMUL:       decode_r_insn("mul");
 876:         INSN_PMUH:       decode_r_insn("mulh");
 877:         INSN_PMULHSU:    decode_r_insn("mulhsu");
 878:         INSN_PMULHU:     decode_r_insn("mulhu");
 879:         INSN_DIV:        decode_r_insn("div");
 880:         INSN_DIVU:       decode_r_insn("divu");
 881:         INSN_REM:        decode_r_insn("rem");
 882:         INSN_REMU:       decode_r_insn("remu");
 883:         // LOAD & STORE
 884:         INSN_LOAD:       decode_load_insn();
 885:         INSN_STORE:      decode_store_insn();
 886:         // MISC-MEM
 887:         INSN_FENCE:      decode_fence();
 888:         INSN_FENCEI:     decode_mnemonic("fence.i");
 889:         // RV32B - ZBB
 890:         INSN_SLOI:       decode_i_shift_insn("sloi");
 891:         INSN_SROI:       decode_i_shift_insn("sroi");
 892:         INSN_RORI:       decode_i_shift_insn("rori");
 893:         INSN_SLO:        decode_r_insn("slo");
 894:         INSN_SRO:        decode_r_insn("sro");
 895:         INSN_ROL:        decode_r_insn("rol");
 896:         INSN_ROR:        decode_r_insn("ror");
 897:         INSN_MIN:        decode_r_insn("min");
 898:         INSN_MAX:        decode_r_insn("max");
 899:         INSN_MINU:       decode_r_insn("minu");
 900:         INSN_MAXU:       decode_r_insn("maxu");
 901:         INSN_XNOR:       decode_r_insn("xnor");
 902:         INSN_ORN:        decode_r_insn("orn");
 903:         INSN_ANDN:       decode_r_insn("andn");
 904:         // Version 0.92 of the Bitmanip Extension defines the pseudo-instruction
 905:         // zext.h rd rs = pack rd, rs, zero.
 906:         // Currently instruction set simulators don't output this pseudo-instruction.
 907:         INSN_PACK:       decode_r_insn("pack");
 908:         // INSN_PACK: begin
 909:           // casez (rvfi_insn)
 910:             // INSN_ZEXTH:  decode_r1_insn("zext.h");
 911:             // default:     decode_r_insn("pack");
 912:           // endcase
 913:         // end
 914:         INSN_PACKH:      decode_r_insn("packh");
 915:         INSN_PACKU:      decode_r_insn("packu");
 916:         INSN_CLZ:        decode_r1_insn("clz");
 917:         INSN_CTZ:        decode_r1_insn("ctz");
 918:         INSN_PCNT:       decode_r1_insn("pcnt");
 919:         INSN_SEXTB:      decode_r1_insn("sext.b");
 920:         INSN_SEXTH:      decode_r1_insn("sext.h");
 921:         // RV32B - ZBS
 922:         INSN_SBCLRI:     decode_i_insn("sbclri");
 923:         INSN_SBSETI:     decode_i_insn("sbseti");
 924:         INSN_SBINVI:     decode_i_insn("sbinvi");
 925:         INSN_SBEXTI:     decode_i_insn("sbexti");
 926:         INSN_SBCLR:      decode_r_insn("sbclr");
 927:         INSN_SBSET:      decode_r_insn("sbset");
 928:         INSN_SBINV:      decode_r_insn("sbinv");
 929:         INSN_SBEXT:      decode_r_insn("sbext");
 930:         // RV32B - ZBE
 931:         INSN_BDEP:       decode_r_insn("bdep");
 932:         INSN_BEXT:       decode_r_insn("bext");
 933:         // RV32B - ZBP
 934:         INSN_GREV:       decode_r_insn("grev");
 935:         INSN_GREVI: begin
 936:           unique casez (rvfi_insn)
 937:             INSN_REV_P:  decode_r1_insn("rev.p");
 938:             INSN_REV2_N: decode_r1_insn("rev2.n");
 939:             INSN_REV_N:  decode_r1_insn("rev.n");
 940:             INSN_REV4_B: decode_r1_insn("rev4.b");
 941:             INSN_REV2_B: decode_r1_insn("rev2.b");
 942:             INSN_REV_B:  decode_r1_insn("rev.b");
 943:             INSN_REV8_H: decode_r1_insn("rev8.h");
 944:             INSN_REV4_H: decode_r1_insn("rev4.h");
 945:             INSN_REV2_H: decode_r1_insn("rev2.h");
 946:             INSN_REV_H:  decode_r1_insn("rev.h");
 947:             INSN_REV16:  decode_r1_insn("rev16");
 948:             INSN_REV8:   decode_r1_insn("rev8");
 949:             INSN_REV4:   decode_r1_insn("rev4");
 950:             INSN_REV2:   decode_r1_insn("rev2");
 951:             INSN_REV:    decode_r1_insn("rev");
 952:             default:     decode_i_insn("grevi");
 953:           endcase
 954:         end
 955:         INSN_GORC:       decode_r_insn("gorc");
 956:         INSN_GORCI: begin
 957:           unique casez (rvfi_insn)
 958:             INSN_ORC_P:  decode_r1_insn("orc.p");
 959:             INSN_ORC2_N: decode_r1_insn("orc2.n");
 960:             INSN_ORC_N:  decode_r1_insn("orc.n");
 961:             INSN_ORC4_B: decode_r1_insn("orc4.b");
 962:             INSN_ORC2_B: decode_r1_insn("orc2.b");
 963:             INSN_ORC_B:  decode_r1_insn("orc.b");
 964:             INSN_ORC8_H: decode_r1_insn("orc8.h");
 965:             INSN_ORC4_H: decode_r1_insn("orc4.h");
 966:             INSN_ORC2_H: decode_r1_insn("orc2.h");
 967:             INSN_ORC_H:  decode_r1_insn("orc.h");
 968:             INSN_ORC16:  decode_r1_insn("orc16");
 969:             INSN_ORC8:   decode_r1_insn("orc8");
 970:             INSN_ORC4:   decode_r1_insn("orc4");
 971:             INSN_ORC2:   decode_r1_insn("orc2");
 972:             INSN_ORC:    decode_r1_insn("orc");
 973:             default:     decode_i_insn("gorci");
 974:           endcase
 975:         end
 976:         INSN_SHFL:       decode_r_insn("shfl");
 977:         INSN_SHFLI: begin
 978:           unique casez (rvfi_insn)
 979:             INSN_ZIP_N:  decode_r1_insn("zip.n");
 980:             INSN_ZIP2_B: decode_r1_insn("zip2.b");
 981:             INSN_ZIP_B:  decode_r1_insn("zip.b");
 982:             INSN_ZIP4_H: decode_r1_insn("zip4.h");
 983:             INSN_ZIP2_H: decode_r1_insn("zip2.h");
 984:             INSN_ZIP_H:  decode_r1_insn("zip.h");
 985:             INSN_ZIP8:   decode_r1_insn("zip8");
 986:             INSN_ZIP4:   decode_r1_insn("zip4");
 987:             INSN_ZIP2:   decode_r1_insn("zip2");
 988:             INSN_ZIP:    decode_r1_insn("zip");
 989:             default:     decode_i_insn("shfli");
 990:           endcase
 991:         end
 992:         INSN_UNSHFL:       decode_r_insn("unshfl");
 993:         INSN_UNSHFLI: begin
 994:           unique casez (rvfi_insn)
 995:             INSN_UNZIP_N:  decode_r1_insn("unzip.n");
 996:             INSN_UNZIP2_B: decode_r1_insn("unzip2.b");
 997:             INSN_UNZIP_B:  decode_r1_insn("unzip.b");
 998:             INSN_UNZIP4_H: decode_r1_insn("unzip4.h");
 999:             INSN_UNZIP2_H: decode_r1_insn("unzip2.h");
1000:             INSN_UNZIP_H:  decode_r1_insn("unzip.h");
1001:             INSN_UNZIP8:   decode_r1_insn("unzip8");
1002:             INSN_UNZIP4:   decode_r1_insn("unzip4");
1003:             INSN_UNZIP2:   decode_r1_insn("unzip2");
1004:             INSN_UNZIP:    decode_r1_insn("unzip");
1005:             default:       decode_i_insn("unshfli");
1006:           endcase
1007:         end
1008: 
1009:         // RV32B - ZBT
1010:         INSN_CMIX:       decode_r_cmixcmov_insn("cmix");
1011:         INSN_CMOV:       decode_r_cmixcmov_insn("cmov");
1012:         INSN_FSR:        decode_r_funnelshift_insn("fsr");
1013:         INSN_FSL:        decode_r_funnelshift_insn("fsl");
1014:         INSN_FSRI:       decode_i_funnelshift_insn("fsri");
1015: 
1016:         // RV32B - ZBF
1017:         INSN_BFP:        decode_r_insn("bfp");
1018: 
1019:         // RV32B - ZBC
1020:         INSN_CLMUL:      decode_r_insn("clmul");
1021:         INSN_CLMULR:     decode_r_insn("clmulr");
1022:         INSN_CLMULH:     decode_r_insn("clmulh");
1023: 
1024:         // RV32B - ZBR
1025:         INSN_CRC32_B:    decode_r1_insn("crc32.b");
1026:         INSN_CRC32_H:    decode_r1_insn("crc32.h");
1027:         INSN_CRC32_W:    decode_r1_insn("crc32.w");
1028:         INSN_CRC32C_B:   decode_r1_insn("crc32c.b");
1029:         INSN_CRC32C_H:   decode_r1_insn("crc32c.h");
1030:         INSN_CRC32C_W:   decode_r1_insn("crc32c.w");
1031: 
1032:         default:         decode_mnemonic("INVALID");
1033:       endcase
1034:     end
1035:   end
1036: 
1037: endmodule
1038: