From 9148edde69ed00b9f02f321bec961c8e4e883fc1 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 18 Oct 2016 14:17:57 -0400 Subject: [PATCH] Implemented command option 'ignore shorted', same syntax as 'ignore class', but removes instances of the specified class whose pins are shorted together. Currently requires that all pins must be shorted together. --- base/netcmp.c | 12 ++++++--- base/netcmp.h | 2 +- base/netgen.c | 31 ++++++++++++++++------ base/objlist.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++ base/objlist.h | 7 +++++ base/spice.c | 31 ++++++++++++++++++++++ tcltk/tclnetgen.c | 13 +++++++--- 7 files changed, 145 insertions(+), 16 deletions(-) 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; }