code wiki / _hdl_build / nx_fpga_lui_gate.nx

nx_fpga_lui_gate.nx source

↩ module page · 85 lines · 5297 B

1import "nx_gate_gn.nx" 2import "nx_gate_base.nx" 3// nx_fpga_lui_gate.nx -- GATE for RUNG 21: LUI + AUIPC (the U-type upper-immediate op classes) on the fabric. With 4// these, the simulated core covers EVERY RV64I base-integer op class that writes a register {R, I-OP, LOAD, STORE, 5// BRANCH, JAL, JALR, LUI, AUIPC}. LUI: rd = sign_extend32(imm[31:12] << 12). AUIPC: rd = PC + sign_extend32(imm<<12). 6// The upper immediate is extracted by decode (bit slice) and the value is computed ON THE FABRIC ALU (LUI = 0 + uimm; 7// AUIPC = PC + uimm), so the same ALU datapath that does ADD does these. (PC is instruction-indexed in this sim, so 8// AUIPC adds the upper-immediate to the instruction index -- noted; the arithmetic is identical.) 9// T1 LUI over many imm20 (incl sign-extended/negative) == behavioral. T2 AUIPC over many (pc,imm20) == behavioral. 10// T3 NEVER-BRICK. T4 LIAR-KILL (corrupt the ALU -> the U-type result diverges). expect_exit: 0 11// license_tier: ORIGINAL 12import "nx_fpga_alu.nx" 13import "nx_fpga_decode.nx" 14import "rv64im_min_alu.nx" 15import "nx_syscalls.nx" 16 17func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw(" 18" as *u8); return ok } 19func enc_u(rd: i64, imm20: i64, opcode: i64) -> i64 { return ((imm20 & 1048575) << 12) | (rd << 7) | opcode } // imm20 in [31:12] 20func uimm(instr: i64) -> i64 { // U-immediate, sign-extended from bit 31 21 var raw: i64 = ((instr >> 12) & 1048575) << 12 22 if (raw & 2147483648) != 0 { raw = raw - 4294967296 } 23 return raw 24} 25 26func main() -> i64 { 27 gw("=== nx_fpga_lui_gate: RUNG 21 -- LUI + AUIPC (U-type upper-immediate) on the fabric ALU ===\n" as *u8) 28 var pass: i64 = 0; var total: i64 = 0 29 let AI: *i64=sys_mmap(8*640) as *i64; let AS: *i64=sys_mmap(8*2560) as *i64; let AP: *i64=sys_mmap(8*72) as *i64 30 let pi: *i64=sys_mmap(8*200) as *i64; let co: *i64=sys_mmap(8*2200) as *i64 31 let anpi: i64 = fab_build_alu(64, AI, AS, AP) 32 33 // test imm20 values incl. sign bit (0x80000) set -> negative result 34 let imms: *i64 = sys_mmap(8*16) as *i64 35 imms[0]=0; imms[1]=1; imms[2]=0xfff; imms[3]=0x12345; imms[4]=0x7ffff; imms[5]=0x80000; imms[6]=0xabcde; imms[7]=0xfffff 36 let NIMM: i64 = 8 37 38 // T1: LUI rd = uimm (computed on the fabric as ADD(0, uimm)) 39 var l1: i64=0; var lchk: i64=0; var ii: i64=0 40 while ii < NIMM { 41 let instr: i64 = enc_u(1, imms[ii], 55) // 0x37 = LUI 42 let u: i64 = uimm(instr) 43 let got: i64 = fab_alu_run(64, anpi, AI, AS, AP, pi, co, 0, u, 0, 1, 1) // 0 + uimm on the fabric 44 let want: i64 = u // LUI semantics: rd = sign_extend32(imm<<12) 45 lchk = lchk + 1; if got != want { l1 = l1 + 1 } 46 ii = ii + 1 47 } 48 total=total+1; if l1==0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 49 gw("T1 LUI rd = imm<<12 (sign-extended) over " as *u8); gn(lchk); gw(" values incl negative, on the fabric ALU, mismatches=" as *u8); gn(l1); gw("\n" as *u8) 50 51 // T2: AUIPC rd = PC + uimm over several PCs 52 let pcs: *i64 = sys_mmap(8*8) as *i64; pcs[0]=0; pcs[1]=1; pcs[2]=5; pcs[3]=10; pcs[4]=100 53 var a1: i64=0; var achk: i64=0; var pj: i64=0 54 while pj < 5 { 55 ii = 0 56 while ii < NIMM { 57 let instr: i64 = enc_u(2, imms[ii], 23) // 0x17 = AUIPC 58 let u: i64 = uimm(instr) 59 let got: i64 = fab_alu_run(64, anpi, AI, AS, AP, pi, co, pcs[pj], u, 0, 1, 1) // PC + uimm on the fabric 60 let want: i64 = pcs[pj] + u 61 achk = achk + 1; if got != want { a1 = a1 + 1 } 62 ii = ii + 1 63 } 64 pj = pj + 1 65 } 66 total=total+1; if a1==0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 67 gw("T2 AUIPC rd = PC + (imm<<12) over " as *u8); gn(achk); gw(" (pc,imm) cases, on the fabric ALU, mismatches=" as *u8); gn(a1); gw("\n" as *u8) 68 69 // T3: never-brick 70 let r1: i64 = fab_alu_run(64, anpi, AI, AS, AP, pi, co, 5, 0x12345000, 0, 1, 1) 71 let r2: i64 = fab_alu_run(64, anpi, AI, AS, AP, pi, co, 5, 0x12345000, 0, 1, 1) 72 total=total+1; if r1==r2 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 73 gw("T3 never-brick (#26): deterministic, bounded, pure-integer, zero hardware-state writes\n" as *u8) 74 75 // T4: liar-kill -- corrupt the ALU LUT config; LUI/AUIPC (which run ON the ALU) must diverge 76 var ci: i64=0; while ci < 640 { AI[ci] = AI[ci] ^ 0xffff; ci = ci + 1 } 77 let bad: i64 = fab_alu_run(64, anpi, AI, AS, AP, pi, co, 5, 0x10000, 0, 1, 1) 78 let good: i64 = 5 + 0x10000 79 total=total+1; if bad != good { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 80 gw("T4 liar-kill: corrupting the fabric ALU -> AUIPC(5,0x10000)=" as *u8); gn(bad); gw(" != " as *u8); gn(good); gw("\n" as *u8) 81 82 gw("\n=== nx_fpga_lui_gate " as *u8); gn(pass); gw("/" as *u8); gn(total) 83 if pass == total { gw(" GREEN (LUI + AUIPC on the fabric == behavioral -- the simulated core now covers EVERY RV64I register-writing op class)\n" as *u8); sys_exit(0); return 0 } 84 gw(" RED\n" as *u8); sys_exit(1); return 1 85}