parent
6303eb45ce
commit
8791e6c5f2
|
|
@ -514,11 +514,6 @@ class RandomizeMarkVisitor final : public VNVisitor {
|
||||||
= VN_CAST(methodCallp->fromp(), ConstraintRef)) {
|
= VN_CAST(methodCallp->fromp(), ConstraintRef)) {
|
||||||
constrp = constrRefp->constrp();
|
constrp = constrRefp->constrp();
|
||||||
if (constrRefp->fromp()) classp = VN_AS(constrRefp->classOrPackagep(), Class);
|
if (constrRefp->fromp()) classp = VN_AS(constrRefp->classOrPackagep(), Class);
|
||||||
if (constrp->isStatic()) {
|
|
||||||
nodep->v3warn(E_UNSUPPORTED,
|
|
||||||
"Unsupported: 'constraint_mode()' on static constraint");
|
|
||||||
valid = false;
|
|
||||||
}
|
|
||||||
} else if (AstClassRefDType* classRefDtp
|
} else if (AstClassRefDType* classRefDtp
|
||||||
= VN_CAST(methodCallp->fromp()->dtypep()->skipRefp(), ClassRefDType)) {
|
= VN_CAST(methodCallp->fromp()->dtypep()->skipRefp(), ClassRefDType)) {
|
||||||
classp = classRefDtp->classp();
|
classp = classRefDtp->classp();
|
||||||
|
|
@ -538,11 +533,6 @@ class RandomizeMarkVisitor final : public VNVisitor {
|
||||||
constrp->user1(constraintMode.asInt);
|
constrp->user1(constraintMode.asInt);
|
||||||
} else {
|
} else {
|
||||||
classp->foreachMember([=](AstClass*, AstConstraint* constrp) {
|
classp->foreachMember([=](AstClass*, AstConstraint* constrp) {
|
||||||
if (constrp->isStatic()) {
|
|
||||||
nodep->v3warn(E_UNSUPPORTED,
|
|
||||||
"Unsupported: 'constraint_mode()' on static constraint: "
|
|
||||||
<< constrp->prettyNameQ());
|
|
||||||
}
|
|
||||||
constrp->user1(constraintMode.asInt);
|
constrp->user1(constraintMode.asInt);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -1834,6 +1824,8 @@ class RandomizeVisitor final : public VNVisitor {
|
||||||
std::map<std::string, AstCDType*> m_randcDtypes; // RandC data type deduplication
|
std::map<std::string, AstCDType*> m_randcDtypes; // RandC data type deduplication
|
||||||
AstConstraint* m_constraintp = nullptr; // Current constraint
|
AstConstraint* m_constraintp = nullptr; // Current constraint
|
||||||
std::set<std::string> m_writtenVars; // Track write_var calls per class to avoid duplicates
|
std::set<std::string> m_writtenVars; // Track write_var calls per class to avoid duplicates
|
||||||
|
std::map<AstClass*, AstVar*>
|
||||||
|
m_staticConstraintModeVars; // Static constraint mode vars per class
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
// Check if two nodes are semantically equivalent (not pointer equality):
|
// Check if two nodes are semantically equivalent (not pointer equality):
|
||||||
|
|
@ -1947,6 +1939,24 @@ class RandomizeVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
AstVar* getCreateStaticConstraintModeVar(AstClass* const classp) {
|
||||||
|
auto it = m_staticConstraintModeVars.find(classp);
|
||||||
|
if (it != m_staticConstraintModeVars.end()) return it->second;
|
||||||
|
if (AstClassExtends* const extendsp = classp->extendsp()) {
|
||||||
|
return getCreateStaticConstraintModeVar(extendsp->classp());
|
||||||
|
}
|
||||||
|
AstVar* const staticModeVarp = createStaticModeVar(classp, "__Vstaticconstraintmode");
|
||||||
|
m_staticConstraintModeVars[classp] = staticModeVarp;
|
||||||
|
return staticModeVarp;
|
||||||
|
}
|
||||||
|
AstVar* getStaticConstraintModeVar(AstClass* const classp) {
|
||||||
|
auto it = m_staticConstraintModeVars.find(classp);
|
||||||
|
if (it != m_staticConstraintModeVars.end()) return it->second;
|
||||||
|
if (AstClassExtends* const extendsp = classp->extendsp()) {
|
||||||
|
return getStaticConstraintModeVar(extendsp->classp());
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
AstVar* createModeVar(AstClass* const classp, const char* const name) {
|
AstVar* createModeVar(AstClass* const classp, const char* const name) {
|
||||||
FileLine* const fl = classp->fileline();
|
FileLine* const fl = classp->fileline();
|
||||||
if (!m_dynarrayDtp) {
|
if (!m_dynarrayDtp) {
|
||||||
|
|
@ -1960,6 +1970,24 @@ class RandomizeVisitor final : public VNVisitor {
|
||||||
classp->addStmtsp(modeVarp);
|
classp->addStmtsp(modeVarp);
|
||||||
return modeVarp;
|
return modeVarp;
|
||||||
}
|
}
|
||||||
|
AstVar* createStaticModeVar(AstClass* const classp, const char* const name) {
|
||||||
|
// Create a static variable that will be shared across all instances.
|
||||||
|
// By setting lifetime to STATIC_EXPLICIT, V3Class will move this to the class package.
|
||||||
|
FileLine* const fl = classp->fileline();
|
||||||
|
if (!m_dynarrayDtp) {
|
||||||
|
m_dynarrayDtp = new AstDynArrayDType{
|
||||||
|
fl, v3Global.rootp()->typeTablep()->findBitDType()->dtypep()};
|
||||||
|
m_dynarrayDtp->dtypep(m_dynarrayDtp);
|
||||||
|
v3Global.rootp()->typeTablep()->addTypesp(m_dynarrayDtp);
|
||||||
|
}
|
||||||
|
AstVar* const modeVarp = new AstVar{fl, VVarType::MODULETEMP, name, m_dynarrayDtp};
|
||||||
|
modeVarp->lifetime(VLifetime::STATIC_EXPLICIT);
|
||||||
|
// Note: user2p is set to classp here. V3Scope will later update varScopep
|
||||||
|
// to point to the package scope when the variable is moved by V3Class.
|
||||||
|
modeVarp->user2p(classp);
|
||||||
|
classp->addStmtsp(modeVarp);
|
||||||
|
return modeVarp;
|
||||||
|
}
|
||||||
static void addSetRandMode(AstNodeFTask* const ftaskp, AstVar* const genp,
|
static void addSetRandMode(AstNodeFTask* const ftaskp, AstVar* const genp,
|
||||||
AstVar* const randModeVarp) {
|
AstVar* const randModeVarp) {
|
||||||
FileLine* const fl = ftaskp->fileline();
|
FileLine* const fl = ftaskp->fileline();
|
||||||
|
|
@ -1976,19 +2004,29 @@ class RandomizeVisitor final : public VNVisitor {
|
||||||
bool hasConstraints = false;
|
bool hasConstraints = false;
|
||||||
uint32_t randModeCount = 0;
|
uint32_t randModeCount = 0;
|
||||||
uint32_t constraintModeCount = 0;
|
uint32_t constraintModeCount = 0;
|
||||||
|
uint32_t staticConstraintModeCount = 0;
|
||||||
classp->foreachMember([&](AstClass*, AstNode* memberp) {
|
classp->foreachMember([&](AstClass*, AstNode* memberp) {
|
||||||
// SystemVerilog only allows single inheritance, so we don't need to worry about
|
// SystemVerilog only allows single inheritance, so we don't need to worry about
|
||||||
// index overlap. If the index > 0, it's already been set.
|
// index overlap. If the index > 0, it's already been set.
|
||||||
if (VN_IS(memberp, Constraint)) {
|
if (AstConstraint* const constrp = VN_CAST(memberp, Constraint)) {
|
||||||
hasConstraints = true;
|
hasConstraints = true;
|
||||||
RandomizeMode constraintMode = {.asInt = memberp->user1()};
|
RandomizeMode constraintMode = {.asInt = memberp->user1()};
|
||||||
if (!constraintMode.usesMode) return;
|
if (!constraintMode.usesMode) return;
|
||||||
if (constraintMode.index == 0) {
|
if (constraintMode.index == 0) {
|
||||||
|
// Use separate index counters for static vs non-static constraints
|
||||||
|
if (constrp->isStatic()) {
|
||||||
|
constraintMode.index = staticConstraintModeCount++;
|
||||||
|
} else {
|
||||||
constraintMode.index = constraintModeCount++;
|
constraintMode.index = constraintModeCount++;
|
||||||
|
}
|
||||||
memberp->user1(constraintMode.asInt);
|
memberp->user1(constraintMode.asInt);
|
||||||
|
} else {
|
||||||
|
if (constrp->isStatic()) {
|
||||||
|
staticConstraintModeCount = constraintMode.index + 1;
|
||||||
} else {
|
} else {
|
||||||
constraintModeCount = constraintMode.index + 1;
|
constraintModeCount = constraintMode.index + 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else if (VN_IS(memberp, Var)) {
|
} else if (VN_IS(memberp, Var)) {
|
||||||
RandomizeMode randMode = {.asInt = memberp->user1()};
|
RandomizeMode randMode = {.asInt = memberp->user1()};
|
||||||
if (!randMode.usesMode) return;
|
if (!randMode.usesMode) return;
|
||||||
|
|
@ -2009,6 +2047,10 @@ class RandomizeVisitor final : public VNVisitor {
|
||||||
AstVar* const constraintModeVarp = getCreateConstraintModeVar(classp);
|
AstVar* const constraintModeVarp = getCreateConstraintModeVar(classp);
|
||||||
makeModeInit(constraintModeVarp, classp, constraintModeCount);
|
makeModeInit(constraintModeVarp, classp, constraintModeCount);
|
||||||
}
|
}
|
||||||
|
if (staticConstraintModeCount > 0) {
|
||||||
|
AstVar* const staticConstraintModeVarp = getCreateStaticConstraintModeVar(classp);
|
||||||
|
makeStaticModeInit(staticConstraintModeVarp, classp, staticConstraintModeCount);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
void makeModeInit(AstVar* modeVarp, AstClass* classp, uint32_t modeCount) {
|
void makeModeInit(AstVar* modeVarp, AstClass* classp, uint32_t modeCount) {
|
||||||
|
|
@ -2025,6 +2067,37 @@ class RandomizeVisitor final : public VNVisitor {
|
||||||
new AstVarRef{fl, modeVarModp, modeVarp, VAccess::WRITE},
|
new AstVarRef{fl, modeVarModp, modeVarp, VAccess::WRITE},
|
||||||
new AstConst{fl, 1}, true));
|
new AstConst{fl, 1}, true));
|
||||||
}
|
}
|
||||||
|
void makeStaticModeInit(AstVar* modeVarp, AstClass* classp, uint32_t modeCount) {
|
||||||
|
// For static constraint mode, we need lazy initialization since it's shared across
|
||||||
|
// instances. Generate: if (size() == 0) { resize(N); set all to 1; }
|
||||||
|
AstNodeModule* const modeVarModp = VN_AS(modeVarp->user2p(), NodeModule);
|
||||||
|
FileLine* fl = modeVarp->fileline();
|
||||||
|
|
||||||
|
// Build the condition: size() == 0
|
||||||
|
AstCMethodHard* const sizep
|
||||||
|
= new AstCMethodHard{fl, new AstVarRef{fl, modeVarModp, modeVarp, VAccess::READ},
|
||||||
|
VCMethod::DYN_SIZE, nullptr};
|
||||||
|
sizep->dtypeSetUInt32();
|
||||||
|
AstEq* const condp = new AstEq{fl, sizep, new AstConst{fl, 0}};
|
||||||
|
|
||||||
|
// Build the then-block: resize and set all to 1
|
||||||
|
AstCMethodHard* const dynarrayNewp
|
||||||
|
= new AstCMethodHard{fl, new AstVarRef{fl, modeVarModp, modeVarp, VAccess::WRITE},
|
||||||
|
VCMethod::DYN_RESIZE, new AstConst{fl, modeCount}};
|
||||||
|
dynarrayNewp->dtypeSetVoid();
|
||||||
|
AstNode* const thenStmtsp = dynarrayNewp->makeStmt();
|
||||||
|
thenStmtsp->addNext(
|
||||||
|
makeModeSetLoop(fl, new AstVarRef{fl, modeVarModp, modeVarp, VAccess::WRITE},
|
||||||
|
new AstConst{fl, 1}, true));
|
||||||
|
|
||||||
|
// Build the if statement
|
||||||
|
AstIf* const ifp = new AstIf{fl, condp, thenStmtsp};
|
||||||
|
|
||||||
|
// Add to new() constructor
|
||||||
|
AstNodeFTask* const newp = VN_AS(m_memberMap.findMember(classp, "new"), NodeFTask);
|
||||||
|
UASSERT_OBJ(newp, classp, "No new() in class");
|
||||||
|
newp->addStmtsp(ifp);
|
||||||
|
}
|
||||||
static AstNode* makeModeSetLoop(FileLine* const fl, AstNodeExpr* const lhsp,
|
static AstNode* makeModeSetLoop(FileLine* const fl, AstNodeExpr* const lhsp,
|
||||||
AstNodeExpr* const rhsp, bool inTask) {
|
AstNodeExpr* const rhsp, bool inTask) {
|
||||||
AstVar* const iterVarp = new AstVar{fl, VVarType::BLOCKTEMP, "i", lhsp->findUInt32DType()};
|
AstVar* const iterVarp = new AstVar{fl, VVarType::BLOCKTEMP, "i", lhsp->findUInt32DType()};
|
||||||
|
|
@ -2054,16 +2127,19 @@ class RandomizeVisitor final : public VNVisitor {
|
||||||
const RandomizeMode rmode = {.asInt = varp->user1()};
|
const RandomizeMode rmode = {.asInt = varp->user1()};
|
||||||
return VN_AS(wrapIfMode(rmode, getRandModeVar(classp), stmtp), NodeStmt);
|
return VN_AS(wrapIfMode(rmode, getRandModeVar(classp), stmtp), NodeStmt);
|
||||||
}
|
}
|
||||||
static AstNode* wrapIfConstraintMode(AstClass* classp, AstConstraint* const constrp,
|
AstNode* wrapIfConstraintMode(AstClass* classp, AstConstraint* const constrp, AstNode* stmtp) {
|
||||||
AstNode* stmtp) {
|
|
||||||
const RandomizeMode rmode = {.asInt = constrp->user1()};
|
const RandomizeMode rmode = {.asInt = constrp->user1()};
|
||||||
return wrapIfMode(rmode, getConstraintModeVar(classp), stmtp);
|
AstVar* const modeVarp = constrp->isStatic() ? getStaticConstraintModeVar(classp)
|
||||||
|
: getConstraintModeVar(classp);
|
||||||
|
return wrapIfMode(rmode, modeVarp, stmtp);
|
||||||
}
|
}
|
||||||
static AstNode* wrapIfMode(const RandomizeMode mode, AstVar* modeVarp, AstNode* stmtp) {
|
static AstNode* wrapIfMode(const RandomizeMode mode, AstVar* modeVarp, AstNode* stmtp) {
|
||||||
FileLine* const fl = stmtp->fileline();
|
FileLine* const fl = stmtp->fileline();
|
||||||
if (mode.usesMode) {
|
if (mode.usesMode) {
|
||||||
AstCMethodHard* const atp = new AstCMethodHard{
|
// user2p can be either AstClass or AstClassPackage (for static constraints)
|
||||||
fl, new AstVarRef{fl, VN_AS(modeVarp->user2p(), Class), modeVarp, VAccess::READ},
|
AstNodeModule* const modp = VN_AS(modeVarp->user2p(), NodeModule);
|
||||||
|
AstCMethodHard* const atp
|
||||||
|
= new AstCMethodHard{fl, new AstVarRef{fl, modp, modeVarp, VAccess::READ},
|
||||||
VCMethod::ARRAY_AT, new AstConst{fl, mode.index}};
|
VCMethod::ARRAY_AT, new AstConst{fl, mode.index}};
|
||||||
atp->dtypeSetUInt32();
|
atp->dtypeSetUInt32();
|
||||||
return new AstIf{fl, atp, stmtp};
|
return new AstIf{fl, atp, stmtp};
|
||||||
|
|
@ -2492,7 +2568,15 @@ class RandomizeVisitor final : public VNVisitor {
|
||||||
// Creates a lvalue reference to the randomize mode var. Called by visit(AstNodeFTaskRef*)
|
// Creates a lvalue reference to the randomize mode var. Called by visit(AstNodeFTaskRef*)
|
||||||
AstNodeExpr* makeModeAssignLhs(FileLine* const fl, AstClass* const classp,
|
AstNodeExpr* makeModeAssignLhs(FileLine* const fl, AstClass* const classp,
|
||||||
AstNodeExpr* const fromp, AstVar* const modeVarp) {
|
AstNodeExpr* const fromp, AstVar* const modeVarp) {
|
||||||
if (classp == m_modp) {
|
// For static constraint mode vars, always use VarRef (not MemberSel).
|
||||||
|
// At this point V3Class hasn't run yet, so user2p may be nullptr.
|
||||||
|
// Generate VarRef with classp as module; V3Scope will update varScopep later
|
||||||
|
// when the variable is moved to the class package.
|
||||||
|
if (modeVarp->lifetime().isStatic()) {
|
||||||
|
// Static mode var - generate VarRef that will be resolved by V3Scope
|
||||||
|
if (fromp) VL_DO_DANGLING(fromp->unlinkFrBack()->deleteTree(), fromp);
|
||||||
|
return new AstVarRef{fl, classp, modeVarp, VAccess::WRITE};
|
||||||
|
} else if (classp == m_modp) {
|
||||||
// Called on 'this' or a member of 'this'
|
// Called on 'this' or a member of 'this'
|
||||||
return new AstVarRef{fl, VN_AS(modeVarp->user2p(), NodeModule), modeVarp,
|
return new AstVarRef{fl, VN_AS(modeVarp->user2p(), NodeModule), modeVarp,
|
||||||
VAccess::WRITE};
|
VAccess::WRITE};
|
||||||
|
|
@ -2848,7 +2932,10 @@ class RandomizeVisitor final : public VNVisitor {
|
||||||
classp = VN_AS(fromp->dtypep()->skipRefp(), ClassRefDType)->classp();
|
classp = VN_AS(fromp->dtypep()->skipRefp(), ClassRefDType)->classp();
|
||||||
}
|
}
|
||||||
UASSERT_OBJ(classp, nodep, "Failed to find class");
|
UASSERT_OBJ(classp, nodep, "Failed to find class");
|
||||||
AstVar* const constraintModeVarp = getConstraintModeVar(classp);
|
// Use correct mode variable based on whether constraint is static
|
||||||
|
AstVar* const constraintModeVarp = (constrp && constrp->isStatic())
|
||||||
|
? getStaticConstraintModeVar(classp)
|
||||||
|
: getConstraintModeVar(classp);
|
||||||
AstNodeExpr* const lhsp
|
AstNodeExpr* const lhsp
|
||||||
= makeModeAssignLhs(nodep->fileline(), classp, fromp, constraintModeVarp);
|
= makeModeAssignLhs(nodep->fileline(), classp, fromp, constraintModeVarp);
|
||||||
replaceWithModeAssign(nodep, constrp, lhsp);
|
replaceWithModeAssign(nodep, constrp, lhsp);
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,18 @@
|
||||||
# This program is free software; you can redistribute it and/or modify it
|
# 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
|
# under the terms of either the GNU Lesser General Public License Version 3
|
||||||
# or the Perl Artistic License Version 2.0.
|
# or the Perl Artistic License Version 2.0.
|
||||||
# SPDX-FileCopyrightText: 2024 Wilson Snyder
|
# SPDX-FileCopyrightText: 2026 Wilson Snyder
|
||||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('vlt')
|
test.scenarios('simulator')
|
||||||
|
|
||||||
test.lint(fails=test.vlt_all, expect_filename=test.golden_filename)
|
if not test.have_solver:
|
||||||
|
test.skip("No constraint solver installed")
|
||||||
|
|
||||||
|
test.compile()
|
||||||
|
|
||||||
|
test.execute()
|
||||||
|
|
||||||
test.passes()
|
test.passes()
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2026 by PlanV GmbH.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
// Test static constraint_mode() support per IEEE 1800-2017 Section 18.4, 18.8
|
||||||
|
// Static constraint mode should be shared across all instances.
|
||||||
|
|
||||||
|
class StaticConstraintTest;
|
||||||
|
rand bit [7:0] value;
|
||||||
|
|
||||||
|
// Static constraint - shared across all instances
|
||||||
|
static constraint static_con {
|
||||||
|
value inside {[10:15]};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non-static constraint for comparison
|
||||||
|
constraint instance_con {
|
||||||
|
value > 5;
|
||||||
|
}
|
||||||
|
endclass
|
||||||
|
|
||||||
|
module t;
|
||||||
|
StaticConstraintTest obj1, obj2;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
obj1 = new();
|
||||||
|
obj2 = new();
|
||||||
|
|
||||||
|
// Test 1: Verify static constraint_mode getter works
|
||||||
|
if (obj1.static_con.constraint_mode() != 1) $stop;
|
||||||
|
if (obj2.static_con.constraint_mode() != 1) $stop;
|
||||||
|
|
||||||
|
// Test 2: Disable static constraint on one instance
|
||||||
|
obj1.static_con.constraint_mode(0);
|
||||||
|
|
||||||
|
// Verify the state is shared across all instances
|
||||||
|
if (obj1.static_con.constraint_mode() != 0) $stop;
|
||||||
|
if (obj2.static_con.constraint_mode() != 0) $stop;
|
||||||
|
|
||||||
|
// Test 3: Re-enable static constraint via different instance
|
||||||
|
obj2.static_con.constraint_mode(1);
|
||||||
|
|
||||||
|
// Verify state is updated for all instances
|
||||||
|
if (obj1.static_con.constraint_mode() != 1) $stop;
|
||||||
|
if (obj2.static_con.constraint_mode() != 1) $stop;
|
||||||
|
|
||||||
|
// Test 4: Verify randomization respects constraint mode when enabled
|
||||||
|
obj1.static_con.constraint_mode(1);
|
||||||
|
obj1.instance_con.constraint_mode(1);
|
||||||
|
for (int i = 0; i < 10; i++) begin
|
||||||
|
void'(obj1.randomize());
|
||||||
|
if (!(obj1.value inside {[10:15]})) $stop;
|
||||||
|
if (!(obj1.value > 5)) $stop;
|
||||||
|
end
|
||||||
|
|
||||||
|
// Test 5: Disable static constraint and verify randomization changes
|
||||||
|
obj1.static_con.constraint_mode(0);
|
||||||
|
// With static_con disabled, value only needs to be > 5
|
||||||
|
for (int i = 0; i < 10; i++) begin
|
||||||
|
obj1.value = 1; // Reset to low value
|
||||||
|
void'(obj1.randomize());
|
||||||
|
if (!(obj1.value > 5)) $stop;
|
||||||
|
end
|
||||||
|
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
%Error-UNSUPPORTED: t/t_constraint_mode_unsup.v:17:55: Unsupported: 'constraint_mode()' on static constraint
|
|
||||||
: ... note: In instance 't'
|
|
||||||
17 | $display("p.cons.constraint_mode()=%0d", p.cons.constraint_mode());
|
|
||||||
| ^~~~~~~~~~~~~~~
|
|
||||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
|
||||||
%Error-UNSUPPORTED: t/t_constraint_mode_unsup.v:18:14: Unsupported: 'constraint_mode()' on static constraint
|
|
||||||
: ... note: In instance 't'
|
|
||||||
18 | p.cons.constraint_mode(0);
|
|
||||||
| ^~~~~~~~~~~~~~~
|
|
||||||
%Error-UNSUPPORTED: t/t_constraint_mode_unsup.v:19:9: Unsupported: 'constraint_mode()' on static constraint: 'cons'
|
|
||||||
: ... note: In instance 't'
|
|
||||||
19 | p.constraint_mode(0);
|
|
||||||
| ^~~~~~~~~~~~~~~
|
|
||||||
%Error: Exiting due to
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
|
||||||
//
|
|
||||||
// This file ONLY is placed under the Creative Commons Public Domain
|
|
||||||
// SPDX-FileCopyrightText: 2024 Antmicro
|
|
||||||
// SPDX-License-Identifier: CC0-1.0
|
|
||||||
|
|
||||||
class Packet;
|
|
||||||
int m_one;
|
|
||||||
static constraint cons { m_one > 0 && m_one < 2; }
|
|
||||||
endclass
|
|
||||||
|
|
||||||
module t;
|
|
||||||
Packet p;
|
|
||||||
|
|
||||||
initial begin
|
|
||||||
p = new;
|
|
||||||
$display("p.cons.constraint_mode()=%0d", p.cons.constraint_mode());
|
|
||||||
p.cons.constraint_mode(0);
|
|
||||||
p.constraint_mode(0);
|
|
||||||
end
|
|
||||||
endmodule
|
|
||||||
Loading…
Reference in New Issue