Compare commits

..
6 Commits
Author SHA1 Message Date
Tim Edwards d9425163e1 Merge branch 'master' into netgen-1.5 2022-09-18 02:00:02 -04:00
Tim Edwards f02e2b1ee0 Handled backslash-escapes (convert "\" to "\\") when writing pins
to the JSON format file (since JSON does not allow single backslash
characters.  Previously nets had been handled correctly, but not
pins.  Resolves github issue tracker Issue #60 from Proppy.
2022-09-17 14:33:27 -04:00
Tim Edwards 9ba1dfe814 Merge branch 'master' into netgen-1.5 2022-09-17 02:00:02 -04:00
Tim Edwards cc5f6d929f Added a missing block of code from Mitch Bailey's version that
fails to handle a topology match with a pin mismatch situation.
2022-09-16 13:55:23 -04:00
Tim Edwards fadd0ae2fc Merge branch 'master' into netgen-1.5 2022-09-16 02:00:02 -04:00
Tim Edwards 4fa4d046c8 Part 2 of folding in Mitch Bailey's code. This part is a
significant overhaul of the MatchPins() code, and better handles
issues with pins disconnected from nets and removes cases in
which proxy pins are incorrectly generated.
2022-09-15 10:50:52 -04:00
4 changed files with 217 additions and 334 deletions
+1 -1
View File
@@ -1 +1 @@
1.5.229
1.5.232
+202 -329
View File
@@ -7250,20 +7250,23 @@ struct nlist *addproxies(struct hashlist *p, void *clientdata)
/* Return codes: */
/* 2: Neither cell had pins, so matching is unnecessary */
/* 1: Exact match */
/* 0: Inexact match resolved by proxy pin insertion. */
/* 0: Circuit match w/pin name mismatch. Force a match. */
/* -1: Pin mismatch. Flatten cell. */
/*--------------------------------------------------------------*/
int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
{
char *cover, *ctemp;
char *cover1, *cover2, *ctemp;
char *bangptr1, *bangptr2, *backslashptr1, *backslashptr2;
struct objlist *ob1, *ob2, *obn, *obp, *ob1s, *ob2s, *obt;
struct NodeClass *NC;
struct Node *N1, *N2;
int i, j, k, m, a, b, swapped, numnodes, numorig;
int i, j, k, m, a, b, swapped, numnodes, numnodes2, numorig;
int result = 1, haspins = 0, notempty = 0;
int hasproxy1 = 0, hasproxy2 = 0;
int needclean1 = 0, needclean2 = 0;
int hasDevices1, hasDevices2;
int isBlackBox1, isBlackBox2;
char *ostr;
#ifdef TCL_NETGEN
Tcl_Obj *mlist, *plist1, *plist2;
@@ -7272,10 +7275,12 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
if (tc1 == NULL) tc1 = Circuit1;
if (tc2 == NULL) tc2 = Circuit2;
numnodes2 = 0;
for (ob2 = tc2->cell; ob2 != NULL; ob2 = ob2->next) {
if (ob2->type != PORT) break;
else haspins = 1;
ob2->model.port = -1;
numnodes2++;
}
numnodes = 0;
for (ob1 = tc1->cell; ob1 != NULL; ob1 = ob1->next) {
@@ -7290,7 +7295,8 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
return 2;
}
cover = (char *)CALLOC(numnodes, sizeof(char));
cover1 = (char *)CALLOC(numnodes, sizeof(char));
cover2 = (char *)CALLOC(numnodes2, sizeof(char));
numorig = numnodes;
#ifdef TCL_NETGEN
@@ -7323,194 +7329,159 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
}
for (NC = NodeClasses; NC != NULL; NC = NC->next) {
a = 0;
a = 0; // circuit1 node offset
for (N1 = NC->nodes; N1 != NULL; N1 = N1->next) {
if (N1->graph == Circuit1->file) {
obn = N1->object;
b = 0; // circuit2 node offset
for (N2 = NC->nodes; N2 != NULL; N2 = N2->next) {
if (N2->graph != Circuit1->file) {
if (b == a) break;
else b++;
}
}
if (N2 == NULL) { // This should never occur in matched nets
continue;
}
else {
obp = N2->object;
}
ob1 = NULL;
if (IsPort(obn)) {
i = 0;
for (ob1 = tc1->cell; ob1 != NULL; ob1 = ob1->next, i++) {
if ((IsPort(ob1)) && (ob1->node == obn->node)) {
b = 0;
for (N2 = NC->nodes; N2 != NULL; N2 = N2->next) {
if (N2->graph != Circuit1->file) {
if (b == a) break;
else b++;
}
}
if (N2 == NULL) {
#ifdef TCL_NETGEN
if (dolist) {
Tcl_SetVar2Ex(netgeninterp, "lvs_out", NULL,
Tcl_NewStringObj("pins", -1),
TCL_APPEND_VALUE | TCL_LIST_ELEMENT);
Tcl_SetVar2Ex(netgeninterp, "lvs_out", NULL, mlist,
TCL_APPEND_VALUE | TCL_LIST_ELEMENT);
}
#endif
FREE(ostr);
return 1;
}
obp = N2->object;
j = 0;
for (ob2 = tc2->cell; ob2 != NULL; ob2 = ob2->next, j++) {
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);
if ((*matchfunc)(ob1->name, ob2->name))
snprintf(ostr + left_col_end + 1, left_col_end, "%s", ob2->name);
else {
/* Check remainder of ports to see if there is a name match on the
* same net number (multiple ports tied to the same net)
*/
struct objlist *ob3;
for (ob3 = ob2->next, ++j; ob3 != NULL; ob3 = ob3->next, j++) {
if ((IsPort(ob3)) && (ob3->node == ob2->node)) {
if ((*matchfunc)(ob3->name, ob1->name)) {
ob2 = ob3;
snprintf(ostr + left_col_end + 1, left_col_end, "%s", ob2->name);
break;
}
}
else {
ob3 = NULL;
break; /* All pins w/the same node should be together */
}
}
if (ob3 == NULL) {
if (ob2->model.port == -1)
snprintf(ostr + left_col_end + 1, left_col_end, "%s **Mismatch**", ob2->name);
else
snprintf(ostr + left_col_end + 1, left_col_end, "(no matching pin)");
/* Pins with different names are on different nets,
* so this should trigger an error return code.
*/
result = 0;
}
}
for (m = 0; m < right_col_end + 1; m++)
if (*(ostr + m) == '\0') *(ostr + m) = ' ';
Fprintf(stdout, ostr);
}
else {
Fprintf(stdout, "Circuit %s port %d \"%s\""
" = cell %s port %d \"%s\"\n",
tc1->name, i, obn->name,
tc2->name, j, obp->name);
}
#ifdef TCL_NETGEN
if (dolist) {
Tcl_ListObjAppendElement(netgeninterp, plist1,
Tcl_NewStringObj(obn->name, -1));
Tcl_ListObjAppendElement(netgeninterp, plist2,
Tcl_NewStringObj(obp->name, -1));
}
#endif
ob2->model.port = i; /* save order */
*(cover + i) = (char)1;
/* If there are multiple pins on the same net, cycle through them; */
/* otherwise, move to the next entry in the partition. */
if (ob1->next && (ob1->next->type == PORT) && (ob1->next->node == ob1->node)) {
ob1 = ob1->next;
ob2 = tc2->cell; /* Restart search for matching pin */
i++;
}
else
break;
}
}
if (ob2 == NULL) {
if (Debug == 0) {
// If first cell has no pins but 2nd cell
// does, then "no matching pin" entries will
// be generated for all pins in the 2nd cell,
// 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);
}
}
else {
Fprintf(stderr, "No matching pin in cell %s for "
"cell %s pin %s\n",
tc2->name, tc1->name, obn->name);
}
#ifdef TCL_NETGEN
if (dolist && strcmp(obn->name, "(no pins)")) {
Tcl_ListObjAppendElement(netgeninterp, plist1,
Tcl_NewStringObj(obn->name, -1));
Tcl_ListObjAppendElement(netgeninterp, plist2,
Tcl_NewStringObj("(no matching pin)", -1));
}
#endif
result = 0;
/* Make a pass through circuit 1 to find out if */
/* the pin really is connected to anything, or */
/* has been left orphaned after flattening. If */
/* disconnected, set its node number to -2. */
notempty = 0;
for (obt = ob1->next; obt; obt = obt->next) {
if (obt->type >= FIRSTPIN) {
notempty = 1;
if (obt->node == ob1->node)
break;
}
}
if ((obt == NULL) && (notempty == 1)) {
ob1->node = -2; // Will run this through cleanuppins
needclean1 = 1;
}
}
if ((IsPort(ob1)) && (*matchfunc)(ob1->name, obn->name)) {
break;
}
}
*(cover1 + i) = (char)1;
}
ob2 = NULL;
if (obp && IsPort(obp)) {
j = 0;
for (ob2 = tc2->cell; ob2 != NULL; ob2 = ob2->next, j++) {
if ((IsPort(ob2)) && (*matchfunc)(ob2->name, obp->name)) {
break;
}
}
*(cover2 + j) = (char)1;
}
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) = ' ';
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) = ' ';
if (ob1 && ob2) { // both pins are in both circuits
if (NC->legalpartition) { // nets match
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);
if ((*matchfunc)(obn->name, obp->name))
/* MatchPins - case 1: portA(0) = portA(1)
* Pin names match
*/
snprintf(ostr + left_col_end + 1, left_col_end,
"%s", obp->name);
else {
/* MatchPins - case 2: portA(0) = portb(1)
* circuits match but the pin names don't.
*/
snprintf(ostr + left_col_end + 1, left_col_end,
"%s **Mismatch**", obp->name);
/* Pins with different names are on different nets,
* so this should trigger an error return code.
*/
result = (result == 1) ? 0 : result; // only set if 1
}
ob2->model.port = i; /* save the order */
}
else {
Fprintf(stderr, "No netlist match for cell %s pin %s\n",
tc1->name, obn->name);
snprintf(ostr, left_col_end, "*%s", obn->name);
snprintf(ostr + left_col_end + 1, left_col_end,
"*%s **Mismatch**", obp->name);
for (m = 0; m < right_col_end + 1; m++)
if (*(ostr + m) == '\0') *(ostr + m) = ' ';
result = -1;
}
#ifdef TCL_NETGEN
if (dolist) {
Tcl_ListObjAppendElement(netgeninterp, plist1,
Tcl_NewStringObj(obn->name, -1));
Tcl_ListObjAppendElement(netgeninterp, plist2,
Tcl_NewStringObj("(no matching pin)", -1));
}
else if (ob1) { // implies (&& !ob2)
/* MatchPins - case 3: portA(0) = netA(1)
* circuits match but circuit2 is missing pin
*/
snprintf(ostr, left_col_end, "%s", obn->name);
if (NC->legalpartition) { // net match
snprintf(ostr + left_col_end + 1, left_col_end,
"*%s **not a pin**", obp->name);
}
#endif
result = 0;
else {
snprintf(ostr + left_col_end + 1, left_col_end,
"*%s **Mismatch**", obp->name);
}
result = -1;
}
else if (ob2) { // imples (&& !ob1)
/* MatchPins - case 4: netA(0) = portA(1)
* circuits match but circuit1 is missing pin
*/
if (NC->legalpartition) { // net match
snprintf(ostr, left_col_end, "*%s **not pin**", obn->name);
}
else {
snprintf(ostr, left_col_end, "*%s **Mismatch**", obn->name);
}
snprintf(ostr + left_col_end + 1, left_col_end, "%s", obp->name);
result = -1;
}
if (ob1 || ob2) {
for (m = 0; m < right_col_end + 1; m++)
if (*(ostr + m) == '\0') *(ostr + m) = ' ';
Fprintf(stdout, ostr);
}
}
else {
Fprintf(stdout, "Circuit %s port %d \"%s\""
" = cell %s port %d \"%s\"\n",
tc1->name, i, (obn) ? obn->name : "",
tc2->name, j, (obp) ? obp->name : "");
}
#ifdef TCL_NETGEN
if (dolist) {
Tcl_ListObjAppendElement(netgeninterp, plist1,
Tcl_NewStringObj((obn) ? obn->name : "", -1));
Tcl_ListObjAppendElement(netgeninterp, plist2,
Tcl_NewStringObj((obp) ? obp->name : "", -1));
}
#endif
a++;
}
}
}
/* Check for unconnected nodes in tc1 */
for (ob1 = tc1->cell; ob1 && IsPort(ob1); ob1 = ob1->next) {
if (ob1->node >= 0) {
/* Check if ob1->node might really be disconnected */
for (obn = ob1->next; obn; obn = obn->next) {
if (obn->node == ob1->node) break;
}
if (obn == NULL) ob1->node = -1; // Make disconnected
}
}
/* Check for unconnected nodes in tc2 */
for (ob2 = tc2->cell; ob2 && IsPort(ob2); ob2 = ob2->next) {
if (ob2->node >= 0) {
/* Check if ob2->node might really be disconnected */
for (obp = ob2->next; obp; obp = obp->next) {
if (obp->node == ob2->node) break;
}
if (obp == NULL) ob2->node = -1; // Make disconnected
}
}
/* Do any unmatched pins have the same name? */
/* This should not happen if unconnected pins are eliminated */
/* so apply only to black-box (CELL_PLACEHOLDER) entries. */
/* (Semi-hack: Allow "!" global flag) */
/* (Semi-hack: Allow "!" global flag) */
/* (Another semi-hack: Ignore the leading backslash in */
/* backslash-escaped verilog names. Removing the backslash */
/* and ending space character is a common way to convert to */
@@ -7518,7 +7489,11 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
ob1 = tc1->cell;
isBlackBox1 = (tc1->flags & CELL_PLACEHOLDER);
isBlackBox2 = (tc2->flags & CELL_PLACEHOLDER);
for (i = 0; i < numorig; i++) {
bangptr1 = strrchr(ob1->name, '!');
if (bangptr1 && (*(bangptr1 + 1) == '\0'))
*bangptr1 = '\0';
@@ -7526,12 +7501,13 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
backslashptr1 = (*(ob1->name) == '\\') ? ob1->name + 1 : ob1->name;
if (*(cover + i) == (char)0) {
if (*(cover1 + i) == (char)0) {
j = 0;
for (ob2 = tc2->cell; ob2 != NULL; ob2 = ob2->next) {
for (ob2 = tc2->cell; ob2 != NULL; ob2 = ob2->next, j++) {
char *name1, *name2;
if (!IsPort(ob2)) break;
if (*(cover2 + j) == (char)1) continue; // port was processed
bangptr2 = strrchr(ob2->name, '!');
if (bangptr2 && (*(bangptr2 + 1) == '\0'))
@@ -7555,18 +7531,23 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
/* matched by name. */
if (((ob1->node == -1) && (ob2->node == -1)) ||
(((tc1->flags & CELL_PLACEHOLDER) &&
(tc2->flags & CELL_PLACEHOLDER)) ||
(NodeClasses == NULL))) {
(isBlackBox1 && isBlackBox2) ||
(NodeClasses == NULL)) {
ob2->model.port = i; /* save order */
*(cover + i) = (char)1;
*(cover1 + i) = (char)1;
*(cover2 + j) = (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);
snprintf(ostr, left_col_end, "%s%s", ob1->name,
(ob1->node == -1 && !isBlackBox1) ?
" (disconnected)" : "");
snprintf(ostr + left_col_end + 1, left_col_end,
"%s%s", ob2->name,
(ob2->node == -1 && !isBlackBox2) ?
" (disconnected)" : "");
for (m = 0; m < right_col_end + 1; m++)
if (*(ostr + m) == '\0') *(ostr + m) = ' ';
Fprintf(stdout, ostr);
@@ -7590,7 +7571,6 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
}
}
if (bangptr2) *bangptr2 = '!';
j++;
}
}
ob1 = ob1->next;
@@ -7609,8 +7589,9 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
/* connections in the cell to the end. Create pins */
/* in tc1 to match. */
for (ob2 = tc2->cell; ob2 != NULL; ob2 = ob2->next) {
for (j = 0, ob2 = tc2->cell; ob2 != NULL; j++, ob2 = ob2->next) {
if (ob2->type != PORT) break;
if (*(cover2 + j) == (char)1) continue; // port was processed
if (ob2->model.port == -1) {
if (Debug == 0) {
@@ -7618,8 +7599,10 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
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);
snprintf(ostr, left_col_end, "**no match**");
snprintf(ostr + left_col_end + 1, left_col_end,
"%s%s", ob2->name,
(ob2->node == -1) ? " (disconnected)" : "");
for (m = 0; m < right_col_end + 1; m++)
if (*(ostr + m) == '\0') *(ostr + m) = ' ';
Fprintf(stdout, ostr);
@@ -7630,80 +7613,12 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
tc2->name, ob2->name);
}
/* Before making a proxy pin, check to see if */
/* flattening instances has left a port with a */
/* net number that doesn't connect to anything */
notempty = 0;
for (obt = ob2->next; obt; obt = obt->next) {
if (obt->type >= FIRSTPIN) {
notempty = 1;
if (obt->node == ob2->node)
break;
}
}
if ((obt == NULL) && (notempty == 1)) {
ob2->node = -2; // Will run this through cleanuppins
needclean2 = 1;
/* On the top level, missing pins are an error, even if */
/* they appear to match unconnected pins on the other side. */
if (CompareQueue == NULL)
result = 0;
#ifdef TCL_NETGEN
if (dolist) {
Tcl_ListObjAppendElement(netgeninterp, plist1,
Tcl_NewStringObj("(no pin)", -1));
Tcl_ListObjAppendElement(netgeninterp, plist2,
Tcl_NewStringObj(ob2->name, -1));
}
#endif
continue;
}
else if (notempty == 1) {
/* Flag this as an error */
result = 0;
#ifdef TCL_NETGEN
if (dolist) {
Tcl_ListObjAppendElement(netgeninterp, plist1,
Tcl_NewStringObj("(no matching pin)", -1));
Tcl_ListObjAppendElement(netgeninterp, plist2,
Tcl_NewStringObj(ob2->name, -1));
}
#endif
}
ob2->model.port = numnodes++; // Assign a port order
/* Add a proxy pin to tc1 */
/* Technically, this should have a matching net number. */
/* But nothing connects to it, so it is only needed to */
/* make sure the "pin magic" numbers are correctly */
/* assigned to both cells. */
obn = (struct objlist *)CALLOC(1, sizeof(struct objlist));
obn->name = (char *)MALLOC(6 + strlen(ob2->name));
sprintf(obn->name, "proxy%s", ob2->name);
obn->type = UNKNOWN;
// obn->model.port = -1;
obn->instance.name = NULL;
obn->node = -1;
if (ob1 == tc1->cell) {
obn->next = ob1;
tc1->cell = obn;
}
else {
obn->next = ob1->next;
ob1->next = obn;
}
ob1 = obn;
hasproxy1 = 1;
HashPtrInstall(obn->name, obn, &(tc1->objdict));
result = -1;
}
}
/* Find the end of the pin list in tc2, for adding proxy pins */
/* Find the end of the pin list in tc2 */
for (ob2 = tc2->cell; ob2 != NULL; ob2 = ob2->next) {
if (ob2 && ((ob2->next && ob2->next->type != PORT) || ob2->next == NULL))
@@ -7716,97 +7631,55 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
/* sequence, then fill in the missing numbers. Otherwise, add the */
/* extra nodes to the end. */
j = 0;
for (i = 0; i < numorig; i++) {
if (*(cover + i) == (char)1) continue;
for (i = 0, ob1 = tc1->cell; i < numorig; i++, ob1 = ob1->next) {
if (*(cover1 + i) == (char)1) continue;
/* If the equivalent node in tc1 is not disconnected */
/* (node != -1) then we should report a match error, */
/* although this does not necessarily imply an error in */
/* netlist connectivity. */
ob1 = tc1->cell;
for (k = i; k > 0 && ob1 != NULL; k--)
ob1 = ob1->next;
if (ob1 == NULL || ob1->type != PORT || ob1->node >= 0) {
/* Check if ob1->node might really be disconnected */
for (obn = ob1->next; obn; obn = obn->next) {
if (obn->node == ob1->node) break;
/* 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%s", ob1->name,
(ob1->node == -1) ? " (disconnected)" : "");
snprintf(ostr + left_col_end + 1, left_col_end, "**no match**");
for (m = 0; m < right_col_end + 1; m++)
if (*(ostr + m) == '\0') *(ostr + m) = ' ';
Fprintf(stdout, ostr);
}
if (obn == NULL) ob1->node = -1; /* Make disconnected */
result = -1;
}
if (ob1 == NULL || ob1->type != PORT || ob1->node >= 0
|| (ob1->node < 0 && tc1->class == CLASS_MODULE)
|| (ob1->node < 0 && ob1->model.port == -1)) {
/* Add a proxy pin to tc2 */
obn = (struct objlist *)CALLOC(1, sizeof(struct objlist));
if (ob1 == NULL) {
obn->name = (char *)MALLOC(15);
sprintf(obn->name, "proxy%d", rand() & 0x3ffffff);
}
else {
obn->name = (char *)MALLOC(6 + strlen(ob1->name));
sprintf(obn->name, "proxy%s", ob1->name);
}
obn->type = UNKNOWN;
obn->model.port = (i - j);
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;
}
else {
obn->next = ob2->next;
ob2->next = obn;
}
ob2 = obn;
hasproxy2 = 1;
HashPtrInstall(obn->name, obn, &(tc2->objdict));
}
else if (ob1 != NULL && ob1->type == PORT) {
/* Disconnected node was not meaningful, has no pin match in */
/* the compared circuit, and so should be discarded. */
ob1->node = -2;
needclean1 = 1;
/* Adjust numbering around removed node */
for (ob2s = tc2->cell; ob2s != NULL && ob2s->type == PORT; ob2s = ob2s->next) {
if (ob2s->model.port > (i - j)) ob2s->model.port--;
}
j++;
else {
Fprintf(stderr, "No netlist match for cell %s pin %s\n",
tc1->name, ob1->name);
}
}
FREE(cover);
FREE(cover1);
FREE(cover2);
if (Debug == 0) {
for (i = 0; i < right_col_end; i++) *(ostr + i) = '-';
Fprintf(stdout, ostr);
}
hasDevices1 = hasDevices2 = 0;
for (ob1 = tc1->cell; ob1 != NULL; ob1 = ob1->next) {
if (ob1->type == FIRSTPIN) {
hasDevices1 = 1;
break;
}
}
for (ob2 = tc2->cell; ob2 != NULL; ob2 = ob2->next) {
if (ob2->type == FIRSTPIN) {
hasDevices2 = 1;
break;
}
}
if (hasDevices1 != hasDevices2)
result = -2; // Attempt to compare empty cell to non-empty cell
if (result < 0) return result;
/* Run cleanuppins on circuit 1 */
if (needclean1) {
CleanupPins(tc1->name, tc1->file);
+6 -4
View File
@@ -62,16 +62,18 @@ proc netgen::convert_to_json {filename lvs_final} {
puts $fjson " \["
set cktval [lindex $value 0]
foreach pin [lrange $cktval 0 end-1] {
puts $fjson " \"$pin\","
set pinstr [string map {"\\" "\\\\"} $pin]
puts $fjson " \"$pinstr\","
}
set pin [lindex $cktval end]
set pin [string map {"\\" "\\\\"} [lindex $cktval end]]
puts $fjson " \"$pin\""
puts $fjson " \], \["
set cktval [lindex $value 1]
foreach pin [lrange $cktval 0 end-1] {
puts $fjson " \"$pin\","
set pinstr [string map {"\\" "\\\\"} $pin]
puts $fjson " \"$pinstr\","
}
set pin [lindex $cktval end]
set pin [string map {"\\" "\\\\"} [lindex $cktval end]]
puts $fjson " \"$pin\""
puts $fjson " \]"
if {$kidx == $nkeys} {
+8
View File
@@ -2650,6 +2650,14 @@ _netcmp_verify(ClientData clientData,
else
Fprintf(stdout, "Netlists do not match.\n");
}
else if (automorphisms == -2) {
if (index == EQUIV_IDX)
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1));
else if (index == UNIQUE_IDX)
Tcl_SetObjResult(interp, Tcl_NewIntObj(-2));
else if (index > 0)
Fprintf(stdout, "Circuits match uniquely with port errors.\n");
}
else {
if (automorphisms) {
if (index == EQUIV_IDX)