Corrected the "property tolerance" command in tclnetgen, and cleaned up
some of the property matching output.
This commit is contained in:
parent
be6a5a87ce
commit
e0527a0a89
|
|
@ -249,6 +249,7 @@ void flattenCell(char *name, int file)
|
|||
int flattenInstancesOf(char *name, int fnum, char *instance)
|
||||
{
|
||||
struct objlist *ParentParams;
|
||||
struct objlist *ParentProps;
|
||||
struct objlist *NextObj;
|
||||
struct objlist *ChildObjList;
|
||||
struct nlist *ThisCell;
|
||||
|
|
@ -308,6 +309,14 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
|
|||
if (ChildCell->class != CLASS_SUBCKT) continue;
|
||||
if (ChildCell == ThisCell) continue; // Avoid infinite loop
|
||||
|
||||
/* Does the parent cell have properties? If so, save a pointer to them */
|
||||
for (ParentProps = ParentParams->next; ParentProps &&
|
||||
ParentProps->type != FIRSTPIN;
|
||||
ParentProps = ParentProps->next) {
|
||||
if (ParentProps->type == PROPERTY) break;
|
||||
}
|
||||
if (ParentProps && (ParentProps->type != PROPERTY)) ParentProps = NULL;
|
||||
|
||||
/* not primitive, so need to flatten this instance */
|
||||
notdone = 1;
|
||||
/* if this is a new instance, flatten it */
|
||||
|
|
@ -406,7 +415,9 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
|
|||
prefixlength = strlen(tmpstr);
|
||||
#endif
|
||||
for (tmp = ChildObjList; tmp != NULL; tmp = tmp->next) {
|
||||
if (tmp->type == PROPERTY) continue;
|
||||
if (tmp->type == PROPERTY)
|
||||
continue;
|
||||
|
||||
else if (IsGlobal(tmp)) {
|
||||
/* Keep the name but search for node of same name in parent */
|
||||
/* and replace the node number, if found. */
|
||||
|
|
@ -455,6 +466,31 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
|
|||
HashPtrInstall(tmp->instance.name, tmp, ThisCell->insttab, OBJHASHSIZE);
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
||||
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 */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* splice instance out of parent */
|
||||
if (ParentParams == ThisCell->cell) {
|
||||
/* ParentParams are the very first thing in the list */
|
||||
|
|
@ -468,6 +504,7 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
|
|||
for (ob2->next = ChildObjList; ob2->next != NULL; ob2 = ob2->next) ;
|
||||
}
|
||||
/* now, ob2 is last element in child list, so skip and reclaim parent */
|
||||
|
||||
tmp = ParentParams;
|
||||
do {
|
||||
tmp = tmp->next;
|
||||
|
|
|
|||
|
|
@ -3327,8 +3327,8 @@ int PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print)
|
|||
}
|
||||
}
|
||||
if (vl2->type != PROP_ENDLIST) {
|
||||
if (do_print) Fprintf(stdout, "Circuit 2 %s instance %s does not"
|
||||
" define required properties.\n",
|
||||
if (do_print) Fprintf(stdout, "Circuit 2 %s instance %s missing"
|
||||
" required properties.\n",
|
||||
Circuit2->name, ob2->instance.name);
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -3352,8 +3352,8 @@ int PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print)
|
|||
}
|
||||
}
|
||||
if (vl1->type != PROP_ENDLIST) {
|
||||
if (do_print) Fprintf(stdout, "Circuit 1 %s instance %s does not"
|
||||
" define required properties.\n",
|
||||
if (do_print) Fprintf(stdout, "Circuit 1 %s instance %s missing"
|
||||
" required properties.\n",
|
||||
Circuit1->name, ob1->instance.name);
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -3389,6 +3389,14 @@ int PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print)
|
|||
kl2 = (struct property *)HashLookup(vl2->key, tc2->proptab, OBJHASHSIZE);
|
||||
if (kl2 == NULL) continue;
|
||||
|
||||
/* Watch out for uninitialized entries in cell def */
|
||||
if (vl1->type == vl2->type) {
|
||||
if (kl1->type == PROP_STRING && kl1->pdefault.string == NULL)
|
||||
SetPropertyDefault(kl1, vl1);
|
||||
if (kl2->type == PROP_STRING && kl2->pdefault.string == NULL)
|
||||
SetPropertyDefault(kl2, vl2);
|
||||
}
|
||||
|
||||
if (vl1->type != vl2->type) {
|
||||
if (kl1->type != vl1->type) PromoteProperty(kl1, vl1);
|
||||
if (kl2->type != vl2->type) PromoteProperty(kl2, vl2);
|
||||
|
|
|
|||
100
base/netgen.c
100
base/netgen.c
|
|
@ -193,28 +193,27 @@ int TokGetValue(char *estr, struct nlist *parent, int glob, double *dval)
|
|||
spiceparams, OBJHASHSIZE);
|
||||
if (kl != NULL) {
|
||||
result = ConvertStringToFloat(kl->pdefault.string, dval);
|
||||
return ((result == 0) ? -1 : 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Check local parameters */
|
||||
kl = (struct property *)HashLookup(estr,
|
||||
parent->proptab, OBJHASHSIZE);
|
||||
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;
|
||||
}
|
||||
|
||||
/* Check local parameters */
|
||||
kl = (struct property *)HashLookup(estr, parent->proptab, OBJHASHSIZE);
|
||||
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);
|
||||
|
|
@ -1924,10 +1923,6 @@ void DeleteProperties(struct keyvalue **topptr)
|
|||
/* to relate them to the cell that is being instanced. Because this */
|
||||
/* is used to link the same properties multiple times for parallel */
|
||||
/* devices, copy the list (a refcount would work better. . .) */
|
||||
/* */
|
||||
/* If "isdefault" is "true", then the record is installed in the */
|
||||
/* object hash under the name "defaults"; otherwise, it gets the */
|
||||
/* name "properties" and is not added to the object hash. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
struct objlist *LinkProperties(char *model, struct keyvalue *topptr)
|
||||
|
|
@ -1953,10 +1948,6 @@ struct objlist *LinkProperties(char *model, struct keyvalue *topptr)
|
|||
return NULL;
|
||||
}
|
||||
cell = LookupCellFile(model, filenum);
|
||||
if (cell == NULL) {
|
||||
Printf("No cell '%s' found to link properties to.\n", model);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tp = GetObject();
|
||||
tp->type = PROPERTY;
|
||||
|
|
@ -1977,6 +1968,27 @@ struct objlist *LinkProperties(char *model, struct keyvalue *topptr)
|
|||
/* No promotion to types other than string at this point */
|
||||
newkv->type = PROP_STRING;
|
||||
newkv->value.string = strsave(kv->value);
|
||||
|
||||
if (cell != NULL) {
|
||||
struct property *kl = NULL;
|
||||
|
||||
/* If there is a matching cell, make sure that the property */
|
||||
/* key exists. If not, create it and flag a warning. */
|
||||
|
||||
kl = (struct property *)HashLookup(newkv->key, cell->proptab, OBJHASHSIZE);
|
||||
if (kl == NULL) {
|
||||
Fprintf(stderr, "Warning: Property %s passed to cell %s which "
|
||||
"does not define a default.\n",
|
||||
newkv->key, cell->name);
|
||||
kl = NewProperty();
|
||||
kl->key = strsave(newkv->key);
|
||||
kl->idx = 0;
|
||||
kl->type = PROP_STRING;
|
||||
kl->slop.ival = 0;
|
||||
kl->pdefault.string = NULL;
|
||||
HashPtrInstall(kl->key, kl, cell->proptab, OBJHASHSIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Final entry marks the end of the list */
|
||||
|
|
@ -1989,6 +2001,40 @@ struct objlist *LinkProperties(char *model, struct keyvalue *topptr)
|
|||
return tp;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* SetPropertyDefault() --- */
|
||||
/* */
|
||||
/* If a cell does not set property defaults, but an instance of that */
|
||||
/* cell passes a property to it, then there will be a default value */
|
||||
/* with a string type and a NULL value. Set the default to be equal */
|
||||
/* to the instance type and value. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
int SetPropertyDefault(struct property *prop, struct valuelist *vl)
|
||||
{
|
||||
if (prop == NULL || vl == NULL) return -1;
|
||||
if (prop->type != PROP_STRING || prop->pdefault.string != NULL) return 1;
|
||||
|
||||
prop->type = vl->type;
|
||||
|
||||
switch (vl->type) {
|
||||
case PROP_STRING:
|
||||
prop->pdefault.string = strsave(vl->value.string);
|
||||
break;
|
||||
case PROP_INTEGER:
|
||||
prop->pdefault.ival = vl->value.ival;
|
||||
break;
|
||||
case PROP_DOUBLE:
|
||||
case PROP_VALUE:
|
||||
prop->pdefault.dval = vl->value.dval;
|
||||
break;
|
||||
case PROP_EXPRESSION:
|
||||
prop->pdefault.stack = CopyTokStack(vl->value.stack);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* PromoteProperty() --- */
|
||||
/* */
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ extern int PropertyTolerance(char *name, int fnum, char *key, int ival,
|
|||
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);
|
||||
|
|
|
|||
|
|
@ -903,9 +903,9 @@ skip_ends:
|
|||
if (!strcasecmp(nexttok, "M"))
|
||||
sscanf(eqptr + 1, "%d", &ndev);
|
||||
else if (!strcasecmp(nexttok, "L"))
|
||||
AddProperty(&kvlist, "length", eqptr + 1);
|
||||
AddProperty(&kvlist, "L", eqptr + 1);
|
||||
else if (!strcasecmp(nexttok, "W"))
|
||||
AddProperty(&kvlist, "width", eqptr + 1);
|
||||
AddProperty(&kvlist, "W", eqptr + 1);
|
||||
else
|
||||
AddProperty(&kvlist, nexttok, eqptr + 1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3206,11 +3206,16 @@ _netcmp_property(ClientData clientData,
|
|||
if (result != TCL_OK) return result;
|
||||
|
||||
result = Tcl_GetIntFromObj(interp, tobj2, &ival);
|
||||
if (result != TCL_OK) Tcl_ResetResult(interp);
|
||||
if ((result = Tcl_GetDoubleFromObj(interp, tobj2, &dval))
|
||||
!= TCL_OK)
|
||||
return result;
|
||||
|
||||
if (result != TCL_OK) {
|
||||
Tcl_ResetResult(interp);
|
||||
if (!strncasecmp(Tcl_GetString(tobj2), "inf", 3)) {
|
||||
ival = 1<<30;
|
||||
dval = 1.0E+300;
|
||||
}
|
||||
else if ((result = Tcl_GetDoubleFromObj(interp, tobj2, &dval))
|
||||
!= TCL_OK)
|
||||
return result;
|
||||
}
|
||||
PropertyTolerance(tp->name, fnum, Tcl_GetString(tobj1),
|
||||
ival, dval);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue