run scope elaboration as queued work items.
Putting scope elaboration into work queue items allows for handling more complex processing order. The elaboration_work_list queue drives the processing of elaborate_scope and parameter evaluation.
This commit is contained in:
parent
360be597a8
commit
c810406195
87
elaborate.cc
87
elaborate.cc
|
|
@ -3775,6 +3775,50 @@ struct root_elem {
|
|||
NetScope *scope;
|
||||
};
|
||||
|
||||
class elaborate_root_scope_t : public elaborator_work_item_t {
|
||||
public:
|
||||
elaborate_root_scope_t(Design*des, NetScope*scope, Module*rmod)
|
||||
: elaborator_work_item_t(des), scope_(scope), rmod_(rmod)
|
||||
{ }
|
||||
|
||||
~elaborate_root_scope_t() { }
|
||||
|
||||
virtual void elaborate_runrun()
|
||||
{
|
||||
Module::replace_t stub;
|
||||
if (! rmod_->elaborate_scope(des, scope_, stub))
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
private:
|
||||
NetScope*scope_;
|
||||
Module*rmod_;
|
||||
};
|
||||
|
||||
class top_defparams : public elaborator_work_item_t {
|
||||
public:
|
||||
top_defparams(Design*des)
|
||||
: elaborator_work_item_t(des)
|
||||
{ }
|
||||
|
||||
~top_defparams() { }
|
||||
|
||||
virtual void elaborate_runrun()
|
||||
{
|
||||
// This method recurses through the scopes, looking for
|
||||
// defparam assignments to apply to the parameters in the
|
||||
// various scopes. This needs to be done after all the scopes
|
||||
// and basic parameters are taken care of because the defparam
|
||||
// can assign to a parameter declared *after* it.
|
||||
des->run_defparams();
|
||||
|
||||
// At this point, all parameter overrides are done. Scan the
|
||||
// scopes and evaluate the parameters all the way down to
|
||||
// constants.
|
||||
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
|
||||
|
|
@ -3829,21 +3873,27 @@ Design* elaborate(list<perm_string>roots)
|
|||
r->mod = rmod;
|
||||
r->scope = scope;
|
||||
root_elems[i++] = r;
|
||||
|
||||
// Arrange for these scopes to be elaborated as root
|
||||
// scopes. Create an "elaborate_root_scope" object to
|
||||
// contain the work item, and append it to the scope
|
||||
// elaborations work list.
|
||||
elaborator_work_item_t*es = new elaborate_root_scope_t(des, scope, rmod);
|
||||
des->elaboration_work_list.push_back(es);
|
||||
}
|
||||
|
||||
// Elaborate the instances of the root modules into the root
|
||||
// scopes that we created. The elaborate_scope for each will
|
||||
// recurse down the design, furtner elaborating sub-scope all
|
||||
// the way down to the leaves.
|
||||
for (i = 0; i < root_elems.count(); i += 1) {
|
||||
Module*rmod = root_elems[i]->mod;
|
||||
NetScope*scope = root_elems[i]->scope;
|
||||
// After the work items for the root scope elaboration, push a
|
||||
// work item to process the defparams.
|
||||
des->elaboration_work_list.push_back(new top_defparams(des));
|
||||
|
||||
Module::replace_t stub;
|
||||
if (! rmod->elaborate_scope(des, scope, stub)) {
|
||||
delete des;
|
||||
return 0;
|
||||
}
|
||||
// Run the work list of scope elaborations until the list is
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Errors already? Probably missing root modules. Just give up
|
||||
|
|
@ -3851,19 +3901,6 @@ Design* elaborate(list<perm_string>roots)
|
|||
if (des->errors > 0)
|
||||
return des;
|
||||
|
||||
// This method recurses through the scopes, looking for
|
||||
// defparam assignments to apply to the parameters in the
|
||||
// various scopes. This needs to be done after all the scopes
|
||||
// and basic parameters are taken care of because the defparam
|
||||
// can assign to a parameter declared *after* it.
|
||||
des->run_defparams();
|
||||
|
||||
|
||||
// At this point, all parameter overrides are done. Scan the
|
||||
// scopes and evaluate the parameters all the way down to
|
||||
// constants.
|
||||
des->evaluate_parameters();
|
||||
|
||||
// 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
|
||||
|
|
|
|||
21
netlist.h
21
netlist.h
|
|
@ -3598,6 +3598,18 @@ class NetESignal : public NetExpr {
|
|||
NetExpr*word_;
|
||||
};
|
||||
|
||||
/*
|
||||
* The Design object keeps a list of work items for processing
|
||||
* elaboration. This is the type of those work items.
|
||||
*/
|
||||
struct elaborator_work_item_t {
|
||||
explicit elaborator_work_item_t(Design*d)
|
||||
: des(d) { }
|
||||
virtual ~elaborator_work_item_t() { }
|
||||
virtual void elaborate_runrun() =0;
|
||||
protected:
|
||||
Design*des;
|
||||
};
|
||||
|
||||
/*
|
||||
* This class contains an entire design. It includes processes and a
|
||||
|
|
@ -3647,6 +3659,15 @@ class Design {
|
|||
NetScope* find_scope(NetScope*, const std::list<hname_t>&path,
|
||||
NetScope::TYPE type = NetScope::MODULE) const;
|
||||
|
||||
/* These members help manage elaboration of scopes. When we
|
||||
get to a point in scope elaboration where we want to put
|
||||
off a scope elaboration, an object of scope_elaboration_t
|
||||
is pushed onto the scope_elaborations list. The scope
|
||||
elaborator will go through this list elaborating scopes
|
||||
until the list is empty. */
|
||||
list<elaborator_work_item_t*>elaboration_work_list;
|
||||
void run_elaboration_work(void);
|
||||
|
||||
// PARAMETERS
|
||||
|
||||
void run_defparams();
|
||||
|
|
|
|||
Loading…
Reference in New Issue