nx_live_fire_gguf_test.nx source
↩ module page · 247 lines · 9472 B
1// nx_live_fire_gguf_test.nx -- the live-fire smoke.
2
3import "nx_syscalls.nx"
4import "nx_tier.nx"
5import "nx_le.nx"
6import "nx_tensor.nx"
7import "nx_strconv.nx"
8import "nx_gguf.nx"
9import "nx_gguf_load.nx"
10import "nx_placement.nx"
11import "nx_gguf_load_lazy.nx"
12import "nx_live_fire_gguf.nx"
13
14// Write tensor_info entry; return new offset.
15func _write_ti(buf: *u8, off: i64,
16 name: *u8, name_len: i64,
17 n_dims: i64, dim_0: i64, dim_1: i64,
18 ggml_type: i64, data_offset: i64) -> i64 {
19 nx_le_write_u64(buf, off, name_len)
20 var o: i64 = off + 8
21 var i: i64 = 0
22 while i < name_len { buf[o + i] = name[i]; i = i + 1 }
23 o = o + name_len
24 nx_le_write_u32(buf, o, n_dims); o = o + 4
25 nx_le_write_u64(buf, o, dim_0); o = o + 8
26 if n_dims >= 2 { nx_le_write_u64(buf, o, dim_1); o = o + 8 }
27 nx_le_write_u32(buf, o, ggml_type); o = o + 4
28 nx_le_write_u64(buf, o, data_offset); o = o + 8
29 return o
30}
31
32func main() -> i64 {
33 // ----- PHASE 0: Build the GGUF in-memory -----
34 //
35 // 3 top-level tensors so the test exercises a realistic structure:
36 // "score" F32 [2,2] = 16 bytes data
37 // "norm" F32 [4] = 16 bytes data
38 // "weight" Q8_0 [32] = 34 bytes data
39 let src: *u8 = sys_mmap(2048)
40 src[0]=0x47; src[1]=0x47; src[2]=0x55; src[3]=0x46
41 src[4]=3
42 nx_le_write_u64(src, 8, 3)
43 nx_le_write_u64(src, 16, 0)
44
45 let n_sc: *u8 = sys_mmap(5)
46 n_sc[0]=0x73; n_sc[1]=0x63; n_sc[2]=0x6F; n_sc[3]=0x72; n_sc[4]=0x65
47
48 let n_nm: *u8 = sys_mmap(4)
49 n_nm[0]=0x6E; n_nm[1]=0x6F; n_nm[2]=0x72; n_nm[3]=0x6D
50
51 let n_wt: *u8 = sys_mmap(6)
52 n_wt[0]=0x77; n_wt[1]=0x65; n_wt[2]=0x69; n_wt[3]=0x67; n_wt[4]=0x68; n_wt[5]=0x74
53
54 var p: i64 = 24
55 p = _write_ti(src, p, n_sc, 5, 2, 2, 2, NX_GGML_TYPE_F32, 0)
56 p = _write_ti(src, p, n_nm, 4, 1, 4, 1, NX_GGML_TYPE_F32, 16)
57 p = _write_ti(src, p, n_wt, 6, 1, 32, 1, NX_GGML_TYPE_Q8_0, 32)
58 let data_off: i64 = (p + 31) / 32 * 32
59
60 // score [2,2] F32: 1.0, 2.0, 0.5, -1.0
61 nx_le_write_u32(src, data_off + 0, 0x3F800000)
62 nx_le_write_u32(src, data_off + 4, 0x40000000)
63 nx_le_write_u32(src, data_off + 8, 0x3F000000)
64 nx_le_write_u32(src, data_off + 12, 0xBF800000)
65 // norm [4] F32: 1.0, 1.0, 1.0, 1.0
66 nx_le_write_u32(src, data_off + 16, 0x3F800000)
67 nx_le_write_u32(src, data_off + 20, 0x3F800000)
68 nx_le_write_u32(src, data_off + 24, 0x3F800000)
69 nx_le_write_u32(src, data_off + 28, 0x3F800000)
70 // weight [32] Q8_0: scale=0.5 (f16 0x3800), qs[i] = i
71 let q8_off: i64 = data_off + 32
72 nx_le_write_u16(src, q8_off + 0, 0x3800)
73 var qi: nx_int = 0
74 while qi < 32 {
75 src[q8_off + 2 + qi] = qi
76 qi = qi + 1
77 }
78 let total_bytes: i64 = data_off + 32 + 34
79
80 // ----- PHASE 1: WRITE to disk via sys_write -----
81 let path: *u8 = sys_mmap(64)
82 path[0]=0x2F; path[1]=0x74; path[2]=0x6D; path[3]=0x70 // "/tmp"
83 path[4]=0x2F // "/"
84 path[5]=0x6E; path[6]=0x78; path[7]=0x5F // "nx_"
85 path[8]=0x6C; path[9]=0x69; path[10]=0x76; path[11]=0x65 // "live"
86 path[12]=0x5F; path[13]=0x66; path[14]=0x69; path[15]=0x72
87 path[16]=0x65; path[17]=0x2E; path[18]=0x67; path[19]=0x67
88 path[20]=0x75; path[21]=0x66 // "_fire.gguf"
89 path[22]=0
90 // Full path: "/tmp/nx_live_fire.gguf"
91
92 let t0_w: i64 = sys_now_ms()
93 let fd: i64 = sys_openat_wr(path, 0x1A4) // 0644 octal = 420 = 0x1A4
94 if fd < 0 { return 30 }
95 let n_w: i64 = sys_write(fd, src, total_bytes)
96 let v_cl: i64 = sys_close(fd)
97 let t1_w: i64 = sys_now_ms()
98 if n_w != total_bytes { return 31 }
99 if v_cl != 0 { return 32 }
100 let elapsed_w: i64 = t1_w - t0_w
101 if elapsed_w > NX_LF_WRITE_BUDGET_MS { return 33 }
102
103 // ----- PHASE 2: READ back via sys_read_file -----
104 let t0_r: i64 = sys_now_ms()
105 let out_len: *i64 = sys_mmap(8) as *i64
106 out_len[0] = 0
107 let read_buf: *u8 = sys_read_file(path, out_len)
108 let t1_r: i64 = sys_now_ms()
109 if read_buf == (0 as *u8) { return 40 }
110 if out_len[0] != total_bytes { return 41 }
111 let elapsed_r: i64 = t1_r - t0_r
112 if elapsed_r > NX_LF_READ_BUDGET_MS { return 42 }
113
114 // Bit-exact compare against the source we wrote (proves the
115 // kernel didn't lose / reorder / pad anything).
116 var bi: i64 = 0
117 while bi < total_bytes {
118 if read_buf[bi] != src[bi] { return 50 }
119 bi = bi + 1
120 }
121
122 // ----- PHASE 3: parse the header -----
123 let t0_p: i64 = sys_now_ms()
124 let hdr: *NxGgufHeader = sys_mmap(NX_GGUF_HDR_BYTES) as *NxGgufHeader
125 let v_parse: nx_int = nx_gguf_parse(read_buf, out_len[0], hdr)
126 let t1_p: i64 = sys_now_ms()
127 if v_parse != NX_GGUF_OK { return 60 + v_parse }
128 if hdr.n_tensors != 3 { return 70 }
129 let elapsed_p: i64 = t1_p - t0_p
130 if elapsed_p > NX_LF_PARSE_BUDGET_MS { return 71 }
131
132 // ----- PHASE 4: LAZY-load all 3 tensor handles -----
133 let t0_l: i64 = sys_now_ms()
134 let err: *i64 = sys_mmap(8) as *i64
135 err[0] = 0
136 let lazy_score: *NxPlacedTensor = nx_gguf_load_tensor_lazy(
137 read_buf, hdr, n_sc, 5, err)
138 if err[0] != NX_GL_OK { return 80 }
139 err[0] = 0
140 let lazy_norm: *NxPlacedTensor = nx_gguf_load_tensor_lazy(
141 read_buf, hdr, n_nm, 4, err)
142 if err[0] != NX_GL_OK { return 81 }
143 err[0] = 0
144 let lazy_weight: *NxPlacedTensor = nx_gguf_load_tensor_lazy(
145 read_buf, hdr, n_wt, 6, err)
146 if err[0] != NX_GL_OK { return 82 }
147 let t1_l: i64 = sys_now_ms()
148 let elapsed_l: i64 = t1_l - t0_l
149 if elapsed_l > NX_LF_LAZY_LOAD_BUDGET_MS { return 83 }
150
151 // Quantitative claim: 3 lazy handles total 88*3 = 264 bytes
152 // regardless of tensor sizes. No dequantized storage yet.
153 if nx_placed_tensor_storage_bytes(lazy_score) != 0 { return 90 }
154 if nx_placed_tensor_storage_bytes(lazy_norm) != 0 { return 91 }
155 if nx_placed_tensor_storage_bytes(lazy_weight) != 0 { return 92 }
156
157 // ----- PHASE 5: MATERIALIZE on demand + verify values -----
158 let t0_m: i64 = sys_now_ms()
159 let t_score: *NxTensor = nx_placed_tensor_get(lazy_score)
160 let t_norm: *NxTensor = nx_placed_tensor_get(lazy_norm)
161 let t_weight: *NxTensor = nx_placed_tensor_get(lazy_weight)
162 let t1_m: i64 = sys_now_ms()
163 if t_score == (0 as *NxTensor) { return 100 }
164 if t_norm == (0 as *NxTensor) { return 101 }
165 if t_weight == (0 as *NxTensor) { return 102 }
166 let elapsed_m: i64 = t1_m - t0_m
167 if elapsed_m > NX_LF_MATERIALIZE_BUDGET_MS { return 103 }
168
169 // Verify exact Q10 values match what we wrote.
170 let sp: *i64 = t_score.storage as *i64
171 if sp[0] != 1024 { return 110 } // 1.0
172 if sp[1] != 2048 { return 111 } // 2.0
173 if sp[2] != 512 { return 112 } // 0.5
174 if sp[3] != (0 - 1024) { return 113 } // -1.0
175
176 let np: *i64 = t_norm.storage as *i64
177 if np[0] != 1024 { return 120 }
178 if np[3] != 1024 { return 121 }
179
180 let wp: *i64 = t_weight.storage as *i64
181 // scale_q10 = 512; qs[i] = i; expected[i] = 512 * i
182 var ki: nx_int = 0
183 while ki < 32 {
184 if wp[ki] != 512 * ki { return 130 + ki }
185 ki = ki + 1
186 }
187
188 // ----- PHASE 6: write timing report to disk -----
189 //
190 // Encode the elapsed values as a tiny TSV that the smoke wrapper
191 // can cat after PASS so the user sees real numbers. Format:
192 // "write_ms\tread_ms\tparse_ms\tlazy_ms\tmat_ms\ttotal_bytes\n"
193 let report_path: *u8 = sys_mmap(64)
194 report_path[0]=0x2F; report_path[1]=0x74; report_path[2]=0x6D; report_path[3]=0x70
195 report_path[4]=0x2F
196 report_path[5]=0x6E; report_path[6]=0x78; report_path[7]=0x5F
197 report_path[8]=0x6C; report_path[9]=0x69; report_path[10]=0x76; report_path[11]=0x65
198 report_path[12]=0x5F; report_path[13]=0x66; report_path[14]=0x69; report_path[15]=0x72
199 report_path[16]=0x65; report_path[17]=0x2E; report_path[18]=0x74; report_path[19]=0x73
200 report_path[20]=0x76 // ".tsv"
201 report_path[21]=0
202 // Full: "/tmp/nx_live_fire.tsv"
203
204 let line: *u8 = sys_mmap(256)
205 var lo: i64 = 0
206 let dec: *u8 = sys_mmap(32)
207 var n_dec: i64 = 0
208
209 // helper inline: write integer + tab to line
210 n_dec = nx_strconv_format_i64(elapsed_w, dec)
211 var k: i64 = 0
212 while k < n_dec { line[lo] = dec[k]; lo = lo + 1; k = k + 1 }
213 line[lo] = 0x09; lo = lo + 1
214
215 n_dec = nx_strconv_format_i64(elapsed_r, dec)
216 k = 0
217 while k < n_dec { line[lo] = dec[k]; lo = lo + 1; k = k + 1 }
218 line[lo] = 0x09; lo = lo + 1
219
220 n_dec = nx_strconv_format_i64(elapsed_p, dec)
221 k = 0
222 while k < n_dec { line[lo] = dec[k]; lo = lo + 1; k = k + 1 }
223 line[lo] = 0x09; lo = lo + 1
224
225 n_dec = nx_strconv_format_i64(elapsed_l, dec)
226 k = 0
227 while k < n_dec { line[lo] = dec[k]; lo = lo + 1; k = k + 1 }
228 line[lo] = 0x09; lo = lo + 1
229
230 n_dec = nx_strconv_format_i64(elapsed_m, dec)
231 k = 0
232 while k < n_dec { line[lo] = dec[k]; lo = lo + 1; k = k + 1 }
233 line[lo] = 0x09; lo = lo + 1
234
235 n_dec = nx_strconv_format_i64(total_bytes, dec)
236 k = 0
237 while k < n_dec { line[lo] = dec[k]; lo = lo + 1; k = k + 1 }
238 line[lo] = 0x0A; lo = lo + 1 // newline
239
240 let fd_rep: i64 = sys_openat_wr(report_path, 0x1A4)
241 if fd_rep < 0 { return 200 }
242 let nw_rep: i64 = sys_write(fd_rep, line, lo)
243 sys_close(fd_rep)
244 if nw_rep != lo { return 201 }
245
246 return 0
247}