Elaborate package scopes in textual order (fix for issue #461)

When elaborating a subclass, the base class scope needs to be elaborated
before the subclass scope. If the base class and subclass are defined in
different packages, this requires the package scopes to be elaborated in
the correct order. SystemVerilog reqires packages to be defined before
they are used, so that is the order we should elaborate them in.
This commit is contained in:
Martin Whitaker 2021-01-03 18:45:08 +00:00
parent 9fa9a9d95a
commit ba25b55f53
4 changed files with 40 additions and 33 deletions

View File

@ -6766,18 +6766,18 @@ static void check_timescales()
if (some_explicit && some_implicit) if (some_explicit && some_implicit)
break; break;
} }
map<perm_string,PPackage*>::iterator pkg; vector<PPackage*>::iterator pkg;
if (gn_system_verilog() && !(some_explicit && some_implicit)) { if (gn_system_verilog() && !(some_explicit && some_implicit)) {
for (pkg = pform_packages.begin(); pkg != pform_packages.end(); ++pkg) { for (pkg = pform_packages.begin(); pkg != pform_packages.end(); ++pkg) {
const PPackage*pp = (*pkg).second; const PPackage*pp = *pkg;
check_timescales(some_explicit, some_implicit, pp); check_timescales(some_explicit, some_implicit, pp);
if (some_explicit && some_implicit) if (some_explicit && some_implicit)
break; break;
} }
} }
if (gn_system_verilog() && !(some_explicit && some_implicit)) { if (gn_system_verilog() && !(some_explicit && some_implicit)) {
for (unsigned idx = 0; idx < pform_units.size(); idx += 1) { for (pkg = pform_units.begin(); pkg != pform_units.end(); ++pkg) {
const PPackage*pp = pform_units[idx]; const PPackage*pp = *pkg;
// We don't need a timescale if the compilation unit // We don't need a timescale if the compilation unit
// contains no items outside a design element. // contains no items outside a design element.
if (pp->parameters.empty() && if (pp->parameters.empty() &&
@ -6828,15 +6828,15 @@ static void check_timescales()
return; return;
for (pkg = pform_packages.begin(); pkg != pform_packages.end(); ++pkg) { for (pkg = pform_packages.begin(); pkg != pform_packages.end(); ++pkg) {
PPackage*pp = (*pkg).second; PPackage*pp = *pkg;
if (pp->has_explicit_timescale()) if (pp->has_explicit_timescale())
continue; continue;
cerr << " : -- package " << (*pkg).first cerr << " : -- package " << pp->pscope_name()
<< " declared here: " << pp->get_fileline() << endl; << " declared here: " << pp->get_fileline() << endl;
} }
for (unsigned idx = 0; idx < pform_units.size(); idx += 1) { for (pkg = pform_units.begin(); pkg != pform_units.end(); ++pkg) {
PPackage*pp = pform_units[idx]; PPackage*pp = *pkg;
if (pp->has_explicit_timescale()) if (pp->has_explicit_timescale())
continue; continue;
@ -6892,8 +6892,9 @@ Design* elaborate(list<perm_string>roots)
// Elaborate the compilation unit scopes. From here on, these are // Elaborate the compilation unit scopes. From here on, these are
// treated as an additional set of packages. // treated as an additional set of packages.
if (gn_system_verilog()) { if (gn_system_verilog()) {
for (i = 0; i < pform_units.size(); i += 1) { for (vector<PPackage*>::iterator pkg = pform_units.begin()
PPackage*unit = pform_units[i]; ; pkg != pform_units.end() ; ++pkg) {
PPackage*unit = *pkg;
NetScope*scope = des->make_package_scope(unit->pscope_name(), 0, true); NetScope*scope = des->make_package_scope(unit->pscope_name(), 0, true);
scope->set_line(unit); scope->set_line(unit);
scope->add_imports(&unit->explicit_imports); scope->add_imports(&unit->explicit_imports);
@ -6904,6 +6905,7 @@ Design* elaborate(list<perm_string>roots)
pack_elems[i].pack = unit; pack_elems[i].pack = unit;
pack_elems[i].scope = scope; pack_elems[i].scope = scope;
i += 1;
unit_scopes[unit] = scope; unit_scopes[unit] = scope;
} }
@ -6914,20 +6916,19 @@ Design* elaborate(list<perm_string>roots)
// in SystemVerilog, packages are not allowed to refer to // in SystemVerilog, packages are not allowed to refer to
// the compilation unit scope, but the VHDL preprocessor // the compilation unit scope, but the VHDL preprocessor
// assumes they can. // assumes they can.
for (map<perm_string,PPackage*>::iterator pac = pform_packages.begin() for (vector<PPackage*>::iterator pkg = pform_packages.begin()
; pac != pform_packages.end() ; ++ pac) { ; pkg != pform_packages.end() ; ++pkg) {
PPackage*pack = *pkg;
NetScope*unit_scope = unit_scopes[pack->parent_scope()];
NetScope*scope = des->make_package_scope(pack->pscope_name(), unit_scope, false);
scope->set_line(pack);
scope->add_imports(&pack->explicit_imports);
set_scope_timescale(des, scope, pack);
ivl_assert(*pac->second, pac->first == pac->second->pscope_name()); elaborator_work_item_t*es = new elaborate_package_t(des, scope, pack);
NetScope*unit_scope = unit_scopes[pac->second->parent_scope()];
NetScope*scope = des->make_package_scope(pac->first, unit_scope, false);
scope->set_line(pac->second);
scope->add_imports(&pac->second->explicit_imports);
set_scope_timescale(des, scope, pac->second);
elaborator_work_item_t*es = new elaborate_package_t(des, scope, pac->second);
des->elaboration_work_list.push_back(es); des->elaboration_work_list.push_back(es);
pack_elems[i].pack = pac->second; pack_elems[i].pack = pack;
pack_elems[i].scope = scope; pack_elems[i].scope = scope;
i += 1; i += 1;
} }

View File

@ -1,5 +1,5 @@
const char COPYRIGHT[] = const char COPYRIGHT[] =
"Copyright (c) 1998-2020 Stephen Williams (steve@icarus.com)"; "Copyright (c) 1998-2021 Stephen Williams (steve@icarus.com)";
/* /*
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
@ -1142,9 +1142,9 @@ int main(int argc, char*argv[])
pform_dump(out, *pac); pform_dump(out, *pac);
} }
out << "PFORM DUMP PACKAGES:" << endl; out << "PFORM DUMP PACKAGES:" << endl;
for (map<perm_string,PPackage*>::iterator pac = pform_packages.begin() for (vector<PPackage*>::iterator pac = pform_packages.begin()
; pac != pform_packages.end() ; ++ pac) { ; pac != pform_packages.end() ; ++ pac) {
pform_dump(out, pac->second); pform_dump(out, *pac);
} }
out << "PFORM DUMP MODULES:" << endl; out << "PFORM DUMP MODULES:" << endl;
for (map<perm_string,Module*>::iterator mod = pform_modules.begin() for (map<perm_string,Module*>::iterator mod = pform_modules.begin()

View File

@ -1,7 +1,7 @@
#ifndef IVL_parse_api_H #ifndef IVL_parse_api_H
#define IVL_parse_api_H #define IVL_parse_api_H
/* /*
* Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com) * Copyright (c) 2001-2021 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -43,7 +43,7 @@ struct enum_type_t;
extern std::map<perm_string,Module*> pform_modules; extern std::map<perm_string,Module*> pform_modules;
extern std::map<perm_string,PUdp*> pform_primitives; extern std::map<perm_string,PUdp*> pform_primitives;
extern std::vector<PPackage*> pform_units; extern std::vector<PPackage*> pform_units;
extern std::map<perm_string,PPackage*> pform_packages; extern std::vector<PPackage*> pform_packages;
extern void pform_dump(std::ostream&out, const PClass*pac); extern void pform_dump(std::ostream&out, const PClass*pac);
extern void pform_dump(std::ostream&out, const PPackage*pac); extern void pform_dump(std::ostream&out, const PPackage*pac);

View File

@ -29,9 +29,14 @@
using namespace std; using namespace std;
/* /*
* This is a map of packages that have been defined. * This is a list of packages in the order that they were defined.
*/ */
map<perm_string,PPackage*> pform_packages; vector<PPackage*> pform_packages;
/*
* This allows us to easily check for name collisions.
*/
static map<perm_string,PPackage*> packages_by_name;
static PPackage*pform_cur_package = 0; static PPackage*pform_cur_package = 0;
@ -51,8 +56,8 @@ void pform_end_package_declaration(const struct vlltype&loc)
ivl_assert(loc, pform_cur_package); ivl_assert(loc, pform_cur_package);
perm_string use_name = pform_cur_package->pscope_name(); perm_string use_name = pform_cur_package->pscope_name();
map<perm_string,PPackage*>::const_iterator test = pform_packages.find(use_name); map<perm_string,PPackage*>::const_iterator test = packages_by_name.find(use_name);
if (test != pform_packages.end()) { if (test != packages_by_name.end()) {
ostringstream msg; ostringstream msg;
msg << "Package " << use_name << " was already declared here: " msg << "Package " << use_name << " was already declared here: "
<< test->second->get_fileline() << ends; << test->second->get_fileline() << ends;
@ -60,7 +65,8 @@ void pform_end_package_declaration(const struct vlltype&loc)
} }
pform_packages[use_name] = pform_cur_package; packages_by_name[use_name] = pform_cur_package;
pform_packages.push_back(pform_cur_package);
pform_cur_package = 0; pform_cur_package = 0;
pform_pop_scope(); pform_pop_scope();
} }
@ -152,8 +158,8 @@ data_type_t* pform_test_type_identifier(PPackage*pkg, const char*txt)
PPackage* pform_test_package_identifier(const char*pkg_name) PPackage* pform_test_package_identifier(const char*pkg_name)
{ {
perm_string use_name = lex_strings.make(pkg_name); perm_string use_name = lex_strings.make(pkg_name);
map<perm_string,PPackage*>::const_iterator pcur = pform_packages.find(use_name); map<perm_string,PPackage*>::const_iterator pcur = packages_by_name.find(use_name);
if (pcur == pform_packages.end()) if (pcur == packages_by_name.end())
return 0; return 0;
assert(pcur->second); assert(pcur->second);