Fairly extensive modifications that allow for handling of, and

comparisons between, duplicate cells (cells with the same netlist
that may have more than one name in a circuit, or which for some
reason appear with the same name more than once in a netlist).
Added more checks to the list prematching, which prevents various
troubles with cells having a mismatched hierarchy.  Added a
command option to "flatten class" to flatten instances only within
a specific cell.  Corrected one error in the pin matching routine.
Added a check in the pin matching routine to look for pins that
have been found to be no-connects after cleaning up the pin lists
of the children of that cell.
This commit is contained in:
Tim Edwards 2016-05-16 10:50:12 -04:00
parent 06d772edd0
commit 7edeb2e37d
12 changed files with 5688 additions and 76 deletions

View File

@ -381,7 +381,8 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
/* delete all ports at beginning of list */
if (Debug) Printf("deleting leading port from child\n");
tmp = ChildObjList->next;
FreeObjectAndHash(ChildObjList, ChildCell);
// FreeObjectAndHash(ChildObjList, ChildCell);
FreeObject(ChildObjList);
ChildObjList = tmp;
}
tmp = ChildObjList;
@ -389,7 +390,8 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
if (IsPort(tmp->next)) {
ob2 = (tmp->next)->next;
if (Debug) Printf("deleting a port from child\n");
FreeObjectAndHash(tmp->next, ChildCell);
// FreeObjectAndHash(tmp->next, ChildCell);
FreeObject(tmp->next);
tmp->next = ob2;
}
else tmp = tmp->next;
@ -499,9 +501,22 @@ int flattenoneentry(struct hashlist *p, int file)
struct nlist *ptr;
ptr = (struct nlist *)(p->ptr);
if (file == ptr->file)
if (file == ptr->file) {
if (!(*matchfunc)(ptr->name, model_to_flatten) && (ptr->class == CLASS_SUBCKT))
flattenInstancesOf(ptr->name, file, model_to_flatten);
else if (ptr->flags & CELL_DUPLICATE) {
char *bptr = strstr(ptr->name, "[[");
if (bptr != NULL) {
*bptr = '\0';
if (!(*matchfunc)(ptr->name, model_to_flatten)
&& (ptr->class == CLASS_SUBCKT)) {
*bptr = '[';
flattenInstancesOf(ptr->name, file, model_to_flatten);
}
*bptr = '[';
}
}
}
return(1);
}
@ -1204,7 +1219,11 @@ int CleanupPins(char *name, int filenum)
lob = NULL;
for (ob = ThisCell->cell; ob != NULL; ) {
if (ob->type == UNKNOWN) continue;
if (ob->type == UNKNOWN) {
lob = ob;
ob = ob->next;
continue;
}
else if (ob->type != PORT) break;
nob = ob->next;
if (ob->node == -1) {
@ -1243,6 +1262,13 @@ typedef struct ecompare {
char refcount;
} ECompare;
typedef struct ecomplist *ECompListPtr;
typedef struct ecomplist {
ECompare *ecomp;
ECompListPtr next;
} ECompList;
/*------------------------------------------------------*/
/* Survey the contents of a cell and
/*------------------------------------------------------*/
@ -1253,38 +1279,58 @@ SurveyCell(struct nlist *tc, struct hashlist **comptab, int file1, int file2, in
struct objlist *ob;
struct nlist *tsub, *teq;
ECompare *ecomp, *qcomp, *ncomp;
int file = (which == 0) ? file1 : file2;
int ofile = (which == 0) ? file2 : file1;
char *dstr;
for (ob = tc->cell; ob; ob = ob->next) {
if (ob->type == FIRSTPIN) {
tsub = LookupCellFile(ob->model.class, (which == 0) ? file1 : file2);
ecomp = (ECompare *)HashLookup(ob->model.class, comptab, OBJHASHSIZE);
tsub = LookupCellFile(ob->model.class, file);
if (tsub->flags & CELL_DUPLICATE) {
// Always register a duplicate under the original name
dstr = strstr(ob->model.class, "[[");
if (dstr) *dstr = '\0';
}
else dstr = NULL;
teq = LookupClassEquivalent(ob->model.class, file, ofile);
ecomp = (ECompare *)HashInt2Lookup(ob->model.class, file,
comptab, OBJHASHSIZE);
if (ecomp == NULL) {
ncomp = (ECompare *)MALLOC(sizeof(ECompare));
if (which == 0) {
ncomp->num1 = 1;
ncomp->num2 = 0;
ncomp->cell1 = tsub;
teq = LookupClassEquivalent(ob->model.class, file1, file2);
ncomp->cell2 = teq;
}
else {
ncomp->num1 = 0;
ncomp->num2 = 1;
ncomp->cell2 = tsub;
teq = LookupClassEquivalent(ob->model.class, file2, file1);
ncomp->cell1 = teq;
}
ncomp->add1 = 0;
ncomp->add2 = 0;
ncomp->refcount = (char)1;
HashPtrInstall(ob->model.class, ncomp, comptab, OBJHASHSIZE);
HashInt2PtrInstall(ob->model.class, file, ncomp, comptab,
OBJHASHSIZE);
if (teq != NULL) {
qcomp = (ECompare *)HashLookup(teq->name, comptab, OBJHASHSIZE);
char *bstr = NULL;
if (teq->flags & CELL_DUPLICATE) {
bstr = strstr(teq->name, "[[");
if (bstr) *bstr = '\0';
}
qcomp = (ECompare *)HashInt2Lookup(teq->name, ofile,
comptab, OBJHASHSIZE);
if (qcomp == NULL) {
HashPtrInstall(teq->name, ncomp, comptab, OBJHASHSIZE);
HashInt2PtrInstall(teq->name, ofile, ncomp, comptab,
OBJHASHSIZE);
ncomp->refcount++;
}
if (bstr) *bstr = '[';
}
}
else {
@ -1293,6 +1339,7 @@ SurveyCell(struct nlist *tc, struct hashlist **comptab, int file1, int file2, in
else
ecomp->num2++;
}
if (dstr) *dstr = '[';
}
}
}
@ -1318,10 +1365,11 @@ SurveyCell(struct nlist *tc, struct hashlist **comptab, int file1, int file2, in
int
PrematchLists(char *name1, int file1, char *name2, int file2)
{
struct nlist *tc1, *tc2, *teq, *tsub1, *tsub2;
struct nlist *tc1, *tc2, *tsub1, *tsub2;
struct objlist *ob1, *ob2, *lob;
struct hashlist **comptab;
ECompare *ecomp, *ncomp;
ECompList *list0X, *listX0;
int match, modified = 0;
if (file1 == -1)
@ -1350,17 +1398,24 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
// in the hierarchy of each instance contain devices
// or subcircuits that have more in the compared circuit.
listX0 = list0X = NULL;
ecomp = (ECompare *)HashFirst(comptab, OBJHASHSIZE);
while (ecomp != NULL) {
/* Case 1: Both cell1 and cell2 classes are subcircuits, */
/* and flattening both of them improves the matching. */
if ((ecomp->num1 != ecomp->num2) && (ecomp->cell2 != NULL) &&
(ecomp->cell2->class == CLASS_SUBCKT)) {
(ecomp->cell1 != NULL) &&
(ecomp->cell2->class == CLASS_SUBCKT) &&
(ecomp->cell1->class == CLASS_SUBCKT)) {
ecomp->add2 = -ecomp->num2;
ecomp->add1 = -ecomp->num1;
match = 1;
for (ob2 = ecomp->cell2->cell; ob2; ob2 = ob2->next) {
if (ob2->type == FIRSTPIN) {
ncomp = (ECompare *)HashLookup(ob2->model.class,
comptab, OBJHASHSIZE);
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
ecomp->cell2->file, comptab, OBJHASHSIZE);
if (ncomp != NULL) {
if ((ncomp->num1 > ncomp->num2) &&
((ncomp->add2 + ecomp->num2) >=
@ -1386,10 +1441,10 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
}
}
if (match) {
if (ecomp->cell2)
flattenInstancesOf(name2, file2, ecomp->cell2->name);
if (ecomp->cell1)
flattenInstancesOf(name1, file1, ecomp->cell1->name);
if (ecomp->cell2)
flattenInstancesOf(name2, file2, ecomp->cell2->name);
modified++;
}
@ -1397,8 +1452,9 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
if (ecomp->cell2)
for (ob2 = ecomp->cell2->cell; ob2; ob2 = ob2->next) {
if (ob2->type == FIRSTPIN) {
ncomp = (ECompare *)HashLookup(ob2->model.class,
comptab, OBJHASHSIZE);
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
ecomp->cell2->file, comptab,
OBJHASHSIZE);
if (ncomp != NULL) {
if (match) {
ncomp->num1 += ncomp->add1;
@ -1415,6 +1471,137 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
}
ecomp->add1 = 0;
ecomp->add2 = 0;
/* If the pair was unresolved, and the number of */
/* instances is either N:0 or 0:M, add to a list so */
/* they can be cross-checked at the end. */
if ((ecomp->num1 != 0) && (ecomp->num2 == 0)) {
ECompList *newcomplist;
newcomplist = (ECompList *)MALLOC(sizeof(ECompList));
newcomplist->ecomp = ecomp;
newcomplist->next = listX0;
listX0 = newcomplist;
}
else if ((ecomp->num1 == 0) && (ecomp->num2 != 0)) {
ECompList *newcomplist;
newcomplist = (ECompList *)MALLOC(sizeof(ECompList));
newcomplist->ecomp = ecomp;
newcomplist->next = list0X;
list0X = newcomplist;
}
}
/* Case 2: Cell2 class is a subcircuit, and flattening */
/* (it without regard to cell1) improves the matching. */
else if ((ecomp->num1 != ecomp->num2) && (ecomp->cell2 != NULL) &&
(ecomp->cell2->class == CLASS_SUBCKT)) {
ecomp->add2 = -ecomp->num2;
match = 1;
for (ob2 = ecomp->cell2->cell; ob2; ob2 = ob2->next) {
if (ob2->type == FIRSTPIN) {
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
ecomp->cell2->file, comptab, OBJHASHSIZE);
if (ncomp != NULL) {
if ((ncomp->num1 > ncomp->num2) &&
((ncomp->add2 + ecomp->num2) <=
ncomp->num1)) {
ncomp->add2 += ecomp->num2;
}
else {
match = 0;
break;
}
}
else {
match = 0;
break;
}
}
}
if (match) {
if (ecomp->cell2)
flattenInstancesOf(name2, file2, ecomp->cell2->name);
modified++;
}
/* Reset or apply the count adjustments */
if (ecomp->cell2)
for (ob2 = ecomp->cell2->cell; ob2; ob2 = ob2->next) {
if (ob2->type == FIRSTPIN) {
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
ecomp->cell2->file, comptab,
OBJHASHSIZE);
if (ncomp != NULL) {
if (match) {
ncomp->num2 += ncomp->add2;
}
ncomp->add2 = 0;
}
}
}
if (match) {
ecomp->num2 = 0;
}
ecomp->add2 = 0;
}
/* Case 3: Cell1 class is a subcircuit, and flattening */
/* (it without regard to cell1) improves the matching. */
else if ((ecomp->num1 != ecomp->num2) && (ecomp->cell1 != NULL) &&
(ecomp->cell1->class == CLASS_SUBCKT)) {
ecomp->add1 = -ecomp->num1;
match = 1;
for (ob2 = ecomp->cell1->cell; ob2; ob2 = ob2->next) {
if (ob2->type == FIRSTPIN) {
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
ecomp->cell1->file, comptab, OBJHASHSIZE);
if (ncomp != NULL) {
if ((ncomp->num2 > ncomp->num1) &&
((ncomp->add1 + ecomp->num1) <=
ncomp->num2)) {
ncomp->add1 += ecomp->num1;
}
else {
match = 0;
break;
}
}
else {
match = 0;
break;
}
}
}
if (match) {
if (ecomp->cell1)
flattenInstancesOf(name1, file1, ecomp->cell1->name);
modified++;
}
/* Reset or apply the count adjustments */
if (ecomp->cell1)
for (ob2 = ecomp->cell1->cell; ob2; ob2 = ob2->next) {
if (ob2->type == FIRSTPIN) {
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
ecomp->cell1->file, comptab,
OBJHASHSIZE);
if (ncomp != NULL) {
if (match) {
ncomp->num1 += ncomp->add1;
}
ncomp->add1 = 0;
}
}
}
if (match) {
ecomp->num1 = 0;
}
ecomp->add1 = 0;
}
ecomp = (ECompare *)HashNext(comptab, OBJHASHSIZE);
}
@ -1619,10 +1806,75 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
}
}
}
ecomp = (ECompare *)HashNext(comptab, OBJHASHSIZE);
}
// Finally, check all entries in listX0 vs. all entries in list0X to see
// if flattening one side will improve the matching. Ignore entries
// that are duplicates (already matched).
if ((listX0 != NULL) && (list0X != NULL)) {
ECompare *ecomp0X, *ecompX0;
ECompList *elist0X, *elistX0;
for (elistX0 = listX0; elistX0; elistX0 = elistX0->next) {
ecompX0 = elistX0->ecomp;
for (elist0X = list0X; elist0X; elist0X = elist0X->next) {
ecomp0X = elist0X->ecomp;
// Check that this has not already been processed and flattened
if (ecompX0->num1 > 0 && ecomp0X->num2 > 0) {
// Are any components of ecompX0->cell1 in the ecomp0X list?
for (ob1 = ecompX0->cell1->cell; ob1; ob1 = ob1->next) {
if (ob1->type == FIRSTPIN) {
char *dstr = NULL;
tc1 = LookupCellFile(ob1->model.class, ecompX0->cell1->file);
if (tc1->flags & CELL_DUPLICATE) {
dstr = strstr(ob1->model.class, "[[");
if (dstr) *dstr = '\0';
}
ncomp = (ECompare *)HashInt2Lookup(ob1->model.class,
ecompX0->cell1->file, comptab, OBJHASHSIZE);
if (dstr) *dstr = '[';
if ((ncomp == ecomp0X) && (ecomp0X->num2 <= ecompX0->num1)) {
flattenInstancesOf(name1, file1, ecompX0->cell1->name);
ecompX0->num1 = 0;
ecomp0X->num1 += ecompX0->num1;
modified++;
break;
}
}
}
// Are any components of ecomp0X->cell2 in the ecompX0 list?
for (ob2 = ecomp0X->cell2->cell; ob2; ob2 = ob2->next) {
if (ob2->type == FIRSTPIN) {
char *dstr = NULL;
tc2 = LookupCellFile(ob2->model.class, ecomp0X->cell2->file);
if (tc2->flags & CELL_DUPLICATE) {
dstr = strstr(ob1->model.class, "[[");
if (dstr) *dstr = '\0';
}
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
ecomp0X->cell2->file, comptab, OBJHASHSIZE);
if (dstr) *dstr = '[';
if ((ncomp == ecompX0) && (ecompX0->num1 <= ecomp0X->num2)) {
flattenInstancesOf(name2, file2, ecomp0X->cell2->name);
ecomp0X->num2 = 0;
ecompX0->num2 += ecomp0X->num2;
modified++;
break;
}
}
}
}
}
}
}
// Free the hash table and its contents.
ecomp = (ECompare *)HashFirst(comptab, OBJHASHSIZE);
@ -1633,5 +1885,17 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
HashKill(comptab, OBJHASHSIZE);
FREE(comptab);
// Free the 0:X and X:0 lists
while (listX0 != NULL) {
ECompList *nextptr = listX0->next;
FREE(listX0);
listX0 = nextptr;
}
while (list0X != NULL) {
ECompList *nextptr = list0X->next;
FREE(list0X);
list0X = nextptr;
}
return modified;
}

View File

@ -150,6 +150,15 @@ unsigned long hash(char *s, int hashsize)
return (hashsize == 0) ? hashval : (hashval % hashsize);
}
unsigned long genhash(char *s, int c, int hashsize)
{
unsigned long hashval;
for (hashval = (unsigned long)c; *s != '\0'; )
hashval = (*s++) + (hashval << 6) + (hashval << 16) - hashval;
return (hashsize == 0) ? hashval : (hashval % hashsize);
}
/*----------------------------------------------------------------------*/
/* HashLookup -- */
/* return the 'ptr' field of the hash table entry, or NULL if not found */
@ -194,6 +203,27 @@ void *HashIntLookup(char *s, int i, struct hashlist **hashtab, int hashsize)
return (NULL); /* not found */
}
/*----------------------------------------------------------------------*/
/* Similar to HashIntLookup, but HashInt2Lookup adds the integer c as */
/* part of the hash, using a special hash function to hash the char */
/* first, then the character string. */
/*----------------------------------------------------------------------*/
void *HashInt2Lookup(char *s, int c, struct hashlist **hashtab, int hashsize)
{
struct hashlist *np;
unsigned long hashval;
hashval = genhash(s, c, hashsize);
for (np = hashtab[hashval]; np != NULL; np = np->next)
if (!strcmp(s, np->name))
return (np->ptr); /* correct match */
return (NULL); /* not found */
}
/*----------------------------------------------------------------------*/
/* return the hashlist entry, after (re)initializing its 'ptr' field */
/*----------------------------------------------------------------------*/
@ -247,6 +277,32 @@ struct hashlist *HashIntPtrInstall(char *name, int value, void *ptr,
return(hashtab[hashval] = np);
}
/*----------------------------------------------------------------------*/
/* And the following is used with HashInt2. */
/*----------------------------------------------------------------------*/
struct hashlist *HashInt2PtrInstall(char *name, int c, void *ptr,
struct hashlist **hashtab, int hashsize)
{
struct hashlist *np;
unsigned long hashval;
hashval = genhash(name, c, hashsize);
for (np = hashtab[hashval]; np != NULL; np = np->next)
if (!strcmp(name, np->name)) {
np->ptr = ptr;
return (np); /* match found in hash table */
}
/* not in table, so install it */
if ((np = (struct hashlist *) CALLOC(1,sizeof(struct hashlist))) == NULL)
return (NULL);
if ((np->name = strsave(name)) == NULL) return (NULL);
np->ptr = ptr;
np->next = hashtab[hashval];
return(hashtab[hashval] = np);
}
/*----------------------------------------------------------------------*/
/* destroy a hash table, freeing associated memory */
/*----------------------------------------------------------------------*/

View File

@ -30,10 +30,13 @@ extern struct hashlist *HashPtrInstall(char *name, void *ptr,
struct hashlist **hashtab, int hashsize);
extern struct hashlist *HashIntPtrInstall(char *name, int value, void *ptr,
struct hashlist **hashtab, int hashsize);
extern struct hashlist *HashInt2PtrInstall(char *name, int c, void *ptr,
struct hashlist **hashtab, int hashsize);
/* these functions return the ->ptr field of a struct hashlist */
extern void *HashLookup(char *s, struct hashlist **hashtab, int hashsize);
extern void *HashIntLookup(char *s, int i, struct hashlist **hashtab, int hashsize);
extern void *HashInt2Lookup(char *s, int c, struct hashlist **hashtab, int hashsize);
extern void *HashFirst(struct hashlist **hashtab, int hashsize);
extern void *HashNext(struct hashlist **hashtab, int hashsize);

View File

@ -2486,14 +2486,16 @@ int FirstElementPass(struct Element *E, int noflat)
if (Ecorr->hashval == 0) {
if (Ecorr->graph == Circuit2->file) {
tp = LookupCellFile(Ecorr->object->model.class, Circuit2->file);
if (tp == tp2) {
// if (tp == tp2) {
if (tp && tp2 && (tp->classhash == tp2->classhash)) {
Ecorr->hashval = 1;
C2++;
}
}
else if (Ecorr->graph == Circuit1->file) {
tp = LookupCellFile(Ecorr->object->model.class, Circuit1->file);
if (tp == tp1) {
// if (tp == tp1) {
if (tp && tp1 && (tp->classhash == tp1->classhash)) {
Ecorr->hashval = 1;
C1++;
}
@ -2535,7 +2537,8 @@ int FirstElementPass(struct Element *E, int noflat)
if (Ecorr->hashval == 0) {
if (Ecorr->graph == Circuit2->file) {
tp = LookupCellFile(Ecorr->object->model.class, Circuit2->file);
if (tp == tp2) {
// if (tp == tp2) {
if (tp->classhash == tp2->classhash) {
Ecorr->hashval = 1;
C2++;
}
@ -2648,8 +2651,14 @@ void MatchFail(char *name1, char *name2)
tc1 = LookupCell(name1);
tc2 = LookupCell(name2);
tc1->flags &= ~CELL_MATCHED;
tc2->flags &= ~CELL_MATCHED;
if (!(tc1->flags & CELL_DUPLICATE) && !(tc2->flags & CELL_DUPLICATE)) {
tc1->flags &= ~CELL_MATCHED;
tc2->flags &= ~CELL_MATCHED;
}
else if (tc1->flags & CELL_DUPLICATE)
tc1->flags &= ~CELL_MATCHED;
else if (tc2->flags & CELL_DUPLICATE)
tc2->flags &= ~CELL_MATCHED;
}
/*--------------------------------------------------------------*/
@ -2666,7 +2675,7 @@ int FlattenUnmatched(struct nlist *tc, char *parent, int stoplevel, int loclevel
Fprintf(stdout, "Flattening unmatched subcell %s in circuit %s ",
tc->name, parent);
changed = flattenInstancesOf(parent, tc->file, tc->name);
Fprintf(stdout, "(%d instances)\n", changed);
Fprintf(stdout, "(%d instance%s)\n", changed, ((changed == 1) ? "" : "s"));
return 1;
}
@ -2722,9 +2731,16 @@ void DescendCompareQueue(struct nlist *tc, struct nlist *tctop, int stoplevel,
struct nlist *tcsub, *tc2, *tctest;
struct objlist *ob;
struct Correspond *scomp, *newcomp;
char *sdup = NULL;
if (loclevel == stoplevel && !(tc->flags & CELL_MATCHED)) {
// Any duplicate cell should be name-matched against a non-duplicate
if (tc->flags & CELL_DUPLICATE) {
sdup = strstr(tc->name, "[[");
if (sdup) *sdup = '\0';
}
// Find exact-name equivalents or cells that have been specified
// as equivalent using the "equate class" command.
@ -2742,10 +2758,15 @@ void DescendCompareQueue(struct nlist *tc, struct nlist *tctop, int stoplevel,
if (tc2 != NULL) {
tctest = LookupPrematchedClass(tc2, tc->file);
if (tctest != NULL && tctest != tc) return;
if (tctest != NULL && tctest != tc) {
if (sdup) *sdup = '[';
return;
}
}
}
if (sdup) *sdup = '[';
if (tc2 != NULL) {
newcomp = (struct Correspond *)CALLOC(1, sizeof(struct Correspond));
newcomp->next = NULL;
@ -3272,8 +3293,8 @@ int PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print)
/* Check if there are any properties to match */
if ((tp1 == NULL) && (tp2 == NULL)) return 0;
if (tp1 != NULL) t1type = tp1->type;
if (tp2 != NULL) t2type = tp2->type;
t1type = (tp1 != NULL) ? tp1->type : 0;
t2type = (tp2 != NULL) ? tp2->type : 0;
if (tp1 == NULL)
if (t2type != PROPERTY) return 0;
@ -4319,8 +4340,9 @@ int EquivalenceClasses(char *name1, int file1, char *name2, int file2)
{
char *class1, *class2;
struct Correspond *newc;
struct nlist *tp, *tp2;
struct nlist *tp, *tp2, *tpx;
unsigned char need_new_seed = 0;
int reverse = 0;
if (file1 != -1 && file2 != -1) {
@ -4328,19 +4350,31 @@ int EquivalenceClasses(char *name1, int file1, char *name2, int file2)
if (tp && (*matchfunc)(tp->name, name2))
return 1; /* Already equivalent */
tp = LookupCellFile(name1, file1);
tp2 = LookupCellFile(name2, file2);
if (tp->classhash == tp2->classhash)
return 1; /* Already equivalent */
/* Where cells with duplicate cell names have been checked and */
/* found to be equivalent, the original keeps the hash value. */
if (tp->flags & CELL_DUPLICATE)
reverse = 1;
/* Do a cross-check for each name in the other netlist. If */
/* conflicting names exist, then alter the classhash to make it */
/* unique. */
/* unique. In the case of duplicate cells, don't do this. */
tp = LookupCellFile(name1, file2);
if (tp != NULL) need_new_seed = 1;
tp = LookupCellFile(name2, file1);
if (tp != NULL) need_new_seed = 1;
if (!(tp->flags & CELL_DUPLICATE) && !(tp2->flags & CELL_DUPLICATE)) {
tpx = LookupCellFile(name1, file2);
if (tpx != NULL) need_new_seed = 1;
tpx = LookupCellFile(name2, file1);
if (tpx != NULL) need_new_seed = 1;
}
/* Now make the classhash values the same so that these cells */
/* are indistinguishable by the netlist comparator. */
tp = LookupCellFile(name1, file1);
if (need_new_seed == 1) {
char *altname;
while (need_new_seed == 1) {
@ -4356,8 +4390,11 @@ int EquivalenceClasses(char *name1, int file1, char *name2, int file2)
FREE(altname);
}
}
tp2 = LookupCellFile(name2, file2);
tp2->classhash = tp->classhash;
if (reverse)
tp->classhash = tp2->classhash;
else
tp2->classhash = tp->classhash;
return 1;
}
@ -4421,8 +4458,14 @@ int reorderpins(struct hashlist *p, int file)
firstpin = ob;
ob2 = tc2->cell;
for (i = 0; i < numports; i++) {
nodes[ob2->model.port] = ob->node;
names[ob2->model.port] = ob->name;
if (ob2->model.port >= numports) {
Fprintf(stderr, "Port number %d greater than number "
"of ports %d\n", ob2->model.port + 1, numports);
}
else {
nodes[ob2->model.port] = ob->node;
names[ob2->model.port] = ob->name;
}
ob = ob->next;
ob2 = ob2->next;
}
@ -4735,7 +4778,42 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2)
}
}
/* Find the end of the pin list in tc1 */
/* Do any unmatched pins have the same name? */
/* (This should not happen if unconnected pins are eliminated) */
ob1 = tc1->cell;
for (i = 0; i < numorig; i++) {
if (*(cover + i) == (char)0) {
j = 0;
for (ob2 = tc2->cell; ob2 != NULL; ob2 = ob2->next) {
if (!IsPort(ob2)) break;
if ((*matchfunc)(ob1->name, ob2->name)) {
ob2->model.port = i; /* save order */
*(cover + i) = (char)1;
if (Debug == 0) {
for (m = 0; m < 43; m++) *(ostr + m) = ' ';
for (m = 44; m < 87; m++) *(ostr + m) = ' ';
sprintf(ostr, "%s", ob1->name);
sprintf(ostr + 44, "%s", ob2->name);
for (m = 0; m < 88; m++)
if (*(ostr + m) == '\0') *(ostr + m) = ' ';
Fprintf(stdout, ostr);
}
else {
Fprintf(stdout, "Circuit %s port %d \"%s\""
" = cell %s port %d \"%s\"\n",
tc1->name, i, ob1->name,
tc2->name, j, ob2->name);
}
}
j++;
}
}
ob1 = ob1->next;
}
/* Find the end of the pin list in tc1, for adding proxy pins */
for (ob1 = tc1->cell; ob1 != NULL; ob1 = ob1->next) {
if (ob1 && ob1->next && ob1->next->type != PORT)
@ -4806,29 +4884,21 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2)
}
}
/* Find the end of the pin list in tc2, for adding proxy pins */
for (ob2 = tc2->cell; ob2 != NULL; ob2 = ob2->next) {
if (ob2 && ob2->next && ob2->next->type != PORT)
break;
}
/* If cell 2 has fewer nodes than cell 1, then add dummy (unconnected) */
/* pins to cell 2. If these correspond to numbers missing in the match */
/* sequence, then fill in the missing numbers. Otherwise, add the */
/* extra nodes to the end. */
j = 0;
for (ob2 = tc2->cell; ob2 != NULL; ob2 = ob2->next) {
j++;
if (ob2->next->type != PORT) break;
}
if (numnodes > numorig) {
ctemp = (char *)CALLOC(numnodes, sizeof(char));
for (i = 0; i < numorig; i++)
ctemp[i] = cover[i];
FREE(cover);
cover = ctemp;
}
i = 0;
while (j < numnodes) {
while (*(cover + i) != (char)0) i++;
if (i >= numnodes) break;
for (i = 0; i < numorig; i++) {
if (*(cover + i) == (char)1) continue;
/* If the equivalent node in tc1 is not disconnected */
/* (node != -1) then we should report a match error, */
@ -4839,6 +4909,14 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2)
for (k = i; k > 0 && ob1 != NULL; k--)
ob1 = ob1->next;
if (ob1 == NULL || ob1->type != PORT || ob1->node >= 0) {
/* Check if ob1->node might really be disconnected */
for (obn = ob1->next; obn; obn = obn->next) {
if (obn->node == ob1->node) break;
}
if (obn == NULL) ob1->node = -1; /* Make disconnected */
}
if (ob1 == NULL || ob1->type != PORT || ob1->node >= 0) {
/* Add a proxy pin to tc2 */
@ -4852,7 +4930,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2)
sprintf(obn->name, "proxy%s", ob1->name);
}
obn->type = UNKNOWN;
obn->model.port = i;
obn->model.port = (i - j);
obn->instance.name = NULL;
obn->node = -1;
obn->next = ob2->next;
@ -4861,9 +4939,18 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2)
hasproxy2 = 1;
HashPtrInstall(obn->name, obn, tc2->objtab, OBJHASHSIZE);
}
j++;
i++;
else if (ob1 != NULL && ob1->type == PORT) {
/* Disconnected node was not meaningful, has no pin match in */
/* the compared circuit, and so should be discarded. */
needclean1 = 1;
/* Adjust numbering around removed node */
for (ob2s = tc2->cell; ob2s != NULL && ob2s->type == PORT; ob2s = ob2s->next) {
if (ob2s->model.port > (i - j)) ob2s->model.port--;
}
j++;
}
}
FREE(cover);

View File

@ -188,6 +188,7 @@ struct nlist {
#define CELL_TOP 0x04 /* cell is a top-level cell */
#define CELL_PLACEHOLDER 0x08 /* cell is a placeholder cell */
#define CELL_PROPSMATCHED 0x10 /* properties matched to matching cell */
#define CELL_DUPLICATE 0x20 /* cell has a duplicate */
/* Flags for combination allowances */

View File

@ -797,8 +797,9 @@ void DescribeInstance(char *name, int file)
{
if (ob->node > nodemax) nodemax = ob->node;
else if ((ob->node == -1) && (ob->model.port != PROXY)) {
if (disconnectednodes == 0) Fprintf(stderr, "\n");
disconnectednodes++;
Fprintf(stderr, " disconnected node: %s\n", ob->name);
Fprintf(stderr, "Cell %s disconnected node: %s\n", tp->name, ob->name);
}
}
instlist = (unsigned char *) CALLOC((nodemax + 1), sizeof(unsigned char));

View File

@ -534,6 +534,7 @@ void ReadSpiceFile(char *fname, int filenum, struct cellstack **CellStackPtr,
}
Printf("Duplicate cell %s in file\n", nexttok);
tp->flags |= CELL_DUPLICATE;
while (tp != NULL) {
n++;
/* Append "[[n]]" to the preexisting model name to force uniqueness */

File diff suppressed because it is too large Load Diff

3048
make.log

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -161,7 +161,12 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out}} {
} else {
# Match pins
netgen::log echo off
equate pins "$fnum1 [lindex $endval 0]" "$fnum2 [lindex $endval 1]"
set result [equate pins "$fnum1 [lindex $endval 0]" \
"$fnum2 [lindex $endval 1]"]
if {$result != 0} {
equate classes "$fnum1 [lindex $endval 0]" \
"$fnum2 [lindex $endval 1]"
}
netgen::log echo on
}
if {$result == 2} {lappend properr [lindex $endval 0]}

View File

@ -122,7 +122,7 @@ Command netgen_cmds[] = {
"<format> <file>\n "
"write a netlist file"},
{"flatten", _netgen_flatten,
"[class] <cell>\n "
"[class] [<parent>] <cell>\n "
"flatten a hierarchical cell"},
{"nodes", _netgen_nodes,
"[<element>] <cell> <file>\n "
@ -1005,9 +1005,9 @@ _netgen_flatten(ClientData clientData,
{
char *repstr, *file;
int result, llen, filenum;
struct nlist *tp;
struct nlist *tp, *tp2;
if ((objc < 2) || (objc > 3)) {
if ((objc < 2) || (objc > 4)) {
Tcl_WrongNumArgs(interp, 1, objv, "?class? valid_cellname");
return TCL_ERROR;
}
@ -1016,12 +1016,32 @@ _netgen_flatten(ClientData clientData,
if (result != TCL_OK) return result;
repstr = tp->name;
if (objc == 3) {
if (objc >= 3) {
char *argv = Tcl_GetString(objv[1]);
if (!strcmp(argv, "class")) {
tp = GetTopCell(filenum);
Printf("Flattening instances of %s in file %s\n", repstr, tp->name);
FlattenInstancesOf(repstr, filenum);
if (objc == 4) {
int numflat;
tp2 = LookupCellFile(Tcl_GetString(objv[2]), filenum);
if (tp2 == NULL) {
Tcl_SetResult(interp, "No such cell.", NULL);
return TCL_ERROR;
}
else {
Printf("Flattening instances of %s in cell %s within file %s\n",
repstr, tp2->name, tp->name);
numflat = flattenInstancesOf(tp2->name, filenum, repstr);
if (numflat == 0) {
Tcl_SetResult(interp, "No instances found to flatten.", NULL);
return TCL_ERROR;
}
}
}
else {
Printf("Flattening instances of %s in file %s\n", repstr, tp->name);
FlattenInstancesOf(repstr, filenum);
}
}
else {
Tcl_WrongNumArgs(interp, 1, objv, "class valid_cellname");
@ -2009,8 +2029,9 @@ _netcmp_compare(ClientData clientData,
return TCL_ERROR;
}
CleanupPins(name1, fnum1); // Remove unconnected pins
CleanupPins(name2, fnum2); // Remove unconnected pins
// WIP!
// CleanupPins(name1, fnum1); // Remove unconnected pins
// CleanupPins(name2, fnum2); // Remove unconnected pins
UniquePins(name1, fnum1); // Check for and remove duplicate pins
UniquePins(name2, fnum2); // Check for and remove duplicate pins
@ -2025,8 +2046,9 @@ _netcmp_compare(ClientData clientData,
// but define global nodes that are brought out as ports by
// ConvertGlobals().
CleanupPins(name1, fnum1);
CleanupPins(name2, fnum2);
// WIP!
// CleanupPins(name1, fnum1);
// CleanupPins(name2, fnum2);
CreateTwoLists(name1, fnum1, name2, fnum2);
while (PrematchLists(name1, fnum1, name2, fnum2) > 0) {
@ -2342,8 +2364,11 @@ _netcmp_verify(ClientData clientData,
if (ElementClasses == NULL || NodeClasses == NULL) {
if (index == EQUIV_IDX || index == UNIQUE_IDX)
Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
else if (CurrentCell != NULL)
Fprintf(stdout, "Verify: cell %s has no elements and/or nodes."
" Not checked.\n", CurrentCell->name);
else
Fprintf(stdout, "Cell has no elements and/or nodes. Not checked.\n");
Fprintf(stdout, "Verify: no current cell to verify.\n");
return TCL_OK;
}
else {
@ -2691,7 +2716,10 @@ _netcmp_equate(ClientData clientData,
case ELEM_IDX:
if (ElementClasses == NULL) {
Fprintf(stderr, "Cell has no elements.\n");
if (CurrentCell == NULL)
Fprintf(stderr, "Equate elements: no current cell.\n");
Fprintf(stderr, "Equate elements: cell %s and/or %s has no elements.\n",
name1, name2);
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
return TCL_OK;
}
@ -2707,7 +2735,10 @@ _netcmp_equate(ClientData clientData,
case PINS_IDX:
if (ElementClasses == NULL) {
Fprintf(stderr, "Cell has no elements.\n");
if (CurrentCell == NULL)
Fprintf(stderr, "Equate elements: no current cell.\n");
Fprintf(stderr, "Equate pins: cell %s and/or %s has no elements.\n",
name1, name2);
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
return TCL_OK;
}