code wiki / _hdl_build / nx_fpga_rtype_gate.nx

nx_fpga_rtype_gate.nx source

↩ module page · 159 lines · 8864 B

1import "nx_gate_gn.nx" 2import "nx_gate_base.nx" 3// nx_fpga_rtype_gate.nx -- GATE for RUNG 9: an RV64I R-type instruction DECODED + EXECUTED on the fabric == 4// the behavioral CPU. Composes the DECODER fabric (nx_fpga_decode: funct3/funct7b5 -> control + result-class) 5// with the ALU/shift/compare datapath fabrics: decode-on-fabric drives execute-on-fabric, and the composed 6// result is checked against the behavioral path (decode -> nx_rv64im_alu_compute). Both stages are real fabric 7// computations -- the CPU's integer execute stage running on the simulated FPGA. 8// T1 INSTRUCTION EXECUTE == behavioral, all 10 R-type ops (ADD/SUB/SLL/SLT/SLTU/XOR/SRL/SRA/OR/AND) x KAT+LFSR. 9// T2 DECODER correct -- the decoder fabric's control outputs == the golden decode table, all funct3 x funct7b5. 10// T3 NEVER-BRICK. T4 LIAR-KILL -- corrupt the decoder's class LUT -> wrong dispatch -> wrong instruction result. 11// GREEN iff all pass. expect_exit: 0 license_tier: ORIGINAL 12import "nx_fpga_decode.nx" 13import "nx_fpga_alu.nx" 14import "nx_fpga_cmp.nx" 15import "nx_fpga_shift.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 22func ref_aluop(f3: i64, f7b5: i64) -> i64 { 23 if f3==0 { if f7b5==1 { return NX_RV64IM_ALU_SUB } return NX_RV64IM_ALU_ADD } 24 if f3==1 { return NX_RV64IM_ALU_SLL } 25 if f3==2 { return NX_RV64IM_ALU_SLT } 26 if f3==3 { return NX_RV64IM_ALU_SLTU } 27 if f3==4 { return NX_RV64IM_ALU_XOR } 28 if f3==5 { if f7b5==1 { return NX_RV64IM_ALU_SRA } return NX_RV64IM_ALU_SRL } 29 if f3==6 { return NX_RV64IM_ALU_OR } 30 return NX_RV64IM_ALU_AND 31} 32 33// ctx layout: 0=DI 1=DS 2=DP | 3=AI 4=AS 5=AP 6=alu_npi | 7=CI 8=CS 9=CP 10=cmp_npi | 11=SI 12=SS 13=SP 14=sh_npi | 15=PI 16=CO 17=CTRL 34// decode (on fabric) -> dispatch to the datapath (on fabric) -> the instruction result. 35func r9_exec(ctx: *i64, f3: i64, f7b5: i64, rs1: i64, rs2: i64) -> i64 { 36 let DI: *i64 = ctx[0] as *i64; let DS: *i64 = ctx[1] as *i64; let DP: *i64 = ctx[2] as *i64 37 let PIv: *i64 = ctx[15] as *i64; let COv: *i64 = ctx[16] as *i64; let CTRL: *i64 = ctx[17] as *i64 38 fab_decode_run(DI, DS, DP, PIv, COv, f3, f7b5, CTRL) 39 let cls: i64 = CTRL[6] | (CTRL[7] << 1) 40 if cls == 0 { return fab_alu_run(64, ctx[6], ctx[3] as *i64, ctx[4] as *i64, ctx[5] as *i64, PIv, COv, rs1, rs2, CTRL[0], CTRL[1], CTRL[2]) } 41 if cls == 1 { return fab_shift_run(64, ctx[14], ctx[11] as *i64, ctx[12] as *i64, ctx[13] as *i64, PIv, COv, rs1, rs2 & 63, CTRL[3], CTRL[4]) } 42 return fab_cmp_run(64, ctx[10], ctx[7] as *i64, ctx[8] as *i64, ctx[9] as *i64, PIv, COv, rs1, rs2, CTRL[5]) 43} 44 45func main() -> i64 { 46 gw("=== nx_fpga_rtype_gate: RUNG 9 -- R-type instruction DECODE+EXECUTE on the fabric == behavioral CPU ===\n" as *u8) 47 var pass: i64 = 0; var total: i64 = 0 48 49 let ctx: *i64 = sys_mmap(8 * 32) as *i64 50 ctx[0] = sys_mmap(8 * 16) as i64; ctx[1] = sys_mmap(8 * 48) as i64; ctx[2] = sys_mmap(8 * 16) as i64 51 ctx[3] = sys_mmap(8 * 640) as i64; ctx[4] = sys_mmap(8 * 2560) as i64; ctx[5] = sys_mmap(8 * 72) as i64 52 ctx[7] = sys_mmap(8 * 256) as i64; ctx[8] = sys_mmap(8 * 1024) as i64; ctx[9] = sys_mmap(8 * 72) as i64 53 ctx[11] = sys_mmap(8 * 800) as i64; ctx[12] = sys_mmap(8 * 3200) as i64; ctx[13] = sys_mmap(8 * 72) as i64 54 ctx[15] = sys_mmap(8 * 140) as i64; ctx[16] = sys_mmap(8 * 800) as i64; ctx[17] = sys_mmap(8 * 16) as i64 55 56 fab_build_decode(ctx[0] as *i64, ctx[1] as *i64, ctx[2] as *i64) 57 ctx[6] = fab_build_alu(64, ctx[3] as *i64, ctx[4] as *i64, ctx[5] as *i64) 58 ctx[10] = fab_build_cmp(64, ctx[7] as *i64, ctx[8] as *i64, ctx[9] as *i64) 59 ctx[14] = fab_build_shifter(64, ctx[11] as *i64, ctx[12] as *i64, ctx[13] as *i64) 60 61 // the 10 R-type ops (f3, f7b5) 62 let f3a: *i64 = sys_mmap(8 * 16) as *i64; let f7a: *i64 = sys_mmap(8 * 16) as *i64 63 f3a[0]=0; f7a[0]=0; f3a[1]=0; f7a[1]=1; f3a[2]=1; f7a[2]=0; f3a[3]=2; f7a[3]=0; f3a[4]=3; f7a[4]=0 64 f3a[5]=4; f7a[5]=0; f3a[6]=5; f7a[6]=0; f3a[7]=5; f7a[7]=1; f3a[8]=6; f7a[8]=0; f3a[9]=7; f7a[9]=0 65 let nops: i64 = 10 66 67 // operand KATs 68 let ka: *i64 = sys_mmap(8 * 16) as *i64; let kb: *i64 = sys_mmap(8 * 16) as *i64 69 ka[0]=0; kb[0]=0 70 ka[1]=1; kb[1]=1 71 ka[2]=0-1; kb[2]=5 72 ka[3]=6148914691236517205; kb[3]=0-6148914691236517206 73 ka[4]=(1<<63); kb[4]=3 74 ka[5]=123456789; kb[5]=37 75 ka[6]=0-1; kb[6]=0-1 76 ka[7]=0; kb[7]=0-1 77 let nka: i64 = 8 78 79 // ---- T1: instruction execute == behavioral, all 10 ops ---- 80 var checks: i64 = 0; var mism: i64 = 0 81 var oi: i64 = 0 82 while oi < nops { 83 let f3: i64 = f3a[oi]; let f7: i64 = f7a[oi] 84 let aluop: i64 = ref_aluop(f3, f7) 85 var ki: i64 = 0 86 while ki < nka { 87 checks = checks + 1 88 if r9_exec(ctx, f3, f7, ka[ki], kb[ki]) != nx_rv64im_alu_compute(aluop, ka[ki], kb[ki]) { mism = mism + 1 } 89 ki = ki + 1 90 } 91 var lcg: i64 = 1442695040888963407 92 var t: i64 = 0 93 while t < 120 { 94 lcg = (lcg * 2862933555777941757 + 3037000493) & 4611686018427387903 95 let d1: i64 = (lcg >> 5) & 4294967295 96 lcg = (lcg * 2862933555777941757 + 3037000493) & 4611686018427387903 97 let d2: i64 = (lcg >> 5) & 4294967295 98 let a: i64 = (d1 << 32) | d2 99 lcg = (lcg * 2862933555777941757 + 3037000493) & 4611686018427387903 100 let d3: i64 = (lcg >> 5) & 4294967295 101 lcg = (lcg * 2862933555777941757 + 3037000493) & 4611686018427387903 102 let d4: i64 = (lcg >> 5) & 4294967295 103 let b: i64 = (d3 << 32) | d4 104 checks = checks + 1 105 if r9_exec(ctx, f3, f7, a, b) != nx_rv64im_alu_compute(aluop, a, b) { mism = mism + 1 } 106 t = t + 1 107 } 108 oi = oi + 1 109 } 110 total=total+1; if mism==0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 111 gw("T1 R-type DECODE+EXECUTE on fabric == behavioral: " as *u8); gn(checks); gw(" checks (10 ops x KAT+LFSR), mismatches=" as *u8); gn(mism); gw("\n" as *u8) 112 113 // ---- T2: decoder fabric correct vs the golden decode table ---- 114 let DIc: *i64 = ctx[0] as *i64; let DSc: *i64 = ctx[1] as *i64; let DPc: *i64 = ctx[2] as *i64 115 let PIc: *i64 = ctx[15] as *i64; let COc: *i64 = ctx[16] as *i64; let CTc: *i64 = ctx[17] as *i64 116 var dchecks: i64 = 0; var dbad: i64 = 0 117 var f3: i64 = 0 118 while f3 < 8 { 119 var f7: i64 = 0 120 while f7 < 2 { 121 fab_decode_run(DIc, DSc, DPc, PIc, COc, f3, f7, CTc) 122 dchecks = dchecks + 1 123 if CTc[0] != r9_sub(f3,f7) { dbad = dbad + 1 } 124 if CTc[1] != r9_msel0(f3) { dbad = dbad + 1 } 125 if CTc[2] != r9_msel1(f3) { dbad = dbad + 1 } 126 if CTc[3] != r9_right(f3) { dbad = dbad + 1 } 127 if CTc[4] != r9_arith(f3,f7) { dbad = dbad + 1 } 128 if CTc[5] != r9_uns(f3) { dbad = dbad + 1 } 129 if (CTc[6] | (CTc[7]<<1)) != r9_class(f3) { dbad = dbad + 1 } 130 f7 = f7 + 1 131 } 132 f3 = f3 + 1 133 } 134 total=total+1; if dbad==0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 135 gw("T2 decoder fabric == golden decode table: " as *u8); gn(dchecks); gw(" funct3xfunct7b5 combos, control-bit mismatches=" as *u8); gn(dbad); gw("\n" as *u8) 136 137 // ---- T3: never-brick (bounded + deterministic) ---- 138 let r1: i64 = r9_exec(ctx, 0, 1, 999983, 314159) 139 let r2: i64 = r9_exec(ctx, 0, 1, 999983, 314159) 140 total=total+1; if r1==r2 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 141 gw("T3 never-brick (#26): the decode+execute pipeline is bounded + deterministic, zero hardware-state writes\n" as *u8) 142 143 // ---- T4: liar-kill -- corrupt the decoder's class0 LUT -> wrong dispatch -> wrong results ---- 144 let DIk: *i64 = ctx[0] as *i64 145 DIk[6] = DIk[6] ^ 0xffff 146 var liar_wrong: i64 = 0 147 var lt: i64 = 0 148 while lt < nops { 149 let f3b: i64 = f3a[lt]; let f7b: i64 = f7a[lt] 150 if r9_exec(ctx, f3b, f7b, 1234567, 89) != nx_rv64im_alu_compute(ref_aluop(f3b,f7b), 1234567, 89) { liar_wrong = liar_wrong + 1 } 151 lt = lt + 1 152 } 153 total=total+1; if liar_wrong > 0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 154 gw("T4 liar-kill: corrupting the decoder class LUT mis-dispatches " as *u8); gn(liar_wrong); gw("/10 ops\n" as *u8) 155 156 gw("\n=== nx_fpga_rtype_gate " as *u8); gn(pass); gw("/" as *u8); gn(total) 157 if pass == total { gw(" GREEN (an RV64I R-type instruction decodes + executes on the simulated FPGA fabric == the behavioral CPU; all 10 ops)\n" as *u8); sys_exit(0); return 0 } 158 gw(" RED\n" as *u8); sys_exit(1); return 1 159}