mirror of
https://github.com/verilator/verilator.git
synced 2024-12-29 10:47:34 +00:00
Support unconstrained randomization for associative array and queue (#5515)
This commit is contained in:
parent
8f1ea09558
commit
920c8012de
@ -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});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user