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}