Support virtual class

This commit is contained in:
Wilson Snyder 2020-08-23 20:27:25 -04:00
parent 3d073c9534
commit 917d3b0fb3
11 changed files with 80 additions and 28 deletions

View File

@ -9,7 +9,7 @@ The contributors that suggested a given feature are shown in []. Thanks!
** Support hierarchical Verilation (#2206). [Yutetsu TAKATSUKASA]
**** Support class extern.
**** Support (with limitations) class extern, class extends, virtual class.
**** Support $urandom, $urandom_range without stability.

View File

@ -1036,7 +1036,7 @@ private:
// Unless public, v3Descope will not uniquify function names even if duplicate per-scope,
// so make it unique now.
string suffix; // So, make them unique
if (!nodep->taskPublic()) suffix = "_" + m_scopep->nameDotless();
if (!nodep->taskPublic() && !nodep->classMethod()) suffix = "_" + m_scopep->nameDotless();
string name = ((nodep->name() == "new") ? "new" : prefix + nodep->name() + suffix);
AstCFunc* cfuncp = new AstCFunc(
nodep->fileline(), name, m_scopep,
@ -1049,6 +1049,7 @@ private:
cfuncp->dpiExport(nodep->dpiExport());
cfuncp->dpiImportWrapper(nodep->dpiImport());
cfuncp->isStatic(!(nodep->dpiImport() || nodep->taskPublic() || nodep->classMethod()));
cfuncp->isVirtual(nodep->isVirtual());
cfuncp->pure(nodep->pure());
if (nodep->name() == "new") {
cfuncp->isConstructor(true);

View File

@ -2028,7 +2028,6 @@ private:
virtual void visit(AstClass* nodep) override {
if (nodep->didWidthAndSet()) return;
userIterateChildren(nodep, nullptr); // First size all members
if (nodep->isVirtual()) nodep->v3warn(E_UNSUPPORTED, "Unsupported: virtual class");
nodep->repairCache();
}
virtual void visit(AstClassRefDType* nodep) override {
@ -2739,7 +2738,10 @@ private:
// Either made explicitly or V3LinkDot made implicitly
classp->v3fatalSrc("Can't find class's new");
}
if (classp->isVirtual()) {
nodep->v3error(
"Illegal to call 'new' using an abstract virtual class (IEEE 1800-2017 8.21)");
}
userIterate(nodep->taskp(), nullptr);
userIterateChildren(nodep, nullptr);
processFTaskRefArgs(nodep);
@ -3771,9 +3773,6 @@ private:
nodep->didWidth(true);
return;
}
if (nodep->isVirtual() || nodep->pureVirtual()) {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: 'virtual' class method");
}
// Function hasn't been widthed, so make it so.
// Would use user1 etc, but V3Width called from too many places to spend a user
nodep->doingWidth(true);

View File

@ -1,7 +0,0 @@
%Error-UNSUPPORTED: t/t_class_virtual.v:8:25: Unsupported: 'virtual' class method
8 | virtual function int hello;
| ^~~~~
%Error-UNSUPPORTED: t/t_class_virtual.v:7:9: Unsupported: virtual class
7 | virtual class VBase;
| ^~~~~
%Error: Exiting due to

View File

@ -8,11 +8,13 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(vlt => 1);
scenarios(simulator => 1);
lint(
fails => 1,
expect_filename => $Self->{golden_filename},
compile(
);
execute(
check_finished => 1,
);
ok(1);

View File

@ -10,14 +10,13 @@ virtual class VBase;
endfunction
endclass
`ifndef VERILATOR
virtual class VA extends VBase;
class VA extends VBase;
virtual function int hello;
return 2;
endfunction
endclass
virtual class VB extends VBase;
class VB extends VBase;
virtual function int hello;
return 3;
endfunction
@ -28,6 +27,10 @@ module t;
VA va = new;
VB vb = new;
VBase b;
if (va.hello() != 2) $stop;
if (vb.hello() != 3) $stop;
b = va;
if (b.hello() != 2) $stop;
b = vb;
@ -36,4 +39,3 @@ module t;
$finish;
end
endmodule
`endif

View File

@ -0,0 +1,5 @@
%Error: t/t_class_virtual_bad.v:12:17: Illegal to call 'new' using an abstract virtual class (IEEE 1800-2017 8.21)
: ... In instance t
12 | VBase b = new;
| ^~~
%Error: Exiting due to

View File

@ -0,0 +1,19 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2020 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(vlt => 1);
lint(
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,14 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2019 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
virtual class VBase;
endclass
module t;
initial begin
VBase b = new; // Error
end
endmodule

View File

@ -8,11 +8,13 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(vlt => 1);
scenarios(simulator => 1);
lint(
fails => 1,
expect_filename => $Self->{golden_filename},
compile(
);
execute(
check_finished => 1,
);
ok(1);

View File

@ -4,6 +4,21 @@
// any use, without warranty, 2019 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
virtual class VC;
pure virtual task hello();
virtual class VBase;
pure virtual function int hello();
endclass
class VA extends VBase;
virtual function int hello;
return 2;
endfunction
endclass
module t;
initial begin
VA va = new;
if (va.hello() != 2) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule