From 406b400458619e1491b2fd0b97b625fba6f80021 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 4 Apr 2025 12:25:31 +1300 Subject: [PATCH] opt_expr: Fix #4590 If all the (non-select) inputs of a `$_MUX{4,8,16}_` are undefined, replace it, just like we do for `$mux` and `$_MUX_`. Add `tests/opt/opt_expr_mux_undef.ys` to verify this. This doesn't do any const folding on the wide muxes, or shrinking to less wide muxes. It only handles the case where all inputs are 'x and the mux can be completely removed. --- passes/opt/opt_expr.cc | 14 ++ tests/opt/opt_expr_mux_undef.ys | 290 ++++++++++++++++++++++++++++++++ 2 files changed, 304 insertions(+) create mode 100644 tests/opt/opt_expr_mux_undef.ys diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 9967c7753..df969daf0 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -1573,6 +1573,20 @@ skip_identity: } } + if (mux_undef && cell->type.in(ID($_MUX4_), ID($_MUX8_), ID($_MUX16_))) { + int num_inputs = 4; + if (cell->type == ID($_MUX8_)) num_inputs = 8; + if (cell->type == ID($_MUX16_)) num_inputs = 16; + int undef_inputs = 0; + for (auto &conn : cell->connections()) + if (!conn.first.in(ID::S, ID::T, ID::U, ID::V, ID::Y)) + undef_inputs += conn.second.is_fully_undef(); + if (undef_inputs == num_inputs) { + replace_cell(assign_map, module, cell, "mux_undef", ID::Y, cell->getPort(ID::A)); + goto next_cell; + } + } + #define FOLD_1ARG_CELL(_t) \ if (cell->type == ID($##_t)) { \ RTLIL::SigSpec a = cell->getPort(ID::A); \ diff --git a/tests/opt/opt_expr_mux_undef.ys b/tests/opt/opt_expr_mux_undef.ys new file mode 100644 index 000000000..83c29e07b --- /dev/null +++ b/tests/opt/opt_expr_mux_undef.ys @@ -0,0 +1,290 @@ + +read_rtlil <