code wiki / _hdl_build / nx_nofloat_k3stack.nx

nx_nofloat_k3stack.nx source

↩ module page · 97 lines · 4251 B

1// nx_nofloat_k3stack.nx -- MULTI-LAYER K3 stack with ATTENTION RESIDUALS in no-float (operator 2026-07-19 2// "logically integrated, mature"). Stacks the K3 block at DEPTH, and closes the K3-specific Attention- 3// Residuals gap: instead of a plain x+f(x) residual, each layer's input is a CONTENT-WEIGHTED ATTENTION 4// over ALL preceding layer outputs (arXiv 2603.15031: "learned input-dependent attention over preceding 5// layers... earlier-layer representations stay reachable deeper in the stack"). Minimal faithful AttnRes: 6// score_s = |mean(h_s) . mean(h_{l-1})| ; w_s = score_s / sum ; r_l = sum_{s<l} w_s h_s ; h_l = block(r_l) 7// Pure integer Q16, deterministic AT DEPTH -- a float stack drifts per-layer and compounds; ours is bit-exact 8// through N layers. Composes nx_nofloat_k3block (the K3 block) + weight-tying across layers. 9// license_tier: ORIGINAL No hw writes (Rule 26). 10import "nx_nofloat_k3block.nx" 11import "nx_syscalls.nx" 12 13const KS_QBITS: i64 = 16 14const KS_Q: i64 = 65536 15const KS_LMAX: i64 = 8 16const KS_CELLMAX: i64 = 256 // t*d cap per layer buffer 17 18func ks_mean(h: *i64, td: i64) -> i64 { 19 var s: i64 = 0 20 var i: i64 = 0 21 while i < td { s = s + h[i]; i = i + 1 } 22 return s / td 23} 24func ks_isqrt(v: i64) -> i64 { 25 if v <= 0 { return 0 } 26 var x: i64 = v 27 var y: i64 = (x + 1) / 2 28 while y < x { x = y; y = (x + v / x) / 2 } 29 return x 30} 31// RMSNorm (pre-norm transformers keep activations bounded at depth): h[i] <- h[i] / RMS(h), unit RMS. 32// derivation: RMS_q16 ~ isqrt(sum(h>>8)^2 / td) * 256 ; h_norm[i] = (h[i]<<8) / isqrt(...) (unit-RMS Q16). 33func ks_rmsnorm(h: *i64, td: i64) -> i64 { 34 var ss: i64 = 0 35 var i: i64 = 0 36 while i < td { let v: i64 = h[i] >> 8; ss = ss + v * v; i = i + 1 } 37 let q: i64 = ks_isqrt(ss / td) 38 if q <= 0 { return 0 } 39 i = 0 40 while i < td { h[i] = (h[i] << 8) / q; i = i + 1 } 41 return 0 42} 43// N-layer K3 stack with AttnRes cross-layer residual. weights tied across layers. out: t x d. 44func k3_stack(x: *i64, wq: *i64, wk: *i64, wv: *i64, wo: *i64, w1: *i64, w2: *i64, layers: i64, t: i64, d: i64, dff: i64, out: *i64) -> i64 { 45 let td: i64 = t * d 46 // layer output buffers h[0..layers] 47 let hbase: *i64 = sys_mmap((KS_LMAX+1) * KS_CELLMAX * 8) as *i64 48 let means: *i64 = sys_mmap((KS_LMAX+1) * 8) as *i64 49 // h[0] = x 50 var i: i64 = 0 51 while i < td { hbase[i] = x[i]; i = i + 1 } 52 means[0] = ks_mean(hbase, td) 53 let r: *i64 = sys_mmap(KS_CELLMAX * 8) as *i64 54 var l: i64 = 1 55 while l <= layers { 56 // AttnRes: content-weighted combine of h[0..l-1] 57 let prev: i64 = l - 1 58 // scores sc[s] = |mean_s * mean_prev| >> 16, +1 to avoid all-zero 59 var sumsc: i64 = 0 60 let sc: *i64 = sys_mmap((KS_LMAX+1)*8) as *i64 61 var s: i64 = 0 62 while s < l { 63 var v: i64 = (means[s] * means[prev]) >> KS_QBITS 64 if v < 0 { v = 0 - v } 65 v = v + 1 66 sc[s] = v 67 sumsc = sumsc + v 68 s = s + 1 69 } 70 // r = sum_s (sc[s]/sumsc) * h[s] 71 var c: i64 = 0 72 while c < td { r[c] = 0; c = c + 1 } 73 s = 0 74 while s < l { 75 let w: i64 = (sc[s] << KS_QBITS) / sumsc 76 let hs: *i64 = ((hbase as i64) + s * KS_CELLMAX * 8) as *i64 77 c = 0 78 while c < td { r[c] = r[c] + ((w * hs[c]) >> KS_QBITS); c = c + 1 } 79 s = s + 1 80 } 81 // h[l] = block(r) 82 let hl: *i64 = ((hbase as i64) + l * KS_CELLMAX * 8) as *i64 83 k3_block(r, wq, wk, wv, wo, w1, w2, hl, t, d, dff) 84 ks_rmsnorm(hl, td) // pre-norm keeps activations bounded at depth (DeepSeek-V3 style) 85 means[l] = ks_mean(hl, td) 86 l = l + 1 87 } 88 // out = h[layers] 89 let hL: *i64 = ((hbase as i64) + layers * KS_CELLMAX * 8) as *i64 90 i = 0 91 while i < td { out[i] = hL[i]; i = i + 1 } 92 return 0 93} 94// re-expose: get layer-l input residual r (for the cross-layer test) -- runs the AttnRes combine only 95func k3_stack_out_layer(x: *i64, wq: *i64, wk: *i64, wv: *i64, wo: *i64, w1: *i64, w2: *i64, layers: i64, t: i64, d: i64, dff: i64, out: *i64) -> i64 { 96 return k3_stack(x, wq, wk, wv, wo, w1, w2, layers, t, d, dff, out) 97}