Fix FSM detect unchecked casts and variable redeclaration (#7758)
This commit is contained in:
parent
901909d3c7
commit
394c9bc9b2
|
|
@ -9,6 +9,7 @@ Please see the Verilator manual for 200+ additional contributors. Thanks to all.
|
|||
|
||||
404allen404
|
||||
Adam Bagley
|
||||
Adam Kostrzewski
|
||||
Adrian Sampson
|
||||
Adrien Le Masle
|
||||
أحمد المحمودي (Ahmed El-Mahmoudy)
|
||||
|
|
|
|||
|
|
@ -1322,6 +1322,12 @@ AstNode* AstArraySel::baseFromp(AstNode* nodep, bool overMembers) {
|
|||
} else if (VN_IS(nodep, Sel)) {
|
||||
nodep = VN_AS(nodep, Sel)->fromp();
|
||||
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)) {
|
||||
nodep = VN_AS(nodep, MemberSel)->fromp();
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -530,8 +530,10 @@ class CoverageVisitor final : public VNVisitor {
|
|||
newent.cleanup();
|
||||
}
|
||||
}
|
||||
} else if (VN_IS(dtypep, QueueDType)) {
|
||||
} else if (VN_IS(dtypep, QueueDType) || VN_IS(dtypep, AssocArrayDType)
|
||||
|| VN_IS(dtypep, WildcardArrayDType)) {
|
||||
// Not covered
|
||||
varp->v3warn(COVERIGN, "Coverage ignored for type " << dtypep->prettyTypeName());
|
||||
} else {
|
||||
dtypep->v3fatalSrc("Unexpected node data type in toggle coverage generation: "
|
||||
<< dtypep->prettyTypeName());
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "V3Ast.h"
|
||||
#include "V3Control.h"
|
||||
#include "V3Graph.h"
|
||||
#include "V3UniqueNames.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
|
|
@ -987,14 +988,23 @@ class FsmDetectVisitor final : public VNVisitor {
|
|||
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,
|
||||
AstVarScope*& fromVscp) {
|
||||
AstNodeAssign* const assp = VN_CAST(nodep, NodeAssign);
|
||||
if (!assp) return nullptr;
|
||||
AstVarRef* const lhsp = VN_AS(assp->lhsp(), VarRef);
|
||||
UASSERT_OBJ(lhsp, assp, "register commit lhs should be normalized to a VarRef");
|
||||
AstVarRef* const lhsp = tryExtractVarRef(assp->lhsp());
|
||||
AstVarRef* const rhsp = VN_CAST(assp->rhsp(), VarRef);
|
||||
if (!rhsp) return nullptr;
|
||||
if (!rhsp || !lhsp) return nullptr;
|
||||
stateVscp = lhsp->varScopep();
|
||||
fromVscp = rhsp->varScopep();
|
||||
return assp;
|
||||
|
|
@ -1006,11 +1016,9 @@ class FsmDetectVisitor final : public VNVisitor {
|
|||
FsmStateValue& resetValue) {
|
||||
AstNodeAssign* const assp = VN_CAST(nodep, NodeAssign);
|
||||
if (!assp) return nullptr;
|
||||
AstVarRef* const lhsp = VN_AS(assp->lhsp(), VarRef);
|
||||
UASSERT_OBJ(lhsp, assp,
|
||||
"conditional register commit lhs should be normalized to a VarRef");
|
||||
AstVarRef* const lhsp = tryExtractVarRef(assp->lhsp());
|
||||
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 (constValueStatus(rhsp->thenp(), resetValue) != ConstValueStatus::OK)
|
||||
return nullptr;
|
||||
|
|
@ -1033,7 +1041,7 @@ class FsmDetectVisitor final : public VNVisitor {
|
|||
FsmStateValue& value) {
|
||||
AstNodeAssign* const assp = VN_CAST(nodep, NodeAssign);
|
||||
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,
|
||||
"direct constant state assignment lhs should be normalized to a VarRef");
|
||||
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);
|
||||
AstNodeExpr* valuep = eqp->rhsp();
|
||||
if (!vrefp) {
|
||||
vrefp = VN_AS(eqp->rhsp(), VarRef);
|
||||
vrefp = tryExtractVarRef(eqp->rhsp());
|
||||
if (!vrefp) { return false; }
|
||||
valuep = eqp->lhsp();
|
||||
}
|
||||
|
||||
|
|
@ -2082,6 +2091,7 @@ public:
|
|||
class FsmLowerVisitor final {
|
||||
// STATE - across all visitors
|
||||
const FsmState& m_state;
|
||||
V3UniqueNames m_fsmBuildNames;
|
||||
|
||||
// METHODS
|
||||
// Rebuild a state-typed constant using the tracked state variable
|
||||
|
|
@ -2133,8 +2143,8 @@ class FsmLowerVisitor final {
|
|||
AstNodeModule* const modp = scopep->modp();
|
||||
AstNodeDType* const prevDTypep = scopep->findLogicDType(
|
||||
sampleVscp->width(), sampleVscp->width(), sampleVscp->dtypep()->numeric());
|
||||
AstVarScope* const prevVscp
|
||||
= scopep->createTemp("__Vfsmcov_prev__" + stateVscp->varp()->shortName(), prevDTypep);
|
||||
const std::string tmpName = m_fsmBuildNames.get(stateVscp->varp()->shortName());
|
||||
AstVarScope* const prevVscp = scopep->createTemp(tmpName, prevDTypep);
|
||||
// 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
|
||||
// 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
|
||||
// still valid in the same pass.
|
||||
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); }
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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