diff options
Diffstat (limited to 'frontends/verilog')
-rw-r--r-- | frontends/verilog/verilog_frontend.cc | 2 | ||||
-rw-r--r-- | frontends/verilog/verilog_frontend.h | 1 | ||||
-rw-r--r-- | frontends/verilog/verilog_lexer.l | 72 | ||||
-rw-r--r-- | frontends/verilog/verilog_parser.y | 88 |
4 files changed, 131 insertions, 32 deletions
diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc index 058d750c3..42eabc02d 100644 --- a/frontends/verilog/verilog_frontend.cc +++ b/frontends/verilog/verilog_frontend.cc @@ -42,7 +42,7 @@ static std::list<std::vector<std::string>> verilog_defaults_stack; static void error_on_dpi_function(AST::AstNode *node) { if (node->type == AST::AST_DPI_FUNCTION) - log_file_error(node->filename, node->linenum, "Found DPI function %s.\n", node->str.c_str()); + log_file_error(node->filename, node->location.first_line, "Found DPI function %s.\n", node->str.c_str()); for (auto child : node->children) error_on_dpi_function(child); } diff --git a/frontends/verilog/verilog_frontend.h b/frontends/verilog/verilog_frontend.h index a7c9b2fe6..a2e06f0e4 100644 --- a/frontends/verilog/verilog_frontend.h +++ b/frontends/verilog/verilog_frontend.h @@ -87,7 +87,6 @@ YOSYS_NAMESPACE_END // the usual bison/flex stuff extern int frontend_verilog_yydebug; -int frontend_verilog_yylex(void); void frontend_verilog_yyerror(char const *fmt, ...); void frontend_verilog_yyrestart(FILE *f); int frontend_verilog_yyparse(void); diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 18fa2966b..0a7c34ec0 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -55,29 +55,57 @@ namespace VERILOG_FRONTEND { } YOSYS_NAMESPACE_END +#define YYSTYPE FRONTEND_VERILOG_YYSTYPE +#define YYLTYPE FRONTEND_VERILOG_YYLTYPE + #define SV_KEYWORD(_tok) \ if (sv_mode) return _tok; \ log("Lexer warning: The SystemVerilog keyword `%s' (at %s:%d) is not "\ "recognized unless read_verilog is called with -sv!\n", yytext, \ AST::current_filename.c_str(), frontend_verilog_yyget_lineno()); \ - frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); \ + yylval->string = new std::string(std::string("\\") + yytext); \ return TOK_ID; #define NON_KEYWORD() \ - frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); \ + yylval->string = new std::string(std::string("\\") + yytext); \ return TOK_ID; #define YY_INPUT(buf,result,max_size) \ result = readsome(*VERILOG_FRONTEND::lexin, buf, max_size) +YYLTYPE real_location; +YYLTYPE old_location; + +#define YY_USER_ACTION \ + old_location = real_location; \ + real_location.first_line = real_location.last_line; \ + real_location.first_column = real_location.last_column; \ + for(int i = 0; yytext[i] != '\0'; ++i){ \ + if(yytext[i] == '\n') { \ + real_location.last_line++; \ + real_location.last_column = 1; \ + } \ + else { \ + real_location.last_column++; \ + } \ + } \ + (*yylloc) = real_location; + +#define YY_BREAK \ + (*yylloc) = old_location; \ + break; + #undef YY_BUF_SIZE #define YY_BUF_SIZE 65536 +extern int frontend_verilog_yylex(YYSTYPE *yylval_param, YYLTYPE *yyloc_param); %} %option yylineno %option noyywrap %option nounput +%option bison-locations +%option bison-bridge %option prefix="frontend_verilog_yy" %x COMMENT @@ -97,12 +125,16 @@ YOSYS_NAMESPACE_END if (!current_filename.empty() && current_filename.back() == '"') current_filename = current_filename.substr(0, current_filename.size()-1); frontend_verilog_yyset_lineno(0); + yylloc->first_line = yylloc->last_line = 0; + real_location.first_line = real_location.last_line = 0; } <INITIAL,SYNOPSYS_TRANSLATE_OFF>"`file_pop"[^\n]*\n { current_filename = fn_stack.back(); fn_stack.pop_back(); frontend_verilog_yyset_lineno(ln_stack.back()); + yylloc->first_line = yylloc->last_line = ln_stack.back(); + real_location.first_line = real_location.last_line = ln_stack.back(); ln_stack.pop_back(); } @@ -110,6 +142,8 @@ YOSYS_NAMESPACE_END char *p = yytext + 5; while (*p == ' ' || *p == '\t') p++; frontend_verilog_yyset_lineno(atoi(p)); + yylloc->first_line = yylloc->last_line = atoi(p); + real_location.first_line = real_location.last_line = atoi(p); while (*p && *p != ' ' && *p != '\t') p++; while (*p == ' ' || *p == '\t') p++; char *q = *p ? p + 1 : p; @@ -198,7 +232,7 @@ YOSYS_NAMESPACE_END [a-zA-Z_$][a-zA-Z0-9_$]*/[ \t\r\n]*:[ \t\r\n]*(assert|assume|cover|restrict)[^a-zA-Z0-9_$\.] { if (!strcmp(yytext, "default")) return TOK_DEFAULT; - frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); + yylval->string = new std::string(std::string("\\") + yytext); return TOK_SVA_LABEL; } @@ -235,27 +269,27 @@ YOSYS_NAMESPACE_END "typedef" { SV_KEYWORD(TOK_TYPEDEF); } [0-9][0-9_]* { - frontend_verilog_yylval.string = new std::string(yytext); + yylval->string = new std::string(yytext); return TOK_CONSTVAL; } [0-9]*[ \t]*\'[sS]?[bodhBODH]?[ \t\r\n]*[0-9a-fA-FzxZX?_]+ { - frontend_verilog_yylval.string = new std::string(yytext); + yylval->string = new std::string(yytext); return TOK_CONSTVAL; } [0-9][0-9_]*\.[0-9][0-9_]*([eE][-+]?[0-9_]+)? { - frontend_verilog_yylval.string = new std::string(yytext); + yylval->string = new std::string(yytext); return TOK_REALVAL; } [0-9][0-9_]*[eE][-+]?[0-9_]+ { - frontend_verilog_yylval.string = new std::string(yytext); + yylval->string = new std::string(yytext); return TOK_REALVAL; } \" { BEGIN(STRING); } -<STRING>\\. { yymore(); } +<STRING>\\. { yymore(); real_location = old_location; } <STRING>\" { BEGIN(0); char *yystr = strdup(yytext); @@ -291,14 +325,14 @@ YOSYS_NAMESPACE_END yystr[j++] = yystr[i++]; } yystr[j] = 0; - frontend_verilog_yylval.string = new std::string(yystr, j); + yylval->string = new std::string(yystr, j); free(yystr); return TOK_STRING; } -<STRING>. { yymore(); } +<STRING>. { yymore(); real_location = old_location; } and|nand|or|nor|xor|xnor|not|buf|bufif0|bufif1|notif0|notif1 { - frontend_verilog_yylval.string = new std::string(yytext); + yylval->string = new std::string(yytext); return TOK_PRIMITIVE; } @@ -306,18 +340,18 @@ supply0 { return TOK_SUPPLY0; } supply1 { return TOK_SUPPLY1; } "$"(display|write|strobe|monitor|time|stop|finish|dumpfile|dumpvars|dumpon|dumpoff|dumpall) { - frontend_verilog_yylval.string = new std::string(yytext); + yylval->string = new std::string(yytext); return TOK_ID; } "$"(setup|hold|setuphold|removal|recovery|recrem|skew|timeskew|fullskew|nochange) { if (!specify_mode) REJECT; - frontend_verilog_yylval.string = new std::string(yytext); + yylval->string = new std::string(yytext); return TOK_ID; } "$"(info|warning|error|fatal) { - frontend_verilog_yylval.string = new std::string(yytext); + yylval->string = new std::string(yytext); return TOK_MSG_TASKS; } @@ -325,12 +359,12 @@ supply1 { return TOK_SUPPLY1; } "$unsigned" { return TOK_TO_UNSIGNED; } [a-zA-Z_$][a-zA-Z0-9_$]* { - frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); + yylval->string = new std::string(std::string("\\") + yytext); return TOK_ID; } [a-zA-Z_$][a-zA-Z0-9_$\.]* { - frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); + yylval->string = new std::string(std::string("\\") + yytext); return TOK_ID; } @@ -377,7 +411,7 @@ import[ \t\r\n]+\"(DPI|DPI-C)\"[ \t\r\n]+function[ \t\r\n]+ { } <IMPORT_DPI>[a-zA-Z_$][a-zA-Z0-9_$]* { - frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); + yylval->string = new std::string(std::string("\\") + yytext); return TOK_ID; } @@ -393,7 +427,7 @@ import[ \t\r\n]+\"(DPI|DPI-C)\"[ \t\r\n]+function[ \t\r\n]+ { } "\\"[^ \t\r\n]+ { - frontend_verilog_yylval.string = new std::string(yytext); + yylval->string = new std::string(yytext); return TOK_ID; } @@ -435,7 +469,7 @@ import[ \t\r\n]+\"(DPI|DPI-C)\"[ \t\r\n]+function[ \t\r\n]+ { [-+]?[=*]> { if (!specify_mode) REJECT; - frontend_verilog_yylval.string = new std::string(yytext); + yylval->string = new std::string(yytext); return TOK_SPECIFY_OPER; } diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index bb2a10e9a..be8b39e9f 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -38,8 +38,11 @@ #include <stack> #include <string.h> #include "frontends/verilog/verilog_frontend.h" +#include "frontends/verilog/verilog_parser.tab.hh" #include "kernel/log.h" +#define YYLEX_PARAM &yylval, &yylloc + USING_YOSYS_NAMESPACE using namespace AST; using namespace VERILOG_FRONTEND; @@ -68,6 +71,20 @@ namespace VERILOG_FRONTEND { } YOSYS_NAMESPACE_END +#define SET_AST_NODE_LOC(WHICH, BEGIN, END) \ + do { (WHICH)->location.first_line = (BEGIN).first_line; \ + (WHICH)->location.first_column = (BEGIN).first_column; \ + (WHICH)->location.last_line = (END).last_line; \ + (WHICH)->location.last_column = (END).last_column; } while(0) + +#define SET_RULE_LOC(LHS, BEGIN, END) \ + do { (LHS).first_line = (BEGIN).first_line; \ + (LHS).first_column = (BEGIN).first_column; \ + (LHS).last_line = (END).last_line; \ + (LHS).last_column = (END).last_column; } while(0) + +int frontend_verilog_yylex(YYSTYPE *yylval_param, YYLTYPE *yyloc_param); + static void append_attr(AstNode *ast, std::map<std::string, AstNode*> *al) { for (auto &it : *al) { @@ -125,6 +142,7 @@ static void addRange(AstNode *parent, int msb = 31, int lsb = 0, bool isSigned = %} %define api.prefix {frontend_verilog_yy} +%define api.pure /* The union is defined in the header, so we need to provide all the * includes it requires @@ -202,6 +220,7 @@ static void addRange(AstNode *parent, int msb = 31, int lsb = 0, bool isSigned = %nonassoc TOK_ELSE %debug +%locations %% @@ -244,7 +263,9 @@ attr: }; attr_opt: - attr_opt ATTR_BEGIN opt_attr_list ATTR_END | + attr_opt ATTR_BEGIN opt_attr_list ATTR_END { + SET_RULE_LOC(@$, @2, @$); + }| /* empty */; defattr: @@ -326,6 +347,7 @@ module: if (port_stubs.size() != 0) frontend_verilog_yyerror("Missing details for module port `%s'.", port_stubs.begin()->first.c_str()); + SET_AST_NODE_LOC(ast_stack.back(), @2, @$); ast_stack.pop_back(); log_assert(ast_stack.size() == 1); current_ast_mod = NULL; @@ -389,6 +411,7 @@ module_arg: node->str = *$1; node->port_id = ++port_counter; ast_stack.back()->children.push_back(node); + SET_AST_NODE_LOC(node, @1, @1); } else { if (port_stubs.count(*$1) != 0) frontend_verilog_yyerror("Duplicate module port `%s'.", $1->c_str()); @@ -414,6 +437,7 @@ module_arg: attr wire_type range TOK_ID { AstNode *node = $2; node->str = *$4; + SET_AST_NODE_LOC(node, @4, @4); node->port_id = ++port_counter; if ($3 != NULL) node->children.push_back($3); @@ -495,6 +519,7 @@ wire_type: current_wire_const = false; } wire_type_token_list { $$ = astbuf3; + SET_RULE_LOC(@$, @2, @$); }; wire_type_token_list: @@ -1477,11 +1502,24 @@ wire_name_and_opt_assign: if (astbuf1->attributes.count("\\defaultvalue")) delete astbuf1->attributes.at("\\defaultvalue"); astbuf1->attributes["\\defaultvalue"] = $3; - } else - if (astbuf1->is_reg || astbuf1->is_logic) - ast_stack.back()->children.push_back(new AstNode(AST_INITIAL, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_LE, wire, $3)))); - else - ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, $3)); + } + else if (astbuf1->is_reg || astbuf1->is_logic){ + AstNode *assign = new AstNode(AST_ASSIGN_LE, wire, $3); + AstNode *block = new AstNode(AST_BLOCK, assign); + AstNode *init = new AstNode(AST_INITIAL, block); + + SET_AST_NODE_LOC(assign, @1, @3); + SET_AST_NODE_LOC(block, @1, @3); + SET_AST_NODE_LOC(init, @1, @3); + + ast_stack.back()->children.push_back(init); + } + else { + AstNode *assign = new AstNode(AST_ASSIGN, wire, $3); + SET_AST_NODE_LOC(assign, @1, @3); + ast_stack.back()->children.push_back(assign); + } + }; wire_name: @@ -1530,6 +1568,8 @@ wire_name: if (node->is_input || node->is_output) node->port_id = current_function_or_task_port_id++; } + //FIXME: for some reason, TOK_ID has a location which always points to one column *after* the real last column... + SET_AST_NODE_LOC(node, @1, @1); ast_stack.back()->children.push_back(node); delete $1; @@ -1543,7 +1583,9 @@ assign_expr_list: assign_expr: lvalue '=' expr { - ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, $1, $3)); + AstNode *node = new AstNode(AST_ASSIGN, $1, $3); + SET_AST_NODE_LOC(node, @$, @$); + ast_stack.back()->children.push_back(node); }; typedef_decl: @@ -1628,14 +1670,19 @@ single_cell: astbuf2->str = *$1; delete $1; ast_stack.back()->children.push_back(astbuf2); - } '(' cell_port_list ')' | + } '(' cell_port_list ')' { + SET_AST_NODE_LOC(astbuf2, @1, @$); + } | TOK_ID non_opt_range { astbuf2 = astbuf1->clone(); if (astbuf2->type != AST_PRIMITIVE) astbuf2->str = *$1; delete $1; ast_stack.back()->children.push_back(new AstNode(AST_CELLARRAY, $2, astbuf2)); - } '(' cell_port_list ')'; + } '(' cell_port_list ')'{ + SET_AST_NODE_LOC(astbuf2, @1, @$); + SET_AST_NODE_LOC(astbuf3, @1, @$); + }; prim_list: single_prim | @@ -1770,8 +1817,13 @@ always_stmt: ast_stack.back()->children.push_back(block); ast_stack.push_back(block); } behavioral_stmt { + SET_AST_NODE_LOC(ast_stack.back(), @6, @6); ast_stack.pop_back(); + + SET_AST_NODE_LOC(ast_stack.back(), @2, @$); ast_stack.pop_back(); + + SET_RULE_LOC(@$, @2, @$); } | attr always_comb_or_latch { AstNode *node = new AstNode(AST_ALWAYS); @@ -2126,6 +2178,7 @@ behavioral_stmt: ast_stack.back()->children.push_back(block); ast_stack.push_back(block); } behavioral_stmt { + SET_AST_NODE_LOC(ast_stack.back(), @13, @13); ast_stack.pop_back(); ast_stack.pop_back(); } | @@ -2139,6 +2192,7 @@ behavioral_stmt: ast_stack.back()->children.push_back(block); ast_stack.push_back(block); } behavioral_stmt { + SET_AST_NODE_LOC(ast_stack.back(), @7, @7); ast_stack.pop_back(); ast_stack.pop_back(); } | @@ -2152,6 +2206,7 @@ behavioral_stmt: ast_stack.back()->children.push_back(block); ast_stack.push_back(block); } behavioral_stmt { + SET_AST_NODE_LOC(ast_stack.back(), @7, @7); ast_stack.pop_back(); ast_stack.pop_back(); } | @@ -2159,14 +2214,18 @@ behavioral_stmt: AstNode *node = new AstNode(AST_CASE); AstNode *block = new AstNode(AST_BLOCK); AstNode *cond = new AstNode(AST_COND, AstNode::mkconst_int(1, false, 1), block); + SET_AST_NODE_LOC(cond, @4, @4); ast_stack.back()->children.push_back(node); node->children.push_back(new AstNode(AST_REDUCE_BOOL, $4)); node->children.push_back(cond); ast_stack.push_back(node); ast_stack.push_back(block); append_attr(node, $1); - } behavioral_stmt optional_else { + } behavioral_stmt { + SET_AST_NODE_LOC(ast_stack.back(), @7, @7); + } optional_else { ast_stack.pop_back(); + SET_AST_NODE_LOC(ast_stack.back(), @2, @9); ast_stack.pop_back(); } | case_attr case_type '(' expr ')' { @@ -2174,7 +2233,9 @@ behavioral_stmt: ast_stack.back()->children.push_back(node); ast_stack.push_back(node); append_attr(node, $1); + SET_AST_NODE_LOC(ast_stack.back(), @4, @4); } opt_synopsys_attr case_body TOK_ENDCASE { + SET_AST_NODE_LOC(ast_stack.back(), @2, @9); case_type_stack.pop_back(); ast_stack.pop_back(); }; @@ -2226,10 +2287,14 @@ optional_else: TOK_ELSE { AstNode *block = new AstNode(AST_BLOCK); AstNode *cond = new AstNode(AST_COND, new AstNode(AST_DEFAULT), block); + SET_AST_NODE_LOC(cond, @1, @1); + ast_stack.pop_back(); ast_stack.back()->children.push_back(cond); ast_stack.push_back(block); - } behavioral_stmt | + } behavioral_stmt { + SET_AST_NODE_LOC(ast_stack.back(), @3, @3); + } | /* empty */ %prec FAKE_THEN; case_body: @@ -2250,6 +2315,7 @@ case_item: case_type_stack.push_back(0); } behavioral_stmt { case_type_stack.pop_back(); + SET_AST_NODE_LOC(ast_stack.back(), @4, @4); ast_stack.pop_back(); ast_stack.pop_back(); }; |