diff --git a/base/actel.c b/base/actel.c index 2b33e18..0cc05de 100644 --- a/base/actel.c +++ b/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); diff --git a/base/ext.c b/base/ext.c index c440db7..6e840d3 100644 --- a/base/ext.c +++ b/base/ext.c @@ -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 */ diff --git a/base/flatten.c b/base/flatten.c index 14b3b25..86b6bf1 100644 --- a/base/flatten.c +++ b/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) { diff --git a/base/hash.c b/base/hash.c index ac07897..96104b3 100644 --- a/base/hash.c +++ b/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); } - - diff --git a/base/hash.h b/base/hash.h index 63002b8..eb0519f 100644 --- a/base/hash.h +++ b/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); diff --git a/base/netcmp.c b/base/netcmp.c index 0dc987c..55abf65 100644 --- a/base/netcmp.c +++ b/base/netcmp.c @@ -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) { diff --git a/base/netgen.c b/base/netgen.c index 6595aaa..f9f0dc5 100644 --- a/base/netgen.c +++ b/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++; } diff --git a/base/netgen.h b/base/netgen.h index 58312ec..602ef62 100644 --- a/base/netgen.h +++ b/base/netgen.h @@ -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 *); diff --git a/base/objlist.c b/base/objlist.c index 0e1538f..3f50548 100644 --- a/base/objlist.c +++ b/base/objlist.c @@ -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); } diff --git a/base/objlist.h b/base/objlist.h index 14e5f30..943408d 100644 --- a/base/objlist.h +++ b/base/objlist.h @@ -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 */ diff --git a/base/spice.c b/base/spice.c index d5de1c6..b3b863b 100644 --- a/base/spice.c +++ b/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 diff --git a/base/xilinx.c b/base/xilinx.c index 3c15e33..c14e584 100644 --- a/base/xilinx.c +++ b/base/xilinx.c @@ -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); diff --git a/defs.mak b/defs.mak index 9bc0a89..19e534d 100644 --- a/defs.mak +++ b/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 diff --git a/scripts/config.log b/scripts/config.log index f7cc77b..da3ae98 100644 --- a/scripts/config.log +++ b/scripts/config.log @@ -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 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 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 diff --git a/scripts/config.status b/scripts/config.status index 8afbcbb..1508f6a 100755 --- a/scripts/config.status +++ b/scripts/config.status @@ -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" diff --git a/scripts/defs.mak b/scripts/defs.mak index 9bc0a89..19e534d 100644 --- a/scripts/defs.mak +++ b/scripts/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 diff --git a/tcltk/tclnetgen.c b/tcltk/tclnetgen.c index ff8ff5a..924d9c3 100644 --- a/tcltk/tclnetgen.c +++ b/tcltk/tclnetgen.c @@ -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;