code wiki / _hdl_build / nx_lwq24_probe.nx

nx_lwq24_probe.nx source

↩ module page · 146 lines · 5045 B

1// nx_lwq24_probe.nx -- LAYERED probe for the LWC-2 FILL FAIL (2026-08-01). 2// P1: fq4m_fill_q24 + fq4m_rows_cached_q24 SERIALLY (no pool, no lazy-weight) vs the scalar oracle. 3// P2: the full nx_f32_lazy_matmul dispatch on the same data. 4// Whichever layer first diverges owns the bug. Same exact-regime synthesis as nx_lw_cache_gate 5// (d=1.0 f16, dmin=0, sc=1 -> dequant == q4 integers; int activations). 6// expect_exit: 0 license_tier: ORIGINAL No hw writes (Rule 26). 7import "nx_f32_lazy_weight.nx" 8import "nx_fmt.nx" 9const PB_MAGIC_1103515245: i64 = 1103515245 10const PB_MAGIC_12345: i64 = 12345 11const PB_MAGIC_2147483647: i64 = 2147483647 12const PB_MAGIC_20260708: i64 = 20260708 13const PB_MAGIC_424242: i64 = 424242 14 15const PB_M: i64 = 3 16const PB_K: i64 = 512 17const PB_N: i64 = 37 18 19func p_lcg(s: i64) -> i64 { 20 var v: i64 = s * PB_MAGIC_1103515245 + PB_MAGIC_12345 21 v = v & PB_MAGIC_2147483647 22 return v 23} 24func p_block_dense(buf: *u8, off: i64, seed: i64) -> i64 { 25 buf[off + 0] = 0x00 as u8 26 buf[off + 1] = 0x3C as u8 27 buf[off + 2] = 0 as u8 28 buf[off + 3] = 0 as u8 29 var i: i64 = 0 30 while i < 4 { 31 buf[off + 4 + i] = 0x01 as u8 32 buf[off + 8 + i] = 0x00 as u8 33 buf[off + 12 + i] = 0x01 as u8 34 i = i + 1 35 } 36 var s: i64 = seed 37 var z: i64 = 0 38 while z < 128 { 39 s = p_lcg(s) 40 buf[off + 16 + z] = (s & 255) as u8 41 z = z + 1 42 } 43 return off + 144 44} 45func p_fill_weights(buf: *u8, n_rows: i64, k: i64, seed: i64) -> i64 { 46 let bpr: i64 = (k / 256) * 144 47 var s: i64 = seed 48 var r: i64 = 0 49 while r < n_rows { 50 var b: i64 = 0 51 while b < k / 256 { 52 s = p_lcg(s) 53 p_block_dense(buf, r * bpr + b * 144, s) 54 b = b + 1 55 } 56 r = r + 1 57 } 58 return 0 59} 60func p_fill_a(p: *i64, count: i64, seed: i64, half: i64) -> i64 { 61 var s: i64 = seed 62 var i: i64 = 0 63 while i < count { 64 s = p_lcg(s) 65 let v: i64 = (s % (half + half)) - half 66 p[i] = nx_i32_to_f32(v) 67 i = i + 1 68 } 69 return 0 70} 71// first differing index, or -1 72func p_diff(a: *i64, b: *i64, count: i64) -> i64 { 73 var i: i64 = 0 74 while i < count { 75 if a[i] != b[i] { return i } 76 i = i + 1 77 } 78 return 0 - 1 79} 80 81func main() -> i64 { 82 let a_n: i64 = PB_M * PB_K 83 let b_n: i64 = PB_N * (PB_K / 256) * 144 84 let c_n: i64 = PB_M * PB_N 85 let A: *i64 = sys_mmap(a_n * 8) as *i64 86 let B: *u8 = sys_mmap(b_n) 87 let Cs: *i64 = sys_mmap(c_n * 8) as *i64 88 let Cq: *i64 = sys_mmap(c_n * 8) as *i64 89 p_fill_a(A, a_n, PB_MAGIC_20260708, 5) 90 p_fill_weights(B, PB_N, PB_K, PB_MAGIC_424242) 91 92 let v1: nx_int = nx_f32_q4k_matmul(A, B, 0, Cs, PB_M, PB_K, PB_N) 93 fmt_puts("P0 scalar rc=" as *u8); fmt_putn(v1); fmt_puts("\n" as *u8) 94 95 // ---- P1: serial fill + serial cached dot, NO pool, NO lazy-weight ---- 96 let cache: *u8 = sys_mmap(PB_N * PB_K * 4) 97 let fr: i64 = fq4m_fill_q24(cache, B, 0, PB_K, PB_N, 0, PB_N) 98 fmt_puts("P1 fill rc=" as *u8); fmt_putn(fr) 99 fmt_puts(" cache[0..3]=" as *u8) 100 fmt_putn(_fq4m_q24_at(cache, 0)); fmt_puts("," as *u8) 101 fmt_putn(_fq4m_q24_at(cache, 1)); fmt_puts("," as *u8) 102 fmt_putn(_fq4m_q24_at(cache, 2)); fmt_puts("," as *u8) 103 fmt_putn(_fq4m_q24_at(cache, 3)); fmt_puts("\n" as *u8) 104 105 let pq: *i64 = sys_mmap(a_n * 8) as *i64 106 _fq4m_pack_q10(A, a_n, pq) 107 let cr: i64 = fq4m_rows_cached_q24(pq, cache, Cq, PB_M, PB_K, PB_N, 0, PB_N) 108 let d1: i64 = p_diff(Cq, Cs, c_n) 109 fmt_puts("P1 cached-serial rc=" as *u8); fmt_putn(cr) 110 fmt_puts(" first_diff=" as *u8); fmt_putn(d1) 111 if d1 >= 0 { 112 fmt_puts(" got=" as *u8); fmt_putn(Cq[d1]) 113 fmt_puts(" want=" as *u8); fmt_putn(Cs[d1]) 114 } 115 fmt_puts("\n" as *u8) 116 117 // ---- P1b: the streamed fused oracle on the same data ---- 118 let Cf: *i64 = sys_mmap(c_n * 8) as *i64 119 let vf: nx_int = nx_f32_q4k_matmul_fused(A, B, 0, Cf, PB_M, PB_K, PB_N) 120 let df: i64 = p_diff(Cf, Cs, c_n) 121 fmt_puts("P1b fused-serial rc=" as *u8); fmt_putn(vf) 122 fmt_puts(" first_diff_vs_scalar=" as *u8); fmt_putn(df) 123 if df >= 0 { 124 fmt_puts(" got=" as *u8); fmt_putn(Cf[df]) 125 fmt_puts(" want=" as *u8); fmt_putn(Cs[df]) 126 } 127 let dqf: i64 = p_diff(Cq, Cf, c_n) 128 fmt_puts(" cached_vs_fused_diff=" as *u8); fmt_putn(dqf) 129 fmt_puts("\n" as *u8) 130 131 // ---- P2: the full lazy dispatch ---- 132 let W: *NxF32LazyWeight = nx_f32_lazy_weight_new_q4k(B, 0, PB_K, PB_N) 133 let Cd: *i64 = sys_mmap(c_n * 8) as *i64 134 let v2: nx_int = nx_f32_lazy_matmul(A, W, Cd, PB_M, PB_K, PB_N) 135 let d2: i64 = p_diff(Cd, Cs, c_n) 136 fmt_puts("P2 lazy rc=" as *u8); fmt_putn(v2) 137 fmt_puts(" pk_state=" as *u8); fmt_putn(W.pk_state) 138 fmt_puts(" used=" as *u8); fmt_putn(nx_lw_cache_used()) 139 fmt_puts(" first_diff=" as *u8); fmt_putn(d2) 140 if d2 >= 0 { 141 fmt_puts(" got=" as *u8); fmt_putn(Cd[d2]) 142 fmt_puts(" want=" as *u8); fmt_putn(Cs[d2]) 143 } 144 fmt_puts("\n" as *u8) 145 return 0 146}