try to improve the coverage
This commit is contained in:
parent
3f017b4d8c
commit
3dddb90fc5
|
|
@ -245,8 +245,7 @@ class RandomizeMarkVisitor final : public VNVisitor {
|
||||||
const std::vector<AstVar*>& newPath) {
|
const std::vector<AstVar*>& newPath) {
|
||||||
if (!constrp) return;
|
if (!constrp) return;
|
||||||
|
|
||||||
AstConstraint* cloneConstrp = constrp->cloneTree(false);
|
AstConstraint* const cloneConstrp = constrp->cloneTree(false);
|
||||||
if (!cloneConstrp) return;
|
|
||||||
|
|
||||||
std::string pathPrefix = rootVarRefp->name();
|
std::string pathPrefix = rootVarRefp->name();
|
||||||
for (AstVar* pathMemberVarp : newPath) {
|
for (AstVar* pathMemberVarp : newPath) {
|
||||||
|
|
@ -255,7 +254,7 @@ class RandomizeMarkVisitor final : public VNVisitor {
|
||||||
|
|
||||||
cloneConstrp->name(pathPrefix + GLOBAL_CONSTRAINT_SEPARATOR + cloneConstrp->name());
|
cloneConstrp->name(pathPrefix + GLOBAL_CONSTRAINT_SEPARATOR + cloneConstrp->name());
|
||||||
cloneConstrp->foreach([&](AstVarRef* varRefp) {
|
cloneConstrp->foreach([&](AstVarRef* varRefp) {
|
||||||
if (!varRefp || !varRefp->varp()) return;
|
UASSERT(varRefp && varRefp->varp(), "VarRef should be valid in constraint");
|
||||||
|
|
||||||
AstNodeExpr* const chainp = buildMemberSelChain(rootVarRefp, newPath);
|
AstNodeExpr* const chainp = buildMemberSelChain(rootVarRefp, newPath);
|
||||||
AstMemberSel* const finalSelp
|
AstMemberSel* const finalSelp
|
||||||
|
|
@ -306,9 +305,8 @@ class RandomizeMarkVisitor final : public VNVisitor {
|
||||||
if (!fromp || !cloneCons) return;
|
if (!fromp || !cloneCons) return;
|
||||||
cloneCons->name(fromp->name() + GLOBAL_CONSTRAINT_SEPARATOR + cloneCons->name());
|
cloneCons->name(fromp->name() + GLOBAL_CONSTRAINT_SEPARATOR + cloneCons->name());
|
||||||
cloneCons->foreach([&](AstVarRef* varRefp) {
|
cloneCons->foreach([&](AstVarRef* varRefp) {
|
||||||
if (!varRefp || !varRefp->varp()) return;
|
UASSERT(varRefp && varRefp->varp(), "VarRef should be valid in constraint");
|
||||||
AstVarRef* const clonedFromp = fromp->cloneTree(false);
|
AstVarRef* const clonedFromp = fromp->cloneTree(false);
|
||||||
if (!clonedFromp) return;
|
|
||||||
AstMemberSel* const varMemberp
|
AstMemberSel* const varMemberp
|
||||||
= new AstMemberSel{cloneCons->fileline(), clonedFromp, varRefp->varp()};
|
= new AstMemberSel{cloneCons->fileline(), clonedFromp, varRefp->varp()};
|
||||||
varMemberp->user2p(m_classp);
|
varMemberp->user2p(m_classp);
|
||||||
|
|
@ -641,8 +639,7 @@ class RandomizeMarkVisitor final : public VNVisitor {
|
||||||
gConsClass->foreachMember(
|
gConsClass->foreachMember(
|
||||||
[&](AstClass* const classp, AstConstraint* const constrp) {
|
[&](AstClass* const classp, AstConstraint* const constrp) {
|
||||||
if (!constrp) return;
|
if (!constrp) return;
|
||||||
AstConstraint* cloneConstrp = constrp->cloneTree(false);
|
AstConstraint* const cloneConstrp = constrp->cloneTree(false);
|
||||||
if (!cloneConstrp) return;
|
|
||||||
// Name manipulation
|
// Name manipulation
|
||||||
nameManipulation(varRefp, cloneConstrp);
|
nameManipulation(varRefp, cloneConstrp);
|
||||||
m_clonedConstraints.push_back(cloneConstrp);
|
m_clonedConstraints.push_back(cloneConstrp);
|
||||||
|
|
@ -726,10 +723,9 @@ class ConstraintExprVisitor final : public VNVisitor {
|
||||||
} else if (VN_IS(fromp, MemberSel)) {
|
} else if (VN_IS(fromp, MemberSel)) {
|
||||||
// Recursive case: build path from outer levels
|
// Recursive case: build path from outer levels
|
||||||
return buildMemberPath(VN_AS(fromp, MemberSel)) + "." + memberSelp->name();
|
return buildMemberPath(VN_AS(fromp, MemberSel)) + "." + memberSelp->name();
|
||||||
} else {
|
|
||||||
// Fallback: just return member name
|
|
||||||
return memberSelp->name();
|
|
||||||
}
|
}
|
||||||
|
memberSelp->v3fatalSrc("Unexpected node type in MemberSel chain");
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
AstSFormatF* getConstFormat(AstNodeExpr* nodep) {
|
AstSFormatF* getConstFormat(AstNodeExpr* nodep) {
|
||||||
|
|
@ -869,10 +865,6 @@ class ConstraintExprVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
membersel = VN_AS(topMemberSel, MemberSel)->cloneTree(false);
|
membersel = VN_AS(topMemberSel, MemberSel)->cloneTree(false);
|
||||||
smtName = buildMemberPath(membersel);
|
smtName = buildMemberPath(membersel);
|
||||||
} else if (VN_IS(nodep->backp(), MemberSel)) {
|
|
||||||
// Normal case: simple one-level MemberSel
|
|
||||||
membersel = VN_AS(nodep->backp(), MemberSel)->cloneTree(false);
|
|
||||||
smtName = membersel->fromp()->name() + "." + membersel->name();
|
|
||||||
} else {
|
} else {
|
||||||
// No MemberSel: just variable name
|
// No MemberSel: just variable name
|
||||||
smtName = nodep->name();
|
smtName = nodep->name();
|
||||||
|
|
@ -1156,16 +1148,13 @@ class ConstraintExprVisitor final : public VNVisitor {
|
||||||
|
|
||||||
// Traverse MemberSel chain to find the root variable reference
|
// Traverse MemberSel chain to find the root variable reference
|
||||||
AstNode* rootNode = nodep->fromp();
|
AstNode* rootNode = nodep->fromp();
|
||||||
while (VN_IS(rootNode, MemberSel) && !VN_IS(rootNode, NodeVarRef)) {
|
while (VN_IS(rootNode, MemberSel)) {
|
||||||
rootNode = VN_AS(rootNode, MemberSel)->fromp();
|
rootNode = VN_AS(rootNode, MemberSel)->fromp();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the root variable participates in global constraints
|
// Check if the root variable participates in global constraints
|
||||||
AstVar* const constrainedVar
|
AstVar* const constrainedVar
|
||||||
= VN_IS(rootNode, VarRef)
|
= VN_IS(rootNode, VarRef) ? VN_AS(rootNode, VarRef)->varp() : nullptr;
|
||||||
? VN_AS(rootNode, VarRef)->varp()
|
|
||||||
: (VN_IS(rootNode, MemberSel) ? VN_AS(rootNode, MemberSel)->varp()
|
|
||||||
: nullptr);
|
|
||||||
if (constrainedVar && constrainedVar->isGlobalConstrained()) {
|
if (constrainedVar && constrainedVar->isGlobalConstrained()) {
|
||||||
// Global constraint - unwrap the MemberSel
|
// Global constraint - unwrap the MemberSel
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,8 @@ module t_constraint_global_random;
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
t = new();
|
t = new();
|
||||||
|
|
||||||
|
// Test 1: Regular randomize() with global constraints
|
||||||
success = t.randomize();
|
success = t.randomize();
|
||||||
if (success != 1) $stop;
|
if (success != 1) $stop;
|
||||||
|
|
||||||
|
|
@ -59,6 +61,24 @@ module t_constraint_global_random;
|
||||||
if (t.m1.inner.val < 1 || t.m1.inner.val > 5 ||
|
if (t.m1.inner.val < 1 || t.m1.inner.val > 5 ||
|
||||||
t.m2.inner.val < 1 || t.m2.inner.val > 5) $stop;
|
t.m2.inner.val < 1 || t.m2.inner.val > 5) $stop;
|
||||||
|
|
||||||
|
// Test 2: randomize() with inline constraint on global-constrained members
|
||||||
|
success = 0;
|
||||||
|
success = t.randomize() with {
|
||||||
|
m1.inner.val == 2;
|
||||||
|
m2.inner.val == 5;
|
||||||
|
};
|
||||||
|
if (success != 1) $stop;
|
||||||
|
|
||||||
|
// Verify inline constraints
|
||||||
|
if (t.m1.inner.val != 2) $stop;
|
||||||
|
if (t.m2.inner.val != 5) $stop;
|
||||||
|
|
||||||
|
// Verify global constraints still hold
|
||||||
|
if (t.m1.x != 3 || t.m2.x != 5) $stop;
|
||||||
|
if (t.m1.inner.val >= t.m2.inner.val) $stop;
|
||||||
|
if (t.y <= t.m1.x || t.y >= t.m2.x) $stop;
|
||||||
|
if (t.m1.inner.val + t.m2.inner.val >= 8) $stop;
|
||||||
|
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue