code wiki / _hdl_build / nx_rule_soundness.nx
nx_rule_soundness.nx
buildroot/runtime/_hdl_build/nx_rule_soundness.nx
about
nx_rule_soundness.nx -- SOVEREIGN soundness prover for the nx_eqsat rewrite
rules. Each rule in nx_eqsat.nx does a union that ASSERTS an algebraic
equivalence; this organ PROVES that equivalence holds for ALL inputs in W-bit
(mod 2^W) arithmetic, via the winning strategy:
(1) WIDTH-INDEPENDENT INDUCTION (reuses the nx_alu_divider_proof_test.nx
template): prove a per-element invariant EXHAUSTIVELY at a representative
width W, plus a width-independence argument (per_rule comments) that
lifts the W=8 machine-check to ANY W. For the SIX width-trivial unary
rules {add_zero, sub_self, add_self, and_self, or_zero, mul_one} the
lift is genuine: identity-element / group-inverse / per-bit-idempotence /
k=1-shift laws DO NOT depend on W. For mul_pow2 it is k-induction with
the side-condition k+1<W (base k=0, step *2 == <<1 mod 2^W).
(2) EXHAUSTIVE SMALL-WIDTH: enumerate every x in [0,2^W) (and, for mul_pow2,
every k in [0,W)) -- a real proof over the rule's full local operand
space at W, NOT sampling.
(3) nx_triangulate AS INDEPENDENT CROSS-CHECK: two independent gsim legs
(LHS-eval, RHS-eval) plus an independent oracle, fed to nx_tri_pass_strict
(unanimity, k_min = n_legs). Defense in depth.
TWO INDEPENDENT WITNESSES, ANDed (honoring the design's two-witness claim):
- WITNESS A (algebraic, SEPARATELY CODED): a NishiLang-native masked-arith
computation of the rule's invariant, computed WITHOUT reading the gsim legs
(so it is independent of the gsim truncation behavior). Asserts the masked
identity directly.
- WITNESS B (triangulation over gsim legs): the two netlist evaluators must
BOTH equal the masked oracle.
A rule vector is CERTIFIED iff WITNESS A holds AND WITNESS B passes.
TRUNCATION-GAP DEFENSE (adversarial trap #1): nx_gsim_eval_cell computes a*b,
a<<b, a+b, a-b in FULL i64 with ZERO truncation. So this organ MASKS every
evaluator output (and the oracle) to (1<<W)-1 BEFORE comparison -- the check
then tests the real mod-2^W identity, not a coincidental i64 identity. The
algebraic witness also masks. No rule is certified on raw unmasked i64.
k>=W BOUNDARY DEFENSE (adversarial trap #2): mul_pow2 fires unbounded in
nx_eqsat.nx (NO k<W guard -- owed). For k>=W the identity is FALSE
(2^k mod 2^W == 0 so x*2^k mod 2^W == 0 for all x, but x<<k is an out-of-range
dependencies 2 imports · 3 importers
imports: nx_alu_divider.nxnx_triangulate.nx
imported by: nx_rule_soundness_test.nxnx_self_build_cycle_test.nxnx_self_repair_cycle_test.nx
structs
| none |
consts
| 55 | const NX_RS_ADD_ZERO: i64 = 1 |
| 56 | const NX_RS_SUB_SELF: i64 = 2 |
| 57 | const NX_RS_ADD_SELF: i64 = 3 |
| 58 | const NX_RS_AND_SELF: i64 = 4 |
| 59 | const NX_RS_OR_ZERO: i64 = 5 |
| 60 | const NX_RS_MUL_ONE: i64 = 6 |
| 64 | const NX_RS_OOR: i64 = 0 - 999999 |
functions
| 67 | func nx_rs_mask(w: i64) -> i64 { return (1 << w) - 1 } |
| 71 | func nx_rs_mk(vals: *i64, cells: *NxGsimCell, g: *NxGsim) -> i64 |
| 79 | func nx_rs_witness_a(rule: i64, x: i64, w: i64) -> i64 |
| 108 | func nx_rs_oracle(rule: i64, x: i64, w: i64) -> i64 |
| 122 | func nx_rs_eval_lhs(rule: i64, x: i64, w: i64, vals: *i64, cells: *NxGsimCell, g: *NxGsim) -> i64 |
| 153 | func nx_rs_eval_rhs(rule: i64, x: i64, w: i64, vals: *i64, cells: *NxGsimCell, g: *NxGsim) -> i64 |
| 176 | func nx_rs_certify_unary(rule: i64, x: i64, w: i64, |
| 196 | func nx_rs_pow2(k: i64, w: i64) -> i64 |
| 206 | func nx_rs_mulpow2_oracle(x: i64, k: i64, w: i64) -> i64 |
| 215 | func nx_rs_mulpow2_witness_a(x: i64, k: i64, w: i64) -> i64 |
| 226 | func nx_rule_shl_wbit(x: i64, k: i64, w: i64) -> i64 |
| 235 | func nx_rs_certify_mulpow2(x: i64, k: i64, w: i64, called by 2: mainsr_mulpow2_guarded_sound calls 9: nx_rs_masknx_rs_pow2nx_rs_mulpow2_oraclenx_rs_mkdiv_constdiv_op2+3 |
| 272 | func nx_rs_mulpow2_boundary_unsound(x: i64, k: i64, w: i64) -> i64 |