code wiki / _hdl_build / nx_f32_hw_matmul.nx
nx_f32_hw_matmul.nx source
↩ module page · 67 lines · 2979 B
1// nx_f32_hw_matmul.nx -- HARDWARE-float GEMM (the rung above the software nx_f32_matmul).
2//
3// module: nishi-core.genealogy.f32_hw_matmul
4// capability: CORE_COMPUTE (escape the math perf lock via the SSE hardware-float rung)
5//
6// Same GEMM as nx_f32_matmul, but the inner MAC uses nx_f32_hw's f32_add/f32_mul -- which compile
7// to SSE addss/mulss on the real FPU (rung A, nx_f32_sse_kat_gate GREEN) -- instead of the bits-up
8// SOFTWARE f32. binary32 layout is identical, so results are bit-for-bit cross-checkable against the
9// software matmul (the gate's differential). This is the measured lever for the math/simd lock.
10// Sovereign: imports nx_f32_hw (-> __f32_* SSE intrinsics) + nx_syscalls. license_tier: ORIGINAL
11import "nx_f32_hw.nx"
12import "nx_syscalls.nx"
13
14const NX_HWMM_OK: i64 = 0
15const NX_HWMM_ERR: i64 = 1
16
17func hmm_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != 0 as u8 { n = n + 1 } sys_write(1, s, n); return 0 }
18func hmm_putn(v: i64) -> i64 {
19 if v == 0 { sys_write(1, "0" as *u8, 1); return 0 }
20 var m: i64 = v
21 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m }
22 let d: *u8 = sys_mmap(24); var k: i64 = 0
23 while m > 0 { d[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
24 var j: i64 = k - 1
25 while j >= 0 { sys_write(1, ((d as i64)+j) as *u8, 1); j = j - 1 }
26 return 0
27}
28
29// C[m,n] = A[m,k] @ B[k,n], row-major, hardware-float MAC.
30func nx_f32_hw_matmul(a: *i64, b: *i64, c: *i64, m: i64, k: i64, n: i64) -> i64 {
31 if m <= 0 { return NX_HWMM_ERR }
32 if k <= 0 { return NX_HWMM_ERR }
33 if n <= 0 { return NX_HWMM_ERR }
34 var i: i64 = 0
35 while i < m {
36 var j: i64 = 0
37 while j < n {
38 // hot loop uses the __f32_* intrinsics DIRECTLY (compiler emits addss/mulss INLINE) --
39 // bit-identical to the f32_add/f32_mul wrappers but no per-MAC call overhead (~1.6x,
40 // measured in nx_f32_intrin_matmul). Differential gate stays bit-exact vs nx_f32_matmul.
41 var acc: i64 = __f32_from_i64(0)
42 var l: i64 = 0
43 while l < k {
44 acc = __f32_add(acc, __f32_mul(a[i * k + l], b[l * n + j]))
45 l = l + 1
46 }
47 c[i * n + j] = acc
48 j = j + 1
49 }
50 i = i + 1
51 }
52 return NX_HWMM_OK
53}
54
55func main() -> i64 {
56 hmm_puts("=== hardware-float GEMM demo (SSE addss/mulss) ===\n")
57 let A: *i64 = sys_mmap(4 * 8) as *i64
58 A[0] = f32_of(1); A[1] = f32_of(2); A[2] = f32_of(3); A[3] = f32_of(4)
59 let B: *i64 = sys_mmap(4 * 8) as *i64
60 B[0] = f32_of(5); B[1] = f32_of(6); B[2] = f32_of(7); B[3] = f32_of(8)
61 let C: *i64 = sys_mmap(4 * 8) as *i64
62 nx_f32_hw_matmul(A, B, C, 2, 2, 2)
63 hmm_puts(" [[1,2],[3,4]] @ [[5,6],[7,8]] = [[")
64 hmm_putn(f32_int(C[0])); hmm_puts(","); hmm_putn(f32_int(C[1])); hmm_puts("],[")
65 hmm_putn(f32_int(C[2])); hmm_puts(","); hmm_putn(f32_int(C[3])); hmm_puts("]] (expect [[19,22],[43,50]])\n")
66 sys_exit(0); return 0
67}