code wiki / _hdl_build / nx_fpga_alu_gate.nx

nx_fpga_alu_gate.nx source

↩ module page · 140 lines · 7494 B

1import "nx_gate_gn.nx" 2import "nx_gate_base.nx" 3// nx_fpga_alu_gate.nx -- GATE for RUNG 8: the LUT4-fabric ALU datapath == the team's BEHAVIORAL ALU 4// (nx_rv64im_alu_compute) at the full 64-bit RV64 word width, for the logic+arithmetic ops {AND,OR,XOR,ADD,SUB}. 5// The fabric runs ONLY from its bitstream; the oracle is the real CPU's ALU -- so GREEN means "these ALU ops 6// run correctly on the simulated FPGA fabric, byte-for-byte with the behavioral model." 7// T1 EQUIVALENCE -- 5 ops x (edge KATs + deterministic-LFSR full-64-bit operands) == nx_rv64im_alu_compute. 8// T2 OP-SELECT REAL -- the control bits select genuinely different ops (results differ where they must). 9// T3 NEVER-BRICK -- bounded (9W cells), total ({0,1}), deterministic. 10// T4 LIAR-KILL -- corrupting one result-MUX LUT makes an op wrong -> the fabric runs the bitstream; check bites. 11// GREEN iff all pass. expect_exit: 0 license_tier: ORIGINAL 12import "nx_fpga_alu.nx" 13import "rv64im_min_alu.nx" 14import "nx_syscalls.nx" 15 16func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw(" 17" as *u8); return ok } 18 19func main() -> i64 { 20 gw("=== nx_fpga_alu_gate: RUNG 8 -- LUT4-fabric ALU datapath == behavioral nx_rv64im_alu_compute @ 64-bit ===\n" as *u8) 21 var pass: i64 = 0; var total: i64 = 0 22 let W: i64 = 64 23 24 let inits: *i64 = sys_mmap(8 * 640) as *i64 25 let src: *i64 = sys_mmap(8 * 2560) as *i64 26 let po: *i64 = sys_mmap(8 * 72) as *i64 27 let pi: *i64 = sys_mmap(8 * 140) as *i64 28 let co: *i64 = sys_mmap(8 * 640) as *i64 29 let npi: i64 = fab_build_alu(W, inits, src, po) 30 31 // op table: opcode, sub, msel0, msel1 32 let opc: *i64 = sys_mmap(8 * 8) as *i64 33 let osb: *i64 = sys_mmap(8 * 8) as *i64 34 let om0: *i64 = sys_mmap(8 * 8) as *i64 35 let om1: *i64 = sys_mmap(8 * 8) as *i64 36 opc[0]=NX_RV64IM_ALU_AND; osb[0]=0; om0[0]=0; om1[0]=0 37 opc[1]=NX_RV64IM_ALU_OR; osb[1]=0; om0[1]=1; om1[1]=0 38 opc[2]=NX_RV64IM_ALU_XOR; osb[2]=0; om0[2]=0; om1[2]=1 39 opc[3]=NX_RV64IM_ALU_ADD; osb[3]=0; om0[3]=1; om1[3]=1 40 opc[4]=NX_RV64IM_ALU_SUB; osb[4]=1; om0[4]=1; om1[4]=1 41 let nops: i64 = 5 42 43 // edge KATs (full 64-bit): 0, all-ones(-1), 1, INT_MIN, 0x5555..., 0xAAAA..., mixed 44 let ka: *i64 = sys_mmap(8 * 24) as *i64 45 let kb: *i64 = sys_mmap(8 * 24) as *i64 46 ka[0]=0; kb[0]=0 47 ka[1]=0-1; kb[1]=0-1 48 ka[2]=1; kb[2]=0-1 49 ka[3]=(1 << 63); kb[3]=(1 << 63) 50 ka[4]=6148914691236517205; kb[4]=0-6148914691236517206 // 0x5555... , 0xAAAA... 51 ka[5]=123456789; kb[5]=987654321 52 ka[6]=0-1; kb[6]=1 53 ka[7]=(1 << 63); kb[7]=1 54 ka[8]=9223372036854775807; kb[8]=1 // INT_MAX + 1 (overflow) 55 ka[9]=0; kb[9]=1 // 0 - 1 borrow 56 let nkat: i64 = 10 57 58 // ---- T1: equivalence vs behavioral, all 5 ops ---- 59 var checks: i64 = 0; var mism: i64 = 0 60 var oi: i64 = 0 61 while oi < nops { 62 // KATs 63 var ki: i64 = 0 64 while ki < nkat { 65 let got: i64 = fab_alu_run(W, npi, inits, src, po, pi, co, ka[ki], kb[ki], osb[oi], om0[oi], om1[oi]) 66 let want: i64 = nx_rv64im_alu_compute(opc[oi], ka[ki], kb[ki]) 67 checks = checks + 1 68 if got != want { mism = mism + 1 } 69 ki = ki + 1 70 } 71 // deterministic-LFSR full-64-bit operands 72 var lcg: i64 = 1099511628211 73 var t: i64 = 0 74 while t < 200 { 75 lcg = (lcg * 2862933555777941757 + 3037000493) & 4611686018427387903 76 let d1: i64 = (lcg >> 5) & 4294967295 77 lcg = (lcg * 2862933555777941757 + 3037000493) & 4611686018427387903 78 let d2: i64 = (lcg >> 5) & 4294967295 79 let a: i64 = (d1 << 32) | d2 80 lcg = (lcg * 2862933555777941757 + 3037000493) & 4611686018427387903 81 let d3: i64 = (lcg >> 5) & 4294967295 82 lcg = (lcg * 2862933555777941757 + 3037000493) & 4611686018427387903 83 let d4: i64 = (lcg >> 5) & 4294967295 84 let b: i64 = (d3 << 32) | d4 85 let got: i64 = fab_alu_run(W, npi, inits, src, po, pi, co, a, b, osb[oi], om0[oi], om1[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 oi = oi + 1 92 } 93 total=total+1; if mism==0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 94 gw("T1 fabric ALU == behavioral @64-bit: " as *u8); gn(checks); gw(" checks (5 ops x KAT+LFSR), mismatches=" as *u8); gn(mism); gw("\n" as *u8) 95 96 // ---- T2: op-select real -- distinct ops give distinct results for a witness operand ---- 97 let wa: i64 = 6148914691236517205 // 0x5555... 98 let wb: i64 = 3735928559 // 0xDEADBEEF 99 let rv: *i64 = sys_mmap(8 * 8) as *i64 100 oi = 0 101 while oi < nops { rv[oi] = fab_alu_run(W, npi, inits, src, po, pi, co, wa, wb, osb[oi], om0[oi], om1[oi]); oi = oi + 1 } 102 var distinct: i64 = 1 103 if rv[0]==rv[1] { distinct = 0 } // AND vs OR 104 if rv[1]==rv[2] { distinct = 0 } // OR vs XOR 105 if rv[3]==rv[4] { distinct = 0 } // ADD vs SUB 106 total=total+1; if distinct==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 107 gw("T2 op-select real: the control bits select genuinely different ops (AND!=OR!=XOR, ADD!=SUB)\n" as *u8) 108 109 // ---- T3: never-brick ---- 110 var t3ok: i64 = 1 111 let r1: i64 = fab_alu_run(W, npi, inits, src, po, pi, co, 11111111, 22222222, 1, 1, 1) 112 var cc: i64 = 0 113 while cc < 9*W { if co[cc] < 0 { t3ok = 0 } if co[cc] > 1 { t3ok = 0 } cc = cc + 1 } 114 let r2: i64 = fab_alu_run(W, npi, inits, src, po, pi, co, 11111111, 22222222, 1, 1, 1) 115 if r1 != r2 { t3ok = 0 } 116 total=total+1; if t3ok==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 117 gw("T3 never-brick (#26): 9W-cell bounded pass, every cell output in {0,1}, deterministic, zero hw-state writes\n" as *u8) 118 119 // ---- T4: liar-kill -- corrupt the result-MUX LUT of bit 0 -> some op wrong ---- 120 let res0: i64 = 6*W + 0*3 + 2 // result MUX cell of bit 0 121 inits[res0] = inits[res0] ^ 0xffff // fully scramble that LUT 122 var liar_wrong: i64 = 0 123 var lt: i64 = 0 124 var llcg: i64 = 999983 125 while lt < 64 { 126 llcg = (llcg * 2862933555777941757 + 3037000493) & 4611686018427387903 127 let a: i64 = (llcg >> 5) 128 llcg = (llcg * 2862933555777941757 + 3037000493) & 4611686018427387903 129 let b: i64 = (llcg >> 5) 130 let got: i64 = fab_alu_run(W, npi, inits, src, po, pi, co, a, b, 0, 1, 1) // ADD 131 if got != nx_rv64im_alu_compute(NX_RV64IM_ALU_ADD, a, b) { liar_wrong = liar_wrong + 1 } 132 lt = lt + 1 133 } 134 total=total+1; if liar_wrong > 0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 135 gw("T4 liar-kill: scrambling bit-0 result-MUX LUT breaks ADD in " as *u8); gn(liar_wrong); gw("/64 operands\n" as *u8) 136 137 gw("\n=== nx_fpga_alu_gate " as *u8); gn(pass); gw("/" as *u8); gn(total) 138 if pass == total { gw(" GREEN (the LUT4-fabric ALU runs AND/OR/XOR/ADD/SUB == the behavioral rv64 ALU at 64-bit, from the bitstream; the CPU datapath on the simulated FPGA)\n" as *u8); sys_exit(0); return 0 } 139 gw(" RED\n" as *u8); sys_exit(1); return 1 140}