diff options
author | N. Engelhardt <nak@symbioticeda.com> | 2020-03-23 13:43:35 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-03-23 13:43:35 +0100 |
commit | b86905d9523767bccc9224ce33a0b51265e4950c (patch) | |
tree | f0b4b717df853f6933dab6246b1dcce3aa2c497b | |
parent | eb2bf340fb46c263c869ff7ce3083864f931c4fb (diff) | |
parent | 6cad865d1258cc4b9a2fc84219823004f59d5b3c (diff) | |
download | yosys-b86905d9523767bccc9224ce33a0b51265e4950c.tar.gz yosys-b86905d9523767bccc9224ce33a0b51265e4950c.tar.bz2 yosys-b86905d9523767bccc9224ce33a0b51265e4950c.zip |
Merge pull request #1803 from Grazfather/typedef
Support standard typedef grammar (Fixed)
-rw-r--r-- | frontends/ast/ast.cc | 13 | ||||
-rw-r--r-- | frontends/verilog/verilog_frontend.cc | 20 | ||||
-rw-r--r-- | frontends/verilog/verilog_frontend.h | 6 | ||||
-rw-r--r-- | frontends/verilog/verilog_lexer.l | 28 | ||||
-rw-r--r-- | frontends/verilog/verilog_parser.y | 46 | ||||
-rw-r--r-- | tests/svtypes/enum_simple.sv | 5 | ||||
-rw-r--r-- | tests/svtypes/typedef_memory.sv | 2 | ||||
-rw-r--r-- | tests/svtypes/typedef_memory_2.sv | 2 | ||||
-rw-r--r-- | tests/svtypes/typedef_package.sv | 4 | ||||
-rw-r--r-- | tests/svtypes/typedef_param.sv | 10 | ||||
-rw-r--r-- | tests/svtypes/typedef_scopes.sv | 18 | ||||
-rw-r--r-- | tests/svtypes/typedef_simple.sv | 10 |
12 files changed, 124 insertions, 40 deletions
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 650c7a937..632a4d4f9 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -1179,12 +1179,13 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump for (auto n : design->verilog_globals) (*it)->children.push_back(n->clone()); - for (auto n : design->verilog_packages){ - for (auto o : n->children) { + // append nodes from previous packages using package-qualified names + for (auto &n : design->verilog_packages) { + for (auto &o : n->children) { AstNode *cloned_node = o->clone(); - log("cloned node %s\n", type2str(cloned_node->type).c_str()); - if (cloned_node->type == AST_ENUM){ - for (auto e : cloned_node->children){ + // log("cloned node %s\n", type2str(cloned_node->type).c_str()); + if (cloned_node->type == AST_ENUM) { + for (auto &e : cloned_node->children) { log_assert(e->type == AST_ENUM_ITEM); e->str = n->str + std::string("::") + e->str.substr(1); } @@ -1220,6 +1221,8 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump design->add(process_module(*it, defer)); } else if ((*it)->type == AST_PACKAGE) { + // process enum/other declarations + (*it)->simplify(true, false, false, 1, -1, false, false); design->verilog_packages.push_back((*it)->clone()); } else { diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc index 42eabc02d..f2c1c227f 100644 --- a/frontends/verilog/verilog_frontend.cc +++ b/frontends/verilog/verilog_frontend.cc @@ -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 @@ -450,6 +466,9 @@ struct VerilogFrontend : public Frontend { lexin = new std::istringstream(code_after_preproc); } + // make package typedefs available to parser + add_package_types(pkg_user_types, design->verilog_packages); + frontend_verilog_yyset_lineno(1); frontend_verilog_yyrestart(NULL); frontend_verilog_yyparse(); @@ -468,6 +487,7 @@ 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); + if (!flag_nopp) delete lexin; diff --git a/frontends/verilog/verilog_frontend.h b/frontends/verilog/verilog_frontend.h index a2e06f0e4..73ea51e6c 100644 --- a/frontends/verilog/verilog_frontend.h +++ b/frontends/verilog/verilog_frontend.h @@ -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; diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index d22a18458..74e8dce7f 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -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_$\.]* { diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index e32682f18..f7e3afd13 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -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: @@ -494,6 +522,7 @@ interface: ast_stack.pop_back(); log_assert(ast_stack.size() == 1); current_ast_mod = NULL; + user_types.clear(); }; interface_body: @@ -1591,8 +1620,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 +1658,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); } ; diff --git a/tests/svtypes/enum_simple.sv b/tests/svtypes/enum_simple.sv index ccaf50da0..4e4d5871c 100644 --- a/tests/svtypes/enum_simple.sv +++ b/tests/svtypes/enum_simple.sv @@ -5,8 +5,9 @@ module enum_simple(input clk, input rst); typedef enum logic [1:0] { ts0, ts1, ts2, ts3 } states_t; - (states_t) state; - (states_t) enum_const = ts1; + states_t state; + (states_t) state1; + states_t enum_const = ts1; always @(posedge clk) begin if (rst) begin diff --git a/tests/svtypes/typedef_memory.sv b/tests/svtypes/typedef_memory.sv index 577e484ad..37e63c1d0 100644 --- a/tests/svtypes/typedef_memory.sv +++ b/tests/svtypes/typedef_memory.sv @@ -1,7 +1,7 @@ module top(input [3:0] addr, wdata, input clk, wen, output reg [3:0] rdata); typedef logic [3:0] ram16x4_t[0:15]; - (ram16x4_t) mem; + ram16x4_t mem; always @(posedge clk) begin if (wen) mem[addr] <= wdata; diff --git a/tests/svtypes/typedef_memory_2.sv b/tests/svtypes/typedef_memory_2.sv index f3089bf55..6d65131db 100644 --- a/tests/svtypes/typedef_memory_2.sv +++ b/tests/svtypes/typedef_memory_2.sv @@ -1,7 +1,7 @@ module top(input [3:0] addr, wdata, input clk, wen, output reg [3:0] rdata); typedef logic [3:0] nibble; - (nibble) mem[0:15]; + nibble mem[0:15]; always @(posedge clk) begin if (wen) mem[addr] <= wdata; diff --git a/tests/svtypes/typedef_package.sv b/tests/svtypes/typedef_package.sv index b766f10cf..57a78c53a 100644 --- a/tests/svtypes/typedef_package.sv +++ b/tests/svtypes/typedef_package.sv @@ -5,8 +5,8 @@ endpackage module top; - (* keep *) (pkg::uint8_t) a = 8'hAA; - (* keep *) (pkg::enum8_t) b_enum = pkg::bb; + (* keep *) pkg::uint8_t a = 8'hAA; + (* keep *) pkg::enum8_t b_enum = pkg::bb; always @* assert(a == 8'hAA); always @* assert(b_enum == 8'hBB); diff --git a/tests/svtypes/typedef_param.sv b/tests/svtypes/typedef_param.sv index ddbd471e0..d838dd828 100644 --- a/tests/svtypes/typedef_param.sv +++ b/tests/svtypes/typedef_param.sv @@ -6,12 +6,12 @@ module top; typedef logic [1:0] uint2_t; typedef logic signed [3:0] int4_t; typedef logic signed [7:0] int8_t; - typedef (int8_t) char_t; + typedef int8_t char_t; - parameter (uint2_t) int2 = 2'b10; - localparam (int4_t) int4 = -1; - localparam (int8_t) int8 = int4; - localparam (char_t) ch = int8; + parameter uint2_t int2 = 2'b10; + localparam int4_t int4 = -1; + localparam int8_t int8 = int4; + localparam char_t ch = int8; `STATIC_ASSERT(int2 == 2'b10); diff --git a/tests/svtypes/typedef_scopes.sv b/tests/svtypes/typedef_scopes.sv index 1c45c7057..d41a58147 100644 --- a/tests/svtypes/typedef_scopes.sv +++ b/tests/svtypes/typedef_scopes.sv @@ -4,30 +4,30 @@ typedef enum logic {s0, s1} outer_enum_t; module top; - (outer_uint4_t) u4_i = 8'hA5; - (outer_enum_t) enum4_i = s0; + outer_uint4_t u4_i = 8'hA5; + outer_enum_t enum4_i = s0; always @(*) assert(u4_i == 4'h5); always @(*) assert(enum4_i == 1'b0); typedef logic [3:0] inner_type; typedef enum logic [2:0] {s2=2, s3, s4} inner_enum_t; - (inner_type) inner_i1 = 8'h5A; - (inner_enum_t) inner_enum1 = s3; + inner_type inner_i1 = 8'h5A; + inner_enum_t inner_enum1 = s3; always @(*) assert(inner_i1 == 4'hA); always @(*) assert(inner_enum1 == 3'h3); if (1) begin: genblock typedef logic [7:0] inner_type; - parameter (inner_type) inner_const = 8'hA5; + parameter inner_type inner_const = 8'hA5; typedef enum logic [2:0] {s5=5, s6, s7} inner_enum_t; - (inner_type) inner_gb_i = inner_const; //8'hA5; - (inner_enum_t) inner_gb_enum1 = s7; + inner_type inner_gb_i = inner_const; //8'hA5; + inner_enum_t inner_gb_enum1 = s7; always @(*) assert(inner_gb_i == 8'hA5); always @(*) assert(inner_gb_enum1 == 3'h7); end - (inner_type) inner_i2 = 8'h42; - (inner_enum_t) inner_enum2 = s4; + inner_type inner_i2 = 8'h42; + inner_enum_t inner_enum2 = s4; always @(*) assert(inner_i2 == 4'h2); always @(*) assert(inner_enum2 == 3'h4); diff --git a/tests/svtypes/typedef_simple.sv b/tests/svtypes/typedef_simple.sv index 7e760dee4..8f89910e5 100644 --- a/tests/svtypes/typedef_simple.sv +++ b/tests/svtypes/typedef_simple.sv @@ -3,12 +3,12 @@ module top; typedef logic [1:0] uint2_t; typedef logic signed [3:0] int4_t; typedef logic signed [7:0] int8_t; - typedef (int8_t) char_t; + typedef int8_t char_t; - (* keep *) (uint2_t) int2 = 2'b10; - (* keep *) (int4_t) int4 = -1; - (* keep *) (int8_t) int8 = int4; - (* keep *) (char_t) ch = int8; + (* keep *) uint2_t int2 = 2'b10; + (* keep *) int4_t int4 = -1; + (* keep *) int8_t int8 = int4; + (* keep *) char_t ch = int8; always @* assert(int2 == 2'b10); |