mirror of
https://github.com/verilator/verilator.git
synced 2025-01-01 04:07: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;
|
AstVar* randLoopIndxp = nullptr;
|
||||||
AstNodeStmt* stmtsp = nullptr;
|
AstNodeStmt* stmtsp = nullptr;
|
||||||
auto createLoopIndex = [&](AstNodeDType* tempDTypep) {
|
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(""),
|
return new AstVar{fl, VVarType::VAR, uniqueNamep->get(""),
|
||||||
dtypep->findBasicDType(VBasicDTypeKwd::UINT32)};
|
dtypep->findBasicDType(VBasicDTypeKwd::UINT32)};
|
||||||
};
|
};
|
||||||
@ -1398,17 +1405,20 @@ class RandomizeVisitor final : public VNVisitor {
|
|||||||
return new AstForeach{fl, randLoopVarp, newRandStmtsp(fl, tempElementp, nullptr)};
|
return new AstForeach{fl, randLoopVarp, newRandStmtsp(fl, tempElementp, nullptr)};
|
||||||
};
|
};
|
||||||
AstNodeExpr* 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);
|
AstVar* const newRandLoopIndxp = createLoopIndex(tempDTypep);
|
||||||
randLoopIndxp = AstNode::addNext(randLoopIndxp, newRandLoopIndxp);
|
randLoopIndxp = AstNode::addNext(randLoopIndxp, newRandLoopIndxp);
|
||||||
tempElementp
|
AstNodeExpr* tempExprp = tempElementp ? tempElementp : exprp;
|
||||||
= VN_CAST(tempDTypep, DynArrayDType)
|
AstVarRef* tempRefp = new AstVarRef{fl, newRandLoopIndxp, VAccess::READ};
|
||||||
? static_cast<AstNodeExpr*>(
|
if (VN_IS(tempDTypep, DynArrayDType))
|
||||||
new AstCMethodHard{fl, tempElementp ? tempElementp : exprp, "atWrite",
|
tempElementp = new AstCMethodHard{fl, tempExprp, "atWrite", tempRefp};
|
||||||
new AstVarRef{fl, newRandLoopIndxp, VAccess::READ}})
|
else if (VN_IS(tempDTypep, UnpackArrayDType))
|
||||||
: static_cast<AstNodeExpr*>(
|
tempElementp = new AstArraySel{fl, tempExprp, tempRefp};
|
||||||
new AstArraySel{fl, tempElementp ? tempElementp : exprp,
|
else if (VN_IS(tempDTypep, AssocArrayDType))
|
||||||
new AstVarRef{fl, newRandLoopIndxp, VAccess::READ}});
|
tempElementp = new AstAssocSel{fl, tempExprp, tempRefp};
|
||||||
|
else if (VN_IS(tempDTypep, QueueDType))
|
||||||
|
tempElementp = new AstCMethodHard{fl, tempExprp, "atWriteAppend", tempRefp};
|
||||||
tempElementp->dtypep(tempDTypep->subDTypep());
|
tempElementp->dtypep(tempDTypep->subDTypep());
|
||||||
tempDTypep = tempDTypep->virtRefDTypep();
|
tempDTypep = tempDTypep->virtRefDTypep();
|
||||||
}
|
}
|
||||||
@ -1449,9 +1459,13 @@ class RandomizeVisitor final : public VNVisitor {
|
|||||||
return newRandStmtsp(fl, exprp, nullptr, offset, firstMemberp);
|
return newRandStmtsp(fl, exprp, nullptr, offset, firstMemberp);
|
||||||
} else if (AstDynArrayDType* const dynarrayDtp = VN_CAST(memberDtp, DynArrayDType)) {
|
} else if (AstDynArrayDType* const dynarrayDtp = VN_CAST(memberDtp, DynArrayDType)) {
|
||||||
return createArrayForeachLoop(fl, dynarrayDtp, exprp);
|
return createArrayForeachLoop(fl, dynarrayDtp, exprp);
|
||||||
|
} else if (AstQueueDType* const queueDtp = VN_CAST(memberDtp, QueueDType)) {
|
||||||
|
return createArrayForeachLoop(fl, queueDtp, exprp);
|
||||||
} else if (AstUnpackArrayDType* const unpackarrayDtp
|
} else if (AstUnpackArrayDType* const unpackarrayDtp
|
||||||
= VN_CAST(memberDtp, UnpackArrayDType)) {
|
= VN_CAST(memberDtp, UnpackArrayDType)) {
|
||||||
return createArrayForeachLoop(fl, unpackarrayDtp, exprp);
|
return createArrayForeachLoop(fl, unpackarrayDtp, exprp);
|
||||||
|
} else if (AstAssocArrayDType* const assocarrayDtp = VN_CAST(memberDtp, AssocArrayDType)) {
|
||||||
|
return createArrayForeachLoop(fl, assocarrayDtp, exprp);
|
||||||
} else {
|
} else {
|
||||||
AstNodeExpr* valp;
|
AstNodeExpr* valp;
|
||||||
if (AstEnumDType* const enumDtp = VN_CAST(memberp ? memberp->subDTypep()->subDTypep()
|
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
|
if (memberVarp->user3()) return; // Handled in constraints
|
||||||
const AstNodeDType* const dtypep = memberVarp->dtypep()->skipRefp();
|
const AstNodeDType* const dtypep = memberVarp->dtypep()->skipRefp();
|
||||||
if (VN_IS(dtypep, BasicDType) || VN_IS(dtypep, StructDType)
|
if (const AstClassRefDType* const classRefp = VN_CAST(dtypep, ClassRefDType)) {
|
||||||
|| 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 (classRefp->classp() == nodep) {
|
if (classRefp->classp() == nodep) {
|
||||||
memberVarp->v3warn(E_UNSUPPORTED,
|
memberVarp->v3warn(E_UNSUPPORTED,
|
||||||
"Unsupported: random member variable with the "
|
"Unsupported: random member variable with the "
|
||||||
@ -1662,8 +1669,10 @@ class RandomizeVisitor final : public VNVisitor {
|
|||||||
new AstAnd{fl, basicFvarRefReadp, callp}}};
|
new AstAnd{fl, basicFvarRefReadp, callp}}};
|
||||||
basicRandomizep->addStmtsp(wrapIfRandMode(nodep, memberVarp, assignIfNotNullp));
|
basicRandomizep->addStmtsp(wrapIfRandMode(nodep, memberVarp, assignIfNotNullp));
|
||||||
} else {
|
} else {
|
||||||
memberVarp->v3warn(E_UNSUPPORTED, "Unsupported: random member variable with type "
|
AstVar* const randcVarp = newRandcVarsp(memberVarp);
|
||||||
<< memberVarp->dtypep()->prettyDTypeNameQ());
|
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
|
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;
|
module t_randomize_array;
|
||||||
unconstrained_packed_array_test packed_class;
|
unconstrained_packed_array_test packed_class;
|
||||||
unconstrained_unpacked_array_test unpacked_class;
|
unconstrained_unpacked_array_test unpacked_class;
|
||||||
unconstrained_dynamic_array_test dynamic_class;
|
unconstrained_dynamic_array_test dynamic_class;
|
||||||
unconstrained_struct_with_array_test struct_with_array_class;
|
unconstrained_struct_with_array_test struct_with_array_class;
|
||||||
|
unconstrained_associative_array_test associative_array_class;
|
||||||
|
unconstrained_queue_test queue_class;
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
// Test 1: Packed Array Unconstrained Constrained Test
|
// Test 1: Packed Array Unconstrained Constrained Test
|
||||||
@ -132,12 +168,23 @@ module t_randomize_array;
|
|||||||
end
|
end
|
||||||
|
|
||||||
// Test 4: Struct Containing Array Test
|
// Test 4: Struct Containing Array Test
|
||||||
|
|
||||||
struct_with_array_class = new();
|
struct_with_array_class = new();
|
||||||
repeat(2) begin
|
repeat(2) begin
|
||||||
struct_with_array_class.check_randomization();
|
struct_with_array_class.check_randomization();
|
||||||
end
|
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");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
@ -3,10 +3,6 @@
|
|||||||
| ^~~~
|
| ^~~~
|
||||||
... For warning description see https://verilator.org/warn/CONSTRAINTIGN?v=latest
|
... 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.
|
... 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
|
%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'
|
: ... note: In instance 't'
|
||||||
10 | rand Cls cls;
|
10 | rand Cls cls;
|
||||||
|
Loading…
Reference in New Issue
Block a user