code wiki / _hdl_build / nx_fpga_rexec_gate.nx
nx_fpga_rexec_gate.nx source
↩ module page · 125 lines · 7512 B
1import "nx_gate_gn.nx"
2import "nx_gate_base.nx"
3// nx_fpga_rexec_gate.nx -- GATE for RUNG 32b: the R-type ALU-class EXECUTE datapath as ONE composed fabric
4// (decode + ALU folded via fab_append). Proves a REAL CPU control-unit + datapath, composed into a single
5// netlist, executes == the behavioral CPU:
6// T1 the composed (decode->ALU) fabric computes the DECODED op == nx_rv64im_alu_compute over the 5 ALU-class
7// R-type ops (ADD/SUB/XOR/OR/AND) x KAT+LFSR @ 64-bit, 0 mismatch -- the decoder's control drives the ALU.
8// T2 compose->Verilog->reparse: the composed fabric serializes through fab_emit_verilog_seq + fab_parse_seq
9// and the RE-PARSED netlist computes the SAME results == oracle (the whole-datapath .v round-trips).
10// T3 NEVER-BRICK (#26): bounded & exact cell count (8 + 9W), pure memory.
11// T4 LIAR-KILL: corrupt the DECODER's msel0 LUT -> wrong op selected -> results diverge from the oracle.
12// Sovereign, no-float, integer-only. expect_exit: 0 license_tier: ORIGINAL
13import "nx_fpga_rexec.nx"
14import "nx_fpga_verilog.nx"
15import "nx_fpga_fabric.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
22// reference ALU op for the 5 ALU-class R-type ops (f3 in {0,4,6,7})
23func ref_aop(f3: i64, f7b5: i64) -> i64 {
24 if f3==0 { if f7b5==1 { return NX_RV64IM_ALU_SUB } return NX_RV64IM_ALU_ADD }
25 if f3==4 { return NX_RV64IM_ALU_XOR }
26 if f3==6 { return NX_RV64IM_ALU_OR }
27 return NX_RV64IM_ALU_AND
28}
29
30func main() -> i64 {
31 gw("=== nx_fpga_rexec_gate: RUNG 32b -- R-type ALU-class EXECUTE as ONE composed fabric (decode+ALU) ===\n" as *u8)
32 let W: i64=64
33 var pass: i64=0; var total: i64=0
34 let cinit: *i64=sys_mmap(8*700) as *i64; let csrc: *i64=sys_mmap(8*2800) as *i64; let ckind: *i64=sys_mmap(8*700) as *i64
35 let cpo: *i64=sys_mmap(8*72) as *i64; let onpi: *i64=sys_mmap(16) as *i64
36 let NCELLS: i64=fab_build_rexec_alu(W, cinit, csrc, ckind, cpo, onpi)
37 let NPI: i64=onpi[0]
38 let pi: *i64=sys_mmap(8*200) as *i64; let co: *i64=sys_mmap(8*800) as *i64
39
40 // the 5 ALU-class ops (f3, f7b5)
41 let f3s: *i64=sys_mmap(8*8) as *i64; let f7s: *i64=sys_mmap(8*8) as *i64
42 f3s[0]=0; f7s[0]=0; f3s[1]=0; f7s[1]=1; f3s[2]=4; f7s[2]=0; f3s[3]=6; f7s[3]=0; f3s[4]=7; f7s[4]=0
43 let nops: i64=5
44 // operand KATs
45 let ka: *i64=sys_mmap(8*8) as *i64; let kb: *i64=sys_mmap(8*8) as *i64
46 ka[0]=0; kb[0]=0; ka[1]=1; kb[1]=1; ka[2]=0-1; kb[2]=5; ka[3]=0; kb[3]=0-1; ka[4]=(1<<63); kb[4]=3; ka[5]=123456789; kb[5]=37
47 let nka: i64=6
48
49 // ---- T1: composed decode+ALU == behavioral over the 5 ALU-class ops ----
50 var checks: i64=0; var mism: i64=0; var c_op: i64=0-1; var c_a: i64=0; var c_b: i64=0; var c_got: i64=0; var c_exp: i64=0
51 var oi: i64=0
52 while oi<nops {
53 let f3: i64=f3s[oi]; let f7: i64=f7s[oi]; let aop: i64=ref_aop(f3,f7)
54 var ki: i64=0
55 while ki<nka {
56 let got: i64=fab_rexec_run(W, NCELLS, NPI, cinit, csrc, cpo, pi, co, f3, f7, ka[ki], kb[ki])
57 let exp: i64=nx_rv64im_alu_compute(aop, ka[ki], kb[ki])
58 if got!=exp { if c_op<0 { c_op=f3; c_a=ka[ki]; c_b=kb[ki]; c_got=got; c_exp=exp } mism=mism+1 }
59 checks=checks+1; ki=ki+1
60 }
61 var lcg: i64=1442695040888963407; var t: i64=0
62 while t<50 {
63 lcg=(lcg*2862933555777941757+3037000493)&4611686018427387903; let d1: i64=(lcg>>5)&4294967295
64 lcg=(lcg*2862933555777941757+3037000493)&4611686018427387903; let d2: i64=(lcg>>5)&4294967295
65 let a: i64=(d1<<32)|d2
66 lcg=(lcg*2862933555777941757+3037000493)&4611686018427387903; let d3: i64=(lcg>>5)&4294967295
67 lcg=(lcg*2862933555777941757+3037000493)&4611686018427387903; let d4: i64=(lcg>>5)&4294967295
68 let b: i64=(d3<<32)|d4
69 let got: i64=fab_rexec_run(W, NCELLS, NPI, cinit, csrc, cpo, pi, co, f3, f7, a, b)
70 let exp: i64=nx_rv64im_alu_compute(aop, a, b)
71 if got!=exp { if c_op<0 { c_op=f3; c_a=a; c_b=b; c_got=got; c_exp=exp } mism=mism+1 }
72 checks=checks+1; t=t+1
73 }
74 oi=oi+1
75 }
76 total=total+1; if mism==0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
77 gw("T1 composed decode+ALU == behavioral: checks=" as *u8); gn(checks); gw(" (5 ALU-class ops x KAT+LFSR) mismatches=" as *u8); gn(mism); gw(" (NCELLS=" as *u8); gn(NCELLS); gw(" NPI=" as *u8); gn(NPI); gw(")\n" as *u8)
78 if c_op>=0 { gw(" first diverge: f3=" as *u8); gn(c_op); gw(" a=" as *u8); gn(c_a); gw(" b=" as *u8); gn(c_b); gw(" got=" as *u8); gn(c_got); gw(" exp=" as *u8); gn(c_exp); gw("\n" as *u8) }
79
80 // ---- T2: compose -> Verilog -> reparse -> re-evaluate == oracle ----
81 let buf: *u8=sys_mmap(131072)
82 let len: i64=fab_emit_verilog_seq(buf, NCELLS, NPI, W, ckind, cinit, csrc, cpo)
83 buf[len]=0 as u8
84 let rk: *i64=sys_mmap(8*700) as *i64; let ri: *i64=sys_mmap(8*700) as *i64; let rs: *i64=sys_mmap(8*2800) as *i64; let rp: *i64=sys_mmap(8*72) as *i64
85 let pn: *i64=sys_mmap(16) as *i64; let pno: *i64=sys_mmap(16) as *i64
86 let rnc: i64=fab_parse_seq(buf, len, rk, ri, rs, rp, pn, pno)
87 var rmis: i64=0
88 var ri2: i64=0
89 while ri2<nops {
90 let f3: i64=f3s[ri2]; let f7: i64=f7s[ri2]; let aop: i64=ref_aop(f3,f7)
91 var kj: i64=0
92 while kj<nka {
93 let got: i64=fab_rexec_run(W, rnc, pn[0], ri, rs, rp, pi, co, f3, f7, ka[kj], kb[kj])
94 if got != nx_rv64im_alu_compute(aop, ka[kj], kb[kj]) { rmis=rmis+1 }
95 kj=kj+1
96 }
97 ri2=ri2+1
98 }
99 var structok: i64=0
100 if rnc==NCELLS { if pn[0]==NPI { if pno[0]==W { structok=1 } } }
101 total=total+1
102 if rmis==0 { if structok==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } } else { gw(" [FAIL] " as *u8) }
103 gw("T2 compose->Verilog->reparse netlist == oracle: ncells=" as *u8); gn(rnc); gw(" npi=" as *u8); gn(pn[0]); gw(" vlen=" as *u8); gn(len); gw(" mismatches=" as *u8); gn(rmis); gw("\n" as *u8)
104
105 // ---- T3: never-brick -- bounded & exact cell count ----
106 total=total+1; if NCELLS==8+9*W { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
107 gw("T3 NEVER-BRICK (#26): bounded & exact NCELLS=" as *u8); gn(NCELLS); gw(" == 8+9W=" as *u8); gn(8+9*W); gw(" (pure memory, zero hardware-state writes)\n" as *u8)
108
109 // ---- T4: liar-kill -- corrupt the DECODER msel0 LUT -> wrong op selected -> divergence ----
110 let saved: i64=cinit[1]; cinit[1]=cinit[1]^65535 // cell 1 = decoder msel0 LUT
111 var liar_wrong: i64=0
112 var lt: i64=0
113 while lt<nops {
114 let f3: i64=f3s[lt]; let f7: i64=f7s[lt]
115 if fab_rexec_run(W, NCELLS, NPI, cinit, csrc, cpo, pi, co, f3, f7, 1234567, 89) != nx_rv64im_alu_compute(ref_aop(f3,f7), 1234567, 89) { liar_wrong=liar_wrong+1 }
116 lt=lt+1
117 }
118 cinit[1]=saved
119 total=total+1; if liar_wrong>0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
120 gw("T4 LIAR-KILL: corrupting the decoder msel0 LUT mis-selects " as *u8); gn(liar_wrong); gw("/5 ops\n" as *u8)
121
122 gw("REXEC-GATE verdict=" as *u8)
123 if pass==total { gw("GREEN passes=" as *u8); gn(pass); gw("/" as *u8); gn(total); gw(" END\n" as *u8); sys_exit(0); return 0 }
124 gw("RED passes=" as *u8); gn(pass); gw("/" as *u8); gn(total); gw(" END\n" as *u8); sys_exit(1); return 1
125}