code wiki / _hdl_build / nx_fpga_rexec_gate.nx

nx_fpga_rexec_gate.nx source

↩ module page · 125 lines · 7512 B

1import "nx_gate_gn.nx" 2import "nx_gate_base.nx" 3// nx_fpga_rexec_gate.nx -- GATE for RUNG 32b: the R-type ALU-class EXECUTE datapath as ONE composed fabric 4// (decode + ALU folded via fab_append). Proves a REAL CPU control-unit + datapath, composed into a single 5// netlist, executes == the behavioral CPU: 6// T1 the composed (decode->ALU) fabric computes the DECODED op == nx_rv64im_alu_compute over the 5 ALU-class 7// R-type ops (ADD/SUB/XOR/OR/AND) x KAT+LFSR @ 64-bit, 0 mismatch -- the decoder's control drives the ALU. 8// T2 compose->Verilog->reparse: the composed fabric serializes through fab_emit_verilog_seq + fab_parse_seq 9// and the RE-PARSED netlist computes the SAME results == oracle (the whole-datapath .v round-trips). 10// T3 NEVER-BRICK (#26): bounded & exact cell count (8 + 9W), pure memory. 11// T4 LIAR-KILL: corrupt the DECODER's msel0 LUT -> wrong op selected -> results diverge from the oracle. 12// Sovereign, no-float, integer-only. expect_exit: 0 license_tier: ORIGINAL 13import "nx_fpga_rexec.nx" 14import "nx_fpga_verilog.nx" 15import "nx_fpga_fabric.nx" 16import "rv64im_min_alu.nx" 17import "nx_syscalls.nx" 18 19func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw(" 20" as *u8); return ok } 21 22// reference ALU op for the 5 ALU-class R-type ops (f3 in {0,4,6,7}) 23func ref_aop(f3: i64, f7b5: i64) -> i64 { 24 if f3==0 { if f7b5==1 { return NX_RV64IM_ALU_SUB } return NX_RV64IM_ALU_ADD } 25 if f3==4 { return NX_RV64IM_ALU_XOR } 26 if f3==6 { return NX_RV64IM_ALU_OR } 27 return NX_RV64IM_ALU_AND 28} 29 30func main() -> i64 { 31 gw("=== nx_fpga_rexec_gate: RUNG 32b -- R-type ALU-class EXECUTE as ONE composed fabric (decode+ALU) ===\n" as *u8) 32 let W: i64=64 33 var pass: i64=0; var total: i64=0 34 let cinit: *i64=sys_mmap(8*700) as *i64; let csrc: *i64=sys_mmap(8*2800) as *i64; let ckind: *i64=sys_mmap(8*700) as *i64 35 let cpo: *i64=sys_mmap(8*72) as *i64; let onpi: *i64=sys_mmap(16) as *i64 36 let NCELLS: i64=fab_build_rexec_alu(W, cinit, csrc, ckind, cpo, onpi) 37 let NPI: i64=onpi[0] 38 let pi: *i64=sys_mmap(8*200) as *i64; let co: *i64=sys_mmap(8*800) as *i64 39 40 // the 5 ALU-class ops (f3, f7b5) 41 let f3s: *i64=sys_mmap(8*8) as *i64; let f7s: *i64=sys_mmap(8*8) as *i64 42 f3s[0]=0; f7s[0]=0; f3s[1]=0; f7s[1]=1; f3s[2]=4; f7s[2]=0; f3s[3]=6; f7s[3]=0; f3s[4]=7; f7s[4]=0 43 let nops: i64=5 44 // operand KATs 45 let ka: *i64=sys_mmap(8*8) as *i64; let kb: *i64=sys_mmap(8*8) as *i64 46 ka[0]=0; kb[0]=0; ka[1]=1; kb[1]=1; ka[2]=0-1; kb[2]=5; ka[3]=0; kb[3]=0-1; ka[4]=(1<<63); kb[4]=3; ka[5]=123456789; kb[5]=37 47 let nka: i64=6 48 49 // ---- T1: composed decode+ALU == behavioral over the 5 ALU-class ops ---- 50 var checks: i64=0; var mism: i64=0; var c_op: i64=0-1; var c_a: i64=0; var c_b: i64=0; var c_got: i64=0; var c_exp: i64=0 51 var oi: i64=0 52 while oi<nops { 53 let f3: i64=f3s[oi]; let f7: i64=f7s[oi]; let aop: i64=ref_aop(f3,f7) 54 var ki: i64=0 55 while ki<nka { 56 let got: i64=fab_rexec_run(W, NCELLS, NPI, cinit, csrc, cpo, pi, co, f3, f7, ka[ki], kb[ki]) 57 let exp: i64=nx_rv64im_alu_compute(aop, ka[ki], kb[ki]) 58 if got!=exp { if c_op<0 { c_op=f3; c_a=ka[ki]; c_b=kb[ki]; c_got=got; c_exp=exp } mism=mism+1 } 59 checks=checks+1; ki=ki+1 60 } 61 var lcg: i64=1442695040888963407; var t: i64=0 62 while t<50 { 63 lcg=(lcg*2862933555777941757+3037000493)&4611686018427387903; let d1: i64=(lcg>>5)&4294967295 64 lcg=(lcg*2862933555777941757+3037000493)&4611686018427387903; let d2: i64=(lcg>>5)&4294967295 65 let a: i64=(d1<<32)|d2 66 lcg=(lcg*2862933555777941757+3037000493)&4611686018427387903; let d3: i64=(lcg>>5)&4294967295 67 lcg=(lcg*2862933555777941757+3037000493)&4611686018427387903; let d4: i64=(lcg>>5)&4294967295 68 let b: i64=(d3<<32)|d4 69 let got: i64=fab_rexec_run(W, NCELLS, NPI, cinit, csrc, cpo, pi, co, f3, f7, a, b) 70 let exp: i64=nx_rv64im_alu_compute(aop, a, b) 71 if got!=exp { if c_op<0 { c_op=f3; c_a=a; c_b=b; c_got=got; c_exp=exp } mism=mism+1 } 72 checks=checks+1; t=t+1 73 } 74 oi=oi+1 75 } 76 total=total+1; if mism==0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 77 gw("T1 composed decode+ALU == behavioral: checks=" as *u8); gn(checks); gw(" (5 ALU-class ops x KAT+LFSR) mismatches=" as *u8); gn(mism); gw(" (NCELLS=" as *u8); gn(NCELLS); gw(" NPI=" as *u8); gn(NPI); gw(")\n" as *u8) 78 if c_op>=0 { gw(" first diverge: f3=" as *u8); gn(c_op); gw(" a=" as *u8); gn(c_a); gw(" b=" as *u8); gn(c_b); gw(" got=" as *u8); gn(c_got); gw(" exp=" as *u8); gn(c_exp); gw("\n" as *u8) } 79 80 // ---- T2: compose -> Verilog -> reparse -> re-evaluate == oracle ---- 81 let buf: *u8=sys_mmap(131072) 82 let len: i64=fab_emit_verilog_seq(buf, NCELLS, NPI, W, ckind, cinit, csrc, cpo) 83 buf[len]=0 as u8 84 let rk: *i64=sys_mmap(8*700) as *i64; let ri: *i64=sys_mmap(8*700) as *i64; let rs: *i64=sys_mmap(8*2800) as *i64; let rp: *i64=sys_mmap(8*72) as *i64 85 let pn: *i64=sys_mmap(16) as *i64; let pno: *i64=sys_mmap(16) as *i64 86 let rnc: i64=fab_parse_seq(buf, len, rk, ri, rs, rp, pn, pno) 87 var rmis: i64=0 88 var ri2: i64=0 89 while ri2<nops { 90 let f3: i64=f3s[ri2]; let f7: i64=f7s[ri2]; let aop: i64=ref_aop(f3,f7) 91 var kj: i64=0 92 while kj<nka { 93 let got: i64=fab_rexec_run(W, rnc, pn[0], ri, rs, rp, pi, co, f3, f7, ka[kj], kb[kj]) 94 if got != nx_rv64im_alu_compute(aop, ka[kj], kb[kj]) { rmis=rmis+1 } 95 kj=kj+1 96 } 97 ri2=ri2+1 98 } 99 var structok: i64=0 100 if rnc==NCELLS { if pn[0]==NPI { if pno[0]==W { structok=1 } } } 101 total=total+1 102 if rmis==0 { if structok==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } } else { gw(" [FAIL] " as *u8) } 103 gw("T2 compose->Verilog->reparse netlist == oracle: ncells=" as *u8); gn(rnc); gw(" npi=" as *u8); gn(pn[0]); gw(" vlen=" as *u8); gn(len); gw(" mismatches=" as *u8); gn(rmis); gw("\n" as *u8) 104 105 // ---- T3: never-brick -- bounded & exact cell count ---- 106 total=total+1; if NCELLS==8+9*W { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 107 gw("T3 NEVER-BRICK (#26): bounded & exact NCELLS=" as *u8); gn(NCELLS); gw(" == 8+9W=" as *u8); gn(8+9*W); gw(" (pure memory, zero hardware-state writes)\n" as *u8) 108 109 // ---- T4: liar-kill -- corrupt the DECODER msel0 LUT -> wrong op selected -> divergence ---- 110 let saved: i64=cinit[1]; cinit[1]=cinit[1]^65535 // cell 1 = decoder msel0 LUT 111 var liar_wrong: i64=0 112 var lt: i64=0 113 while lt<nops { 114 let f3: i64=f3s[lt]; let f7: i64=f7s[lt] 115 if fab_rexec_run(W, NCELLS, NPI, cinit, csrc, cpo, pi, co, f3, f7, 1234567, 89) != nx_rv64im_alu_compute(ref_aop(f3,f7), 1234567, 89) { liar_wrong=liar_wrong+1 } 116 lt=lt+1 117 } 118 cinit[1]=saved 119 total=total+1; if liar_wrong>0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 120 gw("T4 LIAR-KILL: corrupting the decoder msel0 LUT mis-selects " as *u8); gn(liar_wrong); gw("/5 ops\n" as *u8) 121 122 gw("REXEC-GATE verdict=" as *u8) 123 if pass==total { gw("GREEN passes=" as *u8); gn(pass); gw("/" as *u8); gn(total); gw(" END\n" as *u8); sys_exit(0); return 0 } 124 gw("RED passes=" as *u8); gn(pass); gw("/" as *u8); gn(total); gw(" END\n" as *u8); sys_exit(1); return 1 125}