This commit is contained in:
Wilson Snyder 2020-02-27 19:43:46 -05:00
commit 4957a3b294
46 changed files with 753 additions and 341 deletions

View File

@ -9,6 +9,10 @@ The contributors that suggested a given feature are shown in []. Thanks!
*** Add check for assertOn for asserts, #2162. [Tobias Wölfel]
*** Fix genblk naming with directly nested generate blocks, #2176. [Alexander Grobman]
**** Use gcc -Os in examples instead of -O2 for better average performance.
**** Fix undeclared VL_SHIFTR_WWQ, #2114. [Alex Solomatnikov]
@ -54,6 +58,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
**** Fix OpenSolaris issues, #2154. [brancoliticus]
**** Fix gated clocks under --protect-lib, #2169. [Todd Strader]
* Verilator 4.026 2020-01-11

View File

@ -208,12 +208,6 @@ EXAMPLES_FIRST = \
EXAMPLES = $(EXAMPLES_FIRST) $(filter-out $(EXAMPLES_FIRST), $(sort $(wildcard examples/*)))
ifeq ($(OBJCACHE_JOBS),)
ifneq ($(OBJCACHE_HOSTS),)
export OBJCACHE_JOBS := -j $(shell objcache --jobs "$(OBJCACHE_HOSTS)")
endif
endif
# See uninstall also - don't put wildcards in this variable, it might uninstall other stuff
VL_INST_MAN_FILES = verilator.1 verilator_coverage.1 verilator_gantt.1 verilator_profcfunc.1

View File

@ -25,7 +25,7 @@ endif::[]
^.^| *Welcome to Verilator, the fastest free Verilog HDL simulator.*
+++ <br/> +++ &bullet; Accepts synthesizable Verilog or SystemVerilog
+++ <br/> +++ &bullet; Performs lint code-quality checks
+++ <br/> +++ &bullet; Compiles into multithreaded {cpp}, SystemC, or (soon) {cpp}-under-Python
+++ <br/> +++ &bullet; Compiles into multithreaded {cpp}, or SystemC
+++ <br/> +++ &bullet; Creates XML to front-end your own tools
<.^|image:https://www.veripool.org/img/verilator_256_200_min.png[Logo,256,200]
@ -81,7 +81,7 @@ touch of {cpp} code, Verilator is the tool for you.
Verilator does not simply convert Verilog HDL to {cpp} or SystemC. Rather
than only translate, Verilator compiles your code into a much faster
optimized and optionally thread-partitioned model, which is in turn wrapped
inside a {cpp}/SystemC/Python module. The results are a compiled Verilog
inside a {cpp}/SystemC/{cpp}-under-Python module. The results are a compiled Verilog
model that executes even on a single-thread over 10x faster than standalone
SystemC, and on a single thread is about 100 times faster than interpreted
Verilog simulators such as http://iverilog.icarus.com[Icarus

View File

@ -1906,13 +1906,13 @@ Now we run Verilator on our little example.
We then can compile it
cd obj_dir
make -j -f Vour.mk Vour__ALL.a
make -j -f Vour.mk ../sc_main.o verilated.o
make -j -C obj_dir -f Vour.mk Vour__ALL.a
make -j -C obj_dir -f Vour.mk ../sc_main.o verilated.o
And link with SystemC. Note your path to the libraries may vary,
depending on the operating system.
cd obj_dir
export SYSTEMC_LIBDIR=/path/to/where/libsystemc.a/exists
export LD_LIBRARY_PATH=$SYSTEMC_LIBDIR:$LD_LIBRARY_PATH
# Might be needed if SystemC 2.3.0
@ -1964,27 +1964,27 @@ OPT, OPT_FAST, or OPT_SLOW lib/verilated.mk. Or, use the -CFLAGS and/or
the compiler or linker. Or, just for one run, pass them on the command
line to make:
make OPT_FAST="-O2 -fno-stack-protector" -f Vour.mk Vour__ALL.a
make OPT_FAST="-Os -fno-stack-protector" -f Vour.mk Vour__ALL.a
OPT_FAST specifies optimizations for those programs that are part of the
fast path, mostly code that is executed every cycle. OPT_SLOW specifies
optimizations for slow-path files (plus tracing), which execute only
rarely, yet take a long time to compile with optimization on. OPT
specifies overall optimization and affects all compiles, including those
OPT_FAST and OPT_SLOW control. For best results, use OPT="-O2", and link
OPT_FAST and OPT_SLOW control. For best results, use OPT="-Os", and link
with "-static". Nearly the same results can be had with much better
compile times with OPT_FAST="-O1 -fstrict-aliasing". Higher optimization
such as "-O3" may help, but gcc compile times may be excessive under O3 on
even medium sized designs. Alternatively, some larger designs report
better performance using "-Os".
such as "-O2" or "-O3" may help, but gcc compile times may be excessive
under O3 on even medium sized designs.
Unfortunately, using the optimizer with SystemC files can result in
compiles taking several minutes. (The SystemC libraries have many little
inlined functions that drive the compiler nuts.)
For best results, use GCC 3.3 or newer. GCC 3.2 and earlier have
optimization bugs around pointer aliasing detection, which can result in 2x
performance losses.
For best results, use the latest clang compiler (about 10% faster than
GCC). Note the now fairly old GCC 3.2 and earlier have optimization bugs
around pointer aliasing detection, which can result in 2x performance
losses.
If you will be running many simulations on a single compile, investigate
feedback driven compilation. With GCC, using -fprofile-arcs, then
@ -1995,6 +1995,9 @@ especially if you link in DPI code. To enable LTO on GCC, pass "-flto" in
both compilation and link. Note LTO may cause excessive compile times on
large designs.
Using profile driven compiler optimization, with feedback from a real
design, can yield up to30% improvements.
If you are using your own makefiles, you may want to compile the Verilated
code with -DVL_INLINE_OPT=inline. This will inline functions, however this
requires that all cpp files be compiled in a single compiler run.
@ -2005,7 +2008,7 @@ either oprofile or gprof to see where in the C++ code the time is spent.
Run the gprof output through verilator_profcfunc and it will tell you what
Verilog line numbers on which most of the time is being spent.
When done, please let the author know the results. I like to keep tabs on
When done, please let the author know the results. We like to keep tabs on
how Verilator compares, and may be able to suggest additional improvements.
@ -2080,7 +2083,7 @@ After running Make, the C++ compiler may produce the following:
A generic Linux/OS variable specifying what directories have shared object
(.so) files. This path should include SystemC and any other shared objects
needed at simultion runtime.
needed at simulation runtime.
=item OBJCACHE

View File

@ -123,13 +123,13 @@ sub report {
}
my $nthreads = scalar keys %Threads;
$Global{cpus}{cpu_time} = {};
$Global{cpus} = {};
foreach my $thread (keys %Threads) {
# Make potentially multiple characters per column
foreach my $start (keys %{$Threads{$thread}}) {
my $cpu = $Threads{$thread}{$start}{cpu};
my $elapsed = $Threads{$thread}{$start}{end} - $start;
$Global{cpus}{cpu_time}{$cpu} += $elapsed;
$Global{cpus}{$cpu}{cpu_time} += $elapsed;
}
}

View File

@ -34,5 +34,5 @@ add_executable(example ../make_tracing_c/sim_main.cpp)
# Add the Verilated circuit to the target
verilate(example COVERAGE TRACE
INCLUDE_DIRS "../make_tracing_c"
VERILATOR_ARGS -f ../make_tracing_c/input.vc -O2 -x-assign 0
VERILATOR_ARGS -f ../make_tracing_c/input.vc -Os -x-assign 0
SOURCES ../make_tracing_c/top.v)

View File

@ -41,7 +41,7 @@ add_executable(example ../make_tracing_sc/sc_main.cpp)
# Add the Verilated circuit to the target
verilate(example SYSTEMC COVERAGE TRACE
INCLUDE_DIRS "../make_tracing_sc"
VERILATOR_ARGS -f ../make_tracing_sc/input.vc -O2 -x-assign 0
VERILATOR_ARGS -f ../make_tracing_sc/input.vc -Os -x-assign 0
SOURCES ../make_tracing_sc/top.v)
verilator_link_systemc(example)

View File

@ -34,7 +34,7 @@ VERILATOR_FLAGS =
# Generate C++
VERILATOR_FLAGS += -cc
# Optimize
VERILATOR_FLAGS += -O2 -x-assign 0
VERILATOR_FLAGS += -Os -x-assign 0
# Warn abount lint issues; may not want this on less solid designs
VERILATOR_FLAGS += -Wall
# Make waveforms

View File

@ -38,7 +38,7 @@ VERILATOR_FLAGS += -cc --exe
# Generate makefile dependencies (not shown as complicates the Makefile)
#VERILATOR_FLAGS += -MMD
# Optimize
VERILATOR_FLAGS += -O2 -x-assign 0
VERILATOR_FLAGS += -Os -x-assign 0
# Warn abount lint issues; may not want this on less solid designs
VERILATOR_FLAGS += -Wall
# Make waveforms

View File

@ -38,7 +38,7 @@ endif
# SystemC takes minutes to optimize, thus it is off by default.
OPT_SLOW =
# Fast path optimizations. Most time is spent in these classes.
OPT_FAST = -O2 -fstrict-aliasing
OPT_FAST = -Os -fstrict-aliasing
#OPT_FAST = -O
#OPT_FAST =

View File

@ -38,7 +38,7 @@ VERILATOR_FLAGS += -sc --exe
# Generate makefile dependencies (not shown as complicates the Makefile)
#VERILATOR_FLAGS += -MMD
# Optimize
VERILATOR_FLAGS += -O2 -x-assign 0
VERILATOR_FLAGS += -Os -x-assign 0
# Warn abount lint issues; may not want this on less solid designs
VERILATOR_FLAGS += -Wall
# Make waveforms

View File

@ -46,7 +46,7 @@ endif
# SystemC takes minutes to optimize, thus it is off by default.
OPT_SLOW =
# Fast path optimizations. Most time is spent in these classes.
OPT_FAST = -O2 -fstrict-aliasing
OPT_FAST = -Os -fstrict-aliasing
#OPT_FAST = -O
#OPT_FAST =

View File

@ -86,7 +86,7 @@ LDLIBS += $(VM_USER_LDLIBS)
# SystemC takes minutes to optimize, thus it is off by default.
#OPT_SLOW =
# Fast path optimizations. Most time is spent in these classes.
#OPT_FAST = -O2 -fstrict-aliasing
#OPT_FAST = -Os -fstrict-aliasing
#OPT_FAST = -O
#OPT_FAST =

View File

@ -223,9 +223,12 @@
#ifdef __MINGW32__
# define __USE_MINGW_ANSI_STDIO 1 // Force old MinGW (GCC 5 and older) to use C99 formats
# define __STDC_FORMAT_MACROS 1 // Otherwise MinGW doesn't get PRId64 for fstapi.c
#endif
// The inttypes supplied with some GCC & MINGW32 versions requires STDC_FORMAT_MACROS
// to be declared in order to get the PRIxx macros used by fstapi.c
#define __STDC_FORMAT_MACROS
#if defined(__CYGWIN__)
# include <stdint.h>
@ -273,10 +276,6 @@ typedef signed __int32 ssize_t; ///< signed size_t; returned fro
#else // Linux or compliant Unix flavors, -m64
// The inttypes supplied with some GCC versions requires STDC_FORMAT_MACROS
// to be declared in order to get the PRIxx macros used by fstapi.c
#define __STDC_FORMAT_MACROS
# include <inttypes.h> // Solaris
# include <stdint.h> // Linux and most flavors
# include <sys/types.h> // __WORDSIZE

View File

@ -1282,6 +1282,7 @@ void AstBegin::dump(std::ostream& str) const {
if (unnamed()) str<<" [UNNAMED]";
if (generate()) str<<" [GEN]";
if (genforp()) str<<" [GENFOR]";
if (implied()) str<<" [IMPLIED]";
}
void AstCoverDecl::dump(std::ostream& str) const {
this->AstNode::dump(str);

View File

@ -2335,21 +2335,6 @@ public:
//######################################################################
class AstGenerate : public AstNode {
// A Generate/end block
// Parents: MODULE
// Children: modItems
public:
AstGenerate(FileLine* fl, AstNode* stmtsp)
: ASTGEN_SUPER(fl) {
addNOp1p(stmtsp);
}
ASTNODE_NODE_FUNCS(Generate)
// op1 = Statements
AstNode* stmtsp() const { return op1p(); } // op1 = List of statements
void addStmtp(AstNode* nodep) { addOp1p(nodep); }
};
class AstParseRef : public AstNode {
// A reference to a variable, function or task
// We don't know which at parse time due to bison constraints
@ -3754,16 +3739,19 @@ class AstBegin : public AstNode {
// Children: statements
private:
string m_name; // Name of block
bool m_unnamed; // Originally unnamed
bool m_unnamed; // Originally unnamed (name change does not affect this)
bool m_generate; // Underneath a generate
bool m_implied; // Not inserted by user
public:
// Node that simply puts name into the output stream
AstBegin(FileLine* fl, const string& name, AstNode* stmtsp, bool generate=false)
AstBegin(FileLine* fl, const string& name, AstNode* stmtsp, bool generate = false,
bool implied = false)
: ASTGEN_SUPER(fl)
, m_name(name) {
addNOp1p(stmtsp);
m_unnamed = (name=="");
m_unnamed = (name == "");
m_generate = generate;
m_implied = implied;
}
ASTNODE_NODE_FUNCS(Begin)
virtual void dump(std::ostream& str) const;
@ -3778,6 +3766,7 @@ public:
bool unnamed() const { return m_unnamed; }
void generate(bool flag) { m_generate = flag; }
bool generate() const { return m_generate; }
bool implied() const { return m_implied; }
};
class AstInitial : public AstNode {

View File

@ -125,7 +125,7 @@ private:
while ((pos=dottedname.find("__DOT__")) != string::npos) {
string ident = dottedname.substr(0, pos);
dottedname = dottedname.substr(pos+strlen("__DOT__"));
if (!nodep->unnamed()) {
if (nodep->name() != "") {
if (m_namedScope=="") m_namedScope = ident;
else m_namedScope = m_namedScope + "__DOT__"+ident;
}

View File

@ -76,7 +76,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
}
virtual void visit(AstBegin* nodep) VL_OVERRIDE {
if (nodep->unnamed()) {
if (nodep->name() == "") {
putbs("begin\n");
} else {
putbs("begin : "+nodep->name()+"\n");
@ -84,11 +84,6 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
iterateChildren(nodep);
puts("end\n");
}
virtual void visit(AstGenerate* nodep) VL_OVERRIDE {
putfs(nodep, "generate\n");
iterateChildren(nodep);
putqs(nodep, "end\n");
}
virtual void visit(AstFinal* nodep) VL_OVERRIDE {
putfs(nodep, "final begin\n");
iterateChildren(nodep);

View File

@ -683,7 +683,6 @@ class LinkDotFindVisitor : public AstNVisitor {
string m_scope; // Scope text
AstBegin* m_beginp; // Current Begin/end block
AstNodeFTask* m_ftaskp; // Current function/task
bool m_inGenerate; // Inside a generate
bool m_inRecursion; // Inside a recursive module
int m_paramNum; // Parameter number, for position based connection
int m_beginNum; // Begin block number, 0=none seen
@ -891,16 +890,6 @@ class LinkDotFindVisitor : public AstNVisitor {
nodep->user1p(m_curSymp);
iterateChildren(nodep);
}
virtual void visit(AstGenerate* nodep) VL_OVERRIDE {
// Begin: ... blocks often replicate under genif/genfor, so simply
// suppress duplicate checks. See t_gen_forif.v for an example.
bool lastInGen = m_inGenerate;
{
m_inGenerate = true;
iterateChildren(nodep);
}
m_inGenerate = lastInGen;
}
virtual void visit(AstBegin* nodep) VL_OVERRIDE {
UINFO(5," "<<nodep<<endl);
// Rename "genblk"s to include a number
@ -909,9 +898,6 @@ class LinkDotFindVisitor : public AstNVisitor {
++m_beginNum;
nodep->name(nodep->name()+cvtToStr(m_beginNum));
}
// Just for loop index, make special name. The [00] is so it will "dearray" to same
// name as after we expand the GENFOR
if (nodep->genforp()) nodep->name(nodep->name());
}
// All blocks are numbered in the standard, IE we start with "genblk1" even if only one.
if (nodep->name()=="" && nodep->unnamed()) {
@ -928,20 +914,24 @@ class LinkDotFindVisitor : public AstNVisitor {
}
}
}
int oldNum = m_beginNum;
AstBegin* oldbegin = m_beginp;
VSymEnt* oldCurSymp = m_curSymp;
{
m_beginNum = 0;
m_beginp = nodep;
m_curSymp = m_statep->insertBlock(m_curSymp, nodep->name(), nodep, m_packagep);
m_curSymp->fallbackp(oldCurSymp);
// Iterate
if (nodep->name() == "") {
iterateChildren(nodep);
} else {
int oldNum = m_beginNum;
AstBegin* oldbegin = m_beginp;
VSymEnt* oldCurSymp = m_curSymp;
{
m_beginNum = 0;
m_beginp = nodep;
m_curSymp = m_statep->insertBlock(m_curSymp, nodep->name(), nodep, m_packagep);
m_curSymp->fallbackp(oldCurSymp);
// Iterate
iterateChildren(nodep);
}
m_curSymp = oldCurSymp;
m_beginp = oldbegin;
m_beginNum = oldNum;
}
m_curSymp = oldCurSymp;
m_beginp = oldbegin;
m_beginNum = oldNum;
}
virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE {
// NodeTask: Remember its name for later resolution
@ -1202,7 +1192,6 @@ public:
m_statep = statep;
m_beginp = NULL;
m_ftaskp = NULL;
m_inGenerate = false;
m_inRecursion = false;
m_paramNum = 0;
m_beginNum = 0;
@ -2470,8 +2459,10 @@ private:
checkNoDot(nodep);
VSymEnt* oldCurSymp = m_curSymp;
{
m_ds.m_dotSymp = m_curSymp = m_statep->getNodeSym(nodep);
UINFO(5," cur=se"<<cvtToHex(m_curSymp)<<endl);
if (nodep->name() != "") {
m_ds.m_dotSymp = m_curSymp = m_statep->getNodeSym(nodep);
UINFO(5," cur=se"<<cvtToHex(m_curSymp)<<endl);
}
iterateChildren(nodep);
}
m_ds.m_dotSymp = m_curSymp = oldCurSymp;

View File

@ -445,7 +445,7 @@ private:
new AstConst(fl, 1),
new AstConst(fl, -1))));
stmtsp->addNext(new AstWhile(fl, condp, newp, incp));
newp = new AstBegin(nodep->fileline(), "", stmtsp);
newp = new AstBegin(nodep->fileline(), "", stmtsp, false, true);
dimension--;
}
//newp->dumpTree(cout, "-foreach-new:");
@ -498,6 +498,21 @@ private:
virtual void visit(AstBegin* nodep) VL_OVERRIDE {
V3Config::applyCoverageBlock(m_modp, nodep);
cleanFileline(nodep);
AstNode* backp = nodep->backp();
// IEEE says directly nested item is not a new block
bool nestedIf = (nodep->implied() // User didn't provide begin/end
&& (VN_IS(nodep->stmtsp(), GenIf)
|| VN_IS(nodep->stmtsp(), GenCase)) // Has an if/case
&& !nodep->stmtsp()->nextp()); // Has only one item
// It's not FOR(BEGIN(...)) but we earlier changed it to BEGIN(FOR(...))
if (nodep->genforp() && nodep->name() == "") {
nodep->name("genblk");
}
else if (nodep->generate() && nodep->name() == ""
&& (VN_IS(backp, CaseItem) || VN_IS(backp, GenIf))
&& !nestedIf) {
nodep->name("genblk");
}
iterateChildren(nodep);
}
virtual void visit(AstCase* nodep) VL_OVERRIDE {

View File

@ -431,20 +431,6 @@ private:
}
// Generate Statements
virtual void visit(AstGenerate* nodep) VL_OVERRIDE {
if (debug()>=9) nodep->dumpTree(cout, "-genin: ");
iterateChildren(nodep);
// After expanding the generate, all statements under it can be moved
// up, and the generate block deleted as it's not relevant
if (AstNode* stmtsp = nodep->stmtsp()) {
stmtsp->unlinkFrBackWithNext();
nodep->replaceWith(stmtsp);
if (debug()>=9) stmtsp->dumpTree(cout, "-genout: ");
} else {
nodep->unlinkFrBack();
}
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
virtual void visit(AstGenIf* nodep) VL_OVERRIDE {
UINFO(9," GENIF "<<nodep<<endl);
iterateAndNextNull(nodep->condp());

View File

@ -353,7 +353,8 @@ class ProtectVisitor : public AstNVisitor {
nodep->v3error("Unsupported: unpacked arrays with protect-lib on "<<nodep->prettyNameQ());
}
if (nodep->direction() == VDirection::INPUT) {
if (nodep->isUsedClock()) {
if (nodep->isUsedClock()
|| nodep->attrClocker() == VVarAttrClocker::CLOCKER_YES) {
handleClock(nodep);
} else {
handleDataInput(nodep);

View File

@ -20,7 +20,7 @@ my $Opt_DistTitle = $ARGV[0] or die "%Error: No disttitle specified,";
my $Opt_DistDate = $ARGV[1] or die "%Error: No distdate specified,";
my $header =
("\\usepackage[left=1.7in,right=1.7in,top=1.3in,bottom=1.3in]{geometry}\n"
("\\usepackage[left=1.0in,right=1.0in,top=1.0in,bottom=1.0in]{geometry}\n"
."\\usepackage[pdftex,bookmarks=true,bookmarksnumbered=true,hypertexnames=false,breaklinks=true,colorlinks=true,linkcolor=blue]{hyperref}\n"
."\\usepackage{fancyhdr} \\pagestyle{fancy}\n"
."\\usepackage{graphicx}\n"

View File

@ -1156,7 +1156,7 @@ interface_item<nodep>: // IEEE: interface_item + non_port_interface_item
;
interface_generate_region<nodep>: // ==IEEE: generate_region
yGENERATE interface_itemList yENDGENERATE { $$ = new AstGenerate($1, $2); }
yGENERATE interface_itemList yENDGENERATE { $$ = $2; }
| yGENERATE yENDGENERATE { $$ = NULL; }
;
@ -2036,7 +2036,7 @@ bind_instantiation<nodep>: // ==IEEE: bind_instantiation
// different, so we copy all rules for checkers.
generate_region<nodep>: // ==IEEE: generate_region
yGENERATE ~c~genItemList yENDGENERATE { $$ = new AstGenerate($1, $2); }
yGENERATE ~c~genItemList yENDGENERATE { $$ = $2; }
| yGENERATE yENDGENERATE { $$ = NULL; }
;
@ -2044,20 +2044,22 @@ generate_region<nodep>: // ==IEEE: generate_region
//UNSUP BISONPRE_COPY(generate_region,{s/~c~/c_/g}) // {copied}
//UNSUP ;
generate_block_or_null<nodep>: // IEEE: generate_block_or_null
generate_block_or_null<nodep>: // IEEE: generate_block_or_null (called from gencase/genif/genfor)
// ';' // is included in
// // IEEE: generate_block
// // Must always return a BEGIN node, or NULL - see GenFor construction
generate_item { $$ = $1 ? (new AstBegin($1->fileline(),"genblk",$1,true)) : NULL; }
generate_item { $$ = $1 ? (new AstBegin($1->fileline(),"",$1,true,true)) : NULL; }
| genItemBegin { $$ = $1; }
;
genItemBegin<nodep>: // IEEE: part of generate_block
yBEGIN ~c~genItemList yEND { $$ = new AstBegin($1,"genblk",$2,true); }
yBEGIN ~c~genItemList yEND { $$ = new AstBegin($1,"",$2,true,false); }
| yBEGIN yEND { $$ = NULL; }
| id ':' yBEGIN ~c~genItemList yEND endLabelE { $$ = new AstBegin($<fl>1,*$1,$4,true); GRAMMARP->endLabel($<fl>6,*$1,$6); }
| id ':' yBEGIN ~c~genItemList yEND endLabelE
{ $$ = new AstBegin($<fl>1,*$1,$4,true,false); GRAMMARP->endLabel($<fl>6,*$1,$6); }
| id ':' yBEGIN yEND endLabelE { $$ = NULL; GRAMMARP->endLabel($<fl>5,*$1,$5); }
| yBEGIN ':' idAny ~c~ genItemList yEND endLabelE { $$ = new AstBegin($<fl>3,*$3,$4,true); GRAMMARP->endLabel($<fl>6,*$3,$6); }
| yBEGIN ':' idAny ~c~genItemList yEND endLabelE
{ $$ = new AstBegin($<fl>3,*$3,$4,true,false); GRAMMARP->endLabel($<fl>6,*$3,$6); }
| yBEGIN ':' idAny yEND endLabelE { $$ = NULL; GRAMMARP->endLabel($<fl>5,*$3,$5); }
;
@ -2115,11 +2117,11 @@ loop_generate_construct<nodep>: // ==IEEE: loop_generate_construct
{ // Convert BEGIN(...) to BEGIN(GENFOR(...)), as we need the BEGIN to hide the local genvar
AstBegin* lowerBegp = VN_CAST($9, Begin);
UASSERT_OBJ(!($9 && !lowerBegp), $9, "Child of GENFOR should have been begin");
if (!lowerBegp) lowerBegp = new AstBegin($1,"genblk",NULL,true); // Empty body
if (!lowerBegp) lowerBegp = new AstBegin($1, "genblk", NULL, true, true); // Empty body
AstNode* lowerNoBegp = lowerBegp->stmtsp();
if (lowerNoBegp) lowerNoBegp->unlinkFrBackWithNext();
//
AstBegin* blkp = new AstBegin($1,lowerBegp->name(),NULL,true);
AstBegin* blkp = new AstBegin($1, lowerBegp->name(), NULL, true, true);
// V3LinkDot detects BEGIN(GENFOR(...)) as a special case
AstNode* initp = $3; AstNode* varp = $3;
if (VN_IS(varp, Var)) { // Genvar
@ -2793,10 +2795,10 @@ statement_item<nodep>: // IEEE: statement_item
statementFor<beginp>: // IEEE: part of statement
yFOR '(' for_initialization expr ';' for_stepE ')' stmtBlock
{ $$ = new AstBegin($1,"",$3);
{ $$ = new AstBegin($1, "", $3, false, true);
$$->addStmtsp(new AstWhile($1, $4,$8,$6)); }
| yFOR '(' for_initialization ';' for_stepE ')' stmtBlock
{ $$ = new AstBegin($1,"",$3);
{ $$ = new AstBegin($1, "", $3, false, true);
$$->addStmtsp(new AstWhile($1, new AstConst($1,AstConst::LogicTrue()),$7,$5)); }
;
@ -4473,7 +4475,7 @@ assertion_item<nodep>: // ==IEEE: assertion_item
deferred_immediate_assertion_item<nodep>: // ==IEEE: deferred_immediate_assertion_item
deferred_immediate_assertion_statement { $$ = $1; }
| id/*block_identifier*/ ':' deferred_immediate_assertion_statement
{ $$ = new AstBegin($<fl>1, *$1, $3); }
{ $$ = new AstBegin($<fl>1, *$1, $3, false, true); }
;
procedural_assertion_statement<nodep>: // ==IEEE: procedural_assertion_statement
@ -4528,7 +4530,8 @@ deferred_immediate_assertion_statement<nodep>: // ==IEEE: deferred_immediate_ass
concurrent_assertion_item<nodep>: // IEEE: concurrent_assertion_item
concurrent_assertion_statement { $$ = $1; }
| id/*block_identifier*/ ':' concurrent_assertion_statement { $$ = new AstBegin($<fl>1, *$1, $3); }
| id/*block_identifier*/ ':' concurrent_assertion_statement
{ $$ = new AstBegin($<fl>1, *$1, $3, false, true); }
// // IEEE: checker_instantiation
// // identical to module_instantiation; see etcInst
;

View File

@ -1048,7 +1048,7 @@ sub compile {
"-DTEST_VERBOSE=\"".($self->{verbose} ? 1 : 0)."\"",
"-DTEST_SYSTEMC=\"" .($self->sc ? 1 : 0). "\"",
"-DCMAKE_PREFIX_PATH=\"".(($ENV{SYSTEMC_INCLUDE}||$ENV{SYSTEMC}||'')."/..\""),
"-DTEST_OPT_FAST=\"" . ($param{benchmark}?"-O2":"") . "\"",
"-DTEST_OPT_FAST=\"" . ($param{benchmark} ? "-Os" : "") . "\"",
"-DTEST_VERILATION=\"" . $::Opt_Verilation . "\"",
]);
return 1 if $self->errors || $self->skips || $self->unsupporteds;
@ -1066,7 +1066,7 @@ sub compile {
"TEST_OBJ_DIR=$self->{obj_dir}",
"CPPFLAGS_DRIVER=-D".uc($self->{name}),
($self->{verbose} ? "CPPFLAGS_DRIVER2=-DTEST_VERBOSE=1":""),
($param{benchmark}?"OPT_FAST=-O2":""),
($param{benchmark} ? "OPT_FAST=-Os" : ""),
"$self->{VM_PREFIX}", # bypass default rule, as we don't need archive
($param{make_flags}||""),
]);

View File

@ -0,0 +1,6 @@
010: exp=top.t.show0 got=top.t.show0
014: exp=top.t.genblk1.show1 got=top.t.genblk1.show1
018: exp=top.t.genblk2.show2 got=top.t.genblk2.show2
023: exp=top.t.genblk3.genblk1.show3 got=top.t.genblk3.genblk1.show3
029: exp=top.t.x1.x3.show4 got=top.t.x1.x3.show4
*-* All Finished *-*

20
test_regress/t/t_gen_genblk.pl Executable file
View File

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

View File

@ -0,0 +1,51 @@
module t (/*AUTOARG*/
// Inputs
clk, reset_l
);
input clk;
input reset_l;
generate
show #(`__LINE__, "top.t.show0") show0();
if (0) ;
else if (0) ;
else if (1) show #(`__LINE__, "top.t.genblk1.show1") show1();
if (0) begin end
else if (0) begin end
else if (1) begin show #(`__LINE__, "top.t.genblk2.show2") show2(); end
if (0) ;
else begin
if (0) begin end
else if (1) begin show #(`__LINE__, "top.t.genblk3.genblk1.show3") show3(); end
end
if (0) ;
else begin : x1
if (0) begin : x2 end
else if (1) begin : x3 show #(`__LINE__, "top.t.x1.x3.show4") show4(); end
end
endgenerate
int cyc;
always @ (posedge clk) begin
cyc <= cyc + 1;
if (cyc == 99) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
module show #(parameter LINE=0, parameter string EXPT) ();
always @ (posedge t.clk) begin
if (t.cyc == LINE) begin
$display("%03d: exp=%s got=%m", LINE, EXPT);
end
end
endmodule

View File

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

View File

@ -24,7 +24,7 @@ module t();
generate
genvar the_genvar;
begin
begin : ia
for (the_genvar = 0; the_genvar < 2; the_genvar++) begin : TestIf
begin
assign my_intf[the_genvar].val = '1;
@ -36,7 +36,7 @@ module t();
generate
genvar the_second_genvar;
begin
begin : ib
intf #(.PARAM(1)) my_intf [1:0] ();
for (the_second_genvar = 0; the_second_genvar < 2; the_second_genvar++) begin : TestIf
begin
@ -49,7 +49,7 @@ module t();
generate
genvar the_third_genvar;
begin
begin : ic
for (the_third_genvar = 0; the_third_genvar < 2; the_third_genvar++) begin : TestIf
begin
intf #(.PARAM(1)) my_intf [1:0] ();

View File

@ -14,17 +14,17 @@ if (cyc > 0 && sig``_in != sig``_out) begin \
$stop; \
end
module t (/*AUTOARG*/
// Inputs
clk
);
module t #(parameter GATED_CLK = 0) (/*AUTOARG*/
// Inputs
clk
);
input clk;
localparam last_cyc =
`ifdef TEST_BENCHMARK
`TEST_BENCHMARK;
`TEST_BENCHMARK;
`else
10;
10;
`endif
genvar x;
@ -55,6 +55,8 @@ module t (/*AUTOARG*/
logic [3:0] [31:0] s4x32_in;
logic [3:0] [31:0] s4x32_out;
wire clk_en = crc[0];
secret
secret (
.accum_in,
@ -77,6 +79,7 @@ module t (/*AUTOARG*/
.s129_out,
.s4x32_in,
.s4x32_out,
.clk_en,
.clk);
always @(posedge clk) begin
@ -87,8 +90,6 @@ module t (/*AUTOARG*/
cyc <= cyc + 1;
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
accum_in <= accum_in + 5;
// 7 is the secret_value inside the secret module
accum_out_expect <= accum_in + accum_out_expect + 7;
`DRIVE(s1)
`DRIVE(s2)
`DRIVE(s8)
@ -122,6 +123,22 @@ module t (/*AUTOARG*/
end
end
logic possibly_gated_clk;
if (GATED_CLK != 0) begin: yes_gated_clock
logic clk_en_latch /*verilator clock_enable*/;
/* verilator lint_off COMBDLY */
always_comb if (clk == '0) clk_en_latch <= clk_en;
/* verilator lint_on COMBDLY */
assign possibly_gated_clk = clk & clk_en_latch;
end else begin: no_gated_clock
assign possibly_gated_clk = clk;
end
always @(posedge possibly_gated_clk) begin
// 7 is the secret_value inside the secret module
accum_out_expect <= accum_in + accum_out_expect + 7;
end
always @(*) begin
// XSim (and maybe all event simulators?) sees the moment where
// s1_in has not yet propagated to s1_out, however, they do always

View File

@ -0,0 +1,75 @@
#!/usr/bin/perl
# Makes the test run with tracing enabled by default, can be overridden
# with --notrace
unshift(@ARGV, "--trace");
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2019 by Todd Strader. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
scenarios(
vlt => 1,
xsim => 1,
);
$Self->{sim_time} = $Self->{benchmark} * 100 if $Self->{benchmark};
top_filename("t/t_prot_lib.v");
my $secret_prefix = "secret";
my $secret_dir = "$Self->{obj_dir}/$secret_prefix";
mkdir $secret_dir;
while (1) {
# Always compile the secret file with Verilator no matter what simulator
# we are testing with
run(logfile => "$secret_dir/vlt_compile.log",
cmd => ["perl",
"$ENV{VERILATOR_ROOT}/bin/verilator",
"--prefix",
"Vt_prot_lib_secret",
"-cc",
"-Mdir",
$secret_dir,
"-GGATED_CLK=1",
"--protect-lib",
$secret_prefix,
"t/t_prot_lib_secret.v"]);
last if $Self->{errors};
run(logfile => "$secret_dir/secret_gcc.log",
cmd=>["make",
"-C",
$secret_dir,
"-f",
"Vt_prot_lib_secret.mk"]);
last if $Self->{errors};
compile(
verilator_flags2 => ["$secret_dir/secret.sv",
"-GGATED_CLK=1",
"-LDFLAGS",
"'-L$secret_prefix -lsecret -static'"],
xsim_flags2 => ["$secret_dir/secret.sv"],
);
execute(
check_finished => 1,
xsim_run_flags2 => ["--sv_lib",
"$secret_dir/libsecret",
"--dpi_absolute"],
);
if ($Self->{vlt} && $Self->{trace}) {
# We can see the ports of the secret module
file_grep("$Self->{obj_dir}/simx.vcd", qr/accum_in/);
# but we can't see what's inside
file_grep_not("$Self->{obj_dir}/simx.vcd", qr/secret_/);
}
ok(1);
last;
}
1;

View File

@ -2,35 +2,50 @@
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2019 by Todd Strader.
module secret (
input [31:0] accum_in,
output wire [31:0] accum_out,
input accum_bypass,
output [31:0] accum_bypass_out,
input s1_in,
output logic s1_out,
input [1:0] s2_in,
output logic [1:0] s2_out,
input [7:0] s8_in,
output logic [7:0] s8_out,
input [32:0] s33_in,
output logic [32:0] s33_out,
input [63:0] s64_in,
output logic [63:0] s64_out,
input [64:0] s65_in,
output logic [64:0] s65_out,
input [128:0] s129_in,
output logic [128:0] s129_out,
input [3:0] [31:0] s4x32_in,
output logic [3:0] [31:0] s4x32_out,
input clk);
module secret #(parameter GATED_CLK = 0)
(
input [31:0] accum_in,
output wire [31:0] accum_out,
input accum_bypass,
output [31:0] accum_bypass_out,
input s1_in,
output logic s1_out,
input [1:0] s2_in,
output logic [1:0] s2_out,
input [7:0] s8_in,
output logic [7:0] s8_out,
input [32:0] s33_in,
output logic [32:0] s33_out,
input [63:0] s64_in,
output logic [63:0] s64_out,
input [64:0] s65_in,
output logic [64:0] s65_out,
input [128:0] s129_in,
output logic [128:0] s129_out,
input [3:0] [31:0] s4x32_in,
output logic [3:0] [31:0] s4x32_out,
input clk_en,
input clk /*verilator clocker*/);
logic [31:0] secret_accum_q = 0;
logic [31:0] secret_value = 7;
logic [31:0] secret_accum_q = 0;
logic [31:0] secret_value = 7;
initial $display("created %m");
always @(posedge clk) begin
logic the_clk;
generate
if (GATED_CLK != 0) begin: yes_gated_clock
logic clk_en_latch /*verilator clock_enable*/;
/* verilator lint_off COMBDLY */
always_comb if (clk == '0) clk_en_latch <= clk_en;
/* verilator lint_on COMBDLY */
assign the_clk = clk & clk_en_latch;
end else begin: no_gated_clock
assign the_clk = clk;
end
endgenerate
always @(posedge the_clk) begin
secret_accum_q <= secret_accum_q + accum_in + secret_value;
end

View File

@ -1,173 +0,0 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2006 by Wilson Snyder.
module t (/*AUTOARG*/
// Inputs
clk
);
// verilator lint_off MULTIDRIVEN
wire [31:0] outb0c0;
wire [31:0] outb0c1;
wire [31:0] outb1c0;
wire [31:0] outb1c1;
reg [7:0] lclmem [7:0];
ma ma0 (.outb0c0(outb0c0), .outb0c1(outb0c1),
.outb1c0(outb1c0), .outb1c1(outb1c1)
);
global_mod #(32'hf00d) global_cell ();
global_mod #(32'hf22d) global_cell2 ();
input clk;
integer cyc=1;
always @ (posedge clk) begin
cyc <= cyc + 1;
`ifdef TEST_VERBOSE
$write("[%0t] cyc%0d: %0x %0x %0x %0x\n", $time, cyc, outb0c0, outb0c1, outb1c0, outb1c1);
`endif
if (cyc==2) begin
if (global_cell.globali != 32'hf00d) $stop;
if (global_cell2.globali != 32'hf22d) $stop;
if (outb0c0 != 32'h00) $stop;
if (outb0c1 != 32'h01) $stop;
if (outb1c0 != 32'h10) $stop;
if (outb1c1 != 32'h11) $stop;
end
if (cyc==3) begin
// Can we scope down and read and write vars?
ma0.mb0.mc0.out <= ma0.mb0.mc0.out + 32'h100;
ma0.mb0.mc1.out <= ma0.mb0.mc1.out + 32'h100;
ma0.mb1.mc0.out <= ma0.mb1.mc0.out + 32'h100;
ma0.mb1.mc1.out <= ma0.mb1.mc1.out + 32'h100;
end
if (cyc==4) begin
// Can we do dotted's inside array sels?
ma0.rmtmem[ma0.mb0.mc0.out[2:0]] = 8'h12;
lclmem[ma0.mb0.mc0.out[2:0]] = 8'h24;
if (outb0c0 != 32'h100) $stop;
if (outb0c1 != 32'h101) $stop;
if (outb1c0 != 32'h110) $stop;
if (outb1c1 != 32'h111) $stop;
end
if (cyc==5) begin
if (ma0.rmtmem[ma0.mb0.mc0.out[2:0]] != 8'h12) $stop;
if (lclmem[ma0.mb0.mc0.out[2:0]] != 8'h24) $stop;
if (outb0c0 != 32'h1100) $stop;
if (outb0c1 != 32'h2101) $stop;
if (outb1c0 != 32'h2110) $stop;
if (outb1c1 != 32'h3111) $stop;
end
if (cyc==6) begin
if (outb0c0 != 32'h31100) $stop;
if (outb0c1 != 32'h02101) $stop;
if (outb1c0 != 32'h42110) $stop;
if (outb1c1 != 32'h03111) $stop;
end
if (cyc==9) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
`ifdef USE_INLINE_MID
`define INLINE_MODULE /*verilator inline_module*/
`define INLINE_MID_MODULE /*verilator no_inline_module*/
`else
`ifdef USE_INLINE
`define INLINE_MODULE /*verilator inline_module*/
`define INLINE_MID_MODULE /*verilator inline_module*/
`else
`define INLINE_MODULE /*verilator public_module*/
`define INLINE_MID_MODULE /*verilator public_module*/
`endif
`endif
module global_mod;
`INLINE_MODULE
parameter INITVAL = 0;
integer globali;
initial globali = INITVAL;
endmodule
module ma (
output wire [31:0] outb0c0,
output wire [31:0] outb0c1,
output wire [31:0] outb1c0,
output wire [31:0] outb1c1
);
`INLINE_MODULE
reg [7:0] rmtmem [7:0];
mb #(0) mb0 (.outc0(outb0c0), .outc1(outb0c1));
mb #(1) mb1 (.outc0(outb1c0), .outc1(outb1c1));
endmodule
module mb (
output wire [31:0] outc0,
output wire [31:0] outc1
);
`INLINE_MID_MODULE
parameter P2 = 0;
mc #(P2,0) mc0 (.out(outc0));
mc #(P2,1) mc1 (.out(outc1));
global_mod #(32'hf33d) global_cell2 ();
wire reach_up_clk = t.clk;
always @(reach_up_clk) begin
if (P2==0) begin // Only for mb0
if (outc0 !== t.ma0.mb0.mc0.out) $stop; // Top module name and lower instances
if (outc0 !== ma0.mb0.mc0.out) $stop; // Upper module name and lower instances
if (outc0 !== ma .mb0.mc0.out) $stop; // Upper module name and lower instances
if (outc0 !== mb.mc0.out) $stop; // This module name and lower instances
if (outc0 !== mb0.mc0.out) $stop; // Upper instance name and lower instances
if (outc0 !== mc0.out) $stop; // Lower instances
if (outc1 !== t.ma0.mb0.mc1.out) $stop; // Top module name and lower instances
if (outc1 !== ma0.mb0.mc1.out) $stop; // Upper module name and lower instances
if (outc1 !== ma .mb0.mc1.out) $stop; // Upper module name and lower instances
if (outc1 !== mb.mc1.out) $stop; // This module name and lower instances
if (outc1 !== mb0.mc1.out) $stop; // Upper instance name and lower instances
if (outc1 !== mc1.out) $stop; // Lower instances
end
end
endmodule
module mc (output reg [31:0] out);
`INLINE_MODULE
parameter P2 = 0;
parameter P3 = 0;
initial begin
out = {24'h0,P2[3:0],P3[3:0]};
//$write("%m P2=%0x p3=%0x out=%x\n",P2, P3, out);
end
// Can we look from the top module name down?
wire [31:0] reach_up_cyc = t.cyc;
always @ (posedge t.clk) begin
//$write("[%0t] %m: Got reachup, cyc=%0d\n", $time, reach_up_cyc);
if (reach_up_cyc==2) begin
if (global_cell.globali != 32'hf00d) $stop;
if (global_cell2.globali != 32'hf33d) $stop;
end
if (reach_up_cyc==4) begin
out[15:12] <= {P2[3:0]+P3[3:0]+4'd1};
end
if (reach_up_cyc==5) begin
// Can we set another instance?
if (P3==1) begin // Without this, there are two possible correct answers...
mc0.out[19:16] <= {mc0.out[19:16]+P2[3:0]+P3[3:0]+4'd2};
$display("%m Set %x->%x %x %x %x %x",mc0.out, {mc0.out[19:16]+P2[3:0]+P3[3:0]+4'd2}, mc0.out[19:16],P2[3:0],P3[3:0],4'd2);
end
end
end
endmodule

View File

@ -0,0 +1,173 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2006 by Wilson Snyder.
module t (/*AUTOARG*/
// Inputs
clk
);
// verilator lint_off MULTIDRIVEN
wire [31:0] outb0c0;
wire [31:0] outb0c1;
wire [31:0] outb1c0;
wire [31:0] outb1c1;
reg [7:0] lclmem [7:0];
ma ma0 (.outb0c0(outb0c0), .outb0c1(outb0c1),
.outb1c0(outb1c0), .outb1c1(outb1c1)
);
global_mod #(32'hf00d) global_cell ();
global_mod #(32'hf22d) global_cell2 ();
input clk;
integer cyc=1;
always @ (posedge clk) begin
cyc <= cyc + 1;
`ifdef TEST_VERBOSE
$write("[%0t] cyc%0d: %0x %0x %0x %0x\n", $time, cyc, outb0c0, outb0c1, outb1c0, outb1c1);
`endif
if (cyc==2) begin
if (global_cell.globali != 32'hf00d) $stop;
if (global_cell2.globali != 32'hf22d) $stop;
if (outb0c0 != 32'h00) $stop;
if (outb0c1 != 32'h01) $stop;
if (outb1c0 != 32'h10) $stop;
if (outb1c1 != 32'h11) $stop;
end
if (cyc==3) begin
// Can we scope down and read and write vars?
ma0.mb0.mc0.out <= ma0.mb0.mc0.out + 32'h100;
ma0.mb0.mc1.out <= ma0.mb0.mc1.out + 32'h100;
ma0.mb1.mc0.out <= ma0.mb1.mc0.out + 32'h100;
ma0.mb1.mc1.out <= ma0.mb1.mc1.out + 32'h100;
end
if (cyc==4) begin
// Can we do dotted's inside array sels?
ma0.rmtmem[ma0.mb0.mc0.out[2:0]] = 8'h12;
lclmem[ma0.mb0.mc0.out[2:0]] = 8'h24;
if (outb0c0 != 32'h100) $stop;
if (outb0c1 != 32'h101) $stop;
if (outb1c0 != 32'h110) $stop;
if (outb1c1 != 32'h111) $stop;
end
if (cyc==5) begin
if (ma0.rmtmem[ma0.mb0.mc0.out[2:0]] != 8'h12) $stop;
if (lclmem[ma0.mb0.mc0.out[2:0]] != 8'h24) $stop;
if (outb0c0 != 32'h1100) $stop;
if (outb0c1 != 32'h2101) $stop;
if (outb1c0 != 32'h2110) $stop;
if (outb1c1 != 32'h3111) $stop;
end
if (cyc==6) begin
if (outb0c0 != 32'h31100) $stop;
if (outb0c1 != 32'h02101) $stop;
if (outb1c0 != 32'h42110) $stop;
if (outb1c1 != 32'h03111) $stop;
end
if (cyc==9) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
`ifdef USE_INLINE_MID
`define INLINE_MODULE /*verilator inline_module*/
`define INLINE_MID_MODULE /*verilator no_inline_module*/
`else
`ifdef USE_INLINE
`define INLINE_MODULE /*verilator inline_module*/
`define INLINE_MID_MODULE /*verilator inline_module*/
`else
`define INLINE_MODULE /*verilator public_module*/
`define INLINE_MID_MODULE /*verilator public_module*/
`endif
`endif
module global_mod;
`INLINE_MODULE
parameter INITVAL = 0;
integer globali;
initial globali = INITVAL;
endmodule
module ma (
output wire [31:0] outb0c0,
output wire [31:0] outb0c1,
output wire [31:0] outb1c0,
output wire [31:0] outb1c1
);
`INLINE_MODULE
reg [7:0] rmtmem [7:0];
mb #(0) mb0 (.outc0(outb0c0), .outc1(outb0c1));
mb #(1) mb1 (.outc0(outb1c0), .outc1(outb1c1));
endmodule
module mb (
output wire [31:0] outc0,
output wire [31:0] outc1
);
`INLINE_MID_MODULE
parameter P2 = 0;
mc #(P2,0) mc0 (.out(outc0));
mc #(P2,1) mc1 (.out(outc1));
global_mod #(32'hf33d) global_cell2 ();
wire reach_up_clk = t.clk;
always @(reach_up_clk) begin
if (P2==0) begin // Only for mb0
if (outc0 !== t.ma0.mb0.mc0.out) $stop; // Top module name and lower instances
if (outc0 !== ma0.mb0.mc0.out) $stop; // Upper module name and lower instances
if (outc0 !== ma .mb0.mc0.out) $stop; // Upper module name and lower instances
if (outc0 !== mb.mc0.out) $stop; // This module name and lower instances
if (outc0 !== mb0.mc0.out) $stop; // Upper instance name and lower instances
if (outc0 !== mc0.out) $stop; // Lower instances
if (outc1 !== t.ma0.mb0.mc1.out) $stop; // Top module name and lower instances
if (outc1 !== ma0.mb0.mc1.out) $stop; // Upper module name and lower instances
if (outc1 !== ma .mb0.mc1.out) $stop; // Upper module name and lower instances
if (outc1 !== mb.mc1.out) $stop; // This module name and lower instances
if (outc1 !== mb0.mc1.out) $stop; // Upper instance name and lower instances
if (outc1 !== mc1.out) $stop; // Lower instances
end
end
endmodule
module mc (output reg [31:0] out);
`INLINE_MODULE
parameter P2 = 0;
parameter P3 = 0;
initial begin
out = {24'h0,P2[3:0],P3[3:0]};
//$write("%m P2=%0x p3=%0x out=%x\n",P2, P3, out);
end
// Can we look from the top module name down?
wire [31:0] reach_up_cyc = t.cyc;
always @ (posedge t.clk) begin
//$write("[%0t] %m: Got reachup, cyc=%0d\n", $time, reach_up_cyc);
if (reach_up_cyc==2) begin
if (global_cell.globali != 32'hf00d) $stop;
if (global_cell2.globali != 32'hf33d) $stop;
end
if (reach_up_cyc==4) begin
out[15:12] <= {P2[3:0]+P3[3:0]+4'd1};
end
if (reach_up_cyc==5) begin
// Can we set another instance?
if (P3==1) begin // Without this, there are two possible correct answers...
mc0.out[19:16] <= {mc0.out[19:16]+P2[3:0]+P3[3:0]+4'd2};
$display("%m Set %x->%x %x %x %x %x",mc0.out, {mc0.out[19:16]+P2[3:0]+P3[3:0]+4'd2}, mc0.out[19:16],P2[3:0],P3[3:0],4'd2);
end
end
end
endmodule

View File

@ -9,7 +9,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
scenarios(simulator => 1);
top_filename("t/t_var_dotted.v");
top_filename("t/t_var_dotted1.v");
compile(
v_flags2 => ['+define+NOUSE_INLINE',],

View File

@ -9,7 +9,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
scenarios(simulator => 1);
top_filename("t/t_var_dotted.v");
top_filename("t/t_var_dotted1.v");
compile(
v_flags2 => ['+define+USE_INLINE',],

View File

@ -9,7 +9,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
scenarios(simulator => 1);
top_filename("t/t_var_dotted.v");
top_filename("t/t_var_dotted1.v");
compile(
v_flags2 => ['+define+USE_INLINE_MID',],

View File

@ -0,0 +1,131 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty 2020 by Wilson Snyder.
`ifdef USE_INLINE
`define INLINE_MODULE /*verilator inline_module*/
`else
`define INLINE_MODULE /*verilator public_module*/
`endif
module t (/*AUTOARG*/);
`define DRAM1(bank) mem.mem_bank[bank].dccm.dccm_bank.ram_core
`define DRAM2(bank) mem.mem_bank2[bank].dccm.dccm_bank.ram_core
`define DRAM3(bank) mem.mem_bank3[bank].dccm.dccm_bank.ram_core
`define DRAM4(bank) mem.sub4.mem_bank4[bank].dccm.dccm_bank.ram_core
initial begin
`DRAM1(0)[3] = 130;
`DRAM1(1)[3] = 131;
`DRAM2(0)[3] = 230;
`DRAM2(1)[3] = 231;
`DRAM3(0)[3] = 330;
`DRAM3(1)[3] = 331;
`DRAM4(0)[3] = 430;
`DRAM4(1)[3] = 431;
if (`DRAM1(0)[3] !== 130) $stop;
if (`DRAM1(1)[3] !== 131) $stop;
if (`DRAM2(0)[3] !== 230) $stop;
if (`DRAM2(1)[3] !== 231) $stop;
if (`DRAM3(0)[3] !== 330) $stop;
if (`DRAM3(1)[3] !== 331) $stop;
if (`DRAM4(0)[3] !== 430) $stop;
if (`DRAM4(1)[3] !== 431) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
eh2_lsu_dccm_mem mem (/*AUTOINST*/);
endmodule
module eh2_lsu_dccm_mem
#(
DCCM_INDEX_DEPTH = 8192,
DCCM_NUM_BANKS = 2
)(
);
`INLINE_MODULE
// 8 Banks, 16KB each (2048 x 72)
for (genvar i=0; i<DCCM_NUM_BANKS; i++) begin: mem_bank
if (DCCM_INDEX_DEPTH == 16384) begin : dccm
eh2_ram
#(.depth(16384), .width(32))
dccm_bank (.*);
end
else if (DCCM_INDEX_DEPTH == 8192) begin : dccm
eh2_ram
#(.depth(8192), .width(32))
dccm_bank (.*);
end
else if (DCCM_INDEX_DEPTH == 4096) begin : dccm
eh2_ram
#(.depth(4096), .width(32))
dccm_bank (.*);
end
end : mem_bank
// Check that generate doesn't also add a genblk
generate
for (genvar i=0; i<DCCM_NUM_BANKS; i++) begin: mem_bank2
if (DCCM_INDEX_DEPTH == 8192) begin : dccm
eh2_ram
#(.depth(8192), .width(32))
dccm_bank (.*);
end
end
endgenerate
// Nor this
generate
begin
for (genvar i=0; i<DCCM_NUM_BANKS; i++) begin: mem_bank3
if (DCCM_INDEX_DEPTH == 8192) begin : dccm
eh2_ram
#(.depth(8192), .width(32))
dccm_bank (.*);
end
end
end
endgenerate
// This does
generate
begin : sub4
for (genvar i=0; i<DCCM_NUM_BANKS; i++) begin: mem_bank4
if (DCCM_INDEX_DEPTH == 8192) begin : dccm
eh2_ram
#(.depth(8192), .width(32))
dccm_bank (.*);
end
end
end
endgenerate
// This is an error (previously declared)
//generate
// begin
// eh2_ram
// #(.depth(8192), .width(32))
// dccm_bank (.*);
// end
// begin
// eh2_ram
// #(.depth(8192), .width(32))
// dccm_bank (.*);
// end
//endgenerate
endmodule
module eh2_ram #(depth=4096, width=39)
();
`INLINE_MODULE
reg [(width-1):0] ram_core [(depth-1):0];
endmodule

View File

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

View File

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

View File

@ -0,0 +1,7 @@
%Error: t/t_var_dotted_dup_bad.v:13: Duplicate declaration of cell: 'dccm_bank'
eh2_ram dccm_bank (.*);
^~~~~~~~~
t/t_var_dotted_dup_bad.v:10: ... Location of original declaration
eh2_ram dccm_bank (.*);
^~~~~~~~~
%Error: Exiting due to

View File

@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2005 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
scenarios(vlt => 1);
lint(
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,20 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty 2020 by Wilson Snyder.
module t (/*AUTOARG*/);
generate
begin
eh2_ram dccm_bank (.*);
end
begin
eh2_ram dccm_bank (.*); // Error: duplicate
end
endgenerate
endmodule
module eh2_ram ();
endmodule

View File

@ -1,9 +1,9 @@
ingen: {mod}.genblk1 top.t.genblk1
d3a: {mod}.d3nameda top.t.d3nameda
b2: {mod} top.t
b3n: {mod}.b3named: top.t.b3named
b3: {mod} top.t
b4: {mod} top.t
d3a: {mod}.d3nameda top.t.unnamedblk1.d3nameda
b2: {mod} top.t.unnamedblk2
b3n: {mod}.b3named: top.t.unnamedblk2.b3named
b3: {mod} top.t.unnamedblk2.unnamedblk3
b4: {mod} top.t.unnamedblk2.unnamedblk3.unnamedblk4
t1 {mod}.tsk top.t
t2 {mod}.tsk top.t
t2 {mod}.tsk top.t.unnamedblk7
*-* All Finished *-*

View File

@ -13,7 +13,7 @@
: ... Suggested alternative: 'notfuncs'
i = sub.nofuncs();
^~~~~~~
... Known scopes under 'nofuncs': <no cells found>
... Known scopes under 'nofuncs': sub
%Error: t/t_var_notfound_bad.v:21: Can't find definition of task/function: 'notask'
: ... Suggested alternative: 'nottask'
notask();