code wiki / _hdl_build / nx_decode_kind.nx
nx_decode_kind.nx source
↩ module page · 60 lines · 3300 B
1// nx_decode_kind.nx -- the RV64IM instruction-class DECODER as a GATE-NETWORK
2// (the next module after the ALU, toward a bootable gate-level CPU). Mirrors the
3// behavioral nx_rv64im_decode_kind op-for-op: extract opcode/funct3/funct7, then
4// a CONST + EQ-match + cascade-MUX over the opcode (same shape as the ALU op-
5// select), with the M-extension sub-decode for the R-type opcodes 0x33/0x3b.
6//
7// Output = NX_RV64IM_OP_* (the op class the executor routes to the ALU/loads/
8// branches). Verified EXHAUSTIVELY: decode_kind depends only on the 17 bits
9// {opcode[6:0], funct3[14:12], funct7[31:25]}, so all 2^17 combos are checkable.
10// license_tier: ORIGINAL
11
12import "nx_alu_divider.nx" // div_const / div_op2 / div_mux + NxGsim + NX_GATE_KIND_*
13import "rv64im_min_decoder.nx" // the NX_RV64IM_OP_* class enum
14
15// emit "result = match ? klass : prev" and return the new net.
16func dk_sel(g: *NxGsim, opcode: i64, opval: i64, klass: i64, prev: i64) -> i64 {
17 let m: i64 = div_op2(g, NX_GATE_KIND_EQ, opcode, div_const(g, opval))
18 return div_mux(g, m, klass, prev)
19}
20
21func nx_decode_kind_synth(g: *NxGsim, ninst: i64) -> i64 {
22 let c7f: i64 = div_const(g, 127) // 0x7f
23 let c7: i64 = div_const(g, 7)
24 let c12: i64 = div_const(g, 12)
25 let c25: i64 = div_const(g, 25)
26 let c1: i64 = div_const(g, 1)
27 let c4: i64 = div_const(g, 4)
28 let c0: i64 = div_const(g, 0)
29
30 let opcode: i64 = div_op2(g, NX_GATE_KIND_AND, ninst, c7f)
31 let funct3: i64 = div_op2(g, NX_GATE_KIND_AND, div_op2(g, NX_GATE_KIND_SHR, ninst, c12), c7)
32 let funct7: i64 = div_op2(g, NX_GATE_KIND_AND, div_op2(g, NX_GATE_KIND_SHR, ninst, c25), c7f)
33
34 let is_m: i64 = div_op2(g, NX_GATE_KIND_EQ, funct7, c1)
35 let f3lt4: i64 = div_op2(g, NX_GATE_KIND_LTU, funct3, c4)
36 let f3eq0: i64 = div_op2(g, NX_GATE_KIND_EQ, funct3, c0)
37
38 // R-type 64-bit (0x33): f7==1 ? (f3<4 ? M_MUL : M_DIV) : OP
39 let mclass: i64 = div_mux(g, f3lt4, div_const(g, NX_RV64IM_OP_M_MUL), div_const(g, NX_RV64IM_OP_M_DIV))
40 let class33: i64 = div_mux(g, is_m, mclass, div_const(g, NX_RV64IM_OP_OP))
41 // R-type 32-bit (0x3b): f7==1 ? (f3==0 ? M_MUL_32 : M_DIV_32) : OP_32
42 let mclass32: i64 = div_mux(g, f3eq0, div_const(g, NX_RV64IM_OP_M_MUL_32), div_const(g, NX_RV64IM_OP_M_DIV_32))
43 let class3b: i64 = div_mux(g, is_m, mclass32, div_const(g, NX_RV64IM_OP_OP_32))
44
45 var r: i64 = div_const(g, NX_RV64IM_OP_INVALID)
46 r = dk_sel(g, opcode, 0x37, div_const(g, NX_RV64IM_OP_LUI), r)
47 r = dk_sel(g, opcode, 0x17, div_const(g, NX_RV64IM_OP_AUIPC), r)
48 r = dk_sel(g, opcode, 0x6f, div_const(g, NX_RV64IM_OP_JAL), r)
49 r = dk_sel(g, opcode, 0x67, div_const(g, NX_RV64IM_OP_JALR), r)
50 r = dk_sel(g, opcode, 0x63, div_const(g, NX_RV64IM_OP_BRANCH), r)
51 r = dk_sel(g, opcode, 0x03, div_const(g, NX_RV64IM_OP_LOAD), r)
52 r = dk_sel(g, opcode, 0x23, div_const(g, NX_RV64IM_OP_STORE), r)
53 r = dk_sel(g, opcode, 0x13, div_const(g, NX_RV64IM_OP_OP_IMM), r)
54 r = dk_sel(g, opcode, 0x1b, div_const(g, NX_RV64IM_OP_OP_IMM_32), r)
55 r = dk_sel(g, opcode, 0x0f, div_const(g, NX_RV64IM_OP_FENCE), r)
56 r = dk_sel(g, opcode, 0x73, div_const(g, NX_RV64IM_OP_SYSTEM), r)
57 r = dk_sel(g, opcode, 0x33, class33, r)
58 r = dk_sel(g, opcode, 0x3b, class3b, r)
59 return r
60}