mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 10:03:44 +02:00
Support rand dynamic arrays used inside with clause of randomize (#8246)
Signed-off-by: Kamil Danecki <[email protected]> Signed-off-by: Igor Zaworski <[email protected]>
This commit is contained in:
+59
-40
@@ -1465,7 +1465,7 @@ class ConstraintExprVisitor final : public VNVisitor {
|
||||
AstMemberSel* const memberselp, const std::string& smtName,
|
||||
AstNodeModule* const classOrPackagep) const {
|
||||
uint32_t unpackedDims = 0;
|
||||
if (varp->dtypep()->isNonPackedArray()) {
|
||||
if (varp->dtypeSkipRefp()->isNonPackedArray()) {
|
||||
unpackedDims = varp->dtypep()->dimensions(false).second;
|
||||
}
|
||||
if (VN_IS(varp->dtypeSkipRefp(), StructDType)
|
||||
@@ -2688,47 +2688,66 @@ class ConstraintExprVisitor final : public VNVisitor {
|
||||
if (editFormat(nodep)) return;
|
||||
FileLine* const fl = nodep->fileline();
|
||||
|
||||
if (nodep->method() == VCMethod::ARRAY_AT && nodep->fromp()->user1()) {
|
||||
// Queue/dynamic element: pre-edit clone for the rand_mode hoist, non-rand index only.
|
||||
// A std::randomize() with-clause argument carries no rand qualifier
|
||||
// of its own but is still part of the solve.
|
||||
bool indexIsRand = false;
|
||||
if (nodep->pinsp()) {
|
||||
nodep->pinsp()->foreach([&](const AstNodeVarRef* vrefp) {
|
||||
if (vrefp->varp()->rand().isRandomizable()
|
||||
|| vrefp->varp()->isStdRandomizeArg()) {
|
||||
indexIsRand = true;
|
||||
if (nodep->method() == VCMethod::ARRAY_AT) {
|
||||
const bool indexIsRand = nodep->pinsp()->exists([](const AstNodeVarRef* const vrefp) {
|
||||
return vrefp->varp()->rand().isRandomizable();
|
||||
});
|
||||
if (nodep->fromp()->user1()) {
|
||||
// Queue/dynamic element: pre-edit clone for the rand_mode hoist, non-rand index
|
||||
// only. A std::randomize() with-clause argument carries no rand qualifier of its
|
||||
// own but is still part of the solve.
|
||||
{
|
||||
const AstNode* const basep = nodep->baseFromp(true);
|
||||
if (basep->name() == "__Vthis"
|
||||
&& VN_AS(basep->backp(), MemberSel)->varp()->isRand()) {
|
||||
nodep->fromp()->v3warn(E_UNSUPPORTED,
|
||||
"Unsupported: Complex expression captured from "
|
||||
"current scope with randomized variable");
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
AstNodeExpr* const origp = indexIsRand ? nullptr : nodep->cloneTree(false);
|
||||
AstCMethodHard* const sizep
|
||||
= m_structSel ? new AstCMethodHard{fl, nodep->fromp()->cloneTreePure(false),
|
||||
VCMethod::DYN_SIZE}
|
||||
: nullptr;
|
||||
AstNodeExpr* const originalPinp = nodep->pinsp();
|
||||
iterateChildren(nodep);
|
||||
AstNodeExpr* const pinp = nodep->pinsp()->unlinkFrBack();
|
||||
if (VN_IS(pinp, SFormatF) && m_structSel) VN_AS(pinp, SFormatF)->name("%x");
|
||||
AstSFormatF* newp;
|
||||
if (m_structSel) {
|
||||
AstNodeExpr* const argsp = AstNode::addNext(nodep->fromp()->unlinkFrBack(), pinp);
|
||||
sizep->dtypeSetInt();
|
||||
AstLogAnd* const condp = new AstLogAnd{
|
||||
fl,
|
||||
new AstLteS{
|
||||
fl, new AstConst{fl, AstConst::WidthedValue{}, originalPinp->width(), 0},
|
||||
originalPinp->cloneTreePure(false)},
|
||||
new AstLtS{fl, originalPinp->cloneTreePure(false), sizep}};
|
||||
m_conditionp = m_conditionp ? new AstLogAnd{fl, m_conditionp, condp} : condp;
|
||||
newp = new AstSFormatF{fl, "%s.%s", false, argsp};
|
||||
}
|
||||
AstNodeExpr* const origp = indexIsRand ? nullptr : nodep->cloneTree(false);
|
||||
AstCMethodHard* const sizep
|
||||
= m_structSel ? new AstCMethodHard{fl, nodep->fromp()->cloneTreePure(false),
|
||||
VCMethod::DYN_SIZE}
|
||||
: nullptr;
|
||||
AstNodeExpr* const originalPinp = nodep->pinsp();
|
||||
iterateChildren(nodep);
|
||||
AstNodeExpr* const pinp = nodep->pinsp()->unlinkFrBack();
|
||||
AstSFormatF* newp;
|
||||
if (m_structSel) {
|
||||
if (AstSFormatF* const sformatfp = VN_CAST(pinp, SFormatF)) {
|
||||
sformatfp->name("%x");
|
||||
}
|
||||
AstNodeExpr* const argsp
|
||||
= AstNode::addNext(nodep->fromp()->unlinkFrBack(), pinp);
|
||||
sizep->dtypeSetInt();
|
||||
AstLogAnd* const condp
|
||||
= new AstLogAnd{fl,
|
||||
new AstLteS{fl,
|
||||
new AstConst{fl, AstConst::WidthedValue{},
|
||||
originalPinp->width(), 0},
|
||||
originalPinp->cloneTreePure(false)},
|
||||
new AstLtS{fl, originalPinp->cloneTreePure(false), sizep}};
|
||||
m_conditionp = m_conditionp ? new AstLogAnd{fl, m_conditionp, condp} : condp;
|
||||
newp = new AstSFormatF{fl, "%s.%s", false, argsp};
|
||||
} else {
|
||||
newp = createSolverArrDerefp(fl, nodep->fromp()->unlinkFrBack(), pinp);
|
||||
}
|
||||
nodep->replaceWith(newp);
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
if (origp && !hoistRandModeOverSelect(newp, origp)) {
|
||||
VL_DO_DANGLING(origp->deleteTree(), origp);
|
||||
}
|
||||
|
||||
} else if (indexIsRand) {
|
||||
nodep->v3warn(E_UNSUPPORTED,
|
||||
"Unsupported: Randomization of an index to a non-random variable");
|
||||
|
||||
} else {
|
||||
newp = createSolverArrDerefp(fl, nodep->fromp()->unlinkFrBack(), pinp);
|
||||
}
|
||||
nodep->replaceWith(newp);
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
if (origp && !hoistRandModeOverSelect(newp, origp)) {
|
||||
VL_DO_DANGLING(origp->deleteTree(), origp);
|
||||
nodep->user1(false);
|
||||
UASSERT_OBJ(editFormat(nodep), nodep,
|
||||
"editFormat should return true when user1 is false");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user