code wiki / _hdl_build / nx_fpga_pc_gate.nx
nx_fpga_pc_gate.nx source
↩ module page · 69 lines · 3806 B
1import "nx_gate_gn.nx"
2import "nx_gate_base.nx"
3// nx_fpga_pc_gate.nx -- GATE for RUNG 13a: the loadable PROGRAM COUNTER register. Proves the control-flow atom:
4// a clocked register that increments by default and LOADS a target on demand (the branch/jump primitive).
5// T1 INCREMENT (load=0): PC 0->1->2->... T2 LOAD (load=1,loadval=42): PC<-42 (a branch target).
6// T3 RESUME after load: next tick increments 42->43. T4 NEVER-BRICK. T5 LIAR-KILL (corrupt the inc net).
7// expect_exit: 0 license_tier: ORIGINAL
8import "nx_fpga_pc.nx"
9import "nx_syscalls.nx"
10
11func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw("
12" as *u8); return ok }
13
14func main() -> i64 {
15 gw("=== nx_fpga_pc_gate: RUNG 13a -- the loadable PROGRAM COUNTER register (control-flow atom) ===\n" as *u8)
16 var pass: i64 = 0; var total: i64 = 0
17 let W: i64 = 8
18 let kind: *i64=sys_mmap(8*64) as *i64; let init: *i64=sys_mmap(8*64) as *i64; let src: *i64=sys_mmap(8*256) as *i64
19 let po: *i64=sys_mmap(8*16) as *i64; let q: *i64=sys_mmap(8*64) as *i64; let co: *i64=sys_mmap(8*64) as *i64; let pi: *i64=sys_mmap(8*16) as *i64
20 seq_build_pc(W, kind, init, src, po)
21 var z: i64 = 0; while z < pc_ncells(W) { q[z]=0; z=z+1 }
22
23 // T1: increment 0..5
24 var t1ok: i64 = 1
25 var t: i64 = 0
26 while t < 6 {
27 if pc_read(W, q) != t { t1ok = 0 }
28 pc_tick(W, kind, init, src, pi, co, q, 0, 0)
29 t = t + 1
30 }
31 total=total+1; if t1ok==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
32 gw("T1 increment: PC counts 0->5 on load=0 ticks\n" as *u8)
33
34 // T2: load a branch target (42)
35 pc_tick(W, kind, init, src, pi, co, q, 1, 42)
36 let pl: i64 = pc_read(W, q)
37 total=total+1; if pl==42 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
38 gw("T2 load: PC <- 42 (branch target) on load=1; PC=" as *u8); gn(pl); gw("\n" as *u8)
39
40 // T3: resume increment after load
41 pc_tick(W, kind, init, src, pi, co, q, 0, 0)
42 let pr: i64 = pc_read(W, q)
43 total=total+1; if pr==43 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
44 gw("T3 resume: next tick increments 42->" as *u8); gn(pr); gw("\n" as *u8)
45
46 // T4: never-brick (deterministic) -- reset, tick 10, twice, same
47 z = 0; while z < pc_ncells(W) { q[z]=0; z=z+1 }
48 t = 0; while t < 10 { pc_tick(W, kind, init, src, pi, co, q, 0, 0); t=t+1 }
49 let a: i64 = pc_read(W, q)
50 z = 0; while z < pc_ncells(W) { q[z]=0; z=z+1 }
51 t = 0; while t < 10 { pc_tick(W, kind, init, src, pi, co, q, 0, 0); t=t+1 }
52 let b: i64 = pc_read(W, q)
53 total=total+1; if a==b { if a==10 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } } else { gw(" [FAIL] " as *u8) }
54 gw("T4 never-brick (#26): deterministic (two runs of 10 ticks -> " as *u8); gn(a); gw("), bounded, zero hw-state writes\n" as *u8)
55
56 // T5: liar-kill -- corrupt the increment sum cell of bit 0 -> counting breaks
57 seq_build_pc(W, kind, init, src, po)
58 init[W + 1] = init[W + 1] ^ 0xffff
59 z = 0; while z < pc_ncells(W) { q[z]=0; z=z+1 }
60 var bad: i64 = 0
61 t = 0
62 while t < 8 { if pc_read(W, q) != t { bad = bad + 1 } pc_tick(W, kind, init, src, pi, co, q, 0, 0); t=t+1 }
63 total=total+1; if bad > 0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
64 gw("T5 liar-kill: corrupting the increment net breaks the count in " as *u8); gn(bad); gw("/8 ticks\n" as *u8)
65
66 gw("\n=== nx_fpga_pc_gate " as *u8); gn(pass); gw("/" as *u8); gn(total)
67 if pass == total { gw(" GREEN (a loadable program counter -- increment or branch-target-load -- on the simulated FPGA)\n" as *u8); sys_exit(0); return 0 }
68 gw(" RED\n" as *u8); sys_exit(1); return 1
69}