code wiki / _hdl_build / nx_fpga_shift_gate.nx

nx_fpga_shift_gate.nx source

↩ module page · 136 lines · 6973 B

1import "nx_gate_gn.nx" 2import "nx_gate_base.nx" 3// nx_fpga_shift_gate.nx -- GATE for RUNG 8c: the barrel-shifter fabric SLL/SRL/SRA == behavioral 4// nx_rv64im_alu_compute @ 64-bit, over ALL 64 shift amounts (every barrel stage combination) + sign-fill + the 5// shamt = b & 0x3f masking + LFSR. 6// T1 SLL == behavioral T2 SRL == behavioral T3 SRA == behavioral (incl negative a sign-fill) 7// T4 OP-DISTINCT -- SLL/SRL/SRA give different results (the control bits genuinely pick the shift kind). 8// T5 NEVER-BRICK T6 LIAR-KILL (scramble a stage MUX -> a shift breaks). 9// GREEN iff all pass. expect_exit: 0 license_tier: ORIGINAL 10import "nx_fpga_shift.nx" 11import "rv64im_min_alu.nx" 12import "nx_syscalls.nx" 13 14func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw(" 15" as *u8); return ok } 16 17func main() -> i64 { 18 gw("=== nx_fpga_shift_gate: RUNG 8c -- barrel-shifter SLL/SRL/SRA == behavioral @64-bit, all 64 shamts ===\n" as *u8) 19 var pass: i64 = 0; var total: i64 = 0 20 let W: i64 = 64 21 22 let inits: *i64 = sys_mmap(8 * 800) as *i64 23 let src: *i64 = sys_mmap(8 * 3200) as *i64 24 let po: *i64 = sys_mmap(8 * 72) as *i64 25 let pi: *i64 = sys_mmap(8 * 80) as *i64 26 let co: *i64 = sys_mmap(8 * 800) as *i64 27 let npi: i64 = fab_build_shifter(W, inits, src, po) 28 29 // operand KATs (incl sign-set + all-ones for SRA fill) 30 let ka: *i64 = sys_mmap(8 * 12) as *i64 31 ka[0]=1; ka[1]=0-1; ka[2]=6148914691236517205; ka[3]=(1<<63); ka[4]=81985529216486895; ka[5]=9223372036854775807 32 let nka: i64 = 6 33 // shift KATs (incl 32/63 boundary + 64/65/100 to test shamt = b&0x3f masking) 34 let kb: *i64 = sys_mmap(8 * 16) as *i64 35 kb[0]=0; kb[1]=1; kb[2]=7; kb[3]=31; kb[4]=32; kb[5]=63; kb[6]=64; kb[7]=65; kb[8]=100; kb[9]=0-1 36 let nkb: i64 = 10 37 38 // op table: opcode, right, arith 39 let opc: *i64 = sys_mmap(8 * 4) as *i64; let orp: *i64 = sys_mmap(8 * 4) as *i64; let oar: *i64 = sys_mmap(8 * 4) as *i64 40 opc[0]=NX_RV64IM_ALU_SLL; orp[0]=0; oar[0]=0 41 opc[1]=NX_RV64IM_ALU_SRL; orp[1]=1; oar[1]=0 42 opc[2]=NX_RV64IM_ALU_SRA; orp[2]=1; oar[2]=1 43 44 let names: *i64 = sys_mmap(8 * 4) as *i64 45 names[0]="SLL" as *u8 as i64; names[1]="SRL" as *u8 as i64; names[2]="SRA" as *u8 as i64 46 47 var oi: i64 = 0 48 while oi < 3 { 49 var checks: i64 = 0; var mism: i64 = 0 50 // KAT operands x shift KATs 51 var ai: i64 = 0 52 while ai < nka { 53 var bi: i64 = 0 54 while bi < nkb { 55 let a: i64 = ka[ai]; let b: i64 = kb[bi]; let shamt: i64 = b & 63 56 let got: i64 = fab_shift_run(W, npi, inits, src, po, pi, co, a, shamt, orp[oi], oar[oi]) 57 let want: i64 = nx_rv64im_alu_compute(opc[oi], a, b) 58 checks = checks + 1 59 if got != want { mism = mism + 1 } 60 bi = bi + 1 61 } 62 ai = ai + 1 63 } 64 // also EXHAUSTIVE over all 64 shamts for one witness operand (every stage combo) 65 var sh: i64 = 0 66 while sh < 64 { 67 let a: i64 = 0-81985529216486896 // a sign-set witness 68 let got: i64 = fab_shift_run(W, npi, inits, src, po, pi, co, a, sh, orp[oi], oar[oi]) 69 let want: i64 = nx_rv64im_alu_compute(opc[oi], a, sh) 70 checks = checks + 1 71 if got != want { mism = mism + 1 } 72 sh = sh + 1 73 } 74 // LFSR 75 var lcg: i64 = 1234567891011 76 var t: i64 = 0 77 while t < 200 { 78 lcg = (lcg * 2862933555777941757 + 3037000493) & 4611686018427387903 79 let d1: i64 = (lcg >> 5) & 4294967295 80 lcg = (lcg * 2862933555777941757 + 3037000493) & 4611686018427387903 81 let d2: i64 = (lcg >> 5) & 4294967295 82 let a: i64 = (d1 << 32) | d2 83 lcg = (lcg * 2862933555777941757 + 3037000493) & 4611686018427387903 84 let b: i64 = (lcg >> 5) 85 let got: i64 = fab_shift_run(W, npi, inits, src, po, pi, co, a, b & 63, orp[oi], oar[oi]) 86 let want: i64 = nx_rv64im_alu_compute(opc[oi], a, b) 87 checks = checks + 1 88 if got != want { mism = mism + 1 } 89 t = t + 1 90 } 91 total=total+1; if mism==0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 92 gw("T"); gn(oi+1); gw(" "); gw(names[oi] as *u8); gw(" == behavioral: "); gn(checks); gw(" checks, wrong="); gn(mism); gw("\n" as *u8) 93 oi = oi + 1 94 } 95 96 // ---- T4: op-distinct -- SLL/SRL/SRA differ for a sign-set operand shifted by 4 ---- 97 let wa: i64 = (1<<63) | 255 98 let rl: i64 = fab_shift_run(W, npi, inits, src, po, pi, co, wa, 4, 0, 0) 99 let rr: i64 = fab_shift_run(W, npi, inits, src, po, pi, co, wa, 4, 1, 0) 100 let rar: i64 = fab_shift_run(W, npi, inits, src, po, pi, co, wa, 4, 1, 1) 101 total=total+1 102 var ok4: i64 = 1 103 if rl==rr { ok4=0 } if rr==rar { ok4=0 } if rl==rar { ok4=0 } 104 if ok4==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 105 gw("T4 op-distinct: SLL/SRL/SRA give 3 different results for a sign-set operand (control bits select the shift)\n" as *u8) 106 107 // ---- T5: never-brick ---- 108 var t5ok: i64 = 1 109 let s1: i64 = fab_shift_run(W, npi, inits, src, po, pi, co, 123456789, 13, 1, 1) 110 var cc: i64 = 0 111 while cc < 2+12*W { if co[cc] < 0 { t5ok = 0 } if co[cc] > 1 { t5ok = 0 } cc = cc + 1 } 112 let s2: i64 = fab_shift_run(W, npi, inits, src, po, pi, co, 123456789, 13, 1, 1) 113 if s1 != s2 { t5ok = 0 } 114 total=total+1; if t5ok==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 115 gw("T5 never-brick (#26): bounded 2+12W-cell pass, outputs in {0,1}, deterministic, zero hw-state writes\n" as *u8) 116 117 // ---- T6: liar-kill -- scramble a stage-0 out MUX -> SLL breaks ---- 118 inits[3] = inits[3] ^ 0xffff // out MUX of stage0 bit0 (cell 3) 119 var liar_wrong: i64 = 0 120 var lt: i64 = 0 121 var llcg: i64 = 271828182 122 while lt < 64 { 123 llcg = (llcg * 2862933555777941757 + 3037000493) & 4611686018427387903 124 let a: i64 = (llcg >> 5) 125 llcg = (llcg * 2862933555777941757 + 3037000493) & 4611686018427387903 126 let b: i64 = (llcg >> 5) 127 if fab_shift_run(W, npi, inits, src, po, pi, co, a, b & 63, 0, 0) != nx_rv64im_alu_compute(NX_RV64IM_ALU_SLL, a, b) { liar_wrong = liar_wrong + 1 } 128 lt = lt + 1 129 } 130 total=total+1; if liar_wrong > 0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 131 gw("T6 liar-kill: scrambling a stage-0 MUX breaks SLL in "); gn(liar_wrong); gw("/64 operands\n" as *u8) 132 133 gw("\n=== nx_fpga_shift_gate " as *u8); gn(pass); gw("/" as *u8); gn(total) 134 if pass == total { gw(" GREEN (barrel-shifter SLL/SRL/SRA == behavioral rv64 ALU @64-bit, all shamts; log-depth shift network on the simulated FPGA)\n" as *u8); sys_exit(0); return 0 } 135 gw(" RED\n" as *u8); sys_exit(1); return 1 136}