code wiki / _hdl_build / nx_fpga_div_gate.nx

nx_fpga_div_gate.nx source

↩ module page · 85 lines · 5213 B

1import "nx_gate_gn.nx" 2import "nx_gate_base.nx" 3// nx_fpga_div_gate.nx -- GATE for RUNG 25: DIVU + REMU (the M-extension division) on the fabric via RESTORING DIVISION. 4// Classic sequential divider: process the dividend MSB->LSB; each step shift the next bit into the partial remainder r, 5// COMPARE r to the divisor b on the fabric (SLTU via nx_fpga_cmp), and if r>=b SUBTRACT b on the fabric ALU 6// (nx_fpga_alu) and set the quotient bit. The arithmetic (compare + subtract) runs on the proven fabric datapath. 7// Verified == the behavioral nx_rv64im_alu_compute(DIVU) (quotient) AND (REMU) (remainder). With MUL (R24) this 8// completes the rv64i**M** integer set in sim. 9// T1 DIVU quotient AND REMU remainder over representative (a,b) pairs == behavioral. T2 headline 100/7 = 14 rem 2. 10// T3 NEVER-BRICK. T4 LIAR-KILL (corrupt the fabric ALU -> the subtract diverges -> wrong quotient). 11// (Dividend kept <=255 -> 8 iterations -> light; b>=1, division-by-zero is the oracle's special case, not tested here.) 12// expect_exit: 0 license_tier: ORIGINAL 13import "nx_fpga_alu.nx" 14import "nx_fpga_cmp.nx" 15import "rv64im_min_alu.nx" 16import "nx_syscalls.nx" 17 18func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw(" 19" as *u8); return ok } 20 21func main() -> i64 { 22 gw("=== nx_fpga_div_gate: RUNG 25 -- DIVU/REMU (M-extension) via fabric RESTORING DIVISION (cmp + subtract) ===\n" as *u8) 23 var pass: i64 = 0; var total: i64 = 0 24 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 25 let CI: *i64=sys_mmap(8*280) as *i64; let CS: *i64=sys_mmap(8*1120) as *i64; let CP: *i64=sys_mmap(8*72) as *i64 26 let pi: *i64=sys_mmap(8*200) as *i64; let co: *i64=sys_mmap(8*2200) as *i64 27 let anpi: i64 = fab_build_alu(64, AI, AS, AP) 28 let cnpi: i64 = fab_build_cmp(64, CI, CS, CP) 29 30 let ta: *i64=sys_mmap(8*16) as *i64; let tb: *i64=sys_mmap(8*16) as *i64 31 ta[0]=100; tb[0]=7 32 ta[1]=255; tb[1]=16 33 ta[2]=0; tb[2]=5 34 ta[3]=255; tb[3]=255 35 ta[4]=200; tb[4]=1 36 ta[5]=13; tb[5]=4 37 ta[6]=255; tb[6]=2 38 ta[7]=100; tb[7]=100 39 ta[8]=7; tb[8]=13 40 ta[9]=250; tb[9]=25 41 let NP: i64 = 10 42 43 var mism: i64=0; var p: i64=0 44 while p < NP { 45 let a: i64=ta[p]; let b: i64=tb[p] 46 var q: i64=0; var r: i64=0; var i: i64=7 47 while i >= 0 { 48 r = (r << 1) | ((a >> i) & 1) // bring down the next dividend bit 49 let lt: i64 = fab_cmp_run(64, cnpi, CI, CS, CP, pi, co, r, b, 1) // r < b ? (unsigned) on the fabric 50 if lt == 0 { // r >= b 51 r = fab_alu_run(64, anpi, AI, AS, AP, pi, co, r, b, 1, 1, 1) // r = r - b on the fabric ALU 52 q = q | (1 << i) // set quotient bit i 53 } 54 i = i - 1 55 } 56 let wantq: i64 = nx_rv64im_alu_compute(NX_RV64IM_ALU_DIVU, a, b) 57 let wantr: i64 = nx_rv64im_alu_compute(NX_RV64IM_ALU_REMU, a, b) 58 if q != wantq { mism = mism + 1 } 59 if r != wantr { mism = mism + 1 } 60 p = p + 1 61 } 62 total=total+1; if mism==0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 63 gw("T1 DIVU quotient + REMU remainder via fabric restoring-division over " as *u8); gn(NP); gw(" pairs == behavioral, mismatches=" as *u8); gn(mism); gw("\n" as *u8) 64 65 // T2: headline 100 / 7 66 var q2: i64=0; var r2: i64=0; var j: i64=7 67 while j >= 0 { r2=(r2<<1)|((100>>j)&1); let lt: i64=fab_cmp_run(64,cnpi,CI,CS,CP,pi,co,r2,7,1); if lt==0 { r2=fab_alu_run(64,anpi,AI,AS,AP,pi,co,r2,7,1,1,1); q2=q2|(1<<j) } j=j-1 } 68 total=total+1; if q2==14 { if r2==2 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } } else { gw(" [FAIL] " as *u8) } 69 gw("T2 100 / 7 on the fabric = quotient " as *u8); gn(q2); gw(" remainder " as *u8); gn(r2); gw(" (=14 rem 2)\n" as *u8) 70 71 // T3: never-brick 72 let c1: i64=fab_cmp_run(64,cnpi,CI,CS,CP,pi,co,9,7,1); let c2: i64=fab_cmp_run(64,cnpi,CI,CS,CP,pi,co,9,7,1) 73 total=total+1; if c1==c2 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 74 gw("T3 never-brick (#26): deterministic, bounded restoring loop, pure-integer, zero hardware-state writes\n" as *u8) 75 76 // T4: liar-kill -- corrupt the fabric ALU; the divider's subtract diverges 77 var ci: i64=0; while ci < 640 { AI[ci] = AI[ci] ^ 0xffff; ci = ci + 1 } 78 let bad: i64=fab_alu_run(64,anpi,AI,AS,AP,pi,co,11,7,1,1,1) 79 total=total+1; if bad != 4 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 80 gw("T4 liar-kill: corrupting the fabric ALU -> a divider subtract(11,7)=" as *u8); gn(bad); gw(" != 4\n" as *u8) 81 82 gw("\n=== nx_fpga_div_gate " as *u8); gn(pass); gw("/" as *u8); gn(total) 83 if pass == total { gw(" GREEN (DIVU/REMU run on the fabric via restoring division (compare + subtract) == behavioral -- with MUL, the rv64iM integer set is complete in sim)\n" as *u8); sys_exit(0); return 0 } 84 gw(" RED\n" as *u8); sys_exit(1); return 1 85}