Fix unused parameterized class causing internal error (#4013).

This commit is contained in:
Wilson Snyder 2025-09-26 20:50:47 -04:00
parent ebee20c47d
commit 1761622e14
6 changed files with 78 additions and 1 deletions

View File

@ -36,6 +36,7 @@ Verilator 5.041 devel
* Optimize dead functions in more cases (#6380) (#6430). [Artur Bieniek, Antmicro Ltd.]
* Optimize constant folding in wide expression expansion (#6381). [Geza Lore]
* Fix missing BLKSEQ when connecting module port to array (#2973).
* Fix unused parameterized class causing internal error (#4013). [Alberto Del Rio]
* Fix false CONSTVAR error on initializers (#4992).
* Fix interface exposure with `--public-depth` or `--trace-depth` (#5758).
* Fix cell scoping performance (#6059). [Jerry Tianchen]

View File

@ -2165,6 +2165,9 @@ public:
bool brokeExists() const { return V3Broken::isLinkable(this); }
bool brokeExistsAbove() const { return brokeExists() && (m_brokenState >> 7); }
// Perform a function on every link in a node
virtual void foreachLink(std::function<void(AstNode** linkpp, const char* namep)> f) = 0;
#ifdef VL_LEAK_CHECKS
static void* operator new(size_t size);
static void operator delete(void* obj, size_t size);

View File

@ -1110,7 +1110,7 @@ class ParamProcessor final {
UINFO(8, " Done with " << modInfop->m_modp);
newModp = modInfop->m_modp;
}
if (defaultsResolved) { srcModp->user4p(newModp); }
if (defaultsResolved) srcModp->user4p(newModp);
for (auto* stmtp = newModp->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
if (AstParamTypeDType* dtypep = VN_CAST(stmtp, ParamTypeDType)) {
@ -1843,12 +1843,15 @@ public:
resortNetlistModules(netlistp);
// Remove defaulted classes
// Unlike modules, which we keep around and mark dead() for later V3Dead
std::unordered_set<AstClass*> removedClassps;
for (AstClass* const classp : m_state.m_paramClasses) {
if (!classp->user3p()) {
// If there was an error, don't remove classes as they might
// have remained referenced, and will crash in V3Broken or
// other locations. This is fine, we will abort imminently.
if (V3Error::errorCount()) continue;
removedClassps.emplace(classp);
VL_DO_DANGLING(pushDeletep(classp->unlinkFrBack()), classp);
} else {
// Referenced. classp became a specialized class with the default
@ -1856,6 +1859,18 @@ public:
classp->hasGParam(false);
}
}
// Remove references to defaulted classes
// Reuse user3 to mark all nodes being deleted
AstNode::user3ClearTree();
for (AstClass* classp : removedClassps) {
classp->foreach([](AstNode* const nodep) { nodep->user3(true); });
}
// Set all links pointing to a user3 (deleting) node as null
netlistp->foreach([](AstNode* const nodep) {
nodep->foreachLink([](AstNode** const linkpp, const char*) {
if (*linkpp && (*linkpp)->user3()) *linkpp = nullptr;
});
});
}
~ParamTop() = default;
VL_UNCOPYABLE(ParamTop);

View File

@ -1027,6 +1027,16 @@ def write_ast_impl(filename):
emitBlock("}}\n")
emitBlock("void Ast{t}::foreachLink(std::function<void(" +
"AstNode** linkpp, const char* namep)> f) {{\n",
t=node.name)
if node.superClass.name != 'Node':
emitBlock(" Ast{base}::foreachLink(f);\n", base=node.superClass.name)
for ptr in node.ptrs:
emitBlock(" f(reinterpret_cast<AstNode**>(&m_{name}), \"{name}\");",
name=ptr['name'])
emitBlock("}}\n")
emitBlock("void Ast{t}::dumpJsonGen(std::ostream& str) const {{\n", t=node.name)
if node.superClass.name != 'Node':
emitBlock(" Ast{base}::dumpJson(str);\n", base=node.superClass.name)
@ -1088,6 +1098,7 @@ def write_ast_macros(filename):
Ast{t}* clonep() const {{ return static_cast<Ast{t}*>(AstNode::clonep()); }}
Ast{t}* addNext(Ast{t}* nodep) {{ return static_cast<Ast{t}*>(AstNode::addNext(this, nodep)); }}
const char* brokenGen() const override;
void foreachLink(std::function<void(AstNode** linkpp, const char* namep)> f) override;
bool wouldBreakGen(const AstNode* const oldp, const AstNode* const newp) const override;
void dumpTreeJsonOpGen(std::ostream& str, const string& indent) const override;
void dumpJsonGen(std::ostream& str) const;

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2024 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
import vltest_bootstrap
test.scenarios('simulator')
test.compile()
test.execute()
test.passes()

View File

@ -0,0 +1,29 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module sub #(
parameter type T = logic
);
mailbox #(T) mbox;
endmodule
module try #(
parameter I = 1
);
endmodule
module t;
typedef struct packed {
logic a;
logic b;
} my_struct_t;
sub #(my_struct_t) u_sub ();
try #(2) u_try2 ();
initial $finish;
endmodule