This commit is contained in:
parent
2022bacd38
commit
a24dd8b2dc
|
|
@ -57,6 +57,7 @@ Dan Ruelas-Petrisko
|
|||
Daniel Bates
|
||||
Danny Oler
|
||||
Dave Sargeant
|
||||
David Garau
|
||||
David Horton
|
||||
David Ledger
|
||||
David Metz
|
||||
|
|
|
|||
|
|
@ -3653,8 +3653,11 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
return nullptr;
|
||||
}
|
||||
static const AstVar* getNextVarp(const AstNode* stmtsp) {
|
||||
// Only IO ports, as parameters are on paramsp(), not the pinsp() list paired here
|
||||
while (stmtsp) {
|
||||
if (const AstVar* const varp = VN_CAST(stmtsp, Var)) return varp;
|
||||
if (const AstVar* const varp = VN_CAST(stmtsp, Var)) {
|
||||
if (varp->isIO()) return varp;
|
||||
}
|
||||
stmtsp = stmtsp->nextp();
|
||||
}
|
||||
return nullptr;
|
||||
|
|
@ -4470,7 +4473,9 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
AstIfaceRefDType* const ifacerefp
|
||||
= LinkDotState::ifaceRefFromArray(varp->subDTypep());
|
||||
if (varp->isIfaceRef() && m_genericIfaceModule
|
||||
&& VN_IS(varp->childDTypep(), IfaceGenericDType)) {
|
||||
&& VN_IS(varp->childDTypep(), IfaceGenericDType) && !start) {
|
||||
// Defer only dotted member access ('d.PARAM'), as V3Param must specialize
|
||||
// first; a standalone ref ('.x(d)') resolves via allowVar below now
|
||||
ok = true;
|
||||
m_ds.m_unresolvedGenericIface = true;
|
||||
} else if (ifacerefp && varp->isIfaceRef()) {
|
||||
|
|
|
|||
|
|
@ -2529,12 +2529,17 @@ class ParamVisitor final : public VNVisitor {
|
|||
std::deque<std::string> m_strings; // Allocator for temporary strings
|
||||
std::map<const AstRefDType*, bool>
|
||||
m_isCircular; // Stores information whether `AstRefDType` is circular
|
||||
using VarsByName = std::unordered_map<std::string, AstVar*>;
|
||||
// Persists across modules; one specialized interface clone serves every module bound to it
|
||||
std::unordered_map<const AstNodeModule*, VarsByName> m_ifaceParams;
|
||||
|
||||
// STATE - for current visit position (use VL_RESTORER)
|
||||
AstNodeModule* m_modp = nullptr; // Module iterating
|
||||
std::unordered_set<std::string> m_ifacePortNames; // Interface port names in current module
|
||||
std::unordered_map<std::string, AstCell*>
|
||||
m_ifaceInstCells; // Local interface instance cells in current module, keyed by name
|
||||
VarsByName m_modIfaceRefs; // Interface-ref Vars in current module, keyed by name
|
||||
bool m_modIfaceRefsDone = false; // m_modIfaceRefs has been gathered for m_modp
|
||||
string m_generateHierName; // Generate portion of hierarchy name
|
||||
|
||||
// METHODS
|
||||
|
|
@ -2573,7 +2578,10 @@ class ParamVisitor final : public VNVisitor {
|
|||
VL_RESTORER(m_modp);
|
||||
VL_RESTORER_CLEAR(m_ifacePortNames);
|
||||
VL_RESTORER_CLEAR(m_ifaceInstCells);
|
||||
VL_RESTORER_CLEAR(m_modIfaceRefs);
|
||||
VL_RESTORER(m_modIfaceRefsDone);
|
||||
m_modp = modp;
|
||||
m_modIfaceRefsDone = false;
|
||||
iterateChildren(modp);
|
||||
}
|
||||
}
|
||||
|
|
@ -2925,6 +2933,76 @@ class ParamVisitor final : public VNVisitor {
|
|||
if (!VN_IS(nodep->classOrPackageNodep(), Typedef)) visitCellOrClassRef(nodep, false);
|
||||
}
|
||||
|
||||
// Recurse into AstGenBlock as generate blocks aren't flattened until V3Begin::debeginAll,
|
||||
// well after V3Param runs
|
||||
static void gatherVars(AstNode* stmtsp, bool (*matchp)(const AstVar*), VarsByName& varsr) {
|
||||
for (AstNode* nodep = stmtsp; nodep; nodep = nodep->nextp()) {
|
||||
if (AstVar* const varp = VN_CAST(nodep, Var)) {
|
||||
// emplace, not assign, so the first declaration of a name wins
|
||||
if (matchp(varp)) varsr.emplace(varp->name(), varp);
|
||||
} else if (AstGenBlock* const genp = VN_CAST(nodep, GenBlock)) {
|
||||
gatherVars(genp->itemsp(), matchp, varsr);
|
||||
}
|
||||
}
|
||||
}
|
||||
const VarsByName& modIfaceRefs() {
|
||||
if (!m_modIfaceRefsDone) {
|
||||
gatherVars(
|
||||
m_modp->stmtsp(), [](const AstVar* varp) { return varp->isIfaceRef(); },
|
||||
m_modIfaceRefs);
|
||||
m_modIfaceRefsDone = true;
|
||||
}
|
||||
return m_modIfaceRefs;
|
||||
}
|
||||
const VarsByName& ifaceParams(AstNodeModule* ifacep) {
|
||||
const auto pair = m_ifaceParams.emplace(ifacep, VarsByName{});
|
||||
if (pair.second) {
|
||||
gatherVars(
|
||||
ifacep->stmtsp(), [](const AstVar* varp) { return varp->isParam(); },
|
||||
pair.first->second);
|
||||
}
|
||||
return pair.first->second;
|
||||
}
|
||||
// Resolve a generic-interface 'ifacePort.member' Dot left unlinked by V3LinkDot, now that
|
||||
// ifacePort may have been specialized. Returns nullptr if still unresolvable
|
||||
AstNode* tryResolveGenericIfaceDot(AstDot* dotp) {
|
||||
AstParseRef* const lhsp = VN_CAST(dotp->lhsp(), ParseRef);
|
||||
AstParseRef* const rhsp = VN_CAST(dotp->rhsp(), ParseRef);
|
||||
if (!lhsp || !rhsp) return nullptr;
|
||||
// Always called from visit(AstVar) inside processWorkQ()'s VL_RESTORER(m_modp) scope
|
||||
if (VL_UNCOVERABLE(!m_modp)) return nullptr;
|
||||
|
||||
const auto& refVars = modIfaceRefs();
|
||||
const auto ifaceVarIt = refVars.find(lhsp->name());
|
||||
// V3LinkDot only defers Dots whose lhs is a non-array iface-ref var, so this can't fail
|
||||
if (VL_UNCOVERABLE(ifaceVarIt == refVars.end())) return nullptr;
|
||||
AstVar* const ifaceVarp = ifaceVarIt->second;
|
||||
AstIfaceRefDType* const ifacerefp = VN_CAST(ifaceVarp->subDTypep(), IfaceRefDType);
|
||||
if (VL_UNCOVERABLE(!ifacerefp || !ifacerefp->ifacep())) return nullptr;
|
||||
|
||||
const auto& ifaceVars = ifaceParams(ifacerefp->ifacep());
|
||||
const auto targetVarIt = ifaceVars.find(rhsp->name());
|
||||
if (targetVarIt == ifaceVars.end()) return nullptr;
|
||||
AstVar* const targetVarp = targetVarIt->second;
|
||||
// processWorkQ() visits interface cells first, so the interface is already constified
|
||||
if (VL_UNCOVERABLE(!VN_IS(targetVarp->valuep(), Const))) iterate(targetVarp);
|
||||
if (VL_UNCOVERABLE(!targetVarp->valuep() || !VN_IS(targetVarp->valuep(), Const))) {
|
||||
return nullptr; // LCOV_EXCL_LINE
|
||||
}
|
||||
return targetVarp->valuep()->cloneTree(false);
|
||||
}
|
||||
void resolveGenericIfaceDotsIn(AstNode* nodep) {
|
||||
// Collect first: the deleteTree() below frees a node foreach() would still read from
|
||||
std::vector<AstDot*> dotps;
|
||||
nodep->foreach([&](AstDot* dotp) { dotps.push_back(dotp); });
|
||||
for (AstDot* const dotp : dotps) {
|
||||
if (AstNode* const newp = tryResolveGenericIfaceDot(dotp)) {
|
||||
dotp->replaceWith(newp);
|
||||
VL_DO_DANGLING(dotp->deleteTree(), dotp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure all parameters are constantified
|
||||
void visit(AstVar* nodep) override {
|
||||
if (nodep->user2SetOnce()) return; // Process once
|
||||
|
|
@ -2937,6 +3015,8 @@ 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()) {
|
||||
// Resolve now: a sibling cell's pin fold may need this before linkDotParamed
|
||||
resolveGenericIfaceDotsIn(nodep->valuep());
|
||||
// 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
|
||||
|
|
@ -2952,9 +3032,8 @@ class ParamVisitor final : public VNVisitor {
|
|||
}
|
||||
});
|
||||
if (hasUnresolvedLparamXRef) return;
|
||||
// Defer if value has a class::member Dot, or references a deferred lparam
|
||||
const bool hasDot = nodep->valuep()->exists(
|
||||
[](AstDot* dotp) { return VN_IS(dotp->lhsp(), ClassOrPackageRef); });
|
||||
// Defer if value has any unresolved Dot, or references a deferred lparam
|
||||
const bool hasDot = nodep->valuep()->exists([](AstDot*) { return true; });
|
||||
bool refsDeferred = false;
|
||||
if (!hasDot) {
|
||||
const auto& deferredVarps = v3Global.rootp()->deferredParamVarps();
|
||||
|
|
|
|||
|
|
@ -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=["--timing"])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 PlanV GmbH
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// verilog_format: off
|
||||
`define stop $stop
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
interface inf #(parameter int PARAM = 1);
|
||||
logic [PARAM-1:0] v;
|
||||
endinterface
|
||||
|
||||
module leaf (inf d);
|
||||
initial begin
|
||||
#1;
|
||||
`checkd(d.v, 13);
|
||||
`checkd(d.PARAM, 5);
|
||||
end
|
||||
endmodule
|
||||
|
||||
module mid2 (interface c);
|
||||
leaf leaf_i(.d(c));
|
||||
endmodule
|
||||
|
||||
module mid1 (interface b);
|
||||
mid2 mid2_i(.c(b));
|
||||
endmodule
|
||||
|
||||
module t;
|
||||
inf #(.PARAM(5)) a();
|
||||
mid1 mid1_i(.b(a));
|
||||
initial begin
|
||||
a.v = 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=["--timing"])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain
|
||||
// SPDX-FileCopyrightText: 2026 PlanV GmbH
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// verilog_format: off
|
||||
`define stop $stop
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
interface inf #(parameter int PARAM = 1);
|
||||
logic [PARAM-1:0] v;
|
||||
endinterface
|
||||
|
||||
module leaf (inf c);
|
||||
initial begin
|
||||
#1;
|
||||
`checkd(c.v, 13)
|
||||
`checkd(c.PARAM, 5)
|
||||
end
|
||||
endmodule
|
||||
|
||||
module mid #(int PARAM = 1) (interface b);
|
||||
leaf leaf_i(.c(b));
|
||||
initial `checkd(PARAM,7)
|
||||
endmodule
|
||||
|
||||
module t;
|
||||
inf #(.PARAM(5)) a();
|
||||
mid #(.PARAM(7)) mid_i (.b(a));
|
||||
initial begin
|
||||
a.v = 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: 2025 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.compile(verilator_flags2=['--timing'])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain
|
||||
// SPDX-FileCopyrightText: 2025 Antmicro
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// verilog_format: off
|
||||
`define stop $stop
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
interface inf #(parameter int PARAM = 1);
|
||||
logic [PARAM-1:0] v;
|
||||
modport mp (input v);
|
||||
endinterface
|
||||
|
||||
module Leaf #(parameter int PARAM = 1) (inf.mp leaf_a);
|
||||
initial begin
|
||||
#1;
|
||||
`checkd(leaf_a.PARAM, PARAM);
|
||||
end
|
||||
endmodule
|
||||
|
||||
module GenericModule (interface.mp a);
|
||||
localparam LOC_PARAM = a.PARAM;
|
||||
// A generic interface's parameter, parameterizing a sibling interface cell
|
||||
inf #(.PARAM(LOC_PARAM)) nested_inst();
|
||||
Leaf #(.PARAM(LOC_PARAM)) leaf (nested_inst);
|
||||
initial begin
|
||||
#1;
|
||||
`checkd(a.v, 7);
|
||||
`checkd(a.PARAM, 13);
|
||||
`checkd(LOC_PARAM, a.PARAM);
|
||||
end
|
||||
endmodule
|
||||
|
||||
module t;
|
||||
inf #(.PARAM(13)) inf_inst();
|
||||
GenericModule genericModule (inf_inst);
|
||||
initial begin
|
||||
inf_inst.v = 7;
|
||||
$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=['--timing'])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 David Garau
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// verilog_format: off
|
||||
`define stop $stop
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
interface leaf_if;
|
||||
localparam int LEAF_PARAM = 42;
|
||||
logic dummy;
|
||||
endinterface
|
||||
|
||||
interface inf #(parameter int PARAM = 1);
|
||||
logic [PARAM-1:0] v;
|
||||
// Makes 'a.nested.LEAF_PARAM' a chained Dot, whose lhsp is itself a Dot
|
||||
leaf_if nested();
|
||||
parameter int ARR[2] = '{PARAM, PARAM + 1};
|
||||
modport mp (input v);
|
||||
endinterface
|
||||
|
||||
module GenericModule (interface.mp a);
|
||||
localparam int LOC_CHAIN = a.nested.LEAF_PARAM;
|
||||
// Makes the Dot's rhsp an indexed select, not a plain identifier
|
||||
localparam int LOC_ARR = a.ARR[0];
|
||||
initial begin
|
||||
#1;
|
||||
`checkd(a.v, 7);
|
||||
`checkd(LOC_CHAIN, 42);
|
||||
`checkd(LOC_ARR, 13);
|
||||
end
|
||||
endmodule
|
||||
|
||||
module t;
|
||||
inf #(.PARAM(13)) inf_inst();
|
||||
GenericModule genericModule (inf_inst);
|
||||
initial begin
|
||||
inf_inst.v = 7;
|
||||
$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=['--timing'])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 David Garau
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// verilog_format: off
|
||||
`define stop $stop
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
interface inf #(parameter int PARAM = 1);
|
||||
logic [PARAM-1:0] v;
|
||||
// A non-Var/non-GenBlock item the member gather must skip past
|
||||
modport mp (input v);
|
||||
if (1) begin : blk_decoy
|
||||
// Same name as the real parameter below, but not a parameter
|
||||
logic PARAM_IF;
|
||||
end
|
||||
if (1) begin : blk_if
|
||||
localparam int PARAM_IF = PARAM + 100;
|
||||
end
|
||||
for (genvar i = 0; i < 1; i++) begin : blk_for
|
||||
localparam int PARAM_FOR = PARAM + 200;
|
||||
end
|
||||
endinterface
|
||||
|
||||
module GenericModule (interface.mp a);
|
||||
// Two references to the same member, so the second reuses the gathered members
|
||||
localparam int LOC_PARAM1 = a.PARAM;
|
||||
localparam int LOC_PARAM2 = a.PARAM;
|
||||
// Members inside generate blocks, reachable only by recursing into them
|
||||
localparam int LOC_IF = a.PARAM_IF;
|
||||
localparam int LOC_FOR = a.PARAM_FOR;
|
||||
initial begin
|
||||
#1;
|
||||
`checkd(a.v, 7);
|
||||
`checkd(LOC_PARAM1, 13);
|
||||
`checkd(LOC_PARAM2, 13);
|
||||
`checkd(LOC_IF, 113);
|
||||
`checkd(LOC_FOR, 213);
|
||||
end
|
||||
endmodule
|
||||
|
||||
module t;
|
||||
inf #(.PARAM(13)) inf_inst();
|
||||
GenericModule genericModule (inf_inst);
|
||||
initial begin
|
||||
inf_inst.v = 7;
|
||||
$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=['--timing'])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 David Garau
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// verilog_format: off
|
||||
`define stop $stop
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
interface inf #(parameter int PARAM = 1);
|
||||
logic [PARAM-1:0] v;
|
||||
modport mp (input v);
|
||||
endinterface
|
||||
|
||||
module GenericModule (interface.mp a);
|
||||
// Dotted localparam inside a generate block, feeding a sibling cell in the same block.
|
||||
// The interface-ref gather must recurse in here yet still find port 'a' at module level.
|
||||
// Generate blocks on the interface side are covered by t_interface_generic_iface_param_genblock.
|
||||
if (1) begin : blk
|
||||
localparam int LOC_PARAM = a.PARAM;
|
||||
inf #(.PARAM(LOC_PARAM)) inner();
|
||||
end
|
||||
initial begin
|
||||
#1;
|
||||
`checkd(a.v, 7);
|
||||
`checkd(blk.LOC_PARAM, 13);
|
||||
`checkd(blk.inner.PARAM, 13);
|
||||
end
|
||||
endmodule
|
||||
|
||||
module t;
|
||||
inf #(.PARAM(13)) inf_inst();
|
||||
GenericModule genericModule (inf_inst);
|
||||
initial begin
|
||||
inf_inst.v = 7;
|
||||
$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: 2025 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.compile(verilator_flags2=['--timing'])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain
|
||||
// SPDX-FileCopyrightText: 2025 Antmicro
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// verilog_format: off
|
||||
`define stop $stop
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
interface inf #(int PARAM = 0);
|
||||
logic[PARAM-1:0] v;
|
||||
|
||||
modport port_in (
|
||||
input v
|
||||
);
|
||||
modport port_out (
|
||||
output v
|
||||
);
|
||||
endinterface
|
||||
|
||||
module GenericModule #(PARAM=0) (interface.port_in a);
|
||||
localparam int LOC_PARAM = a.PARAM;
|
||||
initial begin
|
||||
#1;
|
||||
`checkd(a.v, 7);
|
||||
`checkd(a.PARAM, 13);
|
||||
`checkd(LOC_PARAM, a.PARAM);
|
||||
end
|
||||
endmodule
|
||||
|
||||
module t;
|
||||
inf #(.PARAM(13)) inf_inst();
|
||||
GenericModule genericModule (inf_inst);
|
||||
initial begin
|
||||
inf_inst.v = 7;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
%Error: t/t_interface_generic_iface_param_ref_bad.v:19:32: Can't find definition of 'NONEXISTENT_PARAM' in dotted variable/method: 'a.NONEXISTENT_PARAM'
|
||||
: ... note: In instance 't.genericModule'
|
||||
19 | localparam int LOC_PARAM = a.NONEXISTENT_PARAM;
|
||||
| ^~~~~~~~~~~~~~~~~
|
||||
... Known scopes under 'a': <no instances found>
|
||||
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
||||
%Error: Exiting due to
|
||||
|
|
@ -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(fails=True, expect_filename=test.golden_filename)
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 David Garau
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// verilog_format: off
|
||||
`define stop $stop
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
interface inf #(parameter int PARAM = 1);
|
||||
logic [PARAM-1:0] v;
|
||||
modport mp (input v);
|
||||
endinterface
|
||||
|
||||
module GenericModule (interface.mp a);
|
||||
// A member that does not exist on the (now concrete) interface
|
||||
localparam int LOC_PARAM = a.NONEXISTENT_PARAM;
|
||||
initial begin
|
||||
#1;
|
||||
`checkd(a.v, 7);
|
||||
end
|
||||
endmodule
|
||||
|
||||
module t;
|
||||
inf #(.PARAM(13)) inf_inst();
|
||||
GenericModule genericModule (inf_inst);
|
||||
initial begin
|
||||
inf_inst.v = 7;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
Loading…
Reference in New Issue