diff --git a/include/verilated_save.cpp b/include/verilated_save.cpp index f7a6e5bc4..0972f513f 100644 --- a/include/verilated_save.cpp +++ b/include/verilated_save.cpp @@ -202,7 +202,7 @@ void VerilatedSave::flush() VL_MT_UNSAFE_ONE { VL_FATAL_MT("", 0, "", msg.c_str()); close(); break; - // LCOV_EXCL_END + // LCOV_EXCL_STOP } } } @@ -233,7 +233,7 @@ void VerilatedRestore::fill() VL_MT_UNSAFE_ONE { VL_FATAL_MT("", 0, "", msg.c_str()); close(); break; - // LCOV_EXCL_END + // LCOV_EXCL_STOP } } else { // got==0, EOF // Fill buffer from here to end with NULLs so reader's don't diff --git a/include/verilated_trace.h b/include/verilated_trace.h index 5dfb5f9fe..0d103380f 100644 --- a/include/verilated_trace.h +++ b/include/verilated_trace.h @@ -40,7 +40,7 @@ // Threaded tracing // A simple synchronized first in first out queue -template class VerilatedThreadQueue { +template class VerilatedThreadQueue { // LCOV_EXCL_LINE // lcov bug private: VerilatedMutex m_mutex; // Protects m_queue std::condition_variable_any m_cv; @@ -233,8 +233,8 @@ protected: // These hooks are called before a full or change based dump is produced. // The return value indicates whether to proceed with the dump. - virtual bool preFullDump() { return true; } - virtual bool preChangeDump() { return true; } + virtual bool preFullDump() = 0; + virtual bool preChangeDump() = 0; public: //========================================================================= diff --git a/include/verilated_trace_imp.cpp b/include/verilated_trace_imp.cpp index 6ae07a7e6..c8a64bba8 100644 --- a/include/verilated_trace_imp.cpp +++ b/include/verilated_trace_imp.cpp @@ -194,13 +194,14 @@ template <> void VerilatedTrace::workerThreadMain() { shutdown = true; break; - //=== - // Unknown command - default: + //=== + // Unknown command + default: { // LCOV_EXCL_START VL_TRACE_THREAD_DEBUG("Command UNKNOWN"); VL_PRINTF_MT("Trace command: 0x%08x\n", cmd); VL_FATAL_MT(__FILE__, __LINE__, "", "Unknown trace command"); break; + } // LCOV_EXCL_STOP } // The above switch will execute 'continue' when necessary, @@ -376,12 +377,12 @@ template <> void VerilatedTrace::set_time_resolution(const std::st template <> void VerilatedTrace::dump(vluint64_t timeui) { m_assertOne.check(); - if (VL_UNLIKELY(m_timeLastDump && timeui <= m_timeLastDump)) { + if (VL_UNCOVERABLE(m_timeLastDump && timeui <= m_timeLastDump)) { // LCOV_EXCL_START VL_PRINTF_MT("%%Warning: previous dump at t=%" VL_PRI64 "u, requesting t=%" VL_PRI64 "u, dump call ignored\n", m_timeLastDump, timeui); return; - } + } // LCOV_EXCL_STOP m_timeLastDump = timeui; Verilated::quiesce(); @@ -456,11 +457,11 @@ template <> void VerilatedTrace::addCallbackRecord(std::vector& cbVec, CallbackRecord& cbRec) { m_assertOne.check(); - if (VL_UNLIKELY(timeLastDump() != 0)) { + if (VL_UNCOVERABLE(timeLastDump() != 0)) { // LCOV_EXCL_START std::string msg = (std::string("Internal: ") + __FILE__ + "::" + __FUNCTION__ + " called with already open file"); VL_FATAL_MT(__FILE__, __LINE__, "", msg.c_str()); - } + } // LCOV_EXCL_STOP cbVec.push_back(cbRec); } diff --git a/include/verilated_vcd_c.cpp b/include/verilated_vcd_c.cpp index cc9b88941..8689b6fc8 100644 --- a/include/verilated_vcd_c.cpp +++ b/include/verilated_vcd_c.cpp @@ -366,7 +366,7 @@ void VerilatedVcd::bufferFlush() VL_MT_UNSAFE_ONE { VL_FATAL_MT("", 0, "", msg.c_str()); closeErr(); break; - // LCOV_EXCL_END + // LCOV_EXCL_STOP } } } diff --git a/nodist/code_coverage.dat b/nodist/code_coverage.dat index 481f8c18f..c85cfa642 100644 --- a/nodist/code_coverage.dat +++ b/nodist/code_coverage.dat @@ -42,6 +42,6 @@ remove_source("*examples/*"); # Would just be removed with remove_source in later step remove_gcda_regexp(qr!test_regress/.*/(Vt_|Vtop_).*\.gcda!); -exclude_line_regexp(qr/(\bv3fatalSrc\b|\bVL_UNCOVERABLE\b|\bVL_FATAL|\bUASSERT\bERROR_RSVD_WORD\bV3ERROR_NA)/); +exclude_line_regexp(qr/(\bv3fatalSrc\b|\bfatalSrc\b|\bVL_UNCOVERABLE\b|\bVL_FATAL|\bUASSERT\bERROR_RSVD_WORD\bV3ERROR_NA)/); 1; diff --git a/src/V3Expand.cpp b/src/V3Expand.cpp index 6b33f497f..edddb8923 100644 --- a/src/V3Expand.cpp +++ b/src/V3Expand.cpp @@ -197,7 +197,8 @@ private: UINFO(8, " Wordize ASSIGN(CONST) " << nodep << endl); // -> {for each_word{ ASSIGN(WORDSEL(wide,#),WORDSEL(CONST,#))}} if (rhsp->num().isFourState()) { - rhsp->v3error("Unsupported: 4-state numbers in this context"); + rhsp->v3error( // LCOV_EXCL_LINE // impossible? + "Unsupported: 4-state numbers in this context"); } for (int w = 0; w < nodep->widthWords(); w++) { addWordAssign( diff --git a/src/V3Inst.cpp b/src/V3Inst.cpp index fab5f9eac..6883d4b7a 100644 --- a/src/V3Inst.cpp +++ b/src/V3Inst.cpp @@ -423,7 +423,7 @@ private: } } if (!varNewp) { - if (debug() >= 9) m_deModVars.dump(); + if (debug() >= 9) m_deModVars.dump(); // LCOV_EXCL_LINE nodep->v3fatalSrc("Module dearray failed for " << AstNode::prettyNameQ(varNewName)); } diff --git a/src/V3Number.cpp b/src/V3Number.cpp index d3491bcd2..3569bbd73 100644 --- a/src/V3Number.cpp +++ b/src/V3Number.cpp @@ -467,8 +467,8 @@ string V3Number::ascii(bool prefixed, bool cleanVerilog) const { if (isDouble()) { out.precision(17); - if (width() != 64) { - out << "%E-bad-width-double"; + if (VL_UNCOVERABLE(width() != 64)) { + out << "%E-bad-width-double"; // LCOV_EXCL_LINE } else { out << toDouble(); } @@ -476,8 +476,8 @@ string V3Number::ascii(bool prefixed, bool cleanVerilog) const { } else if (isString()) { return '"' + toString() + '"'; } else { - if ((m_value[words() - 1] | m_valueX[words() - 1]) & ~hiWordMask()) { - out << "%E-hidden-bits"; + if (VL_UNCOVERABLE((m_value[words() - 1] | m_valueX[words() - 1]) & ~hiWordMask())) { + out << "%E-hidden-bits"; // LCOV_EXCL_LINE } } if (prefixed) { @@ -936,15 +936,6 @@ bool V3Number::isAnyXZ() const { } return false; } -bool V3Number::isLt(const V3Number& rhs) const { - for (int bit = 0; bit < std::max(this->width(), rhs.width()); bit++) { - if (this->bitIs1(bit) && rhs.bitIs0(bit)) { return 1; } - if (rhs.bitIs1(bit) && this->bitIs0(bit)) { return 0; } - if (this->bitIsXZ(bit)) { return 0; } - if (rhs.bitIsXZ(bit)) { return 0; } - } - return 0; -} bool V3Number::isLtXZ(const V3Number& rhs) const { // Include X/Z in comparisons for sort ordering for (int bit = 0; bit < std::max(this->width(), rhs.width()); bit++) { diff --git a/src/V3Number.h b/src/V3Number.h index c25509a49..93563a117 100644 --- a/src/V3Number.h +++ b/src/V3Number.h @@ -267,7 +267,6 @@ public: bool isEqOne() const; bool isEqAllOnes(int optwidth = 0) const; bool isCaseEq(const V3Number& rhs) const; // operator== - bool isLt(const V3Number& rhs) const; // operator< bool isLtXZ(const V3Number& rhs) const; // operator< with XZ compared void isSigned(bool ssigned) { m_signed = ssigned; } bool isAnyX() const; diff --git a/src/V3OrderGraph.h b/src/V3OrderGraph.h index 8816d4898..dcaafc789 100644 --- a/src/V3OrderGraph.h +++ b/src/V3OrderGraph.h @@ -386,12 +386,12 @@ public: } virtual string name() const { string nm; - if (logicp()) { + if (VL_UNCOVERABLE(!logicp())) { // Avoid crash when debugging + nm = "nul"; // LCOV_EXCL_LINE + } else { nm = logicp()->name(); nm += (string("\\nMV:") + " d=" + cvtToHex(logicp()->domainp()) + " s=" + cvtToHex(logicp()->scopep())); - } else { - nm = "nul"; } return nm; } diff --git a/src/V3Param.cpp b/src/V3Param.cpp index 9b121a9f9..87a05339e 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -410,11 +410,9 @@ private: string index = AstNode::encodeNumber(constp->toSInt()); string replacestr = nodep->name() + "__BRA__??__KET__"; size_t pos = m_unlinkedTxt.find(replacestr); - if (pos == string::npos) { - nodep->v3error("Could not find array index in unlinked text: '" - << m_unlinkedTxt << "' for node: " << nodep); - return; - } + UASSERT_OBJ(pos != string::npos, nodep, + "Could not find array index in unlinked text: '" + << m_unlinkedTxt << "' for node: " << nodep); m_unlinkedTxt.replace(pos, replacestr.length(), nodep->name() + "__BRA__" + index + "__KET__"); } else { diff --git a/src/V3PreProc.cpp b/src/V3PreProc.cpp index 466d3b209..3c616fccd 100644 --- a/src/V3PreProc.cpp +++ b/src/V3PreProc.cpp @@ -549,7 +549,7 @@ void V3PreProcImp::unputString(const string& strg) { // However this can lead to "flex scanner push-back overflow" // so instead we scan from a temporary buffer, then on EOF return. // This is also faster than the old scheme, amazingly. - if (m_lexp->m_bufferState != m_lexp->currentBuffer()) { + if (VL_UNCOVERABLE(m_lexp->m_bufferState != m_lexp->currentBuffer())) { fatalSrc("bufferStack missing current buffer; will return incorrectly"); // Hard to debug lost text as won't know till much later } @@ -1087,7 +1087,7 @@ int V3PreProcImp::getStateToken() { stateChange(ps_DEFFORM); m_lexp->pushStateDefForm(); goto next_tok; - } else { + } else { // LCOV_EXCL_LINE fatalSrc("Bad case\n"); } goto next_tok; @@ -1174,7 +1174,9 @@ int V3PreProcImp::getStateToken() { stateChange(ps_DEFARG); goto next_tok; } else { - if (m_defRefs.empty()) fatalSrc("Shouldn't be in DEFPAREN w/o active defref"); + if (VL_UNCOVERABLE(m_defRefs.empty())) { + fatalSrc("Shouldn't be in DEFPAREN w/o active defref"); + } VDefineRef* refp = &(m_defRefs.top()); error(string("Expecting ( to begin argument list for define reference `") + refp->name() + "\n"); @@ -1183,7 +1185,9 @@ int V3PreProcImp::getStateToken() { } } case ps_DEFARG: { - if (m_defRefs.empty()) fatalSrc("Shouldn't be in DEFARG w/o active defref"); + if (VL_UNCOVERABLE(m_defRefs.empty())) { + fatalSrc("Shouldn't be in DEFARG w/o active defref"); + } VDefineRef* refp = &(m_defRefs.top()); refp->nextarg(refp->nextarg() + m_lexp->m_defValue); m_lexp->m_defValue = ""; @@ -1208,7 +1212,9 @@ int V3PreProcImp::getStateToken() { statePop(); if (state() == ps_JOIN) { // Handle {left}```FOO(ARG) where `FOO(ARG) might be empty - if (m_joinStack.empty()) fatalSrc("`` join stack empty, but in a ``"); + if (VL_UNCOVERABLE(m_joinStack.empty())) { + fatalSrc("`` join stack empty, but in a ``"); + } string lhs = m_joinStack.top(); m_joinStack.pop(); out.insert(0, lhs); @@ -1295,7 +1301,9 @@ int V3PreProcImp::getStateToken() { } case ps_JOIN: { if (tok == VP_SYMBOL || tok == VP_TEXT) { - if (m_joinStack.empty()) fatalSrc("`` join stack empty, but in a ``"); + if (VL_UNCOVERABLE(m_joinStack.empty())) { + fatalSrc("`` join stack empty, but in a ``"); + } string lhs = m_joinStack.top(); m_joinStack.pop(); UINFO(5, "`` LHS:" << lhs << endl); @@ -1429,7 +1437,9 @@ int V3PreProcImp::getStateToken() { if (m_defRefs.empty()) { // Just output the substitution if (state() == ps_JOIN) { // Handle {left}```FOO where `FOO might be empty - if (m_joinStack.empty()) fatalSrc("`` join stack empty, but in a ``"); + if (VL_UNCOVERABLE(m_joinStack.empty())) { + fatalSrc("`` join stack empty, but in a ``"); + } string lhs = m_joinStack.top(); m_joinStack.pop(); out.insert(0, lhs); @@ -1500,9 +1510,9 @@ int V3PreProcImp::getStateToken() { case VP_COMMENT: // Handled at top of loop case VP_DEFFORM: // Handled by state=ps_DEFFORM; case VP_DEFVALUE: // Handled by state=ps_DEFVALUE; - default: + default: // LCOV_EXCL_LINE fatalSrc(string("Internal error: Unexpected token ") + tokenName(tok) + "\n"); - break; + break; // LCOV_EXCL_LINE } return tok; } diff --git a/src/V3Simulate.h b/src/V3Simulate.h index d8120b0a3..a5480a342 100644 --- a/src/V3Simulate.h +++ b/src/V3Simulate.h @@ -508,7 +508,7 @@ private: iterateAndNextNull(valuep); if (optimizable()) newValue(nodep, fetchValue(valuep)); } else { - clearOptimizable(nodep, "No value found for enum item"); + clearOptimizable(nodep, "No value found for enum item"); // LCOV_EXCL_LINE } } } diff --git a/src/V3SplitVar.cpp b/src/V3SplitVar.cpp index f051ed1c8..d1c794ee1 100644 --- a/src/V3SplitVar.cpp +++ b/src/V3SplitVar.cpp @@ -1275,7 +1275,7 @@ public: reason = "it is not an aggregate type of bit nor logic"; if (!reason) reason = cannotSplitVarCommonReason(nodep); } else { - reason = "its type is unknown"; + reason = "its type is unknown"; // LCOV_EXCL_LINE } if (reason) UINFO(5, diff --git a/src/V3Task.cpp b/src/V3Task.cpp index ab1a52fe1..e7a718290 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -1511,7 +1511,7 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp) for (int i = 0; i < tpinnum; ++i) { UINFO(0, " pin " << i << " conn=" << cvtToHex(tconnects[i].second) << endl); } - } // LCOV_EXCL_END + } // LCOV_EXCL_STOP return tconnects; } diff --git a/src/V3Width.cpp b/src/V3Width.cpp index cc6a73313..c1224d3a9 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -1933,7 +1933,7 @@ private: // if (nodep->childDTypep()) { // nodep->dtypep(moveChildDTypeEdit(nodep)); // data_type '{ pattern } // } - //userIterateChildren(nodep, NULL); + // userIterateChildren(nodep, NULL); } virtual void visit(AstMemberDType* nodep) VL_OVERRIDE { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed diff --git a/test_regress/t/t_number_bad.out b/test_regress/t/t_number_bad.out index b88db4a1f..dedb6786d 100644 --- a/test_regress/t/t_number_bad.out +++ b/test_regress/t/t_number_bad.out @@ -7,4 +7,10 @@ %Error: t/t_number_bad.v:11:29: Number is missing value digits: 32'h 11 | parameter integer FOO4 = 32'h; | ^~~~ +%Error: t/t_number_bad.v:13:29: Illegal character in binary constant: 2 + 13 | parameter integer FOO5 = 32'b2; + | ^~~~~ +%Error: t/t_number_bad.v:14:29: Illegal character in octal constant + 14 | parameter integer FOO6 = 32'o8; + | ^~~~~ %Error: Exiting due to diff --git a/test_regress/t/t_number_bad.v b/test_regress/t/t_number_bad.v index b2c1ae547..0ed4ef7a2 100644 --- a/test_regress/t/t_number_bad.v +++ b/test_regress/t/t_number_bad.v @@ -10,4 +10,7 @@ module t (/*AUTOARG*/); parameter integer FOO3 = 32'd; parameter integer FOO4 = 32'h; + parameter integer FOO5 = 32'b2; + parameter integer FOO6 = 32'o8; + endmodule diff --git a/test_regress/t/t_vlcov_flag_invalid_bad.out b/test_regress/t/t_vlcov_flag_invalid_bad.out new file mode 100644 index 000000000..54d2f3d73 --- /dev/null +++ b/test_regress/t/t_vlcov_flag_invalid_bad.out @@ -0,0 +1 @@ +%Error: Invalid option: --invalid-dash diff --git a/test_regress/t/t_vlcov_flag_invalid_bad.pl b/test_regress/t/t_vlcov_flag_invalid_bad.pl new file mode 100755 index 000000000..c89584f1b --- /dev/null +++ b/test_regress/t/t_vlcov_flag_invalid_bad.pl @@ -0,0 +1,22 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 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 + +scenarios(vlt => 1); + +run(cmd => ["../bin/verilator_coverage", '--invalid-dash'], + logfile => $Self->{run_log_filename}, + fails => 1, + expect_filename => $Self->{golden_filename}, + verilator_run => 1, + ); + +ok(1); + +1;