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}