diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index dc7f16782..87ba85785 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -23,6 +23,7 @@ #include "kernel/newcelltypes.h" #include "kernel/utils.h" #include "kernel/log.h" +#include "kernel/unstable/patch.h" #include #include #include @@ -617,17 +618,23 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons log_abort(); } - if (!sig_a.wire) + auto port_a = ID::A; + if (!sig_a.wire) { std::swap(sig_a, sig_b); + port_a = ID::B; + } if (sig_b == State::S0 || sig_b == State::S1) { if (cell->type.in(ID($xor), ID($_XOR_))) { - SigSpec sig_y; - if (cell->type == ID($xor)) - sig_y = (sig_b == State::S1 ? module->Not(NEW_ID, sig_a).as_bit() : sig_a); - else if (cell->type == ID($_XOR_)) - sig_y = (sig_b == State::S1 ? module->NotGate(NEW_ID, sig_a) : sig_a); - else log_abort(); - replace_cell(assign_map, module, cell, "xor_buffer", ID::Y, sig_y); + if (sig_b == State::S0) { + replace_cell(assign_map, module, cell, "xor_buffer", ID::Y, sig_a); + } else { + RTLIL::Patch patcher; + patcher.mod = module; + Wire* y = patcher.addWire(NEW_ID, cell->type == ID($xor) ? cell->getParam(ID::Y_WIDTH).as_int() : 1); + Cell* new_cell = cell->type == ID($xor) ? patcher.addNot(NEW_ID, sig_a, y) : patcher.addNotGate(NEW_ID, sig_a, y); + patcher.leaves = {cell->getPort(port_a).as_wire()}; + patcher.patch(cell, new_cell); + } goto next_cell; } if (cell->type.in(ID($xnor), ID($_XNOR_))) {