code wiki / _hdl_build / nx_faithdiff_probe.nx

nx_faithdiff_probe.nx source

↩ module page · 180 lines · 11077 B

1// nx_faithdiff_probe.nx -- functions UNDER wat-faithfulness test. NO main -> the WAT target exports each. 2// Imports the REAL codec so the probe tests the SHIPPING functions (not copies) + a FULL encode->decode 3// roundtrip -> a divergence VM-vs-native here == the identical divergence in the deployed wasm. license: ORIGINAL 4import "nx_video_codec_wasm.nx" // brings vv_enc/vv_dec (+ vc_* incl AQ/tile/deblock) exactly as shipped 5const K_MAGIC_16384: i64 = 16384 6const K_MAGIC_20480: i64 = 20480 7const K_MAGIC_6016: i64 = 6016 8const K_MAGIC_4096: i64 = 4096 9const K_MAGIC_8192: i64 = 8192 10const K_MAGIC_90000: i64 = 90000 11const K_MAGIC_90128: i64 = 90128 12const K_MAGIC_90256: i64 = 90256 13const K_MAGIC_130000: i64 = 130000 14const K_MAGIC_52000: i64 = 52000 15const K_MAGIC_89000: i64 = 89000 16const K_MAGIC_16777216: i64 = 16777216 17const K_MAGIC_57008: i64 = 57008 18const K_MAGIC_57500: i64 = 57500 19const K_MAGIC_57692: i64 = 57692 20const K_MAGIC_58400: i64 = 58400 21 22// the TILE integration pattern (isolated): tfy pack/unpack + the variable-bound compare 23func fd_tile(tfy: i64, sy: i64) -> i64 { 24 let tf: i64 = tfy & 1; let ytop: i64 = tfy >> 1 25 var r: i64 = tf 26 if sy > ytop { r = r + 1000 } 27 return r } 28 29// FULL codec roundtrip at a caller-provided memory base (native = real alloc; VM = mod.mem offset). Fills a 30// 64x64 frame from seed, vv_enc (key) then vv_dec, returns a checksum of the decoded recon + bitcount. If VM 31// and native return the same value, the ENTIRE encode->decode path (AQ + tile + deblock + transform + 32// entropy) lowered to wasm faithfully. W=64,H=64 is codec-safe (chroma 32x32, both /16). 33func fd_roundtrip(membase: i64, seed: i64) -> i64 { 34 let W: i64 = 64; let H: i64 = 64 35 let N: i64 = W*H; let C: i64 = (W/2)*(H/2); let sz: i64 = N + 2*C 36 let cur: *u8 = membase as *u8 37 let prevE: *u8 = (membase + sz) as *u8; let reconE: *u8 = (membase + 2*sz) as *u8 38 let prevD: *u8 = (membase + 3*sz) as *u8; let reconD: *u8 = (membase + 4*sz) as *u8 39 let stream: *u8 = (membase + 5*sz) as *u8 40 let blk: *i64 = (membase + 5*sz + K_MAGIC_16384) as *i64 41 let mv: *i64 = (membase + 5*sz + K_MAGIC_20480) as *i64 42 var i: i64 = 0 43 while i < sz { prevE[i] = 0 as u8; prevD[i] = 0 as u8; i = i + 1 } 44 i = 0 45 while i < N { let x: i64 = i & 63; let y: i64 = i >> 6 46 var v: i64 = (x + y) * 2 + (seed & 63); if x > 31 { v = v + 40 }; if v > 255 { v = 255 } 47 cur[i] = v as u8; i = i + 1 } 48 i = N; while i < sz { cur[i] = 128 as u8; i = i + 1 } 49 let kb: i64 = vv_enc(cur, prevE, reconE, W, H, 20, 1, K_MAGIC_6016, stream, K_MAGIC_16384, blk, mv) 50 vv_dec(prevD, reconD, W, H, 20, stream, kb, blk, mv) 51 var sum: i64 = 0; i = 0 52 while i < sz { sum = sum + (reconD[i] & 0xff) * (i + 1); i = i + 1 } 53 return (sum & 0xffffff) * K_MAGIC_4096 + (kb & 0xfff) } 54 55// full BANDED roundtrip (the tile-parallel path): 2 bands via vv_enc_band/vv_dec_band, decode reverse. 56func fd_band_roundtrip(membase: i64, seed: i64) -> i64 { 57 let W: i64 = 64; let H: i64 = 64 58 let N: i64 = W*H; let C: i64 = (W/2)*(H/2); let sz: i64 = N + 2*C 59 let cur: *u8 = membase as *u8 60 let prev: *u8 = (membase + sz) as *u8; let reconE: *u8 = (membase + 2*sz) as *u8; let reconD: *u8 = (membase + 3*sz) as *u8 61 let s0: *u8 = (membase + 4*sz) as *u8; let s1: *u8 = (membase + 4*sz + K_MAGIC_8192) as *u8 62 let blk: *i64 = (membase + 4*sz + K_MAGIC_16384) as *i64; let mv: *i64 = (membase + 4*sz + K_MAGIC_20480) as *i64 63 var i: i64 = 0 64 while i < sz { prev[i] = 0 as u8; i = i + 1 } 65 i = 0 66 while i < N { let x: i64 = i & 63; let y: i64 = i >> 6 67 var v: i64 = (x + y) * 2 + (seed & 63); if x > 31 { v = v + 40 }; if v > 255 { v = 255 } 68 cur[i] = v as u8; i = i + 1 } 69 i = N; while i < sz { cur[i] = 128 as u8; i = i + 1 } 70 let l0: i64 = vv_enc_band(cur, prev, reconE, W, H, 0, 2, 20, 1, K_MAGIC_6016, s0, K_MAGIC_8192, blk, mv) // BH=4, 2 bands x 2 rows 71 let l1: i64 = vv_enc_band(cur, prev, reconE, W, H, 2, 4, 20, 1, K_MAGIC_6016, s1, K_MAGIC_8192, blk, mv) 72 vv_dec_band(prev, reconD, W, H, 2, 4, 20, s1, l1, blk, mv) 73 vv_dec_band(prev, reconD, W, H, 0, 2, 20, s0, l0, blk, mv) 74 var sum: i64 = 0; i = 0 75 while i < sz { sum = sum + (reconD[i] & 0xff) * (i + 1); i = i + 1 } 76 return (sum & 0xffffff) * K_MAGIC_4096 + ((l0 + l1) & 0xfff) } 77 78// RANGE-CODED full-frame roundtrip (task #31): vv_enc_rc -> vv_dec_rc through the LZMA range coder. A VM-vs- 79// native divergence here == the identical divergence in the deployed wasm -> catches any range-coder lowering 80// bug BEFORE it ships. rctx buffers laid out high in membase to avoid the codec scratch below. 81func fd_rc_roundtrip(membase: i64, seed: i64) -> i64 { 82 let W: i64 = 64; let H: i64 = 64 83 let N: i64 = W*H; let C: i64 = (W/2)*(H/2); let sz: i64 = N + 2*C 84 let cur: *u8 = membase as *u8 85 let prevE: *u8 = (membase + sz) as *u8; let reconE: *u8 = (membase + 2*sz) as *u8 86 let prevD: *u8 = (membase + 3*sz) as *u8; let reconD: *u8 = (membase + 4*sz) as *u8 87 let stream: *u8 = (membase + 5*sz) as *u8 88 let blk: *i64 = (membase + 5*sz + K_MAGIC_16384) as *i64 89 let mv: *i64 = (membase + 5*sz + K_MAGIC_20480) as *i64 90 let est: *i64 = (membase + K_MAGIC_90000) as *i64 91 let probs: *i64 = (membase + K_MAGIC_90128) as *i64 92 let rcbuf: *u8 = (membase + K_MAGIC_90256) as *u8 93 let rctx: *i64 = (membase + K_MAGIC_130000) as *i64 94 var i: i64 = 0 95 while i < sz { prevE[i] = 0 as u8; prevD[i] = 0 as u8; i = i + 1 } 96 i = 0 97 while i < N { let x: i64 = i & 63; let y: i64 = i >> 6 98 var v: i64 = (x + y) * 2 + (seed & 63); if x > 31 { v = v + 40 }; if v > 255 { v = 255 } 99 cur[i] = v as u8; i = i + 1 } 100 i = N; while i < sz { cur[i] = 128 as u8; i = i + 1 } 101 rctx[0] = 1; rctx[1] = est as i64; rctx[2] = probs as i64; rctx[3] = rcbuf as i64 102 let kb: i64 = vv_enc_rc(cur, prevE, reconE, W, H, 20, 1, K_MAGIC_6016, stream, K_MAGIC_16384, blk, mv, rctx) 103 rctx[0] = 1; rctx[1] = est as i64; rctx[2] = probs as i64; rctx[3] = rcbuf as i64 104 vv_dec_rc(prevD, reconD, W, H, 20, stream, kb, blk, mv, rctx) 105 var sum: i64 = 0; i = 0 106 while i < sz { sum = sum + (reconD[i] & 0xff) * (i + 1); i = i + 1 } 107 return (sum & 0xffffff) * K_MAGIC_4096 + (kb & 0xfff) } 108 109// VARIABLE-TRANSFORM (t8) roundtrip (task #46 rung 2): vv_enc_t8 -> vv_dec_t8, KEYFRAME then a P-FRAME 110// (right half changed -> left half SKIPs, right half codes inter residuals) so the 8x8 intra AND inter 111// paths + the 1 bit/MB select all execute IN THE VM. t8 buffers live in a fresh region (membase+52000..) 112// clear of the other probes' layouts. Checksums the P recon + both bitcounts. 113func fd_t8_roundtrip(membase: i64, seed: i64) -> i64 { 114 let W: i64 = 64; let H: i64 = 64 115 let N: i64 = W*H; let C: i64 = (W/2)*(H/2); let sz: i64 = N + 2*C 116 let cur: *u8 = membase as *u8 117 let prevE: *u8 = (membase + sz) as *u8; let reconE: *u8 = (membase + 2*sz) as *u8 118 let prevD: *u8 = (membase + 3*sz) as *u8; let reconD: *u8 = (membase + 4*sz) as *u8 119 let stream: *u8 = (membase + 5*sz) as *u8 120 let blk: *i64 = (membase + 5*sz + K_MAGIC_16384) as *i64 121 let mv: *i64 = (membase + 5*sz + K_MAGIC_20480) as *i64 122 let t8c: *i64 = (membase + K_MAGIC_52000) as *i64 123 let rctx: *i64 = (membase + K_MAGIC_89000) as *i64 124 vc_t8_init(t8c) 125 var i: i64 = 0 126 while i < sz { prevE[i] = 0 as u8; prevD[i] = 0 as u8; i = i + 1 } 127 i = 0 128 while i < N { let x: i64 = i & 63; let y: i64 = i >> 6 129 var v: i64 = (x + y) * 2 + (seed & 63); if x > 31 { v = v + 40 }; if v > 255 { v = 255 } 130 cur[i] = v as u8; i = i + 1 } 131 i = N; while i < sz { cur[i] = 128 as u8; i = i + 1 } 132 rctx[0] = 0; rctx[1] = 0; rctx[2] = 0; rctx[3] = 0; rctx[4] = t8c as i64 133 let kb: i64 = vv_enc_t8(cur, prevE, reconE, W, H, 20, 1, K_MAGIC_6016, stream, K_MAGIC_16384, blk, mv, rctx) 134 rctx[0] = 0; rctx[1] = 0; rctx[2] = 0; rctx[3] = 0; rctx[4] = t8c as i64 135 vv_dec_t8(prevD, reconD, W, H, 20, stream, kb, blk, mv, rctx) 136 i = 0 137 while i < sz { prevE[i] = reconE[i]; prevD[i] = reconD[i]; i = i + 1 } 138 i = 0 139 while i < N { let x: i64 = i & 63 140 if x > 31 { var v2: i64 = (cur[i] as i64) + 25; if v2 > 255 { v2 = 255 }; cur[i] = v2 as u8 } 141 i = i + 1 } 142 rctx[0] = 4; rctx[1] = 0; rctx[2] = 0; rctx[3] = 0; rctx[4] = t8c as i64; rctx[5] = 0 // emode 4 = CAVLC + RD-AUTO: the P-frame exercises vc_rd_t8_inter + bit-patch in the VM 143 let pb: i64 = vv_enc_t8(cur, prevE, reconE, W, H, 20, 0, K_MAGIC_6016, stream, K_MAGIC_16384, blk, mv, rctx) 144 rctx[0] = 0; rctx[1] = 0; rctx[2] = 0; rctx[3] = 0; rctx[4] = t8c as i64 // decoder never sees the auto flag 145 vv_dec_t8(prevD, reconD, W, H, 20, stream, pb, blk, mv, rctx) 146 var sum: i64 = 0; i = 0 147 while i < sz { sum = sum + (reconD[i] & 0xff) * (i + 1); i = i + 1 } 148 return (sum & 0xfffff) * K_MAGIC_16777216 + (kb & 0xfff) * K_MAGIC_4096 + (pb & 0xfff) } 149 150// RANGE-CODED + t8 roundtrip: vv_enc_rct8 -> vv_dec_rct8 (rc_block64 contexts + the two-section frame), 151// keyframe only (the rc+inter interaction is fd_rc's + fd_t8's job; this pins the rct8 composition). 152func fd_rct8_roundtrip(membase: i64, seed: i64) -> i64 { 153 let W: i64 = 64; let H: i64 = 64 154 let N: i64 = W*H; let C: i64 = (W/2)*(H/2); let sz: i64 = N + 2*C 155 let cur: *u8 = membase as *u8 156 let prevE: *u8 = (membase + sz) as *u8; let reconE: *u8 = (membase + 2*sz) as *u8 157 let prevD: *u8 = (membase + 3*sz) as *u8; let reconD: *u8 = (membase + 4*sz) as *u8 158 let stream: *u8 = (membase + 5*sz) as *u8 159 let blk: *i64 = (membase + 5*sz + K_MAGIC_16384) as *i64 160 let mv: *i64 = (membase + 5*sz + K_MAGIC_20480) as *i64 161 let t8c: *i64 = (membase + K_MAGIC_52000) as *i64 // VC_T8_SIZE*8 = 5008B, ends K_MAGIC_57008 162 let est: *i64 = (membase + K_MAGIC_57500) as *i64 163 let probs: *i64 = (membase + K_MAGIC_57692) as *i64 // 24 contexts (RC_NCTX8) fit here with room 164 let rcbuf: *u8 = (membase + K_MAGIC_58400) as *u8 // ~30000B rc section scratch, ends < K_MAGIC_89000 165 let rctx: *i64 = (membase + K_MAGIC_89000) as *i64 166 vc_t8_init(t8c) 167 var i: i64 = 0 168 while i < sz { prevE[i] = 0 as u8; prevD[i] = 0 as u8; i = i + 1 } 169 i = 0 170 while i < N { let x: i64 = i & 63; let y: i64 = i >> 6 171 var v: i64 = (x + y) * 2 + (seed & 63); if x > 31 { v = v + 40 }; if v > 255 { v = 255 } 172 cur[i] = v as u8; i = i + 1 } 173 i = N; while i < sz { cur[i] = 128 as u8; i = i + 1 } 174 rctx[0] = 1; rctx[1] = est as i64; rctx[2] = probs as i64; rctx[3] = rcbuf as i64; rctx[4] = t8c as i64 175 let kb: i64 = vv_enc_rct8(cur, prevE, reconE, W, H, 20, 1, K_MAGIC_6016, stream, K_MAGIC_16384, blk, mv, rctx) 176 rctx[0] = 1; rctx[1] = est as i64; rctx[2] = probs as i64; rctx[3] = rcbuf as i64; rctx[4] = t8c as i64 177 vv_dec_rct8(prevD, reconD, W, H, 20, stream, kb, blk, mv, rctx) 178 var sum: i64 = 0; i = 0 179 while i < sz { sum = sum + (reconD[i] & 0xff) * (i + 1); i = i + 1 } 180 return (sum & 0xffffff) * K_MAGIC_4096 + (kb & 0xfff) }