diff options
Diffstat (limited to 'frontends/verilog/verilog_parser.y')
-rw-r--r-- | frontends/verilog/verilog_parser.y | 104 |
1 files changed, 63 insertions, 41 deletions
diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 8bd58d24c..dc7ec8348 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -277,7 +277,7 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode) %token TOK_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED %token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_PROPERTY TOK_ENUM TOK_TYPEDEF %token TOK_RAND TOK_CONST TOK_CHECKER TOK_ENDCHECKER TOK_EVENTUALLY -%token TOK_INCREMENT TOK_DECREMENT TOK_UNIQUE TOK_PRIORITY +%token TOK_INCREMENT TOK_DECREMENT TOK_UNIQUE TOK_UNIQUE0 TOK_PRIORITY %token TOK_STRUCT TOK_PACKED TOK_UNSIGNED TOK_INT TOK_BYTE TOK_SHORTINT TOK_UNION %token TOK_OR_ASSIGN TOK_XOR_ASSIGN TOK_AND_ASSIGN TOK_SUB_ASSIGN @@ -286,7 +286,7 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode) %type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id integral_number %type <string> type_name %type <ast> opt_enum_init enum_type struct_type non_wire_data_type -%type <boolean> opt_signed opt_property unique_case_attr always_comb_or_latch always_or_always_ff +%type <boolean> opt_signed opt_property always_comb_or_latch always_or_always_ff %type <al> attr case_attr %type <ast> struct_union @@ -609,12 +609,17 @@ interface_body_stmt: param_decl | localparam_decl | typedef_decl | defparam_decl | wire_decl | always_stmt | assign_stmt | modport_stmt; +mintypmax_expr: + expr { delete $1; } | + expr ':' expr ':' expr { delete $1; delete $3; delete $5; }; + non_opt_delay: '#' TOK_ID { delete $2; } | '#' TOK_CONSTVAL { delete $2; } | '#' TOK_REALVAL { delete $2; } | - '#' '(' expr ')' { delete $3; } | - '#' '(' expr ':' expr ':' expr ')' { delete $3; delete $5; delete $7; }; + '#' '(' mintypmax_expr ')' | + '#' '(' mintypmax_expr ',' mintypmax_expr ')' | + '#' '(' mintypmax_expr ',' mintypmax_expr ',' mintypmax_expr ')'; delay: non_opt_delay | %empty; @@ -770,6 +775,7 @@ module_body: module_body module_body_stmt | /* the following line makes the generate..endgenrate keywords optional */ module_body gen_stmt | + module_body gen_block | module_body ';' | %empty; @@ -1490,10 +1496,10 @@ enum_base_type: type_atom type_signing | %empty { astbuf1->is_reg = true; addRange(astbuf1); } ; -type_atom: TOK_INTEGER { astbuf1->is_reg = true; addRange(astbuf1); } // 4-state signed - | TOK_INT { astbuf1->is_reg = true; addRange(astbuf1); } // 2-state signed - | TOK_SHORTINT { astbuf1->is_reg = true; addRange(astbuf1, 15, 0); } // 2-state signed - | TOK_BYTE { astbuf1->is_reg = true; addRange(astbuf1, 7, 0); } // 2-state signed +type_atom: TOK_INTEGER { astbuf1->is_reg = true; astbuf1->is_signed = true; addRange(astbuf1); } // 4-state signed + | TOK_INT { astbuf1->is_reg = true; astbuf1->is_signed = true; addRange(astbuf1); } // 2-state signed + | TOK_SHORTINT { astbuf1->is_reg = true; astbuf1->is_signed = true; addRange(astbuf1, 15, 0); } // 2-state signed + | TOK_BYTE { astbuf1->is_reg = true; astbuf1->is_signed = true; addRange(astbuf1, 7, 0); } // 2-state signed ; type_vec: TOK_REG { astbuf1->is_reg = true; } // unsigned @@ -1783,7 +1789,13 @@ wire_name: } rewriteAsMemoryNode(node, $2); } - if (current_function_or_task == NULL) { + if (current_function_or_task) { + if (node->is_input || node->is_output) + node->port_id = current_function_or_task_port_id++; + } else if (ast_stack.back()->type == AST_GENBLOCK) { + if (node->is_input || node->is_output) + frontend_verilog_yyerror("Cannot declare module port `%s' within a generate block.", $1->c_str()); + } else { if (do_not_require_port_stubs && (node->is_input || node->is_output) && port_stubs.count(*$1) == 0) { port_stubs[*$1] = ++port_counter; } @@ -1798,9 +1810,6 @@ wire_name: if (node->is_input || node->is_output) frontend_verilog_yyerror("Module port `%s' is not declared in module header.", $1->c_str()); } - } else { - if (node->is_input || node->is_output) - node->port_id = current_function_or_task_port_id++; } //FIXME: for some reason, TOK_ID has a location which always points to one column *after* the real last column... SET_AST_NODE_LOC(node, @1, @1); @@ -2459,6 +2468,16 @@ behavioral_stmt: exitTypeScope(); if ($4 != NULL && $8 != NULL && *$4 != *$8) frontend_verilog_yyerror("Begin label (%s) and end label (%s) don't match.", $4->c_str()+1, $8->c_str()+1); + AstNode *node = ast_stack.back(); + // In SystemVerilog, unnamed blocks with block item declarations + // create an implicit hierarchy scope + if (sv_mode && node->str.empty()) + for (const AstNode* child : node->children) + if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER + || child->type == AST_LOCALPARAM || child->type == AST_TYPEDEF) { + node->str = "$unnamed_block$" + std::to_string(autoidx++); + break; + } SET_AST_NODE_LOC(ast_stack.back(), @2, @8); delete $4; delete $8; @@ -2473,6 +2492,7 @@ behavioral_stmt: ast_stack.back()->children.push_back($7); } ';' simple_behavioral_stmt ')' { AstNode *block = new AstNode(AST_BLOCK); + block->str = "$for_loop$" + std::to_string(autoidx++); ast_stack.back()->children.push_back(block); ast_stack.push_back(block); } behavioral_stmt { @@ -2539,20 +2559,21 @@ behavioral_stmt: ast_stack.pop_back(); }; -unique_case_attr: - %empty { - $$ = false; +case_attr: + attr { + $$ = $1; } | - TOK_PRIORITY case_attr { - $$ = $2; + attr TOK_UNIQUE0 { + (*$1)[ID::parallel_case] = AstNode::mkconst_int(1, false); + $$ = $1; } | - TOK_UNIQUE case_attr { - $$ = true; - }; - -case_attr: - attr unique_case_attr { - if ($2) (*$1)[ID::parallel_case] = AstNode::mkconst_int(1, false); + attr TOK_PRIORITY { + (*$1)[ID::full_case] = AstNode::mkconst_int(1, false); + $$ = $1; + } | + attr TOK_UNIQUE { + (*$1)[ID::full_case] = AstNode::mkconst_int(1, false); + (*$1)[ID::parallel_case] = AstNode::mkconst_int(1, false); $$ = $1; }; @@ -2722,6 +2743,7 @@ single_arg: module_gen_body: module_gen_body gen_stmt_or_module_body_stmt | + module_gen_body gen_block | %empty; gen_stmt_or_module_body_stmt: @@ -2747,12 +2769,7 @@ gen_stmt: ast_stack.back()->children.push_back(node); ast_stack.push_back(node); ast_stack.back()->children.push_back($3); - AstNode *block = new AstNode(AST_GENBLOCK); - ast_stack.back()->children.push_back(block); - ast_stack.push_back(block); - } gen_stmt_block { - ast_stack.pop_back(); - } opt_gen_else { + } gen_stmt_block opt_gen_else { SET_AST_NODE_LOC(ast_stack.back(), @1, @7); ast_stack.pop_back(); } | @@ -2765,6 +2782,18 @@ gen_stmt: SET_AST_NODE_LOC(ast_stack.back(), @1, @7); ast_stack.pop_back(); } | + TOK_MSG_TASKS { + AstNode *node = new AstNode(AST_TECALL); + node->str = *$1; + delete $1; + ast_stack.back()->children.push_back(node); + ast_stack.push_back(node); + } opt_arg_list ';'{ + SET_AST_NODE_LOC(ast_stack.back(), @1, @3); + ast_stack.pop_back(); + }; + +gen_block: TOK_BEGIN { enterTypeScope(); } opt_label { @@ -2774,22 +2803,15 @@ gen_stmt: ast_stack.push_back(node); } module_gen_body TOK_END opt_label { exitTypeScope(); + if ($3 != NULL && $7 != NULL && *$3 != *$7) + frontend_verilog_yyerror("Begin label (%s) and end label (%s) don't match.", $3->c_str()+1, $7->c_str()+1); delete $3; delete $7; SET_AST_NODE_LOC(ast_stack.back(), @1, @7); ast_stack.pop_back(); - } | - TOK_MSG_TASKS { - AstNode *node = new AstNode(AST_TECALL); - node->str = *$1; - delete $1; - ast_stack.back()->children.push_back(node); - ast_stack.push_back(node); - } opt_arg_list ';'{ - SET_AST_NODE_LOC(ast_stack.back(), @1, @3); - ast_stack.pop_back(); }; +// result is wrapped in a genblock only if necessary gen_stmt_block: { AstNode *node = new AstNode(AST_GENBLOCK); @@ -2798,7 +2820,7 @@ gen_stmt_block: } gen_stmt_or_module_body_stmt { SET_AST_NODE_LOC(ast_stack.back(), @2, @2); ast_stack.pop_back(); - }; + } | gen_block; opt_gen_else: TOK_ELSE gen_stmt_block | %empty %prec FAKE_THEN; |