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