3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-04-25 01:55:33 +00:00

sv: support for parameters without default values

- Modules with a parameter without a default value will be automatically
  deferred until the hierarchy pass
- Allows for parameters without defaults as module items, rather than
  just int the `parameter_port_list`, despite being forbidden in the LRM
- Check for parameters without defaults that haven't been overriden
- Add location info to parameter/localparam declarations
This commit is contained in:
Zachary Snow 2021-03-02 10:43:53 -05:00
parent 375af199ef
commit d738b2c127
12 changed files with 225 additions and 5 deletions

View file

@ -968,6 +968,14 @@ void AST::set_src_attr(RTLIL::AttrObject *obj, const AstNode *ast)
obj->attributes[ID::src] = ast->loc_string();
}
static bool param_has_no_default(const AstNode *param) {
const auto &children = param->children;
log_assert(param->type == AST_PARAMETER);
log_assert(children.size() <= 2);
return children.empty() ||
(children.size() == 1 && children[0]->type == AST_RANGE);
}
// create a new AstModule from an AST_MODULE AST node
static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast = NULL, bool quiet = false)
{
@ -1006,6 +1014,10 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
if (!defer)
{
for (const AstNode *node : ast->children)
if (node->type == AST_PARAMETER && param_has_no_default(node))
log_file_error(node->filename, node->location.first_line, "Parameter `%s' has no default value and has not been overridden!\n", node->str.c_str());
bool blackbox_module = flag_lib;
if (!blackbox_module && !flag_noblackbox) {
@ -1229,7 +1241,18 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
if (flag_icells && (*it)->str.compare(0, 2, "\\$") == 0)
(*it)->str = (*it)->str.substr(1);
if (defer)
bool defer_local = defer;
if (!defer_local)
for (const AstNode *node : (*it)->children)
if (node->type == AST_PARAMETER && param_has_no_default(node))
{
log("Deferring `%s' because it contains parameter(s) without defaults.\n", ast->str.c_str());
defer_local = true;
break;
}
if (defer_local)
(*it)->str = "$abstract" + (*it)->str;
if (design->has((*it)->str)) {
@ -1248,7 +1271,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
}
}
design->add(process_module(*it, defer));
design->add(process_module(*it, defer_local));
current_ast_mod = nullptr;
}
else if ((*it)->type == AST_PACKAGE) {
@ -1619,6 +1642,8 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::Id
}
continue;
rewrite_parameter:
if (param_has_no_default(child))
child->children.insert(child->children.begin(), nullptr);
delete child->children.at(0);
if ((it->second.flags & RTLIL::CONST_FLAG_REAL) != 0) {
child->children[0] = new AstNode(AST_REALVALUE);

View file

@ -1462,7 +1462,26 @@ param_decl_list:
single_param_decl | param_decl_list ',' single_param_decl;
single_param_decl:
TOK_ID '=' expr {
single_param_decl_ident '=' expr {
AstNode *decl = ast_stack.back()->children.back();
log_assert(decl->type == AST_PARAMETER || decl->type == AST_LOCALPARAM);
delete decl->children[0];
decl->children[0] = $3;
} |
single_param_decl_ident {
AstNode *decl = ast_stack.back()->children.back();
if (decl->type != AST_PARAMETER) {
log_assert(decl->type == AST_LOCALPARAM);
frontend_verilog_yyerror("localparam initialization is missing!");
}
if (!sv_mode)
frontend_verilog_yyerror("Parameter defaults can only be omitted in SystemVerilog mode!");
delete decl->children[0];
decl->children.erase(decl->children.begin());
};
single_param_decl_ident:
TOK_ID {
AstNode *node;
if (astbuf1 == nullptr) {
if (!sv_mode)
@ -1473,10 +1492,9 @@ single_param_decl:
node = astbuf1->clone();
}
node->str = *$1;
delete node->children[0];
node->children[0] = $3;
ast_stack.back()->children.push_back(node);
delete $1;
SET_AST_NODE_LOC(node, @1, @1);
};
defparam_decl: