code wiki / _hdl_build / nx_fpga_fabric_gate.nx
nx_fpga_fabric_gate.nx source
↩ module page · 119 lines · 6805 B
1import "nx_gate_gn.nx"
2import "nx_gate_base.nx"
3// nx_fpga_fabric_gate.nx -- GATE for RUNG 5: a LUT4 fabric EXECUTES A BITSTREAM. Builds real circuits as a
4// fabric of LUT4 cells + routing, generates each bitstream, runs fab_eval driven ONLY by the bitstream, and
5// checks the output against an INDEPENDENT golden model -- EXHAUSTIVELY (3 inputs = 8 combos).
6// T1 FULL-ADDER -- sum=parity3, cout=maj3 as TWO LUT4 cells; fab_eval reproduces a+b+cin over all 8 combos.
7// T2 ROUTED CHAIN -- cell1 wires from cell0's OUTPUT: (a AND b) XOR c; proves inter-cell ROUTING, all 8 combos.
8// T3 NEVER-BRICK -- fab_eval is bounded (ncells steps), total (outputs in {0,1}), deterministic; no hw write.
9// T4 LIAR-KILL -- corrupting ONE bitstream bit makes the full-adder output WRONG -> the fabric truly runs
10// the bitstream (not the source netlist) and the check bites.
11// GREEN iff all pass. expect_exit: 0 license_tier: ORIGINAL
12import "nx_fpga_fabric.nx"
13import "nx_syscalls.nx"
14
15func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw("
16" as *u8); return ok }
17
18// 3-input truth-table inits (the synthesizer step: enumerate the function over a,b,c)
19func parity3_init() -> i64 {
20 var tt: i64 = 0; var i: i64 = 0
21 while i < 16 { let a: i64=i&1; let b: i64=(i>>1)&1; let c: i64=(i>>2)&1; if (a^b^c)==1 { tt = tt | (1<<i) } i=i+1 }
22 return tt
23}
24func maj3_init() -> i64 {
25 var tt: i64 = 0; var i: i64 = 0
26 while i < 16 { let a: i64=i&1; let b: i64=(i>>1)&1; let c: i64=(i>>2)&1; if (a+b+c)>=2 { tt = tt | (1<<i) } i=i+1 }
27 return tt
28}
29
30func main() -> i64 {
31 gw("=== nx_fpga_fabric_gate: RUNG 5 -- a LUT4 fabric EXECUTES A BITSTREAM (real circuits, exhaustively proven) ===\n" as *u8)
32 var pass: i64 = 0; var total: i64 = 0
33
34 // ---------- T1: FULL-ADDER as a 2-cell fabric, run from its bitstream ----------
35 let npi: i64 = 3
36 let fa_inits: *i64 = sys_mmap(8 * 4) as *i64
37 let fa_src: *i64 = sys_mmap(8 * 16) as *i64
38 fa_inits[0] = parity3_init() // cell0 = SUM
39 fa_inits[1] = maj3_init() // cell1 = COUT
40 fa_src[0]=0; fa_src[1]=1; fa_src[2]=2; fa_src[3]=0 // cell0 wires PI0,PI1,PI2 (input3 unused)
41 fa_src[4]=0; fa_src[5]=1; fa_src[6]=2; fa_src[7]=0 // cell1 wires PI0,PI1,PI2
42 let pi: *i64 = sys_mmap(8 * 4) as *i64
43 let co: *i64 = sys_mmap(8 * 8) as *i64
44 var fa_checks: i64 = 0; var fa_bad: i64 = 0
45 var v: i64 = 0
46 while v < 8 {
47 let a: i64=v&1; let b: i64=(v>>1)&1; let cin: i64=(v>>2)&1
48 pi[0]=a; pi[1]=b; pi[2]=cin
49 fab_eval(2, npi, fa_inits, fa_src, pi, co)
50 let sum: i64 = fab_po(npi + 0, npi, pi, co) // PO0 = cell0
51 let cout: i64 = fab_po(npi + 1, npi, pi, co) // PO1 = cell1
52 fa_checks = fa_checks + 2
53 if sum != (a ^ b ^ cin) { fa_bad = fa_bad + 1 }
54 if cout != (((a+b+cin) >= 2) as i64) { fa_bad = fa_bad + 1 }
55 v = v + 1
56 }
57 total=total+1; if fa_bad==0 { if fa_checks==16 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } } else { gw(" [FAIL] " as *u8) }
58 gw("T1 full-adder fabric (2 LUT4 cells) executes its bitstream: " as *u8); gn(fa_checks); gw(" checks (sum+cout x8), wrong=" as *u8); gn(fa_bad); gw("\n" as *u8)
59
60 // ---------- T2: ROUTED CHAIN (a AND b) XOR c -- cell1 wires from cell0's OUTPUT ----------
61 let ch_inits: *i64 = sys_mmap(8 * 4) as *i64
62 let ch_src: *i64 = sys_mmap(8 * 16) as *i64
63 ch_inits[0] = fl_gate_to_lut4(FL_AND) // cell0 = a AND b
64 ch_inits[1] = fl_gate_to_lut4(FL_XOR) // cell1 = in0 XOR in1
65 ch_src[0]=0; ch_src[1]=1; ch_src[2]=0; ch_src[3]=0 // cell0 wires PI0(a),PI1(b)
66 ch_src[4]=npi+0; ch_src[5]=2; ch_src[6]=0; ch_src[7]=0 // cell1 wires CELL0_out, PI2(c) <-- ROUTING
67 var ch_bad: i64 = 0; var ch_checks: i64 = 0
68 v = 0
69 while v < 8 {
70 let a: i64=v&1; let b: i64=(v>>1)&1; let c: i64=(v>>2)&1
71 pi[0]=a; pi[1]=b; pi[2]=c
72 fab_eval(2, npi, ch_inits, ch_src, pi, co)
73 let out: i64 = fab_po(npi + 1, npi, pi, co) // PO = cell1
74 ch_checks = ch_checks + 1
75 if out != ((a & b) ^ c) { ch_bad = ch_bad + 1 }
76 v = v + 1
77 }
78 total=total+1; if ch_bad==0 { if ch_checks==8 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } } else { gw(" [FAIL] " as *u8) }
79 gw("T2 routed chain (a AND b) XOR c, cell1<-cell0 wire: " as *u8); gn(ch_checks); gw(" checks, wrong=" as *u8); gn(ch_bad); gw(" (inter-cell ROUTING works)\n" as *u8)
80
81 // ---------- T3: NEVER-BRICK -- bounded, total (outputs {0,1}), deterministic ----------
82 var t3ok: i64 = 1
83 v = 0
84 while v < 8 {
85 let a: i64=v&1; let b: i64=(v>>1)&1; let cin: i64=(v>>2)&1
86 pi[0]=a; pi[1]=b; pi[2]=cin
87 fab_eval(2, npi, fa_inits, fa_src, pi, co)
88 let s1: i64 = fab_po(npi+0, npi, pi, co)
89 let co2: *i64 = sys_mmap(8 * 8) as *i64
90 fab_eval(2, npi, fa_inits, fa_src, pi, co2)
91 let s2: i64 = fab_po(npi+0, npi, pi, co2)
92 if s1 != s2 { t3ok = 0 } // deterministic
93 if s1 < 0 { t3ok = 0 }; if s1 > 1 { t3ok = 0 } // total/bounded
94 v = v + 1
95 }
96 total=total+1; if t3ok==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
97 gw("T3 never-brick (#26): fab_eval bounded (ncells steps), outputs in {0,1}, deterministic, zero hw-state writes\n" as *u8)
98
99 // ---------- T4: LIAR-KILL -- flip ONE bitstream bit -> full-adder SUM goes wrong somewhere ----------
100 let bad_inits: *i64 = sys_mmap(8 * 4) as *i64
101 bad_inits[0] = fa_inits[0] ^ 1 // corrupt cell0 (sum) LUT bit 0
102 bad_inits[1] = fa_inits[1]
103 var liar_wrong: i64 = 0
104 v = 0
105 while v < 8 {
106 let a: i64=v&1; let b: i64=(v>>1)&1; let cin: i64=(v>>2)&1
107 pi[0]=a; pi[1]=b; pi[2]=cin
108 fab_eval(2, npi, bad_inits, fa_src, pi, co)
109 let sum: i64 = fab_po(npi+0, npi, pi, co)
110 if sum != (a ^ b ^ cin) { liar_wrong = liar_wrong + 1 }
111 v = v + 1
112 }
113 total=total+1; if liar_wrong > 0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
114 gw("T4 liar-kill: a 1-bit bitstream corruption makes SUM wrong in " as *u8); gn(liar_wrong); gw("/8 combos (the fabric runs the BITSTREAM, and the check bites)\n" as *u8)
115
116 gw("\n=== nx_fpga_fabric_gate " as *u8); gn(pass); gw("/" as *u8); gn(total)
117 if pass == total { gw(" GREEN (a bitstream-configured LUT4 fabric executes real circuits in sim: full-adder + routed chain, exhaustive; never-brick by construction)\n" as *u8); sys_exit(0); return 0 }
118 gw(" RED\n" as *u8); sys_exit(1); return 1
119}