diff --git a/design_dump.cc b/design_dump.cc index b86fc389c..113ce5bc0 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -1879,6 +1879,12 @@ void Design::dump(ostream&o) const cur->second->dump(o); } + o << "$ROOT CLASSESS:" << endl; + for (map::const_iterator cur = classes_.begin() + ; cur != classes_.end() ; ++cur) { + cur->second->dump_scope(o); + } + o << "SCOPES:" << endl; for (list::const_iterator scope = root_scopes_.begin(); scope != root_scopes_.end(); ++ scope ) { diff --git a/elab_expr.cc b/elab_expr.cc index 7832fcf85..965f65075 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -5093,6 +5093,8 @@ NetExpr* PENewClass::elaborate_expr_constructor_(Design*des, NetScope*scope, const netclass_t*ctype, NetExpr*obj, unsigned /*flags*/) const { + ivl_assert(*this, ctype); + // If there is an initializer function, then pass the object // through that function first. Note that the initializer // function has no arguments other than the object itself. @@ -5130,6 +5132,12 @@ NetExpr* PENewClass::elaborate_expr_constructor_(Design*des, NetScope*scope, NetFuncDef*def = new_scope->func_def(); + if (def == 0) { + cerr << get_fileline() << ": internal error: " + << "Scope " << scope_path(new_scope) + << " is missing constructor definition." << endl; + des->errors += 1; + } ivl_assert(*this, def); // Are there too many arguments passed to the function. If so, diff --git a/elab_scope.cc b/elab_scope.cc index e611a9073..98d1718e3 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -442,21 +442,15 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass) for (map::iterator cur = use_type->properties.begin() ; cur != use_type->properties.end() ; ++ cur) { - if (scope) { - ivl_type_s*tmp = cur->second.type->elaborate_type(des, scope); - ivl_assert(*pclass, tmp); - if (debug_scopes) { - cerr << pclass->get_fileline() << ": elaborate_scope_class: " - << " Property " << cur->first - << " type=" << *tmp << endl; - } - use_class->set_property(cur->first, cur->second.qual, tmp); - } else { - cerr << pclass->get_fileline() << ": sorry: Don't know how to elaborate " - << "property " << cur->first - << " for class type in $root scope," << endl; - des->errors += 1; + ivl_type_s*tmp = cur->second.type->elaborate_type(des, scope); + ivl_assert(*pclass, tmp); + if (debug_scopes) { + cerr << pclass->get_fileline() << ": elaborate_scope_class: " + << " Property " << cur->first + << " type=" << *tmp << endl; } + use_class->set_property(cur->first, cur->second.qual, tmp); + } for (map::iterator cur = pclass->tasks.begin() @@ -499,9 +493,7 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass) scope->add_class(use_class); } else { - cerr << pclass->get_fileline() << ": sorry: " - << "Don't know how to elaborate class in $root scope." << endl; - des->errors += 1; + des->add_class(use_class, pclass); } } diff --git a/elab_sig.cc b/elab_sig.cc index 9d5df8245..316748ed4 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -836,10 +836,13 @@ void PWhile::elaborate_sig(Design*des, NetScope*scope) const statement_->elaborate_sig(des, scope); } -static netclass_t* locate_class_type(Design*, NetScope*scope, +static netclass_t* locate_class_type(Design*des, NetScope*scope, class_type_t*class_type) { netclass_t*use_class = scope->find_class(class_type->name); + if (use_class) return use_class; + + use_class = des->find_class(class_type->name); return use_class; } @@ -1301,3 +1304,16 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const return sig; } + + +void Design::root_elaborate_sig(void) +{ + for (map::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); + } +} diff --git a/elab_type.cc b/elab_type.cc index 2f3dab573..41c3c68ca 100644 --- a/elab_type.cc +++ b/elab_type.cc @@ -38,8 +38,12 @@ using namespace std; */ ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*scope) { - map::iterator pos = cache_type_elaborate_.lower_bound(scope); - if (pos->first == scope) + Definitions*use_definitions = scope; + if (use_definitions == 0) + use_definitions = des; + + map::iterator pos = cache_type_elaborate_.lower_bound(use_definitions); + if (pos->first == use_definitions) return pos->second; ivl_type_s*tmp = elaborate_type_raw(des, scope); @@ -91,9 +95,13 @@ ivl_type_s* atom2_type_t::elaborate_type_raw(Design*des, NetScope*) const } } -ivl_type_s* class_type_t::elaborate_type_raw(Design*, NetScope*scope) const +ivl_type_s* class_type_t::elaborate_type_raw(Design*des, NetScope*scope) const { - return scope->find_class(name); + ivl_type_s* found_class = scope->find_class(name); + if (found_class == 0) + found_class = des->find_class(name); + + return found_class; } /* @@ -219,6 +227,12 @@ ivl_type_s* uarray_type_t::elaborate_type_raw(Design*des, NetScope*scope) const vector dimensions; bool bad_range = evaluate_ranges(des, scope, dimensions, *dims); + if (bad_range) { + cerr << get_fileline() << " : warning: " + << "Bad dimensions for type here." << endl; + } + + ivl_assert(*this, btype); ivl_type_s*res = new netuarray_t(dimensions, btype); return res; } diff --git a/elaborate.cc b/elaborate.cc index c63566d47..3de901cec 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -2543,6 +2543,7 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const ivl_assert(*this, lv->word()); use_lv_type = utype->element_type(); + ivl_assert(*this, use_lv_type); rv = elaborate_rval_(des, scope, use_lv_type); } else { @@ -5962,6 +5963,16 @@ bool Design::check_proc_delay() const return result_flag; } +void Design::root_elaborate(void) +{ + for (map::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); + } +} + /* * This function is the root of all elaboration. The input is the list * of root module names. The function locates the Module definitions @@ -6093,6 +6104,11 @@ Design* elaborate(listroots) } } + if (debug_elaborate) { + cerr << ": elaborate: " + << "elaboration work list done. Start processing residual defparams." << endl; + } + // Look for residual defparams (that point to a non-existent // scope) and clean them out. des->residual_defparams(); @@ -6102,6 +6118,11 @@ Design* elaborate(listroots) if (des->errors > 0) return des; + if (debug_elaborate) { + cerr << ": elaborate: " + << "Start calling Package elaborate_sig methods." << endl; + } + // With the parameters evaluated down to constants, we have // what we need to elaborate signals and memories. This pass // creates all the NetNet and NetMemory objects for declared @@ -6120,6 +6141,18 @@ Design* elaborate(listroots) } } + if (debug_elaborate) { + cerr << ": elaborate: " + << "Start calling $root elaborate_sig methods." << endl; + } + + des->root_elaborate_sig(); + + if (debug_elaborate) { + cerr << ": elaborate: " + << "Start calling root module elaborate_sig methods." << endl; + } + for (i = 0; i < root_elems.size(); i++) { Module *rmod = root_elems[i].mod; NetScope *scope = root_elems[i].scope; @@ -6176,6 +6209,8 @@ Design* elaborate(listroots) rc &= pkg->elaborate(des, scope); } + des->root_elaborate(); + for (i = 0; i < root_elems.size(); i++) { Module *rmod = root_elems[i].mod; NetScope *scope = root_elems[i].scope; diff --git a/emit.cc b/emit.cc index c71e05c1e..fe6880156 100644 --- a/emit.cc +++ b/emit.cc @@ -510,6 +510,14 @@ int Design::emit(struct target_t*tgt) const scope->second->emit_scope(tgt); } + for (map::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); + cur->second->emit_defs(tgt); + } + // enumerate root scopes for (list::const_iterator scope = root_scopes_.begin() ; scope != root_scopes_.end(); ++ scope ) { diff --git a/net_design.cc b/net_design.cc index 8f89b003a..cd162d6b2 100644 --- a/net_design.cc +++ b/net_design.cc @@ -134,6 +134,21 @@ NetScope* Design::make_package_scope(perm_string name) 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::const_iterator cur = classes_.find(name); + if (cur != classes_.end()) + return cur->second; + + return 0; +} + NetScope* Design::find_package(perm_string name) const { map::const_iterator cur = packages_.find(name); diff --git a/net_scope.cc b/net_scope.cc index e20173ab9..ead04797b 100644 --- a/net_scope.cc +++ b/net_scope.cc @@ -96,6 +96,11 @@ const NetExpr* Definitions::enumeration_expr(perm_string key) } } +void Definitions::add_class(netclass_t*net_class) +{ + classes_[net_class->get_name()] = net_class; +} + /* * The NetScope class keeps a scope tree organized. Each node of the * scope tree points to its parent, its right sibling and its leftmost @@ -632,14 +637,9 @@ NetNet* NetScope::find_signal(perm_string key) return 0; } -void NetScope::add_class(netclass_t*net_class) -{ - classes_[net_class->get_name()] = net_class; -} - netclass_t*NetScope::find_class(perm_string name) { - // Special class: The scope itself is the class that we are + // Special case: The scope itself is the class that we are // looking for. This may happen for example when elaborating // methods within the class. if (type_==CLASS && name_==hname_t(name)) diff --git a/netclass.cc b/netclass.cc index 9c2d56c29..05fcd18e2 100644 --- a/netclass.cc +++ b/netclass.cc @@ -56,10 +56,10 @@ void netclass_t::set_class_scope(NetScope*class_scope) class_scope_ = class_scope; } -void netclass_t::set_definition_scope(NetScope*definition_scope) +void netclass_t::set_definition_scope(NetScope*use_definition_scope) { assert(definition_scope_ == 0); - definition_scope_ = definition_scope; + definition_scope_ = use_definition_scope; } ivl_variable_type_t netclass_t::base_type() const diff --git a/netclass.h b/netclass.h index 85ce90641..b6d26e114 100644 --- a/netclass.h +++ b/netclass.h @@ -47,6 +47,8 @@ class netclass_t : public ivl_type_s { // (tasks/functions). In other words, this is the class itself. void set_class_scope(NetScope*cscope); + inline const NetScope* class_scope(void) const { return class_scope_; } + // Set the scope for the class definition. This is the scope // where the class definition was encountered, and may be used // to locate symbols that the class definition may inherit diff --git a/netlist.h b/netlist.h index bf60aab0a..6d5563fb3 100644 --- a/netlist.h +++ b/netlist.h @@ -74,6 +74,7 @@ class NetRamDq; class NetTaskDef; class NetEvTrig; class NetEvWait; +class PClass; class PExpr; class PFunction; struct enum_type_t; @@ -888,6 +889,9 @@ class Definitions { // value. const NetExpr* enumeration_expr(perm_string key); + // Definitions scopes can also hold classes, by name. + void add_class(netclass_t*class_type); + protected: // Enumerations. The enum_sets_ is a list of all the // enumerations present in this scope. The enum_names_ is a @@ -896,6 +900,8 @@ class Definitions { std::map enum_sets_; std::map enum_names_; + std::map classes_; + }; /* @@ -980,7 +986,6 @@ class NetScope : public Definitions, public Attrib { void rem_signal(NetNet*); NetNet* find_signal(perm_string name); - void add_class(netclass_t*class_type); netclass_t* find_class(perm_string name); /* The parent and child() methods allow users of NetScope @@ -1239,8 +1244,6 @@ class NetScope : public Definitions, public Attrib { const PFunction*func_pform_; unsigned elab_stage_; - std::map classes_; - NetScope*up_; map children_; @@ -4790,6 +4793,11 @@ class Design : public Definitions { // Look for defparams that never matched, and print warnings. 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 scope. The name parameter may be partially hierarchical, so this method, unlike the NetScope::find_signal method, @@ -4803,6 +4811,10 @@ class Design : public Definitions { // Tasks NetScope* find_task(NetScope*scope, const pform_name_t&name); + // Find a class in the $root scope. + void add_class(netclass_t*cl, PClass*pclass); + netclass_t* find_class(perm_string name) const; + // NODES void add_node(NetNode*); void del_node(NetNode*); @@ -4837,6 +4849,9 @@ class Design : public Definitions { // packages do not nest. std::mappackages_; + // Need this for elaboration of $root scope pclass objects. + std::map class_to_pclass_; + // List the nodes in the design. NetNode*nodes_; // These are in support of the node functor iterator. diff --git a/pform_types.h b/pform_types.h index 15d3a4853..833dbb7f5 100644 --- a/pform_types.h +++ b/pform_types.h @@ -39,6 +39,7 @@ class Design; class NetScope; +class Definitions; class PExpr; class PWire; class Statement; @@ -133,7 +134,7 @@ class data_type_t : public LineInfo { virtual ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const; // Keep per-scope elaboration results cached. - std::map cache_type_elaborate_; + std::map cache_type_elaborate_; }; struct void_type_t : public data_type_t { diff --git a/t-dll-proc.cc b/t-dll-proc.cc index 87b49ed5c..e4a585103 100644 --- a/t-dll-proc.cc +++ b/t-dll-proc.cc @@ -102,6 +102,8 @@ bool dll_target::func_def(const NetScope*net) ivl_scope_t scop = lookup_scope_(net); const NetFuncDef*def = net->func_def(); + assert(def); + assert(def->proc()); assert(stmt_cur_ == 0); stmt_cur_ = (struct ivl_statement_s*)calloc(1, sizeof*stmt_cur_); def->proc()->emit_proc(this); diff --git a/t-dll.cc b/t-dll.cc index def9d01b5..054558c63 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -2411,6 +2411,11 @@ void dll_target::scope(const NetScope*net) { if (net->parent()==0 && net->type()==NetScope::CLASS) { + if (debug_emit) { + cerr << "dll_target::scope: " + << "Add class " << scope_path(net) + << " as a root scope." << endl; + } add_root(net); } if (net->parent() == 0) {