mirror of
https://github.com/verilator/verilator.git
synced 2025-04-16 01:26:54 +00:00
Support 1800-2009 /*comments*/ in define values. Match Verilog-Perl
This commit is contained in:
parent
78d490d5e4
commit
4df9d70e4a
2
Changes
2
Changes
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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); }
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
//======================================================================
|
||||
|
Loading…
Reference in New Issue
Block a user