aboutsummaryrefslogtreecommitdiffstats
path: root/passes/opt/opt_const.cc
diff options
context:
space:
mode:
Diffstat (limited to 'passes/opt/opt_const.cc')
-rw-r--r--passes/opt/opt_const.cc36
1 files changed, 20 insertions, 16 deletions
diff --git a/passes/opt/opt_const.cc b/passes/opt/opt_const.cc
index b7b361e95..0ead97b4e 100644
--- a/passes/opt/opt_const.cc
+++ b/passes/opt/opt_const.cc
@@ -17,8 +17,6 @@
*
*/
-#undef MUX_UNDEF_SEL_TO_UNDEF_RESULTS
-
#include "opt_status.h"
#include "kernel/register.h"
#include "kernel/sigtools.h"
@@ -133,18 +131,19 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
ACTION_DO("\\Y", input.extract(2, 1));
if (input.match(" 0")) ACTION_DO("\\Y", input.extract(2, 1));
if (input.match(" 1")) ACTION_DO("\\Y", input.extract(1, 1));
-#ifdef MUX_UNDEF_SEL_TO_UNDEF_RESULTS
if (input.match("01 ")) ACTION_DO("\\Y", input.extract(0, 1));
- // TODO: "10 " -> replace with "!S" gate
- // TODO: "0 " -> replace with "B AND S" gate
- // TODO: " 1 " -> replace with "A OR S" gate
- // TODO: "1 " -> replace with "B OR !S" gate (?)
- // TODO: " 0 " -> replace with "A AND !S" gate (?)
- if (input.match(" *")) ACTION_DO_Y(x);
-#endif
+ if (input.match("10 ")) {
+ cell->type = "$_INV_";
+ cell->connections["\\A"] = input.extract(0, 1);
+ cell->connections.erase("\\B");
+ cell->connections.erase("\\S");
+ goto next_cell;
+ }
+ if (input.match("01*")) ACTION_DO_Y(x);
+ if (input.match("10*")) ACTION_DO_Y(x);
}
- if (cell->type == "$eq" || cell->type == "$ne")
+ if (cell->type == "$eq" || cell->type == "$ne" || cell->type == "$eqx" || cell->type == "$nex")
{
RTLIL::SigSpec a = cell->connections["\\A"];
RTLIL::SigSpec b = cell->connections["\\B"];
@@ -160,22 +159,27 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
assert(a.chunks.size() == b.chunks.size());
for (size_t i = 0; i < a.chunks.size(); i++) {
- if (a.chunks[i].wire == NULL && a.chunks[i].data.bits[0] > RTLIL::State::S1)
- continue;
- if (b.chunks[i].wire == NULL && b.chunks[i].data.bits[0] > RTLIL::State::S1)
+ if (a.chunks[i].wire == NULL && b.chunks[i].wire == NULL && a.chunks[i].data.bits[0] != b.chunks[i].data.bits[0] &&
+ a.chunks[i].data.bits[0] <= RTLIL::State::S1 && b.chunks[i].data.bits[0] <= RTLIL::State::S1) {
+ RTLIL::SigSpec new_y = RTLIL::SigSpec((cell->type == "$eq" || cell->type == "$eqx") ? RTLIL::State::S0 : RTLIL::State::S1);
+ new_y.extend(cell->parameters["\\Y_WIDTH"].as_int(), false);
+ replace_cell(module, cell, "empty", "\\Y", new_y);
+ goto next_cell;
+ }
+ if (a.chunks[i] == b.chunks[i])
continue;
new_a.append(a.chunks[i]);
new_b.append(b.chunks[i]);
}
if (new_a.width == 0) {
- RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type == "$eq" ? RTLIL::State::S1 : RTLIL::State::S0);
+ RTLIL::SigSpec new_y = RTLIL::SigSpec((cell->type == "$eq" || cell->type == "$eqx") ? RTLIL::State::S1 : RTLIL::State::S0);
new_y.extend(cell->parameters["\\Y_WIDTH"].as_int(), false);
replace_cell(module, cell, "empty", "\\Y", new_y);
goto next_cell;
}
- if (new_a.width != a.width) {
+ if (new_a.width < a.width || new_b.width < b.width) {
new_a.optimize();
new_b.optimize();
cell->connections["\\A"] = new_a;