mirror of
https://github.com/verilator/verilator.git
synced 2025-04-16 01:26:54 +00:00
Support $test$plusargs and $value$plusargs, but see the docs.
This commit is contained in:
parent
19d62b7a68
commit
62f707f501
2
Changes
2
Changes
@ -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 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.
|
*** Add VARHIDDEN warning when signal name hides module name.
|
||||||
|
|
||||||
**** Fix MinGW compilation, bug184. [by Shankar Giri]
|
**** Fix MinGW compilation, bug184. [by Shankar Giri]
|
||||||
|
@ -768,6 +768,7 @@ We'll compile this example into C++.
|
|||||||
#include "Vour.h"
|
#include "Vour.h"
|
||||||
#include "verilated.h"
|
#include "verilated.h"
|
||||||
int main(int argc, char **argv, char **env) {
|
int main(int argc, char **argv, char **env) {
|
||||||
|
Verilated::commandArgs(argc, argv);
|
||||||
Vour* top = new Vour;
|
Vour* top = new Vour;
|
||||||
while (!Verilated::gotFinish()) { top->eval(); }
|
while (!Verilated::gotFinish()) { top->eval(); }
|
||||||
exit(0);
|
exit(0);
|
||||||
@ -825,6 +826,7 @@ This is an example similar to the above, but using SystemPerl.
|
|||||||
cat <<EOF >sc_main.cpp
|
cat <<EOF >sc_main.cpp
|
||||||
#include "Vour.h"
|
#include "Vour.h"
|
||||||
int sc_main(int argc, char **argv) {
|
int sc_main(int argc, char **argv) {
|
||||||
|
Verilated::commandArgs(argc, argv);
|
||||||
sc_clock clk ("clk",10, 0.5, 3, true);
|
sc_clock clk ("clk",10, 0.5, 3, true);
|
||||||
Vour* top;
|
Vour* top;
|
||||||
top = new Vour("top"); // SP_CELL (top, Vour);
|
top = new Vour("top"); // SP_CELL (top, Vour);
|
||||||
@ -1080,7 +1082,9 @@ example:
|
|||||||
return main_time;
|
return main_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main(int argc, char** argv) {
|
||||||
|
Verilated::commandArgs(argc, argv); // Remember args
|
||||||
|
|
||||||
top = new Vtop; // Create instance
|
top = new Vtop; // Create instance
|
||||||
|
|
||||||
top->reset_l = 0; // Set some inputs
|
top->reset_l = 0; // Set some inputs
|
||||||
@ -1784,6 +1788,22 @@ arrays.
|
|||||||
|
|
||||||
Treated as $time.
|
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
|
=back
|
||||||
|
|
||||||
=head1 ERRORS AND WARNINGS
|
=head1 ERRORS AND WARNINGS
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "verilated.h"
|
#include "verilated.h"
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#define VL_VALUE_STRING_MAX_WIDTH 1024 ///< Max static char array for VL_VALUE_STRING
|
#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_gotFinish = false;
|
||||||
bool Verilated::s_assertOn = true;
|
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
|
// 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);
|
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
|
IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||||
int fbits, WDataInP fromp, // Else if a sscanf
|
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
|
// Deal with all read-and-scan somethings
|
||||||
// Note LSBs are preserved if there's an overflow
|
// Note LSBs are preserved if there's an overflow
|
||||||
const int obits = va_arg(ap, int);
|
const int obits = va_arg(ap, int);
|
||||||
int lsb = 0;
|
|
||||||
WData qowp[2];
|
WData qowp[2];
|
||||||
WDataOutP owp = qowp;
|
WDataOutP owp = qowp;
|
||||||
if (obits > VL_QUADSIZE) {
|
if (obits > VL_QUADSIZE) {
|
||||||
@ -500,6 +558,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
|||||||
_vl_vsss_read(fp,floc,fromp, tmp, NULL);
|
_vl_vsss_read(fp,floc,fromp, tmp, NULL);
|
||||||
if (!tmp[0]) goto done;
|
if (!tmp[0]) goto done;
|
||||||
int pos = strlen(tmp)-1;
|
int pos = strlen(tmp)-1;
|
||||||
|
int lsb = 0;
|
||||||
for (int i=0; i<obits && pos>=0; pos--) {
|
for (int i=0; i<obits && pos>=0; pos--) {
|
||||||
_vl_vsss_setbit(owp,obits,lsb, 8, tmp[pos]); lsb+=8;
|
_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
|
case 'd': { // Signed decimal
|
||||||
_vl_vsss_skipspace(fp,floc,fromp);
|
_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;
|
if (!tmp[0]) goto done;
|
||||||
vlsint64_t ld;
|
vlsint64_t ld;
|
||||||
sscanf(tmp,"%lld",&ld);
|
sscanf(tmp,"%lld",&ld);
|
||||||
@ -517,7 +576,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
|||||||
case 't': // FALLTHRU // Time
|
case 't': // FALLTHRU // Time
|
||||||
case 'u': { // Unsigned decimal
|
case 'u': { // Unsigned decimal
|
||||||
_vl_vsss_skipspace(fp,floc,fromp);
|
_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;
|
if (!tmp[0]) goto done;
|
||||||
QData ld;
|
QData ld;
|
||||||
sscanf(tmp,"%llu",&ld);
|
sscanf(tmp,"%llu",&ld);
|
||||||
@ -526,67 +585,23 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
|||||||
}
|
}
|
||||||
case 'b': {
|
case 'b': {
|
||||||
_vl_vsss_skipspace(fp,floc,fromp);
|
_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;
|
if (!tmp[0]) goto done;
|
||||||
int pos = strlen(tmp)-1;
|
_vl_vsss_based(owp,obits, 1, tmp, 0, strlen(tmp));
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'o': {
|
case 'o': {
|
||||||
_vl_vsss_skipspace(fp,floc,fromp);
|
_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;
|
if (!tmp[0]) goto done;
|
||||||
int pos = strlen(tmp)-1;
|
_vl_vsss_based(owp,obits, 3, tmp, 0, strlen(tmp));
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'x': {
|
case 'x': {
|
||||||
_vl_vsss_skipspace(fp,floc,fromp);
|
_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;
|
if (!tmp[0]) goto done;
|
||||||
int pos = strlen(tmp)-1;
|
_vl_vsss_based(owp,obits, 4, tmp, 0, strlen(tmp));
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
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
|
// Verilated:: Methods
|
||||||
|
|
||||||
@ -870,6 +927,15 @@ const char* Verilated::catName(const char* n1, const char* n2) {
|
|||||||
return strp;
|
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
|
// VerilatedModule:: Methods
|
||||||
|
|
||||||
|
@ -166,6 +166,9 @@ public:
|
|||||||
/// Enable/disable assertions
|
/// Enable/disable assertions
|
||||||
static void assertOn(bool flag) { s_assertOn=flag; }
|
static void assertOn(bool flag) { s_assertOn=flag; }
|
||||||
static bool assertOn() { return s_assertOn; }
|
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_IQX(int lbits, QData ld, const char* formatp, ...);
|
||||||
extern IData VL_SSCANF_IWX(int lbits, WDataInP lwp, 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
|
// Base macros
|
||||||
|
|
||||||
@ -1420,6 +1426,26 @@ static inline WDataOutP VL_COND_WIWW(int obits, int, int, int,
|
|||||||
return(owp);
|
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
|
// Constification
|
||||||
|
|
||||||
|
@ -1558,6 +1558,56 @@ public:
|
|||||||
AstNode* msbp() const { return op4p()->castNode(); }
|
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 {
|
struct AstGenFor : public AstNodeFor {
|
||||||
AstGenFor(FileLine* fileline, AstNode* initsp, AstNode* condp,
|
AstGenFor(FileLine* fileline, AstNode* initsp, AstNode* condp,
|
||||||
AstNode* incsp, AstNode* bodysp)
|
AstNode* incsp, AstNode* bodysp)
|
||||||
|
@ -236,6 +236,59 @@ public:
|
|||||||
virtual void visit(AstSScanF* nodep, AstNUser*) {
|
virtual void visit(AstSScanF* nodep, AstNUser*) {
|
||||||
displayNode(nodep, nodep->text(), nodep->exprsp(), true);
|
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*) {
|
virtual void visit(AstFGetS* nodep, AstNUser*) {
|
||||||
checkMaxWords(nodep);
|
checkMaxWords(nodep);
|
||||||
emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), NULL);
|
emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), NULL);
|
||||||
|
@ -194,6 +194,9 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||||||
virtual void visit(AstSScanF* nodep, AstNUser*) {
|
virtual void visit(AstSScanF* nodep, AstNUser*) {
|
||||||
visitNodeDisplay(nodep, nodep->fromp(), nodep->text(), nodep->exprsp());
|
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*) {
|
virtual void visit(AstFOpen* nodep, AstNUser*) {
|
||||||
putbs(nodep->verilogKwd());
|
putbs(nodep->verilogKwd());
|
||||||
|
@ -166,6 +166,14 @@ private:
|
|||||||
}
|
}
|
||||||
m_setRefLvalue = last_setRefLvalue;
|
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
|
// Nodes that change LValue state
|
||||||
virtual void visit(AstSel* nodep, AstNUser*) {
|
virtual void visit(AstSel* nodep, AstNUser*) {
|
||||||
|
@ -86,6 +86,8 @@ private:
|
|||||||
virtual void visit(AstFGetS* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
|
virtual void visit(AstFGetS* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
|
||||||
virtual void visit(AstFScanF* 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(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(AstConcat* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
|
||||||
virtual void visit(AstReplicate* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
|
virtual void visit(AstReplicate* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
|
||||||
|
@ -753,6 +753,13 @@ private:
|
|||||||
nodep->lsbp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
nodep->lsbp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||||
nodep->msbp()->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*) {
|
virtual void visit(AstUCStmt* nodep, AstNUser*) {
|
||||||
// TOP LEVEL NODE
|
// TOP LEVEL NODE
|
||||||
// Just let all arguments seek their natural sizes
|
// Just let all arguments seek their natural sizes
|
||||||
|
@ -184,8 +184,10 @@ escid \\[^ \t\f\r\n]+
|
|||||||
"$sscanf" { FL; return yD_SSCANF; }
|
"$sscanf" { FL; return yD_SSCANF; }
|
||||||
"$stime" { FL; return yD_STIME; }
|
"$stime" { FL; return yD_STIME; }
|
||||||
"$stop" { FL; return yD_STOP; }
|
"$stop" { FL; return yD_STOP; }
|
||||||
|
"$test$plusargs" { FL; return yD_TESTPLUSARGS; }
|
||||||
"$time" { FL; return yD_TIME; }
|
"$time" { FL; return yD_TIME; }
|
||||||
"$timeskew" { FL; return yaTIMINGSPEC; }
|
"$timeskew" { FL; return yaTIMINGSPEC; }
|
||||||
|
"$value$plusargs" { FL; return yD_VALUEPLUSARGS; }
|
||||||
"$width" { FL; return yaTIMINGSPEC; }
|
"$width" { FL; return yaTIMINGSPEC; }
|
||||||
"$write" { FL; return yD_WRITE; }
|
"$write" { FL; return yD_WRITE; }
|
||||||
/* Keywords */
|
/* Keywords */
|
||||||
|
@ -353,9 +353,11 @@ class AstSenTree;
|
|||||||
%token<fl> yD_SSCANF "$sscanf"
|
%token<fl> yD_SSCANF "$sscanf"
|
||||||
%token<fl> yD_STIME "$stime"
|
%token<fl> yD_STIME "$stime"
|
||||||
%token<fl> yD_STOP "$stop"
|
%token<fl> yD_STOP "$stop"
|
||||||
|
%token<fl> yD_TESTPLUSARGS "$test$plusargs"
|
||||||
%token<fl> yD_TIME "$time"
|
%token<fl> yD_TIME "$time"
|
||||||
%token<fl> yD_UNIT "$unit"
|
%token<fl> yD_UNIT "$unit"
|
||||||
%token<fl> yD_UNSIGNED "$unsigned"
|
%token<fl> yD_UNSIGNED "$unsigned"
|
||||||
|
%token<fl> yD_VALUEPLUSARGS "$value$plusargs"
|
||||||
%token<fl> yD_WARNING "$warning"
|
%token<fl> yD_WARNING "$warning"
|
||||||
%token<fl> yD_WRITE "$write"
|
%token<fl> yD_WRITE "$write"
|
||||||
%token<fl> yD_aIGNORE "${ignored-bbox-sys}"
|
%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_SIGNED '(' expr ')' { $$ = new AstSigned($1,$3); }
|
||||||
| yD_STIME { $$ = new AstSel($1,new AstTime($1),0,32); }
|
| yD_STIME { $$ = new AstSel($1,new AstTime($1),0,32); }
|
||||||
| yD_TIME { $$ = new AstTime($1); }
|
| yD_TIME { $$ = new AstTime($1); }
|
||||||
|
| yD_TESTPLUSARGS '(' str ')' { $$ = new AstTestPlusArgs($1,*$3); }
|
||||||
| yD_UNSIGNED '(' expr ')' { $$ = new AstUnsigned($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]
|
list_of_argumentsE<nodep>: // IEEE: [list_of_arguments]
|
||||||
|
@ -23,6 +23,7 @@ int main(int argc, char **argv, char **env) {
|
|||||||
if (0 && argc && argv && env) {} // Prevent unused variable warnings
|
if (0 && argc && argv && env) {} // Prevent unused variable warnings
|
||||||
top = new Vtop; // Create instance of module
|
top = new Vtop; // Create instance of module
|
||||||
|
|
||||||
|
Verilated::commandArgs(argc, argv);
|
||||||
Verilated::debug(0);
|
Verilated::debug(0);
|
||||||
|
|
||||||
#if VM_TRACE // If verilator was invoked with --trace
|
#if VM_TRACE // If verilator was invoked with --trace
|
||||||
|
@ -248,6 +248,7 @@ sub new {
|
|||||||
))],
|
))],
|
||||||
v_flags2 => [], # Overridden in some sim files
|
v_flags2 => [], # Overridden in some sim files
|
||||||
v_other_filenames => [], # After the filename so we can spec multiple files
|
v_other_filenames => [], # After the filename so we can spec multiple files
|
||||||
|
all_run_flags => [],
|
||||||
# IV
|
# IV
|
||||||
iv => 0,
|
iv => 0,
|
||||||
iv_flags => [split(/\s+/,"+define+iverilog -o $self->{obj_dir}/simiv")],
|
iv_flags => [split(/\s+/,"+define+iverilog -o $self->{obj_dir}/simiv")],
|
||||||
@ -495,6 +496,7 @@ sub execute {
|
|||||||
fails=>$param{fails},
|
fails=>$param{fails},
|
||||||
cmd=>["$self->{obj_dir}/simiv",
|
cmd=>["$self->{obj_dir}/simiv",
|
||||||
@{$param{ivrun_flags}},
|
@{$param{ivrun_flags}},
|
||||||
|
@{$param{all_run_flags}},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
if ($param{nc}) {
|
if ($param{nc}) {
|
||||||
@ -502,13 +504,16 @@ sub execute {
|
|||||||
fails=>$param{fails},
|
fails=>$param{fails},
|
||||||
cmd=>[($ENV{VERILATOR_NCVERILOG}||"ncverilog"),
|
cmd=>[($ENV{VERILATOR_NCVERILOG}||"ncverilog"),
|
||||||
@{$param{ncrun_flags}},
|
@{$param{ncrun_flags}},
|
||||||
|
@{$param{all_run_flags}},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
if ($param{vcs}) {
|
if ($param{vcs}) {
|
||||||
#my $fh = IO::File->new(">simv.key") or die "%Error: $! simv.key,";
|
#my $fh = IO::File->new(">simv.key") or die "%Error: $! simv.key,";
|
||||||
#$fh->print("quit\n"); $fh->close;
|
#$fh->print("quit\n"); $fh->close;
|
||||||
$self->_run(logfile=>"$self->{obj_dir}/vcs_sim.log",
|
$self->_run(logfile=>"$self->{obj_dir}/vcs_sim.log",
|
||||||
cmd=>["./simv",],
|
cmd=>["./simv",
|
||||||
|
@{$param{all_run_flags}},
|
||||||
|
],
|
||||||
%param,
|
%param,
|
||||||
expect=>undef, # vcs expect isn't the same
|
expect=>undef, # vcs expect isn't the same
|
||||||
);
|
);
|
||||||
@ -518,6 +523,7 @@ sub execute {
|
|||||||
) {
|
) {
|
||||||
$self->_run(logfile=>"$self->{obj_dir}/vl_sim.log",
|
$self->_run(logfile=>"$self->{obj_dir}/vl_sim.log",
|
||||||
cmd=>["$self->{obj_dir}/$param{VM_PREFIX}",
|
cmd=>["$self->{obj_dir}/$param{VM_PREFIX}",
|
||||||
|
@{$param{all_run_flags}},
|
||||||
],
|
],
|
||||||
%param,
|
%param,
|
||||||
);
|
);
|
||||||
@ -731,6 +737,7 @@ sub _make_main {
|
|||||||
print $fh "int main(int argc, char **argv, char **env) {\n";
|
print $fh "int main(int argc, char **argv, char **env) {\n";
|
||||||
print $fh " double sim_time = $self->{sim_time};\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::debug(".($self->{verilated_debug}?1:0).");\n";
|
||||||
print $fh " Verilated::randReset(".$self->{verilated_randReset}.");\n" if defined $self->{verilated_randReset};
|
print $fh " Verilated::randReset(".$self->{verilated_randReset}.");\n" if defined $self->{verilated_randReset};
|
||||||
print $fh " topp = new $VM_PREFIX (\"TOP\");\n";
|
print $fh " topp = new $VM_PREFIX (\"TOP\");\n";
|
||||||
|
14
test_regress/t/t_sys_plusargs.pl
Executable file
14
test_regress/t/t_sys_plusargs.pl
Executable 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;
|
38
test_regress/t/t_sys_plusargs.v
Normal file
38
test_regress/t/t_sys_plusargs.v
Normal 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
|
21
test_regress/t/t_sys_plusargs_bad.pl
Executable file
21
test_regress/t/t_sys_plusargs_bad.pl
Executable 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;
|
||||||
|
|
22
test_regress/t/t_sys_plusargs_bad.v
Normal file
22
test_regress/t/t_sys_plusargs_bad.v
Normal 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
|
@ -26,6 +26,7 @@
|
|||||||
Vtop *top;
|
Vtop *top;
|
||||||
|
|
||||||
int sc_main(int argc, char* argv[]) {
|
int sc_main(int argc, char* argv[]) {
|
||||||
|
Verilated::commandArgs(argc, argv);
|
||||||
Verilated::randReset(2);
|
Verilated::randReset(2);
|
||||||
Verilated::debug(0); // We compiled with it on for testing, turn it back off
|
Verilated::debug(0); // We compiled with it on for testing, turn it back off
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ double sc_time_stamp () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv, char **env) {
|
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
|
Verilated::debug(0); // We compiled with it on for testing, turn it back off
|
||||||
|
|
||||||
top = new Vvgen;
|
top = new Vvgen;
|
||||||
|
Loading…
Reference in New Issue
Block a user