Support 1800-2009 /*comments*/ in define values. Match Verilog-Perl

This commit is contained in:
Wilson Snyder 2010-01-28 09:41:24 -05:00
parent 78d490d5e4
commit 4df9d70e4a
7 changed files with 148 additions and 19 deletions

View File

@ -50,6 +50,8 @@ indicates the contributor was also the author of the fix; Thanks!
**** Support for loop i++, ++i, i--, --i, bug175. [by Byron Bradley]
**** Support 1800-2009 /*comments*/ in define values.
**** Add Makefile VM_GLOBAL_FAST, listing objects needed to link executables.
**** Add --bbox-unsup option to black-box unsupported UDP tables.

View File

@ -119,6 +119,7 @@ class V3PreLex {
int m_parenLevel; // Parenthesis counting inside def args
int m_pslParenLevel;// PSL Parenthesis (){} counting, so we can find final ;
bool m_pslMoreNeeded;// Next // comment is really psl
bool m_defCmtSlash; // /*...*/ comment in define had \ ending
string m_defValue; // Definition value being built.
// CONSTRUCTORS
@ -127,6 +128,7 @@ class V3PreLex {
m_pedantic = false;
m_formalLevel = 0;
m_parenLevel = 0;
m_defCmtSlash = false;
m_pslParenLevel = 0;
m_pslMoreNeeded = false;
}

View File

@ -59,6 +59,7 @@ static void pslMoreNeeded(bool flag) { LEXP->m_pslMoreNeeded = flag; }
%x DEFFPAR
%x DEFFORM
%x DEFVAL
%x DEFCMT
%x ARGMODE
%x INCMODE
%x PRTMODE
@ -151,16 +152,27 @@ psl [p]sl
<DEFFORM>. { appendDefValue(yytext,yyleng); }
/* Reading definition value */
<DEFVAL>"/*" { yy_push_state(CMTMODE); yymore(); }
<DEFVAL>"/*" { LEXP->m_defCmtSlash=false; yy_push_state(DEFCMT); yymore(); } /* Special comment parser */
<DEFVAL>"//"[^\n\r]* { return (VP_COMMENT);}
<DEFVAL>{drop} { }
<DEFVAL><<EOF>> { linenoInc(); yy_pop_state(); yytext=(char*)"\n"; yyleng=1; return (VP_DEFVALUE); } /* Technically illegal, but people complained */
<DEFVAL>{crnl} { linenoInc(); yy_pop_state(); yytext=(char*)"\n"; yyleng=1; return (VP_DEFVALUE); }
<DEFVAL>[\\]{crnl} { linenoInc(); appendDefValue((char*)"\n",1); } /* Include return so can maintain output line count */
<DEFVAL>[\\]{crnl} { linenoInc(); appendDefValue((char*)"\n",1); } /* Return, but not \ is part of define value */
<DEFVAL>[^\/\*\n\r\\]+ |
<DEFVAL>[\\][^\n\r] |
<DEFVAL>. { appendDefValue(yytext,yyleng); }
/* Comments inside define values - if embedded get added to define value per spec */
/* - if no \{crnl} ending then the comment belongs to the next line, as a non-embedded comment */
/* - if all but (say) 3rd line is missing \ then it's indeterminate */
<DEFCMT>"*/" { yy_pop_state(); appendDefValue(yytext,yyleng); }
<DEFCMT>[\\]{crnl} { linenoInc(); LEXP->m_defCmtSlash=true;
appendDefValue(yytext,yyleng-2); appendDefValue((char*)"\n",1); } /* Return but not \ */
<DEFCMT>{crnl} { linenoInc(); yymore(); if (LEXP->m_defCmtSlash) yyerrorf("One line of /* ... */ is missing \\ before newline");
BEGIN(CMTMODE); }
<DEFCMT>. { yymore(); }
<DEFCMT><<EOF>> { yyerrorf("EOF in '/* ... */' block comment\n"); yyleng=0; yyterminate(); }
/* Define arguments */
<ARGMODE>"/*" { yy_push_state(CMTMODE); yymore(); }
<ARGMODE>"//"[^\n\r]* { return (VP_COMMENT);}
@ -214,6 +226,7 @@ psl [p]sl
<PSLONEE>. { yyerrorf("Unexpected text following psl assertion\n"); }
/* C-style comments. */
/**** See also DEFCMT */
/* We distinguish between the start of a comment, and later, so we may find a "psl" prefix */
<INITIAL>"/*" { yy_push_state(optPsl() ? CMTBEGM : CMTMODE); yymore(); }
<CMTBEGM>{psl} { yyleng -= 3; BEGIN PSLMUL1; return (VP_COMMENT); }

View File

@ -146,6 +146,7 @@ struct V3PreProcImp : public V3PreProc {
const char* tokenName(int tok);
int getRawToken();
int getToken();
void debugToken(int tok, const char* cmtp);
void parseTop();
void parseUndef();
@ -679,7 +680,8 @@ int V3PreProcImp::getRawToken() {
m_lineAdd--;
m_rawAtBol = true;
yytext=(char*)"\n"; yyleng=1;
return (VP_TEXT);
if (debug()) debugToken(VP_WHITE, "LNA");
return (VP_WHITE);
}
if (m_lineCmt!="") {
// We have some `line directive or other processed data to return to the user.
@ -696,6 +698,7 @@ int V3PreProcImp::getRawToken() {
V3PreLex::s_currentLexp->appendDefValue(yytext,yyleng);
goto next_tok;
} else {
if (debug()) debugToken(VP_TEXT, "LCM");
return (VP_TEXT);
}
}
@ -706,15 +709,7 @@ int V3PreProcImp::getRawToken() {
V3PreLex::s_currentLexp = m_lexp; // Tell parser where to get/put data
int tok = yylex();
if (debug()>4) {
string buf = string (yytext, yyleng);
string::size_type pos;
while ((pos=buf.find("\n")) != string::npos) { buf.replace(pos, 1, "\\n"); }
while ((pos=buf.find("\r")) != string::npos) { buf.replace(pos, 1, "\\r"); }
fprintf (stderr, "%d: RAW %s s%d dr%d: <%d>%-10s: %s\n",
fileline()->lineno(), m_off?"of":"on", m_state, (int)m_defRefs.size(),
m_lexp->currentStartState(), tokenName(tok), buf.c_str());
}
if (debug()) debugToken(tok, "RAW");
// On EOF, try to pop to upper level includes, as needed.
if (tok==VP_EOF) {
@ -727,6 +722,18 @@ int V3PreProcImp::getRawToken() {
}
}
void V3PreProcImp::debugToken(int tok, const char* cmtp) {
if (debug()>4) {
string buf = string (yytext, yyleng);
string::size_type pos;
while ((pos=buf.find("\n")) != string::npos) { buf.replace(pos, 1, "\\n"); }
while ((pos=buf.find("\r")) != string::npos) { buf.replace(pos, 1, "\\r"); }
fprintf (stderr, "%d: %s %s s%d dr%d: <%d>%-10s: %s\n",
fileline()->lineno(), cmtp, m_off?"of":"on", m_state, (int)m_defRefs.size(),
m_lexp->currentStartState(), tokenName(tok), buf.c_str());
}
}
// Sorry, we're not using bison/yacc. It doesn't handle returning white space
// in the middle of parsing other tokens.
@ -803,6 +810,11 @@ int V3PreProcImp::getToken() {
else fileline()->v3fatalSrc("Bad case\n");
goto next_tok;
}
else if (tok==VP_TEXT) {
// IE, something like comment between define and symbol
if (!m_off) return tok;
else goto next_tok;
}
else {
fileline()->v3error("Expecting define name. Found: "<<tokenName(tok));
goto next_tok;
@ -833,13 +845,17 @@ int V3PreProcImp::getToken() {
string formals = m_formals;
string value = m_lexp->m_defValue;
// Remove returns
for (unsigned i=0; i<formals.length(); i++) {
// Not removing returns in values has two problems,
// 1. we need to correct line numbers with `line after each substitution
// 2. Substituting in " .... " with embedded returns requires \ escape.
// This is very difficult in the presence of `".
for (size_t i=0; i<formals.length(); i++) {
if (formals[i] == '\n') {
formals[i] = ' ';
newlines += "\n";
}
}
for (unsigned i=0; i<value.length(); i++) {
for (size_t i=0; i<value.length(); i++) {
if (value[i] == '\n') {
value[i] = ' ';
newlines += "\n";
@ -853,7 +869,8 @@ int V3PreProcImp::getToken() {
define(fileline(), m_lastSym, value, formals, false);
}
} else {
fileline()->v3fatalSrc("Bad define text\n");
string msg = string("Bad define text, unexpected ")+tokenName(tok)+"\n";
fileline()->v3fatalSrc(msg);
}
m_state = ps_TOP;
// DEFVALUE is terminated by a return, but lex can't return both tokens.

View File

@ -13,7 +13,7 @@
// please note it here, otherwise:**
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2009 by Wilson Snyder.
// without warranty, 2010 by Wilson Snyder.
module t (/*AUTOARG*/
// Inputs

View File

@ -78,7 +78,7 @@ text.
foo bar
foo bar
foobar2
@ -203,4 +203,54 @@ x,y)--bee submacro has comma paren
$display("bits %d %d", $bits(foo), `10);
`line 158 "t/t_preproc.v" 2
`line 173 "t/t_preproc.v" 0
`line 173 "t/t_preproc.v" 0
assign a3 = ~b3 ;
\
def foo
1 /*verilator NOT IN DEFINE*/ (nodef)
2 /*verilator PART OF DEFINE*/ (hasdef)
3 /*verilator NOT PART OF DEFINE*/ (nodef)
4 /*verilator PART OF DEFINE*/ (nodef)
HAS a NEW LINE
`line 203 "t/t_preproc.v" 2

View File

@ -30,7 +30,7 @@
text.
`define FOOBAR foo /*but not */ bar /* or this either */
`define FOOBAR foo /*this */ bar /* this too */
`define FOOBAR2 foobar2 // but not
`FOOBAR
`FOOBAR2
@ -155,3 +155,48 @@ Line_Preproc_Check `__LINE__
// bug191
`define bug191(bits) $display("bits %d %d", $bits(foo), `bits);
`bug191(10)
//======================================================================
// bug202
`define FC_INV3(out, in) \
`ifdef DC \
cell \inv_``out <$typeof(out)> (.a(<in>), .o(<out>)); \
/* multi-line comment \
multi-line comment */ \
`else \
`ifdef MACRO_ATTRIBUTE \
(* macro_attribute = `"INV (out``,in``)`" *) \
`endif \
assign out = ~in ; \
`endif
`FC_INV3(a3,b3)
`define /* multi \
line1*/ \
bug202( i /*multi \
line2*/ \
) \
/* multi \
line 3*/ \
def i \
`bug202(foo)
//======================================================================
`define CMT1 // verilator NOT IN DEFINE
`define CMT2 /* verilator PART OF DEFINE */
`define CMT3 /* verilator NOT PART
OF DEFINE */
`define CMT4 /* verilator PART \
OF DEFINE */
1 `CMT1 (nodef)
2 `CMT2 (hasdef)
3 `CMT3 (nodef)
4 `CMT4 (nodef)
`define NL HAS a NEW \
LINE
`NL
//======================================================================