diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 5a39378d9..4f810c35a 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -1520,6 +1520,27 @@ skip_identity: goto next_cell; } + if (consume_x && mux_bool && (cell->type == ID($_MUX_) || (cell->type == ID($mux) && cell->parameters[ID::WIDTH] == 1)) && cell->getPort(ID::A) == State::S1) { + cover_list("opt.opt_expr.mux_ornot", "$mux", "$_MUX_", cell->type.str()); + log_debug("Replacing %s cell `%s' in module `%s' with or-gate and not-gate.\n", log_id(cell->type), log_id(cell), log_id(module)); + cell->setPort(ID::A, module->Not(NEW_ID2_SUFFIX("not"), cell->getPort(ID::S), false, cell->get_src_attribute())); + cell->unsetPort(ID::S); + if (cell->type == ID($mux)) { + Const width = cell->parameters[ID::WIDTH]; + cell->parameters[ID::A_WIDTH] = width; + cell->parameters[ID::B_WIDTH] = width; + cell->parameters[ID::Y_WIDTH] = width; + cell->parameters[ID::A_SIGNED] = 0; + cell->parameters[ID::B_SIGNED] = 0; + cell->parameters.erase(ID::WIDTH); + cell->type = ID($or); + } else + cell->type = ID($_OR_); + module->rename(cell, NEW_ID2_SUFFIX("ornot")); + did_something = true; + goto next_cell; + } + if (consume_x && mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && cell->getPort(ID::B) == State::S1) { cover_list("opt.opt_expr.mux_or", "$mux", "$_MUX_", cell->type.str()); log_debug("Replacing %s cell `%s' in module `%s' with or-gate.\n", log_id(cell->type), log_id(cell), log_id(module)); @@ -1540,6 +1561,27 @@ skip_identity: goto next_cell; } + if (consume_x && mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && cell->getPort(ID::B) == State::S0) { + cover_list("opt.opt_expr.mux_andnot", "$mux", "$_MUX_", cell->type.str()); + log_debug("Replacing %s cell `%s' in module `%s' with and-gate and not-gate.\n", log_id(cell->type), log_id(cell), log_id(module)); + cell->setPort(ID::B, module->Not(NEW_ID2_SUFFIX("not"), cell->getPort(ID::S), false, cell->get_src_attribute())); + cell->unsetPort(ID::S); + if (cell->type == ID($mux)) { + Const width = cell->parameters[ID::WIDTH]; + cell->parameters[ID::A_WIDTH] = width; + cell->parameters[ID::B_WIDTH] = width; + cell->parameters[ID::Y_WIDTH] = width; + cell->parameters[ID::A_SIGNED] = 0; + cell->parameters[ID::B_SIGNED] = 0; + cell->parameters.erase(ID::WIDTH); + cell->type = ID($and); + } else + cell->type = ID($_AND_); + module->rename(cell, NEW_ID2_SUFFIX("andnot")); + did_something = true; + goto next_cell; + } + if (mux_undef && cell->type.in(ID($mux), ID($pmux))) { RTLIL::SigSpec new_a, new_b, new_s; int width = GetSize(cell->getPort(ID::A));