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()) { 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 fcb6ca769..c52bfb5b8 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -260,18 +260,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; } @@ -279,11 +279,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; } @@ -291,12 +291,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; } @@ -304,12 +304,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; } @@ -651,7 +651,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 3b9a4a8b1..637cc9be3 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -766,8 +766,23 @@ 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 (complete_selection) + return true; + if (!selects_boxes && boxed_module(mod_name)) + return false; if (full_selection) return true; if (selected_modules.count(mod_name) > 0) @@ -779,6 +794,10 @@ 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) return true; if (selected_modules.count(mod_name) > 0) @@ -788,6 +807,10 @@ 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) return true; if (selected_modules.count(mod_name) > 0) @@ -800,7 +823,17 @@ bool RTLIL::Selection::selected_member(const RTLIL::IdString &mod_name, const RT void RTLIL::Selection::optimize(RTLIL::Design *design) { - if (full_selection) { + if (design != current_design) { + current_design = design; + } + + if (selects_boxes && full_selection) + complete_selection = true; + if (complete_selection) { + full_selection = false; + selects_boxes = true; + } + if (selects_all()) { selected_modules.clear(); selected_members.clear(); return; @@ -810,7 +843,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 || (!selects_boxes && boxed_module(mod_name))) del_list.push_back(mod_name); selected_members.erase(mod_name); } @@ -819,7 +852,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 || (!selects_boxes && boxed_module(it.first))) del_list.push_back(it.first); for (auto mod_name : del_list) selected_members.erase(mod_name); @@ -827,7 +860,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 +871,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,13 +881,24 @@ void RTLIL::Selection::optimize(RTLIL::Design *design) selected_modules.insert(mod_name); } - if (selected_modules.size() == 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; } } +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) { @@ -863,7 +907,7 @@ RTLIL::Design::Design() hashidx_ = hashidx_count; refcount_modules_ = 0; - selection_stack.push_back(RTLIL::Selection()); + push_full_selection(); #ifdef WITH_PYTHON RTLIL::Design::get_all_designs()->insert(std::pair(hashidx_, this)); @@ -908,7 +952,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; @@ -1066,6 +1110,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); @@ -1089,27 +1134,21 @@ 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_stack.back().selected_module(mod_name); + return selection().selected_module(mod_name); } 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_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 { if (!selected_active_module.empty() && mod_name != selected_active_module) 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 @@ -1122,37 +1161,86 @@ bool RTLIL::Design::selected_whole_module(RTLIL::Module *mod) const return selected_whole_module(mod->name); } -std::vector RTLIL::Design::selected_modules() const +void RTLIL::Design::push_selection(RTLIL::Selection sel) { - std::vector result; - result.reserve(modules_.size()); - for (auto &it : modules_) - if (selected_module(it.first) && !it.second->get_blackbox_attribute()) - result.push_back(it.second); - return result; + sel.current_design = this; + selection_stack.push_back(sel); } -std::vector RTLIL::Design::selected_whole_modules() const +void RTLIL::Design::push_empty_selection() { - std::vector result; - result.reserve(modules_.size()); - for (auto &it : modules_) - if (selected_whole_module(it.first) && !it.second->get_blackbox_attribute()) - result.push_back(it.second); - return result; + push_selection(RTLIL::Selection::EmptySelection(this)); } -std::vector RTLIL::Design::selected_whole_modules_warn(bool include_wb) const +void RTLIL::Design::push_full_selection() { + push_selection(RTLIL::Selection::FullSelection(this)); +} + +void RTLIL::Design::push_complete_selection() +{ + push_selection(RTLIL::Selection::CompleteSelection(this)); +} + +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 +{ + 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 (it.second->get_blackbox_attribute(include_wb)) - continue; - else 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; } @@ -2284,6 +2372,13 @@ 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) { + // 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()); + } } for (auto &it : processes) { @@ -2411,6 +2506,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; @@ -2431,6 +2536,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..52e7a17e7 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -56,8 +56,33 @@ 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; struct Selection; struct Monitor; struct Design; @@ -869,6 +894,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; @@ -1134,32 +1164,94 @@ public: struct RTLIL::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) : full_selection(full) { } + // 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 (!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); + if (module->get_blackbox_attribute()) + selects_boxes = true; } } + // add member of module to this selection 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); + if (module->get_blackbox_attribute()) + selects_boxes = true; + } } + // checks if selection is empty bool empty() const { - return !full_selection && selected_modules.empty() && selected_members.empty(); + 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); }; + + // 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); }; }; struct RTLIL::Monitor @@ -1213,7 +1305,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; @@ -1240,57 +1332,118 @@ 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(); + // 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_stack.back().full_selection; + 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) { - if (selection_stack.size() > 0) { - RTLIL::Selection &sel = selection_stack.back(); - sel.select(module); - } + RTLIL::Selection &sel = selection(); + sel.select(module); } + // add member of module to the current selection template void select(T1 *module, T2 *member) { - if (selection_stack.size() > 0) { - RTLIL::Selection &sel = selection_stack.back(); - sel.select(module, member); - } + RTLIL::Selection &sel = selection(); + sel.select(module, member); } - std::vector selected_modules() const; - std::vector selected_whole_modules() const; - std::vector selected_whole_modules_warn(bool include_wb = false) 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); } + // 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); #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 +1466,6 @@ public: std::vector connections_; std::vector bindings_; - RTLIL::IdString name; idict avail_parameters; dict parameter_default_values; dict memories; @@ -1358,8 +1510,14 @@ 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; + 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 +1803,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 +1826,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 +1854,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 +1868,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 +1885,6 @@ public: void operator=(RTLIL::Cell &other) = delete; RTLIL::Module *module; - RTLIL::IdString name; RTLIL::IdString type; dict connections_; dict parameters; @@ -1822,7 +1977,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 +1989,6 @@ protected: ~Process(); public: - RTLIL::IdString name; RTLIL::Module *module; RTLIL::CaseRule root_case; std::vector syncs; 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 a5520e6ef..9b0bc92ce 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -312,11 +312,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->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()); @@ -979,7 +979,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..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); + 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 aec4c964b..1d75091af 100644 --- a/passes/cmds/select.cc +++ b/passes/cmds/select.cc @@ -141,24 +141,42 @@ static bool match_attr(const dict &attributes, co return match_attr(attributes, match_expr, std::string(), 0); } +static void select_all(RTLIL::Design *design, RTLIL::Selection &lhs) +{ + if (!lhs.selects_all()) + return; + lhs.current_design = design; + lhs.selected_modules.clear(); + for (auto mod : design->modules()) { + 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) { - lhs.full_selection = false; - lhs.selected_modules.clear(); - lhs.selected_members.clear(); + if (lhs.selects_all()) { + lhs.clear(); return; } if (lhs.selected_modules.size() == 0 && lhs.selected_members.size() == 0) { - lhs.full_selection = true; + 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()) { + 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 +230,7 @@ static void select_op_random(RTLIL::Design *design, RTLIL::Selection &lhs, int c } } - lhs = RTLIL::Selection(false); + lhs = RTLIL::Selection(false, lhs.selects_boxes, design); while (!objects.empty() && count-- > 0) { @@ -243,7 +261,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 +272,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 +292,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 +312,38 @@ 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.full_selection) { - lhs.full_selection = true; - lhs.selected_modules.clear(); - lhs.selected_members.clear(); + if (lhs.complete_selection) + return; + else if (rhs.complete_selection) { + lhs.complete_selection = true; + lhs.optimize(design); return; } - if (lhs.full_selection) + if (rhs.selects_boxes) { + if (lhs.full_selection) { + select_all(design, lhs); + } + lhs.selects_boxes = true; + } + else if (lhs.full_selection) return; + if (rhs.full_selection) { + if (lhs.selects_boxes) { + auto new_rhs = RTLIL::Selection(rhs); + select_all(design, new_rhs); + for (auto mod : new_rhs.selected_modules) + lhs.selected_modules.insert(mod); + } else { + lhs.clear(); + lhs.full_selection = true; + } + return; + } + for (auto &it : rhs.selected_members) for (auto &it2 : it.second) lhs.selected_members[it.first].insert(it2); @@ -316,21 +356,31 @@ 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 (rhs.complete_selection) { + lhs.clear(); return; } - if (lhs.full_selection) { - if (!rhs.full_selection && rhs.selected_modules.size() == 0 && rhs.selected_members.size() == 0) - return; - lhs.full_selection = false; - for (auto mod : design->modules()) - lhs.selected_modules.insert(mod->name); + if (rhs.full_selection) { + if (lhs.selects_boxes) { + auto new_rhs = RTLIL::Selection(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); + } + } else { + lhs.clear(); + } + return; } + if (rhs.empty() || lhs.empty()) + return; + + select_all(design, lhs); + for (auto &it : rhs.selected_modules) { lhs.selected_modules.erase(it); lhs.selected_members.erase(it); @@ -366,38 +416,46 @@ 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.complete_selection) return; - if (lhs.full_selection) { - lhs.full_selection = false; - for (auto mod : design->modules()) - lhs.selected_modules.insert(mod->name); + if (rhs.full_selection && !lhs.selects_boxes) + return; + + if (lhs.empty()) + return; + + if (rhs.empty()) { + lhs.clear(); + return; } + select_all(design, lhs); + 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); @@ -610,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; } @@ -645,8 +701,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) { @@ -796,15 +851,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()) @@ -945,38 +1001,33 @@ 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()); } } } 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->modules()) + for (auto mod : design->all_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)); } + if (push_selection) design->pop_selection(); return desc; } @@ -1001,9 +1052,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)); + design->push_empty_selection(); else - design->selection_stack.push_back(work_stack.back()); + design->push_selection(work_stack.back()); } // extern decl. in register.h @@ -1017,7 +1068,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::EmptySelection(design); return work_stack.back(); } @@ -1390,7 +1441,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); + auto sel = RTLIL::Selection::EmptySelection(design); string line; while (std::getline(f, line)) { @@ -1431,7 +1482,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; + auto sel = RTLIL::Selection::FullSelection(design); select_filter_active_mod(design, sel); work_stack.push_back(sel); } @@ -1441,16 +1492,16 @@ 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->selection_stack.back() = RTLIL::Selection(true); + design->selection() = RTLIL::Selection::FullSelection(design); design->selected_active_module = std::string(); return; } if (none_mode) { - design->selection_stack.back() = RTLIL::Selection(false); + design->selection() = RTLIL::Selection::EmptySelection(design); return; } @@ -1465,28 +1516,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->push_selection(work_stack.back()); + RTLIL::Selection *sel = &design->selection(); sel->optimize(design); - for (auto mod : design->modules()) + for (auto mod : design->all_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 +1535,8 @@ struct SelectPass : public Pass { } if (f != nullptr) fclose(f); + if (work_stack.size() > 0) + design->pop_selection(); #undef LOG_OBJECT return; } @@ -1503,8 +1545,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; } @@ -1512,8 +1554,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; } @@ -1553,23 +1595,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->push_selection(*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->all_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 +1625,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->pop_selection(); 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::EmptySelection(design); else design->selection_vars[set_name] = work_stack.back(); return; @@ -1613,7 +1646,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) @@ -1624,8 +1657,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; @@ -1665,7 +1698,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); + design->pop_selection(); + design->push_full_selection(); design->selected_active_module = std::string(); return; } @@ -1674,7 +1708,8 @@ struct CdPass : public Pass { { string modname = design->selected_active_module; - design->selection_stack.back() = RTLIL::Selection(true); + design->pop_selection(); + design->push_full_selection(); design->selected_active_module = std::string(); while (1) @@ -1691,9 +1726,10 @@ struct CdPass : public Pass { continue; design->selected_active_module = modname; - design->selection_stack.back() = RTLIL::Selection(); - 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; } @@ -1710,9 +1746,10 @@ struct CdPass : public Pass { if (design->module(modname) != nullptr) { design->selected_active_module = modname; - design->selection_stack.back() = RTLIL::Selection(); - 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; } @@ -1759,7 +1796,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()) { 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 7e51b6cb1..7e25615bb 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/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/cutpoint.cc b/passes/sat/cutpoint.cc index 88f995dda..263a3a4c8 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/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/abc9.cc b/passes/techmap/abc9.cc index a96a82659..fe5cc7af1 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -306,9 +306,10 @@ struct Abc9Pass : public ScriptPass } run("design -stash $abc9"); run("design -load $abc9_map"); - run("proc"); + if (help_mode) run("select =*"); + else active_design->push_complete_selection(); 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) @@ -369,6 +370,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"); @@ -391,7 +394,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) { @@ -400,8 +403,9 @@ struct Abc9Pass : public ScriptPass } log_push(); - active_design->selection().select(mod); + 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)); @@ -452,7 +456,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..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))); + 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/abc_new.cc b/passes/techmap/abc_new.cc index 5be823916..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"); @@ -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..19e568a61 100644 --- a/passes/techmap/aigmap.cc +++ b/passes/techmap/aigmap.cc @@ -171,8 +171,7 @@ struct AigmapPass : public Pass { module->remove(cell); 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/clockgate.cc b/passes/techmap/clockgate.cc index 363f998db..6a12e2005 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; diff --git a/passes/techmap/nlutmap.cc b/passes/techmap/nlutmap.cc index 016789157..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); + auto sel = RTLIL::Selection::EmptySelection(module->design); for (auto cell : module->cells()) if (!mapped_cells.count(cell)) sel.select(module, cell); 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/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 <