From 47b52800bf4d2ee85ef6472a610155e4169d5278 Mon Sep 17 00:00:00 2001 From: Todd Strader Date: Thu, 6 Nov 2025 08:23:35 -0500 Subject: [PATCH] Fix expression coverage of system calls (#6592) --- src/V3Ast.h | 2 + src/V3AstNodeExpr.h | 53 +++ src/V3Coverage.cpp | 11 +- src/V3EmitV.cpp | 4 + test_regress/t/t_cover_sys_line_expr.out | 339 ++++++++++++++++++ test_regress/t/t_cover_sys_line_expr.py | 26 ++ test_regress/t/t_cover_sys_line_expr.v | 81 +++++ .../t/t_sys_file_basic_cover_expr.out | 1 + test_regress/t/t_sys_file_basic_cover_expr.py | 26 ++ 9 files changed, 539 insertions(+), 4 deletions(-) create mode 100644 test_regress/t/t_cover_sys_line_expr.out create mode 100755 test_regress/t/t_cover_sys_line_expr.py create mode 100644 test_regress/t/t_cover_sys_line_expr.v create mode 120000 test_regress/t/t_sys_file_basic_cover_expr.out create mode 100755 test_regress/t/t_sys_file_basic_cover_expr.py diff --git a/src/V3Ast.h b/src/V3Ast.h index 165e2ee44..65054e378 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -902,6 +902,8 @@ public: // isUnlikely handles $stop or similar statement which means an above IF // statement is unlikely to be taken virtual bool isUnlikely() const { return false; } + // Is an IEEE system function (versus internally-generated) + virtual bool isSystemFunc() const { return false; } virtual int instrCount() const { return 0; } // Iff node is identical to another node virtual bool isSame(const AstNode* samep) const { diff --git a/src/V3AstNodeExpr.h b/src/V3AstNodeExpr.h index 066e2be69..e8448a0bf 100644 --- a/src/V3AstNodeExpr.h +++ b/src/V3AstNodeExpr.h @@ -134,6 +134,7 @@ public: bool cleanRhs() const override { return false; } bool sizeMattersLhs() const override { return false; } bool sizeMattersRhs() const override { return false; } + bool isSystemFunc() const override { return true; } int instrCount() const override { return INSTR_COUNT_DBL_TRIG; } void numberOperate(V3Number&, const V3Number&, const V3Number&) override { V3ERROR_NA; } }; @@ -172,6 +173,7 @@ public: bool cleanRhs() const override { return false; } bool sizeMattersLhs() const override { return false; } bool sizeMattersRhs() const override { return false; } + bool isSystemFunc() const override { return true; } int instrCount() const override { return INSTR_COUNT_DBL_TRIG; } bool doubleFlavor() const override { return true; } }; @@ -347,6 +349,7 @@ protected: public: ASTGEN_MEMBERS_AstNodeTermop; + bool isSystemFunc() const override { return true; } }; class AstNodeTriop VL_NOT_FINAL : public AstNodeExpr { // Ternary expression @@ -403,6 +406,7 @@ public: bool sizeMattersLhs() const override { return false; } bool sizeMattersRhs() const override { return false; } bool sizeMattersThs() const override { return false; } + bool isSystemFunc() const override { return true; } int instrCount() const override { return INSTR_COUNT_DBL_TRIG; } void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, const V3Number& ths) override { @@ -449,6 +453,7 @@ public: bool cleanOut() const override { return true; } bool cleanLhs() const override { return false; } bool sizeMattersLhs() const override { return false; } + bool isSystemFunc() const override { return true; } int instrCount() const override { return INSTR_COUNT_DBL_TRIG; } bool doubleFlavor() const override { return true; } }; @@ -1350,6 +1355,7 @@ public: int instrCount() const override { return widthInstrs() * 64; } bool isPredictOptimizable() const override { return false; } bool isPure() override { return false; } // SPECIAL: $display has 'visual' ordering + bool isSystemFunc() const override { return true; } bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstFOpen final : public AstNodeExpr { @@ -1372,6 +1378,7 @@ public: bool isOutputter() override { return true; } bool isUnlikely() const override { return true; } bool sameNode(const AstNode* /*samep*/) const override { return true; } + bool isSystemFunc() const override { return true; } }; class AstFOpenMcd final : public AstNodeExpr { // @astgen op2 := filenamep : AstNodeExpr @@ -1415,6 +1422,7 @@ public: bool isOutputter() override { return true; } // SPECIAL: makes output bool cleanOut() const override { return false; } bool sameNode(const AstNode* /*samep*/) const override { return true; } + bool isSystemFunc() const override { return true; } }; class AstFRewind final : public AstNodeExpr { // @astgen op1 := filep : Optional[AstNode] @@ -1462,6 +1470,7 @@ public: } string text() const { return m_text; } // * = Text to display void text(const string& text) { m_text = text; } + bool isSystemFunc() const override { return true; } }; class AstFSeek final : public AstNodeExpr { // @astgen op1 := filep : AstNode // file (must be a VarRef) @@ -1484,6 +1493,7 @@ public: bool isOutputter() override { return true; } // SPECIAL: makes output bool cleanOut() const override { return false; } bool sameNode(const AstNode* /*samep*/) const override { return true; } + bool isSystemFunc() const override { return true; } }; class AstFTell final : public AstNodeExpr { // @astgen op1 := filep : AstNode // file (must be a VarRef) @@ -1503,6 +1513,7 @@ public: bool isUnlikely() const override { return true; } bool cleanOut() const override { return false; } bool sameNode(const AstNode* /*samep*/) const override { return true; } + bool isSystemFunc() const override { return true; } }; class AstFalling final : public AstNodeExpr { // Verilog $falling_gclk @@ -1519,6 +1530,7 @@ public: bool cleanOut() const override { V3ERROR_NA_RETURN(""); } int instrCount() const override { return widthInstrs(); } bool sameNode(const AstNode* /*samep*/) const override { return true; } + bool isSystemFunc() const override { return true; } }; class AstFell final : public AstNodeExpr { // Verilog $fell @@ -1537,6 +1549,7 @@ public: bool cleanOut() const override { V3ERROR_NA_RETURN(""); } int instrCount() const override { return widthInstrs(); } bool sameNode(const AstNode* /*samep*/) const override { return true; } + bool isSystemFunc() const override { return true; } }; class AstFuture final : public AstNodeExpr { // Verilog $future_gclk @@ -1555,6 +1568,7 @@ public: bool cleanOut() const override { V3ERROR_NA_RETURN(""); } int instrCount() const override { return widthInstrs(); } bool sameNode(const AstNode* /*samep*/) const override { return true; } + bool isSystemFunc() const override { return true; } }; class AstGatePin final : public AstNodeExpr { // Possibly expand a gate primitive input pin value to match the range of the gate primitive @@ -1835,6 +1849,7 @@ public: bool cleanOut() const override { V3ERROR_NA_RETURN(""); } int instrCount() const override { return widthInstrs(); } bool sameNode(const AstNode* /*samep*/) const override { return true; } + bool isSystemFunc() const override { return true; } }; class AstPatMember final : public AstNodeExpr { // Verilog '{a} or '{a{b}} @@ -1923,6 +1938,7 @@ public: bool isGateOptimizable() const override { return false; } bool isPredictOptimizable() const override { return false; } bool isPure() override { return !seedp(); } + bool isSystemFunc() const override { return true; } int instrCount() const override { return INSTR_COUNT_PLI; } bool sameNode(const AstNode* /*samep*/) const override { return true; } bool combinable(const AstRand* samep) const { @@ -1947,6 +1963,7 @@ public: bool cleanOut() const override { return false; } bool isGateOptimizable() const override { return false; } bool isPredictOptimizable() const override { return false; } + bool isSystemFunc() const override { return true; } int instrCount() const override { return INSTR_COUNT_PLI; } bool sameNode(const AstNode* /*samep*/) const override { return true; } }; @@ -1965,6 +1982,7 @@ public: bool cleanOut() const override { V3ERROR_NA_RETURN(""); } int instrCount() const override { return widthInstrs(); } bool sameNode(const AstNode* /*samep*/) const override { return true; } + bool isSystemFunc() const override { return true; } }; class AstRose final : public AstNodeExpr { // Verilog $rose @@ -1983,6 +2001,7 @@ public: bool cleanOut() const override { V3ERROR_NA_RETURN(""); } int instrCount() const override { return widthInstrs(); } bool sameNode(const AstNode* /*samep*/) const override { return true; } + bool isSystemFunc() const override { return true; } }; class AstSExpr final : public AstNodeExpr { // Sequence expression @@ -2055,6 +2074,7 @@ public: string emitVerilog() override { V3ERROR_NA_RETURN(""); } string emitC() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { V3ERROR_NA_RETURN(true); } + bool isSystemFunc() const override { return true; } }; class AstSScanF final : public AstNodeExpr { // @astgen op1 := exprsp : List[AstNode] // VarRefs for results @@ -2086,6 +2106,7 @@ public: string text() const { return m_text; } // * = Text to display VTimescale timeunit() const { return m_timeunit; } void timeunit(const VTimescale& flag) { m_timeunit = flag; } + bool isSystemFunc() const override { return true; } }; class AstSampled final : public AstNodeExpr { // Verilog $sampled @@ -2102,6 +2123,7 @@ public: bool cleanOut() const override { V3ERROR_NA_RETURN(""); } int instrCount() const override { return 0; } bool sameNode(const AstNode* /*samep*/) const override { return true; } + bool isSystemFunc() const override { return true; } }; class AstScopeName final : public AstNodeExpr { // For display %m and DPI context imports @@ -2228,6 +2250,7 @@ public: bool cleanOut() const override { V3ERROR_NA_RETURN(""); } int instrCount() const override { return widthInstrs(); } bool sameNode(const AstNode* /*samep*/) const override { return true; } + bool isSystemFunc() const override { return true; } }; class AstStackTraceF final : public AstNodeExpr { // $stacktrace used as function @@ -2263,6 +2286,7 @@ public: bool cleanOut() const override { V3ERROR_NA_RETURN(""); } int instrCount() const override { return widthInstrs(); } bool sameNode(const AstNode* /*samep*/) const override { return true; } + bool isSystemFunc() const override { return true; } }; class AstStructSel final : public AstNodeExpr { // Unpacked struct/union member access @@ -2330,6 +2354,7 @@ public: bool isUnlikely() const override { return true; } bool cleanOut() const override { return true; } bool sameNode(const AstNode* /*samep*/) const override { return true; } + bool isSystemFunc() const override { return true; } }; class AstTestPlusArgs final : public AstNodeExpr { // Search expression. If nullptr then this is a $test$plusargs instead of $value$plusargs. @@ -2346,6 +2371,7 @@ public: bool isGateOptimizable() const override { return false; } bool isPredictOptimizable() const override { return false; } // but isPure() true + bool isSystemFunc() const override { return true; } bool cleanOut() const override { return true; } bool sameNode(const AstNode* /*samep*/) const override { return true; } }; @@ -2380,6 +2406,7 @@ public: string emitC() override { V3ERROR_NA_RETURN(""); } string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } + bool isSystemFunc() const override { return true; } int instrCount() const override { return widthInstrs(); } bool sameNode(const AstNode* /*samep*/) const override { return true; } }; @@ -2396,6 +2423,7 @@ public: string emitC() override { V3ERROR_NA_RETURN(""); } string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } + bool isSystemFunc() const override { return true; } int instrCount() const override { return widthInstrs(); } bool sameNode(const AstNode* /*samep*/) const override { return true; } VTimescale timeunit() const { return m_timeunit; } @@ -2450,6 +2478,7 @@ public: bool isGateOptimizable() const override { return false; } bool isPredictOptimizable() const override { return false; } bool isPure() override { return !outp(); } + bool isSystemFunc() const override { return true; } bool cleanOut() const override { return true; } bool sameNode(const AstNode* /*samep*/) const override { return true; } }; @@ -2553,6 +2582,7 @@ public: bool cleanRhs() const override { return true; } bool sizeMattersLhs() const override { return false; } bool sizeMattersRhs() const override { return false; } + bool isSystemFunc() const override { return true; } int instrCount() const override { return widthInstrs() * 20; } bool isPure() override { return false; } }; @@ -2731,6 +2761,7 @@ public: bool cleanRhs() const override { return true; } bool sizeMattersLhs() const override { return false; } bool sizeMattersRhs() const override { return false; } + bool isSystemFunc() const override { return true; } int instrCount() const override { return widthInstrs() * 64; } AstNode* strgp() const { return lhsp(); } AstNode* filep() const { return rhsp(); } @@ -2751,6 +2782,7 @@ public: bool cleanRhs() const override { return true; } bool sizeMattersLhs() const override { return false; } bool sizeMattersRhs() const override { return false; } + bool isSystemFunc() const override { return true; } int instrCount() const override { return widthInstrs() * 64; } bool isPredictOptimizable() const override { return false; } bool isPure() override { return false; } // SPECIAL: $display has 'visual' ordering @@ -3667,6 +3699,7 @@ public: bool isGateOptimizable() const override { return false; } bool isPredictOptimizable() const override { return false; } bool isPure() override { return false; } + bool isSystemFunc() const override { return true; } int instrCount() const override { return INSTR_COUNT_PLI; } }; @@ -4452,6 +4485,7 @@ public: bool sizeMattersRhs() const override { return false; } bool sizeMattersThs() const override { return false; } bool sizeMattersFhs() const override { return false; } + bool isSystemFunc() const override { return true; } int instrCount() const override { return widthInstrs() * 16; } }; @@ -4466,6 +4500,7 @@ public: string emitVerilog() override { return "%f$inferred_disable"; } string emitC() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } + bool isSystemFunc() const override { return true; } bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstTime final : public AstNodeTermop { @@ -4482,6 +4517,7 @@ public: bool cleanOut() const override { return true; } bool isGateOptimizable() const override { return false; } bool isPredictOptimizable() const override { return false; } + bool isSystemFunc() const override { return true; } int instrCount() const override { return INSTR_COUNT_TIME; } bool sameNode(const AstNode* /*samep*/) const override { return true; } void dump(std::ostream& str = std::cout) const override; @@ -4503,6 +4539,7 @@ public: bool cleanOut() const override { return true; } bool isGateOptimizable() const override { return false; } bool isPredictOptimizable() const override { return false; } + bool isSystemFunc() const override { return true; } int instrCount() const override { return INSTR_COUNT_TIME; } bool sameNode(const AstNode* /*samep*/) const override { return true; } void dump(std::ostream& str = std::cout) const override; @@ -4795,6 +4832,7 @@ public: bool cleanLhs() const override { return false; } // Eliminated before matters bool sizeMattersLhs() const override { return false; } // Eliminated before matters int instrCount() const override { return INSTR_COUNT_DBL; } + bool isSystemFunc() const override { return true; } }; class AstCAwait final : public AstNodeUniop { // Emit C++'s co_await expression @@ -4867,6 +4905,7 @@ public: bool cleanLhs() const override { return true; } bool sizeMattersLhs() const override { return false; } int instrCount() const override { return widthInstrs() * 16; } + bool isSystemFunc() const override { return true; } }; class AstCastWrap final : public AstNodeUniop { // A cast which has been expanded and the LHSP does all the lifting @@ -4896,6 +4935,7 @@ public: bool cleanLhs() const override { return true; } bool sizeMattersLhs() const override { return false; } int instrCount() const override { return widthInstrs() * 16; } + bool isSystemFunc() const override { return true; } }; class AstCvtPackString final : public AstNodeUniop { // Convert to Verilator Packed String (aka verilog "string") @@ -4977,6 +5017,7 @@ public: int instrCount() const override { return widthInstrs() * 16; } bool isPredictOptimizable() const override { return false; } bool isPure() override { return false; } // SPECIAL: $display has 'visual' ordering + bool isSystemFunc() const override { return true; } AstNode* filep() const { return lhsp(); } }; class AstFGetC final : public AstNodeUniop { @@ -4995,6 +5036,7 @@ public: bool isPredictOptimizable() const override { return false; } bool isPure() override { return false; } // SPECIAL: $display has 'visual' ordering AstNode* filep() const { return lhsp(); } + bool isSystemFunc() const override { return true; } }; class AstISToRD final : public AstNodeUniop { // $itor where lhs is signed @@ -5012,6 +5054,7 @@ public: bool cleanLhs() const override { return true; } bool sizeMattersLhs() const override { return false; } int instrCount() const override { return INSTR_COUNT_DBL; } + bool isSystemFunc() const override { return true; } }; class AstIToRD final : public AstNodeUniop { // $itor where lhs is unsigned @@ -5028,6 +5071,7 @@ public: bool cleanLhs() const override { return true; } bool sizeMattersLhs() const override { return false; } int instrCount() const override { return INSTR_COUNT_DBL; } + bool isSystemFunc() const override { return true; } }; class AstIsUnbounded final : public AstNodeUniop { // True if is unbounded ($) @@ -5046,6 +5090,7 @@ public: bool cleanOut() const override { return false; } bool cleanLhs() const override { return false; } bool sizeMattersLhs() const override { return false; } + bool isSystemFunc() const override { return true; } }; class AstIsUnknown final : public AstNodeUniop { // True if any unknown bits @@ -5061,6 +5106,7 @@ public: bool cleanOut() const override { return false; } bool cleanLhs() const override { return false; } bool sizeMattersLhs() const override { return false; } + bool isSystemFunc() const override { return true; } }; class AstLenN final : public AstNodeUniop { // Length of a string @@ -5191,6 +5237,7 @@ public: bool cleanLhs() const override { return true; } bool sizeMattersLhs() const override { return false; } int instrCount() const override { return widthInstrs() * 4; } + bool isSystemFunc() const override { return true; } }; class AstOneHot0 final : public AstNodeUniop { // True if only single bit, or no bits set in vector @@ -5207,6 +5254,7 @@ public: bool cleanLhs() const override { return true; } bool sizeMattersLhs() const override { return false; } int instrCount() const override { return widthInstrs() * 3; } + bool isSystemFunc() const override { return true; } }; class AstRToIRoundS final : public AstNodeUniop { // Convert real to integer, with arbitrary sized output (not just "integer" format) @@ -5225,6 +5273,7 @@ public: bool cleanLhs() const override { return false; } bool sizeMattersLhs() const override { return false; } int instrCount() const override { return INSTR_COUNT_DBL; } + bool isSystemFunc() const override { return true; } }; class AstRToIS final : public AstNodeUniop { // $rtoi(lhs) @@ -5241,6 +5290,7 @@ public: bool cleanLhs() const override { return false; } // Eliminated before matters bool sizeMattersLhs() const override { return false; } // Eliminated before matters int instrCount() const override { return INSTR_COUNT_DBL; } + bool isSystemFunc() const override { return true; } }; class AstRealToBits final : public AstNodeUniop { public: @@ -5256,6 +5306,7 @@ public: bool cleanLhs() const override { return false; } // Eliminated before matters bool sizeMattersLhs() const override { return false; } // Eliminated before matters int instrCount() const override { return INSTR_COUNT_DBL; } + bool isSystemFunc() const override { return true; } }; class AstRedAnd final : public AstNodeUniop { public: @@ -5337,6 +5388,7 @@ public: bool cleanLhs() const override { return false; } // Eliminated before matters bool sizeMattersLhs() const override { return true; } // Eliminated before matters int instrCount() const override { return 0; } + bool isSystemFunc() const override { return true; } }; class AstTimeImport final : public AstNodeUniop { // Take a constant that represents a time and needs conversion based on time units @@ -5419,6 +5471,7 @@ public: bool cleanLhs() const override { return false; } // Eliminated before matters bool sizeMattersLhs() const override { return true; } // Eliminated before matters int instrCount() const override { return 0; } + bool isSystemFunc() const override { return true; } }; // === AstNodeSystemUniopD === diff --git a/src/V3Coverage.cpp b/src/V3Coverage.cpp index 6a72acd00..5d3e5fd83 100644 --- a/src/V3Coverage.cpp +++ b/src/V3Coverage.cpp @@ -141,7 +141,7 @@ class CoverageVisitor final : public VNVisitor { const VNUser2InUse m_inuser2; V3UniqueNames m_exprTempNames; // For generating unique temporary variable names used by // expression coverage - std::unordered_map, AstVar*> m_funcTemps; + std::unordered_map m_funcTemps; // STATE - across all visitors int m_nextHandle = 0; @@ -277,6 +277,7 @@ class CoverageVisitor final : public VNVisitor { VL_RESTORER(m_modp); VL_RESTORER(m_state); VL_RESTORER(m_exprTempNames); + VL_RESTORER(m_funcTemps); createHandle(nodep); m_modp = nodep; m_state.m_inModOff @@ -333,6 +334,7 @@ class CoverageVisitor final : public VNVisitor { void visit(AstNodeFTask* nodep) override { VL_RESTORER(m_ftaskp); VL_RESTORER(m_exprTempNames); + VL_RESTORER(m_funcTemps); m_ftaskp = nodep; if (!nodep->dpiImport()) iterateProcedure(nodep); } @@ -784,9 +786,10 @@ class CoverageVisitor final : public VNVisitor { comment += (first ? "" : " && ") + term.m_emitV + "==" + (term.m_objective ? "1" : "0"); AstNodeExpr* covExprp = nullptr; - if (AstFuncRef* const frefp = VN_CAST(term.m_exprp, FuncRef)) { - AstNodeDType* const dtypep = frefp->taskp()->fvarp()->dtypep(); - const auto pair = m_funcTemps.emplace(*frefp, nullptr); + if (VN_IS(term.m_exprp, FuncRef) || term.m_exprp->isSystemFunc()) { + AstNodeExpr* const frefp = term.m_exprp; + AstNodeDType* const dtypep = frefp->dtypep(); + const auto pair = m_funcTemps.emplace(frefp, nullptr); AstVar* varp = pair.first->second; if (pair.second) { varp = new AstVar{fl, VVarType::MODULETEMP, m_exprTempNames.get(frefp), diff --git a/src/V3EmitV.cpp b/src/V3EmitV.cpp index 58e66b8bb..f8818749b 100644 --- a/src/V3EmitV.cpp +++ b/src/V3EmitV.cpp @@ -699,6 +699,10 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst { emitVerilogFormat(nodep, nodep->emitVerilog(), nodep->lhsp(), nodep->rhsp(), nodep->thsp()); } + void visit(AstNodeQuadop* nodep) override { + emitVerilogFormat(nodep, nodep->emitVerilog(), nodep->lhsp(), nodep->rhsp(), nodep->thsp(), + nodep->fhsp()); + } void visit(AstMemberSel* nodep) override { iterateConst(nodep->fromp()); puts("."); diff --git a/test_regress/t/t_cover_sys_line_expr.out b/test_regress/t/t_cover_sys_line_expr.out new file mode 100644 index 000000000..5824d5a89 --- /dev/null +++ b/test_regress/t/t_cover_sys_line_expr.out @@ -0,0 +1,339 @@ +// // verilator_coverage annotation + // DESCRIPTION: Verilator: Verilog Test module + // + // This file ONLY is placed under the Creative Commons Public Domain, for + // any use, without warranty, 2024 by Wilson Snyder. + // SPDX-License-Identifier: CC0-1.0 + + module t (/*AUTOARG*/ + // Inputs + clk + ); + + input clk; + + int cyc, bump, result; + logic foo; +%000001 initial begin +-000001 point: comment=block hier=top.t +%000001 cyc = 0; +-000001 point: comment=block hier=top.t +%000001 foo = '1; +-000001 point: comment=block hier=top.t + end + + + 000010 always @(posedge clk) begin ++000010 point: comment=block hier=top.t +~000010 if (($time != 0) && foo) bump <= bump + 1; ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($realtime != 0) && foo) bump <= bump + 1; ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($stime != 0) && foo) bump <= bump + 1; ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($bitstoreal(123) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($bitstoreal(64'h7b) != $itor($signed(32'sh0)))==0) => 0 hier=top.t ++000010 point: comment=(($bitstoreal(64'h7b) != $itor($signed(32'sh0)))==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($itor(123) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($itor($signed(32'sh7b)) != $itor($signed(32'sh0)))==0) => 0 hier=top.t ++000010 point: comment=(($itor($signed(32'sh7b)) != $itor($signed(32'sh0)))==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($signed(3) != 0) && foo) bump <= bump + 1; +-000000 point: comment=((32'sh3 != 32'sh0)==0) => 0 hier=top.t ++000010 point: comment=((32'sh3 != 32'sh0)==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($realtobits(1.23) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($realtobits(1.23) != 64'h0)==0) => 0 hier=top.t ++000010 point: comment=(($realtobits(1.23) != 64'h0)==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($rtoi(1.23) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($rtoi(1.23) != 32'sh0)==0) => 0 hier=top.t ++000010 point: comment=(($rtoi(1.23) != 32'sh0)==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($unsigned(-3) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(((- 32'sh3) != 32'sh0)==0) => 0 hier=top.t ++000010 point: comment=(((- 32'sh3) != 32'sh0)==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($clog2(123) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($clog2(32'sh7b) != 32'sh0)==0) => 0 hier=top.t ++000010 point: comment=(($clog2(32'sh7b) != 32'sh0)==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($ln(123) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($ln($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==0) => 0 hier=top.t ++000010 point: comment=(($ln($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($log10(123) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($log10($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==0) => 0 hier=top.t ++000010 point: comment=(($log10($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($exp(123) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($exp($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==0) => 0 hier=top.t ++000010 point: comment=(($exp($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($sqrt(123) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($sqrt($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==0) => 0 hier=top.t ++000010 point: comment=(($sqrt($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($pow(123, 2) != 0) && foo) bump <= bump + 1; +-000000 point: comment=((($itor($signed(32'sh7b)) ** $itor($signed(32'sh2))) != $itor($signed(32'sh0)))==0) => 0 hier=top.t ++000010 point: comment=((($itor($signed(32'sh7b)) ** $itor($signed(32'sh2))) != $itor($signed(32'sh0)))==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($floor(1.23) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($floor(1.23) != $itor($signed(32'sh0)))==0) => 0 hier=top.t ++000010 point: comment=(($floor(1.23) != $itor($signed(32'sh0)))==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($ceil(1.23) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($ceil(1.23) != $itor($signed(32'sh0)))==0) => 0 hier=top.t ++000010 point: comment=(($ceil(1.23) != $itor($signed(32'sh0)))==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($sin(123) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($sin($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==0) => 0 hier=top.t ++000010 point: comment=(($sin($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($cos(123) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($cos($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==0) => 0 hier=top.t ++000010 point: comment=(($cos($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($tan(123) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($tan($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==0) => 0 hier=top.t ++000010 point: comment=(($tan($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($asin(123) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($asin($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==0) => 0 hier=top.t ++000010 point: comment=(($asin($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($acos(123) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($acos($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==0) => 0 hier=top.t ++000010 point: comment=(($acos($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($atan(123) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($atan($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==0) => 0 hier=top.t ++000010 point: comment=(($atan($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($atan2(123, 2) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($atan2($itor($signed(32'sh7b)),$itor($signed(32'sh2))) != $itor($signed(32'sh0)))==0) => 0 hier=top.t ++000010 point: comment=(($atan2($itor($signed(32'sh7b)),$itor($signed(32'sh2))) != $itor($signed(32'sh0)))==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($hypot(123, 2) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($hypot($itor($signed(32'sh7b)),$itor($signed(32'sh2))) != $itor($signed(32'sh0)))==0) => 0 hier=top.t ++000010 point: comment=(($hypot($itor($signed(32'sh7b)),$itor($signed(32'sh2))) != $itor($signed(32'sh0)))==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($sinh(123) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($sinh($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==0) => 0 hier=top.t ++000010 point: comment=(($sinh($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($cosh(123) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($cosh($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==0) => 0 hier=top.t ++000010 point: comment=(($cosh($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($tanh(123) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($tanh($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==0) => 0 hier=top.t ++000010 point: comment=(($tanh($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($asinh(123) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($asinh($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==0) => 0 hier=top.t ++000010 point: comment=(($asinh($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($acosh(123) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($acosh($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==0) => 0 hier=top.t ++000010 point: comment=(($acosh($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($atanh(123) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($atanh($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==0) => 0 hier=top.t ++000010 point: comment=(($atanh($itor($signed(32'sh7b))) != $itor($signed(32'sh0)))==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($countbits(123, 2) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($countbits(32'sh7b, 32'sh2, , 32'sh2) != 32'sh0)==0) => 0 hier=top.t ++000010 point: comment=(($countbits(32'sh7b, 32'sh2, , 32'sh2) != 32'sh0)==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($onehot(123) != 0) && foo) bump <= bump + 1; ++000010 point: comment=(($onehot(32'sh7b) != 32'sh0)==0) => 0 hier=top.t +-000000 point: comment=(($onehot(32'sh7b) != 32'sh0)==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t +-000000 point: comment=if hier=top.t ++000010 point: comment=else hier=top.t +~000010 if ($isunknown(foo) && foo) bump <= bump + 1; ++000010 point: comment=($isunknown(foo)==0) => 0 hier=top.t +-000000 point: comment=($isunknown(foo)==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t +-000000 point: comment=if hier=top.t ++000010 point: comment=else hier=top.t +~000010 if (($countones(123) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($countones(32'sh7b) != 32'sh0)==0) => 0 hier=top.t ++000010 point: comment=(($countones(32'sh7b) != 32'sh0)==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($onehot0(123) != 0) && foo) bump <= bump + 1; ++000010 point: comment=(($onehot0(32'sh7b) != 32'sh0)==0) => 0 hier=top.t +-000000 point: comment=(($onehot0(32'sh7b) != 32'sh0)==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t +-000000 point: comment=if hier=top.t ++000010 point: comment=else hier=top.t +~000010 if (($sampled(foo) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($sampled(foo) != 32'sh0)==0) => 0 hier=top.t ++000010 point: comment=(($sampled(foo) != 32'sh0)==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($fell(foo) != 0) && foo) bump <= bump + 1; ++000010 point: comment=(($fell(foo) != 32'sh0)==0) => 0 hier=top.t +-000000 point: comment=(($fell(foo) != 32'sh0)==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t +-000000 point: comment=if hier=top.t ++000010 point: comment=else hier=top.t +%000009 if (($changed(foo) != 0) && foo) bump <= bump + 1; +-000009 point: comment=(((! $stable(foo)) != 32'sh0)==0) => 0 hier=top.t +-000001 point: comment=(((! $stable(foo)) != 32'sh0)==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t +-000001 point: comment=if hier=top.t +-000009 point: comment=else hier=top.t +%000009 if (($rose(foo) != 0) && foo) bump <= bump + 1; +-000009 point: comment=(($rose(foo) != 32'sh0)==0) => 0 hier=top.t +-000001 point: comment=(($rose(foo) != 32'sh0)==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t +-000001 point: comment=if hier=top.t +-000009 point: comment=else hier=top.t +%000009 if (($stable(foo) != 0) && foo) bump <= bump + 1; +-000001 point: comment=(($stable(foo) != 32'sh0)==0) => 0 hier=top.t +-000009 point: comment=(($stable(foo) != 32'sh0)==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t +-000009 point: comment=if hier=top.t +-000001 point: comment=else hier=top.t +%000009 if (($past(foo) != 0) && foo) bump <= bump + 1; +-000001 point: comment=(($past(foo) != 32'sh0)==0) => 0 hier=top.t +-000009 point: comment=(($past(foo) != 32'sh0)==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t +-000009 point: comment=if hier=top.t +-000001 point: comment=else hier=top.t +~000010 if (($random != 0) && foo) bump <= bump + 1; ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($dist_erlang(result, 2, 3) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($dist_erlang(result, 32'sh2, 32'sh3) != 32'sh0)==0) => 0 hier=top.t ++000010 point: comment=(($dist_erlang(result, 32'sh2, 32'sh3) != 32'sh0)==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($dist_normal(result, 2, 3) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($dist_normal(result, 32'sh2, 32'sh3) != 32'sh0)==0) => 0 hier=top.t ++000010 point: comment=(($dist_normal(result, 32'sh2, 32'sh3) != 32'sh0)==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($dist_t(result, 2) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($dist_t(result, 32'sh2) != 32'sh0)==0) => 0 hier=top.t +-000000 point: comment=(($dist_t(result, 32'sh2) != 32'sh0)==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t +-000000 point: comment=if hier=top.t ++000010 point: comment=else hier=top.t +~000010 if (($dist_chi_square(result, 2) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($dist_chi_square(result, 32'sh2) != 32'sh0)==0) => 0 hier=top.t ++000010 point: comment=(($dist_chi_square(result, 32'sh2) != 32'sh0)==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($dist_exponential(result, 2) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($dist_exponential(result, 32'sh2) != 32'sh0)==0) => 0 hier=top.t +-000000 point: comment=(($dist_exponential(result, 32'sh2) != 32'sh0)==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($dist_poisson(result, 2) != 0) && foo) bump <= bump + 1; ++000010 point: comment=(($dist_poisson(result, 32'sh2) != 32'sh0)==0) => 0 hier=top.t ++000010 point: comment=(($dist_poisson(result, 32'sh2) != 32'sh0)==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($dist_uniform(result, 2, 3) != 0) && foo) bump <= bump + 1; +-000000 point: comment=(($dist_uniform(result, 32'sh2, 32'sh3) != 32'sh0)==0) => 0 hier=top.t ++000010 point: comment=(($dist_uniform(result, 32'sh2, 32'sh3) != 32'sh0)==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t +~000010 if (($sformatf("abc") != "abc") && foo) bump <= bump + 1; ++000010 point: comment=(($sformatf(%22abc%22);%0A != %22abc%22)==0) => 0 hier=top.t +-000000 point: comment=(($sformatf(%22abc%22);%0A != %22abc%22)==1 && foo==1) => 1 hier=top.t +-000000 point: comment=(foo==0) => 0 hier=top.t +-000000 point: comment=if hier=top.t ++000010 point: comment=else hier=top.t +~000010 if (foo && foo) bump <= bump + 1; +-000000 point: comment=(foo==0) => 0 hier=top.t ++000010 point: comment=(foo==1) => 1 hier=top.t ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t + 000010 cyc <= cyc + 1; ++000010 point: comment=block hier=top.t +%000009 if (cyc==9) begin +-000001 point: comment=if hier=top.t +-000009 point: comment=else hier=top.t +%000001 $write("*-* All Finished *-*\n"); +-000001 point: comment=if hier=top.t +%000001 $finish; +-000001 point: comment=if hier=top.t + end + end + endmodule + diff --git a/test_regress/t/t_cover_sys_line_expr.py b/test_regress/t/t_cover_sys_line_expr.py new file mode 100755 index 000000000..c1be5c43d --- /dev/null +++ b/test_regress/t/t_cover_sys_line_expr.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 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. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios("simulator") + +test.compile(verilator_flags2=["--cc --coverage-line --coverage-expr"]) + +test.execute() + +test.run(cmd=[os.environ["VERILATOR_ROOT"] + "/bin/verilator_coverage", + "--annotate-points", + "--annotate", test.obj_dir + "/annotated", + test.obj_dir + "/coverage.dat"], + verilator_run=True) # yapf:disable + +test.files_identical(test.obj_dir + "/annotated/t_cover_sys_line_expr.v", test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_cover_sys_line_expr.v b/test_regress/t/t_cover_sys_line_expr.v new file mode 100644 index 000000000..d83664aa0 --- /dev/null +++ b/test_regress/t/t_cover_sys_line_expr.v @@ -0,0 +1,81 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/ + // Inputs + clk + ); + + input clk; + + int cyc, bump, result; + logic foo; + initial begin + cyc = 0; + foo = '1; + end + + + always @(posedge clk) begin + if (($time != 0) && foo) bump <= bump + 1; + if (($realtime != 0) && foo) bump <= bump + 1; + if (($stime != 0) && foo) bump <= bump + 1; + if (($bitstoreal(123) != 0) && foo) bump <= bump + 1; + if (($itor(123) != 0) && foo) bump <= bump + 1; + if (($signed(3) != 0) && foo) bump <= bump + 1; + if (($realtobits(1.23) != 0) && foo) bump <= bump + 1; + if (($rtoi(1.23) != 0) && foo) bump <= bump + 1; + if (($unsigned(-3) != 0) && foo) bump <= bump + 1; + if (($clog2(123) != 0) && foo) bump <= bump + 1; + if (($ln(123) != 0) && foo) bump <= bump + 1; + if (($log10(123) != 0) && foo) bump <= bump + 1; + if (($exp(123) != 0) && foo) bump <= bump + 1; + if (($sqrt(123) != 0) && foo) bump <= bump + 1; + if (($pow(123, 2) != 0) && foo) bump <= bump + 1; + if (($floor(1.23) != 0) && foo) bump <= bump + 1; + if (($ceil(1.23) != 0) && foo) bump <= bump + 1; + if (($sin(123) != 0) && foo) bump <= bump + 1; + if (($cos(123) != 0) && foo) bump <= bump + 1; + if (($tan(123) != 0) && foo) bump <= bump + 1; + if (($asin(123) != 0) && foo) bump <= bump + 1; + if (($acos(123) != 0) && foo) bump <= bump + 1; + if (($atan(123) != 0) && foo) bump <= bump + 1; + if (($atan2(123, 2) != 0) && foo) bump <= bump + 1; + if (($hypot(123, 2) != 0) && foo) bump <= bump + 1; + if (($sinh(123) != 0) && foo) bump <= bump + 1; + if (($cosh(123) != 0) && foo) bump <= bump + 1; + if (($tanh(123) != 0) && foo) bump <= bump + 1; + if (($asinh(123) != 0) && foo) bump <= bump + 1; + if (($acosh(123) != 0) && foo) bump <= bump + 1; + if (($atanh(123) != 0) && foo) bump <= bump + 1; + if (($countbits(123, 2) != 0) && foo) bump <= bump + 1; + if (($onehot(123) != 0) && foo) bump <= bump + 1; + if ($isunknown(foo) && foo) bump <= bump + 1; + if (($countones(123) != 0) && foo) bump <= bump + 1; + if (($onehot0(123) != 0) && foo) bump <= bump + 1; + if (($sampled(foo) != 0) && foo) bump <= bump + 1; + if (($fell(foo) != 0) && foo) bump <= bump + 1; + if (($changed(foo) != 0) && foo) bump <= bump + 1; + if (($rose(foo) != 0) && foo) bump <= bump + 1; + if (($stable(foo) != 0) && foo) bump <= bump + 1; + if (($past(foo) != 0) && foo) bump <= bump + 1; + if (($random != 0) && foo) bump <= bump + 1; + if (($dist_erlang(result, 2, 3) != 0) && foo) bump <= bump + 1; + if (($dist_normal(result, 2, 3) != 0) && foo) bump <= bump + 1; + if (($dist_t(result, 2) != 0) && foo) bump <= bump + 1; + if (($dist_chi_square(result, 2) != 0) && foo) bump <= bump + 1; + if (($dist_exponential(result, 2) != 0) && foo) bump <= bump + 1; + if (($dist_poisson(result, 2) != 0) && foo) bump <= bump + 1; + if (($dist_uniform(result, 2, 3) != 0) && foo) bump <= bump + 1; + if (($sformatf("abc") != "abc") && foo) bump <= bump + 1; + if (foo && foo) bump <= bump + 1; + cyc <= cyc + 1; + if (cyc==9) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end +endmodule diff --git a/test_regress/t/t_sys_file_basic_cover_expr.out b/test_regress/t/t_sys_file_basic_cover_expr.out new file mode 120000 index 000000000..36fc2f5aa --- /dev/null +++ b/test_regress/t/t_sys_file_basic_cover_expr.out @@ -0,0 +1 @@ +t_sys_file_basic.out \ No newline at end of file diff --git a/test_regress/t/t_sys_file_basic_cover_expr.py b/test_regress/t/t_sys_file_basic_cover_expr.py new file mode 100755 index 000000000..0c86310dc --- /dev/null +++ b/test_regress/t/t_sys_file_basic_cover_expr.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 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. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios("simulator") +test.top_filename = "t/t_sys_file_basic.v" + +test.unlink_ok(test.obj_dir + "/t_sys_file_basic_test.log") + +test.compile( + verilator_flags2=["--coverage-expr"], + # Build without cached objects, see bug363 + make_flags=["VM_PARALLEL_BUILDS=0"], +) + +test.execute() +test.files_identical(test.obj_dir + "/t_sys_file_basic_test.log", test.golden_filename) + +test.passes()