From d69fbc23bbabf87e62e09840d0c4d69b04b87339 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Sat, 3 Feb 2024 21:21:09 -0500 Subject: [PATCH] Added code to handle the problem in which a verilog netlist is read before its component cells, and the component cells are read in as SPICE netlists. Then the original verilog cell and its instances need to have pins reordered to match the subcircuit definition in the SPICE netlist. Otherwise, when verilog and SPICE netlists are mixed, the order in which the files are read is critical, and failures due to reading out-of-order are very obscure and nearly impossible to debug. --- VERSION | 2 +- base/netcmp.c | 7 ++++- base/spice.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 82 insertions(+), 8 deletions(-) diff --git a/VERSION b/VERSION index b5e75ec..54f6bb2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.5.266 +1.5.267 diff --git a/base/netcmp.c b/base/netcmp.c index 299fc72..eee161a 100644 --- a/base/netcmp.c +++ b/base/netcmp.c @@ -7473,6 +7473,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist) int hasproxy1 = 0, hasproxy2 = 0; int needclean1 = 0, needclean2 = 0; int nomatch = 0; + int filenum = -1; int *correspond; char *ostr; #ifdef TCL_NETGEN @@ -8150,7 +8151,11 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist) /* Reorder pins in Circuit2 instances to match Circuit1 */ - RecurseCellFileHashTable(reorderpins, Circuit2->file); + if (Circuit2 != NULL) + filenum = Circuit2->file; + else + filenum = tc2->file; + RecurseCellFileHashTable(reorderpins, filenum); /* Reorder pins in Circuit2 cell to match Circuit1 */ /* Unlike the instance records, the structures are swapped, */ diff --git a/base/spice.c b/base/spice.c index e888bd5..ff09d24 100644 --- a/base/spice.c +++ b/base/spice.c @@ -43,6 +43,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "print.h" #include "query.h" #include "objlist.h" +#include "netcmp.h" // Global storage for parameters from .PARAM struct hashdict spiceparams; @@ -519,7 +520,7 @@ void ReadSpiceFile(char *fname, int filenum, struct cellstack **CellStackPtr, char *eqptr, devtype, in_subckt; struct keyvalue *kvlist = NULL; char inst[MAX_STR_LEN], model[MAX_STR_LEN], instname[MAX_STR_LEN]; - struct nlist *tp; + struct nlist *tp, *tpsave; struct objlist *parent, *sobj, *nobj, *lobj, *pobj; inst[MAX_STR_LEN-1] = '\0'; @@ -557,6 +558,7 @@ void ReadSpiceFile(char *fname, int filenum, struct cellstack **CellStackPtr, snprintf(model, MAX_STR_LEN-1, "%s", nexttok); tp = LookupCellFile(nexttok, filenum); + tpsave = NULL; /* Check for name conflict with duplicate cell names */ /* This may mean that the cell was used before it was */ @@ -595,11 +597,46 @@ void ReadSpiceFile(char *fname, int filenum, struct cellstack **CellStackPtr, tp = LookupCellFile(nexttok, filenum); } else if (tp != NULL) { /* Make a new definition for an empty cell */ - FreePorts(nexttok); - CellDelete(nexttok, filenum); /* This removes any PLACEHOLDER flag */ - CellDef(model, filenum); - tp = LookupCellFile(model, filenum); - update = 1; /* Will need to update existing instances */ + /* Handle issue with SPICE read after verilog, where a placeholder + * was created from the verilog. (1) If the pin names are "1", "2", + * "3", then this is a SPICE placeholder, and just remove the CellDef + * and re-create it. Otherwise, create new cell "_PLACEHOLDER_". + * (2) After encountering .ends, run MatchPins between the two cells. + * (3) delete the original cell and rename the new cell. + */ + int i = 1; + char pname[10]; + for (pobj = tp->cell; pobj && pobj->type == PORT; pobj = pobj->next) { + sprintf(pname, "%d", i); + if (!matchnocase(pobj->name, pname)) break; + i++; + } + if ((pobj == NULL) || (pobj->type != PORT)) { + /* This is a SPICE placeholder created because the cell was instanced + * before it was defined. However, the pins can be assumed to be in + * the correct order, and pin reordering does not need to be done. + */ + FreePorts(nexttok); + CellDelete(nexttok, filenum); /* This removes any PLACEHOLDER flag */ + CellDef(model, filenum); + tp = LookupCellFile(model, filenum); + update = 1; /* Will need to update existing instances */ + } + else { + /* This is (probably) a verilog placeholder created because the + * verilog was read before the (SPICE) definitions. The verilog + * netlist should have named the pins of the parent cell. However, + * there is no guarantee the order of pins is correct. The MatchPins() + * routine from netcmp.c can be used here to match the cell against + * the placeholder, and reorder the pins in all instances to match. + * Note that we cannot just reorder the SPICE pins to match the + * verilog order, because there may be other SPICE netlists which + * instance the cell with the correct SPICE port order. + */ + tpsave = tp; + CellDef("_PLACEHOLDER_", filenum); + tp = LookupCellFile("_PLACEHOLDER_", filenum); + } } else if (tp == NULL) { /* Completely new cell, no name conflict */ CellDef(model, filenum); @@ -691,6 +728,38 @@ skip_ends: if (*CellStackPtr) PopStack(CellStackPtr); if (*CellStackPtr) ReopenCellDef((*CellStackPtr)->cellname, filenum); SkipNewLine(NULL); + + if (tpsave != NULL) { + struct nlist *tpplace; + char *savename; + + /* Handle a placeholder from a verilog file that has been replaced + * by a netlist with pins in a different order. The pins need to + * be matched, corrected in the original cell and all instances, + * and the new cell deleted. + */ + + Printf("Verilog placeholder %s replaced by SPICE definition\n", + tpsave->name); + tpplace = LookupCellFile("_PLACEHOLDER_", filenum); + /* MatchPins is part of netcmp and normally Circuit2 is the + * circuit being matched, so set Circuit2 to the original + * verilog black-box cell, and MatchPins() will force its + * pins to be rearranged to match the SPICE definition just + * read. + */ + Circuit2 = tpsave; + MatchPins(tpplace, tpsave, 0); + savename = strsave(tpsave->name); + /* Now the original verilog black-box cell can be removed */ + FreePorts(savename); + CellDelete(savename, filenum); + /* And _PLACEHOLDER_ is renamed to the original name of the cell. */ + CellRehash("_PLACEHOLDER_", savename, filenum); + tpsave = NULL; + Circuit2 = NULL; + FREE(savename); + } } else if (matchnocase(nexttok, ".MODEL")) { unsigned char class = CLASS_SUBCKT;