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:
parent
cbb2f78ee9
commit
5f634b2a91
10
base/actel.c
10
base/actel.c
|
|
@ -39,7 +39,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
|
||||
#define ACTELHASHSIZE 99
|
||||
static long actelhashbase = 0xA00;
|
||||
static struct hashlist *actelnametab[ACTELHASHSIZE];
|
||||
static struct hashdict actelnamedict;
|
||||
static FILE *actelfile;
|
||||
|
||||
char *ActelName(char *Name);
|
||||
|
|
@ -53,16 +53,16 @@ void PrintActelNames(char *filename)
|
|||
{
|
||||
if (filename == NULL) actelfile = stdout;
|
||||
else actelfile = fopen(filename,"w");
|
||||
RecurseHashTable(actelnametab, ACTELHASHSIZE, PrintActelName);
|
||||
RecurseHashTable(&actelnamedict, PrintActelName);
|
||||
if (actelfile != stdout) fclose(actelfile);
|
||||
}
|
||||
|
||||
long ActelNameHash(char *name)
|
||||
/* hashes name into nametab if necessary, then returns address of entry */
|
||||
/* hashes name into namedict if necessary, then returns address of entry */
|
||||
{
|
||||
struct hashlist *p;
|
||||
|
||||
p = HashInstall(name, actelnametab, ACTELHASHSIZE);
|
||||
p = HashInstall(name, &actelnamedict);
|
||||
if (p == NULL) return(0);
|
||||
if (p->ptr != NULL) return ((long)(p->ptr));
|
||||
actelhashbase++;
|
||||
|
|
@ -403,7 +403,7 @@ void Actel(char *name, char *filename)
|
|||
return;
|
||||
}
|
||||
ClearDumpedList();
|
||||
InitializeHashTable(actelnametab, ACTELHASHSIZE);
|
||||
InitializeHashTable(&actelnamedict, ACTELHASHSIZE);
|
||||
if (LookupCell(name) != NULL)
|
||||
actelCell(name);
|
||||
CloseFile(FileName);
|
||||
|
|
|
|||
|
|
@ -544,10 +544,10 @@ void simCell(char *name, int filenum)
|
|||
if (ob2 && ob2->type == PROPERTY) {
|
||||
struct property *kl;
|
||||
struct valuelist *vl;
|
||||
kl = (struct property *)HashLookup("length", tp2->proptab, OBJHASHSIZE);
|
||||
kl = (struct property *)HashLookup("length", &(tp2->propdict));
|
||||
vl = (struct valuelist *)ob2->instance.name;
|
||||
l = 1.0e6 * vl[kl->idx].value.dval; /* m -> um */
|
||||
kl = (struct property *)HashLookup("width", tp2->proptab, OBJHASHSIZE);
|
||||
kl = (struct property *)HashLookup("width", &(tp2->propdict));
|
||||
w = 1.0e6 * vl[kl->idx].value.dval; /* m -> um */
|
||||
}
|
||||
FlushString(" %g %g\n", l, w);
|
||||
|
|
@ -579,7 +579,7 @@ void simCell(char *name, int filenum)
|
|||
if (ob2 && ob2->type == PROPERTY) {
|
||||
struct property *kl;
|
||||
struct valuelist *vl;
|
||||
kl = (struct property *)HashLookup("value", tp2->proptab, OBJHASHSIZE);
|
||||
kl = (struct property *)HashLookup("value", &(tp2->propdict));
|
||||
vl = (struct valuelist *)ob2->instance.name;
|
||||
if (tp2->class == CLASS_CAP)
|
||||
v = 1.0e15 * vl[kl->idx].value.dval; /* F -> fF */
|
||||
|
|
|
|||
315
base/flatten.c
315
base/flatten.c
|
|
@ -177,7 +177,7 @@ void flattenCell(char *name, int file)
|
|||
}
|
||||
}
|
||||
}
|
||||
HashPtrInstall(tmp->name, tmp, ThisCell->objtab, OBJHASHSIZE);
|
||||
HashPtrInstall(tmp->name, tmp, &(ThisCell->objdict));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -198,9 +198,9 @@ void flattenCell(char *name, int file)
|
|||
#endif
|
||||
FreeString(tmp->instance.name);
|
||||
tmp->instance.name = strsave(tmpstr);
|
||||
HashPtrInstall(tmp->name, tmp, ThisCell->objtab, OBJHASHSIZE);
|
||||
HashPtrInstall(tmp->name, tmp, &(ThisCell->objdict));
|
||||
if (tmp->type == FIRSTPIN)
|
||||
HashPtrInstall(tmp->instance.name, tmp, ThisCell->insttab, OBJHASHSIZE);
|
||||
HashPtrInstall(tmp->instance.name, tmp, &(ThisCell->instdict));
|
||||
}
|
||||
|
||||
/* splice instance out of parent */
|
||||
|
|
@ -440,7 +440,7 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
|
|||
}
|
||||
// Don't hash this if the parent had a port of this name
|
||||
if (!ob2 || ob2->type != PORT)
|
||||
HashPtrInstall(tmp->name, tmp, ThisCell->objtab, OBJHASHSIZE);
|
||||
HashPtrInstall(tmp->name, tmp, &(ThisCell->objdict));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -461,9 +461,9 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
|
|||
#endif
|
||||
FreeString(tmp->instance.name);
|
||||
tmp->instance.name = strsave(tmpstr);
|
||||
HashPtrInstall(tmp->name, tmp, ThisCell->objtab, OBJHASHSIZE);
|
||||
HashPtrInstall(tmp->name, tmp, &(ThisCell->objdict));
|
||||
if (tmp->type == FIRSTPIN)
|
||||
HashPtrInstall(tmp->instance.name, tmp, ThisCell->insttab, OBJHASHSIZE);
|
||||
HashPtrInstall(tmp->instance.name, tmp, &(ThisCell->instdict));
|
||||
}
|
||||
|
||||
/* do property inheritance */
|
||||
|
|
@ -704,7 +704,7 @@ void convertGlobalsOf(char *name, int fnum, char *instance)
|
|||
newnode->instance.name = NULL;
|
||||
newnode->model.class = NULL;
|
||||
newpin->node = maxnode;
|
||||
HashPtrInstall(newnode->name, newnode, ThisCell->objtab, OBJHASHSIZE);
|
||||
HashPtrInstall(newnode->name, newnode, &(ThisCell->objdict));
|
||||
}
|
||||
|
||||
// Remove any references to the net as a GLOBAL type in the instance
|
||||
|
|
@ -727,7 +727,7 @@ void convertGlobalsOf(char *name, int fnum, char *instance)
|
|||
// Now there should be only one object of this name in the instance,
|
||||
// which is the pin, and we will set the hash table to point to it.
|
||||
|
||||
HashPtrInstall(newpin->name, newpin, ThisCell->objtab, OBJHASHSIZE);
|
||||
HashPtrInstall(newpin->name, newpin, &(ThisCell->objdict));
|
||||
|
||||
}
|
||||
CacheNodeNames(ThisCell);
|
||||
|
|
@ -840,7 +840,7 @@ void ConvertGlobals(char *name, int filenum)
|
|||
strsave(ObjList->instance.name) : NULL;
|
||||
NewObj->name = (ObjList->name) ? strsave(ObjList->name) : NULL;
|
||||
|
||||
HashPtrInstall(NewObj->name, NewObj, ThisCell->objtab, OBJHASHSIZE);
|
||||
HashPtrInstall(NewObj->name, NewObj, &(ThisCell->objdict));
|
||||
|
||||
/* Find all parent cells of this cell. Find the global node */
|
||||
/* if it exists or create it if it doesn't. Add the node to */
|
||||
|
|
@ -959,11 +959,11 @@ struct nlist *uniquepins(struct hashlist *p, void *clientdata)
|
|||
modified = 1;
|
||||
|
||||
// Check if the node we're about to remove is in the
|
||||
// objtab hash table; if so, replace it with the one
|
||||
// objdict hash table; if so, replace it with the one
|
||||
// that we are going to keep.
|
||||
|
||||
if (LookupObject(ob->name, ptr) == ob) {
|
||||
HashPtrInstall(ob->name, saveob, ptr->objtab, OBJHASHSIZE);
|
||||
HashPtrInstall(ob->name, saveob, &(ptr->objdict));
|
||||
}
|
||||
}
|
||||
tob = tob->next;
|
||||
|
|
@ -998,7 +998,7 @@ struct nlist *uniquepins(struct hashlist *p, void *clientdata)
|
|||
|
||||
// Renumber the pins in order. Since when removing duplicates, the
|
||||
// first entry is always kept, the first pin is never changed, so
|
||||
// the insttab record is never corrupted.
|
||||
// the instdict record is never corrupted.
|
||||
|
||||
i = FIRSTPIN;
|
||||
firstpin->type = i++;
|
||||
|
|
@ -1093,8 +1093,7 @@ int UniquePins(char *name, int filenum)
|
|||
// The hash table is pointing at the cell we are
|
||||
// about to delete. Hash the one we're keeping instead.
|
||||
|
||||
HashPtrInstall(ob->name, firstport[ob->node],
|
||||
ThisCell->objtab, OBJHASHSIZE);
|
||||
HashPtrInstall(ob->name, firstport[ob->node], &(ThisCell->objdict));
|
||||
}
|
||||
|
||||
if (lob == NULL) {
|
||||
|
|
@ -1131,7 +1130,7 @@ int UniquePins(char *name, int filenum)
|
|||
/* Callback function for CleanupPins */
|
||||
/* Note that if the first pin of the instance is a */
|
||||
/* disconnected node, then removing it invalidates the */
|
||||
/* insttab hash. */
|
||||
/* instdict hash. */
|
||||
/*------------------------------------------------------*/
|
||||
|
||||
struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
|
||||
|
|
@ -1181,9 +1180,9 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
|
|||
}
|
||||
|
||||
// Check if the node we're about to remove is in the
|
||||
// objtab hash table
|
||||
// objdict hash table
|
||||
if (LookupObject(ob->name, ptr) == ob) {
|
||||
HashDelete(ob->name, ptr->objtab, OBJHASHSIZE);
|
||||
HashDelete(ob->name, &(ptr->objdict));
|
||||
}
|
||||
|
||||
FREE(ob->name);
|
||||
|
|
@ -1199,10 +1198,9 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
|
|||
obt = obt->next;
|
||||
}
|
||||
|
||||
/* Rehash the insttab, in case the first pin got removed */
|
||||
/* Rehash the instdict, in case the first pin got removed */
|
||||
if (firstpin && (firstpin->type == FIRSTPIN))
|
||||
HashPtrInstall(firstpin->instance.name, firstpin, ptr->insttab,
|
||||
OBJHASHSIZE);
|
||||
HashPtrInstall(firstpin->instance.name, firstpin, &(ptr->instdict));
|
||||
}
|
||||
}
|
||||
return NULL; /* Keep the search going */
|
||||
|
|
@ -1272,9 +1270,9 @@ int CleanupPins(char *name, int filenum)
|
|||
}
|
||||
|
||||
// Check if the node we're about to remove is in the
|
||||
// objtab hash table
|
||||
// objdict hash table
|
||||
if (LookupObject(ob->name, ThisCell) == ob) {
|
||||
HashDelete(ob->name, ThisCell->objtab, OBJHASHSIZE);
|
||||
HashDelete(ob->name, &(ThisCell->objdict));
|
||||
}
|
||||
|
||||
FREE(ob->name);
|
||||
|
|
@ -1307,11 +1305,151 @@ typedef struct ecomplist {
|
|||
} ECompList;
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
/* Survey the contents of a cell and
|
||||
/* Survey a specific device in a cell and sort into a */
|
||||
/* hash by critical property. */
|
||||
/*------------------------------------------------------*/
|
||||
|
||||
void
|
||||
SurveyCell(struct nlist *tc, struct hashlist **comptab, int file1, int file2, int which)
|
||||
SurveyDevice(struct nlist *tc, struct hashdict *devdict,
|
||||
struct nlist *cell, struct property *kl,
|
||||
int file1, int file2, int which)
|
||||
{
|
||||
struct objlist *ob, *ob2;
|
||||
struct nlist *tsub, *teq;
|
||||
ECompare *dcomp, *ncomp, *qcomp;
|
||||
int file = (which == 0) ? file1 : file2;
|
||||
int ofile = (which == 0) ? file2 : file1;
|
||||
char *p1str, *p2str, *d1str, *d2str;
|
||||
|
||||
for (ob = tc->cell; ob; ob = ob->next) {
|
||||
if (ob->type == FIRSTPIN) {
|
||||
|
||||
tsub = LookupCellFile(ob->model.class, file);
|
||||
if (tsub == cell) {
|
||||
|
||||
p1str = (char *)MALLOC(strlen(ob->model.class) + 20);
|
||||
sprintf(p1str, "%s", ob->model.class);
|
||||
|
||||
if (tsub->flags & CELL_DUPLICATE) {
|
||||
// Always register a duplicate under the original name
|
||||
d1str = strstr(p1str, "[[");
|
||||
if (d1str) *d1str = '\0';
|
||||
}
|
||||
d1str = p1str + strlen(p1str);
|
||||
sprintf(d1str, "::");
|
||||
d1str += 2;
|
||||
|
||||
teq = LookupClassEquivalent(ob->model.class, file, ofile);
|
||||
p2str = (char *)MALLOC(strlen(teq->name) + 20);
|
||||
sprintf(p2str, "%s", teq->name);
|
||||
|
||||
if (teq->flags & CELL_DUPLICATE) {
|
||||
// Always register a duplicate under the original name
|
||||
d2str = strstr(p2str, "[[");
|
||||
if (d2str) *d2str = '\0';
|
||||
}
|
||||
d2str = p2str + strlen(p2str);
|
||||
sprintf(d2str, "::");
|
||||
d2str += 2;
|
||||
|
||||
// Advance ob to property list
|
||||
for (ob2 = ob->next; ob2 && ob2->type != FIRSTPIN; ob2 = ob2->next) {
|
||||
if (ob2->type == PROPERTY) {
|
||||
struct valuelist *kv;
|
||||
int i;
|
||||
for (i = 0; ; i++) {
|
||||
kv = &(ob2->instance.props[i]);
|
||||
if (kv->type == PROP_ENDLIST) break;
|
||||
if ((*matchfunc)(kv->key, kl->key)) {
|
||||
switch(kv->type) {
|
||||
case PROP_INTEGER:
|
||||
sprintf(d1str, "%d", kv->value.ival);
|
||||
sprintf(d2str, "%d", kv->value.ival);
|
||||
break;
|
||||
case PROP_DOUBLE:
|
||||
case PROP_VALUE:
|
||||
// To-do: Round to tolerance
|
||||
sprintf(d1str, "%g", kv->value.dval);
|
||||
sprintf(d2str, "%g", kv->value.dval);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (*d1str == '\0') {
|
||||
// No critical property instanced, so use default
|
||||
switch(kl->type) {
|
||||
case PROP_INTEGER:
|
||||
sprintf(d1str, "%d", kl->pdefault.ival);
|
||||
sprintf(d2str, "%d", kl->pdefault.ival);
|
||||
break;
|
||||
case PROP_DOUBLE:
|
||||
case PROP_VALUE:
|
||||
// To-do: Round to tolerance
|
||||
sprintf(d1str, "%g", kl->pdefault.dval);
|
||||
sprintf(d2str, "%g", kl->pdefault.dval);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Create hash key from object class and the critical
|
||||
// property affecting the device count.
|
||||
|
||||
dcomp = (ECompare *)HashInt2Lookup(p1str, file, devdict);
|
||||
|
||||
// Fill in the values for this device::property combination
|
||||
|
||||
if (dcomp == NULL) {
|
||||
ncomp = (ECompare *)MALLOC(sizeof(ECompare));
|
||||
if (which == 0) {
|
||||
ncomp->num1 = 1;
|
||||
ncomp->num2 = 0;
|
||||
ncomp->cell1 = tsub;
|
||||
ncomp->cell2 = teq;
|
||||
}
|
||||
else {
|
||||
ncomp->num1 = 0;
|
||||
ncomp->num2 = 1;
|
||||
ncomp->cell2 = tsub;
|
||||
ncomp->cell1 = teq;
|
||||
}
|
||||
ncomp->add1 = 0;
|
||||
ncomp->add2 = 0;
|
||||
ncomp->refcount = (char)1;
|
||||
|
||||
HashInt2PtrInstall(p1str, file, ncomp, devdict);
|
||||
if (teq != NULL) {
|
||||
qcomp = (ECompare *)HashInt2Lookup(p2str, ofile,
|
||||
devdict);
|
||||
if (qcomp == NULL) {
|
||||
HashInt2PtrInstall(p2str, ofile, ncomp, devdict);
|
||||
ncomp->refcount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (which == 0)
|
||||
dcomp->num1++;
|
||||
else
|
||||
dcomp->num2++;
|
||||
}
|
||||
|
||||
FREE(p1str);
|
||||
FREE(p2str);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
/* Survey the contents of a cell and sort into a hash */
|
||||
/*------------------------------------------------------*/
|
||||
|
||||
void
|
||||
SurveyCell(struct nlist *tc, struct hashdict *compdict, int file1, int file2, int which)
|
||||
{
|
||||
struct objlist *ob;
|
||||
struct nlist *tsub, *teq;
|
||||
|
|
@ -1331,8 +1469,7 @@ SurveyCell(struct nlist *tc, struct hashlist **comptab, int file1, int file2, in
|
|||
else dstr = NULL;
|
||||
|
||||
teq = LookupClassEquivalent(ob->model.class, file, ofile);
|
||||
ecomp = (ECompare *)HashInt2Lookup(ob->model.class, file,
|
||||
comptab, OBJHASHSIZE);
|
||||
ecomp = (ECompare *)HashInt2Lookup(ob->model.class, file, compdict);
|
||||
|
||||
if (ecomp == NULL) {
|
||||
ncomp = (ECompare *)MALLOC(sizeof(ECompare));
|
||||
|
|
@ -1352,19 +1489,16 @@ SurveyCell(struct nlist *tc, struct hashlist **comptab, int file1, int file2, in
|
|||
ncomp->add2 = 0;
|
||||
ncomp->refcount = (char)1;
|
||||
|
||||
HashInt2PtrInstall(ob->model.class, file, ncomp, comptab,
|
||||
OBJHASHSIZE);
|
||||
HashInt2PtrInstall(ob->model.class, file, ncomp, compdict);
|
||||
if (teq != NULL) {
|
||||
char *bstr = NULL;
|
||||
if (teq->flags & CELL_DUPLICATE) {
|
||||
bstr = strstr(teq->name, "[[");
|
||||
if (bstr) *bstr = '\0';
|
||||
}
|
||||
qcomp = (ECompare *)HashInt2Lookup(teq->name, ofile,
|
||||
comptab, OBJHASHSIZE);
|
||||
qcomp = (ECompare *)HashInt2Lookup(teq->name, ofile, compdict);
|
||||
if (qcomp == NULL) {
|
||||
HashInt2PtrInstall(teq->name, ofile, ncomp, comptab,
|
||||
OBJHASHSIZE);
|
||||
HashInt2PtrInstall(teq->name, ofile, ncomp, compdict);
|
||||
ncomp->refcount++;
|
||||
}
|
||||
if (bstr) *bstr = '[';
|
||||
|
|
@ -1393,7 +1527,7 @@ SurveyCell(struct nlist *tc, struct hashlist **comptab, int file1, int file2, in
|
|||
/* */
|
||||
/* If there is a mismatch between instances of low- */
|
||||
/* level devices, determine if the mismatches can be */
|
||||
/* resolved by parallel/serial combining, accoring to */
|
||||
/* resolved by parallel/serial combining, according to */
|
||||
/* combination rules. */
|
||||
/* */
|
||||
/* Return the number of modifications made. */
|
||||
|
|
@ -1404,7 +1538,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
|||
{
|
||||
struct nlist *tc1, *tc2, *tsub1, *tsub2;
|
||||
struct objlist *ob1, *ob2, *lob;
|
||||
struct hashlist **comptab;
|
||||
struct hashdict compdict;
|
||||
ECompare *ecomp, *ncomp;
|
||||
ECompList *list0X, *listX0;
|
||||
int match, modified = 0;
|
||||
|
|
@ -1421,14 +1555,13 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
|||
|
||||
if (tc1 == NULL || tc2 == NULL) return;
|
||||
|
||||
comptab = (struct hashlist **)CALLOC(OBJHASHSIZE,
|
||||
sizeof(struct hashlist *));
|
||||
InitializeHashTable(&compdict, OBJHASHSIZE);
|
||||
|
||||
// Gather information about instances of cell "name1"
|
||||
SurveyCell(tc1, comptab, file1, file2, 0);
|
||||
SurveyCell(tc1, &compdict, file1, file2, 0);
|
||||
|
||||
// Gather information about instances of cell "name2"
|
||||
SurveyCell(tc2, comptab, file1, file2, 1);
|
||||
SurveyCell(tc2, &compdict, file1, file2, 1);
|
||||
|
||||
// Find all instances of one cell that have fewer in
|
||||
// the compared circuit. Check whether subcircuits
|
||||
|
|
@ -1436,7 +1569,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
|||
// or subcircuits that have more in the compared circuit.
|
||||
|
||||
listX0 = list0X = NULL;
|
||||
ecomp = (ECompare *)HashFirst(comptab, OBJHASHSIZE);
|
||||
ecomp = (ECompare *)HashFirst(&compdict);
|
||||
while (ecomp != NULL) {
|
||||
|
||||
/* Case 1: Both cell1 and cell2 classes are subcircuits, */
|
||||
|
|
@ -1452,7 +1585,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
|||
for (ob2 = ecomp->cell2->cell; ob2; ob2 = ob2->next) {
|
||||
if (ob2->type == FIRSTPIN) {
|
||||
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
|
||||
ecomp->cell2->file, comptab, OBJHASHSIZE);
|
||||
ecomp->cell2->file, &compdict);
|
||||
if (ncomp != NULL) {
|
||||
if ((ncomp->num1 > ncomp->num2) &&
|
||||
((ncomp->add2 + ecomp->num2) >=
|
||||
|
|
@ -1498,8 +1631,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
|||
for (ob2 = ecomp->cell2->cell; ob2; ob2 = ob2->next) {
|
||||
if (ob2->type == FIRSTPIN) {
|
||||
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
|
||||
ecomp->cell2->file, comptab,
|
||||
OBJHASHSIZE);
|
||||
ecomp->cell2->file, &compdict);
|
||||
if (ncomp != NULL) {
|
||||
if (match) {
|
||||
ncomp->num1 += ncomp->add1;
|
||||
|
|
@ -1549,7 +1681,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
|||
for (ob2 = ecomp->cell2->cell; ob2; ob2 = ob2->next) {
|
||||
if (ob2->type == FIRSTPIN) {
|
||||
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
|
||||
ecomp->cell2->file, comptab, OBJHASHSIZE);
|
||||
ecomp->cell2->file, &compdict);
|
||||
if (ncomp != NULL) {
|
||||
if ((ncomp->num1 > ncomp->num2) &&
|
||||
((ncomp->add2 + ecomp->num2) <=
|
||||
|
|
@ -1582,8 +1714,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
|||
for (ob2 = ecomp->cell2->cell; ob2; ob2 = ob2->next) {
|
||||
if (ob2->type == FIRSTPIN) {
|
||||
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
|
||||
ecomp->cell2->file, comptab,
|
||||
OBJHASHSIZE);
|
||||
ecomp->cell2->file, &compdict);
|
||||
if (ncomp != NULL) {
|
||||
if (match) {
|
||||
ncomp->num2 += ncomp->add2;
|
||||
|
|
@ -1608,7 +1739,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
|||
for (ob2 = ecomp->cell1->cell; ob2; ob2 = ob2->next) {
|
||||
if (ob2->type == FIRSTPIN) {
|
||||
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
|
||||
ecomp->cell1->file, comptab, OBJHASHSIZE);
|
||||
ecomp->cell1->file, &compdict);
|
||||
if (ncomp != NULL) {
|
||||
if ((ncomp->num2 > ncomp->num1) &&
|
||||
((ncomp->add1 + ecomp->num1) <=
|
||||
|
|
@ -1641,8 +1772,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
|||
for (ob2 = ecomp->cell1->cell; ob2; ob2 = ob2->next) {
|
||||
if (ob2->type == FIRSTPIN) {
|
||||
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
|
||||
ecomp->cell1->file, comptab,
|
||||
OBJHASHSIZE);
|
||||
ecomp->cell1->file, &compdict);
|
||||
if (ncomp != NULL) {
|
||||
if (match) {
|
||||
ncomp->num1 += ncomp->add1;
|
||||
|
|
@ -1656,13 +1786,85 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
|||
}
|
||||
ecomp->add1 = 0;
|
||||
}
|
||||
ecomp = (ECompare *)HashNext(comptab, OBJHASHSIZE);
|
||||
ecomp = (ECompare *)HashNext(&compdict);
|
||||
}
|
||||
|
||||
// Check for cells, either low-level devices or subcircuits,
|
||||
// that have properties allowing devices to be merged. If
|
||||
// the classes of both cells are the same, and the number of
|
||||
// instances is different, and merging the device with more
|
||||
// instances improves the matching, then perform the merge.
|
||||
|
||||
ecomp = (ECompare *)HashFirst(&compdict);
|
||||
while (ecomp != NULL) {
|
||||
|
||||
if ((ecomp->num1 != ecomp->num2) &&
|
||||
(ecomp->cell1 != NULL) &&
|
||||
(ecomp->cell2 != NULL) &&
|
||||
(ecomp->cell1->classhash == ecomp->cell2->classhash)) {
|
||||
|
||||
struct hashdict devdict;
|
||||
ECompare *dcomp;
|
||||
|
||||
// Determine if either device has mergeable properties. If so,
|
||||
// sort the device into bins by critical (mergeable) property,
|
||||
// and merge devices where merging makes a better match.
|
||||
|
||||
struct property *kl1, *kl2;
|
||||
|
||||
kl1 = (struct property *)HashFirst(&(ecomp->cell1->propdict));
|
||||
while (kl1 != NULL) {
|
||||
if (kl1->merge == MERGE_ADD_CRIT || kl1->merge == MERGE_PAR_CRIT)
|
||||
break;
|
||||
kl1 = (struct property *)HashNext(&(ecomp->cell1->propdict));
|
||||
}
|
||||
kl2 = (struct property *)HashFirst(&(ecomp->cell2->propdict));
|
||||
while (kl2 != NULL) {
|
||||
if (kl2->merge == MERGE_ADD_CRIT || kl2->merge == MERGE_PAR_CRIT)
|
||||
break;
|
||||
kl2 = (struct property *)HashNext(&(ecomp->cell1->propdict));
|
||||
}
|
||||
if (kl1 != NULL || kl2 != NULL) {
|
||||
|
||||
// Create the device hash table
|
||||
|
||||
InitializeHashTable(&devdict, OBJHASHSIZE);
|
||||
|
||||
// Populate the device hash table
|
||||
|
||||
SurveyDevice(tc1, &devdict, ecomp->cell1, kl1, file1, file2, 0);
|
||||
SurveyDevice(tc2, &devdict, ecomp->cell2, kl2, file1, file2, 0);
|
||||
|
||||
// Scan the device hash table. If devices can be merged
|
||||
// and this improves the matching between cells, then do
|
||||
// the merge.
|
||||
|
||||
dcomp = (ECompare *)HashFirst(&devdict);
|
||||
while (dcomp != NULL) {
|
||||
if (dcomp->num1 != dcomp->num2) {
|
||||
/* XXX WIP WIP WIP XXX */
|
||||
}
|
||||
dcomp = (ECompare *)HashNext(&devdict);
|
||||
}
|
||||
|
||||
// Free the device hash table
|
||||
|
||||
dcomp = (ECompare *)HashFirst(&devdict);
|
||||
while (dcomp != NULL) {
|
||||
if (--dcomp->refcount == (char)0) FREE(dcomp);
|
||||
dcomp = (ECompare *)HashNext(&devdict);
|
||||
}
|
||||
HashKill(&devdict);
|
||||
}
|
||||
}
|
||||
|
||||
ecomp = (ECompare *)HashNext(&compdict);
|
||||
}
|
||||
|
||||
// Remove non-matching zero-value devices. This can
|
||||
// be done on a per-instance basis.
|
||||
|
||||
ecomp = (ECompare *)HashFirst(comptab, OBJHASHSIZE);
|
||||
ecomp = (ECompare *)HashFirst(&compdict);
|
||||
while (ecomp != NULL) {
|
||||
if ((ecomp->num1 != ecomp->num2) && (ecomp->cell1 != NULL) &&
|
||||
(ecomp->cell1->class == CLASS_RES)) {
|
||||
|
|
@ -1869,7 +2071,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
|||
}
|
||||
}
|
||||
}
|
||||
ecomp = (ECompare *)HashNext(comptab, OBJHASHSIZE);
|
||||
ecomp = (ECompare *)HashNext(&compdict);
|
||||
}
|
||||
|
||||
// Finally, check all entries in listX0 vs. all entries in list0X to see
|
||||
|
|
@ -1901,7 +2103,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
|||
if (dstr) *dstr = '\0';
|
||||
}
|
||||
ncomp = (ECompare *)HashInt2Lookup(ob1->model.class,
|
||||
ecompX0->cell1->file, comptab, OBJHASHSIZE);
|
||||
ecompX0->cell1->file, &compdict);
|
||||
if (dstr) *dstr = '[';
|
||||
if ((ncomp == ecomp0X) && (ecomp0X->num2 <= ecompX0->num1)) {
|
||||
Fprintf(stdout, "Flattening instances of %s in cell %s"
|
||||
|
|
@ -1927,7 +2129,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
|||
if (dstr) *dstr = '\0';
|
||||
}
|
||||
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
|
||||
ecomp0X->cell2->file, comptab, OBJHASHSIZE);
|
||||
ecomp0X->cell2->file, &compdict);
|
||||
if (dstr) *dstr = '[';
|
||||
if ((ncomp == ecompX0) && (ecompX0->num1 <= ecomp0X->num2)) {
|
||||
Fprintf(stdout, "Flattening instances of %s in cell %s"
|
||||
|
|
@ -1948,13 +2150,12 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
|||
|
||||
// Free the hash table and its contents.
|
||||
|
||||
ecomp = (ECompare *)HashFirst(comptab, OBJHASHSIZE);
|
||||
ecomp = (ECompare *)HashFirst(&compdict);
|
||||
while (ecomp != NULL) {
|
||||
if (--ecomp->refcount == (char)0) FREE(ecomp);
|
||||
ecomp = (ECompare *)HashNext(comptab, OBJHASHSIZE);
|
||||
ecomp = (ECompare *)HashNext(&compdict);
|
||||
}
|
||||
HashKill(comptab, OBJHASHSIZE);
|
||||
FREE(comptab);
|
||||
HashKill(&compdict);
|
||||
|
||||
// Free the 0:X and X:0 lists
|
||||
while (listX0 != NULL) {
|
||||
|
|
|
|||
163
base/hash.c
163
base/hash.c
|
|
@ -33,22 +33,25 @@ unsigned long (*hashfunc)(char *, int) = NULL;
|
|||
int (*matchfunc)(char *, char *) = NULL;
|
||||
int (*matchintfunc)(char *, char *, int, int) = NULL;
|
||||
|
||||
void InitializeHashTable(struct hashlist **tab, int size)
|
||||
void InitializeHashTable(struct hashdict *dict, int size)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < size; i++) tab[i] = NULL;
|
||||
struct hashlist **hashtab;
|
||||
|
||||
dict->hashtab = (struct hashlist **)CALLOC(size, sizeof(struct hashlist *));
|
||||
dict->hashsize = size;
|
||||
dict->hashfirstindex = 0;
|
||||
dict->hashfirstptr = NULL;
|
||||
}
|
||||
|
||||
int RecurseHashTable(struct hashlist **hashtab, int hashsize,
|
||||
int (*func)(struct hashlist *elem))
|
||||
int RecurseHashTable(struct hashdict *dict, int (*func)(struct hashlist *elem))
|
||||
/* returns the sum of the return values of (*func) */
|
||||
{
|
||||
int i, sum;
|
||||
struct hashlist *p;
|
||||
|
||||
sum = 0;
|
||||
for (i = 0; i < hashsize; i++)
|
||||
for (p = hashtab[i]; p != NULL; p = p->next)
|
||||
for (i = 0; i < dict->hashsize; i++)
|
||||
for (p = dict->hashtab[i]; p != NULL; p = p->next)
|
||||
sum += (*func)(p);
|
||||
return(sum);
|
||||
}
|
||||
|
|
@ -57,15 +60,15 @@ int RecurseHashTable(struct hashlist **hashtab, int hashsize,
|
|||
* type int value to the function.
|
||||
*/
|
||||
|
||||
int RecurseHashTableValue(struct hashlist **hashtab, int hashsize,
|
||||
int RecurseHashTableValue(struct hashdict *dict,
|
||||
int (*func)(struct hashlist *elem, int), int value)
|
||||
{
|
||||
int i, sum;
|
||||
struct hashlist *p;
|
||||
|
||||
sum = 0;
|
||||
for (i = 0; i < hashsize; i++)
|
||||
for (p = hashtab[i]; p != NULL; p = p->next)
|
||||
for (i = 0; i < dict->hashsize; i++)
|
||||
for (p = dict->hashtab[i]; p != NULL; p = p->next)
|
||||
sum += (*func)(p, value);
|
||||
return(sum);
|
||||
}
|
||||
|
|
@ -76,7 +79,7 @@ int RecurseHashTableValue(struct hashlist **hashtab, int hashsize,
|
|||
* function through that structure.
|
||||
*/
|
||||
|
||||
struct nlist *RecurseHashTablePointer(struct hashlist **hashtab, int hashsize,
|
||||
struct nlist *RecurseHashTablePointer(struct hashdict *dict,
|
||||
struct nlist *(*func)(struct hashlist *elem, void *),
|
||||
void *pointer)
|
||||
{
|
||||
|
|
@ -84,8 +87,8 @@ struct nlist *RecurseHashTablePointer(struct hashlist **hashtab, int hashsize,
|
|||
struct hashlist *p;
|
||||
struct nlist *tp;
|
||||
|
||||
for (i = 0; i < hashsize; i++) {
|
||||
for (p = hashtab[i]; p != NULL; p = p->next) {
|
||||
for (i = 0; i < dict->hashsize; i++) {
|
||||
for (p = dict->hashtab[i]; p != NULL; p = p->next) {
|
||||
tp = (*func)(p, pointer);
|
||||
if (tp != NULL) return tp;
|
||||
}
|
||||
|
|
@ -164,14 +167,14 @@ unsigned long genhash(char *s, int c, int hashsize)
|
|||
/* return the 'ptr' field of the hash table entry, or NULL if not found */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
void *HashLookup(char *s, struct hashlist **hashtab, int hashsize)
|
||||
void *HashLookup(char *s, struct hashdict *dict)
|
||||
{
|
||||
struct hashlist *np;
|
||||
unsigned long hashval;
|
||||
|
||||
hashval = (*hashfunc)(s, hashsize);
|
||||
hashval = (*hashfunc)(s, dict->hashsize);
|
||||
|
||||
for (np = hashtab[hashval]; np != NULL; np = np->next)
|
||||
for (np = dict->hashtab[hashval]; np != NULL; np = np->next)
|
||||
if ((*matchfunc)(s, np->name)) return (np->ptr); /* correct match */
|
||||
return (NULL); /* not found */
|
||||
}
|
||||
|
|
@ -183,14 +186,14 @@ void *HashLookup(char *s, struct hashlist **hashtab, int hashsize)
|
|||
/* passed integer value i */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
void *HashIntLookup(char *s, int i, struct hashlist **hashtab, int hashsize)
|
||||
void *HashIntLookup(char *s, int i, struct hashdict *dict)
|
||||
{
|
||||
struct hashlist *np;
|
||||
unsigned long hashval;
|
||||
|
||||
hashval = (*hashfunc)(s, hashsize);
|
||||
hashval = (*hashfunc)(s, dict->hashsize);
|
||||
|
||||
for (np = hashtab[hashval]; np != NULL; np = np->next) {
|
||||
for (np = dict->hashtab[hashval]; np != NULL; np = np->next) {
|
||||
if (np->ptr == NULL) {
|
||||
if ((*matchintfunc)(s, np->name, i, -1))
|
||||
return NULL;
|
||||
|
|
@ -209,14 +212,14 @@ void *HashIntLookup(char *s, int i, struct hashlist **hashtab, int hashsize)
|
|||
/* first, then the character string. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
void *HashInt2Lookup(char *s, int c, struct hashlist **hashtab, int hashsize)
|
||||
void *HashInt2Lookup(char *s, int c, struct hashdict *dict)
|
||||
{
|
||||
struct hashlist *np;
|
||||
unsigned long hashval;
|
||||
|
||||
hashval = genhash(s, c, hashsize);
|
||||
hashval = genhash(s, c, dict->hashsize);
|
||||
|
||||
for (np = hashtab[hashval]; np != NULL; np = np->next)
|
||||
for (np = dict->hashtab[hashval]; np != NULL; np = np->next)
|
||||
if (!strcmp(s, np->name))
|
||||
return (np->ptr); /* correct match */
|
||||
|
||||
|
|
@ -228,14 +231,13 @@ void *HashInt2Lookup(char *s, int c, struct hashlist **hashtab, int hashsize)
|
|||
/* return the hashlist entry, after (re)initializing its 'ptr' field */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
struct hashlist *HashPtrInstall(char *name, void *ptr,
|
||||
struct hashlist **hashtab, int hashsize)
|
||||
struct hashlist *HashPtrInstall(char *name, void *ptr, struct hashdict *dict)
|
||||
{
|
||||
struct hashlist *np;
|
||||
unsigned long hashval;
|
||||
|
||||
hashval = (*hashfunc)(name,hashsize);
|
||||
for (np = hashtab[hashval]; np != NULL; np = np->next)
|
||||
hashval = (*hashfunc)(name, dict->hashsize);
|
||||
for (np = dict->hashtab[hashval]; np != NULL; np = np->next)
|
||||
if ((*matchfunc)(name, np->name)) {
|
||||
np->ptr = ptr;
|
||||
return (np); /* match found in hash table */
|
||||
|
|
@ -246,8 +248,8 @@ struct hashlist *HashPtrInstall(char *name, void *ptr,
|
|||
return (NULL);
|
||||
if ((np->name = strsave(name)) == NULL) return (NULL);
|
||||
np->ptr = ptr;
|
||||
np->next = hashtab[hashval];
|
||||
return(hashtab[hashval] = np);
|
||||
np->next = dict->hashtab[hashval];
|
||||
return(dict->hashtab[hashval] = np);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
|
@ -256,13 +258,13 @@ struct hashlist *HashPtrInstall(char *name, void *ptr,
|
|||
/*----------------------------------------------------------------------*/
|
||||
|
||||
struct hashlist *HashIntPtrInstall(char *name, int value, void *ptr,
|
||||
struct hashlist **hashtab, int hashsize)
|
||||
struct hashdict *dict)
|
||||
{
|
||||
struct hashlist *np;
|
||||
unsigned long hashval;
|
||||
|
||||
hashval = (*hashfunc)(name,hashsize);
|
||||
for (np = hashtab[hashval]; np != NULL; np = np->next)
|
||||
hashval = (*hashfunc)(name, dict->hashsize);
|
||||
for (np = dict->hashtab[hashval]; np != NULL; np = np->next)
|
||||
if ((*matchintfunc)(name, np->name, value, (int)(*((int *)np->ptr)))) {
|
||||
np->ptr = ptr;
|
||||
return (np); /* match found in hash table */
|
||||
|
|
@ -273,8 +275,8 @@ struct hashlist *HashIntPtrInstall(char *name, int value, void *ptr,
|
|||
return (NULL);
|
||||
if ((np->name = strsave(name)) == NULL) return (NULL);
|
||||
np->ptr = ptr;
|
||||
np->next = hashtab[hashval];
|
||||
return(hashtab[hashval] = np);
|
||||
np->next = dict->hashtab[hashval];
|
||||
return(dict->hashtab[hashval] = np);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
|
@ -282,13 +284,13 @@ struct hashlist *HashIntPtrInstall(char *name, int value, void *ptr,
|
|||
/*----------------------------------------------------------------------*/
|
||||
|
||||
struct hashlist *HashInt2PtrInstall(char *name, int c, void *ptr,
|
||||
struct hashlist **hashtab, int hashsize)
|
||||
struct hashdict *dict)
|
||||
{
|
||||
struct hashlist *np;
|
||||
unsigned long hashval;
|
||||
|
||||
hashval = genhash(name, c, hashsize);
|
||||
for (np = hashtab[hashval]; np != NULL; np = np->next)
|
||||
hashval = genhash(name, c, dict->hashsize);
|
||||
for (np = dict->hashtab[hashval]; np != NULL; np = np->next)
|
||||
if (!strcmp(name, np->name)) {
|
||||
np->ptr = ptr;
|
||||
return (np); /* match found in hash table */
|
||||
|
|
@ -299,27 +301,31 @@ struct hashlist *HashInt2PtrInstall(char *name, int c, void *ptr,
|
|||
return (NULL);
|
||||
if ((np->name = strsave(name)) == NULL) return (NULL);
|
||||
np->ptr = ptr;
|
||||
np->next = hashtab[hashval];
|
||||
return(hashtab[hashval] = np);
|
||||
np->next = dict->hashtab[hashval];
|
||||
return(dict->hashtab[hashval] = np);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* destroy a hash table, freeing associated memory */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
void *HashKill(struct hashlist **hashtab, int hashsize)
|
||||
void *HashKill(struct hashdict *dict)
|
||||
{
|
||||
struct hashlist *np, *p;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < hashsize; i++) {
|
||||
for (p = hashtab[i]; p != NULL; ) {
|
||||
if (dict->hashtab == NULL) return; // Hash not initialized
|
||||
|
||||
for (i = 0; i < dict->hashsize; i++) {
|
||||
for (p = dict->hashtab[i]; p != NULL; ) {
|
||||
np = p->next;
|
||||
FREE(p->name);
|
||||
FREE(p);
|
||||
p = np;
|
||||
}
|
||||
}
|
||||
FREE(dict->hashtab);
|
||||
dict->hashtab = NULL;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
|
@ -327,14 +333,13 @@ void *HashKill(struct hashlist **hashtab, int hashsize)
|
|||
/* to the new hash entry. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
struct hashlist *HashInstall(char *name,
|
||||
struct hashlist **hashtab, int hashsize)
|
||||
struct hashlist *HashInstall(char *name, struct hashdict *dict)
|
||||
{
|
||||
struct hashlist *np;
|
||||
unsigned long hashval;
|
||||
|
||||
hashval = (*hashfunc)(name,hashsize);
|
||||
for (np = hashtab[hashval]; np != NULL; np = np->next)
|
||||
hashval = (*hashfunc)(name, dict->hashsize);
|
||||
for (np = dict->hashtab[hashval]; np != NULL; np = np->next)
|
||||
if ((*matchfunc)(name, np->name)) return (np); /* match found in hash table */
|
||||
|
||||
/* not in table, so install it */
|
||||
|
|
@ -342,27 +347,27 @@ struct hashlist *HashInstall(char *name,
|
|||
return (NULL);
|
||||
if ((np->name = strsave(name)) == NULL) return (NULL);
|
||||
np->ptr = NULL;
|
||||
np->next = hashtab[hashval];
|
||||
return(hashtab[hashval] = np);
|
||||
np->next = dict->hashtab[hashval];
|
||||
return(dict->hashtab[hashval] = np);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* frees a hash table entry, (but not the 'ptr' field) */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
void HashDelete(char *name, struct hashlist **hashtab, int hashsize)
|
||||
void HashDelete(char *name, struct hashdict *dict)
|
||||
{
|
||||
unsigned long hashval;
|
||||
struct hashlist *np;
|
||||
struct hashlist *np2;
|
||||
|
||||
hashval = (*hashfunc)(name, hashsize);
|
||||
np = hashtab[hashval];
|
||||
hashval = (*hashfunc)(name, dict->hashsize);
|
||||
np = dict->hashtab[hashval];
|
||||
if (np == NULL) return;
|
||||
|
||||
if ((*matchfunc)(name, np->name)) {
|
||||
/* it is the first element in the list */
|
||||
hashtab[hashval] = np->next;
|
||||
dict->hashtab[hashval] = np->next;
|
||||
FREE(np->name);
|
||||
FREE(np);
|
||||
return;
|
||||
|
|
@ -385,19 +390,19 @@ void HashDelete(char *name, struct hashlist **hashtab, int hashsize)
|
|||
/* HashDelete with additional integer value matching */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
void HashIntDelete(char *name, int value, struct hashlist **hashtab, int hashsize)
|
||||
void HashIntDelete(char *name, int value, struct hashdict *dict)
|
||||
{
|
||||
unsigned long hashval;
|
||||
struct hashlist *np;
|
||||
struct hashlist *np2;
|
||||
|
||||
hashval = (*hashfunc)(name, hashsize);
|
||||
np = hashtab[hashval];
|
||||
hashval = (*hashfunc)(name, dict->hashsize);
|
||||
np = dict->hashtab[hashval];
|
||||
if (np == NULL) return;
|
||||
|
||||
if ((*matchintfunc)(name, np->name, value, (int)(*((int *)np->ptr)))) {
|
||||
/* it is the first element in the list */
|
||||
hashtab[hashval] = np->next;
|
||||
dict->hashtab[hashval] = np->next;
|
||||
FREE(np->name);
|
||||
FREE(np);
|
||||
return;
|
||||
|
|
@ -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 */
|
||||
static struct hashlist *hashfirstptr;
|
||||
|
||||
void *HashNext(struct hashlist **hashtab, int hashsize)
|
||||
/* returns 'ptr' field of next element, NULL when done */
|
||||
void *HashNext(struct hashdict *dict)
|
||||
{
|
||||
if (hashfirstptr != NULL && hashfirstptr->next != NULL) {
|
||||
hashfirstptr = hashfirstptr->next;
|
||||
return(hashfirstptr->ptr);
|
||||
}
|
||||
while (hashfirstindex < hashsize) {
|
||||
if ((hashfirstptr = hashtab[hashfirstindex++]) != NULL) {
|
||||
return(hashfirstptr->ptr);
|
||||
}
|
||||
}
|
||||
hashfirstindex = 0;
|
||||
hashfirstptr = NULL;
|
||||
return(NULL);
|
||||
if (dict->hashfirstptr != NULL && dict->hashfirstptr->next != NULL) {
|
||||
dict->hashfirstptr = dict->hashfirstptr->next;
|
||||
return(dict->hashfirstptr->ptr);
|
||||
}
|
||||
while (dict->hashfirstindex < dict->hashsize) {
|
||||
if ((dict->hashfirstptr = dict->hashtab[dict->hashfirstindex++]) != NULL) {
|
||||
return(dict->hashfirstptr->ptr);
|
||||
}
|
||||
}
|
||||
|
||||
dict->hashfirstindex = 0;
|
||||
dict->hashfirstptr = NULL;
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
void *HashFirst(struct hashlist **hashtab, int hashsize)
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Hash key iterator setup */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
void *HashFirst(struct hashdict *dict)
|
||||
{
|
||||
hashfirstindex = 0;
|
||||
hashfirstptr = NULL;
|
||||
return(HashNext(hashtab,hashsize));
|
||||
dict->hashfirstindex = 0;
|
||||
dict->hashfirstptr = NULL;
|
||||
return HashNext(dict);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
44
base/hash.h
44
base/hash.h
|
|
@ -7,38 +7,44 @@ struct hashlist {
|
|||
struct hashlist *next;
|
||||
};
|
||||
|
||||
extern void InitializeHashTable(struct hashlist **tab, int size);
|
||||
extern int RecurseHashTable(struct hashlist **hashtab, int hashsize,
|
||||
struct hashdict {
|
||||
int hashsize;
|
||||
int hashfirstindex;
|
||||
struct hashlist *hashfirstptr;
|
||||
struct hashlist **hashtab;
|
||||
};
|
||||
|
||||
|
||||
extern void InitializeHashTable(struct hashdict *dict, int size);
|
||||
extern int RecurseHashTable(struct hashdict *dict,
|
||||
int (*func)(struct hashlist *elem));
|
||||
extern int RecurseHashTableValue(struct hashlist **hashtab, int hashsize,
|
||||
extern int RecurseHashTableValue(struct hashdict *dict,
|
||||
int (*func)(struct hashlist *elem, int), int);
|
||||
extern struct nlist *RecurseHashTablePointer(struct hashlist **hashtab,
|
||||
int hashsize, struct nlist *(*func)(struct hashlist *elem,
|
||||
void *), void *pointer);
|
||||
extern struct nlist *RecurseHashTablePointer(struct hashdict *dict,
|
||||
struct nlist *(*func)(struct hashlist *elem, void *),
|
||||
void *pointer);
|
||||
extern void HashDelete(char *name, struct hashdict *dict);
|
||||
extern void HashIntDelete(char *name, int value, struct hashdict *dict);
|
||||
|
||||
|
||||
extern int CountHashTableEntries(struct hashlist *p);
|
||||
extern int CountHashTableBinsUsed(struct hashlist *p);
|
||||
extern void HashDelete(char *name, struct hashlist **hashtab, int hashsize);
|
||||
extern void HashIntDelete(char *name, int value, struct hashlist **hashtab,
|
||||
int hashsize);
|
||||
|
||||
/* these functions return a pointer to a hash list element */
|
||||
extern struct hashlist *HashInstall(char *name, struct hashlist **hashtab,
|
||||
int hashsize);
|
||||
extern struct hashlist *HashInstall(char *name, struct hashdict *dict);
|
||||
extern struct hashlist *HashPtrInstall(char *name, void *ptr,
|
||||
struct hashlist **hashtab, int hashsize);
|
||||
struct hashdict *dict);
|
||||
extern struct hashlist *HashIntPtrInstall(char *name, int value, void *ptr,
|
||||
struct hashlist **hashtab, int hashsize);
|
||||
struct hashdict *dict);
|
||||
extern struct hashlist *HashInt2PtrInstall(char *name, int c, void *ptr,
|
||||
struct hashlist **hashtab, int hashsize);
|
||||
struct hashdict *dict);
|
||||
|
||||
/* these functions return the ->ptr field of a struct hashlist */
|
||||
extern void *HashLookup(char *s, struct hashlist **hashtab, int hashsize);
|
||||
extern void *HashIntLookup(char *s, int i, struct hashlist **hashtab, int hashsize);
|
||||
extern void *HashInt2Lookup(char *s, int c, struct hashlist **hashtab, int hashsize);
|
||||
extern void *HashFirst(struct hashlist **hashtab, int hashsize);
|
||||
extern void *HashNext(struct hashlist **hashtab, int hashsize);
|
||||
extern void *HashLookup(char *s, struct hashdict *dict);
|
||||
extern void *HashIntLookup(char *s, int i, struct hashdict *dict);
|
||||
extern void *HashInt2Lookup(char *s, int c, struct hashdict *dict);
|
||||
extern void *HashFirst(struct hashdict *dict);
|
||||
extern void *HashNext(struct hashdict *dict);
|
||||
|
||||
extern unsigned long hashnocase(char *s, int hashsize);
|
||||
extern unsigned long hash(char *s, int hashsize);
|
||||
|
|
|
|||
|
|
@ -3319,7 +3319,7 @@ int PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print)
|
|||
if (vl2->type == PROP_ENDLIST) break;
|
||||
if (vl2 == NULL) continue;
|
||||
if (vl2->key == NULL) continue;
|
||||
kl2 = (struct property *)HashLookup(vl2->key, tc2->proptab, OBJHASHSIZE);
|
||||
kl2 = (struct property *)HashLookup(vl2->key, &(tc2->propdict));
|
||||
if (kl2 != NULL) break; // Property is required
|
||||
else if ((*matchfunc)(vl2->key, "M")) {
|
||||
if (vl2->type == PROP_INTEGER)
|
||||
|
|
@ -3344,7 +3344,7 @@ int PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print)
|
|||
if (vl1->type == PROP_ENDLIST) break;
|
||||
if (vl1 == NULL) continue;
|
||||
if (vl1->key == NULL) continue;
|
||||
kl1 = (struct property *)HashLookup(vl1->key, tc1->proptab, OBJHASHSIZE);
|
||||
kl1 = (struct property *)HashLookup(vl1->key, &(tc1->propdict));
|
||||
if (kl1 != NULL) break; // Property is required
|
||||
else if ((*matchfunc)(vl1->key, "M")) {
|
||||
if (vl1->type == PROP_INTEGER)
|
||||
|
|
@ -3369,7 +3369,7 @@ int PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print)
|
|||
if (vl1->key == NULL) continue;
|
||||
|
||||
/* Check if this is a "property of interest". */
|
||||
kl1 = (struct property *)HashLookup(vl1->key, tc1->proptab, OBJHASHSIZE);
|
||||
kl1 = (struct property *)HashLookup(vl1->key, &(tc1->propdict));
|
||||
if (kl1 == NULL) continue;
|
||||
|
||||
/* Find the matching property in vl2. With luck, they're in order. */
|
||||
|
|
@ -3386,7 +3386,7 @@ int PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print)
|
|||
if (vl2->key == NULL) continue;
|
||||
|
||||
/* Both device classes must agree on the properties to compare */
|
||||
kl2 = (struct property *)HashLookup(vl2->key, tc2->proptab, OBJHASHSIZE);
|
||||
kl2 = (struct property *)HashLookup(vl2->key, &(tc2->propdict));
|
||||
if (kl2 == NULL) continue;
|
||||
|
||||
/* Watch out for uninitialized entries in cell def */
|
||||
|
|
@ -4488,7 +4488,7 @@ int reorderpins(struct hashlist *p, int file)
|
|||
ob->node = nodes[i];
|
||||
ob->name = names[i];
|
||||
}
|
||||
HashPtrInstall(ob->name, ob, ptr->objtab, OBJHASHSIZE);
|
||||
HashPtrInstall(ob->name, ob, &(ptr->objdict));
|
||||
ob = ob->next;
|
||||
names[i] = NULL;
|
||||
}
|
||||
|
|
@ -4566,12 +4566,11 @@ struct nlist *addproxies(struct hashlist *p, void *clientdata)
|
|||
lob = obn;
|
||||
|
||||
// Hash the new pin record for "LookupObject()"
|
||||
HashPtrInstall(obn->name, obn, ptr->objtab, OBJHASHSIZE);
|
||||
HashPtrInstall(obn->name, obn, &(ptr->objdict));
|
||||
|
||||
if (tob == tc->cell) {
|
||||
// Rehash the instance in insttab
|
||||
HashPtrInstall(firstpin->instance.name, firstpin,
|
||||
ptr->insttab, OBJHASHSIZE);
|
||||
// Rehash the instance in instdict
|
||||
HashPtrInstall(firstpin->instance.name, firstpin, &(ptr->instdict));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -4595,7 +4594,7 @@ struct nlist *addproxies(struct hashlist *p, void *clientdata)
|
|||
obn->next = NULL;
|
||||
lob->next = obn;
|
||||
lob = obn;
|
||||
HashPtrInstall(obn->name, obn, ptr->objtab, OBJHASHSIZE);
|
||||
HashPtrInstall(obn->name, obn, &(ptr->objdict));
|
||||
}
|
||||
|
||||
// We messed with the node name list, so have to re-cache them
|
||||
|
|
@ -4888,7 +4887,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2)
|
|||
ob1 = obn;
|
||||
hasproxy1 = 1;
|
||||
|
||||
HashPtrInstall(obn->name, obn, tc1->objtab, OBJHASHSIZE);
|
||||
HashPtrInstall(obn->name, obn, &(tc1->objdict));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4946,7 +4945,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2)
|
|||
ob2 = obn;
|
||||
hasproxy2 = 1;
|
||||
|
||||
HashPtrInstall(obn->name, obn, tc2->objtab, OBJHASHSIZE);
|
||||
HashPtrInstall(obn->name, obn, &(tc2->objdict));
|
||||
}
|
||||
|
||||
else if (ob1 != NULL && ob1->type == PORT) {
|
||||
|
|
|
|||
106
base/netgen.c
106
base/netgen.c
|
|
@ -54,7 +54,7 @@ extern int errno; /* Defined in stdlib.h */
|
|||
static char staticstrings[MAX_STATIC_STRINGS][200];
|
||||
static int laststring;
|
||||
|
||||
extern struct hashlist **spiceparams; /* From spice.c */
|
||||
extern struct hashdict spiceparams; /* From spice.c */
|
||||
|
||||
char *Str(char *format, ...)
|
||||
{
|
||||
|
|
@ -188,18 +188,15 @@ int TokGetValue(char *estr, struct nlist *parent, int glob, double *dval)
|
|||
|
||||
if (glob == TRUE) {
|
||||
/* Check global parameters */
|
||||
if (spiceparams != NULL) {
|
||||
kl = (struct property *)HashLookup(estr,
|
||||
spiceparams, OBJHASHSIZE);
|
||||
if (kl != NULL) {
|
||||
result = ConvertStringToFloat(kl->pdefault.string, dval);
|
||||
return ((result == 0) ? -1 : 1);
|
||||
}
|
||||
kl = (struct property *)HashLookup(estr, &spiceparams);
|
||||
if (kl != NULL) {
|
||||
result = ConvertStringToFloat(kl->pdefault.string, dval);
|
||||
return ((result == 0) ? -1 : 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check local parameters */
|
||||
kl = (struct property *)HashLookup(estr, parent->proptab, OBJHASHSIZE);
|
||||
kl = (struct property *)HashLookup(estr, &(parent->propdict));
|
||||
if (kl != NULL) {
|
||||
switch(kl->type) {
|
||||
case PROP_STRING:
|
||||
|
|
@ -834,19 +831,17 @@ PropertyDelete(char *name, int fnum, char *key)
|
|||
|
||||
/* key == NULL means delete all properties. */
|
||||
|
||||
RecurseHashTable(tc->proptab, OBJHASHSIZE, freeprop);
|
||||
HashKill(tc->proptab, OBJHASHSIZE);
|
||||
FREE(tc->proptab);
|
||||
tc->proptab = (struct hashlist **)CALLOC(OBJHASHSIZE,
|
||||
sizeof(struct hashlist *));
|
||||
RecurseHashTable(&(tc->propdict), freeprop);
|
||||
HashKill(&(tc->propdict));
|
||||
InitializeHashTable(&(tc->propdict), OBJHASHSIZE);
|
||||
}
|
||||
else {
|
||||
kl = (struct property *)HashLookup(key, tc->proptab, OBJHASHSIZE);
|
||||
kl = (struct property *)HashLookup(key, &(tc->propdict));
|
||||
if (kl != NULL) {
|
||||
if (kl->type == PROP_STRING || kl->type == PROP_EXPRESSION)
|
||||
FREE(kl->pdefault.string);
|
||||
FREE(kl->key);
|
||||
HashDelete(key, tc->proptab, OBJHASHSIZE);
|
||||
HashDelete(key, &(tc->propdict));
|
||||
}
|
||||
else {
|
||||
Printf("No property %s found for device %s\n", key, name);
|
||||
|
|
@ -879,7 +874,7 @@ PropertyTolerance(char *name, int fnum, char *key, int ival, double dval)
|
|||
return -1;
|
||||
}
|
||||
|
||||
kl = (struct property *)HashLookup(key, tc->proptab, OBJHASHSIZE);
|
||||
kl = (struct property *)HashLookup(key, &(tc->propdict));
|
||||
if (kl == NULL) {
|
||||
Printf("No property %s found for device %s\n", key, name);
|
||||
return -1;
|
||||
|
|
@ -900,6 +895,40 @@ PropertyTolerance(char *name, int fnum, char *key, int ival, double dval)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Set the merge type of a property in the master cell record. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
int
|
||||
PropertyMerge(char *name, int fnum, char *key, int merge_type)
|
||||
{
|
||||
struct property *kl = NULL;
|
||||
struct nlist *tc;
|
||||
int result;
|
||||
|
||||
if ((fnum == -1) && (Circuit1 != NULL) && (Circuit2 != NULL)) {
|
||||
result = PropertyMerge(name, Circuit1->file, key, merge_type);
|
||||
result = PropertyMerge(name, Circuit2->file, key, merge_type);
|
||||
return result;
|
||||
}
|
||||
|
||||
tc = LookupCellFile(name, fnum);
|
||||
if (tc == NULL) {
|
||||
Printf("No device %s found for PropertyTolerance()\n", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
kl = (struct property *)HashLookup(key, &(tc->propdict));
|
||||
if (kl == NULL) {
|
||||
Printf("No property %s found for device %s\n", key, name);
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
kl->merge = merge_type;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Add a new value property to the indicated cell */
|
||||
/* Value properties are used for resistors and capacitors in SPICE */
|
||||
|
|
@ -923,18 +952,18 @@ struct property *PropertyValue(char *name, int fnum, char *key,
|
|||
tc = LookupCellFile(name, fnum);
|
||||
if (tc == NULL)
|
||||
Printf("No device %s found for PropertyValue()\n", name);
|
||||
else if ((kl = (struct property *)HashLookup(key, tc->proptab,
|
||||
OBJHASHSIZE)) != NULL) {
|
||||
else if ((kl = (struct property *)HashLookup(key, &(tc->propdict))) != NULL) {
|
||||
Printf("Device %s already has property named \"%s\"\n", name, key);
|
||||
}
|
||||
else {
|
||||
kl = NewProperty();
|
||||
kl->key = strsave(key);
|
||||
kl->idx = 0;
|
||||
kl->merge = MERGE_NONE;
|
||||
kl->type = PROP_VALUE;
|
||||
kl->slop.dval = slop;
|
||||
kl->pdefault.dval = pdefault;
|
||||
HashPtrInstall(kl->key, kl, tc->proptab, OBJHASHSIZE);
|
||||
HashPtrInstall(kl->key, kl, &(tc->propdict));
|
||||
}
|
||||
return kl;
|
||||
}
|
||||
|
|
@ -958,18 +987,18 @@ struct property *PropertyDouble(char *name, int fnum, char *key,
|
|||
tc = LookupCellFile(name, fnum);
|
||||
if (tc == NULL)
|
||||
Printf("No device %s found for PropertyDouble()\n", name);
|
||||
else if ((kl = (struct property *)HashLookup(key, tc->proptab,
|
||||
OBJHASHSIZE)) != NULL) {
|
||||
else if ((kl = (struct property *)HashLookup(key, &(tc->propdict))) != NULL) {
|
||||
Printf("Device %s already has property named \"%s\"\n", name, key);
|
||||
}
|
||||
else {
|
||||
kl = NewProperty();
|
||||
kl->key = strsave(key);
|
||||
kl->idx = 0;
|
||||
kl->merge = MERGE_NONE;
|
||||
kl->type = PROP_DOUBLE;
|
||||
kl->slop.dval = slop;
|
||||
kl->pdefault.dval = pdefault;
|
||||
HashPtrInstall(kl->key, kl, tc->proptab, OBJHASHSIZE);
|
||||
HashPtrInstall(kl->key, kl, &(tc->propdict));
|
||||
}
|
||||
return kl;
|
||||
}
|
||||
|
|
@ -991,18 +1020,18 @@ struct property *PropertyInteger(char *name, int fnum, char *key,
|
|||
tc = LookupCellFile(name, fnum);
|
||||
if (tc == NULL)
|
||||
Printf("No device %s found for PropertyInteger()\n", name);
|
||||
else if ((kl = (struct property *)HashLookup(key, tc->proptab,
|
||||
OBJHASHSIZE)) != NULL) {
|
||||
else if ((kl = (struct property *)HashLookup(key, &(tc->propdict))) != NULL) {
|
||||
Printf("Device %s already has property named \"%s\"\n", name, key);
|
||||
}
|
||||
else {
|
||||
kl = NewProperty();
|
||||
kl->key = strsave(key);
|
||||
kl->idx = 0;
|
||||
kl->merge = MERGE_NONE;
|
||||
kl->type = PROP_INTEGER;
|
||||
kl->slop.ival = slop;
|
||||
kl->pdefault.ival = pdefault;
|
||||
HashPtrInstall(kl->key, kl, tc->proptab, OBJHASHSIZE);
|
||||
HashPtrInstall(kl->key, kl, &(tc->propdict));
|
||||
}
|
||||
return kl;
|
||||
}
|
||||
|
|
@ -1024,21 +1053,21 @@ struct property *PropertyString(char *name, int fnum, char *key, int range,
|
|||
tc = LookupCellFile(name, fnum);
|
||||
if (tc == NULL)
|
||||
Printf("No device %s found for PropertyString()\n", name);
|
||||
else if ((kl = (struct property *)HashLookup(key, tc->proptab,
|
||||
OBJHASHSIZE)) != NULL) {
|
||||
else if ((kl = (struct property *)HashLookup(key, &(tc->propdict))) != NULL) {
|
||||
Printf("Device %s already has property named \"%s\"\n", name, key);
|
||||
}
|
||||
else {
|
||||
kl = NewProperty();
|
||||
kl->key = strsave(key);
|
||||
kl->idx = 0;
|
||||
kl->merge = MERGE_NONE;
|
||||
kl->type = PROP_STRING;
|
||||
kl->slop.ival = (range >= 0) ? range : 0;
|
||||
if (pdefault != NULL)
|
||||
kl->pdefault.string = strsave(pdefault);
|
||||
else
|
||||
kl->pdefault.string = NULL;
|
||||
HashPtrInstall(kl->key, kl, tc->proptab, OBJHASHSIZE);
|
||||
HashPtrInstall(kl->key, kl, &(tc->propdict));
|
||||
}
|
||||
return kl;
|
||||
}
|
||||
|
|
@ -1975,7 +2004,7 @@ struct objlist *LinkProperties(char *model, struct keyvalue *topptr)
|
|||
/* If there is a matching cell, make sure that the property */
|
||||
/* key exists. If not, create it and flag a warning. */
|
||||
|
||||
kl = (struct property *)HashLookup(newkv->key, cell->proptab, OBJHASHSIZE);
|
||||
kl = (struct property *)HashLookup(newkv->key, &(cell->propdict));
|
||||
if (kl == NULL) {
|
||||
/* Ideally, for devices, one should check against all */
|
||||
/* known standard properties. That's a pain, so */
|
||||
|
|
@ -1988,10 +2017,11 @@ struct objlist *LinkProperties(char *model, struct keyvalue *topptr)
|
|||
kl = NewProperty();
|
||||
kl->key = strsave(newkv->key);
|
||||
kl->idx = 0;
|
||||
kl->merge = MERGE_NONE;
|
||||
kl->type = PROP_STRING;
|
||||
kl->slop.ival = 0;
|
||||
kl->pdefault.string = NULL;
|
||||
HashPtrInstall(kl->key, kl, cell->proptab, OBJHASHSIZE);
|
||||
HashPtrInstall(kl->key, kl, &(cell->propdict));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2183,7 +2213,7 @@ struct nlist *resolveprops(struct hashlist *p, void *clientdata)
|
|||
for (i = 0;; i++) {
|
||||
vl = &(ob->instance.props[i]);
|
||||
if (vl->type == PROP_ENDLIST) break;
|
||||
prop = (struct property *)HashLookup(vl->key, tc->proptab, OBJHASHSIZE);
|
||||
prop = (struct property *)HashLookup(vl->key, &(tc->propdict));
|
||||
|
||||
/* Warning: prop should never be null, but condition */
|
||||
/* should be handled. */
|
||||
|
|
@ -2238,7 +2268,7 @@ void ResolveProperties(char *name1, int file1, char *name2, int file2)
|
|||
/* index. If the property does not exist in the second cell, then */
|
||||
/* create it. */
|
||||
|
||||
kl1 = (struct property *)HashFirst(tp1->proptab, OBJHASHSIZE);
|
||||
kl1 = (struct property *)HashFirst(&(tp1->propdict));
|
||||
/* If indexes are not zero, then properties have already been matched. */
|
||||
if (kl1 == NULL) return; /* Cell has no properties */
|
||||
if (kl1->idx != 0) return;
|
||||
|
|
@ -2247,7 +2277,7 @@ void ResolveProperties(char *name1, int file1, char *name2, int file2)
|
|||
while (kl1 != NULL) {
|
||||
kl1->idx = i;
|
||||
|
||||
kl2 = (struct property *)HashLookup(kl1->key, tp2->proptab, OBJHASHSIZE);
|
||||
kl2 = (struct property *)HashLookup(kl1->key, &(tp2->propdict));
|
||||
if (kl2 == NULL) {
|
||||
/* No such property in tp2 */
|
||||
switch (kl1->type) {
|
||||
|
|
@ -2270,16 +2300,16 @@ void ResolveProperties(char *name1, int file1, char *name2, int file2)
|
|||
}
|
||||
}
|
||||
if (kl2 != NULL) kl2->idx = i;
|
||||
kl1 = (struct property *)HashNext(tp1->proptab, OBJHASHSIZE);
|
||||
kl1 = (struct property *)HashNext(&(tp1->propdict));
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Now check tp2 for properties not in tp1 */
|
||||
|
||||
kl2 = (struct property *)HashFirst(tp2->proptab, OBJHASHSIZE);
|
||||
kl2 = (struct property *)HashFirst(&(tp2->propdict));
|
||||
|
||||
while (kl2 != NULL) {
|
||||
kl1 = (struct property *)HashLookup(kl2->key, tp1->proptab, OBJHASHSIZE);
|
||||
kl1 = (struct property *)HashLookup(kl2->key, &(tp1->propdict));
|
||||
if (kl1 == NULL) {
|
||||
/* No such property in tp1 */
|
||||
switch (kl2->type) {
|
||||
|
|
@ -2302,7 +2332,7 @@ void ResolveProperties(char *name1, int file1, char *name2, int file2)
|
|||
}
|
||||
}
|
||||
if (kl1 != NULL) kl1->idx = i;
|
||||
kl2 = (struct property *)HashNext(tp1->proptab, OBJHASHSIZE);
|
||||
kl2 = (struct property *)HashNext(&(tp1->propdict));
|
||||
i++;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ extern struct property *PropertyString(char *name, int fnum, char *key,
|
|||
extern int PropertyDelete(char *name, int fnum, char *key);
|
||||
extern int PropertyTolerance(char *name, int fnum, char *key, int ival,
|
||||
double dval);
|
||||
extern int PropertyMerge(char *name, int fnum, char *key, int merge_type);
|
||||
extern void ResolveProperties(char *name1, int file1, char *name2, int file2);
|
||||
extern void CopyProperties(struct objlist *obj_to, struct objlist *obj_from);
|
||||
extern int PromoteProperty(struct property *, struct valuelist *);
|
||||
|
|
|
|||
|
|
@ -251,18 +251,18 @@ void PrintMemoryStats(void)
|
|||
|
||||
|
||||
#define CELLHASHSIZE 1000
|
||||
static struct hashlist *cell_hashtab[CELLHASHSIZE];
|
||||
static struct hashdict cell_dict;
|
||||
|
||||
void InitCellHashTable(void)
|
||||
{
|
||||
hashfunc = hash;
|
||||
matchfunc = match;
|
||||
InitializeHashTable(cell_hashtab, CELLHASHSIZE);
|
||||
hashfunc = hash;
|
||||
matchfunc = match;
|
||||
InitializeHashTable(&cell_dict, CELLHASHSIZE);
|
||||
}
|
||||
|
||||
struct nlist *LookupCell(char *s)
|
||||
{
|
||||
return((struct nlist *)HashLookup(s, cell_hashtab, CELLHASHSIZE));
|
||||
return((struct nlist *)HashLookup(s, &cell_dict));
|
||||
}
|
||||
|
||||
/* Similar hash lookup to the above, but will check if the matching */
|
||||
|
|
@ -274,7 +274,7 @@ struct nlist *LookupCellFile(char *s, int f)
|
|||
struct nlist *he;
|
||||
|
||||
if (f == -1) return LookupCell(s);
|
||||
return HashIntLookup(s, f, cell_hashtab, CELLHASHSIZE);
|
||||
return HashIntLookup(s, f, &cell_dict);
|
||||
}
|
||||
|
||||
struct nlist *InstallInCellHashTable(char *name, int fnum)
|
||||
|
|
@ -291,34 +291,23 @@ struct nlist *InstallInCellHashTable(char *name, int fnum)
|
|||
if (p == NULL) return(NULL);
|
||||
if ((p->name = strsave(name)) == NULL) goto fail;
|
||||
p->file = fnum;
|
||||
if ((p->objtab = (struct hashlist **)CALLOC(OBJHASHSIZE,
|
||||
sizeof(struct hashlist *))) == NULL) goto fail;
|
||||
if ((p->insttab = (struct hashlist **)CALLOC(OBJHASHSIZE,
|
||||
sizeof(struct hashlist *))) == NULL) goto fail;
|
||||
if ((p->proptab = (struct hashlist **)CALLOC(OBJHASHSIZE,
|
||||
sizeof(struct hashlist *))) == NULL) goto fail;
|
||||
InitializeHashTable(&(p->objdict), OBJHASHSIZE);
|
||||
InitializeHashTable(&(p->instdict), OBJHASHSIZE);
|
||||
InitializeHashTable(&(p->propdict), OBJHASHSIZE);
|
||||
p->permutes = NULL;
|
||||
|
||||
// Hash size 0 indicates to hash function that no binning is being done
|
||||
p->classhash = (*hashfunc)(name, 0);
|
||||
|
||||
ptr = HashIntPtrInstall(name, fnum, p, cell_hashtab, CELLHASHSIZE);
|
||||
ptr = HashIntPtrInstall(name, fnum, p, &cell_dict);
|
||||
if (ptr == NULL) return(NULL);
|
||||
return(p);
|
||||
fail:
|
||||
if (p->name != NULL) FREE(p->name);
|
||||
if (p->objtab != NULL) {
|
||||
HashKill(p->objtab, OBJHASHSIZE);
|
||||
FREE(p->objtab);
|
||||
}
|
||||
if (p->insttab != NULL) {
|
||||
HashKill(p->insttab, OBJHASHSIZE);
|
||||
FREE(p->insttab);
|
||||
}
|
||||
if (p->proptab != NULL) {
|
||||
HashKill(p->proptab, OBJHASHSIZE);
|
||||
FREE(p->proptab);
|
||||
}
|
||||
HashKill(&(p->objdict));
|
||||
HashKill(&(p->instdict));
|
||||
RecurseHashTable(&(p->propdict), freeprop);
|
||||
HashKill(&(p->propdict));
|
||||
FREE(p);
|
||||
return(NULL);
|
||||
}
|
||||
|
|
@ -341,9 +330,9 @@ void CellRehash(char *name, char *newname, int file)
|
|||
FREE(tp->name);
|
||||
tp->name = strsave(newname);
|
||||
|
||||
ptr = HashIntPtrInstall(newname, file, (void *)tp, cell_hashtab, CELLHASHSIZE);
|
||||
ptr = HashIntPtrInstall(newname, file, (void *)tp, &cell_dict);
|
||||
if (ptr != NULL)
|
||||
HashIntDelete(name, file, cell_hashtab, CELLHASHSIZE);
|
||||
HashIntDelete(name, file, &cell_dict);
|
||||
|
||||
// Change the classhash to reflect the new name
|
||||
tp->classhash = (*hashfunc)(newname, 0);
|
||||
|
|
@ -365,7 +354,7 @@ int deleteclass(struct hashlist *p, int file)
|
|||
nob = ob->next;
|
||||
if ((ob->type == FIRSTPIN) && (ob->model.class != NULL)) {
|
||||
if ((*matchfunc)(ob->model.class, OldCell->name)) {
|
||||
HashDelete(ob->instance.name, ptr->insttab, OBJHASHSIZE);
|
||||
HashDelete(ob->instance.name, &(ptr->instdict));
|
||||
while (1) {
|
||||
FreeObjectAndHash(ob, ptr);
|
||||
ob = nob;
|
||||
|
|
@ -482,22 +471,13 @@ void CellDelete(char *name, int fnum)
|
|||
return;
|
||||
}
|
||||
|
||||
HashIntDelete(name, fnum, cell_hashtab, CELLHASHSIZE);
|
||||
HashIntDelete(name, fnum, &cell_dict);
|
||||
/* now make sure that we free all the fields of the nlist struct */
|
||||
if (tp->name != NULL) FREE(tp->name);
|
||||
if (tp->objtab != NULL) {
|
||||
HashKill(tp->objtab, OBJHASHSIZE);
|
||||
FREE(tp->objtab);
|
||||
}
|
||||
if (tp->insttab != NULL) {
|
||||
HashKill(tp->insttab, OBJHASHSIZE);
|
||||
FREE(tp->insttab);
|
||||
}
|
||||
if (tp->proptab != NULL) {
|
||||
RecurseHashTable(tp->proptab, OBJHASHSIZE, freeprop);
|
||||
HashKill(tp->proptab, OBJHASHSIZE);
|
||||
FREE(tp->proptab);
|
||||
}
|
||||
HashKill(&(tp->objdict));
|
||||
HashKill(&(tp->instdict));
|
||||
RecurseHashTable(&(tp->propdict), freeprop);
|
||||
HashKill(&(tp->propdict));
|
||||
FreeNodeNames(tp);
|
||||
ob = tp->cell;
|
||||
while (ob != NULL) {
|
||||
|
|
@ -548,8 +528,8 @@ void PrintCellHashTable(int full, int filenum)
|
|||
|
||||
TopFile = filenum;
|
||||
|
||||
bins = RecurseHashTable(cell_hashtab, CELLHASHSIZE, CountHashTableBinsUsed);
|
||||
total = RecurseHashTable(cell_hashtab, CELLHASHSIZE, CountHashTableEntries);
|
||||
bins = RecurseHashTable(&cell_dict, CountHashTableBinsUsed);
|
||||
total = RecurseHashTable(&cell_dict, CountHashTableEntries);
|
||||
if (full != 2)
|
||||
Printf("Hash table: %d of %d bins used; %d cells total (%.2f per bin)\n",
|
||||
bins, CELLHASHSIZE, total, (bins == 0) ? 0 :
|
||||
|
|
@ -557,7 +537,7 @@ void PrintCellHashTable(int full, int filenum)
|
|||
|
||||
OldDebug = Debug;
|
||||
Debug = full;
|
||||
RecurseHashTable(cell_hashtab, CELLHASHSIZE, PrintCellHashTableElement);
|
||||
RecurseHashTable(&cell_dict, PrintCellHashTableElement);
|
||||
Debug = OldDebug;
|
||||
#ifndef TCL_NETGEN
|
||||
if (full == 2) Printf("\n");
|
||||
|
|
@ -566,12 +546,12 @@ void PrintCellHashTable(int full, int filenum)
|
|||
|
||||
struct nlist *FirstCell(void)
|
||||
{
|
||||
return((struct nlist *)HashFirst(cell_hashtab, CELLHASHSIZE));
|
||||
return((struct nlist *)HashFirst(&cell_dict));
|
||||
}
|
||||
|
||||
struct nlist *NextCell(void)
|
||||
{
|
||||
return((struct nlist *)HashNext(cell_hashtab, CELLHASHSIZE));
|
||||
return((struct nlist *)HashNext(&cell_dict));
|
||||
}
|
||||
|
||||
static int ClearDumpedElement(struct hashlist *np)
|
||||
|
|
@ -585,17 +565,17 @@ static int ClearDumpedElement(struct hashlist *np)
|
|||
|
||||
void ClearDumpedList(void)
|
||||
{
|
||||
RecurseHashTable(cell_hashtab, CELLHASHSIZE, ClearDumpedElement);
|
||||
RecurseHashTable(&cell_dict, ClearDumpedElement);
|
||||
}
|
||||
|
||||
int RecurseCellHashTable(int (*foo)(struct hashlist *np))
|
||||
{
|
||||
return RecurseHashTable(cell_hashtab, CELLHASHSIZE, foo);
|
||||
return RecurseHashTable(&cell_dict, foo);
|
||||
}
|
||||
|
||||
int RecurseCellFileHashTable(int (*foo)(struct hashlist *, int), int value)
|
||||
{
|
||||
return RecurseHashTableValue(cell_hashtab, CELLHASHSIZE, foo, value);
|
||||
return RecurseHashTableValue(&cell_dict, foo, value);
|
||||
}
|
||||
|
||||
/* Yet another version, passing one parameter that is a pointer */
|
||||
|
|
@ -603,7 +583,7 @@ int RecurseCellFileHashTable(int (*foo)(struct hashlist *, int), int value)
|
|||
struct nlist *RecurseCellHashTable2(struct nlist *(*foo)(struct hashlist *,
|
||||
void *), void *pointer)
|
||||
{
|
||||
return RecurseHashTablePointer(cell_hashtab, CELLHASHSIZE, foo, pointer);
|
||||
return RecurseHashTablePointer(&cell_dict, foo, pointer);
|
||||
}
|
||||
|
||||
/************************** WILD-CARD STUFF *******************************/
|
||||
|
|
@ -914,13 +894,13 @@ struct objlist *CopyObjList(struct objlist *oldlist)
|
|||
|
||||
struct objlist *LookupObject(char *name, struct nlist *WhichCell)
|
||||
{
|
||||
return((struct objlist *)HashLookup(name, WhichCell->objtab, OBJHASHSIZE));
|
||||
return((struct objlist *)HashLookup(name, &(WhichCell->objdict)));
|
||||
}
|
||||
|
||||
struct objlist *LookupInstance(char *name, struct nlist *WhichCell)
|
||||
/* searches for exact match of instance 'name' in cell 'WhichCell' */
|
||||
{
|
||||
return((struct objlist *)HashLookup(name, WhichCell->insttab, OBJHASHSIZE));
|
||||
return((struct objlist *)HashLookup(name, &(WhichCell->instdict)));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -939,7 +919,7 @@ void AddToCurrentCell(struct objlist *ob)
|
|||
|
||||
/* add to object hash table for this cell */
|
||||
if (CurrentCell != NULL) {
|
||||
HashPtrInstall(ob->name, ob, CurrentCell->objtab, OBJHASHSIZE);
|
||||
HashPtrInstall(ob->name, ob, &(CurrentCell->objdict));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -966,13 +946,13 @@ void AddToCurrentCellNoHash(struct objlist *ob)
|
|||
void AddInstanceToCurrentCell(struct objlist *ob)
|
||||
{
|
||||
/* add to instance hash table for this cell */
|
||||
HashPtrInstall(ob->instance.name, ob, CurrentCell->insttab, OBJHASHSIZE);
|
||||
HashPtrInstall(ob->instance.name, ob, &(CurrentCell->instdict));
|
||||
}
|
||||
|
||||
void FreeObject(struct objlist *ob)
|
||||
{
|
||||
/* This just frees the object record. Beware of pointer left */
|
||||
/* in the objtab hash table. Hash table records should be */
|
||||
/* in the objlist hash table. Hash table records should be */
|
||||
/* removed first. */
|
||||
|
||||
if (ob->name != NULL) FreeString(ob->name);
|
||||
|
|
@ -1013,7 +993,7 @@ void FreeObject(struct objlist *ob)
|
|||
|
||||
void FreeObjectAndHash(struct objlist *ob, struct nlist *ptr)
|
||||
{
|
||||
HashDelete(ob->name, ptr->objtab, OBJHASHSIZE);
|
||||
HashDelete(ob->name, &(ptr->objdict));
|
||||
FreeObject(ob);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,10 @@
|
|||
#ifndef _OBJLIST_H
|
||||
#define _OBJLIST_H
|
||||
|
||||
#ifndef _HASH_H
|
||||
#include "hash.h"
|
||||
#endif
|
||||
|
||||
#define SEPARATOR "/"
|
||||
#define INSTANCE_DELIMITER "#"
|
||||
#define PORT_DELIMITER "."
|
||||
|
|
@ -99,10 +103,22 @@ struct valuelist {
|
|||
|
||||
/* Part 3: Keys & Defaults (kept in the cell record as a hash table) */
|
||||
|
||||
#define MERGE_NONE 0 /* Property does not change when devices merge */
|
||||
#define MERGE_ADD 1 /* Properties sum with device merge */
|
||||
#define MERGE_ADD_CRIT 2 /* Properties sum with device merge */
|
||||
#define MERGE_PAR 3 /* Properties add in parallel with device merge */
|
||||
#define MERGE_PAR_CRIT 4 /* Properties add in parallel with device merge */
|
||||
|
||||
/* Note: A "critical" merge means that the property causes the number of */
|
||||
/* devices to change. e.g., transistor width is critical; transistor drain */
|
||||
/* area sums when devices are merged, but does not change the number of devices.*/
|
||||
/* More than one property can be critical. e.g., width and number of fingers. */
|
||||
|
||||
struct property {
|
||||
char *key; /* name of the property */
|
||||
unsigned char idx; /* index into valuelist */
|
||||
unsigned char type; /* string, integer, double, value, expression */
|
||||
unsigned char merge; /* how property changes when devices are merged */
|
||||
union {
|
||||
char *string;
|
||||
double dval;
|
||||
|
|
@ -172,9 +188,9 @@ struct nlist {
|
|||
unsigned long classhash; /* randomized hash value for cell class */
|
||||
struct Permutation *permutes; /* list of permuting pins */
|
||||
struct objlist *cell;
|
||||
struct hashlist **objtab; /* hash table of object names */
|
||||
struct hashlist **insttab; /* hash table of instance names */
|
||||
struct hashlist **proptab; /* hash table of property keys */
|
||||
struct hashdict objdict; /* hash table of object names */
|
||||
struct hashdict instdict; /* hash table of instance names */
|
||||
struct hashdict propdict; /* hash table of property keys */
|
||||
struct objlist **nodename_cache;
|
||||
long nodename_cache_maxnodenum; /* largest node number in cache */
|
||||
void *embedding; /* this will be cast to the appropriate data structure */
|
||||
|
|
|
|||
19
base/spice.c
19
base/spice.c
|
|
@ -40,7 +40,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
#include "print.h"
|
||||
|
||||
// Global storage for parameters from .PARAM
|
||||
struct hashlist **spiceparams;
|
||||
struct hashdict spiceparams;
|
||||
|
||||
void SpiceSubCell(struct nlist *tp, int IsSubCell)
|
||||
{
|
||||
|
|
@ -358,6 +358,12 @@ int renamepins(struct hashlist *p, int file)
|
|||
obp = ob;
|
||||
for (ob2 = tc->cell; ob2 != NULL; ob2 = ob2->next) {
|
||||
if (ob2->type != PORT) break;
|
||||
else if ((obp->type < FIRSTPIN) || (obp->type == FIRSTPIN && obp != ob)) {
|
||||
Fprintf(stderr, "Pin count mismatch between cell and instance of %s\n",
|
||||
tc->name);
|
||||
InputParseError(stderr);
|
||||
break;
|
||||
}
|
||||
if (!matchnocase(ob2->name, obp->name + strlen(obp->instance.name) + 1)) {
|
||||
// Printf("Cell %s pin correspondence: %s vs. %s\n",
|
||||
// tc->name, obp->name, ob2->name);
|
||||
|
|
@ -778,7 +784,7 @@ skip_ends:
|
|||
kl->type = PROP_STRING;
|
||||
kl->slop.ival = 0;
|
||||
kl->pdefault.string = strsave(eqptr + 1);
|
||||
HashPtrInstall(nexttok, kl, spiceparams, OBJHASHSIZE);
|
||||
HashPtrInstall(nexttok, kl, &spiceparams);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1844,8 +1850,7 @@ char *ReadSpiceTop(char *fname, int *fnum, int blackbox)
|
|||
matchintfunc = matchfilenocase;
|
||||
hashfunc = hashnocase;
|
||||
|
||||
spiceparams = (struct hashlist **)CALLOC(OBJHASHSIZE,
|
||||
sizeof(struct hashlist *));
|
||||
InitializeHashTable(&spiceparams, OBJHASHSIZE);
|
||||
|
||||
/* All spice files should start with a comment line, */
|
||||
/* but we won't depend upon it. Any comment line */
|
||||
|
|
@ -1857,10 +1862,8 @@ char *ReadSpiceTop(char *fname, int *fnum, int blackbox)
|
|||
// Cleanup
|
||||
while (CellStack != NULL) PopStack(&CellStack);
|
||||
|
||||
RecurseHashTable(spiceparams, OBJHASHSIZE, freeprop);
|
||||
HashKill(spiceparams, OBJHASHSIZE);
|
||||
FREE(spiceparams);
|
||||
spiceparams = NULL;
|
||||
RecurseHashTable(&spiceparams, freeprop);
|
||||
HashKill(&spiceparams);
|
||||
|
||||
// Important: If the file is a library, containing subcircuit
|
||||
// definitions but no components, then it needs to be registered
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
|
||||
#define XILINXHASHSIZE 99
|
||||
static long xilinxhashbase = 0xA00;
|
||||
static struct hashlist *xilinxnametab[XILINXHASHSIZE];
|
||||
static struct hashdict xilinxnamedict;
|
||||
static FILE *xilinxfile;
|
||||
|
||||
char *gndnet = "0";
|
||||
|
|
@ -156,7 +156,7 @@ Xilinx(cellname, filename)
|
|||
return;
|
||||
}
|
||||
ClearDumpedList();
|
||||
InitializeHashTable(xilinxnametab, XILINXHASHSIZE);
|
||||
InitializeHashTable(&xilinxnamedict, XILINXHASHSIZE);
|
||||
if (LookupCell(cellname) != NULL)
|
||||
xilinxCell(cellname);
|
||||
CloseFile(FileName);
|
||||
|
|
|
|||
2
defs.mak
2
defs.mak
|
|
@ -65,7 +65,7 @@ CPP = gcc -E -x c
|
|||
CXX = @CXX@
|
||||
|
||||
CPPFLAGS = -I. -I${NETGENDIR}
|
||||
DFLAGS = -DCAD_DIR=\"${LIBDIR}\" -DTCL_DIR=\"${TCLDIR}\" -DPACKAGE_NAME=\"netgen\" -DPACKAGE_TARNAME=\"netgen\" -DPACKAGE_VERSION=\"1.3\" -DPACKAGE_STRING=\"netgen\ 1.3\" -DPACKAGE_BUGREPORT=\"eda-dev@opencircuitdesign.com\" -DPACKAGE_URL=\"\" -DNETGEN_VERSION=\"1.5\" -DNETGEN_REVISION=\"50\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DSIZEOF_VOID_P=8 -DSIZEOF_UNSIGNED_INT=4 -DSIZEOF_UNSIGNED_LONG=8 -DSIZEOF_UNSIGNED_LONG_LONG=8 -DSTDC_HEADERS=1 -DHAVE_SETENV=1 -DHAVE_PUTENV=1 -DHAVE_DIRENT_H=1 -DHAVE_LIMITS_H=1 -DHAVE_VA_COPY=1 -DHAVE___VA_COPY=1 -DDBUG_OFF=1 -DTCL_NETGEN=1 -Dlinux=1 -DSYSV=1 -DISC=1 -DSHDLIB_EXT=\".so\" -DNDEBUG
|
||||
DFLAGS = -DCAD_DIR=\"${LIBDIR}\" -DTCL_DIR=\"${TCLDIR}\" -DPACKAGE_NAME=\"netgen\" -DPACKAGE_TARNAME=\"netgen\" -DPACKAGE_VERSION=\"1.3\" -DPACKAGE_STRING=\"netgen\ 1.3\" -DPACKAGE_BUGREPORT=\"eda-dev@opencircuitdesign.com\" -DPACKAGE_URL=\"\" -DNETGEN_VERSION=\"1.5\" -DNETGEN_REVISION=\"54\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DSIZEOF_VOID_P=8 -DSIZEOF_UNSIGNED_INT=4 -DSIZEOF_UNSIGNED_LONG=8 -DSIZEOF_UNSIGNED_LONG_LONG=8 -DSTDC_HEADERS=1 -DHAVE_SETENV=1 -DHAVE_PUTENV=1 -DHAVE_DIRENT_H=1 -DHAVE_LIMITS_H=1 -DHAVE_VA_COPY=1 -DHAVE___VA_COPY=1 -DDBUG_OFF=1 -DTCL_NETGEN=1 -Dlinux=1 -DSYSV=1 -DISC=1 -DSHDLIB_EXT=\".so\" -DNDEBUG
|
||||
CFLAGS = -g -m64 -fPIC -fPIC
|
||||
|
||||
DEPEND_FILE = Depend
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ PATH: /sbin
|
|||
PATH: /usr/bin
|
||||
PATH: /usr/sbin
|
||||
PATH: /usr/local/bin
|
||||
PATH: /home/tim/src/timberwolf-6.3/bin
|
||||
|
||||
|
||||
## ----------- ##
|
||||
|
|
@ -125,7 +126,7 @@ configure: failed program was:
|
|||
| #define PACKAGE_BUGREPORT "eda-dev@opencircuitdesign.com"
|
||||
| #define PACKAGE_URL ""
|
||||
| #define NETGEN_VERSION "1.5"
|
||||
| #define NETGEN_REVISION "50"
|
||||
| #define NETGEN_REVISION "54"
|
||||
| /* end confdefs.h. */
|
||||
| #include <ac_nonexistent.h>
|
||||
configure:3382: result: gcc -E
|
||||
|
|
@ -146,7 +147,7 @@ configure: failed program was:
|
|||
| #define PACKAGE_BUGREPORT "eda-dev@opencircuitdesign.com"
|
||||
| #define PACKAGE_URL ""
|
||||
| #define NETGEN_VERSION "1.5"
|
||||
| #define NETGEN_REVISION "50"
|
||||
| #define NETGEN_REVISION "54"
|
||||
| /* end confdefs.h. */
|
||||
| #include <ac_nonexistent.h>
|
||||
configure:3445: checking for library containing strerror
|
||||
|
|
@ -261,7 +262,7 @@ configure: failed program was:
|
|||
| #define PACKAGE_BUGREPORT "eda-dev@opencircuitdesign.com"
|
||||
| #define PACKAGE_URL ""
|
||||
| #define NETGEN_VERSION "1.5"
|
||||
| #define NETGEN_REVISION "50"
|
||||
| #define NETGEN_REVISION "54"
|
||||
| #define STDC_HEADERS 1
|
||||
| #define HAVE_SYS_TYPES_H 1
|
||||
| #define HAVE_SYS_STAT_H 1
|
||||
|
|
@ -302,7 +303,7 @@ configure: failed program was:
|
|||
| #define PACKAGE_BUGREPORT "eda-dev@opencircuitdesign.com"
|
||||
| #define PACKAGE_URL ""
|
||||
| #define NETGEN_VERSION "1.5"
|
||||
| #define NETGEN_REVISION "50"
|
||||
| #define NETGEN_REVISION "54"
|
||||
| #define STDC_HEADERS 1
|
||||
| #define HAVE_SYS_TYPES_H 1
|
||||
| #define HAVE_SYS_STAT_H 1
|
||||
|
|
@ -382,7 +383,7 @@ configure: failed program was:
|
|||
| #define PACKAGE_BUGREPORT "eda-dev@opencircuitdesign.com"
|
||||
| #define PACKAGE_URL ""
|
||||
| #define NETGEN_VERSION "1.5"
|
||||
| #define NETGEN_REVISION "50"
|
||||
| #define NETGEN_REVISION "54"
|
||||
| #define STDC_HEADERS 1
|
||||
| #define HAVE_SYS_TYPES_H 1
|
||||
| #define HAVE_SYS_STAT_H 1
|
||||
|
|
@ -454,7 +455,7 @@ configure: failed program was:
|
|||
| #define PACKAGE_BUGREPORT "eda-dev@opencircuitdesign.com"
|
||||
| #define PACKAGE_URL ""
|
||||
| #define NETGEN_VERSION "1.5"
|
||||
| #define NETGEN_REVISION "50"
|
||||
| #define NETGEN_REVISION "54"
|
||||
| #define STDC_HEADERS 1
|
||||
| #define HAVE_SYS_TYPES_H 1
|
||||
| #define HAVE_SYS_STAT_H 1
|
||||
|
|
@ -621,7 +622,7 @@ CC='gcc'
|
|||
CFLAGS='-g -m64 -fPIC'
|
||||
CPP='gcc -E -x c'
|
||||
CPPFLAGS=''
|
||||
DEFS='-DPACKAGE_NAME=\"netgen\" -DPACKAGE_TARNAME=\"netgen\" -DPACKAGE_VERSION=\"1.3\" -DPACKAGE_STRING=\"netgen\ 1.3\" -DPACKAGE_BUGREPORT=\"eda-dev@opencircuitdesign.com\" -DPACKAGE_URL=\"\" -DNETGEN_VERSION=\"1.5\" -DNETGEN_REVISION=\"50\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DSIZEOF_VOID_P=8 -DSIZEOF_UNSIGNED_INT=4 -DSIZEOF_UNSIGNED_LONG=8 -DSIZEOF_UNSIGNED_LONG_LONG=8 -DSTDC_HEADERS=1 -DHAVE_SETENV=1 -DHAVE_PUTENV=1 -DHAVE_DIRENT_H=1 -DHAVE_LIMITS_H=1 -DHAVE_VA_COPY=1 -DHAVE___VA_COPY=1 -DDBUG_OFF=1 -DTCL_NETGEN=1 -Dlinux=1 -DSYSV=1 -DISC=1'
|
||||
DEFS='-DPACKAGE_NAME=\"netgen\" -DPACKAGE_TARNAME=\"netgen\" -DPACKAGE_VERSION=\"1.3\" -DPACKAGE_STRING=\"netgen\ 1.3\" -DPACKAGE_BUGREPORT=\"eda-dev@opencircuitdesign.com\" -DPACKAGE_URL=\"\" -DNETGEN_VERSION=\"1.5\" -DNETGEN_REVISION=\"54\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DSIZEOF_VOID_P=8 -DSIZEOF_UNSIGNED_INT=4 -DSIZEOF_UNSIGNED_LONG=8 -DSIZEOF_UNSIGNED_LONG_LONG=8 -DSTDC_HEADERS=1 -DHAVE_SETENV=1 -DHAVE_PUTENV=1 -DHAVE_DIRENT_H=1 -DHAVE_LIMITS_H=1 -DHAVE_VA_COPY=1 -DHAVE___VA_COPY=1 -DDBUG_OFF=1 -DTCL_NETGEN=1 -Dlinux=1 -DSYSV=1 -DISC=1'
|
||||
DEPEND_FLAG='-MM'
|
||||
ECHO_C=''
|
||||
ECHO_N='printf'
|
||||
|
|
@ -734,7 +735,7 @@ unused=''
|
|||
#define PACKAGE_BUGREPORT "eda-dev@opencircuitdesign.com"
|
||||
#define PACKAGE_URL ""
|
||||
#define NETGEN_VERSION "1.5"
|
||||
#define NETGEN_REVISION "50"
|
||||
#define NETGEN_REVISION "54"
|
||||
#define STDC_HEADERS 1
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
|
|
|||
|
|
@ -657,7 +657,7 @@ S["ECHO_T"]=""
|
|||
S["ECHO_N"]="-n"
|
||||
S["ECHO_C"]=""
|
||||
S["DEFS"]="-DPACKAGE_NAME=\\\"netgen\\\" -DPACKAGE_TARNAME=\\\"netgen\\\" -DPACKAGE_VERSION=\\\"1.3\\\" -DPACKAGE_STRING=\\\"netgen\\ 1.3\\\" -DPACKAGE_BUGREPORT=\\\"eda-dev@open"\
|
||||
"circuitdesign.com\\\" -DPACKAGE_URL=\\\"\\\" -DNETGEN_VERSION=\\\"1.5\\\" -DNETGEN_REVISION=\\\"50\\\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -"\
|
||||
"circuitdesign.com\\\" -DPACKAGE_URL=\\\"\\\" -DNETGEN_VERSION=\\\"1.5\\\" -DNETGEN_REVISION=\\\"54\\\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -"\
|
||||
"DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DSIZEOF_VOID_P=8 -D"\
|
||||
"SIZEOF_UNSIGNED_INT=4 -DSIZEOF_UNSIGNED_LONG=8 -DSIZEOF_UNSIGNED_LONG_LONG=8 -DSTDC_HEADERS=1 -DHAVE_SETENV=1 -DHAVE_PUTENV=1 -DHAVE_DIRENT_H=1 -DHA"\
|
||||
"VE_LIMITS_H=1 -DHAVE_VA_COPY=1 -DHAVE___VA_COPY=1 -DDBUG_OFF=1 -DTCL_NETGEN=1 -Dlinux=1 -DSYSV=1 -DISC=1"
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ CPP = gcc -E -x c
|
|||
CXX = @CXX@
|
||||
|
||||
CPPFLAGS = -I. -I${NETGENDIR}
|
||||
DFLAGS = -DCAD_DIR=\"${LIBDIR}\" -DTCL_DIR=\"${TCLDIR}\" -DPACKAGE_NAME=\"netgen\" -DPACKAGE_TARNAME=\"netgen\" -DPACKAGE_VERSION=\"1.3\" -DPACKAGE_STRING=\"netgen\ 1.3\" -DPACKAGE_BUGREPORT=\"eda-dev@opencircuitdesign.com\" -DPACKAGE_URL=\"\" -DNETGEN_VERSION=\"1.5\" -DNETGEN_REVISION=\"50\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DSIZEOF_VOID_P=8 -DSIZEOF_UNSIGNED_INT=4 -DSIZEOF_UNSIGNED_LONG=8 -DSIZEOF_UNSIGNED_LONG_LONG=8 -DSTDC_HEADERS=1 -DHAVE_SETENV=1 -DHAVE_PUTENV=1 -DHAVE_DIRENT_H=1 -DHAVE_LIMITS_H=1 -DHAVE_VA_COPY=1 -DHAVE___VA_COPY=1 -DDBUG_OFF=1 -DTCL_NETGEN=1 -Dlinux=1 -DSYSV=1 -DISC=1 -DSHDLIB_EXT=\".so\" -DNDEBUG
|
||||
DFLAGS = -DCAD_DIR=\"${LIBDIR}\" -DTCL_DIR=\"${TCLDIR}\" -DPACKAGE_NAME=\"netgen\" -DPACKAGE_TARNAME=\"netgen\" -DPACKAGE_VERSION=\"1.3\" -DPACKAGE_STRING=\"netgen\ 1.3\" -DPACKAGE_BUGREPORT=\"eda-dev@opencircuitdesign.com\" -DPACKAGE_URL=\"\" -DNETGEN_VERSION=\"1.5\" -DNETGEN_REVISION=\"54\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DSIZEOF_VOID_P=8 -DSIZEOF_UNSIGNED_INT=4 -DSIZEOF_UNSIGNED_LONG=8 -DSIZEOF_UNSIGNED_LONG_LONG=8 -DSTDC_HEADERS=1 -DHAVE_SETENV=1 -DHAVE_PUTENV=1 -DHAVE_DIRENT_H=1 -DHAVE_LIMITS_H=1 -DHAVE_VA_COPY=1 -DHAVE___VA_COPY=1 -DDBUG_OFF=1 -DTCL_NETGEN=1 -Dlinux=1 -DSYSV=1 -DISC=1 -DSHDLIB_EXT=\".so\" -DNDEBUG
|
||||
CFLAGS = -g -m64 -fPIC -fPIC
|
||||
|
||||
DEPEND_FILE = Depend
|
||||
|
|
|
|||
|
|
@ -2970,6 +2970,7 @@ _netcmp_equate(ClientData clientData,
|
|||
/* add --- add new property */
|
||||
/* remove --- delete existing property */
|
||||
/* tolerance --- set property tolerance */
|
||||
/* merge --- set property merge behavior */
|
||||
/* Formerly: (none) */
|
||||
/* Results: */
|
||||
/* Side Effects: */
|
||||
|
|
@ -2987,10 +2988,10 @@ _netcmp_property(ClientData clientData,
|
|||
int ival, argstart;
|
||||
|
||||
char *options[] = {
|
||||
"add", "create", "remove", "delete", "tolerance", NULL
|
||||
"add", "create", "remove", "delete", "tolerance", "merge", NULL
|
||||
};
|
||||
enum OptionIdx {
|
||||
ADD_IDX, CREATE_IDX, REMOVE_IDX, DELETE_IDX, TOLERANCE_IDX
|
||||
ADD_IDX, CREATE_IDX, REMOVE_IDX, DELETE_IDX, TOLERANCE_IDX, MERGE_IDX
|
||||
};
|
||||
int result, index, idx2;
|
||||
|
||||
|
|
@ -3001,6 +3002,13 @@ _netcmp_property(ClientData clientData,
|
|||
INTEGER_IDX, DOUBLE_IDX, VALUE_IDX, STRING_IDX
|
||||
};
|
||||
|
||||
char *mergeoptions[] = {
|
||||
"none", "add", "add_critical", "par", "par_critical", NULL
|
||||
};
|
||||
enum MergeOptionIdx {
|
||||
NONE_IDX, ADD_ONLY_IDX, ADD_CRIT_IDX, PAR_ONLY_IDX, PAR_CRIT_IDX
|
||||
};
|
||||
|
||||
if (objc < 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "valid_cellname ?option?");
|
||||
return TCL_ERROR;
|
||||
|
|
@ -3012,7 +3020,7 @@ _netcmp_property(ClientData clientData,
|
|||
/* Print all properties of the cell as key/type/tolerance triplets */
|
||||
tobj1 = Tcl_NewListObj(0, NULL);
|
||||
|
||||
kl = (struct property *)HashFirst(tp->proptab, OBJHASHSIZE);
|
||||
kl = (struct property *)HashFirst(&(tp->propdict));
|
||||
while (kl != NULL) {
|
||||
tobj2 = Tcl_NewListObj(0, NULL);
|
||||
|
||||
|
|
@ -3039,7 +3047,7 @@ _netcmp_property(ClientData clientData,
|
|||
|
||||
Tcl_ListObjAppendElement(interp, tobj1, tobj2);
|
||||
|
||||
kl = (struct property *)HashNext(tp->proptab, OBJHASHSIZE);
|
||||
kl = (struct property *)HashNext(&(tp->propdict));
|
||||
}
|
||||
Tcl_SetObjResult(interp, tobj1);
|
||||
}
|
||||
|
|
@ -3175,11 +3183,9 @@ _netcmp_property(ClientData clientData,
|
|||
if (objc == 3) {
|
||||
/* "remove" without additional arguments means */
|
||||
/* delete all properties. */
|
||||
RecurseHashTable(tp->proptab, OBJHASHSIZE, freeprop);
|
||||
HashKill(tp->proptab, OBJHASHSIZE);
|
||||
FREE(tp->proptab);
|
||||
tp->proptab = (struct hashlist **)CALLOC(OBJHASHSIZE,
|
||||
sizeof(struct hashlist *));
|
||||
RecurseHashTable(&(tp->propdict), freeprop);
|
||||
HashKill(&(tp->propdict));
|
||||
InitializeHashTable(&(tp->propdict), OBJHASHSIZE);
|
||||
}
|
||||
else {
|
||||
for (i = 3; i < objc; i++)
|
||||
|
|
@ -3221,6 +3227,53 @@ _netcmp_property(ClientData clientData,
|
|||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MERGE_IDX:
|
||||
if (objc == 3) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "{property_key merge_type} ...");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
for (i = 3; i < objc; i++) {
|
||||
// Each value must be a duplet
|
||||
result = Tcl_ListObjLength(interp, objv[i], &llen);
|
||||
if ((result != TCL_OK) || (llen != 2)) {
|
||||
Tcl_SetResult(interp, "Not a {key merge_type} pair list.",
|
||||
NULL);
|
||||
}
|
||||
else {
|
||||
int mergeval;
|
||||
|
||||
result = Tcl_ListObjIndex(interp, objv[i], 0, &tobj1);
|
||||
if (result != TCL_OK) return result;
|
||||
result = Tcl_ListObjIndex(interp, objv[i], 1, &tobj2);
|
||||
if (result != TCL_OK) return result;
|
||||
|
||||
result = Tcl_GetIndexFromObj(interp, tobj2,
|
||||
(CONST84 char **)mergeoptions,
|
||||
"merge_type", 0, &idx2);
|
||||
if (result != TCL_OK) return result;
|
||||
|
||||
switch (idx2) {
|
||||
case NONE_IDX:
|
||||
mergeval = MERGE_NONE;
|
||||
break;
|
||||
case ADD_ONLY_IDX:
|
||||
mergeval = MERGE_ADD;
|
||||
break;
|
||||
case ADD_CRIT_IDX:
|
||||
mergeval = MERGE_ADD_CRIT;
|
||||
break;
|
||||
case PAR_ONLY_IDX:
|
||||
mergeval = MERGE_PAR;
|
||||
break;
|
||||
case PAR_CRIT_IDX:
|
||||
mergeval = MERGE_PAR_CRIT;
|
||||
break;
|
||||
}
|
||||
PropertyMerge(tp->name, fnum, Tcl_GetString(tobj1), mergeval);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return TCL_OK;
|
||||
|
|
|
|||
Loading…
Reference in New Issue