Overhaul of the hash table method. Original method used global

variables to iterate over hash table contents.  This led to the
inability to nest hash table iterators.  Fixed by defining a
wrapper structure that holds the actual hash table plus the size
and iterator indexes.  Not only does this solve the nesting
problem, but it also avoids the need to pass the hash table size
on every call, and that reduces the number of ways a hash table
subroutine can go wrong (e.g., cannot access the table out of
bounds simply by passing a size that is larger than was used to
initialize the table).
This commit is contained in:
Tim Edwards 2016-06-23 10:13:18 -04:00
parent cbb2f78ee9
commit 5f634b2a91
17 changed files with 599 additions and 302 deletions

View File

@ -39,7 +39,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#define ACTELHASHSIZE 99
static long actelhashbase = 0xA00;
static struct hashlist *actelnametab[ACTELHASHSIZE];
static struct hashdict actelnamedict;
static FILE *actelfile;
char *ActelName(char *Name);
@ -53,16 +53,16 @@ void PrintActelNames(char *filename)
{
if (filename == NULL) actelfile = stdout;
else actelfile = fopen(filename,"w");
RecurseHashTable(actelnametab, ACTELHASHSIZE, PrintActelName);
RecurseHashTable(&actelnamedict, PrintActelName);
if (actelfile != stdout) fclose(actelfile);
}
long ActelNameHash(char *name)
/* hashes name into nametab if necessary, then returns address of entry */
/* hashes name into namedict if necessary, then returns address of entry */
{
struct hashlist *p;
p = HashInstall(name, actelnametab, ACTELHASHSIZE);
p = HashInstall(name, &actelnamedict);
if (p == NULL) return(0);
if (p->ptr != NULL) return ((long)(p->ptr));
actelhashbase++;
@ -403,7 +403,7 @@ void Actel(char *name, char *filename)
return;
}
ClearDumpedList();
InitializeHashTable(actelnametab, ACTELHASHSIZE);
InitializeHashTable(&actelnamedict, ACTELHASHSIZE);
if (LookupCell(name) != NULL)
actelCell(name);
CloseFile(FileName);

View File

@ -544,10 +544,10 @@ void simCell(char *name, int filenum)
if (ob2 && ob2->type == PROPERTY) {
struct property *kl;
struct valuelist *vl;
kl = (struct property *)HashLookup("length", tp2->proptab, OBJHASHSIZE);
kl = (struct property *)HashLookup("length", &(tp2->propdict));
vl = (struct valuelist *)ob2->instance.name;
l = 1.0e6 * vl[kl->idx].value.dval; /* m -> um */
kl = (struct property *)HashLookup("width", tp2->proptab, OBJHASHSIZE);
kl = (struct property *)HashLookup("width", &(tp2->propdict));
w = 1.0e6 * vl[kl->idx].value.dval; /* m -> um */
}
FlushString(" %g %g\n", l, w);
@ -579,7 +579,7 @@ void simCell(char *name, int filenum)
if (ob2 && ob2->type == PROPERTY) {
struct property *kl;
struct valuelist *vl;
kl = (struct property *)HashLookup("value", tp2->proptab, OBJHASHSIZE);
kl = (struct property *)HashLookup("value", &(tp2->propdict));
vl = (struct valuelist *)ob2->instance.name;
if (tp2->class == CLASS_CAP)
v = 1.0e15 * vl[kl->idx].value.dval; /* F -> fF */

View File

@ -177,7 +177,7 @@ void flattenCell(char *name, int file)
}
}
}
HashPtrInstall(tmp->name, tmp, ThisCell->objtab, OBJHASHSIZE);
HashPtrInstall(tmp->name, tmp, &(ThisCell->objdict));
continue;
}
@ -198,9 +198,9 @@ void flattenCell(char *name, int file)
#endif
FreeString(tmp->instance.name);
tmp->instance.name = strsave(tmpstr);
HashPtrInstall(tmp->name, tmp, ThisCell->objtab, OBJHASHSIZE);
HashPtrInstall(tmp->name, tmp, &(ThisCell->objdict));
if (tmp->type == FIRSTPIN)
HashPtrInstall(tmp->instance.name, tmp, ThisCell->insttab, OBJHASHSIZE);
HashPtrInstall(tmp->instance.name, tmp, &(ThisCell->instdict));
}
/* splice instance out of parent */
@ -440,7 +440,7 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
}
// Don't hash this if the parent had a port of this name
if (!ob2 || ob2->type != PORT)
HashPtrInstall(tmp->name, tmp, ThisCell->objtab, OBJHASHSIZE);
HashPtrInstall(tmp->name, tmp, &(ThisCell->objdict));
continue;
}
@ -461,9 +461,9 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
#endif
FreeString(tmp->instance.name);
tmp->instance.name = strsave(tmpstr);
HashPtrInstall(tmp->name, tmp, ThisCell->objtab, OBJHASHSIZE);
HashPtrInstall(tmp->name, tmp, &(ThisCell->objdict));
if (tmp->type == FIRSTPIN)
HashPtrInstall(tmp->instance.name, tmp, ThisCell->insttab, OBJHASHSIZE);
HashPtrInstall(tmp->instance.name, tmp, &(ThisCell->instdict));
}
/* do property inheritance */
@ -704,7 +704,7 @@ void convertGlobalsOf(char *name, int fnum, char *instance)
newnode->instance.name = NULL;
newnode->model.class = NULL;
newpin->node = maxnode;
HashPtrInstall(newnode->name, newnode, ThisCell->objtab, OBJHASHSIZE);
HashPtrInstall(newnode->name, newnode, &(ThisCell->objdict));
}
// Remove any references to the net as a GLOBAL type in the instance
@ -727,7 +727,7 @@ void convertGlobalsOf(char *name, int fnum, char *instance)
// Now there should be only one object of this name in the instance,
// which is the pin, and we will set the hash table to point to it.
HashPtrInstall(newpin->name, newpin, ThisCell->objtab, OBJHASHSIZE);
HashPtrInstall(newpin->name, newpin, &(ThisCell->objdict));
}
CacheNodeNames(ThisCell);
@ -840,7 +840,7 @@ void ConvertGlobals(char *name, int filenum)
strsave(ObjList->instance.name) : NULL;
NewObj->name = (ObjList->name) ? strsave(ObjList->name) : NULL;
HashPtrInstall(NewObj->name, NewObj, ThisCell->objtab, OBJHASHSIZE);
HashPtrInstall(NewObj->name, NewObj, &(ThisCell->objdict));
/* Find all parent cells of this cell. Find the global node */
/* if it exists or create it if it doesn't. Add the node to */
@ -959,11 +959,11 @@ struct nlist *uniquepins(struct hashlist *p, void *clientdata)
modified = 1;
// Check if the node we're about to remove is in the
// objtab hash table; if so, replace it with the one
// objdict hash table; if so, replace it with the one
// that we are going to keep.
if (LookupObject(ob->name, ptr) == ob) {
HashPtrInstall(ob->name, saveob, ptr->objtab, OBJHASHSIZE);
HashPtrInstall(ob->name, saveob, &(ptr->objdict));
}
}
tob = tob->next;
@ -998,7 +998,7 @@ struct nlist *uniquepins(struct hashlist *p, void *clientdata)
// Renumber the pins in order. Since when removing duplicates, the
// first entry is always kept, the first pin is never changed, so
// the insttab record is never corrupted.
// the instdict record is never corrupted.
i = FIRSTPIN;
firstpin->type = i++;
@ -1093,8 +1093,7 @@ int UniquePins(char *name, int filenum)
// The hash table is pointing at the cell we are
// about to delete. Hash the one we're keeping instead.
HashPtrInstall(ob->name, firstport[ob->node],
ThisCell->objtab, OBJHASHSIZE);
HashPtrInstall(ob->name, firstport[ob->node], &(ThisCell->objdict));
}
if (lob == NULL) {
@ -1131,7 +1130,7 @@ int UniquePins(char *name, int filenum)
/* Callback function for CleanupPins */
/* Note that if the first pin of the instance is a */
/* disconnected node, then removing it invalidates the */
/* insttab hash. */
/* instdict hash. */
/*------------------------------------------------------*/
struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
@ -1181,9 +1180,9 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
}
// Check if the node we're about to remove is in the
// objtab hash table
// objdict hash table
if (LookupObject(ob->name, ptr) == ob) {
HashDelete(ob->name, ptr->objtab, OBJHASHSIZE);
HashDelete(ob->name, &(ptr->objdict));
}
FREE(ob->name);
@ -1199,10 +1198,9 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
obt = obt->next;
}
/* Rehash the insttab, in case the first pin got removed */
/* Rehash the instdict, in case the first pin got removed */
if (firstpin && (firstpin->type == FIRSTPIN))
HashPtrInstall(firstpin->instance.name, firstpin, ptr->insttab,
OBJHASHSIZE);
HashPtrInstall(firstpin->instance.name, firstpin, &(ptr->instdict));
}
}
return NULL; /* Keep the search going */
@ -1272,9 +1270,9 @@ int CleanupPins(char *name, int filenum)
}
// Check if the node we're about to remove is in the
// objtab hash table
// objdict hash table
if (LookupObject(ob->name, ThisCell) == ob) {
HashDelete(ob->name, ThisCell->objtab, OBJHASHSIZE);
HashDelete(ob->name, &(ThisCell->objdict));
}
FREE(ob->name);
@ -1307,11 +1305,151 @@ typedef struct ecomplist {
} ECompList;
/*------------------------------------------------------*/
/* Survey the contents of a cell and
/* Survey a specific device in a cell and sort into a */
/* hash by critical property. */
/*------------------------------------------------------*/
void
SurveyCell(struct nlist *tc, struct hashlist **comptab, int file1, int file2, int which)
SurveyDevice(struct nlist *tc, struct hashdict *devdict,
struct nlist *cell, struct property *kl,
int file1, int file2, int which)
{
struct objlist *ob, *ob2;
struct nlist *tsub, *teq;
ECompare *dcomp, *ncomp, *qcomp;
int file = (which == 0) ? file1 : file2;
int ofile = (which == 0) ? file2 : file1;
char *p1str, *p2str, *d1str, *d2str;
for (ob = tc->cell; ob; ob = ob->next) {
if (ob->type == FIRSTPIN) {
tsub = LookupCellFile(ob->model.class, file);
if (tsub == cell) {
p1str = (char *)MALLOC(strlen(ob->model.class) + 20);
sprintf(p1str, "%s", ob->model.class);
if (tsub->flags & CELL_DUPLICATE) {
// Always register a duplicate under the original name
d1str = strstr(p1str, "[[");
if (d1str) *d1str = '\0';
}
d1str = p1str + strlen(p1str);
sprintf(d1str, "::");
d1str += 2;
teq = LookupClassEquivalent(ob->model.class, file, ofile);
p2str = (char *)MALLOC(strlen(teq->name) + 20);
sprintf(p2str, "%s", teq->name);
if (teq->flags & CELL_DUPLICATE) {
// Always register a duplicate under the original name
d2str = strstr(p2str, "[[");
if (d2str) *d2str = '\0';
}
d2str = p2str + strlen(p2str);
sprintf(d2str, "::");
d2str += 2;
// Advance ob to property list
for (ob2 = ob->next; ob2 && ob2->type != FIRSTPIN; ob2 = ob2->next) {
if (ob2->type == PROPERTY) {
struct valuelist *kv;
int i;
for (i = 0; ; i++) {
kv = &(ob2->instance.props[i]);
if (kv->type == PROP_ENDLIST) break;
if ((*matchfunc)(kv->key, kl->key)) {
switch(kv->type) {
case PROP_INTEGER:
sprintf(d1str, "%d", kv->value.ival);
sprintf(d2str, "%d", kv->value.ival);
break;
case PROP_DOUBLE:
case PROP_VALUE:
// To-do: Round to tolerance
sprintf(d1str, "%g", kv->value.dval);
sprintf(d2str, "%g", kv->value.dval);
break;
}
break;
}
}
break;
}
}
if (*d1str == '\0') {
// No critical property instanced, so use default
switch(kl->type) {
case PROP_INTEGER:
sprintf(d1str, "%d", kl->pdefault.ival);
sprintf(d2str, "%d", kl->pdefault.ival);
break;
case PROP_DOUBLE:
case PROP_VALUE:
// To-do: Round to tolerance
sprintf(d1str, "%g", kl->pdefault.dval);
sprintf(d2str, "%g", kl->pdefault.dval);
break;
}
}
// Create hash key from object class and the critical
// property affecting the device count.
dcomp = (ECompare *)HashInt2Lookup(p1str, file, devdict);
// Fill in the values for this device::property combination
if (dcomp == NULL) {
ncomp = (ECompare *)MALLOC(sizeof(ECompare));
if (which == 0) {
ncomp->num1 = 1;
ncomp->num2 = 0;
ncomp->cell1 = tsub;
ncomp->cell2 = teq;
}
else {
ncomp->num1 = 0;
ncomp->num2 = 1;
ncomp->cell2 = tsub;
ncomp->cell1 = teq;
}
ncomp->add1 = 0;
ncomp->add2 = 0;
ncomp->refcount = (char)1;
HashInt2PtrInstall(p1str, file, ncomp, devdict);
if (teq != NULL) {
qcomp = (ECompare *)HashInt2Lookup(p2str, ofile,
devdict);
if (qcomp == NULL) {
HashInt2PtrInstall(p2str, ofile, ncomp, devdict);
ncomp->refcount++;
}
}
}
else {
if (which == 0)
dcomp->num1++;
else
dcomp->num2++;
}
FREE(p1str);
FREE(p2str);
}
}
}
}
/*------------------------------------------------------*/
/* Survey the contents of a cell and sort into a hash */
/*------------------------------------------------------*/
void
SurveyCell(struct nlist *tc, struct hashdict *compdict, int file1, int file2, int which)
{
struct objlist *ob;
struct nlist *tsub, *teq;
@ -1331,8 +1469,7 @@ SurveyCell(struct nlist *tc, struct hashlist **comptab, int file1, int file2, in
else dstr = NULL;
teq = LookupClassEquivalent(ob->model.class, file, ofile);
ecomp = (ECompare *)HashInt2Lookup(ob->model.class, file,
comptab, OBJHASHSIZE);
ecomp = (ECompare *)HashInt2Lookup(ob->model.class, file, compdict);
if (ecomp == NULL) {
ncomp = (ECompare *)MALLOC(sizeof(ECompare));
@ -1352,19 +1489,16 @@ SurveyCell(struct nlist *tc, struct hashlist **comptab, int file1, int file2, in
ncomp->add2 = 0;
ncomp->refcount = (char)1;
HashInt2PtrInstall(ob->model.class, file, ncomp, comptab,
OBJHASHSIZE);
HashInt2PtrInstall(ob->model.class, file, ncomp, compdict);
if (teq != NULL) {
char *bstr = NULL;
if (teq->flags & CELL_DUPLICATE) {
bstr = strstr(teq->name, "[[");
if (bstr) *bstr = '\0';
}
qcomp = (ECompare *)HashInt2Lookup(teq->name, ofile,
comptab, OBJHASHSIZE);
qcomp = (ECompare *)HashInt2Lookup(teq->name, ofile, compdict);
if (qcomp == NULL) {
HashInt2PtrInstall(teq->name, ofile, ncomp, comptab,
OBJHASHSIZE);
HashInt2PtrInstall(teq->name, ofile, ncomp, compdict);
ncomp->refcount++;
}
if (bstr) *bstr = '[';
@ -1393,7 +1527,7 @@ SurveyCell(struct nlist *tc, struct hashlist **comptab, int file1, int file2, in
/* */
/* If there is a mismatch between instances of low- */
/* level devices, determine if the mismatches can be */
/* resolved by parallel/serial combining, accoring to */
/* resolved by parallel/serial combining, according to */
/* combination rules. */
/* */
/* Return the number of modifications made. */
@ -1404,7 +1538,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
{
struct nlist *tc1, *tc2, *tsub1, *tsub2;
struct objlist *ob1, *ob2, *lob;
struct hashlist **comptab;
struct hashdict compdict;
ECompare *ecomp, *ncomp;
ECompList *list0X, *listX0;
int match, modified = 0;
@ -1421,14 +1555,13 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
if (tc1 == NULL || tc2 == NULL) return;
comptab = (struct hashlist **)CALLOC(OBJHASHSIZE,
sizeof(struct hashlist *));
InitializeHashTable(&compdict, OBJHASHSIZE);
// Gather information about instances of cell "name1"
SurveyCell(tc1, comptab, file1, file2, 0);
SurveyCell(tc1, &compdict, file1, file2, 0);
// Gather information about instances of cell "name2"
SurveyCell(tc2, comptab, file1, file2, 1);
SurveyCell(tc2, &compdict, file1, file2, 1);
// Find all instances of one cell that have fewer in
// the compared circuit. Check whether subcircuits
@ -1436,7 +1569,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
// or subcircuits that have more in the compared circuit.
listX0 = list0X = NULL;
ecomp = (ECompare *)HashFirst(comptab, OBJHASHSIZE);
ecomp = (ECompare *)HashFirst(&compdict);
while (ecomp != NULL) {
/* Case 1: Both cell1 and cell2 classes are subcircuits, */
@ -1452,7 +1585,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
for (ob2 = ecomp->cell2->cell; ob2; ob2 = ob2->next) {
if (ob2->type == FIRSTPIN) {
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
ecomp->cell2->file, comptab, OBJHASHSIZE);
ecomp->cell2->file, &compdict);
if (ncomp != NULL) {
if ((ncomp->num1 > ncomp->num2) &&
((ncomp->add2 + ecomp->num2) >=
@ -1498,8 +1631,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
for (ob2 = ecomp->cell2->cell; ob2; ob2 = ob2->next) {
if (ob2->type == FIRSTPIN) {
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
ecomp->cell2->file, comptab,
OBJHASHSIZE);
ecomp->cell2->file, &compdict);
if (ncomp != NULL) {
if (match) {
ncomp->num1 += ncomp->add1;
@ -1549,7 +1681,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
for (ob2 = ecomp->cell2->cell; ob2; ob2 = ob2->next) {
if (ob2->type == FIRSTPIN) {
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
ecomp->cell2->file, comptab, OBJHASHSIZE);
ecomp->cell2->file, &compdict);
if (ncomp != NULL) {
if ((ncomp->num1 > ncomp->num2) &&
((ncomp->add2 + ecomp->num2) <=
@ -1582,8 +1714,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
for (ob2 = ecomp->cell2->cell; ob2; ob2 = ob2->next) {
if (ob2->type == FIRSTPIN) {
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
ecomp->cell2->file, comptab,
OBJHASHSIZE);
ecomp->cell2->file, &compdict);
if (ncomp != NULL) {
if (match) {
ncomp->num2 += ncomp->add2;
@ -1608,7 +1739,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
for (ob2 = ecomp->cell1->cell; ob2; ob2 = ob2->next) {
if (ob2->type == FIRSTPIN) {
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
ecomp->cell1->file, comptab, OBJHASHSIZE);
ecomp->cell1->file, &compdict);
if (ncomp != NULL) {
if ((ncomp->num2 > ncomp->num1) &&
((ncomp->add1 + ecomp->num1) <=
@ -1641,8 +1772,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
for (ob2 = ecomp->cell1->cell; ob2; ob2 = ob2->next) {
if (ob2->type == FIRSTPIN) {
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
ecomp->cell1->file, comptab,
OBJHASHSIZE);
ecomp->cell1->file, &compdict);
if (ncomp != NULL) {
if (match) {
ncomp->num1 += ncomp->add1;
@ -1656,13 +1786,85 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
}
ecomp->add1 = 0;
}
ecomp = (ECompare *)HashNext(comptab, OBJHASHSIZE);
ecomp = (ECompare *)HashNext(&compdict);
}
// Check for cells, either low-level devices or subcircuits,
// that have properties allowing devices to be merged. If
// the classes of both cells are the same, and the number of
// instances is different, and merging the device with more
// instances improves the matching, then perform the merge.
ecomp = (ECompare *)HashFirst(&compdict);
while (ecomp != NULL) {
if ((ecomp->num1 != ecomp->num2) &&
(ecomp->cell1 != NULL) &&
(ecomp->cell2 != NULL) &&
(ecomp->cell1->classhash == ecomp->cell2->classhash)) {
struct hashdict devdict;
ECompare *dcomp;
// Determine if either device has mergeable properties. If so,
// sort the device into bins by critical (mergeable) property,
// and merge devices where merging makes a better match.
struct property *kl1, *kl2;
kl1 = (struct property *)HashFirst(&(ecomp->cell1->propdict));
while (kl1 != NULL) {
if (kl1->merge == MERGE_ADD_CRIT || kl1->merge == MERGE_PAR_CRIT)
break;
kl1 = (struct property *)HashNext(&(ecomp->cell1->propdict));
}
kl2 = (struct property *)HashFirst(&(ecomp->cell2->propdict));
while (kl2 != NULL) {
if (kl2->merge == MERGE_ADD_CRIT || kl2->merge == MERGE_PAR_CRIT)
break;
kl2 = (struct property *)HashNext(&(ecomp->cell1->propdict));
}
if (kl1 != NULL || kl2 != NULL) {
// Create the device hash table
InitializeHashTable(&devdict, OBJHASHSIZE);
// Populate the device hash table
SurveyDevice(tc1, &devdict, ecomp->cell1, kl1, file1, file2, 0);
SurveyDevice(tc2, &devdict, ecomp->cell2, kl2, file1, file2, 0);
// Scan the device hash table. If devices can be merged
// and this improves the matching between cells, then do
// the merge.
dcomp = (ECompare *)HashFirst(&devdict);
while (dcomp != NULL) {
if (dcomp->num1 != dcomp->num2) {
/* XXX WIP WIP WIP XXX */
}
dcomp = (ECompare *)HashNext(&devdict);
}
// Free the device hash table
dcomp = (ECompare *)HashFirst(&devdict);
while (dcomp != NULL) {
if (--dcomp->refcount == (char)0) FREE(dcomp);
dcomp = (ECompare *)HashNext(&devdict);
}
HashKill(&devdict);
}
}
ecomp = (ECompare *)HashNext(&compdict);
}
// Remove non-matching zero-value devices. This can
// be done on a per-instance basis.
ecomp = (ECompare *)HashFirst(comptab, OBJHASHSIZE);
ecomp = (ECompare *)HashFirst(&compdict);
while (ecomp != NULL) {
if ((ecomp->num1 != ecomp->num2) && (ecomp->cell1 != NULL) &&
(ecomp->cell1->class == CLASS_RES)) {
@ -1869,7 +2071,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
}
}
}
ecomp = (ECompare *)HashNext(comptab, OBJHASHSIZE);
ecomp = (ECompare *)HashNext(&compdict);
}
// Finally, check all entries in listX0 vs. all entries in list0X to see
@ -1901,7 +2103,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
if (dstr) *dstr = '\0';
}
ncomp = (ECompare *)HashInt2Lookup(ob1->model.class,
ecompX0->cell1->file, comptab, OBJHASHSIZE);
ecompX0->cell1->file, &compdict);
if (dstr) *dstr = '[';
if ((ncomp == ecomp0X) && (ecomp0X->num2 <= ecompX0->num1)) {
Fprintf(stdout, "Flattening instances of %s in cell %s"
@ -1927,7 +2129,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
if (dstr) *dstr = '\0';
}
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
ecomp0X->cell2->file, comptab, OBJHASHSIZE);
ecomp0X->cell2->file, &compdict);
if (dstr) *dstr = '[';
if ((ncomp == ecompX0) && (ecompX0->num1 <= ecomp0X->num2)) {
Fprintf(stdout, "Flattening instances of %s in cell %s"
@ -1948,13 +2150,12 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
// Free the hash table and its contents.
ecomp = (ECompare *)HashFirst(comptab, OBJHASHSIZE);
ecomp = (ECompare *)HashFirst(&compdict);
while (ecomp != NULL) {
if (--ecomp->refcount == (char)0) FREE(ecomp);
ecomp = (ECompare *)HashNext(comptab, OBJHASHSIZE);
ecomp = (ECompare *)HashNext(&compdict);
}
HashKill(comptab, OBJHASHSIZE);
FREE(comptab);
HashKill(&compdict);
// Free the 0:X and X:0 lists
while (listX0 != NULL) {

View File

@ -33,22 +33,25 @@ unsigned long (*hashfunc)(char *, int) = NULL;
int (*matchfunc)(char *, char *) = NULL;
int (*matchintfunc)(char *, char *, int, int) = NULL;
void InitializeHashTable(struct hashlist **tab, int size)
void InitializeHashTable(struct hashdict *dict, int size)
{
int i;
for (i = 0; i < size; i++) tab[i] = NULL;
struct hashlist **hashtab;
dict->hashtab = (struct hashlist **)CALLOC(size, sizeof(struct hashlist *));
dict->hashsize = size;
dict->hashfirstindex = 0;
dict->hashfirstptr = NULL;
}
int RecurseHashTable(struct hashlist **hashtab, int hashsize,
int (*func)(struct hashlist *elem))
int RecurseHashTable(struct hashdict *dict, int (*func)(struct hashlist *elem))
/* returns the sum of the return values of (*func) */
{
int i, sum;
struct hashlist *p;
sum = 0;
for (i = 0; i < hashsize; i++)
for (p = hashtab[i]; p != NULL; p = p->next)
for (i = 0; i < dict->hashsize; i++)
for (p = dict->hashtab[i]; p != NULL; p = p->next)
sum += (*func)(p);
return(sum);
}
@ -57,15 +60,15 @@ int RecurseHashTable(struct hashlist **hashtab, int hashsize,
* type int value to the function.
*/
int RecurseHashTableValue(struct hashlist **hashtab, int hashsize,
int RecurseHashTableValue(struct hashdict *dict,
int (*func)(struct hashlist *elem, int), int value)
{
int i, sum;
struct hashlist *p;
sum = 0;
for (i = 0; i < hashsize; i++)
for (p = hashtab[i]; p != NULL; p = p->next)
for (i = 0; i < dict->hashsize; i++)
for (p = dict->hashtab[i]; p != NULL; p = p->next)
sum += (*func)(p, value);
return(sum);
}
@ -76,7 +79,7 @@ int RecurseHashTableValue(struct hashlist **hashtab, int hashsize,
* function through that structure.
*/
struct nlist *RecurseHashTablePointer(struct hashlist **hashtab, int hashsize,
struct nlist *RecurseHashTablePointer(struct hashdict *dict,
struct nlist *(*func)(struct hashlist *elem, void *),
void *pointer)
{
@ -84,8 +87,8 @@ struct nlist *RecurseHashTablePointer(struct hashlist **hashtab, int hashsize,
struct hashlist *p;
struct nlist *tp;
for (i = 0; i < hashsize; i++) {
for (p = hashtab[i]; p != NULL; p = p->next) {
for (i = 0; i < dict->hashsize; i++) {
for (p = dict->hashtab[i]; p != NULL; p = p->next) {
tp = (*func)(p, pointer);
if (tp != NULL) return tp;
}
@ -164,14 +167,14 @@ unsigned long genhash(char *s, int c, int hashsize)
/* return the 'ptr' field of the hash table entry, or NULL if not found */
/*----------------------------------------------------------------------*/
void *HashLookup(char *s, struct hashlist **hashtab, int hashsize)
void *HashLookup(char *s, struct hashdict *dict)
{
struct hashlist *np;
unsigned long hashval;
hashval = (*hashfunc)(s, hashsize);
hashval = (*hashfunc)(s, dict->hashsize);
for (np = hashtab[hashval]; np != NULL; np = np->next)
for (np = dict->hashtab[hashval]; np != NULL; np = np->next)
if ((*matchfunc)(s, np->name)) return (np->ptr); /* correct match */
return (NULL); /* not found */
}
@ -183,14 +186,14 @@ void *HashLookup(char *s, struct hashlist **hashtab, int hashsize)
/* passed integer value i */
/*----------------------------------------------------------------------*/
void *HashIntLookup(char *s, int i, struct hashlist **hashtab, int hashsize)
void *HashIntLookup(char *s, int i, struct hashdict *dict)
{
struct hashlist *np;
unsigned long hashval;
hashval = (*hashfunc)(s, hashsize);
hashval = (*hashfunc)(s, dict->hashsize);
for (np = hashtab[hashval]; np != NULL; np = np->next) {
for (np = dict->hashtab[hashval]; np != NULL; np = np->next) {
if (np->ptr == NULL) {
if ((*matchintfunc)(s, np->name, i, -1))
return NULL;
@ -209,14 +212,14 @@ void *HashIntLookup(char *s, int i, struct hashlist **hashtab, int hashsize)
/* first, then the character string. */
/*----------------------------------------------------------------------*/
void *HashInt2Lookup(char *s, int c, struct hashlist **hashtab, int hashsize)
void *HashInt2Lookup(char *s, int c, struct hashdict *dict)
{
struct hashlist *np;
unsigned long hashval;
hashval = genhash(s, c, hashsize);
hashval = genhash(s, c, dict->hashsize);
for (np = hashtab[hashval]; np != NULL; np = np->next)
for (np = dict->hashtab[hashval]; np != NULL; np = np->next)
if (!strcmp(s, np->name))
return (np->ptr); /* correct match */
@ -228,14 +231,13 @@ void *HashInt2Lookup(char *s, int c, struct hashlist **hashtab, int hashsize)
/* return the hashlist entry, after (re)initializing its 'ptr' field */
/*----------------------------------------------------------------------*/
struct hashlist *HashPtrInstall(char *name, void *ptr,
struct hashlist **hashtab, int hashsize)
struct hashlist *HashPtrInstall(char *name, void *ptr, struct hashdict *dict)
{
struct hashlist *np;
unsigned long hashval;
hashval = (*hashfunc)(name,hashsize);
for (np = hashtab[hashval]; np != NULL; np = np->next)
hashval = (*hashfunc)(name, dict->hashsize);
for (np = dict->hashtab[hashval]; np != NULL; np = np->next)
if ((*matchfunc)(name, np->name)) {
np->ptr = ptr;
return (np); /* match found in hash table */
@ -246,8 +248,8 @@ struct hashlist *HashPtrInstall(char *name, void *ptr,
return (NULL);
if ((np->name = strsave(name)) == NULL) return (NULL);
np->ptr = ptr;
np->next = hashtab[hashval];
return(hashtab[hashval] = np);
np->next = dict->hashtab[hashval];
return(dict->hashtab[hashval] = np);
}
/*----------------------------------------------------------------------*/
@ -256,13 +258,13 @@ struct hashlist *HashPtrInstall(char *name, void *ptr,
/*----------------------------------------------------------------------*/
struct hashlist *HashIntPtrInstall(char *name, int value, void *ptr,
struct hashlist **hashtab, int hashsize)
struct hashdict *dict)
{
struct hashlist *np;
unsigned long hashval;
hashval = (*hashfunc)(name,hashsize);
for (np = hashtab[hashval]; np != NULL; np = np->next)
hashval = (*hashfunc)(name, dict->hashsize);
for (np = dict->hashtab[hashval]; np != NULL; np = np->next)
if ((*matchintfunc)(name, np->name, value, (int)(*((int *)np->ptr)))) {
np->ptr = ptr;
return (np); /* match found in hash table */
@ -273,8 +275,8 @@ struct hashlist *HashIntPtrInstall(char *name, int value, void *ptr,
return (NULL);
if ((np->name = strsave(name)) == NULL) return (NULL);
np->ptr = ptr;
np->next = hashtab[hashval];
return(hashtab[hashval] = np);
np->next = dict->hashtab[hashval];
return(dict->hashtab[hashval] = np);
}
/*----------------------------------------------------------------------*/
@ -282,13 +284,13 @@ struct hashlist *HashIntPtrInstall(char *name, int value, void *ptr,
/*----------------------------------------------------------------------*/
struct hashlist *HashInt2PtrInstall(char *name, int c, void *ptr,
struct hashlist **hashtab, int hashsize)
struct hashdict *dict)
{
struct hashlist *np;
unsigned long hashval;
hashval = genhash(name, c, hashsize);
for (np = hashtab[hashval]; np != NULL; np = np->next)
hashval = genhash(name, c, dict->hashsize);
for (np = dict->hashtab[hashval]; np != NULL; np = np->next)
if (!strcmp(name, np->name)) {
np->ptr = ptr;
return (np); /* match found in hash table */
@ -299,27 +301,31 @@ struct hashlist *HashInt2PtrInstall(char *name, int c, void *ptr,
return (NULL);
if ((np->name = strsave(name)) == NULL) return (NULL);
np->ptr = ptr;
np->next = hashtab[hashval];
return(hashtab[hashval] = np);
np->next = dict->hashtab[hashval];
return(dict->hashtab[hashval] = np);
}
/*----------------------------------------------------------------------*/
/* destroy a hash table, freeing associated memory */
/*----------------------------------------------------------------------*/
void *HashKill(struct hashlist **hashtab, int hashsize)
void *HashKill(struct hashdict *dict)
{
struct hashlist *np, *p;
int i;
for (i = 0; i < hashsize; i++) {
for (p = hashtab[i]; p != NULL; ) {
if (dict->hashtab == NULL) return; // Hash not initialized
for (i = 0; i < dict->hashsize; i++) {
for (p = dict->hashtab[i]; p != NULL; ) {
np = p->next;
FREE(p->name);
FREE(p);
p = np;
}
}
FREE(dict->hashtab);
dict->hashtab = NULL;
}
/*----------------------------------------------------------------------*/
@ -327,14 +333,13 @@ void *HashKill(struct hashlist **hashtab, int hashsize)
/* to the new hash entry. */
/*----------------------------------------------------------------------*/
struct hashlist *HashInstall(char *name,
struct hashlist **hashtab, int hashsize)
struct hashlist *HashInstall(char *name, struct hashdict *dict)
{
struct hashlist *np;
unsigned long hashval;
hashval = (*hashfunc)(name,hashsize);
for (np = hashtab[hashval]; np != NULL; np = np->next)
hashval = (*hashfunc)(name, dict->hashsize);
for (np = dict->hashtab[hashval]; np != NULL; np = np->next)
if ((*matchfunc)(name, np->name)) return (np); /* match found in hash table */
/* not in table, so install it */
@ -342,27 +347,27 @@ struct hashlist *HashInstall(char *name,
return (NULL);
if ((np->name = strsave(name)) == NULL) return (NULL);
np->ptr = NULL;
np->next = hashtab[hashval];
return(hashtab[hashval] = np);
np->next = dict->hashtab[hashval];
return(dict->hashtab[hashval] = np);
}
/*----------------------------------------------------------------------*/
/* frees a hash table entry, (but not the 'ptr' field) */
/*----------------------------------------------------------------------*/
void HashDelete(char *name, struct hashlist **hashtab, int hashsize)
void HashDelete(char *name, struct hashdict *dict)
{
unsigned long hashval;
struct hashlist *np;
struct hashlist *np2;
hashval = (*hashfunc)(name, hashsize);
np = hashtab[hashval];
hashval = (*hashfunc)(name, dict->hashsize);
np = dict->hashtab[hashval];
if (np == NULL) return;
if ((*matchfunc)(name, np->name)) {
/* it is the first element in the list */
hashtab[hashval] = np->next;
dict->hashtab[hashval] = np->next;
FREE(np->name);
FREE(np);
return;
@ -385,19 +390,19 @@ void HashDelete(char *name, struct hashlist **hashtab, int hashsize)
/* HashDelete with additional integer value matching */
/*----------------------------------------------------------------------*/
void HashIntDelete(char *name, int value, struct hashlist **hashtab, int hashsize)
void HashIntDelete(char *name, int value, struct hashdict *dict)
{
unsigned long hashval;
struct hashlist *np;
struct hashlist *np2;
hashval = (*hashfunc)(name, hashsize);
np = hashtab[hashval];
hashval = (*hashfunc)(name, dict->hashsize);
np = dict->hashtab[hashval];
if (np == NULL) return;
if ((*matchintfunc)(name, np->name, value, (int)(*((int *)np->ptr)))) {
/* it is the first element in the list */
hashtab[hashval] = np->next;
dict->hashtab[hashval] = np->next;
FREE(np->name);
FREE(np);
return;
@ -418,32 +423,34 @@ void HashIntDelete(char *name, int value, struct hashlist **hashtab, int hashsiz
}
/*----------------------------------------------------------------------*/
static int hashfirstindex; /* was long */
static struct hashlist *hashfirstptr;
void *HashNext(struct hashlist **hashtab, int hashsize)
/* Hash key iterator */
/* returns 'ptr' field of next element, NULL when done */
/*----------------------------------------------------------------------*/
void *HashNext(struct hashdict *dict)
{
if (hashfirstptr != NULL && hashfirstptr->next != NULL) {
hashfirstptr = hashfirstptr->next;
return(hashfirstptr->ptr);
if (dict->hashfirstptr != NULL && dict->hashfirstptr->next != NULL) {
dict->hashfirstptr = dict->hashfirstptr->next;
return(dict->hashfirstptr->ptr);
}
while (hashfirstindex < hashsize) {
if ((hashfirstptr = hashtab[hashfirstindex++]) != NULL) {
return(hashfirstptr->ptr);
while (dict->hashfirstindex < dict->hashsize) {
if ((dict->hashfirstptr = dict->hashtab[dict->hashfirstindex++]) != NULL) {
return(dict->hashfirstptr->ptr);
}
}
hashfirstindex = 0;
hashfirstptr = NULL;
dict->hashfirstindex = 0;
dict->hashfirstptr = NULL;
return(NULL);
}
void *HashFirst(struct hashlist **hashtab, int hashsize)
/*----------------------------------------------------------------------*/
/* Hash key iterator setup */
/*----------------------------------------------------------------------*/
void *HashFirst(struct hashdict *dict)
{
hashfirstindex = 0;
hashfirstptr = NULL;
return(HashNext(hashtab,hashsize));
dict->hashfirstindex = 0;
dict->hashfirstptr = NULL;
return HashNext(dict);
}

View File

@ -7,38 +7,44 @@ struct hashlist {
struct hashlist *next;
};
extern void InitializeHashTable(struct hashlist **tab, int size);
extern int RecurseHashTable(struct hashlist **hashtab, int hashsize,
struct hashdict {
int hashsize;
int hashfirstindex;
struct hashlist *hashfirstptr;
struct hashlist **hashtab;
};
extern void InitializeHashTable(struct hashdict *dict, int size);
extern int RecurseHashTable(struct hashdict *dict,
int (*func)(struct hashlist *elem));
extern int RecurseHashTableValue(struct hashlist **hashtab, int hashsize,
extern int RecurseHashTableValue(struct hashdict *dict,
int (*func)(struct hashlist *elem, int), int);
extern struct nlist *RecurseHashTablePointer(struct hashlist **hashtab,
int hashsize, struct nlist *(*func)(struct hashlist *elem,
void *), void *pointer);
extern struct nlist *RecurseHashTablePointer(struct hashdict *dict,
struct nlist *(*func)(struct hashlist *elem, void *),
void *pointer);
extern void HashDelete(char *name, struct hashdict *dict);
extern void HashIntDelete(char *name, int value, struct hashdict *dict);
extern int CountHashTableEntries(struct hashlist *p);
extern int CountHashTableBinsUsed(struct hashlist *p);
extern void HashDelete(char *name, struct hashlist **hashtab, int hashsize);
extern void HashIntDelete(char *name, int value, struct hashlist **hashtab,
int hashsize);
/* these functions return a pointer to a hash list element */
extern struct hashlist *HashInstall(char *name, struct hashlist **hashtab,
int hashsize);
extern struct hashlist *HashInstall(char *name, struct hashdict *dict);
extern struct hashlist *HashPtrInstall(char *name, void *ptr,
struct hashlist **hashtab, int hashsize);
struct hashdict *dict);
extern struct hashlist *HashIntPtrInstall(char *name, int value, void *ptr,
struct hashlist **hashtab, int hashsize);
struct hashdict *dict);
extern struct hashlist *HashInt2PtrInstall(char *name, int c, void *ptr,
struct hashlist **hashtab, int hashsize);
struct hashdict *dict);
/* these functions return the ->ptr field of a struct hashlist */
extern void *HashLookup(char *s, struct hashlist **hashtab, int hashsize);
extern void *HashIntLookup(char *s, int i, struct hashlist **hashtab, int hashsize);
extern void *HashInt2Lookup(char *s, int c, struct hashlist **hashtab, int hashsize);
extern void *HashFirst(struct hashlist **hashtab, int hashsize);
extern void *HashNext(struct hashlist **hashtab, int hashsize);
extern void *HashLookup(char *s, struct hashdict *dict);
extern void *HashIntLookup(char *s, int i, struct hashdict *dict);
extern void *HashInt2Lookup(char *s, int c, struct hashdict *dict);
extern void *HashFirst(struct hashdict *dict);
extern void *HashNext(struct hashdict *dict);
extern unsigned long hashnocase(char *s, int hashsize);
extern unsigned long hash(char *s, int hashsize);

View File

@ -3319,7 +3319,7 @@ int PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print)
if (vl2->type == PROP_ENDLIST) break;
if (vl2 == NULL) continue;
if (vl2->key == NULL) continue;
kl2 = (struct property *)HashLookup(vl2->key, tc2->proptab, OBJHASHSIZE);
kl2 = (struct property *)HashLookup(vl2->key, &(tc2->propdict));
if (kl2 != NULL) break; // Property is required
else if ((*matchfunc)(vl2->key, "M")) {
if (vl2->type == PROP_INTEGER)
@ -3344,7 +3344,7 @@ int PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print)
if (vl1->type == PROP_ENDLIST) break;
if (vl1 == NULL) continue;
if (vl1->key == NULL) continue;
kl1 = (struct property *)HashLookup(vl1->key, tc1->proptab, OBJHASHSIZE);
kl1 = (struct property *)HashLookup(vl1->key, &(tc1->propdict));
if (kl1 != NULL) break; // Property is required
else if ((*matchfunc)(vl1->key, "M")) {
if (vl1->type == PROP_INTEGER)
@ -3369,7 +3369,7 @@ int PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print)
if (vl1->key == NULL) continue;
/* Check if this is a "property of interest". */
kl1 = (struct property *)HashLookup(vl1->key, tc1->proptab, OBJHASHSIZE);
kl1 = (struct property *)HashLookup(vl1->key, &(tc1->propdict));
if (kl1 == NULL) continue;
/* Find the matching property in vl2. With luck, they're in order. */
@ -3386,7 +3386,7 @@ int PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print)
if (vl2->key == NULL) continue;
/* Both device classes must agree on the properties to compare */
kl2 = (struct property *)HashLookup(vl2->key, tc2->proptab, OBJHASHSIZE);
kl2 = (struct property *)HashLookup(vl2->key, &(tc2->propdict));
if (kl2 == NULL) continue;
/* Watch out for uninitialized entries in cell def */
@ -4488,7 +4488,7 @@ int reorderpins(struct hashlist *p, int file)
ob->node = nodes[i];
ob->name = names[i];
}
HashPtrInstall(ob->name, ob, ptr->objtab, OBJHASHSIZE);
HashPtrInstall(ob->name, ob, &(ptr->objdict));
ob = ob->next;
names[i] = NULL;
}
@ -4566,12 +4566,11 @@ struct nlist *addproxies(struct hashlist *p, void *clientdata)
lob = obn;
// Hash the new pin record for "LookupObject()"
HashPtrInstall(obn->name, obn, ptr->objtab, OBJHASHSIZE);
HashPtrInstall(obn->name, obn, &(ptr->objdict));
if (tob == tc->cell) {
// Rehash the instance in insttab
HashPtrInstall(firstpin->instance.name, firstpin,
ptr->insttab, OBJHASHSIZE);
// Rehash the instance in instdict
HashPtrInstall(firstpin->instance.name, firstpin, &(ptr->instdict));
}
}
else {
@ -4595,7 +4594,7 @@ struct nlist *addproxies(struct hashlist *p, void *clientdata)
obn->next = NULL;
lob->next = obn;
lob = obn;
HashPtrInstall(obn->name, obn, ptr->objtab, OBJHASHSIZE);
HashPtrInstall(obn->name, obn, &(ptr->objdict));
}
// We messed with the node name list, so have to re-cache them
@ -4888,7 +4887,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2)
ob1 = obn;
hasproxy1 = 1;
HashPtrInstall(obn->name, obn, tc1->objtab, OBJHASHSIZE);
HashPtrInstall(obn->name, obn, &(tc1->objdict));
}
}
@ -4946,7 +4945,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2)
ob2 = obn;
hasproxy2 = 1;
HashPtrInstall(obn->name, obn, tc2->objtab, OBJHASHSIZE);
HashPtrInstall(obn->name, obn, &(tc2->objdict));
}
else if (ob1 != NULL && ob1->type == PORT) {

View File

@ -54,7 +54,7 @@ extern int errno; /* Defined in stdlib.h */
static char staticstrings[MAX_STATIC_STRINGS][200];
static int laststring;
extern struct hashlist **spiceparams; /* From spice.c */
extern struct hashdict spiceparams; /* From spice.c */
char *Str(char *format, ...)
{
@ -188,18 +188,15 @@ int TokGetValue(char *estr, struct nlist *parent, int glob, double *dval)
if (glob == TRUE) {
/* Check global parameters */
if (spiceparams != NULL) {
kl = (struct property *)HashLookup(estr,
spiceparams, OBJHASHSIZE);
kl = (struct property *)HashLookup(estr, &spiceparams);
if (kl != NULL) {
result = ConvertStringToFloat(kl->pdefault.string, dval);
return ((result == 0) ? -1 : 1);
}
}
}
/* Check local parameters */
kl = (struct property *)HashLookup(estr, parent->proptab, OBJHASHSIZE);
kl = (struct property *)HashLookup(estr, &(parent->propdict));
if (kl != NULL) {
switch(kl->type) {
case PROP_STRING:
@ -834,19 +831,17 @@ PropertyDelete(char *name, int fnum, char *key)
/* key == NULL means delete all properties. */
RecurseHashTable(tc->proptab, OBJHASHSIZE, freeprop);
HashKill(tc->proptab, OBJHASHSIZE);
FREE(tc->proptab);
tc->proptab = (struct hashlist **)CALLOC(OBJHASHSIZE,
sizeof(struct hashlist *));
RecurseHashTable(&(tc->propdict), freeprop);
HashKill(&(tc->propdict));
InitializeHashTable(&(tc->propdict), OBJHASHSIZE);
}
else {
kl = (struct property *)HashLookup(key, tc->proptab, OBJHASHSIZE);
kl = (struct property *)HashLookup(key, &(tc->propdict));
if (kl != NULL) {
if (kl->type == PROP_STRING || kl->type == PROP_EXPRESSION)
FREE(kl->pdefault.string);
FREE(kl->key);
HashDelete(key, tc->proptab, OBJHASHSIZE);
HashDelete(key, &(tc->propdict));
}
else {
Printf("No property %s found for device %s\n", key, name);
@ -879,7 +874,7 @@ PropertyTolerance(char *name, int fnum, char *key, int ival, double dval)
return -1;
}
kl = (struct property *)HashLookup(key, tc->proptab, OBJHASHSIZE);
kl = (struct property *)HashLookup(key, &(tc->propdict));
if (kl == NULL) {
Printf("No property %s found for device %s\n", key, name);
return -1;
@ -900,6 +895,40 @@ PropertyTolerance(char *name, int fnum, char *key, int ival, double dval)
return 0;
}
/*----------------------------------------------------------------------*/
/* Set the merge type of a property in the master cell record. */
/*----------------------------------------------------------------------*/
int
PropertyMerge(char *name, int fnum, char *key, int merge_type)
{
struct property *kl = NULL;
struct nlist *tc;
int result;
if ((fnum == -1) && (Circuit1 != NULL) && (Circuit2 != NULL)) {
result = PropertyMerge(name, Circuit1->file, key, merge_type);
result = PropertyMerge(name, Circuit2->file, key, merge_type);
return result;
}
tc = LookupCellFile(name, fnum);
if (tc == NULL) {
Printf("No device %s found for PropertyTolerance()\n", name);
return -1;
}
kl = (struct property *)HashLookup(key, &(tc->propdict));
if (kl == NULL) {
Printf("No property %s found for device %s\n", key, name);
return -1;
}
else {
kl->merge = merge_type;
}
return 0;
}
/*----------------------------------------------------------------------*/
/* Add a new value property to the indicated cell */
/* Value properties are used for resistors and capacitors in SPICE */
@ -923,18 +952,18 @@ struct property *PropertyValue(char *name, int fnum, char *key,
tc = LookupCellFile(name, fnum);
if (tc == NULL)
Printf("No device %s found for PropertyValue()\n", name);
else if ((kl = (struct property *)HashLookup(key, tc->proptab,
OBJHASHSIZE)) != NULL) {
else if ((kl = (struct property *)HashLookup(key, &(tc->propdict))) != NULL) {
Printf("Device %s already has property named \"%s\"\n", name, key);
}
else {
kl = NewProperty();
kl->key = strsave(key);
kl->idx = 0;
kl->merge = MERGE_NONE;
kl->type = PROP_VALUE;
kl->slop.dval = slop;
kl->pdefault.dval = pdefault;
HashPtrInstall(kl->key, kl, tc->proptab, OBJHASHSIZE);
HashPtrInstall(kl->key, kl, &(tc->propdict));
}
return kl;
}
@ -958,18 +987,18 @@ struct property *PropertyDouble(char *name, int fnum, char *key,
tc = LookupCellFile(name, fnum);
if (tc == NULL)
Printf("No device %s found for PropertyDouble()\n", name);
else if ((kl = (struct property *)HashLookup(key, tc->proptab,
OBJHASHSIZE)) != NULL) {
else if ((kl = (struct property *)HashLookup(key, &(tc->propdict))) != NULL) {
Printf("Device %s already has property named \"%s\"\n", name, key);
}
else {
kl = NewProperty();
kl->key = strsave(key);
kl->idx = 0;
kl->merge = MERGE_NONE;
kl->type = PROP_DOUBLE;
kl->slop.dval = slop;
kl->pdefault.dval = pdefault;
HashPtrInstall(kl->key, kl, tc->proptab, OBJHASHSIZE);
HashPtrInstall(kl->key, kl, &(tc->propdict));
}
return kl;
}
@ -991,18 +1020,18 @@ struct property *PropertyInteger(char *name, int fnum, char *key,
tc = LookupCellFile(name, fnum);
if (tc == NULL)
Printf("No device %s found for PropertyInteger()\n", name);
else if ((kl = (struct property *)HashLookup(key, tc->proptab,
OBJHASHSIZE)) != NULL) {
else if ((kl = (struct property *)HashLookup(key, &(tc->propdict))) != NULL) {
Printf("Device %s already has property named \"%s\"\n", name, key);
}
else {
kl = NewProperty();
kl->key = strsave(key);
kl->idx = 0;
kl->merge = MERGE_NONE;
kl->type = PROP_INTEGER;
kl->slop.ival = slop;
kl->pdefault.ival = pdefault;
HashPtrInstall(kl->key, kl, tc->proptab, OBJHASHSIZE);
HashPtrInstall(kl->key, kl, &(tc->propdict));
}
return kl;
}
@ -1024,21 +1053,21 @@ struct property *PropertyString(char *name, int fnum, char *key, int range,
tc = LookupCellFile(name, fnum);
if (tc == NULL)
Printf("No device %s found for PropertyString()\n", name);
else if ((kl = (struct property *)HashLookup(key, tc->proptab,
OBJHASHSIZE)) != NULL) {
else if ((kl = (struct property *)HashLookup(key, &(tc->propdict))) != NULL) {
Printf("Device %s already has property named \"%s\"\n", name, key);
}
else {
kl = NewProperty();
kl->key = strsave(key);
kl->idx = 0;
kl->merge = MERGE_NONE;
kl->type = PROP_STRING;
kl->slop.ival = (range >= 0) ? range : 0;
if (pdefault != NULL)
kl->pdefault.string = strsave(pdefault);
else
kl->pdefault.string = NULL;
HashPtrInstall(kl->key, kl, tc->proptab, OBJHASHSIZE);
HashPtrInstall(kl->key, kl, &(tc->propdict));
}
return kl;
}
@ -1975,7 +2004,7 @@ struct objlist *LinkProperties(char *model, struct keyvalue *topptr)
/* If there is a matching cell, make sure that the property */
/* key exists. If not, create it and flag a warning. */
kl = (struct property *)HashLookup(newkv->key, cell->proptab, OBJHASHSIZE);
kl = (struct property *)HashLookup(newkv->key, &(cell->propdict));
if (kl == NULL) {
/* Ideally, for devices, one should check against all */
/* known standard properties. That's a pain, so */
@ -1988,10 +2017,11 @@ struct objlist *LinkProperties(char *model, struct keyvalue *topptr)
kl = NewProperty();
kl->key = strsave(newkv->key);
kl->idx = 0;
kl->merge = MERGE_NONE;
kl->type = PROP_STRING;
kl->slop.ival = 0;
kl->pdefault.string = NULL;
HashPtrInstall(kl->key, kl, cell->proptab, OBJHASHSIZE);
HashPtrInstall(kl->key, kl, &(cell->propdict));
}
}
}
@ -2183,7 +2213,7 @@ struct nlist *resolveprops(struct hashlist *p, void *clientdata)
for (i = 0;; i++) {
vl = &(ob->instance.props[i]);
if (vl->type == PROP_ENDLIST) break;
prop = (struct property *)HashLookup(vl->key, tc->proptab, OBJHASHSIZE);
prop = (struct property *)HashLookup(vl->key, &(tc->propdict));
/* Warning: prop should never be null, but condition */
/* should be handled. */
@ -2238,7 +2268,7 @@ void ResolveProperties(char *name1, int file1, char *name2, int file2)
/* index. If the property does not exist in the second cell, then */
/* create it. */
kl1 = (struct property *)HashFirst(tp1->proptab, OBJHASHSIZE);
kl1 = (struct property *)HashFirst(&(tp1->propdict));
/* If indexes are not zero, then properties have already been matched. */
if (kl1 == NULL) return; /* Cell has no properties */
if (kl1->idx != 0) return;
@ -2247,7 +2277,7 @@ void ResolveProperties(char *name1, int file1, char *name2, int file2)
while (kl1 != NULL) {
kl1->idx = i;
kl2 = (struct property *)HashLookup(kl1->key, tp2->proptab, OBJHASHSIZE);
kl2 = (struct property *)HashLookup(kl1->key, &(tp2->propdict));
if (kl2 == NULL) {
/* No such property in tp2 */
switch (kl1->type) {
@ -2270,16 +2300,16 @@ void ResolveProperties(char *name1, int file1, char *name2, int file2)
}
}
if (kl2 != NULL) kl2->idx = i;
kl1 = (struct property *)HashNext(tp1->proptab, OBJHASHSIZE);
kl1 = (struct property *)HashNext(&(tp1->propdict));
i++;
}
/* Now check tp2 for properties not in tp1 */
kl2 = (struct property *)HashFirst(tp2->proptab, OBJHASHSIZE);
kl2 = (struct property *)HashFirst(&(tp2->propdict));
while (kl2 != NULL) {
kl1 = (struct property *)HashLookup(kl2->key, tp1->proptab, OBJHASHSIZE);
kl1 = (struct property *)HashLookup(kl2->key, &(tp1->propdict));
if (kl1 == NULL) {
/* No such property in tp1 */
switch (kl2->type) {
@ -2302,7 +2332,7 @@ void ResolveProperties(char *name1, int file1, char *name2, int file2)
}
}
if (kl1 != NULL) kl1->idx = i;
kl2 = (struct property *)HashNext(tp1->proptab, OBJHASHSIZE);
kl2 = (struct property *)HashNext(&(tp1->propdict));
i++;
}

View File

@ -37,6 +37,7 @@ extern struct property *PropertyString(char *name, int fnum, char *key,
extern int PropertyDelete(char *name, int fnum, char *key);
extern int PropertyTolerance(char *name, int fnum, char *key, int ival,
double dval);
extern int PropertyMerge(char *name, int fnum, char *key, int merge_type);
extern void ResolveProperties(char *name1, int file1, char *name2, int file2);
extern void CopyProperties(struct objlist *obj_to, struct objlist *obj_from);
extern int PromoteProperty(struct property *, struct valuelist *);

View File

@ -251,18 +251,18 @@ void PrintMemoryStats(void)
#define CELLHASHSIZE 1000
static struct hashlist *cell_hashtab[CELLHASHSIZE];
static struct hashdict cell_dict;
void InitCellHashTable(void)
{
hashfunc = hash;
matchfunc = match;
InitializeHashTable(cell_hashtab, CELLHASHSIZE);
InitializeHashTable(&cell_dict, CELLHASHSIZE);
}
struct nlist *LookupCell(char *s)
{
return((struct nlist *)HashLookup(s, cell_hashtab, CELLHASHSIZE));
return((struct nlist *)HashLookup(s, &cell_dict));
}
/* Similar hash lookup to the above, but will check if the matching */
@ -274,7 +274,7 @@ struct nlist *LookupCellFile(char *s, int f)
struct nlist *he;
if (f == -1) return LookupCell(s);
return HashIntLookup(s, f, cell_hashtab, CELLHASHSIZE);
return HashIntLookup(s, f, &cell_dict);
}
struct nlist *InstallInCellHashTable(char *name, int fnum)
@ -291,34 +291,23 @@ struct nlist *InstallInCellHashTable(char *name, int fnum)
if (p == NULL) return(NULL);
if ((p->name = strsave(name)) == NULL) goto fail;
p->file = fnum;
if ((p->objtab = (struct hashlist **)CALLOC(OBJHASHSIZE,
sizeof(struct hashlist *))) == NULL) goto fail;
if ((p->insttab = (struct hashlist **)CALLOC(OBJHASHSIZE,
sizeof(struct hashlist *))) == NULL) goto fail;
if ((p->proptab = (struct hashlist **)CALLOC(OBJHASHSIZE,
sizeof(struct hashlist *))) == NULL) goto fail;
InitializeHashTable(&(p->objdict), OBJHASHSIZE);
InitializeHashTable(&(p->instdict), OBJHASHSIZE);
InitializeHashTable(&(p->propdict), OBJHASHSIZE);
p->permutes = NULL;
// Hash size 0 indicates to hash function that no binning is being done
p->classhash = (*hashfunc)(name, 0);
ptr = HashIntPtrInstall(name, fnum, p, cell_hashtab, CELLHASHSIZE);
ptr = HashIntPtrInstall(name, fnum, p, &cell_dict);
if (ptr == NULL) return(NULL);
return(p);
fail:
if (p->name != NULL) FREE(p->name);
if (p->objtab != NULL) {
HashKill(p->objtab, OBJHASHSIZE);
FREE(p->objtab);
}
if (p->insttab != NULL) {
HashKill(p->insttab, OBJHASHSIZE);
FREE(p->insttab);
}
if (p->proptab != NULL) {
HashKill(p->proptab, OBJHASHSIZE);
FREE(p->proptab);
}
HashKill(&(p->objdict));
HashKill(&(p->instdict));
RecurseHashTable(&(p->propdict), freeprop);
HashKill(&(p->propdict));
FREE(p);
return(NULL);
}
@ -341,9 +330,9 @@ void CellRehash(char *name, char *newname, int file)
FREE(tp->name);
tp->name = strsave(newname);
ptr = HashIntPtrInstall(newname, file, (void *)tp, cell_hashtab, CELLHASHSIZE);
ptr = HashIntPtrInstall(newname, file, (void *)tp, &cell_dict);
if (ptr != NULL)
HashIntDelete(name, file, cell_hashtab, CELLHASHSIZE);
HashIntDelete(name, file, &cell_dict);
// Change the classhash to reflect the new name
tp->classhash = (*hashfunc)(newname, 0);
@ -365,7 +354,7 @@ int deleteclass(struct hashlist *p, int file)
nob = ob->next;
if ((ob->type == FIRSTPIN) && (ob->model.class != NULL)) {
if ((*matchfunc)(ob->model.class, OldCell->name)) {
HashDelete(ob->instance.name, ptr->insttab, OBJHASHSIZE);
HashDelete(ob->instance.name, &(ptr->instdict));
while (1) {
FreeObjectAndHash(ob, ptr);
ob = nob;
@ -482,22 +471,13 @@ void CellDelete(char *name, int fnum)
return;
}
HashIntDelete(name, fnum, cell_hashtab, CELLHASHSIZE);
HashIntDelete(name, fnum, &cell_dict);
/* now make sure that we free all the fields of the nlist struct */
if (tp->name != NULL) FREE(tp->name);
if (tp->objtab != NULL) {
HashKill(tp->objtab, OBJHASHSIZE);
FREE(tp->objtab);
}
if (tp->insttab != NULL) {
HashKill(tp->insttab, OBJHASHSIZE);
FREE(tp->insttab);
}
if (tp->proptab != NULL) {
RecurseHashTable(tp->proptab, OBJHASHSIZE, freeprop);
HashKill(tp->proptab, OBJHASHSIZE);
FREE(tp->proptab);
}
HashKill(&(tp->objdict));
HashKill(&(tp->instdict));
RecurseHashTable(&(tp->propdict), freeprop);
HashKill(&(tp->propdict));
FreeNodeNames(tp);
ob = tp->cell;
while (ob != NULL) {
@ -548,8 +528,8 @@ void PrintCellHashTable(int full, int filenum)
TopFile = filenum;
bins = RecurseHashTable(cell_hashtab, CELLHASHSIZE, CountHashTableBinsUsed);
total = RecurseHashTable(cell_hashtab, CELLHASHSIZE, CountHashTableEntries);
bins = RecurseHashTable(&cell_dict, CountHashTableBinsUsed);
total = RecurseHashTable(&cell_dict, CountHashTableEntries);
if (full != 2)
Printf("Hash table: %d of %d bins used; %d cells total (%.2f per bin)\n",
bins, CELLHASHSIZE, total, (bins == 0) ? 0 :
@ -557,7 +537,7 @@ void PrintCellHashTable(int full, int filenum)
OldDebug = Debug;
Debug = full;
RecurseHashTable(cell_hashtab, CELLHASHSIZE, PrintCellHashTableElement);
RecurseHashTable(&cell_dict, PrintCellHashTableElement);
Debug = OldDebug;
#ifndef TCL_NETGEN
if (full == 2) Printf("\n");
@ -566,12 +546,12 @@ void PrintCellHashTable(int full, int filenum)
struct nlist *FirstCell(void)
{
return((struct nlist *)HashFirst(cell_hashtab, CELLHASHSIZE));
return((struct nlist *)HashFirst(&cell_dict));
}
struct nlist *NextCell(void)
{
return((struct nlist *)HashNext(cell_hashtab, CELLHASHSIZE));
return((struct nlist *)HashNext(&cell_dict));
}
static int ClearDumpedElement(struct hashlist *np)
@ -585,17 +565,17 @@ static int ClearDumpedElement(struct hashlist *np)
void ClearDumpedList(void)
{
RecurseHashTable(cell_hashtab, CELLHASHSIZE, ClearDumpedElement);
RecurseHashTable(&cell_dict, ClearDumpedElement);
}
int RecurseCellHashTable(int (*foo)(struct hashlist *np))
{
return RecurseHashTable(cell_hashtab, CELLHASHSIZE, foo);
return RecurseHashTable(&cell_dict, foo);
}
int RecurseCellFileHashTable(int (*foo)(struct hashlist *, int), int value)
{
return RecurseHashTableValue(cell_hashtab, CELLHASHSIZE, foo, value);
return RecurseHashTableValue(&cell_dict, foo, value);
}
/* Yet another version, passing one parameter that is a pointer */
@ -603,7 +583,7 @@ int RecurseCellFileHashTable(int (*foo)(struct hashlist *, int), int value)
struct nlist *RecurseCellHashTable2(struct nlist *(*foo)(struct hashlist *,
void *), void *pointer)
{
return RecurseHashTablePointer(cell_hashtab, CELLHASHSIZE, foo, pointer);
return RecurseHashTablePointer(&cell_dict, foo, pointer);
}
/************************** WILD-CARD STUFF *******************************/
@ -914,13 +894,13 @@ struct objlist *CopyObjList(struct objlist *oldlist)
struct objlist *LookupObject(char *name, struct nlist *WhichCell)
{
return((struct objlist *)HashLookup(name, WhichCell->objtab, OBJHASHSIZE));
return((struct objlist *)HashLookup(name, &(WhichCell->objdict)));
}
struct objlist *LookupInstance(char *name, struct nlist *WhichCell)
/* searches for exact match of instance 'name' in cell 'WhichCell' */
{
return((struct objlist *)HashLookup(name, WhichCell->insttab, OBJHASHSIZE));
return((struct objlist *)HashLookup(name, &(WhichCell->instdict)));
}
@ -939,7 +919,7 @@ void AddToCurrentCell(struct objlist *ob)
/* add to object hash table for this cell */
if (CurrentCell != NULL) {
HashPtrInstall(ob->name, ob, CurrentCell->objtab, OBJHASHSIZE);
HashPtrInstall(ob->name, ob, &(CurrentCell->objdict));
}
}
@ -966,13 +946,13 @@ void AddToCurrentCellNoHash(struct objlist *ob)
void AddInstanceToCurrentCell(struct objlist *ob)
{
/* add to instance hash table for this cell */
HashPtrInstall(ob->instance.name, ob, CurrentCell->insttab, OBJHASHSIZE);
HashPtrInstall(ob->instance.name, ob, &(CurrentCell->instdict));
}
void FreeObject(struct objlist *ob)
{
/* This just frees the object record. Beware of pointer left */
/* in the objtab hash table. Hash table records should be */
/* in the objlist hash table. Hash table records should be */
/* removed first. */
if (ob->name != NULL) FreeString(ob->name);
@ -1013,7 +993,7 @@ void FreeObject(struct objlist *ob)
void FreeObjectAndHash(struct objlist *ob, struct nlist *ptr)
{
HashDelete(ob->name, ptr->objtab, OBJHASHSIZE);
HashDelete(ob->name, &(ptr->objdict));
FreeObject(ob);
}

View File

@ -3,6 +3,10 @@
#ifndef _OBJLIST_H
#define _OBJLIST_H
#ifndef _HASH_H
#include "hash.h"
#endif
#define SEPARATOR "/"
#define INSTANCE_DELIMITER "#"
#define PORT_DELIMITER "."
@ -99,10 +103,22 @@ struct valuelist {
/* Part 3: Keys & Defaults (kept in the cell record as a hash table) */
#define MERGE_NONE 0 /* Property does not change when devices merge */
#define MERGE_ADD 1 /* Properties sum with device merge */
#define MERGE_ADD_CRIT 2 /* Properties sum with device merge */
#define MERGE_PAR 3 /* Properties add in parallel with device merge */
#define MERGE_PAR_CRIT 4 /* Properties add in parallel with device merge */
/* Note: A "critical" merge means that the property causes the number of */
/* devices to change. e.g., transistor width is critical; transistor drain */
/* area sums when devices are merged, but does not change the number of devices.*/
/* More than one property can be critical. e.g., width and number of fingers. */
struct property {
char *key; /* name of the property */
unsigned char idx; /* index into valuelist */
unsigned char type; /* string, integer, double, value, expression */
unsigned char merge; /* how property changes when devices are merged */
union {
char *string;
double dval;
@ -172,9 +188,9 @@ struct nlist {
unsigned long classhash; /* randomized hash value for cell class */
struct Permutation *permutes; /* list of permuting pins */
struct objlist *cell;
struct hashlist **objtab; /* hash table of object names */
struct hashlist **insttab; /* hash table of instance names */
struct hashlist **proptab; /* hash table of property keys */
struct hashdict objdict; /* hash table of object names */
struct hashdict instdict; /* hash table of instance names */
struct hashdict propdict; /* hash table of property keys */
struct objlist **nodename_cache;
long nodename_cache_maxnodenum; /* largest node number in cache */
void *embedding; /* this will be cast to the appropriate data structure */

View File

@ -40,7 +40,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "print.h"
// Global storage for parameters from .PARAM
struct hashlist **spiceparams;
struct hashdict spiceparams;
void SpiceSubCell(struct nlist *tp, int IsSubCell)
{
@ -358,6 +358,12 @@ int renamepins(struct hashlist *p, int file)
obp = ob;
for (ob2 = tc->cell; ob2 != NULL; ob2 = ob2->next) {
if (ob2->type != PORT) break;
else if ((obp->type < FIRSTPIN) || (obp->type == FIRSTPIN && obp != ob)) {
Fprintf(stderr, "Pin count mismatch between cell and instance of %s\n",
tc->name);
InputParseError(stderr);
break;
}
if (!matchnocase(ob2->name, obp->name + strlen(obp->instance.name) + 1)) {
// Printf("Cell %s pin correspondence: %s vs. %s\n",
// tc->name, obp->name, ob2->name);
@ -778,7 +784,7 @@ skip_ends:
kl->type = PROP_STRING;
kl->slop.ival = 0;
kl->pdefault.string = strsave(eqptr + 1);
HashPtrInstall(nexttok, kl, spiceparams, OBJHASHSIZE);
HashPtrInstall(nexttok, kl, &spiceparams);
}
}
}
@ -1844,8 +1850,7 @@ char *ReadSpiceTop(char *fname, int *fnum, int blackbox)
matchintfunc = matchfilenocase;
hashfunc = hashnocase;
spiceparams = (struct hashlist **)CALLOC(OBJHASHSIZE,
sizeof(struct hashlist *));
InitializeHashTable(&spiceparams, OBJHASHSIZE);
/* All spice files should start with a comment line, */
/* but we won't depend upon it. Any comment line */
@ -1857,10 +1862,8 @@ char *ReadSpiceTop(char *fname, int *fnum, int blackbox)
// Cleanup
while (CellStack != NULL) PopStack(&CellStack);
RecurseHashTable(spiceparams, OBJHASHSIZE, freeprop);
HashKill(spiceparams, OBJHASHSIZE);
FREE(spiceparams);
spiceparams = NULL;
RecurseHashTable(&spiceparams, freeprop);
HashKill(&spiceparams);
// Important: If the file is a library, containing subcircuit
// definitions but no components, then it needs to be registered

View File

@ -36,7 +36,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#define XILINXHASHSIZE 99
static long xilinxhashbase = 0xA00;
static struct hashlist *xilinxnametab[XILINXHASHSIZE];
static struct hashdict xilinxnamedict;
static FILE *xilinxfile;
char *gndnet = "0";
@ -156,7 +156,7 @@ Xilinx(cellname, filename)
return;
}
ClearDumpedList();
InitializeHashTable(xilinxnametab, XILINXHASHSIZE);
InitializeHashTable(&xilinxnamedict, XILINXHASHSIZE);
if (LookupCell(cellname) != NULL)
xilinxCell(cellname);
CloseFile(FileName);

View File

@ -65,7 +65,7 @@ CPP = gcc -E -x c
CXX = @CXX@
CPPFLAGS = -I. -I${NETGENDIR}
DFLAGS = -DCAD_DIR=\"${LIBDIR}\" -DTCL_DIR=\"${TCLDIR}\" -DPACKAGE_NAME=\"netgen\" -DPACKAGE_TARNAME=\"netgen\" -DPACKAGE_VERSION=\"1.3\" -DPACKAGE_STRING=\"netgen\ 1.3\" -DPACKAGE_BUGREPORT=\"eda-dev@opencircuitdesign.com\" -DPACKAGE_URL=\"\" -DNETGEN_VERSION=\"1.5\" -DNETGEN_REVISION=\"50\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DSIZEOF_VOID_P=8 -DSIZEOF_UNSIGNED_INT=4 -DSIZEOF_UNSIGNED_LONG=8 -DSIZEOF_UNSIGNED_LONG_LONG=8 -DSTDC_HEADERS=1 -DHAVE_SETENV=1 -DHAVE_PUTENV=1 -DHAVE_DIRENT_H=1 -DHAVE_LIMITS_H=1 -DHAVE_VA_COPY=1 -DHAVE___VA_COPY=1 -DDBUG_OFF=1 -DTCL_NETGEN=1 -Dlinux=1 -DSYSV=1 -DISC=1 -DSHDLIB_EXT=\".so\" -DNDEBUG
DFLAGS = -DCAD_DIR=\"${LIBDIR}\" -DTCL_DIR=\"${TCLDIR}\" -DPACKAGE_NAME=\"netgen\" -DPACKAGE_TARNAME=\"netgen\" -DPACKAGE_VERSION=\"1.3\" -DPACKAGE_STRING=\"netgen\ 1.3\" -DPACKAGE_BUGREPORT=\"eda-dev@opencircuitdesign.com\" -DPACKAGE_URL=\"\" -DNETGEN_VERSION=\"1.5\" -DNETGEN_REVISION=\"54\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DSIZEOF_VOID_P=8 -DSIZEOF_UNSIGNED_INT=4 -DSIZEOF_UNSIGNED_LONG=8 -DSIZEOF_UNSIGNED_LONG_LONG=8 -DSTDC_HEADERS=1 -DHAVE_SETENV=1 -DHAVE_PUTENV=1 -DHAVE_DIRENT_H=1 -DHAVE_LIMITS_H=1 -DHAVE_VA_COPY=1 -DHAVE___VA_COPY=1 -DDBUG_OFF=1 -DTCL_NETGEN=1 -Dlinux=1 -DSYSV=1 -DISC=1 -DSHDLIB_EXT=\".so\" -DNDEBUG
CFLAGS = -g -m64 -fPIC -fPIC
DEPEND_FILE = Depend

View File

@ -33,6 +33,7 @@ PATH: /sbin
PATH: /usr/bin
PATH: /usr/sbin
PATH: /usr/local/bin
PATH: /home/tim/src/timberwolf-6.3/bin
## ----------- ##
@ -125,7 +126,7 @@ configure: failed program was:
| #define PACKAGE_BUGREPORT "eda-dev@opencircuitdesign.com"
| #define PACKAGE_URL ""
| #define NETGEN_VERSION "1.5"
| #define NETGEN_REVISION "50"
| #define NETGEN_REVISION "54"
| /* end confdefs.h. */
| #include <ac_nonexistent.h>
configure:3382: result: gcc -E
@ -146,7 +147,7 @@ configure: failed program was:
| #define PACKAGE_BUGREPORT "eda-dev@opencircuitdesign.com"
| #define PACKAGE_URL ""
| #define NETGEN_VERSION "1.5"
| #define NETGEN_REVISION "50"
| #define NETGEN_REVISION "54"
| /* end confdefs.h. */
| #include <ac_nonexistent.h>
configure:3445: checking for library containing strerror
@ -261,7 +262,7 @@ configure: failed program was:
| #define PACKAGE_BUGREPORT "eda-dev@opencircuitdesign.com"
| #define PACKAGE_URL ""
| #define NETGEN_VERSION "1.5"
| #define NETGEN_REVISION "50"
| #define NETGEN_REVISION "54"
| #define STDC_HEADERS 1
| #define HAVE_SYS_TYPES_H 1
| #define HAVE_SYS_STAT_H 1
@ -302,7 +303,7 @@ configure: failed program was:
| #define PACKAGE_BUGREPORT "eda-dev@opencircuitdesign.com"
| #define PACKAGE_URL ""
| #define NETGEN_VERSION "1.5"
| #define NETGEN_REVISION "50"
| #define NETGEN_REVISION "54"
| #define STDC_HEADERS 1
| #define HAVE_SYS_TYPES_H 1
| #define HAVE_SYS_STAT_H 1
@ -382,7 +383,7 @@ configure: failed program was:
| #define PACKAGE_BUGREPORT "eda-dev@opencircuitdesign.com"
| #define PACKAGE_URL ""
| #define NETGEN_VERSION "1.5"
| #define NETGEN_REVISION "50"
| #define NETGEN_REVISION "54"
| #define STDC_HEADERS 1
| #define HAVE_SYS_TYPES_H 1
| #define HAVE_SYS_STAT_H 1
@ -454,7 +455,7 @@ configure: failed program was:
| #define PACKAGE_BUGREPORT "eda-dev@opencircuitdesign.com"
| #define PACKAGE_URL ""
| #define NETGEN_VERSION "1.5"
| #define NETGEN_REVISION "50"
| #define NETGEN_REVISION "54"
| #define STDC_HEADERS 1
| #define HAVE_SYS_TYPES_H 1
| #define HAVE_SYS_STAT_H 1
@ -621,7 +622,7 @@ CC='gcc'
CFLAGS='-g -m64 -fPIC'
CPP='gcc -E -x c'
CPPFLAGS=''
DEFS='-DPACKAGE_NAME=\"netgen\" -DPACKAGE_TARNAME=\"netgen\" -DPACKAGE_VERSION=\"1.3\" -DPACKAGE_STRING=\"netgen\ 1.3\" -DPACKAGE_BUGREPORT=\"eda-dev@opencircuitdesign.com\" -DPACKAGE_URL=\"\" -DNETGEN_VERSION=\"1.5\" -DNETGEN_REVISION=\"50\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DSIZEOF_VOID_P=8 -DSIZEOF_UNSIGNED_INT=4 -DSIZEOF_UNSIGNED_LONG=8 -DSIZEOF_UNSIGNED_LONG_LONG=8 -DSTDC_HEADERS=1 -DHAVE_SETENV=1 -DHAVE_PUTENV=1 -DHAVE_DIRENT_H=1 -DHAVE_LIMITS_H=1 -DHAVE_VA_COPY=1 -DHAVE___VA_COPY=1 -DDBUG_OFF=1 -DTCL_NETGEN=1 -Dlinux=1 -DSYSV=1 -DISC=1'
DEFS='-DPACKAGE_NAME=\"netgen\" -DPACKAGE_TARNAME=\"netgen\" -DPACKAGE_VERSION=\"1.3\" -DPACKAGE_STRING=\"netgen\ 1.3\" -DPACKAGE_BUGREPORT=\"eda-dev@opencircuitdesign.com\" -DPACKAGE_URL=\"\" -DNETGEN_VERSION=\"1.5\" -DNETGEN_REVISION=\"54\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DSIZEOF_VOID_P=8 -DSIZEOF_UNSIGNED_INT=4 -DSIZEOF_UNSIGNED_LONG=8 -DSIZEOF_UNSIGNED_LONG_LONG=8 -DSTDC_HEADERS=1 -DHAVE_SETENV=1 -DHAVE_PUTENV=1 -DHAVE_DIRENT_H=1 -DHAVE_LIMITS_H=1 -DHAVE_VA_COPY=1 -DHAVE___VA_COPY=1 -DDBUG_OFF=1 -DTCL_NETGEN=1 -Dlinux=1 -DSYSV=1 -DISC=1'
DEPEND_FLAG='-MM'
ECHO_C=''
ECHO_N='printf'
@ -734,7 +735,7 @@ unused=''
#define PACKAGE_BUGREPORT "eda-dev@opencircuitdesign.com"
#define PACKAGE_URL ""
#define NETGEN_VERSION "1.5"
#define NETGEN_REVISION "50"
#define NETGEN_REVISION "54"
#define STDC_HEADERS 1
#define HAVE_SYS_TYPES_H 1
#define HAVE_SYS_STAT_H 1

View File

@ -657,7 +657,7 @@ S["ECHO_T"]=""
S["ECHO_N"]="-n"
S["ECHO_C"]=""
S["DEFS"]="-DPACKAGE_NAME=\\\"netgen\\\" -DPACKAGE_TARNAME=\\\"netgen\\\" -DPACKAGE_VERSION=\\\"1.3\\\" -DPACKAGE_STRING=\\\"netgen\\ 1.3\\\" -DPACKAGE_BUGREPORT=\\\"eda-dev@open"\
"circuitdesign.com\\\" -DPACKAGE_URL=\\\"\\\" -DNETGEN_VERSION=\\\"1.5\\\" -DNETGEN_REVISION=\\\"50\\\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -"\
"circuitdesign.com\\\" -DPACKAGE_URL=\\\"\\\" -DNETGEN_VERSION=\\\"1.5\\\" -DNETGEN_REVISION=\\\"54\\\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -"\
"DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DSIZEOF_VOID_P=8 -D"\
"SIZEOF_UNSIGNED_INT=4 -DSIZEOF_UNSIGNED_LONG=8 -DSIZEOF_UNSIGNED_LONG_LONG=8 -DSTDC_HEADERS=1 -DHAVE_SETENV=1 -DHAVE_PUTENV=1 -DHAVE_DIRENT_H=1 -DHA"\
"VE_LIMITS_H=1 -DHAVE_VA_COPY=1 -DHAVE___VA_COPY=1 -DDBUG_OFF=1 -DTCL_NETGEN=1 -Dlinux=1 -DSYSV=1 -DISC=1"

View File

@ -65,7 +65,7 @@ CPP = gcc -E -x c
CXX = @CXX@
CPPFLAGS = -I. -I${NETGENDIR}
DFLAGS = -DCAD_DIR=\"${LIBDIR}\" -DTCL_DIR=\"${TCLDIR}\" -DPACKAGE_NAME=\"netgen\" -DPACKAGE_TARNAME=\"netgen\" -DPACKAGE_VERSION=\"1.3\" -DPACKAGE_STRING=\"netgen\ 1.3\" -DPACKAGE_BUGREPORT=\"eda-dev@opencircuitdesign.com\" -DPACKAGE_URL=\"\" -DNETGEN_VERSION=\"1.5\" -DNETGEN_REVISION=\"50\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DSIZEOF_VOID_P=8 -DSIZEOF_UNSIGNED_INT=4 -DSIZEOF_UNSIGNED_LONG=8 -DSIZEOF_UNSIGNED_LONG_LONG=8 -DSTDC_HEADERS=1 -DHAVE_SETENV=1 -DHAVE_PUTENV=1 -DHAVE_DIRENT_H=1 -DHAVE_LIMITS_H=1 -DHAVE_VA_COPY=1 -DHAVE___VA_COPY=1 -DDBUG_OFF=1 -DTCL_NETGEN=1 -Dlinux=1 -DSYSV=1 -DISC=1 -DSHDLIB_EXT=\".so\" -DNDEBUG
DFLAGS = -DCAD_DIR=\"${LIBDIR}\" -DTCL_DIR=\"${TCLDIR}\" -DPACKAGE_NAME=\"netgen\" -DPACKAGE_TARNAME=\"netgen\" -DPACKAGE_VERSION=\"1.3\" -DPACKAGE_STRING=\"netgen\ 1.3\" -DPACKAGE_BUGREPORT=\"eda-dev@opencircuitdesign.com\" -DPACKAGE_URL=\"\" -DNETGEN_VERSION=\"1.5\" -DNETGEN_REVISION=\"54\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DSIZEOF_VOID_P=8 -DSIZEOF_UNSIGNED_INT=4 -DSIZEOF_UNSIGNED_LONG=8 -DSIZEOF_UNSIGNED_LONG_LONG=8 -DSTDC_HEADERS=1 -DHAVE_SETENV=1 -DHAVE_PUTENV=1 -DHAVE_DIRENT_H=1 -DHAVE_LIMITS_H=1 -DHAVE_VA_COPY=1 -DHAVE___VA_COPY=1 -DDBUG_OFF=1 -DTCL_NETGEN=1 -Dlinux=1 -DSYSV=1 -DISC=1 -DSHDLIB_EXT=\".so\" -DNDEBUG
CFLAGS = -g -m64 -fPIC -fPIC
DEPEND_FILE = Depend

View File

@ -2970,6 +2970,7 @@ _netcmp_equate(ClientData clientData,
/* add --- add new property */
/* remove --- delete existing property */
/* tolerance --- set property tolerance */
/* merge --- set property merge behavior */
/* Formerly: (none) */
/* Results: */
/* Side Effects: */
@ -2987,10 +2988,10 @@ _netcmp_property(ClientData clientData,
int ival, argstart;
char *options[] = {
"add", "create", "remove", "delete", "tolerance", NULL
"add", "create", "remove", "delete", "tolerance", "merge", NULL
};
enum OptionIdx {
ADD_IDX, CREATE_IDX, REMOVE_IDX, DELETE_IDX, TOLERANCE_IDX
ADD_IDX, CREATE_IDX, REMOVE_IDX, DELETE_IDX, TOLERANCE_IDX, MERGE_IDX
};
int result, index, idx2;
@ -3001,6 +3002,13 @@ _netcmp_property(ClientData clientData,
INTEGER_IDX, DOUBLE_IDX, VALUE_IDX, STRING_IDX
};
char *mergeoptions[] = {
"none", "add", "add_critical", "par", "par_critical", NULL
};
enum MergeOptionIdx {
NONE_IDX, ADD_ONLY_IDX, ADD_CRIT_IDX, PAR_ONLY_IDX, PAR_CRIT_IDX
};
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "valid_cellname ?option?");
return TCL_ERROR;
@ -3012,7 +3020,7 @@ _netcmp_property(ClientData clientData,
/* Print all properties of the cell as key/type/tolerance triplets */
tobj1 = Tcl_NewListObj(0, NULL);
kl = (struct property *)HashFirst(tp->proptab, OBJHASHSIZE);
kl = (struct property *)HashFirst(&(tp->propdict));
while (kl != NULL) {
tobj2 = Tcl_NewListObj(0, NULL);
@ -3039,7 +3047,7 @@ _netcmp_property(ClientData clientData,
Tcl_ListObjAppendElement(interp, tobj1, tobj2);
kl = (struct property *)HashNext(tp->proptab, OBJHASHSIZE);
kl = (struct property *)HashNext(&(tp->propdict));
}
Tcl_SetObjResult(interp, tobj1);
}
@ -3175,11 +3183,9 @@ _netcmp_property(ClientData clientData,
if (objc == 3) {
/* "remove" without additional arguments means */
/* delete all properties. */
RecurseHashTable(tp->proptab, OBJHASHSIZE, freeprop);
HashKill(tp->proptab, OBJHASHSIZE);
FREE(tp->proptab);
tp->proptab = (struct hashlist **)CALLOC(OBJHASHSIZE,
sizeof(struct hashlist *));
RecurseHashTable(&(tp->propdict), freeprop);
HashKill(&(tp->propdict));
InitializeHashTable(&(tp->propdict), OBJHASHSIZE);
}
else {
for (i = 3; i < objc; i++)
@ -3221,6 +3227,53 @@ _netcmp_property(ClientData clientData,
}
}
break;
case MERGE_IDX:
if (objc == 3) {
Tcl_WrongNumArgs(interp, 1, objv, "{property_key merge_type} ...");
return TCL_ERROR;
}
for (i = 3; i < objc; i++) {
// Each value must be a duplet
result = Tcl_ListObjLength(interp, objv[i], &llen);
if ((result != TCL_OK) || (llen != 2)) {
Tcl_SetResult(interp, "Not a {key merge_type} pair list.",
NULL);
}
else {
int mergeval;
result = Tcl_ListObjIndex(interp, objv[i], 0, &tobj1);
if (result != TCL_OK) return result;
result = Tcl_ListObjIndex(interp, objv[i], 1, &tobj2);
if (result != TCL_OK) return result;
result = Tcl_GetIndexFromObj(interp, tobj2,
(CONST84 char **)mergeoptions,
"merge_type", 0, &idx2);
if (result != TCL_OK) return result;
switch (idx2) {
case NONE_IDX:
mergeval = MERGE_NONE;
break;
case ADD_ONLY_IDX:
mergeval = MERGE_ADD;
break;
case ADD_CRIT_IDX:
mergeval = MERGE_ADD_CRIT;
break;
case PAR_ONLY_IDX:
mergeval = MERGE_PAR;
break;
case PAR_CRIT_IDX:
mergeval = MERGE_PAR_CRIT;
break;
}
PropertyMerge(tp->name, fnum, Tcl_GetString(tobj1), mergeval);
}
}
break;
}
}
return TCL_OK;