mirror of
https://github.com/verilator/verilator.git
synced 2025-01-01 04:07:34 +00:00
Support interface class diamond relationship.
This commit is contained in:
parent
21e85f87bc
commit
74ec50f933
@ -474,6 +474,7 @@ AC_SUBST(CFG_LDFLAGS_VERILATED)
|
||||
# pthreads is harmless otherwise.
|
||||
CFG_LIBS="$LIBS $CFG_LIBS"
|
||||
_MY_LDLIBS_CHECK_OPT(CFG_LIBS, -lpthread)
|
||||
_MY_LDLIBS_CHECK_OPT(CFG_LIBS, -latomic)
|
||||
|
||||
# Check libraries for MingW
|
||||
_MY_LDLIBS_CHECK_OPT(CFG_LIBS, -lbcrypt)
|
||||
|
@ -248,16 +248,18 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void putConstructorSubinit(const AstClass* classp, AstCFunc* cfuncp, bool top, bool& firstr) {
|
||||
void putConstructorSubinit(const AstClass* classp, AstCFunc* cfuncp, bool top, std::set<AstClass*> &doneClassesr) {
|
||||
for (const AstClassExtends* extp = classp->extendsp(); extp;
|
||||
extp = VN_AS(extp->nextp(), ClassExtends)) {
|
||||
if (extp->classp()->useVirtualPublic()) {
|
||||
// It's a c++ virtual class (diamond relation)
|
||||
// Must get the subclasses initialized first
|
||||
putConstructorSubinit(extp->classp(), cfuncp, false, firstr);
|
||||
putConstructorSubinit(extp->classp(), cfuncp, false, doneClassesr);
|
||||
}
|
||||
puts(firstr ? "" : "\n, ");
|
||||
firstr = false;
|
||||
// Diamond pattern with same base class twice?
|
||||
if (doneClassesr.find(extp->classp()) != doneClassesr.end()) continue;
|
||||
puts(doneClassesr.empty() ? "" : "\n , ");
|
||||
doneClassesr.emplace(extp->classp());
|
||||
puts(prefixNameProtect(extp->classp()));
|
||||
if (constructorNeedsProcess(extp->classp())) {
|
||||
puts("(vlProcess, vlSymsp");
|
||||
@ -295,8 +297,8 @@ public:
|
||||
const AstClass* const classp = VN_CAST(nodep->scopep()->modp(), Class);
|
||||
if (nodep->isConstructor() && classp && classp->extendsp()) {
|
||||
puts("\n : ");
|
||||
bool first = true;
|
||||
putConstructorSubinit(classp, nodep, true, first /*ref*/);
|
||||
std::set<AstClass*> doneClasses;
|
||||
putConstructorSubinit(classp, nodep, true, doneClasses /*ref*/);
|
||||
}
|
||||
}
|
||||
puts(" {\n");
|
||||
|
@ -2030,7 +2030,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||
AstNodeFTask* m_ftaskp = nullptr; // Current function/task
|
||||
int m_modportNum = 0; // Uniqueify modport numbers
|
||||
bool m_inSens = false; // True if in senitem
|
||||
std::set<std::string> m_ifClassImpNames; // Names imported from interface class
|
||||
std::map<std::string, AstNode*> m_ifClassImpNames; // Names imported from interface class
|
||||
std::set<AstClass*> m_extendsParam; // Classes that have a parameterized super class
|
||||
// (except the default instances)
|
||||
// They are added to the set only in linkDotPrimary.
|
||||
@ -2235,9 +2235,9 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||
<< "... Location of interface class's function\n"
|
||||
<< interfaceSubp->warnContextSecondary());
|
||||
}
|
||||
if (!existsInChild
|
||||
&& m_ifClassImpNames.find(interfaceSubp->name())
|
||||
!= m_ifClassImpNames.end()) {
|
||||
const auto it = m_ifClassImpNames.find(interfaceSubp->name());
|
||||
if (!existsInChild && it != m_ifClassImpNames.end()
|
||||
&& it->second != interfaceSubp) { // Not exact same function from diamond
|
||||
implementsClassp->v3error(
|
||||
"Class " << implementsClassp->prettyNameQ() << " implements "
|
||||
<< interfaceClassp->prettyNameQ()
|
||||
@ -2249,7 +2249,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||
<< "... Location of interface class's function\n"
|
||||
<< interfaceSubp->warnContextSecondary());
|
||||
}
|
||||
m_ifClassImpNames.emplace(interfaceSubp->name());
|
||||
m_ifClassImpNames.emplace(interfaceSubp->name(), interfaceSubp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
21
test_regress/t/t_class_diamond.pl
Executable file
21
test_regress/t/t_class_diamond.pl
Executable file
@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2024 by Wilson Snyder. 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-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
scenarios(simulator => 1);
|
||||
|
||||
compile(
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
59
test_regress/t/t_class_diamond.v
Normal file
59
test_regress/t/t_class_diamond.v
Normal file
@ -0,0 +1,59 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2024 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module class_tb ();
|
||||
interface class Ibase;
|
||||
pure virtual function int fn();
|
||||
endclass
|
||||
|
||||
interface class Ic1 extends Ibase;
|
||||
pure virtual function int fn1();
|
||||
endclass
|
||||
|
||||
interface class Ic2 extends Ibase;
|
||||
pure virtual function int fn2();
|
||||
endclass
|
||||
|
||||
interface class Ic3 extends Ic1, Ic2;
|
||||
endclass
|
||||
|
||||
class Cls implements Ic3;
|
||||
virtual function int fn();
|
||||
return 10;
|
||||
endfunction
|
||||
virtual function int fn1();
|
||||
return 1;
|
||||
endfunction
|
||||
virtual function int fn2();
|
||||
return 2;
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
initial begin
|
||||
Cls cls;
|
||||
Ibase ibase;
|
||||
Ic1 ic1;
|
||||
Ic2 ic2;
|
||||
Ic3 ic3;
|
||||
cls = new;
|
||||
if (cls.fn() != 10) $stop;
|
||||
if (cls.fn1() != 1) $stop;
|
||||
if (cls.fn2() != 2) $stop;
|
||||
ibase = cls;
|
||||
ic1 = cls;
|
||||
ic2 = cls;
|
||||
ic3 = cls;
|
||||
if (ibase.fn() != 10) $stop;
|
||||
if (ic1.fn() != 10) $stop;
|
||||
if (ic2.fn() != 10) $stop;
|
||||
if (ic3.fn() != 10) $stop;
|
||||
if (ic1.fn1() != 1) $stop;
|
||||
if (ic2.fn2() != 2) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
@ -19,6 +19,24 @@ endclass
|
||||
class Cls implements IclsBoth;
|
||||
endclass
|
||||
|
||||
|
||||
// This is not a collision - diamond
|
||||
interface class Ibase;
|
||||
pure virtual function int fn();
|
||||
endclass
|
||||
|
||||
interface class Ic1 extends Ibase;
|
||||
pure virtual function int fn1();
|
||||
endclass
|
||||
|
||||
interface class Ic2 extends Ibase;
|
||||
pure virtual function int fn2();
|
||||
endclass
|
||||
|
||||
interface class Ic3 extends Ic1, Ic2;
|
||||
endclass
|
||||
|
||||
|
||||
module t (/*AUTOARG*/);
|
||||
Cls c;
|
||||
endmodule
|
||||
|
Loading…
Reference in New Issue
Block a user