mirror of
https://github.com/verilator/verilator.git
synced 2026-10-05 17:43:31 +02:00
This commit is contained in:
@@ -309,6 +309,8 @@ class ParamProcessor final {
|
||||
// Guard against infinite recursion in classTypeMatchesDefaultClone slow path
|
||||
std::unordered_set<const AstClass*> m_defaultCloneInProgress;
|
||||
|
||||
std::vector<AstClass*> m_specializedClassps; // Classes specialized since last drained
|
||||
|
||||
// member names cached for fast lookup
|
||||
VMemberMap m_memberMap;
|
||||
|
||||
@@ -2143,6 +2145,14 @@ class ParamProcessor final {
|
||||
const bool cloned = (newModp != srcModp);
|
||||
UINFO(9, "nodeDeparamCommon result: " << newModp->prettyNameQ() << " cloned=" << cloned);
|
||||
|
||||
// ParamVisitor skips the body of a class still marked hasGParam(), relying on it
|
||||
// being visited through a reference instead. A class reached only by a deferred
|
||||
// class-scoped reference (e.g. the 'C#(V)::t' default of a type parameter that the
|
||||
// instantiation overrides) is never visited, so record specializations here.
|
||||
// user2() is set once processWorkQ has elaborated the body, which needs no re-queue.
|
||||
AstClass* const newClassp = VN_CAST(newModp, Class);
|
||||
if (newClassp && !newClassp->user2()) m_specializedClassps.push_back(newClassp);
|
||||
|
||||
// Link source class to its specialized version for later relinking of method references
|
||||
if (defaultsResolved) srcModp->user4p(newModp);
|
||||
|
||||
@@ -2455,6 +2465,13 @@ public:
|
||||
return newModp;
|
||||
}
|
||||
|
||||
// Return, and forget, the classes specialized since the previous call
|
||||
std::vector<AstClass*> takeSpecializedClassps() {
|
||||
std::vector<AstClass*> taken;
|
||||
taken.swap(m_specializedClassps);
|
||||
return taken;
|
||||
}
|
||||
|
||||
// CONSTRUCTORS
|
||||
explicit ParamProcessor(AstNetlist* nodep)
|
||||
: m_hierBlocks{v3Global.opt.hierBlocks(), nodep} {
|
||||
@@ -2775,6 +2792,10 @@ class ParamVisitor final : public VNVisitor {
|
||||
|
||||
// Visit all cells under module, recursively
|
||||
while (true) {
|
||||
// Classes specialized since the last pass still need their bodies elaborated
|
||||
for (AstClass* const classp : m_processor.takeSpecializedClassps()) {
|
||||
m_state.m_workQueueNext.emplace(ParamState::WQKey{true, classp->level()}, classp);
|
||||
}
|
||||
if (workQueue.empty()) std::swap(workQueue, m_state.m_workQueueNext);
|
||||
if (workQueue.empty()) break;
|
||||
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# 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-FileCopyrightText: 2026 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('linter')
|
||||
|
||||
test.lint()
|
||||
|
||||
test.passes()
|
||||
@@ -0,0 +1,36 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2026 Ethan Sifferman
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// Overriding a type parameter whose default is a parameterized class scope
|
||||
// still specializes the class, so its body must be elaborated (#8440).
|
||||
|
||||
package pkg;
|
||||
function automatic integer func();
|
||||
return 1;
|
||||
endfunction
|
||||
endpackage
|
||||
|
||||
class class_with_package_call #(
|
||||
parameter int unused_param = 0
|
||||
);
|
||||
typedef int value_t;
|
||||
localparam int local_param = pkg::func();
|
||||
endclass
|
||||
|
||||
module module_with_type_parameter #(
|
||||
parameter type value_t = class_with_package_call#(0)::value_t
|
||||
);
|
||||
endmodule
|
||||
|
||||
interface iface_with_type_parameter #(
|
||||
parameter type value_t = class_with_package_call#(1)::value_t
|
||||
) ();
|
||||
value_t value;
|
||||
endinterface
|
||||
|
||||
module top;
|
||||
module_with_type_parameter #(.value_t(logic signed [15:0])) dut ();
|
||||
iface_with_type_parameter #(.value_t(logic signed [15:0])) itf ();
|
||||
endmodule
|
||||
Reference in New Issue
Block a user