Parser changes to support typedef.
authorPeter <peter@crozier.com>
Thu, 27 Feb 2020 16:57:35 +0000 (16:57 +0000)
committerGrazfather <grazfather@gmail.com>
Mon, 23 Mar 2020 01:20:46 +0000 (18:20 -0700)
frontends/verilog/verilog_frontend.cc
frontends/verilog/verilog_frontend.h
frontends/verilog/verilog_lexer.l
frontends/verilog/verilog_parser.y

index 42eabc02dacdd5d0e3dfa84686c752ba803659dd..de05d29a7b9c6e6c768d66215203cd770da2ad98 100644 (file)
@@ -47,6 +47,22 @@ static void error_on_dpi_function(AST::AstNode *node)
                error_on_dpi_function(child);
 }
 
+static void add_package_types(std::map<std::string, AST::AstNode *> &user_types, std::vector<AST::AstNode *> &package_list)
+{
+       // 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) {
+                       if (node->type == AST::AST_TYPEDEF) {
+                               std::string s = pkg->str + "::" + node->str.substr(1);
+                               user_types[s] = node;
+                       }
+               }
+       }
+}
+
 struct VerilogFrontend : public Frontend {
        VerilogFrontend() : Frontend("verilog", "read modules from Verilog file") { }
        void help() YS_OVERRIDE
@@ -468,6 +484,9 @@ struct VerilogFrontend : public Frontend {
                AST::process(design, current_ast, flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog1, flag_dump_vlog2, flag_dump_rtlil, flag_nolatches,
                                flag_nomeminit, flag_nomem2reg, flag_mem2reg, flag_noblackbox, lib_mode, flag_nowb, flag_noopt, flag_icells, flag_pwires, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire);
 
+               // make latest package info available to next parser
+               add_package_types(pkg_user_types, design->verilog_packages);
+
                if (!flag_nopp)
                        delete lexin;
 
index a2e06f0e41e193850f60b4bd69956fb70f02bea2..73ea51e6cbdc892a9eb373ded1555874da8fd3b3 100644 (file)
@@ -45,6 +45,12 @@ 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 package typedef'ed types
+       extern std::map<std::string, AST::AstNode*> pkg_user_types;
+
        // state of `default_nettype
        extern bool default_nettype_wire;
 
index d22a184585fba5a71c4b8620a5b48047edccf5cc..74e8dce7f9636ac99a34bd50e06e6b6134ab7c2a 100644 (file)
@@ -372,9 +372,33 @@ supply1 { return TOK_SUPPLY1; }
 "$signed"   { return TOK_TO_SIGNED; }
 "$unsigned" { return TOK_TO_UNSIGNED; }
 
+[a-zA-Z_][a-zA-Z0-9_]*::[a-zA-Z_$][a-zA-Z0-9_$]* {
+       // package qualifier
+       auto s = std::string("\\") + yytext;
+       if (pkg_user_types.count(s) > 0) {
+               // found it
+               yylval->string = new std::string(s);
+               return TOK_USER_TYPE;
+       }
+       else {
+               // backup before :: just return first part
+               size_t len = strchr(yytext, ':') - yytext;
+               yyless(len);
+               yylval->string = new std::string(std::string("\\") + yytext);
+               return TOK_ID;
+       }
+}
+
 [a-zA-Z_$][a-zA-Z0-9_$]* {
-       yylval->string = new std::string(std::string("\\") + yytext);
-       return TOK_ID;
+       auto s = std::string("\\") + yytext;
+       if (user_types.count(s) > 0) {
+               yylval->string = new std::string(s);
+               return TOK_USER_TYPE;
+       }
+       else {
+               yylval->string = new std::string(std::string("\\") + yytext);
+               return TOK_ID;
+       }
 }
 
 [a-zA-Z_$][a-zA-Z0-9_$\.]* {
index e32682f1857a3963f0b5ba60c6f8ae801be3e703..690dfdb6e5138bf2472e86a1ab723adea320d71a 100644 (file)
@@ -54,6 +54,8 @@ 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::map<std::string, AstNode*> pkg_user_types;
        std::vector<AstNode*> ast_stack;
        struct AstNode *astbuf1, *astbuf2, *astbuf3;
        struct AstNode *current_function_or_task;
@@ -125,6 +127,26 @@ struct specify_rise_fall {
        specify_triple 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;
+       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);
+               pkg_user_types[qname] = tnode;
+       }
+       delete name;
+       ast_stack.back()->children.push_back(tnode);
+}
+
 static AstNode *makeRange(int msb = 31, int lsb = 0, bool isSigned = true)
 {
        auto range = new AstNode(AST_RANGE);
@@ -167,6 +189,7 @@ static void addRange(AstNode *parent, int msb = 31, int lsb = 0, bool isSigned =
 %token <string> TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE
 %token <string> TOK_SVA_LABEL TOK_SPECIFY_OPER TOK_MSG_TASKS
 %token <string> TOK_BASE TOK_BASED_CONSTVAL TOK_UNBASED_UNSIZED_CONSTVAL
+%token <string> TOK_USER_TYPE
 %token TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER TOK_FINAL
 %token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END
 %token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM
@@ -190,6 +213,7 @@ static void addRange(AstNode *parent, int msb = 31, int lsb = 0, bool isSigned =
 %type <ast> range range_or_multirange  non_opt_range non_opt_multirange range_or_signed_int
 %type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list
 %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
 %type <boolean> opt_signed opt_property unique_case_attr always_comb_or_latch always_or_always_ff
 %type <al> attr case_attr
@@ -330,7 +354,9 @@ hierarchical_id:
        };
 
 hierarchical_type_id:
-       '(' hierarchical_id ')' { $$ = $2; };
+       TOK_USER_TYPE
+       | '(' TOK_USER_TYPE ')' { $$ = $2; }            // non-standard grammar
+       ;
 
 module:
        attr TOK_MODULE TOK_ID {
@@ -352,6 +378,7 @@ module:
                ast_stack.pop_back();
                log_assert(ast_stack.size() == 1);
                current_ast_mod = NULL;
+               user_types.clear();
        };
 
 module_para_opt:
@@ -465,6 +492,7 @@ package:
        } ';' package_body TOK_ENDPACKAGE {
                ast_stack.pop_back();
                current_ast_mod = NULL;
+               user_types.clear();
        };
 
 package_body:
@@ -1591,8 +1619,12 @@ assign_expr:
                ast_stack.back()->children.push_back(node);
        };
 
+type_name: TOK_ID              // first time seen
+        | TOK_USER_TYPE        // redefinition
+        ;
+
 typedef_decl:
-       TOK_TYPEDEF wire_type range TOK_ID range_or_multirange ';' {
+       TOK_TYPEDEF wire_type range type_name range_or_multirange ';' {
                astbuf1 = $2;
                astbuf2 = $3;
                if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) {
@@ -1625,13 +1657,10 @@ typedef_decl:
                        }
                        astbuf1->children.push_back(rangeNode);
                }
-
-               ast_stack.back()->children.push_back(new AstNode(AST_TYPEDEF, astbuf1));
-               ast_stack.back()->children.back()->str = *$4;
+               addTypedefNode($4, astbuf1);
        } |
-       TOK_TYPEDEF enum_type TOK_ID ';' {
-               ast_stack.back()->children.push_back(new AstNode(AST_TYPEDEF, astbuf1));
-               ast_stack.back()->children.back()->str = *$3;
+       TOK_TYPEDEF enum_type type_name ';' {
+               addTypedefNode($3, astbuf1);
        }
        ;