diff --git a/base/flatten.c b/base/flatten.c index 86b6bf1..c1d1132 100644 --- a/base/flatten.c +++ b/base/flatten.c @@ -24,6 +24,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config.h" #include +#include #ifdef IBMPC #include @@ -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; @@ -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 */ @@ -466,28 +469,19 @@ int flattenInstancesOf(char *name, int fnum, char *instance) 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); } @@ -1304,6 +1298,88 @@ typedef struct ecomplist { ECompListPtr next; } ECompList; +/*------------------------------------------------------*/ +/* Split a device into multiple devices based on a */ +/* critical property; e.g., MOSFET width. Devices with */ +/* property name equal to kl->key and value "value" */ +/* will be split into "ndev" devices with the property */ +/* of each divided down by "ndev". */ +/*------------------------------------------------------*/ + +void +SplitDevice(struct nlist *tc, struct nlist *cell, struct property *kl, + double value, int ndev, int file1, int file2, int which) +{ + struct objlist *ob, *ob2, *newdevs, *ob3, *lastob, *nob; + struct nlist *tsub; + unsigned char found; + int file = (which == 0) ? file1 : file2; + + newdevs = NULL; /* Linked list of the copied devices */ + + for (ob = tc->cell; ob; ob = ob->next) { + if (ob->type == FIRSTPIN) { + tsub = LookupCellFile(ob->model.class, file); + if (tsub == cell) { + + // Advance ob to property list + found = 0; + for (ob2 = ob->next; ob2 && ob2->type != FIRSTPIN; ob2 = ob2->next) { + if (ob2->type == PROPERTY) { + struct valuelist *kv; + int i; + double dval = 0.0; + for (i = 0; ; i++) { + kv = &(ob2->instance.props[i]); + if (kv->type == PROP_ENDLIST) break; + if ((*matchfunc)(kv->key, kl->key)) { + switch(kv->type) { + case PROP_INTEGER: + dval = (double)kv->value.ival; + break; + case PROP_DOUBLE: + case PROP_VALUE: + dval = kv->value.dval; + break; + } + break; + } + } + + /* To-do: Account for slop */ + + if (dval == value) { + switch(kv->type) { + case PROP_INTEGER: + kv->value.ival /= ndev; + found = 1; + break; + case PROP_DOUBLE: + case PROP_VALUE: + kv->value.dval /= ndev; + found = 1; + break; + } + } + } + if (found) break; + } + if (found) { + int i; + for (i = 1; i < ndev; i++) { + ob3 = CopyObjList(ob, 0); // Make exact copy + for (nob = ob3; nob->next != NULL; nob = nob->next); + nob->next = newdevs; + newdevs = ob3; + } + } + } + } + lastob = ob; + } + lastob->next = newdevs; // Append new devices to list +} + /*------------------------------------------------------*/ /* Survey a specific device in a cell and sort into a */ /* hash by critical property. */ @@ -1353,6 +1429,8 @@ SurveyDevice(struct nlist *tc, struct hashdict *devdict, d2str += 2; // Advance ob to property list + // To-do: Quantize values according to slop + for (ob2 = ob->next; ob2 && ob2->type != FIRSTPIN; ob2 = ob2->next) { if (ob2->type == PROPERTY) { struct valuelist *kv; @@ -1811,6 +1889,9 @@ PrematchLists(char *name1, int file1, char *name2, int file2) // and merge devices where merging makes a better match. struct property *kl1, *kl2; + double slop = 0.0; + + // Look for a mergeable property in cell1 kl1 = (struct property *)HashFirst(&(ecomp->cell1->propdict)); while (kl1 != NULL) { @@ -1818,13 +1899,63 @@ PrematchLists(char *name1, int file1, char *name2, int file2) break; kl1 = (struct property *)HashNext(&(ecomp->cell1->propdict)); } + + // Look for the equivalent property in cell2 (mergeable or not). + // If cell1 had no mergeable properties, then look for one is cell2. + kl2 = (struct property *)HashFirst(&(ecomp->cell2->propdict)); while (kl2 != NULL) { - if (kl2->merge == MERGE_ADD_CRIT || kl2->merge == MERGE_PAR_CRIT) + if (kl1 != NULL) { + if ((*matchfunc)(kl1->key, kl2->key)) + break; + } + else if (kl2->merge == MERGE_ADD_CRIT || kl2->merge == MERGE_PAR_CRIT) break; - kl2 = (struct property *)HashNext(&(ecomp->cell1->propdict)); + kl2 = (struct property *)HashNext(&(ecomp->cell2->propdict)); } - if (kl1 != NULL || kl2 != NULL) { + if (kl2 != NULL) { + // Get slop value + switch (kl2->type) { + case PROP_INTEGER: + slop = (double)kl2->slop.ival; + break; + case PROP_DOUBLE: + case PROP_VALUE: + slop = kl2->slop.dval; + break; + } + } + + // If cell2 had a mergeable property but cell1 didn't, then look + // through cell1 again to find the equivalent property. + + if ((kl1 == NULL) && (kl2 != NULL)) { + kl1 = (struct property *)HashFirst(&(ecomp->cell1->propdict)); + while (kl1 != NULL) { + if ((*matchfunc)(kl1->key, kl2->key)) + break; + kl1 = (struct property *)HashNext(&(ecomp->cell1->propdict)); + } + } + if (kl1 != NULL) { + // Get slop value + switch (kl1->type) { + case PROP_INTEGER: + slop = MAX(slop, (double)kl1->slop.ival); + break; + case PROP_DOUBLE: + case PROP_VALUE: + slop = MAX(slop, kl1->slop.dval); + break; + } + } + + if ((kl1 != NULL) && (kl2 != NULL)) { + + double dval, dval1, dval2, mindev, pd, df, dr; + unsigned char dosplit; + char *valptr; + int ndev; // Create the device hash table @@ -1833,20 +1964,65 @@ PrematchLists(char *name1, int file1, char *name2, int file2) // Populate the device hash table SurveyDevice(tc1, &devdict, ecomp->cell1, kl1, file1, file2, 0); - SurveyDevice(tc2, &devdict, ecomp->cell2, kl2, file1, file2, 0); + SurveyDevice(tc2, &devdict, ecomp->cell2, kl2, file1, file2, 1); // Scan the device hash table. If devices can be merged // and this improves the matching between cells, then do // the merge. + mindev = 1E20; + dval1 = dval2 = 0.0; + dcomp = (ECompare *)HashFirst(&devdict); while (dcomp != NULL) { - if (dcomp->num1 != dcomp->num2) { - /* XXX WIP WIP WIP XXX */ + if ((dcomp->num1 == 0) || (dcomp->num2 == 0)) { + valptr = strstr(devdict.hashfirstptr->name, "::"); + if (sscanf(valptr + 2, "%lg", &dval) == 1) { + if (dval < mindev) mindev = dval; + if (dcomp->num1 == 0) + dval2 += (dval * dcomp->num2) / dcomp->refcount; + else + dval1 += (dval * dcomp->num1) / dcomp->refcount; + } } dcomp = (ECompare *)HashNext(&devdict); } + // If dval2 and dval1 agree within slop, and both are + // divisible by mindev, then break up all devices into + // sizes of mindev. + + dosplit = 0; + pd = 2 * fabs(dval1 - dval2) / (dval1 + dval2); + if (pd < slop) { + df = dval1 / mindev; + dr = round(df); + pd = 2 * fabs(df - dr) / (df + dr); + if (pd < slop) dosplit = 1; + } + + if (dosplit) { + dcomp = (ECompare *)HashFirst(&devdict); + while (dcomp != NULL) { + if (dcomp->num1 == 0 || dcomp->num2 == 0) { + valptr = strstr(devdict.hashfirstptr->name, "::"); + sscanf(valptr + 2, "%lg", &dval); + ndev = (int)round(dval / mindev); + } + if (dcomp->num1 == 0) { + SplitDevice(tc2, ecomp->cell2, kl2, dval, ndev, + file1, file2, 1); + modified++; + } + else if (dcomp->num2 == 0) { + SplitDevice(tc1, ecomp->cell1, kl1, dval, ndev, + file1, file2, 0); + modified++; + } + dcomp = (ECompare *)HashNext(&devdict); + } + } + // Free the device hash table dcomp = (ECompare *)HashFirst(&devdict); diff --git a/base/netcmp.c b/base/netcmp.c index 55abf65..b663553 100644 --- a/base/netcmp.c +++ b/base/netcmp.c @@ -4476,6 +4476,11 @@ int reorderpins(struct hashlist *p, int file) } ob = ob->next; ob2 = ob2->next; + if (ob == NULL) { + Fprintf(stderr, "Instance of %s has only %d of %d ports\n", + tc2->name, i + 1, numports); + break; + } } ob = firstpin; @@ -4491,6 +4496,7 @@ int reorderpins(struct hashlist *p, int file) HashPtrInstall(ob->name, ob, &(ptr->objdict)); ob = ob->next; names[i] = NULL; + if (ob == NULL) break; // Error message already output } } else diff --git a/base/netgen.c b/base/netgen.c index f9f0dc5..9d40349 100644 --- a/base/netgen.c +++ b/base/netgen.c @@ -168,12 +168,18 @@ struct tokstack *CopyTokStack(struct tokstack *stack) /* value was successfully converted, 0 if there was no value to */ /* convert (empty string), and -1 if unable to convert the */ /* string to a value (e.g., unknown parameter name). */ +/* */ +/* Inheritance is taken from "parprops" (instanced property */ +/* values) if available, and from parent->propdict if not, or */ +/* if the property is not instanced. */ /*--------------------------------------------------------------*/ -int TokGetValue(char *estr, struct nlist *parent, int glob, double *dval) +int TokGetValue(char *estr, struct nlist *parent, struct objlist *parprops, + int glob, double *dval) { struct property *kl = NULL; - int result; + struct valuelist *kv; + int i, result; if (*estr == '\0') return 0; @@ -195,22 +201,50 @@ int TokGetValue(char *estr, struct nlist *parent, int glob, double *dval) } } - /* Check local parameters */ - kl = (struct property *)HashLookup(estr, &(parent->propdict)); - if (kl != NULL) { - switch(kl->type) { - case PROP_STRING: - result = ConvertStringToFloat(kl->pdefault.string, dval); - break; - case PROP_DOUBLE: - case PROP_VALUE: - *dval = kl->pdefault.dval; - result = 1; - break; - case PROP_INTEGER: - *dval = (double)kl->pdefault.ival; - result = 1; + /* Check local instanced parameters */ + result = 0; + if ((parprops != NULL) && (parprops->type == PROPERTY)) { + for (i = 0; ; i++) { + kv = &(parprops->instance.props[i]); + if (kv->type == PROP_ENDLIST) break; + else if ((*matchfunc)(estr, kv->key)) { + switch (kv->type) { + case PROP_STRING: + result = ConvertStringToFloat(kv->value.string, dval); + break; + case PROP_DOUBLE: + case PROP_VALUE: + *dval = kv->value.dval; + result = 1; + break; + case PROP_INTEGER: + *dval = (double)kv->value.ival; + result = 1; + break; + } break; + } + } + } + + /* Check local parent parameters */ + if (result == 0) { + kl = (struct property *)HashLookup(estr, &(parent->propdict)); + if (kl != NULL) { + switch(kl->type) { + case PROP_STRING: + result = ConvertStringToFloat(kl->pdefault.string, dval); + break; + case PROP_DOUBLE: + case PROP_VALUE: + *dval = kl->pdefault.dval; + result = 1; + break; + case PROP_INTEGER: + *dval = (double)kl->pdefault.ival; + result = 1; + break; + } } } return ((result == 0) ? -1 : 1); @@ -228,14 +262,14 @@ int TokGetValue(char *estr, struct nlist *parent, int glob, double *dval) /* single value, then replace the property type. */ /*--------------------------------------------------------------*/ -int ReduceExpressions(struct objlist *instprop, +int ReduceExpressions(struct objlist *instprop, struct objlist *parprops, struct nlist *parent, int glob) { struct tokstack *expstack, *stackptr, *lptr, *nptr; struct valuelist *kv; struct property *kl = NULL; char *estr, *tstr, *sstr; - int toktype, functype, i, result, modified, numlast; + int toktype, functype, i, result, modified, numlast, savetok; double dval; if (instprop == NULL) return 0; // Nothing to do @@ -245,7 +279,9 @@ int ReduceExpressions(struct objlist *instprop, kv = &(instprop->instance.props[i]); - if (kv->type == PROP_EXPRESSION) { + if (kv->type == PROP_ENDLIST) + break; + else if (kv->type == PROP_EXPRESSION) { expstack = kv->value.stack; } else if (kv->type == PROP_STRING) { @@ -269,7 +305,7 @@ int ReduceExpressions(struct objlist *instprop, } /* Not a number, so must be arithmetic */ *tstr = '\0'; - result = TokGetValue(estr, parent, glob, &dval); + result = TokGetValue(estr, parent, parprops, glob, &dval); if (result == 1) PushTok(TOK_DOUBLE, &dval, &expstack); else if (result == -1) PushTok(TOK_STRING, estr, &expstack); PushTok(TOK_PLUS, NULL, &expstack); @@ -289,7 +325,7 @@ int ReduceExpressions(struct objlist *instprop, } /* Not a number, so must be arithmetic */ *tstr = '\0'; - result = TokGetValue(estr, parent, glob, &dval); + result = TokGetValue(estr, parent, parprops, glob, &dval); if (result == 1) PushTok(TOK_DOUBLE, &dval, &expstack); else if (result == -1) PushTok(TOK_STRING, estr, &expstack); PushTok(TOK_MINUS, NULL, &expstack); @@ -310,7 +346,7 @@ int ReduceExpressions(struct objlist *instprop, case '/': *tstr = '\0'; - result = TokGetValue(estr, parent, glob, &dval); + result = TokGetValue(estr, parent, parprops, glob, &dval); if (result == 1) PushTok(TOK_DOUBLE, &dval, &expstack); else if (result == -1) PushTok(TOK_STRING, estr, &expstack); PushTok(TOK_DIVIDE, NULL, &expstack); @@ -320,7 +356,7 @@ int ReduceExpressions(struct objlist *instprop, case '*': *tstr = '\0'; - result = TokGetValue(estr, parent, glob, &dval); + result = TokGetValue(estr, parent, parprops, glob, &dval); if (result == 1) PushTok(TOK_DOUBLE, &dval, &expstack); else if (result == -1) PushTok(TOK_STRING, estr, &expstack); PushTok(TOK_MULTIPLY, NULL, &expstack); @@ -339,7 +375,7 @@ int ReduceExpressions(struct objlist *instprop, else { /* Treat as a parenthetical grouping */ - result = TokGetValue(estr, parent, glob, &dval); + result = TokGetValue(estr, parent, parprops, glob, &dval); if (result == 1) PushTok(TOK_DOUBLE, &dval, &expstack); else if (result == -1) PushTok(TOK_STRING, estr, &expstack); PushTok(TOK_FUNC_OPEN, NULL, &expstack); @@ -350,8 +386,15 @@ int ReduceExpressions(struct objlist *instprop, case ')': *tstr = '\0'; + if (expstack == NULL) break; - switch (expstack->toktype) { + savetok = expstack->toktype; + + result = TokGetValue(estr, parent, parprops, glob, &dval); + if (result == 1) PushTok(TOK_DOUBLE, &dval, &expstack); + else if (result == -1) PushTok(TOK_STRING, estr, &expstack); + + switch (savetok) { case TOK_FUNC_THEN: PushTok(TOK_FUNC_ELSE, NULL, &expstack); break; @@ -365,7 +408,7 @@ int ReduceExpressions(struct objlist *instprop, case '\'': *tstr = '\0'; - result = TokGetValue(estr, parent, glob, &dval); + result = TokGetValue(estr, parent, parprops, glob, &dval); if (result == 1) PushTok(TOK_DOUBLE, &dval, &expstack); else if (result == -1) PushTok(TOK_STRING, estr, &expstack); PushTok(TOK_SGL_QUOTE, NULL, &expstack); @@ -375,7 +418,7 @@ int ReduceExpressions(struct objlist *instprop, case '"': *tstr = '\0'; - result = TokGetValue(estr, parent, glob, &dval); + result = TokGetValue(estr, parent, parprops, glob, &dval); if (result == 1) PushTok(TOK_DOUBLE, &dval, &expstack); else if (result == -1) PushTok(TOK_STRING, estr, &expstack); PushTok(TOK_DBL_QUOTE, NULL, &expstack); @@ -385,7 +428,7 @@ int ReduceExpressions(struct objlist *instprop, case '{': *tstr = '\0'; - result = TokGetValue(estr, parent, glob, &dval); + result = TokGetValue(estr, parent, parprops, glob, &dval); if (result == 1) PushTok(TOK_DOUBLE, &dval, &expstack); else if (result == -1) PushTok(TOK_STRING, estr, &expstack); PushTok(TOK_GROUP_OPEN, NULL, &expstack); @@ -395,7 +438,7 @@ int ReduceExpressions(struct objlist *instprop, case '}': *tstr = '\0'; - result = TokGetValue(estr, parent, glob, &dval); + result = TokGetValue(estr, parent, parprops, glob, &dval); if (result == 1) PushTok(TOK_DOUBLE, &dval, &expstack); PushTok(TOK_GROUP_CLOSE, NULL, &expstack); estr = tstr + 1; @@ -405,7 +448,7 @@ int ReduceExpressions(struct objlist *instprop, case '!': if (*(tstr + 1) == '=') { *tstr = '\0'; - result = TokGetValue(estr, parent, glob, &dval); + result = TokGetValue(estr, parent, parprops, glob, &dval); if (result == 1) PushTok(TOK_DOUBLE, &dval, &expstack); else if (result == -1) PushTok(TOK_STRING, estr, &expstack); PushTok(TOK_NE, NULL, &expstack); @@ -416,7 +459,7 @@ int ReduceExpressions(struct objlist *instprop, case '=': if (*(tstr + 1) == '=') { *tstr = '\0'; - result = TokGetValue(estr, parent, glob, &dval); + result = TokGetValue(estr, parent, parprops, glob, &dval); if (result == 1) PushTok(TOK_DOUBLE, &dval, &expstack); else if (result == -1) PushTok(TOK_STRING, estr, &expstack); PushTok(TOK_EQ, NULL, &expstack); @@ -426,7 +469,7 @@ int ReduceExpressions(struct objlist *instprop, case '>': *tstr = '\0'; - result = TokGetValue(estr, parent, glob, &dval); + result = TokGetValue(estr, parent, parprops, glob, &dval); if (result == 1) PushTok(TOK_DOUBLE, &dval, &expstack); else if (result == -1) PushTok(TOK_STRING, estr, &expstack); @@ -442,7 +485,7 @@ int ReduceExpressions(struct objlist *instprop, case '<': *tstr = '\0'; - result = TokGetValue(estr, parent, glob, &dval); + result = TokGetValue(estr, parent, parprops, glob, &dval); if (result == 1) PushTok(TOK_DOUBLE, &dval, &expstack); else if (result == -1) PushTok(TOK_STRING, estr, &expstack); @@ -458,7 +501,7 @@ int ReduceExpressions(struct objlist *instprop, case ',': *tstr = '\0'; - result = TokGetValue(estr, parent, glob, &dval); + result = TokGetValue(estr, parent, parprops, glob, &dval); if (result == 1) PushTok(TOK_DOUBLE, &dval, &expstack); else if (result == -1) PushTok(TOK_STRING, estr, &expstack); if (expstack == NULL) break; @@ -483,7 +526,7 @@ int ReduceExpressions(struct objlist *instprop, } tstr++; } - result = TokGetValue(estr, parent, glob, &dval); + result = TokGetValue(estr, parent, parprops, glob, &dval); if (result == 1) PushTok(TOK_DOUBLE, &dval, &expstack); else if (result == -1) PushTok(TOK_STRING, estr, &expstack); @@ -754,7 +797,7 @@ int ReduceExpressions(struct objlist *instprop, switch (stackptr->toktype) { case TOK_STRING: result = TokGetValue(stackptr->data.string, parent, - glob, &dval); + parprops, glob, &dval); if (result == 1) { stackptr->toktype = TOK_DOUBLE; FREE(stackptr->data.string); diff --git a/base/netgen.h b/base/netgen.h index 602ef62..c156053 100644 --- a/base/netgen.h +++ b/base/netgen.h @@ -43,8 +43,8 @@ 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); diff --git a/base/objlist.c b/base/objlist.c index 3f50548..804a963 100644 --- a/base/objlist.c +++ b/base/objlist.c @@ -843,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 */ { @@ -880,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); } diff --git a/base/objlist.h b/base/objlist.h index 943408d..1794c7c 100644 --- a/base/objlist.h +++ b/base/objlist.h @@ -232,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 */ diff --git a/base/spice.c b/base/spice.c index b3b863b..f41d369 100644 --- a/base/spice.c +++ b/base/spice.c @@ -860,7 +860,7 @@ skip_ends: 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); + ReduceExpressions(pobj, NULL, CurrentCell, TRUE); ndev--; } DeleteProperties(&kvlist); @@ -927,8 +927,8 @@ 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); SetClass(CLASS_FET); EndCell(); ReopenCellDef((*CellStackPtr)->cellname, filenum); /* Reopen */ @@ -946,7 +946,7 @@ skip_ends: 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); + ReduceExpressions(pobj, NULL, CurrentCell, TRUE); ndev--; } DeleteProperties(&kvlist); @@ -1049,7 +1049,7 @@ skip_ends: else Cap((*CellStackPtr)->cellname, instname, ctop, cbot); pobj = LinkProperties(model, kvlist); - ReduceExpressions(pobj, CurrentCell, TRUE); + ReduceExpressions(pobj, NULL, CurrentCell, TRUE); ndev--; } DeleteProperties(&kvlist); @@ -1151,7 +1151,7 @@ skip_ends: else Res((*CellStackPtr)->cellname, instname, rtop, rbot); pobj = LinkProperties(model, kvlist); - ReduceExpressions(pobj, CurrentCell, TRUE); + ReduceExpressions(pobj, NULL, CurrentCell, TRUE); ndev--; } DeleteProperties(&kvlist); @@ -1215,7 +1215,7 @@ skip_ends: if (multi) snprintf(instname, 255, "%s%s.%d", model, inst, ndev); Cell(instname, model, anode, cathode); pobj = LinkProperties(model, kvlist); - ReduceExpressions(pobj, CurrentCell, TRUE); + ReduceExpressions(pobj, NULL, CurrentCell, TRUE); ndev--; } DeleteProperties(&kvlist); @@ -1307,7 +1307,7 @@ skip_ends: XLine((*CellStackPtr)->cellname, instname, node1, node2, node3, node4); pobj = LinkProperties(model, kvlist); - ReduceExpressions(pobj, CurrentCell, TRUE); + ReduceExpressions(pobj, NULL, CurrentCell, TRUE); ndev--; } DeleteProperties(&kvlist); @@ -1397,7 +1397,7 @@ skip_ends: else Inductor((*CellStackPtr)->cellname, instname, end_a, end_b); pobj = LinkProperties(model, kvlist); - ReduceExpressions(pobj, CurrentCell, TRUE); + ReduceExpressions(pobj, NULL, CurrentCell, TRUE); ndev--; } DeleteProperties(&kvlist); @@ -1457,7 +1457,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 */ @@ -1510,7 +1510,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 */ @@ -1574,7 +1574,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); } @@ -1720,7 +1720,7 @@ skip_ends: } Instance(subcktname, instancename); pobj = LinkProperties(subcktname, kvlist); - ReduceExpressions(pobj, CurrentCell, TRUE); + ReduceExpressions(pobj, NULL, CurrentCell, TRUE); ndev--; /* (Diagnostic) */