mirror of
https://github.com/RTimothyEdwards/netgen.git
synced 2026-08-22 14:07:07 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b7363862b3 | ||
|
|
29566bde4d | ||
|
|
99d096cfc1 | ||
|
|
9943676df4 | ||
|
|
568ed65c05 | ||
|
|
cb85aa7115 | ||
|
|
be819b7200 | ||
|
|
618f912cac | ||
|
|
17c2bff72b | ||
|
|
7e68f3a32e | ||
|
|
c60443b862 | ||
|
|
4a295dbfe4 | ||
|
|
eb72af6d54 | ||
|
|
e7f2cacc88 | ||
|
|
7dfe6ee19f | ||
|
|
c7f27c909f | ||
|
|
758b5a249a | ||
|
|
15d10f1d93 | ||
|
|
a6e3e7e457 | ||
|
|
5f634b2a91 |
+5
-5
@@ -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);
|
||||
|
||||
+3
-3
@@ -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 */
|
||||
|
||||
+63
-80
@@ -24,6 +24,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef IBMPC
|
||||
#include <alloc.h>
|
||||
@@ -39,6 +40,8 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include "print.h"
|
||||
#include "netcmp.h"
|
||||
|
||||
extern struct hashdict spiceparams;
|
||||
|
||||
#define OLDPREFIX 1
|
||||
|
||||
void flattenCell(char *name, int file)
|
||||
@@ -95,7 +98,7 @@ void flattenCell(char *name, int file)
|
||||
if (ChildCell->dumped == 0) flattenCell(ParentParams->model.class,
|
||||
ChildCell->file);
|
||||
|
||||
ChildObjList = CopyObjList(ChildCell->cell);
|
||||
ChildObjList = CopyObjList(ChildCell->cell, 1);
|
||||
|
||||
/* update node numbers in child to unique numbers */
|
||||
oldmax = 0;
|
||||
@@ -177,7 +180,7 @@ void flattenCell(char *name, int file)
|
||||
}
|
||||
}
|
||||
}
|
||||
HashPtrInstall(tmp->name, tmp, ThisCell->objtab, OBJHASHSIZE);
|
||||
HashPtrInstall(tmp->name, tmp, &(ThisCell->objdict));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -198,9 +201,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 */
|
||||
@@ -322,7 +325,7 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
|
||||
/* if this is a new instance, flatten it */
|
||||
/* if (ChildCell->dumped == 0) flattenCell(ParentParams->model.class, file); */
|
||||
|
||||
ChildObjList = CopyObjList(ChildCell->cell);
|
||||
ChildObjList = CopyObjList(ChildCell->cell, 1);
|
||||
numflat++;
|
||||
|
||||
/* update node numbers in child to unique numbers */
|
||||
@@ -440,7 +443,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,33 +464,24 @@ 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 */
|
||||
/* Do property inheritance */
|
||||
|
||||
if (ParentProps) {
|
||||
for (ob2 = ChildObjList; ob2 != NULL; ob2=ob2->next) {
|
||||
|
||||
/* If the parent cell has properties to declare, then */
|
||||
/* pass them on to children. */
|
||||
/* pass them on to children. Use globals only if the */
|
||||
/* spiceparams dictionary is active (during file reading */
|
||||
/* only). */
|
||||
|
||||
if (ob2->type == PROPERTY) {
|
||||
struct valuelist *vl;
|
||||
int i;
|
||||
for (i == 0;; i++) {
|
||||
vl = &(ob2->instance.props[i]);
|
||||
if (vl->type == PROP_ENDLIST) break;
|
||||
else if (vl->type == PROP_EXPRESSION) {
|
||||
/* Only expressions take substitutions */
|
||||
struct tokstack *token;
|
||||
for (token = vl->value.stack; token; token = token->next) {
|
||||
/* WIP */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ob2->type == PROPERTY)
|
||||
ReduceExpressions(ob2, ParentProps, ChildCell,
|
||||
(spiceparams.hashtab == NULL) ? 0 : 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -508,7 +502,7 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
|
||||
tmp = ParentParams;
|
||||
do {
|
||||
tmp = tmp->next;
|
||||
} while ((tmp != NULL) && (tmp->type > FIRSTPIN));
|
||||
} while ((tmp != NULL) && ((tmp->type > FIRSTPIN) || (tmp->type == PROPERTY)));
|
||||
if (ob2) ob2->next = tmp;
|
||||
while (ParentParams != tmp) {
|
||||
ob2 = ParentParams->next;
|
||||
@@ -526,8 +520,8 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
|
||||
|
||||
void Flatten(char *name, int file)
|
||||
{
|
||||
ClearDumpedList(); /* keep track of flattened cells */
|
||||
flattenCell(name, file);
|
||||
ClearDumpedList(); /* keep track of flattened cells */
|
||||
flattenCell(name, file);
|
||||
}
|
||||
|
||||
|
||||
@@ -704,7 +698,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 +721,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 +834,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 +953,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 +992,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 +1087,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 +1124,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 +1174,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 +1192,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 +1264,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 +1299,11 @@ typedef struct ecomplist {
|
||||
} ECompList;
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
/* Survey the contents of a cell and
|
||||
/* Survey the contents of a cell and sort into a hash */
|
||||
/*------------------------------------------------------*/
|
||||
|
||||
void
|
||||
SurveyCell(struct nlist *tc, struct hashlist **comptab, int file1, int file2, int which)
|
||||
SurveyCell(struct nlist *tc, struct hashdict *compdict, int file1, int file2, int which)
|
||||
{
|
||||
struct objlist *ob;
|
||||
struct nlist *tsub, *teq;
|
||||
@@ -1331,8 +1323,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 +1343,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 +1381,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 +1392,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 +1409,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 +1423,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 +1439,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 +1485,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 +1535,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 +1568,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 +1593,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 +1626,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 +1640,13 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
}
|
||||
ecomp->add1 = 0;
|
||||
}
|
||||
ecomp = (ECompare *)HashNext(comptab, OBJHASHSIZE);
|
||||
}
|
||||
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 +1853,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 +1885,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 +1911,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 +1932,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) {
|
||||
|
||||
+85
-78
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+25
-19
@@ -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);
|
||||
|
||||
+336
-90
@@ -1800,11 +1800,12 @@ struct Node *CreateNodeList(char *name, short graph)
|
||||
return (head);
|
||||
}
|
||||
|
||||
void CreateLists(char *name, short graph)
|
||||
/* creates two lists of the correct 'shape', then traverses nodes
|
||||
in sequence to link up 'subelement' field of ElementList,
|
||||
then 'node' field of NodeList structures.
|
||||
*/
|
||||
* in sequence to link up 'subelement' field of ElementList,
|
||||
* then 'node' field of NodeList structures.
|
||||
*/
|
||||
|
||||
void CreateLists(char *name, short graph)
|
||||
{
|
||||
struct Element *ElementScan;
|
||||
struct ElementList *EListScan;
|
||||
@@ -1826,6 +1827,8 @@ void CreateLists(char *name, short graph)
|
||||
return;
|
||||
}
|
||||
|
||||
CombineParallel(name, graph);
|
||||
|
||||
Elements = CreateElementList(name, graph);
|
||||
Nodes = CreateNodeList(name, graph);
|
||||
if (LookupElementList == NULL) return;
|
||||
@@ -1952,6 +1955,7 @@ void CreateLists(char *name, short graph)
|
||||
}
|
||||
|
||||
ConnectAllNodes(name, graph);
|
||||
CombineParallel(name, graph);
|
||||
|
||||
E = CreateElementList(name, graph);
|
||||
N = CreateNodeList(name, graph);
|
||||
@@ -3255,6 +3259,304 @@ int Iterate(void)
|
||||
return(!notdone);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* "ob" points to the first property record of an object */
|
||||
/* instance. Check if there are multiple property records. If */
|
||||
/* so, group them by same properties of interest, order them by */
|
||||
/* critical property (if defined), and merge devices with the */
|
||||
/* same properties (by summing property "M" for devices; does */
|
||||
/* not apply to subcircuits, which must maintain individual */
|
||||
/* property records for each instance). */
|
||||
/*--------------------------------------------------------------*/
|
||||
|
||||
typedef struct _proplink *proplinkptr;
|
||||
typedef struct _proplink {
|
||||
struct property *prop;
|
||||
proplinkptr next;
|
||||
} proplink;
|
||||
|
||||
void PropertyOptimize(struct objlist *ob, struct nlist *tp)
|
||||
{
|
||||
struct objlist *ob2, *obt;
|
||||
struct property *kl, *m_rec, **plist;
|
||||
struct valuelist ***vlist, *vl, *vl2, *newvlist;
|
||||
proplinkptr plink, ptop;
|
||||
int pcount, p, i, j, icount, pmatch, ival, crit, ctype;
|
||||
double dval;
|
||||
static struct valuelist nullvl;
|
||||
|
||||
nullvl.type = PROP_INTEGER;
|
||||
nullvl.value.ival = 0;
|
||||
|
||||
// How many property records are there?
|
||||
// If there are not at least two property records then there
|
||||
// is nothing to be optimized.
|
||||
icount = 0;
|
||||
for (ob2 = ob; ob2 && ob2->type == PROPERTY; ob2 = ob2->next) icount++;
|
||||
if (icount < 2) return;
|
||||
|
||||
// Look through master cell property list and create
|
||||
// an array of properties of interest to fill in order.
|
||||
|
||||
m_rec = NULL;
|
||||
ptop = NULL;
|
||||
pcount = 1;
|
||||
crit = -1;
|
||||
ctype = -1;
|
||||
kl = (struct property *)HashFirst(&(tp->propdict));
|
||||
while (kl != NULL) {
|
||||
// Make a linked list so we don't have to iterate through the hash again
|
||||
plink = (proplinkptr)MALLOC(sizeof(proplink));
|
||||
plink->prop = kl;
|
||||
plink->next = ptop;
|
||||
ptop = plink;
|
||||
if ((*matchfunc)(kl->key, "M")) {
|
||||
kl->idx = 0;
|
||||
m_rec = kl;
|
||||
}
|
||||
else
|
||||
kl->idx = pcount++;
|
||||
|
||||
// Set critical property index, if there is one (TO-DO: Handle types
|
||||
// other than MERGE_ADD_CRIT, and deal with possibility of multiple
|
||||
// critical properties per instance).
|
||||
if (kl->merge == MERGE_ADD_CRIT) {
|
||||
crit = kl->idx;
|
||||
ctype = kl->merge;
|
||||
}
|
||||
kl = (struct property *)HashNext(&(tp->propdict));
|
||||
}
|
||||
// Recast the linked list as an array
|
||||
plist = (struct property **)CALLOC(pcount, sizeof(struct property *));
|
||||
vlist = (struct valuelist ***)CALLOC(pcount, sizeof(struct valuelist **));
|
||||
if (m_rec == NULL)
|
||||
vlist[0] = (struct valuelist **)CALLOC(icount, sizeof(struct valuelist *));
|
||||
pcount = 1;
|
||||
while (ptop != NULL) {
|
||||
if (ptop->prop == m_rec) {
|
||||
plist[0] = m_rec;
|
||||
vlist[0] = (struct valuelist **)CALLOC(icount,
|
||||
sizeof(struct valuelist *));
|
||||
}
|
||||
else {
|
||||
plist[pcount] = ptop->prop;
|
||||
vlist[pcount++] = (struct valuelist **)CALLOC(icount,
|
||||
sizeof(struct valuelist *));
|
||||
}
|
||||
plink = ptop;
|
||||
FREE(ptop);
|
||||
ptop = plink->next;
|
||||
}
|
||||
|
||||
// Now, for each property record, sort the properties of interest
|
||||
// so that they are all in order. Property "M" goes in position
|
||||
// zero.
|
||||
|
||||
i = 0;
|
||||
for (ob2 = ob; ob2 && ob2->type == PROPERTY; ob2 = ob2->next) {
|
||||
for (p = 0;; p++) {
|
||||
vl = &(ob2->instance.props[p]);
|
||||
if (vl->type == PROP_ENDLIST) break;
|
||||
if (vl->key == NULL) continue;
|
||||
kl = (struct property *)HashLookup(vl->key, &(tp->propdict));
|
||||
if (kl == NULL && m_rec == NULL) {
|
||||
if ((*matchfunc)(vl->key, "M")) {
|
||||
vlist[0][i] = vl;
|
||||
}
|
||||
}
|
||||
else if (kl != NULL) {
|
||||
vlist[kl->idx][i] = vl;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
// Now combine records with same properties by summing M.
|
||||
for (i = 0; i < icount - 1; i++) {
|
||||
for (j = 1; j < icount; j++) {
|
||||
pmatch = 0;
|
||||
for (p = 1; p < pcount; p++) {
|
||||
kl = plist[p];
|
||||
vl = vlist[p][i];
|
||||
vl2 = vlist[p][j];
|
||||
if (vl == NULL && vl2 == NULL) {
|
||||
pmatch++;
|
||||
continue;
|
||||
}
|
||||
// TO-DO: If either value is missing, it takes kl->pdefault
|
||||
// and must apply promotions if necessary.
|
||||
else if (vl == NULL || vl2 == NULL) continue;
|
||||
|
||||
// Critical properties will be multiplied up by M and do not
|
||||
// need to match. May want a more nuanced comparison, though.
|
||||
if (p == crit) {
|
||||
pmatch++;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(vl->type) {
|
||||
case PROP_DOUBLE:
|
||||
case PROP_VALUE:
|
||||
dval = fabs(vl->value.dval - vl2->value.dval);
|
||||
if (dval <= kl->slop.dval) pmatch++;
|
||||
break;
|
||||
case PROP_INTEGER:
|
||||
ival = abs(vl->value.ival - vl2->value.ival);
|
||||
if (ival <= kl->slop.ival) pmatch++;
|
||||
break;
|
||||
case PROP_STRING:
|
||||
if ((*matchfunc)(vl->value.string, vl2->value.string)) pmatch++;
|
||||
break;
|
||||
|
||||
/* will not attempt to match expressions, but it could
|
||||
* be done with some minor effort by matching each
|
||||
* stack token and comparing those that are strings.
|
||||
*/
|
||||
}
|
||||
}
|
||||
if (pmatch == (pcount - 1)) {
|
||||
// Sum M (p == 0) records and remove one record
|
||||
if (vlist[0][i] == NULL) {
|
||||
// Add this to the end of the property record
|
||||
// find ith record in ob
|
||||
p = 0;
|
||||
for (ob2 = ob; p != i; ob2 = ob2->next, p++);
|
||||
// Count entries, add one, reallocate
|
||||
for (p = 0;; p++) {
|
||||
vl = &ob2->instance.props[p];
|
||||
if (vl->type == PROP_ENDLIST) break;
|
||||
}
|
||||
p++;
|
||||
newvlist = (struct valuelist *)CALLOC(p + 1,
|
||||
sizeof(struct valuelist));
|
||||
// Move end record forward
|
||||
vl = &newvlist[p];
|
||||
vl->key = NULL;
|
||||
vl->type = PROP_ENDLIST;
|
||||
vl->value.ival = 0;
|
||||
|
||||
// Add "M" record behind it
|
||||
vl = &newvlist[--p];
|
||||
vl->key = strsave("M");
|
||||
vl->type = PROP_INTEGER;
|
||||
vl->value.ival = 1;
|
||||
vlist[0][i] = vl;
|
||||
// Copy the rest of the records and regenerate vlist
|
||||
for (--p; p >= 0; p--) {
|
||||
vl = &newvlist[p];
|
||||
vl->key = ob2->instance.props[p].key;
|
||||
vl->type = ob2->instance.props[p].type;
|
||||
vl->value = ob2->instance.props[p].value;
|
||||
|
||||
kl = (struct property *)HashLookup(vl->key, &(tp->propdict));
|
||||
if (kl != NULL) vlist[kl->idx][i] = vl;
|
||||
}
|
||||
|
||||
// Replace instance properties with the new list
|
||||
FREE(ob2->instance.props);
|
||||
ob2->instance.props = newvlist;
|
||||
}
|
||||
|
||||
// If there is a critical property, then M is never
|
||||
// greater than 1.
|
||||
if (crit >= 0) {
|
||||
if (vlist[0][i] != NULL) {
|
||||
if (vlist[0][i]->value.ival > 1) {
|
||||
vl = vlist[crit][i];
|
||||
if (vl->type == PROP_INTEGER)
|
||||
vl->value.ival *= vlist[0][i]->value.ival;
|
||||
else if (vl->type == PROP_DOUBLE)
|
||||
vl->value.dval *= (double)vlist[0][i]->value.ival;
|
||||
vlist[0][i]->value.ival = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (vlist[0][j] == NULL) {
|
||||
vlist[0][j] = &nullvl; // Mark this position
|
||||
if (crit >= 0) {
|
||||
vl = vlist[crit][i];
|
||||
if (ctype == MERGE_ADD_CRIT) {
|
||||
if (vl->type == PROP_INTEGER)
|
||||
vl->value.ival += vlist[crit][j]->value.ival;
|
||||
else if (vl->type == PROP_DOUBLE)
|
||||
vl->value.dval += vlist[crit][j]->value.dval;
|
||||
}
|
||||
else { /* MERGE_PAR_CRIT */
|
||||
if (vl->type == PROP_INTEGER) {
|
||||
double di = vl->value.ival;
|
||||
double dj = vlist[crit][j]->value.ival;
|
||||
di = 1.0 / (1.0 / di + 1.0 / dj);
|
||||
vl->value.ival = (int)di;
|
||||
}
|
||||
else if (vl->type == PROP_DOUBLE) {
|
||||
vl->value.dval += 1.0 / (1.0 / vl->value.dval +
|
||||
1.0 / vlist[crit][j]->value.dval);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
vlist[0][i]->value.ival++;
|
||||
}
|
||||
}
|
||||
else if (vlist[0][i]->value.ival > 0) {
|
||||
if (crit >= 0) {
|
||||
vl = vlist[crit][i];
|
||||
if (ctype == MERGE_ADD_CRIT) {
|
||||
if (vl->type == PROP_INTEGER)
|
||||
vl->value.ival += vlist[0][j]->value.ival *
|
||||
vlist[crit][j]->value.ival;
|
||||
else if (vl->type == PROP_DOUBLE)
|
||||
vl->value.dval += (double)vlist[0][j]->value.ival *
|
||||
vlist[crit][j]->value.dval;
|
||||
}
|
||||
else { /* MERGE_PAR_CRIT */
|
||||
if (vl->type == PROP_INTEGER) {
|
||||
double d = (double)vlist[crit][j]->value.ival /
|
||||
(double)vlist[0][j]->value.ival;
|
||||
vl->value.ival = (int)(1.0 / (1.0 / (double)vl->value.ival
|
||||
+ 1.0 / d));
|
||||
}
|
||||
else if (vl->type == PROP_DOUBLE) {
|
||||
double d = vlist[crit][j]->value.dval /
|
||||
(double)vlist[0][j]->value.ival;
|
||||
vl->value.dval = 1.0 / (1.0 / vl->value.dval + 1.0 / d);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
vlist[0][i]->value.ival += vlist[0][j]->value.ival;
|
||||
}
|
||||
vlist[0][j]->value.ival = 0;
|
||||
}
|
||||
}
|
||||
else j++;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove entries with M = 0
|
||||
ob2 = ob;
|
||||
for (i = 1; i < icount; i++) {
|
||||
vl = vlist[0][i];
|
||||
if (vl != NULL && vl->value.ival == 0) {
|
||||
obt = ob2->next;
|
||||
ob2->next = ob2->next->next;
|
||||
FreeObjectAndHash(obt, tp);
|
||||
}
|
||||
else
|
||||
ob2 = ob2->next;
|
||||
}
|
||||
|
||||
// Cleanup memory allocation
|
||||
for (p = 0; p < pcount; p++) {
|
||||
kl = (struct property *)plist[p];
|
||||
if (kl) kl->idx = 0;
|
||||
FREE(vlist[p]);
|
||||
}
|
||||
FREE(plist);
|
||||
FREE(vlist);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* Compare the properties of two objects. The passed values */
|
||||
/* ob1 and ob2 are pointers to the first entry (firstpin) of */
|
||||
@@ -3310,6 +3612,10 @@ int PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print)
|
||||
|
||||
if ((t1type != PROPERTY) && (t2type != PROPERTY)) return 0;
|
||||
|
||||
// Organize and merge property records
|
||||
if (t1type == PROPERTY) PropertyOptimize(tp1, tc1);
|
||||
if (t2type == PROPERTY) PropertyOptimize(tp2, tc2);
|
||||
|
||||
if (t1type != PROPERTY) {
|
||||
// t1 has no properties. See if t2's properties are required
|
||||
// to be checked. If so, flag t1 as missing required properties
|
||||
@@ -3319,7 +3625,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 +3650,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 +3675,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 +3692,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 */
|
||||
@@ -3894,80 +4200,6 @@ int ResolveAutomorphisms()
|
||||
return(VerifyMatching());
|
||||
}
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
/* CombineSetup -- */
|
||||
/* Add an entry to a cell describing the combination */
|
||||
/* allowances. */
|
||||
/* Return 1 if OK, 0 if error */
|
||||
/*------------------------------------------------------*/
|
||||
|
||||
int CombineSetup(char *model, int filenum, int comb_type)
|
||||
{
|
||||
struct nlist *tp;
|
||||
|
||||
// If -1 is passed as filenum, then re-run this routine on
|
||||
// each of Circuit1 and Circuit2 models.
|
||||
|
||||
if (filenum == -1) {
|
||||
if ((Circuit1 != NULL) && (Circuit1->file != -1))
|
||||
CombineSetup(model, Circuit1->file, comb_type);
|
||||
if ((Circuit2 != NULL) && (Circuit2->file != -1))
|
||||
CombineSetup(model, Circuit2->file, comb_type);
|
||||
return 1;
|
||||
}
|
||||
|
||||
tp = LookupCellFile(model, filenum);
|
||||
if (tp == NULL) {
|
||||
Printf("No such model %s\n", model);
|
||||
return 0;
|
||||
}
|
||||
|
||||
tp->flags |= comb_type;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
/* CombineForget -- */
|
||||
/* Remove combination allowances for a cell */
|
||||
/* */
|
||||
/* Return 1 if OK, 0 if error */
|
||||
/* */
|
||||
/* If comb_type is 0, then forget all allowed */
|
||||
/* combinations of the device. */
|
||||
/*------------------------------------------------------*/
|
||||
|
||||
int CombineForget(char *model, int filenum, int comb_type)
|
||||
{
|
||||
struct nlist *tp;
|
||||
|
||||
// If -1 is passed as filenum, then re-run this routine on
|
||||
// each of Circuit1 and Circuit2 models.
|
||||
|
||||
if (filenum == -1) {
|
||||
if ((Circuit1 != NULL) && (Circuit1->file != -1))
|
||||
CombineForget(model, Circuit1->file, comb_type);
|
||||
if ((Circuit2 != NULL) && (Circuit2->file != -1))
|
||||
CombineForget(model, Circuit2->file, comb_type);
|
||||
return 1;
|
||||
}
|
||||
|
||||
tp = LookupCellFile(model, filenum);
|
||||
if (tp == NULL) {
|
||||
Printf("No such model %s\n", model);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (comb_type != 0) {
|
||||
/* Remove this specific combination allowance */
|
||||
tp->flags &= ~comb_type;
|
||||
}
|
||||
else {
|
||||
/* Blanket remove all combinations for this device */
|
||||
tp->flags &= ~(COMB_SERIAL | COMB_PARALLEL);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
/* PermuteSetup -- */
|
||||
/* Add an entry to a cell's "permutes" linked list. */
|
||||
@@ -4476,6 +4708,20 @@ int reorderpins(struct hashlist *p, int file)
|
||||
}
|
||||
ob = ob->next;
|
||||
ob2 = ob2->next;
|
||||
if (i < numports - 1) {
|
||||
if (ob == NULL || ob->type <= FIRSTPIN) {
|
||||
Fprintf(stderr, "Instance of %s has only "
|
||||
"%d of %d ports\n",
|
||||
tc2->name, i + 1, numports);
|
||||
break;
|
||||
}
|
||||
else if (ob2 == NULL || ob2->type != PORT) {
|
||||
Fprintf(stderr, "Instance of %s has "
|
||||
"%d ports, expected %d\n",
|
||||
tc2->name, i + 1, numports);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ob = firstpin;
|
||||
@@ -4488,9 +4734,10 @@ 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;
|
||||
if (ob == NULL) break; // Error message already output
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -4566,12 +4813,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 +4841,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 +5134,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 +5192,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) {
|
||||
|
||||
+571
-337
File diff suppressed because it is too large
Load Diff
+4
-2
@@ -37,13 +37,14 @@ 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 *);
|
||||
extern int SetPropertyDefault(struct property *, struct valuelist *);
|
||||
extern struct objlist *LinkProperties(char *model, struct keyvalue *topptr);
|
||||
extern int ReduceExpressions(struct objlist *instprop, struct nlist *parent,
|
||||
int glob);
|
||||
extern int ReduceExpressions(struct objlist *instprop, struct objlist *parprops,
|
||||
struct nlist *parent, int glob);
|
||||
extern void Node(char *name);
|
||||
extern void Global(char *name);
|
||||
extern void UniqueGlobal(char *name);
|
||||
@@ -115,6 +116,7 @@ extern void FlattenCurrent();
|
||||
extern void ConvertGlobals(char *name, int fnum);
|
||||
extern int CleanupPins(char *name, int fnum);
|
||||
extern void ConnectAllNodes(char *model, int fnum);
|
||||
extern void CombineParallel(char *model, int fnum);
|
||||
extern int NoDisconnectedNodes;
|
||||
extern int PropertyKeyMatch(char *, char *);
|
||||
extern int PropertyValueMatch(char *, char *);
|
||||
|
||||
+45
-58
@@ -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 *******************************/
|
||||
@@ -863,7 +843,7 @@ int ListLength(char *list_template)
|
||||
|
||||
|
||||
|
||||
struct objlist *CopyObjList(struct objlist *oldlist)
|
||||
struct objlist *CopyObjList(struct objlist *oldlist, unsigned char doforall)
|
||||
/* copies list pointed to by oldlist, creating
|
||||
a list whose head pointer is returned */
|
||||
{
|
||||
@@ -900,6 +880,13 @@ struct objlist *CopyObjList(struct objlist *oldlist)
|
||||
tail->next = newob;
|
||||
tail = newob;
|
||||
tmp = tmp->next;
|
||||
|
||||
// If "doforall" is 0, then only copy one object; otherwise,
|
||||
// copy to the end of the list.
|
||||
if (!doforall) {
|
||||
if ((tmp == NULL) || ((tmp->type <= FIRSTPIN) && (tmp->type != PROPERTY)))
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (head);
|
||||
}
|
||||
@@ -914,13 +901,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 +926,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 +953,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 +1000,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);
|
||||
}
|
||||
|
||||
|
||||
+20
-4
@@ -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 */
|
||||
@@ -216,7 +232,7 @@ extern int ListLength(char *list_template);
|
||||
extern struct nlist *LookupPrematchedClass(struct nlist *, int);
|
||||
extern struct objlist *LookupObject(char *name, struct nlist *WhichCell);
|
||||
extern struct objlist *LookupInstance(char *name, struct nlist *WhichCell);
|
||||
extern struct objlist *CopyObjList(struct objlist *oldlist);
|
||||
extern struct objlist *CopyObjList(struct objlist *oldlist, unsigned char doforall);
|
||||
extern void UpdateNodeNumbers(struct objlist *lst, int from, int to);
|
||||
|
||||
/* Function pointer to List or ListExact, allowing regular expressions */
|
||||
|
||||
+97
-170
@@ -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)
|
||||
{
|
||||
@@ -73,7 +73,7 @@ void SpiceSubCell(struct nlist *tp, int IsSubCell)
|
||||
for (ob = tp->cell; ob != NULL; ob = ob->next)
|
||||
if (ob->node > maxnode) maxnode = ob->node;
|
||||
|
||||
/* was: for (node = 0; node <= maxnode; node++) */
|
||||
/* was: for (node = 0; node <= maxnode; node++) */
|
||||
for (node = 1; node <= maxnode; node++)
|
||||
FlushString("# %3d = %s\n", node, NodeName(tp, node));
|
||||
|
||||
@@ -154,7 +154,6 @@ void SpiceSubCell(struct nlist *tp, int IsSubCell)
|
||||
|
||||
/* caps and resistors, print out device value */
|
||||
|
||||
|
||||
/* print out device type (model/subcircuit name) */
|
||||
|
||||
switch (tp2->class) {
|
||||
@@ -358,6 +357,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);
|
||||
@@ -467,7 +472,7 @@ extern void IncludeSpice(char *, int, struct cellstack **, int);
|
||||
void ReadSpiceFile(char *fname, int filenum, struct cellstack **CellStackPtr,
|
||||
int blackbox)
|
||||
{
|
||||
int cdnum = 1, rdnum = 1, ndev, multi;
|
||||
int cdnum = 1, rdnum = 1;
|
||||
int warnings = 0, update = 0, hasports = 0;
|
||||
char *eqptr, devtype, in_subckt;
|
||||
struct keyvalue *kvlist = NULL;
|
||||
@@ -778,7 +783,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -815,7 +820,6 @@ skip_ends:
|
||||
/* Read the device model */
|
||||
snprintf(model, 99, "%s", nexttok);
|
||||
|
||||
ndev = 1;
|
||||
while (nexttok != NULL)
|
||||
{
|
||||
/* Parse for M and other parameters */
|
||||
@@ -825,10 +829,7 @@ skip_ends:
|
||||
if ((eqptr = strchr(nexttok, '=')) != NULL)
|
||||
{
|
||||
*eqptr = '\0';
|
||||
if (!strcasecmp(nexttok, "M"))
|
||||
sscanf(eqptr + 1, "%d", &ndev);
|
||||
else
|
||||
AddProperty(&kvlist, nexttok, eqptr + 1);
|
||||
AddProperty(&kvlist, nexttok, eqptr + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -837,6 +838,7 @@ skip_ends:
|
||||
Port("collector");
|
||||
Port("base");
|
||||
Port("emitter");
|
||||
PropertyInteger(model, filenum, "M", 0, 1);
|
||||
SetClass(CLASS_BJT);
|
||||
EndCell();
|
||||
ReopenCellDef((*CellStackPtr)->cellname, filenum); /* Reopen */
|
||||
@@ -847,16 +849,10 @@ skip_ends:
|
||||
goto baddevice;
|
||||
}
|
||||
|
||||
multi = (ndev > 1) ? 1 : 0;
|
||||
if (!multi) snprintf(instname, 255, "%s%s", model, inst);
|
||||
while (ndev > 0)
|
||||
{
|
||||
if (multi) snprintf(instname, 255, "%s%s.%d", model, inst, ndev);
|
||||
Cell(instname, model, collector, base, emitter);
|
||||
pobj = LinkProperties(model, kvlist);
|
||||
ReduceExpressions(pobj, CurrentCell, TRUE);
|
||||
ndev--;
|
||||
}
|
||||
snprintf(instname, 255, "%s%s", model, inst);
|
||||
Cell(instname, model, collector, base, emitter);
|
||||
pobj = LinkProperties(model, kvlist);
|
||||
ReduceExpressions(pobj, NULL, CurrentCell, TRUE);
|
||||
DeleteProperties(&kvlist);
|
||||
}
|
||||
else if (toupper(nexttok[0]) == 'M') {
|
||||
@@ -890,7 +886,6 @@ skip_ends:
|
||||
/* Read the device model */
|
||||
snprintf(model, 99, "%s", nexttok);
|
||||
|
||||
ndev = 1;
|
||||
while (nexttok != NULL)
|
||||
{
|
||||
/* Parse for parameters; treat "M" separately */
|
||||
@@ -900,14 +895,7 @@ skip_ends:
|
||||
if ((eqptr = strchr(nexttok, '=')) != NULL)
|
||||
{
|
||||
*eqptr = '\0';
|
||||
if (!strcasecmp(nexttok, "M"))
|
||||
sscanf(eqptr + 1, "%d", &ndev);
|
||||
else if (!strcasecmp(nexttok, "L"))
|
||||
AddProperty(&kvlist, "L", eqptr + 1);
|
||||
else if (!strcasecmp(nexttok, "W"))
|
||||
AddProperty(&kvlist, "W", eqptr + 1);
|
||||
else
|
||||
AddProperty(&kvlist, nexttok, eqptr + 1);
|
||||
AddProperty(&kvlist, nexttok, eqptr + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -921,8 +909,9 @@ skip_ends:
|
||||
Port("gate");
|
||||
Port("source");
|
||||
Port("bulk");
|
||||
PropertyDouble(model, filenum, "length", 0.01, 0.0);
|
||||
PropertyDouble(model, filenum, "width", 0.01, 0.0);
|
||||
PropertyDouble(model, filenum, "L", 0.01, 0.0);
|
||||
PropertyDouble(model, filenum, "W", 0.01, 0.0);
|
||||
PropertyInteger(model, filenum, "M", 0, 1);
|
||||
SetClass(CLASS_FET);
|
||||
EndCell();
|
||||
ReopenCellDef((*CellStackPtr)->cellname, filenum); /* Reopen */
|
||||
@@ -933,16 +922,10 @@ skip_ends:
|
||||
goto baddevice;
|
||||
}
|
||||
|
||||
multi = (ndev > 1) ? 1 : 0;
|
||||
if (!multi) snprintf(instname, 255, "%s%s", model, inst);
|
||||
while (ndev > 0)
|
||||
{
|
||||
if (multi) snprintf(instname, 255, "%s%s.%d", model, inst, ndev);
|
||||
Cell(instname, model, drain, gate, source, bulk);
|
||||
pobj = LinkProperties(model, kvlist);
|
||||
ReduceExpressions(pobj, CurrentCell, TRUE);
|
||||
ndev--;
|
||||
}
|
||||
snprintf(instname, 255, "%s%s", model, inst);
|
||||
Cell(instname, model, drain, gate, source, bulk);
|
||||
pobj = LinkProperties(model, kvlist);
|
||||
ReduceExpressions(pobj, NULL, CurrentCell, TRUE);
|
||||
DeleteProperties(&kvlist);
|
||||
SpiceSkipNewLine();
|
||||
}
|
||||
@@ -987,17 +970,13 @@ skip_ends:
|
||||
snprintf(model, 99, "%s", nexttok);
|
||||
|
||||
/* Any other device properties? */
|
||||
ndev = 1;
|
||||
while (nexttok != NULL)
|
||||
{
|
||||
SpiceTokNoNewline();
|
||||
if ((nexttok == NULL) || (nexttok[0] == '\0')) break;
|
||||
if ((eqptr = strchr(nexttok, '=')) != NULL) {
|
||||
*eqptr = '\0';
|
||||
if (!strcasecmp(nexttok, "M"))
|
||||
sscanf(eqptr + 1, "%d", &ndev);
|
||||
else
|
||||
AddProperty(&kvlist, nexttok, eqptr + 1);
|
||||
AddProperty(&kvlist, nexttok, eqptr + 1);
|
||||
}
|
||||
else if (!strncmp(nexttok, "$[", 2)) {
|
||||
// Support for CDL modeled capacitor format
|
||||
@@ -1020,6 +999,7 @@ skip_ends:
|
||||
Port("top");
|
||||
Port("bottom");
|
||||
PropertyValue(model, filenum, "value", 0.01, 0.0);
|
||||
PropertyInteger(model, filenum, "M", 0, 1);
|
||||
SetClass(CLASS_CAP);
|
||||
EndCell();
|
||||
ReopenCellDef((*CellStackPtr)->cellname, filenum); /* Reopen */
|
||||
@@ -1033,19 +1013,13 @@ skip_ends:
|
||||
usemodel = 1;
|
||||
}
|
||||
|
||||
multi = (ndev > 1) ? 1 : 0;
|
||||
if (!multi) snprintf(instname, 255, "%s%s", model, inst);
|
||||
|
||||
while (ndev > 0) {
|
||||
if (multi) snprintf(instname, 255, "%s%s.%d", model, inst, ndev);
|
||||
if (usemodel)
|
||||
Cell(instname, model, ctop, cbot);
|
||||
else
|
||||
Cap((*CellStackPtr)->cellname, instname, ctop, cbot);
|
||||
pobj = LinkProperties(model, kvlist);
|
||||
ReduceExpressions(pobj, CurrentCell, TRUE);
|
||||
ndev--;
|
||||
}
|
||||
snprintf(instname, 255, "%s%s", model, inst);
|
||||
if (usemodel)
|
||||
Cell(instname, model, ctop, cbot);
|
||||
else
|
||||
Cap((*CellStackPtr)->cellname, instname, ctop, cbot);
|
||||
pobj = LinkProperties(model, kvlist);
|
||||
ReduceExpressions(pobj, NULL, CurrentCell, TRUE);
|
||||
DeleteProperties(&kvlist);
|
||||
}
|
||||
}
|
||||
@@ -1090,16 +1064,12 @@ skip_ends:
|
||||
snprintf(model, 99, "%s", nexttok);
|
||||
|
||||
/* Any other device properties? */
|
||||
ndev = 1;
|
||||
while (nexttok != NULL) {
|
||||
SpiceTokNoNewline();
|
||||
if ((nexttok == NULL) || (nexttok[0] == '\0')) break;
|
||||
if ((eqptr = strchr(nexttok, '=')) != NULL) {
|
||||
*eqptr = '\0';
|
||||
if (!strcasecmp(nexttok, "M"))
|
||||
sscanf(eqptr + 1, "%d", &ndev);
|
||||
else
|
||||
AddProperty(&kvlist, nexttok, eqptr + 1);
|
||||
AddProperty(&kvlist, nexttok, eqptr + 1);
|
||||
}
|
||||
else if (!strncmp(nexttok, "$[", 2)) {
|
||||
// Support for CDL modeled resistor format
|
||||
@@ -1120,6 +1090,7 @@ skip_ends:
|
||||
Port("end_a");
|
||||
Port("end_b");
|
||||
PropertyValue(model, filenum, "value", 0.01, 0.0);
|
||||
PropertyInteger(model, filenum, "M", 0, 1);
|
||||
SetClass(CLASS_RES);
|
||||
EndCell();
|
||||
ReopenCellDef((*CellStackPtr)->cellname, filenum); /* Reopen */
|
||||
@@ -1135,19 +1106,13 @@ skip_ends:
|
||||
else
|
||||
strcpy(model, "r"); /* Use default resistor model */
|
||||
|
||||
multi = (ndev > 1) ? 1 : 0;
|
||||
if (!multi) snprintf(instname, 255, "%s%s", model, inst);
|
||||
|
||||
while (ndev > 0) {
|
||||
if (multi) snprintf(instname, 255, "%s%s.%d", model, inst, ndev);
|
||||
if (usemodel)
|
||||
Cell(instname, model, rtop, rbot);
|
||||
else
|
||||
Res((*CellStackPtr)->cellname, instname, rtop, rbot);
|
||||
pobj = LinkProperties(model, kvlist);
|
||||
ReduceExpressions(pobj, CurrentCell, TRUE);
|
||||
ndev--;
|
||||
}
|
||||
snprintf(instname, 255, "%s%s", model, inst);
|
||||
if (usemodel)
|
||||
Cell(instname, model, rtop, rbot);
|
||||
else
|
||||
Res((*CellStackPtr)->cellname, instname, rtop, rbot);
|
||||
pobj = LinkProperties(model, kvlist);
|
||||
ReduceExpressions(pobj, NULL, CurrentCell, TRUE);
|
||||
DeleteProperties(&kvlist);
|
||||
}
|
||||
}
|
||||
@@ -1172,7 +1137,6 @@ skip_ends:
|
||||
/* Read the device model */
|
||||
snprintf(model, 99, "%s", nexttok);
|
||||
|
||||
ndev = 1;
|
||||
while (nexttok != NULL)
|
||||
{
|
||||
/* Parse for M and other parameters */
|
||||
@@ -1182,10 +1146,7 @@ skip_ends:
|
||||
if ((eqptr = strchr(nexttok, '=')) != NULL)
|
||||
{
|
||||
*eqptr = '\0';
|
||||
if (!strcasecmp(nexttok, "M"))
|
||||
sscanf(eqptr + 1, "%d", &ndev);
|
||||
else
|
||||
AddProperty(&kvlist, nexttok, eqptr + 1);
|
||||
AddProperty(&kvlist, nexttok, eqptr + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1193,6 +1154,7 @@ skip_ends:
|
||||
CellDefNoCase(model, filenum);
|
||||
Port("anode");
|
||||
Port("cathode");
|
||||
PropertyInteger(model, filenum, "M", 0, 1);
|
||||
SetClass(CLASS_DIODE);
|
||||
EndCell();
|
||||
ReopenCellDef((*CellStackPtr)->cellname, filenum); /* Reopen */
|
||||
@@ -1202,16 +1164,10 @@ skip_ends:
|
||||
Fprintf(stderr, "Device \"%s\" has wrong number of ports for a diode.\n");
|
||||
goto baddevice;
|
||||
}
|
||||
multi = (ndev > 1) ? 1 : 0;
|
||||
if (!multi) snprintf(instname, 255, "%s%s", model, inst);
|
||||
while (ndev > 0)
|
||||
{
|
||||
if (multi) snprintf(instname, 255, "%s%s.%d", model, inst, ndev);
|
||||
Cell(instname, model, anode, cathode);
|
||||
pobj = LinkProperties(model, kvlist);
|
||||
ReduceExpressions(pobj, CurrentCell, TRUE);
|
||||
ndev--;
|
||||
}
|
||||
snprintf(instname, 255, "%s%s", model, inst);
|
||||
Cell(instname, model, anode, cathode);
|
||||
pobj = LinkProperties(model, kvlist);
|
||||
ReduceExpressions(pobj, NULL, CurrentCell, TRUE);
|
||||
DeleteProperties(&kvlist);
|
||||
}
|
||||
else if (toupper(nexttok[0]) == 'T') { /* transmission line */
|
||||
@@ -1254,16 +1210,12 @@ skip_ends:
|
||||
snprintf(model, 99, "%s", nexttok);
|
||||
|
||||
/* Any other device properties? */
|
||||
ndev = 1;
|
||||
while (nexttok != NULL) {
|
||||
SpiceTokNoNewline();
|
||||
if ((nexttok == NULL) || (nexttok[0] == '\0')) break;
|
||||
if ((eqptr = strchr(nexttok, '=')) != NULL) {
|
||||
*eqptr = '\0';
|
||||
if (!strcasecmp(nexttok, "M"))
|
||||
sscanf(eqptr + 1, "%d", &ndev);
|
||||
else
|
||||
AddProperty(&kvlist, nexttok, eqptr + 1);
|
||||
AddProperty(&kvlist, nexttok, eqptr + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1275,6 +1227,7 @@ skip_ends:
|
||||
Port("node2");
|
||||
Port("node3");
|
||||
Port("node4");
|
||||
PropertyInteger(model, filenum, "M", 0, 1);
|
||||
SetClass(CLASS_XLINE);
|
||||
EndCell();
|
||||
ReopenCellDef((*CellStackPtr)->cellname, filenum); /* Reopen */
|
||||
@@ -1290,20 +1243,15 @@ skip_ends:
|
||||
else
|
||||
strcpy(model, "t"); /* Use default xline model */
|
||||
|
||||
multi = (ndev > 1) ? 1 : 0;
|
||||
if (!multi) snprintf(instname, 255, "%s%s", model, inst);
|
||||
snprintf(instname, 255, "%s%s", model, inst);
|
||||
|
||||
while (ndev > 0) {
|
||||
if (multi) snprintf(instname, 255, "%s%s.%d", model, inst, ndev);
|
||||
if (usemodel)
|
||||
Cell(instname, model, node1, node2, node3, node4);
|
||||
else
|
||||
XLine((*CellStackPtr)->cellname, instname, node1, node2,
|
||||
if (usemodel)
|
||||
Cell(instname, model, node1, node2, node3, node4);
|
||||
else
|
||||
XLine((*CellStackPtr)->cellname, instname, node1, node2,
|
||||
node3, node4);
|
||||
pobj = LinkProperties(model, kvlist);
|
||||
ReduceExpressions(pobj, CurrentCell, TRUE);
|
||||
ndev--;
|
||||
}
|
||||
pobj = LinkProperties(model, kvlist);
|
||||
ReduceExpressions(pobj, NULL, CurrentCell, TRUE);
|
||||
DeleteProperties(&kvlist);
|
||||
}
|
||||
}
|
||||
@@ -1343,7 +1291,6 @@ skip_ends:
|
||||
snprintf(model, 99, "%s", nexttok);
|
||||
|
||||
/* Any other device properties? */
|
||||
ndev = 1;
|
||||
while (nexttok != NULL)
|
||||
{
|
||||
/* Parse for M and other parameters */
|
||||
@@ -1353,10 +1300,7 @@ skip_ends:
|
||||
if ((eqptr = strchr(nexttok, '=')) != NULL)
|
||||
{
|
||||
*eqptr = '\0';
|
||||
if (!strcasecmp(nexttok, "M"))
|
||||
sscanf(eqptr + 1, "%d", &ndev);
|
||||
else
|
||||
AddProperty(&kvlist, nexttok, eqptr + 1);
|
||||
AddProperty(&kvlist, nexttok, eqptr + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1366,6 +1310,7 @@ skip_ends:
|
||||
CellDefNoCase(model, filenum);
|
||||
Port("end_a");
|
||||
Port("end_b");
|
||||
PropertyInteger(model, filenum, "M", 0, 1);
|
||||
SetClass(CLASS_INDUCTOR);
|
||||
EndCell();
|
||||
ReopenCellDef((*CellStackPtr)->cellname, filenum); /* Reopen */
|
||||
@@ -1381,19 +1326,13 @@ skip_ends:
|
||||
else
|
||||
strcpy(model, "l"); /* Use default inductor model */
|
||||
|
||||
multi = (ndev > 1) ? 1 : 0;
|
||||
if (!multi) snprintf(instname, 255, "%s%s", model, inst);
|
||||
while (ndev > 0)
|
||||
{
|
||||
if (multi) snprintf(instname, 255, "%s%s.%d", model, inst, ndev);
|
||||
if (usemodel)
|
||||
Cell(instname, model, end_a, end_b);
|
||||
else
|
||||
Inductor((*CellStackPtr)->cellname, instname, end_a, end_b);
|
||||
pobj = LinkProperties(model, kvlist);
|
||||
ReduceExpressions(pobj, CurrentCell, TRUE);
|
||||
ndev--;
|
||||
}
|
||||
snprintf(instname, 255, "%s%s", model, inst);
|
||||
if (usemodel)
|
||||
Cell(instname, model, end_a, end_b);
|
||||
else
|
||||
Inductor((*CellStackPtr)->cellname, instname, end_a, end_b);
|
||||
pobj = LinkProperties(model, kvlist);
|
||||
ReduceExpressions(pobj, NULL, CurrentCell, TRUE);
|
||||
DeleteProperties(&kvlist);
|
||||
}
|
||||
|
||||
@@ -1439,6 +1378,7 @@ skip_ends:
|
||||
CellDefNoCase(model, filenum);
|
||||
Port("pos");
|
||||
Port("neg");
|
||||
PropertyInteger(model, filenum, "M", 0, 1);
|
||||
SetClass(CLASS_MODULE);
|
||||
EndCell();
|
||||
ReopenCellDef((*CellStackPtr)->cellname, filenum); /* Reopen */
|
||||
@@ -1451,7 +1391,7 @@ skip_ends:
|
||||
}
|
||||
Cell(instname, model, pos, neg);
|
||||
pobj = LinkProperties(model, kvlist);
|
||||
ReduceExpressions(pobj, CurrentCell, TRUE);
|
||||
ReduceExpressions(pobj, NULL, CurrentCell, TRUE);
|
||||
DeleteProperties(&kvlist);
|
||||
}
|
||||
else if (toupper(nexttok[0]) == 'I') { /* current source */
|
||||
@@ -1492,6 +1432,7 @@ skip_ends:
|
||||
CellDefNoCase(model, filenum);
|
||||
Port("pos");
|
||||
Port("neg");
|
||||
PropertyInteger(model, filenum, "M", 0, 1);
|
||||
SetClass(CLASS_MODULE);
|
||||
EndCell();
|
||||
ReopenCellDef((*CellStackPtr)->cellname, filenum); /* Reopen */
|
||||
@@ -1504,7 +1445,7 @@ skip_ends:
|
||||
}
|
||||
Cell(instname, model, pos, neg);
|
||||
pobj = LinkProperties(model, kvlist);
|
||||
ReduceExpressions(pobj, CurrentCell, TRUE);
|
||||
ReduceExpressions(pobj, NULL, CurrentCell, TRUE);
|
||||
DeleteProperties(&kvlist);
|
||||
}
|
||||
else if (toupper(nexttok[0]) == 'E') { /* controlled voltage source */
|
||||
@@ -1556,6 +1497,7 @@ skip_ends:
|
||||
Port("neg");
|
||||
Port("ctrlp");
|
||||
Port("ctrln");
|
||||
PropertyInteger(model, filenum, "M", 0, 1);
|
||||
SetClass(CLASS_MODULE);
|
||||
EndCell();
|
||||
ReopenCellDef((*CellStackPtr)->cellname, filenum); /* Reopen */
|
||||
@@ -1568,7 +1510,7 @@ skip_ends:
|
||||
}
|
||||
Cell(instname, model, pos, neg, ctrlp, ctrln);
|
||||
pobj = LinkProperties(model, kvlist);
|
||||
ReduceExpressions(pobj, CurrentCell, TRUE);
|
||||
ReduceExpressions(pobj, NULL, CurrentCell, TRUE);
|
||||
DeleteProperties(&kvlist);
|
||||
}
|
||||
|
||||
@@ -1595,7 +1537,6 @@ skip_ends:
|
||||
head = NULL;
|
||||
tail = NULL;
|
||||
SpiceTokNoNewline();
|
||||
ndev = 1;
|
||||
while (nexttok != NULL) {
|
||||
/* must still be a node or a parameter */
|
||||
struct portelement *new_port;
|
||||
@@ -1623,10 +1564,7 @@ skip_ends:
|
||||
((tp = LookupCellFile(nexttok, filenum)) == NULL))
|
||||
{
|
||||
*eqptr = '\0';
|
||||
if (!strcasecmp(nexttok, "M"))
|
||||
sscanf(eqptr + 1, "%d", &ndev);
|
||||
else
|
||||
AddProperty(&kvlist, nexttok, eqptr + 1);
|
||||
AddProperty(&kvlist, nexttok, eqptr + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1698,6 +1636,7 @@ skip_ends:
|
||||
if (head == NULL) {
|
||||
Port((char *)NULL); // Must have something for pin 1
|
||||
}
|
||||
PropertyInteger(subcktname, filenum, "M", 0, 1);
|
||||
SetClass(CLASS_MODULE);
|
||||
EndCell();
|
||||
ReopenCellDef((*CellStackPtr)->cellname, filenum); /* Reopen */
|
||||
@@ -1705,38 +1644,30 @@ skip_ends:
|
||||
}
|
||||
|
||||
/* nexttok is now NULL, scan->name points to class */
|
||||
multi = (ndev > 1) ? 1 : 0;
|
||||
if (multi) strcat(instancename, ".");
|
||||
while (ndev > 0) {
|
||||
if (multi) {
|
||||
char *dotptr = strrchr(instancename, '.');
|
||||
sprintf(dotptr + 1, "%d", ndev);
|
||||
}
|
||||
Instance(subcktname, instancename);
|
||||
pobj = LinkProperties(subcktname, kvlist);
|
||||
ReduceExpressions(pobj, CurrentCell, TRUE);
|
||||
ndev--;
|
||||
Instance(subcktname, instancename);
|
||||
pobj = LinkProperties(subcktname, kvlist);
|
||||
ReduceExpressions(pobj, NULL, CurrentCell, TRUE);
|
||||
|
||||
/* (Diagnostic) */
|
||||
/* Fprintf(stderr, "instancing subcell: %s (%s):", subcktname, instancename); */
|
||||
/*
|
||||
/* (Diagnostic) */
|
||||
/* Fprintf(stderr, "instancing subcell: %s (%s):", subcktname, instancename); */
|
||||
/*
|
||||
for (scan = head; scan != NULL; scan = scan->next)
|
||||
Fprintf(stderr," %s", scan->name);
|
||||
Fprintf(stderr," %s", scan->name);
|
||||
Fprintf(stderr,"\n");
|
||||
*/
|
||||
*/
|
||||
|
||||
obptr = LookupInstance(instancename, CurrentCell);
|
||||
if (obptr != NULL) {
|
||||
scan = head;
|
||||
if (scan != NULL)
|
||||
do {
|
||||
if (LookupObject(scan->name, CurrentCell) == NULL) Node(scan->name);
|
||||
join(scan->name, obptr->name);
|
||||
obptr = obptr->next;
|
||||
scan = scan->next;
|
||||
} while (obptr != NULL && obptr->type > FIRSTPIN && scan != NULL);
|
||||
obptr = LookupInstance(instancename, CurrentCell);
|
||||
if (obptr != NULL) {
|
||||
scan = head;
|
||||
if (scan != NULL)
|
||||
do {
|
||||
if (LookupObject(scan->name, CurrentCell) == NULL) Node(scan->name);
|
||||
join(scan->name, obptr->name);
|
||||
obptr = obptr->next;
|
||||
scan = scan->next;
|
||||
} while (obptr != NULL && obptr->type > FIRSTPIN && scan != NULL);
|
||||
|
||||
if ((obptr == NULL && scan != NULL) ||
|
||||
if ((obptr == NULL && scan != NULL) ||
|
||||
(obptr != NULL && scan == NULL && obptr->type > FIRSTPIN)) {
|
||||
if (warnings <= 100) {
|
||||
Fprintf(stderr,"Parameter list mismatch in %s: ", instancename);
|
||||
@@ -1750,8 +1681,7 @@ skip_ends:
|
||||
Fprintf(stderr, "Too many warnings. . . will not report any more.\n");
|
||||
}
|
||||
warnings++;
|
||||
}
|
||||
} // repeat over ndev
|
||||
}
|
||||
}
|
||||
DeleteProperties(&kvlist);
|
||||
|
||||
@@ -1844,8 +1774,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 +1786,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
|
||||
|
||||
+2
-2
@@ -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);
|
||||
|
||||
@@ -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=\"[email protected]\" -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=\"[email protected]\" -DPACKAGE_URL=\"\" -DNETGEN_VERSION=\"1.5\" -DNETGEN_REVISION=\"58\" -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
|
||||
|
||||
+39
-39
@@ -125,7 +125,7 @@ configure: failed program was:
|
||||
| #define PACKAGE_BUGREPORT "[email protected]"
|
||||
| #define PACKAGE_URL ""
|
||||
| #define NETGEN_VERSION "1.5"
|
||||
| #define NETGEN_REVISION "50"
|
||||
| #define NETGEN_REVISION "58"
|
||||
| /* end confdefs.h. */
|
||||
| #include <ac_nonexistent.h>
|
||||
configure:3382: result: gcc -E
|
||||
@@ -146,7 +146,7 @@ configure: failed program was:
|
||||
| #define PACKAGE_BUGREPORT "[email protected]"
|
||||
| #define PACKAGE_URL ""
|
||||
| #define NETGEN_VERSION "1.5"
|
||||
| #define NETGEN_REVISION "50"
|
||||
| #define NETGEN_REVISION "58"
|
||||
| /* end confdefs.h. */
|
||||
| #include <ac_nonexistent.h>
|
||||
configure:3445: checking for library containing strerror
|
||||
@@ -261,7 +261,7 @@ configure: failed program was:
|
||||
| #define PACKAGE_BUGREPORT "[email protected]"
|
||||
| #define PACKAGE_URL ""
|
||||
| #define NETGEN_VERSION "1.5"
|
||||
| #define NETGEN_REVISION "50"
|
||||
| #define NETGEN_REVISION "58"
|
||||
| #define STDC_HEADERS 1
|
||||
| #define HAVE_SYS_TYPES_H 1
|
||||
| #define HAVE_SYS_STAT_H 1
|
||||
@@ -302,7 +302,7 @@ configure: failed program was:
|
||||
| #define PACKAGE_BUGREPORT "[email protected]"
|
||||
| #define PACKAGE_URL ""
|
||||
| #define NETGEN_VERSION "1.5"
|
||||
| #define NETGEN_REVISION "50"
|
||||
| #define NETGEN_REVISION "58"
|
||||
| #define STDC_HEADERS 1
|
||||
| #define HAVE_SYS_TYPES_H 1
|
||||
| #define HAVE_SYS_STAT_H 1
|
||||
@@ -382,7 +382,7 @@ configure: failed program was:
|
||||
| #define PACKAGE_BUGREPORT "[email protected]"
|
||||
| #define PACKAGE_URL ""
|
||||
| #define NETGEN_VERSION "1.5"
|
||||
| #define NETGEN_REVISION "50"
|
||||
| #define NETGEN_REVISION "58"
|
||||
| #define STDC_HEADERS 1
|
||||
| #define HAVE_SYS_TYPES_H 1
|
||||
| #define HAVE_SYS_STAT_H 1
|
||||
@@ -454,7 +454,7 @@ configure: failed program was:
|
||||
| #define PACKAGE_BUGREPORT "[email protected]"
|
||||
| #define PACKAGE_URL ""
|
||||
| #define NETGEN_VERSION "1.5"
|
||||
| #define NETGEN_REVISION "50"
|
||||
| #define NETGEN_REVISION "58"
|
||||
| #define STDC_HEADERS 1
|
||||
| #define HAVE_SYS_TYPES_H 1
|
||||
| #define HAVE_SYS_STAT_H 1
|
||||
@@ -491,37 +491,37 @@ configure:4831: checking for tclConfig.sh
|
||||
configure:4903: result: /usr/lib64/tclConfig.sh
|
||||
configure:4919: checking for tkConfig.sh
|
||||
configure:4992: result: /usr/lib64/tkConfig.sh
|
||||
configure:5106: checking for wish executable
|
||||
configure:5133: result: /usr/bin/wish
|
||||
configure:5139: checking for tclsh executable
|
||||
configure:5165: result: /usr/bin/tclsh
|
||||
configure:5288: checking for X
|
||||
configure:5427: gcc -o conftest -g conftest.c -lX11 >&5
|
||||
configure:5427: $? = 0
|
||||
configure:5477: result: libraries , headers
|
||||
configure:5576: gcc -o conftest -g conftest.c -lX11 >&5
|
||||
configure:5576: $? = 0
|
||||
configure:5674: checking for gethostbyname
|
||||
configure:5674: gcc -o conftest -g conftest.c >&5
|
||||
configure:5674: $? = 0
|
||||
configure:5674: result: yes
|
||||
configure:5771: checking for connect
|
||||
configure:5771: gcc -o conftest -g conftest.c >&5
|
||||
configure:5771: $? = 0
|
||||
configure:5771: result: yes
|
||||
configure:5820: checking for remove
|
||||
configure:5820: gcc -o conftest -g conftest.c >&5
|
||||
configure:5820: $? = 0
|
||||
configure:5820: result: yes
|
||||
configure:5869: checking for shmat
|
||||
configure:5869: gcc -o conftest -g conftest.c >&5
|
||||
configure:5869: $? = 0
|
||||
configure:5869: result: yes
|
||||
configure:5927: checking for IceConnectionNumber in -lICE
|
||||
configure:5952: gcc -o conftest -g conftest.c -lICE >&5
|
||||
configure:5952: $? = 0
|
||||
configure:5961: result: yes
|
||||
configure:6675: creating ./config.status
|
||||
configure:5125: checking for wish executable
|
||||
configure:5152: result: /usr/bin/wish
|
||||
configure:5158: checking for tclsh executable
|
||||
configure:5184: result: /usr/bin/tclsh
|
||||
configure:5307: checking for X
|
||||
configure:5446: gcc -o conftest -g conftest.c -lX11 >&5
|
||||
configure:5446: $? = 0
|
||||
configure:5496: result: libraries , headers
|
||||
configure:5595: gcc -o conftest -g conftest.c -lX11 >&5
|
||||
configure:5595: $? = 0
|
||||
configure:5693: checking for gethostbyname
|
||||
configure:5693: gcc -o conftest -g conftest.c >&5
|
||||
configure:5693: $? = 0
|
||||
configure:5693: result: yes
|
||||
configure:5790: checking for connect
|
||||
configure:5790: gcc -o conftest -g conftest.c >&5
|
||||
configure:5790: $? = 0
|
||||
configure:5790: result: yes
|
||||
configure:5839: checking for remove
|
||||
configure:5839: gcc -o conftest -g conftest.c >&5
|
||||
configure:5839: $? = 0
|
||||
configure:5839: result: yes
|
||||
configure:5888: checking for shmat
|
||||
configure:5888: gcc -o conftest -g conftest.c >&5
|
||||
configure:5888: $? = 0
|
||||
configure:5888: result: yes
|
||||
configure:5946: checking for IceConnectionNumber in -lICE
|
||||
configure:5971: gcc -o conftest -g conftest.c -lICE >&5
|
||||
configure:5971: $? = 0
|
||||
configure:5980: result: yes
|
||||
configure:6694: creating ./config.status
|
||||
|
||||
## ---------------------- ##
|
||||
## Running config.status. ##
|
||||
@@ -621,7 +621,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=\"[email protected]\" -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=\"[email protected]\" -DPACKAGE_URL=\"\" -DNETGEN_VERSION=\"1.5\" -DNETGEN_REVISION=\"58\" -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 +734,7 @@ unused=''
|
||||
#define PACKAGE_BUGREPORT "[email protected]"
|
||||
#define PACKAGE_URL ""
|
||||
#define NETGEN_VERSION "1.5"
|
||||
#define NETGEN_REVISION "50"
|
||||
#define NETGEN_REVISION "58"
|
||||
#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=\\\"58\\\" -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"
|
||||
|
||||
Vendored
+21
-2
@@ -4861,7 +4861,7 @@ $as_echo_n "checking for tclConfig.sh... " >&6; }
|
||||
# 1. Search previously named locations.
|
||||
|
||||
for dir in \
|
||||
$prefix \
|
||||
$ac_default_prefix \
|
||||
$exec_prefix
|
||||
do
|
||||
if test -r "$dir/tclConfig.sh" ; then
|
||||
@@ -4948,7 +4948,7 @@ $as_echo_n "checking for tkConfig.sh... " >&6; }
|
||||
# 1. Search previously named locations.
|
||||
#
|
||||
for dir in \
|
||||
$prefix \
|
||||
$ac_default_prefix \
|
||||
$exec_prefix
|
||||
do
|
||||
if test -r "$dir/tkConfig.sh" ; then
|
||||
@@ -5007,6 +5007,25 @@ if test $usingTcl ; then
|
||||
. $tcl_config_sh
|
||||
. $tk_config_sh
|
||||
|
||||
# Should probably trust the config file contents, but this configure
|
||||
# file checks the Tcl and Tk include and lib directories. Since
|
||||
# the config file doesn't separate out the libraries from the strings
|
||||
# passed to the compiler/linker, do it manually here.
|
||||
#
|
||||
# Extract TCL_LIB_DIR from TCL_LIB_SPEC
|
||||
# Extract TK_LIB_DIR from TK_LIB_SPEC
|
||||
# Extract TCL_INC_DIR from TCL_INCLUDE_SPEC
|
||||
# Extract TK_INC_DIR from TK_INCLUDE_SPEC
|
||||
#
|
||||
# These will be the defaults unless overridden by configure command line
|
||||
|
||||
tmpstr=${TCL_LIB_SPEC#*-L}
|
||||
TCL_LIB_DIR=${tmpstr% -l*}
|
||||
tmpstr=${TK_LIB_SPEC#*-L}
|
||||
TK_LIB_DIR=${tmpstr% -l*}
|
||||
TCL_INC_DIR=${TCL_INCLUDE_SPEC#*-I}
|
||||
TK_INC_DIR=${TK_INCLUDE_SPEC#*-I}
|
||||
|
||||
if test "$TCL_VERSION" = "7.6" -a "$TK_VERSION" = "4.2" ; then
|
||||
:
|
||||
elif test "$TCL_VERSION" = "7.5" -a "$TK_VERSION" = "4.1" ; then
|
||||
|
||||
@@ -472,6 +472,25 @@ if test $usingTcl ; then
|
||||
. $tcl_config_sh
|
||||
. $tk_config_sh
|
||||
|
||||
# Should probably trust the config file contents, but this configure
|
||||
# file checks the Tcl and Tk include and lib directories. Since
|
||||
# the config file doesn't separate out the libraries from the strings
|
||||
# passed to the compiler/linker, do it manually here.
|
||||
#
|
||||
# Extract TCL_LIB_DIR from TCL_LIB_SPEC
|
||||
# Extract TK_LIB_DIR from TK_LIB_SPEC
|
||||
# Extract TCL_INC_DIR from TCL_INCLUDE_SPEC
|
||||
# Extract TK_INC_DIR from TK_INCLUDE_SPEC
|
||||
#
|
||||
# These will be the defaults unless overridden by configure command line
|
||||
|
||||
tmpstr=${TCL_LIB_SPEC#*-L}
|
||||
TCL_LIB_DIR=${tmpstr% -l*}
|
||||
tmpstr=${TK_LIB_SPEC#*-L}
|
||||
TK_LIB_DIR=${tmpstr% -l*}
|
||||
TCL_INC_DIR=${TCL_INCLUDE_SPEC#*-I}
|
||||
TK_INC_DIR=${TK_INCLUDE_SPEC#*-I}
|
||||
|
||||
if test "$TCL_VERSION" = "7.6" -a "$TK_VERSION" = "4.2" ; then
|
||||
:
|
||||
elif test "$TCL_VERSION" = "7.5" -a "$TK_VERSION" = "4.1" ; then
|
||||
|
||||
+1
-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=\"[email protected]\" -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=\"[email protected]\" -DPACKAGE_URL=\"\" -DNETGEN_VERSION=\"1.5\" -DNETGEN_REVISION=\"58\" -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
|
||||
|
||||
+1
-1
@@ -126,7 +126,7 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out}} {
|
||||
}
|
||||
} else {
|
||||
netgen::permute default ;# transistors and resistors
|
||||
netgen::combine default ;# standard parallel/serial allowances
|
||||
netgen::property default
|
||||
}
|
||||
|
||||
puts stdout "Comparison output logged to file $logfile"
|
||||
|
||||
+103
-186
@@ -91,7 +91,6 @@ int _netcmp_automorphs(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_equate(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_ignore(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_permute(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_combine(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_property(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_exhaustive(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_restart(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
@@ -231,14 +230,8 @@ Command netcmp_cmds[] = {
|
||||
"capacitor: enable capacitor permutations\n "
|
||||
"transistor: enable transistor permutations\n "
|
||||
"(none): enable transistor and resistor permutations"},
|
||||
{"combine", _netcmp_combine,
|
||||
"[transistors|resistors|capacitors|<model>]\n "
|
||||
"<model> [<serial>|<parallel>]: enable combinations of device model\n "
|
||||
"resistor: enable resistor serial/parallel combinations\n "
|
||||
"capacitor: enable capacitor parallel combinations\n "
|
||||
"transistor: enable transistor parallel combinations\n "
|
||||
"(none): enable standard combinations"},
|
||||
{"property", _netcmp_property,
|
||||
"default: apply property defaults\n "
|
||||
"<device>|<model> <property_key> [...]\n "
|
||||
"<device>: name of a device type (capacitor, etc.)\n "
|
||||
"<model>: name of a device model\n "
|
||||
@@ -2970,6 +2963,9 @@ _netcmp_equate(ClientData clientData,
|
||||
/* add --- add new property */
|
||||
/* remove --- delete existing property */
|
||||
/* tolerance --- set property tolerance */
|
||||
/* merge --- set property merge behavior */
|
||||
/* or */
|
||||
/* netgen::property default */
|
||||
/* Formerly: (none) */
|
||||
/* Results: */
|
||||
/* Side Effects: */
|
||||
@@ -2987,10 +2983,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,10 +2997,55 @@ _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;
|
||||
}
|
||||
|
||||
/* Check for special command "property default" */
|
||||
if ((objc == 2) && (!strcmp(Tcl_GetString(objv[1]), "default"))) {
|
||||
|
||||
/* For each FET device, do "merge {w add_critical}" and */
|
||||
/* "remove as ad ps pd". This allows parallel devices */
|
||||
/* to be added by width, and prevents attempts to */
|
||||
/* compare source/drain area and perimeter. */
|
||||
|
||||
tp = FirstCell();
|
||||
while (tp != NULL) {
|
||||
switch (tp->class) {
|
||||
case CLASS_NMOS: case CLASS_PMOS: case CLASS_FET3:
|
||||
case CLASS_NMOS4: case CLASS_PMOS4: case CLASS_FET4:
|
||||
case CLASS_FET:
|
||||
PropertyMerge(tp->name, tp->file, "w", MERGE_ADD_CRIT);
|
||||
PropertyDelete(tp->name, tp->file, "as");
|
||||
PropertyDelete(tp->name, tp->file, "ad");
|
||||
PropertyDelete(tp->name, tp->file, "ps");
|
||||
PropertyDelete(tp->name, tp->file, "pd");
|
||||
break;
|
||||
case CLASS_RES: case CLASS_RES3:
|
||||
PropertyMerge(tp->name, tp->file, "l", MERGE_PAR_CRIT);
|
||||
break;
|
||||
case CLASS_CAP: case CLASS_ECAP: case CLASS_CAP3:
|
||||
// NOTE: No attempt to combine area, width, or length;
|
||||
// only value.
|
||||
PropertyMerge(tp->name, tp->file, "value", MERGE_ADD_CRIT);
|
||||
break;
|
||||
case CLASS_INDUCTOR:
|
||||
PropertyMerge(tp->name, tp->file, "value", MERGE_PAR_CRIT);
|
||||
break;
|
||||
}
|
||||
tp = NextCell();
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
result = CommonParseCell(interp, objv[1], &tp, &fnum);
|
||||
if (result != TCL_OK) return result;
|
||||
|
||||
@@ -3012,7 +3053,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 +3080,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 +3216,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,180 +3260,58 @@ _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;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* Function name: _netcmp_combine */
|
||||
/* Syntax: netgen::combine [default] */
|
||||
/* netgen::combine combine_class */
|
||||
/* netgen::combine valid_cellname serial|parallel */
|
||||
/* netgen::combine forget valid_cellname */
|
||||
/* netgen::combine forget */
|
||||
/* Formerly: t */
|
||||
/* Results: */
|
||||
/* Side Effects: */
|
||||
/*--------------------------------------------------------------*/
|
||||
|
||||
int
|
||||
_netcmp_combine(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
{
|
||||
char *model;
|
||||
char *combineclass[] = {
|
||||
"transistors", "resistors", "capacitors", "default", "forget",
|
||||
"cell", NULL
|
||||
};
|
||||
enum OptionIdx {
|
||||
TRANS_IDX, RES_IDX, CAP_IDX, DEFLT_IDX, FORGET_IDX, CELL_IDX
|
||||
};
|
||||
int result, index, index2, fnum = -1;
|
||||
struct nlist *tp = NULL;
|
||||
|
||||
char *combinetype[] = {
|
||||
"serial", "parallel", NULL
|
||||
};
|
||||
enum SubOptionIdx {
|
||||
SERIAL_IDX, PARALLEL_IDX
|
||||
};
|
||||
|
||||
if (objc > 3) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?valid_cellname serial|parallel?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (objc == 1) {
|
||||
index = DEFLT_IDX;
|
||||
}
|
||||
else {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)combineclass,
|
||||
"combine class", 0, &index) != TCL_OK) {
|
||||
if (objc != 3) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?valid_cellname serial|parallel?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
result = CommonParseCell(interp, objv[1], &tp, &fnum);
|
||||
if (result != TCL_OK) {
|
||||
Fprintf(stdout, "No such device \"%s\".\n",
|
||||
Tcl_GetString(objv[1]));
|
||||
return result;
|
||||
}
|
||||
index = CELL_IDX;
|
||||
if (Tcl_GetIndexFromObj(interp, objv[2],
|
||||
(CONST84 char **)combinetype,
|
||||
"combine type", 0, &index2) != TCL_OK) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv,
|
||||
"?valid_cellname serial|parallel?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
else if (index == CELL_IDX) {
|
||||
if (objc != 4) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "cell ?valid_cellname serial|parallel?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
result = CommonParseCell(interp, objv[2], &tp, &fnum);
|
||||
if (result != TCL_OK) {
|
||||
Fprintf(stdout, "No such device \"%s\".\n",
|
||||
Tcl_GetString(objv[2]));
|
||||
return result;
|
||||
}
|
||||
if (Tcl_GetIndexFromObj(interp, objv[3],
|
||||
(CONST84 char **)combinetype,
|
||||
"combine type", 0, &index2) != TCL_OK) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv,
|
||||
"?valid_cellname serial|parallel?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
else if (index == FORGET_IDX) {
|
||||
if (objc < 3) {
|
||||
/* General purpose combine forget */
|
||||
tp = FirstCell();
|
||||
while (tp != NULL) {
|
||||
CombineForget(tp->name, tp->file, NULL);
|
||||
tp = NextCell();
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
else {
|
||||
/* Specific combine forget */
|
||||
result = CommonParseCell(interp, objv[2], &tp, &fnum);
|
||||
if (result != TCL_OK) {
|
||||
Fprintf(stdout, "No such device \"%s\".\n",
|
||||
Tcl_GetString(objv[2]));
|
||||
return result;
|
||||
}
|
||||
if (objc != 4) {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[3],
|
||||
(CONST84 char **)combinetype,
|
||||
"combine type", 0, &index2) != TCL_OK) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv,
|
||||
"?valid_cellname serial|parallel?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (CombineForget(tp->name, fnum, (index2 == SERIAL_IDX)
|
||||
? COMB_SERIAL : COMB_PARALLEL))
|
||||
Fprintf(stdout, "Model %s combine %s\n", tp->name,
|
||||
(index2 == SERIAL_IDX) ? "serial" : "parallel");
|
||||
else
|
||||
Fprintf(stderr, "Unable to reset model %s %s combination.\n",
|
||||
tp->name, (index2 == SERIAL_IDX) ? "serial" : "parallel");
|
||||
}
|
||||
else {
|
||||
if (CombineForget(tp->name, fnum, NULL))
|
||||
Fprintf(stdout, "No combinations of circuit %s allowed\n", tp->name);
|
||||
else
|
||||
Fprintf(stderr, "Unable to reset model %s %s combinations\n",
|
||||
tp->name, (index2 == SERIAL_IDX) ? "serial" : "parallel");
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (objc == 1 || objc == 2) {
|
||||
tp = FirstCell();
|
||||
while (tp != NULL) {
|
||||
switch (tp->class) {
|
||||
case CLASS_NMOS: case CLASS_PMOS: case CLASS_FET3:
|
||||
case CLASS_NMOS4: case CLASS_PMOS4: case CLASS_FET4:
|
||||
case CLASS_FET:
|
||||
if (index == TRANS_IDX || index == DEFLT_IDX)
|
||||
CombineSetup(tp->name, tp->file, COMB_PARALLEL);
|
||||
break;
|
||||
case CLASS_RES: case CLASS_RES3:
|
||||
if (index == RES_IDX || index == DEFLT_IDX) {
|
||||
CombineSetup(tp->name, tp->file, COMB_SERIAL);
|
||||
CombineSetup(tp->name, tp->file, COMB_PARALLEL);
|
||||
}
|
||||
break;
|
||||
case CLASS_CAP: case CLASS_ECAP: case CLASS_CAP3:
|
||||
if (index == CAP_IDX)
|
||||
CombineSetup(tp->name, tp->file, COMB_PARALLEL);
|
||||
break;
|
||||
}
|
||||
tp = NextCell();
|
||||
}
|
||||
}
|
||||
else if (index == CELL_IDX) {
|
||||
if (CombineSetup(tp->name, fnum, ((index2 == SERIAL_IDX) ?
|
||||
COMB_SERIAL : COMB_PARALLEL)))
|
||||
Fprintf(stdout, "Model %s allow %s combinations\n", tp->name,
|
||||
(index2 == SERIAL_IDX) ? "serial" : "parallel");
|
||||
else
|
||||
Fprintf(stderr, "Unable to set model %s %s combinations.\n",
|
||||
tp->name, (index2 == SERIAL_IDX) ?
|
||||
"serial" : "parallel");
|
||||
}
|
||||
else {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?valid_cellname serial|parallel?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* Function name: _netcmp_permute */
|
||||
/* Syntax: netgen::permute [default] */
|
||||
|
||||
Reference in New Issue
Block a user