Added defparam support to Verilog/AST frontend
authorClifford Wolf <clifford@clifford.at>
Thu, 4 Jul 2013 12:12:33 +0000 (14:12 +0200)
committerClifford Wolf <clifford@clifford.at>
Thu, 4 Jul 2013 12:12:33 +0000 (14:12 +0200)
frontends/ast/ast.cc
frontends/ast/ast.h
frontends/ast/genrtlil.cc
frontends/ast/simplify.cc
frontends/verilog/lexer.l
frontends/verilog/parser.y
tests/simple/paramods.v

index a14297b62f95c57edd06b2f8547e3b4097d9b254..f7a39cf19ae542bbffa939b5fd5c3e86fd8c0c69 100644 (file)
@@ -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);
index c8de580e39b9c9850405aa81a1b4bf71258052d9..12e9a71bc57a78ca6a8a3813b27f7ca69b13ae7d 100644 (file)
@@ -50,6 +50,7 @@ namespace AST
                AST_AUTOWIRE,
                AST_PARAMETER,
                AST_LOCALPARAM,
+               AST_DEFPARAM,
                AST_PARASET,
                AST_ARGUMENT,
                AST_RANGE,
index aa5a98c4133069c3d6f6264287f0a0e904c4306b..03bb8a43009cdb21eca454f656807e00886481f0 100644 (file)
@@ -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:
index bc135b39dccc617f3d508b4c211b6c4a5e1caef2..cf21c85d923c777ac5910baeb99c8349babb1103 100644 (file)
@@ -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) {
index 78f1d3674be428e948659a17d2b32fd95f6fa99a..cc7590ca564fe1ac980c1f6ac73953030b18b3d9 100644 (file)
@@ -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;
 }
index 68ac26bf9846bc4912aa460294f5e48995031058..ba0efcf51c9974bbf074e99542188cb21f8198ec 100644 (file)
@@ -94,7 +94,7 @@ static void free_attr(std::map<std::string, AstNode*> *al)
 
 %token <string> 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<std::string, AstNode*> *al)
 %token TOK_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED
 
 %type <ast> wire_type range expr basic_expr concat_list rvalue lvalue lvalue_concat_list
-%type <string> opt_label tok_prim_wrapper
+%type <string> opt_label tok_prim_wrapper hierarchical_id
 %type <boolean> opt_signed
 %type <al> 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;
index 94fd2dfc2245ca65ebb697fcbbdb202b26e241d3..8d0134a674508e032a6ae03d1704c622b03baae1 100644 (file)
@@ -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;