code wiki / _hdl_build / nx_fpga_rtype_gate.nx
nx_fpga_rtype_gate.nx source
↩ module page · 159 lines · 8864 B
1import "nx_gate_gn.nx"
2import "nx_gate_base.nx"
3// nx_fpga_rtype_gate.nx -- GATE for RUNG 9: an RV64I R-type instruction DECODED + EXECUTED on the fabric ==
4// the behavioral CPU. Composes the DECODER fabric (nx_fpga_decode: funct3/funct7b5 -> control + result-class)
5// with the ALU/shift/compare datapath fabrics: decode-on-fabric drives execute-on-fabric, and the composed
6// result is checked against the behavioral path (decode -> nx_rv64im_alu_compute). Both stages are real fabric
7// computations -- the CPU's integer execute stage running on the simulated FPGA.
8// T1 INSTRUCTION EXECUTE == behavioral, all 10 R-type ops (ADD/SUB/SLL/SLT/SLTU/XOR/SRL/SRA/OR/AND) x KAT+LFSR.
9// T2 DECODER correct -- the decoder fabric's control outputs == the golden decode table, all funct3 x funct7b5.
10// T3 NEVER-BRICK. T4 LIAR-KILL -- corrupt the decoder's class LUT -> wrong dispatch -> wrong instruction result.
11// GREEN iff all pass. expect_exit: 0 license_tier: ORIGINAL
12import "nx_fpga_decode.nx"
13import "nx_fpga_alu.nx"
14import "nx_fpga_cmp.nx"
15import "nx_fpga_shift.nx"
16import "rv64im_min_alu.nx"
17import "nx_syscalls.nx"
18
19func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw("
20" as *u8); return ok }
21
22func ref_aluop(f3: i64, f7b5: i64) -> i64 {
23 if f3==0 { if f7b5==1 { return NX_RV64IM_ALU_SUB } return NX_RV64IM_ALU_ADD }
24 if f3==1 { return NX_RV64IM_ALU_SLL }
25 if f3==2 { return NX_RV64IM_ALU_SLT }
26 if f3==3 { return NX_RV64IM_ALU_SLTU }
27 if f3==4 { return NX_RV64IM_ALU_XOR }
28 if f3==5 { if f7b5==1 { return NX_RV64IM_ALU_SRA } return NX_RV64IM_ALU_SRL }
29 if f3==6 { return NX_RV64IM_ALU_OR }
30 return NX_RV64IM_ALU_AND
31}
32
33// ctx layout: 0=DI 1=DS 2=DP | 3=AI 4=AS 5=AP 6=alu_npi | 7=CI 8=CS 9=CP 10=cmp_npi | 11=SI 12=SS 13=SP 14=sh_npi | 15=PI 16=CO 17=CTRL
34// decode (on fabric) -> dispatch to the datapath (on fabric) -> the instruction result.
35func r9_exec(ctx: *i64, f3: i64, f7b5: i64, rs1: i64, rs2: i64) -> i64 {
36 let DI: *i64 = ctx[0] as *i64; let DS: *i64 = ctx[1] as *i64; let DP: *i64 = ctx[2] as *i64
37 let PIv: *i64 = ctx[15] as *i64; let COv: *i64 = ctx[16] as *i64; let CTRL: *i64 = ctx[17] as *i64
38 fab_decode_run(DI, DS, DP, PIv, COv, f3, f7b5, CTRL)
39 let cls: i64 = CTRL[6] | (CTRL[7] << 1)
40 if cls == 0 { return fab_alu_run(64, ctx[6], ctx[3] as *i64, ctx[4] as *i64, ctx[5] as *i64, PIv, COv, rs1, rs2, CTRL[0], CTRL[1], CTRL[2]) }
41 if cls == 1 { return fab_shift_run(64, ctx[14], ctx[11] as *i64, ctx[12] as *i64, ctx[13] as *i64, PIv, COv, rs1, rs2 & 63, CTRL[3], CTRL[4]) }
42 return fab_cmp_run(64, ctx[10], ctx[7] as *i64, ctx[8] as *i64, ctx[9] as *i64, PIv, COv, rs1, rs2, CTRL[5])
43}
44
45func main() -> i64 {
46 gw("=== nx_fpga_rtype_gate: RUNG 9 -- R-type instruction DECODE+EXECUTE on the fabric == behavioral CPU ===\n" as *u8)
47 var pass: i64 = 0; var total: i64 = 0
48
49 let ctx: *i64 = sys_mmap(8 * 32) as *i64
50 ctx[0] = sys_mmap(8 * 16) as i64; ctx[1] = sys_mmap(8 * 48) as i64; ctx[2] = sys_mmap(8 * 16) as i64
51 ctx[3] = sys_mmap(8 * 640) as i64; ctx[4] = sys_mmap(8 * 2560) as i64; ctx[5] = sys_mmap(8 * 72) as i64
52 ctx[7] = sys_mmap(8 * 256) as i64; ctx[8] = sys_mmap(8 * 1024) as i64; ctx[9] = sys_mmap(8 * 72) as i64
53 ctx[11] = sys_mmap(8 * 800) as i64; ctx[12] = sys_mmap(8 * 3200) as i64; ctx[13] = sys_mmap(8 * 72) as i64
54 ctx[15] = sys_mmap(8 * 140) as i64; ctx[16] = sys_mmap(8 * 800) as i64; ctx[17] = sys_mmap(8 * 16) as i64
55
56 fab_build_decode(ctx[0] as *i64, ctx[1] as *i64, ctx[2] as *i64)
57 ctx[6] = fab_build_alu(64, ctx[3] as *i64, ctx[4] as *i64, ctx[5] as *i64)
58 ctx[10] = fab_build_cmp(64, ctx[7] as *i64, ctx[8] as *i64, ctx[9] as *i64)
59 ctx[14] = fab_build_shifter(64, ctx[11] as *i64, ctx[12] as *i64, ctx[13] as *i64)
60
61 // the 10 R-type ops (f3, f7b5)
62 let f3a: *i64 = sys_mmap(8 * 16) as *i64; let f7a: *i64 = sys_mmap(8 * 16) as *i64
63 f3a[0]=0; f7a[0]=0; f3a[1]=0; f7a[1]=1; f3a[2]=1; f7a[2]=0; f3a[3]=2; f7a[3]=0; f3a[4]=3; f7a[4]=0
64 f3a[5]=4; f7a[5]=0; f3a[6]=5; f7a[6]=0; f3a[7]=5; f7a[7]=1; f3a[8]=6; f7a[8]=0; f3a[9]=7; f7a[9]=0
65 let nops: i64 = 10
66
67 // operand KATs
68 let ka: *i64 = sys_mmap(8 * 16) as *i64; let kb: *i64 = sys_mmap(8 * 16) as *i64
69 ka[0]=0; kb[0]=0
70 ka[1]=1; kb[1]=1
71 ka[2]=0-1; kb[2]=5
72 ka[3]=6148914691236517205; kb[3]=0-6148914691236517206
73 ka[4]=(1<<63); kb[4]=3
74 ka[5]=123456789; kb[5]=37
75 ka[6]=0-1; kb[6]=0-1
76 ka[7]=0; kb[7]=0-1
77 let nka: i64 = 8
78
79 // ---- T1: instruction execute == behavioral, all 10 ops ----
80 var checks: i64 = 0; var mism: i64 = 0
81 var oi: i64 = 0
82 while oi < nops {
83 let f3: i64 = f3a[oi]; let f7: i64 = f7a[oi]
84 let aluop: i64 = ref_aluop(f3, f7)
85 var ki: i64 = 0
86 while ki < nka {
87 checks = checks + 1
88 if r9_exec(ctx, f3, f7, ka[ki], kb[ki]) != nx_rv64im_alu_compute(aluop, ka[ki], kb[ki]) { mism = mism + 1 }
89 ki = ki + 1
90 }
91 var lcg: i64 = 1442695040888963407
92 var t: i64 = 0
93 while t < 120 {
94 lcg = (lcg * 2862933555777941757 + 3037000493) & 4611686018427387903
95 let d1: i64 = (lcg >> 5) & 4294967295
96 lcg = (lcg * 2862933555777941757 + 3037000493) & 4611686018427387903
97 let d2: i64 = (lcg >> 5) & 4294967295
98 let a: i64 = (d1 << 32) | d2
99 lcg = (lcg * 2862933555777941757 + 3037000493) & 4611686018427387903
100 let d3: i64 = (lcg >> 5) & 4294967295
101 lcg = (lcg * 2862933555777941757 + 3037000493) & 4611686018427387903
102 let d4: i64 = (lcg >> 5) & 4294967295
103 let b: i64 = (d3 << 32) | d4
104 checks = checks + 1
105 if r9_exec(ctx, f3, f7, a, b) != nx_rv64im_alu_compute(aluop, a, b) { mism = mism + 1 }
106 t = t + 1
107 }
108 oi = oi + 1
109 }
110 total=total+1; if mism==0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
111 gw("T1 R-type DECODE+EXECUTE on fabric == behavioral: " as *u8); gn(checks); gw(" checks (10 ops x KAT+LFSR), mismatches=" as *u8); gn(mism); gw("\n" as *u8)
112
113 // ---- T2: decoder fabric correct vs the golden decode table ----
114 let DIc: *i64 = ctx[0] as *i64; let DSc: *i64 = ctx[1] as *i64; let DPc: *i64 = ctx[2] as *i64
115 let PIc: *i64 = ctx[15] as *i64; let COc: *i64 = ctx[16] as *i64; let CTc: *i64 = ctx[17] as *i64
116 var dchecks: i64 = 0; var dbad: i64 = 0
117 var f3: i64 = 0
118 while f3 < 8 {
119 var f7: i64 = 0
120 while f7 < 2 {
121 fab_decode_run(DIc, DSc, DPc, PIc, COc, f3, f7, CTc)
122 dchecks = dchecks + 1
123 if CTc[0] != r9_sub(f3,f7) { dbad = dbad + 1 }
124 if CTc[1] != r9_msel0(f3) { dbad = dbad + 1 }
125 if CTc[2] != r9_msel1(f3) { dbad = dbad + 1 }
126 if CTc[3] != r9_right(f3) { dbad = dbad + 1 }
127 if CTc[4] != r9_arith(f3,f7) { dbad = dbad + 1 }
128 if CTc[5] != r9_uns(f3) { dbad = dbad + 1 }
129 if (CTc[6] | (CTc[7]<<1)) != r9_class(f3) { dbad = dbad + 1 }
130 f7 = f7 + 1
131 }
132 f3 = f3 + 1
133 }
134 total=total+1; if dbad==0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
135 gw("T2 decoder fabric == golden decode table: " as *u8); gn(dchecks); gw(" funct3xfunct7b5 combos, control-bit mismatches=" as *u8); gn(dbad); gw("\n" as *u8)
136
137 // ---- T3: never-brick (bounded + deterministic) ----
138 let r1: i64 = r9_exec(ctx, 0, 1, 999983, 314159)
139 let r2: i64 = r9_exec(ctx, 0, 1, 999983, 314159)
140 total=total+1; if r1==r2 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
141 gw("T3 never-brick (#26): the decode+execute pipeline is bounded + deterministic, zero hardware-state writes\n" as *u8)
142
143 // ---- T4: liar-kill -- corrupt the decoder's class0 LUT -> wrong dispatch -> wrong results ----
144 let DIk: *i64 = ctx[0] as *i64
145 DIk[6] = DIk[6] ^ 0xffff
146 var liar_wrong: i64 = 0
147 var lt: i64 = 0
148 while lt < nops {
149 let f3b: i64 = f3a[lt]; let f7b: i64 = f7a[lt]
150 if r9_exec(ctx, f3b, f7b, 1234567, 89) != nx_rv64im_alu_compute(ref_aluop(f3b,f7b), 1234567, 89) { liar_wrong = liar_wrong + 1 }
151 lt = lt + 1
152 }
153 total=total+1; if liar_wrong > 0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
154 gw("T4 liar-kill: corrupting the decoder class LUT mis-dispatches " as *u8); gn(liar_wrong); gw("/10 ops\n" as *u8)
155
156 gw("\n=== nx_fpga_rtype_gate " as *u8); gn(pass); gw("/" as *u8); gn(total)
157 if pass == total { gw(" GREEN (an RV64I R-type instruction decodes + executes on the simulated FPGA fabric == the behavioral CPU; all 10 ops)\n" as *u8); sys_exit(0); return 0 }
158 gw(" RED\n" as *u8); sys_exit(1); return 1
159}