Compare commits

..
43 Commits
Author SHA1 Message Date
Tim Edwards 41939adb84 Merge branch 'master' into work 2017-06-20 22:55:26 -04:00
Tim Edwards 39573981be Update at Tue Jun 20 22:55:24 EDT 2017 by tim 2017-06-20 22:55:24 -04:00
Tim Edwards b9e26f6fce Implemented better black-box handling. Netlist with "stub" entries
for subcircuits (.subckt ... .ends pair with cellname and pin names
and pin order, but no contents) are automatically treated as black-
box circuits if found and if the "-blackbox" option is passed to the
"lvs" (scripted) command.  The "equate pins" command can be used
outside of a comparison to force two circuits (black-box or
otherwise) to be matched by pin name (if not a black-box circuit,
then this is a provisional name match, as a circuit comparison will
order based on connectivity first, not pin names).  So two sets of
black-box circuit libraries can be used as long as their pin names
match.  One hack added to ignore the "!" at the end of global names
when comparing pin names for matching.  Otherwise, pin names must
compare by case-insensitive string match.
2017-06-20 22:50:31 -04:00
Tim Edwards 78779ce2e9 Corrected the "property parallel none" command option so that it
gets applied properly to all existing cells (as well as all
future cells, but normally the former is applicable in a setup
file for LVS).
2017-06-19 22:22:08 -04:00
Tim Edwards 70bb33cc62 Finally reworked "cells" command behavior into something
consistent.
2017-06-19 21:04:33 -04:00
Tim Edwards fdf2f32654 Fixed the "cells -all" command so that it now matches the
documentation, and behaves as intended, which is that "-all" is
not a standalone option but is itself an optional qualifier to
the "cells <valid_cellname>" command.  So the options are
"cells <valid_cellname>" and "cells -all <valid_cellname>".
2017-06-19 20:22:59 -04:00
Tim Edwards 05d4225e97 New command option "model blackbox on|off" makes "readnet spice"
treat empty subcircuits as blackbox cells automatically without
requiring specific callse to "model <cell> blackbox" for each.
Enabled in LVS script by giving option "-blackbox" at the end
of the LVS command.
2017-06-19 17:41:31 -04:00
Tim Edwards b6218699a9 Merge branch 'master' into work 2017-06-19 12:39:02 -04:00
Tim Edwards d7927ef547 Update at Mon Jun 19 12:39:00 EDT 2017 by tim 2017-06-19 12:39:00 -04:00
Tim Edwards af7bc39bbf Added tilde expansion handling for .INCLUDE statements to the
SPICE netlist read routine.
2017-06-19 12:38:27 -04:00
Tim Edwards 5cd68b9ef1 Merge branch 'master' into work 2017-06-18 22:48:13 -04:00
Tim Edwards 07788e7501 Update at Sun Jun 18 22:48:11 EDT 2017 by tim 2017-06-18 22:48:11 -04:00
Tim Edwards 24cc7d0c94 Update to add "property parallel none" command option. 2017-06-18 22:47:51 -04:00
Tim Edwards dbcd36d3ec Merge branch 'master' into work 2017-05-15 16:31:03 -04:00
Tim Edwards 25c17abb70 Update at Mon May 15 16:31:00 EDT 2017 by tim 2017-05-15 16:31:00 -04:00
Tim Edwards fd019b4afd Corrected the same error as a few commits back that causes a message
about property errors to show up, not due to property errors, but
due to proxy pins being inserted in the middle of a device record.
However, the first one was fixed for the case of proxy pins being
added to circuit 1, but the same fix was not made for the opposite
case of proxy pins being added to circuit 2.  This commit corrects
that omission.
2017-05-15 16:29:12 -04:00
Tim Edwards cdfd74bac4 Removed old comment from code referring to the development state. 2017-05-08 21:00:43 -04:00
Tim Edwards dd9e02c5f3 Merge branch 'master' into work 2017-05-08 20:57:01 -04:00
Tim Edwards 26cd16f3ff Update at Mon May 8 20:56:58 EDT 2017 by tim 2017-05-08 20:56:58 -04:00
Tim Edwards ccdd47bc0b Corrected rare case where a cell that is flattened is the first
instance in a cell, and is empty, and causes the cell contents
to be nulled out.
2017-05-08 20:55:58 -04:00
Tim Edwards ace1c28507 Corrected an error placing proxy pins after the first pin of the
first object if the (presumably top-level) cell has no pins
(top-level cells not in a subcircuit definition satisfy this
condition).
2017-05-05 21:08:09 -04:00
Tim Edwards 5e9635e05f Merge branch 'master' into work 2017-05-05 17:36:32 -04:00
Tim Edwards 5c168946e3 Update at Fri May 5 17:36:29 EDT 2017 by tim 2017-05-05 17:36:29 -04:00
Tim Edwards 1471f0c09f Corrected error in combining property records of serial devices. 2017-05-05 17:35:57 -04:00
Tim Edwards 73b81fcfe3 Merge branch 'master' into work 2017-04-25 08:47:58 -04:00
Tim Edwards b083a6df7c Update at Tue Apr 25 08:47:57 EDT 2017 by tim 2017-04-25 08:47:57 -04:00
Tim Edwards 2b5a96500c Corrected the .gitignore file, which was apparently missed when
version 1.5 was first created in git.
2017-04-25 08:47:33 -04:00
Tim Edwards 66f94b47e6 Merge branch 'master' into work 2017-03-06 14:01:26 -05:00
Tim Edwards 09532ee628 Update at Mon Mar 6 14:01:25 EST 2017 by tim 2017-03-06 14:01:25 -05:00
Tim Edwards 2b7d416a41 A few corrections to the JSON format output. 2017-03-06 14:01:14 -05:00
Tim Edwards 090e9e122a Merge branch 'master' into work 2017-03-03 09:11:54 -05:00
Tim Edwards 67f1c1a2e9 Update at Fri Mar 3 09:11:52 EST 2017 by tim 2017-03-03 09:11:52 -05:00
Tim Edwards a7dcb4ef45 Corrected new JSON file output format from netgen. 2017-03-03 09:11:30 -05:00
Tim Edwards a0f1b4cc92 Merge branch 'master' into work 2017-02-27 09:36:54 -05:00
Tim Edwards b5d5496e40 Update at Mon Feb 27 09:36:52 EST 2017 by tim 2017-02-27 09:36:52 -05:00
Tim Edwards 7cac67c81b Corrected an error in the property match subroutine that was failing
to stop at the end of an instance record without properties, leading
to strange errors where netgen declares "There were property errors"
but does not print any errors (because there aren't any).
2017-02-27 09:35:18 -05:00
Tim Edwards ede7406b08 Merge branch 'master' into work 2017-02-08 15:17:01 -05:00
Tim Edwards 516d1c33fb Update at Wed Feb 8 15:16:59 EST 2017 by tim 2017-02-08 15:16:59 -05:00
Tim Edwards 0ad5730701 Corrected an error where snprintf() was not used when printing
formatted side-by-side output, causing a crash for names that
exceed the 40-column limit.
2017-02-08 15:16:24 -05:00
Tim Edwards 24d98ff0d3 Removed backup file for netgen.tcl.in, and made corrections for
the output JSON format, which was incorrect when some entries
were empty.
2017-01-09 17:06:23 -05:00
Tim Edwards 092c99dc1b Merge branch 'master' into work 2017-01-09 12:53:00 -05:00
Tim Edwards 4659b0795d Update at Mon Jan 9 12:52:59 EST 2017 by tim 2017-01-09 12:52:59 -05:00
Tim Edwards b1924bff65 Finished implementing the Tcl list output format, and added a
routine to convert the list output format to a JSON output file,
for easy readback, parsing, and display using python.
2017-01-09 12:51:31 -05:00
11 changed files with 796 additions and 249 deletions
+11 -10
View File
@@ -1,12 +1,13 @@
*.*%
*.cdslck
.inca.db.*
inca.*.pak
*.swp
*.log
netgen
netgenexec
defs.mak
Depend
config.cache
config.log
config.status
*.o
*.so
*~
*/av_extracted*/
.nfs*
*.cd-
*/mommdl/
*.log
UPDATE_ME
VERSION
+6 -5
View File
@@ -1,15 +1,14 @@
TO_DO list for version 1.5
------------------------------
1) Parallel (transistors and capacitors) and serial (resistors)
device merging, plus methods for describing how any device
class may be merged.
As of version 1.5.70, the major to-do item list is complete.
Possible useful additions (not critical)
----------------------
1) Add new output style allowing netlists to be described by Tcl scripts
(similar to the C-Code format, but does not require compiling).
(similar to the C-Code format, but does not require compiling) (this
was done in 1.5.72, but now needs some scripts to make use of it.)
2) Add automatic file format guessing from file extension for "write" command
3) Add Tk GUI to match (and improve upon!) the original X11 GUI.
4) Incorporate into Tcl-based xcircuit
@@ -33,5 +32,7 @@ Possible useful additions (not critical)
ntk and ext formats, SPICE format writing, and sim format reading).
11) Add a "property" command to add/remove properties to check, and change
the slop values (done).
12) Add a "subcircuit" command to mimic a SPICE ".SUBCKT ... .ENDS" card.
12) Add a "subcircuit" command to mimic a SPICE ".SUBCKT ... .ENDS" card
(i.e., the ability to add subcircuit "stub" definitions from the
command line or from a setup file).
+1 -1
View File
@@ -1 +1 @@
1.5.70
1.5.82
+25 -15
View File
@@ -486,24 +486,30 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
}
/* splice instance out of parent */
if (ParentParams == ThisCell->cell) {
/* ParentParams are the very first thing in the list */
ThisCell->cell = ChildObjList;
for (ob2 = ChildObjList; ob2 && ob2->next != NULL; ob2 = ob2->next) ;
if ((ParentParams == ThisCell->cell) && (ChildObjList == NULL)) {
ThisCell->cell = ob2; /* Child cell was empty */
tmp = ob2;
}
else {
/* find ParentParams in ThisCell list */
for (ob2 = ThisCell->cell; ob2 && ob2->next != ParentParams; ob2=ob2->next);
if (ob2)
for (ob2->next = ChildObjList; ob2->next != NULL; ob2 = ob2->next) ;
}
/* now, ob2 is last element in child list, so skip and reclaim parent */
if (ParentParams == ThisCell->cell) {
/* ParentParams are the very first thing in the list */
ThisCell->cell = ChildObjList;
for (ob2 = ChildObjList; ob2 && ob2->next != NULL; ob2 = ob2->next) ;
}
else {
/* find ParentParams in ThisCell list */
for (ob2 = ThisCell->cell; ob2 && ob2->next != ParentParams; ob2=ob2->next);
if (ob2)
for (ob2->next = ChildObjList; ob2->next != NULL; ob2 = ob2->next) ;
}
/* now, ob2 is last element in child list, so skip and reclaim parent */
tmp = ParentParams;
do {
tmp = tmp->next;
} while ((tmp != NULL) && ((tmp->type > FIRSTPIN) || (tmp->type == PROPERTY)));
if (ob2) ob2->next = tmp;
tmp = ParentParams;
do {
tmp = tmp->next;
} while ((tmp != NULL) && ((tmp->type > FIRSTPIN) || (tmp->type == PROPERTY)));
if (ob2) ob2->next = tmp;
}
while (ParentParams != tmp) {
ob2 = ParentParams->next;
FreeObjectAndHash(ParentParams, ThisCell);
@@ -1224,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) {
+203 -133
View File
@@ -998,15 +998,17 @@ Tcl_Obj *ListElementClasses(int legal)
int numlists1, numlists2, n1, n2, n, f1, f2, i, maxf;
char *estr;
Tcl_Obj *dobj, *lobj, *e1obj, *e2obj, *sobj, *gobj;
Tcl_Obj *lobj, *c1obj, *c2obj, *e1obj, *e2obj, *sobj;
Tcl_Obj *g1obj, *g2obj, *dobj;
lobj = Tcl_NewListObj(0, NULL);
dobj = Tcl_NewListObj(0, NULL);
for (escan = ElementClasses; escan != NULL; escan = escan->next) {
if (legal == escan->legalpartition) {
struct Element *E;
e1obj = Tcl_NewListObj(0, NULL);
e2obj = Tcl_NewListObj(0, NULL);
lobj = Tcl_NewListObj(0, NULL);
g1obj = Tcl_NewListObj(0, NULL);
g2obj = Tcl_NewListObj(0, NULL);
numlists1 = numlists2 = 0;
for (E = escan->elements; E != NULL; E = E->next)
@@ -1035,22 +1037,30 @@ Tcl_Obj *ListElementClasses(int legal)
}
for (n = 0; n < ((n1 > n2) ? n1 : n2); n++) {
c1obj = Tcl_NewListObj(0, NULL);
c2obj = Tcl_NewListObj(0, NULL);
e1obj = Tcl_NewListObj(0, NULL);
e2obj = Tcl_NewListObj(0, NULL);
if (n < n1) {
estr = elist1[n]->name;
if (*estr == '/') estr++; // Remove leading slash, if any
Tcl_ListObjAppendElement(netgeninterp, e1obj, Tcl_NewStringObj(estr, -1));
Tcl_ListObjAppendElement(netgeninterp, c1obj, Tcl_NewStringObj(estr, -1));
}
else
Tcl_ListObjAppendElement(netgeninterp, e1obj,
Tcl_ListObjAppendElement(netgeninterp, c1obj,
Tcl_NewStringObj("(no matching instance)", -1));
Tcl_ListObjAppendElement(netgeninterp, c1obj, e1obj);
if (n < n2) {
estr = elist2[n]->name;
if (*estr == '/') estr++; // Remove leading slash, if any
Tcl_ListObjAppendElement(netgeninterp, e2obj, Tcl_NewStringObj(estr, -1));
Tcl_ListObjAppendElement(netgeninterp, c2obj, Tcl_NewStringObj(estr, -1));
}
else
Tcl_ListObjAppendElement(netgeninterp, e2obj,
Tcl_ListObjAppendElement(netgeninterp, c2obj,
Tcl_NewStringObj("(no matching instance)", -1));
Tcl_ListObjAppendElement(netgeninterp, c2obj, e2obj);
if (n >= n1)
maxf = elist2[n]->fanout;
@@ -1111,24 +1121,17 @@ Tcl_Obj *ListElementClasses(int legal)
}
f2++;
}
Tcl_ListObjAppendElement(netgeninterp, g1obj, c1obj);
Tcl_ListObjAppendElement(netgeninterp, g2obj, c2obj);
}
Tcl_ListObjAppendElement(netgeninterp, lobj, g1obj);
Tcl_ListObjAppendElement(netgeninterp, lobj, g2obj);
Tcl_ListObjAppendElement(netgeninterp, dobj, lobj);
FreeFormattedLists(elist1, numlists1);
FreeFormattedLists(elist2, numlists2);
gobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(netgeninterp, gobj, e1obj);
Tcl_ListObjAppendElement(netgeninterp, gobj, e2obj);
Tcl_ListObjAppendElement(netgeninterp, lobj, gobj);
}
}
dobj = Tcl_NewListObj(0, NULL);
if (legal)
Tcl_ListObjAppendElement(netgeninterp, dobj, Tcl_NewStringObj("goodelements", -1));
else
Tcl_ListObjAppendElement(netgeninterp, dobj, Tcl_NewStringObj("badelements", -1));
Tcl_ListObjAppendElement(netgeninterp, dobj, lobj);
return dobj;
}
@@ -1375,15 +1378,17 @@ Tcl_Obj *ListNodeClasses(int legal)
struct NodeClass *nscan;
int numlists1, numlists2, n1, n2, n, f, i, maxf;
Tcl_Obj *dobj, *lobj, *e1obj, *e2obj, *sobj, *gobj;
Tcl_Obj *lobj, *c1obj, *c2obj, *n1obj, *n2obj, *sobj;
Tcl_Obj *dobj, *g1obj, *g2obj;
lobj = Tcl_NewListObj(0, NULL);
dobj = Tcl_NewListObj(0, NULL);
for (nscan = NodeClasses; nscan != NULL; nscan = nscan->next) {
if (legal == nscan->legalpartition) {
struct Node *N;
e1obj = Tcl_NewListObj(0, NULL);
e2obj = Tcl_NewListObj(0, NULL);
lobj = Tcl_NewListObj(0, NULL);
g1obj = Tcl_NewListObj(0, NULL);
g2obj = Tcl_NewListObj(0, NULL);
numlists1 = numlists2 = 0;
for (N = nscan->nodes; N != NULL; N = N->next) {
@@ -1410,18 +1415,27 @@ Tcl_Obj *ListNodeClasses(int legal)
}
for (n = 0; n < ((n1 > n2) ? n1 : n2); n++) {
c1obj = Tcl_NewListObj(0, NULL);
c2obj = Tcl_NewListObj(0, NULL);
n1obj = Tcl_NewListObj(0, NULL);
n2obj = Tcl_NewListObj(0, NULL);
if (n < n1)
Tcl_ListObjAppendElement(netgeninterp, e1obj,
Tcl_ListObjAppendElement(netgeninterp, c1obj,
Tcl_NewStringObj(nlists1[n]->name, -1));
else
Tcl_ListObjAppendElement(netgeninterp, e1obj,
Tcl_ListObjAppendElement(netgeninterp, c1obj,
Tcl_NewStringObj("(no matching net)", -1));
Tcl_ListObjAppendElement(netgeninterp, c1obj, n1obj);
if (n < n2)
Tcl_ListObjAppendElement(netgeninterp, e2obj,
Tcl_ListObjAppendElement(netgeninterp, c2obj,
Tcl_NewStringObj(nlists2[n]->name, -1));
else
Tcl_ListObjAppendElement(netgeninterp, e2obj,
Tcl_ListObjAppendElement(netgeninterp, c2obj,
Tcl_NewStringObj("(no matching net)", -1));
Tcl_ListObjAppendElement(netgeninterp, c2obj, n2obj);
if (n >= n1)
maxf = nlists2[n]->fanout;
@@ -1445,7 +1459,7 @@ Tcl_Obj *ListNodeClasses(int legal)
if (nlists1[n]->flist[f].permute > 1)
FREE(nlists1[n]->flist[f].name);
Tcl_ListObjAppendElement(netgeninterp, e1obj, sobj);
Tcl_ListObjAppendElement(netgeninterp, n1obj, sobj);
}
if (n < n2)
if (f < nlists2[n]->fanout) {
@@ -1459,26 +1473,20 @@ Tcl_Obj *ListNodeClasses(int legal)
if (nlists2[n]->flist[f].permute > 1)
FREE(nlists2[n]->flist[f].name);
Tcl_ListObjAppendElement(netgeninterp, e2obj, sobj);
Tcl_ListObjAppendElement(netgeninterp, n2obj, sobj);
}
}
Tcl_ListObjAppendElement(netgeninterp, g1obj, c1obj);
Tcl_ListObjAppendElement(netgeninterp, g2obj, c2obj);
}
Tcl_ListObjAppendElement(netgeninterp, lobj, g1obj);
Tcl_ListObjAppendElement(netgeninterp, lobj, g2obj);
Tcl_ListObjAppendElement(netgeninterp, dobj, lobj);
FreeFormattedLists(nlists1, numlists1);
FreeFormattedLists(nlists2, numlists2);
gobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(netgeninterp, gobj, e1obj);
Tcl_ListObjAppendElement(netgeninterp, gobj, e2obj);
Tcl_ListObjAppendElement(netgeninterp, lobj, gobj);
}
}
dobj = Tcl_NewListObj(0, NULL);
if (legal)
Tcl_ListObjAppendElement(netgeninterp, dobj, Tcl_NewStringObj("goodnets", -1));
else
Tcl_ListObjAppendElement(netgeninterp, dobj, Tcl_NewStringObj("badnets", -1));
Tcl_ListObjAppendElement(netgeninterp, dobj, lobj);
return dobj;
}
@@ -2957,16 +2965,16 @@ int FirstElementPass(struct Element *E, int noflat, int dolist)
#ifdef TCL_NETGEN
if (dolist) {
Tcl_Obj *dlist, *mlist;
Tcl_Obj *mlist;
dlist = Tcl_NewListObj(0, NULL);
mlist = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(netgeninterp, mlist, clist1);
Tcl_ListObjAppendElement(netgeninterp, mlist, clist2);
Tcl_ListObjAppendElement(netgeninterp, dlist,
Tcl_NewStringObj("devices", -1));
Tcl_ListObjAppendElement(netgeninterp, dlist, mlist);
Tcl_SetVar2Ex(netgeninterp, "lvs_out", NULL, dlist,
Tcl_SetVar2Ex(netgeninterp, "lvs_out", NULL,
Tcl_NewStringObj("devices", -1),
TCL_APPEND_VALUE | TCL_LIST_ELEMENT);
Tcl_SetVar2Ex(netgeninterp, "lvs_out", NULL, mlist,
TCL_APPEND_VALUE | TCL_LIST_ELEMENT);
}
#endif
@@ -3016,16 +3024,15 @@ void FirstNodePass(struct Node *N, int dolist)
#ifdef TCL_NETGEN
if (dolist) {
Tcl_Obj *dlist, *nlist;
Tcl_Obj *nlist;
dlist = Tcl_NewListObj(0, NULL);
nlist = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(netgeninterp, dlist,
Tcl_NewStringObj("nets", -1));
Tcl_ListObjAppendElement(netgeninterp, dlist, nlist);
Tcl_ListObjAppendElement(netgeninterp, nlist, Tcl_NewIntObj(C1));
Tcl_ListObjAppendElement(netgeninterp, nlist, Tcl_NewIntObj(C2));
Tcl_SetVar2Ex(netgeninterp, "lvs_out", NULL, dlist,
Tcl_SetVar2Ex(netgeninterp, "lvs_out", NULL,
Tcl_NewStringObj("nets", -1),
TCL_APPEND_VALUE | TCL_LIST_ELEMENT);
Tcl_SetVar2Ex(netgeninterp, "lvs_out", NULL, nlist,
TCL_APPEND_VALUE | TCL_LIST_ELEMENT);
}
#endif
@@ -3483,16 +3490,16 @@ void CreateTwoLists(char *name1, int file1, char *name2, int file2, int dolist)
#ifdef TCL_NETGEN
if (dolist) {
Tcl_Obj *dlist, *nlist;
Tcl_Obj *nlist;
dlist = Tcl_NewListObj(0, NULL);
nlist = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(netgeninterp, dlist,
Tcl_NewStringObj("name", -1));
Tcl_ListObjAppendElement(netgeninterp, dlist, nlist);
Tcl_ListObjAppendElement(netgeninterp, nlist, Tcl_NewStringObj(name1, -1));
Tcl_ListObjAppendElement(netgeninterp, nlist, Tcl_NewStringObj(name2, -1));
Tcl_SetVar2Ex(netgeninterp, "lvs_out", NULL, dlist,
Tcl_SetVar2Ex(netgeninterp, "lvs_out", NULL,
Tcl_NewStringObj("name", -1),
TCL_APPEND_VALUE | TCL_LIST_ELEMENT);
Tcl_SetVar2Ex(netgeninterp, "lvs_out", NULL, nlist,
TCL_APPEND_VALUE | TCL_LIST_ELEMENT);
}
#endif
@@ -4489,21 +4496,38 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int serial)
#ifdef TCL_NETGEN
/*--------------------------------------------------------------*/
/* Property list starts with a pair of instance names, followed */
/* by a list of corresponding but mismatched properties. */
/*--------------------------------------------------------------*/
Tcl_Obj *NewPropertyList(char *inst1, char *inst2)
{
Tcl_Obj *proplist;
Tcl_Obj *mpair, *instobj;
mpair = Tcl_NewListObj(0, NULL);
instobj = Tcl_NewStringObj(inst1, -1);
Tcl_ListObjAppendElement(netgeninterp, mpair, instobj);
instobj = Tcl_NewStringObj(inst2, -1);
Tcl_ListObjAppendElement(netgeninterp, mpair, instobj);
proplist = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(netgeninterp, proplist, mpair);
return proplist;
}
/*--------------------------------------------------------------*/
/* Generate a Tcl list entry for a property mismatching pair */
/*--------------------------------------------------------------*/
Tcl_Obj *PropertyList(char *inst1, struct valuelist *vl1,
char *inst2, struct valuelist *vl2)
Tcl_Obj *PropertyList(struct valuelist *vl1, struct valuelist *vl2)
{
Tcl_Obj *mobj, *mpair, *propobj;
mpair = Tcl_NewListObj(0, NULL);
mobj = Tcl_NewListObj(0, NULL);
propobj = Tcl_NewStringObj(inst1, -1);
Tcl_ListObjAppendElement(netgeninterp, mobj, propobj);
if (vl1 == NULL)
propobj = Tcl_NewStringObj("(no matching parameter)", -1);
else
@@ -4523,9 +4547,6 @@ Tcl_Obj *PropertyList(char *inst1, struct valuelist *vl1,
Tcl_ListObjAppendElement(netgeninterp, mpair, mobj);
mobj = Tcl_NewListObj(0, NULL);
propobj = Tcl_NewStringObj(inst2, -1);
Tcl_ListObjAppendElement(netgeninterp, mobj, propobj);
if (vl2 == NULL)
propobj = Tcl_NewStringObj("(no matching parameter)", -1);
else
@@ -4540,6 +4561,8 @@ Tcl_Obj *PropertyList(char *inst1, struct valuelist *vl1,
propobj = Tcl_NewDoubleObj(vl2->value.dval);
else if (vl2->type == PROP_STRING)
propobj = Tcl_NewStringObj(vl2->value.string, -1);
else if (vl2->type == PROP_EXPRESSION)
propobj = Tcl_NewStringObj("(unresolved expression)", -1);
Tcl_ListObjAppendElement(netgeninterp, mobj, propobj);
Tcl_ListObjAppendElement(netgeninterp, mpair, mobj);
@@ -4582,9 +4605,8 @@ PropertyCheckMismatch(struct objlist *tp1, struct nlist *tc1,
static struct property klm, kls;
static char mkey[2], skey[2];
#ifdef TCL_NETLIST
Tcl_Obj *proplist;
proplist = Tcl_NewListObj(0, NULL);
#ifdef TCL_NETGEN
Tcl_Obj *proplist = NULL;
#endif
// Set up static records representing property M = 1 and S = 1
@@ -4648,9 +4670,10 @@ PropertyCheckMismatch(struct objlist *tp1, struct nlist *tc1,
Fprintf(stdout, "Property %s in circuit2 has no matching "
"property in circuit1\n", vl2->key);
}
#ifdef TCL_NETLIST
#ifdef TCL_NETGEN
if (do_list) {
Tcl_Obj *mpair = PropertyList(inst1, vl1, inst2, vl2);
Tcl_Obj *mpair = PropertyList(NULL, vl2);
if (!proplist) proplist = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(netgeninterp, proplist, mpair);
}
#endif
@@ -4703,9 +4726,10 @@ PropertyCheckMismatch(struct objlist *tp1, struct nlist *tc1,
Fprintf(stdout, "Property %s in circuit1 has no matching "
"property in circuit2\n", vl1->key);
}
#ifdef TCL_NETLIST
#ifdef TCL_NETGEN
if (do_list) {
Tcl_Obj *mpair = PropertyList(inst1, vl1, inst2, vl2);
Tcl_Obj *mpair = PropertyList(vl1, NULL);
if (!proplist) proplist = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(netgeninterp, proplist, mpair);
}
#endif
@@ -4785,9 +4809,10 @@ PropertyCheckMismatch(struct objlist *tp1, struct nlist *tc1,
}
Fprintf(stdout, " (property type mismatch)\n");
}
#ifdef TCL_NETLIST
#ifdef TCL_NETGEN
if (do_list) {
Tcl_Obj *mpair = PropertyList(inst1, vl1, inst2, vl2);
Tcl_Obj *mpair = PropertyList(vl1, vl2);
if (!proplist) proplist = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(netgeninterp, proplist, mpair);
}
#endif
@@ -4814,9 +4839,10 @@ PropertyCheckMismatch(struct objlist *tp1, struct nlist *tc1,
else
Fprintf(stdout, "\n");
}
#ifdef TCL_NETLIST
#ifdef TCL_NETGEN
if (do_list) {
Tcl_Obj *mpair = PropertyList(inst1, vl1, inst2, vl2);
Tcl_Obj *mpair = PropertyList(vl1, vl2);
if (!proplist) proplist = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(netgeninterp, proplist, mpair);
}
#endif
@@ -4840,9 +4866,10 @@ PropertyCheckMismatch(struct objlist *tp1, struct nlist *tc1,
else
Fprintf(stdout, "\n");
}
#ifdef TCL_NETLIST
#ifdef TCL_NETGEN
if (do_list) {
Tcl_Obj *mpair = PropertyList(inst1, vl1, inst2, vl2);
Tcl_Obj *mpair = PropertyList(vl1, vl2);
if (!proplist) proplist = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(netgeninterp, proplist, mpair);
}
#endif
@@ -4867,9 +4894,10 @@ PropertyCheckMismatch(struct objlist *tp1, struct nlist *tc1,
kl1->key, vl1->value.string,
vl2->value.string);
}
#ifdef TCL_NETLIST
#ifdef TCL_NETGEN
if (do_list) {
Tcl_Obj *mpair = PropertyList(inst1, vl1, inst2, vl2);
Tcl_Obj *mpair = PropertyList(vl1, vl2);
if (!proplist) proplist = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(netgeninterp, proplist, mpair);
}
#endif
@@ -4886,9 +4914,10 @@ PropertyCheckMismatch(struct objlist *tp1, struct nlist *tc1,
kl1->key, vl1->value.string,
vl2->value.string, islop);
}
#ifdef TCL_NETLIST
#ifdef TCL_NETGEN
if (do_list) {
Tcl_Obj *mpair = PropertyList(inst1, vl1, inst2, vl2);
Tcl_Obj *mpair = PropertyList(vl1, vl2);
if (!proplist) proplist = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(netgeninterp, proplist, mpair);
}
#endif
@@ -4900,9 +4929,10 @@ PropertyCheckMismatch(struct objlist *tp1, struct nlist *tc1,
/* Expressions could potentially be compared. . . */
if (do_print)
Fprintf(stdout, " %s (unresolved expressions.)\n", kl1->key);
#ifdef TCL_NETLIST
#ifdef TCL_NETGEN
if (do_list) {
Tcl_Obj *mpair = PropertyList(inst1, vl1, inst2, vl2);
Tcl_Obj *mpair = PropertyList(vl1, vl2);
if (!proplist) proplist = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(netgeninterp, proplist, mpair);
}
#endif
@@ -4917,8 +4947,8 @@ PropertyCheckMismatch(struct objlist *tp1, struct nlist *tc1,
if (len2 > 0) FREE(check2);
*count = mismatches;
#ifdef TCL_NETLIST
if (dolist) return proplist;
#ifdef TCL_NETGEN
return proplist;
#endif
}
@@ -4955,7 +4985,7 @@ PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print,
int rval = 1;
char *inst1, *inst2;
#ifdef TCL_NETGEN
Tcl_Obj *proplist, *mpair;
Tcl_Obj *proplist = NULL, *mpair, *mlist;
#endif
tc1 = LookupCellFile(ob1->model.class, Circuit1->file);
@@ -4972,10 +5002,12 @@ PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print,
/* Find the first property record of each circuit. obn1, obn2 are */
/* the last device record before the properties for each device. */
for (tp1 = ob1; (tp1 != NULL) && tp1->type >= FIRSTPIN; tp1 = tp1->next)
for (tp1 = ob1->next; (tp1 != NULL) && tp1->type > FIRSTPIN; tp1 = tp1->next)
obn1 = tp1;
for (tp2 = ob2; (tp2 != NULL) && tp2->type >= FIRSTPIN; tp2 = tp2->next)
for (tp2 = ob2->next; (tp2 != NULL) && tp2->type > FIRSTPIN; tp2 = tp2->next)
obn2 = tp2;
if (tp1 && (tp1->type == FIRSTPIN)) tp1 = NULL; /* tp1 had no properties */
if (tp2 && (tp2->type == FIRSTPIN)) tp2 = NULL; /* tp2 had no properties */
/* Check if there are any properties to match */
@@ -5041,14 +5073,11 @@ PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print,
inst2 = ob2->instance.name;
if (*inst2 == '/') inst2++;
proplist = Tcl_NewListObj(0, NULL);
while(1) {
if (t1type != PROPERTY) {
// t1 has no properties. See if t2's properties are required
// to be checked. If so, flag t2 instance as unmatched
mismatches++;
for (i = 0;; i++) {
vl2 = &(tp2->instance.props[i]);
if (vl2->type == PROP_ENDLIST) break;
@@ -5058,13 +5087,17 @@ PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print,
if (kl2 != NULL) break; // Property is required
}
if (vl2->type != PROP_ENDLIST) {
mismatches++;
if (do_print) Fprintf(stdout, "Circuit 2 %s instance %s has no"
" property match in circuit 1.\n",
Circuit2->name, inst2);
#ifdef TCL_NETGEN
if (do_list) {
mpair = PropertyList(inst1, NULL, inst2, vl2);
Tcl_ListObjAppendElement(netgeninterp, proplist, mpair);
mpair = PropertyList(NULL, vl2);
if (mpair) {
if (!proplist) proplist = NewPropertyList(inst1, inst2);
Tcl_ListObjAppendElement(netgeninterp, proplist, mpair);
}
}
#endif
rval = -1;
@@ -5091,8 +5124,11 @@ PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print,
Circuit1->name, inst1);
#ifdef TCL_NETGEN
if (do_list) {
mpair = PropertyList(inst1, vl1, inst2, NULL);
Tcl_ListObjAppendElement(netgeninterp, proplist, mpair);
mpair = PropertyList(vl1, NULL);
if (mpair) {
if (!proplist) proplist = NewPropertyList(inst1, inst2);
Tcl_ListObjAppendElement(netgeninterp, proplist, mpair);
}
}
#endif
rval = -1;
@@ -5115,13 +5151,16 @@ PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print,
PropertyOptimize(tp2, tc2, 1, TRUE);
}
#ifdef TCL_NETGEN
mpair =
mlist =
#endif
PropertyCheckMismatch(tp1, tc1, inst1, tp2, tc2,
inst2, do_print, do_list, &count, &rval);
mismatches += count;
#ifdef TCL_NETGEN
Tcl_ListObjAppendElement(netgeninterp, proplist, mpair);
if (do_list && (mlist != NULL)) {
if (!proplist) proplist = NewPropertyList(inst1, inst2);
Tcl_ListObjAppendList(netgeninterp, proplist, mlist);
}
#endif
}
@@ -5204,7 +5243,7 @@ void PrintPropertyResults(int do_list)
#ifdef TCL_NETGEN
if (do_list) {
Tcl_Obj *proprec, *proplist, *eprop;
Tcl_Obj *proplist, *eprop;
proplist = Tcl_NewListObj(0, NULL);
for (EC = ElementClasses; EC != NULL; EC = EC->next) {
@@ -5212,11 +5251,10 @@ void PrintPropertyResults(int do_list)
if (eprop != NULL)
Tcl_ListObjAppendElement(netgeninterp, proplist, eprop);
}
proprec = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(netgeninterp, proprec,
Tcl_NewStringObj("properties", -1));
Tcl_ListObjAppendElement(netgeninterp, proprec, proplist);
Tcl_SetVar2Ex(netgeninterp, "lvs_out", NULL, proprec,
Tcl_SetVar2Ex(netgeninterp, "lvs_out", NULL,
Tcl_NewStringObj("properties", -1),
TCL_APPEND_VALUE | TCL_LIST_ELEMENT);
Tcl_SetVar2Ex(netgeninterp, "lvs_out", NULL, proplist,
TCL_APPEND_VALUE | TCL_LIST_ELEMENT);
}
else {
@@ -6236,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;
@@ -6245,7 +6284,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
int needclean1 = 0, needclean2 = 0;
char ostr[89];
#ifdef TCL_NETGEN
Tcl_Obj *dlist, *mlist, *plist1, *plist2;
Tcl_Obj *mlist, *plist1, *plist2;
#endif
if (tc1 == NULL) tc1 = Circuit1;
@@ -6274,11 +6313,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
#ifdef TCL_NETGEN
if (dolist) {
dlist = Tcl_NewListObj(0, NULL);
mlist = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(netgeninterp, dlist,
Tcl_NewStringObj("pins", -1));
Tcl_ListObjAppendElement(netgeninterp, dlist, mlist);
plist1 = Tcl_NewListObj(0, NULL);
plist2 = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(netgeninterp, mlist, plist1);
@@ -6322,9 +6357,13 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
}
if (N2 == NULL) {
#ifdef TCL_NETGEN
if (dolist)
Tcl_SetVar2Ex(netgeninterp, "lvs_out", NULL, dlist,
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
return 1;
}
@@ -6337,11 +6376,11 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
if (Debug == 0) {
for (m = 0; m < 43; m++) *(ostr + m) = ' ';
for (m = 44; m < 87; m++) *(ostr + m) = ' ';
sprintf(ostr, "%s", obn->name);
snprintf(ostr, 43, "%s", obn->name);
if (!strcasecmp(obn->name, obp->name))
sprintf(ostr + 44, "%s", obp->name);
snprintf(ostr + 44, 43, "%s", obp->name);
else
sprintf(ostr + 44, "%s **Mismatch**", obp->name);
snprintf(ostr + 44, 43, "%s **Mismatch**", obp->name);
for (m = 0; m < 88; m++)
if (*(ostr + m) == '\0') *(ostr + m) = ' ';
Fprintf(stdout, ostr);
@@ -6375,8 +6414,8 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
if (strcmp(obn->name, "(no pins)")) {
for (m = 0; m < 43; m++) *(ostr + m) = ' ';
for (m = 44; m < 87; m++) *(ostr + m) = ' ';
sprintf(ostr, "%s", obn->name);
sprintf(ostr + 44, "(no matching pin)");
snprintf(ostr, 32, "%s", obn->name);
snprintf(ostr + 44, 43, "(no matching pin)");
for (m = 0; m < 88; m++)
if (*(ostr + m) == '\0') *(ostr + m) = ' ';
Fprintf(stdout, ostr);
@@ -6420,8 +6459,8 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
if (Debug == 0) {
for (m = 0; m < 43; m++) *(ostr + m) = ' ';
for (m = 44; m < 87; m++) *(ostr + m) = ' ';
sprintf(ostr, "%s", obn->name);
sprintf(ostr + 44, "(no matching pin)");
snprintf(ostr, 43, "%s", obn->name);
snprintf(ostr + 44, 43, "(no matching pin)");
for (m = 0; m < 88; m++)
if (*(ostr + m) == '\0') *(ostr + m) = ' ';
Fprintf(stdout, ostr);
@@ -6448,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;
@@ -6462,8 +6513,8 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
if (Debug == 0) {
for (m = 0; m < 43; m++) *(ostr + m) = ' ';
for (m = 44; m < 87; m++) *(ostr + m) = ' ';
sprintf(ostr, "%s", ob1->name);
sprintf(ostr + 44, "%s", ob2->name);
snprintf(ostr, 43, "%s", ob1->name);
snprintf(ostr + 44, 43, "%s", ob2->name);
for (m = 0; m < 88; m++)
if (*(ostr + m) == '\0') *(ostr + m) = ' ';
Fprintf(stdout, ostr);
@@ -6483,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 */
@@ -6509,8 +6562,8 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
if (strcmp(ob2->name, "(no pins)")) {
for (m = 0; m < 43; m++) *(ostr + m) = ' ';
for (m = 44; m < 87; m++) *(ostr + m) = ' ';
sprintf(ostr, "(no matching pin)");
sprintf(ostr + 44, "%s", ob2->name);
snprintf(ostr, 43, "(no matching pin)");
snprintf(ostr + 44, 43, "%s", ob2->name);
for (m = 0; m < 88; m++)
if (*(ostr + m) == '\0') *(ostr + m) = ' ';
Fprintf(stdout, ostr);
@@ -6559,8 +6612,14 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
obn->model.port = -1;
obn->instance.name = NULL;
obn->node = -1;
obn->next = ob1->next;
ob1->next = obn;
if (ob1 == tc1->cell) {
obn->next = ob1;
tc1->cell = obn;
}
else {
obn->next = ob1->next;
ob1->next = obn;
}
ob1 = obn;
hasproxy1 = 1;
@@ -6617,8 +6676,15 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
obn->model.port = (i - j);
obn->instance.name = NULL;
obn->node = -1;
obn->next = ob2->next;
ob2->next = obn;
if (ob2 == tc2->cell) {
obn->next = ob2;
tc2->cell = obn;
}
else {
obn->next = ob2->next;
ob2->next = obn;
}
ob2 = obn;
hasproxy2 = 1;
@@ -6658,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;
}
@@ -6677,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.
@@ -6738,9 +6804,13 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
#ifdef TCL_NETGEN
/* Handle list output */
if (dolist)
Tcl_SetVar2Ex(netgeninterp, "lvs_out", NULL, dlist,
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
return result;
+34 -12
View File
@@ -49,6 +49,7 @@ int NextNode;
int Composition = NONE;
int QuickSearch = 0;
int GlobalParallelNone = FALSE;
int AddToExistingDefinition = 0; /* default: overwrite cell when reopened */
@@ -870,6 +871,32 @@ int ReduceExpressions(struct objlist *instprop, struct objlist *parprops,
return 0;
}
/*----------------------------------------------------------------------*/
/* Set/clear the flag bit COMB_NO_PARALLEL on all cells. Note that the */
/* function is called with value for enabling combine parallel, so */
/* value TRUE means clear bit, value FALSE means set bit. */
/*----------------------------------------------------------------------*/
struct nlist *SetParallelCombineFlag(struct hashlist *p, void *clientdata)
{
struct nlist *ptr;
int *value = (int *)clientdata;
ptr = (struct nlist *)(p->ptr);
if (*value == TRUE)
ptr->flags &= (~COMB_NO_PARALLEL);
else
ptr->flags |= COMB_NO_PARALLEL;
return NULL; /* NULL keeps search alive */
}
void SetParallelCombine(int value)
{
ClearDumpedList();
RecurseCellHashTable2(SetParallelCombineFlag, (void *)(&value));
}
/*----------------------------------------------------------------------*/
/* Delete a property from the master cell record. */
/*----------------------------------------------------------------------*/
@@ -1192,7 +1219,7 @@ void CellDef(char *name, int fnum)
np = InstallInCellHashTable(name, fnum);
CurrentCell = LookupCellFile(name, fnum);
CurrentCell->class = CLASS_SUBCKT; /* default */
CurrentCell->flags = 0;
CurrentCell->flags = (GlobalParallelNone) ? COMB_NO_PARALLEL : 0;
LastPlaced = NULL;
CurrentTail = NULL;
@@ -3306,11 +3333,6 @@ int CombineSerial(char *model, int file)
int i, j, scnt = 0;
struct valuelist *kv;
// To avoid posting a non-working version, serial combination is
// disabled here until code is finished to compare the serial/parallel
// property networks.
// return 0;
if ((tp = LookupCellFile(model, file)) == NULL) {
Printf("Cell: %s does not exist.\n", model);
return -1;
@@ -3387,11 +3409,10 @@ int CombineSerial(char *model, int file)
/* a parameter '_tag', string value set to "+". */
for (obn = instlist[i][1]; obn->next &&
obn->next->type != PROPERTY &&
obn->next->type != FIRSTPIN; obn = obn->next);
obn->next->type > FIRSTPIN; obn = obn->next);
obp = obn->next;
if (obp == NULL || obp->type == FIRSTPIN) {
if (obp == NULL || obp->type != PROPERTY) {
struct objlist *nob;
/* No property record, so insert one */
nob = GetObject();
@@ -3463,10 +3484,11 @@ int CombineSerial(char *model, int file)
/* Excise the 2nd instance. instlist[i][1] remains as the */
/* only pointer to it. */
for (obp = instlist[i][0]; obp->next->type != FIRSTPIN; obp = obp->next);
for (obp = instlist[i][0]; obp->next->type > FIRSTPIN ||
obp->next->type == PROPERTY; obp = obp->next);
for (ob2 = obp; ob2->next != instlist[i][1]; ob2 = ob2->next);
for (obs = ob2->next; obs->next && obs->next->type != FIRSTPIN;
obs = obs->next);
for (obs = ob2->next; obs->next && (obs->next->type > FIRSTPIN
|| obs->next->type == PROPERTY); obs = obs->next);
ob2->next = obs->next;
if (obs->next) obs->next = NULL; // Terminate 2nd instance record
+4
View File
@@ -35,6 +35,7 @@ extern struct property *PropertyInteger(char *name, int fnum, char *key,
extern struct property *PropertyString(char *name, int fnum, char *key,
double slop, char *pdefault);
extern int PropertyDelete(char *name, int fnum, char *key);
extern void SetParallelCombine(int value);
extern int PropertyTolerance(char *name, int fnum, char *key, int ival,
double dval);
extern int PropertyMerge(char *name, int fnum, char *key, int merge_type);
@@ -53,6 +54,8 @@ extern void PortList(char *prefix, char *list_template);
extern char *Cell(char *inststr, char *model, ...);
extern int IsIgnored(char *, int);
extern int auto_blackbox; /* For handling empty subcircuits */
/* netcmp.c */
extern struct nlist *LookupClassEquivalent(char *model, int file1, int file2);
extern void AssignCircuits(char *name1, int file1, char *name2, int file2);
@@ -132,6 +135,7 @@ extern int IgnoreRC; /* set this to 1 to ignore capacitance and resistance */
extern int NoOutput; /* set this to 1 to disable stdout output */
extern int Composition; /* direction of composition */
extern int UnixWildcards; /* TRUE if *,?,{},[] only; false if full REGEXP */
extern int GlobalParallelNone; /* If TRUE, don't parallel combine any cells */
/* magic internal flag to restrict searches to recently placed cells */
extern int QuickSearch;
/* does re"CellDef"ing a cell add to it or overwrite it??? */
+6 -3
View File
@@ -563,8 +563,11 @@ static int PrintCellHashTableElement(struct hashlist *p)
/* only print primitive cells if Debug is enabled */
if (Debug == 1) Printf("Cell: %s (instanced %d times); Primitive\n",
ptr->name, ptr->number);
else if (Debug == 3) { /* list */
Tcl_AppendElement(netgeninterp, ptr->name);
}
}
else if (Debug == 2) { /* list only */
else if ((Debug == 2) || (Debug == 3)) { /* list only */
#ifdef TCL_NETGEN
Tcl_AppendElement(netgeninterp, ptr->name);
#else
@@ -595,7 +598,7 @@ void PrintCellHashTable(int full, int filenum)
bins = RecurseHashTable(&cell_dict, CountHashTableBinsUsed);
total = RecurseHashTable(&cell_dict, CountHashTableEntries);
if (full != 2)
if (full < 2)
Printf("Hash table: %d of %d bins used; %d cells total (%.2f per bin)\n",
bins, CELLHASHSIZE, total, (bins == 0) ? 0 :
(float)((float)total / (float)bins));
@@ -605,7 +608,7 @@ void PrintCellHashTable(int full, int filenum)
RecurseHashTable(&cell_dict, PrintCellHashTableElement);
Debug = OldDebug;
#ifndef TCL_NETGEN
if (full == 2) Printf("\n");
if (full >= 2) Printf("\n");
#endif
}
+48 -5
View File
@@ -25,8 +25,10 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdarg.h> /* what about varargs, like in pdutils.c ??? */
#endif
#ifdef IBMPC
#include <stdlib.h> /* for calloc(), free() */
#include <stdlib.h> /* for calloc(), free(), getenv() */
#ifndef IBMPC
#include <sys/types.h> /* for getpwnam() tilde expansion */
#include <pwd.h>
#endif
#ifdef TCL_NETGEN
@@ -42,6 +44,10 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
// Global storage for parameters from .PARAM
struct hashdict spiceparams;
// Global setting for auto-detect of empty subcircuits as
// black-box subcells.
int auto_blackbox = FALSE;
// Check if a token represents a numerical value (with
// units) or an expression. This is basically a hack
// to see if it either passes StringIsValue() or is
@@ -398,6 +404,7 @@ int renamepins(struct hashlist *p, int file)
void CleanupSubcell() {
int maxnode = 0;
int has_devices = FALSE;
struct objlist *sobj, *nobj, *lobj, *pobj;
if (CurrentCell == NULL) return;
@@ -409,6 +416,8 @@ void CleanupSubcell() {
lobj = NULL;
for (sobj = CurrentCell->cell; sobj != NULL;) {
nobj = sobj->next;
if (sobj->type == FIRSTPIN)
has_devices = TRUE;
if (sobj->node < 0) {
if (IsGlobal(sobj)) {
if (lobj != NULL)
@@ -437,6 +446,8 @@ void CleanupSubcell() {
lobj = sobj;
sobj = nobj;
}
if ((has_devices == FALSE) && (auto_blackbox == TRUE))
SetClass(CLASS_MODULE);
}
/*------------------------------------------------------*/
@@ -615,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
@@ -743,7 +754,7 @@ skip_ends:
SpiceSkipNewLine();
}
else if (matchnocase(nexttok, ".INCLUDE")) {
char *iname, *iptr, *quotptr, *pathend;
char *iname, *iptr, *quotptr, *pathend, *userpath = NULL;
SpiceTokNoNewline();
if (nexttok == NULL) continue; /* Ignore if no filename */
@@ -755,12 +766,44 @@ skip_ends:
pathend = strrchr(fname, '/');
iptr = nexttok;
while (*iptr == '\'' || *iptr == '\"' || *iptr == '`') iptr++;
if ((pathend != NULL) && (*iptr != '/')) {
if ((pathend != NULL) && (*iptr != '/') && (*iptr != '~')) {
*pathend = '\0';
iname = (char *)MALLOC(strlen(fname) + strlen(iptr) + 2);
sprintf(iname, "%s/%s", fname, iptr);
*pathend = '/';
}
#ifndef IBMPC
else if ((*iptr == '~') && (*(iptr + 1) == '/')) {
/* For ~/<path>, substitute tilde from $HOME */
userpath = getenv("HOME");
iname = (char *)MALLOC(strlen(userpath) + strlen(iptr));
sprintf(fname, "%s%s", userpath, iptr + 1);
}
else if (*iptr == '~') {
/* For ~<user>/<path>, substitute tilde from getpwnam() */
struct passwd *passwd;
char *pathstart;
pathstart = strchr(iptr, '/');
if (pathstart) *pathstart = '\0';
passwd = getpwnam(iptr + 1);
if (passwd != NULL) {
userpath = passwd->pw_dir;
if (pathstart) {
*pathstart = '/';
iname = (char *)MALLOC(strlen(userpath) + strlen(pathstart) + 1);
sprintf(fname, "%s%s", userpath, pathstart);
}
else {
/* Almost certainly an error, but make the substitution anyway */
iname = STRDUP(userpath);
}
}
else {
/* Probably an error, but copy the filename verbatim */
iname = STRDUP(iptr);
}
}
#endif
else
iname = STRDUP(iptr);
+339 -2
View File
@@ -26,6 +26,333 @@ if {${tcl_version} >= 8.6} {
load TCL_DIR/tclnetgenSHDLIB_EXT
}
#----------------------------------------------------------------
# Convert LVS list result into a JSON file
#----------------------------------------------------------------
proc netgen::convert_to_json {filename lvs_final} {
set pidx [string last . $filename]
set jsonname [string replace $filename $pidx end ".json"]
if {![catch {open $jsonname w} fjson]} {
puts $fjson "\["
# Outer list is of each cell compared
set clen [llength $lvs_final]
set cidx 0
foreach circuit $lvs_final {
incr cidx
puts $fjson " \{"
set nkeys [llength $circuit]
set kidx 0
foreach {key value} $circuit {
incr kidx 2
switch $key {
name {
puts $fjson " \"${key}\": \["
set cktval [lindex $value 0]
puts $fjson " \"${cktval}\","
set cktval [lindex $value 1]
puts $fjson " \"${cktval}\""
if {$kidx == $nkeys} {
puts $fjson " \]"
} else {
puts $fjson " \],"
}
}
pins {
puts $fjson " \"${key}\": \["
puts $fjson " \["
set cktval [lindex $value 0]
foreach pin [lrange $cktval 0 end-1] {
puts $fjson " \"$pin\","
}
set pin [lindex $cktval end]
puts $fjson " \"$pin\""
puts $fjson " \], \["
set cktval [lindex $value 1]
foreach pin [lrange $cktval 0 end-1] {
puts $fjson " \"$pin\","
}
set pin [lindex $cktval end]
puts $fjson " \"$pin\""
puts $fjson " \]"
if {$kidx == $nkeys} {
puts $fjson " \]"
} else {
puts $fjson " \],"
}
}
nets {
puts $fjson " \"${key}\": \["
set cktval [lindex $value 0]
puts $fjson " $cktval,"
set cktval [lindex $value 1]
puts $fjson " $cktval"
if {$kidx == $nkeys} {
puts $fjson " \]"
} else {
puts $fjson " \],"
}
}
devices {
puts $fjson " \"${key}\": \["
puts $fjson " \["
set cktval [lindex $value 0]
foreach dev [lrange $cktval 0 end-1] {
set devname [lindex $dev 0]
set devnum [lindex $dev 1]
puts $fjson " \[\"${devname}\", ${devnum}\],"
}
set dev [lindex $cktval end]
set devname [lindex $dev 0]
set devnum [lindex $dev 1]
puts $fjson " \[\"${devname}\", ${devnum} \]"
puts $fjson " \], \["
set cktval [lindex $value 1]
foreach dev [lrange $cktval 0 end-1] {
set devname [lindex $dev 0]
set devnum [lindex $dev 1]
puts $fjson " \[\"${devname}\", ${devnum} \],"
}
set dev [lindex $cktval end]
set devname [lindex $dev 0]
set devnum [lindex $dev 1]
puts $fjson " \[\"${devname}\", ${devnum} \]"
puts $fjson " \]"
if {$kidx == $nkeys} {
puts $fjson " \]"
} else {
puts $fjson " \],"
}
}
goodnets -
badnets {
puts $fjson " \"${key}\": \["
set glen [llength $value]
set gidx 0
foreach group $value {
incr gidx
puts $fjson " \["
puts $fjson " \["
set cktval [lindex $group 0]
set nlen [llength $cktval]
set nidx 0
foreach net $cktval {
incr nidx
puts $fjson " \["
set netname [lindex $net 0]
puts $fjson " \"$netname\","
puts $fjson " \["
set netconn [lindex $net 1]
foreach fanout [lrange $netconn 0 end-1] {
set devname [lindex $fanout 0]
set pinname [lindex $fanout 1]
set count [lindex $fanout 2]
if {$count == {}} {set count 0}
puts $fjson " \[ \"$devname\", \"$pinname\", $count \],"
}
set fanout [lindex $netconn end]
set devname [lindex $fanout 0]
set pinname [lindex $fanout 1]
set count [lindex $fanout 2]
if {$count == {}} {set count 0}
puts $fjson " \[ \"$devname\", \"$pinname\", $count \]"
puts $fjson " \]"
if {$nidx == $nlen} {
puts $fjson " \]"
} else {
puts $fjson " \],"
}
}
puts $fjson " \], \["
set cktval [lindex $group 1]
set nlen [llength $cktval]
set nidx 0
foreach net $cktval {
incr nidx
puts $fjson " \["
set netname [lindex $net 0]
puts $fjson " \"$netname\","
puts $fjson " \["
set netconn [lindex $net 1]
foreach fanout [lrange $netconn 0 end-1] {
set devname [lindex $fanout 0]
set pinname [lindex $fanout 1]
set count [lindex $fanout 2]
if {$count == {}} {set count 0}
puts $fjson " \[ \"$devname\", \"$pinname\", $count \],"
}
set fanout [lindex $netconn end]
set devname [lindex $fanout 0]
set pinname [lindex $fanout 1]
set count [lindex $fanout 2]
if {$count == {}} {set count 0}
puts $fjson " \[ \"$devname\", \"$pinname\", $count \]"
puts $fjson " \]"
if {$nidx == $nlen} {
puts $fjson " \]"
} else {
puts $fjson " \],"
}
}
puts $fjson " \]"
if {$gidx == $glen} {
puts $fjson " \]"
} else {
puts $fjson " \],"
}
}
if {$kidx == $nkeys} {
puts $fjson " \]"
} else {
puts $fjson " \],"
}
}
goodelements -
badelements {
puts $fjson " \"${key}\": \["
set glen [llength $value]
set gidx 0
foreach group $value {
incr gidx
puts $fjson " \["
puts $fjson " \["
set cktval [lindex $group 0]
set ilen [llength $cktval]
set iidx 0
foreach inst $cktval {
incr iidx
puts $fjson " \["
set instname [lindex $inst 0]
puts $fjson " \"$instname\","
puts $fjson " \["
set instpins [lindex $inst 1]
foreach fanout [lrange $instpins 0 end-1] {
set pinname [lindex $fanout 0]
set count [lindex $fanout 1]
if {$count == {}} {set count 0}
puts $fjson " \[ \"$pinname\", $count \],"
}
set fanout [lindex $instpins end]
set pinname [lindex $fanout 0]
set count [lindex $fanout 1]
if {$count == {}} {set count 0}
puts $fjson " \[ \"$pinname\", $count \]"
puts $fjson " \]"
if {$iidx == $ilen} {
puts $fjson " \]"
} else {
puts $fjson " \],"
}
}
puts $fjson " \], \["
set cktval [lindex $group 1]
set ilen [llength $cktval]
set iidx 0
foreach inst $cktval {
incr iidx
puts $fjson " \["
set instname [lindex $inst 0]
puts $fjson " \"$instname\","
puts $fjson " \["
set instpins [lindex $inst 1]
foreach fanout [lrange $instpins 0 end-1] {
set pinname [lindex $fanout 0]
set count [lindex $fanout 1]
if {$count == {}} {set count 0}
puts $fjson " \[ \"$pinname\", $count \],"
}
set fanout [lindex $instpins end]
set pinname [lindex $fanout 0]
set count [lindex $fanout 1]
if {$count == {}} {set count 0}
puts $fjson " \[ \"$pinname\", $count \]"
puts $fjson " \]"
if {$iidx == $ilen} {
puts $fjson " \]"
} else {
puts $fjson " \],"
}
}
puts $fjson " \]"
if {$gidx == $glen} {
puts $fjson " \]"
} else {
puts $fjson " \],"
}
}
if {$kidx == $nkeys} {
puts $fjson " \]"
} else {
puts $fjson " \],"
}
}
properties {
puts $fjson " \"${key}\": \["
set plen [llength $value]
set pidx 0
foreach instance $value {
incr pidx
puts $fjson " \["
set instnames [lindex $instance 0]
set instname0 [lindex $instnames 0]
puts $fjson " \["
puts $fjson " \"${instname0}\","
puts $fjson " \["
foreach property [lrange $instance 1 end-1] {
set prop0 [lindex $property 0]
set propname [lindex $prop0 0]
set propval [lindex $prop0 1]
puts $fjson " \[\"${propname}\", \"${propval}\"\],"
}
set property [lindex $instance end]
set prop0 [lindex $property 0]
set propname [lindex $prop0 0]
set propval [lindex $prop0 1]
puts $fjson " \[\"${propname}\", \"${propval}\"\]"
puts $fjson " \]"
puts $fjson " \],"
set instname1 [lindex $instnames 1]
puts $fjson " \["
puts $fjson " \"${instname1}\","
puts $fjson " \["
foreach property [lrange $instance 1 end-1] {
set prop1 [lindex $property 1]
set propname [lindex $prop1 0]
set propval [lindex $prop1 1]
puts $fjson " \[\"${propname}\", \"${propval}\"\],"
}
set property [lindex $instance end]
set prop1 [lindex $property 1]
set propname [lindex $prop1 0]
set propval [lindex $prop1 1]
puts $fjson " \[\"${propname}\", \"${propval}\"\]"
puts $fjson " \]"
puts $fjson " \]"
if {$pidx == $plen} {
puts $fjson " \]"
} else {
puts $fjson " \],"
}
}
if {$kidx == $nkeys} {
puts $fjson " \]"
} else {
puts $fjson " \],"
}
}
}
}
if {$cidx == $clen} {
puts $fjson " \}"
} else {
puts $fjson " \},"
}
}
puts $fjson "\]"
}
close $fjson
}
#----------------------------------------------------------------
# Define the "lvs" command as a way of calling the netgen options
# for standard compare, essentially the same as the old "netcomp"
@@ -42,12 +369,20 @@ if {${tcl_version} >= 8.6} {
proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
set dolist 0
puts stdout "Diagnostic version"
set dojson 0
foreach arg $args {
if {$arg == "-list"} {
puts stdout "Generating list result"
set dolist 1
set lvs_final {}
} elseif {$arg == "-json"} {
puts stdout "Generating JSON file result"
set dolist 1
set dojson 1
set lvs_final {}
} elseif {$arg == "-blackbox"} {
puts stdout "Treating empty subcircuits as black-box cells"
netgen::model blackbox on
}
}
@@ -229,7 +564,9 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
}
netgen::log end
puts stdout "LVS Done."
if {$dolist == 1} {
if {$dojson == 1} {
netgen::convert_to_json $logfile $lvs_final
} elseif {$dolist == 1} {
return $lvs_final
}
}
+119 -63
View File
@@ -1437,9 +1437,9 @@ _netgen_cells(ClientData clientData,
char *optstart;
int filenum = -1;
struct nlist *np = NULL;
int result, dolist = 0;
int result, printopt, dolist = 0, doall = 0, dotop = 0;
if (objc > 1) {
while (objc > 1) {
optstart = Tcl_GetString(objv[1]);
if (*optstart == '-') optstart++;
if (!strcmp(optstart, "list")) {
@@ -1447,27 +1447,41 @@ _netgen_cells(ClientData clientData,
objv++;
objc--;
}
else if (!strcmp(optstart, "all")) {
doall = 1;
objv++;
objc--;
}
else if (!strcmp(optstart, "top")) {
dotop = 1;
objv++;
objc--;
}
else {
result = CommonParseCell(interp, objv[1], &np, &filenum);
if (result != TCL_OK) return result;
objv++;
objc--;
}
}
if (objc == 1) {
PrintCellHashTable((dolist) ? 2 : 0, -1);
}
else if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "[list] [-all|-top|valid_filename]");
if (objc != 1) {
Tcl_WrongNumArgs(interp, 1, objv, "[list] [-top] [-all] [valid_filename]");
return TCL_ERROR;
}
else {
Tcl_Obj *lobj;
repstr = Tcl_GetString(objv[1]);
if (!strncmp(repstr, "-top", 4)) {
if (dotop) {
if (dolist)
lobj = Tcl_NewListObj(0, NULL);
else
Fprintf(stdout, "Top level cells: ");
np = FirstCell();
while (np != NULL) {
if (np->flags & CELL_TOP) {
if ((np->flags & CELL_TOP) && ((filenum == -1) ||
(np->file == filenum))) {
if (dolist)
Tcl_ListObjAppendElement(interp, lobj,
Tcl_NewStringObj(np->name, -1));
@@ -1483,11 +1497,13 @@ _netgen_cells(ClientData clientData,
return TCL_OK;
}
else if (strncmp(repstr, "-all", 4)) {
result = CommonParseCell(interp, objv[1], &np, &filenum);
if (result != TCL_OK) return result;
else {
if (dolist)
printopt = (doall) ? 3 : 2;
else
printopt = (doall) ? 1 : 0;
PrintCellHashTable(printopt, filenum);
}
PrintCellHashTable((dolist) ? 2 : 1, filenum);
}
return TCL_OK;
}
@@ -1528,8 +1544,27 @@ _netgen_model(ClientData clientData,
return TCL_ERROR;
}
/* Check for "model blackbox on|off" */
/* Behavior is to treat empty subcircuits as blackbox cells */
if ((objc > 1) && !strcmp(Tcl_GetString(objv[1]), "blackbox")) {
if ((objc > 2) && !strcmp(Tcl_GetString(objv[2]), "on")) {
auto_blackbox = TRUE;
return TCL_OK;
}
else if ((objc > 2) && !strcmp(Tcl_GetString(objv[2]), "off")) {
auto_blackbox = FALSE;
return TCL_OK;
}
else if (objc == 2) {
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(auto_blackbox));
return TCL_OK;
}
}
result = CommonParseCell(interp, objv[1], &tp, &fnum);
if (result != TCL_OK) return result;
if (result != TCL_OK)
return result;
if (objc == 3) {
model = Tcl_GetString(objv[2]);
@@ -1641,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;
@@ -2487,49 +2529,33 @@ _netcmp_verify(ClientData clientData,
if (dolist)
{
if (objc == 1 || index == NODE_IDX || index == ALL_IDX) {
if (nbad == NULL) {
Tcl_Obj *n0, *n1;
nbad = Tcl_NewListObj(0, NULL);
n0 = Tcl_NewStringObj("badnets", -1);
n1 = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(netgeninterp, nbad, n0);
Tcl_ListObjAppendElement(netgeninterp, nbad, n1);
}
if (nbad == NULL) nbad = Tcl_NewListObj(0, NULL);
Tcl_SetVar2Ex(interp, "lvs_out", NULL,
Tcl_NewStringObj("badnets", -1),
TCL_APPEND_VALUE | TCL_LIST_ELEMENT);
Tcl_SetVar2Ex(interp, "lvs_out", NULL, nbad,
TCL_APPEND_VALUE | TCL_LIST_ELEMENT);
#if 0
if (ngood == NULL) {
Tcl_Obj *n0, *n1;
ngood = Tcl_NewListObj(0, NULL);
n0 = Tcl_NewStringObj("goodnets", -1);
n1 = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(netgeninterp, ngood, n0);
Tcl_ListObjAppendElement(netgeninterp, ngood, n1);
}
if (ngood == NULL) ngood = Tcl_NewListObj(0, NULL);
Tcl_SetVar2Ex(interp, "lvs_out", NULL,
Tcl_NewStringObj("goodnets", -1),
TCL_APPEND_VALUE | TCL_LIST_ELEMENT);
Tcl_SetVar2Ex(interp, "lvs_out", NULL, ngood,
TCL_APPEND_VALUE | TCL_LIST_ELEMENT);
#endif
}
if (objc == 1 || index == ELEM_IDX || index == ALL_IDX) {
if (ebad == NULL) {
Tcl_Obj *e0, *e1;
ebad = Tcl_NewListObj(0, NULL);
e0 = Tcl_NewStringObj("badelements", -1);
e1 = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(netgeninterp, ebad, e0);
Tcl_ListObjAppendElement(netgeninterp, ebad, e1);
}
if (ebad == NULL) ebad = Tcl_NewListObj(0, NULL);
Tcl_SetVar2Ex(interp, "lvs_out", NULL,
Tcl_NewStringObj("badelements", -1),
TCL_APPEND_VALUE | TCL_LIST_ELEMENT);
Tcl_SetVar2Ex(interp, "lvs_out", NULL, ebad,
TCL_APPEND_VALUE | TCL_LIST_ELEMENT);
#if 0
if (egood == NULL) {
Tcl_Obj *e0, *e1;
ebad = Tcl_NewListObj(0, NULL);
e0 = Tcl_NewStringObj("goodelements", -1);
e1 = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(netgeninterp, egood, e0);
Tcl_ListObjAppendElement(netgeninterp, egood, e1);
}
if (egood == NULL) egood = Tcl_NewListObj(0, NULL);
Tcl_SetVar2Ex(interp, "lvs_out", NULL,
Tcl_NewStringObj("goodelements", -1),
TCL_APPEND_VALUE | TCL_LIST_ELEMENT);
Tcl_SetVar2Ex(interp, "lvs_out", NULL, egood,
TCL_APPEND_VALUE | TCL_LIST_ELEMENT);
#endif
@@ -2694,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) {
@@ -2865,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",
@@ -2873,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;
@@ -3109,8 +3145,12 @@ _netcmp_equate(ClientData clientData,
/* netgen::property <device>|<model> <option> */
/* yes|no */
/* Where <option> is one of: */
/* serial --- allow/prohibit serial combination */
/* serial --- allow/prohibit serial combination */
/* parallel --- allow/prohibit parallel combination */
/* or */
/* netgen::property parallel none */
/* --- prohibit parallel combinations by */
/* default. */
/* */
/* Formerly: (none) */
/* Results: */
@@ -3204,6 +3244,22 @@ _netcmp_property(ClientData clientData,
}
return TCL_OK;
}
else if ((objc == 3) && (!strcmp(Tcl_GetString(objv[1]), "parallel"))) {
if (!strcmp(Tcl_GetString(objv[2]), "none")) {
GlobalParallelNone = TRUE;
SetParallelCombine(FALSE);
}
else if (!strcmp(Tcl_GetString(objv[2]), "all")) {
GlobalParallelNone = FALSE;
SetParallelCombine(TRUE);
}
else {
Tcl_SetResult(interp, "Bad option, should be property parallel none|all",
NONE);
return TCL_ERROR;
}
return TCL_OK;
}
result = CommonParseCell(interp, objv[1], &tp, &fnum);
if (result != TCL_OK) return result;