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/verilog | |
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/verilog')
-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); |