code wiki / _hdl_build / nx_fpga_verilog_seq_gate.nx

nx_fpga_verilog_seq_gate.nx source

↩ module page · 88 lines · 5853 B

1import "nx_gate_gn.nx" 2import "nx_gate_base.nx" 3// nx_fpga_verilog_seq_gate.nx -- GATE for RUNG 28: SEQUENTIAL synth bridge. R27 emitted COMBINATIONAL fabrics to 4// Verilog; this proves the emitter (nx_fpga_verilog) also serializes CLOCKED fabrics -- DFF cells as `reg ff[k]` 5// latched in `always @(posedge clk)` -- so the WHOLE CPU (regfile/PC are sequential) can be emitted, not just logic. 6// Emits a 3-bit free-running COUNTER (nx_fpga_seq), round-trips it (emit -> re-parse -> byte-identical fabric), and 7// RUNS the RE-PARSED netlist through seq_tick to prove it actually COUNTS 0,1,2,3,... -- a working clocked circuit. 8// T1 the emitted sequential netlist re-parses to the SAME fabric (kind/init/src/po byte-identical). 9// T2 the RE-PARSED netlist, clocked via seq_tick, counts 0,1,2,3,4,5 (it is a working counter). 10// T3 NEVER-BRICK. T4 LIAR-KILL (corrupt the const-1/increment LUT -> emitted+reparsed counter stops counting). 11// expect_exit: 0 license_tier: ORIGINAL 12import "nx_fpga_verilog.nx" 13import "nx_fpga_seq.nx" 14import "nx_fpga_fabric.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 20// clock the (parsed) counter from q, read its W-bit count at each of `steps` ticks into out[] 21func run_counter(W: i64, ncells: i64, npi: i64, kind: *i64, init: *i64, src: *i64, po: *i64, steps: i64, out: *i64) -> i64 { 22 let pi: *i64=sys_mmap(8*8) as *i64; let co: *i64=sys_mmap(8*64) as *i64; let q: *i64=sys_mmap(8*64) as *i64 23 var z: i64=0; while z<ncells { q[z]=0; z=z+1 } 24 pi[0]=0 25 var t: i64=0 26 while t < steps { 27 seq_eval(ncells, npi, kind, init, src, pi, co, q) 28 var c: i64=0; var i: i64=0 29 while i < W { c = c | ((fab_po(po[i], npi, pi, co) & 1) << i); i=i+1 } 30 out[t]=c 31 seq_tick(ncells, npi, kind, init, src, pi, co, q) 32 t=t+1 33 } 34 return 0 35} 36 37func main() -> i64 { 38 gw("=== nx_fpga_verilog_seq_gate: RUNG 28 -- SEQUENTIAL synth bridge: clocked fabric -> Verilog (always @posedge) ===\n" as *u8) 39 var pass: i64 = 0; var total: i64 = 0 40 let W: i64 = 3 41 let kind: *i64=sys_mmap(8*16) as *i64; let init: *i64=sys_mmap(8*16) as *i64; let src: *i64=sys_mmap(8*64) as *i64; let po: *i64=sys_mmap(8*16) as *i64 42 let npi: i64 = seq_build_counter(W, kind, init, src, po) 43 let ncells: i64 = 3*W + 1; let npo: i64 = W 44 45 let buf: *u8=sys_mmap(8192) 46 let len: i64=fab_emit_verilog_seq(buf, ncells, npi, npo, kind, init, src, po) 47 buf[len]=0 as u8 48 gw("--- emitted sequential Verilog netlist (the bridge artifact) ---\n" as *u8); gw(buf); gw("--- end ---\n" as *u8) 49 50 // T1: round-trip 51 let rk: *i64=sys_mmap(8*16) as *i64; let ri: *i64=sys_mmap(8*16) as *i64; let rs: *i64=sys_mmap(8*64) as *i64; let rp: *i64=sys_mmap(8*16) as *i64 52 let pnpi: *i64=sys_mmap(16) as *i64; let pnpo: *i64=sys_mmap(16) as *i64 53 let rnc: i64=fab_parse_seq(buf, len, rk, ri, rs, rp, pnpi, pnpo) 54 var diff: i64=0 55 if rnc!=ncells {diff=diff+1} if pnpi[0]!=npi {diff=diff+1} if pnpo[0]!=npo {diff=diff+1} 56 var k: i64=0; while k<ncells { if rk[k]!=kind[k] {diff=diff+1} if ri[k]!=init[k] {diff=diff+1} var j: i64=0; while j<4 { if rs[k*4+j]!=src[k*4+j] {diff=diff+1} j=j+1 } k=k+1 } 57 var p: i64=0; while p<npo { if rp[p]!=po[p] {diff=diff+1} p=p+1 } 58 total=total+1; if diff==0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 59 gw("T1 the emitted SEQUENTIAL netlist re-parses to the SAME fabric (kind/init/src/po), differences=" as *u8); gn(diff); gw("\n" as *u8) 60 61 // T2: clock the re-parsed netlist -> it must count 0..5 62 let out: *i64=sys_mmap(8*16) as *i64 63 run_counter(W, rnc, pnpi[0], rk, ri, rs, rp, 6, out) 64 var cmis: i64=0; var t: i64=0 65 while t<6 { if out[t]!=t { cmis=cmis+1 } t=t+1 } 66 total=total+1; if cmis==0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 67 gw("T2 the RE-PARSED netlist clocked via seq_tick counts: \x00" as *u8); t=0; while t<6 { gn(out[t]); gw(" \x00" as *u8); t=t+1 }; gw("(expect 0 1 2 3 4 5), mismatches=" as *u8); gn(cmis); gw("\n" as *u8) 68 69 // T3: never-brick 70 let l2: i64=fab_emit_verilog_seq(buf, ncells, npi, npo, kind, init, src, po) 71 total=total+1; if l2==len { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 72 gw("T3 never-brick (#26): deterministic text emit, bounded, zero hardware-state writes\n" as *u8) 73 74 // T4: liar-kill -- corrupt the const-1 LUT (cell W), re-emit+re-parse; the counter must STOP counting 75 init[W] = init[W] ^ 0xffff // const1 -> const0: the +1 vanishes 76 let buf2: *u8=sys_mmap(8192); let len2: i64=fab_emit_verilog_seq(buf2, ncells, npi, npo, kind, init, src, po); buf2[len2]=0 as u8 77 let k2: *i64=sys_mmap(8*16) as *i64; let i2: *i64=sys_mmap(8*16) as *i64; let s2: *i64=sys_mmap(8*64) as *i64; let p2: *i64=sys_mmap(8*16) as *i64 78 let pn2: *i64=sys_mmap(16) as *i64; let po2: *i64=sys_mmap(16) as *i64 79 let rnc2: i64=fab_parse_seq(buf2, len2, k2, i2, s2, p2, pn2, po2) 80 let out2: *i64=sys_mmap(8*16) as *i64 81 run_counter(W, rnc2, pn2[0], k2, i2, s2, p2, 3, out2) 82 total=total+1; if out2[1] != 1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 83 gw("T4 liar-kill: corrupting the const-1 LUT -> the emitted+reparsed counter reads " as *u8); gn(out2[1]); gw(" at tick 1 (!= 1: counting broke)\n" as *u8) 84 85 gw("\n=== nx_fpga_verilog_seq_gate " as *u8); gn(pass); gw("/" as *u8); gn(total) 86 if pass == total { gw(" GREEN (the synth bridge serializes CLOCKED fabrics too: DFFs -> always@posedge, round-trips to a working counter -- the whole CPU can now be emitted to Verilog)\n" as *u8); sys_exit(0); return 0 } 87 gw(" RED\n" as *u8); sys_exit(1); return 1 88}