Signed-off-by: Kamil Rakoczy <krakoczy@antmicro.com>
This commit is contained in:
parent
fbe8439eb8
commit
c840ffb0ae
|
@ -1013,6 +1013,7 @@ class LinkDotFindVisitor final : public VNVisitor {
|
||||||
VL_RESTORER(m_modBlockNum);
|
VL_RESTORER(m_modBlockNum);
|
||||||
VL_RESTORER(m_modWithNum);
|
VL_RESTORER(m_modWithNum);
|
||||||
VL_RESTORER(m_modArgNum);
|
VL_RESTORER(m_modArgNum);
|
||||||
|
VL_RESTORER(m_explicitNew);
|
||||||
{
|
{
|
||||||
UINFO(4, " Link Class: " << nodep << endl);
|
UINFO(4, " Link Class: " << nodep << endl);
|
||||||
VSymEnt* const upperSymp = m_curSymp;
|
VSymEnt* const upperSymp = m_curSymp;
|
||||||
|
@ -1176,12 +1177,39 @@ class LinkDotFindVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
// Change to appropriate package if extern declaration (vs definition)
|
// Change to appropriate package if extern declaration (vs definition)
|
||||||
if (nodep->classOrPackagep()) {
|
if (nodep->classOrPackagep()) {
|
||||||
|
// class-in-class
|
||||||
|
AstDot* const dotp = VN_CAST(nodep->classOrPackagep(), Dot);
|
||||||
AstClassOrPackageRef* const cpackagerefp
|
AstClassOrPackageRef* const cpackagerefp
|
||||||
= VN_CAST(nodep->classOrPackagep(), ClassOrPackageRef);
|
= VN_CAST(nodep->classOrPackagep(), ClassOrPackageRef);
|
||||||
if (!cpackagerefp) {
|
if (dotp) {
|
||||||
nodep->v3warn(E_UNSUPPORTED,
|
AstClassOrPackageRef* const lhsp = VN_AS(dotp->lhsp(), ClassOrPackageRef);
|
||||||
"Unsupported: extern function definition with class-in-class");
|
m_statep->resolveClassOrPackage(m_curSymp, lhsp, false,
|
||||||
} else {
|
"External definition :: reference");
|
||||||
|
AstClass* const lhsclassp = VN_CAST(lhsp->classOrPackageSkipp(), Class);
|
||||||
|
if (!lhsclassp) {
|
||||||
|
nodep->v3error("Extern declaration's scope is not a defined class");
|
||||||
|
} else {
|
||||||
|
m_curSymp = m_statep->getNodeSym(lhsclassp);
|
||||||
|
upSymp = m_curSymp;
|
||||||
|
AstClassOrPackageRef* const rhsp = VN_AS(dotp->rhsp(), ClassOrPackageRef);
|
||||||
|
m_statep->resolveClassOrPackage(m_curSymp, rhsp, false,
|
||||||
|
"External definition :: reference");
|
||||||
|
AstClass* const rhsclassp = VN_CAST(rhsp->classOrPackageSkipp(), Class);
|
||||||
|
if (!rhsclassp) {
|
||||||
|
nodep->v3error("Extern declaration's scope is not a defined class");
|
||||||
|
} else {
|
||||||
|
m_curSymp = m_statep->getNodeSym(rhsclassp);
|
||||||
|
upSymp = m_curSymp;
|
||||||
|
if (!nodep->isExternDef()) {
|
||||||
|
// Move it to proper spot under the target class
|
||||||
|
nodep->unlinkFrBack();
|
||||||
|
rhsclassp->addStmtsp(nodep);
|
||||||
|
nodep->isExternDef(true); // So we check there's a matching extern
|
||||||
|
nodep->classOrPackagep()->unlinkFrBack()->deleteTree();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (cpackagerefp) {
|
||||||
if (!cpackagerefp->classOrPackageSkipp()) {
|
if (!cpackagerefp->classOrPackageSkipp()) {
|
||||||
m_statep->resolveClassOrPackage(m_curSymp, cpackagerefp, false,
|
m_statep->resolveClassOrPackage(m_curSymp, cpackagerefp, false,
|
||||||
"External definition :: reference");
|
"External definition :: reference");
|
||||||
|
@ -1200,6 +1228,8 @@ class LinkDotFindVisitor final : public VNVisitor {
|
||||||
nodep->classOrPackagep()->unlinkFrBack()->deleteTree();
|
nodep->classOrPackagep()->unlinkFrBack()->deleteTree();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
v3fatalSrc("Unhandled extern function definition package");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Set the class as package for iteration
|
// Set the class as package for iteration
|
||||||
|
@ -4007,6 +4037,11 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||||
LINKDOT_VISIT_START();
|
LINKDOT_VISIT_START();
|
||||||
UINFO(5, indent() << "visit " << nodep << endl);
|
UINFO(5, indent() << "visit " << nodep << endl);
|
||||||
checkNoDot(nodep);
|
checkNoDot(nodep);
|
||||||
|
AstClass* const topclassp = VN_CAST(m_modp, Class);
|
||||||
|
if (nodep->isInterfaceClass() && topclassp && topclassp->isInterfaceClass()) {
|
||||||
|
nodep->v3error("Interface class shall not be nested within another interface class."
|
||||||
|
" (IEEE 1800-2023 8.26)");
|
||||||
|
}
|
||||||
VL_RESTORER(m_curSymp);
|
VL_RESTORER(m_curSymp);
|
||||||
VL_RESTORER(m_modSymp);
|
VL_RESTORER(m_modSymp);
|
||||||
VL_RESTORER(m_modp);
|
VL_RESTORER(m_modp);
|
||||||
|
|
|
@ -100,9 +100,15 @@ private:
|
||||||
if (local || prot) {
|
if (local || prot) {
|
||||||
const auto refClassp = VN_CAST(m_modp, Class);
|
const auto refClassp = VN_CAST(m_modp, Class);
|
||||||
const char* how = nullptr;
|
const char* how = nullptr;
|
||||||
if (local && defClassp && refClassp != defClassp) {
|
// Inner nested classes can access `local` or `protected` members of their outer class
|
||||||
|
const auto nestedAccess = [refClassp](const AstClass*, const AstNode* memberp) {
|
||||||
|
return memberp == refClassp;
|
||||||
|
};
|
||||||
|
if (local && defClassp
|
||||||
|
&& ((refClassp != defClassp) && !(defClassp->existsMember(nestedAccess)))) {
|
||||||
how = "'local'";
|
how = "'local'";
|
||||||
} else if (prot && defClassp && !AstClass::isClassExtendedFrom(refClassp, defClassp)) {
|
} else if (prot && defClassp && !AstClass::isClassExtendedFrom(refClassp, defClassp)
|
||||||
|
&& !(defClassp->existsMember(nestedAccess))) {
|
||||||
how = "'protected'";
|
how = "'protected'";
|
||||||
}
|
}
|
||||||
if (how) {
|
if (how) {
|
||||||
|
|
|
@ -7354,8 +7354,7 @@ class_item<nodep>: // ==IEEE: class_item
|
||||||
| class_method { $$ = $1; }
|
| class_method { $$ = $1; }
|
||||||
| class_constraint { $$ = $1; }
|
| class_constraint { $$ = $1; }
|
||||||
//
|
//
|
||||||
| class_declaration
|
| class_declaration { $$ = $1; }
|
||||||
{ $$ = nullptr; BBUNSUP($1, "Unsupported: class within class"); }
|
|
||||||
| timeunits_declaration { $$ = $1; }
|
| timeunits_declaration { $$ = $1; }
|
||||||
| covergroup_declaration
|
| covergroup_declaration
|
||||||
{ $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: covergroup within class"); }
|
{ $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: covergroup within class"); }
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
%Error-UNSUPPORTED: t/t_class_class.v:12:4: Unsupported: class within class
|
|
||||||
12 | class SubCls;
|
|
||||||
| ^~~~~
|
|
||||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
|
||||||
%Error: Exiting due to
|
|
|
@ -11,6 +11,8 @@ import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('simulator')
|
test.scenarios('simulator')
|
||||||
|
|
||||||
test.compile(fails=test.vlt_all, expect_filename=test.golden_filename)
|
test.compile()
|
||||||
|
|
||||||
|
test.execute()
|
||||||
|
|
||||||
test.passes()
|
test.passes()
|
||||||
|
|
|
@ -31,5 +31,8 @@ module t (/*AUTOARG*/);
|
||||||
if (c.imemberb != 20) $stop;
|
if (c.imemberb != 20) $stop;
|
||||||
if (c.sc.smembera != 30) $stop;
|
if (c.sc.smembera != 30) $stop;
|
||||||
if (c.sc.smemberb != 40) $stop;
|
if (c.sc.smemberb != 40) $stop;
|
||||||
|
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -11,6 +11,9 @@
|
||||||
`define check_ne(lhs, rhs) `check_comp(lhs, rhs, ==, 1'b0) `check_comp(lhs, rhs, !=, 1'b1)
|
`define check_ne(lhs, rhs) `check_comp(lhs, rhs, ==, 1'b0) `check_comp(lhs, rhs, !=, 1'b1)
|
||||||
|
|
||||||
class Cls;
|
class Cls;
|
||||||
|
class InnerCls;
|
||||||
|
int j;
|
||||||
|
endclass
|
||||||
int i;
|
int i;
|
||||||
endclass
|
endclass
|
||||||
|
|
||||||
|
@ -22,14 +25,25 @@ module t;
|
||||||
Cls a = new;
|
Cls a = new;
|
||||||
Cls b = new;
|
Cls b = new;
|
||||||
ExtendCls ext = new;
|
ExtendCls ext = new;
|
||||||
|
Cls::InnerCls ia = new;
|
||||||
|
Cls::InnerCls ib = new;
|
||||||
|
ExtendCls::InnerCls iext = new;
|
||||||
`check_ne(a, b)
|
`check_ne(a, b)
|
||||||
`check_ne(a, ext)
|
`check_ne(a, ext)
|
||||||
`check_ne(ext, a)
|
`check_ne(ext, a)
|
||||||
|
`check_ne(ia, ib)
|
||||||
|
`check_ne(ia, iext)
|
||||||
|
`check_ne(iext, ia)
|
||||||
a = b;
|
a = b;
|
||||||
|
ia = ib;
|
||||||
`check_eq(a, b)
|
`check_eq(a, b)
|
||||||
|
`check_eq(ia, ib)
|
||||||
a = ext;
|
a = ext;
|
||||||
|
ia = iext;
|
||||||
`check_eq(a, ext)
|
`check_eq(a, ext)
|
||||||
`check_eq(ext, a)
|
`check_eq(ext, a)
|
||||||
|
`check_eq(ia, iext)
|
||||||
|
`check_eq(iext, ia)
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,21 +5,55 @@
|
||||||
// SPDX-License-Identifier: CC0-1.0
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
class Base0;
|
class Base0;
|
||||||
|
class BaseInnerOnly;
|
||||||
|
int inneronly;
|
||||||
|
function new();
|
||||||
|
inneronly = 10;
|
||||||
|
if (inneronly != 10) $stop;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class BaseInnerOver;
|
||||||
|
int innerover;
|
||||||
|
function new();
|
||||||
|
innerover = 10;
|
||||||
|
if (innerover != 10) $stop;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
int baseonly;
|
int baseonly;
|
||||||
int baseover;
|
int baseover;
|
||||||
|
BaseInnerOnly inneronly = new;
|
||||||
|
BaseInnerOver innerover = new;
|
||||||
|
|
||||||
function void b_set_bo(int v); baseover = v; endfunction
|
function void b_set_bo(int v); baseover = v; endfunction
|
||||||
function int b_get_bo(); return baseover; endfunction
|
function int b_get_bo(); return baseover; endfunction
|
||||||
function int get_bo(); return baseover; endfunction
|
function int get_bo(); return baseover; endfunction
|
||||||
|
function void b_set_io(int v); innerover.innerover = v; endfunction
|
||||||
|
function int b_get_io(); return innerover.innerover; endfunction
|
||||||
|
function int get_io(); return innerover.innerover; endfunction
|
||||||
endclass
|
endclass
|
||||||
|
|
||||||
class Ext extends Base0;
|
class Ext extends Base0;
|
||||||
|
class BaseInnerOver;
|
||||||
|
int innerover;
|
||||||
|
function new();
|
||||||
|
innerover = 20;
|
||||||
|
if (innerover != 20) $stop;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
int baseover;
|
int baseover;
|
||||||
int extonly;
|
int extonly;
|
||||||
|
BaseInnerOnly inneronly = new;
|
||||||
|
BaseInnerOver innerover = new;
|
||||||
|
|
||||||
function void e_set_bo(int v); baseover = v; endfunction
|
function void e_set_bo(int v); baseover = v; endfunction
|
||||||
function int e_get_bo(); return baseover; endfunction
|
function int e_get_bo(); return baseover; endfunction
|
||||||
function int get_bo(); return baseover; endfunction
|
function int get_bo(); return baseover; endfunction
|
||||||
|
function void e_set_io(int v); innerover.innerover = v; endfunction
|
||||||
|
function int e_get_io(); return innerover.innerover; endfunction
|
||||||
|
function int get_io(); return innerover.innerover; endfunction
|
||||||
endclass
|
endclass
|
||||||
|
|
||||||
module t (/*AUTOARG*/);
|
module t (/*AUTOARG*/);
|
||||||
|
@ -29,15 +63,24 @@ module t (/*AUTOARG*/);
|
||||||
c.baseonly = 10;
|
c.baseonly = 10;
|
||||||
c.baseover = 20;
|
c.baseover = 20;
|
||||||
c.extonly = 30;
|
c.extonly = 30;
|
||||||
|
c.inneronly.inneronly = 40;
|
||||||
|
c.innerover.innerover = 50;
|
||||||
if (c.baseonly != 10) $stop;
|
if (c.baseonly != 10) $stop;
|
||||||
if (c.baseover != 20) $stop;
|
if (c.baseover != 20) $stop;
|
||||||
if (c.extonly != 30) $stop;
|
if (c.extonly != 30) $stop;
|
||||||
|
if (c.inneronly.inneronly != 40) $stop;
|
||||||
|
if (c.innerover.innerover != 50) $stop;
|
||||||
|
|
||||||
c.b_set_bo(100);
|
c.b_set_bo(100);
|
||||||
c.e_set_bo(200);
|
c.e_set_bo(200);
|
||||||
|
c.b_set_io(300);
|
||||||
|
c.e_set_io(400);
|
||||||
if (c.b_get_bo() != 100) $stop;
|
if (c.b_get_bo() != 100) $stop;
|
||||||
if (c.e_get_bo() != 200) $stop;
|
if (c.e_get_bo() != 200) $stop;
|
||||||
if (c.get_bo() != 200) $stop;
|
if (c.get_bo() != 200) $stop;
|
||||||
|
if (c.b_get_io() != 300) $stop;
|
||||||
|
if (c.e_get_io() != 400) $stop;
|
||||||
|
if (c.get_io() != 400) $stop;
|
||||||
|
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
|
|
|
@ -6,22 +6,59 @@
|
||||||
|
|
||||||
package Pkg;
|
package Pkg;
|
||||||
class Base0;
|
class Base0;
|
||||||
|
class BaseInnerOnly;
|
||||||
|
int inneronly;
|
||||||
|
function new();
|
||||||
|
inneronly = 10;
|
||||||
|
if (inneronly != 10) $stop;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class BaseInnerOver;
|
||||||
|
int innerover;
|
||||||
|
function new();
|
||||||
|
innerover = 10;
|
||||||
|
if (innerover != 10) $stop;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
int baseonly;
|
int baseonly;
|
||||||
int baseover;
|
int baseover;
|
||||||
|
BaseInnerOnly inneronly = new;
|
||||||
|
BaseInnerOver innerover = new;
|
||||||
|
|
||||||
function void b_set_bo(int v); baseover = v; endfunction
|
function void b_set_bo(int v); baseover = v; endfunction
|
||||||
function int b_get_bo(); return baseover; endfunction
|
function int b_get_bo(); return baseover; endfunction
|
||||||
function int get_bo(); return baseover; endfunction
|
function int get_bo(); return baseover; endfunction
|
||||||
|
function void b_set_io(int v); innerover.innerover = v; endfunction
|
||||||
|
function int b_get_io(); return innerover.innerover; endfunction
|
||||||
|
function int get_io(); return innerover.innerover; endfunction
|
||||||
endclass
|
endclass
|
||||||
endpackage
|
endpackage
|
||||||
|
|
||||||
|
// We need to import Base0, as verilator currently doesn't support
|
||||||
|
// multiple `::` references, but we would need to do that to reference
|
||||||
|
// `BaseInnerOnly` class inside `Ext` class.
|
||||||
|
import Pkg::Base0;
|
||||||
class Ext extends Pkg::Base0;
|
class Ext extends Pkg::Base0;
|
||||||
|
class BaseInnerOver;
|
||||||
|
int innerover;
|
||||||
|
function new();
|
||||||
|
innerover = 20;
|
||||||
|
if (innerover != 20) $stop;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
int baseover;
|
int baseover;
|
||||||
int extonly;
|
int extonly;
|
||||||
|
BaseInnerOnly inneronly = new;
|
||||||
|
BaseInnerOver innerover = new;
|
||||||
|
|
||||||
function void e_set_bo(int v); baseover = v; endfunction
|
function void e_set_bo(int v); baseover = v; endfunction
|
||||||
function int e_get_bo(); return baseover; endfunction
|
function int e_get_bo(); return baseover; endfunction
|
||||||
function int get_bo(); return baseover; endfunction
|
function int get_bo(); return baseover; endfunction
|
||||||
|
function void e_set_io(int v); innerover.innerover = v; endfunction
|
||||||
|
function int e_get_io(); return innerover.innerover; endfunction
|
||||||
|
function int get_io(); return innerover.innerover; endfunction
|
||||||
endclass
|
endclass
|
||||||
|
|
||||||
module t (/*AUTOARG*/);
|
module t (/*AUTOARG*/);
|
||||||
|
@ -31,15 +68,24 @@ module t (/*AUTOARG*/);
|
||||||
c.baseonly = 10;
|
c.baseonly = 10;
|
||||||
c.baseover = 20;
|
c.baseover = 20;
|
||||||
c.extonly = 30;
|
c.extonly = 30;
|
||||||
|
c.inneronly.inneronly = 40;
|
||||||
|
c.innerover.innerover = 50;
|
||||||
if (c.baseonly != 10) $stop;
|
if (c.baseonly != 10) $stop;
|
||||||
if (c.baseover != 20) $stop;
|
if (c.baseover != 20) $stop;
|
||||||
if (c.extonly != 30) $stop;
|
if (c.extonly != 30) $stop;
|
||||||
|
if (c.inneronly.inneronly != 40) $stop;
|
||||||
|
if (c.innerover.innerover != 50) $stop;
|
||||||
|
|
||||||
c.b_set_bo(100);
|
c.b_set_bo(100);
|
||||||
c.e_set_bo(200);
|
c.e_set_bo(200);
|
||||||
|
c.b_set_io(300);
|
||||||
|
c.e_set_io(400);
|
||||||
if (c.b_get_bo() != 100) $stop;
|
if (c.b_get_bo() != 100) $stop;
|
||||||
if (c.e_get_bo() != 200) $stop;
|
if (c.e_get_bo() != 200) $stop;
|
||||||
if (c.get_bo() != 200) $stop;
|
if (c.get_bo() != 200) $stop;
|
||||||
|
if (c.b_get_io() != 300) $stop;
|
||||||
|
if (c.e_get_io() != 400) $stop;
|
||||||
|
if (c.get_io() != 400) $stop;
|
||||||
|
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
|
|
|
@ -8,26 +8,53 @@ module t (/*AUTOARG*/
|
||||||
);
|
);
|
||||||
|
|
||||||
class Foo;
|
class Foo;
|
||||||
|
class InnerFoo;
|
||||||
|
int y = 10;
|
||||||
|
function int get_y;
|
||||||
|
return y;
|
||||||
|
endfunction
|
||||||
|
function int get_30;
|
||||||
|
return 30;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
int x = 1;
|
int x = 1;
|
||||||
|
InnerFoo foo = new;
|
||||||
function int get_x;
|
function int get_x;
|
||||||
return x;
|
return x;
|
||||||
endfunction
|
endfunction
|
||||||
function int get_3;
|
function int get_3;
|
||||||
return 3;
|
return 3;
|
||||||
endfunction
|
endfunction
|
||||||
|
function InnerFoo get_foo;
|
||||||
|
return foo;
|
||||||
|
endfunction
|
||||||
endclass
|
endclass
|
||||||
|
|
||||||
class Bar #(type T=Foo) extends T;
|
class Bar #(type T=Foo) extends T;
|
||||||
endclass
|
endclass
|
||||||
|
|
||||||
class Baz;
|
class Baz;
|
||||||
|
class InnerFoo;
|
||||||
|
int y = 20;
|
||||||
|
function int get_y;
|
||||||
|
return y;
|
||||||
|
endfunction
|
||||||
|
function int get_40;
|
||||||
|
return 40;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
int x = 2;
|
int x = 2;
|
||||||
|
InnerFoo foo = new;
|
||||||
function int get_x;
|
function int get_x;
|
||||||
return x;
|
return x;
|
||||||
endfunction
|
endfunction
|
||||||
function int get_4;
|
function int get_4;
|
||||||
return 4;
|
return 4;
|
||||||
endfunction
|
endfunction
|
||||||
|
function InnerFoo get_foo;
|
||||||
|
return foo;
|
||||||
|
endfunction
|
||||||
endclass
|
endclass
|
||||||
|
|
||||||
class ExtendBar extends Bar#();
|
class ExtendBar extends Bar#();
|
||||||
|
@ -71,6 +98,9 @@ module t (/*AUTOARG*/
|
||||||
function int get_x_of_item(int i);
|
function int get_x_of_item(int i);
|
||||||
return q[i].x;
|
return q[i].x;
|
||||||
endfunction
|
endfunction
|
||||||
|
function int get_y_of_item(int i);
|
||||||
|
return q[i].get_foo().get_y();
|
||||||
|
endfunction
|
||||||
endclass
|
endclass
|
||||||
|
|
||||||
Bar #() bar_foo_i;
|
Bar #() bar_foo_i;
|
||||||
|
@ -93,8 +123,12 @@ module t (/*AUTOARG*/
|
||||||
|
|
||||||
if (bar_foo_i.get_x() != 1) $stop;
|
if (bar_foo_i.get_x() != 1) $stop;
|
||||||
if (bar_foo_i.get_3() != 3) $stop;
|
if (bar_foo_i.get_3() != 3) $stop;
|
||||||
|
if (bar_foo_i.get_foo().get_y() != 10) $stop;
|
||||||
|
if (bar_foo_i.get_foo().get_30() != 30) $stop;
|
||||||
if (bar_baz_i.get_x() != 2) $stop;
|
if (bar_baz_i.get_x() != 2) $stop;
|
||||||
if (bar_baz_i.get_4() != 4) $stop;
|
if (bar_baz_i.get_4() != 4) $stop;
|
||||||
|
if (bar_baz_i.get_foo().get_y() != 20) $stop;
|
||||||
|
if (bar_baz_i.get_foo().get_40() != 40) $stop;
|
||||||
if (extend_bar_i.get_x() != 1) $stop;
|
if (extend_bar_i.get_x() != 1) $stop;
|
||||||
if (extend_bar_i.get_6() != 6) $stop;
|
if (extend_bar_i.get_6() != 6) $stop;
|
||||||
if (extend_bar_i.get_x() != 1) $stop;
|
if (extend_bar_i.get_x() != 1) $stop;
|
||||||
|
@ -106,6 +140,7 @@ module t (/*AUTOARG*/
|
||||||
if (extend_extend_bar_i.get_x() != 1) $stop;
|
if (extend_extend_bar_i.get_x() != 1) $stop;
|
||||||
if (extend_extend_bar_i.get_12() != 12) $stop;
|
if (extend_extend_bar_i.get_12() != 12) $stop;
|
||||||
if (extend_foo_dict_i.get_x_of_item(1) != 1) $stop;
|
if (extend_foo_dict_i.get_x_of_item(1) != 1) $stop;
|
||||||
|
if (extend_foo_dict_i.get_y_of_item(1) != 10) $stop;
|
||||||
|
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
|
|
|
@ -7,7 +7,20 @@
|
||||||
typedef class Cls;
|
typedef class Cls;
|
||||||
|
|
||||||
class Base;
|
class Base;
|
||||||
|
class BaseInner;
|
||||||
|
int value = 10;
|
||||||
|
function void test;
|
||||||
|
if (value != 10) $stop;
|
||||||
|
if (this.value != 10) $stop;
|
||||||
|
value = 20;
|
||||||
|
if (value != 20) $stop;
|
||||||
|
this.value = 30;
|
||||||
|
if (value != 30) $stop;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
int value = 1;
|
int value = 1;
|
||||||
|
BaseInner inner = new;
|
||||||
function void test;
|
function void test;
|
||||||
if (value != 1) $stop;
|
if (value != 1) $stop;
|
||||||
if (this.value != 1) $stop;
|
if (this.value != 1) $stop;
|
||||||
|
@ -19,7 +32,25 @@ class Base;
|
||||||
endclass
|
endclass
|
||||||
|
|
||||||
class Cls extends Base;
|
class Cls extends Base;
|
||||||
|
class BaseInner extends Base::BaseInner;
|
||||||
|
int value = 100;
|
||||||
|
function void test;
|
||||||
|
if (value != 100) $stop;
|
||||||
|
if (this.value != 100) $stop;
|
||||||
|
if (super.value != 10) $stop;
|
||||||
|
super.test();
|
||||||
|
if (value != 100) $stop;
|
||||||
|
if (this.value != 100) $stop;
|
||||||
|
if (super.value != 30) $stop;
|
||||||
|
value = 200;
|
||||||
|
if (value != 200) $stop;
|
||||||
|
this.value = 300;
|
||||||
|
if (value != 300) $stop;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
int value = 20;
|
int value = 20;
|
||||||
|
BaseInner inner = new;
|
||||||
function void test;
|
function void test;
|
||||||
if (value != 20) $stop;
|
if (value != 20) $stop;
|
||||||
if (this.value != 20) $stop;
|
if (this.value != 20) $stop;
|
||||||
|
@ -31,7 +62,9 @@ class Cls extends Base;
|
||||||
super.value = 9;
|
super.value = 9;
|
||||||
this.value = 29;
|
this.value = 29;
|
||||||
if (super.value != 9) $stop;
|
if (super.value != 9) $stop;
|
||||||
if (value != 29) $stop;;
|
if (value != 29) $stop;
|
||||||
|
|
||||||
|
inner.test();
|
||||||
endfunction
|
endfunction
|
||||||
endclass
|
endclass
|
||||||
|
|
||||||
|
|
|
@ -7,15 +7,24 @@
|
||||||
typedef class Cls;
|
typedef class Cls;
|
||||||
|
|
||||||
class Base;
|
class Base;
|
||||||
|
class Inner;
|
||||||
|
int value = 10;
|
||||||
|
function void testBaseInner;
|
||||||
|
if (value != 10) $stop;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
int value = 1;
|
int value = 1;
|
||||||
|
Inner inner = new;
|
||||||
function void testBase;
|
function void testBase;
|
||||||
if (value != 1) $stop;
|
if (value != 1) $stop;
|
||||||
|
if (inner.value != 10) $stop;
|
||||||
endfunction
|
endfunction
|
||||||
endclass
|
endclass
|
||||||
|
|
||||||
class Cls extends Base;
|
class Cls extends Base;
|
||||||
function void testDerived;
|
function void testDerived;
|
||||||
if (value != 1) $stop;
|
if (value != 1) $stop;
|
||||||
|
if (inner.value != 10) $stop;
|
||||||
endfunction
|
endfunction
|
||||||
endclass
|
endclass
|
||||||
|
|
||||||
|
@ -25,6 +34,7 @@ module t (/*AUTOARG*/);
|
||||||
c = new;
|
c = new;
|
||||||
c.testBase();
|
c.testBase();
|
||||||
c.testDerived();
|
c.testDerived();
|
||||||
|
c.inner.testBaseInner();
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,6 +13,16 @@ class Cls;
|
||||||
extern task ext_t_np;
|
extern task ext_t_np;
|
||||||
extern task ext_t_p();
|
extern task ext_t_p();
|
||||||
extern task ext_t_i(int in);
|
extern task ext_t_i(int in);
|
||||||
|
class SubCls;
|
||||||
|
int value;
|
||||||
|
extern function int ext_f_np;
|
||||||
|
extern function int ext_f_p();
|
||||||
|
extern function int ext_f_i(int in);
|
||||||
|
extern static function int get_10();
|
||||||
|
extern task ext_t_np;
|
||||||
|
extern task ext_t_p();
|
||||||
|
extern task ext_t_i(int in);
|
||||||
|
endclass
|
||||||
endclass
|
endclass
|
||||||
|
|
||||||
function int Cls::ext_f_np;
|
function int Cls::ext_f_np;
|
||||||
|
@ -42,15 +52,51 @@ task Cls::ext_t_i(int in);
|
||||||
value = in;
|
value = in;
|
||||||
endtask
|
endtask
|
||||||
|
|
||||||
|
function int Cls::SubCls::ext_f_np;
|
||||||
|
return 10;
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function int Cls::SubCls::ext_f_p();
|
||||||
|
return value;
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function int Cls::SubCls::ext_f_i(int in);
|
||||||
|
return in+10;
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function int Cls::SubCls::get_10();
|
||||||
|
return 10;
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
task Cls::SubCls::ext_t_np();
|
||||||
|
$write("Cls::SubCls::ext_t_np\n");
|
||||||
|
endtask
|
||||||
|
task Cls::SubCls::ext_t_p();
|
||||||
|
$write("Cls::SubCls::ext_t_p\n");
|
||||||
|
endtask
|
||||||
|
task Cls::SubCls::ext_t_i(int in);
|
||||||
|
if (in != 20) $stop;
|
||||||
|
value = in;
|
||||||
|
endtask
|
||||||
|
|
||||||
|
|
||||||
module t (/*AUTOARG*/);
|
module t (/*AUTOARG*/);
|
||||||
initial begin
|
initial begin
|
||||||
Cls c = new;
|
Cls c = new;
|
||||||
|
Cls::SubCls subc = new;
|
||||||
c.ext_t_i(2);
|
c.ext_t_i(2);
|
||||||
c.ext_t_np();
|
|
||||||
c.ext_t_p();
|
|
||||||
if (c.ext_f_np() != 1) $stop;
|
if (c.ext_f_np() != 1) $stop;
|
||||||
if (c.ext_f_p() != 2) $stop;
|
if (c.ext_f_p() != 2) $stop;
|
||||||
if (c.ext_f_i(10) != 11) $stop;
|
if (c.ext_f_i(10) != 11) $stop;
|
||||||
if (Cls::get_1() != 1) $stop;
|
if (Cls::get_1() != 1) $stop;
|
||||||
|
subc.ext_t_i(20);
|
||||||
|
if (subc.ext_f_np() != 10) $stop;
|
||||||
|
if (subc.ext_f_p() != 20) $stop;
|
||||||
|
if (subc.ext_f_i(11) != 21) $stop;
|
||||||
|
if (Cls::SubCls::get_10() != 10) $stop;
|
||||||
|
subc.ext_t_np();
|
||||||
|
subc.ext_t_p();
|
||||||
|
c.ext_t_np();
|
||||||
|
c.ext_t_p();
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -31,6 +31,34 @@ class Cls;
|
||||||
Cls::s_loc(); // Ok
|
Cls::s_loc(); // Ok
|
||||||
Cls::s_prot(); // Ok
|
Cls::s_prot(); // Ok
|
||||||
endtask
|
endtask
|
||||||
|
class InnerCls;
|
||||||
|
typedef enum {A = 10, B = 20, C = 30} en_t;
|
||||||
|
|
||||||
|
int m_pub = 1;
|
||||||
|
local int m_loc = 2;
|
||||||
|
protected int m_prot = B;
|
||||||
|
task f_pub; endtask
|
||||||
|
local task f_loc; endtask
|
||||||
|
protected task f_prot; endtask
|
||||||
|
static task s_pub; endtask
|
||||||
|
static local task s_loc; endtask
|
||||||
|
static protected task s_prot; endtask
|
||||||
|
task check;
|
||||||
|
Cls o;
|
||||||
|
if (m_pub != 1) $stop;
|
||||||
|
if (m_loc != 2) $stop;
|
||||||
|
if (m_prot != 20) $stop;
|
||||||
|
f_pub(); // Ok
|
||||||
|
f_loc(); // Ok
|
||||||
|
f_prot(); // Ok
|
||||||
|
s_pub(); // Ok
|
||||||
|
s_loc(); // Ok
|
||||||
|
s_prot(); // Ok
|
||||||
|
Cls::s_pub(); // Ok
|
||||||
|
Cls::s_loc(); // Ok
|
||||||
|
Cls::s_prot(); // Ok
|
||||||
|
endtask
|
||||||
|
endclass
|
||||||
endclass
|
endclass
|
||||||
|
|
||||||
class Ext extends Cls;
|
class Ext extends Cls;
|
||||||
|
@ -44,27 +72,52 @@ class Ext extends Cls;
|
||||||
Cls::s_pub(); // Ok
|
Cls::s_pub(); // Ok
|
||||||
Cls::s_prot(); // Ok
|
Cls::s_prot(); // Ok
|
||||||
endtask
|
endtask
|
||||||
|
class ExtInner extends Cls::InnerCls;
|
||||||
|
task check;
|
||||||
|
if (m_pub != 1) $stop;
|
||||||
|
if (m_prot != 20) $stop;
|
||||||
|
f_pub(); // Ok
|
||||||
|
f_prot(); // Ok
|
||||||
|
s_pub(); // Ok
|
||||||
|
s_prot(); // Ok
|
||||||
|
Cls::InnerCls::s_pub(); // Ok
|
||||||
|
Cls::InnerCls::s_prot(); // Ok
|
||||||
|
endtask
|
||||||
|
endclass
|
||||||
endclass
|
endclass
|
||||||
|
|
||||||
module t (/*AUTOARG*/);
|
module t (/*AUTOARG*/);
|
||||||
const Cls mod_c = new;
|
const Cls mod_c = new;
|
||||||
|
const Cls::InnerCls imod_c = new;
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
Cls c;
|
Cls c;
|
||||||
|
Cls::InnerCls i;
|
||||||
Ext e;
|
Ext e;
|
||||||
|
Ext::ExtInner ei;
|
||||||
if (c.A != 10) $stop;
|
if (c.A != 10) $stop;
|
||||||
|
if (i.A != 10) $stop;
|
||||||
c = new;
|
c = new;
|
||||||
|
i = new;
|
||||||
e = new;
|
e = new;
|
||||||
|
ei = new;
|
||||||
if (c.m_pub != 1) $stop;
|
if (c.m_pub != 1) $stop;
|
||||||
|
if (i.m_pub != 1) $stop;
|
||||||
//
|
//
|
||||||
if (mod_c.A != 10) $stop;
|
if (mod_c.A != 10) $stop;
|
||||||
|
if (imod_c.A != 10) $stop;
|
||||||
//
|
//
|
||||||
c.check();
|
c.check();
|
||||||
|
i.check();
|
||||||
e.check();
|
e.check();
|
||||||
|
ei.check();
|
||||||
//
|
//
|
||||||
Cls::s_pub(); // Ok
|
Cls::s_pub(); // Ok
|
||||||
|
Cls::InnerCls::s_pub(); // Ok
|
||||||
c.s_pub(); // Ok
|
c.s_pub(); // Ok
|
||||||
|
i.s_pub(); // Ok
|
||||||
e.s_pub(); // Ok
|
e.s_pub(); // Ok
|
||||||
|
ei.s_pub(); // Ok
|
||||||
//
|
//
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
%Error-ENCAPSULATED: t/t_class_local_nested_bad.v:14:22: 'name' is hidden as 'local' within this context (IEEE 1800-2023 8.18)
|
||||||
|
: ... note: In instance 't'
|
||||||
|
14 | name = Node::name;
|
||||||
|
| ^~~~
|
||||||
|
t/t_class_local_nested_bad.v:14:22: ... Location of definition
|
||||||
|
9 | static local string name;
|
||||||
|
| ^~~~
|
||||||
|
... For error description see https://verilator.org/warn/ENCAPSULATED?v=latest
|
||||||
|
%Error: Exiting due to
|
|
@ -0,0 +1,16 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# 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
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('simulator')
|
||||||
|
|
||||||
|
test.compile(fails=test.vlt_all, expect_filename=test.golden_filename)
|
||||||
|
|
||||||
|
test.passes()
|
|
@ -0,0 +1,25 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2025 by Antmicro.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
class NodeList;
|
||||||
|
class Node;
|
||||||
|
static local string name;
|
||||||
|
endclass
|
||||||
|
|
||||||
|
string name;
|
||||||
|
function new();
|
||||||
|
name = Node::name;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
module t(/*AUTOARG*/);
|
||||||
|
initial begin
|
||||||
|
NodeList n = new;
|
||||||
|
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
|
@ -7,8 +7,13 @@
|
||||||
module t (/*AUTOARG*/);
|
module t (/*AUTOARG*/);
|
||||||
|
|
||||||
class Cls;
|
class Cls;
|
||||||
|
class Inner;
|
||||||
|
int imemberinnera;
|
||||||
|
int imemberinnerb;
|
||||||
|
endclass
|
||||||
int imembera;
|
int imembera;
|
||||||
int imemberb;
|
int imemberb;
|
||||||
|
Inner innermemberc;
|
||||||
endclass : Cls
|
endclass : Cls
|
||||||
|
|
||||||
class Dead;
|
class Dead;
|
||||||
|
@ -18,10 +23,16 @@ endclass
|
||||||
Cls c;
|
Cls c;
|
||||||
if (c != null) $stop;
|
if (c != null) $stop;
|
||||||
c = new;
|
c = new;
|
||||||
|
if (c.innermemberc != null) $stop;
|
||||||
|
c.innermemberc = new;
|
||||||
c.imembera = 10;
|
c.imembera = 10;
|
||||||
c.imemberb = 20;
|
c.imemberb = 20;
|
||||||
|
c.innermemberc.imemberinnera = 30;
|
||||||
|
c.innermemberc.imemberinnerb = 40;
|
||||||
if (c.imembera != 10) $stop;
|
if (c.imembera != 10) $stop;
|
||||||
if (c.imemberb != 20) $stop;
|
if (c.imemberb != 20) $stop;
|
||||||
|
if (c.innermemberc.imemberinnera != 30) $stop;
|
||||||
|
if (c.innermemberc.imemberinnerb != 40) $stop;
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# 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
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('simulator')
|
||||||
|
|
||||||
|
test.compile(verilator_flags2=["--exe --main"])
|
||||||
|
|
||||||
|
test.execute()
|
||||||
|
|
||||||
|
test.passes()
|
|
@ -0,0 +1,90 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2025 by Antmicro.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
class NodeList;
|
||||||
|
class Node;
|
||||||
|
string name;
|
||||||
|
Node link;
|
||||||
|
|
||||||
|
function new();
|
||||||
|
name = "node";
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
Node head;
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class NodeTree;
|
||||||
|
class Node;
|
||||||
|
int id;
|
||||||
|
Node link;
|
||||||
|
endclass
|
||||||
|
|
||||||
|
Node root;
|
||||||
|
endclass
|
||||||
|
|
||||||
|
// Based on IEEE 1800-2017 section 8.23 Nested classes
|
||||||
|
class Outer;
|
||||||
|
int outerProp;
|
||||||
|
local int outerLocalProp;
|
||||||
|
static int outerStaticProp;
|
||||||
|
static local int outerLocalStaticProp;
|
||||||
|
|
||||||
|
class Inner;
|
||||||
|
function void innerMethod(Outer h);
|
||||||
|
outerStaticProp = 1;
|
||||||
|
outerLocalStaticProp = 1;
|
||||||
|
h.outerProp = 1;
|
||||||
|
h.outerLocalProp = 1;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
endclass
|
||||||
|
|
||||||
|
|
||||||
|
module t(/*AUTOARG*/);
|
||||||
|
initial begin
|
||||||
|
NodeList n = new;
|
||||||
|
NodeList::Node n1 = new;
|
||||||
|
NodeList::Node n2 = new;
|
||||||
|
NodeTree tr = new;
|
||||||
|
NodeTree::Node t1 = new;
|
||||||
|
NodeTree::Node t2 = new;
|
||||||
|
Outer o = new;
|
||||||
|
Outer::Inner i = new;
|
||||||
|
|
||||||
|
i.innerMethod(o);
|
||||||
|
|
||||||
|
if(o.outerProp != 1) $stop;
|
||||||
|
if(Outer::outerStaticProp != 1) $stop;
|
||||||
|
|
||||||
|
if (n1.name != "node") $stop;
|
||||||
|
|
||||||
|
n1.name = "n1";
|
||||||
|
if (n1.name != "n1") $stop;
|
||||||
|
|
||||||
|
n2.name = "n2";
|
||||||
|
if (n2.name != "n2") $stop;
|
||||||
|
|
||||||
|
n.head = n1;
|
||||||
|
n1.link = n2;
|
||||||
|
if (n.head.name != "n1") $stop;
|
||||||
|
if (n.head.link.name != "n2") $stop;
|
||||||
|
|
||||||
|
t1.id = 1;
|
||||||
|
if (t1.id != 1) $stop;
|
||||||
|
|
||||||
|
t2.id = 2;
|
||||||
|
if (t2.id != 2) $stop;
|
||||||
|
|
||||||
|
tr.root = t1;
|
||||||
|
t1.link = t2;
|
||||||
|
if (tr.root.id != 1) $stop;
|
||||||
|
if (tr.root.link.id != 2) $stop;
|
||||||
|
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
|
@ -11,6 +11,17 @@ class ClsNoArg;
|
||||||
imembera = 5;
|
imembera = 5;
|
||||||
if (other != 6) $stop;
|
if (other != 6) $stop;
|
||||||
endfunction : new
|
endfunction : new
|
||||||
|
class InnerNoArg;
|
||||||
|
const int imembera;
|
||||||
|
function new();
|
||||||
|
int other = other_func();
|
||||||
|
imembera = 5;
|
||||||
|
if (other != 6) $stop;
|
||||||
|
endfunction
|
||||||
|
function int other_func();
|
||||||
|
return 6;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
function int other_func();
|
function int other_func();
|
||||||
return 6;
|
return 6;
|
||||||
endfunction
|
endfunction
|
||||||
|
@ -52,6 +63,7 @@ module t (/*AUTOARG*/);
|
||||||
ClsArg c2;
|
ClsArg c2;
|
||||||
Cls2Arg c3;
|
Cls2Arg c3;
|
||||||
Cls2Arg c4;
|
Cls2Arg c4;
|
||||||
|
ClsNoArg::InnerNoArg c5 = new;
|
||||||
|
|
||||||
c1 = new;
|
c1 = new;
|
||||||
if (c1.imembera != 5) $stop;
|
if (c1.imembera != 5) $stop;
|
||||||
|
@ -72,6 +84,9 @@ module t (/*AUTOARG*/);
|
||||||
if (c4.imembera != 6) $stop;
|
if (c4.imembera != 6) $stop;
|
||||||
if (c4.imemberb != 9) $stop;
|
if (c4.imemberb != 9) $stop;
|
||||||
|
|
||||||
|
c5 = new;
|
||||||
|
if (c5.imembera != 5) $stop;
|
||||||
|
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
|
|
@ -42,6 +42,9 @@ class Cls #(parameter PBASE = 12);
|
||||||
return PBASE;
|
return PBASE;
|
||||||
endfunction
|
endfunction
|
||||||
typedef enum { E_PBASE = PBASE } enum_t;
|
typedef enum { E_PBASE = PBASE } enum_t;
|
||||||
|
class ClsInner;
|
||||||
|
bit [PBASE-1:0] member;
|
||||||
|
endclass
|
||||||
endclass
|
endclass
|
||||||
|
|
||||||
typedef Cls#(8) Cls8_t;
|
typedef Cls#(8) Cls8_t;
|
||||||
|
@ -136,6 +139,8 @@ module t (/*AUTOARG*/);
|
||||||
Cls c12;
|
Cls c12;
|
||||||
Cls #(.PBASE(4)) c4;
|
Cls #(.PBASE(4)) c4;
|
||||||
Cls8_t c8;
|
Cls8_t c8;
|
||||||
|
Cls#()::ClsInner ci;
|
||||||
|
Cls#(8)::ClsInner ci8;
|
||||||
Wrap #(.P(16)) w16;
|
Wrap #(.P(16)) w16;
|
||||||
Wrap2 #(.P(32)) w32;
|
Wrap2 #(.P(32)) w32;
|
||||||
SelfRefClassTypeParam src_logic;
|
SelfRefClassTypeParam src_logic;
|
||||||
|
@ -155,6 +160,8 @@ module t (/*AUTOARG*/);
|
||||||
c12 = new;
|
c12 = new;
|
||||||
c4 = new;
|
c4 = new;
|
||||||
c8 = new;
|
c8 = new;
|
||||||
|
ci = new;
|
||||||
|
ci8 = new;
|
||||||
w16 = new;
|
w16 = new;
|
||||||
w32 = new;
|
w32 = new;
|
||||||
src_int = new;
|
src_int = new;
|
||||||
|
@ -195,6 +202,10 @@ module t (/*AUTOARG*/);
|
||||||
c4.member = 32'haaaaaaaa;
|
c4.member = 32'haaaaaaaa;
|
||||||
c8.member = 32'haaaaaaaa;
|
c8.member = 32'haaaaaaaa;
|
||||||
// verilator lint_on WIDTH
|
// verilator lint_on WIDTH
|
||||||
|
ci.member = 12'haaa;
|
||||||
|
ci8.member = 8'hff;
|
||||||
|
if (ci.member != 12'haaa) $stop;
|
||||||
|
if (ci8.member != 8'hff) $stop;
|
||||||
if (c12.member != 12'haaa) $stop;
|
if (c12.member != 12'haaa) $stop;
|
||||||
if (c4.member != 4'ha) $stop;
|
if (c4.member != 4'ha) $stop;
|
||||||
if (c12.get_member() != 12'haaa) $stop;
|
if (c12.get_member() != 12'haaa) $stop;
|
||||||
|
|
|
@ -14,10 +14,18 @@ module test;
|
||||||
if (enum_item.first().name() != "BAR_0")
|
if (enum_item.first().name() != "BAR_0")
|
||||||
$stop;
|
$stop;
|
||||||
endfunction
|
endfunction
|
||||||
|
class Inner1;
|
||||||
|
static function void print();
|
||||||
|
E enum_item;
|
||||||
|
if (enum_item.first().name() != "BAR_0")
|
||||||
|
$stop;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
endclass
|
endclass
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
baz#(bar_e)::print();
|
baz#(bar_e)::print();
|
||||||
|
baz#(bar_e)::Inner1::print();
|
||||||
|
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
|
|
|
@ -8,6 +8,12 @@
|
||||||
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||||
|
|
||||||
class Cls;
|
class Cls;
|
||||||
|
class InnerCls;
|
||||||
|
static function int f_inner_cs_st();
|
||||||
|
++c_st; return c_st;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
int c_no = 2;
|
int c_no = 2;
|
||||||
//automatic int c_au = 2; // automatic not a legal keyword here
|
//automatic int c_au = 2; // automatic not a legal keyword here
|
||||||
static int c_st = 22;
|
static int c_st = 22;
|
||||||
|
@ -22,7 +28,6 @@ class Cls;
|
||||||
static function int f_cs_st ();
|
static function int f_cs_st ();
|
||||||
++c_st; return c_st;
|
++c_st; return c_st;
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
endclass
|
endclass
|
||||||
|
|
||||||
module t (/*AUTOARG*/);
|
module t (/*AUTOARG*/);
|
||||||
|
@ -43,6 +48,7 @@ module t (/*AUTOARG*/);
|
||||||
v = b.f_c_st(); `checkh(v, 26);
|
v = b.f_c_st(); `checkh(v, 26);
|
||||||
//
|
//
|
||||||
v = Cls::f_cs_st(); `checkh(v, 27);
|
v = Cls::f_cs_st(); `checkh(v, 27);
|
||||||
|
v = Cls::InnerCls::f_inner_cs_st(); `checkh(v, 28);
|
||||||
|
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
|
|
|
@ -8,18 +8,33 @@ virtual class VBase;
|
||||||
virtual function int hello;
|
virtual function int hello;
|
||||||
return 1;
|
return 1;
|
||||||
endfunction
|
endfunction
|
||||||
|
virtual class VNested;
|
||||||
|
virtual function int hello;
|
||||||
|
return 10;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
endclass
|
endclass
|
||||||
|
|
||||||
class VA extends VBase;
|
class VA extends VBase;
|
||||||
virtual function int hello;
|
virtual function int hello;
|
||||||
return 2;
|
return 2;
|
||||||
endfunction
|
endfunction
|
||||||
|
class VNested extends VBase::VNested;
|
||||||
|
virtual function int hello;
|
||||||
|
return 20;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
endclass
|
endclass
|
||||||
|
|
||||||
class VB extends VBase;
|
class VB extends VBase;
|
||||||
virtual function int hello;
|
virtual function int hello;
|
||||||
return 3;
|
return 3;
|
||||||
endfunction
|
endfunction
|
||||||
|
class VNested extends VBase::VNested;
|
||||||
|
virtual function int hello;
|
||||||
|
return 30;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
endclass
|
endclass
|
||||||
|
|
||||||
virtual class uvm_phase;
|
virtual class uvm_phase;
|
||||||
|
@ -59,18 +74,27 @@ module t;
|
||||||
initial begin
|
initial begin
|
||||||
VA va = new;
|
VA va = new;
|
||||||
VB vb = new;
|
VB vb = new;
|
||||||
|
VA::VNested vna = new;
|
||||||
|
VB::VNested vnb = new;
|
||||||
VBase b;
|
VBase b;
|
||||||
|
VBase::VNested bn;
|
||||||
|
|
||||||
uvm_build_phase ph;
|
uvm_build_phase ph;
|
||||||
ExtendsCls ec;
|
ExtendsCls ec;
|
||||||
|
|
||||||
if (va.hello() != 2) $stop;
|
if (va.hello() != 2) $stop;
|
||||||
if (vb.hello() != 3) $stop;
|
if (vb.hello() != 3) $stop;
|
||||||
|
if (vna.hello() != 20) $stop;
|
||||||
|
if (vnb.hello() != 30) $stop;
|
||||||
|
|
||||||
b = va;
|
b = va;
|
||||||
|
bn = vna;
|
||||||
if (b.hello() != 2) $stop;
|
if (b.hello() != 2) $stop;
|
||||||
|
if (bn.hello() != 20) $stop;
|
||||||
b = vb;
|
b = vb;
|
||||||
|
bn = vnb;
|
||||||
if (b.hello() != 3) $stop;
|
if (b.hello() != 3) $stop;
|
||||||
|
if (bn.hello() != 30) $stop;
|
||||||
|
|
||||||
ph = new;
|
ph = new;
|
||||||
if (ph.get1() != 1) $stop;
|
if (ph.get1() != 1) $stop;
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# 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
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('linter')
|
||||||
|
|
||||||
|
test.lint()
|
||||||
|
|
||||||
|
test.passes()
|
|
@ -0,0 +1,16 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2025 Antmicro.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
class Cls;
|
||||||
|
// IEEE 2023 only disallows nested interface inside another interface, not
|
||||||
|
// class
|
||||||
|
interface class good_can_nest;
|
||||||
|
endclass
|
||||||
|
endclass
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/);
|
||||||
|
Cls c;
|
||||||
|
endmodule
|
|
@ -1,5 +1,4 @@
|
||||||
%Error-UNSUPPORTED: t/t_implements_nested_bad.v:8:14: Unsupported: class within class
|
%Error: t/t_implements_nested_bad.v:9:17: Interface class shall not be nested within another interface class. (IEEE 1800-2023 8.26)
|
||||||
8 | interface class bad_cannot_nest;
|
9 | interface class bad_cannot_nest;
|
||||||
| ^~~~~
|
| ^~~~~
|
||||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
|
||||||
%Error: Exiting due to
|
%Error: Exiting due to
|
||||||
|
|
|
@ -5,7 +5,9 @@
|
||||||
// SPDX-License-Identifier: CC0-1.0
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
class Cls;
|
class Cls;
|
||||||
interface class bad_cannot_nest;
|
interface class inte;
|
||||||
|
interface class bad_cannot_nest;
|
||||||
|
endclass
|
||||||
endclass
|
endclass
|
||||||
endclass
|
endclass
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# 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
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('simulator')
|
||||||
|
|
||||||
|
test.compile(verilator_flags2=["--binary --timing"])
|
||||||
|
|
||||||
|
test.passes()
|
|
@ -0,0 +1,39 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2025 by Antmicro.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
class semaphore_cls;
|
||||||
|
class InnerKeyClass;
|
||||||
|
int innerKeys;
|
||||||
|
function new(int keyCount = 0);
|
||||||
|
innerKeys = keyCount;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
// Test an implementation similar to what Verilator will do internally
|
||||||
|
InnerKeyClass m_keys;
|
||||||
|
function new(int keyCount = 0);
|
||||||
|
m_keys = new(keyCount);
|
||||||
|
endfunction
|
||||||
|
function void put(int keyCount = 1);
|
||||||
|
m_keys.innerKeys += keyCount;
|
||||||
|
endfunction
|
||||||
|
task get(int keyCount = 1);
|
||||||
|
wait (m_keys.innerKeys >= keyCount);
|
||||||
|
m_keys.innerKeys -= keyCount;
|
||||||
|
endtask
|
||||||
|
function int try_get(int keyCount = 1);
|
||||||
|
if (m_keys.innerKeys >= keyCount) begin
|
||||||
|
m_keys.innerKeys -= keyCount;
|
||||||
|
return 1;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
return 0;
|
||||||
|
end
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
`define SEMAPHORE_T semaphore_cls
|
||||||
|
|
||||||
|
`include "t_semaphore.v"
|
Loading…
Reference in New Issue