code wiki / _hdl_build / nx_nofloat_lm_gate.nx

nx_nofloat_lm_gate.nx source

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