mirror of
https://github.com/verilator/verilator.git
synced 2026-10-05 17:43:31 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0abde90933 | ||
|
|
e01b69198a | ||
|
|
53cd9d2403 | ||
|
|
3d0f5fc078 | ||
|
|
54eedcc739 | ||
|
|
ae6f5844da | ||
|
|
1bea845ceb | ||
|
|
d581582339 | ||
|
|
4eabc1992e | ||
|
|
316eb24bbb | ||
|
|
f0a8824efc | ||
|
|
345a5d5646 | ||
|
|
464679c78b | ||
|
|
28eeec1cf4 |
@@ -3,6 +3,23 @@ Revision history for Verilator
|
||||
The contributors that suggested a given feature are shown in []. [by ...]
|
||||
indicates the contributor was also the author of the fix; Thanks!
|
||||
|
||||
* Verilator 3.847 2013-05-11
|
||||
|
||||
*** Add ALWCOMBORDER warning. [KC Buckenmaier]
|
||||
|
||||
*** Add --pins-sc-uint and --pins-sc-biguint, bug638. [Alex Hornung]
|
||||
|
||||
**** Support "signal[vec]++".
|
||||
|
||||
**** Fix simulation error when inputs and MULTIDRIVEN, bug634. [Ted Campbell]
|
||||
|
||||
**** Fix module resolution with __, bug631. [Jason McMullan]
|
||||
|
||||
**** Fix packed array non-zero right index select crash, bug642. [Krzysztof Jankowski]
|
||||
|
||||
**** Fix nested union crash, bug643. [Krzysztof Jankowski]
|
||||
|
||||
|
||||
* Verilator 3.846 2013-03-09
|
||||
|
||||
** IEEE 1800-2012 is now the default language. This adds 4 new keywords
|
||||
|
||||
+38
-7
@@ -302,6 +302,8 @@ descriptions in the next sections for more information.
|
||||
--output-split <bytes> Split .cpp files into pieces
|
||||
--output-split-cfuncs <statements> Split .ccp functions
|
||||
--pins-bv <bits> Specify types for top level ports
|
||||
--pins-sc-uint Specify types for top level ports
|
||||
--pins-sc-biguint Specify types for top level ports
|
||||
--pins-uint8 Specify types for top level ports
|
||||
--pipe-filter <command> Filter all input through a script
|
||||
--prefix <topname> Name of top level class
|
||||
@@ -820,6 +822,20 @@ wide should use sc_bv's instead of uint32/vluint64_t's. The default is
|
||||
33". The more sc_bv is used, the worse for performance. Use the
|
||||
"/*verilator sc_bv*/" attribute to select specific ports to be sc_bv.
|
||||
|
||||
=item --pins-sc-uint
|
||||
|
||||
Specifies SystemC inputs/outputs of greater than 2 bits wide should use
|
||||
sc_uint between 2 and 64. When combined with the "--pins-sc-biguint"
|
||||
combination, it results in sc_uint being used between 2 and 64 and
|
||||
sc_biguint being used between 65 and 512.
|
||||
|
||||
=item --pins-sc-biguint
|
||||
|
||||
Specifies SystemC inputs/outputs of greater than 65 bits wide should use
|
||||
sc_biguint between 65 and 512, and sc_bv from 513 upwards. When combined
|
||||
with the "--pins-sc-uint" combination, it results in sc_uint being used
|
||||
between 2 and 64 and sc_biguint being used between 65 and 512.
|
||||
|
||||
=item --pins-uint8
|
||||
|
||||
Specifies SystemC inputs/outputs that are smaller than the --pins-bv
|
||||
@@ -1052,10 +1068,10 @@ Disable the specified warning message.
|
||||
=item -Wno-lint
|
||||
|
||||
Disable all lint related warning messages, and all style warnings. This is
|
||||
equivalent to "-Wno-CASEINCOMPLETE -Wno-CASEOVERLAP -Wno-CASEX
|
||||
-Wno-CASEWITHX -Wno-CMPCONST -Wno-ENDLABEL -Wno-IMPLICIT -Wno-LITENDIAN
|
||||
-Wno-PINMISSING -Wno-SYNCASYNCNET -Wno-UNDRIVEN -Wno-UNSIGNED -Wno-UNUSED
|
||||
-Wno-WIDTH" plus the list shown for Wno-style.
|
||||
equivalent to "-Wno-ALWCOMBORDER -Wno-CASEINCOMPLETE -Wno-CASEOVERLAP
|
||||
-Wno-CASEX -Wno-CASEWITHX -Wno-CMPCONST -Wno-ENDLABEL -Wno-IMPLICIT
|
||||
-Wno-LITENDIAN -Wno-PINMISSING -Wno-SYNCASYNCNET -Wno-UNDRIVEN
|
||||
-Wno-UNSIGNED -Wno-UNUSED -Wno-WIDTH" plus the list shown for Wno-style.
|
||||
|
||||
It is strongly recommended you cleanup your code rather than using this
|
||||
option, it is only intended to be use when running test-cases of code
|
||||
@@ -1084,9 +1100,10 @@ Enables the specified warning message.
|
||||
|
||||
Enable all lint related warning messages (note by default they are already
|
||||
enabled), but do not affect style messages. This is equivalent to
|
||||
"-Wwarn-CASEINCOMPLETE -Wwarn-CASEOVERLAP -Wwarn-CASEX -Wwarn-CASEWITHX
|
||||
-Wwarn-CMPCONST -Wwarn-ENDLABEL -Wwarn-IMPLICIT -Wwarn-LITENDIAN
|
||||
-Wwarn-PINMISSING -Wwarn-REALCVT -Wwarn-UNSIGNED -Wwarn-WIDTH".
|
||||
"-Wwarn-ALWCOMBORDER -Wwarn-CASEINCOMPLETE -Wwarn-CASEOVERLAP -Wwarn-CASEX
|
||||
-Wwarn-CASEWITHX -Wwarn-CMPCONST -Wwarn-ENDLABEL -Wwarn-IMPLICIT
|
||||
-Wwarn-LITENDIAN -Wwarn-PINMISSING -Wwarn-REALCVT -Wwarn-UNSIGNED
|
||||
-Wwarn-WIDTH".
|
||||
|
||||
=item -Wwarn-style
|
||||
|
||||
@@ -2698,6 +2715,20 @@ List of all warnings:
|
||||
|
||||
=over 4
|
||||
|
||||
=item ALWCOMBORDER
|
||||
|
||||
Warns that an always_comb block has a variable which is set after it is
|
||||
used. This may cause simulation-synthesis mismatches, as not all
|
||||
commercial simulators allow this ordering.
|
||||
|
||||
always_comb begin
|
||||
a = b;
|
||||
b = 1;
|
||||
end
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
|
||||
=item ASSIGNIN
|
||||
|
||||
Error that an assignment is being made to an input signal. This is almost
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
|
||||
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
||||
#AC_INIT([Verilator],[#.### devel])
|
||||
AC_INIT([Verilator],[3.846 2013-03-09])
|
||||
AC_INIT([Verilator],[3.847 2013-05-11])
|
||||
AC_CONFIG_HEADER(src/config_build.h)
|
||||
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk include/verilated_config.h)
|
||||
|
||||
|
||||
@@ -1075,6 +1075,10 @@ const char* Verilated::commandArgsPlusMatch(const char* prefixp) {
|
||||
return VerilatedImp::argPlusMatch(prefixp).c_str();
|
||||
}
|
||||
|
||||
void Verilated::internalsDump() {
|
||||
VerilatedImp::internalsDump();
|
||||
}
|
||||
|
||||
void Verilated::scopesDump() {
|
||||
VerilatedImp::scopesDump();
|
||||
}
|
||||
|
||||
@@ -294,6 +294,11 @@ public:
|
||||
static const char* productName() { return VERILATOR_PRODUCT; }
|
||||
static const char* productVersion() { return VERILATOR_VERSION; }
|
||||
|
||||
/// For debugging, print much of the Verilator internal state.
|
||||
/// The output of this function may change in future
|
||||
/// releases - contact the authors before production use.
|
||||
static void internalsDump();
|
||||
|
||||
/// For debugging, print text list of all scope names with
|
||||
/// dpiImport/Export context. This function may change in future
|
||||
/// releases - contact the authors before production use.
|
||||
@@ -547,6 +552,7 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
|
||||
//===================================================================
|
||||
// SYSTEMC OPERATORS
|
||||
// Copying verilog format to systemc integers and bit vectors.
|
||||
// Get a SystemC variable
|
||||
|
||||
#define VL_ASSIGN_ISI(obits,vvar,svar) { (vvar) = VL_CLEAN_II((obits),(obits),(svar).read()); }
|
||||
#define VL_ASSIGN_QSQ(obits,vvar,svar) { (vvar) = VL_CLEAN_QQ((obits),(obits),(svar).read()); }
|
||||
@@ -564,7 +570,21 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
|
||||
owp[words-1] &= VL_MASK_I(obits); \
|
||||
}
|
||||
|
||||
#define VL_ASSIGN_ISU(obits,vvar,svar) { (vvar) = VL_CLEAN_II((obits),(obits),(svar).read().to_uint()); }
|
||||
#define VL_ASSIGN_QSU(obits,vvar,svar) { (vvar) = VL_CLEAN_QQ((obits),(obits),(svar).read().to_uint64()); }
|
||||
#define VL_ASSIGN_WSB(obits,owp,svar) { \
|
||||
int words = VL_WORDS_I(obits); \
|
||||
sc_biguint<obits> _butemp = (svar).read(); \
|
||||
for (int i=0; i < words; i++) { \
|
||||
int msb = ((i+1)*VL_WORDSIZE) - 1; \
|
||||
msb = (msb >= obits) ? (obits-1) : msb; \
|
||||
owp[i] = _butemp.range(msb,i*VL_WORDSIZE).to_uint(); \
|
||||
} \
|
||||
owp[words-1] &= VL_MASK_I(obits); \
|
||||
}
|
||||
|
||||
// Copying verilog format from systemc integers and bit vectors.
|
||||
// Set a SystemC variable
|
||||
|
||||
#define VL_ASSIGN_SII(obits,svar,vvar) { (svar).write(vvar); }
|
||||
#define VL_ASSIGN_SQQ(obits,svar,vvar) { (svar).write(vvar); }
|
||||
@@ -586,6 +606,20 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
|
||||
svar.write(_bvtemp); \
|
||||
}
|
||||
|
||||
#define VL_ASSIGN_SUI(obits,svar,rd) { (svar).write(rd); }
|
||||
#define VL_ASSIGN_SUQ(obits,svar,rd) { (svar).write(rd); }
|
||||
#define VL_ASSIGN_SBI(obits,svar,rd) { (svar).write(rd); }
|
||||
#define VL_ASSIGN_SBQ(obits,svar,rd) { (svar).write(rd); }
|
||||
#define VL_ASSIGN_SBW(obits,svar,rwp) { \
|
||||
sc_biguint<obits> _butemp; \
|
||||
for (int i=0; i < VL_WORDS_I(obits); i++) { \
|
||||
int msb = ((i+1)*VL_WORDSIZE) - 1; \
|
||||
msb = (msb >= obits) ? (obits-1) : msb; \
|
||||
_butemp.range(msb,i*VL_WORDSIZE) = rwp[i]; \
|
||||
} \
|
||||
svar.write(_butemp); \
|
||||
}
|
||||
|
||||
//===================================================================
|
||||
// Extending sizes
|
||||
|
||||
|
||||
+28
-2
@@ -78,6 +78,18 @@ public: // But only for verilated*.cpp
|
||||
m_fdps[2] = stderr;
|
||||
}
|
||||
~VerilatedImp() {}
|
||||
static void internalsDump() {
|
||||
VL_PRINTF("internalsDump:\n");
|
||||
VL_PRINTF(" Argv:");
|
||||
for (ArgVec::iterator it=s_s.m_argVec.begin(); it!=s_s.m_argVec.end(); ++it) {
|
||||
VL_PRINTF(" %s",it->c_str());
|
||||
}
|
||||
VL_PRINTF("\n");
|
||||
VL_PRINTF(" Version: %s %s\n", Verilated::productName(), Verilated::productVersion());
|
||||
scopesDump();
|
||||
exportsDump();
|
||||
userDump();
|
||||
}
|
||||
|
||||
// METHODS - arguments
|
||||
static void commandArgs(int argc, const char** argv) {
|
||||
@@ -129,6 +141,14 @@ private:
|
||||
}
|
||||
}
|
||||
}
|
||||
static void userDump() {
|
||||
bool first = true;
|
||||
for (UserMap::iterator it=s_s.m_userMap.begin(); it!=s_s.m_userMap.end(); ++it) {
|
||||
if (first) { VL_PRINTF(" userDump:\n"); first=false; }
|
||||
VL_PRINTF(" DPI_USER_DATA scope %p key %p: %p\n",
|
||||
it->first.first, it->first.second, it->second);
|
||||
}
|
||||
}
|
||||
|
||||
public: // But only for verilated*.cpp
|
||||
// METHODS - scope name
|
||||
@@ -150,9 +170,8 @@ public: // But only for verilated*.cpp
|
||||
ScopeNameMap::iterator it=s_s.m_nameMap.find(scopep->name());
|
||||
if (it != s_s.m_nameMap.end()) s_s.m_nameMap.erase(it);
|
||||
}
|
||||
|
||||
static void scopesDump() {
|
||||
VL_PRINTF("scopesDump:\n");
|
||||
VL_PRINTF(" scopesDump:\n");
|
||||
for (ScopeNameMap::iterator it=s_s.m_nameMap.begin(); it!=s_s.m_nameMap.end(); ++it) {
|
||||
const VerilatedScope* scopep = it->second;
|
||||
scopep->scopeDump();
|
||||
@@ -194,6 +213,13 @@ public: // But only for verilated*.cpp
|
||||
}
|
||||
return "*UNKNOWN*";
|
||||
}
|
||||
static void exportsDump() {
|
||||
bool first = true;
|
||||
for (ExportNameMap::iterator it=s_s.m_exportMap.begin(); it!=s_s.m_exportMap.end(); ++it) {
|
||||
if (first) { VL_PRINTF(" exportDump:\n"); first=false; }
|
||||
VL_PRINTF(" DPI_EXPORT_NAME %05d: %s\n", it->second, it->first);
|
||||
}
|
||||
}
|
||||
// We don't free up m_exportMap until the end, because we can't be sure
|
||||
// what other models are using the assigned funcnum's.
|
||||
|
||||
|
||||
+56
-5
@@ -366,10 +366,8 @@ AST.
|
||||
|
||||
=head1 TESTING
|
||||
|
||||
To write a test see the BUGS section of the Verilator primary manual, and
|
||||
the documentation in:
|
||||
|
||||
test_regress/t/driver.pl --help
|
||||
For an overview of how to write a test see the BUGS section of the
|
||||
Verilator primary manual.
|
||||
|
||||
It is important to add tests for failures as well as success (for example to
|
||||
check that an error message is correctly triggered).
|
||||
@@ -378,7 +376,60 @@ Tests that fail should by convenition have the suffix C<_bad> in their name,
|
||||
and include C<fails =E<gt> 1> in either their C<compile> or C<execute> step as
|
||||
appropriate.
|
||||
|
||||
Developers will also want to configure with two extra flags:
|
||||
=head2 Controlling the Test Driver
|
||||
|
||||
Test drivers are written in PERL. All invoke the main test driver script,
|
||||
which can provide detailed help on all the features available when writing
|
||||
a test driver.
|
||||
|
||||
test_regress/t/driver.pl --help
|
||||
|
||||
For convenience, a summary of the most commonly used features is provided
|
||||
here. All drivers require a call to C<compile> subroutine to compile the
|
||||
test. For run-time tests, this is followed by a call to the C<execute>
|
||||
subroutine. Both of these functions can optionally be provided with a hash
|
||||
table as argument specifying additonal options.
|
||||
|
||||
The test driver assumes by default that the source Verilog file name
|
||||
matches the PERL driver name. So a test whose driver is C<t/t_mytest.pl>
|
||||
will expect a Verilog source file C<t/t_mytest.v>. This can be changed
|
||||
using the C<top_filename> subroutine, for example
|
||||
|
||||
top_filename("t/t_myothertest.v");
|
||||
|
||||
By default all tests will run with major simulators (Icarus Verilog, NC,
|
||||
VCS, ModelSim) as well as Verilator, to allow results to be
|
||||
compared. However if you wish a test only to be used with Verilator, you
|
||||
can use the following:
|
||||
|
||||
$Self->{vlt} or $Self->skip("Verilator only test");
|
||||
|
||||
Of the many options that can be set through arguments to C<compiler> and
|
||||
C<execute>, the following are particularly useful:
|
||||
|
||||
=over 4
|
||||
|
||||
=item C<verilator_flags2>
|
||||
|
||||
A list of flags to be passed to verilator when compiling.
|
||||
|
||||
=item C<fails>
|
||||
|
||||
Set to 1 to indicate that the compilation or execution is intended to fail.
|
||||
|
||||
=back
|
||||
|
||||
For example the following would specify that compilation requires two
|
||||
defines and is expected to fail.
|
||||
|
||||
compile (
|
||||
verilator_flags2 => ["-DSMALL_CLOCK -DGATED_COMMENT"],
|
||||
fails => 1,
|
||||
);
|
||||
|
||||
=head2 Regression Testing for Developers
|
||||
|
||||
Developers will also want to call ./configure with two extra flags:
|
||||
|
||||
=over 4
|
||||
|
||||
|
||||
@@ -137,6 +137,7 @@ private:
|
||||
if (nodep->castPslAssert()) ifp->branchPred(AstBranchPred::BP_UNLIKELY);
|
||||
//
|
||||
AstNode* newp = new AstAlways (nodep->fileline(),
|
||||
VAlwaysKwd::ALWAYS,
|
||||
sentreep,
|
||||
bodysp);
|
||||
// Install it
|
||||
|
||||
+24
@@ -467,6 +467,30 @@ public:
|
||||
|
||||
//######################################################################
|
||||
|
||||
class VAlwaysKwd {
|
||||
public:
|
||||
enum en {
|
||||
ALWAYS,
|
||||
ALWAYS_FF,
|
||||
ALWAYS_LATCH,
|
||||
ALWAYS_COMB
|
||||
};
|
||||
enum en m_e;
|
||||
inline VAlwaysKwd () : m_e(ALWAYS) {}
|
||||
inline VAlwaysKwd (en _e) : m_e(_e) {}
|
||||
explicit inline VAlwaysKwd (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
"always","always_ff","always_latch","always_comb"};
|
||||
return names[m_e]; }
|
||||
};
|
||||
inline bool operator== (VAlwaysKwd lhs, VAlwaysKwd rhs) { return (lhs.m_e == rhs.m_e); }
|
||||
inline bool operator== (VAlwaysKwd lhs, VAlwaysKwd::en rhs) { return (lhs.m_e == rhs); }
|
||||
inline bool operator== (VAlwaysKwd::en lhs, VAlwaysKwd rhs) { return (lhs == rhs.m_e); }
|
||||
|
||||
//######################################################################
|
||||
|
||||
class AstCaseType {
|
||||
public:
|
||||
enum en {
|
||||
|
||||
+19
-2
@@ -103,13 +103,21 @@ bool AstVar::isSigPublic() const {
|
||||
}
|
||||
|
||||
bool AstVar::isScQuad() const {
|
||||
return (isSc() && isQuad() && !isScBv());
|
||||
return (isSc() && isQuad() && !isScBv() && !isScBigUint());
|
||||
}
|
||||
|
||||
bool AstVar::isScBv() const {
|
||||
return ((isSc() && width() >= v3Global.opt.pinsBv()) || m_attrScBv);
|
||||
}
|
||||
|
||||
bool AstVar::isScUint() const {
|
||||
return ((isSc() && v3Global.opt.pinsScUint() && width() >= 2 && width() <= 64) && !isScBv());
|
||||
}
|
||||
|
||||
bool AstVar::isScBigUint() const {
|
||||
return ((isSc() && v3Global.opt.pinsScBigUint() && width() >= 65 && width() <= 512) && !isScBv());
|
||||
}
|
||||
|
||||
void AstVar::combineType(AstVarType type) {
|
||||
// These flags get combined with the existing settings of the flags.
|
||||
// We don't test varType for certain types, instead set flags since
|
||||
@@ -278,7 +286,11 @@ string AstVar::dpiArgType(bool named, bool forReturn) const {
|
||||
}
|
||||
|
||||
string AstVar::scType() const {
|
||||
if (isScBv()) {
|
||||
if (isScBigUint()) {
|
||||
return (string("sc_biguint<")+cvtToStr(widthMin())+"> "); // Keep the space so don't get >>
|
||||
} else if (isScUint()) {
|
||||
return (string("sc_uint<")+cvtToStr(widthMin())+"> "); // Keep the space so don't get >>
|
||||
} else if (isScBv()) {
|
||||
return (string("sc_bv<")+cvtToStr(widthMin())+"> "); // Keep the space so don't get >>
|
||||
} else if (widthMin() == 1) {
|
||||
return "bool";
|
||||
@@ -665,6 +677,11 @@ void AstNode::dump(ostream& str) {
|
||||
if (name()!="") str<<" "<<AstNode::quoteName(name());
|
||||
}
|
||||
|
||||
void AstAlways::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (keyword() != VAlwaysKwd::ALWAYS) str<<" ["<<keyword().ascii()<<"]";
|
||||
}
|
||||
|
||||
void AstArraySel::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
str<<" [start:"<<start()<<"] [length:"<<length()<<"]";
|
||||
|
||||
+9
-3
@@ -979,6 +979,8 @@ public:
|
||||
bool isSc() const { return m_sc; }
|
||||
bool isScQuad() const;
|
||||
bool isScBv() const;
|
||||
bool isScUint() const;
|
||||
bool isScBigUint() const;
|
||||
bool isScSensitive() const { return m_scSensitive; }
|
||||
bool isSigPublic() const;
|
||||
bool isSigModPublic() const { return m_sigModPublic; }
|
||||
@@ -1621,15 +1623,19 @@ public:
|
||||
};
|
||||
|
||||
struct AstAlways : public AstNode {
|
||||
AstAlways(FileLine* fl, AstSenTree* sensesp, AstNode* bodysp)
|
||||
: AstNode(fl) {
|
||||
VAlwaysKwd m_keyword;
|
||||
public:
|
||||
AstAlways(FileLine* fl, VAlwaysKwd keyword, AstSenTree* sensesp, AstNode* bodysp)
|
||||
: AstNode(fl), m_keyword(keyword) {
|
||||
addNOp1p(sensesp); addNOp2p(bodysp);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(Always, ALWAYS)
|
||||
//
|
||||
virtual void dump(ostream& str);
|
||||
AstSenTree* sensesp() const { return op1p()->castSenTree(); } // op1 = Sensitivity list
|
||||
AstNode* bodysp() const { return op2p()->castNode(); } // op2 = Statements to evaluate
|
||||
void addStmtp(AstNode* nodep) { addOp2p(nodep); }
|
||||
VAlwaysKwd keyword() const { return m_keyword; }
|
||||
// Special accessors
|
||||
bool isJustOneBodyStmt() const { return bodysp() && !bodysp()->nextp(); }
|
||||
};
|
||||
@@ -1700,7 +1706,7 @@ struct AstAssignW : public AstNodeAssign {
|
||||
AstAlways* convertToAlways() {
|
||||
AstNode* lhs1p = lhsp()->unlinkFrBack();
|
||||
AstNode* rhs1p = rhsp()->unlinkFrBack();
|
||||
AstAlways* newp = new AstAlways (fileline(), NULL,
|
||||
AstAlways* newp = new AstAlways (fileline(), VAlwaysKwd::ALWAYS, NULL,
|
||||
new AstAssign (fileline(), lhs1p, rhs1p));
|
||||
replaceWith(newp); // User expected to then deleteTree();
|
||||
return newp;
|
||||
|
||||
@@ -684,6 +684,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
||||
AstNode* bodyp = nodep->bodysp()->cloneTree(true);
|
||||
|
||||
AstAlways* alwp = new AstAlways(nodep->fileline(),
|
||||
nodep->keyword(),
|
||||
sensesp,
|
||||
bodyp);
|
||||
|
||||
|
||||
+27
-6
@@ -79,7 +79,10 @@ public:
|
||||
puts (nodep->isWide()?"W":(nodep->isQuad()?"Q":"I"));
|
||||
}
|
||||
void emitScIQW(AstVar* nodep) {
|
||||
puts (nodep->isScBv()?"SW":(nodep->isScQuad()?"SQ":"SI"));
|
||||
puts (nodep->isScBigUint() ? "SB"
|
||||
: nodep->isScUint() ? "SU"
|
||||
: nodep->isScBv() ? "SW"
|
||||
: (nodep->isScQuad() ? "SQ" : "SI"));
|
||||
}
|
||||
void emitOpName(AstNode* nodep, const string& format,
|
||||
AstNode* lhsp, AstNode* rhsp, AstNode* thsp);
|
||||
@@ -1699,7 +1702,7 @@ void EmitCStmts::emitVarList(AstNode* firstp, EisWhich which, const string& pref
|
||||
if (varp->isUsedClock() && varp->widthMin()==1) sortbytes = 0;
|
||||
else if (varp->dtypeSkipRefp()->castUnpackArrayDType()) sortbytes=8;
|
||||
else if (varp->basicp() && varp->basicp()->isOpaque()) sortbytes=7;
|
||||
else if (varp->isScBv()) sortbytes=6;
|
||||
else if (varp->isScBv() || varp->isScBigUint()) sortbytes=6;
|
||||
else if (sigbytes==8) sortbytes=5;
|
||||
else if (sigbytes==4) sortbytes=4;
|
||||
else if (sigbytes==2) sortbytes=2;
|
||||
@@ -2172,6 +2175,21 @@ class EmitCTrace : EmitCStmts {
|
||||
AstVar* varp = varrefp->varp();
|
||||
return varp->isSc() && varp->isScBv();
|
||||
}
|
||||
|
||||
bool emitTraceIsScBigUint(AstTraceInc* nodep) {
|
||||
AstVarRef* varrefp = nodep->valuep()->castVarRef();
|
||||
if (!varrefp) return false;
|
||||
AstVar* varp = varrefp->varp();
|
||||
return varp->isSc() && varp->isScBigUint();
|
||||
}
|
||||
|
||||
bool emitTraceIsScUint(AstTraceInc* nodep) {
|
||||
AstVarRef* varrefp = nodep->valuep()->castVarRef();
|
||||
if (!varrefp) return false;
|
||||
AstVar* varp = varrefp->varp();
|
||||
return varp->isSc() && varp->isScUint();
|
||||
}
|
||||
|
||||
void emitTraceInitOne(AstTraceDecl* nodep) {
|
||||
if (nodep->isDouble()) {
|
||||
puts("vcdp->declDouble");
|
||||
@@ -2207,7 +2225,7 @@ class EmitCTrace : EmitCStmts {
|
||||
? "full":"chg");
|
||||
if (nodep->isDouble()) {
|
||||
puts("vcdp->"+full+"Double");
|
||||
} else if (nodep->isWide() || emitTraceIsScBv(nodep)) {
|
||||
} else if (nodep->isWide() || emitTraceIsScBv(nodep) || emitTraceIsScBigUint(nodep)) {
|
||||
puts("vcdp->"+full+"Array");
|
||||
} else if (nodep->isQuad()) {
|
||||
puts("vcdp->"+full+"Quad ");
|
||||
@@ -2221,7 +2239,7 @@ class EmitCTrace : EmitCStmts {
|
||||
puts(",");
|
||||
emitTraceValue(nodep, arrayindex);
|
||||
if (!nodep->isDouble() // When float/double no longer have widths this can go
|
||||
&& (nodep->declp()->left() || nodep->declp()->right() || emitTraceIsScBv(nodep))) {
|
||||
&& (nodep->declp()->left() || nodep->declp()->right() || emitTraceIsScBv(nodep) || emitTraceIsScBigUint(nodep))) {
|
||||
puts(","+cvtToStr(nodep->declp()->widthMin()));
|
||||
}
|
||||
puts(");\n");
|
||||
@@ -2231,7 +2249,8 @@ class EmitCTrace : EmitCStmts {
|
||||
AstVarRef* varrefp = nodep->valuep()->castVarRef();
|
||||
AstVar* varp = varrefp->varp();
|
||||
puts("(");
|
||||
if (emitTraceIsScBv(nodep)) puts("VL_SC_BV_DATAP(");
|
||||
if (emitTraceIsScBigUint(nodep)) puts("(vluint32_t*)");
|
||||
else if (emitTraceIsScBv(nodep)) puts("VL_SC_BV_DATAP(");
|
||||
varrefp->iterate(*this); // Put var name out
|
||||
// Tracing only supports 1D arrays
|
||||
if (varp->dtypeSkipRefp()->castUnpackArrayDType()) {
|
||||
@@ -2240,7 +2259,9 @@ class EmitCTrace : EmitCStmts {
|
||||
else puts("["+cvtToStr(arrayindex)+"]");
|
||||
}
|
||||
if (varp->isSc()) puts(".read()");
|
||||
if (emitTraceIsScBv(nodep)) puts(")");
|
||||
if (emitTraceIsScUint(nodep)) puts(nodep->isQuad() ? ".to_uint64()" : ".to_uint()");
|
||||
else if (emitTraceIsScBigUint(nodep)) puts(".get_raw()");
|
||||
else if (emitTraceIsScBv(nodep)) puts(")");
|
||||
puts(")");
|
||||
} else {
|
||||
puts("(");
|
||||
|
||||
+1
-1
@@ -102,7 +102,7 @@ class EmitCSyms : EmitCBaseVisitor {
|
||||
if (rsvd != "") {
|
||||
// Generally V3Name should find all of these and throw SYMRSVDWORD.
|
||||
// We'll still check here because the compiler errors resulting if we miss this warning are SO nasty
|
||||
nodep->v3error("Symbol matching "+rsvd+" reserved word reached emitter, should have hit SYMRSVDWORD: '"<<nodep->name()<<"'");
|
||||
nodep->v3error("Symbol matching "+rsvd+" reserved word reached emitter, should have hit SYMRSVDWORD: '"<<nodep->prettyName()<<"'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -57,6 +57,7 @@ public:
|
||||
// Warning codes:
|
||||
EC_FIRST_WARN, // Just a code so the program knows where to start warnings
|
||||
//
|
||||
ALWCOMBORDER, // Always_comb with unordered statements
|
||||
ASSIGNDLY, // Assignment delays
|
||||
ASSIGNIN, // Assigning to input
|
||||
BLKANDNBLK, // Blocked and non-blocking assignments to same variable
|
||||
@@ -116,7 +117,7 @@ public:
|
||||
"BLKLOOPINIT", "DETECTARRAY", "MULTITOP", "TASKNSVAR",
|
||||
// Warnings
|
||||
" EC_FIRST_WARN",
|
||||
"ASSIGNDLY", "ASSIGNIN",
|
||||
"ALWCOMBORDER", "ASSIGNDLY", "ASSIGNIN",
|
||||
"BLKANDNBLK", "BLKSEQ",
|
||||
"CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CDCRSTLOGIC", "CMPCONST",
|
||||
"COMBDLY", "DEFPARAM", "DECLFILENAME",
|
||||
@@ -146,7 +147,8 @@ public:
|
||||
bool mentionManual() const { return ( m_e==EC_FATALSRC || pretendError() ); }
|
||||
|
||||
// Warnings that are lint only
|
||||
bool lintError() const { return ( m_e==CASEINCOMPLETE || m_e==CASEOVERLAP
|
||||
bool lintError() const { return ( m_e==ALWCOMBORDER
|
||||
|| m_e==CASEINCOMPLETE || m_e==CASEOVERLAP
|
||||
|| m_e==CASEWITHX || m_e==CASEX
|
||||
|| m_e==CMPCONST
|
||||
|| m_e==ENDLABEL
|
||||
|
||||
@@ -64,6 +64,7 @@ class GateGraphBaseVisitor {
|
||||
public:
|
||||
virtual AstNUser* visit(GateLogicVertex* vertexp, AstNUser* vup=NULL) =0;
|
||||
virtual AstNUser* visit(GateVarVertex* vertexp, AstNUser* vup=NULL) =0;
|
||||
virtual ~GateGraphBaseVisitor() {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
@@ -48,6 +48,8 @@ public:
|
||||
struct V3HashedUserCheck {
|
||||
// Functor for V3Hashed::findDuplicate
|
||||
virtual bool check(AstNode*,AstNode*) =0;
|
||||
V3HashedUserCheck() {}
|
||||
virtual ~V3HashedUserCheck() {}
|
||||
};
|
||||
|
||||
class V3Hashed : public VHashedBase {
|
||||
|
||||
+5
-4
@@ -75,7 +75,7 @@ public:
|
||||
void LinkCellsGraph::loopsMessageCb(V3GraphVertex* vertexp) {
|
||||
if (LinkCellsVertex* vvertexp = dynamic_cast<LinkCellsVertex*>(vertexp)) {
|
||||
vvertexp->modp()->v3error("Recursive module (module instantiates itself): "
|
||||
<<vvertexp->modp()->name());
|
||||
<<vvertexp->modp()->prettyName());
|
||||
V3Error::abortIfErrors();
|
||||
} else { // Everything should match above, but...
|
||||
v3fatalSrc("Recursive instantiations");
|
||||
@@ -128,8 +128,9 @@ private:
|
||||
// Read-subfile
|
||||
// If file not found, make AstNotFoundModule, rather than error out.
|
||||
// We'll throw the error when we know the module will really be needed.
|
||||
string prettyName = AstNode::prettyName(modName);
|
||||
V3Parse parser (v3Global.rootp(), m_filterp, m_parseSymp);
|
||||
parser.parseFile(nodep->fileline(), modName, false, "");
|
||||
parser.parseFile(nodep->fileline(), prettyName, false, "");
|
||||
V3Error::abortIfErrors();
|
||||
// We've read new modules, grab new pointers to their names
|
||||
readModNames();
|
||||
@@ -137,7 +138,7 @@ private:
|
||||
modp = m_mods.rootp()->findIdFallback(modName)->nodep()->castNodeModule();
|
||||
if (!modp) {
|
||||
// This shouldn't throw a message as parseFile will create a AstNotFoundModule for us
|
||||
nodep->v3error("Can't resolve module reference: "<<modName);
|
||||
nodep->v3error("Can't resolve module reference: "<<prettyName);
|
||||
}
|
||||
}
|
||||
return modp;
|
||||
@@ -189,7 +190,7 @@ private:
|
||||
<<"' does not match "<<nodep->typeName()<<" name: "<<nodep->prettyName());
|
||||
}
|
||||
}
|
||||
bool topMatch = (v3Global.opt.topModule()==nodep->name());
|
||||
bool topMatch = (v3Global.opt.topModule()==nodep->prettyName());
|
||||
if (topMatch) {
|
||||
m_topVertexp = vertex(nodep);
|
||||
UINFO(2,"Link --top-module: "<<nodep<<endl);
|
||||
|
||||
+3
-3
@@ -698,7 +698,7 @@ private:
|
||||
&& (!m_ftaskp || m_ftaskp != foundp->nodep()) // Not the function's variable hiding function
|
||||
&& !nodep->fileline()->warnIsOff(V3ErrorCode::VARHIDDEN)
|
||||
&& !foundp->nodep()->fileline()->warnIsOff(V3ErrorCode::VARHIDDEN)) {
|
||||
nodep->v3warn(VARHIDDEN,"Declaration of signal hides declaration in upper scope: "<<nodep->name()<<endl
|
||||
nodep->v3warn(VARHIDDEN,"Declaration of signal hides declaration in upper scope: "<<nodep->prettyName()<<endl
|
||||
<<foundp->nodep()->warnMore()<<"... Location of original declaration");
|
||||
}
|
||||
ins = true;
|
||||
@@ -744,7 +744,7 @@ private:
|
||||
// User can disable the message at either point
|
||||
if (!nodep->fileline()->warnIsOff(V3ErrorCode::VARHIDDEN)
|
||||
&& !foundp->nodep()->fileline()->warnIsOff(V3ErrorCode::VARHIDDEN)) {
|
||||
nodep->v3warn(VARHIDDEN,"Declaration of enum value hides declaration in upper scope: "<<nodep->name()<<endl
|
||||
nodep->v3warn(VARHIDDEN,"Declaration of enum value hides declaration in upper scope: "<<nodep->prettyName()<<endl
|
||||
<<foundp->nodep()->warnMore()<<"... Location of original declaration");
|
||||
}
|
||||
ins = true;
|
||||
@@ -858,7 +858,7 @@ private:
|
||||
}
|
||||
virtual void visit(AstDefParam* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
nodep->v3warn(DEFPARAM,"Suggest replace defparam with Verilog 2001 #(."<<nodep->name()<<"(...etc...))");
|
||||
nodep->v3warn(DEFPARAM,"Suggest replace defparam with Verilog 2001 #(."<<nodep->prettyName()<<"(...etc...))");
|
||||
VSymEnt* foundp = m_statep->getNodeSym(nodep)->findIdFallback(nodep->path());
|
||||
AstCell* cellp = foundp->nodep()->castCell();
|
||||
if (!cellp) {
|
||||
|
||||
+1
-1
@@ -227,7 +227,7 @@ private:
|
||||
}
|
||||
}
|
||||
//if (debug()>=9) { UINFO(0,"\n"); beginp->dumpTree(cout," labeli: "); }
|
||||
if (!beginp) { nodep->v3error("disable isn't underneath a begin with name: "<<nodep->name()); }
|
||||
if (!beginp) { nodep->v3error("disable isn't underneath a begin with name: "<<nodep->prettyName()); }
|
||||
else {
|
||||
// Jump to the end of the named begin
|
||||
AstJumpLabel* labelp = findAddLabel(beginp, false);
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ private:
|
||||
} else {
|
||||
string rsvd = m_words.isKeyword(nodep->name());
|
||||
if (rsvd != "") {
|
||||
nodep->v3warn(SYMRSVDWORD,"Symbol matches "+rsvd+": '"<<nodep->name()<<"'");
|
||||
nodep->v3warn(SYMRSVDWORD,"Symbol matches "+rsvd+": '"<<nodep->prettyName()<<"'");
|
||||
string newname = (string)"__SYM__"+nodep->name();
|
||||
nodep->name(newname);
|
||||
}
|
||||
|
||||
@@ -737,6 +737,8 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||
else if ( onoff (sw, "-lint-only", flag/*ref*/) ) { m_lintOnly = flag; }
|
||||
else if ( !strcmp (sw, "-no-pins64") ) { m_pinsBv = 33; }
|
||||
else if ( !strcmp (sw, "-pins64") ) { m_pinsBv = 65; }
|
||||
else if ( onoff (sw, "-pins-sc-uint", flag/*ref*/) ){ m_pinsScUint = flag; if (!m_pinsScBigUint) m_pinsBv = 65; }
|
||||
else if ( onoff (sw, "-pins-sc-biguint", flag/*ref*/) ){ m_pinsScBigUint = flag; m_pinsBv = 513; }
|
||||
else if ( onoff (sw, "-pins-uint8", flag/*ref*/) ){ m_pinsUint8 = flag; }
|
||||
else if ( !strcmp (sw, "-private") ) { m_public = false; }
|
||||
else if ( onoff (sw, "-profile-cfuncs", flag/*ref*/) ) { m_profileCFuncs = flag; }
|
||||
|
||||
@@ -76,6 +76,8 @@ class V3Options {
|
||||
bool m_lintOnly; // main switch: --lint-only
|
||||
bool m_outFormatOk; // main switch: --cc, --sc or --sp was specified
|
||||
bool m_warnFatal; // main switch: --warnFatal
|
||||
bool m_pinsScUint; // main switch: --pins-sc-uint
|
||||
bool m_pinsScBigUint;// main switch: --pins-sc-biguint
|
||||
bool m_pinsUint8; // main switch: --pins-uint8
|
||||
bool m_profileCFuncs;// main switch: --profile-cfuncs
|
||||
bool m_psl; // main switch: --psl
|
||||
@@ -215,6 +217,8 @@ class V3Options {
|
||||
bool outFormatOk() const { return m_outFormatOk; }
|
||||
bool keepTempFiles() const { return (V3Error::debugDefault()!=0); }
|
||||
bool warnFatal() const { return m_warnFatal; }
|
||||
bool pinsScUint() const { return m_pinsScUint; }
|
||||
bool pinsScBigUint() const { return m_pinsScBigUint; }
|
||||
bool pinsUint8() const { return m_pinsUint8; }
|
||||
bool profileCFuncs() const { return m_profileCFuncs; }
|
||||
bool psl() const { return m_psl; }
|
||||
|
||||
+37
-12
@@ -375,8 +375,10 @@ private:
|
||||
void processBrokeLoop();
|
||||
#endif
|
||||
void processCircular();
|
||||
typedef deque<OrderEitherVertex*> VertexVec;
|
||||
void processInputs();
|
||||
void processInputsIterate(OrderEitherVertex* vertexp);
|
||||
void processInputsInIterate(OrderEitherVertex* vertexp, VertexVec& todoVec);
|
||||
void processInputsOutIterate(OrderEitherVertex* vertexp, VertexVec& todoVec);
|
||||
void processSensitive();
|
||||
void processDomains();
|
||||
void processDomainsIterate(OrderEitherVertex* vertexp);
|
||||
@@ -1059,28 +1061,33 @@ void OrderVisitor::processBrokeLoop() {
|
||||
// Clock propagation
|
||||
|
||||
void OrderVisitor::processInputs() {
|
||||
m_graph.userClearVertices(); // Vertex::user() // true if processed
|
||||
m_graph.userClearVertices(); // Vertex::user() // 1 if input recursed, 2 if marked as input, 3 if out-edges recursed
|
||||
// Start at input vertex, process from input-to-output order
|
||||
VertexVec todoVec; // List of newly-input marked vectors we need to process
|
||||
todoVec.push_front(m_inputsVxp);
|
||||
m_inputsVxp->isFromInput(true); // By definition
|
||||
processInputsIterate(m_inputsVxp);
|
||||
while (!todoVec.empty()) {
|
||||
OrderEitherVertex* vertexp = todoVec.back(); todoVec.pop_back();
|
||||
processInputsOutIterate(vertexp, todoVec);
|
||||
}
|
||||
}
|
||||
|
||||
void OrderVisitor::processInputsIterate(OrderEitherVertex* vertexp) {
|
||||
void OrderVisitor::processInputsInIterate(OrderEitherVertex* vertexp, VertexVec& todoVec) {
|
||||
// Propagate PrimaryIn through simple assignments
|
||||
if (vertexp->user()) return; // Already processed
|
||||
if (0 && debug()>=9) {
|
||||
UINFO(9," InIt "<<vertexp<<endl);
|
||||
UINFO(9," InIIter "<<vertexp<<endl);
|
||||
if (OrderLogicVertex* vvertexp = dynamic_cast<OrderLogicVertex*>(vertexp)) {
|
||||
vvertexp->nodep()->dumpTree(cout,"- TT: ");
|
||||
}
|
||||
}
|
||||
vertexp->user(true); // Processing
|
||||
vertexp->user(1); // Processing
|
||||
// First handle all inputs to this vertex, in most cases they'll be already processed earlier
|
||||
// Also, determine if this vertex is an input
|
||||
int inonly = 1; // 0=no, 1=maybe, 2=yes until a no
|
||||
for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep=edgep->inNextp()) {
|
||||
OrderEitherVertex* frVertexp = (OrderEitherVertex*)edgep->fromp();
|
||||
processInputsIterate(frVertexp);
|
||||
processInputsInIterate(frVertexp, todoVec);
|
||||
if (frVertexp->isFromInput()) {
|
||||
if (inonly==1) inonly = 2;
|
||||
} else if (dynamic_cast<OrderVarPostVertex*>(frVertexp)) {
|
||||
@@ -1091,20 +1098,38 @@ void OrderVisitor::processInputsIterate(OrderEitherVertex* vertexp) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (inonly == 2) { // Set it. Note may have already been set earlier, too
|
||||
|
||||
if (inonly == 2 && vertexp->user()<2) { // Set it. Note may have already been set earlier, too
|
||||
UINFO(9," Input reassignment: "<<vertexp<<endl);
|
||||
vertexp->isFromInput(true);
|
||||
vertexp->user(2); // 2 means on list
|
||||
// Can't work on out-edges of a node we know is an input immediately,
|
||||
// as it might visit other nodes before their input state is resolved.
|
||||
// So push to list and work on it later when all in-edges known resolved
|
||||
todoVec.push_back(vertexp);
|
||||
}
|
||||
// If we're still an input, process all targets of this vertex
|
||||
if (vertexp->isFromInput()) {
|
||||
//UINFO(9," InIdone "<<vertexp<<endl);
|
||||
}
|
||||
|
||||
void OrderVisitor::processInputsOutIterate(OrderEitherVertex* vertexp, VertexVec& todoVec) {
|
||||
if (vertexp->user()==3) return; // Already out processed
|
||||
//UINFO(9," InOIter "<<vertexp<<endl);
|
||||
// First make sure input path is fully recursed
|
||||
processInputsInIterate(vertexp, todoVec);
|
||||
// Propagate PrimaryIn through simple assignments
|
||||
if (!vertexp->isFromInput()) v3fatalSrc("processInputsOutIterate only for input marked vertexes");
|
||||
vertexp->user(3); // out-edges processed
|
||||
|
||||
{
|
||||
// Propagate PrimaryIn through simple assignments, followint target of vertex
|
||||
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
|
||||
OrderEitherVertex* toVertexp = (OrderEitherVertex*)edgep->top();
|
||||
if (OrderVarStdVertex* vvertexp = dynamic_cast<OrderVarStdVertex*>(toVertexp)) {
|
||||
processInputsIterate(vvertexp);
|
||||
processInputsInIterate(vvertexp, todoVec);
|
||||
}
|
||||
if (OrderLogicVertex* vvertexp = dynamic_cast<OrderLogicVertex*>(toVertexp)) {
|
||||
if (vvertexp->nodep()->castNodeAssign()) {
|
||||
processInputsIterate(vvertexp);
|
||||
processInputsInIterate(vvertexp, todoVec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -416,7 +416,7 @@ private:
|
||||
}
|
||||
if (splitAlwaysp) {
|
||||
++m_statSplits;
|
||||
AstAlways* alwaysp = new AstAlways(newListp->fileline(), NULL, NULL);
|
||||
AstAlways* alwaysp = new AstAlways(newListp->fileline(), VAlwaysKwd::ALWAYS, NULL, NULL);
|
||||
addAfterp->addNextHere(alwaysp); addAfterp=alwaysp;
|
||||
alwaysp->addStmtp(newListp);
|
||||
} else {
|
||||
|
||||
+89
-27
@@ -133,6 +133,17 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
bool isUsedNotDrivenBit (int bit, int width) const {
|
||||
for (int i=0; i<width; i++) {
|
||||
if (bitNumOk(bit+i)
|
||||
&& (m_usedWhole || m_flags[(bit+i)*FLAGS_PER_BIT + FLAG_USED])
|
||||
&& !(m_drivenWhole || m_flags[(bit+i)*FLAGS_PER_BIT + FLAG_DRIVEN])) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool isUsedNotDrivenAny () const {
|
||||
return isUsedNotDrivenBit(0, m_flags.size()/FLAGS_PER_BIT);
|
||||
}
|
||||
bool unusedMatch(AstVar* nodep) {
|
||||
const char* regexpp = v3Global.opt.unusedRegexp().c_str();
|
||||
if (!regexpp || !*regexpp) return false;
|
||||
@@ -213,11 +224,13 @@ private:
|
||||
// NODE STATE
|
||||
// AstVar::user1p -> UndrivenVar* for usage var, 0=not set yet
|
||||
AstUser1InUse m_inuser1;
|
||||
AstUser2InUse m_inuser2;
|
||||
|
||||
// STATE
|
||||
vector<UndrivenVarEntry*> m_entryps; // Nodes to delete when we are finished
|
||||
vector<UndrivenVarEntry*> m_entryps[3]; // Nodes to delete when we are finished
|
||||
bool m_markBoth; // Mark as driven+used
|
||||
AstNodeFTask* m_taskp; // Current task
|
||||
AstAlways* m_alwaysp; // Current always
|
||||
|
||||
// METHODS
|
||||
static int debug() {
|
||||
@@ -226,31 +239,45 @@ private:
|
||||
return level;
|
||||
}
|
||||
|
||||
UndrivenVarEntry* getEntryp(AstVar* nodep) {
|
||||
if (!nodep->user1p()) {
|
||||
UndrivenVarEntry* getEntryp(AstVar* nodep, int which_user) {
|
||||
if (!(which_user==1 ? nodep->user1p() : nodep->user2p())) {
|
||||
UndrivenVarEntry* entryp = new UndrivenVarEntry (nodep);
|
||||
m_entryps.push_back(entryp);
|
||||
nodep->user1p(entryp);
|
||||
//UINFO(9," Associate u="<<which_user<<" "<<(void*)this<<" "<<nodep->name()<<endl);
|
||||
m_entryps[which_user].push_back(entryp);
|
||||
if (which_user==1) nodep->user1p(entryp);
|
||||
else if (which_user==2) nodep->user2p(entryp);
|
||||
else nodep->v3fatalSrc("Bad case");
|
||||
return entryp;
|
||||
} else {
|
||||
UndrivenVarEntry* entryp = (UndrivenVarEntry*)(nodep->user1p());
|
||||
UndrivenVarEntry* entryp = (UndrivenVarEntry*)(which_user==1 ? nodep->user1p() : nodep->user2p());
|
||||
return entryp;
|
||||
}
|
||||
}
|
||||
|
||||
void warnAlwCombOrder(AstVarRef* nodep) {
|
||||
AstVar* varp = nodep->varp();
|
||||
if (!varp->isParam() && !varp->isGenVar() && !varp->isUsedLoopIdx()
|
||||
&& !varp->fileline()->warnIsOff(V3ErrorCode::ALWCOMBORDER)) { // Warn only once per variable
|
||||
nodep->v3warn(ALWCOMBORDER, "Always_comb variable driven after use: "<<nodep->prettyName());
|
||||
varp->fileline()->modifyWarnOff(V3ErrorCode::ALWCOMBORDER, true); // Complain just once for any usage
|
||||
}
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstVar* nodep, AstNUser*) {
|
||||
UndrivenVarEntry* entryp = getEntryp (nodep);
|
||||
if (nodep->isInput()
|
||||
|| nodep->isSigPublic() || nodep->isSigUserRWPublic()
|
||||
|| (m_taskp && (m_taskp->dpiImport() || m_taskp->dpiExport()))) {
|
||||
entryp->drivenWhole();
|
||||
}
|
||||
if (nodep->isOutput()
|
||||
|| nodep->isSigPublic() || nodep->isSigUserRWPublic()
|
||||
|| nodep->isSigUserRdPublic()
|
||||
|| (m_taskp && (m_taskp->dpiImport() || m_taskp->dpiExport()))) {
|
||||
entryp->usedWhole();
|
||||
for (int usr=1; usr<(m_alwaysp?3:2); ++usr) {
|
||||
UndrivenVarEntry* entryp = getEntryp (nodep, usr);
|
||||
if (nodep->isInput()
|
||||
|| nodep->isSigPublic() || nodep->isSigUserRWPublic()
|
||||
|| (m_taskp && (m_taskp->dpiImport() || m_taskp->dpiExport()))) {
|
||||
entryp->drivenWhole();
|
||||
}
|
||||
if (nodep->isOutput()
|
||||
|| nodep->isSigPublic() || nodep->isSigUserRWPublic()
|
||||
|| nodep->isSigUserRdPublic()
|
||||
|| (m_taskp && (m_taskp->dpiImport() || m_taskp->dpiExport()))) {
|
||||
entryp->usedWhole();
|
||||
}
|
||||
}
|
||||
// Discover variables used in bit definitions, etc
|
||||
nodep->iterateChildren(*this);
|
||||
@@ -263,10 +290,19 @@ private:
|
||||
AstVarRef* varrefp = nodep->fromp()->castVarRef();
|
||||
AstConst* constp = nodep->lsbp()->castConst();
|
||||
if (varrefp && constp && !constp->num().isFourState()) {
|
||||
UndrivenVarEntry* entryp = getEntryp (varrefp->varp());
|
||||
int lsb = constp->toUInt();
|
||||
if (m_markBoth || varrefp->lvalue()) entryp->drivenBit(lsb, nodep->width());
|
||||
if (m_markBoth || !varrefp->lvalue()) entryp->usedBit(lsb, nodep->width());
|
||||
for (int usr=1; usr<(m_alwaysp?3:2); ++usr) {
|
||||
UndrivenVarEntry* entryp = getEntryp (varrefp->varp(), usr);
|
||||
int lsb = constp->toUInt();
|
||||
if (m_markBoth || varrefp->lvalue()) {
|
||||
// Don't warn if already driven earlier as "a=0; if(a) a=1;" is fine.
|
||||
if (usr==2 && m_alwaysp && entryp->isUsedNotDrivenBit(lsb, nodep->width())) {
|
||||
UINFO(9," Select. Entryp="<<(void*)entryp<<endl);
|
||||
warnAlwCombOrder(varrefp);
|
||||
}
|
||||
entryp->drivenBit(lsb, nodep->width());
|
||||
}
|
||||
if (m_markBoth || !varrefp->lvalue()) entryp->usedBit(lsb, nodep->width());
|
||||
}
|
||||
} else {
|
||||
// else other varrefs handled as unknown mess in AstVarRef
|
||||
nodep->iterateChildren(*this);
|
||||
@@ -274,10 +310,18 @@ private:
|
||||
}
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
// Any variable
|
||||
UndrivenVarEntry* entryp = getEntryp (nodep->varp());
|
||||
bool fdrv = nodep->lvalue() && nodep->varp()->attrFileDescr(); // FD's are also being read from
|
||||
if (m_markBoth || nodep->lvalue()) entryp->drivenWhole();
|
||||
if (m_markBoth || !nodep->lvalue() || fdrv) entryp->usedWhole();
|
||||
for (int usr=1; usr<(m_alwaysp?3:2); ++usr) {
|
||||
UndrivenVarEntry* entryp = getEntryp (nodep->varp(), usr);
|
||||
bool fdrv = nodep->lvalue() && nodep->varp()->attrFileDescr(); // FD's are also being read from
|
||||
if (m_markBoth || nodep->lvalue()) {
|
||||
if (usr==2 && m_alwaysp && entryp->isUsedNotDrivenAny()) {
|
||||
UINFO(9," Full bus. Entryp="<<(void*)entryp<<endl);
|
||||
warnAlwCombOrder(nodep);
|
||||
}
|
||||
entryp->drivenWhole();
|
||||
}
|
||||
if (m_markBoth || !nodep->lvalue() || fdrv) entryp->usedWhole();
|
||||
}
|
||||
}
|
||||
|
||||
// Don't know what black boxed calls do, assume in+out
|
||||
@@ -288,6 +332,19 @@ private:
|
||||
m_markBoth = prevMark;
|
||||
}
|
||||
|
||||
virtual void visit(AstAlways* nodep, AstNUser*) {
|
||||
AstAlways* prevAlwp = m_alwaysp;
|
||||
{
|
||||
AstNode::user2ClearTree();
|
||||
if (nodep->keyword() == VAlwaysKwd::ALWAYS_COMB) UINFO(9," "<<nodep<<endl);
|
||||
if (nodep->keyword() == VAlwaysKwd::ALWAYS_COMB) m_alwaysp = nodep;
|
||||
else m_alwaysp = NULL;
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->keyword() == VAlwaysKwd::ALWAYS_COMB) UINFO(9," Done "<<nodep<<endl);
|
||||
}
|
||||
m_alwaysp = prevAlwp;
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeFTask* nodep, AstNUser*) {
|
||||
AstNodeFTask* prevTaskp = m_taskp;
|
||||
m_taskp = nodep;
|
||||
@@ -315,12 +372,17 @@ public:
|
||||
UndrivenVisitor(AstNetlist* nodep) {
|
||||
m_markBoth = false;
|
||||
m_taskp = NULL;
|
||||
m_alwaysp = NULL;
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~UndrivenVisitor() {
|
||||
for (vector<UndrivenVarEntry*>::iterator it = m_entryps.begin(); it != m_entryps.end(); ++it) {
|
||||
for (vector<UndrivenVarEntry*>::iterator it = m_entryps[1].begin(); it != m_entryps[1].end(); ++it) {
|
||||
(*it)->reportViolations();
|
||||
delete (*it);
|
||||
}
|
||||
for (int usr=1; usr<3; ++usr) {
|
||||
for (vector<UndrivenVarEntry*>::iterator it = m_entryps[usr].begin(); it != m_entryps[usr].end(); ++it) {
|
||||
delete (*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
+1
-1
@@ -115,7 +115,7 @@ private:
|
||||
m_forVarp = initAssp->lhsp()->castVarRef()->varp();
|
||||
m_forVscp = initAssp->lhsp()->castVarRef()->varScopep();
|
||||
if (nodep->castGenFor() && !m_forVarp->isGenVar()) {
|
||||
nodep->v3error("Non-genvar used in generate for: "<<m_forVarp->name()<<endl);
|
||||
nodep->v3error("Non-genvar used in generate for: "<<m_forVarp->prettyName()<<endl);
|
||||
}
|
||||
if (m_generate) V3Const::constifyParamsEdit(initAssp->rhsp()); // rhsp may change
|
||||
AstConst* constInitp = initAssp->rhsp()->castConst();
|
||||
|
||||
+1
-1
@@ -1135,7 +1135,7 @@ private:
|
||||
} else {
|
||||
AstSel* newp = new AstSel(nodep->fileline(), nodep->fromp()->unlinkFrBack(),
|
||||
memberp->lsb(), memberp->width());
|
||||
newp->dtypep(memberp);
|
||||
newp->dtypep(memberp->skipRefp()); // Must skip over the member to find the union; as the member may disappear later
|
||||
newp->didWidth(true); // Don't replace dtype with basic type
|
||||
UINFO(9," MEMBERSEL -> "<<newp<<endl);
|
||||
nodep->replaceWith(newp);
|
||||
|
||||
+1
-1
@@ -217,7 +217,7 @@ private:
|
||||
fromp,
|
||||
new AstMul(nodep->fileline(),
|
||||
new AstConst(nodep->fileline(),AstConst::Unsized32(),elwidth),
|
||||
newSubLsbOf(rhsp, fromRange)),
|
||||
subp),
|
||||
new AstConst (nodep->fileline(),AstConst::Unsized32(),elwidth));
|
||||
newp->declRange(fromRange);
|
||||
newp->declElWidth(elwidth);
|
||||
|
||||
+3
-3
@@ -403,9 +403,9 @@ word [a-zA-Z0-9_]+
|
||||
"$warning" { FL; return yD_WARNING; }
|
||||
/* SV2005 Keywords */
|
||||
"$unit" { FL; return yD_UNIT; } /* Yes, a keyword, not task */
|
||||
"always_comb" { FL; return yALWAYS; }
|
||||
"always_ff" { FL; return yALWAYS; }
|
||||
"always_latch" { FL; return yALWAYS; }
|
||||
"always_comb" { FL; return yALWAYS_COMB; }
|
||||
"always_ff" { FL; return yALWAYS_FF; }
|
||||
"always_latch" { FL; return yALWAYS_LATCH; }
|
||||
"bind" { FL; return yBIND; }
|
||||
"bit" { FL; return yBIT; }
|
||||
"break" { FL; return yBREAK; }
|
||||
|
||||
+11
-5
@@ -273,6 +273,9 @@ class AstSenTree;
|
||||
// Double underscores "yX__Y" means token X followed by Y,
|
||||
// and "yX__ETC" means X folled by everything but Y(s).
|
||||
%token<fl> yALWAYS "always"
|
||||
%token<fl> yALWAYS_FF "always_ff"
|
||||
%token<fl> yALWAYS_COMB "always_comb"
|
||||
%token<fl> yALWAYS_LATCH "always_latch"
|
||||
%token<fl> yAND "and"
|
||||
%token<fl> yASSERT "assert"
|
||||
%token<fl> yASSIGN "assign"
|
||||
@@ -1549,7 +1552,10 @@ module_common_item<nodep>: // ==IEEE: module_common_item
|
||||
| final_construct { $$ = $1; }
|
||||
// // IEEE: always_construct
|
||||
// // Verilator only - event_control attached to always
|
||||
| yALWAYS event_controlE stmtBlock { $$ = new AstAlways($1,$2,$3); }
|
||||
| yALWAYS event_controlE stmtBlock { $$ = new AstAlways($1,VAlwaysKwd::ALWAYS, $2,$3); }
|
||||
| yALWAYS_FF event_controlE stmtBlock { $$ = new AstAlways($1,VAlwaysKwd::ALWAYS_FF, $2,$3); }
|
||||
| yALWAYS_COMB event_controlE stmtBlock { $$ = new AstAlways($1,VAlwaysKwd::ALWAYS_COMB, $2,$3); }
|
||||
| yALWAYS_LATCH event_controlE stmtBlock { $$ = new AstAlways($1,VAlwaysKwd::ALWAYS_LATCH, $2,$3); }
|
||||
| loop_generate_construct { $$ = $1; }
|
||||
| conditional_generate_construct { $$ = $1; }
|
||||
// // Verilator only
|
||||
@@ -2204,10 +2210,10 @@ foperator_assignment<nodep>: // IEEE: operator_assignment (for first part of exp
|
||||
|
||||
finc_or_dec_expression<nodep>: // ==IEEE: inc_or_dec_expression
|
||||
//UNSUP: Generic scopes in incrementes
|
||||
varRefBase yP_PLUSPLUS { $$ = new AstAssign($2,$1,new AstAdd ($2,$1->cloneTree(true),new AstConst($2,V3Number($2,"'b1")))); }
|
||||
| varRefBase yP_MINUSMINUS { $$ = new AstAssign($2,$1,new AstSub ($2,$1->cloneTree(true),new AstConst($2,V3Number($2,"'b1")))); }
|
||||
| yP_PLUSPLUS varRefBase { $$ = new AstAssign($1,$2,new AstAdd ($1,$2->cloneTree(true),new AstConst($1,V3Number($1,"'b1")))); }
|
||||
| yP_MINUSMINUS varRefBase { $$ = new AstAssign($1,$2,new AstSub ($1,$2->cloneTree(true),new AstConst($1,V3Number($1,"'b1")))); }
|
||||
fexprLvalue yP_PLUSPLUS { $$ = new AstAssign($2,$1,new AstAdd ($2,$1->cloneTree(true),new AstConst($2,V3Number($2,"'b1")))); }
|
||||
| fexprLvalue yP_MINUSMINUS { $$ = new AstAssign($2,$1,new AstSub ($2,$1->cloneTree(true),new AstConst($2,V3Number($2,"'b1")))); }
|
||||
| yP_PLUSPLUS fexprLvalue { $$ = new AstAssign($1,$2,new AstAdd ($1,$2->cloneTree(true),new AstConst($1,V3Number($1,"'b1")))); }
|
||||
| yP_MINUSMINUS fexprLvalue { $$ = new AstAssign($1,$2,new AstSub ($1,$2->cloneTree(true),new AstConst($1,V3Number($1,"'b1")))); }
|
||||
;
|
||||
|
||||
//************************************************
|
||||
|
||||
@@ -1504,6 +1504,7 @@ sub sig_child {}
|
||||
sub kill_tree_all {}
|
||||
sub wait_all {}
|
||||
sub ready {}
|
||||
sub running {}
|
||||
|
||||
#######################################################################
|
||||
1;
|
||||
|
||||
@@ -99,7 +99,7 @@ int dpix_run_tests() {
|
||||
static int didDump = 0;
|
||||
if (didDump++ == 0) {
|
||||
# ifdef TEST_VERBOSE
|
||||
Verilated::scopesDump();
|
||||
Verilated::internalsDump();
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,91 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2013 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
integer cyc=0;
|
||||
reg [63:0] crc;
|
||||
reg [63:0] sum;
|
||||
|
||||
// Take CRC data and apply to testblock inputs
|
||||
wire [3:0] datai = crc[3:0];
|
||||
|
||||
/*AUTOWIRE*/
|
||||
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
||||
logic [3:0] datao; // From test of Test.v
|
||||
// End of automatics
|
||||
|
||||
Test test (/*AUTOINST*/
|
||||
// Outputs
|
||||
.datao (datao[3:0]),
|
||||
// Inputs
|
||||
.clk (clk),
|
||||
.datai (datai[3:0]));
|
||||
|
||||
// Aggregate outputs into a single result vector
|
||||
wire [63:0] result = {60'h0, datao};
|
||||
|
||||
// Test loop
|
||||
always @ (posedge clk) begin
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("[%0t] cyc==%0d crc=%x result=%x\n",$time, cyc, crc, result);
|
||||
`endif
|
||||
cyc <= cyc + 1;
|
||||
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
|
||||
sum <= result ^ {sum[62:0],sum[63]^sum[2]^sum[0]};
|
||||
if (cyc==0) begin
|
||||
// Setup
|
||||
crc <= 64'h5aef0c8d_d70a4497;
|
||||
sum <= 64'h0;
|
||||
end
|
||||
else if (cyc<10) begin
|
||||
sum <= 64'h0;
|
||||
end
|
||||
else if (cyc<90) begin
|
||||
end
|
||||
else if (cyc==99) begin
|
||||
$write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
|
||||
if (crc !== 64'hc77bb9b3784ea091) $stop;
|
||||
// What checksum will we end up with (above print should match)
|
||||
`define EXPECTED_SUM 64'h3db7bc8bfe61f983
|
||||
if (sum !== `EXPECTED_SUM) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module Test
|
||||
(
|
||||
input logic clk,
|
||||
input logic [3:0] datai,
|
||||
output logic [3:0] datao
|
||||
);
|
||||
genvar i;
|
||||
|
||||
parameter SIZE = 4;
|
||||
|
||||
logic [SIZE:1][3:0] delay;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
delay[1][3:0] <= datai;
|
||||
end
|
||||
|
||||
generate
|
||||
for (i = 2; i < (SIZE+1); i++) begin
|
||||
always_ff @(posedge clk) begin
|
||||
delay[i][3:0] <= delay[i-1][3:0];
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
always_comb datao = delay[SIZE][3:0];
|
||||
|
||||
endmodule
|
||||
@@ -18,16 +18,17 @@ module t (/*AUTOARG*/
|
||||
reg ionewire;
|
||||
|
||||
`ifdef never_just_for_verilog_mode
|
||||
wire oonewire; // From sub of t_inst_v2k_sub.v
|
||||
wire oonewire; // From sub of t_inst_v2k__sub.v
|
||||
`endif
|
||||
|
||||
wire [7:0] osizedreg; // From sub of t_inst_v2k_sub.v
|
||||
wire [7:0] osizedreg; // From sub of t_inst_v2k__sub.v
|
||||
wire [1:0] tied;
|
||||
wire [3:0] tied_also;
|
||||
|
||||
hello hsub (.tied_also);
|
||||
|
||||
t_inst_v2k_sub sub
|
||||
// Double underscore tests bug631
|
||||
t_inst_v2k__sub sub
|
||||
(
|
||||
// Outputs
|
||||
.osizedreg (osizedreg[7:0]),
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// without warranty, 2003 by Wilson Snyder.
|
||||
|
||||
// This file is named .vi to test +libext+ flags.
|
||||
module t_inst_v2k_sub
|
||||
module t_inst_v2k__sub
|
||||
(
|
||||
output reg [7:0] osizedreg,
|
||||
output wire oonewire /*verilator public*/,
|
||||
Executable
+22
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
verilator_flags2 => ["--lint-only"],
|
||||
verilator_make_gcc => 0,
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
fails => 1,
|
||||
expect=>
|
||||
'%Warning-ALWCOMBORDER: t/t_lint_always_comb_bad.v:\d+: Always_comb variable driven after use: mid
|
||||
.*%Error: Exiting due to.*',
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,48 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2013 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Outputs
|
||||
mid, o3,
|
||||
// Inputs
|
||||
clk, i3
|
||||
);
|
||||
input clk;
|
||||
output logic mid;
|
||||
input i3;
|
||||
output logic o3;
|
||||
|
||||
wire [15:0] temp1;
|
||||
wire [15:0] temp1_d1r;
|
||||
|
||||
logic setbefore;
|
||||
always_comb begin
|
||||
setbefore = 1'b1;
|
||||
if (setbefore) setbefore = 1'b0; // fine
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
if (mid)
|
||||
temp1 = 'h0;
|
||||
else
|
||||
temp1 = (temp1_d1r - 'h1);
|
||||
mid = (temp1_d1r == 'h0); // BAD
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
o3 = 'h0;
|
||||
case (i3)
|
||||
1'b1: begin
|
||||
o3 = i3;
|
||||
end
|
||||
default: ;
|
||||
endcase
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
temp1_d1r <= temp1;
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -12,6 +12,7 @@ module t (/*AUTOARG*/
|
||||
|
||||
reg [39:0] con1,con2, con3;
|
||||
reg [31:0] w32;
|
||||
reg [31:0] v32 [2];
|
||||
|
||||
// surefire lint_off UDDSCN
|
||||
reg [200:0] conw3, conw4;
|
||||
@@ -105,6 +106,21 @@ module t (/*AUTOARG*/
|
||||
w32 = 12; w32 ^= 15; if (w32 != 3) $stop;
|
||||
w32 = 12; w32 >>= 1; if (w32 != 6) $stop;
|
||||
w32 = 12; w32 <<= 1; if (w32 != 24) $stop;
|
||||
|
||||
// Increments
|
||||
v32[2] = 12; v32[2]++; if (v32[2] != 13) $stop;
|
||||
v32[2] = 12; ++v32[2]; if (v32[2] != 13) $stop;
|
||||
v32[2] = 12; v32[2]--; if (v32[2] != 11) $stop;
|
||||
v32[2] = 12; --v32[2]; if (v32[2] != 11) $stop;
|
||||
v32[2] = 12; v32[2] += 2; if (v32[2] != 14) $stop;
|
||||
v32[2] = 12; v32[2] -= 2; if (v32[2] != 10) $stop;
|
||||
v32[2] = 12; v32[2] *= 2; if (v32[2] != 24) $stop;
|
||||
v32[2] = 12; v32[2] /= 2; if (v32[2] != 6) $stop;
|
||||
v32[2] = 12; v32[2] &= 6; if (v32[2] != 4) $stop;
|
||||
v32[2] = 12; v32[2] |= 15; if (v32[2] != 15) $stop;
|
||||
v32[2] = 12; v32[2] ^= 15; if (v32[2] != 3) $stop;
|
||||
v32[2] = 12; v32[2] >>= 1; if (v32[2] != 6) $stop;
|
||||
v32[2] = 12; v32[2] <<= 1; if (v32[2] != 24) $stop;
|
||||
end
|
||||
if (cyc==2) begin
|
||||
win <= 32'h123123;
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2013 by Ted Campbell.
|
||||
|
||||
#include "Vt_order_multidriven.h"
|
||||
#include "verilated.h"
|
||||
#include "verilated_vcd_c.h"
|
||||
|
||||
Vt_order_multidriven * vcore;
|
||||
VerilatedVcdC * vcd;
|
||||
vluint64_t vtime;
|
||||
|
||||
#define PHASE_90
|
||||
|
||||
static void half_cycle( int clk ) {
|
||||
if ( clk & 1 ) vcore->i_clk_wr = !vcore->i_clk_wr;
|
||||
if ( clk & 2 ) vcore->i_clk_rd = !vcore->i_clk_rd;
|
||||
|
||||
vtime += 10 / 2;
|
||||
|
||||
vcore->eval();
|
||||
vcore->eval();
|
||||
|
||||
vcd->dump( vtime );
|
||||
}
|
||||
|
||||
static void cycle() {
|
||||
#ifdef PHASE_90
|
||||
half_cycle( 1 );
|
||||
half_cycle( 2 );
|
||||
half_cycle( 1 );
|
||||
half_cycle( 2 );
|
||||
#else
|
||||
half_cycle( 3 );
|
||||
half_cycle( 3 );
|
||||
#endif
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
Verilated::traceEverOn( true );
|
||||
|
||||
vcore = new Vt_order_multidriven;
|
||||
vcd = new VerilatedVcdC;
|
||||
|
||||
vcore->trace( vcd, 99 );
|
||||
vcd->open( "obj_dir/t_order_multidriven/sim.vcd" );
|
||||
|
||||
vcore->i_clk_wr = 0;
|
||||
vcore->i_clk_rd = 0;
|
||||
|
||||
for ( int i = 0; i < 256; ++i )
|
||||
cycle( );
|
||||
|
||||
vcd->close( );
|
||||
printf("*-* All Finished *-*\n");
|
||||
}
|
||||
Executable
+23
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
$Self->{vlt} or $Self->skip("Verilator only test");
|
||||
|
||||
compile (
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
v_flags2 => ["--trace --exe $Self->{t_dir}/t_order_multidriven.cpp"],
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,192 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2013 by Ted Campbell.
|
||||
|
||||
//With MULTI_CLK defined shows bug, without it is hidden
|
||||
`define MULTI_CLK
|
||||
|
||||
//bug634
|
||||
|
||||
module t (
|
||||
input i_clk_wr,
|
||||
input i_clk_rd
|
||||
);
|
||||
|
||||
wire wr$wen;
|
||||
wire [7:0] wr$addr;
|
||||
wire [7:0] wr$wdata;
|
||||
wire [7:0] wr$rdata;
|
||||
|
||||
wire rd$wen;
|
||||
wire [7:0] rd$addr;
|
||||
wire [7:0] rd$wdata;
|
||||
wire [7:0] rd$rdata;
|
||||
|
||||
wire clk_wr;
|
||||
wire clk_rd;
|
||||
|
||||
`ifdef MULTI_CLK
|
||||
assign clk_wr = i_clk_wr;
|
||||
assign clk_rd = i_clk_rd;
|
||||
`else
|
||||
assign clk_wr = i_clk_wr;
|
||||
assign clk_rd = i_clk_wr;
|
||||
`endif
|
||||
|
||||
FooWr u_wr (
|
||||
.i_clk ( clk_wr ),
|
||||
|
||||
.o_wen ( wr$wen ),
|
||||
.o_addr ( wr$addr ),
|
||||
.o_wdata ( wr$wdata ),
|
||||
.i_rdata ( wr$rdata )
|
||||
);
|
||||
|
||||
FooRd u_rd (
|
||||
.i_clk ( clk_rd ),
|
||||
|
||||
.o_wen ( rd$wen ),
|
||||
.o_addr ( rd$addr ),
|
||||
.o_wdata ( rd$wdata ),
|
||||
.i_rdata ( rd$rdata )
|
||||
);
|
||||
|
||||
FooMem u_mem (
|
||||
.iv_clk ( {clk_wr, clk_rd } ),
|
||||
.iv_wen ( {wr$wen, rd$wen } ),
|
||||
.iv_addr ( {wr$addr, rd$addr } ),
|
||||
.iv_wdata ( {wr$wdata,rd$wdata} ),
|
||||
.ov_rdata ( {wr$rdata,rd$rdata} )
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
// Memory Writer
|
||||
module FooWr(
|
||||
input i_clk,
|
||||
|
||||
output o_wen,
|
||||
output [7:0] o_addr,
|
||||
output [7:0] o_wdata,
|
||||
input [7:0] i_rdata
|
||||
);
|
||||
|
||||
reg [7:0] cnt = 0;
|
||||
|
||||
// Count [0,200]
|
||||
always @( posedge i_clk )
|
||||
if ( cnt < 8'd50 )
|
||||
cnt <= cnt + 8'd1;
|
||||
|
||||
// Write addr in (10,30) if even
|
||||
assign o_wen = ( cnt > 8'd10 ) && ( cnt < 8'd30 ) && ( cnt[0] == 1'b0 );
|
||||
assign o_addr = cnt;
|
||||
assign o_wdata = cnt;
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
// Memory Reader
|
||||
module FooRd(
|
||||
input i_clk,
|
||||
|
||||
output o_wen,
|
||||
output [7:0] o_addr,
|
||||
output [7:0] o_wdata,
|
||||
input [7:0] i_rdata
|
||||
);
|
||||
|
||||
reg [7:0] cnt = 0;
|
||||
reg [7:0] addr_r;
|
||||
reg en_r;
|
||||
|
||||
// Count [0,200]
|
||||
always @( posedge i_clk )
|
||||
if ( cnt < 8'd200 )
|
||||
cnt <= cnt + 8'd1;
|
||||
|
||||
// Read data
|
||||
assign o_wen = 0;
|
||||
assign o_addr = cnt - 8'd100;
|
||||
|
||||
// Track issued read
|
||||
always @( posedge i_clk )
|
||||
begin
|
||||
addr_r <= o_addr;
|
||||
en_r <= ( cnt > 8'd110 ) && ( cnt < 8'd130 ) && ( cnt[0] == 1'b0 );
|
||||
end
|
||||
|
||||
// Display to console 100 cycles after writer
|
||||
always @( negedge i_clk )
|
||||
if ( en_r ) begin
|
||||
`ifdef TEST_VERBOSE
|
||||
$display( "MEM[%x] == %x", addr_r, i_rdata );
|
||||
`endif
|
||||
if (addr_r != i_rdata) $stop;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
// Multi-port memory abstraction
|
||||
module FooMem(
|
||||
input [2 -1:0] iv_clk,
|
||||
input [2 -1:0] iv_wen,
|
||||
input [2*8-1:0] iv_addr,
|
||||
input [2*8-1:0] iv_wdata,
|
||||
output [2*8-1:0] ov_rdata
|
||||
);
|
||||
|
||||
FooMemImpl u_impl (
|
||||
.a_clk ( iv_clk [0*1+:1] ),
|
||||
.a_wen ( iv_wen [0*1+:1] ),
|
||||
.a_addr ( iv_addr [0*8+:8] ),
|
||||
.a_wdata ( iv_wdata[0*8+:8] ),
|
||||
.a_rdata ( ov_rdata[0*8+:8] ),
|
||||
|
||||
.b_clk ( iv_clk [1*1+:1] ),
|
||||
.b_wen ( iv_wen [1*1+:1] ),
|
||||
.b_addr ( iv_addr [1*8+:8] ),
|
||||
.b_wdata ( iv_wdata[1*8+:8] ),
|
||||
.b_rdata ( ov_rdata[1*8+:8] )
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
// Dual-Port L1 Memory Implementation
|
||||
module FooMemImpl(
|
||||
input a_clk,
|
||||
input a_wen,
|
||||
input [7:0] a_addr,
|
||||
input [7:0] a_wdata,
|
||||
output [7:0] a_rdata,
|
||||
|
||||
input b_clk,
|
||||
input b_wen,
|
||||
input [7:0] b_addr,
|
||||
input [7:0] b_wdata,
|
||||
output [7:0] b_rdata
|
||||
);
|
||||
|
||||
/* verilator lint_off MULTIDRIVEN */
|
||||
reg [7:0] mem[0:255];
|
||||
/* verilator lint_on MULTIDRIVEN */
|
||||
|
||||
always @( posedge a_clk )
|
||||
if ( a_wen )
|
||||
mem[a_addr] <= a_wdata;
|
||||
|
||||
always @( posedge b_clk )
|
||||
if ( b_wen )
|
||||
mem[b_addr] <= b_wdata;
|
||||
|
||||
always @( posedge a_clk )
|
||||
a_rdata <= mem[a_addr];
|
||||
|
||||
always @( posedge b_clk )
|
||||
b_rdata <= mem[b_addr];
|
||||
|
||||
endmodule
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,38 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2012 by Wilson Snyder.
|
||||
|
||||
//bug505
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
a #(1) a1 ();
|
||||
b #(2) b2 ();
|
||||
|
||||
initial begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
||||
module a;
|
||||
parameter ONE /*verilator public*/ = 22;
|
||||
initial if (ONE != 1) $stop;
|
||||
`ifdef VERILATOR
|
||||
initial if ($c32("ONE") != 1) $stop;
|
||||
`endif
|
||||
endmodule
|
||||
|
||||
module b #(
|
||||
parameter TWO /*verilator public*/ = 22
|
||||
);
|
||||
initial if (TWO != 2) $stop;
|
||||
`ifdef VERILATOR
|
||||
initial if ($c32("TWO") != 2) $stop;
|
||||
`endif
|
||||
endmodule
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
v_flags2 => ["--lint-only"],
|
||||
verilator_make_gcc => 0,
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,45 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2013 by Wilson Snyder.
|
||||
|
||||
typedef struct packed {
|
||||
logic [1:0] b1;
|
||||
logic [1:0] b2;
|
||||
logic [1:0] b3;
|
||||
logic [1:0] b4;
|
||||
} t__aa_bbbbbbb_ccccc_dddddd_eee;
|
||||
|
||||
typedef struct packed {
|
||||
logic [31:0] a;
|
||||
union packed {
|
||||
logic [7:0] fbyte;
|
||||
t__aa_bbbbbbb_ccccc_dddddd_eee pairs;
|
||||
} b1;
|
||||
logic [23:0] b2;
|
||||
logic [7:0] c1;
|
||||
logic [23:0] c2;
|
||||
logic [31:0] d;
|
||||
} t__aa_bbbbbbb_ccccc_dddddd;
|
||||
|
||||
typedef struct packed {
|
||||
logic [31:0] a;
|
||||
logic [31:0] b;
|
||||
logic [31:0] c;
|
||||
logic [31:0] d;
|
||||
} t__aa_bbbbbbb_ccccc_eee;
|
||||
|
||||
typedef union packed {
|
||||
t__aa_bbbbbbb_ccccc_dddddd dddddd;
|
||||
t__aa_bbbbbbb_ccccc_eee eee;
|
||||
} t__aa_bbbbbbb_ccccc;
|
||||
|
||||
|
||||
module t (
|
||||
input t__aa_bbbbbbb_ccccc xxxxxxx_yyyyy_zzzz,
|
||||
output logic [15:0] datao_pre
|
||||
);
|
||||
always_comb datao_pre = { xxxxxxx_yyyyy_zzzz.dddddd.b1.fbyte, xxxxxxx_yyyyy_zzzz.dddddd.c1 };
|
||||
|
||||
endmodule
|
||||
|
||||
Executable
+46
@@ -0,0 +1,46 @@
|
||||
#!/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.
|
||||
|
||||
$Self->{vlt} or $Self->skip("Verilator only test");
|
||||
|
||||
top_filename("t/t_var_pinsizes.v");
|
||||
|
||||
compile (
|
||||
verilator_flags2 => ["-sp --pins-sc-biguint --trace --exe $Self->{t_dir}/t_var_pinsizes.cpp"],
|
||||
make_main => 0,
|
||||
);
|
||||
|
||||
if ($Self->{vlt}) {
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<bool> \s+ i1;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<uint32_t> \s+ i8;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<uint32_t> \s+ i16;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<uint32_t> \s+ i32;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<vluint64_t> \s+ i64;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_biguint<65>\s> \s+ i65;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_biguint<128>\s> \s+ i128;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_bv<513>\s> \s+ i513;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_bv<1>\s> \s+ ibv1;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_bv<16>\s> \s+ ibv16;/x);
|
||||
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<bool> \s+ o1;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<uint32_t> \s+ o8;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<uint32_t> \s+ o16;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<uint32_t> \s+ o32;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<vluint64_t> \s+ o64;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_biguint<65>\s> \s+ o65;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_biguint<128>\s> \s+ o128;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_bv<513>\s> \s+ o513;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_bv<1>\s> \s+ obv1;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_bv<16>\s> \s+ obv16;/x);
|
||||
}
|
||||
|
||||
execute();
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
Executable
+46
@@ -0,0 +1,46 @@
|
||||
#!/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.
|
||||
|
||||
$Self->{vlt} or $Self->skip("Verilator only test");
|
||||
|
||||
top_filename("t/t_var_pinsizes.v");
|
||||
|
||||
compile (
|
||||
verilator_flags2 => ["-sp --pins-sc-uint --trace --exe $Self->{t_dir}/t_var_pinsizes.cpp"],
|
||||
make_main => 0,
|
||||
);
|
||||
|
||||
if ($Self->{vlt}) {
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<bool> \s+ i1;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_uint<8>\s> \s+ i8;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_uint<16>\s> \s+ i16;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_uint<32>\s> \s+ i32;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_uint<64>\s> \s+ i64;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_bv<65>\s> \s+ i65;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_bv<128>\s> \s+ i128;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_bv<513>\s> \s+ i513;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_bv<1>\s> \s+ ibv1;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_bv<16>\s> \s+ ibv16;/x);
|
||||
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<bool> \s+ o1;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_uint<8>\s> \s+ o8;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_uint<16>\s> \s+ o16;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_uint<32>\s> \s+ o32;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_uint<64>\s> \s+ o64;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_bv<65>\s> \s+ o65;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_bv<128>\s> \s+ o128;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_bv<513>\s> \s+ o513;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_bv<1>\s> \s+ obv1;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_bv<16>\s> \s+ obv16;/x);
|
||||
}
|
||||
|
||||
execute();
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
Executable
+46
@@ -0,0 +1,46 @@
|
||||
#!/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.
|
||||
|
||||
$Self->{vlt} or $Self->skip("Verilator only test");
|
||||
|
||||
top_filename("t/t_var_pinsizes.v");
|
||||
|
||||
compile (
|
||||
verilator_flags2 => ["-sp --pins-sc-uint --pins-sc-biguint --trace --exe $Self->{t_dir}/t_var_pinsizes.cpp"],
|
||||
make_main => 0,
|
||||
);
|
||||
|
||||
if ($Self->{vlt}) {
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<bool> \s+ i1;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_uint<8>\s> \s+ i8;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_uint<16>\s> \s+ i16;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_uint<32>\s> \s+ i32;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_uint<64>\s> \s+ i64;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_biguint<65>\s> \s+ i65;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_biguint<128>\s> \s+ i128;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_bv<513>\s> \s+ i513;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_bv<1>\s> \s+ ibv1;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_bv<16>\s> \s+ ibv16;/x);
|
||||
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<bool> \s+ o1;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_uint<8>\s> \s+ o8;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_uint<16>\s> \s+ o16;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_uint<32>\s> \s+ o32;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_uint<64>\s> \s+ o64;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_biguint<65>\s> \s+ o65;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_biguint<128>\s> \s+ o128;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_bv<513>\s> \s+ o513;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_bv<1>\s> \s+ obv1;/x);
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_bv<16>\s> \s+ obv16;/x);
|
||||
}
|
||||
|
||||
execute();
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -12,6 +12,12 @@
|
||||
# include "Vt_var_pins_sc64.h"
|
||||
#elif defined(T_VAR_PINS_SCUI)
|
||||
# include "Vt_var_pins_scui.h"
|
||||
#elif defined(T_VAR_PINS_SC_UINT)
|
||||
# include "Vt_var_pins_sc_uint.h"
|
||||
#elif defined(T_VAR_PINS_SC_BIGUINT)
|
||||
# include "Vt_var_pins_sc_biguint.h"
|
||||
#elif defined(T_VAR_PINS_SC_UINT_BIGUINT)
|
||||
# include "Vt_var_pins_sc_uint_biguint.h"
|
||||
#else
|
||||
# error "Unknown test"
|
||||
#endif
|
||||
@@ -30,3 +36,11 @@ int main() {
|
||||
tb->final();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sc_main(int argc, char *argv[]) {
|
||||
tb = new VM_PREFIX("tb");
|
||||
|
||||
VL_PRINTF("*-* All Finished *-*\n");
|
||||
tb->final();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -8,26 +8,30 @@
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Outputs
|
||||
o1, o8, o16, o32, o64, o65, obv1, obv16,
|
||||
o1, o8, o16, o32, o64, o65, o128, o513, obv1, obv16,
|
||||
// Inputs
|
||||
clk, i1, i8, i16, i32, i64, i65, ibv1, ibv16
|
||||
clk, i1, i8, i16, i32, i64, i65, i128, i513, ibv1, ibv16
|
||||
);
|
||||
|
||||
input clk;
|
||||
|
||||
input i1;
|
||||
input [7:0] i8;
|
||||
input [15:0] i16;
|
||||
input [31:0] i32;
|
||||
input [63:0] i64;
|
||||
input [64:0] i65;
|
||||
input i1;
|
||||
input [7:0] i8;
|
||||
input [15:0] i16;
|
||||
input [31:0] i32;
|
||||
input [63:0] i64;
|
||||
input [64:0] i65;
|
||||
input [127:0] i128;
|
||||
input [512:0] i513;
|
||||
|
||||
output o1;
|
||||
output [7:0] o8;
|
||||
output [15:0] o16;
|
||||
output [31:0] o32;
|
||||
output [63:0] o64;
|
||||
output [64:0] o65;
|
||||
output o1;
|
||||
output [7:0] o8;
|
||||
output [15:0] o16;
|
||||
output [31:0] o32;
|
||||
output [63:0] o64;
|
||||
output [64:0] o65;
|
||||
output [127:0] o128;
|
||||
output [512:0] o513;
|
||||
|
||||
input [0:0] ibv1 /*verilator sc_bv*/;
|
||||
input [15:0] ibv16 /*verilator sc_bv*/;
|
||||
@@ -42,6 +46,8 @@ module t (/*AUTOARG*/
|
||||
o32 <= i32;
|
||||
o64 <= i64;
|
||||
o65 <= i65;
|
||||
o128 <= i128;
|
||||
o513 <= i513;
|
||||
obv1 <= ibv1;
|
||||
obv16 <= ibv16;
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user