diff options
| author | Zachary Snow <zach@zachjs.com> | 2021-08-30 11:35:36 -0600 | 
|---|---|---|
| committer | Zachary Snow <zachary.j.snow@gmail.com> | 2021-08-30 15:19:21 -0600 | 
| commit | f0a52e3dd275ee57a1b3ffd0a734b591bf21f668 (patch) | |
| tree | 3c0c7883cf1e5045701ee5c739cfd6a6a6fbbc2c /frontends | |
| parent | 1dbf91a8ef3109d6573ae64fc3fd08aedc0a690d (diff) | |
| download | yosys-f0a52e3dd275ee57a1b3ffd0a734b591bf21f668.tar.gz yosys-f0a52e3dd275ee57a1b3ffd0a734b591bf21f668.tar.bz2 yosys-f0a52e3dd275ee57a1b3ffd0a734b591bf21f668.zip | |
sv: support declaration in procedural for initialization
In line with other tools, this adds an extra wrapping block around such
for loops to appropriately scope the variable.
Diffstat (limited to 'frontends')
| -rw-r--r-- | frontends/verilog/verilog_parser.y | 49 | 
1 files changed, 48 insertions, 1 deletions
| diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index b0c16c0f4..23404f844 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -2607,6 +2607,53 @@ asgn_binop:  	TOK_SSHL_ASSIGN { $$ = AST_SHIFT_SLEFT; } |  	TOK_SSHR_ASSIGN { $$ = AST_SHIFT_SRIGHT; } ; +for_initialization: +	TOK_ID '=' expr { +		AstNode *ident = new AstNode(AST_IDENTIFIER); +		ident->str = *$1; +		AstNode *node = new AstNode(AST_ASSIGN_EQ, ident, $3); +		ast_stack.back()->children.push_back(node); +		SET_AST_NODE_LOC(node, @1, @3); +	} | +	non_io_wire_type range TOK_ID { +		frontend_verilog_yyerror("For loop variable declaration is missing initialization!"); +	} | +	non_io_wire_type range TOK_ID '=' expr { +		if (!sv_mode) +			frontend_verilog_yyerror("For loop inline variable declaration is only supported in SystemVerilog mode!"); + +		// loop variable declaration +		AstNode *wire = $1; +		AstNode *range = checkRange(wire, $2); +		if (range != nullptr) +			wire->children.push_back(range); +		SET_AST_NODE_LOC(wire, @1, @3); +		SET_AST_NODE_LOC(range, @2, @2); + +		AstNode *ident = new AstNode(AST_IDENTIFIER); +		ident->str = *$3; +		wire->str = *$3; +		delete $3; + +		AstNode *loop = ast_stack.back(); +		AstNode *parent = ast_stack.at(ast_stack.size() - 2); +		log_assert(parent->children.back() == loop); + +		// loop variable initialization +		AstNode *asgn = new AstNode(AST_ASSIGN_EQ, ident, $5); +		loop->children.push_back(asgn); +		SET_AST_NODE_LOC(asgn, @3, @5); +		SET_AST_NODE_LOC(ident, @3, @3); + +		// inject a wrapping block to declare the loop variable and +		// contain the current loop +		AstNode *wrapper = new AstNode(AST_BLOCK); +		wrapper->str = "$fordecl_block$" + std::to_string(autoidx++); +		wrapper->children.push_back(wire); +		wrapper->children.push_back(loop); +		parent->children.back() = wrapper; // replaces `loop` +	}; +  // this production creates the obligatory if-else shift/reduce conflict  behavioral_stmt:  	defattr | assert | wire_decl | param_decl | localparam_decl | typedef_decl | @@ -2667,7 +2714,7 @@ behavioral_stmt:  		ast_stack.back()->children.push_back(node);  		ast_stack.push_back(node);  		append_attr(node, $1); -	} simple_behavioral_stmt ';' expr { +	} for_initialization ';' expr {  		ast_stack.back()->children.push_back($7);  	} ';' simple_behavioral_stmt ')' {  		AstNode *block = new AstNode(AST_BLOCK); | 
