code wiki / _hdl_build / nx_nofloat_lm_gate.nx
nx_nofloat_lm_gate.nx source
↩ module page · 295 lines · 17415 B
1// nx_nofloat_lm_gate.nx -- THE CAPSTONE: a tiny TRANSFORMER LANGUAGE MODEL trains END-TO-END on next-token
2// prediction, in PURE INTEGER Q16 (CAP-NF-LM). Full LM forward:
3// X = embed(E, ids) -> pre-norm transformer block (attn+RoPE+causal-softmax+SwiGLU-FFN+residuals)
4// -> rmsnorm_rows -> logits = H_n . W_lm -> loss = softmax-cross-entropy(logits, next-token ids)
5// Composed ENTIRELY from gradcheck-verified ops + the two new LM-head ops (embed gather/scatter, fused softce).
6//
7// A1 embed gradcheck : dE (gather backward = scatter-add) == finite difference.
8// A2 softce gradcheck : dlogits (fused CE identity softmax-onehot) == finite difference.
9// A3 full-LM gradcheck wrt W_lm : the LM-head gradient through CE == finite diff.
10// A4 full-LM gradcheck wrt E : the LONGEST chain -- E's gradient flows back through head+norm+FFN+attention
11// +RoPE+softmax+embed (the WHOLE model) == finite diff. This proves end-to-end backprop of the LM.
12// D neg-control teeth ; C bit-exact.
13// B THE LM FITS (memorizes a FIXED sequence) : train E + W_lm (through the full forward; gradient traverses the whole block) on a
14// next-token task (ids 0,1,2,3 -> 1,2,3,0); assert CE loss drops substantially from ~ln(V).
15//
16// Evidence -> knowledge/status/nofloat_lm.log. Sovereign: nx_nofloat_autograd + nx_syscalls (pure integer).
17// HONEST scope: single-head, single-block, tiny vocab; multi-head/GQA + deeper stack + scale remain. expect_exit: 0
18import "nx_nofloat_autograd.nx"
19import "nx_syscalls.nx"
20import "nx_gate_emit_lib.nx"
21
22const LLOG: *u8 = "knowledge/status/nofloat_lm.log"
23const Q16: i64 = 65536
24
25
26func g_abs(v: i64) -> i64 { if v < 0 { return 0 - v } return v }
27func l_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 }
28func l_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 }
29// deterministic small nonzero init (zero-init = dead-gradient trap): values in ~[-0.25, 0.25] Q16
30func lm_init(arr: *i64, n: i64, seed: i64) -> i64 { var i: i64=0; while i<n { arr[i] = (((i*7 + seed*13 + 1) % 11) - 5) * 3277; i=i+1 } return 0 }
31
32// ---- full LM forward; W = ptr-array of 9 weight arrays [E,Wq,Wk,Wv,Wo,Wg,Wu,Wd,Wlm]; leaves[i]<->W[i], leaves[9]=logits ----
33func lm_fwd(tape: *i64, vals: *i64, st: *i64, W: *i64, ids: *i64, tgt: *i64, T: i64, dm: i64, ffn: i64, V: i64, scale: i64, leaves: *i64) -> i64 {
34 let E: *i64 = W[0] as *i64; let Wq: *i64 = W[1] as *i64; let Wk: *i64 = W[2] as *i64; let Wv: *i64 = W[3] as *i64; let Wo: *i64 = W[4] as *i64
35 let Wg: *i64 = W[5] as *i64; let Wu: *i64 = W[6] as *i64; let Wd: *i64 = W[7] as *i64; let Wlm: *i64 = W[8] as *i64
36 st[0]=0; st[1]=0
37 let nE: i64 = nfa_leaf(tape,vals,st,V,dm,E,0)
38 let nWq: i64 = nfa_leaf(tape,vals,st,dm,dm,Wq,0)
39 let nWk: i64 = nfa_leaf(tape,vals,st,dm,dm,Wk,0)
40 let nWv: i64 = nfa_leaf(tape,vals,st,dm,dm,Wv,0)
41 let nWo: i64 = nfa_leaf(tape,vals,st,dm,dm,Wo,0)
42 let nWg: i64 = nfa_leaf(tape,vals,st,dm,ffn,Wg,0)
43 let nWu: i64 = nfa_leaf(tape,vals,st,dm,ffn,Wu,0)
44 let nWd: i64 = nfa_leaf(tape,vals,st,ffn,dm,Wd,0)
45 let nWlm:i64 = nfa_leaf(tape,vals,st,dm,V,Wlm,0)
46 let nX: i64 = nfa_embed(tape,vals,st,nE,ids,T)
47 let nXn: i64 = nfa_rmsnorm_rows(tape,vals,st,nX)
48 let nQ: i64 = nfa_matmul(tape,vals,st,nXn,nWq)
49 let nK: i64 = nfa_matmul(tape,vals,st,nXn,nWk)
50 let nV: i64 = nfa_matmul(tape,vals,st,nXn,nWv)
51 let nQr: i64 = nfa_rope(tape,vals,st,nQ)
52 let nKr: i64 = nfa_rope(tape,vals,st,nK)
53 let nS: i64 = nfa_matmul_nt(tape,vals,st,nQr,nKr)
54 let nSs: i64 = nfa_cmul(tape,vals,st,nS,scale)
55 let nA: i64 = nfa_softmax_rows(tape,vals,st,nSs,1)
56 let nO: i64 = nfa_matmul(tape,vals,st,nA,nV)
57 let nOp: i64 = nfa_matmul(tape,vals,st,nO,nWo)
58 let nH: i64 = nfa_vadd(tape,vals,st,nX,nOp)
59 let nHn: i64 = nfa_rmsnorm_rows(tape,vals,st,nH)
60 let nG: i64 = nfa_matmul(tape,vals,st,nHn,nWg)
61 let nU: i64 = nfa_matmul(tape,vals,st,nHn,nWu)
62 let nSg: i64 = nfa_silu(tape,vals,st,nG)
63 let nHs: i64 = nfa_hadamard(tape,vals,st,nSg,nU)
64 let nDp: i64 = nfa_matmul(tape,vals,st,nHs,nWd)
65 let nY: i64 = nfa_vadd(tape,vals,st,nH,nDp)
66 let nYn: i64 = nfa_rmsnorm_rows(tape,vals,st,nY)
67 let nLg: i64 = nfa_matmul(tape,vals,st,nYn,nWlm)
68 let nLoss: i64 = nfa_softce_rows(tape,vals,st,nLg,tgt)
69 leaves[0]=nE; leaves[1]=nWq; leaves[2]=nWk; leaves[3]=nWv; leaves[4]=nWo
70 leaves[5]=nWg; leaves[6]=nWu; leaves[7]=nWd; leaves[8]=nWlm; leaves[9]=nLg
71 return nLoss
72}
73func lm_lossval(tape: *i64, vals: *i64, st: *i64, W: *i64, ids: *i64, tgt: *i64, T: i64, dm: i64, ffn: i64, V: i64, scale: i64) -> i64 {
74 let lv: *i64 = sys_mmap(10*8) as *i64
75 let nLoss: i64 = lm_fwd(tape,vals,st,W,ids,tgt,T,dm,ffn,V,scale,lv)
76 return nfa_val(tape,vals,nLoss,0)
77}
78// gradcheck wrt weight array widx (leaves[widx]); extract ALL analytic grads first (lm_lossval rebuilds the tape).
79func lm_gc_w(tape: *i64, vals: *i64, grads: *i64, st: *i64, W: *i64, ids: *i64, tgt: *i64, T: i64, dm: i64, ffn: i64, V: i64, scale: i64, leaves: *i64, widx: i64, h: i64, tol_q: i64, floor_q: i64, worst: *i64) -> i64 {
80 let nLoss: i64 = lm_fwd(tape,vals,st,W,ids,tgt,T,dm,ffn,V,scale,leaves)
81 nfa_backward(tape,vals,grads,st[0],nLoss)
82 let nnode: i64 = leaves[widx]
83 let cnt: i64 = tape[7*nnode+3]*tape[7*nnode+4]
84 let ana: *i64 = sys_mmap(64*8) as *i64
85 var c: i64=0
86 while c<cnt { ana[c]=nfa_grad(tape,grads,nnode,c); c=c+1 }
87 let arr: *i64 = W[widx] as *i64
88 var ok: i64=1; worst[0]=0
89 var i: i64=0
90 while i<cnt {
91 let old: i64 = arr[i]
92 arr[i]=old+h; let lp: i64 = lm_lossval(tape,vals,st,W,ids,tgt,T,dm,ffn,V,scale)
93 arr[i]=old-h; let lm2: i64 = lm_lossval(tape,vals,st,W,ids,tgt,T,dm,ffn,V,scale)
94 arr[i]=old
95 let fd: i64 = ((lp-lm2)*Q16)/(2*h)
96 let num: i64 = g_abs(fd-ana[i])
97 var den: i64 = g_abs(ana[i]); if den<floor_q { den=floor_q }
98 if num >= ((tol_q*den)>>16) { ok=0 }
99 let rel: i64 = (num*1000)/den
100 if rel>worst[0] { worst[0]=rel }
101 i=i+1
102 }
103 return ok
104}
105
106// ---- A1 embed standalone: loss = mse(embed(E,ids), tgt) ----
107func emb_loss(tape: *i64, vals: *i64, st: *i64, E: *i64, ids: *i64, Tg: *i64, V: i64, dm: i64, T: i64, leaves: *i64) -> i64 {
108 st[0]=0; st[1]=0
109 let nE: i64 = nfa_leaf(tape,vals,st,V,dm,E,0)
110 let nX: i64 = nfa_embed(tape,vals,st,nE,ids,T)
111 let nt: i64 = nfa_leaf(tape,vals,st,T,dm,Tg,0)
112 let loss: i64 = nfa_mse(tape,vals,st,nX,nt)
113 leaves[0]=nE
114 return loss
115}
116func emb_lossval(tape: *i64, vals: *i64, st: *i64, E: *i64, ids: *i64, Tg: *i64, V: i64, dm: i64, T: i64) -> i64 {
117 let lv: *i64 = sys_mmap(8) as *i64
118 let loss: i64 = emb_loss(tape,vals,st,E,ids,Tg,V,dm,T,lv)
119 return nfa_val(tape,vals,loss,0)
120}
121
122// ---- A2 softce standalone: loss = softce(logits_leaf, tgt) ----
123func ce_loss(tape: *i64, vals: *i64, st: *i64, L: *i64, tgt: *i64, T: i64, V: i64, leaves: *i64) -> i64 {
124 st[0]=0; st[1]=0
125 let nL: i64 = nfa_leaf(tape,vals,st,T,V,L,0)
126 let loss: i64 = nfa_softce_rows(tape,vals,st,nL,tgt)
127 leaves[0]=nL
128 return loss
129}
130func ce_lossval(tape: *i64, vals: *i64, st: *i64, L: *i64, tgt: *i64, T: i64, V: i64) -> i64 {
131 let lv: *i64 = sys_mmap(8) as *i64
132 let loss: i64 = ce_loss(tape,vals,st,L,tgt,T,V,lv)
133 return nfa_val(tape,vals,loss,0)
134}
135
136func main() -> i64 {
137 g_puts("nx_nofloat_lm gate (a tiny TRANSFORMER LM trains end-to-end on next-token, PURE INTEGER Q16)\n" as *u8)
138 var pass: i64=0; var total: i64=0
139 let tape: *i64 = sys_mmap(512*7*8) as *i64
140 let vals: *i64 = sys_mmap(16384*8) as *i64
141 let grads: *i64 = sys_mmap(16384*8) as *i64
142 let st: *i64 = sys_mmap(2*8) as *i64
143 let h: i64 = 512; let floor_q: i64 = 4096
144 let worst: *i64 = sys_mmap(8) as *i64
145
146 // ---- A1: embed gradcheck (V=3,dm=2,T=3; ids gather rows 0,2,1; one repeats nothing here) ----
147 let eE: *i64 = sys_mmap(6*8) as *i64; lm_init(eE,6,1)
148 let eids: *i64 = sys_mmap(3*8) as *i64; eids[0]=0; eids[1]=2; eids[2]=1
149 let eTg: *i64 = sys_mmap(6*8) as *i64; eTg[0]=13107; eTg[1]=0-6554; eTg[2]=19661; eTg[3]=6554; eTg[4]=0-26214; eTg[5]=32768
150 let elv: *i64 = sys_mmap(8) as *i64
151 let el: i64 = emb_loss(tape,vals,st,eE,eids,eTg,3,2,3,elv)
152 nfa_backward(tape,vals,grads,st[0],el)
153 let enode: i64 = elv[0]
154 let eana: *i64 = sys_mmap(8*8) as *i64
155 var ec: i64=0
156 while ec<6 { eana[ec]=nfa_grad(tape,grads,enode,ec); ec=ec+1 }
157 var e_ok: i64=1; var e_worst: i64=0
158 var ei: i64=0
159 while ei<6 {
160 let old: i64=eE[ei]; eE[ei]=old+h; let lp: i64=emb_lossval(tape,vals,st,eE,eids,eTg,3,2,3); eE[ei]=old-h; let lm2: i64=emb_lossval(tape,vals,st,eE,eids,eTg,3,2,3); eE[ei]=old
161 let fd: i64=((lp-lm2)*Q16)/(2*h); let num: i64=g_abs(fd-eana[ei]); var den: i64=g_abs(eana[ei]); if den<floor_q{den=floor_q}
162 if num >= ((4096*den)>>16) { e_ok=0 }
163 let rel: i64=(num*1000)/den; if rel>e_worst{e_worst=rel}
164 ei=ei+1
165 }
166 g_puts(" [measure] embed worst rel grad err = " as *u8); g_pn(e_worst); g_puts(" /1000 (tol=62)\n" as *u8)
167 pass=pass+g_check("A1: embed gradcheck -- gather backward (scatter-add) == finite differences" as *u8, e_ok); total=total+1
168
169 // ---- A2: softce gradcheck (T=2,V=3) ----
170 let cL: *i64 = sys_mmap(6*8) as *i64; cL[0]=32768; cL[1]=0-16384; cL[2]=49152; cL[3]=16384; cL[4]=65536; cL[5]=0-32768
171 let ctg: *i64 = sys_mmap(2*8) as *i64; ctg[0]=1; ctg[1]=2
172 let clv: *i64 = sys_mmap(8) as *i64
173 let cl: i64 = ce_loss(tape,vals,st,cL,ctg,2,3,clv)
174 nfa_backward(tape,vals,grads,st[0],cl)
175 let cnode: i64 = clv[0]
176 let cana: *i64 = sys_mmap(8*8) as *i64
177 var cc: i64=0
178 while cc<6 { cana[cc]=nfa_grad(tape,grads,cnode,cc); cc=cc+1 }
179 var c_ok: i64=1; var c_worst: i64=0
180 var ci: i64=0
181 while ci<6 {
182 let old: i64=cL[ci]; cL[ci]=old+h; let lp: i64=ce_lossval(tape,vals,st,cL,ctg,2,3); cL[ci]=old-h; let lm2: i64=ce_lossval(tape,vals,st,cL,ctg,2,3); cL[ci]=old
183 let fd: i64=((lp-lm2)*Q16)/(2*h); let num: i64=g_abs(fd-cana[ci]); var den: i64=g_abs(cana[ci]); if den<floor_q{den=floor_q}
184 if num >= ((8192*den)>>16) { c_ok=0 } // tol 1/8 (ln/exp fixed-point approximation)
185 let rel: i64=(num*1000)/den; if rel>c_worst{c_worst=rel}
186 ci=ci+1
187 }
188 g_puts(" [measure] softce worst rel grad err = " as *u8); g_pn(c_worst); g_puts(" /1000 (tol=125)\n" as *u8)
189 pass=pass+g_check("A2: softce gradcheck -- fused softmax-CE (softmax-onehot) backward == finite differences" as *u8, c_ok); total=total+1
190
191 // ---- LM dims + weights ----
192 let T: i64=4; let dm: i64=4; let ffn: i64=8; let V: i64=4; let scale: i64=32768 // 1/sqrt(4)=0.5
193 let E: *i64 = sys_mmap(V*dm*8) as *i64; lm_init(E,V*dm,1)
194 let Wq: *i64 = sys_mmap(dm*dm*8) as *i64; lm_init(Wq,dm*dm,2)
195 let Wk: *i64 = sys_mmap(dm*dm*8) as *i64; lm_init(Wk,dm*dm,3)
196 let Wv: *i64 = sys_mmap(dm*dm*8) as *i64; lm_init(Wv,dm*dm,4)
197 let Wo: *i64 = sys_mmap(dm*dm*8) as *i64; lm_init(Wo,dm*dm,5)
198 let Wg: *i64 = sys_mmap(dm*ffn*8) as *i64; lm_init(Wg,dm*ffn,6)
199 let Wu: *i64 = sys_mmap(dm*ffn*8) as *i64; lm_init(Wu,dm*ffn,7)
200 let Wd: *i64 = sys_mmap(ffn*dm*8) as *i64; lm_init(Wd,ffn*dm,8)
201 let Wlm:*i64 = sys_mmap(dm*V*8) as *i64; lm_init(Wlm,dm*V,9)
202 let W: *i64 = sys_mmap(9*8) as *i64
203 W[0]=E as i64; W[1]=Wq as i64; W[2]=Wk as i64; W[3]=Wv as i64; W[4]=Wo as i64; W[5]=Wg as i64; W[6]=Wu as i64; W[7]=Wd as i64; W[8]=Wlm as i64
204 let ids: *i64 = sys_mmap(T*8) as *i64; ids[0]=0; ids[1]=1; ids[2]=2; ids[3]=3
205 let tgt: *i64 = sys_mmap(T*8) as *i64; tgt[0]=1; tgt[1]=2; tgt[2]=3; tgt[3]=0
206 let leaves: *i64 = sys_mmap(10*8) as *i64
207
208 // ---- A3: full-LM gradcheck wrt Wlm (widx 8) ----
209 let a3_ok: i64 = lm_gc_w(tape,vals,grads,st,W,ids,tgt,T,dm,ffn,V,scale,leaves,8,h,8192,floor_q,worst)
210 g_puts(" [measure] full-LM dL/dWlm worst rel grad err = " as *u8); g_pn(worst[0]); g_puts(" /1000 (tol=125)\n" as *u8)
211 pass=pass+g_check("A3: full-LM gradcheck wrt Wlm (LM head through CE) == finite differences" as *u8, a3_ok); total=total+1
212
213 // ---- A4: full-LM gradcheck wrt E (widx 0) -- the LONGEST chain (head+norm+FFN+attn+RoPE+softmax+embed) ----
214 let a4_ok: i64 = lm_gc_w(tape,vals,grads,st,W,ids,tgt,T,dm,ffn,V,scale,leaves,0,h,16384,floor_q,worst)
215 g_puts(" [measure] full-LM dL/dE worst rel grad err = " as *u8); g_pn(worst[0]); g_puts(" /1000 (tol=250)\n" as *u8)
216 pass=pass+g_check("A4: full-LM gradcheck wrt E through the WHOLE model == finite differences (end-to-end backprop)" as *u8, a4_ok); total=total+1
217
218 // ---- D: neg-control teeth (Wlm grad) ----
219 let nLd: i64 = lm_fwd(tape,vals,st,W,ids,tgt,T,dm,ffn,V,scale,leaves)
220 nfa_backward(tape,vals,grads,st[0],nLd)
221 let dana: i64 = nfa_grad(tape,grads,leaves[8],0)
222 let old0: i64 = Wlm[0]; Wlm[0]=old0+h; let lpd: i64=lm_lossval(tape,vals,st,W,ids,tgt,T,dm,ffn,V,scale); Wlm[0]=old0-h; let lmd: i64=lm_lossval(tape,vals,st,W,ids,tgt,T,dm,ffn,V,scale); Wlm[0]=old0
223 let dfd: i64 = ((lpd-lmd)*Q16)/(2*h)
224 let dbad: i64 = 0 - dana
225 var dden: i64 = g_abs(dana); if dden<floor_q { dden=floor_q }
226 var caught: i64 = 1
227 if g_abs(dfd-dbad) < ((8192*dden)>>16) { caught=0 }
228 pass=pass+g_check("D: neg-control -- a WRONG LM gradient is rejected (teeth)" as *u8, caught); total=total+1
229
230 // ---- B: the LM FITS (memorizes a FIXED sequence) next-token (train E + Wlm through the full forward; grad traverses the whole block) ----
231 let gbuf: *i64 = sys_mmap(64*8) as *i64
232 var lf: i64=0; var ll: i64=0
233 var ep: i64=0
234 while ep < 8000 {
235 let nLoss: i64 = lm_fwd(tape,vals,st,W,ids,tgt,T,dm,ffn,V,scale,leaves)
236 nfa_backward(tape,vals,grads,st[0],nLoss)
237 if ep==0 { lf = nfa_val(tape,vals,nLoss,0) }
238 ll = nfa_val(tape,vals,nLoss,0)
239 // update E (widx 0) and Wlm (widx 8)
240 let nE2: i64 = leaves[0]; let cE: i64 = V*dm
241 var z: i64=0
242 while z<cE { gbuf[z]=nfa_grad(tape,grads,nE2,z); z=z+1 }
243 nfa_sgd(E, gbuf, cE, 2048)
244 let nWl: i64 = leaves[8]; let cWl: i64 = dm*V
245 z=0
246 while z<cWl { gbuf[z]=nfa_grad(tape,grads,nWl,z); z=z+1 }
247 nfa_sgd(Wlm, gbuf, cWl, 2048)
248 ep=ep+1
249 }
250 g_puts(" [measure] LM next-token CE loss: start=" as *u8); g_pn(lf); g_puts(" end=" as *u8); g_pn(ll); g_puts(" (ln(V)=ln4 ~ 90852 Q16)\n" as *u8)
251 var fits: i64 = 1
252 if ll*2 > lf { fits=0 } // >= 50% CE reduction = it fit the fixed sequence (memorization, not generalization)
253 if lf <= 0 { fits=0 }
254 pass=pass+g_check("B: the LM FITS (memorizes a FIXED sequence) -- next-token CE loss drops >=50% via end-to-end backprop (E+Wlm trained)" as *u8, fits); total=total+1
255
256 // ---- C: bit-exact ----
257 let E2: *i64 = sys_mmap(V*dm*8) as *i64; lm_init(E2,V*dm,1)
258 let Wlm2:*i64 = sys_mmap(dm*V*8) as *i64; lm_init(Wlm2,dm*V,9)
259 let W2: *i64 = sys_mmap(9*8) as *i64
260 W2[0]=E2 as i64; W2[1]=Wq as i64; W2[2]=Wk as i64; W2[3]=Wv as i64; W2[4]=Wo as i64; W2[5]=Wg as i64; W2[6]=Wu as i64; W2[7]=Wd as i64; W2[8]=Wlm2 as i64
261 let lvc: *i64 = sys_mmap(10*8) as *i64
262 let gbuf2: *i64 = sys_mmap(64*8) as *i64
263 var ep2: i64=0
264 while ep2 < 8000 {
265 let nLoss: i64 = lm_fwd(tape,vals,st,W2,ids,tgt,T,dm,ffn,V,scale,lvc)
266 nfa_backward(tape,vals,grads,st[0],nLoss)
267 let nE2: i64=lvc[0]; var z: i64=0
268 while z<V*dm { gbuf2[z]=nfa_grad(tape,grads,nE2,z); z=z+1 }
269 nfa_sgd(E2, gbuf2, V*dm, 2048)
270 let nWl: i64=lvc[8]; z=0
271 while z<dm*V { gbuf2[z]=nfa_grad(tape,grads,nWl,z); z=z+1 }
272 nfa_sgd(Wlm2, gbuf2, dm*V, 2048)
273 ep2=ep2+1
274 }
275 var bitexact: i64 = 1
276 var zc: i64=0
277 while zc<V*dm { if E2[zc]!=E[zc] { bitexact=0 } zc=zc+1 }
278 zc=0
279 while zc<dm*V { if Wlm2[zc]!=Wlm[zc] { bitexact=0 } zc=zc+1 }
280 pass=pass+g_check("C: bit-exact -- training the LM twice gives IDENTICAL integer weights (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(LLOG, 420)
285 if logf >= 0 {
286 l_ws(logf,"NOFLOATLM 1-block 1-head V=4 A1_embed=" as *u8); l_wn(logf,e_ok); l_ws(logf," A2_softce=" as *u8); l_wn(logf,c_ok)
287 l_ws(logf," A3_Wlm=" as *u8); l_wn(logf,a3_ok); l_ws(logf," A4_E_fullchain=" as *u8); l_wn(logf,a4_ok); l_ws(logf," D=" as *u8); l_wn(logf,caught)
288 l_ws(logf," B_fits=" as *u8); l_wn(logf,fits); l_ws(logf," CE_start=" as *u8); l_wn(logf,lf); l_ws(logf," CE_end=" as *u8); l_wn(logf,ll); l_ws(logf," C_bitexact=" as *u8); l_wn(logf,bitexact)
289 if okall==1 { l_ws(logf," verdict=GREEN\n" as *u8) } else { l_ws(logf," verdict=RED\n" as *u8) }
290 sys_close(logf)
291 }
292 g_puts("---- nofloat_lm 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 tiny transformer LM trains end-to-end on next-token prediction 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}