Handle multiple instances of modules with class definitions
For classes declared inside a module each module instance creates a new
unique class type. These types are not compatible to each other. This is
necessary since module parameters can change the class implementation.
This is defined in section 6.22 ("Type compatibility") of the LRM (1800-2017).
In the current implementation when a class is elaborated the elaborated
type is stored in the class_type_t so it is possible to look up the
elaborated class type. But this class_type_t is shared among elaborated
class types. As a result when creating multiple instances of a module with
a class definition an internal assert is triggered.
To support multiple module instances with class definitions instead of
storing the elaborated type in the type definition look up the type in the
scope in which the type definition is references.
This is similar to how the same problem is solved for enum types.
For packages we still need to remember the elaborated type otherwise scoped
class type references wont work. Since there is only one instance of a
package this doesn't have the same problem as classes in modules.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This commit is contained in:
parent
583a7ddc35
commit
eed38bd14a
|
|
@ -489,29 +489,30 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
|
|||
<< endl;
|
||||
}
|
||||
|
||||
class_type_t*base_class = dynamic_cast<class_type_t*> (use_type->base_type);
|
||||
if (use_type->base_type && !base_class) {
|
||||
cerr << pclass->get_fileline() << ": error: "
|
||||
<< "Base type of " << use_type->name
|
||||
<< " is not a class." << endl;
|
||||
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) {
|
||||
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: "
|
||||
<< "Base class " << base_class->name
|
||||
<< " not found." << endl;
|
||||
<< "Base type of " << use_type->name
|
||||
<< " is not a class." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
netclass_t*use_class = new netclass_t(use_type->name, use_base_class);
|
||||
|
||||
ivl_assert(*pclass, use_type->save_elaborated_type == 0);
|
||||
use_type->save_elaborated_type = use_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);
|
||||
use_type->save_elaborated_type = use_class;
|
||||
}
|
||||
|
||||
NetScope*class_scope = new NetScope(scope, hname_t(pclass->pscope_name()),
|
||||
NetScope::CLASS, scope->unit());
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
return save_elaborated_type;
|
||||
if (save_elaborated_type)
|
||||
return save_elaborated_type;
|
||||
return scope->find_class(des, name);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue