Compare commits

...
17 Commits
Author SHA1 Message Date
Tim Edwards e4a4621b96 Merge branch 'master' into netgen-1.5 2025-01-02 02:00:01 -05:00
Tim Edwards 1d286f9973 Corrected an issue with generating proxy pins that had previously
forced flattening to be done whenever any pin mismatch occurred,
which undermined the whole proxy pin method.  With the proxy pins
fixed, reinstated the method of avoiding flattening when pin
issues can be trivially corrected.  Also:  Added output to the
pin matching for one mismatch case that was being missed.
2025-01-01 13:27:39 -05:00
Tim Edwards 3ca77300ac Merge branch 'master' into netgen-1.5 2024-12-28 02:00:02 -05:00
Tim Edwards 6d2ef396ef After giving the previous code change some more thought, I
decided that it is beneficial to break symmetries by net name;
it's just that net names should not be used before all symmetries
related to pins have been broken.  So I rewrote the compare
routine to take an argument allowing or disallowing net name
matches, and make one call to break symmetries by pin name
followed by another call to break symmetries by net name.  This
still solves the original problem, but does not allow symmetries
to be broken randomly on internal nets if names have been matched
in both netlists.  Otherwise the output may report nets that
appear to be swapped, making the output confusing.
2024-12-27 16:20:00 -05:00
Tim Edwards 2483b7440f Corrected an error in "ResolveAutomorphsByPin" where the code states
to check that the nodes with matching names are pins, but never does.
This results in an attempt to resolve automorphs by matching pin
names AND net names.  However, net names can match without the nets
matching, as pointed out by Andrey Bondar (private communication).
Fixed simply by adding the specified check that the node being name-
matched is actually a pin.
2024-12-26 21:20:24 -05:00
Tim Edwards 236fba18aa Merge branch 'master' into netgen-1.5 2024-11-15 02:00:04 -05:00
Tim Edwards 49c0de0433 Corrected an error found by Sylvain Munaut and discussed on
open-source-silicon slack on Nov. 3 in which the simple verilog
expression "assign name1 = name2[a:b]";  this revealed an error
where the parsing of "name2" was being incorrectly run with
GetBusTok() which must be called when the token starts with "[".
This problem existed both for the left-hand-side parsing and
the right-hand-side parsing, and has been fixed for both (where
either side may be a subset of a bus and the other a complete
bus).
2024-11-14 21:28:51 -05:00
Tim Edwards 3b9dca0cf2 Implemented the patch from Sylvain Munaut in github PR#90 (issue
that the position in the code has shifted quite a bit and I
don't really trust that git will do a clean merge.
2024-11-14 20:39:19 -05:00
Tim Edwards 1272ed22fe Merge branch 'master' into netgen-1.5 2024-10-20 02:00:02 -04:00
Tim Edwards 7d910b616c Modified the string matching "matchnocase()" routine to compare
a verilog escaped string against an equivalent non-escaped
string (requires that the escaped string differs from the non-
escaped string by having a "\" at the front and " " at the end.
The space character is always maintained as part of the string).
2024-10-19 17:07:09 -04:00
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
8 changed files with 391 additions and 223 deletions
+1 -1
View File
@@ -1 +1 @@
1.5.282
1.5.290
+40
View File
@@ -1306,6 +1306,14 @@ int UniquePins(char *name, int filenum)
return 1;
}
/* Structure used below for keeping track of node numbers
* belonging to removed nodes.
*/
struct LinkedNum {
int node;
struct LinkedNum *next;
};
/*------------------------------------------------------*/
/* Callback function for CleanupPins */
/* Note that if the first pin of the instance is a */
@@ -1318,6 +1326,7 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
struct nlist *ptr;
struct objlist *ob, *obt, *lob, *nob, *firstpin, *pob;
struct nlist *tc = (struct nlist *)clientdata;
struct LinkedNum *newnodenum, *removedNodes = (struct LinkedNum *)NULL;
int pinnum;
char *saveinst = NULL;
@@ -1373,6 +1382,15 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
saveinst = ob->instance.name;
}
if (ob->model.class != NULL) FREE(ob->model.class);
// Record the net number of the pin being removed, to
// check at the end if the net belonged to a pin that
// got orphaned.
newnodenum = (struct LinkedNum *)MALLOC(sizeof(struct LinkedNum));
newnodenum->node = ob->node;
newnodenum->next = removedNodes;
removedNodes = newnodenum;
FREE(ob);
}
else {
@@ -1416,6 +1434,28 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
}
}
while (removedNodes != NULL) {
int nodenum = removedNodes->node;
struct objlist *ob2;
/* Only concerned with nodes that are in the pin list of ptr->cell */
for (ob = ptr->cell; ob != NULL; ob = ob->next) {
if (ob->type != PORT) break;
if (ob->node == nodenum) break;
}
if (ob && (ob->type == PORT)) {
/* Check if this node number exists only in the port record */
for (nob = ob->next; nob != NULL; nob = nob->next)
if (nob->node == nodenum) break;
if (nob == NULL) {
ob->node = -1; /* This pin is now disconnected */
}
}
newnodenum = removedNodes;
removedNodes = removedNodes->next;
FREE(newnodenum);
}
if (saveinst != NULL) FREE(saveinst);
return NULL; /* Keep the search going */
}
+294 -214
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
@@ -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 */
+1 -1
View File
@@ -62,7 +62,7 @@ extern void RegroupDataStructures();
extern void FormatIllegalElementClasses();
extern void FormatIllegalNodeClasses();
extern int ResolveAutomorphsByProperty();
extern int ResolveAutomorphsByPin();
extern int ResolveAutomorphsByPin(int match_nets);
extern void SummarizeElementClasses(struct ElementClass *EC);
extern int remove_group_tags(struct objlist *ob);
+16
View File
@@ -223,6 +223,7 @@ int matchnocase(char *st1, char *st2)
{
char *sp1 = st1;
char *sp2 = st2;
char v1 = FALSE, v2 = FALSE;
/* In case of a property that does not exist in one netlist, matchnocase()
* may be passed a null value, so return 0 to indicate a non-match.
@@ -231,11 +232,26 @@ int matchnocase(char *st1, char *st2)
*/
if (!sp1 || !sp2) return 0;
/* Verilog back-slash escaped names should match an equivalent non-
* back-slashed name. (NOTE: This behavior needs to be added to match().)
*/
if ((*sp1 == '\\') && (*sp2 != '\\')) {
v1 = TRUE;
sp1++;
}
if ((*sp2 == '\\') && (*sp1 != '\\')) {
v2 = TRUE;
sp2++;
}
while (*sp1 != '\0' && *sp2 != '\0') {
if (to_lower[*sp1] != to_lower[*sp2]) break;
sp1++;
sp2++;
}
if (v1 && (*sp1 == ' ')) sp1++;
if (v2 && (*sp2 == ' ')) sp2++;
if ((*sp1 != '\0') || (*sp2 != '\0')) return 0;
return 1;
}
+17 -4
View File
@@ -717,10 +717,12 @@ int GetBus(char *astr, struct bus *wb)
return 0;
}
//--------------------------------------------------------------------
// Output a Verilog Module. Note that since Verilog does not describe
// low-level devices like transistors, capacitors, etc., then this
// format is limited to black-box subcircuits. Cells containing any
// such low-level devices are ignored.
//--------------------------------------------------------------------
void VerilogModule(struct nlist *tp)
{
@@ -1833,8 +1835,9 @@ skip_endmodule:
}
else { /* "assign" */
SkipTokComments(VLOG_PIN_CHECK_DELIMITERS);
if (GetBusTok(&wb) == 0) {
char *aptr = strvchr(nexttok, '[');
char *aptr = strvchr(nexttok, '[');
if (((aptr == NULL) && (GetBusTok(&wb) == 0)) ||
((aptr != NULL) && (GetBus(aptr, &wb) == 0))) {
if (aptr != NULL) {
*aptr = '\0';
/* Find object of first net in bus */
@@ -1852,6 +1855,15 @@ skip_endmodule:
}
else {
lhs = LookupObject(nexttok, CurrentCell);
/* Handle the case in which an assignment is made
* without first declaring a wire for the signal,
* which is considered valid syntax (patch by
* Sylvain Munaut).
*/
if (lhs == NULL) {
Node(nexttok);
lhs = LookupObject(nexttok, CurrentCell);
}
strcpy(noderoot, nexttok);
}
SkipTokComments(VLOG_DELIMITERS);
@@ -1900,8 +1912,9 @@ skip_endmodule:
break;
}
else {
if (GetBusTok(&wb2) == 0) {
char *aptr = strvchr(nexttok, '[');
char *aptr = strvchr(nexttok, '[');
if (((aptr == NULL) && (GetBusTok(&wb2) == 0)) ||
((aptr != NULL) && (GetBus(aptr, &wb2) == 0))) {
j = wb2.start;
if (aptr != NULL) {
*aptr = '\0';
+5
View File
@@ -655,6 +655,11 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
}
} elseif {[netgen::print queue] == {} && $result == 0} {
set pinMismatch 1
} else {
# This assumes that proxy pins are added correctly. Previously,
# that was not trusted, and so an initial pin mismatch would
# always force subcells to be flattened.
set doFlatten 0
}
}
if {$doFlatten} {
+17 -3
View File
@@ -2512,7 +2512,13 @@ _netcmp_run(ClientData clientData,
if (automorphisms > 0) {
// Next, attempt to resolve automorphisms uniquely by
// using the pin names
automorphisms = ResolveAutomorphsByPin();
automorphisms = ResolveAutomorphsByPin(FALSE);
}
if (automorphisms > 0) {
// Next, attempt to resolve automorphisms uniquely by
// using the net names (should only be done after
// resolving by pin).
automorphisms = ResolveAutomorphsByPin(TRUE);
}
if (automorphisms > 0) {
// Anything left is truly indistinguishable
@@ -2522,8 +2528,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");