diff --git a/include/verilated_funcs.h b/include/verilated_funcs.h index 673cf822a..4cf04ff20 100644 --- a/include/verilated_funcs.h +++ b/include/verilated_funcs.h @@ -284,6 +284,8 @@ inline uint64_t vl_time_stamp64() VL_MT_SAFE { # endif #endif +// clang-format on + uint64_t VerilatedContext::time() const VL_MT_SAFE { // When using non-default context, fastest path is return time if (VL_LIKELY(m_s.m_time)) return m_s.m_time; @@ -311,25 +313,6 @@ double vl_time_multiplier(int scale) VL_PURE; // Return power of 10. e.g. returns 100 if n==2 uint64_t vl_time_pow10(int n) VL_PURE; -#ifdef VL_DEBUG -/// Evaluate statement if VL_DEBUG defined -# define VL_DEBUG_IFDEF(stmt) \ - do { \ - stmt \ - } while (false) -/// Evaluate statement if VL_DEBUG defined and Verilated::debug() enabled -# define VL_DEBUG_IF(stmt) \ - do { \ - if (VL_UNLIKELY(Verilated::debug())) {stmt} \ - } while (false) -#else -// We intentionally do not compile the stmt to improve compile speed -# define VL_DEBUG_IFDEF(stmt) do {} while (false) -# define VL_DEBUG_IF(stmt) do {} while (false) -#endif - -// clang-format on - //========================================================================= // Functional macros/routines // These all take the form diff --git a/include/verilated_types.h b/include/verilated_types.h index 512b1c9c3..5e030bc20 100644 --- a/include/verilated_types.h +++ b/include/verilated_types.h @@ -39,6 +39,28 @@ #include #include +//========================================================================= +// Debug functions + +#ifdef VL_DEBUG +/// Evaluate statement if VL_DEBUG defined +#define VL_DEBUG_IFDEF(stmt) \ + do { stmt } while (false) +/// Evaluate statement if VL_DEBUG defined and Verilated::debug() enabled +#define VL_DEBUG_IF(stmt) \ + do { \ + if (VL_UNLIKELY(Verilated::debug())) { stmt } \ + } while (false) +#else +// We intentionally do not compile the stmt to improve compile speed +#define VL_DEBUG_IFDEF(stmt) \ + do { \ + } while (false) +#define VL_DEBUG_IF(stmt) \ + do { \ + } while (false) +#endif + //=================================================================== // String formatters (required by below containers) @@ -1534,12 +1556,15 @@ class VlClass VL_NOT_FINAL : public VlDeletable { friend class VlClassRef; // Needed for access to the ref counter and deleter // MEMBERS - std::atomic m_counter{0}; // Reference count for this object + std::atomic m_counter{1}; // Reference count for this object VlDeleter* m_deleterp = nullptr; // The deleter that will delete this object // METHODS // Atomically increments the reference counter - void refCountInc() VL_MT_SAFE { ++m_counter; } + void refCountInc() VL_MT_SAFE { + VL_DEBUG_IFDEF(assert(m_counter);); // If zero, we might have already deleted + ++m_counter; + } // Atomically decrements the reference counter. Assuming VlClassRef semantics are sound, it // should never get called at m_counter == 0. void refCountDec() VL_MT_SAFE { @@ -1548,8 +1573,8 @@ class VlClass VL_NOT_FINAL : public VlDeletable { public: // CONSTRUCTORS - VlClass() { refCountInc(); } - VlClass(const VlClass& copied) { refCountInc(); } + VlClass() {} + VlClass(const VlClass& copied) {} ~VlClass() override = default; }; @@ -1629,18 +1654,21 @@ public: // METHODS // Copy and move assignments VlClassRef& operator=(const VlClassRef& copied) { + if (m_objp == copied.m_objp) return *this; refCountDec(); m_objp = copied.m_objp; refCountInc(); return *this; } VlClassRef& operator=(VlClassRef&& moved) { + if (m_objp == moved.m_objp) return *this; refCountDec(); m_objp = vlstd::exchange(moved.m_objp, nullptr); return *this; } template VlClassRef& operator=(const VlClassRef& copied) { + if (m_objp == copied.m_objp) return *this; refCountDec(); m_objp = copied.m_objp; refCountInc(); @@ -1648,6 +1676,7 @@ public: } template VlClassRef& operator=(VlClassRef&& moved) { + if (m_objp == moved.m_objp) return *this; refCountDec(); m_objp = vlstd::exchange(moved.m_objp, nullptr); return *this;