Fix parsing "#0 'b0", bug256.

This commit is contained in:
Wilson Snyder 2014-03-11 19:07:58 -04:00
parent 9e76078939
commit 85c5765c00
6 changed files with 88 additions and 23 deletions

View File

@ -9,6 +9,8 @@ indicates the contributor was also the author of the fix; Thanks!
*** Add parameters into trace files, bug706. [Alex Solomatnikov]
**** Fix parsing "#0 'b0", bug256.
**** Fix array bound checks on real variables.
**** Fix --skip-identical mis-detecting on OS-X, bug707.

View File

@ -105,6 +105,7 @@ class V3ParseImp {
int m_inBeginKwd; // Inside a `begin_keywords
int m_lastVerilogState; // Last LEX state in `begin_keywords
int m_prevLexToken; // previous parsed token (for lexer)
bool m_ahead; // aheadToken is valid
int m_aheadToken; // Token we read ahead
V3ParseBisonYYSType m_aheadVal; // aheadToken's value
@ -193,6 +194,7 @@ public:
void statePushVlg(); // Parser -> lexer communication
void statePop(); // Parser -> lexer communication
static int stateVerilogRecent(); // Parser -> lexer communication
int prevLexToken() { return m_prevLexToken; } // Parser -> lexer communication
size_t flexPpInputToLex(char* buf, size_t max_size) { return ppInputToLex(buf,max_size); }
//==== Symbol tables
@ -208,11 +210,13 @@ public:
m_inLibrary = false;
m_inBeginKwd = 0;
m_lastVerilogState = stateVerilogRecent();
m_prevLexToken = 0;
m_ahead = false;
m_aheadToken = 0;
}
~V3ParseImp();
void parserClear();
void unputString(const char* textp, size_t length);
// METHODS
// Preprocess and read the Verilog file specified into the netlist database
@ -223,6 +227,7 @@ public:
private:
void lexFile(const string& modname);
int yylexReadTok();
int lexToken(); // Internal; called from lexToBison
};

View File

@ -57,11 +57,26 @@ public:
void statePop() {
yy_pop_state();
}
void unputString(const char* textp, size_t length) {
// Add characters to input stream in back-to-front order
const char* cp = textp;
for (cp += length - 1; length--; cp--) {
unput(*cp);
}
}
};
void V3ParseImp::stateExitPsl() { parsep()->m_lexerp->stateExitPsl(); }
void V3ParseImp::statePushVlg() { parsep()->m_lexerp->stateExitPsl(); }
void V3ParseImp::statePop() { parsep()->m_lexerp->statePop(); }
int V3ParseImp::yylexThis() { return parsep()->m_lexerp->yylex(); }
void V3ParseImp::unputString(const char* textp, size_t length) { parsep()->m_lexerp->unputString(textp, length); }
int V3ParseImp::yylexReadTok() {
// Call yylex() remembering last non-whitespace token
int token = parsep()->m_lexerp->yylex();
m_prevLexToken = token; // Save so can find '#' to parse following number
return token;
}
//######################################################################
// Read class functions

View File

@ -43,7 +43,8 @@ extern void yyerrorf(const char* format, ...);
//======================================================================
#define NEXTLINE() {PARSEP->linenoInc();}
#define LINECHECK() { const char* cp=yytext; for (int n=yyleng; n; --n) if (cp[n]=='\n') NEXTLINE(); }
#define LINECHECKS(textp,len) { const char* cp=textp; for (int n=len; n; --n) if (cp[n]=='\n') NEXTLINE(); }
#define LINECHECK() LINECHECKS(yytext,yyleng)
#define CRELINE() (PARSEP->copyOrSameFileLine())
#define FL { yylval.fl = CRELINE(); }
@ -149,6 +150,13 @@ id [a-zA-Z_][a-zA-Z0-9_$]*
/* escaped identifier */
escid \\[^ \t\f\r\n]+
word [a-zA-Z0-9_]+
/* verilog numbers, constructed to not match the ' that begins a '( or '{ */
vnum1 [0-9]*?['']s?[bcodhBCODH][ \t\n]*[A-Fa-f0-9xXzZ_?]*
vnum2 [0-9]*?['']s?[01xXzZ]
vnum3 [0-9][_0-9]*[ \t\n]*['']s?[bcodhBCODH]?[ \t]*[A-Fa-f0-9xXzZ_?]+
vnum4 [0-9][_0-9]*[ \t\n]*['']s?[bcodhBCODH]
vnum5 [0-9][_0-9]*[ \t\n]*['']s
vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
%%
@ -912,24 +920,21 @@ word [a-zA-Z0-9_]+
}
\" { yy_push_state(STRING); yymore(); }
[0-9]*?['']s?[bcodhBCODH][ \t\n]*[A-Fa-f0-9xXzZ_?]* {
FL; LINECHECK(); yylval.nump = PARSEP->newNumber(yylval.fl,(char*)yytext);
return yaINTNUM;
}
[0-9]*?['']s?[01xXzZ] { /* SystemVerilog */
FL; yylval.nump = PARSEP->newNumber(yylval.fl,(char*)yytext);
return yaINTNUM;
}
/* Note below is constructed to not match the ' that begins a '( or '{ */
[0-9][_0-9]*[ \t\n]*['']s?[bcodhBCODH]?[ \t]*[A-Fa-f0-9xXzZ_?]+ {
FL; LINECHECK(); yylval.nump = PARSEP->newNumber(yylval.fl,(char*)yytext);
return yaINTNUM;
}
[0-9][_0-9]*[ \t\n]*['']s?[bcodhBCODH] {
FL; LINECHECK(); yylval.nump = PARSEP->newNumber(yylval.fl,(char*)yytext);
return yaINTNUM;
}
[0-9][_0-9]*[ \t\n]*['']s {
{vnum} {
/* "# 1'b0" is a delay value so must lex as "#" "1" "'b0" */
if (PARSEP->prevLexToken()=='#') {
int shortlen = 0;
while (isdigit(yytext[shortlen])) shortlen++;
if (shortlen) {
// Push rest for later parse
PARSEP->unputString(yytext+shortlen, yyleng-shortlen);
FL; LINECHECKS(yytext,shortlen);
// Return is stuff before '
yytext[shortlen] = '\0';
yylval.nump = PARSEP->newNumber(yylval.fl, (char*)yytext);
return yaINTNUM;
}
}
FL; LINECHECK(); yylval.nump = PARSEP->newNumber(yylval.fl,(char*)yytext);
return yaINTNUM;
}
@ -1106,8 +1111,8 @@ int V3ParseImp::lexToken() {
yylval = m_aheadVal;
} else {
// Parse new token
token = yylexThis();
//yylval // Set by yylexThis()
token = yylexReadTok();
//yylval // Set by yylexReadTok()
}
// If a paren, read another
if (token == yCONST__LEX
@ -1116,7 +1121,7 @@ int V3ParseImp::lexToken() {
) {
if (debugFlex()) { cout<<" lexToken: reading ahead to find possible strength"<<endl; }
V3ParseBisonYYSType curValue = yylval; // Remember value, as about to read ahead
int nexttok = yylexThis();
int nexttok = yylexReadTok();
m_ahead = true;
m_aheadToken = nexttok;
m_aheadVal = yylval;

18
test_regress/t/t_parse_delay.pl Executable file
View File

@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;

View File

@ -0,0 +1,20 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2014 by Wilson Snyder.
module t (/*AUTOARG*/);
// verilator lint_off WIDTH
reg [6:0] myreg1;
initial begin
myreg1 = # 100 7'd0;
myreg1 = # 100 'b0; // [#] [100] ['b0]
myreg1 = #100'b0; // [#] [100] ['b0]
myreg1 = 100'b0;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule