Minor cleanup and comments.

The initial elaboration needs better comments/documentation.
This commit is contained in:
Stephen Williams 2008-06-21 18:36:46 -07:00
parent 27cdd27889
commit 360be597a8
4 changed files with 116 additions and 35 deletions

View File

@ -3775,6 +3775,12 @@ struct root_elem {
NetScope *scope;
};
/*
* This function is the root of all elaboration. The input is the list
* of root module names. The function locates the Module definitions
* for each root, does the whole elaboration sequence, and fills in
* the resulting Design.
*/
Design* elaborate(list<perm_string>roots)
{
svector<root_elem*> root_elems(roots.size());
@ -3785,7 +3791,7 @@ Design* elaborate(list<perm_string>roots)
// module and elaborate what I find.
Design*des = new Design;
// Scan the root modules, and elaborate their scopes.
// Scan the root modules by name, and elaborate their scopes.
for (list<perm_string>::const_iterator root = roots.begin()
; root != roots.end()
; root++) {
@ -3804,29 +3810,42 @@ Design* elaborate(list<perm_string>roots)
// Get the module definition for this root instance.
Module *rmod = (*mod).second;
// Make the root scope.
// Make the root scope. This makes a NetScoep object and
// pushes it into the list of root scopes in the Design.
NetScope*scope = des->make_root_scope(*root);
// Collect some basic properties of this scope from the
// Module definition.
scope->set_line(rmod);
scope->time_unit(rmod->time_unit);
scope->time_precision(rmod->time_precision);
scope->default_nettype(rmod->default_nettype);
des->set_precision(rmod->time_precision);
Module::replace_t stub;
// Recursively elaborate from this root scope down. This
// does a lot of the grunt work of creating sub-scopes, etc.
if (! rmod->elaborate_scope(des, scope, stub)) {
delete des;
return 0;
}
// Save this scope, along with its defintion, in the
// "root_elems" list for later passes.
struct root_elem *r = new struct root_elem;
r->mod = rmod;
r->scope = scope;
root_elems[i++] = r;
}
// 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;
Module::replace_t stub;
if (! rmod->elaborate_scope(des, scope, stub)) {
delete des;
return 0;
}
}
// Errors already? Probably missing root modules. Just give up
// now and return nothing.
if (des->errors > 0)

View File

@ -244,6 +244,57 @@ bool eval_as_double(double&value, NetExpr*expr)
return false;
}
/*
* At the parser level, a name component it a name with a collection
* of expressions. For example foo[N] is the name "foo" and the index
* expression "N". This function takes as input the name component and
* returns the path component name. It will evaulate the index
* expression if it is present.
*/
hname_t eval_path_component(Design*des, NetScope*scope,
const name_component_t&comp)
{
// No index exression, so the path component is an undecorated
// name, for example "foo".
if (comp.index.empty())
return hname_t(comp.name);
// The parser will assure that path components will have only
// one index. For example, foo[N] is one index, foo[n][m] is two.
assert(comp.index.size() == 1);
const index_component_t&index = comp.index.front();
// The parser will assure that path components will have only
// bit select index expressions. For example, "foo[n]" is OK,
// but "foo[n:m]" is not.
assert(index.sel == index_component_t::SEL_BIT);
// Evaluate the bit select to get a number.
NetExpr*tmp = elab_and_eval(des, scope, index.msb, -1);
ivl_assert(*index.msb, tmp);
// Now we should have a constant value for the bit select
// expression, and we can use it to make the final hname_t
// value, for example "foo[5]".
if (NetEConst*ctmp = dynamic_cast<NetEConst*>(tmp)) {
hname_t res(comp.name, ctmp->value().as_long());
delete ctmp;
return res;
}
// Darn, the expression doesn't evaluate to a constant. That's
// and error to be reported. And make up a fake index value to
// return to the caller.
cerr << index.msb->get_fileline() << ": error: "
<< "Scope index expression is not constant: "
<< *index.msb << endl;
des->errors += 1;
delete tmp;
return hname_t (comp.name, 0);
}
std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
const pform_name_t&path)
{
@ -253,30 +304,7 @@ std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
for (pform_path_it cur = path.begin() ; cur != path.end(); cur++) {
const name_component_t&comp = *cur;
if (comp.index.empty()) {
res.push_back(hname_t(comp.name));
continue;
}
assert(comp.index.size() == 1);
const index_component_t&index = comp.index.front();
assert(index.sel == index_component_t::SEL_BIT);
NetExpr*tmp = elab_and_eval(des, scope, index.msb, -1);
ivl_assert(*index.msb, tmp);
if (NetEConst*ctmp = dynamic_cast<NetEConst*>(tmp)) {
res.push_back(hname_t(comp.name, ctmp->value().as_long()));
delete ctmp;
continue;
} else {
cerr << index.msb->get_fileline() << ": error: "
<< "Scope index expression is not constant: "
<< *index.msb << endl;
des->errors += 1;
}
return res;
res.push_back( eval_path_component(des,scope,comp) );
}
return res;

View File

@ -152,6 +152,16 @@ void eval_expr(NetExpr*&expr, int prune_width =-1);
bool eval_as_long(long&value, NetExpr*expr);
bool eval_as_double(double&value, NetExpr*expr);
/*
* Evaluate the component of a scope path to get an hname_t value. Do
* the evaluation in the context of the given scope.
*/
extern hname_t eval_path_component(Design*des, NetScope*scope,
const name_component_t&comp);
/*
* Evaluate an entire scope path in the context of the given scope.
*/
extern std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
const pform_name_t&path);

View File

@ -53,10 +53,34 @@ struct name_component_t {
extern bool operator < (const name_component_t&lef, const name_component_t&rig);
/*
* The pform_name_t is the general form for a hierarchical identifier.
* The pform_name_t is the general form for a hierarchical
* identifier. It is an ordered list of name components. Each name
* component is an identifier and an optional list of bit/part
* selects. The simplest name component is a simple identifier:
*
* foo
*
* The bit/part selects come from the source and are made part of the
* name component. A bit select is a single number that may be a bit
* select of a vector or a word select of an array:
*
* foo[5] -- a bit select/word index
* foo[6:4] -- a part select
*
* The index components of a name component are collected into an
* ordered list, so there may be many, for example:
*
* foo[5][6:4] -- a part select of an array word
*
* The pform_name_t, then, is an ordered list of these name
* components. The list of names comes from a hierarchical name in the
* source, like this:
*
* foo[5].bar[6:4] -- a part select of a vector in sub-scope foo[5].
*/
typedef std::list<name_component_t> pform_name_t;
inline perm_string peek_head_name(const pform_name_t&that)
{
return that.front().name;