From 56432a920f9c2189ead2f724f18cde20aad7bf99 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 4 Jul 2013 14:12:33 +0200 Subject: [PATCH] Added defparam support to Verilog/AST frontend --- frontends/ast/ast.cc | 3 ++- frontends/ast/ast.h | 1 + frontends/ast/genrtlil.cc | 1 + frontends/ast/simplify.cc | 20 ++++++++++++++-- frontends/verilog/lexer.l | 3 ++- frontends/verilog/parser.y | 48 +++++++++++++++++++++++++++++++------- tests/simple/paramods.v | 16 +++++++++++++ 7 files changed, 79 insertions(+), 13 deletions(-) diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index a14297b62..f7a39cf19 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -72,6 +72,7 @@ std::string AST::type2str(AstNodeType type) X(AST_AUTOWIRE) X(AST_PARAMETER) X(AST_LOCALPARAM) + X(AST_DEFPARAM) X(AST_PARASET) X(AST_ARGUMENT) X(AST_RANGE) @@ -327,7 +328,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) fprintf(f, ");\n"); for (auto child : children) - if (child->type == AST_PARAMETER || child->type == AST_LOCALPARAM) + if (child->type == AST_PARAMETER || child->type == AST_LOCALPARAM || child->type == AST_DEFPARAM) child->dumpVlog(f, indent + " "); else rem_children1.push_back(child); diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index c8de580e3..12e9a71bc 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -50,6 +50,7 @@ namespace AST AST_AUTOWIRE, AST_PARAMETER, AST_LOCALPARAM, + AST_DEFPARAM, AST_PARASET, AST_ARGUMENT, AST_RANGE, diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index aa5a98c41..03bb8a430 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -531,6 +531,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint) case AST_AUTOWIRE: case AST_PARAMETER: case AST_LOCALPARAM: + case AST_DEFPARAM: case AST_GENVAR: case AST_GENFOR: case AST_GENBLOCK: diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index bc135b39d..cf21c85d9 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -103,7 +103,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage) } // activate const folding if this is anything that must be evaluated statically (ranges, parameters, attributes, etc.) - if (type == AST_WIRE || type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_PARASET || type == AST_RANGE || type == AST_PREFIX) + if (type == AST_WIRE || type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_RANGE || type == AST_PREFIX) const_fold = true; if (type == AST_IDENTIFIER && current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM)) const_fold = true; @@ -163,7 +163,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage) } wires_are_incompatible: if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_GENVAR || - node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK) { + node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_CELL) { backup_scope[node->str] = current_scope[node->str]; current_scope[node->str] = node; } @@ -224,6 +224,22 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage) if (type == AST_MODULE) current_scope.clear(); + // convert defparam nodes to cell parameters + if (type == AST_DEFPARAM && !str.empty()) { + size_t pos = str.rfind('.'); + if (pos == std::string::npos) + log_error("Defparam `%s' does not contain a dot (module/parameter seperator) at %s:%d!\n", + RTLIL::id2cstr(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::id2cstr(modname), RTLIL::id2cstr(paraname), filename.c_str(), linenum); + AstNode *cell = current_scope.at(modname), *paraset = clone(); + cell->children.insert(cell->children.begin() + 1, paraset); + paraset->type = AST_PARASET; + paraset->str = paraname; + str.clear(); + } + // resolve constant prefixes if (type == AST_PREFIX) { if (children[0]->type != AST_CONSTANT) { diff --git a/frontends/verilog/lexer.l b/frontends/verilog/lexer.l index 78f1d3674..cc7590ca5 100644 --- a/frontends/verilog/lexer.l +++ b/frontends/verilog/lexer.l @@ -95,6 +95,7 @@ namespace VERILOG_FRONTEND { "endtask" { return TOK_ENDTASK; } "parameter" { return TOK_PARAMETER; } "localparam" { return TOK_LOCALPARAM; } +"defparam" { return TOK_DEFPARAM; } "assign" { return TOK_ASSIGN; } "always" { return TOK_ALWAYS; } "initial" { return TOK_INITIAL; } @@ -184,7 +185,7 @@ supply1 { return TOK_SUPPLY1; } "$signed" { return TOK_TO_SIGNED; } "$unsigned" { return TOK_TO_UNSIGNED; } -[a-zA-Z_$][a-zA-Z0-9_\.$]* { +[a-zA-Z_$][a-zA-Z0-9_$]* { frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); return TOK_ID; } diff --git a/frontends/verilog/parser.y b/frontends/verilog/parser.y index 68ac26bf9..ba0efcf51 100644 --- a/frontends/verilog/parser.y +++ b/frontends/verilog/parser.y @@ -94,7 +94,7 @@ static void free_attr(std::map *al) %token TOK_STRING TOK_ID TOK_CONST TOK_PRIMITIVE %token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END -%token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM +%token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM %token TOK_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_REG %token TOK_INTEGER TOK_SIGNED TOK_ASSIGN TOK_ALWAYS TOK_INITIAL %token TOK_BEGIN TOK_END TOK_IF TOK_ELSE TOK_FOR @@ -106,7 +106,7 @@ static void free_attr(std::map *al) %token TOK_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED %type wire_type range expr basic_expr concat_list rvalue lvalue lvalue_concat_list -%type opt_label tok_prim_wrapper +%type opt_label tok_prim_wrapper hierarchical_id %type opt_signed %type attr @@ -176,19 +176,32 @@ attr_list: attr_list ',' attr_assign; attr_assign: - TOK_ID { + hierarchical_id { if (attr_list.count(*$1) != 0) delete attr_list[*$1]; attr_list[*$1] = AstNode::mkconst_int(0, false, 0); delete $1; } | - TOK_ID '=' expr { + hierarchical_id '=' expr { if (attr_list.count(*$1) != 0) delete attr_list[*$1]; attr_list[*$1] = $3; delete $1; }; +hierarchical_id: + TOK_ID { + $$ = $1; + } | + hierarchical_id '.' TOK_ID { + if ($3->substr(0, 1) == "\\") + *$1 += "." + $3->substr(1); + else + *$1 += "." + *$3; + delete $3; + $$ = $1; + }; + module: attr TOK_MODULE TOK_ID { AstNode *mod = new AstNode(AST_MODULE); @@ -309,7 +322,7 @@ module_body: /* empty */; module_body_stmt: - task_func_decl | param_decl | localparam_decl | wire_decl | assign_stmt | cell_stmt | + task_func_decl | param_decl | localparam_decl | defparam_decl | wire_decl | assign_stmt | cell_stmt | always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr; task_func_decl: @@ -389,6 +402,23 @@ single_localparam_decl: delete $2; }; +defparam_decl: + TOK_DEFPARAM defparam_decl_list ';'; + +defparam_decl_list: + single_defparam_decl | defparam_decl_list ',' single_defparam_decl; + +single_defparam_decl: + range hierarchical_id '=' expr { + AstNode *node = new AstNode(AST_DEFPARAM); + node->str = *$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: attr wire_type range { albuf = $1; @@ -671,7 +701,7 @@ simple_behavioral_stmt: behavioral_stmt: defattr | simple_behavioral_stmt ';' | - TOK_ID attr { + hierarchical_id attr { AstNode *node = new AstNode(AST_TCALL); node->str = *$1; delete $1; @@ -808,12 +838,12 @@ case_expr_list: }; rvalue: - TOK_ID '[' expr ']' '.' rvalue { + hierarchical_id '[' expr ']' '.' rvalue { $$ = new AstNode(AST_PREFIX, $3, $6); $$->str = *$1; delete $1; } | - TOK_ID range { + hierarchical_id range { $$ = new AstNode(AST_IDENTIFIER, $2); $$->str = *$1; delete $1; @@ -931,7 +961,7 @@ basic_expr: $$->str = str; delete $1; } | - TOK_ID attr { + hierarchical_id attr { AstNode *node = new AstNode(AST_FCALL); node->str = *$1; delete $1; diff --git a/tests/simple/paramods.v b/tests/simple/paramods.v index 94fd2dfc2..8d0134a67 100644 --- a/tests/simple/paramods.v +++ b/tests/simple/paramods.v @@ -23,6 +23,22 @@ endmodule // ----------------------------------- +module test3(a, b, x, y); + +input [7:0] a, b; +output [7:0] x, y; + +inc inc_a (.in(a), .out(x)); +inc inc_b (b, y); + +defparam inc_a.step = 3; +defparam inc_b.step = 7; +defparam inc_b.width = 4; + +endmodule + +// ----------------------------------- + module inc(in, out); parameter width = 8; -- 2.30.2