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}