Compare commits

...
10 Commits
Author SHA1 Message Date
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
5 changed files with 530 additions and 164 deletions
+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.73
+167 -125
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,8 +5073,6 @@ 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
@@ -5063,8 +5093,11 @@ PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print,
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 {
@@ -6245,7 +6283,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 +6312,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 +6356,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 +6375,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 +6413,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 +6458,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);
@@ -6462,8 +6500,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);
@@ -6509,8 +6547,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);
@@ -6738,9 +6776,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;
+340 -1
View File
@@ -26,6 +26,337 @@ 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 " \],"
}
}
if {$gidx == $glen} {
puts $fjson " \]"
} else {
puts $fjson " \],"
}
}
if {$glen > 0} {
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 " \],"
}
}
if {$gidx == $glen} {
puts $fjson " \]"
} else {
puts $fjson " \],"
}
}
if {$glen > 0} {
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 prop0 [lindex $property 0]
set propname [lindex $prop0 0]
set propval [lindex $prop0 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 +373,18 @@ if {${tcl_version} >= 8.6} {
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"
set dolist 1
set lvs_final {}
} elseif {$arg == "-json"} {
puts stdout "Generating JSON file result"
set dolist 1
set dojson 1
set lvs_final {}
}
}
@@ -229,7 +566,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
}
}
+16 -32
View File
@@ -2487,49 +2487,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