mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 01:54:01 +02:00
+8
-1
@@ -1442,6 +1442,8 @@ class AstEnumItemRef final : public AstNodeExpr {
|
||||
// @astgen ptr := m_itemp : Optional[AstEnumItem] // [AfterLink] Pointer to item
|
||||
// @astgen ptr := m_classOrPackagep : Optional[AstNodeModule] // Class/package defined in
|
||||
string m_name; // Name of enum (for param relink)
|
||||
string m_dotted; // Dotted part of scope the name()'ed reference is under or ""
|
||||
bool m_containsGenBlock = false; // Contains gen block reference
|
||||
public:
|
||||
AstEnumItemRef(FileLine* fl, AstEnumItem* itemp, AstNodeModule* classOrPackagep)
|
||||
: ASTGEN_SUPER_EnumItemRef(fl)
|
||||
@@ -1458,10 +1460,15 @@ public:
|
||||
int instrCount() const override { return 0; }
|
||||
bool sameNode(const AstNode* samep) const override {
|
||||
const AstEnumItemRef* const sp = VN_DBG_AS(samep, EnumItemRef);
|
||||
return itemp() == sp->itemp();
|
||||
return itemp() == sp->itemp() && dotted() == sp->dotted()
|
||||
&& containsGenBlock() == sp->containsGenBlock();
|
||||
}
|
||||
AstEnumItem* itemp() const VL_MT_STABLE { return m_itemp; }
|
||||
void itemp(AstEnumItem* nodep) { m_itemp = nodep; }
|
||||
string dotted() const { return m_dotted; }
|
||||
void dotted(const string& dotted) { m_dotted = dotted; }
|
||||
bool containsGenBlock() const { return m_containsGenBlock; }
|
||||
void containsGenBlock(const bool flag) { m_containsGenBlock = flag; }
|
||||
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
||||
string emitC() override { V3ERROR_NA_RETURN(""); }
|
||||
bool cleanOut() const override { return true; }
|
||||
|
||||
+7
-1
@@ -1482,6 +1482,8 @@ const char* AstEnumItemRef::broken() const {
|
||||
}
|
||||
void AstEnumItemRef::dump(std::ostream& str) const {
|
||||
Super::dump(str);
|
||||
if (containsGenBlock()) str << " [GENBLK]";
|
||||
if (!dotted().empty()) str << " .=" << dotted();
|
||||
str << " -> ";
|
||||
if (itemp()) {
|
||||
itemp()->dump(str);
|
||||
@@ -1489,7 +1491,11 @@ void AstEnumItemRef::dump(std::ostream& str) const {
|
||||
str << "UNLINKED";
|
||||
}
|
||||
}
|
||||
void AstEnumItemRef::dumpJson(std::ostream& str) const { dumpJsonGen(str); }
|
||||
void AstEnumItemRef::dumpJson(std::ostream& str) const {
|
||||
dumpJsonBoolFuncIf(str, containsGenBlock);
|
||||
dumpJsonStrFunc(str, dotted);
|
||||
dumpJsonGen(str);
|
||||
}
|
||||
AstNodeBiop* AstEq::newTyped(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp) {
|
||||
if (lhsp->isString() && rhsp->isString()) {
|
||||
return new AstEqN{fl, lhsp, rhsp};
|
||||
|
||||
+72
-31
@@ -3510,6 +3510,37 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||
<< " search start due to inlinedDots=" << inlinedDots);
|
||||
return dotSymp;
|
||||
}
|
||||
VSymEnt* findDottedRefSymp(AstNode* nodep, VSymEnt* lookupSymp, const string& dotted,
|
||||
string& baddot, VSymEnt*& okSymp, bool* modportp = nullptr) {
|
||||
// Return scope to search for a relinked hierarchical reference
|
||||
// (AstVarXRef or AstEnumItemRef), or nullptr after error if not found
|
||||
// If modportp is given, set true when the reference went through a modport
|
||||
if (modportp) *modportp = false;
|
||||
VSymEnt* dotSymp = m_statep->findDotted(nodep->fileline(), lookupSymp, dotted, baddot,
|
||||
okSymp, true); // Maybe nullptr
|
||||
if (!dotSymp) {
|
||||
nodep->v3error(
|
||||
"Can't find definition of "
|
||||
<< (!baddot.empty() ? AstNode::prettyNameQ(baddot) : nodep->prettyNameQ()) << '\n'
|
||||
<< nodep->warnContextPrimary());
|
||||
return nullptr;
|
||||
}
|
||||
if (const AstVar* const varp = VN_CAST(dotSymp->nodep(), Var)) {
|
||||
if (const AstIfaceRefDType* const ifaceRefp
|
||||
= VN_CAST(varp->childDTypep(), IfaceRefDType)) {
|
||||
if (ifaceRefp->modportp()) {
|
||||
dotSymp = m_statep->getNodeSym(ifaceRefp->modportp());
|
||||
if (modportp) *modportp = true;
|
||||
} else {
|
||||
dotSymp = m_statep->getNodeSym(ifaceRefp->ifacep());
|
||||
}
|
||||
}
|
||||
} else if (const AstModportClockingRef* const clockingRefp
|
||||
= VN_CAST(dotSymp->nodep(), ModportClockingRef)) {
|
||||
dotSymp = m_statep->getNodeSym(clockingRefp->clockingp());
|
||||
}
|
||||
return dotSymp;
|
||||
}
|
||||
|
||||
static bool isParamedClassRefDType(const AstNode* classp) {
|
||||
while (const AstRefDType* const refp = VN_CAST(classp, RefDType))
|
||||
@@ -4731,8 +4762,20 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||
}
|
||||
} else if (AstEnumItem* const valuep = VN_CAST(foundp->nodep(), EnumItem)) {
|
||||
if (allowVar) {
|
||||
AstNode* const newp
|
||||
AstEnumItemRef* const refp
|
||||
= new AstEnumItemRef{nodep->fileline(), valuep, foundp->classOrPackagep()};
|
||||
AstNode* newp = refp;
|
||||
// Hierarchical reference, relinked after V3Param as the referenced
|
||||
// module may be specialized, similar to AstVarXRef
|
||||
refp->dotted(m_ds.m_dotText);
|
||||
refp->containsGenBlock(m_ds.m_genBlk);
|
||||
if (m_ds.m_unresolvedCell && m_ds.m_unlinkedScopep) {
|
||||
UINFO(9, indent() << "deferring until post-V3Param: " << refp);
|
||||
newp = new AstUnlinkedRef{nodep->fileline(), refp, refp->name(),
|
||||
m_ds.m_unlinkedScopep->unlinkFrBack()};
|
||||
m_ds.m_unlinkedScopep = nullptr;
|
||||
m_ds.m_unresolvedCell = false;
|
||||
}
|
||||
nodep->replaceWith(newp);
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
ok = true;
|
||||
@@ -5028,38 +5071,16 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||
UINFO(9, "Dead module for " << nodep);
|
||||
nodep->varp(nullptr);
|
||||
} else {
|
||||
VSymEnt* lookupSymp = m_curSymp; // Start search at current scope
|
||||
if (nodep->inlinedDots() != "") { // Correct for current post-inlined scope
|
||||
lookupSymp = findInlinedDotsSym(nodep, nodep->inlinedDots());
|
||||
}
|
||||
string baddot;
|
||||
VSymEnt* okSymp;
|
||||
VSymEnt* dotSymp = m_curSymp; // Start search at current scope
|
||||
if (nodep->inlinedDots() != "") { // Correct for current post-inlined scope
|
||||
dotSymp = findInlinedDotsSym(nodep, nodep->inlinedDots());
|
||||
}
|
||||
dotSymp = m_statep->findDotted(nodep->fileline(), dotSymp, nodep->dotted(), baddot,
|
||||
okSymp, true); // Maybe nullptr
|
||||
if (!dotSymp) {
|
||||
nodep->v3error(
|
||||
"Can't find definition of "
|
||||
<< (!baddot.empty() ? AstNode::prettyNameQ(baddot) : nodep->prettyNameQ())
|
||||
<< '\n'
|
||||
<< nodep->warnContextPrimary());
|
||||
return;
|
||||
}
|
||||
|
||||
bool modport = false;
|
||||
if (const AstVar* const varp = VN_CAST(dotSymp->nodep(), Var)) {
|
||||
if (const AstIfaceRefDType* const ifaceRefp
|
||||
= VN_CAST(varp->childDTypep(), IfaceRefDType)) {
|
||||
if (ifaceRefp->modportp()) {
|
||||
dotSymp = m_statep->getNodeSym(ifaceRefp->modportp());
|
||||
modport = true;
|
||||
} else {
|
||||
dotSymp = m_statep->getNodeSym(ifaceRefp->ifacep());
|
||||
}
|
||||
}
|
||||
} else if (const AstModportClockingRef* const clockingRefp
|
||||
= VN_CAST(dotSymp->nodep(), ModportClockingRef)) {
|
||||
dotSymp = m_statep->getNodeSym(clockingRefp->clockingp());
|
||||
}
|
||||
bool modport;
|
||||
VSymEnt* const dotSymp
|
||||
= findDottedRefSymp(nodep, lookupSymp, nodep->dotted(), baddot, okSymp, &modport);
|
||||
if (!dotSymp) return;
|
||||
|
||||
if (!m_statep->forScopeCreation()) {
|
||||
VSymEnt* foundp = nullptr;
|
||||
@@ -5157,7 +5178,27 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||
// EnumItemRefs are created by the first pass, but V3Param may regenerate due to
|
||||
// a parameterized class/module, so we shouldn't get can't find errors.
|
||||
// No checkNoDot; created and iterated from a parseRef
|
||||
if (nodep->user3SetOnce()) return;
|
||||
LINKDOT_VISIT_START();
|
||||
if (m_statep->forParamed() && !nodep->dotted().empty() && m_modSymp) {
|
||||
// Hierarchical reference, relink as V3Param may have specialized the module
|
||||
string baddot;
|
||||
VSymEnt* okSymp = nullptr;
|
||||
VSymEnt* const dotSymp
|
||||
= findDottedRefSymp(nodep, m_curSymp, nodep->dotted(), baddot, okSymp);
|
||||
if (!dotSymp) return;
|
||||
VSymEnt* const foundp
|
||||
= m_statep->findSymPrefixed(dotSymp, nodep->name(), baddot, true);
|
||||
AstEnumItem* const itemp = foundp ? VN_CAST(foundp->nodep(), EnumItem) : nullptr;
|
||||
if (!itemp) {
|
||||
nodep->v3error("Enum item " << nodep->prettyNameQ() << " not found in "
|
||||
<< AstNode::prettyNameQ(nodep->dotted()) << '\n'
|
||||
<< nodep->warnContextPrimary());
|
||||
return;
|
||||
}
|
||||
nodep->itemp(itemp);
|
||||
UINFO(9, indent() << " relinked " << nodep);
|
||||
}
|
||||
if (!nodep->itemp()) {
|
||||
UINFO(9, indent() << "linkEnumRef se" << cvtToHex(m_curSymp) << " n=" << nodep);
|
||||
UASSERT_OBJ(m_curSymp, nodep, "nullptr lookup symbol table");
|
||||
|
||||
+11
-1
@@ -3387,6 +3387,11 @@ class ParamVisitor final : public VNVisitor {
|
||||
}
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
void visit(AstEnumItemRef* nodep) override {
|
||||
// Needs relink, as may remove pointed-to item
|
||||
if (nodep->containsGenBlock()) nodep->itemp(nullptr);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
void visit(AstVarXRef* nodep) override {
|
||||
if (nodep->containsGenBlock()) {
|
||||
// Needs relink, as may remove pointed-to var
|
||||
@@ -3466,10 +3471,13 @@ class ParamVisitor final : public VNVisitor {
|
||||
void visit(AstUnlinkedRef* nodep) override {
|
||||
AstVarXRef* const varxrefp = VN_CAST(nodep->refp(), VarXRef);
|
||||
AstNodeFTaskRef* const taskrefp = VN_CAST(nodep->refp(), NodeFTaskRef);
|
||||
AstEnumItemRef* const enumrefp = VN_CAST(nodep->refp(), EnumItemRef);
|
||||
if (varxrefp) {
|
||||
m_unlinkedTxt = varxrefp->dotted();
|
||||
} else if (taskrefp) {
|
||||
m_unlinkedTxt = taskrefp->dotted();
|
||||
} else if (enumrefp) {
|
||||
m_unlinkedTxt = enumrefp->dotted();
|
||||
} else {
|
||||
nodep->v3fatalSrc("Unexpected AstUnlinkedRef node");
|
||||
return;
|
||||
@@ -3478,8 +3486,10 @@ class ParamVisitor final : public VNVisitor {
|
||||
|
||||
if (varxrefp) {
|
||||
varxrefp->dotted(m_unlinkedTxt);
|
||||
} else {
|
||||
} else if (taskrefp) {
|
||||
taskrefp->dotted(m_unlinkedTxt);
|
||||
} else {
|
||||
enumrefp->dotted(m_unlinkedTxt);
|
||||
}
|
||||
nodep->replaceWith(nodep->refp()->unlinkFrBack());
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
|
||||
@@ -307,6 +307,16 @@ module Vt_debug_emitv_t;
|
||||
$stop;
|
||||
end
|
||||
sub.r = 62.0;
|
||||
do begin
|
||||
if ((SUB_B !== 2'h1)) begin
|
||||
begin
|
||||
$write("%%Error: %s:%0d: got=%0d exp=%0d\n",
|
||||
136'h742f745f64656275675f656d6974762e76,
|
||||
'sh105, SUB_B, 2'h1);
|
||||
$stop;
|
||||
end
|
||||
end
|
||||
end while (1'h0)
|
||||
mod_res = (mod_val % 'sh5);
|
||||
$display("%g", $log10(r));
|
||||
$display("%g", $ln(r));
|
||||
@@ -1498,6 +1508,12 @@ interface Vt_debug_emitv_Iface;
|
||||
endinterface
|
||||
module Vt_debug_emitv_sub;
|
||||
input logic clk;
|
||||
/* generate */ begin : sub_gen
|
||||
typedef enum logic [1:0] {
|
||||
SUB_A = 2'h0,
|
||||
SUB_B = 2'h1
|
||||
} sub_e;
|
||||
end : sub_gen
|
||||
task inc;
|
||||
input int signed i;
|
||||
output int signed o;
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
// SPDX-FileCopyrightText: 2020 Wilson Snyder
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||
|
||||
package Pkg;
|
||||
localparam PKG_PARAM = 1;
|
||||
|
||||
@@ -256,6 +258,7 @@ module t (/*AUTOARG*/
|
||||
|
||||
if (Pkg::PKG_PARAM != 1) $stop;
|
||||
sub.r = 62.0;
|
||||
`checkd(sub.sub_gen.SUB_B, 2'd1);
|
||||
|
||||
mod_res = mod_val % 5;
|
||||
|
||||
@@ -479,6 +482,9 @@ module t (/*AUTOARG*/
|
||||
endmodule
|
||||
|
||||
module sub(input logic clk);
|
||||
if (1) begin : sub_gen
|
||||
typedef enum logic [1:0] {SUB_A, SUB_B} sub_e;
|
||||
end
|
||||
task inc(input int i, output int o);
|
||||
o = {1'b0, i[31:1]} + 32'd1;
|
||||
endtask
|
||||
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# 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=["--binary"])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
@@ -0,0 +1,91 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain
|
||||
// SPDX-FileCopyrightText: 2026 Saqib Khan
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// Enum item referenced through a parameterized instance (#8347) (#8389)
|
||||
|
||||
// verilog_format: off
|
||||
`define stop $stop
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
interface ifc #(
|
||||
parameter int W = 1
|
||||
);
|
||||
typedef enum logic [3:0] {
|
||||
I_IDLE = 1,
|
||||
I_WORK = 4'(W)
|
||||
} state_t;
|
||||
endinterface
|
||||
|
||||
module child #(
|
||||
parameter int W = 1
|
||||
);
|
||||
typedef enum logic [4:0] {
|
||||
S_IDLE = 0,
|
||||
S_WORK = 5'(W)
|
||||
} state_t;
|
||||
state_t fsm = S_WORK;
|
||||
if (1) begin : blk
|
||||
typedef enum logic [4:0] {
|
||||
B_IDLE = 0,
|
||||
B_WORK = 5'(W + 10)
|
||||
} blk_t;
|
||||
end
|
||||
if (W == 1) begin : gif
|
||||
typedef enum logic [4:0] {G_ONE = 21} one_t;
|
||||
end else begin : gif
|
||||
typedef enum logic [4:0] {G_OTHER = 22} other_t;
|
||||
end
|
||||
endmodule
|
||||
|
||||
module sub (
|
||||
ifc i
|
||||
);
|
||||
int work;
|
||||
initial work = int'(i.I_WORK);
|
||||
endmodule
|
||||
|
||||
module t;
|
||||
child #(.W(2)) a ();
|
||||
child #(.W(3)) b ();
|
||||
child c ();
|
||||
for (genvar g = 0; g < 2; ++g) begin : gen
|
||||
child #(.W(g + 4)) u ();
|
||||
wire working = u.fsm == u.S_WORK;
|
||||
int work = int'(u.S_WORK);
|
||||
end
|
||||
ifc #(.W(6)) i6 ();
|
||||
ifc #(.W(7)) i7[2] ();
|
||||
sub s (.i(i6));
|
||||
|
||||
wire working = a.fsm == a.S_WORK;
|
||||
|
||||
initial begin
|
||||
#1;
|
||||
`checkd(working, 1'b1);
|
||||
`checkd(a.S_IDLE, 0);
|
||||
`checkd(a.S_WORK, 2);
|
||||
`checkd(b.S_WORK, 3);
|
||||
`checkd(c.S_WORK, 1);
|
||||
`checkd(a.fsm, a.S_WORK);
|
||||
`checkd(b.fsm, b.S_WORK);
|
||||
`checkd(a.blk.B_WORK, 12);
|
||||
`checkd(t.b.blk.B_WORK, 13);
|
||||
`checkd(b.gif.G_OTHER, 22);
|
||||
`checkd(gen[0].working, 1'b1);
|
||||
`checkd(gen[1].working, 1'b1);
|
||||
`checkd(gen[0].work, 4);
|
||||
`checkd(gen[1].work, 5);
|
||||
`checkd(gen[0].u.S_WORK, 4);
|
||||
`checkd(gen[1].u.S_WORK, 5);
|
||||
`checkd(i6.I_WORK, 6);
|
||||
`checkd(i7[0].I_WORK, 7);
|
||||
`checkd(i7[1].I_WORK, 7);
|
||||
`checkd(s.work, 6);
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
@@ -0,0 +1,10 @@
|
||||
%Error: t/t_enum_param_xref_bad.v:26:27: Can't find definition of 'u'
|
||||
: ... note: In instance 't'
|
||||
26 | int bad = int'(gen[2].u.S_WORK);
|
||||
| ^~~~~~
|
||||
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
||||
%Error: t/t_enum_param_xref_bad.v:27:27: Enum item 'G_OTHER' not found in 'one.gif'
|
||||
: ... note: In instance 't'
|
||||
27 | int bad2 = int'(one.gif.G_OTHER);
|
||||
| ^~~~~~~
|
||||
%Error: Exiting due to
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# 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('linter')
|
||||
|
||||
test.lint(fails=True, expect_filename=test.golden_filename)
|
||||
|
||||
test.passes()
|
||||
@@ -0,0 +1,28 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain
|
||||
// SPDX-FileCopyrightText: 2026 Saqib Khan
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module child #(
|
||||
parameter int W = 1
|
||||
);
|
||||
typedef enum logic [4:0] {
|
||||
S_IDLE = 0,
|
||||
S_WORK = 5'(W)
|
||||
} state_t;
|
||||
if (W == 1) begin : gif
|
||||
typedef enum logic [4:0] {G_ONE = 21} one_t;
|
||||
end else begin : gif
|
||||
typedef enum logic [4:0] {G_OTHER = 22} other_t;
|
||||
end
|
||||
endmodule
|
||||
|
||||
module t;
|
||||
for (genvar g = 0; g < 2; ++g) begin : gen
|
||||
child #(.W(g + 4)) u ();
|
||||
end
|
||||
child #(.W(1)) one ();
|
||||
int bad = int'(gen[2].u.S_WORK);
|
||||
int bad2 = int'(one.gif.G_OTHER);
|
||||
endmodule
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# 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('linter')
|
||||
|
||||
test.lint(verilator_flags2=["--timing"])
|
||||
|
||||
test.passes()
|
||||
@@ -0,0 +1,35 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain
|
||||
// SPDX-FileCopyrightText: 2026 Saqib Khan
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// Enum item through a parameterized instance in randomize-with (#8347) (#8389)
|
||||
|
||||
class Item;
|
||||
rand int x;
|
||||
endclass
|
||||
|
||||
module child #(
|
||||
parameter int W = 1
|
||||
);
|
||||
typedef enum logic [1:0] {
|
||||
S_IDLE = 0,
|
||||
S_WORK = 2'(W)
|
||||
} state_t;
|
||||
endmodule
|
||||
|
||||
module t;
|
||||
child #(.W(2)) a ();
|
||||
child #(.W(3)) b ();
|
||||
Item items[4];
|
||||
|
||||
initial begin
|
||||
items[a.S_WORK] = new;
|
||||
items[b.S_WORK] = new;
|
||||
// Same enum item reference in randomize object and constraint
|
||||
void'(items[a.S_WORK].randomize() with {items[a.S_WORK].x == 5;});
|
||||
// Different enum item references
|
||||
void'(items[a.S_WORK].randomize() with {items[b.S_WORK].x == 5;});
|
||||
end
|
||||
endmodule
|
||||
Reference in New Issue
Block a user