Rework symbol search to work incrementally.
This is necessary to handle paths that turn out to end with member names instead of symbol names.
This commit is contained in:
parent
0bdabab4fb
commit
174177d437
2
PExpr.cc
2
PExpr.cc
|
|
@ -363,7 +363,7 @@ bool PEIdent::has_aa_term(Design*des, NetScope*scope) const
|
|||
|
||||
const NetExpr*ex1, *ex2;
|
||||
|
||||
scope = symbol_search(0, des, scope, path_, net, par, eve, ex1, ex2);
|
||||
scope = symbol_search(this, des, scope, path_, net, par, eve, ex1, ex2);
|
||||
|
||||
if (scope)
|
||||
return scope->is_auto();
|
||||
|
|
|
|||
|
|
@ -2303,7 +2303,7 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
|||
|
||||
const NetExpr*ex1, *ex2;
|
||||
|
||||
NetScope*found_in = symbol_search(0, des, scope, path_, net, par, eve,
|
||||
NetScope*found_in = symbol_search(this, des, scope, path_, net, par, eve,
|
||||
ex1, ex2);
|
||||
|
||||
// If there is a part/bit select expression, then process it
|
||||
|
|
|
|||
|
|
@ -853,9 +853,9 @@ bool eval_as_double(double&value, NetExpr*expr)
|
|||
* returns the path component name. It will evaluate the index
|
||||
* expression if it is present.
|
||||
*/
|
||||
static hname_t eval_path_component(Design*des, NetScope*scope,
|
||||
const name_component_t&comp,
|
||||
bool&error_flag)
|
||||
hname_t eval_path_component(Design*des, NetScope*scope,
|
||||
const name_component_t&comp,
|
||||
bool&error_flag)
|
||||
{
|
||||
// No index expression, so the path component is an undecorated
|
||||
// name, for example "foo".
|
||||
|
|
|
|||
|
|
@ -261,6 +261,9 @@ bool eval_as_double(double&value, NetExpr*expr);
|
|||
*/
|
||||
extern std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
|
||||
const pform_name_t&path);
|
||||
extern hname_t eval_path_component(Design*des, NetScope*scope,
|
||||
const name_component_t&comp,
|
||||
bool&error_flag);
|
||||
|
||||
/*
|
||||
* Return true if the data type is a type that is normally available
|
||||
|
|
|
|||
203
symbol_search.cc
203
symbol_search.cc
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2010 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -19,12 +20,149 @@
|
|||
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include <cassert>
|
||||
# include "ivl_assert.h"
|
||||
|
||||
|
||||
/*
|
||||
* Search for the hierarchical name.
|
||||
*/
|
||||
struct symbol_search_results {
|
||||
inline symbol_search_results() {
|
||||
scope = 0;
|
||||
net = 0;
|
||||
par_val = 0;
|
||||
par_msb = 0;
|
||||
par_lsb = 0;
|
||||
eve = 0;
|
||||
}
|
||||
|
||||
inline bool is_scope() const {
|
||||
if (net) return false;
|
||||
if (eve) return false;
|
||||
if (par_val) return false;
|
||||
if (scope) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Scope where symbol was located. This is set in all cases,
|
||||
// assuming the search succeeded.
|
||||
NetScope*scope;
|
||||
// If this was a net, the signal itself.
|
||||
NetNet*net;
|
||||
// If this was a parameter, the value expression and the
|
||||
// optional value dimensions.
|
||||
const NetExpr*par_val;
|
||||
const NetExpr*par_msb;
|
||||
const NetExpr*par_lsb;
|
||||
// If this is a named event, ...
|
||||
NetEvent*eve;
|
||||
};
|
||||
|
||||
bool symbol_search(const LineInfo*li, Design*des, NetScope*scope,
|
||||
pform_name_t path, struct symbol_search_results*res,
|
||||
NetScope*start_scope = 0)
|
||||
{
|
||||
assert(scope);
|
||||
bool prefix_scope = false;
|
||||
bool recurse_flag = false;
|
||||
name_component_t path_tail = path.back();
|
||||
path.pop_back();
|
||||
|
||||
// If this is a recursive call, then we need to know that so
|
||||
// that we can enable the search for scopes. Set the
|
||||
// recurse_flag to true if this is a recurse.
|
||||
if (start_scope==0)
|
||||
start_scope = scope;
|
||||
else
|
||||
recurse_flag = true;
|
||||
|
||||
// If there are components ahead of the tail, symbol_search
|
||||
// recursively. Ideally, the result is a scope that we search
|
||||
// for the tail key, but there are other special cases as well.
|
||||
if (path.size() > 0) {
|
||||
symbol_search_results recurse;
|
||||
bool flag = symbol_search(li, des, scope, path, &recurse, start_scope);
|
||||
if (! flag)
|
||||
return false;
|
||||
|
||||
// The prefix is found to be a scope, so switch to that
|
||||
// scoke, set the hier_path to turn of upwards searches,
|
||||
// and continue our search for the tail.
|
||||
if (recurse.is_scope()) {
|
||||
scope = recurse.scope;
|
||||
prefix_scope = true;
|
||||
|
||||
if (scope->is_auto() && li) {
|
||||
cerr << li->get_fileline() << ": error: Hierarchical "
|
||||
"reference to automatically allocated item "
|
||||
"`" << path_tail.name << "' in path `" << path << "'" << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (scope) {
|
||||
if (NetNet*net = scope->find_signal(path_tail.name)) {
|
||||
res->scope = scope;
|
||||
res->net = net;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (NetEvent*eve = scope->find_event(path_tail.name)) {
|
||||
res->scope = scope;
|
||||
res->eve = eve;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (const NetExpr*par = scope->get_parameter(des, path_tail.name, res->par_msb, res->par_lsb)) {
|
||||
res->scope = scope;
|
||||
res->par_val = par;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (recurse_flag) {
|
||||
bool flag = false;
|
||||
hname_t path_item = eval_path_component(des, start_scope, path_tail, flag);
|
||||
list<hname_t>path_list;
|
||||
path_list.push_back(path_item);
|
||||
if (flag) {
|
||||
cerr << li->get_fileline() << ": XXXXX: Errors evaluating scope index" << endl;
|
||||
} else if (NetScope*chld = des->find_scope(scope, path_list)) {
|
||||
res->scope = chld;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Don't scan up past a module boundary.
|
||||
if (scope->type()==NetScope::MODULE && !scope->nested_module())
|
||||
break;
|
||||
// Don't scan up if we are searching within a prefixed scope.
|
||||
if (prefix_scope)
|
||||
break;
|
||||
|
||||
scope = scope->parent();
|
||||
}
|
||||
|
||||
// Last chance: this is a single name, so it might be the name
|
||||
// of a root scope. Ask the design if this is a root
|
||||
// scope. This is only possible if there is no prefix.
|
||||
if (prefix_scope==false) {
|
||||
hname_t path_item (path_tail.name);
|
||||
list<hname_t>path_list;
|
||||
path_list.push_back(path_item);
|
||||
scope = des->find_scope(path_list);
|
||||
if (scope) {
|
||||
res->scope = scope;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compatibility version. Remove me!
|
||||
*/
|
||||
NetScope*symbol_search(const LineInfo*li, Design*des, NetScope*scope,
|
||||
pform_name_t path,
|
||||
NetNet*&net,
|
||||
|
|
@ -32,58 +170,19 @@ NetScope*symbol_search(const LineInfo*li, Design*des, NetScope*scope,
|
|||
NetEvent*&eve,
|
||||
const NetExpr*&ex1, const NetExpr*&ex2)
|
||||
{
|
||||
assert(scope);
|
||||
bool hier_path = false;
|
||||
|
||||
/* Get the tail name of the object we are looking for. */
|
||||
perm_string key = peek_tail_name(path);
|
||||
path.pop_back();
|
||||
|
||||
/* Initialize output argument to cleared. */
|
||||
net = 0;
|
||||
par = 0;
|
||||
eve = 0;
|
||||
|
||||
/* If the path has a scope part, then search for the specified
|
||||
scope that we are supposed to search. */
|
||||
if (! path.empty()) {
|
||||
list<hname_t> path_list = eval_scope_path(des, scope, path);
|
||||
assert(path_list.size() <= path.size());
|
||||
|
||||
// If eval_scope_path returns a short list, then some
|
||||
// part of the scope was not found. Abort.
|
||||
if (path_list.size() < path.size())
|
||||
return 0;
|
||||
|
||||
scope = des->find_scope(scope, path_list);
|
||||
|
||||
if (scope && scope->is_auto() && li) {
|
||||
cerr << li->get_fileline() << ": error: Hierarchical "
|
||||
"reference to automatically allocated item "
|
||||
"`" << key << "' in path `" << path << "'" << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
hier_path = true;
|
||||
symbol_search_results recurse;
|
||||
bool flag = symbol_search(li, des, scope, path, &recurse);
|
||||
if (! flag) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (scope) {
|
||||
if ( (net = scope->find_signal(key)) )
|
||||
return scope;
|
||||
if (recurse.is_scope())
|
||||
return recurse.scope;
|
||||
|
||||
if ( (eve = scope->find_event(key)) )
|
||||
return scope;
|
||||
|
||||
if ( (par = scope->get_parameter(des, key, ex1, ex2)) )
|
||||
return scope;
|
||||
|
||||
/* We can't look up if we are at the enclosing module scope
|
||||
* or if a hierarchical path was given. */
|
||||
if ((scope->type()==NetScope::MODULE && !scope->nested_module()) || hier_path)
|
||||
scope = 0;
|
||||
else
|
||||
scope = scope->parent();
|
||||
}
|
||||
|
||||
return 0;
|
||||
net = recurse.net;
|
||||
par = recurse.par_val;
|
||||
ex1 = recurse.par_msb;
|
||||
ex2 = recurse.par_lsb;
|
||||
eve = recurse.eve;
|
||||
return recurse.scope;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue