Support class extending its parameter (#3904)

This commit is contained in:
Ryszard Rozak 2023-01-26 02:33:18 +01:00 committed by GitHub
parent 21aafe8f50
commit 91c44d7830
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 246 additions and 10 deletions

View File

@ -3174,20 +3174,46 @@ private:
cextp->v3error("Attempting to extend using non-class"); // LCOV_EXCL_LINE
} else {
VSymEnt* const foundp = m_curSymp->findIdFallback(cpackagerefp->name());
bool ok = false;
if (foundp) {
if (AstClass* const classp = VN_CAST(foundp->nodep(), Class)) {
AstClassRefDType* classRefDtypep = nullptr;
AstClass* classp = VN_CAST(foundp->nodep(), Class);
if (classp) {
AstPin* paramsp = cpackagerefp->paramsp();
if (paramsp) paramsp = paramsp->cloneTree(true);
classRefDtypep
= new AstClassRefDType{nodep->fileline(), classp, paramsp};
} else if (AstParamTypeDType* const paramp
= VN_CAST(foundp->nodep(), ParamTypeDType)) {
if (m_statep->forPrimary()) {
// Extending has to be handled after V3Param.cpp, but the type
// reference has to be visited
iterate(paramp);
return;
} else {
AstNodeDType* const paramTypep = paramp->getChildDTypep();
classRefDtypep
= VN_CAST(paramTypep->cloneTree(false), ClassRefDType);
if (!classRefDtypep) {
paramTypep->v3error(
"Attempting to extend using non-class");
} else {
classp = classRefDtypep->classp();
}
}
} else {
cextp->v3warn(E_UNSUPPORTED,
"Unsupported: " << foundp->nodep()->prettyTypeName()
<< " in AstClassExtends");
}
if (classp) {
UINFO(8, "Import to " << nodep << " from export class " << classp
<< endl);
if (classp == nodep) {
cextp->v3error("Attempting to extend class "
<< nodep->prettyNameQ() << " from itself");
} else {
AstPin* paramsp = cpackagerefp->paramsp();
if (paramsp) paramsp = paramsp->cloneTree(true);
const auto newp
= new AstClassRefDType{nodep->fileline(), classp, paramsp};
cextp->childDTypep(newp);
cextp->childDTypep(classRefDtypep);
classp->isExtended(true);
nodep->isExtended(true);
VSymEnt* const srcp = m_statep->getNodeSym(classp);
@ -3195,10 +3221,8 @@ private:
VL_DO_DANGLING(cpackagerefp->unlinkFrBack()->deleteTree(),
cpackagerefp);
}
ok = true;
}
}
if (!ok) {
} else {
const string suggest = m_statep->suggestSymFallback(
m_curSymp, cpackagerefp->name(), LinkNodeMatcherClass{});
cpackagerefp->v3error(

View File

@ -0,0 +1,5 @@
%Error-UNSUPPORTED: t/t_class_extends_alias_unsup.v:22:22: Unsupported: TYPEDEF 'foo_t' in AstClassExtends
22 | class bar extends foo_t;
| ^~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%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 2023 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(linter => 1);
lint(
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,38 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2023 by Antmicro Ltd.
// SPDX-License-Identifier: CC0-1.0
module t (/*AUTOARG*/
);
class foo;
int x = 1;
function int get_x;
return x;
endfunction
function int get_3;
return 3;
endfunction
endclass
typedef foo foo_t;
class bar extends foo_t;
endclass
bar bar_foo_t_i;
initial begin
bar_foo_t_i = new;
if (bar_foo_t_i.get_x() == 1 && bar_foo_t_i.get_3() == 3) begin
$write("*-* All Finished *-*\n");
$finish;
end
else begin
$stop;
end
end
endmodule

View File

@ -0,0 +1,5 @@
%Error: t/t_class_extends_aliased_real_bad.v:14:10: Attempting to extend using non-class
: ... In instance t
14 | bar #(real_t) bar_real_t;
| ^~~~~~
%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 2023 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(linter => 1);
lint(
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,19 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2023 by Antmicro Ltd.
// SPDX-License-Identifier: CC0-1.0
module t (/*AUTOARG*/);
class bar #(type T) extends T;
endclass
typedef real real_t;
bar #(real_t) bar_real_t;
initial begin
$stop;
end
endmodule

View File

@ -0,0 +1,5 @@
%Error: t/t_class_extends_int_param_bad.v:9:23: Attempting to extend using non-class
: ... In instance t
9 | class bar #(type T=int) extends T;
| ^~~
%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 2023 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(linter => 1);
lint(
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,15 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2023 by Antmicro Ltd.
// SPDX-License-Identifier: CC0-1.0
module t (/*AUTOARG*/);
class bar #(type T=int) extends T;
endclass
initial begin
$stop;
end
endmodule

View File

@ -0,0 +1,20 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2023 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;

View File

@ -0,0 +1,48 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2023 by Antmicro Ltd.
// SPDX-License-Identifier: CC0-1.0
module t (/*AUTOARG*/
);
class foo;
int x = 1;
function int get_x;
return x;
endfunction
function int get_3;
return 3;
endfunction
endclass
class bar #(type T=foo) extends T;
endclass
class baz;
int x = 2;
function int get_x;
return x;
endfunction
function int get_4;
return 4;
endfunction
endclass
bar bar_foo_i;
bar #(baz) bar_baz_i;
initial begin
bar_foo_i = new;
bar_baz_i = new;
if (bar_foo_i.get_x() == 1 && bar_foo_i.get_3() == 3 &&
bar_baz_i.get_x() == 2 && bar_baz_i.get_4() == 4) begin
$write("*-* All Finished *-*\n");
$finish;
end
else begin
$stop;
end
end
endmodule