[Pkg-electronics-commits] [verilator] 01/01: Imported Upstream version 3.866
أحمد المحمودي (Ahmed El-Mahmoudy)
aelmahmoudy at sabily.org
Wed Nov 26 11:08:59 UTC 2014
This is an automated email from the git hooks/post-receive script.
aelmahmoudy-guest pushed a commit to branch upstream
in repository verilator.
commit 4e4068dbf5d15dec088c1f8bfffc294f7235d298
Author: أحمد المحمودي (Ahmed El-Mahmoudy) <aelmahmoudy at users.sourceforge.net>
Date: Wed Nov 26 09:20:18 2014 +0200
Imported Upstream version 3.866
---
Changes | 27 ++++
README.pdf | Bin 112602 -> 112209 bytes
bin/verilator | 42 ++++--
configure | 18 +--
configure.ac | 2 +-
include/verilated_config.h | 2 +-
include/verilated_vcd_c.cpp | 21 ++-
include/verilated_vcd_c.h | 17 ++-
internals.pdf | Bin 197894 -> 197500 bytes
src/V3Ast.cpp | 19 ++-
src/V3Ast.h | 13 +-
src/V3AstNodes.cpp | 4 +
src/V3AstNodes.h | 31 ++++-
src/V3Clean.cpp | 4 +
src/V3Const.cpp | 148 ++++++++++++++++++++-
src/V3Dead.cpp | 16 +++
src/V3EmitC.cpp | 36 ++++-
src/V3Gate.cpp | 131 +++++++++++++++++-
src/V3Inline.cpp | 1 +
src/V3LinkParse.cpp | 21 ++-
src/V3Options.cpp | 34 +++--
src/V3Options.h | 4 +-
src/V3PreLex.h | 2 +
src/V3PreLex.l | 7 +-
src/V3Premit.cpp | 2 +-
src/V3Scope.cpp | 5 +-
src/V3Table.cpp | 2 +-
src/V3TraceDecl.cpp | 14 +-
src/V3Unknown.cpp | 10 +-
src/V3Unroll.cpp | 40 ++++--
src/V3Width.cpp | 2 +-
src/config_build.h | 2 +-
src/config_rev.h | 2 +-
src/verilog.y | 49 +++++--
.../t/{t_param_public.pl => t_cellarray.pl} | 11 +-
test_regress/t/t_cellarray.v | 100 ++++++++++++++
.../t/{t_param_public.pl => t_concat_opt.pl} | 8 +-
test_regress/t/t_concat_opt.v | 71 ++++++++++
test_regress/t/t_enum_public.cpp | 26 ++++
.../t/{t_param_public.pl => t_enum_public.pl} | 12 +-
test_regress/t/t_enum_public.v | 33 +++++
.../t/{t_param_public.pl => t_flag_define.pl} | 3 +-
test_regress/t/t_flag_define.v | 61 +++++++++
test_regress/t/t_flag_define.vc | 7 +
test_regress/t/t_math_signed5.v | 11 ++
test_regress/t/t_param_public.cpp | 24 ++++
test_regress/t/t_param_public.pl | 12 +-
test_regress/t/t_param_public.v | 5 +
test_regress/t/t_preproc.out | 6 +-
test_regress/t/t_preproc.v | 4 +
.../t/{t_param_public.pl => t_select_bound1.pl} | 0
test_regress/t/t_select_bound1.v | 91 +++++++++++++
.../t/{t_param_public.pl => t_select_bound2.pl} | 0
test_regress/t/t_select_bound2.v | 91 +++++++++++++
test_regress/t/t_select_plus.v | 2 +-
.../t/{t_param_public.pl => t_trace_array.pl} | 5 +-
test_regress/t/t_trace_array.v | 26 ++++
test_regress/t/t_trace_ena.v | 8 ++
test_regress/t/t_trace_ena_cc.pl | 1 +
.../t/{t_param_public.pl => t_trace_primitive.pl} | 7 +-
test_regress/t/t_trace_primitive.v | 43 ++++++
.../t/{t_param_public.pl => t_unroll_genf.pl} | 0
test_regress/t/t_unroll_genf.v | 29 ++++
verilator.1 | 49 ++++---
verilator.html | 43 ++++--
verilator.pdf | Bin 388497 -> 389398 bytes
verilator.txt | 42 +++---
67 files changed, 1384 insertions(+), 175 deletions(-)
diff --git a/Changes b/Changes
index 5d56f16..d6a81dd 100644
--- a/Changes
+++ b/Changes
@@ -3,6 +3,33 @@ 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.866 2014-11-15
+
+*** Fix +define+A+B to define A and B to match other simulators, bug847. [Adam Krolnik]
+
+*** Add optimization of wires from arrayed cells, msg1447. [Jie Xu]
+
+*** Add optimization of operators between concats, msg1447. [Jie Xu]
+
+*** Add public enums, bug833. [Jonathon Donaldson]
+
+*** Trace_off now operates on cells, bug826. [Lane Brooks]
+
+**** Fix public parameters in unused packages, bug804. [Jonathon Donaldson]
+
+**** Fix select when partially out-of-bound, bug823. [Cliffort Wolf]
+
+**** Fix generate unrolling with function call, bug830. [Steven Slatter]
+
+**** Fix cast-to-size context-determined sizing, bug828. [Geoff Barrett]
+
+**** Fix not tracing modules following primitives, bug837. [Jie Xu]
+
+**** Fix trace overflow on huge arrays, bug834. [Geoff Barrett]
+
+**** Fix quoted comment slashes in defines, bug845. [Adam Krolnik]
+
+
* Verilator 3.864 2014-09-21
*** Support power operator with real, bug809. [Jonathon Donaldson]
diff --git a/README.pdf b/README.pdf
index 3157273..23a73fc 100644
Binary files a/README.pdf and b/README.pdf differ
diff --git a/bin/verilator b/bin/verilator
index 004a2ce..59f2e1c 100755
--- a/bin/verilator
+++ b/bin/verilator
@@ -267,7 +267,7 @@ descriptions in the next sections for more information.
--debugi <level> Enable debugging at a specified level
--debugi-<srcfile> <level> Enable debugging a source file at a level
--default-language <lang> Default language to parse
- +define+<var>+<value> Set preprocessor define
+ +define+<var>=<value> Set preprocessor define
--dump-tree Enable dumping .tree files
--dump-treei <level> Enable dumping .tree files at a level
-E Preprocess, but do not compile
@@ -572,13 +572,16 @@ the comment "DefaultClock":
=item -DI<var>=I<value>
-Defines the given preprocessor symbol. Same as +define; +define is fairly
-standard across Verilog tools while -D is an alias for GCC compatibility.
+Defines the given preprocessor symbol, without allowing. Similar to
++define; +define is fairly standard across Verilog tools while -D is an
+alias for GCC compatibility.
=item --debug
Select the debug built image of Verilator (if available), and enable more
-internal assertions, debugging messages, and intermediate form dump files.
+internal assertions (equivelent to C<--debug-check>), debugging messages
+(equivelent to C<--debugi 4>), and intermediate form dump files (equivilent
+to C<--dump-tree>).
=item --debug-check
@@ -590,9 +593,9 @@ changing debug verbosity. Enabled automatically when --debug specified.
=item --debugi-<srcfile> <level>
Rarely needed - for developer use. Set internal debugging level globally
-to the specified debug level (1-10) or set the specified source file to the
-specified level. Higher levels produce more detailed messages (plain
-C<--debug> is equivalent to C<--debugi 4>).
+to the specified debug level (1-10) or set the specified Verilator source
+file to the specified level (e.g. C<--debugi-V3Width 9>). Higher levels
+produce more detailed messages.
=item --default-language I<value>
@@ -613,10 +616,13 @@ used.
If no language is specified, either by this flag or +I<lang>ext+ options,
then the latest SystemVerilog language (IEEE 1800-2012) is used.
-=item +define+I<var>+I<value>
+=item +define+I<var>=I<value>
-Defines the given preprocessor symbol. Same as -D; +define is fairly
-standard across Verilog tools while -D is an alias for GCC compatibility.
+=item +define+I<var>=I<value>+I<var2>=I<value2>...
+
+Defines the given preprocessor symbol, or multiple symbols if separated by
+plusses. Similar to -D; +define is fairly standard across Verilog tools
+while -D is an alias for GCC compatibility.
=item --dump-tree
@@ -2249,6 +2255,14 @@ 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 public*/ (typedef enum)
+
+Used after an enum typedef declaration to indicate the emitted C code
+should have the enum values visible. Due to C++ language restrictions, this
+may only be used on 64-bit or narrower integral enumerations.
+
+ typedef enum logic [2:0] { ZERO = 3'b0 } pub_t /*verilator public*/;
+
=item /*verilator public*/ (variable)
Used after an input, output, register, or wire declaration to indicate the
@@ -2336,12 +2350,14 @@ behavior. See the test_regress/t/t_dpi_display.v file for an example.
=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.
+module, or cells below this module. Often this is placed just after a
+primitive's module statement, so that the entire module and cells below it
+are not traced.
=item /*verilator tracing_on*/
-Re-enable waveform tracing for all future signals that are declared.
+Re-enable waveform tracing for all future signals or cells that are
+declared.
=back
diff --git a/configure b/configure
index 7ac9203..2d8c517 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.68 for Verilator 3.864 2014-09-21.
+# Generated by GNU Autoconf 2.68 for Verilator 3.866 2014-11-15.
#
#
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -557,8 +557,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='Verilator'
PACKAGE_TARNAME='verilator'
-PACKAGE_VERSION='3.864 2014-09-21'
-PACKAGE_STRING='Verilator 3.864 2014-09-21'
+PACKAGE_VERSION='3.866 2014-11-15'
+PACKAGE_STRING='Verilator 3.866 2014-11-15'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -1223,7 +1223,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures Verilator 3.864 2014-09-21 to adapt to many kinds of systems.
+\`configure' configures Verilator 3.866 2014-11-15 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1284,7 +1284,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of Verilator 3.864 2014-09-21:";;
+ short | recursive ) echo "Configuration of Verilator 3.866 2014-11-15:";;
esac
cat <<\_ACEOF
@@ -1376,7 +1376,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-Verilator configure 3.864 2014-09-21
+Verilator configure 3.866 2014-11-15
generated by GNU Autoconf 2.68
Copyright (C) 2010 Free Software Foundation, Inc.
@@ -1633,7 +1633,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by Verilator $as_me 3.864 2014-09-21, which was
+It was created by Verilator $as_me 3.866 2014-11-15, which was
generated by GNU Autoconf 2.68. Invocation command line was
$ $0 $@
@@ -4625,7 +4625,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by Verilator $as_me 3.864 2014-09-21, which was
+This file was extended by Verilator $as_me 3.866 2014-11-15, which was
generated by GNU Autoconf 2.68. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -4687,7 +4687,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-Verilator config.status 3.864 2014-09-21
+Verilator config.status 3.866 2014-11-15
configured by $0, generated by GNU Autoconf 2.68,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index 3f4c4bc..21386f3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6,7 +6,7 @@
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
#AC_INIT([Verilator],[#.### devel])
-AC_INIT([Verilator],[3.864 2014-09-21])
+AC_INIT([Verilator],[3.866 2014-11-15])
AC_CONFIG_HEADER(src/config_build.h)
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk include/verilated_config.h)
diff --git a/include/verilated_config.h b/include/verilated_config.h
index ef38823..1bbe02c 100644
--- a/include/verilated_config.h
+++ b/include/verilated_config.h
@@ -25,4 +25,4 @@
// Autoconf substitutes this with the strings from AC_INIT.
#define VERILATOR_PRODUCT "Verilator"
-#define VERILATOR_VERSION "3.864 2014-09-21"
+#define VERILATOR_VERSION "3.866 2014-11-15"
diff --git a/include/verilated_vcd_c.cpp b/include/verilated_vcd_c.cpp
index 3919c40..8aa36e2 100644
--- a/include/verilated_vcd_c.cpp
+++ b/include/verilated_vcd_c.cpp
@@ -261,6 +261,20 @@ void VerilatedVcd::printTime (vluint64_t timeui) {
printQuad(timeui);
}
+void VerilatedVcd::bufferResize(vluint64_t minsize) {
+ // minsize is size of largest write. We buffer at least 8 times as much data,
+ // writing when we are 3/4 full (with thus 2*minsize remaining free)
+ if (VL_UNLIKELY(minsize > m_wrChunkSize)) {
+ char* oldbufp = m_wrBufp;
+ m_wrChunkSize = minsize*2;
+ m_wrBufp = new char [m_wrChunkSize * 8];
+ memcpy(m_wrBufp, oldbufp, m_writep - oldbufp);
+ m_writep = m_wrBufp + (m_writep - oldbufp);
+ m_wrFlushp = m_wrBufp + m_wrChunkSize * 6;
+ delete oldbufp; oldbufp=NULL;
+ }
+}
+
void VerilatedVcd::bufferFlush () {
// We add output data to m_writep.
// When it gets nearly full we dump it using this routine which calls write()
@@ -444,6 +458,9 @@ void VerilatedVcd::declare (vluint32_t code, const char* name, const char* wirep
m_sigs.reserve(m_nextCode*2); // Power-of-2 allocation speeds things up
}
+ // Make sure write buffer is large enough (one character per bit), plus header
+ bufferResize(bits+1024);
+
// Save declaration info
VerilatedVcdSig sig = VerilatedVcdSig(code, bits);
m_sigs.push_back(sig);
@@ -522,7 +539,7 @@ void VerilatedVcd::declDouble (vluint32_t code, const char* name, int arraynum
void VerilatedVcd::fullDouble (vluint32_t code, const double newval) {
(*((double*)&m_sigs_oldvalp[code])) = newval;
- // Buffer can't overflow; we have at least bufferInsertSize() bytes (>>>16 bytes)
+ // Buffer can't overflow before sprintf; we sized during declaration
sprintf(m_writep, "r%.16g", newval);
m_writep += strlen(m_writep);
*m_writep++=' '; printCode(code); *m_writep++='\n';
@@ -530,7 +547,7 @@ void VerilatedVcd::fullDouble (vluint32_t code, const double newval) {
}
void VerilatedVcd::fullFloat (vluint32_t code, const float newval) {
(*((float*)&m_sigs_oldvalp[code])) = newval;
- // Buffer can't overflow; we have at least bufferInsertSize() bytes (>>>16 bytes)
+ // Buffer can't overflow before sprintf; we sized during declaration
sprintf(m_writep, "r%.16g", (double)newval);
m_writep += strlen(m_writep);
*m_writep++=' '; printCode(code); *m_writep++='\n';
diff --git a/include/verilated_vcd_c.h b/include/verilated_vcd_c.h
index f6c62ef..daf4c3b 100644
--- a/include/verilated_vcd_c.h
+++ b/include/verilated_vcd_c.h
@@ -77,7 +77,9 @@ private:
vluint64_t m_timeLastDump; ///< Last time we did a dump
char* m_wrBufp; ///< Output buffer
+ char* m_wrFlushp; ///< Output buffer flush trigger location
char* m_writep; ///< Write pointer into output buffer
+ vluint64_t m_wrChunkSize; ///< Output buffer size
vluint64_t m_wroteBytes; ///< Number of bytes written to this file
vluint32_t* m_sigs_oldvalp; ///< Pointer to old signal values
@@ -87,13 +89,12 @@ private:
NameMap* m_namemapp; ///< List of names for the header
static vector<VerilatedVcd*> s_vcdVecp; ///< List of all created traces
- inline static size_t bufferSize() { return 256*1024; } // See below for slack calculation
- inline static size_t bufferInsertSize() { return 16*1024; }
+ void bufferResize(vluint64_t minsize);
void bufferFlush();
- void bufferCheck() {
+ inline void bufferCheck() {
// Flush the write buffer if there's not enough space left for new information
// We only call this once per vector, so we need enough slop for a very wide "b###" line
- if (VL_UNLIKELY(m_writep > (m_wrBufp+(bufferSize()-bufferInsertSize())))) {
+ if (VL_UNLIKELY(m_writep > m_wrFlushp)) {
bufferFlush();
}
}
@@ -135,17 +136,19 @@ protected:
public:
// CREATORS
VerilatedVcd () : m_isOpen(false), m_rolloverMB(0), m_modDepth(0), m_nextCode(1) {
- m_wrBufp = new char [bufferSize()];
- m_writep = m_wrBufp;
m_namemapp = NULL;
m_timeRes = m_timeUnit = 1e-9;
m_timeLastDump = 0;
m_sigs_oldvalp = NULL;
m_evcd = false;
m_scopeEscape = '.'; // Backward compatibility
- m_wroteBytes = 0;
m_fd = 0;
m_fullDump = true;
+ m_wrChunkSize = 8*1024;
+ m_wrBufp = new char [m_wrChunkSize*8];
+ m_wrFlushp = m_wrBufp + m_wrChunkSize * 6;
+ m_writep = m_wrBufp;
+ m_wroteBytes = 0;
}
~VerilatedVcd();
diff --git a/internals.pdf b/internals.pdf
index 051d857..1f649cf 100644
Binary files a/internals.pdf and b/internals.pdf differ
diff --git a/src/V3Ast.cpp b/src/V3Ast.cpp
index b3ba3f8..5b980d6 100644
--- a/src/V3Ast.cpp
+++ b/src/V3Ast.cpp
@@ -884,24 +884,21 @@ void AstNode::cloneRelinkTree() {
//======================================================================
// Comparison
-bool AstNode::sameTree(AstNode* node2p) {
- return sameTreeIter(node2p, true);
-}
-
-bool AstNode::sameTreeIter(AstNode* node2p, bool ignNext) {
+bool AstNode::sameTreeIter(AstNode* node2p, bool ignNext, bool gateOnly) {
// Return true if the two trees are identical
if (this==NULL && node2p==NULL) return true;
if (this==NULL || node2p==NULL) return false;
if (this->type() != node2p->type()
|| this->dtypep() != node2p->dtypep()
- || !this->same(node2p)) {
+ || !this->same(node2p)
+ || (gateOnly && !this->isGateOptimizable())) {
return false;
}
- return (this->op1p()->sameTreeIter(node2p->op1p(),false)
- && this->op2p()->sameTreeIter(node2p->op2p(),false)
- && this->op3p()->sameTreeIter(node2p->op3p(),false)
- && this->op4p()->sameTreeIter(node2p->op4p(),false)
- && (ignNext || this->nextp()->sameTreeIter(node2p->nextp(),false))
+ return (this->op1p()->sameTreeIter(node2p->op1p(),false,gateOnly)
+ && this->op2p()->sameTreeIter(node2p->op2p(),false,gateOnly)
+ && this->op3p()->sameTreeIter(node2p->op3p(),false,gateOnly)
+ && this->op4p()->sameTreeIter(node2p->op4p(),false,gateOnly)
+ && (ignNext || this->nextp()->sameTreeIter(node2p->nextp(),false,gateOnly))
);
}
diff --git a/src/V3Ast.h b/src/V3Ast.h
index c3bbc62..f14284a 100644
--- a/src/V3Ast.h
+++ b/src/V3Ast.h
@@ -236,6 +236,8 @@ public:
DIM_SIZE, // V3Width processes
DIM_UNPK_DIMENSIONS, // V3Width converts to constant
//
+ DT_PUBLIC, // V3LinkParse moves to AstTypedef::attrPublic
+ //
MEMBER_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
//
VAR_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
@@ -255,6 +257,7 @@ public:
"%E-AT",
"DIM_BITS", "DIM_DIMENSIONS", "DIM_HIGH", "DIM_INCREMENT", "DIM_LEFT",
"DIM_LOW", "DIM_RIGHT", "DIM_SIZE", "DIM_UNPK_DIMENSIONS",
+ "DT_PUBLIC",
"MEMBER_BASE",
"VAR_BASE", "VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC",
"VAR_PUBLIC_FLAT", "VAR_PUBLIC_FLAT_RD","VAR_PUBLIC_FLAT_RW",
@@ -932,7 +935,7 @@ class AstNode {
AstNode* cloneTreeIterList();
void checkTreeIter(AstNode* backp);
void checkTreeIterList(AstNode* backp);
- bool sameTreeIter(AstNode* node2p, bool ignNext);
+ bool sameTreeIter(AstNode* node2p, bool ignNext, bool gateOnly);
void deleteTreeIter();
void deleteNode();
static void relinkOneLink(AstNode*& pointpr, AstNode* newp);
@@ -1158,6 +1161,7 @@ public:
// METHODS - Iterate on a tree
AstNode* cloneTree(bool cloneNextLink);
bool sameTree(AstNode* node2p); // Does tree of this == node2p?
+ bool sameGateTree(AstNode* node2p); // Does tree of this == node2p?, not allowing non-isGateOptimizable
void deleteTree(); // Always deletes the next link
void checkTree(); // User Interface version
void checkIter() const;
@@ -1564,8 +1568,9 @@ public:
virtual void dumpSmall(ostream& str);
virtual bool hasDType() const { return true; }
virtual AstBasicDType* basicp() const = 0; // (Slow) recurse down to find basic data type
- virtual AstNodeDType* skipRefp() const = 0; // recurses over typedefs to next non-typeref type
+ virtual AstNodeDType* skipRefp() const = 0; // recurses over typedefs/const/enum to next non-typeref type
virtual AstNodeDType* skipRefToConstp() const = 0; // recurses over typedefs to next non-typeref-or-const type
+ virtual AstNodeDType* skipRefToEnump() const = 0; // recurses over typedefs/const to next non-typeref-or-enum/struct type
virtual int widthAlignBytes() const = 0; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
virtual int widthTotalBytes() const = 0; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
virtual bool maybePointedTo() const { return true; }
@@ -1616,6 +1621,7 @@ public:
virtual AstBasicDType* basicp() const { return findLogicDType(width(),width(),numeric())->castBasicDType(); }
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
+ virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
virtual int widthTotalBytes() const; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
// op1 = members
@@ -1672,6 +1678,7 @@ public:
virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
+ virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return elementsConst() * subDTypep()->widthTotalBytes(); }
int msb() const;
@@ -1886,6 +1893,8 @@ inline bool AstNode::isNeqZero() { return (this->castConst() && this->castConst
inline bool AstNode::isOne() { return (this->castConst() && this->castConst()->num().isEqOne()); }
inline bool AstNode::isAllOnes() { return (this->castConst() && this->castConst()->isEqAllOnes()); }
inline bool AstNode::isAllOnesV() { return (this->castConst() && this->castConst()->isEqAllOnesV()); }
+inline bool AstNode::sameTree(AstNode* node2p) { return sameTreeIter(node2p, true, false); }
+inline bool AstNode::sameGateTree(AstNode* node2p) { return sameTreeIter(node2p, true, true); }
inline void AstNodeVarRef::init() { if (m_varp) dtypep(m_varp->dtypep()); }
diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp
index c1fac9d..afd2ce3 100644
--- a/src/V3AstNodes.cpp
+++ b/src/V3AstNodes.cpp
@@ -819,6 +819,10 @@ void AstPin::dump(ostream& str) {
else { str<<" ->UNLINKED"; }
if (svImplicit()) str<<" [.SV]";
}
+void AstTypedef::dump(ostream& str) {
+ this->AstNode::dump(str);
+ if (attrPublic()) str<<" [PUBLIC]";
+}
void AstRange::dump(ostream& str) {
this->AstNode::dump(str);
if (littleEndian()) str<<" [LITTLE]";
diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h
index a11a5cc..391c434 100644
--- a/src/V3AstNodes.h
+++ b/src/V3AstNodes.h
@@ -183,22 +183,30 @@ public:
class AstTypedef : public AstNode {
private:
string m_name;
+ bool m_attrPublic;
public:
- AstTypedef(FileLine* fl, const string& name, VFlagChildDType, AstNodeDType* dtp)
+ AstTypedef(FileLine* fl, const string& name, AstNode* attrsp, VFlagChildDType, AstNodeDType* dtp)
: AstNode(fl), m_name(name) {
childDTypep(dtp); // Only for parser
+ addAttrsp(attrsp);
dtypep(NULL); // V3Width will resolve
+ m_attrPublic = false;
}
ASTNODE_NODE_FUNCS(Typedef, TYPEDEF)
+ virtual void dump(ostream& str);
AstNodeDType* getChildDTypep() const { return childDTypep(); }
AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Type assigning to
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); }
+ void addAttrsp(AstNode* nodep) { addNOp4p(nodep); }
+ AstNode* attrsp() const { return op4p()->castNode(); } // op4 = Attributes during early parse
// METHODS
virtual string name() const { return m_name; }
virtual bool maybePointedTo() const { return true; }
virtual bool hasDType() const { return true; }
void name(const string& flag) { m_name = flag; }
+ bool attrPublic() const { return m_attrPublic; }
+ void attrPublic(bool flag) { m_attrPublic = flag; }
};
class AstTypedefFwd : public AstNode {
@@ -242,6 +250,7 @@ public:
virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
+ virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const { return dtypep()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return dtypep()->widthTotalBytes(); }
virtual string name() const { return m_name; }
@@ -384,6 +393,7 @@ public:
virtual AstBasicDType* basicp() const { return (AstBasicDType*)this; } // (Slow) recurse down to find basic data type
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
+ virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
virtual int widthTotalBytes() const; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
AstBasicDTypeKwd keyword() const { return m.m_keyword; } // Avoid using - use isSomething accessors instead
@@ -445,6 +455,7 @@ public:
virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type
virtual AstNodeDType* skipRefp() const { return subDTypep()->skipRefp(); }
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
+ virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); }
};
@@ -474,6 +485,7 @@ public:
virtual AstBasicDType* basicp() const { return NULL; }
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
+ virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const { return 1; }
virtual int widthTotalBytes() const { return 1; }
string cellName() const { return m_cellName; }
@@ -528,6 +540,10 @@ public:
if (defp()) return defp()->skipRefToConstp();
else { v3fatalSrc("Typedef not linked"); return NULL; }
}
+ virtual AstNodeDType* skipRefToEnump() const {
+ if (defp()) return defp()->skipRefToEnump();
+ else { v3fatalSrc("Typedef not linked"); return NULL; }
+ }
virtual int widthAlignBytes() const { return dtypeSkipRefp()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return dtypeSkipRefp()->widthTotalBytes(); }
void name(const string& flag) { m_name = flag; }
@@ -599,6 +615,7 @@ public:
AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } // op1 = Range of variable (Note don't need virtual - AstVar isn't a NodeDType)
virtual AstNodeDType* skipRefp() const { return subDTypep()->skipRefp(); }
virtual AstNodeDType* skipRefToConstp() const { return subDTypep()->skipRefToConstp(); }
+ virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); } // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); } // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
// METHODS
@@ -688,6 +705,7 @@ public:
virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type
virtual AstNodeDType* skipRefp() const { return subDTypep()->skipRefp(); }
virtual AstNodeDType* skipRefToConstp() const { return subDTypep()->skipRefToConstp(); }
+ virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); }
};
@@ -1201,11 +1219,13 @@ private:
AstScope* m_scopep; // Scope variable is underneath
AstVar* m_varp; // [AfterLink] Pointer to variable itself
bool m_circular:1; // Used in circular ordering dependency, need change detect
+ bool m_trace:1; // Tracing is turned on for this scope
public:
AstVarScope(FileLine* fl, AstScope* scopep, AstVar* varp)
:AstNode(fl)
, m_scopep(scopep), m_varp(varp) {
m_circular = false;
+ m_trace = true;
dtypeFrom(varp);
}
ASTNODE_NODE_FUNCS(VarScope, VARSCOPE)
@@ -1226,6 +1246,8 @@ public:
void valuep(AstNode* valuep) { addOp1p(valuep); }
bool isCircular() const { return m_circular; }
void circular(bool flag) { m_circular = flag; }
+ bool isTrace() const { return m_trace; }
+ void trace(bool flag) { m_trace = flag; }
};
class AstVarRef : public AstNodeVarRef {
@@ -1483,13 +1505,14 @@ private:
string m_origName; // Original name before dot addition
string m_modName; // Module the cell instances
AstNodeModule* m_modp; // [AfterLink] Pointer to module instanced
- bool m_hasIfaceVar; // True if a Var has been created for this cell
+ bool m_hasIfaceVar:1; // True if a Var has been created for this cell
+ bool m_trace:1; // Trace this cell
public:
AstCell(FileLine* fl, const string& instName, const string& modName,
AstPin* pinsp, AstPin* paramsp, AstRange* rangep)
: AstNode(fl)
, m_name(instName), m_origName(instName), m_modName(modName)
- , m_modp(NULL), m_hasIfaceVar(false) {
+ , m_modp(NULL), m_hasIfaceVar(false), m_trace(true) {
addNOp1p(pinsp); addNOp2p(paramsp); setNOp3p(rangep); }
ASTNODE_NODE_FUNCS(Cell, CELL)
// No cloneRelink, we presume cloneee's want the same module linkages
@@ -1512,6 +1535,8 @@ public:
void modp(AstNodeModule* nodep) { m_modp = nodep; }
bool hasIfaceVar() const { return m_hasIfaceVar; }
void hasIfaceVar(bool flag) { m_hasIfaceVar = flag; }
+ void trace(bool flag) { m_trace=flag; }
+ bool isTrace() const { return m_trace; }
};
class AstCellInline : public AstNode {
diff --git a/src/V3Clean.cpp b/src/V3Clean.cpp
index 4091e37..18dd12e 100644
--- a/src/V3Clean.cpp
+++ b/src/V3Clean.cpp
@@ -238,6 +238,10 @@ private:
nodep->iterateChildren(*this);
insureCleanAndNext (nodep->valuep());
}
+ virtual void visit(AstTypedef* nodep, AstNUser*) {
+ // No cleaning, or would loose pointer to enum
+ nodep->iterateChildren(*this);
+ }
// Control flow operators
virtual void visit(AstNodeCond* nodep, AstNUser*) {
diff --git a/src/V3Const.cpp b/src/V3Const.cpp
index 9f9f18c..259c5a5 100644
--- a/src/V3Const.cpp
+++ b/src/V3Const.cpp
@@ -173,6 +173,16 @@ private:
if (rnodep->width() != bnodep->width()) return false;
return rnodep->lhsp()->castConst();
}
+ static bool operandSubAdd(AstNode* nodep) {
+ // SUB( ADD(CONSTx,y), CONSTz) -> ADD(SUB(CONSTx,CONSTz), y)
+ AstNodeBiop* np = nodep->castNodeBiop();
+ AstNodeBiop* lp = np->lhsp()->castNodeBiop();
+ return (lp
+ && lp->lhsp()->castConst()
+ && np->rhsp()->castConst()
+ && lp->width()==np->width());
+ }
+
static bool operandAndOrSame(AstNode* nodep) {
// OR( AND(VAL,x), AND(VAL,y)) -> AND(VAL,OR(x,y))
// OR( AND(x,VAL), AND(y,VAL)) -> AND(OR(x,y),VAL)
@@ -418,12 +428,12 @@ private:
static bool operandsSame(AstNode* node1p, AstNode* node2p) {
// For now we just detect constants & simple vars, though it could be more generic
if (node1p->castConst() && node2p->castConst()) {
- return node1p->sameTree(node2p);
+ return node1p->sameGateTree(node2p);
}
else if (node1p->castVarRef() && node2p->castVarRef()) {
// Avoid comparing widthMin's, which results in lost optimization attempts
- // If cleanup sameTree to be smarter, this can be restored.
- //return node1p->sameTree(node2p);
+ // If cleanup sameGateTree to be smarter, this can be restored.
+ //return node1p->sameGateTree(node2p);
return node1p->same(node2p);
} else {
return false;
@@ -439,7 +449,7 @@ private:
AstVarRef* elsevarp = elsep->lhsp()->castVarRef();
if (!ifvarp || !elsevarp) return false;
if (ifvarp->isWide()) return false; // Would need temporaries, so not worth it
- if (!ifvarp->sameTree(elsevarp)) return false;
+ if (!ifvarp->sameGateTree(elsevarp)) return false;
return true;
}
bool operandIfIf(AstNodeIf* nodep) {
@@ -450,6 +460,89 @@ private:
if (afterComment(lowerIfp->elsesp())) return false;
return true;
}
+ bool ifConcatMergeableBiop(AstNode* nodep) {
+ return (nodep->castAnd()
+ || nodep->castOr()
+ || nodep->castXor()
+ || nodep->castXnor());
+ }
+ bool ifAdjacentSel(AstSel* lhsp, AstSel* rhsp) {
+ if (!v3Global.opt.oAssemble()) return false; // opt disabled
+ if (!lhsp || !rhsp) return false;
+ AstNode* lfromp = lhsp->fromp();
+ AstNode* rfromp = rhsp->fromp();
+ if (!lfromp || !rfromp || !lfromp->sameGateTree(rfromp)) return false;
+ AstConst* lstart = lhsp->lsbp()->castConst();
+ AstConst* rstart = rhsp->lsbp()->castConst();
+ AstConst* lwidth = lhsp->widthp()->castConst();
+ AstConst* rwidth = rhsp->widthp()->castConst();
+ if (!lstart || !rstart || !lwidth || !rwidth) return false; // too complicated
+ int rend = (rstart->toSInt() + rwidth->toSInt());
+ if (rend == lstart->toSInt()) return true;
+ return false;
+ }
+ bool ifMergeAdjacent(AstNode* lhsp, AstNode* rhsp) {
+ // called by concatmergeable to determine if {lhsp, rhsp} make sense
+ if (!v3Global.opt.oAssemble()) return false; // opt disabled
+ // two same varref
+ if (operandsSame(lhsp, rhsp)) return true;
+ AstSel* lselp = lhsp->castSel();
+ AstSel* rselp = rhsp->castSel();
+ // a[i:0] a
+ if (lselp && !rselp && rhsp->sameGateTree(lselp->fromp()))
+ rselp = new AstSel(rhsp->fileline(), rhsp->cloneTree(false), 0, rhsp->width());
+ // a[i:j] {a[j-1:k], b}
+ if (lselp && !rselp && rhsp->castConcat())
+ return ifMergeAdjacent(lhsp, rhsp->castConcat()->lhsp());
+ // a a[msb:j]
+ if (rselp && !lselp && lhsp->sameGateTree(rselp->fromp()))
+ lselp = new AstSel(lhsp->fileline(), lhsp->cloneTree(false), 0, lhsp->width());
+ // {b, a[j:k]} a[k-1:i]
+ if (rselp && !lselp && lhsp->castConcat())
+ return ifMergeAdjacent(lhsp->castConcat()->rhsp(), rhsp);
+ if (!lselp || !rselp) return false;
+
+ // a[a:b] a[b-1:c] are adjacent
+ AstNode* lfromp = lselp->fromp();
+ AstNode* rfromp = rselp->fromp();
+ if (!lfromp || !rfromp || !lfromp->sameGateTree(rfromp)) return false;
+ AstConst* lstart = lselp->lsbp()->castConst();
+ AstConst* rstart = rselp->lsbp()->castConst();
+ AstConst* lwidth = lselp->widthp()->castConst();
+ AstConst* rwidth = rselp->widthp()->castConst();
+ if (!lstart || !rstart || !lwidth || !rwidth) return false; // too complicated
+ int rend = (rstart->toSInt() + rwidth->toSInt());
+ // a[i:j] a[j-1:k]
+ if (rend == lstart->toSInt()) return true;
+ // a[i:0] a[msb:j]
+ if (rend == rfromp->width() && lstart->toSInt() == 0) return true;
+ return false;
+ }
+ bool concatMergeable(AstNode* lhsp, AstNode* rhsp) {
+ // determine if {a OP b, c OP d} => {a, c} OP {b, d} is advantagous
+ if (!v3Global.opt.oAssemble()) return false; // opt disabled
+ if (lhsp->type() != rhsp->type()) return false;
+ if (!ifConcatMergeableBiop(lhsp)) return false;
+
+ AstNodeBiop* lp = lhsp->castNodeBiop();
+ AstNodeBiop* rp = rhsp->castNodeBiop();
+ if (!lp || !rp) return false;
+ // {a[]&b[], a[]&b[]}
+ bool lad = ifMergeAdjacent(lp->lhsp(), rp->lhsp());
+ bool rad = ifMergeAdjacent(lp->rhsp(), rp->rhsp());
+ if (lad && rad) return true;
+ // {a[] & b[]&c[], a[] & b[]&c[]}
+ else if (lad && concatMergeable(lp->rhsp(), rp->rhsp())) return true;
+ // {a[]&b[] & c[], a[]&b[] & c[]}
+ else if (rad && concatMergeable(lp->lhsp(), rp->lhsp())) return true;
+ else {
+ // {(a[]&b[])&(c[]&d[]), (a[]&b[])&(c[]&d[])}
+ if (concatMergeable(lp->lhsp(), rp->lhsp())
+ && concatMergeable(lp->rhsp(), rp->rhsp()))
+ return true;
+ }
+ return false;
+ }
//----------------------------------------
// Constant Replacement functions.
@@ -668,6 +761,45 @@ private:
rrp->deleteTree();
//nodep->dumpTree(cout, " repShiftSame_new: ");
}
+ void replaceConcatSel(AstConcat* nodep) {
+ // {a[1], a[0]} -> a[1:0]
+ AstSel* lselp = nodep->lhsp()->unlinkFrBack()->castSel();
+ AstSel* rselp = nodep->rhsp()->unlinkFrBack()->castSel();
+ int lstart = lselp->lsbConst();
+ int lwidth = lselp->widthConst();
+ int rstart = rselp->lsbConst();
+ int rwidth = rselp->widthConst();
+
+ if ((rstart + rwidth) != lstart) nodep->v3fatalSrc("tried to merge two selects which are not adjacent");
+ AstSel* newselp = new AstSel(lselp->fromp()->fileline(), rselp->fromp()->cloneTree(false), rstart, lwidth+rwidth);
+ UINFO(5, "merged two adjacent sel "<<lselp <<" and "<<rselp<< " to one "<<newselp<<endl);
+
+ nodep->replaceWith(newselp);
+ lselp->deleteTree(); lselp = NULL;
+ rselp->deleteTree(); rselp = NULL;
+ nodep->deleteTree(); nodep = NULL;
+ }
+ void replaceConcatMerge(AstConcat* nodep) {
+ AstNodeBiop* lp = nodep->lhsp()->castNodeBiop();
+ AstNodeBiop* rp = nodep->rhsp()->castNodeBiop();
+ AstNode* llp = lp->lhsp()->cloneTree(false);
+ AstNode* lrp = lp->rhsp()->cloneTree(false);
+ AstNode* rlp = rp->lhsp()->cloneTree(false);
+ AstNode* rrp = rp->rhsp()->cloneTree(false);
+ if (concatMergeable(lp, rp)) {
+ AstConcat* newlp = new AstConcat(rlp->fileline(), llp, rlp);
+ AstConcat* newrp = new AstConcat(rrp->fileline(), lrp, rrp);
+ // use the lhs to replace the parent concat
+ lp->lhsp()->replaceWith(newlp);
+ lp->rhsp()->replaceWith(newrp);
+ lp->dtypeChgWidthSigned(newlp->width(), newlp->width(), AstNumeric::fromBool(true));
+ UINFO(5, "merged "<< nodep <<endl);
+ rp->unlinkFrBack()->deleteTree(); rp = NULL;
+ nodep->replaceWith(lp->unlinkFrBack()); nodep->deleteTree(); nodep = NULL;
+ lp->lhsp()->accept(*this);
+ lp->rhsp()->accept(*this);
+ } else nodep->v3fatalSrc("tried to merge two Concat which are not adjacent");
+ }
void replaceExtend (AstNode* nodep, AstNode* arg0p) {
// -> EXTEND(nodep)
// like a AstExtend{$rhsp}, but we need to set the width correctly from base node
@@ -792,7 +924,7 @@ private:
AstSel* sel2p = nextp->lhsp()->castSel(); if (!sel2p) return false;
AstVarRef* varref1p = sel1p->fromp()->castVarRef(); if (!varref1p) return false;
AstVarRef* varref2p = sel2p->fromp()->castVarRef(); if (!varref2p) return false;
- if (!varref1p->sameTree(varref2p)) return false;
+ if (!varref1p->sameGateTree(varref2p)) return false;
AstConst* con1p = sel1p->lsbp()->castConst(); if (!con1p) return false;
AstConst* con2p = sel2p->lsbp()->castConst(); if (!con2p) return false;
// We need to make sure there's no self-references involved in either
@@ -1539,7 +1671,7 @@ private:
AstSenItem* litemp = senp->castSenItem();
AstSenItem* ritemp = cmpp->castSenItem();
if (litemp && ritemp) {
- if ((litemp->varrefp() && ritemp->varrefp() && litemp->varrefp()->sameTree(ritemp->varrefp()))
+ if ((litemp->varrefp() && ritemp->varrefp() && litemp->varrefp()->sameGateTree(ritemp->varrefp()))
|| (!litemp->varrefp() && !ritemp->varrefp())) {
// We've sorted in the order ANY, BOTH, POS, NEG, so we don't need to try opposite orders
if (( litemp->edgeType()==AstEdgeType::ET_ANYEDGE) // ANY or {BOTH|POS|NEG} -> ANY
@@ -1910,6 +2042,7 @@ private:
TREEOP ("AstMul {operandIsPowTwo($lhsp), $rhsp}", "replaceMulShift(nodep)"); // a*2^n -> a<<n
TREEOP ("AstDiv {$lhsp, operandIsPowTwo($rhsp)}", "replaceDivShift(nodep)"); // a/2^n -> a>>n
TREEOP ("AstPow {operandIsTwo($lhsp), $rhsp}", "replacePowShift(nodep)"); // 2**a == 1<<a
+ TREEOP ("AstSub {$lhsp.castAdd, operandSubAdd(nodep)}", "AstAdd{AstSub{$lhsp->castAdd()->lhsp(),$rhsp}, $lhsp->castAdd()->rhsp()}"); // ((a+x)-y) -> (a+(x-y))
// Trinary ops
// Note V3Case::Sel requires Cond to always be conditionally executed in C to prevent core dump!
TREEOP ("AstNodeCond{$condp.isZero, $expr1p, $expr2p}", "replaceWChild(nodep,$expr2p)");
@@ -2064,6 +2197,9 @@ private:
// CONCAT({const},CONCAT({const},{c})) -> CONCAT((constifiedCONC{const|const},{c}))
TREEOPV("AstConcat{operandConcatMove(nodep)}", "moveConcat(nodep)");
TREEOPV("AstConcat{$lhsp.isZero, $rhsp}", "replaceExtend(nodep, nodep->rhsp())");
+ // CONCAT(a[1],a[0]) -> a[1:0]
+ TREEOPV("AstConcat{$lhsp->castSel(), $rhsp->castSel(), ifAdjacentSel($lhsp->castSel(),,$rhsp->castSel())}", "replaceConcatSel(nodep)");
+ TREEOPV("AstConcat{ifConcatMergeableBiop($lhsp), concatMergeable($lhsp,,$rhsp)}", "replaceConcatMerge(nodep)");
// Common two-level operations that can be simplified
TREEOP ("AstAnd {$lhsp.castOr, $rhsp.castOr, operandAndOrSame(nodep)}", "replaceAndOr(nodep)");
TREEOP ("AstOr {$lhsp.castAnd,$rhsp.castAnd,operandAndOrSame(nodep)}", "replaceAndOr(nodep)");
diff --git a/src/V3Dead.cpp b/src/V3Dead.cpp
index 6c6c143..0e9d010 100644
--- a/src/V3Dead.cpp
+++ b/src/V3Dead.cpp
@@ -81,6 +81,7 @@ private:
typedef multimap<AstVarScope*,AstNodeAssign*> AssignMap;
// STATE
+ AstNodeModule* m_modp; // Current module
vector<AstNode*> m_varEtcsp; // List of all encountered to avoid another loop through tree
vector<AstVarScope*> m_vscsp; // List of all encountered to avoid another loop through tree
AssignMap m_assignMap; // List of all simple assignments for each variable
@@ -112,6 +113,12 @@ private:
}
// VISITORS
+ virtual void visit(AstNodeModule* nodep, AstNUser*) {
+ m_modp = nodep;
+ nodep->iterateChildren(*this);
+ checkAll(nodep);
+ m_modp = NULL;
+ }
virtual void visit(AstCell* nodep, AstNUser*) {
nodep->iterateChildren(*this);
checkAll(nodep);
@@ -158,6 +165,13 @@ private:
nodep->packagep()->user1Inc();
}
}
+ virtual void visit(AstTypedef* nodep, AstNUser*) {
+ nodep->iterateChildren(*this);
+ checkAll(nodep);
+ // Don't let packages with only public variables disappear
+ // Normal modules may disappear, e.g. if they are parameterized then removed
+ if (nodep->attrPublic() && m_modp && m_modp->castPackage()) m_modp->user1Inc();
+ }
virtual void visit(AstVarScope* nodep, AstNUser*) {
nodep->iterateChildren(*this);
checkAll(nodep);
@@ -168,6 +182,7 @@ private:
virtual void visit(AstVar* nodep, AstNUser*) {
nodep->iterateChildren(*this);
checkAll(nodep);
+ if (nodep->isSigPublic() && m_modp && m_modp->castPackage()) m_modp->user1Inc();
if (mightElim(nodep)) {
m_varEtcsp.push_back(nodep);
}
@@ -253,6 +268,7 @@ private:
public:
// CONSTRUCTORS
DeadVisitor(AstNetlist* nodep, bool elimUserVars, bool elimDTypes) {
+ m_modp = NULL;
m_elimUserVars = elimUserVars;
m_elimDTypes = elimDTypes;
m_sideEffect = false;
diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp
index 829a911..3d3d69a 100644
--- a/src/V3EmitC.cpp
+++ b/src/V3EmitC.cpp
@@ -96,6 +96,38 @@ public:
}
}
+ void emitTypedefs(AstNode* firstp) {
+ bool first = true;
+ for (AstNode* loopp=firstp; loopp; loopp = loopp->nextp()) {
+ if (AstTypedef* nodep = loopp->castTypedef()) {
+ if (nodep->attrPublic()) {
+ if (first) {
+ first = false;
+ puts("\n// TYPEDEFS\n");
+ puts("// That were declared public\n");
+ } else {
+ puts("\n");
+ }
+ if (AstEnumDType* adtypep = nodep->dtypep()->skipRefToEnump()->castEnumDType()) {
+ if (adtypep->width()>64) {
+ puts("// enum "+nodep->name()+" // Ignored: Too wide for C++\n");
+ } else {
+ puts("enum "+nodep->name()+" {\n");
+ for (AstEnumItem* itemp = adtypep->itemsp(); itemp; itemp=itemp->nextp()->castEnumItem()) {
+ puts(itemp->name());
+ puts(" = ");
+ itemp->valuep()->iterateAndNext(*this);
+ if (nodep->nextp()) puts(",");
+ puts("\n");
+ }
+ puts("};\n");
+ }
+ }
+ }
+ }
+ }
+ }
+
// VISITORS
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
bool paren = true; bool decind = false;
@@ -663,6 +695,7 @@ public:
nodep->iterateChildren(*this);
}
// NOPs
+ virtual void visit(AstTypedef*, AstNUser*) {}
virtual void visit(AstPragma*, AstNUser*) {}
virtual void visit(AstCell*, AstNUser*) {} // Handled outside the Visit class
virtual void visit(AstVar*, AstNUser*) {} // Handled outside the Visit class
@@ -670,7 +703,6 @@ public:
virtual void visit(AstTraceDecl*, AstNUser*) {} // Handled outside the Visit class
virtual void visit(AstTraceInc*, AstNUser*) {} // Handled outside the Visit class
virtual void visit(AstCFile*, AstNUser*) {} // Handled outside the Visit class
- virtual void visit(AstTypedef*, AstNUser*) {} // Nothing needed presently
// Default
virtual void visit(AstNode* nodep, AstNUser*) {
puts((string)"\n???? // "+nodep->prettyTypeName()+"\n");
@@ -1845,6 +1877,8 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
}
}
+ emitTypedefs(modp->stmtsp());
+
puts("\n// PORTS\n");
if (modp->isTop()) puts("// The application code writes and reads these signals to\n");
if (modp->isTop()) puts("// propagate new values into/out from the Verilated model.\n");
diff --git a/src/V3Gate.cpp b/src/V3Gate.cpp
index 9096158..ebc7cb8 100644
--- a/src/V3Gate.cpp
+++ b/src/V3Gate.cpp
@@ -303,6 +303,7 @@ private:
V3Double0 m_statSigs; // Statistic tracking
V3Double0 m_statRefs; // Statistic tracking
V3Double0 m_statDedupLogic; // Statistic tracking
+ V3Double0 m_statAssignMerged; // Statistic tracking
// METHODS
void iterateNewStmt(AstNode* nodep, const char* nonReducibleReason, const char* consumeReason) {
@@ -352,6 +353,7 @@ private:
void consumedMove();
void replaceAssigns();
void dedupe();
+ void mergeAssigns();
// VISITORS
virtual void visit(AstNetlist* nodep, AstNUser*) {
@@ -368,6 +370,7 @@ private:
optimizeSignals(true);
// Remove redundant logic
if (v3Global.opt.oDedupe()) dedupe();
+ if (v3Global.opt.oAssemble()) mergeAssigns();
// Warn
warnSignals();
consumedMark();
@@ -506,6 +509,7 @@ public:
V3Stats::addStat("Optimizations, Gate sigs deleted", m_statSigs);
V3Stats::addStat("Optimizations, Gate inputs replaced", m_statRefs);
V3Stats::addStat("Optimizations, Gate sigs deduped", m_statDedupLogic);
+ V3Stats::addStat("Optimizations, Gate assign merged", m_statAssignMerged);
}
};
@@ -1009,7 +1013,6 @@ private:
lvertexp->user(true);
}
}
-
return NULL;
}
@@ -1063,6 +1066,132 @@ void GateVisitor::dedupe() {
m_statDedupLogic += deduper.numDeduped();
}
+
+//######################################################################
+// Recurse through the graph, try to merge assigns
+
+class GateMergeAssignsGraphVisitor : public GateGraphBaseVisitor {
+private:
+ // NODE STATE
+ AstNodeAssign* m_assignp;
+ AstActive* m_activep;
+ GateLogicVertex* m_logicvp;
+ V3Graph* m_graphp;
+ V3Double0 m_numMergedAssigns; // Statistic tracking
+
+
+ // assemble two Sel into one if possible
+ AstSel* merge(AstSel* pre, AstSel* cur) {
+ AstVarRef* preVarRefp = pre->fromp()->castVarRef();
+ AstVarRef* curVarRefp = cur->fromp()->castVarRef();
+ if (!preVarRefp || !curVarRefp || !curVarRefp->same(preVarRefp)) return NULL; // not the same var
+ AstConst* pstart = pre->lsbp()->castConst();
+ AstConst* pwidth = pre->widthp()->castConst();
+ AstConst* cstart = cur->lsbp()->castConst();
+ AstConst* cwidth = cur->widthp()->castConst();
+ if (!pstart || !pwidth || !cstart || !cwidth) return NULL; // too complicated
+ if (cur->lsbConst()+cur->widthConst() == pre->lsbConst())
+ return new AstSel(curVarRefp->fileline(), curVarRefp->cloneTree(false), cur->lsbConst(), pre->widthConst()+cur->widthConst());
+ else return NULL;
+ }
+
+ virtual AstNUser* visit(GateVarVertex *vvertexp, AstNUser*) {
+ for (V3GraphEdge* edgep = vvertexp->inBeginp(); edgep; ) {
+ V3GraphEdge* oldedgep = edgep;
+ edgep = edgep->inNextp(); // for recursive since the edge could be deleted
+ if (GateLogicVertex* lvertexp = dynamic_cast<GateLogicVertex*>(oldedgep->fromp())) {
+ if (AstNodeAssign* assignp = lvertexp->nodep()->castNodeAssign()) {
+ //if (lvertexp->outSize1() && assignp->lhsp()->castSel()) {
+ if (assignp->lhsp()->castSel() && lvertexp->outSize1()) {
+ UINFO(9, "assing to the nodep["<<assignp->lhsp()->castSel()->lsbConst()<<"]"<<endl);
+ // first assign with Sel-lhs
+ if (!m_activep) m_activep = lvertexp->activep();
+ if (!m_logicvp) m_logicvp = lvertexp;
+ if (!m_assignp) m_assignp = assignp;
+
+ // not under the same active
+ if (m_activep != lvertexp->activep()) {
+ m_activep = lvertexp->activep();
+ m_logicvp = lvertexp;
+ m_assignp = assignp;
+ continue;
+ }
+
+ AstSel* preselp = m_assignp->lhsp()->castSel();
+ AstSel* curselp = assignp->lhsp()->castSel();
+ if (!preselp || !curselp) continue;
+
+ if (AstSel* newselp = merge(preselp, curselp)) {
+ UINFO(5, "assemble to new sel: "<<newselp<<endl);
+ // replace preSel with newSel
+ preselp->replaceWith(newselp); preselp->deleteTree(); preselp = NULL;
+ // create new rhs for pre assignment
+ AstNode* newrhsp = new AstConcat(m_assignp->rhsp()->fileline(), m_assignp->rhsp()->cloneTree(false), assignp->rhsp()->cloneTree(false));
+ AstNode* oldrhsp = m_assignp->rhsp();
+ oldrhsp->replaceWith(newrhsp); oldrhsp->deleteTree(); oldrhsp = NULL;
+ m_assignp->dtypeChgWidthSigned(m_assignp->width()+assignp->width(), m_assignp->width()+assignp->width(), AstNumeric::fromBool(true));
+ // don't need to delete, will be handled
+ //assignp->unlinkFrBack(); assignp->deleteTree(); assignp = NULL;
+
+ // update the graph
+ {
+ // delete all inedges to lvertexp
+ if (!lvertexp->inEmpty()) {
+ for (V3GraphEdge* ledgep = lvertexp->inBeginp(); ledgep; ) {
+ V3GraphEdge* oedgep = ledgep;
+ ledgep = ledgep->inNextp();
+ GateEitherVertex* fromvp = dynamic_cast<GateEitherVertex*>(oedgep->fromp());
+ new V3GraphEdge(m_graphp, fromvp, m_logicvp, 1);
+ oedgep->unlinkDelete(); oedgep = NULL;
+ }
+ }
+ // delete all outedges to lvertexp, only one
+ oldedgep->unlinkDelete(); oldedgep = NULL;
+ }
+ ++m_numMergedAssigns;
+ } else {
+ m_assignp = assignp;
+ m_logicvp = lvertexp;
+ }
+ }
+ }
+ }
+ }
+ return NULL;
+ }
+
+ virtual AstNUser* visit(GateLogicVertex* lvertexp, AstNUser* vup) {
+ return NULL;
+ }
+
+public:
+ GateMergeAssignsGraphVisitor(V3Graph* graphp) {
+ m_assignp = NULL;
+ m_activep = NULL;
+ m_logicvp = NULL;
+ m_numMergedAssigns = 0;
+ m_graphp = graphp;
+ }
+ void mergeAssignsTree(GateVarVertex* vvertexp) {
+ vvertexp->accept(*this);
+ }
+ V3Double0 numMergedAssigns() { return m_numMergedAssigns; }
+};
+
+
+//----------------------------------------------------------------------
+
+void GateVisitor::mergeAssigns() {
+ GateMergeAssignsGraphVisitor merger(&m_graph);
+ for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
+ if (GateVarVertex* vvertexp = dynamic_cast<GateVarVertex*>(itp)) {
+ merger.mergeAssignsTree(vvertexp);
+ }
+ }
+ m_statAssignMerged += merger.numMergedAssigns();
+}
+
+
//######################################################################
// Convert VARSCOPE(ASSIGN(default, VARREF)) to just VARSCOPE(default)
diff --git a/src/V3Inline.cpp b/src/V3Inline.cpp
index 9754435..b98897a 100644
--- a/src/V3Inline.cpp
+++ b/src/V3Inline.cpp
@@ -314,6 +314,7 @@ private:
// Also clear I/O bits, as it is now local.
string name = m_cellp->name() + "__DOT__" + nodep->name();
if (!nodep->isFuncLocal()) nodep->inlineAttrReset(name);
+ if (!m_cellp->isTrace()) nodep->trace(false);
if (debug()>=9) { nodep->dumpTree(cout,"varchanged:"); }
if (debug()>=9) { nodep->valuep()->dumpTree(cout,"varchangei:"); }
// Iterate won't hit AstIfaceRefDType directly as it is no longer underneath the module
diff --git a/src/V3LinkParse.cpp b/src/V3LinkParse.cpp
index f33d42c..34667da 100644
--- a/src/V3LinkParse.cpp
+++ b/src/V3LinkParse.cpp
@@ -62,6 +62,7 @@ private:
AstNodeModule* m_valueModp; // If set, move AstVar->valuep() initial values to this module
AstNodeModule* m_modp; // Current module
AstNodeFTask* m_ftaskp; // Current task
+ AstNodeDType* m_dtypep; // Current data type
// METHODS
static int debug() {
@@ -104,6 +105,15 @@ private:
m_valueModp = upperValueModp;
}
}
+ virtual void visit(AstNodeDType* nodep, AstNUser*) {
+ if (!nodep->user1SetOnce()) { // Process only once.
+ cleanFileline(nodep);
+ AstNodeDType* upperDtypep = m_dtypep;
+ m_dtypep = nodep;
+ nodep->iterateChildren(*this);
+ m_dtypep = upperDtypep;
+ }
+ }
virtual void visit(AstEnumItem* nodep, AstNUser*) {
// Expand ranges
cleanFileline(nodep);
@@ -176,7 +186,13 @@ private:
virtual void visit(AstAttrOf* nodep, AstNUser*) {
cleanFileline(nodep);
nodep->iterateChildren(*this);
- if (nodep->attrType() == AstAttrType::VAR_CLOCK) {
+ if (nodep->attrType() == AstAttrType::DT_PUBLIC) {
+ AstTypedef* typep = nodep->backp()->castTypedef();
+ if (!typep) nodep->v3fatalSrc("Attribute not attached to typedef");
+ typep->attrPublic(true);
+ nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
+ }
+ else if (nodep->attrType() == AstAttrType::VAR_CLOCK) {
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
m_varp->attrScClocked(true);
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
@@ -265,7 +281,7 @@ private:
nodep->deleteTree(); nodep=NULL;
return;
} else {
- defp = new AstTypedef(nodep->fileline(), nodep->name(), VFlagChildDType(), dtypep);
+ defp = new AstTypedef(nodep->fileline(), nodep->name(), NULL, VFlagChildDType(), dtypep);
m_implTypedef.insert(make_pair(make_pair(nodep->containerp(), defp->name()), defp));
backp->addNextHere(defp);
}
@@ -327,6 +343,7 @@ public:
m_varp = NULL;
m_modp = NULL;
m_ftaskp = NULL;
+ m_dtypep = NULL;
m_inAlways = false;
m_inGenerate = false;
m_needStart = false;
diff --git a/src/V3Options.cpp b/src/V3Options.cpp
index 7c31676..a5b582d 100644
--- a/src/V3Options.cpp
+++ b/src/V3Options.cpp
@@ -107,17 +107,27 @@ void V3Options::addLangExt(const string& langext, const V3LangCode& lc) {
void V3Options::addLibExtV(const string& libext) {
m_impp->addLibExtV(libext);
}
-void V3Options::addDefine(const string& defline) {
+void V3Options::addDefine(const string& defline, bool allowPlus) {
// Split +define+foo=value into the appropriate parts and parse
- string def = defline;
- string value;
- string::size_type pos;
- if ( ((pos=defline.find("+")) != string::npos)
- || ((pos=defline.find("=")) != string::npos)) {
- value = def.substr(pos+1);
- def.erase(pos);
+ // Optional + says to allow multiple defines on the line
+ // + is not quotable, as other simulators do not allow that
+ string left = defline;
+ while (left != "") {
+ string def = left;
+ string::size_type pos;
+ if (allowPlus && ((pos=left.find("+")) != string::npos)) {
+ left = left.substr(pos+1);
+ def.erase(pos);
+ } else {
+ left = "";
+ }
+ string value;
+ if ((pos=def.find("=")) != string::npos) {
+ value = def.substr(pos+1);
+ def.erase(pos);
+ }
+ V3PreShell::defineCmdLine(def,value);
}
- V3PreShell::defineCmdLine(def,value);
}
void V3Options::addCppFile(const string& filename) {
@@ -668,7 +678,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
if (argv[i][0]=='+') {
char *sw = argv[i];
if ( !strncmp (sw, "+define+", 8)) {
- addDefine (string (sw+strlen("+define+")));
+ addDefine (string (sw+strlen("+define+")), true);
}
else if ( !strncmp (sw, "+incdir+", 8)) {
addIncDirUser (parseFileArg(optdir, string (sw+strlen("+incdir+"))));
@@ -774,6 +784,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
case 'b': m_oCombine = flag; break;
case 'c': m_oConst = flag; break;
case 'd': m_oDedupe = flag; break;
+ case 'm': m_oAssemble = flag; break;
case 'e': m_oCase = flag; break;
case 'f': m_oFlopGater = flag; break;
case 'g': m_oGate = flag; break;
@@ -802,7 +813,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
m_convergeLimit = atoi(argv[i]);
}
else if ( !strncmp (sw, "-D", 2)) {
- addDefine (string (sw+strlen("-D")));
+ addDefine (string (sw+strlen("-D")), false);
}
else if ( !strcmp (sw, "-debug") ) {
setDebugMode(3);
@@ -1319,6 +1330,7 @@ void V3Options::optimize(int level) {
m_oSubstConst = flag;
m_oTable = flag;
m_oDedupe = flag;
+ m_oAssemble = flag;
// And set specific optimization levels
if (level >= 3) {
m_inlineMult = -1; // Maximum inlining
diff --git a/src/V3Options.h b/src/V3Options.h
index a05924f..4e1c936 100644
--- a/src/V3Options.h
+++ b/src/V3Options.h
@@ -139,6 +139,7 @@ class V3Options {
bool m_oCombine; // main switch: -Ob: common icode packing
bool m_oConst; // main switch: -Oc: constant folding
bool m_oDedupe; // main switch: -Od: logic deduplication
+ bool m_oAssemble; // main switch: -Om: assign assemble
bool m_oExpand; // main switch: -Ox: expansion of C macros
bool m_oFlopGater; // main switch: -Of: flop gater detection
bool m_oGate; // main switch: -Og: gate wire elimination
@@ -155,7 +156,7 @@ class V3Options {
private:
// METHODS
void addArg(const string& flag);
- void addDefine(const string& defline);
+ void addDefine(const string& defline, bool allowPlus);
void addFuture(const string& flag);
void addIncDirUser(const string& incdir); // User requested
void addIncDirFallback(const string& incdir); // Low priority if not found otherwise
@@ -282,6 +283,7 @@ class V3Options {
bool oCombine() const { return m_oCombine; }
bool oConst() const { return m_oConst; }
bool oDedupe() const { return m_oDedupe; }
+ bool oAssemble() const { return m_oAssemble; }
bool oExpand() const { return m_oExpand; }
bool oFlopGater() const { return m_oFlopGater; }
bool oGate() const { return m_oGate; }
diff --git a/src/V3PreLex.h b/src/V3PreLex.h
index 17e20e6..1c5cf17 100644
--- a/src/V3PreLex.h
+++ b/src/V3PreLex.h
@@ -169,6 +169,7 @@ class V3PreLex {
int m_pslParenLevel;// PSL Parenthesis (){} counting, so we can find final ;
bool m_pslMoreNeeded;// Next // comment is really psl
bool m_defCmtSlash; // /*...*/ comment in define had \ ending
+ bool m_defQuote; // Definition value inside quote
string m_defValue; // Definition value being built.
int m_enterExit; // For VL_LINE, the enter/exit level
@@ -181,6 +182,7 @@ class V3PreLex {
m_pedantic = false;
m_formalLevel = 0;
m_parenLevel = 0;
+ m_defQuote = false;
m_defCmtSlash = false;
m_tokFilelinep = filelinep;
m_enterExit = 0;
diff --git a/src/V3PreLex.l b/src/V3PreLex.l
index b58b671..58191a9 100644
--- a/src/V3PreLex.l
+++ b/src/V3PreLex.l
@@ -125,7 +125,7 @@ psl [p]sl
<STRMODE>{backslash}{crnl} { linenoInc(); yymore(); }
<STRMODE>{backslash}. { yymore(); }
<STRMODE>{quote} { yy_pop_state();
- if (LEXP->m_parenLevel || LEXP->m_formalLevel) { appendDefValue(yytext,yyleng); yyleng=0; }
+ if (LEXP->m_parenLevel || LEXP->m_defQuote) { LEXP->m_defQuote=false; appendDefValue(yytext,yyleng); yyleng=0; }
else return (VP_STRING); }
/* Stringification */
@@ -162,7 +162,7 @@ psl [p]sl
<DEFFORM><<EOF>> { linenoInc(); yy_pop_state(); yyerrorf("Unterminated ( in define formal arguments."); yyleng=0; return VP_DEFFORM; }
<DEFFORM>{crnl} { linenoInc(); appendDefValue((char*)"\n",1); } /* Include return so can maintain output line count */
<DEFFORM>[\\]{crnl} { linenoInc(); appendDefValue((char*)"\\\n",2); } /* Include return so can maintain output line count */
-<DEFFORM>{quote} { yy_push_state(STRMODE); yymore(); } /* Legal only in default values */
+<DEFFORM>{quote} { LEXP->m_defQuote=true; yy_push_state(STRMODE); yymore(); } /* Legal only in default values */
<DEFFORM>"`\\`\"" { appendDefValue(yytext,yyleng); } /* Maybe illegal, otherwise in default value */
<DEFFORM>{tickquote} { appendDefValue(yytext,yyleng); } /* Maybe illegal, otherwise in default value */
<DEFFORM>[{\[] { LEXP->m_formalLevel++; appendDefValue(yytext,yyleng); }
@@ -179,7 +179,8 @@ psl [p]sl
<DEFVAL><<EOF>> { linenoInc(); yy_pop_state(); yytext=(char*)"\n"; yyleng=1; return (VP_DEFVALUE); } /* Technically illegal, but people complained */
<DEFVAL>{crnl} { linenoInc(); yy_pop_state(); yytext=(char*)"\n"; yyleng=1; return (VP_DEFVALUE); }
<DEFVAL>[\\]{crnl} { linenoInc(); appendDefValue((char*)"\\\n",2); } /* Return, AND \ is part of define value */
-<DEFVAL>[^\/\*\n\r\\]+ |
+<DEFVAL>{quote} { LEXP->m_defQuote=true; yy_push_state(STRMODE); yymore(); }
+<DEFVAL>[^\/\*\n\r\\\"]+ |
<DEFVAL>[\\][^\n\r] |
<DEFVAL>. { appendDefValue(yytext,yyleng); }
diff --git a/src/V3Premit.cpp b/src/V3Premit.cpp
index 0b46054..1fe71fb 100644
--- a/src/V3Premit.cpp
+++ b/src/V3Premit.cpp
@@ -352,7 +352,7 @@ private:
while (searchp && searchp->castComment()) searchp = searchp->nextp();
if (searchp
&& searchp->castDisplay()
- && nodep->filep()->sameTree(searchp->castDisplay()->filep())) {
+ && nodep->filep()->sameGateTree(searchp->castDisplay()->filep())) {
// There's another display next; we can just wait to flush
} else {
UINFO(4,"Autoflush "<<nodep<<endl);
diff --git a/src/V3Scope.cpp b/src/V3Scope.cpp
index ce2dffa..d3f2d73 100644
--- a/src/V3Scope.cpp
+++ b/src/V3Scope.cpp
@@ -241,6 +241,7 @@ private:
if (!nodep->user1p()) {
AstVarScope* varscp = new AstVarScope(nodep->fileline(), m_scopep, nodep);
UINFO(6," New scope "<<varscp<<endl);
+ if (m_aboveCellp && !m_aboveCellp->isTrace()) varscp->trace(false);
nodep->user1p(varscp);
if (!m_scopep) nodep->v3fatalSrc("No scope for var");
m_varScopes.insert(make_pair(make_pair(nodep, m_scopep), varscp));
@@ -258,8 +259,8 @@ private:
// the var's referenced package etc might not be created yet.
// So push to a list and post-correct
m_varRefScopes.insert(make_pair(nodep, m_scopep));
- }
- }
+ }
+ }
virtual void visit(AstScopeName* nodep, AstNUser*) {
// If there's a %m in the display text, we add a special node that will contain the name()
string prefix = (string)("__DOT__")+m_scopep->name();
diff --git a/src/V3Table.cpp b/src/V3Table.cpp
index 19e38b2..625b005 100644
--- a/src/V3Table.cpp
+++ b/src/V3Table.cpp
@@ -353,7 +353,7 @@ private:
== var2p->dtypep()->arrayUnpackedElements())) {
AstNode* init1p = var1p->valuep()->castInitArray();
AstNode* init2p = var2p->valuep()->castInitArray();
- if (init1p->sameTree(init2p)) {
+ if (init1p->sameGateTree(init2p)) {
UINFO(8," Duplicate table var "<<vsc2p<<" == "<<vsc1p<<endl);
vsc1p->unlinkFrBack()->deleteTree();
return vsc2p;
diff --git a/src/V3TraceDecl.cpp b/src/V3TraceDecl.cpp
index aa84f92..2bbfbb4 100644
--- a/src/V3TraceDecl.cpp
+++ b/src/V3TraceDecl.cpp
@@ -64,13 +64,17 @@ private:
return level;
}
- const char* varIgnoreTrace(AstVar* nodep) {
+ const char* vscIgnoreTrace(AstVarScope* nodep) {
// Return true if this shouldn't be traced
// See also similar rule in V3Coverage::varIgnoreToggle
- string prettyName = nodep->prettyName();
- if (!nodep->isTrace()) {
+ AstVar* varp = nodep->varp();
+ string prettyName = varp->prettyName();
+ if (!varp->isTrace()) {
return "Verilator trace_off";
}
+ else if (!nodep->isTrace()) {
+ return "Verilator cell trace_off";
+ }
else if (!v3Global.opt.traceUnderscore()) {
if (prettyName.size()>=1 && prettyName[0] == '_')
return "Leading underscore";
@@ -163,8 +167,8 @@ private:
m_traVscp = nodep;
m_traValuep = NULL;
- if (varIgnoreTrace(varp)) {
- addIgnore(varIgnoreTrace(varp));
+ if (vscIgnoreTrace(nodep)) {
+ addIgnore(vscIgnoreTrace(nodep));
} else {
++m_statSigs;
if (nodep->valuep()) m_traValuep = nodep->valuep()->cloneTree(true);
diff --git a/src/V3Unknown.cpp b/src/V3Unknown.cpp
index be10ab7..d1d9f70 100644
--- a/src/V3Unknown.cpp
+++ b/src/V3Unknown.cpp
@@ -337,14 +337,14 @@ private:
// Find range of dtype we are selecting from
// Similar code in V3Const::warnSelect
int maxmsb = nodep->fromp()->dtypep()->width()-1;
- int maxlsb = maxmsb - nodep->width() + 1;
if (debug()>=9) nodep->dumpTree(cout,"sel_old: ");
- V3Number maxlsbnum (nodep->fileline(), nodep->lsbp()->width(), maxlsb);
+ V3Number maxmsbnum (nodep->fileline(), nodep->lsbp()->width(), maxmsb);
- // See if the condition is constant true
+ // If (maxmsb >= selected), we're in bound
AstNode* condp = new AstGte (nodep->fileline(),
- new AstConst(nodep->fileline(), maxlsbnum),
+ new AstConst(nodep->fileline(), maxmsbnum),
nodep->lsbp()->cloneTree(false));
+ // See if the condition is constant true (e.g. always in bound due to constant select)
// Note below has null backp(); the Edit function knows how to deal with that.
condp = V3Const::constifyEdit(condp);
if (condp->isOne()) {
@@ -352,7 +352,7 @@ private:
condp->deleteTree();
}
else if (!lvalue) {
- // SEL(...) -> COND(LTE(bit<=maxlsb), ARRAYSEL(...), {width{1'bx}})
+ // SEL(...) -> COND(LTE(bit<=maxmsb), ARRAYSEL(...), {width{1'bx}})
AstNRelinker replaceHandle;
nodep->unlinkFrBack(&replaceHandle);
V3Number xnum (nodep->fileline(), nodep->width());
diff --git a/src/V3Unroll.cpp b/src/V3Unroll.cpp
index 80d66f4..135560d 100644
--- a/src/V3Unroll.cpp
+++ b/src/V3Unroll.cpp
@@ -164,15 +164,27 @@ private:
bool gt = condp->castGt() || condp->castGtS();
bool gte = condp->castGte() || condp->castGteS();
if (!lt && !lte && !gt && !gte)
- return cantUnroll(nodep, "condition not <= or <");
- AstNodeBiop* condBip = condp->castNodeBiop();
- if (!condBip->rhsp()->castVarRef())
+ return cantUnroll(nodep, "condition not <=, <, >= or >");
+ AstNodeBiop* cmpInstrp = condp->castNodeBiop();
+ bool cmpVarLhs;
+ if (cmpInstrp->lhsp()->castVarRef()
+ && cmpInstrp->lhsp()->castVarRef()->varp() == m_forVarp
+ && cmpInstrp->lhsp()->castVarRef()->varScopep() == m_forVscp) {
+ cmpVarLhs = true;
+ } else if (cmpInstrp->rhsp()->castVarRef()
+ && cmpInstrp->rhsp()->castVarRef()->varp() == m_forVarp
+ && cmpInstrp->rhsp()->castVarRef()->varScopep() == m_forVscp) {
+ cmpVarLhs = false;
+ } else if (!cmpInstrp->rhsp()->castVarRef()) {
return cantUnroll(nodep, "no variable on rhs of condition");
- if (condBip->rhsp()->castVarRef()->varp() != m_forVarp
- || condBip->rhsp()->castVarRef()->varScopep() != m_forVscp)
+ } else {
return cantUnroll(nodep, "different variable in condition");
- if (m_generate) V3Const::constifyParamsEdit(condBip->lhsp()); // rhsp may change
- AstConst* constStopp = condBip->lhsp()->castConst();
+ }
+
+ if (m_generate) V3Const::constifyParamsEdit(cmpVarLhs ? cmpInstrp->rhsp()
+ : cmpInstrp->lhsp()); // rhsp/lhsp may change
+ AstConst* constStopp = (cmpVarLhs ? cmpInstrp->rhsp()->castConst()
+ : cmpInstrp->lhsp()->castConst());
if (!constStopp) return cantUnroll(nodep, "non-constant final value");
UINFO(8, " Stop expr ok: "<<constStopp<<endl);
//
@@ -217,9 +229,9 @@ private:
if (m_varAssignHit) return cantUnroll(nodep, "genvar assigned *inside* loop");
//
// Finally, we can do it
- forUnroller(nodep, initp, precondsp, condp, incp, bodysp,
+ forUnroller(nodep, initp, precondsp, incp, bodysp,
constInitp->num(),
- condBip, constStopp->num(),
+ cmpInstrp, constStopp->num(), cmpVarLhs,
incInstrp, constIncp->num()); nodep = NULL;
// Cleanup
return true;
@@ -227,10 +239,10 @@ private:
void forUnroller(AstNode* nodep,
AstNode* initp,
- AstNode* precondsp, AstNode* condp,
+ AstNode* precondsp,
AstNode* incp, AstNode* bodysp,
const V3Number& numInit,
- AstNodeBiop* cmpInstrp, const V3Number& numStop,
+ AstNodeBiop* cmpInstrp, const V3Number& numStop, bool cmpVarLhs,
AstNodeBiop* incInstrp, const V3Number& numInc) {
UINFO(4, " Unroll for var="<<numInit<<"; var<"<<numStop<<"; var+="<<numInc<<endl);
UINFO(6, " cmpI "<<cmpInstrp<<endl);
@@ -270,7 +282,11 @@ private:
UINFO(8," Looping "<<loopValue<<endl);
// if loopValue<valStop
V3Number contin (nodep->fileline(), 1);
- cmpInstrp->numberOperate(contin, numStop, loopValue);
+ if (cmpVarLhs) {
+ cmpInstrp->numberOperate(contin, loopValue, numStop);
+ } else {
+ cmpInstrp->numberOperate(contin, numStop, loopValue);
+ }
if (contin.isEqZero()) {
break; // Done with the loop
} else {
diff --git a/src/V3Width.cpp b/src/V3Width.cpp
index 62bdb3e..2a8fd9d 100644
--- a/src/V3Width.cpp
+++ b/src/V3Width.cpp
@@ -931,7 +931,7 @@ private:
: nodep->findBitDType(width, width, underDtp->numeric()));
nodep->dtypep(newDtp);
// We ignore warnings as that is sort of the point of a cast
- iterateCheck(nodep,"Cast LHS",nodep->lhsp(),SELF,FINAL,newDtp,EXTEND_EXP,false);
+ iterateCheck(nodep,"Cast LHS",nodep->lhsp(),CONTEXT,FINAL,newDtp,EXTEND_EXP,false);
}
if (vup->c()->final()) {
// CastSize not needed once sizes determined
diff --git a/src/config_build.h b/src/config_build.h
index f92709e..b254886 100644
--- a/src/config_build.h
+++ b/src/config_build.h
@@ -27,7 +27,7 @@
//**** Version and host name
// Autoconf substitutes this with the strings from AC_INIT.
-#define PACKAGE_STRING "Verilator 3.864 2014-09-21"
+#define PACKAGE_STRING "Verilator 3.866 2014-11-15"
#define DTVERSION PACKAGE_STRING
diff --git a/src/config_rev.h b/src/config_rev.h
index b2eb163..42c6ac1 100644
--- a/src/config_rev.h
+++ b/src/config_rev.h
@@ -1 +1 @@
-static const char* DTVERSION_rev = "verilator_3_862-18-ge8edbad";
+static const char* DTVERSION_rev = "verilator_3_864-18-g55f0d4d";
diff --git a/src/verilog.y b/src/verilog.y
index 5e4d869..4cdeb17 100644
--- a/src/verilog.y
+++ b/src/verilog.y
@@ -62,6 +62,7 @@ public:
int m_pinNum; // Pin number currently parsing
string m_instModule; // Name of module referenced for instantiations
AstPin* m_instParamp; // Parameters for instantiations
+ bool m_tracingParse; // Tracing disable for parser
static int s_modTypeImpNum; // Implicit type number, incremented each module
@@ -78,6 +79,7 @@ public:
m_instParamp = NULL;
m_varAttrp = NULL;
m_caseAttrp = NULL;
+ m_tracingParse = true;
}
static V3ParseGrammar* singletonp() {
static V3ParseGrammar singleton;
@@ -86,6 +88,9 @@ public:
// METHODS
void argWrapList(AstNodeFTaskRef* nodep);
+ bool allTracingOn(FileLine* fl) {
+ return v3Global.opt.trace() && m_tracingParse && fl->tracingOn();
+ }
AstNodeDType* createArray(AstNodeDType* basep, AstRange* rangep, bool isPacked);
AstVar* createVariable(FileLine* fileline, string name, AstRange* arrayp, AstNode* attrsp);
AstNode* createSupplyExpr(FileLine* fileline, string name, int value);
@@ -685,7 +690,7 @@ timeunits_declaration<nodep>: // ==IEEE: timeunits_declaration
package_declaration: // ==IEEE: package_declaration
packageFront package_itemListE yENDPACKAGE endLabelE
- { $1->modTrace(v3Global.opt.trace() && $1->fileline()->tracingOn()); // Stash for implicit wires, etc
+ { $1->modTrace(GRAMMARP->allTracingOn($1->fileline())); // Stash for implicit wires, etc
if ($2) $1->addStmtp($2);
SYMP->popScope($1);
GRAMMARP->endLabel($<fl>4,$1,$4); }
@@ -695,7 +700,7 @@ packageFront<modulep>:
yPACKAGE idAny ';'
{ $$ = new AstPackage($1,*$2);
$$->inLibrary(true); // packages are always libraries; don't want to make them a "top"
- $$->modTrace(v3Global.opt.trace());
+ $$->modTrace(GRAMMARP->allTracingOn($$->fileline()));
PARSEP->rootp()->addModulep($$);
SYMP->pushNew($$); }
;
@@ -768,7 +773,7 @@ module_declaration: // ==IEEE: module_declaration
// // IEEE: module_nonansi_header + module_ansi_header
modFront importsAndParametersE portsStarE ';'
module_itemListE yENDMODULE endLabelE
- { $1->modTrace(v3Global.opt.trace() && $1->fileline()->tracingOn()); // Stash for implicit wires, etc
+ { $1->modTrace(GRAMMARP->allTracingOn($1->fileline())); // Stash for implicit wires, etc
if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3);
if ($5) $1->addStmtp($5);
SYMP->popScope($1);
@@ -778,6 +783,7 @@ module_declaration: // ==IEEE: module_declaration
{ $1->modTrace(false); // Stash for implicit wires, etc
if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3);
if ($5) $1->addStmtp($5);
+ GRAMMARP->m_tracingParse = true;
SYMP->popScope($1);
GRAMMARP->endLabel($<fl>7,$1,$7); }
//
@@ -790,7 +796,7 @@ modFront<modulep>:
// // any formal arguments, as the arguments must land in the new scope.
yMODULE lifetimeE idAny
{ $$ = new AstModule($1,*$3); $$->inLibrary(PARSEP->inLibrary()||PARSEP->inCellDefine());
- $$->modTrace(v3Global.opt.trace());
+ $$->modTrace(GRAMMARP->allTracingOn($$->fileline()));
PARSEP->rootp()->addModulep($$);
SYMP->pushNew($$); }
;
@@ -806,7 +812,7 @@ udpFront<modulep>:
{ $$ = new AstPrimitive($1,*$3); $$->inLibrary(true);
$$->modTrace(false);
$$->addStmtp(new AstPragma($1,AstPragmaType::INLINE_MODULE));
- PARSEP->fileline()->tracingOn(false);
+ GRAMMARP->m_tracingParse = false;
PARSEP->rootp()->addModulep($$);
SYMP->pushNew($$); }
;
@@ -1011,7 +1017,7 @@ program_declaration: // IEEE: program_declaration + program_nonansi_header + pr
// // timeunits_delcarationE is instead in program_item
pgmFront parameter_port_listE portsStarE ';'
program_itemListE yENDPROGRAM endLabelE
- { $1->modTrace(v3Global.opt.trace() && $1->fileline()->tracingOn()); // Stash for implicit wires, etc
+ { $1->modTrace(GRAMMARP->allTracingOn($1->fileline())); // Stash for implicit wires, etc
if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3);
if ($5) $1->addStmtp($5);
SYMP->popScope($1);
@@ -1023,7 +1029,7 @@ program_declaration: // IEEE: program_declaration + program_nonansi_header + pr
pgmFront<modulep>:
yPROGRAM lifetimeE idAny/*new_program*/
{ $$ = new AstModule($1,*$3); $$->inLibrary(PARSEP->inLibrary()||PARSEP->inCellDefine());
- $$->modTrace(v3Global.opt.trace());
+ $$->modTrace(GRAMMARP->allTracingOn($$->fileline()));
PARSEP->rootp()->addModulep($$);
SYMP->pushNew($$); }
;
@@ -1594,8 +1600,9 @@ implicit_typeE<dtypep>: // IEEE: part of *data_type_or_implicit
type_declaration<nodep>: // ==IEEE: type_declaration
// // Use idAny, as we can redeclare a typedef on an existing typedef
- yTYPEDEF data_type idAny variable_dimensionListE ';' { $$ = new AstTypedef($<fl>1, *$3, VFlagChildDType(), GRAMMARP->createArray($2,$4,false));
- SYMP->reinsert($$); }
+ yTYPEDEF data_type idAny variable_dimensionListE dtypeAttrListE ';'
+ /**/ { $$ = new AstTypedef($<fl>1, *$3, $5, VFlagChildDType(), GRAMMARP->createArray($2,$4,false));
+ SYMP->reinsert($$); }
//UNSUP yTYPEDEF id/*interface*/ '.' idAny/*type*/ idAny/*type*/ ';' { $$ = NULL; $1->v3error("Unsupported: SystemVerilog 2005 typedef in this context"); } //UNSUP
// // Combines into above "data_type id" rule
// // Verilator: Not important what it is in the AST, just need to make sure the yaID__aTYPE gets returned
@@ -1606,6 +1613,20 @@ type_declaration<nodep>: // ==IEEE: type_declaration
//UNSUP yTYPEDEF yCLASS idAny ';' { $$ = NULL; $$ = new AstTypedefFwd($<fl>1, *$3); SYMP->reinsert($$); }
;
+dtypeAttrListE<nodep>:
+ /* empty */ { $$ = NULL; }
+ | dtypeAttrList { $$ = $1; }
+ ;
+
+dtypeAttrList<nodep>:
+ dtypeAttr { $$ = $1; }
+ | dtypeAttrList dtypeAttr { $$ = $1->addNextNull($2); }
+ ;
+
+dtypeAttr<nodep>:
+ yVL_PUBLIC { $$ = new AstAttrOf($1,AstAttrType::DT_PUBLIC); }
+ ;
+
//************************************************
// Module Items
@@ -2017,9 +2038,11 @@ instnameList<nodep>:
| instnameList ',' instnameParen { $$ = $1->addNext($3); }
;
-instnameParen<nodep>:
- id instRangeE '(' cellpinList ')' { $$ = new AstCell($<fl>1,*$1,GRAMMARP->m_instModule,$4, GRAMMARP->m_instParamp,$2); }
- | id instRangeE { $$ = new AstCell($<fl>1,*$1,GRAMMARP->m_instModule,NULL,GRAMMARP->m_instParamp,$2); }
+instnameParen<cellp>:
+ id instRangeE '(' cellpinList ')' { $$ = new AstCell($<fl>1,*$1,GRAMMARP->m_instModule,$4, GRAMMARP->m_instParamp,$2);
+ $$->trace(GRAMMARP->allTracingOn($<fl>1)); }
+ | id instRangeE { $$ = new AstCell($<fl>1,*$1,GRAMMARP->m_instModule,NULL,GRAMMARP->m_instParamp,$2);
+ $$->trace(GRAMMARP->allTracingOn($<fl>1)); }
//UNSUP instRangeE '(' cellpinList ')' { UNSUP } // UDP
// // Adding above and switching to the Verilog-Perl syntax
// // causes a shift conflict due to use of idClassSel inside exprScope.
@@ -3783,7 +3806,7 @@ AstVar* V3ParseGrammar::createVariable(FileLine* fileline, string name, AstRange
// Propagate from current module tracing state
if (nodep->isGenVar()) nodep->trace(false);
else if (nodep->isParam() && !v3Global.opt.traceParams()) nodep->trace(false);
- else nodep->trace(v3Global.opt.trace() && nodep->fileline()->tracingOn());
+ else nodep->trace(allTracingOn(nodep->fileline()));
// Remember the last variable created, so we can attach attributes to it in later parsing
GRAMMARP->m_varAttrp = nodep;
diff --git a/test_regress/t/t_param_public.pl b/test_regress/t/t_cellarray.pl
similarity index 71%
copy from test_regress/t/t_param_public.pl
copy to test_regress/t/t_cellarray.pl
index f912897..b39a34d 100755
--- a/test_regress/t/t_param_public.pl
+++ b/test_regress/t/t_cellarray.pl
@@ -8,11 +8,16 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
# Version 2.0.
compile (
- );
+ v_flags2 => ["--stats"],
+ );
execute (
- check_finished=>1,
- );
+ check_finished=>1,
+ );
+
+if ($Self->{vlt}) {
+ file_grep ($Self->{stats}, qr/Optimizations, Gate assign merged\s+(\d+)/i, 28);
+};
ok(1);
1;
diff --git a/test_regress/t/t_cellarray.v b/test_regress/t/t_cellarray.v
new file mode 100644
index 0000000..0d2a62d
--- /dev/null
+++ b/test_regress/t/t_cellarray.v
@@ -0,0 +1,100 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed into the Public Domain, for any use,
+// without warranty, 2014 by Jie Xu.
+//
+
+// change these two parameters to see the speed differences
+`define DATA_WIDTH 8
+`define REP_COUNT4 `DATA_WIDTH/4
+`define REP_COUNT2 `DATA_WIDTH/2
+
+
+module t (/*AUTOARG*/
+ // Inputs
+ clk
+ );
+ input clk;
+ reg [3:0] count4 = 0;
+ reg [1:0] count2 = 0;
+
+ reg [`DATA_WIDTH-1:0] a = {`REP_COUNT4{4'b0000}};
+ reg [`DATA_WIDTH-1:0] b = {`REP_COUNT4{4'b1111}};
+ reg [`DATA_WIDTH-1:0] c = {`REP_COUNT4{4'b1111}};
+ reg [`DATA_WIDTH-1:0] d = {`REP_COUNT4{4'b1111}};
+ reg [`DATA_WIDTH-1:0] res1;
+ reg [`DATA_WIDTH-1:0] res2;
+ reg [`DATA_WIDTH-1:0] res3;
+ reg [`DATA_WIDTH-1:0] res4;
+
+ drv1 t_drv1 [`DATA_WIDTH-1:0] (.colSelA(a), .datao(res1));
+ drv2 t_drv2 [`DATA_WIDTH-1:0] (.colSelA(a), .colSelB(b), .datao(res2));
+ drv3 t_drv3 [`DATA_WIDTH-1:0] (.colSelA(a), .colSelB(b), .colSelC(c), .datao(res3));
+ drv4 t_drv4 [`DATA_WIDTH-1:0] (.colSelA(a), .colSelB(b), .colSelC(c), .colSelD(d), .datao(res4));
+
+ always@(posedge clk)
+ begin
+ count2 <= count2 + 1;
+ count4 <= count4 + 1;
+ a <= {`REP_COUNT4{count4}};
+ b <= {`REP_COUNT4{count4}};
+ c <= {`REP_COUNT2{count2}};
+ d <= {`REP_COUNT2{count2}};
+
+ if (res1 != (a)) begin
+ $stop;
+ end
+ if (res2 != (a&b)) begin
+ $stop;
+ end
+ if (res3 != (a&b&c)) begin
+ $stop;
+ end
+ if (res4 != (a&b&c&d)) begin
+ $stop;
+ end
+
+ if (count4 > 10) begin
+ $write("*-* All Finished *-*\n");
+ $finish;
+ end
+ end
+endmodule
+
+
+module drv1
+ (input colSelA,
+ output datao
+ );
+ assign datao = colSelA;
+endmodule
+
+module drv2
+ (input colSelA,
+ input colSelB,
+ output datao
+ );
+ assign datao = colSelB & colSelA;
+endmodule
+
+module drv3
+ (input colSelA,
+ input colSelB,
+ input colSelC,
+ output datao
+ );
+ assign datao = colSelB & colSelA & colSelC;
+
+endmodule
+
+module drv4
+ (input colSelA,
+ input colSelB,
+ input colSelC,
+ input colSelD,
+ output datao
+ );
+ assign datao = colSelB & colSelA & colSelC & colSelD;
+
+endmodule
+
diff --git a/test_regress/t/t_param_public.pl b/test_regress/t/t_concat_opt.pl
similarity index 78%
copy from test_regress/t/t_param_public.pl
copy to test_regress/t/t_concat_opt.pl
index f912897..29bf04d 100755
--- a/test_regress/t/t_param_public.pl
+++ b/test_regress/t/t_concat_opt.pl
@@ -2,17 +2,17 @@
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
+# Copyright 2004 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
- );
+ );
execute (
- check_finished=>1,
- );
+ check_finished=>1,
+ );
ok(1);
1;
diff --git a/test_regress/t/t_concat_opt.v b/test_regress/t/t_concat_opt.v
new file mode 100644
index 0000000..fe723f2
--- /dev/null
+++ b/test_regress/t/t_concat_opt.v
@@ -0,0 +1,71 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed into the Public Domain, for any use,
+// without warranty, 2004 by Jie Xu.
+//
+// The test was added together with the concat optimization.
+
+module t (/*AUTOARG*/
+ // Inputs
+ clk
+ );
+
+ input clk;
+ integer cyc; initial cyc=1;
+
+ reg [31:0] in_a;
+ reg [31:0] in_b;
+ reg [31:0] in_c;
+ reg [31:0] in_d;
+ reg [31:0] in_e;
+ reg [15:0] in_f;
+ wire [31:0] in_g;
+
+ assign in_g = in_a << 4;
+
+ reg [31:0] out_x;
+ reg [31:0] out_y;
+ reg [31:0] out_z;
+ reg [31:0] out_o;
+ reg [31:0] out_p;
+ reg [31:0] out_q;
+
+ assign out_x = {in_a[31:16] & in_f, in_a[15:0] & in_f};
+ assign out_y = {in_a[31:18] & in_b[31:18], in_a[17:0] & in_b[17:0]};
+ assign out_z = {in_c[31:14] & in_d[31:14] & in_e[31:14], in_c[13:0] & in_d[13:0] & in_e[13:0]};
+ assign out_o = out_z | out_y;
+ assign out_p = {in_a[31:16] & in_f | in_e[31:16], in_a[15:0] & in_f | in_e[15:0]};
+ assign out_q = {{in_a[31:25] ^ in_g[31:25], in_a[24:16] ^ in_g[24:16]}, {in_a[15:5] ^ in_g[15:5], in_a[4:0] ^ in_g[4:0]}};
+
+ always @ (posedge clk) begin
+ if (cyc!=0) begin
+ cyc <= cyc + 1;
+ in_a <= cyc;
+ in_b <= cyc + 1;
+ in_c <= cyc + 3;
+ in_d <= cyc + 8;
+ in_e <= cyc;
+ in_f <= cyc[15:0];
+
+ if (out_x != (in_a & {2{in_f}}))
+ $stop;
+ if (out_y != (in_a&in_b))
+ $stop;
+ if (out_z != (in_e&in_d&in_c))
+ $stop;
+ if (out_o != (((in_a&in_b)|(in_c&in_e&in_d))))
+ $stop;
+ if (out_p != (in_a & {2{in_f}} | in_e))
+ $stop;
+ if (out_q != (in_a ^ in_g))
+ $stop;
+
+ if (cyc==100) begin
+ $write("*-* All Finished *-*\n");
+ $finish;
+ end
+ end
+ end
+
+endmodule
+
diff --git a/test_regress/t/t_enum_public.cpp b/test_regress/t/t_enum_public.cpp
new file mode 100644
index 0000000..8beeb64
--- /dev/null
+++ b/test_regress/t/t_enum_public.cpp
@@ -0,0 +1,26 @@
+// -*- mode: C++; c-file-style: "cc-mode" -*-
+//
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed into the Public Domain, for any use,
+// without warranty, 2006 by Wilson Snyder.
+
+#include <verilated.h>
+#include "Vt_enum_public.h"
+
+#include "Vt_enum_public_p3.h"
+#include "Vt_enum_public_p62.h"
+
+int main (int argc, char *argv[]) {
+ Vt_enum_public *topp = new Vt_enum_public;
+
+ Verilated::debug(0);
+
+ // Make sure public tag worked
+ if (Vt_enum_public_p3::ZERO || Vt_enum_public_p3::ONE) {}
+ if (Vt_enum_public_p62::ZERO || Vt_enum_public_p62::ALLONE) {}
+
+ for (int i = 0; i < 10; i++) {
+ topp->eval();
+ }
+}
diff --git a/test_regress/t/t_param_public.pl b/test_regress/t/t_enum_public.pl
similarity index 72%
copy from test_regress/t/t_param_public.pl
copy to test_regress/t/t_enum_public.pl
index f912897..4408cbf 100755
--- a/test_regress/t/t_param_public.pl
+++ b/test_regress/t/t_enum_public.pl
@@ -7,8 +7,16 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
-compile (
- );
+if ($Self->{vlt}) {
+ compile (
+ verilator_flags2 => ["--exe $Self->{t_dir}/$Self->{name}.cpp"],
+ make_top_shell => 0,
+ make_main => 0,
+ );
+} else {
+ compile (
+ );
+}
execute (
check_finished=>1,
diff --git a/test_regress/t/t_enum_public.v b/test_regress/t/t_enum_public.v
new file mode 100644
index 0000000..f3b1a93
--- /dev/null
+++ b/test_regress/t/t_enum_public.v
@@ -0,0 +1,33 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed into the Public Domain, for any use,
+// without warranty, 2009 by Wilson Snyder.
+
+package p3;
+ typedef enum logic [2:0] {
+ ZERO = 3'b0,
+ ONE = 3'b1 } e3_t /*verilator public*/;
+endpackage
+
+package p62;
+ typedef enum logic [62:0] {
+ ZERO = '0,
+ ALLONE = '1 } e62_t /*verilator public*/;
+endpackage
+
+module t (/*AUTOARG*/);
+
+ enum integer {
+ EI_A,
+ EI_B,
+ EI_C
+ } m_state;
+
+ initial begin
+ m_state = EI_A;
+ $write("*-* All Finished *-*\n");
+ $finish;
+ end
+
+endmodule
+
diff --git a/test_regress/t/t_param_public.pl b/test_regress/t/t_flag_define.pl
similarity index 78%
copy from test_regress/t/t_param_public.pl
copy to test_regress/t/t_flag_define.pl
index f912897..0ecc0c0 100755
--- a/test_regress/t/t_param_public.pl
+++ b/test_regress/t/t_flag_define.pl
@@ -2,12 +2,13 @@
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
+# Copyright 2008 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
+ v_flags2 => ["-f t/t_flag_define.vc"],
);
execute (
diff --git a/test_regress/t/t_flag_define.v b/test_regress/t/t_flag_define.v
new file mode 100644
index 0000000..d26cc18
--- /dev/null
+++ b/test_regress/t/t_flag_define.v
@@ -0,0 +1,61 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed into the Public Domain, for any use,
+// without warranty, 2014 by Wilson Snyder
+
+`define STRINGIFY(x) `"x`"
+
+module t;
+ initial begin
+`ifdef D1A
+ if (`STRINGIFY(`D4B) !== "") $stop;
+`else
+ $write("%%Error: Missing define\n"); $stop;
+`endif
+
+`ifdef D2A
+ if (`STRINGIFY(`D2A) !== "VALA") $stop;
+`else
+ $write("%%Error: Missing define\n"); $stop;
+`endif
+
+`ifdef D3A
+ if (`STRINGIFY(`D4B) !== "") $stop;
+`else
+ $write("%%Error: Missing define\n"); $stop;
+`endif
+
+`ifdef D3B
+ if (`STRINGIFY(`D4B) !== "") $stop;
+`else
+ $write("%%Error: Missing define\n"); $stop;
+`endif
+
+`ifdef D4A
+ if (`STRINGIFY(`D4A) !== "VALA") $stop;
+`else
+ $write("%%Error: Missing define\n"); $stop;
+`endif
+
+`ifdef D4B
+ if (`STRINGIFY(`D4B) !== "") $stop;
+`else
+ $write("%%Error: Missing define\n"); $stop;
+`endif
+
+`ifdef D5A
+ if (`STRINGIFY(`D5A) !== "VALA") $stop;
+`else
+ $write("%%Error: Missing define\n"); $stop;
+`endif
+
+`ifdef D5A
+ if (`STRINGIFY(`D5B) !== "VALB") $stop;
+`else
+ $write("%%Error: Missing define\n"); $stop;
+`endif
+
+ $write("*-* All Finished *-*\n");
+ $finish;
+ end
+endmodule
diff --git a/test_regress/t/t_flag_define.vc b/test_regress/t/t_flag_define.vc
new file mode 100644
index 0000000..f0b52c5
--- /dev/null
+++ b/test_regress/t/t_flag_define.vc
@@ -0,0 +1,7 @@
++define+D1A
++define+D2A=VALA
++define+D3A+D3B
++define+D4A=VALA+D4B
++define+D5A=VALA+D5B=VALB
+// Quotes do NOT escape the plus
+//+define+D5A="VALA+D5B"+D5C
diff --git a/test_regress/t/t_math_signed5.v b/test_regress/t/t_math_signed5.v
index 3bd62b7..f8d1700 100644
--- a/test_regress/t/t_math_signed5.v
+++ b/test_regress/t/t_math_signed5.v
@@ -26,6 +26,7 @@
reg [5:0] w6_u;
reg [15:0] w16a_u;
reg [15:0] w16_u;
+ reg [31:0] w32_u;
real r;
reg signed [4:0] bug754_a;
@@ -162,6 +163,16 @@
w4_u = (w4_u >> w4_u) ^~ (w4_u >> w4_u);
`checkh(w4_u, 4'b1111);
+ // bug828
+ // verilator lint_off WIDTH
+ w32_u = 32'(signed'({4'b0001,5'b10000}) << 3);
+ `checkh(w32_u, 32'h0000_0180);
+ w32_u = 32'(signed'({4'b0011,5'b10000}) << 3);
+ `checkh(w32_u, 32'h0000_0380);
+ // verilator lint_on WIDTH
+ w32_u = 32'(signed'({4'b0011,5'b10000})) << 3; // Check no width warning
+ `checkh(w32_u, 32'h0000_0380);
+
if (fail) $stop;
$write("*-* All Finished *-*\n");
$finish;
diff --git a/test_regress/t/t_param_public.cpp b/test_regress/t/t_param_public.cpp
new file mode 100644
index 0000000..59c3338
--- /dev/null
+++ b/test_regress/t/t_param_public.cpp
@@ -0,0 +1,24 @@
+// -*- mode: C++; c-file-style: "cc-mode" -*-
+//
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed into the Public Domain, for any use,
+// without warranty, 2006 by Wilson Snyder.
+
+#include <verilated.h>
+#include "Vt_param_public.h"
+
+#include "Vt_param_public_p.h"
+
+int main (int argc, char *argv[]) {
+ Vt_param_public *topp = new Vt_param_public;
+
+ Verilated::debug(0);
+
+ // Make sure public tag worked
+ if (Vt_param_public_p::INPACK) {}
+
+ for (int i = 0; i < 10; i++) {
+ topp->eval();
+ }
+}
diff --git a/test_regress/t/t_param_public.pl b/test_regress/t/t_param_public.pl
index f912897..4408cbf 100755
--- a/test_regress/t/t_param_public.pl
+++ b/test_regress/t/t_param_public.pl
@@ -7,8 +7,16 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
-compile (
- );
+if ($Self->{vlt}) {
+ compile (
+ verilator_flags2 => ["--exe $Self->{t_dir}/$Self->{name}.cpp"],
+ make_top_shell => 0,
+ make_main => 0,
+ );
+} else {
+ compile (
+ );
+}
execute (
check_finished=>1,
diff --git a/test_regress/t/t_param_public.v b/test_regress/t/t_param_public.v
index 045c952..e8b815f 100644
--- a/test_regress/t/t_param_public.v
+++ b/test_regress/t/t_param_public.v
@@ -36,3 +36,8 @@ module b #(
initial if ($c32("TWO") != 2) $stop;
`endif
endmodule
+
+//bug804
+package p;
+ localparam INPACK /*verilator public*/ = 6;
+endpackage
diff --git a/test_regress/t/t_preproc.out b/test_regress/t/t_preproc.out
index 5c918d4..7e0bddf 100644
--- a/test_regress/t/t_preproc.out
+++ b/test_regress/t/t_preproc.out
@@ -788,6 +788,10 @@ module t;
initial $write("GOT='%s' EXP='%s'\n", "foo `A(bar) baz", "foo `A(bar) baz");
+
+
+
+ initial $write("Slashed=`%s'\n", "1//2.3");
endmodule
@@ -809,4 +813,4 @@ predef 1 1
predef 2 2
-`line 544 "t/t_preproc.v" 2
+`line 548 "t/t_preproc.v" 2
diff --git a/test_regress/t/t_preproc.v b/test_regress/t/t_preproc.v
index 25ad540..7137314 100644
--- a/test_regress/t/t_preproc.v
+++ b/test_regress/t/t_preproc.v
@@ -520,6 +520,10 @@ module t;
`define A(name) boo name hiss
initial $write("GOT='%s' EXP='%s'\n", `STR(`A(bar)), "foo `A(bar) baz");
`undef A `undef STR
+ //----
+ // bug845
+`define SLASHED "1//2.3"
+ initial $write("Slashed=`%s'\n", `SLASHED);
endmodule
//======================================================================
// IEEE mandated predefines
diff --git a/test_regress/t/t_param_public.pl b/test_regress/t/t_select_bound1.pl
similarity index 100%
copy from test_regress/t/t_param_public.pl
copy to test_regress/t/t_select_bound1.pl
diff --git a/test_regress/t/t_select_bound1.v b/test_regress/t/t_select_bound1.v
new file mode 100644
index 0000000..8c57e18
--- /dev/null
+++ b/test_regress/t/t_select_bound1.v
@@ -0,0 +1,91 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed into the Public Domain, for any use,
+// without warranty, 2014 by Wilson Snyder.
+
+// bug823
+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 [2:0] in = crc[2:0];
+
+ /*AUTOWIRE*/
+ // Beginning of automatic wires (for undeclared instantiated-module outputs)
+ wire [3:0] mask; // From test of Test.v
+ wire [3:0] out; // From test of Test.v
+ // End of automatics
+
+ Test test (/*AUTOINST*/
+ // Outputs
+ .out (out[3:0]),
+ .mask (mask[3:0]),
+ // Inputs
+ .clk (clk),
+ .in (in[2:0]));
+
+ // Aggregate outputs into a single result vector
+ wire [63:0] result = {60'h0, out & mask};
+
+ // Test loop
+ always @ (posedge clk) begin
+`ifdef TEST_VERBOSE
+ $write("[%0t] cyc==%0d crc=%x out=%b mask=%b\n",$time, cyc, crc, out, mask);
+`endif
+ cyc <= cyc + 1;
+ crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
+ sum <= result ^ {sum[62:0],sum[63]^sum[2]^sum[0]};
+ if (cyc==0) begin
+ // Setup
+ crc <= 64'h5aef0c8d_d70a4497;
+ sum <= '0;
+ end
+ else if (cyc<10) begin
+ sum <= '0;
+ 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'ha9d3a7a69d2bea75
+ if (sum !== `EXPECTED_SUM) $stop;
+ $write("*-* All Finished *-*\n");
+ $finish;
+ end
+ end
+
+endmodule
+
+module Test (/*AUTOARG*/
+ // Outputs
+ out, mask,
+ // Inputs
+ clk, in
+ );
+
+ input clk;
+ input [2:0] in;
+ output reg [3:0] out;
+ output reg [3:0] mask;
+ localparam [15:5] p = 11'h1ac;
+
+ always @(posedge clk) begin
+ // verilator lint_off WIDTH
+ out <= p[15 + in -: 5];
+ // verilator lint_on WIDTH
+ mask[3] <= ((15 + in - 5) < 12);
+ mask[2] <= ((15 + in - 5) < 13);
+ mask[1] <= ((15 + in - 5) < 14);
+ mask[0] <= ((15 + in - 5) < 15);
+ end
+
+endmodule
diff --git a/test_regress/t/t_param_public.pl b/test_regress/t/t_select_bound2.pl
similarity index 100%
copy from test_regress/t/t_param_public.pl
copy to test_regress/t/t_select_bound2.pl
diff --git a/test_regress/t/t_select_bound2.v b/test_regress/t/t_select_bound2.v
new file mode 100644
index 0000000..ff6600d
--- /dev/null
+++ b/test_regress/t/t_select_bound2.v
@@ -0,0 +1,91 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed into the Public Domain, for any use,
+// without warranty, 2014 by Wilson Snyder.
+
+// bug823
+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 [6:0] in = crc[6:0];
+
+ /*AUTOWIRE*/
+ // Beginning of automatic wires (for undeclared instantiated-module outputs)
+ wire [3:0] mask; // From test of Test.v
+ wire [3:0] out; // From test of Test.v
+ // End of automatics
+
+ Test test (/*AUTOINST*/
+ // Outputs
+ .out (out[3:0]),
+ .mask (mask[3:0]),
+ // Inputs
+ .clk (clk),
+ .in (in[6:0]));
+
+ // Aggregate outputs into a single result vector
+ wire [63:0] result = {60'h0, out & mask};
+
+ // Test loop
+ always @ (posedge clk) begin
+`ifdef TEST_VERBOSE
+ $write("[%0t] cyc==%0d crc=%x out=%b mask=%b\n",$time, cyc, crc, out, mask);
+`endif
+ cyc <= cyc + 1;
+ crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
+ sum <= result ^ {sum[62:0],sum[63]^sum[2]^sum[0]};
+ if (cyc==0) begin
+ // Setup
+ crc <= 64'h5aef0c8d_d70a4497;
+ sum <= '0;
+ end
+ else if (cyc<10) begin
+ sum <= '0;
+ 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'h4e9d3a74e9d3f656
+ if (sum !== `EXPECTED_SUM) $stop;
+ $write("*-* All Finished *-*\n");
+ $finish;
+ end
+ end
+
+endmodule
+
+module Test (/*AUTOARG*/
+ // Outputs
+ out, mask,
+ // Inputs
+ clk, in
+ );
+
+ input clk;
+ input [6:0] in; // Note much wider than any index
+ output reg [3:0] out;
+ output reg [3:0] mask;
+ localparam [15:5] p = 11'h1ac;
+
+ always @(posedge clk) begin
+ // verilator lint_off WIDTH
+ out <= p[15 + in -: 5];
+ // verilator lint_on WIDTH
+ mask[3] <= ((15 + in - 5) < 12);
+ mask[2] <= ((15 + in - 5) < 13);
+ mask[1] <= ((15 + in - 5) < 14);
+ mask[0] <= ((15 + in - 5) < 15);
+ end
+
+endmodule
diff --git a/test_regress/t/t_select_plus.v b/test_regress/t/t_select_plus.v
index 09f4cfd..0d078c3 100644
--- a/test_regress/t/t_select_plus.v
+++ b/test_regress/t/t_select_plus.v
@@ -66,7 +66,7 @@ module t (/*AUTOARG*/
8'd04: begin if ((to^from)!==80'h6d000000000000000000) $stop; end
8'd05: begin if (((to^from)&~80'hf)!==80'h90000000000000000000) $stop; end // Exceed bounds, verilator may write index 0
8'd06: begin if (((to^from)&~80'hf)!==80'h00000000000000000020) $stop; end // Exceed bounds, verilator may write index 0
- 8'd07: begin if (((to^from)&~80'hf)!==80'h0c000000000000000000) $stop; end
+ 8'd07: begin if (((to^from)&~80'hf)!==80'h4c000000000000000000) $stop; end
8'd08: begin if ((to^from)!==80'h0004d000000000000000) $stop; end
8'd09: begin if (((to^from)&~80'hf)!==80'h00000000000000000000) $stop; end
default: $stop;
diff --git a/test_regress/t/t_param_public.pl b/test_regress/t/t_trace_array.pl
similarity index 65%
copy from test_regress/t/t_param_public.pl
copy to test_regress/t/t_trace_array.pl
index f912897..12e9fb1 100755
--- a/test_regress/t/t_param_public.pl
+++ b/test_regress/t/t_trace_array.pl
@@ -2,17 +2,20 @@
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
+# 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.
compile (
+ verilator_flags2 => ['--cc --trace --trace-structs'],
);
execute (
check_finished=>1,
);
+file_grep ("$Self->{obj_dir}/simx.vcd", qr/\$enddefinitions/x);
+
ok(1);
1;
diff --git a/test_regress/t/t_trace_array.v b/test_regress/t/t_trace_array.v
new file mode 100644
index 0000000..6cf6ce8
--- /dev/null
+++ b/test_regress/t/t_trace_array.v
@@ -0,0 +1,26 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed into the Public Domain, for any use,
+// without warranty, 2014 by Wilson Snyder.
+
+module t (clk);
+ input clk;
+ integer cyc=0;
+
+ // Trace would overflow at 256KB which is 256 kb dump, 16 kb in a chunk
+
+ typedef struct packed {
+ logic [1024*1024:0] d;
+ } s1_t; // 128 b
+
+ s1_t biggie;
+
+ always @ (posedge clk) begin
+ cyc <= cyc + 1;
+ biggie [ cyc +: 32 ] <= 32'hfeedface;
+ if (cyc == 5) begin
+ $write("*-* All Finished *-*\n");
+ $finish;
+ end
+ end
+endmodule
diff --git a/test_regress/t/t_trace_ena.v b/test_regress/t/t_trace_ena.v
index 8e45279..b47e3d6 100644
--- a/test_regress/t/t_trace_ena.v
+++ b/test_regress/t/t_trace_ena.v
@@ -17,6 +17,10 @@ module t (/*AUTOARG*/
integer c_trace_on;
real r;
+ // verilator tracing_off
+ sub sub ();
+ // verilator tracing_on
+
always @ (posedge clk) begin
if (cyc!=0) begin
cyc <= cyc + 1;
@@ -34,3 +38,7 @@ module t (/*AUTOARG*/
end
endmodule
+
+module sub;
+ integer inside_sub = 0;
+endmodule
diff --git a/test_regress/t/t_trace_ena_cc.pl b/test_regress/t/t_trace_ena_cc.pl
index 5f72b9a..4d5b6f9 100755
--- a/test_regress/t/t_trace_ena_cc.pl
+++ b/test_regress/t/t_trace_ena_cc.pl
@@ -21,6 +21,7 @@ if ($Self->{vlt}) {
file_grep ("$Self->{obj_dir}/V$Self->{name}__Trace__Slow.cpp", qr/c_trace_on\"/x);
file_grep_not ("$Self->{obj_dir}/V$Self->{name}__Trace__Slow.cpp", qr/_trace_off\"/x);
file_grep ("$Self->{obj_dir}/simx.vcd", qr/\$enddefinitions/x);
+ file_grep_not ("$Self->{obj_dir}/simx.vcd", qr/inside_sub/x);
}
ok(1);
diff --git a/test_regress/t/t_param_public.pl b/test_regress/t/t_trace_primitive.pl
similarity index 67%
copy from test_regress/t/t_param_public.pl
copy to test_regress/t/t_trace_primitive.pl
index f912897..17dfb5e 100755
--- a/test_regress/t/t_param_public.pl
+++ b/test_regress/t/t_trace_primitive.pl
@@ -2,17 +2,22 @@
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
+# Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
+ v_flags2 => ["--trace"],
);
execute (
check_finished=>1,
);
+if ($Self->{vlt}) {
+ file_grep ("$Self->{obj_dir}/simx.vcd", "sub_t_i");
+};
+
ok(1);
1;
diff --git a/test_regress/t/t_trace_primitive.v b/test_regress/t/t_trace_primitive.v
new file mode 100644
index 0000000..00fb855
--- /dev/null
+++ b/test_regress/t/t_trace_primitive.v
@@ -0,0 +1,43 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed into the Public Domain, for any use,
+// without warranty, 2014 by Jie Xu.
+
+module t
+ (
+ clk
+ );
+
+ input clk;
+ integer cyc; initial cyc = 0;
+
+ reg a;
+ reg b;
+ reg z;
+ sub_t sub_t_i (z, a, b);
+
+ always @ (posedge clk) begin
+ cyc <= cyc + 1;
+ a <= cyc[0];
+ b <= cyc[1];
+
+ if (cyc > 10) begin
+ $write("*-* All Finished *-*\n");
+ $finish;
+ end
+ end
+endmodule
+
+primitive CINV (a, b);
+output b;
+input a;
+assign b = ~a;
+endprimitive
+
+
+module sub_t (z, x, y);
+input x, y;
+output z;
+
+assign z = x & y;
+endmodule
diff --git a/test_regress/t/t_param_public.pl b/test_regress/t/t_unroll_genf.pl
similarity index 100%
copy from test_regress/t/t_param_public.pl
copy to test_regress/t/t_unroll_genf.pl
diff --git a/test_regress/t/t_unroll_genf.v b/test_regress/t/t_unroll_genf.v
new file mode 100644
index 0000000..776f1b3
--- /dev/null
+++ b/test_regress/t/t_unroll_genf.v
@@ -0,0 +1,29 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed into the Public Domain, for any use,
+// without warranty, 2004 by Wilson Snyder.
+
+//bug830
+module sub();
+endmodule
+
+function integer cdiv(input integer x);
+ begin
+ cdiv = 10;
+ end
+endfunction
+
+module t (/*AUTOARG*/);
+
+ genvar j;
+ generate
+ for (j = 0; j < cdiv(10); j=j+1)
+ sub sub();
+ endgenerate
+
+ initial begin
+ $write("*-* All Finished *-*\n");
+ $finish;
+ end
+
+endmodule
diff --git a/verilator.1 b/verilator.1
index 26f5a1d..0a29938 100644
--- a/verilator.1
+++ b/verilator.1
@@ -124,7 +124,7 @@
.\" ========================================================================
.\"
.IX Title "VERILATOR 1"
-.TH VERILATOR 1 "2014-08-31" "perl v5.14.2" "User Contributed Perl Documentation"
+.TH VERILATOR 1 "2014-11-13" "perl v5.14.2" "User Contributed Perl Documentation"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
@@ -200,7 +200,7 @@ descriptions in the next sections for more information.
\& \-\-debugi <level> Enable debugging at a specified level
\& \-\-debugi\-<srcfile> <level> Enable debugging a source file at a level
\& \-\-default\-language <lang> Default language to parse
-\& +define+<var>+<value> Set preprocessor define
+\& +define+<var>=<value> Set preprocessor define
\& \-\-dump\-tree Enable dumping .tree files
\& \-\-dump\-treei <level> Enable dumping .tree files at a level
\& \-E Preprocess, but do not compile
@@ -486,12 +486,15 @@ the comment \*(L"DefaultClock\*(R":
.Ve
.IP "\-D\fIvar\fR=\fIvalue\fR" 4
.IX Item "-Dvar=value"
-Defines the given preprocessor symbol. Same as +define; +define is fairly
-standard across Verilog tools while \-D is an alias for \s-1GCC\s0 compatibility.
+Defines the given preprocessor symbol, without allowing. Similar to
++define; +define is fairly standard across Verilog tools while \-D is an
+alias for \s-1GCC\s0 compatibility.
.IP "\-\-debug" 4
.IX Item "--debug"
Select the debug built image of Verilator (if available), and enable more
-internal assertions, debugging messages, and intermediate form dump files.
+internal assertions (equivelent to \f(CW\*(C`\-\-debug\-check\*(C'\fR), debugging messages
+(equivelent to \f(CW\*(C`\-\-debugi 4\*(C'\fR), and intermediate form dump files (equivilent
+to \f(CW\*(C`\-\-dump\-tree\*(C'\fR).
.IP "\-\-debug\-check" 4
.IX Item "--debug-check"
Rarely needed. Enable internal debugging assertion checks, without
@@ -503,9 +506,9 @@ changing debug verbosity. Enabled automatically when \-\-debug specified.
.IX Item "--debugi-<srcfile> <level>"
.PD
Rarely needed \- for developer use. Set internal debugging level globally
-to the specified debug level (1\-10) or set the specified source file to the
-specified level. Higher levels produce more detailed messages (plain
-\&\f(CW\*(C`\-\-debug\*(C'\fR is equivalent to \f(CW\*(C`\-\-debugi 4\*(C'\fR).
+to the specified debug level (1\-10) or set the specified Verilator source
+file to the specified level (e.g. \f(CW\*(C`\-\-debugi\-V3Width 9\*(C'\fR). Higher levels
+produce more detailed messages.
.IP "\-\-default\-language \fIvalue\fR" 4
.IX Item "--default-language value"
Select the language to be used by default when first processing each
@@ -524,10 +527,15 @@ used.
.Sp
If no language is specified, either by this flag or +\fIlang\fRext+ options,
then the latest SystemVerilog language (\s-1IEEE\s0 1800\-2012) is used.
-.IP "+define+\fIvar\fR+\fIvalue\fR" 4
-.IX Item "+define+var+value"
-Defines the given preprocessor symbol. Same as \-D; +define is fairly
-standard across Verilog tools while \-D is an alias for \s-1GCC\s0 compatibility.
+.IP "+define+\fIvar\fR=\fIvalue\fR" 4
+.IX Item "+define+var=value"
+.PD 0
+.IP "+define+\fIvar\fR=\fIvalue\fR+\fIvar2\fR=\fIvalue2\fR..." 4
+.IX Item "+define+var=value+var2=value2..."
+.PD
+Defines the given preprocessor symbol, or multiple symbols if separated by
+plusses. Similar to \-D; +define is fairly standard across Verilog tools
+while \-D is an alias for \s-1GCC\s0 compatibility.
.IP "\-\-dump\-tree" 4
.IX Item "--dump-tree"
Rarely needed. Enable writing .tree debug files with dumping level 3,
@@ -2088,6 +2096,15 @@ function or task should not be inlined into where it is used. This may
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.
+.IP "/*verilator public*/ (typedef enum)" 4
+.IX Item "/*verilator public*/ (typedef enum)"
+Used after an enum typedef declaration to indicate the emitted C code
+should have the enum values visible. Due to \*(C+ language restrictions, this
+may only be used on 64\-bit or narrower integral enumerations.
+.Sp
+.Vb 1
+\& typedef enum logic [2:0] { ZERO = 3\*(Aqb0 } pub_t /*verilator public*/;
+.Ve
.IP "/*verilator public*/ (variable)" 4
.IX Item "/*verilator public*/ (variable)"
Used after an input, output, register, or wire declaration to indicate the
@@ -2166,11 +2183,13 @@ behavior. See the test_regress/t/t_dpi_display.v file for an example.
.IP "/*verilator tracing_off*/" 4
.IX 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.
+module, or cells below this module. Often this is placed just after a
+primitive's module statement, so that the entire module and cells below it
+are not traced.
.IP "/*verilator tracing_on*/" 4
.IX Item "/*verilator tracing_on*/"
-Re-enable waveform tracing for all future signals that are declared.
+Re-enable waveform tracing for all future signals or cells that are
+declared.
.SH "LANGUAGE LIMITATIONS"
.IX Header "LANGUAGE LIMITATIONS"
There are some limitations and lack of features relative to a commercial
diff --git a/verilator.html b/verilator.html
index f6f7670..02007a4 100644
--- a/verilator.html
+++ b/verilator.html
@@ -175,7 +175,7 @@ descriptions in the next sections for more information.</p>
--debugi <level> Enable debugging at a specified level
--debugi-<srcfile> <level> Enable debugging a source file at a level
--default-language <lang> Default language to parse
- +define+<var>+<value> Set preprocessor define
+ +define+<var>=<value> Set preprocessor define
--dump-tree Enable dumping .tree files
--dump-treei <level> Enable dumping .tree files at a level
-E Preprocess, but do not compile
@@ -483,14 +483,17 @@ the comment "DefaultClock":</p>
<dt><strong><a name="dvar_value" class="item">-D<em>var</em>=<em>value</em></a></strong></dt>
<dd>
-<p>Defines the given preprocessor symbol. Same as +define; +define is fairly
-standard across Verilog tools while -D is an alias for GCC compatibility.</p>
+<p>Defines the given preprocessor symbol, without allowing. Similar to
++define; +define is fairly standard across Verilog tools while -D is an
+alias for GCC compatibility.</p>
</dd>
<dt><strong><a name="debug" class="item">--debug</a></strong></dt>
<dd>
<p>Select the debug built image of Verilator (if available), and enable more
-internal assertions, debugging messages, and intermediate form dump files.</p>
+internal assertions (equivelent to <a href="#debug_check"><code>--debug-check</code></a>), debugging messages
+(equivelent to <code>--debugi 4</code>), and intermediate form dump files (equivilent
+to <a href="#dump_tree"><code>--dump-tree</code></a>).</p>
</dd>
<dt><strong><a name="debug_check" class="item">--debug-check</a></strong></dt>
@@ -504,9 +507,9 @@ changing debug verbosity. Enabled automatically when --debug specified.</p>
<dd>
<p>Rarely needed - for developer use. Set internal debugging level globally
-to the specified debug level (1-10) or set the specified source file to the
-specified level. Higher levels produce more detailed messages (plain
-<a href="#debug"><code>--debug</code></a> is equivalent to <code>--debugi 4</code>).</p>
+to the specified debug level (1-10) or set the specified Verilator source
+file to the specified level (e.g. <code>--debugi-V3Width 9</code>). Higher levels
+produce more detailed messages.</p>
</dd>
<dt><strong><a name="default_language_value" class="item">--default-language <em>value</em></a></strong></dt>
@@ -525,11 +528,14 @@ used.</p>
<p>If no language is specified, either by this flag or +<em>lang</em>ext+ options,
then the latest SystemVerilog language (IEEE 1800-2012) is used.</p>
</dd>
-<dt><strong><a name="define_var_value" class="item">+define+<em>var</em>+<em>value</em></a></strong></dt>
+<dt><strong><a name="define_var_value" class="item">+define+<em>var</em>=<em>value</em></a></strong></dt>
+
+<dt><strong><a name="define_var_value_var2_value2" class="item">+define+<em>var</em>=<em>value</em>+<em>var2</em>=<em>value2</em>...</a></strong></dt>
<dd>
-<p>Defines the given preprocessor symbol. Same as -D; +define is fairly
-standard across Verilog tools while -D is an alias for GCC compatibility.</p>
+<p>Defines the given preprocessor symbol, or multiple symbols if separated by
+plusses. Similar to -D; +define is fairly standard across Verilog tools
+while -D is an alias for GCC compatibility.</p>
</dd>
<dt><strong><a name="dump_tree" class="item">--dump-tree</a></strong></dt>
@@ -2179,6 +2185,15 @@ 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.</p>
</dd>
+<dt><strong><a name="verilator_public_typedef_enum" class="item">/*verilator public*/ (typedef enum)</a></strong></dt>
+
+<dd>
+<p>Used after an enum typedef declaration to indicate the emitted C code
+should have the enum values visible. Due to C++ language restrictions, this
+may only be used on 64-bit or narrower integral enumerations.</p>
+<pre>
+ typedef enum logic [2:0] { ZERO = 3'b0 } pub_t /*verilator public*/;</pre>
+</dd>
<dt><strong><a name="verilator_public_variable" class="item">/*verilator public*/ (variable)</a></strong></dt>
<dd>
@@ -2272,13 +2287,15 @@ behavior. See the test_regress/t/t_dpi_display.v file for an example.</p>
<dd>
<p>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.</p>
+module, or cells below this module. Often this is placed just after a
+primitive's module statement, so that the entire module and cells below it
+are not traced.</p>
</dd>
<dt><strong><a name="verilator_tracing_on" class="item">/*verilator tracing_on*/</a></strong></dt>
<dd>
-<p>Re-enable waveform tracing for all future signals that are declared.</p>
+<p>Re-enable waveform tracing for all future signals or cells that are
+declared.</p>
</dd>
</dl>
<p>
diff --git a/verilator.pdf b/verilator.pdf
index 3f883ea..ada2468 100644
Binary files a/verilator.pdf and b/verilator.pdf differ
diff --git a/verilator.txt b/verilator.txt
index 67e9e6f..ed48441 100644
--- a/verilator.txt
+++ b/verilator.txt
@@ -66,7 +66,7 @@ ARGUMENT SUMMARY
--debugi <level> Enable debugging at a specified level
--debugi-<srcfile> <level> Enable debugging a source file at a level
--default-language <lang> Default language to parse
- +define+<var>+<value> Set preprocessor define
+ +define+<var>=<value> Set preprocessor define
--dump-tree Enable dumping .tree files
--dump-treei <level> Enable dumping .tree files at a level
-E Preprocess, but do not compile
@@ -348,14 +348,15 @@ ARGUMENTS
DefaultClock: cover property (@(posedge clk) cyc==3);
-D*var*=*value*
- Defines the given preprocessor symbol. Same as +define; +define is
- fairly standard across Verilog tools while -D is an alias for GCC
- compatibility.
+ Defines the given preprocessor symbol, without allowing. Similar to
+ +define; +define is fairly standard across Verilog tools while -D is
+ an alias for GCC compatibility.
--debug
Select the debug built image of Verilator (if available), and enable
- more internal assertions, debugging messages, and intermediate form
- dump files.
+ more internal assertions (equivelent to "--debug-check"), debugging
+ messages (equivelent to "--debugi 4"), and intermediate form dump
+ files (equivilent to "--dump-tree").
--debug-check
Rarely needed. Enable internal debugging assertion checks, without
@@ -366,8 +367,8 @@ ARGUMENTS
--debugi-<srcfile> <level>
Rarely needed - for developer use. Set internal debugging level
globally to the specified debug level (1-10) or set the specified
- source file to the specified level. Higher levels produce more
- detailed messages (plain "--debug" is equivalent to "--debugi 4").
+ Verilator source file to the specified level (e.g. "--debugi-V3Width
+ 9"). Higher levels produce more detailed messages.
--default-language *value*
Select the language to be used by default when first processing each
@@ -388,10 +389,11 @@ ARGUMENTS
options, then the latest SystemVerilog language (IEEE 1800-2012) is
used.
- +define+*var*+*value*
- Defines the given preprocessor symbol. Same as -D; +define is fairly
- standard across Verilog tools while -D is an alias for GCC
- compatibility.
+ +define+*var*=*value*
+ +define+*var*=*value*+*var2*=*value2*...
+ Defines the given preprocessor symbol, or multiple symbols if
+ separated by plusses. Similar to -D; +define is fairly standard
+ across Verilog tools while -D is an alias for GCC compatibility.
--dump-tree
Rarely needed. Enable writing .tree debug files with dumping level
@@ -1886,6 +1888,14 @@ LANGUAGE EXTENSIONS
tasks below it must be pure; they cannot reference any variables
outside the task itself.
+ /*verilator public*/ (typedef enum)
+ Used after an enum typedef declaration to indicate the emitted C
+ code should have the enum values visible. Due to C++ language
+ restrictions, this may only be used on 64-bit or narrower integral
+ enumerations.
+
+ typedef enum logic [2:0] { ZERO = 3'b0 } pub_t /*verilator public*/;
+
/*verilator public*/ (variable)
Used after an input, output, register, or wire declaration to
indicate the signal should be declared so that C code may read or
@@ -1969,11 +1979,13 @@ LANGUAGE EXTENSIONS
/*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.
+ this module, or cells below this module. Often this is placed just
+ after a primitive's module statement, so that the entire module and
+ cells below it are not traced.
/*verilator tracing_on*/
- Re-enable waveform tracing for all future signals that are declared.
+ Re-enable waveform tracing for all future signals or cells that are
+ declared.
LANGUAGE LIMITATIONS
There are some limitations and lack of features relative to a commercial
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-electronics/verilator.git
More information about the Pkg-electronics-commits
mailing list