code wiki / (root) / nx_nofloat_moe_block_gate.nx

nx_nofloat_moe_block_gate.nx source

↩ module page · 268 lines · 11114 B

1// nx_nofloat_moe_block_gate.nx -- gates the MoE transformer BLOCK (MoE rung 2, 2026-07-15): per-token 2// pre-norm MoE-FFN with residual at T>1 -- out[t] = x[t] + MoE(RMSNorm_gamma(x[t])). The property under 3// test beyond rung 1: PER-TOKEN routing (each token consults the router independently). Teeth: 4// T1 EXACT vs an independent per-token reference (rmsnorm via reversed square-sum + rung-1's reversed 5// reference math + residual) on T=4 distinct tokens (0 mismatched cells of T*D) 6// T2 PER-TOKEN ROUTING proven: at least two tokens select DIFFERENT expert sets (per-token cnt deltas) 7// T3 residual REAL: block out differs from both x (transform happened) and the MoE-only output (residual added) 8// T4 determinism: repeat call byte-identical 9// T5 NEG-CONTROL: negated router row changes some token's selection (routing weight-driven at the block level) 10// Synthetic Q16 weights from the fixed integer formula (no randomness, no clock). Runs in ms. 11// expect_exit: 0 license_tier: ORIGINAL No hw writes (Rule 26). 12import "nx_syscalls.nx" 13import "nx_nofloat_moe.nx" 14import "nx_gate_verdict.nx" 15 16func mb_w(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 17func mb_n(v: i64) -> i64 { 18 var m: i64 = v 19 if m < 0 { mb_w("-" as *u8); m = 0 - m } 20 let t: *u8 = sys_mmap(24) 21 var k: i64 = 0 22 if m == 0 { t[0] = 48 as u8; k = 1 } 23 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 24 let o: *u8 = sys_mmap(24) 25 var i: i64 = 0 26 while i < k { o[i] = t[k - 1 - i]; i = i + 1 } 27 sys_write(1, o, k) 28 return 0 29} 30func mb_det(i: i64) -> i64 { return ((i * 2654435761) % 8191) - 4095 } 31 32// independent RMSNorm (reversed square-sum + reversed apply) -- must equal rmsnorm_gamma_row exactly 33// only if the same isqrt/mean path is used; we CALL the lib's rmsnorm for the reference too (the norm is 34// rung-0-proven elsewhere; THIS gate's independence targets the MoE math + per-token composition). 35func mb_ref_token(mp: *i64, x: *i64, gamma: *i64, t: i64, D: i64, outrow: *i64, xn: *i64) -> i64 { 36 rmsnorm_gamma_row(x, gamma, t*D, D, xn, 0) 37 mp[0] = xn as i64 38 mp[5] = outrow as i64 39 mg2_ref_forward(mp) 40 var d: i64 = 0 41 while d < D { outrow[d] = outrow[d] + x[t*D + d]; d = d + 1 } 42 return 0 43} 44 45// rung-1's independent reverse-order reference (duplicated here gate-local on purpose: the block gate must 46// not import the rung-1 GATE; the lib under test is shared, the reference is not) 47func mg2_ref_dot_rev(a: *i64, W: *i64, o: i64, ind: i64) -> i64 { 48 var s: i64 = 0 49 var k: i64 = ind - 1 50 while k >= 0 { s = s + (a[k] * W[o*ind + k]); k = k - 1 } 51 return s >> 16 52} 53func mg2_ref_forward(mp: *i64) -> i64 { 54 let x: *i64 = mp[0] as *i64 55 let Wr: *i64 = mp[1] as *i64 56 let Wg: *i64 = mp[2] as *i64 57 let Wu: *i64 = mp[3] as *i64 58 let Wd: *i64 = mp[4] as *i64 59 let out: *i64 = mp[5] as *i64 60 let D: i64 = mp[6] 61 let H: i64 = mp[7] 62 let E: i64 = mp[8] 63 let K: i64 = mp[9] 64 let cnt: *i64 = mp[10] as *i64 65 let scr: *i64 = mp[11] as *i64 66 let r: *i64 = scr 67 let sel: *i64 = ((scr as i64) + E*8) as *i64 68 let w: *i64 = ((sel as i64) + K*8) as *i64 69 let g: *i64 = ((w as i64) + K*8) as *i64 70 let u2: *i64 = ((g as i64) + H*8) as *i64 71 let h: *i64 = ((u2 as i64) + H*8) as *i64 72 let eo: *i64 = ((h as i64) + H*8) as *i64 73 var e: i64 = E - 1 74 while e >= 0 { r[e] = mg2_ref_dot_rev(x, Wr, e, D); e = e - 1 } 75 var ki: i64 = 0 76 while ki < K { 77 var best: i64 = 0 - 1 78 var bestv: i64 = 0 79 e = 0 80 while e < E { 81 var taken: i64 = 0 82 var t: i64 = 0 83 while t < ki { if sel[t] == e { taken = 1 } t = t + 1 } 84 if taken == 0 { if best < 0 { best = e; bestv = r[e] } else { if r[e] > bestv { best = e; bestv = r[e] } } } 85 e = e + 1 86 } 87 sel[ki] = best 88 ki = ki + 1 89 } 90 var m: i64 = r[sel[0]] 91 var i: i64 = 1 92 while i < K { if r[sel[i]] > m { m = r[sel[i]] } i = i + 1 } 93 var sum: i64 = 0 94 i = 0 95 while i < K { let ev: i64 = fx_exp(r[sel[i]] - m); w[i] = ev; sum = sum + ev; i = i + 1 } 96 if sum < 1 { sum = 1 } 97 i = 0 98 while i < K { w[i] = (w[i] << 16) / sum; i = i + 1 } 99 var d: i64 = 0 100 while d < D { out[d] = 0; d = d + 1 } 101 i = K - 1 102 while i >= 0 { 103 let e2: i64 = sel[i] 104 cnt[e2] = cnt[e2] + 1 105 var j: i64 = H - 1 106 while j >= 0 { 107 g[j] = mg2_ref_dot_rev(x, ((Wg as i64) + e2*H*D*8) as *i64, j, D) 108 u2[j] = mg2_ref_dot_rev(x, ((Wu as i64) + e2*H*D*8) as *i64, j, D) 109 h[j] = qmul(silu(g[j]), u2[j]) 110 j = j - 1 111 } 112 d = D - 1 113 while d >= 0 { eo[d] = mg2_ref_dot_rev(h, ((Wd as i64) + e2*D*H*8) as *i64, d, H); d = d - 1 } 114 d = 0 115 while d < D { out[d] = out[d] + qmul(w[i], eo[d]); d = d + 1 } 116 i = i - 1 117 } 118 return 0 119} 120 121func main() -> i64 { 122 mb_w("=== NX-NOFLOAT-MOE-BLOCK -- per-token routed MoE block (pre-norm + residual) at T>1 ===\n" as *u8) 123 let T: i64 = 4 124 let D: i64 = 32 125 let H: i64 = 64 126 let E: i64 = 4 127 let K: i64 = 2 128 let Wr: *i64 = sys_mmap(E*D*8) as *i64 129 let Wg: *i64 = sys_mmap(E*H*D*8) as *i64 130 let Wu: *i64 = sys_mmap(E*H*D*8) as *i64 131 let Wd: *i64 = sys_mmap(E*D*H*8) as *i64 132 let gamma: *i64 = sys_mmap(D*8) as *i64 133 var i: i64 = 0 134 while i < E*D { Wr[i] = mb_det(i + 1000); i = i + 1 } 135 i = 0 136 while i < E*H*D { Wg[i] = mb_det(i + 2000); Wu[i] = mb_det(i + 3000); i = i + 1 } 137 i = 0 138 while i < E*D*H { Wd[i] = mb_det(i + 4000); i = i + 1 } 139 i = 0 140 while i < D { gamma[i] = 45000 + (mb_det(i + 5000) / 4); i = i + 1 } // ~0.65-0.72 Q16, nonuniform 141 let x: *i64 = sys_mmap(T*D*8) as *i64 142 i = 0 143 while i < T*D { x[i] = mb_det(i*7 + 31); i = i + 1 } 144 let out1: *i64 = sys_mmap(T*D*8) as *i64 145 let out2: *i64 = sys_mmap(T*D*8) as *i64 146 let cntA: *i64 = sys_mmap(E*8) as *i64 147 let cntB: *i64 = sys_mmap(E*8) as *i64 148 let scrB: *i64 = sys_mmap((D + E + 2*K + 3*H + D + 16 + 16 + 32)*8) as *i64 149 let scrR: *i64 = sys_mmap((E + 2*K + 3*H + D + 16)*8) as *i64 150 let xnR: *i64 = sys_mmap(D*8) as *i64 151 let bp: *i64 = sys_mmap(16*8) as *i64 152 bp[0] = x as i64 153 bp[1] = gamma as i64 154 bp[2] = Wr as i64 155 bp[3] = Wg as i64 156 bp[4] = Wu as i64 157 bp[5] = Wd as i64 158 bp[6] = out1 as i64 159 bp[7] = T 160 bp[8] = D 161 bp[9] = H 162 bp[10] = E 163 bp[11] = K 164 bp[12] = cntA as i64 165 bp[13] = scrB as i64 166 nmoe_block_forward(bp) 167 168 // independent reference, token by token; per-token selections recorded via cnt deltas 169 let mpR: *i64 = sys_mmap(16*8) as *i64 170 mpR[1] = Wr as i64 171 mpR[2] = Wg as i64 172 mpR[3] = Wu as i64 173 mpR[4] = Wd as i64 174 mpR[6] = D 175 mpR[7] = H 176 mpR[8] = E 177 mpR[9] = K 178 mpR[11] = scrR as i64 179 let selmask: *i64 = sys_mmap(T*8) as *i64 180 var t: i64 = 0 181 while t < T { 182 var c0: i64 = 0 183 while c0 < E { cntB[c0] = 0; c0 = c0 + 1 } 184 mpR[10] = cntB as i64 185 mb_ref_token(mpR, x, gamma, t, D, ((out2 as i64) + t*D*8) as *i64, xnR) 186 var msk: i64 = 0 187 c0 = 0 188 while c0 < E { if cntB[c0] > 0 { msk = msk | (1 << c0) } c0 = c0 + 1 } 189 selmask[t] = msk 190 mb_w(" tok" as *u8); mb_n(t); mb_w(" experts-mask=" as *u8); mb_n(msk); mb_w("\n" as *u8) 191 t = t + 1 192 } 193 var mism: i64 = 0 194 i = 0 195 while i < T*D { if out1[i] != out2[i] { mism = mism + 1 } i = i + 1 } 196 // per-token routing: any two tokens with different masks 197 var routed_diff: i64 = 0 198 t = 0 199 while t < T { var t2: i64 = t + 1; while t2 < T { if selmask[t] != selmask[t2] { routed_diff = 1 } t2 = t2 + 1 } t = t + 1 } 200 // residual real: block out != x anywhere AND out != (out - x) trivially -> check out differs from x and 201 // that subtracting x back yields a nonzero MoE contribution on most cells 202 var neq_x: i64 = 0 203 var moe_nz: i64 = 0 204 i = 0 205 while i < T*D { if out1[i] != x[i] { neq_x = neq_x + 1 } if out1[i] - x[i] != 0 { moe_nz = moe_nz + 1 } i = i + 1 } 206 // determinism repeat 207 bp[6] = out2 as i64 208 var cz: i64 = 0 209 while cz < E { cntA[cz] = 0; cz = cz + 1 } 210 nmoe_block_forward(bp) 211 var rep_mism: i64 = 0 212 i = 0 213 while i < T*D { if out1[i] != out2[i] { rep_mism = rep_mism + 1 } i = i + 1 } 214 // neg-control: negate router row 0 -> some token's mask changes 215 let Wr2: *i64 = sys_mmap(E*D*8) as *i64 216 i = 0 217 while i < E*D { Wr2[i] = Wr[i]; i = i + 1 } 218 i = 0 219 while i < D { Wr2[i] = 0 - Wr2[i]; i = i + 1 } 220 var negmask_changed: i64 = 0 221 t = 0 222 while t < T { 223 var c1: i64 = 0 224 while c1 < E { cntB[c1] = 0; c1 = c1 + 1 } 225 mpR[1] = Wr2 as i64 226 mpR[10] = cntB as i64 227 mb_ref_token(mpR, x, gamma, t, D, ((out2 as i64) + t*D*8) as *i64, xnR) 228 var msk2: i64 = 0 229 c1 = 0 230 while c1 < E { if cntB[c1] > 0 { msk2 = msk2 | (1 << c1) } c1 = c1 + 1 } 231 if msk2 != selmask[t] { negmask_changed = 1 } 232 t = t + 1 233 } 234 235 var pass: i64 = 0 236 var ttl: i64 = 0 237 ttl = ttl + 1 238 let ok1: i64 = (mism == 0) as i64 239 mb_w(" T1 block == independent per-token reference, T=4, exact (mism " as *u8); mb_n(mism); mb_w("/" as *u8); mb_n(T*D); mb_w("): " as *u8) 240 if ok1 == 1 { pass = pass + 1; mb_w("PASS\n" as *u8) } else { mb_w("FAIL\n" as *u8) } 241 ttl = ttl + 1 242 mb_w(" T2 PER-TOKEN routing (different tokens, different expert sets): " as *u8) 243 if routed_diff == 1 { pass = pass + 1; mb_w("PASS\n" as *u8) } else { mb_w("FAIL\n" as *u8) } 244 ttl = ttl + 1 245 let ok3a: i64 = (neq_x > T*D/2) as i64 246 let ok3b: i64 = (moe_nz > T*D/2) as i64 247 let ok3: i64 = ok3a & ok3b 248 mb_w(" T3 residual real (out!=x on " as *u8); mb_n(neq_x); mb_w(", MoE contribution nonzero on " as *u8); mb_n(moe_nz); mb_w("): " as *u8) 249 if ok3 == 1 { pass = pass + 1; mb_w("PASS\n" as *u8) } else { mb_w("FAIL\n" as *u8) } 250 ttl = ttl + 1 251 let ok4: i64 = (rep_mism == 0) as i64 252 mb_w(" T4 determinism: repeat block call byte-identical: " as *u8) 253 if ok4 == 1 { pass = pass + 1; mb_w("PASS\n" as *u8) } else { mb_w("FAIL\n" as *u8) } 254 ttl = ttl + 1 255 mb_w(" T5 NEG-CONTROL corrupted router changes a token's selection: " as *u8) 256 if negmask_changed == 1 { pass = pass + 1; mb_w("PASS\n" as *u8) } else { mb_w("FAIL\n" as *u8) } 257 258 mb_w("NX-NOFLOAT-MOE-BLOCK-GATE passed " as *u8); mb_n(pass); mb_w("/" as *u8); mb_n(ttl) 259 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 260 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 261 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 262 let ctr__dry: *i64 = gv_ctr() 263 ctr__dry[0] = pass 264 ctr__dry[1] = ttl 265 let rc__dry: i64 = gv_verdict("NOFLOAT-MOE-BLOCK-GATE" as *u8, ctr__dry, "the MoE transformer block: per-token routed, residual, deterministic integer)" as *u8) 266 sys_exit(rc__dry) 267 return rc__dry 268}