Support 1800-2009 defines with default arguments.
This commit is contained in:
parent
9b0d26aedd
commit
e7cbefa316
2
Changes
2
Changes
|
|
@ -22,7 +22,7 @@ indicates the contributor was also the author of the fix; Thanks!
|
|||
|
||||
*** Support $sformat and $swrite.
|
||||
|
||||
*** Support `undefineall.
|
||||
*** Support 1800-2009 define defaults and `undefineall.
|
||||
|
||||
*** Add VARHIDDEN warning when signal name hides module name.
|
||||
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ class V3PreLex {
|
|||
bool m_pedantic; // Obey standard; don't Substitute `__FILE__ and `__LINE__
|
||||
|
||||
// State from lexer
|
||||
int m_formalLevel; // Parenthesis counting inside def formals
|
||||
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
|
||||
|
|
@ -126,6 +127,7 @@ class V3PreLex {
|
|||
m_fp = fp;
|
||||
m_keepComments = 0;
|
||||
m_pedantic = false;
|
||||
m_formalLevel = 0;
|
||||
m_parenLevel = 0;
|
||||
m_pslParenLevel = 0;
|
||||
m_pslMoreNeeded = false;
|
||||
|
|
|
|||
|
|
@ -30,18 +30,20 @@
|
|||
|
||||
V3PreLex* V3PreLex::s_currentLexp = NULL; // Current lexing point
|
||||
|
||||
#define LEXP V3PreLex::s_currentLexp
|
||||
|
||||
// Prevent conflicts from perl version
|
||||
static void linenoInc() {V3PreLex::s_currentLexp->incLineno();}
|
||||
static void linenoInc() {LEXP->incLineno();}
|
||||
static bool optPsl() { return V3PreProc::optPsl(); }
|
||||
static bool pedantic() { return V3PreLex::s_currentLexp->m_pedantic; }
|
||||
static void yyerror(char* msg) { V3PreLex::s_currentLexp->m_curFilelinep->v3error(msg); }
|
||||
static void yyerrorf(const char* msg) { V3PreLex::s_currentLexp->m_curFilelinep->v3error(msg); }
|
||||
static void appendDefValue(const char* t,int l) { V3PreLex::s_currentLexp->appendDefValue(t,l); }
|
||||
static int pslParenLevel() { return V3PreLex::s_currentLexp->m_pslParenLevel; }
|
||||
static void pslParenLevelInc() { V3PreLex::s_currentLexp->m_pslParenLevel++; }
|
||||
static void pslParenLevelDec() { if (pslParenLevel()) V3PreLex::s_currentLexp->m_pslParenLevel--; }
|
||||
static bool pslMoreNeeded() { return V3PreLex::s_currentLexp->m_pslMoreNeeded; }
|
||||
static void pslMoreNeeded(bool flag) { V3PreLex::s_currentLexp->m_pslMoreNeeded = flag; }
|
||||
static bool pedantic() { return LEXP->m_pedantic; }
|
||||
static void yyerror(char* msg) { LEXP->m_curFilelinep->v3error(msg); }
|
||||
static void yyerrorf(const char* msg) { LEXP->m_curFilelinep->v3error(msg); }
|
||||
static void appendDefValue(const char* t,int l) { LEXP->appendDefValue(t,l); }
|
||||
static int pslParenLevel() { return LEXP->m_pslParenLevel; }
|
||||
static void pslParenLevelInc() { LEXP->m_pslParenLevel++; }
|
||||
static void pslParenLevelDec() { if (pslParenLevel()) LEXP->m_pslParenLevel--; }
|
||||
static bool pslMoreNeeded() { return LEXP->m_pslMoreNeeded; }
|
||||
static void pslMoreNeeded(bool flag) { LEXP->m_pslMoreNeeded = flag; }
|
||||
|
||||
/**********************************************************************/
|
||||
%}
|
||||
|
|
@ -75,7 +77,7 @@ psl [p]sl
|
|||
/**************************************************************/
|
||||
%%
|
||||
|
||||
<INITIAL>^{ws}*"`line"{ws}+.*{crnl} { V3PreLex::s_currentLexp->lineDirective(yytext);
|
||||
<INITIAL>^{ws}*"`line"{ws}+.*{crnl} { LEXP->lineDirective(yytext);
|
||||
return(VP_LINE); }
|
||||
|
||||
/* Special directives we recognize */
|
||||
|
|
@ -92,13 +94,13 @@ psl [p]sl
|
|||
/* Optional directives we recognize */
|
||||
<INITIAL>"`__FILE__" { if (!pedantic()) {
|
||||
static string rtnfile;
|
||||
rtnfile = '"'; rtnfile += V3PreLex::s_currentLexp->m_curFilelinep->cfilename();
|
||||
rtnfile = '"'; rtnfile += LEXP->m_curFilelinep->cfilename();
|
||||
rtnfile += '"'; yytext=(char*)rtnfile.c_str(); yyleng = rtnfile.length();
|
||||
return (VP_STRING);
|
||||
} else return(VP_DEFREF); }
|
||||
<INITIAL>"`__LINE__" { if (!pedantic()) {
|
||||
static char buf[10];
|
||||
sprintf(buf, "%d",V3PreLex::s_currentLexp->m_curFilelinep->lineno());
|
||||
sprintf(buf, "%d",LEXP->m_curFilelinep->lineno());
|
||||
yytext = buf; yyleng = strlen(yytext); return (VP_TEXT);
|
||||
} else return(VP_DEFREF); }
|
||||
<INITIAL>"`error" { if (!pedantic()) return (VP_ERROR); else return(VP_DEFREF); }
|
||||
|
|
@ -111,7 +113,7 @@ psl [p]sl
|
|||
<STRMODE>{backslash}{crnl} { linenoInc(); yymore(); }
|
||||
<STRMODE>{backslash}. { yymore(); }
|
||||
<STRMODE>{quote} { yy_pop_state();
|
||||
if (V3PreLex::s_currentLexp->m_parenLevel) appendDefValue(yytext,yyleng);
|
||||
if (LEXP->m_parenLevel || LEXP->m_formalLevel) { appendDefValue(yytext,yyleng); yyleng=0; }
|
||||
else return (VP_STRING); }
|
||||
|
||||
/* Protected blocks */
|
||||
|
|
@ -130,21 +132,24 @@ psl [p]sl
|
|||
|
||||
/* Reading definition formal parenthesis (or not) to begin formal arguments */
|
||||
/* Note '(' must IMMEDIATELY follow definition name */
|
||||
<DEFFPAR>[(] { appendDefValue("(",1); BEGIN(DEFFORM); }
|
||||
<DEFFPAR>[(] { appendDefValue("(",1); LEXP->m_formalLevel=1; BEGIN(DEFFORM); }
|
||||
<DEFFPAR>{crnl} { yy_pop_state(); unput('\n'); yyleng=0; return VP_DEFFORM; } /* DEFVAL will later grab the return */
|
||||
<DEFFPAR><<EOF>> { yy_pop_state(); return VP_DEFFORM; } /* empty formals */
|
||||
<DEFFPAR>. { yy_pop_state(); unput(yytext[yyleng-1]); yyleng=0; return VP_DEFFORM; } /* empty formals */
|
||||
|
||||
/* Reading definition formals */
|
||||
<DEFFORM>[(] { yy_pop_state(); yyerrorf("Extra ( in define formal arguments.\n"); yyleng=0; return VP_DEFFORM; }
|
||||
<DEFFORM>[)] { yy_pop_state(); appendDefValue(yytext,yyleng); yyleng=0; return VP_DEFFORM; }
|
||||
<DEFFORM>[(] { appendDefValue(yytext,yyleng); yyleng=0; ++LEXP->m_formalLevel; }
|
||||
<DEFFORM>[)] { appendDefValue(yytext,yyleng); yyleng=0; if ((--LEXP->m_formalLevel)==0) { yy_pop_state(); return VP_DEFFORM; } }
|
||||
<DEFFORM>"/*" { yy_push_state(CMTMODE); yymore(); }
|
||||
<DEFFORM>"//"[^\n\r]* { return (VP_COMMENT);}
|
||||
<DEFFORM>{drop} { }
|
||||
<DEFFORM><<EOF>> { linenoInc(); yy_pop_state(); yyerrorf("Unterminated ( in define formal arguments."); yyleng=0; return VP_DEFFORM; }
|
||||
<DEFFORM>{crnl} { linenoInc(); appendDefValue((char*)"\n",1); } /* Include return so can maintain output line count */
|
||||
<DEFFORM>[\\]{crnl} { linenoInc(); appendDefValue((char*)"\n",1); } /* Include return so can maintain output line count */
|
||||
<DEFFORM>[^\/\*\n\r\\()]+ |
|
||||
<DEFFORM>{quote} { yy_push_state(STRMODE); yymore(); }
|
||||
<DEFFORM>[{\[] { LEXP->m_formalLevel++; appendDefValue(yytext,yyleng); }
|
||||
<DEFFORM>[}\]] { LEXP->m_formalLevel--; appendDefValue(yytext,yyleng); }
|
||||
<DEFFORM>[^\/\*\n\r\\(){}\[\]\"]+ |
|
||||
<DEFFORM>[\\][^\n\r] |
|
||||
<DEFFORM>. { appendDefValue(yytext,yyleng); }
|
||||
|
||||
|
|
@ -166,26 +171,24 @@ psl [p]sl
|
|||
<ARGMODE><<EOF>> { yyerrorf("EOF in define argument list\n"); yyleng = 0; yyterminate(); }
|
||||
<ARGMODE>{crnl} { linenoInc(); yytext=(char*)"\n"; yyleng=1; return(VP_WHITE); }
|
||||
<ARGMODE>{quote} { yy_push_state(STRMODE); yymore(); }
|
||||
<ARGMODE>[{\[] { V3PreLex::s_currentLexp->m_parenLevel++;
|
||||
appendDefValue(yytext,yyleng); }
|
||||
<ARGMODE>[}\]] { V3PreLex::s_currentLexp->m_parenLevel--;
|
||||
appendDefValue(yytext,yyleng); }
|
||||
<ARGMODE>[(] { V3PreLex::s_currentLexp->m_parenLevel++;
|
||||
<ARGMODE>[{\[] { LEXP->m_parenLevel++; appendDefValue(yytext,yyleng); }
|
||||
<ARGMODE>[}\]] { LEXP->m_parenLevel--; appendDefValue(yytext,yyleng); }
|
||||
<ARGMODE>[(] { LEXP->m_parenLevel++;
|
||||
// Note paren level 0 means before "(" of starting args
|
||||
// Level 1 means "," between arguments
|
||||
// Level 2+ means one argument's internal ()
|
||||
if (V3PreLex::s_currentLexp->m_parenLevel>1) {
|
||||
if (LEXP->m_parenLevel>1) {
|
||||
appendDefValue(yytext,yyleng);
|
||||
} else {
|
||||
return (VP_TEXT);
|
||||
}}
|
||||
<ARGMODE>[)] { V3PreLex::s_currentLexp->m_parenLevel--;
|
||||
if (V3PreLex::s_currentLexp->m_parenLevel>0) {
|
||||
<ARGMODE>[)] { LEXP->m_parenLevel--;
|
||||
if (LEXP->m_parenLevel>0) {
|
||||
appendDefValue(yytext,yyleng);
|
||||
} else {
|
||||
yy_pop_state(); return (VP_DEFARG);
|
||||
}}
|
||||
<ARGMODE>[,] { if (V3PreLex::s_currentLexp->m_parenLevel>1) {
|
||||
<ARGMODE>[,] { if (LEXP->m_parenLevel>1) {
|
||||
appendDefValue(yytext,yyleng);
|
||||
} else {
|
||||
yy_pop_state(); return (VP_DEFARG);
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ private:
|
|||
FileLine* defFileline(const string& name);
|
||||
|
||||
bool commentTokenMatch(string& cmdr, const char* strg);
|
||||
string trimWhitespace(const string& strg);
|
||||
string trimWhitespace(const string& strg, bool trailing);
|
||||
void unputString(const string& strg);
|
||||
|
||||
void parsingOn() {
|
||||
|
|
@ -411,10 +411,19 @@ void V3PreProcImp::unputString(const string& strg) {
|
|||
m_lexp->scanBytes(strg);
|
||||
}
|
||||
|
||||
string V3PreProcImp::trimWhitespace(const string& strg) {
|
||||
string V3PreProcImp::trimWhitespace(const string& strg, bool trailing) {
|
||||
// Remove leading whitespace
|
||||
string out = strg;
|
||||
while (out.length()>0 && isspace(out[0])) {
|
||||
out.erase(0,1);
|
||||
string::size_type leadspace = 0;
|
||||
while (out.length() > leadspace
|
||||
&& isspace(out[leadspace])) leadspace++;
|
||||
if (leadspace) out.erase(0,leadspace);
|
||||
// Remove trailing whitespace
|
||||
if (trailing) {
|
||||
string::size_type trailspace = 0;
|
||||
while (out.length() > trailspace
|
||||
&& isspace(out[out.length()-1-trailspace])) trailspace++;
|
||||
if (trailspace) out.erase(out.length()-trailspace,trailspace);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
|
@ -429,7 +438,7 @@ string V3PreProcImp::defineSubst(V3DefineRef* refp) {
|
|||
// parsed result.
|
||||
UINFO(4,"defineSubstIn `"<<refp->name()<<" "<<refp->params()<<endl);
|
||||
for (unsigned i=0; i<refp->args().size(); i++) {
|
||||
UINFO(4,"defineArg["<<i<<"] = "<<refp->args()[i]<<endl);
|
||||
UINFO(4,"defineArg["<<i<<"] = '"<<refp->args()[i]<<"'"<<endl);
|
||||
}
|
||||
// Grab value
|
||||
string value = defValue(refp->name());
|
||||
|
|
@ -439,27 +448,63 @@ string V3PreProcImp::defineSubst(V3DefineRef* refp) {
|
|||
{ // Parse argument list into map
|
||||
unsigned numArgs=0;
|
||||
string argName;
|
||||
for (const char* cp=refp->params().c_str(); *cp; cp++) {
|
||||
if (*cp=='(') {
|
||||
} else if (argName=="" && isspace(*cp)) {
|
||||
} else if (isspace(*cp) || *cp==')' || *cp==',') {
|
||||
int paren = 1; // (), {} and [] can use same counter, as must be matched pair per spec
|
||||
string token;
|
||||
bool quote = false;
|
||||
bool haveDefault = false;
|
||||
// Note there's a leading ( and trailing ), so parens==1 is the base parsing level
|
||||
const char* cp=refp->params().c_str();
|
||||
if (*cp == '(') cp++;
|
||||
for (; *cp; cp++) {
|
||||
//UINFO(4," Parse Paren="<<paren<<" Arg="<<numArgs<<" token='"<<token<<"' Parse="<<cp<<endl);
|
||||
if (!quote && paren==1) {
|
||||
if (*cp==')' || *cp==',') {
|
||||
string value;
|
||||
if (haveDefault) { value=token; } else { argName=token; }
|
||||
argName = trimWhitespace(argName,true);
|
||||
UINFO(4," Got Arg="<<numArgs<<" argName='"<<argName<<"' default='"<<value<<"'"<<endl);
|
||||
// Parse it
|
||||
if (argName!="") {
|
||||
if (refp->args().size() > numArgs) {
|
||||
// A call `def( a ) must be equivelent to `def(a ), so trimWhitespace
|
||||
// Note other sims don't trim trailing whitespace, so we don't either.
|
||||
argValueByName[argName] = trimWhitespace(refp->args()[numArgs]);
|
||||
string arg = trimWhitespace(refp->args()[numArgs], false);
|
||||
if (arg != "") value = arg;
|
||||
} else if (!haveDefault) {
|
||||
fileline()->v3error("Define missing argument '"+argName+"' for: "+refp->name()+"\n");
|
||||
return " `"+refp->name()+" ";
|
||||
}
|
||||
numArgs++;
|
||||
//cout << " arg "<<argName<<endl;
|
||||
}
|
||||
argValueByName[argName] = value;
|
||||
// Prepare for next
|
||||
argName = "";
|
||||
} else if ( isalpha(*cp) || *cp=='_'
|
||||
|| (argName!="" && (isdigit(*cp) || *cp=='$'))) {
|
||||
argName += *cp;
|
||||
token = "";
|
||||
haveDefault = false;
|
||||
continue;
|
||||
}
|
||||
else if (*cp=='=') {
|
||||
haveDefault = true;
|
||||
argName = token;
|
||||
token = "";
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (refp->args().size() != numArgs) {
|
||||
fileline()->v3error("Define passed wrong number of arguments: "+refp->name()+"\n");
|
||||
if (cp[0]=='\\' && cp[1]) {
|
||||
token += cp[0]; // \{any} Put out literal next character
|
||||
token += cp[1];
|
||||
cp++;
|
||||
continue;
|
||||
}
|
||||
if (!quote) {
|
||||
if (*cp=='(' || *cp=='{' || *cp=='[') paren++;
|
||||
else if (*cp==')' || *cp=='}' || *cp==']') paren--;
|
||||
}
|
||||
if (*cp=='"') quote=!quote;
|
||||
if (*cp) token += *cp;
|
||||
}
|
||||
if (refp->args().size() > numArgs) {
|
||||
fileline()->v3error("Define passed too many arguments: "+refp->name()+"\n");
|
||||
return " `"+refp->name()+" ";
|
||||
}
|
||||
}
|
||||
|
|
@ -768,42 +813,27 @@ int V3PreProcImp::getToken() {
|
|||
if (tok == VP_DEFVALUE) {
|
||||
if (debug()) cout<<"DefValue='"<<m_lexp->m_defValue<<"' formals='"<<m_formals<<"'\n";
|
||||
// Add any formals
|
||||
string formAndValue = m_formals + m_lexp->m_defValue;
|
||||
string formals = m_formals;
|
||||
string value = m_lexp->m_defValue;
|
||||
// Remove returns
|
||||
for (unsigned i=0; i<formAndValue.length(); i++) {
|
||||
if (formAndValue[i] == '\n') {
|
||||
formAndValue[i] = ' ';
|
||||
for (unsigned i=0; i<formals.length(); i++) {
|
||||
if (formals[i] == '\n') {
|
||||
formals[i] = ' ';
|
||||
newlines += "\n";
|
||||
}
|
||||
}
|
||||
for (unsigned i=0; i<value.length(); i++) {
|
||||
if (value[i] == '\n') {
|
||||
value[i] = ' ';
|
||||
newlines += "\n";
|
||||
}
|
||||
}
|
||||
if (!m_off) {
|
||||
string params;
|
||||
if (formAndValue=="" || isspace(formAndValue[0])) {
|
||||
// Define without parameters
|
||||
} else if (formAndValue[0] == '(') {
|
||||
string::size_type paren = formAndValue.find(")");
|
||||
if (paren == string::npos) {
|
||||
fileline()->v3error("Missing ) to end define arguments.");
|
||||
} else {
|
||||
params = formAndValue.substr(0, paren+1);
|
||||
formAndValue.replace(0, paren+1, "");
|
||||
}
|
||||
} else {
|
||||
fileline()->v3error("Missing space or paren to start define value.");
|
||||
}
|
||||
// Remove leading whitespace
|
||||
unsigned leadspace = 0;
|
||||
while (formAndValue.length() > leadspace
|
||||
&& isspace(formAndValue[leadspace])) leadspace++;
|
||||
if (leadspace) formAndValue.erase(0,leadspace);
|
||||
// Remove trailing whitespace
|
||||
unsigned trailspace = 0;
|
||||
while (formAndValue.length() > trailspace
|
||||
&& isspace(formAndValue[formAndValue.length()-1-trailspace])) trailspace++;
|
||||
if (trailspace) formAndValue.erase(formAndValue.length()-trailspace,trailspace);
|
||||
// Remove leading and trailing whitespace
|
||||
value = trimWhitespace(value, true);
|
||||
// Define it
|
||||
UINFO(4,"Define "<<m_lastSym<<" = '"<<formAndValue<<"'"<<endl);
|
||||
define(fileline(), m_lastSym, formAndValue, params, false);
|
||||
UINFO(4,"Define "<<m_lastSym<<" "<<formals<<" = '"<<value<<"'"<<endl);
|
||||
define(fileline(), m_lastSym, value, formals, false);
|
||||
}
|
||||
} else {
|
||||
fileline()->v3fatalSrc("Bad define text\n");
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ private:
|
|||
outrefp = outp->castSel()->fromp()->castVarRef();
|
||||
width = outp->castSel()->widthConst();
|
||||
} else {
|
||||
v3error("Can't find LHS varref");
|
||||
nodep->v3error("Can't find LHS varref");
|
||||
}
|
||||
outrefp->lvalue(true);
|
||||
AstVar* varp = outrefp->varp();
|
||||
|
|
@ -185,7 +185,7 @@ private:
|
|||
} else if (outp->castSel()) {
|
||||
outrefp = outp->castSel()->fromp()->castVarRef();
|
||||
} else {
|
||||
v3error("Can't find LHS varref");
|
||||
nodep->v3error("Can't find LHS varref");
|
||||
}
|
||||
|
||||
createEnableVar(outp, outrefp, enrhsp, outrhsp->width());
|
||||
|
|
@ -215,7 +215,7 @@ private:
|
|||
enrhsp = new AstReplicate(enrhsp->fileline(), enrhsp, new AstConst(enrhsp->fileline(), V3Number(enrhsp->fileline(), 32, enp->width())));
|
||||
enrhsp->width(enp->width(), enp->widthMin());
|
||||
} else {
|
||||
v3error("Don't know how to deal with selection logic wider than 1 bit");
|
||||
enrhsp->v3error("Don't know how to deal with selection logic wider than 1 bit");
|
||||
}
|
||||
}
|
||||
m_modp->addStmtp(enp);
|
||||
|
|
@ -351,7 +351,7 @@ private:
|
|||
// not sure what I should do here other than error that they are mixing low-Z and tristate drivers.
|
||||
// The other scenerio, and probably more likely, is that they are using a high-Z construct that
|
||||
// is not supported. Improving the high-Z detection logic will reduce the occurance of this failure.
|
||||
v3error("Mixing tristate and low-Z drivers. Perhaps you are using a high-Z construct not supported");
|
||||
nodep->v3error("Mixing tristate and low-Z drivers. Perhaps you are using a high-Z construct not supported");
|
||||
} else {
|
||||
UINFO(9, " No tristates found on " << lhsp <<endl);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,75 @@
|
|||
`line 1 "t/t_preproc_def09.v" 1
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
'initial $display("start", "msg1" , "msg2" , "end");'
|
||||
'initial $display("start", "msg1" , "msg2" , "end");'
|
||||
'initial $display("start", " msg1" , , "end");'
|
||||
'initial $display("start", " msg1" , , "end");'
|
||||
'initial $display("start", , "msg2 ", "end");'
|
||||
'initial $display("start", , "msg2 ", "end");'
|
||||
'initial $display("start", , , "end");'
|
||||
'initial $display("start", , , "end");'
|
||||
'initial $display("start", , , "end");'
|
||||
'initial $display("start", , , "end");'
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
'$display(5,,2,,3 );'
|
||||
'$display(5,,2,,3);'
|
||||
'$display(1 ,,"B",,3 );'
|
||||
'$display(1 ,,"B",,3 );'
|
||||
'$display(5,,2,,);'
|
||||
'$display(5,,2,,);'
|
||||
|
||||
|
||||
|
||||
'$display(1,,,,3);'
|
||||
'$display(5,,,,"C");'
|
||||
'$display(5,,2,,"C");'
|
||||
'$display(5,,2,,"C");'
|
||||
'$display(5,,2,,"C");'
|
||||
'$display(5,,2,,"C");'
|
||||
|
||||
|
||||
'$display(1 ,,0,,"C");'
|
||||
'$display(1 ,,0,,"C");'
|
||||
'$display(5,,0,,"C");'
|
||||
'$display(5,,0,,"C");'
|
||||
|
||||
|
||||
|
||||
'b + 1 + 42 + a '
|
||||
'b + 1 + 42 + a'
|
||||
|
||||
|
||||
|
||||
'"==)" "((((" () ';
|
||||
'"==)" "((((" () ';
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
'(6) (eq=al) ZOT'
|
||||
HERE-71 - Line71
|
||||
|
||||
|
||||
`line 74 "t/t_preproc_def09.v" 2
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003-2009 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.
|
||||
|
||||
my $stdout_filename = "$Self->{obj_dir}/$Self->{name}__test.vpp";
|
||||
|
||||
if (!$Self->{v3}) {
|
||||
ok(1);
|
||||
} else {
|
||||
compile (
|
||||
v_flags2 => ['-E'],
|
||||
verilator_make_gcc=>0,
|
||||
stdout_filename => $stdout_filename,
|
||||
);
|
||||
ok(files_identical($stdout_filename, "t/$Self->{name}.out"));
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2009 by Wilson Snyder.
|
||||
|
||||
`undefineall
|
||||
|
||||
// Definitions as speced
|
||||
// Note there are trailing spaces, which spec doesn't show properly
|
||||
`define D(x,y) initial $display("start", x , y, "end");
|
||||
'`D( "msg1" , "msg2" )'
|
||||
'initial $display("start", "msg1" , "msg2" , "end");'
|
||||
'`D( " msg1", )'
|
||||
'initial $display("start", " msg1" , , "end");'
|
||||
'`D(, "msg2 ")'
|
||||
'initial $display("start", , "msg2 ", "end");'
|
||||
'`D(,)'
|
||||
'initial $display("start", , , "end");'
|
||||
'`D( , )'
|
||||
'initial $display("start", , , "end");'
|
||||
//`D("msg1") // ILLEGAL: only one argument
|
||||
//`D() // ILLEGAL: only one empty argument
|
||||
//`D(,,) // ILLEGAL: more actual than formal arguments
|
||||
|
||||
// Defaults:
|
||||
`define MACRO1(a=5,b="B",c) $display(a,,b,,c);
|
||||
'`MACRO1 ( , 2, 3 )'
|
||||
'$display(5,,2,,3);'
|
||||
'`MACRO1 ( 1 , , 3 )'
|
||||
'$display(1 ,,"B",,3 );'
|
||||
'`MACRO1 ( , 2, )'
|
||||
'$display(5,,2,,);'
|
||||
//`MACRO1 ( 1 ) // ILLEGAL: b and c omitted, no default for c
|
||||
|
||||
`define MACRO2(a=5, b, c="C") $display(a,,b,,c);
|
||||
'`MACRO2 (1, , 3)'
|
||||
'$display(5,,,,"C");'
|
||||
'`MACRO2 (, 2, )'
|
||||
'$display(5,,2,,"C");'
|
||||
'`MACRO2 (, 2)'
|
||||
'$display(5,,2,,"C");'
|
||||
|
||||
`define MACRO3(a=5, b=0, c="C") $display(a,,b,,c);
|
||||
'`MACRO3 ( 1 )'
|
||||
'$display(1 ,,0,,"C");'
|
||||
'`MACRO3 ( )'
|
||||
'$display(5,,0,,"C");'
|
||||
//`MACRO3 // ILLEGAL: parentheses required
|
||||
|
||||
`define DTOP(a,b) a + b
|
||||
'`DTOP( `DTOP(b,1), `DTOP(42,a) )'
|
||||
'b + 1 + 42 + a'
|
||||
|
||||
// Local tests
|
||||
`define MACROQUOTE(a="==)",b="((((",c=() ) 'a b c'
|
||||
`MACROQUOTE();
|
||||
'"==)" "((((" () ';
|
||||
|
||||
// Also check our line counting doesn't go bad
|
||||
`define MACROPAREN(a=(6),
|
||||
b=(eq=al),
|
||||
c) 'a b c'
|
||||
`MACROPAREN(
|
||||
|
||||
|
||||
|
||||
,,
|
||||
|
||||
|
||||
ZOT)
|
||||
HERE-`__LINE__ - Line71
|
||||
|
||||
//======================================================================
|
||||
Loading…
Reference in New Issue