aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--frontends/verilog/verilog_frontend.cc3
-rw-r--r--frontends/verilog/verilog_frontend.h5
-rw-r--r--frontends/verilog/verilog_lexer.l17
-rw-r--r--frontends/verilog/verilog_parser.y51
-rw-r--r--tests/svtypes/typedef_scopes.sv7
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<std::string, AST::AstNode *> &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<std::string, AST::AstNode *> &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<std::string, AST::AstNode*> user_types;
+ // names of locally typedef'ed types in a stack
+ typedef std::map<std::string, AST::AstNode*> UserTypeMap;
+ extern std::vector<UserTypeMap *> user_type_stack;
// names of package typedef'ed types
extern std::map<std::string, AST::AstNode*> 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<std::string, AstNode*> *attr_list, default_attr_list;
std::stack<std::map<std::string, AstNode*> *> attr_list_stack;
std::map<std::string, AstNode*> *albuf;
- std::map<std::string, AstNode*> user_types;
+ std::vector<UserTypeMap*> user_type_stack;
std::map<std::string, AstNode*> pkg_user_types;
std::vector<AstNode*> 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
+