code wiki / _hdl_build / nx_fpga_compose_gate.nx
nx_fpga_compose_gate.nx source
↩ module page · 123 lines · 7604 B
1import "nx_gate_gn.nx"
2import "nx_gate_base.nx"
3// nx_fpga_compose_gate.nx -- GATE for RUNG 32a: the fabric COMPOSE primitive (fab_append). Composes two
4// independent 8-bit ripple-adder fabrics into ONE fabric where adder B's first operand is WIRED to adder A's
5// SUM (so the composed fabric computes (a+b)+c in a single fab_eval), and proves:
6// T1 the composed single fabric computes (a+b+c)&0xFF == behavioral oracle over 200 random (a,b,c), 0 mismatch.
7// T2 the composed fabric serializes through the Verilog synth bridge (emit + re-parse) and the RE-PARSED
8// netlist computes the SAME result == oracle -- i.e. compose THEN emit works (the R32c mechanism, early-proven).
9// T3 NEVER-BRICK (#26): the composed cell count is BOUNDED & exact (no unbounded growth); pure memory ops.
10// T4 LIAR-KILL: corrupt one composed cell's LUT init -> the composed output DIVERGES from the oracle.
11// Sovereign, no-float, integer-only. expect_exit: 0 license_tier: ORIGINAL
12import "nx_fpga_compose.nx"
13import "nx_fpga_adder.nx"
14import "nx_fpga_verilog.nx"
15import "nx_fpga_fabric.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
21// build the composed (a+b)+c fabric into cinit/csrc/ckind/cpo. Returns NCELLS (=4W). NPI via *outnpi; cpo = W outs.
22func build_compose(W: i64, cinit: *i64, csrc: *i64, ckind: *i64, cpo: *i64, outnpi: *i64) -> i64 {
23 let NPI: i64 = 3*W + 1 // pa[0..W-1], pb[W..2W-1], pc[2W..3W-1], zero-line@3W
24 outnpi[0] = NPI
25 // adder A: a + b
26 let Ai: *i64=sys_mmap(8*4*W) as *i64; let As: *i64=sys_mmap(8*16*W) as *i64; let Apo: *i64=sys_mmap(8*(2*W+4)) as *i64; let Ak: *i64=sys_mmap(8*4*W) as *i64
27 let Anpi: i64 = fab_build_ripple_adder(W, Ai, As, Apo)
28 var z: i64=0; while z<2*W { Ak[z]=0; z=z+1 }
29 // adder B: (A.sum) + c
30 let Bi: *i64=sys_mmap(8*4*W) as *i64; let Bs: *i64=sys_mmap(8*16*W) as *i64; let Bpo: *i64=sys_mmap(8*(2*W+4)) as *i64; let Bk: *i64=sys_mmap(8*4*W) as *i64
31 let Bnpi: i64 = fab_build_ripple_adder(W, Bi, Bs, Bpo)
32 z=0; while z<2*W { Bk[z]=0; z=z+1 }
33 // inmap A: a->PI[0..W-1], b->PI[W..2W-1], cin->zero-line PI[3W]
34 let imA: *i64=sys_mmap(8*(2*W+4)) as *i64
35 var i: i64=0; while i<W { imA[i]=i; imA[W+i]=W+i; i=i+1 }
36 imA[2*W]=3*W
37 let baseA: i64 = fab_append(NPI, cinit, csrc, ckind, 0, Anpi, 2*W, Ai, As, Ak, imA)
38 // inmap B: operand1 -> A.sum[i] (composed net), operand2 -> pc PI[2W..3W-1], cin -> zero-line PI[3W]
39 let imB: *i64=sys_mmap(8*(2*W+4)) as *i64
40 i=0; while i<W { imB[i]=fab_sub_out(NPI, baseA, Anpi, Apo[i], imA); imB[W+i]=2*W+i; i=i+1 }
41 imB[2*W]=3*W
42 let baseB: i64 = fab_append(NPI, cinit, csrc, ckind, 2*W, Bnpi, 2*W, Bi, Bs, Bk, imB)
43 // composed outputs = B.sum[i]
44 i=0; while i<W { cpo[i]=fab_sub_out(NPI, baseB, Bnpi, Bpo[i], imB); i=i+1 }
45 return 4*W
46}
47
48// evaluate a composed combinational fabric for (a,b,c) using caller-owned pi/co scratch; returns the W-bit sum.
49func run_compose(W: i64, NCELLS: i64, NPI: i64, cinit: *i64, csrc: *i64, cpo: *i64, pi: *i64, co: *i64, a: i64, b: i64, c: i64) -> i64 {
50 var i: i64=0
51 while i<W { pi[i]=(a>>i)&1; pi[W+i]=(b>>i)&1; pi[2*W+i]=(c>>i)&1; i=i+1 }
52 pi[3*W]=0
53 fab_eval(NCELLS, NPI, cinit, csrc, pi, co)
54 var s: i64=0; i=0
55 while i<W { let bit: i64=fab_resolve(cpo[i], NPI, pi, co); s=s|(bit<<i); i=i+1 }
56 return s
57}
58
59func main() -> i64 {
60 gw("=== nx_fpga_compose_gate: RUNG 32a -- compose module-fabrics into ONE fabric (fab_append) ===\n" as *u8)
61 let W: i64=8; let MASK: i64=255
62 var pass: i64=0; var total: i64=0
63 let cinit: *i64=sys_mmap(8*64) as *i64; let csrc: *i64=sys_mmap(8*256) as *i64; let ckind: *i64=sys_mmap(8*64) as *i64
64 let cpo: *i64=sys_mmap(8*16) as *i64; let onpi: *i64=sys_mmap(16) as *i64
65 let NCELLS: i64=build_compose(W, cinit, csrc, ckind, cpo, onpi)
66 let NPI: i64=onpi[0]
67 let pi: *i64=sys_mmap(8*64) as *i64; let co: *i64=sys_mmap(8*64) as *i64
68
69 // T1: composed fabric == oracle over 200 random (a,b,c)
70 var seed: i64=20260626; var mism: i64=0; var checks: i64=0
71 var t: i64=0
72 while t<200 {
73 seed=(seed*1103515245+12345)&2147483647; let a: i64=seed&MASK
74 seed=(seed*1103515245+12345)&2147483647; let b: i64=seed&MASK
75 seed=(seed*1103515245+12345)&2147483647; let c: i64=seed&MASK
76 let got: i64=run_compose(W, NCELLS, NPI, cinit, csrc, cpo, pi, co, a, b, c)
77 let exp: i64=(a+b+c)&MASK
78 if got!=exp { mism=mism+1 }
79 checks=checks+1
80 t=t+1
81 }
82 total=total+1; if mism==0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
83 gw("T1 composed (a+b)+c fabric == oracle: checks=" as *u8); gn(checks); gw(" mismatches=" as *u8); gn(mism); gw(" (NCELLS=" as *u8); gn(NCELLS); gw(" NPI=" as *u8); gn(NPI); gw(")\n" as *u8)
84
85 // T2: compose THEN emit -> Verilog -> re-parse -> re-evaluate -> == oracle
86 let buf: *u8=sys_mmap(65536)
87 let len: i64=fab_emit_verilog_seq(buf, NCELLS, NPI, W, ckind, cinit, csrc, cpo)
88 buf[len]=0 as u8
89 let rk: *i64=sys_mmap(8*64) as *i64; let ri: *i64=sys_mmap(8*64) as *i64; let rs: *i64=sys_mmap(8*256) as *i64; let rp: *i64=sys_mmap(8*16) as *i64
90 let pn: *i64=sys_mmap(16) as *i64; let pno: *i64=sys_mmap(16) as *i64
91 let rnc: i64=fab_parse_seq(buf, len, rk, ri, rs, rp, pn, pno)
92 var rmis: i64=0; seed=99887766
93 var t2: i64=0
94 while t2<40 {
95 seed=(seed*1103515245+12345)&2147483647; let a: i64=seed&MASK
96 seed=(seed*1103515245+12345)&2147483647; let b: i64=seed&MASK
97 seed=(seed*1103515245+12345)&2147483647; let c: i64=seed&MASK
98 let got: i64=run_compose(W, rnc, pn[0], ri, rs, rp, pi, co, a, b, c)
99 let exp: i64=(a+b+c)&MASK
100 if got!=exp { rmis=rmis+1 }
101 t2=t2+1
102 }
103 var structok: i64=0
104 if rnc==NCELLS { if pn[0]==NPI { if pno[0]==W { structok=1 } } }
105 total=total+1
106 if rmis==0 { if structok==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } } else { gw(" [FAIL] " as *u8) }
107 gw("T2 compose->Verilog->reparse netlist == oracle: reparsed 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)
108
109 // T3 NEVER-BRICK (#26): the compose produced exactly the bounded cell count -- no unbounded growth, pure memory.
110 total=total+1; if NCELLS==4*W { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
111 gw("T3 NEVER-BRICK (#26): composed cell count BOUNDED & exact NCELLS=" as *u8); gn(NCELLS); gw(" == 4*W=" as *u8); gn(4*W); gw(" (pure memory, zero hardware-state writes)\n" as *u8)
112
113 // T4 LIAR-KILL: corrupt one composed cell's LUT init -> output must diverge from the oracle.
114 let savedi: i64=cinit[0]; cinit[0]=0 // cell 0 = A.sum bit0; force it stuck-0
115 let got_bad: i64=run_compose(W, NCELLS, NPI, cinit, csrc, cpo, pi, co, 1, 0, 0) // oracle=1, LSB now stuck 0
116 cinit[0]=savedi
117 total=total+1; if got_bad != 1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
118 gw("T4 LIAR-KILL: corrupted composed cell -> got=" as *u8); gn(got_bad); gw(" != oracle 1 (divergence detected)\n" as *u8)
119
120 gw("COMPOSE-GATE verdict=" as *u8)
121 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 }
122 gw("RED passes=" as *u8); gn(pass); gw("/" as *u8); gn(total); gw(" END\n" as *u8); sys_exit(1); return 1
123}