better comparing an explicit type parameter against its default
This commit is contained in:
parent
dfb7b034a5
commit
f303f05dd5
|
|
@ -1235,30 +1235,31 @@ class ParamProcessor final {
|
|||
}
|
||||
}
|
||||
|
||||
// Check if exprp is a ClassRefDType whose class is the default-parameter clone
|
||||
// of origp's template class. This catches the case where an explicit type parameter
|
||||
// like Holder#(W#(int)) resolves to the same specialization as the implicit default
|
||||
// Holder#(), because W#(int) deparameterizes to W_ (the all-default clone of W).
|
||||
// Uses the user4p link set at line ~1658 when defaultsResolved is true.
|
||||
static bool classTypeMatchesDefaultClone(const AstNodeDType* exprp,
|
||||
const AstNodeDType* origp) {
|
||||
// Check if exprp's class matches origp's class after deparameterization.
|
||||
// Handles both the simple case (user4p link from defaultsResolved) and the
|
||||
// nested case where the default's inner class has non-default sub-parameters
|
||||
// (e.g., uvm_sequence#(uvm_reg_item) where uvm_reg_item != default uvm_sequence_item).
|
||||
bool classTypeMatchesDefaultClone(const AstNodeDType* exprp, const AstNodeDType* origp) {
|
||||
exprp = exprp->skipRefp();
|
||||
origp = origp->skipRefp();
|
||||
const auto* const exprClassRefp = VN_CAST(exprp, ClassRefDType);
|
||||
const auto* const origClassRefp = VN_CAST(origp, ClassRefDType);
|
||||
UINFO(9, "classTypeMatchesDefaultClone: exprClassRef="
|
||||
<< exprClassRefp << " origClassRef=" << origClassRefp);
|
||||
if (!exprClassRefp || !origClassRefp) return false;
|
||||
// Fast path: check user4p link (set when template was deparameterized with defaults)
|
||||
const AstNodeModule* const defaultClonep
|
||||
= VN_CAST(origClassRefp->classp()->user4p(), Class);
|
||||
const bool result = defaultClonep && defaultClonep == exprClassRefp->classp();
|
||||
UINFO(9, " origClass=" << origClassRefp->classp()->prettyNameQ()
|
||||
<< " origClassp=" << cvtToHex(origClassRefp->classp())
|
||||
<< " user4p=" << (defaultClonep ? cvtToHex(defaultClonep) : "null")
|
||||
<< " exprClass=" << exprClassRefp->classp()->prettyNameQ()
|
||||
<< " exprClassp=" << cvtToHex(exprClassRefp->classp())
|
||||
<< " result=" << result);
|
||||
return result;
|
||||
if (defaultClonep && defaultClonep == exprClassRefp->classp()) return true;
|
||||
// Slow path: deparameterize the default type and compare the result.
|
||||
if (!origClassRefp->classp()->hasGParam()) return false;
|
||||
// const_cast safe: cloneTree doesn't modify the source
|
||||
AstClassRefDType* const origClonep = static_cast<AstClassRefDType*>(
|
||||
const_cast<AstClassRefDType*>(origClassRefp)->cloneTree(false));
|
||||
AstNodeModule* const resolvedModp
|
||||
= classRefDeparam(origClonep, origClassRefp->classp());
|
||||
const bool match
|
||||
= resolvedModp && VN_CAST(resolvedModp, Class) == exprClassRefp->classp();
|
||||
VL_DO_DANGLING(origClonep->deleteTree(), origClonep);
|
||||
return match;
|
||||
}
|
||||
|
||||
static bool paramConstsEqualAtMaxWidth(AstConst* exprp, AstConst* origp) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
#!/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('simulator')
|
||||
|
||||
test.compile(verilator_flags2=["--binary"])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
// DESCRIPTION: Verilator: Verify that nested class type parameters with
|
||||
// explicit-equivalent defaults resolve to the same specialization.
|
||||
//
|
||||
// When uvm_reg_sequence#(type BASE = uvm_sequence#(uvm_reg_item)) is
|
||||
// extended with the explicit equivalent default, both must produce the
|
||||
// same specialization so that $cast succeeds between them.
|
||||
//
|
||||
// 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
|
||||
|
||||
virtual class uvm_object;
|
||||
endclass
|
||||
|
||||
class uvm_factory;
|
||||
uvm_object m_type_names[string];
|
||||
|
||||
function uvm_object create_object_by_name(string name);
|
||||
uvm_object wrapper;
|
||||
if (m_type_names.exists(name)) begin
|
||||
wrapper = m_type_names[name];
|
||||
end
|
||||
else begin
|
||||
$display("%%Error: object not found '%s'", name);
|
||||
$stop;
|
||||
end
|
||||
return wrapper;
|
||||
endfunction
|
||||
|
||||
function void register(uvm_object obj, string name);
|
||||
m_type_names[name] = obj;
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
uvm_factory factory;
|
||||
|
||||
class uvm_sequence_item extends uvm_object;
|
||||
endclass
|
||||
|
||||
class uvm_reg_item extends uvm_sequence_item;
|
||||
endclass
|
||||
|
||||
virtual class uvm_sequence #(
|
||||
type REQ = uvm_sequence_item,
|
||||
type RSP = REQ
|
||||
) extends uvm_object;
|
||||
endclass
|
||||
|
||||
class uvm_reg_sequence #(
|
||||
type BASE = uvm_sequence#(uvm_reg_item)
|
||||
) extends BASE;
|
||||
function new;
|
||||
factory.register(this, "uvm_reg_sequence");
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
class uvm_reg_hw_reset_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));
|
||||
function new;
|
||||
factory.register(this, "uvm_reg_hw_reset_seq");
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
module t;
|
||||
initial begin
|
||||
uvm_reg_hw_reset_seq rsq;
|
||||
|
||||
uvm_reg_sequence seq;
|
||||
uvm_object obj;
|
||||
int cst;
|
||||
string seq_name;
|
||||
|
||||
factory = new;
|
||||
rsq = new;
|
||||
|
||||
seq_name = "uvm_reg_hw_reset_seq";
|
||||
|
||||
obj = factory.create_object_by_name(seq_name);
|
||||
if (obj == null) $stop;
|
||||
|
||||
cst = $cast(seq, obj);
|
||||
/* verilator lint_off WIDTHTRUNC */
|
||||
if (!cst || seq == null) begin
|
||||
$display("%%Error: cast failed");
|
||||
$stop;
|
||||
end
|
||||
/* verilator lint_on WIDTHTRUNC */
|
||||
if (seq != rsq) $stop;
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
Loading…
Reference in New Issue