Internal code coverage improvements. No functional change intended.

This commit is contained in:
Wilson Snyder 2020-05-23 10:34:58 -04:00
parent c18b0eb122
commit 6a882f9dc6
20 changed files with 83 additions and 51 deletions

View File

@ -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

View File

@ -40,7 +40,7 @@
// Threaded tracing
// A simple synchronized first in first out queue
template <class T> class VerilatedThreadQueue {
template <class T> 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:
//=========================================================================

View File

@ -194,13 +194,14 @@ template <> void VerilatedTrace<VL_DERIVED_T>::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<VL_DERIVED_T>::set_time_resolution(const std::st
template <> void VerilatedTrace<VL_DERIVED_T>::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<VL_DERIVED_T>::addCallbackRecord(std::vector<CallbackRecord>& 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);
}

View File

@ -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
}
}
}

View File

@ -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;

View File

@ -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(

View File

@ -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));
}

View File

@ -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++) {

View File

@ -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;

View File

@ -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;
}

View File

@ -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 {

View File

@ -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;
}

View File

@ -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
}
}
}

View File

@ -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,

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1 @@
%Error: Invalid option: --invalid-dash

View File

@ -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;