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}