diff --git a/include/verilated.cpp b/include/verilated.cpp index b1f0ea992..c8582ab77 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -2257,21 +2257,12 @@ void Verilated::flushCb(VerilatedVoidCb cb) VL_MT_SAFE { // When running internal code coverage (gcc --coverage, as opposed to // verilator --coverage), dump coverage data to properly cover failing // tests. -#ifdef VL_GCOV -extern "C" { -void __gcov_flush(); // gcc sources gcc/gcov-io.h has the prototype -} -void vl_gcov_flush() { __gcov_flush(); } -#else -void vl_gcov_flush() {} -#endif - void Verilated::flushCall() VL_MT_SAFE { const VerilatedLockGuard lock(m_mutex); if (s_flushCb) (*s_flushCb)(); fflush(stderr); fflush(stdout); - vl_gcov_flush(); + VL_GCOV_FLUSH(); } const char* Verilated::productName() VL_PURE { return VERILATOR_PRODUCT; } diff --git a/include/verilatedos.h b/include/verilatedos.h index e3afdb903..357ee8654 100644 --- a/include/verilatedos.h +++ b/include/verilatedos.h @@ -152,15 +152,15 @@ #if defined(VL_CPPCHECK) || defined(__clang_analyzer__) || __cplusplus < 201103L # define VL_DANGLING(var) #else -///< After e.g. delete, set variable to NULL to indicate must not use later +/// After e.g. delete, set variable to NULL to indicate must not use later # define VL_DANGLING(var) \ do { \ *const_cast(reinterpret_cast(&var)) = NULL; \ } while (false) #endif -///< Perform an e.g. delete, then set variable to NULL to indicate must not use later. -///< Unlike VL_DO_CLEAR the setting of the variable is only for debug reasons. +/// Perform an e.g. delete, then set variable to NULL to indicate must not use later. +/// Unlike VL_DO_CLEAR the setting of the variable is only for debug reasons. #define VL_DO_DANGLING(stmt, var) \ do { \ do { \ @@ -169,7 +169,7 @@ VL_DANGLING(var); \ } while (false) -///< Perform an e.g. delete, then set variable to NULL as a requirement +/// Perform an e.g. delete, then set variable to NULL as a requirement #define VL_DO_CLEAR(stmt, stmt2) \ do { \ do { \ @@ -217,6 +217,20 @@ # define VL_INLINE_OPT ///< "inline" if compiling all objects in single compiler run #endif +//========================================================================= +// Internal coverage + +#ifdef VL_GCOV +extern "C" { +void __gcov_flush(); // gcc sources gcc/gcov-io.h has the prototype +} +/// Flush internal code coverage data before e.g. abort() +# define VL_GCOV_FLUSH() \ + __gcov_flush() +#else +# define VL_GCOV_FLUSH() +#endif + //========================================================================= // Warning disabled diff --git a/src/V3Error.cpp b/src/V3Error.cpp index 14be86818..8c617d294 100644 --- a/src/V3Error.cpp +++ b/src/V3Error.cpp @@ -156,15 +156,20 @@ string V3Error::msgPrefix() { //====================================================================== // Abort/exit -void V3Error::vlAbort() { +void V3Error::vlAbortOrExit() { if (V3Error::debugDefault()) { std::cerr << msgPrefix() << "Aborting since under --debug" << endl; - abort(); + V3Error::vlAbort(); } else { exit(1); } } +void V3Error::vlAbort() { + VL_GCOV_FLUSH(); + abort(); +} + //====================================================================== // Global Functions @@ -272,7 +277,7 @@ void V3Error::v3errorEnd(std::ostringstream& sstr, const string& locationStr) { #endif } - vlAbort(); + vlAbortOrExit(); } else if (isError(s_errorCode, s_errorSuppressed)) { // We don't dump tree on any error because a Visitor may be in middle of // a tree cleanup and cause a false broken problem. diff --git a/src/V3Error.h b/src/V3Error.h index d31028058..f86d5888f 100644 --- a/src/V3Error.h +++ b/src/V3Error.h @@ -238,7 +238,7 @@ private: V3Error() { std::cerr << ("Static class"); - abort(); + V3Error::vlAbort(); } public: @@ -287,6 +287,7 @@ public: s_errorSuppressed = false; } static std::ostringstream& v3errorStr() { return s_errorStr; } + static void vlAbortOrExit(); static void vlAbort(); // static, but often overridden in classes. static void v3errorEnd(std::ostringstream& sstr, const string& locationStr = ""); @@ -362,7 +363,7 @@ inline void v3errorEndFatal(std::ostringstream& sstr) { if (VL_UNCOVERABLE(!(condition))) { \ std::cerr << "Internal Error: " << __FILE__ << ":" << std::dec << __LINE__ << ":" \ << (stmsg) << std::endl; \ - abort(); \ + V3Error::vlAbort(); \ } \ } while (false) // Check self test values for expected value. Safe from side-effects. diff --git a/src/V3Options.cpp b/src/V3Options.cpp index 554168b81..ba8827c96 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -842,7 +842,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char else if ( onoff (sw, "-coverage-underscore", flag/*ref*/)){ m_coverageUnderscore = flag; } else if ( onoff (sw, "-coverage-user", flag/*ref*/)){ m_coverageUser = flag; } else if ( onoff (sw, "-covsp", flag/*ref*/)) { } // TBD - else if (!strcmp(sw, "-debug-abort")) { abort(); } // Undocumented, see also --debug-sigsegv + else if (!strcmp(sw, "-debug-abort")) { V3Error::vlAbort(); } // Undocumented, see also --debug-sigsegv else if ( onoff (sw, "-debug-check", flag/*ref*/)) { m_debugCheck = flag; } else if ( onoff (sw, "-debug-collision", flag/*ref*/)) { m_debugCollision = flag; } // Undocumented else if ( onoff (sw, "-debug-leak", flag/*ref*/)) { m_debugLeak = flag; }