Apply 'make format'
This commit is contained in:
parent
a680919edc
commit
e4da16caf0
|
|
@ -227,13 +227,13 @@ public:
|
|||
"ENCAPSULATED", "ENDLABEL", "ENUMITEMWIDTH", "ENUMVALUE", "EOFNEWLINE", "FSMMULTI",
|
||||
"FUNCTIMECTL", "FUTURE", "GENCLK", "GENUNNAMED", "HIERBLOCK", "HIERPARAM", "IFDEPTH",
|
||||
"IGNOREDRETURN", "IMPERFECTSCH", "IMPLICIT", "IMPLICITSTATIC", "IMPORTSTAR", "IMPURE",
|
||||
"INCABSPATH","INFINITELOOP", "INITIALDLY", "INSECURE", "INSIDETRUE", "LATCH",
|
||||
"INCABSPATH", "INFINITELOOP", "INITIALDLY", "INSECURE", "INSIDETRUE", "LATCH",
|
||||
"LITENDIAN", "MINTYPMAXDLY", "MISINDENT", "MODDUP", "MODMISSING", "MULTIDRIVEN",
|
||||
"MULTITOP", "NEWERSTD", "NOEFFECT", "NOLATCH", "NONSTD", "NORETURN", "NULLPORT",
|
||||
"PARAMNODEFAULT", "PINCONNECTEMPTY", "PINMISSING", "PINNOCONNECT", "PINNOTFOUND",
|
||||
"PKGNODECL", "PREPROCZERO", "PROCASSINIT", "PROCASSWIRE", "PROFOUTOFDATE", "PROTECTED",
|
||||
"PROTOTYPEMIS", "RANDC", "REALCVT", "REDEFMACRO", "RISEFALLDLY", "SELRANGE",
|
||||
"SHORTREAL", "SIDEEFFECT", "SPECIFYIGN", "SPLITVAR", "STATICVAR","STMTDLY",
|
||||
"SHORTREAL", "SIDEEFFECT", "SPECIFYIGN", "SPLITVAR", "STATICVAR", "STMTDLY",
|
||||
"SUPERNFIRST", "SYMRSVDWORD", "SYNCASYNCNET", "TICKCOUNT", "TIMESCALEMOD", "UNDRIVEN",
|
||||
"UNOPT", "UNOPTFLAT", "UNOPTTHREADS", "UNPACKED", "UNSATCONSTR", "UNSIGNED", "UNUSED",
|
||||
"UNUSEDGENVAR", "UNUSEDLOOP", "UNUSEDPARAM", "UNUSEDSIGNAL", "USERERROR", "USERFATAL",
|
||||
|
|
|
|||
|
|
@ -65,16 +65,16 @@ public:
|
|||
enum class Kind : uint8_t { STATE, RESET_ANY, DEFAULT_ANY };
|
||||
|
||||
private:
|
||||
Kind m_kind; // State vs synthetic ANY/default vertex role.
|
||||
Kind m_kind; // State vs synthetic ANY/default vertex role.
|
||||
string m_label; // User-facing state or pseudo-state label.
|
||||
int m_value = 0; // Encoded state value for real state vertices.
|
||||
|
||||
protected:
|
||||
FsmVertex(V3Graph* graphp, Kind kind, string label, int value) VL_MT_DISABLED
|
||||
: V3GraphVertex{graphp}
|
||||
, m_kind{kind}
|
||||
, m_label{label}
|
||||
, m_value{value} {}
|
||||
: V3GraphVertex{graphp},
|
||||
m_kind{kind},
|
||||
m_label{label},
|
||||
m_value{value} {}
|
||||
~FsmVertex() override = default;
|
||||
|
||||
public:
|
||||
|
|
@ -116,18 +116,17 @@ public:
|
|||
class FsmArcEdge final : public V3GraphEdge {
|
||||
VL_RTTI_IMPL(FsmArcEdge, V3GraphEdge)
|
||||
bool m_isReset = false; // Arc originates from the synthetic reset source.
|
||||
bool m_isCond = false; // Arc came from a conditional next-state split.
|
||||
bool m_isCond = false; // Arc came from a conditional next-state split.
|
||||
bool m_isDefault = false; // Arc represents a case default source.
|
||||
FileLine* m_flp = nullptr; // Source location for emitted coverage metadata.
|
||||
|
||||
public:
|
||||
FsmArcEdge(V3Graph* graphp, FsmVertex* fromp, FsmStateVertex* top, bool isReset,
|
||||
bool isCond, bool isDefault, FileLine* flp) VL_MT_DISABLED
|
||||
: V3GraphEdge{graphp, fromp, top, 1}
|
||||
, m_isReset{isReset}
|
||||
, m_isCond{isCond}
|
||||
, m_isDefault{isDefault}
|
||||
, m_flp{flp} {}
|
||||
FsmArcEdge(V3Graph* graphp, FsmVertex* fromp, FsmStateVertex* top, bool isReset, bool isCond,
|
||||
bool isDefault, FileLine* flp) VL_MT_DISABLED : V3GraphEdge{graphp, fromp, top, 1},
|
||||
m_isReset{isReset},
|
||||
m_isCond{isCond},
|
||||
m_isDefault{isDefault},
|
||||
m_flp{flp} {}
|
||||
~FsmArcEdge() override = default;
|
||||
|
||||
bool isReset() const { return m_isReset; }
|
||||
|
|
@ -159,18 +158,18 @@ class FsmGraph final : public V3Graph {
|
|||
AstVarScope* m_stateVarScopep = nullptr; // Scoped state variable being tracked.
|
||||
std::vector<FsmSenDesc> m_senses; // Saved event controls for recreated active blocks.
|
||||
FsmResetCondDesc m_resetCond; // Saved reset predicate shape, if one exists.
|
||||
bool m_hasResetCond = false; // Whether the detected FSM had a reset branch.
|
||||
bool m_hasResetCond = false; // Whether the detected FSM had a reset branch.
|
||||
bool m_resetInclude = false; // Whether reset arcs count toward coverage totals.
|
||||
bool m_inclCond = false; // Whether conditional arcs should be kept explicitly.
|
||||
FileLine* m_flp = nullptr; // Representative source location for declarations/arcs.
|
||||
bool m_inclCond = false; // Whether conditional arcs should be kept explicitly.
|
||||
FileLine* m_flp = nullptr; // Representative source location for declarations/arcs.
|
||||
std::unordered_map<int, FsmStateVertex*> m_stateVertices; // Value to state-vertex map.
|
||||
FsmPseudoVertex* m_resetVertexp = nullptr; // Synthetic ANY source for reset arcs.
|
||||
FsmPseudoVertex* m_defaultVertexp = nullptr; // Synthetic default source for case defaults.
|
||||
|
||||
public:
|
||||
FsmGraph() VL_MT_DISABLED
|
||||
: m_resetVertexp{new FsmPseudoVertex{this, FsmVertex::Kind::RESET_ANY, "ANY"}}
|
||||
, m_defaultVertexp{new FsmPseudoVertex{this, FsmVertex::Kind::DEFAULT_ANY, "default"}} {}
|
||||
: m_resetVertexp{new FsmPseudoVertex{this, FsmVertex::Kind::RESET_ANY, "ANY"}},
|
||||
m_defaultVertexp{new FsmPseudoVertex{this, FsmVertex::Kind::DEFAULT_ANY, "default"}} {}
|
||||
|
||||
AstScope* scopep() const { return m_scopep; }
|
||||
void scopep(AstScope* scopep) { m_scopep = scopep; }
|
||||
|
|
@ -269,9 +268,7 @@ class FsmDetectVisitor final : public VNVisitor {
|
|||
|
||||
// Reset arcs are only modeled for the simple signal form that survives to
|
||||
// this pass after earlier normalization.
|
||||
static bool isSimpleResetCond(AstNodeExpr* condp) {
|
||||
return VN_IS(condp, VarRef);
|
||||
}
|
||||
static bool isSimpleResetCond(AstNodeExpr* condp) { return VN_IS(condp, VarRef); }
|
||||
|
||||
// Normalize the reset condition into a compact description so the lowering
|
||||
// phase can regenerate the same predicate after detection. By the time
|
||||
|
|
@ -358,9 +355,8 @@ class FsmDetectVisitor final : public VNVisitor {
|
|||
static bool validateKnownStateValue(AstNode* nodep,
|
||||
const std::unordered_map<int, string>& labels, int value) {
|
||||
if (labels.find(value) != labels.end()) return true;
|
||||
nodep->v3warn(COVERIGN,
|
||||
"Ignoring unsupported: FSM coverage on enum state transitions "
|
||||
"that assign a constant not present in the declared enum");
|
||||
nodep->v3warn(COVERIGN, "Ignoring unsupported: FSM coverage on enum state transitions "
|
||||
"that assign a constant not present in the declared enum");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -405,8 +401,8 @@ class FsmDetectVisitor final : public VNVisitor {
|
|||
if (!validateKnownStateValue(condp->elsep(), labels, elseValue)) return true;
|
||||
for (const int branchValue : {thenValue, elseValue}) {
|
||||
for (const std::pair<string, int>& from : froms) {
|
||||
graph.addArc(from.second, branchValue, false, true,
|
||||
itemp->isDefault(), assp->fileline());
|
||||
graph.addArc(from.second, branchValue, false, true, itemp->isDefault(),
|
||||
assp->fileline());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
@ -425,7 +421,8 @@ class FsmDetectVisitor final : public VNVisitor {
|
|||
if (AstNodeAssign* const assp = VN_CAST(nodep, NodeAssign)) {
|
||||
AstVarRef* const vrefp = VN_CAST(assp->lhsp(), VarRef);
|
||||
int toValue = 0;
|
||||
if (vrefp && vrefp->varScopep() == stateVscp && exprConstValue(assp->rhsp(), toValue)) {
|
||||
if (vrefp && vrefp->varScopep() == stateVscp
|
||||
&& exprConstValue(assp->rhsp(), toValue)) {
|
||||
if (!validateKnownStateValue(assp, labels, toValue)) continue;
|
||||
graph.addArc(0, toValue, true, false, false, assp->fileline());
|
||||
}
|
||||
|
|
@ -450,12 +447,12 @@ class FsmDetectVisitor final : public VNVisitor {
|
|||
std::unordered_map<int, string> labels;
|
||||
if (enump) {
|
||||
if (stateVscp->width() < 1 || stateVscp->width() > 32) {
|
||||
casep->v3warn(COVERIGN,
|
||||
"Ignoring unsupported: FSM coverage on enum-typed state "
|
||||
"variables wider than 32 bits");
|
||||
casep->v3warn(COVERIGN, "Ignoring unsupported: FSM coverage on enum-typed state "
|
||||
"variables wider than 32 bits");
|
||||
return;
|
||||
}
|
||||
for (AstEnumItem* itemp = enump->itemsp(); itemp; itemp = VN_AS(itemp->nextp(), EnumItem)) {
|
||||
for (AstEnumItem* itemp = enump->itemsp(); itemp;
|
||||
itemp = VN_AS(itemp->nextp(), EnumItem)) {
|
||||
const AstConst* const constp = VN_AS(itemp->valuep(), Const);
|
||||
const int value = constp->toSInt();
|
||||
states.emplace_back(itemp->name(), value);
|
||||
|
|
@ -491,7 +488,8 @@ class FsmDetectVisitor final : public VNVisitor {
|
|||
entry.graphp->addStateVertex(state.first, state.second);
|
||||
}
|
||||
}
|
||||
for (AstCaseItem* itemp = casep->itemsp(); itemp; itemp = VN_AS(itemp->nextp(), CaseItem)) {
|
||||
for (AstCaseItem* itemp = casep->itemsp(); itemp;
|
||||
itemp = VN_AS(itemp->nextp(), CaseItem)) {
|
||||
emitCaseItemArcs(*entry.graphp, itemp, stateVscp, labels, entry.graphp->inclCond());
|
||||
}
|
||||
}
|
||||
|
|
@ -508,12 +506,13 @@ class FsmDetectVisitor final : public VNVisitor {
|
|||
AstIf* const firstIfp = VN_CAST(stmtsp, If);
|
||||
if (firstIfp) {
|
||||
if (AstCase* const casep = VN_CAST(firstIfp->elsesp(), Case)) {
|
||||
candidates.emplace_back(casep, isSimpleResetCond(firstIfp->condp()) ? firstIfp->condp()
|
||||
: nullptr);
|
||||
candidates.emplace_back(
|
||||
casep, isSimpleResetCond(firstIfp->condp()) ? firstIfp->condp() : nullptr);
|
||||
}
|
||||
}
|
||||
for (AstNode* nodep = stmtsp; nodep; nodep = nodep->nextp()) {
|
||||
if (AstCase* const casep = VN_CAST(nodep, Case)) candidates.emplace_back(casep, nullptr);
|
||||
if (AstCase* const casep = VN_CAST(nodep, Case))
|
||||
candidates.emplace_back(casep, nullptr);
|
||||
}
|
||||
if (candidates.empty()) return;
|
||||
|
||||
|
|
@ -531,11 +530,10 @@ class FsmDetectVisitor final : public VNVisitor {
|
|||
"the same always block. Only the first candidate will be "
|
||||
"instrumented.");
|
||||
} else {
|
||||
cand.first->v3warn(
|
||||
COVERIGN,
|
||||
"Ignoring unsupported: FSM coverage on multiple supported case "
|
||||
"statements found in the same always block. Only the first "
|
||||
"candidate will be instrumented.");
|
||||
cand.first->v3warn(COVERIGN,
|
||||
"Ignoring unsupported: FSM coverage on multiple supported case "
|
||||
"statements found in the same always block. Only the first "
|
||||
"candidate will be instrumented.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -608,13 +606,12 @@ class FsmLowerVisitor final {
|
|||
|
||||
// Rebuild the original event control from the saved sense description so
|
||||
// post-state coverage sampling runs on the same triggering edges.
|
||||
static AstSenTree* buildSenTree(
|
||||
FileLine* flp, const std::vector<FsmSenDesc>& senses) {
|
||||
static AstSenTree* buildSenTree(FileLine* flp, const std::vector<FsmSenDesc>& senses) {
|
||||
AstSenTree* const sentreep = new AstSenTree{flp, nullptr};
|
||||
for (const FsmSenDesc& sense : senses) {
|
||||
AstSenItem* const senItemp = new AstSenItem{
|
||||
flp, VEdgeType{sense.edgeType},
|
||||
new AstVarRef{flp, sense.varScopep, VAccess::READ}};
|
||||
AstSenItem* const senItemp
|
||||
= new AstSenItem{flp, VEdgeType{sense.edgeType},
|
||||
new AstVarRef{flp, sense.varScopep, VAccess::READ}};
|
||||
sentreep->addSensesp(senItemp);
|
||||
}
|
||||
return sentreep;
|
||||
|
|
@ -629,9 +626,8 @@ class FsmLowerVisitor final {
|
|||
AstVarScope* const stateVscp = graph.stateVarScopep();
|
||||
FileLine* const flp = graph.fileline();
|
||||
AstNodeModule* const modp = scopep->modp();
|
||||
AstNodeDType* const prevDTypep
|
||||
= scopep->findLogicDType(stateVscp->width(), stateVscp->width(),
|
||||
stateVscp->dtypep()->numeric());
|
||||
AstNodeDType* const prevDTypep = scopep->findLogicDType(
|
||||
stateVscp->width(), stateVscp->width(), stateVscp->dtypep()->numeric());
|
||||
AstVarScope* const prevVscp
|
||||
= scopep->createTemp("__Vfsmcov_prev__" + stateVscp->varp()->shortName(), prevDTypep);
|
||||
// The saved previous-state temp crosses the scheduler's pre/post split
|
||||
|
|
@ -667,10 +663,15 @@ class FsmLowerVisitor final {
|
|||
const FsmStateVertex* const statep = vtx.as<FsmStateVertex>();
|
||||
// State coverage fires when the FSM enters a state from any other
|
||||
// value, so repeated self-holds do not count as new entries.
|
||||
AstCoverOtherDecl* const declp = new AstCoverOtherDecl{
|
||||
flp, "v_fsm_state/" + modp->prettyName(),
|
||||
graph.stateVarName() + "::" + statep->label(), "", 0, graph.stateVarName(), "",
|
||||
statep->label()};
|
||||
AstCoverOtherDecl* const declp
|
||||
= new AstCoverOtherDecl{flp,
|
||||
"v_fsm_state/" + modp->prettyName(),
|
||||
graph.stateVarName() + "::" + statep->label(),
|
||||
"",
|
||||
0,
|
||||
graph.stateVarName(),
|
||||
"",
|
||||
statep->label()};
|
||||
declp->hier(scopep->prettyName());
|
||||
modp->addStmtsp(declp);
|
||||
AstNodeExpr* const guardp
|
||||
|
|
@ -691,21 +692,23 @@ class FsmLowerVisitor final {
|
|||
// reset and synthetic-default sources, so reports match the
|
||||
// reviewer-visible graph dump and the user-visible annotation.
|
||||
const string resetTag
|
||||
= arcp->isReset() ? (graph.resetInclude() ? "[reset_include]" : "[reset]") : "";
|
||||
const string fsmTag = arcp->isReset() ? (graph.resetInclude() ? "reset_include"
|
||||
: "reset")
|
||||
: arcp->isDefault() ? "default"
|
||||
: "";
|
||||
AstCoverOtherDecl* const declp = new AstCoverOtherDecl{
|
||||
flp, "v_fsm_arc/" + modp->prettyName(),
|
||||
graph.stateVarName() + "::" + fromVertexp->label() + "->" + toStatep->label()
|
||||
+ resetTag,
|
||||
"",
|
||||
0,
|
||||
graph.stateVarName(),
|
||||
fromVertexp->label(),
|
||||
toStatep->label(),
|
||||
fsmTag};
|
||||
= arcp->isReset() ? (graph.resetInclude() ? "[reset_include]" : "[reset]")
|
||||
: "";
|
||||
const string fsmTag = arcp->isReset()
|
||||
? (graph.resetInclude() ? "reset_include" : "reset")
|
||||
: arcp->isDefault() ? "default"
|
||||
: "";
|
||||
AstCoverOtherDecl* const declp
|
||||
= new AstCoverOtherDecl{flp,
|
||||
"v_fsm_arc/" + modp->prettyName(),
|
||||
graph.stateVarName() + "::" + fromVertexp->label()
|
||||
+ "->" + toStatep->label() + resetTag,
|
||||
"",
|
||||
0,
|
||||
graph.stateVarName(),
|
||||
fromVertexp->label(),
|
||||
toStatep->label(),
|
||||
fsmTag};
|
||||
declp->hier(scopep->prettyName());
|
||||
modp->addStmtsp(declp);
|
||||
AstNodeExpr* guardp = nullptr;
|
||||
|
|
@ -733,12 +736,12 @@ class FsmLowerVisitor final {
|
|||
new AstEq{flp, new AstVarRef{flp, stateVscp, VAccess::READ},
|
||||
makeStateConst(flp, stateVscp, toStatep->value())});
|
||||
} else {
|
||||
guardp = andExpr(
|
||||
flp,
|
||||
new AstEq{flp, new AstVarRef{flp, prevVscp, VAccess::READ},
|
||||
makeStateConst(flp, prevVscp, fromVertexp->value())},
|
||||
new AstEq{flp, new AstVarRef{flp, stateVscp, VAccess::READ},
|
||||
makeStateConst(flp, stateVscp, toStatep->value())});
|
||||
guardp
|
||||
= andExpr(flp,
|
||||
new AstEq{flp, new AstVarRef{flp, prevVscp, VAccess::READ},
|
||||
makeStateConst(flp, prevVscp, fromVertexp->value())},
|
||||
new AstEq{flp, new AstVarRef{flp, stateVscp, VAccess::READ},
|
||||
makeStateConst(flp, stateVscp, toStatep->value())});
|
||||
}
|
||||
covPostp->addStmtsp(new AstIf{flp, guardp, new AstCoverInc{flp, declp}});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -448,8 +448,7 @@ private:
|
|||
void optimize(int level);
|
||||
void showVersion(bool verbose);
|
||||
void coverage(bool flag) {
|
||||
m_coverageLine = m_coverageToggle = m_coverageExpr = m_coverageFsm = m_coverageUser
|
||||
= flag;
|
||||
m_coverageLine = m_coverageToggle = m_coverageExpr = m_coverageFsm = m_coverageUser = flag;
|
||||
}
|
||||
static bool suffixed(const string& sw, const char* arg);
|
||||
static string parseFileArg(const string& optdir, const string& relfilename);
|
||||
|
|
|
|||
|
|
@ -54,8 +54,8 @@
|
|||
#include "V3Expand.h"
|
||||
#include "V3File.h"
|
||||
#include "V3Force.h"
|
||||
#include "V3FsmDetect.h"
|
||||
#include "V3Fork.h"
|
||||
#include "V3FsmDetect.h"
|
||||
#include "V3FuncOpt.h"
|
||||
#include "V3Gate.h"
|
||||
#include "V3Global.h"
|
||||
|
|
|
|||
|
|
@ -25,12 +25,8 @@ tree_texts = [filename.read_text(encoding="utf8") for filename in tree_files]
|
|||
assert any("COVEROTHERDECL" in text and " fv=t.state" in text for text in tree_texts)
|
||||
assert any(
|
||||
"COVEROTHERDECL" in text and " ff=ANY" in text and " ft=S0" in text and " fg=reset" in text
|
||||
for text in tree_texts
|
||||
)
|
||||
assert any(
|
||||
"COVEROTHERDECL" in text and " ff=default" in text and " ft=S0" in text and " fg=default"
|
||||
in text
|
||||
for text in tree_texts
|
||||
)
|
||||
for text in tree_texts)
|
||||
assert any("COVEROTHERDECL" in text and " ff=default" in text and " ft=S0" in text
|
||||
and " fg=default" in text for text in tree_texts)
|
||||
|
||||
test.passes()
|
||||
|
|
|
|||
|
|
@ -14,9 +14,7 @@ test.scenarios('vlt')
|
|||
# When an enum-backed FSM assigns a constant that is not one of the declared
|
||||
# enum items, FSM coverage should warn and skip the unsupported edge rather
|
||||
# than turning optional coverage into a hard compile failure.
|
||||
test.lint(
|
||||
verilator_flags2=["--coverage-fsm"],
|
||||
fails=True)
|
||||
test.lint(verilator_flags2=["--coverage-fsm"], fails=True)
|
||||
|
||||
test.file_grep(
|
||||
test.compile_log_filename,
|
||||
|
|
|
|||
|
|
@ -13,9 +13,7 @@ test.scenarios('vlt')
|
|||
|
||||
# FSM coverage currently stores recovered enum state values in the detector's
|
||||
# 32-bit internal representation, so wider enum-backed FSMs are rejected.
|
||||
test.lint(
|
||||
verilator_flags2=["--coverage-fsm"],
|
||||
fails=True)
|
||||
test.lint(verilator_flags2=["--coverage-fsm"], fails=True)
|
||||
|
||||
test.file_grep(
|
||||
test.compile_log_filename,
|
||||
|
|
|
|||
|
|
@ -24,9 +24,8 @@ tree_texts = [filename.read_text(encoding="utf8") for filename in tree_files]
|
|||
|
||||
generic_lines = []
|
||||
for text in tree_texts:
|
||||
generic_lines.extend(
|
||||
line for line in text.splitlines() if "COVEROTHERDECL" in line and " page=v_line/" in line
|
||||
)
|
||||
generic_lines.extend(line for line in text.splitlines()
|
||||
if "COVEROTHERDECL" in line and " page=v_line/" in line)
|
||||
|
||||
assert generic_lines
|
||||
assert any(" fv=" not in line and " ff=" not in line and " ft=" not in line and " fg=" not in line
|
||||
|
|
|
|||
|
|
@ -15,9 +15,7 @@ test.scenarios('vlt')
|
|||
# always_ff now warn and keep only the first candidate instrumented. Different-
|
||||
# state multi-candidate cases still use the existing FSMMULTI warning path; this
|
||||
# test locks down only the same-state unsupported form.
|
||||
test.lint(
|
||||
verilator_flags2=["--coverage-fsm"],
|
||||
fails=True)
|
||||
test.lint(verilator_flags2=["--coverage-fsm"], fails=True)
|
||||
|
||||
test.file_grep(
|
||||
test.compile_log_filename,
|
||||
|
|
|
|||
|
|
@ -11,9 +11,6 @@ import vltest_bootstrap
|
|||
|
||||
test.scenarios('vlt')
|
||||
|
||||
test.lint(
|
||||
verilator_flags2=["--coverage-fsm"],
|
||||
fails=True,
|
||||
expect_filename=test.golden_filename)
|
||||
test.lint(verilator_flags2=["--coverage-fsm"], fails=True, expect_filename=test.golden_filename)
|
||||
|
||||
test.passes()
|
||||
|
|
|
|||
Loading…
Reference in New Issue