fix FSM detect unchecked casts and variable redeclaration
This commit is contained in:
parent
e2e1bfe8dd
commit
fef5145a06
|
|
@ -9,6 +9,7 @@ Please see the Verilator manual for 200+ additional contributors. Thanks to all.
|
||||||
|
|
||||||
404allen404
|
404allen404
|
||||||
Adam Bagley
|
Adam Bagley
|
||||||
|
Adam Kostrzewski
|
||||||
Adrian Sampson
|
Adrian Sampson
|
||||||
Adrien Le Masle
|
Adrien Le Masle
|
||||||
أحمد المحمودي (Ahmed El-Mahmoudy)
|
أحمد المحمودي (Ahmed El-Mahmoudy)
|
||||||
|
|
|
||||||
|
|
@ -1322,6 +1322,12 @@ AstNode* AstArraySel::baseFromp(AstNode* nodep, bool overMembers) {
|
||||||
} else if (VN_IS(nodep, Sel)) {
|
} else if (VN_IS(nodep, Sel)) {
|
||||||
nodep = VN_AS(nodep, Sel)->fromp();
|
nodep = VN_AS(nodep, Sel)->fromp();
|
||||||
continue;
|
continue;
|
||||||
|
} else if (VN_IS(nodep, AssocSel)) {
|
||||||
|
nodep = VN_AS(nodep, AssocSel)->fromp();
|
||||||
|
continue;
|
||||||
|
} else if (VN_IS(nodep, WildcardSel)) {
|
||||||
|
nodep = VN_AS(nodep, WildcardSel)->fromp();
|
||||||
|
continue;
|
||||||
} else if (overMembers && VN_IS(nodep, MemberSel)) {
|
} else if (overMembers && VN_IS(nodep, MemberSel)) {
|
||||||
nodep = VN_AS(nodep, MemberSel)->fromp();
|
nodep = VN_AS(nodep, MemberSel)->fromp();
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
|
|
@ -530,8 +530,10 @@ class CoverageVisitor final : public VNVisitor {
|
||||||
newent.cleanup();
|
newent.cleanup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (VN_IS(dtypep, QueueDType)) {
|
} else if (VN_IS(dtypep, QueueDType) || VN_IS(dtypep, AssocArrayDType)
|
||||||
|
|| VN_IS(dtypep, WildcardArrayDType)) {
|
||||||
// Not covered
|
// Not covered
|
||||||
|
varp->v3warn(COVERIGN, "Coverage ignored for type " << dtypep->prettyTypeName());
|
||||||
} else {
|
} else {
|
||||||
dtypep->v3fatalSrc("Unexpected node data type in toggle coverage generation: "
|
dtypep->v3fatalSrc("Unexpected node data type in toggle coverage generation: "
|
||||||
<< dtypep->prettyTypeName());
|
<< dtypep->prettyTypeName());
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
#include "V3Control.h"
|
#include "V3Control.h"
|
||||||
#include "V3Graph.h"
|
#include "V3Graph.h"
|
||||||
|
#include "V3UniqueNames.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
|
@ -987,14 +988,23 @@ class FsmDetectVisitor final : public VNVisitor {
|
||||||
return assp;
|
return assp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static AstVarRef* tryExtractVarRef(AstNodeExpr* const exprp) {
|
||||||
|
AstVarRef* const varp = VN_CAST(AstArraySel::baseFromp(exprp, true), VarRef);
|
||||||
|
if (!varp) {
|
||||||
|
exprp->v3warn(COVERIGN,
|
||||||
|
"Ignoring unsupported: FSM coverage with " << exprp->prettyTypeName());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return varp;
|
||||||
|
}
|
||||||
|
|
||||||
static AstNodeAssign* nodeStateVarAssign(AstNode* nodep, AstVarScope*& stateVscp,
|
static AstNodeAssign* nodeStateVarAssign(AstNode* nodep, AstVarScope*& stateVscp,
|
||||||
AstVarScope*& fromVscp) {
|
AstVarScope*& fromVscp) {
|
||||||
AstNodeAssign* const assp = VN_CAST(nodep, NodeAssign);
|
AstNodeAssign* const assp = VN_CAST(nodep, NodeAssign);
|
||||||
if (!assp) return nullptr;
|
if (!assp) return nullptr;
|
||||||
AstVarRef* const lhsp = VN_AS(assp->lhsp(), VarRef);
|
AstVarRef* const lhsp = tryExtractVarRef(assp->lhsp());
|
||||||
UASSERT_OBJ(lhsp, assp, "register commit lhs should be normalized to a VarRef");
|
|
||||||
AstVarRef* const rhsp = VN_CAST(assp->rhsp(), VarRef);
|
AstVarRef* const rhsp = VN_CAST(assp->rhsp(), VarRef);
|
||||||
if (!rhsp) return nullptr;
|
if (!rhsp || !lhsp) return nullptr;
|
||||||
stateVscp = lhsp->varScopep();
|
stateVscp = lhsp->varScopep();
|
||||||
fromVscp = rhsp->varScopep();
|
fromVscp = rhsp->varScopep();
|
||||||
return assp;
|
return assp;
|
||||||
|
|
@ -1006,11 +1016,9 @@ class FsmDetectVisitor final : public VNVisitor {
|
||||||
FsmStateValue& resetValue) {
|
FsmStateValue& resetValue) {
|
||||||
AstNodeAssign* const assp = VN_CAST(nodep, NodeAssign);
|
AstNodeAssign* const assp = VN_CAST(nodep, NodeAssign);
|
||||||
if (!assp) return nullptr;
|
if (!assp) return nullptr;
|
||||||
AstVarRef* const lhsp = VN_AS(assp->lhsp(), VarRef);
|
AstVarRef* const lhsp = tryExtractVarRef(assp->lhsp());
|
||||||
UASSERT_OBJ(lhsp, assp,
|
|
||||||
"conditional register commit lhs should be normalized to a VarRef");
|
|
||||||
AstCond* const rhsp = VN_CAST(assp->rhsp(), Cond);
|
AstCond* const rhsp = VN_CAST(assp->rhsp(), Cond);
|
||||||
if (!rhsp) return nullptr;
|
if (!rhsp || !lhsp) return nullptr;
|
||||||
if (AstVarRef* const elsep = VN_CAST(rhsp->elsep(), VarRef)) {
|
if (AstVarRef* const elsep = VN_CAST(rhsp->elsep(), VarRef)) {
|
||||||
if (constValueStatus(rhsp->thenp(), resetValue) != ConstValueStatus::OK)
|
if (constValueStatus(rhsp->thenp(), resetValue) != ConstValueStatus::OK)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
@ -1033,7 +1041,7 @@ class FsmDetectVisitor final : public VNVisitor {
|
||||||
FsmStateValue& value) {
|
FsmStateValue& value) {
|
||||||
AstNodeAssign* const assp = VN_CAST(nodep, NodeAssign);
|
AstNodeAssign* const assp = VN_CAST(nodep, NodeAssign);
|
||||||
if (!assp) return nullptr;
|
if (!assp) return nullptr;
|
||||||
AstVarRef* const lhsp = VN_AS(assp->lhsp(), VarRef);
|
AstVarRef* const lhsp = VN_CAST(AstArraySel::baseFromp(assp->lhsp(), true), VarRef);
|
||||||
UASSERT_OBJ(lhsp, assp,
|
UASSERT_OBJ(lhsp, assp,
|
||||||
"direct constant state assignment lhs should be normalized to a VarRef");
|
"direct constant state assignment lhs should be normalized to a VarRef");
|
||||||
if (constValueStatus(assp->rhsp(), value) != ConstValueStatus::OK) return nullptr;
|
if (constValueStatus(assp->rhsp(), value) != ConstValueStatus::OK) return nullptr;
|
||||||
|
|
@ -1220,7 +1228,8 @@ class FsmDetectVisitor final : public VNVisitor {
|
||||||
AstVarRef* vrefp = VN_CAST(eqp->lhsp(), VarRef);
|
AstVarRef* vrefp = VN_CAST(eqp->lhsp(), VarRef);
|
||||||
AstNodeExpr* valuep = eqp->rhsp();
|
AstNodeExpr* valuep = eqp->rhsp();
|
||||||
if (!vrefp) {
|
if (!vrefp) {
|
||||||
vrefp = VN_AS(eqp->rhsp(), VarRef);
|
vrefp = tryExtractVarRef(eqp->rhsp());
|
||||||
|
if (!vrefp) { return false; }
|
||||||
valuep = eqp->lhsp();
|
valuep = eqp->lhsp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2082,6 +2091,7 @@ public:
|
||||||
class FsmLowerVisitor final {
|
class FsmLowerVisitor final {
|
||||||
// STATE - across all visitors
|
// STATE - across all visitors
|
||||||
const FsmState& m_state;
|
const FsmState& m_state;
|
||||||
|
V3UniqueNames m_fsmBuildNames;
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
// Rebuild a state-typed constant using the tracked state variable
|
// Rebuild a state-typed constant using the tracked state variable
|
||||||
|
|
@ -2133,8 +2143,8 @@ class FsmLowerVisitor final {
|
||||||
AstNodeModule* const modp = scopep->modp();
|
AstNodeModule* const modp = scopep->modp();
|
||||||
AstNodeDType* const prevDTypep = scopep->findLogicDType(
|
AstNodeDType* const prevDTypep = scopep->findLogicDType(
|
||||||
sampleVscp->width(), sampleVscp->width(), sampleVscp->dtypep()->numeric());
|
sampleVscp->width(), sampleVscp->width(), sampleVscp->dtypep()->numeric());
|
||||||
AstVarScope* const prevVscp
|
const std::string tmpName = m_fsmBuildNames.get(stateVscp->varp()->shortName());
|
||||||
= scopep->createTemp("__Vfsmcov_prev__" + stateVscp->varp()->shortName(), prevDTypep);
|
AstVarScope* const prevVscp = scopep->createTemp(tmpName, prevDTypep);
|
||||||
// The saved previous-state temp crosses the scheduler's pre/post split
|
// The saved previous-state temp crosses the scheduler's pre/post split
|
||||||
// in the same way as Verilator's built-in NBA shadow variables, so keep
|
// in the same way as Verilator's built-in NBA shadow variables, so keep
|
||||||
// both vars marked as post-life participants for stable MT ordering.
|
// both vars marked as post-life participants for stable MT ordering.
|
||||||
|
|
@ -2283,7 +2293,8 @@ public:
|
||||||
// concrete coverage instrumentation while the saved scoped pointers are
|
// concrete coverage instrumentation while the saved scoped pointers are
|
||||||
// still valid in the same pass.
|
// still valid in the same pass.
|
||||||
explicit FsmLowerVisitor(const FsmState& state)
|
explicit FsmLowerVisitor(const FsmState& state)
|
||||||
: m_state{state} {
|
: m_state{state}
|
||||||
|
, m_fsmBuildNames{"__Vfsmcov_prev"} {
|
||||||
for (const DetectedFsm& fsm : m_state.fsms()) { buildOne(*fsm.graphp); }
|
for (const DetectedFsm& fsm : m_state.fsms()) { buildOne(*fsm.graphp); }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
%Warning-COVERIGN: t/t_cover_fsm_concat_unsup.v:12:17: Ignoring unsupported: FSM coverage with CONCAT
|
||||||
|
12 | assign c = ({a, b} == 8'h00);
|
||||||
|
| ^
|
||||||
|
... For warning description see https://verilator.org/warn/COVERIGN?v=latest
|
||||||
|
... Use "/* verilator lint_off COVERIGN */" and lint_on around source to disable this message.
|
||||||
|
%Error: Exiting due to
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# DESCRIPTION: Verilator: FSM coverage concat as unsupported operation test
|
||||||
|
#
|
||||||
|
# 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-FileCopyrightText: 2026 Wilson Snyder
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('vlt')
|
||||||
|
|
||||||
|
test.lint(fails=True, expect_filename=test.golden_filename, verilator_flags2=['--coverage'])
|
||||||
|
|
||||||
|
test.passes()
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||||
|
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
module t (
|
||||||
|
input logic[6:0] a,
|
||||||
|
input logic b,
|
||||||
|
output logic c
|
||||||
|
);
|
||||||
|
assign c = ({a, b} == 8'h00);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
// // verilator_coverage annotation
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain
|
||||||
|
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
package P;
|
||||||
|
typedef struct packed{
|
||||||
|
logic [7:0] vs;
|
||||||
|
} C;
|
||||||
|
typedef struct packed{
|
||||||
|
C a; int b;
|
||||||
|
} B;
|
||||||
|
typedef struct packed{
|
||||||
|
B a;
|
||||||
|
} A;
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
module t (
|
||||||
|
%000009 input clk
|
||||||
|
);
|
||||||
|
typedef enum logic [1:0] {
|
||||||
|
S_IDLE = 2'd0,
|
||||||
|
S_RUN = 2'd1,
|
||||||
|
S_DONE = 2'd2,
|
||||||
|
S_ERR = 2'd3
|
||||||
|
} state_t;
|
||||||
|
|
||||||
|
%000001 logic rst;
|
||||||
|
%000001 logic start;
|
||||||
|
integer cyc;
|
||||||
|
%000001 state_t state /*verilator fsm_reset_arc*/;
|
||||||
|
%000002 P::A a;
|
||||||
|
%000001 logic done;
|
||||||
|
|
||||||
|
logic [7:0] va[int];
|
||||||
|
logic [7:0] va2d[int][int];
|
||||||
|
|
||||||
|
%000001 logic b;
|
||||||
|
%000001 logic c;
|
||||||
|
%000001 logic d;
|
||||||
|
|
||||||
|
assign b = (a.a.a.vs == 8'h0);
|
||||||
|
assign c = (va[0] == 8'h0);
|
||||||
|
assign d = (va2d[0][0] == 8'h0);
|
||||||
|
|
||||||
|
%000001 initial begin
|
||||||
|
%000001 rst = 1'b1;
|
||||||
|
%000001 start = 1'b0;
|
||||||
|
%000001 cyc = 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
%000009 always @(posedge clk) begin
|
||||||
|
%000009 cyc <= cyc + 1;
|
||||||
|
%000008 if (cyc == 1) rst <= 1'b0;
|
||||||
|
%000008 if (cyc == 2) start <= 1'b1;
|
||||||
|
%000008 if (cyc == 3) start <= 1'b0;
|
||||||
|
%000008 if (cyc == 8) begin
|
||||||
|
%000001 $write("*-* All Finished *-*\n");
|
||||||
|
%000001 $finish;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
%000009 always_ff @(posedge clk) begin
|
||||||
|
%000007 if (rst) begin
|
||||||
|
%000002 state <= S_IDLE;
|
||||||
|
end
|
||||||
|
%000007 else begin
|
||||||
|
%000007 case (state)
|
||||||
|
// [FSM coverage]
|
||||||
|
%000001 // [fsm_arc t.state::ANY->S_IDLE[reset_include]] [reset arc, excluded from %]
|
||||||
|
%000002 // [fsm_arc t.state::S_DONE->S_DONE]
|
||||||
|
%000003 // [fsm_arc t.state::S_IDLE->S_IDLE]
|
||||||
|
%000001 // [fsm_arc t.state::S_IDLE->S_RUN]
|
||||||
|
%000001 // [fsm_state t.state::S_DONE]
|
||||||
|
%000000 // [fsm_state t.state::S_ERR] *** UNCOVERED ***
|
||||||
|
%000000 // [fsm_state t.state::S_IDLE] *** UNCOVERED ***
|
||||||
|
%000001 // [fsm_state t.state::S_RUN]
|
||||||
|
%000002 S_IDLE:
|
||||||
|
%000001 if (start) state <= S_RUN;
|
||||||
|
%000001 else state <= S_IDLE;
|
||||||
|
%000003 S_RUN: begin
|
||||||
|
%000003 a.a.a.vs <= a.a.a.vs + 1;
|
||||||
|
%000003 done <= (a.a.a.vs == 8'h1);
|
||||||
|
%000002 if (done) begin
|
||||||
|
%000001 state <= S_DONE;
|
||||||
|
%000002 end else begin
|
||||||
|
%000002 state <= S_RUN;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
%000002 S_DONE: state <= S_DONE;
|
||||||
|
%000000 default: state <= S_ERR;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# DESCRIPTION: Verilator: FSM coverage array sel test
|
||||||
|
#
|
||||||
|
# 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-FileCopyrightText: 2026 Wilson Snyder
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('simulator')
|
||||||
|
|
||||||
|
test.compile(verilator_flags2=["--coverage"])
|
||||||
|
|
||||||
|
test.execute()
|
||||||
|
|
||||||
|
test.run(cmd=[
|
||||||
|
os.environ["VERILATOR_ROOT"] + "/bin/verilator_coverage",
|
||||||
|
"--annotate",
|
||||||
|
test.obj_dir + "/annotated",
|
||||||
|
test.obj_dir + "/coverage.dat",
|
||||||
|
],
|
||||||
|
verilator_run=True)
|
||||||
|
|
||||||
|
test.files_identical(test.obj_dir + "/annotated/" + test.name + ".v", test.golden_filename)
|
||||||
|
|
||||||
|
test.passes()
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain
|
||||||
|
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
package P;
|
||||||
|
typedef struct packed{
|
||||||
|
logic [7:0] vs;
|
||||||
|
} C;
|
||||||
|
typedef struct packed{
|
||||||
|
C a; int b;
|
||||||
|
} B;
|
||||||
|
typedef struct packed{
|
||||||
|
B a;
|
||||||
|
} A;
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
module t (
|
||||||
|
input clk
|
||||||
|
);
|
||||||
|
typedef enum logic [1:0] {
|
||||||
|
S_IDLE = 2'd0,
|
||||||
|
S_RUN = 2'd1,
|
||||||
|
S_DONE = 2'd2,
|
||||||
|
S_ERR = 2'd3
|
||||||
|
} state_t;
|
||||||
|
|
||||||
|
logic rst;
|
||||||
|
logic start;
|
||||||
|
integer cyc;
|
||||||
|
state_t state /*verilator fsm_reset_arc*/;
|
||||||
|
P::A a;
|
||||||
|
logic done;
|
||||||
|
|
||||||
|
logic [7:0] va[int];
|
||||||
|
logic [7:0] va2d[int][int];
|
||||||
|
|
||||||
|
logic b;
|
||||||
|
logic c;
|
||||||
|
logic d;
|
||||||
|
|
||||||
|
assign b = (a.a.a.vs == 8'h0);
|
||||||
|
assign c = (va[0] == 8'h0);
|
||||||
|
assign d = (va2d[0][0] == 8'h0);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
rst = 1'b1;
|
||||||
|
start = 1'b0;
|
||||||
|
cyc = 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
cyc <= cyc + 1;
|
||||||
|
if (cyc == 1) rst <= 1'b0;
|
||||||
|
if (cyc == 2) start <= 1'b1;
|
||||||
|
if (cyc == 3) start <= 1'b0;
|
||||||
|
if (cyc == 8) begin
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (rst) begin
|
||||||
|
state <= S_IDLE;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
case (state)
|
||||||
|
S_IDLE:
|
||||||
|
if (start) state <= S_RUN;
|
||||||
|
else state <= S_IDLE;
|
||||||
|
S_RUN: begin
|
||||||
|
a.a.a.vs <= a.a.a.vs + 1;
|
||||||
|
done <= (a.a.a.vs == 8'h1);
|
||||||
|
if (done) begin
|
||||||
|
state <= S_DONE;
|
||||||
|
end else begin
|
||||||
|
state <= S_RUN;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
S_DONE: state <= S_DONE;
|
||||||
|
default: state <= S_ERR;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,89 @@
|
||||||
|
// // verilator_coverage annotation
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain
|
||||||
|
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
module t #(
|
||||||
|
parameter int unsigned W = 16,
|
||||||
|
parameter int unsigned D = 4,
|
||||||
|
parameter int unsigned BW = 2
|
||||||
|
) (
|
||||||
|
%000009 input clk
|
||||||
|
);
|
||||||
|
typedef enum logic [1:0] {
|
||||||
|
S_IDLE = 2'd0,
|
||||||
|
S_RUN = 2'd1,
|
||||||
|
S_DONE = 2'd2,
|
||||||
|
S_ERR = 2'd3
|
||||||
|
} state_t;
|
||||||
|
|
||||||
|
%000001 logic rst;
|
||||||
|
%000001 logic start;
|
||||||
|
integer cyc;
|
||||||
|
%000001 state_t state /*verilator fsm_reset_arc*/;
|
||||||
|
%000001 logic [1:0] done_arr;
|
||||||
|
|
||||||
|
%000001 logic [W-1:0] a;
|
||||||
|
%000000 logic [BW-1:0] b;
|
||||||
|
begin
|
||||||
|
%000001 logic [D-1:0][W-1:0] s;
|
||||||
|
begin
|
||||||
|
%000009 always_ff @(posedge clk)
|
||||||
|
%000009 s[b] <= a;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
%000001 initial begin
|
||||||
|
%000001 rst = 1'b1;
|
||||||
|
%000001 start = 1'b0;
|
||||||
|
%000001 cyc = 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
%000009 always @(posedge clk) begin
|
||||||
|
%000009 cyc <= cyc + 1;
|
||||||
|
%000008 if (cyc == 1) rst <= 1'b0;
|
||||||
|
%000008 if (cyc == 2) start <= 1'b1;
|
||||||
|
%000008 if (cyc == 3) start <= 1'b0;
|
||||||
|
%000008 if (cyc == 4) a[0] = 1'b1;
|
||||||
|
%000008 if (cyc == 8) begin
|
||||||
|
%000001 $write("*-* All Finished *-*\n");
|
||||||
|
%000001 $finish;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
%000009 always_ff @(posedge clk) begin
|
||||||
|
%000007 if (rst) begin
|
||||||
|
%000002 state <= S_IDLE;
|
||||||
|
end
|
||||||
|
%000007 else begin
|
||||||
|
%000007 case (state)
|
||||||
|
// [FSM coverage]
|
||||||
|
%000001 // [fsm_arc t.state::ANY->S_IDLE[reset_include]] [reset arc, excluded from %]
|
||||||
|
%000002 // [fsm_arc t.state::S_DONE->S_DONE]
|
||||||
|
%000003 // [fsm_arc t.state::S_IDLE->S_IDLE]
|
||||||
|
%000001 // [fsm_arc t.state::S_IDLE->S_RUN]
|
||||||
|
%000001 // [fsm_state t.state::S_DONE]
|
||||||
|
%000000 // [fsm_state t.state::S_ERR] *** UNCOVERED ***
|
||||||
|
%000000 // [fsm_state t.state::S_IDLE] *** UNCOVERED ***
|
||||||
|
%000001 // [fsm_state t.state::S_RUN]
|
||||||
|
%000002 S_IDLE:
|
||||||
|
%000001 if (start) state <= S_RUN;
|
||||||
|
%000001 else state <= S_IDLE;
|
||||||
|
%000003 S_RUN: begin;
|
||||||
|
%000003 done_arr[0] <= (a[0] == 1'b1);
|
||||||
|
%000002 if (done_arr[0]) begin
|
||||||
|
%000001 state <= S_DONE;
|
||||||
|
%000002 end else begin
|
||||||
|
%000002 state <= S_RUN;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
%000002 S_DONE: state <= S_DONE;
|
||||||
|
%000000 default: state <= S_ERR;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# DESCRIPTION: Verilator: FSM coverage assignment test
|
||||||
|
#
|
||||||
|
# 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-FileCopyrightText: 2026 Wilson Snyder
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('simulator')
|
||||||
|
|
||||||
|
test.compile(verilator_flags2=["--coverage"])
|
||||||
|
|
||||||
|
test.execute()
|
||||||
|
|
||||||
|
test.run(cmd=[
|
||||||
|
os.environ["VERILATOR_ROOT"] + "/bin/verilator_coverage",
|
||||||
|
"--annotate",
|
||||||
|
test.obj_dir + "/annotated",
|
||||||
|
test.obj_dir + "/coverage.dat",
|
||||||
|
],
|
||||||
|
verilator_run=True)
|
||||||
|
|
||||||
|
test.files_identical(test.obj_dir + "/annotated/" + test.name + ".v", test.golden_filename)
|
||||||
|
|
||||||
|
test.passes()
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain
|
||||||
|
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
module t #(
|
||||||
|
parameter int unsigned W = 16,
|
||||||
|
parameter int unsigned D = 4,
|
||||||
|
parameter int unsigned BW = 2
|
||||||
|
) (
|
||||||
|
input clk
|
||||||
|
);
|
||||||
|
typedef enum logic [1:0] {
|
||||||
|
S_IDLE = 2'd0,
|
||||||
|
S_RUN = 2'd1,
|
||||||
|
S_DONE = 2'd2,
|
||||||
|
S_ERR = 2'd3
|
||||||
|
} state_t;
|
||||||
|
|
||||||
|
logic rst;
|
||||||
|
logic start;
|
||||||
|
integer cyc;
|
||||||
|
state_t state /*verilator fsm_reset_arc*/;
|
||||||
|
logic [1:0] done_arr;
|
||||||
|
|
||||||
|
logic [W-1:0] a;
|
||||||
|
logic [BW-1:0] b;
|
||||||
|
begin
|
||||||
|
logic [D-1:0][W-1:0] s;
|
||||||
|
begin
|
||||||
|
always_ff @(posedge clk)
|
||||||
|
s[b] <= a;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
rst = 1'b1;
|
||||||
|
start = 1'b0;
|
||||||
|
cyc = 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
cyc <= cyc + 1;
|
||||||
|
if (cyc == 1) rst <= 1'b0;
|
||||||
|
if (cyc == 2) start <= 1'b1;
|
||||||
|
if (cyc == 3) start <= 1'b0;
|
||||||
|
if (cyc == 4) a[0] = 1'b1;
|
||||||
|
if (cyc == 8) begin
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (rst) begin
|
||||||
|
state <= S_IDLE;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
case (state)
|
||||||
|
S_IDLE:
|
||||||
|
if (start) state <= S_RUN;
|
||||||
|
else state <= S_IDLE;
|
||||||
|
S_RUN: begin;
|
||||||
|
done_arr[0] <= (a[0] == 1'b1);
|
||||||
|
if (done_arr[0]) begin
|
||||||
|
state <= S_DONE;
|
||||||
|
end else begin
|
||||||
|
state <= S_RUN;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
S_DONE: state <= S_DONE;
|
||||||
|
default: state <= S_ERR;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
%Warning-COVERIGN: t/t_cover_fsm_sel_togglevar_unsup.v:20:14: Coverage ignored for type ASSOCARRAYDTYPE
|
||||||
|
: ... note: In instance 't'
|
||||||
|
20 | input P::A a,
|
||||||
|
| ^
|
||||||
|
... For warning description see https://verilator.org/warn/COVERIGN?v=latest
|
||||||
|
... Use "/* verilator lint_off COVERIGN */" and lint_on around source to disable this message.
|
||||||
|
%Warning-COVERIGN: t/t_cover_fsm_sel_togglevar_unsup.v:20:14: Coverage ignored for type WILDCARDARRAYDTYPE
|
||||||
|
: ... note: In instance 't'
|
||||||
|
20 | input P::A a,
|
||||||
|
| ^
|
||||||
|
%Error: Exiting due to
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# DESCRIPTION: Verilator: FSM coverage ignores associative array selection operators
|
||||||
|
#
|
||||||
|
# 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-FileCopyrightText: 2026 Wilson Snyder
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('vlt')
|
||||||
|
|
||||||
|
test.lint(fails=True, expect_filename=test.golden_filename, verilator_flags2=['--coverage'])
|
||||||
|
|
||||||
|
test.passes()
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||||
|
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
package P;
|
||||||
|
typedef struct {
|
||||||
|
logic [7:0] va[int];
|
||||||
|
logic [7:0] vw[*];
|
||||||
|
} C;
|
||||||
|
typedef struct {
|
||||||
|
C a; int b;
|
||||||
|
} B;
|
||||||
|
typedef struct {
|
||||||
|
B a;
|
||||||
|
} A;
|
||||||
|
endpackage
|
||||||
|
module t (
|
||||||
|
input P::A a,
|
||||||
|
output logic b,
|
||||||
|
output logic c
|
||||||
|
);
|
||||||
|
assign b = (a.a.a.va[0] == 8'h0);
|
||||||
|
assign c = (a.a.a.vw[0] == 8'h0);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# DESCRIPTION: Verilator: FSM no duplicate variables test
|
||||||
|
#
|
||||||
|
# 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-FileCopyrightText: 2026 Wilson Snyder
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('simulator')
|
||||||
|
|
||||||
|
test.compile(verilator_flags2=["--coverage -Wno-PINMISSING"])
|
||||||
|
|
||||||
|
test.execute()
|
||||||
|
|
||||||
|
test.passes()
|
||||||
|
|
@ -0,0 +1,173 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain
|
||||||
|
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
module rr
|
||||||
|
#(
|
||||||
|
) (
|
||||||
|
input logic clk,
|
||||||
|
input logic rst,
|
||||||
|
input logic [7:0] data,
|
||||||
|
input logic data_q
|
||||||
|
);
|
||||||
|
logic a;
|
||||||
|
logic [15:0] dcnt;
|
||||||
|
typedef enum logic [7:0] {
|
||||||
|
S0,
|
||||||
|
S1,
|
||||||
|
S2,
|
||||||
|
S3
|
||||||
|
} state_t;
|
||||||
|
state_t state_d, state_q;
|
||||||
|
always_ff @(posedge clk or negedge rst)
|
||||||
|
if (!rst) state_q <= S0;
|
||||||
|
always_ff @(posedge clk)
|
||||||
|
unique case (state_q)
|
||||||
|
S1: if (a) dcnt[7:0] <= data;
|
||||||
|
S2: if (a) dcnt[15:8] <= data;
|
||||||
|
S3: if (data_q) dcnt <= dcnt - 1;
|
||||||
|
default: dcnt <= dcnt;
|
||||||
|
endcase
|
||||||
|
endmodule
|
||||||
|
module re
|
||||||
|
#(
|
||||||
|
) (
|
||||||
|
input logic clk,
|
||||||
|
input logic rst,
|
||||||
|
output logic o,
|
||||||
|
input unused0, /* block optimizations */
|
||||||
|
input unused1,
|
||||||
|
input unused2,
|
||||||
|
input unused3,
|
||||||
|
input unused4,
|
||||||
|
input unused5,
|
||||||
|
input unused6,
|
||||||
|
input unused7,
|
||||||
|
input unused8,
|
||||||
|
input unused9,
|
||||||
|
input unused10,
|
||||||
|
input unused11,
|
||||||
|
input unused12,
|
||||||
|
input unused13,
|
||||||
|
input unused14,
|
||||||
|
input unused15,
|
||||||
|
input unused16,
|
||||||
|
input unused17,
|
||||||
|
input unused18,
|
||||||
|
input unused19,
|
||||||
|
input unused20,
|
||||||
|
input unused21,
|
||||||
|
input unused22,
|
||||||
|
input unused23,
|
||||||
|
input unused24,
|
||||||
|
input unused25,
|
||||||
|
input unused26,
|
||||||
|
input unused27,
|
||||||
|
input unused28,
|
||||||
|
input unused29,
|
||||||
|
input unused30,
|
||||||
|
input unused31,
|
||||||
|
input unused32,
|
||||||
|
input unused33,
|
||||||
|
input unused34,
|
||||||
|
input unused35,
|
||||||
|
input unused36,
|
||||||
|
input unused37,
|
||||||
|
input unused38,
|
||||||
|
input unused39,
|
||||||
|
input unused40
|
||||||
|
);
|
||||||
|
logic [15:0] dcnt;
|
||||||
|
typedef enum logic [7:0] {
|
||||||
|
S0,
|
||||||
|
S1
|
||||||
|
} state_t;
|
||||||
|
state_t state_d, state_q;
|
||||||
|
always_ff @(posedge clk or negedge rst)
|
||||||
|
if (!rst) state_q <= S0;
|
||||||
|
always_ff @(posedge clk)
|
||||||
|
unique case (state_q)
|
||||||
|
S1: o <= dcnt[0];
|
||||||
|
default: o <= '0;
|
||||||
|
endcase
|
||||||
|
initial begin
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
module rh
|
||||||
|
#(
|
||||||
|
) (
|
||||||
|
input logic clk
|
||||||
|
);
|
||||||
|
logic [7:0] a;
|
||||||
|
logic b;
|
||||||
|
logic c;
|
||||||
|
logic d;
|
||||||
|
logic rst;
|
||||||
|
rr xrr (
|
||||||
|
.clk,
|
||||||
|
.rst(rst),
|
||||||
|
.data (a),
|
||||||
|
.data_q (b & c)
|
||||||
|
);
|
||||||
|
re xre (
|
||||||
|
.clk,
|
||||||
|
.rst(rst),
|
||||||
|
.o (d)
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
|
module U
|
||||||
|
#(
|
||||||
|
) (
|
||||||
|
input clk,
|
||||||
|
input rst
|
||||||
|
);
|
||||||
|
rh xrh (
|
||||||
|
.clk (clk)
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
|
module C #(
|
||||||
|
) (
|
||||||
|
input clk,
|
||||||
|
input rst
|
||||||
|
);
|
||||||
|
U U (
|
||||||
|
.clk,
|
||||||
|
.rst
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
|
module A #(
|
||||||
|
) (
|
||||||
|
);
|
||||||
|
logic clk;
|
||||||
|
logic rst;
|
||||||
|
C c0 (
|
||||||
|
.clk,
|
||||||
|
.rst
|
||||||
|
);
|
||||||
|
C c1 (
|
||||||
|
.clk,
|
||||||
|
.rst
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
|
module B #(
|
||||||
|
) (
|
||||||
|
);
|
||||||
|
logic clk;
|
||||||
|
logic rst;
|
||||||
|
C xC (
|
||||||
|
.clk,
|
||||||
|
.rst
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
|
module t #(
|
||||||
|
) (
|
||||||
|
);
|
||||||
|
B b (
|
||||||
|
);
|
||||||
|
A a (
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue