diff --git a/VERSION b/VERSION index 9fe136c..960ac53 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.5.182 +1.5.183 diff --git a/base/netcmp.c b/base/netcmp.c index ed94313..be933b8 100644 --- a/base/netcmp.c +++ b/base/netcmp.c @@ -7240,71 +7240,74 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist) } } - /* Do any unmatched pins have the same name? */ - /* (This should not happen if unconnected pins are eliminated) */ + /* 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) */ - ob1 = tc1->cell; - bangptr1 = strrchr(ob1->name, '!'); - if (bangptr1 && (*(bangptr1 + 1) == '\0')) - *bangptr1 = '\0'; - else bangptr1 = NULL; + if ((tc1->flags & CELL_PLACEHOLDER) && (tc2->flags & CELL_PLACEHOLDER)) { + ob1 = tc1->cell; + bangptr1 = strrchr(ob1->name, '!'); + if (bangptr1 && (*(bangptr1 + 1) == '\0')) + *bangptr1 = '\0'; + else bangptr1 = NULL; - for (i = 0; i < numorig; i++) { - if (*(cover + i) == (char)0) { - j = 0; - for (ob2 = tc2->cell; ob2 != NULL; ob2 = ob2->next) { - char *name1, *name2; + for (i = 0; i < numorig; i++) { + if (*(cover + i) == (char)0) { + j = 0; + for (ob2 = tc2->cell; ob2 != NULL; ob2 = ob2->next) { + char *name1, *name2; - if (!IsPort(ob2)) break; + if (!IsPort(ob2)) break; - bangptr2 = strrchr(ob2->name, '!'); - if (bangptr2 && (*(bangptr2 + 1) == '\0')) - *bangptr2 = '\0'; - else bangptr2 = NULL; + bangptr2 = strrchr(ob2->name, '!'); + if (bangptr2 && (*(bangptr2 + 1) == '\0')) + *bangptr2 = '\0'; + else bangptr2 = NULL; - name1 = ob1->name; - name2 = ob2->name; + name1 = ob1->name; + name2 = ob2->name; - /* Recognize proxy pins as matching */ - if (!strncmp(name1, "proxy", 5)) name1 +=5; - if (!strncmp(name2, "proxy", 5)) name2 +=5; + /* Recognize proxy pins as matching */ + if (!strncmp(name1, "proxy", 5)) name1 +=5; + if (!strncmp(name2, "proxy", 5)) name2 +=5; - if ((*matchfunc)(name1, name2)) { - ob2->model.port = i; /* save order */ - *(cover + i) = (char)1; + if ((*matchfunc)(name1, name2)) { + ob2->model.port = i; /* save order */ + *(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); - } - else { - Fprintf(stdout, "Circuit %s port %d \"%s\"" + 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); + } + else { + Fprintf(stdout, "Circuit %s port %d \"%s\"" " = cell %s port %d \"%s\"\n", tc1->name, i, ob1->name, tc2->name, j, ob2->name); - } + } #ifdef TCL_NETGEN - if (dolist) { - Tcl_ListObjAppendElement(netgeninterp, plist1, + if (dolist) { + Tcl_ListObjAppendElement(netgeninterp, plist1, Tcl_NewStringObj(ob1->name, -1)); - Tcl_ListObjAppendElement(netgeninterp, plist2, + Tcl_ListObjAppendElement(netgeninterp, plist2, Tcl_NewStringObj(ob2->name, -1)); - } + } #endif + } + if (bangptr2) *bangptr2 = '!'; + j++; } - if (bangptr2) *bangptr2 = '!'; - j++; - } + } + ob1 = ob1->next; } - ob1 = ob1->next; + if (bangptr1) *bangptr1 = '!'; } - if (bangptr1) *bangptr1 = '!'; /* Find the end of the pin list in tc1, for adding proxy pins */ diff --git a/base/verilog.c b/base/verilog.c index 8e2a802..92dfbd1 100644 --- a/base/verilog.c +++ b/base/verilog.c @@ -63,6 +63,10 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define VLOG_PIN_NAME_DELIMITERS "X///**/(**)X()" #define VLOG_PIN_CHECK_DELIMITERS "X///**/(**)X,;(){}" +// Used by portelement structure "flags" record. +#define PORT_NOT_FOUND 0 +#define PORT_FOUND 1 + // Global storage for verilog parameters struct hashdict verilogparams; // Global storage for verilog definitions @@ -1404,6 +1408,7 @@ skip_endmodule: char *name; // Name of port in subcell char *net; // Name of net connecting to port in the parent int width; // Width of port, if port is a bus + char flags; // Used for marking if port was added into netlist struct portelement *next; }; @@ -1530,6 +1535,7 @@ nextinst: new_port = (struct portelement *)CALLOC(1, sizeof(struct portelement)); new_port->name = strsave(nexttok + 1); new_port->width = -1; + new_port->flags = PORT_NOT_FOUND; SkipTokComments(VLOG_DELIMITERS); if (!match(nexttok, "(")) { Printf("Badly formed subcircuit pin line at \"%s\"\n", nexttok); @@ -1964,6 +1970,7 @@ nextinst: obpinidx = -1; while (scan != NULL) { if (match(obpinname, scan->name)) { + scan->flags |= PORT_FOUND; break; } scan = scan->next; @@ -2056,6 +2063,89 @@ nextinst: if (LookupObject(scan->net, CurrentCell) == NULL) Node(scan->net); join(scan->net, obptr->name); } + + /* Before exiting the loop, check if all ports in the */ + /* scan list were handled. */ + + if ((obptr->next == NULL) || (obptr->next->type <= FIRSTPIN)) { + for (scan = head; scan; scan = scan->next) { + if (!(scan->flags & PORT_FOUND)) { + if (tp->flags & CELL_PLACEHOLDER) { + char tempname[128]; + int maxnode; + + /* This pin was probably implicit in the first call */ + /* and so it needs to be added to the definition. */ + + ReopenCellDef(modulename, filenum); + Port(scan->name); + ReopenCellDef((*CellStackPtr)->cellname, filenum); + + /* obptr->next now gets the new port. Update the */ + /* port number, and copy class and instance name. */ + nobj = GetObject(); + sprintf(tempname, "%s%s%s", obptr->instance.name, + SEPARATOR, scan->name); + nobj->name = strsave(tempname); + nobj->model.class = strsave(obptr->model.class); + nobj->instance.name = strsave(obptr->instance.name); + nobj->type = obptr->type + 1; + nobj->next = obptr->next; + nobj->node = -1; + obptr->next = nobj; + HashPtrInstall(nobj->name, nobj, &(CurrentCell->objdict)); + + if (LookupObject(scan->net, CurrentCell) == NULL) + Node(scan->net); + join(scan->net, nobj->name); + scan->flags |= PORT_FOUND; + + /* Now any previous instance of the same cell must */ + /* insert the same additional pin as a no-connect. */ + /* NOTE: This should be running a callback on all */ + /* cells in the file, not just CurrentCell. */ + + for (sobj = CurrentCell->cell; sobj && (sobj != obptr); + sobj = sobj->next) { + if (sobj->type == FIRSTPIN) { + if (match(sobj->model.class, obptr->model.class)) { + while (sobj->next->type > FIRSTPIN) + sobj = sobj->next; + /* Stop when reaching the current instance */ + if (sobj->type == obptr->type + 1) break; + nobj = GetObject(); + sprintf(tempname, "%s%s%s", sobj->instance.name, + SEPARATOR, scan->name); + nobj->name = strsave(tempname); + nobj->model.class = strsave(sobj->model.class); + nobj->instance.name = strsave(sobj->instance.name); + nobj->type = obptr->type + 1; + nobj->node = -1; + nobj->next = sobj->next; + sobj->next = nobj; + HashPtrInstall(nobj->name, nobj, + &(CurrentCell->objdict)); + + sprintf(tempname, "_noconnect_%d_", localcount++); + Node(tempname); + join(tempname, nobj->name); + Fprintf(stderr, "Note: Implicit pin %s in instance " + "%s of %s in cell %s\n", + scan->name, sobj->instance.name, + modulename, CurrentCell->name); + } + } + } + } + else { + Fprintf(stderr, "Error: Instance %s has pin %s which is " + "not in the %s cell definition.\n", + locinst, scan->name, modulename); + } + } + } + } + obptr = obptr->next; } while (obptr != NULL && obptr->type > FIRSTPIN); }