From 20077d3d56a68a3fddf1be829b9406f1a6ca262b Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 3 Mar 2021 17:31:45 -0500 Subject: [PATCH 1/4] Modifed the handling of parallelized no-connects so that the behavior can be turned on or off from the setup using "property parallel open" to allow parallelizing devices with no-connect pins vs. "property parallel connected" to only allow parallelizing of devices with all pins connected. --- base/netgen.c | 12 ++++++++---- base/netgen.h | 1 + tcltk/tclnetgen.c | 10 ++++++++-- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/base/netgen.c b/base/netgen.c index ab8e97f..0c8dc86 100644 --- a/base/netgen.c +++ b/base/netgen.c @@ -50,6 +50,7 @@ int NextNode; int Composition = NONE; int QuickSearch = 0; int GlobalParallelNone = FALSE; +int GlobalParallelOpen = TRUE; int AddToExistingDefinition = 0; /* default: overwrite cell when reopened */ @@ -3164,10 +3165,13 @@ int CombineParallel(char *model, int file) /* can be treated as equivalent for the purpose of parallelization. */ nodecount = (int *)CALLOC((tp->nodename_cache_maxnodenum + 1), sizeof(int)); - for (ob = tp->cell; ob; ob = ob->next) { - if (ob->node >= 0) - if (ob->type != NODE) - nodecount[ob->node]++; + + if (GlobalParallelOpen) { + for (ob = tp->cell; ob; ob = ob->next) { + if (ob->node >= 0) + if (ob->type != NODE) + nodecount[ob->node]++; + } } lob = NULL; diff --git a/base/netgen.h b/base/netgen.h index 9de7dfe..20e55f3 100644 --- a/base/netgen.h +++ b/base/netgen.h @@ -149,6 +149,7 @@ extern int NoOutput; /* set this to 1 to disable stdout output */ extern int Composition; /* direction of composition */ extern int UnixWildcards; /* TRUE if *,?,{},[] only; false if full REGEXP */ extern int GlobalParallelNone; /* If TRUE, don't parallel combine any cells */ +extern int GlobalParallelOpen; /* If TRUE, parallel combine cells w/no-connects */ /* magic internal flag to restrict searches to recently placed cells */ extern int QuickSearch; /* does re"CellDef"ing a cell add to it or overwrite it??? */ diff --git a/tcltk/tclnetgen.c b/tcltk/tclnetgen.c index 6f57700..e34522f 100644 --- a/tcltk/tclnetgen.c +++ b/tcltk/tclnetgen.c @@ -3417,9 +3417,15 @@ _netcmp_property(ClientData clientData, GlobalParallelNone = FALSE; SetParallelCombine(TRUE); } + else if (!strcmp(Tcl_GetString(objv[2]), "connected")) { + GlobalParallelOpen = FALSE; + } + else if (!strcmp(Tcl_GetString(objv[2]), "open")) { + GlobalParallelOpen = TRUE; + } else { - Tcl_SetResult(interp, "Bad option, should be property parallel none|all", - NULL); + Tcl_SetResult(interp, "Bad option, should be property parallel " + "none|all|connected", NULL); return TCL_ERROR; } return TCL_OK; From fd72e24a86cf9ffe02a2664070d4b9e649c6ca75 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 5 Mar 2021 11:32:17 -0500 Subject: [PATCH 2/4] Corrected an error in the code that handles no-connects as valid pins for enabling parallel combinations, which could cause a crash. Added a "-force" option to "equate pins" to allow pins to be matched even on subcircuits that did not correctly match; this was done in conjuction with an extra option to the "lvs" command "-noflatten=" to pass a list of cellname to not be flattened even if they do not match. This is generally discouraged, as it prevents netgen from resolving differences between layout and schematic hierarchy, but it can be useful for checking that the hierarchy above a certain cell is correct, given that if a subcell is really unmatched, then its errors will keep propagating up the top level, making additional errors hard to diagnose. --- VERSION | 2 +- base/netcmp.c | 12 +++++-- tcltk/netgen.tcl.in | 79 ++++++++++++++++++++++++++++++++++++++------- tcltk/tclnetgen.c | 25 ++++++++++++-- 4 files changed, 102 insertions(+), 16 deletions(-) diff --git a/VERSION b/VERSION index 8823545..274b8fb 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.5.170 +1.5.171 diff --git a/base/netcmp.c b/base/netcmp.c index 962aa18..6f48f86 100644 --- a/base/netcmp.c +++ b/base/netcmp.c @@ -5363,13 +5363,21 @@ PropertyMatch(struct objlist *ob1, int file1, /* WIP---Check for no-connect pins in merged devices on both sides. */ /* Both sides should either have no-connects marked, or neither. */ /* (Permutable pins may need to be handled correctly. . . */ + for (tp1 = ob1, tp2 = ob2; (tp1 != NULL) && tp1->type >= FIRSTPIN && (tp2 != NULL) && tp2->type >= FIRSTPIN; tp1 = tp1->next, tp2 = tp2->next) { struct objlist *node1, *node2; - node1 = Circuit1->nodename_cache[tp1->node]; - node2 = Circuit2->nodename_cache[tp2->node]; + if (file1 == Circuit1->file) + node1 = Circuit1->nodename_cache[tp1->node]; + else + node1 = Circuit2->nodename_cache[tp1->node]; + + if (file2 == Circuit1->file) + node2 = Circuit1->nodename_cache[tp2->node]; + else + node2 = Circuit2->nodename_cache[tp2->node]; if (node1->instance.flags != node2->instance.flags) { diff --git a/tcltk/netgen.tcl.in b/tcltk/netgen.tcl.in index 431bcf1..e3ac928 100644 --- a/tcltk/netgen.tcl.in +++ b/tcltk/netgen.tcl.in @@ -352,7 +352,7 @@ proc netgen::convert_to_json {filename lvs_final} { close $fjson } -#---------------------------------------------------------------- +#----------------------------------------------------------------------- # Define the "lvs" command as a way of calling the netgen options # for standard compare, essentially the same as the old "netcomp" # standalone program. @@ -361,14 +361,20 @@ proc netgen::convert_to_json {filename lvs_final} { # although if the cells have not been read in yet, then the # original syntax of filename or {filename cellname} is required. # -# "args" is passed to verify and may therefore contain only the -# value "-list" or nothing. If "-list", then output is returned -# as a nested list. -#---------------------------------------------------------------- +# "args" may be "-list", "-json", or "-blackbox". +# "-list" returns output as a nested list. +# "-json" creates a .json-format output file in addition to stdout. +# "-blackbox" treats empty cells as black-box entries. +# "-noflatten={list}" is a list of cells not to flatten if mismatched. +# i.e., the cells are expected to match and any mismatch cannot be +# expected to be resolved by flattening the contents of the mismatched +# cells. +#----------------------------------------------------------------------- proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} { set dolist 0 set dojson 0 + set noflat {} foreach arg $args { if {$arg == "-list"} { puts stdout "Generating list result" @@ -382,6 +388,9 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} { } elseif {$arg == "-blackbox"} { puts stdout "Treating empty subcircuits as black-box cells" netgen::model blackbox on + } elseif {[string first "-noflatten=" $arg] == 0} { + set noflat [string trim [string range $arg 11 end] \"\{\}] + puts stdout "Will not flatten these subcells: $noflat" } } @@ -501,6 +510,7 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} { return } set properr {} + set matcherr {} set pinsgood 0 while {$endval != {}} { if {$dolist == 1} { @@ -529,9 +539,30 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} { # Flatten the non-matching subcircuit (but not the top-level cells) if {[netgen::print queue] != {}} { - netgen::log put " Flattening non-matched subcircuits $endval" - netgen::flatten class "[lindex $endval 0] $fnum1" - netgen::flatten class "[lindex $endval 1] $fnum2" + if {([lsearch $noflat [lindex $endval 0]] == -1) && + ([lsearch $noflat [lindex $endval 1]] == -1)} { + netgen::log put " Flattening non-matched subcircuits $endval" + netgen::flatten class "[lindex $endval 0] $fnum1" + netgen::flatten class "[lindex $endval 1] $fnum2" + } else { + netgen::log put " Continuing with black-boxed subcircuits $endval" + lappend matcherr [lindex $endval 0] + # Match pins + netgen::log echo off + if {$dolist == 1} { + set result [equate -list -force pins "$fnum1 [lindex $endval 0]" \ + "$fnum2 [lindex $endval 1]"] + } else { + set result [equate -force pins "$fnum1 [lindex $endval 0]" \ + "$fnum2 [lindex $endval 1]"] + } + if {$result != 0} { + equate classes "$fnum1 [lindex $endval 0]" \ + "$fnum2 [lindex $endval 1]" + } + set pinsgood $result + netgen::log echo on + } } } else { # Match pins @@ -554,9 +585,32 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} { } else { # Flatten the non-matching subcircuit (but not the top-level cells) if {[netgen::print queue] != {}} { - netgen::log put " Flattening non-matched subcircuits $endval" - netgen::flatten class "[lindex $endval 0] $fnum1" - netgen::flatten class "[lindex $endval 1] $fnum2" + if {([lsearch $noflat [lindex $endval 1]] == -1) && + ([lsearch $noflat [lindex $endval 1]] == -1)} { + netgen::log put " Flattening non-matched subcircuits $endval" + netgen::flatten class "[lindex $endval 0] $fnum1" + netgen::flatten class "[lindex $endval 1] $fnum2" + } else { + netgen::log put " Continuing with black-boxed subcircuits $endval" + lappend matcherr [lindex $endval 0] + netgen::log put " Continuing with black-boxed subcircuits $endval" + lappend matcherr [lindex $endval 0] + # Match pins + netgen::log echo off + if {$dolist == 1} { + set result [equate -list -force pins "$fnum1 [lindex $endval 0]" \ + "$fnum2 [lindex $endval 1]"] + } else { + set result [equate -force pins "$fnum1 [lindex $endval 0]" \ + "$fnum2 [lindex $endval 1]"] + } + if {$result != 0} { + equate classes "$fnum1 [lindex $endval 0]" \ + "$fnum2 [lindex $endval 1]" + } + set pinsgood $result + netgen::log echo on + } } } netgen::log echo off @@ -579,6 +633,9 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} { if {$properr != {}} { netgen::log put "The following cells had property errors: $properr\n" } + if {$matcherr != {}} { + netgen::log put "The following subcells failed to match: $matcherr\n" + } if {$dolog} { netgen::log end } diff --git a/tcltk/tclnetgen.c b/tcltk/tclnetgen.c index e34522f..ccab280 100644 --- a/tcltk/tclnetgen.c +++ b/tcltk/tclnetgen.c @@ -2827,11 +2827,13 @@ _netcmp_equate(ClientData clientData, char *name1 = NULL, *name2 = NULL, *optstart; struct nlist *tp1, *tp2, *SaveC1, *SaveC2; struct objlist *ob1, *ob2; + struct ElementClass *saveEclass = NULL; + struct NodeClass *saveNclass = NULL; int file1, file2; - int i, l1, l2, ltest, lent, dolist = 0; + int i, l1, l2, ltest, lent, dolist = 0, doforce = 0; Tcl_Obj *tobj1, *tobj2, *tobj3; - if (objc > 1) { + while (objc > 1) { optstart = Tcl_GetString(objv[1]); if (*optstart == '-') optstart++; if (!strcmp(optstart, "list")) { @@ -2839,6 +2841,13 @@ _netcmp_equate(ClientData clientData, objv++; objc--; } + else if (!strcmp(optstart, "force")) { + doforce = 1; + objv++; + objc--; + } + else + break; } if ((objc != 2) && (objc != 4) && (objc != 6)) { @@ -2996,6 +3005,12 @@ _netcmp_equate(ClientData clientData, break; case PINS_IDX: + if ((ElementClasses != NULL) && (doforce == TRUE)) { + saveEclass = ElementClasses; + saveNclass = NodeClasses; + ElementClasses = NULL; + NodeClasses = NULL; + } if ((ElementClasses == NULL) && (auto_blackbox == FALSE)) { if (CurrentCell == NULL) { Fprintf(stderr, "Equate elements: no current cell.\n"); @@ -3058,6 +3073,12 @@ _netcmp_equate(ClientData clientData, /* Recover temporarily set global variables (see above) */ Circuit1 = SaveC1; Circuit2 = SaveC2; + + /* Recover ElementClasses if forcing pins on mismatched circuits */ + if (doforce == TRUE) { + ElementClasses = saveEclass; + NodeClasses = saveNclass; + } } break; From d763ad0e60dec5a4d06d336666a874799cedc9e7 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 5 Mar 2021 17:23:22 -0500 Subject: [PATCH 3/4] First and simplest (but most effective) cut at aligning the two sides of the output when presenting side-by-side results. This matches up net or device names within a partition. Where net or device names match, the contents are also aligned on either side. I attempted to also do a "best match" of contents between sides, but as this involves a lot of analyzing the contents, it is very computationally expensive, and so the code has been disabled. It could be added back in as an option. There are also various ways to optimize it for speed. --- base/netcmp.c | 329 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 327 insertions(+), 2 deletions(-) diff --git a/base/netcmp.c b/base/netcmp.c index 6f48f86..3a9050c 100644 --- a/base/netcmp.c +++ b/base/netcmp.c @@ -1141,6 +1141,323 @@ Tcl_Obj *ListElementClasses(int legal) #endif +/* + *--------------------------------------------------------------------- + * + * Sort the fanout lists of two formatted list entries so that they + * are as well aligned as they can be made, practically. The matching + * is ad hoc as it does not affect LVS results but only how the results + * are organized and presented in the output. + * + *--------------------------------------------------------------------- + */ + +void +SortFanoutLists(nlist1, nlist2) + struct FormattedList *nlist1, *nlist2; +{ + struct hashdict f1hash, f2hash; + int f1, f2, total; + struct FanoutList temp; + int *matched; + char pinname[1024], pinnameA[1024], pinnameB[1024]; + + InitializeHashTable(&f1hash, OBJHASHSIZE); + InitializeHashTable(&f2hash, OBJHASHSIZE); + + if (nlist1->fanout < nlist2->fanout) { + matched = CALLOC(nlist2->fanout, sizeof(int)); + total = 0; + + for (f2 = 0; f2 < nlist2->fanout; f2++) { + sprintf(pinname, "%s/%s", nlist2->flist[f2].model, + nlist2->flist[f2].name); + HashPtrInstall(pinname, (void *)(f2 + 1), &f2hash); + } + + for (f1 = 0; f1 < nlist1->fanout; f1++) { + sprintf(pinname, "%s/%s", nlist1->flist[f1].model, + nlist1->flist[f1].name); + f2 = (int)HashLookup(pinname, &f2hash); + if (f2 != 0) { + f2 -= 1; + matched[f1] = -1; + total++; + if (f2 != f1) { + temp = nlist2->flist[f2]; + nlist2->flist[f2] = nlist2->flist[f1]; + nlist2->flist[f1] = temp; + sprintf(pinnameA, "%s/%s", nlist2->flist[f1].model, + nlist2->flist[f1].name); + sprintf(pinnameB, "%s/%s", nlist2->flist[f2].model, + nlist2->flist[f2].name); + HashPtrInstall(pinnameA, (void *)(f1 + 1), &f2hash); + HashPtrInstall(pinnameB, (void *)(f2 + 1), &f2hash); + } + } + } + + /* To do: If full pin names don't match, match by model name only */ + } + else { + matched = CALLOC(nlist1->fanout, sizeof(int)); + total = 0; + + for (f1 = 0; f1 < nlist1->fanout; f1++) { + sprintf(pinname, "%s/%s", nlist1->flist[f1].model, + nlist1->flist[f1].name); + HashPtrInstall(pinname, (void *)(f1 + 1), &f1hash); + } + + for (f2 = 0; f2 < nlist2->fanout; f2++) { + sprintf(pinname, "%s/%s", nlist2->flist[f2].model, + nlist2->flist[f2].name); + f1 = (int)HashLookup(pinname, &f1hash); + if (f1 != 0) { + f1 -= 1; + matched[f2] = -1; + total++; + if (f1 != f2) { + temp = nlist1->flist[f1]; + nlist1->flist[f1] = nlist1->flist[f2]; + nlist1->flist[f2] = temp; + sprintf(pinnameA, "%s/%s", nlist1->flist[f1].model, + nlist1->flist[f1].name); + sprintf(pinnameB, "%s/%s", nlist1->flist[f2].model, + nlist1->flist[f2].name); + HashPtrInstall(pinnameA, (void *)(f1 + 1), &f1hash); + HashPtrInstall(pinnameB, (void *)(f2 + 1), &f1hash); + } + } + } + + /* To do: If full pin names don't match, match by model name only */ + } + + FREE(matched); + HashKill(&f1hash); + HashKill(&f2hash); +} + +/* + *--------------------------------------------------------------------- + * + * Determine the match between two entries in a bad node fragment + * according to an ad hoc metric of how many fanout entries are + * the same between the two. This is not used to match circuits + * for LVS, but is used to sort the dump of unmatched nets generated + * for an unmatched subcell, so that the end-user is not presented + * with a list in a confusingly arbitrary order. + * + * Score is normalized to 100. + * If a model/pin has an equivalent on the other size, add 1 + * If a model/pin equivalent has the same count, add 1 + * Total values and normalize to a 100 score for an exact match. + * + *--------------------------------------------------------------------- + */ + +int +NodeMatchScore(nlist1, nlist2) + struct FormattedList *nlist1, *nlist2; +{ + struct hashdict f1hash, f2hash; + char pinname[1024]; + int f1, f2, maxfanout; + int score = 0; + + InitializeHashTable(&f1hash, OBJHASHSIZE); + InitializeHashTable(&f2hash, OBJHASHSIZE); + + if (nlist1->fanout < nlist2->fanout) { + for (f2 = 0; f2 < nlist2->fanout; f2++) { + sprintf(pinname, "%s/%s", nlist2->flist[f2].model, + nlist2->flist[f2].name); + HashPtrInstall(pinname, (void *)(f2 + 1), &f2hash); + } + + for (f1 = 0; f1 < nlist1->fanout; f1++) { + sprintf(pinname, "%s/%s", nlist1->flist[f1].model, + nlist1->flist[f1].name); + f2 = (int)HashLookup(pinname, &f2hash); + if (f2 != 0) { + f2 -= 1; + score++; + if (nlist1->flist[f1].count == nlist2->flist[f2].count) + score++; + } + } + } + else { + for (f1 = 0; f1 < nlist1->fanout; f1++) { + sprintf(pinname, "%s/%s", nlist1->flist[f1].model, + nlist1->flist[f1].name); + HashPtrInstall(pinname, (void *)(f1 + 1), &f1hash); + } + + for (f2 = 0; f2 < nlist2->fanout; f2++) { + sprintf(pinname, "%s/%s", nlist2->flist[f2].model, + nlist2->flist[f2].name); + f1 = (int)HashLookup(pinname, &f1hash); + if (f1 != 0) { + f1 -= 1; + score++; + if (nlist2->flist[f2].count == nlist1->flist[f1].count) + score++; + } + } + } + + HashKill(&f1hash); + HashKill(&f2hash); + + maxfanout = (nlist1->fanout < nlist2->fanout) ? nlist2->fanout : nlist1->fanout; + score = (50 * score) / maxfanout; + + return score; +} + +/* + *--------------------------------------------------------------------- + * + * Sort node list 2 to match the entries in list 1, to the extent + * possible. Exact name matching is preferred, followed by matching + * of the largest percentage of components. + * + *--------------------------------------------------------------------- + */ + +void SortUnmatchedLists(nlists1, nlists2, n1max, n2max) + struct FormattedList **nlists1, **nlists2; + int n1max, n2max; +{ + struct FormattedList *temp; + int n1, n2; + int *matched, total, best, ibest; + + struct hashdict n1hash, n2hash; + + InitializeHashTable(&n1hash, OBJHASHSIZE); + InitializeHashTable(&n2hash, OBJHASHSIZE); + + if (n1max < n2max) { + matched = CALLOC(n2max, sizeof(int)); + total = 0; + + for (n2 = 0; n2 < n2max; n2++) + HashPtrInstall(nlists2[n2]->name, (void *)(n2 + 1), &n2hash); + + /* Match by name */ + for (n1 = 0; n1 < n1max; n1++) { + n2 = (int)HashLookup(nlists1[n1]->name, &n2hash); + if (n2 != 0) { + n2 -= 1; + matched[n1] = -1; + total++; + if (n2 != n1) { + temp = nlists2[n2]; + nlists2[n2] = nlists2[n1]; + nlists2[n1] = temp; + HashPtrInstall(nlists2[n1]->name, (void *)(n1 + 1), &n2hash); + HashPtrInstall(nlists2[n2]->name, (void *)(n2 + 1), &n2hash); + SortFanoutLists(nlists1[n1], nlists2[n1]); + } + } + } + + /* For all nets that didn't match by name, match by content */ +#if 0 + /* This is ifdef'd out because the improvement in the presentation + * of the output is minimal, but the amount of computation is huge. + * There are numerous ways to optimize this. + */ + if (total < n1max) { + for (n1 = 0; n1 < n1max; n1++) { + if (matched[n1] != -1) { + best = 0; + ibest = -1; + for (n2 = 0; n2 < n2max; n2++) { + if (matched[n2] != -1) { + matched[n2] = NodeMatchScore(nlists1[n1], nlists2[n2]); + if (matched[n2] > best) { + best = matched[n2]; + ibest = n2; + } + } + } + if (ibest >= 0) { + matched[n1] = -1; + temp = nlists2[ibest]; + nlists2[ibest] = nlists2[n1]; + nlists2[n1] = temp; + SortFanoutLists(nlists1[n1], nlists2[n1]); + } + } + } + } +#endif + } + else { + matched = CALLOC(n1max, sizeof(int)); + total = 0; + + for (n1 = 0; n1 < n1max; n1++) + HashPtrInstall(nlists1[n1]->name, (void *)(n1 + 1), &n1hash); + + for (n2 = 0; n2 < n2max; n2++) { + n1 = (int)HashLookup(nlists2[n2]->name, &n1hash); + if (n1 != 0) { + n1 -= 1; + matched[n2] = -1; + total++; + if (n1 != n2) { + temp = nlists1[n1]; + nlists1[n1] = nlists1[n2]; + nlists1[n2] = temp; + HashPtrInstall(nlists1[n1]->name, (void *)(n1 + 1), &n1hash); + HashPtrInstall(nlists1[n2]->name, (void *)(n2 + 1), &n1hash); + SortFanoutLists(nlists2[n2], nlists1[n2]); + } + } + } + /* For all nets that didn't match by name, match by content */ +#if 0 + /* This is ifdef'd out because the improvement in the presentation + * of the output is minimal, but the amount of computation is huge. + * There are numerous ways to optimize this. + */ + if (total < n2max) { + for (n2 = 0; n2 < n2max; n2++) { + if (matched[n2] != -1) { + best = 0; + ibest = -1; + for (n1 = 0; n1 < n1max; n1++) { + if (matched[n1] != -1) { + matched[n1] = NodeMatchScore(nlists2[n2], nlists1[n1]); + if (matched[n1] > best) { + best = matched[n1]; + ibest = n1; + } + } + } + if (ibest >= 0) { + matched[n2] = -1; + temp = nlists1[ibest]; + nlists1[ibest] = nlists1[n2]; + nlists1[n2] = temp; + SortFanoutLists(nlists2[n2], nlists1[n2]); + } + } + } + } +#endif + } + + FREE(matched); + HashKill(&n1hash); + HashKill(&n2hash); +} + /* *--------------------------------------------------------------------- *--------------------------------------------------------------------- @@ -1219,8 +1536,9 @@ void FormatIllegalElementClasses() n2++; } } - Fprintf(stdout, "\n"); + SortUnmatchedLists(elist1, elist2, n1, n2); + 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) = ' '; @@ -1522,6 +1840,12 @@ void FormatIllegalNodeClasses() ostr = CALLOC(right_col_end + 2, sizeof(char)); found = 0; + /* + * To do: match net names across partitions, to make it much clearer how + * two nets are mismatched, when they have been dropped into different + * partitions. + */ + for (nscan = NodeClasses; nscan != NULL; nscan = nscan->next) if (!(nscan->legalpartition)) { struct Node *N; @@ -1574,8 +1898,9 @@ void FormatIllegalNodeClasses() n2++; } } - Fprintf(stdout, "\n"); + SortUnmatchedLists(nlists1, nlists2, n1, n2); + 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) = ' '; From 6b9d92de65cbeb6dd1ec5264ef0c0d5c1b7cbc32 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 5 Mar 2021 20:19:04 -0500 Subject: [PATCH 4/4] Corrected some pointer-to-int and int-to-pointer conversions to keep the compiler happy. --- base/netcmp.c | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/base/netcmp.c b/base/netcmp.c index 3a9050c..d50e05a 100644 --- a/base/netcmp.c +++ b/base/netcmp.c @@ -1166,19 +1166,19 @@ SortFanoutLists(nlist1, nlist2) InitializeHashTable(&f2hash, OBJHASHSIZE); if (nlist1->fanout < nlist2->fanout) { - matched = CALLOC(nlist2->fanout, sizeof(int)); + matched = (int *)CALLOC(nlist2->fanout, sizeof(int)); total = 0; for (f2 = 0; f2 < nlist2->fanout; f2++) { sprintf(pinname, "%s/%s", nlist2->flist[f2].model, nlist2->flist[f2].name); - HashPtrInstall(pinname, (void *)(f2 + 1), &f2hash); + HashPtrInstall(pinname, (void *)((long)f2 + 1), &f2hash); } for (f1 = 0; f1 < nlist1->fanout; f1++) { sprintf(pinname, "%s/%s", nlist1->flist[f1].model, nlist1->flist[f1].name); - f2 = (int)HashLookup(pinname, &f2hash); + f2 = (int)(long)HashLookup(pinname, &f2hash); if (f2 != 0) { f2 -= 1; matched[f1] = -1; @@ -1191,8 +1191,8 @@ SortFanoutLists(nlist1, nlist2) nlist2->flist[f1].name); sprintf(pinnameB, "%s/%s", nlist2->flist[f2].model, nlist2->flist[f2].name); - HashPtrInstall(pinnameA, (void *)(f1 + 1), &f2hash); - HashPtrInstall(pinnameB, (void *)(f2 + 1), &f2hash); + HashPtrInstall(pinnameA, (void *)((long)f1 + 1), &f2hash); + HashPtrInstall(pinnameB, (void *)((long)f2 + 1), &f2hash); } } } @@ -1200,19 +1200,19 @@ SortFanoutLists(nlist1, nlist2) /* To do: If full pin names don't match, match by model name only */ } else { - matched = CALLOC(nlist1->fanout, sizeof(int)); + matched = (int *)CALLOC(nlist1->fanout, sizeof(int)); total = 0; for (f1 = 0; f1 < nlist1->fanout; f1++) { sprintf(pinname, "%s/%s", nlist1->flist[f1].model, nlist1->flist[f1].name); - HashPtrInstall(pinname, (void *)(f1 + 1), &f1hash); + HashPtrInstall(pinname, (void *)((long)f1 + 1), &f1hash); } for (f2 = 0; f2 < nlist2->fanout; f2++) { sprintf(pinname, "%s/%s", nlist2->flist[f2].model, nlist2->flist[f2].name); - f1 = (int)HashLookup(pinname, &f1hash); + f1 = (int)(long)HashLookup(pinname, &f1hash); if (f1 != 0) { f1 -= 1; matched[f2] = -1; @@ -1225,8 +1225,8 @@ SortFanoutLists(nlist1, nlist2) nlist1->flist[f1].name); sprintf(pinnameB, "%s/%s", nlist1->flist[f2].model, nlist1->flist[f2].name); - HashPtrInstall(pinnameA, (void *)(f1 + 1), &f1hash); - HashPtrInstall(pinnameB, (void *)(f2 + 1), &f1hash); + HashPtrInstall(pinnameA, (void *)((long)f1 + 1), &f1hash); + HashPtrInstall(pinnameB, (void *)((long)f2 + 1), &f1hash); } } } @@ -1273,13 +1273,13 @@ NodeMatchScore(nlist1, nlist2) for (f2 = 0; f2 < nlist2->fanout; f2++) { sprintf(pinname, "%s/%s", nlist2->flist[f2].model, nlist2->flist[f2].name); - HashPtrInstall(pinname, (void *)(f2 + 1), &f2hash); + HashPtrInstall(pinname, (void *)((long)f2 + 1), &f2hash); } for (f1 = 0; f1 < nlist1->fanout; f1++) { sprintf(pinname, "%s/%s", nlist1->flist[f1].model, nlist1->flist[f1].name); - f2 = (int)HashLookup(pinname, &f2hash); + f2 = (int)(long)HashLookup(pinname, &f2hash); if (f2 != 0) { f2 -= 1; score++; @@ -1292,13 +1292,13 @@ NodeMatchScore(nlist1, nlist2) for (f1 = 0; f1 < nlist1->fanout; f1++) { sprintf(pinname, "%s/%s", nlist1->flist[f1].model, nlist1->flist[f1].name); - HashPtrInstall(pinname, (void *)(f1 + 1), &f1hash); + HashPtrInstall(pinname, (void *)((long)f1 + 1), &f1hash); } for (f2 = 0; f2 < nlist2->fanout; f2++) { sprintf(pinname, "%s/%s", nlist2->flist[f2].model, nlist2->flist[f2].name); - f1 = (int)HashLookup(pinname, &f1hash); + f1 = (int)(long)HashLookup(pinname, &f1hash); if (f1 != 0) { f1 -= 1; score++; @@ -1341,15 +1341,15 @@ void SortUnmatchedLists(nlists1, nlists2, n1max, n2max) InitializeHashTable(&n2hash, OBJHASHSIZE); if (n1max < n2max) { - matched = CALLOC(n2max, sizeof(int)); + matched = (int *)CALLOC(n2max, sizeof(int)); total = 0; for (n2 = 0; n2 < n2max; n2++) - HashPtrInstall(nlists2[n2]->name, (void *)(n2 + 1), &n2hash); + HashPtrInstall(nlists2[n2]->name, (void *)((long)n2 + 1), &n2hash); /* Match by name */ for (n1 = 0; n1 < n1max; n1++) { - n2 = (int)HashLookup(nlists1[n1]->name, &n2hash); + n2 = (int)(long)HashLookup(nlists1[n1]->name, &n2hash); if (n2 != 0) { n2 -= 1; matched[n1] = -1; @@ -1358,8 +1358,8 @@ void SortUnmatchedLists(nlists1, nlists2, n1max, n2max) temp = nlists2[n2]; nlists2[n2] = nlists2[n1]; nlists2[n1] = temp; - HashPtrInstall(nlists2[n1]->name, (void *)(n1 + 1), &n2hash); - HashPtrInstall(nlists2[n2]->name, (void *)(n2 + 1), &n2hash); + HashPtrInstall(nlists2[n1]->name, (void *)((long)n1 + 1), &n2hash); + HashPtrInstall(nlists2[n2]->name, (void *)((long)n2 + 1), &n2hash); SortFanoutLists(nlists1[n1], nlists2[n1]); } } @@ -1398,14 +1398,14 @@ void SortUnmatchedLists(nlists1, nlists2, n1max, n2max) #endif } else { - matched = CALLOC(n1max, sizeof(int)); + matched = (int *)CALLOC(n1max, sizeof(int)); total = 0; for (n1 = 0; n1 < n1max; n1++) - HashPtrInstall(nlists1[n1]->name, (void *)(n1 + 1), &n1hash); + HashPtrInstall(nlists1[n1]->name, (void *)((long)n1 + 1), &n1hash); for (n2 = 0; n2 < n2max; n2++) { - n1 = (int)HashLookup(nlists2[n2]->name, &n1hash); + n1 = (int)(long)HashLookup(nlists2[n2]->name, &n1hash); if (n1 != 0) { n1 -= 1; matched[n2] = -1; @@ -1414,8 +1414,8 @@ void SortUnmatchedLists(nlists1, nlists2, n1max, n2max) temp = nlists1[n1]; nlists1[n1] = nlists1[n2]; nlists1[n2] = temp; - HashPtrInstall(nlists1[n1]->name, (void *)(n1 + 1), &n1hash); - HashPtrInstall(nlists1[n2]->name, (void *)(n2 + 1), &n1hash); + HashPtrInstall(nlists1[n1]->name, (void *)((long)n1 + 1), &n1hash); + HashPtrInstall(nlists1[n2]->name, (void *)((long)n2 + 1), &n1hash); SortFanoutLists(nlists2[n2], nlists1[n2]); } }