code wiki / _hdl_build / nx_nhdl_hier_gate.nx
nx_nhdl_hier_gate.nx source
↩ module page · 120 lines · 7586 B
1import "nx_gate_gn.nx"
2import "nx_gate_base.nx"
3// nx_nhdl_hier_gate.nx -- GATE for NHDL H2: HIERARCHY + folding in the sovereign netlist format. Defines ONE
4// reusable module (adder8) and INSTANTIATES it 4x in a chain (sum of 5 operands), then ELABORATES the hierarchical
5// NHDL to a flat fabric via the proven fab_append, proving:
6// T1 the elaborated flat fabric computes (op0+..+op4)&0xFF == behavioral oracle over 100 random inputs (hierarchy lossless).
7// T2 FOLDING BENCHMARK: hierarchical NHDL stores adder8's 16 cells ONCE + 4 instance lines, vs a FLAT netlist that
8// expands to 4x16=64 cells -- hierarchical is smaller and the gap SCALES with instance count (def amortized).
9// T3 NEVER-BRICK (#26): bounded, pure memory.
10// T4 LIAR-KILL: corrupt ONE cell of the shared .def -> ALL 4 instances break -> elaborated fabric computes wrong.
11// Sovereign, no-float. expect_exit: 0 license_tier: ORIGINAL
12import "nx_nhdl_hier.nx"
13import "nx_nhdl.nx"
14import "nx_fpga_adder.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// emit the K-instance adder-chain design as hierarchical NHDL (one .def adder8 + K .inst). Returns length.
22func emit_chain(hbuf: *u8, mi: *i64, ms: *i64, mpo: *i64, m_npi: i64, m_npo: i64, m_nc: i64, W: i64, K: i64) -> i64 {
23 let NOPS: i64=K+1
24 let TNPI: i64=NOPS*W + 1
25 let ZERO: i64=NOPS*W
26 var o: i64=0
27 o=nh_ws(hbuf,o,".nhdl 2\n.def adder8 \x00" as *u8); o=nh_wi(hbuf,o,m_npi); o=nh_ws(hbuf,o," \x00" as *u8); o=nh_wi(hbuf,o,m_npo); o=nh_ws(hbuf,o," \x00" as *u8); o=nh_wi(hbuf,o,m_nc); o=nh_ws(hbuf,o,"\n\x00" as *u8)
28 let zk: *i64=sys_mmap(8*64) as *i64; var z: i64=0; while z<m_nc { zk[z]=0; z=z+1 }
29 o=nh_emit_cells(hbuf, o, m_nc, zk, mi, ms)
30 o=nh_ws(hbuf,o,".po\x00" as *u8); var j: i64=0; while j<m_npo { o=nh_ws(hbuf,o," \x00" as *u8); o=nh_wi(hbuf,o,mpo[j]); j=j+1 }
31 o=nh_ws(hbuf,o,"\n.enddef\n.top \x00" as *u8); o=nh_wi(hbuf,o,TNPI); o=nh_ws(hbuf,o," \x00" as *u8); o=nh_wi(hbuf,o,W); o=nh_ws(hbuf,o,"\n\x00" as *u8)
32 var i: i64=0
33 while i<K {
34 o=nh_ws(hbuf,o,".inst adder8\x00" as *u8)
35 var b: i64=0
36 while b<W { var net: i64=b; if i>0 { net=TNPI + (i-1)*m_npo + b } o=nh_ws(hbuf,o," \x00" as *u8); o=nh_wi(hbuf,o,net); b=b+1 } // operand a
37 b=0; while b<W { o=nh_ws(hbuf,o," \x00" as *u8); o=nh_wi(hbuf,o,(i+1)*W + b); b=b+1 } // operand b = op(i+1)
38 o=nh_ws(hbuf,o," \x00" as *u8); o=nh_wi(hbuf,o,ZERO) // cin = zero
39 o=nh_ws(hbuf,o,"\n\x00" as *u8)
40 i=i+1
41 }
42 o=nh_ws(hbuf,o,".po\x00" as *u8)
43 var b2: i64=0; while b2<W { o=nh_ws(hbuf,o," \x00" as *u8); o=nh_wi(hbuf,o, TNPI + (K-1)*m_npo + b2); b2=b2+1 }
44 o=nh_ws(hbuf,o,"\n.end\n\x00" as *u8)
45 return o
46}
47
48func run_sum(cn: i64, NPI: i64, cinit: *i64, csrc: *i64, cpo: *i64, pi: *i64, co: *i64, ops: *i64, NOPS: i64, W: i64) -> i64 {
49 var i: i64=0
50 while i<NOPS { var b: i64=0; while b<W { pi[i*W+b]=(ops[i]>>b)&1; b=b+1 } i=i+1 }
51 pi[NOPS*W]=0
52 fab_eval(cn, NPI, cinit, csrc, pi, co)
53 var s: i64=0; var b2: i64=0
54 while b2<W { let bit: i64=fab_resolve(cpo[b2], NPI, pi, co); s=s|(bit<<b2); b2=b2+1 }
55 return s
56}
57
58func main() -> i64 {
59 gw("=== nx_nhdl_hier_gate: NHDL H2 -- hierarchy + folding (one .def adder8, instantiated 4x) ===\n" as *u8)
60 let W: i64=8; let K: i64=4; let NOPS: i64=5; let MASK: i64=255
61 var pass: i64=0; var total: i64=0
62 // adder8 module fabric
63 let mi: *i64=sys_mmap(8*64) as *i64; let ms: *i64=sys_mmap(8*256) as *i64; let mpo: *i64=sys_mmap(8*16) as *i64
64 let m_npi: i64=fab_build_ripple_adder(W, mi, ms, mpo) // =2W+1=17
65 let m_npo: i64=W+1; let m_nc: i64=2*W // 9, 16
66 // emit hierarchical chain
67 let hbuf: *u8=sys_mmap(16384)
68 let hlen: i64=emit_chain(hbuf, mi, ms, mpo, m_npi, m_npo, m_nc, W, K)
69 hbuf[hlen]=0 as u8
70 // elaborate -> flat fabric
71 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
72 let cpo: *i64=sys_mmap(8*16) as *i64; let onpi: *i64=sys_mmap(16) as *i64; let onpo: *i64=sys_mmap(16) as *i64
73 let cn: i64=nhdl_hier_elaborate(hbuf, hlen, cinit, csrc, ckind, cpo, onpi, onpo)
74 let NPI: i64=onpi[0]
75 let pi: *i64=sys_mmap(8*128) as *i64; let co: *i64=sys_mmap(8*256) as *i64
76
77 // ---- T1: elaborated flat fabric == oracle over 100 random inputs ----
78 var seed: i64=20260626; var mism: i64=0; var checks: i64=0
79 let ops: *i64=sys_mmap(8*8) as *i64
80 var t: i64=0
81 while t<100 {
82 var i: i64=0; var sum: i64=0
83 while i<NOPS { seed=(seed*1103515245+12345)&2147483647; ops[i]=seed&MASK; sum=sum+ops[i]; i=i+1 }
84 let got: i64=run_sum(cn, NPI, cinit, csrc, cpo, pi, co, ops, NOPS, W)
85 if got != (sum & MASK) { mism=mism+1 }
86 checks=checks+1; t=t+1
87 }
88 total=total+1; if mism==0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
89 gw("T1 elaborated hierarchy (4x adder8 chain) == oracle: checks=" as *u8); gn(checks); gw(" mismatches=" as *u8); gn(mism); gw(" (flat cells=" as *u8); gn(cn); gw(" NPI=" as *u8); gn(NPI); gw(")\n" as *u8)
90
91 // ---- T2: FOLDING BENCHMARK -- hierarchical vs flat NHDL ----
92 let fbuf: *u8=sys_mmap(16384)
93 let flen: i64=nhdl_emit(fbuf, "chain_flat" as *u8, cn, NPI, W, ckind, cinit, csrc, cpo)
94 total=total+1; if hlen<flen { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
95 gw("T2 FOLDING vs flat NHDL: hierarchical=" as *u8); gn(hlen); gw("B (adder8 16 cells stored ONCE + " as *u8); gn(K); gw(" inst lines) vs FLAT=" as *u8); gn(flen); gw("B (" as *u8); gn(cn); gw(" cells expanded). flat cells = K*16 grows with K; the .def stays 16 -> folding scales\n" as *u8)
96
97 // ---- T3: never-brick ----
98 total=total+1; if cn==K*m_nc { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
99 gw("T3 NEVER-BRICK (#26): elaboration bounded & exact (flat cells=" as *u8); gn(cn); gw(" == K*16=" as *u8); gn(K*m_nc); gw("), pure memory\n" as *u8)
100
101 // ---- T4: liar-kill -- corrupt ONE cell of the shared .def -> ALL instances break ----
102 var lpos: i64=0-1; var si: i64=0
103 while si<hlen { if hbuf[si]==(76 as u8) { if lpos<0 { lpos=si } } si=si+1 } // first 'L' = .def cell 0
104 let dpos: i64=lpos+2
105 if (hbuf[dpos] as i64)==48 { hbuf[dpos]=49 as u8 } else { hbuf[dpos]=48 as u8 }
106 let cn2: i64=nhdl_hier_elaborate(hbuf, hlen, cinit, csrc, ckind, cpo, onpi, onpo)
107 var liar_wrong: i64=0; var lt: i64=0
108 while lt<10 {
109 var i: i64=0; var sum: i64=0
110 while i<NOPS { seed=(seed*1103515245+12345)&2147483647; ops[i]=seed&MASK; sum=sum+ops[i]; i=i+1 }
111 if run_sum(cn2, onpi[0], cinit, csrc, cpo, pi, co, ops, NOPS, W) != (sum & MASK) { liar_wrong=liar_wrong+1 }
112 lt=lt+1
113 }
114 total=total+1; if liar_wrong>0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
115 gw("T4 LIAR-KILL: 1 corrupted .def cell breaks all 4 instances -> wrong on " as *u8); gn(liar_wrong); gw("/10 inputs\n" as *u8)
116
117 gw("NHDL-HIER-GATE verdict=" as *u8)
118 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 }
119 gw("RED passes=" as *u8); gn(pass); gw("/" as *u8); gn(total); gw(" END\n" as *u8); sys_exit(1); return 1
120}