From 4df9d70e4af04b4d72adedff62e2a479e6b8ed5d Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Thu, 28 Jan 2010 09:41:24 -0500 Subject: [PATCH] Support 1800-2009 /*comments*/ in define values. Match Verilog-Perl --- Changes | 2 ++ src/V3PreLex.h | 2 ++ src/V3PreLex.l | 17 ++++++++++-- src/V3PreProc.cpp | 43 +++++++++++++++++++--------- test_regress/t/t_EXAMPLE.v | 2 +- test_regress/t/t_preproc.out | 54 ++++++++++++++++++++++++++++++++++-- test_regress/t/t_preproc.v | 47 ++++++++++++++++++++++++++++++- 7 files changed, 148 insertions(+), 19 deletions(-) diff --git a/Changes b/Changes index 45bd0ed9d..29578c769 100644 --- a/Changes +++ b/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. diff --git a/src/V3PreLex.h b/src/V3PreLex.h index 8e944cd6d..2dc6cb5af 100644 --- a/src/V3PreLex.h +++ b/src/V3PreLex.h @@ -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; } diff --git a/src/V3PreLex.l b/src/V3PreLex.l index b7780daa3..c26403534 100644 --- a/src/V3PreLex.l +++ b/src/V3PreLex.l @@ -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 . { appendDefValue(yytext,yyleng); } /* Reading definition value */ -"/*" { yy_push_state(CMTMODE); yymore(); } +"/*" { LEXP->m_defCmtSlash=false; yy_push_state(DEFCMT); yymore(); } /* Special comment parser */ "//"[^\n\r]* { return (VP_COMMENT);} {drop} { } <> { linenoInc(); yy_pop_state(); yytext=(char*)"\n"; yyleng=1; return (VP_DEFVALUE); } /* Technically illegal, but people complained */ {crnl} { linenoInc(); yy_pop_state(); yytext=(char*)"\n"; yyleng=1; return (VP_DEFVALUE); } -[\\]{crnl} { linenoInc(); appendDefValue((char*)"\n",1); } /* Include return so can maintain output line count */ +[\\]{crnl} { linenoInc(); appendDefValue((char*)"\n",1); } /* Return, but not \ is part of define value */ [^\/\*\n\r\\]+ | [\\][^\n\r] | . { 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 */ +"*/" { yy_pop_state(); appendDefValue(yytext,yyleng); } +[\\]{crnl} { linenoInc(); LEXP->m_defCmtSlash=true; + appendDefValue(yytext,yyleng-2); appendDefValue((char*)"\n",1); } /* Return but not \ */ +{crnl} { linenoInc(); yymore(); if (LEXP->m_defCmtSlash) yyerrorf("One line of /* ... */ is missing \\ before newline"); + BEGIN(CMTMODE); } +. { yymore(); } +<> { yyerrorf("EOF in '/* ... */' block comment\n"); yyleng=0; yyterminate(); } + /* Define arguments */ "/*" { yy_push_state(CMTMODE); yymore(); } "//"[^\n\r]* { return (VP_COMMENT);} @@ -214,6 +226,7 @@ psl [p]sl . { 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 */ "/*" { yy_push_state(optPsl() ? CMTBEGM : CMTMODE); yymore(); } {psl} { yyleng -= 3; BEGIN PSLMUL1; return (VP_COMMENT); } diff --git a/src/V3PreProc.cpp b/src/V3PreProc.cpp index c7429b2a8..df7c1fc80 100644 --- a/src/V3PreProc.cpp +++ b/src/V3PreProc.cpp @@ -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: "<m_defValue; // Remove returns - for (unsigned i=0; iv3fatalSrc("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. diff --git a/test_regress/t/t_EXAMPLE.v b/test_regress/t/t_EXAMPLE.v index 3c2e1c20f..820fa557c 100644 --- a/test_regress/t/t_EXAMPLE.v +++ b/test_regress/t/t_EXAMPLE.v @@ -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 diff --git a/test_regress/t/t_preproc.out b/test_regress/t/t_preproc.out index 07ac975da..24a3d959a 100644 --- a/test_regress/t/t_preproc.out +++ b/test_regress/t/t_preproc.out @@ -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 diff --git a/test_regress/t/t_preproc.v b/test_regress/t/t_preproc.v index c5670aea4..a8456ca99 100644 --- a/test_regress/t/t_preproc.v +++ b/test_regress/t/t_preproc.v @@ -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(), .o()); \ + /* 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 + +//======================================================================