code wiki / _hdl_build / nx_newton_struct.nx

nx_newton_struct.nx source

↩ module page · 71 lines · 3388 B

1// nx_newton_struct.nx -- the Newton-Raphson reciprocal-divider STRUCTURE (the 2// operator dependency chain of nx_alu_divider_newton.nx) as an NxGsim network, 3// parameterized by width W, iteration count, correction stages, and the 4// MULTIPLIER MODEL (deep limb-schoolbook vs shallow single-cell Wallace). 5// 6// Extracted from nx_latency_metric_test.nx so the latency race AND the 7// hardware-adaptive divider picker (nx_div_pick.nx) build the SAME structure from 8// ONE source (DRY). It is a LATENCY/topology skeleton -- the functional 1:1 9// Newton gate-net is nx_recip_synth.nx; the scalar arithmetic proof is 10// nx_alu_divider_newton.nx. license_tier: ORIGINAL 11 12import "nx_alu_divider.nx" // div_const / div_op2 / div_mux + NxGsim + NX_GATE_KIND_* 13import "nx_mul_wide.nx" // nx_mul_wide_synth (deep 64x64->128 multiplier) 14 15// One product on the Newton chain. use_wide selects the deep (limb-schoolbook) 16// vs shallow (single MUL cell) multiplier model -- the two sides of the 17// honest-metric trap (a multiply is NOT free). 18func nx_newton_mulprod(g: *NxGsim, a: i64, b: i64, use_wide: i64, hio: *i64) -> i64 { 19 if use_wide != 0 { return nx_mul_wide_synth(g, a, b, hio) } 20 return div_op2(g, NX_GATE_KIND_MUL, a, b) 21} 22 23// Emit the Newton reciprocal-divider operator dependency chain for nets na (N) / 24// nb (D) at width W. Returns the quotient-structure net. 25func nx_newton_struct(g: *NxGsim, na: i64, nb: i64, W: i64, iters: i64, kcorr: i64, use_wide: i64) -> i64 { 26 let hio: *i64 = sys_mmap(8) as *i64; hio[0] = 0 27 let c0: i64 = div_const(g, 0) 28 let c1: i64 = div_const(g, 1) 29 let F: i64 = div_const(g, 1 << W) 30 let two_ff: i64 = div_const(g, 2) 31 let twoW: i64 = div_const(g, 2 * W) 32 let shc: i64 = div_const(g, W + 1) 33 34 let p_sh: i64 = div_op2(g, NX_GATE_KIND_SHR, nb, c1) 35 let p: i64 = div_op2(g, NX_GATE_KIND_LTU, p_sh, F) 36 let s: i64 = div_op2(g, NX_GATE_KIND_SUB, F, p) 37 let dn: i64 = div_op2(g, NX_GATE_KIND_SHL, nb, s) 38 39 let t48: i64 = div_op2(g, NX_GATE_KIND_MUL, div_const(g, 48), F) 40 let t32: i64 = div_op2(g, NX_GATE_KIND_MUL, div_const(g, 32), dn) 41 let num: i64 = div_op2(g, NX_GATE_KIND_SUB, t48, t32) 42 let r3855: i64 = div_op2(g, NX_GATE_KIND_MUL, num, div_const(g, 3855)) 43 var x: i64 = div_op2(g, NX_GATE_KIND_SHR, r3855, div_const(g, 16)) 44 45 var it: i64 = 0 46 while it < iters { 47 let dx: i64 = nx_newton_mulprod(g, dn, x, use_wide, hio) 48 let t: i64 = div_op2(g, NX_GATE_KIND_SUB, two_ff, dx) 49 let xt: i64 = nx_newton_mulprod(g, x, t, use_wide, hio) 50 x = div_op2(g, NX_GATE_KIND_SHR, xt, twoW) 51 it = it + 1 52 } 53 54 let nx_lo: i64 = nx_newton_mulprod(g, na, x, use_wide, hio) 55 let shamt: i64 = div_op2(g, NX_GATE_KIND_ADD, shc, p) 56 var q: i64 = div_op2(g, NX_GATE_KIND_SHR, nx_lo, shamt) 57 58 var kk: i64 = 0 59 while kk < kcorr { 60 let qp1: i64 = div_op2(g, NX_GATE_KIND_ADD, q, c1) 61 let qp1D: i64 = nx_newton_mulprod(g, qp1, nb, use_wide, hio) 62 let le: i64 = div_op2(g, NX_GATE_KIND_LTU, qp1D, na) 63 let qD: i64 = nx_newton_mulprod(g, q, nb, use_wide, hio) 64 let hi: i64 = div_op2(g, NX_GATE_KIND_LTU, na, qD) 65 let qup: i64 = div_op2(g, NX_GATE_KIND_ADD, q, le) 66 let qdn: i64 = div_op2(g, NX_GATE_KIND_SUB, q, hi) 67 q = div_mux(g, le, qup, div_mux(g, hi, qdn, q)) 68 kk = kk + 1 69 } 70 return q 71}