code wiki / _hdl_build / nx_decoder_select.nx

nx_decoder_select.nx source

↩ module page · 159 lines · 8423 B

1// nx_decoder_select.nx -- sink-based RV64IM DECODER builder (.nxgate / gsim). 2// 3// The next per-module synth after ALU + regfile. Drives the SAME NxCellSink the ALU uses (MEM sink 4// -> Verifier proves; TEXT sink -> ships the .nxgate). Mirrors nx_alu_select.nx. 5// RUNG 1: 6 field extracts (opcode/rd/funct3/rs1/rs2/funct7) as SHR+AND gates. 6// RUNG 2: opcode -> KIND classifier (11 direct opcodes + 0x33/0x3b M-extension overlays). 7// Both mirror the behavioral oracles in rv64im_min_decoder.nx. Immediate decoders = next rung. 8// MUX convention (per nx_nxgate_sim.nx line 86 + nx_alu_emit_mux_step): fanin (sel, if_true, if_false), 9// out = sel ? if_true : if_false. Flat idiom (loop + intermediate lets) for nx_cc robustness. 10// license_tier: ORIGINAL expect_exit: 0 11import "nx_cell_sink.nx" 12const K_MAGIC_4095: i64 = 4095 13const K_MAGIC_2048: i64 = 2048 14const K_MAGIC_4096: i64 = 4096 15const K_MAGIC_8192: i64 = 8192 16const K_MAGIC_1048575: i64 = 1048575 17const K_MAGIC_1048576: i64 = 1048576 18const K_MAGIC_2097152: i64 = 2097152 19 20// ===== RUNG 1: field extraction ===== 21// one field: out = (inst >> shift) & mask, as SHR then AND gate cells. 22func nx_dec_field(k: *NxCellSink, n_inst: i64, shift: i64, mask: i64) -> i64 { 23 let sc: i64 = nx_sink_const(k, 64, shift) 24 let sh: i64 = nx_sink_cell(k, NX_GATE_KIND_SHR, 64, n_inst, sc, 0 - 1, 2) 25 let mc: i64 = nx_sink_const(k, 64, mask) 26 return nx_sink_cell(k, NX_GATE_KIND_AND, 64, sh, mc, 0 - 1, 2) 27} 28 29// fill outs[0..5] with the field output net ids: opcode, rd, funct3, rs1, rs2, funct7. 30func nx_decoder_fields_build(k: *NxCellSink, n_inst: i64, outs: *i64) -> i64 { 31 outs[0] = nx_dec_field(k, n_inst, 0, 127) // opcode inst[6:0] 32 outs[1] = nx_dec_field(k, n_inst, 7, 31) // rd inst[11:7] 33 outs[2] = nx_dec_field(k, n_inst, 12, 7) // funct3 inst[14:12] 34 outs[3] = nx_dec_field(k, n_inst, 15, 31) // rs1 inst[19:15] 35 outs[4] = nx_dec_field(k, n_inst, 20, 31) // rs2 inst[24:20] 36 outs[5] = nx_dec_field(k, n_inst, 25, 127) // funct7 inst[31:25] 37 return 0 38} 39 40// ===== RUNG 2: opcode -> KIND classifier ===== 41// Mirrors nx_rv64im_decode_kind. Table-driven cascade for the 11 direct opcodes, then the 42// 0x33/0x3b M-extension overlays (funct7==1, disambiguated by funct3). Inputs = extracted 43// opcode/funct7/funct3 net ids. MUX(sel, if_true, if_false). 44func nx_decoder_kind_build(k: *NxCellSink, n_op: i64, n_f7: i64, n_f3: i64) -> i64 { 45 let opc: *i64 = sys_mmap(8 * 16) as *i64 46 let knd: *i64 = sys_mmap(8 * 16) as *i64 47 opc[0] = 55; knd[0] = 1 // 0x37 LUI 48 opc[1] = 23; knd[1] = 2 // 0x17 AUIPC 49 opc[2] = 111; knd[2] = 3 // 0x6f JAL 50 opc[3] = 103; knd[3] = 4 // 0x67 JALR 51 opc[4] = 99; knd[4] = 5 // 0x63 BRANCH 52 opc[5] = 3; knd[5] = 6 // 0x03 LOAD 53 opc[6] = 35; knd[6] = 7 // 0x23 STORE 54 opc[7] = 19; knd[7] = 8 // 0x13 OP_IMM 55 opc[8] = 27; knd[8] = 10 // 0x1b OP_IMM_32 56 opc[9] = 15; knd[9] = 12 // 0x0f FENCE 57 opc[10] = 115; knd[10] = 13 // 0x73 SYSTEM 58 let n_direct: i64 = 11 59 60 let zero: i64 = nx_sink_const(k, 64, 0) 61 var r: i64 = zero // INVALID default 62 var i: i64 = 0 63 while i < n_direct { 64 let oc: i64 = nx_sink_const(k, 64, opc[i]) 65 let mtch: i64 = nx_sink_cell(k, NX_GATE_KIND_EQ, 1, n_op, oc, 0 - 1, 2) 66 let kc: i64 = nx_sink_const(k, 64, knd[i]) 67 r = nx_sink_cell(k, NX_GATE_KIND_MUX, 64, mtch, kc, r, 3) // mtch ? kc : r 68 i = i + 1 69 } 70 71 let one: i64 = nx_sink_const(k, 64, 1) 72 // 0x33: is_m ? (f3<4 ? M_MUL(14) : M_DIV(15)) : OP(9) 73 let ism: i64 = nx_sink_cell(k, NX_GATE_KIND_EQ, 1, n_f7, one, 0 - 1, 2) 74 let c4: i64 = nx_sink_const(k, 64, 4) 75 let f3lt4: i64 = nx_sink_cell(k, NX_GATE_KIND_LT, 1, n_f3, c4, 0 - 1, 2) 76 let k14: i64 = nx_sink_const(k, 64, 14) 77 let k15: i64 = nx_sink_const(k, 64, 15) 78 let k9: i64 = nx_sink_const(k, 64, 9) 79 let mk: i64 = nx_sink_cell(k, NX_GATE_KIND_MUX, 64, f3lt4, k14, k15, 3) // f3lt4 ? 14 : 15 80 let kind33: i64 = nx_sink_cell(k, NX_GATE_KIND_MUX, 64, ism, mk, k9, 3) // ism ? mk : 9 81 let oc33: i64 = nx_sink_const(k, 64, 51) 82 let m33: i64 = nx_sink_cell(k, NX_GATE_KIND_EQ, 1, n_op, oc33, 0 - 1, 2) 83 r = nx_sink_cell(k, NX_GATE_KIND_MUX, 64, m33, kind33, r, 3) // m33 ? kind33 : r 84 85 // 0x3b: is_m ? (f3==0 ? M_MUL_32(16) : M_DIV_32(17)) : OP_32(11) 86 let ism2: i64 = nx_sink_cell(k, NX_GATE_KIND_EQ, 1, n_f7, one, 0 - 1, 2) 87 let zc: i64 = nx_sink_const(k, 64, 0) 88 let f3eq0: i64 = nx_sink_cell(k, NX_GATE_KIND_EQ, 1, n_f3, zc, 0 - 1, 2) 89 let k16: i64 = nx_sink_const(k, 64, 16) 90 let k17: i64 = nx_sink_const(k, 64, 17) 91 let k11: i64 = nx_sink_const(k, 64, 11) 92 let mk2: i64 = nx_sink_cell(k, NX_GATE_KIND_MUX, 64, f3eq0, k16, k17, 3) // f3eq0 ? 16 : 17 93 let kind3b: i64 = nx_sink_cell(k, NX_GATE_KIND_MUX, 64, ism2, mk2, k11, 3) // ism2 ? mk2 : 11 94 let oc3b: i64 = nx_sink_const(k, 64, 59) 95 let m3b: i64 = nx_sink_cell(k, NX_GATE_KIND_EQ, 1, n_op, oc3b, 0 - 1, 2) 96 r = nx_sink_cell(k, NX_GATE_KIND_MUX, 64, m3b, kind3b, r, 3) // m3b ? kind3b : r 97 98 return r 99} 100 101// ===== RUNG 3: per-format immediate decoders (I/S/B/U/J) ===== 102// Mirrors nx_rv64im_imm_i/s/b/u/j. Each immediate = gather bit-parts (SHR+AND+SHL), OR them, 103// then sign-extend via MUX on the sign bit (gsim MUX treats sel as != 0, so the masked sign bit 104// IS the selector). MUX(sel, if_true, if_false). 105 106// one bit-part: ((inst >> shr) & mask) << shl (shl==0 -> no shift-left cell) 107func nx_dec_part(k: *NxCellSink, n_inst: i64, shr: i64, mask: i64, shl: i64) -> i64 { 108 let sc: i64 = nx_sink_const(k, 64, shr) 109 let sh: i64 = nx_sink_cell(k, NX_GATE_KIND_SHR, 64, n_inst, sc, 0 - 1, 2) 110 let mc: i64 = nx_sink_const(k, 64, mask) 111 let a: i64 = nx_sink_cell(k, NX_GATE_KIND_AND, 64, sh, mc, 0 - 1, 2) 112 if shl == 0 { return a } 113 let lc: i64 = nx_sink_const(k, 64, shl) 114 return nx_sink_cell(k, NX_GATE_KIND_SHL, 64, a, lc, 0 - 1, 2) 115} 116func nx_dec_or(k: *NxCellSink, x: i64, y: i64) -> i64 { 117 return nx_sink_cell(k, NX_GATE_KIND_OR, 64, x, y, 0 - 1, 2) 118} 119// sign-extend: if (raw & signmask) != 0 -> raw | extmask, else raw. 120func nx_dec_sext(k: *NxCellSink, raw: i64, signmask: i64, extmask: i64) -> i64 { 121 let sc: i64 = nx_sink_const(k, 64, signmask) 122 let sb: i64 = nx_sink_cell(k, NX_GATE_KIND_AND, 64, raw, sc, 0 - 1, 2) 123 let ec: i64 = nx_sink_const(k, 64, extmask) 124 let ext: i64 = nx_sink_cell(k, NX_GATE_KIND_OR, 64, raw, ec, 0 - 1, 2) 125 return nx_sink_cell(k, NX_GATE_KIND_MUX, 64, sb, ext, raw, 3) // sb!=0 ? ext : raw 126} 127 128// fill outs[0..4] = imm net ids for I, S, B, U, J. 129func nx_decoder_imm_build(k: *NxCellSink, n_inst: i64, outs: *i64) -> i64 { 130 // I: inst[31:20], sext bit 11 131 let i_raw: i64 = nx_dec_part(k, n_inst, 20, K_MAGIC_4095, 0) 132 outs[0] = nx_dec_sext(k, i_raw, K_MAGIC_2048, 0 - K_MAGIC_4096) 133 // S: inst[31:25]<<5 | inst[11:7], sext bit 11 134 let s_hi: i64 = nx_dec_part(k, n_inst, 25, 127, 5) 135 let s_lo: i64 = nx_dec_part(k, n_inst, 7, 31, 0) 136 let s_raw: i64 = nx_dec_or(k, s_hi, s_lo) 137 outs[1] = nx_dec_sext(k, s_raw, K_MAGIC_2048, 0 - K_MAGIC_4096) 138 // B: inst[31]<<12 | inst[7]<<11 | inst[30:25]<<5 | inst[11:8]<<1, sext bit 12 139 let b12: i64 = nx_dec_part(k, n_inst, 31, 1, 12) 140 let b11: i64 = nx_dec_part(k, n_inst, 7, 1, 11) 141 let b10_5: i64 = nx_dec_part(k, n_inst, 25, 63, 5) 142 let b4_1: i64 = nx_dec_part(k, n_inst, 8, 15, 1) 143 let b_o1: i64 = nx_dec_or(k, b12, b11) 144 let b_o2: i64 = nx_dec_or(k, b_o1, b10_5) 145 let b_raw: i64 = nx_dec_or(k, b_o2, b4_1) 146 outs[2] = nx_dec_sext(k, b_raw, K_MAGIC_4096, 0 - K_MAGIC_8192) 147 // U: (inst[31:12]) << 12, no sext (matches behavioral) 148 outs[3] = nx_dec_part(k, n_inst, 12, K_MAGIC_1048575, 12) 149 // J: inst[31]<<20 | inst[19:12]<<12 | inst[20]<<11 | inst[30:21]<<1, sext bit 20 150 let j20: i64 = nx_dec_part(k, n_inst, 31, 1, 20) 151 let j19_12: i64 = nx_dec_part(k, n_inst, 12, 255, 12) 152 let j11: i64 = nx_dec_part(k, n_inst, 20, 1, 11) 153 let j10_1: i64 = nx_dec_part(k, n_inst, 21, 1023, 1) 154 let j_o1: i64 = nx_dec_or(k, j20, j19_12) 155 let j_o2: i64 = nx_dec_or(k, j_o1, j11) 156 let j_raw: i64 = nx_dec_or(k, j_o2, j10_1) 157 outs[4] = nx_dec_sext(k, j_raw, K_MAGIC_1048576, 0 - K_MAGIC_2097152) 158 return 0 159}