code wiki / _hdl_build / nx_alu_divider_r4.nx

nx_alu_divider_r4.nx source

↩ module page · 65 lines · 3273 B

1// nx_alu_divider_r4.nx -- the divider's QUANTITATIVE exceed: a RADIX-4 divider 2// that resolves 2 quotient bits per iteration, so W/2 subtract-stages instead of 3// the radix-2 restoring divider's W -- ~half the sequential latency depth. 4// 5// This is the QUANT half of the full exceed (the QUAL half = exhaustive 100% 6// verification, nx_alu_divider_exhaustive_test). A full S-class exceed needs 7// BOTH: radix-4 must be FASTER (fewer stages, measured) AND still 100%-correct 8// (exhaustively verified) -- faster AND more capable. 9// 10// Algorithm (radix-4 restoring, MSB-first, width even): 11// precompute b, 2b, 3b; rem=0, quo=0; for s in 0..W/2-1: 12// rem4 = (rem<<2) | next-2-bits(a) 13// q in {0,1,2,3} = count of {rem4>=b, rem4>=2b, rem4>=3b} (rem4<4b => q<=3) 14// rem = rem4 - q*b ; quo = (quo<<2) | q 15// Reuses nx_alu_divider's div_const/div_op2/div_mux gate-builders. 16// Research: radix-4 SRT/restoring division -- Parhami, Computer Arithmetic; 17// Hennessy & Patterson. [CANON] license_tier: ORIGINAL 18 19import "nx_alu_divider.nx" 20 21// Synthesize a radix-4 divider for nets na (dividend) / nb (divisor), width even. 22// rem_out[0] := remainder net; returns the quotient net. 23func nx_div_synth_r4(g: *NxGsim, na: i64, nb: i64, width: i64, rem_out: *i64) -> i64 { 24 let c0: i64 = div_const(g, 0) 25 let c1: i64 = div_const(g, 1) 26 let c2: i64 = div_const(g, 2) 27 let c3: i64 = div_const(g, 3) 28 let b1: i64 = nb 29 let b2: i64 = div_op2(g, NX_GATE_KIND_SHL, nb, c1) // 2b 30 let b3: i64 = div_op2(g, NX_GATE_KIND_ADD, b2, nb) // 3b 31 var rem: i64 = c0 32 var quo: i64 = c0 33 let stages: i64 = width / 2 34 var s: i64 = 0 35 while s < stages { 36 let shamt: i64 = width - 2 - 2 * s 37 let cs: i64 = div_const(g, shamt) 38 let shifted: i64 = div_op2(g, NX_GATE_KIND_SHL, rem, c2) // rem << 2 39 let abits_sh: i64 = div_op2(g, NX_GATE_KIND_SHR, na, cs) // a >> shamt 40 let abits: i64 = div_op2(g, NX_GATE_KIND_AND, abits_sh, c3) // & 3 (2 bits) 41 let rem4: i64 = div_op2(g, NX_GATE_KIND_OR, shifted, abits) // (rem<<2)|bits 42 // ge_k = (rem4 >= k*b) = !(rem4 < k*b) 43 let lt1: i64 = div_op2(g, NX_GATE_KIND_LTU, rem4, b1) 44 let ge1: i64 = div_op2(g, NX_GATE_KIND_XOR, lt1, c1) 45 let lt2: i64 = div_op2(g, NX_GATE_KIND_LTU, rem4, b2) 46 let ge2: i64 = div_op2(g, NX_GATE_KIND_XOR, lt2, c1) 47 let lt3: i64 = div_op2(g, NX_GATE_KIND_LTU, rem4, b3) 48 let ge3: i64 = div_op2(g, NX_GATE_KIND_XOR, lt3, c1) 49 // q*b = largest fitting multiple: ge3? 3b : (ge2? 2b : (ge1? b : 0)) 50 let m1: i64 = div_mux(g, ge1, b1, c0) 51 let m2: i64 = div_mux(g, ge2, b2, m1) 52 let qb: i64 = div_mux(g, ge3, b3, m2) 53 let rem_next: i64 = div_op2(g, NX_GATE_KIND_SUB, rem4, qb) // the ONE subtract per stage 54 // q = ge1 + ge2 + ge3 (in {0..3}); quo = (quo<<2) | q 55 let q01: i64 = div_op2(g, NX_GATE_KIND_ADD, ge1, ge2) 56 let qd: i64 = div_op2(g, NX_GATE_KIND_ADD, q01, ge3) 57 let quo_sh: i64 = div_op2(g, NX_GATE_KIND_SHL, quo, c2) 58 let quo_next: i64 = div_op2(g, NX_GATE_KIND_OR, quo_sh, qd) 59 rem = rem_next 60 quo = quo_next 61 s = s + 1 62 } 63 rem_out[0] = rem 64 return quo 65}