'Merge from master for release.'

This commit is contained in:
Wilson Snyder 2020-08-15 09:18:29 -04:00
commit c4f7bd6a04
65 changed files with 1975 additions and 296 deletions

1
.gitignore vendored
View File

@ -1,5 +1,6 @@
\#*
.#*
.nfs*
*~
*.tidy
*.old

29
Changes
View File

@ -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

View File

@ -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 '<input file>', 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

View File

@ -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)

View File

@ -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

View File

@ -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<double>(lwp[0]);
if (ms_word == 1) return static_cast<double>(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<double>(ihi) * exp2(2 * VL_EDATASIZE);
double mid = static_cast<double>(imid) * exp2(VL_EDATASIZE);
double lo = static_cast<double>(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

View File

@ -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<double>(static_cast<vlsint32_t>(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<double>(static_cast<vluint32_t>(lhs));
}
static inline double VL_ITOR_D_Q(int, QData lhs) VL_PURE {
return static_cast<double>(static_cast<vluint64_t>(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<double>(static_cast<vlsint32_t>(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<double>(static_cast<vlsint64_t>(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

View File

@ -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; }

View File

@ -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());

View File

@ -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

View File

@ -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);

View File

@ -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<const AstPackageRef*>(samep)->m_packagep);
return (m_classOrPackagep
== static_cast<const AstClassOrPackageRef*>(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, ...

View File

@ -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

View File

@ -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
}

View File

@ -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 {

View File

@ -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);

View File

@ -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);

View File

@ -106,6 +106,8 @@ private:
typedef std::deque<AstCell*> 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;

View File

@ -139,7 +139,6 @@ struct V3ParseBisonYYSType {
AstSenItem* senitemp;
AstNodeVarRef* varnodep;
AstPackage* packagep;
AstPackageRef* packagerefp;
AstParseRef* parserefp;
AstPatMember* patmemberp;
AstPattern* patternp;

View File

@ -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);
}
};

View File

@ -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 {

View File

@ -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.

View File

@ -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 */

View File

@ -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<fl> yD_FDISPLAYB "$fdisplayb"
%token<fl> yD_FDISPLAYH "$fdisplayh"
%token<fl> yD_FDISPLAYO "$fdisplayo"
%token<fl> yD_FELL "$fell"
%token<fl> yD_FEOF "$feof"
%token<fl> yD_FERROR "$ferror"
%token<fl> yD_FFLUSH "$fflush"
@ -771,6 +761,7 @@ BISONPRE_VERSION(3.0,%define parse.error verbose)
%token<fl> yD_REWIND "$rewind"
%token<fl> yD_RIGHT "$right"
%token<fl> yD_ROOT "$root"
%token<fl> yD_ROSE "$rose"
%token<fl> yD_RTOI "$rtoi"
%token<fl> yD_SAMPLED "$sampled"
%token<fl> yD_SFORMAT "$sformat"
@ -782,6 +773,7 @@ BISONPRE_VERSION(3.0,%define parse.error verbose)
%token<fl> yD_SIZE "$size"
%token<fl> yD_SQRT "$sqrt"
%token<fl> yD_SSCANF "$sscanf"
%token<fl> yD_STABLE "$stable"
%token<fl> yD_STIME "$stime"
%token<fl> yD_STOP "$stop"
%token<fl> yD_SWRITE "$swrite"
@ -1476,7 +1468,7 @@ program_declaration: // IEEE: program_declaration + program_nonansi_header + pr
pgmFront<modulep>:
yPROGRAM lifetimeE idAny/*new_program*/
{ $$ = new AstModule($<fl>3,*$3);
{ $$ = new AstModule($<fl>3, *$3, true);
$$->lifetime($2);
$$->inLibrary(PARSEP->inLibrary() || $$->fileline()->celldefineOn());
$$->modTrace(GRAMMARP->allTracingOn($$->fileline()));
@ -1783,8 +1775,8 @@ simple_type<dtypep>: // ==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($<fl>2, *$2);
refp->packagep($1); $$ = refp; }
{ AstRefDType* refp = new AstRefDType($<fl>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<dtypep>: // ==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($<fl>2, *$2);
refp->packagep($1);
{ AstRefDType* refp = new AstRefDType($<fl>2, *$2, $1, NULL);
$$ = GRAMMARP->createArray(refp, $3, true); }
| packageClassScopeE idType parameter_value_assignmentClass packed_dimensionListE
{ AstRefDType* refp = new AstRefDType($<fl>2, *$2);
refp->packagep($1);
BBUNSUP($3->fileline(), "Unsupported: Parameter classes");
{ AstRefDType* refp = new AstRefDType($<fl>2, *$2, $1, $3);
$$ = GRAMMARP->createArray(refp, $4, true); }
;
@ -1851,7 +1840,8 @@ var_data_type<dtypep>: // ==IEEE: var_data_type
;
type_reference<dtypep>: // ==IEEE: type_reference
yTYPE '(' exprOrDataType ')' { $$ = new AstRefDType($1, AstRefDType::FlagTypeOfExpr(), $3); }
yTYPE '(' exprOrDataType ')'
{ $$ = new AstRefDType($1, AstRefDType::FlagTypeOfExpr(), $3); }
;
struct_unionDecl<uorstructp>: // IEEE: part of data_type
@ -2021,8 +2011,7 @@ enum_base_typeE<dtypep>: // IEEE: enum_base_type
| idAny rangeListE
{ $$ = GRAMMARP->createArray(new AstRefDType($<fl>1, *$1), $2, true); }
| packageClassScope idAny rangeListE
{ AstRefDType* refp = new AstRefDType($<fl>2, *$2);
refp->packagep($1);
{ AstRefDType* refp = new AstRefDType($<fl>2, *$2, $1, NULL);
$$ = GRAMMARP->createArray(refp, $3, true); }
;
@ -2526,7 +2515,7 @@ delay_control<nodep>: //== IEEE: delay_control
delay_value<nodep>: // ==IEEE:delay_value
// // IEEE: ps_identifier
packageClassScopeE varRefBase { $$ = $2; $2->packagep($1); }
packageClassScopeE varRefBase { $$ = AstDot::newIfPkg($<fl>2, $1, $2); }
| yaINTNUM { $$ = new AstConst($<fl>1, *$1); }
| yaFLOATNUM { $$ = new AstConst($<fl>1, AstConst::RealDouble(), $1); }
| timeNumAdjusted { $$ = $1; }
@ -3412,7 +3401,7 @@ taskRef<nodep>: // IEEE: part of tf_call
id { $$ = new AstTaskRef($<fl>1,*$1,NULL); }
| id '(' list_of_argumentsE ')' { $$ = new AstTaskRef($<fl>1,*$1,$3); }
| packageClassScope id '(' list_of_argumentsE ')'
{ $$ = AstDot::newIfPkg($<fl>2, CAST_PACKAGE_CLASS($1), new AstTaskRef($<fl>2, *$2, $4)); }
{ $$ = AstDot::newIfPkg($<fl>2, $1, new AstTaskRef($<fl>2, *$2, $4)); }
;
funcRef<nodep>: // IEEE: part of tf_call
@ -3428,7 +3417,7 @@ funcRef<nodep>: // IEEE: part of tf_call
id '(' list_of_argumentsE ')'
{ $$ = new AstFuncRef($<fl>1, *$1, $3); }
| packageClassScope id '(' list_of_argumentsE ')'
{ $$ = AstDot::newIfPkg($<fl>2, CAST_PACKAGE_CLASS($1), new AstFuncRef($<fl>2, *$2, $4)); }
{ $$ = AstDot::newIfPkg($<fl>2, $1, new AstFuncRef($<fl>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<nodep>: // 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<nodep>: // 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<nodep>: // 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<nodep>: // scope and variable for use to inside an expression
yTHIS { $$ = new AstParseRef($<fl>1, VParseRefExp::PX_ROOT, "this"); }
| yD_ROOT { $$ = new AstParseRef($<fl>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($<fl>2, false, $1, $3); }
// // expr below must be a "yTHIS"
| ~l~expr '.' ySUPER { $$ = $1; BBUNSUP($3, "Unsupported: super"); }
@ -4742,7 +4737,7 @@ idClassSel<nodep>: // Misc Ref to dotted, and/or arrayed, and/or bit-ranged va
{ $$ = new AstDot($2, false, new AstParseRef($<fl>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($<fl>2, true, $1, $2); }
;
idClassSelForeach<nodep>:
@ -4754,7 +4749,7 @@ idClassSelForeach<nodep>:
{ $$ = new AstDot($2, false, new AstParseRef($<fl>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($<fl>2, true, $1, $2); }
;
idDotted<nodep>:
@ -4785,7 +4780,8 @@ idDottedMoreForeach<nodep>:
// id below includes:
// enum_identifier
idArrayed<nodep>: // IEEE: id + select
id { $$ = new AstParseRef($<fl>1, VParseRefExp::PX_TEXT, *$1, NULL, NULL); }
id
{ $$ = new AstParseRef($<fl>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<nodep>: // IEEE: id + select
;
idArrayedForeach<nodep>: // IEEE: id + select (under foreach expression)
id { $$ = new AstParseRef($<fl>1, VParseRefExp::PX_TEXT, *$1, NULL, NULL); }
id
{ $$ = new AstParseRef($<fl>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<nodep>: // 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($<fl>1, VParseRefExp::PX_TEXT, *$1, NULL, NULL);
$<scp>$ = $<scp>1;
if ($3) BBUNSUP($3->fileline(), "Unsupported: Parameterized classes"); }
{ $$ = new AstClassOrPackageRef($<fl>1, *$1, $<scp>1, $3);
$<scp>$ = $<scp>1; }
//
// // package_sopeIdFollows expanded
| yD_UNIT yP_COLONCOLON
{ $$ = new AstParseRef($<fl>1, VParseRefExp::PX_TEXT, "$unit", NULL, NULL);
{ $$ = new AstClassOrPackageRef($<fl>1, "$unit", NULL, NULL);
$<scp>$ = NULL; // No purpose otherwise, every symtab can see root
SYMP->nextId(PARSEP->rootp()); }
//
| yLOCAL__COLONCOLON yP_COLONCOLON
{ $$ = new AstParseRef($<fl>1, VParseRefExp::PX_TEXT, "local", NULL, NULL);
{ $$ = new AstClassOrPackageRef($<fl>1, "local::", NULL, NULL);
$<scp>$ = NULL; // UNSUP
SYMP->nextId(PARSEP->rootp());
BBUNSUP($1, "Unsupported: Randomize 'local::'"); }
@ -5912,11 +5908,11 @@ class_typeExtImpOne<nodep>: // part of IEEE: class_type, where we either get a p
//=== Below rules assume special scoping per above
packageClassScopeNoId<packagep>: // IEEE: [package_scope] not followed by yaID
packageClassScopeNoId<nodep>: // IEEE: [package_scope] not followed by yaID
packageClassScope { $$ = $1; $<scp>$ = $<scp>1; SYMP->nextId(NULL); }
;
packageClassScopeE<packagep>: // IEEE: [package_scope]
packageClassScopeE<nodep>: // 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<packagep>: // IEEE: [package_scope]
| packageClassScope { $$ = $1; $<scp>$ = $<scp>1; }
;
packageClassScope<packagep>: // IEEE: class_scope + type
packageClassScope<nodep>: // 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<packagep>: // IEEE: class_scope + type
packageClassScopeList { $$ = $1; $<scp>$ = $<scp>1; }
| localNextId yP_COLONCOLON { $$ = $1; $<scp>$ = $<scp>1; }
| dollarUnitNextId yP_COLONCOLON { $$ = $1; $<scp>$ = $<scp>1; }
| dollarUnitNextId yP_COLONCOLON packageClassScopeList { $$ = $3; $<scp>$ = $<scp>3; }
| dollarUnitNextId yP_COLONCOLON packageClassScopeList
{ $$ = new AstDot($2, true, $1, $3); $<scp>$ = $<scp>3; }
;
packageClassScopeList<packagep>: // IEEE: class_type: "id [ parameter_value_assignment ]" but allow yaID__aTYPE
packageClassScopeList<nodep>: // 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<packagep>: // 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; $<scp>$ = $<scp>1; }
| packageClassScopeList packageClassScopeItem
{ $$ = $2; $<scp>$ = $<scp>2; BBUNSUP($<fl>2, "Unsupported: Nested :: references"); }
{ $$ = new AstDot($<fl>2, true, $1, $2); $<scp>$ = $<scp>2; }
;
packageClassScopeItem<packagep>: // IEEE: package_scope or [package_scope]::[class_scope]
packageClassScopeItem<nodep>: // 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<packagep>: // IEEE: package_scope or [package_scope]::[cla
idCC
/*mid*/ { SYMP->nextId($<scp>1); }
/*cont*/ yP_COLONCOLON
{ $$ = VN_CAST($<scp>1, Package); $<scp>$ = $<scp>1; } // UNSUP classes
{ $$ = new AstClassOrPackageRef($<fl>1, *$1, $<scp>1, NULL); $<scp>$ = $<scp>1; }
//
| idCC parameter_value_assignment
/*mid*/ { SYMP->nextId($<scp>1); } // Change next *after* we handle parameters, not before
/*cont*/ yP_COLONCOLON
{ $$ = VN_CAST($<scp>1, Package); $<scp>$ = $<scp>1; // UNSUP classes
if ($2) BBUNSUP($2->fileline(), "Unsupported: Parameterized classes"); }
{ $$ = new AstClassOrPackageRef($<fl>1, *$1, $<scp>1, $2); $<scp>$ = $<scp>1; }
;
dollarUnitNextId<packagep>: // $unit
dollarUnitNextId<nodep>: // $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($<fl>1); SYMP->nextId(PARSEP->rootp()); }
{ $$ = new AstClassOrPackageRef($1, "$unit", GRAMMARP->unitPackage($<fl>1), NULL);
SYMP->nextId(PARSEP->rootp()); }
;
localNextId<packagep>: // local
localNextId<nodep>: // 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($<fl>1); SYMP->nextId(PARSEP->rootp());
{ $$ = new AstClassOrPackageRef($1, "local::", GRAMMARP->unitPackage($<fl>1), NULL);
SYMP->nextId(PARSEP->rootp());
BBUNSUP($<fl>1, "Unsupported: Randomize 'local::'"); }
;

View File

@ -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.

View File

@ -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

View File

@ -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;
| ^~~~

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

21
test_regress/t/t_const_hi.pl Executable file
View File

@ -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;

View File

@ -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

21
test_regress/t/t_fell.pl Normal file
View File

@ -0,0 +1,21 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
scenarios(simulator => 1);
compile(
verilator_flags2 => ['--assert'],
);
execute(
check_finished => 1,
);
ok(1);
1;

81
test_regress/t/t_fell.v Normal file
View File

@ -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

View File

@ -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

View File

@ -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");

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

21
test_regress/t/t_param_func2.pl Executable file
View File

@ -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;

View File

@ -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

View File

@ -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

21
test_regress/t/t_param_width.pl Executable file
View File

@ -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;

View File

@ -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

View File

@ -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();
| ^~~~~~~

View File

@ -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;

View File

@ -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

21
test_regress/t/t_rose.pl Normal file
View File

@ -0,0 +1,21 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
scenarios(simulator => 1);
compile(
verilator_flags2 => ['--assert'],
);
execute(
check_finished => 1,
);
ok(1);
1;

81
test_regress/t/t_rose.v Normal file
View File

@ -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

View File

@ -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;
}

30
test_regress/t/t_sc_names.pl Executable file
View File

@ -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;

View File

@ -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

View File

@ -0,0 +1,21 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
scenarios(simulator => 1);
compile(
verilator_flags2 => ['--assert'],
);
execute(
check_finished => 1,
);
ok(1);
1;

81
test_regress/t/t_stable.v Normal file
View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -0,0 +1,200 @@
<?xml version="1.0" ?>
<!-- DESCRIPTION: Verilator output: XML representation of netlist -->
<verilator_xml>
<files>
<file id="a" filename="&lt;built-in&gt;" language="1800-2017"/>
<file id="b" filename="&lt;command-line&gt;" language="1800-2017"/>
<file id="c" filename="input.vc" language="1800-2017"/>
<file id="d" filename="t/t_xml_flat_vlvbound.v" language="1800-2017"/>
</files>
<module_files>
<file id="d" filename="t/t_xml_flat_vlvbound.v" language="1800-2017"/>
</module_files>
<cells>
<cell fl="d7" loc="d,7,8,7,21" name="TOP" submodname="TOP" hier="TOP"/>
</cells>
<netlist>
<module fl="d7" loc="d,7,8,7,21" name="TOP" origName="TOP" topModule="1" public="true">
<var fl="d9" loc="d,9,25,9,28" name="i_a" dtype_id="1" dir="input" vartype="logic" origName="i_a" public="true"/>
<var fl="d10" loc="d,10,25,10,28" name="i_b" dtype_id="1" dir="input" vartype="logic" origName="i_b" public="true"/>
<var fl="d11" loc="d,11,25,11,28" name="o_a" dtype_id="2" dir="output" vartype="logic" origName="o_a" public="true"/>
<var fl="d12" loc="d,12,25,12,28" name="o_b" dtype_id="2" dir="output" vartype="logic" origName="o_b" public="true"/>
<var fl="d9" loc="d,9,25,9,28" name="vlvbound_test.i_a" dtype_id="1" vartype="logic" origName="i_a"/>
<var fl="d10" loc="d,10,25,10,28" name="vlvbound_test.i_b" dtype_id="1" vartype="logic" origName="i_b"/>
<var fl="d11" loc="d,11,25,11,28" name="vlvbound_test.o_a" dtype_id="2" vartype="logic" origName="o_a"/>
<var fl="d12" loc="d,12,25,12,28" name="vlvbound_test.o_b" dtype_id="2" vartype="logic" origName="o_b"/>
<topscope fl="d7" loc="d,7,8,7,21">
<scope fl="d7" loc="d,7,8,7,21" name="TOP">
<varscope fl="d9" loc="d,9,25,9,28" name="i_a" dtype_id="1"/>
<varscope fl="d10" loc="d,10,25,10,28" name="i_b" dtype_id="1"/>
<varscope fl="d11" loc="d,11,25,11,28" name="o_a" dtype_id="2"/>
<varscope fl="d12" loc="d,12,25,12,28" name="o_b" dtype_id="2"/>
<varscope fl="d9" loc="d,9,25,9,28" name="vlvbound_test.i_a" dtype_id="1"/>
<varscope fl="d10" loc="d,10,25,10,28" name="vlvbound_test.i_b" dtype_id="1"/>
<varscope fl="d11" loc="d,11,25,11,28" name="vlvbound_test.o_a" dtype_id="2"/>
<varscope fl="d12" loc="d,12,25,12,28" name="vlvbound_test.o_b" dtype_id="2"/>
<varscope fl="d15" loc="d,15,34,15,37" name="__Vfunc_vlvbound_test.foo__0__Vfuncout" dtype_id="2"/>
<varscope fl="d15" loc="d,15,57,15,60" name="__Vfunc_vlvbound_test.foo__0__val" dtype_id="1"/>
<varscope fl="d16" loc="d,16,17,16,20" name="__Vfunc_vlvbound_test.foo__0__ret" dtype_id="2"/>
<varscope fl="d17" loc="d,17,13,17,14" name="__Vfunc_vlvbound_test.foo__0__i" dtype_id="3"/>
<varscope fl="d15" loc="d,15,34,15,37" name="__Vfunc_vlvbound_test.foo__1__Vfuncout" dtype_id="2"/>
<varscope fl="d15" loc="d,15,57,15,60" name="__Vfunc_vlvbound_test.foo__1__val" dtype_id="1"/>
<varscope fl="d16" loc="d,16,17,16,20" name="__Vfunc_vlvbound_test.foo__1__ret" dtype_id="2"/>
<varscope fl="d17" loc="d,17,13,17,14" name="__Vfunc_vlvbound_test.foo__1__i" dtype_id="3"/>
<assignalias fl="d9" loc="d,9,25,9,28" dtype_id="1">
<varref fl="d9" loc="d,9,25,9,28" name="i_a" dtype_id="1"/>
<varref fl="d9" loc="d,9,25,9,28" name="i_a" dtype_id="1"/>
</assignalias>
<assignalias fl="d10" loc="d,10,25,10,28" dtype_id="1">
<varref fl="d10" loc="d,10,25,10,28" name="i_b" dtype_id="1"/>
<varref fl="d10" loc="d,10,25,10,28" name="i_b" dtype_id="1"/>
</assignalias>
<assignalias fl="d11" loc="d,11,25,11,28" dtype_id="2">
<varref fl="d11" loc="d,11,25,11,28" name="o_a" dtype_id="2"/>
<varref fl="d11" loc="d,11,25,11,28" name="o_a" dtype_id="2"/>
</assignalias>
<assignalias fl="d12" loc="d,12,25,12,28" dtype_id="2">
<varref fl="d12" loc="d,12,25,12,28" name="o_b" dtype_id="2"/>
<varref fl="d12" loc="d,12,25,12,28" name="o_b" dtype_id="2"/>
</assignalias>
<always fl="d24" loc="d,24,14,24,15">
<comment fl="d24" loc="d,24,16,24,19" name="Function: foo"/>
<assign fl="d24" loc="d,24,20,24,23" dtype_id="1">
<varref fl="d24" loc="d,24,20,24,23" name="i_a" dtype_id="1"/>
<varref fl="d15" loc="d,15,57,15,60" name="__Vfunc_vlvbound_test.foo__0__val" dtype_id="1"/>
</assign>
<assign fl="d18" loc="d,18,11,18,12" dtype_id="3">
<const fl="d18" loc="d,18,12,18,13" name="32&apos;sh0" dtype_id="4"/>
<varref fl="d18" loc="d,18,10,18,11" name="__Vfunc_vlvbound_test.foo__0__i" dtype_id="3"/>
</assign>
<while fl="d18" loc="d,18,5,18,8">
<gts fl="d18" loc="d,18,18,18,19" dtype_id="5">
<const fl="d18" loc="d,18,20,18,21" name="32&apos;sh7" dtype_id="4"/>
<varref fl="d18" loc="d,18,16,18,17" name="__Vfunc_vlvbound_test.foo__0__i" dtype_id="3"/>
</gts>
<assign fl="d19" loc="d,19,14,19,15" dtype_id="6">
<eq fl="d19" loc="d,19,31,19,33" dtype_id="6">
<const fl="d19" loc="d,19,34,19,39" name="2&apos;h0" dtype_id="7"/>
<sel fl="d19" loc="d,19,20,19,21" dtype_id="7">
<varref fl="d19" loc="d,19,17,19,20" name="__Vfunc_vlvbound_test.foo__0__val" dtype_id="1"/>
<sel fl="d19" loc="d,19,22,19,23" dtype_id="8">
<muls fl="d19" loc="d,19,22,19,23" dtype_id="4">
<const fl="d19" loc="d,19,23,19,24" name="32&apos;sh2" dtype_id="4"/>
<varref fl="d19" loc="d,19,21,19,22" name="__Vfunc_vlvbound_test.foo__0__i" dtype_id="3"/>
</muls>
<const fl="d19" loc="d,19,22,19,23" name="32&apos;h0" dtype_id="9"/>
<const fl="d19" loc="d,19,22,19,23" name="32&apos;h4" dtype_id="9"/>
</sel>
<const fl="d19" loc="d,19,28,19,29" name="32&apos;sh2" dtype_id="4"/>
</sel>
</eq>
<sel fl="d19" loc="d,19,10,19,11" dtype_id="6">
<varref fl="d19" loc="d,19,7,19,10" name="__Vfunc_vlvbound_test.foo__0__ret" dtype_id="2"/>
<sel fl="d19" loc="d,19,11,19,12" dtype_id="10">
<varref fl="d19" loc="d,19,11,19,12" name="__Vfunc_vlvbound_test.foo__0__i" dtype_id="3"/>
<const fl="d19" loc="d,19,11,19,12" name="32&apos;h0" dtype_id="9"/>
<const fl="d19" loc="d,19,11,19,12" name="32&apos;h3" dtype_id="9"/>
</sel>
<const fl="d19" loc="d,19,10,19,11" name="32&apos;h1" dtype_id="9"/>
</sel>
</assign>
<assign fl="d18" loc="d,18,24,18,26" dtype_id="3">
<add fl="d18" loc="d,18,24,18,26" dtype_id="9">
<const fl="d18" loc="d,18,24,18,26" name="32&apos;h1" dtype_id="9"/>
<varref fl="d18" loc="d,18,23,18,24" name="__Vfunc_vlvbound_test.foo__0__i" dtype_id="3"/>
</add>
<varref fl="d18" loc="d,18,23,18,24" name="__Vfunc_vlvbound_test.foo__0__i" dtype_id="3"/>
</assign>
</while>
<assign fl="d21" loc="d,21,5,21,11" dtype_id="2">
<varref fl="d21" loc="d,21,12,21,15" name="__Vfunc_vlvbound_test.foo__0__ret" dtype_id="2"/>
<varref fl="d21" loc="d,21,5,21,11" name="__Vfunc_vlvbound_test.foo__0__Vfuncout" dtype_id="2"/>
</assign>
<assign fl="d24" loc="d,24,14,24,15" dtype_id="2">
<varref fl="d24" loc="d,24,16,24,19" name="__Vfunc_vlvbound_test.foo__0__Vfuncout" dtype_id="2"/>
<varref fl="d24" loc="d,24,10,24,13" name="o_a" dtype_id="2"/>
</assign>
</always>
<always fl="d25" loc="d,25,14,25,15">
<comment fl="d25" loc="d,25,16,25,19" name="Function: foo"/>
<assign fl="d25" loc="d,25,20,25,23" dtype_id="1">
<varref fl="d25" loc="d,25,20,25,23" name="i_b" dtype_id="1"/>
<varref fl="d15" loc="d,15,57,15,60" name="__Vfunc_vlvbound_test.foo__1__val" dtype_id="1"/>
</assign>
<assign fl="d18" loc="d,18,11,18,12" dtype_id="3">
<const fl="d18" loc="d,18,12,18,13" name="32&apos;sh0" dtype_id="4"/>
<varref fl="d18" loc="d,18,10,18,11" name="__Vfunc_vlvbound_test.foo__1__i" dtype_id="3"/>
</assign>
<while fl="d18" loc="d,18,5,18,8">
<gts fl="d18" loc="d,18,18,18,19" dtype_id="5">
<const fl="d18" loc="d,18,20,18,21" name="32&apos;sh7" dtype_id="4"/>
<varref fl="d18" loc="d,18,16,18,17" name="__Vfunc_vlvbound_test.foo__1__i" dtype_id="3"/>
</gts>
<assign fl="d19" loc="d,19,14,19,15" dtype_id="6">
<eq fl="d19" loc="d,19,31,19,33" dtype_id="6">
<const fl="d19" loc="d,19,34,19,39" name="2&apos;h0" dtype_id="7"/>
<sel fl="d19" loc="d,19,20,19,21" dtype_id="7">
<varref fl="d19" loc="d,19,17,19,20" name="__Vfunc_vlvbound_test.foo__1__val" dtype_id="1"/>
<sel fl="d19" loc="d,19,22,19,23" dtype_id="8">
<muls fl="d19" loc="d,19,22,19,23" dtype_id="4">
<const fl="d19" loc="d,19,23,19,24" name="32&apos;sh2" dtype_id="4"/>
<varref fl="d19" loc="d,19,21,19,22" name="__Vfunc_vlvbound_test.foo__1__i" dtype_id="3"/>
</muls>
<const fl="d19" loc="d,19,22,19,23" name="32&apos;h0" dtype_id="9"/>
<const fl="d19" loc="d,19,22,19,23" name="32&apos;h4" dtype_id="9"/>
</sel>
<const fl="d19" loc="d,19,28,19,29" name="32&apos;sh2" dtype_id="4"/>
</sel>
</eq>
<sel fl="d19" loc="d,19,10,19,11" dtype_id="6">
<varref fl="d19" loc="d,19,7,19,10" name="__Vfunc_vlvbound_test.foo__1__ret" dtype_id="2"/>
<sel fl="d19" loc="d,19,11,19,12" dtype_id="10">
<varref fl="d19" loc="d,19,11,19,12" name="__Vfunc_vlvbound_test.foo__1__i" dtype_id="3"/>
<const fl="d19" loc="d,19,11,19,12" name="32&apos;h0" dtype_id="9"/>
<const fl="d19" loc="d,19,11,19,12" name="32&apos;h3" dtype_id="9"/>
</sel>
<const fl="d19" loc="d,19,10,19,11" name="32&apos;h1" dtype_id="9"/>
</sel>
</assign>
<assign fl="d18" loc="d,18,24,18,26" dtype_id="3">
<add fl="d18" loc="d,18,24,18,26" dtype_id="9">
<const fl="d18" loc="d,18,24,18,26" name="32&apos;h1" dtype_id="9"/>
<varref fl="d18" loc="d,18,23,18,24" name="__Vfunc_vlvbound_test.foo__1__i" dtype_id="3"/>
</add>
<varref fl="d18" loc="d,18,23,18,24" name="__Vfunc_vlvbound_test.foo__1__i" dtype_id="3"/>
</assign>
</while>
<assign fl="d21" loc="d,21,5,21,11" dtype_id="2">
<varref fl="d21" loc="d,21,12,21,15" name="__Vfunc_vlvbound_test.foo__1__ret" dtype_id="2"/>
<varref fl="d21" loc="d,21,5,21,11" name="__Vfunc_vlvbound_test.foo__1__Vfuncout" dtype_id="2"/>
</assign>
<assign fl="d25" loc="d,25,14,25,15" dtype_id="2">
<varref fl="d25" loc="d,25,16,25,19" name="__Vfunc_vlvbound_test.foo__1__Vfuncout" dtype_id="2"/>
<varref fl="d25" loc="d,25,10,25,13" name="o_b" dtype_id="2"/>
</assign>
</always>
</scope>
</topscope>
<var fl="d15" loc="d,15,34,15,37" name="__Vfunc_vlvbound_test.foo__0__Vfuncout" dtype_id="2" vartype="logic" origName="__Vfunc_vlvbound_test__DOT__foo__0__Vfuncout"/>
<var fl="d15" loc="d,15,57,15,60" name="__Vfunc_vlvbound_test.foo__0__val" dtype_id="1" vartype="logic" origName="__Vfunc_vlvbound_test__DOT__foo__0__val"/>
<var fl="d16" loc="d,16,17,16,20" name="__Vfunc_vlvbound_test.foo__0__ret" dtype_id="2" vartype="logic" origName="__Vfunc_vlvbound_test__DOT__foo__0__ret"/>
<var fl="d17" loc="d,17,13,17,14" name="__Vfunc_vlvbound_test.foo__0__i" dtype_id="3" vartype="integer" origName="__Vfunc_vlvbound_test__DOT__foo__0__i"/>
<var fl="d15" loc="d,15,34,15,37" name="__Vfunc_vlvbound_test.foo__1__Vfuncout" dtype_id="2" vartype="logic" origName="__Vfunc_vlvbound_test__DOT__foo__1__Vfuncout"/>
<var fl="d15" loc="d,15,57,15,60" name="__Vfunc_vlvbound_test.foo__1__val" dtype_id="1" vartype="logic" origName="__Vfunc_vlvbound_test__DOT__foo__1__val"/>
<var fl="d16" loc="d,16,17,16,20" name="__Vfunc_vlvbound_test.foo__1__ret" dtype_id="2" vartype="logic" origName="__Vfunc_vlvbound_test__DOT__foo__1__ret"/>
<var fl="d17" loc="d,17,13,17,14" name="__Vfunc_vlvbound_test.foo__1__i" dtype_id="3" vartype="integer" origName="__Vfunc_vlvbound_test__DOT__foo__1__i"/>
</module>
<typetable fl="a0" loc="a,0,0,0,0">
<basicdtype fl="d18" loc="d,18,18,18,19" id="6" name="logic"/>
<basicdtype fl="d19" loc="d,19,34,19,39" id="7" name="logic" left="1" right="0"/>
<basicdtype fl="d9" loc="d,9,11,9,16" id="1" name="logic" left="15" right="0"/>
<basicdtype fl="d11" loc="d,11,12,11,17" id="2" name="logic" left="6" right="0"/>
<basicdtype fl="d17" loc="d,17,5,17,12" id="3" name="integer" left="31" right="0"/>
<basicdtype fl="d19" loc="d,19,10,19,11" id="10" name="logic" left="2" right="0"/>
<basicdtype fl="d19" loc="d,19,11,19,12" id="9" name="logic" left="31" right="0"/>
<basicdtype fl="d19" loc="d,19,20,19,21" id="8" name="logic" left="3" right="0"/>
<basicdtype fl="d18" loc="d,18,12,18,13" id="4" name="logic" left="31" right="0"/>
<basicdtype fl="d18" loc="d,18,18,18,19" id="5" name="logic"/>
</typetable>
</netlist>
</verilator_xml>

View File

@ -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;

View File

@ -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