Support unconstrained randomization for associative array and queue (#5515)

This commit is contained in:
Yilou Wang 2024-10-08 16:54:20 +02:00 committed by GitHub
parent 8f1ea09558
commit 920c8012de
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 76 additions and 24 deletions

View File

@ -1380,6 +1380,13 @@ class RandomizeVisitor final : public VNVisitor {
AstVar* randLoopIndxp = nullptr;
AstNodeStmt* stmtsp = nullptr;
auto createLoopIndex = [&](AstNodeDType* tempDTypep) {
if (VN_IS(tempDTypep, AssocArrayDType)) {
return new AstVar{
fl, VVarType::VAR, uniqueNamep->get(""),
dtypep->findBasicDType(
((AstBasicDType*)VN_AS(tempDTypep, AssocArrayDType)->keyDTypep())
->keyword())};
}
return new AstVar{fl, VVarType::VAR, uniqueNamep->get(""),
dtypep->findBasicDType(VBasicDTypeKwd::UINT32)};
};
@ -1398,17 +1405,20 @@ class RandomizeVisitor final : public VNVisitor {
return new AstForeach{fl, randLoopVarp, newRandStmtsp(fl, tempElementp, nullptr)};
};
AstNodeExpr* tempElementp = nullptr;
while (VN_CAST(tempDTypep, DynArrayDType) || VN_CAST(tempDTypep, UnpackArrayDType)) {
while (VN_IS(tempDTypep, DynArrayDType) || VN_IS(tempDTypep, UnpackArrayDType)
|| VN_IS(tempDTypep, AssocArrayDType) || VN_IS(tempDTypep, QueueDType)) {
AstVar* const newRandLoopIndxp = createLoopIndex(tempDTypep);
randLoopIndxp = AstNode::addNext(randLoopIndxp, newRandLoopIndxp);
tempElementp
= VN_CAST(tempDTypep, DynArrayDType)
? static_cast<AstNodeExpr*>(
new AstCMethodHard{fl, tempElementp ? tempElementp : exprp, "atWrite",
new AstVarRef{fl, newRandLoopIndxp, VAccess::READ}})
: static_cast<AstNodeExpr*>(
new AstArraySel{fl, tempElementp ? tempElementp : exprp,
new AstVarRef{fl, newRandLoopIndxp, VAccess::READ}});
AstNodeExpr* tempExprp = tempElementp ? tempElementp : exprp;
AstVarRef* tempRefp = new AstVarRef{fl, newRandLoopIndxp, VAccess::READ};
if (VN_IS(tempDTypep, DynArrayDType))
tempElementp = new AstCMethodHard{fl, tempExprp, "atWrite", tempRefp};
else if (VN_IS(tempDTypep, UnpackArrayDType))
tempElementp = new AstArraySel{fl, tempExprp, tempRefp};
else if (VN_IS(tempDTypep, AssocArrayDType))
tempElementp = new AstAssocSel{fl, tempExprp, tempRefp};
else if (VN_IS(tempDTypep, QueueDType))
tempElementp = new AstCMethodHard{fl, tempExprp, "atWriteAppend", tempRefp};
tempElementp->dtypep(tempDTypep->subDTypep());
tempDTypep = tempDTypep->virtRefDTypep();
}
@ -1449,9 +1459,13 @@ class RandomizeVisitor final : public VNVisitor {
return newRandStmtsp(fl, exprp, nullptr, offset, firstMemberp);
} else if (AstDynArrayDType* const dynarrayDtp = VN_CAST(memberDtp, DynArrayDType)) {
return createArrayForeachLoop(fl, dynarrayDtp, exprp);
} else if (AstQueueDType* const queueDtp = VN_CAST(memberDtp, QueueDType)) {
return createArrayForeachLoop(fl, queueDtp, exprp);
} else if (AstUnpackArrayDType* const unpackarrayDtp
= VN_CAST(memberDtp, UnpackArrayDType)) {
return createArrayForeachLoop(fl, unpackarrayDtp, exprp);
} else if (AstAssocArrayDType* const assocarrayDtp = VN_CAST(memberDtp, AssocArrayDType)) {
return createArrayForeachLoop(fl, assocarrayDtp, exprp);
} else {
AstNodeExpr* valp;
if (AstEnumDType* const enumDtp = VN_CAST(memberp ? memberp->subDTypep()->subDTypep()
@ -1631,14 +1645,7 @@ class RandomizeVisitor final : public VNVisitor {
}
if (memberVarp->user3()) return; // Handled in constraints
const AstNodeDType* const dtypep = memberVarp->dtypep()->skipRefp();
if (VN_IS(dtypep, BasicDType) || VN_IS(dtypep, StructDType)
|| VN_IS(dtypep, UnionDType) || VN_IS(dtypep, PackArrayDType)
|| VN_IS(dtypep, UnpackArrayDType) || VN_IS(dtypep, DynArrayDType)) {
AstVar* const randcVarp = newRandcVarsp(memberVarp);
AstVarRef* const refp = new AstVarRef{fl, classp, memberVarp, VAccess::WRITE};
AstNodeStmt* const stmtp = newRandStmtsp(fl, refp, randcVarp);
basicRandomizep->addStmtsp(new AstBegin{fl, "", stmtp});
} else if (const AstClassRefDType* const classRefp = VN_CAST(dtypep, ClassRefDType)) {
if (const AstClassRefDType* const classRefp = VN_CAST(dtypep, ClassRefDType)) {
if (classRefp->classp() == nodep) {
memberVarp->v3warn(E_UNSUPPORTED,
"Unsupported: random member variable with the "
@ -1662,8 +1669,10 @@ class RandomizeVisitor final : public VNVisitor {
new AstAnd{fl, basicFvarRefReadp, callp}}};
basicRandomizep->addStmtsp(wrapIfRandMode(nodep, memberVarp, assignIfNotNullp));
} else {
memberVarp->v3warn(E_UNSUPPORTED, "Unsupported: random member variable with type "
<< memberVarp->dtypep()->prettyDTypeNameQ());
AstVar* const randcVarp = newRandcVarsp(memberVarp);
AstVarRef* const refp = new AstVarRef{fl, classp, memberVarp, VAccess::WRITE};
AstNodeStmt* const stmtp = newRandStmtsp(fl, refp, randcVarp);
basicRandomizep->addStmtsp(new AstBegin{fl, "", stmtp});
}
});
}

View File

@ -106,11 +106,47 @@ class unconstrained_struct_with_array_test;
endclass
class unconstrained_associative_array_test;
rand int associative_array[string];
function new();
associative_array["key1"] = 0;
associative_array["key2"] = 0;
endfunction
function void check_randomization();
`check_rand(this, associative_array["key1"]);
`check_rand(this, associative_array["key2"]);
endfunction
endclass
class unconstrained_queue_test;
rand int queue_array[$];
function new();
for (int i = 0; i < 3; i++) begin
queue_array.push_back('h0 + i);
end
endfunction
function void check_randomization();
foreach (queue_array[i]) begin
`check_rand(this, queue_array[i]);
end
endfunction
endclass
module t_randomize_array;
unconstrained_packed_array_test packed_class;
unconstrained_unpacked_array_test unpacked_class;
unconstrained_dynamic_array_test dynamic_class;
unconstrained_struct_with_array_test struct_with_array_class;
unconstrained_associative_array_test associative_array_class;
unconstrained_queue_test queue_class;
initial begin
// Test 1: Packed Array Unconstrained Constrained Test
@ -132,12 +168,23 @@ module t_randomize_array;
end
// Test 4: Struct Containing Array Test
struct_with_array_class = new();
repeat(2) begin
struct_with_array_class.check_randomization();
end
// Test 5: Associative Array Unconstrained Test
associative_array_class = new();
repeat(2) begin
associative_array_class.check_randomization();
end
// Test 6: Queue Unconstrained Test
queue_class = new();
repeat(2) begin
queue_class.check_randomization();
end
$write("*-* All Finished *-*\n");
$finish;
end

View File

@ -3,10 +3,6 @@
| ^~~~
... For warning description see https://verilator.org/warn/CONSTRAINTIGN?v=latest
... Use "/* verilator lint_off CONSTRAINTIGN */" and lint_on around source to disable this message.
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:8:13: Unsupported: random member variable with type 'int$[string]'
: ... note: In instance 't'
8 | rand int assocarr[string];
| ^~~~~~~~
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:10:13: Unsupported: random member variable with the type of the containing class
: ... note: In instance 't'
10 | rand Cls cls;