mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 01:54:01 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
02530172e7 | ||
|
|
447d803800 | ||
|
|
6b04901c4d | ||
|
|
7fb29621c3 | ||
|
|
b032fce962 | ||
|
|
ce879122bb | ||
|
|
2fa16708b7 | ||
|
|
54bc8608e3 | ||
|
|
706a7802cc | ||
|
|
9dc01cf540 | ||
|
|
8943ad5966 | ||
|
|
deb7a1c9c0 | ||
|
|
96a5445d44 | ||
|
|
d693065afb | ||
|
|
bdeee35669 | ||
|
|
62b3deb90d | ||
|
|
9df9ff59e0 | ||
|
|
23a3271c06 |
@@ -3,6 +3,29 @@ Revision history for Verilator
|
|||||||
The contributors that suggested a given feature are shown in []. Thanks!
|
The contributors that suggested a given feature are shown in []. Thanks!
|
||||||
|
|
||||||
|
|
||||||
|
* Verilator 3.904 2017-05-30
|
||||||
|
|
||||||
|
*** Fix non-cutable ordering loops on clock arrays, bug1009. [Todd Strader]
|
||||||
|
|
||||||
|
*** Support ports of array of reals, bug1154. [J Briquet]
|
||||||
|
|
||||||
|
*** Support arrayed parameter overrides, bug1153. [John Stevenson]
|
||||||
|
|
||||||
|
*** Support $value$plusargs with variables, bug1165. [Wesley Terpstra]
|
||||||
|
|
||||||
|
**** Support modport access to un-modport objects, bug1161. [Todd Strader]
|
||||||
|
|
||||||
|
**** Add stack trace when can't optimize function, bug1158. [Todd Strader]
|
||||||
|
|
||||||
|
**** Add warning on mis-sized literal, bug1156. [Todd Strader]
|
||||||
|
|
||||||
|
**** Fix interface functions returning wrong parameters, bug996. [Todd Strader]
|
||||||
|
|
||||||
|
**** Fix non-arrayed cells with interface arrays, bug1153. [John Stevenson]
|
||||||
|
|
||||||
|
**** Fix --assert with complex case statements, bug1164. [Enzo Chi]
|
||||||
|
|
||||||
|
|
||||||
* Verilator 3.902 2017-04-02
|
* Verilator 3.902 2017-04-02
|
||||||
|
|
||||||
** Add -FI option to force includes,msg2146. [Amir Gonnen]
|
** Add -FI option to force includes,msg2146. [Amir Gonnen]
|
||||||
|
|||||||
+47
-26
@@ -495,6 +495,10 @@ If the signal is the input to top-module, the directly the signal name. If you
|
|||||||
find it difficult to find the exact name, try to use C</*verilator clocker*/> in
|
find it difficult to find the exact name, try to use C</*verilator clocker*/> in
|
||||||
RTL file to mark the signal directly.
|
RTL file to mark the signal directly.
|
||||||
|
|
||||||
|
If clock signals are assigned to vectors and then later used individually,
|
||||||
|
Verilator will attempt to decompose the vector and connect the single-bit
|
||||||
|
clock signals directly. This should be transparent to the user.
|
||||||
|
|
||||||
=item --compiler I<compiler-name>
|
=item --compiler I<compiler-name>
|
||||||
|
|
||||||
Enables tunings and workarounds for the specified C++ compiler.
|
Enables tunings and workarounds for the specified C++ compiler.
|
||||||
@@ -1913,54 +1917,71 @@ documented below.
|
|||||||
Verilator has an important difference from an event based simulator; signal
|
Verilator has an important difference from an event based simulator; signal
|
||||||
values that are changed by the VPI will not immediately propagate their
|
values that are changed by the VPI will not immediately propagate their
|
||||||
values, instead the top level header file's eval() method must be called.
|
values, instead the top level header file's eval() method must be called.
|
||||||
Normally this would be part of the normal evaluation (IE the next clock
|
Normally this would be part of the normal evaluation (i.e. the next clock
|
||||||
edge), not as part of the value change. This makes the performance of VPI
|
edge), not as part of the value change. This makes the performance of VPI
|
||||||
routines extremely fast compared to event based simulators, but can confuse
|
routines extremely fast compared to event based simulators, but can confuse
|
||||||
some test-benches that expect immediate propagation.
|
some test-benches that expect immediate propagation.
|
||||||
|
|
||||||
Note the VPI by it's specified implementation will always be much slower
|
Note the VPI by its specified implementation will always be much slower
|
||||||
than accessing the Verilator values by direct reference
|
than accessing the Verilator values by direct reference
|
||||||
(structure->module->signame), as the VPI accessors perform lookup in
|
(structure->module->signame), as the VPI accessors perform lookup in
|
||||||
functions at runtime requiring at best hundreds of instructions, while the
|
functions at runtime requiring at best hundreds of instructions, while the
|
||||||
direct references are evaluated by the compiler and result in only a couple
|
direct references are evaluated by the compiler and result in only a couple
|
||||||
of instructions.
|
of instructions.
|
||||||
|
|
||||||
|
For signal callbacks to work the main loop of the program must call
|
||||||
|
VerilatedVpi::callValueCbs().
|
||||||
|
|
||||||
=head2 VPI Example
|
=head2 VPI Example
|
||||||
|
|
||||||
In the below example, we have readme marked read-only, and writeme which if
|
In the below example, we have readme marked read-only, and writeme which if
|
||||||
written from outside the model will have the same semantics as if it
|
written from outside the model will have the same semantics as if it
|
||||||
changed on the specified clock edge.
|
changed on the specified clock edge.
|
||||||
|
|
||||||
module t;
|
cat <<EOF >our.v
|
||||||
reg readme /*verilator public_flat_rd*/;
|
module our (input clk);
|
||||||
reg writeme /*verilator public_flat_rw @(posedge clk) */;
|
reg readme /*verilator public_flat_rd*/;
|
||||||
endmodule
|
reg writeme /*verilator public_flat_rw @(posedge clk) */;
|
||||||
|
initial $finish;
|
||||||
|
endmodule
|
||||||
|
EOF
|
||||||
|
|
||||||
There are many online tutorials and books on the VPI, but an example that
|
There are many online tutorials and books on the VPI, but an example that
|
||||||
accesses the above would be:
|
accesses the above signal "readme" would be:
|
||||||
|
|
||||||
void read_and_check() {
|
cat <<EOF >sim_main.cpp
|
||||||
vpiHandle vh1 = vpi_handle_by_name((PLI_BYTE8*)"t.readme", NULL);
|
#include "Vour.h"
|
||||||
if (!vh1) { error... }
|
#include "verilated.h"
|
||||||
const char* name = vpi_get_str(vpiName, vh1);
|
#include "verilated_vpi.h" // Required to get definitions
|
||||||
printf("Module name: %s\n"); // Prints "readme"
|
|
||||||
|
|
||||||
s_vpi_value v;
|
vluint64_t main_time = 0; // See comments in first example
|
||||||
v.format = vpiIntVal;
|
double sc_time_stamp () { return main_time; }
|
||||||
vpi_get_value(vh1, &v);
|
|
||||||
printf("Value of v: %d\n", v.value.integer); // Prints "readme"
|
|
||||||
}
|
|
||||||
|
|
||||||
For signal callbacks to work the main loop of the program must call
|
void read_and_check() {
|
||||||
VerilatedVpi::callValueCbs().
|
vpiHandle vh1 = vpi_handle_by_name((PLI_BYTE8*)"TOP.our.readme", NULL);
|
||||||
|
if (!vh1) { vl_fatal(__FILE__, __LINE__, "sim_main", "No handle found"); }
|
||||||
|
const char* name = vpi_get_str(vpiName, vh1);
|
||||||
|
printf("Module name: %s\n", name); // Prints "readme"
|
||||||
|
|
||||||
#include "verilated_vpi.h" // Required to get definitions
|
s_vpi_value v;
|
||||||
...
|
v.format = vpiIntVal;
|
||||||
while (time passes) {
|
vpi_get_value(vh1, &v);
|
||||||
...
|
printf("Value of v: %d\n", v.value.integer); // Prints "readme"
|
||||||
topp->eval();
|
}
|
||||||
VerilatedVpi::callValueCbs();
|
|
||||||
}
|
int main(int argc, char **argv, char **env) {
|
||||||
|
Verilated::commandArgs(argc, argv);
|
||||||
|
Vour* top = new Vour;
|
||||||
|
Verilated::internalsDump(); // See scopes to help debug
|
||||||
|
while (!Verilated::gotFinish()) {
|
||||||
|
top->eval();
|
||||||
|
VerilatedVpi::callValueCbs(); // For signal callbacks
|
||||||
|
read_and_check();
|
||||||
|
}
|
||||||
|
delete top;
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
|
||||||
=head1 CROSS COMPILATION
|
=head1 CROSS COMPILATION
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
||||||
#AC_INIT([Verilator],[#.### devel])
|
#AC_INIT([Verilator],[#.### devel])
|
||||||
AC_INIT([Verilator],[3.902 2017-04-02])
|
AC_INIT([Verilator],[3.904 2017-05-30])
|
||||||
# When releasing, also update header of Changes file
|
# When releasing, also update header of Changes file
|
||||||
|
|
||||||
AC_CONFIG_HEADER(src/config_build.h)
|
AC_CONFIG_HEADER(src/config_build.h)
|
||||||
|
|||||||
+62
-20
@@ -302,8 +302,7 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
|||||||
bool inPct = false;
|
bool inPct = false;
|
||||||
bool widthSet = false;
|
bool widthSet = false;
|
||||||
int width = 0;
|
int width = 0;
|
||||||
const char* pos = formatp;
|
for (const char* pos = formatp; *pos; ++pos) {
|
||||||
for (; *pos; ++pos) {
|
|
||||||
if (!inPct && pos[0]=='%') {
|
if (!inPct && pos[0]=='%') {
|
||||||
pctp = pos;
|
pctp = pos;
|
||||||
inPct = true;
|
inPct = true;
|
||||||
@@ -1077,22 +1076,36 @@ IData VL_TESTPLUSARGS_I(const char* formatp) {
|
|||||||
else return 1;
|
else return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
IData VL_VALUEPLUSARGS_IN(int, const char* prefixp, char, string& ldr) {
|
IData VL_VALUEPLUSARGS_INW(int rbits, const string& ld, WDataOutP rwp) {
|
||||||
const string& match = VerilatedImp::argPlusMatch(prefixp);
|
string prefix;
|
||||||
const char* dp = match.c_str() + 1 /*leading + */ + strlen(prefixp);
|
bool inPct = false;
|
||||||
if (match == "") return 0;
|
bool done = false;
|
||||||
ldr = string(dp);
|
char fmt = ' ';
|
||||||
return 1;
|
for (const char* posp = ld.c_str(); !done && *posp; ++posp) {
|
||||||
}
|
if (!inPct && posp[0]=='%') {
|
||||||
|
inPct = true;
|
||||||
|
} else if (!inPct) { // Normal text
|
||||||
|
prefix += *posp;
|
||||||
|
} else { // Format character
|
||||||
|
switch (tolower(*posp)) {
|
||||||
|
case '%':
|
||||||
|
prefix += *posp;
|
||||||
|
inPct = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fmt = *posp;
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rwp) {
|
const string& match = VerilatedImp::argPlusMatch(prefix.c_str());
|
||||||
const string& match = VerilatedImp::argPlusMatch(prefixp);
|
const char* dp = match.c_str() + 1 /*leading + */ + prefix.length();
|
||||||
const char* dp = match.c_str() + 1 /*leading + */ + strlen(prefixp);
|
|
||||||
if (match == "") return 0;
|
if (match == "") return 0;
|
||||||
|
|
||||||
VL_ZERO_RESET_W(rbits, rwp);
|
VL_ZERO_RESET_W(rbits, rwp);
|
||||||
switch (tolower(fmt)) {
|
switch (tolower(fmt)) {
|
||||||
case '%':
|
|
||||||
break;
|
|
||||||
case 'd':
|
case 'd':
|
||||||
vlsint64_t ld;
|
vlsint64_t ld;
|
||||||
sscanf(dp,"%30" VL_PRI64 "d",&ld);
|
sscanf(dp,"%30" VL_PRI64 "d",&ld);
|
||||||
@@ -1108,18 +1121,47 @@ IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rw
|
|||||||
case 'x':
|
case 'x':
|
||||||
_vl_vsss_based(rwp,rbits, 4, dp, 0, (int)strlen(dp));
|
_vl_vsss_based(rwp,rbits, 4, dp, 0, (int)strlen(dp));
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's': // string/no conversion
|
||||||
for (int i=0, lsb=0, pos=((int)strlen(dp))-1; i<rbits && pos>=0; pos--) {
|
for (int i=0, lsb=0, posp=((int)strlen(dp))-1; i<rbits && posp>=0; posp--) {
|
||||||
_vl_vsss_setbit(rwp,rbits,lsb, 8, dp[pos]); lsb+=8;
|
_vl_vsss_setbit(rwp,rbits,lsb, 8, dp[posp]); lsb+=8;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: // Compile time should have found all errors before this
|
case 'e': //FALLTHRU - Unsupported
|
||||||
vl_fatal (__FILE__, __LINE__, "", "$value$plusargs format error");
|
case 'f': //FALLTHRU - Unsupported
|
||||||
break;
|
case 'g': //FALLTHRU - Unsupported
|
||||||
|
default: // Other simulators simply return 0 in these cases and don't error out
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
_VL_CLEAN_INPLACE_W(rbits,rwp);
|
_VL_CLEAN_INPLACE_W(rbits,rwp);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
IData VL_VALUEPLUSARGS_INN(int, const string& ld, string& rdr) {
|
||||||
|
string prefix;
|
||||||
|
bool inPct = false;
|
||||||
|
bool done = false;
|
||||||
|
for (const char* posp = ld.c_str(); !done && *posp; ++posp) {
|
||||||
|
if (!inPct && posp[0]=='%') {
|
||||||
|
inPct = true;
|
||||||
|
} else if (!inPct) { // Normal text
|
||||||
|
prefix += *posp;
|
||||||
|
} else { // Format character
|
||||||
|
switch (tolower(*posp)) {
|
||||||
|
case '%':
|
||||||
|
prefix += *posp;
|
||||||
|
inPct = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const string& match = VerilatedImp::argPlusMatch(prefix.c_str());
|
||||||
|
const char* dp = match.c_str() + 1 /*leading + */ + prefix.length();
|
||||||
|
if (match == "") return 0;
|
||||||
|
rdr = string(dp);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
const char* vl_mc_scan_plusargs(const char* prefixp) {
|
const char* vl_mc_scan_plusargs(const char* prefixp) {
|
||||||
const string& match = VerilatedImp::argPlusMatch(prefixp);
|
const string& match = VerilatedImp::argPlusMatch(prefixp);
|
||||||
|
|||||||
@@ -1077,7 +1077,9 @@ static inline QData VL_MULS_QQQ(int,int lbits,int, QData lhs,QData rhs) {
|
|||||||
|
|
||||||
static inline WDataOutP VL_MULS_WWW(int,int lbits,int, WDataOutP owp,WDataInP lwp,WDataInP rwp){
|
static inline WDataOutP VL_MULS_WWW(int,int lbits,int, WDataOutP owp,WDataInP lwp,WDataInP rwp){
|
||||||
int words = VL_WORDS_I(lbits);
|
int words = VL_WORDS_I(lbits);
|
||||||
|
// cppcheck-suppress variableScope
|
||||||
IData lwstore[VL_MULS_MAX_WORDS]; // Fixed size, as MSVC++ doesn't allow [words] here
|
IData lwstore[VL_MULS_MAX_WORDS]; // Fixed size, as MSVC++ doesn't allow [words] here
|
||||||
|
// cppcheck-suppress variableScope
|
||||||
IData rwstore[VL_MULS_MAX_WORDS];
|
IData rwstore[VL_MULS_MAX_WORDS];
|
||||||
WDataInP lwusp = lwp;
|
WDataInP lwusp = lwp;
|
||||||
WDataInP rwusp = rwp;
|
WDataInP rwusp = rwp;
|
||||||
|
|||||||
@@ -66,6 +66,19 @@ extern void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwo
|
|||||||
extern IData VL_SSCANF_INX(int lbits, const string& ld, const char* formatp, ...);
|
extern IData VL_SSCANF_INX(int lbits, const string& ld, const char* formatp, ...);
|
||||||
extern void VL_SFORMAT_X(int obits_ignored, string &output, const char* formatp, ...);
|
extern void VL_SFORMAT_X(int obits_ignored, string &output, const char* formatp, ...);
|
||||||
extern string VL_SFORMATF_NX(const char* formatp, ...);
|
extern string VL_SFORMATF_NX(const char* formatp, ...);
|
||||||
extern IData VL_VALUEPLUSARGS_IN(int rbits, const char* prefixp, char fmt, string& ldr);
|
extern IData VL_VALUEPLUSARGS_INW(int rbits, const string& ld, WDataOutP rdp);
|
||||||
|
inline IData VL_VALUEPLUSARGS_INI(int rbits, const string& ld, IData& rdr) {
|
||||||
|
IData rwp[1];
|
||||||
|
IData got = VL_VALUEPLUSARGS_INW(rbits,ld,rwp);
|
||||||
|
if (got) rdr = rwp[0];
|
||||||
|
return got;
|
||||||
|
}
|
||||||
|
inline IData VL_VALUEPLUSARGS_INQ(int rbits, const string& ld, QData& rdr) {
|
||||||
|
IData rwp[2];
|
||||||
|
IData got = VL_VALUEPLUSARGS_INW(rbits,ld,rwp);
|
||||||
|
if (got) rdr = VL_SET_QW(rwp);
|
||||||
|
return got;
|
||||||
|
}
|
||||||
|
extern IData VL_VALUEPLUSARGS_INN(int, const string& ld, string& rdr);
|
||||||
|
|
||||||
#endif // Guard
|
#endif // Guard
|
||||||
|
|||||||
+1
-1
@@ -108,7 +108,7 @@ private:
|
|||||||
// Move the active's contents to the other active
|
// Move the active's contents to the other active
|
||||||
UINFO(4," merge active "<<sensesp<<" into "<<wantp<<endl);
|
UINFO(4," merge active "<<sensesp<<" into "<<wantp<<endl);
|
||||||
if (nodep->sensesStorep()) {
|
if (nodep->sensesStorep()) {
|
||||||
if (sensesp != nodep->sensesStorep()) nodep->v3fatalSrc("sensesStore should have been deleted earlier if different\n");
|
if (sensesp != nodep->sensesStorep()) nodep->v3fatalSrc("sensesStore should have been deleted earlier if different");
|
||||||
sensesp->unlinkFrBack();
|
sensesp->unlinkFrBack();
|
||||||
// There may be other references to same sense tree,
|
// There may be other references to same sense tree,
|
||||||
// we'll be removing all references when we get to them,
|
// we'll be removing all references when we get to them,
|
||||||
|
|||||||
+4
-14
@@ -246,20 +246,10 @@ private:
|
|||||||
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
||||||
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) {
|
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) {
|
||||||
AstNode* onep;
|
AstNode* onep;
|
||||||
AstConst* iconstp = icondp->castConst();
|
if (nodep->casex() || nodep->casez() || nodep->caseInside()) {
|
||||||
if (iconstp && iconstp->num().isFourState()
|
onep = AstEqWild::newTyped(itemp->fileline(),
|
||||||
&& (nodep->casex() || nodep->casez() || nodep->caseInside())) {
|
nodep->exprp()->cloneTree(false),
|
||||||
V3Number nummask (itemp->fileline(), iconstp->width());
|
icondp->cloneTree(false));
|
||||||
nummask.opBitsNonX(iconstp->num());
|
|
||||||
V3Number numval (itemp->fileline(), iconstp->width());
|
|
||||||
numval.opBitsOne(iconstp->num());
|
|
||||||
AstNode* and1p = new AstAnd(itemp->fileline(), nodep->exprp()->cloneTree(false),
|
|
||||||
new AstConst(itemp->fileline(), nummask));
|
|
||||||
AstNode* and2p = new AstAnd(itemp->fileline(),
|
|
||||||
new AstConst(itemp->fileline(), numval),
|
|
||||||
new AstConst(itemp->fileline(), nummask));
|
|
||||||
onep = AstEq::newTyped(itemp->fileline(), and1p, and2p);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
onep = AstEq::newTyped(icondp->fileline(),
|
onep = AstEq::newTyped(icondp->fileline(),
|
||||||
nodep->exprp()->cloneTree(false),
|
nodep->exprp()->cloneTree(false),
|
||||||
|
|||||||
+13
-1
@@ -1675,6 +1675,7 @@ public:
|
|||||||
virtual bool maybePointedTo() const { return true; }
|
virtual bool maybePointedTo() const { return true; }
|
||||||
virtual AstNodeDType* virtRefDTypep() const { return NULL; } // Iff has a non-null refDTypep(), as generic node function
|
virtual AstNodeDType* virtRefDTypep() const { return NULL; } // Iff has a non-null refDTypep(), as generic node function
|
||||||
virtual void virtRefDTypep(AstNodeDType* nodep) { } // Iff has refDTypep(), set as generic node function
|
virtual void virtRefDTypep(AstNodeDType* nodep) { } // Iff has refDTypep(), set as generic node function
|
||||||
|
virtual bool similarDType(AstNodeDType* samep) const = 0; // Assignable equivalence. Call skipRefp() on this and samep before calling
|
||||||
//
|
//
|
||||||
// Changing the width may confuse the data type resolution, so must clear TypeTable cache after use.
|
// Changing the width may confuse the data type resolution, so must clear TypeTable cache after use.
|
||||||
void widthForce(int width, int sized) { m_width=width; m_widthMin=sized; }
|
void widthForce(int width, int sized) { m_width=width; m_widthMin=sized; }
|
||||||
@@ -1724,6 +1725,9 @@ public:
|
|||||||
virtual int widthAlignBytes() const; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
|
virtual int widthAlignBytes() const; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
|
||||||
virtual int widthTotalBytes() const; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
|
virtual int widthTotalBytes() const; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
|
||||||
// op1 = members
|
// op1 = members
|
||||||
|
virtual bool similarDType(AstNodeDType* samep) const {
|
||||||
|
return this==samep; // We don't compare members, require exact equivalence
|
||||||
|
}
|
||||||
AstMemberDType* membersp() const { return op1p()->castMemberDType(); } // op1 = AstMember list
|
AstMemberDType* membersp() const { return op1p()->castMemberDType(); } // op1 = AstMember list
|
||||||
void addMembersp(AstNode* nodep) { addNOp1p(nodep); }
|
void addMembersp(AstNode* nodep) { addNOp1p(nodep); }
|
||||||
bool packed() const { return m_packed; }
|
bool packed() const { return m_packed; }
|
||||||
@@ -1754,7 +1758,7 @@ public:
|
|||||||
virtual void dump(ostream& str);
|
virtual void dump(ostream& str);
|
||||||
virtual void dumpSmall(ostream& str);
|
virtual void dumpSmall(ostream& str);
|
||||||
virtual const char* broken() const { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists())
|
virtual const char* broken() const { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists())
|
||||||
|| (!m_refDTypep && childDTypep()))); return NULL; }
|
|| (!m_refDTypep && childDTypep()))); return NULL; }
|
||||||
virtual void cloneRelink() { if (m_refDTypep && m_refDTypep->clonep()) {
|
virtual void cloneRelink() { if (m_refDTypep && m_refDTypep->clonep()) {
|
||||||
m_refDTypep = m_refDTypep->clonep();
|
m_refDTypep = m_refDTypep->clonep();
|
||||||
}}
|
}}
|
||||||
@@ -1763,6 +1767,14 @@ public:
|
|||||||
return (msb()==sp->msb()
|
return (msb()==sp->msb()
|
||||||
&& subDTypep()==sp->subDTypep()
|
&& subDTypep()==sp->subDTypep()
|
||||||
&& rangenp()->sameTree(sp->rangenp())); } // HashedDT doesn't recurse, so need to check children
|
&& rangenp()->sameTree(sp->rangenp())); } // HashedDT doesn't recurse, so need to check children
|
||||||
|
virtual bool similarDType(AstNodeDType* samep) const {
|
||||||
|
AstNodeArrayDType* sp = samep->castNodeArrayDType();
|
||||||
|
return (sp
|
||||||
|
&& type() == samep->type()
|
||||||
|
&& msb() == sp->msb()
|
||||||
|
&& rangenp()->sameTree(sp->rangenp())
|
||||||
|
&& subDTypep()->skipRefp()->similarDType(sp->subDTypep()->skipRefp()));
|
||||||
|
}
|
||||||
virtual V3Hash sameHash() const { return V3Hash(V3Hash(m_refDTypep),V3Hash(msb()),V3Hash(lsb())); }
|
virtual V3Hash sameHash() const { return V3Hash(V3Hash(m_refDTypep),V3Hash(msb()),V3Hash(lsb())); }
|
||||||
AstNodeDType* getChildDTypep() const { return childDTypep(); }
|
AstNodeDType* getChildDTypep() const { return childDTypep(); }
|
||||||
AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable
|
AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable
|
||||||
|
|||||||
@@ -140,6 +140,13 @@ AstNodeBiop* AstLte::newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AstNodeBiop* AstEqWild::newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp) {
|
||||||
|
if (lhsp->isDouble() && rhsp->isDouble()) {
|
||||||
|
return new AstEqD(fl, lhsp, rhsp);
|
||||||
|
} else {
|
||||||
|
return new AstEqWild(fl, lhsp, rhsp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool AstVar::isSigPublic() const {
|
bool AstVar::isSigPublic() const {
|
||||||
return (m_sigPublic || (v3Global.opt.allPublic() && !isTemp() && !isGenVar()));
|
return (m_sigPublic || (v3Global.opt.allPublic() && !isTemp() && !isGenVar()));
|
||||||
|
|||||||
+29
-16
@@ -180,6 +180,10 @@ public:
|
|||||||
virtual AstNodeDType* skipRefp() const { return subDTypep()->skipRefp(); }
|
virtual AstNodeDType* skipRefp() const { return subDTypep()->skipRefp(); }
|
||||||
virtual AstNodeDType* skipRefToConstp() const { return subDTypep()->skipRefToConstp(); }
|
virtual AstNodeDType* skipRefToConstp() const { return subDTypep()->skipRefToConstp(); }
|
||||||
virtual AstNodeDType* skipRefToEnump() const { return subDTypep()->skipRefToEnump(); }
|
virtual AstNodeDType* skipRefToEnump() const { return subDTypep()->skipRefToEnump(); }
|
||||||
|
virtual bool similarDType(AstNodeDType* samep) const {
|
||||||
|
AstParamTypeDType* sp = samep->castParamTypeDType();
|
||||||
|
return (sp && this->subDTypep()->skipRefp()->similarDType(sp->subDTypep()->skipRefp()));
|
||||||
|
}
|
||||||
virtual int widthAlignBytes() const { return dtypep()->widthAlignBytes(); }
|
virtual int widthAlignBytes() const { return dtypep()->widthAlignBytes(); }
|
||||||
virtual int widthTotalBytes() const { return dtypep()->widthTotalBytes(); }
|
virtual int widthTotalBytes() const { return dtypep()->widthTotalBytes(); }
|
||||||
// METHODS
|
// METHODS
|
||||||
@@ -250,7 +254,9 @@ public:
|
|||||||
m_uniqueNum = uniqueNumInc();
|
m_uniqueNum = uniqueNumInc();
|
||||||
}
|
}
|
||||||
ASTNODE_NODE_FUNCS(DefImplicitDType)
|
ASTNODE_NODE_FUNCS(DefImplicitDType)
|
||||||
virtual bool same(AstNode* samep) const { return m_uniqueNum==samep->castDefImplicitDType()->m_uniqueNum; }
|
virtual bool same(AstNode* samep) const { return m_uniqueNum==samep->castDefImplicitDType()->m_uniqueNum; }
|
||||||
|
virtual bool similarDType(AstNodeDType* samep) const {
|
||||||
|
return type()==samep->type() && same(samep); }
|
||||||
virtual V3Hash sameHash() const { return V3Hash(m_uniqueNum); }
|
virtual V3Hash sameHash() const { return V3Hash(m_uniqueNum); }
|
||||||
AstNodeDType* getChildDTypep() const { return childDTypep(); }
|
AstNodeDType* getChildDTypep() const { return childDTypep(); }
|
||||||
AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable
|
AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable
|
||||||
@@ -392,6 +398,8 @@ public:
|
|||||||
virtual V3Hash sameHash() const { return V3Hash(V3Hash(m.m_keyword), V3Hash(m.m_nrange.hi())); }
|
virtual V3Hash sameHash() const { return V3Hash(V3Hash(m.m_keyword), V3Hash(m.m_nrange.hi())); }
|
||||||
virtual bool same(AstNode* samep) const { // width/widthMin/numeric compared elsewhere
|
virtual bool same(AstNode* samep) const { // width/widthMin/numeric compared elsewhere
|
||||||
return samep->castBasicDType()->m == m; }
|
return samep->castBasicDType()->m == m; }
|
||||||
|
virtual bool similarDType(AstNodeDType* samep) const {
|
||||||
|
return type()==samep->type() && same(samep); }
|
||||||
virtual string name() const { return m.m_keyword.ascii(); }
|
virtual string name() const { return m.m_keyword.ascii(); }
|
||||||
virtual const char* broken() const { BROKEN_RTN(dtypep()!=this); return NULL; }
|
virtual const char* broken() const { BROKEN_RTN(dtypep()!=this); return NULL; }
|
||||||
AstRange* rangep() const { return op1p()->castRange(); } // op1 = Range of variable
|
AstRange* rangep() const { return op1p()->castRange(); } // op1 = Range of variable
|
||||||
@@ -456,6 +464,8 @@ public:
|
|||||||
}}
|
}}
|
||||||
virtual bool same(AstNode* samep) const {
|
virtual bool same(AstNode* samep) const {
|
||||||
return (m_refDTypep==samep->castConstDType()->m_refDTypep); }
|
return (m_refDTypep==samep->castConstDType()->m_refDTypep); }
|
||||||
|
virtual bool similarDType(AstNodeDType* samep) const {
|
||||||
|
return skipRefp()->similarDType(samep->skipRefp()); }
|
||||||
virtual V3Hash sameHash() const { return V3Hash(m_refDTypep); } // node's type() included elsewhere
|
virtual V3Hash sameHash() const { return V3Hash(m_refDTypep); } // node's type() included elsewhere
|
||||||
AstNodeDType* getChildDTypep() const { return childDTypep(); }
|
AstNodeDType* getChildDTypep() const { return childDTypep(); }
|
||||||
AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable
|
AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable
|
||||||
@@ -499,6 +509,7 @@ public:
|
|||||||
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
|
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
|
||||||
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
|
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
|
||||||
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
|
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
|
||||||
|
virtual bool similarDType(AstNodeDType* samep) const { return this==samep; }
|
||||||
virtual int widthAlignBytes() const { return 1; }
|
virtual int widthAlignBytes() const { return 1; }
|
||||||
virtual int widthTotalBytes() const { return 1; }
|
virtual int widthTotalBytes() const { return 1; }
|
||||||
string cellName() const { return m_cellName; }
|
string cellName() const { return m_cellName; }
|
||||||
@@ -540,6 +551,8 @@ public:
|
|||||||
return (m_refDTypep==samep->castRefDType()->m_refDTypep
|
return (m_refDTypep==samep->castRefDType()->m_refDTypep
|
||||||
&& m_name==samep->castRefDType()->m_name
|
&& m_name==samep->castRefDType()->m_name
|
||||||
&& m_packagep==samep->castRefDType()->m_packagep); }
|
&& m_packagep==samep->castRefDType()->m_packagep); }
|
||||||
|
virtual bool similarDType(AstNodeDType* samep) const {
|
||||||
|
return skipRefp()->similarDType(samep->skipRefp()); }
|
||||||
virtual V3Hash sameHash() const { return V3Hash(V3Hash(m_refDTypep),V3Hash(m_packagep)); }
|
virtual V3Hash sameHash() const { return V3Hash(V3Hash(m_refDTypep),V3Hash(m_packagep)); }
|
||||||
virtual void dump(ostream& str=cout);
|
virtual void dump(ostream& str=cout);
|
||||||
virtual string name() const { return m_name; }
|
virtual string name() const { return m_name; }
|
||||||
@@ -623,6 +636,7 @@ public:
|
|||||||
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
|
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
|
||||||
virtual AstNodeDType* virtRefDTypep() const { return m_refDTypep; }
|
virtual AstNodeDType* virtRefDTypep() const { return m_refDTypep; }
|
||||||
virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); }
|
virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); }
|
||||||
|
virtual bool similarDType(AstNodeDType* samep) const { return this==samep; }
|
||||||
//
|
//
|
||||||
virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type (Note don't need virtual - AstVar isn't a NodeDType)
|
virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type (Note don't need virtual - AstVar isn't a NodeDType)
|
||||||
AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } // op1 = Range of variable (Note don't need virtual - AstVar isn't a NodeDType)
|
AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } // op1 = Range of variable (Note don't need virtual - AstVar isn't a NodeDType)
|
||||||
@@ -704,6 +718,7 @@ public:
|
|||||||
m_refDTypep = m_refDTypep->clonep();
|
m_refDTypep = m_refDTypep->clonep();
|
||||||
}}
|
}}
|
||||||
virtual bool same(AstNode* samep) const { return m_uniqueNum==samep->castEnumDType()->m_uniqueNum; }
|
virtual bool same(AstNode* samep) const { return m_uniqueNum==samep->castEnumDType()->m_uniqueNum; }
|
||||||
|
virtual bool similarDType(AstNodeDType* samep) const { return this==samep; }
|
||||||
virtual V3Hash sameHash() const { return V3Hash(m_uniqueNum); }
|
virtual V3Hash sameHash() const { return V3Hash(m_uniqueNum); }
|
||||||
AstNodeDType* getChildDTypep() const { return childDTypep(); }
|
AstNodeDType* getChildDTypep() const { return childDTypep(); }
|
||||||
AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Data type
|
AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Data type
|
||||||
@@ -733,6 +748,7 @@ public:
|
|||||||
ASTNODE_NODE_FUNCS(ParseTypeDType)
|
ASTNODE_NODE_FUNCS(ParseTypeDType)
|
||||||
AstNodeDType* dtypep() const { return NULL; }
|
AstNodeDType* dtypep() const { return NULL; }
|
||||||
// METHODS
|
// METHODS
|
||||||
|
virtual bool similarDType(AstNodeDType* samep) const { return this==samep; }
|
||||||
virtual AstBasicDType* basicp() const { return NULL; }
|
virtual AstBasicDType* basicp() const { return NULL; }
|
||||||
virtual AstNodeDType* skipRefp() const { return NULL; }
|
virtual AstNodeDType* skipRefp() const { return NULL; }
|
||||||
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
|
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
|
||||||
@@ -2642,28 +2658,24 @@ public:
|
|||||||
class AstValuePlusArgs : public AstNodeMath {
|
class AstValuePlusArgs : public AstNodeMath {
|
||||||
// Parents: expr
|
// Parents: expr
|
||||||
// Child: variable to set. If NULL then this is a $test$plusargs instead of $value$plusargs
|
// Child: variable to set. If NULL then this is a $test$plusargs instead of $value$plusargs
|
||||||
private:
|
|
||||||
string m_text;
|
|
||||||
public:
|
public:
|
||||||
AstValuePlusArgs(FileLine* fileline, const string& text, AstNode* exprsp)
|
AstValuePlusArgs(FileLine* fileline, AstNode* searchp, AstNode* outp)
|
||||||
: AstNodeMath (fileline), m_text(text) {
|
: AstNodeMath (fileline) {
|
||||||
setOp1p(exprsp);
|
setOp1p(searchp); setOp2p(outp);
|
||||||
}
|
}
|
||||||
ASTNODE_NODE_FUNCS(ValuePlusArgs)
|
ASTNODE_NODE_FUNCS(ValuePlusArgs)
|
||||||
virtual string name() const { return m_text; }
|
|
||||||
virtual string verilogKwd() const { return "$value$plusargs"; }
|
virtual string verilogKwd() const { return "$value$plusargs"; }
|
||||||
virtual string emitVerilog() { return verilogKwd(); }
|
virtual string emitVerilog() { return "%f$value$plusargs(%l, %k%r)"; }
|
||||||
virtual string emitC() { return "VL_VALUEPLUSARGS_%nq(%lw, %P, NULL)"; }
|
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||||
virtual bool isGateOptimizable() const { return false; }
|
virtual bool isGateOptimizable() const { return false; }
|
||||||
virtual bool isPredictOptimizable() const { return false; }
|
virtual bool isPredictOptimizable() const { return false; }
|
||||||
virtual bool cleanOut() { return true; }
|
virtual bool cleanOut() { return true; }
|
||||||
virtual V3Hash sameHash() const { return V3Hash(text()); }
|
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||||
virtual bool same(AstNode* samep) const {
|
virtual bool same(AstNode* samep) const { return true; }
|
||||||
return text()==samep->castValuePlusArgs()->text(); }
|
AstNode* searchp() const { return op1p(); } // op1 = Search expression
|
||||||
AstNode* exprsp() const { return op1p(); } // op1 = Expressions to output
|
void searchp(AstNode* nodep) { setOp1p(nodep); }
|
||||||
void exprsp(AstNode* nodep) { setOp1p(nodep); } // op1 = Expressions to output
|
AstNode* outp() const { return op2p(); } // op2 = Expressions to output
|
||||||
string text() const { return m_text; } // * = Text to display
|
void outp(AstNode* nodep) { setOp2p(nodep); }
|
||||||
void text(const string& text) { m_text=text; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class AstTestPlusArgs : public AstNodeMath {
|
class AstTestPlusArgs : public AstNodeMath {
|
||||||
@@ -4657,6 +4669,7 @@ public:
|
|||||||
dtypeSetLogicBool(); }
|
dtypeSetLogicBool(); }
|
||||||
ASTNODE_NODE_FUNCS(EqWild)
|
ASTNODE_NODE_FUNCS(EqWild)
|
||||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstEqWild(this->fileline(), lhsp, rhsp); }
|
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstEqWild(this->fileline(), lhsp, rhsp); }
|
||||||
|
static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp); // Return AstEqWild/AstEqD
|
||||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opWildEq(lhs,rhs); }
|
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opWildEq(lhs,rhs); }
|
||||||
virtual string emitVerilog() { return "%k(%l %f==? %r)"; }
|
virtual string emitVerilog() { return "%k(%l %f==? %r)"; }
|
||||||
virtual string emitC() { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; }
|
virtual string emitC() { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; }
|
||||||
|
|||||||
+5
-5
@@ -62,7 +62,7 @@ public:
|
|||||||
if (debug()>=9) cout<<"-nodeDel: "<<(void*)(nodep)<<endl;
|
if (debug()>=9) cout<<"-nodeDel: "<<(void*)(nodep)<<endl;
|
||||||
NodeMap::iterator iter = s_nodes.find(nodep);
|
NodeMap::iterator iter = s_nodes.find(nodep);
|
||||||
if (iter==s_nodes.end() || !(iter->second & FLAG_ALLOCATED)) {
|
if (iter==s_nodes.end() || !(iter->second & FLAG_ALLOCATED)) {
|
||||||
((AstNode*)(nodep))->v3fatalSrc("Deleting AstNode object that was never tracked or already deleted\n");
|
((AstNode*)(nodep))->v3fatalSrc("Deleting AstNode object that was never tracked or already deleted");
|
||||||
}
|
}
|
||||||
if (iter!=s_nodes.end()) s_nodes.erase(iter);
|
if (iter!=s_nodes.end()) s_nodes.erase(iter);
|
||||||
}
|
}
|
||||||
@@ -71,7 +71,7 @@ public:
|
|||||||
if (debug()>=9) cout<<"-nodeNew: "<<(void*)(nodep)<<endl;
|
if (debug()>=9) cout<<"-nodeNew: "<<(void*)(nodep)<<endl;
|
||||||
NodeMap::iterator iter = s_nodes.find(nodep);
|
NodeMap::iterator iter = s_nodes.find(nodep);
|
||||||
if (iter!=s_nodes.end() || (iter->second & FLAG_ALLOCATED)) {
|
if (iter!=s_nodes.end() || (iter->second & FLAG_ALLOCATED)) {
|
||||||
((AstNode*)(nodep))->v3fatalSrc("Newing AstNode object that is already allocated\n");
|
((AstNode*)(nodep))->v3fatalSrc("Newing AstNode object that is already allocated");
|
||||||
}
|
}
|
||||||
if (iter == s_nodes.end()) {
|
if (iter == s_nodes.end()) {
|
||||||
int flags = FLAG_ALLOCATED; // This int needed to appease GCC 4.1.2
|
int flags = FLAG_ALLOCATED; // This int needed to appease GCC 4.1.2
|
||||||
@@ -94,16 +94,16 @@ public:
|
|||||||
NodeMap::iterator iter = s_nodes.find(nodep);
|
NodeMap::iterator iter = s_nodes.find(nodep);
|
||||||
if (iter == s_nodes.end()) {
|
if (iter == s_nodes.end()) {
|
||||||
#ifdef VL_LEAK_CHECKS
|
#ifdef VL_LEAK_CHECKS
|
||||||
nodep->v3fatalSrc("AstNode is in tree, but not allocated\n");
|
nodep->v3fatalSrc("AstNode is in tree, but not allocated");
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
if (!(iter->second & FLAG_ALLOCATED)) {
|
if (!(iter->second & FLAG_ALLOCATED)) {
|
||||||
#ifdef VL_LEAK_CHECKS
|
#ifdef VL_LEAK_CHECKS
|
||||||
nodep->v3fatalSrc("AstNode is in tree, but not allocated\n");
|
nodep->v3fatalSrc("AstNode is in tree, but not allocated");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (iter->second & FLAG_IN_TREE) {
|
if (iter->second & FLAG_IN_TREE) {
|
||||||
nodep->v3fatalSrc("AstNode is already in tree at another location\n");
|
nodep->v3fatalSrc("AstNode is already in tree at another location");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int or_flags = FLAG_IN_TREE | (linkable?FLAG_LINKABLE:0);
|
int or_flags = FLAG_IN_TREE | (linkable?FLAG_LINKABLE:0);
|
||||||
|
|||||||
+7
-2
@@ -75,7 +75,8 @@ public:
|
|||||||
m_numStmts += 1;
|
m_numStmts += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
V3CCtorsVisitor(AstNodeModule* nodep, string basename, string argsp="", string callargsp="") {
|
V3CCtorsVisitor(AstNodeModule* nodep, string basename, string argsp="", string callargsp="",
|
||||||
|
const string& stmt="") {
|
||||||
m_basename = basename;
|
m_basename = basename;
|
||||||
m_argsp = argsp;
|
m_argsp = argsp;
|
||||||
m_callargsp = callargsp;
|
m_callargsp = callargsp;
|
||||||
@@ -87,6 +88,9 @@ public:
|
|||||||
m_tlFuncp->isStatic(false);
|
m_tlFuncp->isStatic(false);
|
||||||
m_tlFuncp->slow(true);
|
m_tlFuncp->slow(true);
|
||||||
m_tlFuncp->argTypes(m_argsp);
|
m_tlFuncp->argTypes(m_argsp);
|
||||||
|
if (stmt != "") {
|
||||||
|
m_tlFuncp->addStmtsp(new AstCStmt(nodep->fileline(), stmt));
|
||||||
|
}
|
||||||
m_funcp = m_tlFuncp;
|
m_funcp = m_tlFuncp;
|
||||||
m_modp->addStmtp(m_tlFuncp);
|
m_modp->addStmtp(m_tlFuncp);
|
||||||
}
|
}
|
||||||
@@ -100,7 +104,8 @@ void V3CCtors::cctorsAll() {
|
|||||||
// Process each module in turn
|
// Process each module in turn
|
||||||
V3CCtorsVisitor var_reset (modp, "_ctor_var_reset");
|
V3CCtorsVisitor var_reset (modp, "_ctor_var_reset");
|
||||||
V3CCtorsVisitor configure_coverage (modp, "_configure_coverage",
|
V3CCtorsVisitor configure_coverage (modp, "_configure_coverage",
|
||||||
EmitCBaseVisitor::symClassVar()+ ", bool first", "vlSymsp, first");
|
EmitCBaseVisitor::symClassVar()+ ", bool first", "vlSymsp, first",
|
||||||
|
"if (0 && vlSymsp && first) {} // Prevent unused\n");
|
||||||
|
|
||||||
for (AstNode* np = modp->stmtsp(); np; np = np->nextp()) {
|
for (AstNode* np = modp->stmtsp(); np; np = np->nextp()) {
|
||||||
AstVar* varp = np->castVar();
|
AstVar* varp = np->castVar();
|
||||||
|
|||||||
+1
-1
@@ -174,7 +174,7 @@ private:
|
|||||||
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) {
|
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) {
|
||||||
//if (debug()>=9) icondp->dumpTree(cout," caseitem: ");
|
//if (debug()>=9) icondp->dumpTree(cout," caseitem: ");
|
||||||
AstConst* iconstp = icondp->castConst();
|
AstConst* iconstp = icondp->castConst();
|
||||||
if (!iconstp) nodep->v3fatalSrc("above 'can't parse' should have caught this\n");
|
if (!iconstp) nodep->v3fatalSrc("above 'can't parse' should have caught this");
|
||||||
if (neverItem(nodep, iconstp)) {
|
if (neverItem(nodep, iconstp)) {
|
||||||
// X in casez can't ever be executed
|
// X in casez can't ever be executed
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+2
-2
@@ -629,9 +629,9 @@ private:
|
|||||||
}
|
}
|
||||||
virtual void visit(AstNodeVarRef* nodep) {
|
virtual void visit(AstNodeVarRef* nodep) {
|
||||||
if (m_scopep) {
|
if (m_scopep) {
|
||||||
if (!m_logicVertexp) nodep->v3fatalSrc("Var ref not under a logic block\n");
|
if (!m_logicVertexp) nodep->v3fatalSrc("Var ref not under a logic block");
|
||||||
AstVarScope* varscp = nodep->varScopep();
|
AstVarScope* varscp = nodep->varScopep();
|
||||||
if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n");
|
if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp");
|
||||||
CdcVarVertex* varvertexp = makeVarVertex(varscp);
|
CdcVarVertex* varvertexp = makeVarVertex(varscp);
|
||||||
UINFO(5," VARREF to "<<varscp<<endl);
|
UINFO(5," VARREF to "<<varscp<<endl);
|
||||||
// We use weight of one for normal edges,
|
// We use weight of one for normal edges,
|
||||||
|
|||||||
+1
-1
@@ -253,7 +253,7 @@ private:
|
|||||||
AstNode::user1ClearTree();
|
AstNode::user1ClearTree();
|
||||||
// Create the change detection function
|
// Create the change detection function
|
||||||
AstScope* scopep = nodep->scopep();
|
AstScope* scopep = nodep->scopep();
|
||||||
if (!scopep) nodep->v3fatalSrc("No scope found on top level, perhaps you have no statements?\n");
|
if (!scopep) nodep->v3fatalSrc("No scope found on top level, perhaps you have no statements?");
|
||||||
m_statep->m_scopetopp = scopep;
|
m_statep->m_scopetopp = scopep;
|
||||||
|
|
||||||
// Create a wrapper change detection function that calls each change detection function
|
// Create a wrapper change detection function that calls each change detection function
|
||||||
|
|||||||
+1
-1
@@ -559,7 +559,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
|||||||
if (!vVxp->inBeginp()) {
|
if (!vVxp->inBeginp()) {
|
||||||
// At this point, any variable not linked is an error
|
// At this point, any variable not linked is an error
|
||||||
// (It should have at least landed under the Head node)
|
// (It should have at least landed under the Head node)
|
||||||
vVxp->nodep()->v3fatalSrc("Variable became stranded in clk gate detection\n");
|
vVxp->nodep()->v3fatalSrc("Variable became stranded in clk gate detection");
|
||||||
}
|
}
|
||||||
if (!lastVxp || vVxp->sortCmp(lastVxp)) {
|
if (!lastVxp || vVxp->sortCmp(lastVxp)) {
|
||||||
// Different sources for this new node
|
// Different sources for this new node
|
||||||
|
|||||||
+1
-1
@@ -192,7 +192,7 @@ private:
|
|||||||
UINFO(4," TOPSCOPE "<<nodep<<endl);
|
UINFO(4," TOPSCOPE "<<nodep<<endl);
|
||||||
m_topScopep=nodep;
|
m_topScopep=nodep;
|
||||||
m_scopep = nodep->scopep();
|
m_scopep = nodep->scopep();
|
||||||
if (!m_scopep) nodep->v3fatalSrc("No scope found on top level, perhaps you have no statements?\n");
|
if (!m_scopep) nodep->v3fatalSrc("No scope found on top level, perhaps you have no statements?");
|
||||||
//VV***** We reset all user1p()
|
//VV***** We reset all user1p()
|
||||||
AstNode::user1ClearTree();
|
AstNode::user1ClearTree();
|
||||||
// Make top functions
|
// Make top functions
|
||||||
|
|||||||
+1
-1
@@ -239,7 +239,7 @@ private:
|
|||||||
V3Hash hashval = it->first;
|
V3Hash hashval = it->first;
|
||||||
AstNode* node1p = it->second;
|
AstNode* node1p = it->second;
|
||||||
if (!node1p->castCFunc()) continue;
|
if (!node1p->castCFunc()) continue;
|
||||||
if (hashval.isIllegal()) node1p->v3fatalSrc("Illegal (unhashed) nodes\n");
|
if (hashval.isIllegal()) node1p->v3fatalSrc("Illegal (unhashed) nodes");
|
||||||
for (V3Hashed::iterator eqit = it; eqit != m_hashed.end(); ++eqit) {
|
for (V3Hashed::iterator eqit = it; eqit != m_hashed.end(); ++eqit) {
|
||||||
AstNode* node2p = eqit->second;
|
AstNode* node2p = eqit->second;
|
||||||
if (!(eqit->first == hashval)) break;
|
if (!(eqit->first == hashval)) break;
|
||||||
|
|||||||
+9
-1
@@ -555,7 +555,7 @@ private:
|
|||||||
// Replace oldp node with a constant set to specified value
|
// Replace oldp node with a constant set to specified value
|
||||||
UASSERT (oldp, "Null old\n");
|
UASSERT (oldp, "Null old\n");
|
||||||
if (oldp->castConst() && !oldp->castConst()->num().isFourState()) {
|
if (oldp->castConst() && !oldp->castConst()->num().isFourState()) {
|
||||||
oldp->v3fatalSrc("Already constant??\n");
|
oldp->v3fatalSrc("Already constant??");
|
||||||
}
|
}
|
||||||
AstNode* newp = new AstConst(oldp->fileline(), num);
|
AstNode* newp = new AstConst(oldp->fileline(), num);
|
||||||
newp->dtypeFrom(oldp);
|
newp->dtypeFrom(oldp);
|
||||||
@@ -1491,6 +1491,14 @@ private:
|
|||||||
did=true;
|
did=true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (m_params && valuep->castInitArray() && nodep->backp()->castPin()) {
|
||||||
|
// Allow parameters to pass arrays
|
||||||
|
// Earlier recursion of InitArray made sure each array value is constant
|
||||||
|
// This exception is fairly fragile, i.e. doesn't support arrays of arrays or other stuff
|
||||||
|
AstNode* newp = valuep->cloneTree(false);
|
||||||
|
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
|
did = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!did && m_required) {
|
if (!did && m_required) {
|
||||||
|
|||||||
+4
-4
@@ -207,8 +207,8 @@ private:
|
|||||||
dimvalp.push_front(valp);
|
dimvalp.push_front(valp);
|
||||||
}
|
}
|
||||||
AstVarRef* varrefp = dimselp->castVarRef();
|
AstVarRef* varrefp = dimselp->castVarRef();
|
||||||
if (!varrefp) nodep->v3fatalSrc("No var underneath arraysels\n");
|
if (!varrefp) nodep->v3fatalSrc("No var underneath arraysels");
|
||||||
if (!varrefp->varScopep()) varrefp->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n");
|
if (!varrefp->varScopep()) varrefp->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp");
|
||||||
varrefp->unlinkFrBack();
|
varrefp->unlinkFrBack();
|
||||||
AstVar* oldvarp = varrefp->varp();
|
AstVar* oldvarp = varrefp->varp();
|
||||||
int modVecNum = oldvarp->user4(); oldvarp->user4(modVecNum+1);
|
int modVecNum = oldvarp->user4(); oldvarp->user4(modVecNum+1);
|
||||||
@@ -393,7 +393,7 @@ private:
|
|||||||
if (!m_activep) nodep->v3fatalSrc("<= not under sensitivity block");
|
if (!m_activep) nodep->v3fatalSrc("<= not under sensitivity block");
|
||||||
if (!m_activep->hasClocked()) nodep->v3error("Internal: Blocking <= assignment in non-clocked block, should have converted in V3Active");
|
if (!m_activep->hasClocked()) nodep->v3error("Internal: Blocking <= assignment in non-clocked block, should have converted in V3Active");
|
||||||
AstVarScope* oldvscp = nodep->varScopep();
|
AstVarScope* oldvscp = nodep->varScopep();
|
||||||
if (!oldvscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n");
|
if (!oldvscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp");
|
||||||
AstVarScope* dlyvscp = oldvscp->user1p()->castVarScope();
|
AstVarScope* dlyvscp = oldvscp->user1p()->castVarScope();
|
||||||
if (dlyvscp) { // Multiple use of delayed variable
|
if (dlyvscp) { // Multiple use of delayed variable
|
||||||
AstActive* oldactivep = dlyvscp->user2p()->castActive();
|
AstActive* oldactivep = dlyvscp->user2p()->castActive();
|
||||||
@@ -433,7 +433,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstNodeFor* nodep) {
|
virtual void visit(AstNodeFor* nodep) {
|
||||||
nodep->v3fatalSrc("For statements should have been converted to while statements in V3Begin\n");
|
nodep->v3fatalSrc("For statements should have been converted to while statements in V3Begin");
|
||||||
}
|
}
|
||||||
virtual void visit(AstWhile* nodep) {
|
virtual void visit(AstWhile* nodep) {
|
||||||
bool oldloop = m_inLoop;
|
bool oldloop = m_inLoop;
|
||||||
|
|||||||
+25
-47
@@ -217,7 +217,7 @@ public:
|
|||||||
}
|
}
|
||||||
virtual void visit(AstNodeCase* nodep) {
|
virtual void visit(AstNodeCase* nodep) {
|
||||||
// In V3Case...
|
// In V3Case...
|
||||||
nodep->v3fatalSrc("Case statements should have been reduced out\n");
|
nodep->v3fatalSrc("Case statements should have been reduced out");
|
||||||
}
|
}
|
||||||
virtual void visit(AstComment* nodep) {
|
virtual void visit(AstComment* nodep) {
|
||||||
putsDecoration((string)"// "+nodep->name()+" at "+nodep->fileline()->ascii()+"\n");
|
putsDecoration((string)"// "+nodep->name()+" at "+nodep->fileline()->ascii()+"\n");
|
||||||
@@ -277,54 +277,15 @@ public:
|
|||||||
displayNode(nodep, NULL, nodep->text(), nodep->exprsp(), true);
|
displayNode(nodep, NULL, nodep->text(), nodep->exprsp(), true);
|
||||||
}
|
}
|
||||||
virtual void visit(AstValuePlusArgs* nodep) {
|
virtual void visit(AstValuePlusArgs* nodep) {
|
||||||
string prefix;
|
puts("VL_VALUEPLUSARGS_IN");
|
||||||
char format = '?';
|
emitIQW(nodep->outp());
|
||||||
bool pct=false;
|
|
||||||
int got=0;
|
|
||||||
string txt = nodep->text();
|
|
||||||
for (string::const_iterator it=txt.begin(); it!=txt.end(); ++it) {
|
|
||||||
char ch = *it;
|
|
||||||
if (pct) {
|
|
||||||
pct = false;
|
|
||||||
switch (tolower(ch)) {
|
|
||||||
case '%':
|
|
||||||
prefix += ch;
|
|
||||||
break;
|
|
||||||
case 'd': // FALLTHRU
|
|
||||||
case 'o': // FALLTHRU
|
|
||||||
case 'h': // FALLTHRU
|
|
||||||
case 'x': // FALLTHRU
|
|
||||||
case 'b': // FALLTHRU
|
|
||||||
case 'v': // FALLTHRU
|
|
||||||
case 's':
|
|
||||||
got++; format = tolower(ch);
|
|
||||||
break;
|
|
||||||
case 'e': // FALLTHRU
|
|
||||||
case 'f': // FALLTHRU
|
|
||||||
case 'g':
|
|
||||||
got++; format = tolower(ch);
|
|
||||||
nodep->v3error("Unsupported $value$plusargs format qualifier: '"<<ch<<"'"<<endl);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
got++;
|
|
||||||
nodep->v3error("Illegal $value$plusargs format qualifier: '"<<ch<<"'"<<endl);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (ch == '%') pct = true;
|
|
||||||
else prefix += ch;
|
|
||||||
}
|
|
||||||
if (got!=1) nodep->v3error("Missing or extra $value$plusargs format qualifier: '"<<nodep->text()<<"'"<<endl);
|
|
||||||
puts("VL_VALUEPLUSARGS_I");
|
|
||||||
emitIQW(nodep->exprsp());
|
|
||||||
puts("(");
|
puts("(");
|
||||||
puts(cvtToStr(nodep->exprsp()->widthMin())); // Note argument width, not node width (which is always 32)
|
puts(cvtToStr(nodep->outp()->widthMin()));
|
||||||
putbs(",");
|
|
||||||
putsQuoted(prefix);
|
|
||||||
putbs(",");
|
|
||||||
puts("'"); puts(cvtToStr(format)); puts("'");
|
|
||||||
puts(",");
|
puts(",");
|
||||||
nodep->exprsp()->iterateAndNext(*this);
|
emitCvtPackStr(nodep->searchp());
|
||||||
|
puts(",");
|
||||||
|
putbs("");
|
||||||
|
nodep->outp()->iterateAndNext(*this);
|
||||||
puts(")");
|
puts(")");
|
||||||
}
|
}
|
||||||
virtual void visit(AstTestPlusArgs* nodep) {
|
virtual void visit(AstTestPlusArgs* nodep) {
|
||||||
@@ -618,6 +579,23 @@ public:
|
|||||||
puts(nodep->hiername());
|
puts(nodep->hiername());
|
||||||
puts(nodep->varp()->name());
|
puts(nodep->varp()->name());
|
||||||
}
|
}
|
||||||
|
void emitCvtPackStr(AstNode* nodep) {
|
||||||
|
if (AstConst* constp = nodep->castConst()) {
|
||||||
|
putbs("string(");
|
||||||
|
putsQuoted(constp->num().toString());
|
||||||
|
puts(")");
|
||||||
|
} else {
|
||||||
|
putbs("VL_CVT_PACK_STR_N");
|
||||||
|
emitIQW(nodep);
|
||||||
|
puts("(");
|
||||||
|
if (nodep->isWide()) {
|
||||||
|
puts(cvtToStr(nodep->widthWords())); // Note argument width, not node width (which is always 32)
|
||||||
|
puts(",");
|
||||||
|
}
|
||||||
|
nodep->iterateAndNext(*this);
|
||||||
|
puts(")");
|
||||||
|
}
|
||||||
|
}
|
||||||
void emitConstant(AstConst* nodep, AstVarRef* assigntop, const string& assignString) {
|
void emitConstant(AstConst* nodep, AstVarRef* assigntop, const string& assignString) {
|
||||||
// Put out constant set to the specified variable, or given variable in a string
|
// Put out constant set to the specified variable, or given variable in a string
|
||||||
if (nodep->num().isFourState()) {
|
if (nodep->num().isFourState()) {
|
||||||
|
|||||||
@@ -238,10 +238,6 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||||||
virtual void visit(AstSFormatF* nodep) {
|
virtual void visit(AstSFormatF* nodep) {
|
||||||
visitNodeDisplay(nodep, NULL, nodep->text(), nodep->exprsp());
|
visitNodeDisplay(nodep, NULL, nodep->text(), nodep->exprsp());
|
||||||
}
|
}
|
||||||
virtual void visit(AstValuePlusArgs* nodep) {
|
|
||||||
visitNodeDisplay(nodep, NULL, nodep->text(), nodep->exprsp());
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void visit(AstFOpen* nodep) {
|
virtual void visit(AstFOpen* nodep) {
|
||||||
putfs(nodep,nodep->verilogKwd());
|
putfs(nodep,nodep->verilogKwd());
|
||||||
putbs(" (");
|
putbs(" (");
|
||||||
|
|||||||
+1
-1
@@ -270,7 +270,7 @@ void FileLine::operator delete(void* objp, size_t size) {
|
|||||||
if (it != fileLineLeakChecks.end()) {
|
if (it != fileLineLeakChecks.end()) {
|
||||||
fileLineLeakChecks.erase(it);
|
fileLineLeakChecks.erase(it);
|
||||||
} else {
|
} else {
|
||||||
flp->v3fatalSrc("Deleting FileLine object that was never tracked\n");
|
flp->v3fatalSrc("Deleting FileLine object that was never tracked");
|
||||||
}
|
}
|
||||||
::operator delete(objp);
|
::operator delete(objp);
|
||||||
}
|
}
|
||||||
|
|||||||
+216
-4
@@ -113,6 +113,20 @@ public:
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
// Returns only the result from the LAST vertex iterated over
|
||||||
|
// Note: This behaves differently than iterateInEdges() in that it will traverse
|
||||||
|
// all edges that exist when it is initially called, whereas
|
||||||
|
// iterateInEdges() will stop traversing edges if one is deleted
|
||||||
|
VNUser iterateCurrentOutEdges(GateGraphBaseVisitor& v, VNUser vu=VNUser(0)) {
|
||||||
|
VNUser ret = VNUser(0);
|
||||||
|
V3GraphEdge* next_edgep = NULL;
|
||||||
|
for (V3GraphEdge* edgep = outBeginp(); edgep; edgep = next_edgep) {
|
||||||
|
// Need to find the next edge before visiting in case the edge is deleted
|
||||||
|
next_edgep = edgep->outNextp();
|
||||||
|
ret = dynamic_cast<GateEitherVertex*>(edgep->top())->accept(v, vu);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class GateVarVertex : public GateEitherVertex {
|
class GateVarVertex : public GateEitherVertex {
|
||||||
@@ -291,6 +305,7 @@ private:
|
|||||||
// {statement}Node::user1p -> GateLogicVertex* for this statement
|
// {statement}Node::user1p -> GateLogicVertex* for this statement
|
||||||
// AstVarScope::user2 -> bool: Signal used in SenItem in *this* always statement
|
// AstVarScope::user2 -> bool: Signal used in SenItem in *this* always statement
|
||||||
// AstVar::user2 -> bool: Warned about SYNCASYNCNET
|
// AstVar::user2 -> bool: Warned about SYNCASYNCNET
|
||||||
|
// AstVarNodeRef::user2 -> bool: ConcatOffset visited
|
||||||
AstUser1InUse m_inuser1;
|
AstUser1InUse m_inuser1;
|
||||||
AstUser2InUse m_inuser2;
|
AstUser2InUse m_inuser2;
|
||||||
|
|
||||||
@@ -358,6 +373,7 @@ private:
|
|||||||
void replaceAssigns();
|
void replaceAssigns();
|
||||||
void dedupe();
|
void dedupe();
|
||||||
void mergeAssigns();
|
void mergeAssigns();
|
||||||
|
void decomposeClkVectors();
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNetlist* nodep) {
|
virtual void visit(AstNetlist* nodep) {
|
||||||
@@ -365,6 +381,8 @@ private:
|
|||||||
//if (debug()>6) m_graph.dump();
|
//if (debug()>6) m_graph.dump();
|
||||||
if (debug()>6) m_graph.dumpDotFilePrefixed("gate_pre");
|
if (debug()>6) m_graph.dumpDotFilePrefixed("gate_pre");
|
||||||
warnSignals(); // Before loss of sync/async pointers
|
warnSignals(); // Before loss of sync/async pointers
|
||||||
|
// Decompose clock vectors -- need to do this before removing redundant edges
|
||||||
|
decomposeClkVectors();
|
||||||
m_graph.removeRedundantEdgesSum(&V3GraphEdge::followAlwaysTrue);
|
m_graph.removeRedundantEdgesSum(&V3GraphEdge::followAlwaysTrue);
|
||||||
m_graph.dumpDotFilePrefixed("gate_simp");
|
m_graph.dumpDotFilePrefixed("gate_simp");
|
||||||
// Find gate interconnect and optimize
|
// Find gate interconnect and optimize
|
||||||
@@ -409,9 +427,9 @@ private:
|
|||||||
}
|
}
|
||||||
virtual void visit(AstNodeVarRef* nodep) {
|
virtual void visit(AstNodeVarRef* nodep) {
|
||||||
if (m_scopep) {
|
if (m_scopep) {
|
||||||
if (!m_logicVertexp) nodep->v3fatalSrc("Var ref not under a logic block\n");
|
if (!m_logicVertexp) nodep->v3fatalSrc("Var ref not under a logic block");
|
||||||
AstVarScope* varscp = nodep->varScopep();
|
AstVarScope* varscp = nodep->varScopep();
|
||||||
if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n");
|
if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp");
|
||||||
GateVarVertex* vvertexp = makeVarVertex(varscp);
|
GateVarVertex* vvertexp = makeVarVertex(varscp);
|
||||||
UINFO(5," VARREF to "<<varscp<<endl);
|
UINFO(5," VARREF to "<<varscp<<endl);
|
||||||
if (m_inSenItem) vvertexp->setIsClock();
|
if (m_inSenItem) vvertexp->setIsClock();
|
||||||
@@ -484,7 +502,7 @@ private:
|
|||||||
}
|
}
|
||||||
virtual void visit(AstConcat* nodep) {
|
virtual void visit(AstConcat* nodep) {
|
||||||
if (nodep->backp()->castNodeAssign() && nodep->backp()->castNodeAssign()->lhsp()==nodep) {
|
if (nodep->backp()->castNodeAssign() && nodep->backp()->castNodeAssign()->lhsp()==nodep) {
|
||||||
nodep->v3fatalSrc("Concat on LHS of assignment; V3Const should have deleted it\n");
|
nodep->v3fatalSrc("Concat on LHS of assignment; V3Const should have deleted it");
|
||||||
}
|
}
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
@@ -704,7 +722,7 @@ void GateVisitor::replaceAssigns() {
|
|||||||
if (!vscp->valuep()->castNodeMath()
|
if (!vscp->valuep()->castNodeMath()
|
||||||
|| vscp->valuep()->nextp()) {
|
|| vscp->valuep()->nextp()) {
|
||||||
vscp->dumpTree(cerr, "vscStrange: ");
|
vscp->dumpTree(cerr, "vscStrange: ");
|
||||||
vscp->v3fatalSrc("Value of varscope not mathematical\n");
|
vscp->v3fatalSrc("Value of varscope not mathematical");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1238,6 +1256,200 @@ void GateVisitor::mergeAssigns() {
|
|||||||
m_statAssignMerged += merger.numMergedAssigns();
|
m_statAssignMerged += merger.numMergedAssigns();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
// Find a var's offset in a concatenation
|
||||||
|
|
||||||
|
class GateConcatVisitor : public GateBaseVisitor {
|
||||||
|
private:
|
||||||
|
// STATE
|
||||||
|
AstVarScope* m_vscp; // Varscope we're trying to find
|
||||||
|
int m_offset; // Current offset of varscope
|
||||||
|
int m_found_offset; // Found offset of varscope
|
||||||
|
bool m_found; // Offset found
|
||||||
|
|
||||||
|
// VISITORS
|
||||||
|
virtual void visit(AstNodeVarRef* nodep) {
|
||||||
|
UINFO(9,"CLK DECOMP Concat search var (off = "<<m_offset<<") - "<<nodep<<endl);
|
||||||
|
if (nodep->varScopep() == m_vscp && !nodep->user2() && !m_found) {
|
||||||
|
// A concatenation may use the same var multiple times
|
||||||
|
// But the graph will initially have an edge per instance
|
||||||
|
nodep->user2(true);
|
||||||
|
m_found_offset = m_offset;
|
||||||
|
m_found = true;
|
||||||
|
UINFO(9,"CLK DECOMP Concat found var (off = "<<m_offset<<") - "<<nodep<<endl);
|
||||||
|
}
|
||||||
|
m_offset += nodep->dtypep()->width();
|
||||||
|
}
|
||||||
|
virtual void visit(AstConcat* nodep) {
|
||||||
|
UINFO(9,"CLK DECOMP Concat search (off = "<<m_offset<<") - "<<nodep<<endl);
|
||||||
|
nodep->rhsp()->iterate(*this);
|
||||||
|
nodep->lhsp()->iterate(*this);
|
||||||
|
}
|
||||||
|
//--------------------
|
||||||
|
// Default
|
||||||
|
virtual void visit(AstNode* nodep) {
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
// CONSTUCTORS
|
||||||
|
GateConcatVisitor() {
|
||||||
|
m_vscp = NULL;
|
||||||
|
m_offset = 0;
|
||||||
|
m_found_offset = 0;
|
||||||
|
m_found = false;
|
||||||
|
}
|
||||||
|
virtual ~GateConcatVisitor() {}
|
||||||
|
// PUBLIC METHODS
|
||||||
|
bool concatOffset(AstConcat* concatp, AstVarScope* vscp, int& offsetr) {
|
||||||
|
m_vscp = vscp;
|
||||||
|
m_offset = 0;
|
||||||
|
m_found = false;
|
||||||
|
// Iterate
|
||||||
|
concatp->accept(*this);
|
||||||
|
UINFO(9,"CLK DECOMP Concat Offset (found = "<<m_found<<") ("<<m_found_offset<<") - "<<concatp<<" : "<<vscp<<endl);
|
||||||
|
offsetr = m_found_offset;
|
||||||
|
return m_found;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
// Recurse through the graph, looking for clock vectors to bypass
|
||||||
|
|
||||||
|
class GateClkDecompState {
|
||||||
|
public:
|
||||||
|
int m_offset;
|
||||||
|
AstVarScope* m_last_vsp;
|
||||||
|
GateClkDecompState(int offset, AstVarScope* vsp) {
|
||||||
|
m_offset = offset;
|
||||||
|
m_last_vsp = vsp;
|
||||||
|
}
|
||||||
|
virtual ~GateClkDecompState() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class GateClkDecompGraphVisitor : public GateGraphBaseVisitor {
|
||||||
|
private:
|
||||||
|
// NODE STATE
|
||||||
|
// AstVarScope::user2p -> bool: already visited
|
||||||
|
V3Graph* m_graphp;
|
||||||
|
int m_seen_clk_vectors;
|
||||||
|
AstVarScope* m_clk_vsp;
|
||||||
|
GateVarVertex* m_clk_vvertexp;
|
||||||
|
GateConcatVisitor m_concat_visitor;
|
||||||
|
int m_total_seen_clk_vectors;
|
||||||
|
int m_total_decomposed_clk_vectors;
|
||||||
|
|
||||||
|
virtual VNUser visit(GateVarVertex* vvertexp, VNUser vu) {
|
||||||
|
// Check that we haven't been here before
|
||||||
|
AstVarScope* vsp = vvertexp->varScp();
|
||||||
|
if (vsp->user2SetOnce()) return VNUser(0);
|
||||||
|
UINFO(9,"CLK DECOMP Var - "<<vvertexp<<" : "<<vsp<<endl);
|
||||||
|
if (vsp->varp()->width() > 1) {
|
||||||
|
m_seen_clk_vectors++;
|
||||||
|
m_total_seen_clk_vectors++;
|
||||||
|
}
|
||||||
|
GateClkDecompState* currState = (GateClkDecompState*) vu.c();
|
||||||
|
GateClkDecompState nextState(currState->m_offset, vsp);
|
||||||
|
vvertexp->iterateCurrentOutEdges(*this, VNUser(&nextState));
|
||||||
|
if (vsp->varp()->width() > 1) {
|
||||||
|
m_seen_clk_vectors--;
|
||||||
|
}
|
||||||
|
vsp->user2(false);
|
||||||
|
return VNUser(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual VNUser visit(GateLogicVertex* lvertexp, VNUser vu) {
|
||||||
|
GateClkDecompState* currState = (GateClkDecompState*) vu.c();
|
||||||
|
int clk_offset = currState->m_offset;
|
||||||
|
if (AstAssignW* assignp = lvertexp->nodep()->castAssignW()) {
|
||||||
|
UINFO(9,"CLK DECOMP Logic (off = "<<clk_offset<<") - "<<lvertexp<<" : "<<m_clk_vsp<<endl);
|
||||||
|
if (AstSel* rselp = assignp->rhsp()->castSel()) {
|
||||||
|
if (rselp->lsbp()->castConst() && rselp->widthp()->castConst()) {
|
||||||
|
if (clk_offset < rselp->lsbConst() || clk_offset > rselp->msbConst()) {
|
||||||
|
UINFO(9,"CLK DECOMP Sel [ "<<rselp->msbConst()<<" : "<<rselp->lsbConst()<<" ] dropped clock ("<<clk_offset<<")"<<endl);
|
||||||
|
return VNUser(0);
|
||||||
|
}
|
||||||
|
clk_offset -= rselp->lsbConst();
|
||||||
|
} else {
|
||||||
|
return VNUser(0);
|
||||||
|
}
|
||||||
|
} else if (AstConcat* catp = assignp->rhsp()->castConcat()) {
|
||||||
|
UINFO(9,"CLK DECOMP Concat searching - "<<assignp->lhsp()<<endl);
|
||||||
|
int concat_offset;
|
||||||
|
if (!m_concat_visitor.concatOffset(catp, currState->m_last_vsp, concat_offset)) {
|
||||||
|
return VNUser(0);
|
||||||
|
}
|
||||||
|
clk_offset += concat_offset;
|
||||||
|
}
|
||||||
|
if (AstSel* lselp = assignp->lhsp()->castSel()) {
|
||||||
|
if (lselp->lsbp()->castConst() && lselp->widthp()->castConst()) {
|
||||||
|
clk_offset += lselp->lsbConst();
|
||||||
|
} else {
|
||||||
|
return VNUser(0);
|
||||||
|
}
|
||||||
|
} else if (AstVarRef* vrp = assignp->lhsp()->castVarRef()) {
|
||||||
|
if (vrp->dtypep()->width() == 1 && m_seen_clk_vectors) {
|
||||||
|
if (clk_offset != 0) {
|
||||||
|
UINFO(9,"Should only make it here with clk_offset = 0"<<endl);
|
||||||
|
return VNUser(0);
|
||||||
|
}
|
||||||
|
UINFO(9,"CLK DECOMP Connecting - "<<assignp->lhsp()<<" <-> "<<m_clk_vsp<<endl);
|
||||||
|
AstNode* rhsp = assignp->rhsp();
|
||||||
|
rhsp->replaceWith(new AstVarRef(rhsp->fileline(), m_clk_vsp, false));
|
||||||
|
for (V3GraphEdge* edgep = lvertexp->inBeginp(); edgep; ) {
|
||||||
|
edgep->unlinkDelete(); VL_DANGLING(edgep);
|
||||||
|
}
|
||||||
|
new V3GraphEdge(m_graphp, m_clk_vvertexp, lvertexp, 1);
|
||||||
|
m_total_decomposed_clk_vectors++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GateClkDecompState nextState(clk_offset, currState->m_last_vsp);
|
||||||
|
return lvertexp->iterateCurrentOutEdges(*this, VNUser(&nextState));
|
||||||
|
}
|
||||||
|
return VNUser(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
GateClkDecompGraphVisitor(V3Graph* graphp) {
|
||||||
|
m_graphp = graphp;
|
||||||
|
m_seen_clk_vectors = 0;
|
||||||
|
m_clk_vsp = NULL;
|
||||||
|
m_clk_vvertexp = NULL;
|
||||||
|
m_total_seen_clk_vectors = 0;
|
||||||
|
m_total_decomposed_clk_vectors = 0;
|
||||||
|
}
|
||||||
|
virtual ~GateClkDecompGraphVisitor() {
|
||||||
|
V3Stats::addStat("Optimizations, Clocker seen vectors", m_total_seen_clk_vectors);
|
||||||
|
V3Stats::addStat("Optimizations, Clocker decomposed vectors", m_total_decomposed_clk_vectors);
|
||||||
|
}
|
||||||
|
void clkDecomp(GateVarVertex* vvertexp) {
|
||||||
|
UINFO(9,"CLK DECOMP Starting Var - "<<vvertexp<<endl);
|
||||||
|
m_seen_clk_vectors = 0;
|
||||||
|
m_clk_vsp = vvertexp->varScp();
|
||||||
|
m_clk_vvertexp = vvertexp;
|
||||||
|
GateClkDecompState nextState(0, m_clk_vsp);
|
||||||
|
vvertexp->accept(*this, VNUser(&nextState));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void GateVisitor::decomposeClkVectors() {
|
||||||
|
UINFO(9,"Starting clock decomposition"<<endl);
|
||||||
|
AstNode::user2ClearTree();
|
||||||
|
GateClkDecompGraphVisitor decomposer(&m_graph);
|
||||||
|
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
|
||||||
|
if (GateVarVertex* vertp = dynamic_cast<GateVarVertex*>(itp)) {
|
||||||
|
AstVarScope* vsp = vertp->varScp();
|
||||||
|
if (vsp->varp()->attrClocker() == AstVarAttrClocker::CLOCKER_YES) {
|
||||||
|
if (vsp->varp()->width() > 1) {
|
||||||
|
UINFO(9,"Clocker > 1 bit, not decomposing: "<<vsp<<endl);
|
||||||
|
} else {
|
||||||
|
UINFO(9,"CLK DECOMP - "<<vertp<<" : "<<vsp<<endl);
|
||||||
|
decomposer.clkDecomp(vertp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// Convert VARSCOPE(ASSIGN(default, VARREF)) to just VARSCOPE(default)
|
// Convert VARSCOPE(ASSIGN(default, VARREF)) to just VARSCOPE(default)
|
||||||
|
|||||||
+1
-1
@@ -529,7 +529,7 @@ double V3Graph::orderDFSIterate(V3GraphVertex* vertexp) {
|
|||||||
// Compute fanouts of each node
|
// Compute fanouts of each node
|
||||||
// If forward edge, don't double count that fanout
|
// If forward edge, don't double count that fanout
|
||||||
if (vertexp->user() == 2) return vertexp->fanout(); // Already processed it
|
if (vertexp->user() == 2) return vertexp->fanout(); // Already processed it
|
||||||
if (vertexp->user() == 1) v3fatalSrc("Loop found, backward edges should be dead\n");
|
if (vertexp->user() == 1) v3fatalSrc("Loop found, backward edges should be dead");
|
||||||
vertexp->user(1);
|
vertexp->user(1);
|
||||||
double fanout = 0;
|
double fanout = 0;
|
||||||
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
|
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
|
||||||
|
|||||||
+2
-2
@@ -44,7 +44,7 @@ DfaVertex* DfaGraph::findStart() {
|
|||||||
startp = vvertexp;
|
startp = vvertexp;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
v3fatalSrc("Non DfaVertex in DfaGraph\n");
|
v3fatalSrc("Non DfaVertex in DfaGraph");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!startp) v3fatalSrc("No start point in NFA graph");
|
if (!startp) v3fatalSrc("No start point in NFA graph");
|
||||||
@@ -520,7 +520,7 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!acceptp) v3fatalSrc("No accepting vertex in DFA\n");
|
if (!acceptp) v3fatalSrc("No accepting vertex in DFA");
|
||||||
|
|
||||||
// Remap edges
|
// Remap edges
|
||||||
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
|
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
|
||||||
|
|||||||
+3
-3
@@ -277,7 +277,7 @@ private:
|
|||||||
AstVarRef* exprvarrefp = nodep->user2p()->castVarRef();
|
AstVarRef* exprvarrefp = nodep->user2p()->castVarRef();
|
||||||
UINFO(8,"connectto: "<<nodep->user2p()<<endl);
|
UINFO(8,"connectto: "<<nodep->user2p()<<endl);
|
||||||
if (!exprconstp && !exprvarrefp) {
|
if (!exprconstp && !exprvarrefp) {
|
||||||
nodep->v3fatalSrc("Unknown interconnect type; pinReconnectSimple should have cleared up\n");
|
nodep->v3fatalSrc("Unknown interconnect type; pinReconnectSimple should have cleared up");
|
||||||
}
|
}
|
||||||
if (exprconstp) {
|
if (exprconstp) {
|
||||||
m_modp->addStmtp(new AstAssignW(nodep->fileline(),
|
m_modp->addStmtp(new AstAssignW(nodep->fileline(),
|
||||||
@@ -362,7 +362,7 @@ private:
|
|||||||
nodep->varp( exprvarrefp->varp() );
|
nodep->varp( exprvarrefp->varp() );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
nodep->v3fatalSrc("Null connection?\n");
|
nodep->v3fatalSrc("Null connection?");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nodep->name(nodep->varp()->name());
|
nodep->name(nodep->varp()->name());
|
||||||
@@ -514,7 +514,7 @@ private:
|
|||||||
|
|
||||||
AstNode* connectRefp = pinp->exprp();
|
AstNode* connectRefp = pinp->exprp();
|
||||||
if (!connectRefp->castConst() && !connectRefp->castVarRef()) {
|
if (!connectRefp->castConst() && !connectRefp->castVarRef()) {
|
||||||
pinp->v3fatalSrc("Unknown interconnect type; pinReconnectSimple should have cleared up\n");
|
pinp->v3fatalSrc("Unknown interconnect type; pinReconnectSimple should have cleared up");
|
||||||
}
|
}
|
||||||
if (pinNewVarp->isOutOnly() && connectRefp->castConst()) {
|
if (pinNewVarp->isOutOnly() && connectRefp->castConst()) {
|
||||||
pinp->v3error("Output port is connected to a constant pin, electrical short");
|
pinp->v3error("Output port is connected to a constant pin, electrical short");
|
||||||
|
|||||||
+109
-51
@@ -90,7 +90,7 @@ private:
|
|||||||
// Make a ASSIGNW (expr, pin)
|
// Make a ASSIGNW (expr, pin)
|
||||||
AstNode* exprp = nodep->exprp()->cloneTree(false);
|
AstNode* exprp = nodep->exprp()->cloneTree(false);
|
||||||
if (exprp->width() != nodep->modVarp()->width())
|
if (exprp->width() != nodep->modVarp()->width())
|
||||||
nodep->v3fatalSrc("Width mismatch, should have been handled in pinReconnectSimple\n");
|
nodep->v3fatalSrc("Width mismatch, should have been handled in pinReconnectSimple");
|
||||||
if (nodep->modVarp()->isInout()) {
|
if (nodep->modVarp()->isInout()) {
|
||||||
nodep->v3fatalSrc("Unsupported: Verilator is a 2-state simulator");
|
nodep->v3fatalSrc("Unsupported: Verilator is a 2-state simulator");
|
||||||
} else if (nodep->modVarp()->isOutput()) {
|
} else if (nodep->modVarp()->isOutput()) {
|
||||||
@@ -154,14 +154,10 @@ public:
|
|||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|
||||||
class InstDeVisitor : public AstNVisitor {
|
class InstDeModVarVisitor : public AstNVisitor {
|
||||||
// Find all cells with arrays, and convert to non-arrayed
|
// Expand all module variables, and save names for later reference
|
||||||
private:
|
private:
|
||||||
// STATE
|
// STATE
|
||||||
AstRange* m_cellRangep; // Range for arrayed instantiations, NULL for normal instantiations
|
|
||||||
int m_instNum; // Current instantiation number
|
|
||||||
int m_instLsb; // Current instantiation number
|
|
||||||
|
|
||||||
typedef map<string,AstVar*> VarNameMap;
|
typedef map<string,AstVar*> VarNameMap;
|
||||||
VarNameMap m_modVarNameMap; // Per module, name of cloned variables
|
VarNameMap m_modVarNameMap; // Per module, name of cloned variables
|
||||||
|
|
||||||
@@ -172,15 +168,109 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNodeModule* nodep) {
|
virtual void visit(AstVar* nodep) {
|
||||||
|
if (nodep->dtypep()->castIfaceRefDType()) {
|
||||||
|
UINFO(8," dm-1-VAR "<<nodep<<endl);
|
||||||
|
insert(nodep);
|
||||||
|
}
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
// Save some time
|
||||||
|
virtual void visit(AstNodeMath*) {}
|
||||||
|
// Default: Just iterate
|
||||||
|
virtual void visit(AstNode* nodep) {
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
// METHODS
|
||||||
|
void insert(AstVar* nodep) {
|
||||||
|
UINFO(8," dmINSERT "<<nodep<<endl);
|
||||||
|
m_modVarNameMap.insert(make_pair(nodep->name(), nodep));
|
||||||
|
}
|
||||||
|
AstVar* find(const string& name) {
|
||||||
|
VarNameMap::iterator it = m_modVarNameMap.find(name);
|
||||||
|
if (it != m_modVarNameMap.end()) {
|
||||||
|
return it->second;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void dump() {
|
||||||
|
for (VarNameMap::iterator it=m_modVarNameMap.begin(); it!=m_modVarNameMap.end(); ++it) {
|
||||||
|
cout<<"-namemap: "<<it->first<<" -> "<<it->second<<endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
// CONSTUCTORS
|
||||||
|
explicit InstDeModVarVisitor() {}
|
||||||
|
void accept(AstNodeModule* nodep) {
|
||||||
|
UINFO(8," dmMODULE "<<nodep<<endl);
|
||||||
m_modVarNameMap.clear();
|
m_modVarNameMap.clear();
|
||||||
|
nodep->accept(*this);
|
||||||
|
}
|
||||||
|
virtual ~InstDeModVarVisitor() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
|
||||||
|
class InstDeVisitor : public AstNVisitor {
|
||||||
|
// Find all cells with arrays, and convert to non-arrayed
|
||||||
|
private:
|
||||||
|
// STATE
|
||||||
|
AstRange* m_cellRangep; // Range for arrayed instantiations, NULL for normal instantiations
|
||||||
|
int m_instNum; // Current instantiation number
|
||||||
|
int m_instLsb; // Current instantiation number
|
||||||
|
InstDeModVarVisitor m_deModVars; // State of variables for current cell module
|
||||||
|
|
||||||
|
typedef map<string,AstVar*> VarNameMap;
|
||||||
|
|
||||||
|
static int debug() {
|
||||||
|
static int level = -1;
|
||||||
|
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
// VISITORS
|
||||||
|
virtual void visit(AstVar* nodep) {
|
||||||
|
if (nodep->dtypep()->castUnpackArrayDType()
|
||||||
|
&& nodep->dtypep()->castUnpackArrayDType()->subDTypep()->castIfaceRefDType()) {
|
||||||
|
UINFO(8," dv-vec-VAR "<<nodep<<endl);
|
||||||
|
AstUnpackArrayDType* arrdtype = nodep->dtypep()->castUnpackArrayDType();
|
||||||
|
AstNode* prevp = NULL;
|
||||||
|
for (int i = arrdtype->lsb(); i <= arrdtype->msb(); ++i) {
|
||||||
|
string varNewName = nodep->name() + "__BRA__" + cvtToStr(i) + "__KET__";
|
||||||
|
UINFO(8,"VAR name insert "<<varNewName<<" "<<nodep<<endl);
|
||||||
|
if (!m_deModVars.find(varNewName)) {
|
||||||
|
AstIfaceRefDType* ifaceRefp = arrdtype->subDTypep()->castIfaceRefDType()->cloneTree(false);
|
||||||
|
arrdtype->addNextHere(ifaceRefp);
|
||||||
|
ifaceRefp->cellp(NULL);
|
||||||
|
|
||||||
|
AstVar* varNewp = nodep->cloneTree(false);
|
||||||
|
varNewp->name(varNewName);
|
||||||
|
varNewp->origName(varNewp->origName() + "__BRA__" + cvtToStr(i) + "__KET__");
|
||||||
|
varNewp->dtypep(ifaceRefp);
|
||||||
|
m_deModVars.insert(varNewp);
|
||||||
|
if (!prevp) {
|
||||||
|
prevp = varNewp;
|
||||||
|
} else {
|
||||||
|
prevp->addNextHere(varNewp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (prevp) nodep->addNextHere(prevp);
|
||||||
|
if (prevp && debug()==9) { prevp->dumpTree(cout, "newintf: "); cout << endl; }
|
||||||
|
}
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstCell* nodep) {
|
virtual void visit(AstCell* nodep) {
|
||||||
|
UINFO(4," CELL "<<nodep<<endl);
|
||||||
|
// Find submodule vars
|
||||||
|
if (!nodep->modp()) nodep->v3fatalSrc("Unlinked");
|
||||||
|
m_deModVars.accept(nodep->modp());
|
||||||
|
//
|
||||||
if (nodep->rangep()) {
|
if (nodep->rangep()) {
|
||||||
m_cellRangep = nodep->rangep();
|
m_cellRangep = nodep->rangep();
|
||||||
UINFO(4," CELL "<<nodep<<endl);
|
|
||||||
|
|
||||||
AstVar* ifaceVarp = nodep->nextp()->castVar();
|
AstVar* ifaceVarp = nodep->nextp()->castVar();
|
||||||
bool isIface = ifaceVarp
|
bool isIface = ifaceVarp
|
||||||
@@ -199,9 +289,10 @@ private:
|
|||||||
// The spec says we add [x], but that won't work in C...
|
// The spec says we add [x], but that won't work in C...
|
||||||
newp->name(newp->name()+"__BRA__"+cvtToStr(m_instNum)+"__KET__");
|
newp->name(newp->name()+"__BRA__"+cvtToStr(m_instNum)+"__KET__");
|
||||||
newp->origName(newp->origName()+"__BRA__"+cvtToStr(m_instNum)+"__KET__");
|
newp->origName(newp->origName()+"__BRA__"+cvtToStr(m_instNum)+"__KET__");
|
||||||
|
UINFO(8," CELL loop "<<newp<<endl);
|
||||||
|
|
||||||
// If this AstCell is actually an interface instantiation, let's ensure we also clone
|
// If this AstCell is actually an interface instantiation, also clone the IfaceRef
|
||||||
// the IfaceRef.
|
// within the same parent module as the cell
|
||||||
if (isIface) {
|
if (isIface) {
|
||||||
AstUnpackArrayDType* arrdtype = ifaceVarp->dtypep()->castUnpackArrayDType();
|
AstUnpackArrayDType* arrdtype = ifaceVarp->dtypep()->castUnpackArrayDType();
|
||||||
AstIfaceRefDType* origIfaceRefp = arrdtype->subDTypep()->castIfaceRefDType();
|
AstIfaceRefDType* origIfaceRefp = arrdtype->subDTypep()->castIfaceRefDType();
|
||||||
@@ -229,42 +320,11 @@ private:
|
|||||||
}
|
}
|
||||||
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
|
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
|
||||||
} else {
|
} else {
|
||||||
|
m_cellRangep = NULL;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstVar* nodep) {
|
|
||||||
bool isIface = nodep->dtypep()->castUnpackArrayDType()
|
|
||||||
&& nodep->dtypep()->castUnpackArrayDType()->subDTypep()->castIfaceRefDType();
|
|
||||||
if (isIface) {
|
|
||||||
AstUnpackArrayDType* arrdtype = nodep->dtypep()->castUnpackArrayDType();
|
|
||||||
AstNode* prev = NULL;
|
|
||||||
for (int i = arrdtype->lsb(); i <= arrdtype->msb(); ++i) {
|
|
||||||
AstIfaceRefDType* ifaceRefp = arrdtype->subDTypep()->castIfaceRefDType()->cloneTree(false);
|
|
||||||
arrdtype->addNextHere(ifaceRefp);
|
|
||||||
ifaceRefp->cellp(NULL);
|
|
||||||
|
|
||||||
string varNewName = nodep->name() + "__BRA__" + cvtToStr(i) + "__KET__";
|
|
||||||
VarNameMap::iterator it = m_modVarNameMap.find(varNewName);
|
|
||||||
if (it == m_modVarNameMap.end()) {
|
|
||||||
AstVar* varNewp = nodep->cloneTree(false);
|
|
||||||
m_modVarNameMap.insert(make_pair(varNewName, varNewp));
|
|
||||||
varNewp->name(varNewName);
|
|
||||||
varNewp->origName(varNewp->origName() + "__BRA__" + cvtToStr(i) + "__KET__");
|
|
||||||
varNewp->dtypep(ifaceRefp);
|
|
||||||
if (!prev) {
|
|
||||||
prev = varNewp;
|
|
||||||
} else {
|
|
||||||
prev->addNextHere(varNewp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (prev) nodep->addNextHere(prev);
|
|
||||||
if (prev && debug()==9) { prev->dumpTree(cout, "newintf: "); cout << endl; }
|
|
||||||
}
|
|
||||||
nodep->iterateChildren(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void visit(AstPin* nodep) {
|
virtual void visit(AstPin* nodep) {
|
||||||
// Any non-direct pins need reconnection with a part-select
|
// Any non-direct pins need reconnection with a part-select
|
||||||
if (!nodep->exprp()) return; // No-connect
|
if (!nodep->exprp()) return; // No-connect
|
||||||
@@ -334,30 +394,28 @@ private:
|
|||||||
// Clone pin varp:
|
// Clone pin varp:
|
||||||
for (int i = pinArrp->lsb(); i <= pinArrp->msb(); ++i) {
|
for (int i = pinArrp->lsb(); i <= pinArrp->msb(); ++i) {
|
||||||
string varNewName = pinVarp->name() + "__BRA__" + cvtToStr(i) + "__KET__";
|
string varNewName = pinVarp->name() + "__BRA__" + cvtToStr(i) + "__KET__";
|
||||||
VarNameMap::iterator it = m_modVarNameMap.find(varNewName);
|
|
||||||
AstVar* varNewp = NULL;
|
AstVar* varNewp = NULL;
|
||||||
|
|
||||||
// Only clone the var once for each module
|
// Only clone the var once for all usages of a given child module
|
||||||
if (!pinVarp->backp()) {
|
if (!pinVarp->backp()) {
|
||||||
if (it != m_modVarNameMap.end()) {
|
varNewp = m_deModVars.find(varNewName);
|
||||||
varNewp = it->second;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
AstIfaceRefDType* ifaceRefp = pinArrp->subDTypep()->castIfaceRefDType();
|
AstIfaceRefDType* ifaceRefp = pinArrp->subDTypep()->castIfaceRefDType();
|
||||||
ifaceRefp->cellp(NULL);
|
ifaceRefp->cellp(NULL);
|
||||||
varNewp = pinVarp->cloneTree(false);
|
varNewp = pinVarp->cloneTree(false);
|
||||||
m_modVarNameMap.insert(make_pair(varNewName, varNewp));
|
|
||||||
varNewp->name(varNewName);
|
varNewp->name(varNewName);
|
||||||
varNewp->origName(varNewp->origName() + "__BRA__" + cvtToStr(i) + "__KET__");
|
varNewp->origName(varNewp->origName() + "__BRA__" + cvtToStr(i) + "__KET__");
|
||||||
varNewp->dtypep(ifaceRefp);
|
varNewp->dtypep(ifaceRefp);
|
||||||
|
m_deModVars.insert(varNewp);
|
||||||
if (!prevp) {
|
if (!prevp) {
|
||||||
prevp = varNewp;
|
prevp = varNewp;
|
||||||
} else {
|
} else {
|
||||||
prevp->addNextHere(varNewp);
|
prevp->addNextHere(varNewp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (varNewp == NULL) {
|
if (!varNewp) {
|
||||||
nodep->v3fatalSrc("Module dearray failed\n");
|
if (debug()>=9) m_deModVars.dump();
|
||||||
|
nodep->v3fatalSrc("Module dearray failed for "<<AstNode::prettyName(varNewName));
|
||||||
}
|
}
|
||||||
|
|
||||||
// But clone the pin for each module instance
|
// But clone the pin for each module instance
|
||||||
|
|||||||
+10
-6
@@ -445,6 +445,10 @@ public:
|
|||||||
<<") <- se"<<srcp<<" "<<srcp->nodep()<<endl);
|
<<") <- se"<<srcp<<" "<<srcp->nodep()<<endl);
|
||||||
// srcp should be an interface reference pointing to the interface we want to import
|
// srcp should be an interface reference pointing to the interface we want to import
|
||||||
lhsp->importFromIface(symsp(), srcp);
|
lhsp->importFromIface(symsp(), srcp);
|
||||||
|
// Allow access to objects not permissible to be listed in a modport
|
||||||
|
if (srcp->nodep()->castModport()) {
|
||||||
|
lhsp->importFromIface(symsp(), srcp->parentp(), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//m_scopeAliasMap[samn].clear(); // Done with it, but put into debug file
|
//m_scopeAliasMap[samn].clear(); // Done with it, but put into debug file
|
||||||
}
|
}
|
||||||
@@ -839,7 +843,7 @@ class LinkDotFindVisitor : public AstNVisitor {
|
|||||||
virtual void visit(AstNodeFTask* nodep) {
|
virtual void visit(AstNodeFTask* nodep) {
|
||||||
// NodeTask: Remember its name for later resolution
|
// NodeTask: Remember its name for later resolution
|
||||||
UINFO(5," "<<nodep<<endl);
|
UINFO(5," "<<nodep<<endl);
|
||||||
if (!m_curSymp || !m_modSymp) nodep->v3fatalSrc("Function/Task not under module??\n");
|
if (!m_curSymp || !m_modSymp) nodep->v3fatalSrc("Function/Task not under module?");
|
||||||
// Remember the existing symbol table scope
|
// Remember the existing symbol table scope
|
||||||
VSymEnt* oldCurSymp = m_curSymp;
|
VSymEnt* oldCurSymp = m_curSymp;
|
||||||
{
|
{
|
||||||
@@ -873,7 +877,7 @@ class LinkDotFindVisitor : public AstNVisitor {
|
|||||||
}
|
}
|
||||||
virtual void visit(AstVar* nodep) {
|
virtual void visit(AstVar* nodep) {
|
||||||
// Var: Remember its name for later resolution
|
// Var: Remember its name for later resolution
|
||||||
if (!m_curSymp || !m_modSymp) nodep->v3fatalSrc("Var not under module??\n");
|
if (!m_curSymp || !m_modSymp) nodep->v3fatalSrc("Var not under module?");
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (!m_statep->forScopeCreation()) {
|
if (!m_statep->forScopeCreation()) {
|
||||||
// Find under either a task or the module's vars
|
// Find under either a task or the module's vars
|
||||||
@@ -957,12 +961,12 @@ class LinkDotFindVisitor : public AstNVisitor {
|
|||||||
}
|
}
|
||||||
virtual void visit(AstTypedef* nodep) {
|
virtual void visit(AstTypedef* nodep) {
|
||||||
// Remember its name for later resolution
|
// Remember its name for later resolution
|
||||||
if (!m_curSymp) nodep->v3fatalSrc("Typedef not under module??\n");
|
if (!m_curSymp) nodep->v3fatalSrc("Typedef not under module?");
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep);
|
m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep);
|
||||||
}
|
}
|
||||||
virtual void visit(AstParamTypeDType* nodep) {
|
virtual void visit(AstParamTypeDType* nodep) {
|
||||||
if (!m_curSymp) nodep->v3fatalSrc("Parameter type not under module??\n");
|
if (!m_curSymp) nodep->v3fatalSrc("Parameter type not under module?");
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep);
|
m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep);
|
||||||
}
|
}
|
||||||
@@ -1593,7 +1597,7 @@ private:
|
|||||||
checkNoDot(nodep);
|
checkNoDot(nodep);
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (!nodep->modVarp()) {
|
if (!nodep->modVarp()) {
|
||||||
if (!m_pinSymp) nodep->v3fatalSrc("Pin not under cell?\n");
|
if (!m_pinSymp) nodep->v3fatalSrc("Pin not under cell?");
|
||||||
VSymEnt* foundp = m_pinSymp->findIdFlat(nodep->name());
|
VSymEnt* foundp = m_pinSymp->findIdFlat(nodep->name());
|
||||||
const char* whatp = nodep->param() ? "parameter pin" : "pin";
|
const char* whatp = nodep->param() ? "parameter pin" : "pin";
|
||||||
if (!foundp) {
|
if (!foundp) {
|
||||||
@@ -1861,7 +1865,7 @@ private:
|
|||||||
}
|
}
|
||||||
//
|
//
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
//Cells/interfaces can't be implicit
|
// Cells/interfaces can't be implicit
|
||||||
bool isCell = foundp ? foundp->nodep()->castCell() != NULL : false;
|
bool isCell = foundp ? foundp->nodep()->castCell() != NULL : false;
|
||||||
bool checkImplicit = (!m_ds.m_dotp && m_ds.m_dotText=="" && !isCell);
|
bool checkImplicit = (!m_ds.m_dotp && m_ds.m_dotText=="" && !isCell);
|
||||||
bool err = !(checkImplicit && m_statep->implicitOk(m_modp, nodep->name()));
|
bool err = !(checkImplicit && m_statep->implicitOk(m_modp, nodep->name()));
|
||||||
|
|||||||
@@ -174,8 +174,10 @@ private:
|
|||||||
virtual void visit(AstValuePlusArgs* nodep) {
|
virtual void visit(AstValuePlusArgs* nodep) {
|
||||||
bool last_setRefLvalue = m_setRefLvalue;
|
bool last_setRefLvalue = m_setRefLvalue;
|
||||||
{
|
{
|
||||||
|
m_setRefLvalue = false;
|
||||||
|
nodep->searchp()->iterateAndNext(*this);
|
||||||
m_setRefLvalue = true;
|
m_setRefLvalue = true;
|
||||||
nodep->exprsp()->iterateAndNext(*this);
|
nodep->outp()->iterateAndNext(*this);
|
||||||
}
|
}
|
||||||
m_setRefLvalue = last_setRefLvalue;
|
m_setRefLvalue = last_setRefLvalue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -236,12 +236,12 @@ private:
|
|||||||
|
|
||||||
virtual void visit(AstPragma* nodep) {
|
virtual void visit(AstPragma* nodep) {
|
||||||
if (nodep->pragType() == AstPragmaType::PUBLIC_MODULE) {
|
if (nodep->pragType() == AstPragmaType::PUBLIC_MODULE) {
|
||||||
if (!m_modp) nodep->v3fatalSrc("PUBLIC_MODULE not under a module\n");
|
if (!m_modp) nodep->v3fatalSrc("PUBLIC_MODULE not under a module");
|
||||||
m_modp->modPublic(true);
|
m_modp->modPublic(true);
|
||||||
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
|
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
else if (nodep->pragType() == AstPragmaType::PUBLIC_TASK) {
|
else if (nodep->pragType() == AstPragmaType::PUBLIC_TASK) {
|
||||||
if (!m_ftaskp) nodep->v3fatalSrc("PUBLIC_TASK not under a task\n");
|
if (!m_ftaskp) nodep->v3fatalSrc("PUBLIC_TASK not under a task");
|
||||||
m_ftaskp->taskPublic(true);
|
m_ftaskp->taskPublic(true);
|
||||||
m_modp->modPublic(true); // Need to get to the task...
|
m_modp->modPublic(true); // Need to get to the task...
|
||||||
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
|
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
|
||||||
|
|||||||
+12
-6
@@ -48,7 +48,7 @@ V3Number::V3Number(VerilogStringLiteral, FileLine* fileline, const string& str)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
opCleanThis();
|
opCleanThis(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
V3Number::V3Number (FileLine* fileline, const char* sourcep) {
|
V3Number::V3Number (FileLine* fileline, const char* sourcep) {
|
||||||
@@ -254,7 +254,7 @@ V3Number::V3Number (FileLine* fileline, const char* sourcep) {
|
|||||||
setBit(obit, bitIs(obit-1));
|
setBit(obit, bitIs(obit-1));
|
||||||
obit++;
|
obit++;
|
||||||
}
|
}
|
||||||
opCleanThis();
|
opCleanThis(true);
|
||||||
|
|
||||||
//printf("Dump \"%s\" CP \"%s\" B '%c' %d W %d\n", sourcep, value_startp, base, width(), m_value[0]);
|
//printf("Dump \"%s\" CP \"%s\" B '%c' %d W %d\n", sourcep, value_startp, base, width(), m_value[0]);
|
||||||
}
|
}
|
||||||
@@ -1587,10 +1587,16 @@ V3Number& V3Number::opClean (const V3Number& lhs, uint32_t bits) {
|
|||||||
return opSel(lhs, bits-1, 0);
|
return opSel(lhs, bits-1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void V3Number::opCleanThis() {
|
void V3Number::opCleanThis(bool warnOnTruncation) {
|
||||||
// Clean in place number
|
// Clean MSB of number
|
||||||
m_value[words()-1] &= hiWordMask();
|
uint32_t newValueMsb = m_value[words()-1] & hiWordMask();
|
||||||
m_valueX[words()-1] &= hiWordMask();
|
uint32_t newValueXMsb = m_valueX[words()-1] & hiWordMask();
|
||||||
|
if (warnOnTruncation && (newValueMsb != m_value[words()-1] || newValueXMsb != m_valueX[words()-1])) {
|
||||||
|
// Displaying in decimal avoids hiWordMask truncation
|
||||||
|
m_fileline->v3warn(WIDTH,"Value too large for "<<width()<<" bit number: "<<displayed(m_fileline, "%d"));
|
||||||
|
}
|
||||||
|
m_value[words()-1] = newValueMsb;
|
||||||
|
m_valueX[words()-1] = newValueXMsb;
|
||||||
}
|
}
|
||||||
|
|
||||||
V3Number& V3Number::opSel (const V3Number& lhs, const V3Number& msb, const V3Number& lsb) {
|
V3Number& V3Number::opSel (const V3Number& lhs, const V3Number& msb, const V3Number& lsb) {
|
||||||
|
|||||||
+1
-1
@@ -45,7 +45,7 @@ class V3Number {
|
|||||||
// METHODS
|
// METHODS
|
||||||
V3Number& setSingleBits(char value);
|
V3Number& setSingleBits(char value);
|
||||||
V3Number& setString(const string& str) { m_isString=true; m_stringVal=str; return *this; }
|
V3Number& setString(const string& str) { m_isString=true; m_stringVal=str; return *this; }
|
||||||
void opCleanThis();
|
void opCleanThis(bool warnOnTruncation = false);
|
||||||
public:
|
public:
|
||||||
FileLine* fileline() const { return m_fileline; }
|
FileLine* fileline() const { return m_fileline; }
|
||||||
void fileline(FileLine* fl) { m_fileline=fl; }
|
void fileline(FileLine* fl) { m_fileline=fl; }
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ void test(string lhss, string op, string rhss, string exps) {
|
|||||||
V3Number ok (new FileLine("ck",__LINE__), 1);
|
V3Number ok (new FileLine("ck",__LINE__), 1);
|
||||||
ok.opCaseEq(expnum,gotnum);
|
ok.opCaseEq(expnum,gotnum);
|
||||||
if (ok.toUInt()!=1) {
|
if (ok.toUInt()!=1) {
|
||||||
v3fatalSrc("%Error:Test FAILED\n");
|
v3fatalSrc("%Error:Test FAILED");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -560,7 +560,7 @@ string V3Options::version() {
|
|||||||
|
|
||||||
void V3Options::throwSigsegv() {
|
void V3Options::throwSigsegv() {
|
||||||
// cppcheck-suppress nullPointer
|
// cppcheck-suppress nullPointer
|
||||||
char* zp=NULL; *zp=0;
|
char* zp=NULL; *zp=0; // Intentional core dump, ignore warnings here
|
||||||
}
|
}
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
@@ -607,7 +607,7 @@ bool V3Options::onoff(const char* sw, const char* arg, bool& flag) {
|
|||||||
// if sw=="-no-arg", then return true (found it), and flag=false
|
// if sw=="-no-arg", then return true (found it), and flag=false
|
||||||
// if sw=="-noarg", then return true (found it), and flag=false
|
// if sw=="-noarg", then return true (found it), and flag=false
|
||||||
// else return false
|
// else return false
|
||||||
if (arg[0]!='-') v3fatalSrc("OnOff switches must have leading dash.\n");
|
if (arg[0]!='-') v3fatalSrc("OnOff switches must have leading dash");
|
||||||
if (0==strcmp(sw,arg)) { flag=true; return true; }
|
if (0==strcmp(sw,arg)) { flag=true; return true; }
|
||||||
else if (0==strncmp(sw,"-no",3) && (0==strcmp(sw+3,arg+1))) { flag=false; return true; }
|
else if (0==strncmp(sw,"-no",3) && (0==strcmp(sw+3,arg+1))) { flag=false; return true; }
|
||||||
else if (0==strncmp(sw,"-no-",4) && (0==strcmp(sw+4,arg+1))) { flag=false; return true; }
|
else if (0==strncmp(sw,"-no-",4) && (0==strcmp(sw+4,arg+1))) { flag=false; return true; }
|
||||||
|
|||||||
+5
-5
@@ -194,7 +194,7 @@ public:
|
|||||||
// METHODS
|
// METHODS
|
||||||
OrderVarVertex* newVarUserVertex(V3Graph* graphp, AstScope* scopep,
|
OrderVarVertex* newVarUserVertex(V3Graph* graphp, AstScope* scopep,
|
||||||
AstVarScope* varscp, WhichVertex type, bool* createdp=NULL) {
|
AstVarScope* varscp, WhichVertex type, bool* createdp=NULL) {
|
||||||
if (type>=WV_MAX) varscp->v3fatalSrc("Bad Case\n");
|
if (type>=WV_MAX) varscp->v3fatalSrc("Bad case");
|
||||||
OrderVarVertex* vertexp = m_vertexp[type];
|
OrderVarVertex* vertexp = m_vertexp[type];
|
||||||
if (!vertexp) {
|
if (!vertexp) {
|
||||||
UINFO(6,"New vertex "<<varscp<<endl);
|
UINFO(6,"New vertex "<<varscp<<endl);
|
||||||
@@ -205,7 +205,7 @@ public:
|
|||||||
case WV_PORD: vertexp = new OrderVarPordVertex (graphp, scopep, varscp); break;
|
case WV_PORD: vertexp = new OrderVarPordVertex (graphp, scopep, varscp); break;
|
||||||
case WV_POST: vertexp = new OrderVarPostVertex (graphp, scopep, varscp); break;
|
case WV_POST: vertexp = new OrderVarPostVertex (graphp, scopep, varscp); break;
|
||||||
case WV_SETL: vertexp = new OrderVarSettleVertex(graphp, scopep, varscp); break;
|
case WV_SETL: vertexp = new OrderVarSettleVertex(graphp, scopep, varscp); break;
|
||||||
default: varscp->v3fatalSrc("Bad Case\n");
|
default: varscp->v3fatalSrc("Bad case");
|
||||||
}
|
}
|
||||||
m_vertexp[type] = vertexp;
|
m_vertexp[type] = vertexp;
|
||||||
} else {
|
} else {
|
||||||
@@ -806,15 +806,15 @@ private:
|
|||||||
virtual void visit(AstNodeVarRef* nodep) {
|
virtual void visit(AstNodeVarRef* nodep) {
|
||||||
if (m_scopep) {
|
if (m_scopep) {
|
||||||
AstVarScope* varscp = nodep->varScopep();
|
AstVarScope* varscp = nodep->varScopep();
|
||||||
if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n");
|
if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp");
|
||||||
if (m_inSenTree) {
|
if (m_inSenTree) {
|
||||||
// Add CLOCK dependency... This is a root of the tree we'll trace
|
// Add CLOCK dependency... This is a root of the tree we'll trace
|
||||||
if (nodep->lvalue()) nodep->v3fatalSrc("How can a sensitivity be setting a var?\n");
|
if (nodep->lvalue()) nodep->v3fatalSrc("How can a sensitivity be setting a var?");
|
||||||
OrderVarVertex* varVxp = newVarUserVertex(varscp, WV_STD);
|
OrderVarVertex* varVxp = newVarUserVertex(varscp, WV_STD);
|
||||||
varVxp->isClock(true);
|
varVxp->isClock(true);
|
||||||
new OrderEdge(&m_graph, varVxp, m_activeSenVxp, WEIGHT_MEDIUM);
|
new OrderEdge(&m_graph, varVxp, m_activeSenVxp, WEIGHT_MEDIUM);
|
||||||
} else {
|
} else {
|
||||||
if (!m_logicVxp) nodep->v3fatalSrc("Var ref not under a logic block\n");
|
if (!m_logicVxp) nodep->v3fatalSrc("Var ref not under a logic block");
|
||||||
// What new directions is this used
|
// What new directions is this used
|
||||||
// We don't want to add extra edges if the logic block has many usages of same var
|
// We don't want to add extra edges if the logic block has many usages of same var
|
||||||
bool gen = false;
|
bool gen = false;
|
||||||
|
|||||||
+61
-3
@@ -204,7 +204,7 @@ private:
|
|||||||
pinp->modPTypep(cloneiter->second->castParamTypeDType());
|
pinp->modPTypep(cloneiter->second->castParamTypeDType());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
pinp->v3fatalSrc("Not linked?\n");
|
pinp->v3fatalSrc("Not linked?");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -283,7 +283,59 @@ private:
|
|||||||
virtual void visit(AstVarRef* nodep) {
|
virtual void visit(AstVarRef* nodep) {
|
||||||
if (nodep->varp()) nodep->varp()->iterate(*this);
|
if (nodep->varp()) nodep->varp()->iterate(*this);
|
||||||
}
|
}
|
||||||
|
bool ifaceParamReplace(AstVarXRef* nodep, AstNode* candp) {
|
||||||
|
for (; candp; candp = candp->nextp()) {
|
||||||
|
if (nodep->name() == candp->name()) {
|
||||||
|
if (AstVar* varp = candp->castVar()) {
|
||||||
|
UINFO(9,"Found interface parameter: "<<varp<<endl);
|
||||||
|
nodep->varp(varp);
|
||||||
|
return true;
|
||||||
|
} else if (AstPin* pinp = candp->castPin()) {
|
||||||
|
UINFO(9,"Found interface parameter: "<<pinp<<endl);
|
||||||
|
if (!pinp->exprp()) pinp->v3fatalSrc("Interface parameter pin missing expression");
|
||||||
|
nodep->replaceWith(pinp->exprp()->cloneTree(false)); VL_DANGLING(nodep);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
virtual void visit(AstVarXRef* nodep) {
|
virtual void visit(AstVarXRef* nodep) {
|
||||||
|
// Check to see if the scope is just an interface because interfaces are special
|
||||||
|
string dotted = nodep->dotted();
|
||||||
|
if (!dotted.empty() && nodep->varp() && nodep->varp()->isParam()) {
|
||||||
|
AstNode* backp = nodep;
|
||||||
|
while ((backp = backp->backp())) {
|
||||||
|
if (backp->castNodeModule()) {
|
||||||
|
UINFO(9,"Hit module boundary, done looking for interface"<<endl);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (backp->castVar()
|
||||||
|
&& backp->castVar()->isIfaceRef()
|
||||||
|
&& backp->castVar()->childDTypep()
|
||||||
|
&& backp->castVar()->childDTypep()->castIfaceRefDType()) {
|
||||||
|
AstIfaceRefDType* ifacerefp = backp->castVar()->childDTypep()->castIfaceRefDType();
|
||||||
|
// Interfaces passed in on the port map have ifaces
|
||||||
|
if (AstIface* ifacep = ifacerefp->ifacep()) {
|
||||||
|
if (dotted == backp->name()) {
|
||||||
|
UINFO(9,"Iface matching scope: "<<ifacep<<endl);
|
||||||
|
if (ifaceParamReplace(nodep, ifacep->stmtsp())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Interfaces declared in this module have cells
|
||||||
|
else if (AstCell* cellp = ifacerefp->cellp()) {
|
||||||
|
if (dotted == cellp->name()) {
|
||||||
|
UINFO(9,"Iface matching scope: "<<cellp<<endl);
|
||||||
|
if (ifaceParamReplace(nodep, cellp->paramsp())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
nodep->varp(NULL); // Needs relink, as may remove pointed-to var
|
nodep->varp(NULL); // Needs relink, as may remove pointed-to var
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -493,6 +545,12 @@ void ParamVisitor::visitCell(AstCell* nodep) {
|
|||||||
if (AstVar* modvarp = pinp->modVarp()) {
|
if (AstVar* modvarp = pinp->modVarp()) {
|
||||||
if (!modvarp->isGParam()) {
|
if (!modvarp->isGParam()) {
|
||||||
pinp->v3error("Attempted parameter setting of non-parameter: Param "<<pinp->prettyName()<<" of "<<nodep->prettyName());
|
pinp->v3error("Attempted parameter setting of non-parameter: Param "<<pinp->prettyName()<<" of "<<nodep->prettyName());
|
||||||
|
} else if (pinp->exprp()->castInitArray()
|
||||||
|
&& modvarp->subDTypep()->castUnpackArrayDType()) {
|
||||||
|
// Array assigned to array
|
||||||
|
AstNode* exprp = pinp->exprp();
|
||||||
|
longname += "_" + paramSmallName(nodep->modp(),modvarp)+paramValueNumber(exprp);
|
||||||
|
any_overrides = true;
|
||||||
} else {
|
} else {
|
||||||
AstConst* exprp = pinp->exprp()->castConst();
|
AstConst* exprp = pinp->exprp()->castConst();
|
||||||
AstConst* origp = modvarp->valuep()->castConst();
|
AstConst* origp = modvarp->valuep()->castConst();
|
||||||
@@ -651,11 +709,11 @@ void ParamVisitor::visitCell(AstCell* nodep) {
|
|||||||
for (AstPin* pinp = nodep->paramsp(); pinp; pinp=pinp->nextp()->castPin()) {
|
for (AstPin* pinp = nodep->paramsp(); pinp; pinp=pinp->nextp()->castPin()) {
|
||||||
if (pinp->exprp()) {
|
if (pinp->exprp()) {
|
||||||
if (AstVar* modvarp = pinp->modVarp()) {
|
if (AstVar* modvarp = pinp->modVarp()) {
|
||||||
AstConst* constp = pinp->exprp()->castConst();
|
AstNode* newp = pinp->exprp(); // Const or InitArray
|
||||||
// Remove any existing parameter
|
// Remove any existing parameter
|
||||||
if (modvarp->valuep()) modvarp->valuep()->unlinkFrBack()->deleteTree();
|
if (modvarp->valuep()) modvarp->valuep()->unlinkFrBack()->deleteTree();
|
||||||
// Set this parameter to value requested by cell
|
// Set this parameter to value requested by cell
|
||||||
modvarp->valuep(constp->cloneTree(false));
|
modvarp->valuep(newp->cloneTree(false));
|
||||||
}
|
}
|
||||||
else if (AstParamTypeDType* modptp = pinp->modPTypep()) {
|
else if (AstParamTypeDType* modptp = pinp->modPTypep()) {
|
||||||
AstNodeDType* dtypep = pinp->exprp()->castNodeDType();
|
AstNodeDType* dtypep = pinp->exprp()->castNodeDType();
|
||||||
|
|||||||
@@ -44,12 +44,25 @@
|
|||||||
#include "V3Task.h"
|
#include "V3Task.h"
|
||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// Simulate class functions
|
// Simulate class functions
|
||||||
|
|
||||||
|
class SimulateStackNode {
|
||||||
|
public:
|
||||||
|
// MEMBERS
|
||||||
|
AstFuncRef* m_funcp;
|
||||||
|
V3TaskConnects* m_tconnects;
|
||||||
|
// CONSTRUCTORS
|
||||||
|
SimulateStackNode(AstFuncRef* funcp, V3TaskConnects* tconnects):
|
||||||
|
m_funcp(funcp),
|
||||||
|
m_tconnects(tconnects) {}
|
||||||
|
~SimulateStackNode() {}
|
||||||
|
};
|
||||||
|
|
||||||
class SimulateVisitor : public AstNVisitor {
|
class SimulateVisitor : public AstNVisitor {
|
||||||
// Simulate a node tree, returning value of variables
|
// Simulate a node tree, returning value of variables
|
||||||
// Two major operating modes:
|
// Two major operating modes:
|
||||||
@@ -90,6 +103,7 @@ private:
|
|||||||
// Simulating:
|
// Simulating:
|
||||||
deque<V3Number*> m_numFreeps; ///< List of all numbers free and not in use
|
deque<V3Number*> m_numFreeps; ///< List of all numbers free and not in use
|
||||||
deque<V3Number*> m_numAllps; ///< List of all numbers free and in use
|
deque<V3Number*> m_numAllps; ///< List of all numbers free and in use
|
||||||
|
deque<SimulateStackNode*> m_callStack; ///< Call stack for verbose error messages
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
// V3Numbers that represents strings are a bit special and the API for V3Number does not allow changing them.
|
// V3Numbers that represents strings are a bit special and the API for V3Number does not allow changing them.
|
||||||
@@ -103,6 +117,54 @@ private:
|
|||||||
return level;
|
return level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Potentially very slow, intended for debugging
|
||||||
|
string prettyNumber(V3Number* nump, AstNodeDType* dtypep) {
|
||||||
|
if (AstRefDType* refdtypep = dtypep->castRefDType()) {
|
||||||
|
dtypep = refdtypep->skipRefp();
|
||||||
|
}
|
||||||
|
if (AstStructDType* stp = dtypep->castStructDType()) {
|
||||||
|
if (stp->packed()) {
|
||||||
|
ostringstream out;
|
||||||
|
out<<"'{";
|
||||||
|
for (AstMemberDType* itemp = stp->membersp(); itemp; itemp=itemp->nextp()->castMemberDType()) {
|
||||||
|
int width = itemp->width();
|
||||||
|
int lsb = itemp->lsb();
|
||||||
|
int msb = lsb + width - 1;
|
||||||
|
V3Number fieldNum = V3Number(nump->fileline(), width);
|
||||||
|
fieldNum.opSel(*nump, msb, lsb);
|
||||||
|
out<<itemp->name()<<": ";
|
||||||
|
if (AstNodeDType * childTypep = itemp->subDTypep()) {
|
||||||
|
out<<prettyNumber(&fieldNum, childTypep);
|
||||||
|
} else {
|
||||||
|
out<<fieldNum;
|
||||||
|
}
|
||||||
|
if (itemp->nextp()) out<<", ";
|
||||||
|
}
|
||||||
|
out<<"}";
|
||||||
|
return out.str();
|
||||||
|
}
|
||||||
|
} else if (AstPackArrayDType * arrayp = dtypep->castPackArrayDType()) {
|
||||||
|
if (AstNodeDType * childTypep = arrayp->subDTypep()) {
|
||||||
|
ostringstream out;
|
||||||
|
out<<"[";
|
||||||
|
int arrayElements = arrayp->elementsConst();
|
||||||
|
for (int element = 0; element < arrayElements; ++element) {
|
||||||
|
int width = childTypep->width();
|
||||||
|
int lsb = width * element;
|
||||||
|
int msb = lsb + width - 1;
|
||||||
|
V3Number fieldNum = V3Number(nump->fileline(), width);
|
||||||
|
fieldNum.opSel(*nump, msb, lsb);
|
||||||
|
int arrayElem = arrayp->lsb() + element;
|
||||||
|
out<<arrayElem<<" = "<<prettyNumber(&fieldNum, childTypep);
|
||||||
|
if (element < arrayElements - 1) out<<", ";
|
||||||
|
}
|
||||||
|
out<<"]";
|
||||||
|
return out.str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nump->ascii();
|
||||||
|
}
|
||||||
|
|
||||||
// Checking METHODS
|
// Checking METHODS
|
||||||
public:
|
public:
|
||||||
/// Call other-this function on all new *non-constant* var references
|
/// Call other-this function on all new *non-constant* var references
|
||||||
@@ -119,6 +181,19 @@ public:
|
|||||||
cout<<endl;
|
cout<<endl;
|
||||||
}
|
}
|
||||||
m_whyNotOptimizable = why;
|
m_whyNotOptimizable = why;
|
||||||
|
ostringstream stack;
|
||||||
|
for (deque<SimulateStackNode*>::iterator it=m_callStack.begin(); it !=m_callStack.end(); ++it) {
|
||||||
|
AstFuncRef* funcp = (*it)->m_funcp;
|
||||||
|
stack<<"\nCalled from:\n"<<funcp->fileline()<<" "<<funcp->prettyName()<<"() with parameters:";
|
||||||
|
V3TaskConnects* tconnects = (*it)->m_tconnects;
|
||||||
|
for (V3TaskConnects::iterator conIt = tconnects->begin(); conIt != tconnects->end(); ++conIt) {
|
||||||
|
AstVar* portp = conIt->first;
|
||||||
|
AstNode* pinp = conIt->second->exprp();
|
||||||
|
AstNodeDType* dtypep = pinp->dtypep();
|
||||||
|
stack<<"\n "<<portp->prettyName()<<" = "<<prettyNumber(fetchNumber(pinp), dtypep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_whyNotOptimizable += stack.str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inline bool optimizable() const { return m_whyNotNodep==NULL; }
|
inline bool optimizable() const { return m_whyNotNodep==NULL; }
|
||||||
@@ -718,8 +793,11 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
SimulateStackNode stackNode(nodep, &tconnects);
|
||||||
|
m_callStack.push_front(&stackNode);
|
||||||
// Evaluate the function
|
// Evaluate the function
|
||||||
funcp->accept(*this);
|
funcp->accept(*this);
|
||||||
|
m_callStack.pop_front();
|
||||||
if (!m_checkOnly && optimizable()) {
|
if (!m_checkOnly && optimizable()) {
|
||||||
// Grab return value from output variable (if it's a function)
|
// Grab return value from output variable (if it's a function)
|
||||||
if (!funcp->fvarp()) nodep->v3fatalSrc("Function reference points at non-function");
|
if (!funcp->fvarp()) nodep->v3fatalSrc("Function reference points at non-function");
|
||||||
|
|||||||
+4
-4
@@ -272,12 +272,12 @@ private:
|
|||||||
//UINFO(9," push "<<nodep<<endl);
|
//UINFO(9," push "<<nodep<<endl);
|
||||||
SplitLogicVertex* vertexp = new SplitLogicVertex(&m_graph, nodep);
|
SplitLogicVertex* vertexp = new SplitLogicVertex(&m_graph, nodep);
|
||||||
m_stmtStackps.push_back(vertexp);
|
m_stmtStackps.push_back(vertexp);
|
||||||
if (nodep->user3p()) nodep->v3fatalSrc("user3p should not be used; cleared in processBlock\n");
|
if (nodep->user3p()) nodep->v3fatalSrc("user3p should not be used; cleared in processBlock");
|
||||||
nodep->user3p(vertexp);
|
nodep->user3p(vertexp);
|
||||||
}
|
}
|
||||||
void scoreboardPopStmt() {
|
void scoreboardPopStmt() {
|
||||||
//UINFO(9," pop"<<endl);
|
//UINFO(9," pop"<<endl);
|
||||||
if (m_stmtStackps.empty()) v3fatalSrc("Stack underflow\n");
|
if (m_stmtStackps.empty()) v3fatalSrc("Stack underflow");
|
||||||
m_stmtStackps.pop_back();
|
m_stmtStackps.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,8 +346,8 @@ private:
|
|||||||
SplitLogicVertex* vvertexp = (SplitLogicVertex*)nextp->user3p();
|
SplitLogicVertex* vvertexp = (SplitLogicVertex*)nextp->user3p();
|
||||||
vvertexp->splitColor(vvertexp->color());
|
vvertexp->splitColor(vvertexp->color());
|
||||||
uint32_t color = vvertexp->splitColor();
|
uint32_t color = vvertexp->splitColor();
|
||||||
if (color >= numVertexes) nextp->v3fatalSrc("More colors than vertexes!\n");
|
if (color >= numVertexes) nextp->v3fatalSrc("More colors than vertexes");
|
||||||
if (!color) nextp->v3fatalSrc("No node color assigned\n");
|
if (!color) nextp->v3fatalSrc("No node color assigned");
|
||||||
if (lastOfColor[color]) {
|
if (lastOfColor[color]) {
|
||||||
new SplitStrictEdge(&m_graph, lastOfColor[color], vvertexp);
|
new SplitStrictEdge(&m_graph, lastOfColor[color], vvertexp);
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-5
@@ -183,16 +183,19 @@ public:
|
|||||||
}
|
}
|
||||||
return any;
|
return any;
|
||||||
}
|
}
|
||||||
void importFromIface(VSymGraph* graphp, const VSymEnt* srcp) {
|
void importFromIface(VSymGraph* graphp, const VSymEnt* srcp, bool onlyUnmodportable = false) {
|
||||||
// Import interface tokens from source symbol table into this symbol table, recursively
|
// Import interface tokens from source symbol table into this symbol table, recursively
|
||||||
UINFO(9, " importIf se"<<(void*)this<<" from se"<<(void*)srcp<<endl);
|
UINFO(9, " importIf se"<<(void*)this<<" from se"<<(void*)srcp<<endl);
|
||||||
for (IdNameMap::const_iterator it=srcp->m_idNameMap.begin(); it!=srcp->m_idNameMap.end(); ++it) {
|
for (IdNameMap::const_iterator it=srcp->m_idNameMap.begin(); it!=srcp->m_idNameMap.end(); ++it) {
|
||||||
const string& name = it->first;
|
const string& name = it->first;
|
||||||
VSymEnt* subSrcp = it->second;
|
VSymEnt* subSrcp = it->second;
|
||||||
VSymEnt* subSymp = new VSymEnt(graphp, subSrcp);
|
AstVar* varp = subSrcp->nodep()->castVar();
|
||||||
reinsert(name, subSymp);
|
if (!onlyUnmodportable || (varp && varp->varType() == AstVarType::GPARAM)) {
|
||||||
// And recurse to create children
|
VSymEnt* subSymp = new VSymEnt(graphp, subSrcp);
|
||||||
subSymp->importFromIface(graphp, subSrcp);
|
reinsert(name, subSymp);
|
||||||
|
// And recurse to create children
|
||||||
|
subSymp->importFromIface(graphp, subSrcp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void cellErrorScopes(AstNode* lookp, string prettyName="") {
|
void cellErrorScopes(AstNode* lookp, string prettyName="") {
|
||||||
|
|||||||
+2
-2
@@ -263,7 +263,7 @@ private:
|
|||||||
if (nodep->varp()->user2p()) { // It's being converted to a alias.
|
if (nodep->varp()->user2p()) { // It's being converted to a alias.
|
||||||
UINFO(9, " relinkVar "<<(void*)nodep->varp()->user2p()<<" "<<nodep<<endl);
|
UINFO(9, " relinkVar "<<(void*)nodep->varp()->user2p()<<" "<<nodep<<endl);
|
||||||
AstVarScope* newvscp = nodep->varp()->user2p()->castVarScope();
|
AstVarScope* newvscp = nodep->varp()->user2p()->castVarScope();
|
||||||
if (!newvscp) nodep->v3fatalSrc("Null?\n");
|
if (!newvscp) nodep->v3fatalSrc("not linked");
|
||||||
nodep->varScopep(newvscp);
|
nodep->varScopep(newvscp);
|
||||||
nodep->varp(nodep->varScopep()->varp());
|
nodep->varp(nodep->varScopep()->varp());
|
||||||
nodep->name(nodep->varp()->name());
|
nodep->name(nodep->varp()->name());
|
||||||
@@ -1147,7 +1147,7 @@ private:
|
|||||||
m_insStmtp = NULL; // Next thing should be new statement
|
m_insStmtp = NULL; // Next thing should be new statement
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeFor* nodep) {
|
virtual void visit(AstNodeFor* nodep) {
|
||||||
nodep->v3fatalSrc("For statements should have been converted to while statements in V3Begin.cpp\n");
|
nodep->v3fatalSrc("For statements should have been converted to while statements in V3Begin.cpp");
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeStmt* nodep) {
|
virtual void visit(AstNodeStmt* nodep) {
|
||||||
m_insMode = IM_BEFORE;
|
m_insMode = IM_BEFORE;
|
||||||
|
|||||||
+1
-1
@@ -387,7 +387,7 @@ private:
|
|||||||
} else if (basefromp->castConst()) {
|
} else if (basefromp->castConst()) {
|
||||||
// If it's a PARAMETER[bit], then basefromp may be a constant instead of a varrefp
|
// If it's a PARAMETER[bit], then basefromp may be a constant instead of a varrefp
|
||||||
} else {
|
} else {
|
||||||
nodep->v3fatalSrc("No VarRef or Const under ArraySel\n");
|
nodep->v3fatalSrc("No VarRef or Const under ArraySel");
|
||||||
}
|
}
|
||||||
// Find range of dtype we are selecting from
|
// Find range of dtype we are selecting from
|
||||||
int declElements = -1;
|
int declElements = -1;
|
||||||
|
|||||||
+20
-15
@@ -2094,8 +2094,9 @@ private:
|
|||||||
}
|
}
|
||||||
virtual void visit(AstValuePlusArgs* nodep) {
|
virtual void visit(AstValuePlusArgs* nodep) {
|
||||||
if (m_vup->prelim()) {
|
if (m_vup->prelim()) {
|
||||||
userIterateAndNext(nodep->exprsp(), WidthVP(SELF,BOTH).p());
|
userIterateAndNext(nodep->searchp(), WidthVP(SELF,BOTH).p());
|
||||||
nodep->dtypeSetSigned32(); // Spec says integer return
|
userIterateAndNext(nodep->outp(), WidthVP(SELF,BOTH).p());
|
||||||
|
nodep->dtypeChgWidthSigned(32,1,AstNumeric::SIGNED); // Spec says integer return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstUCStmt* nodep) {
|
virtual void visit(AstUCStmt* nodep) {
|
||||||
@@ -2136,7 +2137,8 @@ private:
|
|||||||
AstNodeDType* subDTypep = pinDTypep;
|
AstNodeDType* subDTypep = pinDTypep;
|
||||||
int pinwidth = pinDTypep->width();
|
int pinwidth = pinDTypep->width();
|
||||||
int conwidth = conDTypep->width();
|
int conwidth = conDTypep->width();
|
||||||
if (conDTypep == pinDTypep) { // If match, we're golden
|
if (conDTypep == pinDTypep // If match, we're golden
|
||||||
|
|| similarDTypeRecurse(conDTypep, pinDTypep)) {
|
||||||
userIterateAndNext(nodep->exprp(), WidthVP(subDTypep,FINAL).p());
|
userIterateAndNext(nodep->exprp(), WidthVP(subDTypep,FINAL).p());
|
||||||
}
|
}
|
||||||
else if (m_cellRangep) {
|
else if (m_cellRangep) {
|
||||||
@@ -2178,22 +2180,22 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO Simple dtype checking, should be a more general check
|
// TODO Simple dtype checking, should be a more general check
|
||||||
AstNodeArrayDType* loArrayp = exprDTypep->skipRefp()->castUnpackArrayDType();
|
AstNodeArrayDType* exprArrayp = exprDTypep->skipRefp()->castUnpackArrayDType();
|
||||||
AstNodeArrayDType* hiArrayp = modDTypep->skipRefp()->castUnpackArrayDType();
|
AstNodeArrayDType* modArrayp = modDTypep->skipRefp()->castUnpackArrayDType();
|
||||||
if (loArrayp && hiArrayp && loArrayp->subDTypep()->skipRefp()->castIfaceRefDType()
|
if (exprArrayp && modArrayp && exprArrayp->subDTypep()->skipRefp()->castIfaceRefDType()
|
||||||
&& loArrayp->declRange().elements() != hiArrayp->declRange().elements()) {
|
&& exprArrayp->declRange().elements() != modArrayp->declRange().elements()) {
|
||||||
int loSize = loArrayp->declRange().elements();
|
int exprSize = exprArrayp->declRange().elements();
|
||||||
int hiSize = hiArrayp->declRange().elements();
|
int modSize = modArrayp->declRange().elements();
|
||||||
nodep->v3error("Illegal "<<nodep->prettyOperatorName()<<","
|
nodep->v3error("Illegal "<<nodep->prettyOperatorName()<<","
|
||||||
<<" mismatch between port which is an interface array of size "<<loSize<<","
|
<<" mismatch between port which is an interface array of size "<<modSize<<","
|
||||||
<<" and expression which is an interface array of size "<<hiSize<<".");
|
<<" and expression which is an interface array of size "<<exprSize<<".");
|
||||||
UINFO(1," Related lo: "<<modDTypep->skipRefp()<<endl);
|
UINFO(1," Related lo: "<<modDTypep->skipRefp()<<endl);
|
||||||
UINFO(1," Related hi: "<<exprDTypep->skipRefp()<<endl);
|
UINFO(1," Related hi: "<<exprDTypep->skipRefp()<<endl);
|
||||||
} else if ((loArrayp && !hiArrayp && pinwidth != conwidth)
|
} else if ((exprArrayp && !modArrayp && pinwidth != conwidth)
|
||||||
|| (!loArrayp && hiArrayp && pinwidth != conwidth)) {
|
|| (!exprArrayp && modArrayp && pinwidth != conwidth)) {
|
||||||
nodep->v3error("Illegal "<<nodep->prettyOperatorName()<<","
|
nodep->v3error("Illegal "<<nodep->prettyOperatorName()<<","
|
||||||
<<" mismatch between port which is"<<(loArrayp?"":" not")<<" an array,"
|
<<" mismatch between port which is"<<(modArrayp?"":" not")<<" an array,"
|
||||||
<<" and expression which is"<<(hiArrayp?"":" not")<<" an array.");
|
<<" and expression which is"<<(exprArrayp?"":" not")<<" an array.");
|
||||||
UINFO(1," Related lo: "<<modDTypep->skipRefp()<<endl);
|
UINFO(1," Related lo: "<<modDTypep->skipRefp()<<endl);
|
||||||
UINFO(1," Related hi: "<<exprDTypep->skipRefp()<<endl);
|
UINFO(1," Related hi: "<<exprDTypep->skipRefp()<<endl);
|
||||||
}
|
}
|
||||||
@@ -2909,6 +2911,9 @@ private:
|
|||||||
return false; // No change
|
return false; // No change
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool similarDTypeRecurse(AstNodeDType* node1p, AstNodeDType* node2p) {
|
||||||
|
return node1p->skipRefp()->similarDType(node2p->skipRefp());
|
||||||
|
}
|
||||||
void iterateCheckFileDesc (AstNode* nodep, AstNode* underp, Stage stage) {
|
void iterateCheckFileDesc (AstNode* nodep, AstNode* underp, Stage stage) {
|
||||||
if (stage != BOTH) nodep->v3fatalSrc("Bad call");
|
if (stage != BOTH) nodep->v3fatalSrc("Bad call");
|
||||||
// underp may change as a result of replacement
|
// underp may change as a result of replacement
|
||||||
|
|||||||
+1
-1
@@ -52,7 +52,7 @@ bool VlcOptions::onoff(const char* sw, const char* arg, bool& flag) {
|
|||||||
// if sw=="-no-arg", then return true (found it), and flag=false
|
// if sw=="-no-arg", then return true (found it), and flag=false
|
||||||
// if sw=="-noarg", then return true (found it), and flag=false
|
// if sw=="-noarg", then return true (found it), and flag=false
|
||||||
// else return false
|
// else return false
|
||||||
if (arg[0]!='-') v3fatalSrc("OnOff switches must have leading dash.\n");
|
if (arg[0]!='-') v3fatalSrc("OnOff switches must have leading dash.");
|
||||||
if (0==strcmp(sw,arg)) { flag=true; return true; }
|
if (0==strcmp(sw,arg)) { flag=true; return true; }
|
||||||
else if (0==strncmp(sw,"-no",3) && (0==strcmp(sw+3,arg+1))) { flag=false; return true; }
|
else if (0==strncmp(sw,"-no",3) && (0==strcmp(sw+3,arg+1))) { flag=false; return true; }
|
||||||
else if (0==strncmp(sw,"-no-",4) && (0==strcmp(sw+4,arg+1))) { flag=false; return true; }
|
else if (0==strncmp(sw,"-no-",4) && (0==strcmp(sw+4,arg+1))) { flag=false; return true; }
|
||||||
|
|||||||
+1
-1
@@ -873,7 +873,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
|||||||
/* Attributes */
|
/* Attributes */
|
||||||
/* Note simulators vary in support for "(* /_*something*_/ foo*)" where _ doesn't exist */
|
/* Note simulators vary in support for "(* /_*something*_/ foo*)" where _ doesn't exist */
|
||||||
<V95,V01,V05,VA5,S05,S09,S12,SAX>{
|
<V95,V01,V05,VA5,S05,S09,S12,SAX>{
|
||||||
"(*"({ws}|{crnl})*({id}|{escid}) { yymore(); yy_push_state(ATTRMODE); } // Doesn't match (*), but (* attr_spec
|
"(*"({ws}|{crnl})*({id}|{escid}) { yymore(); yy_push_state(ATTRMODE); } /* Doesn't match (*), but (* attr_spec */
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|||||||
+2
-2
@@ -2710,12 +2710,12 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
|
|||||||
| yD_SQRT '(' expr ')' { $$ = new AstSqrtD($1,$3); }
|
| yD_SQRT '(' expr ')' { $$ = new AstSqrtD($1,$3); }
|
||||||
| yD_SSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstSScanF($1,*$5,$3,$6); }
|
| yD_SSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstSScanF($1,*$5,$3,$6); }
|
||||||
| yD_STIME parenE { $$ = new AstSel($1,new AstTime($1),0,32); }
|
| yD_STIME parenE { $$ = new AstSel($1,new AstTime($1),0,32); }
|
||||||
| yD_SYSTEM '(' expr ')' { $$ = new AstSystemF($1,$3); }
|
| yD_SYSTEM '(' expr ')' { $$ = new AstSystemF($1,$3); }
|
||||||
| yD_TESTPLUSARGS '(' str ')' { $$ = new AstTestPlusArgs($1,*$3); }
|
| yD_TESTPLUSARGS '(' str ')' { $$ = new AstTestPlusArgs($1,*$3); }
|
||||||
| yD_TIME parenE { $$ = new AstTime($1); }
|
| yD_TIME parenE { $$ = new AstTime($1); }
|
||||||
| yD_UNPACKED_DIMENSIONS '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_UNPK_DIMENSIONS,$3); }
|
| yD_UNPACKED_DIMENSIONS '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_UNPK_DIMENSIONS,$3); }
|
||||||
| yD_UNSIGNED '(' expr ')' { $$ = new AstUnsigned($1,$3); }
|
| yD_UNSIGNED '(' expr ')' { $$ = new AstUnsigned($1,$3); }
|
||||||
| yD_VALUEPLUSARGS '(' str ',' expr ')' { $$ = new AstValuePlusArgs($1,*$3,$5); }
|
| yD_VALUEPLUSARGS '(' expr ',' expr ')' { $$ = new AstValuePlusArgs($1,$3,$5); }
|
||||||
;
|
;
|
||||||
|
|
||||||
exprOrDataType<nodep>: // expr | data_type: combined to prevent conflicts
|
exprOrDataType<nodep>: // expr | data_type: combined to prevent conflicts
|
||||||
|
|||||||
Executable
+19
@@ -0,0 +1,19 @@
|
|||||||
|
#!/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.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
verilator_flags2 => ['--assert'],
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2016 by Wilson Snyder
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/
|
||||||
|
// Outputs
|
||||||
|
dout,
|
||||||
|
// Inputs
|
||||||
|
clk, sel, a, c
|
||||||
|
);
|
||||||
|
|
||||||
|
input clk;
|
||||||
|
input bit [3:0] sel;
|
||||||
|
input bit [3:0] a;
|
||||||
|
input bit c;
|
||||||
|
output bit dout;
|
||||||
|
|
||||||
|
localparam logic DC = 1'b?;
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
unique casez(sel)
|
||||||
|
4'b0000: dout <= a[0];
|
||||||
|
4'b001?: dout <= a[1];
|
||||||
|
{1'b0, 1'b1, 1'b?, 1'b?}: dout <= a[2];
|
||||||
|
{1'b1, 1'b?, 1'b?, DC}: dout <= a[3];
|
||||||
|
default: dout <= '0;
|
||||||
|
endcase
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/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.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty.
|
||||||
|
//
|
||||||
|
|
||||||
|
module some_module (
|
||||||
|
input wrclk
|
||||||
|
);
|
||||||
|
|
||||||
|
logic [ 1 : 0 ] some_state;
|
||||||
|
logic [1:0] some_other_state;
|
||||||
|
|
||||||
|
always @(posedge wrclk) begin
|
||||||
|
case (some_state)
|
||||||
|
2'b11:
|
||||||
|
if (some_other_state == 0)
|
||||||
|
some_state <= 2'b00;
|
||||||
|
default:
|
||||||
|
$display ("This is a display statement");
|
||||||
|
endcase
|
||||||
|
|
||||||
|
if (wrclk)
|
||||||
|
some_other_state <= 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
`define BROKEN
|
||||||
|
|
||||||
|
module t1(
|
||||||
|
input [3:0] i_clks,
|
||||||
|
input i_clk0,
|
||||||
|
input i_clk1
|
||||||
|
);
|
||||||
|
|
||||||
|
some_module
|
||||||
|
some_module
|
||||||
|
(
|
||||||
|
`ifdef BROKEN
|
||||||
|
.wrclk (i_clks[3])
|
||||||
|
`else
|
||||||
|
.wrclk (i_clk1)
|
||||||
|
`endif
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module t2(
|
||||||
|
input [2:0] i_clks,
|
||||||
|
input i_clk0,
|
||||||
|
input i_clk1,
|
||||||
|
input i_clk2,
|
||||||
|
input i_data
|
||||||
|
);
|
||||||
|
logic [3:0] the_clks;
|
||||||
|
logic data_q;
|
||||||
|
|
||||||
|
assign the_clks = {i_clk1, i_clk2, i_clk1, i_clk0};
|
||||||
|
|
||||||
|
always @(posedge i_clk0) begin
|
||||||
|
data_q <= i_data;
|
||||||
|
end
|
||||||
|
|
||||||
|
t1 t1
|
||||||
|
(
|
||||||
|
.i_clks (the_clks),
|
||||||
|
.i_clk0 (i_clk0),
|
||||||
|
.i_clk1 (i_clk1)
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module t(
|
||||||
|
input clk0 /*verilator clocker*/,
|
||||||
|
input clk1 /*verilator clocker*/,
|
||||||
|
input clk2 /*verilator clocker*/,
|
||||||
|
input data_in
|
||||||
|
);
|
||||||
|
|
||||||
|
logic [2:0] clks;
|
||||||
|
|
||||||
|
assign clks = {1'b0, clk1, clk0};
|
||||||
|
|
||||||
|
t2
|
||||||
|
t2
|
||||||
|
(
|
||||||
|
.i_clks (clks),
|
||||||
|
.i_clk0 (clk0),
|
||||||
|
.i_clk1 (clk1),
|
||||||
|
.i_clk2 (clk2),
|
||||||
|
.i_data (data_in)
|
||||||
|
);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/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.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty.
|
||||||
|
//
|
||||||
|
|
||||||
|
module some_module (
|
||||||
|
input wrclk
|
||||||
|
);
|
||||||
|
|
||||||
|
logic [ 1 : 0 ] some_state;
|
||||||
|
logic [1:0] some_other_state;
|
||||||
|
|
||||||
|
always @(posedge wrclk) begin
|
||||||
|
case (some_state)
|
||||||
|
2'b11:
|
||||||
|
if (some_other_state == 0)
|
||||||
|
some_state <= 2'b00;
|
||||||
|
default:
|
||||||
|
$display ("This is a display statement");
|
||||||
|
endcase
|
||||||
|
|
||||||
|
if (wrclk)
|
||||||
|
some_other_state <= 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
`define BROKEN
|
||||||
|
|
||||||
|
module t1(
|
||||||
|
input [3:0] i_clks,
|
||||||
|
input i_clk0,
|
||||||
|
input i_clk1
|
||||||
|
);
|
||||||
|
|
||||||
|
some_module
|
||||||
|
some_module
|
||||||
|
(
|
||||||
|
`ifdef BROKEN
|
||||||
|
.wrclk (i_clks[3])
|
||||||
|
`else
|
||||||
|
.wrclk (i_clk1)
|
||||||
|
`endif
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module t2(
|
||||||
|
input [2:0] i_clks,
|
||||||
|
input i_clk0,
|
||||||
|
input i_clk1,
|
||||||
|
input i_clk2,
|
||||||
|
input i_data
|
||||||
|
);
|
||||||
|
logic [3:0] the_clks;
|
||||||
|
logic data_q;
|
||||||
|
|
||||||
|
assign the_clks[3] = i_clk1;
|
||||||
|
assign the_clks[2] = i_clk2;
|
||||||
|
assign the_clks[1] = i_clk1;
|
||||||
|
assign the_clks[0] = i_clk0;
|
||||||
|
|
||||||
|
always @(posedge i_clk0) begin
|
||||||
|
data_q <= i_data;
|
||||||
|
end
|
||||||
|
|
||||||
|
t1 t1
|
||||||
|
(
|
||||||
|
.i_clks (the_clks),
|
||||||
|
.i_clk0 (i_clk0),
|
||||||
|
.i_clk1 (i_clk1)
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module t(
|
||||||
|
/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk /*verilator clocker*/,
|
||||||
|
input clk0 /*verilator clocker*/,
|
||||||
|
input clk1 /*verilator clocker*/,
|
||||||
|
input clk2 /*verilator clocker*/,
|
||||||
|
input data_in
|
||||||
|
);
|
||||||
|
|
||||||
|
input clk;
|
||||||
|
|
||||||
|
logic [2:0] clks;
|
||||||
|
|
||||||
|
assign clks = {1'b0, clk1, clk0};
|
||||||
|
|
||||||
|
t2
|
||||||
|
t2
|
||||||
|
(
|
||||||
|
.i_clks (clks),
|
||||||
|
.i_clk0 (clk0),
|
||||||
|
.i_clk1 (clk),
|
||||||
|
.i_clk2 (clk2),
|
||||||
|
.i_data (data_in)
|
||||||
|
);
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/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.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty.
|
||||||
|
//
|
||||||
|
|
||||||
|
/* verilator lint_off LITENDIAN */
|
||||||
|
module some_module (
|
||||||
|
input wrclk
|
||||||
|
);
|
||||||
|
|
||||||
|
logic [ 1 : 0 ] some_state;
|
||||||
|
logic [1:0] some_other_state;
|
||||||
|
|
||||||
|
always @(posedge wrclk) begin
|
||||||
|
case (some_state)
|
||||||
|
2'b11:
|
||||||
|
if (some_other_state == 0)
|
||||||
|
some_state <= 2'b00;
|
||||||
|
default:
|
||||||
|
$display ("This is a display statement");
|
||||||
|
endcase
|
||||||
|
|
||||||
|
if (wrclk)
|
||||||
|
some_other_state <= 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
`define BROKEN
|
||||||
|
|
||||||
|
module t1(
|
||||||
|
input [-12:-9] i_clks,
|
||||||
|
input i_clk0,
|
||||||
|
input i_clk1
|
||||||
|
);
|
||||||
|
|
||||||
|
some_module
|
||||||
|
some_module
|
||||||
|
(
|
||||||
|
`ifdef BROKEN
|
||||||
|
.wrclk (i_clks[-12])
|
||||||
|
`else
|
||||||
|
.wrclk (i_clk1)
|
||||||
|
`endif
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module t2(
|
||||||
|
input [2:0] i_clks,
|
||||||
|
input i_clk0,
|
||||||
|
input i_clk1,
|
||||||
|
input i_clk2,
|
||||||
|
input i_data
|
||||||
|
);
|
||||||
|
logic [-12:-9] the_clks;
|
||||||
|
logic data_q;
|
||||||
|
|
||||||
|
assign the_clks[-12] = i_clk1;
|
||||||
|
assign the_clks[-11] = i_clk2;
|
||||||
|
assign the_clks[-10] = i_clk1;
|
||||||
|
assign the_clks[-9] = i_clk0;
|
||||||
|
|
||||||
|
always @(posedge i_clk0) begin
|
||||||
|
data_q <= i_data;
|
||||||
|
end
|
||||||
|
|
||||||
|
t1 t1
|
||||||
|
(
|
||||||
|
.i_clks (the_clks),
|
||||||
|
.i_clk0 (i_clk0),
|
||||||
|
.i_clk1 (i_clk1)
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module t(
|
||||||
|
input clk0 /*verilator clocker*/,
|
||||||
|
input clk1 /*verilator clocker*/,
|
||||||
|
input clk2 /*verilator clocker*/,
|
||||||
|
input data_in
|
||||||
|
);
|
||||||
|
|
||||||
|
logic [2:0] clks;
|
||||||
|
|
||||||
|
assign clks = {1'b0, clk1, clk0};
|
||||||
|
|
||||||
|
t2
|
||||||
|
t2
|
||||||
|
(
|
||||||
|
.i_clks (clks),
|
||||||
|
.i_clk0 (clk0),
|
||||||
|
.i_clk1 (clk1),
|
||||||
|
.i_clk2 (clk2),
|
||||||
|
.i_data (data_in)
|
||||||
|
);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/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.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty.
|
||||||
|
//
|
||||||
|
|
||||||
|
module some_module (
|
||||||
|
input wrclk
|
||||||
|
);
|
||||||
|
|
||||||
|
logic [ 1 : 0 ] some_state;
|
||||||
|
logic [1:0] some_other_state;
|
||||||
|
|
||||||
|
always @(posedge wrclk) begin
|
||||||
|
case (some_state)
|
||||||
|
2'b11:
|
||||||
|
if (some_other_state == 0)
|
||||||
|
some_state <= 2'b00;
|
||||||
|
default:
|
||||||
|
$display ("This is a display statement");
|
||||||
|
endcase
|
||||||
|
|
||||||
|
if (wrclk)
|
||||||
|
some_other_state <= 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
`define BROKEN
|
||||||
|
|
||||||
|
module t1(
|
||||||
|
input [3:0] i_clks,
|
||||||
|
input i_clk0,
|
||||||
|
input i_clk1
|
||||||
|
);
|
||||||
|
|
||||||
|
generate
|
||||||
|
genvar i;
|
||||||
|
for (i = 0; i < 2; i = i + 1) begin: a_generate_block
|
||||||
|
some_module
|
||||||
|
some_module
|
||||||
|
(
|
||||||
|
`ifdef BROKEN
|
||||||
|
.wrclk (i_clks[3])
|
||||||
|
`else
|
||||||
|
.wrclk (i_clk1)
|
||||||
|
`endif
|
||||||
|
);
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module t2(
|
||||||
|
input [2:0] i_clks,
|
||||||
|
input i_clk0,
|
||||||
|
input i_clk1,
|
||||||
|
input i_clk2,
|
||||||
|
input i_data
|
||||||
|
);
|
||||||
|
logic [3:0] the_clks;
|
||||||
|
logic data_q;
|
||||||
|
|
||||||
|
assign the_clks[3] = i_clk1;
|
||||||
|
assign the_clks[2] = i_clk2;
|
||||||
|
assign the_clks[1] = i_clk1;
|
||||||
|
assign the_clks[0] = i_clk0;
|
||||||
|
|
||||||
|
always @(posedge i_clk0) begin
|
||||||
|
data_q <= i_data;
|
||||||
|
end
|
||||||
|
|
||||||
|
t1 t1
|
||||||
|
(
|
||||||
|
.i_clks (the_clks),
|
||||||
|
.i_clk0 (i_clk0),
|
||||||
|
.i_clk1 (i_clk1)
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module t(
|
||||||
|
input clk0 /*verilator clocker*/,
|
||||||
|
input clk1 /*verilator clocker*/,
|
||||||
|
input clk2 /*verilator clocker*/,
|
||||||
|
input data_in
|
||||||
|
);
|
||||||
|
|
||||||
|
logic [2:0] clks;
|
||||||
|
|
||||||
|
assign clks = {1'b0, clk1, clk0};
|
||||||
|
|
||||||
|
t2
|
||||||
|
t2
|
||||||
|
(
|
||||||
|
.i_clks (clks),
|
||||||
|
.i_clk0 (clk0),
|
||||||
|
.i_clk1 (clk1),
|
||||||
|
.i_clk2 (clk2),
|
||||||
|
.i_data (data_in)
|
||||||
|
);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/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.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty.
|
||||||
|
//
|
||||||
|
|
||||||
|
module some_module (
|
||||||
|
input [3:0] i_clks
|
||||||
|
);
|
||||||
|
|
||||||
|
logic [ 1 : 0 ] some_state;
|
||||||
|
logic [1:0] some_other_state;
|
||||||
|
|
||||||
|
always @(posedge i_clks[3]) begin
|
||||||
|
case (some_state)
|
||||||
|
2'b11:
|
||||||
|
if (some_other_state == 0)
|
||||||
|
some_state <= 2'b00;
|
||||||
|
default:
|
||||||
|
$display ("This is a display statement");
|
||||||
|
endcase
|
||||||
|
|
||||||
|
if (i_clks[3])
|
||||||
|
some_other_state <= 0;
|
||||||
|
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
`define BROKEN
|
||||||
|
|
||||||
|
module t1(
|
||||||
|
input [3:0] i_clks,
|
||||||
|
input i_clk0,
|
||||||
|
input i_clk1
|
||||||
|
);
|
||||||
|
|
||||||
|
some_module
|
||||||
|
some_module
|
||||||
|
(
|
||||||
|
.i_clks (i_clks)
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module t2(
|
||||||
|
input [2:0] i_clks,
|
||||||
|
input i_clk0,
|
||||||
|
input i_clk1,
|
||||||
|
input i_clk2,
|
||||||
|
input i_data
|
||||||
|
);
|
||||||
|
logic [3:0] the_clks;
|
||||||
|
logic data_q;
|
||||||
|
|
||||||
|
assign the_clks[3] = i_clk1;
|
||||||
|
assign the_clks[2] = i_clk2;
|
||||||
|
assign the_clks[1] = i_clk1;
|
||||||
|
assign the_clks[0] = i_clk0;
|
||||||
|
|
||||||
|
always @(posedge i_clk0) begin
|
||||||
|
data_q <= i_data;
|
||||||
|
end
|
||||||
|
|
||||||
|
t1 t1
|
||||||
|
(
|
||||||
|
.i_clks (the_clks),
|
||||||
|
.i_clk0 (i_clk0),
|
||||||
|
.i_clk1 (i_clk1)
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module t(
|
||||||
|
/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk /*verilator clocker*/,
|
||||||
|
input clk0 /*verilator clocker*/,
|
||||||
|
input clk1 /*verilator clocker*/,
|
||||||
|
input clk2 /*verilator clocker*/,
|
||||||
|
input data_in
|
||||||
|
);
|
||||||
|
|
||||||
|
input clk;
|
||||||
|
|
||||||
|
logic [2:0] clks;
|
||||||
|
|
||||||
|
assign clks = {1'b0, clk1, clk0};
|
||||||
|
|
||||||
|
t2
|
||||||
|
t2
|
||||||
|
(
|
||||||
|
.i_clks (clks),
|
||||||
|
.i_clk0 (clk0),
|
||||||
|
.i_clk1 (clk),
|
||||||
|
.i_clk2 (clk2),
|
||||||
|
.i_data (data_in)
|
||||||
|
);
|
||||||
|
|
||||||
|
// initial begin
|
||||||
|
// $write("*-* All Finished *-*\n");
|
||||||
|
// $finish;
|
||||||
|
// end
|
||||||
|
endmodule
|
||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/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.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty.
|
||||||
|
//
|
||||||
|
|
||||||
|
module some_module (
|
||||||
|
input [3:0] i_clks
|
||||||
|
);
|
||||||
|
|
||||||
|
logic [ 1 : 0 ] some_state;
|
||||||
|
logic [1:0] some_other_state;
|
||||||
|
logic the_clk;
|
||||||
|
|
||||||
|
assign the_clk = i_clks[3];
|
||||||
|
|
||||||
|
always @(posedge the_clk) begin
|
||||||
|
case (some_state)
|
||||||
|
2'b11:
|
||||||
|
if (some_other_state == 0)
|
||||||
|
some_state <= 2'b00;
|
||||||
|
default:
|
||||||
|
$display ("This is a display statement");
|
||||||
|
endcase
|
||||||
|
|
||||||
|
if (the_clk)
|
||||||
|
some_other_state <= 0;
|
||||||
|
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
`define BROKEN
|
||||||
|
|
||||||
|
module t1(
|
||||||
|
input [3:0] i_clks,
|
||||||
|
input i_clk0,
|
||||||
|
input i_clk1
|
||||||
|
);
|
||||||
|
|
||||||
|
some_module
|
||||||
|
some_module
|
||||||
|
(
|
||||||
|
.i_clks (i_clks)
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module ident(
|
||||||
|
input i_ident,
|
||||||
|
output o_ident
|
||||||
|
);
|
||||||
|
assign o_ident = i_ident;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module t2(
|
||||||
|
input [2:0] i_clks,
|
||||||
|
input i_clk0,
|
||||||
|
input i_clk1,
|
||||||
|
input i_clk2,
|
||||||
|
input i_data
|
||||||
|
);
|
||||||
|
logic [3:0] the_clks;
|
||||||
|
logic data_q;
|
||||||
|
logic ident_clk1;
|
||||||
|
|
||||||
|
always @(posedge i_clk0) begin
|
||||||
|
data_q <= i_data;
|
||||||
|
end
|
||||||
|
|
||||||
|
ident
|
||||||
|
ident
|
||||||
|
(
|
||||||
|
.i_ident (i_clk1),
|
||||||
|
.o_ident (ident_clk1)
|
||||||
|
);
|
||||||
|
|
||||||
|
t1 t1
|
||||||
|
(
|
||||||
|
.i_clks ({ident_clk1, i_clk2, ident_clk1, i_clk0}),
|
||||||
|
.i_clk0 (i_clk0),
|
||||||
|
.i_clk1 (i_clk1)
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module t(
|
||||||
|
/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk /*verilator clocker*/ /*verilator public_flat*/,
|
||||||
|
input clk0 /*verilator clocker*/,
|
||||||
|
input clk1 /*verilator clocker*/,
|
||||||
|
input clk2 /*verilator clocker*/,
|
||||||
|
input data_in
|
||||||
|
);
|
||||||
|
|
||||||
|
input clk;
|
||||||
|
|
||||||
|
logic [2:0] clks;
|
||||||
|
|
||||||
|
assign clks = {1'b0, clk1, clk0};
|
||||||
|
|
||||||
|
t2
|
||||||
|
t2
|
||||||
|
(
|
||||||
|
.i_clks (clks),
|
||||||
|
.i_clk0 (clk0),
|
||||||
|
.i_clk1 (clk),
|
||||||
|
.i_clk2 (clk2),
|
||||||
|
.i_data (data_in)
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule
|
||||||
Executable
+31
@@ -0,0 +1,31 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2017 by Todd Strader. 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 (
|
||||||
|
v_flags2 => ["--lint-only"],
|
||||||
|
fails=>1,
|
||||||
|
expect=>
|
||||||
|
q{%Warning-USERFATAL: f_add = 15
|
||||||
|
%Warning-USERFATAL: Use "/* verilator lint_off USERFATAL */" and lint_on around source to disable this message.
|
||||||
|
%Error: t/t_func_const2_bad.v:10: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_add2'
|
||||||
|
%Error: t/t_func_const2_bad.v:21: ... Location of non-constant STOP: $stop executed during function constification; maybe indicates assertion firing
|
||||||
|
Called from:
|
||||||
|
t/t_func_const2_bad.v:26: f_add() with parameters:
|
||||||
|
a = 32'h7
|
||||||
|
b = 32'h8
|
||||||
|
Called from:
|
||||||
|
t/t_func_const2_bad.v:10: f_add2() with parameters:
|
||||||
|
a = ?32?sh7
|
||||||
|
b = ?32?sh8
|
||||||
|
c = ?32?sh9
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2017 by Todd Strader.
|
||||||
|
|
||||||
|
module t;
|
||||||
|
|
||||||
|
localparam P6 = f_add(5, 1);
|
||||||
|
localparam P14 = f_add2(2, 3, f_add(4, 5));
|
||||||
|
localparam P24 = f_add2(7, 8, 9);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
// Should never get here
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
function integer f_add(input [31:0] a, input [31:0] b);
|
||||||
|
f_add = a+b;
|
||||||
|
if (f_add == 15)
|
||||||
|
$fatal(2, "f_add = 15");
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
// Speced ok: function called from function
|
||||||
|
function integer f_add2(input [31:0] a, input [31:0] b, input [31:0] c);
|
||||||
|
f_add2 = f_add(a,b)+c;
|
||||||
|
endfunction
|
||||||
|
endmodule
|
||||||
@@ -11,24 +11,39 @@ compile (
|
|||||||
v_flags2 => ["--lint-only"],
|
v_flags2 => ["--lint-only"],
|
||||||
fails=>1,
|
fails=>1,
|
||||||
expect=>
|
expect=>
|
||||||
q{%Error: t/t_func_const_bad.v:\d+: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_output'
|
q{%Error: t/t_func_const_bad.v:11: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_output'
|
||||||
%Error: t/t_func_const_bad.v:\d+: ... Location of non-constant VAR 'o': Language violation: Outputs not allowed in constant functions
|
%Error: t/t_func_const_bad.v:12: ... Location of non-constant VAR 'o': Language violation: Outputs not allowed in constant functions
|
||||||
%Error: t/t_func_const_bad.v:\d+: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_dotted'
|
%Error: t/t_func_const_bad.v:20: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_dotted'
|
||||||
%Error: t/t_func_const_bad.v:\d+: ... Location of non-constant VARXREF 'EIGHT': Language violation: Dotted hierarchical references not allowed in constant functions
|
%Error: t/t_func_const_bad.v:22: ... Location of non-constant VARXREF 'EIGHT': Language violation: Dotted hierarchical references not allowed in constant functions
|
||||||
%Error: t/t_func_const_bad.v:\d+: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_nonparam'
|
Called from:
|
||||||
%Error: t/t_func_const_bad.v:\d+: ... Location of non-constant VARREF 'modvar': Language violation: reference to non-function-local variable
|
t/t_func_const_bad.v:20: f_bad_dotted() with parameters:
|
||||||
%Error: t/t_func_const_bad.v:\d+: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_infinite'
|
a = ?32?sh2
|
||||||
%Error: t/t_func_const_bad.v:\d+: ... Location of non-constant WHILE: Loop unrolling took too long; probably this is an infinite loop, or set --unroll-count above 1024
|
%Error: t/t_func_const_bad.v:27: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_nonparam'
|
||||||
%Error: t/t_func_const_bad.v:\d+: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_stop'
|
%Error: t/t_func_const_bad.v:29: ... Location of non-constant VARREF 'modvar': Language violation: reference to non-function-local variable
|
||||||
%Error: t/t_func_const_bad.v:\d+: ... Location of non-constant STOP: .stop executed during function constification; maybe indicates assertion firing
|
Called from:
|
||||||
|
t/t_func_const_bad.v:27: f_bad_nonparam() with parameters:
|
||||||
|
a = ?32?sh3
|
||||||
|
%Error: t/t_func_const_bad.v:35: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_infinite'
|
||||||
|
%Error: t/t_func_const_bad.v:37: ... Location of non-constant WHILE: Loop unrolling took too long; probably this is an infinite loop, or set --unroll-count above 1024
|
||||||
|
Called from:
|
||||||
|
t/t_func_const_bad.v:35: f_bad_infinite() with parameters:
|
||||||
|
a = ?32?sh3
|
||||||
|
%Error: t/t_func_const_bad.v:43: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_stop'
|
||||||
|
%Error: t/t_func_const_bad.v:45: ... Location of non-constant STOP: $stop executed during function constification; maybe indicates assertion firing
|
||||||
|
Called from:
|
||||||
|
t/t_func_const_bad.v:43: f_bad_stop() with parameters:
|
||||||
|
a = ?32?sh3
|
||||||
-Info: Printing in loop: 0
|
-Info: Printing in loop: 0
|
||||||
-Info: Printing in loop: 1
|
-Info: Printing in loop: 1
|
||||||
-Info: Printing in loop: 2
|
-Info: Printing in loop: 2
|
||||||
%Warning-USERFATAL: Fatal Error
|
%Warning-USERFATAL: Fatal Error
|
||||||
%Warning-USERFATAL: Use ... verilator lint_off USERFATAL ... and lint_on around source to disable this message.
|
%Warning-USERFATAL: Use "/* verilator lint_off USERFATAL */" and lint_on around source to disable this message.
|
||||||
%Error: t/t_func_const_bad.v:\d+: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_fatal'
|
%Error: t/t_func_const_bad.v:49: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_fatal'
|
||||||
%Error: t/t_func_const_bad.v:\d+: ... Location of non-constant STOP: .stop executed during function constification; maybe indicates assertion firing
|
%Error: t/t_func_const_bad.v:54: ... Location of non-constant STOP: $stop executed during function constification; maybe indicates assertion firing
|
||||||
%Error: Exiting due to.*},
|
Called from:
|
||||||
|
t/t_func_const_bad.v:49: f_bad_fatal() with parameters:
|
||||||
|
a = ?32?sh3
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
ok(1);
|
ok(1);
|
||||||
|
|||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2017 by Todd Strader. 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 (
|
||||||
|
v_flags2 => ["--lint-only"],
|
||||||
|
fails=>1,
|
||||||
|
expect=>
|
||||||
|
q{%Warning-USERFATAL: f_add = 15
|
||||||
|
%Warning-USERFATAL: Use "/* verilator lint_off USERFATAL */" and lint_on around source to disable this message.
|
||||||
|
%Error: t/t_func_const_packed_array_bad.v:11: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_add2'
|
||||||
|
%Error: t/t_func_const_packed_array_bad.v:22: ... Location of non-constant STOP: $stop executed during function constification; maybe indicates assertion firing
|
||||||
|
Called from:
|
||||||
|
t/t_func_const_packed_array_bad.v:30: f_add() with parameters:
|
||||||
|
params = [0 = 32'h7, 1 = 32'h8]
|
||||||
|
Called from:
|
||||||
|
t/t_func_const_packed_array_bad.v:11: f_add2() with parameters:
|
||||||
|
a = ?32?sh7
|
||||||
|
b = ?32?sh8
|
||||||
|
c = ?32?sh9
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2017 by Todd Strader.
|
||||||
|
|
||||||
|
module t;
|
||||||
|
|
||||||
|
localparam [ 1 : 0 ] [ 31 : 0 ] P = {32'd5, 32'd1};
|
||||||
|
localparam P6 = f_add(P);
|
||||||
|
localparam P14 = f_add2(2, 3, f_add(P));
|
||||||
|
localparam P24 = f_add2(7, 8, 9);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
// Should never get here
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
function integer f_add(input [ 1 : 0 ] [ 31 : 0 ] params);
|
||||||
|
f_add = params[0]+params[1];
|
||||||
|
if (f_add == 15)
|
||||||
|
$fatal(2, "f_add = 15");
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
// Speced ok: function called from function
|
||||||
|
function integer f_add2(input [31:0] a, input [31:0] b, input [31:0] c);
|
||||||
|
logic [ 1 : 0 ] [ 31 : 0 ] params;
|
||||||
|
params[0] = a;
|
||||||
|
params[1] = b;
|
||||||
|
f_add2 = f_add(params)+c;
|
||||||
|
endfunction
|
||||||
|
endmodule
|
||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2017 by Todd Strader. 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 (
|
||||||
|
v_flags2 => ["--lint-only"],
|
||||||
|
fails=>1,
|
||||||
|
expect=>
|
||||||
|
q{%Warning-USERFATAL: f_add = 15
|
||||||
|
%Warning-USERFATAL: Use "/* verilator lint_off USERFATAL */" and lint_on around source to disable this message.
|
||||||
|
%Error: t/t_func_const_packed_struct_bad.v:13: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_add2'
|
||||||
|
%Error: t/t_func_const_packed_struct_bad.v:24: ... Location of non-constant STOP: $stop executed during function constification; maybe indicates assertion firing
|
||||||
|
Called from:
|
||||||
|
t/t_func_const_packed_struct_bad.v:32: f_add() with parameters:
|
||||||
|
params = [0 = '{a: 32'h7, b: 32'h22b}, 1 = '{a: 32'h3039, b: 32'h8}]
|
||||||
|
Called from:
|
||||||
|
t/t_func_const_packed_struct_bad.v:13: f_add2() with parameters:
|
||||||
|
a = ?32?sh7
|
||||||
|
b = ?32?sh8
|
||||||
|
c = ?32?sh9
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2017 by Todd Strader.
|
||||||
|
|
||||||
|
module t;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [ 31 : 0 ] a;
|
||||||
|
logic [ 31 : 0 ] b;
|
||||||
|
} params_t;
|
||||||
|
|
||||||
|
localparam P24 = f_add2(7, 8, 9);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
// Should never get here
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
function integer f_add(input params_t [ 1 : 0 ] params);
|
||||||
|
f_add = params[0].a+params[1].b;
|
||||||
|
if (f_add == 15)
|
||||||
|
$fatal(2, "f_add = 15");
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
// Speced ok: function called from function
|
||||||
|
function integer f_add2(input [31:0] a, input [31:0] b, input [31:0] c);
|
||||||
|
params_t [ 1 : 0 ] params;
|
||||||
|
params[0] = '{a:a, b:555};
|
||||||
|
params[1] = '{a:12345, b:b};
|
||||||
|
f_add2 = f_add(params)+c;
|
||||||
|
endfunction
|
||||||
|
endmodule
|
||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2017 by Todd Strader. 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 (
|
||||||
|
v_flags2 => ["--lint-only"],
|
||||||
|
fails=>1,
|
||||||
|
expect=>
|
||||||
|
q{%Warning-USERFATAL: f_add = 15
|
||||||
|
%Warning-USERFATAL: Use "/* verilator lint_off USERFATAL */" and lint_on around source to disable this message.
|
||||||
|
%Error: t/t_func_const_packed_struct_bad2.v:19: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_add2'
|
||||||
|
%Error: t/t_func_const_packed_struct_bad2.v:30: ... Location of non-constant STOP: $stop executed during function constification; maybe indicates assertion firing
|
||||||
|
Called from:
|
||||||
|
t/t_func_const_packed_struct_bad2.v:42: f_add() with parameters:
|
||||||
|
params = [0 = '{a: 32'h7, foo: 6'hb, sub_params: '{b: 32'h37, bar: 8'h6f}}, 1 = '{a: 32'h3039, foo: 6'hc, sub_params: '{b: 32'h8, bar: 8'h70}}]
|
||||||
|
Called from:
|
||||||
|
t/t_func_const_packed_struct_bad2.v:19: f_add2() with parameters:
|
||||||
|
a = ?32?sh7
|
||||||
|
b = ?32?sh8
|
||||||
|
c = ?32?sh9
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2017 by Todd Strader.
|
||||||
|
|
||||||
|
module t;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [ 31 : 0 ] b;
|
||||||
|
logic [ 7 : 0 ] bar;
|
||||||
|
} sub_params_t;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [ 31 : 0 ] a;
|
||||||
|
logic [ 5 : 0 ] foo;
|
||||||
|
sub_params_t sub_params;
|
||||||
|
} params_t;
|
||||||
|
|
||||||
|
localparam P24 = f_add2(7, 8, 9);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
// Should never get here
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
function integer f_add(input params_t [ 1 : 0 ] params);
|
||||||
|
f_add = params[0].a+params[1].sub_params.b;
|
||||||
|
if (f_add == 15)
|
||||||
|
$fatal(2, "f_add = 15");
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
// Speced ok: function called from function
|
||||||
|
function integer f_add2(input [31:0] a, input [31:0] b, input [31:0] c);
|
||||||
|
params_t [ 1 : 0 ] params;
|
||||||
|
sub_params_t sp0;
|
||||||
|
sub_params_t sp1;
|
||||||
|
sp0 = '{b:55, bar:111};
|
||||||
|
params[0] = '{a:a, foo:11, sub_params:sp0};
|
||||||
|
sp1 = '{b:b, bar:112};
|
||||||
|
params[1] = '{a:12345, foo:12, sub_params:sp1};
|
||||||
|
f_add2 = f_add(params)+c;
|
||||||
|
endfunction
|
||||||
|
endmodule
|
||||||
Executable
+30
@@ -0,0 +1,30 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2017 by Todd Strader. 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 (
|
||||||
|
v_flags2 => ["--lint-only"],
|
||||||
|
fails=>1,
|
||||||
|
expect=>
|
||||||
|
q{%Warning-USERFATAL: f_add = 15
|
||||||
|
%Warning-USERFATAL: Use "/* verilator lint_off USERFATAL */" and lint_on around source to disable this message.
|
||||||
|
%Error: t/t_func_const_struct_bad.v:16: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_add2'
|
||||||
|
%Error: t/t_func_const_struct_bad.v:27: ... Location of non-constant STOP: $stop executed during function constification; maybe indicates assertion firing
|
||||||
|
Called from:
|
||||||
|
t/t_func_const_struct_bad.v:37: f_add() with parameters:
|
||||||
|
params = '{a: 32'h7, b: 32'h8}
|
||||||
|
Called from:
|
||||||
|
t/t_func_const_struct_bad.v:16: f_add2() with parameters:
|
||||||
|
a = ?32?sh7
|
||||||
|
b = ?32?sh8
|
||||||
|
c = ?32?sh9
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2017 by Todd Strader.
|
||||||
|
|
||||||
|
module t;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [ 31 : 0 ] a;
|
||||||
|
logic [ 31 : 0 ] b;
|
||||||
|
} params_t;
|
||||||
|
|
||||||
|
localparam params_t P = '{a:5, b:1};
|
||||||
|
localparam P6 = f_add(P);
|
||||||
|
localparam P14 = f_add2(2, 3, f_add(P));
|
||||||
|
localparam P24 = f_add2(7, 8, 9);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
// Should never get here
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
function integer f_add(input params_t params);
|
||||||
|
f_add = params.a+params.b;
|
||||||
|
if (f_add == 15)
|
||||||
|
$fatal(2, "f_add = 15");
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
// Speced ok: function called from function
|
||||||
|
function integer f_add2(input [31:0] a, input [31:0] b, input [31:0] c);
|
||||||
|
params_t params;
|
||||||
|
params = '{
|
||||||
|
a: a,
|
||||||
|
b: b
|
||||||
|
};
|
||||||
|
f_add2 = f_add(params)+c;
|
||||||
|
endfunction
|
||||||
|
endmodule
|
||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/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 (
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2017 by John Stevenson.
|
||||||
|
|
||||||
|
typedef logic [63:0] uid_t;
|
||||||
|
typedef logic [31:0] value_t;
|
||||||
|
|
||||||
|
interface the_intf #(parameter M = 5);
|
||||||
|
logic valid;
|
||||||
|
uid_t uid;
|
||||||
|
value_t [M-1:0] values;
|
||||||
|
|
||||||
|
modport i(
|
||||||
|
output valid,
|
||||||
|
output uid,
|
||||||
|
output values
|
||||||
|
);
|
||||||
|
modport t(
|
||||||
|
input valid,
|
||||||
|
input uid,
|
||||||
|
input values
|
||||||
|
);
|
||||||
|
endinterface
|
||||||
|
|
||||||
|
module Contemplator #(
|
||||||
|
parameter IMPL = 0,
|
||||||
|
parameter M = 5,
|
||||||
|
parameter N = 1 )
|
||||||
|
(
|
||||||
|
input logic clk,
|
||||||
|
the_intf.i out [N-1:0]
|
||||||
|
);
|
||||||
|
|
||||||
|
the_intf #(.M(M)) inp[N-1:0] ();
|
||||||
|
|
||||||
|
DeepThought #(
|
||||||
|
.N ( N ))
|
||||||
|
ultimateAnswerer(
|
||||||
|
.src ( inp ),
|
||||||
|
.dst ( out ));
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module DeepThought #(
|
||||||
|
parameter N = 1 )
|
||||||
|
(
|
||||||
|
the_intf.t src[N-1:0],
|
||||||
|
the_intf.i dst[N-1:0]
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk
|
||||||
|
);
|
||||||
|
input clk;
|
||||||
|
|
||||||
|
localparam M = 5;
|
||||||
|
localparam N = 1;
|
||||||
|
|
||||||
|
the_intf #(.M(M)) out0 [N-1:0] ();
|
||||||
|
the_intf #(.M(M)) out1 [N-1:0] ();
|
||||||
|
|
||||||
|
Contemplator #(
|
||||||
|
.IMPL ( 0 ),
|
||||||
|
.M ( M ),
|
||||||
|
.N ( N ))
|
||||||
|
contemplatorOfTheZerothKind(
|
||||||
|
.clk ( clk ),
|
||||||
|
.out ( out0 ));
|
||||||
|
|
||||||
|
Contemplator #(
|
||||||
|
.IMPL ( 1 ),
|
||||||
|
.M ( M ),
|
||||||
|
.N ( N ))
|
||||||
|
contemplatorOfTheFirstKind(
|
||||||
|
.clk ( clk ),
|
||||||
|
.out ( out1 ));
|
||||||
|
initial begin
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/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 (
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
// DESCRIPTION: Verilator: Interface parameter getter
|
||||||
|
//
|
||||||
|
// A test of the import parameter used with modport
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2015 by Todd Strader
|
||||||
|
|
||||||
|
interface test_if #(parameter integer FOO = 1);
|
||||||
|
|
||||||
|
// Interface variable
|
||||||
|
logic data;
|
||||||
|
|
||||||
|
// Modport
|
||||||
|
modport mp(
|
||||||
|
import getFoo,
|
||||||
|
output data
|
||||||
|
);
|
||||||
|
|
||||||
|
function integer getFoo ();
|
||||||
|
return FOO;
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
endinterface // test_if
|
||||||
|
|
||||||
|
function integer identity (input integer x);
|
||||||
|
return x;
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk
|
||||||
|
);
|
||||||
|
input clk;
|
||||||
|
|
||||||
|
test_if #( .FOO (identity(5)) ) the_interface ();
|
||||||
|
|
||||||
|
testmod testmod_i (.clk (clk),
|
||||||
|
.intf (the_interface),
|
||||||
|
.intf_no_mp (the_interface)
|
||||||
|
);
|
||||||
|
|
||||||
|
localparam THE_TOP_FOO = the_interface.FOO;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
if (THE_TOP_FOO != 5) begin
|
||||||
|
$display("%%Error: THE_TOP_FOO = %0d", THE_TOP_FOO);
|
||||||
|
$stop;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
module testmod
|
||||||
|
(
|
||||||
|
input clk,
|
||||||
|
test_if.mp intf,
|
||||||
|
test_if intf_no_mp
|
||||||
|
);
|
||||||
|
|
||||||
|
localparam THE_FOO = intf.FOO;
|
||||||
|
localparam THE_OTHER_FOO = intf_no_mp.FOO;
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
if (THE_FOO != 5) begin
|
||||||
|
$display("%%Error: THE_FOO = %0d", THE_FOO);
|
||||||
|
$stop;
|
||||||
|
end
|
||||||
|
if (THE_OTHER_FOO != 5) begin
|
||||||
|
$display("%%Error: THE_OTHER_FOO = %0d", THE_OTHER_FOO);
|
||||||
|
$stop;
|
||||||
|
end
|
||||||
|
if (intf.FOO != 5) begin
|
||||||
|
$display("%%Error: intf.FOO = %0d", intf.FOO);
|
||||||
|
$stop;
|
||||||
|
end
|
||||||
|
if (intf_no_mp.FOO != 5) begin
|
||||||
|
$display("%%Error: intf_no_mp.FOO = %0d", intf_no_mp.FOO);
|
||||||
|
$stop;
|
||||||
|
end
|
||||||
|
// if (i.getFoo() != 5) begin
|
||||||
|
// $display("%%Error: i.getFoo() = %0d", i.getFoo());
|
||||||
|
// $stop;
|
||||||
|
// end
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
@@ -10,8 +10,8 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
|||||||
compile (
|
compile (
|
||||||
fails=>1,
|
fails=>1,
|
||||||
expect=>
|
expect=>
|
||||||
q{%Error: t/t_interface_size_bad.v:\d+: Illegal IFACEREF port connection 'foo', mismatch between port which is an interface array of size 4, and expression which is an interface array of size 5.
|
q{%Error: t/t_interface_size_bad.v:\d+: Illegal IFACEREF port connection 'foo', mismatch between port which is an interface array of size 5, and expression which is an interface array of size 4.
|
||||||
%Error: t/t_interface_size_bad.v:\d+: Illegal IFACEREF port connection 'foo', mismatch between port which is an interface array of size 6, and expression which is an interface array of size 5.
|
%Error: t/t_interface_size_bad.v:\d+: Illegal IFACEREF port connection 'foo', mismatch between port which is an interface array of size 5, and expression which is an interface array of size 6.
|
||||||
%Error: Exiting due to.*},
|
%Error: Exiting due to.*},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Executable
+20
@@ -0,0 +1,20 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2017 by Todd Strader. 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.
|
||||||
|
|
||||||
|
$Self->skip("Verilator only test") if !$Self->{vlt};
|
||||||
|
|
||||||
|
compile (
|
||||||
|
fails=>1,
|
||||||
|
expect=>
|
||||||
|
'%Warning-WIDTH: t/t_lint_literal_bad.v:9: Value too large for 8 bit number: 256
|
||||||
|
',
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2017 by Todd Strader.
|
||||||
|
|
||||||
|
module t (
|
||||||
|
);
|
||||||
|
|
||||||
|
localparam the_localparam = 8'd256;
|
||||||
|
|
||||||
|
endmodule
|
||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/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 (
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2017 by Wilson Snyder.
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/);
|
||||||
|
|
||||||
|
reg [5:0] addr;
|
||||||
|
|
||||||
|
parameter BANKS = 6;
|
||||||
|
parameter ROWS = 8;
|
||||||
|
|
||||||
|
wire [2:0] bank;
|
||||||
|
wire [2:0] row;
|
||||||
|
|
||||||
|
integer a;
|
||||||
|
integer used[BANKS][ROWS];
|
||||||
|
|
||||||
|
// Test loop
|
||||||
|
initial begin
|
||||||
|
for (a = 0; a < BANKS*ROWS; ++a) begin
|
||||||
|
addr[5:0] = a[5:0];
|
||||||
|
hash (addr, bank, row);
|
||||||
|
used [bank][row] ++;
|
||||||
|
if (used [bank][row] > 1) begin
|
||||||
|
$write ("Error: Hash failed addr=%x bank=%x row=%x\n", addr, bank, row);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
task hash (input [5:0] addr,
|
||||||
|
output [2:0] bank,
|
||||||
|
output [2:0] row);
|
||||||
|
|
||||||
|
reg [1:0] third;
|
||||||
|
reg [1:0] fourth;
|
||||||
|
|
||||||
|
third = {addr[5], addr[4]};
|
||||||
|
fourth = {addr[3] ^ addr[1],
|
||||||
|
addr[2] ^ addr[0]};
|
||||||
|
|
||||||
|
case (third)
|
||||||
|
2'h0:
|
||||||
|
case (fourth)
|
||||||
|
2'h0: begin bank = 3'h0; row = {1'h0, addr[1:0]}; end
|
||||||
|
2'h1: begin bank = 3'h1; row = {1'h0, addr[1:0]}; end
|
||||||
|
2'h2: begin bank = 3'h2; row = {1'h0, addr[1:0]}; end
|
||||||
|
2'h3: begin bank = 3'h3; row = {1'h0, addr[1:0]}; end
|
||||||
|
endcase
|
||||||
|
|
||||||
|
2'h1:
|
||||||
|
case (fourth)
|
||||||
|
2'h0: begin bank = 3'h0; row = {1'h1, addr[1:0]}; end
|
||||||
|
2'h1: begin bank = 3'h1; row = {1'h1, addr[1:0]}; end
|
||||||
|
2'h2: begin bank = 3'h4; row = {1'h0, addr[1:0]}; end
|
||||||
|
2'h3: begin bank = 3'h5; row = {1'h0, addr[1:0]}; end
|
||||||
|
endcase
|
||||||
|
|
||||||
|
2'h2:
|
||||||
|
case (fourth)
|
||||||
|
2'h0: begin bank = 3'h2; row = {1'h1, addr[1:0]}; end
|
||||||
|
2'h1: begin bank = 3'h3; row = {1'h1, addr[1:0]}; end
|
||||||
|
2'h2: begin bank = 3'h4; row = {1'h1, addr[1:0]}; end
|
||||||
|
2'h3: begin bank = 3'h5; row = {1'h1, addr[1:0]}; end
|
||||||
|
endcase
|
||||||
|
|
||||||
|
2'h3: $stop;
|
||||||
|
endcase
|
||||||
|
endtask
|
||||||
|
endmodule
|
||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/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 (
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2017 by Wilson Snyder.
|
||||||
|
|
||||||
|
module t;
|
||||||
|
localparam int c[4] = '{5, 6, 7, 8};
|
||||||
|
a #(.p(c)) i_a ();
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module a
|
||||||
|
#( parameter int p[4] = '{1, 2, 3, 4} );
|
||||||
|
initial begin
|
||||||
|
if (p[0] != 5) $stop;
|
||||||
|
if (p[1] != 6) $stop;
|
||||||
|
if (p[2] != 7) $stop;
|
||||||
|
if (p[3] != 8) $stop;
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
@@ -8,6 +8,8 @@ module t;
|
|||||||
integer p_i;
|
integer p_i;
|
||||||
reg [7*8:1] p_str;
|
reg [7*8:1] p_str;
|
||||||
string sv_str;
|
string sv_str;
|
||||||
|
reg [7*8:1] p_in;
|
||||||
|
string sv_in;
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
if ($test$plusargs("PLUS")!==1) $stop;
|
if ($test$plusargs("PLUS")!==1) $stop;
|
||||||
@@ -20,23 +22,47 @@ module t;
|
|||||||
if ($value$plusargs("NOTTHERE%d", p_i)!==0) $stop;
|
if ($value$plusargs("NOTTHERE%d", p_i)!==0) $stop;
|
||||||
if (p_i !== 10) $stop;
|
if (p_i !== 10) $stop;
|
||||||
|
|
||||||
|
p_i = 0;
|
||||||
if ($value$plusargs("INT=%d", p_i)!==1) $stop;
|
if ($value$plusargs("INT=%d", p_i)!==1) $stop;
|
||||||
if (p_i !== 32'd1234) $stop;
|
if (p_i !== 32'd1234) $stop;
|
||||||
|
|
||||||
|
p_i = 0;
|
||||||
if ($value$plusargs("INT=%H", p_i)!==1) $stop; // tests uppercase % also
|
if ($value$plusargs("INT=%H", p_i)!==1) $stop; // tests uppercase % also
|
||||||
if (p_i !== 32'h1234) $stop;
|
if (p_i !== 32'h1234) $stop;
|
||||||
|
|
||||||
if ($value$plusargs("INT=%o", p_i)!==1) $stop;
|
p_i = 0;
|
||||||
|
// Check octal and WIDTH
|
||||||
|
if (!$value$plusargs("INT=%o", p_i)) $stop;
|
||||||
if (p_i !== 32'o1234) $stop;
|
if (p_i !== 32'o1234) $stop;
|
||||||
|
|
||||||
|
p_str = "none";
|
||||||
if ($value$plusargs("IN%s", p_str)!==1) $stop;
|
if ($value$plusargs("IN%s", p_str)!==1) $stop;
|
||||||
$display("str='%s'",p_str);
|
$display("str='%s'",p_str);
|
||||||
if (p_str !== "T=1234") $stop;
|
if (p_str !== "T=1234") $stop;
|
||||||
|
|
||||||
|
sv_str = "none";
|
||||||
if ($value$plusargs("IN%s", sv_str)!==1) $stop;
|
if ($value$plusargs("IN%s", sv_str)!==1) $stop;
|
||||||
$display("str='%s'",sv_str);
|
$display("str='%s'",sv_str);
|
||||||
if (sv_str != "T=1234") $stop;
|
if (sv_str != "T=1234") $stop;
|
||||||
|
|
||||||
|
p_in = "IN%s";
|
||||||
|
`ifdef VERILATOR
|
||||||
|
p_in = $c(p_in); // Prevent constant propagation
|
||||||
|
`endif
|
||||||
|
sv_str = "none";
|
||||||
|
if ($value$plusargs(p_in, sv_str)!==1) $stop;
|
||||||
|
$display("str='%s'",sv_str);
|
||||||
|
if (sv_str != "T=1234") $stop;
|
||||||
|
|
||||||
|
sv_in = "INT=%d";
|
||||||
|
`ifdef VERILATOR
|
||||||
|
if ($c1(0)) sv_in = "NEVER"; // Prevent constant propagation
|
||||||
|
`endif
|
||||||
|
p_i = 0;
|
||||||
|
if ($value$plusargs(sv_in, p_i)!==1) $stop;
|
||||||
|
$display("i='%d'",p_i);
|
||||||
|
if (p_i !== 32'd1234) $stop;
|
||||||
|
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -8,13 +8,11 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
|||||||
# Version 2.0.
|
# Version 2.0.
|
||||||
|
|
||||||
compile (
|
compile (
|
||||||
fails=>$Self->{v3},
|
);
|
||||||
expect=>
|
|
||||||
q{%Error: t/t_sys_plusargs_bad.v:\d+: Missing or extra \$value\$plusargs format qualifier: 'NOTTHERE'
|
execute (
|
||||||
%Error: t/t_sys_plusargs_bad.v:\d+: Illegal \$value\$plusargs format qualifier: 'z'
|
check_finished=>1,
|
||||||
%Error: t/t_sys_plusargs_bad.v:\d+: Missing or extra \$value\$plusargs format qualifier: 'INT=%x%x'
|
);
|
||||||
%Error: Exiting due to.*},
|
|
||||||
);
|
|
||||||
|
|
||||||
ok(1);
|
ok(1);
|
||||||
1;
|
1;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ module t;
|
|||||||
// BAD: Multi letter
|
// BAD: Multi letter
|
||||||
if ($value$plusargs("INT=%x%x", p_i)!==0) $stop;
|
if ($value$plusargs("INT=%x%x", p_i)!==0) $stop;
|
||||||
|
|
||||||
$stop;
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|||||||
@@ -6,8 +6,6 @@
|
|||||||
`begin_keywords "VAMS-2.3"
|
`begin_keywords "VAMS-2.3"
|
||||||
|
|
||||||
module t (/*autoarg*/
|
module t (/*autoarg*/
|
||||||
// Outputs
|
|
||||||
aout,
|
|
||||||
// Inputs
|
// Inputs
|
||||||
clk, in
|
clk, in
|
||||||
);
|
);
|
||||||
@@ -15,21 +13,43 @@ module t (/*autoarg*/
|
|||||||
input clk;
|
input clk;
|
||||||
|
|
||||||
input [15:0] in;
|
input [15:0] in;
|
||||||
output aout;
|
|
||||||
wreal aout;
|
wreal aout;
|
||||||
|
|
||||||
integer cyc=0;
|
integer cyc=0;
|
||||||
|
|
||||||
real vin;
|
real vin;
|
||||||
real gnd;
|
wreal vpass;
|
||||||
|
through through (.vin, .vpass);
|
||||||
|
|
||||||
|
real gnd;
|
||||||
wire out;
|
wire out;
|
||||||
within_range within_range (/*AUTOINST*/
|
within_range within_range (/*AUTOINST*/
|
||||||
// Interfaces
|
// Interfaces
|
||||||
.vin (vin),
|
.vpass (vpass),
|
||||||
.gnd (gnd),
|
.gnd (gnd),
|
||||||
// Outputs
|
// Outputs
|
||||||
.out (out));
|
.out (out));
|
||||||
|
|
||||||
|
// wreal bus declaration
|
||||||
|
wreal vin_upper_bus[1:0];
|
||||||
|
|
||||||
|
// wreal nets declaration
|
||||||
|
wreal vout_split_0;
|
||||||
|
wreal vout_split_1;
|
||||||
|
|
||||||
|
wreal_bus wreal_bus( .vin_bus(vin_upper_bus[1:0]),
|
||||||
|
.vout_split_0(vout_split_0),
|
||||||
|
.vout_split_1(vout_split_1));
|
||||||
|
|
||||||
|
|
||||||
|
// implicit declaration of wreal
|
||||||
|
`ifdef VERILATOR
|
||||||
|
wreal wreal_implicit_net; // implicit declaration of wreal not supported yet
|
||||||
|
`endif
|
||||||
|
// verilator lint_off IMPLICIT
|
||||||
|
first_level first_level(.in(cyc[0]), .out(wreal_implicit_net));
|
||||||
|
// verilator lint_on IMPLICIT
|
||||||
|
|
||||||
parameter real lsb = 1;
|
parameter real lsb = 1;
|
||||||
// verilator lint_off WIDTH
|
// verilator lint_off WIDTH
|
||||||
assign aout = $itor(in) * lsb;
|
assign aout = $itor(in) * lsb;
|
||||||
@@ -70,14 +90,47 @@ module t (/*autoarg*/
|
|||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module within_range
|
module through
|
||||||
(input wreal vin,
|
(input wreal vin,
|
||||||
|
output wreal vpass);
|
||||||
|
assign vpass = vin;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module within_range
|
||||||
|
(input wreal vpass,
|
||||||
input wreal gnd,
|
input wreal gnd,
|
||||||
output out);
|
output out);
|
||||||
|
|
||||||
parameter real V_MIN = 0.5;
|
parameter real V_MIN = 0.5;
|
||||||
parameter real V_MAX = 10;
|
parameter real V_MAX = 10;
|
||||||
|
|
||||||
wreal in_int = vin - gnd;
|
wreal in_int = vpass - gnd;
|
||||||
wire out = (V_MIN <= in_int && in_int <= V_MAX);
|
wire out = (V_MIN <= in_int && in_int <= V_MAX);
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
module wreal_bus
|
||||||
|
(input wreal vin_bus [1:0],
|
||||||
|
output wreal vout_split_0,
|
||||||
|
output wreal vout_split_1);
|
||||||
|
assign vout_split_0 = vin_bus[0];
|
||||||
|
assign vout_split_1 = vin_bus[1];
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module first_level
|
||||||
|
(input in,
|
||||||
|
`ifdef VERILATOR
|
||||||
|
output wreal out
|
||||||
|
`else
|
||||||
|
output out // Implicity becomes real
|
||||||
|
`endif
|
||||||
|
);
|
||||||
|
second_level second_level(.in(in), .out(out));
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module second_level
|
||||||
|
(input in,
|
||||||
|
output out);
|
||||||
|
wreal out;
|
||||||
|
assign out = in ? 1.23456: 7.8910;
|
||||||
|
endmodule
|
||||||
|
|||||||
Reference in New Issue
Block a user