aboutsummaryrefslogtreecommitdiffstats
path: root/frontends/verilog
diff options
context:
space:
mode:
authorClaire Wolf <clifford@clifford.at>2020-03-03 08:38:32 -0800
committerGitHub <noreply@github.com>2020-03-03 08:38:32 -0800
commitb597f85b13b5369398350ef4ef43b7b2521eb140 (patch)
tree18ea3d52b5927ea1491162458e16cfcfd3280418 /frontends/verilog
parent91892465e1af2bcb5ec348b86ba4e566b040cb12 (diff)
parentf80fe8dc22ca2b3639b7b0bbff69458addb05432 (diff)
downloadyosys-b597f85b13b5369398350ef4ef43b7b2521eb140.tar.gz
yosys-b597f85b13b5369398350ef4ef43b7b2521eb140.tar.bz2
yosys-b597f85b13b5369398350ef4ef43b7b2521eb140.zip
Merge pull request #1718 from boqwxp/precise_locations
Closes #1717. Add more precise Verilog source location information to AST and RTLIL nodes.
Diffstat (limited to 'frontends/verilog')
-rw-r--r--frontends/verilog/verilog_frontend.cc2
-rw-r--r--frontends/verilog/verilog_frontend.h1
-rw-r--r--frontends/verilog/verilog_lexer.l72
-rw-r--r--frontends/verilog/verilog_parser.y88
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..e881a1339 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) {
@@ -202,6 +219,8 @@ static void addRange(AstNode *parent, int msb = 31, int lsb = 0, bool isSigned =
%nonassoc TOK_ELSE
%debug
+%locations
+%pure-parser
%%
@@ -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();
};