mirror of
https://github.com/verilator/verilator.git
synced 2025-01-01 04:07:34 +00:00
Fix arrays of unpacked structs (#4173).
This commit is contained in:
parent
c6052830e1
commit
0606a29f13
1
Changes
1
Changes
@ -27,6 +27,7 @@ Verilator 5.011 devel
|
||||
* Fix initialization order of initial static after function/task (#4159). [Kamil Rakoczy, Antmicro Ltd]
|
||||
* Fix linking AstRefDType if it has parameterized class ref (#4164) (#4170). [Ryszard Rozak, Antmicro Ltd]
|
||||
* Fix crash caused by $display() optimization (#4165) (#4166). [Tudor Timi]
|
||||
* Fix arrays of unpacked structs (#4173). [Risto Pejašinović]
|
||||
* Fix detection of wire/reg duplicates.
|
||||
* Fix false IMPLICITSTATIC on package functions.
|
||||
|
||||
|
@ -887,6 +887,7 @@ public:
|
||||
if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep();
|
||||
}
|
||||
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
|
||||
AstNodeUOrStructDType* getChildStructp() const;
|
||||
AstNodeDType* subDTypep() const override VL_MT_STABLE {
|
||||
return m_refDTypep ? m_refDTypep : childDTypep();
|
||||
}
|
||||
|
@ -1671,10 +1671,19 @@ void AstLogOr::dump(std::ostream& str) const {
|
||||
this->AstNodeExpr::dump(str);
|
||||
if (sideEffect()) str << " [SIDE]";
|
||||
}
|
||||
|
||||
void AstMemberDType::dumpSmall(std::ostream& str) const {
|
||||
this->AstNodeDType::dumpSmall(str);
|
||||
str << "member";
|
||||
}
|
||||
AstNodeUOrStructDType* AstMemberDType::getChildStructp() const {
|
||||
AstNodeDType* subdtp = skipRefp();
|
||||
while (AstNodeArrayDType* const asubdtp = VN_CAST(subdtp, NodeArrayDType)) {
|
||||
subdtp = asubdtp->subDTypep();
|
||||
}
|
||||
return VN_CAST(subdtp, NodeUOrStructDType); // Maybe nullptr
|
||||
}
|
||||
|
||||
void AstMemberSel::dump(std::ostream& str) const {
|
||||
this->AstNodeExpr::dump(str);
|
||||
str << " -> ";
|
||||
@ -1831,6 +1840,7 @@ void AstNodeUOrStructDType::dump(std::ostream& str) const {
|
||||
this->AstNodeDType::dump(str);
|
||||
if (packed()) str << " [PACKED]";
|
||||
if (isFourstate()) str << " [4STATE]";
|
||||
if (classOrPackagep()) str << " pkg=" << nodeAddr(classOrPackagep());
|
||||
}
|
||||
void AstNodeDType::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
|
@ -62,6 +62,7 @@ private:
|
||||
AstClassPackage* const packagep
|
||||
= new AstClassPackage{nodep->fileline(), nodep->origName()};
|
||||
packagep->name(nodep->name() + "__Vclpkg");
|
||||
nodep->editCountInc();
|
||||
nodep->classOrPackagep(packagep);
|
||||
packagep->classp(nodep);
|
||||
v3Global.rootp()->addModulesp(packagep);
|
||||
@ -177,14 +178,15 @@ private:
|
||||
}
|
||||
|
||||
void setStructModulep(AstNodeUOrStructDType* const dtypep) {
|
||||
// Give it a pointer to its package and a final name
|
||||
// Give struct a pointer to its package and a final name
|
||||
dtypep->editCountInc();
|
||||
dtypep->classOrPackagep(m_classPackagep ? m_classPackagep : m_modp);
|
||||
dtypep->name(dtypep->name() + (VN_IS(dtypep, UnionDType) ? "__union" : "__struct")
|
||||
+ cvtToStr(dtypep->uniqueNum()));
|
||||
|
||||
for (const AstMemberDType* itemp = dtypep->membersp(); itemp;
|
||||
itemp = VN_AS(itemp->nextp(), MemberDType)) {
|
||||
AstNodeUOrStructDType* const subp = VN_CAST(itemp->skipRefp(), NodeUOrStructDType);
|
||||
AstNodeUOrStructDType* const subp = itemp->getChildStructp();
|
||||
// Recurse only into anonymous unpacked structs inside this definition,
|
||||
// other unpacked structs will be reached from another typedefs
|
||||
if (subp && !subp->packed() && subp->name().empty()) setStructModulep(subp);
|
||||
|
@ -63,6 +63,7 @@ static void makeVlToString(AstIface* nodep) {
|
||||
}
|
||||
static void makeVlToString(AstNodeUOrStructDType* nodep) {
|
||||
AstNodeModule* const modp = nodep->classOrPackagep();
|
||||
UASSERT_OBJ(modp, nodep, "Unlinked struct package");
|
||||
AstCFunc* const funcp
|
||||
= new AstCFunc{nodep->fileline(), "VL_TO_STRING", nullptr, "std::string"};
|
||||
funcp->argTypes("const " + EmitCBase::prefixNameProtect(nodep) + "& obj");
|
||||
|
@ -219,7 +219,7 @@ class EmitCHeader final : public EmitCConstInit {
|
||||
emitted.insert(sdtypep);
|
||||
for (const AstMemberDType* itemp = sdtypep->membersp(); itemp;
|
||||
itemp = VN_AS(itemp->nextp(), MemberDType)) {
|
||||
AstNodeUOrStructDType* subp = VN_CAST(itemp->skipRefp(), NodeUOrStructDType);
|
||||
AstNodeUOrStructDType* const subp = itemp->getChildStructp();
|
||||
if (subp && !subp->packed()) {
|
||||
// Recurse if it belongs to the current module
|
||||
if (subp->classOrPackagep() == modp) {
|
||||
|
@ -54,6 +54,7 @@ class EmitCGatherDependencies final : VNVisitorConst {
|
||||
} else if (const AstNodeUOrStructDType* const dtypep
|
||||
= VN_CAST(nodep, NodeUOrStructDType)) {
|
||||
if (!dtypep->packed()) {
|
||||
UASSERT_OBJ(dtypep->classOrPackagep(), nodep, "Unlinked struct package");
|
||||
m_dependencies.insert(EmitCBase::prefixNameProtect(dtypep->classOrPackagep()));
|
||||
}
|
||||
}
|
||||
|
21
test_regress/t/t_struct_nest_uarray.pl
Executable file
21
test_regress/t/t_struct_nest_uarray.pl
Executable file
@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. 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-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
scenarios(simulator => 1);
|
||||
|
||||
compile(
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
48
test_regress/t/t_struct_nest_uarray.v
Normal file
48
test_regress/t/t_struct_nest_uarray.v
Normal file
@ -0,0 +1,48 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2023 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
`define stop $stop
|
||||
`define checks(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='%s' exp='%s'\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||
|
||||
typedef struct {
|
||||
struct {
|
||||
struct {
|
||||
logic [31:0] next;
|
||||
} val;
|
||||
} el[1];
|
||||
} pstr_t;
|
||||
|
||||
module t (/*AUTOARG*/);
|
||||
|
||||
typedef struct {
|
||||
struct {
|
||||
struct {
|
||||
logic [31:0] next;
|
||||
} val;
|
||||
} el[1];
|
||||
} str_t;
|
||||
|
||||
str_t str;
|
||||
pstr_t pstr;
|
||||
|
||||
initial begin
|
||||
string s;
|
||||
|
||||
str.el[0].val.next = 6;
|
||||
s = $sformatf("%p", str);
|
||||
$display("%s", s);
|
||||
`checks(s, "'{el:'{'{val:'{next:'h6}}} }");
|
||||
|
||||
pstr.el[0].val.next = 6;
|
||||
s = $sformatf("%p", pstr);
|
||||
$display("%s", s);
|
||||
`checks(s, "'{el:'{'{val:'{next:'h6}}} }");
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
Loading…
Reference in New Issue
Block a user