From 6de80bc6b388a7d294fd711c3a34226f8b1a9acb Mon Sep 17 00:00:00 2001 From: Alain Dargelas Date: Mon, 10 Mar 2025 13:47:06 -0700 Subject: [PATCH 1/2] neg sub pass --- passes/opt/Makefile.inc | 1 + passes/opt/peepopt.cc | 1 + passes/opt/peepopt_sub_neg.pmg | 62 ++++++++++++++++++++ tests/peepopt/neg_sub.ys | 102 +++++++++++++++++++++++++++++++++ 4 files changed, 166 insertions(+) create mode 100644 passes/opt/peepopt_sub_neg.pmg create mode 100644 tests/peepopt/neg_sub.ys diff --git a/passes/opt/Makefile.inc b/passes/opt/Makefile.inc index 9dd90072d..8b973c9a8 100644 --- a/passes/opt/Makefile.inc +++ b/passes/opt/Makefile.inc @@ -34,6 +34,7 @@ PEEPOPT_PATTERN += passes/opt/peepopt_muldiv.pmg PEEPOPT_PATTERN += passes/opt/peepopt_muldiv_c.pmg PEEPOPT_PATTERN += passes/opt/peepopt_muxorder.pmg PEEPOPT_PATTERN += passes/opt/peepopt_formal_clockgateff.pmg +PEEPOPT_PATTERN += passes/opt/peepopt_sub_neg.pmg passes/opt/peepopt_pm.h: passes/pmgen/pmgen.py $(PEEPOPT_PATTERN) $(P) mkdir -p $(dir $@) && $(PYTHON_EXECUTABLE) $< -o $@ -p peepopt $(filter-out $<,$^) diff --git a/passes/opt/peepopt.cc b/passes/opt/peepopt.cc index 8448b0485..cb6174d66 100644 --- a/passes/opt/peepopt.cc +++ b/passes/opt/peepopt.cc @@ -121,6 +121,7 @@ struct PeepoptPass : public Pass { pm.run_shiftmul_left(); pm.run_muldiv(); pm.run_muldiv_c(); + pm.run_sub_neg(); if (muxorder) pm.run_muxorder(); } diff --git a/passes/opt/peepopt_sub_neg.pmg b/passes/opt/peepopt_sub_neg.pmg new file mode 100644 index 000000000..0b23c1ea4 --- /dev/null +++ b/passes/opt/peepopt_sub_neg.pmg @@ -0,0 +1,62 @@ +pattern sub_neg +// +// Authored by Akash Levy and Alain Dargelas of Silimate, Inc. under ISC license. +// Transforms -(a-b) ----> (b-a) + +state a b sub_y + +match sub + // Select sub + select sub->type == $sub +endmatch + +code a b sub_y + // Get sub signals + a = port(sub, \A); + b = port(sub, \B); + sub_y = port(sub, \Y); + + bool a_signed = sub->getParam(ID::A_SIGNED).as_bool(); + bool b_signed = sub->getParam(ID::B_SIGNED).as_bool(); + + // Fanout of each sub Y bit should be 1 (no bit-split) + if (nusers(sub_y) != 2) + reject; + + // Both operands need to be signed to be swapped + if (!a_signed || !b_signed) + reject; + + // A and B can be interchanged + branch; + std::swap(a, b); +endcode + +match neg + // Select neg of form -(a-b) + select neg->type == $neg + + index remove_bottom_padding(port(neg, \A)) === sub_y +endmatch + +code + // Get neg signals + SigSpec neg_a = port(neg, \A); + SigSpec neg_y = port(neg, \Y); + + bool a_signed = neg->getParam(ID::A_SIGNED).as_bool(); + if (!a_signed) + reject; + + // Rewire to only keep sub + sub->setPort(\A, b); + sub->setPort(\B, a); + sub->setPort(\Y, neg_y); + + // Remove neg + autoremove(neg); + + // Log, fixup, accept + log("sub_neg pattern in %s: neg=%s, sub=%s\n", log_id(module), log_id(neg), log_id(sub)); + accept; +endcode diff --git a/tests/peepopt/neg_sub.ys b/tests/peepopt/neg_sub.ys new file mode 100644 index 000000000..17980f632 --- /dev/null +++ b/tests/peepopt/neg_sub.ys @@ -0,0 +1,102 @@ +log -header "Test simple positive case" +log -push +design -reset +read_verilog < Date: Mon, 10 Mar 2025 14:44:14 -0700 Subject: [PATCH 2/2] Code review --- passes/opt/peepopt_sub_neg.pmg | 4 +-- tests/peepopt/neg_sub.ys | 46 ++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/passes/opt/peepopt_sub_neg.pmg b/passes/opt/peepopt_sub_neg.pmg index 0b23c1ea4..24e617052 100644 --- a/passes/opt/peepopt_sub_neg.pmg +++ b/passes/opt/peepopt_sub_neg.pmg @@ -20,8 +20,8 @@ code a b sub_y bool b_signed = sub->getParam(ID::B_SIGNED).as_bool(); // Fanout of each sub Y bit should be 1 (no bit-split) - if (nusers(sub_y) != 2) - reject; + if (nusers(sub_y) != 2) + reject; // Both operands need to be signed to be swapped if (!a_signed || !b_signed) diff --git a/tests/peepopt/neg_sub.ys b/tests/peepopt/neg_sub.ys index 17980f632..5926f2b6b 100644 --- a/tests/peepopt/neg_sub.ys +++ b/tests/peepopt/neg_sub.ys @@ -100,3 +100,49 @@ select -assert-any t:$neg select -assert-any t:$sub design -reset log -pop + +log -header "Negative case with disconnected intermediate signal (operator in the middle)" +log -push +design -reset +read_verilog <