Split out logic for reprocessing an AstModule
authorRupert Swarbrick <rswarbrick@gmail.com>
Wed, 20 Oct 2021 00:43:30 +0000 (18:43 -0600)
committerZachary Snow <zachary.j.snow@gmail.com>
Tue, 26 Oct 2021 01:25:50 +0000 (18:25 -0700)
This will enable other features to use same core logic for replacing an
existing AstModule with a newly elaborated version.

frontends/ast/ast.cc
frontends/ast/ast.h
kernel/rtlil.cc
kernel/rtlil.h
passes/hierarchy/hierarchy.cc

index 4fbc238b02db8b28ee2e28351c9018673943d985..fe1f9e86146ecc414620704233f6b8191d2ffe17 100644 (file)
@@ -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<RTLIL::IdString, RTLIL::Module*> &local_interfaces)
+void AstModule::expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Module*> &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 dict<RTLIL::IdStri
                }
        }
 
-       // The old module will be deleted. Rename and mark for deletion:
-       std::string original_name = this->name.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
index 63104bca4b9246811f3142e29db405c07193a5b0..66bbdd7b4eed78c9652ce0a797e258e2beadebb6 100644 (file)
@@ -348,7 +348,7 @@ namespace AST
                RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, bool mayfail) override;
                RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, const dict<RTLIL::IdString, RTLIL::Module*> &interfaces, const dict<RTLIL::IdString, RTLIL::IdString> &modports, bool mayfail) override;
                std::string derive_common(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, AstNode **new_ast_out, bool quiet = false);
-               void reprocess_module(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Module *> &local_interfaces) override;
+               void expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Module *> &local_interfaces) override;
                RTLIL::Module *clone() const override;
                void loadconfig() const;
        };
@@ -395,6 +395,18 @@ namespace AST_INTERNAL
        extern dict<std::string, pool<int>> 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
index 3778972bcfd619fa2f97e6e7f43c127be70dd573..9fac575235c8d8b455c67952a5f6b87a314537f0 100644 (file)
@@ -936,9 +936,9 @@ void RTLIL::Module::makeblackbox()
        set_bool_attribute(ID::blackbox);
 }
 
-void RTLIL::Module::reprocess_module(RTLIL::Design *, const dict<RTLIL::IdString, RTLIL::Module *> &)
+void RTLIL::Module::expand_interfaces(RTLIL::Design *, const dict<RTLIL::IdString, RTLIL::Module *> &)
 {
-       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<RTLIL::IdString, RTLIL::Const> &, bool mayfail)
index 96982d2d96c934959ed525229ae923e66ab64352..c428f31543a47c045f8aec7e4893ff29c8c6ce47 100644 (file)
@@ -1160,7 +1160,7 @@ public:
        virtual RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, bool mayfail = false);
        virtual RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, const dict<RTLIL::IdString, RTLIL::Module*> &interfaces, const dict<RTLIL::IdString, RTLIL::IdString> &modports, bool mayfail = false);
        virtual size_t count_id(RTLIL::IdString id);
-       virtual void reprocess_module(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Module *> &local_interfaces);
+       virtual void expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Module *> &local_interfaces);
 
        virtual void sort();
        virtual void check();
index 65003658066762910d0da873b2192428b9c222fd..1e69ab903364f86ce0b909ebb2c972846195aab7 100644 (file)
@@ -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;
        }