code wiki / _hdl_build / nx_cpu_rtype_exec_test.nx
nx_cpu_rtype_exec_test.nx source
↩ module page · 143 lines · 6556 B
1// nx_cpu_rtype_exec_test.nx -- TOP-LEVEL COMPOSITION capstone: a full R-type decode->execute
2// datapath, composed from the three proven gate-emit modules in ONE gate-sim graph:
3// inst -> [decoder fields] -> funct3/funct7 -> [R-type control] -> alu_op
4// (rs1_val, rs2_val, alu_op) -> [ALU build_select, divider-backed] -> result
5// Verifies the composed netlist against the behavioral chain
6// decode_kind -> sim_alu_select -> nx_rv64im_alu_compute
7// over funct3 0..7 x funct7 {0,1,0x20} x random nonzero operands. Proves the decoder + control + ALU
8// COMPOSE into a working R-type execute datapath at the GATE level -- the integration milestone
9// toward emitting the whole CPU. Sovereign, no-float. license_tier: ORIGINAL expect_exit: 0
10import "nx_decoder_select.nx"
11import "nx_rtype_control.nx"
12import "nx_alu_select.nx"
13import "rv64im_min_sim.nx" // nx_rv64im_sim_alu_select + NX_RV64IM_OP_OP
14import "rv64im_min_alu.nx" // nx_rv64im_alu_compute
15
16func _emit_cstr(s: *u8) -> i64 {
17 var n: i64 = 0
18 while s[n] != (0 as u8) { n = n + 1 }
19 sys_write(1, s, n)
20 return 0
21}
22func _emit_dec(v: i64) -> i64 {
23 let b: *u8 = sys_mmap(28)
24 let t2: *u8 = sys_mmap(28)
25 var n: i64 = v
26 if n < 0 { sys_write(1, "-" as *u8, 1); n = 0 - n }
27 var t: i64 = 0
28 if n == 0 { t2[0] = 48; t = 1 }
29 while n > 0 { t2[t] = 48 + (n % 10); n = n / 10; t = t + 1 }
30 var i: i64 = 0
31 while i < t { b[i] = t2[t - 1 - i]; i = i + 1 }
32 sys_write(1, b, t)
33 return 0
34}
35
36func main() -> i64 {
37 let cells: *NxGsimCell = sys_mmap(48 * 8000) as *NxGsimCell
38 let vals: *i64 = sys_mmap(8 * 8000) as *i64
39 let g: *NxGsim = sys_mmap(64) as *NxGsim
40 g.cells = cells
41 g.vals = vals
42 let k: *NxCellSink = sys_mmap(64) as *NxCellSink
43
44 g.n_nets = 3 // net 0 = inst, net 1 = rs1_val, net 2 = rs2_val
45 g.n_cells = 0
46 nx_sink_init_mem(k, g)
47 // compose: decoder fields -> control -> ALU
48 let outs: *i64 = sys_mmap(8 * 6) as *i64
49 nx_decoder_fields_build(k, 0, outs) // outs[2]=funct3, outs[5]=funct7
50 let aluop: i64 = nx_rtype_op_aluop_build(k, outs[2], outs[5])
51 let result: i64 = nx_alu_build_select(k, 1, 2, aluop, 1) // a=rs1_val, b=rs2_val, op=alu_op
52
53 let f7s: *i64 = sys_mmap(8 * 4) as *i64
54 f7s[0] = 0; f7s[1] = 1; f7s[2] = 32
55 var seed: i64 = 1234567
56 var mism: i64 = 0
57 var checks: i64 = 0
58 var c_f3: i64 = 0 - 1
59 var c_f7: i64 = 0
60 var c_a: i64 = 0
61 var c_b: i64 = 0
62 var c_got: i64 = 0
63 var c_exp: i64 = 0
64 var fi: i64 = 0
65 while fi < 3 {
66 var f3: i64 = 0
67 while f3 < 8 {
68 var rep: i64 = 0
69 while rep < 5 {
70 seed = (seed * 1103515245 + 12345) & 2147483647
71 let a: i64 = seed
72 seed = (seed * 1103515245 + 12345) & 2147483647
73 let b0: i64 = seed
74 var b: i64 = b0 | 1 // nonzero divisor
75 // RV64: shift ops use rs2[5:0]. The gate ALU NOW masks the shift amount internally
76 // (METAL-03 fix in nx_alu_build_select), so feed the RAW random b -- the gate must
77 // match the behavioral a<<(b&0x3f) for ANY b, including out-of-range amounts.
78 // build the R-type instruction word (rd/rs1/rs2 arbitrary; only funct3/funct7 matter here)
79 let inst: i64 = 51 | (f3 << 12) | (f7s[fi] << 25) | (1 << 7) | (2 << 15) | (3 << 20)
80 g.vals[0] = inst
81 g.vals[1] = a
82 g.vals[2] = b
83 if nx_gsim_run(g) != NX_GSIM_OK { sys_exit(40); return 40 }
84 let got: i64 = g.vals[result]
85 let aop: i64 = nx_rv64im_sim_alu_select(NX_RV64IM_OP_OP, f3, f7s[fi])
86 let exp: i64 = nx_rv64im_alu_compute(aop, a, b)
87 if got != exp {
88 if c_f3 < 0 { c_f3 = f3; c_f7 = f7s[fi]; c_a = a; c_b = b; c_got = got; c_exp = exp }
89 mism = mism + 1
90 }
91 checks = checks + 1
92 rep = rep + 1
93 }
94 f3 = f3 + 1
95 }
96 fi = fi + 1
97 }
98 _emit_cstr("R-type datapath: checks=" as *u8); _emit_dec(checks)
99 _emit_cstr(" mismatches=" as *u8); _emit_dec(mism); _emit_cstr("\n" as *u8)
100 if c_f3 >= 0 {
101 _emit_cstr(" first diverge: f3=" as *u8); _emit_dec(c_f3)
102 _emit_cstr(" f7=" as *u8); _emit_dec(c_f7)
103 _emit_cstr(" a=" as *u8); _emit_dec(c_a)
104 _emit_cstr(" b=" as *u8); _emit_dec(c_b)
105 _emit_cstr(" got=" as *u8); _emit_dec(c_got)
106 _emit_cstr(" exp=" as *u8); _emit_dec(c_exp); _emit_cstr("\n" as *u8)
107 }
108
109 // KAT: add (f3=0,f7=0), a=20 b=4 -> 24
110 let inst_add: i64 = 51 | (1 << 7) | (2 << 15) | (3 << 20)
111 g.vals[0] = inst_add; g.vals[1] = 20; g.vals[2] = 4
112 if nx_gsim_run(g) != NX_GSIM_OK { sys_exit(41); return 41 }
113 let kadd: i64 = g.vals[result]
114 // KAT: mul (f3=0,f7=1), a=20 b=4 -> 80
115 let inst_mul: i64 = 51 | (1 << 25) | (1 << 7) | (2 << 15) | (3 << 20)
116 g.vals[0] = inst_mul; g.vals[1] = 20; g.vals[2] = 4
117 if nx_gsim_run(g) != NX_GSIM_OK { sys_exit(42); return 42 }
118 let kmul: i64 = g.vals[result]
119 _emit_cstr("KAT add(20,4)=" as *u8); _emit_dec(kadd)
120 _emit_cstr(" mul(20,4)=" as *u8); _emit_dec(kmul); _emit_cstr("\n" as *u8)
121
122 // KAT (METAL-03): out-of-range shift amounts MUST mask to rs2[5:0] (would FAIL pre-fix).
123 // SLL a=1 b=65 -> 1 << (65 & 63) = 1 << 1 = 2
124 let inst_sll: i64 = 51 | (1 << 12) | (1 << 7) | (2 << 15) | (3 << 20)
125 g.vals[0] = inst_sll; g.vals[1] = 1; g.vals[2] = 65
126 if nx_gsim_run(g) != NX_GSIM_OK { sys_exit(43); return 43 }
127 let ksll: i64 = g.vals[result]
128 // SRL a=256 b=64 -> 64 & 63 = 0 -> NO shift -> 256
129 let inst_srl: i64 = 51 | (5 << 12) | (1 << 7) | (2 << 15) | (3 << 20)
130 g.vals[0] = inst_srl; g.vals[1] = 256; g.vals[2] = 64
131 if nx_gsim_run(g) != NX_GSIM_OK { sys_exit(44); return 44 }
132 let ksrl: i64 = g.vals[result]
133 _emit_cstr("KAT(METAL-03) sll(1,65)=" as *u8); _emit_dec(ksll); _emit_cstr(" srl(256,64)=" as *u8); _emit_dec(ksrl); _emit_cstr("\n" as *u8)
134
135 if mism != 0 { sys_exit(1); return 1 }
136 if kadd != 24 { sys_exit(2); return 2 }
137 if kmul != 80 { sys_exit(3); return 3 }
138 if ksll != 2 { sys_exit(4); return 4 }
139 if ksrl != 256 { sys_exit(5); return 5 }
140 _emit_cstr("R-TYPE DATAPATH COMPOSE PASS (decode->control->ALU; 120 checks 0 mismatch; add/mul KATs)\n" as *u8)
141 sys_exit(0)
142 return 0
143}