code wiki / _hdl_build / nx_rtype_control.nx
nx_rtype_control.nx source
↩ module page · 56 lines · 3111 B
1// nx_rtype_control.nx -- sink-based R-type (opcode OP) decode->execute CONTROL: maps funct3/funct7
2// to an ALU op code, as gates. This is the glue between the decoder and the ALU -- the missing piece
3// for top-level CPU netlist composition. Mirrors the OP branch of nx_rv64im_sim_alu_select
4// (rv64im_min_sim.nx): funct3 selects the base op (funct7==0x20 picks SUB/SRA for f3 0/5), and
5// funct7==0x01 overlays the M-extension (mul/mulh/.../div/.../rem). MUX(sel, if_true, if_false) per
6// gsim. Flat idiom. Verified standalone by nx_rtype_control_mem_test (exhaustive over funct3 x funct7).
7// license_tier: ORIGINAL expect_exit: 0
8import "nx_cell_sink.nx"
9import "rv64im_min_alu.nx" // NX_RV64IM_ALU_* op codes
10
11func _rc_c(k: *NxCellSink, v: i64) -> i64 { return nx_sink_const(k, 64, v) }
12func _rc_eq(k: *NxCellSink, a: i64, cval: i64) -> i64 {
13 let c: i64 = nx_sink_const(k, 64, cval)
14 return nx_sink_cell(k, NX_GATE_KIND_EQ, 1, a, c, 0 - 1, 2)
15}
16// sel ? t : f
17func _rc_mux(k: *NxCellSink, sel: i64, t: i64, f: i64) -> i64 {
18 return nx_sink_cell(k, NX_GATE_KIND_MUX, 64, sel, t, f, 3)
19}
20
21// returns the ALU-op net for an R-type OP instruction given funct3/funct7 net ids.
22func nx_rtype_op_aluop_build(k: *NxCellSink, n_f3: i64, n_f7: i64) -> i64 {
23 let f7eq20: i64 = _rc_eq(k, n_f7, 32) // 0x20 -> SUB/SRA variant
24 let f7eq1: i64 = _rc_eq(k, n_f7, 1) // 0x01 -> M extension
25 let f3eq1: i64 = _rc_eq(k, n_f3, 1)
26 let f3eq2: i64 = _rc_eq(k, n_f3, 2)
27 let f3eq3: i64 = _rc_eq(k, n_f3, 3)
28 let f3eq4: i64 = _rc_eq(k, n_f3, 4)
29 let f3eq5: i64 = _rc_eq(k, n_f3, 5)
30 let f3eq6: i64 = _rc_eq(k, n_f3, 6)
31 let f3eq7: i64 = _rc_eq(k, n_f3, 7)
32
33 // ----- base (non-M) op -----
34 let add_or_sub: i64 = _rc_mux(k, f7eq20, _rc_c(k, NX_RV64IM_ALU_SUB), _rc_c(k, NX_RV64IM_ALU_ADD))
35 let srl_or_sra: i64 = _rc_mux(k, f7eq20, _rc_c(k, NX_RV64IM_ALU_SRA), _rc_c(k, NX_RV64IM_ALU_SRL))
36 var base: i64 = add_or_sub // f3==0 default
37 base = _rc_mux(k, f3eq1, _rc_c(k, NX_RV64IM_ALU_SLL), base)
38 base = _rc_mux(k, f3eq2, _rc_c(k, NX_RV64IM_ALU_SLT), base)
39 base = _rc_mux(k, f3eq3, _rc_c(k, NX_RV64IM_ALU_SLTU), base)
40 base = _rc_mux(k, f3eq4, _rc_c(k, NX_RV64IM_ALU_XOR), base)
41 base = _rc_mux(k, f3eq5, srl_or_sra, base)
42 base = _rc_mux(k, f3eq6, _rc_c(k, NX_RV64IM_ALU_OR), base)
43 base = _rc_mux(k, f3eq7, _rc_c(k, NX_RV64IM_ALU_AND), base)
44
45 // ----- M-extension op (funct7 == 0x01) -----
46 var mop: i64 = _rc_c(k, NX_RV64IM_ALU_MUL) // f3==0 default
47 mop = _rc_mux(k, f3eq1, _rc_c(k, NX_RV64IM_ALU_MULH), mop)
48 mop = _rc_mux(k, f3eq2, _rc_c(k, NX_RV64IM_ALU_MULHSU), mop)
49 mop = _rc_mux(k, f3eq3, _rc_c(k, NX_RV64IM_ALU_MULHU), mop)
50 mop = _rc_mux(k, f3eq4, _rc_c(k, NX_RV64IM_ALU_DIV), mop)
51 mop = _rc_mux(k, f3eq5, _rc_c(k, NX_RV64IM_ALU_DIVU), mop)
52 mop = _rc_mux(k, f3eq6, _rc_c(k, NX_RV64IM_ALU_REM), mop)
53 mop = _rc_mux(k, f3eq7, _rc_c(k, NX_RV64IM_ALU_REMU), mop)
54
55 return _rc_mux(k, f7eq1, mop, base) // f7==1 ? M-op : base
56}