From 9b68c5776ba311407708598326daa6b3e5e11de2 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 17 Sep 2022 22:01:58 +0200 Subject: [PATCH 1/2] Allow objects to be assigned to a variable of a base class SystemVerilog allows objects to be assigned to a variable that is a base type of the objects type. E.g. ``` class B; endclass Class C extends B; endclass C c = new B b = c; ``` Add a type_compatibility() method for netclass_t that allows these kinds of assignments. This already works fine in vvp since, as SystemVerilog does not support multiple inheritance, properties will always be at the same offset in the base class and the inheriting class. Signed-off-by: Lars-Peter Clausen --- netclass.cc | 11 +++++++++++ netclass.h | 3 +++ 2 files changed, 14 insertions(+) diff --git a/netclass.cc b/netclass.cc index 3365a8949..99ad5d68a 100644 --- a/netclass.cc +++ b/netclass.cc @@ -195,3 +195,14 @@ const NetExpr* netclass_t::get_parameter(Design *des, perm_string name, { return class_scope_->get_parameter(des, name, par_type); } + +bool netclass_t::test_compatibility(ivl_type_t that) const +{ + for (const netclass_t *class_type = dynamic_cast(that); + class_type; class_type = class_type->get_super()) { + if (class_type == this) + return true; + } + + return false; +} diff --git a/netclass.h b/netclass.h index 0c598fe32..a34487e9b 100644 --- a/netclass.h +++ b/netclass.h @@ -119,6 +119,9 @@ class netclass_t : public ivl_type_s { void set_virtual(bool virtual_class) { virtual_class_ = virtual_class; } bool is_virtual() const { return virtual_class_; } + protected: + bool test_compatibility(ivl_type_t that) const; + private: perm_string name_; // If this is derived from another base class, point to it From 4cfba91d65de521e8377a23a906515c0364b09d9 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 17 Dec 2022 10:41:42 -0800 Subject: [PATCH 2/2] Add regression tests for class compatibility Check that it is possible to assign an object to another object that is of a type of any of its base classes. Also check that an error is reported if this is not the case. Signed-off-by: Lars-Peter Clausen --- ivtest/ivltests/sv_class_compat1.v | 31 +++++++++++++++++++ ivtest/ivltests/sv_class_compat2.v | 40 +++++++++++++++++++++++++ ivtest/ivltests/sv_class_compat_fail1.v | 22 ++++++++++++++ ivtest/ivltests/sv_class_compat_fail2.v | 22 ++++++++++++++ ivtest/ivltests/sv_class_compat_fail3.v | 27 +++++++++++++++++ ivtest/regress-sv.list | 5 ++++ ivtest/regress-vlog95.list | 2 ++ 7 files changed, 149 insertions(+) create mode 100644 ivtest/ivltests/sv_class_compat1.v create mode 100644 ivtest/ivltests/sv_class_compat2.v create mode 100644 ivtest/ivltests/sv_class_compat_fail1.v create mode 100644 ivtest/ivltests/sv_class_compat_fail2.v create mode 100644 ivtest/ivltests/sv_class_compat_fail3.v diff --git a/ivtest/ivltests/sv_class_compat1.v b/ivtest/ivltests/sv_class_compat1.v new file mode 100644 index 000000000..be4d94804 --- /dev/null +++ b/ivtest/ivltests/sv_class_compat1.v @@ -0,0 +1,31 @@ +// Check that an object can be assigned to a variable of its base class type + +module test; + + class B; + int x; + + task t; + $display("PASSED"); + endtask + endclass + + class C extends B; + int y; + + task t; + $display("FAILED"); + endtask + endclass + + B b; + C c; + + initial begin + c = new; + b = c; + + b.t; + end + +endmodule diff --git a/ivtest/ivltests/sv_class_compat2.v b/ivtest/ivltests/sv_class_compat2.v new file mode 100644 index 000000000..29eb7bf59 --- /dev/null +++ b/ivtest/ivltests/sv_class_compat2.v @@ -0,0 +1,40 @@ +// Check that an object can be assigned to a variable of base class across more +// than one hierarchy level + +module test; + + class B; + int x; + + task t; + $display("PASSED"); + endtask + endclass + + class C extends B; + int y; + + task t; + $display("FAILED"); + endtask + endclass + + class D extends C; + int z; + + task t; + $display("FAILED"); + endtask + endclass + + B b; + D d; + + initial begin + d = new; + b = d; + + b.t; + end + +endmodule diff --git a/ivtest/ivltests/sv_class_compat_fail1.v b/ivtest/ivltests/sv_class_compat_fail1.v new file mode 100644 index 000000000..e96f018a8 --- /dev/null +++ b/ivtest/ivltests/sv_class_compat_fail1.v @@ -0,0 +1,22 @@ +// Check that an error is reported when trying to assign an object to variable +// of an unrelated class type + +module test; + + class B; + int x; + endclass + + class C; + int y; + endclass + + B b; + C c; + + initial begin + c = new; + b = c; // This should fail, both classes are unrelated + end + +endmodule diff --git a/ivtest/ivltests/sv_class_compat_fail2.v b/ivtest/ivltests/sv_class_compat_fail2.v new file mode 100644 index 000000000..e8563b47f --- /dev/null +++ b/ivtest/ivltests/sv_class_compat_fail2.v @@ -0,0 +1,22 @@ +// Check that an error is reported when trying when trying to assign an object +// of a base class to a variable of a inherited class. + +module test; + + class B; + int x; + endclass + + class C extends B; + int y; + endclass + + B b; + C c; + + initial begin + b = new; + c = b; // This should fail, B is a base class of C + end + +endmodule diff --git a/ivtest/ivltests/sv_class_compat_fail3.v b/ivtest/ivltests/sv_class_compat_fail3.v new file mode 100644 index 000000000..a7301386e --- /dev/null +++ b/ivtest/ivltests/sv_class_compat_fail3.v @@ -0,0 +1,27 @@ +// Check that an error is reported when trying to assign an object to a variable +// that shares a common base class but is not directly related. + +module test; + + class B; + int x; + endclass + + class C extends B; + int y; + endclass + + class D extends B; + int z; + endclass + + C c; + D d; + + initial begin + c = new; + d = c; // This should fail, both C and D inherit from B, but there is no + // direct relationship. + end + +endmodule diff --git a/ivtest/regress-sv.list b/ivtest/regress-sv.list index d002e84a3..c42d9795e 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -531,6 +531,11 @@ sv_class21 normal,-g2009 ivltests sv_class22 normal,-g2009 ivltests sv_class23 normal,-g2009 ivltests sv_class24 normal,-g2009 ivltests +sv_class_compat1 normal,-g2009 ivltests +sv_class_compat2 normal,-g2009 ivltests +sv_class_compat_fail1 CE,-g2009 ivltests +sv_class_compat_fail2 CE,-g2009 ivltests +sv_class_compat_fail3 CE,-g2009 ivltests sv_class_constructor1 normal,-g2009 ivltests sv_class_constructor_fail CE,-g2009 ivltests sv_class_empty_item normal,-g2009 ivltests diff --git a/ivtest/regress-vlog95.list b/ivtest/regress-vlog95.list index acd4b9f86..613b29177 100644 --- a/ivtest/regress-vlog95.list +++ b/ivtest/regress-vlog95.list @@ -404,6 +404,8 @@ sv_class21 CE,-g2009 ivltests sv_class22 CE,-g2009 ivltests sv_class23 CE,-g2009 ivltests sv_class24 CE,-g2009 ivltests +sv_class_compat1 CE,-g2009 ivltests +sv_class_compat2 CE,-g2009 ivltests sv_class_constructor1 CE,-g2009 ivltests sv_class_empty_item CE,-g2009 ivltests sv_class_extends_scoped CE,-g2009 ivltests