diff --git a/base/netcmp.c b/base/netcmp.c index 8fa533e..35c0bf9 100644 --- a/base/netcmp.c +++ b/base/netcmp.c @@ -4551,13 +4551,13 @@ int EquivalenceNodes(char *name1, int file1, char *name2, int file2) /* database. */ /*------------------------------------------------------*/ -int IgnoreClass(char *name, int file) +int IgnoreClass(char *name, int file, unsigned char type) { struct IgnoreList *newIgnore; if ((file == -1) && (Circuit1 != NULL) && (Circuit2 != NULL)) { - IgnoreClass(name, Circuit1->file); - IgnoreClass(name, Circuit2->file); + IgnoreClass(name, Circuit1->file, type); + IgnoreClass(name, Circuit2->file, type); return; } @@ -4567,9 +4567,13 @@ int IgnoreClass(char *name, int file) newIgnore->class = (char *)MALLOC(1 + strlen(name)); strcpy(newIgnore->class, name); newIgnore->file = file; + newIgnore->type = type; /* Remove existing classes from database */ - ClassDelete(name, file); + if (type == IGNORE_CLASS) + ClassDelete(name, file); + else + RemoveShorted(name, file); return 0; } diff --git a/base/netcmp.h b/base/netcmp.h index 240e822..e8daa42 100644 --- a/base/netcmp.h +++ b/base/netcmp.h @@ -32,7 +32,7 @@ extern int PermuteForget(char *model, int filenum, char *pin1, char *pin2); extern int EquivalenceElements(char *name1, int file1, char *name2, int file2); extern int EquivalenceNodes(char *name1, int file1, char *name2, int file2); extern int EquivalenceClasses(char *name1, int file1, char *name2, int file2); -extern int IgnoreClass(char *name, int file); +extern int IgnoreClass(char *name, int file, unsigned char type); extern int MatchPins(struct nlist *tp1, struct nlist *tp2); extern int CreateCompareQueue(char *, int, char *, int); diff --git a/base/netgen.c b/base/netgen.c index b1b24a6..aee2446 100644 --- a/base/netgen.c +++ b/base/netgen.c @@ -1212,6 +1212,10 @@ void CellDefNoCase(char *name, int file) CurrentCell->flags |= CELL_NOCASE; } +/*----------------------------------------------------------------------*/ +/* Return 0 if class 'name' is not being ignored (per the 'ignore' */ +/* command); 1 if it is ignored, and 2 if shorted instances should be */ +/* ignored. */ /*----------------------------------------------------------------------*/ int IsIgnored(char *name, int file) @@ -1223,7 +1227,7 @@ int IsIgnored(char *name, int file) { if ((file == -1) || (ilist->file == -1) || (file == ilist->file)) if ((*matchfunc)(ilist->class, nptr)) - return 1; + return ilist->type; /* IGNORE_CLASS or IGNORE_SHORTED */ } return 0; } @@ -1361,10 +1365,6 @@ void Instance(char *model, char *instancename) return; } fnum = CurrentCell->file; - if (IsIgnored(model, fnum)) { - Printf("Class '%s' instanced in input but is being ignored.\n", model); - return; - } instanced_cell = LookupCellFile(model, fnum); if (instanced_cell == NULL) { Printf("Attempt to instance undefined model '%s'\n", model); @@ -1504,7 +1504,7 @@ char *Cell(char *inststr, char *model, ...) struct objlist *namedporthead, *namedportp, *namedlisthead, *namedlistp; int portnum, portlist, done; char namedport[512]; /* tmp buffers */ - int filenum; + int filenum, itype, samenode; static char *instancename = NULL; char *instnameptr; @@ -1517,7 +1517,7 @@ char *Cell(char *inststr, char *model, ...) filenum = CurrentCell->file; if (Debug) Printf(" calling cell: %s\n",model); - if (IsIgnored(model, filenum)) { + if ((itype = IsIgnored(model, filenum)) == IGNORE_CLASS) { Printf("Class '%s' instanced in input but is being ignored.\n", model); return NULL; } @@ -1600,6 +1600,21 @@ char *Cell(char *inststr, char *model, ...) } va_end(ap); + /* Check for shorted pins */ + if ((itype == IGNORE_SHORTED) && (head != NULL)) { + unsigned char shorted = (unsigned char)1; + for (tp = head->next; tp; tp = tp->next) { + if (strcasecmp(head->name, tp->name)) + shorted = (unsigned char)0; + break; + } + if (shorted == (unsigned char)1) { + Printf("Instance of '%s' is shorted, ignoring.\n", model); + FreeObject(head); + return NULL; + } + } + if (inststr == NULL) { if (instancename != NULL) FreeString(instancename); @@ -1992,7 +2007,7 @@ struct objlist *LinkProperties(char *model, struct keyvalue *topptr) else filenum = CurrentCell->file; - if (IsIgnored(model, filenum)) { + if (IsIgnored(model, filenum) == IGNORE_CLASS) { Printf("Class '%s' instanced in input but is being ignored.\n", model); return NULL; } diff --git a/base/objlist.c b/base/objlist.c index dd28cc7..9ddd032 100644 --- a/base/objlist.c +++ b/base/objlist.c @@ -340,6 +340,71 @@ void CellRehash(char *name, char *newname, int file) struct nlist *OldCell; +int removeshorted(struct hashlist *p, int file) +{ + struct nlist *ptr; + struct objlist *ob, *lob, *nob, *tob; + unsigned char shorted; + + ptr = (struct nlist *)(p->ptr); + + if ((file != -1) && (ptr->file != file)) return; + + lob = NULL; + for (ob = ptr->cell; ob != NULL;) { + nob = ob->next; + if ((ob->type == FIRSTPIN) && (ob->model.class != NULL)) { + if ((*matchfunc)(ob->model.class, OldCell->name)) { + shorted = (unsigned char)1; + for (tob = nob; tob->type > FIRSTPIN; tob = tob->next) { + if (tob->node != ob->node) { + shorted = (unsigned char)0; + break; + } + } + if (shorted == (unsigned char)0) { + lob = ob; + ob = nob; + continue; + } + HashDelete(ob->instance.name, &(ptr->instdict)); + while (1) { + FreeObjectAndHash(ob, ptr); + ob = nob; + if (ob == NULL) break; + nob = ob->next; + if (ob->type != PROPERTY && ob->type <= FIRSTPIN) break; + } + if (lob == NULL) + ptr->cell = ob; + else + lob->next = ob; + } + else { + lob = ob; + ob = nob; + } + } + else { + lob = ob; + ob = nob; + } + } +} + +/* Remove shorted instances of class "class" from the database */ + +void RemoveShorted(char *class, int file) +{ + if (file == -1) + OldCell = LookupCell(class); + else + OldCell = LookupCellFile(class, file); + + if (OldCell == NULL) return; + RecurseCellFileHashTable(removeshorted, file); +} + int deleteclass(struct hashlist *p, int file) { struct nlist *ptr; diff --git a/base/objlist.h b/base/objlist.h index 1794c7c..d852e99 100644 --- a/base/objlist.h +++ b/base/objlist.h @@ -159,9 +159,16 @@ extern struct objlist *LastPlaced; struct IgnoreList { char *class; int file; + unsigned char type; struct IgnoreList *next; }; +/* Types used by IgnoreList above */ + +#define IGNORE_NONE (unsigned char)0 +#define IGNORE_CLASS (unsigned char)1 +#define IGNORE_SHORTED (unsigned char)2 + /* Record structure for handling pin permutations in a cell */ /* Linked list structure allows multiple permutations per cell. */ diff --git a/base/spice.c b/base/spice.c index 12ff209..2a6d438 100644 --- a/base/spice.c +++ b/base/spice.c @@ -1530,6 +1530,8 @@ skip_ends: else if (toupper(nexttok[0]) == 'X') { /* subcircuit instances */ char instancename[100], subcktname[100]; + int itype; + instancename[99] = '\0'; subcktname[99] = '\0'; @@ -1602,6 +1604,34 @@ skip_ends: if (scan->next != NULL) scan = scan->next; tail->next = NULL; + /* Check for ignored class */ + + if ((itype = IsIgnored(subcktname, filenum)) == IGNORE_CLASS) { + Printf("Class '%s' instanced in input but is being ignored.\n", model); + return; + } + + /* Check for shorted pins */ + + if ((itype == IGNORE_SHORTED) && (head != NULL)) { + unsigned char shorted = (unsigned char)1; + struct portelement *p; + for (p = head->next; p; p = p->next) { + if (strcasecmp(head->name, p->name)) + shorted = (unsigned char)0; + break; + } + if (shorted == (unsigned char)1) { + Printf("Instance of '%s' is shorted, ignoring.\n", subcktname); + while (head) { + p = head->next; + FREE(head); + head = p; + } + return; + } + } + /* Create cell name and revise instance name based on the cell name */ /* For clarity, if "instancename" does not contain the cellname, */ /* then prepend the cellname to the instance name. HOWEVER, if any */ @@ -1658,6 +1688,7 @@ skip_ends: } /* nexttok is now NULL, scan->name points to class */ + Instance(subcktname, instancename); pobj = LinkProperties(subcktname, kvlist); ReduceExpressions(pobj, NULL, CurrentCell, TRUE); diff --git a/tcltk/tclnetgen.c b/tcltk/tclnetgen.c index c7e480f..89293b9 100644 --- a/tcltk/tclnetgen.c +++ b/tcltk/tclnetgen.c @@ -2518,10 +2518,10 @@ _netcmp_ignore(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { char *options[] = { - "class", NULL + "class", "shorted", NULL }; enum OptionIdx { - CLASS_IDX + CLASS_IDX, SHORTED_IDX }; int result, index; int file = -1; @@ -2542,7 +2542,14 @@ _netcmp_ignore(ClientData clientData, Tcl_WrongNumArgs(interp, 1, objv, "[class] valid_cellname"); return TCL_ERROR; } - IgnoreClass(name, file); + switch (index) { + case CLASS_IDX: + IgnoreClass(name, file, IGNORE_CLASS); + break; + case SHORTED_IDX: + IgnoreClass(name, file, IGNORE_SHORTED); + break; + } return TCL_OK; }