This commit is contained in:
parent
ba3937734f
commit
121fd3f613
|
|
@ -1406,6 +1406,7 @@ class ParamProcessor final {
|
|||
AstConst* normedNamep = nullptr;
|
||||
if (exprp && !exprp->num().isDouble() && !exprp->num().isString()) {
|
||||
AstVar* cloneVarp = modvarp->cloneTree(false);
|
||||
bool cloneVarpUnresolved = false;
|
||||
if (AstNode* const oldValuep = cloneVarp->valuep()) {
|
||||
oldValuep->unlinkFrBack();
|
||||
VL_DO_DANGLING(oldValuep->deleteTree(), oldValuep);
|
||||
|
|
@ -1441,24 +1442,26 @@ class ParamProcessor final {
|
|||
any = true;
|
||||
}
|
||||
});
|
||||
// Substitute RefDType to an overridden paramtype. RefDType is
|
||||
// not a foreach leaf, so collect matches and replace after the
|
||||
// walk. Reverse order so descendants are replaced before
|
||||
// ancestors -- replacing an ancestor would free its descendants.
|
||||
// Replace RefDType to a ParamTypeDType with pin override
|
||||
// or the paramtype's default so constify below does not
|
||||
// reach into the template. Collect then replace in
|
||||
// reverse so descendants aren't freed early.
|
||||
std::vector<std::pair<AstRefDType*, AstNodeDType*>> toReplace;
|
||||
cloneVarp->foreach([&](AstRefDType* refp) {
|
||||
AstParamTypeDType* const ptdp
|
||||
= VN_CAST(refp->refDTypep(), ParamTypeDType);
|
||||
if (!ptdp) return;
|
||||
AstPin* overridePinp = nullptr;
|
||||
for (AstPin* pp = paramsp; pp; pp = VN_AS(pp->nextp(), Pin)) {
|
||||
if (pp->modPTypep() == ptdp) {
|
||||
if (AstNodeDType* const overDtp
|
||||
= VN_CAST(pp->exprp(), NodeDType)) {
|
||||
toReplace.emplace_back(refp, overDtp);
|
||||
}
|
||||
overridePinp = pp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
AstNodeDType* const substp
|
||||
= overridePinp ? VN_CAST(overridePinp->exprp(), NodeDType)
|
||||
: ptdp->subDTypep();
|
||||
if (substp) toReplace.emplace_back(refp, substp);
|
||||
});
|
||||
for (auto it = toReplace.rbegin(); it != toReplace.rend(); ++it) {
|
||||
AstRefDType* const refp = it->first;
|
||||
|
|
@ -1475,13 +1478,24 @@ class ParamProcessor final {
|
|||
<< varrefp->prettyName() << "' in pin dtype clone. Pin: "
|
||||
<< pinp->prettyNameQ() << " of " << nodep->prettyNameQ());
|
||||
});
|
||||
// Skip the widthing constify if any RefDType is unresolved.
|
||||
cloneVarp->foreach([&](AstRefDType* refp) {
|
||||
if (VN_IS(refp->refDTypep(), ParamTypeDType)) {
|
||||
UINFO(5, " cellPinCleanup: skip normedNamep "
|
||||
"(unresolved RefDType->ParamTypeDType) pin="
|
||||
<< pinp->prettyNameQ());
|
||||
cloneVarpUnresolved = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
V3Const::constifyParamsEdit(cloneVarp);
|
||||
if (AstConst* const widthedp = VN_CAST(cloneVarp->valuep(), Const)) {
|
||||
// Stamp the port's type on the const so equal values hash the same.
|
||||
if (cloneVarp->dtypep()) widthedp->dtypep(cloneVarp->dtypep());
|
||||
widthedp->unlinkFrBack();
|
||||
normedNamep = widthedp;
|
||||
if (!cloneVarpUnresolved) {
|
||||
V3Const::constifyParamsEdit(cloneVarp);
|
||||
if (AstConst* const widthedp = VN_CAST(cloneVarp->valuep(), Const)) {
|
||||
// Stamp the port's type so equal values hash the same.
|
||||
if (cloneVarp->dtypep()) widthedp->dtypep(cloneVarp->dtypep());
|
||||
widthedp->unlinkFrBack();
|
||||
normedNamep = widthedp;
|
||||
}
|
||||
}
|
||||
VL_DO_DANGLING(cloneVarp->deleteTree(), cloneVarp);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,77 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Wilson Snyder
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// Chained paramtypes: type B = A where A = logic[W-1:0]. The iterative
|
||||
// RefDType substitution in cellPinCleanup must unwind the chain over
|
||||
// multiple passes: B -> REFDTYPE(A) -> A's body -> VARREF(W) -> override.
|
||||
// Each instance overrides .val (paramtype-typed, spec-matched width) so
|
||||
// cellPinCleanup processes a RefDType pin that must be resolved per-spec.
|
||||
// Pre-fix, pin values are checked against the template's B (8 bits),
|
||||
// producing WIDTHTRUNC warnings on i16/i32. Post-fix, they check
|
||||
// against each spec's resolved B and pass cleanly.
|
||||
|
||||
module m #(
|
||||
parameter int W = 8,
|
||||
parameter type A = logic [W-1:0],
|
||||
parameter type B = A,
|
||||
parameter B val = '0
|
||||
) ();
|
||||
A a_sig;
|
||||
B b_sig;
|
||||
initial a_sig = '1;
|
||||
initial b_sig = '1;
|
||||
endmodule
|
||||
|
||||
module t;
|
||||
m #(.W(8), .val(8'hA5)) i8 ();
|
||||
m #(.W(16), .val(16'hBEEF)) i16 ();
|
||||
m #(.W(32), .val(32'hDEADBEEF)) i32 ();
|
||||
|
||||
initial begin
|
||||
#1;
|
||||
if ($bits(i8.val) !== 8) begin
|
||||
$write("%%Error $bits(i8.val)=%0d\n", $bits(i8.val)); $stop;
|
||||
end
|
||||
if ($bits(i8.a_sig) !== 8) begin
|
||||
$write("%%Error $bits(i8.a_sig)=%0d\n", $bits(i8.a_sig)); $stop;
|
||||
end
|
||||
if ($bits(i8.b_sig) !== 8) begin
|
||||
$write("%%Error $bits(i8.b_sig)=%0d\n", $bits(i8.b_sig)); $stop;
|
||||
end
|
||||
if (i8.val !== 8'hA5) begin $write("%%Error i8.val=%h\n", i8.val); $stop; end
|
||||
if (i8.a_sig !== 8'hFF) begin $write("%%Error i8.a_sig=%h\n", i8.a_sig); $stop; end
|
||||
if (i8.b_sig !== 8'hFF) begin $write("%%Error i8.b_sig=%h\n", i8.b_sig); $stop; end
|
||||
|
||||
if ($bits(i16.val) !== 16) begin
|
||||
$write("%%Error $bits(i16.val)=%0d\n", $bits(i16.val)); $stop;
|
||||
end
|
||||
if ($bits(i16.a_sig) !== 16) begin
|
||||
$write("%%Error $bits(i16.a_sig)=%0d\n", $bits(i16.a_sig)); $stop;
|
||||
end
|
||||
if ($bits(i16.b_sig) !== 16) begin
|
||||
$write("%%Error $bits(i16.b_sig)=%0d\n", $bits(i16.b_sig)); $stop;
|
||||
end
|
||||
if (i16.val !== 16'hBEEF) begin $write("%%Error i16.val=%h\n", i16.val); $stop; end
|
||||
if (i16.a_sig !== 16'hFFFF) begin $write("%%Error i16.a_sig=%h\n", i16.a_sig); $stop; end
|
||||
if (i16.b_sig !== 16'hFFFF) begin $write("%%Error i16.b_sig=%h\n", i16.b_sig); $stop; end
|
||||
|
||||
if ($bits(i32.val) !== 32) begin
|
||||
$write("%%Error $bits(i32.val)=%0d\n", $bits(i32.val)); $stop;
|
||||
end
|
||||
if ($bits(i32.a_sig) !== 32) begin
|
||||
$write("%%Error $bits(i32.a_sig)=%0d\n", $bits(i32.a_sig)); $stop;
|
||||
end
|
||||
if ($bits(i32.b_sig) !== 32) begin
|
||||
$write("%%Error $bits(i32.b_sig)=%0d\n", $bits(i32.b_sig)); $stop;
|
||||
end
|
||||
if (i32.val !== 32'hDEADBEEF) begin $write("%%Error i32.val=%h\n", i32.val); $stop; end
|
||||
if (i32.a_sig !== 32'hFFFFFFFF) begin $write("%%Error i32.a_sig=%h\n", i32.a_sig); $stop; end
|
||||
if (i32.b_sig !== 32'hFFFFFFFF) begin $write("%%Error i32.b_sig=%h\n", i32.b_sig); $stop; end
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -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,47 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Wilson Snyder
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// Interleaved specs (A B A C B A). Any cross-instance leakage from
|
||||
// template poisoning causes a later instance of a repeated tuple to
|
||||
// mismatch its expected value.
|
||||
|
||||
module m #(
|
||||
parameter int W = 8,
|
||||
parameter type T = logic [W-1:0],
|
||||
parameter T VAL = '0
|
||||
) ();
|
||||
logic [W-1:0] observed;
|
||||
assign observed = VAL;
|
||||
endmodule
|
||||
|
||||
module t;
|
||||
m #(.W(8), .VAL(8'h11)) ia1 (); // A
|
||||
m #(.W(16), .VAL(16'h2222)) ib1 (); // B
|
||||
m #(.W(8), .VAL(8'h11)) ia2 (); // A
|
||||
m #(.W(32), .VAL(32'h33333333)) ic1 (); // C
|
||||
m #(.W(16), .VAL(16'h2222)) ib2 (); // B
|
||||
m #(.W(8), .VAL(8'h11)) ia3 (); // A
|
||||
|
||||
initial begin
|
||||
#1;
|
||||
if ($bits(ia1.observed) !== 8) begin $write("%%Error ia1 bits\n"); $stop; end
|
||||
if ($bits(ib1.observed) !== 16) begin $write("%%Error ib1 bits\n"); $stop; end
|
||||
if ($bits(ia2.observed) !== 8) begin $write("%%Error ia2 bits\n"); $stop; end
|
||||
if ($bits(ic1.observed) !== 32) begin $write("%%Error ic1 bits\n"); $stop; end
|
||||
if ($bits(ib2.observed) !== 16) begin $write("%%Error ib2 bits\n"); $stop; end
|
||||
if ($bits(ia3.observed) !== 8) begin $write("%%Error ia3 bits\n"); $stop; end
|
||||
|
||||
if (ia1.observed !== 8'h11) begin $write("%%Error ia1=%h\n", ia1.observed); $stop; end
|
||||
if (ib1.observed !== 16'h2222) begin $write("%%Error ib1=%h\n", ib1.observed); $stop; end
|
||||
if (ia2.observed !== 8'h11) begin $write("%%Error ia2=%h\n", ia2.observed); $stop; end
|
||||
if (ic1.observed !== 32'h33333333) begin $write("%%Error ic1=%h\n", ic1.observed); $stop; end
|
||||
if (ib2.observed !== 16'h2222) begin $write("%%Error ib2=%h\n", ib2.observed); $stop; end
|
||||
if (ia3.observed !== 8'h11) begin $write("%%Error ia3=%h\n", ia3.observed); $stop; end
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -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,61 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Wilson Snyder
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// Deep value-param chain under a type param. Each intermediate must
|
||||
// recompute per spec; template poisoning at any level fails a specific
|
||||
// assertion pointing at the leaking level. Each instance overrides
|
||||
// .val (paramtype-typed) with a spec-matched width so cellPinCleanup
|
||||
// processes a RefDType pin and the full W1->W2->W3->W4 chain must
|
||||
// unwind.
|
||||
|
||||
module m #(
|
||||
parameter int W1 = 4,
|
||||
parameter int W2 = W1 + 4,
|
||||
parameter int W3 = W2 * 2,
|
||||
parameter int W4 = W3 + 1,
|
||||
parameter type T = logic [W4-1:0],
|
||||
parameter T val = '0
|
||||
) ();
|
||||
endmodule
|
||||
|
||||
module t;
|
||||
m #(.W1(8), .val(25'h1234567)) iw8 (); // W4 = 25
|
||||
m iwd (); // default W4 = 17
|
||||
m #(.W1(16), .val(41'h123456789AB)) iw16 (); // W4 = 41
|
||||
|
||||
initial begin
|
||||
if (iw8.W1 !== 8) begin $write("%%Error iw8.W1=%0d\n", iw8.W1); $stop; end
|
||||
if (iw8.W2 !== 12) begin $write("%%Error iw8.W2=%0d\n", iw8.W2); $stop; end
|
||||
if (iw8.W3 !== 24) begin $write("%%Error iw8.W3=%0d\n", iw8.W3); $stop; end
|
||||
if (iw8.W4 !== 25) begin $write("%%Error iw8.W4=%0d\n", iw8.W4); $stop; end
|
||||
if ($bits(iw8.val) !== 25) begin
|
||||
$write("%%Error $bits(iw8.val)=%0d\n", $bits(iw8.val)); $stop;
|
||||
end
|
||||
if (iw8.val !== 25'h1234567) begin $write("%%Error iw8.val=%h\n", iw8.val); $stop; end
|
||||
|
||||
if (iwd.W1 !== 4) begin $write("%%Error iwd.W1=%0d\n", iwd.W1); $stop; end
|
||||
if (iwd.W2 !== 8) begin $write("%%Error iwd.W2=%0d\n", iwd.W2); $stop; end
|
||||
if (iwd.W3 !== 16) begin $write("%%Error iwd.W3=%0d\n", iwd.W3); $stop; end
|
||||
if (iwd.W4 !== 17) begin $write("%%Error iwd.W4=%0d\n", iwd.W4); $stop; end
|
||||
if ($bits(iwd.val) !== 17) begin
|
||||
$write("%%Error $bits(iwd.val)=%0d\n", $bits(iwd.val)); $stop;
|
||||
end
|
||||
|
||||
if (iw16.W1 !== 16) begin $write("%%Error iw16.W1=%0d\n", iw16.W1); $stop; end
|
||||
if (iw16.W2 !== 20) begin $write("%%Error iw16.W2=%0d\n", iw16.W2); $stop; end
|
||||
if (iw16.W3 !== 40) begin $write("%%Error iw16.W3=%0d\n", iw16.W3); $stop; end
|
||||
if (iw16.W4 !== 41) begin $write("%%Error iw16.W4=%0d\n", iw16.W4); $stop; end
|
||||
if ($bits(iw16.val) !== 41) begin
|
||||
$write("%%Error $bits(iw16.val)=%0d\n", $bits(iw16.val)); $stop;
|
||||
end
|
||||
if (iw16.val !== 41'h123456789AB) begin
|
||||
$write("%%Error iw16.val=%h\n", iw16.val); $stop;
|
||||
end
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -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,65 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Wilson Snyder
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// Hash-normalization: the port type must resolve per-specialization, not
|
||||
// from the template default. Two pin values differing only in bits above
|
||||
// the template-default width must still produce distinct specs when the
|
||||
// actual spec's width is wider. Pin values equal after widthing must
|
||||
// share a spec (#5479 dedup preserved).
|
||||
|
||||
module test #(
|
||||
parameter int width = 16,
|
||||
parameter int width2 = width + 8,
|
||||
parameter type data_t = logic [width2-1:0],
|
||||
parameter data_t data = data_t'(0)
|
||||
) ();
|
||||
endmodule
|
||||
|
||||
module t;
|
||||
// width=24 -> width2=32 -> data_t is 32 bits
|
||||
test #(.width(24), .data(32'hFFFFFFFF)) i_aa ();
|
||||
test #(.width(24), .data(32'h11FFFFFF)) i_ab ();
|
||||
test #(.width(24), .data(32'h11FFFFFF)) i_ac ();
|
||||
// width=16 -> width2=24 -> data_t is 24 bits
|
||||
test #(.width(16), .data(24'hFFFFFF)) i_bb ();
|
||||
|
||||
initial begin
|
||||
if ($bits(i_aa.data) !== 32) begin
|
||||
$write("%%Error $bits(i_aa.data)=%0d expected 32\n", $bits(i_aa.data)); $stop;
|
||||
end
|
||||
if ($bits(i_ab.data) !== 32) begin
|
||||
$write("%%Error $bits(i_ab.data)=%0d expected 32\n", $bits(i_ab.data)); $stop;
|
||||
end
|
||||
if ($bits(i_ac.data) !== 32) begin
|
||||
$write("%%Error $bits(i_ac.data)=%0d expected 32\n", $bits(i_ac.data)); $stop;
|
||||
end
|
||||
if ($bits(i_bb.data) !== 24) begin
|
||||
$write("%%Error $bits(i_bb.data)=%0d expected 24\n", $bits(i_bb.data)); $stop;
|
||||
end
|
||||
if (i_aa.data !== 32'hFFFFFFFF) begin
|
||||
$write("%%Error i_aa.data=%h\n", i_aa.data); $stop;
|
||||
end
|
||||
if (i_ab.data !== 32'h11FFFFFF) begin
|
||||
$write("%%Error i_ab.data=%h\n", i_ab.data); $stop;
|
||||
end
|
||||
if (i_ac.data !== 32'h11FFFFFF) begin
|
||||
$write("%%Error i_ac.data=%h\n", i_ac.data); $stop;
|
||||
end
|
||||
if (i_bb.data !== 24'hFFFFFF) begin
|
||||
$write("%%Error i_bb.data=%h\n", i_bb.data); $stop;
|
||||
end
|
||||
// Distinct full-32b values must NOT share a spec (values differ).
|
||||
if (i_aa.data === i_ab.data) begin
|
||||
$write("%%Error i_aa.data and i_ab.data must differ\n"); $stop;
|
||||
end
|
||||
// Equal pin values share a spec (#5479 dedup).
|
||||
if (i_ab.data !== i_ac.data) begin
|
||||
$write("%%Error i_ab.data and i_ac.data must match\n"); $stop;
|
||||
end
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -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,62 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Wilson Snyder
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// Ariane-shaped 3-level hierarchy with parameter forwarding. Each
|
||||
// mid instance forwards its paramtype to its leaf. Three distinct
|
||||
// width/value tuples catch cross-hierarchy template leakage.
|
||||
|
||||
module leaf #(
|
||||
parameter int W = 4,
|
||||
parameter type T = logic [W-1:0],
|
||||
parameter T VAL = '0
|
||||
) ();
|
||||
logic [W-1:0] observed;
|
||||
assign observed = VAL;
|
||||
endmodule
|
||||
|
||||
module mid #(
|
||||
parameter int W = 4,
|
||||
parameter type T = logic [W-1:0],
|
||||
parameter T VAL = '0
|
||||
) ();
|
||||
leaf #(.W(W), .T(T), .VAL(VAL)) l ();
|
||||
endmodule
|
||||
|
||||
module t;
|
||||
mid #(.W(8), .VAL(8'hA5)) m_a ();
|
||||
mid #(.W(16), .VAL(16'hBEEF)) m_b ();
|
||||
mid #(.W(32), .VAL(32'hDEADBEEF)) m_c ();
|
||||
|
||||
initial begin
|
||||
#1;
|
||||
if (m_a.l.W !== 8) begin $write("%%Error m_a.l.W=%0d\n", m_a.l.W); $stop; end
|
||||
if ($bits(m_a.l.observed) !== 8) begin
|
||||
$write("%%Error $bits(m_a.l.observed)=%0d\n", $bits(m_a.l.observed)); $stop;
|
||||
end
|
||||
if (m_a.l.observed !== 8'hA5) begin
|
||||
$write("%%Error m_a.l.observed=%h\n", m_a.l.observed); $stop;
|
||||
end
|
||||
|
||||
if (m_b.l.W !== 16) begin $write("%%Error m_b.l.W=%0d\n", m_b.l.W); $stop; end
|
||||
if ($bits(m_b.l.observed) !== 16) begin
|
||||
$write("%%Error $bits(m_b.l.observed)=%0d\n", $bits(m_b.l.observed)); $stop;
|
||||
end
|
||||
if (m_b.l.observed !== 16'hBEEF) begin
|
||||
$write("%%Error m_b.l.observed=%h\n", m_b.l.observed); $stop;
|
||||
end
|
||||
|
||||
if (m_c.l.W !== 32) begin $write("%%Error m_c.l.W=%0d\n", m_c.l.W); $stop; end
|
||||
if ($bits(m_c.l.observed) !== 32) begin
|
||||
$write("%%Error $bits(m_c.l.observed)=%0d\n", $bits(m_c.l.observed)); $stop;
|
||||
end
|
||||
if (m_c.l.observed !== 32'hDEADBEEF) begin
|
||||
$write("%%Error m_c.l.observed=%h\n", m_c.l.observed); $stop;
|
||||
end
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -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,96 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Wilson Snyder
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// Dependent value-param + type-param + value-param-of-type-param must be
|
||||
// re-evaluated per specialization, not baked from the template default.
|
||||
// Regression test for template poisoning in V3Param::cellPinCleanup: the
|
||||
// normedNamep widthing block used to reach through a RefDType into the
|
||||
// template's ParamTypeDType and constify its body, mutating the base
|
||||
// module's dependent-param valuep so later specializations inherited the
|
||||
// stale constant. Three instances with distinct .width values in the
|
||||
// same compilation catch any such cross-instance leakage.
|
||||
|
||||
module test #(
|
||||
parameter int width = 16,
|
||||
parameter int width2 = width + 8,
|
||||
parameter type data_t = logic [width2-1:0],
|
||||
parameter data_t data = data_t'(0)
|
||||
) ();
|
||||
// Internal signal declared as the dependent type param, driven to
|
||||
// all-ones. Post-fix, $bits and value readback must match the
|
||||
// spec's own resolved width, not the template default.
|
||||
data_t data_t_sig;
|
||||
initial data_t_sig = '1;
|
||||
endmodule
|
||||
|
||||
module t;
|
||||
test #(.width(24), .data(32'h0)) inst_a ();
|
||||
test #(.width(16), .data(24'h0)) inst_b ();
|
||||
test #(.width( 8), .data(16'h0)) inst_c ();
|
||||
|
||||
initial begin
|
||||
#1;
|
||||
// inst_a: width=24 -> width2=32 -> data_t is 32 bits
|
||||
if (inst_a.width2 !== 32) begin
|
||||
$write("%%Error inst_a.width2=%0d expected 32\n", inst_a.width2); $stop;
|
||||
end
|
||||
if ($bits(inst_a.data) !== 32) begin
|
||||
$write("%%Error $bits(inst_a.data)=%0d expected 32\n", $bits(inst_a.data)); $stop;
|
||||
end
|
||||
if (inst_a.data !== 32'h0) begin
|
||||
$write("%%Error inst_a.data=%h expected 0\n", inst_a.data); $stop;
|
||||
end
|
||||
if ($bits(inst_a.data_t_sig) !== 32) begin
|
||||
$write("%%Error $bits(inst_a.data_t_sig)=%0d expected 32\n",
|
||||
$bits(inst_a.data_t_sig)); $stop;
|
||||
end
|
||||
if (inst_a.data_t_sig !== 32'hFFFFFFFF) begin
|
||||
$write("%%Error inst_a.data_t_sig=%h expected FFFFFFFF\n",
|
||||
inst_a.data_t_sig); $stop;
|
||||
end
|
||||
|
||||
// inst_b: width=16 -> width2=24 -> data_t is 24 bits
|
||||
if (inst_b.width2 !== 24) begin
|
||||
$write("%%Error inst_b.width2=%0d expected 24\n", inst_b.width2); $stop;
|
||||
end
|
||||
if ($bits(inst_b.data) !== 24) begin
|
||||
$write("%%Error $bits(inst_b.data)=%0d expected 24\n", $bits(inst_b.data)); $stop;
|
||||
end
|
||||
if (inst_b.data !== 24'h0) begin
|
||||
$write("%%Error inst_b.data=%h expected 0\n", inst_b.data); $stop;
|
||||
end
|
||||
if ($bits(inst_b.data_t_sig) !== 24) begin
|
||||
$write("%%Error $bits(inst_b.data_t_sig)=%0d expected 24\n",
|
||||
$bits(inst_b.data_t_sig)); $stop;
|
||||
end
|
||||
if (inst_b.data_t_sig !== 24'hFFFFFF) begin
|
||||
$write("%%Error inst_b.data_t_sig=%h expected FFFFFF\n",
|
||||
inst_b.data_t_sig); $stop;
|
||||
end
|
||||
|
||||
// inst_c: width=8 -> width2=16 -> data_t is 16 bits
|
||||
if (inst_c.width2 !== 16) begin
|
||||
$write("%%Error inst_c.width2=%0d expected 16\n", inst_c.width2); $stop;
|
||||
end
|
||||
if ($bits(inst_c.data) !== 16) begin
|
||||
$write("%%Error $bits(inst_c.data)=%0d expected 16\n", $bits(inst_c.data)); $stop;
|
||||
end
|
||||
if (inst_c.data !== 16'h0) begin
|
||||
$write("%%Error inst_c.data=%h expected 0\n", inst_c.data); $stop;
|
||||
end
|
||||
if ($bits(inst_c.data_t_sig) !== 16) begin
|
||||
$write("%%Error $bits(inst_c.data_t_sig)=%0d expected 16\n",
|
||||
$bits(inst_c.data_t_sig)); $stop;
|
||||
end
|
||||
if (inst_c.data_t_sig !== 16'hFFFF) begin
|
||||
$write("%%Error inst_c.data_t_sig=%h expected FFFF\n",
|
||||
inst_c.data_t_sig); $stop;
|
||||
end
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -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,59 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Wilson Snyder
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// Packed struct type param with dependent field widths. $bits and
|
||||
// field access on a typed-by-paramtype variable must see the correct
|
||||
// per-spec field widths. Also exercises the #7445 CVA6 pattern
|
||||
// (struct member access on a VARREF of a parameterized type).
|
||||
|
||||
module m #(
|
||||
parameter int W = 8,
|
||||
parameter type T = struct packed {
|
||||
logic [W-1:0] a;
|
||||
logic [W-1:0] b;
|
||||
}
|
||||
) ();
|
||||
T t_sig;
|
||||
logic [W-1:0] a_sig;
|
||||
initial t_sig = '1;
|
||||
initial a_sig = t_sig.a;
|
||||
endmodule
|
||||
|
||||
module t;
|
||||
m #(.W(4)) i4 ();
|
||||
m #(.W(8)) i8 ();
|
||||
m #(.W(16)) i16 ();
|
||||
|
||||
initial begin
|
||||
#1;
|
||||
if ($bits(i4.t_sig) !== 8) begin $write("%%Error i4.t_sig bits\n"); $stop; end
|
||||
if ($bits(i4.t_sig.a) !== 4) begin $write("%%Error i4.t_sig.a bits\n"); $stop; end
|
||||
if ($bits(i4.t_sig.b) !== 4) begin $write("%%Error i4.t_sig.b bits\n"); $stop; end
|
||||
if ($bits(i4.a_sig) !== 4) begin $write("%%Error i4.a_sig bits\n"); $stop; end
|
||||
if (i4.t_sig.a !== 4'hF) begin $write("%%Error i4.t_sig.a=%h\n", i4.t_sig.a); $stop; end
|
||||
if (i4.t_sig.b !== 4'hF) begin $write("%%Error i4.t_sig.b=%h\n", i4.t_sig.b); $stop; end
|
||||
if (i4.a_sig !== 4'hF) begin $write("%%Error i4.a_sig=%h\n", i4.a_sig); $stop; end
|
||||
|
||||
if ($bits(i8.t_sig) !== 16) begin $write("%%Error i8.t_sig bits\n"); $stop; end
|
||||
if ($bits(i8.t_sig.a) !== 8) begin $write("%%Error i8.t_sig.a bits\n"); $stop; end
|
||||
if ($bits(i8.t_sig.b) !== 8) begin $write("%%Error i8.t_sig.b bits\n"); $stop; end
|
||||
if ($bits(i8.a_sig) !== 8) begin $write("%%Error i8.a_sig bits\n"); $stop; end
|
||||
if (i8.t_sig.a !== 8'hFF) begin $write("%%Error i8.t_sig.a=%h\n", i8.t_sig.a); $stop; end
|
||||
if (i8.t_sig.b !== 8'hFF) begin $write("%%Error i8.t_sig.b=%h\n", i8.t_sig.b); $stop; end
|
||||
if (i8.a_sig !== 8'hFF) begin $write("%%Error i8.a_sig=%h\n", i8.a_sig); $stop; end
|
||||
|
||||
if ($bits(i16.t_sig) !== 32) begin $write("%%Error i16.t_sig bits\n"); $stop; end
|
||||
if ($bits(i16.t_sig.a) !== 16) begin $write("%%Error i16.t_sig.a bits\n"); $stop; end
|
||||
if ($bits(i16.t_sig.b) !== 16) begin $write("%%Error i16.t_sig.b bits\n"); $stop; end
|
||||
if ($bits(i16.a_sig) !== 16) begin $write("%%Error i16.a_sig bits\n"); $stop; end
|
||||
if (i16.t_sig.a !== 16'hFFFF) begin $write("%%Error i16.t_sig.a=%h\n", i16.t_sig.a); $stop; end
|
||||
if (i16.t_sig.b !== 16'hFFFF) begin $write("%%Error i16.t_sig.b=%h\n", i16.t_sig.b); $stop; end
|
||||
if (i16.a_sig !== 16'hFFFF) begin $write("%%Error i16.a_sig=%h\n", i16.a_sig); $stop; end
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
Loading…
Reference in New Issue