code wiki / _hdl_build / nx_fpga_lut_gate.nx
nx_fpga_lut_gate.nx source
↩ module page · 105 lines · 6419 B
1import "nx_gate_gn.nx"
2import "nx_gate_base.nx"
3// nx_fpga_lut_gate.nx -- GATE for RUNG 4 of the sovereign FPGA-boot sim: the LUT4/DFF fabric primitives + the
4// gate->LUT4 tech-map (nx_fpga_lut). EXHAUSTIVELY proven (a LUT4 has only 16 input combos, so every claim is
5// checked over its WHOLE truth table -- no sampling). Never-brick by construction is asserted mechanically.
6// T1 LUT-IS-BITSTREAM -- a LUT4 configured by init bits outputs exactly that truth table (all 16 combos).
7// T2 TECH-MAP EXACT -- every single-LUT-mappable primitive (AND/OR/NOT/XOR/NAND/NOR/XNOR/MUX) compiles to
8// a LUT4 init whose evaluation == the INDEPENDENT golden gate_ref, over ALL 16 combos.
9// T3 DFF SEQUENTIAL -- Q holds without a tick, latches D on a tick (the fabric's sequential atom).
10// T4 NEVER-BRICK -- every LUT output is in {0,1} (bounded/total) AND deterministic (same in -> same out);
11// a simulator writes NO real hardware state. (#26 by construction.)
12// T5 LIAR-KILL -- the AND-LUT does NOT reproduce XOR (a real mismatch exists) -> the check distinguishes
13// functions, not a rubber stamp; and a wide-arithmetic kind (ADD) reports NOT-single-LUT-mappable.
14// GREEN iff all pass. expect_exit: 0 license_tier: ORIGINAL
15import "nx_fpga_lut.nx"
16import "nx_syscalls.nx"
17
18func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw("
19" as *u8); return ok }
20
21func main() -> i64 {
22 gw("=== nx_fpga_lut_gate: RUNG 4 FPGA fabric primitives (LUT4/DFF) + gate->LUT4 tech-map, exhaustively proven ===\n" as *u8)
23 var pass: i64 = 0; var total: i64 = 0
24
25 // ---- T1: a LUT4 IS its bitstream -- output bit i for input-index i, all 16 combos ----
26 // Use XOR's truth table as a concrete init and confirm lut4_eval returns exactly that bit.
27 let xinit: i64 = fl_gate_to_lut4(FL_XOR)
28 var t1ok: i64 = 1
29 var i: i64 = 0
30 while i < 16 {
31 let a: i64 = i & 1; let b: i64 = (i>>1)&1; let c: i64 = (i>>2)&1; let d: i64 = (i>>3)&1
32 let want: i64 = (xinit >> lut4_index(a,b,c,d)) & 1
33 if lut4_eval(xinit, a, b, c, d) != want { t1ok = 0 }
34 i = i + 1
35 }
36 total=total+1; if t1ok==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
37 gw("T1 LUT4 is its bitstream: configured cell outputs exactly its 16-bit truth table (init=" as *u8); gn(xinit); gw(")\n" as *u8)
38
39 // ---- T2: TECH-MAP EXACT over every single-LUT-mappable primitive, ALL 16 combos each ----
40 let kinds: *i64 = sys_mmap(8 * 16) as *i64
41 kinds[0]=FL_AND; kinds[1]=FL_OR; kinds[2]=FL_NOT; kinds[3]=FL_XOR; kinds[4]=FL_NAND; kinds[5]=FL_NOR; kinds[6]=FL_XNOR; kinds[7]=FL_MUX
42 let nk: i64 = 8
43 var checks: i64 = 0; var mism: i64 = 0
44 var ki: i64 = 0
45 while ki < nk {
46 let kind: i64 = kinds[ki]
47 let init: i64 = fl_gate_to_lut4(kind)
48 var j: i64 = 0
49 while j < 16 {
50 let a: i64 = j & 1; let b: i64 = (j>>1)&1; let c: i64 = (j>>2)&1; let d: i64 = (j>>3)&1
51 checks = checks + 1
52 if lut4_eval(init, a, b, c, d) != fl_gate_ref(kind, a, b, c, d) { mism = mism + 1 }
53 j = j + 1
54 }
55 ki = ki + 1
56 }
57 total=total+1; if mism==0 { if checks==128 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } } else { gw(" [FAIL] " as *u8) }
58 gw("T2 tech-map exact: " as *u8); gn(nk); gw(" primitives x 16 combos = " as *u8); gn(checks); gw(" checks, mismatches=" as *u8); gn(mism); gw(" (each primitive -> ONE LUT4)\n" as *u8)
59
60 // ---- T3: DFF sequential -- holds without a tick, latches D on a tick ----
61 var t3ok: i64 = 1
62 if fl_dff_next(0, 1, 0) != 0 { t3ok = 0 } // no tick: keep Q=0 even though D=1
63 if fl_dff_next(1, 0, 0) != 1 { t3ok = 0 } // no tick: keep Q=1
64 if fl_dff_next(0, 1, 1) != 1 { t3ok = 0 } // tick: latch D=1
65 if fl_dff_next(1, 0, 1) != 0 { t3ok = 0 } // tick: latch D=0
66 total=total+1; if t3ok==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
67 gw("T3 DFF sequential: Q holds without clock, latches D on tick\n" as *u8)
68
69 // ---- T4: NEVER-BRICK -- bounded/total (every output in {0,1}) + deterministic ----
70 var t4ok: i64 = 1
71 var kk: i64 = 0
72 while kk < nk {
73 let init: i64 = fl_gate_to_lut4(kinds[kk])
74 var m: i64 = 0
75 while m < 16 {
76 let a: i64 = m & 1; let b: i64 = (m>>1)&1; let c: i64 = (m>>2)&1; let d: i64 = (m>>3)&1
77 let o1: i64 = lut4_eval(init, a, b, c, d)
78 let o2: i64 = lut4_eval(init, a, b, c, d)
79 if o1 != o2 { t4ok = 0 } // deterministic
80 if o1 < 0 { t4ok = 0 } // bounded
81 if o1 > 1 { t4ok = 0 }
82 m = m + 1
83 }
84 kk = kk + 1
85 }
86 total=total+1; if t4ok==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
87 gw("T4 never-brick (#26): every LUT output in {0,1}, deterministic, zero hardware-state writes (pure in-memory sim)\n" as *u8)
88
89 // ---- T5: LIAR-KILL -- the AND-LUT must NOT reproduce XOR (a real mismatch exists) + ADD is NOT single-LUT-mappable ----
90 let and_init: i64 = fl_gate_to_lut4(FL_AND)
91 var differs: i64 = 0
92 var z: i64 = 0
93 while z < 16 {
94 let a: i64 = z & 1; let b: i64 = (z>>1)&1; let c: i64 = (z>>2)&1; let d: i64 = (z>>3)&1
95 if lut4_eval(and_init, a, b, c, d) != fl_gate_ref(FL_XOR, a, b, c, d) { differs = differs + 1 }
96 z = z + 1
97 }
98 let add_unmappable: i64 = fl_kind_lutmappable(7) // ADD = wide arithmetic -> NOT one LUT4
99 total=total+1; if differs > 0 { if add_unmappable == 0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } } else { gw(" [FAIL] " as *u8) }
100 gw("T5 liar-kill: AND-LUT != XOR in " as *u8); gn(differs); gw("/16 combos (test distinguishes functions); ADD not-single-LUT-mappable=" as *u8); if add_unmappable==0 { gw("YES\n" as *u8) } else { gw("NO\n" as *u8) }
101
102 gw("\n=== nx_fpga_lut_gate " as *u8); gn(pass); gw("/" as *u8); gn(total)
103 if pass == total { gw(" GREEN (FPGA fabric primitives modeled from spec; every gate primitive tech-maps into a bitstream-configured LUT4, exhaustively; never-brick by construction)\n" as *u8); sys_exit(0); return 0 }
104 gw(" RED\n" as *u8); sys_exit(1); return 1
105}