mirror of
https://github.com/verilator/verilator.git
synced 2026-10-02 16:13:34 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4eeeb72dd5 | ||
|
|
adefa45fb4 | ||
|
|
cfc06ab2a7 | ||
|
|
f3a4752799 | ||
|
|
3d788b4b93 | ||
|
|
5d2675e38a | ||
|
|
288d7bd9dc | ||
|
|
3e8cf26c1a | ||
|
|
ce212722ad | ||
|
|
5c127daeb4 | ||
|
|
e49fc945df | ||
|
|
384807ebbd | ||
|
|
ac619ef3d8 | ||
|
|
a348bd3458 |
@@ -3,6 +3,20 @@ 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.681 2008/11/12
|
||||
|
||||
*** Add SystemVerilog unique and priority case.
|
||||
|
||||
**** Include Verilog file's directory name in coverage reports.
|
||||
|
||||
**** Fix 'for' under 'generate-for' causing error; bug38. [Rafael Shirakawa]
|
||||
|
||||
**** Fix coverage hierarchy being backwards with inlining. [Vasu Arasanipalai]
|
||||
|
||||
**** Fix GCC 4.3 compile error; bug35. [Lane Brooks]
|
||||
|
||||
**** Fix MSVC compile error; bug42. [John Stroebel]
|
||||
|
||||
* Verilator 3.680 2008/10/08
|
||||
|
||||
** Support negative bit indexes. [Stephane Laurent]
|
||||
@@ -11,6 +25,8 @@ indicates the contributor was also the author of the fix; Thanks!
|
||||
*** Suppress width warnings between constant strings and wider vectors.
|
||||
[Rodney Sinclair]
|
||||
|
||||
**** Ignore SystemVerilog timeunit and timeprecision.
|
||||
|
||||
**** Expand environment variables in -f input files. [Lawrence Butcher]
|
||||
|
||||
**** Report error if port declaration is missing; bug32. [Guy-Armand Kamendje]
|
||||
|
||||
+1
-1
@@ -111,7 +111,7 @@ DISTFILES_INC = $(INFOS) .gitignore COPYING *.in *.ac \
|
||||
include/.*ignore \
|
||||
.*attributes */.*attributes */*/.*attributes \
|
||||
src/.*ignore src/*.in src/*.cpp src/*.[chly] src/astgen src/bisonpre src/*fix \
|
||||
src/*.pl \
|
||||
src/*.pl src/*.pod \
|
||||
test_*/.*ignore test_*/Makefile* test_*/*.cpp \
|
||||
test_*/*.pl test_*/*.v test_*/*.vc test_*/vlint \
|
||||
test_verilated/vgen*.pl \
|
||||
|
||||
+33
-4
@@ -1038,7 +1038,8 @@ including function call-like preprocessor defines.
|
||||
|
||||
Verilator supports ==? and !=? operators, $bits, $countones, $error,
|
||||
$fatal, $info, $isunknown, $onehot, $onehot0, $warning, always_comb,
|
||||
always_ff, always_latch, do-while, and final.
|
||||
always_ff, always_latch, do-while, final, priority case/if, and unique
|
||||
case/if.
|
||||
|
||||
It also supports .name and .* interconnection.
|
||||
|
||||
@@ -1084,6 +1085,10 @@ formally prove the directive to be true, or failing that, will insert the
|
||||
appropriate code to detect failing cases at runtime and print an "Assertion
|
||||
failed" error message.
|
||||
|
||||
Verilator likewise also asserts any "unique" or "priority" SystemVerilog
|
||||
keywords on case statements. However, "unique if" and "priority if" are
|
||||
currently simply ignored.
|
||||
|
||||
=head1 LANGUAGE EXTENSIONS
|
||||
|
||||
The following additional constructs are the extensions Verilator supports
|
||||
@@ -1545,10 +1550,19 @@ while, wire, xnor, xor
|
||||
|
||||
Generally supported.
|
||||
|
||||
=item priority if, unique if
|
||||
|
||||
Priority and unique if's are treated as normal ifs and not asserted to be
|
||||
full nor unique.
|
||||
|
||||
=item specify specparam
|
||||
|
||||
All specify blocks and timing checks are ignored.
|
||||
|
||||
=item timeunit, timeprecision
|
||||
|
||||
All timing control statements are ignored.
|
||||
|
||||
=item uwire
|
||||
|
||||
Verilator does not perform warning checking on uwires, it treats the uwire
|
||||
@@ -2020,9 +2034,9 @@ Visual C++ Version 7 or newer, but this is not tested by the author.
|
||||
|
||||
=item Can you provide binaries?
|
||||
|
||||
Verilator is available as a RPM for SuSE and perhaps other systems; this is
|
||||
done by porters and may slightly lag the primary distribution. If there
|
||||
isn't a binary build for your distribution, how about you set one up?
|
||||
Verilator is available as a RPM for SuSE, Redhat and perhaps other systems;
|
||||
this is done by porters and may slightly lag the primary distribution. If
|
||||
there isn't a binary build for your distribution, how about you set one up?
|
||||
Please contact the authors for assistance.
|
||||
|
||||
Note people sometimes request binaries when they are having problems with
|
||||
@@ -2097,6 +2111,21 @@ Verilator makes standard VCD (Value Change Dump) files. They are viewable
|
||||
with the public domain Dinotrace or GtkWave programs, or any of the many
|
||||
commercial offerings.
|
||||
|
||||
=item How do I reduce the size of large waveform (trace) files?
|
||||
|
||||
First, instead of calling SpTraceVcdCFile->open at the beginning of time,
|
||||
delay calling it until the time stamp where you want to tracing to begin.
|
||||
Likewise you can also call SpTraceVcdCFile->open before the end of time
|
||||
(perhaps a short period after you detect a verification error.)
|
||||
|
||||
Next, add /*verilator tracing_off*/ to any very low level modules you never
|
||||
want to trace (such as perhaps library cells). Finally, use the
|
||||
--trace-depth option to limit the depth of tracing, for example
|
||||
--trace-depth 1 to see only the top level signals.
|
||||
|
||||
Also be sure you write your trace files to a local disk, instead of to a
|
||||
network disk. Network disks are generally far slower.
|
||||
|
||||
=item How do I do coverage analysis?
|
||||
|
||||
Verilator supports both block (line) coverage and user inserted functional
|
||||
|
||||
@@ -539,7 +539,11 @@ IData VL_FGETS_IXQ(int obits, void* destp, QData fpq) {
|
||||
// any read data. This means we can't know in what location the first
|
||||
// character will finally live, so we need to copy. Yuk.
|
||||
IData bytes = VL_BYTES_I(obits);
|
||||
char buffer[bytes];
|
||||
char buffer[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
|
||||
// V3Emit has static check that bytes < VL_TO_STRING_MAX_WORDS, but be safe
|
||||
if (VL_UNLIKELY(bytes > VL_TO_STRING_MAX_WORDS*VL_WORDSIZE)) {
|
||||
vl_fatal(__FILE__,__LINE__,"","Internal: fgets buffer overrun");
|
||||
}
|
||||
|
||||
// We don't use fgets, as we must read \0s.
|
||||
IData got = 0;
|
||||
|
||||
@@ -86,10 +86,10 @@ typedef long vlsint32_t; ///< 32-bit signed type
|
||||
typedef unsigned long vluint32_t; ///< 32-bit unsigned type
|
||||
typedef long long vlsint64_t; ///< 64-bit signed type
|
||||
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||
#elif defined(_WIN32) && !defined(__MINGW32__)
|
||||
#elif defined(_WIN32) && defined(_MSC_VER)
|
||||
typedef unsigned char uint8_t; ///< 8-bit unsigned type (backward compatibility)
|
||||
typedef unsigned short int uint16_t; ///< 16-bit unsigned type (backward compatibility)
|
||||
typedef unsigned long uint32_t; ///< 32-bit unsigned type (backward compatibility)
|
||||
typedef unsigned int uint32_t; ///< 32-bit unsigned type (backward compatibility)
|
||||
typedef unsigned char vluint8_t; ///< 8-bit unsigned type
|
||||
typedef unsigned short int vluint16_t; ///< 16-bit unsigned type
|
||||
typedef int vlsint32_t; ///< 32-bit signed type
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Verilator Source Code Notes
|
||||
|
||||
=head1 INTRODUCTION
|
||||
|
||||
See also the Verilator internals presentation at http://www.veripool.org.
|
||||
|
||||
=head1 VISITOR FUNCTIONS
|
||||
|
||||
=head2 Passing Variables
|
||||
|
||||
There's three ways data is passed between visitor functions.
|
||||
|
||||
1. A visitor-class member variable. This is generally for passing "parent"
|
||||
information down to children. m_modp is a common example. It's set to
|
||||
NULL in the constructor, where that node (AstModule visitor) sets it, then
|
||||
the children are iterated, then it's cleared. Children under an AstModule
|
||||
will see it set, while nodes elsewhere will see it clear. If there can be
|
||||
nested items (for example an AstFor under an AstFor) the variable needs to
|
||||
be save-set-restored in the AstFor visitor, otherwise exiting the lower for
|
||||
will loose the upper for's setting.
|
||||
|
||||
2. User() attributes. Each node has 4 ->user() number or ->userp() pointer
|
||||
utility values (a common technique lifted from graph traversal packages).
|
||||
A visitor first clears the one it wants to use by calling
|
||||
AstNode::user#ClearTree(), then it can mark any node's user() with whatever
|
||||
data it wants. Readers just call nodep->user(), but may need to cast
|
||||
appropriately, so you'll often see nodep->userp()->castSOMETYPE(). At the
|
||||
top of each visitor are comments describing how the user() stuff applies to
|
||||
that visitor class. For example:
|
||||
|
||||
// NODE STATE
|
||||
// Cleared entire netlist
|
||||
// AstModule::userp() // bool. True to inline this module
|
||||
|
||||
This says that at the AstNetlist userClearTree() is called. Each
|
||||
AstModule's is user() is used to indicate if we're going to inline it.
|
||||
|
||||
These comments are important to make sure a user#() on a given AstNode type
|
||||
is never being used for two different purposes.
|
||||
|
||||
Note that calling user#ClearTree is fast, it doesn't walk the tree, so it's
|
||||
ok to call fairly often. For example, it's commonly called on every
|
||||
module.
|
||||
|
||||
3. Parameters can be passed between the visitors in close to the "normal"
|
||||
function caller to callee way. This is the second "vup" parameter that is
|
||||
ignored on most of the visitor functions. V3Width does this, but it proved
|
||||
more messy than the above and is deprecated. (V3Width was nearly the first
|
||||
module written. Someday this scheme may be removed, as it slows the
|
||||
program down to have to pass vup everywhere.)
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2008-2008 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.
|
||||
+1
-1
@@ -115,7 +115,7 @@ private:
|
||||
} else {
|
||||
// V3Coverage assigned us a bucket to increment.
|
||||
AstCoverInc* covincp = snodep->coverincp()->castCoverInc();
|
||||
if (!covincp) snodep->v3fatalSrc("Missing coverage in PSL");
|
||||
if (!covincp) snodep->v3fatalSrc("Missing AstCoverInc under assertion");
|
||||
covincp->unlinkFrBack();
|
||||
if (message!="") covincp->declp()->comment(message);
|
||||
bodysp = covincp;
|
||||
|
||||
+5
-1
@@ -31,7 +31,6 @@
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
@@ -143,6 +142,11 @@ private:
|
||||
}
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
virtual void visit(AstCoverDecl* nodep, AstNUser*) {
|
||||
// Don't need to fix path in coverage statements, they're not under
|
||||
// any BEGINs, but V3Coverage adds them all under the module itself.
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
|
||||
@@ -155,6 +155,7 @@ private:
|
||||
virtual void visit(AstModule* nodep, AstNUser*) {
|
||||
m_modp = nodep;
|
||||
nodep->iterateChildren(*this);
|
||||
m_modp = NULL;
|
||||
}
|
||||
virtual void visit(AstNodeUniop* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
|
||||
@@ -245,6 +245,7 @@ private:
|
||||
m_modp = nodep;
|
||||
m_stableNum = 0;
|
||||
nodep->iterateChildren(*this);
|
||||
m_modp= NULL;
|
||||
}
|
||||
virtual void visit(AstScope* nodep, AstNUser*) {
|
||||
//UINFO(4," SCOPE "<<nodep<<endl);
|
||||
|
||||
@@ -407,6 +407,7 @@ private:
|
||||
nodep->iterateChildren(*this);
|
||||
m_state = STATE_IDLE;
|
||||
}
|
||||
m_modp = NULL;
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
||||
m_funcp = nodep;
|
||||
|
||||
+29
-7
@@ -52,11 +52,13 @@ private:
|
||||
bool m_checkBlock; // Should this block get covered?
|
||||
AstModule* m_modp; // Current module to add statement to
|
||||
FileMap m_fileps; // Column counts for each fileline
|
||||
string m_beginHier; // AstBegin hier name for user coverage points
|
||||
|
||||
//int debug() { return 9; }
|
||||
|
||||
// METHODS
|
||||
AstCoverInc* newCoverInc(FileLine* fl, const string& type, const string& comment) {
|
||||
AstCoverInc* newCoverInc(FileLine* fl, const string& hier,
|
||||
const string& type, const string& comment) {
|
||||
int column = 0;
|
||||
FileMap::iterator it = m_fileps.find(fl);
|
||||
if (it == m_fileps.end()) {
|
||||
@@ -66,6 +68,7 @@ private:
|
||||
}
|
||||
|
||||
AstCoverDecl* declp = new AstCoverDecl(fl, column, type, comment);
|
||||
declp->hier(hier);
|
||||
m_modp->addStmtp(declp);
|
||||
|
||||
return new AstCoverInc(fl, declp);
|
||||
@@ -86,7 +89,7 @@ private:
|
||||
if (!nodep->backp()->castIf()
|
||||
|| nodep->backp()->castIf()->elsesp()!=nodep) { // Ignore if else; did earlier
|
||||
UINFO(4," COVER: "<<nodep<<endl);
|
||||
nodep->addIfsp(newCoverInc(nodep->fileline(), "block", "if"));
|
||||
nodep->addIfsp(newCoverInc(nodep->fileline(), "", "block", "if"));
|
||||
}
|
||||
}
|
||||
// Don't do empty else's, only empty if/case's
|
||||
@@ -96,9 +99,9 @@ private:
|
||||
if (m_checkBlock && v3Global.opt.coverageLine()) { // if a "else" branch didn't disable it
|
||||
UINFO(4," COVER: "<<nodep<<endl);
|
||||
if (nodep->elsesp()->castIf()) {
|
||||
nodep->addElsesp(newCoverInc(nodep->elsesp()->fileline(), "block", "elsif"));
|
||||
nodep->addElsesp(newCoverInc(nodep->elsesp()->fileline(), "", "block", "elsif"));
|
||||
} else {
|
||||
nodep->addElsesp(newCoverInc(nodep->elsesp()->fileline(), "block", "else"));
|
||||
nodep->addElsesp(newCoverInc(nodep->elsesp()->fileline(), "", "block", "else"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -111,18 +114,20 @@ private:
|
||||
nodep->bodysp()->iterateAndNext(*this);
|
||||
if (m_checkBlock) { // if the case body didn't disable it
|
||||
UINFO(4," COVER: "<<nodep<<endl);
|
||||
nodep->addBodysp(newCoverInc(nodep->fileline(), "block", "case"));
|
||||
nodep->addBodysp(newCoverInc(nodep->fileline(), "", "block", "case"));
|
||||
}
|
||||
m_checkBlock = true; // Reset as a child may have cleared it
|
||||
}
|
||||
}
|
||||
virtual void visit(AstPslCover* nodep, AstNUser*) {
|
||||
UINFO(4," PSLCOVER: "<<nodep<<endl);
|
||||
m_checkBlock = true; // Always do cover blocks, even if there's a $stop
|
||||
nodep->iterateChildren(*this);
|
||||
if (!nodep->coverincp()) {
|
||||
// Note the name may be overridden by V3Assert processing
|
||||
nodep->coverincp(newCoverInc(nodep->fileline(), "psl_cover", "cover"));
|
||||
nodep->coverincp(newCoverInc(nodep->fileline(), m_beginHier, "psl_cover", "cover"));
|
||||
}
|
||||
m_checkBlock = true; // Reset as a child may have cleared it
|
||||
}
|
||||
virtual void visit(AstStop* nodep, AstNUser*) {
|
||||
UINFO(4," STOP: "<<nodep<<endl);
|
||||
@@ -134,8 +139,24 @@ private:
|
||||
UINFO(4," OFF: "<<nodep<<endl);
|
||||
m_checkBlock = false;
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
} else {
|
||||
if (m_checkBlock) nodep->iterateChildren(*this);
|
||||
}
|
||||
if (m_checkBlock) nodep->iterateChildren(*this);
|
||||
}
|
||||
virtual void visit(AstBegin* nodep, AstNUser*) {
|
||||
// Record the hiearchy of any named begins, so we can apply to user
|
||||
// coverage points. This is because there may be cov points inside
|
||||
// generate blocks; each point should get separate consideration.
|
||||
// (Currently ignored for line coverage, since any generate iteration
|
||||
// covers the code in that line.)
|
||||
string oldHier = m_beginHier;
|
||||
{
|
||||
if (nodep->name()!="") {
|
||||
m_beginHier = m_beginHier + (m_beginHier!=""?".":"") + nodep->name();
|
||||
}
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
m_beginHier = oldHier;
|
||||
}
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
// Default: Just iterate
|
||||
@@ -150,6 +171,7 @@ public:
|
||||
CoverageVisitor(AstNetlist* rootp) {
|
||||
// Operate on all modules
|
||||
m_checkBlock = true;
|
||||
m_beginHier = "";
|
||||
rootp->iterateChildren(*this);
|
||||
}
|
||||
virtual ~CoverageVisitor() {}
|
||||
|
||||
@@ -85,6 +85,7 @@ private:
|
||||
m_modp = nodep;
|
||||
m_funcp = NULL;
|
||||
nodep->iterateChildren(*this);
|
||||
m_modp = NULL;
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
||||
m_funcp = nodep;
|
||||
|
||||
@@ -77,6 +77,7 @@ private:
|
||||
m_modp = nodep;
|
||||
m_deepNum = 0;
|
||||
nodep->iterateChildren(*this);
|
||||
m_modp = NULL;
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
||||
// We recurse into this.
|
||||
|
||||
@@ -177,6 +177,7 @@ private:
|
||||
m_modFuncs.clear();
|
||||
nodep->iterateChildren(*this);
|
||||
makePublicFuncWrappers();
|
||||
m_modp = NULL;
|
||||
}
|
||||
virtual void visit(AstScope* nodep, AstNUser*) {
|
||||
m_scopep = nodep;
|
||||
|
||||
+6
-2
@@ -214,10 +214,10 @@ public:
|
||||
puts("__vlCoverInsert("); // As Declared in emitCoverageDecl
|
||||
puts("&__Vcoverage[");
|
||||
puts(cvtToStr(m_coverIds.remap(nodep))); puts("]");
|
||||
puts(", \""); puts(nodep->fileline()->filebasename()); puts("\"");
|
||||
puts(", \""); puts(nodep->fileline()->filename()); puts("\"");
|
||||
puts(", "); puts(cvtToStr(nodep->fileline()->lineno()));
|
||||
puts(", "); puts(cvtToStr(nodep->column()));
|
||||
puts(", \""); puts(nodep->hier()); puts("\"");
|
||||
puts(", \""); puts((nodep->hier()!=""?".":"")+nodep->hier()); puts("\"");
|
||||
puts(", \""); puts(nodep->typeText()); puts("\"");
|
||||
puts(", \""); puts(nodep->comment()); puts("\"");
|
||||
puts(");\n");
|
||||
@@ -242,6 +242,10 @@ public:
|
||||
virtual void visit(AstSScanF* nodep, AstNUser*) {
|
||||
displayNode(nodep, nodep->text(), nodep->exprsp(), true);
|
||||
}
|
||||
virtual void visit(AstFGetS* nodep, AstNUser*) {
|
||||
checkMaxWords(nodep);
|
||||
emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), NULL);
|
||||
}
|
||||
|
||||
void checkMaxWords(AstNode* nodep) {
|
||||
if (nodep->widthWords() > VL_TO_STRING_MAX_WORDS) {
|
||||
|
||||
@@ -78,6 +78,7 @@ class EmitCSyms : EmitCBaseVisitor {
|
||||
nameCheck(nodep);
|
||||
m_modp = nodep;
|
||||
nodep->iterateChildren(*this);
|
||||
m_modp = NULL;
|
||||
}
|
||||
virtual void visit(AstScope* nodep, AstNUser*) {
|
||||
nameCheck(nodep);
|
||||
|
||||
@@ -53,6 +53,7 @@ public:
|
||||
putbs("module "+modClassName(nodep)+";\n");
|
||||
nodep->iterateChildren(*this);
|
||||
puts("endmodule\n");
|
||||
m_modp = NULL;
|
||||
}
|
||||
virtual void visit(AstNodeFTask* nodep, AstNUser*) {
|
||||
putbs(nodep->castTask() ? "task ":"function ");
|
||||
|
||||
@@ -316,6 +316,7 @@ private:
|
||||
m_modp = nodep;
|
||||
m_activeReducible = true;
|
||||
nodep->iterateChildren(*this);
|
||||
m_modp = NULL;
|
||||
}
|
||||
virtual void visit(AstScope* nodep, AstNUser*) {
|
||||
UINFO(4," SCOPE "<<nodep<<endl);
|
||||
|
||||
+3
-1
@@ -249,7 +249,9 @@ private:
|
||||
virtual void visit(AstCoverDecl* nodep, AstNUser*) {
|
||||
// Fix path in coverage statements
|
||||
if (m_cellp) {
|
||||
nodep->hier(nodep->hier()+"."+m_cellp->prettyName());
|
||||
nodep->hier(m_cellp->prettyName()
|
||||
+ (nodep->hier()!="" ? ".":"")
|
||||
+ nodep->hier());
|
||||
}
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ private:
|
||||
//if (nodep->name() == "t_chg") m_debug = 9; else m_debug=0;
|
||||
m_modp = nodep;
|
||||
nodep->iterateChildren(*this);
|
||||
m_modp = NULL;
|
||||
}
|
||||
virtual void visit(AstCell* nodep, AstNUser*) {
|
||||
UINFO(4," CELL "<<nodep<<endl);
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include "verilatedos.h"
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <cstring>
|
||||
#include <unistd.h>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
@@ -47,6 +47,7 @@ private:
|
||||
virtual void visit(AstModule* nodep, AstNUser*) {
|
||||
m_modp = nodep;
|
||||
nodep->iterateChildren(*this);
|
||||
m_modp = NULL;
|
||||
}
|
||||
virtual void visit(AstCell* nodep, AstNUser*) {
|
||||
// Track module depths, so can sort list from parent down to children
|
||||
|
||||
+1
-2
@@ -18,12 +18,11 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#include <config_build.h>
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include "V3Number.h"
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <set>
|
||||
|
||||
@@ -461,6 +461,7 @@ private:
|
||||
virtual void visit(AstModule* nodep, AstNUser*) {
|
||||
m_modp = nodep;
|
||||
nodep->iterateChildren(*this);
|
||||
m_modp = NULL;
|
||||
}
|
||||
virtual void visit(AstScope* nodep, AstNUser*) {
|
||||
UINFO(4," SCOPE "<<nodep<<endl);
|
||||
|
||||
@@ -142,6 +142,7 @@ private:
|
||||
m_modp = nodep;
|
||||
m_funcp = NULL;
|
||||
nodep->iterateChildren(*this);
|
||||
m_modp = NULL;
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
||||
m_funcp = nodep;
|
||||
|
||||
@@ -31,6 +31,11 @@ class V3Lexer;
|
||||
class V3Number;
|
||||
class AstNode;
|
||||
|
||||
//======================================================================
|
||||
// Types (between parser & lexer)
|
||||
|
||||
typedef enum { uniq_NONE, uniq_UNIQUE, uniq_PRIORITY } V3UniqState;
|
||||
|
||||
//============================================================================
|
||||
|
||||
class V3Read {
|
||||
|
||||
@@ -70,6 +70,7 @@ private:
|
||||
m_modp = nodep;
|
||||
m_constXCvt = true;
|
||||
nodep->iterateChildren(*this);
|
||||
m_modp = NULL;
|
||||
}
|
||||
virtual void visit(AstCaseItem* nodep, AstNUser*) {
|
||||
m_constXCvt = false; // Avoid loosing the X's in casex
|
||||
|
||||
+5
-1
@@ -336,7 +336,11 @@ private:
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeFor* nodep, AstNUser*) {
|
||||
nodep->v3error("V3Task should have removed standard FORs");
|
||||
if (m_generate) { // Ignore for's when expanding genfor's
|
||||
nodep->iterateChildren(*this);
|
||||
} else {
|
||||
nodep->v3error("V3Task should have removed standard FORs");
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstBegin* nodep, AstNUser*) {
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
//**********************************************************************
|
||||
//**** Version and host name
|
||||
|
||||
#define DTVERSION "Verilator 3.680 2008/10/08"
|
||||
#define DTVERSION "Verilator 3.681 2008/11/12"
|
||||
|
||||
//**********************************************************************
|
||||
//**** Functions
|
||||
@@ -84,6 +84,7 @@
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
+5
-5
@@ -355,7 +355,11 @@ escid \\[^ \t\f\r\n]+
|
||||
"endproperty" {yylval.fileline = CRELINE(); return yENDPROPERTY;}
|
||||
"final" {yylval.fileline = CRELINE(); return yFINAL;}
|
||||
"iff" {yylval.fileline = CRELINE(); return yIFF;}
|
||||
"priority" {yylval.fileline = CRELINE(); return yPRIORITY;}
|
||||
"static" {yylval.fileline = CRELINE(); return ySTATIC;}
|
||||
"timeprecision" {yylval.fileline = CRELINE(); return yTIMEPRECISION;}
|
||||
"timeunit" {yylval.fileline = CRELINE(); return yTIMEUNIT;}
|
||||
"unique" {yylval.fileline = CRELINE(); return yUNIQUE;}
|
||||
/* Generic unsupported warnings */
|
||||
/* Note assert_strobe was in SystemVerilog 3.1, but removed for SystemVerilog 2005 */
|
||||
"alias" {yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext);}
|
||||
@@ -406,7 +410,6 @@ escid \\[^ \t\f\r\n]+
|
||||
"null" {yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext);}
|
||||
"package" {yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext);}
|
||||
"packed" {yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext);}
|
||||
"priority" {yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext);}
|
||||
"program" {yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext);}
|
||||
"protected" {yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext);}
|
||||
"pure" {yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext);}
|
||||
@@ -425,11 +428,8 @@ escid \\[^ \t\f\r\n]+
|
||||
"tagged" {yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext);}
|
||||
"this" {yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext);}
|
||||
"throughout" {yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext);}
|
||||
"timeprecision" {yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext);}
|
||||
"timeunit" {yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext);}
|
||||
"type" {yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext);}
|
||||
"typedef" {yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext);}
|
||||
"unique" {yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext);}
|
||||
"var" {yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext);}
|
||||
"virtual" {yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext);}
|
||||
"void" {yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext);}
|
||||
@@ -694,7 +694,7 @@ escid \\[^ \t\f\r\n]+
|
||||
}
|
||||
[0-9][_0-9]*(\.[_0-9]+)?(fs|ps|ns|us|ms|s|step) {
|
||||
yylval.cdouble = 0; /* Only for times, not used yet */
|
||||
return yaFLOATNUM;
|
||||
return yaTIMENUM;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+38
-6
@@ -57,6 +57,7 @@ public:
|
||||
static string s_instModule; // Name of module referenced for instantiations
|
||||
static AstPin* s_instParamp; // Parameters for instantiations
|
||||
static bool s_trace; // Tracing is turned on
|
||||
static int s_uniqueAttr; // Bitmask of unique/priority keywords
|
||||
|
||||
static AstVar* createVariable(FileLine* fileline, string name, AstRange* arrayp);
|
||||
static AstNode* createSupplyExpr(FileLine* fileline, string name, int value);
|
||||
@@ -107,6 +108,7 @@ class AstSenTree;
|
||||
string* strp;
|
||||
int cint;
|
||||
double cdouble;
|
||||
V3UniqState uniqstate;
|
||||
|
||||
AstNode* nodep;
|
||||
|
||||
@@ -139,6 +141,8 @@ class AstSenTree;
|
||||
|
||||
// IEEE: integral_number
|
||||
%token<nump> yaINTNUM "INTEGER NUMBER"
|
||||
// IEEE: time_literal + time_unit
|
||||
%token<cdouble> yaTIMENUM "TIME NUMBER"
|
||||
// IEEE: string_literal
|
||||
%token<strp> yaSTRING "STRING"
|
||||
%token<fileline> yaTIMINGSPEC "TIMING SPEC ELEMENT"
|
||||
@@ -201,6 +205,7 @@ class AstSenTree;
|
||||
%token<fileline> yOUTPUT "output"
|
||||
%token<fileline> yPARAMETER "parameter"
|
||||
%token<fileline> yPOSEDGE "posedge"
|
||||
%token<fileline> yPRIORITY "priority"
|
||||
%token<fileline> yPROPERTY "property"
|
||||
%token<fileline> yREG "reg"
|
||||
%token<fileline> ySCALARED "scalared"
|
||||
@@ -210,8 +215,11 @@ class AstSenTree;
|
||||
%token<fileline> ySUPPLY0 "supply0"
|
||||
%token<fileline> ySUPPLY1 "supply1"
|
||||
%token<fileline> yTASK "task"
|
||||
%token<fileline> yTIMEPRECISION "timeprecision"
|
||||
%token<fileline> yTIMEUNIT "timeunit"
|
||||
%token<fileline> yTRI "tri"
|
||||
%token<fileline> yTRUE "true"
|
||||
%token<fileline> yUNIQUE "unique"
|
||||
%token<fileline> yUNSIGNED "unsigned"
|
||||
%token<fileline> yVECTORED "vectored"
|
||||
%token<fileline> yWHILE "while"
|
||||
@@ -425,7 +433,7 @@ statePop: /* empty */ { V3Read::statePop(); }
|
||||
// Files
|
||||
|
||||
fileE: /* empty */ { }
|
||||
| file { }
|
||||
| timeunitsDeclE file { }
|
||||
;
|
||||
|
||||
file: description { }
|
||||
@@ -436,13 +444,26 @@ file: description { }
|
||||
description: moduleDecl { }
|
||||
;
|
||||
|
||||
// IEEE: timeunits_declaration + empty
|
||||
timeunitsDeclE: /*empty*/ { }
|
||||
| yTIMEUNIT yaTIMENUM ';' { }
|
||||
| yTIMEPRECISION yaTIMENUM ';' { }
|
||||
| yTIMEUNIT yaTIMENUM ';' yTIMEPRECISION yaTIMENUM ';' { }
|
||||
| yTIMEPRECISION yaTIMENUM ';' yTIMEUNIT yaTIMENUM ';' { }
|
||||
;
|
||||
|
||||
//**********************************************************************
|
||||
// Module headers
|
||||
|
||||
// IEEE: module_declaration:
|
||||
moduleDecl: modHdr modParE modPortsE ';' modItemListE yENDMODULE endLabelE
|
||||
moduleDecl: modHeader timeunitsDeclE modItemListE yENDMODULE endLabelE
|
||||
{ if ($3) $1->addStmtp($3); }
|
||||
;
|
||||
|
||||
modHeader<modulep>:
|
||||
modHdr modParE modPortsE ';'
|
||||
{ $1->modTrace(V3Parse::s_trace); // Stash for implicit wires, etc
|
||||
if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3); if ($5) $1->addStmtp($5); }
|
||||
if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3); }
|
||||
;
|
||||
|
||||
modHdr<modulep>:
|
||||
@@ -719,6 +740,7 @@ dlyTerm<nodep>:
|
||||
yaID { $$ = NULL; }
|
||||
| yaINTNUM { $$ = NULL; }
|
||||
| yaFLOATNUM { $$ = NULL; }
|
||||
| yaTIMENUM { $$ = NULL; }
|
||||
;
|
||||
|
||||
// IEEE: mintypmax_expression and constant_mintypmax_expression
|
||||
@@ -982,10 +1004,20 @@ stmt<nodep>:
|
||||
//************************************************
|
||||
// Case/If
|
||||
|
||||
unique_priorityE<uniqstate>:
|
||||
/*empty*/ { $$ = uniq_NONE; }
|
||||
| yPRIORITY { $$ = uniq_PRIORITY; }
|
||||
| yUNIQUE { $$ = uniq_UNIQUE; }
|
||||
;
|
||||
|
||||
stateCaseForIf<nodep>:
|
||||
caseStmt caseAttrE caseListE yENDCASE { $$ = $1; if ($3) $1->addItemsp($3); }
|
||||
| yIF '(' expr ')' stmtBlock %prec prLOWER_THAN_ELSE { $$ = new AstIf($1,$3,$5,NULL); }
|
||||
| yIF '(' expr ')' stmtBlock yELSE stmtBlock { $$ = new AstIf($1,$3,$5,$7); }
|
||||
unique_priorityE caseStmt caseAttrE caseListE yENDCASE { $$ = $2; if ($4) $2->addItemsp($4);
|
||||
if ($1 == uniq_UNIQUE) $2->parallelPragma(true);
|
||||
if ($1 == uniq_PRIORITY) $2->fullPragma(true); }
|
||||
| unique_priorityE yIF '(' expr ')' stmtBlock %prec prLOWER_THAN_ELSE
|
||||
{ $$ = new AstIf($2,$4,$6,NULL); }
|
||||
| unique_priorityE yIF '(' expr ')' stmtBlock yELSE stmtBlock
|
||||
{ $$ = new AstIf($2,$4,$6,$8); }
|
||||
| yFOR '(' varRefBase '=' expr ';' expr ';' varRefBase '=' expr ')' stmtBlock
|
||||
{ $$ = new AstFor($1, new AstAssign($4,$3,$5)
|
||||
,$7, new AstAssign($10,$9,$11)
|
||||
|
||||
@@ -481,7 +481,9 @@ sub _run {
|
||||
my %param = (tee=>1,
|
||||
@_);
|
||||
my $command = join(' ',@{$param{cmd}});
|
||||
print "\t$command\n";
|
||||
print "\t$command";
|
||||
print " > $param{logfile}" if $param{logfile};
|
||||
print "\n";
|
||||
|
||||
if ($param{logfile}) {
|
||||
open(SAVEOUT, ">&STDOUT") or die "%Error: Can't dup stdout";
|
||||
|
||||
@@ -23,8 +23,8 @@ if ($Last_Self->{nc}) {
|
||||
{
|
||||
my $fh = IO::File->new(">$cf") or die "%Error: $! writing $cf,";
|
||||
$fh->printf("report_summary -module *\n");
|
||||
$fh->printf("report_detail -both -module *\n");
|
||||
$fh->printf("report_html -both -module * > obj_dir/${name}__nccover.html\n");
|
||||
$fh->printf("report_detail -both -instance *\n");
|
||||
$fh->printf("report_html -both -instance * > obj_dir/${name}__nccover.html\n");
|
||||
$fh->close;
|
||||
}
|
||||
$Last_Self->_run (logfile=>"obj_dir/${name}__nccover.log",
|
||||
@@ -36,7 +36,9 @@ if ($Last_Self->{nc}) {
|
||||
file_grep ("obj_dir/$Last_Self->{name}_simx.log", qr/COVER: Cyc==4/);
|
||||
file_grep ("obj_dir/$Last_Self->{name}_simx.log", qr/COVER: Cyc==5/);
|
||||
file_grep ("obj_dir/$Last_Self->{name}_simx.log", qr/COVER: Cyc==6/);
|
||||
file_grep ($Last_Self->{coverage_filename}, qr/cyc_eq_5.*,c=>[^0]/);
|
||||
|
||||
# Allow old Perl format dump, or new binary dump
|
||||
file_grep ($Last_Self->{coverage_filename}, qr/(cyc_eq_5.*,c=>[^0]|cyc_eq_5.* [1-9][0-9]*\n)/);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
||||
@@ -64,7 +64,22 @@ module Test
|
||||
cover property (@(posedge clk) disable iff (!toggle) cyc==8)
|
||||
$stop;
|
||||
|
||||
//============================================================
|
||||
// Using a macro and generate
|
||||
wire reset = (cyc < 2);
|
||||
|
||||
`define covclk(eqn) cover property (@(posedge clk) disable iff (reset) (eqn))
|
||||
|
||||
genvar i;
|
||||
generate
|
||||
for (i=0; i<32; i=i+1)
|
||||
begin: cycval
|
||||
CycCover_i: `covclk( cyc[i] );
|
||||
end
|
||||
endgenerate
|
||||
|
||||
`ifndef verilator // Unsupported
|
||||
//============================================================
|
||||
// Using a more complicated property
|
||||
property C1;
|
||||
@(posedge clk)
|
||||
|
||||
@@ -32,6 +32,12 @@ module t (/*AUTOARG*/
|
||||
2'b1_0: ;
|
||||
// Note no default
|
||||
endcase
|
||||
priority case ({a,b_fc})
|
||||
2'b0_0: ;
|
||||
2'b0_1: ;
|
||||
2'b1_0: ;
|
||||
// Note no default
|
||||
endcase
|
||||
end
|
||||
|
||||
always @* begin
|
||||
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
#!/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
|
||||
# General Public License or the Perl Artistic License.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,87 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
|
||||
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 [9:0] in = crc[9:0];
|
||||
|
||||
/*AUTOWIRE*/
|
||||
|
||||
Test test (/*AUTOINST*/
|
||||
// Inputs
|
||||
.clk (clk),
|
||||
.in (in[9:0]));
|
||||
|
||||
// Aggregate outputs into a single result vector
|
||||
wire [63:0] result = {64'h0};
|
||||
|
||||
// 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;
|
||||
end
|
||||
else if (cyc<10) begin
|
||||
sum <= 64'h0;
|
||||
end
|
||||
else if (cyc<90) begin
|
||||
end
|
||||
else if (cyc==99) begin
|
||||
$write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
|
||||
if (crc !== 64'hc77bb9b3784ea091) $stop;
|
||||
// What checksum will we end up with (above print should match)
|
||||
`define EXPECTED_SUM 64'h0
|
||||
if (sum !== `EXPECTED_SUM) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module Test (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk, in
|
||||
);
|
||||
input clk;
|
||||
input [9:0] in;
|
||||
|
||||
reg a [9:0];
|
||||
integer ai;
|
||||
always @* begin
|
||||
for (ai=0;ai<10;ai=ai+1) begin
|
||||
a[ai]=in[ai];
|
||||
end
|
||||
end
|
||||
|
||||
reg [1:0] b [9:0];
|
||||
integer j;
|
||||
|
||||
generate
|
||||
genvar i;
|
||||
for (i=0; i<2; i=i+1) begin
|
||||
always @(posedge clk) begin
|
||||
for (j=0; j<10; j=j+1) begin
|
||||
if (a[j])
|
||||
b[i][j] <= 1'b0;
|
||||
else
|
||||
b[i][j] <= 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
endmodule
|
||||
@@ -8,6 +8,11 @@ module t (/*AUTOARG*/
|
||||
clk
|
||||
);
|
||||
|
||||
`ifdef verilator // Otherwise need it in every module, including test, but that'll make a mess
|
||||
timeunit 1ns;
|
||||
timeprecision 1ns;
|
||||
`endif
|
||||
|
||||
input clk;
|
||||
integer cyc; initial cyc=1;
|
||||
|
||||
|
||||
@@ -16,9 +16,10 @@ execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
file_grep ($Last_Self->{coverage_filename}, qr/,o=>'cover'.*,c=>2\);/);
|
||||
file_grep ($Last_Self->{coverage_filename}, qr/DefaultClock.*,c=>1\);/);
|
||||
file_grep ($Last_Self->{coverage_filename}, qr/ToggleLogIf.*,c=>9\);/);
|
||||
# Allow old Perl format dump, or new binary dump
|
||||
file_grep ($Last_Self->{coverage_filename}, qr/(,o=>'cover'.*,c=>2\)|o.cover.* 2\n)/);
|
||||
file_grep ($Last_Self->{coverage_filename}, qr/(DefaultClock.*,c=>1\)|DefaultClock.* 1\n)/);
|
||||
file_grep ($Last_Self->{coverage_filename}, qr/(ToggleLogIf.*,c=>9\)|ToggleLogIf.* 9\n)/);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ VERILATOR_FLAGS = --sc $(V_FLAGS) top.v
|
||||
|
||||
precopy: obj_dir obj_dir/sc_main.cpp
|
||||
obj_dir/sc_main.cpp: ../test_sp/sc_main.cpp
|
||||
mkdir obj_dir
|
||||
mkdir -p obj_dir
|
||||
cp $^ $@
|
||||
|
||||
prep:
|
||||
|
||||
@@ -16,6 +16,8 @@ module t_clk_two (/*AUTOARG*/
|
||||
// verilator lint_on GENCLK
|
||||
reg [31:0] count;
|
||||
|
||||
t_clk_twob tb (.*);
|
||||
|
||||
wire reset_h = ~reset_l;
|
||||
always @ (posedge fastclk) begin
|
||||
if (reset_h) clk2 <= 0;
|
||||
@@ -26,3 +28,17 @@ module t_clk_two (/*AUTOARG*/
|
||||
else count <= count + 1;
|
||||
end
|
||||
endmodule
|
||||
|
||||
module t_clk_twob (/*AUTOARG*/
|
||||
// Inputs
|
||||
fastclk, reset_l
|
||||
);
|
||||
input fastclk;
|
||||
input reset_l;
|
||||
|
||||
always @ (posedge fastclk) begin
|
||||
// Extra line coverage point, just to make sure coverage
|
||||
// hierarchy under inlining lands properly
|
||||
if (reset_l) ;
|
||||
end
|
||||
endmodule
|
||||
|
||||
Reference in New Issue
Block a user