aboutsummaryrefslogtreecommitdiffstats
path: root/frontends
diff options
context:
space:
mode:
authorN. Engelhardt <nak@symbioticeda.com>2020-03-23 13:43:35 +0100
committerGitHub <noreply@github.com>2020-03-23 13:43:35 +0100
commitb86905d9523767bccc9224ce33a0b51265e4950c (patch)
treef0b4b717df853f6933dab6246b1dcce3aa2c497b /frontends
parenteb2bf340fb46c263c869ff7ce3083864f931c4fb (diff)
parent6cad865d1258cc4b9a2fc84219823004f59d5b3c (diff)
downloadyosys-b86905d9523767bccc9224ce33a0b51265e4950c.tar.gz
yosys-b86905d9523767bccc9224ce33a0b51265e4950c.tar.bz2
yosys-b86905d9523767bccc9224ce33a0b51265e4950c.zip
Merge pull request #1803 from Grazfather/typedef
Support standard typedef grammar (Fixed)
Diffstat (limited to 'frontends')
-rw-r--r--frontends/ast/ast.cc13
-rw-r--r--frontends/verilog/verilog_frontend.cc20
-rw-r--r--frontends/verilog/verilog_frontend.h6
-rw-r--r--frontends/verilog/verilog_lexer.l28
-rw-r--r--frontends/verilog/verilog_parser.y46
5 files changed, 98 insertions, 15 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);
}
;