Compare commits

...
10 Commits
Author SHA1 Message Date
Tim Edwards 9b84776374 Merge branch 'master' into netgen-1.5 2022-10-26 02:00:01 -04:00
Tim Edwards 06386bee1b Corrected an issue with "flatten": If a cell has disconnected ports,
then flattening instances of that cell can cause a port of the parent
cell connected to the disconnected port of the child cell to itself
become disconnected.  If the parent port is not changed to show the
disconnected state, then pin mismatch can occur if the netlist being
matched didn't have the same flattened subcell.  This condition is
now detected and handled correctly.
2022-10-25 20:14:44 -04:00
Tim Edwards 2af3f2a3f7 Merge branch 'master' into netgen-1.5 2022-10-25 02:00:01 -04:00
Tim Edwards 7cd8d82964 Fix for an error causing a segfault. This does not fix the
underlying issue (which needs to be investigated), but it does
prevent netgen from crashing when it encounters it (netgen will
generate an erro message instead).
2022-10-24 21:45:14 -04:00
Tim Edwards 738abbdad9 Merge branch 'master' into netgen-1.5 2022-10-01 02:00:01 -04:00
Tim Edwards 3aeea9d164 Re-applied the modifications of revisions 231 and 232, and updated
the version to revision 234.
2022-09-30 11:47:36 -04:00
Tim Edwards 12e1ff295f Revert "Part 2 of folding in Mitch Bailey's code. This part is a"
This reverts commit 4fa4d046c8.

Reverting back to before the major change to MatchPins(), which is
breaking existing LVS scripts.
2022-09-30 11:36:09 -04:00
Tim Edwards 8d7569e9a3 Merge branch 'master' into netgen-1.5 2022-09-24 02:00:02 -04:00
Tim Edwards 2f9e898ec6 Version updated along with the merge of pull request #62 from
Mitch Bailey.
2022-09-23 16:04:49 -04:00
D. Mitch Bailey 9663579dd0 Restore matching circuits if one is empty (but only if pins match). 2022-09-21 08:05:39 -07:00
4 changed files with 380 additions and 207 deletions
+1 -1
View File
@@ -1 +1 @@
1.5.232
1.5.236
+41
View File
@@ -243,6 +243,13 @@ void flattenCell(char *name, int file)
ThisCell->dumped = 1; /* indicate cell has been flattened */
}
/* Structure used to keep track of nodes needing checking */
struct linkednode {
int node;
struct linkednode *next;
};
/*--------------------------------------------------------------*/
/* flattenInstancesOf -- */
/* */
@@ -265,6 +272,7 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
struct nlist *ThisCell;
struct nlist *ChildCell;
struct objlist *tmp, *ob2, *ob3;
struct linkednode *checknodes = NULL, *newlnode, *chknode;
int notdone, rnodenum;
char tmpstr[1024];
int nextnode, oldmax, numflat = 0;
@@ -416,6 +424,16 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
}
UpdateNodeNumbers(ChildStart, tmp->node, ob2->node);
}
else if (tmp->node == -1) {
/* Opposite case: If child port is an unconnected node, then */
/* removing the instance may make the parent node become */
/* unconnected. For now, just record the node number. At the */
/* end we'll check if these nodes are actually disconnected. */
newlnode = (struct linkednode *)MALLOC(sizeof(struct linkednode));
newlnode->node = ob2->node;
newlnode->next = checknodes;
checknodes = newlnode;
}
/* in pathological cases, the lengths of the port lists may
* change. This is an error, but that is no reason to allow
@@ -598,6 +616,29 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
NextObj = ParentParams;
} /* repeat until no more instances found */
}
/* Check nodes that may have become disconnected after child flattening */
while (checknodes != NULL) {
struct objlist *portnode = NULL;
chknode = checknodes;
checknodes = checknodes->next;
for (ob3 = ThisCell->cell; ob3; ob3 = ob3->next) {
if ((ob3->type != PORT) && (portnode == NULL))
break;
else if ((ob3->type == PORT) && (ob3->node == chknode->node))
portnode = ob3;
else if ((ob3->type >= FIRSTPIN) && (ob3->node == chknode->node))
break;
}
if ((ob3 == NULL) && (portnode != NULL)) {
/* Port became disconnected when child was flattened */
portnode->node = -1;
}
FREE(chknode);
}
CacheNodeNames(ThisCell);
ThisCell->dumped = 1; /* indicate cell has been flattened */
return numflat;
+336 -204
View File
@@ -5005,6 +5005,11 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
// find ith record in ob
p = 0;
for (ob2 = ob; p != i; ob2 = ob2->next, p++);
/* Sanity check */
if (ob2->type != PROPERTY) {
Fprintf(stderr, "Incorrect property run count!\n");
continue;
}
// Count entries, add one, reallocate
for (p = 0;; p++) {
vl = &ob2->instance.props[p];
@@ -7250,23 +7255,20 @@ struct nlist *addproxies(struct hashlist *p, void *clientdata)
/* Return codes: */
/* 2: Neither cell had pins, so matching is unnecessary */
/* 1: Exact match */
/* 0: Circuit match w/pin name mismatch. Force a match. */
/* -1: Pin mismatch. Flatten cell. */
/* 0: Inexact match resolved by proxy pin insertion. */
/*--------------------------------------------------------------*/
int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
{
char *cover1, *cover2, *ctemp;
char *cover, *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, numnodes2, numorig;
int i, j, k, m, a, b, swapped, numnodes, 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;
@@ -7275,12 +7277,10 @@ 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) {
@@ -7295,8 +7295,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
return 2;
}
cover1 = (char *)CALLOC(numnodes, sizeof(char));
cover2 = (char *)CALLOC(numnodes2, sizeof(char));
cover = (char *)CALLOC(numnodes, sizeof(char));
numorig = numnodes;
#ifdef TCL_NETGEN
@@ -7329,159 +7328,194 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
}
for (NC = NodeClasses; NC != NULL; NC = NC->next) {
a = 0; // circuit1 node offset
a = 0;
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)) && (*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 (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);
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
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;
}
ob2->model.port = i; /* save the order */
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;
}
}
break;
}
else {
snprintf(ostr, left_col_end, "*%s", obn->name);
snprintf(ostr + left_col_end + 1, left_col_end,
"*%s **Mismatch**", obp->name);
}
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) = ' ';
result = -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);
Fprintf(stdout, ostr);
}
else {
snprintf(ostr + left_col_end + 1, left_col_end,
"*%s **Mismatch**", obp->name);
Fprintf(stderr, "No netlist match for cell %s pin %s\n",
tc1->name, obn->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));
}
if (dolist) {
Tcl_ListObjAppendElement(netgeninterp, plist1,
Tcl_NewStringObj(obn->name, -1));
Tcl_ListObjAppendElement(netgeninterp, plist2,
Tcl_NewStringObj("(no matching pin)", -1));
}
#endif
result = 0;
}
}
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 */
@@ -7489,11 +7523,7 @@ 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';
@@ -7501,13 +7531,12 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
backslashptr1 = (*(ob1->name) == '\\') ? ob1->name + 1 : ob1->name;
if (*(cover1 + i) == (char)0) {
if (*(cover + i) == (char)0) {
j = 0;
for (ob2 = tc2->cell; ob2 != NULL; ob2 = ob2->next, j++) {
for (ob2 = tc2->cell; ob2 != NULL; ob2 = ob2->next) {
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'))
@@ -7531,23 +7560,18 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
/* matched by name. */
if (((ob1->node == -1) && (ob2->node == -1)) ||
(isBlackBox1 && isBlackBox2) ||
(NodeClasses == NULL)) {
(((tc1->flags & CELL_PLACEHOLDER) &&
(tc2->flags & CELL_PLACEHOLDER)) ||
(NodeClasses == NULL))) {
ob2->model.port = i; /* save order */
*(cover1 + i) = (char)1;
*(cover2 + j) = (char)1;
*(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%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)" : "");
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);
@@ -7571,6 +7595,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
}
}
if (bangptr2) *bangptr2 = '!';
j++;
}
}
ob1 = ob1->next;
@@ -7589,9 +7614,8 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
/* connections in the cell to the end. Create pins */
/* in tc1 to match. */
for (j = 0, ob2 = tc2->cell; ob2 != NULL; j++, ob2 = ob2->next) {
for (ob2 = tc2->cell; ob2 != NULL; 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) {
@@ -7599,10 +7623,8 @@ 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 match**");
snprintf(ostr + left_col_end + 1, left_col_end,
"%s%s", ob2->name,
(ob2->node == -1) ? " (disconnected)" : "");
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);
@@ -7613,12 +7635,80 @@ 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
result = -1;
/* 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));
}
}
/* Find the end of the pin list in tc2 */
/* Find the end of the pin list in tc2, for adding proxy pins */
for (ob2 = tc2->cell; ob2 != NULL; ob2 = ob2->next) {
if (ob2 && ((ob2->next && ob2->next->type != PORT) || ob2->next == NULL))
@@ -7631,55 +7721,97 @@ 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. */
for (i = 0, ob1 = tc1->cell; i < numorig; i++, ob1 = ob1->next) {
if (*(cover1 + i) == (char)1) continue;
j = 0;
for (i = 0; i < numorig; i++) {
if (*(cover + i) == (char)1) continue;
/* 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 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;
}
result = -1;
if (obn == NULL) ob1->node = -1; /* Make disconnected */
}
else {
Fprintf(stderr, "No netlist match for cell %s pin %s\n",
tc1->name, ob1->name);
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++;
}
}
FREE(cover1);
FREE(cover2);
FREE(cover);
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);
+2 -2
View File
@@ -62,7 +62,7 @@ proc netgen::convert_to_json {filename lvs_final} {
puts $fjson " \["
set cktval [lindex $value 0]
foreach pin [lrange $cktval 0 end-1] {
set pinstr [string map {"\\" "\\\\"} $pin]
set pinstr [string map {"\\" "\\\\"} $pin]
puts $fjson " \"$pinstr\","
}
set pin [string map {"\\" "\\\\"} [lindex $cktval end]]
@@ -70,7 +70,7 @@ proc netgen::convert_to_json {filename lvs_final} {
puts $fjson " \], \["
set cktval [lindex $value 1]
foreach pin [lrange $cktval 0 end-1] {
set pinstr [string map {"\\" "\\\\"} $pin]
set pinstr [string map {"\\" "\\\\"} $pin]
puts $fjson " \"$pinstr\","
}
set pin [string map {"\\" "\\\\"} [lindex $cktval end]]