X(AST_AUTOWIRE)
X(AST_PARAMETER)
X(AST_LOCALPARAM)
+ X(AST_DEFPARAM)
X(AST_PARASET)
X(AST_ARGUMENT)
X(AST_RANGE)
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);
AST_AUTOWIRE,
AST_PARAMETER,
AST_LOCALPARAM,
+ AST_DEFPARAM,
AST_PARASET,
AST_ARGUMENT,
AST_RANGE,
case AST_AUTOWIRE:
case AST_PARAMETER:
case AST_LOCALPARAM:
+ case AST_DEFPARAM:
case AST_GENVAR:
case AST_GENFOR:
case AST_GENBLOCK:
}
// 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;
}
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;
}
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) {
"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; }
"$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;
}
%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
%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
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);
/* 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:
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;
behavioral_stmt:
defattr |
simple_behavioral_stmt ';' |
- TOK_ID attr {
+ hierarchical_id attr {
AstNode *node = new AstNode(AST_TCALL);
node->str = *$1;
delete $1;
};
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;
$$->str = str;
delete $1;
} |
- TOK_ID attr {
+ hierarchical_id attr {
AstNode *node = new AstNode(AST_FCALL);
node->str = *$1;
delete $1;
// -----------------------------------
+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;