code wiki / _hdl_build / nx_ptx_emit.nx
nx_ptx_emit.nx source
↩ module page · 77 lines · 5052 B
1// nx_ptx_emit.nx -- the SEED of the sovereign PTX emitter: a NishiLang program (compiled by nx_cc) that GENERATES
2// dispatchable PTX text for an elementwise integer kernel, parameterized by OP. Not hand-written, not nvcc -- OUR
3// stack emits the GPU kernel. Writes emitted_vadd.ptx; the driver harness then launches it on the RTX 5080.
4// Proves nx_cc -> (program that emits) PTX -> GPU. Grow this into the nx_cc backend proper. license_tier: ORIGINAL
5import "nx_syscalls.nx"
6
7func w(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 }
8
9const OP: i64 = 0 // 0=add.s32 1=mul.lo.s32 2=max.s32
10
11func emit_head(fd: i64) -> i64 {
12 w(fd, ".version 7.0\n.target sm_70\n.address_size 64\n\n" as *u8)
13 w(fd, ".visible .entry vadd(\n .param .u64 vadd_a,\n .param .u64 vadd_b,\n .param .u64 vadd_c,\n .param .u32 vadd_n\n)\n{\n" as *u8)
14 w(fd, " .reg .pred %p<2>;\n .reg .b32 %r<9>;\n .reg .b64 %rd<11>;\n" as *u8)
15 return 0
16}
17func emit_index(fd: i64) -> i64 {
18 w(fd, " ld.param.u64 %rd1, [vadd_a];\n ld.param.u64 %rd2, [vadd_b];\n ld.param.u64 %rd3, [vadd_c];\n ld.param.u32 %r1, [vadd_n];\n" as *u8)
19 w(fd, " mov.u32 %r2, %ntid.x;\n mov.u32 %r3, %ctaid.x;\n mov.u32 %r4, %tid.x;\n mad.lo.s32 %r5, %r3, %r2, %r4;\n" as *u8)
20 w(fd, " setp.ge.u32 %p1, %r5, %r1;\n @%p1 bra $L_END;\n" as *u8)
21 return 0
22}
23func emit_load(fd: i64) -> i64 {
24 w(fd, " cvta.to.global.u64 %rd4, %rd1;\n cvta.to.global.u64 %rd5, %rd2;\n cvta.to.global.u64 %rd6, %rd3;\n" as *u8)
25 w(fd, " mul.wide.u32 %rd7, %r5, 4;\n add.s64 %rd8, %rd4, %rd7;\n add.s64 %rd9, %rd5, %rd7;\n add.s64 %rd10, %rd6, %rd7;\n" as *u8)
26 w(fd, " ld.global.u32 %r6, [%rd8];\n ld.global.u32 %r7, [%rd9];\n" as *u8)
27 return 0
28}
29func emit_op(fd: i64) -> i64 {
30 if OP==0 { w(fd, " add.s32 %r8, %r6, %r7;\n" as *u8) }
31 else { if OP==1 { w(fd, " mul.lo.s32 %r8, %r6, %r7;\n" as *u8) }
32 else { w(fd, " max.s32 %r8, %r6, %r7;\n" as *u8) } }
33 return 0
34}
35func emit_tail(fd: i64) -> i64 {
36 w(fd, " st.global.u32 [%rd10], %r8;\n$L_END:\n ret;\n}\n" as *u8)
37 return 0
38}
39
40// --- GEMM emitter: a REDUCTION-LOOP integer-MAC kernel (the matmul core), integer-exact/deterministic ---
41func emit_gemm_head(fd: i64) -> i64 {
42 w(fd, ".version 7.0\n.target sm_70\n.address_size 64\n\n" as *u8)
43 w(fd, ".visible .entry gemm(\n .param .u64 g_a, .param .u64 g_b, .param .u64 g_c,\n .param .u32 g_m, .param .u32 g_n, .param .u32 g_k\n)\n{\n" as *u8)
44 w(fd, " .reg .pred %p<3>;\n .reg .b32 %r<20>;\n .reg .b64 %rd<14>;\n" as *u8)
45 return 0
46}
47func emit_gemm_idx(fd: i64) -> i64 {
48 w(fd, " ld.param.u64 %rd1, [g_a];\n ld.param.u64 %rd2, [g_b];\n ld.param.u64 %rd3, [g_c];\n" as *u8)
49 w(fd, " ld.param.u32 %r1, [g_m];\n ld.param.u32 %r2, [g_n];\n ld.param.u32 %r3, [g_k];\n" as *u8)
50 w(fd, " mov.u32 %r4, %ntid.x; mov.u32 %r5, %ctaid.x; mov.u32 %r6, %tid.x;\n mad.lo.s32 %r7, %r5, %r4, %r6;\n" as *u8)
51 w(fd, " mov.u32 %r8, %ntid.y; mov.u32 %r9, %ctaid.y; mov.u32 %r10, %tid.y;\n mad.lo.s32 %r11, %r9, %r8, %r10;\n" as *u8)
52 return 0
53}
54func emit_gemm_bounds(fd: i64) -> i64 {
55 w(fd, " setp.ge.u32 %p1, %r7, %r2;\n setp.ge.u32 %p2, %r11, %r1;\n or.pred %p1, %p1, %p2;\n @%p1 bra $DONE;\n" as *u8)
56 w(fd, " cvta.to.global.u64 %rd4, %rd1;\n cvta.to.global.u64 %rd5, %rd2;\n cvta.to.global.u64 %rd6, %rd3;\n" as *u8)
57 w(fd, " mov.s32 %r12, 0;\n mov.s32 %r13, 0;\n$LOOP:\n setp.ge.u32 %p1, %r13, %r3;\n @%p1 bra $ENDLOOP;\n" as *u8)
58 return 0
59}
60func emit_gemm_body(fd: i64) -> i64 {
61 w(fd, " mad.lo.s32 %r14, %r11, %r3, %r13;\n mul.wide.s32 %rd7, %r14, 4;\n add.s64 %rd8, %rd4, %rd7;\n ld.global.u32 %r15, [%rd8];\n" as *u8)
62 w(fd, " mad.lo.s32 %r16, %r13, %r2, %r7;\n mul.wide.s32 %rd9, %r16, 4;\n add.s64 %rd10, %rd5, %rd9;\n ld.global.u32 %r17, [%rd10];\n" as *u8)
63 w(fd, " mad.lo.s32 %r12, %r15, %r17, %r12;\n add.s32 %r13, %r13, 1;\n bra $LOOP;\n" as *u8)
64 w(fd, "$ENDLOOP:\n mad.lo.s32 %r18, %r11, %r2, %r7;\n mul.wide.s32 %rd11, %r18, 4;\n add.s64 %rd12, %rd6, %rd11;\n st.global.u32 [%rd12], %r12;\n$DONE:\n ret;\n}\n" as *u8)
65 return 0
66}
67
68func main() -> i64 {
69 let path: *u8 = "/mnt/c/Users/elder/AppData/Local/Temp/claude/C--Users-elder/10730ed9-0e7d-4843-ad8a-e2d4a8122cbd/scratchpad/emitted_gemm.ptx" as *u8
70 let fd: i64 = sys_openat_wr(path)
71 if fd < 0 { w(1, "NX-PTX-EMIT: FAILED to open output file\n" as *u8); return 1 }
72 emit_gemm_head(fd); emit_gemm_idx(fd); emit_gemm_bounds(fd); emit_gemm_body(fd)
73 sys_close(fd)
74 w(1, "NX-PTX-EMIT: nx_cc-compiled emitter WROTE emitted_gemm.ptx -- a REDUCTION-LOOP integer-MAC matmul kernel.\n" as *u8)
75 w(1, " The sovereign stack now generates a MATMUL GPU kernel (loops+reduction+integer MAC), not just elementwise. Driver launches it next.\n" as *u8)
76 return 0
77}