Fix parameter pollution when using class parameter
This commit is contained in:
parent
680ef8dda9
commit
1210fdbfff
|
|
@ -1348,6 +1348,17 @@ class ParamProcessor final {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// True if a $bits/$size type query in nodep's parameters reads another type parameter.
|
||||||
|
static bool defaultParamsHaveTypeQueryOnParamType(const AstClassRefDType* nodep) {
|
||||||
|
bool found = false;
|
||||||
|
nodep->foreach([&](const AstAttrOf* attrp) {
|
||||||
|
if (found || !attrp->attrType().isTypeQuery()) return;
|
||||||
|
const AstRefDType* const refp = VN_CAST(attrp->fromp(), RefDType);
|
||||||
|
if (refp && VN_IS(refp->refDTypep(), ParamTypeDType)) found = true;
|
||||||
|
});
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if exprp's class matches origp's class after deparameterization.
|
// Check if exprp's class matches origp's class after deparameterization.
|
||||||
// Handles both the simple case (user4p link from defaultsResolved) and the
|
// Handles both the simple case (user4p link from defaultsResolved) and the
|
||||||
// nested case where the default's inner class has non-default sub-parameters
|
// nested case where the default's inner class has non-default sub-parameters
|
||||||
|
|
@ -1362,6 +1373,9 @@ class ParamProcessor final {
|
||||||
const AstNodeModule* const defaultClonep
|
const AstNodeModule* const defaultClonep
|
||||||
= VN_CAST(origClassRefp->classp()->user4p(), Class);
|
= VN_CAST(origClassRefp->classp()->user4p(), Class);
|
||||||
if (defaultClonep && defaultClonep == exprClassRefp->classp()) return true;
|
if (defaultClonep && defaultClonep == exprClassRefp->classp()) return true;
|
||||||
|
// Skip the comparison when the default's $bits/$size reads another type parameter, as
|
||||||
|
// deparameterizing it below would resolve that shared type at the wrong width (#7711).
|
||||||
|
if (defaultParamsHaveTypeQueryOnParamType(origClassRefp)) return false;
|
||||||
// Slow path: deparameterize the default type and compare the result.
|
// Slow path: deparameterize the default type and compare the result.
|
||||||
// Different templates can never match; use origName() because exprp's
|
// Different templates can never match; use origName() because exprp's
|
||||||
// class may already be a specialization (clone) of the template.
|
// class may already be a specialization (clone) of the template.
|
||||||
|
|
|
||||||
|
|
@ -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,42 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// A class type parameter whose default reads $bits of a sibling type
|
||||||
|
// parameter must not freeze that sibling at its default width when other
|
||||||
|
// parameters of the interface are overridden (#7711).
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||||
|
// SPDX-FileCopyrightText: 2026 Wilson Snyder
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
class cls #(int width);
|
||||||
|
endclass
|
||||||
|
|
||||||
|
interface ifc
|
||||||
|
#(parameter int width = 8,
|
||||||
|
parameter type dtype = logic[width-1:0],
|
||||||
|
parameter type cparam = cls#($bits(dtype)));
|
||||||
|
dtype data;
|
||||||
|
endinterface
|
||||||
|
|
||||||
|
module t;
|
||||||
|
// width is overridden, dtype keeps its default logic[width-1:0], and the
|
||||||
|
// class type parameter is overridden. dtype must follow width (1 bit).
|
||||||
|
ifc #(.width(1), .cparam(cls#(1))) inst1();
|
||||||
|
// Same interface left at its default width (8 bits) must still work.
|
||||||
|
ifc inst8();
|
||||||
|
|
||||||
|
always_comb inst1.data = 1'b0;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
if ($bits(inst1.data) != 1) begin
|
||||||
|
$write("%%Error: $bits(inst1.data)=%0d exp=1\n", $bits(inst1.data));
|
||||||
|
$stop;
|
||||||
|
end
|
||||||
|
if ($bits(inst8.data) != 8) begin
|
||||||
|
$write("%%Error: $bits(inst8.data)=%0d exp=8\n", $bits(inst8.data));
|
||||||
|
$stop;
|
||||||
|
end
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue