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);
}
// 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

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, 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

View 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)

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, 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();

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 ((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;
}