code wiki / _hdl_build / nx_nofloat_mxfp8_gate.nx

nx_nofloat_mxfp8_gate.nx source

↩ module page · 71 lines · 3502 B

1// nx_nofloat_mxfp8_gate.nx -- gate: MXFP8 (OCP E4M3 + E5M2) dequant to Q16, EXACT known values. 2// T1 E4M3 normals decode to exact Q16 (1.0, 1.5, 2.0, 0.5, -1.0) 3// T2 E4M3 subnormal (2^-7) + NaN (E=1111,M=111) -> 0 4// T3 E5M2 normals decode to exact Q16 (1.0, 1.25, 0.5) 5// T4 E5M2 subnormal (2^-16) + inf (E=11111,M=0) -> 0 6// T5 E8M0 shared block scale: same element, scale 2^+1 doubles, 2^-1 halves 7// T6 block decode: 32-element E4M3 block all decode + bit-identical on a second pass (deterministic) 8// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0 9import "nx_nofloat_mxfp8.nx" 10import "nx_gate_verdict.nx" 11import "nx_syscalls.nx" 12 13const G8_S0: i64 = 127 // E8M0 scale exponent for 2^0 = 1 14 15func main() -> i64 { 16 let ctr: *i64 = gv_ctr() 17 gv_head("nx_nofloat_mxfp8 gate -- OCP E4M3 + E5M2 dequant to Q16, exact known values" as *u8) 18 19 // T1: E4M3 normals (scale 2^0) 20 var t1: i64 = 1 21 if mx8_e4m3(56, G8_S0) != 65536 { t1 = 0 } // 0x38 = 1.0 22 if mx8_e4m3(60, G8_S0) != 98304 { t1 = 0 } // 0x3C = 1.5 23 if mx8_e4m3(64, G8_S0) != 131072 { t1 = 0 } // 0x40 = 2.0 24 if mx8_e4m3(48, G8_S0) != 32768 { t1 = 0 } // 0x30 = 0.5 25 if mx8_e4m3(184, G8_S0) != (0 - 65536) { t1 = 0 } // 0xB8 = -1.0 26 gv_check("T1 E4M3 normals -> exact Q16 (1.0, 1.5, 2.0, 0.5, -1.0)" as *u8, t1, ctr) 27 28 // T2: E4M3 subnormal + NaN 29 var t2: i64 = 1 30 if mx8_e4m3(4, G8_S0) != 512 { t2 = 0 } // 0x04 = 2^-7 = 512 Q16 31 if mx8_e4m3(127, G8_S0) != 0 { t2 = 0 } // 0x7F = NaN -> 0 32 gv_check("T2 E4M3 subnormal (2^-7=512) + NaN -> 0" as *u8, t2, ctr) 33 34 // T3: E5M2 normals 35 var t3: i64 = 1 36 if mx8_e5m2(60, G8_S0) != 65536 { t3 = 0 } // 0x3C = 1.0 37 if mx8_e5m2(61, G8_S0) != 81920 { t3 = 0 } // 0x3D = 1.25 38 if mx8_e5m2(56, G8_S0) != 32768 { t3 = 0 } // 0x38 = 0.5 39 gv_check("T3 E5M2 normals -> exact Q16 (1.0, 1.25, 0.5)" as *u8, t3, ctr) 40 41 // T4: E5M2 subnormal + inf 42 var t4: i64 = 1 43 if mx8_e5m2(1, G8_S0) != 1 { t4 = 0 } // 0x01 = 2^-16 = 1 Q16 44 if mx8_e5m2(124, G8_S0) != 0 { t4 = 0 } // 0x7C = inf -> 0 45 gv_check("T4 E5M2 subnormal (2^-16=1) + inf -> 0" as *u8, t4, ctr) 46 47 // T5: E8M0 block scale doubles/halves 48 var t5: i64 = 1 49 if mx8_e4m3(56, 128) != 131072 { t5 = 0 } // 1.0 * 2^1 = 2.0 50 if mx8_e4m3(56, 126) != 32768 { t5 = 0 } // 1.0 * 2^-1 = 0.5 51 if mx8_e5m2(60, 128) != 131072 { t5 = 0 } // 1.0 * 2^1 = 2.0 52 gv_check("T5 E8M0 shared block scale: 2^+1 doubles, 2^-1 halves" as *u8, t5, ctr) 53 54 // T6: block decode + determinism (32-elem E4M3 block all 0x38=1.0, scale byte 127) 55 let buf: *u8 = sys_mmap(64) as *u8 56 var i: i64 = 0 57 while i < 32 { buf[i] = 56 as u8; i = i + 1 } // 32 bytes of 0x38 58 buf[32] = 127 as u8 // E8M0 scale at soff=32 59 let out: *i64 = sys_mmap(64*8) as *i64 60 let out2: *i64 = sys_mmap(64*8) as *i64 61 mx8_block_e4m3(buf, 0, 32, out) 62 mx8_block_e4m3(buf, 0, 32, out2) 63 var t6: i64 = 1 64 i = 0 65 while i < 32 { if out[i] != 65536 { t6 = 0 } if out2[i] != out[i] { t6 = 0 } i = i + 1 } 66 gv_check("T6 block decode: 32 E4M3 elements all 1.0, bit-identical on re-decode" as *u8, t6, ctr) 67 68 let rc: i64 = gv_verdict("NOFLOAT-MXFP8-GATE" as *u8, ctr, "MXFP8 OCP E4M3+E5M2 dequant to Q16: exact normals/subnormals, NaN/inf guarded, E8M0 block scale, deterministic no-float" as *u8) 69 sys_exit(rc) 70 return rc 71}