Minor cleanup and comments.
The initial elaboration needs better comments/documentation.
This commit is contained in:
parent
27cdd27889
commit
360be597a8
39
elaborate.cc
39
elaborate.cc
|
|
@ -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)
|
||||
|
|
|
|||
76
netmisc.cc
76
netmisc.cc
|
|
@ -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;
|
||||
|
|
|
|||
10
netmisc.h
10
netmisc.h
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue