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}