code wiki / _hdl_build / nx_mul_wide.nx
nx_mul_wide.nx source
↩ module page · 71 lines · 4583 B
1// nx_mul_wide.nx -- 64x64 -> 128 unsigned MULTIPLIER as a gate-network (fixes the
2// mulh SIL-1 stub; the high-cascade core fundamental that feeds the divider
3// frontier + all crypto + the future LLM -- nx_dimret => INVEST).
4//
5// The sim's MUL cell gives only the LOW 64 bits (it wraps). The full 128-bit
6// product is assembled from 32-bit limbs (each 32x32 partial product < 2^64, so
7// it fits the i64 cell exactly), schoolbook with column carries:
8// a = ah:al, b = bh:bl (32-bit halves; the &MASK32 also undoes arithmetic >>)
9// ll=al*bl lh=al*bh hl=ah*bl hh=ah*bh
10// c0 = ll_lo
11// c1 = ll_hi + lh_lo + hl_lo (carry1 = c1>>32)
12// c2 = carry1 + lh_hi + hl_hi + hh_lo (carry2 = c2>>32)
13// c3 = carry2 + hh_hi
14// lo = c0 | (c1<<32) ; hi = (c2&MASK32) | ((c3&MASK32)<<32)
15// Output: returns the LO net; writes the HI net to hi_out[0]. Reuses
16// nx_alu_divider's div_const/div_op2 cell-builders (DRY). license_tier: ORIGINAL
17
18import "nx_alu_divider.nx"
19import "nx_cell_sink.nx"
20
21const MW_MASK32: i64 = 4294967295 // 2^32 - 1
22
23// Canonical sink-based 64x64->128 multiplier: emits the SAME schoolbook gate
24// graph to either an in-memory NxGsim (verifier) or the .nxgate text sink
25// (shipping) -- one source. Returns the LO net; writes the HI net to hi_out[0].
26func nx_mul_wide_sink(k: *NxCellSink, na: i64, nb: i64, hi_out: *i64) -> i64 {
27 let c32: i64 = nx_sink_const(k, 64, 32)
28 let m: i64 = nx_sink_const(k, 64, MW_MASK32)
29
30 let al: i64 = nx_sink_cell(k, NX_GATE_KIND_AND, 64, na, m, 0 - 1, 2)
31 let ah: i64 = nx_sink_cell(k, NX_GATE_KIND_AND, 64, nx_sink_cell(k, NX_GATE_KIND_SHR, 64, na, c32, 0 - 1, 2), m, 0 - 1, 2)
32 let bl: i64 = nx_sink_cell(k, NX_GATE_KIND_AND, 64, nb, m, 0 - 1, 2)
33 let bh: i64 = nx_sink_cell(k, NX_GATE_KIND_AND, 64, nx_sink_cell(k, NX_GATE_KIND_SHR, 64, nb, c32, 0 - 1, 2), m, 0 - 1, 2)
34
35 let ll: i64 = nx_sink_cell(k, NX_GATE_KIND_MUL, 64, al, bl, 0 - 1, 2)
36 let lh: i64 = nx_sink_cell(k, NX_GATE_KIND_MUL, 64, al, bh, 0 - 1, 2)
37 let hl: i64 = nx_sink_cell(k, NX_GATE_KIND_MUL, 64, ah, bl, 0 - 1, 2)
38 let hh: i64 = nx_sink_cell(k, NX_GATE_KIND_MUL, 64, ah, bh, 0 - 1, 2)
39
40 let ll_lo: i64 = nx_sink_cell(k, NX_GATE_KIND_AND, 64, ll, m, 0 - 1, 2)
41 let ll_hi: i64 = nx_sink_cell(k, NX_GATE_KIND_AND, 64, nx_sink_cell(k, NX_GATE_KIND_SHR, 64, ll, c32, 0 - 1, 2), m, 0 - 1, 2)
42 let lh_lo: i64 = nx_sink_cell(k, NX_GATE_KIND_AND, 64, lh, m, 0 - 1, 2)
43 let lh_hi: i64 = nx_sink_cell(k, NX_GATE_KIND_AND, 64, nx_sink_cell(k, NX_GATE_KIND_SHR, 64, lh, c32, 0 - 1, 2), m, 0 - 1, 2)
44 let hl_lo: i64 = nx_sink_cell(k, NX_GATE_KIND_AND, 64, hl, m, 0 - 1, 2)
45 let hl_hi: i64 = nx_sink_cell(k, NX_GATE_KIND_AND, 64, nx_sink_cell(k, NX_GATE_KIND_SHR, 64, hl, c32, 0 - 1, 2), m, 0 - 1, 2)
46 let hh_lo: i64 = nx_sink_cell(k, NX_GATE_KIND_AND, 64, hh, m, 0 - 1, 2)
47 let hh_hi: i64 = nx_sink_cell(k, NX_GATE_KIND_AND, 64, nx_sink_cell(k, NX_GATE_KIND_SHR, 64, hh, c32, 0 - 1, 2), m, 0 - 1, 2)
48
49 let c1sum: i64 = nx_sink_cell(k, NX_GATE_KIND_ADD, 64, nx_sink_cell(k, NX_GATE_KIND_ADD, 64, ll_hi, lh_lo, 0 - 1, 2), hl_lo, 0 - 1, 2)
50 let c1: i64 = nx_sink_cell(k, NX_GATE_KIND_AND, 64, c1sum, m, 0 - 1, 2)
51 let carry1: i64 = nx_sink_cell(k, NX_GATE_KIND_AND, 64, nx_sink_cell(k, NX_GATE_KIND_SHR, 64, c1sum, c32, 0 - 1, 2), m, 0 - 1, 2)
52 let c2a: i64 = nx_sink_cell(k, NX_GATE_KIND_ADD, 64, carry1, lh_hi, 0 - 1, 2)
53 let c2b: i64 = nx_sink_cell(k, NX_GATE_KIND_ADD, 64, c2a, hl_hi, 0 - 1, 2)
54 let c2sum: i64 = nx_sink_cell(k, NX_GATE_KIND_ADD, 64, c2b, hh_lo, 0 - 1, 2)
55 let c2: i64 = nx_sink_cell(k, NX_GATE_KIND_AND, 64, c2sum, m, 0 - 1, 2)
56 let carry2: i64 = nx_sink_cell(k, NX_GATE_KIND_AND, 64, nx_sink_cell(k, NX_GATE_KIND_SHR, 64, c2sum, c32, 0 - 1, 2), m, 0 - 1, 2)
57 let c3: i64 = nx_sink_cell(k, NX_GATE_KIND_AND, 64, nx_sink_cell(k, NX_GATE_KIND_ADD, 64, carry2, hh_hi, 0 - 1, 2), m, 0 - 1, 2)
58
59 let lo: i64 = nx_sink_cell(k, NX_GATE_KIND_OR, 64, ll_lo, nx_sink_cell(k, NX_GATE_KIND_SHL, 64, c1, c32, 0 - 1, 2), 0 - 1, 2)
60 let hi: i64 = nx_sink_cell(k, NX_GATE_KIND_OR, 64, c2, nx_sink_cell(k, NX_GATE_KIND_SHL, 64, c3, c32, 0 - 1, 2), 0 - 1, 2)
61 hi_out[0] = hi
62 return lo
63}
64
65// Legacy NxGsim entry -- thin MEM-sink wrapper over nx_mul_wide_sink (ONE
66// multiplier algorithm; byte-identical netlist, all multiplier gates stay green).
67func nx_mul_wide_synth(g: *NxGsim, na: i64, nb: i64, hi_out: *i64) -> i64 {
68 let k: *NxCellSink = sys_mmap(64) as *NxCellSink
69 nx_sink_init_mem(k, g)
70 return nx_mul_wide_sink(k, na, nb, hi_out)
71}