code wiki / _hdl_build / nx_blackwell_mma_asm_gate.nx

nx_blackwell_mma_asm_gate.nx source

↩ module page · 71 lines · 5974 B

1// nx_blackwell_mma_asm_gate.nx -- CUDA-EXCEED roadmap C0: gate for the SOVEREIGN Blackwell tensor-core MMA 2// assembler. The ENCODER now lives in nx_mma_asm.nx (shared per-vendor lib, debt-free); this gate exercises it. 3// 4// We RE'd the Blackwell sm_120 encoding from nvcc -arch=sm_120 -cubin -> cuobjdump -sass (bench/mma_probe.cu + 5// mma_probe2.cu). Field layout (differential-decoded, 10 samples, registers to R44 + Rc accumulator + .reuse): 6// low64 = opcode | Rd<<16 | Ra<<24 | Rb<<32 ; high64 = Rc | typebits<<8 | control<<40 7// IMMA = the NO-FLOAT-aligned target (integer tensor cores = DETERMINISTIC = the exceed cuBLAS float can't match). 8// No hw writes (Rule 26). expect_exit: 0 license_tier: ORIGINAL 9import "nx_syscalls.nx" 10import "nx_mma_asm.nx" 11 12func bp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 13func bx(v: i64) -> i64 { bp("0x" as *u8); let bb:*u8=sys_mmap(20); var k:i64=0; var m:i64=v; if m==0{bb[0]=48 as u8;k=1} while m>0{ let d:i64=m&15; if d<10{bb[k]=(48+d) as u8}else{bb[k]=(87+d) as u8}; m=(m>>4); k=k+1 } var i:i64=0; let o:*u8=sys_mmap(20); while i<k{o[i]=bb[k-1-i];i=i+1} sys_write(1,o,k); return 0 } 14func bd(v: i64) -> i64 { let p: *u8=sys_mmap(1); p[0]=(48+v) as u8; sys_write(1,p,1); return 0 } 15 16func chk(name: *u8, lo: i64, hi: i64, rlo: i64, rhi: i64, st: *i64) -> i64 { 17 bp(" " as *u8); bp(name); bp(" -> low=" as *u8); bx(lo); bp(" high=" as *u8); bx(hi) 18 if lo==rlo { if hi==rhi { bp(" == NVIDIA ref PASS\n" as *u8); st[0]=st[0]+1; return 0 } } 19 bp(" != ref(low=" as *u8); bx(rlo); bp(" high=" as *u8); bx(rhi); bp(") FAIL\n" as *u8); return 0 20} 21 22func main() -> i64 { 23 bp("=== SOVEREIGN Blackwell sm_120 tensor-core MMA assembler (nx_mma_asm) -- RE-derived, bit-exact vs NVIDIA ===\n" as *u8) 24 let HMMA: i64 = NV_HMMA_16816 25 let IMMA: i64 = NV_IMMA_16816 26 let RZ: i64 = NV_RZ 27 let TB_H: i64 = NV_TB_HMMA 28 let TB_I: i64 = NV_TB_IMMA 29 let C1: i64 = 0x004ff6 30 let C2: i64 = 0x010ff0 31 let st: *i64 = sys_mmap(8); st[0]=0 32 33 chk("HMMA.bf16 R16,R8,R12" as *u8, nv_mma_low(HMMA,16,8,12), nv_mma_high(RZ,TB_H,C1), 0x0000000c0810723c, 0x004ff600000418ff, st) 34 chk("HMMA.bf16 R12,R8,R14" as *u8, nv_mma_low(HMMA,12,8,14), nv_mma_high(RZ,TB_H,C2), 0x0000000e080c723c, 0x010ff000000418ff, st) 35 chk("IMMA.s8 R4,R10,R4 " as *u8, nv_mma_low(IMMA,4,10,4), nv_mma_high(RZ,TB_I,C1), 0x000000040a047237, 0x004ff600004054ff, st) 36 chk("IMMA.s8 R16,R10,R0" as *u8, nv_mma_low(IMMA,16,10,0), nv_mma_high(RZ,TB_I,C2), 0x000000000a107237, 0x010ff000004054ff, st) 37 38 // broader RE set (mma_probe2.cu): high registers up to R44 + Rc!=RZ accumulator + .reuse flag + two control words 39 chk("HMMA R28,R40,R32,RZ " as *u8, nv_mma_low(HMMA,28,40,32), nv_mma_high(RZ,TB_H,0x008ff6), 0x00000020281c723c, 0x008ff600000418ff, st) 40 chk("HMMA R44,R12,R44,RZ " as *u8, nv_mma_low(HMMA,44,12,44), nv_mma_high(RZ,TB_H,0x000ff6), 0x0000002c0c2c723c, 0x000ff600000418ff, st) 41 chk("HMMA R24,R16,R38,R24" as *u8, nv_mma_low(HMMA,24,16,38), nv_mma_high(24,TB_H,0x000ff6), 0x000000261018723c, 0x000ff60000041818, st) 42 chk("HMMA R20,R8,R38.r,R20" as *u8, nv_mma_low(HMMA,20,8,38), nv_mma_high(20,TB_H,0x0a0ff6), 0x000000260814723c, 0x0a0ff60000041814, st) 43 chk("HMMA R40,R8,R6,R40 " as *u8, nv_mma_low(HMMA,40,8,6), nv_mma_high(40,TB_H,0x000fe2), 0x000000060828723c, 0x000fe20000041828, st) 44 chk("HMMA R20,R40,R24,RZ " as *u8, nv_mma_low(HMMA,20,40,24), nv_mma_high(RZ,TB_H,0x004ff6), 0x000000182814723c, 0x004ff600000418ff, st) 45 46 // FP16 variant (mma_probe3.cu): HMMA.16816.F32 -- SAME opcode 0x723c, dtype in typebits (F16=0x0018 vs BF16=0x0418) 47 chk("HMMA.f16 R16,R8,R12 " as *u8, nv_mma_low(HMMA,16,8,12), nv_mma_high(RZ,NV_TB_HMMA_F16,C1), 0x0000000c0810723c, 0x004ff600000018ff, st) 48 chk("HMMA.f16 R12,R8,R14 " as *u8, nv_mma_low(HMMA,12,8,14), nv_mma_high(RZ,NV_TB_HMMA_F16,C2), 0x0000000e080c723c, 0x010ff000000018ff, st) 49 50 // INT8 m16n8k32 (mma_probe4.cu): IMMA.16832.S8.S8 -- wider-K int8 (the deterministic exceed op); typebits 0x405c 51 chk("IMMA.k32 R8,R8,R6 " as *u8, nv_mma_low(IMMA,8,8,6), nv_mma_high(RZ,NV_TB_IMMA_K32,0x004fe2), 0x0000000608087237, 0x004fe20000405cff, st) 52 53 // FP8 (mma_probe5.cu): QMMA.16832.F32.E4M3.E4M3 -- NEW opcode 0x727a (quarter-precision), the FP8 throughput ceiling 54 chk("QMMA.fp8 R8,R8,R6 " as *u8, nv_mma_low(NV_QMMA_16832,8,8,6), nv_mma_high(RZ,NV_TB_QMMA_E4M3,0x004fe2), 0x000000060808727a, 0x004fe20000002cff, st) 55 56 // AMPERE (RTX 3090, sm_86) -- PROVES the encoder is MULTI-ARCH: identical opcode+operand+typebits as Blackwell, 57 // ONLY the control/scheduler word differs (arch-specific). So nx_mma_asm is portable across NVIDIA archs (3090+5080). 58 chk("HMMA.bf16 Ampere-3090" as *u8, nv_mma_low(HMMA,16,8,12), nv_mma_high(RZ,TB_H,0x044ff0), 0x0000000c0810723c, 0x044ff000000418ff, st) 59 chk("IMMA.s8 Ampere-3090 " as *u8, nv_mma_low(IMMA,16,10,8), nv_mma_high(RZ,TB_I,0x008fe2), 0x000000080a107237, 0x008fe200004054ff, st) 60 61 // negative control: a WRONG operand must NOT reproduce the reference (proves the encoder reads the operands) 62 let nlo: i64 = nv_mma_low(HMMA,17,8,12) 63 var neg_ok: i64 = 0 64 if nlo != 0x0000000c0810723c { neg_ok = 1 } 65 bp(" NEG HMMA Rd=17 (!= ref): " as *u8); if neg_ok==1 { bp("PASS(differs)\n" as *u8) } else { bp("FAIL\n" as *u8) } 66 67 let pass: i64 = st[0] 68 bp("MMA-ASM passed " as *u8); bd(pass/10); bd(pass%10); bp("/16 neg=" as *u8); bd(neg_ok); bp("\n" as *u8) 69 if pass==16 { if neg_ok==1 { bp("verdict=GREEN (sovereign NVIDIA tensor-core encoder bit-exact across 16 samples: Blackwell sm_120 [HMMA BF16/FP16 + IMMA s8 k16/k32 + QMMA FP8] AND Ampere sm_86 [3090: HMMA+IMMA] = MULTI-ARCH portable, only the control/scheduler word differs per arch. C0 instruction-encoding cracked across dtypes+archs)\n" as *u8); sys_exit(0); return 0 } } 70 bp("verdict=RED\n" as *u8); sys_exit(1); return 1 71}