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.
|
# pthreads is harmless otherwise.
|
||||||
CFG_LIBS="$LIBS $CFG_LIBS"
|
CFG_LIBS="$LIBS $CFG_LIBS"
|
||||||
_MY_LDLIBS_CHECK_OPT(CFG_LIBS, -lpthread)
|
_MY_LDLIBS_CHECK_OPT(CFG_LIBS, -lpthread)
|
||||||
|
_MY_LDLIBS_CHECK_OPT(CFG_LIBS, -latomic)
|
||||||
|
|
||||||
# Check libraries for MingW
|
# Check libraries for MingW
|
||||||
_MY_LDLIBS_CHECK_OPT(CFG_LIBS, -lbcrypt)
|
_MY_LDLIBS_CHECK_OPT(CFG_LIBS, -lbcrypt)
|
||||||
|
|
|
@ -248,16 +248,18 @@ public:
|
||||||
return nullptr;
|
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;
|
for (const AstClassExtends* extp = classp->extendsp(); extp;
|
||||||
extp = VN_AS(extp->nextp(), ClassExtends)) {
|
extp = VN_AS(extp->nextp(), ClassExtends)) {
|
||||||
if (extp->classp()->useVirtualPublic()) {
|
if (extp->classp()->useVirtualPublic()) {
|
||||||
// It's a c++ virtual class (diamond relation)
|
// It's a c++ virtual class (diamond relation)
|
||||||
// Must get the subclasses initialized first
|
// Must get the subclasses initialized first
|
||||||
putConstructorSubinit(extp->classp(), cfuncp, false, firstr);
|
putConstructorSubinit(extp->classp(), cfuncp, false, doneClassesr);
|
||||||
}
|
}
|
||||||
puts(firstr ? "" : "\n, ");
|
// Diamond pattern with same base class twice?
|
||||||
firstr = false;
|
if (doneClassesr.find(extp->classp()) != doneClassesr.end()) continue;
|
||||||
|
puts(doneClassesr.empty() ? "" : "\n , ");
|
||||||
|
doneClassesr.emplace(extp->classp());
|
||||||
puts(prefixNameProtect(extp->classp()));
|
puts(prefixNameProtect(extp->classp()));
|
||||||
if (constructorNeedsProcess(extp->classp())) {
|
if (constructorNeedsProcess(extp->classp())) {
|
||||||
puts("(vlProcess, vlSymsp");
|
puts("(vlProcess, vlSymsp");
|
||||||
|
@ -295,8 +297,8 @@ public:
|
||||||
const AstClass* const classp = VN_CAST(nodep->scopep()->modp(), Class);
|
const AstClass* const classp = VN_CAST(nodep->scopep()->modp(), Class);
|
||||||
if (nodep->isConstructor() && classp && classp->extendsp()) {
|
if (nodep->isConstructor() && classp && classp->extendsp()) {
|
||||||
puts("\n : ");
|
puts("\n : ");
|
||||||
bool first = true;
|
std::set<AstClass*> doneClasses;
|
||||||
putConstructorSubinit(classp, nodep, true, first /*ref*/);
|
putConstructorSubinit(classp, nodep, true, doneClasses /*ref*/);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
puts(" {\n");
|
puts(" {\n");
|
||||||
|
|
|
@ -2030,7 +2030,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||||
AstNodeFTask* m_ftaskp = nullptr; // Current function/task
|
AstNodeFTask* m_ftaskp = nullptr; // Current function/task
|
||||||
int m_modportNum = 0; // Uniqueify modport numbers
|
int m_modportNum = 0; // Uniqueify modport numbers
|
||||||
bool m_inSens = false; // True if in senitem
|
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
|
std::set<AstClass*> m_extendsParam; // Classes that have a parameterized super class
|
||||||
// (except the default instances)
|
// (except the default instances)
|
||||||
// They are added to the set only in linkDotPrimary.
|
// 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"
|
<< "... Location of interface class's function\n"
|
||||||
<< interfaceSubp->warnContextSecondary());
|
<< interfaceSubp->warnContextSecondary());
|
||||||
}
|
}
|
||||||
if (!existsInChild
|
const auto it = m_ifClassImpNames.find(interfaceSubp->name());
|
||||||
&& m_ifClassImpNames.find(interfaceSubp->name())
|
if (!existsInChild && it != m_ifClassImpNames.end()
|
||||||
!= m_ifClassImpNames.end()) {
|
&& it->second != interfaceSubp) { // Not exact same function from diamond
|
||||||
implementsClassp->v3error(
|
implementsClassp->v3error(
|
||||||
"Class " << implementsClassp->prettyNameQ() << " implements "
|
"Class " << implementsClassp->prettyNameQ() << " implements "
|
||||||
<< interfaceClassp->prettyNameQ()
|
<< interfaceClassp->prettyNameQ()
|
||||||
|
@ -2249,7 +2249,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||||
<< "... Location of interface class's function\n"
|
<< "... Location of interface class's function\n"
|
||||||
<< interfaceSubp->warnContextSecondary());
|
<< interfaceSubp->warnContextSecondary());
|
||||||
}
|
}
|
||||||
m_ifClassImpNames.emplace(interfaceSubp->name());
|
m_ifClassImpNames.emplace(interfaceSubp->name(), interfaceSubp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
@ -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;
|
class Cls implements IclsBoth;
|
||||||
endclass
|
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*/);
|
module t (/*AUTOARG*/);
|
||||||
Cls c;
|
Cls c;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
Loading…
Reference in New Issue