Handle multiple passes of scope and defparam elaboration.
When generate schems and instance arrays are nested, it takes multiple iterations of elaborate scope, defparams and evaluate parameters before everything is worked out. Rework the work item processing so that the loop elaborates scopes and runs defparams in phases. The phases are needed so that we can tell when the remaining defparams are orphaned.
This commit is contained in:
parent
d9b02657a7
commit
e02d186946
55
elaborate.cc
55
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()
|
||||
{
|
||||
list<NetScope*>tmp_list;
|
||||
for (set<NetScope*>::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(list<perm_string>roots)
|
|||
// 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<elaborator_work_item_t*> 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)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
# include "config.h"
|
||||
|
||||
# include <iostream>
|
||||
# include <set>
|
||||
# include <cstdlib>
|
||||
|
||||
/*
|
||||
|
|
@ -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<NetScope*> target_scopes;
|
||||
list<pair<list<hname_t>,NetExpr*> > defparams_even_later;
|
||||
|
||||
while (! defparams_later.empty()) {
|
||||
pair<list<hname_t>,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<NetScope*>::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<NetScope*>::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<list<hname_t>,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<string,const char*>::const_iterator tmp = flags_.find(key);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
# include <map>
|
||||
# include <list>
|
||||
# include <vector>
|
||||
# include <set>
|
||||
# include <utility>
|
||||
# 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 {
|
|||
list<elaborator_work_item_t*>elaboration_work_list;
|
||||
void run_elaboration_work(void);
|
||||
|
||||
set<NetScope*> 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
|
||||
|
|
|
|||
8
t-dll.cc
8
t-dll.cc
|
|
@ -30,6 +30,7 @@
|
|||
# include <malloc.h>
|
||||
#endif
|
||||
# include <stdlib.h>
|
||||
# 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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue