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}