[Pkg-electronics-commits] [verilator] 01/03: Imported Upstream version 3.854

أحمد المحمودي (Ahmed El-Mahmoudy) aelmahmoudy at sabily.org
Tue Dec 3 09:36:57 UTC 2013


This is an automated email from the git hooks/post-receive script.

aelmahmoudy-guest pushed a commit to branch master
in repository verilator.

commit e344482bfe3eeb12e3ada8f1857527291a15872b
Author: أحمد المحمودي (Ahmed El-Mahmoudy) <aelmahmoudy at sabily.org>
Date:   Tue Dec 3 09:21:03 2013 +0200

    Imported Upstream version 3.854
---
 Changes                                            |  24 ++
 README.pdf                                         | Bin 111870 -> 112233 bytes
 bin/verilator                                      |  13 +
 configure                                          |  18 +-
 configure.ac                                       |   2 +-
 include/verilated.cpp                              |   1 +
 include/verilated_config.h                         |   2 +-
 include/verilated_vpi.h                            |  79 ++++--
 internals.pdf                                      | Bin 195231 -> 195589 bytes
 src/V3Ast.cpp                                      |   4 +-
 src/V3Ast.h                                        |   6 +-
 src/V3AstNodes.h                                   |  16 +-
 src/V3Changed.cpp                                  |   2 +-
 src/V3Coverage.cpp                                 |  46 +++-
 src/V3Error.h                                      |   3 +-
 src/V3Global.h                                     |   2 +-
 src/V3Options.cpp                                  |   5 +-
 src/V3Simulate.h                                   |  13 +-
 src/V3Width.cpp                                    |  14 +-
 src/V3WidthSel.cpp                                 |   2 +-
 src/Verilator.cpp                                  | 156 ++++++------
 src/config_build.h                                 |   2 +-
 src/config_rev.h                                   |   2 +-
 test_regress/driver.pl                             |   4 +-
 test_regress/t/TestSimulator.h                     |  78 ++++++
 test_regress/t/{t_dpi_string_c.cpp => TestVpi.h}   |  44 ++--
 test_regress/t/t_cover_toggle.v                    |  19 +-
 test_regress/t/t_dpi_string_c.cpp                  |   1 +
 test_regress/t/t_enum.v                            |  11 +
 .../t/{t_select_index2.pl => t_param_chain.pl}     |   5 +-
 test_regress/t/t_param_chain.v                     |  36 +++
 test_regress/t/t_select_index2.pl                  |   3 +
 .../t/{t_select_index2.pl => t_struct_unpacked.pl} |   5 +-
 ...t_struct_unpacked_bad.v => t_struct_unpacked.v} |  12 +-
 test_regress/t/t_struct_unpacked_bad.pl            |   3 +-
 test_regress/t/t_struct_unpacked_bad.v             |  10 +-
 test_regress/t/t_var_const.v                       |   5 +
 test_regress/t/t_vpi_get.cpp                       | 283 +++++++++++++++++++++
 test_regress/t/{t_vpi_memory.pl => t_vpi_get.pl}   |   8 +-
 test_regress/t/t_vpi_get.v                         |  71 ++++++
 test_regress/t/t_vpi_memory.cpp                    |  69 +++--
 test_regress/t/t_vpi_memory.pl                     |   2 +-
 test_regress/t/t_vpi_memory.v                      |  13 +-
 test_regress/t/t_vpi_unimpl.cpp                    |  18 +-
 test_regress/t/t_vpi_var.cpp                       | 188 +++++++++-----
 test_regress/t/t_vpi_var.pl                        |   5 +
 test_regress/t/t_vpi_var.v                         |  28 +-
 verilator.1                                        |  13 +-
 verilator.html                                     |  14 +
 verilator.pdf                                      | Bin 388701 -> 389267 bytes
 verilator.txt                                      |  13 +
 51 files changed, 1073 insertions(+), 300 deletions(-)

diff --git a/Changes b/Changes
index ba63ea5..7e4abe5 100644
--- a/Changes
+++ b/Changes
@@ -3,6 +3,30 @@ 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.854 2013-11-26
+
+***   Add UNPACKED warning to convert unpacked structs. [Jeremy Bennett]
+
+***   Add --compiler clang to work around compiler bug, bug694. [Stefan Ludwig]
+
+****  Support vpi_get of vpiSuppressVal, bug687. [Varun Koyyalagunta]
+
+****  Support vpi_get_time, bug688. [Varun Koyyalagunta]
+
+****  Fix evaluation of chained parameter functions, bug684. [Ted Campbell]
+
+****  Fix enum value extension of '1.
+
+****  Fix multiple VPI variable callbacks, bug679. [Rich Porter]
+
+****  Fix vpi_get of vpiSize, bug680. [Rich Porter]
+
+****  Fix vpi_remove_cb inside callback, bug689. [Varun Koyyalagunta]
+
+****  Fix crash with coverage of structures, bug691. [Eivind Liland]
+
+****  Fix array assignment from const var, bug693. [Jie Xu]
+
 
 * Verilator 3.853 2013-09-30
 
diff --git a/README.pdf b/README.pdf
index af8f953..2ca3927 100644
Binary files a/README.pdf and b/README.pdf differ
diff --git a/bin/verilator b/bin/verilator
index 5b49ad5..2a607c0 100755
--- a/bin/verilator
+++ b/bin/verilator
@@ -469,6 +469,12 @@ Enables tunings and work-arounds for the specified C++ compiler.
 
 =over 4
 
+=item clang
+
+Tune for clang.  This may reduce execution speed as it enables several
+workarounds to avoid silly hardcoded limits in clang.  This includes
+breaking deep structures as for msvc as described below.
+
 =item gcc
 
 Tune for Gnu C++, although generated code should work on almost any
@@ -3225,6 +3231,13 @@ section for more details.
 Ignoring this warning will only slow simulations, it will simulate
 correctly.
 
+=item UNPACKED
+
+Warns that unpacked structs and unions are not supported.
+
+Ignoring this warning will make Verilator treat the structure as packed,
+which may make Verilator simulations differ from other simulators.
+
 =item UNSIGNED
 
 Warns that you are comparing a unsigned value in a way that implies it is
diff --git a/configure b/configure
index 4ead2a1..31abbfd 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.853 2013-09-30.
+# Generated by GNU Autoconf 2.68 for Verilator 3.854 2013-11-26.
 #
 #
 # 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.853 2013-09-30'
-PACKAGE_STRING='Verilator 3.853 2013-09-30'
+PACKAGE_VERSION='3.854 2013-11-26'
+PACKAGE_STRING='Verilator 3.854 2013-11-26'
 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.853 2013-09-30 to adapt to many kinds of systems.
+\`configure' configures Verilator 3.854 2013-11-26 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.853 2013-09-30:";;
+     short | recursive ) echo "Configuration of Verilator 3.854 2013-11-26:";;
    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.853 2013-09-30
+Verilator configure 3.854 2013-11-26
 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.853 2013-09-30, which was
+It was created by Verilator $as_me 3.854 2013-11-26, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   $ $0 $@
@@ -4565,7 +4565,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.853 2013-09-30, which was
+This file was extended by Verilator $as_me 3.854 2013-11-26, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -4627,7 +4627,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.853 2013-09-30
+Verilator config.status 3.854 2013-11-26
 configured by $0, generated by GNU Autoconf 2.68,
   with options \\"\$ac_cs_config\\"
 
diff --git a/configure.ac b/configure.ac
index 12f82a5..02cc927 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.853 2013-09-30])
+AC_INIT([Verilator],[3.854 2013-11-26])
 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.cpp b/include/verilated.cpp
index 5a6c909..b2a098b 100644
--- a/include/verilated.cpp
+++ b/include/verilated.cpp
@@ -770,6 +770,7 @@ void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) {
 }
 
 void VL_SFORMAT_X(int obits_ignored, string &output, const char* formatp, ...) {
+    if (obits_ignored) {}
     output = "";
     va_list ap;
     va_start(ap,formatp);
diff --git a/include/verilated_config.h b/include/verilated_config.h
index 593bc36..4952cf0 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.853 2013-09-30"
+#define VERILATOR_VERSION    "3.854 2013-11-26"
diff --git a/include/verilated_vpi.h b/include/verilated_vpi.h
index 1c1a123..a045d82 100644
--- a/include/verilated_vpi.h
+++ b/include/verilated_vpi.h
@@ -38,7 +38,7 @@
 // Internal macros
 
 #define _VL_VPI_INTERNAL    VerilatedVpi::error_info()->setMessage(vpiInternal)->setMessage
-#define _VL_VPI_SYSTEM	     VerilatedVpi::error_info()->setMessage(vpiSystem  )->setMessage
+#define _VL_VPI_SYSTEM      VerilatedVpi::error_info()->setMessage(vpiSystem  )->setMessage
 #define _VL_VPI_ERROR       VerilatedVpi::error_info()->setMessage(vpiError   )->setMessage
 #define _VL_VPI_WARNING     VerilatedVpi::error_info()->setMessage(vpiWarning )->setMessage
 #define _VL_VPI_NOTICE      VerilatedVpi::error_info()->setMessage(vpiNotice  )->setMessage
@@ -52,6 +52,8 @@
 // Implementation
 
 #include <set>
+#include <list>
+#include <map>
 
 #define VL_DEBUG_IF_PLI VL_DEBUG_IF
 #define VL_VPI_LINE_SIZE 8192
@@ -180,6 +182,10 @@ class VerilatedVpioVar : public VerilatedVpio {
 protected:
     void*			m_varDatap;	// varp()->datap() adjusted for array entries
     vlsint32_t			m_index;
+    const VerilatedRange&	get_range() {
+	// Determine number of dimensions and return outermost
+	return (m_varp->dims()>1) ? m_varp->array() : m_varp->range();
+    }
 public:
     VerilatedVpioVar(const VerilatedVar* varp, const VerilatedScope* scopep)
 	: m_varp(varp), m_scopep(scopep), m_index(0) {
@@ -198,10 +204,12 @@ public:
     vluint8_t mask_byte(int idx) { return m_mask.u8[idx & 3]; }
     vluint32_t entSize() const { return m_entSize; }
     const vluint32_t index() { return m_index; }
-    virtual const vluint32_t type() { return (varp()->dims()>1) ? vpiMemory : vpiReg; /* but might be wire, logic */ }
-    virtual const vluint32_t size() { return range().elements(); }
-    const VerilatedRange& range() { return m_varp->dims()?m_varp->array():m_varp->range(); }
-    virtual const VerilatedRange* rangep() { return &range(); }
+    virtual const vluint32_t type() {
+      if (varp()->vldir() != vpiNoDirection) return vpiPort;
+      return (varp()->dims()>1) ? vpiMemory : vpiReg; /* but might be wire, logic */
+    }
+    virtual const vluint32_t size() { return get_range().elements(); }
+    virtual const VerilatedRange* rangep() { return &get_range(); }
     virtual const char* name() { return m_varp->name(); }
     virtual const char* fullname() {
 	VL_STATIC_OR_THREAD string out;
@@ -301,7 +309,7 @@ class VerilatedVpiError;
 
 class VerilatedVpi {
     enum { CB_ENUM_MAX_VALUE = cbAtEndOfSimTime+1 };	// Maxium callback reason
-    typedef set<VerilatedVpioCb*> VpioCbSet;
+    typedef list<VerilatedVpioCb*> VpioCbList;
     typedef set<pair<QData,VerilatedVpioCb*>,VerilatedVpiTimedCbsCmp > VpioTimedCbs;
 
     struct product_info {
@@ -309,7 +317,7 @@ class VerilatedVpi {
 	PLI_BYTE8* version;
     };
 
-    VpioCbSet		m_cbObjSets[CB_ENUM_MAX_VALUE];	// Callbacks for each supported reason
+    VpioCbList		m_cbObjLists[CB_ENUM_MAX_VALUE];	// Callbacks for each supported reason
     VpioTimedCbs	m_timedCbs;	// Time based callbacks
     VerilatedVpiError*  m_errorInfop;	// Container for vpi error info
 
@@ -325,16 +333,17 @@ public:
 	    }
 	}
 	if (VL_UNLIKELY(vop->reason() >= CB_ENUM_MAX_VALUE)) vl_fatal(__FILE__,__LINE__,"", "vpi bb reason too large");
-	s_s.m_cbObjSets[vop->reason()].insert(vop);
+	s_s.m_cbObjLists[vop->reason()].push_back(vop);
     }
     static void cbTimedAdd(VerilatedVpioCb* vop) {
 	s_s.m_timedCbs.insert(make_pair(vop->time(), vop));
     }
     static void cbReasonRemove(VerilatedVpioCb* cbp) {
-	VpioCbSet& cbObjSet = s_s.m_cbObjSets[cbp->reason()];
-	VpioCbSet::iterator it=cbObjSet.find(cbp);
-	if (VL_LIKELY(it != cbObjSet.end())) {
-	    cbObjSet.erase(it);
+	VpioCbList& cbObjList = s_s.m_cbObjLists[cbp->reason()];
+	// We do not remove it now as we may be iterating the list,
+	// instead set to NULL and will cleanup later
+	for (VpioCbList::iterator it=cbObjList.begin(); it!=cbObjList.end(); ++it) {
+            if (*it == cbp) *it = NULL;
 	}
     }
     static void cbTimedRemove(VerilatedVpioCb* cbp) {
@@ -364,19 +373,26 @@ public:
 	}
     }
     static void callCbs(vluint32_t reason) {
-	VpioCbSet& cbObjSet = s_s.m_cbObjSets[reason];
-	for (VpioCbSet::iterator it=cbObjSet.begin(); it!=cbObjSet.end();) {
-	    VerilatedVpioCb* vop = *it;
-	    ++it;  // iterator may be deleted by callback
+	VpioCbList& cbObjList = s_s.m_cbObjLists[reason];
+	for (VpioCbList::iterator it=cbObjList.begin(); it!=cbObjList.end();) {
+	    if (VL_UNLIKELY(!*it)) { // Deleted earlier, cleanup
+		it = cbObjList.erase(it);
+		continue;
+	    }
+	    VerilatedVpioCb* vop = *it++;
 	    VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi:  reason_callback %d %p\n",reason,vop););
 	    (vop->cb_rtnp()) (vop->cb_datap());
 	}
     }
     static void callValueCbs() {
-	VpioCbSet& cbObjSet = s_s.m_cbObjSets[cbValueChange];
-	for (VpioCbSet::iterator it=cbObjSet.begin(); it!=cbObjSet.end();) {
-	    VerilatedVpioCb* vop = *it;
-	    ++it;  // iterator may be deleted by callback
+	VpioCbList& cbObjList = s_s.m_cbObjLists[cbValueChange];
+        set<VerilatedVpioVar*> update; // set of objects to update after callbacks
+	for (VpioCbList::iterator it=cbObjList.begin(); it!=cbObjList.end();) {
+	    if (VL_UNLIKELY(!*it)) { // Deleted earlier, cleanup
+		it = cbObjList.erase(it);
+		continue;
+	    }
+	    VerilatedVpioCb* vop = *it++;
 	    if (VerilatedVpioVar* varop = VerilatedVpioVar::castp(vop->cb_datap()->obj)) {
 		void* newDatap = varop->varDatap();
 		void* prevDatap = varop->prevDatap();  // Was malloced when we added the callback
@@ -386,12 +402,15 @@ public:
 		if (memcmp(prevDatap, newDatap, varop->entSize())) {
 		    VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi:  value_callback %p %s v[0]=%d\n",
 					      vop,varop->fullname(), *((CData*)newDatap)););
-		    memcpy(prevDatap, newDatap, varop->entSize());
+                    update.insert(varop);
 		    vpi_get_value(vop->cb_datap()->obj, vop->cb_datap()->value);
 		    (vop->cb_rtnp()) (vop->cb_datap());
 		}
 	    }
 	}
+	for (set<VerilatedVpioVar*>::iterator it=update.begin(); it!=update.end(); it++ ) {
+	    memcpy((*it)->prevDatap(), (*it)->varDatap(), (*it)->entSize());
+	}
     }
 
     static VerilatedVpiError* error_info(); // getter for vpi error info
@@ -1006,6 +1025,8 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
 			      VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
 		return;
 	    }
+	} else if (value_p->format == vpiSuppressVal) {
+	    return;
 	}
         _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) as requested for %s",
 		      VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
@@ -1297,7 +1318,21 @@ void vpi_put_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p,
 // time processing
 
 void vpi_get_time(vpiHandle object, p_vpi_time time_p) {
-    _VL_VPI_UNIMP(); return;
+    if (VL_UNLIKELY(!time_p)) {
+	_VL_VPI_WARNING(__FILE__, __LINE__, "Ignoring vpi_get_time with NULL value pointer");
+	return;
+    }
+    if (time_p->type == vpiSimTime) {
+	QData qtime = VL_TIME_Q();
+	IData itime[2];
+	VL_SET_WQ(itime, qtime);
+	time_p->low = itime[0];
+	time_p->high = itime[1];
+	return;
+    }
+    _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported type (%d)",
+		  VL_FUNC, time_p->type);
+    return;
 }
 
 // I/O routines
diff --git a/internals.pdf b/internals.pdf
index da74b58..4c9e757 100644
Binary files a/internals.pdf and b/internals.pdf differ
diff --git a/src/V3Ast.cpp b/src/V3Ast.cpp
index 0f5f739..300c7f0 100644
--- a/src/V3Ast.cpp
+++ b/src/V3Ast.cpp
@@ -1016,8 +1016,8 @@ void AstNode::dumpTreeAndNext(ostream& os, const string& indent, int maxDepth) {
     }
 }
 
-void AstNode::dumpTreeFile(const string& filename, bool append) {
-    if (v3Global.opt.dumpTree()) {
+void AstNode::dumpTreeFile(const string& filename, bool append, bool doDump) {
+    if (v3Global.opt.dumpTree() && doDump) {
 	{   // Write log & close
 	    UINFO(2,"Dumping "<<filename<<endl);
 	    const auto_ptr<ofstream> logsp (V3File::new_ofstream(filename, append));
diff --git a/src/V3Ast.h b/src/V3Ast.h
index 24e9d0a..4fa3924 100644
--- a/src/V3Ast.h
+++ b/src/V3Ast.h
@@ -1160,7 +1160,7 @@ public:
     void	dumpTree(const string& indent, int maxDepth=0) { dumpTree(cout,indent,maxDepth); }
     void	dumpTreeGdb(); // For GDB only
     void	dumpTreeAndNext(ostream& str=cout, const string& indent="    ", int maxDepth=0);
-    void	dumpTreeFile(const string& filename, bool append=false);
+    void	dumpTreeFile(const string& filename, bool append=false, bool doDump=true);
     static void	dumpTreeFileGdb(const char* filenamep=NULL);
 
     // METHODS - queries
@@ -1542,6 +1542,7 @@ public:
     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* skipRefToConstp() const = 0;  // recurses over typedefs to next non-typeref-or-const 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; }
@@ -1591,12 +1592,14 @@ public:
     // For basicp() we reuse the size to indicate a "fake" basic type of same size
     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 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
     AstMemberDType* membersp() const { return op1p()->castMemberDType(); } // op1 = AstMember list
     void addMembersp(AstNode* nodep) { addNOp1p(nodep); }
     bool packed() const { return m_packed; }
+    bool packedUnsup() const { return true; }  // packed() but as don't support unpacked, presently all structs
     void clearCache() { m_members.clear(); }
     void repairMemberCache();
     AstMemberDType* findMember(const string& name) const {
@@ -1645,6 +1648,7 @@ public:
     // METHODS
     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 int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); }
     virtual int widthTotalBytes() const { return elementsConst() * subDTypep()->widthTotalBytes(); }
     int		msb() const;
diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h
index a93a0bb..147501b 100644
--- a/src/V3AstNodes.h
+++ b/src/V3AstNodes.h
@@ -227,6 +227,7 @@ public:
     AstNodeDType* dtypeSkipRefp() const { return dtypep()->skipRefp(); }	// op1 = Range of variable
     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 int widthAlignBytes() const { return dtypep()->widthAlignBytes(); }
     virtual int widthTotalBytes() const { return dtypep()->widthTotalBytes(); }
     virtual string name() const { return m_name; }
@@ -368,6 +369,7 @@ public:
     // METHODS
     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 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
@@ -427,7 +429,8 @@ public:
     virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); }
     // METHODS
     virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); }  // (Slow) recurse down to find basic data type
-    virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
+    virtual AstNodeDType* skipRefp() const { return subDTypep()->skipRefp(); }
+    virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
     virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); }
     virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); }
 };
@@ -456,6 +459,7 @@ public:
     virtual void cloneRelink();
     virtual AstBasicDType* basicp() const { return NULL; }
     virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
+    virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
     virtual int widthAlignBytes() const { return 1; }
     virtual int widthTotalBytes() const { return 1; }
     string cellName() const { return m_cellName; }
@@ -506,6 +510,10 @@ public:
 	if (defp()) return defp()->skipRefp();
 	else { v3fatalSrc("Typedef not linked"); return NULL; }
     }
+    virtual AstNodeDType* skipRefToConstp() const {
+	if (defp()) return defp()->skipRefToConstp();
+	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; }
@@ -573,7 +581,8 @@ public:
     //
     virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); }  // (Slow) recurse down to find basic data type (Note don't need virtual - AstVar isn't a NodeDType)
     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 dtypeSkipRefp(); }
+    virtual AstNodeDType* skipRefp() const { return subDTypep()->skipRefp(); }
+    virtual AstNodeDType* skipRefToConstp() const { return subDTypep()->skipRefToConstp(); }
     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
@@ -662,6 +671,7 @@ public:
     // METHODS
     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 int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); }
     virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); }
 };
@@ -961,7 +971,7 @@ public:
     void	combineType(AstVarType type);
     AstNodeDType* getChildDTypep() const { return childDTypep(); }
     AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); }	// op1 = Range of variable
-    AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); }	// op1 = Range of variable (Note don't need virtual - AstVar isn't a NodeDType)
+    AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); }
     AstBasicDType* basicp() const { return subDTypep()->basicp(); }  // (Slow) recurse down to find basic data type (Note don't need virtual - AstVar isn't a NodeDType)
     AstNode* 	valuep() const { return op3p()->castNode(); } // op3 = Initial value that never changes (static const)
     void	valuep(AstNode* nodep) { setOp3p(nodep); }    // It's valuep, not constp, as may be more complicated than an AstConst
diff --git a/src/V3Changed.cpp b/src/V3Changed.cpp
index b9483f1..525f9d5 100644
--- a/src/V3Changed.cpp
+++ b/src/V3Changed.cpp
@@ -89,7 +89,7 @@ private:
 	AstUnpackArrayDType* arrayp = varp->dtypeSkipRefp()->castUnpackArrayDType();
 	AstStructDType *structp = varp->dtypeSkipRefp()->castStructDType();
 	bool isArray = arrayp;
-	bool isStruct = structp && structp->packed();
+	bool isStruct = structp && structp->packedUnsup();
 	int elements = isArray ? arrayp->elementsConst() : 1;
 	if (isArray && (elements > DETECTARRAY_MAX_INDEXES)) {
 	    vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect more than "<<cvtToStr(DETECTARRAY_MAX_INDEXES)
diff --git a/src/V3Coverage.cpp b/src/V3Coverage.cpp
index 8e63fc2..b5af0e1 100644
--- a/src/V3Coverage.cpp
+++ b/src/V3Coverage.cpp
@@ -213,7 +213,7 @@ private:
 	    }
 	}
 	else if (AstUnpackArrayDType* adtypep = dtypep->castUnpackArrayDType()) {
-	    for (int index_docs=adtypep->lsb(); index_docs<=adtypep->msb()+1; ++index_docs) {
+	    for (int index_docs=adtypep->lsb(); index_docs<=adtypep->msb(); ++index_docs) {
 		int index_code = index_docs - adtypep->lsb();
 		ToggleEnt newent (above.m_comment+string("[")+cvtToStr(index_docs)+"]",
 				  new AstArraySel(varp->fileline(), above.m_varRefp->cloneTree(true), index_code),
@@ -224,6 +224,50 @@ private:
 		newent.cleanup();
 	    }
 	}
+	else if (AstPackArrayDType* adtypep = dtypep->castPackArrayDType()) {
+	    for (int index_docs=adtypep->lsb(); index_docs<=adtypep->msb(); ++index_docs) {
+		AstNodeDType* subtypep = adtypep->subDTypep()->skipRefp();
+		int index_code = index_docs - adtypep->lsb();
+		ToggleEnt newent (above.m_comment+string("[")+cvtToStr(index_docs)+"]",
+				  new AstSel(varp->fileline(), above.m_varRefp->cloneTree(true),
+					     index_code*subtypep->width(), subtypep->width()),
+				  new AstSel(varp->fileline(), above.m_chgRefp->cloneTree(true),
+					     index_code*subtypep->width(), subtypep->width()));
+		toggleVarRecurse(adtypep->subDTypep()->skipRefp(), depth+1,
+				 newent,
+				 varp, chgVarp);
+		newent.cleanup();
+	    }
+	}
+	else if (AstStructDType* adtypep = dtypep->castStructDType()) {
+	    // For now it's packed, so similar to array
+	    for (AstMemberDType* itemp = adtypep->membersp(); itemp; itemp=itemp->nextp()->castMemberDType()) {
+		AstNodeDType* subtypep = itemp->subDTypep()->skipRefp();
+		int index_code = itemp->lsb();
+		ToggleEnt newent (above.m_comment+string(".")+itemp->name(),
+				  new AstSel(varp->fileline(), above.m_varRefp->cloneTree(true),
+					     index_code, subtypep->width()),
+				  new AstSel(varp->fileline(), above.m_chgRefp->cloneTree(true),
+					     index_code, subtypep->width()));
+		toggleVarRecurse(subtypep, depth+1,
+				 newent,
+				 varp, chgVarp);
+		newent.cleanup();
+	    }
+	}
+	else if (AstUnionDType* adtypep = dtypep->castUnionDType()) {
+	    // Arbitrarially handle only the first member of the union
+	    if (AstMemberDType* itemp = adtypep->membersp()) {
+		AstNodeDType* subtypep = itemp->subDTypep()->skipRefp();
+		ToggleEnt newent (above.m_comment+string(".")+itemp->name(),
+				  above.m_varRefp->cloneTree(true),
+				  above.m_chgRefp->cloneTree(true));
+		toggleVarRecurse(subtypep, depth+1,
+				 newent,
+				 varp, chgVarp);
+		newent.cleanup();
+	    }
+	}
 	else {
 	    dtypep->v3fatalSrc("Unexpected node data type in toggle coverage generation: "<<dtypep->prettyTypeName());
 	}
diff --git a/src/V3Error.h b/src/V3Error.h
index a4909c3..51a3913 100644
--- a/src/V3Error.h
+++ b/src/V3Error.h
@@ -93,6 +93,7 @@ public:
 	UNDRIVEN,	// No drivers
 	UNOPT,		// Unoptimizable block
 	UNOPTFLAT,	// Unoptimizable block after flattening
+	UNPACKED,	// Unsupported unpacked
 	UNSIGNED,	// Comparison is constant due to unsigned arithmetic
 	UNUSED,		// No receivers
 	VARHIDDEN,	// Hiding variable
@@ -129,7 +130,7 @@ public:
 	    "PINMISSING", "PINNOCONNECT",
 	    "REALCVT", "REDEFMACRO",
 	    "SELRANGE", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
-	    "UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNSIGNED", "UNUSED",
+	    "UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNPACKED", "UNSIGNED", "UNUSED",
 	    "VARHIDDEN", "WIDTH", "WIDTHCONCAT",
 	    " MAX"
 	};
diff --git a/src/V3Global.h b/src/V3Global.h
index fede611..6b38502 100644
--- a/src/V3Global.h
+++ b/src/V3Global.h
@@ -74,7 +74,7 @@ public:
     // METHODS
     void readFiles();
     void checkTree();
-    static void dumpGlobalTree(const string& filename, int newNumber=0);
+    static void dumpCheckGlobalTree(const string& filename, int newNumber=0, bool doDump=true);
     void assertDTypesResolved(bool flag) { m_assertDTypesResolved = flag; }
     void assertWidthsMatch(bool flag) { m_assertWidthsMatch = flag; }
     string debugFilename(const string& nameComment, int newNumber=0) {
diff --git a/src/V3Options.cpp b/src/V3Options.cpp
index 0acf370..444f6bf 100644
--- a/src/V3Options.cpp
+++ b/src/V3Options.cpp
@@ -963,7 +963,10 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
 	    }
 	    else if ( !strcmp (sw, "-compiler") && (i+1)<argc) {
 		shift;
-		if (!strcmp (argv[i], "gcc")) {
+		if (!strcmp (argv[i], "clang")) {
+		    m_compLimitParens = 80;   // limit unknown
+		    m_compLimitBlocks = 80;   // limit unknown
+		} else if (!strcmp (argv[i], "gcc")) {
 		    m_compLimitParens = 0;
 		} else if (!strcmp (argv[i], "msvc")) {
 		    m_compLimitParens = 80;   // 128, but allow some room
diff --git a/src/V3Simulate.h b/src/V3Simulate.h
index ead3a83..fd4c07d 100644
--- a/src/V3Simulate.h
+++ b/src/V3Simulate.h
@@ -603,20 +603,25 @@ private:
 	if (m_params) { V3Width::widthParamsEdit(funcp); } funcp=NULL; // Make sure we've sized the function
 	funcp = nodep->taskp()->castNodeFTask(); if (!funcp) nodep->v3fatalSrc("Not linked");
 	// Apply function call values to function
-	// Note we'd need a stack if we allowed recursive functions!
 	V3TaskConnects tconnects = V3Task::taskConnects(nodep, nodep->taskp()->stmtsp());
+	// Must do this in two steps, eval all params, then apply them
+	// Otherwise chained functions may have the wrong results
 	for (V3TaskConnects::iterator it=tconnects.begin(); it!=tconnects.end(); ++it) {
 	    AstVar* portp = it->first;
 	    AstNode* pinp = it->second->exprp();
-	    if (pinp==NULL) {
-		// Too few arguments in function call - ignore it
-	    } else {
+	    if (pinp) {  // Else too few arguments in function call - ignore it
 		if (portp->isOutput()) {
 		    clearOptimizable(portp,"Language violation: Outputs not allowed in constant functions");
 		    return;
 		}
 		// Evaluate pin value
 		pinp->accept(*this);
+	    }
+	}
+	for (V3TaskConnects::iterator it=tconnects.begin(); it!=tconnects.end(); ++it) {
+	    AstVar* portp = it->first;
+	    AstNode* pinp = it->second->exprp();
+	    if (pinp) {  // Else too few arguments in function call - ignore it
 		// Apply value to the function
 		if (!m_checkOnly && optimizable()) {
 		    newNumber(portp)->opAssign(*fetchNumber(pinp));
diff --git a/src/V3Width.cpp b/src/V3Width.cpp
index a91df61..d5e49de 100644
--- a/src/V3Width.cpp
+++ b/src/V3Width.cpp
@@ -852,7 +852,7 @@ private:
 			       || nodep->dtypeSkipRefp()->castNodeClassDType())) {
 	    nodep->v3error("Unsupported: Inputs and outputs must be simple data types");
 	}
-	if (nodep->dtypeSkipRefp()->castConstDType()) {
+	if (nodep->dtypep()->skipRefToConstp()->castConstDType()) {
 	    nodep->isConst(true);
 	}
 	// Parameters if implicit untyped inherit from what they are assigned to
@@ -1088,7 +1088,9 @@ private:
 	if (nodep->didWidthAndSet()) return;  // This node is a dtype & not both PRELIMed+FINALed
 	UINFO(5,"   NODECLASS "<<nodep<<endl);
 	//if (debug()>=9) nodep->dumpTree("-class-in--");
-	if (!nodep->packed()) nodep->v3error("Unsupported: Unpacked struct/union");
+	if (!nodep->packed()) {
+	    nodep->v3warn(UNPACKED, "Unsupported: Unpacked struct/union");
+	}
 	nodep->iterateChildren(*this);  // First size all members
 	nodep->repairMemberCache();
 	// Determine bit assignments and width
@@ -2251,12 +2253,16 @@ private:
     void widthCheck (AstNode* nodep, const char* side,
 		     AstNode* underp, AstNodeDType* expDTypep,
 		     bool ignoreWarn=false) {
-	//UINFO(9,"wchk "<<side<<endl<<"  "<<nodep<<endl<<"  "<<underp<<endl<<"  e"<<expWidth<<" m"<<expWidthMin<<" i"<<ignoreWarn<<endl);
+	//UINFO(9,"wchk "<<side<<endl<<"  "<<nodep<<endl<<"  "<<underp<<endl<<"  e="<<expDTypep<<" i"<<ignoreWarn<<endl);
 	int expWidth = expDTypep->width();
 	int expWidthMin = expDTypep->widthMin();
 	if (expWidthMin==0) expWidthMin = expWidth;
 	bool bad = widthBad(underp,expWidth,expWidthMin);
-	if (bad && fixAutoExtend(underp/*ref*/,expWidth)) bad=false;  // Changes underp
+	if ((bad || underp->width() !=expWidth)
+	    && fixAutoExtend(underp/*ref*/,expWidth)) {
+	    underp=NULL; // Changes underp
+	    return;
+	}
 	if (underp->castConst() && underp->castConst()->num().isFromString()
 	    && expWidth > underp->width()
 	    && (((expWidth - underp->width()) % 8) == 0)) {  // At least it's character sized
diff --git a/src/V3WidthSel.cpp b/src/V3WidthSel.cpp
index 3626aa4..4f5357f 100644
--- a/src/V3WidthSel.cpp
+++ b/src/V3WidthSel.cpp
@@ -389,7 +389,7 @@ private:
 	VNumRange fromRange = fromdata.m_fromRange;
 	if (ddtypep->castBasicDType()
 	    || (ddtypep->castNodeClassDType()
-		&& ddtypep->castNodeClassDType()->packed())) {
+		&& ddtypep->castNodeClassDType()->packedUnsup())) {
 	    AstSel* newp = NULL;
 	    if (nodep->castSelPlus()) {
 		if (fromRange.littleEndian()) {
diff --git a/src/Verilator.cpp b/src/Verilator.cpp
index 6fc8596..2de7a6b 100644
--- a/src/Verilator.cpp
+++ b/src/Verilator.cpp
@@ -141,8 +141,8 @@ void V3Global::readFiles() {
     }
 }
 
-void V3Global::dumpGlobalTree(const string& filename, int newNumber) {
-    v3Global.rootp()->dumpTreeFile(v3Global.debugFilename(filename, newNumber));
+void V3Global::dumpCheckGlobalTree(const string& filename, int newNumber, bool doDump) {
+    v3Global.rootp()->dumpTreeFile(v3Global.debugFilename(filename, newNumber), false, doDump);
 }
 
 //######################################################################
@@ -152,26 +152,26 @@ void process () {
 
     // Sort modules by level so later algorithms don't need to care
     V3LinkLevel::modSortByLevel();
-    V3Global::dumpGlobalTree("cells.tree");
+    V3Global::dumpCheckGlobalTree("cells.tree");
     V3Error::abortIfErrors();
 
     // Convert parseref's to varrefs, and other directly post parsing fixups
     V3LinkParse::linkParse(v3Global.rootp());
-    if (dumpMore) V3Global::dumpGlobalTree("linkparse.tree");
+    V3Global::dumpCheckGlobalTree("linkparse.tree", 0, dumpMore);
     // Cross-link signal names
     // Cross-link dotted hierarchical references
     V3LinkDot::linkDotPrimary(v3Global.rootp());
-    if (dumpMore) V3Global::dumpGlobalTree("linkdot.tree");
+    V3Global::dumpCheckGlobalTree("linkdot.tree", 0, dumpMore);
     v3Global.checkTree();  // Force a check, as link is most likely place for problems
     // Correct state we couldn't know at parse time, repair SEL's
     V3LinkResolve::linkResolve(v3Global.rootp());
-    if (dumpMore) V3Global::dumpGlobalTree("linkresolve.tree");
+    V3Global::dumpCheckGlobalTree("linkresolve.tree", 0, dumpMore);
     // Set Lvalue's in variable refs
     V3LinkLValue::linkLValue(v3Global.rootp());
-    if (dumpMore) V3Global::dumpGlobalTree("linklvalue.tree");
+    V3Global::dumpCheckGlobalTree("linklvalue.tree", 0, dumpMore);
     // Convert return/continue/disable to jumps
     V3LinkJump::linkJump(v3Global.rootp());
-    V3Global::dumpGlobalTree("link.tree");
+    V3Global::dumpCheckGlobalTree("link.tree");
     V3Error::abortIfErrors();
 
     if (v3Global.opt.stats()) V3Stats::statsStageAll(v3Global.rootp(), "Link");
@@ -179,19 +179,19 @@ void process () {
     // Remove parameters by cloning modules to de-parameterized versions
     //   This requires some width calculations and constant propagation
     V3Param::param(v3Global.rootp());
-    if (dumpMore) V3Global::dumpGlobalTree("param.tree");
+    V3Global::dumpCheckGlobalTree("param.tree", 0, dumpMore);
     V3LinkDot::linkDotParamed(v3Global.rootp());	// Cleanup as made new modules
-    V3Global::dumpGlobalTree("paramlink.tree");
+    V3Global::dumpCheckGlobalTree("paramlink.tree");
     V3Error::abortIfErrors();
 
     // Remove any modules that were parameterized and are no longer referenced.
     V3Dead::deadifyModules(v3Global.rootp());
-    if (dumpMore) V3Global::dumpGlobalTree("dead.tree");
+    V3Global::dumpCheckGlobalTree("dead.tree", 0, dumpMore);
     v3Global.checkTree();
 
     // Calculate and check widths, edit tree to TRUNC/EXTRACT any width mismatches
     V3Width::width(v3Global.rootp());
-    V3Global::dumpGlobalTree("width.tree");
+    V3Global::dumpCheckGlobalTree("width.tree");
 
     V3Error::abortIfErrors();
 
@@ -199,19 +199,19 @@ void process () {
     V3Width::widthCommit(v3Global.rootp());
     v3Global.assertDTypesResolved(true);
     v3Global.assertWidthsMatch(true);
-    if (dumpMore) V3Global::dumpGlobalTree("widthcommit.tree");
+    V3Global::dumpCheckGlobalTree("widthcommit.tree", 0, dumpMore);
 
     // Coverage insertion
     //    Before we do dead code elimination and inlining, or we'll lose it.
     if (v3Global.opt.coverage()) {
 	V3Coverage::coverage(v3Global.rootp());
-	V3Global::dumpGlobalTree("coverage.tree");
+	V3Global::dumpCheckGlobalTree("coverage.tree");
     }
 
     // Push constants, but only true constants preserving liveness
     // so V3Undriven sees variables to be eliminated, ie "if (0 && foo) ..."
     V3Const::constifyAllLive(v3Global.rootp());
-    V3Global::dumpGlobalTree("const.tree");
+    V3Global::dumpCheckGlobalTree("const.tree");
 
     // Signal based lint checks, no change to structures
     // Must be before first constification pass drops dead code
@@ -220,10 +220,10 @@ void process () {
     // Assertion insertion
     //    After we've added block coverage, but before other nasty transforms
     V3AssertPre::assertPreAll(v3Global.rootp());
-    V3Global::dumpGlobalTree("assertpre.tree");
+    V3Global::dumpCheckGlobalTree("assertpre.tree");
     //
     V3Assert::assertAll(v3Global.rootp());
-    V3Global::dumpGlobalTree("assert.tree");
+    V3Global::dumpCheckGlobalTree("assert.tree");
 
     if (!v3Global.opt.xmlOnly()) {
 	// Add top level wrapper with instance pointing to old top
@@ -234,38 +234,38 @@ void process () {
 
     // Propagate constants into expressions
     V3Const::constifyAllLint(v3Global.rootp());
-    V3Global::dumpGlobalTree("const.tree");
+    V3Global::dumpCheckGlobalTree("const.tree");
 
     if (!v3Global.opt.xmlOnly()) {
 	// Remove cell arrays (must be between V3Width and scoping)
 	V3Inst::dearrayAll(v3Global.rootp());
-	if (dumpMore) V3Global::dumpGlobalTree("dearray.tree");
+	V3Global::dumpCheckGlobalTree("dearray.tree", 0, dumpMore);
     }
 
     if (!v3Global.opt.xmlOnly()) {
 	// Expand inouts, stage 2
 	// Also simplify pin connections to always be AssignWs in prep for V3Unknown
 	V3Tristate::tristateAll(v3Global.rootp());
-	V3Global::dumpGlobalTree("tristate.tree");
+	V3Global::dumpCheckGlobalTree("tristate.tree");
 
 	// Task inlining & pushing BEGINs names to variables/cells
 	// Begin processing must be after Param, before module inlining
 	V3Begin::debeginAll(v3Global.rootp());	// Flatten cell names, before inliner
-	V3Global::dumpGlobalTree("begin.tree");
+	V3Global::dumpCheckGlobalTree("begin.tree");
 
 	// Move assignments from X into MODULE temps.
 	// (Before flattening, so each new X variable is shared between all scopes of that module.)
 	V3Unknown::unknownAll(v3Global.rootp());
-	V3Global::dumpGlobalTree("unknown.tree");
+	V3Global::dumpCheckGlobalTree("unknown.tree");
 
 	// Module inlining
 	// Cannot remove dead variables after this, as alias information for final
 	// V3Scope's V3LinkDot is in the AstVar.
 	if (v3Global.opt.oInline()) {
 	    V3Inline::inlineAll(v3Global.rootp());
-	    V3Global::dumpGlobalTree("inline.tree");
+	    V3Global::dumpCheckGlobalTree("inline.tree");
 	    V3LinkDot::linkDotArrayed(v3Global.rootp());	// Cleanup as made new modules
-	    if (dumpMore) V3Global::dumpGlobalTree("linkdot.tree");
+	    V3Global::dumpCheckGlobalTree("linkdot.tree", 0, dumpMore);
 	}
     }
 
@@ -273,11 +273,11 @@ void process () {
 
     // Initial const/dead to reduce work for ordering code
     V3Const::constifyAll(v3Global.rootp());
-    if (dumpMore) V3Global::dumpGlobalTree("const_predead.tree");
+    V3Global::dumpCheckGlobalTree("const_predead.tree", 0, dumpMore);
     v3Global.checkTree();
 
     V3Dead::deadifyDTypes(v3Global.rootp());
-    V3Global::dumpGlobalTree("const.tree");
+    V3Global::dumpCheckGlobalTree("const.tree");
     v3Global.checkTree();
 
     V3Error::abortIfErrors();
@@ -290,17 +290,17 @@ void process () {
 
 	// Convert instantiations to wassigns and always blocks
 	V3Inst::instAll(v3Global.rootp());
-	V3Global::dumpGlobalTree("inst.tree");
+	V3Global::dumpCheckGlobalTree("inst.tree");
 
 	// Inst may have made lots of concats; fix them
 	V3Const::constifyAll(v3Global.rootp());
-	V3Global::dumpGlobalTree("const.tree");
+	V3Global::dumpCheckGlobalTree("const.tree");
 
 	// Flatten hierarchy, creating a SCOPE for each module's usage as a cell
 	V3Scope::scopeAll(v3Global.rootp());
-	V3Global::dumpGlobalTree("scope.tree");
+	V3Global::dumpCheckGlobalTree("scope.tree");
 	V3LinkDot::linkDotScope(v3Global.rootp());
-	V3Global::dumpGlobalTree("linkdot.tree");
+	V3Global::dumpCheckGlobalTree("linkdot.tree");
     }
 
     //--SCOPE BASED OPTIMIZATIONS--------------
@@ -308,87 +308,87 @@ void process () {
     if (!v3Global.opt.xmlOnly()) {
 	// Cleanup
 	V3Const::constifyAll(v3Global.rootp());
-	if (dumpMore) V3Global::dumpGlobalTree("const_predead.tree");
+	V3Global::dumpCheckGlobalTree("const_predead.tree", 0, dumpMore);
 	V3Dead::deadifyDTypes(v3Global.rootp());
 	v3Global.checkTree();
-	V3Global::dumpGlobalTree("const.tree");
+	V3Global::dumpCheckGlobalTree("const.tree");
 
 	// Convert case statements to if() blocks.  Must be after V3Unknown
 	// Must be before V3Task so don't need to deal with task in case value compares
 	V3Case::caseAll(v3Global.rootp());
-	V3Global::dumpGlobalTree("case.tree");
+	V3Global::dumpCheckGlobalTree("case.tree");
 
 	// Inline all tasks
 	V3Task::taskAll(v3Global.rootp());
-	V3Global::dumpGlobalTree("task.tree");
+	V3Global::dumpCheckGlobalTree("task.tree");
 
 	// Add __PVT's
 	// After V3Task so task internal variables will get renamed
 	V3Name::nameAll(v3Global.rootp());
-	if (dumpMore) V3Global::dumpGlobalTree("name.tree");
+	V3Global::dumpCheckGlobalTree("name.tree", 0, dumpMore);
 
 	// Loop unrolling & convert FORs to WHILEs
 	V3Unroll::unrollAll(v3Global.rootp());
-	V3Global::dumpGlobalTree("unroll.tree");
+	V3Global::dumpCheckGlobalTree("unroll.tree");
 
 	// Expand slices of arrays
 	V3Slice::sliceAll(v3Global.rootp());
-	V3Global::dumpGlobalTree("slices.tree");
+	V3Global::dumpCheckGlobalTree("slices.tree");
 
 	// Push constants across variables and remove redundant assignments
 	V3Const::constifyAll(v3Global.rootp());
-	V3Global::dumpGlobalTree("const.tree");
+	V3Global::dumpCheckGlobalTree("const.tree");
 
 	if (v3Global.opt.oLife()) {
 	    V3Life::lifeAll(v3Global.rootp());
-	    V3Global::dumpGlobalTree("life.tree");
+	    V3Global::dumpCheckGlobalTree("life.tree");
 	}
 
 	// Make large low-fanin logic blocks into lookup tables
 	// This should probably be done much later, once we have common logic elimination.
 	if (!v3Global.opt.lintOnly() && v3Global.opt.oTable()) {
 	    V3Table::tableAll(v3Global.rootp());
-	    V3Global::dumpGlobalTree("table.tree");
+	    V3Global::dumpCheckGlobalTree("table.tree");
 	}
 
 	// Cleanup
 	V3Const::constifyAll(v3Global.rootp());
-	if (dumpMore) V3Global::dumpGlobalTree("const_predead.tree");
+	V3Global::dumpCheckGlobalTree("const_predead.tree", 0, dumpMore);
 	V3Dead::deadifyDTypes(v3Global.rootp());
 	v3Global.checkTree();
-	V3Global::dumpGlobalTree("const.tree");
+	V3Global::dumpCheckGlobalTree("const.tree");
 
 	// Detect clock enables and mode into sensitives, and split always based on clocks
 	// (so this is a good prelude to splitAlways.)
 	if (v3Global.opt.oFlopGater()) {
 	    V3ClkGater::clkGaterAll(v3Global.rootp());
-	    V3Global::dumpGlobalTree("clkgater.tree");
+	    V3Global::dumpCheckGlobalTree("clkgater.tree");
 	}
 
 	// Move assignments/sensitives into a SBLOCK for each unique sensitivity list
 	// (May convert some ALWAYS to combo blocks, so should be before V3Gate step.)
 	V3Active::activeAll(v3Global.rootp());
-	V3Global::dumpGlobalTree("active.tree");
+	V3Global::dumpCheckGlobalTree("active.tree");
 
 	// Split single ALWAYS blocks into multiple blocks for better ordering chances
 	if (v3Global.opt.oSplit()) {
 	    V3Split::splitAlwaysAll(v3Global.rootp());
-	    if (dumpMore) V3Global::dumpGlobalTree("split.tree");
+	    V3Global::dumpCheckGlobalTree("split.tree", 0, dumpMore);
 	}
 	V3SplitAs::splitAsAll(v3Global.rootp());
-	V3Global::dumpGlobalTree("splitas.tree");
+	V3Global::dumpCheckGlobalTree("splitas.tree");
 
 	// Create tracing sample points, before we start eliminating signals
 	if (v3Global.opt.trace()) {
 	    V3TraceDecl::traceDeclAll(v3Global.rootp());
-	    V3Global::dumpGlobalTree("tracedecl.tree");
+	    V3Global::dumpCheckGlobalTree("tracedecl.tree");
 	}
 
 	// Gate-based logic elimination; eliminate signals and push constant across cell boundaries
 	// Instant propagation makes lots-o-constant reduction possibilities.
 	if (v3Global.opt.oGate()) {
 	    V3Gate::gateAll(v3Global.rootp());
-	    V3Global::dumpGlobalTree("gate.tree");
+	    V3Global::dumpCheckGlobalTree("gate.tree");
 	    // V3Gate calls constant propagation itself.
 	} else {
 	    v3info("Command Line disabled gate optimization with -Og/-O0.  This may cause ordering problems.");
@@ -397,14 +397,14 @@ void process () {
 	// Combine COVERINCs with duplicate terms
 	if (v3Global.opt.coverage()) {
 	    V3CoverageJoin::coverageJoin(v3Global.rootp());
-	    V3Global::dumpGlobalTree("coveragejoin.tree");
+	    V3Global::dumpCheckGlobalTree("coveragejoin.tree");
 	}
 
 	// Remove unused vars
 	V3Const::constifyAll(v3Global.rootp());
-	if (dumpMore) V3Global::dumpGlobalTree("const_predead.tree");
+	V3Global::dumpCheckGlobalTree("const_predead.tree", 0, dumpMore);
 	V3Dead::deadifyAll(v3Global.rootp());
-	V3Global::dumpGlobalTree("const.tree");
+	V3Global::dumpCheckGlobalTree("const.tree");
 
 	// Clock domain crossing analysis
 	if (v3Global.opt.cdc()) {
@@ -416,34 +416,34 @@ void process () {
 	// Reorder assignments in pipelined blocks
 	if (v3Global.opt.oReorder()) {
 	    V3Split::splitReorderAll(v3Global.rootp());
-	    V3Global::dumpGlobalTree("reorder.tree");
+	    V3Global::dumpCheckGlobalTree("reorder.tree");
 	}
 
 	// Create delayed assignments
 	// This creates lots of duplicate ACTIVES so ActiveTop needs to be after this step
 	V3Delayed::delayedAll(v3Global.rootp());
-	V3Global::dumpGlobalTree("delayed.tree");
+	V3Global::dumpCheckGlobalTree("delayed.tree");
 
 	// Make Active's on the top level
 	// Differs from V3Active, because identical clocks may be pushed down to a module and now be identical
 	V3ActiveTop::activeTopAll(v3Global.rootp());
-	V3Global::dumpGlobalTree("activetop.tree");
+	V3Global::dumpCheckGlobalTree("activetop.tree");
 
 	if (v3Global.opt.stats()) V3Stats::statsStageAll(v3Global.rootp(), "PreOrder");
 
 	// Order the code; form SBLOCKs and BLOCKCALLs
 	V3Order::orderAll(v3Global.rootp());
-	V3Global::dumpGlobalTree("order.tree");
+	V3Global::dumpCheckGlobalTree("order.tree");
 
 #ifndef NEW_ORDERING
 	// Change generated clocks to look at delayed signals
 	V3GenClk::genClkAll(v3Global.rootp());
-	V3Global::dumpGlobalTree("genclk.tree");
+	V3Global::dumpCheckGlobalTree("genclk.tree");
 #endif
 
 	// Convert sense lists into IF statements.
 	V3Clock::clockAll(v3Global.rootp());
-	V3Global::dumpGlobalTree("clock.tree");
+	V3Global::dumpCheckGlobalTree("clock.tree");
 
 	// Cleanup any dly vars or other temps that are simple assignments
 	// Life must be done before Subst, as it assumes each CFunc under _eval is called only once.
@@ -455,19 +455,19 @@ void process () {
 	    V3LifePost::lifepostAll(v3Global.rootp());
 	}
 	if (v3Global.opt.oLife() || v3Global.opt.oLifePost()) {
-	    V3Global::dumpGlobalTree("life.tree");
+	    V3Global::dumpCheckGlobalTree("life.tree");
 	}
 
 	// Remove unused vars
 	V3Const::constifyAll(v3Global.rootp());
-	if (dumpMore) V3Global::dumpGlobalTree("const_predead.tree");
+	V3Global::dumpCheckGlobalTree("const_predead.tree", 0, dumpMore);
 	V3Dead::deadifyAll(v3Global.rootp());
-	V3Global::dumpGlobalTree("const.tree");
+	V3Global::dumpCheckGlobalTree("const.tree");
 
 #ifndef NEW_ORDERING
 	// Detect change loop
 	V3Changed::changedAll(v3Global.rootp());
-	V3Global::dumpGlobalTree("changed.tree");
+	V3Global::dumpCheckGlobalTree("changed.tree");
 #endif
 
 	// Create tracing logic, since we ripped out some signals the user might want to trace
@@ -475,14 +475,14 @@ void process () {
 	// (It's OK if untraced temporaries move around, or vars "effectively" activate the same way.)
 	if (v3Global.opt.trace()) {
 	    V3Trace::traceAll(v3Global.rootp());
-	    V3Global::dumpGlobalTree("trace.tree");
+	    V3Global::dumpCheckGlobalTree("trace.tree");
 	}
 
 	if (v3Global.opt.stats()) V3Stats::statsStageAll(v3Global.rootp(), "Scoped");
 
 	// Remove scopes; make varrefs/funccalls relative to current module
 	V3Descope::descopeAll(v3Global.rootp());
-	V3Global::dumpGlobalTree("descope.tree");
+	V3Global::dumpCheckGlobalTree("descope.tree");
     }
 
     //--MODULE OPTIMIZATIONS--------------
@@ -491,19 +491,19 @@ void process () {
 	// Split deep blocks to appease MSVC++.  Must be before Localize.
 	if (!v3Global.opt.lintOnly() && v3Global.opt.compLimitBlocks()) {
 	    V3DepthBlock::depthBlockAll(v3Global.rootp());
-	    V3Global::dumpGlobalTree("deepblock.tree");
+	    V3Global::dumpCheckGlobalTree("deepblock.tree");
 	}
 
 	// Move BLOCKTEMPS from class to local variables
 	if (v3Global.opt.oLocalize()) {
 	    V3Localize::localizeAll(v3Global.rootp());
-	    if (dumpMore) V3Global::dumpGlobalTree("localize.tree");
+	    V3Global::dumpCheckGlobalTree("localize.tree", 0, dumpMore);
 	}
 
 	// Icache packing; combine common code in each module's functions into subroutines
 	if (v3Global.opt.oCombine()) {
 	    V3Combine::combineAll(v3Global.rootp());
-	    V3Global::dumpGlobalTree("combine.tree");
+	    V3Global::dumpCheckGlobalTree("combine.tree");
 	}
     }
 
@@ -514,9 +514,9 @@ void process () {
     if (!v3Global.opt.xmlOnly()) {
 	// Remove unused vars
 	V3Const::constifyAll(v3Global.rootp());
-	if (dumpMore) V3Global::dumpGlobalTree("const_predead.tree");
+	V3Global::dumpCheckGlobalTree("const_predead.tree", 0, dumpMore);
 	V3Dead::deadifyAll(v3Global.rootp());
-	V3Global::dumpGlobalTree("const.tree");
+	V3Global::dumpCheckGlobalTree("const.tree");
 
 	// Here down, widthMin() is the Verilog width, and width() is the C++ width
 	// Bits between widthMin() and width() are irrelevant, but may be non zero.
@@ -524,18 +524,18 @@ void process () {
 
 	// Make all math operations either 8, 16, 32 or 64 bits
 	V3Clean::cleanAll(v3Global.rootp());
-	V3Global::dumpGlobalTree("clean.tree");
+	V3Global::dumpCheckGlobalTree("clean.tree");
 
 	// Move wide constants to BLOCK temps.
 	V3Premit::premitAll(v3Global.rootp());
-	V3Global::dumpGlobalTree("premit.tree");
+	V3Global::dumpCheckGlobalTree("premit.tree");
     }
 
     // Expand macros and wide operators into C++ primitives
     if (!v3Global.opt.xmlOnly()
 	&& v3Global.opt.oExpand()) {
 	V3Expand::expandAll(v3Global.rootp());
-	V3Global::dumpGlobalTree("expand.tree");
+	V3Global::dumpCheckGlobalTree("expand.tree");
     }
 
     // Propagate constants across WORDSEL arrayed temporaries
@@ -543,18 +543,18 @@ void process () {
 	&& v3Global.opt.oSubst()) {
 	// Constant folding of expanded stuff
 	V3Const::constifyCpp(v3Global.rootp());
-	V3Global::dumpGlobalTree("const.tree");
+	V3Global::dumpCheckGlobalTree("const.tree");
 	V3Subst::substituteAll(v3Global.rootp());
-	V3Global::dumpGlobalTree("subst.tree");
+	V3Global::dumpCheckGlobalTree("subst.tree");
     }
     if (!v3Global.opt.xmlOnly()
 	&& v3Global.opt.oSubstConst()) {
 	// Constant folding of substitutions
 	V3Const::constifyCpp(v3Global.rootp());
-	if (dumpMore) V3Global::dumpGlobalTree("constc.tree");
+	V3Global::dumpCheckGlobalTree("constc.tree", 0, dumpMore);
 
 	V3Dead::deadifyAll(v3Global.rootp());
-	V3Global::dumpGlobalTree("dead.tree");
+	V3Global::dumpCheckGlobalTree("dead.tree");
     }
 
     if (!v3Global.opt.lintOnly()
@@ -562,7 +562,7 @@ void process () {
 	// Fix very deep expressions
 	// Mark evaluation functions as member functions, if needed.
 	V3Depth::depthAll(v3Global.rootp());
-	if (dumpMore) V3Global::dumpGlobalTree("depth.tree");
+	V3Global::dumpCheckGlobalTree("depth.tree", 0, dumpMore);
 
 	// Branch prediction
 	V3Branch::branchAll(v3Global.rootp());
@@ -570,7 +570,7 @@ void process () {
 	// Add C casts when longs need to become long-long and vice-versa
 	// Note depth may insert something needing a cast, so this must be last.
 	V3Cast::castAll(v3Global.rootp());
-	V3Global::dumpGlobalTree("cast.tree");
+	V3Global::dumpCheckGlobalTree("cast.tree");
     }
 
     V3Error::abortIfErrors();
@@ -676,7 +676,7 @@ int main(int argc, char** argv, char** env) {
     }
 
     // Final steps
-    V3Global::dumpGlobalTree("final.tree",990);
+    V3Global::dumpCheckGlobalTree("final.tree",990);
     V3Error::abortIfWarnings();
 
     if (!v3Global.opt.lintOnly() && !v3Global.opt.cdc()
diff --git a/src/config_build.h b/src/config_build.h
index 3859bb8..d5755b8 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.853 2013-09-30"
+#define PACKAGE_STRING "Verilator 3.854 2013-11-26"
 
 #define DTVERSION	PACKAGE_STRING
 
diff --git a/src/config_rev.h b/src/config_rev.h
index d26d493..1680fa2 100644
--- a/src/config_rev.h
+++ b/src/config_rev.h
@@ -1 +1 @@
-static const char* DTVERSION_rev = "verilator_3_852-3-g761b9c9";
+static const char* DTVERSION_rev = "verilator_3_853-19-g0e1fcd3";
diff --git a/test_regress/driver.pl b/test_regress/driver.pl
index 74d719d..d47684e 100755
--- a/test_regress/driver.pl
+++ b/test_regress/driver.pl
@@ -713,7 +713,7 @@ sub execute {
 		   @{$param{all_run_flags}},
 		          );
 	if ($param{iv_pli}) {
-	    unshift @cmd, "vvp -m $self->{obj_dir}/libvpi.so";
+	    unshift @cmd, "vvp -n -m $self->{obj_dir}/libvpi.so"; # don't enter command line on $stop, include vpi
 	}
 	$self->_run(logfile=>"$self->{obj_dir}/iv_sim.log",
 		    fails=>$param{fails},
@@ -1212,7 +1212,7 @@ sub _make_top_v {
     print $fh "   initial begin\n";
     print $fh "      \$display(\"-Tracing Waves to Dumpfile: $self->{vcd_filename}\");\n";
     print $fh "      \$dumpfile(\"$self->{vcd_filename}\");\n";
-    print $fh "      \$dumpvars(12, t);\n";
+    print $fh "      \$dumpvars(0, top);\n";
     print $fh "   end\n";
     print $fh "`endif\n";
 
diff --git a/test_regress/t/TestSimulator.h b/test_regress/t/TestSimulator.h
new file mode 100644
index 0000000..4a875e6
--- /dev/null
+++ b/test_regress/t/TestSimulator.h
@@ -0,0 +1,78 @@
+// -*- mode: C++; c-file-style: "cc-mode" -*-
+//*************************************************************************
+//
+// Copyright 2013-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.
+//
+// Verilator is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+//*************************************************************************
+
+#include "vpi_user.h"
+
+class TestSimulator {
+private:
+    struct SimTypes {
+	int verilator;
+	int icarus;
+	int mti;
+	int ncsim;
+	int vcs;
+    };
+    s_vpi_vlog_info   m_info;
+    SimTypes          m_simulators;
+public:
+    TestSimulator() {
+	vpi_get_vlog_info(&m_info);
+	if (0 == strcmp(m_info.product, "Verilator")) {
+	    m_simulators.verilator = true;
+	} else if (0 == strcmp(m_info.product, "Verilator")) {
+	    m_simulators.icarus = true;
+	} else if (0 == strncmp(m_info.product, "Chronologic Simulation VCS", strlen("Chronologic Simulation VCS"))) {
+	    m_simulators.vcs = true;
+	} else {
+	    printf("%%Warning: %s:%d: Unknown simulator in TestSimulator.h: %s\n",
+		   __FILE__, __LINE__, m_info.product);
+	}
+    }
+    ~TestSimulator() { }
+    // METHORS
+private:
+    static TestSimulator& singleton() {
+	static TestSimulator s_singleton;
+	return s_singleton;
+    }
+    static const SimTypes& simulators() { return singleton().m_simulators; }
+public:
+    static const s_vpi_vlog_info& get_info() { return singleton().m_info; }
+    // Simulator names
+    static bool is_icarus() { return simulators().icarus; }
+    static bool is_verilator() { return simulators().verilator; }
+    static bool is_mti() { return simulators().mti; }
+    static bool is_ncsim() { return simulators().ncsim; }
+    static bool is_vcs() { return simulators().vcs; }
+    // Simulator properties
+    static bool is_event_driven() { return !simulators().verilator; }
+    static bool has_get_scalar() { return !simulators().icarus; }
+    // return test level scope
+    static const char* top() {
+	if (simulators().verilator) {
+	    return "t";
+	} else {
+	    return "top.t";
+	}
+    }
+    // return absolute scope of obj
+    static const char* rooted(const char *obj) {
+	static char buf[256];
+	snprintf(buf, sizeof(buf), "%s.%s", top(), obj);
+	return buf;
+    }
+};
+
+#define VPI_HANDLE(signal) vpi_handle_by_name((PLI_BYTE8*)TestSimulator::rooted(signal), NULL);
diff --git a/test_regress/t/t_dpi_string_c.cpp b/test_regress/t/TestVpi.h
similarity index 50%
copy from test_regress/t/t_dpi_string_c.cpp
copy to test_regress/t/TestVpi.h
index cba6071..642c378 100644
--- a/test_regress/t/t_dpi_string_c.cpp
+++ b/test_regress/t/TestVpi.h
@@ -1,7 +1,7 @@
 // -*- mode: C++; c-file-style: "cc-mode" -*-
 //*************************************************************************
 //
-// Copyright 2009-2009 by Wilson Snyder. This program is free software; you can
+// Copyright 2013-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.
@@ -13,32 +13,22 @@
 //
 //*************************************************************************
 
-#include <cstdio>
-#include "svdpi.h"
+#include "vpi_user.h"
 
 //======================================================================
 
-#if defined(VERILATOR)
-# include "Vt_dpi_string__Dpi.h"
-#elif defined(VCS)
-# include "../vc_hdrs.h"
-#elif defined(CADENCE)
-# define NEED_EXTERNS
-#else
-# error "Unknown simulator for DPI test"
-#endif
-
-#ifdef NEED_EXTERNS
-extern "C" {
-
-    extern int dpii_string (const char* s);
-
-}
-#endif
-
-//======================================================================
-
-int dpii_string(const char* s) {
-    printf("dpii_string: %s\n",s);
-    return strlen(s);
-}
+class TestVpiHandle {
+    /// For testing, etc, wrap vpiHandle in an auto-releasing class
+    vpiHandle m_handle;
+    bool      m_free;
+public:
+    TestVpiHandle() : m_handle(NULL), m_free(true) { }
+    TestVpiHandle(vpiHandle h) : m_handle(h), m_free(true) { }
+    ~TestVpiHandle() { if (m_handle && m_free) { vpi_free_object(m_handle); m_handle=NULL; } } // icarus has yet to catch up with 1800-2009
+    operator vpiHandle () const { return m_handle; }
+    inline TestVpiHandle& operator= (vpiHandle h) { m_handle = h; return *this; }
+    TestVpiHandle& nofree() {
+	m_free = false;
+        return *this;
+    }
+};
diff --git a/test_regress/t/t_cover_toggle.v b/test_regress/t/t_cover_toggle.v
index 21d8ed6..8dce8e3 100644
--- a/test_regress/t/t_cover_toggle.v
+++ b/test_regress/t/t_cover_toggle.v
@@ -10,7 +10,21 @@ module t (/*AUTOARG*/
 
    input clk;
 
-   reg 	 toggle; initial toggle=0;
+   typedef struct packed {
+      union packed {
+	 logic 	  ua;
+	 logic 	  ub;
+      } u;
+      logic b;
+   } str_t;
+
+   reg 	 toggle; initial toggle='0;
+
+   str_t stoggle; initial stoggle='0;
+
+   const reg aconst = '0;
+
+   reg [1:0][1:0] ptoggle; initial ptoggle=0;
 
    integer cyc; initial cyc=1;
    wire [7:0] cyc_copy = cyc[7:0];
@@ -51,6 +65,9 @@ module t (/*AUTOARG*/
 	 cyc <= cyc + 1;
 	 memory[cyc + 'd100] <= memory[cyc + 'd100] + 2'b1;
 	 toggle <= '0;
+	 stoggle.u <= toggle;
+	 stoggle.b <= toggle;
+	 ptoggle[0][0] <= toggle;
 	 if (cyc==3) begin
 	    toggle <= '1;
 	 end
diff --git a/test_regress/t/t_dpi_string_c.cpp b/test_regress/t/t_dpi_string_c.cpp
index cba6071..540beed 100644
--- a/test_regress/t/t_dpi_string_c.cpp
+++ b/test_regress/t/t_dpi_string_c.cpp
@@ -14,6 +14,7 @@
 //*************************************************************************
 
 #include <cstdio>
+#include <cstring>
 #include "svdpi.h"
 
 //======================================================================
diff --git a/test_regress/t/t_enum.v b/test_regress/t/t_enum.v
index 9548fc9..1681cb6 100644
--- a/test_regress/t/t_enum.v
+++ b/test_regress/t/t_enum.v
@@ -34,6 +34,9 @@ module t (/*AUTOARG*/);
 
    var logic [ONES:0] sized_based_on_enum;
 
+   var enum logic [3:0]  { QINVALID='1, QSEND={2'b0,2'h0}, QOP={2'b0,2'h1}, QCL={2'b0,2'h2},
+			   QPR={2'b0,2'h3 }, QACK, QRSP } inv;
+
    initial begin
       if (e0 !== 0) $stop;
       if (e1 !== 1) $stop;
@@ -61,6 +64,14 @@ module t (/*AUTOARG*/);
       if (FIVE[BIT1] != 1'b0) $stop;
       if (FIVE[BIT2] != 1'b1) $stop;
 
+      if (QINVALID != 15) $stop;
+      if (QSEND    !=  0) $stop;
+      if (QOP      !=  1) $stop;
+      if (QCL      !=  2) $stop;
+      if (QPR      !=  3) $stop;
+      if (QACK     !=  4) $stop;
+      if (QRSP     !=  5) $stop;
+
       $write("*-* All Finished *-*\n");
       $finish;
    end
diff --git a/test_regress/t/t_select_index2.pl b/test_regress/t/t_param_chain.pl
similarity index 91%
copy from test_regress/t/t_select_index2.pl
copy to test_regress/t/t_param_chain.pl
index 570a6d9..f912897 100755
--- a/test_regress/t/t_select_index2.pl
+++ b/test_regress/t/t_param_chain.pl
@@ -8,7 +8,10 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 # Version 2.0.
 
 compile (
-    v_flags2 => ["--lint-only"],
+    );
+
+execute (
+    check_finished=>1,
     );
 
 ok(1);
diff --git a/test_regress/t/t_param_chain.v b/test_regress/t/t_param_chain.v
new file mode 100644
index 0000000..543a178
--- /dev/null
+++ b/test_regress/t/t_param_chain.v
@@ -0,0 +1,36 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed into the Public Domain, for any use,
+// without warranty, 2013 by Wilson Snyder.
+
+module t (/*AUTOARG*/);
+
+    function integer max2;
+       input integer x;
+       input integer y;
+       begin
+	  begin : blk
+	     automatic int temp;
+	     temp = x;
+	  end
+       end
+       max2 = ( x > y ) ? x : y;
+    endfunction
+
+    function integer max4;
+       input integer x;
+       input integer y;
+       input integer z;
+       input integer w;
+       // MAX2 is used multiple times
+       max4 = max2( max2( x, y ), max2( z, w ) );
+    endfunction
+
+   localparam  MAX4 = max4( 1, 1, 0, 0 );
+
+   initial begin
+      if (MAX4 != 1) $stop;
+      $write("*-* All Finished *-*\n");
+      $finish;
+   end
+endmodule
diff --git a/test_regress/t/t_select_index2.pl b/test_regress/t/t_select_index2.pl
index 570a6d9..514f638 100755
--- a/test_regress/t/t_select_index2.pl
+++ b/test_regress/t/t_select_index2.pl
@@ -9,6 +9,9 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 
 compile (
     v_flags2 => ["--lint-only"],
+    make_top_shell => 0,
+    make_main => 0,
+    verilator_make_gcc => 0,
     );
 
 ok(1);
diff --git a/test_regress/t/t_select_index2.pl b/test_regress/t/t_struct_unpacked.pl
similarity index 91%
copy from test_regress/t/t_select_index2.pl
copy to test_regress/t/t_struct_unpacked.pl
index 570a6d9..f912897 100755
--- a/test_regress/t/t_select_index2.pl
+++ b/test_regress/t/t_struct_unpacked.pl
@@ -8,7 +8,10 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 # Version 2.0.
 
 compile (
-    v_flags2 => ["--lint-only"],
+    );
+
+execute (
+    check_finished=>1,
     );
 
 ok(1);
diff --git a/test_regress/t/t_struct_unpacked_bad.v b/test_regress/t/t_struct_unpacked.v
similarity index 55%
copy from test_regress/t/t_struct_unpacked_bad.v
copy to test_regress/t/t_struct_unpacked.v
index d5030de..92d7596 100644
--- a/test_regress/t/t_struct_unpacked_bad.v
+++ b/test_regress/t/t_struct_unpacked.v
@@ -5,12 +5,22 @@
 
 module x;
 
+   // verilator lint_off UNPACKED
    typedef struct {
       int 	  a;
    } notpacked_t;
+   // verilator lint_on UNPACKED
 
    typedef struct packed {
-      notpacked_t	a;
+      notpacked_t b;
    } ispacked_t;
 
+   ispacked_t p;
+
+   initial begin
+      p.b = 1;
+      if (p.b != 1) $stop;
+      $write("*-* All Finished *-*\n");
+      $finish;
+   end
 endmodule
diff --git a/test_regress/t/t_struct_unpacked_bad.pl b/test_regress/t/t_struct_unpacked_bad.pl
index b58b030..095c350 100755
--- a/test_regress/t/t_struct_unpacked_bad.pl
+++ b/test_regress/t/t_struct_unpacked_bad.pl
@@ -10,7 +10,8 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 compile (
 	 fails=>$Self->{v3},
 	 expect=>
-q{%Error: t/t_struct_unpacked_bad.v:8: Unsupported: Unpacked struct/union
+q{%Warning-UNPACKED: t/t_struct_unpacked_bad.v:\d+: Unsupported: Unpacked struct/union
+%Warning-UNPACKED: Use .*
 .*%Error: Exiting due to.*},
 	 );
 
diff --git a/test_regress/t/t_struct_unpacked_bad.v b/test_regress/t/t_struct_unpacked_bad.v
index d5030de..c726c13 100644
--- a/test_regress/t/t_struct_unpacked_bad.v
+++ b/test_regress/t/t_struct_unpacked_bad.v
@@ -10,7 +10,15 @@ module x;
    } notpacked_t;
 
    typedef struct packed {
-      notpacked_t	a;
+      notpacked_t b;
    } ispacked_t;
 
+   ispacked_t p;
+
+   initial begin
+      p.b = 1;
+      if (p.b != 1) $stop;
+      $write("*-* All Finished *-*\n");
+      $finish;
+   end
 endmodule
diff --git a/test_regress/t/t_var_const.v b/test_regress/t/t_var_const.v
index 6a38084..2eebf5b 100644
--- a/test_regress/t/t_var_const.v
+++ b/test_regress/t/t_var_const.v
@@ -12,8 +12,13 @@ module t (/*AUTOARG*/
 
    const logic [2:0] five = 3'd5;
 
+   const logic unsigned [31:0] var_const = 22;
+   logic [7:0] res_const;
+   assign res_const = var_const[7:0];  // bug693
+
    always @ (posedge clk) begin
       if (five !== 3'd5) $stop;
+      if (res_const !== 8'd22) $stop;
       $write("*-* All Finished *-*\n");
       $finish;
    end
diff --git a/test_regress/t/t_vpi_get.cpp b/test_regress/t/t_vpi_get.cpp
new file mode 100644
index 0000000..e1e78dc
--- /dev/null
+++ b/test_regress/t/t_vpi_get.cpp
@@ -0,0 +1,283 @@
+// -*- mode: C++; c-file-style: "cc-mode" -*-
+//*************************************************************************
+//
+// Copyright 2010-2011 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.
+//
+// Verilator is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+//*************************************************************************
+
+#ifdef IS_VPI
+
+#include "vpi_user.h"
+#include <cstdlib>
+
+#else
+
+#include "Vt_vpi_get.h"
+#include "verilated.h"
+#include "svdpi.h"
+
+#include "Vt_vpi_get__Dpi.h"
+
+#include "verilated_vpi.h"
+#include "verilated_vpi.cpp"
+#include "verilated_vcd_c.h"
+
+#endif
+
+#include <cstdio>
+#include <cstring>
+#include <iostream>
+using namespace std;
+
+#include "TestSimulator.h"
+#include "TestVpi.h"
+
+// __FILE__ is too long
+#define FILENM "t_vpi_get.cpp"
+
+#define TEST_MSG if (0) printf
+
+unsigned int main_time = false;
+
+//======================================================================
+
+#define CHECK_RESULT_VH(got, exp) \
+    if ((got) != (exp)) { \
+	printf("%%Error: %s:%d: GOT = %p   EXP = %p\n", \
+	       FILENM,__LINE__, (got), (exp)); \
+	return __LINE__; \
+    }
+
+#define CHECK_RESULT_NZ(got) \
+    if (!(got)) { \
+	printf("%%Error: %s:%d: GOT = NULL  EXP = !NULL\n", FILENM,__LINE__); \
+	return __LINE__; \
+    }
+
+// Use cout to avoid issues with %d/%lx etc
+#define CHECK_RESULT(got, exp) \
+    if ((got) != (exp)) {			     \
+	cout<<dec<<"%Error: "<<FILENM<<":"<<__LINE__ \
+	   <<": GOT = "<<(got)<<"   EXP = "<<(exp)<<endl;	\
+	return __LINE__; \
+    }
+
+#define CHECK_RESULT_HEX(got, exp) \
+    if ((got) != (exp)) {				  \
+	cout<<dec<<"%Error: "<<FILENM<<":"<<__LINE__<<hex \
+	   <<": GOT = "<<(got)<<"   EXP = "<<(exp)<<endl;	\
+	return __LINE__; \
+    }
+
+#define CHECK_RESULT_CSTR(got, exp) \
+    if (strcmp((got),(exp))) { \
+	printf("%%Error: %s:%d: GOT = '%s'   EXP = '%s'\n", \
+	       FILENM,__LINE__, (got)?(got):"<null>", (exp)?(exp):"<null>"); \
+	return __LINE__; \
+    }
+
+#define CHECK_RESULT_CSTR_STRIP(got, exp) \
+    CHECK_RESULT_CSTR(got+strspn(got, " "), exp)
+
+static int _mon_check_props(TestVpiHandle& handle, int size, int direction, int scalar, int type) {
+    s_vpi_value value = {
+      vpiIntVal
+    };
+    // check size of object
+    int vpisize = vpi_get(vpiSize, handle);
+    CHECK_RESULT(vpisize, size);
+
+    // icarus verilog does not support vpiScalar, vpiVector or vpi*Range
+    if (TestSimulator::has_get_scalar()) {
+      int vpiscalar = vpi_get(vpiScalar, handle);
+      CHECK_RESULT((bool)vpiscalar, (bool)scalar);
+      int vpivector = vpi_get(vpiVector, handle);
+      CHECK_RESULT((bool)vpivector, (bool)!scalar);
+    }
+
+    // Icarus only supports ranges on memories
+    if (!scalar && !(TestSimulator::is_icarus() && type != vpiMemory)) {
+      TestVpiHandle left_h, right_h;
+
+      // check coherency for vectors
+      // get left hand side of range
+      left_h = vpi_handle(vpiLeftRange, handle);
+      CHECK_RESULT_NZ(left_h);
+      vpi_get_value(left_h, &value);
+      int coherency = value.value.integer;
+      // get right hand side of range
+      right_h = vpi_handle(vpiRightRange, handle);
+      CHECK_RESULT_NZ(right_h);
+      vpi_get_value(right_h, &value);
+      TEST_MSG("%d:%d\n", coherency, value.value.integer);
+      coherency -= value.value.integer;
+      // calculate size & check
+      coherency = abs(coherency) + 1;
+      CHECK_RESULT(coherency, size);
+    }
+
+    // Only check direction on ports
+    if (type == vpiPort) {
+      // check direction of object
+      int vpidir = vpi_get(vpiDirection, handle);
+      // Don't check port directions in verilator
+      // see #681
+      if (!TestSimulator::is_verilator()) {
+        CHECK_RESULT(vpidir, direction);
+      }
+    }
+
+    // check type of object
+    int vpitype = vpi_get(vpiType, handle);
+    if (!(TestSimulator::is_verilator() && type == vpiPort)) {
+      // Don't check for ports in verilator
+      // see #681
+      CHECK_RESULT(vpitype, type);
+    }
+
+    return 0; // Ok
+}
+
+struct params {
+    const char*   signal;
+    struct {
+      unsigned int  size;
+      unsigned int  direction;
+      unsigned int  scalar;
+      unsigned int  type;
+    } attributes, children;
+} values[] = {
+    {"onebit", {1, vpiNoDirection, 1, vpiReg}, {0, 0, 0, 0}},
+    {"twoone", {2, vpiNoDirection, 0, vpiReg}, {0, 0, 0, 0}},
+    {"onetwo", {2, vpiNoDirection, 0, TestSimulator::is_verilator() ? vpiReg : vpiMemory}, {0, 0, 0, 0}},
+    {"fourthreetwoone", {2, vpiNoDirection, 0, vpiMemory}, {2, vpiNoDirection, 0, vpiMemoryWord}},
+    {"clk", {1, vpiInput, 1, vpiPort}, {0, 0, 0, 0}},
+    {"testin", {16, vpiInput, 0, vpiPort}, {0, 0, 0, 0}},
+    {"testout", {24, vpiOutput, 0, vpiPort}, {0, 0, 0, 0}},
+    {"sub.subin", {1, vpiInput, 1, vpiPort}, {0, 0, 0, 0}},
+    {"sub.subout", {1, vpiOutput, 1, vpiPort}, {0, 0, 0, 0}},
+    {NULL, {0, 0, 0, 0}, {0, 0, 0, 0}}
+};
+
+int mon_check_props() {
+    struct params* value = values;
+    while (value->signal) {
+      TestVpiHandle h = VPI_HANDLE(value->signal);
+      CHECK_RESULT_NZ(h);
+      TEST_MSG("%s\n", value->signal);
+      if (int status = _mon_check_props(h, value->attributes.size, value->attributes.direction, value->attributes.scalar, value->attributes.type)) return status;
+      if (value->children.size) {
+        int size = 0;
+        TestVpiHandle iter_h = vpi_iterate(vpiMemoryWord, h);
+        while (TestVpiHandle word_h = vpi_scan(iter_h.nofree())) {
+          // check size and range
+          if (int status = _mon_check_props(word_h, value->children.size, value->children.direction, value->children.scalar, value->children.type)) return status;
+          size++;
+        }
+        CHECK_RESULT(size, value->attributes.size);
+      }
+      value++;
+    }
+    return 0;
+}
+
+int mon_check() {
+    // Callback from initial block in monitor
+    if (int status = mon_check_props()) return status;
+    return 0; // Ok
+}
+
+//======================================================================
+
+#ifdef IS_VPI
+
+static int mon_check_vpi() {
+  vpiHandle href = vpi_handle(vpiSysTfCall, 0);
+  s_vpi_value vpi_value;
+
+  vpi_value.format = vpiIntVal;
+  vpi_value.value.integer = mon_check();
+  vpi_put_value(href, &vpi_value, NULL, vpiNoDelay);
+
+  return 0;
+}
+
+static s_vpi_systf_data vpi_systf_data[] = {
+  {vpiSysFunc, vpiIntFunc, (PLI_BYTE8*)"$mon_check", (PLI_INT32(*)(PLI_BYTE8*))mon_check_vpi, 0, 0, 0},
+  0
+};
+
+// cver entry
+void vpi_compat_bootstrap(void) {
+  p_vpi_systf_data systf_data_p;
+  systf_data_p = &(vpi_systf_data[0]);
+  while (systf_data_p->type != 0) vpi_register_systf(systf_data_p++);
+}
+
+// icarus entry
+void (*vlog_startup_routines[])() = {
+      vpi_compat_bootstrap,
+      0
+};
+
+#else
+double sc_time_stamp () {
+    return main_time;
+}
+int main(int argc, char **argv, char **env) {
+    double sim_time = 1100;
+    Verilated::commandArgs(argc, argv);
+    Verilated::debug(0);
+
+    VM_PREFIX* topp = new VM_PREFIX ("");  // Note null name - we're flattening it out
+
+#ifdef VERILATOR
+# ifdef TEST_VERBOSE
+    Verilated::scopesDump();
+# endif
+#endif
+
+    Verilated::traceEverOn(true);
+    VerilatedVcdC* tfp = new VerilatedVcdC;
+#if VM_TRACE
+    VL_PRINTF("Enabling waves...\n");
+    topp->trace (tfp, 99);
+    tfp->open ("obj_dir/t_vpi_var/simx.vcd");
+#endif
+
+    topp->eval();
+    topp->clk = 0;
+    main_time += 10;
+
+    while (sc_time_stamp() < sim_time && !Verilated::gotFinish()) {
+	main_time += 1;
+	topp->eval();
+	VerilatedVpi::callValueCbs();
+	topp->clk = !topp->clk;
+	//mon_do();
+#if VM_TRACE
+	if (tfp) tfp->dump (main_time);
+#endif
+    }
+    if (!Verilated::gotFinish()) {
+	vl_fatal(FILENM,__LINE__,"main", "%Error: Timeout; never got a $finish");
+    }
+    topp->final();
+
+#if VM_TRACE
+    if (tfp) tfp->close();
+#endif
+
+    delete topp; topp=NULL;
+    exit(0L);
+}
+
+#endif
diff --git a/test_regress/t/t_vpi_memory.pl b/test_regress/t/t_vpi_get.pl
similarity index 81%
copy from test_regress/t/t_vpi_memory.pl
copy to test_regress/t/t_vpi_get.pl
index 5a1982e..bb8c84c 100755
--- a/test_regress/t/t_vpi_memory.pl
+++ b/test_regress/t/t_vpi_get.pl
@@ -10,16 +10,16 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 compile (
     make_top_shell => 0,
     make_main => 0,
+    verilator_flags2 => ["-CFLAGS '-DVL_DEBUG -ggdb' --exe --no-l2name $Self->{t_dir}/t_vpi_get.cpp"],
     make_pli => 1,
-    iv_flags2 => ["-g2005-sv -D USE_VPI_NOT_DPI -s t -o obj_dir/iv_t_vpi_memory/simiv"],
+    iv_flags2 => ["-g2005-sv -D USE_VPI_NOT_DPI"],
     v_flags2 => ["+define+USE_VPI_NOT_DPI"],
-    verilator_flags2 => ["-CFLAGS '-DVL_DEBUG -ggdb' --exe --no-l2name $Self->{t_dir}/t_vpi_memory.cpp"],
-    );
+);
 
 execute (
     iv_pli => 1,
     check_finished=>1
-    );
+);
 
 ok(1);
 1;
diff --git a/test_regress/t/t_vpi_get.v b/test_regress/t/t_vpi_get.v
new file mode 100644
index 0000000..4bc4740
--- /dev/null
+++ b/test_regress/t/t_vpi_get.v
@@ -0,0 +1,71 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// Copyright 2010 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.
+
+`ifdef USE_VPI_NOT_DPI
+//We call it via $c so we can verify DPI isn't required - see bug572
+`else
+import "DPI-C" context function integer mon_check();
+`endif
+
+module t (/*AUTOARG*/
+   // Inputs
+   input clk                          	/*verilator public_flat_rd		  */,
+
+   // test ports
+   input  [15:0] 	testin  	/*verilator public_flat_rd		  */,
+   output [23:0] 	testout 	/*verilator public_flat_rw @(posedge clk) */
+
+   );
+
+`ifdef VERILATOR
+`systemc_header
+extern "C" int mon_check();
+`verilog
+`endif
+
+   reg		onebit		/*verilator public_flat_rw @(posedge clk) */;
+   reg [2:1]	twoone		/*verilator public_flat_rw @(posedge clk) */;
+   reg   	onetwo [1:2]	/*verilator public_flat_rw @(posedge clk) */;
+   reg [2:1] 	fourthreetwoone[4:3] /*verilator public_flat_rw @(posedge clk) */;
+
+   integer      status;
+
+`ifdef iverilog
+   // stop icarus optimizing signals away
+   wire 	redundant = onebit | onetwo[1] | twoone | fourthreetwoone[3];
+`endif
+
+   wire         subin  /*verilator public_flat_rd*/;
+   wire         subout /*verilator public_flat_rd*/;
+   sub sub(.*);
+
+   // Test loop
+   initial begin
+`ifdef VERILATOR
+      status = $c32("mon_check()");
+`endif
+`ifdef iverilog
+     status = $mon_check();
+`endif
+`ifndef USE_VPI_NOT_DPI
+     status = mon_check();
+`endif
+      if (status!=0) begin
+	 $write("%%Error: t_vpi_var.cpp:%0d: C Test failed\n", status);
+	 $stop;
+      end
+      $write("*-* All Finished *-*\n");
+      $finish;
+   end
+
+endmodule : t
+
+module sub (
+   input  subin  /*verilator public_flat_rd*/,
+   output subout /*verilator public_flat_rd*/
+);
+endmodule : sub
diff --git a/test_regress/t/t_vpi_memory.cpp b/test_regress/t/t_vpi_memory.cpp
index 0a9ad78..785ef94 100644
--- a/test_regress/t/t_vpi_memory.cpp
+++ b/test_regress/t/t_vpi_memory.cpp
@@ -16,6 +16,7 @@
 #ifdef IS_VPI
 
 #include "vpi_user.h"
+#include <cstdlib>
 
 #else
 
@@ -36,6 +37,9 @@
 #include <iostream>
 using namespace std;
 
+#include "TestSimulator.h"
+#include "TestVpi.h"
+
 // __FILE__ is too long
 #define FILENM "t_vpi_memory.cpp"
 
@@ -45,19 +49,6 @@ unsigned int main_time = false;
 
 //======================================================================
 
-class VlVpiHandle {
-    /// For testing, etc, wrap vpiHandle in an auto-releasing class
-    vpiHandle m_handle;
-public:
-    VlVpiHandle() : m_handle(NULL) { }
-    VlVpiHandle(vpiHandle h) : m_handle(h) { }
-    ~VlVpiHandle() { if (m_handle) { vpi_free_object(m_handle); m_handle=NULL; } } // icarus has yet to catch up with 1800-2009
-    operator vpiHandle () const { return m_handle; }
-    inline VlVpiHandle& operator= (vpiHandle h) { m_handle = h; return *this; }
-};
-
-//======================================================================
-
 #define CHECK_RESULT_VH(got, exp) \
     if ((got) != (exp)) { \
 	printf("%%Error: %s:%d: GOT = %p   EXP = %p\n", \
@@ -96,30 +87,14 @@ public:
 #define CHECK_RESULT_CSTR_STRIP(got, exp) \
     CHECK_RESULT_CSTR(got+strspn(got, " "), exp)
 
-// ideally we should be able to iterate on vpiRange against a list of this struct
-typedef struct range {
-    int size;
-    int left;
-    int right;
-} range_s, *range_p;
-
-int _mon_check_range(VlVpiHandle& handle, int size, int left, int right) {
-    VlVpiHandle iter_h, rng_h, left_h, right_h;
+int _mon_check_range(TestVpiHandle& handle, int size, int left, int right) {
+    TestVpiHandle iter_h, left_h, right_h;
     s_vpi_value value = {
       vpiIntVal
     };
     // check size of object
     int vpisize = vpi_get(vpiSize, handle);
     CHECK_RESULT(vpisize, size);
-/*
-    // get range and check against expected
-    iter_h = vpi_iterate(vpiRange, handle);
-    CHECK_RESULT_NZ(iter_h);
-    rng_h = vpi_scan(iter_h);
-    CHECK_RESULT_NZ(rng_h);
-    int vpitype = vpi_get(vpiType, rng_h);
-    CHECK_RESULT(vpitype, vpiRange);
-*/
     // check size of range
     vpisize = vpi_get(vpiSize, handle);
     CHECK_RESULT(vpisize, size);
@@ -128,28 +103,33 @@ int _mon_check_range(VlVpiHandle& handle, int size, int left, int right) {
     CHECK_RESULT_NZ(left_h);
     vpi_get_value(left_h, &value);
     CHECK_RESULT(value.value.integer, left);
+    int coherency = value.value.integer;
     // check right hand side of range
     right_h = vpi_handle(vpiRightRange, handle);
     CHECK_RESULT_NZ(right_h);
     vpi_get_value(right_h, &value);
     CHECK_RESULT(value.value.integer, right);
+    coherency -= value.value.integer;
+    // calculate size & check
+    coherency = abs(coherency) + 1;
+    CHECK_RESULT(coherency, size);
     return 0; // Ok
 }
 
 int _mon_check_memory() {
     int cnt;
-    VlVpiHandle mem_h, lcl_h;
+    TestVpiHandle mem_h, lcl_h;
     vpiHandle iter_h; // icarus does not like auto free of iterator handles
     s_vpi_value value = {
       vpiIntVal
     };
     vpi_printf((PLI_BYTE8*)"Check memory vpi ...\n");
-    mem_h = vpi_handle_by_name((PLI_BYTE8*)"t.mem0", NULL);
+    mem_h = vpi_handle_by_name((PLI_BYTE8*)TestSimulator::rooted("mem0"), NULL);
     CHECK_RESULT_NZ(mem_h);
     // check type
     int vpitype = vpi_get(vpiType, mem_h);
     CHECK_RESULT(vpitype, vpiMemory);
-    _mon_check_range(mem_h, 16, 16, 1);
+    if (int status = _mon_check_range(mem_h, 16, 16, 1)) return status;
     // iterate and store
     iter_h = vpi_iterate(vpiMemoryWord, mem_h);
     cnt = 0;
@@ -157,7 +137,7 @@ int _mon_check_memory() {
 	value.value.integer = ++cnt;
         vpi_put_value(lcl_h, &value, NULL, vpiNoDelay);
         // check size and range
-        _mon_check_range(lcl_h, 32, 31, 0);
+        if (int status = _mon_check_range(lcl_h, 32, 31, 0)) return status;
     }
     CHECK_RESULT(cnt, 16); // should be 16 addresses
     // iterate and accumulate
@@ -171,10 +151,8 @@ int _mon_check_memory() {
     CHECK_RESULT(cnt, 16); // should be 16 addresses
     // don't care for non verilator
     // (crashes on Icarus)
-    s_vpi_vlog_info info;
-    vpi_get_vlog_info(&info);
-    if (strcmp(info.product, "Verilator") != 0) {
-	vpi_printf((PLI_BYTE8*)"Skipping property checks for simulator %s\n", info.product);
+    if (TestSimulator::is_icarus()) {
+	vpi_printf((PLI_BYTE8*)"Skipping property checks for simulator %s\n", TestSimulator::get_info().product);
         return 0; // Ok
     }
     // make sure trying to get properties that don't exist
@@ -202,9 +180,19 @@ int mon_check() {
 
 #ifdef IS_VPI
 
+static int mon_check_vpi() {
+  vpiHandle href = vpi_handle(vpiSysTfCall, 0);
+  s_vpi_value vpi_value;
+
+  vpi_value.format = vpiIntVal;
+  vpi_value.value.integer = mon_check();
+  vpi_put_value(href, &vpi_value, NULL, vpiNoDelay);
+
+  return 0;
+}
 
 static s_vpi_systf_data vpi_systf_data[] = {
-  {vpiSysFunc, vpiSysFunc, (PLI_BYTE8*)"$mon_check", (PLI_INT32(*)(PLI_BYTE8*))mon_check, 0, 0, 0},
+  {vpiSysFunc, vpiIntFunc, (PLI_BYTE8*)"$mon_check", (PLI_INT32(*)(PLI_BYTE8*))mon_check_vpi, 0, 0, 0},
   0
 };
 
@@ -222,6 +210,7 @@ void (*vlog_startup_routines[])() = {
 };
 
 #else
+
 double sc_time_stamp () {
     return main_time;
 }
diff --git a/test_regress/t/t_vpi_memory.pl b/test_regress/t/t_vpi_memory.pl
index 5a1982e..ee515df 100755
--- a/test_regress/t/t_vpi_memory.pl
+++ b/test_regress/t/t_vpi_memory.pl
@@ -11,7 +11,7 @@ compile (
     make_top_shell => 0,
     make_main => 0,
     make_pli => 1,
-    iv_flags2 => ["-g2005-sv -D USE_VPI_NOT_DPI -s t -o obj_dir/iv_t_vpi_memory/simiv"],
+    iv_flags2 => ["-g2005-sv -D USE_VPI_NOT_DPI"],
     v_flags2 => ["+define+USE_VPI_NOT_DPI"],
     verilator_flags2 => ["-CFLAGS '-DVL_DEBUG -ggdb' --exe --no-l2name $Self->{t_dir}/t_vpi_memory.cpp"],
     );
diff --git a/test_regress/t/t_vpi_memory.v b/test_regress/t/t_vpi_memory.v
index 1ae92a6..ea16810 100644
--- a/test_regress/t/t_vpi_memory.v
+++ b/test_regress/t/t_vpi_memory.v
@@ -38,8 +38,19 @@ extern "C" int mon_check();
 `ifndef USE_VPI_NOT_DPI
      status = mon_check();
 `endif
+      if (status!=0) begin
+	 $write("%%Error: t_vpi_var.cpp:%0d: C Test failed\n", status);
+	 $stop;
+      end
       for (i = 16; i > 0; i--)
-	if (mem0[i] !== i) $write("%%Error: %d : GOT = %d  EXP = %d\n", i, mem0[i], i);
+	if (mem0[i] !== i) begin
+          $write("%%Error: %d : GOT = %d  EXP = %d\n", i, mem0[i], i);
+	  status = 1;
+        end
+      if (status!=0) begin
+	 $write("%%Error: t_vpi_var.cpp:%0d: C Test failed\n", status);
+	 $stop;
+      end
       $write("*-* All Finished *-*\n");
       $finish;
    end
diff --git a/test_regress/t/t_vpi_unimpl.cpp b/test_regress/t/t_vpi_unimpl.cpp
index 51f52c4..4fb3965 100644
--- a/test_regress/t/t_vpi_unimpl.cpp
+++ b/test_regress/t/t_vpi_unimpl.cpp
@@ -25,6 +25,8 @@
 
 #include <iostream>
 
+#include "TestVpi.h"
+
 // __FILE__ is too long
 #define FILENM "t_vpi_unimpl.cpp"
 
@@ -35,20 +37,6 @@ unsigned int callback_count = false;
 
 //======================================================================
 
-
-class VlVpiHandle {
-    /// For testing, etc, wrap vpiHandle in an auto-releasing class
-    vpiHandle m_handle;
-public:
-    VlVpiHandle() : m_handle(NULL) { }
-    VlVpiHandle(vpiHandle h) : m_handle(h) { }
-    ~VlVpiHandle() { if (m_handle) { vpi_release_handle(m_handle); m_handle=NULL; } }
-    operator vpiHandle () const { return m_handle; }
-    inline VlVpiHandle& operator= (vpiHandle h) { m_handle = h; return *this; }
-};
-
-//======================================================================
-
 #define CHECK_RESULT_VH(got, exp) \
     if ((got) != (exp)) { \
 	printf("%%Error: %s:%d: GOT = %p   EXP = %p\n", \
@@ -88,7 +76,7 @@ public:
     CHECK_RESULT_CSTR(got+strspn(got, " "), exp)
 
 int _mon_check_unimpl(p_cb_data cb_data) {
-    static VlVpiHandle cb, clk_h;
+    static TestVpiHandle cb, clk_h;
     if (cb_data) {
 	// this is the callback
         s_vpi_error_info info;
diff --git a/test_regress/t/t_vpi_var.cpp b/test_regress/t/t_vpi_var.cpp
index 893f918..ce89966 100644
--- a/test_regress/t/t_vpi_var.cpp
+++ b/test_regress/t/t_vpi_var.cpp
@@ -13,6 +13,12 @@
 //
 //*************************************************************************
 
+#ifdef IS_VPI
+
+#include "vpi_user.h"
+
+#else
+
 #include "Vt_vpi_var.h"
 #include "verilated.h"
 #include "svdpi.h"
@@ -23,7 +29,16 @@
 #include "verilated_vpi.cpp"
 #include "verilated_vcd_c.h"
 
+#endif
+
+#include <cstdlib>
+#include <cstdio>
+#include <cstring>
 #include <iostream>
+using namespace std;
+
+#include "TestSimulator.h"
+#include "TestVpi.h"
 
 // __FILE__ is too long
 #define FILENM "t_vpi_var.cpp"
@@ -39,20 +54,6 @@ unsigned int callback_count_strs_max = 500;
 
 //======================================================================
 
-
-class VlVpiHandle {
-    /// For testing, etc, wrap vpiHandle in an auto-releasing class
-    vpiHandle m_handle;
-public:
-    VlVpiHandle() : m_handle(NULL) { }
-    VlVpiHandle(vpiHandle h) : m_handle(h) { }
-    ~VlVpiHandle() { if (m_handle) { vpi_release_handle(m_handle); m_handle=NULL; } }
-    operator vpiHandle () const { return m_handle; }
-    inline VlVpiHandle& operator= (vpiHandle h) { m_handle = h; return *this; }
-};
-
-//======================================================================
-
 #define CHECK_RESULT_VH(got, exp) \
     if ((got) != (exp)) { \
 	printf("%%Error: %s:%d: GOT = %p   EXP = %p\n", \
@@ -112,7 +113,8 @@ int _mon_check_mcd() {
     CHECK_RESULT(status, 0);
 
     status = vpi_mcd_close(mcd);
-    CHECK_RESULT(status, 0);
+    // Icarus says 'error' on ones we're not using, so check only used ones return 0.
+    CHECK_RESULT(status & mcd, 0);
 
     status = vpi_flush();
     CHECK_RESULT(status, 0);
@@ -120,12 +122,18 @@ int _mon_check_mcd() {
     return 0;
 }
 
+int _mon_check_callbacks_error(p_cb_data cb_data) {
+    vpi_printf((PLI_BYTE8*)"%%Error: callback should not be executed\n");
+    return 1;
+}
+
 int _mon_check_callbacks() {
     t_cb_data cb_data;
     cb_data.reason = cbEndOfSimulation;
-    cb_data.cb_rtn = NULL;
+    cb_data.cb_rtn = _mon_check_callbacks_error;
     cb_data.user_data = 0;
     cb_data.value = NULL;
+    cb_data.time = NULL;
 
     vpiHandle vh = vpi_register_cb(&cb_data);
     CHECK_RESULT_NZ(vh);
@@ -137,13 +145,20 @@ int _mon_check_callbacks() {
 }
 
 int _value_callback(p_cb_data cb_data) {
-    CHECK_RESULT(cb_data->value->value.integer+10, main_time);
+
+    if (TestSimulator::is_verilator()) {
+      // this check only makes sense in Verilator
+      CHECK_RESULT(cb_data->value->value.integer+10, main_time);
+    }
     callback_count++;
     return 0;
 }
 
 int _value_callback_half(p_cb_data cb_data) {
-    CHECK_RESULT(cb_data->value->value.integer*2+10, main_time);
+    if (TestSimulator::is_verilator()) {
+      // this check only makes sense in Verilator
+      CHECK_RESULT(cb_data->value->value.integer*2+10, main_time);
+    }
     callback_count_half++;
     return 0;
 }
@@ -158,7 +173,7 @@ int _value_callback_quad(p_cb_data cb_data) {
 }
 
 int _mon_check_value_callbacks() {
-    vpiHandle vh1 = vpi_handle_by_name((PLI_BYTE8*)"t.count", NULL);
+    vpiHandle vh1 = VPI_HANDLE("count");
     CHECK_RESULT_NZ(vh1);
 
     s_vpi_value v;
@@ -170,11 +185,12 @@ int _mon_check_value_callbacks() {
     cb_data.cb_rtn = _value_callback;
     cb_data.obj = vh1;
     cb_data.value = &v;
+    cb_data.time = NULL;
 
     vpiHandle vh = vpi_register_cb(&cb_data);
     CHECK_RESULT_NZ(vh);
 
-    vh1 = vpi_handle_by_name((PLI_BYTE8*)"t.half_count", NULL);
+    vh1 = VPI_HANDLE("half_count");
     CHECK_RESULT_NZ(vh1);
 
     cb_data.obj = vh1;
@@ -183,7 +199,7 @@ int _mon_check_value_callbacks() {
     vh = vpi_register_cb(&cb_data);
     CHECK_RESULT_NZ(vh);
 
-    vh1 = vpi_handle_by_name((PLI_BYTE8*)"t.quads", NULL);
+    vh1 = VPI_HANDLE("quads");
     CHECK_RESULT_NZ(vh1);
 
     v.format = vpiVectorVal;
@@ -205,10 +221,10 @@ int _mon_check_value_callbacks() {
 }
 
 int _mon_check_var() {
-    VlVpiHandle vh1 = vpi_handle_by_name((PLI_BYTE8*)"t.onebit", NULL);
+    TestVpiHandle vh1 = VPI_HANDLE("onebit");
     CHECK_RESULT_NZ(vh1);
 
-    VlVpiHandle vh2 = vpi_handle_by_name((PLI_BYTE8*)"t", NULL);
+    TestVpiHandle vh2 = vpi_handle_by_name((PLI_BYTE8*)TestSimulator::top(), NULL);
     CHECK_RESULT_NZ(vh2);
 
     // scope attributes
@@ -216,55 +232,57 @@ int _mon_check_var() {
     p = vpi_get_str(vpiName, vh2);
     CHECK_RESULT_CSTR(p, "t");
     p = vpi_get_str(vpiFullName, vh2);
-    CHECK_RESULT_CSTR(p, "t");
+    CHECK_RESULT_CSTR(p, TestSimulator::top());
 
-    VlVpiHandle vh3 = vpi_handle_by_name((PLI_BYTE8*)"onebit", vh2);
+    TestVpiHandle vh3 = vpi_handle_by_name((PLI_BYTE8*)"onebit", vh2);
     CHECK_RESULT_NZ(vh3);
 
     // onebit attributes
     PLI_INT32 d;
     d = vpi_get(vpiType, vh3);
     CHECK_RESULT(d, vpiReg);
-    d = vpi_get(vpiDirection, vh3);
-    CHECK_RESULT(d, vpiNoDirection);
-    d = vpi_get(vpiVector, vh3);
-    CHECK_RESULT(d, 0);
+    if (TestSimulator::has_get_scalar()) {
+      d = vpi_get(vpiVector, vh3);
+      CHECK_RESULT(d, 0);
+    }
 
     p = vpi_get_str(vpiName, vh3);
     CHECK_RESULT_CSTR(p, "onebit");
     p = vpi_get_str(vpiFullName, vh3);
-    CHECK_RESULT_CSTR(p, "t.onebit");
+    CHECK_RESULT_CSTR(p, TestSimulator::rooted("onebit"));
 
     // array attributes
-    VlVpiHandle vh4 = vpi_handle_by_name((PLI_BYTE8*)"t.fourthreetwoone", NULL);
+    TestVpiHandle vh4 = VPI_HANDLE("fourthreetwoone");
     CHECK_RESULT_NZ(vh4);
-    d = vpi_get(vpiVector, vh4);
-    CHECK_RESULT(d, 1);
+    if (TestSimulator::has_get_scalar()) {
+      d = vpi_get(vpiVector, vh4);
+      CHECK_RESULT(d, 1);
+    }
 
     t_vpi_value tmpValue;
     tmpValue.format = vpiIntVal;
     {
-	VlVpiHandle vh10 = vpi_handle(vpiLeftRange, vh4);
+	TestVpiHandle vh10 = vpi_handle(vpiLeftRange, vh4);
 	CHECK_RESULT_NZ(vh10);
 	vpi_get_value(vh10, &tmpValue);
 	CHECK_RESULT(tmpValue.value.integer,4);
     }
     {
-	VlVpiHandle vh10 = vpi_handle(vpiRightRange, vh4);
+	TestVpiHandle vh10 = vpi_handle(vpiRightRange, vh4);
 	CHECK_RESULT_NZ(vh10);
 	vpi_get_value(vh10, &tmpValue);
 	CHECK_RESULT(tmpValue.value.integer,3);
     }
     {
-	VlVpiHandle vh10 = vpi_iterate(vpiMemoryWord, vh4);
+	TestVpiHandle vh10 = vpi_iterate(vpiMemoryWord, vh4);
 	CHECK_RESULT_NZ(vh10);
-	VlVpiHandle vh11 = vpi_scan(vh10);
+	TestVpiHandle vh11 = vpi_scan(vh10);
 	CHECK_RESULT_NZ(vh11);
-	VlVpiHandle vh12 = vpi_handle(vpiLeftRange, vh11);
+	TestVpiHandle vh12 = vpi_handle(vpiLeftRange, vh11);
 	CHECK_RESULT_NZ(vh12);
 	vpi_get_value(vh12, &tmpValue);
 	CHECK_RESULT(tmpValue.value.integer,2);
-	VlVpiHandle vh13 = vpi_handle(vpiRightRange, vh11);
+	TestVpiHandle vh13 = vpi_handle(vpiRightRange, vh11);
 	CHECK_RESULT_NZ(vh13);
 	vpi_get_value(vh13, &tmpValue);
 	CHECK_RESULT(tmpValue.value.integer,1);
@@ -276,30 +294,30 @@ int _mon_check_var() {
 int _mon_check_varlist() {
     const char* p;
 
-    VlVpiHandle vh2 = vpi_handle_by_name((PLI_BYTE8*)"t.sub", NULL);
+    TestVpiHandle vh2 = VPI_HANDLE("sub");
     CHECK_RESULT_NZ(vh2);
 
-    VlVpiHandle vh10 = vpi_iterate(vpiReg, vh2);
-    CHECK_RESULT_NZ(vh10);
+    TestVpiHandle vh10 = vpi_iterate(vpiReg, vh2);
+    CHECK_RESULT_NZ(vh10.nofree());
 
-    VlVpiHandle vh11 = vpi_scan(vh10);
+    TestVpiHandle vh11 = vpi_scan(vh10);
     CHECK_RESULT_NZ(vh11);
     p = vpi_get_str(vpiFullName, vh11);
-    CHECK_RESULT_CSTR(p, "t.sub.subsig1");
+    CHECK_RESULT_CSTR(p, TestSimulator::rooted("sub.subsig1"));
 
-    VlVpiHandle vh12 = vpi_scan(vh10);
+    TestVpiHandle vh12 = vpi_scan(vh10);
     CHECK_RESULT_NZ(vh12);
     p = vpi_get_str(vpiFullName, vh12);
-    CHECK_RESULT_CSTR(p, "t.sub.subsig2");
+    CHECK_RESULT_CSTR(p, TestSimulator::rooted("sub.subsig2"));
 
-    VlVpiHandle vh13 = vpi_scan(vh10);
+    TestVpiHandle vh13 = vpi_scan(vh10);
     CHECK_RESULT(vh13,0);
 
     return 0;
 }
 
 int _mon_check_getput() {
-    VlVpiHandle vh2 = vpi_handle_by_name((PLI_BYTE8*)"t.onebit", NULL);
+    TestVpiHandle vh2 = VPI_HANDLE("onebit");
     CHECK_RESULT_NZ(vh2);
 
     s_vpi_value v;
@@ -321,7 +339,7 @@ int _mon_check_getput() {
 }
 
 int _mon_check_quad() {
-    VlVpiHandle vh2 = vpi_handle_by_name((PLI_BYTE8*)"t.quads", NULL);
+    TestVpiHandle vh2 = VPI_HANDLE("quads");
     CHECK_RESULT_NZ(vh2);
 
     s_vpi_value v;
@@ -332,9 +350,9 @@ int _mon_check_quad() {
     t.high = 0;
     t.low = 0;
 
-    VlVpiHandle vhidx2 = vpi_handle_by_index(vh2, 2);
+    TestVpiHandle vhidx2 = vpi_handle_by_index(vh2, 2);
     CHECK_RESULT_NZ(vhidx2);
-    VlVpiHandle vhidx3 = vpi_handle_by_index(vh2, 3);
+    TestVpiHandle vhidx3 = vpi_handle_by_index(vh2, 3);
     CHECK_RESULT_NZ(vhidx2);
 
     v.format = vpiVectorVal;
@@ -366,15 +384,15 @@ int _mon_check_string() {
         const char *initial;
         const char *value;
     } text_test_obs[] = {
-        {"t.text_byte", "B", "xxA"}, // x's dropped
-        {"t.text_half", "Hf", "xxT2"}, // x's dropped
-        {"t.text_word", "Word", "Tree"},
-        {"t.text_long", "Long64b", "44Four44"},
-        {"t.text"     , "Verilog Test module", "lorem ipsum"},
+        {"text_byte", "B", "xxA"}, // x's dropped
+        {"text_half", "Hf", "xxT2"}, // x's dropped
+        {"text_word", "Word", "Tree"},
+        {"text_long", "Long64b", "44Four44"},
+        {"text"     , "Verilog Test module", "lorem ipsum"},
     };
 
     for (int i=0; i<5; i++) {
-      VlVpiHandle vh1 = vpi_handle_by_name((PLI_BYTE8*)text_test_obs[i].name, NULL);
+      TestVpiHandle vh1 = VPI_HANDLE(text_test_obs[i].name);
       CHECK_RESULT_NZ(vh1);
 
       s_vpi_value v;
@@ -397,9 +415,9 @@ int _mon_check_string() {
 }
 
 int _mon_check_putget_str(p_cb_data cb_data) {
-    static VlVpiHandle cb;
+    static TestVpiHandle cb;
     static struct {
-	VlVpiHandle scope, sig, rfr, check, verbose;
+	TestVpiHandle scope, sig, rfr, check, verbose;
         char str[128+1];          // char per bit plus null terminator
         int type;                 // value type in .str
         union {
@@ -492,7 +510,7 @@ int _mon_check_putget_str(p_cb_data cb_data) {
 	// setup and install
         for (int i=1; i<=128; i++) {
             char buf[32];
-            snprintf(buf, sizeof(buf), "t.arr[%d].arr", i);
+            snprintf(buf, sizeof(buf), TestSimulator::rooted("arr[%d].arr"), i);
 	    CHECK_RESULT_NZ(data[i].scope   = vpi_handle_by_name((PLI_BYTE8*)buf, NULL));
 	    CHECK_RESULT_NZ(data[i].sig     = vpi_handle_by_name((PLI_BYTE8*)"sig", data[i].scope));
 	    CHECK_RESULT_NZ(data[i].rfr     = vpi_handle_by_name((PLI_BYTE8*)"rfr", data[i].scope));
@@ -502,12 +520,13 @@ int _mon_check_putget_str(p_cb_data cb_data) {
 
 	static t_cb_data cb_data;
 	static s_vpi_value v;
-        static VlVpiHandle count_h = vpi_handle_by_name((PLI_BYTE8*)"t.count", NULL);
+        static TestVpiHandle count_h = VPI_HANDLE("count");
 
         cb_data.reason = cbValueChange;
         cb_data.cb_rtn = _mon_check_putget_str; // this function
         cb_data.obj = count_h;
         cb_data.value = &v;
+        cb_data.time = NULL;
         v.format = vpiIntVal;
 
         cb = vpi_register_cb(&cb_data);
@@ -524,12 +543,15 @@ int _mon_check_vlog_info() {
     CHECK_RESULT_CSTR(vlog_info.argv[1], "+PLUS");
     CHECK_RESULT_CSTR(vlog_info.argv[2], "+INT=1234");
     CHECK_RESULT_CSTR(vlog_info.argv[3], "+STRSTR");
-    CHECK_RESULT_CSTR(vlog_info.product, "Verilator");
-    CHECK_RESULT(strlen(vlog_info.version) > 0, 1);
-
+    if (TestSimulator::is_verilator()) {
+      CHECK_RESULT_CSTR(vlog_info.product, "Verilator");
+      CHECK_RESULT(strlen(vlog_info.version) > 0, 1);
+    }
     return 0;
 }
 
+#ifndef IS_VPI
+
 #define CHECK_ENUM_STR(fn, enum) \
     do { \
         const char* strVal = VerilatedVpiError::fn(enum); \
@@ -567,6 +589,8 @@ int _mon_check_vl_str() {
     return 0;
 }
 
+#endif
+
 int mon_check() {
     // Callback from initial block in monitor
     if (int status = _mon_check_mcd()) return status;
@@ -579,12 +603,46 @@ int mon_check() {
     if (int status = _mon_check_string()) return status;
     if (int status = _mon_check_putget_str(NULL)) return status;
     if (int status = _mon_check_vlog_info()) return status;
+#ifndef IS_VPI
     if (int status = _mon_check_vl_str()) return status;
+#endif
     return 0; // Ok
 }
 
 //======================================================================
 
+#ifdef IS_VPI
+
+static int mon_check_vpi() {
+  vpiHandle href = vpi_handle(vpiSysTfCall, 0);
+  s_vpi_value vpi_value;
+
+  vpi_value.format = vpiIntVal;
+  vpi_value.value.integer = mon_check();
+  vpi_put_value(href, &vpi_value, NULL, vpiNoDelay);
+
+  return 0;
+}
+
+static s_vpi_systf_data vpi_systf_data[] = {
+  {vpiSysFunc, vpiIntFunc, (PLI_BYTE8*)"$mon_check", (PLI_INT32(*)(PLI_BYTE8*))mon_check_vpi, 0, 0, 0},
+  0
+};
+
+// cver entry
+void vpi_compat_bootstrap(void) {
+  p_vpi_systf_data systf_data_p;
+  systf_data_p = &(vpi_systf_data[0]);
+  while (systf_data_p->type != 0) vpi_register_systf(systf_data_p++);
+}
+
+// icarus entry
+void (*vlog_startup_routines[])() = {
+      vpi_compat_bootstrap,
+      0
+};
+
+#else
 
 double sc_time_stamp () {
     return main_time;
@@ -640,3 +698,5 @@ int main(int argc, char **argv, char **env) {
     delete topp; topp=NULL;
     exit(0L);
 }
+
+#endif
diff --git a/test_regress/t/t_vpi_var.pl b/test_regress/t/t_vpi_var.pl
index bb1c70f..5061134 100755
--- a/test_regress/t/t_vpi_var.pl
+++ b/test_regress/t/t_vpi_var.pl
@@ -10,10 +10,15 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 compile (
 	 make_top_shell => 0,
 	 make_main => 0,
+	 make_pli => 1,
+	 sim_time => 2100,
+	 iv_flags2 => ["-g2005-sv -D USE_VPI_NOT_DPI -DWAVES"],
+	 v_flags2 => ["+define+USE_VPI_NOT_DPI"],
 	 verilator_flags2 => ["-CFLAGS '-DVL_DEBUG -ggdb' --exe --no-l2name $Self->{t_dir}/t_vpi_var.cpp"],
 	 );
 
 execute (
+	 iv_pli => 1,
 	 check_finished=>1,
          all_run_flags => ['+PLUS +INT=1234 +STRSTR']
      );
diff --git a/test_regress/t/t_vpi_var.v b/test_regress/t/t_vpi_var.v
index 26515d7..624f3e0 100644
--- a/test_regress/t/t_vpi_var.v
+++ b/test_regress/t/t_vpi_var.v
@@ -5,7 +5,7 @@
 // Lesser General Public License Version 3 or the Perl Artistic License
 // Version 2.0.
 
-`ifdef VERILATOR
+`ifdef USE_VPI_NOT_DPI
 //We call it via $c so we can verify DPI isn't required - see bug572
 `else
 import "DPI-C" context function integer mon_check();
@@ -45,7 +45,9 @@ extern "C" int mon_check();
 
    // Test loop
    initial begin
+      count = 0;
       onebit = 1'b0;
+      fourthreetwoone[3] = 0; // stop icarus optimizing away
       text_byte = "B";
       text_half = "Hf";
       text_word = "Word";
@@ -53,13 +55,18 @@ extern "C" int mon_check();
       text = "Verilog Test module";
 `ifdef VERILATOR
       status = $c32("mon_check()");
-`else
-      status = mon_check();
+`endif
+`ifdef iverilog
+     status = $mon_check();
+`endif
+`ifndef USE_VPI_NOT_DPI
+     status = mon_check();
 `endif
       if (status!=0) begin
 	 $write("%%Error: t_vpi_var.cpp:%0d: C Test failed\n", status);
 	 $stop;
       end
+      $write("%%Info: Checking results\n");
       if (onebit != 1'b1) $stop;
       if (quads[2] != 62'h12819213_abd31a1c) $stop;
       if (quads[3] != 62'h1c77bb9b_3784ea09) $stop;
@@ -83,16 +90,20 @@ extern "C" int mon_check();
 
    genvar i;
    generate
-   for (i=1;i<=128;i++) begin : arr
+   for (i=1; i<=128; i=i+1) begin : arr
      arr #(.LENGTH(i)) arr();
    end endgenerate
 
-endmodule
+endmodule : t
 
 module sub;
    reg subsig1 /*verilator public_flat_rd*/;
    reg subsig2 /*verilator public_flat_rd*/;
-endmodule
+`ifdef iverilog
+   // stop icarus optimizing signals away
+   wire redundant = subsig1 | subsig2;
+`endif
+endmodule : sub
 
 module arr;
 
@@ -104,6 +115,11 @@ module arr;
    reg 		  check /*verilator public_flat_rw*/;
    reg          verbose /*verilator public_flat_rw*/;
 
+   initial begin
+      sig = {LENGTH{1'b0}};
+      rfr = {LENGTH{1'b0}};
+   end
+
    always @(posedge check) begin
      if (verbose) $display("%m : %x %x", sig, rfr);
      if (check && sig != rfr) $stop;
diff --git a/verilator.1 b/verilator.1
index 8a93de9..c5511e3 100644
--- a/verilator.1
+++ b/verilator.1
@@ -124,7 +124,7 @@
 .\" ========================================================================
 .\"
 .IX Title "VERILATOR 1"
-.TH VERILATOR 1 "2013-09-30" "perl v5.14.2" "User Contributed Perl Documentation"
+.TH VERILATOR 1 "2013-11-26" "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
@@ -389,6 +389,11 @@ interest in adding more traditional \s-1CDC\s0 checks, please contact the author
 .IX Item "--compiler compiler-name"
 Enables tunings and work-arounds for the specified \*(C+ compiler.
 .RS 4
+.IP "clang" 4
+.IX Item "clang"
+Tune for clang.  This may reduce execution speed as it enables several
+workarounds to avoid silly hardcoded limits in clang.  This includes
+breaking deep structures as for msvc as described below.
 .IP "gcc" 4
 .IX Item "gcc"
 Tune for Gnu \*(C+, although generated code should work on almost any
@@ -2999,6 +3004,12 @@ section for more details.
 .Sp
 Ignoring this warning will only slow simulations, it will simulate
 correctly.
+.IP "\s-1UNPACKED\s0" 4
+.IX Item "UNPACKED"
+Warns that unpacked structs and unions are not supported.
+.Sp
+Ignoring this warning will make Verilator treat the structure as packed,
+which may make Verilator simulations differ from other simulators.
 .IP "\s-1UNSIGNED\s0" 4
 .IX Item "UNSIGNED"
 Warns that you are comparing a unsigned value in a way that implies it is
diff --git a/verilator.html b/verilator.html
index bad675d..b25e0f2 100644
--- a/verilator.html
+++ b/verilator.html
@@ -381,6 +381,13 @@ interest in adding more traditional CDC checks, please contact the authors.</p>
 <dd>
 <p>Enables tunings and work-arounds for the specified C++ compiler.</p>
 <dl>
+<dt><strong><a name="clang" class="item">clang</a></strong></dt>
+
+<dd>
+<p>Tune for clang.  This may reduce execution speed as it enables several
+workarounds to avoid silly hardcoded limits in clang.  This includes
+breaking deep structures as for msvc as described below.</p>
+</dd>
 <dt><strong><a name="gcc" class="item">gcc</a></strong></dt>
 
 <dd>
@@ -3145,6 +3152,13 @@ section for more details.</p>
 <p>Ignoring this warning will only slow simulations, it will simulate
 correctly.</p>
 </dd>
+<dt><strong><a name="unpacked" class="item">UNPACKED</a></strong></dt>
+
+<dd>
+<p>Warns that unpacked structs and unions are not supported.</p>
+<p>Ignoring this warning will make Verilator treat the structure as packed,
+which may make Verilator simulations differ from other simulators.</p>
+</dd>
 <dt><strong><a name="unsigned" class="item">UNSIGNED</a></strong></dt>
 
 <dd>
diff --git a/verilator.pdf b/verilator.pdf
index eb1d29e..3c25a4a 100644
Binary files a/verilator.pdf and b/verilator.pdf differ
diff --git a/verilator.txt b/verilator.txt
index 6f9d8ec..e59cb25 100644
--- a/verilator.txt
+++ b/verilator.txt
@@ -250,6 +250,12 @@ ARGUMENTS
     --compiler *compiler-name*
         Enables tunings and work-arounds for the specified C++ compiler.
 
+        clang
+            Tune for clang. This may reduce execution speed as it enables
+            several workarounds to avoid silly hardcoded limits in clang.
+            This includes breaking deep structures as for msvc as described
+            below.
+
         gcc Tune for Gnu C++, although generated code should work on almost
             any compliant C++ compiler. Currently the default.
 
@@ -2802,6 +2808,13 @@ ERRORS AND WARNINGS
         Ignoring this warning will only slow simulations, it will simulate
         correctly.
 
+    UNPACKED
+        Warns that unpacked structs and unions are not supported.
+
+        Ignoring this warning will make Verilator treat the structure as
+        packed, which may make Verilator simulations differ from other
+        simulators.
+
     UNSIGNED
         Warns that you are comparing a unsigned value in a way that implies
         it is signed, for example "X < 0" will always be true when X is

-- 
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