code wiki / (root) / nx_transformer_stack_test.nx

nx_transformer_stack_test.nx source

↩ module page · 207 lines · 8025 B

1// nx_transformer_stack_test.nx -- smoke for nx_transformer_stack.nx. 2// 3// Builds a 1-layer synthetic Llama-shape GGUF with ALL-ZERO weights 4// (so the forward pass becomes an identity), feeds x_in through the 5// stack, and verifies x_in is unchanged. 6// 7// Test spec: hidden=2, head_dim=2, ffn_dim=4, n_tokens=1. 8// Weights = 0 means: 9// - RMSNorm(x, 0) = 0 (gamma=0 zeros out the norm output) 10// - matmul(0, W) = 0 (zero input/weight = zero output) 11// - attention(0, 0, 0) = 0 (softmax of all-zero scores * zero V) 12// - residual: x + 0 = x (UNCHANGED) 13// - FFN: same identity-via-zero pattern 14// So output x == input x after the entire forward pass. 15 16import "nx_syscalls.nx" 17import "nx_tier.nx" 18import "nx_le.nx" 19import "nx_tensor.nx" 20import "nx_gguf.nx" 21import "nx_gguf_load.nx" 22import "nx_transformer_stack.nx" 23 24// Write tensor_info entry; return new offset. 25func _write_ti(buf: *u8, off: i64, 26 name: *u8, name_len: i64, 27 n_dims: i64, dim_0: i64, dim_1: i64, 28 ggml_type: i64, data_offset: i64) -> i64 { 29 nx_le_write_u64(buf, off, name_len) 30 var o: i64 = off + 8 31 var i: i64 = 0 32 while i < name_len { buf[o + i] = name[i]; i = i + 1 } 33 o = o + name_len 34 nx_le_write_u32(buf, o, n_dims); o = o + 4 35 nx_le_write_u64(buf, o, dim_0); o = o + 8 36 if n_dims >= 2 { nx_le_write_u64(buf, o, dim_1); o = o + 8 } 37 nx_le_write_u32(buf, o, ggml_type); o = o + 4 38 nx_le_write_u64(buf, o, data_offset); o = o + 8 39 return o 40} 41 42// Build a layer-0 tensor name "blk.0.{suffix}" into buf-of-size 32. 43// Returns name length. 44func _mk_blk_name(suffix: *u8, suffix_len: nx_int, out: *u8) -> nx_int { 45 out[0]=0x62; out[1]=0x6c; out[2]=0x6b; out[3]=0x2e 46 out[4]=0x30 // '0' 47 out[5]=0x2e // '.' 48 var i: nx_int = 0 49 while i < suffix_len { 50 out[6 + i] = suffix[i] 51 i = i + 1 52 } 53 return 6 + suffix_len 54} 55 56func main() -> i64 { 57 // ----- Verdict gate ----- 58 var vi: nx_int = 0 59 while vi < NX_TS_N_VERDICTS { 60 if nx_ts_verdict_is_valid(vi) != 1 { return 5 + vi } 61 vi = vi + 1 62 } 63 64 let buf: *u8 = sys_mmap(2048) 65 buf[0]=0x47; buf[1]=0x47; buf[2]=0x55; buf[3]=0x46 66 buf[4]=3 67 nx_le_write_u64(buf, 8, 9) // 9 tensors 68 nx_le_write_u64(buf, 16, 0) 69 70 // ----- Suffix constants ----- 71 let s_an: *u8 = sys_mmap(16) 72 s_an[0]=0x61; s_an[1]=0x74; s_an[2]=0x74; s_an[3]=0x6e 73 s_an[4]=0x5f; s_an[5]=0x6e; s_an[6]=0x6f; s_an[7]=0x72 74 s_an[8]=0x6d; s_an[9]=0x2e; s_an[10]=0x77; s_an[11]=0x65 75 s_an[12]=0x69; s_an[13]=0x67; s_an[14]=0x68; s_an[15]=0x74 76 77 let s_q: *u8 = sys_mmap(13) 78 s_q[0]=0x61; s_q[1]=0x74; s_q[2]=0x74; s_q[3]=0x6e 79 s_q[4]=0x5f; s_q[5]=0x71; s_q[6]=0x2e; s_q[7]=0x77 80 s_q[8]=0x65; s_q[9]=0x69; s_q[10]=0x67; s_q[11]=0x68 81 s_q[12]=0x74 82 83 let s_k: *u8 = sys_mmap(13) 84 s_k[0]=0x61; s_k[1]=0x74; s_k[2]=0x74; s_k[3]=0x6e 85 s_k[4]=0x5f; s_k[5]=0x6b; s_k[6]=0x2e; s_k[7]=0x77 86 s_k[8]=0x65; s_k[9]=0x69; s_k[10]=0x67; s_k[11]=0x68 87 s_k[12]=0x74 88 89 let s_v: *u8 = sys_mmap(13) 90 s_v[0]=0x61; s_v[1]=0x74; s_v[2]=0x74; s_v[3]=0x6e 91 s_v[4]=0x5f; s_v[5]=0x76; s_v[6]=0x2e; s_v[7]=0x77 92 s_v[8]=0x65; s_v[9]=0x69; s_v[10]=0x67; s_v[11]=0x68 93 s_v[12]=0x74 94 95 let s_o: *u8 = sys_mmap(18) 96 s_o[0]=0x61; s_o[1]=0x74; s_o[2]=0x74; s_o[3]=0x6e 97 s_o[4]=0x5f; s_o[5]=0x6f; s_o[6]=0x75; s_o[7]=0x74 98 s_o[8]=0x70; s_o[9]=0x75; s_o[10]=0x74; s_o[11]=0x2e 99 s_o[12]=0x77; s_o[13]=0x65; s_o[14]=0x69; s_o[15]=0x67 100 s_o[16]=0x68; s_o[17]=0x74 101 102 let s_fn: *u8 = sys_mmap(15) 103 s_fn[0]=0x66; s_fn[1]=0x66; s_fn[2]=0x6e; s_fn[3]=0x5f 104 s_fn[4]=0x6e; s_fn[5]=0x6f; s_fn[6]=0x72; s_fn[7]=0x6d 105 s_fn[8]=0x2e; s_fn[9]=0x77; s_fn[10]=0x65; s_fn[11]=0x69 106 s_fn[12]=0x67; s_fn[13]=0x68; s_fn[14]=0x74 107 108 let s_fg: *u8 = sys_mmap(15) 109 s_fg[0]=0x66; s_fg[1]=0x66; s_fg[2]=0x6e; s_fg[3]=0x5f 110 s_fg[4]=0x67; s_fg[5]=0x61; s_fg[6]=0x74; s_fg[7]=0x65 111 s_fg[8]=0x2e; s_fg[9]=0x77; s_fg[10]=0x65; s_fg[11]=0x69 112 s_fg[12]=0x67; s_fg[13]=0x68; s_fg[14]=0x74 113 114 let s_fu: *u8 = sys_mmap(13) 115 s_fu[0]=0x66; s_fu[1]=0x66; s_fu[2]=0x6e; s_fu[3]=0x5f 116 s_fu[4]=0x75; s_fu[5]=0x70; s_fu[6]=0x2e; s_fu[7]=0x77 117 s_fu[8]=0x65; s_fu[9]=0x69; s_fu[10]=0x67; s_fu[11]=0x68 118 s_fu[12]=0x74 119 120 let s_fd: *u8 = sys_mmap(15) 121 s_fd[0]=0x66; s_fd[1]=0x66; s_fd[2]=0x6e; s_fd[3]=0x5f 122 s_fd[4]=0x64; s_fd[5]=0x6f; s_fd[6]=0x77; s_fd[7]=0x6e 123 s_fd[8]=0x2e; s_fd[9]=0x77; s_fd[10]=0x65; s_fd[11]=0x69 124 s_fd[12]=0x67; s_fd[13]=0x68; s_fd[14]=0x74 125 126 // Full names "blk.0.{suffix}" 127 let n_an: *u8 = sys_mmap(32); let l_an: nx_int = _mk_blk_name(s_an, 16, n_an) 128 let n_q: *u8 = sys_mmap(32); let l_q: nx_int = _mk_blk_name(s_q, 13, n_q) 129 let n_k: *u8 = sys_mmap(32); let l_k: nx_int = _mk_blk_name(s_k, 13, n_k) 130 let n_v: *u8 = sys_mmap(32); let l_v: nx_int = _mk_blk_name(s_v, 13, n_v) 131 let n_o: *u8 = sys_mmap(32); let l_o: nx_int = _mk_blk_name(s_o, 18, n_o) 132 let n_fn: *u8 = sys_mmap(32); let l_fn: nx_int = _mk_blk_name(s_fn, 15, n_fn) 133 let n_fg: *u8 = sys_mmap(32); let l_fg: nx_int = _mk_blk_name(s_fg, 15, n_fg) 134 let n_fu: *u8 = sys_mmap(32); let l_fu: nx_int = _mk_blk_name(s_fu, 13, n_fu) 135 let n_fd: *u8 = sys_mmap(32); let l_fd: nx_int = _mk_blk_name(s_fd, 15, n_fd) 136 137 // ----- Tensor sizes (F32, in bytes) ----- 138 // attn_norm [2] = 8 139 // attn_q/k/v [2,2] = 16 each 140 // attn_output [2,2] = 16 141 // ffn_norm [2] = 8 142 // ffn_gate [2,4] = 32 143 // ffn_up [2,4] = 32 144 // ffn_down [4,2] = 32 145 // Cumulative offsets in data section: 0, 8, 24, 40, 56, 72, 80, 112, 144 146 147 // Write tensor_info entries (each F32). 148 var p: i64 = 24 149 p = _write_ti(buf, p, n_an, l_an, 1, 2, 1, NX_GGML_TYPE_F32, 0) 150 p = _write_ti(buf, p, n_q, l_q, 2, 2, 2, NX_GGML_TYPE_F32, 8) 151 p = _write_ti(buf, p, n_k, l_k, 2, 2, 2, NX_GGML_TYPE_F32, 24) 152 p = _write_ti(buf, p, n_v, l_v, 2, 2, 2, NX_GGML_TYPE_F32, 40) 153 p = _write_ti(buf, p, n_o, l_o, 2, 2, 2, NX_GGML_TYPE_F32, 56) 154 p = _write_ti(buf, p, n_fn, l_fn, 1, 2, 1, NX_GGML_TYPE_F32, 72) 155 p = _write_ti(buf, p, n_fg, l_fg, 2, 2, 4, NX_GGML_TYPE_F32, 80) 156 p = _write_ti(buf, p, n_fu, l_fu, 2, 2, 4, NX_GGML_TYPE_F32, 112) 157 p = _write_ti(buf, p, n_fd, l_fd, 2, 4, 2, NX_GGML_TYPE_F32, 144) 158 159 // data_off = align_up(p, 32). 160 let data_off: i64 = (p + 31) / 32 * 32 161 162 // Tensor data: all zeros (sys_mmap already returns zeroed memory 163 // on the substrate's mmap; but we write zeros explicitly for the 164 // 176 bytes that hold weight values). 165 var zi: nx_int = 0 166 while zi < 176 { 167 buf[data_off + zi] = 0 168 zi = zi + 1 169 } 170 171 let hdr: *NxGgufHeader = sys_mmap(NX_GGUF_HDR_BYTES) as *NxGgufHeader 172 let vp: nx_int = nx_gguf_parse(buf, 2048, hdr) 173 if vp != NX_GGUF_OK { return 20 + vp } 174 if hdr.n_tensors != 9 { return 30 } 175 176 // ----- Build x_in [1, 2] = (42, 17) Q10 ----- 177 let sh: *i64 = sys_mmap(2 * 8) as *i64 178 sh[0] = 1; sh[1] = 2 179 let err: *i64 = sys_mmap(8) as *i64 180 err[0] = 0 181 let x: *NxTensor = nx_t_alloc(NX_DT_I64, sh, 2, err) 182 if err[0] != 0 { return 40 } 183 let px: *i64 = x.storage as *i64 184 px[0] = 42 * 1024 // 42 in Q10 185 px[1] = 17 * 1024 // 17 in Q10 186 187 // positions [1] = (0) 188 let pos: *i64 = sys_mmap(8) as *i64 189 pos[0] = 0 190 191 // ----- Call the stack forward ----- 192 // n_layers = 1, hidden = 2, head_dim = 2, ffn_dim = 4 193 // rope_base = 10000, attn_scale_q10 = 724 (~ 1/sqrt(2)) 194 // final_norm_gamma = null (skip final norm; we want pure identity) 195 let v: nx_int = nx_transformer_stack_forward( 196 x, pos, buf, hdr, 197 1, 2, 2, 4, 198 10000, 724, 199 0 as *i64) 200 if v != NX_TS_OK { return 100 + v } 201 202 // ----- Verify x is unchanged (all-zero weights = identity) ----- 203 if px[0] != 42 * 1024 { return 200 } 204 if px[1] != 17 * 1024 { return 201 } 205 206 return 0 207}