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}