Fix a variety of bugs in vpi_handle_by_name.

This function was apparently not well tested, because any use of
acc_handle_object() triggered a use of vpi_handle_by_name that was
buggy.

The implementation was awkwardly written, to parts of it were redone.
This commit is contained in:
Stephen Williams 2014-04-13 16:25:30 -07:00
parent 3a77537ed8
commit fdcb073c14
1 changed files with 80 additions and 25 deletions

View File

@ -23,6 +23,7 @@
#ifdef CHECK_WITH_VALGRIND
# include "vvp_cleanup.h"
#endif
# include <vector>
# include <cstdio>
# include <cstdarg>
# include <cstring>
@ -31,6 +32,7 @@
# include <cmath>
# include <iostream>
using namespace std;
vpi_mode_t vpi_mode_flag = VPI_MODE_NONE;
FILE*vpi_trace = 0;
@ -1262,22 +1264,30 @@ static vpiHandle find_name(const char *name, vpiHandle handle)
static vpiHandle find_scope(const char *name, vpiHandle handle, int depth)
{
vpiHandle iter, hand, rtn = 0;
iter = !handle ? vpi_iterate(vpiModule, NULL) :
vpi_iterate(vpiInternalScope, handle);
vpiHandle iter = handle==0
? vpi_iterate(vpiModule, NULL)
: vpi_iterate(vpiInternalScope, handle);
vector<char> name_buf (strlen(name)+1);
strcpy(&name_buf[0], name);
char*nm_first = &name_buf[0];
char*nm_rest = strchr(nm_first, '.');
if (nm_rest) {
*nm_rest++ = 0;
}
vpiHandle rtn = 0;
vpiHandle hand;
while (iter && (hand = vpi_scan(iter))) {
char *nm = vpi_get_str(vpiName, hand);
int len = strlen(nm);
const char *cp = name + len; /* hier separator */
if (!handle && !strcmp(name, nm)) {
/* root module */
rtn = hand;
} else if (!strncmp(name, nm, len) && *(cp) == '.')
/* recurse deeper */
rtn = find_scope(cp+1, hand, depth + 1);
if (strcmp(nm_first,nm)==0) {
if (nm_rest)
rtn=find_scope(nm_rest, hand, depth+1);
else
rtn = hand;
}
/* found it yet ? */
if (rtn) {
@ -1286,9 +1296,6 @@ static vpiHandle find_scope(const char *name, vpiHandle handle, int depth)
}
}
/* matched up to here */
if (!rtn) rtn = handle;
return rtn;
}
@ -1301,6 +1308,20 @@ vpiHandle vpi_handle_by_name(const char *name, vpiHandle scope)
name, scope);
}
// Chop the name into path and base. For example, if the name
// is "a.b.c", then nm_path becomes "a.b" and nm_base becomes
// "c". If the name is "c" then nm_path is nil and nm_base is "c".
vector<char> name_buf (strlen(name)+1);
strcpy(&name_buf[0], name);
char*nm_path = &name_buf[0];
char*nm_base = strrchr(nm_path, '.');
if (nm_base) {
*nm_base++ = 0;
} else {
nm_base = nm_path;
nm_path = 0;
}
/* If scope provided, look in corresponding module; otherwise
* traverse the hierarchy specified in name to find the leaf module
* and try finding it there.
@ -1315,26 +1336,60 @@ vpiHandle vpi_handle_by_name(const char *name, vpiHandle scope)
hand = scope;
break;
default:
if (vpi_trace) {
fprintf(vpi_trace, "vpi_handle_by_name: "
"Scope is not a vpiScope or vpiModule\n");
}
// Use vpi_chk_error() here when it is implemented.
return 0;
}
} else if (nm_path) {
// The name has a path, and no other scope handle was
// passed in. That suggests we are looking for "a.b.c"
// in the root scope. So convert "a.b" to a scope and
// start there to look for "c".
hand = find_scope(nm_path, NULL, 0);
nm_path = 0;
} else {
hand = find_scope(name, NULL, 0);
// Special case: scope==<nil>, meaning we are looking in
// the root, and there is no path to the name, i.e. the
// string is "c" instead of "top.c". Try to find "c" as
// a scope and return that.
hand = find_scope(nm_base, NULL, 0);
}
if (hand) {
/* remove hierarchical portion of name */
const char *nm = vpi_get_str(vpiFullName, hand);
int len = strlen(nm);
const char *cp = name + len;
if (!strncmp(name, nm, len) && *cp == '.') name = cp + 1;
if (hand == 0) {
if (vpi_trace) {
fprintf(vpi_trace, "vpi_handle_by_name: "
"Scope does not exist. Giving up.\n");
}
/* Ok, time to burn some cycles */
vpiHandle out = find_name(name, hand);
return out;
return 0;
}
return 0;
// If there is a path part, then use it to find the
// scope. For example, if the full name is a.b.c, then
// the nm_path string is a.b and we search for that
// scope. If we find it, then set hand to that scope.
if (nm_path) {
vpiHandle tmp = find_scope(nm_path, hand, 0);
while (tmp == 0 && hand != 0) {
hand = vpi_handle(vpiScope, hand);
tmp = find_scope(nm_path, hand, 0);
}
hand = tmp;
}
// Now we have the correct scope, look for the item.
vpiHandle out = find_name(nm_base, hand);
if (vpi_trace) {
fprintf(vpi_trace, "vpi_handle_by_name: DONE\n");
}
return out;
}