parent
4f4d48e9d7
commit
45a5e72509
|
|
@ -134,6 +134,7 @@ Jose Loyola
|
||||||
Josep Sans
|
Josep Sans
|
||||||
Joseph Nwabueze
|
Joseph Nwabueze
|
||||||
Josh Redford
|
Josh Redford
|
||||||
|
Julian Carrier
|
||||||
Julian Daube
|
Julian Daube
|
||||||
Julie Schwartz
|
Julie Schwartz
|
||||||
Julien Margetts
|
Julien Margetts
|
||||||
|
|
|
||||||
|
|
@ -2667,12 +2667,27 @@ class ConstVisitor final : public VNVisitor {
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
if (const AstInitArray* const initp = VN_CAST(nodep->lhsp(), InitArray)) {
|
if (const AstInitArray* const initp = VN_CAST(nodep->lhsp(), InitArray)) {
|
||||||
if (!(m_doExpensive || m_params)) return false;
|
if (!(m_doExpensive || m_params)) return false;
|
||||||
// At present only support 1D unpacked arrays
|
const auto isConstInit = [](const AstNode* const exprp,
|
||||||
const auto initOfConst = [](const AstNode* const nodep) -> bool { //
|
const auto& isConstInitRecurse) -> bool {
|
||||||
return VN_IS(nodep, Const) || VN_IS(nodep, InitItem);
|
if (VN_IS(exprp, Const)) return true;
|
||||||
|
if (const AstInitItem* const itemp = VN_CAST(exprp, InitItem)) {
|
||||||
|
return isConstInitRecurse(itemp->valuep(), isConstInitRecurse);
|
||||||
|
}
|
||||||
|
if (const AstInitArray* const arrayp = VN_CAST(exprp, InitArray)) {
|
||||||
|
const auto itemIsConstInit = [&isConstInitRecurse](const AstNode* const itemp)
|
||||||
|
-> bool {
|
||||||
|
return isConstInitRecurse(itemp, isConstInitRecurse);
|
||||||
|
};
|
||||||
|
if (arrayp->initsp() && !arrayp->initsp()->forall(itemIsConstInit)) return false;
|
||||||
|
if (arrayp->defaultp()
|
||||||
|
&& !isConstInitRecurse(arrayp->defaultp(), isConstInitRecurse)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
};
|
};
|
||||||
if (initp->initsp() && !initp->initsp()->forall(initOfConst)) return false;
|
if (!isConstInit(initp, isConstInit)) return false;
|
||||||
if (initp->defaultp() && !initp->defaultp()->forall(initOfConst)) return false;
|
|
||||||
} else if (!VN_IS(nodep->lhsp(), Const)) {
|
} else if (!VN_IS(nodep->lhsp(), Const)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5282,6 +5282,34 @@ class WidthVisitor final : public VNVisitor {
|
||||||
return newp;
|
return newp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AstPatMember* defaultPatp_patternArray(AstPatMember* defaultp, AstNodeDType* elemDTypep) {
|
||||||
|
AstNodeExpr* const valuep = defaultp->lhssp()->cloneTree(false);
|
||||||
|
AstNodeDType* const elemDTypeSkipRefp = elemDTypep->skipRefp();
|
||||||
|
|
||||||
|
if (!VN_IS(elemDTypeSkipRefp, UnpackArrayDType)) {
|
||||||
|
VL_DO_DANGLING(pushDeletep(valuep), valuep);
|
||||||
|
return defaultp->cloneTree(false);
|
||||||
|
}
|
||||||
|
if (VN_IS(valuep, Pattern)) {
|
||||||
|
VL_DO_DANGLING(pushDeletep(valuep), valuep);
|
||||||
|
return defaultp->cloneTree(false);
|
||||||
|
}
|
||||||
|
if (!valuep->dtypep()) userIterate(valuep, WidthVP{SELF, BOTH}.p());
|
||||||
|
if (valuep->dtypep()
|
||||||
|
&& AstNode::computeCastable(valuep->dtypep()->skipRefp(), elemDTypeSkipRefp, nullptr)
|
||||||
|
.isAssignable()) {
|
||||||
|
VL_DO_DANGLING(pushDeletep(valuep), valuep);
|
||||||
|
return defaultp->cloneTree(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
AstPatMember* const nestedDefaultp
|
||||||
|
= new AstPatMember{defaultp->fileline(), valuep, nullptr, nullptr};
|
||||||
|
nestedDefaultp->isDefault(true);
|
||||||
|
AstPattern* const recursivePatternp
|
||||||
|
= new AstPattern{defaultp->fileline(), nestedDefaultp};
|
||||||
|
return new AstPatMember{defaultp->fileline(), recursivePatternp, nullptr, nullptr};
|
||||||
|
}
|
||||||
|
|
||||||
void patternArray(AstPattern* nodep, AstNodeArrayDType* arrayDtp, AstPatMember* defaultp) {
|
void patternArray(AstPattern* nodep, AstNodeArrayDType* arrayDtp, AstPatMember* defaultp) {
|
||||||
const VNumRange range = arrayDtp->declRange();
|
const VNumRange range = arrayDtp->declRange();
|
||||||
PatVecMap patmap = patVectorMap(nodep, range);
|
PatVecMap patmap = patVectorMap(nodep, range);
|
||||||
|
|
@ -5296,7 +5324,7 @@ class WidthVisitor final : public VNVisitor {
|
||||||
const auto it = patmap.find(ent);
|
const auto it = patmap.find(ent);
|
||||||
if (it == patmap.end()) {
|
if (it == patmap.end()) {
|
||||||
if (defaultp) {
|
if (defaultp) {
|
||||||
newpatp = defaultp->cloneTree(false);
|
newpatp = defaultPatp_patternArray(defaultp, arrayDtp->subDTypep());
|
||||||
patp = newpatp;
|
patp = newpatp;
|
||||||
} else if (!(VN_IS(arrayDtp, UnpackArrayDType) && !allConstant && isConcat)) {
|
} else if (!(VN_IS(arrayDtp, UnpackArrayDType) && !allConstant && isConcat)) {
|
||||||
// If arrayDtp is an unpacked array and item is not constant,
|
// If arrayDtp is an unpacked array and item is not constant,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of either the GNU Lesser General Public License Version 3
|
||||||
|
# or the Perl Artistic License Version 2.0.
|
||||||
|
# SPDX-FileCopyrightText: 2026 Wilson Snyder
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('simulator')
|
||||||
|
|
||||||
|
test.compile()
|
||||||
|
|
||||||
|
test.execute()
|
||||||
|
|
||||||
|
test.passes()
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||||
|
// SPDX-FileCopyrightText: 2026 Wilson Snyder
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
module t;
|
||||||
|
|
||||||
|
int arr_default_scalar[4][4];
|
||||||
|
int row[4];
|
||||||
|
int arr_default_array[2][4];
|
||||||
|
int arr_mixed_default[2][3];
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
arr_default_scalar = '{default: 0};
|
||||||
|
foreach (arr_default_scalar[i, j]) begin
|
||||||
|
if (arr_default_scalar[i][j] != 0) $stop;
|
||||||
|
end
|
||||||
|
|
||||||
|
row = '{1, 2, 3, 4};
|
||||||
|
arr_default_array = '{default: row};
|
||||||
|
foreach (arr_default_array[i, j]) begin
|
||||||
|
if (arr_default_array[i][j] != row[j]) $stop;
|
||||||
|
end
|
||||||
|
|
||||||
|
arr_mixed_default = '{0: '{0: 1, default: 3}, default: '{default: 2}};
|
||||||
|
if (arr_mixed_default[0][0] != 1) $stop;
|
||||||
|
if (arr_mixed_default[0][1] != 3) $stop;
|
||||||
|
if (arr_mixed_default[0][2] != 3) $stop;
|
||||||
|
if (arr_mixed_default[1][0] != 2) $stop;
|
||||||
|
if (arr_mixed_default[1][1] != 2) $stop;
|
||||||
|
if (arr_mixed_default[1][2] != 2) $stop;
|
||||||
|
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
-Info: t/t_assert_elab_p.v:14:5: %m test.sv:25: 4=4 2=2 STAGE_IDS='{'h1, 'h1, 'h1, 'h1}
|
-Info: t/t_assert_elab_p.v:14:5: %m test.sv:25: 4=4 2=2 STAGE_IDS='{'{'h1, 'h1}, '{'h1, 'h1}, '{'h1, 'h1}, '{'h1, 'h1}}
|
||||||
: ... note: In instance 't.pipe'
|
: ... note: In instance 't.pipe'
|
||||||
14 | $info("%m %s:%0d: 4=%0d 2=%0d STAGE_IDS=%p", "test.sv", 25, 4, 2, STAGE_IDS);
|
14 | $info("%m %s:%0d: 4=%0d 2=%0d STAGE_IDS=%p", "test.sv", 25, 4, 2, STAGE_IDS);
|
||||||
| ^~~~~
|
| ^~~~~
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue