Support $test$plusargs and $value$plusargs, but see the docs.

This commit is contained in:
Wilson Snyder 2009-11-19 17:04:21 -05:00
parent 19d62b7a68
commit 62f707f501
20 changed files with 403 additions and 55 deletions

View File

@ -16,6 +16,8 @@ indicates the contributor was also the author of the fix; Thanks!
*** Support declarations in loop initializers, bug172. [by Byron Bradley]
*** Support $test$plusargs and $value$plusargs, but see the docs!
*** Add VARHIDDEN warning when signal name hides module name.
**** Fix MinGW compilation, bug184. [by Shankar Giri]

View File

@ -768,6 +768,7 @@ We'll compile this example into C++.
#include "Vour.h"
#include "verilated.h"
int main(int argc, char **argv, char **env) {
Verilated::commandArgs(argc, argv);
Vour* top = new Vour;
while (!Verilated::gotFinish()) { top->eval(); }
exit(0);
@ -825,6 +826,7 @@ This is an example similar to the above, but using SystemPerl.
cat <<EOF >sc_main.cpp
#include "Vour.h"
int sc_main(int argc, char **argv) {
Verilated::commandArgs(argc, argv);
sc_clock clk ("clk",10, 0.5, 3, true);
Vour* top;
top = new Vour("top"); // SP_CELL (top, Vour);
@ -1080,7 +1082,9 @@ example:
return main_time;
}
int main() {
int main(int argc, char** argv) {
Verilated::commandArgs(argc, argv); // Remember args
top = new Vtop; // Create instance
top->reset_l = 0; // Set some inputs
@ -1784,6 +1788,22 @@ arrays.
Treated as $time.
=item $test$plusargs, $value$plusargs
Supported, but the instantiating C++/SystemC testbench must call
Verilated::commandArgs(argc, argv);
to register the command line before calling $test$plusargs or
$value$plusargs.
=item $timeformat
Not supported as Verilator needs to determine all formatting at compile
time. Generally you can just ifdef them out for no ill effect. Note also
VL_TIME_MULTIPLER can be defined at compile time to move the decimal point
when displaying all times, model wide.
=back
=head1 ERRORS AND WARNINGS

View File

@ -25,6 +25,7 @@
#include "verilated.h"
#include <cctype>
#include <vector>
#define VL_VALUE_STRING_MAX_WIDTH 1024 ///< Max static char array for VL_VALUE_STRING
@ -37,6 +38,38 @@ bool Verilated::s_calcUnusedSigs = false;
bool Verilated::s_gotFinish = false;
bool Verilated::s_assertOn = true;
//===========================================================================
// Local Implementation Globals
// (Not in Verilated as they can be slow, and we want to mimimize the STL imports)
class VerilatedImp {
protected:
friend class Verilated;
typedef vector<string> ArgVec;
static ArgVec s_argVec; // Argument list
static bool s_argVecLoaded; // Ever loaded argument list
// METHODS
public: // But only for this C file
static string argPlusMatch(const char* prefixp) {
int len = strlen(prefixp);
if (!s_argVecLoaded) {
s_argVecLoaded = true; // Complain only once
vl_fatal("unknown",0,"",
"%Error: Verilog called $test$plusargs or $value$plusargs without"
" testbench C first calling Verilated::commandArgs(argc,argv).");
}
for (ArgVec::iterator it=s_argVec.begin(); it!=s_argVec.end(); ++it) {
if ((*it)[0]=='+') {
if (0==strncmp(prefixp, it->c_str()+1, len)) return *it;
}
}
return "";
}
};
VerilatedImp::ArgVec VerilatedImp::s_argVec;
bool VerilatedImp::s_argVecLoaded = false;
//===========================================================================
// User definable functions
@ -441,6 +474,32 @@ static inline void _vl_vsss_setbit(WDataOutP owp, int obits, int lsb, int nbits,
VL_ASSIGNBIT_WI(0, lsb, owp, ld & 1);
}
}
static inline void _vl_vsss_based(WDataOutP owp, int obits, int baseLog2, const char* strp, int posstart, int posend) {
// Read in base "2^^baseLog2" digits from strp[posstart..posend-1] into owp of size obits.
int lsb = 0;
for (int i=0, pos=posend-1; i<obits && pos>=posstart; pos--) {
switch (tolower (strp[pos])) {
case 'x': case 'z': case '?': //FALLTHRU
case '0': lsb += baseLog2; break;
case '1': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 1); lsb+=baseLog2; break;
case '2': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 2); lsb+=baseLog2; break;
case '3': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 3); lsb+=baseLog2; break;
case '4': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 4); lsb+=baseLog2; break;
case '5': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 5); lsb+=baseLog2; break;
case '6': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 6); lsb+=baseLog2; break;
case '7': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 7); lsb+=baseLog2; break;
case '8': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 8); lsb+=baseLog2; break;
case '9': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 9); lsb+=baseLog2; break;
case 'a': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 10); lsb+=baseLog2; break;
case 'b': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 11); lsb+=baseLog2; break;
case 'c': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 12); lsb+=baseLog2; break;
case 'd': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 13); lsb+=baseLog2; break;
case 'e': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 14); lsb+=baseLog2; break;
case 'f': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 15); lsb+=baseLog2; break;
case '_': break;
}
}
}
IData _vl_vsscanf(FILE* fp, // If a fscanf
int fbits, WDataInP fromp, // Else if a sscanf
@ -480,7 +539,6 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
// Deal with all read-and-scan somethings
// Note LSBs are preserved if there's an overflow
const int obits = va_arg(ap, int);
int lsb = 0;
WData qowp[2];
WDataOutP owp = qowp;
if (obits > VL_QUADSIZE) {
@ -500,6 +558,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
_vl_vsss_read(fp,floc,fromp, tmp, NULL);
if (!tmp[0]) goto done;
int pos = strlen(tmp)-1;
int lsb = 0;
for (int i=0; i<obits && pos>=0; pos--) {
_vl_vsss_setbit(owp,obits,lsb, 8, tmp[pos]); lsb+=8;
}
@ -507,7 +566,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
}
case 'd': { // Signed decimal
_vl_vsss_skipspace(fp,floc,fromp);
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789+-xz?_");
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789+-xXzZ?_");
if (!tmp[0]) goto done;
vlsint64_t ld;
sscanf(tmp,"%lld",&ld);
@ -517,7 +576,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
case 't': // FALLTHRU // Time
case 'u': { // Unsigned decimal
_vl_vsss_skipspace(fp,floc,fromp);
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789+-xz?_");
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789+-xXzZ?_");
if (!tmp[0]) goto done;
QData ld;
sscanf(tmp,"%llu",&ld);
@ -526,67 +585,23 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
}
case 'b': {
_vl_vsss_skipspace(fp,floc,fromp);
_vl_vsss_read(fp,floc,fromp, tmp, "01xz?_");
_vl_vsss_read(fp,floc,fromp, tmp, "01xXzZ?_");
if (!tmp[0]) goto done;
int pos = strlen(tmp)-1;
for (int i=0; i<obits && pos>=0; pos--) {
switch(tmp[pos]) {
case 'x': case 'z': case '?': //FALLTHRU
case '0': lsb++; break;
case '1': _vl_vsss_setbit(owp,obits,lsb, 1, 1); lsb++; break;
case '_': break;
}
}
_vl_vsss_based(owp,obits, 1, tmp, 0, strlen(tmp));
break;
}
case 'o': {
_vl_vsss_skipspace(fp,floc,fromp);
_vl_vsss_read(fp,floc,fromp, tmp, "01234567xz?_");
_vl_vsss_read(fp,floc,fromp, tmp, "01234567xXzZ?_");
if (!tmp[0]) goto done;
int pos = strlen(tmp)-1;
for (int i=0; i<obits && pos>=0; pos--) {
switch(tmp[pos]) {
case 'x': case 'z': case '?': //FALLTHRU
case '0': lsb+=3; break;
case '1': _vl_vsss_setbit(owp,obits,lsb, 3, 1); lsb+=3; break;
case '2': _vl_vsss_setbit(owp,obits,lsb, 3, 2); lsb+=3; break;
case '3': _vl_vsss_setbit(owp,obits,lsb, 3, 3); lsb+=3; break;
case '4': _vl_vsss_setbit(owp,obits,lsb, 3, 4); lsb+=3; break;
case '5': _vl_vsss_setbit(owp,obits,lsb, 3, 5); lsb+=3; break;
case '6': _vl_vsss_setbit(owp,obits,lsb, 3, 6); lsb+=3; break;
case '7': _vl_vsss_setbit(owp,obits,lsb, 3, 7); lsb+=3; break;
case '_': break;
}
}
_vl_vsss_based(owp,obits, 3, tmp, 0, strlen(tmp));
break;
}
case 'x': {
_vl_vsss_skipspace(fp,floc,fromp);
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789abcdefxz?_");
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789abcdefABCDEFxXzZ?_");
if (!tmp[0]) goto done;
int pos = strlen(tmp)-1;
for (int i=0; i<obits && pos>=0; pos--) {
switch(tmp[pos]) {
case 'x': case 'z': case '?': //FALLTHRU
case '0': lsb+=4; break;
case '1': _vl_vsss_setbit(owp,obits,lsb, 4, 1); lsb+=4; break;
case '2': _vl_vsss_setbit(owp,obits,lsb, 4, 2); lsb+=4; break;
case '3': _vl_vsss_setbit(owp,obits,lsb, 4, 3); lsb+=4; break;
case '4': _vl_vsss_setbit(owp,obits,lsb, 4, 4); lsb+=4; break;
case '5': _vl_vsss_setbit(owp,obits,lsb, 4, 5); lsb+=4; break;
case '6': _vl_vsss_setbit(owp,obits,lsb, 4, 6); lsb+=4; break;
case '7': _vl_vsss_setbit(owp,obits,lsb, 4, 7); lsb+=4; break;
case '8': _vl_vsss_setbit(owp,obits,lsb, 4, 8); lsb+=4; break;
case '9': _vl_vsss_setbit(owp,obits,lsb, 4, 9); lsb+=4; break;
case 'a': _vl_vsss_setbit(owp,obits,lsb, 4, 10); lsb+=4; break;
case 'b': _vl_vsss_setbit(owp,obits,lsb, 4, 11); lsb+=4; break;
case 'c': _vl_vsss_setbit(owp,obits,lsb, 4, 12); lsb+=4; break;
case 'd': _vl_vsss_setbit(owp,obits,lsb, 4, 13); lsb+=4; break;
case 'e': _vl_vsss_setbit(owp,obits,lsb, 4, 14); lsb+=4; break;
case 'f': _vl_vsss_setbit(owp,obits,lsb, 4, 15); lsb+=4; break;
case '_': break;
}
}
_vl_vsss_based(owp,obits, 4, tmp, 0, strlen(tmp));
break;
}
default:
@ -851,6 +866,48 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
}
}
IData VL_TESTPLUSARGS_I(const char* formatp) {
string match = VerilatedImp::argPlusMatch(formatp);
if (match == "") return 0;
else return 1;
}
IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rwp) {
string match = VerilatedImp::argPlusMatch(prefixp);
const char* dp = match.c_str() + 1 /*leading + */ + strlen(prefixp);
if (match == "") return 0;
VL_ZERO_RESET_W(rbits, rwp);
switch (tolower(fmt)) {
case '%':
break;
case 'd':
vlsint64_t ld;
sscanf(dp,"%lld",&ld);
VL_SET_WQ(rwp,ld);
break;
case 'b':
_vl_vsss_based(rwp,rbits, 1, dp, 0, strlen(dp));
break;
case 'o':
_vl_vsss_based(rwp,rbits, 3, dp, 0, strlen(dp));
break;
case 'h': //FALLTHRU
case 'x':
_vl_vsss_based(rwp,rbits, 4, dp, 0, strlen(dp));
break;
case 's':
for (int i=0, lsb=0, pos=strlen(dp)-1; i<rbits && pos>=0; pos--) {
_vl_vsss_setbit(rwp,rbits,lsb, 8, dp[pos]); lsb+=8;
}
break;
default: // Compile time should have found all errors before this
vl_fatal (__FILE__, __LINE__, "", "$value$plusargs format error");
break;
}
_VL_CLEAN_INPLACE_W(rbits,rwp);
return 1;
}
//===========================================================================
// Verilated:: Methods
@ -870,6 +927,15 @@ const char* Verilated::catName(const char* n1, const char* n2) {
return strp;
}
void Verilated::commandArgs(int argc, const char** argv) {
VerilatedImp::s_argVec.clear();
for (int i=0; i<argc; i++) {
VerilatedImp::s_argVec.push_back(argv[i]);
}
// Can't just test later for empty vector, no arguments is ok
VerilatedImp::s_argVecLoaded = true;
}
//===========================================================================
// VerilatedModule:: Methods

View File

@ -166,6 +166,9 @@ public:
/// Enable/disable assertions
static void assertOn(bool flag) { s_assertOn=flag; }
static bool assertOn() { return s_assertOn; }
/// Command line arguments
static void commandArgs(int argc, const char** argv);
static void commandArgs(int argc, char** argv) { commandArgs(argc,(const char**)argv); }
};
//=========================================================================
@ -218,6 +221,9 @@ extern IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...);
extern IData VL_SSCANF_IQX(int lbits, QData ld, const char* formatp, ...);
extern IData VL_SSCANF_IWX(int lbits, WDataInP lwp, const char* formatp, ...);
extern IData VL_TESTPLUSARGS_I(const char* formatp);
extern IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rwp);
//=========================================================================
// Base macros
@ -1420,6 +1426,26 @@ static inline WDataOutP VL_COND_WIWW(int obits, int, int, int,
return(owp);
}
//======================================================================
// System Functions
inline IData VL_VALUEPLUSARGS_IQ(int rbits, const char* prefixp, char fmt, QData& ldr) {
WData wd[2]; IData v=VL_VALUEPLUSARGS_IW(rbits,prefixp,fmt,wd); if (v) ldr=VL_SET_QW(wd);
return v;
}
inline IData VL_VALUEPLUSARGS_II(int rbits, const char* prefixp, char fmt, CData& ldr) {
QData qd; IData v=VL_VALUEPLUSARGS_IQ(rbits,prefixp,fmt,qd); if (v) ldr=qd;
return v;
}
inline IData VL_VALUEPLUSARGS_II(int rbits, const char* prefixp, char fmt, SData& ldr) {
QData qd; IData v=VL_VALUEPLUSARGS_IQ(rbits,prefixp,fmt,qd); if (v) ldr=qd;
return v;
}
inline IData VL_VALUEPLUSARGS_II(int rbits, const char* prefixp, char fmt, IData& ldr) {
QData qd; IData v=VL_VALUEPLUSARGS_IQ(rbits,prefixp,fmt,qd); if (v) ldr=qd;
return v;
}
//======================================================================
// Constification

View File

@ -1558,6 +1558,56 @@ public:
AstNode* msbp() const { return op4p()->castNode(); }
};
struct AstValuePlusArgs : public AstNodeMath {
// Parents: expr
// Child: variable to set. If NULL then this is a $test$plusargs instead of $value$plusargs
private:
string m_text;
public:
AstValuePlusArgs(FileLine* fileline, const string& text, AstNode* exprsp)
: AstNodeMath (fileline), m_text(text) {
setOp1p(exprsp);
}
ASTNODE_NODE_FUNCS(ValuePlusArgs, VALUEPLUSARGS)
virtual string name() const { return m_text; }
virtual string verilogKwd() const { return "$value$plusargs"; }
virtual string emitVerilog() { return verilogKwd(); }
virtual string emitC() { return "VL_VALUEPLUSARGS_%nq(%lw, %P, NULL)"; }
virtual bool isGateOptimizable() const { return false; }
virtual bool isPredictOptimizable() const { return false; }
virtual bool cleanOut() { return true; }
virtual V3Hash sameHash() const { return V3Hash(text()); }
virtual bool same(AstNode* samep) const {
return text()==samep->castValuePlusArgs()->text(); }
AstNode* exprsp() const { return op1p()->castNode(); } // op1 = Expressions to output
void exprsp(AstNode* nodep) { setOp1p(nodep); } // op1 = Expressions to output
string text() const { return m_text; } // * = Text to display
void text(const string& text) { m_text=text; }
};
struct AstTestPlusArgs : public AstNodeMath {
// Parents: expr
// Child: variable to set. If NULL then this is a $test$plusargs instead of $value$plusargs
private:
string m_text;
public:
AstTestPlusArgs(FileLine* fileline, const string& text)
: AstNodeMath (fileline), m_text(text) { }
ASTNODE_NODE_FUNCS(TestPlusArgs, TESTPLUSARGS)
virtual string name() const { return m_text; }
virtual string verilogKwd() const { return "$test$plusargs"; }
virtual string emitVerilog() { return verilogKwd(); }
virtual string emitC() { return "VL_VALUEPLUSARGS_%nq(%lw, %P, NULL)"; }
virtual bool isGateOptimizable() const { return false; }
virtual bool isPredictOptimizable() const { return false; }
virtual bool cleanOut() { return true; }
virtual V3Hash sameHash() const { return V3Hash(text()); }
virtual bool same(AstNode* samep) const {
return text()==samep->castTestPlusArgs()->text(); }
string text() const { return m_text; } // * = Text to display
void text(const string& text) { m_text=text; }
};
struct AstGenFor : public AstNodeFor {
AstGenFor(FileLine* fileline, AstNode* initsp, AstNode* condp,
AstNode* incsp, AstNode* bodysp)

View File

@ -236,6 +236,59 @@ public:
virtual void visit(AstSScanF* nodep, AstNUser*) {
displayNode(nodep, nodep->text(), nodep->exprsp(), true);
}
virtual void visit(AstValuePlusArgs* nodep, AstNUser*) {
string prefix;
char format = '?';
bool pct=false;
int got=0;
for (const char* cp = nodep->text().c_str(); *cp; cp++) {
if (pct) {
pct = false;
switch (tolower(*cp)) {
case '%':
prefix += *cp;
break;
case 'd': // FALLTHRU
case 'o': // FALLTHRU
case 'h': // FALLTHRU
case 'x': // FALLTHRU
case 'b': // FALLTHRU
case 's':
got++; format = tolower(*cp);
break;
case 'e': // FALLTHRU
case 'f': // FALLTHRU
case 'g':
got++; format = tolower(*cp);
nodep->v3error("Unsupported $value$plusargs format qualifier: '"<<*cp<<"'"<<endl);
break;
default:
got++;
nodep->v3error("Illegal $value$plusargs format qualifier: '"<<*cp<<"'"<<endl);
break;
}
}
else if (*cp == '%') pct = true;
else prefix += *cp;
}
if (got!=1) nodep->v3error("Missing or extra $value$plusargs format qualifier: '"<<nodep->text()<<"'"<<endl);
puts("VL_VALUEPLUSARGS_I");
emitIQW(nodep->exprsp());
puts("(");
puts(cvtToStr(nodep->exprsp()->widthMin())); // Note argument width, not node width (which is always 32)
putbs(",");
putsQuoted(prefix);
putbs(",'");
puts(cvtToStr(format));
putbs("',");
nodep->exprsp()->iterateAndNext(*this);
puts(")");
}
virtual void visit(AstTestPlusArgs* nodep, AstNUser*) {
puts("VL_TESTPLUSARGS_I(");
putsQuoted(nodep->text());
puts(")");
}
virtual void visit(AstFGetS* nodep, AstNUser*) {
checkMaxWords(nodep);
emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), NULL);

View File

@ -194,6 +194,9 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
virtual void visit(AstSScanF* nodep, AstNUser*) {
visitNodeDisplay(nodep, nodep->fromp(), nodep->text(), nodep->exprsp());
}
virtual void visit(AstValuePlusArgs* nodep, AstNUser*) {
visitNodeDisplay(nodep, NULL, nodep->text(), nodep->exprsp());
}
virtual void visit(AstFOpen* nodep, AstNUser*) {
putbs(nodep->verilogKwd());

View File

@ -166,6 +166,14 @@ private:
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstValuePlusArgs* nodep, AstNUser*) {
bool last_setRefLvalue = m_setRefLvalue;
{
m_setRefLvalue = true;
nodep->exprsp()->iterateAndNext(*this);
}
m_setRefLvalue = last_setRefLvalue;
}
// Nodes that change LValue state
virtual void visit(AstSel* nodep, AstNUser*) {

View File

@ -86,6 +86,8 @@ private:
virtual void visit(AstFGetS* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstFScanF* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstSScanF* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstTestPlusArgs* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstValuePlusArgs* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
//
virtual void visit(AstConcat* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstReplicate* nodep, AstNUser*) { signed_Ou_Ix(nodep); }

View File

@ -753,6 +753,13 @@ private:
nodep->lsbp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
nodep->msbp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
}
virtual void visit(AstTestPlusArgs* nodep, AstNUser* vup) {
nodep->width(32,32);
}
virtual void visit(AstValuePlusArgs* nodep, AstNUser* vup) {
nodep->exprsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
nodep->width(32,32);
}
virtual void visit(AstUCStmt* nodep, AstNUser*) {
// TOP LEVEL NODE
// Just let all arguments seek their natural sizes

View File

@ -184,8 +184,10 @@ escid \\[^ \t\f\r\n]+
"$sscanf" { FL; return yD_SSCANF; }
"$stime" { FL; return yD_STIME; }
"$stop" { FL; return yD_STOP; }
"$test$plusargs" { FL; return yD_TESTPLUSARGS; }
"$time" { FL; return yD_TIME; }
"$timeskew" { FL; return yaTIMINGSPEC; }
"$value$plusargs" { FL; return yD_VALUEPLUSARGS; }
"$width" { FL; return yaTIMINGSPEC; }
"$write" { FL; return yD_WRITE; }
/* Keywords */

View File

@ -353,9 +353,11 @@ class AstSenTree;
%token<fl> yD_SSCANF "$sscanf"
%token<fl> yD_STIME "$stime"
%token<fl> yD_STOP "$stop"
%token<fl> yD_TESTPLUSARGS "$test$plusargs"
%token<fl> yD_TIME "$time"
%token<fl> yD_UNIT "$unit"
%token<fl> yD_UNSIGNED "$unsigned"
%token<fl> yD_VALUEPLUSARGS "$value$plusargs"
%token<fl> yD_WARNING "$warning"
%token<fl> yD_WRITE "$write"
%token<fl> yD_aIGNORE "${ignored-bbox-sys}"
@ -1947,7 +1949,9 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
| yD_SIGNED '(' expr ')' { $$ = new AstSigned($1,$3); }
| yD_STIME { $$ = new AstSel($1,new AstTime($1),0,32); }
| yD_TIME { $$ = new AstTime($1); }
| yD_TESTPLUSARGS '(' str ')' { $$ = new AstTestPlusArgs($1,*$3); }
| yD_UNSIGNED '(' expr ')' { $$ = new AstUnsigned($1,$3); }
| yD_VALUEPLUSARGS '(' str ',' expr ')' { $$ = new AstValuePlusArgs($1,*$3,$5); }
;
list_of_argumentsE<nodep>: // IEEE: [list_of_arguments]

View File

@ -23,6 +23,7 @@ int main(int argc, char **argv, char **env) {
if (0 && argc && argv && env) {} // Prevent unused variable warnings
top = new Vtop; // Create instance of module
Verilated::commandArgs(argc, argv);
Verilated::debug(0);
#if VM_TRACE // If verilator was invoked with --trace

View File

@ -248,6 +248,7 @@ sub new {
))],
v_flags2 => [], # Overridden in some sim files
v_other_filenames => [], # After the filename so we can spec multiple files
all_run_flags => [],
# IV
iv => 0,
iv_flags => [split(/\s+/,"+define+iverilog -o $self->{obj_dir}/simiv")],
@ -495,6 +496,7 @@ sub execute {
fails=>$param{fails},
cmd=>["$self->{obj_dir}/simiv",
@{$param{ivrun_flags}},
@{$param{all_run_flags}},
]);
}
if ($param{nc}) {
@ -502,13 +504,16 @@ sub execute {
fails=>$param{fails},
cmd=>[($ENV{VERILATOR_NCVERILOG}||"ncverilog"),
@{$param{ncrun_flags}},
@{$param{all_run_flags}},
]);
}
if ($param{vcs}) {
#my $fh = IO::File->new(">simv.key") or die "%Error: $! simv.key,";
#$fh->print("quit\n"); $fh->close;
$self->_run(logfile=>"$self->{obj_dir}/vcs_sim.log",
cmd=>["./simv",],
cmd=>["./simv",
@{$param{all_run_flags}},
],
%param,
expect=>undef, # vcs expect isn't the same
);
@ -518,6 +523,7 @@ sub execute {
) {
$self->_run(logfile=>"$self->{obj_dir}/vl_sim.log",
cmd=>["$self->{obj_dir}/$param{VM_PREFIX}",
@{$param{all_run_flags}},
],
%param,
);
@ -731,6 +737,7 @@ sub _make_main {
print $fh "int main(int argc, char **argv, char **env) {\n";
print $fh " double sim_time = $self->{sim_time};\n";
}
print $fh " Verilated::commandArgs(argc, argv);\n";
print $fh " Verilated::debug(".($self->{verilated_debug}?1:0).");\n";
print $fh " Verilated::randReset(".$self->{verilated_randReset}.");\n" if defined $self->{verilated_randReset};
print $fh " topp = new $VM_PREFIX (\"TOP\");\n";

View File

@ -0,0 +1,14 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
compile (
v_flags2 => ['-v', 't/t_flag_libinc.v'],
);
execute (
check_finished=>1,
all_run_flags => ['+PLUS +INT=1234 +STRSTR'],
);
ok(1);
1;

View File

@ -0,0 +1,38 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2009 by Wilson Snyder.
module t;
integer p_i;
reg [7*8:1] p_str;
initial begin
if ($test$plusargs("PLUS")!==1) $stop;
if ($test$plusargs("PLUSNOT")!==0) $stop;
if ($test$plusargs("PL")!==1) $stop;
//if ($test$plusargs("")!==1) $stop; // Simulators differ in this answer
if ($test$plusargs("NOTTHERE")!==0) $stop;
p_i = 10;
if ($value$plusargs("NOTTHERE%d", p_i)!==0) $stop;
if (p_i !== 10) $stop;
if ($value$plusargs("INT=%d", p_i)!==1) $stop;
if (p_i !== 32'd1234) $stop;
if ($value$plusargs("INT=%H", p_i)!==1) $stop; // tests uppercase % also
if (p_i !== 32'h1234) $stop;
if ($value$plusargs("INT=%o", p_i)!==1) $stop;
if (p_i !== 32'o1234) $stop;
if ($value$plusargs("IN%s", p_str)!==1) $stop;
$display("str='%s'",p_str);
if (p_str !== "T=1234") $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,21 @@
#!/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 (
fails=>$Self->{v3},
expect=>
q{%Error: t/t_sys_plusargs_bad.v:\d+: Missing or extra \$value\$plusargs format qualifier: 'NOTTHERE'
%Error: t/t_sys_plusargs_bad.v:\d+: Illegal \$value\$plusargs format qualifier: 'z'
%Error: t/t_sys_plusargs_bad.v:\d+: Missing or extra \$value\$plusargs format qualifier: 'INT=%x%x'
%Error: Exiting due to.*},
);
ok(1);
1;

View File

@ -0,0 +1,22 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2009 by Wilson Snyder.
module t;
integer p_i;
initial begin
// BAD: Missing argument
if ($value$plusargs("NOTTHERE", p_i)!==0) $stop;
// BAD: Bad letter
if ($value$plusargs("INT=%z", p_i)!==0) $stop;
// BAD: Multi letter
if ($value$plusargs("INT=%x%x", p_i)!==0) $stop;
$stop;
end
endmodule

View File

@ -26,6 +26,7 @@
Vtop *top;
int sc_main(int argc, char* argv[]) {
Verilated::commandArgs(argc, argv);
Verilated::randReset(2);
Verilated::debug(0); // We compiled with it on for testing, turn it back off

View File

@ -19,6 +19,7 @@ double sc_time_stamp () {
}
int main(int argc, char **argv, char **env) {
Verilated::commandArgs(argc, argv);
Verilated::debug(0); // We compiled with it on for testing, turn it back off
top = new Vvgen;