code wiki / _hdl_build / nx_eqsat_rule_proof_test.nx
nx_eqsat_rule_proof_test.nx source
↩ module page · 98 lines · 4826 B
1// nx_eqsat_rule_proof_test.nx -- SOVEREIGN soundness proof for the eqsat rewrite rules
2// (algebraic-normal-form leg). Models nx_alu_divider_proof_test.nx: a machine-checked exhaustive
3// small-width check, cross-checked by triangulation legs that all run through nx_gsim (independent
4// of NishiLang `*`/`<<` codegen, because they go via the netlist).
5//
6// WORKED EXAMPLE: certify mul x 8 == shl x 3 BY PROOF (not by battery): build the LHS netlist
7// (MUL x 8) and the RHS netlist (SHL x 3), sweep x over a representative width, and require both
8// legs to equal a third independent oracle on EVERY vector.
9//
10// MIGRATED OFF A HAND-ROLLED VERDICT 2026-08-14, and it had NEVER BEEN COMPILED before that day --
11// nor had nx_eqsat.nx itself, which did not compile at all (a module const read 470 lines above its
12// declaration). So this proof existed on disk, fully written, and had never once run.
13//
14// A NEGATIVE CONTROL WAS ADDED IN THE SAME PASS. The original asserted only that the sound pair
15// AGREES on all 256 vectors. A triangulator that returned pass for everything would have scored
16// full marks -- the gates-green-on-garbage class. The control sweeps an UNSOUND pair (mul x 8 vs
17// shl x FOUR, off by one bit) through the same machinery and requires it to DISAGREE, so a pass on
18// the sound pair now means the comparison can actually fail.
19// license_tier: ORIGINAL expect_exit: 0
20import "nx_gate_verdict.nx"
21import "nx_alu_divider.nx"
22import "nx_triangulate.nx"
23
24const PW: i64 = 8 // representative width: sweep x in [0, 2^PW)
25const PW_VECTORS: i64 = 256 // 2^PW -- named so the anti-vacuity tooth reads as arithmetic, not a magic literal
26
27// Build a fresh single-input gsim with net 0 = x (primary input).
28func _mk(vals: *i64, cells: *NxGsimCell, g: *NxGsim) -> i64 {
29 g.vals = vals; g.n_nets = 1; g.cells = cells; g.n_cells = 0; return 0
30}
31
32func main() -> i64 {
33 gv_head("nx_eqsat rule-soundness gate -- triangulated exhaustive proof of mul-to-shl strength reduction" as *u8)
34 let ctr: *i64 = gv_ctr()
35
36 let vals: *i64 = sys_mmap(64 * 8) as *i64
37 let cells: *NxGsimCell = sys_mmap(64 * 48) as *NxGsimCell
38 let g: *NxGsim = sys_mmap(64) as *NxGsim
39
40 var total: i64 = 0
41 var proven: i64 = 0
42 var unsound_disagreements: i64 = 0
43 var run_ok: i64 = 1
44 let hi: i64 = 1 << PW // 2^PW
45
46 var x: i64 = 0
47 while x < hi {
48 // LEG A (LHS): MUL x 8 via the netlist (independent of native `*`)
49 _mk(vals, cells, g)
50 let c8: i64 = div_const(g, 8)
51 let prod: i64 = div_op2(g, NX_GATE_KIND_MUL, 0, c8)
52 g.vals[0] = x
53 if nx_gsim_run(g) != NX_GSIM_OK { run_ok = 0 }
54 let lhs: i64 = g.vals[prod]
55
56 // LEG B (RHS): SHL x 3 via the netlist (independent of native `<<`)
57 _mk(vals, cells, g)
58 let c3: i64 = div_const(g, 3)
59 let shft: i64 = div_op2(g, NX_GATE_KIND_SHL, 0, c3)
60 g.vals[0] = x
61 if nx_gsim_run(g) != NX_GSIM_OK { run_ok = 0 }
62 let rhs: i64 = g.vals[shft]
63
64 // ORACLE: x * 8 computed directly (third independent source)
65 let oracle: i64 = x * 8
66
67 // Triangulate: 2 independent netlist legs must BOTH equal the oracle.
68 let legs: *i64 = sys_mmap(2 * 8) as *i64
69 legs[0] = lhs
70 legs[1] = rhs
71 let v: *NxTriVerdict = sys_mmap(64) as *NxTriVerdict
72 let rc: i64 = nx_tri_pass_strict(legs, 2, oracle, 2, v)
73 total = total + 1
74 if rc == 1 { proven = proven + 1 }
75
76 // NEGATIVE CONTROL, same machinery, deliberately WRONG shift amount.
77 _mk(vals, cells, g)
78 let c4: i64 = div_const(g, 4)
79 let bad: i64 = div_op2(g, NX_GATE_KIND_SHL, 0, c4)
80 g.vals[0] = x
81 if nx_gsim_run(g) != NX_GSIM_OK { run_ok = 0 }
82 if g.vals[bad] != oracle { unsound_disagreements = unsound_disagreements + 1 }
83
84 x = x + 1
85 }
86
87 gv_check("every swept vector triangulates: two netlist legs and the oracle agree" as *u8, proven == total, ctr)
88 // BIND THE AGGREGATE TO ITS DENOMINATOR. proven==total is trivially true over an EMPTY sweep,
89 // so the count itself has to be asserted or the tooth passes on the empty set.
90 gv_check("the sweep actually covered all 2^PW vectors" as *u8, total == PW_VECTORS, ctr)
91 gv_check("every netlist evaluation completed" as *u8, run_ok == 1, ctr)
92 // WITHOUT THIS THE GATE IS VACUOUS: it proves the comparison can return NOT-equal, so the
93 // agreement above is a finding rather than a constant.
94 gv_check("neg-control-unsound-shift-by-4-DISAGREES-with-mul-by-8" as *u8, unsound_disagreements > 0, ctr)
95
96 return gv_verdict("nx_eqsat_rule_proof_test" as *u8, ctr,
97 "exhaustive 256-vector triangulated proof of mul-to-shl, with an unsound-pair control proving the comparison can fail" as *u8)
98}