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}