Corrected the "property tolerance" command in tclnetgen, and cleaned up

some of the property matching output.
This commit is contained in:
Tim Edwards 2016-05-16 17:33:15 -04:00
parent be6a5a87ce
commit e0527a0a89
6 changed files with 136 additions and 39 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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() --- */
/* */

View File

@ -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);

View File

@ -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);
}

View File

@ -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);
}