From 70d7a02cae7ef38eb4f3afcf325979b80e87518e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 15 Nov 2016 13:35:19 +0100 Subject: [PATCH] Added support for hierarchical defparams --- frontends/ast/ast.cc | 9 +++++-- frontends/ast/simplify.cc | 43 ++++++++++++++++++++++-------- frontends/verilog/verilog_parser.y | 5 ++-- passes/hierarchy/hierarchy.cc | 2 +- tests/simple/hierdefparam.v | 23 ++++++++++++++++ 5 files changed, 65 insertions(+), 17 deletions(-) create mode 100644 tests/simple/hierdefparam.v diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 5b4a4af47..2d58c682f 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -1113,8 +1113,13 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict 0) - log_error("Requested parameter `%s' does not exist in module `%s'!\n", parameters.begin()->first.c_str(), stripped_name.c_str()); + + for (auto param : parameters) { + AstNode *defparam = new AstNode(AST_DEFPARAM, new AstNode(AST_IDENTIFIER)); + defparam->children[0]->str = param.first.str(); + defparam->children.push_back(AstNode::mkconst_bits(param.second.bits, (param.second.flags & RTLIL::CONST_FLAG_SIGNED) != 0)); + new_ast->children.push_back(defparam); + } std::string modname; diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 3432c61da..58db882d3 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -685,19 +685,40 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, current_scope.clear(); // convert defparam nodes to cell parameters - if (type == AST_DEFPARAM && !str.empty()) { - size_t pos = str.rfind('.'); + if (type == AST_DEFPARAM && !children.empty()) + { + if (children[0]->type != AST_IDENTIFIER) + log_error("Module name in defparam at %s:%d contains non-constant expressions!\n", filename.c_str(), linenum); + + string modname, paramname = children[0]->str; + + size_t pos = paramname.rfind('.'); + + while (pos != 0 && pos != std::string::npos) + { + modname = paramname.substr(0, pos); + + if (current_scope.count(modname)) + break; + + pos = paramname.rfind('.', pos - 1); + } + if (pos == std::string::npos) - log_error("Defparam `%s' does not contain a dot (module/parameter separator) at %s:%d!\n", - RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum); - std::string modname = str.substr(0, pos), paraname = "\\" + str.substr(pos+1); - if (current_scope.count(modname) == 0 || current_scope.at(modname)->type != AST_CELL) - log_error("Can't find cell for defparam `%s . %s` at %s:%d!\n", RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paraname).c_str(), filename.c_str(), linenum); - AstNode *cell = current_scope.at(modname), *paraset = clone(); + log_error("Can't find object for defparam `%s` at %s:%d!\n", RTLIL::unescape_id(paramname).c_str(), filename.c_str(), linenum); + + paramname = "\\" + paramname.substr(pos+1); + + if (current_scope.at(modname)->type != AST_CELL) + log_error("Defparam argument `%s . %s` does not match a cell at %s:%d!\n", + RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paramname).c_str(), filename.c_str(), linenum); + + AstNode *paraset = new AstNode(AST_PARASET, children[1]->clone(), GetSize(children) > 2 ? children[2]->clone() : NULL); + paraset->str = paramname; + + AstNode *cell = current_scope.at(modname); cell->children.insert(cell->children.begin() + 1, paraset); - paraset->type = AST_PARASET; - paraset->str = paraname; - str.clear(); + delete_children(); } // resolve constant prefixes diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 5bbda5355..607c48a81 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -666,14 +666,13 @@ defparam_decl_list: single_defparam_decl | defparam_decl_list ',' single_defparam_decl; single_defparam_decl: - range hierarchical_id '=' expr { + range rvalue '=' expr { AstNode *node = new AstNode(AST_DEFPARAM); - node->str = *$2; + node->children.push_back($2); node->children.push_back($4); if ($1 != NULL) node->children.push_back($1); ast_stack.back()->children.push_back(node); - delete $2; }; wire_decl: diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index e21a7a4e3..376df5698 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -213,7 +213,7 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check log_error("Module `%s' referenced in module `%s' in cell `%s' does not have a port named '%s'.\n", log_id(cell->type), log_id(module), log_id(cell), log_id(conn.first)); for (auto ¶m : cell->parameters) - if (mod->avail_parameters.count(param.first) == 0 && param.first[0] != '$') + if (mod->avail_parameters.count(param.first) == 0 && param.first[0] != '$' && strchr(param.first.c_str(), '.') == NULL) log_error("Module `%s' referenced in module `%s' in cell `%s' does not have a parameter named '%s'.\n", log_id(cell->type), log_id(module), log_id(cell), log_id(param.first)); } diff --git a/tests/simple/hierdefparam.v b/tests/simple/hierdefparam.v new file mode 100644 index 000000000..ff92c38bd --- /dev/null +++ b/tests/simple/hierdefparam.v @@ -0,0 +1,23 @@ +module hierdefparam_top(input [7:0] A, output [7:0] Y); + generate begin:foo + hierdefparam_a mod_a(.A(A), .Y(Y)); + end endgenerate + defparam foo.mod_a.bar[0].mod_b.addvalue = 42; + defparam foo.mod_a.bar[1].mod_b.addvalue = 43; +endmodule + +module hierdefparam_a(input [7:0] A, output [7:0] Y); + genvar i; + generate + for (i = 0; i < 2; i=i+1) begin:bar + wire [7:0] a, y; + hierdefparam_b mod_b(.A(a), .Y(y)); + end + endgenerate + assign bar[0].a = A, bar[1].a = bar[0].y, Y = bar[1].y; +endmodule + +module hierdefparam_b(input [7:0] A, output [7:0] Y); + parameter [7:0] addvalue = 44; + assign Y = A + addvalue; +endmodule -- 2.30.2