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 #define ACTELHASHSIZE 99
static long actelhashbase = 0xA00; static long actelhashbase = 0xA00;
static struct hashlist *actelnametab[ACTELHASHSIZE]; static struct hashdict actelnamedict;
static FILE *actelfile; static FILE *actelfile;
char *ActelName(char *Name); char *ActelName(char *Name);
@ -53,16 +53,16 @@ void PrintActelNames(char *filename)
{ {
if (filename == NULL) actelfile = stdout; if (filename == NULL) actelfile = stdout;
else actelfile = fopen(filename,"w"); else actelfile = fopen(filename,"w");
RecurseHashTable(actelnametab, ACTELHASHSIZE, PrintActelName); RecurseHashTable(&actelnamedict, PrintActelName);
if (actelfile != stdout) fclose(actelfile); if (actelfile != stdout) fclose(actelfile);
} }
long ActelNameHash(char *name) 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; struct hashlist *p;
p = HashInstall(name, actelnametab, ACTELHASHSIZE); p = HashInstall(name, &actelnamedict);
if (p == NULL) return(0); if (p == NULL) return(0);
if (p->ptr != NULL) return ((long)(p->ptr)); if (p->ptr != NULL) return ((long)(p->ptr));
actelhashbase++; actelhashbase++;
@ -403,7 +403,7 @@ void Actel(char *name, char *filename)
return; return;
} }
ClearDumpedList(); ClearDumpedList();
InitializeHashTable(actelnametab, ACTELHASHSIZE); InitializeHashTable(&actelnamedict, ACTELHASHSIZE);
if (LookupCell(name) != NULL) if (LookupCell(name) != NULL)
actelCell(name); actelCell(name);
CloseFile(FileName); CloseFile(FileName);

View File

@ -544,10 +544,10 @@ void simCell(char *name, int filenum)
if (ob2 && ob2->type == PROPERTY) { if (ob2 && ob2->type == PROPERTY) {
struct property *kl; struct property *kl;
struct valuelist *vl; struct valuelist *vl;
kl = (struct property *)HashLookup("length", tp2->proptab, OBJHASHSIZE); kl = (struct property *)HashLookup("length", &(tp2->propdict));
vl = (struct valuelist *)ob2->instance.name; vl = (struct valuelist *)ob2->instance.name;
l = 1.0e6 * vl[kl->idx].value.dval; /* m -> um */ 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 */ w = 1.0e6 * vl[kl->idx].value.dval; /* m -> um */
} }
FlushString(" %g %g\n", l, w); FlushString(" %g %g\n", l, w);
@ -579,7 +579,7 @@ void simCell(char *name, int filenum)
if (ob2 && ob2->type == PROPERTY) { if (ob2 && ob2->type == PROPERTY) {
struct property *kl; struct property *kl;
struct valuelist *vl; struct valuelist *vl;
kl = (struct property *)HashLookup("value", tp2->proptab, OBJHASHSIZE); kl = (struct property *)HashLookup("value", &(tp2->propdict));
vl = (struct valuelist *)ob2->instance.name; vl = (struct valuelist *)ob2->instance.name;
if (tp2->class == CLASS_CAP) if (tp2->class == CLASS_CAP)
v = 1.0e15 * vl[kl->idx].value.dval; /* F -> fF */ 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; continue;
} }
@ -198,9 +198,9 @@ void flattenCell(char *name, int file)
#endif #endif
FreeString(tmp->instance.name); FreeString(tmp->instance.name);
tmp->instance.name = strsave(tmpstr); tmp->instance.name = strsave(tmpstr);
HashPtrInstall(tmp->name, tmp, ThisCell->objtab, OBJHASHSIZE); HashPtrInstall(tmp->name, tmp, &(ThisCell->objdict));
if (tmp->type == FIRSTPIN) if (tmp->type == FIRSTPIN)
HashPtrInstall(tmp->instance.name, tmp, ThisCell->insttab, OBJHASHSIZE); HashPtrInstall(tmp->instance.name, tmp, &(ThisCell->instdict));
} }
/* splice instance out of parent */ /* 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 // Don't hash this if the parent had a port of this name
if (!ob2 || ob2->type != PORT) if (!ob2 || ob2->type != PORT)
HashPtrInstall(tmp->name, tmp, ThisCell->objtab, OBJHASHSIZE); HashPtrInstall(tmp->name, tmp, &(ThisCell->objdict));
continue; continue;
} }
@ -461,9 +461,9 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
#endif #endif
FreeString(tmp->instance.name); FreeString(tmp->instance.name);
tmp->instance.name = strsave(tmpstr); tmp->instance.name = strsave(tmpstr);
HashPtrInstall(tmp->name, tmp, ThisCell->objtab, OBJHASHSIZE); HashPtrInstall(tmp->name, tmp, &(ThisCell->objdict));
if (tmp->type == FIRSTPIN) if (tmp->type == FIRSTPIN)
HashPtrInstall(tmp->instance.name, tmp, ThisCell->insttab, OBJHASHSIZE); HashPtrInstall(tmp->instance.name, tmp, &(ThisCell->instdict));
} }
/* do property inheritance */ /* do property inheritance */
@ -704,7 +704,7 @@ void convertGlobalsOf(char *name, int fnum, char *instance)
newnode->instance.name = NULL; newnode->instance.name = NULL;
newnode->model.class = NULL; newnode->model.class = NULL;
newpin->node = maxnode; 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 // 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, // 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. // 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); CacheNodeNames(ThisCell);
@ -840,7 +840,7 @@ void ConvertGlobals(char *name, int filenum)
strsave(ObjList->instance.name) : NULL; strsave(ObjList->instance.name) : NULL;
NewObj->name = (ObjList->name) ? strsave(ObjList->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 */ /* 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 */ /* 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; modified = 1;
// Check if the node we're about to remove is in the // 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. // that we are going to keep.
if (LookupObject(ob->name, ptr) == ob) { if (LookupObject(ob->name, ptr) == ob) {
HashPtrInstall(ob->name, saveob, ptr->objtab, OBJHASHSIZE); HashPtrInstall(ob->name, saveob, &(ptr->objdict));
} }
} }
tob = tob->next; 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 // Renumber the pins in order. Since when removing duplicates, the
// first entry is always kept, the first pin is never changed, so // 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; i = FIRSTPIN;
firstpin->type = i++; firstpin->type = i++;
@ -1093,8 +1093,7 @@ int UniquePins(char *name, int filenum)
// The hash table is pointing at the cell we are // The hash table is pointing at the cell we are
// about to delete. Hash the one we're keeping instead. // about to delete. Hash the one we're keeping instead.
HashPtrInstall(ob->name, firstport[ob->node], HashPtrInstall(ob->name, firstport[ob->node], &(ThisCell->objdict));
ThisCell->objtab, OBJHASHSIZE);
} }
if (lob == NULL) { if (lob == NULL) {
@ -1131,7 +1130,7 @@ int UniquePins(char *name, int filenum)
/* Callback function for CleanupPins */ /* Callback function for CleanupPins */
/* Note that if the first pin of the instance is a */ /* Note that if the first pin of the instance is a */
/* disconnected node, then removing it invalidates the */ /* disconnected node, then removing it invalidates the */
/* insttab hash. */ /* instdict hash. */
/*------------------------------------------------------*/ /*------------------------------------------------------*/
struct nlist *cleanuppins(struct hashlist *p, void *clientdata) 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 // Check if the node we're about to remove is in the
// objtab hash table // objdict hash table
if (LookupObject(ob->name, ptr) == ob) { if (LookupObject(ob->name, ptr) == ob) {
HashDelete(ob->name, ptr->objtab, OBJHASHSIZE); HashDelete(ob->name, &(ptr->objdict));
} }
FREE(ob->name); FREE(ob->name);
@ -1199,10 +1198,9 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
obt = obt->next; 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)) if (firstpin && (firstpin->type == FIRSTPIN))
HashPtrInstall(firstpin->instance.name, firstpin, ptr->insttab, HashPtrInstall(firstpin->instance.name, firstpin, &(ptr->instdict));
OBJHASHSIZE);
} }
} }
return NULL; /* Keep the search going */ 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 // Check if the node we're about to remove is in the
// objtab hash table // objdict hash table
if (LookupObject(ob->name, ThisCell) == ob) { if (LookupObject(ob->name, ThisCell) == ob) {
HashDelete(ob->name, ThisCell->objtab, OBJHASHSIZE); HashDelete(ob->name, &(ThisCell->objdict));
} }
FREE(ob->name); FREE(ob->name);
@ -1307,11 +1305,151 @@ typedef struct ecomplist {
} 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 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 objlist *ob;
struct nlist *tsub, *teq; struct nlist *tsub, *teq;
@ -1331,8 +1469,7 @@ SurveyCell(struct nlist *tc, struct hashlist **comptab, int file1, int file2, in
else dstr = NULL; else dstr = NULL;
teq = LookupClassEquivalent(ob->model.class, file, ofile); teq = LookupClassEquivalent(ob->model.class, file, ofile);
ecomp = (ECompare *)HashInt2Lookup(ob->model.class, file, ecomp = (ECompare *)HashInt2Lookup(ob->model.class, file, compdict);
comptab, OBJHASHSIZE);
if (ecomp == NULL) { if (ecomp == NULL) {
ncomp = (ECompare *)MALLOC(sizeof(ECompare)); 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->add2 = 0;
ncomp->refcount = (char)1; ncomp->refcount = (char)1;
HashInt2PtrInstall(ob->model.class, file, ncomp, comptab, HashInt2PtrInstall(ob->model.class, file, ncomp, compdict);
OBJHASHSIZE);
if (teq != NULL) { if (teq != NULL) {
char *bstr = NULL; char *bstr = NULL;
if (teq->flags & CELL_DUPLICATE) { if (teq->flags & CELL_DUPLICATE) {
bstr = strstr(teq->name, "[["); bstr = strstr(teq->name, "[[");
if (bstr) *bstr = '\0'; if (bstr) *bstr = '\0';
} }
qcomp = (ECompare *)HashInt2Lookup(teq->name, ofile, qcomp = (ECompare *)HashInt2Lookup(teq->name, ofile, compdict);
comptab, OBJHASHSIZE);
if (qcomp == NULL) { if (qcomp == NULL) {
HashInt2PtrInstall(teq->name, ofile, ncomp, comptab, HashInt2PtrInstall(teq->name, ofile, ncomp, compdict);
OBJHASHSIZE);
ncomp->refcount++; ncomp->refcount++;
} }
if (bstr) *bstr = '['; 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- */ /* If there is a mismatch between instances of low- */
/* level devices, determine if the mismatches can be */ /* level devices, determine if the mismatches can be */
/* resolved by parallel/serial combining, accoring to */ /* resolved by parallel/serial combining, according to */
/* combination rules. */ /* combination rules. */
/* */ /* */
/* Return the number of modifications made. */ /* 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 nlist *tc1, *tc2, *tsub1, *tsub2;
struct objlist *ob1, *ob2, *lob; struct objlist *ob1, *ob2, *lob;
struct hashlist **comptab; struct hashdict compdict;
ECompare *ecomp, *ncomp; ECompare *ecomp, *ncomp;
ECompList *list0X, *listX0; ECompList *list0X, *listX0;
int match, modified = 0; int match, modified = 0;
@ -1421,14 +1555,13 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
if (tc1 == NULL || tc2 == NULL) return; if (tc1 == NULL || tc2 == NULL) return;
comptab = (struct hashlist **)CALLOC(OBJHASHSIZE, InitializeHashTable(&compdict, OBJHASHSIZE);
sizeof(struct hashlist *));
// Gather information about instances of cell "name1" // 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" // 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 // Find all instances of one cell that have fewer in
// the compared circuit. Check whether subcircuits // 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. // or subcircuits that have more in the compared circuit.
listX0 = list0X = NULL; listX0 = list0X = NULL;
ecomp = (ECompare *)HashFirst(comptab, OBJHASHSIZE); ecomp = (ECompare *)HashFirst(&compdict);
while (ecomp != NULL) { while (ecomp != NULL) {
/* Case 1: Both cell1 and cell2 classes are subcircuits, */ /* 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) { for (ob2 = ecomp->cell2->cell; ob2; ob2 = ob2->next) {
if (ob2->type == FIRSTPIN) { if (ob2->type == FIRSTPIN) {
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class, ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
ecomp->cell2->file, comptab, OBJHASHSIZE); ecomp->cell2->file, &compdict);
if (ncomp != NULL) { if (ncomp != NULL) {
if ((ncomp->num1 > ncomp->num2) && if ((ncomp->num1 > ncomp->num2) &&
((ncomp->add2 + ecomp->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) { for (ob2 = ecomp->cell2->cell; ob2; ob2 = ob2->next) {
if (ob2->type == FIRSTPIN) { if (ob2->type == FIRSTPIN) {
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class, ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
ecomp->cell2->file, comptab, ecomp->cell2->file, &compdict);
OBJHASHSIZE);
if (ncomp != NULL) { if (ncomp != NULL) {
if (match) { if (match) {
ncomp->num1 += ncomp->add1; 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) { for (ob2 = ecomp->cell2->cell; ob2; ob2 = ob2->next) {
if (ob2->type == FIRSTPIN) { if (ob2->type == FIRSTPIN) {
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class, ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
ecomp->cell2->file, comptab, OBJHASHSIZE); ecomp->cell2->file, &compdict);
if (ncomp != NULL) { if (ncomp != NULL) {
if ((ncomp->num1 > ncomp->num2) && if ((ncomp->num1 > ncomp->num2) &&
((ncomp->add2 + ecomp->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) { for (ob2 = ecomp->cell2->cell; ob2; ob2 = ob2->next) {
if (ob2->type == FIRSTPIN) { if (ob2->type == FIRSTPIN) {
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class, ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
ecomp->cell2->file, comptab, ecomp->cell2->file, &compdict);
OBJHASHSIZE);
if (ncomp != NULL) { if (ncomp != NULL) {
if (match) { if (match) {
ncomp->num2 += ncomp->add2; 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) { for (ob2 = ecomp->cell1->cell; ob2; ob2 = ob2->next) {
if (ob2->type == FIRSTPIN) { if (ob2->type == FIRSTPIN) {
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class, ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
ecomp->cell1->file, comptab, OBJHASHSIZE); ecomp->cell1->file, &compdict);
if (ncomp != NULL) { if (ncomp != NULL) {
if ((ncomp->num2 > ncomp->num1) && if ((ncomp->num2 > ncomp->num1) &&
((ncomp->add1 + ecomp->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) { for (ob2 = ecomp->cell1->cell; ob2; ob2 = ob2->next) {
if (ob2->type == FIRSTPIN) { if (ob2->type == FIRSTPIN) {
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class, ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
ecomp->cell1->file, comptab, ecomp->cell1->file, &compdict);
OBJHASHSIZE);
if (ncomp != NULL) { if (ncomp != NULL) {
if (match) { if (match) {
ncomp->num1 += ncomp->add1; ncomp->num1 += ncomp->add1;
@ -1656,13 +1786,85 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
} }
ecomp->add1 = 0; 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 // Remove non-matching zero-value devices. This can
// be done on a per-instance basis. // be done on a per-instance basis.
ecomp = (ECompare *)HashFirst(comptab, OBJHASHSIZE); ecomp = (ECompare *)HashFirst(&compdict);
while (ecomp != NULL) { while (ecomp != NULL) {
if ((ecomp->num1 != ecomp->num2) && (ecomp->cell1 != NULL) && if ((ecomp->num1 != ecomp->num2) && (ecomp->cell1 != NULL) &&
(ecomp->cell1->class == CLASS_RES)) { (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 // 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'; if (dstr) *dstr = '\0';
} }
ncomp = (ECompare *)HashInt2Lookup(ob1->model.class, ncomp = (ECompare *)HashInt2Lookup(ob1->model.class,
ecompX0->cell1->file, comptab, OBJHASHSIZE); ecompX0->cell1->file, &compdict);
if (dstr) *dstr = '['; if (dstr) *dstr = '[';
if ((ncomp == ecomp0X) && (ecomp0X->num2 <= ecompX0->num1)) { if ((ncomp == ecomp0X) && (ecomp0X->num2 <= ecompX0->num1)) {
Fprintf(stdout, "Flattening instances of %s in cell %s" 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'; if (dstr) *dstr = '\0';
} }
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class, ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
ecomp0X->cell2->file, comptab, OBJHASHSIZE); ecomp0X->cell2->file, &compdict);
if (dstr) *dstr = '['; if (dstr) *dstr = '[';
if ((ncomp == ecompX0) && (ecompX0->num1 <= ecomp0X->num2)) { if ((ncomp == ecompX0) && (ecompX0->num1 <= ecomp0X->num2)) {
Fprintf(stdout, "Flattening instances of %s in cell %s" 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. // Free the hash table and its contents.
ecomp = (ECompare *)HashFirst(comptab, OBJHASHSIZE); ecomp = (ECompare *)HashFirst(&compdict);
while (ecomp != NULL) { while (ecomp != NULL) {
if (--ecomp->refcount == (char)0) FREE(ecomp); if (--ecomp->refcount == (char)0) FREE(ecomp);
ecomp = (ECompare *)HashNext(comptab, OBJHASHSIZE); ecomp = (ECompare *)HashNext(&compdict);
} }
HashKill(comptab, OBJHASHSIZE); HashKill(&compdict);
FREE(comptab);
// Free the 0:X and X:0 lists // Free the 0:X and X:0 lists
while (listX0 != NULL) { while (listX0 != NULL) {

View File

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

View File

@ -7,38 +7,44 @@ struct hashlist {
struct hashlist *next; struct hashlist *next;
}; };
extern void InitializeHashTable(struct hashlist **tab, int size); struct hashdict {
extern int RecurseHashTable(struct hashlist **hashtab, int hashsize, 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)); 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); int (*func)(struct hashlist *elem, int), int);
extern struct nlist *RecurseHashTablePointer(struct hashlist **hashtab, extern struct nlist *RecurseHashTablePointer(struct hashdict *dict,
int hashsize, struct nlist *(*func)(struct hashlist *elem, struct nlist *(*func)(struct hashlist *elem, void *),
void *), void *pointer); 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 CountHashTableEntries(struct hashlist *p);
extern int CountHashTableBinsUsed(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 */ /* these functions return a pointer to a hash list element */
extern struct hashlist *HashInstall(char *name, struct hashlist **hashtab, extern struct hashlist *HashInstall(char *name, struct hashdict *dict);
int hashsize);
extern struct hashlist *HashPtrInstall(char *name, void *ptr, 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, 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, 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 */ /* these functions return the ->ptr field of a struct hashlist */
extern void *HashLookup(char *s, struct hashlist **hashtab, int hashsize); extern void *HashLookup(char *s, struct hashdict *dict);
extern void *HashIntLookup(char *s, int i, struct hashlist **hashtab, int hashsize); extern void *HashIntLookup(char *s, int i, struct hashdict *dict);
extern void *HashInt2Lookup(char *s, int c, struct hashlist **hashtab, int hashsize); extern void *HashInt2Lookup(char *s, int c, struct hashdict *dict);
extern void *HashFirst(struct hashlist **hashtab, int hashsize); extern void *HashFirst(struct hashdict *dict);
extern void *HashNext(struct hashlist **hashtab, int hashsize); extern void *HashNext(struct hashdict *dict);
extern unsigned long hashnocase(char *s, int hashsize); extern unsigned long hashnocase(char *s, int hashsize);
extern unsigned long hash(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->type == PROP_ENDLIST) break;
if (vl2 == NULL) continue; if (vl2 == NULL) continue;
if (vl2->key == 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 if (kl2 != NULL) break; // Property is required
else if ((*matchfunc)(vl2->key, "M")) { else if ((*matchfunc)(vl2->key, "M")) {
if (vl2->type == PROP_INTEGER) 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->type == PROP_ENDLIST) break;
if (vl1 == NULL) continue; if (vl1 == NULL) continue;
if (vl1->key == 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 if (kl1 != NULL) break; // Property is required
else if ((*matchfunc)(vl1->key, "M")) { else if ((*matchfunc)(vl1->key, "M")) {
if (vl1->type == PROP_INTEGER) 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; if (vl1->key == NULL) continue;
/* Check if this is a "property of interest". */ /* 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; if (kl1 == NULL) continue;
/* Find the matching property in vl2. With luck, they're in order. */ /* 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; if (vl2->key == NULL) continue;
/* Both device classes must agree on the properties to compare */ /* 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; if (kl2 == NULL) continue;
/* Watch out for uninitialized entries in cell def */ /* Watch out for uninitialized entries in cell def */
@ -4488,7 +4488,7 @@ int reorderpins(struct hashlist *p, int file)
ob->node = nodes[i]; ob->node = nodes[i];
ob->name = names[i]; ob->name = names[i];
} }
HashPtrInstall(ob->name, ob, ptr->objtab, OBJHASHSIZE); HashPtrInstall(ob->name, ob, &(ptr->objdict));
ob = ob->next; ob = ob->next;
names[i] = NULL; names[i] = NULL;
} }
@ -4566,12 +4566,11 @@ struct nlist *addproxies(struct hashlist *p, void *clientdata)
lob = obn; lob = obn;
// Hash the new pin record for "LookupObject()" // Hash the new pin record for "LookupObject()"
HashPtrInstall(obn->name, obn, ptr->objtab, OBJHASHSIZE); HashPtrInstall(obn->name, obn, &(ptr->objdict));
if (tob == tc->cell) { if (tob == tc->cell) {
// Rehash the instance in insttab // Rehash the instance in instdict
HashPtrInstall(firstpin->instance.name, firstpin, HashPtrInstall(firstpin->instance.name, firstpin, &(ptr->instdict));
ptr->insttab, OBJHASHSIZE);
} }
} }
else { else {
@ -4595,7 +4594,7 @@ struct nlist *addproxies(struct hashlist *p, void *clientdata)
obn->next = NULL; obn->next = NULL;
lob->next = obn; lob->next = obn;
lob = 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 // 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; ob1 = obn;
hasproxy1 = 1; 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; ob2 = obn;
hasproxy2 = 1; hasproxy2 = 1;
HashPtrInstall(obn->name, obn, tc2->objtab, OBJHASHSIZE); HashPtrInstall(obn->name, obn, &(tc2->objdict));
} }
else if (ob1 != NULL && ob1->type == PORT) { 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 char staticstrings[MAX_STATIC_STRINGS][200];
static int laststring; static int laststring;
extern struct hashlist **spiceparams; /* From spice.c */ extern struct hashdict spiceparams; /* From spice.c */
char *Str(char *format, ...) char *Str(char *format, ...)
{ {
@ -188,18 +188,15 @@ int TokGetValue(char *estr, struct nlist *parent, int glob, double *dval)
if (glob == TRUE) { if (glob == TRUE) {
/* Check global parameters */ /* Check global parameters */
if (spiceparams != NULL) { kl = (struct property *)HashLookup(estr, &spiceparams);
kl = (struct property *)HashLookup(estr, if (kl != NULL) {
spiceparams, OBJHASHSIZE); result = ConvertStringToFloat(kl->pdefault.string, dval);
if (kl != NULL) { return ((result == 0) ? -1 : 1);
result = ConvertStringToFloat(kl->pdefault.string, dval);
return ((result == 0) ? -1 : 1);
}
} }
} }
/* Check local parameters */ /* Check local parameters */
kl = (struct property *)HashLookup(estr, parent->proptab, OBJHASHSIZE); kl = (struct property *)HashLookup(estr, &(parent->propdict));
if (kl != NULL) { if (kl != NULL) {
switch(kl->type) { switch(kl->type) {
case PROP_STRING: case PROP_STRING:
@ -834,19 +831,17 @@ PropertyDelete(char *name, int fnum, char *key)
/* key == NULL means delete all properties. */ /* key == NULL means delete all properties. */
RecurseHashTable(tc->proptab, OBJHASHSIZE, freeprop); RecurseHashTable(&(tc->propdict), freeprop);
HashKill(tc->proptab, OBJHASHSIZE); HashKill(&(tc->propdict));
FREE(tc->proptab); InitializeHashTable(&(tc->propdict), OBJHASHSIZE);
tc->proptab = (struct hashlist **)CALLOC(OBJHASHSIZE,
sizeof(struct hashlist *));
} }
else { else {
kl = (struct property *)HashLookup(key, tc->proptab, OBJHASHSIZE); kl = (struct property *)HashLookup(key, &(tc->propdict));
if (kl != NULL) { if (kl != NULL) {
if (kl->type == PROP_STRING || kl->type == PROP_EXPRESSION) if (kl->type == PROP_STRING || kl->type == PROP_EXPRESSION)
FREE(kl->pdefault.string); FREE(kl->pdefault.string);
FREE(kl->key); FREE(kl->key);
HashDelete(key, tc->proptab, OBJHASHSIZE); HashDelete(key, &(tc->propdict));
} }
else { else {
Printf("No property %s found for device %s\n", key, name); 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; return -1;
} }
kl = (struct property *)HashLookup(key, tc->proptab, OBJHASHSIZE); kl = (struct property *)HashLookup(key, &(tc->propdict));
if (kl == NULL) { if (kl == NULL) {
Printf("No property %s found for device %s\n", key, name); Printf("No property %s found for device %s\n", key, name);
return -1; return -1;
@ -900,6 +895,40 @@ PropertyTolerance(char *name, int fnum, char *key, int ival, double dval)
return 0; 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 */ /* Add a new value property to the indicated cell */
/* Value properties are used for resistors and capacitors in SPICE */ /* 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); tc = LookupCellFile(name, fnum);
if (tc == NULL) if (tc == NULL)
Printf("No device %s found for PropertyValue()\n", name); Printf("No device %s found for PropertyValue()\n", name);
else if ((kl = (struct property *)HashLookup(key, tc->proptab, else if ((kl = (struct property *)HashLookup(key, &(tc->propdict))) != NULL) {
OBJHASHSIZE)) != NULL) {
Printf("Device %s already has property named \"%s\"\n", name, key); Printf("Device %s already has property named \"%s\"\n", name, key);
} }
else { else {
kl = NewProperty(); kl = NewProperty();
kl->key = strsave(key); kl->key = strsave(key);
kl->idx = 0; kl->idx = 0;
kl->merge = MERGE_NONE;
kl->type = PROP_VALUE; kl->type = PROP_VALUE;
kl->slop.dval = slop; kl->slop.dval = slop;
kl->pdefault.dval = pdefault; kl->pdefault.dval = pdefault;
HashPtrInstall(kl->key, kl, tc->proptab, OBJHASHSIZE); HashPtrInstall(kl->key, kl, &(tc->propdict));
} }
return kl; return kl;
} }
@ -958,18 +987,18 @@ struct property *PropertyDouble(char *name, int fnum, char *key,
tc = LookupCellFile(name, fnum); tc = LookupCellFile(name, fnum);
if (tc == NULL) if (tc == NULL)
Printf("No device %s found for PropertyDouble()\n", name); Printf("No device %s found for PropertyDouble()\n", name);
else if ((kl = (struct property *)HashLookup(key, tc->proptab, else if ((kl = (struct property *)HashLookup(key, &(tc->propdict))) != NULL) {
OBJHASHSIZE)) != NULL) {
Printf("Device %s already has property named \"%s\"\n", name, key); Printf("Device %s already has property named \"%s\"\n", name, key);
} }
else { else {
kl = NewProperty(); kl = NewProperty();
kl->key = strsave(key); kl->key = strsave(key);
kl->idx = 0; kl->idx = 0;
kl->merge = MERGE_NONE;
kl->type = PROP_DOUBLE; kl->type = PROP_DOUBLE;
kl->slop.dval = slop; kl->slop.dval = slop;
kl->pdefault.dval = pdefault; kl->pdefault.dval = pdefault;
HashPtrInstall(kl->key, kl, tc->proptab, OBJHASHSIZE); HashPtrInstall(kl->key, kl, &(tc->propdict));
} }
return kl; return kl;
} }
@ -991,18 +1020,18 @@ struct property *PropertyInteger(char *name, int fnum, char *key,
tc = LookupCellFile(name, fnum); tc = LookupCellFile(name, fnum);
if (tc == NULL) if (tc == NULL)
Printf("No device %s found for PropertyInteger()\n", name); Printf("No device %s found for PropertyInteger()\n", name);
else if ((kl = (struct property *)HashLookup(key, tc->proptab, else if ((kl = (struct property *)HashLookup(key, &(tc->propdict))) != NULL) {
OBJHASHSIZE)) != NULL) {
Printf("Device %s already has property named \"%s\"\n", name, key); Printf("Device %s already has property named \"%s\"\n", name, key);
} }
else { else {
kl = NewProperty(); kl = NewProperty();
kl->key = strsave(key); kl->key = strsave(key);
kl->idx = 0; kl->idx = 0;
kl->merge = MERGE_NONE;
kl->type = PROP_INTEGER; kl->type = PROP_INTEGER;
kl->slop.ival = slop; kl->slop.ival = slop;
kl->pdefault.ival = pdefault; kl->pdefault.ival = pdefault;
HashPtrInstall(kl->key, kl, tc->proptab, OBJHASHSIZE); HashPtrInstall(kl->key, kl, &(tc->propdict));
} }
return kl; return kl;
} }
@ -1024,21 +1053,21 @@ struct property *PropertyString(char *name, int fnum, char *key, int range,
tc = LookupCellFile(name, fnum); tc = LookupCellFile(name, fnum);
if (tc == NULL) if (tc == NULL)
Printf("No device %s found for PropertyString()\n", name); Printf("No device %s found for PropertyString()\n", name);
else if ((kl = (struct property *)HashLookup(key, tc->proptab, else if ((kl = (struct property *)HashLookup(key, &(tc->propdict))) != NULL) {
OBJHASHSIZE)) != NULL) {
Printf("Device %s already has property named \"%s\"\n", name, key); Printf("Device %s already has property named \"%s\"\n", name, key);
} }
else { else {
kl = NewProperty(); kl = NewProperty();
kl->key = strsave(key); kl->key = strsave(key);
kl->idx = 0; kl->idx = 0;
kl->merge = MERGE_NONE;
kl->type = PROP_STRING; kl->type = PROP_STRING;
kl->slop.ival = (range >= 0) ? range : 0; kl->slop.ival = (range >= 0) ? range : 0;
if (pdefault != NULL) if (pdefault != NULL)
kl->pdefault.string = strsave(pdefault); kl->pdefault.string = strsave(pdefault);
else else
kl->pdefault.string = NULL; kl->pdefault.string = NULL;
HashPtrInstall(kl->key, kl, tc->proptab, OBJHASHSIZE); HashPtrInstall(kl->key, kl, &(tc->propdict));
} }
return kl; 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 */ /* If there is a matching cell, make sure that the property */
/* key exists. If not, create it and flag a warning. */ /* 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) { if (kl == NULL) {
/* Ideally, for devices, one should check against all */ /* Ideally, for devices, one should check against all */
/* known standard properties. That's a pain, so */ /* known standard properties. That's a pain, so */
@ -1988,10 +2017,11 @@ struct objlist *LinkProperties(char *model, struct keyvalue *topptr)
kl = NewProperty(); kl = NewProperty();
kl->key = strsave(newkv->key); kl->key = strsave(newkv->key);
kl->idx = 0; kl->idx = 0;
kl->merge = MERGE_NONE;
kl->type = PROP_STRING; kl->type = PROP_STRING;
kl->slop.ival = 0; kl->slop.ival = 0;
kl->pdefault.string = NULL; 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++) { for (i = 0;; i++) {
vl = &(ob->instance.props[i]); vl = &(ob->instance.props[i]);
if (vl->type == PROP_ENDLIST) break; 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 */ /* Warning: prop should never be null, but condition */
/* should be handled. */ /* 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 */ /* index. If the property does not exist in the second cell, then */
/* create it. */ /* 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 indexes are not zero, then properties have already been matched. */
if (kl1 == NULL) return; /* Cell has no properties */ if (kl1 == NULL) return; /* Cell has no properties */
if (kl1->idx != 0) return; if (kl1->idx != 0) return;
@ -2247,7 +2277,7 @@ void ResolveProperties(char *name1, int file1, char *name2, int file2)
while (kl1 != NULL) { while (kl1 != NULL) {
kl1->idx = i; kl1->idx = i;
kl2 = (struct property *)HashLookup(kl1->key, tp2->proptab, OBJHASHSIZE); kl2 = (struct property *)HashLookup(kl1->key, &(tp2->propdict));
if (kl2 == NULL) { if (kl2 == NULL) {
/* No such property in tp2 */ /* No such property in tp2 */
switch (kl1->type) { switch (kl1->type) {
@ -2270,16 +2300,16 @@ void ResolveProperties(char *name1, int file1, char *name2, int file2)
} }
} }
if (kl2 != NULL) kl2->idx = i; if (kl2 != NULL) kl2->idx = i;
kl1 = (struct property *)HashNext(tp1->proptab, OBJHASHSIZE); kl1 = (struct property *)HashNext(&(tp1->propdict));
i++; i++;
} }
/* Now check tp2 for properties not in tp1 */ /* Now check tp2 for properties not in tp1 */
kl2 = (struct property *)HashFirst(tp2->proptab, OBJHASHSIZE); kl2 = (struct property *)HashFirst(&(tp2->propdict));
while (kl2 != NULL) { while (kl2 != NULL) {
kl1 = (struct property *)HashLookup(kl2->key, tp1->proptab, OBJHASHSIZE); kl1 = (struct property *)HashLookup(kl2->key, &(tp1->propdict));
if (kl1 == NULL) { if (kl1 == NULL) {
/* No such property in tp1 */ /* No such property in tp1 */
switch (kl2->type) { switch (kl2->type) {
@ -2302,7 +2332,7 @@ void ResolveProperties(char *name1, int file1, char *name2, int file2)
} }
} }
if (kl1 != NULL) kl1->idx = i; if (kl1 != NULL) kl1->idx = i;
kl2 = (struct property *)HashNext(tp1->proptab, OBJHASHSIZE); kl2 = (struct property *)HashNext(&(tp1->propdict));
i++; 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 PropertyDelete(char *name, int fnum, char *key);
extern int PropertyTolerance(char *name, int fnum, char *key, int ival, extern int PropertyTolerance(char *name, int fnum, char *key, int ival,
double dval); 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 ResolveProperties(char *name1, int file1, char *name2, int file2);
extern void CopyProperties(struct objlist *obj_to, struct objlist *obj_from); extern void CopyProperties(struct objlist *obj_to, struct objlist *obj_from);
extern int PromoteProperty(struct property *, struct valuelist *); extern int PromoteProperty(struct property *, struct valuelist *);

View File

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

View File

@ -3,6 +3,10 @@
#ifndef _OBJLIST_H #ifndef _OBJLIST_H
#define _OBJLIST_H #define _OBJLIST_H
#ifndef _HASH_H
#include "hash.h"
#endif
#define SEPARATOR "/" #define SEPARATOR "/"
#define INSTANCE_DELIMITER "#" #define INSTANCE_DELIMITER "#"
#define PORT_DELIMITER "." #define PORT_DELIMITER "."
@ -99,10 +103,22 @@ struct valuelist {
/* Part 3: Keys & Defaults (kept in the cell record as a hash table) */ /* 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 { struct property {
char *key; /* name of the property */ char *key; /* name of the property */
unsigned char idx; /* index into valuelist */ unsigned char idx; /* index into valuelist */
unsigned char type; /* string, integer, double, value, expression */ unsigned char type; /* string, integer, double, value, expression */
unsigned char merge; /* how property changes when devices are merged */
union { union {
char *string; char *string;
double dval; double dval;
@ -172,9 +188,9 @@ struct nlist {
unsigned long classhash; /* randomized hash value for cell class */ unsigned long classhash; /* randomized hash value for cell class */
struct Permutation *permutes; /* list of permuting pins */ struct Permutation *permutes; /* list of permuting pins */
struct objlist *cell; struct objlist *cell;
struct hashlist **objtab; /* hash table of object names */ struct hashdict objdict; /* hash table of object names */
struct hashlist **insttab; /* hash table of instance names */ struct hashdict instdict; /* hash table of instance names */
struct hashlist **proptab; /* hash table of property keys */ struct hashdict propdict; /* hash table of property keys */
struct objlist **nodename_cache; struct objlist **nodename_cache;
long nodename_cache_maxnodenum; /* largest node number in cache */ long nodename_cache_maxnodenum; /* largest node number in cache */
void *embedding; /* this will be cast to the appropriate data structure */ 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" #include "print.h"
// Global storage for parameters from .PARAM // Global storage for parameters from .PARAM
struct hashlist **spiceparams; struct hashdict spiceparams;
void SpiceSubCell(struct nlist *tp, int IsSubCell) void SpiceSubCell(struct nlist *tp, int IsSubCell)
{ {
@ -358,6 +358,12 @@ int renamepins(struct hashlist *p, int file)
obp = ob; obp = ob;
for (ob2 = tc->cell; ob2 != NULL; ob2 = ob2->next) { for (ob2 = tc->cell; ob2 != NULL; ob2 = ob2->next) {
if (ob2->type != PORT) break; 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)) { if (!matchnocase(ob2->name, obp->name + strlen(obp->instance.name) + 1)) {
// Printf("Cell %s pin correspondence: %s vs. %s\n", // Printf("Cell %s pin correspondence: %s vs. %s\n",
// tc->name, obp->name, ob2->name); // tc->name, obp->name, ob2->name);
@ -778,7 +784,7 @@ skip_ends:
kl->type = PROP_STRING; kl->type = PROP_STRING;
kl->slop.ival = 0; kl->slop.ival = 0;
kl->pdefault.string = strsave(eqptr + 1); 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; matchintfunc = matchfilenocase;
hashfunc = hashnocase; hashfunc = hashnocase;
spiceparams = (struct hashlist **)CALLOC(OBJHASHSIZE, InitializeHashTable(&spiceparams, OBJHASHSIZE);
sizeof(struct hashlist *));
/* All spice files should start with a comment line, */ /* All spice files should start with a comment line, */
/* but we won't depend upon it. Any 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 // Cleanup
while (CellStack != NULL) PopStack(&CellStack); while (CellStack != NULL) PopStack(&CellStack);
RecurseHashTable(spiceparams, OBJHASHSIZE, freeprop); RecurseHashTable(&spiceparams, freeprop);
HashKill(spiceparams, OBJHASHSIZE); HashKill(&spiceparams);
FREE(spiceparams);
spiceparams = NULL;
// Important: If the file is a library, containing subcircuit // Important: If the file is a library, containing subcircuit
// definitions but no components, then it needs to be registered // 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 #define XILINXHASHSIZE 99
static long xilinxhashbase = 0xA00; static long xilinxhashbase = 0xA00;
static struct hashlist *xilinxnametab[XILINXHASHSIZE]; static struct hashdict xilinxnamedict;
static FILE *xilinxfile; static FILE *xilinxfile;
char *gndnet = "0"; char *gndnet = "0";
@ -156,7 +156,7 @@ Xilinx(cellname, filename)
return; return;
} }
ClearDumpedList(); ClearDumpedList();
InitializeHashTable(xilinxnametab, XILINXHASHSIZE); InitializeHashTable(&xilinxnamedict, XILINXHASHSIZE);
if (LookupCell(cellname) != NULL) if (LookupCell(cellname) != NULL)
xilinxCell(cellname); xilinxCell(cellname);
CloseFile(FileName); CloseFile(FileName);

View File

@ -65,7 +65,7 @@ CPP = gcc -E -x c
CXX = @CXX@ CXX = @CXX@
CPPFLAGS = -I. -I${NETGENDIR} 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 CFLAGS = -g -m64 -fPIC -fPIC
DEPEND_FILE = Depend DEPEND_FILE = Depend

View File

@ -33,6 +33,7 @@ PATH: /sbin
PATH: /usr/bin PATH: /usr/bin
PATH: /usr/sbin PATH: /usr/sbin
PATH: /usr/local/bin 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_BUGREPORT "eda-dev@opencircuitdesign.com"
| #define PACKAGE_URL "" | #define PACKAGE_URL ""
| #define NETGEN_VERSION "1.5" | #define NETGEN_VERSION "1.5"
| #define NETGEN_REVISION "50" | #define NETGEN_REVISION "54"
| /* end confdefs.h. */ | /* end confdefs.h. */
| #include <ac_nonexistent.h> | #include <ac_nonexistent.h>
configure:3382: result: gcc -E configure:3382: result: gcc -E
@ -146,7 +147,7 @@ configure: failed program was:
| #define PACKAGE_BUGREPORT "eda-dev@opencircuitdesign.com" | #define PACKAGE_BUGREPORT "eda-dev@opencircuitdesign.com"
| #define PACKAGE_URL "" | #define PACKAGE_URL ""
| #define NETGEN_VERSION "1.5" | #define NETGEN_VERSION "1.5"
| #define NETGEN_REVISION "50" | #define NETGEN_REVISION "54"
| /* end confdefs.h. */ | /* end confdefs.h. */
| #include <ac_nonexistent.h> | #include <ac_nonexistent.h>
configure:3445: checking for library containing strerror configure:3445: checking for library containing strerror
@ -261,7 +262,7 @@ configure: failed program was:
| #define PACKAGE_BUGREPORT "eda-dev@opencircuitdesign.com" | #define PACKAGE_BUGREPORT "eda-dev@opencircuitdesign.com"
| #define PACKAGE_URL "" | #define PACKAGE_URL ""
| #define NETGEN_VERSION "1.5" | #define NETGEN_VERSION "1.5"
| #define NETGEN_REVISION "50" | #define NETGEN_REVISION "54"
| #define STDC_HEADERS 1 | #define STDC_HEADERS 1
| #define HAVE_SYS_TYPES_H 1 | #define HAVE_SYS_TYPES_H 1
| #define HAVE_SYS_STAT_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_BUGREPORT "eda-dev@opencircuitdesign.com"
| #define PACKAGE_URL "" | #define PACKAGE_URL ""
| #define NETGEN_VERSION "1.5" | #define NETGEN_VERSION "1.5"
| #define NETGEN_REVISION "50" | #define NETGEN_REVISION "54"
| #define STDC_HEADERS 1 | #define STDC_HEADERS 1
| #define HAVE_SYS_TYPES_H 1 | #define HAVE_SYS_TYPES_H 1
| #define HAVE_SYS_STAT_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_BUGREPORT "eda-dev@opencircuitdesign.com"
| #define PACKAGE_URL "" | #define PACKAGE_URL ""
| #define NETGEN_VERSION "1.5" | #define NETGEN_VERSION "1.5"
| #define NETGEN_REVISION "50" | #define NETGEN_REVISION "54"
| #define STDC_HEADERS 1 | #define STDC_HEADERS 1
| #define HAVE_SYS_TYPES_H 1 | #define HAVE_SYS_TYPES_H 1
| #define HAVE_SYS_STAT_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_BUGREPORT "eda-dev@opencircuitdesign.com"
| #define PACKAGE_URL "" | #define PACKAGE_URL ""
| #define NETGEN_VERSION "1.5" | #define NETGEN_VERSION "1.5"
| #define NETGEN_REVISION "50" | #define NETGEN_REVISION "54"
| #define STDC_HEADERS 1 | #define STDC_HEADERS 1
| #define HAVE_SYS_TYPES_H 1 | #define HAVE_SYS_TYPES_H 1
| #define HAVE_SYS_STAT_H 1 | #define HAVE_SYS_STAT_H 1
@ -621,7 +622,7 @@ CC='gcc'
CFLAGS='-g -m64 -fPIC' CFLAGS='-g -m64 -fPIC'
CPP='gcc -E -x c' CPP='gcc -E -x c'
CPPFLAGS='' 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' DEPEND_FLAG='-MM'
ECHO_C='' ECHO_C=''
ECHO_N='printf' ECHO_N='printf'
@ -734,7 +735,7 @@ unused=''
#define PACKAGE_BUGREPORT "eda-dev@opencircuitdesign.com" #define PACKAGE_BUGREPORT "eda-dev@opencircuitdesign.com"
#define PACKAGE_URL "" #define PACKAGE_URL ""
#define NETGEN_VERSION "1.5" #define NETGEN_VERSION "1.5"
#define NETGEN_REVISION "50" #define NETGEN_REVISION "54"
#define STDC_HEADERS 1 #define STDC_HEADERS 1
#define HAVE_SYS_TYPES_H 1 #define HAVE_SYS_TYPES_H 1
#define HAVE_SYS_STAT_H 1 #define HAVE_SYS_STAT_H 1

View File

@ -657,7 +657,7 @@ S["ECHO_T"]=""
S["ECHO_N"]="-n" S["ECHO_N"]="-n"
S["ECHO_C"]="" 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"\ 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"\ "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"\ "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" "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@ CXX = @CXX@
CPPFLAGS = -I. -I${NETGENDIR} 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 CFLAGS = -g -m64 -fPIC -fPIC
DEPEND_FILE = Depend DEPEND_FILE = Depend

View File

@ -2970,6 +2970,7 @@ _netcmp_equate(ClientData clientData,
/* add --- add new property */ /* add --- add new property */
/* remove --- delete existing property */ /* remove --- delete existing property */
/* tolerance --- set property tolerance */ /* tolerance --- set property tolerance */
/* merge --- set property merge behavior */
/* Formerly: (none) */ /* Formerly: (none) */
/* Results: */ /* Results: */
/* Side Effects: */ /* Side Effects: */
@ -2987,10 +2988,10 @@ _netcmp_property(ClientData clientData,
int ival, argstart; int ival, argstart;
char *options[] = { char *options[] = {
"add", "create", "remove", "delete", "tolerance", NULL "add", "create", "remove", "delete", "tolerance", "merge", NULL
}; };
enum OptionIdx { 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; int result, index, idx2;
@ -3001,6 +3002,13 @@ _netcmp_property(ClientData clientData,
INTEGER_IDX, DOUBLE_IDX, VALUE_IDX, STRING_IDX 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) { if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "valid_cellname ?option?"); Tcl_WrongNumArgs(interp, 1, objv, "valid_cellname ?option?");
return TCL_ERROR; return TCL_ERROR;
@ -3012,7 +3020,7 @@ _netcmp_property(ClientData clientData,
/* Print all properties of the cell as key/type/tolerance triplets */ /* Print all properties of the cell as key/type/tolerance triplets */
tobj1 = Tcl_NewListObj(0, NULL); tobj1 = Tcl_NewListObj(0, NULL);
kl = (struct property *)HashFirst(tp->proptab, OBJHASHSIZE); kl = (struct property *)HashFirst(&(tp->propdict));
while (kl != NULL) { while (kl != NULL) {
tobj2 = Tcl_NewListObj(0, NULL); tobj2 = Tcl_NewListObj(0, NULL);
@ -3039,7 +3047,7 @@ _netcmp_property(ClientData clientData,
Tcl_ListObjAppendElement(interp, tobj1, tobj2); Tcl_ListObjAppendElement(interp, tobj1, tobj2);
kl = (struct property *)HashNext(tp->proptab, OBJHASHSIZE); kl = (struct property *)HashNext(&(tp->propdict));
} }
Tcl_SetObjResult(interp, tobj1); Tcl_SetObjResult(interp, tobj1);
} }
@ -3175,11 +3183,9 @@ _netcmp_property(ClientData clientData,
if (objc == 3) { if (objc == 3) {
/* "remove" without additional arguments means */ /* "remove" without additional arguments means */
/* delete all properties. */ /* delete all properties. */
RecurseHashTable(tp->proptab, OBJHASHSIZE, freeprop); RecurseHashTable(&(tp->propdict), freeprop);
HashKill(tp->proptab, OBJHASHSIZE); HashKill(&(tp->propdict));
FREE(tp->proptab); InitializeHashTable(&(tp->propdict), OBJHASHSIZE);
tp->proptab = (struct hashlist **)CALLOC(OBJHASHSIZE,
sizeof(struct hashlist *));
} }
else { else {
for (i = 3; i < objc; i++) for (i = 3; i < objc; i++)
@ -3221,6 +3227,53 @@ _netcmp_property(ClientData clientData,
} }
} }
break; 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; return TCL_OK;