From ecc22f7fedfa639482dbc55a05709da85116a60f Mon Sep 17 00:00:00 2001 From: Peter Crozier Date: Mon, 23 Mar 2020 20:07:22 +0000 Subject: [PATCH] Support module/package/interface/block scope for typedef names. --- README.md | 2 -- frontends/verilog/verilog_frontend.cc | 3 +- frontends/verilog/verilog_frontend.h | 5 +-- frontends/verilog/verilog_lexer.l | 17 +++++++-- frontends/verilog/verilog_parser.y | 51 +++++++++++++++++++-------- tests/svtypes/typedef_scopes.sv | 7 ++++ 6 files changed, 63 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index d1f7ddf8e..ce7b26411 100644 --- a/README.md +++ b/README.md @@ -541,8 +541,6 @@ from SystemVerilog: SystemVerilog files being read into the same design afterwards. - typedefs are supported (including inside packages) - - type identifiers must currently be enclosed in (parentheses) when declaring - signals of that type (this is syntactically incorrect SystemVerilog) - type casts are currently not supported - enums are supported (including inside packages) diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc index f2c1c227f..1c88d479b 100644 --- a/frontends/verilog/verilog_frontend.cc +++ b/frontends/verilog/verilog_frontend.cc @@ -51,7 +51,6 @@ static void add_package_types(std::map &user_types, { // prime the parser's user type lookup table with the package qualified names // of typedefed names in the packages seen so far. - user_types.clear(); for (const auto &pkg : package_list) { log_assert(pkg->type==AST::AST_PACKAGE); for (const auto &node: pkg->children) { @@ -61,6 +60,8 @@ static void add_package_types(std::map &user_types, } } } + user_type_stack.clear(); + user_type_stack.push_back(new UserTypeMap()); } struct VerilogFrontend : public Frontend { diff --git a/frontends/verilog/verilog_frontend.h b/frontends/verilog/verilog_frontend.h index 73ea51e6c..caa6246ef 100644 --- a/frontends/verilog/verilog_frontend.h +++ b/frontends/verilog/verilog_frontend.h @@ -45,8 +45,9 @@ namespace VERILOG_FRONTEND // this function converts a Verilog constant to an AST_CONSTANT node AST::AstNode *const2ast(std::string code, char case_type = 0, bool warn_z = false); - // names of locally typedef'ed types - extern std::map user_types; + // names of locally typedef'ed types in a stack + typedef std::map UserTypeMap; + extern std::vector user_type_stack; // names of package typedef'ed types extern std::map pkg_user_types; diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 74e8dce7f..bccdf4841 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -99,6 +99,18 @@ YYLTYPE old_location; #define YY_BUF_SIZE 65536 extern int frontend_verilog_yylex(YYSTYPE *yylval_param, YYLTYPE *yyloc_param); + +static bool isUserType(std::string &s) +{ + // 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(s) > 0) { + return true; + } + } + return false; +} + %} %option yylineno @@ -376,7 +388,7 @@ supply1 { return TOK_SUPPLY1; } // package qualifier auto s = std::string("\\") + yytext; if (pkg_user_types.count(s) > 0) { - // found it + // package qualified typedefed name yylval->string = new std::string(s); return TOK_USER_TYPE; } @@ -391,7 +403,8 @@ supply1 { return TOK_SUPPLY1; } [a-zA-Z_$][a-zA-Z0-9_$]* { auto s = std::string("\\") + yytext; - if (user_types.count(s) > 0) { + if (isUserType(s)) { + // previously typedefed name yylval->string = new std::string(s); return TOK_USER_TYPE; } diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index f7e3afd13..1a195bbfd 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -54,7 +54,7 @@ namespace VERILOG_FRONTEND { std::map *attr_list, default_attr_list; std::stack *> attr_list_stack; std::map *albuf; - std::map user_types; + std::vector user_type_stack; std::map pkg_user_types; std::vector ast_stack; struct AstNode *astbuf1, *astbuf2, *astbuf3; @@ -130,14 +130,10 @@ struct specify_rise_fall { static void addTypedefNode(std::string *name, AstNode *node) { log_assert(node); - // seems to be support for local scoped typedefs in simplify() - // and tests redefine types. - //if (user_types.count(*name) > 0) { - // frontend_verilog_yyerror("Type already defined."); - //} auto *tnode = new AstNode(AST_TYPEDEF, node); tnode->str = *name; - 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); @@ -147,6 +143,17 @@ static void addTypedefNode(std::string *name, AstNode *node) ast_stack.back()->children.push_back(tnode); } +static void enterTypeScope() +{ + auto user_types = new UserTypeMap(); + user_type_stack.push_back(user_types); +} + +static void exitTypeScope() +{ + user_type_stack.pop_back(); +} + static AstNode *makeRange(int msb = 31, int lsb = 0, bool isSigned = true) { auto range = new AstNode(AST_RANGE); @@ -359,7 +366,7 @@ hierarchical_type_id: ; module: - attr TOK_MODULE TOK_ID { + attr module_start TOK_ID { do_not_require_port_stubs = false; AstNode *mod = new AstNode(AST_MODULE); ast_stack.back()->children.push_back(mod); @@ -378,9 +385,12 @@ module: ast_stack.pop_back(); log_assert(ast_stack.size() == 1); current_ast_mod = NULL; - user_types.clear(); + exitTypeScope(); }; +module_start: TOK_MODULE { enterTypeScope(); } + ; + module_para_opt: '#' '(' { astbuf1 = nullptr; } module_para_list { if (astbuf1) delete astbuf1; } ')' | /* empty */; @@ -482,7 +492,7 @@ module_arg: }; package: - attr TOK_PACKAGE TOK_ID { + attr package_start TOK_ID { AstNode *mod = new AstNode(AST_PACKAGE); ast_stack.back()->children.push_back(mod); ast_stack.push_back(mod); @@ -492,9 +502,12 @@ package: } ';' package_body TOK_ENDPACKAGE { ast_stack.pop_back(); current_ast_mod = NULL; - user_types.clear(); + exitTypeScope(); }; +package_start: TOK_PACKAGE { enterTypeScope(); } + ; + package_body: package_body package_body_stmt | // optional @@ -505,7 +518,7 @@ package_body_stmt: localparam_decl; interface: - TOK_INTERFACE TOK_ID { + interface_start TOK_ID { do_not_require_port_stubs = false; AstNode *intf = new AstNode(AST_INTERFACE); ast_stack.back()->children.push_back(intf); @@ -522,9 +535,12 @@ interface: ast_stack.pop_back(); log_assert(ast_stack.size() == 1); current_ast_mod = NULL; - user_types.clear(); + exitTypeScope(); }; +interface_start: TOK_INTERFACE { enterTypeScope(); } + ; + interface_body: interface_body interface_body_stmt |; @@ -2210,7 +2226,7 @@ behavioral_stmt: } opt_arg_list ';'{ ast_stack.pop_back(); } | - attr TOK_BEGIN opt_label { + attr begin opt_label { AstNode *node = new AstNode(AST_BLOCK); ast_stack.back()->children.push_back(node); ast_stack.push_back(node); @@ -2218,6 +2234,7 @@ behavioral_stmt: if ($3 != NULL) node->str = *$3; } behavioral_stmt_list 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); if ($3 != NULL) @@ -2301,6 +2318,9 @@ behavioral_stmt: ast_stack.pop_back(); }; +begin: TOK_BEGIN { enterTypeScope(); } + ; + unique_case_attr: /* empty */ { $$ = false; @@ -2516,12 +2536,13 @@ gen_stmt: case_type_stack.pop_back(); ast_stack.pop_back(); } | - TOK_BEGIN opt_label { + begin opt_label { AstNode *node = new AstNode(AST_GENBLOCK); node->str = $2 ? *$2 : std::string(); ast_stack.back()->children.push_back(node); ast_stack.push_back(node); } module_gen_body TOK_END opt_label { + exitTypeScope(); if ($2 != NULL) delete $2; if ($6 != NULL) diff --git a/tests/svtypes/typedef_scopes.sv b/tests/svtypes/typedef_scopes.sv index d41a58147..5507d84f2 100644 --- a/tests/svtypes/typedef_scopes.sv +++ b/tests/svtypes/typedef_scopes.sv @@ -31,5 +31,12 @@ module top; always @(*) assert(inner_i2 == 4'h2); always @(*) assert(inner_enum2 == 3'h4); +endmodule + +typedef logic[7:0] between_t; +module other; + between_t a = 8'h42; + always @(*) assert(a == 8'h42); endmodule + -- 2.30.2