diff --git a/.gitignore b/.gitignore
index e9235a3a7..d426d7134 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
\#*
.#*
+.nfs*
*~
*.tidy
*.old
diff --git a/Changes b/Changes
index 2d2cf87fe..91b9a8eb0 100644
--- a/Changes
+++ b/Changes
@@ -2,6 +2,35 @@ Revision history for Verilator
The contributors that suggested a given feature are shown in []. Thanks!
+* Verilator 4.040 2020-08-15
+
+** Version 4.040 is planned to be the final version that will
+ support pre-C++11 compilers. Please move to C++11 or newer compilers.
+
+*** Fix arrayed interfaces, broke in 4.038 (#2468). [Josh Redford]
+
+**** Support $stable, $rose and $fell. (#2148) (#2501) [Peter Monsson]
+
+**** Support simple function localparams (#2461). [James Hanlon]
+
+**** Miscellaneous parsing error changes towards UVM support.
+
+**** Fix arrayed interfaces (#2469). [Josh Redford]
+
+**** Fix protect lib VCS warning. (#2479) [Julien Margetts]
+
+**** Fix combining different-width parameters (#2484). [abirkmanis]
+
+**** Fix protect-lib without sequential logic (#2492). [Yutetsu TAKATSUKASA]
+
+**** Fix V3Unknown from running with flat XML output (#2494). [James Hanlon]
+
+**** Fix non-32 bit conversion to float (#2495). [dsvf]
+
+**** Fix casting non-self-determined subexpressions (#2493). [phantom-killua]
+
+**** Fix SystemC net names (#2500). [Edgar E. Iglesias]
+
* Verilator 4.038 2020-07-11
diff --git a/ci/travis-install.bash b/ci/travis-install.bash
index f4c89c9bd..27adf42ec 100755
--- a/ci/travis-install.bash
+++ b/ci/travis-install.bash
@@ -80,23 +80,23 @@ elif [ "$TRAVIS_BUILD_STAGE_NAME" = "test" ]; then
if [ "$M32" = 1 ]; then
sudo apt-get install lib32z1-dev gcc-multilib g++-multilib
fi
- yes yes | sudo cpan -fi Unix::Processors Parallel::Forker
- # Not listing Bit::Vector as slow to install, and only skips one test
- install-vcddiff
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
brew update
# brew cask install gtkwave # fst2vcd hangs at launch, so don't bother
brew install ccache perl
- yes yes | sudo cpan -fi Unix::Processors Parallel::Forker
- install-vcddiff
elif [ "$TRAVIS_OS_NAME" = "freebsd" ]; then
# fst2vcd fails with "Could not open '', exiting."
sudo pkg install -y ccache gmake perl5 python3
- yes yes | sudo cpan -fi Unix::Processors Parallel::Forker
- install-vcddiff
else
fatal "Unknown os: '$TRAVIS_OS_NAME'"
fi
+ # Common installs
+ if [ "$TRAVIS_DIST" != "trusty" ]; then
+ TRAVIS_CPAN_REPO=https://cpan.org
+ fi
+ # Not listing Bit::Vector as slow to install, and only skips one test
+ yes yes | sudo cpan -M $TRAVIS_CPAN_REPO -fi Unix::Processors Parallel::Forker
+ install-vcddiff
else
##############################################################################
# Unknown build stage
diff --git a/configure.ac b/configure.ac
index 6a866b524..e672a3198 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,11 +7,12 @@
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
#AC_INIT([Verilator],[#.### devel])
-AC_INIT([Verilator],[4.038 2020-07-11],
+AC_INIT([Verilator],[4.040 2020-08-15],
[https://verilator.org],
[verilator],[https://verilator.org])
# When releasing, also update header of Changes file
# and commit using "devel release" or "Version bump" message
+# Then 'make maintainer-dist'
AC_CONFIG_HEADER(src/config_build.h)
AC_CONFIG_FILES(Makefile docs/Makefile src/Makefile src/Makefile_obj include/verilated.mk include/verilated_config.h verilator.pc verilator-config.cmake verilator-config-version.cmake)
diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS
index cc00fe3a1..5eeec896c 100644
--- a/docs/CONTRIBUTORS
+++ b/docs/CONTRIBUTORS
@@ -11,6 +11,7 @@ Dan Petrisko
David Horton
David Stanford
Driss Hafdi
+Edgar E. Iglesias
Eric Rippey
Fan Shupei
Garrett Smith
@@ -28,6 +29,7 @@ Jan Van Winkel
Jeremy Bennett
John Coiner
John Demme
+Josh Redford
Julien Margetts
Kanad Kanhere
Kevin Kiningham
@@ -37,6 +39,7 @@ Lukasz Dalek
Maarten De Braekeleer
Maciej Sobkowski
Marco Widmer
+Marshal Qiao
Matthew Ballance
Michael Killough
Mike Popoloski
@@ -47,6 +50,7 @@ Peter Horvath
Peter Monsson
Philipp Wagner
Pieter Kapsenberg
+Piotr Binkowski
Qingyao Sun
Richard Myers
Sean Cross
diff --git a/include/verilated.cpp b/include/verilated.cpp
index 72f3e97c9..f21bed470 100644
--- a/include/verilated.cpp
+++ b/include/verilated.cpp
@@ -584,6 +584,30 @@ QData VL_POWSS_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp, bool lsig
return VL_POW_QQW(obits, rbits, rbits, lhs, rwp);
}
+double VL_ITOR_D_W(int lbits, WDataInP lwp) VL_PURE {
+ int ms_word = VL_WORDS_I(lbits) - 1;
+ for (; !lwp[ms_word] && ms_word > 0;) --ms_word;
+ if (ms_word == 0) return static_cast(lwp[0]);
+ if (ms_word == 1) return static_cast(VL_SET_QW(lwp));
+ // We need 53 bits of mantissa, which might mean looking at 3 words
+ // namely ms_word, ms_word-1 and ms_word-2
+ EData ihi = lwp[ms_word];
+ EData imid = lwp[ms_word - 1];
+ EData ilo = lwp[ms_word - 2];
+ double hi = static_cast(ihi) * exp2(2 * VL_EDATASIZE);
+ double mid = static_cast(imid) * exp2(VL_EDATASIZE);
+ double lo = static_cast(ilo);
+ double d = (hi + mid + lo) * exp2(VL_EDATASIZE * (ms_word - 2));
+ return d;
+}
+double VL_ISTOR_D_W(int lbits, WDataInP lwp) VL_PURE {
+ if (!VL_SIGN_W(lbits, lwp)) return VL_ITOR_D_W(lbits, lwp);
+ vluint32_t pos[VL_MULS_MAX_WORDS + 1]; // Fixed size, as MSVC++ doesn't allow [words] here
+ VL_NEGATE_W(VL_WORDS_I(lbits), pos, lwp);
+ _VL_CLEAN_INPLACE_W(lbits, pos);
+ return -VL_ITOR_D_W(lbits, pos);
+}
+
//===========================================================================
// Formatting
diff --git a/include/verilated.h b/include/verilated.h
index f9cb28fbe..099066ab7 100644
--- a/include/verilated.h
+++ b/include/verilated.h
@@ -764,9 +764,27 @@ static inline QData VL_CVT_Q_D(double lhs) VL_PURE {
}
// clang-format on
-/// Return double from QData (numeric)
-static inline double VL_ITOR_D_I(IData lhs) VL_PURE {
- return static_cast(static_cast(lhs));
+/// Return double from lhs (numeric) unsigned
+double VL_ITOR_D_W(int lbits, WDataInP lwp) VL_PURE;
+static inline double VL_ITOR_D_I(int, IData lhs) VL_PURE {
+ return static_cast(static_cast(lhs));
+}
+static inline double VL_ITOR_D_Q(int, QData lhs) VL_PURE {
+ return static_cast(static_cast(lhs));
+}
+/// Return double from lhs (numeric) signed
+double VL_ISTOR_D_W(int lbits, WDataInP lwp) VL_PURE;
+static inline double VL_ISTOR_D_I(int lbits, IData lhs) VL_PURE {
+ if (lbits == 32) return static_cast(static_cast(lhs));
+ WData lwp[VL_WQ_WORDS_E];
+ VL_SET_WI(lwp, lhs);
+ return VL_ISTOR_D_W(lbits, lwp);
+}
+static inline double VL_ISTOR_D_Q(int lbits, QData lhs) VL_PURE {
+ if (lbits == 64) return static_cast(static_cast(lhs));
+ WData lwp[VL_WQ_WORDS_E];
+ VL_SET_WQ(lwp, lhs);
+ return VL_ISTOR_D_W(lbits, lwp);
}
/// Return QData from double (numeric)
static inline IData VL_RTOI_I_D(double lhs) VL_PURE {
@@ -1453,6 +1471,7 @@ static inline int _VL_CMPS_W(int lbits, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
//=========================================================================
// Math
+// Output NOT clean
static inline WDataOutP VL_NEGATE_W(int words, WDataOutP owp, WDataInP lwp) VL_MT_SAFE {
EData carry = 1;
for (int i = 0; i < words; ++i) {
@@ -2538,25 +2557,25 @@ static inline WDataOutP VL_CONSTHI_W_1X(int obits, int lsb, WDataOutP obase,
EData d0) VL_MT_SAFE {
WDataOutP o = obase + VL_WORDS_I(lsb);
o[0] = d0;
- _END(obits,1);
+ _END(obits, VL_WORDS_I(lsb) + 1);
}
static inline WDataOutP VL_CONSTHI_W_2X(int obits, int lsb, WDataOutP obase,
EData d1, EData d0) VL_MT_SAFE {
WDataOutP o = obase + VL_WORDS_I(lsb);
o[0] = d0; o[1] = d1;
- _END(obits,2);
+ _END(obits, VL_WORDS_I(lsb) + 2);
}
static inline WDataOutP VL_CONSTHI_W_3X(int obits, int lsb, WDataOutP obase,
EData d2, EData d1, EData d0) VL_MT_SAFE {
WDataOutP o = obase + VL_WORDS_I(lsb);
o[0] = d0; o[1] = d1; o[2] = d2;
- _END(obits,3);
+ _END(obits, VL_WORDS_I(lsb) + 3);
}
static inline WDataOutP VL_CONSTHI_W_4X(int obits, int lsb, WDataOutP obase,
EData d3, EData d2, EData d1, EData d0) VL_MT_SAFE {
WDataOutP o = obase + VL_WORDS_I(lsb);
o[0] = d0; o[1] = d1; o[2] = d2; o[3] = d3;
- _END(obits,4);
+ _END(obits, VL_WORDS_I(lsb) + 4);
}
static inline WDataOutP VL_CONSTHI_W_5X(int obits, int lsb, WDataOutP obase,
EData d4,
@@ -2564,7 +2583,7 @@ static inline WDataOutP VL_CONSTHI_W_5X(int obits, int lsb, WDataOutP obase,
WDataOutP o = obase + VL_WORDS_I(lsb);
o[0] = d0; o[1] = d1; o[2] = d2; o[3] = d3;
o[4] = d4;
- _END(obits,5);
+ _END(obits, VL_WORDS_I(lsb) + 5);
}
static inline WDataOutP VL_CONSTHI_W_6X(int obits, int lsb, WDataOutP obase,
EData d5, EData d4,
@@ -2572,7 +2591,7 @@ static inline WDataOutP VL_CONSTHI_W_6X(int obits, int lsb, WDataOutP obase,
WDataOutP o = obase + VL_WORDS_I(lsb);
o[0] = d0; o[1] = d1; o[2] = d2; o[3] = d3;
o[4] = d4; o[5] = d5;
- _END(obits,6);
+ _END(obits, VL_WORDS_I(lsb) + 6);
}
static inline WDataOutP VL_CONSTHI_W_7X(int obits, int lsb, WDataOutP obase,
EData d6, EData d5, EData d4,
@@ -2580,7 +2599,7 @@ static inline WDataOutP VL_CONSTHI_W_7X(int obits, int lsb, WDataOutP obase,
WDataOutP o = obase + VL_WORDS_I(lsb);
o[0] = d0; o[1] = d1; o[2] = d2; o[3] = d3;
o[4] = d4; o[5] = d5; o[6] = d6;
- _END(obits,7);
+ _END(obits, VL_WORDS_I(lsb) + 7);
}
static inline WDataOutP VL_CONSTHI_W_8X(int obits, int lsb, WDataOutP obase,
EData d7, EData d6, EData d5, EData d4,
@@ -2588,7 +2607,7 @@ static inline WDataOutP VL_CONSTHI_W_8X(int obits, int lsb, WDataOutP obase,
WDataOutP o = obase + VL_WORDS_I(lsb);
o[0] = d0; o[1] = d1; o[2] = d2; o[3] = d3;
o[4] = d4; o[5] = d5; o[6] = d6; o[7] = d7;
- _END(obits,8);
+ _END(obits, VL_WORDS_I(lsb) + 8);
}
#undef _END
diff --git a/include/verilated_save.h b/include/verilated_save.h
index 74ea32d83..cf6c3a5a5 100644
--- a/include/verilated_save.h
+++ b/include/verilated_save.h
@@ -55,7 +55,7 @@ public:
}
virtual ~VerilatedSerialize() {
close();
- if (m_bufp) VL_DO_CLEAR(delete m_bufp, m_bufp = NULL);
+ if (m_bufp) VL_DO_CLEAR(delete[] m_bufp, m_bufp = NULL);
}
// METHODS
bool isOpen() const { return m_isOpen; }
@@ -118,7 +118,7 @@ public:
}
virtual ~VerilatedDeserialize() {
close();
- if (m_bufp) VL_DO_CLEAR(delete m_bufp, m_bufp = NULL);
+ if (m_bufp) VL_DO_CLEAR(delete[] m_bufp, m_bufp = NULL);
}
// METHODS
bool isOpen() const { return m_isOpen; }
diff --git a/src/V3AssertPre.cpp b/src/V3AssertPre.cpp
index 6448d0eab..ec1775503 100644
--- a/src/V3AssertPre.cpp
+++ b/src/V3AssertPre.cpp
@@ -89,11 +89,54 @@ private:
if (!nodep->immediate()) nodep->sentreep(newSenTree(nodep));
clearAssertInfo();
}
+ virtual void visit(AstFell* nodep) VL_OVERRIDE {
+ if (nodep->sentreep()) return; // Already processed
+ iterateChildren(nodep);
+ FileLine* fl = nodep->fileline();
+ AstNode* exprp = nodep->exprp()->unlinkFrBack();
+ if (exprp->width() > 1) exprp = new AstSel(fl, exprp, 0, 1);
+ AstNode* past = new AstPast(fl, exprp, NULL);
+ past->dtypeFrom(exprp);
+ exprp = new AstAnd(fl, past, new AstNot(fl, exprp->cloneTree(false)));
+ exprp->dtypeSetLogicBool();
+ nodep->replaceWith(exprp);
+ nodep->sentreep(newSenTree(nodep));
+ VL_DO_DANGLING(pushDeletep(nodep), nodep);
+ }
virtual void visit(AstPast* nodep) VL_OVERRIDE {
if (nodep->sentreep()) return; // Already processed
iterateChildren(nodep);
nodep->sentreep(newSenTree(nodep));
}
+ virtual void visit(AstRose* nodep) VL_OVERRIDE {
+ if (nodep->sentreep()) return; // Already processed
+ iterateChildren(nodep);
+ FileLine* fl = nodep->fileline();
+ AstNode* exprp = nodep->exprp()->unlinkFrBack();
+ if (exprp->width() > 1) exprp = new AstSel(fl, exprp, 0, 1);
+ AstNode* past = new AstPast(fl, exprp, NULL);
+ past->dtypeFrom(exprp);
+ exprp = new AstAnd(fl, new AstNot(fl, past), exprp->cloneTree(false));
+ exprp->dtypeSetLogicBool();
+ nodep->replaceWith(exprp);
+ nodep->sentreep(newSenTree(nodep));
+ VL_DO_DANGLING(pushDeletep(nodep), nodep);
+ }
+ virtual void visit(AstStable* nodep) VL_OVERRIDE {
+ if (nodep->sentreep()) return; // Already processed
+ iterateChildren(nodep);
+ FileLine* fl = nodep->fileline();
+ AstNode* exprp = nodep->exprp()->unlinkFrBack();
+ AstNode* past = new AstPast(fl, exprp, NULL);
+ past->dtypeFrom(exprp);
+ exprp = new AstEq(fl, past,
+ exprp->cloneTree(false)); // new AstVarRef(fl, exprp, true)
+ exprp->dtypeSetLogicBool();
+ nodep->replaceWith(exprp);
+ nodep->sentreep(newSenTree(nodep));
+ VL_DO_DANGLING(pushDeletep(nodep), nodep);
+ }
+
virtual void visit(AstPropClocked* nodep) VL_OVERRIDE {
// No need to iterate the body, once replace will get iterated
iterateAndNextNull(nodep->sensesp());
diff --git a/src/V3Ast.h b/src/V3Ast.h
index 674c393f9..f990b491c 100644
--- a/src/V3Ast.h
+++ b/src/V3Ast.h
@@ -1891,6 +1891,7 @@ public:
// For documentation on emitC format see EmitCStmts::emitOpName
virtual string emitC() = 0;
virtual string emitSimpleOperator() { return ""; }
+ virtual bool emitCheckMaxWords() { return false; } // Check VL_MULS_MAX_WORDS
virtual bool cleanOut() const = 0; // True if output has extra upper bits zero
// Someday we will generically support data types on every math node
// Until then isOpaque indicates we shouldn't constant optimize this node type
diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp
index d5ee54c8d..d9ec68bb3 100644
--- a/src/V3AstNodes.cpp
+++ b/src/V3AstNodes.cpp
@@ -1493,19 +1493,19 @@ void AstParseRef::dump(std::ostream& str) const {
this->AstNode::dump(str);
str << " [" << expect().ascii() << "]";
}
-void AstPackageRef::dump(std::ostream& str) const {
+void AstClassOrPackageRef::dump(std::ostream& str) const {
this->AstNode::dump(str);
- if (packagep()) { str << " pkg=" << nodeAddr(packagep()); }
+ if (classOrPackagep()) { str << " cpkg=" << nodeAddr(classOrPackagep()); }
str << " -> ";
- if (packagep()) {
- packagep()->dump(str);
+ if (classOrPackagep()) {
+ classOrPackagep()->dump(str);
} else {
str << "UNLINKED";
}
}
void AstDot::dump(std::ostream& str) const {
this->AstNode::dump(str);
- if (colon()) str << "[::]";
+ if (colon()) str << " [::]";
}
void AstActive::dump(std::ostream& str) const {
this->AstNode::dump(str);
diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h
index bb055fb6c..f24e6b37c 100644
--- a/src/V3AstNodes.h
+++ b/src/V3AstNodes.h
@@ -448,6 +448,7 @@ public:
ASTNODE_NODE_FUNCS(TypedefFwd)
// METHODS
virtual string name() const { return m_name; }
+ virtual bool maybePointedTo() const { return true; }
};
class AstDefImplicitDType : public AstNodeDType {
@@ -1139,6 +1140,15 @@ public:
, m_refDTypep(NULL)
, m_name(name)
, m_packagep(NULL) {}
+ AstRefDType(FileLine* fl, const string& name, AstNode* classOrPackagep, AstNode* paramsp)
+ : ASTGEN_SUPER(fl)
+ , m_typedefp(NULL)
+ , m_refDTypep(NULL)
+ , m_name(name)
+ , m_packagep(NULL) {
+ setNOp3p(classOrPackagep);
+ addNOp4p(paramsp);
+ }
class FlagTypeOfExpr {}; // type(expr) for parser only
AstRefDType(FileLine* fl, FlagTypeOfExpr, AstNode* typeofp)
: ASTGEN_SUPER(fl)
@@ -1216,6 +1226,8 @@ public:
AstNodeModule* packagep() const { return m_packagep; }
void packagep(AstNodeModule* nodep) { m_packagep = nodep; }
AstNode* typeofp() const { return op2p(); }
+ AstNode* classOrPackagep() const { return op3p(); }
+ AstPin* paramsp() const { return VN_CAST(op4p(), Pin); }
};
class AstStructDType : public AstNodeUOrStructDType {
@@ -2429,11 +2441,14 @@ public:
class AstModule : public AstNodeModule {
// A module declaration
+private:
+ bool m_isProgram; // Module represents a program
public:
- AstModule(FileLine* fl, const string& name)
- : ASTGEN_SUPER(fl, name) {}
+ AstModule(FileLine* fl, const string& name, bool program = false)
+ : ASTGEN_SUPER(fl, name)
+ , m_isProgram(program) {}
ASTNODE_NODE_FUNCS(Module)
- virtual string verilogKwd() const { return "module"; }
+ virtual string verilogKwd() const { return m_isProgram ? "program" : "module"; }
};
class AstNotFoundModule : public AstNodeModule {
@@ -2891,29 +2906,40 @@ public:
void ftaskrefp(AstNodeFTaskRef* nodep) { setNOp2p(nodep); } // op2 = Function/task reference
};
-class AstPackageRef : public AstNode {
+class AstClassOrPackageRef : public AstNode {
private:
- AstPackage* m_packagep; // Package hierarchy
+ string m_name;
+ AstNode* m_classOrPackagep; // Package hierarchy
public:
- AstPackageRef(FileLine* fl, AstPackage* packagep)
+ AstClassOrPackageRef(FileLine* fl, const string& name, AstNode* classOrPackagep,
+ AstNode* paramsp)
: ASTGEN_SUPER(fl)
- , m_packagep(packagep) {}
- ASTNODE_NODE_FUNCS(PackageRef)
+ , m_name(name)
+ , m_classOrPackagep(classOrPackagep) {
+ addNOp4p(paramsp);
+ }
+ ASTNODE_NODE_FUNCS(ClassOrPackageRef)
// METHODS
virtual const char* broken() const {
- BROKEN_RTN(!m_packagep || !m_packagep->brokeExists());
+ BROKEN_RTN(m_classOrPackagep && !m_classOrPackagep->brokeExists());
return NULL;
}
virtual void cloneRelink() {
- if (m_packagep && m_packagep->clonep()) { m_packagep = m_packagep->clonep(); }
+ if (m_classOrPackagep && m_classOrPackagep->clonep()) {
+ m_classOrPackagep = m_classOrPackagep->clonep();
+ }
}
virtual bool same(const AstNode* samep) const {
- return (m_packagep == static_cast(samep)->m_packagep);
+ return (m_classOrPackagep
+ == static_cast(samep)->m_classOrPackagep);
}
- virtual V3Hash sameHash() const { return V3Hash(m_packagep); }
+ virtual V3Hash sameHash() const { return V3Hash(m_classOrPackagep); }
virtual void dump(std::ostream& str = std::cout) const;
- AstPackage* packagep() const { return m_packagep; }
- void packagep(AstPackage* nodep) { m_packagep = nodep; }
+ virtual string name() const { return m_name; } // * = Var name
+ AstNode* classOrPackagep() const { return m_classOrPackagep; }
+ AstPackage* packagep() const { return VN_CAST(classOrPackagep(), Package); }
+ void classOrPackagep(AstNode* nodep) { m_classOrPackagep = nodep; }
+ AstPin* paramsp() const { return VN_CAST(op4p(), Pin); }
};
class AstDot : public AstNode {
@@ -2929,9 +2955,9 @@ public:
}
ASTNODE_NODE_FUNCS(Dot)
// For parser, make only if non-null package
- static AstNode* newIfPkg(FileLine* fl, AstPackage* packagep, AstNode* rhsp) {
- if (!packagep) return rhsp;
- return new AstDot(fl, true, new AstPackageRef(fl, packagep), rhsp);
+ static AstNode* newIfPkg(FileLine* fl, AstNode* packageOrClassp, AstNode* rhsp) {
+ if (!packageOrClassp) return rhsp;
+ return new AstDot(fl, true, packageOrClassp, rhsp);
}
virtual void dump(std::ostream& str) const;
virtual string emitVerilog() { V3ERROR_NA_RETURN(""); }
@@ -5497,6 +5523,7 @@ public:
virtual int instrCount() const { return instrCountDouble(); }
};
class AstIToRD : public AstNodeUniop {
+ // $itor where lhs is unsigned
public:
AstIToRD(FileLine* fl, AstNode* lhsp)
: ASTGEN_SUPER(fl, lhsp) {
@@ -5505,10 +5532,27 @@ public:
ASTNODE_NODE_FUNCS(IToRD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opIToRD(lhs); }
virtual string emitVerilog() { return "%f$itor(%l)"; }
- virtual string emitC() { return "VL_ITOR_D_I(%li)"; }
+ virtual string emitC() { return "VL_ITOR_D_%lq(%lw, %li)"; }
virtual bool cleanOut() const { return false; }
- virtual bool cleanLhs() const { return false; } // Eliminated before matters
- virtual bool sizeMattersLhs() const { return false; } // Eliminated before matters
+ virtual bool cleanLhs() const { return true; }
+ virtual bool sizeMattersLhs() const { return false; }
+ virtual int instrCount() const { return instrCountDouble(); }
+};
+class AstISToRD : public AstNodeUniop {
+ // $itor where lhs is signed
+public:
+ AstISToRD(FileLine* fl, AstNode* lhsp)
+ : ASTGEN_SUPER(fl, lhsp) {
+ dtypeSetDouble();
+ }
+ ASTNODE_NODE_FUNCS(ISToRD)
+ virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opISToRD(lhs); }
+ virtual string emitVerilog() { return "%f$itor($signed(%l))"; }
+ virtual string emitC() { return "VL_ISTOR_D_%lq(%lw, %li)"; }
+ virtual bool emitCheckMaxWords() { return true; }
+ virtual bool cleanOut() const { return false; }
+ virtual bool cleanLhs() const { return true; }
+ virtual bool sizeMattersLhs() const { return false; }
virtual int instrCount() const { return instrCountDouble(); }
};
class AstRealToBits : public AstNodeUniop {
@@ -7125,6 +7169,7 @@ public:
virtual string emitVerilog() { return "%k(%l %f* %r)"; }
virtual string emitC() { return "VL_MULS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return ""; }
+ virtual bool emitCheckMaxWords() { return true; }
virtual bool cleanOut() const { return false; }
virtual bool cleanLhs() const { return true; }
virtual bool cleanRhs() const { return true; }
@@ -7262,6 +7307,7 @@ public:
}
virtual string emitVerilog() { return "%k(%l %f** %r)"; }
virtual string emitC() { return "VL_POW_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
+ virtual bool emitCheckMaxWords() { return true; }
virtual bool cleanOut() const { return false; }
virtual bool cleanLhs() const { return true; }
virtual bool cleanRhs() const { return true; }
@@ -7307,6 +7353,7 @@ public:
}
virtual string emitVerilog() { return "%k(%l %f** %r)"; }
virtual string emitC() { return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 1,0)"; }
+ virtual bool emitCheckMaxWords() { return true; }
virtual bool cleanOut() const { return false; }
virtual bool cleanLhs() const { return true; }
virtual bool cleanRhs() const { return true; }
@@ -7330,6 +7377,7 @@ public:
}
virtual string emitVerilog() { return "%k(%l %f** %r)"; }
virtual string emitC() { return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 1,1)"; }
+ virtual bool emitCheckMaxWords() { return true; }
virtual bool cleanOut() const { return false; }
virtual bool cleanLhs() const { return true; }
virtual bool cleanRhs() const { return true; }
@@ -7353,6 +7401,7 @@ public:
}
virtual string emitVerilog() { return "%k(%l %f** %r)"; }
virtual string emitC() { return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 0,1)"; }
+ virtual bool emitCheckMaxWords() { return true; }
virtual bool cleanOut() const { return false; }
virtual bool cleanLhs() const { return true; }
virtual bool cleanRhs() const { return true; }
@@ -7942,6 +7991,31 @@ public:
virtual bool isHeavy() const { return true; }
};
+class AstFell : public AstNodeMath {
+ // Verilog $fell
+ // Parents: math
+ // Children: expression
+public:
+ AstFell(FileLine* fl, AstNode* exprp)
+ : ASTGEN_SUPER(fl) {
+ addOp1p(exprp);
+ }
+ ASTNODE_NODE_FUNCS(Fell)
+ virtual string emitVerilog() { return "$fell(%l)"; }
+ virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) {
+ V3ERROR_NA;
+ }
+ virtual string emitC() { V3ERROR_NA_RETURN(""); }
+ virtual string emitSimpleOperator() { V3ERROR_NA_RETURN(""); }
+ virtual bool cleanOut() const { V3ERROR_NA_RETURN(""); }
+ virtual int instrCount() const { return widthInstrs(); }
+ AstNode* exprp() const { return op1p(); } // op1 = expression
+ AstSenTree* sentreep() const { return VN_CAST(op2p(), SenTree); } // op2 = clock domain
+ void sentreep(AstSenTree* sentreep) { addOp2p(sentreep); } // op2 = clock domain
+ virtual V3Hash sameHash() const { return V3Hash(); }
+ virtual bool same(const AstNode* samep) const { return true; }
+};
+
class AstPast : public AstNodeMath {
// Verilog $past
// Parents: math
@@ -7969,6 +8043,31 @@ public:
virtual bool same(const AstNode* samep) const { return true; }
};
+class AstRose : public AstNodeMath {
+ // Verilog $rose
+ // Parents: math
+ // Children: expression
+public:
+ AstRose(FileLine* fl, AstNode* exprp)
+ : ASTGEN_SUPER(fl) {
+ addOp1p(exprp);
+ }
+ ASTNODE_NODE_FUNCS(Rose)
+ virtual string emitVerilog() { return "$rose(%l)"; }
+ virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) {
+ V3ERROR_NA;
+ }
+ virtual string emitC() { V3ERROR_NA_RETURN(""); }
+ virtual string emitSimpleOperator() { V3ERROR_NA_RETURN(""); }
+ virtual bool cleanOut() const { V3ERROR_NA_RETURN(""); }
+ virtual int instrCount() const { return widthInstrs(); }
+ AstNode* exprp() const { return op1p(); } // op1 = expression
+ AstSenTree* sentreep() const { return VN_CAST(op2p(), SenTree); } // op2 = clock domain
+ void sentreep(AstSenTree* sentreep) { addOp2p(sentreep); } // op2 = clock domain
+ virtual V3Hash sameHash() const { return V3Hash(); }
+ virtual bool same(const AstNode* samep) const { return true; }
+};
+
class AstSampled : public AstNodeMath {
// Verilog $sampled
// Parents: math
@@ -7989,6 +8088,31 @@ public:
virtual bool same(const AstNode* samep) const { return true; }
};
+class AstStable : public AstNodeMath {
+ // Verilog $stable
+ // Parents: math
+ // Children: expression
+public:
+ AstStable(FileLine* fl, AstNode* exprp)
+ : ASTGEN_SUPER(fl) {
+ addOp1p(exprp);
+ }
+ ASTNODE_NODE_FUNCS(Stable)
+ virtual string emitVerilog() { return "$stable(%l)"; }
+ virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) {
+ V3ERROR_NA;
+ }
+ virtual string emitC() { V3ERROR_NA_RETURN(""); }
+ virtual string emitSimpleOperator() { V3ERROR_NA_RETURN(""); }
+ virtual bool cleanOut() const { V3ERROR_NA_RETURN(""); }
+ virtual int instrCount() const { return widthInstrs(); }
+ AstNode* exprp() const { return op1p(); } // op1 = expression
+ AstSenTree* sentreep() const { return VN_CAST(op2p(), SenTree); } // op2 = clock domain
+ void sentreep(AstSenTree* sentreep) { addOp2p(sentreep); } // op2 = clock domain
+ virtual V3Hash sameHash() const { return V3Hash(); }
+ virtual bool same(const AstNode* samep) const { return true; }
+};
+
class AstPattern : public AstNodeMath {
// Verilog '{a,b,c,d...}
// Parents: AstNodeAssign, AstPattern, ...
diff --git a/src/V3Dead.cpp b/src/V3Dead.cpp
index 9739e89da..7a0add24c 100644
--- a/src/V3Dead.cpp
+++ b/src/V3Dead.cpp
@@ -25,7 +25,7 @@
// The following nodes have package pointers and are cleaned up here:
// AstRefDType, AstEnumItemRef, AstNodeVarRef, AstNodeFTask
// These have packagep but will not exist at this stage
-// AstPackageImport, AstDot, AstPackageRef
+// AstPackageImport, AstDot, AstClassOrPackageRef
//
// Note on packagep: After the V3Scope/V3LinkDotScoped stage, package links
// are no longer used, but their presence prevents us from removing empty
diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp
index e8e9a1e8f..441ca96be 100644
--- a/src/V3EmitC.cpp
+++ b/src/V3EmitC.cpp
@@ -877,6 +877,15 @@ public:
emitOpName(nodep, nodep->emitC(), NULL, NULL, NULL);
}
virtual void visit(AstNodeUniop* nodep) VL_OVERRIDE {
+ if (nodep->emitCheckMaxWords()
+ && (nodep->widthWords() > VL_MULS_MAX_WORDS
+ || nodep->lhsp()->widthWords() > VL_MULS_MAX_WORDS)) {
+ nodep->v3warn(
+ E_UNSUPPORTED,
+ "Unsupported: "
+ << nodep->prettyOperatorName() << " operator of " << nodep->width()
+ << " bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h");
+ }
if (emitSimpleOk(nodep)) {
putbs("(");
puts(nodep->emitSimpleOperator());
@@ -888,6 +897,13 @@ public:
}
}
virtual void visit(AstNodeBiop* nodep) VL_OVERRIDE {
+ if (nodep->emitCheckMaxWords() && nodep->widthWords() > VL_MULS_MAX_WORDS) {
+ nodep->v3warn(
+ E_UNSUPPORTED,
+ "Unsupported: "
+ << nodep->prettyOperatorName() << " operator of " << nodep->width()
+ << " bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h");
+ }
if (emitSimpleOk(nodep)) {
putbs("(");
iterateAndNextNull(nodep->lhsp());
@@ -915,56 +931,6 @@ public:
puts(")");
}
}
- virtual void visit(AstMulS* nodep) VL_OVERRIDE {
- if (nodep->widthWords() > VL_MULS_MAX_WORDS) {
- nodep->v3warn(
- E_UNSUPPORTED,
- "Unsupported: Signed multiply of "
- << nodep->width()
- << " bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h");
- }
- visit(VN_CAST(nodep, NodeBiop));
- }
- virtual void visit(AstPow* nodep) VL_OVERRIDE {
- if (nodep->widthWords() > VL_MULS_MAX_WORDS) {
- nodep->v3warn(
- E_UNSUPPORTED,
- "Unsupported: Power of "
- << nodep->width()
- << " bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h");
- }
- visit(VN_CAST(nodep, NodeBiop));
- }
- virtual void visit(AstPowSS* nodep) VL_OVERRIDE {
- if (nodep->widthWords() > VL_MULS_MAX_WORDS) {
- nodep->v3warn(
- E_UNSUPPORTED,
- "Unsupported: Power of "
- << nodep->width()
- << " bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h");
- }
- visit(VN_CAST(nodep, NodeBiop));
- }
- virtual void visit(AstPowSU* nodep) VL_OVERRIDE {
- if (nodep->widthWords() > VL_MULS_MAX_WORDS) {
- nodep->v3warn(
- E_UNSUPPORTED,
- "Unsupported: Power of "
- << nodep->width()
- << " bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h");
- }
- visit(VN_CAST(nodep, NodeBiop));
- }
- virtual void visit(AstPowUS* nodep) VL_OVERRIDE {
- if (nodep->widthWords() > VL_MULS_MAX_WORDS) {
- nodep->v3warn(
- E_UNSUPPORTED,
- "Unsupported: Power of "
- << nodep->width()
- << " bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h");
- }
- visit(VN_CAST(nodep, NodeBiop));
- }
virtual void visit(AstCCast* nodep) VL_OVERRIDE {
// Extending a value of the same word width is just a NOP.
if (nodep->size() <= VL_IDATASIZE) {
@@ -3825,8 +3791,8 @@ void V3EmitC::emitc() {
nodep = VN_CAST(nodep->nextp(), NodeModule)) {
if (VN_IS(nodep, Class)) continue; // Imped with ClassPackage
// clang-format off
- { EmitCImp cint; cint.mainInt(nodep); }
- { EmitCImp slow; slow.mainImp(nodep, true); }
+ EmitCImp cint; cint.mainInt(nodep);
+ cint.mainImp(nodep, true);
{ EmitCImp fast; fast.mainImp(nodep, false); }
// clang-format on
}
diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp
index 99bd1fcb2..18af595a0 100644
--- a/src/V3LinkDot.cpp
+++ b/src/V3LinkDot.cpp
@@ -429,7 +429,9 @@ public:
static AstIfaceRefDType* ifaceRefFromArray(AstNodeDType* nodep) {
AstIfaceRefDType* ifacerefp = VN_CAST(nodep, IfaceRefDType);
if (!ifacerefp) {
- if (AstUnpackArrayDType* arrp = VN_CAST(nodep, UnpackArrayDType)) {
+ if (AstBracketArrayDType* arrp = VN_CAST(nodep, BracketArrayDType)) {
+ ifacerefp = VN_CAST(arrp->subDTypep(), IfaceRefDType);
+ } else if (AstUnpackArrayDType* arrp = VN_CAST(nodep, UnpackArrayDType)) {
ifacerefp = VN_CAST(arrp->subDTypep(), IfaceRefDType);
}
}
@@ -1006,12 +1008,6 @@ class LinkDotFindVisitor : public AstNVisitor {
// Var: Remember its name for later resolution
UASSERT_OBJ(m_curSymp && m_modSymp, nodep, "Var not under module?");
iterateChildren(nodep);
- if (m_ftaskp && nodep->isParam()) {
- nodep->v3warn(E_UNSUPPORTED,
- "Unsupported: Parameters in functions"); // Big3 unsupported too
- VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
- return;
- }
if (nodep->isFuncLocal() && nodep->lifetime().isStatic()) {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: 'static' function/task variables");
} else if (nodep->isClassMember() && nodep->lifetime().isStatic()) {
@@ -1951,7 +1947,7 @@ private:
m_ds.m_dotPos = DP_SCOPE;
// m_ds.m_dotText communicates the cell prefix between stages
- if (VN_IS(nodep->lhsp(), PackageRef)) {
+ if (VN_IS(nodep->lhsp(), ClassOrPackageRef)) {
// if (!start) { nodep->lhsp()->v3error("Package reference may not be embedded in
// dotted reference"); m_ds.m_dotErr=true; }
m_ds.m_dotPos = DP_PACKAGE;
@@ -2047,9 +2043,16 @@ private:
expectWhat = "scope/variable";
allowScope = true;
allowVar = true;
- UASSERT_OBJ(VN_IS(m_ds.m_dotp->lhsp(), PackageRef), m_ds.m_dotp->lhsp(),
+ UASSERT_OBJ(VN_IS(m_ds.m_dotp->lhsp(), ClassOrPackageRef), m_ds.m_dotp->lhsp(),
"Bad package link");
- packagep = VN_CAST(m_ds.m_dotp->lhsp(), PackageRef)->packagep();
+ AstClassOrPackageRef* cpackagerefp
+ = VN_CAST(m_ds.m_dotp->lhsp(), ClassOrPackageRef);
+ packagep = cpackagerefp->packagep();
+ if (!packagep && cpackagerefp->classOrPackagep()) {
+ nodep->v3warn(E_UNSUPPORTED,
+ "Unsupported: Class '::' references: "
+ << AstNode::prettyNameQ(cpackagerefp->name()));
+ }
UASSERT_OBJ(packagep, m_ds.m_dotp->lhsp(), "Bad package link");
m_ds.m_dotSymp = m_statep->getNodeSym(packagep);
m_ds.m_dotPos = DP_SCOPE;
@@ -2399,11 +2402,19 @@ private:
if (nodep->user3SetOnce()) return;
UINFO(8, " " << nodep << endl);
if (m_ds.m_dotp && m_ds.m_dotPos == DP_PACKAGE) {
- UASSERT_OBJ(VN_IS(m_ds.m_dotp->lhsp(), PackageRef), m_ds.m_dotp->lhsp(),
+ UASSERT_OBJ(VN_IS(m_ds.m_dotp->lhsp(), ClassOrPackageRef), m_ds.m_dotp->lhsp(),
"Bad package link");
- UASSERT_OBJ(VN_CAST(m_ds.m_dotp->lhsp(), PackageRef)->packagep(), m_ds.m_dotp->lhsp(),
- "Bad package link");
- nodep->packagep(VN_CAST(m_ds.m_dotp->lhsp(), PackageRef)->packagep());
+ AstClassOrPackageRef* cpackagerefp = VN_CAST(m_ds.m_dotp->lhsp(), ClassOrPackageRef);
+ if (cpackagerefp->name() == "process" || cpackagerefp->name() == "local") {
+ nodep->v3warn(E_UNSUPPORTED,
+ "Unsupported: " << AstNode::prettyNameQ(cpackagerefp->name()));
+ }
+ if (cpackagerefp->paramsp()) {
+ nodep->v3warn(E_UNSUPPORTED, "Unsupported: parameterized packages");
+ }
+ UASSERT_OBJ(VN_CAST(m_ds.m_dotp->lhsp(), ClassOrPackageRef)->packagep(),
+ m_ds.m_dotp->lhsp(), "Bad package link");
+ nodep->packagep(VN_CAST(m_ds.m_dotp->lhsp(), ClassOrPackageRef)->packagep());
m_ds.m_dotPos = DP_SCOPE;
m_ds.m_dotp = NULL;
} else if (m_ds.m_dotp && m_ds.m_dotPos == DP_FINAL) {
@@ -2667,12 +2678,30 @@ private:
virtual void visit(AstRefDType* nodep) VL_OVERRIDE {
// Resolve its reference
if (nodep->user3SetOnce()) return;
+ if (AstNode* cpackagep = nodep->classOrPackagep()) {
+ if (AstClassOrPackageRef* cpackagerefp = VN_CAST(cpackagep, ClassOrPackageRef)) {
+ if (cpackagerefp->packagep()) {
+ nodep->packagep(cpackagerefp->packagep());
+ } else {
+ cpackagep->v3warn(E_UNSUPPORTED, "Unsupported: Class '::' reference");
+ // if (cpackagerefp->paramsp()) {
+ // nodep->v3warn(E_UNSUPPORTED, "Unsupported: parameterized packages");
+ // }
+ }
+ } else {
+ cpackagep->v3warn(E_UNSUPPORTED,
+ "Unsupported: Multiple '::' package/class reference");
+ }
+ VL_DO_DANGLING(cpackagep->unlinkFrBack()->deleteTree(), cpackagep);
+ } else if (nodep->paramsp()) {
+ nodep->v3warn(E_UNSUPPORTED, "Unsupported: parameterized packages");
+ }
if (m_ds.m_dotp && m_ds.m_dotPos == DP_PACKAGE) {
- UASSERT_OBJ(VN_IS(m_ds.m_dotp->lhsp(), PackageRef), m_ds.m_dotp->lhsp(),
+ UASSERT_OBJ(VN_IS(m_ds.m_dotp->lhsp(), ClassOrPackageRef), m_ds.m_dotp->lhsp(),
"Bad package link");
- UASSERT_OBJ(VN_CAST(m_ds.m_dotp->lhsp(), PackageRef)->packagep(), m_ds.m_dotp->lhsp(),
- "Bad package link");
- nodep->packagep(VN_CAST(m_ds.m_dotp->lhsp(), PackageRef)->packagep());
+ UASSERT_OBJ(VN_CAST(m_ds.m_dotp->lhsp(), ClassOrPackageRef)->packagep(),
+ m_ds.m_dotp->lhsp(), "Bad package link");
+ nodep->packagep(VN_CAST(m_ds.m_dotp->lhsp(), ClassOrPackageRef)->packagep());
m_ds.m_dotPos = DP_SCOPE;
m_ds.m_dotp = NULL;
} else {
diff --git a/src/V3Number.cpp b/src/V3Number.cpp
index e7b19e4e5..d684b9ed5 100644
--- a/src/V3Number.cpp
+++ b/src/V3Number.cpp
@@ -2232,13 +2232,24 @@ V3Number& V3Number::opSelInto(const V3Number& lhs, int lsbval, int width) {
//======================================================================
// Ops - Floating point
-V3Number& V3Number::opIToRD(const V3Number& lhs) {
+V3Number& V3Number::opIToRD(const V3Number& lhs, bool isSigned) {
NUM_ASSERT_OP_ARGS1(lhs);
NUM_ASSERT_LOGIC_ARGS1(lhs);
// IEEE says we ignore x/z in real conversions
V3Number noxz(lhs);
noxz.opAssignNonXZ(lhs);
- return setDouble(noxz.toSInt());
+ double d = 0;
+ bool negate = isSigned && noxz.isNegative();
+ if (negate) {
+ V3Number noxz_signed = noxz;
+ noxz.opNegate(noxz_signed);
+ }
+ for (int bit = noxz.width() - 1; bit >= 0; bit--) {
+ // Some precision might be lost in this add, that's what we want
+ if (noxz.bitIs1(bit)) d += exp2(bit);
+ }
+ if (negate) d = -d;
+ return setDouble(d);
}
V3Number& V3Number::opRToIS(const V3Number& lhs) {
NUM_ASSERT_OP_ARGS1(lhs);
diff --git a/src/V3Number.h b/src/V3Number.h
index 9245b2dfd..1426cfd6e 100644
--- a/src/V3Number.h
+++ b/src/V3Number.h
@@ -385,7 +385,8 @@ public:
V3Number& opLteS(const V3Number& lhs, const V3Number& rhs); // Signed
// "D" - double (aka real) math
- V3Number& opIToRD(const V3Number& lhs);
+ V3Number& opIToRD(const V3Number& lhs, bool isSigned = false);
+ V3Number& opISToRD(const V3Number& lhs) { return opIToRD(lhs, true); }
V3Number& opRToIS(const V3Number& lhs);
V3Number& opRToIRoundS(const V3Number& lhs);
V3Number& opRealToBits(const V3Number& lhs);
diff --git a/src/V3Param.cpp b/src/V3Param.cpp
index ad43808c2..550abe513 100644
--- a/src/V3Param.cpp
+++ b/src/V3Param.cpp
@@ -106,6 +106,8 @@ private:
typedef std::deque CellList;
CellList m_cellps; // Cells left to process (in this module)
+ AstNodeFTask* m_ftaskp; // Function/task reference
+
AstNodeModule* m_modp; // Current module being processed
string m_unlinkedTxt; // Text for AstUnlinkedRef
@@ -302,6 +304,11 @@ private:
nodep->user5p(genHierNamep);
m_cellps.push_back(nodep);
}
+ virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE {
+ m_ftaskp = nodep;
+ iterateChildren(nodep);
+ m_ftaskp = NULL;
+ }
// Make sure all parameters are constantified
virtual void visit(AstVar* nodep) VL_OVERRIDE {
@@ -323,6 +330,16 @@ private:
new AstAssign(nodep->fileline(),
new AstVarRef(nodep->fileline(), nodep, true),
nodep->valuep()->cloneTree(true))));
+ if (m_ftaskp) {
+ // We put the initial in wrong place under a function. We
+ // should move the parameter out of the function and to the
+ // module, with appropriate dotting, but this confuses LinkDot
+ // (as then name isn't found later), so punt - probably can
+ // treat as static function variable when that is supported.
+ nodep->v3warn(
+ E_UNSUPPORTED,
+ "Unsupported: Parameters in functions with complex assign");
+ }
}
}
}
@@ -556,6 +573,7 @@ public:
// CONSTRUCTORS
explicit ParamVisitor(AstNetlist* nodep) {
m_longId = 0;
+ m_ftaskp = NULL;
m_modp = NULL;
m_nextValue = 1;
//
@@ -617,7 +635,7 @@ void ParamVisitor::visitCell(AstCell* nodep, const string& hierName) {
// This prevents making additional modules, and makes coverage more
// obvious as it won't show up under a unique module page name.
} else if (exprp->num().isDouble() || exprp->num().isString()
- || exprp->num().isFourState()) {
+ || exprp->num().isFourState() || exprp->num().width() != 32) {
longname
+= ("_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp));
any_overrides = true;
diff --git a/src/V3ParseImp.h b/src/V3ParseImp.h
index 4c904b2cb..d9d5ae2f1 100644
--- a/src/V3ParseImp.h
+++ b/src/V3ParseImp.h
@@ -139,7 +139,6 @@ struct V3ParseBisonYYSType {
AstSenItem* senitemp;
AstNodeVarRef* varnodep;
AstPackage* packagep;
- AstPackageRef* packagerefp;
AstParseRef* parserefp;
AstPatMember* patmemberp;
AstPattern* patternp;
diff --git a/src/V3ProtectLib.cpp b/src/V3ProtectLib.cpp
index 06fd9d726..5d6c2fe28 100644
--- a/src/V3ProtectLib.cpp
+++ b/src/V3ProtectLib.cpp
@@ -60,6 +60,7 @@ private:
string m_libName;
string m_topName;
bool m_foundTop; // Have seen the top module
+ bool m_hasClk; // True if the top module has sequential logic
// VISITORS
virtual void visit(AstNetlist* nodep) VL_OVERRIDE {
@@ -79,6 +80,8 @@ private:
UASSERT_OBJ(!m_foundTop, nodep, "Multiple root modules");
}
FileLine* fl = nodep->fileline();
+ // Need to know the existence of clk before createSvFile()
+ m_hasClk = checkIfClockExists(nodep);
createSvFile(fl);
createCppFile(fl);
@@ -162,14 +165,16 @@ private:
txtp->addNodep(m_comboPortsp);
txtp->addText(fl, ");\n\n");
seqComment(txtp, fl);
- m_seqPortsp = new AstTextBlock(fl,
- "import \"DPI-C\" function longint " + m_libName
- + "_protectlib_seq_update"
- "(\n",
- false, true);
- m_seqPortsp->addText(fl, "chandle handle__V\n");
- txtp->addNodep(m_seqPortsp);
- txtp->addText(fl, ");\n\n");
+ if (m_hasClk) {
+ m_seqPortsp = new AstTextBlock(fl,
+ "import \"DPI-C\" function longint " + m_libName
+ + "_protectlib_seq_update"
+ "(\n",
+ false, true);
+ m_seqPortsp->addText(fl, "chandle handle__V\n");
+ txtp->addNodep(m_seqPortsp);
+ txtp->addText(fl, ");\n\n");
+ }
comboIgnoreComment(txtp, fl);
m_comboIgnorePortsp = new AstTextBlock(fl,
"import \"DPI-C\" function void " + m_libName
@@ -192,12 +197,12 @@ private:
m_tmpDeclsp = new AstTextBlock(fl);
txtp->addNodep(m_tmpDeclsp);
txtp->addText(fl, "\ntime last_combo_seqnum__V;\n");
- txtp->addText(fl, "time last_seq_seqnum__V;\n\n");
+ if (m_hasClk) { txtp->addText(fl, "time last_seq_seqnum__V;\n\n"); }
// CPP hash value
addComment(txtp, fl, "Hash value to make sure this file and the corresponding");
addComment(txtp, fl, "library agree");
- m_hashValuep = new AstTextBlock(fl, "localparam int protectlib_hash__V = ");
+ m_hashValuep = new AstTextBlock(fl, "localparam int protectlib_hash__V = 32'd");
txtp->addNodep(m_hashValuep);
txtp->addText(fl, "\n");
@@ -222,33 +227,41 @@ private:
txtp->addText(fl, "end\n\n");
// Sequential process
- addComment(txtp, fl, "Evaluate clock edges");
- m_clkSensp = new AstTextBlock(fl, "always @(", false, true);
- txtp->addNodep(m_clkSensp);
- txtp->addText(fl, ") begin\n");
- m_comboIgnoreParamsp
- = new AstTextBlock(fl, m_libName + "_protectlib_combo_ignore(\n", false, true);
- m_comboIgnoreParamsp->addText(fl, "handle__V\n");
- txtp->addNodep(m_comboIgnoreParamsp);
- txtp->addText(fl, ");\n");
- m_seqParamsp = new AstTextBlock(
- fl, "last_seq_seqnum__V <= " + m_libName + "_protectlib_seq_update(\n", false, true);
- m_seqParamsp->addText(fl, "handle__V\n");
- txtp->addNodep(m_seqParamsp);
- txtp->addText(fl, ");\n");
- m_nbAssignsp = new AstTextBlock(fl);
- txtp->addNodep(m_nbAssignsp);
- txtp->addText(fl, "end\n\n");
+ if (m_hasClk) {
+ addComment(txtp, fl, "Evaluate clock edges");
+ m_clkSensp = new AstTextBlock(fl, "always @(", false, true);
+ txtp->addNodep(m_clkSensp);
+ txtp->addText(fl, ") begin\n");
+ m_comboIgnoreParamsp
+ = new AstTextBlock(fl, m_libName + "_protectlib_combo_ignore(\n", false, true);
+ m_comboIgnoreParamsp->addText(fl, "handle__V\n");
+ txtp->addNodep(m_comboIgnoreParamsp);
+ txtp->addText(fl, ");\n");
+ m_seqParamsp = new AstTextBlock(
+ fl, "last_seq_seqnum__V <= " + m_libName + "_protectlib_seq_update(\n", false,
+ true);
+ m_seqParamsp->addText(fl, "handle__V\n");
+ txtp->addNodep(m_seqParamsp);
+ txtp->addText(fl, ");\n");
+ m_nbAssignsp = new AstTextBlock(fl);
+ txtp->addNodep(m_nbAssignsp);
+ txtp->addText(fl, "end\n\n");
+ }
// Select between combinatorial and sequential results
addComment(txtp, fl, "Select between combinatorial and sequential results");
txtp->addText(fl, "always @(*) begin\n");
- m_seqAssignsp = new AstTextBlock(fl, "if (last_seq_seqnum__V > "
- "last_combo_seqnum__V) begin\n");
- txtp->addNodep(m_seqAssignsp);
- m_comboAssignsp = new AstTextBlock(fl, "end else begin\n");
- txtp->addNodep(m_comboAssignsp);
- txtp->addText(fl, "end\n");
+ if (m_hasClk) {
+ m_seqAssignsp = new AstTextBlock(fl, "if (last_seq_seqnum__V > "
+ "last_combo_seqnum__V) begin\n");
+ txtp->addNodep(m_seqAssignsp);
+ m_comboAssignsp = new AstTextBlock(fl, "end else begin\n");
+ txtp->addNodep(m_comboAssignsp);
+ txtp->addText(fl, "end\n");
+ } else {
+ m_comboAssignsp = new AstTextBlock(fl, "");
+ txtp->addNodep(m_comboAssignsp);
+ }
txtp->addText(fl, "end\n\n");
// Final
@@ -327,19 +340,21 @@ private:
txtp->addText(fl, "return handlep__V->m_seqnum++;\n");
txtp->addText(fl, "}\n\n");
- seqComment(txtp, fl);
- m_cSeqParamsp = new AstTextBlock(
- fl, "long long " + m_libName + "_protectlib_seq_update(\n", false, true);
- m_cSeqParamsp->addText(fl, "void* vhandlep__V\n");
- txtp->addNodep(m_cSeqParamsp);
- txtp->addText(fl, ")\n");
- m_cSeqClksp = new AstTextBlock(fl, "{\n");
- castPtr(fl, m_cSeqClksp);
- txtp->addNodep(m_cSeqClksp);
- m_cSeqOutsp = new AstTextBlock(fl, "handlep__V->eval();\n");
- txtp->addNodep(m_cSeqOutsp);
- txtp->addText(fl, "return handlep__V->m_seqnum++;\n");
- txtp->addText(fl, "}\n\n");
+ if (m_hasClk) {
+ seqComment(txtp, fl);
+ m_cSeqParamsp = new AstTextBlock(
+ fl, "long long " + m_libName + "_protectlib_seq_update(\n", false, true);
+ m_cSeqParamsp->addText(fl, "void* vhandlep__V\n");
+ txtp->addNodep(m_cSeqParamsp);
+ txtp->addText(fl, ")\n");
+ m_cSeqClksp = new AstTextBlock(fl, "{\n");
+ castPtr(fl, m_cSeqClksp);
+ txtp->addNodep(m_cSeqClksp);
+ m_cSeqOutsp = new AstTextBlock(fl, "handlep__V->eval();\n");
+ txtp->addNodep(m_cSeqOutsp);
+ txtp->addText(fl, "return handlep__V->m_seqnum++;\n");
+ txtp->addText(fl, "}\n\n");
+ }
comboIgnoreComment(txtp, fl);
m_cIgnoreParamsp = new AstTextBlock(
@@ -369,6 +384,7 @@ private:
}
if (nodep->direction() == VDirection::INPUT) {
if (nodep->isUsedClock() || nodep->attrClocker() == VVarAttrClocker::CLOCKER_YES) {
+ UASSERT_OBJ(m_hasClk, nodep, "checkIfClockExists() didn't find this clock");
handleClock(nodep);
} else {
handleDataInput(nodep);
@@ -396,8 +412,10 @@ private:
FileLine* fl = varp->fileline();
handleInput(varp);
m_seqPortsp->addNodep(varp->cloneTree(false));
- m_seqParamsp->addText(fl, varp->name() + "\n");
- m_clkSensp->addText(fl, "edge(" + varp->name() + ")");
+ if (m_hasClk) {
+ m_seqParamsp->addText(fl, varp->name() + "\n");
+ m_clkSensp->addText(fl, "posedge " + varp->name() + " or negedge " + varp->name());
+ }
m_cSeqParamsp->addText(fl, varp->dpiArgType(true, false) + "\n");
m_cSeqClksp->addText(fl, cInputConnection(varp));
}
@@ -408,7 +426,7 @@ private:
m_comboPortsp->addNodep(varp->cloneTree(false));
m_comboParamsp->addText(fl, varp->name() + "\n");
m_comboIgnorePortsp->addNodep(varp->cloneTree(false));
- m_comboIgnoreParamsp->addText(fl, varp->name() + "\n");
+ if (m_hasClk) { m_comboIgnoreParamsp->addText(fl, varp->name() + "\n"); }
m_cComboParamsp->addText(fl, varp->dpiArgType(true, false) + "\n");
m_cComboInsp->addText(fl, cInputConnection(varp));
m_cIgnoreParamsp->addText(fl, varp->dpiArgType(true, false) + "\n");
@@ -421,29 +439,49 @@ private:
m_modPortsp->addNodep(varp->cloneTree(false));
m_comboPortsp->addNodep(varp->cloneTree(false));
m_comboParamsp->addText(fl, varp->name() + "_combo__V\n");
- m_seqPortsp->addNodep(varp->cloneTree(false));
- m_seqParamsp->addText(fl, varp->name() + "_tmp__V\n");
+ if (m_hasClk) {
+ m_seqPortsp->addNodep(varp->cloneTree(false));
+ m_seqParamsp->addText(fl, varp->name() + "_tmp__V\n");
+ }
AstNodeDType* comboDtypep = varp->dtypep()->cloneTree(false);
m_comboDeclsp->addNodep(comboDtypep);
m_comboDeclsp->addText(fl, " " + varp->name() + "_combo__V;\n");
- AstNodeDType* seqDtypep = varp->dtypep()->cloneTree(false);
- m_seqDeclsp->addNodep(seqDtypep);
- m_seqDeclsp->addText(fl, " " + varp->name() + "_seq__V;\n");
+ if (m_hasClk) {
+ AstNodeDType* seqDtypep = varp->dtypep()->cloneTree(false);
+ m_seqDeclsp->addNodep(seqDtypep);
+ m_seqDeclsp->addText(fl, " " + varp->name() + "_seq__V;\n");
- AstNodeDType* tmpDtypep = varp->dtypep()->cloneTree(false);
- m_tmpDeclsp->addNodep(tmpDtypep);
- m_tmpDeclsp->addText(fl, " " + varp->name() + "_tmp__V;\n");
+ AstNodeDType* tmpDtypep = varp->dtypep()->cloneTree(false);
+ m_tmpDeclsp->addNodep(tmpDtypep);
+ m_tmpDeclsp->addText(fl, " " + varp->name() + "_tmp__V;\n");
- m_nbAssignsp->addText(fl, varp->name() + "_seq__V <= " + varp->name() + "_tmp__V;\n");
- m_seqAssignsp->addText(fl, varp->name() + " = " + varp->name() + "_seq__V;\n");
+ m_nbAssignsp->addText(fl, varp->name() + "_seq__V <= " + varp->name() + "_tmp__V;\n");
+ m_seqAssignsp->addText(fl, varp->name() + " = " + varp->name() + "_seq__V;\n");
+ }
m_comboAssignsp->addText(fl, varp->name() + " = " + varp->name() + "_combo__V;\n");
m_cComboParamsp->addText(fl, varp->dpiArgType(true, false) + "\n");
m_cComboOutsp->addText(fl,
V3Task::assignInternalToDpi(varp, true, "", "", "handlep__V->"));
- m_cSeqParamsp->addText(fl, varp->dpiArgType(true, false) + "\n");
- m_cSeqOutsp->addText(fl, V3Task::assignInternalToDpi(varp, true, "", "", "handlep__V->"));
+ if (m_hasClk) {
+ m_cSeqParamsp->addText(fl, varp->dpiArgType(true, false) + "\n");
+ m_cSeqOutsp->addText(fl,
+ V3Task::assignInternalToDpi(varp, true, "", "", "handlep__V->"));
+ }
+ }
+
+ static bool checkIfClockExists(AstNodeModule* modp) {
+ for (AstNode* stmtp = modp->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
+ if (AstVar* varp = VN_CAST(stmtp, Var)) {
+ if (varp->direction() == VDirection::INPUT
+ && (varp->isUsedClock()
+ || varp->attrClocker() == VVarAttrClocker::CLOCKER_YES)) {
+ return true;
+ }
+ }
+ }
+ return false;
}
public:
@@ -475,7 +513,8 @@ public:
, m_cIgnoreParamsp(NULL)
, m_libName(v3Global.opt.protectLib())
, m_topName(v3Global.opt.prefix())
- , m_foundTop(false) {
+ , m_foundTop(false)
+ , m_hasClk(false) {
iterate(nodep);
}
};
diff --git a/src/V3Width.cpp b/src/V3Width.cpp
index de04c0a82..194e46c18 100644
--- a/src/V3Width.cpp
+++ b/src/V3Width.cpp
@@ -332,7 +332,6 @@ private:
//========
// Widths: Output real, input integer signed
virtual void visit(AstBitsToRealD* nodep) VL_OVERRIDE { visit_Or_Lu64(nodep); }
- virtual void visit(AstIToRD* nodep) VL_OVERRIDE { visit_Or_Ls32(nodep); }
// Widths: Output integer signed, input real
virtual void visit(AstRToIS* nodep) VL_OVERRIDE { visit_Os32_Lr(nodep); }
@@ -1032,6 +1031,12 @@ private:
// We don't size the constant until we commit the widths, as need parameters
// to remain unsized, and numbers to remain unsized to avoid backp() warnings
}
+ virtual void visit(AstFell* nodep) VL_OVERRIDE {
+ if (m_vup->prelim()) {
+ iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH);
+ nodep->dtypeSetLogicBool();
+ }
+ }
virtual void visit(AstPast* nodep) VL_OVERRIDE {
if (m_vup->prelim()) {
iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH);
@@ -1056,12 +1061,27 @@ private:
}
}
}
+ virtual void visit(AstRose* nodep) VL_OVERRIDE {
+ if (m_vup->prelim()) {
+ iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH);
+ nodep->dtypeSetLogicBool();
+ }
+ }
+
virtual void visit(AstSampled* nodep) VL_OVERRIDE {
if (m_vup->prelim()) {
iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH);
nodep->dtypeFrom(nodep->exprp());
}
}
+
+ virtual void visit(AstStable* nodep) VL_OVERRIDE {
+ if (m_vup->prelim()) {
+ iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH);
+ nodep->dtypeSetLogicBool();
+ }
+ }
+
virtual void visit(AstRand* nodep) VL_OVERRIDE {
if (m_vup->prelim()) {
nodep->dtypeSetSigned32(); // Says the spec
@@ -1524,7 +1544,8 @@ private:
virtual void visit(AstCast* nodep) VL_OVERRIDE {
nodep->dtypep(iterateEditMoveDTypep(nodep, nodep->subDTypep()));
// if (debug()) nodep->dumpTree(cout, " CastPre: ");
- userIterateAndNext(nodep->lhsp(), WidthVP(SELF, BOTH).p());
+ userIterateAndNext(nodep->lhsp(), WidthVP(SELF, PRELIM).p());
+
// When more general casts are supported, the cast elimination will be done later.
// For now, replace it ASAP, so widthing can propagate easily
// The cast may change signing, but we don't know the sign yet. Make it so.
@@ -1537,11 +1558,19 @@ private:
// Note widthCheckSized might modify nodep->lhsp()
AstNodeDType* subDTypep = nodep->findLogicDType(nodep->width(), nodep->width(),
nodep->lhsp()->dtypep()->numeric());
- widthCheckSized(nodep, "Cast", nodep->lhsp(), subDTypep, EXTEND_EXP, false);
+ iterateCheck(nodep, "value", nodep->lhsp(), CONTEXT, FINAL, subDTypep, EXTEND_EXP,
+ false);
+ } else {
+ iterateCheck(nodep, "value", nodep->lhsp(), SELF, FINAL, nodep->lhsp()->dtypep(),
+ EXTEND_EXP, false);
}
AstNode* newp = nodep->lhsp()->unlinkFrBack();
if (basicp->isDouble() && !newp->isDouble()) {
- newp = new AstIToRD(nodep->fileline(), newp);
+ if (newp->isSigned()) {
+ newp = new AstISToRD(nodep->fileline(), newp);
+ } else {
+ newp = new AstIToRD(nodep->fileline(), newp);
+ }
} else if (!basicp->isDouble() && newp->isDouble()) {
if (basicp->isSigned()) {
newp = new AstRToIRoundS(nodep->fileline(), newp);
@@ -3923,16 +3952,27 @@ private:
iterateCheck(nodep, "LHS", nodep->lhsp(), SELF, FINAL, subDTypep, EXTEND_EXP);
}
}
- void visit_Or_Ls32(AstNodeUniop* nodep) {
- // CALLER: AstIToRD
+ virtual void visit(AstIToRD* nodep) VL_OVERRIDE {
// Real: Output real
// LHS presumed self-determined, then coerced to real
if (m_vup->prelim()) { // First stage evaluation
nodep->dtypeSetDouble();
- AstNodeDType* subDTypep = nodep->findLogicDType(32, 32, VSigning::SIGNED);
- // Self-determined operand
+ // Self-determined operand (TODO check if numeric type)
+ userIterateAndNext(nodep->lhsp(), WidthVP(SELF, PRELIM).p());
+ if (nodep->lhsp()->isSigned()) {
+ nodep->replaceWith(
+ new AstISToRD(nodep->fileline(), nodep->lhsp()->unlinkFrBack()));
+ VL_DO_DANGLING(nodep->deleteTree(), nodep);
+ }
+ }
+ }
+ virtual void visit(AstISToRD* nodep) VL_OVERRIDE {
+ // Real: Output real
+ // LHS presumed self-determined, then coerced to real
+ if (m_vup->prelim()) { // First stage evaluation
+ nodep->dtypeSetDouble();
+ // Self-determined operand (TODO check if numeric type)
userIterateAndNext(nodep->lhsp(), WidthVP(SELF, PRELIM).p());
- iterateCheck(nodep, "LHS", nodep->lhsp(), SELF, FINAL, subDTypep, EXTEND_EXP);
}
}
void visit_Os32_Lr(AstNodeUniop* nodep) {
@@ -4792,7 +4832,12 @@ private:
UINFO(6, " spliceCvtD: " << nodep << endl);
AstNRelinker linker;
nodep->unlinkFrBack(&linker);
- AstNode* newp = new AstIToRD(nodep->fileline(), nodep);
+ AstNode* newp;
+ if (nodep->dtypep()->skipRefp()->isSigned()) {
+ newp = new AstISToRD(nodep->fileline(), nodep);
+ } else {
+ newp = new AstIToRD(nodep->fileline(), nodep);
+ }
linker.relink(newp);
return newp;
} else {
diff --git a/src/Verilator.cpp b/src/Verilator.cpp
index 66800410b..dc040cc50 100644
--- a/src/Verilator.cpp
+++ b/src/Verilator.cpp
@@ -193,12 +193,16 @@ static void process() {
// Expand inouts, stage 2
// Also simplify pin connections to always be AssignWs in prep for V3Unknown
V3Tristate::tristateAll(v3Global.rootp());
+ }
+ if (!v3Global.opt.xmlOnly()) {
// 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);
+ }
+ if (!(v3Global.opt.xmlOnly() && !v3Global.opt.flatten())) {
// Module inlining
// Cannot remove dead variables after this, as alias information for final
// V3Scope's V3LinkDot is in the AstVar.
diff --git a/src/verilog.l b/src/verilog.l
index c309be3fd..f21a64f1c 100644
--- a/src/verilog.l
+++ b/src/verilog.l
@@ -422,6 +422,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"$dimensions" { FL; return yD_DIMENSIONS; }
"$error" { FL; return yD_ERROR; }
"$fatal" { FL; return yD_FATAL; }
+ "$fell" { FL; return yD_FELL; }
"$high" { FL; return yD_HIGH; }
"$increment" { FL; return yD_INCREMENT; }
"$info" { FL; return yD_INFO; }
@@ -434,7 +435,9 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"$past" { FL; return yD_PAST; }
"$right" { FL; return yD_RIGHT; }
"$root" { FL; return yD_ROOT; }
+ "$rose" { FL; return yD_ROSE; }
"$size" { FL; return yD_SIZE; }
+ "$stable" { FL; return yD_STABLE; }
"$unpacked_dimensions" { FL; return yD_UNPACKED_DIMENSIONS; }
"$warning" { FL; return yD_WARNING; }
/* SV2005 Keywords */
diff --git a/src/verilog.y b/src/verilog.y
index fa324cdfa..9ae8db91a 100644
--- a/src/verilog.y
+++ b/src/verilog.y
@@ -264,17 +264,6 @@ int V3ParseGrammar::s_modTypeImpNum = 0;
GRAMMARP->m_instParamp = paramsp; \
}
-static AstPackage* CAST_PACKAGE_CLASS(AstNode* nodep) {
- if (!nodep) {
- return NULL;
- } else if (AstPackage* pkgp = VN_CAST(nodep, Package)) {
- return pkgp;
- } else {
- BBUNSUP(nodep->fileline(), "Unsupported class :: reference");
- return NULL;
- }
-}
-
#define DEL(nodep) \
{ \
if (nodep) nodep->deleteTree(); \
@@ -730,6 +719,7 @@ BISONPRE_VERSION(3.0,%define parse.error verbose)
%token yD_FDISPLAYB "$fdisplayb"
%token yD_FDISPLAYH "$fdisplayh"
%token yD_FDISPLAYO "$fdisplayo"
+%token yD_FELL "$fell"
%token yD_FEOF "$feof"
%token yD_FERROR "$ferror"
%token yD_FFLUSH "$fflush"
@@ -771,6 +761,7 @@ BISONPRE_VERSION(3.0,%define parse.error verbose)
%token yD_REWIND "$rewind"
%token yD_RIGHT "$right"
%token yD_ROOT "$root"
+%token yD_ROSE "$rose"
%token yD_RTOI "$rtoi"
%token yD_SAMPLED "$sampled"
%token yD_SFORMAT "$sformat"
@@ -782,6 +773,7 @@ BISONPRE_VERSION(3.0,%define parse.error verbose)
%token yD_SIZE "$size"
%token yD_SQRT "$sqrt"
%token yD_SSCANF "$sscanf"
+%token yD_STABLE "$stable"
%token yD_STIME "$stime"
%token yD_STOP "$stop"
%token yD_SWRITE "$swrite"
@@ -1476,7 +1468,7 @@ program_declaration: // IEEE: program_declaration + program_nonansi_header + pr
pgmFront:
yPROGRAM lifetimeE idAny/*new_program*/
- { $$ = new AstModule($3,*$3);
+ { $$ = new AstModule($3, *$3, true);
$$->lifetime($2);
$$->inLibrary(PARSEP->inLibrary() || $$->fileline()->celldefineOn());
$$->modTrace(GRAMMARP->allTracingOn($$->fileline()));
@@ -1783,8 +1775,8 @@ simple_type: // ==IEEE: simple_type
// // Even though we looked up the type and have a AstNode* to it,
// // we can't fully resolve it because it may have been just a forward definition.
| packageClassScopeE idType
- { AstRefDType* refp = new AstRefDType($2, *$2);
- refp->packagep($1); $$ = refp; }
+ { AstRefDType* refp = new AstRefDType($2, *$2, $1, NULL);
+ $$ = refp; }
//
// // { generate_block_identifer ... } '.'
// // Need to determine if generate_block_identifier can be lex-detected
@@ -1801,13 +1793,10 @@ data_type: // ==IEEE: data_type
// // IEEE: ps_covergroup_identifier
// // Don't distinguish between types and classes so all these combined
| packageClassScopeE idType packed_dimensionListE
- { AstRefDType* refp = new AstRefDType($2, *$2);
- refp->packagep($1);
+ { AstRefDType* refp = new AstRefDType($2, *$2, $1, NULL);
$$ = GRAMMARP->createArray(refp, $3, true); }
| packageClassScopeE idType parameter_value_assignmentClass packed_dimensionListE
- { AstRefDType* refp = new AstRefDType($2, *$2);
- refp->packagep($1);
- BBUNSUP($3->fileline(), "Unsupported: Parameter classes");
+ { AstRefDType* refp = new AstRefDType($2, *$2, $1, $3);
$$ = GRAMMARP->createArray(refp, $4, true); }
;
@@ -1851,7 +1840,8 @@ var_data_type: // ==IEEE: var_data_type
;
type_reference: // ==IEEE: type_reference
- yTYPE '(' exprOrDataType ')' { $$ = new AstRefDType($1, AstRefDType::FlagTypeOfExpr(), $3); }
+ yTYPE '(' exprOrDataType ')'
+ { $$ = new AstRefDType($1, AstRefDType::FlagTypeOfExpr(), $3); }
;
struct_unionDecl: // IEEE: part of data_type
@@ -2021,8 +2011,7 @@ enum_base_typeE: // IEEE: enum_base_type
| idAny rangeListE
{ $$ = GRAMMARP->createArray(new AstRefDType($1, *$1), $2, true); }
| packageClassScope idAny rangeListE
- { AstRefDType* refp = new AstRefDType($2, *$2);
- refp->packagep($1);
+ { AstRefDType* refp = new AstRefDType($2, *$2, $1, NULL);
$$ = GRAMMARP->createArray(refp, $3, true); }
;
@@ -2526,7 +2515,7 @@ delay_control: //== IEEE: delay_control
delay_value: // ==IEEE:delay_value
// // IEEE: ps_identifier
- packageClassScopeE varRefBase { $$ = $2; $2->packagep($1); }
+ packageClassScopeE varRefBase { $$ = AstDot::newIfPkg($2, $1, $2); }
| yaINTNUM { $$ = new AstConst($1, *$1); }
| yaFLOATNUM { $$ = new AstConst($1, AstConst::RealDouble(), $1); }
| timeNumAdjusted { $$ = $1; }
@@ -3412,7 +3401,7 @@ taskRef: // IEEE: part of tf_call
id { $$ = new AstTaskRef($1,*$1,NULL); }
| id '(' list_of_argumentsE ')' { $$ = new AstTaskRef($1,*$1,$3); }
| packageClassScope id '(' list_of_argumentsE ')'
- { $$ = AstDot::newIfPkg($2, CAST_PACKAGE_CLASS($1), new AstTaskRef($2, *$2, $4)); }
+ { $$ = AstDot::newIfPkg($2, $1, new AstTaskRef($2, *$2, $4)); }
;
funcRef: // IEEE: part of tf_call
@@ -3428,7 +3417,7 @@ funcRef: // IEEE: part of tf_call
id '(' list_of_argumentsE ')'
{ $$ = new AstFuncRef($1, *$1, $3); }
| packageClassScope id '(' list_of_argumentsE ')'
- { $$ = AstDot::newIfPkg($2, CAST_PACKAGE_CLASS($1), new AstFuncRef($2, *$2, $4)); }
+ { $$ = AstDot::newIfPkg($2, $1, new AstFuncRef($2, *$2, $4)); }
//UNSUP list_of_argumentE should be pev_list_of_argumentE
//UNSUP: idDotted is really just id to allow dotted method calls
;
@@ -3609,6 +3598,8 @@ system_f_call_or_t: // IEEE: part of system_tf_call (can be task or func)
| yD_COUNTONES '(' expr ')' { $$ = new AstCountOnes($1,$3); }
| yD_DIMENSIONS '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_DIMENSIONS,$3); }
| yD_EXP '(' expr ')' { $$ = new AstExpD($1,$3); }
+ | yD_FELL '(' expr ')' { $$ = new AstFell($1,$3); }
+ | yD_FELL '(' expr ',' expr ')' { $$ = $3; BBUNSUP($1, "Unsupported: $fell and clock arguments"); }
| yD_FEOF '(' expr ')' { $$ = new AstFEof($1,$3); }
| yD_FERROR '(' idClassSel ',' idClassSel ')' { $$ = new AstFError($1, $3, $5); }
| yD_FGETC '(' expr ')' { $$ = new AstFGetC($1,$3); }
@@ -3650,6 +3641,8 @@ system_f_call_or_t: // IEEE: part of system_tf_call (can be task or func)
| yD_REWIND '(' idClassSel ')' { $$ = new AstFSeek($1, $3, new AstConst($1, 0), new AstConst($1, 0)); }
| yD_RIGHT '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_RIGHT,$3,NULL); }
| yD_RIGHT '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_RIGHT,$3,$5); }
+ | yD_ROSE '(' expr ')' { $$ = new AstRose($1,$3); }
+ | yD_ROSE '(' expr ',' expr ')' { $$ = $3; BBUNSUP($1, "Unsupported: $rose and clock arguments"); }
| yD_RTOI '(' expr ')' { $$ = new AstRToIS($1,$3); }
| yD_SAMPLED '(' expr ')' { $$ = new AstSampled($1, $3); }
| yD_SFORMATF '(' exprDispList ')' { $$ = new AstSFormatF($1, AstSFormatF::NoFormat(), $3, 'd', false); }
@@ -3662,6 +3655,8 @@ system_f_call_or_t: // IEEE: part of system_tf_call (can be task or func)
| yD_SQRT '(' expr ')' { $$ = new AstSqrtD($1,$3); }
| yD_SSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstSScanF($1,*$5,$3,$6); }
| yD_STIME parenE { $$ = new AstSel($1, new AstTime($1, VTimescale(VTimescale::NONE)), 0, 32); }
+ | yD_STABLE '(' expr ')' { $$ = new AstStable($1,$3); }
+ | yD_STABLE '(' expr ',' expr ')' { $$ = $3; BBUNSUP($1, "Unsupported: $stable and clock arguments"); }
| yD_TAN '(' expr ')' { $$ = new AstTanD($1,$3); }
| yD_TANH '(' expr ')' { $$ = new AstTanhD($1,$3); }
| yD_TESTPLUSARGS '(' str ')' { $$ = new AstTestPlusArgs($1,*$3); }
@@ -4263,7 +4258,7 @@ exprScope: // scope and variable for use to inside an expression
yTHIS { $$ = new AstParseRef($1, VParseRefExp::PX_ROOT, "this"); }
| yD_ROOT { $$ = new AstParseRef($1, VParseRefExp::PX_ROOT, "$root"); }
| idArrayed { $$ = $1; }
- | packageClassScope idArrayed { $$ = AstDot::newIfPkg($2->fileline(), CAST_PACKAGE_CLASS($1), $2); }
+ | packageClassScope idArrayed { $$ = AstDot::newIfPkg($2->fileline(), $1, $2); }
| ~l~expr '.' idArrayed { $$ = new AstDot($2, false, $1, $3); }
// // expr below must be a "yTHIS"
| ~l~expr '.' ySUPER { $$ = $1; BBUNSUP($3, "Unsupported: super"); }
@@ -4742,7 +4737,7 @@ idClassSel: // Misc Ref to dotted, and/or arrayed, and/or bit-ranged va
{ $$ = new AstDot($2, false, new AstParseRef($1, VParseRefExp::PX_ROOT, "super"), $3); }
| yTHIS '.' ySUPER '.' idDotted { $$ = $5; BBUNSUP($1, "Unsupported: this.super"); }
// // Expanded: package_scope idDotted
- | packageClassScope idDotted { $$ = $2; BBUNSUP($2, "Unsupported: package scoped id"); }
+ | packageClassScope idDotted { $$ = new AstDot($2, true, $1, $2); }
;
idClassSelForeach:
@@ -4754,7 +4749,7 @@ idClassSelForeach:
{ $$ = new AstDot($2, false, new AstParseRef($1, VParseRefExp::PX_ROOT, "super"), $3); }
| yTHIS '.' ySUPER '.' idDottedForeach { $$ = $5; BBUNSUP($1, "Unsupported: this.super"); }
// // Expanded: package_scope idForeach
- | packageClassScope idDottedForeach { $$ = $2; BBUNSUP($2, "Unsupported: package/class scoped id"); }
+ | packageClassScope idDottedForeach { $$ = new AstDot($2, true, $1, $2); }
;
idDotted:
@@ -4785,7 +4780,8 @@ idDottedMoreForeach:
// id below includes:
// enum_identifier
idArrayed: // IEEE: id + select
- id { $$ = new AstParseRef($1, VParseRefExp::PX_TEXT, *$1, NULL, NULL); }
+ id
+ { $$ = new AstParseRef($1, VParseRefExp::PX_TEXT, *$1, NULL, NULL); }
// // IEEE: id + part_select_range/constant_part_select_range
| idArrayed '[' expr ']' { $$ = new AstSelBit($2, $1, $3); } // Or AstArraySel, don't know yet.
| idArrayed '[' constExpr ':' constExpr ']' { $$ = new AstSelExtract($2, $1, $3, $5); }
@@ -4795,7 +4791,8 @@ idArrayed: // IEEE: id + select
;
idArrayedForeach: // IEEE: id + select (under foreach expression)
- id { $$ = new AstParseRef($1, VParseRefExp::PX_TEXT, *$1, NULL, NULL); }
+ id
+ { $$ = new AstParseRef($1, VParseRefExp::PX_TEXT, *$1, NULL, NULL); }
// // IEEE: id + part_select_range/constant_part_select_range
| idArrayed '[' expr ']' { $$ = new AstSelBit($2, $1, $3); } // Or AstArraySel, don't know yet.
| idArrayed '[' constExpr ':' constExpr ']' { $$ = new AstSelExtract($2, $1, $3, $5); }
@@ -5888,18 +5885,17 @@ class_typeExtImpOne: // part of IEEE: class_type, where we either get a p
idAny
/*mid*/ { /* no nextId as not refing it above this*/ }
/*cont*/ parameter_value_assignmentE
- { $$ = new AstParseRef($1, VParseRefExp::PX_TEXT, *$1, NULL, NULL);
- $$ = $1;
- if ($3) BBUNSUP($3->fileline(), "Unsupported: Parameterized classes"); }
+ { $$ = new AstClassOrPackageRef($1, *$1, $1, $3);
+ $$ = $1; }
//
// // package_sopeIdFollows expanded
| yD_UNIT yP_COLONCOLON
- { $$ = new AstParseRef($1, VParseRefExp::PX_TEXT, "$unit", NULL, NULL);
+ { $$ = new AstClassOrPackageRef($1, "$unit", NULL, NULL);
$$ = NULL; // No purpose otherwise, every symtab can see root
SYMP->nextId(PARSEP->rootp()); }
//
| yLOCAL__COLONCOLON yP_COLONCOLON
- { $$ = new AstParseRef($1, VParseRefExp::PX_TEXT, "local", NULL, NULL);
+ { $$ = new AstClassOrPackageRef($1, "local::", NULL, NULL);
$$ = NULL; // UNSUP
SYMP->nextId(PARSEP->rootp());
BBUNSUP($1, "Unsupported: Randomize 'local::'"); }
@@ -5912,11 +5908,11 @@ class_typeExtImpOne: // part of IEEE: class_type, where we either get a p
//=== Below rules assume special scoping per above
-packageClassScopeNoId: // IEEE: [package_scope] not followed by yaID
+packageClassScopeNoId: // IEEE: [package_scope] not followed by yaID
packageClassScope { $$ = $1; $$ = $1; SYMP->nextId(NULL); }
;
-packageClassScopeE: // IEEE: [package_scope]
+packageClassScopeE: // IEEE: [package_scope]
// // IMPORTANT: The lexer will parse the following ID to be in the found package
// // if not needed must use packageClassScopeNoId
// // TODO: To support classes should return generic type, not packagep
@@ -5925,7 +5921,7 @@ packageClassScopeE: // IEEE: [package_scope]
| packageClassScope { $$ = $1; $$ = $1; }
;
-packageClassScope: // IEEE: class_scope + type
+packageClassScope: // IEEE: class_scope
// // IEEE: "class_type yP_COLONCOLON"
// // IMPORTANT: The lexer will parse the following ID to be in the found package
// // if not needed must use packageClassScopeNoId
@@ -5934,10 +5930,11 @@ packageClassScope: // IEEE: class_scope + type
packageClassScopeList { $$ = $1; $$ = $1; }
| localNextId yP_COLONCOLON { $$ = $1; $$ = $1; }
| dollarUnitNextId yP_COLONCOLON { $$ = $1; $$ = $1; }
- | dollarUnitNextId yP_COLONCOLON packageClassScopeList { $$ = $3; $$ = $3; }
+ | dollarUnitNextId yP_COLONCOLON packageClassScopeList
+ { $$ = new AstDot($2, true, $1, $3); $$ = $3; }
;
-packageClassScopeList: // IEEE: class_type: "id [ parameter_value_assignment ]" but allow yaID__aTYPE
+packageClassScopeList: // IEEE: class_type: "id [ parameter_value_assignment ]" but allow yaID__aTYPE
// // Or IEEE: [package_scope]
// // IMPORTANT: The lexer will parse the following ID to be in the found package
// // if not needed must use packageClassScopeNoId
@@ -5945,10 +5942,10 @@ packageClassScopeList: // IEEE: class_type: "id [ parameter_value_assi
// // If you follow the rules down, class_type is really a list via ps_class_identifier
packageClassScopeItem { $$ = $1; $$ = $1; }
| packageClassScopeList packageClassScopeItem
- { $$ = $2; $$ = $2; BBUNSUP($2, "Unsupported: Nested :: references"); }
+ { $$ = new AstDot($2, true, $1, $2); $$ = $2; }
;
-packageClassScopeItem: // IEEE: package_scope or [package_scope]::[class_scope]
+packageClassScopeItem: // IEEE: package_scope or [package_scope]::[class_scope]
// // IMPORTANT: The lexer will parse the following ID to be in the found package
// // if not needed must use packageClassScopeNoId
// // IEEE: class_type: "id [ parameter_value_assignment ]" but allow yaID__aTYPE
@@ -5956,29 +5953,30 @@ packageClassScopeItem: // IEEE: package_scope or [package_scope]::[cla
idCC
/*mid*/ { SYMP->nextId($1); }
/*cont*/ yP_COLONCOLON
- { $$ = VN_CAST($1, Package); $$ = $1; } // UNSUP classes
+ { $$ = new AstClassOrPackageRef($1, *$1, $1, NULL); $$ = $1; }
//
| idCC parameter_value_assignment
/*mid*/ { SYMP->nextId($1); } // Change next *after* we handle parameters, not before
/*cont*/ yP_COLONCOLON
- { $$ = VN_CAST($1, Package); $$ = $1; // UNSUP classes
- if ($2) BBUNSUP($2->fileline(), "Unsupported: Parameterized classes"); }
+ { $$ = new AstClassOrPackageRef($1, *$1, $1, $2); $$ = $1; }
;
-dollarUnitNextId: // $unit
+dollarUnitNextId: // $unit
// // IMPORTANT: The lexer will parse the following ID to be in the found package
// // if not needed must use packageClassScopeNoId
// // Must call nextId without any additional tokens following
yD_UNIT
- { $$ = GRAMMARP->unitPackage($1); SYMP->nextId(PARSEP->rootp()); }
+ { $$ = new AstClassOrPackageRef($1, "$unit", GRAMMARP->unitPackage($1), NULL);
+ SYMP->nextId(PARSEP->rootp()); }
;
-localNextId: // local
+localNextId: // local
// // IMPORTANT: The lexer will parse the following ID to be in the found package
// // if not needed must use packageClassScopeNoId
// // Must call nextId without any additional tokens following
yLOCAL__COLONCOLON
- { $$ = GRAMMARP->unitPackage($1); SYMP->nextId(PARSEP->rootp());
+ { $$ = new AstClassOrPackageRef($1, "local::", GRAMMARP->unitPackage($1), NULL);
+ SYMP->nextId(PARSEP->rootp());
BBUNSUP($1, "Unsupported: Randomize 'local::'"); }
;
diff --git a/test_regress/t/t_class2.out b/test_regress/t/t_class2.out
index 3444da0d9..25f82f892 100644
--- a/test_regress/t/t_class2.out
+++ b/test_regress/t/t_class2.out
@@ -1,4 +1,7 @@
-%Error: t/t_class2.v:35:16: Can't find definition of variable: 'ENUM_VAL'
+%Error-UNSUPPORTED: t/t_class2.v:35:16: Unsupported: Class '::' references: 'Cls'
35 | if (Cls::ENUM_VAL != 22) $stop;
| ^~~~~~~~
-%Error: Exiting due to
+%Error: Internal Error: t/t_class2.v:35:11: ../V3LinkDot.cpp:#: Bad package link
+ 35 | if (Cls::ENUM_VAL != 22) $stop;
+ | ^~~
+ ... See the manual and https://verilator.org for more assistance.
diff --git a/test_regress/t/t_class_extends.out b/test_regress/t/t_class_extends.out
index c839d805a..8cd0d95fd 100644
--- a/test_regress/t/t_class_extends.out
+++ b/test_regress/t/t_class_extends.out
@@ -1,28 +1,16 @@
%Error-UNSUPPORTED: t/t_class_extends.v:13:21: Unsupported: class extends
13 | class Base1 extends Base0;
| ^~~~~
-%Error: t/t_class_extends.v:13:21: Found definition of 'Base0' as a CLASS but expected a variable
- 13 | class Base1 extends Base0;
- | ^~~~~
%Error-UNSUPPORTED: t/t_class_extends.v:18:21: Unsupported: class extends
18 | class Base2 extends Base1;
| ^~~~~
-%Error: t/t_class_extends.v:18:21: Found definition of 'Base1' as a CLASS but expected a variable
- 18 | class Base2 extends Base1;
- | ^~~~~
%Error-UNSUPPORTED: t/t_class_extends.v:22:19: Unsupported: class extends
22 | class Cls extends Base2;
| ^~~~~
-%Error: t/t_class_extends.v:22:19: Found definition of 'Base2' as a CLASS but expected a variable
- 22 | class Cls extends Base2;
- | ^~~~~
%Error: t/t_class_extends.v:25:4: Can't find typedef: 'T'
25 | T imemberc;
| ^
%Error-UNSUPPORTED: t/t_class_extends.v:33:43: Unsupported: class extends
33 | class uvm__registry #(type T=int) extends uvm_object_wrapper;
| ^~~~~~~~~~~~~~~~~~
-%Error: t/t_class_extends.v:33:43: Found definition of 'uvm_object_wrapper' as a CLASS but expected a variable
- 33 | class uvm__registry #(type T=int) extends uvm_object_wrapper;
- | ^~~~~~~~~~~~~~~~~~
%Error: Exiting due to
diff --git a/test_regress/t/t_class_extends_this.out b/test_regress/t/t_class_extends_this.out
index 020f115a4..6f0456393 100644
--- a/test_regress/t/t_class_extends_this.out
+++ b/test_regress/t/t_class_extends_this.out
@@ -7,9 +7,6 @@
%Error-UNSUPPORTED: t/t_class_extends_this.v:17:19: Unsupported: class extends
17 | class Cls extends Base;
| ^~~~
-%Error: t/t_class_extends_this.v:17:19: Found definition of 'Base' as a CLASS but expected a variable
- 17 | class Cls extends Base;
- | ^~~~
%Error-UNSUPPORTED: t/t_class_extends_this.v:21:11: Unsupported: this
21 | if (this.value != 2) $stop;
| ^~~~
diff --git a/test_regress/t/t_class_member_bad.out b/test_regress/t/t_class_member_bad.out
index eb6537580..1251ff9af 100644
--- a/test_regress/t/t_class_member_bad.out
+++ b/test_regress/t/t_class_member_bad.out
@@ -1,7 +1,4 @@
%Error-UNSUPPORTED: t/t_class_member_bad.v:11:20: Unsupported: class extends
11 | class Cls2 extends Base1;
| ^~~~~
-%Error: t/t_class_member_bad.v:11:20: Found definition of 'Base1' as a CLASS but expected a variable
- 11 | class Cls2 extends Base1;
- | ^~~~~
%Error: Exiting due to
diff --git a/test_regress/t/t_class_method_bad.out b/test_regress/t/t_class_method_bad.out
index 88dcdf4f4..bb2dbc0f6 100644
--- a/test_regress/t/t_class_method_bad.out
+++ b/test_regress/t/t_class_method_bad.out
@@ -1,7 +1,4 @@
%Error-UNSUPPORTED: t/t_class_method_bad.v:11:20: Unsupported: class extends
11 | class Cls2 extends Base1;
| ^~~~~
-%Error: t/t_class_method_bad.v:11:20: Found definition of 'Base1' as a CLASS but expected a variable
- 11 | class Cls2 extends Base1;
- | ^~~~~
%Error: Exiting due to
diff --git a/test_regress/t/t_class_param.out b/test_regress/t/t_class_param.out
index f4aba8765..53cdad86a 100644
--- a/test_regress/t/t_class_param.out
+++ b/test_regress/t/t_class_param.out
@@ -1,4 +1,7 @@
-%Error-UNSUPPORTED: t/t_class_param.v:20:11: Unsupported: Parameter classes
+%Error-UNSUPPORTED: t/t_class_param.v:20:4: Unsupported: parameterized packages
20 | Cls #(.P(4)) c4;
- | ^
+ | ^~~
+%Error-UNSUPPORTED: t/t_class_param.v:9:23: Unsupported: class parameter
+ 9 | class Cls #(parameter P = 12);
+ | ^
%Error: Exiting due to
diff --git a/test_regress/t/t_class_typedef.out b/test_regress/t/t_class_typedef.out
index bc468849c..4979a037a 100644
--- a/test_regress/t/t_class_typedef.out
+++ b/test_regress/t/t_class_typedef.out
@@ -1,4 +1,13 @@
-%Error-UNSUPPORTED: t/t_class_typedef.v:14:24: Unsupported: Parameterized classes
+%Error-UNSUPPORTED: t/t_class_typedef.v:12:4: Unsupported: Class '::' reference
+ 12 | uvm_resource_types::rsrc_q_t rtab [string];
+ | ^~~~~~~~~~~~~~~~~~
+%Error: t/t_class_typedef.v:12:24: Can't find typedef: 'rsrc_q_t'
+ 12 | uvm_resource_types::rsrc_q_t rtab [string];
+ | ^~~~~~~~
+%Error-UNSUPPORTED: t/t_class_typedef.v:14:4: Unsupported: Class '::' reference
14 | uvm_resource_types#(1,2,3)::rsrc_q_t rtab_paramed [string];
- | ^
+ | ^~~~~~~~~~~~~~~~~~
+%Error: t/t_class_typedef.v:14:32: Can't find typedef: 'rsrc_q_t'
+ 14 | uvm_resource_types#(1,2,3)::rsrc_q_t rtab_paramed [string];
+ | ^~~~~~~~
%Error: Exiting due to
diff --git a/test_regress/t/t_class_vparam_unsup.out b/test_regress/t/t_class_vparam_unsup.out
index 66f55b199..b0b72a8c4 100644
--- a/test_regress/t/t_class_vparam_unsup.out
+++ b/test_regress/t/t_class_vparam_unsup.out
@@ -1,4 +1,4 @@
-%Error-UNSUPPORTED: t/t_class_vparam_unsup.v:13:58: Unsupported: Parameter classes
+%Error-UNSUPPORTED: t/t_class_vparam_unsup.v:13:40: Unsupported: parameterized packages
13 | pure virtual function void funcname(paramed_class_t #(CTYPE_t) v);
- | ^~~~~~~
+ | ^~~~~~~~~~~~~~~
%Error: Exiting due to
diff --git a/test_regress/t/t_const_hi.pl b/test_regress/t/t_const_hi.pl
new file mode 100755
index 000000000..a17622844
--- /dev/null
+++ b/test_regress/t/t_const_hi.pl
@@ -0,0 +1,21 @@
+#!/usr/bin/env 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.
+# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
+
+scenarios(simulator => 1);
+
+compile(
+ );
+
+execute(
+ check_finished => 1,
+ );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_const_hi.v b/test_regress/t/t_const_hi.v
new file mode 100644
index 000000000..edf2afef4
--- /dev/null
+++ b/test_regress/t/t_const_hi.v
@@ -0,0 +1,53 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2020 Wilson Snyder.
+// SPDX-License-Identifier: CC0-1.0
+
+module t(/*AUTOARG*/
+ // Inputs
+ clk
+ );
+ input clk;
+
+ integer cyc = 0;
+ reg [1:0] reg_i;
+ reg [1049:0] pad0;
+ reg [1049:0] reg_o;
+ reg [1049:0] spad1;
+
+ /*AUTOWIRE*/
+
+ always_comb begin
+ if (reg_i[1] == 1'b1)
+ reg_o = {986'd0, 64'hffff0000ffff0000};
+ else if (reg_i[0] == 1'b1)
+ reg_o = {64'hffff0000ffff0000, 986'd0};
+ else
+ reg_o = 1050'd0;
+ end
+
+ // Test loop
+ always @ (posedge clk) begin
+ cyc <= cyc + 1;
+ if (cyc == 0) begin
+ reg_i <= 2'b00;
+ pad0 <= '1;
+ spad1 <= '1;
+ end
+ else if (cyc == 1) begin
+ reg_i <= 2'b01;
+ end
+ else if (cyc == 2) begin
+ if (reg_o != {64'hffff0000ffff0000, 986'd0}) $stop;
+ reg_i <= 2'b10;
+ end
+ else if (cyc == 99) begin
+ if (reg_o != {986'd0, 64'hffff0000ffff0000}) $stop;
+ if (pad0 != '1) $stop;
+ if (spad1 != '1) $stop;
+ $write("*-* All Finished *-*\n");
+ $finish;
+ end
+ end
+endmodule
diff --git a/test_regress/t/t_fell.pl b/test_regress/t/t_fell.pl
new file mode 100644
index 000000000..c1a6773e9
--- /dev/null
+++ b/test_regress/t/t_fell.pl
@@ -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.
+
+scenarios(simulator => 1);
+
+compile(
+ verilator_flags2 => ['--assert'],
+ );
+
+execute(
+ check_finished => 1,
+ );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_fell.v b/test_regress/t/t_fell.v
new file mode 100644
index 000000000..eff06f114
--- /dev/null
+++ b/test_regress/t/t_fell.v
@@ -0,0 +1,81 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed into the Public Domain, for any use,
+// without warranty, 2020 by Peter Monsson.
+
+module t (/*AUTOARG*/
+ // Inputs
+ clk
+ );
+
+ input clk;
+ integer cyc; initial cyc=2;
+ wire [31:0] in = cyc;
+
+ Test test (/*AUTOINST*/
+ // Inputs
+ .clk (clk),
+ .in (in[31:0]));
+
+ Test2 test2 (/*AUTOINST*/
+ // Inputs
+ .clk (clk),
+ .in (in[31:0]));
+
+ always @ (posedge clk) begin
+ if (cyc!=0) begin
+ cyc <= cyc + 1;
+ if (cyc==10) begin
+ $write("*-* All Finished *-*\n");
+ $finish;
+ end
+ end
+ end
+
+endmodule
+
+module Test (/*AUTOARG*/
+ // Inputs
+ clk, in
+ );
+
+ input clk;
+ input [31:0] in;
+
+ reg [31:0] dly0 = 1;
+
+ // If called in an assertion, sequence, or property, the appropriate clocking event.
+ // Otherwise, if called in a disable condition or a clock expression in an assertion, sequence, or prop, explicit.
+ // Otherwise, if called in an action block of an assertion, the leading clock of the assertion is used.
+ // Otherwise, if called in a procedure, the inferred clock
+ // Otherwise, default clocking
+
+ always @(posedge clk) begin
+ dly0 <= in;
+ // In clock expression
+ $write("in=%0d, dly0=%0d, fell=%0d, past=%0d\n", in, dly0, $fell(dly0), $past(dly0));
+ if ($fell(dly0[4])) $stop;
+ end
+
+ assert property (@(posedge clk) $fell(dly0) || dly0%2==1);
+endmodule
+
+
+module Test2 (/*AUTOARG*/
+ // Inputs
+ clk, in
+ );
+
+ input clk;
+ input [31:0] in;
+
+ reg [31:0] dly0 = 1;
+
+ always @(posedge clk) begin
+ dly0 <= in;
+ if ($fell(dly0[31:4])) $stop;
+ end
+
+ default clocking @(posedge clk); endclocking
+ assert property ($fell(dly0[0]) || dly0%2==1);
+endmodule
diff --git a/test_regress/t/t_interface_arraymux.v b/test_regress/t/t_interface_arraymux.v
index 8709cbca4..261f154d9 100644
--- a/test_regress/t/t_interface_arraymux.v
+++ b/test_regress/t/t_interface_arraymux.v
@@ -39,6 +39,19 @@ module ThingMuxOH
the_intf.t things_in [NTHINGS-1:0],
the_intf.i thing_out
);
+ assign thing_out.valid = things_in[0].valid;
+endmodule
+
+module ThingMuxShort
+ #(
+ parameter NTHINGS = 1,
+ parameter M = 5 )
+ (
+ input logic [NTHINGS-1:0] select_oh,
+ the_intf.t things_in [NTHINGS],
+ the_intf.i thing_out
+ );
+ assign thing_out.valid = things_in[0].valid;
endmodule
module Thinker
@@ -55,8 +68,10 @@ module Thinker
the_intf #(.M(M)) curr_things [N-1:0] ();
the_intf #(.M(M)) prev_things [N-1:0] ();
+ the_intf #(.M(M)) s_things [N] ();
the_intf #(.M(M)) curr_thing ();
the_intf #(.M(M)) prev_thing ();
+ the_intf #(.M(M)) s_thing ();
logic [N-1:0] select_oh;
@@ -78,6 +93,15 @@ module Thinker
.things_in( prev_things ),
.thing_out( prev_thing ));
+ // 3rd mux, using short array nomenclature:
+ ThingMuxShort #(
+ .NTHINGS ( N ),
+ .M ( M ))
+ s_thing_mux(
+ .select_oh( select_oh ),
+ .things_in( s_things ),
+ .thing_out( s_thing ));
+
endmodule
module t
diff --git a/test_regress/t/t_math_real.v b/test_regress/t/t_math_real.v
index 167bd9fbf..dc94b5aa3 100644
--- a/test_regress/t/t_math_real.v
+++ b/test_regress/t/t_math_real.v
@@ -6,6 +6,7 @@
// Version 2.0.
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
+`define checkr(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: %s:%0d: got=%f exp=%f\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
`define is_near_real(a,b) (( ((a)<(b)) ? (b)-(a) : (a)-(b)) < (((a)/(b))*0.0001))
module t (/*AUTOARG*/
@@ -16,6 +17,16 @@ module t (/*AUTOARG*/
integer i;
reg [63:0] b;
+ reg [47:0] i48;
+ reg signed [47:0] is48;
+ reg [31:0] ci32;
+ reg signed [31:0] cis32;
+ reg [47:0] ci48;
+ reg signed [47:0] cis48;
+ reg [63:0] ci64;
+ reg signed [63:0] cis64;
+ reg [95:0] ci96;
+ reg signed [95:0] cis96;
real r, r2;
integer cyc=0;
@@ -88,6 +99,41 @@ module t (/*AUTOARG*/
// bug
b = 64'h7fe8000000000000;
$display("%6.3f", $bitstoreal(b));
+ // bug
+ i48 = 48'hff00_00000000;
+ r = real'(i48);
+ if (r != 280375465082880.0) $stop;
+ r = $itor(i48);
+ if (r != 280375465082880.0) $stop;
+
+ is48 = 48'shff00_00000000;
+ r = real'(is48);
+ if (r != -1099511627776.0) $stop;
+ r = $itor(is48);
+ if (r != -1099511627776.0) $stop;
+
+ r = 0;
+ r = i48;
+ if (r != 280375465082880.0) $stop;
+ r = 0;
+
+ r = $itor(-10);
+ if (r != -10.0) $stop;
+
+ r = real'(4'sb1111);
+ if (r != -1) $stop;
+ r = $itor(4'sb1111);
+ if (r != -1) $stop;
+
+ r = real'(4'b1111);
+ if (r != 15) $stop;
+ r = $itor(4'b1111);
+ if (r != 15) $stop;
+
+ r = real'(96'hf0000000_00000000_00000000);
+ if (r != 74276402357122816493947453440.0) $stop;
+ r = real'(96'shf0000000_00000000_00000000);
+ if (r != -4951760157141521099596496896.0) $stop;
end
// Test loop
@@ -98,8 +144,18 @@ module t (/*AUTOARG*/
cyc <= cyc + 1;
if (cyc==0) begin
// Setup
+ ci48 <= '0;
+ cis48 <= '0;
+ ci96 <= '0;
+ cis96 <= '0;
end
- else if (cyc<90) begin
+ else if (cyc == 1) begin
+ ci48 <= 48'hff00_00000000;
+ cis48 <= 48'shff00_00000000;
+ ci96 <= 96'hf0000000_00000000_00000000;
+ cis96 <= 96'shf0000000_00000000_00000000;
+ end
+ else if (cyc<80) begin
if ($time != {32'h0, $rtoi($realtime)}) $stop;
if ($itor(cyc) != cyc) $stop;
//Unsup: if ((real `($time)) != $realtime) $stop;
@@ -141,6 +197,76 @@ module t (/*AUTOARG*/
!= (((cyc-50)!=0) ? 10 : 20)) $stop;
//
if ((!(r-50.0)) != (!((cyc-50) != 0))) $stop;
+ //
+ r = real'(ci48);
+ `checkr(r, 280375465082880.0);
+ r = real'(cis48);
+ `checkr(r, -1099511627776.0);
+ //
+ r = real'(ci96);
+ `checkr(r, 74276402357122816493947453440.0);
+ r = real'(cis96);
+ `checkr(r, -4951760157141521099596496896.0);
+ end
+ else if (cyc==90) begin
+ ci32 <= '0;
+ cis32 <= '0;
+ ci48 <= '0;
+ cis48 <= '0;
+ ci64 <= '0;
+ cis64 <= '0;
+ ci96 <= '0;
+ cis96 <= '0;
+ end
+ else if (cyc==91) begin
+ `checkr(real'(ci32), 0.0);
+ `checkr(real'(cis32), 0.0);
+ `checkr(real'(ci48), 0.0);
+ `checkr(real'(cis48), 0.0);
+ `checkr(real'(ci64), 0.0);
+ `checkr(real'(cis64), 0.0);
+ `checkr(real'(ci96), 0.0);
+ `checkr(real'(cis96), 0.0);
+ end
+ else if (cyc==92) begin
+ ci32 <= 32'b1;
+ cis32 <= 32'b1;
+ ci48 <= 48'b1;
+ cis48 <= 48'b1;
+ ci64 <= 64'b1;
+ cis64 <= 64'b1;
+ ci96 <= 96'b1;
+ cis96 <= 96'b1;
+ end
+ else if (cyc==93) begin
+ `checkr(real'(ci32), 1.0);
+ `checkr(real'(cis32), 1.0);
+ `checkr(real'(ci48), 1.0);
+ `checkr(real'(cis48), 1.0);
+ `checkr(real'(ci64), 1.0);
+ `checkr(real'(cis64), 1.0);
+ `checkr(real'(ci96), 1.0);
+ `checkr(real'(cis96), 1.0);
+ end
+ else if (cyc==94) begin
+ ci32 <= ~ '0;
+ cis32 <= ~ '0;
+ ci48 <= ~ '0;
+ cis48 <= ~ '0;
+ ci64 <= ~ '0;
+ cis64 <= ~ '0;
+ ci96 <= ~ '0;
+ cis96 <= ~ '0;
+ end
+ else if (cyc==95) begin
+ `checkr(real'(ci32), 4294967295.0);
+ `checkr(real'(cis32), -1.0);
+ `checkr(real'(ci48), 281474976710655.0);
+ `checkr(real'(cis48), -1.0);
+ `checkr(real'(ci64), 18446744073709551616.0);
+ `checkr(real'(cis64), -1.0);
+ `checkr(real'(ci96), 79228162514264337593543950336.0);
+ `checkr(real'(cis96), -1.0);
end
else if (cyc==99) begin
$write("*-* All Finished *-*\n");
diff --git a/test_regress/t/t_math_real_random.pl b/test_regress/t/t_math_real_random.pl
new file mode 100755
index 000000000..9a15dd2cc
--- /dev/null
+++ b/test_regress/t/t_math_real_random.pl
@@ -0,0 +1,21 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2019 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.
+# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
+
+scenarios(simulator => 1);
+
+compile(
+ );
+
+execute(
+ check_finished => 1,
+ );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_math_real_random.v b/test_regress/t/t_math_real_random.v
new file mode 100644
index 000000000..02c86774f
--- /dev/null
+++ b/test_regress/t/t_math_real_random.v
@@ -0,0 +1,100 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2020 Wilson Snyder.
+// SPDX-License-Identifier: CC0-1.0
+
+`define checkr(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: %s:%0d: got=%f exp=%f\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
+
+module t(/*AUTOARG*/
+ // Inputs
+ clk
+ );
+ input clk;
+
+ integer cyc=0;
+ reg [63:0] crc;
+ reg [63:0] sum;
+
+ reg [127:0] in;
+
+ check #(48) check48 (.*);
+ check #(31) check31 (.*);
+ check #(32) check32 (.*);
+ check #(63) check63 (.*);
+ check #(64) check64 (.*);
+ check #(96) check96 (.*);
+ check #(128) check128 (.*);
+
+ always_comb begin
+ if (crc[2:0] == 0) in = '0;
+ else if (crc[2:0] == 1) in = ~'0;
+ else if (crc[2:0] == 2) in = 128'b1;
+ else if (crc[2:0] == 3) in = ~ 128'b1;
+ else begin
+ in = {crc, crc};
+ if (crc[3]) in[31:0] = '0;
+ if (crc[4]) in[63:32] = '0;
+ if (crc[5]) in[95:64] = '0;
+ if (crc[6]) in[127:96] = '0;
+ if (crc[7]) in[31:0] = ~'0;
+ if (crc[8]) in[63:32] = ~'0;
+ if (crc[9]) in[95:64] = ~'0;
+ if (crc[10]) in[127:96] = ~'0;
+ end
+ end
+
+ // Test loop
+ always @ (posedge clk) begin
+`ifdef TEST_VERBOSE
+ $write("[%0t] cyc==%0d in=%x\n",$time, cyc, in);
+`endif
+ cyc <= cyc + 1;
+ crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
+ if (cyc == 0) begin
+ // Setup
+ crc <= 64'h5aef0c8d_d70a4497;
+ sum <= '0;
+ end
+ else if (cyc == 99) begin
+ `checkr(check48.sum, 14574057015683440.000000);
+ `checkr(check31.sum, 114141374814.000000);
+ `checkr(check32.sum, 236547942750.000000);
+ `checkr(check63.sum, 513694866079917670400.000000);
+ `checkr(check64.sum, 1002533584033221181440.000000);
+ `checkr(check96.sum, 4377373669974269260279175970816.000000);
+ `checkr(check128.sum, 18358899571808044815012294240949812330496.000000);
+ $write("*-* All Finished *-*\n");
+ $finish;
+ end
+ end
+
+endmodule
+
+module check(/*AUTOARG*/
+ // Inputs
+ in, clk, cyc
+ );
+ parameter WIDTH = 128;
+ input [127:0] in;
+
+ wire [WIDTH-1:0] ci = in[WIDTH-1:0];
+ wire signed [WIDTH-1:0] cis = in[WIDTH-1:0];
+
+ real r;
+ real rs;
+ always_comb r = ci;
+ always_comb rs = cis;
+
+ input clk;
+ input integer cyc;
+ real sum;
+
+ always_ff @ (negedge clk) begin
+`ifdef TEST_VERBOSE
+ $write("[%0t] w%0d in=%h r=%f rs=%f sum=%f\n", $time, WIDTH, ci, r, rs, sum);
+`endif
+ if (cyc < 10) sum <= 0;
+ else sum <= sum + r + rs;
+ end
+endmodule
diff --git a/test_regress/t/t_math_shift_extend.pl b/test_regress/t/t_math_shift_extend.pl
new file mode 100755
index 000000000..763e64f5b
--- /dev/null
+++ b/test_regress/t/t_math_shift_extend.pl
@@ -0,0 +1,19 @@
+#!/usr/bin/env 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.
+# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
+
+scenarios(simulator => 1);
+
+compile(
+ );
+
+execute();
+
+ok(1);
+1;
diff --git a/test_regress/t/t_math_shift_extend.v b/test_regress/t/t_math_shift_extend.v
new file mode 100644
index 000000000..b0f4707de
--- /dev/null
+++ b/test_regress/t/t_math_shift_extend.v
@@ -0,0 +1,37 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2020 by Wilson Snyder.
+// SPDX-License-Identifier: CC0-1.0
+
+module t (/*AUTOARG*/);
+
+ logic in1 = 1;
+ logic [1:0] in2 = 2'b11;
+ logic [31:0] out;
+
+ typedef logic [7:0] data_t;
+
+ // verilator lint_off WIDTH
+ initial begin
+ in1 = 1;
+ in2 = 0;
+ out = data_t'(in1 << in2);
+ if (out != 8'b1) $stop;
+
+ in2 = 1;
+ out = data_t'(in1 << in2);
+ if (out != 8'b10) $stop;
+
+ in2 = 2;
+ out = data_t'(in1 << in2);
+ if (out != 8'b100) $stop;
+
+ in2 = 3;
+ out = data_t'(in1 << in2);
+ if (out != 8'b1000) $stop;
+
+ $write("*-* All Finished *-*\n");
+ $finish();
+ end
+endmodule
diff --git a/test_regress/t/t_math_wide_bad.out b/test_regress/t/t_math_wide_bad.out
new file mode 100644
index 000000000..1c4516c1d
--- /dev/null
+++ b/test_regress/t/t_math_wide_bad.out
@@ -0,0 +1,10 @@
+%Error-UNSUPPORTED: t/t_math_wide_bad.v:22:18: Unsupported: operator POWSS operator of 576 bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h
+ 22 | assign z2 = a ** 3;
+ | ^~
+%Error-UNSUPPORTED: t/t_math_wide_bad.v:23:15: Unsupported: operator ISTORD operator of 64 bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h
+ 23 | assign r = real'(a);
+ | ^~~~
+%Error-UNSUPPORTED: t/t_math_wide_bad.v:21:17: Unsupported: operator MULS operator of 576 bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h
+ 21 | assign z = a * b;
+ | ^
+%Error: Exiting due to
diff --git a/test_regress/t/t_math_wide_bad.pl b/test_regress/t/t_math_wide_bad.pl
new file mode 100755
index 000000000..9c9fb65a0
--- /dev/null
+++ b/test_regress/t/t_math_wide_bad.pl
@@ -0,0 +1,19 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2010 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.
+# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
+
+scenarios(linter => 1);
+
+lint(
+ fails => 1,
+ expect_filename => $Self->{golden_filename},
+ );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_math_wide_bad.v b/test_regress/t/t_math_wide_bad.v
new file mode 100644
index 000000000..8864a0bfc
--- /dev/null
+++ b/test_regress/t/t_math_wide_bad.v
@@ -0,0 +1,25 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2020 by Wilson Snyder.
+// SPDX-License-Identifier: CC0-1.0
+
+module t (/*AUTOARG*/
+ // Outputs
+ z, z2, r,
+ // Inputs
+ a, b
+ );
+
+ input signed [17*32 : 0] a;
+ input signed [17*32 : 0] b;
+
+ output signed [17*32 : 0] z;
+ output signed [17*32 : 0] z2;
+ output real r;
+
+ assign z = a * b;
+ assign z2 = a ** 3;
+ assign r = real'(a);
+
+endmodule
diff --git a/test_regress/t/t_param_func2.pl b/test_regress/t/t_param_func2.pl
new file mode 100755
index 000000000..b46d46042
--- /dev/null
+++ b/test_regress/t/t_param_func2.pl
@@ -0,0 +1,21 @@
+#!/usr/bin/env 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.
+# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
+
+scenarios(simulator => 1);
+
+compile(
+ );
+
+execute(
+ check_finished => 1,
+ );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_param_func2.v b/test_regress/t/t_param_func2.v
new file mode 100644
index 000000000..432d2914d
--- /dev/null
+++ b/test_regress/t/t_param_func2.v
@@ -0,0 +1,52 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed into the Public Domain, for any use,
+// without warranty, 2020 by Wilson Snyder.
+// SPDX-License-Identifier: CC0-1.0
+
+module t;
+ sub #(.WIDTH(4)) sub4();
+ sub #(.WIDTH(8)) sub8();
+
+ logic [3:0] out4;
+ logic [7:0] out8;
+
+ initial begin
+ out4 = sub4.orer(4'b1000);
+ out8 = sub8.orer(8'b10000000);
+ if (out4 != 4'b1011) $stop;
+ if (out8 != 8'b10111111) $stop;
+ out4 = sub4.orer2(4'b1000);
+ out8 = sub8.orer2(8'b10000000);
+ if (out4 != 4'b1001) $stop;
+ if (out8 != 8'b10011111) $stop;
+ $write("*-* All Finished *-*\n");
+ $finish;
+ end
+endmodule
+
+
+module sub;
+ parameter WIDTH = 1;
+
+ function [WIDTH-1:0] orer;
+ input [WIDTH-1:0] in;
+ // IEEE provices no way to override this parameter, basically it's a localparam
+ parameter MASK_W = WIDTH - 2;
+ localparam [MASK_W-1:0] MASK = '1;
+ // verilator lint_off WIDTH
+ return in | MASK;
+ // verilator lint_on WIDTH
+ endfunction
+
+ function [WIDTH-1:0] orer2;
+ input [WIDTH-1:0] in;
+ // Same param names as other function to check we disambiguate
+ // IEEE provices no way to override this parameter, basically it's a localparam
+ parameter MASK_W = WIDTH - 3;
+ localparam [MASK_W-1:0] MASK = '1;
+ // verilator lint_off WIDTH
+ return in | MASK;
+ // verilator lint_on WIDTH
+ endfunction
+endmodule
diff --git a/test_regress/t/t_param_in_func_bad.out b/test_regress/t/t_param_in_func_bad.out
index f152cd026..683490111 100644
--- a/test_regress/t/t_param_in_func_bad.out
+++ b/test_regress/t/t_param_in_func_bad.out
@@ -1,7 +1,5 @@
-%Error-UNSUPPORTED: t/t_param_in_func_bad.v:24:26: Unsupported: Parameters in functions
+%Error-UNSUPPORTED: t/t_param_in_func_bad.v:24:26: Unsupported: Parameters in functions with complex assign
+ : ... In instance t
24 | localparam logic[7:0] digits[10]
| ^~~~~~
-%Error: t/t_param_in_func_bad.v:28:11: Can't find definition of variable: 'digits'
- 28 | return digits[d];
- | ^~~~~~
%Error: Exiting due to
diff --git a/test_regress/t/t_param_width.pl b/test_regress/t/t_param_width.pl
new file mode 100755
index 000000000..b46d46042
--- /dev/null
+++ b/test_regress/t/t_param_width.pl
@@ -0,0 +1,21 @@
+#!/usr/bin/env 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.
+# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
+
+scenarios(simulator => 1);
+
+compile(
+ );
+
+execute(
+ check_finished => 1,
+ );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_param_width.v b/test_regress/t/t_param_width.v
new file mode 100644
index 000000000..bc41be394
--- /dev/null
+++ b/test_regress/t/t_param_width.v
@@ -0,0 +1,38 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2016 by Wilson Snyder.
+// SPDX-License-Identifier: CC0-1.0
+
+// issue 1991
+
+module t
+ (/*AUTOARG*/
+ // Inputs
+ clk
+ );
+ input clk;
+ socket #(3'b000) s0();
+ socket #(3'b010) s1();
+ socket #(2'b10) s2();
+ socket #(2'b11) s3();
+
+ always_ff @ (posedge clk) begin
+ if (s0.ADDR != 0) $stop;
+ if (s1.ADDR != 2) $stop;
+ if (s2.ADDR != 2) $stop;
+ if (s3.ADDR != 3) $stop;
+ if ($bits(s0.ADDR) != 3) $stop;
+ if ($bits(s1.ADDR) != 3) $stop;
+ if ($bits(s2.ADDR) != 2) $stop;
+ if ($bits(s3.ADDR) != 2) $stop;
+ $write("*-* All Finished *-*\n");
+ $finish;
+ end
+
+endmodule
+
+module socket #(ADDR)();
+ initial
+ $display("bits %0d, addr %b", $bits(ADDR), ADDR);
+endmodule
diff --git a/test_regress/t/t_process.out b/test_regress/t/t_process.out
index c024cca10..7f135af7b 100644
--- a/test_regress/t/t_process.out
+++ b/test_regress/t/t_process.out
@@ -1,22 +1,9 @@
%Error: t/t_process.v:22:4: Can't find typedef: 'process'
22 | process p;
| ^~~~~~~
-%Error: t/t_process.v:26:20: Can't find definition of task/function: 'self'
+%Error-UNSUPPORTED: t/t_process.v:26:20: Unsupported: 'process'
26 | p = process::self();
| ^~~~
-%Error: t/t_process.v:27:34: Can't find definition of variable: 'RUNNING'
- 27 | if (p.status() != process::RUNNING) $stop;
- | ^~~~~~~
-%Error: t/t_process.v:28:34: Can't find definition of variable: 'WAITING'
- 28 | if (p.status() == process::WAITING) $stop;
- | ^~~~~~~
-%Error: t/t_process.v:29:34: Can't find definition of variable: 'SUSPENDED'
- 29 | if (p.status() == process::SUSPENDED) $stop;
- | ^~~~~~~~~
-%Error: t/t_process.v:30:34: Can't find definition of variable: 'KILLED'
- 30 | if (p.status() == process::KILLED) $stop;
- | ^~~~~~
-%Error: t/t_process.v:31:34: Can't find definition of variable: 'FINISHED'
- 31 | if (p.status() == process::FINISHED) $stop;
- | ^~~~~~~~
-%Error: Exiting due to
+%Error: Internal Error: t/t_process.v:26:11: ../V3LinkDot.cpp:#: Bad package link
+ 26 | p = process::self();
+ | ^~~~~~~
diff --git a/test_regress/t/t_prot_lib_comb.pl b/test_regress/t/t_prot_lib_comb.pl
new file mode 100755
index 000000000..296873c8f
--- /dev/null
+++ b/test_regress/t/t_prot_lib_comb.pl
@@ -0,0 +1,69 @@
+#!/usr/bin/env perl
+# Makes the test run with tracing enabled by default, can be overridden
+# with --notrace
+unshift(@ARGV, "--trace");
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2019 by Todd Strader. This program is free software; you
+# can redistribute it and/or modify it under the terms of either the GNU
+# Lesser General Public License Version 3 or the Perl Artistic License
+# Version 2.0.
+# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
+
+scenarios(
+ vlt => 1,
+ xsim => 1,
+ );
+
+$Self->{sim_time} = $Self->{benchmark} * 100 if $Self->{benchmark};
+
+my $secret_prefix = "secret";
+my $secret_dir = "$Self->{obj_dir}/$secret_prefix";
+mkdir $secret_dir;
+
+while (1) {
+ # Always compile the secret file with Verilator no matter what simulator
+ # we are testing with
+ run(logfile => "$secret_dir/vlt_compile.log",
+ cmd => ["perl",
+ "$ENV{VERILATOR_ROOT}/bin/verilator",
+ "--prefix",
+ "Vt_prot_lib_secret",
+ "-cc",
+ "-Mdir",
+ $secret_dir,
+ "--protect-lib",
+ $secret_prefix,
+ "t/t_prot_lib_comb.v"],
+ verilator_run => 1,
+ );
+ last if $Self->{errors};
+
+ run(logfile => "$secret_dir/secret_gcc.log",
+ cmd=>[$ENV{MAKE},
+ "-C",
+ $secret_dir,
+ "-f",
+ "Vt_prot_lib_secret.mk"]);
+ last if $Self->{errors};
+
+ compile(
+ verilator_flags2 => ["$secret_dir/secret.sv",
+ "+define+PROCESS_TOP",
+ "-LDFLAGS",
+ "$secret_prefix/libsecret.a"],
+ xsim_flags2 => ["$secret_dir/secret.sv"],
+ );
+
+ execute(
+ check_finished => 1,
+ xsim_run_flags2 => ["--sv_lib",
+ "$secret_dir/libsecret",
+ "--dpi_absolute"],
+ );
+
+ ok(1);
+ last;
+}
+1;
diff --git a/test_regress/t/t_prot_lib_comb.v b/test_regress/t/t_prot_lib_comb.v
new file mode 100644
index 000000000..9b8e9e96d
--- /dev/null
+++ b/test_regress/t/t_prot_lib_comb.v
@@ -0,0 +1,56 @@
+// DESCRIPTION: Verilator: Verilog Test module
+// This file ONLY is placed into the Public Domain, for any use,
+// without warranty, 2020 by Yutetsu TAKATSUKASA.
+// SPDX-License-Identifier: CC0-1.0
+
+`ifdef PROCESS_TOP
+`define CHECK if (out0 != (in0 ^ in1) || out1 != (in0 | in1) || out2 != (in0 & in1)) begin \
+ $display("Mismatch in0:%b in1:%b out0:%b out1:%b out2:%b", in0, in1, out0, out1, out2); \
+ $stop; \
+ end
+
+module t (/*AUTOARG*/
+ // Inputs
+ clk
+ );
+ input clk;
+
+
+ logic in0, in1;
+ logic out0, out1, out2;
+ logic [31:0] count = 0;
+ // actually XOR and OR and AND
+ secret i_secret(.in0(in0), .in1(in1), .out0(out0), .out1(out1), .out2(out2));
+
+ always @(posedge clk) begin
+ count <= count + 32'd1;
+ if (count == 32'd1) begin
+ in0 <= 1'b0;
+ in1 <= 1'b0;
+ end else if (count == 32'd2) begin
+ `CHECK
+ in0 <= 1'b1;
+ in1 <= 1'b0;
+ end else if (count == 32'd3) begin
+ `CHECK
+ in0 <= 1'b0;
+ in1 <= 1'b1;
+ end else if (count == 32'd4) begin
+ `CHECK
+ in0 <= 1'b1;
+ in1 <= 1'b1;
+ end else if (count == 32'd5) begin
+ `CHECK
+ $write("*-* All Finished *-*\n");
+ $finish;
+ end
+ end
+endmodule
+
+`else
+module secret(input in0, input in1, output out0, output out1, output out2);
+ assign out0 = in0 ^ in1;
+ assign out1 = in0 | in1;
+ assign out2 = in0 & in1;
+endmodule
+`endif
diff --git a/test_regress/t/t_rose.pl b/test_regress/t/t_rose.pl
new file mode 100644
index 000000000..c1a6773e9
--- /dev/null
+++ b/test_regress/t/t_rose.pl
@@ -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.
+
+scenarios(simulator => 1);
+
+compile(
+ verilator_flags2 => ['--assert'],
+ );
+
+execute(
+ check_finished => 1,
+ );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_rose.v b/test_regress/t/t_rose.v
new file mode 100644
index 000000000..1eadaa61d
--- /dev/null
+++ b/test_regress/t/t_rose.v
@@ -0,0 +1,81 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed into the Public Domain, for any use,
+// without warranty, 2020 by Peter Monsson.
+
+module t (/*AUTOARG*/
+ // Inputs
+ clk
+ );
+
+ input clk;
+ integer cyc; initial cyc=1;
+ wire [31:0] in = cyc;
+
+ Test test (/*AUTOINST*/
+ // Inputs
+ .clk (clk),
+ .in (in[31:0]));
+
+ Test2 test2 (/*AUTOINST*/
+ // Inputs
+ .clk (clk),
+ .in (in[31:0]));
+
+ always @ (posedge clk) begin
+ if (cyc!=0) begin
+ cyc <= cyc + 1;
+ if (cyc==10) begin
+ $write("*-* All Finished *-*\n");
+ $finish;
+ end
+ end
+ end
+
+endmodule
+
+module Test (/*AUTOARG*/
+ // Inputs
+ clk, in
+ );
+
+ input clk;
+ input [31:0] in;
+
+ reg [31:0] dly0 = 0;
+
+ // If called in an assertion, sequence, or property, the appropriate clocking event.
+ // Otherwise, if called in a disable condition or a clock expression in an assertion, sequence, or prop, explicit.
+ // Otherwise, if called in an action block of an assertion, the leading clock of the assertion is used.
+ // Otherwise, if called in a procedure, the inferred clock
+ // Otherwise, default clocking
+
+ always @(posedge clk) begin
+ dly0 <= in;
+ // In clock expression
+ $write("in=%0d, dly0=%0d, rose=%0d, past=%0d\n", in, dly0, $rose(dly0), $past(dly0));
+ if ($rose(dly0[4])) $stop;
+ end
+
+ assert property (@(posedge clk) $rose(dly0) || dly0%2==0);
+endmodule
+
+
+module Test2 (/*AUTOARG*/
+ // Inputs
+ clk, in
+ );
+
+ input clk;
+ input [31:0] in;
+
+ reg [31:0] dly0;
+
+ always @(posedge clk) begin
+ dly0 <= in;
+ if ($rose(dly0[31:4])) $stop;
+ end
+
+ default clocking @(posedge clk); endclocking
+ assert property ($rose(dly0[0]) || dly0%2==0);
+endmodule
diff --git a/test_regress/t/t_sc_names.cpp b/test_regress/t/t_sc_names.cpp
new file mode 100644
index 000000000..13316602e
--- /dev/null
+++ b/test_regress/t/t_sc_names.cpp
@@ -0,0 +1,30 @@
+// -*- mode: C++; c-file-style: "cc-mode" -*-
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2020 by Edgar E. Iglesias.
+// SPDX-License-Identifier: CC0-1.0
+
+#include VM_PREFIX_INCLUDE
+#include "Vt_sc_names.h"
+
+VM_PREFIX* tb = NULL;
+
+int sc_main(int argc, char* argv[]) {
+ tb = new VM_PREFIX("tb");
+ std::vector < sc_object* > ch = tb->get_child_objects();
+ bool found = false;
+
+ /* We expect to find clk in here. */
+ for (int i = 0; i < ch.size(); ++i) {
+ if (!strcmp(ch[i]->basename(), "clk")) {
+ found = true;
+ }
+ }
+
+ if (found) {
+ VL_PRINTF("*-* All Finished *-*\n");
+ tb->final();
+ } else {
+ vl_fatal(__FILE__, __LINE__, "tb", "Unexpected results\n");
+ }
+ return 0;
+}
diff --git a/test_regress/t/t_sc_names.pl b/test_regress/t/t_sc_names.pl
new file mode 100755
index 000000000..2dc3e81c8
--- /dev/null
+++ b/test_regress/t/t_sc_names.pl
@@ -0,0 +1,30 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2020 by Edgar E. Iglesias. 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.
+# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
+
+scenarios(simulator => 1);
+
+if (!$Self->have_sc) {
+ skip("No SystemC installed");
+}
+else {
+ top_filename("t/t_sc_names.v");
+
+ compile(
+ make_main => 0,
+ verilator_flags2 => ["-sc --exe $Self->{t_dir}/t_sc_names.cpp"],
+ );
+
+ execute(
+ check_finished => 1,
+ );
+}
+
+ok(1);
+1;
diff --git a/test_regress/t/t_sc_names.v b/test_regress/t/t_sc_names.v
new file mode 100644
index 000000000..13bcd4371
--- /dev/null
+++ b/test_regress/t/t_sc_names.v
@@ -0,0 +1,11 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2020 by Edgar E. Iglesias.
+// SPDX-License-Identifier: CC0-1.0
+
+module t (
+ clk
+ );
+ input clk;
+endmodule
diff --git a/test_regress/t/t_stable.pl b/test_regress/t/t_stable.pl
new file mode 100644
index 000000000..c1a6773e9
--- /dev/null
+++ b/test_regress/t/t_stable.pl
@@ -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.
+
+scenarios(simulator => 1);
+
+compile(
+ verilator_flags2 => ['--assert'],
+ );
+
+execute(
+ check_finished => 1,
+ );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_stable.v b/test_regress/t/t_stable.v
new file mode 100644
index 000000000..9b9a831b7
--- /dev/null
+++ b/test_regress/t/t_stable.v
@@ -0,0 +1,81 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed into the Public Domain, for any use,
+// without warranty, 2020 by Peter Monsson.
+
+module t (/*AUTOARG*/
+ // Inputs
+ clk
+ );
+
+ input clk;
+ integer cyc; initial cyc=1;
+ wire [31:0] in = cyc;
+
+ Test test (/*AUTOINST*/
+ // Inputs
+ .clk (clk),
+ .in (in[31:0]));
+
+ Test2 test2 (/*AUTOINST*/
+ // Inputs
+ .clk (clk),
+ .in (in[31:0]));
+
+
+ always @ (posedge clk) begin
+ if (cyc!=0) begin
+ cyc <= cyc + 1;
+ if (cyc==10) begin
+ $write("*-* All Finished *-*\n");
+ $finish;
+ end
+ end
+ end
+
+endmodule
+
+module Test (/*AUTOARG*/
+ // Inputs
+ clk, in
+ );
+
+ input clk;
+ input [31:0] in;
+
+ reg [31:0] dly0 = -1;
+
+ // If called in an assertion, sequence, or property, the appropriate clocking event.
+ // Otherwise, if called in a disable condition or a clock expression in an assertion, sequence, or prop, explicit.
+ // Otherwise, if called in an action block of an assertion, the leading clock of the assertion is used.
+ // Otherwise, if called in a procedure, the inferred clock
+ // Otherwise, default clocking
+
+ always @(posedge clk) begin
+ dly0 <= in;
+ // In clock expression
+ $write("dly0=%0d, in=%0d, stable=%0d, past=%0d\n", dly0, in, $stable(dly0), $past(dly0));
+ if ($stable(dly0)) $stop;
+ end
+
+ assert property (@(posedge clk) !$stable(dly0));
+endmodule
+
+module Test2 (/*AUTOARG*/
+ // Inputs
+ clk, in
+ );
+
+ input clk;
+ input [31:0] in;
+
+ reg [31:0] dly0;
+
+ always @(posedge clk) begin
+ dly0 <= in;
+ if (!$stable(dly0[31:4])) $stop;
+ end
+
+ default clocking @(posedge clk); endclocking
+ assert property ($stable(dly0[31:4]));
+endmodule
diff --git a/test_regress/t/t_sys_file_basic.v b/test_regress/t/t_sys_file_basic.v
index 272574d0d..9497d3a2a 100644
--- a/test_regress/t/t_sys_file_basic.v
+++ b/test_regress/t/t_sys_file_basic.v
@@ -8,7 +8,7 @@
`define STRINGIFY(x) `"x`"
`define ratio_error(a,b) (((a)>(b) ? ((a)-(b)) : ((b)-(a))) /(a))
-`define checkr(gotv,expv) do if (`ratio_error((gotv),(expv))>0.0001) begin $write("%%Error: %s:%0d: got=%g exp=%g\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
+`define checkr(gotv,expv) do if (`ratio_error((gotv),(expv))>0.0001) begin $write("%%Error: %s:%0d: got=%f exp=%f\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
`define checks(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='%s' exp='%s'\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
diff --git a/test_regress/t/t_wire_types.v b/test_regress/t/t_wire_types.v
index 11952324a..fb67e7a7b 100644
--- a/test_regress/t/t_wire_types.v
+++ b/test_regress/t/t_wire_types.v
@@ -11,7 +11,7 @@ module t (/*AUTOARG*/
input clk;
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
-`define checkr(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: %s:%0d: got=%g exp=%g\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
+`define checkr(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: %s:%0d: got=%f exp=%f\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
// IEEE: integer_atom_type
wire byte w_byte;
diff --git a/test_regress/t/t_xml_flat_vlvbound.out b/test_regress/t/t_xml_flat_vlvbound.out
new file mode 100644
index 000000000..ae5da8f13
--- /dev/null
+++ b/test_regress/t/t_xml_flat_vlvbound.out
@@ -0,0 +1,200 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_regress/t/t_xml_flat_vlvbound.pl b/test_regress/t/t_xml_flat_vlvbound.pl
new file mode 100755
index 000000000..9c51c5674
--- /dev/null
+++ b/test_regress/t/t_xml_flat_vlvbound.pl
@@ -0,0 +1,25 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2012 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.
+# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
+
+scenarios(vlt => 1);
+
+my $out_filename = "$Self->{obj_dir}/V$Self->{name}.xml";
+
+compile(
+ verilator_flags2 => ['--xml-only', '--flatten'],
+ verilator_make_gmake => 0,
+ make_top_shell => 0,
+ make_main => 0,
+ );
+
+files_identical("$out_filename", $Self->{golden_filename});
+
+ok(1);
+1;
diff --git a/test_regress/t/t_xml_flat_vlvbound.v b/test_regress/t/t_xml_flat_vlvbound.v
new file mode 100644
index 000000000..9ed0db0cf
--- /dev/null
+++ b/test_regress/t/t_xml_flat_vlvbound.v
@@ -0,0 +1,27 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2012 by Wilson Snyder.
+// SPDX-License-Identifier: CC0-1.0
+
+module vlvbound_test
+ (
+ input logic [15:0] i_a,
+ input logic [15:0] i_b,
+ output logic [6:0] o_a,
+ output logic [6:0] o_b
+ );
+
+ function automatic logic [6:0] foo(input logic [15:0] val);
+ logic [6:0] ret;
+ integer i;
+ for (i=0 ; i < 7; i++) begin
+ ret[i] = (val[i*2 +: 2] == 2'b00);
+ end
+ return ret;
+ endfunction
+
+ assign o_a = foo(i_a);
+ assign o_b = foo(i_b);
+
+endmodule