Support separate compilation units in SystemVerilog.

The compilation unit scope is now treated as a specialised form of
package (with an automatically generated name). All items declared
outside a design element are added to the current compilation unit
package. Apart from when searching for a symbol, once we get into
elaboration we can treat these just like any other package.
This commit is contained in:
Martin Whitaker 2017-10-21 15:04:25 +01:00
parent dfddbea26b
commit 988816c0b1
16 changed files with 283 additions and 482 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com) * Copyright (c) 1998-2017 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
@ -1390,6 +1390,8 @@ void NetScope::dump(ostream&o) const
if (is_interface()) o << " (interface)"; if (is_interface()) o << " (interface)";
o << " " << children_.size() << " children, " o << " " << children_.size() << " children, "
<< classes_.size() << " classes" << endl; << classes_.size() << " classes" << endl;
if (unit() && !is_unit())
o << " in compilation unit " << unit()->basename() << endl;
for (unsigned idx = 0 ; idx < attr_cnt() ; idx += 1) for (unsigned idx = 0 ; idx < attr_cnt() ; idx += 1)
o << " (* " << attr_key(idx) << " = " o << " (* " << attr_key(idx) << " = "
@ -1902,18 +1904,6 @@ void Design::dump(ostream&o) const
cur->second->dump(o); cur->second->dump(o);
} }
o << "$ROOT CLASSES:" << endl;
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
; cur != classes_.end() ; ++cur) {
cur->second->dump_scope(o);
}
o << "$ROOT TASKS/FUNCTIONS:" << endl;
for (map<NetScope*,PTaskFunc*>::const_iterator cur = root_tasks_.begin()
; cur != root_tasks_.end() ; ++ cur) {
cur->first->dump(o);
}
o << "SCOPES:" << endl; o << "SCOPES:" << endl;
for (list<NetScope*>::const_iterator scope = root_scopes_.begin(); for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
scope != root_scopes_.end(); ++ scope ) { scope != root_scopes_.end(); ++ scope ) {

View File

@ -167,8 +167,7 @@ static void collect_scope_specparams_(Design*des, NetScope*scope,
} }
/* /*
* Elaborate the enumeration into the given scope. If scope==0, then * Elaborate the enumeration into the given scope.
* the enumeration goes into $root instead of a scope.
*/ */
static void elaborate_scope_enumeration(Design*des, NetScope*scope, static void elaborate_scope_enumeration(Design*des, NetScope*scope,
enum_type_t*enum_type) enum_type_t*enum_type)
@ -193,10 +192,7 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
enum_type); enum_type);
use_enum->set_line(enum_type->li); use_enum->set_line(enum_type->li);
if (scope) scope->add_enumeration_set(enum_type, use_enum);
scope->add_enumeration_set(enum_type, use_enum);
else
des->add_enumeration_set(enum_type, use_enum);
size_t name_idx = 0; size_t name_idx = 0;
// Find the enumeration width. // Find the enumeration width.
@ -364,10 +360,7 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
} }
rc_flag = use_enum->insert_name(name_idx, cur->name, cur_value); rc_flag = use_enum->insert_name(name_idx, cur->name, cur_value);
if (scope) rc_flag &= scope->add_enumeration_name(use_enum, cur->name);
rc_flag &= scope->add_enumeration_name(use_enum, cur->name);
else
rc_flag &= des->add_enumeration_name(use_enum, cur->name);
if (! rc_flag) { if (! rc_flag) {
cerr << use_enum->get_fileline() cerr << use_enum->get_fileline()
@ -397,15 +390,6 @@ static void elaborate_scope_enumerations(Design*des, NetScope*scope,
} }
} }
void elaborate_rootscope_enumerations(Design*des)
{
for (set<enum_type_t*>::const_iterator cur = pform_enum_sets.begin()
; cur != pform_enum_sets.end() ; ++ cur) {
enum_type_t*curp = *cur;
elaborate_scope_enumeration(des, 0, curp);
}
}
/* /*
* If the pclass includes an implicit and explicit constructor, then * If the pclass includes an implicit and explicit constructor, then
* merge the implicit constructor into the explicit constructor as * merge the implicit constructor into the explicit constructor as
@ -509,10 +493,7 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
netclass_t*use_base_class = 0; netclass_t*use_base_class = 0;
if (base_class) { if (base_class) {
if (scope) use_base_class = scope->find_class(base_class->name);
use_base_class = scope->find_class(base_class->name);
if (use_base_class == 0)
use_base_class = des->find_class(base_class->name);
if (use_base_class == 0) { if (use_base_class == 0) {
cerr << pclass->get_fileline() << ": error: " cerr << pclass->get_fileline() << ": error: "
<< "Base class " << base_class->name << "Base class " << base_class->name
@ -527,9 +508,10 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
use_type->save_elaborated_type = use_class; use_type->save_elaborated_type = use_class;
// Class scopes have no parent scope, because references are // Class scopes have no parent scope, because references are
// not allowed to escape a class method. // not allowed to escape a class method. But they are allowed
// to reference the compilation unit scope.
NetScope*class_scope = new NetScope(0, hname_t(pclass->pscope_name()), NetScope*class_scope = new NetScope(0, hname_t(pclass->pscope_name()),
NetScope::CLASS); NetScope::CLASS, scope->unit());
class_scope->set_line(pclass); class_scope->set_line(pclass);
class_scope->set_class_def(use_class); class_scope->set_class_def(use_class);
use_class->set_class_scope(class_scope); use_class->set_class_scope(class_scope);
@ -588,12 +570,7 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
cur->second->elaborate_scope(des, method_scope); cur->second->elaborate_scope(des, method_scope);
} }
if (scope) { scope->add_class(use_class);
scope->add_class(use_class);
} else {
des->add_class(use_class, pclass);
}
} }
static void elaborate_scope_classes(Design*des, NetScope*scope, static void elaborate_scope_classes(Design*des, NetScope*scope,
@ -605,14 +582,6 @@ static void elaborate_scope_classes(Design*des, NetScope*scope,
} }
} }
void elaborate_rootscope_classes(Design*des)
{
for (size_t idx = 0 ; idx < pform_classes.size() ; idx += 1) {
blend_class_constructors(pform_classes[idx]);
elaborate_scope_class(des, 0, pform_classes[idx]);
}
}
static void replace_scope_parameters_(NetScope*scope, const LineInfo&loc, static void replace_scope_parameters_(NetScope*scope, const LineInfo&loc,
const Module::replace_t&replacements) const Module::replace_t&replacements)
{ {
@ -662,11 +631,6 @@ static void elaborate_scope_task(Design*des, NetScope*scope, PTask*task)
task_scope->is_auto(task->is_auto()); task_scope->is_auto(task->is_auto());
task_scope->set_line(task); task_scope->set_line(task);
if (scope==0) {
set_scope_timescale(des, task_scope, task);
des->add_root_task(task_scope, task);
}
if (debug_scopes) { if (debug_scopes) {
cerr << task->get_fileline() << ": elaborate_scope_task: " cerr << task->get_fileline() << ": elaborate_scope_task: "
<< "Elaborate task scope " << scope_path(task_scope) << endl; << "Elaborate task scope " << scope_path(task_scope) << endl;
@ -729,11 +693,6 @@ static void elaborate_scope_func(Design*des, NetScope*scope, PFunction*task)
task_scope->is_auto(task->is_auto()); task_scope->is_auto(task->is_auto());
task_scope->set_line(task); task_scope->set_line(task);
if (scope==0) {
set_scope_timescale(des, task_scope, task);
des->add_root_task(task_scope, task);
}
if (debug_scopes) { if (debug_scopes) {
cerr << task->get_fileline() << ": elaborate_scope_func: " cerr << task->get_fileline() << ": elaborate_scope_func: "
<< "Elaborate task scope " << scope_path(task_scope) << endl; << "Elaborate task scope " << scope_path(task_scope) << endl;
@ -789,28 +748,6 @@ static void elaborate_scope_funcs(Design*des, NetScope*scope,
} }
void elaborate_rootscope_tasks(Design*des)
{
for (map<perm_string,PTaskFunc*>::iterator cur = pform_tasks.begin()
; cur != pform_tasks.end() ; ++ cur) {
if (PTask*task = dynamic_cast<PTask*> (cur->second)) {
elaborate_scope_task(des, 0, task);
continue;
}
if (PFunction*func = dynamic_cast<PFunction*>(cur->second)) {
elaborate_scope_func(des, 0, func);
continue;
}
cerr << cur->second->get_fileline() << ": internal error: "
<< "elaborate_rootscope_tasks does not understand "
<< "this object," << endl;
des->errors += 1;
}
}
class generate_schemes_work_item_t : public elaborator_work_item_t { class generate_schemes_work_item_t : public elaborator_work_item_t {
public: public:
generate_schemes_work_item_t(Design*des__, NetScope*scope, Module*mod) generate_schemes_work_item_t(Design*des__, NetScope*scope, Module*mod)
@ -1756,7 +1693,7 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
// Create the new scope as a MODULE with my name. Note // Create the new scope as a MODULE with my name. Note
// that if this is a nested module, mark it thus so that // that if this is a nested module, mark it thus so that
// scope searches will continue into the parent scope. // scope searches will continue into the parent scope.
NetScope*my_scope = new NetScope(sc, use_name, NetScope::MODULE, NetScope*my_scope = new NetScope(sc, use_name, NetScope::MODULE, 0,
bound_type_? true : false, bound_type_? true : false,
mod->program_block, mod->program_block,
mod->is_interface); mod->is_interface);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com) * Copyright (c) 2000-2017 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com) * Copyright CERN 2012 / 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
@ -1333,27 +1333,3 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
return sig; return sig;
} }
void Design::root_elaborate_sig(void)
{
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
; cur != classes_.end() ; ++ cur) {
netclass_t*cur_class = cur->second;
PClass*cur_pclass = class_to_pclass_[cur_class];
cur_class->elaborate_sig(this, cur_pclass);
}
for (map<NetScope*,PTaskFunc*>::iterator cur = root_tasks_.begin()
; cur != root_tasks_.end() ; ++ cur) {
if (debug_elaborate) {
cerr << cur->second->get_fileline() << ": root_elaborate_sig: "
<< "Elaborate_sig for root task/func " << scope_path(cur->first) << endl;
}
cur->second->elaborate_sig(this, cur->first);
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012-2016 Stephen Williams (steve@icarus.com) * Copyright (c) 2012-2017 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
@ -78,9 +78,8 @@ static void elaborate_array_ranges(Design*des, NetScope*scope,
*/ */
ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*scope) ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*scope)
{ {
ivl_assert(*this, scope);
Definitions*use_definitions = scope; Definitions*use_definitions = scope;
if (use_definitions == 0)
use_definitions = des;
map<Definitions*,ivl_type_s*>::iterator pos = cache_type_elaborate_.lower_bound(use_definitions); map<Definitions*,ivl_type_s*>::iterator pos = cache_type_elaborate_.lower_bound(use_definitions);
if (pos != cache_type_elaborate_.end() && pos->first == use_definitions) if (pos != cache_type_elaborate_.end() && pos->first == use_definitions)
@ -147,13 +146,13 @@ ivl_type_s* class_type_t::elaborate_type_raw(Design*, NetScope*) const
* available at the right time. At that time, the netenum_t* object is * available at the right time. At that time, the netenum_t* object is
* stashed in the scope so that I can retrieve it here. * stashed in the scope so that I can retrieve it here.
*/ */
ivl_type_s* enum_type_t::elaborate_type_raw(Design*des, NetScope*scope) const ivl_type_s* enum_type_t::elaborate_type_raw(Design*, NetScope*scope) const
{ {
ivl_assert(*this, scope); ivl_assert(*this, scope);
ivl_type_s*tmp = scope->enumeration_for_key(this); ivl_type_s*tmp = scope->enumeration_for_key(this);
if (tmp) return tmp; if (tmp == 0 && scope->unit()) {
tmp = scope->unit()->enumeration_for_key(this);
tmp = des->enumeration_for_key(this); }
return tmp; return tmp;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com) * Copyright (c) 1998-2017 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / 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
@ -6170,28 +6170,6 @@ bool Design::check_proc_delay() const
return result_flag; return result_flag;
} }
void Design::root_elaborate(void)
{
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
; cur != classes_.end() ; ++ cur) {
netclass_t*cur_class = cur->second;
PClass*cur_pclass = class_to_pclass_[cur_class];
cur_class->elaborate(this, cur_pclass);
}
for (map<NetScope*,PTaskFunc*>::iterator cur = root_tasks_.begin()
; cur != root_tasks_.end() ; ++ cur) {
if (debug_elaborate) {
cerr << cur->second->get_fileline() << ": Design::root_elaborate: "
<< "Elaborate for root task/func " << scope_path(cur->first) << endl;
}
cur->second->elaborate(this, cur->first);
}
}
/* /*
* This function is the root of all elaboration. The input is the list * This function is the root of all elaboration. The input is the list
* of root module names. The function locates the Module definitions * of root module names. The function locates the Module definitions
@ -6211,8 +6189,13 @@ struct root_elem {
Design* elaborate(list<perm_string>roots) Design* elaborate(list<perm_string>roots)
{ {
unsigned npackages = pform_packages.size();
if (gn_system_verilog())
npackages += pform_units.size();
vector<struct root_elem> root_elems(roots.size()); vector<struct root_elem> root_elems(roots.size());
vector<struct pack_elem> pack_elems(pform_packages.size()); vector<struct pack_elem> pack_elems(npackages);
map<LexicalScope*,NetScope*> unit_scopes;
bool rc = true; bool rc = true;
unsigned i = 0; unsigned i = 0;
@ -6220,23 +6203,36 @@ Design* elaborate(list<perm_string>roots)
// module and elaborate what I find. // module and elaborate what I find.
Design*des = new Design; Design*des = new Design;
// Elaborate enum sets in $root scope. // Elaborate the compilation unit scopes. From here on, these are
elaborate_rootscope_enumerations(des); // treated as an additional set of packages.
if (gn_system_verilog()) {
for (i = 0; i < pform_units.size(); i += 1) {
PPackage*unit = pform_units[i];
NetScope*scope = des->make_package_scope(unit->pscope_name(), 0, true);
scope->set_line(unit);
set_scope_timescale(des, scope, unit);
// Elaborate tasks and functions in $root scope. elaborator_work_item_t*es = new elaborate_package_t(des, scope, unit);
elaborate_rootscope_tasks(des); des->elaboration_work_list.push_back(es);
// Elaborate classes in $root scope. pack_elems[i].pack = unit;
elaborate_rootscope_classes(des); pack_elems[i].scope = scope;
unit_scopes[unit] = scope;
}
}
// Elaborate the packages. Package elaboration is simpler // Elaborate the packages. Package elaboration is simpler
// because there are fewer sub-scopes involved. // because there are fewer sub-scopes involved. Note that
i = 0; // in SystemVerilog, packages are not allowed to refer to
// the compilation unit scope, but the VHDL preprocessor
// assumes they can.
for (map<perm_string,PPackage*>::iterator pac = pform_packages.begin() for (map<perm_string,PPackage*>::iterator pac = pform_packages.begin()
; pac != pform_packages.end() ; ++ pac) { ; pac != pform_packages.end() ; ++ pac) {
ivl_assert(*pac->second, pac->first == pac->second->pscope_name()); ivl_assert(*pac->second, pac->first == pac->second->pscope_name());
NetScope*scope = des->make_package_scope(pac->first); 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->set_line(pac->second);
set_scope_timescale(des, scope, pac->second); set_scope_timescale(des, scope, pac->second);
@ -6267,9 +6263,13 @@ Design* elaborate(list<perm_string>roots)
// Get the module definition for this root instance. // Get the module definition for this root instance.
Module *rmod = (*mod).second; Module *rmod = (*mod).second;
// Get the compilation unit scope for this module.
NetScope*unit_scope = unit_scopes[rmod->parent_scope()];
// Make the root scope. This makes a NetScope object and // Make the root scope. This makes a NetScope object and
// pushes it into the list of root scopes in the Design. // pushes it into the list of root scopes in the Design.
NetScope*scope = des->make_root_scope(*root, rmod->program_block, NetScope*scope = des->make_root_scope(*root, unit_scope,
rmod->program_block,
rmod->is_interface); rmod->is_interface);
// Collect some basic properties of this scope from the // Collect some basic properties of this scope from the
@ -6367,8 +6367,6 @@ Design* elaborate(list<perm_string>roots)
<< "Start calling $root elaborate_sig methods." << endl; << "Start calling $root elaborate_sig methods." << endl;
} }
des->root_elaborate_sig();
if (debug_elaborate) { if (debug_elaborate) {
cerr << "<toplevel>: elaborate: " cerr << "<toplevel>: elaborate: "
<< "Start calling root module elaborate_sig methods." << endl; << "Start calling root module elaborate_sig methods." << endl;
@ -6430,8 +6428,6 @@ Design* elaborate(list<perm_string>roots)
rc &= pkg->elaborate(des, scope); rc &= pkg->elaborate(des, scope);
} }
des->root_elaborate();
for (i = 0; i < root_elems.size(); i++) { for (i = 0; i < root_elems.size(); i++) {
Module *rmod = root_elems[i].mod; Module *rmod = root_elems[i].mod;
NetScope *scope = root_elems[i].scope; NetScope *scope = root_elems[i].scope;

20
emit.cc
View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com) * Copyright (c) 1998-2017 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
@ -510,24 +510,12 @@ int Design::emit(struct target_t*tgt) const
if (tgt->start_design(this) == false) if (tgt->start_design(this) == false)
return -2; return -2;
for (map<NetScope*,PTaskFunc*>::const_iterator scope = root_tasks_.begin()
; scope != root_tasks_.end() ; ++ scope) {
scope->first->emit_scope(tgt);
}
// enumerate package scopes // enumerate package scopes
for (map<perm_string,NetScope*>::const_iterator scope = packages_.begin() for (map<perm_string,NetScope*>::const_iterator scope = packages_.begin()
; scope != packages_.end() ; ++ scope) { ; scope != packages_.end() ; ++ scope) {
scope->second->emit_scope(tgt); scope->second->emit_scope(tgt);
} }
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
; cur != classes_.end() ; ++cur) {
const NetScope*use_scope = cur->second->class_scope();
cur->second->emit_scope(tgt);
tgt->class_type(use_scope, cur->second);
}
// enumerate root scopes // enumerate root scopes
for (list<NetScope*>::const_iterator scope = root_scopes_.begin() for (list<NetScope*>::const_iterator scope = root_scopes_.begin()
; scope != root_scopes_.end(); ++ scope ) { ; scope != root_scopes_.end(); ++ scope ) {
@ -552,12 +540,6 @@ int Design::emit(struct target_t*tgt) const
// emit task and function definitions // emit task and function definitions
bool tasks_rc = true; bool tasks_rc = true;
for (map<NetScope*,PTaskFunc*>::const_iterator scope = root_tasks_.begin()
; scope != root_tasks_.end() ; ++ scope)
tasks_rc &= scope->first->emit_defs(tgt);
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
; cur != classes_.end() ; ++cur)
tasks_rc &= cur->second->emit_defs(tgt);
for (map<perm_string,NetScope*>::const_iterator scope = packages_.begin() for (map<perm_string,NetScope*>::const_iterator scope = packages_.begin()
; scope != packages_.end() ; ++ scope ) ; scope != packages_.end() ; ++ scope )
tasks_rc &= scope->second->emit_defs(tgt); tasks_rc &= scope->second->emit_defs(tgt);

View File

@ -1,7 +1,7 @@
#ifndef IVL_ivl_target_priv_H #ifndef IVL_ivl_target_priv_H
#define IVL_ivl_target_priv_H #define IVL_ivl_target_priv_H
/* /*
* Copyright (c) 2008-2014 Stephen Williams (steve@icarus.com) * Copyright (c) 2008-2017 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
@ -52,7 +52,6 @@ struct ivl_design_s {
// Keep arrays of root scopes. // Keep arrays of root scopes.
std::map<const NetScope*,ivl_scope_t> classes; std::map<const NetScope*,ivl_scope_t> classes;
std::map<const NetScope*,ivl_scope_t> root_tasks;
std::vector<ivl_scope_t> packages; std::vector<ivl_scope_t> packages;
std::vector<ivl_scope_t> roots; std::vector<ivl_scope_t> roots;

16
main.cc
View File

@ -1103,21 +1103,11 @@ int main(int argc, char*argv[])
; cur != disciplines.end() ; ++ cur ) { ; cur != disciplines.end() ; ++ cur ) {
pform_dump(out, (*cur).second); pform_dump(out, (*cur).second);
} }
out << "PFORM DUMP $ROOT TASKS/FUNCTIONS:" << endl;
for (map<perm_string,PTaskFunc*>::iterator cur = pform_tasks.begin()
; cur != pform_tasks.end() ; ++ cur) {
pform_dump(out, cur->second);
}
out << "PFORM DUMP $ROOT CLASSES:" << endl;
for (size_t idx = 0 ; idx < pform_classes.size() ; idx += 1) {
pform_dump(out, pform_classes[idx]);
}
out << "PFORM DUMP PACKAGES:" << endl; out << "PFORM DUMP PACKAGES:" << endl;
for (map<perm_string,PPackage*>::iterator pac = pform_packages.begin() for (map<perm_string,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->second);
} }
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()
; mod != pform_modules.end() ; ++ mod ) { ; mod != pform_modules.end() ; ++ mod ) {
@ -1235,12 +1225,6 @@ int main(int argc, char*argv[])
(*idx).second = 0; (*idx).second = 0;
} }
for(map<perm_string,data_type_t*>::iterator it = pform_typedefs.begin()
; it != pform_typedefs.end() ; ++it) {
delete (*it).second;
(*it).second = 0;
}
if (verbose_flag) { if (verbose_flag) {
if (times_flag) { if (times_flag) {
times(cycles+2); times(cycles+2);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com) * Copyright (c) 2000-2017 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
@ -101,11 +101,11 @@ uint64_t Design::scale_to_precision(uint64_t val,
return val; return val;
} }
NetScope* Design::make_root_scope(perm_string root, bool program_block, NetScope* Design::make_root_scope(perm_string root, NetScope*unit_scope,
bool is_interface) bool program_block, bool is_interface)
{ {
NetScope *root_scope_; NetScope *root_scope_;
root_scope_ = new NetScope(0, hname_t(root), NetScope::MODULE, root_scope_ = new NetScope(0, hname_t(root), NetScope::MODULE, unit_scope,
false, program_block, is_interface); false, program_block, is_interface);
/* This relies on the fact that the basename return value is /* This relies on the fact that the basename return value is
permallocated. */ permallocated. */
@ -125,31 +125,18 @@ list<NetScope*> Design::find_root_scopes() const
return root_scopes_; return root_scopes_;
} }
NetScope* Design::make_package_scope(perm_string name) NetScope* Design::make_package_scope(perm_string name, NetScope*unit_scope,
bool is_unit)
{ {
NetScope*scope; NetScope*scope;
scope = new NetScope(0, hname_t(name), NetScope::PACKAGE, false, false); scope = new NetScope(0, hname_t(name), NetScope::PACKAGE, unit_scope,
false, false, false, is_unit);
scope->set_module_name(scope->basename()); scope->set_module_name(scope->basename());
packages_[name] = scope; packages_[name] = scope;
return scope; return scope;
} }
void Design::add_class(netclass_t*cl, PClass*pclass)
{
Definitions::add_class(cl);
class_to_pclass_[cl] = pclass;
}
netclass_t* Design::find_class(perm_string name) const
{
map<perm_string,netclass_t*>::const_iterator cur = classes_.find(name);
if (cur != classes_.end())
return cur->second;
return 0;
}
NetScope* Design::find_package(perm_string name) const NetScope* Design::find_package(perm_string name) const
{ {
map<perm_string,NetScope*>::const_iterator cur = packages_.find(name); map<perm_string,NetScope*>::const_iterator cur = packages_.find(name);
@ -170,17 +157,6 @@ list<NetScope*> Design::find_package_scopes() const
return res; return res;
} }
list<NetScope*> Design::find_roottask_scopes() const
{
list<NetScope*>res;
for (map<NetScope*,PTaskFunc*>::const_iterator cur = root_tasks_.begin()
; cur != root_tasks_.end() ; ++ cur) {
res.push_back (cur->first);
}
return res;
}
/* /*
* This method locates a scope in the design, given its rooted * This method locates a scope in the design, given its rooted
* hierarchical name. Each component of the key is used to scan one * hierarchical name. Each component of the key is used to scan one
@ -211,25 +187,6 @@ NetScope* Design::find_scope(const std::list<hname_t>&path) const
} }
} }
for (map<NetScope*,PTaskFunc*>::const_iterator root = root_tasks_.begin()
; root != root_tasks_.end() ; ++ root) {
NetScope*cur = root->first;
if (path.front() != cur->fullname())
continue;
std::list<hname_t> tmp = path;
tmp.pop_front();
while (cur) {
if (tmp.empty()) return cur;
cur = cur->child( tmp.front() );
tmp.pop_front();
}
}
return 0; return 0;
} }
@ -253,6 +210,49 @@ NetScope* Design::find_scope(const hname_t&path) const
return 0; return 0;
} }
static bool is_design_unit(NetScope*scope)
{
return (scope->type() == NetScope::MODULE && !scope->nested_module())
|| (scope->type() == NetScope::PACKAGE);
}
static bool is_subroutine(NetScope::TYPE type)
{
return type == NetScope::TASK || type == NetScope::FUNC;
}
/*
* This method locates a scope within another scope, given its relative
* hierarchical name. Each component of the key is used to scan one
* more step down the tree until the name runs out or the search
* fails.
*/
NetScope* Design::find_scope_(NetScope*scope, const std::list<hname_t>&path,
NetScope::TYPE type) const
{
std::list<hname_t> tmp = path;
do {
hname_t key = tmp.front();
/* If we are looking for a module or we are not
* looking at the last path component check for
* a name match (second line). */
if (scope->type() == NetScope::MODULE
&& (type == NetScope::MODULE || tmp.size() > 1)
&& scope->module_name()==key.peek_name()) {
/* Up references may match module name */
} else {
scope = scope->child( key );
if (scope == 0) break;
}
tmp.pop_front();
} while (! tmp.empty());
return scope;
}
/* /*
* This is a relative lookup of a scope by name. The starting point is * This is a relative lookup of a scope by name. The starting point is
* the scope parameter within which I start looking for the scope. If * the scope parameter within which I start looking for the scope. If
@ -266,36 +266,62 @@ NetScope* Design::find_scope(NetScope*scope, const std::list<hname_t>&path,
if (path.empty()) if (path.empty())
return scope; return scope;
for ( ; scope ; scope = scope->parent()) { // Record the compilation unit scope for use later.
NetScope*unit_scope = scope->unit();
std::list<hname_t> tmp = path; // First search upwards through the hierarchy.
while (scope) {
NetScope*found_scope = find_scope_(scope, path, type);
if (found_scope)
return found_scope;
NetScope*cur = scope; // Avoid searching the unit scope twice.
do { if (scope == unit_scope)
hname_t key = tmp.front(); unit_scope = 0;
/* If we are looking for a module or we are not
* looking at the last path component check for
* a name match (second line). */
if (cur->type() == NetScope::MODULE
&& (type == NetScope::MODULE || tmp.size() > 1)
&& cur->module_name()==key.peek_name()) {
/* Up references may match module name */ // Special case - see IEEE 1800-2012 section 23.8.1.
if (unit_scope && is_design_unit(scope) && is_subroutine(type)) {
found_scope = find_scope_(unit_scope, path, type);
if (found_scope)
return found_scope;
} else { unit_scope = 0;
cur = cur->child( key ); }
if (cur == 0) break;
}
tmp.pop_front();
} while (! tmp.empty());
if (cur) return cur; scope = scope->parent();
}
// If we haven't already done so, search the compilation unit scope.
if (unit_scope) {
NetScope*found_scope = find_scope_(unit_scope, path, type);
if (found_scope)
return found_scope;
} }
// Last chance. Look for the name starting at the root. // Last chance. Look for the name starting at the root.
return find_scope(path); return find_scope(path);
} }
/*
* This method locates a scope within another scope, given its relative
* hierarchical name. Each component of the key is used to scan one
* more step down the tree until the name runs out or the search
* fails.
*/
NetScope* Design::find_scope_(NetScope*scope, const hname_t&path,
NetScope::TYPE type) const
{
/* If we are looking for a module or we are not
* looking at the last path component check for
* a name match (second line). */
if ((scope->type() == NetScope::MODULE) && (type == NetScope::MODULE)
&& (scope->module_name() == path.peek_name())) {
/* Up references may match module name */
return scope;
}
return scope->child( path );
}
/* /*
* This is a relative lookup of a scope by name. The starting point is * This is a relative lookup of a scope by name. The starting point is
* the scope parameter within which I start looking for the scope. If * the scope parameter within which I start looking for the scope. If
@ -307,24 +333,36 @@ NetScope* Design::find_scope(NetScope*scope, const hname_t&path,
{ {
assert(scope); assert(scope);
for ( ; scope ; scope = scope->parent()) { // Record the compilation unit scope for use later.
NetScope*unit_scope = scope->unit();
NetScope*cur = scope; // First search upwards through the hierarchy.
while (scope) {
NetScope*found_scope = find_scope_(scope, path, type);
if (found_scope)
return found_scope;
/* If we are looking for a module or we are not // Avoid searching the unit scope twice.
* looking at the last path component check for if (scope == unit_scope)
* a name match (second line). */ unit_scope = 0;
if (cur->type() == NetScope::MODULE
&& (type == NetScope::MODULE)
&& cur->module_name()==path.peek_name()) {
/* Up references may match module name */ // Special case - see IEEE 1800-2012 section 23.8.1.
if (unit_scope && is_design_unit(scope) && is_subroutine(type)) {
found_scope = find_scope_(unit_scope, path, type);
if (found_scope)
return found_scope;
} else { unit_scope = 0;
cur = cur->child( path );
} }
if (cur) return cur; scope = scope->parent();
}
// If we haven't already done so, search the compilation unit scope.
if (unit_scope) {
NetScope*found_scope = find_scope_(unit_scope, path, type);
if (found_scope)
return found_scope;
} }
// Last chance. Look for the name starting at the root. // Last chance. Look for the name starting at the root.
@ -867,11 +905,6 @@ NetScope* Design::find_task(NetScope*scope, const pform_name_t&name)
return 0; return 0;
} }
void Design::add_root_task(NetScope*tscope, PTaskFunc*tf)
{
root_tasks_[tscope] = tf;
}
void Design::add_node(NetNode*net) void Design::add_node(NetNode*net)
{ {
assert(net->design_ == 0); assert(net->design_ == 0);

View File

@ -112,10 +112,10 @@ void Definitions::add_class(netclass_t*net_class)
* in question. * in question.
*/ */
NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest, NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, NetScope*unit,
bool program, bool interface) bool nest, bool program, bool interface, bool compilation_unit)
: type_(t), name_(n), nested_module_(nest), program_block_(program), : type_(t), name_(n), nested_module_(nest), program_block_(program),
is_interface_(interface), up_(up) is_interface_(interface), is_unit_(compilation_unit), unit_(unit), up_(up)
{ {
events_ = 0; events_ = 0;
lcounter_ = 0; lcounter_ = 0;
@ -124,6 +124,9 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest,
calls_stask_ = false; calls_stask_ = false;
in_final_ = false; in_final_ = false;
if (compilation_unit)
unit_ = this;
if (up) { if (up) {
assert(t!=CLASS); assert(t!=CLASS);
need_const_func_ = up->need_const_func_; need_const_func_ = up->need_const_func_;
@ -133,6 +136,8 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest,
time_from_timescale_ = up->time_from_timescale(); time_from_timescale_ = up->time_from_timescale();
// Need to check for duplicate names? // Need to check for duplicate names?
up_->children_[name_] = this; up_->children_[name_] = this;
if (unit_ == 0)
unit_ = up_->unit_;
} else { } else {
need_const_func_ = false; need_const_func_ = false;
is_const_func_ = false; is_const_func_ = false;
@ -210,6 +215,8 @@ const netenum_t*NetScope::find_enumeration_for_name(perm_string name)
NetEConstEnum*tmp = cur_scope->enum_names_[name]; NetEConstEnum*tmp = cur_scope->enum_names_[name];
if (tmp) break; if (tmp) break;
cur_scope = cur_scope->parent(); cur_scope = cur_scope->parent();
if (cur_scope == 0)
cur_scope = unit_;
} }
assert(cur_scope); assert(cur_scope);
@ -364,12 +371,7 @@ const NetExpr* NetScope::get_parameter(Design*des,
msb = 0; msb = 0;
lsb = 0; lsb = 0;
const NetExpr*tmp = enumeration_expr(key); const NetExpr*tmp = enumeration_expr(key);
if (tmp) return tmp; return tmp;
tmp = des->enumeration_expr(key);
if (tmp) return tmp;
return 0;
} }
NetScope::param_ref_t NetScope::find_parameter(perm_string key) NetScope::param_ref_t NetScope::find_parameter(perm_string key)
@ -386,11 +388,6 @@ NetScope::param_ref_t NetScope::find_parameter(perm_string key)
return idx; return idx;
} }
NetScope::TYPE NetScope::type() const
{
return type_;
}
void NetScope::print_type(ostream&stream) const void NetScope::print_type(ostream&stream) const
{ {
switch (type_) { switch (type_) {
@ -657,15 +654,11 @@ netclass_t*NetScope::find_class(perm_string name)
if (type_==CLASS && name_==hname_t(name)) if (type_==CLASS && name_==hname_t(name))
return class_def_; return class_def_;
// Look for the class that directly within this scope. // Look for the class directly within this scope.
map<perm_string,netclass_t*>::const_iterator cur = classes_.find(name); map<perm_string,netclass_t*>::const_iterator cur = classes_.find(name);
if (cur != classes_.end()) if (cur != classes_.end())
return cur->second; return cur->second;
// If this is a module scope, then look no further.
if (type_==MODULE)
return 0;
if (up_==0 && type_==CLASS) { if (up_==0 && type_==CLASS) {
assert(class_def_); assert(class_def_);
@ -673,12 +666,16 @@ netclass_t*NetScope::find_class(perm_string name)
return def_parent->find_class(name); return def_parent->find_class(name);
} }
// If there is no further to look, ...
if (up_ == 0)
return 0;
// Try looking up for the class. // Try looking up for the class.
return up_->find_class(name); if (up_!=0 && type_!=MODULE)
return up_->find_class(name);
// Try the compilation unit.
if (unit_ != 0)
return unit_->find_class(name);
// Nowhere left to try...
return 0;
} }
/* /*

View File

@ -927,10 +927,13 @@ class NetScope : public Definitions, public Attrib {
public: public:
enum TYPE { MODULE, CLASS, TASK, FUNC, BEGIN_END, FORK_JOIN, GENBLOCK, PACKAGE }; enum TYPE { MODULE, CLASS, TASK, FUNC, BEGIN_END, FORK_JOIN, GENBLOCK, PACKAGE };
/* Create a new scope, and attach it to the given parent. The /* Create a new scope associated with a given compilation unit,
name is expected to have been permallocated. */ and attach it to the given parent. If no compilation unit is
NetScope(NetScope*up, const hname_t&name, TYPE t, bool nest=false, specified, the parent's compilation unit is used. The name
bool program=false, bool interface=false); is expected to have been permallocated. */
NetScope(NetScope*up, const hname_t&name, TYPE t, NetScope*unit=0,
bool nest=false, bool program=false, bool interface=false,
bool compilation_unit=false);
~NetScope(); ~NetScope();
/* Rename the scope using the name generated by inserting as /* Rename the scope using the name generated by inserting as
@ -1002,10 +1005,12 @@ class NetScope : public Definitions, public Attrib {
netclass_t* find_class(perm_string name); netclass_t* find_class(perm_string name);
/* The parent and child() methods allow users of NetScope /* The unit(), parent(), and child() methods allow users of
objects to locate nearby scopes. */ NetScope objects to locate nearby scopes. */
NetScope* unit() { return unit_; }
NetScope* parent() { return up_; } NetScope* parent() { return up_; }
NetScope* child(const hname_t&name); NetScope* child(const hname_t&name);
const NetScope* unit() const { return unit_; }
const NetScope* parent() const { return up_; } const NetScope* parent() const { return up_; }
const NetScope* child(const hname_t&name) const; const NetScope* child(const hname_t&name) const;
@ -1023,7 +1028,8 @@ class NetScope : public Definitions, public Attrib {
// Program blocks and interfaces have elaboration constraints. // Program blocks and interfaces have elaboration constraints.
inline bool program_block() const { return program_block_; } inline bool program_block() const { return program_block_; }
inline bool is_interface() const { return is_interface_; } inline bool is_interface() const { return is_interface_; }
TYPE type() const; inline bool is_unit() const { return is_unit_; }
inline TYPE type() const { return type_; }
void print_type(ostream&) const; void print_type(ostream&) const;
// This provides a link to the variable initialisation process // This provides a link to the variable initialisation process
@ -1249,6 +1255,8 @@ class NetScope : public Definitions, public Attrib {
bool program_block_; bool program_block_;
// True if the scope is an interface // True if the scope is an interface
bool is_interface_; bool is_interface_;
// True if the scope is a compilation unit
bool is_unit_;
perm_string file_; perm_string file_;
perm_string def_file_; perm_string def_file_;
@ -1279,6 +1287,7 @@ class NetScope : public Definitions, public Attrib {
const PFunction*func_pform_; const PFunction*func_pform_;
unsigned elab_stage_; unsigned elab_stage_;
NetScope*unit_;
NetScope*up_; NetScope*up_;
map<hname_t,NetScope*> children_; map<hname_t,NetScope*> children_;
@ -4835,7 +4844,7 @@ struct elaborator_work_item_t {
* This class contains an entire design. It includes processes and a * This class contains an entire design. It includes processes and a
* netlist, and can be passed around from function to function. * netlist, and can be passed around from function to function.
*/ */
class Design : public Definitions { class Design {
public: public:
Design(); Design();
@ -4857,12 +4866,13 @@ class Design : public Definitions {
const char* get_flag(const string&key) const; const char* get_flag(const string&key) const;
NetScope* make_root_scope(perm_string name, bool program_block, NetScope* make_root_scope(perm_string name, NetScope*unit_scope,
bool is_interface); bool program_block, bool is_interface);
NetScope* find_root_scope(); NetScope* find_root_scope();
std::list<NetScope*> find_root_scopes() const; std::list<NetScope*> find_root_scopes() const;
NetScope* make_package_scope(perm_string name); NetScope* make_package_scope(perm_string name, NetScope*unit_scope,
bool is_unit);
std::list<NetScope*> find_package_scopes() const; std::list<NetScope*> find_package_scopes() const;
/* Attempt to set the precision to the specified value. If the /* Attempt to set the precision to the specified value. If the
@ -4912,11 +4922,6 @@ class Design : public Definitions {
// Look for defparams that never matched, and print warnings. // Look for defparams that never matched, and print warnings.
void residual_defparams(); void residual_defparams();
// Do elaborate_sig for objects in $root scope.
void root_elaborate_sig(void);
void root_elaborate(void);
/* This method locates a signal, starting at a given /* This method locates a signal, starting at a given
scope. The name parameter may be partially hierarchical, so scope. The name parameter may be partially hierarchical, so
this method, unlike the NetScope::find_signal method, this method, unlike the NetScope::find_signal method,
@ -4929,12 +4934,6 @@ class Design : public Definitions {
// Tasks // Tasks
NetScope* find_task(NetScope*scope, const pform_name_t&name); NetScope* find_task(NetScope*scope, const pform_name_t&name);
void add_root_task(NetScope*tscope, PTaskFunc*tf);
std::list<NetScope*> find_roottask_scopes(void) const;
// Find a class in the $root scope.
void add_class(netclass_t*cl, PClass*pclass);
netclass_t* find_class(perm_string name) const;
// NODES // NODES
void add_node(NetNode*); void add_node(NetNode*);
@ -4962,6 +4961,12 @@ class Design : public Definitions {
unsigned errors; unsigned errors;
private: private:
NetScope* find_scope_(NetScope*, const hname_t&name,
NetScope::TYPE type = NetScope::MODULE) const;
NetScope* find_scope_(NetScope*, const std::list<hname_t>&path,
NetScope::TYPE type = NetScope::MODULE) const;
// Keep a tree of scopes. The NetScope class handles the wide // Keep a tree of scopes. The NetScope class handles the wide
// tree and per-hop searches for me. // tree and per-hop searches for me.
list<NetScope*>root_scopes_; list<NetScope*>root_scopes_;
@ -4970,12 +4975,6 @@ class Design : public Definitions {
// packages do not nest. // packages do not nest.
std::map<perm_string,NetScope*>packages_; std::map<perm_string,NetScope*>packages_;
// Tasks in the $root scope
std::map<NetScope*,PTaskFunc*>root_tasks_;
// Need this for elaboration of $root scope pclass objects.
std::map<netclass_t*,PClass*> class_to_pclass_;
// List the nodes in the design. // List the nodes in the design.
NetNode*nodes_; NetNode*nodes_;
// These are in support of the node functor iterator. // These are in support of the node functor iterator.

View File

@ -42,20 +42,13 @@ 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::map<perm_string,data_type_t*> pform_typedefs; extern std::vector<PPackage*> pform_units;
extern std::set<enum_type_t*> pform_enum_sets;
extern std::map<perm_string,PTaskFunc*> pform_tasks;
extern std::vector<PClass*> pform_classes;
extern std::map<perm_string,PPackage*> pform_packages; extern std::map<perm_string,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);
extern void pform_dump(std::ostream&out, const PTaskFunc*tf); extern void pform_dump(std::ostream&out, const PTaskFunc*tf);
extern void elaborate_rootscope_enumerations(Design*des);
extern void elaborate_rootscope_classes(Design*des);
extern void elaborate_rootscope_tasks(Design*des);
/* /*
* This code actually invokes the parser to make modules. If the path * This code actually invokes the parser to make modules. If the path
* parameter is "-", the parser reads from stdin, otherwise it attempts * parameter is "-", the parser reads from stdin, otherwise it attempts

138
pform.cc
View File

@ -63,20 +63,18 @@ map<perm_string,Module*> pform_modules;
map<perm_string,PUdp*> pform_primitives; map<perm_string,PUdp*> pform_primitives;
/* /*
* typedefs in the $root scope go here. * The pform_units is a list of the SystemVerilog compilation unit scopes.
* The current compilation unit is the last element in the list. All items
* declared or defined at the top level (outside any design element) are
* added to the current compilation unit scope.
*/ */
map<perm_string,data_type_t*>pform_typedefs; vector<PPackage*> pform_units;
set<enum_type_t*>pform_enum_sets;
/* static bool is_compilation_unit(LexicalScope*scope)
* Class definitions in the $root scope go here. {
*/ // A compilation unit is the only scope that doesn't have a parent.
vector<PClass*> pform_classes; return scope->parent_scope() == 0;
}
/*
* Task and function definitions in the $root scope go here.
*/
map<perm_string,PTaskFunc*> pform_tasks;
std::string vlltype::get_fileline() const std::string vlltype::get_fileline() const
{ {
@ -406,6 +404,7 @@ void pform_pop_scope()
{ {
assert(lexical_scope); assert(lexical_scope);
lexical_scope = lexical_scope->parent_scope(); lexical_scope = lexical_scope->parent_scope();
assert(lexical_scope);
} }
static LexicalScope::lifetime_t find_lifetime(LexicalScope::lifetime_t lifetime) static LexicalScope::lifetime_t find_lifetime(LexicalScope::lifetime_t lifetime)
@ -413,10 +412,7 @@ static LexicalScope::lifetime_t find_lifetime(LexicalScope::lifetime_t lifetime)
if (lifetime != LexicalScope::INHERITED) if (lifetime != LexicalScope::INHERITED)
return lifetime; return lifetime;
if (lexical_scope != 0) return lexical_scope->default_lifetime;
return lexical_scope->default_lifetime;
return LexicalScope::STATIC;
} }
static PScopeExtra* find_nearest_scopex(LexicalScope*scope) static PScopeExtra* find_nearest_scopex(LexicalScope*scope)
@ -440,7 +436,7 @@ static void pform_set_scope_timescale(PScope*scope, const struct vlltype&loc)
* a timescale directive. */ * a timescale directive. */
scope->time_from_timescale = pform_timescale_file != 0; scope->time_from_timescale = pform_timescale_file != 0;
if (warn_timescale && (lexical_scope == 0) && pform_timescale_file if (warn_timescale && is_compilation_unit(lexical_scope) && pform_timescale_file
&& (strcmp(pform_timescale_file, loc.text) != 0)) { && (strcmp(pform_timescale_file, loc.text) != 0)) {
cerr << loc.get_fileline() << ": warning: " cerr << loc.get_fileline() << ": warning: "
@ -461,17 +457,9 @@ PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name,
pform_set_scope_timescale(class_scope, loc); pform_set_scope_timescale(class_scope, loc);
PScopeExtra*scopex = find_nearest_scopex(lexical_scope); PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
assert(scopex);
assert(!pform_cur_generate); assert(!pform_cur_generate);
/* If no scope was found then this is being defined in the
* compilation unit scope. */
if (scopex == 0) {
pform_classes.push_back(class_scope);
lexical_scope = class_scope;
return class_scope;
}
if (scopex->classes.find(name) != scopex->classes.end()) { if (scopex->classes.find(name) != scopex->classes.end()) {
cerr << class_scope->get_fileline() << ": error: duplicate " cerr << class_scope->get_fileline() << ": error: duplicate "
"definition for class '" << name << "' in '" "definition for class '" << name << "' in '"
@ -513,7 +501,8 @@ PTask* pform_push_task_scope(const struct vlltype&loc, char*name,
pform_set_scope_timescale(task, loc); pform_set_scope_timescale(task, loc);
PScopeExtra*scopex = find_nearest_scopex(lexical_scope); PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
if ((scopex == 0) && !gn_system_verilog()) { assert(scopex);
if (is_compilation_unit(scopex) && !gn_system_verilog()) {
cerr << task->get_fileline() << ": error: task declarations " cerr << task->get_fileline() << ": error: task declarations "
"must be contained within a module." << endl; "must be contained within a module." << endl;
error_count += 1; error_count += 1;
@ -530,7 +519,7 @@ PTask* pform_push_task_scope(const struct vlltype&loc, char*name,
error_count += 1; error_count += 1;
} }
pform_cur_generate->tasks[task->pscope_name()] = task; pform_cur_generate->tasks[task->pscope_name()] = task;
} else if (scopex) { } else {
// Check if the task is already in the dictionary. // Check if the task is already in the dictionary.
if (scopex->tasks.find(task->pscope_name()) != scopex->tasks.end()) { if (scopex->tasks.find(task->pscope_name()) != scopex->tasks.end()) {
cerr << task->get_fileline() << ": error: duplicate " cerr << task->get_fileline() << ": error: duplicate "
@ -539,15 +528,6 @@ PTask* pform_push_task_scope(const struct vlltype&loc, char*name,
error_count += 1; error_count += 1;
} }
scopex->tasks[task->pscope_name()] = task; scopex->tasks[task->pscope_name()] = task;
} else {
if (pform_tasks.find(task_name) != pform_tasks.end()) {
cerr << task->get_fileline() << ": error: "
<< "Duplicate definition for task '" << name
<< "' in $root scope." << endl;
error_count += 1;
}
pform_tasks[task_name] = task;
} }
lexical_scope = task; lexical_scope = task;
@ -570,7 +550,8 @@ PFunction* pform_push_function_scope(const struct vlltype&loc, const char*name,
pform_set_scope_timescale(func, loc); pform_set_scope_timescale(func, loc);
PScopeExtra*scopex = find_nearest_scopex(lexical_scope); PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
if ((scopex == 0) && !gn_system_verilog()) { assert(scopex);
if (is_compilation_unit(scopex) && !gn_system_verilog()) {
cerr << func->get_fileline() << ": error: function declarations " cerr << func->get_fileline() << ": error: function declarations "
"must be contained within a module." << endl; "must be contained within a module." << endl;
error_count += 1; error_count += 1;
@ -588,7 +569,7 @@ PFunction* pform_push_function_scope(const struct vlltype&loc, const char*name,
} }
pform_cur_generate->funcs[func->pscope_name()] = func; pform_cur_generate->funcs[func->pscope_name()] = func;
} else if (scopex != 0) { } else {
// Check if the function is already in the dictionary. // Check if the function is already in the dictionary.
if (scopex->funcs.find(func->pscope_name()) != scopex->funcs.end()) { if (scopex->funcs.find(func->pscope_name()) != scopex->funcs.end()) {
cerr << func->get_fileline() << ": error: duplicate " cerr << func->get_fileline() << ": error: duplicate "
@ -597,15 +578,6 @@ PFunction* pform_push_function_scope(const struct vlltype&loc, const char*name,
error_count += 1; error_count += 1;
} }
scopex->funcs[func->pscope_name()] = func; scopex->funcs[func->pscope_name()] = func;
} else {
if (pform_tasks.find(func_name) != pform_tasks.end()) {
cerr << func->get_fileline() << ": error: "
<< "Duplicate definition for function '" << name
<< "' in $root scope." << endl;
error_count += 1;
}
pform_tasks[func_name] = func;
} }
lexical_scope = func; lexical_scope = func;
@ -705,11 +677,7 @@ static void pform_put_wire_in_scope(perm_string name, PWire*net)
static void pform_put_enum_type_in_scope(enum_type_t*enum_set) static void pform_put_enum_type_in_scope(enum_type_t*enum_set)
{ {
if (lexical_scope) { lexical_scope->enum_sets.insert(enum_set);
lexical_scope->enum_sets.insert(enum_set);
} else {
pform_enum_sets.insert(enum_set);
}
} }
PWire*pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_type, NetNet::PortType port_type, ivl_variable_type_t vt_type) PWire*pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_type, NetNet::PortType port_type, ivl_variable_type_t vt_type)
@ -736,12 +704,7 @@ void pform_set_typedef(perm_string name, data_type_t*data_type, std::list<pform_
if(unp_ranges) if(unp_ranges)
data_type = new uarray_type_t(data_type, unp_ranges); data_type = new uarray_type_t(data_type, unp_ranges);
// If we are in a lexical scope (i.e. a package or module) data_type_t*&ref = lexical_scope->typedefs[name];
// then put the typedef into that scope. Otherwise, put it
// into the $root scope.
data_type_t*&ref = lexical_scope
? lexical_scope->typedefs[name]
: pform_typedefs[name];
ivl_assert(*data_type, ref == 0); ivl_assert(*data_type, ref == 0);
ref = data_type; ref = data_type;
@ -751,25 +714,10 @@ void pform_set_typedef(perm_string name, data_type_t*data_type, std::list<pform_
} }
} }
static data_type_t* test_type_identifier_in_root(perm_string name)
{
map<perm_string,data_type_t*>::iterator cur = pform_typedefs.find(name);
if (cur != pform_typedefs.end())
return cur->second;
else
return 0;
}
data_type_t* pform_test_type_identifier(const char*txt) data_type_t* pform_test_type_identifier(const char*txt)
{ {
perm_string name = lex_strings.make(txt); perm_string name = lex_strings.make(txt);
// If there is no lexical_scope yet, then look only in the
// $root scope for typedefs.
if (lexical_scope == 0) {
return test_type_identifier_in_root(name);
}
LexicalScope*cur_scope = lexical_scope; LexicalScope*cur_scope = lexical_scope;
do { do {
map<perm_string,data_type_t*>::iterator cur; map<perm_string,data_type_t*>::iterator cur;
@ -799,10 +747,6 @@ data_type_t* pform_test_type_identifier(const char*txt)
cur_scope = cur_scope->parent_scope(); cur_scope = cur_scope->parent_scope();
} while (cur_scope); } while (cur_scope);
// See if there is a typedef in the $root scope.
if (data_type_t*tmp = test_type_identifier_in_root(name))
return tmp;
return 0; return 0;
} }
@ -813,13 +757,6 @@ data_type_t* pform_test_type_identifier(const char*txt)
*/ */
bool pform_test_type_identifier_local(perm_string name) bool pform_test_type_identifier_local(perm_string name)
{ {
if (lexical_scope == 0) {
if (test_type_identifier_in_root(name))
return true;
else
return false;
}
LexicalScope*cur_scope = lexical_scope; LexicalScope*cur_scope = lexical_scope;
map<perm_string,data_type_t*>::iterator cur; map<perm_string,data_type_t*>::iterator cur;
@ -1418,11 +1355,9 @@ void pform_endmodule(const char*name, bool inside_celldefine,
use_module_map[mod_name] = cur_module; use_module_map[mod_name] = cur_module;
} }
// The current lexical scope should be this module by now, and // The current lexical scope should be this module by now.
// this module should not have a parent lexical scope.
ivl_assert(*cur_module, lexical_scope == cur_module); ivl_assert(*cur_module, lexical_scope == cur_module);
pform_pop_scope(); pform_pop_scope();
ivl_assert(*cur_module, ! pform_cur_module.empty() || lexical_scope == 0);
tp_decl_flag = false; tp_decl_flag = false;
tu_decl_flag = false; tu_decl_flag = false;
@ -2773,11 +2708,11 @@ void pform_makewire(const struct vlltype&li,
NetNet::Type type, NetNet::Type type,
data_type_t*data_type) data_type_t*data_type)
{ {
if ((lexical_scope == 0) && !gn_system_verilog()) { if (is_compilation_unit(lexical_scope) && !gn_system_verilog()) {
VLerror(li, "error: variable declarations must be contained within a module."); VLerror(li, "error: variable declarations must be contained within a module.");
return; return;
} }
if (lexical_scope == 0) { if (is_compilation_unit(lexical_scope)) {
VLerror(li, "sorry: variable declarations in the $root scope are not yet supported."); VLerror(li, "sorry: variable declarations in the $root scope are not yet supported.");
return; return;
} }
@ -3080,11 +3015,11 @@ void pform_set_parameter(const struct vlltype&loc,
LexicalScope::range_t*value_range) LexicalScope::range_t*value_range)
{ {
LexicalScope*scope = lexical_scope; LexicalScope*scope = lexical_scope;
if ((scope == 0) && !gn_system_verilog()) { if (is_compilation_unit(scope) && !gn_system_verilog()) {
VLerror(loc, "error: parameter declarations must be contained within a module."); VLerror(loc, "error: parameter declarations must be contained within a module.");
return; return;
} }
if (scope == 0) { if (is_compilation_unit(scope)) {
VLerror(loc, "sorry: parameter declarations in the $root scope are not yet supported."); VLerror(loc, "sorry: parameter declarations in the $root scope are not yet supported.");
return; return;
} }
@ -3155,11 +3090,11 @@ void pform_set_localparam(const struct vlltype&loc,
bool signed_flag, list<pform_range_t>*range, PExpr*expr) bool signed_flag, list<pform_range_t>*range, PExpr*expr)
{ {
LexicalScope*scope = lexical_scope; LexicalScope*scope = lexical_scope;
if ((scope == 0) && !gn_system_verilog()) { if (is_compilation_unit(scope) && !gn_system_verilog()) {
VLerror(loc, "error: localparam declarations must be contained within a module."); VLerror(loc, "error: localparam declarations must be contained within a module.");
return; return;
} }
if (scope == 0) { if (is_compilation_unit(scope)) {
VLerror(loc, "sorry: localparam declarations in the $root scope are not yet supported."); VLerror(loc, "sorry: localparam declarations in the $root scope are not yet supported.");
return; return;
} }
@ -3749,6 +3684,21 @@ int pform_parse(const char*path)
} }
} }
if (pform_units.empty() || separate_compilation) {
char unit_name[20];
static unsigned nunits = 0;
if (separate_compilation)
sprintf(unit_name, "$unit#%u", ++nunits);
else
sprintf(unit_name, "$unit");
PPackage*unit = new PPackage(lex_strings.make(unit_name), 0);
unit->default_lifetime = LexicalScope::STATIC;
unit->time_unit = def_ts_units;
unit->time_precision = def_ts_prec;
unit->time_from_timescale = false;
pform_units.push_back(unit);
lexical_scope = unit;
}
reset_lexor(); reset_lexor();
error_count = 0; error_count = 0;
warn_count = 0; warn_count = 0;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003-2015 Stephen Williams (steve@icarus.com) * Copyright (c) 2003-2017 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com) * Copyright CERN 2012 / 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
@ -143,14 +143,21 @@ static bool symbol_search(const LineInfo*li, Design*des, NetScope*scope,
} }
} }
// Don't scan up past a module boundary.
if (scope->type()==NetScope::MODULE && !scope->nested_module())
break;
// Don't scan up if we are searching within a prefixed scope. // Don't scan up if we are searching within a prefixed scope.
if (prefix_scope) if (prefix_scope)
break; break;
scope = scope->parent(); // Don't scan up past a module boundary.
if (scope->type()==NetScope::MODULE && !scope->nested_module())
scope = 0;
else
scope = scope->parent();
// Last chance - try the compilation unit.
if (scope == 0 && start_scope != 0) {
scope = start_scope->unit();
start_scope = 0;
}
} }
// Last chance: this is a single name, so it might be the name // Last chance: this is a single name, so it might be the name

View File

@ -93,10 +93,7 @@ extern "C" void ivl_design_roots(ivl_design_t des, ivl_scope_t **scopes,
assert (nscopes && scopes); assert (nscopes && scopes);
if (des->root_scope_list.size() == 0) { if (des->root_scope_list.size() == 0) {
size_t fill = 0; size_t fill = 0;
des->root_scope_list.resize(des->root_tasks.size() + des->packages.size() + des->roots.size() + des->classes.size()); des->root_scope_list.resize(des->packages.size() + des->roots.size() + des->classes.size());
for (map<const NetScope*,ivl_scope_t>::iterator idx = des->root_tasks.begin()
; idx != des->root_tasks.end() ; ++ idx)
des->root_scope_list[fill++] = idx->second;
for (map<const NetScope*,ivl_scope_t>::iterator idx = des->classes.begin() for (map<const NetScope*,ivl_scope_t>::iterator idx = des->classes.begin()
; idx != des->classes.end() ; ++ idx) ; idx != des->classes.end() ; ++ idx)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com) * Copyright (c) 2000-2017 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / 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
@ -261,12 +261,6 @@ ivl_scope_t dll_target::find_scope(ivl_design_s &des, const NetScope*cur)
return tmp; return tmp;
} }
if (cur->type()==NetScope::TASK || cur->type()==NetScope::FUNC) {
map<const NetScope*,ivl_scope_t>::const_iterator idx = des.root_tasks.find(cur);
if (idx != des.root_tasks.end())
return idx->second;
}
for (unsigned idx = 0; idx < des.roots.size(); idx += 1) { for (unsigned idx = 0; idx < des.roots.size(); idx += 1) {
assert(des.roots[idx]); assert(des.roots[idx]);
ivl_scope_t scope = find_scope_from_root(des.roots[idx], cur); ivl_scope_t scope = find_scope_from_root(des.roots[idx], cur);
@ -288,13 +282,6 @@ ivl_scope_t dll_target::find_scope(ivl_design_s &des, const NetScope*cur)
return scope; return scope;
} }
for (map<const NetScope*,ivl_scope_t>::iterator idx = des.root_tasks.begin()
; idx != des.root_tasks.end() ; ++ idx) {
ivl_scope_t scope = find_scope_from_root(idx->second, cur);
if (scope)
return scope;
}
return 0; return 0;
} }
@ -657,22 +644,6 @@ void dll_target::add_root(const NetScope *s)
case NetScope::CLASS: case NetScope::CLASS:
root_->type_ = IVL_SCT_CLASS; root_->type_ = IVL_SCT_CLASS;
break; break;
case NetScope::TASK: {
const NetTaskDef*def = s->task_def();
if (def == 0) {
cerr << "?:?" << ": internal error: "
<< "task " << root_->name_
<< " has no definition." << endl;
}
assert(def);
root_->type_ = IVL_SCT_TASK;
root_->tname_ = def->scope()->basename();
break;
}
break;
case NetScope::FUNC:
fill_in_scope_function(root_, s);
break;
default: default:
assert(0); assert(0);
} }
@ -701,11 +672,6 @@ void dll_target::add_root(const NetScope *s)
des_.classes[s] = root_; des_.classes[s] = root_;
break; break;
case NetScope::TASK:
case NetScope::FUNC:
des_.root_tasks[s] = root_;
break;
default: default:
assert(0); assert(0);
break; break;
@ -747,11 +713,7 @@ bool dll_target::start_design(const Design*des)
} }
assert(idx == des_.disciplines.size()); assert(idx == des_.disciplines.size());
list<NetScope *> scope_list = des->find_roottask_scopes(); list<NetScope *> scope_list;
for (list<NetScope*>::const_iterator cur = scope_list.begin()
; cur != scope_list.end() ; ++ cur) {
add_root(*cur);
}
scope_list = des->find_package_scopes(); scope_list = des->find_package_scopes();
for (list<NetScope*>::const_iterator cur = scope_list.begin() for (list<NetScope*>::const_iterator cur = scope_list.begin()