mirror of
https://github.com/verilator/verilator.git
synced 2026-10-03 00:23:35 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fedcb6d26a | ||
|
|
eed3c5e543 | ||
|
|
e26ab67e25 | ||
|
|
e77b7427b4 | ||
|
|
475e4207cc | ||
|
|
71b2eed32c | ||
|
|
6cf50e6579 | ||
|
|
69468708e2 | ||
|
|
5da5678e64 | ||
|
|
a428e7f618 | ||
|
|
0eb5a0a539 | ||
|
|
a1c1ff9981 | ||
|
|
2029ade18c | ||
|
|
5f8f474c0c | ||
|
|
f705f9b275 | ||
|
|
91e706ec1f | ||
|
|
dcf351f847 | ||
|
|
06744b664a | ||
|
|
d3049d9c89 | ||
|
|
1f2abb9c0f | ||
|
|
9f0d7e50a5 | ||
|
|
5f262a8f11 | ||
|
|
f62bc6a2e5 | ||
|
|
d7e4bc1379 | ||
|
|
cd2d6575c6 |
@@ -3,6 +3,39 @@ Revision history for Verilator
|
||||
The contributors that suggested a given feature are shown in []. [by ...]
|
||||
indicates the contributor was also the author of the fix; Thanks!
|
||||
|
||||
* Verilator 3.862 2014-06-10
|
||||
|
||||
*** Using command line -Wno-{WARNING} now overrides file-local lint_on.
|
||||
|
||||
*** Add -P to suppress `line and blanks with preprocessing, bug781. [Derek Lockhart]
|
||||
|
||||
*** Support SV 2012 package import before port list.
|
||||
|
||||
**** Change SYMRSVDWORD to print as warning rather than error.
|
||||
|
||||
**** Fix seg-fault with variable of parameterized interface, bug692. [Jie Xu]
|
||||
|
||||
**** Fix false name conflict on cells in generate blocks, bug749. [Igor Lesik]
|
||||
|
||||
**** Fix pattern assignment to basic types, bug767. [Jie Xu]
|
||||
|
||||
**** Fix pattern assignment to conditionals, bug769. [Jie Xu]
|
||||
|
||||
**** Fix shift corner-cases, bug765, bug766, bug768, bug772, bug774, bug776. [Clifford Wolf]
|
||||
|
||||
**** Fix C compiler interpreting signing, bug773. [Clifford Wolf]
|
||||
|
||||
**** Fix late constant division by zero giving X error, bug775. [Clifford Wolf]
|
||||
|
||||
**** Fix gate primitives with arrays and non-arrayed pins.
|
||||
|
||||
**** Fix DETECTARRAY error on packed arrays, bug770. [Jie Xu]
|
||||
|
||||
**** Fix ENDLABEL warnings on escaped identifiers.
|
||||
|
||||
**** Fix string corruption, bug780. [Derek Lockhart]
|
||||
|
||||
|
||||
* Verilator 3.860 2014-05-11
|
||||
|
||||
** PSL is no longer supported, please use System Verilog assertions.
|
||||
|
||||
+15
-6
@@ -303,6 +303,7 @@ descriptions in the next sections for more information.
|
||||
--output-split <bytes> Split .cpp files into pieces
|
||||
--output-split-cfuncs <statements> Split .cpp functions
|
||||
--output-split-ctrace <statements> Split tracing functions
|
||||
-P Disable line numbers and blanks with -E
|
||||
--pins-bv <bits> Specify types for top level ports
|
||||
--pins-sc-uint Specify types for top level ports
|
||||
--pins-sc-biguint Specify types for top level ports
|
||||
@@ -830,6 +831,11 @@ function.
|
||||
Enables splitting trace functions in the output .cpp/.sp files into
|
||||
multiple functions. Defaults to same setting as --output-split-cfuncs.
|
||||
|
||||
=item -P
|
||||
|
||||
With -E, disable generation of `line markers and blank lines, similar to
|
||||
GCC -P flag.
|
||||
|
||||
=item --pins64
|
||||
|
||||
Backward compatible alias for "--pins-bv 65". Note that's a 65, not a 64.
|
||||
@@ -1088,7 +1094,8 @@ supports which the older version does not support.
|
||||
|
||||
=item -Wno-I<message>
|
||||
|
||||
Disable the specified warning message.
|
||||
Disable the specified warning message. This will override any lint_on
|
||||
directives in the source, i.e. the warning will still not be printed.
|
||||
|
||||
=item -Wno-lint
|
||||
|
||||
@@ -1918,6 +1925,9 @@ Disables the specified lint warning, in the specified filename (or wildcard
|
||||
with '*' or '?', or all files if omitted) and range of line numbers (or all
|
||||
lines if omitted).
|
||||
|
||||
Using '*' will override any lint_on directives in the source, i.e. the
|
||||
warning will still not be printed.
|
||||
|
||||
If the -msg is omitted, all lint warnings are disabled. This will override
|
||||
all later lint warning enables for the specified region.
|
||||
|
||||
@@ -3088,10 +3098,9 @@ simulators.
|
||||
|
||||
=item SYMRSVDWORD
|
||||
|
||||
Error that a symbol matches a C++ reserved word and using this as a symbol
|
||||
name would result in odd C compiler errors. You may disable this error
|
||||
message as you would disable warnings, but the symbol will be renamed by
|
||||
Verilator to avoid the conflict.
|
||||
Warning that a symbol matches a C++ reserved word and using this as a symbol
|
||||
name would result in odd C compiler errors. You may disable this warning,
|
||||
but the symbol will be renamed by Verilator to avoid the conflict.
|
||||
|
||||
=item SYNCASYNCNET
|
||||
|
||||
@@ -3380,7 +3389,7 @@ so your simulator shouldn't have to be -- and Verilator is closer to the
|
||||
synthesis interpretation, so this is a good thing for getting working
|
||||
silicon.
|
||||
|
||||
=item Will Verilator output remain under my own copyright?
|
||||
=item Will Verilator output remain under my own license?
|
||||
|
||||
Yes, it's just like using GCC on your programs; this is why Verilator uses
|
||||
the "GNU *Lesser* Public License Version 3" instead of the more typical
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
|
||||
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
||||
#AC_INIT([Verilator],[#.### devel])
|
||||
AC_INIT([Verilator],[3.860 2014-05-11])
|
||||
AC_INIT([Verilator],[3.862 2014-06-10])
|
||||
AC_CONFIG_HEADER(src/config_build.h)
|
||||
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk include/verilated_config.h)
|
||||
|
||||
|
||||
@@ -1250,9 +1250,9 @@ void VerilatedScope::scopeDump() const {
|
||||
m_callbacksp[i], VerilatedImp::exportName(i));
|
||||
}
|
||||
}
|
||||
if (varsp()) {
|
||||
for (VerilatedVarNameMap::const_iterator it = varsp()->begin();
|
||||
it != varsp()->end(); ++it) {
|
||||
if (VerilatedVarNameMap* varsp = this->varsp()) {
|
||||
for (VerilatedVarNameMap::const_iterator it = varsp->begin();
|
||||
it != varsp->end(); ++it) {
|
||||
VL_PRINTF(" VAR %p: %s\n", &(it->second), it->first);
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -1458,7 +1458,7 @@ static inline QData VL_STREAML_QQI(int, int lbits, int, QData ld, IData rd) {
|
||||
static inline WDataOutP VL_STREAML_WWI(int, int lbits, int, WDataOutP owp, WDataInP lwp, IData rd) {
|
||||
VL_ZERO_RESET_W(lbits, owp);
|
||||
// Slice size should never exceed the lhs width
|
||||
int ssize = ((int)rd < lbits) ? ((int)rd) : lbits;
|
||||
int ssize = (rd < (IData)lbits) ? rd : ((IData)lbits);
|
||||
for (int istart=0; istart<lbits; istart+=rd) {
|
||||
int ostart=lbits-rd-istart;
|
||||
ostart = ostart > 0 ? ostart : 0;
|
||||
@@ -1558,7 +1558,7 @@ static inline void _VL_SHIFTL_INPLACE_W(int obits,WDataOutP iowp,IData rd/*1 or
|
||||
static inline WDataOutP VL_SHIFTL_WWI(int obits,int,int,WDataOutP owp,WDataInP lwp, IData rd) {
|
||||
int word_shift = VL_BITWORD_I(rd);
|
||||
int bit_shift = VL_BITBIT_I(rd);
|
||||
if ((int)rd >= obits) {
|
||||
if (rd >= (IData)obits) { // rd may be huge with MSB set
|
||||
for (int i=0; i < VL_WORDS_I(obits); i++) owp[i] = 0;
|
||||
} else if (bit_shift==0) { // Aligned word shift (<<0,<<32,<<64 etc)
|
||||
for (int i=0; i < word_shift; i++) owp[i] = 0;
|
||||
@@ -1576,7 +1576,7 @@ static inline WDataOutP VL_SHIFTL_WWI(int obits,int,int,WDataOutP owp,WDataInP l
|
||||
static inline WDataOutP VL_SHIFTR_WWI(int obits,int,int,WDataOutP owp,WDataInP lwp, IData rd) {
|
||||
int word_shift = VL_BITWORD_I(rd); // Maybe 0
|
||||
int bit_shift = VL_BITBIT_I(rd);
|
||||
if ((int)rd >= obits) {
|
||||
if (rd >= (IData)obits) { // rd may be huge with MSB set
|
||||
for (int i=0; i < VL_WORDS_I(obits); i++) owp[i] = 0;
|
||||
} else if (bit_shift==0) { // Aligned word shift (>>0,>>32,>>64 etc)
|
||||
int copy_words = (VL_WORDS_I(obits)-word_shift);
|
||||
@@ -1622,7 +1622,7 @@ static inline WDataOutP VL_SHIFTRS_WWI(int obits,int lbits,int,WDataOutP owp,WDa
|
||||
int bit_shift = VL_BITBIT_I(rd);
|
||||
int lmsw = VL_WORDS_I(obits)-1;
|
||||
IData sign = VL_SIGNONES_I(lbits,lwp[lmsw]);
|
||||
if ((int)rd >= obits) { // Shifting past end, sign in all of lbits
|
||||
if (rd >= (IData)obits) { // Shifting past end, sign in all of lbits
|
||||
for (int i=0; i <= lmsw; i++) owp[i] = sign;
|
||||
owp[lmsw] &= VL_MASK_I(lbits);
|
||||
} else if (bit_shift==0) { // Aligned word shift (>>0,>>32,>>64 etc)
|
||||
@@ -1661,7 +1661,7 @@ static inline WDataOutP VL_SHIFTRS_WWI(int obits,int lbits,int,WDataOutP owp,WDa
|
||||
|
||||
static inline IData VL_BITSEL_IWII(int, int lbits, int, int, WDataInP lwp, IData rd) {
|
||||
int word = VL_BITWORD_I(rd);
|
||||
if (VL_UNLIKELY((int)rd>lbits)) {
|
||||
if (VL_UNLIKELY(rd>(IData)lbits)) {
|
||||
return ~0; // Spec says you can go outside the range of a array. Don't coredump if so.
|
||||
// We return all 1's as that's more likely to find bugs (?) than 0's.
|
||||
} else {
|
||||
|
||||
@@ -62,8 +62,9 @@ bool VerilatedDeserialize::readDiffers (const void* __restrict datap, size_t siz
|
||||
|
||||
VerilatedDeserialize& VerilatedDeserialize::readAssert (const void* __restrict datap, size_t size) {
|
||||
if (VL_UNLIKELY(readDiffers(datap,size))) {
|
||||
string fn = filename();
|
||||
string msg = (string)"Can't deserialize save-restore file as was made from different model";
|
||||
vl_fatal(filename().c_str(), 0, "", msg.c_str());
|
||||
vl_fatal(fn.c_str(), 0, "", msg.c_str());
|
||||
close();
|
||||
}
|
||||
return *this; // For function chaining
|
||||
@@ -82,8 +83,9 @@ void VerilatedSerialize::header() {
|
||||
void VerilatedDeserialize::header() {
|
||||
VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below
|
||||
if (VL_UNLIKELY(os.readDiffers(VLTSAVE_HEADER_STR, strlen(VLTSAVE_HEADER_STR)))) {
|
||||
string fn = filename();
|
||||
string msg = (string)"Can't deserialize; file has wrong header signature";
|
||||
vl_fatal(filename().c_str(), 0, "", msg.c_str());
|
||||
vl_fatal(fn.c_str(), 0, "", msg.c_str());
|
||||
close();
|
||||
}
|
||||
os.read(Verilated::serializedPtr(), Verilated::serializedSize());
|
||||
@@ -98,8 +100,9 @@ void VerilatedSerialize::trailer() {
|
||||
void VerilatedDeserialize::trailer() {
|
||||
VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below
|
||||
if (VL_UNLIKELY(os.readDiffers(VLTSAVE_TRAILER_STR, strlen(VLTSAVE_TRAILER_STR)))) {
|
||||
string fn = filename();
|
||||
string msg = (string)"Can't deserialize; file has wrong end-of-file signature";
|
||||
vl_fatal(filename().c_str(), 0, "", msg.c_str());
|
||||
vl_fatal(fn.c_str(), 0, "", msg.c_str());
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,8 +172,8 @@ void VerilatedVcd::makeNameMap() {
|
||||
// This comes from user instantiations with no name - IE Vtop("").
|
||||
bool nullScope = false;
|
||||
for (NameMap::iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) {
|
||||
const char* hiername = (*it).first.c_str();
|
||||
if (hiername[0] == '\t') nullScope=true;
|
||||
const string& hiername = it->first;
|
||||
if (hiername.size() >= 1 && hiername[0] == '\t') nullScope=true;
|
||||
}
|
||||
if (nullScope) {
|
||||
NameMap* newmapp = new NameMap;
|
||||
@@ -352,7 +352,8 @@ void VerilatedVcd::dumpHeader () {
|
||||
printStr("$date "); printStr(ctime(&time_str)); printStr(" $end\n");
|
||||
|
||||
printStr("$timescale ");
|
||||
printStr(doubleToTimescale(m_timeRes).c_str());
|
||||
const string& timeResStr = doubleToTimescale(m_timeRes);
|
||||
printStr(timeResStr.c_str());
|
||||
printStr(" $end\n");
|
||||
|
||||
makeNameMap();
|
||||
@@ -370,10 +371,11 @@ void VerilatedVcd::dumpHeader () {
|
||||
// Print the signal names
|
||||
const char* lastName = "";
|
||||
for (NameMap::iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) {
|
||||
const char* hiername = (*it).first.c_str();
|
||||
const char* decl = (*it).second.c_str();
|
||||
const string& hiernamestr = it->first;
|
||||
const string& decl = it->second;
|
||||
|
||||
// Determine difference between the old and new names
|
||||
const char* hiername = hiernamestr.c_str();
|
||||
const char* lp = lastName;
|
||||
const char* np = hiername;
|
||||
lastName = hiername;
|
||||
@@ -408,7 +410,7 @@ void VerilatedVcd::dumpHeader () {
|
||||
}
|
||||
|
||||
printIndent(0);
|
||||
printStr(decl);
|
||||
printStr(decl.c_str());
|
||||
}
|
||||
|
||||
while (m_modDepth>1) {
|
||||
|
||||
+8
-15
@@ -259,10 +259,11 @@ public:
|
||||
virtual const vluint32_t type() { return vpiIterator; }
|
||||
virtual vpiHandle dovpi_scan() {
|
||||
if (VL_LIKELY(m_scopep->varsp())) {
|
||||
if (VL_UNLIKELY(!m_started)) { m_it = m_scopep->varsp()->begin(); m_started=true; }
|
||||
else if (VL_UNLIKELY(m_it == m_scopep->varsp()->end())) return 0;
|
||||
VerilatedVarNameMap* varsp = m_scopep->varsp();
|
||||
if (VL_UNLIKELY(!m_started)) { m_it = varsp->begin(); m_started=true; }
|
||||
else if (VL_UNLIKELY(m_it == varsp->end())) return 0;
|
||||
else ++m_it;
|
||||
if (m_it == m_scopep->varsp()->end()) return 0;
|
||||
if (m_it == varsp->end()) return 0;
|
||||
return ((new VerilatedVpioVar(&(m_it->second), m_scopep))
|
||||
->castVpiHandle());
|
||||
} else {
|
||||
@@ -430,15 +431,10 @@ class VerilatedVpiError {
|
||||
t_vpi_error_info m_errorInfo;
|
||||
bool m_flag;
|
||||
char m_buff[VL_VPI_LINE_SIZE];
|
||||
void setError(PLI_BYTE8 *message, PLI_BYTE8 *file, PLI_INT32 line) {
|
||||
void setError(PLI_BYTE8 *message, PLI_BYTE8 *code, PLI_BYTE8 *file, PLI_INT32 line) {
|
||||
m_errorInfo.message = message;
|
||||
m_errorInfo.file = file;
|
||||
m_errorInfo.line = line;
|
||||
m_errorInfo.code = NULL;
|
||||
do_callbacks();
|
||||
}
|
||||
void setError(PLI_BYTE8 *message, PLI_BYTE8 *code, PLI_BYTE8 *file, PLI_INT32 line) {
|
||||
setError( message, file, line);
|
||||
m_errorInfo.code = code;
|
||||
do_callbacks();
|
||||
}
|
||||
@@ -464,14 +460,11 @@ public:
|
||||
return this;
|
||||
}
|
||||
void setMessage(string file, PLI_INT32 line, string message, ...) {
|
||||
static VL_THREAD string filehold;
|
||||
_VL_VPI_ERROR_SET;
|
||||
m_errorInfo.state = vpiPLI;
|
||||
setError((PLI_BYTE8*)m_buff, (PLI_BYTE8*)file.c_str(), line);
|
||||
}
|
||||
void setMessage(PLI_BYTE8 *code, PLI_BYTE8 *file, PLI_INT32 line, string message, ...) {
|
||||
_VL_VPI_ERROR_SET;
|
||||
m_errorInfo.state = vpiPLI;
|
||||
setError((PLI_BYTE8*)message.c_str(), code, file, line);
|
||||
filehold = file;
|
||||
setError((PLI_BYTE8*)m_buff, NULL, (PLI_BYTE8*)filehold.c_str(), line);
|
||||
}
|
||||
p_vpi_error_info getError() {
|
||||
if (m_flag) return &m_errorInfo;
|
||||
|
||||
+2
-2
@@ -915,8 +915,8 @@ ostream& operator<<(ostream& os, V3Hash rhs) {
|
||||
|
||||
V3Hash::V3Hash(const string& name) {
|
||||
uint32_t val = 0;
|
||||
for (const char* c=name.c_str(); *c; c++) {
|
||||
val = val*31 + *c;
|
||||
for (string::const_iterator it = name.begin(); it!=name.end(); ++it) {
|
||||
val = val*31 + *it;
|
||||
}
|
||||
setBoth(1,val);
|
||||
}
|
||||
|
||||
+19
-2
@@ -163,6 +163,19 @@ public:
|
||||
virtual bool same(AstNode* samep) const { return true; }
|
||||
};
|
||||
|
||||
struct AstGatePin : public AstNodeMath {
|
||||
// Possibly expand a gate primitive input pin value to match the range of the gate primitive
|
||||
AstGatePin(FileLine* fl, AstNode* lhsp, AstRange* rangep) : AstNodeMath(fl) {
|
||||
setOp1p(lhsp); setOp2p(rangep);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(GatePin, GATEPIN)
|
||||
virtual string emitVerilog() { return "%l"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual bool cleanOut() { return true; }
|
||||
AstNode* exprp() const { return op1p(); } // op1 = Pin expression
|
||||
AstRange* rangep() const { return op2p()->castRange(); } // op2 = Range of pin
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
//==== Data Types
|
||||
|
||||
@@ -3181,9 +3194,11 @@ struct AstExtendS : public AstNodeUniop {
|
||||
// Expand a value into a wider entity by sign extension. Width is implied from nodep->width()
|
||||
AstExtendS(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {}
|
||||
AstExtendS(FileLine* fl, AstNode* lhsp, int width) : AstNodeUniop(fl, lhsp) {
|
||||
// Important that widthMin be correct, as opExtend requires it after V3Expand
|
||||
dtypeSetLogicSized(width,width,AstNumeric::UNSIGNED); }
|
||||
ASTNODE_NODE_FUNCS(ExtendS, EXTENDS)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opExtendS(lhs); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) {
|
||||
out.opExtendS(lhs, lhsp()->widthMin()); }
|
||||
virtual string emitVerilog() { return "%l"; }
|
||||
virtual string emitC() { return "VL_EXTENDS_%nq%lq(%nw,%lw, %P, %li)"; }
|
||||
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return true;}
|
||||
@@ -3863,10 +3878,12 @@ struct AstShiftRS : public AstNodeBiop {
|
||||
// Output data type's width determines which bit is used for sign extension
|
||||
AstShiftRS(FileLine* fl, AstNode* lhsp, AstNode* rhsp, int setwidth=0)
|
||||
: AstNodeBiop(fl, lhsp, rhsp) {
|
||||
// Important that widthMin be correct, as opExtend requires it after V3Expand
|
||||
if (setwidth) { dtypeSetLogicSized(setwidth,setwidth,AstNumeric::SIGNED); }
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(ShiftRS, SHIFTRS)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opShiftRS(lhs,rhs); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) {
|
||||
out.opShiftRS(lhs,rhs,lhsp()->widthMin()); }
|
||||
virtual string emitVerilog() { return "%k(%l %f>>> %r)"; }
|
||||
virtual string emitC() { return "VL_SHIFTRS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return ""; }
|
||||
|
||||
+11
-9
@@ -83,17 +83,19 @@ private:
|
||||
void genChangeDet(AstVarScope* vscp) {
|
||||
AstVar* varp = vscp->varp();
|
||||
vscp->v3warn(IMPERFECTSCH,"Imperfect scheduling of variable: "<<vscp);
|
||||
AstUnpackArrayDType* arrayp = varp->dtypeSkipRefp()->castUnpackArrayDType();
|
||||
AstUnpackArrayDType* uarrayp = varp->dtypeSkipRefp()->castUnpackArrayDType();
|
||||
AstPackArrayDType* parrayp = varp->dtypeSkipRefp()->castPackArrayDType();
|
||||
AstNodeClassDType *classp = varp->dtypeSkipRefp()->castNodeClassDType();
|
||||
bool isArray = arrayp;
|
||||
bool isUnpackArray = uarrayp;
|
||||
bool isPackArray = parrayp;
|
||||
bool isClass = classp && classp->packedUnsup();
|
||||
int elements = isArray ? arrayp->elementsConst() : 1;
|
||||
if (isArray && (elements > DETECTARRAY_MAX_INDEXES)) {
|
||||
int elements = isUnpackArray ? uarrayp->elementsConst() : 1;
|
||||
if (isUnpackArray && (elements > DETECTARRAY_MAX_INDEXES)) {
|
||||
vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect more than "<<cvtToStr(DETECTARRAY_MAX_INDEXES)
|
||||
<<" array indexes (probably with UNOPTFLAT warning suppressed): "<<varp->prettyName()<<endl
|
||||
<<vscp->warnMore()
|
||||
<<"... Could recompile with DETECTARRAY_MAX_INDEXES increased to at least "<<cvtToStr(elements));
|
||||
} else if (!isArray && !isClass
|
||||
} else if (!isUnpackArray && !isClass && !isPackArray
|
||||
&& !varp->dtypeSkipRefp()->castBasicDType()) {
|
||||
if (debug()) varp->dumpTree(cout,"-DETECTARRAY-");
|
||||
vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable (probably with UNOPTFLAT warning suppressed): "<<varp->prettyName());
|
||||
@@ -110,17 +112,17 @@ private:
|
||||
for (int index=0; index<elements; ++index) {
|
||||
AstChangeDet* changep
|
||||
= new AstChangeDet (vscp->fileline(),
|
||||
aselIfNeeded(isArray, index,
|
||||
aselIfNeeded(isUnpackArray, index,
|
||||
new AstVarRef(vscp->fileline(), vscp, false)),
|
||||
aselIfNeeded(isArray, index,
|
||||
aselIfNeeded(isUnpackArray, index,
|
||||
new AstVarRef(vscp->fileline(), newvscp, false)),
|
||||
false);
|
||||
m_chgFuncp->addStmtsp(changep);
|
||||
AstAssign* initp
|
||||
= new AstAssign (vscp->fileline(),
|
||||
aselIfNeeded(isArray, index,
|
||||
aselIfNeeded(isUnpackArray, index,
|
||||
new AstVarRef(vscp->fileline(), newvscp, true)),
|
||||
aselIfNeeded(isArray, index,
|
||||
aselIfNeeded(isUnpackArray, index,
|
||||
new AstVarRef(vscp->fileline(), vscp, false)));
|
||||
m_chgFuncp->addFinalsp(initp);
|
||||
}
|
||||
|
||||
+6
-3
@@ -274,6 +274,8 @@ private:
|
||||
// We can only get rid of a<<b>>c or a<<b<<c, with constant b & c
|
||||
// because bits may be masked in that process, or (b+c) may exceed the word width.
|
||||
if (!(nodep->rhsp()->castConst() && lhsp->rhsp()->castConst())) return false;
|
||||
if (nodep->rhsp()->castConst()->num().isFourState()
|
||||
|| lhsp->rhsp()->castConst()->num().isFourState()) return false;
|
||||
if (nodep->width()!=lhsp->width()) return false;
|
||||
if (nodep->width()!=lhsp->lhsp()->width()) return false;
|
||||
return true;
|
||||
@@ -1694,8 +1696,9 @@ private:
|
||||
string fmt = "";
|
||||
bool inPct = false;
|
||||
AstNode* argp = nodep->exprsp();
|
||||
for (const char* inp = nodep->text().c_str(); *inp; inp++) {
|
||||
char ch = *inp; // Breaks with iterators...
|
||||
string text = nodep->text();
|
||||
for (string::const_iterator it = text.begin(); it!=text.end(); ++it) {
|
||||
char ch = *it;
|
||||
if (!inPct && ch=='%') {
|
||||
inPct = true;
|
||||
fmt = ch;
|
||||
@@ -2068,7 +2071,7 @@ private:
|
||||
TREEOP ("AstAnd {operandShiftSame(nodep)}", "replaceShiftSame(nodep)");
|
||||
TREEOP ("AstOr {operandShiftSame(nodep)}", "replaceShiftSame(nodep)");
|
||||
TREEOP ("AstXor {operandShiftSame(nodep)}", "replaceShiftSame(nodep)");
|
||||
TREEOP ("AstXnor{operandShiftSame(nodep)}", "replaceShiftSame(nodep)");
|
||||
// "AstXnor{operandShiftSame(nodep)}", // Cannot ShiftSame as the shifted-in zeros might create a one
|
||||
// Note can't simplify a extend{extends}, extends{extend}, as the sign bits end up in the wrong places
|
||||
TREEOPV("AstExtend {$lhsp.castExtend}", "replaceExtend(nodep, nodep->lhsp()->castExtend()->lhsp())");
|
||||
TREEOPV("AstExtendS{$lhsp.castExtendS}", "replaceExtend(nodep, nodep->lhsp()->castExtendS()->lhsp())");
|
||||
|
||||
+15
-12
@@ -246,12 +246,14 @@ public:
|
||||
char format = '?';
|
||||
bool pct=false;
|
||||
int got=0;
|
||||
for (const char* cp = nodep->text().c_str(); *cp; cp++) {
|
||||
string txt = nodep->text();
|
||||
for (string::const_iterator it=txt.begin(); it!=txt.end(); ++it) {
|
||||
char ch = *it;
|
||||
if (pct) {
|
||||
pct = false;
|
||||
switch (tolower(*cp)) {
|
||||
switch (tolower(ch)) {
|
||||
case '%':
|
||||
prefix += *cp;
|
||||
prefix += ch;
|
||||
break;
|
||||
case 'd': // FALLTHRU
|
||||
case 'o': // FALLTHRU
|
||||
@@ -259,22 +261,22 @@ public:
|
||||
case 'x': // FALLTHRU
|
||||
case 'b': // FALLTHRU
|
||||
case 's':
|
||||
got++; format = tolower(*cp);
|
||||
got++; format = tolower(ch);
|
||||
break;
|
||||
case 'e': // FALLTHRU
|
||||
case 'f': // FALLTHRU
|
||||
case 'g':
|
||||
got++; format = tolower(*cp);
|
||||
nodep->v3error("Unsupported $value$plusargs format qualifier: '"<<*cp<<"'"<<endl);
|
||||
got++; format = tolower(ch);
|
||||
nodep->v3error("Unsupported $value$plusargs format qualifier: '"<<ch<<"'"<<endl);
|
||||
break;
|
||||
default:
|
||||
got++;
|
||||
nodep->v3error("Illegal $value$plusargs format qualifier: '"<<*cp<<"'"<<endl);
|
||||
nodep->v3error("Illegal $value$plusargs format qualifier: '"<<ch<<"'"<<endl);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (*cp == '%') pct = true;
|
||||
else prefix += *cp;
|
||||
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");
|
||||
@@ -622,8 +624,9 @@ public:
|
||||
// Only 32 bits - llx + long long here just to appease CPP format warning
|
||||
if (num<10) puts(cvtToStr(num));
|
||||
else ofp()->printf("0x%" VL_PRI64 "x", (vluint64_t)num);
|
||||
//Unneeded-Causes %lx format warnings:
|
||||
// if (!nodep->num().isSigned() && (num & (1UL<<31))) puts("U");
|
||||
// If signed, we'll do our own functions
|
||||
// But must be here, or <= comparisons etc may end up signed
|
||||
puts("U");
|
||||
}
|
||||
}
|
||||
void emitSetVarConstant(const string& assignString, AstConst* constp) {
|
||||
@@ -1381,7 +1384,7 @@ void EmitCImp::emitVarResets(AstNodeModule* modp) {
|
||||
}
|
||||
bool zeroit = (varp->attrFileDescr() // Zero it out, so we don't core dump if never call $fopen
|
||||
|| (varp->basicp() && varp->basicp()->isZeroInit())
|
||||
|| (varp->name().c_str()[0]=='_' && v3Global.opt.underlineZero()));
|
||||
|| (varp->name().size()>=1 && varp->name()[0]=='_' && v3Global.opt.underlineZero()));
|
||||
if (varp->isWide()) {
|
||||
// DOCUMENT: We randomize everything. If the user wants a _var to be zero,
|
||||
// there should be a initial statement. (Different from verilator2.)
|
||||
|
||||
+2
-1
@@ -383,7 +383,8 @@ void EmitCSyms::emitSymImp() {
|
||||
AstScope* scopep = it->first; AstNodeModule* modp = it->second;
|
||||
if (modp->isTop()) {
|
||||
} else {
|
||||
ofp()->printf("\t%c %-30s ", comma, scopep->nameDotless().c_str());
|
||||
string nameDl = scopep->nameDotless();
|
||||
ofp()->printf("\t%c %-30s ", comma, nameDl.c_str());
|
||||
puts("(Verilated::catName(topp->name(),");
|
||||
// The "." is added by catName
|
||||
putsQuoted(scopep->prettyName());
|
||||
|
||||
+7
-8
@@ -164,16 +164,16 @@ public:
|
||||
|
||||
of.puts("# User CFLAGS (from -CFLAGS on Verilator command line)\n");
|
||||
of.puts("VM_USER_CFLAGS = \\\n");
|
||||
for (V3StringSet::const_iterator it = v3Global.opt.cFlags().begin();
|
||||
it != v3Global.opt.cFlags().end(); ++it) {
|
||||
const V3StringSet& cFlags = v3Global.opt.cFlags();
|
||||
for (V3StringSet::const_iterator it = cFlags.begin(); it != cFlags.end(); ++it) {
|
||||
of.puts("\t"+*it+" \\\n");
|
||||
}
|
||||
of.puts("\n");
|
||||
|
||||
of.puts("# User LDLIBS (from -LDFLAGS on Verilator command line)\n");
|
||||
of.puts("VM_USER_LDLIBS = \\\n");
|
||||
for (V3StringSet::const_iterator it = v3Global.opt.ldLibs().begin();
|
||||
it != v3Global.opt.ldLibs().end(); ++it) {
|
||||
const V3StringSet& ldLibs = v3Global.opt.ldLibs();
|
||||
for (V3StringSet::const_iterator it = ldLibs.begin(); it != ldLibs.end(); ++it) {
|
||||
of.puts("\t"+*it+" \\\n");
|
||||
}
|
||||
of.puts("\n");
|
||||
@@ -181,8 +181,8 @@ public:
|
||||
V3StringSet dirs;
|
||||
of.puts("# User .cpp files (from .cpp's on Verilator command line)\n");
|
||||
of.puts("VM_USER_CLASSES = \\\n");
|
||||
for (V3StringSet::const_iterator it = v3Global.opt.cppFiles().begin();
|
||||
it != v3Global.opt.cppFiles().end(); ++it) {
|
||||
const V3StringSet& cppFiles = v3Global.opt.cppFiles();
|
||||
for (V3StringSet::const_iterator it = cppFiles.begin(); it != cppFiles.end(); ++it) {
|
||||
string cppfile = *it;
|
||||
of.puts("\t"+V3Options::filenameNonExt(cppfile)+" \\\n");
|
||||
string dir = V3Options::filenameDir(cppfile);
|
||||
@@ -207,8 +207,7 @@ public:
|
||||
of.puts("\n### Executable rules... (from --exe)\n");
|
||||
of.puts("VPATH += $(VM_USER_DIR)\n");
|
||||
of.puts("\n");
|
||||
for (V3StringSet::const_iterator it = v3Global.opt.cppFiles().begin();
|
||||
it != v3Global.opt.cppFiles().end(); ++it) {
|
||||
for (V3StringSet::const_iterator it = cppFiles.begin(); it != cppFiles.end(); ++it) {
|
||||
string cppfile = *it;
|
||||
string basename = V3Options::filenameNonExt(cppfile);
|
||||
of.puts(basename+".o: "+cppfile+"\n");
|
||||
|
||||
@@ -253,6 +253,7 @@ void FileLine::warnStyleOff(bool flag) {
|
||||
|
||||
bool FileLine::warnIsOff(V3ErrorCode code) const {
|
||||
if (!m_warnOn.test(code)) return true;
|
||||
if (!defaultFileLine().m_warnOn.test(code)) return true; // Global overrides local
|
||||
// UNOPTFLAT implies UNOPT
|
||||
if (code==V3ErrorCode::UNOPT && !m_warnOn.test(V3ErrorCode::UNOPTFLAT)) return true;
|
||||
if ((code.lintError() || code.styleError()) && !m_warnOn.test(V3ErrorCode::I_LINT)) return true;
|
||||
|
||||
+3
-2
@@ -144,9 +144,10 @@ public:
|
||||
// Warnings we'll present to the user as errors
|
||||
// Later -Werror- options may make more of these.
|
||||
bool pretendError() const { return ( m_e==ASSIGNIN || m_e==BLKANDNBLK
|
||||
|| m_e==IMPURE || m_e==MODDUP || m_e==SYMRSVDWORD); }
|
||||
|| m_e==IMPURE || m_e==MODDUP); }
|
||||
// Warnings to mention manual
|
||||
bool mentionManual() const { return ( m_e==EC_FATALSRC || pretendError() ); }
|
||||
bool mentionManual() const { return ( m_e==EC_FATALSRC || m_e==SYMRSVDWORD
|
||||
|| pretendError() ); }
|
||||
|
||||
// Warnings that are lint only
|
||||
bool lintError() const { return ( m_e==ALWCOMBORDER
|
||||
|
||||
+2
-2
@@ -448,8 +448,8 @@ private:
|
||||
AstNode* newp = new AstShiftR (nodep->fileline(),
|
||||
fromp,
|
||||
dropCondBound(lsbp),
|
||||
nodep->width());
|
||||
newp->dtypeFrom(nodep);
|
||||
fromp->width()); // {large}>>32 requires 64-bit shift operation; then cast
|
||||
newp->dtypeFrom(fromp);
|
||||
if (!nodep->isQuad() && fromp->isQuad()) {
|
||||
newp = new AstCCast (newp->fileline(), newp, nodep);
|
||||
}
|
||||
|
||||
+11
-6
@@ -71,7 +71,8 @@ class V3FileDependImp {
|
||||
time_t mtime() const { return m_stat.st_mtime; }
|
||||
void loadStats() {
|
||||
if (!m_stat.st_mtime) {
|
||||
int err = stat(filename().c_str(), &m_stat);
|
||||
string fn = filename();
|
||||
int err = stat(fn.c_str(), &m_stat);
|
||||
if (err!=0) {
|
||||
m_stat.st_mtime = 1;
|
||||
// Not a error... This can occur due to `line directives in the .vpp files
|
||||
@@ -258,15 +259,19 @@ bool V3File::checkTimes(const string& filename, const string& cmdline) {
|
||||
return dependImp.checkTimes(filename, cmdline);
|
||||
}
|
||||
|
||||
void V3File::createDir(const string& dirname) {
|
||||
#ifndef _WIN32
|
||||
mkdir(dirname.c_str(), 0777);
|
||||
#else
|
||||
mkdir(dirname.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
void V3File::createMakeDir() {
|
||||
static bool created = false;
|
||||
if (!created) {
|
||||
created = true;
|
||||
#ifndef _WIN32
|
||||
mkdir(v3Global.opt.makeDir().c_str(), 0777);
|
||||
#else
|
||||
mkdir(v3Global.opt.makeDir().c_str());
|
||||
#endif
|
||||
createDir(v3Global.opt.makeDir());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -67,6 +67,7 @@ public:
|
||||
static bool checkTimes(const string& filename, const string& cmdline);
|
||||
|
||||
// Directory utilities
|
||||
static void createDir(const string& dirname);
|
||||
static void createMakeDir();
|
||||
};
|
||||
|
||||
@@ -188,8 +189,8 @@ public:
|
||||
}
|
||||
virtual ~V3OutCFile() {}
|
||||
virtual void putsCellDecl(const string& classname, const string& cellname) {
|
||||
this->printf("%-19s\t%s;\n",
|
||||
(classname + "*").c_str(),cellname.c_str());
|
||||
string classStar = classname + "*";
|
||||
this->printf("%-19s\t%s;\n", classStar.c_str(), cellname.c_str());
|
||||
}
|
||||
virtual void putsHeader() { puts("// Verilated -*- C++ -*-\n"); }
|
||||
virtual void putsIntTopInclude() { }
|
||||
|
||||
+5
-4
@@ -258,8 +258,8 @@ public:
|
||||
if (!m_substTreep) {
|
||||
clearSimple("No assignment found\n");
|
||||
}
|
||||
for (GateVarRefList::const_iterator it = rhsVarRefs().begin();
|
||||
it != rhsVarRefs().end(); ++it) {
|
||||
for (GateVarRefList::const_iterator it = m_rhsVarRefs.begin();
|
||||
it != m_rhsVarRefs.end(); ++it) {
|
||||
if (m_lhsVarRef && m_lhsVarRef->varScopep() == (*it)->varScopep()) {
|
||||
clearSimple("Circular logic\n"); // Oh my, we'll get a UNOPTFLAT much later.
|
||||
}
|
||||
@@ -593,8 +593,9 @@ void GateVisitor::optimizeSignals(bool allowMultiIn) {
|
||||
optimizeElimVar(vvertexp->varScp(), substp, consumerp);
|
||||
// If the new replacement referred to a signal,
|
||||
// Correct the graph to point to this new generating variable
|
||||
for (GateVarRefList::const_iterator it = okVisitor.rhsVarRefs().begin();
|
||||
it != okVisitor.rhsVarRefs().end(); ++it) {
|
||||
const GateVarRefList& rhsVarRefs = okVisitor.rhsVarRefs();
|
||||
for (GateVarRefList::const_iterator it = rhsVarRefs.begin();
|
||||
it != rhsVarRefs.end(); ++it) {
|
||||
AstVarScope* newvarscp = (*it)->varScopep();
|
||||
UINFO(9," Point-to-new vertex "<<newvarscp<<endl);
|
||||
GateVarVertex* varvertexp = makeVarVertex(newvarscp);
|
||||
|
||||
@@ -44,6 +44,7 @@ class V3Global {
|
||||
int m_debugFileNumber; // Number to append to debug files created
|
||||
bool m_assertDTypesResolved; // Tree should have dtypep()'s
|
||||
bool m_assertWidthsMatch; // Tree should have width()==widthMin()
|
||||
bool m_constRemoveXs; // Const needs to strip any Xs
|
||||
bool m_needHInlines; // Need __Inlines file
|
||||
bool m_needHeavy; // Need verilated_heavy.h include
|
||||
bool m_dpi; // Need __Dpi include files
|
||||
@@ -58,6 +59,7 @@ public:
|
||||
m_debugFileNumber = 0;
|
||||
m_assertDTypesResolved = false;
|
||||
m_assertWidthsMatch = false;
|
||||
m_constRemoveXs = false;
|
||||
m_needHInlines = false;
|
||||
m_needHeavy = false;
|
||||
m_dpi = false;
|
||||
@@ -77,6 +79,8 @@ public:
|
||||
static void dumpCheckGlobalTree(const string& filename, int newNumber=0, bool doDump=true);
|
||||
void assertDTypesResolved(bool flag) { m_assertDTypesResolved = flag; }
|
||||
void assertWidthsMatch(bool flag) { m_assertWidthsMatch = flag; }
|
||||
bool constRemoveXs() const { return m_constRemoveXs; }
|
||||
void constRemoveXs(bool flag) { m_constRemoveXs = flag; }
|
||||
string debugFilename(const string& nameComment, int newNumber=0) {
|
||||
++m_debugFileNumber;
|
||||
if (newNumber) m_debugFileNumber = newNumber;
|
||||
|
||||
+3
-3
@@ -266,8 +266,8 @@ public:
|
||||
if (nodep->modp()) nodep->modp()->user1p(symp);
|
||||
checkDuplicate(abovep, nodep, nodep->origName());
|
||||
abovep->reinsert(nodep->origName(), symp);
|
||||
if (abovep != modSymp && !modSymp->findIdFlat(nodep->name())) {
|
||||
// If it's foo_DOT_bar, we need to be able to find it under that too.
|
||||
if (forScopeCreation() && abovep != modSymp && !modSymp->findIdFlat(nodep->name())) {
|
||||
// If it's foo_DOT_bar, we need to be able to find it under "foo_DOT_bar" too.
|
||||
// Duplicates are possible, as until resolve generates might have 2 same cells under an if
|
||||
modSymp->reinsert(nodep->name(), symp);
|
||||
}
|
||||
@@ -1451,6 +1451,7 @@ private:
|
||||
virtual void visit(AstPin* nodep, AstNUser*) {
|
||||
// Pin: Link to submodule's port
|
||||
checkNoDot(nodep);
|
||||
nodep->iterateChildren(*this);
|
||||
if (!nodep->modVarp()) {
|
||||
if (!m_pinSymp) nodep->v3fatalSrc("Pin not under cell?\n");
|
||||
VSymEnt* foundp = m_pinSymp->findIdFlat(nodep->name());
|
||||
@@ -1475,7 +1476,6 @@ private:
|
||||
refp->user5p(nodep);
|
||||
}
|
||||
}
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
// Early return() above when deleted
|
||||
}
|
||||
|
||||
@@ -250,8 +250,8 @@ private:
|
||||
void expectFormat(AstNode* nodep, const string& format, AstNode* argp, bool isScan) {
|
||||
// Check display arguments
|
||||
bool inPct = false;
|
||||
for (const char* inp = format.c_str(); *inp; inp++) {
|
||||
char ch = tolower(*inp); // Breaks with iterators...
|
||||
for (string::const_iterator it = format.begin(); it != format.end(); ++it) {
|
||||
char ch = tolower(*it);
|
||||
if (!inPct && ch=='%') {
|
||||
inPct = true;
|
||||
} else if (inPct) {
|
||||
|
||||
+37
-13
@@ -25,6 +25,7 @@
|
||||
#include <cstdarg>
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
#include "V3Global.h"
|
||||
#include "V3Number.h"
|
||||
|
||||
#define MAX_SPRINTF_DOUBLE_SIZE 100 // Maximum characters with a sprintf %e/%f/%g (probably < 30)
|
||||
@@ -103,7 +104,7 @@ V3Number::V3Number (FileLine* fileline, const char* sourcep) {
|
||||
}
|
||||
// Otherwise...
|
||||
else if (!m_sized) {
|
||||
width(32, false); // Says the spec.
|
||||
width(32, false); // Says IEEE 1800-2012 5.7.1
|
||||
if (unbased) isSigned(true); // Also says the spec.
|
||||
}
|
||||
|
||||
@@ -323,6 +324,7 @@ V3Number& V3Number::setAllBits1() {
|
||||
return *this;
|
||||
}
|
||||
V3Number& V3Number::setAllBitsX() {
|
||||
// Use setAllBitsXRemoved if calling this based on a non-X/Z input value such as divide by zero
|
||||
for (int i=0; i<words(); i++) { m_value[i]=m_valueX[i] = ~0; }
|
||||
opCleanThis();
|
||||
return *this;
|
||||
@@ -332,6 +334,20 @@ V3Number& V3Number::setAllBitsZ() {
|
||||
opCleanThis();
|
||||
return *this;
|
||||
}
|
||||
V3Number& V3Number::setAllBitsXRemoved() {
|
||||
if (!v3Global.constRemoveXs()) {
|
||||
return setAllBitsX();
|
||||
} else {
|
||||
// If we get a divide by zero we get Xs.
|
||||
// But after V3Unknown we have removed Xs, so use --x-assign to direct-insert 0/1
|
||||
if (v3Global.opt.xAssign() == "1") {
|
||||
return setAllBits1();
|
||||
} else {
|
||||
return setAllBits0();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
V3Number& V3Number::setMask(int nbits) {
|
||||
setZero();
|
||||
for (int bit=0; bit<nbits; bit++) { setBit(bit,1); }
|
||||
@@ -1125,21 +1141,29 @@ V3Number& V3Number::opShiftR (const V3Number& lhs, const V3Number& rhs) {
|
||||
if (rhs.isFourState()) return setAllBitsX();
|
||||
setZero();
|
||||
uint32_t rhsval = rhs.toUInt();
|
||||
for (int bit=0; bit<this->width(); bit++) {
|
||||
setBit(bit,lhs.bitIs(bit + rhsval));
|
||||
if (rhsval < (uint32_t)lhs.width()) {
|
||||
for (int bit=0; bit<this->width(); bit++) {
|
||||
setBit(bit,lhs.bitIs(bit + rhsval));
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
V3Number& V3Number::opShiftRS (const V3Number& lhs, const V3Number& rhs) {
|
||||
V3Number& V3Number::opShiftRS (const V3Number& lhs, const V3Number& rhs, uint32_t lbits) {
|
||||
// L(lhs) bit return
|
||||
// The spec says a unsigned >>> still acts as a normal >>.
|
||||
// We presume it is signed; as that's V3Width's job to convert to opShiftR
|
||||
if (rhs.isFourState()) return setAllBitsX();
|
||||
setZero();
|
||||
uint32_t rhsval = rhs.toUInt();
|
||||
for (int bit=0; bit<this->width(); bit++) {
|
||||
setBit(bit,lhs.bitIsExtend(bit + rhsval));
|
||||
if (rhsval < (uint32_t)lhs.width()) {
|
||||
for (int bit=0; bit<this->width(); bit++) {
|
||||
setBit(bit,lhs.bitIsExtend(bit + rhsval, lbits));
|
||||
}
|
||||
} else {
|
||||
for (int bit=0; bit<this->width(); bit++) {
|
||||
setBit(bit,lhs.bitIs(lbits-1));
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -1240,7 +1264,7 @@ V3Number& V3Number::opDiv (const V3Number& lhs, const V3Number& rhs) {
|
||||
UINFO(9, "opdiv "<<lhs<<" "<<rhs<<endl);
|
||||
// i op j, max(L(lhs),L(rhs)) bit return, if any 4-state, 4-state return
|
||||
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
|
||||
if (rhs.isEqZero()) return setAllBitsX();
|
||||
if (rhs.isEqZero()) return setAllBitsXRemoved();
|
||||
if (lhs.width()<=64) {
|
||||
setQuad(lhs.toUQuad() / rhs.toUQuad());
|
||||
return *this;
|
||||
@@ -1253,7 +1277,7 @@ V3Number& V3Number::opDivS (const V3Number& lhs, const V3Number& rhs) {
|
||||
// Signed divide
|
||||
//UINFO(9, ">>divs-start "<<lhs<<" "<<rhs<<endl);
|
||||
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
|
||||
if (rhs.isEqZero()) return setAllBitsX();
|
||||
if (rhs.isEqZero()) return setAllBitsXRemoved();
|
||||
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opNegate(lhs);
|
||||
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opNegate(rhs);
|
||||
V3Number qNoSign = opDiv(lhsNoSign,rhsNoSign);
|
||||
@@ -1270,7 +1294,7 @@ V3Number& V3Number::opDivS (const V3Number& lhs, const V3Number& rhs) {
|
||||
V3Number& V3Number::opModDiv (const V3Number& lhs, const V3Number& rhs) {
|
||||
// i op j, max(L(lhs),L(rhs)) bit return, if any 4-state, 4-state return
|
||||
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
|
||||
if (rhs.isEqZero()) return setAllBitsX();
|
||||
if (rhs.isEqZero()) return setAllBitsXRemoved();
|
||||
if (lhs.width()<=64) {
|
||||
setQuad(lhs.toUQuad() % rhs.toUQuad());
|
||||
return *this;
|
||||
@@ -1282,7 +1306,7 @@ V3Number& V3Number::opModDiv (const V3Number& lhs, const V3Number& rhs) {
|
||||
V3Number& V3Number::opModDivS (const V3Number& lhs, const V3Number& rhs) {
|
||||
// Signed moddiv
|
||||
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
|
||||
if (rhs.isEqZero()) return setAllBitsX();
|
||||
if (rhs.isEqZero()) return setAllBitsXRemoved();
|
||||
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opNegate(lhs);
|
||||
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opNegate(rhs);
|
||||
V3Number qNoSign = opModDiv(lhsNoSign,rhsNoSign);
|
||||
@@ -1420,7 +1444,7 @@ V3Number& V3Number::opPow (const V3Number& lhs, const V3Number& rhs, bool lsign,
|
||||
if (lhs.width()>64) m_fileline->v3fatalSrc("Unsupported: Large >64bit ** power operator not implemented yet: "<<*this);
|
||||
if (rhs.width()>64) m_fileline->v3fatalSrc("Unsupported: Large >64bit ** power operator not implemented yet: "<<*this);
|
||||
if (rsign && rhs.isNegative()) {
|
||||
if (lhs.isEqZero()) return setAllBitsX();
|
||||
if (lhs.isEqZero()) return setAllBitsXRemoved();
|
||||
else if (lhs.isEqOne()) return setQuad(1);
|
||||
else if (lsign && lhs.isEqAllOnes()) {
|
||||
if (rhs.bitIs1(0)) return setAllBits1(); // -1^odd=-1
|
||||
@@ -1473,11 +1497,11 @@ V3Number& V3Number::opAssign (const V3Number& lhs) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
V3Number& V3Number::opExtendS (const V3Number& lhs) {
|
||||
V3Number& V3Number::opExtendS (const V3Number& lhs, uint32_t lbits) {
|
||||
// Note may be a width change during the sign extension
|
||||
setZero();
|
||||
for(int bit=0; bit<this->width(); bit++) {
|
||||
setBit(bit,lhs.bitIsExtend(bit));
|
||||
setBit(bit,lhs.bitIsExtend(bit, lbits));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
+16
-6
@@ -60,15 +60,18 @@ public:
|
||||
}
|
||||
private:
|
||||
char bitIs (int bit) const {
|
||||
if (bit>=m_width) {
|
||||
if (bit>=m_width || bit<0) {
|
||||
// We never sign extend
|
||||
return '0';
|
||||
}
|
||||
return ( "01zx"[(((m_value[bit/32] & (1UL<<(bit&31)))?1:0)
|
||||
| ((m_valueX[bit/32] & (1UL<<(bit&31)))?2:0))] ); }
|
||||
char bitIsExtend (int bit) const {
|
||||
if (bit>=m_width) {
|
||||
bit = m_width-1;
|
||||
char bitIsExtend (int bit, int lbits) const {
|
||||
// lbits usually = width, but for C optimizations width=32_bits, lbits = 32_or_less
|
||||
if (bit<0) return '0';
|
||||
UASSERT(lbits<=m_width, "Extend of wrong size");
|
||||
if (bit>=lbits) {
|
||||
bit = lbits ? lbits-1 : 0;
|
||||
// We do sign extend
|
||||
return ( "01zx"[(((m_value[bit/32] & (1UL<<(bit&31)))?1:0)
|
||||
| ((m_valueX[bit/32] & (1UL<<(bit&31)))?2:0))] );
|
||||
@@ -76,22 +79,28 @@ private:
|
||||
return ( "01zx"[(((m_value[bit/32] & (1UL<<(bit&31)))?1:0)
|
||||
| ((m_valueX[bit/32] & (1UL<<(bit&31)))?2:0))] ); }
|
||||
bool bitIs0 (int bit) const {
|
||||
if (bit<0) return false;
|
||||
if (bit>=m_width) return !bitIsXZ(m_width-1);
|
||||
return ( (m_value[bit/32] & (1UL<<(bit&31)))==0 && !(m_valueX[bit/32] & (1UL<<(bit&31))) ); }
|
||||
bool bitIs1 (int bit) const {
|
||||
if (bit<0) return false;
|
||||
if (bit>=m_width) return false;
|
||||
return ( (m_value[bit/32] & (1UL<<(bit&31))) && !(m_valueX[bit/32] & (1UL<<(bit&31))) ); }
|
||||
bool bitIs1Extend (int bit) const {
|
||||
if (bit<0) return false;
|
||||
if (bit>=m_width) return bitIs1Extend(m_width-1);
|
||||
return ( (m_value[bit/32] & (1UL<<(bit&31))) && !(m_valueX[bit/32] & (1UL<<(bit&31))) ); }
|
||||
bool bitIsX (int bit) const {
|
||||
if (bit<0) return false;
|
||||
if (bit>=m_width) return bitIsZ(m_width-1);
|
||||
return ( (m_value[bit/32] & (1UL<<(bit&31))) && (m_valueX[bit/32] & (1UL<<(bit&31))) ); }
|
||||
bool bitIsXZ(int bit) const {
|
||||
if (bit<0) return false;
|
||||
if (bit>=m_width) return bitIsXZ(m_width-1);
|
||||
return ( (m_valueX[bit/32] & (1UL<<(bit&31))) && 1);
|
||||
}
|
||||
bool bitIsZ (int bit) const {
|
||||
if (bit<0) return false;
|
||||
if (bit>=m_width) return bitIsZ(m_width-1);
|
||||
return ( (~m_value[bit/32] & (1UL<<(bit&31))) && (m_valueX[bit/32] & (1UL<<(bit&31))) ); }
|
||||
uint32_t bitsValue(int lsb, int nbits) const {
|
||||
@@ -136,6 +145,7 @@ public:
|
||||
}
|
||||
|
||||
// SETTERS
|
||||
V3Number& setAllBitsXRemoved();
|
||||
V3Number& setAllBitsX();
|
||||
V3Number& setAllBitsZ();
|
||||
V3Number& setAllBits0();
|
||||
@@ -198,7 +208,7 @@ public:
|
||||
V3Number& opBitsNonZ(const V3Number& lhs); // Z->0, 0/1/X->1
|
||||
//
|
||||
V3Number& opAssign (const V3Number& lhs);
|
||||
V3Number& opExtendS (const V3Number& lhs); // Sign extension
|
||||
V3Number& opExtendS (const V3Number& lhs, uint32_t lbits); // Sign extension
|
||||
V3Number& opRedOr (const V3Number& lhs);
|
||||
V3Number& opRedAnd (const V3Number& lhs);
|
||||
V3Number& opRedXor (const V3Number& lhs);
|
||||
@@ -250,7 +260,7 @@ public:
|
||||
V3Number& opRotR (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opRotL (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opShiftR (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opShiftRS (const V3Number& lhs, const V3Number& rhs); // Arithmetic w/carry
|
||||
V3Number& opShiftRS (const V3Number& lhs, const V3Number& rhs, uint32_t lbits); // Arithmetic w/carry
|
||||
V3Number& opShiftL (const V3Number& lhs, const V3Number& rhs);
|
||||
// Comparisons
|
||||
V3Number& opEq (const V3Number& lhs, const V3Number& rhs);
|
||||
|
||||
+5
-2
@@ -622,13 +622,14 @@ void V3Options::parseOpts (FileLine* fl, int argc, char** argv) {
|
||||
|
||||
// Default certain options and error check
|
||||
// Detailed error, since this is what we often get when run with minimal arguments
|
||||
if (vFiles().empty()) {
|
||||
const V3StringList& vFilesList = vFiles();
|
||||
if (vFilesList.empty()) {
|
||||
v3fatal("verilator: No Input Verilog file specified on command line, see verilator --help for more information\n");
|
||||
}
|
||||
|
||||
// Default prefix to the filename
|
||||
if (prefix()=="" && topModule()!="") m_prefix = string("V")+topModule();
|
||||
if (prefix()=="") m_prefix = string("V")+filenameNonExt(*(vFiles().begin()));
|
||||
if (prefix()=="" && vFilesList.size()>=1) m_prefix = string("V")+filenameNonExt(*(vFilesList.begin()));
|
||||
if (modPrefix()=="") m_modPrefix = prefix();
|
||||
|
||||
// Find files in makedir
|
||||
@@ -712,6 +713,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||
else if ( !strcmp (sw, "-E") ) { m_preprocOnly = true; }
|
||||
else if ( onoff (sw, "-MMD", flag/*ref*/) ) { m_makeDepend = flag; }
|
||||
else if ( onoff (sw, "-MP", flag/*ref*/) ) { m_makePhony = flag; }
|
||||
else if ( !strcmp (sw, "-P") ) { m_preprocNoLine = true; }
|
||||
else if ( onoff (sw, "-assert", flag/*ref*/) ) { m_assert = flag; }
|
||||
else if ( onoff (sw, "-autoflush", flag/*ref*/) ) { m_autoflush = flag; }
|
||||
else if ( onoff (sw, "-bbox-sys", flag/*ref*/) ) { m_bboxSys = flag; }
|
||||
@@ -1212,6 +1214,7 @@ V3Options::V3Options() {
|
||||
m_pinsBv = 65;
|
||||
m_profileCFuncs = false;
|
||||
m_preprocOnly = false;
|
||||
m_preprocNoLine = false;
|
||||
m_psl = false;
|
||||
m_public = false;
|
||||
m_savable = false;
|
||||
|
||||
@@ -59,6 +59,7 @@ class V3Options {
|
||||
bool m_preprocOnly; // main switch: -E
|
||||
bool m_makeDepend; // main switch: -MMD
|
||||
bool m_makePhony; // main switch: -MP
|
||||
bool m_preprocNoLine;// main switch: -P
|
||||
bool m_assert; // main switch: --assert
|
||||
bool m_autoflush; // main switch: --autoflush
|
||||
bool m_bboxSys; // main switch: --bbox-sys
|
||||
@@ -192,6 +193,7 @@ class V3Options {
|
||||
bool preprocOnly() const { return m_preprocOnly; }
|
||||
bool makeDepend() const { return m_makeDepend; }
|
||||
bool makePhony() const { return m_makePhony; }
|
||||
bool preprocNoLine() const { return m_preprocNoLine; }
|
||||
bool underlineZero() const { return m_underlineZero; }
|
||||
string bin() const { return m_bin; }
|
||||
string flags() const { return m_flags; }
|
||||
|
||||
+2
-2
@@ -1191,14 +1191,14 @@ void OrderVisitor::processMove() {
|
||||
while (!m_pomReadyDomScope.empty()) {
|
||||
// Start with top node on ready list's domain & scope
|
||||
OrderMoveDomScope* domScopep = m_pomReadyDomScope.begin();
|
||||
OrderMoveVertex* topVertexp = domScopep->readyVertices().begin();
|
||||
OrderMoveVertex* topVertexp = domScopep->readyVertices().begin(); // lintok-begin-on-ref
|
||||
UASSERT(topVertexp, "domScope on ready list without any nodes ready under it");
|
||||
// Work on all scopes ready inside this domain
|
||||
while (domScopep) {
|
||||
UINFO(6," MoveDomain l="<<domScopep->domainp()<<endl);
|
||||
// Process all nodes ready under same domain & scope
|
||||
m_pomNewFuncp = NULL;
|
||||
while (OrderMoveVertex* vertexp = domScopep->readyVertices().begin()) {
|
||||
while (OrderMoveVertex* vertexp = domScopep->readyVertices().begin()) { // lintok-begin-on-ref
|
||||
processMoveOne(vertexp, domScopep, 1);
|
||||
}
|
||||
// Done with scope/domain pair, pick new scope under same domain, or NULL if none left
|
||||
|
||||
@@ -123,6 +123,7 @@ void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool i
|
||||
string vppfilename = v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"_"+modname+".vpp";
|
||||
ofstream* ofp = NULL;
|
||||
ostream* osp;
|
||||
bool noblanks = v3Global.opt.preprocOnly() && v3Global.opt.preprocNoLine();
|
||||
if (v3Global.opt.preprocOnly()) {
|
||||
osp = &cout;
|
||||
} else {
|
||||
@@ -133,6 +134,13 @@ void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool i
|
||||
return;
|
||||
} else {
|
||||
for (deque<string>::iterator it = m_ppBuffers.begin(); it!=m_ppBuffers.end(); ++it) {
|
||||
if (noblanks) {
|
||||
bool blank = true;
|
||||
for (string::iterator its = it->begin(); its != it->end(); ++its) {
|
||||
if (!isspace(*its) && *its!='\n') { blank=false; break; }
|
||||
}
|
||||
if (blank) continue;
|
||||
}
|
||||
*osp << *it;
|
||||
}
|
||||
if (ofp) {
|
||||
|
||||
+1
-1
@@ -107,7 +107,7 @@ psl [p]sl
|
||||
|
||||
/* Optional directives we recognize */
|
||||
<INITIAL>"`__FILE__" { static string rtnfile;
|
||||
rtnfile = '"'; rtnfile += LEXP->curFilelinep()->filename().c_str();
|
||||
rtnfile = '"'; rtnfile += LEXP->curFilelinep()->filename();
|
||||
rtnfile += '"'; yytext=(char*)rtnfile.c_str(); yyleng = rtnfile.length();
|
||||
return (VP_STRING); }
|
||||
<INITIAL>"`__LINE__" { static char buf[10];
|
||||
|
||||
+15
-9
@@ -566,7 +566,8 @@ string V3PreProcImp::defineSubst(V3DefineRef* refp) {
|
||||
bool quote = false;
|
||||
bool haveDefault = false;
|
||||
// Note there's a leading ( and trailing ), so parens==1 is the base parsing level
|
||||
const char* cp=refp->params().c_str();
|
||||
string params = refp->params(); // Must keep in scope
|
||||
const char* cp=params.c_str();
|
||||
if (*cp == '(') cp++;
|
||||
for (; *cp; cp++) {
|
||||
//UINFO(4," Parse Paren="<<paren<<" Arg="<<numArgs<<" token='"<<token<<"' Parse="<<cp<<endl);
|
||||
@@ -1367,9 +1368,11 @@ int V3PreProcImp::getFinalToken(string& buf) {
|
||||
}
|
||||
int tok = m_finToken;
|
||||
buf = m_finBuf;
|
||||
if (0 && debug()>=5) fprintf (stderr,"%d: FIN: %-10s: %s\n",
|
||||
m_lexp->m_tokFilelinep->lineno(),
|
||||
tokenName(tok), V3PreLex::cleanDbgStrg(buf).c_str());
|
||||
if (0 && debug()>=5) {
|
||||
string bufcln = V3PreLex::cleanDbgStrg(buf);
|
||||
fprintf (stderr,"%d: FIN: %-10s: %s\n",
|
||||
m_lexp->m_tokFilelinep->lineno(), tokenName(tok), bufcln.c_str());
|
||||
}
|
||||
// Track `line
|
||||
const char* bufp = buf.c_str();
|
||||
while (*bufp == '\n') bufp++;
|
||||
@@ -1400,7 +1403,7 @@ int V3PreProcImp::getFinalToken(string& buf) {
|
||||
}
|
||||
}
|
||||
// Track newlines in prep for next token
|
||||
for (const char* cp = buf.c_str(); *cp; cp++) {
|
||||
for (string::iterator cp=buf.begin(); cp!=buf.end(); ++cp) {
|
||||
if (*cp == '\n') {
|
||||
m_finAtBol = true;
|
||||
m_finFilelinep->linenoIncInPlace(); // Increment in place to avoid new/delete calls. It's private data.
|
||||
@@ -1422,8 +1425,9 @@ string V3PreProcImp::getline() {
|
||||
string buf;
|
||||
int tok = getFinalToken(buf/*ref*/);
|
||||
if (debug()>=5) {
|
||||
string bufcln = V3PreLex::cleanDbgStrg(buf);
|
||||
fprintf (stderr,"%d: GETFETC: %-10s: %s\n",
|
||||
m_lexp->m_tokFilelinep->lineno(), tokenName(tok), V3PreLex::cleanDbgStrg(buf).c_str());
|
||||
m_lexp->m_tokFilelinep->lineno(), tokenName(tok), bufcln.c_str());
|
||||
}
|
||||
if (tok==VP_EOF) {
|
||||
// Add a final newline, if the user forgot the final \n.
|
||||
@@ -1444,8 +1448,10 @@ string V3PreProcImp::getline() {
|
||||
int len = rtnp-m_lineChars.c_str()+1;
|
||||
string theLine(m_lineChars, 0, len);
|
||||
m_lineChars = m_lineChars.erase(0,len); // Remove returned characters
|
||||
if (debug()>=4) fprintf (stderr,"%d: GETLINE: %s\n",
|
||||
m_lexp->m_tokFilelinep->lineno(),
|
||||
V3PreLex::cleanDbgStrg(theLine).c_str());
|
||||
if (debug()>=4) {
|
||||
string lncln = V3PreLex::cleanDbgStrg(theLine);
|
||||
fprintf (stderr,"%d: GETLINE: %s\n",
|
||||
m_lexp->m_tokFilelinep->lineno(), lncln.c_str());
|
||||
}
|
||||
return theLine;
|
||||
}
|
||||
|
||||
+3
-1
@@ -71,7 +71,9 @@ public:
|
||||
// These options control how the parsing proceeds
|
||||
static int keepComments() { return 2; } // Return comments, 0=no, 1=yes, 2=callback
|
||||
static bool keepWhitespace() { return false; }
|
||||
static bool lineDirectives() { return true; } // Insert `line directives
|
||||
static bool lineDirectives() { // Insert `line directives
|
||||
return !(v3Global.opt.preprocOnly() && v3Global.opt.preprocNoLine());
|
||||
}
|
||||
static bool pedantic() { return false; } // Obey standard; Don't substitute `error
|
||||
static bool optPsl();
|
||||
|
||||
|
||||
+1
-1
@@ -73,7 +73,7 @@ private:
|
||||
return "Verilator trace_off";
|
||||
}
|
||||
else if (!v3Global.opt.traceUnderscore()) {
|
||||
if (prettyName.c_str()[0] == '_')
|
||||
if (prettyName.size()>=1 && prettyName[0] == '_')
|
||||
return "Leading underscore";
|
||||
if (prettyName.find("._") != string::npos)
|
||||
return "Inlined leading underscore";
|
||||
|
||||
+12
-12
@@ -579,29 +579,29 @@ class TristateVisitor : public TristateBaseVisitor {
|
||||
nodep->addStmtp(enassp);
|
||||
|
||||
// now append this driver to the driver logic.
|
||||
AstNode* ref1p = new AstVarRef(nodep->fileline(), newlhsp,false);
|
||||
AstNode* ref2p = new AstVarRef(nodep->fileline(), newenp, false);
|
||||
andp = new AstAnd(nodep->fileline(), ref1p, ref2p);
|
||||
AstNode* ref1p = new AstVarRef(refp->fileline(), newlhsp,false);
|
||||
AstNode* ref2p = new AstVarRef(refp->fileline(), newenp, false);
|
||||
andp = new AstAnd(refp->fileline(), ref1p, ref2p);
|
||||
|
||||
// or this to the others
|
||||
orp = (!orp) ? andp : new AstOr(nodep->fileline(), orp, andp);
|
||||
orp = (!orp) ? andp : new AstOr(refp->fileline(), orp, andp);
|
||||
|
||||
if (envarp) {
|
||||
AstNode* ref3p = new AstVarRef(nodep->fileline(), newenp, false);
|
||||
AstNode* ref3p = new AstVarRef(refp->fileline(), newenp, false);
|
||||
enp = (!enp) ? ref3p : new AstOr(ref3p->fileline(), enp, ref3p);
|
||||
}
|
||||
AstNode* tmp = new AstNot(newenp->fileline(), new AstVarRef(newenp->fileline(), newenp, false));
|
||||
undrivenp = ((!undrivenp) ? tmp
|
||||
: new AstAnd(nodep->fileline(), tmp, undrivenp));
|
||||
: new AstAnd(refp->fileline(), tmp, undrivenp));
|
||||
}
|
||||
if (!undrivenp) { // No drivers on the bus
|
||||
V3Number ones(nodep->fileline(), lhsp->width()); ones.setAllBits1();
|
||||
undrivenp = new AstConst(nodep->fileline(), ones);
|
||||
V3Number ones(invarp->fileline(), lhsp->width()); ones.setAllBits1();
|
||||
undrivenp = new AstConst(invarp->fileline(), ones);
|
||||
}
|
||||
if (!outvarp) {
|
||||
// This is the final resolution of the tristate, so we apply
|
||||
// the pull direction to any undriven pins.
|
||||
V3Number pull(nodep->fileline(), lhsp->width());
|
||||
V3Number pull(invarp->fileline(), lhsp->width());
|
||||
AstPull* pullp = (AstPull*)lhsp->user3p();
|
||||
if (pullp && pullp->direction() == 1) {
|
||||
pull.setAllBits1();
|
||||
@@ -609,9 +609,9 @@ class TristateVisitor : public TristateBaseVisitor {
|
||||
} else {
|
||||
pull.setAllBits0(); // default pull direction is down.
|
||||
}
|
||||
undrivenp = new AstAnd(nodep->fileline(), undrivenp,
|
||||
new AstConst(nodep->fileline(), pull));
|
||||
orp = new AstOr(nodep->fileline(), orp, undrivenp);
|
||||
undrivenp = new AstAnd(invarp->fileline(), undrivenp,
|
||||
new AstConst(invarp->fileline(), pull));
|
||||
orp = new AstOr(invarp->fileline(), orp, undrivenp);
|
||||
} else {
|
||||
undrivenp->deleteTree(); undrivenp=NULL;
|
||||
}
|
||||
|
||||
+4
-3
@@ -145,9 +145,10 @@ public:
|
||||
return isUsedNotDrivenBit(0, m_flags.size()/FLAGS_PER_BIT);
|
||||
}
|
||||
bool unusedMatch(AstVar* nodep) {
|
||||
const char* regexpp = v3Global.opt.unusedRegexp().c_str();
|
||||
if (!regexpp || !*regexpp) return false;
|
||||
return VString::wildmatch(nodep->prettyName().c_str(), regexpp);
|
||||
string regexp = v3Global.opt.unusedRegexp();
|
||||
if (regexp == "") return false;
|
||||
string prettyName = nodep->prettyName();
|
||||
return VString::wildmatch(prettyName.c_str(), regexp.c_str());
|
||||
}
|
||||
void reportViolations() {
|
||||
// Combine bits into overall state
|
||||
|
||||
+175
-75
@@ -163,6 +163,9 @@ private:
|
||||
bool m_doGenerate; // Do errors later inside generate statement
|
||||
int m_dtTables; // Number of created data type tables
|
||||
|
||||
// TYPES
|
||||
typedef map<int,AstPatMember*> PatVecMap;
|
||||
|
||||
// ENUMS
|
||||
enum ExtendRule {
|
||||
EXTEND_EXP, // Extend if expect sign and node signed, e.g. node=y in ADD(x,y), "x + y"
|
||||
@@ -311,8 +314,9 @@ private:
|
||||
// Just once, do the conditional, expect one bit out.
|
||||
iterateCheckBool(nodep,"Conditional Test",nodep->condp(),BOTH);
|
||||
// Determine sub expression widths only relying on what's in the subops
|
||||
nodep->expr1p()->iterateAndNext(*this,WidthVP(CONTEXT,PRELIM).p());
|
||||
nodep->expr2p()->iterateAndNext(*this,WidthVP(CONTEXT,PRELIM).p());
|
||||
// CONTEXT determined, but need data type for pattern assignments
|
||||
nodep->expr1p()->iterateAndNext(*this,WidthVP(vup->c()->dtypeNullp(),PRELIM).p());
|
||||
nodep->expr2p()->iterateAndNext(*this,WidthVP(vup->c()->dtypeNullp(),PRELIM).p());
|
||||
// Calculate width of this expression.
|
||||
// First call (prelim()) vup->c()->width() is probably zero, so we'll return
|
||||
// the size of this subexpression only.
|
||||
@@ -1366,31 +1370,35 @@ private:
|
||||
patp = newpatp;
|
||||
}
|
||||
else {
|
||||
patp->v3error("Assignment pattern missed initializing elements: "<<memp->prettyTypeName());
|
||||
if (!classp->castUnionDType()) {
|
||||
patp->v3error("Assignment pattern missed initializing elements: "<<memp->prettyTypeName());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
patp = it->second;
|
||||
}
|
||||
// Determine initial values
|
||||
vdtypep = memp;
|
||||
patp->dtypep(memp);
|
||||
patp->accept(*this,WidthVP(memp,BOTH).p());
|
||||
// Convert to concat for now
|
||||
AstNode* valuep = patp->lhssp()->unlinkFrBack();
|
||||
if (valuep->castConst()) {
|
||||
// Forming a AstConcat will cause problems with unsized (uncommitted sized) constants
|
||||
if (AstNode* newp = WidthCommitVisitor::newIfConstCommitSize(valuep->castConst())) {
|
||||
pushDeletep(valuep); valuep=NULL;
|
||||
valuep = newp;
|
||||
if (patp) {
|
||||
// Determine initial values
|
||||
vdtypep = memp;
|
||||
patp->dtypep(memp);
|
||||
patp->accept(*this,WidthVP(memp,BOTH).p());
|
||||
// Convert to concat for now
|
||||
AstNode* valuep = patp->lhssp()->unlinkFrBack();
|
||||
if (valuep->castConst()) {
|
||||
// Forming a AstConcat will cause problems with unsized (uncommitted sized) constants
|
||||
if (AstNode* newp = WidthCommitVisitor::newIfConstCommitSize(valuep->castConst())) {
|
||||
pushDeletep(valuep); valuep=NULL;
|
||||
valuep = newp;
|
||||
}
|
||||
}
|
||||
if (!newp) newp = valuep;
|
||||
else {
|
||||
AstConcat* concatp = new AstConcat(patp->fileline(), newp, valuep);
|
||||
newp = concatp;
|
||||
newp->dtypeSetLogicSized(concatp->lhsp()->width()+concatp->rhsp()->width(),
|
||||
concatp->lhsp()->width()+concatp->rhsp()->width(),
|
||||
nodep->dtypep()->numeric());
|
||||
}
|
||||
}
|
||||
if (!newp) newp = valuep;
|
||||
else {
|
||||
AstConcat* concatp = new AstConcat(patp->fileline(), newp, valuep);
|
||||
newp = concatp;
|
||||
newp->dtypeSetLogicSized(concatp->lhsp()->width()+concatp->rhsp()->width(),
|
||||
concatp->lhsp()->width()+concatp->rhsp()->width(),
|
||||
nodep->dtypep()->numeric());
|
||||
}
|
||||
if (newpatp) { pushDeletep(newpatp); newpatp=NULL; }
|
||||
}
|
||||
@@ -1398,34 +1406,16 @@ private:
|
||||
else nodep->v3error("Assignment pattern with no members");
|
||||
pushDeletep(nodep); nodep = NULL; // Deletes defaultp also, if present
|
||||
}
|
||||
else if (AstNodeArrayDType* arrayp = vdtypep->castNodeArrayDType()) {
|
||||
typedef map<int,AstPatMember*> PatMap;
|
||||
PatMap patmap;
|
||||
{
|
||||
int element = arrayp->declRange().left();
|
||||
for (AstPatMember* patp = nodep->itemsp()->castPatMember();
|
||||
patp; patp = patp->nextp()->castPatMember()) {
|
||||
if (patp->keyp()) {
|
||||
if (AstConst* constp = patp->keyp()->castConst()) {
|
||||
element = constp->toSInt();
|
||||
} else {
|
||||
patp->keyp()->v3error("Assignment pattern key not supported/understood: "<<patp->keyp()->prettyTypeName());
|
||||
}
|
||||
}
|
||||
if (patmap.find(element) != patmap.end()) {
|
||||
patp->v3error("Assignment pattern key used multiple times: "<<element);
|
||||
} else {
|
||||
patmap.insert(make_pair(element, patp));
|
||||
}
|
||||
element += arrayp->declRange().leftToRightInc();
|
||||
}
|
||||
}
|
||||
UINFO(9,"ent "<<arrayp->declRange().hi()<<" to "<<arrayp->declRange().lo()<<endl);
|
||||
else if (vdtypep->castNodeArrayDType()) {
|
||||
AstNodeArrayDType* arrayp = vdtypep->castNodeArrayDType();
|
||||
VNumRange range = arrayp->declRange();
|
||||
PatVecMap patmap = patVectorMap(nodep, range);
|
||||
UINFO(9,"ent "<<range.hi()<<" to "<<range.lo()<<endl);
|
||||
AstNode* newp = NULL;
|
||||
for (int ent=arrayp->declRange().hi(); ent>=arrayp->declRange().lo(); --ent) {
|
||||
for (int ent=range.hi(); ent>=range.lo(); --ent) {
|
||||
AstPatMember* newpatp = NULL;
|
||||
AstPatMember* patp = NULL;
|
||||
PatMap::iterator it=patmap.find(ent);
|
||||
PatVecMap::iterator it=patmap.find(ent);
|
||||
if (it == patmap.end()) {
|
||||
if (defaultp) {
|
||||
newpatp = defaultp->cloneTree(false);
|
||||
@@ -1439,37 +1429,97 @@ private:
|
||||
patmap.erase(it);
|
||||
}
|
||||
|
||||
// Determine initial values
|
||||
vdtypep = arrayp->subDTypep();
|
||||
// Don't want the RHS an array
|
||||
patp->dtypep(arrayp->subDTypep());
|
||||
if (patp) {
|
||||
// Determine initial values
|
||||
vdtypep = arrayp->subDTypep();
|
||||
// Don't want the RHS an array
|
||||
patp->dtypep(vdtypep);
|
||||
// Determine values - might be another InitArray
|
||||
patp->accept(*this,WidthVP(patp->dtypep(),BOTH).p());
|
||||
// Convert to InitArray or constify immediately
|
||||
AstNode* valuep = patp->lhssp()->unlinkFrBack();
|
||||
if (valuep->castConst()) {
|
||||
// Forming a AstConcat will cause problems with unsized (uncommitted sized) constants
|
||||
if (AstNode* newp = WidthCommitVisitor::newIfConstCommitSize(valuep->castConst())) {
|
||||
pushDeletep(valuep); valuep=NULL;
|
||||
valuep = newp;
|
||||
patp->accept(*this,WidthVP(patp->dtypep(),BOTH).p());
|
||||
// Convert to InitArray or constify immediately
|
||||
AstNode* valuep = patp->lhssp()->unlinkFrBack();
|
||||
if (valuep->castConst()) {
|
||||
// Forming a AstConcat will cause problems with unsized (uncommitted sized) constants
|
||||
if (AstNode* newp = WidthCommitVisitor::newIfConstCommitSize(valuep->castConst())) {
|
||||
pushDeletep(valuep); valuep=NULL;
|
||||
valuep = newp;
|
||||
}
|
||||
}
|
||||
if (arrayp->castUnpackArrayDType()) {
|
||||
if (!newp) {
|
||||
newp = new AstInitArray(nodep->fileline(), arrayp, valuep);
|
||||
} else {
|
||||
// We iterate hi()..lo() as that is what packed needs,
|
||||
// but INITARRAY needs lo() first
|
||||
newp->castInitArray()->initsp()->addHereThisAsNext(valuep);
|
||||
}
|
||||
} else { // Packed. Convert to concat for now.
|
||||
if (!newp) newp = valuep;
|
||||
else {
|
||||
AstConcat* concatp = new AstConcat(patp->fileline(), newp, valuep);
|
||||
newp = concatp;
|
||||
newp->dtypeSetLogicSized(concatp->lhsp()->width()+concatp->rhsp()->width(),
|
||||
concatp->lhsp()->width()+concatp->rhsp()->width(),
|
||||
nodep->dtypep()->numeric());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (arrayp->castUnpackArrayDType()) {
|
||||
if (!newp) {
|
||||
newp = new AstInitArray(nodep->fileline(), arrayp, valuep);
|
||||
} else {
|
||||
// We iterate hi()..lo() as that is what packed needs,
|
||||
// but INITARRAY needs lo() first
|
||||
newp->castInitArray()->initsp()->addHereThisAsNext(valuep);
|
||||
if (newpatp) { pushDeletep(newpatp); newpatp=NULL; }
|
||||
}
|
||||
if (!patmap.empty()) nodep->v3error("Assignment pattern with too many elements");
|
||||
if (newp) nodep->replaceWith(newp);
|
||||
else nodep->v3error("Assignment pattern with no members");
|
||||
//if (debug()>=9) newp->dumpTree("-apat-out: ");
|
||||
pushDeletep(nodep); nodep = NULL; // Deletes defaultp also, if present
|
||||
}
|
||||
else if (vdtypep->castBasicDType()
|
||||
&& vdtypep->castBasicDType()->isRanged()) {
|
||||
AstBasicDType* bdtypep = vdtypep->castBasicDType();
|
||||
VNumRange range = bdtypep->declRange();
|
||||
PatVecMap patmap = patVectorMap(nodep, range);
|
||||
UINFO(9,"ent "<<range.hi()<<" to "<<range.lo()<<endl);
|
||||
AstNode* newp = NULL;
|
||||
for (int ent=range.hi(); ent>=range.lo(); --ent) {
|
||||
AstPatMember* newpatp = NULL;
|
||||
AstPatMember* patp = NULL;
|
||||
PatVecMap::iterator it=patmap.find(ent);
|
||||
if (it == patmap.end()) {
|
||||
if (defaultp) {
|
||||
newpatp = defaultp->cloneTree(false);
|
||||
patp = newpatp;
|
||||
}
|
||||
} else { // Packed. Convert to concat for now.
|
||||
if (!newp) newp = valuep;
|
||||
else {
|
||||
AstConcat* concatp = new AstConcat(patp->fileline(), newp, valuep);
|
||||
newp = concatp;
|
||||
newp->dtypeSetLogicSized(concatp->lhsp()->width()+concatp->rhsp()->width(),
|
||||
concatp->lhsp()->width()+concatp->rhsp()->width(),
|
||||
nodep->dtypep()->numeric());
|
||||
nodep->v3error("Assignment pattern missed initializing elements: "<<ent);
|
||||
}
|
||||
} else {
|
||||
patp = it->second;
|
||||
patmap.erase(it);
|
||||
}
|
||||
if (patp) {
|
||||
// Determine initial values
|
||||
vdtypep = nodep->findLogicBoolDType();
|
||||
// Don't want the RHS an array
|
||||
patp->dtypep(vdtypep);
|
||||
// Determine values - might be another InitArray
|
||||
patp->accept(*this,WidthVP(patp->dtypep(),BOTH).p());
|
||||
// Convert to InitArray or constify immediately
|
||||
AstNode* valuep = patp->lhssp()->unlinkFrBack();
|
||||
if (valuep->castConst()) {
|
||||
// Forming a AstConcat will cause problems with unsized (uncommitted sized) constants
|
||||
if (AstNode* newp = WidthCommitVisitor::newIfConstCommitSize(valuep->castConst())) {
|
||||
pushDeletep(valuep); valuep=NULL;
|
||||
valuep = newp;
|
||||
}
|
||||
}
|
||||
{ // Packed. Convert to concat for now.
|
||||
if (!newp) newp = valuep;
|
||||
else {
|
||||
AstConcat* concatp = new AstConcat(patp->fileline(), newp, valuep);
|
||||
newp = concatp;
|
||||
newp->dtypeSetLogicSized(concatp->lhsp()->width()+concatp->rhsp()->width(),
|
||||
concatp->lhsp()->width()+concatp->rhsp()->width(),
|
||||
nodep->dtypep()->numeric());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (newpatp) { pushDeletep(newpatp); newpatp=NULL; }
|
||||
@@ -1628,8 +1678,9 @@ private:
|
||||
string dispout = "";
|
||||
bool inPct = false;
|
||||
AstNode* argp = nodep->exprsp();
|
||||
for (const char* inp = nodep->text().c_str(); *inp; inp++) {
|
||||
char ch = *inp; // Breaks with iterators...
|
||||
string txt = nodep->text();
|
||||
for (string::const_iterator it = txt.begin(); it!=txt.end(); ++it) {
|
||||
char ch = *it;
|
||||
if (!inPct && ch=='%') {
|
||||
inPct = true;
|
||||
} else if (inPct && isdigit(ch)) {
|
||||
@@ -1849,6 +1900,32 @@ private:
|
||||
nodep->paramsp()->iterateAndNext(*this);
|
||||
m_cellRangep = NULL;
|
||||
}
|
||||
virtual void visit(AstGatePin* nodep, AstNUser* vup) {
|
||||
if (vup->c()->prelim()) {
|
||||
nodep->rangep()->iterateAndNext(*this,WidthVP(SELF,BOTH).p());
|
||||
nodep->exprp()->iterateAndNext(*this,WidthVP(CONTEXT,PRELIM).p());
|
||||
nodep->dtypeFrom(nodep->rangep());
|
||||
// Very much like like an pin
|
||||
AstNodeDType* conDTypep = nodep->exprp()->dtypep();
|
||||
int numInsts = nodep->rangep()->elementsConst();
|
||||
int pinwidth = numInsts;
|
||||
int conwidth = conDTypep->width();
|
||||
if (conwidth == 1 && pinwidth > 1) { // Multiple connections
|
||||
AstNodeDType* subDTypep = nodep->findLogicDType(1,1, conDTypep->numeric());
|
||||
nodep->exprp()->iterateAndNext(*this,WidthVP(subDTypep,FINAL).p());
|
||||
AstNode* newp = new AstReplicate(nodep->fileline(),
|
||||
nodep->exprp()->unlinkFrBack(),
|
||||
numInsts);
|
||||
nodep->replaceWith(newp);
|
||||
}
|
||||
else {
|
||||
// Eliminating so pass down all of vup
|
||||
nodep->exprp()->iterateAndNext(*this,vup);
|
||||
nodep->replaceWith(nodep->exprp()->unlinkFrBack());
|
||||
}
|
||||
pushDeletep(nodep); nodep=NULL;
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeFTask* nodep, AstNUser* vup) {
|
||||
// Grab width from the output variable (if it's a function)
|
||||
if (nodep->didWidth()) return;
|
||||
@@ -2969,6 +3046,29 @@ private:
|
||||
return varp;
|
||||
}
|
||||
|
||||
PatVecMap patVectorMap(AstPattern* nodep, const VNumRange& range) {
|
||||
PatVecMap patmap;
|
||||
int element = range.left();
|
||||
for (AstPatMember* patp = nodep->itemsp()->castPatMember();
|
||||
patp; patp = patp->nextp()->castPatMember()) {
|
||||
if (patp->keyp()) {
|
||||
if (AstConst* constp = patp->keyp()->castConst()) {
|
||||
element = constp->toSInt();
|
||||
} else {
|
||||
patp->keyp()->v3error("Assignment pattern key not supported/understood: "<<patp->keyp()->prettyTypeName());
|
||||
}
|
||||
}
|
||||
if (patmap.find(element) != patmap.end()) {
|
||||
patp->v3error("Assignment pattern key used multiple times: "<<element);
|
||||
} else {
|
||||
patmap.insert(make_pair(element, patp));
|
||||
}
|
||||
element += range.leftToRightInc();
|
||||
}
|
||||
return patmap;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// METHODS - special type detection
|
||||
void assertAtStatement(AstNode* nodep, AstNUser* vup) {
|
||||
|
||||
+5
-4
@@ -116,8 +116,8 @@ void V3Global::readFiles() {
|
||||
|
||||
V3Parse parser (v3Global.rootp(), &filter, &parseSyms);
|
||||
// Read top module
|
||||
for (V3StringList::const_iterator it = v3Global.opt.vFiles().begin();
|
||||
it != v3Global.opt.vFiles().end(); ++it) {
|
||||
const V3StringList& vFiles = v3Global.opt.vFiles();
|
||||
for (V3StringList::const_iterator it = vFiles.begin(); it != vFiles.end(); ++it) {
|
||||
string filename = *it;
|
||||
parser.parseFile(new FileLine("COMMAND_LINE",0), filename, false,
|
||||
"Cannot find file containing module: ");
|
||||
@@ -126,8 +126,8 @@ void V3Global::readFiles() {
|
||||
// Read libraries
|
||||
// To be compatible with other simulators,
|
||||
// this needs to be done after the top file is read
|
||||
for (V3StringSet::const_iterator it = v3Global.opt.libraryFiles().begin();
|
||||
it != v3Global.opt.libraryFiles().end(); ++it) {
|
||||
const V3StringSet& libraryFiles = v3Global.opt.libraryFiles();
|
||||
for (V3StringSet::const_iterator it = libraryFiles.begin(); it != libraryFiles.end(); ++it) {
|
||||
string filename = *it;
|
||||
parser.parseFile(new FileLine("COMMAND_LINE",0), filename, true,
|
||||
"Cannot find file containing library module: ");
|
||||
@@ -256,6 +256,7 @@ void process () {
|
||||
// Move assignments from X into MODULE temps.
|
||||
// (Before flattening, so each new X variable is shared between all scopes of that module.)
|
||||
V3Unknown::unknownAll(v3Global.rootp());
|
||||
v3Global.constRemoveXs(true);
|
||||
V3Global::dumpCheckGlobalTree("unknown.tree");
|
||||
|
||||
// Module inlining
|
||||
|
||||
+55
-26
@@ -55,6 +55,7 @@ public:
|
||||
AstVarType m_varDecl; // Type for next signal declaration (reg/wire/etc)
|
||||
AstVarType m_varIO; // Type for next signal declaration (input/output/etc)
|
||||
AstVar* m_varAttrp; // Current variable for attribute adding
|
||||
AstRange* m_gateRangep; // Current range for gate declarations
|
||||
AstCase* m_caseAttrp; // Current case statement for attribute adding
|
||||
AstNodeDType* m_varDTypep; // Pointer to data type for next signal declaration
|
||||
AstNodeDType* m_memDTypep; // Pointer to data type for next member declaration
|
||||
@@ -70,6 +71,7 @@ public:
|
||||
m_varDecl = AstVarType::UNKNOWN;
|
||||
m_varIO = AstVarType::UNKNOWN;
|
||||
m_varDTypep = NULL;
|
||||
m_gateRangep = NULL;
|
||||
m_memDTypep = NULL;
|
||||
m_pinNum = -1;
|
||||
m_instModule = "";
|
||||
@@ -98,9 +100,15 @@ public:
|
||||
nodep->addNext(new AstStop(fileline));
|
||||
return nodep;
|
||||
}
|
||||
AstNode* createGatePin(AstNode* exprp) {
|
||||
AstRange* rangep = m_gateRangep;
|
||||
if (!rangep) return exprp;
|
||||
else return new AstGatePin(rangep->fileline(), exprp, rangep->cloneTree(true));
|
||||
}
|
||||
void endLabel(FileLine* fl, AstNode* nodep, string* endnamep) { endLabel(fl, nodep->prettyName(), endnamep); }
|
||||
void endLabel(FileLine* fl, string name, string* endnamep) {
|
||||
if (fl && endnamep && *endnamep != "" && name != *endnamep) {
|
||||
if (fl && endnamep && *endnamep != "" && name != *endnamep
|
||||
&& name != AstNode::prettyName(*endnamep)) {
|
||||
fl->v3warn(ENDLABEL,"End label '"<<*endnamep<<"' does not match begin label '"<<name<<"'");
|
||||
}
|
||||
}
|
||||
@@ -175,6 +183,8 @@ const AstBasicDTypeKwd LOGIC_IMPLICIT = AstBasicDTypeKwd::LOGIC_IMPLICIT;
|
||||
#define VARDONEP(portp,array,attrs) GRAMMARP->createVariable((portp)->fileline(),(portp)->name(),(array),(attrs))
|
||||
#define PINNUMINC() (GRAMMARP->m_pinNum++)
|
||||
|
||||
#define GATERANGE(rangep) { GRAMMARP->m_gateRangep = rangep; }
|
||||
|
||||
#define INSTPREP(modname,paramsp) { GRAMMARP->m_impliedDecl = true; GRAMMARP->m_instModule = modname; GRAMMARP->m_instParamp = paramsp; }
|
||||
|
||||
#define DEL(nodep) { if (nodep) nodep->deleteTree(); }
|
||||
@@ -727,6 +737,11 @@ package_or_generate_item_declaration<nodep>: // ==IEEE: package_or_generate_item
|
||||
| ';' { $$ = NULL; }
|
||||
;
|
||||
|
||||
package_import_declarationList<nodep>:
|
||||
package_import_declaration { $$ = $1; }
|
||||
| package_import_declarationList package_import_declaration { $$ = $1->addNextNull($2); }
|
||||
;
|
||||
|
||||
package_import_declaration<nodep>: // ==IEEE: package_import_declaration
|
||||
yIMPORT package_import_itemList ';' { $$ = $2; }
|
||||
;
|
||||
@@ -753,7 +768,7 @@ package_import_itemObj<strp>: // IEEE: part of package_import_item
|
||||
module_declaration: // ==IEEE: module_declaration
|
||||
// // timeunits_declaration instead in module_item
|
||||
// // IEEE: module_nonansi_header + module_ansi_header
|
||||
modFront parameter_port_listE portsStarE ';'
|
||||
modFront importsAndParametersE portsStarE ';'
|
||||
module_itemListE yENDMODULE endLabelE
|
||||
{ $1->modTrace(v3Global.opt.trace() && $1->fileline()->tracingOn()); // Stash for implicit wires, etc
|
||||
if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3);
|
||||
@@ -783,6 +798,12 @@ modFront<modulep>:
|
||||
SYMP->pushNew($$); }
|
||||
;
|
||||
|
||||
importsAndParametersE<nodep>: // IEEE: common part of module_declaration, interface_declaration, program_declaration
|
||||
// // { package_import_declaration } [ parameter_port_list ]
|
||||
parameter_port_listE { $$ = $1; }
|
||||
| package_import_declarationList parameter_port_listE { $$ = $1->addNextNull($2); }
|
||||
;
|
||||
|
||||
udpFront<modulep>:
|
||||
yPRIMITIVE lifetimeE idAny
|
||||
{ $$ = new AstPrimitive($1,*$3); $$->inLibrary(true);
|
||||
@@ -1909,7 +1930,7 @@ sigAttr<nodep>:
|
||||
| yVL_PUBLIC_FLAT { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC_FLAT); v3Global.dpi(true); }
|
||||
| yVL_PUBLIC_FLAT_RD { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC_FLAT_RD); v3Global.dpi(true); }
|
||||
| yVL_PUBLIC_FLAT_RW { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC_FLAT_RW); v3Global.dpi(true); }
|
||||
| yVL_PUBLIC_FLAT_RW attr_event_control { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC_FLAT_RW); v3Global.dpi(true);
|
||||
| yVL_PUBLIC_FLAT_RW attr_event_control { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC_FLAT_RW); v3Global.dpi(true);
|
||||
$$ = $$->addNext(new AstAlwaysPublic($1,$2,NULL)); }
|
||||
| yVL_ISOLATE_ASSIGNMENTS { $$ = new AstAttrOf($1,AstAttrType::VAR_ISOLATE_ASSIGNMENTS); }
|
||||
| yVL_SC_BV { $$ = new AstAttrOf($1,AstAttrType::VAR_SC_BV); }
|
||||
@@ -3243,62 +3264,66 @@ gateUnsupList<nodep>:
|
||||
| gateUnsupList ',' gateUnsup { $$ = $1->addNext($3); }
|
||||
;
|
||||
|
||||
gateRangeE<nodep>:
|
||||
instRangeE { $$ = $1; GATERANGE($1); }
|
||||
;
|
||||
|
||||
gateBuf<nodep>:
|
||||
gateIdE instRangeE '(' variable_lvalue ',' expr ')'
|
||||
gateIdE gateRangeE '(' variable_lvalue ',' gatePinExpr ')'
|
||||
{ $$ = new AstAssignW ($3,$4,$6); DEL($2); }
|
||||
;
|
||||
gateBufif0<nodep>:
|
||||
gateIdE instRangeE '(' variable_lvalue ',' expr ',' expr ')'
|
||||
gateIdE gateRangeE '(' variable_lvalue ',' gatePinExpr ',' gatePinExpr ')'
|
||||
{ $$ = new AstAssignW ($3,$4,new AstBufIf1($3,new AstNot($3,$8),$6)); DEL($2); }
|
||||
;
|
||||
gateBufif1<nodep>:
|
||||
gateIdE instRangeE '(' variable_lvalue ',' expr ',' expr ')'
|
||||
gateIdE gateRangeE '(' variable_lvalue ',' gatePinExpr ',' gatePinExpr ')'
|
||||
{ $$ = new AstAssignW ($3,$4,new AstBufIf1($3,$8,$6)); DEL($2); }
|
||||
;
|
||||
gateNot<nodep>:
|
||||
gateIdE instRangeE '(' variable_lvalue ',' expr ')'
|
||||
gateIdE gateRangeE '(' variable_lvalue ',' gatePinExpr ')'
|
||||
{ $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); DEL($2); }
|
||||
;
|
||||
gateNotif0<nodep>:
|
||||
gateIdE instRangeE '(' variable_lvalue ',' expr ',' expr ')'
|
||||
gateIdE gateRangeE '(' variable_lvalue ',' gatePinExpr ',' gatePinExpr ')'
|
||||
{ $$ = new AstAssignW ($3,$4,new AstBufIf1($3,new AstNot($3,$8), new AstNot($3, $6))); DEL($2); }
|
||||
;
|
||||
gateNotif1<nodep>:
|
||||
gateIdE instRangeE '(' variable_lvalue ',' expr ',' expr ')'
|
||||
gateIdE gateRangeE '(' variable_lvalue ',' gatePinExpr ',' gatePinExpr ')'
|
||||
{ $$ = new AstAssignW ($3,$4,new AstBufIf1($3,$8, new AstNot($3,$6))); DEL($2); }
|
||||
;
|
||||
gateAnd<nodep>:
|
||||
gateIdE instRangeE '(' variable_lvalue ',' gateAndPinList ')'
|
||||
gateIdE gateRangeE '(' variable_lvalue ',' gateAndPinList ')'
|
||||
{ $$ = new AstAssignW ($3,$4,$6); DEL($2); }
|
||||
;
|
||||
gateNand<nodep>:
|
||||
gateIdE instRangeE '(' variable_lvalue ',' gateAndPinList ')'
|
||||
gateIdE gateRangeE '(' variable_lvalue ',' gateAndPinList ')'
|
||||
{ $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); DEL($2); }
|
||||
;
|
||||
gateOr<nodep>:
|
||||
gateIdE instRangeE '(' variable_lvalue ',' gateOrPinList ')'
|
||||
gateIdE gateRangeE '(' variable_lvalue ',' gateOrPinList ')'
|
||||
{ $$ = new AstAssignW ($3,$4,$6); DEL($2); }
|
||||
;
|
||||
gateNor<nodep>:
|
||||
gateIdE instRangeE '(' variable_lvalue ',' gateOrPinList ')'
|
||||
gateIdE gateRangeE '(' variable_lvalue ',' gateOrPinList ')'
|
||||
{ $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); DEL($2); }
|
||||
;
|
||||
gateXor<nodep>:
|
||||
gateIdE instRangeE '(' variable_lvalue ',' gateXorPinList ')'
|
||||
gateIdE gateRangeE '(' variable_lvalue ',' gateXorPinList ')'
|
||||
{ $$ = new AstAssignW ($3,$4,$6); DEL($2); }
|
||||
;
|
||||
gateXnor<nodep>:
|
||||
gateIdE instRangeE '(' variable_lvalue ',' gateXorPinList ')'
|
||||
gateIdE gateRangeE '(' variable_lvalue ',' gateXorPinList ')'
|
||||
{ $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); DEL($2); }
|
||||
;
|
||||
gatePullup<nodep>:
|
||||
gateIdE instRangeE '(' variable_lvalue ')' { $$ = new AstPull ($3, $4, true); DEL($2); }
|
||||
gateIdE gateRangeE '(' variable_lvalue ')' { $$ = new AstPull ($3, $4, true); DEL($2); }
|
||||
;
|
||||
gatePulldown<nodep>:
|
||||
gateIdE instRangeE '(' variable_lvalue ')' { $$ = new AstPull ($3, $4, false); DEL($2); }
|
||||
gateIdE gateRangeE '(' variable_lvalue ')' { $$ = new AstPull ($3, $4, false); DEL($2); }
|
||||
;
|
||||
gateUnsup<nodep>:
|
||||
gateIdE instRangeE '(' gateUnsupPinList ')' { $$ = new AstImplicit ($3,$4); DEL($2); }
|
||||
gateIdE gateRangeE '(' gateUnsupPinList ')' { $$ = new AstImplicit ($3,$4); DEL($2); }
|
||||
;
|
||||
|
||||
gateIdE:
|
||||
@@ -3307,20 +3332,24 @@ gateIdE:
|
||||
;
|
||||
|
||||
gateAndPinList<nodep>:
|
||||
expr { $$ = $1; }
|
||||
| gateAndPinList ',' expr { $$ = new AstAnd($2,$1,$3); }
|
||||
gatePinExpr { $$ = $1; }
|
||||
| gateAndPinList ',' gatePinExpr { $$ = new AstAnd($2,$1,$3); }
|
||||
;
|
||||
gateOrPinList<nodep>:
|
||||
expr { $$ = $1; }
|
||||
| gateOrPinList ',' expr { $$ = new AstOr($2,$1,$3); }
|
||||
gatePinExpr { $$ = $1; }
|
||||
| gateOrPinList ',' gatePinExpr { $$ = new AstOr($2,$1,$3); }
|
||||
;
|
||||
gateXorPinList<nodep>:
|
||||
expr { $$ = $1; }
|
||||
| gateXorPinList ',' expr { $$ = new AstXor($2,$1,$3); }
|
||||
gatePinExpr { $$ = $1; }
|
||||
| gateXorPinList ',' gatePinExpr { $$ = new AstXor($2,$1,$3); }
|
||||
;
|
||||
gateUnsupPinList<nodep>:
|
||||
expr { $$ = $1; }
|
||||
| gateUnsupPinList ',' expr { $$ = $1->addNext($3); }
|
||||
gatePinExpr { $$ = $1; }
|
||||
| gateUnsupPinList ',' gatePinExpr { $$ = $1->addNext($3); }
|
||||
;
|
||||
|
||||
gatePinExpr<nodep>:
|
||||
expr { $$ = GRAMMARP ->createGatePin($1); }
|
||||
;
|
||||
|
||||
strengthSpecE: // IEEE: drive_strength + pullup_strength + pulldown_strength + charge_strength - plus empty
|
||||
|
||||
@@ -12,7 +12,12 @@ module t (/*AUTOARG*/
|
||||
|
||||
logic [1:0] [3:0] [3:0] array_simp; // big endian array
|
||||
|
||||
logic [3:0] array_oned;
|
||||
|
||||
initial begin
|
||||
array_oned = '{2:1'b1, 0:1'b1, default:1'b0};
|
||||
if (array_oned != 4'b0101) $stop;
|
||||
|
||||
array_simp[0] = '{ 4'd3, 4'd2, 4'd1, 4'd0};
|
||||
if (array_simp[0] !== 16'h3210) $stop;
|
||||
|
||||
|
||||
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 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 => ["-Wno-UNOPTFLAT -Wno-WIDTH"]
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,39 @@
|
||||
// DESCRIPTION: Verilator: Simple test of unoptflat
|
||||
//
|
||||
// Trigger the DETECTARRAY error on packed structure.
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2014 by Jie Xu.
|
||||
|
||||
localparam ID_MSB = 1;
|
||||
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk,
|
||||
res
|
||||
);
|
||||
input clk;
|
||||
output [8:0][8:0] res;
|
||||
|
||||
logic a = 1'b1;
|
||||
logic [8:0] b [8:0]; // where the error is reported
|
||||
logic [8:0][8:0] c; // where the error is reported
|
||||
|
||||
// following just to make c as circular
|
||||
assign c[0] = c[0] | a << 1;
|
||||
assign b[0] = b[0] | a << 2;
|
||||
|
||||
assign res[0] = c[0];
|
||||
assign res[1] = b[0];
|
||||
|
||||
|
||||
always @(posedge clk or negedge clk) begin
|
||||
|
||||
if (res != 0) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -17,6 +17,7 @@ if (!-r "$root/.git") {
|
||||
} else {
|
||||
uint();
|
||||
printfll();
|
||||
cstr();
|
||||
}
|
||||
|
||||
ok(1);
|
||||
@@ -67,4 +68,22 @@ sub printfll {
|
||||
}
|
||||
}
|
||||
|
||||
sub cstr {
|
||||
my $files = "src/*.c* src/*.h include/*.c* include/*.h test_c/*.c* test_regress/t/*.c* test_regress/t/*.h";
|
||||
my $cmd = "cd $root && grep -n -P 'c_str|begin|end' $files | sort";
|
||||
print "C $cmd\n";
|
||||
my $grep = `$cmd`;
|
||||
my %names;
|
||||
foreach my $line (split /\n/, $grep) {
|
||||
if ($line =~ /^([^:]+).*\(\)[a-z0-9_().->]*[.->]+(c_str|r?begin|r?end)\(\)/) {
|
||||
next if $line =~ /lintok-begin-on-ref/;
|
||||
print "$line\n";
|
||||
$names{$1} = 1;
|
||||
}
|
||||
}
|
||||
if (keys %names) {
|
||||
$Self->error("Files with potential c_str() lifetime issue: ",join(' ',sort keys %names));
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
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 2008 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.
|
||||
|
||||
$Self->{vlt} or $Self->skip("Verilator only test");
|
||||
|
||||
compile (
|
||||
v_flags2 => ["--lint-only -Wno-WIDTH"],
|
||||
verilator_make_gcc => 0,
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,20 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2008 by Wilson Snyder.
|
||||
|
||||
module t;
|
||||
|
||||
// width warnings off due to command line
|
||||
wire A = 15'd1234;
|
||||
|
||||
// width warnings off due to command line + manual switch
|
||||
// verilator lint_off WIDTH
|
||||
wire B = 15'd1234;
|
||||
|
||||
// this turnon does nothing as off on command line
|
||||
// verilator lint_on WIDTH
|
||||
wire C = 15'd1234;
|
||||
|
||||
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 2004 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,88 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2014 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
integer cyc=0;
|
||||
reg [63:0] crc;
|
||||
reg [63:0] sum;
|
||||
|
||||
// Take CRC data and apply to testblock inputs
|
||||
wire [7:0] a = crc[7:0];
|
||||
wire [7:0] b = crc[15:8];
|
||||
|
||||
/*AUTOWIRE*/
|
||||
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
||||
wire [63:0] out; // From test of Test.v
|
||||
// End of automatics
|
||||
|
||||
Test test (/*AUTOINST*/
|
||||
// Outputs
|
||||
.out (out[63:0]),
|
||||
// Inputs
|
||||
.clk (clk),
|
||||
.a (a[7:0]),
|
||||
.b (b[7:0]));
|
||||
|
||||
// Aggregate outputs into a single result vector
|
||||
wire [63:0] result = {out};
|
||||
|
||||
// Test loop
|
||||
always @ (posedge clk) begin
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("[%0t] cyc==%0d crc=%x result=%x\n",$time, cyc, crc, result);
|
||||
`endif
|
||||
cyc <= cyc + 1;
|
||||
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
|
||||
sum <= result ^ {sum[62:0],sum[63]^sum[2]^sum[0]};
|
||||
if (cyc==0) begin
|
||||
// Setup
|
||||
crc <= 64'h5aef0c8d_d70a4497;
|
||||
sum <= 64'h0;
|
||||
end
|
||||
else if (cyc<10) begin
|
||||
sum <= 64'h0;
|
||||
end
|
||||
else if (cyc<90) begin
|
||||
end
|
||||
else if (cyc==99) begin
|
||||
$write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
|
||||
if (crc !== 64'hc77bb9b3784ea091) $stop;
|
||||
// What checksum will we end up with (above print should match)
|
||||
`define EXPECTED_SUM 64'h0908a1f2194d24ee
|
||||
if (sum !== `EXPECTED_SUM) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module Test (/*AUTOARG*/
|
||||
// Outputs
|
||||
out,
|
||||
// Inputs
|
||||
clk, a, b
|
||||
);
|
||||
|
||||
input clk;
|
||||
input [7:0] a;
|
||||
input [7:0] b;
|
||||
output reg [63:0] out;
|
||||
|
||||
and u0[7:0] (out[7:0], a[7:0], b[7:0]);
|
||||
and u1[7:0] (out[15:8], a[0], b[7:0]);
|
||||
and u2[7:0] (out[23:16], a[0], b[0]);
|
||||
nand u3[7:0] (out[31:24], a[0], b[7:0]);
|
||||
or u4[7:0] (out[39:32], a[0], b[7:0]);
|
||||
nor u5[7:0] (out[47:40], a[0], b[7:0]);
|
||||
xor u6[7:0] (out[55:48], a[0], b[7:0]);
|
||||
xnor u7[7:0] (out[63:56], a[0], b[7:0]);
|
||||
|
||||
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,49 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2014 by Wilson Snyder.
|
||||
|
||||
// bug749
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
genvar g;
|
||||
for (g=1; g<3; ++g) begin : gblk
|
||||
sub2 #(.IN(g)) u ();
|
||||
//sub #(.IN(g)) u2 ();
|
||||
end
|
||||
|
||||
sub1 #(.IN(0)) u ();
|
||||
|
||||
always @ (posedge clk) begin
|
||||
if (t.u.IN != 0) $stop;
|
||||
if (t.u.FLAVOR != 1) $stop;
|
||||
//if (t.u2.IN != 0) $stop; // This should be not found
|
||||
if (t.gblk[1].u.IN != 1) $stop;
|
||||
if (t.gblk[2].u.IN != 2) $stop;
|
||||
if (t.gblk[1].u.FLAVOR != 2) $stop;
|
||||
if (t.gblk[2].u.FLAVOR != 2) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
||||
module sub1 (/*AUTOARG*/);
|
||||
parameter [31:0] IN = 99;
|
||||
parameter FLAVOR = 1;
|
||||
`ifdef TEST_VERBOSE
|
||||
initial $display("%m");
|
||||
`endif
|
||||
endmodule
|
||||
|
||||
module sub2 (/*AUTOARG*/);
|
||||
parameter [31:0] IN = 99;
|
||||
parameter FLAVOR = 2;
|
||||
`ifdef TEST_VERBOSE
|
||||
initial $display("%m");
|
||||
`endif
|
||||
endmodule
|
||||
@@ -27,10 +27,10 @@ module t (/*AUTOARG*/
|
||||
|
||||
// finish report
|
||||
always @ (posedge clk)
|
||||
if (cnt==SIZE) begin : if_cnt_finish
|
||||
if (cnt==SIZE) begin : \0escaped___name
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end : if_cnt_finish
|
||||
end : \0escaped___name
|
||||
|
||||
generate
|
||||
for (i=0; i<SIZE; i=i+1) begin : generate_for
|
||||
|
||||
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 (
|
||||
v_flags2 => ["--lint-only"],
|
||||
verilator_make_gcc => 0,
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,51 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2014 by Jie Xu.
|
||||
|
||||
//bug692
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input wire clk;
|
||||
|
||||
wire [31:0] result;
|
||||
test_if #(.id(3)) s();
|
||||
sub_test U_SUB_TEST(s.a.b, result); // the line causing error
|
||||
endmodule : t
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
module sub_test
|
||||
(
|
||||
input [31:0] b,
|
||||
output [31:0] c
|
||||
);
|
||||
assign c = b;
|
||||
endmodule
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
interface test_if
|
||||
#(parameter id = 0)
|
||||
();
|
||||
|
||||
typedef struct packed {
|
||||
logic a;
|
||||
logic [31:0] b;
|
||||
} aType;
|
||||
|
||||
aType a;
|
||||
|
||||
typedef struct packed {
|
||||
logic c;
|
||||
logic [31:0] d;
|
||||
} bType;
|
||||
|
||||
bType b;
|
||||
|
||||
modport master (input a, output b);
|
||||
|
||||
endinterface
|
||||
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 (
|
||||
verilator_flags2 => ['--x-assign 0'],
|
||||
);
|
||||
|
||||
execute (
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,11 @@
|
||||
module t(y);
|
||||
output [3:0] y;
|
||||
// bug775
|
||||
// verilator lint_off WIDTH
|
||||
assign y = ((0/0) ? 1 : 2) % 0;
|
||||
|
||||
initial begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
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 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 => ["-CFLAGS '-DVL_DEBUG -ggdb -O0'"],
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,77 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2014 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
|
||||
input clk;
|
||||
|
||||
integer cyc=0;
|
||||
reg [63:0] crc;
|
||||
reg [63:0] sum;
|
||||
|
||||
//bug765; disappears if add this wire
|
||||
//wire [7:0] a = (crc[7] ? {7'b0,crc[0]} : crc[7:0]); // favor low values
|
||||
wire [7:0] a = crc[7:0];
|
||||
|
||||
/*AUTOWIRE*/
|
||||
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
||||
wire [15:0] y; // From test of Test.v
|
||||
// End of automatics
|
||||
|
||||
Test test (/*AUTOINST*/
|
||||
// Outputs
|
||||
.y (y[15:0]),
|
||||
// Inputs
|
||||
.a (a[7:0]));
|
||||
|
||||
// Aggregate outputs into a single result vector
|
||||
wire [63:0] result = {48'h0, y};
|
||||
|
||||
// Test loop
|
||||
always @ (posedge clk) begin
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("[%0t] cyc==%0d crc=%x result=%x\n",$time, cyc, crc, result);
|
||||
`endif
|
||||
cyc <= cyc + 1;
|
||||
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
|
||||
sum <= result ^ {sum[62:0],sum[63]^sum[2]^sum[0]};
|
||||
if (cyc==0) begin
|
||||
// Setup
|
||||
crc <= 64'h5aef0c8d_d70a4497;
|
||||
sum <= 64'h0;
|
||||
end
|
||||
else if (cyc<10) begin
|
||||
sum <= 64'h0;
|
||||
end
|
||||
else if (cyc<90) begin
|
||||
end
|
||||
else if (cyc==99) begin
|
||||
$write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
|
||||
if (crc !== 64'hc77bb9b3784ea091) $stop;
|
||||
// What checksum will we end up with (above print should match)
|
||||
`define EXPECTED_SUM 64'h0
|
||||
if (sum !== `EXPECTED_SUM) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module Test (/*AUTOARG*/
|
||||
// Outputs
|
||||
y,
|
||||
// Inputs
|
||||
a
|
||||
);
|
||||
input signed [7:0] a;
|
||||
output [15:0] y;
|
||||
// verilator lint_off WIDTH
|
||||
assign y = ~66'd0 <<< {4{a}};
|
||||
// verilator lint_on WIDTH
|
||||
endmodule
|
||||
@@ -5,8 +5,16 @@
|
||||
|
||||
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); fail='1; end while(0)
|
||||
`define checkf(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%f exp=%f\n", `__FILE__,`__LINE__, (gotv), (expv)); fail='1; end while(0)
|
||||
`ifdef VERILATOR
|
||||
`define c(v,vs) ($c(vs)) // Don't constify a value
|
||||
`else
|
||||
`define c(v,vs) (v)
|
||||
`endif
|
||||
|
||||
module t (/*AUTOARG*/);
|
||||
module t (/*AUTOARG*/
|
||||
// Outputs
|
||||
ow4_u
|
||||
);
|
||||
|
||||
bit fail;
|
||||
|
||||
@@ -15,6 +23,9 @@
|
||||
reg [2:0] w3_u;
|
||||
reg [3:0] w4_u;
|
||||
reg [4:0] w5_u;
|
||||
reg [5:0] w6_u;
|
||||
reg [15:0] w16a_u;
|
||||
reg [15:0] w16_u;
|
||||
real r;
|
||||
|
||||
reg signed [4:0] bug754_a;
|
||||
@@ -116,8 +127,48 @@
|
||||
w4_u = (w3_u >> 2'b11) >> 1;
|
||||
`checkh(w4_u, 4'b0000);
|
||||
|
||||
// bug766
|
||||
w16a_u = 16'h1234;
|
||||
w16_u = (w16a_u >> 16) >>> 32'h7ffffff1;
|
||||
`checkh(w16_u, 16'h0000);
|
||||
|
||||
// bug768
|
||||
w4_s = 4'sd4;
|
||||
w4_u = $signed(5'd1 > w4_s-w4_s);
|
||||
`checkh(w4_u, 4'b1111);
|
||||
w4_s = `c(4,"4"); // Eval at runtime
|
||||
w4_u = $signed(5'd1 > w4_s-w4_s);
|
||||
`checkh(w4_u, 4'b1111);
|
||||
|
||||
// bug772
|
||||
w4_s = w4_u << 1 <<< 0/0;
|
||||
`ifndef VERILATOR // In v4 can't check value as not 4-state
|
||||
`checkh(w4_s, 4'bxxxx);
|
||||
`endif
|
||||
|
||||
// bug773
|
||||
w5_u = `c(31, 31);
|
||||
w5_s = w5_u >> ((w5_u ? 1 : 2) << w5_u);
|
||||
`checkh(w5_s, 5'b0);
|
||||
|
||||
// bug774
|
||||
w4_u = `c(4, 5);
|
||||
w6_u = `c(6, 35);
|
||||
w4_u = 64'd0 | (w4_u << w6_u);
|
||||
`checkh(w4_u, 0);
|
||||
|
||||
// bug776
|
||||
w4_u = `c(4, 1);
|
||||
w4_u = (w4_u >> w4_u) ^~ (w4_u >> w4_u);
|
||||
`checkh(w4_u, 4'b1111);
|
||||
|
||||
if (fail) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
// bug775
|
||||
output [3:0] ow4_u; // Must be consumed
|
||||
assign ow4_u = ((0/0) ? 1 : 2) % 0;
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -14,14 +14,14 @@ package pkg1;
|
||||
parameter PARAM1 = 8;
|
||||
endpackage // pkg1
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
module t
|
||||
import pkg1::*; // Test SV 2012 import format
|
||||
(/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
import pkg1::*;
|
||||
|
||||
reg [PARAM1:0] bus1;
|
||||
|
||||
initial begin
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
Hello in t_preproc_psl.v
|
||||
yes
|
||||
Multi text
|
||||
multiline line
|
||||
Line: 20
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
#!/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.
|
||||
|
||||
$Self->{vlt} or $Self->skip("Verilator only test");
|
||||
|
||||
my $stdout_filename = "$Self->{obj_dir}/$Self->{name}__test.vpp";
|
||||
|
||||
top_filename("t/t_preproc_noline.v");
|
||||
|
||||
compile (
|
||||
verilator_flags2 => ['-E -P'],
|
||||
verilator_make_gcc=>0,
|
||||
stdout_filename => $stdout_filename,
|
||||
);
|
||||
|
||||
ok(files_identical($stdout_filename, "t/$Self->{name}.out"));
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,20 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2014 by Wilson Snyder.
|
||||
|
||||
`define CHECK text \
|
||||
multiline
|
||||
|
||||
Hello in t_preproc_psl.v
|
||||
|
||||
`ifdef NEVER
|
||||
not
|
||||
`else
|
||||
yes
|
||||
`endif
|
||||
|
||||
Multi `CHECK line
|
||||
|
||||
// Did we end up right?
|
||||
Line: `__LINE__
|
||||
@@ -67,6 +67,9 @@ module t;
|
||||
if (tsu.pack2.four.quad1.b2 != 1'b0) $stop;
|
||||
if (tsu.pack2.four.quad1.b3 != 1'b1) $stop;
|
||||
//
|
||||
tsu = 1'b0 ? '0 : '{pvec: 6'b101011};
|
||||
if (tsu!=6'b101011) $stop;
|
||||
//
|
||||
arr[0] = 6'b101010;
|
||||
arr[1] = 6'b010101;
|
||||
if (arr[0].four !== 4'b0101) $stop;
|
||||
|
||||
@@ -10,8 +10,6 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||
# 22-Mar-2012: Modifications for this test contributed by Jeremy Bennett,
|
||||
# Embecosm.
|
||||
|
||||
$Self->{vlt} and $Self->unsupported("Verilator unsupported");
|
||||
|
||||
compile (
|
||||
# Taken from the original VCS command line.
|
||||
v_flags2 => ["t/t_sv_cpu_code/timescale.sv",
|
||||
@@ -33,7 +31,7 @@ compile (
|
||||
"t/t_sv_cpu_code/cpu.sv",
|
||||
"t/t_sv_cpu_code/chip.sv"],
|
||||
vcs_flags2 => ["-R -sverilog +memcbk -y t/t_sv_cpu_code +libext+.sv+ +incdir+t/t_sv_cpu_code"],
|
||||
verilator_flags2 => ["-y t/t_sv_cpu_code +libext+.sv+ +incdir+t/t_sv_cpu_code"],
|
||||
verilator_flags2 => ["-y t/t_sv_cpu_code +libext+.sv+ +incdir+t/t_sv_cpu_code --top-module t"],
|
||||
iv_flags2 => ["-yt/t_sv_cpu_code -It/t_sv_cpu_code -Y.sv"],
|
||||
);
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ module t (/*AUTOARG*/
|
||||
end
|
||||
|
||||
always @( posedge clk ) begin
|
||||
if (500 == clk_count) begin
|
||||
if (90 == clk_count) begin
|
||||
$finish ();
|
||||
end
|
||||
else begin
|
||||
@@ -103,7 +103,11 @@ module testbench (/*AUTOARG*/
|
||||
// **************************************************************************
|
||||
|
||||
// **** Pinout ****
|
||||
`ifdef VERILATOR // see t_tri_array
|
||||
wire [NUMPADS:1] pad; // GPIO Pads (PORT{A,...,R}).
|
||||
`else
|
||||
wire pad [1:NUMPADS]; // GPIO Pads (PORT{A,...,R}).
|
||||
`endif
|
||||
|
||||
|
||||
// **************************************************************************
|
||||
@@ -129,7 +133,7 @@ module testbench (/*AUTOARG*/
|
||||
(
|
||||
/*AUTOINST*/
|
||||
// Inouts
|
||||
.pad (pad),
|
||||
.pad (pad[NUMPADS:1]),
|
||||
// Inputs
|
||||
.clk (clk),
|
||||
.rst (rst));
|
||||
|
||||
@@ -15,7 +15,11 @@ module chip
|
||||
)
|
||||
(
|
||||
// **** Pinout ****
|
||||
`ifdef VERILATOR // see t_tri_array
|
||||
inout wire [NUMPADS:1] pad,
|
||||
`else
|
||||
inout wire pad [1:NUMPADS],
|
||||
`endif
|
||||
|
||||
// **** Inputs !!!! ****
|
||||
input logic clk,
|
||||
|
||||
@@ -26,7 +26,9 @@ module pad_gpio
|
||||
);
|
||||
|
||||
// **** Analog <-> pad connection ****
|
||||
`ifndef VERILATOR //TODO alias
|
||||
alias ana = pad;
|
||||
`endif
|
||||
|
||||
|
||||
// **** Digital driver <-> pad connection ****
|
||||
|
||||
@@ -19,8 +19,11 @@ module pads
|
||||
|
||||
|
||||
// **** Pinout ****
|
||||
`ifdef VERILATOR // see t_tri_array
|
||||
inout wire [NUMPADS:1] pad,
|
||||
`else
|
||||
inout wire pad [1:NUMPADS],
|
||||
|
||||
`endif
|
||||
|
||||
// **** Inputs ****
|
||||
input logic clk,
|
||||
@@ -32,6 +35,11 @@ module pads
|
||||
// Code Section
|
||||
// ***************************************************************************
|
||||
|
||||
`ifdef VERILATOR // see t_tri_array
|
||||
tri [NUMPADS:1] _anahack;
|
||||
`endif
|
||||
|
||||
|
||||
genvar i;
|
||||
for ( i = 1; i <= NUMPADS; i++ )
|
||||
begin
|
||||
@@ -46,11 +54,16 @@ module pads
|
||||
case ( p_type )
|
||||
PADTYPE_GPIO:
|
||||
pad_gpio #( .ID( i ) )
|
||||
i_pad_gpio(.pad (pad [i]),
|
||||
i_pad_gpio(
|
||||
.pad (pad [i]),
|
||||
// Outputs
|
||||
.input_val (padsif.input_val [i]),
|
||||
// Inouts
|
||||
`ifdef VERILATOR // see t_tri_array
|
||||
.ana (_anahack [i]),
|
||||
`else
|
||||
.ana (padsif.ana [i]),
|
||||
`endif
|
||||
// Inputs
|
||||
.pullup_en (padsif.pullup_en [i]),
|
||||
.pulldown_en (padsif.pulldown_en [i]),
|
||||
@@ -63,7 +76,8 @@ module pads
|
||||
PADTYPE_VDD:
|
||||
begin
|
||||
pad_vdd #( .ID( i ) )
|
||||
i_pad_vdd(.pad (pad[i])
|
||||
i_pad_vdd(
|
||||
.pad (pad[i])
|
||||
/*AUTOINST*/);
|
||||
// Not SV standard, yet... assign padsif.input_val[i] = ();
|
||||
end
|
||||
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
# When fix, update ifdefs in t_sv_cpu files; search for t_tri_array
|
||||
$Self->{vlt} and $Self->unsupported("Verilator unsupported, tristate arrays");
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,69 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2014 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
integer cyc=0;
|
||||
reg [63:0] crc;
|
||||
reg [63:0] sum;
|
||||
|
||||
parameter NPAD = 4;
|
||||
|
||||
tri pad [NPAD-1:0]; // Array
|
||||
wire [NPAD-1:0] data0 = crc[0 +: 4];
|
||||
wire [NPAD-1:0] data1 = crc[8 +: 4];
|
||||
wire [NPAD-1:0] en = crc[16 +: 4];
|
||||
|
||||
for (genvar g=0; g<NPAD; ++g) begin : gpad
|
||||
Pad pad1 (.pad(pad[g]),
|
||||
.ena(en[g]),
|
||||
.data(data1[g]));
|
||||
Pad pad0 (.pad(pad[g]),
|
||||
.ena(!en[g]),
|
||||
.data(data0[g]));
|
||||
end
|
||||
|
||||
// Test loop
|
||||
always @ (posedge clk) begin
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("[%0t] cyc==%0d crc=%x result=%x\n",$time, cyc, crc, result);
|
||||
`endif
|
||||
cyc <= cyc + 1;
|
||||
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
|
||||
sum <= {60'h0, pad[3], pad[2], pad[1], pad[0]}
|
||||
^ {sum[62:0],sum[63]^sum[2]^sum[0]};
|
||||
if (cyc==0) begin
|
||||
// Setup
|
||||
crc <= 64'h5aef0c8d_d70a4497;
|
||||
sum <= 64'h0;
|
||||
end
|
||||
else if (cyc<10) begin
|
||||
sum <= 64'h0;
|
||||
end
|
||||
else if (cyc<90) begin
|
||||
end
|
||||
else if (cyc==99) begin
|
||||
$write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
|
||||
if (crc !== 64'hc77bb9b3784ea091) $stop;
|
||||
// What checksum will we end up with (above print should match)
|
||||
`define EXPECTED_SUM 64'he09fe6f2dfd7a302
|
||||
if (sum !== `EXPECTED_SUM) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module Pad
|
||||
(inout pad,
|
||||
input ena,
|
||||
input data);
|
||||
assign pad = ena ? data : 1'bz;
|
||||
endmodule
|
||||
@@ -12,8 +12,9 @@ top_filename("t/t_var_rsvd_port.v");
|
||||
compile (
|
||||
fails=>$Self->{v3},
|
||||
expect=>
|
||||
q{%Error-SYMRSVDWORD: t/t_var_rsvd_port.v:\d+: Symbol matches C\+\+ common word: 'bool'
|
||||
%Error-SYMRSVDWORD: t/t_var_rsvd_port.v:\d+: Symbol matches C\+\+ reserved word: 'switch'
|
||||
q{%Warning-SYMRSVDWORD: t/t_var_rsvd_port.v:\d+: Symbol matches C\+\+ common word: 'bool'
|
||||
.*
|
||||
%Warning-SYMRSVDWORD: t/t_var_rsvd_port.v:\d+: Symbol matches C\+\+ reserved word: 'switch'
|
||||
%Error: Exiting due to.*},
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user