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}