diff --git a/elaborate.cc b/elaborate.cc index 4cb32bdf7..f22e38f00 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -3819,6 +3819,32 @@ class top_defparams : public elaborator_work_item_t { } }; +class later_defparams : public elaborator_work_item_t { + public: + later_defparams(Design*des) + : elaborator_work_item_t(des) + { } + + ~later_defparams() { } + + virtual void elaborate_runrun() + { + listtmp_list; + for (set::iterator cur = des->defparams_later.begin() + ; cur != des->defparams_later.end() ; cur ++ ) + tmp_list.push_back(*cur); + + des->defparams_later.clear(); + + while (! tmp_list.empty()) { + NetScope*cur = tmp_list.front(); + tmp_list.pop_front(); + cur->run_defparams_later(des); + } + des->evaluate_parameters(); + } +}; + /* * This function is the root of all elaboration. The input is the list * of root module names. The function locates the Module definitions @@ -3890,12 +3916,33 @@ Design* elaborate(listroots) // empty. This list is initially populated above where the // initial root scopes are primed. while (! des->elaboration_work_list.empty()) { - elaborator_work_item_t*tmp = des->elaboration_work_list.front(); - des->elaboration_work_list.pop_front(); - tmp->elaborate_runrun(); - delete tmp; + // Transfer the queue to a temporary queue. + list cur_queue; + while (! des->elaboration_work_list.empty()) { + cur_queue.push_back(des->elaboration_work_list.front()); + des->elaboration_work_list.pop_front(); + } + + // Run from the temporary queue. If the temporary queue + // items create new work queue items, they will show up + // in the elaboration_work_list and then we get to run + // through them in the next pass. + while (! cur_queue.empty()) { + elaborator_work_item_t*tmp = cur_queue.front(); + cur_queue.pop_front(); + tmp->elaborate_runrun(); + delete tmp; + } + + if (! des->elaboration_work_list.empty()) { + des->elaboration_work_list.push_back(new later_defparams(des)); + } } + // Look for residual defparams (that point to a non-existent + // scope) and clean them out. + des->residual_defparams(); + // Errors already? Probably missing root modules. Just give up // now and return nothing. if (des->errors > 0) diff --git a/net_design.cc b/net_design.cc index 98900b180..595c1a44a 100644 --- a/net_design.cc +++ b/net_design.cc @@ -20,6 +20,7 @@ # include "config.h" # include +# include # include /* @@ -199,22 +200,6 @@ void Design::run_defparams() (*scope)->run_defparams(this); } -class run_defparams_later_t : public elaborator_work_item_t { - public: - run_defparams_later_t(Design*des, NetScope*scope) - : elaborator_work_item_t(des), scope_(scope) - { } - - void elaborate_runrun(); - private: - NetScope*scope_; -}; - -void run_defparams_later_t::elaborate_runrun() -{ - scope_->run_defparams_later(des); -} - void NetScope::run_defparams(Design*des) { { NetScope*cur = sub_; @@ -262,13 +247,19 @@ void NetScope::run_defparams(Design*des) } } - if (! defparams_later.empty()) { - des->elaboration_work_list.push_back(new run_defparams_later_t(des, this)); - } + + // If some of the defparams didn't find a scope in the name, + // then try again later. It may be that the target scope is + // created later by generate scheme or instance array. + if (! defparams_later.empty()) + des->defparams_later.insert(this); } void NetScope::run_defparams_later(Design*des) { + set target_scopes; + list,NetExpr*> > defparams_even_later; + while (! defparams_later.empty()) { pair,NetExpr*> cur = defparams_later.front(); defparams_later.pop_front(); @@ -281,8 +272,11 @@ void NetScope::run_defparams_later(Design*des) NetScope*targ_scope = des->find_scope(this, eval_path); if (targ_scope == 0) { - cerr << val->get_fileline() << ": warning: scope of " << - eval_path << "." << name << " not found." << endl; + // If a scope in the target path is not found, + // then push this defparam for handling even + // later. Maybe a later generate scheme or + // instance array will create the scope. + defparams_even_later.push_back(cur); continue; } @@ -296,7 +290,23 @@ void NetScope::run_defparams_later(Design*des) << name << " not found in " << scope_path(targ_scope) << "." << endl; } + + // We'll need to re-evaluate parameters in this scope + target_scopes.insert(targ_scope); } + + // All the scopes that this defparam set touched should have + // their parameters re-evaluated. + for (set::iterator cur = target_scopes.begin() + ; cur != target_scopes.end() ; cur ++ ) + (*cur)->evaluate_parameters(des); + + // If there are some scopes that still have missing scopes, + // then sav them back into the defparams_later list for a + // later pass. + defparams_later = defparams_even_later; + if (! defparams_later.empty()) + des->defparams_later.insert(this); } void Design::evaluate_parameters() @@ -576,6 +586,9 @@ void NetScope::evaluate_parameters(Design*des) cur = cur->sib_; } + if (debug_scopes) + cerr << ":0" << ": debug: " + << "Evaluate parameters in " << scope_path(this) << endl; // Evaluate the parameter values. The parameter expressions // have already been elaborated and replaced by the scope @@ -610,6 +623,32 @@ void NetScope::evaluate_parameters(Design*des) } +void Design::residual_defparams() +{ + for (list::const_iterator scope = root_scopes_.begin(); + scope != root_scopes_.end(); scope++) + (*scope)->residual_defparams(this); +} + +void NetScope::residual_defparams(Design*des) +{ + // Clean out the list of defparams that never managed to match + // a scope. Print a warning for each. + while (! defparams_later.empty()) { + pair,NetExpr*> cur = defparams_later.front(); + defparams_later.pop_front(); + + cerr << cur.second->get_fileline() << ": warning: " + << "Scope of " << cur.first << " not found." << endl; + } + + NetScope*cur = sub_; + while (cur) { + cur->residual_defparams(des); + cur = cur->sib_; + } +} + const char* Design::get_flag(const string&key) const { map::const_iterator tmp = flags_.find(key); diff --git a/netlist.h b/netlist.h index 5057af231..d6e01bab2 100644 --- a/netlist.h +++ b/netlist.h @@ -29,6 +29,7 @@ # include # include # include +# include # include # include "ivl_target.h" # include "pform_types.h" @@ -723,6 +724,9 @@ class NetScope : public Attrib { void evaluate_parameters(class Design*); + // Look for defparams that never matched, and print warnings. + void residual_defparams(class Design*); + /* This method generates a non-hierarchical name that is guaranteed to be unique within this scope. */ perm_string local_symbol(); @@ -3672,10 +3676,14 @@ class Design { listelaboration_work_list; void run_elaboration_work(void); + set defparams_later; + // PARAMETERS void run_defparams(); void evaluate_parameters(); + // Look for defparams that never matched, and print warnings. + void residual_defparams(); /* This method locates a signal, starting at a given scope. The name parameter may be partially hierarchical, so diff --git a/t-dll.cc b/t-dll.cc index 0d9380ac4..06cd40220 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -30,6 +30,7 @@ # include #endif # include +# include "ivl_assert.h" #if defined(__WIN32__) @@ -538,6 +539,13 @@ void dll_target::make_scope_param_expr(ivl_parameter_t cur_par, NetExpr*etmp) } + if (expr_ == 0) { + cerr << etmp->get_fileline() << ": internal error: " + << "Parameter expression not reduced to constant? " + << *etmp << endl; + } + ivl_assert(*etmp, expr_); + cur_par->value = expr_; expr_ = 0; }