code wiki / _hdl_build / nx_f32_matmul_gate.nx
nx_f32_matmul_gate.nx source
↩ module page · 91 lines · 4304 B
1// nx_f32_matmul_gate.nx -- KAT proving the SOVEREIGN f32 GEMM is correct (the math-axis foothold).
2//
3// nx_f32_matmul is a bits-up f32 GEMM (no BLAS, no SIMD). For small integers f32 is bit-exact, so a
4// hand-computed integer reference is the exact expected output. This gate is the EVIDENCE that the
5// genesis "math" axis is NOT bare-locked: a sovereign CPU matmul exists + is correct (BLAS-level
6// PERFORMANCE is the remaining open rung).
7//
8// T1 kat-correct : [[1,2],[3,4]] @ [[5,6],[7,8]] == [[19,22],[43,50]] bit-exact
9// N1 teeth : the result does NOT equal a deliberately-wrong matrix (compare has teeth)
10// N2 bad-dim : m=0 -> NX_F32_MM_ERR_BAD_DIM (error handling)
11//
12// GREEN only if all three hold. Evidence -> knowledge/status/f32_matmul_gate.log.
13// Sovereign: imports nx_f32_matmul (-> nx_f32, nx_tier) + nx_framed_append + nx_syscalls. license_tier: ORIGINAL
14import "nx_f32_matmul.nx"
15import "nx_framed_append.nx"
16import "nx_syscalls.nx"
17
18const MMG_LOG: *u8 = "knowledge/status/f32_matmul_gate.log"
19
20func mm_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != 0 as u8 { n = n + 1 } sys_write(1, s, n); return 0 }
21func mm_cat(dst: *u8, off: i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != 0 as u8 { dst[off + i] = s[i]; i = i + 1 } return off + i }
22func mm_catn(dst: *u8, off: i64, v: i64) -> i64 {
23 var m: i64 = v; var o: i64 = off
24 if m < 0 { m = 0 - m }
25 let t: *u8 = sys_mmap(28); var k: i64 = 0
26 if m == 0 { t[0] = 48 as u8; k = 1 }
27 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
28 var i: i64 = 0
29 while i < k { dst[o + i] = t[k - 1 - i]; i = i + 1 }
30 return o + k
31}
32func mm_eq4(c: *i64, e: *i64) -> i64 { var i: i64 = 0; while i < 4 { if c[i] != e[i] { return 0 } i = i + 1 } return 1 }
33func mm_row(name: *u8, pass: i64) -> i64 {
34 let buf: *u8 = sys_mmap(528)
35 var o: i64 = 0
36 o = mm_cat(buf, o, "MMG row=\x00" as *u8)
37 o = mm_cat(buf, o, name)
38 if pass == 1 { o = mm_cat(buf, o, " verdict=PASS\x00" as *u8) } else { o = mm_cat(buf, o, " verdict=FAIL\x00" as *u8) }
39 buf[o] = 0 as u8
40 fa_appendz(MMG_LOG, buf, 512)
41 mm_puts(" "); mm_puts(name)
42 if pass == 1 { mm_puts(" PASS\n") } else { mm_puts(" FAIL\n") }
43 return 0
44}
45
46func main() -> i64 {
47 mm_puts("f32-matmul gate (sovereign GEMM KAT: the math-axis foothold)\n")
48 // IEEE-754 f32 bit patterns for small ints (bit-exact GEMM):
49 // 1=0x3F800000 2=0x40000000 3=0x40400000 4=0x40800000
50 // 5=0x40A00000 6=0x40C00000 7=0x40E00000 8=0x41000000
51 let A: *i64 = sys_mmap(4 * 8) as *i64
52 A[0] = 0x3F800000; A[1] = 0x40000000; A[2] = 0x40400000; A[3] = 0x40800000
53 let B: *i64 = sys_mmap(4 * 8) as *i64
54 B[0] = 0x40A00000; B[1] = 0x40C00000; B[2] = 0x40E00000; B[3] = 0x41000000
55 let C: *i64 = sys_mmap(4 * 8) as *i64
56 // expected [[19,22],[43,50]]: 19=0x41980000 22=0x41B00000 43=0x422C0000 50=0x42480000
57 let E: *i64 = sys_mmap(4 * 8) as *i64
58 E[0] = 0x41980000; E[1] = 0x41B00000; E[2] = 0x422C0000; E[3] = 0x42480000
59 // wrong: last entry 51.0=0x424C0000 instead of 50.0
60 let W: *i64 = sys_mmap(4 * 8) as *i64
61 W[0] = 0x41980000; W[1] = 0x41B00000; W[2] = 0x422C0000; W[3] = 0x424C0000
62
63 let rc: i64 = nx_f32_matmul(A, B, C, 2, 2, 2)
64 var t1: i64 = 0; if rc == NX_F32_MM_OK { if mm_eq4(C, E) == 1 { t1 = 1 } }
65 var n1: i64 = 0; if mm_eq4(C, W) == 0 { n1 = 1 }
66 let rc2: i64 = nx_f32_matmul(A, B, C, 0, 2, 2)
67 var n2: i64 = 0; if rc2 == NX_F32_MM_ERR_BAD_DIM { n2 = 1 }
68
69 var passes: i64 = 0
70 if t1 == 1 { passes = passes + 1 }
71 if n1 == 1 { passes = passes + 1 }
72 if n2 == 1 { passes = passes + 1 }
73 var green: i64 = 0
74 if passes == 3 { green = 1 }
75
76 mm_row("T1-kat-correct \x00" as *u8, t1)
77 mm_row("N1-compare-teeth\x00" as *u8, n1)
78 mm_row("N2-bad-dim-error\x00" as *u8, n2)
79
80 let vb: *u8 = sys_mmap(528)
81 var o: i64 = 0
82 o = mm_cat(vb, o, "F32-MATMUL verdict=\x00" as *u8)
83 if green == 1 { o = mm_cat(vb, o, "GREEN\x00" as *u8) } else { o = mm_cat(vb, o, "RED\x00" as *u8) }
84 o = mm_cat(vb, o, " passes=\x00" as *u8); o = mm_catn(vb, o, passes); o = mm_cat(vb, o, "/3 END\x00" as *u8)
85 vb[o] = 0 as u8
86 fa_appendz(MMG_LOG, vb, 512)
87 mm_puts(vb); mm_puts("\n")
88
89 if green == 1 { return 0 }
90 return 1
91}