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}