From 398afd102e036000d9a7b19b08d4f474cb85bba1 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:05:39 +1300 Subject: [PATCH 01/26] Refactor full_selection The `Design::selected_*()` methods no longer unconditionally skip boxed modules. Instead, selections are now box and design aware. The selection constructor now optionally takes a design pointer, and has a new `selects_boxes` flag. If the selection has an assigned design, then `Selection::selected_*()` will only return true for boxed modules if the selects_boxes flag is set. A warning is raised if a selection is checked and no design is set. Selections can change design via the `Selection::optimize()` method. Most places that iterate over `Design::modules()` and check `Selection::selected_module()` should instead use `Design::selected_modules()`. Since boxed modules should only ever be selected explicitly, and `full_selection` (now) refers to all non-boxed modules, `Selection::optimize()` will clear the `full_selection` flag if the `selects_boxes` flag is enabled, and instead explicitly selects all modules (including boxed modules). This also means that `full_selection` will only get automatically applied to a design without any boxed modules. These changes necessitated a number of changes to `select.cc` in order to support this functionality when operating on selections, in particular when combining selections (e.g. by union or difference). To minimize redundancy, a number of places that previously iterated over `design->modules()` now push the current selection to the design, use `design->selected_modules()`, and then pop the selection when done. Introduce `RTLIL::NamedObject`, to allow for iterating over all members of a module with a single iterator instead of needing to iterate over wires, cells, memories, and processes separately. Also implement `Module::selected_{memories, processes, members}()` to match wires and cells methods. The `selected_members()` method combines each of the other `selected_*()` methods into a single list. --- kernel/rtlil.cc | 90 +++++++++++++++++--- kernel/rtlil.h | 29 ++++--- passes/cmds/select.cc | 192 ++++++++++++++++++++++-------------------- 3 files changed, 197 insertions(+), 114 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 3b9a4a8b1..8c40e83d3 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -766,8 +766,21 @@ vector RTLIL::AttrObject::get_intvec_attribute(const RTLIL::IdString &id) c return data; } +bool RTLIL::Selection::boxed_module(const RTLIL::IdString &mod_name) const +{ + if (current_design != nullptr) { + auto module = current_design->module(mod_name); + return module && module->get_blackbox_attribute(); + } else { + log_warning("Unable to check if module is boxed for null design.\n"); + return false; + } +} + bool RTLIL::Selection::selected_module(const RTLIL::IdString &mod_name) const { + if (!selects_boxes && boxed_module(mod_name)) + return false; if (full_selection) return true; if (selected_modules.count(mod_name) > 0) @@ -779,6 +792,8 @@ bool RTLIL::Selection::selected_module(const RTLIL::IdString &mod_name) const bool RTLIL::Selection::selected_whole_module(const RTLIL::IdString &mod_name) const { + if (!selects_boxes && boxed_module(mod_name)) + return false; if (full_selection) return true; if (selected_modules.count(mod_name) > 0) @@ -788,6 +803,8 @@ bool RTLIL::Selection::selected_whole_module(const RTLIL::IdString &mod_name) co bool RTLIL::Selection::selected_member(const RTLIL::IdString &mod_name, const RTLIL::IdString &memb_name) const { + if (!selects_boxes && boxed_module(mod_name)) + return false; if (full_selection) return true; if (selected_modules.count(mod_name) > 0) @@ -800,6 +817,19 @@ bool RTLIL::Selection::selected_member(const RTLIL::IdString &mod_name, const RT void RTLIL::Selection::optimize(RTLIL::Design *design) { + if (design != current_design) { + current_design = design; + } + + if (selects_boxes && full_selection) { + selected_modules.clear(); + selected_members.clear(); + full_selection = false; + for (auto mod : current_design->modules()) { + selected_modules.insert(mod->name); + } + return; + } if (full_selection) { selected_modules.clear(); selected_members.clear(); @@ -810,7 +840,7 @@ void RTLIL::Selection::optimize(RTLIL::Design *design) del_list.clear(); for (auto mod_name : selected_modules) { - if (design->modules_.count(mod_name) == 0) + if (current_design->modules_.count(mod_name) == 0) del_list.push_back(mod_name); selected_members.erase(mod_name); } @@ -819,7 +849,7 @@ void RTLIL::Selection::optimize(RTLIL::Design *design) del_list.clear(); for (auto &it : selected_members) - if (design->modules_.count(it.first) == 0) + if (current_design->modules_.count(it.first) == 0) del_list.push_back(it.first); for (auto mod_name : del_list) selected_members.erase(mod_name); @@ -827,7 +857,7 @@ void RTLIL::Selection::optimize(RTLIL::Design *design) for (auto &it : selected_members) { del_list.clear(); for (auto memb_name : it.second) - if (design->modules_[it.first]->count_id(memb_name) == 0) + if (current_design->modules_[it.first]->count_id(memb_name) == 0) del_list.push_back(memb_name); for (auto memb_name : del_list) it.second.erase(memb_name); @@ -838,8 +868,8 @@ void RTLIL::Selection::optimize(RTLIL::Design *design) for (auto &it : selected_members) if (it.second.size() == 0) del_list.push_back(it.first); - else if (it.second.size() == design->modules_[it.first]->wires_.size() + design->modules_[it.first]->memories.size() + - design->modules_[it.first]->cells_.size() + design->modules_[it.first]->processes.size()) + else if (it.second.size() == current_design->modules_[it.first]->wires_.size() + current_design->modules_[it.first]->memories.size() + + current_design->modules_[it.first]->cells_.size() + current_design->modules_[it.first]->processes.size()) add_list.push_back(it.first); for (auto mod_name : del_list) selected_members.erase(mod_name); @@ -848,7 +878,7 @@ void RTLIL::Selection::optimize(RTLIL::Design *design) selected_modules.insert(mod_name); } - if (selected_modules.size() == design->modules_.size()) { + if (!selects_boxes && selected_modules.size() == current_design->modules_.size()) { full_selection = true; selected_modules.clear(); selected_members.clear(); @@ -863,7 +893,7 @@ RTLIL::Design::Design() hashidx_ = hashidx_count; refcount_modules_ = 0; - selection_stack.push_back(RTLIL::Selection()); + selection_stack.push_back(RTLIL::Selection(true, false, this)); #ifdef WITH_PYTHON RTLIL::Design::get_all_designs()->insert(std::pair(hashidx_, this)); @@ -1127,7 +1157,7 @@ std::vector RTLIL::Design::selected_modules() const std::vector result; result.reserve(modules_.size()); for (auto &it : modules_) - if (selected_module(it.first) && !it.second->get_blackbox_attribute()) + if (selected_module(it.first)) result.push_back(it.second); return result; } @@ -1137,7 +1167,7 @@ std::vector RTLIL::Design::selected_whole_modules() const std::vector result; result.reserve(modules_.size()); for (auto &it : modules_) - if (selected_whole_module(it.first) && !it.second->get_blackbox_attribute()) + if (selected_whole_module(it.first)) result.push_back(it.second); return result; } @@ -1146,13 +1176,13 @@ std::vector RTLIL::Design::selected_whole_modules_warn(bool incl { std::vector result; result.reserve(modules_.size()); - for (auto &it : modules_) - if (it.second->get_blackbox_attribute(include_wb)) - continue; - else if (selected_whole_module(it.first)) + for (auto &it : modules_) { + log_assert(selection_stack.size() > 0 || !it.second->get_blackbox_attribute(include_wb)); + if (selected_whole_module(it.first)) result.push_back(it.second); else if (selected_module(it.first)) log_warning("Ignoring partially selected module %s.\n", log_id(it.first)); + } return result; } @@ -2431,6 +2461,40 @@ std::vector RTLIL::Module::selected_cells() const return result; } +std::vector RTLIL::Module::selected_memories() const +{ + std::vector result; + result.reserve(memories.size()); + for (auto &it : memories) + if (design->selected(this, it.second)) + result.push_back(it.second); + return result; +} + +std::vector RTLIL::Module::selected_processes() const +{ + std::vector result; + result.reserve(processes.size()); + for (auto &it : processes) + if (design->selected(this, it.second)) + result.push_back(it.second); + return result; +} + +std::vector RTLIL::Module::selected_members() const +{ + std::vector result; + auto cells = selected_cells(); + auto memories = selected_memories(); + auto wires = selected_wires(); + auto processes = selected_processes(); + result.insert(result.end(), cells.begin(), cells.end()); + result.insert(result.end(), memories.begin(), memories.end()); + result.insert(result.end(), wires.begin(), wires.end()); + result.insert(result.end(), processes.begin(), processes.end()); + return result; +} + void RTLIL::Module::add(RTLIL::Wire *wire) { log_assert(!wire->name.empty()); diff --git a/kernel/rtlil.h b/kernel/rtlil.h index f1bd96be7..ee75237f3 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -58,6 +58,7 @@ namespace RTLIL struct Const; struct AttrObject; + struct NamedObject; struct Selection; struct Monitor; struct Design; @@ -869,6 +870,11 @@ struct RTLIL::AttrObject vector get_intvec_attribute(const RTLIL::IdString &id) const; }; +struct RTLIL::NamedObject : public RTLIL::AttrObject +{ + RTLIL::IdString name; +}; + struct RTLIL::SigChunk { RTLIL::Wire *wire; @@ -1135,11 +1141,14 @@ public: struct RTLIL::Selection { bool full_selection; + bool selects_boxes; pool selected_modules; dict> selected_members; + RTLIL::Design *current_design; - Selection(bool full = true) : full_selection(full) { } + Selection(bool full = true, bool boxes = false, RTLIL::Design *design = nullptr) : full_selection(full), selects_boxes(boxes), current_design(design) { } + bool boxed_module(const RTLIL::IdString &mod_name) const; bool selected_module(const RTLIL::IdString &mod_name) const; bool selected_whole_module(const RTLIL::IdString &mod_name) const; bool selected_member(const RTLIL::IdString &mod_name, const RTLIL::IdString &memb_name) const; @@ -1290,7 +1299,7 @@ struct RTLIL::Design #endif }; -struct RTLIL::Module : public RTLIL::AttrObject +struct RTLIL::Module : public RTLIL::NamedObject { Hasher::hash_t hashidx_; [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; } @@ -1313,7 +1322,6 @@ public: std::vector connections_; std::vector bindings_; - RTLIL::IdString name; idict avail_parameters; dict parameter_default_values; dict memories; @@ -1360,6 +1368,9 @@ public: std::vector selected_wires() const; std::vector selected_cells() const; + std::vector selected_memories() const; + std::vector selected_processes() const; + std::vector selected_members() const; template bool selected(T *member) const { return design->selected_member(name, member->name); @@ -1645,7 +1656,7 @@ namespace RTLIL_BACKEND { void dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire); } -struct RTLIL::Wire : public RTLIL::AttrObject +struct RTLIL::Wire : public RTLIL::NamedObject { Hasher::hash_t hashidx_; [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; } @@ -1668,7 +1679,6 @@ public: void operator=(RTLIL::Wire &other) = delete; RTLIL::Module *module; - RTLIL::IdString name; int width, start_offset, port_id; bool port_input, port_output, upto, is_signed; @@ -1697,14 +1707,13 @@ inline int GetSize(RTLIL::Wire *wire) { return wire->width; } -struct RTLIL::Memory : public RTLIL::AttrObject +struct RTLIL::Memory : public RTLIL::NamedObject { Hasher::hash_t hashidx_; [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; } Memory(); - RTLIL::IdString name; int width, start_offset, size; #ifdef WITH_PYTHON ~Memory(); @@ -1712,7 +1721,7 @@ struct RTLIL::Memory : public RTLIL::AttrObject #endif }; -struct RTLIL::Cell : public RTLIL::AttrObject +struct RTLIL::Cell : public RTLIL::NamedObject { Hasher::hash_t hashidx_; [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; } @@ -1729,7 +1738,6 @@ public: void operator=(RTLIL::Cell &other) = delete; RTLIL::Module *module; - RTLIL::IdString name; RTLIL::IdString type; dict connections_; dict parameters; @@ -1822,7 +1830,7 @@ struct RTLIL::SyncRule RTLIL::SyncRule *clone() const; }; -struct RTLIL::Process : public RTLIL::AttrObject +struct RTLIL::Process : public RTLIL::NamedObject { Hasher::hash_t hashidx_; [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; } @@ -1834,7 +1842,6 @@ protected: ~Process(); public: - RTLIL::IdString name; RTLIL::Module *module; RTLIL::CaseRule root_case; std::vector syncs; diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc index aec4c964b..1b1b7ca43 100644 --- a/passes/cmds/select.cc +++ b/passes/cmds/select.cc @@ -141,6 +141,20 @@ static bool match_attr(const dict &attributes, co return match_attr(attributes, match_expr, std::string(), 0); } +static void full_select_no_box(RTLIL::Design *design, RTLIL::Selection &lhs) +{ + if (!lhs.full_selection) + return; + + lhs.current_design = design; + lhs.selected_modules.clear(); + for (auto mod : design->modules()) { + if (mod->get_blackbox_attribute()) + continue; + lhs.selected_modules.insert(mod->name); + } +} + static void select_op_neg(RTLIL::Design *design, RTLIL::Selection &lhs) { if (lhs.full_selection) { @@ -150,7 +164,7 @@ static void select_op_neg(RTLIL::Design *design, RTLIL::Selection &lhs) return; } - if (lhs.selected_modules.size() == 0 && lhs.selected_members.size() == 0) { + if (!lhs.selects_boxes && lhs.selected_modules.size() == 0 && lhs.selected_members.size() == 0) { lhs.full_selection = true; return; } @@ -159,6 +173,8 @@ static void select_op_neg(RTLIL::Design *design, RTLIL::Selection &lhs) for (auto mod : design->modules()) { + if (!lhs.selects_boxes && mod->get_blackbox_attribute()) + continue; if (lhs.selected_whole_module(mod->name)) continue; if (!lhs.selected_module(mod->name)) { @@ -212,7 +228,7 @@ static void select_op_random(RTLIL::Design *design, RTLIL::Selection &lhs, int c } } - lhs = RTLIL::Selection(false); + lhs = RTLIL::Selection(false, false, design); while (!objects.empty() && count-- > 0) { @@ -243,7 +259,7 @@ static void select_op_submod(RTLIL::Design *design, RTLIL::Selection &lhs) static void select_op_cells_to_modules(RTLIL::Design *design, RTLIL::Selection &lhs) { - RTLIL::Selection new_sel(false); + RTLIL::Selection new_sel(false, lhs.selects_boxes, design); for (auto mod : design->modules()) if (lhs.selected_module(mod->name)) for (auto cell : mod->cells()) @@ -254,7 +270,7 @@ static void select_op_cells_to_modules(RTLIL::Design *design, RTLIL::Selection & static void select_op_module_to_cells(RTLIL::Design *design, RTLIL::Selection &lhs) { - RTLIL::Selection new_sel(false); + RTLIL::Selection new_sel(false, lhs.selects_boxes, design); for (auto mod : design->modules()) for (auto cell : mod->cells()) if ((design->module(cell->type) != nullptr) && lhs.selected_whole_module(cell->type)) @@ -274,6 +290,8 @@ static void select_op_alias(RTLIL::Design *design, RTLIL::Selection &lhs) { for (auto mod : design->modules()) { + if (!lhs.selects_boxes && mod->get_blackbox_attribute()) + continue; if (lhs.selected_whole_module(mod->name)) continue; if (!lhs.selected_module(mod->name)) @@ -292,18 +310,32 @@ static void select_op_alias(RTLIL::Design *design, RTLIL::Selection &lhs) } } -static void select_op_union(RTLIL::Design*, RTLIL::Selection &lhs, const RTLIL::Selection &rhs) +static void select_op_union(RTLIL::Design* design, RTLIL::Selection &lhs, const RTLIL::Selection &rhs) { + if (rhs.selects_boxes) { + if (lhs.full_selection) { + full_select_no_box(design, lhs); + lhs.full_selection = false; + } + lhs.selects_boxes = true; + } + else if (lhs.full_selection) + return; + if (rhs.full_selection) { - lhs.full_selection = true; - lhs.selected_modules.clear(); - lhs.selected_members.clear(); + if (lhs.selects_boxes) { + auto new_rhs = RTLIL::Selection(rhs); + full_select_no_box(design, new_rhs); + for (auto mod : new_rhs.selected_modules) + lhs.selected_modules.insert(mod); + } else { + lhs.full_selection = true; + lhs.selected_modules.clear(); + lhs.selected_members.clear(); + } return; } - if (lhs.full_selection) - return; - for (auto &it : rhs.selected_members) for (auto &it2 : it.second) lhs.selected_members[it.first].insert(it2); @@ -317,18 +349,26 @@ static void select_op_union(RTLIL::Design*, RTLIL::Selection &lhs, const RTLIL:: static void select_op_diff(RTLIL::Design *design, RTLIL::Selection &lhs, const RTLIL::Selection &rhs) { if (rhs.full_selection) { - lhs.full_selection = false; - lhs.selected_modules.clear(); - lhs.selected_members.clear(); + if (lhs.selects_boxes) { + auto new_rhs = RTLIL::Selection(rhs); + full_select_no_box(design, new_rhs); + for (auto mod : new_rhs.selected_modules) { + lhs.selected_modules.erase(mod); + lhs.selected_members.erase(mod); + } + } else { + lhs.full_selection = false; + lhs.selected_modules.clear(); + lhs.selected_members.clear(); + } return; } if (lhs.full_selection) { - if (!rhs.full_selection && rhs.selected_modules.size() == 0 && rhs.selected_members.size() == 0) + if (rhs.empty()) return; + full_select_no_box(design, lhs); lhs.full_selection = false; - for (auto mod : design->modules()) - lhs.selected_modules.insert(mod->name); } for (auto &it : rhs.selected_modules) { @@ -366,7 +406,7 @@ static void select_op_diff(RTLIL::Design *design, RTLIL::Selection &lhs, const R static void select_op_intersect(RTLIL::Design *design, RTLIL::Selection &lhs, const RTLIL::Selection &rhs) { - if (rhs.full_selection) + if (rhs.full_selection && !lhs.selects_boxes) return; if (lhs.full_selection) { @@ -377,27 +417,28 @@ static void select_op_intersect(RTLIL::Design *design, RTLIL::Selection &lhs, co std::vector del_list; - for (auto &it : lhs.selected_modules) - if (rhs.selected_modules.count(it) == 0) { - if (rhs.selected_members.count(it) > 0) - for (auto &it2 : rhs.selected_members.at(it)) - lhs.selected_members[it].insert(it2); - del_list.push_back(it); - } + for (auto mod_name : lhs.selected_modules) { + if (rhs.selected_whole_module(mod_name)) + continue; + if (rhs.selected_module(mod_name)) + for (auto memb_name : rhs.selected_members.at(mod_name)) + lhs.selected_members[mod_name].insert(memb_name); + del_list.push_back(mod_name); + } for (auto &it : del_list) lhs.selected_modules.erase(it); del_list.clear(); for (auto &it : lhs.selected_members) { - if (rhs.selected_modules.count(it.first) > 0) + if (rhs.selected_whole_module(it.first)) continue; - if (rhs.selected_members.count(it.first) == 0) { + if (!rhs.selected_module(it.first)) { del_list.push_back(it.first); continue; } std::vector del_list2; for (auto &it2 : it.second) - if (rhs.selected_members.at(it.first).count(it2) == 0) + if (!rhs.selected_member(it.first, it2)) del_list2.push_back(it2); for (auto &it2 : del_list2) it.second.erase(it2); @@ -796,15 +837,16 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp } } - work_stack.push_back(RTLIL::Selection()); + bool full_selection = (arg == "*" && arg_mod == "*"); + work_stack.push_back(RTLIL::Selection(full_selection, select_blackboxes, design)); RTLIL::Selection &sel = work_stack.back(); - if (arg == "*" && arg_mod == "*" && select_blackboxes) { + if (sel.full_selection) { + if (sel.selects_boxes) sel.optimize(design); select_filter_active_mod(design, work_stack.back()); return; } - sel.full_selection = false; for (auto mod : design->modules()) { if (!select_blackboxes && mod->get_blackbox_attribute()) @@ -958,24 +1000,12 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp static std::string describe_selection_for_assert(RTLIL::Design *design, RTLIL::Selection *sel, bool whole_modules = false) { std::string desc = "Selection contains:\n"; - for (auto mod : design->modules()) + for (auto mod : design->selected_modules()) { - if (sel->selected_module(mod->name)) { - if (whole_modules && sel->selected_whole_module(mod->name)) - desc += stringf("%s\n", id2cstr(mod->name)); - for (auto wire : mod->wires()) - if (sel->selected_member(mod->name, wire->name)) - desc += stringf("%s/%s\n", id2cstr(mod->name), id2cstr(wire->name)); - for (auto &it : mod->memories) - if (sel->selected_member(mod->name, it.first)) - desc += stringf("%s/%s\n", id2cstr(mod->name), id2cstr(it.first)); - for (auto cell : mod->cells()) - if (sel->selected_member(mod->name, cell->name)) - desc += stringf("%s/%s\n", id2cstr(mod->name), id2cstr(cell->name)); - for (auto &it : mod->processes) - if (sel->selected_member(mod->name, it.first)) - desc += stringf("%s/%s\n", id2cstr(mod->name), id2cstr(it.first)); - } + if (whole_modules && sel->selected_whole_module(mod->name)) + desc += stringf("%s\n", id2cstr(mod->name)); + for (auto it : mod->selected_members()) + desc += stringf("%s/%s\n", id2cstr(mod->name), id2cstr(it->name)); } return desc; } @@ -1001,7 +1031,7 @@ void handle_extra_select_args(Pass *pass, const vector &args, size_t arg work_stack.pop_back(); } if (work_stack.empty()) - design->selection_stack.push_back(RTLIL::Selection(false)); + design->selection_stack.push_back(RTLIL::Selection(false, false, design)); else design->selection_stack.push_back(work_stack.back()); } @@ -1017,7 +1047,7 @@ RTLIL::Selection eval_select_args(const vector &args, RTLIL::Design *des work_stack.pop_back(); } if (work_stack.empty()) - return RTLIL::Selection(false); + return RTLIL::Selection(false, false, design); return work_stack.back(); } @@ -1444,13 +1474,13 @@ struct SelectPass : public Pass { log_assert(design->selection_stack.size() > 0); if (clear_mode) { - design->selection_stack.back() = RTLIL::Selection(true); + design->selection_stack.back() = RTLIL::Selection(true, false, design); design->selected_active_module = std::string(); return; } if (none_mode) { - design->selection_stack.back() = RTLIL::Selection(false); + design->selection_stack.back() = RTLIL::Selection(false, false, design); return; } @@ -1465,28 +1495,17 @@ struct SelectPass : public Pass { if (f == nullptr) log_error("Can't open '%s' for writing: %s\n", write_file.c_str(), strerror(errno)); } - RTLIL::Selection *sel = &design->selection_stack.back(); if (work_stack.size() > 0) - sel = &work_stack.back(); + design->selection_stack.push_back(work_stack.back()); + RTLIL::Selection *sel = &design->selection_stack.back(); sel->optimize(design); - for (auto mod : design->modules()) + for (auto mod : design->selected_modules()) { if (sel->selected_whole_module(mod->name) && list_mode) log("%s\n", id2cstr(mod->name)); - if (sel->selected_module(mod->name) && !list_mod_mode) { - for (auto wire : mod->wires()) - if (sel->selected_member(mod->name, wire->name)) - LOG_OBJECT("%s/%s\n", id2cstr(mod->name), id2cstr(wire->name)) - for (auto &it : mod->memories) - if (sel->selected_member(mod->name, it.first)) - LOG_OBJECT("%s/%s\n", id2cstr(mod->name), id2cstr(it.first)) - for (auto cell : mod->cells()) - if (sel->selected_member(mod->name, cell->name)) - LOG_OBJECT("%s/%s\n", id2cstr(mod->name), id2cstr(cell->name)) - for (auto &it : mod->processes) - if (sel->selected_member(mod->name, it.first)) - LOG_OBJECT("%s/%s\n", id2cstr(mod->name), id2cstr(it.first)) - } + if (!list_mod_mode) + for (auto it : mod->selected_members()) + LOG_OBJECT("%s/%s\n", id2cstr(mod->name), id2cstr(it->name)) } if (count_mode) { @@ -1495,6 +1514,8 @@ struct SelectPass : public Pass { } if (f != nullptr) fclose(f); + if (work_stack.size() > 0) + design->selection_stack.pop_back(); #undef LOG_OBJECT return; } @@ -1553,23 +1574,13 @@ struct SelectPass : public Pass { if (work_stack.size() == 0) log_cmd_error("No selection to check.\n"); RTLIL::Selection *sel = &work_stack.back(); + design->selection_stack.push_back(*sel); sel->optimize(design); - for (auto mod : design->modules()) - if (sel->selected_module(mod->name)) { - module_count++; - for (auto wire : mod->wires()) - if (sel->selected_member(mod->name, wire->name)) - total_count++; - for (auto &it : mod->memories) - if (sel->selected_member(mod->name, it.first)) - total_count++; - for (auto cell : mod->cells()) - if (sel->selected_member(mod->name, cell->name)) - total_count++; - for (auto &it : mod->processes) - if (sel->selected_member(mod->name, it.first)) - total_count++; - } + for (auto mod : design->selected_modules()) { + module_count++; + for ([[maybe_unused]] auto member_name : mod->selected_members()) + total_count++; + } if (assert_modcount >= 0 && assert_modcount != module_count) { log_error("Assertion failed: selection contains %d modules instead of the asserted %d:%s\n", @@ -1593,13 +1604,14 @@ struct SelectPass : public Pass { log_error("Assertion failed: selection contains %d elements, less than the minimum number %d:%s\n%s", total_count, assert_min, sel_str.c_str(), desc.c_str()); } + design->selection_stack.pop_back(); return; } if (!set_name.empty()) { if (work_stack.size() == 0) - design->selection_vars[set_name] = RTLIL::Selection(false); + design->selection_vars[set_name] = RTLIL::Selection(false, false, design); else design->selection_vars[set_name] = work_stack.back(); return; @@ -1665,7 +1677,7 @@ struct CdPass : public Pass { log_cmd_error("Invalid number of arguments.\n"); if (args.size() == 1 || args[1] == "/") { - design->selection_stack.back() = RTLIL::Selection(true); + design->selection_stack.back() = RTLIL::Selection(true, false, design); design->selected_active_module = std::string(); return; } @@ -1674,7 +1686,7 @@ struct CdPass : public Pass { { string modname = design->selected_active_module; - design->selection_stack.back() = RTLIL::Selection(true); + design->selection_stack.back() = RTLIL::Selection(true, false, design); design->selected_active_module = std::string(); while (1) @@ -1691,7 +1703,7 @@ struct CdPass : public Pass { continue; design->selected_active_module = modname; - design->selection_stack.back() = RTLIL::Selection(); + design->selection_stack.back() = RTLIL::Selection(true, false, design); select_filter_active_mod(design, design->selection_stack.back()); design->selection_stack.back().optimize(design); return; @@ -1710,7 +1722,7 @@ struct CdPass : public Pass { if (design->module(modname) != nullptr) { design->selected_active_module = modname; - design->selection_stack.back() = RTLIL::Selection(); + design->selection_stack.back() = RTLIL::Selection(true, false, design); select_filter_active_mod(design, design->selection_stack.back()); design->selection_stack.back().optimize(design); return; From 061c234559fa5351345c13be061cdde4f12335fd Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:05:40 +1300 Subject: [PATCH 02/26] tests/select: Add tests for selections with boxes --- tests/select/{blackboxes.ys => boxes.v} | 12 -------- tests/select/boxes_dummy.ys | 13 +++++++++ tests/select/boxes_equals_clean.ys | 7 +++++ tests/select/boxes_equals_name.ys | 7 +++++ tests/select/boxes_equals_operators.ys | 38 +++++++++++++++++++++++++ tests/select/boxes_equals_pattern.ys | 7 +++++ tests/select/boxes_equals_wildcard.ys | 6 ++++ tests/select/boxes_no_equals.ys | 7 +++++ tests/select/boxes_no_equals_clean.ys | 18 ++++++++++++ 9 files changed, 103 insertions(+), 12 deletions(-) rename tests/select/{blackboxes.ys => boxes.v} (51%) create mode 100644 tests/select/boxes_dummy.ys create mode 100644 tests/select/boxes_equals_clean.ys create mode 100644 tests/select/boxes_equals_name.ys create mode 100644 tests/select/boxes_equals_operators.ys create mode 100644 tests/select/boxes_equals_pattern.ys create mode 100644 tests/select/boxes_equals_wildcard.ys create mode 100644 tests/select/boxes_no_equals.ys create mode 100644 tests/select/boxes_no_equals_clean.ys diff --git a/tests/select/blackboxes.ys b/tests/select/boxes.v similarity index 51% rename from tests/select/blackboxes.ys rename to tests/select/boxes.v index 9bfe92c6b..696b26523 100644 --- a/tests/select/blackboxes.ys +++ b/tests/select/boxes.v @@ -1,4 +1,3 @@ -read_verilog -specify < Date: Fri, 14 Mar 2025 14:05:40 +1300 Subject: [PATCH 03/26] Unify Design::selected_modules variants Now uses two enums, one to control whether or not to include partially selected modules (and what to do if they are encountered), and one to control whether or not to include boxed modules (and what to do if they are encountered). Mark Design::selected{modules, whole_modules}() deprecated and make them provide warnings on boxes. There are a lot of places that use them and I can't always tell which ones support boxed modules and which don't. --- kernel/rtlil.cc | 75 +++++++++++++++++++++++++++++++------------------ kernel/rtlil.h | 41 +++++++++++++++++++++++++-- 2 files changed, 86 insertions(+), 30 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 8c40e83d3..946556b04 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -1152,37 +1152,58 @@ bool RTLIL::Design::selected_whole_module(RTLIL::Module *mod) const return selected_whole_module(mod->name); } -std::vector RTLIL::Design::selected_modules() const + +std::vector RTLIL::Design::selected_modules(RTLIL::SelectPartials partials, RTLIL::SelectBoxes boxes) const { + bool include_partials = partials == RTLIL::SELECT_ALL; + bool exclude_boxes = (partials & RTLIL::SB_UNBOXED_ONLY) == 0; + bool ignore_wb = (partials & RTLIL::SB_INCL_WB) != 0; std::vector result; result.reserve(modules_.size()); for (auto &it : modules_) - if (selected_module(it.first)) - result.push_back(it.second); - return result; -} - -std::vector RTLIL::Design::selected_whole_modules() const -{ - std::vector result; - result.reserve(modules_.size()); - for (auto &it : modules_) - if (selected_whole_module(it.first)) - result.push_back(it.second); - return result; -} - -std::vector RTLIL::Design::selected_whole_modules_warn(bool include_wb) const -{ - std::vector result; - result.reserve(modules_.size()); - for (auto &it : modules_) { - log_assert(selection_stack.size() > 0 || !it.second->get_blackbox_attribute(include_wb)); - if (selected_whole_module(it.first)) - result.push_back(it.second); - else if (selected_module(it.first)) - log_warning("Ignoring partially selected module %s.\n", log_id(it.first)); - } + if (selected_whole_module(it.first) || (include_partials && selected_module(it.first))) { + if (!(exclude_boxes && it.second->get_blackbox_attribute(ignore_wb))) + result.push_back(it.second); + else + switch (boxes) + { + case RTLIL::SB_UNBOXED_WARN: + log_warning("Ignoring boxed module %s.\n", log_id(it.first)); + break; + case RTLIL::SB_EXCL_BB_WARN: + log_warning("Ignoring blackbox module %s.\n", log_id(it.first)); + break; + case RTLIL::SB_UNBOXED_ERR: + log_error("Unsupported boxed module %s.\n", log_id(it.first)); + break; + case RTLIL::SB_EXCL_BB_ERR: + log_error("Unsupported blackbox module %s.\n", log_id(it.first)); + break; + case RTLIL::SB_UNBOXED_CMDERR: + log_cmd_error("Unsupported boxed module %s.\n", log_id(it.first)); + break; + case RTLIL::SB_EXCL_BB_CMDERR: + log_cmd_error("Unsupported blackbox module %s.\n", log_id(it.first)); + break; + default: + break; + } + } else if (!include_partials && selected_module(it.first)) { + switch(partials) + { + case RTLIL::SELECT_WHOLE_WARN: + log_warning("Ignoring partially selected module %s.\n", log_id(it.first)); + break; + case RTLIL::SELECT_WHOLE_ERR: + log_error("Unsupported partially selected module %s.\n", log_id(it.first)); + break; + case RTLIL::SELECT_WHOLE_CMDERR: + log_cmd_error("Unsupported partially selected module %s.\n", log_id(it.first)); + break; + default: + break; + } + } return result; } diff --git a/kernel/rtlil.h b/kernel/rtlil.h index ee75237f3..9c9103bb6 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -56,6 +56,30 @@ namespace RTLIL CONST_FLAG_REAL = 4 // only used for parameters }; + enum SelectPartials : unsigned char { + SELECT_ALL = 0, // include partial modules + SELECT_WHOLE_ONLY = 1, // ignore partial modules + SELECT_WHOLE_WARN = 2, // call log_warning on partial module + SELECT_WHOLE_ERR = 3, // call log_error on partial module + SELECT_WHOLE_CMDERR = 4 // call log_cmd_error on partial module + }; + + enum SelectBoxes : unsigned char { + SB_ALL = 0, // include boxed modules + SB_WARN = 1, // helper for log_warning + SB_ERR = 2, // helper for log_error + SB_CMDERR = 3, // helper for log_cmd_error + SB_UNBOXED_ONLY = 4, // ignore boxed modules + SB_UNBOXED_WARN = 5, // call log_warning on boxed module + SB_UNBOXED_ERR = 6, // call log_error on boxed module + SB_UNBOXED_CMDERR = 7, // call log_cmd_error on boxed module + SB_INCL_WB = 8, // helper for white boxes + SB_EXCL_BB_ONLY = 12, // ignore black boxes, but not white boxes + SB_EXCL_BB_WARN = 13, // call log_warning on black boxed module + SB_EXCL_BB_ERR = 14, // call log_error on black boxed module + SB_EXCL_BB_CMDERR = 15 // call log_cmd_error on black boxed module + }; + struct Const; struct AttrObject; struct NamedObject; @@ -1291,9 +1315,20 @@ struct RTLIL::Design } - std::vector selected_modules() const; - std::vector selected_whole_modules() const; - std::vector selected_whole_modules_warn(bool include_wb = false) const; + std::vector selected_modules(RTLIL::SelectPartials partials, RTLIL::SelectBoxes boxes = SB_ALL) const; + + [[deprecated("Use selected_unboxed_modules() to maintain prior behaviour, or consider one of the other selected module helpers.")]] + std::vector selected_modules() const { return selected_modules(SELECT_ALL, SB_UNBOXED_WARN); } + std::vector all_selected_modules() const { return selected_modules(SELECT_ALL, SB_ALL); } + std::vector selected_unboxed_modules() const { return selected_modules(SELECT_ALL, SB_UNBOXED_ONLY); } + std::vector selected_unboxed_modules_warn() const { return selected_modules(SELECT_ALL, SB_UNBOXED_WARN); } + + [[deprecated("Use select_unboxed_whole_modules() to maintain prior behaviour, or consider one of the other selected whole module helpers.")]] + std::vector selected_whole_modules() const { return selected_modules(SELECT_WHOLE_ONLY, SB_UNBOXED_WARN); } + std::vector all_selected_whole_modules() const { return selected_modules(SELECT_WHOLE_ONLY, SB_ALL); } + std::vector selected_whole_modules_warn(bool include_wb = false) const { return selected_modules(SELECT_WHOLE_WARN, include_wb ? SB_EXCL_BB_WARN : SB_UNBOXED_WARN); } + std::vector selected_unboxed_whole_modules() const { return selected_modules(SELECT_WHOLE_ONLY, SB_UNBOXED_ONLY); } + std::vector selected_unboxed_whole_modules_warn() const { return selected_modules(SELECT_WHOLE_WARN, SB_UNBOXED_WARN); } #ifdef WITH_PYTHON static std::map *get_all_designs(void); #endif From 3b1b09baf690f449c23309eac7707a00cfb8351c Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:05:40 +1300 Subject: [PATCH 04/26] Can clean boxed modules If a selection contains a boxed module, but does not select boxes, it should be removed from the selection. --- kernel/rtlil.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 946556b04..c3a415f36 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -840,7 +840,7 @@ void RTLIL::Selection::optimize(RTLIL::Design *design) del_list.clear(); for (auto mod_name : selected_modules) { - if (current_design->modules_.count(mod_name) == 0) + if (current_design->modules_.count(mod_name) == 0 || (!selects_boxes && boxed_module(mod_name))) del_list.push_back(mod_name); selected_members.erase(mod_name); } @@ -849,7 +849,7 @@ void RTLIL::Selection::optimize(RTLIL::Design *design) del_list.clear(); for (auto &it : selected_members) - if (current_design->modules_.count(it.first) == 0) + if (current_design->modules_.count(it.first) == 0 || (!selects_boxes && boxed_module(it.first))) del_list.push_back(it.first); for (auto mod_name : del_list) selected_members.erase(mod_name); From a67b57bd6456ff61f3c90b5e8e449989a43161ec Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:05:40 +1300 Subject: [PATCH 05/26] rtlil: Add selection helpers New methods on Design to push/pop selection instead of accessing the selection stack directly. Includes methods for pushing a full/complete/empty selection. Also helper methods on modules to check `is_selected` and `is_selected_whole`. --- kernel/rtlil.cc | 39 +++++++++++++++++++++++++++++++++++++++ kernel/rtlil.h | 9 +++++++++ 2 files changed, 48 insertions(+) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index c3a415f36..378c976ef 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -1152,6 +1152,35 @@ bool RTLIL::Design::selected_whole_module(RTLIL::Module *mod) const return selected_whole_module(mod->name); } +void RTLIL::Design::push_selection(RTLIL::Selection sel) +{ + sel.current_design = this; + selection_stack.push_back(sel); +} + +void RTLIL::Design::push_empty_selection() +{ + RTLIL::Selection sel(false, false, this); + push_selection(sel); +} + +void RTLIL::Design::push_full_selection() +{ + RTLIL::Selection sel(true, false, this); + push_selection(sel); +} + +void RTLIL::Design::push_complete_selection() +{ + RTLIL::Selection sel(true, true, this); + sel.optimize(this); + push_selection(sel); +} + +void RTLIL::Design::pop_selection() +{ + selection_stack.pop_back(); +} std::vector RTLIL::Design::selected_modules(RTLIL::SelectPartials partials, RTLIL::SelectBoxes boxes) const { @@ -2462,6 +2491,16 @@ bool RTLIL::Module::has_processes_warn() const return !processes.empty(); } +bool RTLIL::Module::is_selected() const +{ + return design->selected_module(this->name); +} + +bool RTLIL::Module::is_selected_whole() const +{ + return design->selected_whole_module(this->name); +} + std::vector RTLIL::Module::selected_wires() const { std::vector result; diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 9c9103bb6..57030d133 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1280,6 +1280,12 @@ struct RTLIL::Design bool selected_module(RTLIL::Module *mod) const; bool selected_whole_module(RTLIL::Module *mod) const; + void push_selection(RTLIL::Selection sel); + void push_empty_selection(); + void push_full_selection(); + void push_complete_selection(); + void pop_selection(); + RTLIL::Selection &selection() { return selection_stack.back(); } @@ -1401,6 +1407,9 @@ public: bool has_memories_warn() const; bool has_processes_warn() const; + bool is_selected() const; + bool is_selected_whole() const; + std::vector selected_wires() const; std::vector selected_cells() const; std::vector selected_memories() const; From dac2bb7d4d6d0bfd18d61316696f5422e1508e8f Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:08:13 +1300 Subject: [PATCH 06/26] Use selection helpers Catch more uses of selection constructor without assigning a design. --- backends/rtlil/rtlil_backend.cc | 4 +- .../source/code_examples/extensions/my_cmd.cc | 4 +- .../extending_yosys/extensions.rst | 2 +- kernel/driver.cc | 2 +- kernel/register.cc | 24 ++++---- kernel/rtlil.cc | 8 +-- kernel/rtlil.h | 6 +- kernel/tclapi.cc | 2 +- kernel/yosys.cc | 8 +-- passes/cmds/add.cc | 2 +- passes/cmds/design.cc | 6 +- passes/cmds/scc.cc | 2 +- passes/cmds/select.cc | 60 ++++++++++--------- passes/cmds/show.cc | 8 +-- passes/cmds/stat.cc | 2 +- passes/cmds/viz.cc | 4 +- passes/hierarchy/submod.cc | 2 +- passes/sat/cutpoint.cc | 2 +- passes/techmap/abc9.cc | 4 +- passes/techmap/abc9_ops.cc | 2 +- passes/techmap/abc_new.cc | 4 +- passes/techmap/aigmap.cc | 2 +- passes/techmap/nlutmap.cc | 2 +- 23 files changed, 84 insertions(+), 78 deletions(-) diff --git a/backends/rtlil/rtlil_backend.cc b/backends/rtlil/rtlil_backend.cc index 113f1a615..ae60ee6c7 100644 --- a/backends/rtlil/rtlil_backend.cc +++ b/backends/rtlil/rtlil_backend.cc @@ -304,8 +304,8 @@ void RTLIL_BACKEND::dump_conn(std::ostream &f, std::string indent, const RTLIL:: void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Module *module, RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n) { - bool print_header = flag_m || design->selected_whole_module(module->name); - bool print_body = !flag_n || !design->selected_whole_module(module->name); + bool print_header = flag_m || module->is_selected_whole(); + bool print_body = !flag_n || !module->is_selected_whole(); if (print_header) { diff --git a/docs/source/code_examples/extensions/my_cmd.cc b/docs/source/code_examples/extensions/my_cmd.cc index 36ddbe175..e6660469c 100644 --- a/docs/source/code_examples/extensions/my_cmd.cc +++ b/docs/source/code_examples/extensions/my_cmd.cc @@ -51,10 +51,10 @@ struct Test2Pass : public Pass { Test2Pass() : Pass("test2", "demonstrating sigmap on test module") { } void execute(std::vector, RTLIL::Design *design) override { - if (design->selection_stack.back().empty()) + if (design->selection().empty()) log_cmd_error("This command can't operator on an empty selection!\n"); - RTLIL::Module *module = design->modules_.at("\\test"); + RTLIL::Module *module = design->module("\\test"); RTLIL::SigSpec a(module->wire("\\a")), x(module->wire("\\x")), y(module->wire("\\y")); log("%d %d %d\n", a == x, x == y, y == a); // will print "0 0 0" diff --git a/docs/source/yosys_internals/extending_yosys/extensions.rst b/docs/source/yosys_internals/extending_yosys/extensions.rst index b02c4cd99..d30dd2bae 100644 --- a/docs/source/yosys_internals/extending_yosys/extensions.rst +++ b/docs/source/yosys_internals/extending_yosys/extensions.rst @@ -237,7 +237,7 @@ Use ``log_cmd_error()`` to report a recoverable error: .. code:: C++ - if (design->selection_stack.back().empty()) + if (design->selection().empty()) log_cmd_error("This command can't operator on an empty selection!\n"); Use ``log_assert()`` and ``log_abort()`` instead of ``assert()`` and ``abort()``. diff --git a/kernel/driver.cc b/kernel/driver.cc index a3d85bd90..eb1326ce0 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -111,7 +111,7 @@ void run(const char *command) log_last_error = ""; } catch (...) { while (GetSize(yosys_get_design()->selection_stack) > selSize) - yosys_get_design()->selection_stack.pop_back(); + yosys_get_design()->pop_selection(); throw; } } diff --git a/kernel/register.cc b/kernel/register.cc index 11cf5b0e4..f0a5ddc06 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -318,18 +318,18 @@ void Pass::call(RTLIL::Design *design, std::vector args) pass_register[args[0]]->execute(args, design); pass_register[args[0]]->post_execute(state); while (design->selection_stack.size() > orig_sel_stack_pos) - design->selection_stack.pop_back(); + design->pop_selection(); } void Pass::call_on_selection(RTLIL::Design *design, const RTLIL::Selection &selection, std::string command) { std::string backup_selected_active_module = design->selected_active_module; design->selected_active_module.clear(); - design->selection_stack.push_back(selection); + design->push_selection(selection); Pass::call(design, command); - design->selection_stack.pop_back(); + design->pop_selection(); design->selected_active_module = backup_selected_active_module; } @@ -337,11 +337,11 @@ void Pass::call_on_selection(RTLIL::Design *design, const RTLIL::Selection &sele { std::string backup_selected_active_module = design->selected_active_module; design->selected_active_module.clear(); - design->selection_stack.push_back(selection); + design->push_selection(selection); Pass::call(design, args); - design->selection_stack.pop_back(); + design->pop_selection(); design->selected_active_module = backup_selected_active_module; } @@ -349,12 +349,12 @@ void Pass::call_on_module(RTLIL::Design *design, RTLIL::Module *module, std::str { std::string backup_selected_active_module = design->selected_active_module; design->selected_active_module = module->name.str(); - design->selection_stack.push_back(RTLIL::Selection(false)); - design->selection_stack.back().select(module); + design->push_empty_selection(); + design->select(module); Pass::call(design, command); - design->selection_stack.pop_back(); + design->pop_selection(); design->selected_active_module = backup_selected_active_module; } @@ -362,12 +362,12 @@ void Pass::call_on_module(RTLIL::Design *design, RTLIL::Module *module, std::vec { std::string backup_selected_active_module = design->selected_active_module; design->selected_active_module = module->name.str(); - design->selection_stack.push_back(RTLIL::Selection(false)); - design->selection_stack.back().select(module); + design->push_empty_selection(); + design->select(module); Pass::call(design, args); - design->selection_stack.pop_back(); + design->pop_selection(); design->selected_active_module = backup_selected_active_module; } @@ -745,7 +745,7 @@ void Backend::backend_call(RTLIL::Design *design, std::ostream *f, std::string f } while (design->selection_stack.size() > orig_sel_stack_pos) - design->selection_stack.pop_back(); + design->pop_selection(); } struct SimHelper { diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 378c976ef..fa7712ee0 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -893,7 +893,7 @@ RTLIL::Design::Design() hashidx_ = hashidx_count; refcount_modules_ = 0; - selection_stack.push_back(RTLIL::Selection(true, false, this)); + push_full_selection(); #ifdef WITH_PYTHON RTLIL::Design::get_all_designs()->insert(std::pair(hashidx_, this)); @@ -1121,7 +1121,7 @@ bool RTLIL::Design::selected_module(const RTLIL::IdString& mod_name) const return false; if (selection_stack.size() == 0) return true; - return selection_stack.back().selected_module(mod_name); + return selection().selected_module(mod_name); } bool RTLIL::Design::selected_whole_module(const RTLIL::IdString& mod_name) const @@ -1130,7 +1130,7 @@ bool RTLIL::Design::selected_whole_module(const RTLIL::IdString& mod_name) const return false; if (selection_stack.size() == 0) return true; - return selection_stack.back().selected_whole_module(mod_name); + return selection().selected_whole_module(mod_name); } bool RTLIL::Design::selected_member(const RTLIL::IdString& mod_name, const RTLIL::IdString& memb_name) const @@ -1139,7 +1139,7 @@ bool RTLIL::Design::selected_member(const RTLIL::IdString& mod_name, const RTLIL return false; if (selection_stack.size() == 0) return true; - return selection_stack.back().selected_member(mod_name, memb_name); + return selection().selected_member(mod_name, memb_name); } bool RTLIL::Design::selected_module(RTLIL::Module *mod) const diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 57030d133..52b63141b 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1295,7 +1295,7 @@ struct RTLIL::Design } bool full_selection() const { - return selection_stack.back().full_selection; + return selection().full_selection; } template bool selected(T1 *module) const { @@ -1308,14 +1308,14 @@ struct RTLIL::Design template void select(T1 *module) { if (selection_stack.size() > 0) { - RTLIL::Selection &sel = selection_stack.back(); + RTLIL::Selection &sel = selection(); sel.select(module); } } template void select(T1 *module, T2 *member) { if (selection_stack.size() > 0) { - RTLIL::Selection &sel = selection_stack.back(); + RTLIL::Selection &sel = selection(); sel.select(module, member); } } diff --git a/kernel/tclapi.cc b/kernel/tclapi.cc index be39ca4a0..e970779d7 100644 --- a/kernel/tclapi.cc +++ b/kernel/tclapi.cc @@ -114,7 +114,7 @@ static int tcl_yosys_cmd(ClientData, Tcl_Interp *interp, int argc, const char *a if (in_repl) { auto design = yosys_get_design(); while (design->selection_stack.size() > 1) - design->selection_stack.pop_back(); + design->pop_selection(); log_reset_stack(); } Tcl_SetResult(interp, (char *)"Yosys command produced an error", TCL_STATIC); diff --git a/kernel/yosys.cc b/kernel/yosys.cc index d39acf9d9..85354c163 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -679,11 +679,11 @@ const char *create_prompt(RTLIL::Design *design, int recursion_counter) str += "yosys"; if (!design->selected_active_module.empty()) str += stringf(" [%s]", RTLIL::unescape_id(design->selected_active_module).c_str()); - if (!design->selection_stack.empty() && !design->selection_stack.back().full_selection) { + if (!design->selection_stack.empty() && !design->full_selection()) { if (design->selected_active_module.empty()) str += "*"; - else if (design->selection_stack.back().selected_modules.size() != 1 || design->selection_stack.back().selected_members.size() != 0 || - design->selection_stack.back().selected_modules.count(design->selected_active_module) == 0) + else if (design->selection().selected_modules.size() != 1 || design->selection().selected_members.size() != 0 || + design->selection().selected_modules.count(design->selected_active_module) == 0) str += "*"; } snprintf(buffer, 100, "%s> ", str.c_str()); @@ -1346,7 +1346,7 @@ void shell(RTLIL::Design *design) Pass::call(design, command); } catch (log_cmd_error_exception) { while (design->selection_stack.size() > 1) - design->selection_stack.pop_back(); + design->pop_selection(); log_reset_stack(); } design->check(); diff --git a/passes/cmds/add.cc b/passes/cmds/add.cc index c09517254..833d6006d 100644 --- a/passes/cmds/add.cc +++ b/passes/cmds/add.cc @@ -102,7 +102,7 @@ static void add_wire(RTLIL::Design *design, RTLIL::Module *module, std::string n RTLIL::Module *mod = design->module(cell->type); if (mod == nullptr) continue; - if (!design->selected_whole_module(mod->name)) + if (!mod->is_selected_whole()) continue; if (mod->get_blackbox_attribute()) continue; diff --git a/passes/cmds/design.cc b/passes/cmds/design.cc index 168d38563..910c9e366 100644 --- a/passes/cmds/design.cc +++ b/passes/cmds/design.cc @@ -216,8 +216,8 @@ struct DesignPass : public Pass { RTLIL::Selection sel; if (argidx != args.size()) { handle_extra_select_args(this, args, argidx, args.size(), copy_from_design); - sel = copy_from_design->selection_stack.back(); - copy_from_design->selection_stack.pop_back(); + sel = copy_from_design->selection(); + copy_from_design->pop_selection(); argidx = args.size(); } @@ -368,7 +368,7 @@ struct DesignPass : public Pass { design->selection_vars.clear(); design->selected_active_module.clear(); - design->selection_stack.push_back(RTLIL::Selection()); + design->push_full_selection(); } if (reset_mode || reset_vlog_mode || !load_name.empty() || push_mode || pop_mode) diff --git a/passes/cmds/scc.cc b/passes/cmds/scc.cc index 197bd9319..ddd72bb45 100644 --- a/passes/cmds/scc.cc +++ b/passes/cmds/scc.cc @@ -340,7 +340,7 @@ struct SccPass : public Pass { int origSelectPos = design->selection_stack.size() - 1; extra_args(args, argidx, design); - RTLIL::Selection newSelection(false); + RTLIL::Selection newSelection(false, false, design); int scc_counter = 0; for (auto mod : design->selected_modules()) diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc index 1b1b7ca43..4db1c2f28 100644 --- a/passes/cmds/select.cc +++ b/passes/cmds/select.cc @@ -687,7 +687,7 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp if (arg[0] == '%') { if (arg == "%") { if (design->selection_stack.size() > 0) - work_stack.push_back(design->selection_stack.back()); + work_stack.push_back(design->selection()); } else if (arg == "%%") { while (work_stack.size() > 1) { @@ -1031,9 +1031,9 @@ void handle_extra_select_args(Pass *pass, const vector &args, size_t arg work_stack.pop_back(); } if (work_stack.empty()) - design->selection_stack.push_back(RTLIL::Selection(false, false, design)); + design->push_empty_selection(); else - design->selection_stack.push_back(work_stack.back()); + design->push_selection(work_stack.back()); } // extern decl. in register.h @@ -1420,7 +1420,7 @@ struct SelectPass : public Pass { if (f.fail()) log_error("Can't open '%s' for reading: %s\n", read_file.c_str(), strerror(errno)); - RTLIL::Selection sel(false); + RTLIL::Selection sel(false, false, design); string line; while (std::getline(f, line)) { @@ -1461,7 +1461,7 @@ struct SelectPass : public Pass { log_cmd_error("Option -unset can not be combined with -list, -write, -count, -set, %s.\n", common_flagset); if (work_stack.size() == 0 && got_module) { - RTLIL::Selection sel; + RTLIL::Selection sel(true, false, design); select_filter_active_mod(design, sel); work_stack.push_back(sel); } @@ -1474,13 +1474,15 @@ struct SelectPass : public Pass { log_assert(design->selection_stack.size() > 0); if (clear_mode) { - design->selection_stack.back() = RTLIL::Selection(true, false, design); + design->pop_selection(); + design->push_full_selection(); design->selected_active_module = std::string(); return; } if (none_mode) { - design->selection_stack.back() = RTLIL::Selection(false, false, design); + design->pop_selection(); + design->push_empty_selection(); return; } @@ -1496,8 +1498,8 @@ struct SelectPass : public Pass { log_error("Can't open '%s' for writing: %s\n", write_file.c_str(), strerror(errno)); } if (work_stack.size() > 0) - design->selection_stack.push_back(work_stack.back()); - RTLIL::Selection *sel = &design->selection_stack.back(); + design->push_selection(work_stack.back()); + RTLIL::Selection *sel = &design->selection(); sel->optimize(design); for (auto mod : design->selected_modules()) { @@ -1515,7 +1517,7 @@ struct SelectPass : public Pass { if (f != nullptr) fclose(f); if (work_stack.size() > 0) - design->selection_stack.pop_back(); + design->pop_selection(); #undef LOG_OBJECT return; } @@ -1524,8 +1526,8 @@ struct SelectPass : public Pass { { if (work_stack.size() == 0) log_cmd_error("Nothing to add to selection.\n"); - select_op_union(design, design->selection_stack.back(), work_stack.back()); - design->selection_stack.back().optimize(design); + select_op_union(design, design->selection(), work_stack.back()); + design->selection().optimize(design); return; } @@ -1533,8 +1535,8 @@ struct SelectPass : public Pass { { if (work_stack.size() == 0) log_cmd_error("Nothing to delete from selection.\n"); - select_op_diff(design, design->selection_stack.back(), work_stack.back()); - design->selection_stack.back().optimize(design); + select_op_diff(design, design->selection(), work_stack.back()); + design->selection().optimize(design); return; } @@ -1574,7 +1576,7 @@ struct SelectPass : public Pass { if (work_stack.size() == 0) log_cmd_error("No selection to check.\n"); RTLIL::Selection *sel = &work_stack.back(); - design->selection_stack.push_back(*sel); + design->push_selection(*sel); sel->optimize(design); for (auto mod : design->selected_modules()) { module_count++; @@ -1604,7 +1606,7 @@ struct SelectPass : public Pass { log_error("Assertion failed: selection contains %d elements, less than the minimum number %d:%s\n%s", total_count, assert_min, sel_str.c_str(), desc.c_str()); } - design->selection_stack.pop_back(); + design->pop_selection(); return; } @@ -1625,7 +1627,7 @@ struct SelectPass : public Pass { } if (work_stack.size() == 0) { - RTLIL::Selection &sel = design->selection_stack.back(); + RTLIL::Selection &sel = design->selection(); if (sel.full_selection) log("*\n"); for (auto &it : sel.selected_modules) @@ -1636,8 +1638,8 @@ struct SelectPass : public Pass { return; } - design->selection_stack.back() = work_stack.back(); - design->selection_stack.back().optimize(design); + design->selection() = work_stack.back(); + design->selection().optimize(design); } } SelectPass; @@ -1677,7 +1679,8 @@ struct CdPass : public Pass { log_cmd_error("Invalid number of arguments.\n"); if (args.size() == 1 || args[1] == "/") { - design->selection_stack.back() = RTLIL::Selection(true, false, design); + design->pop_selection(); + design->push_full_selection(); design->selected_active_module = std::string(); return; } @@ -1686,7 +1689,8 @@ struct CdPass : public Pass { { string modname = design->selected_active_module; - design->selection_stack.back() = RTLIL::Selection(true, false, design); + design->pop_selection(); + design->push_full_selection(); design->selected_active_module = std::string(); while (1) @@ -1703,9 +1707,10 @@ struct CdPass : public Pass { continue; design->selected_active_module = modname; - design->selection_stack.back() = RTLIL::Selection(true, false, design); - select_filter_active_mod(design, design->selection_stack.back()); - design->selection_stack.back().optimize(design); + design->pop_selection(); + design->push_full_selection(); + select_filter_active_mod(design, design->selection()); + design->selection().optimize(design); return; } @@ -1722,9 +1727,10 @@ struct CdPass : public Pass { if (design->module(modname) != nullptr) { design->selected_active_module = modname; - design->selection_stack.back() = RTLIL::Selection(true, false, design); - select_filter_active_mod(design, design->selection_stack.back()); - design->selection_stack.back().optimize(design); + design->pop_selection(); + design->push_full_selection(); + select_filter_active_mod(design, design->selection()); + design->selection().optimize(design); return; } diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc index 82b5c6bcf..8a1bd58c4 100644 --- a/passes/cmds/show.cc +++ b/passes/cmds/show.cc @@ -802,8 +802,8 @@ struct ShowPass : public Pass { std::pair data; data.first = args[++argidx], argidx++; handle_extra_select_args(this, args, argidx, argidx+1, design); - data.second = design->selection_stack.back(); - design->selection_stack.pop_back(); + data.second = design->selection(); + design->pop_selection(); color_selections.push_back(data); continue; } @@ -811,8 +811,8 @@ struct ShowPass : public Pass { std::pair data; data.first = args[++argidx], argidx++; handle_extra_select_args(this, args, argidx, argidx+1, design); - data.second = design->selection_stack.back(); - design->selection_stack.pop_back(); + data.second = design->selection(); + design->pop_selection(); label_selections.push_back(data); continue; } diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc index 5bbbb2789..97a2886d4 100644 --- a/passes/cmds/stat.cc +++ b/passes/cmds/stat.cc @@ -468,7 +468,7 @@ struct StatPass : public Pass { first_module = false; } else { log("\n"); - log("=== %s%s ===\n", log_id(mod->name), design->selected_whole_module(mod->name) ? "" : " (partially selected)"); + log("=== %s%s ===\n", log_id(mod->name), mod->is_selected_whole() ? "" : " (partially selected)"); log("\n"); data.log_data(mod->name, false); } diff --git a/passes/cmds/viz.cc b/passes/cmds/viz.cc index 9dd68bd00..131e799ab 100644 --- a/passes/cmds/viz.cc +++ b/passes/cmds/viz.cc @@ -950,8 +950,8 @@ struct VizPass : public Pass { auto type = arg == "-g" || arg == "-G" ? VizConfig::TYPE_G : arg == "-u" || arg == "-U" ? VizConfig::TYPE_U : arg == "-x" || arg == "-X" ? VizConfig::TYPE_X : VizConfig::TYPE_S; - config.groups.push_back({type, design->selection_stack.back()}); - design->selection_stack.pop_back(); + config.groups.push_back({type, design->selection()}); + design->pop_selection(); continue; } if (arg == "-0" || arg == "-1" || arg == "-2" || arg == "-3" || arg == "-4" || diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index 52fd59cf8..facc5d173 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -246,7 +246,7 @@ struct SubmodWorker SubmodWorker(RTLIL::Design *design, RTLIL::Module *module, bool copy_mode = false, bool hidden_mode = false, std::string opt_name = std::string()) : design(design), module(module), sigmap(module), copy_mode(copy_mode), hidden_mode(hidden_mode), opt_name(opt_name) { - if (!design->selected_whole_module(module->name) && opt_name.empty()) + if (!module->is_selected_whole() && opt_name.empty()) return; if (module->processes.size() > 0) { diff --git a/passes/sat/cutpoint.cc b/passes/sat/cutpoint.cc index bca6a5ec6..e86b964e5 100644 --- a/passes/sat/cutpoint.cc +++ b/passes/sat/cutpoint.cc @@ -57,7 +57,7 @@ struct CutpointPass : public Pass { for (auto module : design->selected_modules()) { - if (design->selected_whole_module(module->name)) { + if (module->is_selected_whole()) { log("Making all outputs of module %s cut points, removing module contents.\n", log_id(module)); module->new_connections(std::vector()); for (auto cell : vector(module->cells())) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index a96a82659..56fa4b011 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -400,7 +400,7 @@ struct Abc9Pass : public ScriptPass } log_push(); - active_design->selection().select(mod); + active_design->select(mod); if (!active_design->selected_whole_module(mod)) log_error("Can't handle partially selected module %s!\n", log_id(mod)); @@ -452,7 +452,7 @@ struct Abc9Pass : public ScriptPass log_pop(); } - active_design->selection_stack.pop_back(); + active_design->pop_selection(); } } diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 4c7667a43..0d28b8f4a 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -454,7 +454,7 @@ void prep_bypass(RTLIL::Design *design) void prep_dff(RTLIL::Design *design) { - auto r = design->selection_vars.insert(std::make_pair(ID($abc9_flops), RTLIL::Selection(false))); + auto r = design->selection_vars.insert(std::make_pair(ID($abc9_flops), RTLIL::Selection(false, false, design))); auto &modules_sel = r.first->second; for (auto module : design->selected_modules()) diff --git a/passes/techmap/abc_new.cc b/passes/techmap/abc_new.cc index 5be823916..23670394b 100644 --- a/passes/techmap/abc_new.cc +++ b/passes/techmap/abc_new.cc @@ -157,7 +157,7 @@ struct AbcNewPass : public ScriptPass { exe_options = abc_exe_options; log_header(active_design, "Mapping module '%s'.\n", log_id(mod)); log_push(); - active_design->selection().select(mod); + active_design->select(mod); } std::string script_save; @@ -194,7 +194,7 @@ struct AbcNewPass : public ScriptPass { } if (!help_mode) { - active_design->selection_stack.pop_back(); + active_design->pop_selection(); } } } diff --git a/passes/techmap/aigmap.cc b/passes/techmap/aigmap.cc index 4836ebe34..b51ad912e 100644 --- a/passes/techmap/aigmap.cc +++ b/passes/techmap/aigmap.cc @@ -172,7 +172,7 @@ struct AigmapPass : public Pass { if (select_mode) { log_assert(!design->selection_stack.empty()); - RTLIL::Selection& sel = design->selection_stack.back(); + RTLIL::Selection& sel = design->selection(); sel.selected_members[module->name] = std::move(new_sel); } diff --git a/passes/techmap/nlutmap.cc b/passes/techmap/nlutmap.cc index 016789157..098c227f6 100644 --- a/passes/techmap/nlutmap.cc +++ b/passes/techmap/nlutmap.cc @@ -42,7 +42,7 @@ struct NlutmapWorker RTLIL::Selection get_selection() { - RTLIL::Selection sel(false); + RTLIL::Selection sel(false, false, module->design); for (auto cell : module->cells()) if (!mapped_cells.count(cell)) sel.select(module, cell); From 091e9488feb9888006e407e60cf9957bcfbbcaf4 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:08:14 +1300 Subject: [PATCH 07/26] rtlil: Design::top_module() can be const Since it doesn't change anything and is just a lookup. --- kernel/rtlil.cc | 2 +- kernel/rtlil.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index fa7712ee0..8205165f5 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -938,7 +938,7 @@ const RTLIL::Module *RTLIL::Design::module(const RTLIL::IdString& name) const return modules_.count(name) ? modules_.at(name) : NULL; } -RTLIL::Module *RTLIL::Design::top_module() +RTLIL::Module *RTLIL::Design::top_module() const { RTLIL::Module *module = nullptr; int module_count = 0; diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 52b63141b..b754b4717 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1246,7 +1246,7 @@ struct RTLIL::Design RTLIL::ObjRange modules(); RTLIL::Module *module(const RTLIL::IdString &name); const RTLIL::Module *module(const RTLIL::IdString &name) const; - RTLIL::Module *top_module(); + RTLIL::Module *top_module() const; bool has(const RTLIL::IdString &id) const { return modules_.count(id) != 0; From d09ae42951c58599b334b667455826e06d892d10 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:08:14 +1300 Subject: [PATCH 08/26] Fixing selections --- kernel/rtlil.cc | 2 +- passes/cmds/select.cc | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 8205165f5..a48a37834 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -1185,7 +1185,7 @@ void RTLIL::Design::pop_selection() std::vector RTLIL::Design::selected_modules(RTLIL::SelectPartials partials, RTLIL::SelectBoxes boxes) const { bool include_partials = partials == RTLIL::SELECT_ALL; - bool exclude_boxes = (partials & RTLIL::SB_UNBOXED_ONLY) == 0; + bool exclude_boxes = (partials & RTLIL::SB_UNBOXED_ONLY) != 0; bool ignore_wb = (partials & RTLIL::SB_INCL_WB) != 0; std::vector result; result.reserve(modules_.size()); diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc index 4db1c2f28..1eed7c818 100644 --- a/passes/cmds/select.cc +++ b/passes/cmds/select.cc @@ -1000,7 +1000,7 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp static std::string describe_selection_for_assert(RTLIL::Design *design, RTLIL::Selection *sel, bool whole_modules = false) { std::string desc = "Selection contains:\n"; - for (auto mod : design->selected_modules()) + for (auto mod : design->all_selected_modules()) { if (whole_modules && sel->selected_whole_module(mod->name)) desc += stringf("%s\n", id2cstr(mod->name)); @@ -1501,7 +1501,7 @@ struct SelectPass : public Pass { design->push_selection(work_stack.back()); RTLIL::Selection *sel = &design->selection(); sel->optimize(design); - for (auto mod : design->selected_modules()) + for (auto mod : design->all_selected_modules()) { if (sel->selected_whole_module(mod->name) && list_mode) log("%s\n", id2cstr(mod->name)); @@ -1578,7 +1578,7 @@ struct SelectPass : public Pass { RTLIL::Selection *sel = &work_stack.back(); design->push_selection(*sel); sel->optimize(design); - for (auto mod : design->selected_modules()) { + for (auto mod : design->all_selected_modules()) { module_count++; for ([[maybe_unused]] auto member_name : mod->selected_members()) total_count++; @@ -1777,7 +1777,7 @@ struct LsPass : public Pass { { std::vector matches; - for (auto mod : design->selected_modules()) + for (auto mod : design->all_selected_modules()) matches.push_back(mod->name); if (!matches.empty()) { From 59802584b0ad9a9731769d1086b278421e1eca6a Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:08:14 +1300 Subject: [PATCH 09/26] Fix describe_selection_for_assert If the current selection is not the provided selection, push the provided selection. --- passes/cmds/select.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc index 1eed7c818..54b6f0a42 100644 --- a/passes/cmds/select.cc +++ b/passes/cmds/select.cc @@ -999,6 +999,8 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp static std::string describe_selection_for_assert(RTLIL::Design *design, RTLIL::Selection *sel, bool whole_modules = false) { + bool push_selection = &design->selection() != sel; + if (push_selection) design->push_selection(*sel); std::string desc = "Selection contains:\n"; for (auto mod : design->all_selected_modules()) { @@ -1007,6 +1009,7 @@ static std::string describe_selection_for_assert(RTLIL::Design *design, RTLIL::S for (auto it : mod->selected_members()) desc += stringf("%s/%s\n", id2cstr(mod->name), id2cstr(it->name)); } + if (push_selection) design->pop_selection(); return desc; } From f15cd73419eb735210bbb09cd03d654faf111a43 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:08:14 +1300 Subject: [PATCH 10/26] Fix select_op_random ignoring boxes --- passes/cmds/select.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc index 54b6f0a42..8579c6111 100644 --- a/passes/cmds/select.cc +++ b/passes/cmds/select.cc @@ -228,7 +228,7 @@ static void select_op_random(RTLIL::Design *design, RTLIL::Selection &lhs, int c } } - lhs = RTLIL::Selection(false, false, design); + lhs = RTLIL::Selection(false, lhs.selects_boxes, design); while (!objects.empty() && count-- > 0) { From b296a970d260b9709ed52a296fae2a4ed1e534e7 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:08:14 +1300 Subject: [PATCH 11/26] abc9: Use push_empty_selection() --- passes/techmap/abc9.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 56fa4b011..1313fbd73 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -391,7 +391,7 @@ struct Abc9Pass : public ScriptPass } else { auto selected_modules = active_design->selected_modules(); - active_design->selection_stack.emplace_back(false); + active_design->push_empty_selection(); for (auto mod : selected_modules) { if (mod->processes.size() > 0) { @@ -402,6 +402,7 @@ struct Abc9Pass : public ScriptPass log_push(); active_design->select(mod); + // this check does nothing because the above line adds the whole module to the selection if (!active_design->selected_whole_module(mod)) log_error("Can't handle partially selected module %s!\n", log_id(mod)); From 9a9cd05f6c195f00e64ed39a3a414d2aa3e64bee Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:08:15 +1300 Subject: [PATCH 12/26] tests: Fixes for boxes cxxrtl `test_unconnected_output` and simple_abc9 `abc9.v` both expect boxed modules in the outputs, so make sure they work as expected. --- tests/cxxrtl/run-test.sh | 2 +- tests/simple_abc9/run-test.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/cxxrtl/run-test.sh b/tests/cxxrtl/run-test.sh index fd11a3783..ee299fc82 100755 --- a/tests/cxxrtl/run-test.sh +++ b/tests/cxxrtl/run-test.sh @@ -13,5 +13,5 @@ run_subtest value run_subtest value_fuzz # Compile-only test. -../../yosys -p "read_verilog test_unconnected_output.v; proc; clean; write_cxxrtl cxxrtl-test-unconnected_output.cc" +../../yosys -p "read_verilog test_unconnected_output.v; select =*; proc; clean; write_cxxrtl cxxrtl-test-unconnected_output.cc" ${CC:-gcc} -std=c++11 -c -o cxxrtl-test-unconnected_output -I../../backends/cxxrtl/runtime cxxrtl-test-unconnected_output.cc diff --git a/tests/simple_abc9/run-test.sh b/tests/simple_abc9/run-test.sh index b75e54dd3..5669321ac 100755 --- a/tests/simple_abc9/run-test.sh +++ b/tests/simple_abc9/run-test.sh @@ -49,6 +49,6 @@ exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v *.sv EXTRA_FLAGS="-f \"veri clean; \ check -assert * abc9_test037 %d; \ select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_ %%; \ - setattr -mod -unset blackbox -unset whitebox'" + setattr -mod -unset blackbox -unset whitebox =*'" # NOTE: Skip 'check -assert' on abc9_test037 because it intentionally has a combinatorial loop From a30bacfcb142a40ed6465c23af89d6978f3001f2 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:08:15 +1300 Subject: [PATCH 13/26] Add Selection::complete_selection Used to select all modules including boxes, set when both `full` and `boxes` are true in the constructor, pulling down `full_selection`. Add `Selection::selects_all()` method as short hand for `full_selection || complete_selection`. Update selection operations to account for complete selections. Add static methods to `Selection` for creating a new empty/full/complete selection to make it clearer to users when doing so. Use said static methods to replace most instances of the `Selection` constructor. Update `Selection::optimize` to use --- kernel/rtlil.cc | 36 +++++++++--------- kernel/rtlil.h | 22 ++++++++--- passes/cmds/scc.cc | 2 +- passes/cmds/select.cc | 75 ++++++++++++++++++++++++-------------- passes/techmap/abc9_ops.cc | 2 +- passes/techmap/nlutmap.cc | 2 +- 6 files changed, 86 insertions(+), 53 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index a48a37834..f9f4cca4a 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -779,6 +779,8 @@ bool RTLIL::Selection::boxed_module(const RTLIL::IdString &mod_name) const bool RTLIL::Selection::selected_module(const RTLIL::IdString &mod_name) const { + if (complete_selection) + return true; if (!selects_boxes && boxed_module(mod_name)) return false; if (full_selection) @@ -792,6 +794,8 @@ bool RTLIL::Selection::selected_module(const RTLIL::IdString &mod_name) const bool RTLIL::Selection::selected_whole_module(const RTLIL::IdString &mod_name) const { + if (complete_selection) + return true; if (!selects_boxes && boxed_module(mod_name)) return false; if (full_selection) @@ -803,6 +807,8 @@ bool RTLIL::Selection::selected_whole_module(const RTLIL::IdString &mod_name) co bool RTLIL::Selection::selected_member(const RTLIL::IdString &mod_name, const RTLIL::IdString &memb_name) const { + if (complete_selection) + return true; if (!selects_boxes && boxed_module(mod_name)) return false; if (full_selection) @@ -821,16 +827,13 @@ void RTLIL::Selection::optimize(RTLIL::Design *design) current_design = design; } - if (selects_boxes && full_selection) { - selected_modules.clear(); - selected_members.clear(); + if (selects_boxes && full_selection) + complete_selection = true; + if (complete_selection) { full_selection = false; - for (auto mod : current_design->modules()) { - selected_modules.insert(mod->name); - } - return; + selects_boxes = true; } - if (full_selection) { + if (selects_all()) { selected_modules.clear(); selected_members.clear(); return; @@ -878,10 +881,13 @@ void RTLIL::Selection::optimize(RTLIL::Design *design) selected_modules.insert(mod_name); } - if (!selects_boxes && selected_modules.size() == current_design->modules_.size()) { - full_selection = true; + if (selected_modules.size() == current_design->modules_.size()) { selected_modules.clear(); selected_members.clear(); + if (selects_boxes) + complete_selection = true; + else + full_selection = true; } } @@ -1160,21 +1166,17 @@ void RTLIL::Design::push_selection(RTLIL::Selection sel) void RTLIL::Design::push_empty_selection() { - RTLIL::Selection sel(false, false, this); - push_selection(sel); + push_selection(RTLIL::Selection::EmptySelection(this)); } void RTLIL::Design::push_full_selection() { - RTLIL::Selection sel(true, false, this); - push_selection(sel); + push_selection(RTLIL::Selection::FullSelection(this)); } void RTLIL::Design::push_complete_selection() { - RTLIL::Selection sel(true, true, this); - sel.optimize(this); - push_selection(sel); + push_selection(RTLIL::Selection::CompleteSelection(this)); } void RTLIL::Design::pop_selection() diff --git a/kernel/rtlil.h b/kernel/rtlil.h index b754b4717..56f00fdf6 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1166,11 +1166,13 @@ struct RTLIL::Selection { bool full_selection; bool selects_boxes; + bool complete_selection; pool selected_modules; dict> selected_members; RTLIL::Design *current_design; - Selection(bool full = true, bool boxes = false, RTLIL::Design *design = nullptr) : full_selection(full), selects_boxes(boxes), current_design(design) { } + Selection(bool full = true, bool boxes = false, RTLIL::Design *design = nullptr) : + full_selection(full && !boxes), selects_boxes(boxes), complete_selection(full && boxes), current_design(design) { } bool boxed_module(const RTLIL::IdString &mod_name) const; bool selected_module(const RTLIL::IdString &mod_name) const; @@ -1178,21 +1180,29 @@ struct RTLIL::Selection bool selected_member(const RTLIL::IdString &mod_name, const RTLIL::IdString &memb_name) const; void optimize(RTLIL::Design *design); + bool selects_all() const { + return full_selection || complete_selection; + } + template void select(T1 *module) { - if (!full_selection && selected_modules.count(module->name) == 0) { + if (!selects_all() && selected_modules.count(module->name) == 0) { selected_modules.insert(module->name); selected_members.erase(module->name); } } template void select(T1 *module, T2 *member) { - if (!full_selection && selected_modules.count(module->name) == 0) + if (!selects_all() && selected_modules.count(module->name) == 0) selected_members[module->name].insert(member->name); } bool empty() const { - return !full_selection && selected_modules.empty() && selected_members.empty(); + return !selects_all() && selected_modules.empty() && selected_members.empty(); } + + static Selection EmptySelection(RTLIL::Design *design = nullptr) { return Selection(false, false, design); }; + static Selection FullSelection(RTLIL::Design *design = nullptr) { return Selection(true, false, design); }; + static Selection CompleteSelection(RTLIL::Design *design = nullptr) { return Selection(true, true, design); }; }; struct RTLIL::Monitor @@ -1282,8 +1292,8 @@ struct RTLIL::Design void push_selection(RTLIL::Selection sel); void push_empty_selection(); - void push_full_selection(); - void push_complete_selection(); + void push_full_selection(); // all modules excluding boxes + void push_complete_selection(); // all modules including boxes void pop_selection(); RTLIL::Selection &selection() { diff --git a/passes/cmds/scc.cc b/passes/cmds/scc.cc index ddd72bb45..0f988e57a 100644 --- a/passes/cmds/scc.cc +++ b/passes/cmds/scc.cc @@ -340,7 +340,7 @@ struct SccPass : public Pass { int origSelectPos = design->selection_stack.size() - 1; extra_args(args, argidx, design); - RTLIL::Selection newSelection(false, false, design); + auto newSelection = RTLIL::Selection::EmptySelection(design); int scc_counter = 0; for (auto mod : design->selected_modules()) diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc index 8579c6111..7517af80a 100644 --- a/passes/cmds/select.cc +++ b/passes/cmds/select.cc @@ -141,35 +141,40 @@ static bool match_attr(const dict &attributes, co return match_attr(attributes, match_expr, std::string(), 0); } -static void full_select_no_box(RTLIL::Design *design, RTLIL::Selection &lhs) +static void select_all(RTLIL::Design *design, RTLIL::Selection &lhs) { - if (!lhs.full_selection) + if (!lhs.selects_all()) return; - lhs.current_design = design; lhs.selected_modules.clear(); for (auto mod : design->modules()) { - if (mod->get_blackbox_attribute()) + if (!lhs.selects_boxes && mod->get_blackbox_attribute()) continue; lhs.selected_modules.insert(mod->name); } + lhs.full_selection = false; + lhs.complete_selection = false; } static void select_op_neg(RTLIL::Design *design, RTLIL::Selection &lhs) { - if (lhs.full_selection) { + if (lhs.selects_all()) { lhs.full_selection = false; + lhs.complete_selection = false; lhs.selected_modules.clear(); lhs.selected_members.clear(); return; } - if (!lhs.selects_boxes && lhs.selected_modules.size() == 0 && lhs.selected_members.size() == 0) { - lhs.full_selection = true; + if (lhs.selected_modules.size() == 0 && lhs.selected_members.size() == 0) { + if (lhs.selects_boxes) + lhs.complete_selection = true; + else + lhs.full_selection = true; return; } - RTLIL::Selection new_sel(false); + auto new_sel = RTLIL::Selection::EmptySelection(); for (auto mod : design->modules()) { @@ -312,10 +317,17 @@ static void select_op_alias(RTLIL::Design *design, RTLIL::Selection &lhs) static void select_op_union(RTLIL::Design* design, RTLIL::Selection &lhs, const RTLIL::Selection &rhs) { + if (lhs.complete_selection) + return; + else if (rhs.complete_selection) { + lhs.complete_selection = true; + lhs.optimize(design); + return; + } + if (rhs.selects_boxes) { if (lhs.full_selection) { - full_select_no_box(design, lhs); - lhs.full_selection = false; + select_all(design, lhs); } lhs.selects_boxes = true; } @@ -325,7 +337,7 @@ static void select_op_union(RTLIL::Design* design, RTLIL::Selection &lhs, const if (rhs.full_selection) { if (lhs.selects_boxes) { auto new_rhs = RTLIL::Selection(rhs); - full_select_no_box(design, new_rhs); + select_all(design, new_rhs); for (auto mod : new_rhs.selected_modules) lhs.selected_modules.insert(mod); } else { @@ -348,10 +360,19 @@ static void select_op_union(RTLIL::Design* design, RTLIL::Selection &lhs, const static void select_op_diff(RTLIL::Design *design, RTLIL::Selection &lhs, const RTLIL::Selection &rhs) { + if (rhs.complete_selection) { + lhs.full_selection = false; + lhs.complete_selection = false; + lhs.selected_modules.clear(); + lhs.selected_members.clear(); + return; + } + if (rhs.full_selection) { if (lhs.selects_boxes) { auto new_rhs = RTLIL::Selection(rhs); - full_select_no_box(design, new_rhs); + select_all(design, new_rhs); + select_all(design, lhs); for (auto mod : new_rhs.selected_modules) { lhs.selected_modules.erase(mod); lhs.selected_members.erase(mod); @@ -364,12 +385,10 @@ static void select_op_diff(RTLIL::Design *design, RTLIL::Selection &lhs, const R return; } - if (lhs.full_selection) { - if (rhs.empty()) - return; - full_select_no_box(design, lhs); - lhs.full_selection = false; - } + if (rhs.empty() || lhs.empty()) + return; + + select_all(design, lhs); for (auto &it : rhs.selected_modules) { lhs.selected_modules.erase(it); @@ -406,14 +425,16 @@ static void select_op_diff(RTLIL::Design *design, RTLIL::Selection &lhs, const R static void select_op_intersect(RTLIL::Design *design, RTLIL::Selection &lhs, const RTLIL::Selection &rhs) { + if (rhs.complete_selection) + return; + if (rhs.full_selection && !lhs.selects_boxes) return; - if (lhs.full_selection) { - lhs.full_selection = false; - for (auto mod : design->modules()) - lhs.selected_modules.insert(mod->name); - } + if (lhs.empty() || rhs.empty()) + return; + + select_all(design, lhs); std::vector del_list; @@ -1050,7 +1071,7 @@ RTLIL::Selection eval_select_args(const vector &args, RTLIL::Design *des work_stack.pop_back(); } if (work_stack.empty()) - return RTLIL::Selection(false, false, design); + return RTLIL::Selection::EmptySelection(design); return work_stack.back(); } @@ -1423,7 +1444,7 @@ struct SelectPass : public Pass { if (f.fail()) log_error("Can't open '%s' for reading: %s\n", read_file.c_str(), strerror(errno)); - RTLIL::Selection sel(false, false, design); + auto sel = RTLIL::Selection::EmptySelection(design); string line; while (std::getline(f, line)) { @@ -1464,7 +1485,7 @@ struct SelectPass : public Pass { log_cmd_error("Option -unset can not be combined with -list, -write, -count, -set, %s.\n", common_flagset); if (work_stack.size() == 0 && got_module) { - RTLIL::Selection sel(true, false, design); + auto sel = RTLIL::Selection::FullSelection(design); select_filter_active_mod(design, sel); work_stack.push_back(sel); } @@ -1616,7 +1637,7 @@ struct SelectPass : public Pass { if (!set_name.empty()) { if (work_stack.size() == 0) - design->selection_vars[set_name] = RTLIL::Selection(false, false, design); + design->selection_vars[set_name] = RTLIL::Selection::EmptySelection(design); else design->selection_vars[set_name] = work_stack.back(); return; diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 0d28b8f4a..6cb569b5a 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -454,7 +454,7 @@ void prep_bypass(RTLIL::Design *design) void prep_dff(RTLIL::Design *design) { - auto r = design->selection_vars.insert(std::make_pair(ID($abc9_flops), RTLIL::Selection(false, false, design))); + auto r = design->selection_vars.insert(std::make_pair(ID($abc9_flops), RTLIL::Selection::EmptySelection(design))); auto &modules_sel = r.first->second; for (auto module : design->selected_modules()) diff --git a/passes/techmap/nlutmap.cc b/passes/techmap/nlutmap.cc index 098c227f6..c823f10fe 100644 --- a/passes/techmap/nlutmap.cc +++ b/passes/techmap/nlutmap.cc @@ -42,7 +42,7 @@ struct NlutmapWorker RTLIL::Selection get_selection() { - RTLIL::Selection sel(false, false, module->design); + auto sel = RTLIL::Selection::EmptySelection(module->design); for (auto cell : module->cells()) if (!mapped_cells.count(cell)) sel.select(module, cell); From 824f7146aab8302510b3e205877971a597f9a753 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:08:15 +1300 Subject: [PATCH 14/26] Selecting a blackbox sets selects_boxes --- kernel/rtlil.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 56f00fdf6..d7c860b39 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1188,12 +1188,17 @@ struct RTLIL::Selection if (!selects_all() && selected_modules.count(module->name) == 0) { selected_modules.insert(module->name); selected_members.erase(module->name); + if (module->get_blackbox_attribute()) + selects_boxes = true; } } template void select(T1 *module, T2 *member) { - if (!selects_all() && selected_modules.count(module->name) == 0) + if (!selects_all() && selected_modules.count(module->name) == 0) { selected_members[module->name].insert(member->name); + if (module->get_blackbox_attribute()) + selects_boxes = true; + } } bool empty() const { From cacea737bcc3f6aa826891ea8f9f17a550771c3f Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:08:15 +1300 Subject: [PATCH 15/26] select.cc: Re-add '=' to empty selection warning --- passes/cmds/select.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc index 7517af80a..c42c0ead2 100644 --- a/passes/cmds/select.cc +++ b/passes/cmds/select.cc @@ -1008,12 +1008,16 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp for (auto &it : arg_mod_found) { if (it.second == false && !disable_empty_warning) { - log_warning("Selection \"%s\" did not match any module.\n", it.first.c_str()); + std::string selection_str = select_blackboxes ? "=" : ""; + selection_str += it.first; + log_warning("Selection \"%s\" did not match any module.\n", selection_str.c_str()); } } for (auto &it : arg_memb_found) { if (it.second == false && !disable_empty_warning) { - log_warning("Selection \"%s\" did not match any object.\n", it.first.c_str()); + std::string selection_str = select_blackboxes ? "=" : ""; + selection_str += it.first; + log_warning("Selection \"%s\" did not match any object.\n", selection_str.c_str()); } } } From 2dec493054aede44642f7af993ca9c4be97ba479 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:08:15 +1300 Subject: [PATCH 16/26] abc9.cc: Call select =* Or rather, say we're calling `select =*`, but actually bypass the select command to avoid the warning that can pop up if there is nothing to select. --- passes/techmap/abc9.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 1313fbd73..3a79c0dbf 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -306,6 +306,8 @@ struct Abc9Pass : public ScriptPass } run("design -stash $abc9"); run("design -load $abc9_map"); + if (help_mode) run("select =*"); + else active_design->push_complete_selection(); run("proc"); run("wbflip"); run("techmap -wb -map %$abc9 -map +/techmap.v A:abc9_flop"); @@ -369,6 +371,8 @@ struct Abc9Pass : public ScriptPass if (saved_designs.count("$abc9_holes") || help_mode) { run("design -stash $abc9"); run("design -load $abc9_holes"); + if (help_mode) run("select =*"); + else active_design->push_complete_selection(); run("techmap -wb -map %$abc9 -map +/techmap.v"); run("opt -purge"); run("aigmap"); From 38293d3bdf3d07be14b531dcbffa56c9d61edb51 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:08:16 +1300 Subject: [PATCH 17/26] select.cc: Fix %i when rhs is empty --- passes/cmds/select.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc index c42c0ead2..bb1055c67 100644 --- a/passes/cmds/select.cc +++ b/passes/cmds/select.cc @@ -431,9 +431,17 @@ static void select_op_intersect(RTLIL::Design *design, RTLIL::Selection &lhs, co if (rhs.full_selection && !lhs.selects_boxes) return; - if (lhs.empty() || rhs.empty()) + if (lhs.empty()) return; + if (rhs.empty()) { + lhs.full_selection = false; + lhs.complete_selection = false; + lhs.selected_modules.clear(); + lhs.selected_members.clear(); + return; + } + select_all(design, lhs); std::vector del_list; From 7eaf33e4da19142cfa127d09660a3a2e8a55fced Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:08:16 +1300 Subject: [PATCH 18/26] abc9: Use techmap -autoproc Fixes quicklogic/pp3 problem with `dffepc` including processes. Also means the preceding `proc` is safe to remove (and may result in some small speedup by doing so). --- passes/techmap/abc9.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 3a79c0dbf..fe5cc7af1 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -308,9 +308,8 @@ struct Abc9Pass : public ScriptPass run("design -load $abc9_map"); if (help_mode) run("select =*"); else active_design->push_complete_selection(); - run("proc"); run("wbflip"); - run("techmap -wb -map %$abc9 -map +/techmap.v A:abc9_flop"); + run("techmap -autoproc -wb -map %$abc9 -map +/techmap.v A:abc9_flop"); run("opt -nodffe -nosdff"); if (dff_mode || help_mode) { if (!help_mode) From add5eba9b2070cbaa3ab937bde27fc94f274519b Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:08:16 +1300 Subject: [PATCH 19/26] Design::selection_stack should never be empty Add a `log_assert` for it in `Design::check()`. Remove unneeded checks in other places. --- kernel/rtlil.cc | 14 ++++++++------ kernel/rtlil.h | 12 ++++-------- kernel/yosys.cc | 2 +- passes/cmds/select.cc | 5 ++--- passes/techmap/aigmap.cc | 1 - 5 files changed, 15 insertions(+), 19 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index f9f4cca4a..6a29c42e7 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -1102,6 +1102,7 @@ void RTLIL::Design::sort() void RTLIL::Design::check() { #ifndef NDEBUG + log_assert(!selection_stack.empty()); for (auto &it : modules_) { log_assert(this == it.second->design); log_assert(it.first == it.second->name); @@ -1125,8 +1126,6 @@ bool RTLIL::Design::selected_module(const RTLIL::IdString& mod_name) const { if (!selected_active_module.empty() && mod_name != selected_active_module) return false; - if (selection_stack.size() == 0) - return true; return selection().selected_module(mod_name); } @@ -1134,8 +1133,6 @@ bool RTLIL::Design::selected_whole_module(const RTLIL::IdString& mod_name) const { if (!selected_active_module.empty() && mod_name != selected_active_module) return false; - if (selection_stack.size() == 0) - return true; return selection().selected_whole_module(mod_name); } @@ -1143,8 +1140,6 @@ bool RTLIL::Design::selected_member(const RTLIL::IdString& mod_name, const RTLIL { if (!selected_active_module.empty() && mod_name != selected_active_module) return false; - if (selection_stack.size() == 0) - return true; return selection().selected_member(mod_name, memb_name); } @@ -1182,6 +1177,9 @@ void RTLIL::Design::push_complete_selection() void RTLIL::Design::pop_selection() { selection_stack.pop_back(); + // Default to a full_selection if we ran out of stack + if (selection_stack.empty()) + push_full_selection(); } std::vector RTLIL::Design::selected_modules(RTLIL::SelectPartials partials, RTLIL::SelectBoxes boxes) const @@ -2366,6 +2364,10 @@ void RTLIL::Module::check() log_assert(!packed_memids.count(memid)); packed_memids.insert(memid); } + auto cell_mod = design->module(it.first); + if (cell_mod != nullptr) { + log_assert(!it.second->get_blackbox_attribute()); + } } for (auto &it : processes) { diff --git a/kernel/rtlil.h b/kernel/rtlil.h index d7c860b39..1c7eaec39 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1322,17 +1322,13 @@ struct RTLIL::Design } template void select(T1 *module) { - if (selection_stack.size() > 0) { - RTLIL::Selection &sel = selection(); - sel.select(module); - } + RTLIL::Selection &sel = selection(); + sel.select(module); } template void select(T1 *module, T2 *member) { - if (selection_stack.size() > 0) { - RTLIL::Selection &sel = selection(); - sel.select(module, member); - } + RTLIL::Selection &sel = selection(); + sel.select(module, member); } diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 85354c163..37e820060 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -679,7 +679,7 @@ const char *create_prompt(RTLIL::Design *design, int recursion_counter) str += "yosys"; if (!design->selected_active_module.empty()) str += stringf(" [%s]", RTLIL::unescape_id(design->selected_active_module).c_str()); - if (!design->selection_stack.empty() && !design->full_selection()) { + if (!design->full_selection()) { if (design->selected_active_module.empty()) str += "*"; else if (design->selection().selected_modules.size() != 1 || design->selection().selected_members.size() != 0 || diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc index bb1055c67..1ed1987c8 100644 --- a/passes/cmds/select.cc +++ b/passes/cmds/select.cc @@ -715,8 +715,7 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp if (arg[0] == '%') { if (arg == "%") { - if (design->selection_stack.size() > 0) - work_stack.push_back(design->selection()); + work_stack.push_back(design->selection()); } else if (arg == "%%") { while (work_stack.size() > 1) { @@ -1507,7 +1506,7 @@ struct SelectPass : public Pass { work_stack.pop_back(); } - log_assert(design->selection_stack.size() > 0); + log_assert(!design->selection_stack.empty()); if (clear_mode) { design->pop_selection(); diff --git a/passes/techmap/aigmap.cc b/passes/techmap/aigmap.cc index b51ad912e..19e568a61 100644 --- a/passes/techmap/aigmap.cc +++ b/passes/techmap/aigmap.cc @@ -171,7 +171,6 @@ struct AigmapPass : public Pass { module->remove(cell); if (select_mode) { - log_assert(!design->selection_stack.empty()); RTLIL::Selection& sel = design->selection(); sel.selected_members[module->name] = std::move(new_sel); } From 732c82f8514c0d4963c604f00503d59dc1c080e2 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:08:56 +1300 Subject: [PATCH 20/26] abc_new: Use push_empty_selection() --- passes/techmap/abc_new.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc_new.cc b/passes/techmap/abc_new.cc index 23670394b..dfa2e2f71 100644 --- a/passes/techmap/abc_new.cc +++ b/passes/techmap/abc_new.cc @@ -139,7 +139,7 @@ struct AbcNewPass : public ScriptPass { if (!help_mode) { selected_modules = order_modules(active_design, active_design->selected_whole_modules_warn()); - active_design->selection_stack.emplace_back(false); + active_design->push_empty_selection(); } else { selected_modules = {nullptr}; run("foreach module in selection"); From 46a311acb2089ce65ae361d45e39910821559f96 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:08:56 +1300 Subject: [PATCH 21/26] firrtl: Drop full_selection check Change `top` pointer default to `nullptr` to avoid issues with `Design->top_module()` only operating on the current selection. Calls to other passes (`bmuxmap` etc) will only operate on the current selection, and may cause problems when those cells are unprocessed, but this is consistent with the other backends that only operate on the full designs and will hopefully be fixed in another PR soon :) --- backends/firrtl/firrtl.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index eac0c9719..ceb805dcb 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -1215,9 +1215,6 @@ struct FirrtlBackend : public Backend { } extra_args(f, filename, args, argidx); - if (!design->full_selection()) - log_cmd_error("This command only operates on fully selected designs!\n"); - log_header(design, "Executing FIRRTL backend.\n"); log_push(); @@ -1230,7 +1227,7 @@ struct FirrtlBackend : public Backend { autoid_counter = 0; // Get the top module, or a reasonable facsimile - we need something for the circuit name. - Module *top = design->top_module(); + Module *top = nullptr; Module *last = nullptr; // Generate module and wire names. for (auto module : design->modules()) { From a3968d43f0e9895a9f00b88ba2bfd5b284f0c648 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:08:56 +1300 Subject: [PATCH 22/26] Drop deprecation on Design::selected_modules() Instead, change the default `Design::selected_modules()` to match the behaviour (i.e. `selected_unboxed_modules_warn()`) because it's a lot of files to touch and they don't really _need_ to be updated. Also change `Design::selected_whole_modules()` users over to `Design::selected_unboxed_whole_modules()`, except `attrmap` because I'm not convinced it should be ignoring boxes. So instead, leave the deprecation warning for that one use and come back to the pass another time. --- kernel/rtlil.h | 4 +--- passes/opt/opt_clean.cc | 2 +- passes/sat/sim.cc | 4 ++-- passes/techmap/clockgate.cc | 2 +- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 1c7eaec39..c81990f43 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1332,10 +1332,8 @@ struct RTLIL::Design } - std::vector selected_modules(RTLIL::SelectPartials partials, RTLIL::SelectBoxes boxes = SB_ALL) const; + std::vector selected_modules(RTLIL::SelectPartials partials = SELECT_ALL, RTLIL::SelectBoxes boxes = SB_UNBOXED_WARN) const; - [[deprecated("Use selected_unboxed_modules() to maintain prior behaviour, or consider one of the other selected module helpers.")]] - std::vector selected_modules() const { return selected_modules(SELECT_ALL, SB_UNBOXED_WARN); } std::vector all_selected_modules() const { return selected_modules(SELECT_ALL, SB_ALL); } std::vector selected_unboxed_modules() const { return selected_modules(SELECT_ALL, SB_UNBOXED_ONLY); } std::vector selected_unboxed_modules_warn() const { return selected_modules(SELECT_ALL, SB_UNBOXED_WARN); } diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index c37c03607..620b38813 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -734,7 +734,7 @@ struct CleanPass : public Pass { count_rm_cells = 0; count_rm_wires = 0; - for (auto module : design->selected_whole_modules()) { + for (auto module : design->selected_unboxed_whole_modules()) { if (module->has_processes()) continue; rmunused_module(module, purge_mode, ys_debug(), true); diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index 8fac93b98..dd2f1d255 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -2887,7 +2887,7 @@ struct SimPass : public Pass { if (!top_mod) log_cmd_error("Design has no top module, use the 'hierarchy' command to specify one.\n"); } else { - auto mods = design->selected_whole_modules(); + auto mods = design->selected_unboxed_whole_modules(); if (GetSize(mods) != 1) log_cmd_error("Only one top module must be selected.\n"); top_mod = mods.front(); @@ -3016,7 +3016,7 @@ struct Fst2TbPass : public Pass { if (!top_mod) log_cmd_error("Design has no top module, use the 'hierarchy' command to specify one.\n"); } else { - auto mods = design->selected_whole_modules(); + auto mods = design->selected_unboxed_whole_modules(); if (GetSize(mods) != 1) log_cmd_error("Only one top module must be selected.\n"); top_mod = mods.front(); diff --git a/passes/techmap/clockgate.cc b/passes/techmap/clockgate.cc index 52851d922..3a3d24c0f 100644 --- a/passes/techmap/clockgate.cc +++ b/passes/techmap/clockgate.cc @@ -333,7 +333,7 @@ struct ClockgatePass : public Pass { dict clk_nets; int gated_flop_count = 0; - for (auto module : design->selected_whole_modules()) { + for (auto module : design->selected_unboxed_whole_modules()) { for (auto cell : module->cells()) { if (!RTLIL::builtin_ff_cell_types().count(cell->type)) continue; From 68adac691d0a5fcb257169b5b6ff4171e2292d24 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:40:06 +1300 Subject: [PATCH 23/26] rtlil.cc: Add comment to log_assert Because the use of `RTLIL::AttrObject::get_blackbox_attribute()` is deprecated, but the assert is needed in case users are doing weird things. --- kernel/rtlil.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 6a29c42e7..c9d2f6760 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -2366,6 +2366,9 @@ void RTLIL::Module::check() } auto cell_mod = design->module(it.first); if (cell_mod != nullptr) { + // assertion check below to make sure that there are no + // cases where a cell has a blackbox attribute since + // that is deprecated log_assert(!it.second->get_blackbox_attribute()); } } From 8405b3b72308d2b393e4ab3a14f00850b9a6d662 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 14 Mar 2025 16:32:00 +1300 Subject: [PATCH 24/26] select: Fix -none and -clear If the selection stack only has one element (which it normally does), then `design->pop_selection()` automatically resets to the default full selection. This is a problem for `select [-none | -clear]` which were trying to replace the current selection, but because the pop added an extra element when the `execute` returned, the extra selection (the one we actually wanted) gets popped too. So instead, reassign `design->selection()` in the same way as if we called `select [selection]`. Also adds selection stack tests, and removes the accidentally-committed `boxes_dummy.ys`. --- passes/cmds/select.cc | 6 ++---- tests/select/boxes_dummy.ys | 13 ------------- tests/select/boxes_stack.ys | 29 +++++++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 17 deletions(-) delete mode 100644 tests/select/boxes_dummy.ys create mode 100644 tests/select/boxes_stack.ys diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc index 1ed1987c8..c34cf43c6 100644 --- a/passes/cmds/select.cc +++ b/passes/cmds/select.cc @@ -1509,15 +1509,13 @@ struct SelectPass : public Pass { log_assert(!design->selection_stack.empty()); if (clear_mode) { - design->pop_selection(); - design->push_full_selection(); + design->selection() = RTLIL::Selection::FullSelection(design); design->selected_active_module = std::string(); return; } if (none_mode) { - design->pop_selection(); - design->push_empty_selection(); + design->selection() = RTLIL::Selection::EmptySelection(design); return; } diff --git a/tests/select/boxes_dummy.ys b/tests/select/boxes_dummy.ys deleted file mode 100644 index 67d59bdf1..000000000 --- a/tests/select/boxes_dummy.ys +++ /dev/null @@ -1,13 +0,0 @@ -read_verilog -specify boxes.v -clean - -echo on -select -list -select -count -select -count * -select -count top -select -count top/w:* -select -list =* -select -count =* -select -clear -select -assert-count 9 =?b diff --git a/tests/select/boxes_stack.ys b/tests/select/boxes_stack.ys new file mode 100644 index 000000000..8c2eb7526 --- /dev/null +++ b/tests/select/boxes_stack.ys @@ -0,0 +1,29 @@ +read_verilog -specify boxes.v +clean + +# default selection == select * +select -assert-count 4 * +select -assert-count 4 % + +# -none replaces default selection +select -none +select -assert-none % +select -assert-count 13 =* + +# select replaces current selection +select =* +select -assert-count 13 % + +# -module changes module +select -module wb +select -assert-none % +select -assert-count 5 =* + +# -none maintains module +select -none +select -assert-count 5 =* + +# -clear clears current selection and module +select -clear +select -assert-count 4 % +select -assert-count 13 =* From dab67f84dae6bc5240fd492a627f3ba2eedf8bd1 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Sat, 5 Apr 2025 10:40:19 +1300 Subject: [PATCH 25/26] rtlil.h: Document selections --- kernel/rtlil.h | 103 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 97 insertions(+), 6 deletions(-) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index c81990f43..97160e1d9 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1164,26 +1164,60 @@ public: struct RTLIL::Selection { - bool full_selection; + // selection includes boxed modules bool selects_boxes; + // selection covers full design, including boxed modules bool complete_selection; + // selection covers full design, not including boxed modules + bool full_selection; pool selected_modules; dict> selected_members; RTLIL::Design *current_design; - Selection(bool full = true, bool boxes = false, RTLIL::Design *design = nullptr) : + // create a new selection + Selection( + // should the selection cover the full design + bool full = true, + // should the selection include boxed modules + bool boxes = false, + // the design to select from + RTLIL::Design *design = nullptr + ) : full_selection(full && !boxes), selects_boxes(boxes), complete_selection(full && boxes), current_design(design) { } + // checks if the given module exists in the current design and is a + // boxed module, warning the user if the current design is not set bool boxed_module(const RTLIL::IdString &mod_name) const; + + // checks if the given module is included in this selection bool selected_module(const RTLIL::IdString &mod_name) const; + + // checks if the given module is wholly included in this selection, + // i.e. not partially selected bool selected_whole_module(const RTLIL::IdString &mod_name) const; + + // checks if the given member from the given module is included in this + // selection bool selected_member(const RTLIL::IdString &mod_name, const RTLIL::IdString &memb_name) const; + + // optimizes this selection for the given design by: + // - removing non-existent modules and members, any boxed modules and + // their members (if selection does not include boxes), and any + // partially selected modules with no selected members; + // - marking partially selected modules as wholly selected if all + // members of that module are selected; and + // - marking selection as a complete_selection if all modules in the + // given design are selected, or a full_selection if it does not + // include boxes. void optimize(RTLIL::Design *design); + // checks if selection covers full design (may or may not include + // boxed-modules) bool selects_all() const { return full_selection || complete_selection; } + // add whole module to this selection template void select(T1 *module) { if (!selects_all() && selected_modules.count(module->name) == 0) { selected_modules.insert(module->name); @@ -1193,6 +1227,7 @@ struct RTLIL::Selection } } + // add member of module to this selection template void select(T1 *module, T2 *member) { if (!selects_all() && selected_modules.count(module->name) == 0) { selected_members[module->name].insert(member->name); @@ -1201,12 +1236,18 @@ struct RTLIL::Selection } } + // checks if selection is empty bool empty() const { return !selects_all() && selected_modules.empty() && selected_members.empty(); } + // create a new selection which is empty static Selection EmptySelection(RTLIL::Design *design = nullptr) { return Selection(false, false, design); }; + + // create a new selection with all non-boxed modules static Selection FullSelection(RTLIL::Design *design = nullptr) { return Selection(true, false, design); }; + + // create a new selection with all modules, including boxes static Selection CompleteSelection(RTLIL::Design *design = nullptr) { return Selection(true, true, design); }; }; @@ -1288,61 +1329,111 @@ struct RTLIL::Design void check(); void optimize(); + // checks if the given module is included in the current selection bool selected_module(const RTLIL::IdString &mod_name) const; + + // checks if the given module is wholly included in the current + // selection, i.e. not partially selected bool selected_whole_module(const RTLIL::IdString &mod_name) const; + + // checks if the given member from the given module is included in the + // current selection bool selected_member(const RTLIL::IdString &mod_name, const RTLIL::IdString &memb_name) const; + // checks if the given module is included in the current selection bool selected_module(RTLIL::Module *mod) const; + + // checks if the given module is wholly included in the current + // selection, i.e. not partially selected bool selected_whole_module(RTLIL::Module *mod) const; + // push the given selection to the selection stack void push_selection(RTLIL::Selection sel); + // push a new selection to the selection stack, with nothing selected void push_empty_selection(); - void push_full_selection(); // all modules excluding boxes - void push_complete_selection(); // all modules including boxes + // push a new selection to the selection stack, with all non-boxed + // modules selected + void push_full_selection(); + // push a new selection to the selection stack, with all modules + // selected including boxes + void push_complete_selection(); + // pop the current selection from the stack, returning to a full + // selection (no boxes) if the stack is empty void pop_selection(); + // get the current selection RTLIL::Selection &selection() { return selection_stack.back(); } + // get the current selection const RTLIL::Selection &selection() const { return selection_stack.back(); } + // is the current selection a full selection (no boxes) bool full_selection() const { return selection().full_selection; } + // is the given module in the current selection template bool selected(T1 *module) const { return selected_module(module->name); } + // is the given member of the given module in the current selection template bool selected(T1 *module, T2 *member) const { return selected_member(module->name, member->name); } + // add whole module to the current selection template void select(T1 *module) { RTLIL::Selection &sel = selection(); sel.select(module); } + // add member of module to the current selection template void select(T1 *module, T2 *member) { RTLIL::Selection &sel = selection(); sel.select(module, member); } - std::vector selected_modules(RTLIL::SelectPartials partials = SELECT_ALL, RTLIL::SelectBoxes boxes = SB_UNBOXED_WARN) const; + // returns all selected modules + std::vector selected_modules( + // controls if partially selected modules are included + RTLIL::SelectPartials partials = SELECT_ALL, + // controls if boxed modules are included + RTLIL::SelectBoxes boxes = SB_UNBOXED_WARN + ) const; + // returns all selected modules, and may include boxes std::vector all_selected_modules() const { return selected_modules(SELECT_ALL, SB_ALL); } + // returns all selected unboxed modules, silently ignoring any boxed + // modules in the selection std::vector selected_unboxed_modules() const { return selected_modules(SELECT_ALL, SB_UNBOXED_ONLY); } + // returns all selected unboxed modules, warning the user if any boxed + // modules have been ignored std::vector selected_unboxed_modules_warn() const { return selected_modules(SELECT_ALL, SB_UNBOXED_WARN); } [[deprecated("Use select_unboxed_whole_modules() to maintain prior behaviour, or consider one of the other selected whole module helpers.")]] std::vector selected_whole_modules() const { return selected_modules(SELECT_WHOLE_ONLY, SB_UNBOXED_WARN); } + // returns all selected whole modules, silently ignoring partially + // selected modules, and may include boxes std::vector all_selected_whole_modules() const { return selected_modules(SELECT_WHOLE_ONLY, SB_ALL); } - std::vector selected_whole_modules_warn(bool include_wb = false) const { return selected_modules(SELECT_WHOLE_WARN, include_wb ? SB_EXCL_BB_WARN : SB_UNBOXED_WARN); } + // returns all selected whole modules, warning the user if any partially + // selected or boxed modules have been ignored; optionally includes + // selected whole modules with the 'whitebox' attribute + std::vector selected_whole_modules_warn( + // should whole modules with the 'whitebox' attribute be + // included + bool include_wb = false + ) const { return selected_modules(SELECT_WHOLE_WARN, include_wb ? SB_EXCL_BB_WARN : SB_UNBOXED_WARN); } + // returns all selected unboxed whole modules, silently ignoring + // partially selected or boxed modules std::vector selected_unboxed_whole_modules() const { return selected_modules(SELECT_WHOLE_ONLY, SB_UNBOXED_ONLY); } + // returns all selected unboxed whole modules, warning the user if any + // partially selected or boxed modules have been ignored std::vector selected_unboxed_whole_modules_warn() const { return selected_modules(SELECT_WHOLE_WARN, SB_UNBOXED_WARN); } #ifdef WITH_PYTHON static std::map *get_all_designs(void); From d8a9ad686009f1f09b2c6f6d73f98a4db54d7f78 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Sat, 5 Apr 2025 10:56:01 +1300 Subject: [PATCH 26/26] Add Selection::clear() method Use method in `select.cc` to reduce code duplication. --- kernel/rtlil.cc | 8 ++++++++ kernel/rtlil.h | 3 +++ passes/cmds/select.cc | 26 ++++++-------------------- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index c9d2f6760..637cc9be3 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -891,6 +891,14 @@ void RTLIL::Selection::optimize(RTLIL::Design *design) } } +void RTLIL::Selection::clear() +{ + full_selection = false; + complete_selection = false; + selected_modules.clear(); + selected_members.clear(); +} + RTLIL::Design::Design() : verilog_defines (new define_map_t) { diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 97160e1d9..52e7a17e7 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1241,6 +1241,9 @@ struct RTLIL::Selection return !selects_all() && selected_modules.empty() && selected_members.empty(); } + // clear this selection, leaving it empty + void clear(); + // create a new selection which is empty static Selection EmptySelection(RTLIL::Design *design = nullptr) { return Selection(false, false, design); }; diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc index c34cf43c6..1d75091af 100644 --- a/passes/cmds/select.cc +++ b/passes/cmds/select.cc @@ -159,10 +159,7 @@ static void select_all(RTLIL::Design *design, RTLIL::Selection &lhs) static void select_op_neg(RTLIL::Design *design, RTLIL::Selection &lhs) { if (lhs.selects_all()) { - lhs.full_selection = false; - lhs.complete_selection = false; - lhs.selected_modules.clear(); - lhs.selected_members.clear(); + lhs.clear(); return; } @@ -341,9 +338,8 @@ static void select_op_union(RTLIL::Design* design, RTLIL::Selection &lhs, const for (auto mod : new_rhs.selected_modules) lhs.selected_modules.insert(mod); } else { + lhs.clear(); lhs.full_selection = true; - lhs.selected_modules.clear(); - lhs.selected_members.clear(); } return; } @@ -361,10 +357,7 @@ static void select_op_union(RTLIL::Design* design, RTLIL::Selection &lhs, const static void select_op_diff(RTLIL::Design *design, RTLIL::Selection &lhs, const RTLIL::Selection &rhs) { if (rhs.complete_selection) { - lhs.full_selection = false; - lhs.complete_selection = false; - lhs.selected_modules.clear(); - lhs.selected_members.clear(); + lhs.clear(); return; } @@ -378,9 +371,7 @@ static void select_op_diff(RTLIL::Design *design, RTLIL::Selection &lhs, const R lhs.selected_members.erase(mod); } } else { - lhs.full_selection = false; - lhs.selected_modules.clear(); - lhs.selected_members.clear(); + lhs.clear(); } return; } @@ -435,10 +426,7 @@ static void select_op_intersect(RTLIL::Design *design, RTLIL::Selection &lhs, co return; if (rhs.empty()) { - lhs.full_selection = false; - lhs.complete_selection = false; - lhs.selected_modules.clear(); - lhs.selected_members.clear(); + lhs.clear(); return; } @@ -680,9 +668,7 @@ static void select_filter_active_mod(RTLIL::Design *design, RTLIL::Selection &se return; if (sel.full_selection) { - sel.full_selection = false; - sel.selected_modules.clear(); - sel.selected_members.clear(); + sel.clear(); sel.selected_modules.insert(design->selected_active_module); return; }