mirror of
https://github.com/verilator/verilator.git
synced 2026-10-05 17:43:31 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bec3daa79f | ||
|
|
ead01ba0b9 | ||
|
|
8e7267f0e2 | ||
|
|
5dbae27f01 | ||
|
|
ecb938f20e | ||
|
|
f1a2ee3273 | ||
|
|
eb2eb14297 | ||
|
|
da07cc6ed1 | ||
|
|
3ff10b40d6 | ||
|
|
7f515e6033 | ||
|
|
a583592cd4 | ||
|
|
b6f2b5b46a | ||
|
|
895a3264a3 | ||
|
|
8738a51449 | ||
|
|
8ca6901f1f |
@@ -3,6 +3,22 @@ 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.633 2/7/2007
|
||||
|
||||
*** Add --trace-depth option for minimizing VCD file size. [Emerson Suguimoto]
|
||||
|
||||
*** With VL_DEBUG, show wires causing convergance errors. [Mike Shinkarovsky]
|
||||
|
||||
**** Fix isolate_assignments when many signals per always. [Mike Shinkarovsky]
|
||||
|
||||
**** Fix isolate_assignments across task/func temporaries. [Mike Shinkarovsky]
|
||||
|
||||
**** Fix $display's with array select followed by wide AND. [David Hewson]
|
||||
|
||||
* Verilator 3.632 1/17/2007
|
||||
|
||||
*** Add /*verilator isolate_assignments*/ attribute. [Mike Shinkarovsky]
|
||||
|
||||
* Verilator 3.631 1/2/2007
|
||||
|
||||
** Support standard NAME[#] for cells created by arraying or generate for.
|
||||
|
||||
+109
-25
@@ -104,10 +104,11 @@ if ($Opt_Sp) {
|
||||
}
|
||||
if ($Opt_Sp eq 'sp' || $Opt_Trace) {
|
||||
if (!defined $ENV{SYSTEMPERL}) {
|
||||
my $try = "$ENV{W}/hw/utils/perltools/SystemC/src";
|
||||
my $try = "$ENV{W}/hw/utils/perltools/SystemC";
|
||||
$ENV{SYSTEMPERL} = $try if -d $try;
|
||||
}
|
||||
(defined $ENV{SYSTEMPERL}) or die "%Error: verilator: Need \$SYSTEMPERL in environment for --sp or --trace\nProbably System-Perl isn't installed, see http://www.veripool.com/systemperl.html\n";
|
||||
(-d "$ENV{SYSTEMPERL}/src") or die "%Error: verilator: \$SYSTEMPERL environment var doesn't seem to point to System-Perl kit\n";
|
||||
}
|
||||
|
||||
# Determine runtime flags
|
||||
@@ -236,7 +237,7 @@ desired, but other assertions are, use --assert --nopsl.)
|
||||
=item --bin I<filename>
|
||||
|
||||
Rarely needed. Override the default filename for Verilator itself. When a
|
||||
dependancy (.d) file is created, this filename will become a source
|
||||
dependency (.d) file is created, this filename will become a source
|
||||
dependency, such that a change in this binary will have make rebuild the
|
||||
output files.
|
||||
|
||||
@@ -253,7 +254,7 @@ Enables all forms of coverage, alias for --coverage-line, --coverage-user
|
||||
Specifies basic block line coverage analysis code should be inserted.
|
||||
|
||||
Coverage analysis adds statements at each code flow change point, which are
|
||||
the branches of IF and CASE statements, a superset of normal Verilog Line
|
||||
the branches of IF and CASE statements, a super-set of normal Verilog Line
|
||||
Coverage. At each such branch a unique counter is incremented. At the end
|
||||
of a test, the counters along with the filename and line number
|
||||
corresponding to each counter are written into logs/coverage.pl.
|
||||
@@ -449,6 +450,13 @@ Adds waveform tracing code to the model. Having tracing compiled in may
|
||||
result in some small performance losses, even when waveforms are not turned
|
||||
on during model execution.
|
||||
|
||||
=item --trace-depth I<levels>
|
||||
|
||||
Specify the number of levels deep to enable tracing, for example
|
||||
--trace-level 1 to only see the top level's signals. Defaults to the
|
||||
entire model. Using a small number will decrease visibility, but greatly
|
||||
improve runtime and trace file size.
|
||||
|
||||
=item --underline-zero
|
||||
|
||||
Rarely needed. Signals starting with a underline should be initialized to
|
||||
@@ -857,7 +865,7 @@ order of magnitude.
|
||||
|
||||
=head1 CROSS COMPILATION
|
||||
|
||||
Verilator supports cross-compling Verilated code. This is generally used
|
||||
Verilator supports cross-compiling Verilated code. This is generally used
|
||||
to run Verilator on a Linux system and produce C++ code that is then compiled
|
||||
on Windows.
|
||||
|
||||
@@ -1075,6 +1083,41 @@ submodules will be named I<submodule>__DOT__I<subsignal> as C++ does not
|
||||
allow "." in signal names. SystemPerl when tracing such signals will
|
||||
replace the __DOT__ with the period.
|
||||
|
||||
=item /*verilator isolate_assignments*/
|
||||
|
||||
Used after a signal declaration to indicate the assignments to this signal
|
||||
in any blocks should be isolated into new blocks. When there is a large
|
||||
combinatorial block that is resulting in a UNOPTFLAT warning, attaching
|
||||
this to the signal causing a false loop may clear up the problem.
|
||||
|
||||
IE, with the following
|
||||
|
||||
reg splitme /* verilator isolate_assignments*/;
|
||||
always @* begin
|
||||
if (....) begin
|
||||
splitme = ....;
|
||||
other assignments
|
||||
end
|
||||
end
|
||||
|
||||
Verilator will internally split the block that assigns to "splitme" into
|
||||
two blocks:
|
||||
|
||||
It would then internally break it into (sort of):
|
||||
|
||||
// All assignments excluding those to splitme
|
||||
always @* begin
|
||||
if (....) begin
|
||||
other assignments
|
||||
end
|
||||
end
|
||||
// All assignments to splitme
|
||||
always @* begin
|
||||
if (....) begin
|
||||
splitme = ....;
|
||||
end
|
||||
end
|
||||
|
||||
=item /*verilator lint_off I<msg>*/
|
||||
|
||||
Disable the specified warning message for any warnings following the comment.
|
||||
@@ -1091,21 +1134,6 @@ reduce the size of the final executable when a task is used a very large
|
||||
number of times. For this flag to work, the task and tasks below it must
|
||||
be pure; they cannot reference any variables outside the task itself.
|
||||
|
||||
=item /*verilator sc_clock*/
|
||||
|
||||
Used after a input declaration to indicate the signal should be declared in
|
||||
SystemC as a sc_clock instead of a bool.
|
||||
|
||||
=item /*verilator tracing_off*/
|
||||
|
||||
Disable waveform tracing for all future signals that are declared in this
|
||||
module. Often this is placed just after a primitive's module statement, so
|
||||
that the entire module is not traced.
|
||||
|
||||
=item /*verilator tracing_on*/
|
||||
|
||||
Re-enable waveform tracing for all future signals that are declared.
|
||||
|
||||
=item /*verilator public*/ (variable)
|
||||
|
||||
Used after a input, output, register, or wire declaration to indicate the
|
||||
@@ -1140,6 +1168,21 @@ Verilator automatically sets this attribute when the module contains any
|
||||
public signals or `systemc_ directives. Also set for all modules when
|
||||
using the --public switch.
|
||||
|
||||
=item /*verilator sc_clock*/
|
||||
|
||||
Used after a input declaration to indicate the signal should be declared in
|
||||
SystemC as a sc_clock instead of a bool.
|
||||
|
||||
=item /*verilator tracing_off*/
|
||||
|
||||
Disable waveform tracing for all future signals that are declared in this
|
||||
module. Often this is placed just after a primitive's module statement, so
|
||||
that the entire module is not traced.
|
||||
|
||||
=item /*verilator tracing_on*/
|
||||
|
||||
Re-enable waveform tracing for all future signals that are declared.
|
||||
|
||||
=back
|
||||
|
||||
=head1 LANGUAGE LIMITATIONS
|
||||
@@ -1343,6 +1386,26 @@ List of all warnings:
|
||||
|
||||
=over 4
|
||||
|
||||
=item BLKANDNBLK
|
||||
|
||||
Error that a variable comes from a mix of blocked and non-blocking
|
||||
assignments. Generally, this is caused by a register driven by both combo
|
||||
logic and a flop:
|
||||
|
||||
always @ (posedge clk) foo[0] <= ...
|
||||
always @* foo[1] = ...
|
||||
|
||||
Simply use a different register for the flop:
|
||||
|
||||
always @ (posedge clk) foo_flopped[0] <= ...
|
||||
always @* foo[0] = foo_flopped[0];
|
||||
always @* foo[1] = ...
|
||||
|
||||
This is good coding practice anyways.
|
||||
|
||||
It is also possible to disable this error when one of the assignments is
|
||||
inside a public task.
|
||||
|
||||
=item CASEINCOMPLETE
|
||||
|
||||
Warns that inside a case statement there is a stimulus pattern for which
|
||||
@@ -1408,6 +1471,17 @@ Warns that the specified signal comes from multiple always blocks. This is
|
||||
often unsupported by synthesis tools, and is considered bad style. It will
|
||||
also cause longer runtimes due to reduced optimizations.
|
||||
|
||||
=item MULTITOP
|
||||
|
||||
Error that there are multiple top level modules, that is modules not
|
||||
instantiated by any other module. Verilator only supports a single top
|
||||
level, if you need more, create a module that wraps all of the top modules.
|
||||
|
||||
Often this error is because some low level cell is being read in, but is
|
||||
not really needed. The best solution is to insure that each module is in a
|
||||
unique file by the same name. Otherwise, make sure all library files are
|
||||
read in as libraries with -v, instead of automatically with -y.
|
||||
|
||||
=item TASKNSVAR
|
||||
|
||||
Error when a call to a task or function has a output from that task tied to
|
||||
@@ -1495,6 +1569,10 @@ The UNOPTFLAT warning may also be due to clock enables, identified from the
|
||||
reported path going through a clock gating cell. To fix these, use the
|
||||
clock_enable meta comment described above.
|
||||
|
||||
The UNOPTFLAT warning may also occur where outputs from a block of logic
|
||||
are independent, but occur in the same always block. To fix this, use the
|
||||
isolate_assignments meta comment described above.
|
||||
|
||||
=item UNSIGNED
|
||||
|
||||
Warns that you are comparing a unsigned value in a way that implies it is
|
||||
@@ -1557,12 +1635,18 @@ For example:
|
||||
always @ (b) a=b
|
||||
|
||||
will toggle forever and thus the executable will give the didn't converge
|
||||
error to prevent an infinite loop. To debug this, compile the Verilated
|
||||
.cpp files with -DVL_DEBUG, then call Verilated::debug(1) in your main.cpp.
|
||||
This will cause each module to print a message when it's invoked. From
|
||||
that it should be obvious what routine(s) are part of the infinite loop.
|
||||
Then in Gdb, add a break point at the routine entry point and "print *this"
|
||||
on each loop so you can see what variables are changing each invocation.
|
||||
error to prevent an infinite loop.
|
||||
|
||||
To debug this, run Verilator with --profile-cfuncs. Run make on the
|
||||
generated files with "OPT=-DVL_DEBUG". Then call Verilated::debug(1) in
|
||||
your main.cpp.
|
||||
|
||||
This will cause each change in a variable to print a message. Near the
|
||||
bottom you'll see the code and variable that causes the problem. For the
|
||||
program above:
|
||||
|
||||
CHANGE: filename.v:1: b
|
||||
CHANGE: filename.v:2: a
|
||||
|
||||
=back
|
||||
|
||||
|
||||
@@ -84,8 +84,8 @@ endif
|
||||
##### SystemPerl builds
|
||||
|
||||
ifeq ($(VM_SP),1)
|
||||
CPPFLAGS += -I$(SYSTEMPERL) -I$(SYSTEMPERL)/src -DSYSTEMPERL
|
||||
VPATH += $(SYSTEMPERL) $(SYSTEMPERL)/src
|
||||
CPPFLAGS += -I$(SYSTEMPERL)/src -DSYSTEMPERL
|
||||
VPATH += $(SYSTEMPERL)/src
|
||||
|
||||
VK_CLASSES_SP = $(addsuffix .sp, $(VM_CLASSES))
|
||||
|
||||
@@ -104,8 +104,8 @@ endif
|
||||
ifeq ($(VM_PCLI),1)
|
||||
LIBS += -lm -lstdc++
|
||||
ifeq ($(VM_TRACE),1)
|
||||
CPPFLAGS += -I$(SYSTEMPERL) -I$(SYSTEMPERL)/src
|
||||
VPATH += $(SYSTEMPERL) $(SYSTEMPERL)/src
|
||||
CPPFLAGS += -I$(SYSTEMPERL)/src
|
||||
VPATH += $(SYSTEMPERL)/src
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
# define VL_ATTR_UNUSED __attribute__ ((unused))
|
||||
# define VL_LIKELY(x) __builtin_expect(!!(x), 1)
|
||||
# define VL_UNLIKELY(x) __builtin_expect(!!(x), 0)
|
||||
# define VL_PREFETCH_RD(p) __builtin_prefetch((p),0)
|
||||
# define VL_PREFETCH_RW(p) __builtin_prefetch((p),1)
|
||||
#else
|
||||
# define VL_ATTR_PRINTF(fmtArgNum) ///< Function with printf format checking
|
||||
# define VL_ATTR_ALIGNED(alignment) ///< Align structure to specified byte alignment
|
||||
@@ -46,6 +48,8 @@
|
||||
# define VL_ATTR_UNUSED ///< Function that may be never used
|
||||
# define VL_LIKELY(x) (!!(x)) ///< Boolean expression more often true then false
|
||||
# define VL_UNLIKELY(x) (!!(x)) ///< Boolean expression more often false then true
|
||||
# define VL_PREFETCH_RD(p) ///< Prefetch data with read intent
|
||||
# define VL_PREFETCH_RW(p) ///< Prefetch data with read/write intent
|
||||
#endif
|
||||
|
||||
#ifdef VL_THREADED
|
||||
|
||||
@@ -156,6 +156,7 @@ RAW_OBJS = \
|
||||
V3Scope.o \
|
||||
V3Signed.o \
|
||||
V3Split.o \
|
||||
V3SplitAs.o \
|
||||
V3Stats.o \
|
||||
V3StatsReport.o \
|
||||
V3Subst.o \
|
||||
|
||||
@@ -505,6 +505,7 @@ public:
|
||||
AstNode* op3p() const { return m_op3p; }
|
||||
AstNode* op4p() const { return m_op4p; }
|
||||
AstNode* clonep() const { return ((m_cloneCnt==s_cloneCntGbl)?m_clonep:NULL); }
|
||||
AstNode* firstAbovep() const { return ((backp() && backp()->nextp()!=this) ? backp() : NULL); } // Returns NULL when second or later in list
|
||||
bool brokeExists() const;
|
||||
|
||||
// CONSTRUCTORS
|
||||
|
||||
@@ -350,6 +350,7 @@ void AstVar::dump(ostream& str) {
|
||||
if (isUsedClock()) str<<" [C]";
|
||||
if (isSigPublic()) str<<" [P]";
|
||||
if (attrClockEn()) str<<" [aCLKEN]";
|
||||
if (attrIsolateAssign()) str<<" [aISO]";
|
||||
if (attrFileDescr()) str<<" [aFD]";
|
||||
if (isFuncReturn()) str<<" [FUNCRTN]";
|
||||
else if (isFuncLocal()) str<<" [FUNC]";
|
||||
|
||||
+11
-1
@@ -241,6 +241,7 @@ private:
|
||||
bool m_funcLocal:1; // Local variable for a function
|
||||
bool m_funcReturn:1; // Return variable for a function
|
||||
bool m_attrClockEn:1;// User clock enable attribute
|
||||
bool m_attrIsolateAssign:1;// User isolate_assignments attribute
|
||||
bool m_fileDescr:1; // File descriptor
|
||||
bool m_isConst:1; // Table contains constant data
|
||||
bool m_isStatic:1; // Static variable
|
||||
@@ -252,7 +253,8 @@ private:
|
||||
m_sc=false; m_scClocked=false; m_scSensitive=false;
|
||||
m_usedClock=false; m_usedParam=false;
|
||||
m_sigPublic=false; m_funcLocal=false; m_funcReturn=false;
|
||||
m_attrClockEn=false; m_fileDescr=false; m_isConst=false; m_isStatic=false;
|
||||
m_attrClockEn=false; m_attrIsolateAssign=false;
|
||||
m_fileDescr=false; m_isConst=false; m_isStatic=false;
|
||||
m_trace=false;
|
||||
}
|
||||
public:
|
||||
@@ -301,6 +303,7 @@ public:
|
||||
void attrClockEn(bool flag) { m_attrClockEn = flag; }
|
||||
void attrFileDescr(bool flag) { m_fileDescr = flag; }
|
||||
void attrScClocked(bool flag) { m_scClocked = flag; }
|
||||
void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; }
|
||||
void usedClock(bool flag) { m_usedClock = flag; }
|
||||
void usedParam(bool flag) { m_usedParam = flag; }
|
||||
void sigPublic(bool flag) { m_sigPublic = flag; }
|
||||
@@ -348,6 +351,7 @@ public:
|
||||
bool attrClockEn() const { return m_attrClockEn; }
|
||||
bool attrFileDescr() const { return m_fileDescr; }
|
||||
bool attrScClocked() const { return m_scClocked; }
|
||||
bool attrIsolateAssign() const { return m_attrIsolateAssign; }
|
||||
int widthAlignBytes() const; // Structure alignment 1,2,4 or 8 bytes (arrays affect this)
|
||||
int widthTotalBytes() const; // Width in bytes rounding up 1,2,4,8,12,...
|
||||
uint32_t msb() const { if (!rangep()) return 0; return rangep()->msbConst(); }
|
||||
@@ -359,6 +363,7 @@ public:
|
||||
// Note the method below too
|
||||
if (fromp->attrClockEn()) attrClockEn(true);
|
||||
if (fromp->attrFileDescr()) attrFileDescr(true);
|
||||
if (fromp->attrIsolateAssign()) attrIsolateAssign(true);
|
||||
}
|
||||
bool gateMultiInputOptimizable() const {
|
||||
// Ok to gate optimize; must return false if propagateAttrFrom would do anything
|
||||
@@ -809,10 +814,13 @@ struct AstTask : public AstNodeFTask {
|
||||
};
|
||||
|
||||
struct AstFunc : public AstNodeFTask {
|
||||
bool m_attrIsolateAssign:1;// User isolate_assignments attribute
|
||||
public:
|
||||
// A function inside a module
|
||||
AstFunc(FileLine* fl, const string& name, AstNode* stmtp, AstNode* fvarsp)
|
||||
:AstNodeFTask(fl, name, stmtp) {
|
||||
addNOp1p(fvarsp);
|
||||
m_attrIsolateAssign = false;
|
||||
}
|
||||
virtual ~AstFunc() {}
|
||||
virtual AstType type() const { return AstType::FUNC;}
|
||||
@@ -821,6 +829,8 @@ struct AstFunc : public AstNodeFTask {
|
||||
// op1 = Range output variable (functions only)
|
||||
AstNode* fvarp() const { return op1p()->castNode(); }
|
||||
void addFvarp(AstNode* nodep) { addOp1p(nodep); }
|
||||
void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; }
|
||||
bool attrIsolateAssign() const { return m_attrIsolateAssign; }
|
||||
};
|
||||
|
||||
struct AstTaskRef : public AstNodeFTaskRef {
|
||||
|
||||
@@ -687,6 +687,21 @@ class EmitCImp : EmitCStmts {
|
||||
if (gotOne) {
|
||||
puts(");\n");
|
||||
//puts("VL_DEBUG_IF( if (__req) cout<<\"\tCLOCKREQ );");
|
||||
for (vector<AstChangeDet*>::iterator it = m_blkChangeDetVec.begin();
|
||||
it != m_blkChangeDetVec.end(); ++it) {
|
||||
AstChangeDet* nodep = *it;
|
||||
if (nodep->lhsp()) {
|
||||
puts("VL_DEBUG_IF( if(__req && (");
|
||||
bool gotOneIgnore = false;
|
||||
doubleOrDetect(nodep, gotOneIgnore);
|
||||
string varname;
|
||||
if (nodep->lhsp()->castVarRef()) {
|
||||
varname = ": "+nodep->lhsp()->castVarRef()->varp()->prettyName();
|
||||
}
|
||||
puts(")) cout<<\"\tCHANGE: "+nodep->fileline()->ascii()
|
||||
+varname+"\"<<endl; );");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -37,6 +37,7 @@ public:
|
||||
FATAL, // Kill the program
|
||||
ERROR, // General error out, can't suppress
|
||||
// Error codes:
|
||||
MULTITOP, // Error: Multiple top level modules
|
||||
TASKNSVAR, // Error: Task I/O not simple
|
||||
// Warning codes:
|
||||
FIRST_WARN, // Just a code so the program knows where to start warnings
|
||||
@@ -71,7 +72,7 @@ public:
|
||||
const char* names[] = {
|
||||
// Leading spaces indicate it can't be disabled.
|
||||
" SUPPRESS", " FATAL", " ERROR",
|
||||
"TASKNSVAR",
|
||||
"MULTITOP", "TASKNSVAR",
|
||||
" FIRST_WARN",
|
||||
"BLKANDNBLK",
|
||||
"CASEINCOMPLETE", "CASEOVERLAP", "CASEX", "CMPCONST",
|
||||
|
||||
@@ -198,10 +198,18 @@ public:
|
||||
m_substTreep = NULL;
|
||||
m_buffersOnly = buffersOnly;
|
||||
m_lhsVarRef = NULL;
|
||||
// Iterate
|
||||
nodep->accept(*this);
|
||||
// Check results
|
||||
if (!m_substTreep) {
|
||||
clearSimple("No assignment found\n");
|
||||
}
|
||||
for (GateVarRefList::const_iterator it = rhsVarRefs().begin();
|
||||
it != rhsVarRefs().end(); ++it) {
|
||||
if (m_lhsVarRef && m_lhsVarRef->varScopep() == (*it)->varScopep()) {
|
||||
clearSimple("Circular logic\n"); // Oh my, we'll get a UNOPTFLAT much later.
|
||||
}
|
||||
}
|
||||
if (debug()>=9 && !m_isSimple) {
|
||||
nodep->dumpTree(cout,"\tgate!Ok: ");
|
||||
}
|
||||
@@ -224,6 +232,7 @@ private:
|
||||
//Entire netlist:
|
||||
// AstVarScope::userp -> GateVarVertex* for usage var, 0=not set yet
|
||||
// {statement}Node::userp -> GateLogicVertex* for this statement
|
||||
|
||||
// STATE
|
||||
V3Graph m_graph; // Scoreboard of var usages/dependencies
|
||||
GateLogicVertex* m_logicVertexp; // Current statement being tracked, NULL=ignored
|
||||
@@ -458,6 +467,7 @@ void GateVisitor::optimizeSignals(bool allowMultiIn) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Process it
|
||||
if (!doit) {
|
||||
if (allowMultiIn && (debug()>=9)) {
|
||||
UINFO(9, "Not ok simp"<<okVisitor.isSimple()<<" mi"<<multiInputs
|
||||
|
||||
@@ -143,6 +143,13 @@ private:
|
||||
if (!m_curVarsp) nodep->v3fatalSrc("Var not under module??\n");
|
||||
nodep->iterateChildren(*this);
|
||||
if (m_idState==ID_FIND) {
|
||||
// We used modTrace before leveling, and we may now
|
||||
// want to turn it off now that we know the levelizations
|
||||
if (v3Global.opt.traceDepth()
|
||||
&& (m_modp->level()-1) > v3Global.opt.traceDepth()) {
|
||||
m_modp->modTrace(false);
|
||||
nodep->trace(false);
|
||||
}
|
||||
// Find under either a task or the module's vars
|
||||
AstNode* findidp = m_curVarsp->findIdName(nodep->name());
|
||||
AstVar* findvarp = findidp->castVar();
|
||||
@@ -213,6 +220,8 @@ private:
|
||||
nodep->userp(m_curVarsp);
|
||||
}
|
||||
// Convert the func's range to the output variable
|
||||
// This should probably be done in the Parser instead, as then we could
|
||||
// just attact normal signal attributes to it.
|
||||
if (AstFunc* funcp = nodep->castFunc()) {
|
||||
if (!funcp->fvarp()->castVar()) {
|
||||
AstRange* rangep = funcp->fvarp()->castRange();
|
||||
@@ -221,6 +230,7 @@ private:
|
||||
newvarp->isSigned(funcp->isSigned());
|
||||
newvarp->funcReturn(true);
|
||||
newvarp->trace(false); // Not user visible
|
||||
newvarp->attrIsolateAssign(funcp->attrIsolateAssign());
|
||||
funcp->addFvarp(newvarp);
|
||||
// Explicit insert required, as the var name shadows the upper level's task name
|
||||
m_curVarsp->insert(newvarp->name(), newvarp);
|
||||
|
||||
+2
-2
@@ -92,8 +92,8 @@ void V3LinkLevel::modSortByLevel() {
|
||||
AstModule* topp = NULL;
|
||||
for (AstModule* nodep = v3Global.rootp()->modulesp(); nodep; nodep=nodep->nextp()->castModule()) {
|
||||
if (nodep->level()<=2) {
|
||||
if (topp) nodep->v3error("Unsupported: Multiple top level modules: "
|
||||
<<nodep->prettyName()<<" and "<<topp->prettyName());
|
||||
if (topp) nodep->v3warn(MULTITOP, "Unsupported: Multiple top level modules: "
|
||||
<<nodep->prettyName()<<" and "<<topp->prettyName());
|
||||
topp = nodep;
|
||||
}
|
||||
vec.push_back(nodep);
|
||||
|
||||
@@ -353,6 +353,10 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
|
||||
shift;
|
||||
m_outputSplitCFuncs = atoi(argv[i]);
|
||||
}
|
||||
else if ( !strcmp (sw, "-trace-depth") ) {
|
||||
shift;
|
||||
m_traceDepth = atoi(argv[i]);
|
||||
}
|
||||
else if ( !strcmp (sw, "-unroll-count") ) { // Undocumented optimization tweak
|
||||
shift;
|
||||
m_unrollCount = atoi(argv[i]);
|
||||
@@ -587,6 +591,7 @@ V3Options::V3Options() {
|
||||
m_inlineMult = 2000;
|
||||
m_outputSplit = 0;
|
||||
m_outputSplitCFuncs = 0;
|
||||
m_traceDepth = 0;
|
||||
m_unrollCount = 64;
|
||||
m_unrollStmts = 20;
|
||||
|
||||
|
||||
@@ -72,6 +72,7 @@ class V3Options {
|
||||
int m_inlineMult; // main switch: --inline-mult
|
||||
int m_outputSplit; // main switch: --output-split
|
||||
int m_outputSplitCFuncs;// main switch: --output-split-cfuncs
|
||||
int m_traceDepth; // main switch: --trace-depth
|
||||
int m_unrollCount; // main switch: --unroll-count
|
||||
int m_unrollStmts; // main switch: --unroll-stmts
|
||||
|
||||
@@ -155,6 +156,7 @@ class V3Options {
|
||||
int inlineMult() const { return m_inlineMult; }
|
||||
int outputSplit() const { return m_outputSplit; }
|
||||
int outputSplitCFuncs() const { return m_outputSplitCFuncs; }
|
||||
int traceDepth() const { return m_traceDepth; }
|
||||
int unrollCount() const { return m_unrollCount; }
|
||||
int unrollStmts() const { return m_unrollStmts; }
|
||||
|
||||
|
||||
@@ -382,6 +382,14 @@ private:
|
||||
//nodep->v3warn(GENCLK,"Signal unoptimizable: Generated clock: "<<nodep->prettyName());
|
||||
} else if (nodep->varp()->isSigPublic()) {
|
||||
nodep->v3warn(UNOPT,"Signal unoptimizable: Feedback to public clock or circular logic: "<<nodep->prettyName());
|
||||
if (!nodep->fileline()->warnIsOff(V3ErrorCode::UNOPT)) {
|
||||
nodep->fileline()->warnOff(V3ErrorCode::UNOPT, true); // Complain just once
|
||||
// Give the user an example.
|
||||
bool tempWeight = (edgep && edgep->weight()==0);
|
||||
if (tempWeight) edgep->weight(1); // Else the below loop detect can't see the loop
|
||||
m_graph.reportLoops(&OrderEdge::followComboConnected, vertexp); // calls OrderGraph::loopsVertexCb
|
||||
if (tempWeight) edgep->weight(0);
|
||||
}
|
||||
} else {
|
||||
// We don't use UNOPT, as there are lots of V2 places where it was needed, that aren't any more
|
||||
// First v3warn not inside warnIsOff so we can see the suppressions with --debug
|
||||
|
||||
+8
-3
@@ -71,14 +71,18 @@ private:
|
||||
// ASSIGN(CONST*here*, VARREF(!sc))
|
||||
// ARRAYSEL(*here*, ...) (No wides can be in any argument but first, so we don't check which arg is wide)
|
||||
// ASSIGN(x, SEL*HERE*(ARRAYSEL()...) (m_assignLhs==true handles this.)
|
||||
//UINFO(9, " Check: "<<nodep<<endl);
|
||||
//UINFO(9, " Detail stmtp="<<(m_stmtp?"Y":"N")<<" U="<<(nodep->user()?"Y":"N")<<" IW "<<(nodep->isWide()?"Y":"N")<<endl);
|
||||
if (m_stmtp
|
||||
&& !nodep->user()) { // Not already done
|
||||
if (nodep->isWide()) { // Else might be cell interconnect or something
|
||||
if (m_assignLhs) {
|
||||
} else if (nodep->backp()->castNodeAssign()
|
||||
&& assignNoTemp(nodep->backp()->castNodeAssign())) {
|
||||
} else if (nodep->firstAbovep()
|
||||
&& nodep->firstAbovep()->castNodeAssign()
|
||||
&& assignNoTemp(nodep->firstAbovep()->castNodeAssign())) {
|
||||
// Not much point if it's just a direct assignment to a constant
|
||||
} else if (nodep->backp()->castArraySel()) { // ArraySel's are pointer refs, ignore
|
||||
} else if (nodep->firstAbovep()
|
||||
&& nodep->firstAbovep()->castArraySel()) { // ArraySel's are pointer refs, ignore
|
||||
} else {
|
||||
UINFO(4,"Cre Temp: "<<nodep<<endl);
|
||||
createDeepTemp(nodep);
|
||||
@@ -140,6 +144,7 @@ private:
|
||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
||||
m_funcp = nodep;
|
||||
nodep->iterateChildren(*this);
|
||||
m_funcp = NULL;
|
||||
}
|
||||
void startStatement(AstNode* nodep) {
|
||||
m_assignLhs = false;
|
||||
|
||||
+1
-1
@@ -428,7 +428,7 @@ private:
|
||||
AstNode* firstp = nodep; // We may reorder, and nodep is no longer first.
|
||||
void* oldBlockUser3 = nodep->user3p(); // May be overloaded in below loop, save it
|
||||
nodep->user3p(NULL);
|
||||
if (nodep->backp()->nextp()==nodep) nodep->v3fatalSrc("Node passed is in next list; should have processed all list at oncen");
|
||||
if (!nodep->firstAbovep()) nodep->v3fatalSrc("Node passed is in next list; should have processed all list at once");
|
||||
// Process it
|
||||
if (!nodep->nextp()) {
|
||||
// Just one, so can't reorder. Just look for more blocks/statements.
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
// $Id$
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Break always into separate statements to reduce temps
|
||||
//
|
||||
// Code available from: http://www.veripool.com/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2007 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// General Public License or the Perl Artistic License.
|
||||
//
|
||||
// Verilator is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//*************************************************************************
|
||||
// V3SplitAs's Transformations:
|
||||
//
|
||||
// Search each ALWAYS for a VARREF lvalue with a /*isolate_assignments*/ attribute
|
||||
// If found, color statements with both, assignment to that varref, or other assignments.
|
||||
// Replicate the Always, and remove mis-colored duplicate code.
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "V3Global.h"
|
||||
#include "V3SplitAs.h"
|
||||
#include "V3Stats.h"
|
||||
#include "V3Ast.h"
|
||||
|
||||
//######################################################################
|
||||
|
||||
class SplitAsBaseVisitor : public AstNVisitor {
|
||||
public:
|
||||
// METHODS
|
||||
//int debug() { return 9; }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// Find all split variables in a block
|
||||
|
||||
class SplitAsFindVisitor : public SplitAsBaseVisitor {
|
||||
private:
|
||||
// STATE
|
||||
AstVarScope* m_splitVscp; // Variable we want to split
|
||||
|
||||
// METHODS
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
if (nodep->lvalue() && !m_splitVscp
|
||||
&& nodep->varp()->attrIsolateAssign()) {
|
||||
m_splitVscp = nodep->varScopep();
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
SplitAsFindVisitor(AstAlways* nodep) {
|
||||
m_splitVscp = NULL;
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~SplitAsFindVisitor() {}
|
||||
// METHODS
|
||||
AstVarScope* splitVscp() const { return m_splitVscp; }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// Remove nodes not containing proper references
|
||||
|
||||
class SplitAsCleanVisitor : public SplitAsBaseVisitor {
|
||||
private:
|
||||
// STATE
|
||||
AstVarScope* m_splitVscp; // Variable we want to split
|
||||
bool m_modeMatch; // Remove matching Vscp, else non-matching
|
||||
bool m_keepStmt; // Current Statement must be preserved
|
||||
bool m_matches; // Statement below has matching lvalue reference
|
||||
|
||||
// METHODS
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
if (nodep->lvalue()) {
|
||||
if (nodep->varScopep()==m_splitVscp) {
|
||||
UINFO(6," CL VAR "<<nodep<<endl);
|
||||
m_matches = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeStmt* nodep, AstNUser*) {
|
||||
UINFO(6," CL STMT "<<nodep<<endl);
|
||||
bool oldKeep = m_keepStmt;
|
||||
{
|
||||
m_matches = false;
|
||||
m_keepStmt = false;
|
||||
|
||||
nodep->iterateChildren(*this);
|
||||
|
||||
if (m_keepStmt
|
||||
|| (m_modeMatch ? m_matches : !m_matches)) {
|
||||
UINFO(6," Keep STMT "<<nodep<<endl);
|
||||
m_keepStmt = true;
|
||||
} else {
|
||||
UINFO(6," Delete STMT "<<nodep<<endl);
|
||||
nodep->unlinkFrBack(); pushDeletep(nodep);
|
||||
}
|
||||
}
|
||||
// If something below matches, the upper statement remains too.
|
||||
m_keepStmt = oldKeep || m_keepStmt;
|
||||
UINFO(9," upKeep="<<m_keepStmt<<" STMT "<<nodep<<endl);
|
||||
}
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
SplitAsCleanVisitor(AstAlways* nodep, AstVarScope* vscp, bool modeMatch) {
|
||||
m_splitVscp = vscp;
|
||||
m_modeMatch = modeMatch;
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~SplitAsCleanVisitor() {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// SplitAs class functions
|
||||
|
||||
class SplitAsVisitor : public SplitAsBaseVisitor {
|
||||
private:
|
||||
// NODE STATE
|
||||
// AstAlways::user() -> bool. True if already processed
|
||||
|
||||
// STATE
|
||||
V3Double0 m_statSplits; // Statistic tracking
|
||||
AstVarScope* m_splitVscp; // Variable we want to split
|
||||
|
||||
// METHODS
|
||||
void splitAlways(AstAlways* nodep) {
|
||||
UINFO(3,"Split "<<nodep<<endl);
|
||||
UINFO(3," For "<<m_splitVscp<<endl);
|
||||
if (debug()>=9) nodep->dumpTree(cout,"-in : ");
|
||||
// Duplicate it and link in
|
||||
AstAlways* newp = nodep->cloneTree(false)->castAlways();
|
||||
newp->user(true); // So we don't clone it again
|
||||
nodep->addNextHere(newp);
|
||||
{ // Delete stuff we don't want in old
|
||||
SplitAsCleanVisitor visitor (nodep, m_splitVscp, false);
|
||||
if (debug()>=9) nodep->dumpTree(cout,"-out0: ");
|
||||
}
|
||||
{ // Delete stuff we don't want in new
|
||||
SplitAsCleanVisitor visitor (newp, m_splitVscp, true);
|
||||
if (debug()>=9) newp->dumpTree(cout,"-out1: ");
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstAlways* nodep, AstNUser*) {
|
||||
// Are there any lvalue references below this?
|
||||
// There could be more then one. So, we process the first one found first.
|
||||
AstVarScope* lastSplitVscp = NULL;
|
||||
while (!nodep->user()) {
|
||||
// Find any splittable variables
|
||||
SplitAsFindVisitor visitor (nodep);
|
||||
m_splitVscp = visitor.splitVscp();
|
||||
if (m_splitVscp && m_splitVscp == lastSplitVscp) {
|
||||
// We did this last time! Something's stuck!
|
||||
nodep->v3fatalSrc("Infinite loop in isolate_assignments removal for: "<<m_splitVscp->prettyName())
|
||||
m_splitVscp = NULL;
|
||||
}
|
||||
lastSplitVscp = m_splitVscp;
|
||||
// Now isolate the always
|
||||
if (m_splitVscp) {
|
||||
splitAlways(nodep);
|
||||
m_statSplits++;
|
||||
} else {
|
||||
nodep->user(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Speedup; no always under math
|
||||
virtual void visit(AstNodeMath* nodep, AstNUser*) {}
|
||||
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
SplitAsVisitor(AstNetlist* nodep) {
|
||||
m_splitVscp = NULL;
|
||||
AstNode::userClearTree(); // userp() used on entire tree
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~SplitAsVisitor() {
|
||||
V3Stats::addStat("Optimizations, isolate_assignments blocks", m_statSplits);
|
||||
}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// SplitAs class functions
|
||||
|
||||
void V3SplitAs::splitAsAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
SplitAsVisitor visitor (nodep);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// $Id$ //-*- C++ -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Break always into separate statements to reduce temps
|
||||
//
|
||||
// Code available from: http://www.veripool.com/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2007 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// General Public License or the Perl Artistic License.
|
||||
//
|
||||
// Verilator is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#ifndef _V3SPLITAS_H_
|
||||
#define _V3SPLITAS_H_ 1
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include "V3Error.h"
|
||||
#include "V3Ast.h"
|
||||
|
||||
//============================================================================
|
||||
|
||||
class V3SplitAs {
|
||||
public:
|
||||
static void splitAsAll(AstNetlist* nodep);
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
+2
-3
@@ -63,9 +63,8 @@ private:
|
||||
m_instrs += nodep->instrCount();
|
||||
if (m_counting) {
|
||||
++m_statTypeCount[nodep->type()];
|
||||
if (nodep->backp() && nodep->backp()->nextp()!=nodep) {
|
||||
// Grab only those above, not those "back"
|
||||
++m_statAbove[nodep->backp()->type()][nodep->type()];
|
||||
if (nodep->firstAbovep()) { // Grab only those above, not those "back"
|
||||
++m_statAbove[nodep->firstAbovep()->type()][nodep->type()];
|
||||
}
|
||||
m_statInstr += nodep->instrCount();
|
||||
if (m_cfuncp && !m_cfuncp->slow()) m_statInstrFast += nodep->instrCount();
|
||||
|
||||
+2
-1
@@ -306,6 +306,7 @@ private:
|
||||
AstVar* newvarp = new AstVar (invarp->fileline(), AstVarType::BLOCKTEMP,
|
||||
name, invarp);
|
||||
newvarp->funcLocal(false);
|
||||
newvarp->propagateAttrFrom(invarp);
|
||||
m_modp->addStmtp(newvarp);
|
||||
AstVarScope* newvscp = new AstVarScope (newvarp->fileline(), m_scopep, newvarp);
|
||||
m_scopep->addVarp(newvscp);
|
||||
@@ -628,7 +629,7 @@ private:
|
||||
if (!funcp) nodep->v3fatalSrc("unlinked");
|
||||
// Inline func refs in the function
|
||||
iterateIntoFTask(funcp);
|
||||
// Create output variabls
|
||||
// Create output variable
|
||||
string namePrefix = "__Vfunc_"+funcp->shortName()+"__"+cvtToStr(m_modNCalls++);
|
||||
AstVarScope* outvscp = createVarScope (funcp->fvarp()->castVar(),
|
||||
namePrefix+"__out");
|
||||
|
||||
+4
-1
@@ -71,6 +71,7 @@
|
||||
#include "V3Scope.h"
|
||||
#include "V3Signed.h"
|
||||
#include "V3Split.h"
|
||||
#include "V3SplitAs.h"
|
||||
#include "V3Stats.h"
|
||||
#include "V3Subst.h"
|
||||
#include "V3Table.h"
|
||||
@@ -284,8 +285,10 @@ void process () {
|
||||
// Split single ALWAYS blocks into multiple blocks for better ordering chances
|
||||
if (v3Global.opt.oSplit()) {
|
||||
V3Split::splitAlwaysAll(v3Global.rootp());
|
||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("split.tree"));
|
||||
//v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("split.tree"));
|
||||
}
|
||||
V3SplitAs::splitAsAll(v3Global.rootp());
|
||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("splitas.tree"));
|
||||
|
||||
// Create tracing sample points, before we start eliminating signals
|
||||
if (v3Global.opt.trace()) {
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
//**********************************************************************
|
||||
//**** Version and host name
|
||||
|
||||
#define DTVERSION "Verilator 3.631 1/2/2007"
|
||||
#define DTVERSION "Verilator 3.633 2/7/2007"
|
||||
|
||||
//**********************************************************************
|
||||
//**** Functions
|
||||
|
||||
@@ -450,6 +450,7 @@ escid \\[^ \t\f\r\n]+
|
||||
<VLG,PSL>"/*verilator public*/" {yylval.fileline = CRELINE(); return yVL_PUBLIC;}
|
||||
<VLG,PSL>"/*verilator public_module*/" {yylval.fileline = CRELINE(); return yVL_PUBLIC_MODULE;}
|
||||
<VLG,PSL>"/*verilator sc_clock*/" {yylval.fileline = CRELINE(); return yVL_CLOCK;}
|
||||
<VLG,PSL>"/*verilator isolate_assignments*/" {yylval.fileline = CRELINE(); return yVL_ISOLATE_ASSIGNMENTS;}
|
||||
<VLG,PSL>"/*verilator systemc_clock*/" {yylval.fileline = CRELINE(); return yVL_CLOCK;}
|
||||
<VLG,PSL>"/*verilator tracing_off*/" {yylval.fileline = CRELINE(); return yVL_TRACING_OFF;}
|
||||
<VLG,PSL>"/*verilator tracing_on*/" {yylval.fileline = CRELINE(); return yVL_TRACING_ON;}
|
||||
|
||||
+13
-3
@@ -104,6 +104,7 @@ class AstSenTree;
|
||||
AstCase* casep;
|
||||
AstCaseItem* caseitemp;
|
||||
AstConst* constp;
|
||||
AstFunc* funcp;
|
||||
AstFuncRef* funcrefp;
|
||||
AstModule* modulep;
|
||||
AstPin* pinp;
|
||||
@@ -169,6 +170,7 @@ class AstSenTree;
|
||||
%token<fileline> yVL_PARALLEL_CASE "/*verilator parallel_case*/"
|
||||
%token<fileline> yVL_PUBLIC "/*verilator public*/"
|
||||
%token<fileline> yVL_PUBLIC_MODULE "/*verilator public_module*/"
|
||||
%token<fileline> yVL_ISOLATE_ASSIGNMENTS "/*verilator isolate_assignments*/"
|
||||
%token<fileline> yVL_TRACING_OFF "/*verilator tracing_off*/"
|
||||
%token<fileline> yVL_TRACING_ON "/*verilator tracing_on*/"
|
||||
|
||||
@@ -245,7 +247,9 @@ class AstSenTree;
|
||||
%type<nodep> idDotted
|
||||
%type<nodep> strAsInt strAsText concIdList
|
||||
%type<nodep> taskDecl
|
||||
%type<nodep> varDeclList funcDecl funcVarList funcVar
|
||||
%type<nodep> varDeclList
|
||||
%type<funcp> funcDecl
|
||||
%type<nodep> funcBody funcVarList funcVar
|
||||
%type<rangep> funcRange
|
||||
%type<nodep> gateDecl
|
||||
%type<nodep> gateBufList gateNotList gateAndList gateNandList
|
||||
@@ -519,6 +523,7 @@ sigAttrList: sigAttr {}
|
||||
sigAttr: yVL_CLOCK { V3Parse::s_varAttrp->attrScClocked(true); }
|
||||
| yVL_CLOCK_ENABLE { V3Parse::s_varAttrp->attrClockEn(true); }
|
||||
| yVL_PUBLIC { V3Parse::s_varAttrp->sigPublic(true); }
|
||||
| yVL_ISOLATE_ASSIGNMENTS { V3Parse::s_varAttrp->attrIsolateAssign(true); }
|
||||
;
|
||||
|
||||
sigList: onesig { $$ = $1; }
|
||||
@@ -711,8 +716,13 @@ taskDecl: yTASK yID ';' stmtBlock yENDTASK { $$ = new AstTask ($1,*
|
||||
| yTASK yID ';' funcVarList stmtBlock yENDTASK { $$ = new AstTask ($1,*$2,$4); $4->addNextNull($5); }
|
||||
;
|
||||
|
||||
funcDecl: yFUNCTION funcRange yID ';' funcVarList stmtBlock yENDFUNCTION { $$ = new AstFunc ($1,*$3,$5,$2); $5->addNextNull($6);}
|
||||
| yFUNCTION ySIGNED funcRange yID ';' funcVarList stmtBlock yENDFUNCTION { $$ = new AstFunc ($1,*$4,$6,$3); $6->addNextNull($7); $$->isSigned(true); }
|
||||
funcDecl: yFUNCTION funcRange yID ';' funcBody yENDFUNCTION { $$ = new AstFunc ($1,*$3,$5,$2); }
|
||||
| yFUNCTION ySIGNED funcRange yID ';' funcBody yENDFUNCTION { $$ = new AstFunc ($1,*$4,$6,$3); $$->isSigned(true); }
|
||||
| yFUNCTION funcRange yID yVL_ISOLATE_ASSIGNMENTS ';' funcBody yENDFUNCTION { $$ = new AstFunc ($1,*$3,$6,$2); $$->attrIsolateAssign(true);}
|
||||
| yFUNCTION ySIGNED funcRange yID yVL_ISOLATE_ASSIGNMENTS ';' funcBody yENDFUNCTION { $$ = new AstFunc ($1,*$4,$7,$3); $$->attrIsolateAssign(true); $$->isSigned(true); }
|
||||
;
|
||||
|
||||
funcBody: funcVarList stmtBlock { $$ = $1;$1->addNextNull($2); }
|
||||
;
|
||||
|
||||
funcRange: '[' constExpr ':' constExpr ']' { $$ = new AstRange($1,$2,$4); }
|
||||
|
||||
@@ -190,20 +190,23 @@ sub new {
|
||||
make_main => 1, # Make __main.cpp
|
||||
# All compilers
|
||||
v_flags => [split(/\s+/,(" -f input.vc --debug-check"
|
||||
.($opt_verbose ? " +define+TEST_VERBOSE+1":"")
|
||||
.($opt_verbose ? " +define+TEST_VERBOSE=1":"")
|
||||
))],
|
||||
v_flags2 => [], # Overridden in some sim files
|
||||
v_other_filenames => [], # After the filename so we can spec multiple files
|
||||
# VCS
|
||||
vcs => 0,
|
||||
vcs_flags => [split(/\s+/,"+cli -I +define+vcs+1 -q +v2k")],
|
||||
vcs_flags2 => [], # Overridden in some sim files
|
||||
# NC
|
||||
nc => 0,
|
||||
nc_flags => [split(/\s+/,"+licqueue +nowarn+LIBNOU +define+nc=1 -q +assert +sv31a")],
|
||||
nc_flags2 => [], # Overridden in some sim files
|
||||
# Verilator
|
||||
'v3' => 0,
|
||||
verilator_flags => [split(/\s+/,"-cc")],
|
||||
verilator_make_gcc => 1,
|
||||
verilated_debug => $Opt_Verilated_Debug,
|
||||
stdout_filename => undef, # Redirect stdout
|
||||
@_};
|
||||
bless $self, $class;
|
||||
@@ -291,6 +294,7 @@ sub compile {
|
||||
fails=>$param{fails},
|
||||
cmd=>["vcs",
|
||||
@{$param{vcs_flags}},
|
||||
@{$param{vcs_flags2}},
|
||||
@{$param{v_flags}},
|
||||
@{$param{v_flags2}},
|
||||
$param{top_filename},
|
||||
@@ -304,6 +308,7 @@ sub compile {
|
||||
fails=>$param{fails},
|
||||
cmd=>["ncverilog",
|
||||
@{$param{nc_flags}},
|
||||
@{$param{nc_flags2}},
|
||||
@{$param{v_flags}},
|
||||
@{$param{v_flags2}},
|
||||
$param{top_filename},
|
||||
@@ -541,7 +546,7 @@ sub _make_main {
|
||||
print $fh "int main(int argc, char **argv, char **env) {\n";
|
||||
print $fh " double sim_time = 1000;\n";
|
||||
}
|
||||
print $fh " Verilated::debug(".($Opt_Verilated_Debug?1:0).");\n";
|
||||
print $fh " Verilated::debug(".($self->{verilated_debug}?1:0).");\n";
|
||||
print $fh " topp = new $VM_PREFIX (\"TOP\");\n";
|
||||
my $set;
|
||||
if ($self->sp) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// $Id:$
|
||||
// $Id$
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// Use this file as a template for submitting bugs, etc.
|
||||
@@ -29,7 +29,9 @@ module t (/*AUTOARG*/
|
||||
always @ (posedge clk) begin
|
||||
if (cyc!=0) begin
|
||||
cyc <= cyc + 1;
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("%d %x %x %x\n", cyc, in_a, in_b, out_x);
|
||||
`endif
|
||||
if (cyc==1) begin
|
||||
// Assign inputs randomly
|
||||
in_a <= 32'h89a14fab;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// $Id:$
|
||||
// $Id$
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
@@ -31,7 +31,9 @@ module t (/*AUTOARG*/
|
||||
always @ (posedge clk) begin
|
||||
if (cyc!=0) begin
|
||||
cyc <= cyc + 1;
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("%x/%x %x\n", q, qq, a);
|
||||
`endif
|
||||
if (cyc==1) begin
|
||||
a = 256'hed388e646c843d35de489bab2413d77045e0eb7642b148537491f3da147e7f26;
|
||||
end
|
||||
|
||||
@@ -65,7 +65,6 @@ module t (/*AUTOARG*/
|
||||
end
|
||||
else if (_mode==4) begin
|
||||
if (mode_d3r != 8'd1) $stop;
|
||||
$write("[%0t] t_blocking: Passed\n", $time);
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
@@ -19,7 +19,9 @@ module t (/*AUTOARG*/
|
||||
sub sub (.in(crc[23:0]), .out1(out1));
|
||||
|
||||
always @ (posedge clk) begin
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("[%0t] cyc==%0d crc=%x sum=%x out=%x\n",$time, cyc, crc, sum, out1);
|
||||
`endif
|
||||
cyc <= cyc + 1;
|
||||
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
|
||||
sum <= {sum[62:0], sum[63]^sum[2]^sum[0]} ^ {63'h0,out1};
|
||||
@@ -29,7 +31,7 @@ module t (/*AUTOARG*/
|
||||
sum <= 64'h0;
|
||||
end
|
||||
else if (cyc==90) begin
|
||||
if (sum != 64'h2e5cb972eb02b8a0) $stop;
|
||||
if (sum !== 64'h2e5cb972eb02b8a0) $stop;
|
||||
end
|
||||
else if (cyc==91) begin
|
||||
end
|
||||
|
||||
@@ -30,7 +30,7 @@ module t (/*AUTOARG*/
|
||||
sum <= 64'h0;
|
||||
end
|
||||
else if (cyc==90) begin
|
||||
if (sum != 64'hf0afc2bfa78277c5) $stop;
|
||||
if (sum !== 64'hf0afc2bfa78277c5) $stop;
|
||||
end
|
||||
else if (cyc==91) begin
|
||||
end
|
||||
|
||||
@@ -31,7 +31,9 @@ module t (/*AUTOARG*/
|
||||
te te (.clk(clk), .b(b), .vconst(vconst), .q(qe));
|
||||
|
||||
always @ (posedge clk) begin
|
||||
`ifdef TEST_VERBOSE
|
||||
$display("%b",{qa,qb,qc,qd,qe});
|
||||
`endif
|
||||
if (cyc!=0) begin
|
||||
cyc <= cyc + 1;
|
||||
if (cyc==1) begin
|
||||
|
||||
@@ -25,7 +25,9 @@ module t (/*AUTOARG*/
|
||||
.Input (Input[8:0]));
|
||||
|
||||
always @ (posedge clk) begin
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("[%0t] cyc==%0d crc=%x q=%x\n",$time, cyc, crc, sum);
|
||||
`endif
|
||||
cyc <= cyc + 1;
|
||||
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
|
||||
if (cyc==0) begin
|
||||
@@ -37,7 +39,7 @@ module t (/*AUTOARG*/
|
||||
sum <= {sum[30:0],sum[31]} ^ {23'h0, crc[8:0]};
|
||||
end
|
||||
else if (cyc==99) begin
|
||||
if (sum != 32'he8bbd130) $stop;
|
||||
if (sum !== 32'he8bbd130) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
|
||||
# $Id$
|
||||
# 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
|
||||
# General Public License or the Perl Artistic License.
|
||||
|
||||
compile (
|
||||
nc_flags2 => ['+access+r'],
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,111 @@
|
||||
// $Id$
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2007 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
integer cyc=0;
|
||||
reg [63:0] crc;
|
||||
reg [63:0] sum;
|
||||
|
||||
wire [3:0] Value = crc[3:0];
|
||||
|
||||
wire [3:0] Result;
|
||||
wire [3:0] Result2;
|
||||
|
||||
Testit testit (/*AUTOINST*/
|
||||
// Outputs
|
||||
.Result (Result[3:0]),
|
||||
.Result2 (Result2[3:0]),
|
||||
// Inputs
|
||||
.clk (clk),
|
||||
.Value (Value[3:0]));
|
||||
|
||||
always @ (posedge clk) begin
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("[%0t] cyc==%0d crc=%x %x %x %x\n",$time, cyc, crc, Result, Result2);
|
||||
`endif
|
||||
cyc <= cyc + 1;
|
||||
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
|
||||
sum <= {56'h0, Result, Result2}
|
||||
^ {sum[62:0],sum[63]^sum[2]^sum[0]};
|
||||
if (cyc==0) begin
|
||||
// Setup
|
||||
crc <= 64'h5aef0c8d_d70a4497;
|
||||
end
|
||||
else if (cyc<10) begin
|
||||
sum <= 64'h0;
|
||||
end
|
||||
else if (cyc<90) begin
|
||||
end
|
||||
else if (cyc==99) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$write("[%0t] cyc==%0d crc=%x %x\n",$time, cyc, crc, sum);
|
||||
if (crc !== 64'hc77bb9b3784ea091) $stop;
|
||||
if (sum !== 64'h4af37965592f64f9) $stop;
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module Test (clk, Value, Result);
|
||||
input clk;
|
||||
input Value;
|
||||
output Result;
|
||||
|
||||
reg Internal;
|
||||
|
||||
assign Result = Internal ^ clk;
|
||||
|
||||
always @(posedge clk)
|
||||
Internal <= #1 Value;
|
||||
endmodule
|
||||
|
||||
module Test_wrap1 (clk, Value, Result);
|
||||
input clk;
|
||||
input Value;
|
||||
output Result;
|
||||
|
||||
Test t (clk, Value, Result);
|
||||
endmodule
|
||||
|
||||
module Test_wrap2 (clk, Value, Result);
|
||||
input clk;
|
||||
input Value;
|
||||
output Result;
|
||||
|
||||
Test t (clk, Value, Result);
|
||||
endmodule
|
||||
|
||||
module Testit (clk, Value, Result, Result2);
|
||||
input clk;
|
||||
input [3:0] Value;
|
||||
output [3:0] Result;
|
||||
output [3:0] Result2;
|
||||
|
||||
genvar i;
|
||||
generate
|
||||
for (i = 0; i < 4; i = i + 1)
|
||||
begin : a
|
||||
if ((i == 0) || (i == 2)) begin : gblk
|
||||
Test_wrap1 test (clk, Value[i] , Result[i]);
|
||||
end
|
||||
else begin : gblk
|
||||
Test_wrap2 test (clk, Value[i], Result[i]);
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
assign Result2[0] = a[0].gblk.test.t.Internal;
|
||||
assign Result2[1] = a[1].gblk.test.t.Internal;
|
||||
assign Result2[2] = a[2].gblk.test.t.Internal;
|
||||
assign Result2[3] = a[3].gblk.test.t.Internal;
|
||||
|
||||
endmodule
|
||||
@@ -119,9 +119,11 @@ module prover (
|
||||
always @ (posedge clk) begin
|
||||
cyc <= cyc + 1;
|
||||
if (cyc>2) begin
|
||||
if (0) $write("results[%d][%d] = 8'b%b_%b_%b_%b_%b_%b_%b_%b;\n",
|
||||
index_a, index_b,
|
||||
gt, gts, gte, gtes, lt, lts, lte, ltes);
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("results[%d][%d] = 8'b%b_%b_%b_%b_%b_%b_%b_%b;\n",
|
||||
index_a, index_b,
|
||||
gt, gts, gte, gtes, lt, lts, lte, ltes);
|
||||
`endif
|
||||
exp = results[index_a][index_b];
|
||||
got = {gt, gts, gte, gtes, lt, lts, lte, ltes};
|
||||
if (exp !== got) begin
|
||||
|
||||
@@ -53,7 +53,9 @@ module t (/*AUTOARG*/
|
||||
always @ (posedge clk) begin
|
||||
if (cyc!=0) begin
|
||||
cyc <= cyc + 1;
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("%x %x\n", q, i);
|
||||
`endif
|
||||
if (cyc==1) begin
|
||||
i <= 256'hed388e646c843d35de489bab2413d77045e0eb7642b148537491f3da147e7f26;
|
||||
end
|
||||
|
||||
@@ -95,7 +95,9 @@ module t (/*AUTOARG*/
|
||||
always @ (posedge clk) begin
|
||||
if (cyc!=0) begin
|
||||
cyc <= cyc + 1;
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("%x %x\n", q1, i);
|
||||
`endif
|
||||
if (cyc==1) begin
|
||||
i <= 128'hed388e646c843d35de489bab2413d770;
|
||||
end
|
||||
|
||||
@@ -47,9 +47,11 @@ module t (/*AUTOARG*/
|
||||
always @ (posedge clk) begin
|
||||
cyc <= cyc + 1;
|
||||
crc <= {crc[6:0], ~^ {crc[7],crc[5],crc[4],crc[3]}};
|
||||
if (0) $write("[%0t] cyc==%0d crc=%b %d.%d,%d.%d -> %x.%x -> %x\n",$time, cyc, crc,
|
||||
LowMaskSel_Top, HighMaskSel_Top, LowMaskSel_Bot, HighMaskSel_Bot,
|
||||
LowLogicImm, HighLogicImm, LogicImm);
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("[%0t] cyc==%0d crc=%b %d.%d,%d.%d -> %x.%x -> %x\n",$time, cyc, crc,
|
||||
LowMaskSel_Top, HighMaskSel_Top, LowMaskSel_Bot, HighMaskSel_Bot,
|
||||
LowLogicImm, HighLogicImm, LogicImm);
|
||||
`endif
|
||||
if (cyc==0) begin
|
||||
// Single case
|
||||
crc <= 8'h0;
|
||||
@@ -65,8 +67,8 @@ module t (/*AUTOARG*/
|
||||
end
|
||||
else if (cyc==99) begin
|
||||
$write("[%0t] cyc==%0d crc=%b %x\n",$time, cyc, crc, sum);
|
||||
if (crc != 8'b00111000) $stop;
|
||||
if (sum != 64'h58743ffa61e41075) $stop;
|
||||
if (crc !== 8'b00111000) $stop;
|
||||
if (sum !== 64'h58743ffa61e41075) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
@@ -29,7 +29,7 @@ module t (/*AUTOARG*/
|
||||
sum <= 64'h0;
|
||||
end
|
||||
else if (cyc==90) begin
|
||||
if (sum != 64'hc1f743ad62c2c04d) $stop;
|
||||
if (sum !== 64'hc1f743ad62c2c04d) $stop;
|
||||
end
|
||||
else if (cyc==91) begin
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// $Id:$
|
||||
// $Id$
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
@@ -25,7 +25,9 @@ module t (/*AUTOARG*/
|
||||
always @ (posedge clk) begin
|
||||
if (cyc!=0) begin
|
||||
cyc <= cyc + 1;
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("%0x %x %x\n", cyc, p, shifted);
|
||||
`endif
|
||||
// Constant versions
|
||||
if (61'h1 ** 21'h31 != 61'h1) $stop;
|
||||
if (61'h2 ** 21'h10 != 61'h10000) $stop;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// $Id:$
|
||||
// $Id$
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
@@ -53,7 +53,9 @@ module t (/*AUTOARG*/
|
||||
always @ (posedge clk) begin
|
||||
if (cyc!=0) begin
|
||||
cyc <= cyc + 1;
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("%x %x %x %x %x\n", rf, rf2, dualasr, sl_mask, sr_mask);
|
||||
`endif
|
||||
if (cyc==1) begin
|
||||
biu <= 64'h12451282_abadee00;
|
||||
okidoki <= 1'b0;
|
||||
|
||||
@@ -28,7 +28,9 @@ module t (/*AUTOARG*/
|
||||
always @ (posedge clk) begin
|
||||
if (cyc!=0) begin
|
||||
cyc <= cyc + 1;
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("%d %x %x %x %x\n", cyc, left, right, qleft, qright);
|
||||
`endif
|
||||
if (cyc==1) begin
|
||||
amt <= 32'd0;
|
||||
if (5'b10110>>2 != 5'b00101) $stop;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// $Id:$
|
||||
// $Id$
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
@@ -47,8 +47,8 @@ module t (/*AUTOARG*/
|
||||
end
|
||||
else if (cyc==99) begin
|
||||
$write("[%0t] cyc==%0d crc=%b %x\n",$time, cyc, crc, sum);
|
||||
if (crc != 8'b01110000) $stop;
|
||||
if (sum != 224'h1fdff998855c3c38d467e28124847831f9ad6d4a09f2801098f032a8) $stop;
|
||||
if (crc !== 8'b01110000) $stop;
|
||||
if (sum !== 224'h1fdff998855c3c38d467e28124847831f9ad6d4a09f2801098f032a8) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
@@ -66,8 +66,8 @@ module t (/*AUTOARG*/
|
||||
else if (cyc==99) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$write("[%0t] cyc==%0d crc=%x %x\n",$time, cyc, crc, sum);
|
||||
if (crc != 64'hc77bb9b3784ea091) $stop;
|
||||
if (sum != 64'h5e9ea8c33a97f81e) $stop;
|
||||
if (crc !== 64'hc77bb9b3784ea091) $stop;
|
||||
if (sum !== 64'h5e9ea8c33a97f81e) $stop;
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
@@ -48,7 +48,7 @@ module t (/*AUTOARG*/
|
||||
sum <= {sum[30:0],sum[31]} ^ {out1, out0};
|
||||
end
|
||||
else if (cyc==99) begin
|
||||
if (sum != 32'he8bbd130) $stop;
|
||||
if (sum !== 32'he8bbd130) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
@@ -6,7 +6,9 @@ unsigned int Array[3];
|
||||
|
||||
unsigned int
|
||||
StepSim (Vt_mem_slot *sim, unsigned int slot, unsigned int bit, unsigned int val, unsigned int rslot) {
|
||||
#ifdef TEST_VERBOSE
|
||||
printf ("StepSim: slot=%d bit=%d val=%d rslot=%d\n", slot, bit, val, rslot);
|
||||
#endif
|
||||
|
||||
sim->SlotIdx = slot;
|
||||
sim->BitToChange = bit;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
|
||||
# $Id:$
|
||||
# $Id$
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
@@ -11,7 +11,7 @@ compile (
|
||||
fails=>$Last_Self->{v3},
|
||||
nc=>0, # Need to get it not to give the prompt
|
||||
expect=>
|
||||
'%Error: t/t_mod_bad_twotop.v:\d+: Unsupported: Multiple top level modules: t2 and t
|
||||
'%Error-MULTITOP: t/t_mod_bad_twotop.v:\d+: Unsupported: Multiple top level modules: t2 and t
|
||||
%Error: Exiting due to.*',
|
||||
);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// $Id:$
|
||||
// $Id$
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// $Id:$
|
||||
// $Id$
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
@@ -12,7 +12,9 @@ module t (clk);
|
||||
|
||||
integer cyc; initial cyc=1;
|
||||
always @ (posedge clk) begin
|
||||
`ifdef TEST_VERBOSE
|
||||
$write ("%x %x\n", cyc, addr);
|
||||
`endif
|
||||
if (cyc!=0) begin
|
||||
cyc <= cyc + 1;
|
||||
if (cyc==1) begin
|
||||
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
|
||||
# $Id$
|
||||
# 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
|
||||
# General Public License or the Perl Artistic License.
|
||||
|
||||
compile (
|
||||
v_flags2 => ['+define+ALLOW_UNOPT'],
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,135 @@
|
||||
// $Id$
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2005 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
|
||||
input clk;
|
||||
integer cyc; initial cyc=0;
|
||||
reg [63:0] crc;
|
||||
reg [63:0] sum;
|
||||
|
||||
`ifdef ALLOW_UNOPT
|
||||
/*verilator lint_off UNOPTFLAT*/
|
||||
`endif
|
||||
|
||||
/*AUTOWIRE*/
|
||||
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
||||
wire [31:0] b; // From file of file.v
|
||||
wire [31:0] c; // From file of file.v
|
||||
wire [31:0] d; // From file of file.v
|
||||
// End of automatics
|
||||
|
||||
file file (/*AUTOINST*/
|
||||
// Outputs
|
||||
.b (b[31:0]),
|
||||
.c (c[31:0]),
|
||||
.d (d[31:0]),
|
||||
// Inputs
|
||||
.crc (crc[31:0]));
|
||||
|
||||
always @ (posedge clk) begin
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("[%0t] cyc=%0d crc=%x sum=%x b=%x d=%x\n",$time,cyc,crc,sum, b, d);
|
||||
`endif
|
||||
cyc <= cyc + 1;
|
||||
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
|
||||
sum <= {b, d}
|
||||
^ {sum[62:0],sum[63]^sum[2]^sum[0]};
|
||||
if (cyc==0) begin
|
||||
// Setup
|
||||
crc <= 64'h5aef0c8d_d70a4497;
|
||||
end
|
||||
else if (cyc<10) begin
|
||||
sum <= 64'h0;
|
||||
end
|
||||
else if (cyc<90) begin
|
||||
end
|
||||
else if (cyc==99) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$write("[%0t] cyc==%0d crc=%x %x\n",$time, cyc, crc, sum);
|
||||
if (crc !== 64'hc77bb9b3784ea091) $stop;
|
||||
if (sum !== 64'h649ee1713d624dd9) $stop;
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module file (/*AUTOARG*/
|
||||
// Outputs
|
||||
b, c, d,
|
||||
// Inputs
|
||||
crc
|
||||
);
|
||||
|
||||
input [31:0] crc;
|
||||
`ifdef ISOLATE
|
||||
output reg [31:0] b /* verilator isolate_assignments*/;
|
||||
`else
|
||||
output reg [31:0] b;
|
||||
`endif
|
||||
|
||||
output reg [31:0] c;
|
||||
output reg [31:0] d;
|
||||
|
||||
always @* begin
|
||||
// Note that while c and b depend on crc, b doesn't depend on c.
|
||||
casez (crc[3:0])
|
||||
4'b??01: begin
|
||||
b = {crc[15:0],get_31_16(crc)};
|
||||
d = c;
|
||||
end
|
||||
4'b??00: begin
|
||||
b = {crc[15:0],~crc[31:16]};
|
||||
d = {crc[15:0],~c[31:16]};
|
||||
end
|
||||
default: begin
|
||||
set_b_d(crc, c);
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
function [31:16] get_31_16 /* verilator isolate_assignments*/;
|
||||
input [31:0] t_crc /* verilator isolate_assignments*/;
|
||||
get_31_16 = t_crc[31:16];
|
||||
endfunction
|
||||
|
||||
task set_b_d;
|
||||
`ifdef ISOLATE
|
||||
input [31:0] t_crc /* verilator isolate_assignments*/;
|
||||
input [31:0] t_c /* verilator isolate_assignments*/;
|
||||
`else
|
||||
input [31:0] t_crc;
|
||||
input [31:0] t_c;
|
||||
`endif
|
||||
begin
|
||||
b = {t_crc[31:16],~t_crc[23:8]};
|
||||
d = {t_crc[31:16], ~t_c[23:8]};
|
||||
end
|
||||
endtask
|
||||
|
||||
always @* begin
|
||||
// Any complicated equation we can't optimize
|
||||
casez (crc[3:0])
|
||||
4'b00??: begin
|
||||
c = {b[29:0],2'b11};
|
||||
end
|
||||
4'b01??: begin
|
||||
c = {b[30:1],2'b01};
|
||||
end
|
||||
4'b10??: begin
|
||||
c = {b[31:2],2'b10};
|
||||
end
|
||||
4'b11??: begin
|
||||
c = {b[31:2],2'b00};
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
||||
Executable
+29
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
|
||||
# $Id$
|
||||
# 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
|
||||
# General Public License or the Perl Artistic License.
|
||||
|
||||
top_filename("t/t_unopt_combo.v");
|
||||
|
||||
compile (
|
||||
fails=>$Last_Self->{v3},
|
||||
expect=>
|
||||
'%Warning-UNOPTFLAT: t/t_unopt_combo.v:\d+: Signal unoptimizable: Feedback to clock or circular logic: TOP->v.c
|
||||
%Warning-UNOPTFLAT: Use "/\* verilator lint_off UNOPTFLAT \*/" and lint_on around source to disable this message.
|
||||
%Warning-UNOPTFLAT: Example path: t/t_unopt_combo.v:\d+: TOP->v.c
|
||||
%Warning-UNOPTFLAT: Example path: t/t_unopt_combo.v:\d+: ALWAYS
|
||||
%Warning-UNOPTFLAT: Example path: t/t_unopt_combo.v:\d+: TOP->v.b
|
||||
%Warning-UNOPTFLAT: Example path: t/t_unopt_combo.v:\d+: ALWAYS
|
||||
%Warning-UNOPTFLAT: Example path: t/t_unopt_combo.v:\d+: TOP->v.c
|
||||
%Error: Exiting due to '
|
||||
);
|
||||
|
||||
execute (
|
||||
) if !$Last_Self->{v3};
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
|
||||
# $Id$
|
||||
# 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
|
||||
# General Public License or the Perl Artistic License.
|
||||
|
||||
top_filename("t/t_unopt_combo.v");
|
||||
|
||||
compile (
|
||||
v_flags2 => ['+define+ISOLATE --stats'],
|
||||
);
|
||||
|
||||
if ($Last_Self->{v3}) {
|
||||
file_grep ($Last_Self->{stats}, qr/Optimizations, isolate_assignments blocks\s+5/i);
|
||||
}
|
||||
|
||||
execute (
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,26 @@
|
||||
// $Id$
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2007 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Outputs
|
||||
x,
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
|
||||
`ifdef ALLOW_UNOPT
|
||||
/*verilator lint_off UNOPTFLAT*/
|
||||
`endif
|
||||
|
||||
input clk;
|
||||
output x; // Avoid eliminating x
|
||||
|
||||
reg x;
|
||||
always @* begin
|
||||
x = ~x;
|
||||
end
|
||||
|
||||
endmodule
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
|
||||
# $Id$
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2007 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# General Public License or the Perl Artistic License.
|
||||
|
||||
top_filename("t/t_unopt_converge.v");
|
||||
#$Last_Self->{verilated_debug} = 1;
|
||||
|
||||
compile (
|
||||
v_flags2 => ['+define+ALLOW_UNOPT'],
|
||||
make_flags => 'CPPFLAGS_ADD=-DVL_DEBUG',
|
||||
);
|
||||
|
||||
execute (
|
||||
fails=>1,
|
||||
expect=> '%Error: \S+:\d+: Verilated model didn\'t converge',
|
||||
) if $Last_Self->{v3};
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
Executable
+22
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
|
||||
# $Id$
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2007 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# General Public License or the Perl Artistic License.
|
||||
|
||||
top_filename("t/t_unopt_converge.v");
|
||||
|
||||
compile (
|
||||
v_flags2 => ['+define+ALLOW_UNOPT'],
|
||||
);
|
||||
|
||||
execute (
|
||||
fails=>1,
|
||||
expect=> '%Error: \S+:\d+: Verilated model didn\'t converge',
|
||||
) if $Last_Self->{v3};
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
|
||||
# $Id$
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2007 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# General Public License or the Perl Artistic License.
|
||||
|
||||
top_filename("t/t_unopt_converge.v");
|
||||
|
||||
compile (
|
||||
fails=>1,
|
||||
expect=> '%Warning-UNOPT: t/t_unopt_converge.v:\d+: Signal unoptimizable: Feedback to public clock or circular logic: TOP->x
|
||||
.*
|
||||
%Error: Exiting due to '
|
||||
) if $Last_Self->{v3};
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
Reference in New Issue
Block a user