From d738b2c1272b02d8799e9feda83b1eae8ba10c07 Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Tue, 2 Mar 2021 10:43:53 -0500 Subject: sv: support for parameters without default values - Modules with a parameter without a default value will be automatically deferred until the hierarchy pass - Allows for parameters without defaults as module items, rather than just int the `parameter_port_list`, despite being forbidden in the LRM - Check for parameters without defaults that haven't been overriden - Add location info to parameter/localparam declarations --- frontends/verilog/verilog_parser.y | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'frontends/verilog/verilog_parser.y') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index bcba9b76a..ea8cc0765 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -1462,7 +1462,26 @@ param_decl_list: single_param_decl | param_decl_list ',' single_param_decl; single_param_decl: - TOK_ID '=' expr { + single_param_decl_ident '=' expr { + AstNode *decl = ast_stack.back()->children.back(); + log_assert(decl->type == AST_PARAMETER || decl->type == AST_LOCALPARAM); + delete decl->children[0]; + decl->children[0] = $3; + } | + single_param_decl_ident { + AstNode *decl = ast_stack.back()->children.back(); + if (decl->type != AST_PARAMETER) { + log_assert(decl->type == AST_LOCALPARAM); + frontend_verilog_yyerror("localparam initialization is missing!"); + } + if (!sv_mode) + frontend_verilog_yyerror("Parameter defaults can only be omitted in SystemVerilog mode!"); + delete decl->children[0]; + decl->children.erase(decl->children.begin()); + }; + +single_param_decl_ident: + TOK_ID { AstNode *node; if (astbuf1 == nullptr) { if (!sv_mode) @@ -1473,10 +1492,9 @@ single_param_decl: node = astbuf1->clone(); } node->str = *$1; - delete node->children[0]; - node->children[0] = $3; ast_stack.back()->children.push_back(node); delete $1; + SET_AST_NODE_LOC(node, @1, @1); }; defparam_decl: -- cgit v1.2.3 From 4f4e70876f06738fa7dda24e01ac296fe318264a Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Thu, 18 Mar 2021 13:38:25 -0400 Subject: sv: allow typenames as function return types --- frontends/verilog/verilog_parser.y | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'frontends/verilog/verilog_parser.y') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index ea8cc0765..91b7afddf 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -861,6 +861,7 @@ task_func_decl: outreg->children.push_back($4); outreg->is_signed = $4->is_signed; $4->is_signed = false; + outreg->is_custom_type = $4->type == AST_WIRETYPE; } current_function_or_task->children.push_back(outreg); current_function_or_task_port_id = 1; @@ -871,6 +872,11 @@ task_func_decl: }; func_return_type: + hierarchical_type_id { + $$ = new AstNode(AST_WIRETYPE); + $$->str = *$1; + delete $1; + } | opt_type_vec opt_signedness_default_unsigned { $$ = makeRange(0, 0, $2); } | -- cgit v1.2.3 From 92d5550a90558a0292c8ac63cecabb2de30eb6aa Mon Sep 17 00:00:00 2001 From: Xiretza Date: Thu, 18 Mar 2021 21:53:02 +0100 Subject: verilog: check entire user type stack for type definition --- frontends/verilog/verilog_parser.y | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'frontends/verilog/verilog_parser.y') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 91b7afddf..e4b3258c2 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -163,12 +163,18 @@ static bool isInLocalScope(const std::string *name) static AstNode *getTypeDefinitionNode(std::string type_name) { - // return the definition nodes from the typedef statement - auto user_types = user_type_stack.back(); - log_assert(user_types->count(type_name) > 0); - auto typedef_node = (*user_types)[type_name]; - log_assert(typedef_node->type == AST_TYPEDEF); - return typedef_node->children[0]; + // check current scope then outer scopes for a name + for (auto it = user_type_stack.rbegin(); it != user_type_stack.rend(); ++it) { + if ((*it)->count(type_name) > 0) { + // return the definition nodes from the typedef statement + auto typedef_node = (**it)[type_name]; + log_assert(typedef_node->type == AST_TYPEDEF); + return typedef_node->children[0]; + } + } + + // The lexer recognized the name as a TOK_USER_TYPE, but now we can't find it anymore? + log_error("typedef for user type `%s' not found", type_name.c_str()); } static AstNode *copyTypeDefinition(std::string type_name) -- cgit v1.2.3 From 445208086121ea343bdb80a9998637361c841bea Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Mon, 10 May 2021 11:06:02 -0400 Subject: sv: check validity of package end label --- frontends/verilog/verilog_parser.y | 2 ++ 1 file changed, 2 insertions(+) (limited to 'frontends/verilog/verilog_parser.y') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index e4b3258c2..dd25f412f 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -579,6 +579,8 @@ package: append_attr(mod, $1); } ';' package_body TOK_ENDPACKAGE opt_label { ast_stack.pop_back(); + if ($4 != NULL && $9 != NULL && *$4 != *$9) + frontend_verilog_yyerror("Package name (%s) and end label (%s) don't match.", $4->c_str()+1, $9->c_str()+1); current_ast_mod = NULL; exitTypeScope(); }; -- cgit v1.2.3 From 15f35d6754af619accdf63030e0a5ad3085cec16 Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Sat, 27 Mar 2021 15:59:48 -0400 Subject: sv: support remaining assignment operators - Add support for: *=, /=, %=, <<=, >>=, <<<=, >>>= - Unify existing support for: +=, -=, &=, |=, ^= --- frontends/verilog/verilog_parser.y | 68 +++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 38 deletions(-) (limited to 'frontends/verilog/verilog_parser.y') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index dd25f412f..c2b43f45b 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -260,6 +260,7 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode) bool boolean; char ch; int integer; + YOSYS_NAMESPACE_PREFIX AST::AstNodeType ast_node_type; } %token TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE @@ -272,7 +273,7 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode) %token TOK_PACKAGE TOK_ENDPACKAGE TOK_PACKAGESEP %token TOK_INTERFACE TOK_ENDINTERFACE TOK_MODPORT TOK_VAR TOK_WILDCARD_CONNECT %token TOK_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_WAND TOK_WOR TOK_REG TOK_LOGIC -%token TOK_INTEGER TOK_SIGNED TOK_ASSIGN TOK_PLUS_ASSIGN TOK_ALWAYS TOK_INITIAL +%token TOK_INTEGER TOK_SIGNED TOK_ASSIGN TOK_ALWAYS TOK_INITIAL %token TOK_ALWAYS_FF TOK_ALWAYS_COMB TOK_ALWAYS_LATCH %token TOK_BEGIN TOK_END TOK_IF TOK_ELSE TOK_FOR TOK_WHILE TOK_REPEAT %token TOK_DPI_FUNCTION TOK_POSEDGE TOK_NEGEDGE TOK_OR TOK_AUTOMATIC @@ -286,7 +287,9 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode) %token TOK_RAND TOK_CONST TOK_CHECKER TOK_ENDCHECKER TOK_EVENTUALLY %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_LONGINT TOK_UNION -%token TOK_OR_ASSIGN TOK_XOR_ASSIGN TOK_AND_ASSIGN TOK_SUB_ASSIGN +%token TOK_BIT_OR_ASSIGN TOK_BIT_AND_ASSIGN TOK_BIT_XOR_ASSIGN TOK_ADD_ASSIGN +%token TOK_SUB_ASSIGN TOK_DIV_ASSIGN TOK_MOD_ASSIGN TOK_MUL_ASSIGN +%token TOK_SHL_ASSIGN TOK_SHR_ASSIGN TOK_SSHL_ASSIGN TOK_SSHR_ASSIGN %type range range_or_multirange non_opt_range non_opt_multirange %type wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list non_io_wire_type io_wire_type @@ -298,6 +301,7 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode) %type integer_atom_type %type attr case_attr %type struct_union +%type asgn_binop %type specify_target %type specify_triple specify_opt_triple @@ -2449,47 +2453,35 @@ simple_behavioral_stmt: SET_AST_NODE_LOC(node, @2, @5); append_attr(node, $1); } | - attr lvalue TOK_XOR_ASSIGN delay expr { - AstNode *xor_node = new AstNode(AST_BIT_XOR, $2->clone(), $5); - AstNode *node = new AstNode(AST_ASSIGN_EQ, $2, xor_node); - SET_AST_NODE_LOC(xor_node, @2, @5); - SET_AST_NODE_LOC(node, @2, @5); - ast_stack.back()->children.push_back(node); - append_attr(node, $1); - } | - attr lvalue TOK_OR_ASSIGN delay expr { - AstNode *or_node = new AstNode(AST_BIT_OR, $2->clone(), $5); - SET_AST_NODE_LOC(or_node, @2, @5); - AstNode *node = new AstNode(AST_ASSIGN_EQ, $2, or_node); - SET_AST_NODE_LOC(node, @2, @5); - ast_stack.back()->children.push_back(node); - append_attr(node, $1); - } | - attr lvalue TOK_PLUS_ASSIGN delay expr { - AstNode *add_node = new AstNode(AST_ADD, $2->clone(), $5); - AstNode *node = new AstNode(AST_ASSIGN_EQ, $2, add_node); - SET_AST_NODE_LOC(node, @2, @5); - SET_AST_NODE_LOC(add_node, @2, @5); - ast_stack.back()->children.push_back(node); - append_attr(node, $1); - } | - attr lvalue TOK_SUB_ASSIGN delay expr { - AstNode *sub_node = new AstNode(AST_SUB, $2->clone(), $5); - AstNode *node = new AstNode(AST_ASSIGN_EQ, $2, sub_node); - SET_AST_NODE_LOC(node, @2, @5); - SET_AST_NODE_LOC(sub_node, @2, @5); - ast_stack.back()->children.push_back(node); - append_attr(node, $1); - } | - attr lvalue TOK_AND_ASSIGN delay expr { - AstNode *and_node = new AstNode(AST_BIT_AND, $2->clone(), $5); - AstNode *node = new AstNode(AST_ASSIGN_EQ, $2, and_node); + attr lvalue asgn_binop delay expr { + AstNode *expr_node = $5; + if ($3 == AST_SHIFT_LEFT || $3 == AST_SHIFT_RIGHT || + $3 == AST_SHIFT_SLEFT || $3 == AST_SHIFT_SRIGHT) { + expr_node = new AstNode(AST_TO_UNSIGNED, expr_node); + SET_AST_NODE_LOC(expr_node, @5, @5); + } + AstNode *op_node = new AstNode($3, $2->clone(), expr_node); + AstNode *node = new AstNode(AST_ASSIGN_EQ, $2, op_node); + SET_AST_NODE_LOC(op_node, @2, @5); SET_AST_NODE_LOC(node, @2, @5); - SET_AST_NODE_LOC(and_node, @2, @5); ast_stack.back()->children.push_back(node); append_attr(node, $1); }; +asgn_binop: + TOK_BIT_OR_ASSIGN { $$ = AST_BIT_OR; } | + TOK_BIT_AND_ASSIGN { $$ = AST_BIT_AND; } | + TOK_BIT_XOR_ASSIGN { $$ = AST_BIT_XOR; } | + TOK_ADD_ASSIGN { $$ = AST_ADD; } | + TOK_SUB_ASSIGN { $$ = AST_SUB; } | + TOK_DIV_ASSIGN { $$ = AST_DIV; } | + TOK_MOD_ASSIGN { $$ = AST_MOD; } | + TOK_MUL_ASSIGN { $$ = AST_MUL; } | + TOK_SHL_ASSIGN { $$ = AST_SHIFT_LEFT; } | + TOK_SHR_ASSIGN { $$ = AST_SHIFT_RIGHT; } | + TOK_SSHL_ASSIGN { $$ = AST_SHIFT_SLEFT; } | + TOK_SSHR_ASSIGN { $$ = AST_SHIFT_SRIGHT; } ; + // this production creates the obligatory if-else shift/reduce conflict behavioral_stmt: defattr | assert | wire_decl | param_decl | localparam_decl | typedef_decl | -- cgit v1.2.3 From 8cfed1a97957e4c096d1e0a0304d978bcb27e116 Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Thu, 27 May 2021 16:47:02 -0400 Subject: sv: support tasks and functions within packages --- frontends/verilog/verilog_parser.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends/verilog/verilog_parser.y') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index c2b43f45b..93ddbec91 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -593,7 +593,7 @@ package_body: package_body package_body_stmt | %empty; package_body_stmt: - typedef_decl | localparam_decl | param_decl; + typedef_decl | localparam_decl | param_decl | task_func_decl; interface: TOK_INTERFACE { -- cgit v1.2.3 From 72787f52fc31954e4b7dc3dc34d86705fc4e9dd1 Mon Sep 17 00:00:00 2001 From: Claire Xenia Wolf Date: Tue, 8 Jun 2021 00:39:36 +0200 Subject: Fixing old e-mail addresses and deadnames s/((Claire|Xen|Xenia|Clifford)\s+)+(Wolf|Xen)\s+<(claire|clifford)@(symbioticeda.com|clifford.at|yosyshq.com)>/Claire Xenia Wolf /gi; s/((Nina|Nak|N\.)\s+)+Engelhardt\s+/N. Engelhardt /gi; s/((David)\s+)+Shah\s+<(dave|david)@(symbioticeda.com|yosyshq.com|ds0.me)>/David Shah /gi; s/((Miodrag)\s+)+Milanovic\s+<(miodrag|micko)@(symbioticeda.com|yosyshq.com)>/Miodrag Milanovic /gi; s,https?://www.clifford.at/yosys/,http://yosyshq.net/yosys/,g; --- frontends/verilog/verilog_parser.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends/verilog/verilog_parser.y') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 93ddbec91..10d904dbd 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -1,7 +1,7 @@ /* * yosys -- Yosys Open SYnthesis Suite * - * Copyright (C) 2012 Clifford Wolf + * Copyright (C) 2012 Claire Xenia Wolf * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above -- cgit v1.2.3 From 801ecc0e1d75f092981361632265edce67130a73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcelina=20Ko=C5=9Bcielnicka?= Date: Mon, 14 Jun 2021 16:28:10 +0200 Subject: verilog: Squash a memory leak. That was added in ecc22f7fedfa639482dbc55a05709da85116a60f --- frontends/verilog/verilog_parser.y | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'frontends/verilog/verilog_parser.y') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 10d904dbd..3f4bf5bfd 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -54,7 +54,7 @@ namespace VERILOG_FRONTEND { dict *attr_list, default_attr_list; std::stack *> attr_list_stack; dict *albuf; - std::vector user_type_stack; + std::vector user_type_stack; dict pkg_user_types; std::vector ast_stack; struct AstNode *astbuf1, *astbuf2, *astbuf3; @@ -132,8 +132,8 @@ static void addTypedefNode(std::string *name, AstNode *node) log_assert(node); auto *tnode = new AstNode(AST_TYPEDEF, node); tnode->str = *name; - auto user_types = user_type_stack.back(); - (*user_types)[*name] = tnode; + auto &user_types = user_type_stack.back(); + user_types[*name] = tnode; if (current_ast_mod && current_ast_mod->type == AST_PACKAGE) { // typedef inside a package so we need the qualified name auto qname = current_ast_mod->str + "::" + (*name).substr(1); @@ -145,8 +145,7 @@ static void addTypedefNode(std::string *name, AstNode *node) static void enterTypeScope() { - auto user_types = new UserTypeMap(); - user_type_stack.push_back(user_types); + user_type_stack.push_back(UserTypeMap()); } static void exitTypeScope() @@ -157,17 +156,17 @@ static void exitTypeScope() static bool isInLocalScope(const std::string *name) { // tests if a name was declared in the current block scope - auto user_types = user_type_stack.back(); - return (user_types->count(*name) > 0); + auto &user_types = user_type_stack.back(); + return (user_types.count(*name) > 0); } static AstNode *getTypeDefinitionNode(std::string type_name) { // check current scope then outer scopes for a name for (auto it = user_type_stack.rbegin(); it != user_type_stack.rend(); ++it) { - if ((*it)->count(type_name) > 0) { + if (it->count(type_name) > 0) { // return the definition nodes from the typedef statement - auto typedef_node = (**it)[type_name]; + auto typedef_node = (*it)[type_name]; log_assert(typedef_node->type == AST_TYPEDEF); return typedef_node->children[0]; } -- cgit v1.2.3 From 091295a5a533c44a4ad20d297fdad1ec2a77903c Mon Sep 17 00:00:00 2001 From: Xiretza Date: Tue, 16 Mar 2021 16:43:03 +0100 Subject: verilog: fix leaking ASTNodes --- frontends/verilog/verilog_parser.y | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'frontends/verilog/verilog_parser.y') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 3f4bf5bfd..4e601b51d 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -503,18 +503,19 @@ optional_comma: module_arg_opt_assignment: '=' expr { if (ast_stack.back()->children.size() > 0 && ast_stack.back()->children.back()->type == AST_WIRE) { - AstNode *wire = new AstNode(AST_IDENTIFIER); - wire->str = ast_stack.back()->children.back()->str; if (ast_stack.back()->children.back()->is_input) { AstNode *n = ast_stack.back()->children.back(); if (n->attributes.count(ID::defaultvalue)) delete n->attributes.at(ID::defaultvalue); n->attributes[ID::defaultvalue] = $2; - } else - if (ast_stack.back()->children.back()->is_reg || ast_stack.back()->children.back()->is_logic) - ast_stack.back()->children.push_back(new AstNode(AST_INITIAL, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_LE, wire, $2)))); - else - ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, $2)); + } else { + AstNode *wire = new AstNode(AST_IDENTIFIER); + wire->str = ast_stack.back()->children.back()->str; + if (ast_stack.back()->children.back()->is_reg || ast_stack.back()->children.back()->is_logic) + ast_stack.back()->children.push_back(new AstNode(AST_INITIAL, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_LE, wire, $2)))); + else + ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, $2)); + } } else frontend_verilog_yyerror("SystemVerilog interface in module port list cannot have a default value."); } | @@ -1158,6 +1159,8 @@ specify_item: cell->children.back()->str = "\\DST"; delete $1; + delete limit; + delete limit2; }; specify_opt_triple: -- cgit v1.2.3 From b57e47fad8b4ecd5438ee49c618fc8978a4bb058 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Thu, 18 Mar 2021 10:38:36 +0100 Subject: verilog: fix wildcard port connections leaking memory --- frontends/verilog/verilog_parser.y | 1 + 1 file changed, 1 insertion(+) (limited to 'frontends/verilog/verilog_parser.y') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 4e601b51d..7d750ea28 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -2084,6 +2084,7 @@ cell_port: if (!sv_mode) frontend_verilog_yyerror("Wildcard port connections are only supported in SystemVerilog mode."); astbuf2->attributes[ID::wildcard_port_conns] = AstNode::mkconst_int(1, false); + free_attr($1); }; always_comb_or_latch: -- cgit v1.2.3 From c6681508f1a2e35d41e8fc6f1f5dec41972ef6fd Mon Sep 17 00:00:00 2001 From: Xiretza Date: Thu, 18 Mar 2021 21:52:06 +0100 Subject: verilog: fix leaking of type names in parser --- frontends/verilog/verilog_parser.y | 2 ++ 1 file changed, 2 insertions(+) (limited to 'frontends/verilog/verilog_parser.y') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 7d750ea28..1a76d0dea 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -692,6 +692,7 @@ wire_type_token: astbuf3->is_custom_type = true; astbuf3->children.push_back(new AstNode(AST_WIRETYPE)); astbuf3->children.back()->str = *$1; + delete $1; } | TOK_WOR { astbuf3->is_wor = true; @@ -1458,6 +1459,7 @@ param_type: astbuf1->is_custom_type = true; astbuf1->children.push_back(new AstNode(AST_WIRETYPE)); astbuf1->children.back()->str = *$1; + delete $1; }; param_decl: -- cgit v1.2.3 From f2c2d73f36d7aaef90ded549143d1ee0c4d4a9f5 Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Mon, 14 Jun 2021 15:32:01 -0400 Subject: sv: fix up end label checking - disallow [gen]blocks with an end label but not begin label - check validity of module end label - fix memory leak of package name and end label - fix memory leak of module end label --- frontends/verilog/verilog_parser.y | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'frontends/verilog/verilog_parser.y') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 1a76d0dea..120a8bca3 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -235,6 +235,16 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode) node->children.push_back(rangeNode); } +static void checkLabelsMatch(const char *element, const std::string *before, const std::string *after) +{ + if (!before && after) + frontend_verilog_yyerror("%s missing where end label (%s) was given.", + element, after->c_str() + 1); + if (before && after && *before != *after) + frontend_verilog_yyerror("%s (%s) and end label (%s) don't match.", + element, before->c_str() + 1, after->c_str() + 1); +} + %} %define api.prefix {frontend_verilog_yy} @@ -457,7 +467,6 @@ module: port_counter = 0; mod->str = *$4; append_attr(mod, $1); - delete $4; } module_para_opt module_args_opt ';' module_body TOK_ENDMODULE opt_label { if (port_stubs.size() != 0) frontend_verilog_yyerror("Missing details for module port `%s'.", @@ -465,7 +474,10 @@ module: SET_AST_NODE_LOC(ast_stack.back(), @2, @$); ast_stack.pop_back(); log_assert(ast_stack.size() == 1); + checkLabelsMatch("Module name", $4, $11); current_ast_mod = NULL; + delete $4; + delete $11; exitTypeScope(); }; @@ -583,9 +595,10 @@ package: append_attr(mod, $1); } ';' package_body TOK_ENDPACKAGE opt_label { ast_stack.pop_back(); - if ($4 != NULL && $9 != NULL && *$4 != *$9) - frontend_verilog_yyerror("Package name (%s) and end label (%s) don't match.", $4->c_str()+1, $9->c_str()+1); + checkLabelsMatch("Package name", $4, $9); current_ast_mod = NULL; + delete $4; + delete $9; exitTypeScope(); }; @@ -2526,8 +2539,7 @@ behavioral_stmt: node->str = *$4; } behavioral_stmt_list TOK_END opt_label { 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); + checkLabelsMatch("Begin label", $4, $8); AstNode *node = ast_stack.back(); // In SystemVerilog, unnamed blocks with block item declarations // create an implicit hierarchy scope @@ -2863,8 +2875,7 @@ gen_block: 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); + checkLabelsMatch("Begin label", $3, $7); delete $3; delete $7; SET_AST_NODE_LOC(ast_stack.back(), @1, @7); -- cgit v1.2.3 From 4446cfa524cf06e84add450214f64b2de6e199c3 Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Thu, 17 Jun 2021 15:59:59 -0400 Subject: sv: fix a few struct and enum memory leaks --- frontends/verilog/verilog_parser.y | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'frontends/verilog/verilog_parser.y') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 120a8bca3..9558b0e87 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -1711,10 +1711,12 @@ member_type_token: delete astbuf1; astbuf1 = template_node; } - | struct_union { + | { + delete astbuf1; + } struct_union { // stash state on ast_stack ast_stack.push_back(astbuf2); - astbuf2 = $1; + astbuf2 = $2; } struct_body { astbuf1 = astbuf2; // recover state -- cgit v1.2.3 From 414154dd275b8cf9f0ffa071d12fc20fd6fee503 Mon Sep 17 00:00:00 2001 From: Rupert Swarbrick Date: Thu, 21 May 2020 17:36:29 +0100 Subject: Add support for parsing the SystemVerilog 'bind' construct This doesn't do anything useful yet: the patch just adds support for the syntax to the lexer and parser and adds some tests to check the syntax parses properly. This generates AST nodes, but doesn't yet generate RTLIL. Since our existing hierarchical_identifier parser doesn't allow bit selects (so you can't do something like foo[1].bar[2].baz), I've also not added support for a trailing bit select (the "constant_bit_select" non-terminal in "bind_target_instance" in the spec). If we turn out to need this in future, we'll want to augment hierarchical_identifier and its other users too. Note that you can't easily use the BNF from the spec: bind_directive ::= "bind" bind_target_scope [ : bind_target_instance_list] bind_instantiation ; | "bind" bind_target_instance bind_instantiation ; even if you fix the lookahead problem, because code like this matches both branches in the BNF: bind a b b_i (.*); The problem is that 'a' could either be a module name or a degenerate hierarchical reference. This seems to be a genuine syntactic ambiguity, which the spec resolves (p739) by saying that we have to wait until resolution time (the hierarchy pass) and take whatever is defined, treating 'a' as an instance name if it names both an instance and a module. To keep the parser simple, it currently accepts this invalid syntax: bind a.b : c d e (.*); This is invalid because we're in the first branch of the BNF above, so the "a.b" term should match bind_target_scope: a module or interface identifier, not an arbitrary hierarchical identifier. This will fail in the hierarchy pass (when it's implemented in a future patch). --- frontends/verilog/verilog_parser.y | 77 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 3 deletions(-) (limited to 'frontends/verilog/verilog_parser.y') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 9558b0e87..de463b47d 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -299,6 +299,7 @@ static void checkLabelsMatch(const char *element, const std::string *before, con %token TOK_BIT_OR_ASSIGN TOK_BIT_AND_ASSIGN TOK_BIT_XOR_ASSIGN TOK_ADD_ASSIGN %token TOK_SUB_ASSIGN TOK_DIV_ASSIGN TOK_MOD_ASSIGN TOK_MUL_ASSIGN %token TOK_SHL_ASSIGN TOK_SHR_ASSIGN TOK_SSHL_ASSIGN TOK_SSHR_ASSIGN +%token TOK_BIND %type range range_or_multirange non_opt_range non_opt_multirange %type wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list non_io_wire_type io_wire_type @@ -364,6 +365,7 @@ design: typedef_decl design | package design | interface design | + bind_directive design | %empty; attr: @@ -636,7 +638,67 @@ interface_body: interface_body_stmt: param_decl | localparam_decl | typedef_decl | defparam_decl | wire_decl | always_stmt | assign_stmt | - modport_stmt; + modport_stmt | bind_directive; + +bind_directive: + TOK_BIND { + AstNode *bnode = new AstNode(AST_BIND); + ast_stack.back()->children.push_back(bnode); + ast_stack.push_back(bnode); + } + bind_target { + // bind_target should have added at least one child + log_assert(ast_stack.back()->children.size() >= 1); + } + TOK_ID { + // The single_cell parser in cell_list_no_array uses astbuf1 as + // a sort of template for constructing cells. + astbuf1 = new AstNode(AST_CELL); + astbuf1->children.push_back(new AstNode(AST_CELLTYPE)); + astbuf1->children[0]->str = *$5; + delete $5; + } + cell_parameter_list_opt cell_list_no_array ';' { + // cell_list should have added at least one more child + log_assert(ast_stack.back()->children.size() >= 2); + delete astbuf1; + ast_stack.pop_back(); + }; + +// bind_target matches the target of the bind (everything before +// bind_instantiation in the IEEE 1800 spec). +// +// We can't use the BNF from the spec directly because it's ambiguous: +// something like "bind foo bar_i (.*)" can either be interpreted with "foo" as +// a module or interface identifier (matching bind_target_scope in the spec) or +// by considering foo as a degenerate hierarchical identifier with no '.' +// characters, followed by no bit select (which matches bind_target_instance in +// the spec). +// +// Instead, we resolve everything as an instance name and then deal with the +// ambiguity when converting to RTLIL / in the hierarchy pass. +bind_target: + bind_target_instance opt_bind_target_instance_list; + +// An optional list of target instances for a bind statement, introduced by a +// colon. +opt_bind_target_instance_list: + ':' bind_target_instance_list | + %empty; + +bind_target_instance_list: + bind_target_instance | + bind_target_instance_list ',' bind_target_instance; + +// A single target instance for a bind statement. The top of ast_stack will be +// the bind node where we should add it. +bind_target_instance: + hierarchical_id { + auto *node = new AstNode(AST_IDENTIFIER); + node->str = *$1; + delete $1; + ast_stack.back()->children.push_back(node); + }; mintypmax_expr: expr { delete $1; } | @@ -813,7 +875,7 @@ module_body: module_body_stmt: task_func_decl | specify_block | param_decl | localparam_decl | typedef_decl | defparam_decl | specparam_declaration | wire_decl | assign_stmt | cell_stmt | - enum_decl | struct_decl | + enum_decl | struct_decl | bind_directive | always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property | checker_decl | ignored_specify_block; checker_decl: @@ -1975,6 +2037,9 @@ cell_list: cell_list ',' single_cell; single_cell: + single_cell_no_array | single_cell_arraylist; + +single_cell_no_array: TOK_ID { astbuf2 = astbuf1->clone(); if (astbuf2->type != AST_PRIMITIVE) @@ -1983,7 +2048,9 @@ single_cell: ast_stack.back()->children.push_back(astbuf2); } '(' cell_port_list ')' { SET_AST_NODE_LOC(astbuf2, @1, @$); - } | + } + +single_cell_arraylist: TOK_ID non_opt_range { astbuf2 = astbuf1->clone(); if (astbuf2->type != AST_PRIMITIVE) @@ -1994,6 +2061,10 @@ single_cell: SET_AST_NODE_LOC(astbuf2, @1, @$); }; +cell_list_no_array: + single_cell_no_array | + cell_list_no_array ',' single_cell_no_array; + prim_list: single_prim | prim_list ',' single_prim; -- cgit v1.2.3 From 681a1c07e52dc82449501f4939e6312f593449bd Mon Sep 17 00:00:00 2001 From: Michael Singer Date: Thu, 5 Aug 2021 21:02:35 +0200 Subject: Allow optional comma after last entry in enum --- frontends/verilog/verilog_parser.y | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'frontends/verilog/verilog_parser.y') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index de463b47d..a5227cb09 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -1624,17 +1624,18 @@ enum_type: TOK_ENUM { // create the template for the names astbuf1 = new AstNode(AST_ENUM_ITEM); astbuf1->children.push_back(AstNode::mkconst_int(0, true)); - } enum_base_type '{' enum_name_list '}' { // create template for the enum vars - auto tnode = astbuf1->clone(); - delete astbuf1; - astbuf1 = tnode; - tnode->type = AST_WIRE; - tnode->attributes[ID::enum_type] = AstNode::mkconst_str(astbuf2->str); - // drop constant but keep any range - delete tnode->children[0]; - tnode->children.erase(tnode->children.begin()); - $$ = astbuf1; } - ; + } enum_base_type '{' enum_name_list optional_comma '}' { + // create template for the enum vars + auto tnode = astbuf1->clone(); + delete astbuf1; + astbuf1 = tnode; + tnode->type = AST_WIRE; + tnode->attributes[ID::enum_type] = AstNode::mkconst_str(astbuf2->str); + // drop constant but keep any range + delete tnode->children[0]; + tnode->children.erase(tnode->children.begin()); + $$ = astbuf1; + }; enum_base_type: type_atom type_signing | type_vec type_signing range { if ($3) astbuf1->children.push_back($3); } -- cgit v1.2.3 From 979053855c85b72c6344bf6350fb9a8360f3d092 Mon Sep 17 00:00:00 2001 From: Brett Witherspoon Date: Tue, 22 Jun 2021 09:51:41 -0500 Subject: sv: improve support for wire and var with user-defined types - User-defined types must be data types. Using a net type (e.g. wire) is a syntax error. - User-defined types without a net type are always variables (i.e. logic). - Nets and variables can now be explicitly declared using user-defined types: typedef logic [1:0] W; wire W w; typedef logic [1:0] V; var V v; Fixes #2846 --- frontends/verilog/verilog_parser.y | 55 ++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 11 deletions(-) (limited to 'frontends/verilog/verilog_parser.y') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index a5227cb09..b0c16c0f4 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -127,6 +127,15 @@ struct specify_rise_fall { specify_triple fall; }; +static void addWiretypeNode(std::string *name, AstNode *node) +{ + log_assert(node); + node->is_custom_type = true; + node->children.push_back(new AstNode(AST_WIRETYPE)); + node->children.back()->str = *name; + delete name; +} + static void addTypedefNode(std::string *name, AstNode *node) { log_assert(node); @@ -305,10 +314,10 @@ static void checkLabelsMatch(const char *element, const std::string *before, con %type wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list non_io_wire_type io_wire_type %type opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id integral_number %type type_name -%type opt_enum_init enum_type struct_type non_wire_data_type func_return_type +%type opt_enum_init enum_type struct_type enum_struct_type func_return_type typedef_base_type %type opt_property always_comb_or_latch always_or_always_ff %type opt_signedness_default_signed opt_signedness_default_unsigned -%type integer_atom_type +%type integer_atom_type integer_vector_type %type attr case_attr %type struct_union %type asgn_binop @@ -763,12 +772,6 @@ opt_wire_type_token: wire_type_token | %empty; wire_type_token: - hierarchical_type_id { - astbuf3->is_custom_type = true; - astbuf3->children.push_back(new AstNode(AST_WIRETYPE)); - astbuf3->children.back()->str = *$1; - delete $1; - } | TOK_WOR { astbuf3->is_wor = true; } | @@ -812,6 +815,9 @@ logic_type: astbuf3->range_left = $1 - 1; astbuf3->range_right = 0; astbuf3->is_signed = true; + } | + hierarchical_type_id { + addWiretypeNode($1, astbuf3); }; integer_atom_type: @@ -821,6 +827,10 @@ integer_atom_type: TOK_LONGINT { $$ = 64; } | TOK_BYTE { $$ = 8; } ; +integer_vector_type: + TOK_LOGIC { $$ = TOK_LOGIC; } | + TOK_REG { $$ = TOK_REG; } ; + non_opt_range: '[' expr ':' expr ']' { $$ = new AstNode(AST_RANGE); @@ -1985,7 +1995,7 @@ type_name: TOK_ID // first time seen ; typedef_decl: - TOK_TYPEDEF non_io_wire_type range type_name range_or_multirange ';' { + TOK_TYPEDEF typedef_base_type range type_name range_or_multirange ';' { astbuf1 = $2; astbuf2 = checkRange(astbuf1, $3); if (astbuf2) @@ -1998,10 +2008,33 @@ typedef_decl: rewriteAsMemoryNode(astbuf1, $5); } addTypedefNode($4, astbuf1); } - | TOK_TYPEDEF non_wire_data_type type_name ';' { addTypedefNode($3, $2); } + | TOK_TYPEDEF enum_struct_type type_name ';' { addTypedefNode($3, $2); } ; -non_wire_data_type: +typedef_base_type: + hierarchical_type_id { + $$ = new AstNode(AST_WIRE); + $$->is_logic = true; + addWiretypeNode($1, $$); + } | + integer_vector_type opt_signedness_default_unsigned { + $$ = new AstNode(AST_WIRE); + if ($1 == TOK_REG) { + $$->is_reg = true; + } else { + $$->is_logic = true; + } + $$->is_signed = $2; + } | + integer_atom_type opt_signedness_default_signed { + $$ = new AstNode(AST_WIRE); + $$->is_logic = true; + $$->is_signed = $2; + $$->range_left = $1 - 1; + $$->range_right = 0; + }; + +enum_struct_type: enum_type | struct_type ; -- cgit v1.2.3 From f0a52e3dd275ee57a1b3ffd0a734b591bf21f668 Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Mon, 30 Aug 2021 11:35:36 -0600 Subject: 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. --- frontends/verilog/verilog_parser.y | 49 +++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) (limited to 'frontends/verilog/verilog_parser.y') 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); -- cgit v1.2.3 From b2e9717419e9a852f4e64f12891b8e9742900917 Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Tue, 31 Aug 2021 11:45:02 -0600 Subject: sv: support declaration in generate for initialization This is accomplished by generating a unique name for the genvar, renaming references to the genvar only in the loop's initialization, guard, and incrementation, and finally adding a localparam inside the loop body with the original name so that the genvar can be shadowed as expected. --- frontends/verilog/verilog_parser.y | 96 +++++++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) (limited to 'frontends/verilog/verilog_parser.y') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 23404f844..8d0ba4cf6 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -254,6 +254,65 @@ static void checkLabelsMatch(const char *element, const std::string *before, con element, before->c_str() + 1, after->c_str() + 1); } +// This transforms a loop like +// for (genvar i = 0; i < 10; i++) begin : blk +// to +// genvar _i; +// for (_i = 0; _i < 10; _i++) begin : blk +// localparam i = _i; +// where `_i` is actually some auto-generated name. +static void rewriteGenForDeclInit(AstNode *loop) +{ + // check if this generate for loop contains an inline declaration + log_assert(loop->type == AST_GENFOR); + AstNode *decl = loop->children[0]; + if (decl->type == AST_ASSIGN_EQ) + return; + log_assert(decl->type == AST_GENVAR); + log_assert(loop->children.size() == 5); + + // identify each component of the loop + AstNode *init = loop->children[1]; + AstNode *cond = loop->children[2]; + AstNode *incr = loop->children[3]; + AstNode *body = loop->children[4]; + log_assert(init->type == AST_ASSIGN_EQ); + log_assert(incr->type == AST_ASSIGN_EQ); + log_assert(body->type == AST_GENBLOCK); + + // create a unique name for the genvar + std::string old_str = decl->str; + std::string new_str = stringf("$genfordecl$%d$%s", autoidx++, old_str.c_str()); + + // rename and move the genvar declaration to the containing description + decl->str = new_str; + loop->children.erase(loop->children.begin()); + log_assert(current_ast_mod != nullptr); + current_ast_mod->children.push_back(decl); + + // create a new localparam with old name so that the items in the loop + // can simply use the old name and shadow it as necessary + AstNode *indirect = new AstNode(AST_LOCALPARAM); + indirect->str = old_str; + AstNode *ident = new AstNode(AST_IDENTIFIER); + ident->str = new_str; + indirect->children.push_back(ident); + + body->children.insert(body->children.begin(), indirect); + + // only perform the renaming for the initialization, guard, and + // incrementation to enable proper shadowing of the synthetic localparam + std::function substitute = [&](AstNode *node) { + if (node->type == AST_IDENTIFIER && node->str == old_str) + node->str = new_str; + for (AstNode *child : node->children) + substitute(child); + }; + substitute(init); + substitute(cond); + substitute(incr); +} + %} %define api.prefix {frontend_verilog_yy} @@ -321,6 +380,7 @@ static void checkLabelsMatch(const char *element, const std::string *before, con %type attr case_attr %type struct_union %type asgn_binop +%type genvar_identifier %type specify_target %type specify_triple specify_opt_triple @@ -2978,16 +3038,50 @@ gen_stmt_or_module_body_stmt: free_attr($1); }; +genvar_identifier: + TOK_ID { + $$ = new AstNode(AST_IDENTIFIER); + $$->str = *$1; + delete $1; + }; + +genvar_initialization: + TOK_GENVAR genvar_identifier { + frontend_verilog_yyerror("Generate for loop variable declaration is missing initialization!"); + } | + TOK_GENVAR genvar_identifier '=' expr { + if (!sv_mode) + frontend_verilog_yyerror("Generate for loop inline variable declaration is only supported in SystemVerilog mode!"); + AstNode *node = new AstNode(AST_GENVAR); + node->is_reg = true; + node->is_signed = true; + node->range_left = 31; + node->range_right = 0; + node->str = $2->str; + node->children.push_back(checkRange(node, nullptr)); + ast_stack.back()->children.push_back(node); + SET_AST_NODE_LOC(node, @1, @4); + node = new AstNode(AST_ASSIGN_EQ, $2, $4); + ast_stack.back()->children.push_back(node); + SET_AST_NODE_LOC(node, @1, @4); + } | + genvar_identifier '=' expr { + AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, $3); + ast_stack.back()->children.push_back(node); + SET_AST_NODE_LOC(node, @1, @3); + }; + // this production creates the obligatory if-else shift/reduce conflict gen_stmt: TOK_FOR '(' { AstNode *node = new AstNode(AST_GENFOR); ast_stack.back()->children.push_back(node); ast_stack.push_back(node); - } simple_behavioral_stmt ';' expr { + } genvar_initialization ';' expr { ast_stack.back()->children.push_back($6); } ';' simple_behavioral_stmt ')' gen_stmt_block { SET_AST_NODE_LOC(ast_stack.back(), @1, @11); + rewriteGenForDeclInit(ast_stack.back()); ast_stack.pop_back(); } | TOK_IF '(' expr ')' { -- cgit v1.2.3 From 6b7267b849abf7688938e5e53ae7017e8588ff18 Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Mon, 2 Aug 2021 18:42:34 -0600 Subject: verilog: fix multiple AST_PREFIX scope resolution issues - Root AST_PREFIX nodes are now subject to genblk expansion to allow them to refer to a locally-visible generate block - Part selects on AST_PREFIX member leafs can now refer to generate block items (previously would not resolve and raise an error) - Add source location information to AST_PREFIX nodes --- frontends/verilog/verilog_parser.y | 1 + 1 file changed, 1 insertion(+) (limited to 'frontends/verilog/verilog_parser.y') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 8d0ba4cf6..91b1140e9 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -2973,6 +2973,7 @@ rvalue: hierarchical_id '[' expr ']' '.' rvalue { $$ = new AstNode(AST_PREFIX, $3, $6); $$->str = *$1; + SET_AST_NODE_LOC($$, @1, @6); delete $1; } | hierarchical_id range { -- cgit v1.2.3 From d6fe6d4fb62be3bb5ec876f1f56356d757b65a41 Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Fri, 13 Aug 2021 20:51:28 -0700 Subject: sv: support wand and wor of data types This enables the usage of declarations of wand or wor with a base type of logic, integer, or a typename. Note that declarations of nets with 2-state base types is still permitted, in violation of the spec. --- frontends/verilog/verilog_parser.y | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'frontends/verilog/verilog_parser.y') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 91b1140e9..80b40f982 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -832,16 +832,10 @@ opt_wire_type_token: wire_type_token | %empty; wire_type_token: - TOK_WOR { - astbuf3->is_wor = true; + // nets + net_type { } | - TOK_WAND { - astbuf3->is_wand = true; - } | - // wires - TOK_WIRE { - } | - TOK_WIRE logic_type { + net_type logic_type { } | // regs TOK_REG { @@ -868,6 +862,15 @@ wire_type_token: astbuf3->range_right = 0; }; +net_type: + TOK_WOR { + astbuf3->is_wor = true; + } | + TOK_WAND { + astbuf3->is_wand = true; + } | + TOK_WIRE; + logic_type: TOK_LOGIC { } | -- cgit v1.2.3 From 9658d2e337a54fc06873de716d0ae5586ffd869b Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Thu, 23 Sep 2021 13:33:55 -0400 Subject: Fix TOK_ID memory leak in for_initialization --- frontends/verilog/verilog_parser.y | 1 + 1 file changed, 1 insertion(+) (limited to 'frontends/verilog/verilog_parser.y') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 8d0ba4cf6..acb8b996c 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -2674,6 +2674,7 @@ for_initialization: AstNode *node = new AstNode(AST_ASSIGN_EQ, ident, $3); ast_stack.back()->children.push_back(node); SET_AST_NODE_LOC(node, @1, @3); + delete $1; } | non_io_wire_type range TOK_ID { frontend_verilog_yyerror("For loop variable declaration is missing initialization!"); -- cgit v1.2.3 From fbd70f28f044968fd59740e34652071c4ee01218 Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Fri, 1 Oct 2021 14:41:11 -0600 Subject: Specify minimum bison version 3.0+ Yosys works with bison 3.0 (or newer), but not bison 2.7 (the previous release). Ideally, we would require "3" rather than "3.0" to give a better error message, but bison 2.3, which still ships with macOS, does not support major-only version requirements. With this change, building with an outdated bison yields: `frontends/rtlil/rtlil_parser.y:25.10-14: require bison 3.0, but have 2.3`. --- frontends/verilog/verilog_parser.y | 2 ++ 1 file changed, 2 insertions(+) (limited to 'frontends/verilog/verilog_parser.y') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 5eb1115ce..171e098a5 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -33,6 +33,8 @@ * */ +%require "3.0" + %{ #include #include -- cgit v1.2.3