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}