code wiki / _hdl_build / nx_jtag_load_gate.nx
nx_jtag_load_gate.nx source
↩ module page · 86 lines · 5633 B
1// nx_jtag_load_gate.nx -- GATE for the JTAG bitstream loader (M5 OpenOCD replacement). Loads the full-adder bitstream
2// through a faithful IEEE 1149.1 TAP and proves the load is real:
3// T1 PROTOCOL -- driving the TAP reaches Update-DR (state 8) and shifts all 272 bits.
4// T2 FAITHFUL -- the shifted-in config Data Register == the bitstream bits (no loss).
5// T3 CONFIGURED -- reassemble -> decode the loaded bits -> the fabric runs the golden full-adder (config works).
6// T4 LIAR-KILL -- a wrong TMS sequence (never reaches Shift-DR) shifts 0 bits (you must speak the real protocol).
7// T5 NEVER-BRICK-- volatile config, deterministic re-load, bounded.
8// GREEN iff all pass. Sovereign nx_cc->nxasm, no OpenOCD/Lattice. expect_exit: 0 license_tier: ORIGINAL
9import "nx_jtag_load.nx"
10import "nx_fpga_bitstream.nx"
11import "nx_fpga_fabric.nx"
12import "nx_fpga_lut.nx"
13import "nx_syscalls.nx"
14
15func w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
16func wn(v: i64) -> i64 { var m: i64=v; if m<0{w("-" as *u8);m=0-m} let t:*u8=sys_mmap(24); var k:i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i:i64=0; let o:*u8=sys_mmap(24); while i<k{o[i]=t[k-1-i];i=i+1} sys_write(1,o,k); return 0 }
17func parity3_init() -> i64 { var tt: i64=0; var i: i64=0; while i<16 { let a: i64=i&1; let b: i64=(i>>1)&1; let c: i64=(i>>2)&1; if (a^b^c)==1 { tt=tt|(1<<i) } i=i+1 } return tt }
18func maj3_init() -> i64 { var tt: i64=0; var i: i64=0; while i<16 { let a: i64=i&1; let b: i64=(i>>1)&1; let c: i64=(i>>2)&1; if (a+b+c)>=2 { tt=tt|(1<<i) } i=i+1 } return tt }
19
20func main() -> i64 {
21 w("=== nx_jtag_load_gate: JTAG bitstream loader (M5 OpenOCD replacement; faithful IEEE 1149.1 TAP) ===\n" as *u8)
22 var pass: i64 = 0; var total: i64 = 0
23
24 // encode the full-adder bitstream
25 let inits: *i64=sys_mmap(8*4) as *i64; inits[0]=parity3_init(); inits[1]=maj3_init()
26 let src: *i64=sys_mmap(8*16) as *i64; src[0]=0;src[1]=1;src[2]=2;src[3]=0; src[4]=0;src[5]=1;src[6]=2;src[7]=0
27 let po_src: *i64=sys_mmap(8*4) as *i64; po_src[0]=3; po_src[1]=4
28 let buf: *u8=sys_mmap(256)
29 let size: i64 = bs_encode(inits, src, po_src, 2, 3, 2, buf)
30 let nbits: i64 = size*8
31
32 // bytes -> bits (LSB first)
33 let bits: *i64=sys_mmap(8*512) as *i64
34 var i: i64 = 0
35 while i < size { var b: i64=0; while b<8 { bits[i*8+b] = ((buf[i] as i64) >> b) & 1; b=b+1 } i=i+1 }
36
37 let tms: *i64=sys_mmap(8*512) as *i64; let tdi: *i64=sys_mmap(8*512) as *i64
38 let dr: *i64=sys_mmap(8*512) as *i64; let shifted: *i64=sys_mmap(8*2) as *i64
39
40 let nclk: i64 = jtag_build_load(nbits, bits, tms, tdi)
41 let state: i64 = jtag_run(tms, tdi, nclk, dr, shifted)
42
43 // T1 protocol
44 total=total+1; if state==8 { if shifted[0]==nbits { pass=pass+1; w(" [PASS] " as *u8) } else { w(" [FAIL] " as *u8) } } else { w(" [FAIL] " as *u8) }
45 w("T1 protocol: final TAP state=" as *u8); wn(state); w(" (8=Update-DR) shifted=" as *u8); wn(shifted[0]); w("/" as *u8); wn(nbits); w(" bits\n" as *u8)
46
47 // T2 faithful
48 var bad: i64 = 0
49 i=0; while i<nbits { if dr[i]!=bits[i] { bad=bad+1 } i=i+1 }
50 total=total+1; if bad==0 { pass=pass+1; w(" [PASS] " as *u8) } else { w(" [FAIL] " as *u8) }
51 w("T2 faithful: config DR == bitstream, mismatched bits=" as *u8); wn(bad); w("\n" as *u8)
52
53 // T3 configured: reassemble -> decode -> run golden
54 let buf2: *u8=sys_mmap(256)
55 i=0; while i<size { var val: i64=0; var b: i64=0; while b<8 { val = val | (dr[i*8+b] << b); b=b+1 } buf2[i]=val as u8; i=i+1 }
56 let inits2: *i64=sys_mmap(8*4) as *i64; let src2: *i64=sys_mmap(8*16) as *i64; let po2: *i64=sys_mmap(8*4) as *i64; let hdr: *i64=sys_mmap(8*4) as *i64
57 bs_decode(buf2, inits2, src2, po2, hdr)
58 let pi: *i64=sys_mmap(8*4) as *i64; let co: *i64=sys_mmap(8*8) as *i64
59 var wrong: i64=0; var v: i64=0
60 while v < 8 {
61 let a: i64=v&1; let b: i64=(v>>1)&1; let cin: i64=(v>>2)&1
62 pi[0]=a; pi[1]=b; pi[2]=cin
63 fab_eval(hdr[0], hdr[1], inits2, src2, pi, co)
64 let sum: i64 = fab_po(po2[0], hdr[1], pi, co)
65 if sum != (a^b^cin) { wrong=wrong+1 }
66 v=v+1
67 }
68 total=total+1; if wrong==0 { pass=pass+1; w(" [PASS] " as *u8) } else { w(" [FAIL] " as *u8) }
69 w("T3 configured: loaded fabric runs the golden full-adder, wrong=" as *u8); wn(wrong); w("\n" as *u8)
70
71 // T4 liar-kill: a wrong TMS sequence (all 0 from TLR) never reaches Shift-DR
72 var j: i64=0; while j<12 { tms[j]=0; tdi[j]=0; j=j+1 }
73 jtag_run(tms, tdi, 12, dr, shifted)
74 total=total+1; if shifted[0]==0 { pass=pass+1; w(" [PASS] " as *u8) } else { w(" [FAIL] " as *u8) }
75 w("T4 liar-kill: wrong TMS (never Shift-DR) shifted=" as *u8); wn(shifted[0]); w(" bits (must speak the real protocol)\n" as *u8)
76
77 // T5 never-brick: deterministic re-load
78 let nclk2: i64 = jtag_build_load(nbits, bits, tms, tdi)
79 let state2: i64 = jtag_run(tms, tdi, nclk2, dr, shifted)
80 total=total+1; if state2==8 { if shifted[0]==nbits { pass=pass+1; w(" [PASS] " as *u8) } else { w(" [FAIL] " as *u8) } } else { w(" [FAIL] " as *u8) }
81 w("T5 never-brick: deterministic re-load shifted=" as *u8); wn(shifted[0]); w(" volatile config (power-cycle clears, can't brick)\n" as *u8)
82
83 w("\n=== nx_jtag_load_gate " as *u8); wn(pass); w("/" as *u8); wn(total)
84 if pass == total { w(" GREEN (JTAG loader: faithful IEEE 1149.1 TAP, bitstream shifts in + configures the fabric; never-brick volatile; the M5 OpenOCD replacement)\n" as *u8); sys_exit(0); return 0 }
85 w(" RED\n" as *u8); sys_exit(1); return 1
86}