From 9cd4b4e72d8934d7c087878446cf48da6abe972c Mon Sep 17 00:00:00 2001 From: Catherine Date: Thu, 21 Dec 2023 00:34:55 +0000 Subject: [PATCH] kernel: call `hierarchy` for abstract modules automatically. Whenever there are abstract modules in the netlist and the pass does not declare that it supports them, call `hierarchy -auto-top` or `hierarchy` (depending on whether there is a module marked `top`) to instantiate them first. This makes several CLI workflows much more usable, including one as basic as: $ yosys file.v -o file.il --- kernel/register.cc | 17 +++++++++++++++++ kernel/register.h | 7 ++++++- passes/cmds/blackbox.cc | 2 +- passes/cmds/design.cc | 2 +- passes/cmds/exec.cc | 2 +- passes/cmds/logcmd.cc | 2 +- passes/cmds/logger.cc | 10 +++++----- passes/cmds/plugin.cc | 2 +- passes/cmds/scratchpad.cc | 2 +- passes/cmds/setattr.cc | 6 +++--- passes/cmds/tee.cc | 2 +- passes/cmds/trace.cc | 2 +- passes/hierarchy/hierarchy.cc | 2 +- 13 files changed, 40 insertions(+), 18 deletions(-) diff --git a/kernel/register.cc b/kernel/register.cc index 9ffb17c1a..247f7f2e2 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -151,6 +151,22 @@ Pass::~Pass() Pass::pre_post_exec_state_t Pass::pre_execute() { + if (!abstract_modules_ok) { + bool has_top = false; + bool has_abstract = false; + for (auto mod : yosys_design->modules()) { + if (mod->get_bool_attribute(ID::top)) + has_top = true; + if (mod->name.begins_with("$abstract")) + has_abstract = true; + } + if (has_abstract) { + std::string command = has_top ? "hierarchy" : "hierarchy -auto-top"; + log_warning("Pass `%s` does not accept abstract modules; running `%s` first!\n", pass_name.c_str(), command.c_str()); + run_pass(command); + } + } + pre_post_exec_state_t state; call_counter++; state.begin_ns = PerformanceTimer::query(); @@ -443,6 +459,7 @@ Frontend::Frontend(std::string name, std::string short_help) : Pass(name.rfind("=", 0) == 0 ? name.substr(1) : "read_" + name, short_help), frontend_name(name.rfind("=", 0) == 0 ? name.substr(1) : name) { + abstract_modules_ok = true; } void Frontend::run_register() diff --git a/kernel/register.h b/kernel/register.h index 15750af2a..77414d183 100644 --- a/kernel/register.h +++ b/kernel/register.h @@ -37,6 +37,7 @@ struct Pass int call_counter; int64_t runtime_ns; bool experimental_flag = false; + bool abstract_modules_ok = false; void experimental() { experimental_flag = true; @@ -78,7 +79,11 @@ struct ScriptPass : Pass RTLIL::Design *active_design; std::string active_run_from, active_run_to; - ScriptPass(std::string name, std::string short_help = "** document me **") : Pass(name, short_help) { } + ScriptPass(std::string name, std::string short_help = "** document me **") : Pass(name, short_help) { + // Either the script pass will include an explicit `hierarchy` invocation or one of the passes called inside will + // trigger the check for abstract modules. + abstract_modules_ok = true; + } virtual void script() = 0; diff --git a/passes/cmds/blackbox.cc b/passes/cmds/blackbox.cc index 43670efaf..9a144fbd3 100644 --- a/passes/cmds/blackbox.cc +++ b/passes/cmds/blackbox.cc @@ -23,7 +23,7 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN struct BlackboxPass : public Pass { - BlackboxPass() : Pass("blackbox", "convert modules into blackbox modules") { } + BlackboxPass() : Pass("blackbox", "convert modules into blackbox modules") { abstract_modules_ok = true; } void help() override { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| diff --git a/passes/cmds/design.cc b/passes/cmds/design.cc index 168d38563..bf51f89a9 100644 --- a/passes/cmds/design.cc +++ b/passes/cmds/design.cc @@ -27,7 +27,7 @@ std::map saved_designs; std::vector pushed_designs; struct DesignPass : public Pass { - DesignPass() : Pass("design", "save, restore and reset current design") { } + DesignPass() : Pass("design", "save, restore and reset current design") { abstract_modules_ok = true; } ~DesignPass() override { for (auto &it : saved_designs) delete it.second; diff --git a/passes/cmds/exec.cc b/passes/cmds/exec.cc index e5fa4fb41..27c0ae511 100644 --- a/passes/cmds/exec.cc +++ b/passes/cmds/exec.cc @@ -37,7 +37,7 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN struct ExecPass : public Pass { - ExecPass() : Pass("exec", "execute commands in the operating system shell") { } + ExecPass() : Pass("exec", "execute commands in the operating system shell") { abstract_modules_ok = true; } void help() override { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| diff --git a/passes/cmds/logcmd.cc b/passes/cmds/logcmd.cc index 20cbd8943..b5733e89c 100644 --- a/passes/cmds/logcmd.cc +++ b/passes/cmds/logcmd.cc @@ -26,7 +26,7 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN struct LogPass : public Pass { - LogPass() : Pass("log", "print text and log files") { } + LogPass() : Pass("log", "print text and log files") { abstract_modules_ok = true; } void help() override { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| diff --git a/passes/cmds/logger.cc b/passes/cmds/logger.cc index 9e45e86af..e0543f5f8 100644 --- a/passes/cmds/logger.cc +++ b/passes/cmds/logger.cc @@ -24,7 +24,7 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN struct LoggerPass : public Pass { - LoggerPass() : Pass("logger", "set logger properties") { } + LoggerPass() : Pass("logger", "set logger properties") { abstract_modules_ok = true; } void help() override { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| @@ -99,7 +99,7 @@ struct LoggerPass : public Pass { } if (args[argidx] == "-warn" && argidx+1 < args.size()) { std::string pattern = args[++argidx]; - if (pattern.front() == '\"' && pattern.back() == '\"') pattern = pattern.substr(1, pattern.size() - 2); + if (pattern.front() == '\"' && pattern.back() == '\"') pattern = pattern.substr(1, pattern.size() - 2); try { log("Added regex '%s' for warnings to warn list.\n", pattern.c_str()); log_warn_regexes.push_back(YS_REGEX_COMPILE(pattern)); @@ -111,7 +111,7 @@ struct LoggerPass : public Pass { } if (args[argidx] == "-nowarn" && argidx+1 < args.size()) { std::string pattern = args[++argidx]; - if (pattern.front() == '\"' && pattern.back() == '\"') pattern = pattern.substr(1, pattern.size() - 2); + if (pattern.front() == '\"' && pattern.back() == '\"') pattern = pattern.substr(1, pattern.size() - 2); try { log("Added regex '%s' for warnings to nowarn list.\n", pattern.c_str()); log_nowarn_regexes.push_back(YS_REGEX_COMPILE(pattern)); @@ -123,7 +123,7 @@ struct LoggerPass : public Pass { } if (args[argidx] == "-werror" && argidx+1 < args.size()) { std::string pattern = args[++argidx]; - if (pattern.front() == '\"' && pattern.back() == '\"') pattern = pattern.substr(1, pattern.size() - 2); + if (pattern.front() == '\"' && pattern.back() == '\"') pattern = pattern.substr(1, pattern.size() - 2); try { log("Added regex '%s' for warnings to werror list.\n", pattern.c_str()); log_werror_regexes.push_back(YS_REGEX_COMPILE(pattern)); @@ -156,7 +156,7 @@ struct LoggerPass : public Pass { if (type=="error" && log_expect_error.size()>0) log_cmd_error("Only single error message can be expected !\n"); std::string pattern = args[++argidx]; - if (pattern.front() == '\"' && pattern.back() == '\"') pattern = pattern.substr(1, pattern.size() - 2); + if (pattern.front() == '\"' && pattern.back() == '\"') pattern = pattern.substr(1, pattern.size() - 2); int count = atoi(args[++argidx].c_str()); if (count<=0) log_cmd_error("Number of expected messages must be higher then 0 !\n"); diff --git a/passes/cmds/plugin.cc b/passes/cmds/plugin.cc index 08b4aa8c4..0c1f6a6e8 100644 --- a/passes/cmds/plugin.cc +++ b/passes/cmds/plugin.cc @@ -122,7 +122,7 @@ void load_plugin(std::string, std::vector) #endif struct PluginPass : public Pass { - PluginPass() : Pass("plugin", "load and list loaded plugins") { } + PluginPass() : Pass("plugin", "load and list loaded plugins") { abstract_modules_ok = true; } void help() override { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| diff --git a/passes/cmds/scratchpad.cc b/passes/cmds/scratchpad.cc index aecc4c17d..259cef683 100644 --- a/passes/cmds/scratchpad.cc +++ b/passes/cmds/scratchpad.cc @@ -26,7 +26,7 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN struct ScratchpadPass : public Pass { - ScratchpadPass() : Pass("scratchpad", "get/set values in the scratchpad") { } + ScratchpadPass() : Pass("scratchpad", "get/set values in the scratchpad") { abstract_modules_ok = true; } void help() override { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| diff --git a/passes/cmds/setattr.cc b/passes/cmds/setattr.cc index 710fa9ab4..205303701 100644 --- a/passes/cmds/setattr.cc +++ b/passes/cmds/setattr.cc @@ -127,7 +127,7 @@ struct SetattrPass : public Pass { } SetattrPass; struct WbflipPass : public Pass { - WbflipPass() : Pass("wbflip", "flip the whitebox attribute") { } + WbflipPass() : Pass("wbflip", "flip the whitebox attribute") { abstract_modules_ok = true; } void help() override { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| @@ -166,7 +166,7 @@ struct WbflipPass : public Pass { } WbflipPass; struct SetparamPass : public Pass { - SetparamPass() : Pass("setparam", "set/unset parameters on objects") { } + SetparamPass() : Pass("setparam", "set/unset parameters on objects") { abstract_modules_ok = true; } void help() override { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| @@ -218,7 +218,7 @@ struct SetparamPass : public Pass { } SetparamPass; struct ChparamPass : public Pass { - ChparamPass() : Pass("chparam", "re-evaluate modules with new parameters") { } + ChparamPass() : Pass("chparam", "re-evaluate modules with new parameters") { abstract_modules_ok = true; } void help() override { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| diff --git a/passes/cmds/tee.cc b/passes/cmds/tee.cc index 39ed4a7a8..61d30f280 100644 --- a/passes/cmds/tee.cc +++ b/passes/cmds/tee.cc @@ -26,7 +26,7 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN struct TeePass : public Pass { - TeePass() : Pass("tee", "redirect command output to file") { } + TeePass() : Pass("tee", "redirect command output to file") { abstract_modules_ok = true; } void help() override { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| diff --git a/passes/cmds/trace.cc b/passes/cmds/trace.cc index 400542776..80d254401 100644 --- a/passes/cmds/trace.cc +++ b/passes/cmds/trace.cc @@ -59,7 +59,7 @@ struct TraceMonitor : public RTLIL::Monitor }; struct TracePass : public Pass { - TracePass() : Pass("trace", "redirect command output to file") { } + TracePass() : Pass("trace", "redirect command output to file") { abstract_modules_ok = true; } void help() override { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index bf0137503..e93b12ca3 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -716,7 +716,7 @@ RTLIL::Wire *find_implicit_port_wire(Module *module, Cell *cell, const std::stri } struct HierarchyPass : public Pass { - HierarchyPass() : Pass("hierarchy", "check, expand and clean up design hierarchy") { } + HierarchyPass() : Pass("hierarchy", "check, expand and clean up design hierarchy") { abstract_modules_ok = true; } void help() override { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|