From bd16d01c0eed5c96a241e6ee9e56b8f7890319a1 Mon Sep 17 00:00:00 2001 From: Rupert Swarbrick Date: Tue, 19 Oct 2021 18:43:30 -0600 Subject: [PATCH] Split out logic for reprocessing an AstModule This will enable other features to use same core logic for replacing an existing AstModule with a newly elaborated version. --- frontends/ast/ast.cc | 67 +++++++++++++++++++++++------------ frontends/ast/ast.h | 14 +++++++- kernel/rtlil.cc | 4 +-- kernel/rtlil.h | 2 +- passes/hierarchy/hierarchy.cc | 2 +- 5 files changed, 61 insertions(+), 28 deletions(-) diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 4fbc238b0..fe1f9e861 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -983,8 +983,7 @@ static bool param_has_no_default(const AstNode *param) { (children.size() == 1 && children[0]->type == AST_RANGE); } -// create and add a new AstModule from an AST_MODULE AST node -static void process_module(RTLIL::Design *design, AstNode *ast, bool defer, AstNode *original_ast = NULL, bool quiet = false) +static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool defer, AstNode *original_ast = NULL, bool quiet = false) { log_assert(current_scope.empty()); log_assert(ast->type == AST_MODULE || ast->type == AST_INTERFACE); @@ -1197,6 +1196,42 @@ static void process_module(RTLIL::Design *design, AstNode *ast, bool defer, AstN } design->add(current_module); + return current_module; +} + +RTLIL::Module * +AST_INTERNAL::process_and_replace_module(RTLIL::Design *design, + RTLIL::Module *old_module, + AstNode *new_ast, + AstNode *original_ast) +{ + // The old module will be deleted. Rename and mark for deletion, using + // a static counter to make sure we get a unique name. + static unsigned counter; + std::ostringstream new_name; + new_name << old_module->name.str() + << "_before_process_and_replace_module_" + << counter; + ++counter; + + design->rename(old_module, new_name.str()); + old_module->set_bool_attribute(ID::to_delete); + + // Check if the module was the top module. If it was, we need to remove + // the top attribute and put it on the new module. + bool is_top = false; + if (old_module->get_bool_attribute(ID::initial_top)) { + old_module->attributes.erase(ID::initial_top); + is_top = true; + } + + // Generate RTLIL from AST for the new module and add to the design: + RTLIL::Module* new_module = process_module(design, new_ast, false, original_ast); + + if (is_top) + new_module->set_bool_attribute(ID::top); + + return new_module; } // renames identifiers in tasks and functions within a package @@ -1412,11 +1447,10 @@ void AST::explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule // When an interface instance is found in a module, the whole RTLIL for the module will be rederived again // from AST. The interface members are copied into the AST module with the prefix of the interface. -void AstModule::reprocess_module(RTLIL::Design *design, const dict &local_interfaces) +void AstModule::expand_interfaces(RTLIL::Design *design, const dict &local_interfaces) { loadconfig(); - bool is_top = false; AstNode *new_ast = ast->clone(); for (auto &intf : local_interfaces) { std::string intfname = intf.first.str(); @@ -1473,28 +1507,15 @@ void AstModule::reprocess_module(RTLIL::Design *design, const dictname.str(); - std::string changed_name = original_name + "_before_replacing_local_interfaces"; - design->rename(this, changed_name); - this->set_bool_attribute(ID::to_delete); + // Generate RTLIL from AST for the new module and add to the design, + // renaming this module to move it out of the way. + RTLIL::Module* new_module = + process_and_replace_module(design, this, new_ast, ast_before_replacing_interface_ports); - // Check if the module was the top module. If it was, we need to remove the top attribute and put it on the - // new module. - if (this->get_bool_attribute(ID::initial_top)) { - this->attributes.erase(ID::initial_top); - is_top = true; - } - - // Generate RTLIL from AST for the new module and add to the design: - process_module(design, new_ast, false, ast_before_replacing_interface_ports); - delete(new_ast); - RTLIL::Module* mod = design->module(original_name); - if (is_top) - mod->set_bool_attribute(ID::top); + delete new_ast; // Set the attribute "interfaces_replaced_in_module" so that it does not happen again. - mod->set_bool_attribute(ID::interfaces_replaced_in_module); + new_module->set_bool_attribute(ID::interfaces_replaced_in_module); } // create a new parametric module (when needed) and return the name of the generated module - WITH support for interfaces diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 63104bca4..66bbdd7b4 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -348,7 +348,7 @@ namespace AST RTLIL::IdString derive(RTLIL::Design *design, const dict ¶meters, bool mayfail) override; RTLIL::IdString derive(RTLIL::Design *design, const dict ¶meters, const dict &interfaces, const dict &modports, bool mayfail) override; std::string derive_common(RTLIL::Design *design, const dict ¶meters, AstNode **new_ast_out, bool quiet = false); - void reprocess_module(RTLIL::Design *design, const dict &local_interfaces) override; + void expand_interfaces(RTLIL::Design *design, const dict &local_interfaces) override; RTLIL::Module *clone() const override; void loadconfig() const; }; @@ -395,6 +395,18 @@ namespace AST_INTERNAL extern dict> current_memwr_visible; struct LookaheadRewriter; struct ProcessGenerator; + + // Create and add a new AstModule from new_ast, then use it to replace + // old_module in design, renaming old_module to move it out of the way. + // Return the new module. + // + // If original_ast is not null, it will be used as the AST node for the + // new module. Otherwise, new_ast will be used. + RTLIL::Module * + process_and_replace_module(RTLIL::Design *design, + RTLIL::Module *old_module, + AST::AstNode *new_ast, + AST::AstNode *original_ast = nullptr); } YOSYS_NAMESPACE_END diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 3778972bc..9fac57523 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -936,9 +936,9 @@ void RTLIL::Module::makeblackbox() set_bool_attribute(ID::blackbox); } -void RTLIL::Module::reprocess_module(RTLIL::Design *, const dict &) +void RTLIL::Module::expand_interfaces(RTLIL::Design *, const dict &) { - log_error("Cannot reprocess_module module `%s' !\n", id2cstr(name)); + log_error("Class doesn't support expand_interfaces (module: `%s')!\n", id2cstr(name)); } RTLIL::IdString RTLIL::Module::derive(RTLIL::Design*, const dict &, bool mayfail) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 96982d2d9..c428f3154 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1160,7 +1160,7 @@ public: virtual RTLIL::IdString derive(RTLIL::Design *design, const dict ¶meters, bool mayfail = false); virtual RTLIL::IdString derive(RTLIL::Design *design, const dict ¶meters, const dict &interfaces, const dict &modports, bool mayfail = false); virtual size_t count_id(RTLIL::IdString id); - virtual void reprocess_module(RTLIL::Design *design, const dict &local_interfaces); + virtual void expand_interfaces(RTLIL::Design *design, const dict &local_interfaces); virtual void sort(); virtual void check(); diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 650036580..1e69ab903 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -554,7 +554,7 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check // If any interface instances or interface ports were found in the module, we need to rederive it completely: if ((if_expander.interfaces_in_module.size() > 0 || has_interface_ports) && !module->get_bool_attribute(ID::interfaces_replaced_in_module)) { - module->reprocess_module(design, if_expander.interfaces_in_module); + module->expand_interfaces(design, if_expander.interfaces_in_module); return did_something; } -- 2.30.2