Corrected a badly implemented routine that can cause very long

run-times on large projects where a lot of cells need to be
deleted.
This commit is contained in:
Tim Edwards 2022-11-16 12:37:05 -05:00
parent 7e8508db53
commit 2292ab813b
2 changed files with 30 additions and 34 deletions

View File

@ -1 +1 @@
1.5.241 1.5.242

View File

@ -440,13 +440,6 @@ void RemoveShorted(char *class, int file)
RecurseCellFileHashTable(removeshorted, file); RecurseCellFileHashTable(removeshorted, file);
} }
/* Structure used to keep track of nodes needing checking */
struct linkednode {
int node;
struct linkednode *next;
};
/* Remove instances of a deleted class from the database. */ /* Remove instances of a deleted class from the database. */
/* NOTE: This treats deleted classes as not existing, so it */ /* NOTE: This treats deleted classes as not existing, so it */
/* needs to take care of disconnected ports in the same manner */ /* needs to take care of disconnected ports in the same manner */
@ -457,13 +450,22 @@ struct linkednode {
int deleteclass(struct hashlist *p, int file) int deleteclass(struct hashlist *p, int file)
{ {
struct nlist *ptr; struct nlist *ptr;
struct objlist *ob, *lob, *nob; struct objlist *ob, *lob, *nob, *portnode;
struct linkednode *checknodes = NULL, *newlnode, *chknode; unsigned char *checknodes;
int i;
ptr = (struct nlist *)(p->ptr); ptr = (struct nlist *)(p->ptr);
if ((file != -1) && (ptr->file != file)) return 0; if ((file != -1) && (ptr->file != file)) return 0;
/* Note: This could be made faster by enumerating all times each
* node is used during the full pass, then subtracting each time
* the node is deleted in a child, then disconnecting all nodes
* that ended up with a zero count.
*/
checknodes = (unsigned char *)CALLOC(ptr->nodename_cache_maxnodenum + 1,
sizeof(unsigned char));
lob = NULL; lob = NULL;
for (ob = ptr->cell; ob != NULL;) { for (ob = ptr->cell; ob != NULL;) {
nob = ob->next; nob = ob->next;
@ -471,12 +473,8 @@ int deleteclass(struct hashlist *p, int file)
if ((*matchfunc)(ob->model.class, OldCell->name)) { if ((*matchfunc)(ob->model.class, OldCell->name)) {
HashDelete(ob->instance.name, &(ptr->instdict)); HashDelete(ob->instance.name, &(ptr->instdict));
while (1) { while (1) {
if (ob->type >= FIRSTPIN) { if (ob->type >= FIRSTPIN)
newlnode = (struct linkednode *)MALLOC(sizeof(struct linkednode)); checknodes[ob->node] = (unsigned char)1;
newlnode->node = ob->node;
newlnode->next = checknodes;
checknodes = newlnode;
}
FreeObjectAndHash(ob, ptr); FreeObjectAndHash(ob, ptr);
ob = nob; ob = nob;
if (ob == NULL) break; if (ob == NULL) break;
@ -499,27 +497,25 @@ int deleteclass(struct hashlist *p, int file)
} }
} }
while (checknodes != NULL) { for (i = 0; i <= ptr->nodename_cache_maxnodenum; i++) {
struct objlist *portnode = NULL; if (checknodes[i] != 0) {
portnode = NULL;
chknode = checknodes;
checknodes = checknodes->next;
for (ob = ptr->cell; ob != NULL; ob = ob->next) { for (ob = ptr->cell; ob != NULL; ob = ob->next) {
if ((ob->type != PORT) && (portnode == NULL)) if ((ob->type != PORT) && (portnode == NULL))
break; break;
else if ((ob->type == PORT) && (ob->node == chknode->node)) else if ((ob->type == PORT) && (ob->node == i))
portnode = ob; portnode = ob;
else if ((ob->type >= FIRSTPIN) && (ob->node == chknode->node)) else if ((ob->type >= FIRSTPIN) && (ob->node == i))
break; break;
} }
if ((ob == NULL) && (portnode != NULL)) { if ((ob == NULL) && (portnode != NULL)) {
/* Port became disconnected when child was deleted */ /* Port became disconnected when child was deleted */
portnode->node = -1; portnode->node = -1;
} }
FREE(chknode);
} }
} }
FREE(checknodes);
}
/* Remove all instances of class "class" from the database */ /* Remove all instances of class "class" from the database */