aboutsummaryrefslogtreecommitdiffstats
path: root/passes
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2017-08-25 16:02:15 +0200
committerClifford Wolf <clifford@clifford.at>2017-08-25 16:02:15 +0200
commitdb6d78a1865456076fccfb44d40fa9a4adecd23b (patch)
tree7f226733bd406806a5e54017b27cfcd24c893a90 /passes
parent86df0fb381682a96dce35978f53a51ad62d036a3 (diff)
downloadyosys-db6d78a1865456076fccfb44d40fa9a4adecd23b.tar.gz
yosys-db6d78a1865456076fccfb44d40fa9a4adecd23b.tar.bz2
yosys-db6d78a1865456076fccfb44d40fa9a4adecd23b.zip
Add removing of redundant pairs of bits in ==, ===, !=, and !== to opt_expr
Diffstat (limited to 'passes')
-rw-r--r--passes/opt/opt_expr.cc72
1 files changed, 72 insertions, 0 deletions
diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc
index b9aa35a9a..08c850a0c 100644
--- a/passes/opt/opt_expr.cc
+++ b/passes/opt/opt_expr.cc
@@ -1252,6 +1252,78 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
}
}
+ // remove redundant pairs of bits in ==, ===, !=, and !==
+ // replace cell with const driver if inputs can't be equal
+ if (do_fine && cell->type.in("$eq", "$ne", "$eqx", "$nex"))
+ {
+ pool<pair<SigBit, SigBit>> redundant_cache;
+ mfp<SigBit> contradiction_cache;
+
+ contradiction_cache.promote(State::S0);
+ contradiction_cache.promote(State::S1);
+
+ int a_width = cell->getParam("\\A_WIDTH").as_int();
+ int b_width = cell->getParam("\\B_WIDTH").as_int();
+
+ bool is_signed = cell->getParam("\\A_SIGNED").as_bool();
+ int width = is_signed ? std::min(a_width, b_width) : std::max(a_width, b_width);
+
+ SigSpec sig_a = cell->getPort("\\A");
+ SigSpec sig_b = cell->getPort("\\B");
+
+ int redundant_bits = 0;
+
+ for (int i = width-1; i >= 0; i--)
+ {
+ SigBit bit_a = i < a_width ? assign_map(sig_a[i]) : State::S0;
+ SigBit bit_b = i < b_width ? assign_map(sig_b[i]) : State::S0;
+ contradiction_cache.merge(bit_a, bit_b);
+
+ if (bit_b < bit_a)
+ std::swap(bit_a, bit_b);
+
+ pair<SigBit, SigBit> key(bit_a, bit_b);
+
+ if (redundant_cache.count(key)) {
+ if (i < a_width) sig_a.remove(i);
+ if (i < b_width) sig_b.remove(i);
+ redundant_bits++;
+ continue;
+ }
+
+ redundant_cache.insert(key);
+ }
+
+ if (contradiction_cache.find(State::S0) == contradiction_cache.find(State::S1))
+ {
+ SigSpec y_sig = cell->getPort("\\Y");
+ Const y_value(cell->type.in("$eq", "$eqx") ? 0 : 1, GetSize(y_sig));
+
+ log("Replacing cell `%s' in module `%s' with constant driver %s.\n",
+ log_id(cell), log_id(module), log_signal(y_value));
+
+ module->connect(y_sig, y_value);
+ module->remove(cell);
+
+ did_something = true;
+ goto next_cell;
+ }
+
+ if (redundant_bits)
+ {
+ log("Removed %d redundant input bits from %s cell `%s' in module `%s'.\n",
+ redundant_bits, log_id(cell->type), log_id(cell), log_id(module));
+
+ cell->setPort("\\A", sig_a);
+ cell->setPort("\\B", sig_b);
+ cell->setParam("\\A_WIDTH", GetSize(sig_a));
+ cell->setParam("\\B_WIDTH", GetSize(sig_b));
+
+ did_something = true;
+ goto next_cell;
+ }
+ }
+
// replace a<0 or a>=0 with the top bit of a
if (do_fine && (cell->type == "$lt" || cell->type == "$ge" || cell->type == "$gt" || cell->type == "$le"))
{