Fix parameter types of user defined arrays (#6042)

This commit is contained in:
Todd Strader 2025-05-27 18:35:21 -04:00 committed by GitHub
parent 66259d8909
commit 76aced4d40
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 73 additions and 16 deletions

View File

@ -2353,6 +2353,9 @@ class LinkDotResolveVisitor final : public VNVisitor {
std::map<AstNode*, AstPin*> m_usedPins; // Pin used in this cell, map to duplicate std::map<AstNode*, AstPin*> m_usedPins; // Pin used in this cell, map to duplicate
std::map<std::string, AstNodeModule*> m_modulesToRevisit; // Modules to revisit a second time std::map<std::string, AstNodeModule*> m_modulesToRevisit; // Modules to revisit a second time
AstNode* m_lastDeferredp = nullptr; // Last node which requested a revisit of its module AstNode* m_lastDeferredp = nullptr; // Last node which requested a revisit of its module
bool m_maybePackedArray
= false; // Array select parse trees may actually be packed array datatypes
AstNodeDType* m_packedArrayDtp = nullptr; // Datatype reference for packed array
struct DotStates final { struct DotStates final {
DotPosition m_dotPos; // Scope part of dotted resolution DotPosition m_dotPos; // Scope part of dotted resolution
@ -3401,8 +3404,12 @@ class LinkDotResolveVisitor final : public VNVisitor {
if (ok) { if (ok) {
AstRefDType* const refp = new AstRefDType{nodep->fileline(), nodep->name()}; AstRefDType* const refp = new AstRefDType{nodep->fileline(), nodep->name()};
refp->typedefp(defp); refp->typedefp(defp);
replaceWithCheckBreak(nodep, refp); if (m_maybePackedArray) {
VL_DO_DANGLING(pushDeletep(nodep), nodep); m_packedArrayDtp = refp;
} else {
replaceWithCheckBreak(nodep, refp);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
} }
} else if (AstParamTypeDType* const defp = VN_CAST(foundp->nodep(), ParamTypeDType)) { } else if (AstParamTypeDType* const defp = VN_CAST(foundp->nodep(), ParamTypeDType)) {
ok = (m_ds.m_dotPos == DP_NONE || m_ds.m_dotPos == DP_SCOPE); ok = (m_ds.m_dotPos == DP_NONE || m_ds.m_dotPos == DP_SCOPE);
@ -4048,22 +4055,48 @@ class LinkDotResolveVisitor final : public VNVisitor {
m_ds.m_dotErr = true; m_ds.m_dotErr = true;
return; return;
} }
iterateAndNextNull(nodep->fromp()); AstNodeDType* packedArrayDtp = nullptr; // Datatype reference for packed array
symIterateNull(nodep->rhsp(), m_curSymp); {
symIterateNull(nodep->thsp(), m_curSymp); VL_RESTORER(m_packedArrayDtp);
{
VL_RESTORER(m_maybePackedArray);
m_maybePackedArray = true;
iterateAndNextNull(nodep->fromp());
}
symIterateNull(nodep->rhsp(), m_curSymp);
symIterateNull(nodep->thsp(), m_curSymp);
if (nodep->attrp()) { if (m_packedArrayDtp) {
AstNode* const attrp = nodep->attrp()->unlinkFrBack(); AstRange* const newRangep
VL_DO_DANGLING(attrp->deleteTree(), attrp); = new AstRange(nodep->fileline(), nodep->rhsp()->unlinkFrBack(),
} nodep->thsp()->unlinkFrBack());
AstNode* const basefromp = AstArraySel::baseFromp(nodep, false); AstPackArrayDType* newArrayTypep
if (VN_IS(basefromp, Replicate)) { = new AstPackArrayDType(nodep->fileline(), m_packedArrayDtp, newRangep);
// From {...}[...] syntax in IEEE 2017 newArrayTypep->childDTypep(m_packedArrayDtp);
if (basefromp) UINFO(9, indent() << " Related node: " << basefromp); newArrayTypep->refDTypep(nullptr);
} else { if (m_maybePackedArray) {
nodep->attrp(new AstAttrOf{nodep->fileline(), VAttrType::VAR_BASE, packedArrayDtp = newArrayTypep;
basefromp->cloneTree(false)}); } else {
replaceWithCheckBreak(nodep, newArrayTypep);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
} else {
if (nodep->attrp()) {
AstNode* const attrp = nodep->attrp()->unlinkFrBack();
VL_DO_DANGLING(attrp->deleteTree(), attrp);
}
AstNode* const basefromp = AstArraySel::baseFromp(nodep, false);
if (VN_IS(basefromp, Replicate)) {
// From {...}[...] syntax in IEEE 2017
if (basefromp) UINFO(9, indent() << " Related node: " << basefromp);
} else {
nodep->attrp(new AstAttrOf{nodep->fileline(), VAttrType::VAR_BASE,
basefromp->cloneTree(false)});
}
}
} }
if (packedArrayDtp) { m_packedArrayDtp = packedArrayDtp; }
} }
void visit(AstMemberSel* nodep) override { void visit(AstMemberSel* nodep) override {
// checkNoDot not appropriate, can be under a dot // checkNoDot not appropriate, can be under a dot

View File

@ -40,6 +40,20 @@ module t();
foo #(.bar (logic [ $bits(qux3) - 1 : 0])) foo #(.bar (logic [ $bits(qux3) - 1 : 0]))
foo_inst3 (.bar_size (bar_size3)); foo_inst3 (.bar_size (bar_size3));
typedef struct packed {
logic foo;
logic bar;
} some_struct_t;
int bar_size4;
foo #(.bar (some_struct_t [7:0]))
foo_inst4 (.bar_size (bar_size4));
int bar_size5;
foo #(.bar (some_struct_t [2:0] [5:0]))
foo_inst5 (.bar_size (bar_size5));
localparam bar_bits = 13; localparam bar_bits = 13;
int bar_size_wrapper; int bar_size_wrapper;
@ -82,6 +96,16 @@ module t();
bar_size3, $bits(qux3)); bar_size3, $bits(qux3));
$stop(); $stop();
end end
if (bar_size4 != $bits(some_struct_t)*8) begin
$display("%m: bar_size4 != bits of some_struct_t * 8 (%0d, %0d)",
bar_size4, $bits(some_struct_t) * 8);
$stop();
end
if (bar_size5 != $bits(some_struct_t)*3*6) begin
$display("%m: bar_size5 != bits of some_struct_t * 3 * 6 (%0d, %0d)",
bar_size5, $bits(some_struct_t) * 3 * 6);
$stop();
end
if (bar_size_wrapper != bar_bits) begin if (bar_size_wrapper != bar_bits) begin
$display("%m: bar_size_wrapper != bar_bits (%0d, %0d)", $display("%m: bar_size_wrapper != bar_bits (%0d, %0d)",
bar_size_wrapper, bar_bits); bar_size_wrapper, bar_bits);