From 0f13b551731766214ba6bb839c2dbddfec0c7c8c Mon Sep 17 00:00:00 2001 From: Jannis Harder Date: Thu, 3 Apr 2025 13:11:48 +0200 Subject: [PATCH 1/2] Liberty file caching with new `libcache` command This adds optional in-memory caching of parsed liberty files to speed up flows that repeatedly parse the same liberty files. To avoid increasing the memory overhead by default, the caching is disabled by default. The caching can be controlled globally or on a per path basis using the new `libcache` command, which also allows purging cached data. --- frontends/liberty/liberty.cc | 2 +- passes/cmds/stat.cc | 2 +- passes/techmap/Makefile.inc | 1 + passes/techmap/clockgate.cc | 2 +- passes/techmap/dfflibmap.cc | 2 +- passes/techmap/libcache.cc | 130 +++++++++++++++++++++++++++++++++++ passes/techmap/libparse.cc | 25 +++++++ passes/techmap/libparse.h | 48 +++++++++---- tests/liberty/libcache.ys | 58 ++++++++++++++++ 9 files changed, 253 insertions(+), 17 deletions(-) create mode 100644 passes/techmap/libcache.cc create mode 100644 tests/liberty/libcache.ys diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc index cda13ff8b..3228f02fb 100644 --- a/frontends/liberty/liberty.cc +++ b/frontends/liberty/liberty.cc @@ -539,7 +539,7 @@ struct LibertyFrontend : public Frontend { log_header(design, "Executing Liberty frontend: %s\n", filename.c_str()); - LibertyParser parser(*f); + LibertyParser parser(*f, filename); int cell_count = 0; std::map> global_type_map; diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc index 7e51b6cb1..23583a8a8 100644 --- a/passes/cmds/stat.cc +++ b/passes/cmds/stat.cc @@ -352,7 +352,7 @@ void read_liberty_cellarea(dict &cell_area, string libert yosys_input_files.insert(liberty_file); if (f->fail()) log_cmd_error("Can't open liberty file `%s': %s\n", liberty_file.c_str(), strerror(errno)); - LibertyParser libparser(*f); + LibertyParser libparser(*f, liberty_file); delete f; for (auto cell : libparser.ast->children) diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index 4e1d16744..e6a910a0d 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -6,6 +6,7 @@ OBJS += passes/techmap/dfflibmap.o OBJS += passes/techmap/maccmap.o OBJS += passes/techmap/booth.o OBJS += passes/techmap/libparse.o +OBJS += passes/techmap/libcache.o ifeq ($(ENABLE_ABC),1) OBJS += passes/techmap/abc.o diff --git a/passes/techmap/clockgate.cc b/passes/techmap/clockgate.cc index 363f998db..b34ad1769 100644 --- a/passes/techmap/clockgate.cc +++ b/passes/techmap/clockgate.cc @@ -312,7 +312,7 @@ struct ClockgatePass : public Pass { std::istream* f = uncompressed(path); if (f->fail()) log_cmd_error("Can't open liberty file `%s': %s\n", path.c_str(), strerror(errno)); - LibertyParser p(*f); + LibertyParser p(*f, path); merged.merge(p); delete f; } diff --git a/passes/techmap/dfflibmap.cc b/passes/techmap/dfflibmap.cc index fe4f8aada..84db7f157 100644 --- a/passes/techmap/dfflibmap.cc +++ b/passes/techmap/dfflibmap.cc @@ -634,7 +634,7 @@ struct DfflibmapPass : public Pass { std::istream* f = uncompressed(path); if (f->fail()) log_cmd_error("Can't open liberty file `%s': %s\n", path.c_str(), strerror(errno)); - LibertyParser p(*f); + LibertyParser p(*f, path); merged.merge(p); delete f; } diff --git a/passes/techmap/libcache.cc b/passes/techmap/libcache.cc new file mode 100644 index 000000000..19f1fa87d --- /dev/null +++ b/passes/techmap/libcache.cc @@ -0,0 +1,130 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2025 Jannis Harder + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + + #include "kernel/yosys.h" + #include "passes/techmap/libparse.h" + + USING_YOSYS_NAMESPACE + PRIVATE_NAMESPACE_BEGIN + + struct LibcachePass : public Pass { + LibcachePass() : Pass("libcache", "control caching of technology library data parsed from liberty files") { } + void help() override + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" libcache {-enable|-disable|-purge} { -all | [path]... }\n"); + log("\n"); + log("Controls the default and per path caching of liberty file data.\n"); + log("\n"); + log(" -enable Enable caching.\n"); + log(" -disable Disable caching.\n"); + log(" -purge Reset cache setting and forget cached data.\n"); + log("\n"); + log("This mode takes a list of paths as argument. If no paths are provided, this\n"); + log("command does nothing. The -all option can be used to change the default cache\n"); + log("setting for -enable/-disable or to reset and forget about all paths.\n"); + log("\n"); + log("By default caching is disabled.\n"); + log("\n"); + log(" libcache -list\n"); + log("\n"); + log("Displays the current cache settings and cached paths.\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *) override + { + bool enable = false; + bool disable = false; + bool purge = false; + bool all = false; + bool list = false; + std::vector paths; + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + if (args[argidx] == "-enable") { + enable = true; + continue; + } + if (args[argidx] == "-disable") { + enable = true; + continue; + } + if (args[argidx] == "-purge") { + purge = true; + continue; + } + if (args[argidx] == "-all") { + all = true; + continue; + } + if (args[argidx] == "-list") { + list = true; + continue; + } + std::string fname = args[argidx]; + rewrite_filename(fname); + paths.push_back(fname); + break; + } + int modes = enable + disable + purge + list; + if (modes == 0) + log_cmd_error("At least one of -enable, -disable, -purge or -list is required.\n"); + if (modes > 1) + log_cmd_error("Only one of -enable, -disable, -purge or -list may be present.\n"); + + if (all && !paths.empty()) + log_cmd_error("The -all option cannot be combined with a list of paths.\n"); + if (list && (all || !paths.empty())) + log_cmd_error("The -list mode takes no further options.\n"); + if (!list && !all && paths.empty()) + log("No paths specified, use -all to %s\n", purge ? "purge all paths" : "change the default setting"); + + if (list) { + log("Caching is %s by default.\n", LibertyAstCache::instance.cache_by_default ? "enabled" : "disabled"); + for (auto const &entry : LibertyAstCache::instance.cache_path) + log("Caching is %s for `%s'.\n", entry.second ? "enabled" : "disabled", entry.first.c_str()); + for (auto const &entry : LibertyAstCache::instance.cached) + log("Data for `%s' is currently cached.\n", entry.first.c_str()); + } else if (enable || disable) { + if (all) { + LibertyAstCache::instance.cache_by_default = enable; + } else { + for (auto const &path : paths) { + LibertyAstCache::instance.cache_path[path] = enable; + } + } + } else if (purge) { + if (all) { + LibertyAstCache::instance.cached.clear(); + LibertyAstCache::instance.cache_path.clear(); + } else { + for (auto const &path : paths) { + LibertyAstCache::instance.cached.erase(path); + LibertyAstCache::instance.cache_path.erase(path); + } + } + } else { + log_assert(false); + } + } +} LibcachePass; + +PRIVATE_NAMESPACE_END diff --git a/passes/techmap/libparse.cc b/passes/techmap/libparse.cc index d3d5b7d57..d7a952603 100644 --- a/passes/techmap/libparse.cc +++ b/passes/techmap/libparse.cc @@ -32,6 +32,31 @@ using namespace Yosys; +#ifndef FILTERLIB + +LibertyAstCache LibertyAstCache::instance; + +std::shared_ptr LibertyAstCache::cached_ast(const std::string &fname) +{ + auto it = cached.find(fname); + if (it == cached.end()) + return nullptr; + log("Using cached data for liberty file `%s'\n", fname.c_str()); + return it->second; +} + +void LibertyAstCache::parsed_ast(const std::string &fname, const std::shared_ptr &ast) +{ + auto it = cache_path.find(fname); + bool should_cache = it == cache_path.end() ? cache_by_default : it->second; + if (!should_cache) + return; + log("Caching data for liberty file `%s'\n", fname.c_str()); + cached.emplace(fname, ast); +} + +#endif + bool LibertyInputStream::extend_buffer_once() { if (eof) diff --git a/passes/techmap/libparse.h b/passes/techmap/libparse.h index 1fcaaebee..9332afebd 100644 --- a/passes/techmap/libparse.h +++ b/passes/techmap/libparse.h @@ -132,6 +132,22 @@ namespace Yosys } }; +#ifndef FILTERLIB + class LibertyAstCache { + LibertyAstCache() {}; + ~LibertyAstCache() {}; + public: + dict> cached; + + bool cache_by_default = false; + dict cache_path; + + std::shared_ptr cached_ast(const std::string &fname); + void parsed_ast(const std::string &fname, const std::shared_ptr &ast); + static LibertyAstCache instance; + }; +#endif + class LibertyMergedCells; class LibertyParser { @@ -152,15 +168,29 @@ namespace Yosys void error(const std::string &str) const; public: - const LibertyAst *ast; + std::shared_ptr shared_ast; + const LibertyAst *ast = nullptr; - LibertyParser(std::istream &f) : f(f), line(1), ast(parse()) {} - ~LibertyParser() { if (ast) delete ast; } + LibertyParser(std::istream &f) : f(f), line(1) { + shared_ast.reset(parse()); + ast = shared_ast.get(); + } + +#ifndef FILTERLIB + LibertyParser(std::istream &f, const std::string &fname) : f(f), line(1) { + shared_ast = LibertyAstCache::instance.cached_ast(fname); + if (!shared_ast) { + shared_ast.reset(parse()); + LibertyAstCache::instance.parsed_ast(fname, shared_ast); + } + ast = shared_ast.get(); + } +#endif }; class LibertyMergedCells { - std::vector asts; + std::vector> asts; public: std::vector cells; @@ -168,10 +198,7 @@ namespace Yosys { if (parser.ast) { const LibertyAst *ast = parser.ast; - asts.push_back(ast); - // The parser no longer owns its top level ast, but we do. - // sketchy zone - parser.ast = nullptr; + asts.push_back(parser.shared_ast); if (ast->id != "library") parser.error("Top level entity isn't \"library\".\n"); for (const LibertyAst *cell : ast->children) @@ -179,11 +206,6 @@ namespace Yosys cells.push_back(cell); } } - ~LibertyMergedCells() - { - for (auto ast : asts) - delete ast; - } }; } diff --git a/tests/liberty/libcache.ys b/tests/liberty/libcache.ys new file mode 100644 index 000000000..a741a9df1 --- /dev/null +++ b/tests/liberty/libcache.ys @@ -0,0 +1,58 @@ +libcache -enable busdef.lib + +logger -expect log "Caching is disabled by default." 1 +logger -expect log "Caching is enabled for `busdef.lib'." 1 +libcache -list +logger -check-expected + +logger -expect log "Caching data" 1 +log Caching data +read_liberty normal.lib; design -reset +logger -check-expected + +logger -expect log "Caching data" 1 +read_liberty -lib busdef.lib; design -reset +logger -check-expected + +logger -expect log "Using caching data" 1 +log Using caching data +read_liberty normal.lib; design -reset +logger -check-expected + +logger -expect log "Using cached data" 1 +read_liberty -lib busdef.lib; design -reset +logger -check-expected + +libcache -purge busdef.lib + +logger -expect log "Caching is disabled by default." 1 +logger -expect log "Caching is enabled for `busdef.lib'." 1 +log Caching is enabled for `busdef.lib'. +libcache -list +logger -check-expected + +libcache -enable -all + +logger -expect log "Caching is enabled by default." 1 +libcache -list +logger -check-expected + +logger -expect log "Caching data" 1 +read_liberty normal.lib; design -reset +logger -check-expected + +logger -expect log "Caching data" 1 +read_liberty -lib busdef.lib; design -reset +logger -check-expected + +logger -expect log "Using cached data" 1 +read_liberty -lib busdef.lib; design -reset +logger -check-expected + +logger -expect log "Using cached data" 1 +read_liberty normal.lib; design -reset +logger -check-expected + +logger -expect log "Using cached data" 1 +dfflibmap -liberty normal.lib +logger -check-expected From d49364d96fac7d62b12243601534e9593e1bf3f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miodrag=20Milanovi=C4=87?= Date: Mon, 7 Apr 2025 12:11:55 +0200 Subject: [PATCH 2/2] Revert "Refactor full_selection" --- backends/firrtl/firrtl.cc | 5 +- 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 | 231 +++----------- kernel/rtlil.h | 208 ++----------- 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 | 289 ++++++++---------- passes/cmds/show.cc | 8 +- passes/cmds/stat.cc | 2 +- passes/cmds/viz.cc | 4 +- passes/hierarchy/submod.cc | 2 +- passes/opt/opt_clean.cc | 2 +- passes/sat/cutpoint.cc | 2 +- passes/sat/sim.cc | 4 +- passes/techmap/abc9.cc | 14 +- passes/techmap/abc9_ops.cc | 2 +- passes/techmap/abc_new.cc | 6 +- passes/techmap/aigmap.cc | 3 +- passes/techmap/clockgate.cc | 2 +- passes/techmap/nlutmap.cc | 2 +- tests/cxxrtl/run-test.sh | 2 +- tests/select/{boxes.v => blackboxes.ys} | 12 + 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 -- tests/select/boxes_stack.ys | 29 -- tests/simple_abc9/run-test.sh | 2 +- 38 files changed, 270 insertions(+), 707 deletions(-) rename tests/select/{boxes.v => blackboxes.ys} (51%) delete mode 100644 tests/select/boxes_equals_clean.ys delete mode 100644 tests/select/boxes_equals_name.ys delete mode 100644 tests/select/boxes_equals_operators.ys delete mode 100644 tests/select/boxes_equals_pattern.ys delete mode 100644 tests/select/boxes_equals_wildcard.ys delete mode 100644 tests/select/boxes_no_equals.ys delete mode 100644 tests/select/boxes_no_equals_clean.ys delete mode 100644 tests/select/boxes_stack.ys diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index ceb805dcb..eac0c9719 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -1215,6 +1215,9 @@ 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(); @@ -1227,7 +1230,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 = nullptr; + Module *top = design->top_module(); 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 ae60ee6c7..113f1a615 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 || module->is_selected_whole(); - bool print_body = !flag_n || !module->is_selected_whole(); + bool print_header = flag_m || design->selected_whole_module(module->name); + bool print_body = !flag_n || !design->selected_whole_module(module->name); if (print_header) { diff --git a/docs/source/code_examples/extensions/my_cmd.cc b/docs/source/code_examples/extensions/my_cmd.cc index e6660469c..36ddbe175 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().empty()) + if (design->selection_stack.back().empty()) log_cmd_error("This command can't operator on an empty selection!\n"); - RTLIL::Module *module = design->module("\\test"); + RTLIL::Module *module = design->modules_.at("\\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 d30dd2bae..b02c4cd99 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().empty()) + if (design->selection_stack.back().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 eb1326ce0..a3d85bd90 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()->pop_selection(); + yosys_get_design()->selection_stack.pop_back(); throw; } } diff --git a/kernel/register.cc b/kernel/register.cc index c52bfb5b8..fcb6ca769 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->pop_selection(); + design->selection_stack.pop_back(); } 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->push_selection(selection); + design->selection_stack.push_back(selection); Pass::call(design, command); - design->pop_selection(); + design->selection_stack.pop_back(); 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->push_selection(selection); + design->selection_stack.push_back(selection); Pass::call(design, args); - design->pop_selection(); + design->selection_stack.pop_back(); 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->push_empty_selection(); - design->select(module); + design->selection_stack.push_back(RTLIL::Selection(false)); + design->selection_stack.back().select(module); Pass::call(design, command); - design->pop_selection(); + design->selection_stack.pop_back(); 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->push_empty_selection(); - design->select(module); + design->selection_stack.push_back(RTLIL::Selection(false)); + design->selection_stack.back().select(module); Pass::call(design, args); - design->pop_selection(); + design->selection_stack.pop_back(); 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->pop_selection(); + design->selection_stack.pop_back(); } struct SimHelper { diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 637cc9be3..3b9a4a8b1 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -766,23 +766,8 @@ 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) @@ -794,10 +779,6 @@ 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) @@ -807,10 +788,6 @@ 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) @@ -823,17 +800,7 @@ 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) - complete_selection = true; - if (complete_selection) { - full_selection = false; - selects_boxes = true; - } - if (selects_all()) { + if (full_selection) { selected_modules.clear(); selected_members.clear(); return; @@ -843,7 +810,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 || (!selects_boxes && boxed_module(mod_name))) + if (design->modules_.count(mod_name) == 0) del_list.push_back(mod_name); selected_members.erase(mod_name); } @@ -852,7 +819,7 @@ void RTLIL::Selection::optimize(RTLIL::Design *design) del_list.clear(); for (auto &it : selected_members) - if (current_design->modules_.count(it.first) == 0 || (!selects_boxes && boxed_module(it.first))) + if (design->modules_.count(it.first) == 0) del_list.push_back(it.first); for (auto mod_name : del_list) selected_members.erase(mod_name); @@ -860,7 +827,7 @@ void RTLIL::Selection::optimize(RTLIL::Design *design) for (auto &it : selected_members) { del_list.clear(); for (auto memb_name : it.second) - if (current_design->modules_[it.first]->count_id(memb_name) == 0) + if (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); @@ -871,8 +838,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() == 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()) + 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()) add_list.push_back(it.first); for (auto mod_name : del_list) selected_members.erase(mod_name); @@ -881,24 +848,13 @@ void RTLIL::Selection::optimize(RTLIL::Design *design) selected_modules.insert(mod_name); } - if (selected_modules.size() == current_design->modules_.size()) { + if (selected_modules.size() == design->modules_.size()) { + full_selection = true; 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) { @@ -907,7 +863,7 @@ RTLIL::Design::Design() hashidx_ = hashidx_count; refcount_modules_ = 0; - push_full_selection(); + selection_stack.push_back(RTLIL::Selection()); #ifdef WITH_PYTHON RTLIL::Design::get_all_designs()->insert(std::pair(hashidx_, this)); @@ -952,7 +908,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() const +RTLIL::Module *RTLIL::Design::top_module() { RTLIL::Module *module = nullptr; int module_count = 0; @@ -1110,7 +1066,6 @@ 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); @@ -1134,21 +1089,27 @@ bool RTLIL::Design::selected_module(const RTLIL::IdString& mod_name) const { if (!selected_active_module.empty() && mod_name != selected_active_module) return false; - return selection().selected_module(mod_name); + if (selection_stack.size() == 0) + return true; + return selection_stack.back().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; - return selection().selected_whole_module(mod_name); + if (selection_stack.size() == 0) + return true; + return selection_stack.back().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; - return selection().selected_member(mod_name, memb_name); + if (selection_stack.size() == 0) + return true; + return selection_stack.back().selected_member(mod_name, memb_name); } bool RTLIL::Design::selected_module(RTLIL::Module *mod) const @@ -1161,86 +1122,37 @@ bool RTLIL::Design::selected_whole_module(RTLIL::Module *mod) const return selected_whole_module(mod->name); } -void RTLIL::Design::push_selection(RTLIL::Selection sel) +std::vector RTLIL::Design::selected_modules() const { - sel.current_design = this; - selection_stack.push_back(sel); -} - -void RTLIL::Design::push_empty_selection() -{ - push_selection(RTLIL::Selection::EmptySelection(this)); -} - -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 (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; - } - } + if (selected_module(it.first) && !it.second->get_blackbox_attribute()) + 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) && !it.second->get_blackbox_attribute()) + 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_) + 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)); return result; } @@ -2372,13 +2284,6 @@ 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) { @@ -2506,16 +2411,6 @@ 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; @@ -2536,40 +2431,6 @@ 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 52e7a17e7..f1bd96be7 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -56,33 +56,8 @@ 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; @@ -894,11 +869,6 @@ 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; @@ -1164,94 +1134,32 @@ 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; - // 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) { } + Selection(bool full = true) : full_selection(full) { } - // 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) { + if (!full_selection && 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 (!selects_all() && selected_modules.count(module->name) == 0) { + if (!full_selection && 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 !selects_all() && selected_modules.empty() && selected_members.empty(); + return !full_selection && 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 @@ -1305,7 +1213,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() const; + RTLIL::Module *top_module(); bool has(const RTLIL::IdString &id) const { return modules_.count(id) != 0; @@ -1332,118 +1240,57 @@ 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().full_selection; + return selection_stack.back().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); + if (selection_stack.size() > 0) { + RTLIL::Selection &sel = selection_stack.back(); + 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); + if (selection_stack.size() > 0) { + RTLIL::Selection &sel = selection_stack.back(); + sel.select(module, member); + } } - // 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); } + std::vector selected_modules() const; + std::vector selected_whole_modules() const; + std::vector selected_whole_modules_warn(bool include_wb = false) const; #ifdef WITH_PYTHON static std::map *get_all_designs(void); #endif }; -struct RTLIL::Module : public RTLIL::NamedObject +struct RTLIL::Module : public RTLIL::AttrObject { Hasher::hash_t hashidx_; [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; } @@ -1466,6 +1313,7 @@ public: std::vector connections_; std::vector bindings_; + RTLIL::IdString name; idict avail_parameters; dict parameter_default_values; dict memories; @@ -1510,14 +1358,8 @@ 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); @@ -1803,7 +1645,7 @@ namespace RTLIL_BACKEND { void dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire); } -struct RTLIL::Wire : public RTLIL::NamedObject +struct RTLIL::Wire : public RTLIL::AttrObject { Hasher::hash_t hashidx_; [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; } @@ -1826,6 +1668,7 @@ 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; @@ -1854,13 +1697,14 @@ inline int GetSize(RTLIL::Wire *wire) { return wire->width; } -struct RTLIL::Memory : public RTLIL::NamedObject +struct RTLIL::Memory : public RTLIL::AttrObject { 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(); @@ -1868,7 +1712,7 @@ struct RTLIL::Memory : public RTLIL::NamedObject #endif }; -struct RTLIL::Cell : public RTLIL::NamedObject +struct RTLIL::Cell : public RTLIL::AttrObject { Hasher::hash_t hashidx_; [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; } @@ -1885,6 +1729,7 @@ public: void operator=(RTLIL::Cell &other) = delete; RTLIL::Module *module; + RTLIL::IdString name; RTLIL::IdString type; dict connections_; dict parameters; @@ -1977,7 +1822,7 @@ struct RTLIL::SyncRule RTLIL::SyncRule *clone() const; }; -struct RTLIL::Process : public RTLIL::NamedObject +struct RTLIL::Process : public RTLIL::AttrObject { Hasher::hash_t hashidx_; [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; } @@ -1989,6 +1834,7 @@ 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 e970779d7..be39ca4a0 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->pop_selection(); + design->selection_stack.pop_back(); 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 9b0bc92ce..a5520e6ef 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->full_selection()) { + if (!design->selection_stack.empty() && !design->selection_stack.back().full_selection) { if (design->selected_active_module.empty()) str += "*"; - else if (design->selection().selected_modules.size() != 1 || design->selection().selected_members.size() != 0 || - design->selection().selected_modules.count(design->selected_active_module) == 0) + 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) 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->pop_selection(); + design->selection_stack.pop_back(); log_reset_stack(); } design->check(); diff --git a/passes/cmds/add.cc b/passes/cmds/add.cc index 833d6006d..c09517254 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 (!mod->is_selected_whole()) + if (!design->selected_whole_module(mod->name)) continue; if (mod->get_blackbox_attribute()) continue; diff --git a/passes/cmds/design.cc b/passes/cmds/design.cc index 910c9e366..168d38563 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(); - copy_from_design->pop_selection(); + sel = copy_from_design->selection_stack.back(); + copy_from_design->selection_stack.pop_back(); argidx = args.size(); } @@ -368,7 +368,7 @@ struct DesignPass : public Pass { design->selection_vars.clear(); design->selected_active_module.clear(); - design->push_full_selection(); + design->selection_stack.push_back(RTLIL::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 0f988e57a..197bd9319 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); - auto newSelection = RTLIL::Selection::EmptySelection(design); + RTLIL::Selection newSelection(false); int scc_counter = 0; for (auto mod : design->selected_modules()) diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc index 1d75091af..aec4c964b 100644 --- a/passes/cmds/select.cc +++ b/passes/cmds/select.cc @@ -141,42 +141,24 @@ 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.selects_all()) { - lhs.clear(); + if (lhs.full_selection) { + lhs.full_selection = false; + lhs.selected_modules.clear(); + lhs.selected_members.clear(); return; } if (lhs.selected_modules.size() == 0 && lhs.selected_members.size() == 0) { - if (lhs.selects_boxes) - lhs.complete_selection = true; - else - lhs.full_selection = true; + lhs.full_selection = true; return; } - auto new_sel = RTLIL::Selection::EmptySelection(); + RTLIL::Selection new_sel(false); 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)) { @@ -230,7 +212,7 @@ static void select_op_random(RTLIL::Design *design, RTLIL::Selection &lhs, int c } } - lhs = RTLIL::Selection(false, lhs.selects_boxes, design); + lhs = RTLIL::Selection(false); while (!objects.empty() && count-- > 0) { @@ -261,7 +243,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, lhs.selects_boxes, design); + RTLIL::Selection new_sel(false); for (auto mod : design->modules()) if (lhs.selected_module(mod->name)) for (auto cell : mod->cells()) @@ -272,7 +254,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, lhs.selects_boxes, design); + RTLIL::Selection new_sel(false); for (auto mod : design->modules()) for (auto cell : mod->cells()) if ((design->module(cell->type) != nullptr) && lhs.selected_whole_module(cell->type)) @@ -292,8 +274,6 @@ 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)) @@ -312,38 +292,18 @@ 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) +static void select_op_union(RTLIL::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) { - 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; - } + 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); @@ -356,30 +316,20 @@ 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.clear(); - return; - } - 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(); - } + lhs.full_selection = false; + lhs.selected_modules.clear(); + lhs.selected_members.clear(); return; } - if (rhs.empty() || lhs.empty()) - return; - - select_all(design, lhs); + 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); + } for (auto &it : rhs.selected_modules) { lhs.selected_modules.erase(it); @@ -416,46 +366,38 @@ 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) + if (rhs.full_selection) return; - if (rhs.full_selection && !lhs.selects_boxes) - return; - - if (lhs.empty()) - return; - - if (rhs.empty()) { - lhs.clear(); - return; + if (lhs.full_selection) { + lhs.full_selection = false; + for (auto mod : design->modules()) + lhs.selected_modules.insert(mod->name); } - select_all(design, lhs); - std::vector del_list; - 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 : 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 &it : del_list) lhs.selected_modules.erase(it); del_list.clear(); for (auto &it : lhs.selected_members) { - if (rhs.selected_whole_module(it.first)) + if (rhs.selected_modules.count(it.first) > 0) continue; - if (!rhs.selected_module(it.first)) { + if (rhs.selected_members.count(it.first) == 0) { del_list.push_back(it.first); continue; } std::vector del_list2; for (auto &it2 : it.second) - if (!rhs.selected_member(it.first, it2)) + if (rhs.selected_members.at(it.first).count(it2) == 0) del_list2.push_back(it2); for (auto &it2 : del_list2) it.second.erase(it2); @@ -668,7 +610,9 @@ static void select_filter_active_mod(RTLIL::Design *design, RTLIL::Selection &se return; if (sel.full_selection) { - sel.clear(); + sel.full_selection = false; + sel.selected_modules.clear(); + sel.selected_members.clear(); sel.selected_modules.insert(design->selected_active_module); return; } @@ -701,7 +645,8 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp if (arg[0] == '%') { if (arg == "%") { - work_stack.push_back(design->selection()); + if (design->selection_stack.size() > 0) + work_stack.push_back(design->selection_stack.back()); } else if (arg == "%%") { while (work_stack.size() > 1) { @@ -851,16 +796,15 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp } } - bool full_selection = (arg == "*" && arg_mod == "*"); - work_stack.push_back(RTLIL::Selection(full_selection, select_blackboxes, design)); + work_stack.push_back(RTLIL::Selection()); RTLIL::Selection &sel = work_stack.back(); - if (sel.full_selection) { - if (sel.selects_boxes) sel.optimize(design); + if (arg == "*" && arg_mod == "*" && select_blackboxes) { 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()) @@ -1001,33 +945,38 @@ 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) { - std::string selection_str = select_blackboxes ? "=" : ""; - selection_str += it.first; - log_warning("Selection \"%s\" did not match any module.\n", selection_str.c_str()); + log_warning("Selection \"%s\" did not match any module.\n", it.first.c_str()); } } for (auto &it : arg_memb_found) { if (it.second == false && !disable_empty_warning) { - std::string selection_str = select_blackboxes ? "=" : ""; - selection_str += it.first; - log_warning("Selection \"%s\" did not match any object.\n", selection_str.c_str()); + log_warning("Selection \"%s\" did not match any object.\n", it.first.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->all_selected_modules()) + for (auto mod : design->modules()) { - 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 (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 (push_selection) design->pop_selection(); return desc; } @@ -1052,9 +1001,9 @@ void handle_extra_select_args(Pass *pass, const vector &args, size_t arg work_stack.pop_back(); } if (work_stack.empty()) - design->push_empty_selection(); + design->selection_stack.push_back(RTLIL::Selection(false)); else - design->push_selection(work_stack.back()); + design->selection_stack.push_back(work_stack.back()); } // extern decl. in register.h @@ -1068,7 +1017,7 @@ RTLIL::Selection eval_select_args(const vector &args, RTLIL::Design *des work_stack.pop_back(); } if (work_stack.empty()) - return RTLIL::Selection::EmptySelection(design); + return RTLIL::Selection(false); return work_stack.back(); } @@ -1441,7 +1390,7 @@ struct SelectPass : public Pass { if (f.fail()) log_error("Can't open '%s' for reading: %s\n", read_file.c_str(), strerror(errno)); - auto sel = RTLIL::Selection::EmptySelection(design); + RTLIL::Selection sel(false); string line; while (std::getline(f, line)) { @@ -1482,7 +1431,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) { - auto sel = RTLIL::Selection::FullSelection(design); + RTLIL::Selection sel; select_filter_active_mod(design, sel); work_stack.push_back(sel); } @@ -1492,16 +1441,16 @@ struct SelectPass : public Pass { work_stack.pop_back(); } - log_assert(!design->selection_stack.empty()); + log_assert(design->selection_stack.size() > 0); if (clear_mode) { - design->selection() = RTLIL::Selection::FullSelection(design); + design->selection_stack.back() = RTLIL::Selection(true); design->selected_active_module = std::string(); return; } if (none_mode) { - design->selection() = RTLIL::Selection::EmptySelection(design); + design->selection_stack.back() = RTLIL::Selection(false); return; } @@ -1516,17 +1465,28 @@ 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) - design->push_selection(work_stack.back()); - RTLIL::Selection *sel = &design->selection(); + sel = &work_stack.back(); sel->optimize(design); - for (auto mod : design->all_selected_modules()) + for (auto mod : design->modules()) { if (sel->selected_whole_module(mod->name) && list_mode) log("%s\n", id2cstr(mod->name)); - if (!list_mod_mode) - for (auto it : mod->selected_members()) - LOG_OBJECT("%s/%s\n", id2cstr(mod->name), id2cstr(it->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 (count_mode) { @@ -1535,8 +1495,6 @@ struct SelectPass : public Pass { } if (f != nullptr) fclose(f); - if (work_stack.size() > 0) - design->pop_selection(); #undef LOG_OBJECT return; } @@ -1545,8 +1503,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(), work_stack.back()); - design->selection().optimize(design); + select_op_union(design, design->selection_stack.back(), work_stack.back()); + design->selection_stack.back().optimize(design); return; } @@ -1554,8 +1512,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(), work_stack.back()); - design->selection().optimize(design); + select_op_diff(design, design->selection_stack.back(), work_stack.back()); + design->selection_stack.back().optimize(design); return; } @@ -1595,13 +1553,23 @@ 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->all_selected_modules()) { - module_count++; - for ([[maybe_unused]] auto member_name : mod->selected_members()) - total_count++; - } + 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++; + } if (assert_modcount >= 0 && assert_modcount != module_count) { log_error("Assertion failed: selection contains %d modules instead of the asserted %d:%s\n", @@ -1625,14 +1593,13 @@ 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::EmptySelection(design); + design->selection_vars[set_name] = RTLIL::Selection(false); else design->selection_vars[set_name] = work_stack.back(); return; @@ -1646,7 +1613,7 @@ struct SelectPass : public Pass { } if (work_stack.size() == 0) { - RTLIL::Selection &sel = design->selection(); + RTLIL::Selection &sel = design->selection_stack.back(); if (sel.full_selection) log("*\n"); for (auto &it : sel.selected_modules) @@ -1657,8 +1624,8 @@ struct SelectPass : public Pass { return; } - design->selection() = work_stack.back(); - design->selection().optimize(design); + design->selection_stack.back() = work_stack.back(); + design->selection_stack.back().optimize(design); } } SelectPass; @@ -1698,8 +1665,7 @@ struct CdPass : public Pass { log_cmd_error("Invalid number of arguments.\n"); if (args.size() == 1 || args[1] == "/") { - design->pop_selection(); - design->push_full_selection(); + design->selection_stack.back() = RTLIL::Selection(true); design->selected_active_module = std::string(); return; } @@ -1708,8 +1674,7 @@ struct CdPass : public Pass { { string modname = design->selected_active_module; - design->pop_selection(); - design->push_full_selection(); + design->selection_stack.back() = RTLIL::Selection(true); design->selected_active_module = std::string(); while (1) @@ -1726,10 +1691,9 @@ struct CdPass : public Pass { continue; design->selected_active_module = modname; - design->pop_selection(); - design->push_full_selection(); - select_filter_active_mod(design, design->selection()); - design->selection().optimize(design); + design->selection_stack.back() = RTLIL::Selection(); + select_filter_active_mod(design, design->selection_stack.back()); + design->selection_stack.back().optimize(design); return; } @@ -1746,10 +1710,9 @@ struct CdPass : public Pass { if (design->module(modname) != nullptr) { design->selected_active_module = modname; - design->pop_selection(); - design->push_full_selection(); - select_filter_active_mod(design, design->selection()); - design->selection().optimize(design); + design->selection_stack.back() = RTLIL::Selection(); + select_filter_active_mod(design, design->selection_stack.back()); + design->selection_stack.back().optimize(design); return; } @@ -1796,7 +1759,7 @@ struct LsPass : public Pass { { std::vector matches; - for (auto mod : design->all_selected_modules()) + for (auto mod : design->selected_modules()) matches.push_back(mod->name); if (!matches.empty()) { diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc index 8a1bd58c4..82b5c6bcf 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(); - design->pop_selection(); + data.second = design->selection_stack.back(); + design->selection_stack.pop_back(); 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(); - design->pop_selection(); + data.second = design->selection_stack.back(); + design->selection_stack.pop_back(); label_selections.push_back(data); continue; } diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc index 7e25615bb..7e51b6cb1 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), mod->is_selected_whole() ? "" : " (partially selected)"); + log("=== %s%s ===\n", log_id(mod->name), design->selected_whole_module(mod->name) ? "" : " (partially selected)"); log("\n"); data.log_data(mod->name, false); } diff --git a/passes/cmds/viz.cc b/passes/cmds/viz.cc index 131e799ab..9dd68bd00 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()}); - design->pop_selection(); + config.groups.push_back({type, design->selection_stack.back()}); + design->selection_stack.pop_back(); 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 facc5d173..52fd59cf8 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 (!module->is_selected_whole() && opt_name.empty()) + if (!design->selected_whole_module(module->name) && opt_name.empty()) return; if (module->processes.size() > 0) { diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 620b38813..c37c03607 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_unboxed_whole_modules()) { + for (auto module : design->selected_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 263a3a4c8..88f995dda 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 (module->is_selected_whole()) { + if (design->selected_whole_module(module->name)) { 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 dd2f1d255..8fac93b98 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_unboxed_whole_modules(); + auto mods = design->selected_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_unboxed_whole_modules(); + auto mods = design->selected_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 fe5cc7af1..a96a82659 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -306,10 +306,9 @@ 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 -autoproc -wb -map %$abc9 -map +/techmap.v A:abc9_flop"); + run("techmap -wb -map %$abc9 -map +/techmap.v A:abc9_flop"); run("opt -nodffe -nosdff"); if (dff_mode || help_mode) { if (!help_mode) @@ -370,8 +369,6 @@ 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"); @@ -394,7 +391,7 @@ struct Abc9Pass : public ScriptPass } else { auto selected_modules = active_design->selected_modules(); - active_design->push_empty_selection(); + active_design->selection_stack.emplace_back(false); for (auto mod : selected_modules) { if (mod->processes.size() > 0) { @@ -403,9 +400,8 @@ struct Abc9Pass : public ScriptPass } log_push(); - active_design->select(mod); + active_design->selection().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)); @@ -456,7 +452,7 @@ struct Abc9Pass : public ScriptPass log_pop(); } - active_design->pop_selection(); + active_design->selection_stack.pop_back(); } } diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 6cb569b5a..4c7667a43 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::EmptySelection(design))); + auto r = design->selection_vars.insert(std::make_pair(ID($abc9_flops), RTLIL::Selection(false))); 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 dfa2e2f71..5be823916 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->push_empty_selection(); + active_design->selection_stack.emplace_back(false); } 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->select(mod); + active_design->selection().select(mod); } std::string script_save; @@ -194,7 +194,7 @@ struct AbcNewPass : public ScriptPass { } if (!help_mode) { - active_design->pop_selection(); + active_design->selection_stack.pop_back(); } } } diff --git a/passes/techmap/aigmap.cc b/passes/techmap/aigmap.cc index 19e568a61..4836ebe34 100644 --- a/passes/techmap/aigmap.cc +++ b/passes/techmap/aigmap.cc @@ -171,7 +171,8 @@ struct AigmapPass : public Pass { module->remove(cell); if (select_mode) { - RTLIL::Selection& sel = design->selection(); + log_assert(!design->selection_stack.empty()); + RTLIL::Selection& sel = design->selection_stack.back(); sel.selected_members[module->name] = std::move(new_sel); } diff --git a/passes/techmap/clockgate.cc b/passes/techmap/clockgate.cc index 6a12e2005..363f998db 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_unboxed_whole_modules()) { + for (auto module : design->selected_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 c823f10fe..016789157 100644 --- a/passes/techmap/nlutmap.cc +++ b/passes/techmap/nlutmap.cc @@ -42,7 +42,7 @@ struct NlutmapWorker RTLIL::Selection get_selection() { - auto sel = RTLIL::Selection::EmptySelection(module->design); + RTLIL::Selection sel(false); 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 ee299fc82..fd11a3783 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; select =*; proc; clean; write_cxxrtl cxxrtl-test-unconnected_output.cc" +../../yosys -p "read_verilog test_unconnected_output.v; 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/boxes.v b/tests/select/blackboxes.ys similarity index 51% rename from tests/select/boxes.v rename to tests/select/blackboxes.ys index 696b26523..9bfe92c6b 100644 --- a/tests/select/boxes.v +++ b/tests/select/blackboxes.ys @@ -1,3 +1,4 @@ +read_verilog -specify <