diff --git a/base/flatten.c b/base/flatten.c index c9b3784..3859cf0 100644 --- a/base/flatten.c +++ b/base/flatten.c @@ -1230,6 +1230,10 @@ int CleanupPins(char *name, int filenum) return 0; } + // If cell is type MODULE, this is a black-box circuit and + // pins are expected to be disconnected (so don't remove them). + if (ThisCell->class == CLASS_MODULE) return 0; + // Avoid a loop through all cells unless we have to do it. for (ob = ThisCell->cell; ob != NULL; ob = ob->next) { diff --git a/base/netcmp.c b/base/netcmp.c index ca774ab..d34b952 100644 --- a/base/netcmp.c +++ b/base/netcmp.c @@ -6274,6 +6274,7 @@ struct nlist *addproxies(struct hashlist *p, void *clientdata) int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist) { char *cover, *ctemp; + char *bangptr1, *bangptr2; struct objlist *ob1, *ob2, *obn, *obp, *ob1s, *ob2s, *obt; struct NodeClass *NC; struct Node *N1, *N2; @@ -6486,13 +6487,25 @@ 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) */ + /* (Semi-hack: Allow "!" global flag) */ 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) { if (!IsPort(ob2)) break; + + bangptr2 = strrchr(ob2->name, '!'); + if (bangptr2 && (*(bangptr2 + 1) == '\0')) + *bangptr2 = '\0'; + else bangptr2 = NULL; + if ((*matchfunc)(ob1->name, ob2->name)) { ob2->model.port = i; /* save order */ *(cover + i) = (char)1; @@ -6521,11 +6534,13 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist) } #endif } + if (bangptr2) *bangptr2 = '!'; j++; } } ob1 = ob1->next; } + if (bangptr1) *bangptr1 = '!'; /* Find the end of the pin list in tc1, for adding proxy pins */ @@ -6709,7 +6724,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist) /* Clean up "UNKNOWN" records from Circuit1 */ - for (obn = tc1->cell; ; obn = obn->next) { + for (obn = tc1->cell; obn; obn = obn->next) { if (obn->type == UNKNOWN) obn->type = PORT; else if (obn->type != PORT) break; } @@ -6728,13 +6743,13 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist) /* Clean up "UNKNOWN" records from Circuit2 */ - for (obn = tc2->cell; ; obn = obn->next) { + for (obn = tc2->cell; obn; obn = obn->next) { if (obn->type == UNKNOWN) obn->type = PORT; else if (obn->type != PORT) break; } /* Check for ports that did not get ordered */ - for (obn = tc2->cell; obn->type == PORT; obn = obn->next) { + for (obn = tc2->cell; obn && (obn->type == PORT); obn = obn->next) { if (obn->model.port == -1) { if (obn->node == -1) { // This only happens when pins have become separated from any net. diff --git a/base/spice.c b/base/spice.c index f82f861..4168c5d 100644 --- a/base/spice.c +++ b/base/spice.c @@ -626,7 +626,7 @@ void ReadSpiceFile(char *fname, int filenum, struct cellstack **CellStackPtr, } SpiceTokNoNewline(); } - SetClass((blackbox) ? CLASS_MODULE : CLASS_SUBCKT); + SetClass((blackbox) ? CLASS_MODULE : CLASS_SUBCKT); if (hasports == 0) { // If the cell defines no ports, then create a proxy diff --git a/tcltk/netgen.tcl.in b/tcltk/netgen.tcl.in index bd721a5..03ba378 100644 --- a/tcltk/netgen.tcl.in +++ b/tcltk/netgen.tcl.in @@ -370,7 +370,6 @@ proc netgen::convert_to_json {filename lvs_final} { proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} { set dolist 0 set dojson 0 - puts stdout "Diagnostic version" foreach arg $args { if {$arg == "-list"} { puts stdout "Generating list result" diff --git a/tcltk/tclnetgen.c b/tcltk/tclnetgen.c index ae0e562..3a23036 100644 --- a/tcltk/tclnetgen.c +++ b/tcltk/tclnetgen.c @@ -1676,6 +1676,13 @@ _netgen_model(ClientData clientData, retclass = modelclasses[SUBCKT_IDX]; break; + case CLASS_MODULE: + if (auto_blackbox) + retclass = modelclasses[BLACKBOX_IDX]; + else + retclass = modelclasses[MODULE_IDX]; + break; + default: /* (includes case CLASS_UNDEF) */ retclass = modelclasses[UNDEF_IDX]; break; @@ -2713,10 +2720,10 @@ _netcmp_equate(ClientData clientData, }; int result, index; char *name1 = NULL, *name2 = NULL, *optstart; - struct nlist *tp1, *tp2; + struct nlist *tp1, *tp2, *SaveC1, *SaveC2; struct objlist *ob1, *ob2; int file1, file2; - int i, l1, l2, ltest, lent, dolist; + int i, l1, l2, ltest, lent, dolist = 0; Tcl_Obj *tobj1, *tobj2, *tobj3; if (objc > 1) { @@ -2884,7 +2891,7 @@ _netcmp_equate(ClientData clientData, break; case PINS_IDX: - if (ElementClasses == NULL) { + if ((ElementClasses == NULL) && (auto_blackbox == FALSE)) { if (CurrentCell == NULL) Fprintf(stderr, "Equate elements: no current cell.\n"); Fprintf(stderr, "Equate pins: cell %s and/or %s has no elements.\n", @@ -2892,20 +2899,30 @@ _netcmp_equate(ClientData clientData, Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0)); return TCL_OK; } - if (tp1 == Circuit1 && tp2 == Circuit2) { - int result; - if (MatchPins(tp1, tp2, dolist)) { - Fprintf(stdout, "Cell pin lists are equivalent.\n"); - Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1)); - } - else { - Fprintf(stdout, "Cell pin lists for %s and %s altered to match.\n", - name1, name2); - Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0)); - } + else if (ElementClasses == NULL) { + /* This has been called outside of a netlist compare, */ + /* probably to force name matching of pins on black-box */ + /* devices. But MatchPins only works if tp1 == Circuit1 */ + /* and tp2 == Circuit2, so preserve these values and */ + /* recover afterward (what a hack). */ + SaveC1 = Circuit1; + SaveC2 = Circuit2; + Circuit1 = tp1; + Circuit2 = tp2; + } + if (MatchPins(tp1, tp2, dolist)) { + Fprintf(stdout, "Cell pin lists are equivalent.\n"); + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1)); } else { - Fprintf(stderr, "Function not defined outside of LVS scope.\n"); + Fprintf(stdout, "Cell pin lists for %s and %s altered to match.\n", + name1, name2); + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0)); + } + if (ElementClasses == NULL) { + /* Recover temporarily set global variables (see above) */ + Circuit1 = SaveC1; + Circuit2 = SaveC2; } break;