Merge pull request #658 from larsclausen/class-in-module

Handle multiple instances of modules with class definitions
This commit is contained in:
Stephen Williams 2022-03-27 15:48:56 -07:00 committed by GitHub
commit 658d4f5eee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 58 additions and 22 deletions

View File

@ -496,29 +496,30 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
<< endl; << endl;
} }
class_type_t*base_class = dynamic_cast<class_type_t*> (use_type->base_type);
if (use_type->base_type && !base_class) { const netclass_t*use_base_class = 0;
if (use_type->base_type) {
ivl_type_t base_type = use_type->base_type->elaborate_type(des, scope);
use_base_class = dynamic_cast<const netclass_t *>(base_type);
if (!use_base_class) {
cerr << pclass->get_fileline() << ": error: " cerr << pclass->get_fileline() << ": error: "
<< "Base type of " << use_type->name << "Base type of " << use_type->name
<< " is not a class." << endl; << " is not a class." << endl;
des->errors += 1; des->errors += 1;
} }
netclass_t*use_base_class = 0;
if (base_class) {
use_base_class = base_class->save_elaborated_type;
if (use_base_class == 0) {
cerr << pclass->get_fileline() << ": error: "
<< "Base class " << base_class->name
<< " not found." << endl;
des->errors += 1;
}
} }
netclass_t*use_class = new netclass_t(use_type->name, use_base_class); netclass_t*use_class = new netclass_t(use_type->name, use_base_class);
// If this is a package we need to remember the elaborated type so that
// scoped type references work. Since there is only one instance for each
// package this works. For classes defined in modules there might be
// multiple instances though. Each module instance will have its own class
// type instance, so the same does not work there.
if (scope->type() == NetScope::PACKAGE) {
ivl_assert(*pclass, use_type->save_elaborated_type == 0); ivl_assert(*pclass, use_type->save_elaborated_type == 0);
use_type->save_elaborated_type = use_class; use_type->save_elaborated_type = use_class;
}
NetScope*class_scope = new NetScope(scope, hname_t(pclass->pscope_name()), NetScope*class_scope = new NetScope(scope, hname_t(pclass->pscope_name()),
NetScope::CLASS, scope->unit()); NetScope::CLASS, scope->unit());

View File

@ -101,10 +101,11 @@ ivl_type_t atom2_type_t::elaborate_type_raw(Design*des, NetScope*) const
} }
} }
ivl_type_t class_type_t::elaborate_type_raw(Design*, NetScope*) const ivl_type_t class_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
{ {
ivl_assert(*this, save_elaborated_type); if (save_elaborated_type)
return save_elaborated_type; return save_elaborated_type;
return scope->find_class(des, name);
} }
/* /*

View File

@ -0,0 +1,32 @@
// Check that it is possible to have multiple instances of a module that defines
// a class and that the actual class types can have different implementations
// based on module parameters.
module M #(
parameter X = 0
);
class C;
function int f;
return X;
endfunction
endclass
C c = new;
endmodule
module test;
M #(10) m1();
M #(20) m2();
initial begin
if (m1.c.f() == 10 && m2.c.f() == 20) begin
$display("PASSED");
end else begin
$display("FAILED");
end
end
endmodule

View File

@ -478,6 +478,7 @@ sv_class_empty_item normal,-g2009 ivltests
sv_class_extends_scoped normal,-g2009 ivltests sv_class_extends_scoped normal,-g2009 ivltests
sv_class_localparam normal,-g2009 ivltests sv_class_localparam normal,-g2009 ivltests
sv_class_new_init normal,-g2009 ivltests sv_class_new_init normal,-g2009 ivltests
sv_class_in_module_decl normal,-g2009 ivltests
sv_darray1 normal,-g2009 ivltests sv_darray1 normal,-g2009 ivltests
sv_darray2 normal,-g2009 ivltests sv_darray2 normal,-g2009 ivltests
sv_darray3 normal,-g2009 ivltests sv_darray3 normal,-g2009 ivltests

View File

@ -376,6 +376,7 @@ sv_class_empty_item CE,-g2009 ivltests
sv_class_extends_scoped CE,-g2009 ivltests sv_class_extends_scoped CE,-g2009 ivltests
sv_class_localparam CE,-g2009 ivltests sv_class_localparam CE,-g2009 ivltests
sv_class_new_init CE,-g2009 ivltests sv_class_new_init CE,-g2009 ivltests
sv_class_in_module_decl CE,-g2009 ivltests
sv_end_label CE,-g2009 ivltests # Also generate sv_end_label CE,-g2009 ivltests # Also generate
sv_foreach2 CE,-g2009,-pallowsigned=1 ivltests sv_foreach2 CE,-g2009,-pallowsigned=1 ivltests
sv_foreach3 CE,-g2009 ivltests sv_foreach3 CE,-g2009 ivltests

View File

@ -23,8 +23,8 @@
using namespace std; using namespace std;
netclass_t::netclass_t(perm_string name, netclass_t*sup) netclass_t::netclass_t(perm_string name, const netclass_t*super)
: name_(name), super_(sup), class_scope_(0), definition_scope_(0) : name_(name), super_(super), class_scope_(0), definition_scope_(0)
{ {
} }

View File

@ -35,7 +35,7 @@ class PExpr;
class netclass_t : public ivl_type_s { class netclass_t : public ivl_type_s {
public: public:
netclass_t(perm_string class_name, netclass_t*par); netclass_t(perm_string class_name, const netclass_t*super);
~netclass_t(); ~netclass_t();
// Set the property of the class during elaboration. Set the // Set the property of the class during elaboration. Set the
@ -120,7 +120,7 @@ class netclass_t : public ivl_type_s {
perm_string name_; perm_string name_;
// If this is derived from another base class, point to it // If this is derived from another base class, point to it
// here. // here.
netclass_t*super_; const netclass_t*super_;
// Map property names to property table index. // Map property names to property table index.
std::map<perm_string,size_t> properties_; std::map<perm_string,size_t> properties_;
// Vector of properties. // Vector of properties.