parent
4c5e104825
commit
26c85d4495
|
|
@ -1993,6 +1993,17 @@ class LinkDotFindVisitor final : public VNVisitor {
|
|||
// No need to insert, only the real typedef matters, but need to track for errors
|
||||
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::
|
||||
UASSERT_OBJ(m_curSymp, nodep, "Parameter type not under module/package/$unit");
|
||||
|
||||
|
|
@ -3511,6 +3522,20 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
<< 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) {
|
||||
// Flag now to avoid V3Broken throwing an internal error
|
||||
|
|
@ -3536,6 +3561,15 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
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) {
|
||||
// Iterate children, changing to given context, with restore to old context
|
||||
VL_RESTORER(m_ds);
|
||||
|
|
@ -4532,6 +4566,16 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
} else {
|
||||
(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)) {
|
||||
if (allowVar) {
|
||||
AstNode* const newp
|
||||
|
|
@ -4967,6 +5011,10 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
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 {
|
||||
// Resolve its reference
|
||||
// EnumItemRefs are created by the first pass, but V3Param may regenerate due to
|
||||
|
|
@ -5984,7 +6032,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
if (nodep->classOrPackagep()) {
|
||||
foundp = m_statep->getNodeSym(nodep->classOrPackagep())->findIdFlat(nodep->name());
|
||||
} 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 {
|
||||
// Defensive: dotPos should be DP_FIRST/DP_NONE or classOrPackagep set.
|
||||
v3fatalSrc("Unexpected dotPos="
|
||||
|
|
|
|||
|
|
@ -9661,7 +9661,8 @@ class WidthVisitor final : public VNVisitor {
|
|||
continue;
|
||||
} else if (const AstNodeUOrStructDType* const adtypep
|
||||
= VN_CAST(dtypep, NodeUOrStructDType)) {
|
||||
bits *= adtypep->width();
|
||||
bits *= adtypep->isStreamableFixedAggregate() ? adtypep->widthStream()
|
||||
: adtypep->width();
|
||||
break;
|
||||
} else if (const AstBasicDType* const adtypep = VN_CAST(dtypep, BasicDType)) {
|
||||
bits *= adtypep->width();
|
||||
|
|
|
|||
|
|
@ -83,6 +83,17 @@ module t;
|
|||
byte tail;
|
||||
} 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_out;
|
||||
simple_t simple_cont_out;
|
||||
|
|
@ -106,6 +117,7 @@ module t;
|
|||
real_struct_t real_struct_out;
|
||||
packed_union_struct_t packed_union_struct;
|
||||
packed_union_struct_t packed_union_struct_out;
|
||||
issue_4521_union_t issue_4521_union;
|
||||
|
||||
logic [19:0] simple_bits;
|
||||
logic [31:0] wide_simple_bits;
|
||||
|
|
@ -122,6 +134,7 @@ module t;
|
|||
logic [15:0] packed_union_bits;
|
||||
logic [11:0] narrow_bits;
|
||||
logic [19:0] simple_streaml_src;
|
||||
logic [$bits(simple_t)-1:0] simple_bits_from_bits;
|
||||
byte byte_array_out[2];
|
||||
|
||||
assign {>>{simple_cont_out}} = 20'habcde;
|
||||
|
|
@ -138,6 +151,13 @@ module t;
|
|||
`checkh(simple_bits, 20'h54321);
|
||||
|
||||
simple = '{8'h12, 4'ha, '{4'hb, 4'hc}};
|
||||
`checkh($bits(simple_t), 20);
|
||||
`checkh($bits(array_t), 32);
|
||||
`checkh($bits(nested_t), 36);
|
||||
`checkh($bits(struct_array_t), 56);
|
||||
`checkh($bits(simple_array), 40);
|
||||
simple_bits_from_bits = {>>{simple}};
|
||||
`checkh(simple_bits_from_bits, 20'h12abc);
|
||||
simple_bits = {>>{simple}};
|
||||
`checkh(simple_bits, 20'h12abc);
|
||||
/* verilator lint_off WIDTHEXPAND */
|
||||
|
|
@ -341,6 +361,16 @@ module t;
|
|||
`checkh(packed_union_struct_out.u.byte_data, 8'hca);
|
||||
`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");
|
||||
$finish;
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,4 +2,11 @@
|
|||
13 | i badi;
|
||||
| ^
|
||||
... 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
|
||||
|
|
|
|||
|
|
@ -13,4 +13,10 @@ module t;
|
|||
i badi; // Bad
|
||||
} struct_t;
|
||||
|
||||
typedef union packed {
|
||||
// Bad
|
||||
logic [($bits(later) / 8)-1:0][7:0] bad_forward;
|
||||
logic [15:0] later;
|
||||
} forward_member_t;
|
||||
|
||||
endmodule
|
||||
|
|
|
|||
Loading…
Reference in New Issue