This commit is contained in:
parent
9a5c1d27c8
commit
c34cd6ddf1
|
|
@ -2293,20 +2293,21 @@ class ParamVisitor final : public VNVisitor {
|
|||
nodep->v3error("Parameter without default value is never given value"
|
||||
<< " (IEEE 1800-2023 6.20.1): " << nodep->prettyNameQ());
|
||||
} else if (nodep->valuep()) {
|
||||
// In visit(AstVar*) for localparams, check if expression contains VARXREF
|
||||
// to another localparam (not parameter). Parameters are already const,
|
||||
// but localparams may not be evaluated yet.
|
||||
bool hasVarXRefToLparam = false;
|
||||
// If the value expression contains a VarXRef to an interface
|
||||
// localparam whose value is not yet constant, defer constification
|
||||
// to avoid premature widthing with unresolved values (see
|
||||
// t_lparam_dep_iface tests). When the referenced localparam is
|
||||
// already const, proceed normally so FUNCREFs with resolved iface
|
||||
// param args get folded.
|
||||
bool hasUnresolvedLparamXRef = false;
|
||||
nodep->valuep()->foreach([&](const AstVarXRef* xrefp) {
|
||||
if (xrefp->varp() && xrefp->varp()->varType() == VVarType::LPARAM) {
|
||||
hasVarXRefToLparam = true;
|
||||
if (const AstVar* const varp = xrefp->varp()) {
|
||||
if (varp->varType() == VVarType::LPARAM && !VN_IS(varp->valuep(), Const)) {
|
||||
hasUnresolvedLparamXRef = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (hasVarXRefToLparam) {
|
||||
// Don't constify - let it be evaluated later
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasUnresolvedLparamXRef) return;
|
||||
V3Const::constifyParamsEdit(nodep);
|
||||
}
|
||||
}
|
||||
|
|
@ -2328,6 +2329,13 @@ class ParamVisitor final : public VNVisitor {
|
|||
if (nodep->name() == candp->name()) {
|
||||
if (AstVar* const varp = VN_CAST(candp, Var)) {
|
||||
UINFO(9, "Found interface parameter: " << varp);
|
||||
// The interface may not have been visited yet (it is at a
|
||||
// deeper level in the work queue), so its localparams may
|
||||
// not be constified. Eagerly constify here so that the
|
||||
// caller's hasUnresolvedLparamXRef check sees a Const.
|
||||
if (varp->isParam() && varp->valuep() && !VN_IS(varp->valuep(), Const)) {
|
||||
V3Const::constifyParamsEdit(varp);
|
||||
}
|
||||
nodep->varp(varp);
|
||||
return true;
|
||||
} else if (const AstPin* const pinp = VN_CAST(candp, Pin)) {
|
||||
|
|
|
|||
|
|
@ -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,37 @@
|
|||
// DESCRIPTION: Verilator: Localparam with package function call using interface param
|
||||
//
|
||||
// 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
|
||||
|
||||
// verilog_format: off
|
||||
`define stop $stop
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d (%s !== %s)\n", `__FILE__,`__LINE__, (gotv), (expv), `"gotv`", `"expv`"); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
package pkg;
|
||||
function automatic bit fn(int value);
|
||||
return (value > 0) ? 1'b1 : 1'b0;
|
||||
endfunction
|
||||
endpackage
|
||||
|
||||
interface ifc();
|
||||
localparam int PARAM = 1;
|
||||
endinterface
|
||||
|
||||
module mod(ifc i);
|
||||
localparam bit lpbit = pkg::fn(i.PARAM);
|
||||
endmodule
|
||||
|
||||
module t;
|
||||
ifc i();
|
||||
mod m(.i);
|
||||
|
||||
initial begin
|
||||
`checkd(m.lpbit, 1'b1);
|
||||
$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,42 @@
|
|||
// DESCRIPTION: Verilator: Localparam with package function call using computed interface param
|
||||
//
|
||||
// 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
|
||||
|
||||
// verilog_format: off
|
||||
`define stop $stop
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d (%s !== %s)\n", `__FILE__,`__LINE__, (gotv), (expv), `"gotv`", `"expv`"); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
package pkg;
|
||||
function automatic bit fn(int value);
|
||||
return (value > 0) ? 1'b1 : 1'b0;
|
||||
endfunction
|
||||
endpackage
|
||||
|
||||
interface ifc #(parameter int WIDTH = 8);
|
||||
localparam int DEPTH = $clog2(WIDTH);
|
||||
localparam int COMPUTED = DEPTH * 2;
|
||||
endinterface
|
||||
|
||||
module mod(ifc i);
|
||||
// LPARAM references i.COMPUTED which depends on i.DEPTH which depends on WIDTH
|
||||
localparam bit lpbit = pkg::fn(i.COMPUTED);
|
||||
localparam int lpval = i.COMPUTED + 1;
|
||||
endmodule
|
||||
|
||||
module t;
|
||||
ifc #(.WIDTH(64)) i();
|
||||
mod m(.i);
|
||||
|
||||
initial begin
|
||||
// DEPTH = $clog2(64) = 6, COMPUTED = 6*2 = 12
|
||||
`checkd(m.lpbit, 1'b1); // fn(12) returns 1 since 12 > 0
|
||||
`checkd(m.lpval, 13); // lpval = 12 + 1 = 13
|
||||
$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,45 @@
|
|||
// DESCRIPTION: Verilator: Localparam with function call using type-parameterized interface param
|
||||
//
|
||||
// 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
|
||||
|
||||
// verilog_format: off
|
||||
`define stop $stop
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d (%s !== %s)\n", `__FILE__,`__LINE__, (gotv), (expv), `"gotv`", `"expv`"); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
package pkg;
|
||||
function automatic bit fn(int value);
|
||||
return (value > 0) ? 1'b1 : 1'b0;
|
||||
endfunction
|
||||
endpackage
|
||||
|
||||
interface ifc #(parameter type some_type) ();
|
||||
localparam int PARAM = 1;
|
||||
localparam int TYPE_WIDTH = $bits(some_type);
|
||||
endinterface
|
||||
|
||||
function automatic bit assert_func(bit value);
|
||||
if (!value) $fatal(2, "DEAD");
|
||||
return value;
|
||||
endfunction
|
||||
|
||||
module mod(ifc i);
|
||||
localparam bit lpbit = pkg::fn(i.PARAM);
|
||||
localparam bit test = assert_func(i.TYPE_WIDTH == 32);
|
||||
endmodule
|
||||
|
||||
module t;
|
||||
ifc #(.some_type(int)) i();
|
||||
mod m(.i);
|
||||
|
||||
initial begin
|
||||
`checkd(m.lpbit, 1'b1); // fn(1) returns 1 since 1 > 0
|
||||
`checkd(m.test, 1'b1); // $bits(int) == 32, so assert_func(1) returns 1
|
||||
$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,49 @@
|
|||
// DESCRIPTION: Verilator: Interface array with multiple consumer modules using FUNCREF LPARAMs
|
||||
//
|
||||
// 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
|
||||
|
||||
// verilog_format: off
|
||||
`define stop $stop
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d (%s !== %s)\n", `__FILE__,`__LINE__, (gotv), (expv), `"gotv`", `"expv`"); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
package pkg;
|
||||
function automatic int decode_width(int value);
|
||||
return (value > 0) ? value * 2 : 0;
|
||||
endfunction
|
||||
endpackage
|
||||
|
||||
interface ifc #(parameter int WIDTH = 8);
|
||||
localparam int DEPTH = $clog2(WIDTH);
|
||||
localparam int DECODED = pkg::decode_width(DEPTH);
|
||||
endinterface
|
||||
|
||||
module producer(ifc i);
|
||||
localparam int BUF_SIZE = pkg::decode_width(i.DEPTH);
|
||||
localparam int OUT_W = i.DECODED + 1;
|
||||
endmodule
|
||||
|
||||
module consumer(ifc i);
|
||||
localparam int HALF = i.DECODED / 2;
|
||||
localparam int TAG_W = pkg::decode_width(i.DEPTH) + i.DECODED;
|
||||
endmodule
|
||||
|
||||
module t;
|
||||
ifc #(.WIDTH(64)) bus[2]();
|
||||
producer p(.i(bus[0]));
|
||||
consumer c(.i(bus[1]));
|
||||
|
||||
initial begin
|
||||
// WIDTH=64, DEPTH=$clog2(64)=6, DECODED=decode_width(6)=12
|
||||
`checkd(p.BUF_SIZE, 12); // decode_width(6) = 12
|
||||
`checkd(p.OUT_W, 13); // 12 + 1 = 13
|
||||
`checkd(c.HALF, 6); // 12 / 2 = 6
|
||||
`checkd(c.TAG_W, 24); // decode_width(6) + 12 = 12 + 12 = 24
|
||||
$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,52 @@
|
|||
// DESCRIPTION: Verilator: Hierarchical interface pass-through with FUNCREF LPARAMs
|
||||
//
|
||||
// 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
|
||||
|
||||
// verilog_format: off
|
||||
`define stop $stop
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d (%s !== %s)\n", `__FILE__,`__LINE__, (gotv), (expv), `"gotv`", `"expv`"); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
package pkg;
|
||||
function automatic int decode_width(int value);
|
||||
return (value > 0) ? value * 2 : 0;
|
||||
endfunction
|
||||
endpackage
|
||||
|
||||
interface ifc #(parameter int WIDTH = 8);
|
||||
localparam int DEPTH = $clog2(WIDTH);
|
||||
localparam int DECODED = pkg::decode_width(DEPTH);
|
||||
endinterface
|
||||
|
||||
// Leaf module: uses interface LPARAM in a FUNCREF-based localparam
|
||||
module leaf(ifc i);
|
||||
localparam int BUF_SIZE = pkg::decode_width(i.DEPTH);
|
||||
localparam int OUT_W = i.DECODED + 1;
|
||||
endmodule
|
||||
|
||||
// Intermediate wrapper: passes interface through to leaf
|
||||
module wrapper(ifc i);
|
||||
leaf u_leaf(.i);
|
||||
endmodule
|
||||
|
||||
// Second level wrapper: adds another layer of hierarchy
|
||||
module subsystem(ifc bus);
|
||||
wrapper u_wrap(.i(bus));
|
||||
endmodule
|
||||
|
||||
module t;
|
||||
ifc #(.WIDTH(64)) bus();
|
||||
subsystem u_sub(.bus);
|
||||
|
||||
initial begin
|
||||
// WIDTH=64, DEPTH=$clog2(64)=6, DECODED=decode_width(6)=12
|
||||
`checkd(u_sub.u_wrap.u_leaf.BUF_SIZE, 12); // decode_width(6) = 12
|
||||
`checkd(u_sub.u_wrap.u_leaf.OUT_W, 13); // 12 + 1 = 13
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
Loading…
Reference in New Issue