Add ternary operator into branch coverage (#5880)

This commit is contained in:
Ryszard Rozak 2025-05-19 15:35:35 +02:00 committed by GitHub
parent ad08302e5f
commit bed0456eca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 1907 additions and 644 deletions

View File

@ -202,6 +202,11 @@ class CleanVisitor final : public VNVisitor {
operandQuadop(nodep);
setClean(nodep, nodep->cleanOut());
}
void visit(AstExprStmt* nodep) override {
iterateChildren(nodep);
computeCppWidth(nodep);
setClean(nodep, isClean(nodep->resultp()));
}
void visit(AstNodeExpr* nodep) override {
iterateChildren(nodep);
computeCppWidth(nodep);

View File

@ -142,6 +142,7 @@ class CoverageVisitor final : public VNVisitor {
bool m_objective = false; // Expression objective
bool m_ifCond = false; // Visiting if condition
bool m_inToggleOff = false; // In function/task etc
bool m_inLoopNotBody = false; // Inside a loop, but not in its body
string m_beginHier; // AstBegin hier name for user coverage points
// STATE - cleared each module
@ -290,7 +291,28 @@ class CoverageVisitor final : public VNVisitor {
// 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(AstWhile* nodep) override {
VL_RESTORER(m_state);
VL_RESTORER(m_inToggleOff);
m_inToggleOff = true;
createHandle(nodep);
{
VL_RESTORER(m_inLoopNotBody);
m_inLoopNotBody = true;
iterateAndNextNull(nodep->precondsp());
iterateNull(nodep->condp());
iterateAndNextNull(nodep->incsp());
}
iterateAndNextNull(nodep->stmtsp());
if (m_state.lineCoverageOn(nodep)) {
lineTrack(nodep);
AstNode* const newp
= newCoverInc(nodep->fileline(), "", "v_line", "block", linesCov(m_state, nodep),
0, traceNameForLine(nodep, "block"));
insertProcStatement(nodep, newp);
}
}
void visit(AstNodeFTask* nodep) override {
if (!nodep->dpiImport()) iterateProcedure(nodep);
}
@ -312,11 +334,11 @@ class CoverageVisitor final : public VNVisitor {
nodep->v3fatalSrc("Bad node type");
}
}
void iterateProcedure(AstNode* nodep, bool exprProc = true) {
void iterateProcedure(AstNode* nodep) {
VL_RESTORER(m_state);
VL_RESTORER(m_exprStmtsp);
VL_RESTORER(m_inToggleOff);
if (exprProc) m_exprStmtsp = nodep;
m_exprStmtsp = nodep;
m_inToggleOff = true;
createHandle(nodep);
iterateChildren(nodep);
@ -482,8 +504,56 @@ class CoverageVisitor final : public VNVisitor {
<< dtypep->prettyTypeName());
}
}
bool includeCondToBranchRecursive(const AstNode* const nodep) {
const AstNode* const backp = nodep->backp();
if (VN_IS(backp, Cond) && VN_AS(backp, Cond)->condp() != nodep) {
return includeCondToBranchRecursive(backp);
} else if (VN_IS(backp, Sel) && VN_AS(backp, Sel)->fromp() == nodep) {
return includeCondToBranchRecursive(backp);
} else if (VN_IS(backp, NodeAssign) && VN_AS(backp, NodeAssign)->rhsp() == nodep
&& !m_inLoopNotBody) {
return true;
}
return false;
}
// VISITORS - LINE COVERAGE
void visit(AstCond* nodep) override {
UINFO(4, " COND: " << nodep << endl);
if (m_seeking == NONE) coverExprs(nodep->condp());
if (m_state.lineCoverageOn(nodep) && VN_IS(m_modp, Module)
&& includeCondToBranchRecursive(nodep)) {
VL_RESTORER(m_seeking);
// Disable expression coverage in sub-expressions, since they were already visited
m_seeking = ABORTED;
const CheckState lastState = m_state;
createHandle(nodep);
iterate(nodep->thenp());
lineTrack(nodep);
AstNodeExpr* const thenp = nodep->thenp()->unlinkFrBack();
nodep->thenp(new AstExprStmt{thenp->fileline(),
newCoverInc(nodep->fileline(), "", "v_branch",
"cond_then", linesCov(m_state, nodep), 0,
traceNameForLine(nodep, "cond_then")),
thenp});
m_state = lastState;
createHandle(nodep);
iterate(nodep->elsep());
AstNodeExpr* const elsep = nodep->elsep()->unlinkFrBack();
nodep->elsep(new AstExprStmt{elsep->fileline(),
newCoverInc(nodep->fileline(), "", "v_branch",
"cond_else", linesCov(m_state, nodep), 1,
traceNameForLine(nodep, "cond_else")),
elsep});
m_state = lastState;
} else {
lineTrack(nodep);
}
}
// Note not AstNodeIf; other types don't get covered
void visit(AstIf* nodep) override {
if (nodep->user2()) return;
@ -904,11 +974,6 @@ class CoverageVisitor final : public VNVisitor {
}
}
void visit(AstCond* nodep) override {
if (m_seeking == NONE) coverExprs(nodep->condp());
lineTrack(nodep);
}
void visit(AstFuncRef* nodep) override {
if (nodep->taskp()->lifetime().isAutomatic()) {
visit(static_cast<AstNodeExpr*>(nodep));

View File

@ -203,9 +203,18 @@ class SliceVisitor final : public VNVisitor {
: elemIdx));
newp = new AstArraySel{nodep->fileline(), snodep->fromp()->cloneTree(false, needPure),
leOffset};
} else if (AstExprStmt* const snodep = VN_CAST(nodep, ExprStmt)) {
UINFO(9, " cloneExprStmt(" << elements << "," << elemIdx << ") " << nodep << endl);
AstNodeExpr* const resultSelp
= cloneAndSel(snodep->resultp(), elements, elemIdx, needPure);
if (snodep->stmtsp()) {
return new AstExprStmt{nodep->fileline(), snodep->stmtsp()->unlinkFrBackWithNext(),
resultSelp};
} else {
return resultSelp;
}
} else if (VN_IS(nodep, NodeVarRef) || VN_IS(nodep, NodeSel) || VN_IS(nodep, CMethodHard)
|| VN_IS(nodep, MemberSel) || VN_IS(nodep, ExprStmt)
|| VN_IS(nodep, StructSel)) {
|| VN_IS(nodep, MemberSel) || VN_IS(nodep, StructSel)) {
UINFO(9, " cloneSel(" << elements << "," << elemIdx << ") " << nodep << endl);
const int leOffset = !arrayp->rangep()->ascending()
? arrayp->rangep()->elementsConst() - 1 - elemIdx

View File

@ -144,6 +144,13 @@ public:
void checkPurity(AstNodeFTask* nodep) { checkPurity(nodep, getFTaskVertex(nodep)); }
private:
void convertAssignWToAlways() {
// Wire assigns must become always statements to deal with insertion
// of multiple statements. Perhaps someday make all wassigns into always's?
UINFO(5, " IM_WireRep " << m_assignwp << endl);
m_assignwp->convertToAlways();
VL_DO_CLEAR(pushDeletep(m_assignwp), m_assignwp = nullptr);
}
void checkPurity(AstNodeFTask* nodep, TaskBaseVertex* vxp) {
if (nodep->recursive()) return; // Impure, but no warning
if (!vxp->pure()) {
@ -191,15 +198,13 @@ private:
m_assignwp = nodep;
VL_DO_DANGLING(iterateChildren(nodep), nodep); // May delete nodep.
}
void visit(AstExprStmt* nodep) override {
if (m_assignwp) convertAssignWToAlways();
iterateChildren(nodep);
}
void visit(AstNodeFTaskRef* nodep) override {
// Includes handling AstMethodCall, AstNew
if (m_assignwp) {
// Wire assigns must become always statements to deal with insertion
// of multiple statements. Perhaps someday make all wassigns into always's?
UINFO(5, " IM_WireRep " << m_assignwp << endl);
m_assignwp->convertToAlways();
VL_DO_CLEAR(pushDeletep(m_assignwp), m_assignwp = nullptr);
}
if (m_assignwp) convertAssignWToAlways();
// We make multiple edges if a task is called multiple times from another task.
UASSERT_OBJ(nodep->taskp(), nodep, "Unlinked task");
TaskFTaskVertex* const taskVtxp = getFTaskVertex(nodep->taskp());

View File

@ -1117,6 +1117,18 @@ class TristateVisitor final : public TristateBaseVisitor {
}
}
void visit(AstExprStmt* nodep) override {
iterateChildren(nodep);
if (m_graphing) {
UASSERT_OBJ(!m_alhs, nodep, "AstExprStmt node on the LHS of assignment");
associateLogic(nodep->resultp(), nodep);
} else if (nodep->resultp()->user1p()) {
nodep->user1p(getEnp(nodep->resultp()));
nodep->resultp()->user1p(nullptr);
m_tgraph.didProcess(nodep);
}
}
void visit(AstSel* nodep) override {
if (m_graphing) {
iterateChildren(nodep);

View File

@ -50,6 +50,10 @@
// Inputs
.clk (clk));
par par1 (/*AUTOINST*/);
cond cond1 (/*AUTOINST*/
// Inputs
.clk (clk),
.cyc (cyc));
000010 always @ (posedge clk) begin
+000010 point: comment=block hier=top.t
@ -415,3 +419,118 @@
endmodule
package my_pkg;
%000001 int x = 1 ? 1 : 0;
-000001 point: comment=block hier=top.my_pkg
endpackage
%000001 class Getter1;
-000001 point: comment=block hier=top.$unit::Getter1__Vclpkg
000020 function int get_1;
+000020 point: comment=block hier=top.$unit::Getter1__Vclpkg
000020 return 1;
+000020 point: comment=block hier=top.$unit::Getter1__Vclpkg
endfunction
endclass
module cond(input logic clk, input int cyc);
logic a, b, c, d, e, f, g, h, k, l, m;
logic [5:0] tab;
typedef logic [7:0] arr_t[1:0];
arr_t data[1:0];
%000001 Getter1 getter1 = new;
-000001 point: comment=block hier=top.t.cond1
string s;
000021 function logic func_side_effect;
+000021 point: comment=block hier=top.t.cond1
000021 $display("SIDE EFFECT");
+000021 point: comment=block hier=top.t.cond1
000021 return 1;
+000021 point: comment=block hier=top.t.cond1
endfunction
000010 function arr_t get_arr;
+000010 point: comment=block hier=top.t.cond1
arr_t arr;
000010 return arr;
+000010 point: comment=block hier=top.t.cond1
endfunction
~000031 assign a = (cyc == 0) ? clk : 1'bz;
-000000 point: comment=cond_then hier=top.t.cond1
+000031 point: comment=cond_else hier=top.t.cond1
~000028 assign b = (cyc == 1) ? clk : 0;
-000003 point: comment=cond_then hier=top.t.cond1
+000028 point: comment=cond_else hier=top.t.cond1
~000021 assign c = func_side_effect() ? clk : 0;
+000021 point: comment=cond_then hier=top.t.cond1
-000000 point: comment=cond_else hier=top.t.cond1
000010 always @(posedge clk) begin
+000010 point: comment=block hier=top.t.cond1
~000010 d = (cyc % 3 == 0) ? 1 : 0;
+000010 point: comment=block hier=top.t.cond1
-000003 point: comment=cond_then hier=top.t.cond1
-000007 point: comment=cond_else hier=top.t.cond1
~000010 s = (getter1.get_1() == 0) ? "abcd" : $sformatf("%d", getter1.get_1()[4:0]);
+000010 point: comment=block hier=top.t.cond1
-000000 point: comment=cond_then hier=top.t.cond1
+000010 point: comment=cond_else hier=top.t.cond1
end
~000019 assign e = (cyc % 3 == 1) ? (clk ? 1 : 0) : 1;
+000012 point: comment=cond_then hier=top.t.cond1
+000019 point: comment=cond_else hier=top.t.cond1
-000007 point: comment=cond_then hier=top.t.cond1
-000005 point: comment=cond_else hier=top.t.cond1
// ternary operator in condition shouldn't be included to the coverae
~000011 assign f = (cyc != 0 ? 1 : 0) ? 1 : 0;
+000011 point: comment=cond_then hier=top.t.cond1
-000000 point: comment=cond_else hier=top.t.cond1
// the same as in index
assign tab[clk ? 1 : 0] = 1;
assign m = tab[clk ? 3 : 4];
for (genvar i = 0; i < 2; i++) begin
000011 assign g = clk ? 1 : 0;
+000010 point: comment=cond_then hier=top.t.cond1
+000011 point: comment=cond_else hier=top.t.cond1
end
000011 always begin
+000011 point: comment=block hier=top.t.cond1
~000010 if (cyc == 5) h = cyc > 5 ? 1 : 0;
-000000 point: comment=cond_then hier=top.t.cond1
-000001 point: comment=cond_else hier=top.t.cond1
-000001 point: comment=if hier=top.t.cond1
+000010 point: comment=else hier=top.t.cond1
000010 else h = 1;
+000010 point: comment=else hier=top.t.cond1
~000011 data[0] = (cyc == 2) ? '{8'h01, 8'h02} : get_arr();
+000011 point: comment=block hier=top.t.cond1
-000001 point: comment=cond_then hier=top.t.cond1
+000010 point: comment=cond_else hier=top.t.cond1
// ternary operator in conditions should be skipped
000055 for (int i = 0; (i < 5) ? 1 : 0; i++) begin
+000011 point: comment=block hier=top.t.cond1
+000055 point: comment=block hier=top.t.cond1
000055 k = 1'(i);
+000055 point: comment=block hier=top.t.cond1
end
000044 for (int i = 0; i < 7; i = (i > 4) ? i + 1 : i + 2) begin
+000011 point: comment=block hier=top.t.cond1
+000044 point: comment=block hier=top.t.cond1
000044 k = 1'(i);
+000044 point: comment=block hier=top.t.cond1
end
~000011 if (k ? 1 : 0) k = 1;
-000000 point: comment=if hier=top.t.cond1
+000011 point: comment=else hier=top.t.cond1
000011 else k = 0;
+000011 point: comment=else hier=top.t.cond1
end
endmodule

View File

@ -47,6 +47,10 @@ module t (/*AUTOARG*/
// Inputs
.clk (clk));
par par1 (/*AUTOINST*/);
cond cond1 (/*AUTOINST*/
// Inputs
.clk (clk),
.cyc (cyc));
always @ (posedge clk) begin
if (cyc!=0) begin
@ -291,3 +295,69 @@ module par();
endfunction
endmodule
package my_pkg;
int x = 1 ? 1 : 0;
endpackage
class Getter1;
function int get_1;
return 1;
endfunction
endclass
module cond(input logic clk, input int cyc);
logic a, b, c, d, e, f, g, h, k, l, m;
logic [5:0] tab;
typedef logic [7:0] arr_t[1:0];
arr_t data[1:0];
Getter1 getter1 = new;
string s;
function logic func_side_effect;
$display("SIDE EFFECT");
return 1;
endfunction
function arr_t get_arr;
arr_t arr;
return arr;
endfunction
assign a = (cyc == 0) ? clk : 1'bz;
assign b = (cyc == 1) ? clk : 0;
assign c = func_side_effect() ? clk : 0;
always @(posedge clk) begin
d = (cyc % 3 == 0) ? 1 : 0;
s = (getter1.get_1() == 0) ? "abcd" : $sformatf("%d", getter1.get_1()[4:0]);
end
assign e = (cyc % 3 == 1) ? (clk ? 1 : 0) : 1;
// ternary operator in condition shouldn't be included to the coverae
assign f = (cyc != 0 ? 1 : 0) ? 1 : 0;
// the same as in index
assign tab[clk ? 1 : 0] = 1;
assign m = tab[clk ? 3 : 4];
for (genvar i = 0; i < 2; i++) begin
assign g = clk ? 1 : 0;
end
always begin
if (cyc == 5) h = cyc > 5 ? 1 : 0;
else h = 1;
data[0] = (cyc == 2) ? '{8'h01, 8'h02} : get_arr();
// ternary operator in conditions should be skipped
for (int i = 0; (i < 5) ? 1 : 0; i++) begin
k = 1'(i);
end
for (int i = 0; i < 7; i = (i > 4) ? i + 1 : i + 2) begin
k = 1'(i);
end
if (k ? 1 : 0) k = 1;
else k = 0;
end
endmodule

View File

@ -6,6 +6,6 @@
`verilator_config
coverage_block_off -file "t/t_cover_line.v" -lines 141
coverage_block_off -file "t/t_cover_line.v" -lines 175
coverage_block_off -file "t/t_cover_line.v" -lines 145
coverage_block_off -file "t/t_cover_line.v" -lines 179
coverage_block_off -module "beta" -block "block"

View File

@ -2,148 +2,210 @@ TN:verilator_coverage
SF:t/t_cover_line.v
DA:15,1
DA:18,1
DA:51,10
DA:52,10
BRDA:52,0,0,10
BRDA:52,0,1,0
DA:53,10
DA:54,10
DA:56,9
BRDA:56,0,0,1
BRDA:56,0,1,9
DA:57,9
BRDA:57,0,0,1
BRDA:57,0,1,9
DA:58,1
DA:59,1
DA:62,9
BRDA:62,0,0,1
BRDA:62,0,1,9
DA:63,9
BRDA:63,0,0,1
BRDA:63,0,1,9
DA:65,9
DA:55,10
DA:56,10
BRDA:56,0,0,10
BRDA:56,0,1,0
DA:57,10
DA:58,10
DA:60,9
BRDA:60,0,0,1
BRDA:60,0,1,9
DA:61,9
BRDA:61,0,0,1
BRDA:61,0,1,9
DA:62,1
DA:63,1
DA:66,9
BRDA:66,0,0,1
BRDA:66,0,1,9
DA:67,9
BRDA:67,0,0,1
BRDA:67,0,1,9
DA:69,9
BRDA:69,0,0,1
BRDA:69,0,1,9
DA:70,9
BRDA:70,0,0,1
BRDA:70,0,1,9
DA:71,1
DA:72,1
DA:75,9
DA:76,9
DA:79,1
DA:80,1
DA:81,1
DA:73,9
BRDA:73,0,0,1
BRDA:73,0,1,9
DA:74,9
BRDA:74,0,0,1
BRDA:74,0,1,9
DA:75,1
DA:76,1
DA:79,9
DA:80,9
DA:83,1
DA:84,1
DA:85,1
DA:87,7
BRDA:87,0,0,1
BRDA:87,0,1,7
DA:87,1
DA:88,1
DA:89,1
DA:92,7
DA:93,7
DA:96,0
DA:97,0
DA:98,0
DA:91,7
BRDA:91,0,0,1
BRDA:91,0,1,7
DA:92,1
DA:93,1
DA:96,7
DA:97,7
DA:100,0
DA:101,10
BRDA:101,0,0,0
BRDA:101,0,1,10
DA:102,10
BRDA:102,0,0,0
BRDA:102,0,1,10
DA:103,0
DA:106,1
DA:107,1
DA:109,1
DA:101,0
DA:102,0
DA:104,0
DA:105,10
BRDA:105,0,0,0
BRDA:105,0,1,10
DA:106,10
BRDA:106,0,0,0
BRDA:106,0,1,10
DA:107,0
DA:110,1
DA:111,1
DA:116,7
BRDA:116,0,0,1
BRDA:116,0,1,7
DA:117,1
DA:118,1
DA:123,1
DA:125,1
DA:136,20
DA:137,18
BRDA:137,0,0,2
BRDA:137,0,1,18
DA:138,2
DA:113,1
DA:115,1
DA:120,7
BRDA:120,0,0,1
BRDA:120,0,1,7
DA:121,1
DA:122,1
DA:127,1
DA:129,1
DA:140,20
DA:141,18
DA:160,20
DA:161,20
DA:162,20
BRDA:162,0,0,0
BRDA:162,0,1,20
DA:164,0
DA:166,18
BRDA:166,0,0,2
BRDA:166,0,1,18
DA:168,2
BRDA:141,0,0,2
BRDA:141,0,1,18
DA:142,2
DA:145,18
DA:164,20
DA:165,20
DA:166,20
BRDA:166,0,0,0
BRDA:166,0,1,20
DA:168,0
DA:170,18
DA:184,1
DA:185,1
DA:186,1
BRDA:186,0,0,1
BRDA:186,0,1,0
DA:187,1
DA:190,11
DA:191,11
BRDA:191,0,0,11
BRDA:191,0,1,0
DA:192,11
BRDA:170,0,0,2
BRDA:170,0,1,18
DA:172,2
DA:174,18
DA:188,1
DA:189,1
DA:190,1
BRDA:190,0,0,1
BRDA:190,0,1,0
DA:191,1
DA:194,11
DA:195,11
BRDA:195,0,0,11
BRDA:195,0,1,0
DA:196,11
BRDA:196,0,0,11
BRDA:196,0,1,0
DA:197,11
DA:211,10
DA:212,10
DA:215,11
DA:217,11
DA:218,10
BRDA:218,0,0,1
BRDA:218,0,1,10
DA:219,1
DA:221,10
BRDA:221,0,0,1
BRDA:221,0,1,10
DA:222,1
DA:225,11
DA:199,11
DA:200,11
BRDA:200,0,0,11
BRDA:200,0,1,0
DA:201,11
DA:215,10
DA:216,10
DA:219,11
DA:221,11
DA:222,10
BRDA:222,0,0,1
BRDA:222,0,1,10
DA:223,1
DA:225,10
BRDA:225,0,0,1
BRDA:225,0,1,10
DA:226,1
DA:227,11
DA:228,11
DA:248,10
DA:249,9
BRDA:249,0,0,1
BRDA:249,0,1,9
DA:251,1
DA:252,1
BRDA:252,0,0,0
BRDA:252,0,1,1
DA:261,10
DA:262,10
DA:263,1
DA:264,1
DA:265,1
DA:266,1
DA:229,11
DA:230,1
DA:231,11
DA:232,11
DA:252,10
DA:253,9
BRDA:253,0,0,1
BRDA:253,0,1,9
DA:255,1
DA:256,1
BRDA:256,0,0,0
BRDA:256,0,1,1
DA:265,10
DA:266,10
DA:267,1
DA:268,5
DA:272,10
DA:273,10
DA:283,0
DA:284,0
BRDA:284,0,0,0
BRDA:284,0,1,0
DA:285,0
DA:268,1
DA:269,1
DA:270,1
DA:271,1
DA:272,5
DA:276,10
DA:277,10
DA:287,0
DA:288,0
DA:290,0
BRF:44
BRH:10
BRDA:288,0,0,0
BRDA:288,0,1,0
DA:289,0
DA:291,0
DA:292,0
DA:294,0
DA:300,1
DA:303,1
DA:304,20
DA:305,20
DA:314,1
DA:317,21
DA:318,21
DA:319,21
DA:322,10
DA:324,10
DA:327,31
BRDA:327,0,0,0
BRDA:327,0,1,31
DA:328,28
BRDA:328,0,0,3
BRDA:328,0,1,28
DA:329,21
BRDA:329,0,0,21
BRDA:329,0,1,0
DA:330,10
DA:331,10
BRDA:331,0,0,10
BRDA:331,0,1,3
BRDA:331,0,2,7
DA:332,10
BRDA:332,0,0,10
BRDA:332,0,1,0
BRDA:332,0,2,10
DA:334,19
BRDA:334,0,0,12
BRDA:334,0,1,19
BRDA:334,0,2,7
BRDA:334,0,3,5
DA:337,11
BRDA:337,0,0,11
BRDA:337,0,1,0
DA:343,11
BRDA:343,0,0,10
BRDA:343,0,1,11
DA:346,11
DA:347,10
BRDA:347,0,0,0
BRDA:347,0,1,1
BRDA:347,0,2,1
BRDA:347,0,3,10
DA:348,10
DA:350,11
BRDA:350,0,0,11
BRDA:350,0,1,1
BRDA:350,0,2,10
DA:353,55
BRDA:353,0,0,11
BRDA:353,0,1,55
DA:354,55
DA:356,44
BRDA:356,0,0,11
BRDA:356,0,1,44
DA:357,44
DA:360,11
BRDA:360,0,0,0
BRDA:360,0,1,11
DA:361,11
BRF:77
BRH:29
end_of_record

View File

@ -0,0 +1,480 @@
// // 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
%000001 class cls;
-000001 point: comment=block hier=top.$unit::cls__Vclpkg
rand int x;
endclass
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
integer cyc;
%000001 initial cyc=1;
-000001 point: comment=block hier=top.t
logic [63:32] cyc2;
%000001 always_comb cyc2 = cyc;
-000001 point: comment=block hier=top.t
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;
000027 function automatic bit invert(bit x);
+000027 point: comment=block hier=top.t
000027 return ~x;
+000027 point: comment=block hier=top.t
+000012 point: comment=(x==0) => 1 hier=top.t
+000015 point: comment=(x==1) => 0 hier=top.t
endfunction
%000009 function automatic bit and_oper(bit a, bit b);
-000009 point: comment=block hier=top.t
%000009 return a & b;
-000009 point: comment=block hier=top.t
-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
localparam int num_intfs = 4;
intf the_intfs [num_intfs-1:0] ();
genvar intf_i;
%000004 for (intf_i = 0; intf_i < num_intfs; intf_i++) begin
-000004 point: comment=block hier=top.t
%000004 always_comb the_intfs[intf_i].t = cyc[intf_i];
-000004 point: comment=block hier=top.t
end
%000009 always @ (posedge clk) begin
-000009 point: comment=block hier=top.t
%000009 cyc <= cyc + 1;
-000009 point: comment=block hier=top.t
%000005 if ((~cyc[0] && cyc[1]) || (~cyc[2] && cyc[3])) $write("");
-000005 point: comment=else hier=top.t
-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 point: comment=if hier=top.t
%000005 if ((~cyc2[32] && cyc2[33]) || (~cyc2[34] && cyc2[35])) $write("");
-000005 point: comment=else hier=top.t
-000002 point: comment=(cyc2[32]==0 && cyc2[33]==1) => 1 hier=top.t
-000002 point: comment=(cyc2[32]==1 && cyc2[34]==1) => 0 hier=top.t
-000004 point: comment=(cyc2[32]==1 && cyc2[35]==0) => 0 hier=top.t
-000002 point: comment=(cyc2[33]==0 && cyc2[34]==1) => 0 hier=top.t
-000003 point: comment=(cyc2[33]==0 && cyc2[35]==0) => 0 hier=top.t
-000002 point: comment=(cyc2[34]==0 && cyc2[35]==1) => 1 hier=top.t
-000004 point: comment=if hier=top.t
%000005 if ((~the_intfs[0].t && the_intfs[1].t) || (~the_intfs[2].t && the_intfs[3].t)) $write("");
-000005 point: comment=else hier=top.t
-000002 point: comment=(the_intfs[0].t==0 && the_intfs[1].t==1) => 1 hier=top.t
-000002 point: comment=(the_intfs[0].t==1 && the_intfs[2].t==1) => 0 hier=top.t
-000004 point: comment=(the_intfs[0].t==1 && the_intfs[3].t==0) => 0 hier=top.t
-000002 point: comment=(the_intfs[1].t==0 && the_intfs[2].t==1) => 0 hier=top.t
-000003 point: comment=(the_intfs[1].t==0 && the_intfs[3].t==0) => 0 hier=top.t
-000002 point: comment=(the_intfs[2].t==0 && the_intfs[3].t==1) => 1 hier=top.t
-000004 point: comment=if hier=top.t
%000005 if ((~t1 && t2) || (~t3 && t4)) $write("");
-000005 point: comment=else hier=top.t
-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
-000004 point: comment=if hier=top.t
%000007 if (t3 && (t1 == t2)) $write("");
-000007 point: comment=else hier=top.t
-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
-000002 point: comment=if hier=top.t
%000007 if (123 == (124 - 32'(t1 || t2))) $write("");
-000002 point: comment=else hier=top.t
-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
-000007 point: comment=if hier=top.t
%000009 some_int <= (t2 || t3) ? 345 : 567;
-000009 point: comment=block hier=top.t
-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
-000006 point: comment=cond_then hier=top.t
-000003 point: comment=cond_else hier=top.t
%000009 some_bool <= t1 && t2;
-000009 point: comment=block hier=top.t
-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
%000007 if (t1 & t2) $write("");
-000007 point: comment=else hier=top.t
-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
-000002 point: comment=if hier=top.t
%000005 if ((!t1 && t2) | (~t3 && t4)) $write("");
-000005 point: comment=else hier=top.t
-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
-000004 point: comment=if hier=top.t
%000005 if (t1 ^ t2) $write("");
-000004 point: comment=else hier=top.t
-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 point: comment=if hier=top.t
%000007 if (~(t1 & t2)) $write("");
-000002 point: comment=else hier=top.t
-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
-000007 point: comment=if hier=top.t
%000006 if (t1 -> t2) $write("");
-000003 point: comment=else hier=top.t
-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
-000006 point: comment=if hier=top.t
%000005 if (t1 <-> t2) $write("");
-000005 point: comment=else hier=top.t
-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
-000004 point: comment=if hier=top.t
%000008 if (&cyc[2:0]) $write("");
-000008 point: comment=else hier=top.t
-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
-000001 point: comment=if hier=top.t
%000009 if (&cyc[3:2]) $write("");
-000009 point: comment=else hier=top.t
-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
-000000 point: comment=if hier=top.t
%000008 if (|cyc[2:0]) $write("");
-000001 point: comment=else hier=top.t
-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
-000008 point: comment=if hier=top.t
%000005 if (^cyc[2:0]) $write("");
-000004 point: comment=else hier=top.t
-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 point: comment=if hier=top.t
%000009 if (|cyc[2:0] || cyc[3]) $write("");
-000000 point: comment=else hier=top.t
-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
-000009 point: comment=if hier=top.t
%000007 if (t1 & t2 & 1'b1) $write("");
-000007 point: comment=else hier=top.t
-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
-000002 point: comment=if hier=top.t
%000009 if (t1 & t2 & 1'b0) $write("");
-000009 point: comment=else hier=top.t
-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
-000000 point: comment=if hier=top.t
%000007 if (t1 & t2 & ONE) $write("");
-000007 point: comment=else hier=top.t
-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
-000002 point: comment=if hier=top.t
%000009 if (t1 & t2 & ZERO) $write("");
-000009 point: comment=else hier=top.t
-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
-000000 point: comment=if 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
-000002 point: comment=elsif hier=top.t
%000002 $write("");
-000002 point: comment=elsif hier=top.t
%000005 end else if (t1 || t2) begin
-000005 point: comment=if hier=top.t
-000002 point: comment=else hier=top.t
-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
%000005 $write("");
-000005 point: comment=if hier=top.t
end
%000007 if (invert(t1) && t2) $write("");
-000007 point: comment=else hier=top.t
-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
-000002 point: comment=if hier=top.t
%000007 if (and_oper(t1, t2)) $write("");
-000007 point: comment=else hier=top.t
-000002 point: comment=if hier=top.t
%000007 if (t2 && t3) begin
-000007 point: comment=else hier=top.t
-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
-000002 point: comment=if hier=top.t
%000001 if (t1 && t2) $write("");
-000001 point: comment=if hier=top.t
-000001 point: comment=else hier=top.t
-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
%000009 if (0 == 1) begin
-000009 point: comment=else hier=top.t
-000000 point: comment=if hier=top.t
%000000 for (int loop_var = 0; loop_var < 1; loop_var++) begin
-000000 point: comment=if hier=top.t
-000000 point: comment=block hier=top.t
%000000 if (cyc[loop_var] && t2) $write("");
-000000 point: comment=if hier=top.t
-000000 point: comment=else hier=top.t
-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=else hier=top.t
-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
-000007 point: comment=if hier=top.t
// impossible branches and redundant terms
%000008 if ((t1 && t2) && ~(t1 && t3) && (t1 || t4)) $write("");
-000008 point: comment=else hier=top.t
-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
-000001 point: comment=if hier=top.t
%000008 if ((cyc[0] && cyc[1]) && ~(cyc[0] && cyc[2]) && (cyc[0] || cyc[3])) $write("");
-000008 point: comment=else hier=top.t
-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
-000001 point: comment=if hier=top.t
// demonstrate current limitations of term matching scheme
%000008 if ((cyc[0] && cyc[1]) && ~(cyc[1-1] && cyc[2]) && (cyc[2-2] || cyc[3])) $write("");
-000008 point: comment=else hier=top.t
-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
-000001 point: comment=if hier=top.t
//verilator coverage_off
if (t1 && t2) $write("");
//verilator coverage_on
%000005 if ((~t1 && t2)
-000005 point: comment=else hier=top.t
-000004 point: comment=if hier=top.t
%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
%000004 (~t3 && t4)) $write("");
-000004 point: comment=if hier=top.t
// intentionally testing wonkified expression terms
%000007 if (
-000007 point: comment=else hier=top.t
-000002 point: comment=if hier=top.t
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
%000002 [1]) $write("");
-000002 point: comment=if hier=top.t
// for now each ternary condition is considered in isolation
%000009 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
-000005 point: comment=cond_then hier=top.t
-000004 point: comment=cond_else hier=top.t
-000002 point: comment=cond_then hier=top.t
-000003 point: comment=cond_else hier=top.t
-000009 point: comment=block hier=top.t
// no expression coverage for multi-bit expressions
%000009 if ((cyc[1:0] & cyc[3:2]) == 2'b11) $write("");
-000009 point: comment=else hier=top.t
-000000 point: comment=if hier=top.t
// truth table is too large
%000005 if (^cyc[6:0]) $write("");
-000004 point: comment=else hier=top.t
-000005 point: comment=if hier=top.t
// this one is too big even for t_cover_expr_max
%000005 if (^cyc) $write("");
-000004 point: comment=else hier=top.t
-000005 point: comment=if hier=top.t
%000008 if (cyc==9) begin
-000008 point: comment=else hier=top.t
-000001 point: comment=if hier=top.t
%000001 $write("*-* All Finished *-*\n");
-000001 point: comment=if hier=top.t
%000001 $finish;
-000001 point: comment=if hier=top.t
end
end
000010 always_comb begin
+000010 point: comment=block hier=top.t
%000008 if (t1 && t2) $write("");
-000008 point: comment=else hier=top.t
-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
-000002 point: comment=if hier=top.t
end
logic ta, tb, tc;
%000001 initial begin
-000001 point: comment=block hier=top.t
%000001 cls obj = new;
-000001 point: comment=block hier=top.t
%000001 cls null_obj = null;
-000001 point: comment=block hier=top.t
int q[5];
int qv[$];
%000001 q = '{1, 2, 2, 4, 3};
-000001 point: comment=block hier=top.t
// lambas not handled
// NB: there is a bug w/ tracing find_first (maybe lambdas in general?)
// tracing_off does not work around the bug
%000001 qv = q.find_first with (item[0] & item[1]);
-000001 point: comment=block hier=top.t
%000001 ta = '1;
-000001 point: comment=block hier=top.t
%000001 tb = '0;
-000001 point: comment=block hier=top.t
%000001 tc = '0;
-000001 point: comment=block hier=top.t
%000003 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
-000003 point: comment=block hier=top.t
%000003 tc = tb;
-000003 point: comment=block hier=top.t
%000003 tb = ta;
-000003 point: comment=block hier=top.t
%000003 ta = '0;
-000003 point: comment=block hier=top.t
end
%000001 if (!bit'(obj.randomize() with {x < 100;})) $write("");
-000000 point: comment=else hier=top.t
-000001 point: comment=if hier=top.t
%000001 if (null_obj != null && null_obj.x == 5) $write("");
-000001 point: comment=else hier=top.t
-000000 point: comment=if hier=top.t
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
);
000030 always_comb begin
+000030 point: comment=block hier=top.t.the_sub_*
~000028 if (p && q) $write("");
+000028 point: comment=else hier=top.t.the_sub_*
+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_*
-000002 point: comment=if hier=top.t.the_sub_*
end
endmodule
interface intf();
logic t;
endinterface

View File

@ -0,0 +1,28 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2024 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('simulator')
test.top_filename = "t/t_cover_expr.v"
test.golden_filename = "t/t_cover_line_expr.out"
test.compile(verilator_flags2=['--cc --coverage-line --coverage-expr'])
test.execute()
test.run(cmd=[os.environ["VERILATOR_ROOT"] + "/bin/verilator_coverage",
"--annotate-points",
"--annotate", test.obj_dir + "/annotated",
test.obj_dir + "/coverage.dat"],
verilator_run=True) # yapf:disable
test.files_identical(test.obj_dir + "/annotated/t_cover_expr.v", test.golden_filename)
test.passes()

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,24 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2024 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('vlt_all')
test.pli_filename = "t/t_tri_gate.cpp"
test.top_filename = "t/t_tri_gate.v"
test.compile(make_top_shell=False,
make_main=False,
v_flags2=['+define+T_COND'],
make_flags=['CPPFLAGS_ADD=-DT_COND'],
verilator_flags2=["--exe", test.pli_filename, "--coverage-line"])
test.execute()
test.passes()