[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