code wiki / _hdl_build / nx_alu_divider_r8.nx
nx_alu_divider_r8.nx source
↩ module page · 54 lines · 2416 B
1// nx_alu_divider_r8.nx -- radix-8 divider (3 quotient bits/iteration => W/3
2// subtract-stages). Bottom-up latency iteration on the divider car (don't move
3// up until S-class): radix-2 (W) -> radix-4 (W/2) -> radix-8 (W/3) -> ... toward
4// the multiplicative frontier (Goldschmidt ~log W). Same proven digit-recurrence
5// invariant, q-digit in {0..7} via 7 compare-multiples + a cascade. Reuses
6// nx_alu_divider_r4 (radix-2 + radix-4) helpers. width must be a multiple of 3.
7// license_tier: ORIGINAL
8
9import "nx_alu_divider_r4.nx"
10
11func nx_div_synth_r8(g: *NxGsim, na: i64, nb: i64, width: i64, rem_out: *i64) -> i64 {
12 let c0: i64 = div_const(g, 0)
13 let c1: i64 = div_const(g, 1)
14 let c3: i64 = div_const(g, 3) // shift by 3 (radix-8)
15 let c7: i64 = div_const(g, 7) // low-3-bit mask
16 // precompute b*1 .. b*7
17 let bmul: *i64 = sys_mmap(8 * 8) as *i64
18 var k: i64 = 1
19 while k <= 7 {
20 let ck: i64 = div_const(g, k)
21 bmul[k] = div_op2(g, NX_GATE_KIND_MUL, nb, ck)
22 k = k + 1
23 }
24 var rem: i64 = c0
25 var quo: i64 = c0
26 let stages: i64 = width / 3
27 var s: i64 = 0
28 while s < stages {
29 let shamt: i64 = width - 3 - 3 * s
30 let cs: i64 = div_const(g, shamt)
31 let shifted: i64 = div_op2(g, NX_GATE_KIND_SHL, rem, c3) // rem << 3
32 let sh: i64 = div_op2(g, NX_GATE_KIND_SHR, na, cs) // a >> shamt
33 let abits: i64 = div_op2(g, NX_GATE_KIND_AND, sh, c7) // 3 bits
34 let rem8: i64 = div_op2(g, NX_GATE_KIND_OR, shifted, abits) // (rem<<3)|bits ; < 8b
35 var qsum: i64 = c0
36 var qb: i64 = c0
37 var j: i64 = 1
38 while j <= 7 {
39 let lt: i64 = div_op2(g, NX_GATE_KIND_LTU, rem8, bmul[j]) // rem8 <u j*b
40 let ge: i64 = div_op2(g, NX_GATE_KIND_XOR, lt, c1) // ge_j = !lt
41 qsum = div_op2(g, NX_GATE_KIND_ADD, qsum, ge) // q = sum ge_j (0..7)
42 qb = div_mux(g, ge, bmul[j], qb) // cascade: largest j*b <= rem8
43 j = j + 1
44 }
45 let rem_next: i64 = div_op2(g, NX_GATE_KIND_SUB, rem8, qb) // ONE subtract per stage
46 let quo_sh: i64 = div_op2(g, NX_GATE_KIND_SHL, quo, c3)
47 let quo_next: i64 = div_op2(g, NX_GATE_KIND_OR, quo_sh, qsum)
48 rem = rem_next
49 quo = quo_next
50 s = s + 1
51 }
52 rem_out[0] = rem
53 return quo
54}