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.
This commit is contained in:
Rupert Swarbrick 2021-10-19 18:43:30 -06:00 committed by Zachary Snow
parent ee230f2bb9
commit bd16d01c0e
5 changed files with 61 additions and 28 deletions

View File

@ -983,8 +983,7 @@ static bool param_has_no_default(const AstNode *param) {
(children.size() == 1 && children[0]->type == AST_RANGE); (children.size() == 1 && children[0]->type == AST_RANGE);
} }
// create and add a new AstModule from an AST_MODULE AST node static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool defer, AstNode *original_ast = NULL, bool quiet = false)
static void process_module(RTLIL::Design *design, AstNode *ast, bool defer, AstNode *original_ast = NULL, bool quiet = false)
{ {
log_assert(current_scope.empty()); log_assert(current_scope.empty());
log_assert(ast->type == AST_MODULE || ast->type == AST_INTERFACE); 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); 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 // 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 // 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. // 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(); loadconfig();
bool is_top = false;
AstNode *new_ast = ast->clone(); AstNode *new_ast = ast->clone();
for (auto &intf : local_interfaces) { for (auto &intf : local_interfaces) {
std::string intfname = intf.first.str(); 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: // Generate RTLIL from AST for the new module and add to the design,
std::string original_name = this->name.str(); // renaming this module to move it out of the way.
std::string changed_name = original_name + "_before_replacing_local_interfaces"; RTLIL::Module* new_module =
design->rename(this, changed_name); process_and_replace_module(design, this, new_ast, ast_before_replacing_interface_ports);
this->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 delete new_ast;
// 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);
// Set the attribute "interfaces_replaced_in_module" so that it does not happen again. // 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 // create a new parametric module (when needed) and return the name of the generated module - WITH support for interfaces

View 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, 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; 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); 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; RTLIL::Module *clone() const override;
void loadconfig() const; void loadconfig() const;
}; };
@ -395,6 +395,18 @@ namespace AST_INTERNAL
extern dict<std::string, pool<int>> current_memwr_visible; extern dict<std::string, pool<int>> current_memwr_visible;
struct LookaheadRewriter; struct LookaheadRewriter;
struct ProcessGenerator; 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 YOSYS_NAMESPACE_END

View File

@ -936,9 +936,9 @@ void RTLIL::Module::makeblackbox()
set_bool_attribute(ID::blackbox); 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) RTLIL::IdString RTLIL::Module::derive(RTLIL::Design*, const dict<RTLIL::IdString, RTLIL::Const> &, bool mayfail)

View 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, 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 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 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 sort();
virtual void check(); virtual void check();

View 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 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)) { 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; return did_something;
} }