module->derive() to be lazy and not touch ast if already derived

This commit is contained in:
Eddie Hung 2019-09-30 14:11:01 -07:00
parent a274b7cc86
commit 08b55a20e3
2 changed files with 51 additions and 33 deletions

View File

@ -1382,10 +1382,10 @@ void AstModule::reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RT
// 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
// This method is used to explode the interface when the interface is a port of the module (not instantiated inside) // This method is used to explode the interface when the interface is a port of the module (not instantiated inside)
RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, dict<RTLIL::IdString, RTLIL::IdString> modports, bool mayfail) RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, dict<RTLIL::IdString, RTLIL::IdString> modports, bool /*mayfail*/)
{ {
AstNode *new_ast = NULL; AstNode *new_ast = NULL;
std::string modname = derive_common(design, parameters, &new_ast, mayfail); std::string modname = derive_common(design, parameters, &new_ast);
// Since interfaces themselves may be instantiated with different parameters, // Since interfaces themselves may be instantiated with different parameters,
// "modname" must also take those into account, so that unique modules // "modname" must also take those into account, so that unique modules
@ -1455,10 +1455,10 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, R
} }
// create a new parametric module (when needed) and return the name of the generated module - without support for interfaces // create a new parametric module (when needed) and return the name of the generated module - without support for interfaces
RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail) RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool /*mayfail*/)
{ {
AstNode *new_ast = NULL; AstNode *new_ast = NULL;
std::string modname = derive_common(design, parameters, &new_ast, mayfail); std::string modname = derive_common(design, parameters, &new_ast);
if (!design->has(modname)) { if (!design->has(modname)) {
new_ast->str = modname; new_ast->str = modname;
@ -1473,47 +1473,75 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, R
} }
// create a new parametric module (when needed) and return the name of the generated module // create a new parametric module (when needed) and return the name of the generated module
std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, AstNode **new_ast_out, bool) std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, AstNode **new_ast_out)
{ {
std::string stripped_name = name.str(); std::string stripped_name = name.str();
if (stripped_name.compare(0, 9, "$abstract") == 0) if (stripped_name.compare(0, 9, "$abstract") == 0)
stripped_name = stripped_name.substr(9); stripped_name = stripped_name.substr(9);
log_header(design, "Executing AST frontend in derive mode using pre-parsed AST for module `%s'.\n", stripped_name.c_str());
loadconfig();
std::string para_info; std::string para_info;
AstNode *new_ast = ast->clone();
int para_counter = 0; int para_counter = 0;
int orig_parameters_n = parameters.size(); for (const auto child : ast->children) {
for (auto it = new_ast->children.begin(); it != new_ast->children.end(); it++) {
AstNode *child = *it;
if (child->type != AST_PARAMETER) if (child->type != AST_PARAMETER)
continue; continue;
para_counter++; para_counter++;
std::string para_id = child->str; std::string para_id = child->str;
if (parameters.count(para_id) > 0) { if (parameters.count(para_id) > 0) {
log("Parameter %s = %s\n", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[child->str]))); log("Parameter %s = %s\n", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[child->str])));
rewrite_parameter:
para_info += stringf("%s=%s", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id]))); para_info += stringf("%s=%s", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id])));
delete child->children.at(0);
if ((parameters[para_id].flags & RTLIL::CONST_FLAG_REAL) != 0) {
child->children[0] = new AstNode(AST_REALVALUE);
child->children[0]->realvalue = std::stod(parameters[para_id].decode_string());
} else if ((parameters[para_id].flags & RTLIL::CONST_FLAG_STRING) != 0)
child->children[0] = AstNode::mkconst_str(parameters[para_id].decode_string());
else
child->children[0] = AstNode::mkconst_bits(parameters[para_id].bits, (parameters[para_id].flags & RTLIL::CONST_FLAG_SIGNED) != 0);
parameters.erase(para_id);
continue; continue;
} }
para_id = stringf("$%d", para_counter); para_id = stringf("$%d", para_counter);
if (parameters.count(para_id) > 0) {
log("Parameter %d (%s) = %s\n", para_counter, child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id])));
para_info += stringf("%s=%s", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id])));
continue;
}
}
std::string modname;
if (parameters.size() == 0)
modname = stripped_name;
else if (para_info.size() > 60)
modname = "$paramod$" + sha1(para_info) + stripped_name;
else
modname = "$paramod" + stripped_name + para_info;
if (design->has(modname))
return modname;
log_header(design, "Executing AST frontend in derive mode using pre-parsed AST for module `%s'.\n", stripped_name.c_str());
loadconfig();
AstNode *new_ast = ast->clone();
para_counter = 0;
for (auto child : new_ast->children) {
if (child->type != AST_PARAMETER)
continue;
para_counter++;
std::string para_id = child->str;
if (parameters.count(para_id) > 0) {
log("Parameter %s = %s\n", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[child->str])));
goto rewrite_parameter;
}
para_id = stringf("$%d", para_counter);
if (parameters.count(para_id) > 0) { if (parameters.count(para_id) > 0) {
log("Parameter %d (%s) = %s\n", para_counter, child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id]))); log("Parameter %d (%s) = %s\n", para_counter, child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id])));
goto rewrite_parameter; goto rewrite_parameter;
} }
continue;
rewrite_parameter:
delete child->children.at(0);
if ((parameters[para_id].flags & RTLIL::CONST_FLAG_REAL) != 0) {
child->children[0] = new AstNode(AST_REALVALUE);
child->children[0]->realvalue = std::stod(parameters[para_id].decode_string());
} else if ((parameters[para_id].flags & RTLIL::CONST_FLAG_STRING) != 0)
child->children[0] = AstNode::mkconst_str(parameters[para_id].decode_string());
else
child->children[0] = AstNode::mkconst_bits(parameters[para_id].bits, (parameters[para_id].flags & RTLIL::CONST_FLAG_SIGNED) != 0);
parameters.erase(para_id);
} }
for (auto param : parameters) { for (auto param : parameters) {
@ -1526,16 +1554,6 @@ std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString
new_ast->children.push_back(defparam); new_ast->children.push_back(defparam);
} }
std::string modname;
if (orig_parameters_n == 0)
modname = stripped_name;
else if (para_info.size() > 60)
modname = "$paramod$" + sha1(para_info) + stripped_name;
else
modname = "$paramod" + stripped_name + para_info;
(*new_ast_out) = new_ast; (*new_ast_out) = new_ast;
return modname; return modname;
} }

View File

@ -296,7 +296,7 @@ namespace AST
~AstModule() YS_OVERRIDE; ~AstModule() YS_OVERRIDE;
RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail) YS_OVERRIDE; RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail) YS_OVERRIDE;
RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, dict<RTLIL::IdString, RTLIL::IdString> modports, bool mayfail) YS_OVERRIDE; RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, dict<RTLIL::IdString, RTLIL::IdString> modports, bool mayfail) YS_OVERRIDE;
std::string derive_common(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, AstNode **new_ast_out, bool mayfail); std::string derive_common(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, AstNode **new_ast_out);
void reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Module *> local_interfaces) YS_OVERRIDE; void reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Module *> local_interfaces) YS_OVERRIDE;
RTLIL::Module *clone() const YS_OVERRIDE; RTLIL::Module *clone() const YS_OVERRIDE;
void loadconfig() const; void loadconfig() const;