From df43a3097a9f20353712782e6bedae76aaa7dd6b Mon Sep 17 00:00:00 2001 From: Abhinav Tondapu Date: Mon, 30 Mar 2026 16:30:46 -0700 Subject: [PATCH] [ENG-1692] negopt runtime fix + small cleanup --- passes/silimate/negopt.cc | 22 +++++++++++- passes/silimate/peepopt_manual2sub.pmg | 6 ++-- passes/silimate/peepopt_muxneg.pmg | 2 +- passes/silimate/peepopt_negmux.pmg | 6 ++-- passes/silimate/peepopt_negneg.pmg | 2 +- passes/silimate/peepopt_negrebuild.pmg | 18 +++++++--- tests/silimate/negmux.ys | 50 ++++++++++++++++++++++++++ tests/silimate/negrebuild.ys | 29 +++++++++++++++ 8 files changed, 123 insertions(+), 12 deletions(-) diff --git a/passes/silimate/negopt.cc b/passes/silimate/negopt.cc index c658807b4..7d774375c 100644 --- a/passes/silimate/negopt.cc +++ b/passes/silimate/negopt.cc @@ -24,6 +24,26 @@ PRIVATE_NAMESPACE_BEGIN bool did_something; +// Normalize top-end sign/zero extension for PMG prefiltering +static SigSpec strip_ext_for_match(SigSpec sig) +{ + int n = GetSize(sig); + if (n <= 1) + return sig; + + while (n > 1) { + SigBit top = sig[n-1]; + SigBit prev = sig[n-2]; + if (top == prev || top == SigBit(State::S0)) { + n--; + continue; + } + break; + } + + return sig.extract(0, n); +} + #include "passes/silimate/peepopt_negopt.h" struct NegoptPass : public Pass { @@ -51,7 +71,7 @@ struct NegoptPass : public Pass { log(" - muxneg: s?(-a):(-b) => -(s?a:b)\n"); log(" - neg2sub: a + (-b) => a - b\n" ); log("\n"); - log("When called without options, both -pre and -post are executed.\n"); + log("Specify exactly one of -pre or -post.\n"); log("\n"); } diff --git a/passes/silimate/peepopt_manual2sub.pmg b/passes/silimate/peepopt_manual2sub.pmg index 257c93b86..898958b58 100644 --- a/passes/silimate/peepopt_manual2sub.pmg +++ b/passes/silimate/peepopt_manual2sub.pmg @@ -169,8 +169,8 @@ code root_add inner_add_B not_gate_B minuend subtrahend result_sig is_signed // Verify inner_add_B has the form (~b + 1): one port is constant 1, // the other is the NOT output - SigSpec pa = inner_add_B->getPort(ID::A); - SigSpec pb = inner_add_B->getPort(ID::B); + SigSpec pa = port(inner_add_B, \A); + SigSpec pb = port(inner_add_B, \B); SigSpec not_y = port(not_gate_B, \Y); auto is_one = [](SigSpec s) { @@ -191,7 +191,7 @@ code root_add inner_add_B not_gate_B minuend subtrahend result_sig is_signed // The minuend is whichever root_add port is NOT the inner_add_B output subtrahend = port(not_gate_B, \A); - if (inner_add_B->getPort(ID::Y) == root_add->getPort(ID::A)) + if (port(inner_add_B, \Y) == port(root_add, \A)) minuend = root_b; else minuend = root_a; diff --git a/passes/silimate/peepopt_muxneg.pmg b/passes/silimate/peepopt_muxneg.pmg index 5d03ad7e9..4b098ebd1 100644 --- a/passes/silimate/peepopt_muxneg.pmg +++ b/passes/silimate/peepopt_muxneg.pmg @@ -48,7 +48,7 @@ code mux_a mux_b mux_s mux_y neg_a_in neg_a_y neg_b_in neg_b_y neg_a_signed neg_ SigSpec neg_a_rs = neg_a_in; SigSpec neg_b_rs = neg_b_in; neg_a_rs.extend_u0(width, neg_a_signed); - neg_b_rs.extend_u0(width, neg_a_signed); + neg_b_rs.extend_u0(width, neg_b_signed); SigSpec mux_out = module->addWire(NEW_ID2_SUFFIX("y"), width); Cell *new_mux = module->addMux(NEW_ID2_SUFFIX("mux"), neg_a_rs, neg_b_rs, mux_s, mux_out); diff --git a/passes/silimate/peepopt_negmux.pmg b/passes/silimate/peepopt_negmux.pmg index fbedbf507..cfa1415f9 100644 --- a/passes/silimate/peepopt_negmux.pmg +++ b/passes/silimate/peepopt_negmux.pmg @@ -7,7 +7,7 @@ pattern negmux // -(s ? a : b) ===> s ? (-a) : (-b) // -state neg_a neg_y mux_a mux_b mux_s mux_y +state neg_a neg_y neg_a_norm mux_a mux_b mux_s mux_y state a_signed match neg @@ -15,11 +15,13 @@ match neg set neg_a port(neg, \A) set neg_y port(neg, \Y) set a_signed neg->getParam(\A_SIGNED).as_bool() + set neg_a_norm strip_ext_for_match(neg_a) endmatch match mux select mux->type == $mux - select nusers(port(mux, \Y)) == 2 + index strip_ext_for_match(port(mux, \Y)) === neg_a_norm + filter nusers(port(mux, \Y)) == 2 set mux_a port(mux, \A) set mux_b port(mux, \B) set mux_s port(mux, \S) diff --git a/passes/silimate/peepopt_negneg.pmg b/passes/silimate/peepopt_negneg.pmg index 09d7aa543..61d03bcc9 100644 --- a/passes/silimate/peepopt_negneg.pmg +++ b/passes/silimate/peepopt_negneg.pmg @@ -23,7 +23,7 @@ match neg2 endmatch code neg1_a neg1_y neg2_a - // Reject if inner negation truncates + // Reject if the inner negation widens its output if (GetSize(neg1_a) > GetSize(neg2_a)) reject; diff --git a/passes/silimate/peepopt_negrebuild.pmg b/passes/silimate/peepopt_negrebuild.pmg index 49683f09f..1094d6389 100644 --- a/passes/silimate/peepopt_negrebuild.pmg +++ b/passes/silimate/peepopt_negrebuild.pmg @@ -7,8 +7,8 @@ pattern negrebuild // (-a) + (-b) ===> -(a + b) // -state add_a add_b add_y neg1_a neg1_y neg2_a neg2_y -state add_signed add_b_signed neg1_signed neg2_signed +state add_a add_b add_y add_a_norm add_b_norm neg1_a neg1_y neg2_a neg2_y +state add_signed add_b_signed neg1_signed neg2_signed neg1_on_a match add select add->type == $add @@ -17,11 +17,20 @@ match add set add_y port(add, \Y) set add_signed add->getParam(\A_SIGNED).as_bool() set add_b_signed add->getParam(\B_SIGNED).as_bool() + set add_a_norm strip_ext_for_match(add_a) + set add_b_norm strip_ext_for_match(add_b) endmatch +code neg1_on_a + neg1_on_a = true; + branch; + neg1_on_a = false; +endcode + match neg1 select neg1->type == $neg - select nusers(port(neg1, \Y)) == 2 + index strip_ext_for_match(port(neg1, \Y)) === (neg1_on_a ? add_a_norm : add_b_norm) + filter nusers(port(neg1, \Y)) == 2 set neg1_a port(neg1, \A) set neg1_y port(neg1, \Y) set neg1_signed neg1->getParam(\A_SIGNED).as_bool() @@ -29,7 +38,8 @@ endmatch match neg2 select neg2->type == $neg - select nusers(port(neg2, \Y)) == 2 + index strip_ext_for_match(port(neg2, \Y)) === (neg1_on_a ? add_b_norm : add_a_norm) + filter nusers(port(neg2, \Y)) == 2 set neg2_a port(neg2, \A) set neg2_y port(neg2, \Y) set neg2_signed neg2->getParam(\A_SIGNED).as_bool() diff --git a/tests/silimate/negmux.ys b/tests/silimate/negmux.ys index 92eacd53b..1caafa7d0 100644 --- a/tests/silimate/negmux.ys +++ b/tests/silimate/negmux.ys @@ -42,6 +42,56 @@ select -assert-count 2 t:$neg design -reset log -pop +log -header "Positive case: neg input is sign extension of mux output" +log -push +design -reset +read_verilog <