Compare commits

..
11 Commits
Author SHA1 Message Date
Tim Edwards 6179ba8cb8 Merge branch 'master' into netgen-1.5 2024-10-17 02:00:02 -04:00
Tim Edwards b1032f846b Refactored code in netcmp.c involved in printing side-by-side
formatted output to make it much cleaner and easier to read.  This
is in preparation of correcting the circuit1<-->circuit2 asymmetry
in the MatchPins() routine.
2024-10-16 20:38:44 -04:00
Tim Edwards 4c546d1472 Corrected an error that prevents property errors from being
printed in detail if a port error is also found.
2024-10-16 09:44:48 -04:00
Tim Edwards aaf8fefc1a Merge branch 'master' into netgen-1.5 2024-10-16 02:00:02 -04:00
Tim Edwards e1aa231db1 Corrected another error discovered by Andrei Bondar in which
the critical property (e.g., L for transistors) is required to
match exactly between devices in order to allow the additive
property (e.g., W for transistors) to be summed.  The critical
property should match if all values are within the slop value,
for floating-point values.  Note:  The implementation is still
not rigorous, as the saved critical value may shift from
device to device;  so comparing, e.g., 1.00 to 1.01 to 1.02 to
1.03, etc., can find that all individual comparisons are within
the slop value even though the slop is exceeded across all values.
2024-10-15 20:52:23 -04:00
Tim Edwards abaf896f7f Merge branch 'master' into netgen-1.5 2024-10-15 02:00:02 -04:00
Tim Edwards df8fa29b2f Fixed an issue with property matching that was preventing the last-
ditch effort of matching based on combining devices with the same
critical property (e.g., adding gate widths together for transistors
of the same gate length, if the property records remain stubbornly
mismatched to the end).  Thanks to Bondar Andrey Renatovich for
surfacing this issue and providing a reproducible example.
2024-10-14 13:24:35 -04:00
Tim Edwards e94d25b3f1 Merge branch 'master' into netgen-1.5 2024-10-08 02:00:03 -04:00
Tim Edwards d14bf70f1c Working to get some MatchPins improvements from Mitch Bailey from
a long time ago into the code.  The improvements collided with
intervening changes to the same routines and would not merge
cleanly, which is why they were never merged.  Step 1:  Show the
net name of a matching net that is missing a pin.  Remove output
of missing pins that is redundant (pin names being output twice).
2024-10-07 11:10:33 -04:00
Tim Edwards e659495ef5 Merge branch 'master' into netgen-1.5 2024-10-04 02:00:03 -04:00
Tim Edwards 5c21000a8b Made a modification to accommodate the situation where a SPICE
instance is matched to a verilog module definition, and the SPICE
instance is read before the verilog definition, forcing a
placeholder cell to be created.  Netgen will now make the
assumption that the verilog ports are in the same order as the
SPICE instance port order.  At the same time, it will output a
warning message that it is making this not-necessarily-warranted
assumption.  If the number of ports don't match or the placeholder
did not come from a SPICE instance, then the placeholder pins are
left alone.
2024-10-03 14:52:42 -04:00
4 changed files with 304 additions and 226 deletions
+1 -1
View File
@@ -1 +1 @@
1.5.280
1.5.285
+238 -223
View File
@@ -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
@@ -7546,23 +7610,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 +7655,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 +7672,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 +7680,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)");
output_string_right(ostr, "%s", "(no matching pin)");
}
nomatch = TRUE;
/* Pins with different names are on different nets,
@@ -7640,9 +7694,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 +7733,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 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, "(no pin, node is %s",
obp->name);
output_string_print(ostr);
}
}
else {
@@ -7729,13 +7779,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 +7862,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 +7914,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 +7975,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\""
@@ -7992,13 +8030,10 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
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);
output_string_left(ostr, "%s", "(no matching pin)");
output_string_right(ostr, "%s", ob2->name);
output_string_print(ostr);
}
}
else {
@@ -8132,23 +8167,6 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
obn->instance.name = NULL;
obn->node = -1;
/* Note: Has this pin already been accounted for? */
if (Debug == 0) {
if (strcmp(ob1->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, "%s", ob1->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);
}
}
else {
Fprintf(stderr, "No netlist match for cell %s pin %s\n",
tc1->name, ob1->name);
}
if (ob2 == tc2->cell) {
obn->next = ob2;
tc2->cell = obn;
@@ -8178,15 +8196,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 */
+55
View File
@@ -1408,6 +1408,9 @@ skip_endmodule:
if (tpsave != NULL) {
struct nlist *tpplace;
char *savename;
int lnum, pnum, ltest;
unsigned char valid;
struct objlist *lobj, *pobj;
/* Handle a placeholder from a verilog file that has been replaced
* by a netlist with pins in a different order. The pins need to
@@ -1418,6 +1421,58 @@ skip_endmodule:
Printf("Verilog placeholder module %s replaced by module definition\n",
tpsave->name);
tpplace = LookupCellFile("_PLACEHOLDER_", filenum);
/* If tpsave was generated from an instance in a SPICE netlist that
* did not have a black-box subcircuit definition, then the pins
* will all be labeled 1, 2, 3, etc. If so, then assume that the
* verilog pins are in order, and rename the placeholder pins.
* If the number of pins does not match, or if the pins are not
* labeled as ascending integers, then leave the cell alone.
* In either case, output a warning message.
*/
/* Get the number of ports in the placeholder */
pnum = 0;
for (pobj = tpplace->cell; pobj; pobj = pobj->next) {
if (pobj->type != PORT) break;
pnum++;
}
/* Get the number of ports in the saved cell and make */
/* sure that it equals the number of ports in the */
/* placeholder, and that all of the ports in the saved */
/* cell are integers in ascending order. */
valid = TRUE;
lnum = 0;
for (lobj = tpsave->cell; lobj; lobj = lobj->next) {
if (lobj->type != PORT) break;
lnum++;
if (sscanf(lobj->name, "%d", &ltest) != 1) break;
if (ltest != lnum) break;
}
if ((lobj != NULL) && (lobj->type == PORT))
valid = FALSE; /* Pins are not integers in ascending order */
if (pnum != lnum) valid = FALSE; /* Different number of pins */
if (valid == TRUE) {
Printf("Replacing pins of placeholder cell %s from cell definition.\n",
tpsave->name);
pobj = tpplace->cell;
for (lobj = tpsave->cell; lobj; lobj = lobj->next) {
if (lobj->type != PORT) break;
if (pobj == NULL) break; /* should not happen */
FREE(lobj->name);
lobj->name = (char *)MALLOC(strlen(pobj->name) + 1);
strcpy(lobj->name, pobj->name);
pobj = pobj->next;
}
}
else {
Printf("Placeholder pins of cell %s are not compatible and"
" will be left unchanged\n", tpsave->name);
}
/* MatchPins is part of netcmp and normally Circuit2 is the
* circuit being matched, so set Circuit2 to the original
* verilog black-box cell, and MatchPins() will force its
+10 -2
View File
@@ -2522,8 +2522,16 @@ _netcmp_run(ClientData clientData,
if (automorphisms == -1)
Fprintf(stdout, "Netlists do not match.\n");
else if (automorphisms == -2)
Fprintf(stdout, "Netlists match uniquely with port errors.\n");
else if (automorphisms == -2) {
Fprintf(stdout, "Netlists match uniquely with port");
if (PropertyErrorDetected) {
Fprintf(stdout, " and property errors.\n");
PrintPropertyResults(dolist);
}
else {
Fprintf(stdout, " errors.\n");
}
}
else {
if (automorphisms == 0)
Fprintf(stdout, "Netlists match uniquely");