Merge d53295a3fb into 5ead758f28
This commit is contained in:
commit
4f9dc73040
|
|
@ -3136,6 +3136,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
bool m_inPackedArray = false; // Currently traversing a packed array tree
|
||||
bool m_replaceWithAlias
|
||||
= true; // Replace VarScope with an alias. Used in the handling of AstAlias
|
||||
bool m_isParam = false; // Specifies whether currently visiting param variable
|
||||
|
||||
struct DotStates final {
|
||||
DotPosition m_dotPos; // Scope part of dotted resolution
|
||||
|
|
@ -5092,6 +5093,8 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
void visit(AstVar* nodep) override {
|
||||
LINKDOT_VISIT_START();
|
||||
checkNoDot(nodep);
|
||||
VL_RESTORER(m_isParam);
|
||||
m_isParam = nodep->varType().isParam();
|
||||
iterateChildren(nodep);
|
||||
if (m_statep->forPrimary() && nodep->isIO() && !m_ftaskp && !nodep->user4()) {
|
||||
nodep->v3error(
|
||||
|
|
@ -5273,27 +5276,32 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
// which may find std::randomize and overwrite classOrPackagep
|
||||
return;
|
||||
}
|
||||
if (m_insideClassExtParam) {
|
||||
// The reference may point to a method declared in a super class, which is proved
|
||||
// by a parameter. In such a case, it can't be linked at the first stage.
|
||||
// Must not do any linking, because e.g. might find an extends of an upper class
|
||||
// because the current class (under parent) isn't yet importing it's extended class
|
||||
// symbols
|
||||
return;
|
||||
}
|
||||
if (AstClass* const targetClassp = VN_CAST(dotSymp->nodep(), Class)) {
|
||||
if (m_extendsParam.count(targetClassp)) {
|
||||
// Target class has parameterized extends not yet resolved.
|
||||
// Its inherited symbols (e.g. static functions from the base class)
|
||||
// aren't imported yet - defer to linkDotParamed.
|
||||
VSymEnt* const foundp
|
||||
= m_statep->findSymPrefixed(dotSymp, nodep->name(), baddot, first);
|
||||
AstNodeFTask* const taskp = foundp ? VN_CAST(foundp->nodep(), NodeFTask) : nullptr;
|
||||
AstNodeModule* const taskModulep = foundp ? foundp->classOrPackagep() : nullptr;
|
||||
// Ignore deferring linking of functions inside params of classes extending
|
||||
// parametric classes if referenced function can be linked in the first pass.
|
||||
if (!m_isParam || !taskp
|
||||
|| (taskp->classMethod() && taskModulep && taskModulep->hasParameterList())) {
|
||||
if (m_insideClassExtParam) {
|
||||
// The reference may point to a method declared in a super class, which is
|
||||
// proved by a parameter. In such a case, it can't be linked at the first
|
||||
// stage. Must not do any linking, because e.g. might find an extends of an
|
||||
// upper class because the current class (under parent) isn't yet importing
|
||||
// it's extended class symbols.
|
||||
return;
|
||||
}
|
||||
if (AstClass* const targetClassp = VN_CAST(dotSymp->nodep(), Class)) {
|
||||
if (m_extendsParam.count(targetClassp)) {
|
||||
// Target class has parameterized extends not yet resolved.
|
||||
// Its inherited symbols (e.g. static functions from the base class)
|
||||
// aren't imported yet - defer to linkDotParamed.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VSymEnt* const foundp
|
||||
= m_statep->findSymPrefixed(dotSymp, nodep->name(), baddot, first);
|
||||
AstNodeFTask* const taskp
|
||||
= foundp ? VN_CAST(foundp->nodep(), NodeFTask) : nullptr; // Maybe nullptr
|
||||
if (taskp) {
|
||||
if (staticAccess && !taskp->isStatic()) {
|
||||
// TODO bug4077
|
||||
|
|
|
|||
|
|
@ -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('vlt')
|
||||
|
||||
test.compile()
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain
|
||||
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
`define stop $stop
|
||||
`define checkh(gotv, expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0x exp=%0x (%s !== %s)\n", `__FILE__,`__LINE__, (gotv), (expv), `"gotv`", `"expv`"); `stop; end while(0);
|
||||
|
||||
function automatic int align(input int a, input int b);
|
||||
return a - (a % b);
|
||||
endfunction
|
||||
|
||||
class Foo;
|
||||
|
||||
static function int mul(input int a, input int b);
|
||||
return a * b;
|
||||
endfunction
|
||||
|
||||
endclass : Foo
|
||||
|
||||
class FooParam #(parameter int param = 5);
|
||||
|
||||
static function int mul(input int a);
|
||||
return a * param;
|
||||
endfunction
|
||||
|
||||
endclass : FooParam
|
||||
|
||||
class Base #(parameter int param = 5);
|
||||
|
||||
function int get_base_param();
|
||||
return param;
|
||||
endfunction
|
||||
|
||||
static function int alignUp(input int a);
|
||||
return ((a + param - 1) / param) * param;
|
||||
endfunction
|
||||
|
||||
endclass : Base
|
||||
|
||||
class Derived #(
|
||||
parameter int a = 17,
|
||||
parameter int b = 8,
|
||||
parameter int c = align(a, b),
|
||||
parameter int d = Base#(b)::alignUp(a),
|
||||
parameter int e = Foo::mul(a, b),
|
||||
parameter int f = FooParam#()::mul(a)
|
||||
) extends Base #(
|
||||
.param (a)
|
||||
);
|
||||
|
||||
function int get_third_param();
|
||||
return c;
|
||||
endfunction
|
||||
|
||||
function int get_fourth_param();
|
||||
return d;
|
||||
endfunction
|
||||
|
||||
function int get_fifth_param();
|
||||
return e;
|
||||
endfunction
|
||||
|
||||
function int get_sixth_param();
|
||||
return f;
|
||||
endfunction
|
||||
|
||||
endclass : Derived
|
||||
|
||||
module t (clk);
|
||||
input clk;
|
||||
|
||||
Derived inst = new;
|
||||
|
||||
always @(posedge clk) begin
|
||||
`checkh(inst.get_base_param(), 17)
|
||||
`checkh(inst.get_third_param(), 16)
|
||||
`checkh(inst.get_fourth_param(), 24)
|
||||
`checkh(inst.get_fifth_param(), 136)
|
||||
`checkh(inst.get_sixth_param(), 85)
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
Loading…
Reference in New Issue