code wiki / _hdl_build / nx_nbit_gate.nx
nx_nbit_gate.nx source
↩ module page · 88 lines · 5828 B
1import "nx_gate_gn.nx"
2import "nx_gate_base.nx"
3// nx_nbit_gate.nx -- GATE for NHDL H5: sovereign PLACE-and-ROUTE + BITSTREAM + VIRTUAL FPGA (nextpnr/prjtrellis
4// competitor). Runs the WHOLE sovereign flow end-to-end: author RTL -> synthesize -> place on a grid -> route ->
5// bitstream -> load into the virtual FPGA -> prove it computes the design.
6// T1 the VIRTUAL FPGA (loaded from the placed+routed bitstream) computes ((a&b)+(a^b))&0xFF == oracle over 100
7// random (a,b) -- P&R is correctness-preserving even though placement is a non-trivial (column-major) permutation.
8// T2 PLACEMENT valid: all 32 cells land on DISTINCT tiles (0 conflicts) = 100% placement on a 6x6 grid (89% util).
9// T3 NEVER-BRICK (#26): bounded; the bitstream is pure config data, zero hardware-state writes.
10// T4 LIAR-KILL: corrupt one tile's LUT config -> the virtual FPGA computes WRONG (the bitstream drives the gates).
11// Sovereign, no-float. expect_exit: 0 license_tier: ORIGINAL
12import "nx_nbit.nx"
13import "nx_nrtl.nx"
14import "nx_nhdl.nx"
15import "nx_syscalls.nx"
16
17func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw("
18" as *u8); return ok }
19
20func vfpga_run(cn: i64, NPI: i64, W: i64, tile_of: *i64, cinit: *i64, csrc: *i64, cpo: *i64, pi: *i64, tileval: *i64, out: *i64, a: i64, b: i64) -> i64 {
21 var i: i64=0; while i<W { pi[i]=(a>>i)&1; pi[W+i]=(b>>i)&1; i=i+1 }
22 pi[2*W]=0
23 nbit_eval(cn, NPI, W, tile_of, cinit, csrc, cpo, pi, tileval, out)
24 var s: i64=0; i=0; while i<W { s=s|((out[i]&1)<<i); i=i+1 }
25 return s
26}
27
28func main() -> i64 {
29 gw("=== nx_nbit_gate: NHDL H5 -- sovereign place-&-route + bitstream + VIRTUAL FPGA (full RTL->board flow) ===\n" as *u8)
30 let W: i64=8; let MASK: i64=255; let R: i64=6; let C: i64=6
31 var pass: i64=0; var total: i64=0
32 // 1) author RTL 2) synthesize -> fabric
33 let srclit: *u8=".nrtl 1\n.module demo 8\n.in a b\n.out y\nt = a & b\nu = a ^ b\ny = t + u\n.end\n\x00" as *u8
34 let mbuf: *u8=sys_mmap(4096); var ci: i64=0; while srclit[ci]!=(0 as u8){ mbuf[ci]=srclit[ci]; ci=ci+1 } mbuf[ci]=0 as u8
35 let cinit: *i64=sys_mmap(8*256) as *i64; let csrc: *i64=sys_mmap(8*1024) as *i64; let ckind: *i64=sys_mmap(8*256) as *i64
36 let cpo: *i64=sys_mmap(8*32) as *i64; let onpi: *i64=sys_mmap(16) as *i64; let onpo: *i64=sys_mmap(16) as *i64; let oW: *i64=sys_mmap(16) as *i64
37 let cn: i64=nrtl_synth(mbuf, ci, cinit, csrc, ckind, cpo, onpi, onpo, oW)
38 let NPI: i64=onpi[0]
39 // 3) place + route
40 let tile_of: *i64=sys_mmap(8*64) as *i64
41 nbit_place(cn, R, C, tile_of)
42 // 4) bitstream + virtual FPGA scratch
43 let bbuf: *u8=sys_mmap(16384)
44 let blen: i64=nbit_emit(bbuf, R, C, NPI, W, cn, tile_of, cinit, csrc, cpo)
45 let pi: *i64=sys_mmap(8*128) as *i64; let tileval: *i64=sys_mmap(8*64) as *i64; let out: *i64=sys_mmap(8*32) as *i64
46
47 // ---- T1: virtual FPGA (from bitstream) == oracle ----
48 var seed: i64=20260626; var mism: i64=0; var checks: i64=0
49 var t: i64=0
50 while t<100 {
51 seed=(seed*1103515245+12345)&2147483647; let a: i64=seed&MASK
52 seed=(seed*1103515245+12345)&2147483647; let b: i64=seed&MASK
53 let got: i64=vfpga_run(cn, NPI, W, tile_of, cinit, csrc, cpo, pi, tileval, out, a, b)
54 if got != (((a&b)+(a^b))&MASK) { mism=mism+1 }
55 checks=checks+1; t=t+1
56 }
57 total=total+1; if mism==0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
58 gw("T1 VIRTUAL FPGA (RTL->synth->P&R->bitstream->load) == oracle: checks=" as *u8); gn(checks); gw(" mismatches=" as *u8); gn(mism); gw(" (gates=" as *u8); gn(cn); gw(" grid=" as *u8); gn(R); gw("x" as *u8); gn(C); gw(" bitstream=" as *u8); gn(blen); gw("B)\n" as *u8)
59
60 // ---- T2: placement valid -- all cells on distinct tiles ----
61 let used: *i64=sys_mmap(8*64) as *i64; var u: i64=0; while u<R*C { used[u]=0; u=u+1 }
62 var conflicts: i64=0; var k: i64=0
63 while k<cn { let tid: i64=tile_of[k]; if used[tid]==1 { conflicts=conflicts+1 } used[tid]=1; k=k+1 }
64 let util: i64=cn*100/(R*C)
65 total=total+1; if conflicts==0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
66 gw("T2 PLACEMENT valid: " as *u8); gn(cn); gw("/" as *u8); gn(cn); gw(" cells on DISTINCT tiles, conflicts=" as *u8); gn(conflicts); gw(" (6x6 grid, " as *u8); gn(util); gw("% util) -- nextpnr/prjtrellis do this for real ECP5; ours sovereign for the virtual board\n" as *u8)
67
68 // ---- T3: never-brick ----
69 total=total+1; if blen>0 { if blen<16384 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } } else { gw(" [FAIL] " as *u8) }
70 gw("T3 NEVER-BRICK (#26): bitstream bounded (" as *u8); gn(blen); gw("B), pure config data, zero hardware-state writes\n" as *u8)
71
72 // ---- T4: liar-kill -- corrupt one tile's LUT config -> virtual FPGA wrong ----
73 let saved: i64=cinit[0]; cinit[0]=cinit[0]^65535
74 var liar_wrong: i64=0; var lt: i64=0
75 while lt<10 {
76 seed=(seed*1103515245+12345)&2147483647; let a: i64=seed&MASK
77 seed=(seed*1103515245+12345)&2147483647; let b: i64=seed&MASK
78 if vfpga_run(cn, NPI, W, tile_of, cinit, csrc, cpo, pi, tileval, out, a, b) != (((a&b)+(a^b))&MASK) { liar_wrong=liar_wrong+1 }
79 lt=lt+1
80 }
81 cinit[0]=saved
82 total=total+1; if liar_wrong>0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
83 gw("T4 LIAR-KILL: corrupted 1 tile LUT config -> virtual FPGA wrong on " as *u8); gn(liar_wrong); gw("/10 inputs\n" as *u8)
84
85 gw("NBIT-GATE verdict=" as *u8)
86 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 }
87 gw("RED passes=" as *u8); gn(pass); gw("/" as *u8); gn(total); gw(" END\n" as *u8); sys_exit(1); return 1
88}