code wiki / _hdl_build / nx_nofloat_block_gate.nx

nx_nofloat_block_gate.nx source

↩ module page · 303 lines · 17778 B

1// nx_nofloat_block_gate.nx -- HARD-EVIDENCE gate for a COMPLETE pre-norm TRANSFORMER BLOCK backprop + train, 2// in PURE INTEGER Q16 (CAP-NF-BLOCK). The block (single-head) is the real Qwen-style shape: 3// H = X + Wo * Attn( RoPE, scaled, causal-softmax )( rmsnorm_rows(X) ) [attention sublayer + residual] 4// Y = H + SwiGLU-FFN( rmsnorm_rows(H) ) [FFN sublayer + residual] 5// SwiGLU-FFN(z) = Wd * ( silu(Wg*z) (*) (Wu*z) ) 6// Composed ENTIRELY from gradcheck-verified ops (rmsnorm_rows, matmul, matmul_nt, rope, cmul, softmax_rows, 7// silu, hadamard, vadd, mse). No new backward math -- this proves the COMPOSITION trains. 8// 9// A1 hadamard gradcheck : loss=mse(a(*)b,t); dL/da == finite diff. 10// A2 rmsnorm_rows gradcheck: per-token norm; dL/dx == finite diff. 11// A3 FULL-BLOCK gradcheck wrt Wd (down-proj, short path): dL/dWd == finite diff. 12// A4 FULL-BLOCK gradcheck wrt Wq (the LONGEST chain: through FFN, residual, attention, RoPE, softmax): measured. 13// B the BLOCK TRAINS : with all weights fixed except the down-proj Wd, Y is LINEAR in Wd (convex MSE) -> 14// train Wd from zero to a realizable teacher target; assert loss collapses + Wd converges. A weight DEEP in 15// a full transformer block is driven by the block's own end-to-end backward. 16// C bit-exact ; D neg-control teeth. 17// 18// Evidence -> knowledge/status/nofloat_block.log. Sovereign: nx_nofloat_autograd + nx_syscalls (pure integer). 19// HONEST scope: single-head; multi-head/GQA + multi-block stack are the remaining COMPOSITION. expect_exit: 0 20import "nx_nofloat_autograd.nx" 21import "nx_syscalls.nx" 22import "nx_gate_emit_lib.nx" 23import "nx_gate_verdict.nx" 24 25const BLOG: *u8 = "knowledge/status/nofloat_block.log" 26const Q16: i64 = 65536 27 28 29func g_abs(v: i64) -> i64 { if v < 0 { return 0 - v } return v } 30func b_ws(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 } 31func b_wn(fd: i64, v: i64) -> i64 { let b: *u8=sys_mmap(28); var m: i64=v; if m<0{sys_write(fd,"-" as *u8,1);m=0-m} let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(fd,b,k); return 0 } 32 33// ---- generic single-input-op gradcheck (op 13=hadamard handled separately; here 14=rmsnorm_rows) ---- 34func one_loss(tape: *i64, vals: *i64, st: *i64, op: i64, Xs: *i64, Bs: *i64, Ts: *i64, r: i64, c: i64, leaves: *i64) -> i64 { 35 st[0]=0; st[1]=0 36 let nX: i64 = nfa_leaf(tape,vals,st,r,c,Xs,0) 37 var ny: i64 = nX 38 if op == 13 { let nB: i64 = nfa_leaf(tape,vals,st,r,c,Bs,0); ny = nfa_hadamard(tape,vals,st,nX,nB) } 39 if op == 14 { ny = nfa_rmsnorm_rows(tape,vals,st,nX) } 40 let nt: i64 = nfa_leaf(tape,vals,st,r,c,Ts,0) 41 let loss: i64 = nfa_mse(tape,vals,st,ny,nt) 42 leaves[0]=nX 43 return loss 44} 45func one_lossval(tape: *i64, vals: *i64, st: *i64, op: i64, Xs: *i64, Bs: *i64, Ts: *i64, r: i64, c: i64) -> i64 { 46 let lv: *i64 = sys_mmap(8) as *i64 47 let loss: i64 = one_loss(tape,vals,st,op,Xs,Bs,Ts,r,c,lv) 48 return nfa_val(tape,vals,loss,0) 49} 50func one_gradcheck(tape: *i64, vals: *i64, grads: *i64, st: *i64, op: i64, Xs: *i64, Bs: *i64, Ts: *i64, r: i64, c: i64, h: i64, tol_q: i64, floor_q: i64, worst: *i64) -> i64 { 51 let lv: *i64 = sys_mmap(8) as *i64 52 let loss: i64 = one_loss(tape,vals,st,op,Xs,Bs,Ts,r,c,lv) 53 nfa_backward(tape,vals,grads,st[0],loss) 54 let nX: i64 = lv[0] 55 var ok: i64=1; worst[0]=0 56 var i: i64=0 57 while i<r*c { 58 let ana: i64 = nfa_grad(tape,grads,nX,i) 59 let xp: *i64 = sys_mmap(r*c*8) as *i64 60 let xm: *i64 = sys_mmap(r*c*8) as *i64 61 var z: i64=0 62 while z<r*c { xp[z]=Xs[z]; xm[z]=Xs[z]; z=z+1 } 63 xp[i]=Xs[i]+h; xm[i]=Xs[i]-h 64 let lp: i64 = one_lossval(tape,vals,st,op,xp,Bs,Ts,r,c) 65 let lm: i64 = one_lossval(tape,vals,st,op,xm,Bs,Ts,r,c) 66 let fd: i64 = ((lp-lm)*Q16)/(2*h) 67 let num: i64 = g_abs(fd-ana) 68 var den: i64 = g_abs(ana); if den<floor_q { den=floor_q } 69 if num >= ((tol_q*den)>>16) { ok=0 } 70 let rel: i64 = (num*1000)/den 71 if rel>worst[0] { worst[0]=rel } 72 i=i+1 73 } 74 return ok 75} 76 77// ---- the full pre-norm transformer block; leaves[0]=nWq, leaves[1]=nWd; returns nY ---- 78func blk_fwd(tape: *i64, vals: *i64, st: *i64, X: *i64, Wq: *i64, Wk: *i64, Wv: *i64, Wo: *i64, Wg: *i64, Wu: *i64, Wd: *i64, T: i64, dm: i64, ffn: i64, scale: i64, leaves: *i64) -> i64 { 79 st[0]=0; st[1]=0 80 let nX: i64 = nfa_leaf(tape,vals,st,T,dm,X,0) 81 let nWq: i64 = nfa_leaf(tape,vals,st,dm,dm,Wq,0) 82 let nWk: i64 = nfa_leaf(tape,vals,st,dm,dm,Wk,0) 83 let nWv: i64 = nfa_leaf(tape,vals,st,dm,dm,Wv,0) 84 let nWo: i64 = nfa_leaf(tape,vals,st,dm,dm,Wo,0) 85 let nWg: i64 = nfa_leaf(tape,vals,st,dm,ffn,Wg,0) 86 let nWu: i64 = nfa_leaf(tape,vals,st,dm,ffn,Wu,0) 87 let nWd: i64 = nfa_leaf(tape,vals,st,ffn,dm,Wd,0) 88 let nXn: i64 = nfa_rmsnorm_rows(tape,vals,st,nX) 89 let nQ: i64 = nfa_matmul(tape,vals,st,nXn,nWq) 90 let nK: i64 = nfa_matmul(tape,vals,st,nXn,nWk) 91 let nV: i64 = nfa_matmul(tape,vals,st,nXn,nWv) 92 let nQr: i64 = nfa_rope(tape,vals,st,nQ) 93 let nKr: i64 = nfa_rope(tape,vals,st,nK) 94 let nS: i64 = nfa_matmul_nt(tape,vals,st,nQr,nKr) 95 let nSs: i64 = nfa_cmul(tape,vals,st,nS,scale) 96 let nA: i64 = nfa_softmax_rows(tape,vals,st,nSs,1) 97 let nO: i64 = nfa_matmul(tape,vals,st,nA,nV) 98 let nOp: i64 = nfa_matmul(tape,vals,st,nO,nWo) 99 let nH: i64 = nfa_vadd(tape,vals,st,nX,nOp) 100 let nHn: i64 = nfa_rmsnorm_rows(tape,vals,st,nH) 101 let nG: i64 = nfa_matmul(tape,vals,st,nHn,nWg) 102 let nU: i64 = nfa_matmul(tape,vals,st,nHn,nWu) 103 let nSg: i64 = nfa_silu(tape,vals,st,nG) 104 let nHs: i64 = nfa_hadamard(tape,vals,st,nSg,nU) 105 let nD: i64 = nfa_matmul(tape,vals,st,nHs,nWd) 106 let nY: i64 = nfa_vadd(tape,vals,st,nH,nD) 107 leaves[0]=nWq; leaves[1]=nWd 108 return nY 109} 110func blk_loss(tape: *i64, vals: *i64, st: *i64, X: *i64, Wq: *i64, Wk: *i64, Wv: *i64, Wo: *i64, Wg: *i64, Wu: *i64, Wd: *i64, Ts: *i64, T: i64, dm: i64, ffn: i64, scale: i64, leaves: *i64) -> i64 { 111 let nY: i64 = blk_fwd(tape,vals,st,X,Wq,Wk,Wv,Wo,Wg,Wu,Wd,T,dm,ffn,scale,leaves) 112 let nt: i64 = nfa_leaf(tape,vals,st,T,dm,Ts,0) 113 return nfa_mse(tape,vals,st,nY,nt) 114} 115func blk_lossval(tape: *i64, vals: *i64, st: *i64, X: *i64, Wq: *i64, Wk: *i64, Wv: *i64, Wo: *i64, Wg: *i64, Wu: *i64, Wd: *i64, Ts: *i64, T: i64, dm: i64, ffn: i64, scale: i64) -> i64 { 116 let lv: *i64 = sys_mmap(2*8) as *i64 117 let loss: i64 = blk_loss(tape,vals,st,X,Wq,Wk,Wv,Wo,Wg,Wu,Wd,Ts,T,dm,ffn,scale,lv) 118 return nfa_val(tape,vals,loss,0) 119} 120func blk_out(tape: *i64, vals: *i64, st: *i64, X: *i64, Wq: *i64, Wk: *i64, Wv: *i64, Wo: *i64, Wg: *i64, Wu: *i64, Wd: *i64, T: i64, dm: i64, ffn: i64, scale: i64, outY: *i64) -> i64 { 121 let lv: *i64 = sys_mmap(2*8) as *i64 122 let nY: i64 = blk_fwd(tape,vals,st,X,Wq,Wk,Wv,Wo,Wg,Wu,Wd,T,dm,ffn,scale,lv) 123 var i: i64=0 124 while i<T*dm { outY[i] = nfa_val(tape,vals,nY,i); i=i+1 } 125 return 0 126} 127 128func main() -> i64 { 129 g_puts("nx_nofloat_block gate (a full pre-norm TRANSFORMER BLOCK backprops + trains in PURE INTEGER Q16)\n" as *u8) 130 var pass: i64=0; var total: i64=0 131 let tape: *i64 = sys_mmap(1024*7*8) as *i64 132 let vals: *i64 = sys_mmap(16384*8) as *i64 133 let grads: *i64 = sys_mmap(16384*8) as *i64 134 let st: *i64 = sys_mmap(2*8) as *i64 135 let h: i64 = 512; let floor_q: i64 = 4096 136 let worst: *i64 = sys_mmap(8) as *i64 137 138 // ---- A1 hadamard gradcheck (2x2) ---- 139 let ha: *i64 = sys_mmap(4*8) as *i64; ha[0]=32768; ha[1]=0-16384; ha[2]=49152; ha[3]=65536 140 let hb: *i64 = sys_mmap(4*8) as *i64; hb[0]=49152; hb[1]=32768; hb[2]=0-32768; hb[3]=16384 141 let ht: *i64 = sys_mmap(4*8) as *i64; ht[0]=13107; ht[1]=0-6554; ht[2]=19661; ht[3]=6554 142 let ha_ok: i64 = one_gradcheck(tape,vals,grads,st,13,ha,hb,ht,2,2,h,4096,floor_q,worst) 143 g_puts(" [measure] hadamard worst rel grad err = " as *u8); g_pn(worst[0]); g_puts(" /1000 (tol=62)\n" as *u8) 144 pass=pass+g_check("A1: hadamard gradcheck -- elementwise mul backward == finite differences" as *u8, ha_ok); total=total+1 145 146 // ---- A2 rmsnorm_rows gradcheck (2 rows x 3 cols) ---- 147 let ra: *i64 = sys_mmap(6*8) as *i64; ra[0]=32768; ra[1]=65536; ra[2]=0-32768; ra[3]=16384; ra[4]=0-49152; ra[5]=24576 148 let rt: *i64 = sys_mmap(6*8) as *i64; rt[0]=13107; rt[1]=52429; rt[2]=0-39322; rt[3]=6554; rt[4]=0-26214; rt[5]=32768 149 let ra_ok: i64 = one_gradcheck(tape,vals,grads,st,14,ra,ra,rt,2,3,h,4096,floor_q,worst) 150 g_puts(" [measure] rmsnorm_rows worst rel grad err = " as *u8); g_pn(worst[0]); g_puts(" /1000 (tol=62)\n" as *u8) 151 pass=pass+g_check("A2: rmsnorm_rows gradcheck -- per-token normalization backward == finite differences" as *u8, ra_ok); total=total+1 152 153 // ---- block dims + weights ---- 154 let T: i64 = 2; let dm: i64 = 2; let ffn: i64 = 4; let scale: i64 = 46341 155 let X: *i64 = sys_mmap(T*dm*8) as *i64; X[0]=32768; X[1]=0-16384; X[2]=49152; X[3]=24576 156 let Wq: *i64 = sys_mmap(dm*dm*8) as *i64; Wq[0]=49152; Wq[1]=0-16384; Wq[2]=32768; Wq[3]=65536 157 let Wk: *i64 = sys_mmap(dm*dm*8) as *i64; Wk[0]=16384; Wk[1]=32768; Wk[2]=0-32768; Wk[3]=49152 158 let Wv: *i64 = sys_mmap(dm*dm*8) as *i64; Wv[0]=65536; Wv[1]=0-32768; Wv[2]=16384; Wv[3]=49152 159 let Wo: *i64 = sys_mmap(dm*dm*8) as *i64; Wo[0]=32768; Wo[1]=16384; Wo[2]=0-16384; Wo[3]=49152 160 let Wg: *i64 = sys_mmap(dm*ffn*8) as *i64; Wg[0]=32768; Wg[1]=0-16384; Wg[2]=49152; Wg[3]=16384; Wg[4]=0-32768; Wg[5]=65536; Wg[6]=24576; Wg[7]=0-8192 161 let Wu: *i64 = sys_mmap(dm*ffn*8) as *i64; Wu[0]=16384; Wu[1]=49152; Wu[2]=0-32768; Wu[3]=32768; Wu[4]=65536; Wu[5]=0-16384; Wu[6]=8192; Wu[7]=40960 162 let Wd: *i64 = sys_mmap(ffn*dm*8) as *i64; Wd[0]=32768; Wd[1]=0-16384; Wd[2]=16384; Wd[3]=49152; Wd[4]=0-32768; Wd[5]=24576; Wd[6]=40960; Wd[7]=0-8192 163 let Tg: *i64 = sys_mmap(T*dm*8) as *i64; Tg[0]=13107; Tg[1]=0-6554; Tg[2]=19661; Tg[3]=6554 164 let lv: *i64 = sys_mmap(2*8) as *i64 165 166 // ---- A3 full-block gradcheck wrt Wd (short path) ---- 167 let loss3: i64 = blk_loss(tape,vals,st,X,Wq,Wk,Wv,Wo,Wg,Wu,Wd,Tg,T,dm,ffn,scale,lv) 168 nfa_backward(tape,vals,grads,st[0],loss3) 169 let nWd: i64 = lv[1] 170 var a3_ok: i64=1; var a3_worst: i64=0 171 var di: i64=0 172 while di < ffn*dm { 173 let ana: i64 = nfa_grad(tape,grads,nWd,di) 174 let wp: *i64 = sys_mmap(ffn*dm*8) as *i64 175 let wm: *i64 = sys_mmap(ffn*dm*8) as *i64 176 var z: i64=0 177 while z<ffn*dm { wp[z]=Wd[z]; wm[z]=Wd[z]; z=z+1 } 178 wp[di]=Wd[di]+h; wm[di]=Wd[di]-h 179 let lp: i64 = blk_lossval(tape,vals,st,X,Wq,Wk,Wv,Wo,Wg,Wu,wp,Tg,T,dm,ffn,scale) 180 let lm: i64 = blk_lossval(tape,vals,st,X,Wq,Wk,Wv,Wo,Wg,Wu,wm,Tg,T,dm,ffn,scale) 181 let fd: i64 = ((lp-lm)*Q16)/(2*h) 182 let num: i64 = g_abs(fd-ana) 183 var den: i64 = g_abs(ana); if den<floor_q { den=floor_q } 184 if num >= ((8192*den)>>16) { a3_ok=0 } 185 let rel: i64 = (num*1000)/den 186 if rel>a3_worst { a3_worst=rel } 187 di=di+1 188 } 189 g_puts(" [measure] block dL/dWd worst rel grad err = " as *u8); g_pn(a3_worst); g_puts(" /1000 (tol=125)\n" as *u8) 190 pass=pass+g_check("A3: FULL-BLOCK gradcheck wrt Wd (FFN down-proj) == finite differences" as *u8, a3_ok); total=total+1 191 192 // ---- A4 full-block gradcheck wrt Wq (the LONGEST chain: FFN<-residual<-attention<-RoPE<-softmax) ---- 193 let loss4: i64 = blk_loss(tape,vals,st,X,Wq,Wk,Wv,Wo,Wg,Wu,Wd,Tg,T,dm,ffn,scale,lv) 194 nfa_backward(tape,vals,grads,st[0],loss4) 195 let nWq: i64 = lv[0] 196 var a4_ok: i64=1; var a4_worst: i64=0 197 var qi: i64=0 198 while qi < dm*dm { 199 let ana: i64 = nfa_grad(tape,grads,nWq,qi) 200 let wp: *i64 = sys_mmap(dm*dm*8) as *i64 201 let wm: *i64 = sys_mmap(dm*dm*8) as *i64 202 var z: i64=0 203 while z<dm*dm { wp[z]=Wq[z]; wm[z]=Wq[z]; z=z+1 } 204 wp[qi]=Wq[qi]+h; wm[qi]=Wq[qi]-h 205 let lp: i64 = blk_lossval(tape,vals,st,X,wp,Wk,Wv,Wo,Wg,Wu,Wd,Tg,T,dm,ffn,scale) 206 let lm: i64 = blk_lossval(tape,vals,st,X,wm,Wk,Wv,Wo,Wg,Wu,Wd,Tg,T,dm,ffn,scale) 207 let fd: i64 = ((lp-lm)*Q16)/(2*h) 208 let num: i64 = g_abs(fd-ana) 209 var den: i64 = g_abs(ana); if den<floor_q { den=floor_q } 210 if num >= ((16384*den)>>16) { a4_ok=0 } // tol 1/4 (longest fixed-point chain in the block) 211 let rel: i64 = (num*1000)/den 212 if rel>a4_worst { a4_worst=rel } 213 qi=qi+1 214 } 215 g_puts(" [measure] block dL/dWq (full chain) worst rel grad err = " as *u8); g_pn(a4_worst); g_puts(" /1000 (tol=250)\n" as *u8) 216 pass=pass+g_check("A4: FULL-BLOCK gradcheck wrt Wq through FFN+residual+attention+RoPE+softmax == finite diff" as *u8, a4_ok); total=total+1 217 218 // ---- D neg-control teeth (block Wd grad) ---- 219 let lossd: i64 = blk_loss(tape,vals,st,X,Wq,Wk,Wv,Wo,Wg,Wu,Wd,Tg,T,dm,ffn,scale,lv) 220 nfa_backward(tape,vals,grads,st[0],lossd) 221 let dana: i64 = nfa_grad(tape,grads,lv[1],0) 222 let wp0: *i64 = sys_mmap(ffn*dm*8) as *i64 223 let wm0: *i64 = sys_mmap(ffn*dm*8) as *i64 224 var z0: i64=0 225 while z0<ffn*dm { wp0[z0]=Wd[z0]; wm0[z0]=Wd[z0]; z0=z0+1 } 226 wp0[0]=Wd[0]+h; wm0[0]=Wd[0]-h 227 let dfd: i64 = ((blk_lossval(tape,vals,st,X,Wq,Wk,Wv,Wo,Wg,Wu,wp0,Tg,T,dm,ffn,scale) - blk_lossval(tape,vals,st,X,Wq,Wk,Wv,Wo,Wg,Wu,wm0,Tg,T,dm,ffn,scale))*Q16)/(2*h) 228 let dbad: i64 = 0 - dana 229 var dden: i64 = g_abs(dana); if dden<floor_q { dden=floor_q } 230 var caught: i64 = 1 231 if g_abs(dfd-dbad) < ((8192*dden)>>16) { caught=0 } 232 pass=pass+g_check("D: neg-control -- a WRONG block gradient is rejected (teeth)" as *u8, caught); total=total+1 233 234 // ---- B the block TRAINS: fix all weights except Wd (Y linear in Wd -> convex); realizable teacher target ---- 235 let Wdt: *i64 = sys_mmap(ffn*dm*8) as *i64; Wdt[0]=49152; Wdt[1]=0-32768; Wdt[2]=16384; Wdt[3]=65536; Wdt[4]=0-16384; Wdt[5]=32768; Wdt[6]=24576; Wdt[7]=0-49152 236 let tgt: *i64 = sys_mmap(T*dm*8) as *i64 237 blk_out(tape,vals,st,X,Wq,Wk,Wv,Wo,Wg,Wu,Wdt,T,dm,ffn,scale,tgt) // target = block output with Wd* 238 let Wdp: *i64 = sys_mmap(ffn*dm*8) as *i64 239 var zz: i64=0 240 while zz<ffn*dm { Wdp[zz]=0; zz=zz+1 } // learn Wd from zero 241 let gW: *i64 = sys_mmap(ffn*dm*8) as *i64 242 let lvb: *i64 = sys_mmap(2*8) as *i64 243 var lf: i64=0; var ll: i64=0 244 var ep: i64=0 245 while ep < 8000 { 246 let lossb: i64 = blk_loss(tape,vals,st,X,Wq,Wk,Wv,Wo,Wg,Wu,Wdp,tgt,T,dm,ffn,scale,lvb) 247 nfa_backward(tape,vals,grads,st[0],lossb) 248 if ep==0 { lf = nfa_val(tape,vals,lossb,0) } 249 ll = nfa_val(tape,vals,lossb,0) 250 var z: i64=0 251 while z<ffn*dm { gW[z]=nfa_grad(tape,grads,lvb[1],z); z=z+1 } 252 nfa_sgd(Wdp, gW, ffn*dm, 1024) 253 ep=ep+1 254 } 255 g_puts(" [measure] block train (Wd) loss: start=" as *u8); g_pn(lf); g_puts(" end=" as *u8); g_pn(ll); g_puts("\n" as *u8) 256 // (T=2,ffn=4 -> Wd is under-determined, so GD reaches a valid minimizer with loss->0, NOT necessarily Wd*; 257 // the honest evidence that the block TRAINS is the loss collapse driven by the end-to-end backward.) 258 var learns: i64 = 1 259 if ll*20 > lf { learns=0 } // >= 95% loss reduction (loss collapses to ~0) 260 if lf <= 100 { learns=0 } // started genuinely untrained 261 pass=pass+g_check("B: the BLOCK TRAINS -- the FFN down-proj is driven by the block's end-to-end backward; loss collapses to ~0" as *u8, learns); total=total+1 262 263 // ---- C bit-exact ---- 264 let Wdp2: *i64 = sys_mmap(ffn*dm*8) as *i64 265 var z2: i64=0 266 while z2<ffn*dm { Wdp2[z2]=0; z2=z2+1 } 267 let gW2: *i64 = sys_mmap(ffn*dm*8) as *i64 268 let lvc: *i64 = sys_mmap(2*8) as *i64 269 var ep2: i64=0 270 while ep2 < 8000 { 271 let lossc: i64 = blk_loss(tape,vals,st,X,Wq,Wk,Wv,Wo,Wg,Wu,Wdp2,tgt,T,dm,ffn,scale,lvc) 272 nfa_backward(tape,vals,grads,st[0],lossc) 273 var z: i64=0 274 while z<ffn*dm { gW2[z]=nfa_grad(tape,grads,lvc[1],z); z=z+1 } 275 nfa_sgd(Wdp2, gW2, ffn*dm, 1024) 276 ep2=ep2+1 277 } 278 var bitexact: i64 = 1 279 var zc: i64=0 280 while zc<ffn*dm { if Wdp2[zc]!=Wdp[zc] { bitexact=0 } zc=zc+1 } 281 pass=pass+g_check("C: bit-exact -- training the block twice gives IDENTICAL integer Wd (determinism)" as *u8, bitexact); total=total+1 282 283 // ---- emit ---- 284 var okall: i64=0; if pass==total { okall=1 } 285 let logf: i64 = sys_openat_append(BLOG, 420) 286 if logf >= 0 { 287 b_ws(logf,"NOFLOATBLOCK pre-norm single-head A1_had=" as *u8); b_wn(logf,ha_ok); b_ws(logf," A2_rmsrows=" as *u8); b_wn(logf,ra_ok) 288 b_ws(logf," A3_Wd=" as *u8); b_wn(logf,a3_ok); b_ws(logf," A4_Wq_fullchain=" as *u8); b_wn(logf,a4_ok); b_ws(logf," D=" as *u8); b_wn(logf,caught) 289 b_ws(logf," B_trains=" as *u8); b_wn(logf,learns); b_ws(logf," C_bitexact=" as *u8); b_wn(logf,bitexact) 290 if okall==1 { b_ws(logf," verdict=GREEN\n" as *u8) } else { b_ws(logf," verdict=RED\n" as *u8) } 291 sys_close(logf) 292 } 293 g_puts("---- nofloat_block gate: passed " as *u8); g_pn(pass); g_puts(" / " as *u8); g_pn(total); g_puts(" ----\n" as *u8) 294 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 295 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 296 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 297 let ctr__dry: *i64 = gv_ctr() 298 ctr__dry[0] = pass 299 ctr__dry[1] = total 300 let rc__dry: i64 = gv_verdict("NOFLOAT-BLOCK-GATE" as *u8, ctr__dry, "a full pre-norm transformer block backprops + trains in pure integer Q16)" as *u8) 301 sys_exit(rc__dry) 302 return rc__dry 303}