diff --git a/Changes b/Changes index 4a99d0189..903cd0082 100644 --- a/Changes +++ b/Changes @@ -168,10 +168,10 @@ The contributors that suggested a given feature are shown in []. Thanks! * Verilator 4.020 2019-10-06 -*** Support $fseek, $ftell, $frewind, #1496. [Howard Su] - *** Add --public-flat-rw, #1511. [Stefan Wallentowitz] +*** Support $fseek, $ftell, $frewind, #1496. [Howard Su] + *** Support vpiModule, #1469. [Stefan Wallentowitz] **** Make Syms file honor --output-split-cfuncs, #1499. [Todd Strader] @@ -192,6 +192,8 @@ The contributors that suggested a given feature are shown in []. Thanks! **** Fix case statements with strings, #1536. [Philipp Wagner] +**** Fix some coverage lost when multithreaded, #2151. + * Verilator 4.018 2019-08-29 diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index 0d9316a81..9352f2ab6 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -382,9 +382,15 @@ public: puts(");\n"); } virtual void visit(AstCoverInc* nodep) VL_OVERRIDE { - puts("++(vlSymsp->__Vcoverage["); - puts(cvtToStr(nodep->declp()->dataDeclThisp()->binNum())); - puts("]);\n"); + if (v3Global.opt.threads()) { + puts("vlSymsp->__Vcoverage["); + puts(cvtToStr(nodep->declp()->dataDeclThisp()->binNum())); + puts("].fetch_add(1, std::memory_order_relaxed);\n"); + } else { + puts("++(vlSymsp->__Vcoverage["); + puts(cvtToStr(nodep->declp()->dataDeclThisp()->binNum())); + puts("]);\n"); + } } virtual void visit(AstCReturn* nodep) VL_OVERRIDE { puts("return ("); @@ -1953,7 +1959,9 @@ void EmitCImp::emitCoverageDecl(AstNodeModule* modp) { if (v3Global.opt.coverage()) { ofp()->putsPrivate(true); putsDecoration("// Coverage\n"); - puts("void __vlCoverInsert(uint32_t* countp, bool enable, const char* filenamep, int lineno, int column,\n"); + puts("void __vlCoverInsert("); + puts(v3Global.opt.threads() ? "std::atomic" : "uint32_t"); + puts("* countp, bool enable, const char* filenamep, int lineno, int column,\n"); puts( "const char* hierp, const char* pagep, const char* commentp);\n"); } } @@ -2068,14 +2076,22 @@ void EmitCImp::emitCoverageImp(AstNodeModule* modp) { puts("\n// Coverage\n"); // Rather than putting out VL_COVER_INSERT calls directly, we do it via this function // This gets around gcc slowness constructing all of the template arguments. - puts("void " + prefixNameProtect(m_modp) - + "::__vlCoverInsert(uint32_t* countp, bool enable," - + " const char* filenamep, int lineno, int column,\n"); + puts("void " + prefixNameProtect(m_modp) + "::__vlCoverInsert("); + puts(v3Global.opt.threads() ? "std::atomic" : "uint32_t"); + puts("* countp, bool enable, const char* filenamep, int lineno, int column,\n"); puts( "const char* hierp, const char* pagep, const char* commentp) {\n"); - puts( "static uint32_t fake_zero_count = 0;\n"); // static doesn't need save-restore as constant - puts( "if (!enable) countp = &fake_zero_count;\n"); // Used for second++ instantiation of identical bin - puts( "*countp = 0;\n"); - puts( "VL_COVER_INSERT(countp,"); + if (v3Global.opt.threads()) { + puts( "assert(sizeof(uint32_t) == sizeof(std::atomic));\n"); + puts( "uint32_t* count32p = reinterpret_cast(countp);\n"); + } else { + puts( "uint32_t* count32p = countp;\n"); + } + // static doesn't need save-restore as is constant + puts( "static uint32_t fake_zero_count = 0;\n"); + // Used for second++ instantiation of identical bin + puts( "if (!enable) count32p = &fake_zero_count;\n"); + puts( "*count32p = 0;\n"); + puts("VL_COVER_INSERT(count32p,"); puts( " \"filename\",filenamep,"); puts( " \"lineno\",lineno,"); puts( " \"column\",column,\n"); diff --git a/src/V3EmitCSyms.cpp b/src/V3EmitCSyms.cpp index 214fff4fd..6cdc1c635 100644 --- a/src/V3EmitCSyms.cpp +++ b/src/V3EmitCSyms.cpp @@ -437,7 +437,10 @@ void EmitCSyms::emitSymHdr() { if (m_coverBins) { puts("\n// COVERAGE\n"); - puts("uint32_t __Vcoverage["); puts(cvtToStr(m_coverBins)); puts("];\n"); + puts(v3Global.opt.threads() ? "std::atomic" : "uint32_t"); + puts(" __Vcoverage["); + puts(cvtToStr(m_coverBins)); + puts("];\n"); } if (!m_scopeNames.empty()) { // Scope names