Correction to previous commit (failed to link to last pointer

after processing properties during flattening).
This commit is contained in:
Tim Edwards 2021-06-12 20:15:55 -04:00
parent 57b2d21221
commit d53541d1d3
1 changed files with 184 additions and 185 deletions

View File

@ -358,218 +358,217 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
ChildListEnd = NULL; ChildListEnd = NULL;
while (1) { while (1) {
// XXX NEEDS INDENTING ChildStart = CopyObjList(ChildCell->cell, 1);
ChildStart = CopyObjList(ChildCell->cell, 1); numflat++;
numflat++;
/* Find the end record of the child cell and save it */ /* Find the end record of the child cell and save it */
for (ChildEnd = ChildStart; ChildEnd && ChildEnd->next; for (ChildEnd = ChildStart; ChildEnd && ChildEnd->next;
ChildEnd = ChildEnd->next); ChildEnd = ChildEnd->next);
if (ChildListEnd == NULL) ChildListEnd = ChildEnd; if (ChildListEnd == NULL) ChildListEnd = ChildEnd;
/* update node numbers in child to unique numbers */ /* update node numbers in child to unique numbers */
oldmax = 0; oldmax = 0;
for (tmp = ChildStart; tmp != NULL; tmp = tmp->next) for (tmp = ChildStart; tmp != NULL; tmp = tmp->next)
if (tmp->node > oldmax) oldmax = tmp->node; if (tmp->node > oldmax) oldmax = tmp->node;
if (nextnode <= oldmax) nextnode = oldmax + 1; if (nextnode <= oldmax) nextnode = oldmax + 1;
for (tmp = ChildStart; tmp != NULL; tmp = tmp->next) for (tmp = ChildStart; tmp != NULL; tmp = tmp->next)
if (tmp->node <= oldmax && tmp->node > 0) { if (tmp->node <= oldmax && tmp->node > 0) {
if (Debug) Printf("Update node %d --> %d\n", tmp->node, nextnode); if (Debug) Printf("Update node %d --> %d\n", tmp->node, nextnode);
UpdateNodeNumbers(ChildStart, tmp->node, nextnode); UpdateNodeNumbers(ChildStart, tmp->node, nextnode);
nextnode++; nextnode++;
} }
/* copy nodenumbers of ports from parent */ /* copy nodenumbers of ports from parent */
ob2 = ParentParams; ob2 = ParentParams;
for (tmp = ChildStart; tmp != NULL; tmp = tmp->next) for (tmp = ChildStart; tmp != NULL; tmp = tmp->next) {
if (IsPort(tmp)) { if (IsPort(tmp)) {
if (tmp->node > 0) { if (tmp->node > 0) {
if (ob2->node == -1) { if (ob2->node == -1) {
// Before commiting to attaching to a unconnected node, see // Before commiting to attaching to a unconnected node, see
// if there is another node in ParentParams with the same // if there is another node in ParentParams with the same
// name and a valid node number. If so, connect them. In // name and a valid node number. If so, connect them. In
// the broader case, it may be necessary to consider all // the broader case, it may be necessary to consider all
// nodes, not just those with node == -1, and call join() // nodes, not just those with node == -1, and call join()
// here to update all node numbers in the parent cell. // here to update all node numbers in the parent cell.
// In that case, a more efficient method is needed for // In that case, a more efficient method is needed for
// tracking same-name ports. // tracking same-name ports.
for (ob3 = ParentParams; ob3 && ob3->type >= FIRSTPIN; ob3 = ob3->next) { for (ob3 = ParentParams; ob3 && ob3->type >= FIRSTPIN;
if (ob3 == ob2) continue; ob3 = ob3->next) {
if ((*matchfunc)(ob3->name, ob2->name) && ob3->node != -1) { if (ob3 == ob2) continue;
ob2->node = ob3->node; if ((*matchfunc)(ob3->name, ob2->name) && ob3->node != -1) {
break; ob2->node = ob3->node;
} break;
}
}
}
if (Debug) {
// Printf(" Sealing port: %d to node %d\n", tmp->node, ob2->node);
Printf("Update node %d --> %d\n", tmp->node, ob2->node);
}
UpdateNodeNumbers(ChildStart, tmp->node, ob2->node);
} }
/* in pathological cases, the lengths of the port lists may
* change. This is an error, but that is no reason to allow
* the code to core dump. We avoid this by placing a
* superfluous check on ob2->type
*/
if (ob2 != NULL) ob2 = ob2->next;
if (ob2 == NULL) break;
} }
if (Debug) { }
// Printf(" Sealing port: %d to node %d\n", tmp->node, ob2->node);
Printf("Update node %d --> %d\n", tmp->node, ob2->node);
}
UpdateNodeNumbers(ChildStart, tmp->node, ob2->node);
}
/* in pathological cases, the lengths of the port lists may /* Using name == NULL to indicate that a .ext file is being */
* change. This is an error, but that is no reason to allow /* flattened on the fly. This is quick & dirty. */
* the code to core dump. We avoid this by placing a
* superfluous check on ob2->type
*/
if (ob2 != NULL) if (name != NULL) {
ob2 = ob2->next; /* delete all port elements from child */
while ((ChildStart != NULL) && IsPort(ChildStart)) {
if (ob2 == NULL) break; /* delete all ports at beginning of list */
} if (Debug) Printf("deleting leading port from child\n");
tmp = ChildStart->next;
/* Using name == NULL to indicate that a .ext file is being */ FreeObject(ChildStart);
/* flattened on the fly. This is quick & dirty. */ ChildStart = tmp;
}
if (name != NULL) { tmp = ChildStart;
/* delete all port elements from child */ while (tmp && (tmp->next != NULL)) {
while ((ChildStart != NULL) && IsPort(ChildStart)) { if (IsPort(tmp->next)) {
/* delete all ports at beginning of list */ ob2 = (tmp->next)->next;
if (Debug) Printf("deleting leading port from child\n"); if (Debug) Printf("deleting a port from child\n");
tmp = ChildStart->next; FreeObject(tmp->next);
// FreeObjectAndHash(ChildStart, ChildCell); tmp->next = ob2;
FreeObject(ChildStart); }
ChildStart = tmp; else tmp = tmp->next;
} }
tmp = ChildStart;
while (tmp && (tmp->next != NULL)) {
if (IsPort(tmp->next)) {
ob2 = (tmp->next)->next;
if (Debug) Printf("deleting a port from child\n");
// FreeObjectAndHash(tmp->next, ChildCell);
FreeObject(tmp->next);
tmp->next = ob2;
}
else tmp = tmp->next;
}
}
/* for each element in child, prepend 'prefix' */
#if !OLDPREFIX
/* replaces all the sprintf's below */
strcpy(tmpstr,ParentParams->instance.name);
strcat(tmpstr,SEPARATOR);
prefixlength = strlen(tmpstr);
#endif
for (tmp = ChildStart; tmp != NULL; tmp = tmp->next) {
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. */
for (ob2 = ThisCell->cell; ob2 != NULL; ob2 = ob2->next) {
/* Type in parent may be a port, not a global */
if (ob2->type == tmp->type || ob2->type == PORT) {
if ((*matchfunc)(tmp->name, ob2->name)) {
if (ob2->node >= 0) {
// Replace all child objects with this node number
rnodenum = tmp->node;
for (ob3 = ChildStart; ob3 != NULL; ob3 = ob3->next) {
if (ob3->node == rnodenum)
ob3->node = ob2->node;
}
break;
}
}
}
}
// Don't hash this if the parent had a port of this name
if (!ob2 || ob2->type != PORT)
HashPtrInstall(tmp->name, tmp, &(ThisCell->objdict));
continue;
}
#if OLDPREFIX
sprintf(tmpstr, "%s%s%s", ParentParams->instance.name, SEPARATOR,
tmp->name);
#else
strcpy(tmpstr+prefixlength,tmp->name);
#endif
if (Debug) Printf("Renaming %s to %s\n", tmp->name, tmpstr);
FreeString(tmp->name);
tmp->name = strsave(tmpstr);
HashPtrInstall(tmp->name, tmp, &(ThisCell->objdict));
if ((tmp->type != NODE) && (tmp->instance.name != NULL)) {
#if OLDPREFIX
sprintf(tmpstr, "%s%s%s", ParentParams->instance.name, SEPARATOR,
tmp->instance.name);
#else
strcpy(tmpstr+prefixlength,tmp->instance.name);
#endif
FreeString(tmp->instance.name);
tmp->instance.name = strsave(tmpstr);
if (tmp->type == FIRSTPIN)
HashPtrInstall(tmp->instance.name, tmp, &(ThisCell->instdict));
}
}
/* Do property inheritance */
/* NOTE: Need to do: Check properties for M > 1 and decrement
* and repeat without moving CurrentProp
*/
if (CurrentProp) {
for (ob2 = ChildStart; ob2 != NULL; ob2=ob2->next) {
/* If the parent cell has properties to declare, then */
/* pass them on to children. Use globals only if the */
/* spiceparams dictionary is active (during file reading */
/* only). */
if (ob2->type == PROPERTY)
ReduceExpressions(ob2, CurrentProp, ChildCell,
(spiceparams.hashtab == NULL) ? 0 : 1);
} }
/* Repeat for each property record, as each property represents a /* for each element in child, prepend 'prefix' */
* unique instance that must be flattened individually. #if !OLDPREFIX
/* replaces all the sprintf's below */
strcpy(tmpstr,ParentParams->instance.name);
strcat(tmpstr,SEPARATOR);
prefixlength = strlen(tmpstr);
#endif
for (tmp = ChildStart; tmp != NULL; tmp = tmp->next) {
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. */
for (ob2 = ThisCell->cell; ob2 != NULL; ob2 = ob2->next) {
/* Type in parent may be a port, not a global */
if (ob2->type == tmp->type || ob2->type == PORT) {
if ((*matchfunc)(tmp->name, ob2->name)) {
if (ob2->node >= 0) {
// Replace all child objects with this node number
rnodenum = tmp->node;
for (ob3 = ChildStart; ob3 != NULL; ob3 = ob3->next) {
if (ob3->node == rnodenum)
ob3->node = ob2->node;
}
break;
}
}
}
}
// Don't hash this if the parent had a port of this name
if (!ob2 || ob2->type != PORT)
HashPtrInstall(tmp->name, tmp, &(ThisCell->objdict));
continue;
}
#if OLDPREFIX
sprintf(tmpstr, "%s%s%s", ParentParams->instance.name, SEPARATOR,
tmp->name);
#else
strcpy(tmpstr+prefixlength,tmp->name);
#endif
if (Debug) Printf("Renaming %s to %s\n", tmp->name, tmpstr);
FreeString(tmp->name);
tmp->name = strsave(tmpstr);
HashPtrInstall(tmp->name, tmp, &(ThisCell->objdict));
if ((tmp->type != NODE) && (tmp->instance.name != NULL)) {
#if OLDPREFIX
sprintf(tmpstr, "%s%s%s", ParentParams->instance.name, SEPARATOR,
tmp->instance.name);
#else
strcpy(tmpstr+prefixlength,tmp->instance.name);
#endif
FreeString(tmp->instance.name);
tmp->instance.name = strsave(tmpstr);
if (tmp->type == FIRSTPIN)
HashPtrInstall(tmp->instance.name, tmp, &(ThisCell->instdict));
}
}
/* Do property inheritance */
/* NOTE: Need to do: Check properties for M > 1 and decrement
* and repeat without moving CurrentProp
*/ */
CurrentProp = CurrentProp->next; if (CurrentProp) {
if (CurrentProp->type != PROPERTY) break; for (ob2 = ChildStart; ob2 != NULL; ob2=ob2->next) {
/* If the parent cell has properties to declare, then */
/* pass them on to children. Use globals only if the */
/* spiceparams dictionary is active (during file */
/* reading only). */
if (ob2->type == PROPERTY)
ReduceExpressions(ob2, CurrentProp, ChildCell,
(spiceparams.hashtab == NULL) ? 0 : 1);
}
/* Repeat for each property record, as each property represents a
* unique instance that must be flattened individually.
*/
CurrentProp = CurrentProp->next;
if (CurrentProp->type != PROPERTY) break;
}
else break;
/* Put the child cell at the start of ChildObjList */
ChildEnd->next = ChildObjList;
ChildObjList = ChildStart;
} }
else break;
/* Put the child cell at the start of ChildObjList */ /* Put the child cell at the start of ChildObjList */
ChildEnd->next = ChildObjList; ChildEnd->next = ChildObjList;
ChildObjList = ChildStart; ChildObjList = ChildStart;
// XXX END INDENTATION
}
/* Pull the instance out of the parent */ /* Pull the instance out of the parent */
if ((ParentParams != ThisCell->cell) || (ChildObjList != NULL)) { if ((ParentParams != ThisCell->cell) || (ChildObjList != NULL)) {
if (ParentParams == ThisCell->cell) { if (ParentParams == ThisCell->cell) {
/* ParentParams are the very first thing in the list */ /* ParentParams are the very first thing in the list */
ThisCell->cell = ChildObjList; ThisCell->cell = ChildObjList;
} }
else { else {
/* find ParentParams in ThisCell list. In most cases, LastObj */ /* find ParentParams in ThisCell list. In most cases, LastObj */
/* should be pointing to it. */ /* should be pointing to it. */
if (LastObj && (LastObj->next == ParentParams)) { if (LastObj && (LastObj->next == ParentParams)) {
LastObj->next = ChildObjList; LastObj->next = ChildObjList;
} }
else { else {
for (ob2 = LastObj; ob2 && ob2->next != ParentParams; for (ob2 = LastObj; ob2 && ob2->next != ParentParams;
ob2 = ob2->next); ob2 = ob2->next);
if (ob2 == NULL) { if (ob2 == NULL) {
/* It should not happen that LastObj is ahead of ParentParams */ /* It should not happen that LastObj is ahead of ParentParams */
/* but just in case, this long loop will find it. */ /* but just in case, this long loop will find it. */
for (ob2 = ThisCell->cell; ob2 && ob2->next != ParentParams; for (ob2 = ThisCell->cell; ob2 && ob2->next != ParentParams;
ob2 = ob2->next); ob2 = ob2->next);
} }
ob2->next = ChildObjList; ob2->next = ChildObjList;
} }
} }
/* Link end of child list into the parent */ /* Link end of child list into the parent */
@ -577,9 +576,9 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
ChildListEnd->next = ParentEnd->next; ChildListEnd->next = ParentEnd->next;
} }
while (ParentParams != ChildListEnd->next) { while (ParentParams != ChildListEnd->next) {
ob2 = ParentParams->next; ob2 = ParentParams->next;
FreeObjectAndHash(ParentParams, ThisCell); FreeObjectAndHash(ParentParams, ThisCell);
ParentParams = ob2; ParentParams = ob2;
} }
NextObj = ParentParams; NextObj = ParentParams;
} /* repeat until no more instances found */ } /* repeat until no more instances found */