code wiki / _hdl_build / nx_wasm_vm_exec_gate.nx
nx_wasm_vm_exec_gate.nx source
↩ module page · 95 lines · 5906 B
1// nx_wasm_vm_exec_gate.nx -- R1+R2: the sovereign WASM VM EXECUTES the real nx_vcodec.wasm and we DIFF it against the
2// native codec. R1 validates the executor on functions that touch NO byte memory (constant accessors + the pure-integer
3// vc_vbits with its calls/control-flow) -- if those match native, the VM's arithmetic, calls, and structured control
4// are sound. R2 then runs the actual codec (vc_wasm_encode -> vc_wasm_decode) on a real 16x16 frame and compares the
5// independent-decoder output to the native packed codec's. If R1 passes but R2 diverges, the fault is the wasm's u8
6// memory access -- the exact thing this VM exists to catch.
7import "nx_syscalls.nx"
8import "nx_gate_emit_lib.nx"
9import "nx_wasm_vm.nx"
10import "nx_vcodec.nx"
11
12func g_abs(v: i64) -> i64 { if v < 0 { return 0 - v } return v }
13
14func main() -> i64 {
15 g_puts("nx_wasm_vm gate R1+R2 (sovereign VM executes the real wasm, DIFF vs native, MEASURED)\n" as *u8)
16 var pass: i64 = 0; var total: i64 = 0
17
18 let box: *i64 = sys_mmap(16) as *i64
19 let wasm: *u8 = sys_read_file("/mnt/c/Users/elder/nishi-core/nxc2/web_assets/_video_build/nx_vcodec.wasm" as *u8, box)
20 if (wasm as i64) == 0 { g_puts(" FAIL cannot read wasm\n" as *u8); g_puts("verdict=RED\n" as *u8); sys_exit(1); return 1 }
21 let mod: *WasmMod = wm_new(wasm, box[0])
22 if wm_parse(mod) != 0 { g_puts(" FAIL parse\n" as *u8); g_puts("verdict=RED\n" as *u8); sys_exit(1); return 1 }
23 mod.mem = sys_mmap(mod.mem_bytes) as *u8
24
25 // ---- DIAG: dump vc_cur_off's parsed metadata + first code bytes (parser sanity) ----
26 let didx: i64 = wm_find_export(mod, "vc_cur_off" as *u8)
27 g_puts(" [diag] vc_cur_off fidx=" as *u8); g_pn(didx); g_puts(" code_off=" as *u8); g_pn(mod.func_code[didx])
28 g_puts(" end=" as *u8); g_pn(mod.func_end[didx]); g_puts(" nloc=" as *u8); g_pn(mod.func_nloc[didx]); g_puts("\n [diag] first bytes:" as *u8)
29 var dbi: i64 = 0
30 while dbi < 16 { g_puts(" " as *u8); g_pn(mod.bytes[mod.func_code[didx] + dbi] as i64); dbi = dbi + 1 }
31 g_puts("\n" as *u8)
32
33 // ---- R1a: constant accessors (executor skeleton: const + return + block-dispatch) ----
34 let a_cur: i64 = wm_run(mod, "vc_cur_off" as *u8, 0,0,0,0,0, 0)
35 let a_prev: i64 = wm_run(mod, "vc_prev_off" as *u8, 0,0,0,0,0, 0)
36 let a_str: i64 = wm_run(mod, "vc_stream_off" as *u8, 0,0,0,0,0, 0)
37 let a_dec: i64 = wm_run(mod, "vc_dec_recon_off" as *u8, 0,0,0,0,0, 0)
38 g_puts(" [R1a] accessors via VM: cur=" as *u8); g_pn(a_cur); g_puts(" prev=" as *u8); g_pn(a_prev)
39 g_puts(" stream=" as *u8); g_pn(a_str); g_puts(" dec_recon=" as *u8); g_pn(a_dec); g_puts("\n" as *u8)
40 pass = pass + g_check("R1a executor returns the exact constant offsets (0/16384/65536/49152)" as *u8,
41 (a_cur==0) & (a_prev==16384) & (a_str==65536) & (a_dec==49152)); total=total+1
42
43 // ---- R1b: pure-integer vc_vbits (arith + calls + control), VM vs native, no byte memory ----
44 var vb_ok: i64 = 1
45 var tv: i64 = 0
46 while tv < 6 {
47 let probe: i64 = (tv*7) - 13 // mix of +/- values
48 let native_vb: i64 = vc_vbits(probe)
49 let vm_vb: i64 = wm_run(mod, "vc_vbits" as *u8, probe, 0,0,0,0, 1)
50 if native_vb != vm_vb { vb_ok = 0 }
51 if tv == 0 { g_puts(" [R1b] vc_vbits sample: native=" as *u8); g_pn(native_vb); g_puts(" vm=" as *u8); g_pn(vm_vb); g_puts("\n" as *u8) }
52 tv = tv + 1
53 }
54 pass = pass + g_check("R1b VM matches native on pure-integer vc_vbits (arith+calls+control sound)" as *u8, vb_ok); total=total+1
55
56 // ---- R2: the codec itself, VM vs native, on a real 16x16 frame ----
57 let W: i64 = 16; let H: i64 = 16; let N: i64 = W*H; let QP: i64 = 20; let SAD: i64 = 64
58 let cur: *u8 = sys_mmap(N) as *u8
59 let prev: *u8 = sys_mmap(N) as *u8
60 let eR: *u8 = sys_mmap(N) as *u8
61 let dR: *u8 = sys_mmap(N) as *u8
62 let stream: *u8 = sys_mmap(8192) as *u8
63 let blk: *i64 = sys_mmap(16*8) as *i64
64 let mv: *i64 = sys_mmap(2*8) as *i64
65 // a textured frame
66 var y: i64 = 0
67 while y < H { var x: i64 = 0
68 while x < W { var v: i64 = 40 + ((x*11 + y*7) % 120); if (y>=4) { if (y<12) { if (x>=4) { if (x<12) { v = 210 } } } } cur[y*W+x] = v as u8; x = x + 1 } y = y + 1 }
69 // NATIVE: encode -> independent decode
70 vc_enc_frame_packed(cur, prev, eR, W, H, QP, 1, SAD, stream, blk, mv)
71 vc_dec_frame_packed(prev, dR, W, H, QP, stream, blk, mv)
72 // WASM via VM: write the same frame into linear memory at O_CUR (0), run encode then decode
73 var i: i64 = 0; while i < N { mod.mem[i] = cur[i]; i = i + 1 }
74 let wbits: i64 = wm_run(mod, "vc_wasm_encode" as *u8, W, H, QP, 1, SAD, 5)
75 wm_run(mod, "vc_wasm_decode" as *u8, W, H, QP, 0, 0, 3)
76 // compare native dR vs wasm DEC_RECON (offset 49152)
77 var mismatch: i64 = 0; var maxd: i64 = 0
78 i = 0
79 while i < N {
80 let wv: i64 = mod.mem[49152 + i] as i64
81 let nv: i64 = dR[i] as i64
82 let d: i64 = g_abs(wv - nv)
83 if d != 0 { mismatch = mismatch + 1 }
84 if d > maxd { maxd = d }
85 i = i + 1
86 }
87 g_puts(" [R2] codec via VM vs native (16x16): native stream bits=" as *u8); g_pn((vc_enc_frame_packed(cur, prev, eR, W, H, QP, 1, SAD, stream, blk, mv)))
88 g_puts(" wasm stream bits=" as *u8); g_pn(wbits); g_puts("\n" as *u8)
89 g_puts(" [R2] decoded-frame diff (wasm vs native): mismatching px=" as *u8); g_pn(mismatch); g_puts(" / " as *u8); g_pn(N); g_puts(" max-diff=" as *u8); g_pn(maxd); g_puts("\n" as *u8)
90 pass = pass + g_check("R2 wasm codec decodes BIT-EXACT to native (shipped wasm is correct)" as *u8, mismatch == 0); total=total+1
91
92 g_puts("---- wasm_vm exec gate: passed " as *u8); g_pn(pass); g_puts(" / " as *u8); g_pn(total); g_puts(" ----\n" as *u8)
93 if pass == total { g_puts("verdict=GREEN\n" as *u8); sys_exit(0); return 0 }
94 g_puts("verdict=RED\n" as *u8); sys_exit(1); return 1
95}