diff --git a/Changes b/Changes index ced84ea4e..9877ca716 100644 --- a/Changes +++ b/Changes @@ -161,7 +161,7 @@ Verilator 5.049 devel * Fix FSM detect unchecked casts and variable redeclaration (#7758). [Adam Kostrzewski, Antmicro Ltd.] * Fix no-scope internal error on virtual interface method calls (#7759). [Yilou Wang] * Fix 'case (_) inside' with x wildcards (#7766). [Geza Lore, Testorrent USA, Inc.] - +* Fix $fflush and autoflush with --threads (#7782). Verilator 5.048 2026-04-26 diff --git a/include/verilated.cpp b/include/verilated.cpp index 6bf868cad..a7d78f3bd 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -318,6 +318,13 @@ void VL_PRINTF_MT(const char* formatp, ...) VL_MT_SAFE { }}); } +void VL_FFLUSH_MT() VL_MT_SAFE { + va_list ap; + VerilatedThreadMsgQueue::post(VerilatedMsg{[=]() { // + Verilated::runFlushCallbacks(); + }}); +} + template static size_t _vl_snprintf_string(std::string& str, const char* format, snprintf_args_ts... args) VL_MT_SAFE { diff --git a/include/verilated_funcs.h b/include/verilated_funcs.h index db4c39e5c..8aebd1e34 100644 --- a/include/verilated_funcs.h +++ b/include/verilated_funcs.h @@ -74,10 +74,8 @@ extern void VL_FATAL_MT(const char* filename, int linenum, const char* hier, extern void VL_WARN_MT(const char* filename, int linenum, const char* hier, const char* msg) VL_MT_SAFE; -// clang-format off /// Print a string, multithread safe. Eventually VL_PRINTF will get called. extern void VL_PRINTF_MT(const char* formatp, ...) VL_ATTR_PRINTF(1) VL_MT_SAFE; -// clang-format on /// Print a debug message from internals with standard prefix, with printf style format extern void VL_DBG_MSGF(const char* formatp, ...) VL_ATTR_PRINTF(1) VL_MT_SAFE; @@ -85,6 +83,9 @@ extern void VL_DBG_MSGF(const char* formatp, ...) VL_ATTR_PRINTF(1) VL_MT_SAFE; /// Print a debug message from string via VL_DBG_MSGF inline void VL_DBG_MSGS(const std::string& str) VL_MT_SAFE { VL_DBG_MSGF("%s", str.c_str()); } +/// Flush stdout +extern void VL_FFLUSH_MT() VL_MT_SAFE; + // EMIT_RULE: VL_RANDOM: oclean=dirty inline IData VL_RANDOM_I() VL_MT_SAFE { return vl_rand64(); } inline QData VL_RANDOM_Q() VL_MT_SAFE { return vl_rand64(); } diff --git a/src/V3EmitCFunc.h b/src/V3EmitCFunc.h index 6eedcbc69..969e2fd0b 100644 --- a/src/V3EmitCFunc.h +++ b/src/V3EmitCFunc.h @@ -1134,7 +1134,7 @@ public: } void visit(AstFFlush* nodep) override { if (!nodep->filep()) { - putns(nodep, "Verilated::runFlushCallbacks();\n"); + putns(nodep, "VL_FFLUSH_MT();"); } else { putns(nodep, "VL_FFLUSH_I("); iterateAndNextConstNull(nodep->filep());