|
|
|
@@ -21,6 +21,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h> /* for rand(), abs(), etc */
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
#include <setjmp.h>
|
|
|
|
|
#include <signal.h>
|
|
|
|
|
#include <time.h> /* for time() as a seed for random number generator */
|
|
|
|
@@ -1496,6 +1497,112 @@ void SortUnmatchedLists(nlists1, nlists2, n1max, n2max)
|
|
|
|
|
HashKill(&n2hash);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*--------------------------------------------------------------*/
|
|
|
|
|
/* Output string formatting routines */
|
|
|
|
|
/* for two-column side-by-side comparisons */
|
|
|
|
|
/*--------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
/*--------------------------------------------------------------*/
|
|
|
|
|
/* Fill left and right columns with spaces */
|
|
|
|
|
/*--------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
void output_string_fill(char *ostr)
|
|
|
|
|
{
|
|
|
|
|
int m;
|
|
|
|
|
for (m = 0; m < left_col_end; m++) *(ostr + m) = ' ';
|
|
|
|
|
for (m = left_col_end + 1; m < right_col_end; m++) *(ostr + m) = ' ';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*--------------------------------------------------------------*/
|
|
|
|
|
/* Write a formatted string in the usual format of sprintf() to */
|
|
|
|
|
/* the left column. */
|
|
|
|
|
/*--------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
void output_string_left(char *ostr, char *format, ...)
|
|
|
|
|
{
|
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
|
|
va_start(ap, format);
|
|
|
|
|
vsnprintf(ostr, left_col_end, format, ap);
|
|
|
|
|
va_end(ap);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*--------------------------------------------------------------*/
|
|
|
|
|
/* Write a formatted string in the usual format of sprintf() to */
|
|
|
|
|
/* the right column. */
|
|
|
|
|
/*--------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
void output_string_right(char *ostr, char *format, ...)
|
|
|
|
|
{
|
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
|
|
va_start(ap, format);
|
|
|
|
|
vsnprintf(ostr + left_col_end + 1, left_col_end, format, ap);
|
|
|
|
|
va_end(ap);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*--------------------------------------------------------------*/
|
|
|
|
|
/* Remove any string breaks within the output string, then */
|
|
|
|
|
/* print the string to stdout. */
|
|
|
|
|
/*--------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
void output_string_print(char *ostr)
|
|
|
|
|
{
|
|
|
|
|
int m;
|
|
|
|
|
for (m = 0; m < right_col_end + 1; m++)
|
|
|
|
|
if (*(ostr + m) == '\0')
|
|
|
|
|
*(ostr + m) = ' ';
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*--------------------------------------------------------------*/
|
|
|
|
|
/* Draw a divider line to the output. If "colbrk" is TRUE, */
|
|
|
|
|
/* then leave the center character as a vertical bar. */
|
|
|
|
|
/* Print the divider line to stdout, then reinstate the */
|
|
|
|
|
/* vertical bar. */
|
|
|
|
|
/*--------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
void output_string_print_divider(char *ostr, char colbrk)
|
|
|
|
|
{
|
|
|
|
|
int m;
|
|
|
|
|
for (m = 0; m < right_col_end; m++) *(ostr + m) = '-';
|
|
|
|
|
if (colbrk) *(ostr + left_col_end) = '|';
|
|
|
|
|
output_string_print(ostr);
|
|
|
|
|
*(ostr + left_col_end) = '|';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*--------------------------------------------------------------*/
|
|
|
|
|
/* Initialize the output string with an empty line and divider */
|
|
|
|
|
/*--------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
char *output_string_init()
|
|
|
|
|
{
|
|
|
|
|
char *ostr = CALLOC(right_col_end + 2, sizeof(char));
|
|
|
|
|
|
|
|
|
|
*(ostr + left_col_end) = '|';
|
|
|
|
|
*(ostr + right_col_end) = '\n';
|
|
|
|
|
*(ostr + right_col_end + 1) = '\0';
|
|
|
|
|
|
|
|
|
|
output_string_fill(ostr);
|
|
|
|
|
|
|
|
|
|
return ostr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*--------------------------------------------------------------*/
|
|
|
|
|
/* Write the header for the comparison output */
|
|
|
|
|
/* Print the header to stdout. */
|
|
|
|
|
/*--------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
void output_string_print_header(char *ostr, struct nlist *tc1, struct nlist *tc2)
|
|
|
|
|
{
|
|
|
|
|
if (tc1)
|
|
|
|
|
output_string_left(ostr, "Circuit 1: %s", tc1->name);
|
|
|
|
|
if (tc2)
|
|
|
|
|
output_string_right(ostr, "Circuit 2: %s", tc2->name);
|
|
|
|
|
|
|
|
|
|
output_string_print(ostr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*---------------------------------------------------------------------
|
|
|
|
|
*---------------------------------------------------------------------
|
|
|
|
@@ -1512,9 +1619,9 @@ void FormatIllegalElementClasses()
|
|
|
|
|
char *permcount;
|
|
|
|
|
int bytesleft;
|
|
|
|
|
|
|
|
|
|
ostr = CALLOC(right_col_end + 2, sizeof(char));
|
|
|
|
|
permname = CALLOC(right_col_end + 2, sizeof(char));
|
|
|
|
|
permcount = CALLOC(right_col_end + 2, sizeof(char));
|
|
|
|
|
ostr = output_string_init();
|
|
|
|
|
|
|
|
|
|
found = 0;
|
|
|
|
|
for (escan = ElementClasses; escan != NULL; escan = escan->next)
|
|
|
|
@@ -1527,15 +1634,7 @@ void FormatIllegalElementClasses()
|
|
|
|
|
|
|
|
|
|
/* Print in side-by-side format */
|
|
|
|
|
|
|
|
|
|
*(ostr + left_col_end) = '|';
|
|
|
|
|
*(ostr + right_col_end) = '\n';
|
|
|
|
|
*(ostr + right_col_end + 1) = '\0';
|
|
|
|
|
for (i = 0; i < left_col_end; i++) *(ostr + i) = ' ';
|
|
|
|
|
for (i = left_col_end + 1; i < right_col_end; i++) *(ostr + i) = ' ';
|
|
|
|
|
snprintf(ostr, left_col_end, "Circuit 1: %s", Circuit1->name);
|
|
|
|
|
snprintf(ostr + left_col_end + 1, left_col_end, "Circuit 2: %s", Circuit2->name);
|
|
|
|
|
for (i = 0; i < right_col_end + 1; i++) if (*(ostr + i) == '\0') *(ostr + i) = ' ';
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
output_string_print_header(ostr, Circuit1, Circuit2);
|
|
|
|
|
}
|
|
|
|
|
found = 1;
|
|
|
|
|
|
|
|
|
@@ -1579,32 +1678,27 @@ void FormatIllegalElementClasses()
|
|
|
|
|
Fprintf(stdout, "\n");
|
|
|
|
|
for (n = 0; n < ((n1 > n2) ? n1 : n2); n++) {
|
|
|
|
|
if (n != 0) {
|
|
|
|
|
for (i = 0; i < left_col_end; i++) *(ostr + i) = ' ';
|
|
|
|
|
for (i = left_col_end + 1; i < right_col_end; i++) *(ostr + i) = ' ';
|
|
|
|
|
output_string_fill(ostr);
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
} else {
|
|
|
|
|
for (i = 0; i < right_col_end; i++) *(ostr + i) = '-';
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
*(ostr + left_col_end) = '|';
|
|
|
|
|
output_string_print_divider(ostr, FALSE);
|
|
|
|
|
}
|
|
|
|
|
for (i = 0; i < left_col_end; i++) *(ostr + i) = ' ';
|
|
|
|
|
for (i = left_col_end + 1; i < right_col_end; i++) *(ostr + i) = ' ';
|
|
|
|
|
output_string_fill(ostr);
|
|
|
|
|
if (n < n1) {
|
|
|
|
|
estr = elist1[n]->name;
|
|
|
|
|
if (*estr == '/') estr++; // Remove leading slash, if any
|
|
|
|
|
snprintf(ostr, left_col_end, "Instance: %s", estr);
|
|
|
|
|
output_string_left(ostr, "Instance: %s", estr);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
snprintf(ostr, left_col_end, "(no matching instance)");
|
|
|
|
|
output_string_left(ostr, "%s", "(no matching instance)");
|
|
|
|
|
if (n < n2) {
|
|
|
|
|
estr = elist2[n]->name;
|
|
|
|
|
if (*estr == '/') estr++; // Remove leading slash, if any
|
|
|
|
|
snprintf(ostr + left_col_end + 1, left_col_end, "Instance: %s", estr);
|
|
|
|
|
output_string_right(ostr, "Instance: %s", estr);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
snprintf(ostr + left_col_end + 1, left_col_end, "(no matching instance)");
|
|
|
|
|
for (i = 0; i < right_col_end + 1; i++) if (*(ostr + i) == '\0') *(ostr + i) = ' ';
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
output_string_right(ostr, "%s", "(no matching instance)");
|
|
|
|
|
output_string_print(ostr);
|
|
|
|
|
|
|
|
|
|
if (n >= n1)
|
|
|
|
|
maxf = elist2[n]->fanout;
|
|
|
|
@@ -1616,12 +1710,11 @@ void FormatIllegalElementClasses()
|
|
|
|
|
|
|
|
|
|
f1 = f2 = 0;
|
|
|
|
|
while ((f1 < maxf) || (f2 < maxf)) {
|
|
|
|
|
for (i = 0; i < left_col_end; i++) *(ostr + i) = ' ';
|
|
|
|
|
for (i = left_col_end + 1; i < right_col_end; i++) *(ostr + i) = ' ';
|
|
|
|
|
output_string_fill(ostr);
|
|
|
|
|
if (n < n1) {
|
|
|
|
|
if (f1 < elist1[n]->fanout) {
|
|
|
|
|
if (elist1[n]->flist[f1].permute == (char)1) {
|
|
|
|
|
snprintf(ostr, left_col_end, " %s = %d", elist1[n]->flist[f1].name,
|
|
|
|
|
output_string_left(ostr, " %s = %d", elist1[n]->flist[f1].name,
|
|
|
|
|
elist1[n]->flist[f1].count);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
@@ -1643,7 +1736,7 @@ void FormatIllegalElementClasses()
|
|
|
|
|
sprintf(value, "%d", elist1[n]->flist[f1].count);
|
|
|
|
|
strcat(permcount, value);
|
|
|
|
|
strcat(permcount, ")");
|
|
|
|
|
snprintf(ostr, left_col_end, " %s = %s", permname, permcount);
|
|
|
|
|
output_string_left(ostr, " %s = %s", permname, permcount);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -1651,7 +1744,7 @@ void FormatIllegalElementClasses()
|
|
|
|
|
if (n < n2) {
|
|
|
|
|
if (f2 < elist2[n]->fanout) {
|
|
|
|
|
if (elist2[n]->flist[f2].permute == (char)1) {
|
|
|
|
|
snprintf(ostr + left_col_end + 1, left_col_end, " %s = %d", elist2[n]->flist[f2].name,
|
|
|
|
|
output_string_right(ostr, " %s = %d", elist2[n]->flist[f2].name,
|
|
|
|
|
elist2[n]->flist[f2].count);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
@@ -1673,21 +1766,18 @@ void FormatIllegalElementClasses()
|
|
|
|
|
sprintf(value, "%d", elist2[n]->flist[f2].count);
|
|
|
|
|
strcat(permcount, value);
|
|
|
|
|
strcat(permcount, ")");
|
|
|
|
|
snprintf(ostr + left_col_end + 1, left_col_end, " %s = %s", permname, permcount);
|
|
|
|
|
output_string_right(ostr, " %s = %s", permname, permcount);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
f2++;
|
|
|
|
|
for (i = 0; i < right_col_end + 1; i++) if (*(ostr + i) == '\0') *(ostr + i) = ' ';
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
output_string_print(ostr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FreeFormattedLists(elist1, numlists1);
|
|
|
|
|
FreeFormattedLists(elist2, numlists2);
|
|
|
|
|
for (i = 0; i < right_col_end; i++) *(ostr + i) = '-';
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
*(ostr + left_col_end) = '|';
|
|
|
|
|
output_string_print_divider(ostr, FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FREE(ostr);
|
|
|
|
@@ -1875,7 +1965,7 @@ void FormatIllegalNodeClasses()
|
|
|
|
|
int found, numlists1, numlists2, n1, n2, n, f, i, maxf;
|
|
|
|
|
char *ostr;
|
|
|
|
|
|
|
|
|
|
ostr = CALLOC(right_col_end + 2, sizeof(char));
|
|
|
|
|
ostr = output_string_init();
|
|
|
|
|
found = 0;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@@ -1893,15 +1983,7 @@ void FormatIllegalNodeClasses()
|
|
|
|
|
Fprintf(stdout, "Class fragments follow (with fanout counts):\n");
|
|
|
|
|
|
|
|
|
|
/* Print in side-by-side format */
|
|
|
|
|
*(ostr + left_col_end) = '|';
|
|
|
|
|
*(ostr + right_col_end) = '\n';
|
|
|
|
|
*(ostr + right_col_end + 1) = '\0';
|
|
|
|
|
for (i = 0; i < left_col_end; i++) *(ostr + i) = ' ';
|
|
|
|
|
for (i = left_col_end + 1; i < right_col_end; i++) *(ostr + i) = ' ';
|
|
|
|
|
snprintf(ostr, left_col_end, "Circuit 1: %s", Circuit1->name);
|
|
|
|
|
snprintf(ostr + left_col_end + 1, left_col_end, "Circuit 2: %s", Circuit2->name);
|
|
|
|
|
for (i = 0; i < right_col_end + 1; i++) if (*(ostr + i) == '\0') *(ostr + i) = ' ';
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
output_string_print_header(ostr, Circuit1, Circuit2);
|
|
|
|
|
}
|
|
|
|
|
found = 1;
|
|
|
|
|
|
|
|
|
@@ -1941,26 +2023,21 @@ void FormatIllegalNodeClasses()
|
|
|
|
|
Fprintf(stdout, "\n");
|
|
|
|
|
for (n = 0; n < ((n1 > n2) ? n1 : n2); n++) {
|
|
|
|
|
if (n != 0) {
|
|
|
|
|
for (i = 0; i < left_col_end; i++) *(ostr + i) = ' ';
|
|
|
|
|
for (i = left_col_end + 1; i < right_col_end; i++) *(ostr + i) = ' ';
|
|
|
|
|
output_string_fill(ostr);
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
} else {
|
|
|
|
|
for (i = 0; i < right_col_end; i++) *(ostr + i) = '-';
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
*(ostr + left_col_end) = '|';
|
|
|
|
|
output_string_print_divider(ostr, FALSE);
|
|
|
|
|
}
|
|
|
|
|
for (i = 0; i < left_col_end; i++) *(ostr + i) = ' ';
|
|
|
|
|
for (i = left_col_end + 1; i < right_col_end; i++) *(ostr + i) = ' ';
|
|
|
|
|
output_string_fill(ostr);
|
|
|
|
|
if (n < n1)
|
|
|
|
|
snprintf(ostr, left_col_end, "Net: %s", nlists1[n]->name);
|
|
|
|
|
output_string_left(ostr, "Net: %s", nlists1[n]->name);
|
|
|
|
|
else
|
|
|
|
|
snprintf(ostr, left_col_end, "(no matching net)");
|
|
|
|
|
output_string_left(ostr, "%s", "(no matching net)");
|
|
|
|
|
if (n < n2)
|
|
|
|
|
snprintf(ostr + left_col_end + 1, left_col_end, "Net: %s", nlists2[n]->name);
|
|
|
|
|
output_string_right(ostr, "Net: %s", nlists2[n]->name);
|
|
|
|
|
else
|
|
|
|
|
snprintf(ostr + left_col_end + 1, left_col_end, "(no matching net)");
|
|
|
|
|
for (i = 0; i < right_col_end + 1; i++) if (*(ostr + i) == '\0') *(ostr + i) = ' ';
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
output_string_right(ostr, "%s", "(no matching net)");
|
|
|
|
|
output_string_print(ostr);
|
|
|
|
|
|
|
|
|
|
if (n >= n1)
|
|
|
|
|
maxf = nlists2[n]->fanout;
|
|
|
|
@@ -1971,17 +2048,16 @@ void FormatIllegalNodeClasses()
|
|
|
|
|
nlists1[n]->fanout : nlists2[n]->fanout;
|
|
|
|
|
|
|
|
|
|
for (f = 0; f < maxf; f++) {
|
|
|
|
|
for (i = 0; i < left_col_end; i++) *(ostr + i) = ' ';
|
|
|
|
|
for (i = left_col_end + 1; i < right_col_end; i++) *(ostr + i) = ' ';
|
|
|
|
|
output_string_fill(ostr);
|
|
|
|
|
if (n < n1)
|
|
|
|
|
if (f < nlists1[n]->fanout) {
|
|
|
|
|
if (nlists1[n]->flist[f].permute <= 1)
|
|
|
|
|
snprintf(ostr, left_col_end, " %s/%s = %d",
|
|
|
|
|
output_string_left(ostr, " %s/%s = %d",
|
|
|
|
|
nlists1[n]->flist[f].model,
|
|
|
|
|
nlists1[n]->flist[f].name,
|
|
|
|
|
nlists1[n]->flist[f].count);
|
|
|
|
|
else {
|
|
|
|
|
snprintf(ostr, left_col_end, " %s/(%s) = %d",
|
|
|
|
|
output_string_left(ostr, " %s/(%s) = %d",
|
|
|
|
|
nlists1[n]->flist[f].model,
|
|
|
|
|
nlists1[n]->flist[f].name,
|
|
|
|
|
nlists1[n]->flist[f].count);
|
|
|
|
@@ -1991,28 +2067,25 @@ void FormatIllegalNodeClasses()
|
|
|
|
|
if (n < n2)
|
|
|
|
|
if (f < nlists2[n]->fanout) {
|
|
|
|
|
if (nlists2[n]->flist[f].permute <= 1)
|
|
|
|
|
snprintf(ostr + left_col_end + 1, left_col_end, " %s/%s = %d",
|
|
|
|
|
output_string_right(ostr, " %s/%s = %d",
|
|
|
|
|
nlists2[n]->flist[f].model,
|
|
|
|
|
nlists2[n]->flist[f].name,
|
|
|
|
|
nlists2[n]->flist[f].count);
|
|
|
|
|
else {
|
|
|
|
|
snprintf(ostr + left_col_end + 1, left_col_end, " %s/(%s) = %d",
|
|
|
|
|
output_string_right(ostr, " %s/(%s) = %d",
|
|
|
|
|
nlists2[n]->flist[f].model,
|
|
|
|
|
nlists2[n]->flist[f].name,
|
|
|
|
|
nlists2[n]->flist[f].count);
|
|
|
|
|
FREE(nlists2[n]->flist[f].name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (i = 0; i < right_col_end + 1; i++) if (*(ostr + i) == '\0') *(ostr + i) = ' ';
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
output_string_print(ostr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FreeFormattedLists(nlists1, numlists1);
|
|
|
|
|
FreeFormattedLists(nlists2, numlists2);
|
|
|
|
|
for (i = 0; i < right_col_end; i++) *(ostr + i) = '-';
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
*(ostr + left_col_end) = '|';
|
|
|
|
|
output_string_print_divider(ostr, FALSE);
|
|
|
|
|
}
|
|
|
|
|
FREE(ostr);
|
|
|
|
|
}
|
|
|
|
@@ -3202,23 +3275,12 @@ int FirstElementPass(struct Element *E, int noflat, int dolist)
|
|
|
|
|
Tcl_Obj *clist1, *clist2;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
ostr = CALLOC(right_col_end + 2, sizeof(char));
|
|
|
|
|
ostr = output_string_init();
|
|
|
|
|
|
|
|
|
|
if (Debug == 0) {
|
|
|
|
|
Fprintf(stdout, "Subcircuit summary:\n");
|
|
|
|
|
*(ostr + left_col_end) = '|';
|
|
|
|
|
*(ostr + right_col_end) = '\n';
|
|
|
|
|
*(ostr + right_col_end + 1) = '\0';
|
|
|
|
|
for (i = 0; i < left_col_end; i++) *(ostr + i) = ' ';
|
|
|
|
|
for (i = left_col_end + 1; i < right_col_end; i++) *(ostr + i) = ' ';
|
|
|
|
|
|
|
|
|
|
snprintf(ostr, left_col_end, "Circuit 1: %s", Circuit1->name);
|
|
|
|
|
snprintf(ostr + left_col_end + 1, left_col_end, "Circuit 2: %s", Circuit2->name);
|
|
|
|
|
for (i = 0; i < right_col_end + 1; i++) if (*(ostr + i) == '\0') *(ostr + i) = ' ';
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
for (i = 0; i < left_col_end; i++) *(ostr + i) = '-';
|
|
|
|
|
for (i = left_col_end + 1; i < right_col_end; i++) *(ostr + i) = '-';
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
output_string_print_header(ostr, Circuit1, Circuit2);
|
|
|
|
|
output_string_print_divider(ostr, TRUE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef TCL_NETGEN
|
|
|
|
@@ -3272,27 +3334,24 @@ int FirstElementPass(struct Element *E, int noflat, int dolist)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Debug == 0) {
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < left_col_end; i++) *(ostr + i) = ' ';
|
|
|
|
|
for (i = left_col_end + 1; i < right_col_end; i++) *(ostr + i) = ' ';
|
|
|
|
|
output_string_fill(ostr);
|
|
|
|
|
if (M1 == C1)
|
|
|
|
|
snprintf(ostr, left_col_end, "%s (%d)", Esrch->object->model.class, C1);
|
|
|
|
|
output_string_left(ostr, "%s (%d)", Esrch->object->model.class, C1);
|
|
|
|
|
else
|
|
|
|
|
snprintf(ostr, left_col_end, "%s (%d->%d)", Esrch->object->model.class,
|
|
|
|
|
output_string_left(ostr, "%s (%d->%d)", Esrch->object->model.class,
|
|
|
|
|
M1, C1);
|
|
|
|
|
if (C2 > 0) {
|
|
|
|
|
if (M2 == C2)
|
|
|
|
|
snprintf(ostr + left_col_end + 1, left_col_end, "%s (%d)%s", tp2->name,
|
|
|
|
|
output_string_right(ostr, "%s (%d)%s", tp2->name,
|
|
|
|
|
C2, (C2 == C1) ? "" : " **Mismatch**");
|
|
|
|
|
else
|
|
|
|
|
snprintf(ostr + left_col_end + 1, left_col_end, "%s (%d->%d)%s",
|
|
|
|
|
output_string_right(ostr, "%s (%d->%d)%s",
|
|
|
|
|
tp2->name, M2, C2, (C2 == C1) ? "" : " **Mismatch**");
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
snprintf(ostr + left_col_end + 1, left_col_end, "(no matching element)");
|
|
|
|
|
output_string_right(ostr, "%s", "(no matching element)");
|
|
|
|
|
}
|
|
|
|
|
for (i = 0; i < right_col_end + 1; i++) if (*(ostr + i) == '\0') *(ostr + i) = ' ';
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
output_string_print(ostr);
|
|
|
|
|
}
|
|
|
|
|
#ifdef TCL_NETGEN
|
|
|
|
|
if (dolist) {
|
|
|
|
@@ -3351,17 +3410,15 @@ int FirstElementPass(struct Element *E, int noflat, int dolist)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Debug == 0) {
|
|
|
|
|
for (i = 0; i < left_col_end; i++) *(ostr + i) = ' ';
|
|
|
|
|
for (i = left_col_end + 1; i < right_col_end; i++) *(ostr + i) = ' ';
|
|
|
|
|
snprintf(ostr, left_col_end, "(no matching element)");
|
|
|
|
|
output_string_fill(ostr);
|
|
|
|
|
output_string_left(ostr, "%s", "(no matching element)");
|
|
|
|
|
if (C2 == M2)
|
|
|
|
|
snprintf(ostr + left_col_end + 1, left_col_end, "%s (%d)",
|
|
|
|
|
output_string_right(ostr, "%s (%d)",
|
|
|
|
|
Esrch->object->model.class, C2);
|
|
|
|
|
else
|
|
|
|
|
snprintf(ostr + left_col_end + 1, left_col_end, "%s (%d->%d)",
|
|
|
|
|
output_string_right(ostr, "%s (%d->%d)",
|
|
|
|
|
Esrch->object->model.class, M2, C2);
|
|
|
|
|
for (i = 0; i < right_col_end + 1; i++) if (*(ostr + i) == '\0') *(ostr + i) = ' ';
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
output_string_print(ostr);
|
|
|
|
|
}
|
|
|
|
|
#ifdef TCL_NETGEN
|
|
|
|
|
if (dolist) {
|
|
|
|
@@ -3405,14 +3462,12 @@ int FirstElementPass(struct Element *E, int noflat, int dolist)
|
|
|
|
|
C1, C2);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
for (i = 0; i < left_col_end; i++) *(ostr + i) = ' ';
|
|
|
|
|
for (i = left_col_end + 1; i < right_col_end; i++) *(ostr + i) = ' ';
|
|
|
|
|
snprintf(ostr, left_col_end, "Number of devices: %d%s", C1, (C1 == C2) ? "" :
|
|
|
|
|
output_string_fill(ostr);
|
|
|
|
|
output_string_left(ostr, "Number of devices: %d%s", C1, (C1 == C2) ? "" :
|
|
|
|
|
" **Mismatch**");
|
|
|
|
|
snprintf(ostr + left_col_end + 1, left_col_end, "Number of devices: %d%s", C2, (C1 == C2) ? "" :
|
|
|
|
|
output_string_right(ostr, "Number of devices: %d%s", C2, (C1 == C2) ? "" :
|
|
|
|
|
" **Mismatch**");
|
|
|
|
|
for (i = 0; i < right_col_end + 1; i++) if (*(ostr + i) == '\0') *(ostr + i) = ' ';
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
output_string_print(ostr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef TCL_NETGEN
|
|
|
|
@@ -3458,23 +3513,14 @@ void FirstNodePass(struct Node *N, int dolist)
|
|
|
|
|
char *ostr;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
ostr = CALLOC(right_col_end + 2, sizeof(char));
|
|
|
|
|
|
|
|
|
|
*(ostr + left_col_end) = '|';
|
|
|
|
|
*(ostr + right_col_end) = '\n';
|
|
|
|
|
*(ostr + right_col_end + 1) = '\0';
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < left_col_end; i++) *(ostr + i) = ' ';
|
|
|
|
|
for (i = left_col_end + 1; i < right_col_end; i++) *(ostr + i) = ' ';
|
|
|
|
|
snprintf(ostr, left_col_end, "Number of nets: %d%s", C1, (C1 == C2) ? "" :
|
|
|
|
|
ostr = output_string_init();
|
|
|
|
|
output_string_left(ostr, "Number of nets: %d%s", C1, (C1 == C2) ? "" :
|
|
|
|
|
" **Mismatch**");
|
|
|
|
|
snprintf(ostr + left_col_end + 1, left_col_end, "Number of nets: %d%s", C2, (C1 == C2) ? "" :
|
|
|
|
|
output_string_right(ostr, "Number of nets: %d%s", C2, (C1 == C2) ? "" :
|
|
|
|
|
" **Mismatch**");
|
|
|
|
|
for (i = 0; i < right_col_end + 1; i++) if (*(ostr + i) == '\0') *(ostr + i) = ' ';
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
output_string_print(ostr);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < right_col_end; i++) *(ostr + i) = '-';
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
output_string_print_divider(ostr, FALSE);
|
|
|
|
|
|
|
|
|
|
FREE(ostr);
|
|
|
|
|
}
|
|
|
|
@@ -5169,26 +5215,34 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
|
|
|
|
|
// (if any)
|
|
|
|
|
|
|
|
|
|
if (comb == TRUE) {
|
|
|
|
|
double pd;
|
|
|
|
|
int mult, cidx = -1;
|
|
|
|
|
struct valuelist *avl, *cvl = NULL;
|
|
|
|
|
critval.type = PROP_ENDLIST;
|
|
|
|
|
critval.value.dval = 0.0;
|
|
|
|
|
for (i = 0; i < run; i++) {
|
|
|
|
|
avl = NULL;
|
|
|
|
|
if (vlist[0][i] == NULL) continue;
|
|
|
|
|
mult = vlist[0][i]->value.ival;
|
|
|
|
|
// if (vlist[0][i] == NULL) continue;
|
|
|
|
|
// mult = vlist[0][i]->value.ival;
|
|
|
|
|
if (vlist[0][i] == NULL)
|
|
|
|
|
mult = 1;
|
|
|
|
|
else
|
|
|
|
|
mult = vlist[0][i]->value.ival;
|
|
|
|
|
changed = 0;
|
|
|
|
|
|
|
|
|
|
/* For all properties that are not M, S, or crit, */
|
|
|
|
|
/* combine as specified by the merge type of the property. */
|
|
|
|
|
|
|
|
|
|
for (p = 1; p < pcount; p++) {
|
|
|
|
|
kl = plist[p];
|
|
|
|
|
vl = vlist[p][i];
|
|
|
|
|
ctype = clist[p][i];
|
|
|
|
|
|
|
|
|
|
/* critical properties never combine, but track them */
|
|
|
|
|
if ((series == TRUE) && (ctype & MERGE_S_CRIT)) {
|
|
|
|
|
if ((vl->type != critval.type) || (vl->value.dval != critval.value.dval))
|
|
|
|
|
pd = 2 * fabs(vl->value.dval - critval.value.dval) /
|
|
|
|
|
(vl->value.dval + critval.value.dval);
|
|
|
|
|
if ((vl->type != critval.type) || (pd > kl->slop.dval))
|
|
|
|
|
{
|
|
|
|
|
critval.type = vl->type;
|
|
|
|
|
critval.value = vl->value;
|
|
|
|
@@ -5197,7 +5251,9 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if ((series == FALSE) && (ctype & MERGE_P_CRIT)) {
|
|
|
|
|
if ((vl->type != critval.type) || (vl->value.dval != critval.value.dval))
|
|
|
|
|
pd = 2 * fabs(vl->value.dval - critval.value.dval) /
|
|
|
|
|
(vl->value.dval + critval.value.dval);
|
|
|
|
|
if ((vl->type != critval.type) || (pd > kl->slop.dval))
|
|
|
|
|
{
|
|
|
|
|
critval.type = vl->type;
|
|
|
|
|
critval.value = vl->value;
|
|
|
|
@@ -5243,6 +5299,11 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
|
|
|
|
|
ctype = clist[p][i];
|
|
|
|
|
|
|
|
|
|
if (ctype & (MERGE_S_ADD | MERGE_P_ADD)) {
|
|
|
|
|
if (!vlist[0][i]) {
|
|
|
|
|
/* Create an entry with M = 0 to force removal */
|
|
|
|
|
vlist[0][i] = (struct valuelist *)CALLOC(1,
|
|
|
|
|
sizeof(struct valuelist));
|
|
|
|
|
}
|
|
|
|
|
vlist[0][i]->value.ival = 0; /* set M to 0 */
|
|
|
|
|
if (cvl && (cvl->type == PROP_INTEGER))
|
|
|
|
|
{
|
|
|
|
@@ -5262,6 +5323,11 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (ctype & (MERGE_S_PAR | MERGE_P_PAR)) {
|
|
|
|
|
if (!vlist[0][i]) {
|
|
|
|
|
/* Create an entry with M = 0 to force removal */
|
|
|
|
|
vlist[0][i] = (struct valuelist *)CALLOC(1,
|
|
|
|
|
sizeof(struct valuelist));
|
|
|
|
|
}
|
|
|
|
|
vlist[0][i]->value.ival = 0; /* set M to 0 */
|
|
|
|
|
/* To do parallel combination, both types need to
|
|
|
|
|
* be double, so recast them if they are integer.
|
|
|
|
@@ -6250,22 +6316,20 @@ PropertyMatch(struct Element *E1, struct Element *E2,
|
|
|
|
|
int multmatch, count;
|
|
|
|
|
PropertyCheckMismatch(tp1, tc1, inst1, tp2, tc2,
|
|
|
|
|
inst2, E1, E2, FALSE, FALSE, &multmatch, NULL);
|
|
|
|
|
if (multmatch == 1) {
|
|
|
|
|
/* Final attempt: Reduce M to 1 on both devices */
|
|
|
|
|
run1 = run2 = 0;
|
|
|
|
|
for (tpc = tp1; tpc && (tpc->type == PROPERTY); tpc = tpc->next) run1++;
|
|
|
|
|
for (tpc = tp2; tpc && (tpc->type == PROPERTY); tpc = tpc->next) run2++;
|
|
|
|
|
PropertyOptimize(tp1, tc1, run1, FALSE, TRUE);
|
|
|
|
|
PropertyOptimize(tp2, tc2, run2, FALSE, TRUE);
|
|
|
|
|
}
|
|
|
|
|
else if (multmatch == 2) {
|
|
|
|
|
run1 = run2 = 0;
|
|
|
|
|
for (tpc = tp1; tpc && (tpc->type == PROPERTY); tpc = tpc->next) run1++;
|
|
|
|
|
for (tpc = tp2; tpc && (tpc->type == PROPERTY); tpc = tpc->next) run2++;
|
|
|
|
|
|
|
|
|
|
if (multmatch == 2) {
|
|
|
|
|
/* Final attempt: Reduce S to 1 on both devices */
|
|
|
|
|
run1 = run2 = 0;
|
|
|
|
|
for (tpc = tp1; tpc && (tpc->type == PROPERTY); tpc = tpc->next) run1++;
|
|
|
|
|
for (tpc = tp2; tpc && (tpc->type == PROPERTY); tpc = tpc->next) run2++;
|
|
|
|
|
PropertyOptimize(tp1, tc1, run1, TRUE, TRUE);
|
|
|
|
|
PropertyOptimize(tp2, tc2, run2, TRUE, TRUE);
|
|
|
|
|
}
|
|
|
|
|
else if ((multmatch == 1) || (run1 != run2)) {
|
|
|
|
|
/* Final attempt: Reduce M to 1 on both devices */
|
|
|
|
|
PropertyOptimize(tp1, tc1, run1, FALSE, TRUE);
|
|
|
|
|
PropertyOptimize(tp2, tc2, run2, FALSE, TRUE);
|
|
|
|
|
}
|
|
|
|
|
#ifdef TCL_NETGEN
|
|
|
|
|
mlist =
|
|
|
|
|
#endif
|
|
|
|
@@ -6503,11 +6567,16 @@ void PrintAutomorphisms(void)
|
|
|
|
|
* separating out those devices that are connected to matching pins
|
|
|
|
|
* in each circuit.
|
|
|
|
|
*
|
|
|
|
|
* If match_nets == TRUE, then also match internal nets by name. Pins
|
|
|
|
|
* should always be matched by name without considering nets first;
|
|
|
|
|
* once all symmetries related to pins have been broken, then matching
|
|
|
|
|
* symmetries by net can keep the output from looking confusing.
|
|
|
|
|
*
|
|
|
|
|
* Return value is the same as VerifyMatching()
|
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int ResolveAutomorphsByPin()
|
|
|
|
|
int ResolveAutomorphsByPin(int match_nets)
|
|
|
|
|
{
|
|
|
|
|
struct NodeClass *NC;
|
|
|
|
|
struct Node *N;
|
|
|
|
@@ -6516,7 +6585,10 @@ int ResolveAutomorphsByPin()
|
|
|
|
|
int portnum;
|
|
|
|
|
|
|
|
|
|
/* Diagnostic */
|
|
|
|
|
Fprintf(stdout, "Resolving symmetries by pin name.\n");
|
|
|
|
|
if (match_nets)
|
|
|
|
|
Fprintf(stdout, "Resolving symmetries by net name.\n");
|
|
|
|
|
else
|
|
|
|
|
Fprintf(stdout, "Resolving symmetries by pin name.\n");
|
|
|
|
|
|
|
|
|
|
for (NC = NodeClasses; NC != NULL; NC = NC->next) {
|
|
|
|
|
struct Node *N1, *N2;
|
|
|
|
@@ -6540,7 +6612,9 @@ int ResolveAutomorphsByPin()
|
|
|
|
|
if (N1->hashval != orighash) continue;
|
|
|
|
|
for (N2 = N1->next; N2 != NULL; N2 = N2->next) {
|
|
|
|
|
if ((N2->graph != N1->graph) &&
|
|
|
|
|
(*matchfunc)(N2->object->name, N1->object->name)) {
|
|
|
|
|
(*matchfunc)(N2->object->name, N1->object->name) &&
|
|
|
|
|
(N1->object->type == PORT || N2->object->type == PORT)) {
|
|
|
|
|
|
|
|
|
|
if (Debug == TRUE)
|
|
|
|
|
Printf("Symmetry group broken by name match (pin %s)\n", N2->object->name);
|
|
|
|
|
Magic(newhash);
|
|
|
|
@@ -7518,6 +7592,10 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
|
|
|
|
for (ob2 = tc2->cell; ob2 != NULL; ob2 = ob2->next) {
|
|
|
|
|
if (ob2->type != PORT) break;
|
|
|
|
|
else haspins = 1;
|
|
|
|
|
/* The model.port record for pins will be used to match the pin order
|
|
|
|
|
* of the cells in each netlist. Make sure the value is reset on
|
|
|
|
|
* entering this subroutine.
|
|
|
|
|
*/
|
|
|
|
|
ob2->model.port = -1;
|
|
|
|
|
}
|
|
|
|
|
numnodes = 0;
|
|
|
|
@@ -7546,23 +7624,13 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
ostr = CALLOC(right_col_end + 2, sizeof(char));
|
|
|
|
|
ostr = output_string_init();
|
|
|
|
|
|
|
|
|
|
if (Debug == 0) {
|
|
|
|
|
/* Format side-by-side comparison of pins */
|
|
|
|
|
Fprintf(stdout, "\nSubcircuit pins:\n");
|
|
|
|
|
*(ostr + left_col_end) = '|';
|
|
|
|
|
*(ostr + right_col_end) = '\n';
|
|
|
|
|
*(ostr + right_col_end + 1) = '\0';
|
|
|
|
|
for (i = 0; i < left_col_end; i++) *(ostr + i) = ' ';
|
|
|
|
|
for (i = left_col_end + 1; i < right_col_end; i++) *(ostr + i) = ' ';
|
|
|
|
|
snprintf(ostr, left_col_end, "Circuit 1: %s", tc1->name);
|
|
|
|
|
snprintf(ostr + left_col_end + 1, left_col_end, "Circuit 2: %s", tc2->name);
|
|
|
|
|
for (i = 0; i < right_col_end + 1; i++) if (*(ostr + i) == '\0') *(ostr + i) = ' ';
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
for (i = 0; i < left_col_end; i++) *(ostr + i) = '-';
|
|
|
|
|
for (i = left_col_end + 1; i < right_col_end; i++) *(ostr + i) = '-';
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
output_string_print_header(ostr, tc1, tc2);
|
|
|
|
|
output_string_print_divider(ostr, TRUE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (NC = NodeClasses; NC != NULL; NC = NC->next) {
|
|
|
|
@@ -7601,13 +7669,12 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
|
|
|
|
nomatch = FALSE;
|
|
|
|
|
if ((IsPort(ob2)) && (ob2->node == obp->node)) {
|
|
|
|
|
if (Debug == 0) {
|
|
|
|
|
for (m = 0; m < left_col_end; m++) *(ostr + m) = ' ';
|
|
|
|
|
for (m = left_col_end + 1; m < right_col_end; m++) *(ostr + m) = ' ';
|
|
|
|
|
snprintf(ostr, left_col_end, "%s", ob1->name);
|
|
|
|
|
output_string_fill(ostr);
|
|
|
|
|
output_string_left(ostr, "%s", ob1->name);
|
|
|
|
|
}
|
|
|
|
|
if ((*matchfunc)(ob1->name, ob2->name)) {
|
|
|
|
|
if (Debug == 0)
|
|
|
|
|
snprintf(ostr + left_col_end + 1, left_col_end, "%s", ob2->name);
|
|
|
|
|
output_string_right(ostr, "%s", ob2->name);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* Check remainder of ports to see if there is a name match on the
|
|
|
|
@@ -7619,7 +7686,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
|
|
|
|
if ((*matchfunc)(ob3->name, ob1->name)) {
|
|
|
|
|
ob2 = ob3;
|
|
|
|
|
if (Debug == 0)
|
|
|
|
|
snprintf(ostr + left_col_end + 1, left_col_end, "%s", ob2->name);
|
|
|
|
|
output_string_right(ostr, "%s", ob2->name);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -7627,9 +7694,10 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
|
|
|
|
if (ob3 == NULL) {
|
|
|
|
|
if (Debug == 0) {
|
|
|
|
|
if (ob2->model.port == -1)
|
|
|
|
|
snprintf(ostr + left_col_end + 1, left_col_end, "%s **Mismatch**", ob2->name);
|
|
|
|
|
output_string_right(ostr, "%s **Mismatch**",
|
|
|
|
|
ob2->name);
|
|
|
|
|
else
|
|
|
|
|
snprintf(ostr + left_col_end + 1, left_col_end, "(no matching pin)", ob2->name);
|
|
|
|
|
output_string_right(ostr, "%s", "(no matching pin)");
|
|
|
|
|
}
|
|
|
|
|
nomatch = TRUE;
|
|
|
|
|
/* Pins with different names are on different nets,
|
|
|
|
@@ -7640,9 +7708,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Debug == 0) {
|
|
|
|
|
for (m = 0; m < right_col_end + 1; m++)
|
|
|
|
|
if (*(ostr + m) == '\0') *(ostr + m) = ' ';
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
output_string_print(ostr);
|
|
|
|
|
}
|
|
|
|
|
else if (nomatch) {
|
|
|
|
|
Fprintf(stderr, "No matching pin in cell %s for "
|
|
|
|
@@ -7681,13 +7747,11 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
|
|
|
|
// so don't print out the "no pins" entry.
|
|
|
|
|
|
|
|
|
|
if (strcmp(obn->name, "(no pins)")) {
|
|
|
|
|
for (m = 0; m < left_col_end; m++) *(ostr + m) = ' ';
|
|
|
|
|
for (m = left_col_end + 1; m < right_col_end; m++) *(ostr + m) = ' ';
|
|
|
|
|
snprintf(ostr, 32, "%s", obn->name);
|
|
|
|
|
snprintf(ostr + left_col_end + 1, left_col_end, "(no pin, node is %s)", obp->name);
|
|
|
|
|
for (m = 0; m < right_col_end + 1; m++)
|
|
|
|
|
if (*(ostr + m) == '\0') *(ostr + m) = ' ';
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
output_string_fill(ostr);
|
|
|
|
|
output_string_left(ostr, "%s", obn->name);
|
|
|
|
|
output_string_right(ostr, "(no pin, node is %s)",
|
|
|
|
|
obp->name);
|
|
|
|
|
output_string_print(ostr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
@@ -7729,13 +7793,10 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
|
|
|
|
|
|
|
|
|
if (ob1 == NULL) {
|
|
|
|
|
if (Debug == 0) {
|
|
|
|
|
for (m = 0; m < left_col_end; m++) *(ostr + m) = ' ';
|
|
|
|
|
for (m = left_col_end + 1; m < right_col_end; m++) *(ostr + m) = ' ';
|
|
|
|
|
snprintf(ostr, left_col_end, "%s", obn->name);
|
|
|
|
|
snprintf(ostr + left_col_end + 1, left_col_end, "(no matching pin)");
|
|
|
|
|
for (m = 0; m < right_col_end + 1; m++)
|
|
|
|
|
if (*(ostr + m) == '\0') *(ostr + m) = ' ';
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
output_string_fill(ostr);
|
|
|
|
|
output_string_left(ostr, "%s", obn->name);
|
|
|
|
|
output_string_right(ostr, "%s", "(no matching pin)");
|
|
|
|
|
output_string_print(ostr);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
Fprintf(stderr, "No netlist match for cell %s pin %s\n",
|
|
|
|
@@ -7815,13 +7876,10 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
|
|
|
|
*(cover + i) = (char)1;
|
|
|
|
|
|
|
|
|
|
if (Debug == 0) {
|
|
|
|
|
for (m = 0; m < left_col_end; m++) *(ostr + m) = ' ';
|
|
|
|
|
for (m = left_col_end + 1; m < right_col_end; m++) *(ostr + m) = ' ';
|
|
|
|
|
snprintf(ostr, left_col_end, "%s", ob1->name);
|
|
|
|
|
snprintf(ostr + left_col_end + 1, left_col_end, "%s", ob2->name);
|
|
|
|
|
for (m = 0; m < right_col_end + 1; m++)
|
|
|
|
|
if (*(ostr + m) == '\0') *(ostr + m) = ' ';
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
output_string_fill(ostr);
|
|
|
|
|
output_string_left(ostr, "%s", ob1->name);
|
|
|
|
|
output_string_right(ostr, "%s", ob2->name);
|
|
|
|
|
output_string_print(ostr);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
Fprintf(stdout, "Circuit %s port %d \"%s\""
|
|
|
|
@@ -7870,13 +7928,10 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
|
|
|
|
*(cover + i) = (char)1;
|
|
|
|
|
|
|
|
|
|
if (Debug == 0) {
|
|
|
|
|
for (m = 0; m < left_col_end; m++) *(ostr + m) = ' ';
|
|
|
|
|
for (m = left_col_end + 1; m < right_col_end; m++) *(ostr + m) = ' ';
|
|
|
|
|
snprintf(ostr, left_col_end, "%s", ob1->name);
|
|
|
|
|
snprintf(ostr + left_col_end + 1, left_col_end, "%s", ob2->name);
|
|
|
|
|
for (m = 0; m < right_col_end + 1; m++)
|
|
|
|
|
if (*(ostr + m) == '\0') *(ostr + m) = ' ';
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
output_string_fill(ostr);
|
|
|
|
|
output_string_left(ostr, "%s", ob1->name);
|
|
|
|
|
output_string_right(ostr, "%s", ob2->name);
|
|
|
|
|
output_string_print(ostr);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
Fprintf(stdout, "Circuit %s port %d \"%s\""
|
|
|
|
@@ -7934,13 +7989,10 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
|
|
|
|
*(cover + i) = (char)1;
|
|
|
|
|
|
|
|
|
|
if (Debug == 0) {
|
|
|
|
|
for (m = 0; m < left_col_end; m++) *(ostr + m) = ' ';
|
|
|
|
|
for (m = left_col_end + 1; m < right_col_end; m++) *(ostr + m) = ' ';
|
|
|
|
|
snprintf(ostr, left_col_end, "%s", ob1->name);
|
|
|
|
|
snprintf(ostr + left_col_end + 1, left_col_end, "%s", ob2->name);
|
|
|
|
|
for (m = 0; m < right_col_end + 1; m++)
|
|
|
|
|
if (*(ostr + m) == '\0') *(ostr + m) = ' ';
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
output_string_fill(ostr);
|
|
|
|
|
output_string_left(ostr, "%s", ob1->name);
|
|
|
|
|
output_string_right(ostr, "%s", ob2->name);
|
|
|
|
|
output_string_print(ostr);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
Fprintf(stdout, "Circuit %s port %d \"%s\""
|
|
|
|
@@ -7989,16 +8041,38 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
|
|
|
|
if (ob2->type != PORT) break;
|
|
|
|
|
if (ob2->model.port == -1) {
|
|
|
|
|
|
|
|
|
|
/* Find this node in NodeClasses and find the corresponding
|
|
|
|
|
* net in the other circuit, if there is one (NOTE: Needs
|
|
|
|
|
* refactoring; should not be going through NodeClasses
|
|
|
|
|
* inside a loop.)
|
|
|
|
|
*/
|
|
|
|
|
obn = NULL;
|
|
|
|
|
for (NC = NodeClasses; NC != NULL; NC = NC->next) {
|
|
|
|
|
for (N2 = NC->nodes; N2 != NULL; N2 = N2->next) {
|
|
|
|
|
if (N2->graph != Circuit1->file) {
|
|
|
|
|
obp = N2->object;
|
|
|
|
|
if (IsPort(obp) && (obp->node == ob2->node)) {
|
|
|
|
|
for (N1 = NC->nodes; N1 != NULL; N1 = N1->next) {
|
|
|
|
|
if (N1->graph == Circuit1->file) {
|
|
|
|
|
obn = N1->object;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Debug == 0) {
|
|
|
|
|
// See above for reverse case
|
|
|
|
|
if (strcmp(ob2->name, "(no pins)")) {
|
|
|
|
|
for (m = 0; m < left_col_end; m++) *(ostr + m) = ' ';
|
|
|
|
|
for (m = left_col_end + 1; m < right_col_end; m++) *(ostr + m) = ' ';
|
|
|
|
|
snprintf(ostr, left_col_end, "(no matching pin)");
|
|
|
|
|
snprintf(ostr + left_col_end + 1, left_col_end, "%s", ob2->name);
|
|
|
|
|
for (m = 0; m < right_col_end + 1; m++)
|
|
|
|
|
if (*(ostr + m) == '\0') *(ostr + m) = ' ';
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
output_string_fill(ostr);
|
|
|
|
|
if (obn == NULL)
|
|
|
|
|
output_string_left(ostr, "%s", "(no matching pin)");
|
|
|
|
|
else
|
|
|
|
|
output_string_left(ostr, "(no pin, node is %s)",
|
|
|
|
|
obn->name);
|
|
|
|
|
output_string_right(ostr, "%s", ob2->name);
|
|
|
|
|
output_string_print(ostr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
@@ -8113,12 +8187,15 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
|
|
|
|
if (obn == NULL) ob1->node = -1; /* Make disconnected */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* NOTE: Previously kept the port if model.port is -1; however,
|
|
|
|
|
* all ports are -1 here so not sure why that was in there. . .
|
|
|
|
|
*/
|
|
|
|
|
if (ob1 == NULL || ob1->type != PORT || ob1->node >= 0
|
|
|
|
|
|| (ob1->node < 0 && tc1->class == CLASS_MODULE)
|
|
|
|
|
|| (ob1->node < 0 && ob1->model.port == -1)) {
|
|
|
|
|
|| (ob1->node < 0 && tc1->class == CLASS_MODULE)) {
|
|
|
|
|
|
|
|
|
|
/* Add a proxy pin to tc2 */
|
|
|
|
|
obn = (struct objlist *)CALLOC(1, sizeof(struct objlist));
|
|
|
|
|
obn->node = -1;
|
|
|
|
|
if (ob1 == NULL) {
|
|
|
|
|
obn->name = (char *)MALLOC(15);
|
|
|
|
|
sprintf(obn->name, "proxy%d", rand() & 0x3ffffff);
|
|
|
|
@@ -8130,7 +8207,6 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
|
|
|
|
obn->type = UNKNOWN;
|
|
|
|
|
obn->model.port = (i - j);
|
|
|
|
|
obn->instance.name = NULL;
|
|
|
|
|
obn->node = -1;
|
|
|
|
|
|
|
|
|
|
if (ob2 == tc2->cell) {
|
|
|
|
|
obn->next = ob2;
|
|
|
|
@@ -8146,9 +8222,16 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
|
|
|
|
HashPtrInstall(obn->name, obn, &(tc2->objdict));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else if (ob1 != NULL && ob1->type == PORT) {
|
|
|
|
|
else if (ob1 != NULL && ob1->type == PORT && ob1->node < 0) {
|
|
|
|
|
/* Disconnected node was not meaningful, has no pin match in */
|
|
|
|
|
/* the compared circuit, and so should be discarded. */
|
|
|
|
|
/* the compared circuit, and so should be discarded. This */
|
|
|
|
|
/* case is not output above, so do it here. */
|
|
|
|
|
|
|
|
|
|
output_string_fill(ostr);
|
|
|
|
|
output_string_left(ostr, "%s", ob1->name);
|
|
|
|
|
output_string_right(ostr, "%s", "(no matching pin)");
|
|
|
|
|
output_string_print(ostr);
|
|
|
|
|
|
|
|
|
|
ob1->node = -2;
|
|
|
|
|
needclean1 = 1;
|
|
|
|
|
|
|
|
|
@@ -8161,15 +8244,12 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
|
|
|
|
}
|
|
|
|
|
FREE(cover);
|
|
|
|
|
|
|
|
|
|
if (Debug == 0) {
|
|
|
|
|
for (i = 0; i < right_col_end; i++) *(ostr + i) = '-';
|
|
|
|
|
Fprintf(stdout, ostr);
|
|
|
|
|
}
|
|
|
|
|
if (Debug == 0)
|
|
|
|
|
output_string_print_divider(ostr, FALSE);
|
|
|
|
|
|
|
|
|
|
/* Run cleanuppins on circuit 1 */
|
|
|
|
|
if (needclean1) {
|
|
|
|
|
if (needclean1)
|
|
|
|
|
CleanupPins(tc1->name, tc1->file);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Add proxy pins to all instances of Circuit1 */
|
|
|
|
|
|
|
|
|
|