Support expression coverage (#5719)
This commit is contained in:
parent
fe15171649
commit
34ced254c0
|
@ -328,6 +328,8 @@ detailed descriptions of these arguments.
|
|||
--compiler-include Include additional header in the precompiled one
|
||||
--converge-limit <loops> Tune convergence settle time
|
||||
--coverage Enable all coverage
|
||||
--coverage-expr Enable expression coverage
|
||||
--coverage-expr-max <value> Maximum permutations allowed for an expression
|
||||
--coverage-line Enable line coverage
|
||||
--coverage-max-width <width> Maximum array depth for coverage
|
||||
--coverage-toggle Enable toggle coverage
|
||||
|
|
|
@ -237,7 +237,17 @@ Summary:
|
|||
.. option:: --coverage
|
||||
|
||||
Enables all forms of coverage, an alias for :vlopt:`--coverage-line`
|
||||
:vlopt:`--coverage-toggle` :vlopt:`--coverage-user`.
|
||||
:vlopt:`--coverage-toggle :vlopt:`--coverage-expr`` :vlopt:`--coverage-user`.
|
||||
|
||||
.. option:: --coverage-expr
|
||||
|
||||
Enables expression coverage analysis. See :ref:`Expression Coverage`.
|
||||
|
||||
.. option:: --coverage-expr-max <value>
|
||||
|
||||
Rarely needed. Specifies the maximum number of permutations able to be
|
||||
covered for a given expression. Defaults to 32. Increasing may slow
|
||||
coverage simulations and make analyzing the results unwieldy.
|
||||
|
||||
.. option:: --coverage-line
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ to read multiple inputs. If no data file is specified, by default,
|
|||
Specifies the directory name to which source files with annotated coverage
|
||||
data should be written.
|
||||
|
||||
Points are children of each line coverage- branches or toggle points.
|
||||
Points are children of each line coverage- branches, expressions or toggle points.
|
||||
When point counts are aggregated into a line, the minimum and maximum counts
|
||||
are used to determine the status of the line (complete, partial, failing)
|
||||
The count is equal to the maximum of the points.
|
||||
|
|
|
@ -270,6 +270,41 @@ A :option:`/*verilator&32;coverage_off*/`
|
|||
signals that do not need toggle analysis, such as RAMs and register files.
|
||||
|
||||
|
||||
.. _Expression Coverage:
|
||||
|
||||
Expression Coverage
|
||||
-------------
|
||||
|
||||
With :vlopt:`--coverage` or :vlopt:`--coverage-expr`, Verilator will
|
||||
automatically add coverage analysis at each expression, indicating with
|
||||
a truth table how every Boolean truth-table possiblity in the expression occurred.
|
||||
|
||||
Multi-bit expressions are ignored, but sub-expressions with are entirely
|
||||
Boolean are analyzed. Expression coverage does not fully explore the truth
|
||||
table of an expression, rather is looks at each term's contribution. E.g.
|
||||
an AND operation will check coverage for TT, XF and FX.
|
||||
|
||||
Some expressions may produce too many cover points. Verilator limits the
|
||||
maximum number of cover poitns per expression to 32, but this may be
|
||||
controlled with :vlopt:`--coverage-expr-max`.
|
||||
|
||||
Below is an example showing expression coverage produced from `verilator_coverage`
|
||||
as applied to the condition expression inside an if statement. Each line
|
||||
shows the minimum number of terms and their values (e.g. `(t1==0 && t2==1)`) needed
|
||||
to reach a result for the overall expression (e.g. `=> 1`). Each line also
|
||||
shows the number of times this combination was hit. Note that individual lines
|
||||
are not mutually exclusive.
|
||||
|
||||
.. code-block::
|
||||
|
||||
%000004 if ((~t1 && t2) || (~t3 && t4)) $write("");
|
||||
-000002 point: comment=(t1==0 && t2==1) => 1 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t3==1) => 0 hier=top.t
|
||||
-000004 point: comment=(t1==1 && t4==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t2==0 && t3==1) => 0 hier=top.t
|
||||
-000003 point: comment=(t2==0 && t4==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t3==0 && t4==1) => 1 hier=top.t
|
||||
|
||||
.. _Suppressing Coverage:
|
||||
|
||||
Suppressing Coverage
|
||||
|
|
|
@ -28,6 +28,9 @@
|
|||
|
||||
#include "V3Coverage.h"
|
||||
|
||||
#include "V3EmitV.h"
|
||||
|
||||
#include <list>
|
||||
#include <unordered_map>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
@ -39,6 +42,18 @@ class CoverageVisitor final : public VNVisitor {
|
|||
// TYPES
|
||||
using LinenoSet = std::set<int>;
|
||||
|
||||
struct CoverTerm final {
|
||||
AstNodeExpr* m_exprp; // Expression branch term
|
||||
bool m_objective; // Term objective
|
||||
std::string m_emitV; // V3EmitV string for cover point comment
|
||||
CoverTerm(AstNodeExpr* exprp, bool objective, const string& emitV)
|
||||
: m_exprp{exprp}
|
||||
, m_objective{objective}
|
||||
, m_emitV(emitV) {}
|
||||
};
|
||||
using CoverExpr = std::deque<CoverTerm>;
|
||||
using CoverExprs = std::list<CoverExpr>;
|
||||
|
||||
struct ToggleEnt final {
|
||||
const string m_comment; // Comment for coverage dump
|
||||
AstNodeExpr* m_varRefp; // How to get to this element
|
||||
|
@ -64,12 +79,20 @@ class CoverageVisitor final : public VNVisitor {
|
|||
return m_on && !m_inModOff && nodep->fileline()->coverageOn()
|
||||
&& v3Global.opt.coverageLine();
|
||||
}
|
||||
bool exprCoverageOn(const AstNode* nodep) const {
|
||||
return m_on && !m_inModOff && nodep->fileline()->coverageOn()
|
||||
&& v3Global.opt.coverageExpr();
|
||||
}
|
||||
};
|
||||
|
||||
enum Objective : uint8_t { NONE, SEEKING, ABORTED };
|
||||
|
||||
// NODE STATE
|
||||
// Entire netlist:
|
||||
// AstIf::user1() -> bool. True indicates ifelse processed
|
||||
// AstIf::user2() -> bool. True indicates coverage-generated
|
||||
const VNUser1InUse m_inuser1;
|
||||
const VNUser2InUse m_inuser2;
|
||||
|
||||
// STATE - across all visitors
|
||||
int m_nextHandle = 0;
|
||||
|
@ -77,6 +100,13 @@ class CoverageVisitor final : public VNVisitor {
|
|||
// STATE - for current visit position (use VL_RESTORER)
|
||||
CheckState m_state; // State save-restored on each new coverage scope/block
|
||||
AstNodeModule* m_modp = nullptr; // Current module to add statement to
|
||||
AstNode* m_exprStmtsp = nullptr; // Node to add expr coverage to
|
||||
bool m_then = false; // Whether we're iterating the then or else branch
|
||||
// when m_exprStmtps is an AstIf
|
||||
CoverExprs m_exprs; // List of expressions that can reach objective
|
||||
Objective m_seeking = NONE; // Seeking objective for expression coverage
|
||||
bool m_objective = false; // Expression objective
|
||||
bool m_ifCond = false; // Visiting if condition
|
||||
bool m_inToggleOff = false; // In function/task etc
|
||||
string m_beginHier; // AstBegin hier name for user coverage points
|
||||
|
||||
|
@ -160,7 +190,7 @@ class CoverageVisitor final : public VNVisitor {
|
|||
UINFO(9, "line create h" << m_state.m_handle << " " << nodep << endl);
|
||||
}
|
||||
void lineTrack(const AstNode* nodep) {
|
||||
if (m_state.lineCoverageOn(nodep)
|
||||
if (m_state.lineCoverageOn(nodep) && !m_ifCond
|
||||
&& m_state.m_nodep->fileline()->filenameno() == nodep->fileline()->filenameno()) {
|
||||
for (int lineno = nodep->fileline()->firstLineno();
|
||||
lineno <= nodep->fileline()->lastLineno(); ++lineno) {
|
||||
|
@ -222,13 +252,36 @@ class CoverageVisitor final : public VNVisitor {
|
|||
}
|
||||
|
||||
void visit(AstNodeProcedure* nodep) override { iterateProcedure(nodep); }
|
||||
void visit(AstWhile* nodep) override { iterateProcedure(nodep); }
|
||||
// we can cover expressions in while loops, but the counting goes outside
|
||||
// the while, see: "minimally-intelligent decision about ... clock domain"
|
||||
// in the Toggle Coverage docs
|
||||
void visit(AstWhile* nodep) override { iterateProcedure(nodep, false); }
|
||||
void visit(AstNodeFTask* nodep) override {
|
||||
if (!nodep->dpiImport()) iterateProcedure(nodep);
|
||||
}
|
||||
void iterateProcedure(AstNode* nodep) {
|
||||
|
||||
void insertProcStatement(AstNode* nodep, AstNode* stmtp) {
|
||||
if (AstNodeProcedure* const itemp = VN_CAST(nodep, NodeProcedure)) {
|
||||
itemp->addStmtsp(stmtp);
|
||||
} else if (AstNodeFTask* const itemp = VN_CAST(nodep, NodeFTask)) {
|
||||
itemp->addStmtsp(stmtp);
|
||||
} else if (AstWhile* const itemp = VN_CAST(nodep, While)) {
|
||||
itemp->addStmtsp(stmtp);
|
||||
} else if (AstIf* const itemp = VN_CAST(nodep, If)) {
|
||||
if (m_then) {
|
||||
itemp->addThensp(stmtp);
|
||||
} else {
|
||||
itemp->addElsesp(stmtp);
|
||||
}
|
||||
} else {
|
||||
nodep->v3fatalSrc("Bad node type");
|
||||
}
|
||||
}
|
||||
void iterateProcedure(AstNode* nodep, bool exprProc = true) {
|
||||
VL_RESTORER(m_state);
|
||||
VL_RESTORER(m_exprStmtsp);
|
||||
VL_RESTORER(m_inToggleOff);
|
||||
if (exprProc) m_exprStmtsp = nodep;
|
||||
m_inToggleOff = true;
|
||||
createHandle(nodep);
|
||||
iterateChildren(nodep);
|
||||
|
@ -237,15 +290,7 @@ class CoverageVisitor final : public VNVisitor {
|
|||
AstNode* const newp
|
||||
= newCoverInc(nodep->fileline(), "", "v_line", "block", linesCov(m_state, nodep),
|
||||
0, traceNameForLine(nodep, "block"));
|
||||
if (AstNodeProcedure* const itemp = VN_CAST(nodep, NodeProcedure)) {
|
||||
itemp->addStmtsp(newp);
|
||||
} else if (AstNodeFTask* const itemp = VN_CAST(nodep, NodeFTask)) {
|
||||
itemp->addStmtsp(newp);
|
||||
} else if (AstWhile* const itemp = VN_CAST(nodep, While)) {
|
||||
itemp->addStmtsp(newp);
|
||||
} else {
|
||||
nodep->v3fatalSrc("Bad node type");
|
||||
}
|
||||
insertProcStatement(nodep, newp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -404,6 +449,8 @@ class CoverageVisitor final : public VNVisitor {
|
|||
// VISITORS - LINE COVERAGE
|
||||
// Note not AstNodeIf; other types don't get covered
|
||||
void visit(AstIf* nodep) override {
|
||||
if (nodep->user2()) return;
|
||||
|
||||
UINFO(4, " IF: " << nodep << endl);
|
||||
if (m_state.m_on) {
|
||||
// An else-if. When we iterate the if, use "elsif" marking
|
||||
|
@ -422,6 +469,10 @@ class CoverageVisitor final : public VNVisitor {
|
|||
CheckState ifState;
|
||||
CheckState elseState;
|
||||
{
|
||||
VL_RESTORER(m_exprStmtsp);
|
||||
VL_RESTORER(m_then);
|
||||
m_exprStmtsp = nodep;
|
||||
m_then = true;
|
||||
createHandle(nodep);
|
||||
iterateAndNextNull(nodep->thensp());
|
||||
lineTrack(nodep);
|
||||
|
@ -429,6 +480,10 @@ class CoverageVisitor final : public VNVisitor {
|
|||
}
|
||||
m_state = lastState;
|
||||
{
|
||||
VL_RESTORER(m_exprStmtsp);
|
||||
VL_RESTORER(m_then);
|
||||
m_exprStmtsp = nodep;
|
||||
m_then = false;
|
||||
createHandle(nodep);
|
||||
iterateAndNextNull(nodep->elsesp());
|
||||
elseState = m_state;
|
||||
|
@ -478,6 +533,9 @@ class CoverageVisitor final : public VNVisitor {
|
|||
}
|
||||
m_state = lastState;
|
||||
}
|
||||
VL_RESTORER(m_ifCond);
|
||||
m_ifCond = true;
|
||||
iterateAndNextNull(nodep->condp());
|
||||
UINFO(9, " done HANDLE " << m_state.m_handle << " for " << nodep << endl);
|
||||
}
|
||||
void visit(AstCaseItem* nodep) override {
|
||||
|
@ -542,6 +600,301 @@ class CoverageVisitor final : public VNVisitor {
|
|||
lineTrack(nodep);
|
||||
}
|
||||
|
||||
void abortExprCoverage() {
|
||||
// is possible to hit max while in NONE, see: exprReduce()
|
||||
// if that happens we don't want to set ABORTED if it isn't already
|
||||
// since that will bleed into other expressions
|
||||
if (m_seeking != NONE) m_seeking = ABORTED;
|
||||
m_exprs.clear();
|
||||
}
|
||||
|
||||
bool checkMaxExprs(size_t additional = 0) {
|
||||
if (m_seeking != ABORTED
|
||||
&& static_cast<int>(m_exprs.size() + additional) <= v3Global.opt.coverageExprMax())
|
||||
return false;
|
||||
abortExprCoverage();
|
||||
return true;
|
||||
}
|
||||
|
||||
void addExprCoverInc(AstNodeExpr* nodep, int start = 0) {
|
||||
FileLine* const fl = nodep->fileline();
|
||||
int count = start;
|
||||
for (CoverExpr& expr : m_exprs) {
|
||||
const string name = "expr_" + std::to_string(count);
|
||||
string comment = "(";
|
||||
bool first = true;
|
||||
AstNodeExpr* condp = nullptr;
|
||||
for (CoverTerm& term : expr) {
|
||||
comment += (first ? "" : " && ") + term.m_emitV
|
||||
+ "==" + (term.m_objective ? "1" : "0");
|
||||
AstNodeExpr* const clonep = term.m_exprp->cloneTree(true);
|
||||
AstNodeExpr* const termp = term.m_objective ? clonep : new AstLogNot{fl, clonep};
|
||||
if (condp) {
|
||||
condp = new AstLogAnd{fl, condp, termp};
|
||||
} else {
|
||||
condp = termp;
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
comment += ") => ";
|
||||
comment += (m_objective ? '1' : '0');
|
||||
AstNode* const newp
|
||||
= newCoverInc(fl, "", "v_expr", comment, "", 0, traceNameForLine(nodep, name));
|
||||
UASSERT_OBJ(condp, nodep, "No terms in expression coverage branch");
|
||||
AstIf* const ifp = new AstIf{fl, condp, newp, nullptr};
|
||||
ifp->user2(true);
|
||||
insertProcStatement(m_exprStmtsp, ifp);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
void coverExprs(AstNodeExpr* nodep) {
|
||||
if (!m_state.exprCoverageOn(nodep) || nodep->dtypep()->width() != 1 || !m_exprStmtsp) {
|
||||
return;
|
||||
}
|
||||
|
||||
UASSERT_OBJ(m_seeking == NONE, nodep, "recursively covering expressions is not expected");
|
||||
UASSERT_OBJ(m_exprs.empty(), nodep, "unexpected expression coverage garbage");
|
||||
VL_RESTORER(m_seeking);
|
||||
VL_RESTORER(m_objective);
|
||||
VL_RESTORER(m_exprs);
|
||||
|
||||
m_seeking = SEEKING;
|
||||
m_objective = false;
|
||||
iterate(nodep);
|
||||
CoverExprs falseExprs;
|
||||
m_exprs.swap(falseExprs);
|
||||
|
||||
m_objective = true;
|
||||
iterate(nodep);
|
||||
if (checkMaxExprs(falseExprs.size())) return;
|
||||
|
||||
addExprCoverInc(nodep);
|
||||
const int start = m_exprs.size();
|
||||
m_objective = false;
|
||||
m_exprs.swap(falseExprs);
|
||||
addExprCoverInc(nodep, start);
|
||||
}
|
||||
|
||||
void exprEither(AstNodeBiop* nodep, bool overrideObjective = false, bool lObjective = false,
|
||||
bool rObjective = false) {
|
||||
VL_RESTORER(m_objective);
|
||||
AstNodeExpr* const lhsp = nodep->lhsp();
|
||||
AstNodeExpr* const rhsp = nodep->rhsp();
|
||||
|
||||
if (overrideObjective) m_objective = lObjective;
|
||||
iterate(lhsp);
|
||||
if (checkMaxExprs()) return;
|
||||
CoverExprs lhsExprs;
|
||||
m_exprs.swap(lhsExprs);
|
||||
if (overrideObjective) m_objective = rObjective;
|
||||
iterate(rhsp);
|
||||
m_exprs.splice(m_exprs.end(), lhsExprs);
|
||||
checkMaxExprs();
|
||||
}
|
||||
|
||||
void exprBoth(AstNodeBiop* nodep, bool overrideObjective = false, bool lObjective = false,
|
||||
bool rObjective = false) {
|
||||
VL_RESTORER(m_objective);
|
||||
AstNodeExpr* const lhsp = nodep->lhsp();
|
||||
AstNodeExpr* const rhsp = nodep->rhsp();
|
||||
|
||||
if (overrideObjective) m_objective = lObjective;
|
||||
iterate(lhsp);
|
||||
if (checkMaxExprs()) return;
|
||||
CoverExprs lhsExprs;
|
||||
m_exprs.swap(lhsExprs);
|
||||
if (overrideObjective) m_objective = rObjective;
|
||||
iterate(rhsp);
|
||||
if (checkMaxExprs()) return;
|
||||
CoverExprs rhsExprs;
|
||||
m_exprs.swap(rhsExprs);
|
||||
|
||||
for (CoverExpr& l : lhsExprs) {
|
||||
for (CoverExpr& r : rhsExprs) {
|
||||
// array size 2 -> (false, true)
|
||||
std::array<std::set<AstVar*>, 2> varps;
|
||||
std::array<std::set<std::string>, 2> strs;
|
||||
|
||||
UASSERT_OBJ(!l.empty() && !r.empty(), nodep, "Empty coverage expression branch");
|
||||
CoverExpr expr;
|
||||
|
||||
// Compare Vars for simple VarRefs otherwise compare stringified terms
|
||||
// remove redundant terms and remove entire expression branches when
|
||||
// terms conflict
|
||||
// Equivalent terms which don't match on either of these criteria will
|
||||
// not be flagged as redundant or impossible, however the results will
|
||||
// still be valid, albeit messier
|
||||
for (CoverTerm& term : l) {
|
||||
if (AstNodeVarRef* const refp = VN_CAST(term.m_exprp, NodeVarRef)) {
|
||||
varps[term.m_objective].insert(refp->varp());
|
||||
} else {
|
||||
strs[term.m_objective].insert(term.m_emitV);
|
||||
}
|
||||
expr.push_back(term);
|
||||
}
|
||||
bool impossible = false;
|
||||
for (CoverTerm& term : r) {
|
||||
bool redundant = false;
|
||||
if (AstNodeVarRef* const refp = VN_CAST(term.m_exprp, NodeVarRef)) {
|
||||
if (varps[term.m_objective].find(refp->varp())
|
||||
!= varps[term.m_objective].end())
|
||||
redundant = true;
|
||||
if (varps[!term.m_objective].find(refp->varp())
|
||||
!= varps[!term.m_objective].end())
|
||||
impossible = true;
|
||||
} else {
|
||||
if (strs[term.m_objective].find(term.m_emitV)
|
||||
!= strs[term.m_objective].end())
|
||||
redundant = true;
|
||||
if (strs[!term.m_objective].find(term.m_emitV)
|
||||
!= strs[!term.m_objective].end())
|
||||
impossible = true;
|
||||
}
|
||||
|
||||
if (!redundant) expr.push_back(term);
|
||||
}
|
||||
if (!impossible) m_exprs.push_back(std::move(expr));
|
||||
if (checkMaxExprs()) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void orExpr(AstNodeBiop* nodep) {
|
||||
if (m_seeking == NONE) {
|
||||
coverExprs(nodep);
|
||||
} else if (m_objective) {
|
||||
exprEither(nodep);
|
||||
} else {
|
||||
exprBoth(nodep);
|
||||
}
|
||||
lineTrack(nodep);
|
||||
}
|
||||
void visit(AstLogOr* nodep) override { orExpr(nodep); }
|
||||
void visit(AstOr* nodep) override { orExpr(nodep); }
|
||||
|
||||
void andExpr(AstNodeBiop* nodep) {
|
||||
if (m_seeking == NONE) {
|
||||
coverExprs(nodep);
|
||||
} else if (m_objective) {
|
||||
exprBoth(nodep);
|
||||
} else {
|
||||
exprEither(nodep);
|
||||
}
|
||||
lineTrack(nodep);
|
||||
}
|
||||
void visit(AstLogAnd* nodep) override { andExpr(nodep); }
|
||||
void visit(AstAnd* nodep) override { andExpr(nodep); }
|
||||
|
||||
void xorExpr(AstNodeBiop* nodep) {
|
||||
if (m_seeking == NONE) {
|
||||
coverExprs(nodep);
|
||||
} else {
|
||||
for (const bool lObjective : {false, true}) {
|
||||
CoverExprs prevExprs;
|
||||
m_exprs.swap(prevExprs);
|
||||
const bool rObjective = lObjective ^ m_objective;
|
||||
exprBoth(nodep, true, lObjective, rObjective);
|
||||
m_exprs.splice(m_exprs.end(), prevExprs);
|
||||
if (checkMaxExprs()) break;
|
||||
}
|
||||
}
|
||||
lineTrack(nodep);
|
||||
}
|
||||
void visit(AstXor* nodep) override { xorExpr(nodep); }
|
||||
|
||||
void exprNot(AstNodeExpr* nodep) {
|
||||
VL_RESTORER(m_objective);
|
||||
if (m_seeking == NONE) {
|
||||
coverExprs(nodep);
|
||||
} else {
|
||||
m_objective = !m_objective;
|
||||
iterateChildren(nodep);
|
||||
lineTrack(nodep);
|
||||
}
|
||||
}
|
||||
void visit(AstNot* nodep) override { exprNot(nodep); }
|
||||
void visit(AstLogNot* nodep) override { exprNot(nodep); }
|
||||
|
||||
template <typename T_Oper>
|
||||
void exprReduce(AstNodeUniop* nodep) {
|
||||
if (m_seeking != ABORTED) {
|
||||
FileLine* const fl = nodep->fileline();
|
||||
AstNodeExpr* const lhsp = nodep->lhsp();
|
||||
const int width = lhsp->dtypep()->width();
|
||||
const size_t expected = std::is_same<T_Oper, AstXor>::value ? 0x1 << width : width + 1;
|
||||
if (checkMaxExprs(expected)) return;
|
||||
AstNodeExpr* unrolledp = new AstSel{fl, lhsp->cloneTree(true),
|
||||
new AstConst{fl, static_cast<uint32_t>(width - 1)},
|
||||
new AstConst{fl, 1}};
|
||||
for (int bit = width - 2; bit >= 0; bit--) {
|
||||
AstSel* const selp = new AstSel{fl, lhsp->cloneTree(true),
|
||||
new AstConst{fl, static_cast<uint32_t>(bit)},
|
||||
new AstConst{fl, 1}};
|
||||
unrolledp = new T_Oper{fl, selp, unrolledp};
|
||||
}
|
||||
iterate(unrolledp);
|
||||
pushDeletep(unrolledp);
|
||||
} else {
|
||||
iterateChildren(nodep);
|
||||
lineTrack(nodep);
|
||||
}
|
||||
}
|
||||
void visit(AstRedOr* nodep) override { exprReduce<AstOr>(nodep); }
|
||||
void visit(AstRedAnd* nodep) override { exprReduce<AstAnd>(nodep); }
|
||||
void visit(AstRedXor* nodep) override { exprReduce<AstXor>(nodep); }
|
||||
|
||||
void visit(AstLogIf* nodep) override {
|
||||
if (m_seeking == NONE) {
|
||||
coverExprs(nodep);
|
||||
} else if (m_objective) {
|
||||
exprEither(nodep, true, false, true);
|
||||
} else {
|
||||
exprBoth(nodep, true, true, false);
|
||||
}
|
||||
lineTrack(nodep);
|
||||
}
|
||||
|
||||
void visit(AstLogEq* nodep) override {
|
||||
VL_RESTORER(m_objective);
|
||||
if (m_seeking == NONE) {
|
||||
coverExprs(nodep);
|
||||
} else {
|
||||
m_objective = !m_objective;
|
||||
xorExpr(nodep);
|
||||
lineTrack(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
void visit(AstCond* nodep) override {
|
||||
if (m_seeking == NONE) coverExprs(nodep->condp());
|
||||
lineTrack(nodep);
|
||||
}
|
||||
|
||||
// Lambdas not supported for expression coverage
|
||||
void visit(AstWith* nodep) override {
|
||||
VL_RESTORER(m_seeking);
|
||||
if (m_seeking == SEEKING) abortExprCoverage();
|
||||
m_seeking = ABORTED;
|
||||
iterateChildren(nodep);
|
||||
lineTrack(nodep);
|
||||
}
|
||||
|
||||
void visit(AstNodeExpr* nodep) override {
|
||||
if (m_seeking != SEEKING) {
|
||||
iterateChildren(nodep);
|
||||
} else {
|
||||
std::stringstream emitV;
|
||||
V3EmitV::verilogForTree(nodep, emitV);
|
||||
// Add new expression with a single term
|
||||
CoverExpr expr;
|
||||
expr.emplace_back(nodep, m_objective, emitV.str());
|
||||
m_exprs.push_back(std::move(expr));
|
||||
checkMaxExprs();
|
||||
}
|
||||
lineTrack(nodep);
|
||||
}
|
||||
|
||||
// VISITORS - BOTH
|
||||
void visit(AstNode* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
|
|
|
@ -1238,6 +1238,8 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
|
|||
DECL_OPTION("-compiler-include", CbVal, callStrSetter(&V3Options::addCompilerIncludes));
|
||||
DECL_OPTION("-converge-limit", Set, &m_convergeLimit);
|
||||
DECL_OPTION("-coverage", CbOnOff, [this](bool flag) { coverage(flag); });
|
||||
DECL_OPTION("-coverage-expr", OnOff, &m_coverageExpr);
|
||||
DECL_OPTION("-coverage-expr-max", Set, &m_coverageExprMax);
|
||||
DECL_OPTION("-coverage-line", OnOff, &m_coverageLine);
|
||||
DECL_OPTION("-coverage-max-width", Set, &m_coverageMaxWidth);
|
||||
DECL_OPTION("-coverage-toggle", OnOff, &m_coverageToggle);
|
||||
|
|
|
@ -230,6 +230,7 @@ private:
|
|||
bool m_build = false; // main switch: --build
|
||||
bool m_cmake = false; // main switch: --make cmake
|
||||
bool m_context = true; // main switch: --Wcontext
|
||||
bool m_coverageExpr = false; // main switch: --coverage-expr
|
||||
bool m_coverageLine = false; // main switch: --coverage-block
|
||||
bool m_coverageToggle = false; // main switch: --coverage-toggle
|
||||
bool m_coverageUnderscore = false; // main switch: --coverage-underscore
|
||||
|
@ -305,6 +306,7 @@ private:
|
|||
bool m_xmlOnly = false; // main switch: --xml-only
|
||||
|
||||
int m_buildJobs = -1; // main switch: --build-jobs, -j
|
||||
int m_coverageExprMax = 32; // main switch: --coverage-expr-max
|
||||
int m_convergeLimit = 100; // main switch: --converge-limit
|
||||
int m_coverageMaxWidth = 256; // main switch: --coverage-max-width
|
||||
int m_expandLimit = 64; // main switch: --expand-limit
|
||||
|
@ -426,7 +428,9 @@ private:
|
|||
void addLibExtV(const string& libext);
|
||||
void optimize(int level);
|
||||
void showVersion(bool verbose);
|
||||
void coverage(bool flag) { m_coverageLine = m_coverageToggle = m_coverageUser = flag; }
|
||||
void coverage(bool flag) {
|
||||
m_coverageLine = m_coverageToggle = m_coverageExpr = m_coverageUser = flag;
|
||||
}
|
||||
static bool suffixed(const string& sw, const char* arg);
|
||||
static string parseFileArg(const string& optdir, const string& relfilename);
|
||||
string filePathCheckOneDir(const string& modname, const string& dirname);
|
||||
|
@ -488,8 +492,9 @@ public:
|
|||
bool cmake() const { return m_cmake; }
|
||||
bool context() const VL_MT_SAFE { return m_context; }
|
||||
bool coverage() const VL_MT_SAFE {
|
||||
return m_coverageLine || m_coverageToggle || m_coverageUser;
|
||||
return m_coverageLine || m_coverageToggle || m_coverageExpr || m_coverageUser;
|
||||
}
|
||||
bool coverageExpr() const { return m_coverageExpr; }
|
||||
bool coverageLine() const { return m_coverageLine; }
|
||||
bool coverageToggle() const { return m_coverageToggle; }
|
||||
bool coverageUnderscore() const { return m_coverageUnderscore; }
|
||||
|
@ -565,6 +570,7 @@ public:
|
|||
|
||||
int buildJobs() const VL_MT_SAFE { return m_buildJobs; }
|
||||
int convergeLimit() const { return m_convergeLimit; }
|
||||
int coverageExprMax() const { return m_coverageExprMax; }
|
||||
int coverageMaxWidth() const { return m_coverageMaxWidth; }
|
||||
bool dumpTreeAddrids() const VL_MT_SAFE;
|
||||
int expandLimit() const { return m_expandLimit; }
|
||||
|
|
|
@ -0,0 +1,317 @@
|
|||
// // 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;
|
||||
|
||||
integer cyc;
|
||||
initial cyc=1;
|
||||
|
||||
integer some_int;
|
||||
integer other_int;
|
||||
logic some_bool;
|
||||
|
||||
wire t1 = cyc[0];
|
||||
wire t2 = cyc[1];
|
||||
wire t3 = cyc[2];
|
||||
wire t4 = cyc[3];
|
||||
|
||||
localparam bit ONE = 1'b1;
|
||||
localparam bit ZERO = 1'b0;
|
||||
|
||||
function automatic bit invert(bit x);
|
||||
000015 return ~x;
|
||||
+000012 point: comment=(x==0) => 1 hier=top.t
|
||||
+000015 point: comment=(x==1) => 0 hier=top.t
|
||||
endfunction
|
||||
|
||||
function automatic bit and_oper(bit a, bit b);
|
||||
%000005 return a & b;
|
||||
-000004 point: comment=(a==0) => 0 hier=top.t
|
||||
-000002 point: comment=(a==1 && b==1) => 1 hier=top.t
|
||||
-000005 point: comment=(b==0) => 0 hier=top.t
|
||||
endfunction
|
||||
|
||||
always @ (posedge clk) begin
|
||||
cyc <= cyc + 1;
|
||||
%000004 if ((~cyc[0] && cyc[1]) || (~cyc[2] && cyc[3])) $write("");
|
||||
-000002 point: comment=(cyc[0]==0 && cyc[1]==1) => 1 hier=top.t
|
||||
-000002 point: comment=(cyc[0]==1 && cyc[2]==1) => 0 hier=top.t
|
||||
-000004 point: comment=(cyc[0]==1 && cyc[3]==0) => 0 hier=top.t
|
||||
-000002 point: comment=(cyc[1]==0 && cyc[2]==1) => 0 hier=top.t
|
||||
-000003 point: comment=(cyc[1]==0 && cyc[3]==0) => 0 hier=top.t
|
||||
-000002 point: comment=(cyc[2]==0 && cyc[3]==1) => 1 hier=top.t
|
||||
%000004 if ((~t1 && t2) || (~t3 && t4)) $write("");
|
||||
-000002 point: comment=(t1==0 && t2==1) => 1 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t3==1) => 0 hier=top.t
|
||||
-000004 point: comment=(t1==1 && t4==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t2==0 && t3==1) => 0 hier=top.t
|
||||
-000003 point: comment=(t2==0 && t4==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t3==0 && t4==1) => 1 hier=top.t
|
||||
%000005 if (t3 && (t1 == t2)) $write("");
|
||||
-000005 point: comment=((t1 == t2)==0) => 0 hier=top.t
|
||||
-000005 point: comment=(t3==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t3==1 && (t1 == t2)==1) => 1 hier=top.t
|
||||
%000005 if (123 == (124 - 32'(t1 || t2))) $write("");
|
||||
-000002 point: comment=(t1==0 && t2==0) => 0 hier=top.t
|
||||
-000005 point: comment=(t1==1) => 1 hier=top.t
|
||||
-000004 point: comment=(t2==1) => 1 hier=top.t
|
||||
%000004 some_int <= (t2 || t3) ? 345 : 567;
|
||||
-000003 point: comment=(t2==0 && t3==0) => 0 hier=top.t
|
||||
-000004 point: comment=(t2==1) => 1 hier=top.t
|
||||
-000004 point: comment=(t3==1) => 1 hier=top.t
|
||||
%000005 some_bool <= t1 && t2;
|
||||
-000004 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t2==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
%000005 if (t1 & t2) $write("");
|
||||
-000004 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t2==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
%000004 if ((!t1 && t2) | (~t3 && t4)) $write("");
|
||||
-000002 point: comment=(t1==0 && t2==1) => 1 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t3==1) => 0 hier=top.t
|
||||
-000004 point: comment=(t1==1 && t4==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t2==0 && t3==1) => 0 hier=top.t
|
||||
-000003 point: comment=(t2==0 && t4==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t3==0 && t4==1) => 1 hier=top.t
|
||||
%000003 if (t1 ^ t2) $write("");
|
||||
-000002 point: comment=(t1==0 && t2==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t1==0 && t2==1) => 1 hier=top.t
|
||||
-000003 point: comment=(t1==1 && t2==0) => 1 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t2==1) => 0 hier=top.t
|
||||
%000005 if (~(t1 & t2)) $write("");
|
||||
-000004 point: comment=(t1==0) => 1 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t2==1) => 0 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 1 hier=top.t
|
||||
%000004 if (t1 -> t2) $write("");
|
||||
-000004 point: comment=(t1==0) => 1 hier=top.t
|
||||
-000003 point: comment=(t1==1 && t2==0) => 0 hier=top.t
|
||||
-000004 point: comment=(t2==1) => 1 hier=top.t
|
||||
%000003 if (t1 <-> t2) $write("");
|
||||
-000002 point: comment=(t1==0 && t2==0) => 1 hier=top.t
|
||||
-000002 point: comment=(t1==0 && t2==1) => 0 hier=top.t
|
||||
-000003 point: comment=(t1==1 && t2==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t2==1) => 1 hier=top.t
|
||||
%000005 if (&cyc[2:0]) $write("");
|
||||
-000004 point: comment=(cyc[2:0][0]==0) => 0 hier=top.t
|
||||
-000001 point: comment=(cyc[2:0][0]==1 && cyc[2:0][1]==1 && cyc[2:0][2]==1) => 1 hier=top.t
|
||||
-000005 point: comment=(cyc[2:0][1]==0) => 0 hier=top.t
|
||||
-000005 point: comment=(cyc[2:0][2]==0) => 0 hier=top.t
|
||||
%000007 if (&cyc[3:2]) $write("");
|
||||
-000005 point: comment=(cyc[3:2][0]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[3:2][0]==1 && cyc[3:2][1]==1) => 1 hier=top.t
|
||||
-000007 point: comment=(cyc[3:2][1]==0) => 0 hier=top.t
|
||||
%000005 if (|cyc[2:0]) $write("");
|
||||
-000001 point: comment=(cyc[2:0][0]==0 && cyc[2:0][1]==0 && cyc[2:0][2]==0) => 0 hier=top.t
|
||||
-000005 point: comment=(cyc[2:0][0]==1) => 1 hier=top.t
|
||||
-000004 point: comment=(cyc[2:0][1]==1) => 1 hier=top.t
|
||||
-000004 point: comment=(cyc[2:0][2]==1) => 1 hier=top.t
|
||||
%000002 if (^cyc[2:0]) $write("");
|
||||
-000001 point: comment=(cyc[2:0][0]==0 && cyc[2:0][1]==0 && cyc[2:0][2]==0) => 0 hier=top.t
|
||||
-000001 point: comment=(cyc[2:0][0]==0 && cyc[2:0][1]==0 && cyc[2:0][2]==1) => 1 hier=top.t
|
||||
-000001 point: comment=(cyc[2:0][0]==0 && cyc[2:0][1]==1 && cyc[2:0][2]==0) => 1 hier=top.t
|
||||
-000001 point: comment=(cyc[2:0][0]==0 && cyc[2:0][1]==1 && cyc[2:0][2]==1) => 0 hier=top.t
|
||||
-000002 point: comment=(cyc[2:0][0]==1 && cyc[2:0][1]==0 && cyc[2:0][2]==0) => 1 hier=top.t
|
||||
-000001 point: comment=(cyc[2:0][0]==1 && cyc[2:0][1]==0 && cyc[2:0][2]==1) => 0 hier=top.t
|
||||
-000001 point: comment=(cyc[2:0][0]==1 && cyc[2:0][1]==1 && cyc[2:0][2]==0) => 0 hier=top.t
|
||||
-000001 point: comment=(cyc[2:0][0]==1 && cyc[2:0][1]==1 && cyc[2:0][2]==1) => 1 hier=top.t
|
||||
%000005 if (|cyc[2:0] || cyc[3]) $write("");
|
||||
-000000 point: comment=(cyc[2:0][0]==0 && cyc[2:0][1]==0 && cyc[2:0][2]==0 && cyc[3]==0) => 0 hier=top.t
|
||||
-000005 point: comment=(cyc[2:0][0]==1) => 1 hier=top.t
|
||||
-000004 point: comment=(cyc[2:0][1]==1) => 1 hier=top.t
|
||||
-000004 point: comment=(cyc[2:0][2]==1) => 1 hier=top.t
|
||||
-000002 point: comment=(cyc[3]==1) => 1 hier=top.t
|
||||
%000005 if (t1 & t2 & 1'b1) $write("");
|
||||
-000000 point: comment=(1'h1==0) => 0 hier=top.t
|
||||
-000004 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t2==1 && 1'h1==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
%000009 if (t1 & t2 & 1'b0) $write("");
|
||||
-000009 point: comment=(1'h0==0) => 0 hier=top.t
|
||||
-000004 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000000 point: comment=(t1==1 && t2==1 && 1'h0==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
%000005 if (t1 & t2 & ONE) $write("");
|
||||
-000000 point: comment=(ONE==0) => 0 hier=top.t
|
||||
-000004 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t2==1 && ONE==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
%000009 if (t1 & t2 & ZERO) $write("");
|
||||
-000009 point: comment=(ZERO==0) => 0 hier=top.t
|
||||
-000004 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000000 point: comment=(t1==1 && t2==1 && ZERO==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
%000005 if (t1 && t2) begin
|
||||
-000004 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t2==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
$write("");
|
||||
%000003 end else if (t1 || t2) begin
|
||||
-000002 point: comment=(t1==0 && t2==0) => 0 hier=top.t
|
||||
-000003 point: comment=(t1==1) => 1 hier=top.t
|
||||
-000002 point: comment=(t2==1) => 1 hier=top.t
|
||||
$write("");
|
||||
end
|
||||
%000005 if (invert(t1) && t2) $write("");
|
||||
-000005 point: comment=(invert(t1)==0) => 0 hier=top.t
|
||||
-000002 point: comment=(invert(t1)==1 && t2==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
if (and_oper(t1, t2)) $write("");
|
||||
%000005 if (t2 && t3) begin
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t2==1 && t3==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t3==0) => 0 hier=top.t
|
||||
%000001 if (t1 && t2) $write("");
|
||||
-000001 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000001 point: comment=(t1==1 && t2==1) => 1 hier=top.t
|
||||
-000000 point: comment=(t2==0) => 0 hier=top.t
|
||||
end
|
||||
if (0 == 1) begin
|
||||
for (int loop_var = 0; loop_var < 1; loop_var++) begin
|
||||
%000000 if (cyc[loop_var] && t2) $write("");
|
||||
-000000 point: comment=(cyc[loop_var[4:0]+:32'h1]]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[loop_var[4:0]+:32'h1]]==1 && t2==1) => 1 hier=top.t
|
||||
-000000 point: comment=(t2==0) => 0 hier=top.t
|
||||
end
|
||||
end
|
||||
// stop at the first layer even if there's more to find
|
||||
%000007 if ((cyc[3+32'(t1 && t2)+:2] == cyc[5+32'(t3 || t4)+:2]) || cyc[31]) $write("");
|
||||
-000002 point: comment=((cyc[(32'sh3 + (t1 && t2))[4:0]+:32'sh2]] == cyc[(32'sh5 + (t3 || t4))[4:0]+:32'sh2]])==0 && cyc[31]==0) => 0 hier=top.t
|
||||
-000007 point: comment=((cyc[(32'sh3 + (t1 && t2))[4:0]+:32'sh2]] == cyc[(32'sh5 + (t3 || t4))[4:0]+:32'sh2]])==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[31]==1) => 1 hier=top.t
|
||||
// impossible branches and redundant terms
|
||||
%000005 if ((t1 && t2) && ~(t1 && t3) && (t1 || t4)) $write("");
|
||||
-000003 point: comment=(t1==0 && t4==0) => 0 hier=top.t
|
||||
-000004 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000000 point: comment=(t1==1 && t2==1 && t3==0 && t4==1) => 1 hier=top.t
|
||||
-000001 point: comment=(t1==1 && t2==1 && t3==0) => 1 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t3==1) => 0 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
%000005 if ((cyc[0] && cyc[1]) && ~(cyc[0] && cyc[2]) && (cyc[0] || cyc[3])) $write("");
|
||||
-000003 point: comment=(cyc[0]==0 && cyc[3]==0) => 0 hier=top.t
|
||||
-000004 point: comment=(cyc[0]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[0]==1 && cyc[1]==1 && cyc[2]==0 && cyc[3]==1) => 1 hier=top.t
|
||||
-000001 point: comment=(cyc[0]==1 && cyc[1]==1 && cyc[2]==0) => 1 hier=top.t
|
||||
-000002 point: comment=(cyc[0]==1 && cyc[2]==1) => 0 hier=top.t
|
||||
-000005 point: comment=(cyc[1]==0) => 0 hier=top.t
|
||||
// demonstrate current limitations of term matching scheme
|
||||
%000005 if ((cyc[0] && cyc[1]) && ~(cyc[1-1] && cyc[2]) && (cyc[2-2] || cyc[3])) $write("");
|
||||
-000002 point: comment=(cyc[(32'sh1 - 32'sh1)[4:0]+:32'h1]]==1 && cyc[2]==1) => 0 hier=top.t
|
||||
-000003 point: comment=(cyc[(32'sh2 - 32'sh2)[4:0]+:32'h1]]==0 && cyc[3]==0) => 0 hier=top.t
|
||||
-000004 point: comment=(cyc[0]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[0]==1 && cyc[1]==1 && cyc[(32'sh1 - 32'sh1)[4:0]+:32'h1]]==0 && cyc[(32'sh2 - 32'sh2)[4:0]+:32'h1]]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[0]==1 && cyc[1]==1 && cyc[(32'sh1 - 32'sh1)[4:0]+:32'h1]]==0 && cyc[3]==1) => 1 hier=top.t
|
||||
-000001 point: comment=(cyc[0]==1 && cyc[1]==1 && cyc[2]==0 && cyc[(32'sh2 - 32'sh2)[4:0]+:32'h1]]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[0]==1 && cyc[1]==1 && cyc[2]==0 && cyc[3]==1) => 1 hier=top.t
|
||||
-000005 point: comment=(cyc[1]==0) => 0 hier=top.t
|
||||
//verilator coverage_off
|
||||
if (t1 && t2) $write("");
|
||||
//verilator coverage_on
|
||||
if ((~t1 && t2)
|
||||
%000004 ||
|
||||
-000002 point: comment=(t1==0 && t2==1) => 1 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t3==1) => 0 hier=top.t
|
||||
-000004 point: comment=(t1==1 && t4==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t2==0 && t3==1) => 0 hier=top.t
|
||||
-000003 point: comment=(t2==0 && t4==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t3==0 && t4==1) => 1 hier=top.t
|
||||
(~t3 && t4)) $write("");
|
||||
// intentionally testing wonkified expression terms
|
||||
if (
|
||||
cyc[
|
||||
0
|
||||
%000005 ] &
|
||||
-000004 point: comment=(cyc[0]==0) => 0 hier=top.t
|
||||
-000002 point: comment=(cyc[0]==1 && cyc[1]==1) => 1 hier=top.t
|
||||
-000005 point: comment=(cyc[1]==0) => 0 hier=top.t
|
||||
cyc
|
||||
[1]) $write("");
|
||||
// for now each ternary condition is considered in isolation
|
||||
%000005 other_int <= t1 ? t2 ? 1 : 2 : 3;
|
||||
-000004 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000005 point: comment=(t1==1) => 1 hier=top.t
|
||||
// no expression coverage for multi-bit expressions
|
||||
if ((cyc[1:0] & cyc[3:2]) == 2'b11) $write("");
|
||||
// truth table is too large
|
||||
if (^cyc[6:0]) $write("");
|
||||
// this one is too big even for t_cover_expr_max
|
||||
if (^cyc) $write("");
|
||||
if (cyc==9) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
%000005 if (t1 && t2) $write("");
|
||||
-000005 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t2==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
end
|
||||
|
||||
logic ta, tb, tc;
|
||||
initial begin
|
||||
int q[5];
|
||||
int qv[$];
|
||||
|
||||
q = '{1, 2, 2, 4, 3};
|
||||
// lambas not handled
|
||||
// NB: there is a bug w/ tracing find_first (maybe lambdas in general?)
|
||||
// tracing_off does not work around the bug
|
||||
qv = q.find_first with (item[0] & item[1]);
|
||||
ta = '1;
|
||||
tb = '0;
|
||||
tc = '0;
|
||||
%000001 while (ta || tb || tc) begin
|
||||
-000001 point: comment=(ta==0 && tb==0 && tc==0) => 0 hier=top.t
|
||||
-000000 point: comment=(ta==1) => 1 hier=top.t
|
||||
-000000 point: comment=(tb==1) => 1 hier=top.t
|
||||
-000000 point: comment=(tc==1) => 1 hier=top.t
|
||||
tc = tb;
|
||||
tb = ta;
|
||||
ta = '0;
|
||||
end
|
||||
end
|
||||
|
||||
sub the_sub_1 (.p(t1), .q(t2));
|
||||
sub the_sub_2 (.p(t3), .q(t4));
|
||||
// TODO -- non-process expressions
|
||||
sub the_sub_3 (.p(t1 ? t2 : t3), .q(t4));
|
||||
|
||||
// TODO
|
||||
// pragma for expr coverage off / on
|
||||
// investigate cover point sorting in annotated source
|
||||
// consider reporting don't care terms
|
||||
//
|
||||
// Branches which are statically impossible to reach are still reported.
|
||||
// E.g.
|
||||
// -000000 point: comment=(t1=1 && t2=1 && 1'h0=1) => 1 hier=top.t
|
||||
// These could potentially be pruned, but they currently follow suit for
|
||||
// what branch coverage does. Perhaps a switch should be added to not
|
||||
// count statically impossible things.
|
||||
|
||||
endmodule
|
||||
|
||||
module sub (
|
||||
input p,
|
||||
input q
|
||||
);
|
||||
|
||||
always_comb begin
|
||||
~000019 if (p && q) $write("");
|
||||
+000017 point: comment=(p==0) => 0 hier=top.t.the_sub_*
|
||||
-000002 point: comment=(p==1 && q==1) => 1 hier=top.t.the_sub_*
|
||||
+000019 point: comment=(q==0) => 0 hier=top.t.the_sub_*
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
#!/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
|
||||
from pathlib import Path
|
||||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.compile(verilator_flags2=['--cc', '--coverage-expr'])
|
||||
|
||||
test.execute()
|
||||
|
||||
# Read the input .v file and do any CHECK_COVER requests
|
||||
test.inline_checks()
|
||||
|
||||
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)
|
||||
|
||||
top = Path(test.top_filename)
|
||||
test.files_identical(test.obj_dir + f"/annotated/{top.name}", test.golden_filename)
|
||||
|
||||
test.passes()
|
|
@ -0,0 +1,161 @@
|
|||
// 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;
|
||||
|
||||
integer cyc;
|
||||
initial cyc=1;
|
||||
|
||||
integer some_int;
|
||||
integer other_int;
|
||||
logic some_bool;
|
||||
|
||||
wire t1 = cyc[0];
|
||||
wire t2 = cyc[1];
|
||||
wire t3 = cyc[2];
|
||||
wire t4 = cyc[3];
|
||||
|
||||
localparam bit ONE = 1'b1;
|
||||
localparam bit ZERO = 1'b0;
|
||||
|
||||
function automatic bit invert(bit x);
|
||||
return ~x;
|
||||
endfunction
|
||||
|
||||
function automatic bit and_oper(bit a, bit b);
|
||||
return a & b;
|
||||
endfunction
|
||||
|
||||
always @ (posedge clk) begin
|
||||
cyc <= cyc + 1;
|
||||
if ((~cyc[0] && cyc[1]) || (~cyc[2] && cyc[3])) $write("");
|
||||
if ((~t1 && t2) || (~t3 && t4)) $write("");
|
||||
if (t3 && (t1 == t2)) $write("");
|
||||
if (123 == (124 - 32'(t1 || t2))) $write("");
|
||||
some_int <= (t2 || t3) ? 345 : 567;
|
||||
some_bool <= t1 && t2;
|
||||
if (t1 & t2) $write("");
|
||||
if ((!t1 && t2) | (~t3 && t4)) $write("");
|
||||
if (t1 ^ t2) $write("");
|
||||
if (~(t1 & t2)) $write("");
|
||||
if (t1 -> t2) $write("");
|
||||
if (t1 <-> t2) $write("");
|
||||
if (&cyc[2:0]) $write("");
|
||||
if (&cyc[3:2]) $write("");
|
||||
if (|cyc[2:0]) $write("");
|
||||
if (^cyc[2:0]) $write("");
|
||||
if (|cyc[2:0] || cyc[3]) $write("");
|
||||
if (t1 & t2 & 1'b1) $write("");
|
||||
if (t1 & t2 & 1'b0) $write("");
|
||||
if (t1 & t2 & ONE) $write("");
|
||||
if (t1 & t2 & ZERO) $write("");
|
||||
if (t1 && t2) begin
|
||||
$write("");
|
||||
end else if (t1 || t2) begin
|
||||
$write("");
|
||||
end
|
||||
if (invert(t1) && t2) $write("");
|
||||
if (and_oper(t1, t2)) $write("");
|
||||
if (t2 && t3) begin
|
||||
if (t1 && t2) $write("");
|
||||
end
|
||||
if (0 == 1) begin
|
||||
for (int loop_var = 0; loop_var < 1; loop_var++) begin
|
||||
if (cyc[loop_var] && t2) $write("");
|
||||
end
|
||||
end
|
||||
// stop at the first layer even if there's more to find
|
||||
if ((cyc[3+32'(t1 && t2)+:2] == cyc[5+32'(t3 || t4)+:2]) || cyc[31]) $write("");
|
||||
// impossible branches and redundant terms
|
||||
if ((t1 && t2) && ~(t1 && t3) && (t1 || t4)) $write("");
|
||||
if ((cyc[0] && cyc[1]) && ~(cyc[0] && cyc[2]) && (cyc[0] || cyc[3])) $write("");
|
||||
// demonstrate current limitations of term matching scheme
|
||||
if ((cyc[0] && cyc[1]) && ~(cyc[1-1] && cyc[2]) && (cyc[2-2] || cyc[3])) $write("");
|
||||
//verilator coverage_off
|
||||
if (t1 && t2) $write("");
|
||||
//verilator coverage_on
|
||||
if ((~t1 && t2)
|
||||
||
|
||||
(~t3 && t4)) $write("");
|
||||
// intentionally testing wonkified expression terms
|
||||
if (
|
||||
cyc[
|
||||
0
|
||||
] &
|
||||
cyc
|
||||
[1]) $write("");
|
||||
// for now each ternary condition is considered in isolation
|
||||
other_int <= t1 ? t2 ? 1 : 2 : 3;
|
||||
// no expression coverage for multi-bit expressions
|
||||
if ((cyc[1:0] & cyc[3:2]) == 2'b11) $write("");
|
||||
// truth table is too large
|
||||
if (^cyc[6:0]) $write("");
|
||||
// this one is too big even for t_cover_expr_max
|
||||
if (^cyc) $write("");
|
||||
if (cyc==9) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
if (t1 && t2) $write("");
|
||||
end
|
||||
|
||||
logic ta, tb, tc;
|
||||
initial begin
|
||||
int q[5];
|
||||
int qv[$];
|
||||
|
||||
q = '{1, 2, 2, 4, 3};
|
||||
// lambas not handled
|
||||
// NB: there is a bug w/ tracing find_first (maybe lambdas in general?)
|
||||
// tracing_off does not work around the bug
|
||||
qv = q.find_first with (item[0] & item[1]);
|
||||
ta = '1;
|
||||
tb = '0;
|
||||
tc = '0;
|
||||
while (ta || tb || tc) begin
|
||||
tc = tb;
|
||||
tb = ta;
|
||||
ta = '0;
|
||||
end
|
||||
end
|
||||
|
||||
sub the_sub_1 (.p(t1), .q(t2));
|
||||
sub the_sub_2 (.p(t3), .q(t4));
|
||||
// TODO -- non-process expressions
|
||||
sub the_sub_3 (.p(t1 ? t2 : t3), .q(t4));
|
||||
|
||||
// TODO
|
||||
// pragma for expr coverage off / on
|
||||
// investigate cover point sorting in annotated source
|
||||
// consider reporting don't care terms
|
||||
//
|
||||
// Branches which are statically impossible to reach are still reported.
|
||||
// E.g.
|
||||
// -000000 point: comment=(t1=1 && t2=1 && 1'h0=1) => 1 hier=top.t
|
||||
// These could potentially be pruned, but they currently follow suit for
|
||||
// what branch coverage does. Perhaps a switch should be added to not
|
||||
// count statically impossible things.
|
||||
|
||||
endmodule
|
||||
|
||||
module sub (
|
||||
input p,
|
||||
input q
|
||||
);
|
||||
|
||||
always_comb begin
|
||||
if (p && q) $write("");
|
||||
end
|
||||
|
||||
endmodule
|
|
@ -0,0 +1,445 @@
|
|||
// // 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;
|
||||
|
||||
integer cyc;
|
||||
initial cyc=1;
|
||||
|
||||
integer some_int;
|
||||
integer other_int;
|
||||
logic some_bool;
|
||||
|
||||
wire t1 = cyc[0];
|
||||
wire t2 = cyc[1];
|
||||
wire t3 = cyc[2];
|
||||
wire t4 = cyc[3];
|
||||
|
||||
localparam bit ONE = 1'b1;
|
||||
localparam bit ZERO = 1'b0;
|
||||
|
||||
function automatic bit invert(bit x);
|
||||
000015 return ~x;
|
||||
+000012 point: comment=(x==0) => 1 hier=top.t
|
||||
+000015 point: comment=(x==1) => 0 hier=top.t
|
||||
endfunction
|
||||
|
||||
function automatic bit and_oper(bit a, bit b);
|
||||
%000005 return a & b;
|
||||
-000004 point: comment=(a==0) => 0 hier=top.t
|
||||
-000002 point: comment=(a==1 && b==1) => 1 hier=top.t
|
||||
-000005 point: comment=(b==0) => 0 hier=top.t
|
||||
endfunction
|
||||
|
||||
always @ (posedge clk) begin
|
||||
cyc <= cyc + 1;
|
||||
%000004 if ((~cyc[0] && cyc[1]) || (~cyc[2] && cyc[3])) $write("");
|
||||
-000002 point: comment=(cyc[0]==0 && cyc[1]==1) => 1 hier=top.t
|
||||
-000002 point: comment=(cyc[0]==1 && cyc[2]==1) => 0 hier=top.t
|
||||
-000004 point: comment=(cyc[0]==1 && cyc[3]==0) => 0 hier=top.t
|
||||
-000002 point: comment=(cyc[1]==0 && cyc[2]==1) => 0 hier=top.t
|
||||
-000003 point: comment=(cyc[1]==0 && cyc[3]==0) => 0 hier=top.t
|
||||
-000002 point: comment=(cyc[2]==0 && cyc[3]==1) => 1 hier=top.t
|
||||
%000004 if ((~t1 && t2) || (~t3 && t4)) $write("");
|
||||
-000002 point: comment=(t1==0 && t2==1) => 1 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t3==1) => 0 hier=top.t
|
||||
-000004 point: comment=(t1==1 && t4==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t2==0 && t3==1) => 0 hier=top.t
|
||||
-000003 point: comment=(t2==0 && t4==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t3==0 && t4==1) => 1 hier=top.t
|
||||
%000005 if (t3 && (t1 == t2)) $write("");
|
||||
-000005 point: comment=((t1 == t2)==0) => 0 hier=top.t
|
||||
-000005 point: comment=(t3==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t3==1 && (t1 == t2)==1) => 1 hier=top.t
|
||||
%000005 if (123 == (124 - 32'(t1 || t2))) $write("");
|
||||
-000002 point: comment=(t1==0 && t2==0) => 0 hier=top.t
|
||||
-000005 point: comment=(t1==1) => 1 hier=top.t
|
||||
-000004 point: comment=(t2==1) => 1 hier=top.t
|
||||
%000004 some_int <= (t2 || t3) ? 345 : 567;
|
||||
-000003 point: comment=(t2==0 && t3==0) => 0 hier=top.t
|
||||
-000004 point: comment=(t2==1) => 1 hier=top.t
|
||||
-000004 point: comment=(t3==1) => 1 hier=top.t
|
||||
%000005 some_bool <= t1 && t2;
|
||||
-000004 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t2==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
%000005 if (t1 & t2) $write("");
|
||||
-000004 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t2==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
%000004 if ((!t1 && t2) | (~t3 && t4)) $write("");
|
||||
-000002 point: comment=(t1==0 && t2==1) => 1 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t3==1) => 0 hier=top.t
|
||||
-000004 point: comment=(t1==1 && t4==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t2==0 && t3==1) => 0 hier=top.t
|
||||
-000003 point: comment=(t2==0 && t4==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t3==0 && t4==1) => 1 hier=top.t
|
||||
%000003 if (t1 ^ t2) $write("");
|
||||
-000002 point: comment=(t1==0 && t2==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t1==0 && t2==1) => 1 hier=top.t
|
||||
-000003 point: comment=(t1==1 && t2==0) => 1 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t2==1) => 0 hier=top.t
|
||||
%000005 if (~(t1 & t2)) $write("");
|
||||
-000004 point: comment=(t1==0) => 1 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t2==1) => 0 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 1 hier=top.t
|
||||
%000004 if (t1 -> t2) $write("");
|
||||
-000004 point: comment=(t1==0) => 1 hier=top.t
|
||||
-000003 point: comment=(t1==1 && t2==0) => 0 hier=top.t
|
||||
-000004 point: comment=(t2==1) => 1 hier=top.t
|
||||
%000003 if (t1 <-> t2) $write("");
|
||||
-000002 point: comment=(t1==0 && t2==0) => 1 hier=top.t
|
||||
-000002 point: comment=(t1==0 && t2==1) => 0 hier=top.t
|
||||
-000003 point: comment=(t1==1 && t2==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t2==1) => 1 hier=top.t
|
||||
%000005 if (&cyc[2:0]) $write("");
|
||||
-000004 point: comment=(cyc[2:0][0]==0) => 0 hier=top.t
|
||||
-000001 point: comment=(cyc[2:0][0]==1 && cyc[2:0][1]==1 && cyc[2:0][2]==1) => 1 hier=top.t
|
||||
-000005 point: comment=(cyc[2:0][1]==0) => 0 hier=top.t
|
||||
-000005 point: comment=(cyc[2:0][2]==0) => 0 hier=top.t
|
||||
%000007 if (&cyc[3:2]) $write("");
|
||||
-000005 point: comment=(cyc[3:2][0]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[3:2][0]==1 && cyc[3:2][1]==1) => 1 hier=top.t
|
||||
-000007 point: comment=(cyc[3:2][1]==0) => 0 hier=top.t
|
||||
%000005 if (|cyc[2:0]) $write("");
|
||||
-000001 point: comment=(cyc[2:0][0]==0 && cyc[2:0][1]==0 && cyc[2:0][2]==0) => 0 hier=top.t
|
||||
-000005 point: comment=(cyc[2:0][0]==1) => 1 hier=top.t
|
||||
-000004 point: comment=(cyc[2:0][1]==1) => 1 hier=top.t
|
||||
-000004 point: comment=(cyc[2:0][2]==1) => 1 hier=top.t
|
||||
%000002 if (^cyc[2:0]) $write("");
|
||||
-000001 point: comment=(cyc[2:0][0]==0 && cyc[2:0][1]==0 && cyc[2:0][2]==0) => 0 hier=top.t
|
||||
-000001 point: comment=(cyc[2:0][0]==0 && cyc[2:0][1]==0 && cyc[2:0][2]==1) => 1 hier=top.t
|
||||
-000001 point: comment=(cyc[2:0][0]==0 && cyc[2:0][1]==1 && cyc[2:0][2]==0) => 1 hier=top.t
|
||||
-000001 point: comment=(cyc[2:0][0]==0 && cyc[2:0][1]==1 && cyc[2:0][2]==1) => 0 hier=top.t
|
||||
-000002 point: comment=(cyc[2:0][0]==1 && cyc[2:0][1]==0 && cyc[2:0][2]==0) => 1 hier=top.t
|
||||
-000001 point: comment=(cyc[2:0][0]==1 && cyc[2:0][1]==0 && cyc[2:0][2]==1) => 0 hier=top.t
|
||||
-000001 point: comment=(cyc[2:0][0]==1 && cyc[2:0][1]==1 && cyc[2:0][2]==0) => 0 hier=top.t
|
||||
-000001 point: comment=(cyc[2:0][0]==1 && cyc[2:0][1]==1 && cyc[2:0][2]==1) => 1 hier=top.t
|
||||
%000005 if (|cyc[2:0] || cyc[3]) $write("");
|
||||
-000000 point: comment=(cyc[2:0][0]==0 && cyc[2:0][1]==0 && cyc[2:0][2]==0 && cyc[3]==0) => 0 hier=top.t
|
||||
-000005 point: comment=(cyc[2:0][0]==1) => 1 hier=top.t
|
||||
-000004 point: comment=(cyc[2:0][1]==1) => 1 hier=top.t
|
||||
-000004 point: comment=(cyc[2:0][2]==1) => 1 hier=top.t
|
||||
-000002 point: comment=(cyc[3]==1) => 1 hier=top.t
|
||||
%000005 if (t1 & t2 & 1'b1) $write("");
|
||||
-000000 point: comment=(1'h1==0) => 0 hier=top.t
|
||||
-000004 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t2==1 && 1'h1==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
%000009 if (t1 & t2 & 1'b0) $write("");
|
||||
-000009 point: comment=(1'h0==0) => 0 hier=top.t
|
||||
-000004 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000000 point: comment=(t1==1 && t2==1 && 1'h0==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
%000005 if (t1 & t2 & ONE) $write("");
|
||||
-000000 point: comment=(ONE==0) => 0 hier=top.t
|
||||
-000004 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t2==1 && ONE==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
%000009 if (t1 & t2 & ZERO) $write("");
|
||||
-000009 point: comment=(ZERO==0) => 0 hier=top.t
|
||||
-000004 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000000 point: comment=(t1==1 && t2==1 && ZERO==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
%000005 if (t1 && t2) begin
|
||||
-000004 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t2==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
$write("");
|
||||
%000003 end else if (t1 || t2) begin
|
||||
-000002 point: comment=(t1==0 && t2==0) => 0 hier=top.t
|
||||
-000003 point: comment=(t1==1) => 1 hier=top.t
|
||||
-000002 point: comment=(t2==1) => 1 hier=top.t
|
||||
$write("");
|
||||
end
|
||||
%000005 if (invert(t1) && t2) $write("");
|
||||
-000005 point: comment=(invert(t1)==0) => 0 hier=top.t
|
||||
-000002 point: comment=(invert(t1)==1 && t2==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
if (and_oper(t1, t2)) $write("");
|
||||
%000005 if (t2 && t3) begin
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t2==1 && t3==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t3==0) => 0 hier=top.t
|
||||
%000001 if (t1 && t2) $write("");
|
||||
-000001 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000001 point: comment=(t1==1 && t2==1) => 1 hier=top.t
|
||||
-000000 point: comment=(t2==0) => 0 hier=top.t
|
||||
end
|
||||
if (0 == 1) begin
|
||||
for (int loop_var = 0; loop_var < 1; loop_var++) begin
|
||||
%000000 if (cyc[loop_var] && t2) $write("");
|
||||
-000000 point: comment=(cyc[loop_var[4:0]+:32'h1]]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[loop_var[4:0]+:32'h1]]==1 && t2==1) => 1 hier=top.t
|
||||
-000000 point: comment=(t2==0) => 0 hier=top.t
|
||||
end
|
||||
end
|
||||
// stop at the first layer even if there's more to find
|
||||
%000007 if ((cyc[3+32'(t1 && t2)+:2] == cyc[5+32'(t3 || t4)+:2]) || cyc[31]) $write("");
|
||||
-000002 point: comment=((cyc[(32'sh3 + (t1 && t2))[4:0]+:32'sh2]] == cyc[(32'sh5 + (t3 || t4))[4:0]+:32'sh2]])==0 && cyc[31]==0) => 0 hier=top.t
|
||||
-000007 point: comment=((cyc[(32'sh3 + (t1 && t2))[4:0]+:32'sh2]] == cyc[(32'sh5 + (t3 || t4))[4:0]+:32'sh2]])==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[31]==1) => 1 hier=top.t
|
||||
// impossible branches and redundant terms
|
||||
%000005 if ((t1 && t2) && ~(t1 && t3) && (t1 || t4)) $write("");
|
||||
-000003 point: comment=(t1==0 && t4==0) => 0 hier=top.t
|
||||
-000004 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000000 point: comment=(t1==1 && t2==1 && t3==0 && t4==1) => 1 hier=top.t
|
||||
-000001 point: comment=(t1==1 && t2==1 && t3==0) => 1 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t3==1) => 0 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
%000005 if ((cyc[0] && cyc[1]) && ~(cyc[0] && cyc[2]) && (cyc[0] || cyc[3])) $write("");
|
||||
-000003 point: comment=(cyc[0]==0 && cyc[3]==0) => 0 hier=top.t
|
||||
-000004 point: comment=(cyc[0]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[0]==1 && cyc[1]==1 && cyc[2]==0 && cyc[3]==1) => 1 hier=top.t
|
||||
-000001 point: comment=(cyc[0]==1 && cyc[1]==1 && cyc[2]==0) => 1 hier=top.t
|
||||
-000002 point: comment=(cyc[0]==1 && cyc[2]==1) => 0 hier=top.t
|
||||
-000005 point: comment=(cyc[1]==0) => 0 hier=top.t
|
||||
// demonstrate current limitations of term matching scheme
|
||||
%000005 if ((cyc[0] && cyc[1]) && ~(cyc[1-1] && cyc[2]) && (cyc[2-2] || cyc[3])) $write("");
|
||||
-000002 point: comment=(cyc[(32'sh1 - 32'sh1)[4:0]+:32'h1]]==1 && cyc[2]==1) => 0 hier=top.t
|
||||
-000003 point: comment=(cyc[(32'sh2 - 32'sh2)[4:0]+:32'h1]]==0 && cyc[3]==0) => 0 hier=top.t
|
||||
-000004 point: comment=(cyc[0]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[0]==1 && cyc[1]==1 && cyc[(32'sh1 - 32'sh1)[4:0]+:32'h1]]==0 && cyc[(32'sh2 - 32'sh2)[4:0]+:32'h1]]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[0]==1 && cyc[1]==1 && cyc[(32'sh1 - 32'sh1)[4:0]+:32'h1]]==0 && cyc[3]==1) => 1 hier=top.t
|
||||
-000001 point: comment=(cyc[0]==1 && cyc[1]==1 && cyc[2]==0 && cyc[(32'sh2 - 32'sh2)[4:0]+:32'h1]]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[0]==1 && cyc[1]==1 && cyc[2]==0 && cyc[3]==1) => 1 hier=top.t
|
||||
-000005 point: comment=(cyc[1]==0) => 0 hier=top.t
|
||||
//verilator coverage_off
|
||||
if (t1 && t2) $write("");
|
||||
//verilator coverage_on
|
||||
if ((~t1 && t2)
|
||||
%000004 ||
|
||||
-000002 point: comment=(t1==0 && t2==1) => 1 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t3==1) => 0 hier=top.t
|
||||
-000004 point: comment=(t1==1 && t4==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t2==0 && t3==1) => 0 hier=top.t
|
||||
-000003 point: comment=(t2==0 && t4==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t3==0 && t4==1) => 1 hier=top.t
|
||||
(~t3 && t4)) $write("");
|
||||
// intentionally testing wonkified expression terms
|
||||
if (
|
||||
cyc[
|
||||
0
|
||||
%000005 ] &
|
||||
-000004 point: comment=(cyc[0]==0) => 0 hier=top.t
|
||||
-000002 point: comment=(cyc[0]==1 && cyc[1]==1) => 1 hier=top.t
|
||||
-000005 point: comment=(cyc[1]==0) => 0 hier=top.t
|
||||
cyc
|
||||
[1]) $write("");
|
||||
// for now each ternary condition is considered in isolation
|
||||
%000005 other_int <= t1 ? t2 ? 1 : 2 : 3;
|
||||
-000004 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000005 point: comment=(t1==1) => 1 hier=top.t
|
||||
// no expression coverage for multi-bit expressions
|
||||
if ((cyc[1:0] & cyc[3:2]) == 2'b11) $write("");
|
||||
// truth table is too large
|
||||
%000001 if (^cyc[6:0]) $write("");
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000001 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000001 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000001 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000001 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==0 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000001 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000001 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000001 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==0 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000001 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==0 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000001 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==0 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==0 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==0) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==0 && cyc[6:0][6]==1) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[6:0][0]==1 && cyc[6:0][1]==1 && cyc[6:0][2]==1 && cyc[6:0][3]==1 && cyc[6:0][4]==1 && cyc[6:0][5]==1 && cyc[6:0][6]==1) => 1 hier=top.t
|
||||
// this one is too big even for t_cover_expr_max
|
||||
if (^cyc) $write("");
|
||||
if (cyc==9) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
%000005 if (t1 && t2) $write("");
|
||||
-000005 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t2==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
end
|
||||
|
||||
logic ta, tb, tc;
|
||||
initial begin
|
||||
int q[5];
|
||||
int qv[$];
|
||||
|
||||
q = '{1, 2, 2, 4, 3};
|
||||
// lambas not handled
|
||||
// NB: there is a bug w/ tracing find_first (maybe lambdas in general?)
|
||||
// tracing_off does not work around the bug
|
||||
qv = q.find_first with (item[0] & item[1]);
|
||||
ta = '1;
|
||||
tb = '0;
|
||||
tc = '0;
|
||||
%000001 while (ta || tb || tc) begin
|
||||
-000001 point: comment=(ta==0 && tb==0 && tc==0) => 0 hier=top.t
|
||||
-000000 point: comment=(ta==1) => 1 hier=top.t
|
||||
-000000 point: comment=(tb==1) => 1 hier=top.t
|
||||
-000000 point: comment=(tc==1) => 1 hier=top.t
|
||||
tc = tb;
|
||||
tb = ta;
|
||||
ta = '0;
|
||||
end
|
||||
end
|
||||
|
||||
sub the_sub_1 (.p(t1), .q(t2));
|
||||
sub the_sub_2 (.p(t3), .q(t4));
|
||||
// TODO -- non-process expressions
|
||||
sub the_sub_3 (.p(t1 ? t2 : t3), .q(t4));
|
||||
|
||||
// TODO
|
||||
// pragma for expr coverage off / on
|
||||
// investigate cover point sorting in annotated source
|
||||
// consider reporting don't care terms
|
||||
//
|
||||
// Branches which are statically impossible to reach are still reported.
|
||||
// E.g.
|
||||
// -000000 point: comment=(t1=1 && t2=1 && 1'h0=1) => 1 hier=top.t
|
||||
// These could potentially be pruned, but they currently follow suit for
|
||||
// what branch coverage does. Perhaps a switch should be added to not
|
||||
// count statically impossible things.
|
||||
|
||||
endmodule
|
||||
|
||||
module sub (
|
||||
input p,
|
||||
input q
|
||||
);
|
||||
|
||||
always_comb begin
|
||||
~000019 if (p && q) $write("");
|
||||
+000017 point: comment=(p==0) => 0 hier=top.t.the_sub_*
|
||||
-000002 point: comment=(p==1 && q==1) => 1 hier=top.t.the_sub_*
|
||||
+000019 point: comment=(q==0) => 0 hier=top.t.the_sub_*
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
#!/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
|
||||
from pathlib import Path
|
||||
|
||||
test.scenarios('simulator')
|
||||
test.top_filename = "t/t_cover_expr.v"
|
||||
|
||||
test.compile(verilator_flags2=['--cc', '--coverage-expr', '--coverage-expr-max', '128'])
|
||||
|
||||
test.execute()
|
||||
|
||||
# Read the input .v file and do any CHECK_COVER requests
|
||||
test.inline_checks()
|
||||
|
||||
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)
|
||||
|
||||
top = Path(test.top_filename)
|
||||
test.files_identical(test.obj_dir + f"/annotated/{top.name}", test.golden_filename)
|
||||
|
||||
test.passes()
|
|
@ -0,0 +1,317 @@
|
|||
// // 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;
|
||||
|
||||
integer cyc;
|
||||
initial cyc=1;
|
||||
|
||||
integer some_int;
|
||||
integer other_int;
|
||||
logic some_bool;
|
||||
|
||||
wire t1 = cyc[0];
|
||||
wire t2 = cyc[1];
|
||||
wire t3 = cyc[2];
|
||||
wire t4 = cyc[3];
|
||||
|
||||
localparam bit ONE = 1'b1;
|
||||
localparam bit ZERO = 1'b0;
|
||||
|
||||
function automatic bit invert(bit x);
|
||||
000015 return ~x;
|
||||
+000012 point: comment=(x==0) => 1 hier=top.t
|
||||
+000015 point: comment=(x==1) => 0 hier=top.t
|
||||
endfunction
|
||||
|
||||
function automatic bit and_oper(bit a, bit b);
|
||||
%000005 return a & b;
|
||||
-000004 point: comment=(a==0) => 0 hier=top.t
|
||||
-000002 point: comment=(a==1 && b==1) => 1 hier=top.t
|
||||
-000005 point: comment=(b==0) => 0 hier=top.t
|
||||
endfunction
|
||||
|
||||
always @ (posedge clk) begin
|
||||
cyc <= cyc + 1;
|
||||
%000004 if ((~cyc[0] && cyc[1]) || (~cyc[2] && cyc[3])) $write("");
|
||||
-000002 point: comment=(cyc[0]==0 && cyc[1]==1) => 1 hier=top.t
|
||||
-000002 point: comment=(cyc[0]==1 && cyc[2]==1) => 0 hier=top.t
|
||||
-000004 point: comment=(cyc[0]==1 && cyc[3]==0) => 0 hier=top.t
|
||||
-000002 point: comment=(cyc[1]==0 && cyc[2]==1) => 0 hier=top.t
|
||||
-000003 point: comment=(cyc[1]==0 && cyc[3]==0) => 0 hier=top.t
|
||||
-000002 point: comment=(cyc[2]==0 && cyc[3]==1) => 1 hier=top.t
|
||||
%000004 if ((~t1 && t2) || (~t3 && t4)) $write("");
|
||||
-000002 point: comment=(t1==0 && t2==1) => 1 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t3==1) => 0 hier=top.t
|
||||
-000004 point: comment=(t1==1 && t4==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t2==0 && t3==1) => 0 hier=top.t
|
||||
-000003 point: comment=(t2==0 && t4==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t3==0 && t4==1) => 1 hier=top.t
|
||||
%000005 if (t3 && (t1 == t2)) $write("");
|
||||
-000005 point: comment=((t1 == t2)==0) => 0 hier=top.t
|
||||
-000005 point: comment=(t3==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t3==1 && (t1 == t2)==1) => 1 hier=top.t
|
||||
%000005 if (123 == (124 - 32'(t1 || t2))) $write("");
|
||||
-000002 point: comment=(t1==0 && t2==0) => 0 hier=top.t
|
||||
-000005 point: comment=(t1==1) => 1 hier=top.t
|
||||
-000004 point: comment=(t2==1) => 1 hier=top.t
|
||||
%000004 some_int <= (t2 || t3) ? 345 : 567;
|
||||
-000003 point: comment=(t2==0 && t3==0) => 0 hier=top.t
|
||||
-000004 point: comment=(t2==1) => 1 hier=top.t
|
||||
-000004 point: comment=(t3==1) => 1 hier=top.t
|
||||
%000005 some_bool <= t1 && t2;
|
||||
-000004 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t2==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
%000005 if (t1 & t2) $write("");
|
||||
-000004 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t2==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
%000004 if ((!t1 && t2) | (~t3 && t4)) $write("");
|
||||
-000002 point: comment=(t1==0 && t2==1) => 1 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t3==1) => 0 hier=top.t
|
||||
-000004 point: comment=(t1==1 && t4==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t2==0 && t3==1) => 0 hier=top.t
|
||||
-000003 point: comment=(t2==0 && t4==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t3==0 && t4==1) => 1 hier=top.t
|
||||
%000003 if (t1 ^ t2) $write("");
|
||||
-000002 point: comment=(t1==0 && t2==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t1==0 && t2==1) => 1 hier=top.t
|
||||
-000003 point: comment=(t1==1 && t2==0) => 1 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t2==1) => 0 hier=top.t
|
||||
%000005 if (~(t1 & t2)) $write("");
|
||||
-000004 point: comment=(t1==0) => 1 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t2==1) => 0 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 1 hier=top.t
|
||||
%000004 if (t1 -> t2) $write("");
|
||||
-000004 point: comment=(t1==0) => 1 hier=top.t
|
||||
-000003 point: comment=(t1==1 && t2==0) => 0 hier=top.t
|
||||
-000004 point: comment=(t2==1) => 1 hier=top.t
|
||||
%000003 if (t1 <-> t2) $write("");
|
||||
-000002 point: comment=(t1==0 && t2==0) => 1 hier=top.t
|
||||
-000002 point: comment=(t1==0 && t2==1) => 0 hier=top.t
|
||||
-000003 point: comment=(t1==1 && t2==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t2==1) => 1 hier=top.t
|
||||
%000005 if (&cyc[2:0]) $write("");
|
||||
-000004 point: comment=(cyc[2:0][0]==0) => 0 hier=top.t
|
||||
-000001 point: comment=(cyc[2:0][0]==1 && cyc[2:0][1]==1 && cyc[2:0][2]==1) => 1 hier=top.t
|
||||
-000005 point: comment=(cyc[2:0][1]==0) => 0 hier=top.t
|
||||
-000005 point: comment=(cyc[2:0][2]==0) => 0 hier=top.t
|
||||
%000007 if (&cyc[3:2]) $write("");
|
||||
-000005 point: comment=(cyc[3:2][0]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[3:2][0]==1 && cyc[3:2][1]==1) => 1 hier=top.t
|
||||
-000007 point: comment=(cyc[3:2][1]==0) => 0 hier=top.t
|
||||
%000005 if (|cyc[2:0]) $write("");
|
||||
-000001 point: comment=(cyc[2:0][0]==0 && cyc[2:0][1]==0 && cyc[2:0][2]==0) => 0 hier=top.t
|
||||
-000005 point: comment=(cyc[2:0][0]==1) => 1 hier=top.t
|
||||
-000004 point: comment=(cyc[2:0][1]==1) => 1 hier=top.t
|
||||
-000004 point: comment=(cyc[2:0][2]==1) => 1 hier=top.t
|
||||
%000002 if (^cyc[2:0]) $write("");
|
||||
-000001 point: comment=(cyc[2:0][0]==0 && cyc[2:0][1]==0 && cyc[2:0][2]==0) => 0 hier=top.t
|
||||
-000001 point: comment=(cyc[2:0][0]==0 && cyc[2:0][1]==0 && cyc[2:0][2]==1) => 1 hier=top.t
|
||||
-000001 point: comment=(cyc[2:0][0]==0 && cyc[2:0][1]==1 && cyc[2:0][2]==0) => 1 hier=top.t
|
||||
-000001 point: comment=(cyc[2:0][0]==0 && cyc[2:0][1]==1 && cyc[2:0][2]==1) => 0 hier=top.t
|
||||
-000002 point: comment=(cyc[2:0][0]==1 && cyc[2:0][1]==0 && cyc[2:0][2]==0) => 1 hier=top.t
|
||||
-000001 point: comment=(cyc[2:0][0]==1 && cyc[2:0][1]==0 && cyc[2:0][2]==1) => 0 hier=top.t
|
||||
-000001 point: comment=(cyc[2:0][0]==1 && cyc[2:0][1]==1 && cyc[2:0][2]==0) => 0 hier=top.t
|
||||
-000001 point: comment=(cyc[2:0][0]==1 && cyc[2:0][1]==1 && cyc[2:0][2]==1) => 1 hier=top.t
|
||||
%000005 if (|cyc[2:0] || cyc[3]) $write("");
|
||||
-000000 point: comment=(cyc[2:0][0]==0 && cyc[2:0][1]==0 && cyc[2:0][2]==0 && cyc[3]==0) => 0 hier=top.t
|
||||
-000005 point: comment=(cyc[2:0][0]==1) => 1 hier=top.t
|
||||
-000004 point: comment=(cyc[2:0][1]==1) => 1 hier=top.t
|
||||
-000004 point: comment=(cyc[2:0][2]==1) => 1 hier=top.t
|
||||
-000002 point: comment=(cyc[3]==1) => 1 hier=top.t
|
||||
%000005 if (t1 & t2 & 1'b1) $write("");
|
||||
-000000 point: comment=(1'h1==0) => 0 hier=top.t
|
||||
-000004 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t2==1 && 1'h1==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
%000009 if (t1 & t2 & 1'b0) $write("");
|
||||
-000009 point: comment=(1'h0==0) => 0 hier=top.t
|
||||
-000004 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000000 point: comment=(t1==1 && t2==1 && 1'h0==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
%000005 if (t1 & t2 & ONE) $write("");
|
||||
-000000 point: comment=(ONE==0) => 0 hier=top.t
|
||||
-000004 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t2==1 && ONE==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
%000009 if (t1 & t2 & ZERO) $write("");
|
||||
-000009 point: comment=(ZERO==0) => 0 hier=top.t
|
||||
-000004 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000000 point: comment=(t1==1 && t2==1 && ZERO==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
%000005 if (t1 && t2) begin
|
||||
-000004 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t2==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
$write("");
|
||||
%000003 end else if (t1 || t2) begin
|
||||
-000002 point: comment=(t1==0 && t2==0) => 0 hier=top.t
|
||||
-000003 point: comment=(t1==1) => 1 hier=top.t
|
||||
-000002 point: comment=(t2==1) => 1 hier=top.t
|
||||
$write("");
|
||||
end
|
||||
%000005 if (invert(t1) && t2) $write("");
|
||||
-000005 point: comment=(invert(t1)==0) => 0 hier=top.t
|
||||
-000002 point: comment=(invert(t1)==1 && t2==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
if (and_oper(t1, t2)) $write("");
|
||||
%000005 if (t2 && t3) begin
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t2==1 && t3==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t3==0) => 0 hier=top.t
|
||||
%000001 if (t1 && t2) $write("");
|
||||
-000001 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000001 point: comment=(t1==1 && t2==1) => 1 hier=top.t
|
||||
-000000 point: comment=(t2==0) => 0 hier=top.t
|
||||
end
|
||||
if (0 == 1) begin
|
||||
for (int loop_var = 0; loop_var < 1; loop_var++) begin
|
||||
%000000 if (cyc[loop_var] && t2) $write("");
|
||||
-000000 point: comment=(cyc[loop_var[4:0]+:32'h1]]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[loop_var[4:0]+:32'h1]]==1 && t2==1) => 1 hier=top.t
|
||||
-000000 point: comment=(t2==0) => 0 hier=top.t
|
||||
end
|
||||
end
|
||||
// stop at the first layer even if there's more to find
|
||||
%000007 if ((cyc[3+32'(t1 && t2)+:2] == cyc[5+32'(t3 || t4)+:2]) || cyc[31]) $write("");
|
||||
-000002 point: comment=((cyc[(32'sh3 + (t1 && t2))[4:0]+:32'sh2]] == cyc[(32'sh5 + (t3 || t4))[4:0]+:32'sh2]])==0 && cyc[31]==0) => 0 hier=top.t
|
||||
-000007 point: comment=((cyc[(32'sh3 + (t1 && t2))[4:0]+:32'sh2]] == cyc[(32'sh5 + (t3 || t4))[4:0]+:32'sh2]])==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[31]==1) => 1 hier=top.t
|
||||
// impossible branches and redundant terms
|
||||
%000005 if ((t1 && t2) && ~(t1 && t3) && (t1 || t4)) $write("");
|
||||
-000003 point: comment=(t1==0 && t4==0) => 0 hier=top.t
|
||||
-000004 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000000 point: comment=(t1==1 && t2==1 && t3==0 && t4==1) => 1 hier=top.t
|
||||
-000001 point: comment=(t1==1 && t2==1 && t3==0) => 1 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t3==1) => 0 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
%000005 if ((cyc[0] && cyc[1]) && ~(cyc[0] && cyc[2]) && (cyc[0] || cyc[3])) $write("");
|
||||
-000003 point: comment=(cyc[0]==0 && cyc[3]==0) => 0 hier=top.t
|
||||
-000004 point: comment=(cyc[0]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[0]==1 && cyc[1]==1 && cyc[2]==0 && cyc[3]==1) => 1 hier=top.t
|
||||
-000001 point: comment=(cyc[0]==1 && cyc[1]==1 && cyc[2]==0) => 1 hier=top.t
|
||||
-000002 point: comment=(cyc[0]==1 && cyc[2]==1) => 0 hier=top.t
|
||||
-000005 point: comment=(cyc[1]==0) => 0 hier=top.t
|
||||
// demonstrate current limitations of term matching scheme
|
||||
%000005 if ((cyc[0] && cyc[1]) && ~(cyc[1-1] && cyc[2]) && (cyc[2-2] || cyc[3])) $write("");
|
||||
-000002 point: comment=(cyc[(32'sh1 - 32'sh1)[4:0]+:32'h1]]==1 && cyc[2]==1) => 0 hier=top.t
|
||||
-000003 point: comment=(cyc[(32'sh2 - 32'sh2)[4:0]+:32'h1]]==0 && cyc[3]==0) => 0 hier=top.t
|
||||
-000004 point: comment=(cyc[0]==0) => 0 hier=top.t
|
||||
-000000 point: comment=(cyc[0]==1 && cyc[1]==1 && cyc[(32'sh1 - 32'sh1)[4:0]+:32'h1]]==0 && cyc[(32'sh2 - 32'sh2)[4:0]+:32'h1]]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[0]==1 && cyc[1]==1 && cyc[(32'sh1 - 32'sh1)[4:0]+:32'h1]]==0 && cyc[3]==1) => 1 hier=top.t
|
||||
-000001 point: comment=(cyc[0]==1 && cyc[1]==1 && cyc[2]==0 && cyc[(32'sh2 - 32'sh2)[4:0]+:32'h1]]==1) => 1 hier=top.t
|
||||
-000000 point: comment=(cyc[0]==1 && cyc[1]==1 && cyc[2]==0 && cyc[3]==1) => 1 hier=top.t
|
||||
-000005 point: comment=(cyc[1]==0) => 0 hier=top.t
|
||||
//verilator coverage_off
|
||||
if (t1 && t2) $write("");
|
||||
//verilator coverage_on
|
||||
if ((~t1 && t2)
|
||||
%000004 ||
|
||||
-000002 point: comment=(t1==0 && t2==1) => 1 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t3==1) => 0 hier=top.t
|
||||
-000004 point: comment=(t1==1 && t4==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t2==0 && t3==1) => 0 hier=top.t
|
||||
-000003 point: comment=(t2==0 && t4==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t3==0 && t4==1) => 1 hier=top.t
|
||||
(~t3 && t4)) $write("");
|
||||
// intentionally testing wonkified expression terms
|
||||
if (
|
||||
cyc[
|
||||
0
|
||||
%000005 ] &
|
||||
-000004 point: comment=(cyc[0]==0) => 0 hier=top.t
|
||||
-000002 point: comment=(cyc[0]==1 && cyc[1]==1) => 1 hier=top.t
|
||||
-000005 point: comment=(cyc[1]==0) => 0 hier=top.t
|
||||
cyc
|
||||
[1]) $write("");
|
||||
// for now each ternary condition is considered in isolation
|
||||
%000005 other_int <= t1 ? t2 ? 1 : 2 : 3;
|
||||
-000004 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000005 point: comment=(t1==1) => 1 hier=top.t
|
||||
// no expression coverage for multi-bit expressions
|
||||
if ((cyc[1:0] & cyc[3:2]) == 2'b11) $write("");
|
||||
// truth table is too large
|
||||
if (^cyc[6:0]) $write("");
|
||||
// this one is too big even for t_cover_expr_max
|
||||
if (^cyc) $write("");
|
||||
if (cyc==9) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
%000005 if (t1 && t2) $write("");
|
||||
-000005 point: comment=(t1==0) => 0 hier=top.t
|
||||
-000002 point: comment=(t1==1 && t2==1) => 1 hier=top.t
|
||||
-000005 point: comment=(t2==0) => 0 hier=top.t
|
||||
end
|
||||
|
||||
logic ta, tb, tc;
|
||||
initial begin
|
||||
int q[5];
|
||||
int qv[$];
|
||||
|
||||
q = '{1, 2, 2, 4, 3};
|
||||
// lambas not handled
|
||||
// NB: there is a bug w/ tracing find_first (maybe lambdas in general?)
|
||||
// tracing_off does not work around the bug
|
||||
qv = q.find_first with (item[0] & item[1]);
|
||||
ta = '1;
|
||||
tb = '0;
|
||||
tc = '0;
|
||||
%000001 while (ta || tb || tc) begin
|
||||
-000001 point: comment=(ta==0 && tb==0 && tc==0) => 0 hier=top.t
|
||||
-000000 point: comment=(ta==1) => 1 hier=top.t
|
||||
-000000 point: comment=(tb==1) => 1 hier=top.t
|
||||
-000000 point: comment=(tc==1) => 1 hier=top.t
|
||||
tc = tb;
|
||||
tb = ta;
|
||||
ta = '0;
|
||||
end
|
||||
end
|
||||
|
||||
sub the_sub_1 (.p(t1), .q(t2));
|
||||
sub the_sub_2 (.p(t3), .q(t4));
|
||||
// TODO -- non-process expressions
|
||||
sub the_sub_3 (.p(t1 ? t2 : t3), .q(t4));
|
||||
|
||||
// TODO
|
||||
// pragma for expr coverage off / on
|
||||
// investigate cover point sorting in annotated source
|
||||
// consider reporting don't care terms
|
||||
//
|
||||
// Branches which are statically impossible to reach are still reported.
|
||||
// E.g.
|
||||
// -000000 point: comment=(t1=1 && t2=1 && 1'h0=1) => 1 hier=top.t
|
||||
// These could potentially be pruned, but they currently follow suit for
|
||||
// what branch coverage does. Perhaps a switch should be added to not
|
||||
// count statically impossible things.
|
||||
|
||||
endmodule
|
||||
|
||||
module sub (
|
||||
input p,
|
||||
input q
|
||||
);
|
||||
|
||||
always_comb begin
|
||||
~000019 if (p && q) $write("");
|
||||
+000017 point: comment=(p==0) => 0 hier=top.t.the_sub_*
|
||||
-000002 point: comment=(p==1 && q==1) => 1 hier=top.t.the_sub_*
|
||||
+000019 point: comment=(q==0) => 0 hier=top.t.the_sub_*
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
#!/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
|
||||
from pathlib import Path
|
||||
|
||||
test.scenarios('simulator')
|
||||
test.top_filename = "t/t_cover_expr.v"
|
||||
|
||||
test.compile(verilator_flags2=['--cc', '--coverage-expr', '--trace'])
|
||||
|
||||
test.execute()
|
||||
|
||||
# Read the input .v file and do any CHECK_COVER requests
|
||||
test.inline_checks()
|
||||
|
||||
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)
|
||||
|
||||
top = Path(test.top_filename)
|
||||
test.files_identical(test.obj_dir + f"/annotated/{top.name}", test.golden_filename)
|
||||
|
||||
test.passes()
|
|
@ -16,6 +16,6 @@ test.compile(verilator_flags2=["-Wno-UNOPTTHREADS", "--stats", "--coverage", "--
|
|||
test.execute()
|
||||
|
||||
if test.vlt:
|
||||
test.file_grep(test.stats, r'Optimizations, Const bit op reduction\s+(\d+)', 144)
|
||||
test.file_grep(test.stats, r'Optimizations, Const bit op reduction\s+(\d+)', 620)
|
||||
|
||||
test.passes()
|
||||
|
|
|
@ -75,5 +75,8 @@ C 'ft/t_wrapper_context.vl38n4pagev_line/topoblockS38-39htop0.top'
|
|||
C 'ft/t_wrapper_context.vl40n7pagev_branch/topoifS40htop0.top' 0
|
||||
C 'ft/t_wrapper_context.vl40n8pagev_branch/topoelseS46htop0.top' 34
|
||||
C 'ft/t_wrapper_context.vl41n11pagev_line/topoelsehtop0.top' 0
|
||||
C 'ft/t_wrapper_context.vl41n27pagev_expr/topo((counter >= 32'sh5)==0) => 0htop0.top' 0
|
||||
C 'ft/t_wrapper_context.vl41n27pagev_expr/topo((counter >= 32'sh5)==1 && stop==1) => 1htop0.top' 0
|
||||
C 'ft/t_wrapper_context.vl41n27pagev_expr/topo(stop==0) => 0htop0.top' 0
|
||||
C 'ft/t_wrapper_context.vl47n10pagev_branch/topoifS47-49htop0.top' 1
|
||||
C 'ft/t_wrapper_context.vl47n11pagev_branch/topoelsehtop0.top' 33
|
||||
|
|
|
@ -75,5 +75,8 @@ C 'ft/t_wrapper_context.vl38n4pagev_line/topoblockS38-39htop1.top'
|
|||
C 'ft/t_wrapper_context.vl40n7pagev_branch/topoifS40htop1.top' 19
|
||||
C 'ft/t_wrapper_context.vl40n8pagev_branch/topoelseS46htop1.top' 0
|
||||
C 'ft/t_wrapper_context.vl41n11pagev_line/topoelsehtop1.top' 18
|
||||
C 'ft/t_wrapper_context.vl41n27pagev_expr/topo((counter >= 32'sh5)==0) => 0htop1.top' 18
|
||||
C 'ft/t_wrapper_context.vl41n27pagev_expr/topo((counter >= 32'sh5)==1 && stop==1) => 1htop1.top' 1
|
||||
C 'ft/t_wrapper_context.vl41n27pagev_expr/topo(stop==0) => 0htop1.top' 0
|
||||
C 'ft/t_wrapper_context.vl47n10pagev_branch/topoifS47-49htop1.top' 0
|
||||
C 'ft/t_wrapper_context.vl47n11pagev_branch/topoelsehtop1.top' 0
|
||||
|
|
Loading…
Reference in New Issue