Parser changes to support typedef.

This commit is contained in:
Peter 2020-02-27 16:57:35 +00:00 committed by Grazfather
parent f828cb5132
commit 14f32028ec
4 changed files with 88 additions and 10 deletions

View File

@ -47,6 +47,22 @@ static void error_on_dpi_function(AST::AstNode *node)
error_on_dpi_function(child); 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 { struct VerilogFrontend : public Frontend {
VerilogFrontend() : Frontend("verilog", "read modules from Verilog file") { } VerilogFrontend() : Frontend("verilog", "read modules from Verilog file") { }
void help() YS_OVERRIDE 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, 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); 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) if (!flag_nopp)
delete lexin; delete lexin;

View File

@ -45,6 +45,12 @@ namespace VERILOG_FRONTEND
// this function converts a Verilog constant to an AST_CONSTANT node // 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); 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 // state of `default_nettype
extern bool default_nettype_wire; extern bool default_nettype_wire;

View File

@ -372,10 +372,34 @@ supply1 { return TOK_SUPPLY1; }
"$signed" { return TOK_TO_SIGNED; } "$signed" { return TOK_TO_SIGNED; }
"$unsigned" { return TOK_TO_UNSIGNED; } "$unsigned" { return TOK_TO_UNSIGNED; }
[a-zA-Z_$][a-zA-Z0-9_$]* { [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); yylval->string = new std::string(std::string("\\") + yytext);
return TOK_ID; return TOK_ID;
} }
}
[a-zA-Z_$][a-zA-Z0-9_$]* {
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_$\.]* { [a-zA-Z_$][a-zA-Z0-9_$\.]* {
yylval->string = new std::string(std::string("\\") + yytext); yylval->string = new std::string(std::string("\\") + yytext);

View File

@ -54,6 +54,8 @@ namespace VERILOG_FRONTEND {
std::map<std::string, AstNode*> *attr_list, default_attr_list; std::map<std::string, AstNode*> *attr_list, default_attr_list;
std::stack<std::map<std::string, AstNode*> *> attr_list_stack; std::stack<std::map<std::string, AstNode*> *> attr_list_stack;
std::map<std::string, AstNode*> *albuf; 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; std::vector<AstNode*> ast_stack;
struct AstNode *astbuf1, *astbuf2, *astbuf3; struct AstNode *astbuf1, *astbuf2, *astbuf3;
struct AstNode *current_function_or_task; struct AstNode *current_function_or_task;
@ -125,6 +127,26 @@ struct specify_rise_fall {
specify_triple 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) static AstNode *makeRange(int msb = 31, int lsb = 0, bool isSigned = true)
{ {
auto range = new AstNode(AST_RANGE); 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_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE
%token <string> TOK_SVA_LABEL TOK_SPECIFY_OPER TOK_MSG_TASKS %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_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 TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER TOK_FINAL
%token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END %token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END
%token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM %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> 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 <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> 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 <ast> opt_enum_init
%type <boolean> opt_signed opt_property unique_case_attr always_comb_or_latch always_or_always_ff %type <boolean> opt_signed opt_property unique_case_attr always_comb_or_latch always_or_always_ff
%type <al> attr case_attr %type <al> attr case_attr
@ -330,7 +354,9 @@ hierarchical_id:
}; };
hierarchical_type_id: hierarchical_type_id:
'(' hierarchical_id ')' { $$ = $2; }; TOK_USER_TYPE
| '(' TOK_USER_TYPE ')' { $$ = $2; } // non-standard grammar
;
module: module:
attr TOK_MODULE TOK_ID { attr TOK_MODULE TOK_ID {
@ -352,6 +378,7 @@ module:
ast_stack.pop_back(); ast_stack.pop_back();
log_assert(ast_stack.size() == 1); log_assert(ast_stack.size() == 1);
current_ast_mod = NULL; current_ast_mod = NULL;
user_types.clear();
}; };
module_para_opt: module_para_opt:
@ -465,6 +492,7 @@ package:
} ';' package_body TOK_ENDPACKAGE { } ';' package_body TOK_ENDPACKAGE {
ast_stack.pop_back(); ast_stack.pop_back();
current_ast_mod = NULL; current_ast_mod = NULL;
user_types.clear();
}; };
package_body: package_body:
@ -1591,8 +1619,12 @@ assign_expr:
ast_stack.back()->children.push_back(node); ast_stack.back()->children.push_back(node);
}; };
type_name: TOK_ID // first time seen
| TOK_USER_TYPE // redefinition
;
typedef_decl: typedef_decl:
TOK_TYPEDEF wire_type range TOK_ID range_or_multirange ';' { TOK_TYPEDEF wire_type range type_name range_or_multirange ';' {
astbuf1 = $2; astbuf1 = $2;
astbuf2 = $3; astbuf2 = $3;
if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) { if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) {
@ -1625,13 +1657,10 @@ typedef_decl:
} }
astbuf1->children.push_back(rangeNode); astbuf1->children.push_back(rangeNode);
} }
addTypedefNode($4, astbuf1);
ast_stack.back()->children.push_back(new AstNode(AST_TYPEDEF, astbuf1));
ast_stack.back()->children.back()->str = *$4;
} | } |
TOK_TYPEDEF enum_type TOK_ID ';' { TOK_TYPEDEF enum_type type_name ';' {
ast_stack.back()->children.push_back(new AstNode(AST_TYPEDEF, astbuf1)); addTypedefNode($3, astbuf1);
ast_stack.back()->children.back()->str = *$3;
} }
; ;