Fix aggregate member bits lookup
This commit is contained in:
parent
ed4c340d42
commit
c433a489d4
|
|
@ -1993,6 +1993,17 @@ class LinkDotFindVisitor final : public VNVisitor {
|
||||||
// No need to insert, only the real typedef matters, but need to track for errors
|
// No need to insert, only the real typedef matters, but need to track for errors
|
||||||
nodep->user1p(m_curSymp);
|
nodep->user1p(m_curSymp);
|
||||||
}
|
}
|
||||||
|
void visit(AstNodeUOrStructDType* nodep) override { // FindVisitor::
|
||||||
|
UASSERT_OBJ(m_curSymp, nodep, "Struct/union dtype not under module/package/$unit");
|
||||||
|
VL_RESTORER(m_curSymp);
|
||||||
|
m_curSymp = m_statep->insertBlock(
|
||||||
|
m_curSymp, "__Vdtype" + cvtToStr(nodep->uniqueNum()), nodep, m_classOrPackagep);
|
||||||
|
iterateChildren(nodep);
|
||||||
|
}
|
||||||
|
void visit(AstMemberDType* nodep) override { // FindVisitor::
|
||||||
|
iterateChildren(nodep);
|
||||||
|
m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_classOrPackagep);
|
||||||
|
}
|
||||||
void visit(AstParamTypeDType* nodep) override { // FindVisitor::
|
void visit(AstParamTypeDType* nodep) override { // FindVisitor::
|
||||||
UASSERT_OBJ(m_curSymp, nodep, "Parameter type not under module/package/$unit");
|
UASSERT_OBJ(m_curSymp, nodep, "Parameter type not under module/package/$unit");
|
||||||
|
|
||||||
|
|
@ -3511,6 +3522,21 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||||
<< declp->warnContextSecondary());
|
<< declp->warnContextSecondary());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void checkMemberDeclOrder(AstNode* nodep, AstMemberDType* declp) {
|
||||||
|
const uint32_t declTokenNum = declp->fileline()->tokenNum();
|
||||||
|
if (nodep->fileline()->tokenNum() < declTokenNum) {
|
||||||
|
UINFO(1, "Related node " << nodep->fileline()->tokenNum() << " " << nodep);
|
||||||
|
UINFO(1, "Related decl " << declTokenNum << " " << declp);
|
||||||
|
nodep->v3error("Reference to "
|
||||||
|
<< nodep->prettyNameQ()
|
||||||
|
<< " before declaration (IEEE 1800-2023 6.18)\n"
|
||||||
|
<< nodep->warnMore()
|
||||||
|
<< "... Suggest move the declaration before the reference\n"
|
||||||
|
<< nodep->warnContextPrimary() << '\n'
|
||||||
|
<< declp->warnOther() << "... Location of original declaration\n"
|
||||||
|
<< declp->warnContextSecondary());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void replaceWithCheckBreak(AstNode* oldp, AstNodeDType* newp) {
|
void replaceWithCheckBreak(AstNode* oldp, AstNodeDType* newp) {
|
||||||
// Flag now to avoid V3Broken throwing an internal error
|
// Flag now to avoid V3Broken throwing an internal error
|
||||||
|
|
@ -3536,6 +3562,15 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||||
if (nodep && nodep->isParam()) nodep->usedParam(true);
|
if (nodep && nodep->isParam()) nodep->usedParam(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VSymEnt* findIdFallbackSkipMemberDType(VSymEnt* lookp, const string& name) {
|
||||||
|
while (lookp) {
|
||||||
|
VSymEnt* const foundp = lookp->findIdFlat(name);
|
||||||
|
if (foundp && !VN_IS(foundp->nodep(), MemberDType)) return foundp;
|
||||||
|
lookp = lookp->fallbackp();
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void symIterateChildren(AstNode* nodep, VSymEnt* symp) {
|
void symIterateChildren(AstNode* nodep, VSymEnt* symp) {
|
||||||
// Iterate children, changing to given context, with restore to old context
|
// Iterate children, changing to given context, with restore to old context
|
||||||
VL_RESTORER(m_ds);
|
VL_RESTORER(m_ds);
|
||||||
|
|
@ -4532,6 +4567,16 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||||
} else {
|
} else {
|
||||||
(void)defp; // Prevent unused variable warning
|
(void)defp; // Prevent unused variable warning
|
||||||
}
|
}
|
||||||
|
} else if (AstMemberDType* const defp = VN_CAST(foundp->nodep(), MemberDType)) {
|
||||||
|
if (allowVar) {
|
||||||
|
checkMemberDeclOrder(nodep, defp);
|
||||||
|
AstRefDType* const refp = new AstRefDType{nodep->fileline(), nodep->name()};
|
||||||
|
refp->refDTypep(defp);
|
||||||
|
replaceWithCheckBreak(nodep, refp);
|
||||||
|
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||||
|
ok = true;
|
||||||
|
m_ds.m_dotText = "";
|
||||||
|
}
|
||||||
} else if (AstEnumItem* const valuep = VN_CAST(foundp->nodep(), EnumItem)) {
|
} else if (AstEnumItem* const valuep = VN_CAST(foundp->nodep(), EnumItem)) {
|
||||||
if (allowVar) {
|
if (allowVar) {
|
||||||
AstNode* const newp
|
AstNode* const newp
|
||||||
|
|
@ -4967,6 +5012,10 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||||
refdtypep->v3error("Self-referential enumerated type definition");
|
refdtypep->v3error("Self-referential enumerated type definition");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void visit(AstNodeUOrStructDType* nodep) override {
|
||||||
|
LINKDOT_VISIT_START();
|
||||||
|
symIterateChildren(nodep, m_statep->getNodeSym(nodep));
|
||||||
|
}
|
||||||
void visit(AstEnumItemRef* nodep) override {
|
void visit(AstEnumItemRef* nodep) override {
|
||||||
// Resolve its reference
|
// Resolve its reference
|
||||||
// EnumItemRefs are created by the first pass, but V3Param may regenerate due to
|
// EnumItemRefs are created by the first pass, but V3Param may regenerate due to
|
||||||
|
|
@ -5984,7 +6033,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||||
if (nodep->classOrPackagep()) {
|
if (nodep->classOrPackagep()) {
|
||||||
foundp = m_statep->getNodeSym(nodep->classOrPackagep())->findIdFlat(nodep->name());
|
foundp = m_statep->getNodeSym(nodep->classOrPackagep())->findIdFlat(nodep->name());
|
||||||
} else if (m_ds.m_dotPos == DP_FIRST || m_ds.m_dotPos == DP_NONE) {
|
} else if (m_ds.m_dotPos == DP_FIRST || m_ds.m_dotPos == DP_NONE) {
|
||||||
foundp = m_curSymp->findIdFallback(nodep->name());
|
foundp = findIdFallbackSkipMemberDType(m_curSymp, nodep->name());
|
||||||
} else {
|
} else {
|
||||||
// Defensive: dotPos should be DP_FIRST/DP_NONE or classOrPackagep set.
|
// Defensive: dotPos should be DP_FIRST/DP_NONE or classOrPackagep set.
|
||||||
v3fatalSrc("Unexpected dotPos="
|
v3fatalSrc("Unexpected dotPos="
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,17 @@ module t;
|
||||||
byte tail;
|
byte tail;
|
||||||
} packed_union_struct_t;
|
} packed_union_struct_t;
|
||||||
|
|
||||||
|
localparam int WORD_WIDTH = 16;
|
||||||
|
|
||||||
|
typedef union packed {
|
||||||
|
struct packed {
|
||||||
|
logic [15:0] temp_1;
|
||||||
|
logic [15:0] temp_2;
|
||||||
|
logic [15:0] temp_3;
|
||||||
|
} regs;
|
||||||
|
logic [($bits(regs) / WORD_WIDTH)-1:0][WORD_WIDTH-1:0] words;
|
||||||
|
} issue_4521_union_t;
|
||||||
|
|
||||||
simple_t simple;
|
simple_t simple;
|
||||||
simple_t simple_out;
|
simple_t simple_out;
|
||||||
simple_t simple_cont_out;
|
simple_t simple_cont_out;
|
||||||
|
|
@ -106,6 +117,7 @@ module t;
|
||||||
real_struct_t real_struct_out;
|
real_struct_t real_struct_out;
|
||||||
packed_union_struct_t packed_union_struct;
|
packed_union_struct_t packed_union_struct;
|
||||||
packed_union_struct_t packed_union_struct_out;
|
packed_union_struct_t packed_union_struct_out;
|
||||||
|
issue_4521_union_t issue_4521_union;
|
||||||
|
|
||||||
logic [19:0] simple_bits;
|
logic [19:0] simple_bits;
|
||||||
logic [31:0] wide_simple_bits;
|
logic [31:0] wide_simple_bits;
|
||||||
|
|
@ -349,6 +361,16 @@ module t;
|
||||||
`checkh(packed_union_struct_out.u.byte_data, 8'hca);
|
`checkh(packed_union_struct_out.u.byte_data, 8'hca);
|
||||||
`checkh(packed_union_struct_out.tail, 8'hfe);
|
`checkh(packed_union_struct_out.tail, 8'hfe);
|
||||||
|
|
||||||
|
`checkh($bits(issue_4521_union_t), 48);
|
||||||
|
`checkh($bits(issue_4521_union.regs), 48);
|
||||||
|
`checkh($bits(issue_4521_union.words), 48);
|
||||||
|
issue_4521_union.regs.temp_1 = 16'h1234;
|
||||||
|
issue_4521_union.regs.temp_2 = 16'h5678;
|
||||||
|
issue_4521_union.regs.temp_3 = 16'h9abc;
|
||||||
|
`checkh(issue_4521_union.words[2], 16'h1234);
|
||||||
|
`checkh(issue_4521_union.words[1], 16'h5678);
|
||||||
|
`checkh(issue_4521_union.words[0], 16'h9abc);
|
||||||
|
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -2,4 +2,11 @@
|
||||||
13 | i badi;
|
13 | i badi;
|
||||||
| ^
|
| ^
|
||||||
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
||||||
|
%Error: t/t_struct_type_bad.v:18:19: Reference to 'later' before declaration (IEEE 1800-2023 6.18)
|
||||||
|
: ... Suggest move the declaration before the reference
|
||||||
|
18 | logic [($bits(later) / 8)-1:0][7:0] bad_forward;
|
||||||
|
| ^~~~~
|
||||||
|
t/t_struct_type_bad.v:19:18: ... Location of original declaration
|
||||||
|
19 | logic [15:0] later;
|
||||||
|
| ^~~~~
|
||||||
%Error: Exiting due to
|
%Error: Exiting due to
|
||||||
|
|
|
||||||
|
|
@ -13,4 +13,10 @@ module t;
|
||||||
i badi; // Bad
|
i badi; // Bad
|
||||||
} struct_t;
|
} struct_t;
|
||||||
|
|
||||||
|
typedef union packed {
|
||||||
|
// Bad
|
||||||
|
logic [($bits(later) / 8)-1:0][7:0] bad_forward;
|
||||||
|
logic [15:0] later;
|
||||||
|
} forward_member_t;
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue