mirror of
https://github.com/RTimothyEdwards/netgen.git
synced 2026-08-22 14:07:07 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7b0bdd29e8 | ||
|
|
3892529873 | ||
|
|
e3b51c6004 | ||
|
|
3200b1bf95 | ||
|
|
814652e552 | ||
|
|
433cbd090a | ||
|
|
3087bd3337 | ||
|
|
4d138b64ca | ||
|
|
b79a29d662 | ||
|
|
bf9c61e412 | ||
|
|
9a2902abbb | ||
|
|
8d34bd372d | ||
|
|
229c2931a8 | ||
|
|
840f997133 | ||
|
|
b8da97deb1 | ||
|
|
b7187d5899 | ||
|
|
cb3cf592e8 | ||
|
|
b1d40e6d12 | ||
|
|
edbefbd1c4 | ||
|
|
d27d441c58 | ||
|
|
48c9e6b292 | ||
|
|
527cdb3dab | ||
|
|
ced5846da3 | ||
|
|
b99d33064f | ||
|
|
ee66c00121 | ||
|
|
f40a50d3b8 | ||
|
|
399472e940 | ||
|
|
8e0371e09b | ||
|
|
395f857a82 | ||
|
|
9e59048731 | ||
|
|
7889e2ae73 | ||
|
|
8c7d2ae239 | ||
|
|
e361640947 | ||
|
|
56b4174646 | ||
|
|
ccf2dc23c9 | ||
|
|
f8ea27d8e8 | ||
|
|
ef914e8d46 | ||
|
|
f9cc4d3db6 | ||
|
|
d8eefdad9a | ||
|
|
2cdf3c450f | ||
|
|
079e0ab5d3 | ||
|
|
f0cf6b52d3 | ||
|
|
9432bfc182 | ||
|
|
4fb892a64f | ||
|
|
faadb78870 | ||
|
|
7fc668c2d4 | ||
|
|
13c45c6d0c | ||
|
|
5efe2151ed | ||
|
|
642de57418 | ||
|
|
397444acd3 | ||
|
|
5e5720e7be | ||
|
|
65c0f6b840 | ||
|
|
09b2bb3316 | ||
|
|
41665036e9 | ||
|
|
b4c189a114 | ||
|
|
85af816ab8 | ||
|
|
4ba5425b6a | ||
|
|
83b2084a10 | ||
|
|
0de1c232e4 | ||
|
|
b8e6f6c030 | ||
|
|
a6742bca2e | ||
|
|
3a03e769af | ||
|
|
445f732f8b | ||
|
|
b911aa7b2e | ||
|
|
b979d0ad97 | ||
|
|
86ab771964 | ||
|
|
2d74b3d94b | ||
|
|
036e1f0947 | ||
|
|
5223011330 | ||
|
|
7bde5125fd | ||
|
|
dd6145463e | ||
|
|
f4ff74783c | ||
|
|
f3d850e68e | ||
|
|
1c08e5a48d | ||
|
|
821145f9c1 | ||
|
|
6eb1efd55a | ||
|
|
6d569ca396 | ||
|
|
7a0bff846f | ||
|
|
ced1299351 | ||
|
|
f213376bfd | ||
|
|
223b197b71 | ||
|
|
f0eb14be5e | ||
|
|
534ea839c0 | ||
|
|
b721cacb40 | ||
|
|
84f984e7f0 | ||
|
|
25ac57d103 | ||
|
|
02a77b61f9 | ||
|
|
dfd1e59432 | ||
|
|
f14ebf323f | ||
|
|
62648c5672 | ||
|
|
7d113beada | ||
|
|
1fe341833c | ||
|
|
aee4b846e2 | ||
|
|
004378be11 | ||
|
|
dc42e98ab9 | ||
|
|
58d7e17231 | ||
|
|
de30eeabe8 | ||
|
|
feab5023e5 | ||
|
|
4d65b0006d | ||
|
|
eefdb61e14 | ||
|
|
1d1ad3c833 | ||
|
|
4166408576 | ||
|
|
2b15b731bb | ||
|
|
9ad6ad3338 | ||
|
|
0fb5efd914 | ||
|
|
763117aabe | ||
|
|
96a95d337f | ||
|
|
393788a039 | ||
|
|
c630c2e397 | ||
|
|
1e8685128c | ||
|
|
440f61d540 | ||
|
|
cc532b2cb7 | ||
|
|
2a4c7b3cde | ||
|
|
87e44b0d8c | ||
|
|
e1322dbaf6 | ||
|
|
661157e041 | ||
|
|
77e5d70626 | ||
|
|
4098b7d5fd | ||
|
|
f860244700 | ||
|
|
66015511cb | ||
|
|
b3277ca53e | ||
|
|
00c2e74524 | ||
|
|
bdb8917327 | ||
|
|
95bce5dbd6 | ||
|
|
e15620257c | ||
|
|
7a947ee9be | ||
|
|
b5f188de42 | ||
|
|
ccbb286cf3 | ||
|
|
4809c02f79 | ||
|
|
af3982766e | ||
|
|
25c1f13e16 | ||
|
|
f0eec657a3 | ||
|
|
9d476bc25a | ||
|
|
5ed3fcb3f1 | ||
|
|
ab9659af17 | ||
|
|
41939adb84 | ||
|
|
39573981be | ||
|
|
b9e26f6fce | ||
|
|
78779ce2e9 | ||
|
|
70bb33cc62 | ||
|
|
fdf2f32654 | ||
|
|
05d4225e97 | ||
|
|
b6218699a9 | ||
|
|
d7927ef547 | ||
|
|
af7bc39bbf | ||
|
|
5cd68b9ef1 | ||
|
|
07788e7501 | ||
|
|
24cc7d0c94 | ||
|
|
dbcd36d3ec | ||
|
|
25c17abb70 | ||
|
|
fd019b4afd | ||
|
|
cdfd74bac4 | ||
|
|
dd9e02c5f3 | ||
|
|
26cd16f3ff | ||
|
|
ccdd47bc0b |
+3
-2
@@ -1,13 +1,14 @@
|
||||
netgen
|
||||
netgenexec
|
||||
defs.mak
|
||||
Depend
|
||||
scripts/defs.mak
|
||||
config.cache
|
||||
config.log
|
||||
scripts/config.log
|
||||
config.status
|
||||
scripts/config.status
|
||||
*.o
|
||||
*.so
|
||||
*~
|
||||
*.log
|
||||
UPDATE_ME
|
||||
VERSION
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#
|
||||
|
||||
NETGENDIR = .
|
||||
PROGRAMS = netgen
|
||||
PROGRAMS = netgen python
|
||||
MODULES = base
|
||||
|
||||
MAKEFLAGS =
|
||||
@@ -60,11 +60,11 @@ install-real: install-dirs
|
||||
(cd $$dir && ${MAKE} install); done
|
||||
|
||||
install-tcl-dirs:
|
||||
${NETGENDIR}/scripts/mkdirs $(DESTDIR)${BINDIR} $(DESTDIR)${MANDIR} \
|
||||
$(DESTDIR)${TCLDIR}
|
||||
${NETGENDIR}/scripts/mkdirs $(DESTDIR)${BINDIR} \
|
||||
$(DESTDIR)${TCLDIR} $(DESTDIR)${PYDIR}
|
||||
|
||||
install-dirs:
|
||||
${NETGENDIR}/scripts/mkdirs $(DESTDIR)${BINDIR} $(DESTDIR)${MANDIR}
|
||||
${NETGENDIR}/scripts/mkdirs $(DESTDIR)${BINDIR}
|
||||
|
||||
install-tcl: install-dirs
|
||||
@echo --- installing executable to $(DESTDIR)${BINDIR}
|
||||
@@ -78,6 +78,7 @@ install-tcl-real: install-tcl-dirs
|
||||
clean:
|
||||
for dir in ${MODULES} ${PROGRAMS} ${UNUSED_MODULES}; do \
|
||||
(cd $$dir && ${MAKE} clean); done
|
||||
${RM} *.tmp */*.tmp *.sav */*.sav *.log TAGS tags
|
||||
|
||||
distclean:
|
||||
touch defs.mak
|
||||
|
||||
@@ -78,13 +78,15 @@ of CVS check-in notes on http://opencircuitdesign.com/netgen/.
|
||||
|
||||
BUILDING NETGEN:
|
||||
----------------
|
||||
NETGEN version 1.4 uses the same "make" procedure as Magic version 7.5
|
||||
NETGEN version 1.5 uses the same "make" procedure as Magic version 8.1
|
||||
and IRSIM version 9.7:
|
||||
|
||||
./configure
|
||||
make
|
||||
make install
|
||||
|
||||
Note: For FreeBSD, use 'gmake' instead.
|
||||
|
||||
IN CASE OF FAILURE
|
||||
-------------------
|
||||
Please contact me ([email protected]) to report compile-time and
|
||||
|
||||
@@ -6,33 +6,24 @@ TO_DO list for version 1.5
|
||||
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) (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
|
||||
5) Extend 2-terminal device handling (namely R and C) to more formats
|
||||
1) Add automatic file format guessing from file extension for "write" command
|
||||
2) Incorporate into Tcl-based xcircuit
|
||||
3) Extend 2-terminal device handling (namely R and C) to more formats
|
||||
(where appropriate).
|
||||
6) Generate feedback in the form of a .mag file to facilitate interactive
|
||||
4) Generate feedback in the form of a .mag file to facilitate interactive
|
||||
netlist comparison in conjunction with magic. This may be an error
|
||||
file, but it may also make use of magic 7.2's "element" command to
|
||||
build rat's nests or outline areas of interest or anything else that
|
||||
might be helpful to interactive comparison.
|
||||
7) Improve upon the readability of the netlist comparator output.
|
||||
In particular, pinpoint situations in which an error does not show
|
||||
up in an obvious way in either the element or node lists.
|
||||
8) Handle the hierarchy of ".ext" files automatically.
|
||||
9) Retain position information from ".ext" files for the purpose of writing
|
||||
5) Handle the hierarchy of ".ext" files automatically.
|
||||
6) Retain position information from ".ext" files for the purpose of writing
|
||||
feedback information into magic and for matching devices in the element
|
||||
list to their counterparts in the original layout [note---done for .sim
|
||||
format, which contains position information. Usefulness of improving
|
||||
the .ext parsing is questionable. Ditto for item 8].
|
||||
10) Expand upon the details of format-to-format translation, (especially
|
||||
7) Expand upon the details of format-to-format translation, (especially
|
||||
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
|
||||
8) 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
@@ -3,7 +3,7 @@ NETGENDIR = ..
|
||||
SRCS = actel.c ccode.c greedy.c ntk.c print.c actellib.c embed.c \
|
||||
hash.c netfile.c objlist.c query.c anneal.c ext.c netcmp.c netgen.c \
|
||||
pdutils.c random.c timing.c bottomup.c flatten.c place.c spice.c \
|
||||
wombat.c xilinx.c xillib.c
|
||||
verilog.c wombat.c xilinx.c xillib.c
|
||||
X11_SRCS = xnetgen.c
|
||||
|
||||
include ${NETGENDIR}/defs.mak
|
||||
|
||||
@@ -31,6 +31,10 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef TCL_NETGEN
|
||||
#include <tcl.h>
|
||||
#endif
|
||||
|
||||
#include "netgen.h"
|
||||
#include "hash.h"
|
||||
#include "objlist.h"
|
||||
|
||||
+134
-134
@@ -196,16 +196,16 @@ char *ReadExt(char *fname, int doflat, int *fnum)
|
||||
}
|
||||
|
||||
while (!EndParseFile()) {
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
|
||||
if (EndParseFile()) break;
|
||||
if (nexttok[0] == '#') SkipNewLine();
|
||||
else if (match(nexttok, "timestamp")) SkipNewLine();
|
||||
else if (match(nexttok, "version")) SkipNewLine();
|
||||
else if (match(nexttok, "tech")) SkipNewLine();
|
||||
else if (match(nexttok, "scale")) SkipNewLine();
|
||||
else if (match(nexttok, "style")) SkipNewLine();
|
||||
else if (match(nexttok, "resistclasses")) SkipNewLine();
|
||||
if (nexttok[0] == '#') SkipNewLine(NULL);
|
||||
else if (match(nexttok, "timestamp")) SkipNewLine(NULL);
|
||||
else if (match(nexttok, "version")) SkipNewLine(NULL);
|
||||
else if (match(nexttok, "tech")) SkipNewLine(NULL);
|
||||
else if (match(nexttok, "scale")) SkipNewLine(NULL);
|
||||
else if (match(nexttok, "style")) SkipNewLine(NULL);
|
||||
else if (match(nexttok, "resistclasses")) SkipNewLine(NULL);
|
||||
else if (match(nexttok, "node")) {
|
||||
char name[200];
|
||||
|
||||
@@ -216,122 +216,122 @@ char *ReadExt(char *fname, int doflat, int *fnum)
|
||||
CellDef(fname, filenum);
|
||||
CellDefInProgress = 1;
|
||||
}
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(name, nexttok);
|
||||
Node(name); /* Ports will be determined by context */
|
||||
SkipNewLine();
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
else if (match(nexttok, "equiv")) {
|
||||
char name[200];
|
||||
char name2[200];
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(name, nexttok);
|
||||
if (LookupObject(name,CurrentCell) == NULL) Node(name);
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(name2, nexttok);
|
||||
if (LookupObject(name2,CurrentCell) == NULL) Node(name2);
|
||||
join(name, name2);
|
||||
SkipNewLine();
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
else if (match(nexttok, "device")) {
|
||||
char dev_name[100], dev_class[100];
|
||||
char gate[200], drain[200], source[200], subs[200];
|
||||
char inststr[64];
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
strcpy(dev_class, nexttok);
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
strcpy(dev_name, nexttok);
|
||||
SkipTok(); /* x coord of gate box */
|
||||
SkipTok(NULL); /* x coord of gate box */
|
||||
strcpy(inststr, dev_class);
|
||||
strcat(inststr, "@");
|
||||
strcat(inststr, nexttok);
|
||||
SkipTok(); /* y coord of gate box */
|
||||
SkipTok(NULL); /* y coord of gate box */
|
||||
strcat(inststr, ",");
|
||||
strcat(inststr, nexttok);
|
||||
SkipTok(); /* skip coord of gate box */
|
||||
SkipTok(); /* skip coord of gate box */
|
||||
SkipTok(NULL); /* skip coord of gate box */
|
||||
SkipTok(NULL); /* skip coord of gate box */
|
||||
|
||||
/* Device-dependent parameters */
|
||||
|
||||
if (match(dev_class, "mosfet")) {
|
||||
SkipTok(); /* skip device length */
|
||||
SkipTok(); /* skip device width */
|
||||
SkipTok();
|
||||
SkipTok(NULL); /* skip device length */
|
||||
SkipTok(NULL); /* skip device width */
|
||||
SkipTok(NULL);
|
||||
GetExtName(subs, nexttok);
|
||||
}
|
||||
else if (match(dev_class, "bjt")) {
|
||||
SkipTok(); /* skip device length */
|
||||
SkipTok(); /* skip device width */
|
||||
SkipTok();
|
||||
SkipTok(NULL); /* skip device length */
|
||||
SkipTok(NULL); /* skip device width */
|
||||
SkipTok(NULL);
|
||||
GetExtName(subs, nexttok);
|
||||
}
|
||||
else if (match(dev_class, "devcap")) {
|
||||
SkipTok(); /* skip device length */
|
||||
SkipTok(); /* skip device width */ /* or. . . */
|
||||
SkipTok(NULL); /* skip device length */
|
||||
SkipTok(NULL); /* skip device width */ /* or. . . */
|
||||
}
|
||||
else if (match(dev_class, "devres")) {
|
||||
SkipTok(); /* skip device length */
|
||||
SkipTok(); /* skip device width */ /* or. . . */
|
||||
SkipTok(NULL); /* skip device length */
|
||||
SkipTok(NULL); /* skip device width */ /* or. . . */
|
||||
}
|
||||
else if (match(dev_class, "diode")) {
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(gate, nexttok);
|
||||
SkipTok(); /* skip terminal length */
|
||||
SkipTok(); /* skip terminal attributes */
|
||||
SkipTok();
|
||||
SkipTok(NULL); /* skip terminal length */
|
||||
SkipTok(NULL); /* skip terminal attributes */
|
||||
SkipTok(NULL);
|
||||
GetExtName(drain, nexttok);
|
||||
SkipTok(); /* skip terminal length */
|
||||
SkipTok(); /* skip terminal attributes */
|
||||
SkipTok(NULL); /* skip terminal length */
|
||||
SkipTok(NULL); /* skip terminal attributes */
|
||||
}
|
||||
else if (match(dev_class, "subckt")) {
|
||||
SkipTok(); /* skip device length */
|
||||
SkipTok(); /* skip device width */
|
||||
SkipTok();
|
||||
SkipTok(NULL); /* skip device length */
|
||||
SkipTok(NULL); /* skip device width */
|
||||
SkipTok(NULL);
|
||||
GetExtName(subs, nexttok);
|
||||
while (nexttok != NULL) {
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(gate, nexttok);
|
||||
SkipTok(); /* skip terminal length */
|
||||
SkipTok(); /* skip terminal attributes */
|
||||
SkipTok(NULL); /* skip terminal length */
|
||||
SkipTok(NULL); /* skip terminal attributes */
|
||||
}
|
||||
}
|
||||
else if (match(dev_class, "rsubckt")) {
|
||||
SkipTok(); /* skip device length */
|
||||
SkipTok(); /* skip device width */
|
||||
SkipTok();
|
||||
SkipTok(NULL); /* skip device length */
|
||||
SkipTok(NULL); /* skip device width */
|
||||
SkipTok(NULL);
|
||||
GetExtName(subs, nexttok);
|
||||
}
|
||||
SkipTokNoNewline();
|
||||
SkipNewLine();
|
||||
SkipTokNoNewline(NULL);
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
else if (match(nexttok, "fet")) { /* old-style FET record */
|
||||
char fet_class[100];
|
||||
char gate[200], drain[200], source[200], subs[200];
|
||||
char inststr[64];
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
strcpy(fet_class, nexttok);
|
||||
SkipTok(); /* x coord of gate box */
|
||||
SkipTok(NULL); /* x coord of gate box */
|
||||
strcpy(inststr, fet_class);
|
||||
strcat(inststr, "@");
|
||||
strcat(inststr, nexttok);
|
||||
SkipTok(); /* y coord of gate box */
|
||||
SkipTok(NULL); /* y coord of gate box */
|
||||
strcat(inststr, ",");
|
||||
strcat(inststr, nexttok);
|
||||
SkipTok(); /* skip coord of gate box */
|
||||
SkipTok(); /* skip coord of gate box */
|
||||
SkipTok(); /* skip gate area */
|
||||
SkipTok(); /* skip gate perimeter */
|
||||
SkipTok();
|
||||
SkipTok(NULL); /* skip coord of gate box */
|
||||
SkipTok(NULL); /* skip coord of gate box */
|
||||
SkipTok(NULL); /* skip gate area */
|
||||
SkipTok(NULL); /* skip gate perimeter */
|
||||
SkipTok(NULL);
|
||||
GetExtName(subs, nexttok);
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(gate, nexttok);
|
||||
SkipTok(); /* skip terminal length */
|
||||
SkipTok(); /* skip terminal attributes */
|
||||
SkipTok();
|
||||
SkipTok(NULL); /* skip terminal length */
|
||||
SkipTok(NULL); /* skip terminal attributes */
|
||||
SkipTok(NULL);
|
||||
GetExtName(drain, nexttok);
|
||||
SkipTok(); /* skip terminal length */
|
||||
SkipTok(); /* skip terminal attributes */
|
||||
SkipTokNoNewline();
|
||||
SkipTok(NULL); /* skip terminal length */
|
||||
SkipTok(NULL); /* skip terminal attributes */
|
||||
SkipTokNoNewline(NULL);
|
||||
if (nexttok == NULL) {
|
||||
/* This gets around a problem with the magic extractor in which */
|
||||
/* transistors having shorted source-drain are written into the */
|
||||
@@ -341,7 +341,7 @@ char *ReadExt(char *fname, int doflat, int *fnum)
|
||||
}
|
||||
else
|
||||
GetExtName(source, nexttok);
|
||||
SkipNewLine();
|
||||
SkipNewLine(NULL);
|
||||
/* remap transistors into things we know about */
|
||||
if (match(fet_class, "nfet"))
|
||||
N(fname, inststr, gate, drain, source);
|
||||
@@ -361,15 +361,15 @@ char *ReadExt(char *fname, int doflat, int *fnum)
|
||||
else if (match(nexttok, "cap")) {
|
||||
if (IgnoreRC) {
|
||||
/* ignore all capacitances */
|
||||
SkipNewLine();
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
else {
|
||||
char ctop[200], cbot[200], cdummy[200];
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(ctop, nexttok);
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(cbot, nexttok);
|
||||
SkipNewLine(); /* Skip over capacitance value */
|
||||
SkipNewLine(NULL); /* Skip over capacitance value */
|
||||
Cap(fname, NULL, ctop, cbot);
|
||||
}
|
||||
}
|
||||
@@ -386,14 +386,14 @@ char *ReadExt(char *fname, int doflat, int *fnum)
|
||||
CellDefInProgress = 1;
|
||||
}
|
||||
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(name, nexttok);
|
||||
if ((basename = strrchr(name,'/')) != NULL) {
|
||||
char tmp[200];
|
||||
strcpy(tmp, basename+1);
|
||||
strcpy(name, tmp);
|
||||
}
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(instancename, nexttok);
|
||||
Printf("Instancing %s as %s\n", name, instancename);
|
||||
Instance(name, instancename);
|
||||
@@ -401,14 +401,14 @@ char *ReadExt(char *fname, int doflat, int *fnum)
|
||||
Printf("Flattening %s in %s\n", instancename, fname);
|
||||
flattenInstancesOf(NULL, filenum, name);
|
||||
}
|
||||
SkipNewLine();
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
else if (match(nexttok, "merge")) {
|
||||
char name[200];
|
||||
char name2[200];
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(name, nexttok);
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(name2, nexttok);
|
||||
if (doflat)
|
||||
join(name, name2);
|
||||
@@ -416,12 +416,12 @@ char *ReadExt(char *fname, int doflat, int *fnum)
|
||||
join(name, name2);
|
||||
else {
|
||||
}
|
||||
SkipNewLine();
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
else {
|
||||
Printf("Strange token in ext: '%s'\n", nexttok);
|
||||
InputParseError(stderr);
|
||||
SkipNewLine();
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
}
|
||||
CloseParseFile();
|
||||
@@ -657,189 +657,189 @@ char *ReadSim(char *fname, int *fnum)
|
||||
CellDef(fname, filenum);
|
||||
|
||||
while (!EndParseFile()) {
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
|
||||
if (EndParseFile()) break;
|
||||
if (nexttok[0] == '|') {
|
||||
SkipTok(); /* "units" */
|
||||
SkipTok(NULL); /* "units" */
|
||||
if (!strcmp(nexttok, "units:")) {
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
simscale = strtod(nexttok, NULL);
|
||||
}
|
||||
SkipNewLine();
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
else if (match(nexttok, "n")) {
|
||||
char gate[200], drain[200], source[200];
|
||||
char inststr[25], *instptr = NULL;
|
||||
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(gate, nexttok);
|
||||
if (LookupObject(gate, CurrentCell) == NULL)
|
||||
Node(gate); /* define the node if it does not already exist */
|
||||
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(drain, nexttok);
|
||||
if (LookupObject(drain, CurrentCell) == NULL)
|
||||
Node(drain); /* define the node if it does not already exist */
|
||||
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(source, nexttok);
|
||||
if (LookupObject(source, CurrentCell) == NULL)
|
||||
Node(source); /* define the node if it does not already exist */
|
||||
|
||||
SkipTokNoNewline(); /* length */
|
||||
SkipTokNoNewline(NULL); /* length */
|
||||
if ((nexttok != NULL) && (nexttok[0] != '\0')) {
|
||||
vstr = ScaleStringFloatValue(&nexttok[0], simscale * 1e-8);
|
||||
AddProperty(&kvlist, "length", vstr);
|
||||
SkipTok(); /* width */
|
||||
SkipTok(NULL); /* width */
|
||||
if ((nexttok != NULL) && (nexttok[0] != '\0')) {
|
||||
vstr = ScaleStringFloatValue(&nexttok[0], simscale * 1e-8);
|
||||
AddProperty(&kvlist, "width", vstr);
|
||||
}
|
||||
SkipTokNoNewline();
|
||||
SkipTokNoNewline(NULL);
|
||||
if (nexttok != NULL) {
|
||||
if (StrIsInt(nexttok)) {
|
||||
strcpy(inststr, "n@");
|
||||
strcat(inststr, nexttok);
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
strcat(inststr, ",");
|
||||
strcat(inststr, nexttok);
|
||||
instptr = inststr;
|
||||
}
|
||||
}
|
||||
}
|
||||
SkipNewLine(); /* skip any attributes */
|
||||
SkipNewLine(NULL); /* skip any attributes */
|
||||
N(fname, instptr, gate, drain, source);
|
||||
LinkProperties("n", kvlist);
|
||||
}
|
||||
else if (match(nexttok, "p")) {
|
||||
char gate[200], drain[200], source[200];
|
||||
char inststr[25], *instptr = NULL;
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(gate, nexttok);
|
||||
if (LookupObject(gate, CurrentCell) == NULL)
|
||||
Node(gate); /* define the node if it does not already exist */
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(drain, nexttok);
|
||||
if (LookupObject(drain, CurrentCell) == NULL)
|
||||
Node(drain); /* define the node if it does not already exist */
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(source, nexttok);
|
||||
if (LookupObject(source, CurrentCell) == NULL)
|
||||
Node(source); /* define the node if it does not already exist */
|
||||
SkipTokNoNewline(); /* length */
|
||||
SkipTokNoNewline(NULL); /* length */
|
||||
if ((nexttok != NULL) && (nexttok[0] != '\0')) {
|
||||
vstr = ScaleStringFloatValue(&nexttok[0], simscale * 1e-8);
|
||||
AddProperty(&kvlist, "length", vstr);
|
||||
SkipTok(); /* width */
|
||||
SkipTok(NULL); /* width */
|
||||
if ((nexttok != NULL) && (nexttok[0] != '\0')) {
|
||||
vstr = ScaleStringFloatValue(&nexttok[0], simscale * 1e-8);
|
||||
AddProperty(&kvlist, "width", vstr);
|
||||
}
|
||||
SkipTokNoNewline();
|
||||
SkipTokNoNewline(NULL);
|
||||
if (nexttok != NULL) {
|
||||
if (StrIsInt(nexttok)) {
|
||||
strcpy(inststr, "p@");
|
||||
strcat(inststr, nexttok);
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
strcat(inststr, ",");
|
||||
strcat(inststr, nexttok);
|
||||
instptr = inststr;
|
||||
}
|
||||
}
|
||||
}
|
||||
SkipNewLine(); /* skip various attributes */
|
||||
SkipNewLine(NULL); /* skip various attributes */
|
||||
P(fname, instptr, gate, drain, source);
|
||||
LinkProperties("p", kvlist);
|
||||
}
|
||||
else if (match(nexttok, "e")) { /* 3-port capacitors (poly/poly2) */
|
||||
char gate[200], drain[200], source[200];
|
||||
char inststr[25], *instptr = NULL;
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(gate, nexttok);
|
||||
if (LookupObject(gate, CurrentCell) == NULL)
|
||||
Node(gate); /* define the node if it does not already exist */
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(drain, nexttok);
|
||||
if (LookupObject(drain, CurrentCell) == NULL)
|
||||
Node(drain); /* define the node if it does not already exist */
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(source, nexttok);
|
||||
if (LookupObject(source, CurrentCell) == NULL)
|
||||
Node(source); /* define the node if it does not already exist */
|
||||
SkipTokNoNewline(); /* skip length */
|
||||
SkipTokNoNewline(NULL); /* skip length */
|
||||
if (nexttok != NULL) {
|
||||
SkipTok(); /* skip width */
|
||||
SkipTokNoNewline();
|
||||
SkipTok(NULL); /* skip width */
|
||||
SkipTokNoNewline(NULL);
|
||||
inststr[0] = '\0';
|
||||
if (nexttok != NULL) {
|
||||
if (StrIsInt(nexttok)) {
|
||||
strcpy(inststr, "e@");
|
||||
strcat(inststr, nexttok);
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
strcat(inststr, ",");
|
||||
strcat(inststr, nexttok);
|
||||
instptr = inststr;
|
||||
}
|
||||
}
|
||||
}
|
||||
SkipNewLine(); /* skip various attributes */
|
||||
SkipNewLine(NULL); /* skip various attributes */
|
||||
E(fname, instptr, gate, drain, source);
|
||||
}
|
||||
else if (match(nexttok, "b")) { /* bipolars added by Tim 7/16/96 */
|
||||
char base[200], emitter[200], collector[200];
|
||||
char inststr[25], *instptr = NULL;
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(base, nexttok);
|
||||
if (LookupObject(base, CurrentCell) == NULL)
|
||||
Node(base); /* define the node if it does not already exist */
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(emitter, nexttok);
|
||||
if (LookupObject(emitter, CurrentCell) == NULL)
|
||||
Node(emitter); /* define the node if it does not already exist */
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(collector, nexttok);
|
||||
if (LookupObject(collector, CurrentCell) == NULL)
|
||||
Node(collector); /* define the node if it does not already exist */
|
||||
SkipTokNoNewline(); /* skip length */
|
||||
SkipTokNoNewline(NULL); /* skip length */
|
||||
if (nexttok != NULL) {
|
||||
SkipTok(); /* skip width */
|
||||
SkipTokNoNewline();
|
||||
SkipTok(NULL); /* skip width */
|
||||
SkipTokNoNewline(NULL);
|
||||
if (nexttok != NULL) {
|
||||
if (StrIsInt(nexttok)) {
|
||||
strcpy(inststr, "b@");
|
||||
strcat(inststr, nexttok);
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
strcat(inststr, ",");
|
||||
strcat(inststr, nexttok);
|
||||
instptr = inststr;
|
||||
}
|
||||
}
|
||||
}
|
||||
SkipNewLine(); /* skip various attributes */
|
||||
SkipNewLine(NULL); /* skip various attributes */
|
||||
B(fname, instptr, collector, base, emitter);
|
||||
}
|
||||
else if (matchnocase(nexttok, "c")) { /* 2-port capacitors */
|
||||
if (IgnoreRC) {
|
||||
/* ignore all capacitances */
|
||||
SkipNewLine();
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
else {
|
||||
char ctop[200], cbot[200], cdummy[200];
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(ctop, nexttok);
|
||||
if (LookupObject(ctop, CurrentCell) == NULL)
|
||||
Node(ctop); /* define the node if it does not already exist */
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(cbot, nexttok);
|
||||
if (LookupObject(cbot, CurrentCell) == NULL)
|
||||
Node(cbot); /* define the node if it does not already exist */
|
||||
SkipTokNoNewline();
|
||||
SkipTokNoNewline(NULL);
|
||||
if (nexttok != NULL) {
|
||||
vstr = ScaleStringFloatValue(&nexttok[0], 1e-15);
|
||||
AddProperty(&kvlist, "value", vstr);
|
||||
}
|
||||
SkipNewLine();
|
||||
SkipNewLine(NULL);
|
||||
Cap(fname, NULL, ctop, cbot);
|
||||
LinkProperties("c", kvlist);
|
||||
}
|
||||
@@ -847,23 +847,23 @@ char *ReadSim(char *fname, int *fnum)
|
||||
else if (match(nexttok, "r")) { /* 2-port resistors */
|
||||
if (IgnoreRC) {
|
||||
/* ignore all capacitances */
|
||||
SkipNewLine();
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
else {
|
||||
char rtop[200], rbot[200];
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(rtop, nexttok);
|
||||
if (LookupObject(rtop, CurrentCell) == NULL)
|
||||
Node(rtop); /* define the node if it does not already exist */
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(rbot, nexttok);
|
||||
if (LookupObject(rbot, CurrentCell) == NULL)
|
||||
Node(rbot); /* define the node if it does not already exist */
|
||||
SkipTokNoNewline();
|
||||
SkipTokNoNewline(NULL);
|
||||
if (nexttok != NULL) {
|
||||
AddProperty(&kvlist, "value", &nexttok[0]);
|
||||
}
|
||||
SkipNewLine(); /* skip various attributes */
|
||||
SkipNewLine(NULL); /* skip various attributes */
|
||||
Res(fname, NULL, rtop, rbot);
|
||||
LinkProperties("r", kvlist);
|
||||
}
|
||||
@@ -871,55 +871,55 @@ char *ReadSim(char *fname, int *fnum)
|
||||
else if (match(nexttok, "z")) { /* 3-port resistors from magic */
|
||||
if (IgnoreRC) {
|
||||
/* ignore all capacitances */
|
||||
SkipNewLine();
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
else {
|
||||
char rtop[200], rbot[200], rdummy[200];
|
||||
char inststr[25], *instptr = NULL;
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(rdummy, nexttok);
|
||||
if (LookupObject(rdummy, CurrentCell) == NULL)
|
||||
Node(rdummy); /* define the node if it does not already exist */
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(rtop, nexttok);
|
||||
if (LookupObject(rtop, CurrentCell) == NULL)
|
||||
Node(rtop); /* define the node if it does not already exist */
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(rbot, nexttok);
|
||||
if (LookupObject(rbot, CurrentCell) == NULL)
|
||||
Node(rbot); /* define the node if it does not already exist */
|
||||
SkipTokNoNewline(); /* skip length */
|
||||
SkipTokNoNewline(NULL); /* skip length */
|
||||
if (nexttok != NULL) {
|
||||
SkipTok(); /* skip width */
|
||||
SkipTokNoNewline();
|
||||
SkipTok(NULL); /* skip width */
|
||||
SkipTokNoNewline(NULL);
|
||||
if (nexttok != NULL) {
|
||||
if (StrIsInt(nexttok)) {
|
||||
strcpy(inststr, "z@");
|
||||
strcat(inststr, nexttok);
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
strcat(inststr, ",");
|
||||
strcat(inststr, nexttok);
|
||||
instptr = inststr;
|
||||
}
|
||||
}
|
||||
}
|
||||
SkipNewLine(); /* skip various attributes */
|
||||
SkipNewLine(NULL); /* skip various attributes */
|
||||
Res3(fname, instptr, rdummy, rtop, rbot);
|
||||
}
|
||||
}
|
||||
else if (match(nexttok, "N")) {
|
||||
/* ignore this keyword */
|
||||
SkipNewLine();
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
else if (match(nexttok, "A")) {
|
||||
/* ignore this keyword */
|
||||
SkipNewLine();
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
else if (match(nexttok, "=")) {
|
||||
char node1[200], node2[200];
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(node1, nexttok);
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
GetExtName(node2, nexttok);
|
||||
join(node1, node2);
|
||||
}
|
||||
@@ -928,12 +928,12 @@ char *ReadSim(char *fname, int *fnum)
|
||||
Printf("Ignoring lumped resistances (\"R\" records) in .sim.\n");
|
||||
has_lumped = 1; /* Don't print this message more than once */
|
||||
}
|
||||
SkipNewLine();
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
else {
|
||||
Printf("Strange token in .sim: '%s'\n", nexttok);
|
||||
InputParseError(stderr);
|
||||
SkipNewLine();
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
DeleteProperties(&kvlist);
|
||||
}
|
||||
|
||||
+34
-22
@@ -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) {
|
||||
@@ -1381,7 +1391,7 @@ SurveyCell(struct nlist *tc, struct hashdict *compdict, int file1, int file2, in
|
||||
/* */
|
||||
/* If there is a mismatch between instances of low- */
|
||||
/* level devices, determine if the mismatches can be */
|
||||
/* resolved by parallel/serial combining, according to */
|
||||
/* resolved by parallel/series combining, according to */
|
||||
/* combination rules. */
|
||||
/* */
|
||||
/* Return the number of modifications made. */
|
||||
@@ -1407,7 +1417,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
else
|
||||
tc2 = LookupCellFile(name2, file2);
|
||||
|
||||
if (tc1 == NULL || tc2 == NULL) return;
|
||||
if (tc1 == NULL || tc2 == NULL) return 0;
|
||||
|
||||
InitializeHashTable(&compdict, OBJHASHSIZE);
|
||||
|
||||
@@ -1649,7 +1659,8 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
ecomp = (ECompare *)HashFirst(&compdict);
|
||||
while (ecomp != NULL) {
|
||||
if ((ecomp->num1 != ecomp->num2) && (ecomp->cell1 != NULL) &&
|
||||
(ecomp->cell1->class == CLASS_RES)) {
|
||||
((ecomp->cell1->class == CLASS_RES) ||
|
||||
(ecomp->cell1->class == CLASS_VSOURCE))) {
|
||||
int node1 = -1, node2 = -1;
|
||||
lob = NULL;
|
||||
for (ob1 = tc1->cell; ob1; ) {
|
||||
@@ -1693,7 +1704,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
if (found) break;
|
||||
}
|
||||
if (found) {
|
||||
Fprintf(stdout, "Removing zero-valued device"
|
||||
Fprintf(stdout, "Removing zero-valued device "
|
||||
"%s from cell %s makes a better match\n",
|
||||
tsub1->name,
|
||||
tc1->name);
|
||||
@@ -1753,7 +1764,8 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
// Repeat the last section for the other circuit
|
||||
|
||||
if ((ecomp->num1 != ecomp->num2) && (ecomp->cell2 != NULL) &&
|
||||
(ecomp->cell2->class == CLASS_RES)) {
|
||||
((ecomp->cell2->class == CLASS_RES) ||
|
||||
(ecomp->cell2->class == CLASS_VSOURCE))) {
|
||||
int node1 = -1, node2 = -1;
|
||||
lob = NULL;
|
||||
for (ob2 = tc2->cell; ob2; ) {
|
||||
@@ -1797,7 +1809,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
if (found) break;
|
||||
}
|
||||
if (found) {
|
||||
Fprintf(stdout, "Removing zero-valued device"
|
||||
Fprintf(stdout, "Removing zero-valued device "
|
||||
"%s from cell %s makes a better match\n",
|
||||
tsub2->name,
|
||||
tc2->name);
|
||||
@@ -1907,7 +1919,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
char *dstr = NULL;
|
||||
tc2 = LookupCellFile(ob2->model.class, ecomp0X->cell2->file);
|
||||
if (tc2->flags & CELL_DUPLICATE) {
|
||||
dstr = strstr(ob1->model.class, "[[");
|
||||
dstr = strstr(ob2->model.class, "[[");
|
||||
if (dstr) *dstr = '\0';
|
||||
}
|
||||
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
|
||||
|
||||
+5
-1
@@ -25,6 +25,10 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include <alloc.h>
|
||||
#endif
|
||||
|
||||
#ifdef TCL_NETGEN
|
||||
#include <tcl.h>
|
||||
#endif
|
||||
|
||||
#include "netgen.h"
|
||||
#include "hash.h"
|
||||
#include "objlist.h"
|
||||
@@ -309,7 +313,7 @@ struct hashlist *HashInt2PtrInstall(char *name, int c, void *ptr,
|
||||
/* destroy a hash table, freeing associated memory */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
void *HashKill(struct hashdict *dict)
|
||||
void HashKill(struct hashdict *dict)
|
||||
{
|
||||
struct hashlist *np, *p;
|
||||
int i;
|
||||
|
||||
@@ -25,6 +25,7 @@ extern struct nlist *RecurseHashTablePointer(struct hashdict *dict,
|
||||
void *pointer);
|
||||
extern void HashDelete(char *name, struct hashdict *dict);
|
||||
extern void HashIntDelete(char *name, int value, struct hashdict *dict);
|
||||
extern void HashKill(struct hashdict *dict);
|
||||
|
||||
|
||||
extern int CountHashTableEntries(struct hashlist *p);
|
||||
|
||||
+597
-313
File diff suppressed because it is too large
Load Diff
-6423
File diff suppressed because it is too large
Load Diff
+5
-1
@@ -36,7 +36,8 @@ extern int EquivalenceNodes(char *name1, int file1, char *name2, int file2);
|
||||
extern int EquivalenceClasses(char *name1, int file1, char *name2, int file2);
|
||||
extern int IgnoreClass(char *name, int file, unsigned char type);
|
||||
extern int MatchPins(struct nlist *tp1, struct nlist *tp2, int dolist);
|
||||
extern int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int serial);
|
||||
extern int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run,
|
||||
int series, int comb);
|
||||
|
||||
extern int CreateCompareQueue(char *, int, char *, int);
|
||||
extern int GetCompareQueueTop(char **, int *, char **, int *);
|
||||
@@ -47,6 +48,9 @@ extern void PrintIllegalClasses();
|
||||
extern void PrintIllegalNodeClasses();
|
||||
extern void PrintIllegalElementClasses();
|
||||
|
||||
extern void DumpNetwork(struct objlist *ob, int cidx);
|
||||
extern void DumpNetworkAll(char *name, int file);
|
||||
|
||||
#ifdef TCL_NETGEN
|
||||
extern int EquivalentNode();
|
||||
extern int EquivalentElement();
|
||||
|
||||
+238
-24
@@ -175,7 +175,7 @@ void CloseFile(char *filename)
|
||||
/* STUFF TO READ INPUT FILES */
|
||||
|
||||
static char *line = NULL; /* actual line read in */
|
||||
static char *linetok; /* line copied to this, then munged by strtok */
|
||||
static char *linetok; /* line copied to this, then munged by strdtok */
|
||||
static int linesize = 0; /* amount of memory allocated for line */
|
||||
static int linenum;
|
||||
char *nexttok;
|
||||
@@ -191,7 +191,68 @@ struct filestack {
|
||||
|
||||
static struct filestack *OpenFiles = NULL;
|
||||
|
||||
#define TOKEN_DELIMITER " \t\n\r"
|
||||
#define WHITESPACE_DELIMITER " \t\n\r"
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* TrimQuoted() --- */
|
||||
/* Remove spaces from inside single- or double-quoted strings. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
void TrimQuoted(char *line)
|
||||
{
|
||||
char *qstart, *qend, *lptr;
|
||||
int slen;
|
||||
int changed;
|
||||
|
||||
/* Single-quoted entries */
|
||||
changed = TRUE;
|
||||
lptr = line;
|
||||
while (changed)
|
||||
{
|
||||
changed = FALSE;
|
||||
qstart = strchr(lptr, '\'');
|
||||
if (qstart)
|
||||
{
|
||||
qend = strchr(qstart + 1, '\'');
|
||||
if (qend && (qend > qstart)) {
|
||||
slen = strlen(lptr);
|
||||
for (lptr = qstart + 1; lptr < qend; lptr++) {
|
||||
if (*lptr == ' ') {
|
||||
memmove(lptr, lptr + 1, slen);
|
||||
qend--;
|
||||
changed = TRUE;
|
||||
}
|
||||
}
|
||||
lptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Double-quoted entries */
|
||||
changed = TRUE;
|
||||
lptr = line;
|
||||
while (changed)
|
||||
{
|
||||
changed = FALSE;
|
||||
qstart = strchr(lptr, '\"');
|
||||
if (qstart)
|
||||
{
|
||||
qend = strchr(qstart + 1, '\"');
|
||||
if (qend && (qend > qstart)) {
|
||||
slen = strlen(lptr);
|
||||
for (lptr = qstart + 1; lptr < qend; lptr++) {
|
||||
if (*lptr == ' ') {
|
||||
memmove(lptr, lptr + 1, slen);
|
||||
qend--;
|
||||
changed = TRUE;
|
||||
}
|
||||
}
|
||||
lptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* GetNextLineNoNewline() */
|
||||
@@ -202,7 +263,7 @@ static struct filestack *OpenFiles = NULL;
|
||||
/* */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
int GetNextLineNoNewline()
|
||||
int GetNextLineNoNewline(char *delimiter)
|
||||
{
|
||||
char *newbuf;
|
||||
int testc;
|
||||
@@ -233,8 +294,9 @@ int GetNextLineNoNewline()
|
||||
}
|
||||
linenum++;
|
||||
strcpy(linetok, line);
|
||||
TrimQuoted(linetok);
|
||||
|
||||
nexttok = strtok(linetok, TOKEN_DELIMITER);
|
||||
nexttok = strdtok(linetok, WHITESPACE_DELIMITER, delimiter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -243,10 +305,10 @@ int GetNextLineNoNewline()
|
||||
/* valid token. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
void GetNextLine()
|
||||
void GetNextLine(char *delimiter)
|
||||
{
|
||||
do {
|
||||
if (GetNextLineNoNewline() == -1) return;
|
||||
if (GetNextLineNoNewline(delimiter) == -1) return;
|
||||
} while (nexttok == NULL);
|
||||
}
|
||||
|
||||
@@ -254,11 +316,12 @@ void GetNextLine()
|
||||
/* if nexttok is already NULL, force scanner to read new line */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
void SkipTok(void)
|
||||
void SkipTok(char *delimiter)
|
||||
{
|
||||
if (nexttok != NULL &&
|
||||
(nexttok = strtok(NULL, TOKEN_DELIMITER)) != NULL) return;
|
||||
GetNextLine();
|
||||
if (nexttok != NULL &&
|
||||
(nexttok = strdtok(NULL, WHITESPACE_DELIMITER, delimiter)))
|
||||
return;
|
||||
GetNextLine(delimiter);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
@@ -266,9 +329,9 @@ void SkipTok(void)
|
||||
/* must be preceeded by at least one call to SkipTok() */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
void SkipTokNoNewline(void)
|
||||
void SkipTokNoNewline(char *delimiter)
|
||||
{
|
||||
nexttok = strtok(NULL, TOKEN_DELIMITER);
|
||||
nexttok = strdtok(NULL, WHITESPACE_DELIMITER, delimiter);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
@@ -290,20 +353,41 @@ void SpiceTokNoNewline(void)
|
||||
{
|
||||
int contline;
|
||||
|
||||
if ((nexttok = strtok(NULL, TOKEN_DELIMITER)) != NULL) return;
|
||||
if ((nexttok = strdtok(NULL, WHITESPACE_DELIMITER, NULL)) != NULL) return;
|
||||
|
||||
while (nexttok == NULL) {
|
||||
contline = getc(infile);
|
||||
if (contline == '*') {
|
||||
GetNextLine();
|
||||
SkipNewLine();
|
||||
GetNextLine(WHITESPACE_DELIMITER);
|
||||
SkipNewLine(NULL);
|
||||
continue;
|
||||
}
|
||||
else if (contline != '+') {
|
||||
ungetc(contline, infile);
|
||||
return;
|
||||
}
|
||||
if (GetNextLineNoNewline() == -1) break;
|
||||
if (GetNextLineNoNewline(WHITESPACE_DELIMITER) == -1) break;
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Skip to the next token, ignoring any C-style comments. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
void SkipTokComments(char *delimiter)
|
||||
{
|
||||
SkipTok(delimiter);
|
||||
while (nexttok) {
|
||||
if (match(nexttok, "//")) {
|
||||
SkipNewLine(delimiter);
|
||||
SkipTok(delimiter);
|
||||
}
|
||||
else if (match(nexttok, "/*")) {
|
||||
while (nexttok && !match(nexttok, "*/"))
|
||||
SkipTok(delimiter);
|
||||
if (nexttok) SkipTok(delimiter);
|
||||
}
|
||||
else break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,9 +395,10 @@ void SpiceTokNoNewline(void)
|
||||
/* skip to the end of the current line */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
void SkipNewLine(void)
|
||||
void SkipNewLine(char *delimiter)
|
||||
{
|
||||
while (nexttok != NULL) nexttok = strtok(NULL, TOKEN_DELIMITER);
|
||||
while (nexttok != NULL)
|
||||
nexttok = strdtok(NULL, WHITESPACE_DELIMITER, delimiter);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
@@ -325,18 +410,144 @@ void SpiceSkipNewLine(void)
|
||||
{
|
||||
int contline;
|
||||
|
||||
SkipNewLine();
|
||||
SkipNewLine(NULL);
|
||||
contline = getc(infile);
|
||||
|
||||
while (contline == '+') {
|
||||
ungetc(contline, infile);
|
||||
GetNextLine();
|
||||
SkipNewLine();
|
||||
GetNextLine(WHITESPACE_DELIMITER);
|
||||
SkipNewLine(NULL);
|
||||
contline = getc(infile);
|
||||
}
|
||||
ungetc(contline, infile);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Function similar to strtok() for token parsing. The difference is */
|
||||
/* that it takes two sets of delimiters. The first is whitespace */
|
||||
/* delimiters, which separate tokens. The second is functional */
|
||||
/* delimiters, which separate tokens and have additional meaning, such */
|
||||
/* as parentheses, commas, semicolons, etc. The parser needs to know */
|
||||
/* when such tokens occur in the string, so they are returned as */
|
||||
/* individual tokens. */
|
||||
/* */
|
||||
/* Definition of delim2: String of single delimiter characters. The */
|
||||
/* special character "X" (which is never a delimiter in practice) is */
|
||||
/* used to separate single-character delimiters from two-character */
|
||||
/* delimiters (this presumably could be further extended as needed). */
|
||||
/* so ",;()" would be a valid delimiter set, but to include C-style */
|
||||
/* comments and verilog-style parameter lists, one would need */
|
||||
/* "X/**///#(X,;()". Two-character delimiters should go first so that */
|
||||
/* they have precedence over one-character delimiters. 'X' should be */
|
||||
/* the first character of the delimiter string in addition to marking */
|
||||
/* the boundary between two-character and one-character delimiters. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
char *strdtok(char *pstring, char *delim1, char *delim2)
|
||||
{
|
||||
static char *stoken = NULL;
|
||||
static char *sstring = NULL;
|
||||
char *s, *s2;
|
||||
char first = FALSE;
|
||||
int twofer;
|
||||
|
||||
if (pstring != NULL) {
|
||||
/* Allocate enough memory to hold the string; tokens will be put here */
|
||||
if (sstring != NULL) FREE(sstring);
|
||||
sstring = (char *)MALLOC(strlen(pstring) + 1);
|
||||
stoken = pstring;
|
||||
first = TRUE;
|
||||
}
|
||||
|
||||
/* Skip over "delim1" delimiters at the string beginning */
|
||||
for (; *stoken; stoken++) {
|
||||
for (s2 = delim1; *s2; s2++)
|
||||
if (*stoken == *s2)
|
||||
break;
|
||||
if (*s2 == '\0') break;
|
||||
}
|
||||
|
||||
if (*stoken == '\0') return NULL; /* Finished parsing */
|
||||
|
||||
/* "stoken" is now set. Now find the end of the current token */
|
||||
|
||||
s = stoken;
|
||||
|
||||
/* Special verilog rule: If a name begins with '\', then all characters */
|
||||
/* are a valid part of the name until a space character is reached. The */
|
||||
/* space character becomes part of the verilog name. The remainder of the */
|
||||
/* name is parsed according to the rules of "delim2". */
|
||||
|
||||
if (*s == '\\') {
|
||||
while (*s != '\0') {
|
||||
if (*s == ' ') {
|
||||
s++;
|
||||
break;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check string from position stoken. If a character in "delim2" is found, */
|
||||
/* save the character in "lastdelim", null the byte at that position, and */
|
||||
/* return the token. If a character in "delim1" is found, do the same but */
|
||||
/* continue checking characters as long as there are contiguous "delim1" */
|
||||
/* characters. If the series ends in a character from "delim2", then treat */
|
||||
/* as for "delim2" above. If not, then set "lastdelim" to a null byte and */
|
||||
/* return the token. */
|
||||
|
||||
for (; *s; s++) {
|
||||
twofer = (delim2 && (*delim2 == 'X')) ? TRUE : FALSE;
|
||||
for (s2 = ((twofer == TRUE) ? delim2 + 1 : delim2); s2 && *s2; s2++) {
|
||||
if (*s2 == 'X') {
|
||||
twofer = FALSE;
|
||||
continue;
|
||||
}
|
||||
if (twofer) {
|
||||
if ((*s == *s2) && (*(s + 1) == *(s2 + 1))) {
|
||||
if (s == stoken) {
|
||||
strncpy(sstring, stoken, 2);
|
||||
*(sstring + 2) = '\0';
|
||||
stoken = s + 2;
|
||||
}
|
||||
else {
|
||||
strncpy(sstring, stoken, (int)(s - stoken));
|
||||
*(sstring + (s - stoken)) = '\0';
|
||||
stoken = s;
|
||||
}
|
||||
return sstring;
|
||||
}
|
||||
s2++;
|
||||
if (*s2 == '\0') break;
|
||||
}
|
||||
else if (*s == *s2) {
|
||||
if (s == stoken) {
|
||||
strncpy(sstring, stoken, 1);
|
||||
*(sstring + 1) = '\0';
|
||||
stoken = s + 1;
|
||||
}
|
||||
else {
|
||||
strncpy(sstring, stoken, (int)(s - stoken));
|
||||
*(sstring + (s - stoken)) = '\0';
|
||||
stoken = s;
|
||||
}
|
||||
return sstring;
|
||||
}
|
||||
}
|
||||
for (s2 = delim1; *s2; s2++) {
|
||||
if (*s == *s2) {
|
||||
strncpy(sstring, stoken, (int)(s - stoken));
|
||||
*(sstring + (s - stoken)) = '\0';
|
||||
stoken = s;
|
||||
return sstring;
|
||||
}
|
||||
}
|
||||
}
|
||||
strcpy(sstring, stoken); /* Just copy to the end */
|
||||
stoken = s;
|
||||
return sstring;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
void InputParseError(FILE *f)
|
||||
@@ -418,7 +629,7 @@ char *ReadNetlist(char *fname, int *fnum)
|
||||
};
|
||||
|
||||
#ifdef mips
|
||||
struct filetype formats[6];
|
||||
struct filetype formats[7];
|
||||
|
||||
formats[0].extension = NTK_EXTENSION;
|
||||
formats[0].proc = ReadNtk;
|
||||
@@ -430,8 +641,10 @@ char *ReadNetlist(char *fname, int *fnum)
|
||||
formats[3].proc = ReadSpice;
|
||||
formats[4].extension = NETGEN_EXTENSION;
|
||||
formats[4].proc = ReadNetgenFile;
|
||||
formats[5].extension = NULL;
|
||||
formats[5].proc = NULL;
|
||||
formats[5].extension = VERILOG_EXTENSION;
|
||||
formats[5].proc = ReadVerilogFile;
|
||||
formats[6].extension = NULL;
|
||||
formats[6].proc = NULL;
|
||||
|
||||
#else /* not mips (i.e. compiler with reasonable initializers) */
|
||||
|
||||
@@ -443,6 +656,7 @@ char *ReadNetlist(char *fname, int *fnum)
|
||||
{SPICE_EXTENSION, ReadSpice},
|
||||
{SPICE_EXT2, ReadSpice},
|
||||
{SPICE_EXT3, ReadSpice},
|
||||
{VERILOG_EXTENSION, ReadVerilog},
|
||||
{NETGEN_EXTENSION, ReadNetgenFile},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
+6
-4
@@ -13,6 +13,7 @@
|
||||
#define NETGEN_EXTENSION ".ntg"
|
||||
#define CCODE_EXTENSION ".c.code"
|
||||
#define ESACAP_EXTENSION ".esa"
|
||||
#define VERILOG_EXTENSION ".v"
|
||||
|
||||
#define LINELENGTH 80
|
||||
|
||||
@@ -27,11 +28,12 @@ extern int File;
|
||||
/* input routines */
|
||||
|
||||
extern char *nexttok;
|
||||
#define SKIPTO(a) do {SkipTok();} while (!match(nexttok,a))
|
||||
extern void SkipTok(void);
|
||||
extern void SkipTokNoNewline(void);
|
||||
#define SKIPTO(a) do {SkipTok(NULL);} while (!match(nexttok,a))
|
||||
extern char *strdtok(char *pstring, char *delim1, char *delim2);
|
||||
extern void SkipTok(char *delimiter);
|
||||
extern void SkipTokNoNewline(char *delimiter);
|
||||
extern void SkipNewLine(char *delimiter);
|
||||
extern void SpiceTokNoNewline(void); /* handles SPICE "+" continuation line */
|
||||
extern void SkipNewLine(void);
|
||||
extern void SpiceSkipNewLine(void); /* handles SPICE "+" continuation line */
|
||||
extern void InputParseError(FILE *f);
|
||||
extern int OpenParseFile(char *name, int fnum);
|
||||
|
||||
+204
-77
@@ -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,58 @@ 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));
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Same as above, for series (here for symmetry, although "property */
|
||||
/* series all" would be an odd command to issue, and "property series */
|
||||
/* none" is the default, so not needed). */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
struct nlist *SetSeriesCombineFlag(struct hashlist *p, void *clientdata)
|
||||
{
|
||||
struct nlist *ptr;
|
||||
int *value = (int *)clientdata;
|
||||
|
||||
ptr = (struct nlist *)(p->ptr);
|
||||
if (*value == TRUE)
|
||||
ptr->flags &= (~COMB_SERIES);
|
||||
else
|
||||
ptr->flags |= COMB_SERIES;
|
||||
|
||||
return NULL; /* NULL keeps search alive */
|
||||
}
|
||||
|
||||
void SetSeriesCombine(int value)
|
||||
{
|
||||
ClearDumpedList();
|
||||
RecurseCellHashTable2(SetSeriesCombineFlag, (void *)(&value));
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Delete a property from the master cell record. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
@@ -965,15 +1018,15 @@ PropertyTolerance(char *name, int fnum, char *key, int ival, double dval)
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
int
|
||||
PropertyMerge(char *name, int fnum, char *key, int merge_type)
|
||||
PropertyMerge(char *name, int fnum, char *key, int merge_type, int merge_mask)
|
||||
{
|
||||
struct property *kl = NULL;
|
||||
struct nlist *tc;
|
||||
int result;
|
||||
|
||||
if ((fnum == -1) && (Circuit1 != NULL) && (Circuit2 != NULL)) {
|
||||
result = PropertyMerge(name, Circuit1->file, key, merge_type);
|
||||
result = PropertyMerge(name, Circuit2->file, key, merge_type);
|
||||
result = PropertyMerge(name, Circuit1->file, key, merge_type, merge_mask);
|
||||
result = PropertyMerge(name, Circuit2->file, key, merge_type, merge_mask);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -989,7 +1042,8 @@ PropertyMerge(char *name, int fnum, char *key, int merge_type)
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
kl->merge = merge_type;
|
||||
kl->merge &= ~merge_mask;
|
||||
kl->merge |= merge_type;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1011,7 +1065,7 @@ struct property *PropertyValue(char *name, int fnum, char *key,
|
||||
if ((fnum == -1) && (Circuit1 != NULL) && (Circuit2 != NULL)) {
|
||||
PropertyValue(name, Circuit1->file, key, slop, pdefault);
|
||||
PropertyValue(name, Circuit2->file, key, slop, pdefault);
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tc = LookupCellFile(name, fnum);
|
||||
@@ -1046,7 +1100,7 @@ struct property *PropertyDouble(char *name, int fnum, char *key,
|
||||
if ((fnum == -1) && (Circuit1 != NULL) && (Circuit2 != NULL)) {
|
||||
PropertyDouble(name, Circuit1->file, key, slop, pdefault);
|
||||
PropertyDouble(name, Circuit2->file, key, slop, pdefault);
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tc = LookupCellFile(name, fnum);
|
||||
@@ -1079,7 +1133,7 @@ struct property *PropertyInteger(char *name, int fnum, char *key,
|
||||
if ((fnum == -1) && (Circuit1 != NULL) && (Circuit2 != NULL)) {
|
||||
PropertyInteger(name, Circuit1->file, key, slop, pdefault);
|
||||
PropertyInteger(name, Circuit2->file, key, slop, pdefault);
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tc = LookupCellFile(name, fnum);
|
||||
@@ -1112,7 +1166,7 @@ struct property *PropertyString(char *name, int fnum, char *key, double dval,
|
||||
if ((fnum == -1) && (Circuit1 != NULL) && (Circuit2 != NULL)) {
|
||||
PropertyString(name, Circuit1->file, key, dval, pdefault);
|
||||
PropertyString(name, Circuit2->file, key, dval, pdefault);
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tc = LookupCellFile(name, fnum);
|
||||
@@ -1176,40 +1230,31 @@ void CellDef(char *name, int fnum)
|
||||
{
|
||||
struct nlist *np;
|
||||
|
||||
if (Debug) Printf("Defining cell: %s\n",name);
|
||||
GarbageCollect();
|
||||
if ((CurrentCell = LookupCellFile(name, fnum)) != NULL) {
|
||||
if (AddToExistingDefinition) {
|
||||
if (Debug) Printf("Defining cell: %s\n",name);
|
||||
GarbageCollect();
|
||||
if ((CurrentCell = LookupCellFile(name, fnum)) != NULL) {
|
||||
if (AddToExistingDefinition) {
|
||||
ReopenCellDef(name, fnum);
|
||||
return ;
|
||||
}
|
||||
else {
|
||||
}
|
||||
else {
|
||||
Printf("Cell: %s exists already, and will be overwritten.\n", name);
|
||||
CellDelete(name, fnum);
|
||||
}
|
||||
}
|
||||
/* install a new cell in lookup table (hashed) */
|
||||
np = InstallInCellHashTable(name, fnum);
|
||||
CurrentCell = LookupCellFile(name, fnum);
|
||||
CurrentCell->class = CLASS_SUBCKT; /* default */
|
||||
CurrentCell->flags = 0;
|
||||
}
|
||||
/* install a new cell in lookup table (hashed) */
|
||||
np = InstallInCellHashTable(name, fnum);
|
||||
CurrentCell = LookupCellFile(name, fnum);
|
||||
CurrentCell->class = CLASS_SUBCKT; /* default */
|
||||
CurrentCell->flags = (GlobalParallelNone) ? COMB_NO_PARALLEL : 0;
|
||||
|
||||
LastPlaced = NULL;
|
||||
CurrentTail = NULL;
|
||||
FreeNodeNames(CurrentCell);
|
||||
NextNode = 1;
|
||||
}
|
||||
LastPlaced = NULL;
|
||||
CurrentTail = NULL;
|
||||
FreeNodeNames(CurrentCell);
|
||||
NextNode = 1;
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Same as CellDef() above, but mark cell as case-insensitive. */
|
||||
/* This routine is used only by the ReadSpice() function. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
void CellDefNoCase(char *name, int file)
|
||||
{
|
||||
CellDef(name, file);
|
||||
CurrentCell->file = file;
|
||||
CurrentCell->flags |= CELL_NOCASE;
|
||||
// Mark cell as case insensitive if case insensitivity is in effect
|
||||
if (matchfunc == matchnocase) CurrentCell->flags |= CELL_NOCASE;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
@@ -2444,8 +2489,7 @@ int ConvertStringToInteger(char *string, int *ival)
|
||||
*ival = (int)lval;
|
||||
return 1;
|
||||
}
|
||||
else if (eptr == string)
|
||||
return 0; /* No conversion */
|
||||
else return 0; /* No conversion */
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
@@ -2850,50 +2894,50 @@ void ConnectAllNodes(char *model, int file)
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Serial and Parallel combination: */
|
||||
/* All devices of the same type that exist in serial and parallel */
|
||||
/* Series and Parallel combination: */
|
||||
/* All devices of the same type that exist in series and parallel */
|
||||
/* combinations will be treated as a single device in a network. */
|
||||
/* Serial connections are only allowed for resistors and inductors. */
|
||||
/* Any device may be connected in parallel. For combinations of serial */
|
||||
/* Series connections are only allowed for resistors and inductors. */
|
||||
/* Any device may be connected in parallel. For combinations of series */
|
||||
/* and parallel, as in a resistor network, there is a set of rules: */
|
||||
/* */
|
||||
/* Running parallel and serial checks: */
|
||||
/* Running parallel and series checks: */
|
||||
/* 1. Run parallel once. If a repeat run and no devices are merged, */
|
||||
/* then go to 4. */
|
||||
/* 2. Run serial until no devices are merged. */
|
||||
/* 3. If serial ran more than once, then go to 1. */
|
||||
/* 2. Run series until no devices are merged. */
|
||||
/* 3. If series ran more than once, then go to 1. */
|
||||
/* 4. End merge */
|
||||
/* */
|
||||
/* Each merge procedure, when it finds two devices that can be merged, */
|
||||
/* removes the second device from the netlist and adds its properties */
|
||||
/* to the first device. If a serial merge, then the nodes are adjusted */
|
||||
/* to the first device. If a series merge, then the nodes are adjusted */
|
||||
/* appropriately. Where A is the property list of the first device and */
|
||||
/* B is the property list of the second device, the first and last */
|
||||
/* properties of A and the first property of B may require a marker to */
|
||||
/* indicate the topology of the network, as follows (in order): */
|
||||
/* */
|
||||
/* For a parallel merge: */
|
||||
/* 1) If A has serial components then tag first property of A with */
|
||||
/* 1) If A has series components then tag first property of A with */
|
||||
/* "open" and tag first property of B with "close". */
|
||||
/* 2) If B has serial components then tag first property of B with */
|
||||
/* 2) If B has series components then tag first property of B with */
|
||||
/* "open". */
|
||||
/* */
|
||||
/* For a serial merge: */
|
||||
/* For a series merge: */
|
||||
/* 1) If A has unbalanced "opens", then add "close" to first */
|
||||
/* property of B to balance the "opens". */
|
||||
/* 2) Always tag B with "serial". */
|
||||
/* 2) Always tag B with "series". */
|
||||
/* */
|
||||
/* Tags are indicated by a property named "_tag" which has a string */
|
||||
/* value of ordered characters, "+" for serial, "(" for open, and ")" */
|
||||
/* value of ordered characters, "+" for series, "(" for open, and ")" */
|
||||
/* for close. A device with only one property record has no "_tag" */
|
||||
/* record. A device which is in parallel with the device(s) in front */
|
||||
/* of it is implicitly parallel by not having an "+" tag, and may not */
|
||||
/* have a tag at all. */
|
||||
/* */
|
||||
/* The property check routine is responsible for comparing device */
|
||||
/* serial/parallel networks against each other. Otherwise, each */
|
||||
/* serial/parallel network is considered topologically as a single */
|
||||
/* device, and any differences in the serial/parallel networks between */
|
||||
/* series/parallel networks against each other. Otherwise, each */
|
||||
/* series/parallel network is considered topologically as a single */
|
||||
/* device, and any differences in the series/parallel networks between */
|
||||
/* two circuits being matched will be treated as a property error. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
@@ -2909,7 +2953,8 @@ int add_prop_tag(struct objlist *obr, char tagc)
|
||||
char *tmpstr;
|
||||
|
||||
hastag = FALSE;
|
||||
for (nob = obr; nob->next && nob->next->type == PROPERTY; nob = nob->next) {
|
||||
for (nob = obr; nob; nob = nob->next) {
|
||||
if (nob->type != PROPERTY) break;
|
||||
for (i = 0; ; i++) {
|
||||
kv = &(nob->instance.props[i]);
|
||||
if (kv->type == PROP_ENDLIST) break;
|
||||
@@ -3000,6 +3045,75 @@ void add_balancing_close(struct objlist *ob1, struct objlist *ob2)
|
||||
while (opentags-- > 0) add_prop_tag(nob, ')');
|
||||
}
|
||||
|
||||
/* Remove unneeded group tags, when device merging has removed all but */
|
||||
/* one, or all but parallel devices inside a group. For simplicity, */
|
||||
/* handle only one group at a time. Return 1 if a group was removed */
|
||||
/* and 0 if not. The caller should run repeatedly until the routine */
|
||||
/* returns 0. */
|
||||
|
||||
int remove_group_tags(struct objlist *ob)
|
||||
{
|
||||
struct objlist *nob, *sob;
|
||||
int i, si, stags;
|
||||
struct valuelist *kv;
|
||||
char *tag;
|
||||
|
||||
/* Find the first property record in ob. */
|
||||
for (nob = ob->next; nob && nob->type != FIRSTPIN; nob = nob->next)
|
||||
if (nob->type == PROPERTY)
|
||||
break;
|
||||
if (nob->type != PROPERTY) return 0; // shouldn't happen
|
||||
|
||||
for (sob = NULL; nob && nob->type == PROPERTY; nob = nob->next) {
|
||||
for (i = 0; ; i++) {
|
||||
kv = &(nob->instance.props[i]);
|
||||
if (kv->type == PROP_ENDLIST) break;
|
||||
if (kv->type == PROP_STRING) {
|
||||
if (!strcmp(kv->key, "_tag")) {
|
||||
for (tag = kv->value.string; *tag != '\0'; tag++) {
|
||||
if (*tag == '(') {
|
||||
sob = nob; /* Save position of open group */
|
||||
si = i; /* Save index of open group */
|
||||
stags = 0; /* Check for series tags */
|
||||
}
|
||||
else if (*tag == '+')
|
||||
stags++;
|
||||
else if (*tag == ')') {
|
||||
if (stags == 0) {
|
||||
/* Remove close tag */
|
||||
for (++i; ; i++) {
|
||||
nob->instance.props[i - 1] = nob->instance.props[i];
|
||||
if (nob->instance.props[i].type == PROP_ENDLIST) break;
|
||||
}
|
||||
/* Remove open tag */
|
||||
for (i = si + 1; ; i++) {
|
||||
sob->instance.props[i - 1] = sob->instance.props[i];
|
||||
if (sob->instance.props[i].type == PROP_ENDLIST) break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
sob = NULL;
|
||||
stags = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sob != NULL) {
|
||||
/* Implicit close tag at end */
|
||||
if (stags == 0) {
|
||||
/* Remove open tag */
|
||||
for (i = si + 1; ; i++) {
|
||||
sob->instance.props[i - 1] = sob->instance.props[i];
|
||||
if (sob->instance.props[i].type == PROP_ENDLIST) break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Find all devices that are of the same class and check for parallel */
|
||||
/* combinations, and combine them where found, adjusting property "M" */
|
||||
@@ -3211,7 +3325,7 @@ int CombineParallel(char *model, int file)
|
||||
|
||||
if (propfirst != NULL) {
|
||||
|
||||
// Serial/Parallel logic:
|
||||
// Series/Parallel logic:
|
||||
// If propfirst has _tag in properties,
|
||||
// then add an "open" tag at propfirst
|
||||
add_prop_tag(propfirst, '(');
|
||||
@@ -3254,9 +3368,9 @@ int CombineParallel(char *model, int file)
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* For the purposes of serial connection checking, find if all pins */
|
||||
/* For the purposes of series connection checking, find if all pins */
|
||||
/* of two instances after the first two pins are connected to the name */
|
||||
/* nodes. This depends on the definition of a serial device as having */
|
||||
/* nodes. This depends on the definition of a series device as having */
|
||||
/* two ports, but any additional ports (such as a substrate connection) */
|
||||
/* must be the same for all devices in series. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
@@ -3266,7 +3380,7 @@ int check_pin_nodes(struct objlist *ob1, struct objlist *ob2)
|
||||
struct objlist *nob, *pob;
|
||||
|
||||
/* A dummy device may have both terminals connected to the same */
|
||||
/* point, triggering a false check for a serial device. */
|
||||
/* point, triggering a false check for a series device. */
|
||||
if (ob1 == ob2) return FALSE;
|
||||
|
||||
for (nob = ob1->next; nob && nob->type != FIRSTPIN; nob = nob->next)
|
||||
@@ -3282,7 +3396,9 @@ int check_pin_nodes(struct objlist *ob1, struct objlist *ob2)
|
||||
pob = pob->next;
|
||||
}
|
||||
|
||||
if (nob->type > FIRSTPIN || pob->type > FIRSTPIN) return FALSE;
|
||||
if (nob && pob && (nob->type > FIRSTPIN || pob->type > FIRSTPIN))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -3293,12 +3409,12 @@ int check_pin_nodes(struct objlist *ob1, struct objlist *ob2)
|
||||
/* one. */
|
||||
/* */
|
||||
/* This routine depends on CombineParallel() being run first so that no */
|
||||
/* parallel devices are reported as serial. */
|
||||
/* parallel devices are reported as series. */
|
||||
/* */
|
||||
/* Return the number of devices merged. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
int CombineSerial(char *model, int file)
|
||||
int CombineSeries(char *model, int file)
|
||||
{
|
||||
struct nlist *tp, *tp2;
|
||||
struct objlist ***instlist;
|
||||
@@ -3306,17 +3422,12 @@ 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;
|
||||
}
|
||||
/* Diagnostic */
|
||||
/* Printf("CombineSerial start model = %s file = %d\n", model, file); */
|
||||
/* Printf("CombineSeries start model = %s file = %d\n", model, file); */
|
||||
|
||||
instlist = (struct objlist ***)CALLOC((tp->nodename_cache_maxnodenum + 1),
|
||||
sizeof(struct objlist **));
|
||||
@@ -3331,26 +3442,36 @@ int CombineSerial(char *model, int file)
|
||||
instlist[ob->node] = (struct objlist **)CALLOC(2,
|
||||
sizeof(struct objlist *));
|
||||
|
||||
/* Device must be marked as able to be combined in serial. */
|
||||
/* Device must be marked as able to be combined in series. */
|
||||
/* Note that devices with more than two pins are expected */
|
||||
/* to serial connect along the first two pins, and the */
|
||||
/* to series connect along the first two pins, and the */
|
||||
/* remaining pins must all connect to the same nodes. By */
|
||||
/* default, CLASS_RES, CLASS_RES3, and CLASS_INDUCTOR are */
|
||||
/* all allowed to combine in serial. All other devices */
|
||||
/* must have serial combination explicitly enabled. */
|
||||
/* all allowed to combine in series. All other devices */
|
||||
/* must have series combination explicitly enabled. */
|
||||
/* NOTE: Arbitrarily, the first two pins of a device are */
|
||||
/* assumed to be the ones that make serial connections. */
|
||||
/* assumed to be the ones that make series connections. */
|
||||
/* Additional pins, if any, do not. */
|
||||
|
||||
tp2 = LookupCellFile(ob->model.class, file);
|
||||
if ((tp2->flags & COMB_SERIAL) && (ob->type <= 2))
|
||||
if ((tp2->flags & COMB_SERIES) && (ob->type <= 2)) {
|
||||
instlist[ob->node][0] = obp;
|
||||
|
||||
/* Node may not be a port of the subcircuit */
|
||||
for (obn = tp->cell; obn && obn->type == PORT; obn = obn->next) {
|
||||
if (obn->node == ob->node) {
|
||||
/* invalidate node */
|
||||
instlist[ob->node][0] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
/* invalidate node */
|
||||
instlist[ob->node][0] = NULL;
|
||||
}
|
||||
else if (instlist[ob->node][0] == NULL) {
|
||||
/* Node is not valid for serial connection */
|
||||
/* Node is not valid for series connection */
|
||||
}
|
||||
else if (instlist[ob->node][1] == NULL) {
|
||||
/* Check if first instance is the same type */
|
||||
@@ -3378,7 +3499,7 @@ int CombineSerial(char *model, int file)
|
||||
struct valuelist *kv2;
|
||||
|
||||
/* Diagnostic */
|
||||
/* Fprintf(stdout, "Found serial instances %s and %s\n",
|
||||
/* Fprintf(stdout, "Found series instances %s and %s\n",
|
||||
instlist[i][0]->instance.name,
|
||||
instlist[i][1]->instance.name); */
|
||||
scnt++;
|
||||
@@ -3464,7 +3585,13 @@ int CombineSerial(char *model, int file)
|
||||
/* only pointer to it. */
|
||||
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 (ob2 = obp; ob2 && ob2->next != instlist[i][1]; ob2 = ob2->next);
|
||||
|
||||
/* Device may have been moved by the above code. If so, look for */
|
||||
/* it from the beginning of the list. */
|
||||
if (ob2 == NULL)
|
||||
for (ob2 = tp->cell; ob2->next != instlist[i][1]; ob2 = ob2->next);
|
||||
|
||||
for (obs = ob2->next; obs->next && (obs->next->type > FIRSTPIN
|
||||
|| obs->next->type == PROPERTY); obs = obs->next);
|
||||
ob2->next = obs->next;
|
||||
@@ -3483,7 +3610,7 @@ int CombineSerial(char *model, int file)
|
||||
obs = obn;
|
||||
}
|
||||
|
||||
/* If 2nd device appears anywhere else in the serial device */
|
||||
/* If 2nd device appears anywhere else in the series device */
|
||||
/* list, replace it with the 1st device. */
|
||||
for (j = i + 1; j <= tp->nodename_cache_maxnodenum; j++) {
|
||||
if (instlist[j] == NULL) continue;
|
||||
|
||||
+13
-4
@@ -35,9 +35,12 @@ 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 void SetSeriesCombine(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);
|
||||
extern int PropertyMerge(char *name, int fnum, char *key, int merge_type,
|
||||
int merge_mask);
|
||||
extern void ResolveProperties(char *name1, int file1, char *name2, int file2);
|
||||
extern void CopyProperties(struct objlist *obj_to, struct objlist *obj_from);
|
||||
extern int PromoteProperty(struct property *, struct valuelist *);
|
||||
@@ -53,6 +56,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);
|
||||
@@ -82,8 +87,10 @@ extern int PrematchLists(char *, int, char *, int);
|
||||
#define CLASS_DIODE 16 /* standard SPICE diode */
|
||||
#define CLASS_INDUCTOR 17 /* standard SPICE inductor */
|
||||
#define CLASS_XLINE 18 /* transmission line model */
|
||||
#define CLASS_MODULE 19 /* sim "x"; black-box subcircuit */
|
||||
#define CLASS_UNDEF 20 /* not defined; error */
|
||||
#define CLASS_VSOURCE 19 /* independent voltage source */
|
||||
#define CLASS_ISOURCE 20 /* independent current source */
|
||||
#define CLASS_MODULE 21 /* sim "x"; black-box subcircuit */
|
||||
#define CLASS_UNDEF 22 /* not defined; error */
|
||||
|
||||
extern char *P(char *fname, char *inststr, char *drain, char *gate, char *source);
|
||||
extern char *P4(char *fname, char *inststr, char *drain, char *gate, char *source,
|
||||
@@ -117,7 +124,7 @@ extern void ConvertGlobals(char *name, int fnum);
|
||||
extern int CleanupPins(char *name, int fnum);
|
||||
extern void ConnectAllNodes(char *model, int fnum);
|
||||
extern int CombineParallel(char *model, int fnum);
|
||||
extern int CombineSerial(char *model, int fnum);
|
||||
extern int CombineSeries(char *model, int fnum);
|
||||
extern int NoDisconnectedNodes;
|
||||
extern int PropertyKeyMatch(char *, char *);
|
||||
extern int PropertyValueMatch(char *, char *);
|
||||
@@ -132,6 +139,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??? */
|
||||
@@ -174,6 +182,7 @@ extern char *ReadSim(char *fname, int *fnum);
|
||||
extern char *ReadSpice(char *fname, int *fnum);
|
||||
extern char *ReadSpiceLib(char *fname, int *fnum);
|
||||
extern char *ReadNetgenFile (char *fname, int *fnum);
|
||||
extern char *ReadVerilog(char *fname, int *fnum);
|
||||
|
||||
extern char *ReadNetlist(char *fname, int *fnum);
|
||||
|
||||
|
||||
+26
-22
@@ -27,6 +27,10 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef TCL_NETGEN
|
||||
#include <tcl.h>
|
||||
#endif
|
||||
|
||||
#include "netgen.h"
|
||||
#include "hash.h"
|
||||
#include "objlist.h"
|
||||
@@ -193,7 +197,7 @@ char *ReadNtk (char *fname, int *fnum)
|
||||
}
|
||||
|
||||
while (!EndParseFile()) {
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
if (EndParseFile()) break;
|
||||
if (nexttok[0] == '|') SKIPTO(";");
|
||||
else if (match(nexttok, "c")) {
|
||||
@@ -203,14 +207,14 @@ char *ReadNtk (char *fname, int *fnum)
|
||||
EndCell();
|
||||
CellDefInProgress = 0;
|
||||
}
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
CellDef(nexttok, CurrentCell->file);
|
||||
LastCellRead = CurrentCell->name;
|
||||
CellDefInProgress = 1;
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
while (!match(nexttok, ";")) {
|
||||
Port(nexttok);
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
}
|
||||
}
|
||||
else if (match(nexttok, "s")) {
|
||||
@@ -224,8 +228,8 @@ char *ReadNtk (char *fname, int *fnum)
|
||||
if (LastCellRead == NULL)
|
||||
LastCellRead = CurrentCell->name;
|
||||
}
|
||||
SkipTok();
|
||||
SkipTok(); /* eat the 'size' of the node */
|
||||
SkipTok(NULL);
|
||||
SkipTok(NULL); /* eat the 'size' of the node */
|
||||
/* after the 'size', all names are synonyms */
|
||||
while (!match(nexttok, ";")) {
|
||||
#if 1
|
||||
@@ -240,7 +244,7 @@ char *ReadNtk (char *fname, int *fnum)
|
||||
#endif
|
||||
if (strlen(last)) join(last, nexttok);
|
||||
strcpy(last, nexttok);
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
}
|
||||
}
|
||||
else if (match(nexttok, "h")) {
|
||||
@@ -250,11 +254,11 @@ char *ReadNtk (char *fname, int *fnum)
|
||||
if (LastCellRead == NULL)
|
||||
LastCellRead = CurrentCell->name;
|
||||
}
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
strcpy(model, nexttok);
|
||||
strcpy(instancename, nexttok);
|
||||
strcat(instancename, INSTANCE_DELIMITER);
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
strcat(instancename, nexttok);
|
||||
if (LookupCell(model) == NULL) {
|
||||
#ifdef DEFINE_UNDEFINED_CELLS
|
||||
@@ -264,7 +268,7 @@ char *ReadNtk (char *fname, int *fnum)
|
||||
|
||||
previous_cell = CurrentCell->name;
|
||||
CellDef(model, CurrentCell->file);
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
args = 0;
|
||||
while (!match(nexttok, ";")) {
|
||||
sprintf(name, "pin%d", args+1);
|
||||
@@ -273,11 +277,11 @@ char *ReadNtk (char *fname, int *fnum)
|
||||
args++;
|
||||
/* check for overflow */
|
||||
if (args == (sizeof(ports) / sizeof(ports[0]))) {
|
||||
while (!match(nexttok, ";")) SkipTok();
|
||||
while (!match(nexttok, ";")) SkipTok(NULL);
|
||||
break; /* out of while loop */
|
||||
}
|
||||
/* if no overflow, get the next token */
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
}
|
||||
EndCell();
|
||||
/* now, reopen previous cell, instance the new cell,
|
||||
@@ -301,7 +305,7 @@ char *ReadNtk (char *fname, int *fnum)
|
||||
ob = LookupCell(model)->cell;
|
||||
while ((ob != NULL) && !IsPort(ob))
|
||||
ob = ob->next;
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
while (!match(nexttok, ";")) {
|
||||
strcpy(name, instancename);
|
||||
strcat(name, SEPARATOR);
|
||||
@@ -311,7 +315,7 @@ char *ReadNtk (char *fname, int *fnum)
|
||||
do {
|
||||
ob = ob->next;
|
||||
} while ((ob != NULL) && !IsPort(ob)) ;
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -322,12 +326,12 @@ char *ReadNtk (char *fname, int *fnum)
|
||||
if (LastCellRead == NULL)
|
||||
LastCellRead = CurrentCell->name;
|
||||
}
|
||||
SkipTok();
|
||||
SkipTok(); /* skip the transistor size */
|
||||
SkipTok(NULL);
|
||||
SkipTok(NULL); /* skip the transistor size */
|
||||
strcpy(name, nexttok);
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
strcpy(model, nexttok);
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
strcpy(instancename, nexttok);
|
||||
N(fname, NULL, name, model, instancename);
|
||||
SKIPTO(";");
|
||||
@@ -339,12 +343,12 @@ char *ReadNtk (char *fname, int *fnum)
|
||||
if (LastCellRead == NULL)
|
||||
LastCellRead = CurrentCell->name;
|
||||
}
|
||||
SkipTok();
|
||||
SkipTok(); /* skip the transistor size */
|
||||
SkipTok(NULL);
|
||||
SkipTok(NULL); /* skip the transistor size */
|
||||
strcpy(name, nexttok);
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
strcpy(model, nexttok);
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
strcpy(instancename, nexttok);
|
||||
P(fname, NULL, name, model, instancename);
|
||||
SKIPTO(";");
|
||||
|
||||
+49
-8
@@ -184,13 +184,46 @@ int match(char *st1, char *st2)
|
||||
|
||||
/* Case-insensitive matching */
|
||||
|
||||
/* For case-insensitivity, the alphabet is lower-cased, but */
|
||||
/* also all common vector delimiters are cast to the same */
|
||||
/* character so that different vector notations will match. */
|
||||
|
||||
static char to_lower[256] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
||||
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
|
||||
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
|
||||
30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
|
||||
40, 41, 42, 43, 44, 45, 46, 47,
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
':', ';', '<', '=', '>', '?', '@',
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'<', '\\', '>', '^', '_', '`',
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'<', '|', '>', '~', 127,
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
||||
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
|
||||
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
|
||||
30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
|
||||
40, 41, 42, 43, 44, 45, 46, 47,
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
':', ';', '<', '=', '>', '?', '@',
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'<', '\\', '>', '^', '_', '`',
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'<', '|', '>', '~', 127
|
||||
};
|
||||
|
||||
int matchnocase(char *st1, char *st2)
|
||||
{
|
||||
char *sp1 = st1;
|
||||
char *sp2 = st2;
|
||||
|
||||
while (*sp1 != '\0' && *sp2 != '\0') {
|
||||
if (tolower(*sp1) != tolower(*sp2)) break;
|
||||
if (to_lower[*sp1] != to_lower[*sp2]) break;
|
||||
sp1++;
|
||||
sp2++;
|
||||
}
|
||||
@@ -216,7 +249,7 @@ int matchfilenocase(char *st1, char *st2, int f1, int f2)
|
||||
|
||||
if (f1 != f2) return 0;
|
||||
while (*sp1 != '\0' && *sp2 != '\0') {
|
||||
if (tolower(*sp1) != tolower(*sp2)) break;
|
||||
if (to_lower[*sp1] != to_lower[*sp2]) break;
|
||||
sp1++;
|
||||
sp2++;
|
||||
}
|
||||
@@ -257,6 +290,7 @@ void InitCellHashTable(void)
|
||||
{
|
||||
hashfunc = hash;
|
||||
matchfunc = match;
|
||||
matchintfunc = matchfile;
|
||||
InitializeHashTable(&cell_dict, CELLHASHSIZE);
|
||||
}
|
||||
|
||||
@@ -348,7 +382,7 @@ int removeshorted(struct hashlist *p, int file)
|
||||
|
||||
ptr = (struct nlist *)(p->ptr);
|
||||
|
||||
if ((file != -1) && (ptr->file != file)) return;
|
||||
if ((file != -1) && (ptr->file != file)) return 0;
|
||||
|
||||
lob = NULL;
|
||||
for (ob = ptr->cell; ob != NULL;) {
|
||||
@@ -412,7 +446,7 @@ int deleteclass(struct hashlist *p, int file)
|
||||
|
||||
ptr = (struct nlist *)(p->ptr);
|
||||
|
||||
if ((file != -1) && (ptr->file != file)) return;
|
||||
if ((file != -1) && (ptr->file != file)) return 0;
|
||||
|
||||
lob = NULL;
|
||||
for (ob = ptr->cell; ob != NULL;) {
|
||||
@@ -469,7 +503,7 @@ int renameinstances(struct hashlist *p, int file)
|
||||
|
||||
ptr = (struct nlist *)(p->ptr);
|
||||
|
||||
if ((file != -1) && (ptr->file != file)) return;
|
||||
if ((file != -1) && (ptr->file != file)) return 0;
|
||||
|
||||
for (ob = ptr->cell; ob != NULL; ob = ob->next) {
|
||||
if ((ob->type >= FIRSTPIN) && (ob->model.class != NULL)) {
|
||||
@@ -563,8 +597,15 @@ 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 */
|
||||
#ifdef TCL_NETGEN
|
||||
Tcl_AppendElement(netgeninterp, ptr->name);
|
||||
#else
|
||||
Printf("%s ", ptr->name);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
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 +636,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 +646,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
|
||||
}
|
||||
|
||||
|
||||
+20
-8
@@ -103,18 +103,30 @@ struct valuelist {
|
||||
|
||||
/* Part 3: Keys & Defaults (kept in the cell record as a hash table) */
|
||||
|
||||
#define MERGE_NONE 0 /* Property does not change when devices merge */
|
||||
#define MERGE_ADD 1 /* Properties sum with device parallel merge */
|
||||
#define MERGE_ADD_CRIT 2 /* Properties sum with device parallel merge */
|
||||
#define MERGE_PAR 3 /* Properties add in parallel with device merge */
|
||||
#define MERGE_PAR_CRIT 4 /* Properties add in parallel with device merge */
|
||||
#define MERGE_SER 5 /* Properties sum with device parallel merge */
|
||||
#define MERGE_SER_CRIT 6 /* Properties sum with device parallel merge */
|
||||
#define MERGE_NONE 0x00 /* Property does not change when devices merge */
|
||||
|
||||
#define MERGE_P_ADD 0x01 /* Properties sum with device parallel merge */
|
||||
#define MERGE_P_PAR 0x02 /* Properties add in parallel with parallel merge */
|
||||
#define MERGE_P_CRIT 0x04 /* This property enables parallel merging */
|
||||
#define MERGE_P_XCRIT 0x08 /* Old "critical" behavior (deprecated) */
|
||||
|
||||
#define MERGE_S_ADD 0x10 /* Properties sum with device series merge */
|
||||
#define MERGE_S_PAR 0x20 /* Properties add in parallel with series merge */
|
||||
#define MERGE_S_CRIT 0x40 /* This property enables series merging */
|
||||
#define MERGE_S_XCRIT 0x80 /* Old "critical" behavior (deprecated) */
|
||||
|
||||
#define MERGE_P_MASK (MERGE_P_ADD | MERGE_P_PAR | MERGE_P_CRIT | MERGE_P_XCRIT)
|
||||
#define MERGE_S_MASK (MERGE_S_ADD | MERGE_S_PAR | MERGE_S_CRIT | MERGE_S_XCRIT)
|
||||
#define MERGE_ALL_MASK (MERGE_P_MASK | MERGE_S_MASK)
|
||||
|
||||
/* Although the above are flags, "ADD" and "PAR" are mutually exclusive. */
|
||||
|
||||
/* Note: A "critical" merge means that the property causes the number of */
|
||||
/* devices to change. e.g., transistor width is critical; transistor drain */
|
||||
/* area sums when devices are merged, but does not change the number of devices.*/
|
||||
/* More than one property can be critical. e.g., width and number of fingers. */
|
||||
/* Also it is possible for a property (e.g., "value") to be critical for both */
|
||||
/* series and parallel merging. */
|
||||
|
||||
struct property {
|
||||
char *key; /* name of the property */
|
||||
@@ -217,7 +229,7 @@ struct nlist {
|
||||
|
||||
/* Flags for combination allowances and prohibitions */
|
||||
|
||||
#define COMB_SERIAL 0x40
|
||||
#define COMB_SERIES 0x40
|
||||
#define COMB_NO_PARALLEL 0x80
|
||||
|
||||
extern struct nlist *CurrentCell;
|
||||
|
||||
@@ -1024,6 +1024,10 @@ void Query(void)
|
||||
promptstring("Write SPICE: circuit name: ", repstr);
|
||||
SpiceCell(repstr, filenum, "");
|
||||
break;
|
||||
case 'v':
|
||||
promptstring("Write Verilog: circuit name: ", repstr);
|
||||
VerilogModule(repstr, filenum, "");
|
||||
break;
|
||||
case 'E':
|
||||
promptstring("Write ESACAP: circuit name: ", repstr);
|
||||
EsacapCell(repstr,"");
|
||||
@@ -1062,6 +1066,10 @@ void Query(void)
|
||||
promptstring("Read SPICE (.ckt) file? ", repstr);
|
||||
ReadSpice(repstr, &filenum);
|
||||
break;
|
||||
case 'V':
|
||||
promptstring("Read Verilog (.v) file? ", repstr);
|
||||
ReadVerilog(repstr, &filenum);
|
||||
break;
|
||||
case 'G' :
|
||||
promptstring("Read NETGEN: file? ", repstr);
|
||||
ReadNetgenFile(repstr, &filenum);
|
||||
|
||||
+128
-46
@@ -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
|
||||
@@ -111,6 +117,12 @@ void SpiceSubCell(struct nlist *tp, int IsSubCell)
|
||||
case CLASS_NPN: case CLASS_PNP: case CLASS_BJT:
|
||||
spice_class = 'Q';
|
||||
break;
|
||||
case CLASS_VSOURCE:
|
||||
spice_class = 'V';
|
||||
break;
|
||||
case CLASS_ISOURCE:
|
||||
spice_class = 'I';
|
||||
break;
|
||||
case CLASS_RES: case CLASS_RES3:
|
||||
spice_class = 'R';
|
||||
break;
|
||||
@@ -166,7 +178,7 @@ void SpiceSubCell(struct nlist *tp, int IsSubCell)
|
||||
break;
|
||||
}
|
||||
|
||||
/* caps and resistors, print out device value */
|
||||
/* caps, resistors, voltage and current sources, print out device value */
|
||||
|
||||
/* print out device type (model/subcircuit name) */
|
||||
|
||||
@@ -211,6 +223,23 @@ void SpiceSubCell(struct nlist *tp, int IsSubCell)
|
||||
FlushString(" %s", model); /* semiconductor resistor */
|
||||
break;
|
||||
|
||||
case CLASS_VSOURCE:
|
||||
case CLASS_ISOURCE:
|
||||
ob = ob->next;
|
||||
if (ob->type == PROPERTY) {
|
||||
struct valuelist *vl;
|
||||
int i;
|
||||
for (i == 0;; i++) {
|
||||
vl = &(ob->instance.props[i]);
|
||||
if (vl->type == PROP_ENDLIST) break;
|
||||
else if (vl->type == PROP_VALUE) {
|
||||
FlushString(" %g", vl->value.dval);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
FlushString(" %s", model); /* everything else */
|
||||
}
|
||||
@@ -398,6 +427,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 +439,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 +469,8 @@ void CleanupSubcell() {
|
||||
lobj = sobj;
|
||||
sobj = nobj;
|
||||
}
|
||||
if ((has_devices == FALSE) && (auto_blackbox == TRUE))
|
||||
SetClass(CLASS_MODULE);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
@@ -501,10 +535,10 @@ void ReadSpiceFile(char *fname, int filenum, struct cellstack **CellStackPtr,
|
||||
|
||||
while (!EndParseFile()) {
|
||||
|
||||
SkipTok(); /* get the next token */
|
||||
SkipTok(NULL); /* get the next token */
|
||||
if ((EndParseFile()) && (nexttok == NULL)) break;
|
||||
|
||||
if (nexttok[0] == '*') SkipNewLine();
|
||||
if (nexttok[0] == '*') SkipNewLine(NULL);
|
||||
|
||||
else if (matchnocase(nexttok, ".SUBCKT")) {
|
||||
SpiceTokNoNewline();
|
||||
@@ -563,18 +597,18 @@ void ReadSpiceFile(char *fname, int filenum, struct cellstack **CellStackPtr,
|
||||
Printf("Renaming original cell to %s\n", model);
|
||||
InstanceRename(nexttok, model, filenum);
|
||||
CellRehash(nexttok, model, filenum);
|
||||
CellDefNoCase(nexttok, filenum);
|
||||
CellDef(nexttok, filenum);
|
||||
tp = LookupCellFile(nexttok, filenum);
|
||||
}
|
||||
else if (tp != NULL) { /* Make a new definition for an empty cell */
|
||||
FreePorts(nexttok);
|
||||
CellDelete(nexttok, filenum); /* This removes any PLACEHOLDER flag */
|
||||
CellDefNoCase(model, filenum);
|
||||
CellDef(model, filenum);
|
||||
tp = LookupCellFile(model, filenum);
|
||||
update = 1; /* Will need to update existing instances */
|
||||
}
|
||||
else if (tp == NULL) { /* Completely new cell, no name conflict */
|
||||
CellDefNoCase(model, filenum);
|
||||
CellDef(model, filenum);
|
||||
tp = LookupCellFile(model, filenum);
|
||||
}
|
||||
|
||||
@@ -615,7 +649,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
|
||||
@@ -640,7 +674,7 @@ skip_ends:
|
||||
|
||||
while (1) {
|
||||
SpiceSkipNewLine();
|
||||
SkipTok();
|
||||
SkipTok(NULL);
|
||||
if (EndParseFile()) break;
|
||||
if (matchnocase(nexttok, ".ENDS")) {
|
||||
in_subckt = 0;
|
||||
@@ -662,7 +696,7 @@ skip_ends:
|
||||
|
||||
if (*CellStackPtr) PopStack(CellStackPtr);
|
||||
if (*CellStackPtr) ReopenCellDef((*CellStackPtr)->cellname, filenum);
|
||||
SkipNewLine();
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
else if (matchnocase(nexttok, ".MODEL")) {
|
||||
unsigned char class = CLASS_SUBCKT;
|
||||
@@ -700,6 +734,12 @@ skip_ends:
|
||||
else if (!strcasecmp(nexttok, "R")) {
|
||||
class = CLASS_RES;
|
||||
}
|
||||
else if (!strcasecmp(nexttok, "V")) {
|
||||
class = CLASS_VSOURCE;
|
||||
}
|
||||
else if (!strcasecmp(nexttok, "I")) {
|
||||
class = CLASS_ISOURCE;
|
||||
}
|
||||
else if (!strcasecmp(nexttok, "C")) {
|
||||
class = CLASS_CAP;
|
||||
}
|
||||
@@ -734,7 +774,7 @@ skip_ends:
|
||||
if (numnodes == 0) {
|
||||
// If there is no current cell, make one
|
||||
if (!(*CellStackPtr)) {
|
||||
CellDefNoCase(fname, filenum);
|
||||
CellDef(fname, filenum);
|
||||
PushStack(fname, CellStackPtr);
|
||||
}
|
||||
Global(nexttok);
|
||||
@@ -743,7 +783,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 +795,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(iname, "%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(iname, "%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);
|
||||
|
||||
@@ -816,7 +888,7 @@ skip_ends:
|
||||
collector[99] = '\0';
|
||||
|
||||
if (!(*CellStackPtr)) {
|
||||
CellDefNoCase(fname, filenum);
|
||||
CellDef(fname, filenum);
|
||||
PushStack(fname, CellStackPtr);
|
||||
}
|
||||
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
|
||||
@@ -848,7 +920,7 @@ skip_ends:
|
||||
}
|
||||
|
||||
if (LookupCellFile(model, filenum) == NULL) {
|
||||
CellDefNoCase(model, filenum);
|
||||
CellDef(model, filenum);
|
||||
Port("collector");
|
||||
Port("base");
|
||||
Port("emitter");
|
||||
@@ -877,7 +949,7 @@ skip_ends:
|
||||
bulk[99] = '\0';
|
||||
|
||||
if (!(*CellStackPtr)) {
|
||||
CellDefNoCase(fname, filenum);
|
||||
CellDef(fname, filenum);
|
||||
PushStack(fname, CellStackPtr);
|
||||
}
|
||||
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
|
||||
@@ -918,7 +990,7 @@ skip_ends:
|
||||
/* SPICE transistor. */
|
||||
|
||||
if (LookupCellFile(model, filenum) == NULL) {
|
||||
CellDefNoCase(model, filenum);
|
||||
CellDef(model, filenum);
|
||||
Port("drain");
|
||||
Port("gate");
|
||||
Port("source");
|
||||
@@ -955,7 +1027,7 @@ skip_ends:
|
||||
cbot[99] = '\0';
|
||||
|
||||
if (!(*CellStackPtr)) {
|
||||
CellDefNoCase(fname, filenum);
|
||||
CellDef(fname, filenum);
|
||||
PushStack(fname, CellStackPtr);
|
||||
}
|
||||
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
|
||||
@@ -1009,7 +1081,7 @@ skip_ends:
|
||||
else
|
||||
{
|
||||
if (LookupCellFile(model, filenum) == NULL) {
|
||||
CellDefNoCase(model, filenum);
|
||||
CellDef(model, filenum);
|
||||
Port("top");
|
||||
Port("bottom");
|
||||
PropertyValue(model, filenum, "value", 0.01, 0.0);
|
||||
@@ -1049,7 +1121,7 @@ skip_ends:
|
||||
rbot[99] = '\0';
|
||||
|
||||
if (!(*CellStackPtr)) {
|
||||
CellDefNoCase(fname, filenum);
|
||||
CellDef(fname, filenum);
|
||||
PushStack(fname, CellStackPtr);
|
||||
}
|
||||
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
|
||||
@@ -1100,7 +1172,7 @@ skip_ends:
|
||||
if (model[0] != '\0')
|
||||
{
|
||||
if (LookupCellFile(model, filenum) == NULL) {
|
||||
CellDefNoCase(model, filenum);
|
||||
CellDef(model, filenum);
|
||||
Port("end_a");
|
||||
Port("end_b");
|
||||
PropertyValue(model, filenum, "value", 0.01, 0.0);
|
||||
@@ -1136,7 +1208,7 @@ skip_ends:
|
||||
anode[99] = '\0';
|
||||
|
||||
if (!(*CellStackPtr)) {
|
||||
CellDefNoCase(fname, filenum);
|
||||
CellDef(fname, filenum);
|
||||
PushStack(fname, CellStackPtr);
|
||||
}
|
||||
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
|
||||
@@ -1165,7 +1237,7 @@ skip_ends:
|
||||
}
|
||||
|
||||
if (LookupCellFile(model, filenum) == NULL) {
|
||||
CellDefNoCase(model, filenum);
|
||||
CellDef(model, filenum);
|
||||
Port("anode");
|
||||
Port("cathode");
|
||||
PropertyInteger(model, filenum, "M", 0, 1);
|
||||
@@ -1198,7 +1270,7 @@ skip_ends:
|
||||
node4[99] = '\0';
|
||||
|
||||
if (!(*CellStackPtr)) {
|
||||
CellDefNoCase(fname, filenum);
|
||||
CellDef(fname, filenum);
|
||||
PushStack(fname, CellStackPtr);
|
||||
}
|
||||
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
|
||||
@@ -1236,7 +1308,7 @@ skip_ends:
|
||||
if (model[0] != '\0')
|
||||
{
|
||||
if (LookupCellFile(model, filenum) == NULL) {
|
||||
CellDefNoCase(model, filenum);
|
||||
CellDef(model, filenum);
|
||||
Port("node1");
|
||||
Port("node2");
|
||||
Port("node3");
|
||||
@@ -1276,7 +1348,7 @@ skip_ends:
|
||||
end_b[99] = '\0';
|
||||
|
||||
if (!(*CellStackPtr)) {
|
||||
CellDefNoCase(fname, filenum);
|
||||
CellDef(fname, filenum);
|
||||
PushStack(fname, CellStackPtr);
|
||||
}
|
||||
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
|
||||
@@ -1321,7 +1393,7 @@ skip_ends:
|
||||
if (model[0] != '\0')
|
||||
{
|
||||
if (LookupCellFile(model, filenum) == NULL) {
|
||||
CellDefNoCase(model, filenum);
|
||||
CellDef(model, filenum);
|
||||
Port("end_a");
|
||||
Port("end_b");
|
||||
PropertyInteger(model, filenum, "M", 0, 1);
|
||||
@@ -1359,7 +1431,7 @@ skip_ends:
|
||||
neg[99] = '\0';
|
||||
|
||||
if (!(*CellStackPtr)) {
|
||||
CellDefNoCase(fname, filenum);
|
||||
CellDef(fname, filenum);
|
||||
PushStack(fname, CellStackPtr);
|
||||
}
|
||||
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
|
||||
@@ -1389,11 +1461,11 @@ skip_ends:
|
||||
}
|
||||
strcpy(model, "vsrc"); /* Default voltage source */
|
||||
if (LookupCellFile(model, filenum) == NULL) {
|
||||
CellDefNoCase(model, filenum);
|
||||
CellDef(model, filenum);
|
||||
Port("pos");
|
||||
Port("neg");
|
||||
PropertyInteger(model, filenum, "M", 0, 1);
|
||||
SetClass(CLASS_MODULE);
|
||||
SetClass(CLASS_VSOURCE);
|
||||
EndCell();
|
||||
ReopenCellDef((*CellStackPtr)->cellname, filenum); /* Reopen */
|
||||
}
|
||||
@@ -1414,7 +1486,7 @@ skip_ends:
|
||||
neg[99] = '\0';
|
||||
|
||||
if (!(*CellStackPtr)) {
|
||||
CellDefNoCase(fname, filenum);
|
||||
CellDef(fname, filenum);
|
||||
PushStack(fname, CellStackPtr);
|
||||
}
|
||||
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
|
||||
@@ -1443,11 +1515,11 @@ skip_ends:
|
||||
}
|
||||
strcpy(model, "isrc"); /* Default current source */
|
||||
if (LookupCellFile(model, filenum) == NULL) {
|
||||
CellDefNoCase(model, filenum);
|
||||
CellDef(model, filenum);
|
||||
Port("pos");
|
||||
Port("neg");
|
||||
PropertyInteger(model, filenum, "M", 0, 1);
|
||||
SetClass(CLASS_MODULE);
|
||||
SetClass(CLASS_ISOURCE);
|
||||
EndCell();
|
||||
ReopenCellDef((*CellStackPtr)->cellname, filenum); /* Reopen */
|
||||
}
|
||||
@@ -1470,7 +1542,7 @@ skip_ends:
|
||||
ctrln[99] = '\0';
|
||||
|
||||
if (!(*CellStackPtr)) {
|
||||
CellDefNoCase(fname, filenum);
|
||||
CellDef(fname, filenum);
|
||||
PushStack(fname, CellStackPtr);
|
||||
}
|
||||
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
|
||||
@@ -1506,7 +1578,7 @@ skip_ends:
|
||||
}
|
||||
strcpy(model, "vcvs"); /* Default controlled voltage source */
|
||||
if (LookupCellFile(model, filenum) == NULL) {
|
||||
CellDefNoCase(model, filenum);
|
||||
CellDef(model, filenum);
|
||||
Port("pos");
|
||||
Port("neg");
|
||||
Port("ctrlp");
|
||||
@@ -1530,7 +1602,7 @@ skip_ends:
|
||||
|
||||
else if (toupper(nexttok[0]) == 'X') { /* subcircuit instances */
|
||||
char instancename[100], subcktname[100];
|
||||
int itype;
|
||||
int itype, in_props;
|
||||
|
||||
instancename[99] = '\0';
|
||||
subcktname[99] = '\0';
|
||||
@@ -1546,13 +1618,14 @@ skip_ends:
|
||||
snprintf(instancename, 99, "%s", nexttok + 1);
|
||||
strncpy(instancename, nexttok + 1, 99);
|
||||
if (!(*CellStackPtr)) {
|
||||
CellDefNoCase(fname, filenum);
|
||||
CellDef(fname, filenum);
|
||||
PushStack(fname, CellStackPtr);
|
||||
}
|
||||
|
||||
head = NULL;
|
||||
tail = NULL;
|
||||
SpiceTokNoNewline();
|
||||
in_props = FALSE;
|
||||
while (nexttok != NULL) {
|
||||
/* must still be a node or a parameter */
|
||||
struct portelement *new_port;
|
||||
@@ -1579,10 +1652,11 @@ skip_ends:
|
||||
if (((eqptr = strchr(nexttok, '=')) != NULL) &&
|
||||
((tp = LookupCellFile(nexttok, filenum)) == NULL))
|
||||
{
|
||||
in_props = TRUE;
|
||||
*eqptr = '\0';
|
||||
AddProperty(&kvlist, nexttok, eqptr + 1);
|
||||
}
|
||||
else
|
||||
else if (in_props == FALSE)
|
||||
{
|
||||
new_port = (struct portelement *)CALLOC(1, sizeof(struct portelement));
|
||||
new_port->name = strsave(nexttok);
|
||||
@@ -1591,6 +1665,11 @@ skip_ends:
|
||||
new_port->next = NULL;
|
||||
tail = new_port;
|
||||
}
|
||||
else
|
||||
{
|
||||
Fprintf(stderr, "Token \"%s\" is not a parameter!\n", nexttok);
|
||||
InputParseError(stderr);
|
||||
}
|
||||
SpiceTokNoNewline();
|
||||
}
|
||||
|
||||
@@ -1671,7 +1750,7 @@ skip_ends:
|
||||
|
||||
Fprintf(stdout, "Call to undefined subcircuit %s\n"
|
||||
"Creating placeholder cell definition.\n", subcktname);
|
||||
CellDefNoCase(subcktname, filenum);
|
||||
CellDef(subcktname, filenum);
|
||||
CurrentCell->flags |= CELL_PLACEHOLDER;
|
||||
for (scan = head, i = 1; scan != NULL; scan = scan->next, i++) {
|
||||
sprintf(defport, "%d", i);
|
||||
@@ -1839,7 +1918,7 @@ char *ReadSpiceTop(char *fname, int *fnum, int blackbox)
|
||||
// as an empty cell. Otherwise, the filename is lost and cells
|
||||
// cannot be matched to the file!
|
||||
|
||||
if (LookupCellFile(fname, filenum) == NULL) CellDefNoCase(fname, filenum);
|
||||
if (LookupCellFile(fname, filenum) == NULL) CellDef(fname, filenum);
|
||||
|
||||
tp = LookupCellFile(fname, filenum);
|
||||
if (tp) tp->flags |= CELL_TOP;
|
||||
@@ -1898,12 +1977,15 @@ void IncludeSpice(char *fname, int parent, struct cellstack **CellStackPtr,
|
||||
if ((filenum = OpenParseFile(fname, parent)) < 0) {
|
||||
|
||||
/* If that fails, see if a standard SPICE extension */
|
||||
/* helps. But really, we're getting desperate at this */
|
||||
/* point. */
|
||||
/* helps, if the file didn't have an extension. But */
|
||||
/* really, we're getting desperate at this point. */
|
||||
|
||||
SetExtension(name, fname, SPICE_EXTENSION);
|
||||
if ((filenum = OpenParseFile(name, parent)) < 0) {
|
||||
Fprintf(stderr,"Error in SPICE file read: No file %s\n",name);
|
||||
if (strchr(fname, '.') == NULL) {
|
||||
SetExtension(name, fname, SPICE_EXTENSION);
|
||||
filenum = OpenParseFile(name, parent);
|
||||
}
|
||||
if (filenum < 0) {
|
||||
Fprintf(stderr,"Error in SPICE file include: No file %s\n",name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
+1796
File diff suppressed because it is too large
Load Diff
@@ -132,6 +132,7 @@ char *xilinx_class(model)
|
||||
}
|
||||
return(model);
|
||||
}
|
||||
void
|
||||
Xilinx(cellname, filename)
|
||||
char *cellname;
|
||||
char *filename;
|
||||
|
||||
@@ -4,4 +4,4 @@
|
||||
# all of its config scripts in a different directory than the configure
|
||||
# script itself.
|
||||
|
||||
( CFLAGS="-g" ; export CFLAGS ; cd scripts ; ./configure $* )
|
||||
( CFLAGS="-g" ; export CFLAGS ; cd scripts ; ./configure "$@" )
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
# defs.mak.in --
|
||||
# source file for autoconf-generated "defs.mak" for netgen
|
||||
|
||||
# defs.mak. Generated from defs.mak.in by configure.
|
||||
# Feel free to change the values in here to suit your needs.
|
||||
# Be aware that running scripts/configure again will overwrite
|
||||
# any changes!
|
||||
|
||||
SHELL = /bin/sh
|
||||
|
||||
prefix = ${BUILDROOT}/usr/local
|
||||
exec_prefix = ${prefix}
|
||||
bindir = ${exec_prefix}/bin
|
||||
libdir = ${exec_prefix}/lib
|
||||
mandir = ${prefix}/share/man
|
||||
|
||||
VERSION =
|
||||
|
||||
SCRIPTS = ${NETGENDIR}/scripts
|
||||
|
||||
INSTALL = /bin/install -c
|
||||
INSTALL_PROGRAM = ${INSTALL}
|
||||
INSTALL_DATA = ${INSTALL} -m 644
|
||||
INSTALL_SCRIPT = ${INSTALL}
|
||||
|
||||
# Override standard "make" target when compiling under TCL
|
||||
ALL_TARGET = tcl
|
||||
INSTALL_TARGET = install-tcl
|
||||
|
||||
# Change CADDIR to install in a different place
|
||||
BINDIR = ${bindir}
|
||||
MANDIR = ${mandir}
|
||||
LIBDIR = ${libdir}
|
||||
DOCDIR = ${libdir}/netgen/doc
|
||||
TCLDIR = ${libdir}/netgen/tcl
|
||||
|
||||
MAIN_EXTRA_LIBS = ${NETGENDIR}/tcltk/libtcltk.o
|
||||
LD_EXTRA_LIBS =
|
||||
LD_SHARED =
|
||||
TOP_EXTRA_LIBS =
|
||||
SUB_EXTRA_LIBS =
|
||||
|
||||
MODULES += tcltk
|
||||
UNUSED_MODULES +=
|
||||
PROGRAMS += tcltk
|
||||
INSTALL_CAD_DIRS += tcltk
|
||||
|
||||
RM = rm -f
|
||||
CP = cp
|
||||
AR = @AR@
|
||||
ARFLAGS = crv
|
||||
LINK = /bin/ld -r
|
||||
LD = /bin/ld
|
||||
M4 = /bin/m4
|
||||
RANLIB = ranlib
|
||||
SHDLIB_EXT = .so
|
||||
LDDL_FLAGS = -shared -Wl,-soname,$@ -Wl,--version-script=${NETGENDIR}/netgen/symbol.map
|
||||
LD_RUN_PATH =
|
||||
LIB_SPECS = -L/usr/lib64 -ltkstub8.6 -L/usr/lib64 -ltclstub8.6
|
||||
LIB_SPECS_NOSTUB = -L/usr/lib64 -ltk8.6 -L/usr/lib64 -ltcl8.6
|
||||
WISH_EXE = /usr/bin/wish
|
||||
TCL_LIB_DIR = /usr/lib
|
||||
|
||||
CC = gcc
|
||||
CPP = gcc -E -x c
|
||||
CXX = @CXX@
|
||||
|
||||
CPPFLAGS = -I. -I${NETGENDIR}
|
||||
DFLAGS = -DCAD_DIR=\"${LIBDIR}\" -DTCL_DIR=\"${TCLDIR}\" -DUSE_TCL_STUBS -DUSE_TK_STUBS -DPACKAGE_NAME=\"netgen\" -DPACKAGE_TARNAME=\"netgen\" -DPACKAGE_VERSION=\"1.3\" -DPACKAGE_STRING=\"netgen\ 1.3\" -DPACKAGE_BUGREPORT=\"[email protected]\" -DPACKAGE_URL=\"\" -DNETGEN_VERSION=\"1.5\" -DNETGEN_REVISION=\"60\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DSIZEOF_VOID_P=8 -DSIZEOF_UNSIGNED_INT=4 -DSIZEOF_UNSIGNED_LONG=8 -DSIZEOF_UNSIGNED_LONG_LONG=8 -DSTDC_HEADERS=1 -DHAVE_SETENV=1 -DHAVE_PUTENV=1 -DHAVE_DIRENT_H=1 -DHAVE_LIMITS_H=1 -DHAVE_VA_COPY=1 -DHAVE___VA_COPY=1 -DDBUG_OFF=1 -DTCL_NETGEN=1 -Dlinux=1 -DSYSV=1 -DISC=1 -DSHDLIB_EXT=\".so\" -DNDEBUG
|
||||
DFLAGS_NOSTUB = -DCAD_DIR=\"${LIBDIR}\" -DTCL_DIR=\"${TCLDIR}\" -DPACKAGE_NAME=\"netgen\" -DPACKAGE_TARNAME=\"netgen\" -DPACKAGE_VERSION=\"1.3\" -DPACKAGE_STRING=\"netgen\ 1.3\" -DPACKAGE_BUGREPORT=\"[email protected]\" -DPACKAGE_URL=\"\" -DNETGEN_VERSION=\"1.5\" -DNETGEN_REVISION=\"60\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DSIZEOF_VOID_P=8 -DSIZEOF_UNSIGNED_INT=4 -DSIZEOF_UNSIGNED_LONG=8 -DSIZEOF_UNSIGNED_LONG_LONG=8 -DSTDC_HEADERS=1 -DHAVE_SETENV=1 -DHAVE_PUTENV=1 -DHAVE_DIRENT_H=1 -DHAVE_LIMITS_H=1 -DHAVE_VA_COPY=1 -DHAVE___VA_COPY=1 -DDBUG_OFF=1 -DTCL_NETGEN=1 -Dlinux=1 -DSYSV=1 -DISC=1 -DSHDLIB_EXT=\".so\" -DNDEBUG
|
||||
CFLAGS = -g -m64 -fPIC -fPIC
|
||||
|
||||
DEPEND_FILE = Depend
|
||||
DEPEND_FLAG = -MM
|
||||
EXEEXT =
|
||||
|
||||
GR_CFLAGS =
|
||||
GR_DFLAGS = -DX11 -DXLIB -DNDEBUG
|
||||
GR_LIBS = -lX11
|
||||
GR_SRCS = ${TK_SRCS}
|
||||
|
||||
OBJS = ${SRCS:.c=.o}
|
||||
LIB_OBJS = ${LIB_SRCS:.c=.o}
|
||||
CLEANS = ${OBJS} ${LIB_OBJS} lib${MODULE}.a lib${MODULE}.o ${MODULE}
|
||||
+2
-2
@@ -8,9 +8,9 @@ DOCDIRS = $(DESTDIR)${DOCDIR}
|
||||
MANFILES =
|
||||
DOCFILES = $(DESTDIR)${DOCDIR}/netgen.doc
|
||||
|
||||
install-tcl: ${MANDIRS} ${MANFILES} ${DOCDIRS} ${DOCFILES}
|
||||
install-tcl: ${DOCDIRS} ${DOCFILES}
|
||||
|
||||
install: ${MANDIRS} ${MANFILES} ${DOCDIRS} ${DOCFILES}
|
||||
install: ${DOCDIRS} ${DOCFILES}
|
||||
|
||||
${MANDIRS}: make-man-dirs
|
||||
|
||||
|
||||
+2
-2
@@ -22,8 +22,8 @@ tclnetgen${SHDLIB_EXT}: ${EXTRA_LIBS}
|
||||
@echo --- making netgen Tcl library \(tclnetgen${SHDLIB_EXT}\)
|
||||
${RM} tclnetgen${SHDLIB_EXT}
|
||||
${CC} ${CFLAGS} ${CPPFLAGS} -o $@ ${LDDL_FLAGS} \
|
||||
${LD_RUN_PATH} ${EXTRA_LIBS} ${LD_EXTRA_LIBS} -lc ${LIBS} \
|
||||
${LIB_SPECS} ${LDFLAGS}
|
||||
${LD_RUN_PATH} ${EXTRA_LIBS} ${LD_EXTRA_LIBS} \
|
||||
-lc ${LIBS} ${LIB_SPECS} ${LDFLAGS}
|
||||
|
||||
$(DESTDIR)${BINDIR}/netgen:
|
||||
${RM} $@
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
MODULE = python
|
||||
NETGENDIR = ..
|
||||
SRCS =
|
||||
SCRIPTS = consoletext.py helpwindow.py lvs_manager.py treeviewsplit.py
|
||||
SCRIPTS += tksimpledialog.py tooltip.py lvs_help.txt
|
||||
|
||||
SCRIPTINSTALL = $(DESTDIR)${PYDIR}
|
||||
|
||||
include ${NETGENDIR}/defs.mak
|
||||
|
||||
main: lvs_manager.py
|
||||
|
||||
tcl-main: lvs_manager.py
|
||||
|
||||
$(DESTDIR)${PYDIR}/consoletext.py:
|
||||
${RM} $@
|
||||
${CP} consoletext.py $@
|
||||
|
||||
$(DESTDIR)${PYDIR}/helpwindow.py:
|
||||
${RM} $@
|
||||
${CP} helpwindow.py $@
|
||||
|
||||
lvs_manager.py: lvs_manager.py.in
|
||||
sed -e '/SUBST_SCRIPT_DIR/s#SUBST_SCRIPT_DIR#$(SCRIPTINSTALL)#' \
|
||||
lvs_manager.py.in > lvs_manager.py
|
||||
|
||||
$(DESTDIR)${PYDIR}/lvs_manager.py: lvs_manager.py
|
||||
${RM} $@
|
||||
${CP} lvs_manager.py $@
|
||||
|
||||
$(DESTDIR)${PYDIR}/treeviewsplit.py: treeviewsplit.py
|
||||
${RM} $@
|
||||
${CP} treeviewsplit.py $@
|
||||
|
||||
$(DESTDIR)${PYDIR}/tksimpledialog.py: tksimpledialog.py
|
||||
${RM} $@
|
||||
${CP} tksimpledialog.py $@
|
||||
|
||||
$(DESTDIR)${PYDIR}/tooltip.py: tooltip.py
|
||||
${RM} $@
|
||||
${CP} tooltip.py $@
|
||||
|
||||
$(DESTDIR)${PYDIR}/lvs_help.txt: lvs_help.txt
|
||||
${RM} $@
|
||||
${CP} lvs_help.txt $@
|
||||
|
||||
install: install-tcl
|
||||
|
||||
install-tcl: $(DESTDIR)${PYDIR} $(DESTDIR)${PYDIR}/consoletext.py \
|
||||
$(DESTDIR)${PYDIR}/helpwindow.py $(DESTDIR)${PYDIR}/lvs_manager.py \
|
||||
$(DESTDIR)${PYDIR}/treeviewsplit.py $(DESTDIR)${PYDIR}/tksimpledialog.py \
|
||||
$(DESTDIR)${PYDIR}/tooltip.py $(DESTDIR)${PYDIR}/lvs_help.txt
|
||||
|
||||
include ${NETGENDIR}/rules.mak
|
||||
Executable
+54
@@ -0,0 +1,54 @@
|
||||
#!/bin/env python3
|
||||
#
|
||||
#--------------------------------------------------------
|
||||
"""
|
||||
consoletext --- extends tkinter class Text
|
||||
with stdout and stderr redirection.
|
||||
"""
|
||||
#--------------------------------------------------------
|
||||
# Written by Tim Edwards
|
||||
# efabless, inc.
|
||||
# September 11, 2016
|
||||
# Version 0.1
|
||||
#--------------------------------------------------------
|
||||
|
||||
import sys
|
||||
import tkinter
|
||||
|
||||
class ConsoleText(tkinter.Text):
|
||||
linelimit = 500
|
||||
class IORedirector(object):
|
||||
'''A general class for redirecting I/O to this Text widget.'''
|
||||
def __init__(self,text_area):
|
||||
self.text_area = text_area
|
||||
|
||||
class StdoutRedirector(IORedirector):
|
||||
'''A class for redirecting stdout to this Text widget.'''
|
||||
def write(self,str):
|
||||
self.text_area.write(str,False)
|
||||
|
||||
class StderrRedirector(IORedirector):
|
||||
'''A class for redirecting stderr to this Text widget.'''
|
||||
def write(self,str):
|
||||
self.text_area.write(str,True)
|
||||
|
||||
def __init__(self, master=None, cnf={}, **kw):
|
||||
'''See the __init__ for Tkinter.Text.'''
|
||||
|
||||
tkinter.Text.__init__(self, master, cnf, **kw)
|
||||
|
||||
self.tag_configure('stdout',background='white',foreground='black')
|
||||
self.tag_configure('stderr',background='white',foreground='red')
|
||||
# None of these works! Cannot change selected text background!
|
||||
self.config(selectbackground='blue', selectforeground='white')
|
||||
self.tag_configure('sel',background='blue',foreground='white')
|
||||
|
||||
def write(self, val, is_stderr=False):
|
||||
lines = int(self.index('end-1c').split('.')[0])
|
||||
if lines > self.linelimit:
|
||||
self.delete('1.0', str(lines - self.linelimit) + '.0')
|
||||
self.insert('end',val,'stderr' if is_stderr else 'stdout')
|
||||
self.see('end')
|
||||
|
||||
def limit(self, val):
|
||||
self.linelimit = val
|
||||
Executable
+229
@@ -0,0 +1,229 @@
|
||||
#!/bin/env python3
|
||||
#
|
||||
#--------------------------------------------------------
|
||||
# Help Window for the Open Galaxy project manager
|
||||
#
|
||||
#--------------------------------------------------------
|
||||
# Written by Tim Edwards
|
||||
# efabless, inc.
|
||||
# September 12, 2016
|
||||
# Version 0.1
|
||||
#--------------------------------------------------------
|
||||
|
||||
import re
|
||||
import tkinter
|
||||
from tkinter import ttk
|
||||
|
||||
class HelpWindow(tkinter.Toplevel):
|
||||
"""Open Galaxy help window."""
|
||||
|
||||
def __init__(self, parent=None, fontsize = 11, *args, **kwargs):
|
||||
'''See the __init__ for Tkinter.Toplevel.'''
|
||||
tkinter.Toplevel.__init__(self, parent, *args, **kwargs)
|
||||
|
||||
s = ttk.Style()
|
||||
s.configure('normal.TButton', font=('Helvetica', fontsize), border = 3, relief = 'raised')
|
||||
|
||||
self.withdraw()
|
||||
self.title('Open Galaxy Help')
|
||||
|
||||
self.helptitle = ttk.Label(self, style='title.TLabel', text = '(no text)')
|
||||
self.helptitle.grid(column = 0, row = 0, sticky = "news")
|
||||
self.helpbar = ttk.Separator(self, orient='horizontal')
|
||||
self.helpbar.grid(column = 0, row = 1, sticky = "news")
|
||||
|
||||
self.hframe = tkinter.Frame(self)
|
||||
self.hframe.grid(column = 0, row = 2, sticky = "news")
|
||||
self.hframe.helpdisplay = ttk.Frame(self.hframe)
|
||||
self.hframe.helpdisplay.pack(side = 'left', fill = 'both', expand = 'true')
|
||||
|
||||
self.hframe.helpdisplay.helptext = tkinter.Text(self.hframe.helpdisplay, wrap='word')
|
||||
self.hframe.helpdisplay.helptext.pack(side = 'top', fill = 'both', expand = 'true')
|
||||
# Add scrollbar to help window
|
||||
self.hframe.scrollbar = ttk.Scrollbar(self.hframe)
|
||||
self.hframe.scrollbar.pack(side='right', fill='y')
|
||||
# attach help window to scrollbar
|
||||
self.hframe.helpdisplay.helptext.config(yscrollcommand = self.hframe.scrollbar.set)
|
||||
self.hframe.scrollbar.config(command = self.hframe.helpdisplay.helptext.yview)
|
||||
|
||||
self.hframe.toc = ttk.Treeview(self.hframe, selectmode='browse')
|
||||
self.hframe.toc.bind('<<TreeviewSelect>>', self.toc_to_page)
|
||||
self.hframe.toc.bind('<<TreeviewOpen>>', self.toc_toggle)
|
||||
self.hframe.toc.bind('<<TreeviewClose>>', self.toc_toggle)
|
||||
self.hframe.toc.tag_configure('title', font=('Helvetica', fontsize, 'bold italic'),
|
||||
foreground = 'brown', anchor = 'center')
|
||||
self.hframe.toc.heading('#0', text = "Table of Contents")
|
||||
|
||||
self.bbar = ttk.Frame(self)
|
||||
self.bbar.grid(column = 0, row = 3, sticky = "news")
|
||||
self.bbar.close_button = ttk.Button(self.bbar, text='Close',
|
||||
command=self.close, style = 'normal.TButton')
|
||||
self.bbar.close_button.grid(column=0, row=0, padx = 5)
|
||||
|
||||
self.bbar.prev_button = ttk.Button(self.bbar, text='Prev',
|
||||
command=self.prevpage, style = 'normal.TButton')
|
||||
self.bbar.prev_button.grid(column=1, row=0, padx = 5)
|
||||
|
||||
self.bbar.next_button = ttk.Button(self.bbar, text='Next',
|
||||
command=self.nextpage, style = 'normal.TButton')
|
||||
self.bbar.next_button.grid(column=2, row=0, padx = 5)
|
||||
|
||||
self.bbar.contents_button = ttk.Button(self.bbar, text='Table of Contents',
|
||||
command=self.page_to_toc, style = 'normal.TButton')
|
||||
self.bbar.contents_button.grid(column=3, row=0, padx = 5)
|
||||
|
||||
self.rowconfigure(0, weight=0)
|
||||
self.rowconfigure(1, weight=0)
|
||||
self.rowconfigure(2, weight=1)
|
||||
self.rowconfigure(3, weight=0)
|
||||
self.columnconfigure(0, weight=1)
|
||||
|
||||
# Help pages
|
||||
self.pages = []
|
||||
self.pageno = -1 # No page
|
||||
self.toggle = False
|
||||
|
||||
def grid_configure(self, padx, pady):
|
||||
pass
|
||||
|
||||
def redisplay(self):
|
||||
# remove contents
|
||||
if self.pageno >= 0 and self.pageno < len(self.pages):
|
||||
self.hframe.helpdisplay.helptext.delete('1.0', 'end')
|
||||
self.hframe.helpdisplay.helptext.insert('end', self.pages[self.pageno]['text'])
|
||||
self.helptitle.configure(text = self.pages[self.pageno]['title'])
|
||||
|
||||
def toc_toggle(self, event):
|
||||
self.toggle = True
|
||||
|
||||
def toc_to_page(self, event):
|
||||
treeview = event.widget
|
||||
selection = treeview.item(treeview.selection())
|
||||
|
||||
# Make sure any open/close callback is handled first!
|
||||
self.update_idletasks()
|
||||
if self.toggle:
|
||||
# Item was opened or closed, so consider this a 'false select' and
|
||||
# do not go to the page.
|
||||
self.toggle = False
|
||||
return
|
||||
|
||||
if 'values' in selection:
|
||||
pagenum = selection['values'][0]
|
||||
else:
|
||||
print('Unknown page selected.')
|
||||
pagenum = 0
|
||||
|
||||
# Display a page after displaying the table of contents
|
||||
self.hframe.toc.pack_forget()
|
||||
self.hframe.scrollbar.pack_forget()
|
||||
self.hframe.helpdisplay.pack(side='left', fill='both', expand = 'true')
|
||||
self.hframe.scrollbar.pack(side='right', fill='y')
|
||||
self.hframe.scrollbar.config(command = self.hframe.helpdisplay.helptext.yview)
|
||||
# Enable Prev and Next buttons
|
||||
self.bbar.prev_button.configure(state='enabled')
|
||||
self.bbar.next_button.configure(state='enabled')
|
||||
# Redisplay
|
||||
self.page(pagenum)
|
||||
|
||||
def page_to_toc(self):
|
||||
# Display the table of contents after displaying a page
|
||||
self.hframe.scrollbar.pack_forget()
|
||||
self.hframe.helpdisplay.pack_forget()
|
||||
self.hframe.toc.pack(side='left', fill='both', expand = 'true')
|
||||
self.hframe.scrollbar.pack(side='right', fill='y')
|
||||
self.hframe.scrollbar.config(command = self.hframe.toc.yview)
|
||||
# Disable Prev and Next buttons
|
||||
self.bbar.prev_button.configure(state='disabled')
|
||||
self.bbar.next_button.configure(state='disabled')
|
||||
|
||||
# Simple add page with a single block of plain text
|
||||
def add_page(self, toc_text, text_block):
|
||||
newdict = {}
|
||||
newdict['text'] = text_block
|
||||
newdict['title'] = toc_text
|
||||
self.pages.append(newdict)
|
||||
newpageno = len(self.pages)
|
||||
self.hframe.toc.insert('', 'end', text=str(newpageno) + '. ' + toc_text,
|
||||
tag='title', value = newpageno - 1)
|
||||
if self.pageno < 0:
|
||||
self.pageno = 0 # First page
|
||||
|
||||
# Fill the help text from a file. The format of the file is:
|
||||
# <page_num>
|
||||
# <title>
|
||||
# <text>
|
||||
# '.'
|
||||
# Text is multi-line and ends when '.' is encountered by itself
|
||||
|
||||
def add_pages_from_file(self, filename):
|
||||
endpagerex = re.compile('^\.$')
|
||||
newpagerex = re.compile('^[0-9\.]+$')
|
||||
commentrex = re.compile('^[\-]+$')
|
||||
hierarchy = ''
|
||||
print('Loading help text from file ' + filename)
|
||||
with open(filename, 'r') as f:
|
||||
toc_text = []
|
||||
page_text = []
|
||||
for line in f:
|
||||
if newpagerex.match(line) or endpagerex.match(line):
|
||||
if toc_text and page_text:
|
||||
newdict = {}
|
||||
self.pages.append(newdict)
|
||||
newpageno = len(self.pages)
|
||||
if '.' in hierarchy:
|
||||
pageinfo = hierarchy.rsplit('.', 1)
|
||||
if pageinfo[1] == '':
|
||||
parentid = ''
|
||||
pageid = pageinfo[0]
|
||||
else:
|
||||
parentid = pageinfo[0]
|
||||
pageid = pageinfo[1]
|
||||
else:
|
||||
parentid = ''
|
||||
pageid = hierarchy
|
||||
if parentid:
|
||||
pageid = parentid + '.' + pageid
|
||||
newdict['text'] = page_text
|
||||
newdict['title'] = pageid + '. ' + toc_text
|
||||
self.hframe.toc.insert(parentid, 'end',
|
||||
text=newdict['title'], tag='title',
|
||||
value = newpageno - 1, iid = pageid)
|
||||
if newpagerex.match(line):
|
||||
hierarchy = line.rstrip()
|
||||
toc_text = []
|
||||
elif not toc_text:
|
||||
toc_text = line.rstrip()
|
||||
page_text = []
|
||||
elif not commentrex.match(line):
|
||||
if not page_text:
|
||||
page_text = line
|
||||
else:
|
||||
page_text += line
|
||||
|
||||
def nextpage(self):
|
||||
# Go to next page
|
||||
if self.pageno < len(self.pages) - 1:
|
||||
self.pageno += 1
|
||||
self.redisplay()
|
||||
|
||||
def prevpage(self):
|
||||
# Go to previous page
|
||||
if self.pageno > 0:
|
||||
self.pageno -= 1
|
||||
self.redisplay()
|
||||
|
||||
def page(self, pagenum):
|
||||
# Go to indicated page
|
||||
if pagenum >= 0 and pagenum < len(self.pages):
|
||||
self.pageno = pagenum
|
||||
self.redisplay()
|
||||
|
||||
def close(self):
|
||||
# pop down help window
|
||||
self.withdraw()
|
||||
|
||||
def open(self):
|
||||
# pop up help window
|
||||
self.deiconify()
|
||||
self.lift()
|
||||
@@ -0,0 +1,5 @@
|
||||
1.
|
||||
Selecting a project
|
||||
-------
|
||||
Start by selecting a project. This step is only necessary if the application is started from the command line. If started from the project manager, then it can only be run if a project was selected.
|
||||
.
|
||||
Executable
+819
@@ -0,0 +1,819 @@
|
||||
#!/bin/env python3
|
||||
#
|
||||
#--------------------------------------------------------
|
||||
# LVS Manager GUI.
|
||||
#
|
||||
# This is a Python tkinter script that handles the
|
||||
# process of running LVS and interpreting results.
|
||||
#
|
||||
#--------------------------------------------------------
|
||||
# Written by Tim Edwards
|
||||
# efabless, inc.
|
||||
# Version 1. November 30, 2016
|
||||
# Version 2. March 6, 2017. Reads JSON format output
|
||||
# Version 3. April 25, 2018. Handles layout vs. verilog
|
||||
#--------------------------------------------------------
|
||||
|
||||
import io
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import json
|
||||
import shutil
|
||||
import signal
|
||||
import socket
|
||||
import select
|
||||
import datetime
|
||||
import contextlib
|
||||
import subprocess
|
||||
|
||||
import tkinter
|
||||
from tkinter import ttk
|
||||
from tkinter import filedialog
|
||||
|
||||
import tksimpledialog
|
||||
import tooltip
|
||||
from consoletext import ConsoleText
|
||||
from helpwindow import HelpWindow
|
||||
from treeviewsplit import TreeViewSplit
|
||||
|
||||
# User preferences file (if it exists)
|
||||
prefsfile = '~/.profile/prefs.json'
|
||||
|
||||
netgen_script_dir = '/usr/local/lib/netgen/python'
|
||||
|
||||
#------------------------------------------------------
|
||||
# Simple dialog for confirming quit
|
||||
#------------------------------------------------------
|
||||
|
||||
class ConfirmDialog(tksimpledialog.Dialog):
|
||||
def body(self, master, warning, seed):
|
||||
if warning:
|
||||
ttk.Label(master, text=warning, wraplength=500).grid(row = 0, columnspan = 2, sticky = 'wns')
|
||||
return self
|
||||
|
||||
def apply(self):
|
||||
return 'okay'
|
||||
|
||||
#------------------------------------------------------
|
||||
# Main class for this application
|
||||
#------------------------------------------------------
|
||||
|
||||
class LVSManager(ttk.Frame):
|
||||
"""LVS Manager GUI."""
|
||||
|
||||
def __init__(self, parent, *args, **kwargs):
|
||||
ttk.Frame.__init__(self, parent, *args, **kwargs)
|
||||
self.root = parent
|
||||
self.init_gui()
|
||||
parent.protocol("WM_DELETE_WINDOW", self.on_quit)
|
||||
|
||||
def on_quit(self):
|
||||
"""Exits program."""
|
||||
if self.msock:
|
||||
self.msock.close()
|
||||
quit()
|
||||
|
||||
def init_gui(self):
|
||||
"""Builds GUI."""
|
||||
global prefsfile
|
||||
|
||||
message = []
|
||||
fontsize = 11
|
||||
|
||||
# Read user preferences file, get default font size from it.
|
||||
prefspath = os.path.expanduser(prefsfile)
|
||||
if os.path.exists(prefspath):
|
||||
with open(prefspath, 'r') as f:
|
||||
self.prefs = json.load(f)
|
||||
if 'fontsize' in self.prefs:
|
||||
fontsize = self.prefs['fontsize']
|
||||
else:
|
||||
self.prefs = {}
|
||||
|
||||
s = ttk.Style()
|
||||
|
||||
available_themes = s.theme_names()
|
||||
s.theme_use(available_themes[0])
|
||||
|
||||
s.configure('bg.TFrame', background='gray40')
|
||||
s.configure('italic.TLabel', font=('Helvetica', fontsize, 'italic'))
|
||||
s.configure('title.TLabel', font=('Helvetica', fontsize, 'bold italic'),
|
||||
foreground = 'brown', anchor = 'center')
|
||||
s.configure('normal.TLabel', font=('Helvetica', fontsize))
|
||||
s.configure('red.TLabel', font=('Helvetica', fontsize), foreground = 'red')
|
||||
s.configure('green.TLabel', font=('Helvetica', fontsize), foreground = 'green3')
|
||||
s.configure('blue.TLabel', font=('Helvetica', fontsize), foreground = 'blue')
|
||||
s.configure('normal.TButton', font=('Helvetica', fontsize),
|
||||
border = 3, relief = 'raised')
|
||||
s.configure('red.TButton', font=('Helvetica', fontsize), foreground = 'red',
|
||||
border = 3, relief = 'raised')
|
||||
s.configure('green.TButton', font=('Helvetica', fontsize), foreground = 'green3',
|
||||
border = 3, relief = 'raised')
|
||||
s.configure('blue.TButton', font=('Helvetica', fontsize), foreground = 'blue',
|
||||
border = 3, relief = 'raised')
|
||||
s.configure('redtitle.TButton', font=('Helvetica', fontsize, 'bold italic'),
|
||||
foreground = 'red', border = 3, relief = 'raised')
|
||||
s.configure('bluetitle.TButton', font=('Helvetica', fontsize, 'bold italic'),
|
||||
foreground = 'blue', border = 3, relief = 'raised')
|
||||
|
||||
# These values to be overridden from arguments
|
||||
self.rootpath = None
|
||||
self.project = None
|
||||
self.logfile = None
|
||||
self.msock = None
|
||||
self.help = None
|
||||
|
||||
# Create the help window
|
||||
if os.path.exists(netgen_script_dir + '/netgen_help.txt'):
|
||||
self.help = HelpWindow(self, fontsize = fontsize)
|
||||
with io.StringIO() as buf, contextlib.redirect_stdout(buf):
|
||||
self.help.add_pages_from_file('lvs_help.txt')
|
||||
message = buf.getvalue()
|
||||
|
||||
# Set the help display to the first page
|
||||
self.help.page(0)
|
||||
|
||||
# Variables used by option menus and other stuff
|
||||
self.project = "(no selection)"
|
||||
self.layout = "(default)"
|
||||
self.schematic = "(default)"
|
||||
self.tech = "(none)"
|
||||
self.lvs_setup = ''
|
||||
self.lvsdata = {}
|
||||
|
||||
# Root window title
|
||||
self.root.title('LVS Manager')
|
||||
self.root.option_add('*tearOff', 'FALSE')
|
||||
self.pack(side = 'top', fill = 'both', expand = 'true')
|
||||
|
||||
pane = tkinter.PanedWindow(self, orient = 'vertical', sashrelief='groove', sashwidth=6)
|
||||
pane.pack(side = 'top', fill = 'both', expand = 'true')
|
||||
self.toppane = ttk.Frame(pane)
|
||||
self.botpane = ttk.Frame(pane)
|
||||
|
||||
# Get username
|
||||
if 'username' in self.prefs:
|
||||
username = self.prefs['username']
|
||||
else:
|
||||
username = os.environ['USER']
|
||||
|
||||
# Label with the user
|
||||
self.toppane.title_frame = ttk.Frame(self.toppane)
|
||||
self.toppane.title_frame.pack(side = 'top', fill = 'x')
|
||||
|
||||
self.toppane.title_frame.title = ttk.Label(self.toppane.title_frame, text='User:', style = 'red.TLabel')
|
||||
self.toppane.title_frame.user = ttk.Label(self.toppane.title_frame, text=username, style = 'blue.TLabel')
|
||||
|
||||
self.toppane.title_frame.title.grid(column=0, row=0, ipadx = 5)
|
||||
self.toppane.title_frame.user.grid(column=1, row=0, ipadx = 5)
|
||||
|
||||
self.toppane.title2_frame = ttk.Frame(self.toppane)
|
||||
self.toppane.title2_frame.pack(side = 'top', fill = 'x')
|
||||
self.toppane.title2_frame.project_label = ttk.Label(self.toppane.title2_frame, text="Project:",
|
||||
style = 'title.TLabel')
|
||||
self.toppane.title2_frame.project_label.grid(column=0, row=0, ipadx = 5)
|
||||
|
||||
# New project select button
|
||||
self.toppane.title2_frame.project_select = ttk.Button(self.toppane.title2_frame,
|
||||
text=self.project, style='normal.TButton', command=self.choose_project)
|
||||
self.toppane.title2_frame.project_select.grid(column=1, row=0, ipadx = 5)
|
||||
|
||||
tooltip.ToolTip(self.toppane.title2_frame.project_select,
|
||||
text = "Select new project")
|
||||
|
||||
# Show path to project
|
||||
self.toppane.title2_frame.path_label = ttk.Label(self.toppane.title2_frame, text=self.project,
|
||||
style = 'normal.TLabel')
|
||||
self.toppane.title2_frame.path_label.grid(column=2, row=0, ipadx = 5, padx = 10)
|
||||
|
||||
# Show top-level layout cellname with select button. Initial cell name is the top-level cell.
|
||||
self.toppane.title2_frame.tech_label = ttk.Label(self.toppane.title2_frame, text="Technology setup:",
|
||||
style = 'title.TLabel')
|
||||
|
||||
self.toppane.title2_frame.tech_label.grid(column=3, row=0, ipadx = 5)
|
||||
self.toppane.title2_frame.tech_select = ttk.Button(self.toppane.title2_frame,
|
||||
text=self.tech, style='normal.TButton', command=self.choose_tech)
|
||||
self.toppane.title2_frame.tech_select.grid(column=4, row=0, ipadx = 3, padx = 3)
|
||||
|
||||
self.toppane.title2_frame.layout_label = ttk.Label(self.toppane.title2_frame, text="Layout:",
|
||||
style = 'title.TLabel')
|
||||
self.toppane.title2_frame.layout_label.grid(column=0, row=1, ipadx = 5)
|
||||
self.toppane.title2_frame.layout_select = ttk.Button(self.toppane.title2_frame,
|
||||
text=self.layout, style='normal.TButton', command=self.choose_layout)
|
||||
self.toppane.title2_frame.layout_select.grid(column=1, row=1, ipadx = 3, padx = 3)
|
||||
|
||||
# Show top-level schematic cellname with select button. Initial cell name is the top-level cell.
|
||||
self.toppane.title2_frame.schem_label = ttk.Label(self.toppane.title2_frame, text="Schematic:",
|
||||
style = 'title.TLabel')
|
||||
self.toppane.title2_frame.schem_label.grid(column=3, row=1, ipadx = 5)
|
||||
self.toppane.title2_frame.schem_select = ttk.Button(self.toppane.title2_frame,
|
||||
text=self.schematic, style='normal.TButton', command=self.choose_netlist)
|
||||
self.toppane.title2_frame.schem_select.grid(column=4, row=1, ipadx = 3, padx = 3)
|
||||
|
||||
tooltip.ToolTip(self.toppane.title2_frame.project_select,
|
||||
text = "Select new project")
|
||||
tooltip.ToolTip(self.toppane.title2_frame.layout_select,
|
||||
text = "Select a layout subcirucit to compare")
|
||||
tooltip.ToolTip(self.toppane.title2_frame.schem_select,
|
||||
text = "Select a schematic subcirucit to compare")
|
||||
|
||||
#---------------------------------------------
|
||||
ttk.Separator(self.toppane, orient='horizontal').pack(side = 'top', fill = 'x')
|
||||
#---------------------------------------------
|
||||
|
||||
# Create listbox of Circuit1 vs. Circuit2 results
|
||||
height = 10
|
||||
self.toppane.lvsreport = TreeViewSplit(self.toppane, fontsize = fontsize)
|
||||
self.toppane.lvsreport.populate("Layout:", [], "Schematic:", [],
|
||||
[["Run", True, self.run_lvs],
|
||||
# ["Find", True, self.findrecord]
|
||||
], height = height)
|
||||
self.toppane.lvsreport.set_title("Line")
|
||||
self.toppane.lvsreport.pack(side = 'top', fill = 'both', expand = 'true')
|
||||
|
||||
tooltip.ToolTip(self.toppane.lvsreport.get_button(0), text="Run LVS")
|
||||
|
||||
#---------------------------------------------
|
||||
# ttk.Separator(self, orient='horizontal').grid(column=0, row=3, sticky='ew')
|
||||
#---------------------------------------------
|
||||
|
||||
# Add a text window below the project name to capture output. Redirect
|
||||
# print statements to it.
|
||||
|
||||
self.botpane.console = ttk.Frame(self.botpane)
|
||||
self.botpane.console.pack(side = 'top', fill = 'both', expand = 'true')
|
||||
|
||||
self.text_box = ConsoleText(self.botpane.console, wrap='word', height = 4)
|
||||
self.text_box.pack(side='left', fill='both', expand='true')
|
||||
console_scrollbar = ttk.Scrollbar(self.botpane.console)
|
||||
console_scrollbar.pack(side='right', fill='y')
|
||||
# attach console to scrollbar
|
||||
self.text_box.config(yscrollcommand = console_scrollbar.set)
|
||||
console_scrollbar.config(command = self.text_box.yview)
|
||||
|
||||
# Add button bar at the bottom of the window
|
||||
self.botpane.bbar = ttk.Frame(self.botpane)
|
||||
self.botpane.bbar.pack(side = 'top', fill = 'x')
|
||||
|
||||
# Define the "quit" button and action
|
||||
self.botpane.bbar.quit_button = ttk.Button(self.botpane.bbar, text='Quit', command=self.on_quit,
|
||||
style = 'normal.TButton')
|
||||
self.botpane.bbar.quit_button.grid(column=0, row=0, padx = 5)
|
||||
|
||||
# Define help button
|
||||
if self.help:
|
||||
self.botpane.bbar.help_button = ttk.Button(self.botpane.bbar, text='Help',
|
||||
command=self.help.open, style = 'normal.TButton')
|
||||
self.botpane.bbar.help_button.grid(column = 2, row = 0, padx = 5)
|
||||
tooltip.ToolTip(self.botpane.bbar.help_button, text = "Show help window")
|
||||
|
||||
# Add the panes once the internal geometry is known.
|
||||
pane.add(self.toppane)
|
||||
pane.add(self.botpane)
|
||||
pane.paneconfig(self.toppane, stretch='first')
|
||||
|
||||
# Redirect stdout and stderr to the console as the last thing to do. . .
|
||||
# Otherwise errors in the GUI get sucked into the void.
|
||||
|
||||
self.stdout = sys.stdout
|
||||
self.stderr = sys.stderr
|
||||
sys.stdout = ConsoleText.StdoutRedirector(self.text_box)
|
||||
sys.stderr = ConsoleText.StderrRedirector(self.text_box)
|
||||
|
||||
if message:
|
||||
print(message)
|
||||
|
||||
def logprint(self, message, doflush=False):
|
||||
if self.logfile:
|
||||
self.logfile.buffer.write(message.encode('utf-8'))
|
||||
self.logfile.buffer.write('\n'.encode('utf-8'))
|
||||
if doflush:
|
||||
self.logfile.flush()
|
||||
|
||||
def printout(self, output):
|
||||
# Generate output
|
||||
if not output:
|
||||
return
|
||||
|
||||
outlines = output.splitlines()
|
||||
for line in outlines:
|
||||
try:
|
||||
print(line)
|
||||
except TypeError:
|
||||
line = line.decode('utf-8')
|
||||
pritn(line)
|
||||
|
||||
def printwarn(self, output):
|
||||
# Check output for warning or error
|
||||
if not output:
|
||||
return 0
|
||||
|
||||
warnrex = re.compile('.*warning', re.IGNORECASE)
|
||||
errrex = re.compile('.*error', re.IGNORECASE)
|
||||
|
||||
errors = 0
|
||||
outlines = output.splitlines()
|
||||
for line in outlines:
|
||||
try:
|
||||
wmatch = warnrex.match(line)
|
||||
except TypeError:
|
||||
line = line.decode('utf-8')
|
||||
wmatch = warnrex.match(line)
|
||||
ematch = errrex.match(line)
|
||||
if ematch:
|
||||
errors += 1
|
||||
if ematch or wmatch:
|
||||
print(line)
|
||||
return errors
|
||||
|
||||
def choose_tech(self):
|
||||
try:
|
||||
project_path = self.rootpath
|
||||
initdirname = self.rootpath + '/tech',
|
||||
except:
|
||||
print('Must choose a project first.')
|
||||
return
|
||||
techname = filedialog.askopenfilename(multiple=False,
|
||||
initialdir = initdirname,
|
||||
filetypes = (("Tcl script", "*.tcl"),("All Files","*.*")),
|
||||
title = "Choose a netgen technology setup script.")
|
||||
if techname != '':
|
||||
print("Selected technology setup script " + techname)
|
||||
techbase = os.path.split(techname)[1]
|
||||
self.tech = os.path.splitext(techbase)[0]
|
||||
self.lvs_setup = techname
|
||||
self.toppane.title2_frame.layout_select.config(text = self.tech)
|
||||
|
||||
def choose_layout(self):
|
||||
try:
|
||||
project_path = self.rootpath
|
||||
initdirname = self.rootpath + '/layout',
|
||||
except:
|
||||
print('Must choose a project first.')
|
||||
return
|
||||
cellname = filedialog.askopenfilename(multiple=False,
|
||||
initialdir = initdirname,
|
||||
filetypes = (("Magic layout", "*.mag"),("All Files","*.*")),
|
||||
title = "Choose a layout cell to compare.")
|
||||
if cellname != '':
|
||||
print("Selected compare cell " + cellname)
|
||||
cellbase = os.path.split(cellname)[1]
|
||||
self.layout = os.path.splitext(cellbase)[0]
|
||||
self.toppane.title2_frame.layout_select.config(text = self.layout)
|
||||
|
||||
def choose_netlist(self):
|
||||
try:
|
||||
project_path = self.rootpath
|
||||
initdirname = self.rootpath + '/netlist/' + self.project + '.spi'
|
||||
except:
|
||||
print('Must choose a project first.')
|
||||
return
|
||||
cellname = filedialog.askopenfilename(multiple=False,
|
||||
initialdir = initdirname,
|
||||
filetypes = (("Spice netlist", "*.spi"),("Verilog netlist", "*.v")),
|
||||
title = "Choose a netlist to compare.")
|
||||
if cellname != '':
|
||||
print("Selected compare cell " + cellname)
|
||||
cellbase = os.path.split(cellname)[1]
|
||||
self.schematic = os.path.splitext(cellbase)[0]
|
||||
self.toppane.title2_frame.schem_select.config(text = self.schematic)
|
||||
fileext = os.path.splitext(cellbase)[1]
|
||||
if fileext == '.v':
|
||||
self.toppane.title2_frame.schem_label.config(text = 'Verilog netlist:')
|
||||
elif fileext == '.sp' or fileext == '.spi' or fileext == '.spice' or fileext == '.spc' or fileext == '.ckt':
|
||||
self.toppane.title2_frame.schem_label.config(text = 'SPICE netlist:')
|
||||
elif fileext == '.cdl':
|
||||
self.toppane.title2_frame.schem_label.config(text = 'CDL netlist:')
|
||||
else:
|
||||
self.toppane.title2_frame.schem_label.config(text = 'Unknown netlist:')
|
||||
|
||||
def choose_project(self):
|
||||
project = filedialog.askdirectory(initialdir = os.getcwd(),
|
||||
title = "Find a project.")
|
||||
if project != '':
|
||||
print("Selected project " + str(project))
|
||||
result = self.set_project(project)
|
||||
|
||||
def set_project(self, rootpath, project_name=None):
|
||||
|
||||
# Check if rootpath is valid. For LVS, there should be subdirectories
|
||||
# "layout/" and "netlist/" or "verilog/".
|
||||
|
||||
haslay = os.path.isdir(rootpath + '/layout')
|
||||
hasvlog = os.path.isdir(rootpath + '/verilog')
|
||||
hasnet = os.path.isdir(rootpath + '/netlist')
|
||||
if not haslay or not (hasvlog or hasnet):
|
||||
if not haslay:
|
||||
print("Project path has no layout (/layout) subdirectory.")
|
||||
if not (hasvlog or hasnet):
|
||||
print("Project path has no verilog (/verilog), or netlist (/netlist) subdirectory.")
|
||||
# Continue anyway; assume that netlists will be selected manually
|
||||
|
||||
if self.logfile:
|
||||
self.logfile.close()
|
||||
self.logfile = None
|
||||
|
||||
if not project_name:
|
||||
project = os.path.split(rootpath)[1]
|
||||
else:
|
||||
project = project_name
|
||||
|
||||
if self.project != project:
|
||||
|
||||
self.rootpath = rootpath
|
||||
self.project = project
|
||||
|
||||
# Clear out old project data
|
||||
self.toppane.lvsreport.repopulate([], [])
|
||||
|
||||
# Close any open logfile.
|
||||
if self.logfile:
|
||||
self.logfile.close()
|
||||
self.logfile = None
|
||||
|
||||
# Put new log file called 'lvs.log' in the mag/ subdirectory
|
||||
self.logfile = open(rootpath + '/layout/lvs.log', 'w')
|
||||
# Print some initial information to the logfile.
|
||||
self.logprint('Starting new log file ' + datetime.datetime.now().strftime('%c'),
|
||||
doflush=True)
|
||||
|
||||
# Update project button
|
||||
self.toppane.title2_frame.project_select.config(text = self.project)
|
||||
self.toppane.title2_frame.path_label.config(text = self.rootpath)
|
||||
# Cell name is the same as project name initially
|
||||
self.layout = self.project
|
||||
self.schematic = self.project
|
||||
self.toppane.title2_frame.layout_select.config(text = self.layout)
|
||||
self.toppane.title2_frame.schem_select.config(text = self.schematic)
|
||||
|
||||
# Update schematic button
|
||||
if os.path.isfile(rootpath + '/verilog/' + self.schematic + '.v'):
|
||||
self.toppane.title2_frame.schem_label.config(text = 'Verilog netlist:')
|
||||
else:
|
||||
self.toppane.title2_frame.schem_label.config(text = 'Schematic netlist:')
|
||||
|
||||
# If there is a comparison file that post-dates both netlists, load it.
|
||||
self.check_lvs()
|
||||
return True
|
||||
|
||||
def check_layout_out_of_date(self, spipath, layoutpath):
|
||||
# Check if a netlist (spipath) is out-of-date relative to the layouts
|
||||
# (layoutpath). Need to read the netlist and check all of the subcells.
|
||||
need_capture = False
|
||||
if not os.path.isfile(spipath):
|
||||
return True
|
||||
if os.path.isfile(layoutpath):
|
||||
spi_statbuf = os.stat(spipath)
|
||||
lay_statbuf = os.stat(layoutpath)
|
||||
if spi_statbuf.st_mtime < lay_statbuf.st_mtime:
|
||||
# netlist exists but is out-of-date
|
||||
need_capture = True
|
||||
else:
|
||||
# only found that the top-level-layout is older than the
|
||||
# netlist. Now need to read the netlist, find all subcircuits,
|
||||
# and check those dates, too.
|
||||
layoutdir = os.path.split(layoutpath)[0]
|
||||
subrex = re.compile('^[^\*]*[ \t]*.subckt[ \t]+([^ \t]+).*$', re.IGNORECASE)
|
||||
with open(spipath, 'r') as ifile:
|
||||
duttext = ifile.read()
|
||||
|
||||
dutlines = duttext.replace('\n+', ' ').splitlines()
|
||||
for line in dutlines:
|
||||
lmatch = subrex.match(line)
|
||||
if lmatch:
|
||||
subname = lmatch.group(1)
|
||||
sublayout = layoutdir + '/' + subname + '.mag'
|
||||
# subcircuits that cannot be found in the current directory are
|
||||
# assumed to be library components and therefore never out-of-date.
|
||||
if os.path.exists(sublayout):
|
||||
sub_statbuf = os.stat(sublayout)
|
||||
if spi_statbuf.st_mtime < lay_statbuf.st_mtime:
|
||||
# netlist exists but is out-of-date
|
||||
need_capture = True
|
||||
break
|
||||
return need_capture
|
||||
|
||||
def check_schematic_out_of_date(self, spipath, schempath):
|
||||
# Check if a netlist (spipath) is out-of-date relative to the schematics
|
||||
# (schempath). Need to read the netlist and check all of the subcells.
|
||||
need_capture = False
|
||||
if not os.path.isfile(spipath):
|
||||
return True
|
||||
if os.path.isfile(schempath):
|
||||
spi_statbuf = os.stat(spipath)
|
||||
sch_statbuf = os.stat(schempath)
|
||||
if spi_statbuf.st_mtime < sch_statbuf.st_mtime:
|
||||
# netlist exists but is out-of-date
|
||||
need_capture = True
|
||||
else:
|
||||
# only found that the top-level-schematic is older than the
|
||||
# netlist. Now need to read the netlist, find all subcircuits,
|
||||
# and check those dates, too.
|
||||
schemdir = os.path.split(schempath)[0]
|
||||
subrex = re.compile('^[^\*]*[ \t]*.subckt[ \t]+([^ \t]+).*$', re.IGNORECASE)
|
||||
with open(spipath, 'r') as ifile:
|
||||
duttext = ifile.read()
|
||||
|
||||
dutlines = duttext.replace('\n+', ' ').splitlines()
|
||||
for line in dutlines:
|
||||
lmatch = subrex.match(line)
|
||||
if lmatch:
|
||||
subname = lmatch.group(1)
|
||||
# NOTE: Electric uses library:cell internally to track libraries,
|
||||
# and maps the ":" to "__" in the netlist. Not entirely certain that
|
||||
# the double-underscore uniquely identifies the library:cell. . .
|
||||
librex = re.compile('(.*)__(.*)', re.IGNORECASE)
|
||||
lmatch = librex.match(subname)
|
||||
if lmatch:
|
||||
elecpath = os.path.split(os.path.split(schempath)[0])[0]
|
||||
libname = lmatch.group(1)
|
||||
subschem = elecpath + '/' + libname + '.delib/' + lmatch.group(2) + '.sch'
|
||||
else:
|
||||
libname = {}
|
||||
subschem = schemdir + '/' + subname + '.sch'
|
||||
# subcircuits that cannot be found in the current directory are
|
||||
# assumed to be library components and therefore never out-of-date.
|
||||
if os.path.exists(subschem):
|
||||
sub_statbuf = os.stat(subschem)
|
||||
if spi_statbuf.st_mtime < sub_statbuf.st_mtime:
|
||||
# netlist exists but is out-of-date
|
||||
need_capture = True
|
||||
break
|
||||
# mapping of characters to what's allowed in SPICE makes finding
|
||||
# the associated schematic file a bit difficult. Requires wild-card
|
||||
# searching.
|
||||
elif libname:
|
||||
restr = lmatch.group(2) + '.sch'
|
||||
restr = restr.replace('.', '\.')
|
||||
restr = restr.replace('_', '.')
|
||||
schrex = re.compile(restr, re.IGNORECASE)
|
||||
libpath = elecpath + '/' + libname + '.delib'
|
||||
if os.path.exists(libpath):
|
||||
liblist = os.listdir(libpath)
|
||||
for file in liblist:
|
||||
lmatch = schrex.match(file)
|
||||
if lmatch:
|
||||
subschem = libpath + '/' + file
|
||||
sub_statbuf = os.stat(subschem)
|
||||
if spi_statbuf.st_mtime < sch_statbuf.st_mtime:
|
||||
# netlist exists but is out-of-date
|
||||
need_capture = True
|
||||
break
|
||||
return need_capture
|
||||
|
||||
def check_lvs(self):
|
||||
# If both netlists exist, and comp.json is more recent than both, then
|
||||
# load LVS results from comp.json
|
||||
project_path = self.rootpath
|
||||
project_name = self.project
|
||||
layout_path = project_path + '/layout/' + project_name + '.spc'
|
||||
net_path = project_path + '/netlist/' + project_name + '.spi'
|
||||
comp_path = project_path + '/layout/comp.json'
|
||||
|
||||
if os.path.exists(layout_path) and os.path.exists(net_path) and os.path.exists(comp_path):
|
||||
magtime = os.stat(layout_path).st_mtime
|
||||
schemtime = os.stat(net_path).st_mtime
|
||||
comptime = os.stat(comp_path).st_mtime
|
||||
if comptime > magtime and comptime > schemtime:
|
||||
print("Loading LVS results from file.")
|
||||
self.generate(comp_path)
|
||||
|
||||
def generate_layout_netlist(self, layout_path, layout_src, project_path):
|
||||
# Does layout netlist exist and is it current?
|
||||
if self.check_layout_out_of_date(layout_path, layout_src):
|
||||
print('Generating layout netlist.')
|
||||
self.update_idletasks()
|
||||
mproc = subprocess.Popen(['magic', '-dnull', '-noconsole',
|
||||
self.layout], stdin = subprocess.PIPE, stdout = subprocess.PIPE,
|
||||
stderr = subprocess.PIPE, cwd = project_path + '/layout',
|
||||
universal_newlines = True)
|
||||
mproc.stdin.write("select top cell\n")
|
||||
mproc.stdin.write("expand\n")
|
||||
mproc.stdin.write("extract all\n")
|
||||
mproc.stdin.write("ext2spice hierarchy on\n")
|
||||
mproc.stdin.write("ext2spice format ngspice\n")
|
||||
mproc.stdin.write("ext2spice scale off\n")
|
||||
mproc.stdin.write("ext2spice renumber off\n")
|
||||
mproc.stdin.write("ext2spice subcircuit top auto\n")
|
||||
mproc.stdin.write("ext2spice cthresh infinite\n")
|
||||
mproc.stdin.write("ext2spice rthresh infinite\n")
|
||||
mproc.stdin.write("ext2spice blackbox on\n")
|
||||
mproc.stdin.write("ext2spice -o " + self.layout + ".spi\n")
|
||||
mproc.stdin.write("quit -noprompt\n")
|
||||
magicout = mproc.communicate()[0]
|
||||
self.printwarn(magicout)
|
||||
if mproc.returncode != 0:
|
||||
print('Failure to generate new layout netlist.')
|
||||
return False
|
||||
|
||||
# Move .spi netlist to project_dir/netlist/lvs/
|
||||
shutil.move(project_path + '/layout/' + self.layout + '.spi', layout_path)
|
||||
# Remove extraction files
|
||||
for file in os.listdir(project_path + '/layout'):
|
||||
if os.path.splitext(file)[1] == '.ext':
|
||||
os.remove(project_path + '/layout/' + file)
|
||||
else:
|
||||
print('Layout netlist is up-to-date, not regenerating.')
|
||||
return True
|
||||
|
||||
def run_lvs(self, value):
|
||||
# "value" is ignored (?)
|
||||
|
||||
# Check if netlists exist and are current; otherwise create them.
|
||||
# Then run LVS.
|
||||
|
||||
project_path = self.rootpath
|
||||
project_name = self.project
|
||||
comp_path = project_path + '/layout/comp.json'
|
||||
has_vlog = False
|
||||
vlog_path = project_path + '/verilog/' + project_name + '.v'
|
||||
|
||||
layout_path = project_path + '/netlist/lvs/' + self.layout + '.spi'
|
||||
net_path = project_path + '/netlist/schem/' + self.schematic + '.spi'
|
||||
layout_src = project_path + '/layout/' + self.layout + '.mag'
|
||||
|
||||
# Does the setup file exist (this is optional)?
|
||||
if self.lvs_setup != '' and not os.path.isfile('setup.tcl'):
|
||||
print('No technology setup file selected.')
|
||||
|
||||
# Does schematic netlist exist?
|
||||
if not os.path.isfile(vlog_path) and not os.path.isfile(net_path):
|
||||
print('Error: No schematic netlist or verilog netlist.')
|
||||
return
|
||||
|
||||
# Does LVS netlist subdirectory exist?
|
||||
if not os.path.exists(project_path + '/netlist/lvs'):
|
||||
os.makedirs(project_path + '/netlist/lvs')
|
||||
|
||||
# Does layout netlist exist and is it current?
|
||||
if not self.generate_layout_netlist(layout_path, layout_src, project_path):
|
||||
return False
|
||||
|
||||
# Final check
|
||||
if not os.path.isfile(layout_path):
|
||||
print('Error: No netlist generated from magic.')
|
||||
return
|
||||
|
||||
else:
|
||||
# Read in netlist and convert commas from [X,Y] arrays to vertical bars
|
||||
# as something that can be converted back as necessary. ngspice treats
|
||||
# commas as special characters for some reason.
|
||||
with open(layout_path) as ifile:
|
||||
spitext = ifile.read()
|
||||
|
||||
# spilines = spitext.replace(',', '|')
|
||||
# with open(layout_path, 'w') as ofile:
|
||||
# ofile.write(spilines)
|
||||
|
||||
# Check the netlist to see if the cell to match is a subcircuit. If
|
||||
# not, then assume it is the top level.
|
||||
|
||||
is_subckt = False
|
||||
subrex = re.compile('^[^\*]*[ \t]*.subckt[ \t]+([^ \t]+).*$', re.IGNORECASE)
|
||||
dutlines = spitext.replace('\n+', ' ').splitlines()
|
||||
for line in dutlines:
|
||||
lmatch = subrex.match(line)
|
||||
if lmatch:
|
||||
subname = lmatch.group(1)
|
||||
if subname == self.layout:
|
||||
is_subckt = True
|
||||
break
|
||||
|
||||
if is_subckt:
|
||||
layout_arg = layout_path + ' ' + self.layout
|
||||
layout_text = '"' + layout_arg + '"'
|
||||
else:
|
||||
layout_arg = layout_path
|
||||
layout_text = layout_arg
|
||||
|
||||
if has_vlog:
|
||||
schem_arg = vlog_path + ' ' + self.schematic
|
||||
else:
|
||||
schem_arg = net_path + ' ' + self.schematic
|
||||
schem_text = '"' + schem_arg + '"'
|
||||
|
||||
# Remove any previous comparison output file
|
||||
comp_out_path = os.path.splitext(comp_path)[0] + '.out'
|
||||
if os.path.exists(comp_out_path):
|
||||
os.remove(comp_out_path)
|
||||
|
||||
# Run netgen as subprocess
|
||||
print('Running: netgen -batch lvs ' + layout_text +
|
||||
' ' + schem_text + ' ' + self.lvs_setup + ' ' + comp_out_path +
|
||||
' -json -blackbox')
|
||||
# Note: Because arguments to subprocess are list items, the {filename cell}
|
||||
# pair does *not* have to be quoted or braced. Doing so causes a parse
|
||||
# error.
|
||||
self.lvsproc = subprocess.Popen(['netgen', '-batch', 'lvs',
|
||||
layout_arg, schem_arg,
|
||||
self.lvs_setup, comp_out_path, '-json', '-blackbox'],
|
||||
cwd=project_path + '/layout',
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=0)
|
||||
# This is largely unnecessary as netgen usually runs to completion very quickly.
|
||||
self.watchclock(comp_path)
|
||||
|
||||
def watchclock(self, filename):
|
||||
if self.lvsproc == None:
|
||||
return
|
||||
|
||||
lvs_status = self.lvsproc.poll()
|
||||
sresult = select.select([self.lvsproc.stdout, self.lvsproc.stderr], [], [], 0)[0]
|
||||
if self.lvsproc.stdout in sresult:
|
||||
outstring = self.lvsproc.stdout.readline().decode().strip()
|
||||
self.logprint(outstring, doflush=True)
|
||||
print(outstring)
|
||||
elif self.lvsproc.stderr in sresult:
|
||||
errstring = self.lvsproc.stderr.readline().decode().strip()
|
||||
self.logprint(errstring, doflush = True)
|
||||
print(errstring, file=sys.stderr)
|
||||
|
||||
if lvs_status != None:
|
||||
print("netgen LVS exited with status " + str(lvs_status))
|
||||
self.lvsproc = None
|
||||
if lvs_status != 0:
|
||||
print('Errors encountered in LVS.')
|
||||
self.logprint('Errors in LVS, lvs status = ' + str(lvs_status), doflush=True)
|
||||
# Done; now read comp.json and fill the treeview listbox.
|
||||
self.generate(filename)
|
||||
else:
|
||||
self.after(500, lambda: self.watchclock(filename))
|
||||
|
||||
# Generate display from "comp.out" file (json file now preferred)
|
||||
|
||||
def generate_orig(self, lvspath):
|
||||
lefttext = []
|
||||
righttext = []
|
||||
print("Reading LVS output file " + lvspath)
|
||||
if os.path.exists(lvspath):
|
||||
with open(lvspath, 'r') as ifile:
|
||||
lvslines = ifile.read().splitlines()
|
||||
for line in lvslines:
|
||||
if '|' in line:
|
||||
# parts = line.split('|')
|
||||
# lefttext.append(parts[0])
|
||||
# righttext.append(parts[1])
|
||||
lefttext.append(line[0:42].strip())
|
||||
righttext.append(line[44:].strip())
|
||||
else:
|
||||
lefttext.append(line)
|
||||
righttext.append('')
|
||||
# Populate treeview with text
|
||||
self.toppane.lvsreport.repopulate(lefttext, righttext)
|
||||
|
||||
else:
|
||||
print("Error: No output file generated from LVS.")
|
||||
|
||||
# Generate output from LVS report JSON file comp.json
|
||||
|
||||
def generate(self, lvspath):
|
||||
lefttext = []
|
||||
righttext = []
|
||||
print("Reading LVS output file " + lvspath)
|
||||
if os.path.exists(lvspath):
|
||||
with open(lvspath, 'r') as ifile:
|
||||
self.lvsdata = json.load(ifile)
|
||||
|
||||
# Populate treeview with text
|
||||
self.toppane.lvsreport.json_repopulate(self.lvsdata)
|
||||
|
||||
else:
|
||||
print("Error: No output file generated from LVS.")
|
||||
|
||||
def findrecord(self, value):
|
||||
print("Unimplemented function")
|
||||
|
||||
def findrecord_test(self, value):
|
||||
# Check if socket is defined; if not, attempt to open one
|
||||
if not self.msock:
|
||||
try:
|
||||
self.msock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
except:
|
||||
print("No response from layout tool.")
|
||||
|
||||
if self.msock:
|
||||
self.msock.connect(("0.0.0.0", 12946))
|
||||
self.msock.setblocking(False)
|
||||
if self.msock:
|
||||
# Pull name of net or device from 'value'
|
||||
# This is a test:
|
||||
self.msock.sendall(b'box 0 0 100 100\r\n')
|
||||
|
||||
if __name__ == '__main__':
|
||||
options = []
|
||||
arguments = []
|
||||
for item in sys.argv[1:]:
|
||||
if item.find('-', 0) == 0:
|
||||
options.append(item)
|
||||
else:
|
||||
arguments.append(item)
|
||||
|
||||
root = tkinter.Tk()
|
||||
app = LVSManager(root)
|
||||
if arguments:
|
||||
if len(arguments) >= 2:
|
||||
app.set_project(arguments[0], project_name=arguments[1])
|
||||
else:
|
||||
app.set_project(arguments[0])
|
||||
|
||||
root.mainloop()
|
||||
Executable
+819
@@ -0,0 +1,819 @@
|
||||
#!/bin/env python3
|
||||
#
|
||||
#--------------------------------------------------------
|
||||
# LVS Manager GUI.
|
||||
#
|
||||
# This is a Python tkinter script that handles the
|
||||
# process of running LVS and interpreting results.
|
||||
#
|
||||
#--------------------------------------------------------
|
||||
# Written by Tim Edwards
|
||||
# efabless, inc.
|
||||
# Version 1. November 30, 2016
|
||||
# Version 2. March 6, 2017. Reads JSON format output
|
||||
# Version 3. April 25, 2018. Handles layout vs. verilog
|
||||
#--------------------------------------------------------
|
||||
|
||||
import io
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import json
|
||||
import shutil
|
||||
import signal
|
||||
import socket
|
||||
import select
|
||||
import datetime
|
||||
import contextlib
|
||||
import subprocess
|
||||
|
||||
import tkinter
|
||||
from tkinter import ttk
|
||||
from tkinter import filedialog
|
||||
|
||||
import tksimpledialog
|
||||
import tooltip
|
||||
from consoletext import ConsoleText
|
||||
from helpwindow import HelpWindow
|
||||
from treeviewsplit import TreeViewSplit
|
||||
|
||||
# User preferences file (if it exists)
|
||||
prefsfile = '~/.profile/prefs.json'
|
||||
|
||||
netgen_script_dir = 'SUBST_SCRIPT_DIR'
|
||||
|
||||
#------------------------------------------------------
|
||||
# Simple dialog for confirming quit
|
||||
#------------------------------------------------------
|
||||
|
||||
class ConfirmDialog(tksimpledialog.Dialog):
|
||||
def body(self, master, warning, seed):
|
||||
if warning:
|
||||
ttk.Label(master, text=warning, wraplength=500).grid(row = 0, columnspan = 2, sticky = 'wns')
|
||||
return self
|
||||
|
||||
def apply(self):
|
||||
return 'okay'
|
||||
|
||||
#------------------------------------------------------
|
||||
# Main class for this application
|
||||
#------------------------------------------------------
|
||||
|
||||
class LVSManager(ttk.Frame):
|
||||
"""LVS Manager GUI."""
|
||||
|
||||
def __init__(self, parent, *args, **kwargs):
|
||||
ttk.Frame.__init__(self, parent, *args, **kwargs)
|
||||
self.root = parent
|
||||
self.init_gui()
|
||||
parent.protocol("WM_DELETE_WINDOW", self.on_quit)
|
||||
|
||||
def on_quit(self):
|
||||
"""Exits program."""
|
||||
if self.msock:
|
||||
self.msock.close()
|
||||
quit()
|
||||
|
||||
def init_gui(self):
|
||||
"""Builds GUI."""
|
||||
global prefsfile
|
||||
|
||||
message = []
|
||||
fontsize = 11
|
||||
|
||||
# Read user preferences file, get default font size from it.
|
||||
prefspath = os.path.expanduser(prefsfile)
|
||||
if os.path.exists(prefspath):
|
||||
with open(prefspath, 'r') as f:
|
||||
self.prefs = json.load(f)
|
||||
if 'fontsize' in self.prefs:
|
||||
fontsize = self.prefs['fontsize']
|
||||
else:
|
||||
self.prefs = {}
|
||||
|
||||
s = ttk.Style()
|
||||
|
||||
available_themes = s.theme_names()
|
||||
s.theme_use(available_themes[0])
|
||||
|
||||
s.configure('bg.TFrame', background='gray40')
|
||||
s.configure('italic.TLabel', font=('Helvetica', fontsize, 'italic'))
|
||||
s.configure('title.TLabel', font=('Helvetica', fontsize, 'bold italic'),
|
||||
foreground = 'brown', anchor = 'center')
|
||||
s.configure('normal.TLabel', font=('Helvetica', fontsize))
|
||||
s.configure('red.TLabel', font=('Helvetica', fontsize), foreground = 'red')
|
||||
s.configure('green.TLabel', font=('Helvetica', fontsize), foreground = 'green3')
|
||||
s.configure('blue.TLabel', font=('Helvetica', fontsize), foreground = 'blue')
|
||||
s.configure('normal.TButton', font=('Helvetica', fontsize),
|
||||
border = 3, relief = 'raised')
|
||||
s.configure('red.TButton', font=('Helvetica', fontsize), foreground = 'red',
|
||||
border = 3, relief = 'raised')
|
||||
s.configure('green.TButton', font=('Helvetica', fontsize), foreground = 'green3',
|
||||
border = 3, relief = 'raised')
|
||||
s.configure('blue.TButton', font=('Helvetica', fontsize), foreground = 'blue',
|
||||
border = 3, relief = 'raised')
|
||||
s.configure('redtitle.TButton', font=('Helvetica', fontsize, 'bold italic'),
|
||||
foreground = 'red', border = 3, relief = 'raised')
|
||||
s.configure('bluetitle.TButton', font=('Helvetica', fontsize, 'bold italic'),
|
||||
foreground = 'blue', border = 3, relief = 'raised')
|
||||
|
||||
# These values to be overridden from arguments
|
||||
self.rootpath = None
|
||||
self.project = None
|
||||
self.logfile = None
|
||||
self.msock = None
|
||||
self.help = None
|
||||
|
||||
# Create the help window
|
||||
if os.path.exists(netgen_script_dir + '/netgen_help.txt'):
|
||||
self.help = HelpWindow(self, fontsize = fontsize)
|
||||
with io.StringIO() as buf, contextlib.redirect_stdout(buf):
|
||||
self.help.add_pages_from_file('lvs_help.txt')
|
||||
message = buf.getvalue()
|
||||
|
||||
# Set the help display to the first page
|
||||
self.help.page(0)
|
||||
|
||||
# Variables used by option menus and other stuff
|
||||
self.project = "(no selection)"
|
||||
self.layout = "(default)"
|
||||
self.schematic = "(default)"
|
||||
self.tech = "(none)"
|
||||
self.lvs_setup = ''
|
||||
self.lvsdata = {}
|
||||
|
||||
# Root window title
|
||||
self.root.title('LVS Manager')
|
||||
self.root.option_add('*tearOff', 'FALSE')
|
||||
self.pack(side = 'top', fill = 'both', expand = 'true')
|
||||
|
||||
pane = tkinter.PanedWindow(self, orient = 'vertical', sashrelief='groove', sashwidth=6)
|
||||
pane.pack(side = 'top', fill = 'both', expand = 'true')
|
||||
self.toppane = ttk.Frame(pane)
|
||||
self.botpane = ttk.Frame(pane)
|
||||
|
||||
# Get username
|
||||
if 'username' in self.prefs:
|
||||
username = self.prefs['username']
|
||||
else:
|
||||
username = os.environ['USER']
|
||||
|
||||
# Label with the user
|
||||
self.toppane.title_frame = ttk.Frame(self.toppane)
|
||||
self.toppane.title_frame.pack(side = 'top', fill = 'x')
|
||||
|
||||
self.toppane.title_frame.title = ttk.Label(self.toppane.title_frame, text='User:', style = 'red.TLabel')
|
||||
self.toppane.title_frame.user = ttk.Label(self.toppane.title_frame, text=username, style = 'blue.TLabel')
|
||||
|
||||
self.toppane.title_frame.title.grid(column=0, row=0, ipadx = 5)
|
||||
self.toppane.title_frame.user.grid(column=1, row=0, ipadx = 5)
|
||||
|
||||
self.toppane.title2_frame = ttk.Frame(self.toppane)
|
||||
self.toppane.title2_frame.pack(side = 'top', fill = 'x')
|
||||
self.toppane.title2_frame.project_label = ttk.Label(self.toppane.title2_frame, text="Project:",
|
||||
style = 'title.TLabel')
|
||||
self.toppane.title2_frame.project_label.grid(column=0, row=0, ipadx = 5)
|
||||
|
||||
# New project select button
|
||||
self.toppane.title2_frame.project_select = ttk.Button(self.toppane.title2_frame,
|
||||
text=self.project, style='normal.TButton', command=self.choose_project)
|
||||
self.toppane.title2_frame.project_select.grid(column=1, row=0, ipadx = 5)
|
||||
|
||||
tooltip.ToolTip(self.toppane.title2_frame.project_select,
|
||||
text = "Select new project")
|
||||
|
||||
# Show path to project
|
||||
self.toppane.title2_frame.path_label = ttk.Label(self.toppane.title2_frame, text=self.project,
|
||||
style = 'normal.TLabel')
|
||||
self.toppane.title2_frame.path_label.grid(column=2, row=0, ipadx = 5, padx = 10)
|
||||
|
||||
# Show top-level layout cellname with select button. Initial cell name is the top-level cell.
|
||||
self.toppane.title2_frame.tech_label = ttk.Label(self.toppane.title2_frame, text="Technology setup:",
|
||||
style = 'title.TLabel')
|
||||
|
||||
self.toppane.title2_frame.tech_label.grid(column=3, row=0, ipadx = 5)
|
||||
self.toppane.title2_frame.tech_select = ttk.Button(self.toppane.title2_frame,
|
||||
text=self.tech, style='normal.TButton', command=self.choose_tech)
|
||||
self.toppane.title2_frame.tech_select.grid(column=4, row=0, ipadx = 3, padx = 3)
|
||||
|
||||
self.toppane.title2_frame.layout_label = ttk.Label(self.toppane.title2_frame, text="Layout:",
|
||||
style = 'title.TLabel')
|
||||
self.toppane.title2_frame.layout_label.grid(column=0, row=1, ipadx = 5)
|
||||
self.toppane.title2_frame.layout_select = ttk.Button(self.toppane.title2_frame,
|
||||
text=self.layout, style='normal.TButton', command=self.choose_layout)
|
||||
self.toppane.title2_frame.layout_select.grid(column=1, row=1, ipadx = 3, padx = 3)
|
||||
|
||||
# Show top-level schematic cellname with select button. Initial cell name is the top-level cell.
|
||||
self.toppane.title2_frame.schem_label = ttk.Label(self.toppane.title2_frame, text="Schematic:",
|
||||
style = 'title.TLabel')
|
||||
self.toppane.title2_frame.schem_label.grid(column=3, row=1, ipadx = 5)
|
||||
self.toppane.title2_frame.schem_select = ttk.Button(self.toppane.title2_frame,
|
||||
text=self.schematic, style='normal.TButton', command=self.choose_netlist)
|
||||
self.toppane.title2_frame.schem_select.grid(column=4, row=1, ipadx = 3, padx = 3)
|
||||
|
||||
tooltip.ToolTip(self.toppane.title2_frame.project_select,
|
||||
text = "Select new project")
|
||||
tooltip.ToolTip(self.toppane.title2_frame.layout_select,
|
||||
text = "Select a layout subcirucit to compare")
|
||||
tooltip.ToolTip(self.toppane.title2_frame.schem_select,
|
||||
text = "Select a schematic subcirucit to compare")
|
||||
|
||||
#---------------------------------------------
|
||||
ttk.Separator(self.toppane, orient='horizontal').pack(side = 'top', fill = 'x')
|
||||
#---------------------------------------------
|
||||
|
||||
# Create listbox of Circuit1 vs. Circuit2 results
|
||||
height = 10
|
||||
self.toppane.lvsreport = TreeViewSplit(self.toppane, fontsize = fontsize)
|
||||
self.toppane.lvsreport.populate("Layout:", [], "Schematic:", [],
|
||||
[["Run", True, self.run_lvs],
|
||||
# ["Find", True, self.findrecord]
|
||||
], height = height)
|
||||
self.toppane.lvsreport.set_title("Line")
|
||||
self.toppane.lvsreport.pack(side = 'top', fill = 'both', expand = 'true')
|
||||
|
||||
tooltip.ToolTip(self.toppane.lvsreport.get_button(0), text="Run LVS")
|
||||
|
||||
#---------------------------------------------
|
||||
# ttk.Separator(self, orient='horizontal').grid(column=0, row=3, sticky='ew')
|
||||
#---------------------------------------------
|
||||
|
||||
# Add a text window below the project name to capture output. Redirect
|
||||
# print statements to it.
|
||||
|
||||
self.botpane.console = ttk.Frame(self.botpane)
|
||||
self.botpane.console.pack(side = 'top', fill = 'both', expand = 'true')
|
||||
|
||||
self.text_box = ConsoleText(self.botpane.console, wrap='word', height = 4)
|
||||
self.text_box.pack(side='left', fill='both', expand='true')
|
||||
console_scrollbar = ttk.Scrollbar(self.botpane.console)
|
||||
console_scrollbar.pack(side='right', fill='y')
|
||||
# attach console to scrollbar
|
||||
self.text_box.config(yscrollcommand = console_scrollbar.set)
|
||||
console_scrollbar.config(command = self.text_box.yview)
|
||||
|
||||
# Add button bar at the bottom of the window
|
||||
self.botpane.bbar = ttk.Frame(self.botpane)
|
||||
self.botpane.bbar.pack(side = 'top', fill = 'x')
|
||||
|
||||
# Define the "quit" button and action
|
||||
self.botpane.bbar.quit_button = ttk.Button(self.botpane.bbar, text='Quit', command=self.on_quit,
|
||||
style = 'normal.TButton')
|
||||
self.botpane.bbar.quit_button.grid(column=0, row=0, padx = 5)
|
||||
|
||||
# Define help button
|
||||
if self.help:
|
||||
self.botpane.bbar.help_button = ttk.Button(self.botpane.bbar, text='Help',
|
||||
command=self.help.open, style = 'normal.TButton')
|
||||
self.botpane.bbar.help_button.grid(column = 2, row = 0, padx = 5)
|
||||
tooltip.ToolTip(self.botpane.bbar.help_button, text = "Show help window")
|
||||
|
||||
# Add the panes once the internal geometry is known.
|
||||
pane.add(self.toppane)
|
||||
pane.add(self.botpane)
|
||||
pane.paneconfig(self.toppane, stretch='first')
|
||||
|
||||
# Redirect stdout and stderr to the console as the last thing to do. . .
|
||||
# Otherwise errors in the GUI get sucked into the void.
|
||||
|
||||
self.stdout = sys.stdout
|
||||
self.stderr = sys.stderr
|
||||
sys.stdout = ConsoleText.StdoutRedirector(self.text_box)
|
||||
sys.stderr = ConsoleText.StderrRedirector(self.text_box)
|
||||
|
||||
if message:
|
||||
print(message)
|
||||
|
||||
def logprint(self, message, doflush=False):
|
||||
if self.logfile:
|
||||
self.logfile.buffer.write(message.encode('utf-8'))
|
||||
self.logfile.buffer.write('\n'.encode('utf-8'))
|
||||
if doflush:
|
||||
self.logfile.flush()
|
||||
|
||||
def printout(self, output):
|
||||
# Generate output
|
||||
if not output:
|
||||
return
|
||||
|
||||
outlines = output.splitlines()
|
||||
for line in outlines:
|
||||
try:
|
||||
print(line)
|
||||
except TypeError:
|
||||
line = line.decode('utf-8')
|
||||
pritn(line)
|
||||
|
||||
def printwarn(self, output):
|
||||
# Check output for warning or error
|
||||
if not output:
|
||||
return 0
|
||||
|
||||
warnrex = re.compile('.*warning', re.IGNORECASE)
|
||||
errrex = re.compile('.*error', re.IGNORECASE)
|
||||
|
||||
errors = 0
|
||||
outlines = output.splitlines()
|
||||
for line in outlines:
|
||||
try:
|
||||
wmatch = warnrex.match(line)
|
||||
except TypeError:
|
||||
line = line.decode('utf-8')
|
||||
wmatch = warnrex.match(line)
|
||||
ematch = errrex.match(line)
|
||||
if ematch:
|
||||
errors += 1
|
||||
if ematch or wmatch:
|
||||
print(line)
|
||||
return errors
|
||||
|
||||
def choose_tech(self):
|
||||
try:
|
||||
project_path = self.rootpath
|
||||
initdirname = self.rootpath + '/tech',
|
||||
except:
|
||||
print('Must choose a project first.')
|
||||
return
|
||||
techname = filedialog.askopenfilename(multiple=False,
|
||||
initialdir = initdirname,
|
||||
filetypes = (("Tcl script", "*.tcl"),("All Files","*.*")),
|
||||
title = "Choose a netgen technology setup script.")
|
||||
if techname != '':
|
||||
print("Selected technology setup script " + techname)
|
||||
techbase = os.path.split(techname)[1]
|
||||
self.tech = os.path.splitext(techbase)[0]
|
||||
self.lvs_setup = techname
|
||||
self.toppane.title2_frame.layout_select.config(text = self.tech)
|
||||
|
||||
def choose_layout(self):
|
||||
try:
|
||||
project_path = self.rootpath
|
||||
initdirname = self.rootpath + '/layout',
|
||||
except:
|
||||
print('Must choose a project first.')
|
||||
return
|
||||
cellname = filedialog.askopenfilename(multiple=False,
|
||||
initialdir = initdirname,
|
||||
filetypes = (("Magic layout", "*.mag"),("All Files","*.*")),
|
||||
title = "Choose a layout cell to compare.")
|
||||
if cellname != '':
|
||||
print("Selected compare cell " + cellname)
|
||||
cellbase = os.path.split(cellname)[1]
|
||||
self.layout = os.path.splitext(cellbase)[0]
|
||||
self.toppane.title2_frame.layout_select.config(text = self.layout)
|
||||
|
||||
def choose_netlist(self):
|
||||
try:
|
||||
project_path = self.rootpath
|
||||
initdirname = self.rootpath + '/netlist/' + self.project + '.spi'
|
||||
except:
|
||||
print('Must choose a project first.')
|
||||
return
|
||||
cellname = filedialog.askopenfilename(multiple=False,
|
||||
initialdir = initdirname,
|
||||
filetypes = (("Spice netlist", "*.spi"),("Verilog netlist", "*.v")),
|
||||
title = "Choose a netlist to compare.")
|
||||
if cellname != '':
|
||||
print("Selected compare cell " + cellname)
|
||||
cellbase = os.path.split(cellname)[1]
|
||||
self.schematic = os.path.splitext(cellbase)[0]
|
||||
self.toppane.title2_frame.schem_select.config(text = self.schematic)
|
||||
fileext = os.path.splitext(cellbase)[1]
|
||||
if fileext == '.v':
|
||||
self.toppane.title2_frame.schem_label.config(text = 'Verilog netlist:')
|
||||
elif fileext == '.sp' or fileext == '.spi' or fileext == '.spice' or fileext == '.spc' or fileext == '.ckt':
|
||||
self.toppane.title2_frame.schem_label.config(text = 'SPICE netlist:')
|
||||
elif fileext == '.cdl':
|
||||
self.toppane.title2_frame.schem_label.config(text = 'CDL netlist:')
|
||||
else:
|
||||
self.toppane.title2_frame.schem_label.config(text = 'Unknown netlist:')
|
||||
|
||||
def choose_project(self):
|
||||
project = filedialog.askdirectory(initialdir = os.getcwd(),
|
||||
title = "Find a project.")
|
||||
if project != '':
|
||||
print("Selected project " + str(project))
|
||||
result = self.set_project(project)
|
||||
|
||||
def set_project(self, rootpath, project_name=None):
|
||||
|
||||
# Check if rootpath is valid. For LVS, there should be subdirectories
|
||||
# "layout/" and "netlist/" or "verilog/".
|
||||
|
||||
haslay = os.path.isdir(rootpath + '/layout')
|
||||
hasvlog = os.path.isdir(rootpath + '/verilog')
|
||||
hasnet = os.path.isdir(rootpath + '/netlist')
|
||||
if not haslay or not (hasvlog or hasnet):
|
||||
if not haslay:
|
||||
print("Project path has no layout (/layout) subdirectory.")
|
||||
if not (hasvlog or hasnet):
|
||||
print("Project path has no verilog (/verilog), or netlist (/netlist) subdirectory.")
|
||||
# Continue anyway; assume that netlists will be selected manually
|
||||
|
||||
if self.logfile:
|
||||
self.logfile.close()
|
||||
self.logfile = None
|
||||
|
||||
if not project_name:
|
||||
project = os.path.split(rootpath)[1]
|
||||
else:
|
||||
project = project_name
|
||||
|
||||
if self.project != project:
|
||||
|
||||
self.rootpath = rootpath
|
||||
self.project = project
|
||||
|
||||
# Clear out old project data
|
||||
self.toppane.lvsreport.repopulate([], [])
|
||||
|
||||
# Close any open logfile.
|
||||
if self.logfile:
|
||||
self.logfile.close()
|
||||
self.logfile = None
|
||||
|
||||
# Put new log file called 'lvs.log' in the mag/ subdirectory
|
||||
self.logfile = open(rootpath + '/layout/lvs.log', 'w')
|
||||
# Print some initial information to the logfile.
|
||||
self.logprint('Starting new log file ' + datetime.datetime.now().strftime('%c'),
|
||||
doflush=True)
|
||||
|
||||
# Update project button
|
||||
self.toppane.title2_frame.project_select.config(text = self.project)
|
||||
self.toppane.title2_frame.path_label.config(text = self.rootpath)
|
||||
# Cell name is the same as project name initially
|
||||
self.layout = self.project
|
||||
self.schematic = self.project
|
||||
self.toppane.title2_frame.layout_select.config(text = self.layout)
|
||||
self.toppane.title2_frame.schem_select.config(text = self.schematic)
|
||||
|
||||
# Update schematic button
|
||||
if os.path.isfile(rootpath + '/verilog/' + self.schematic + '.v'):
|
||||
self.toppane.title2_frame.schem_label.config(text = 'Verilog netlist:')
|
||||
else:
|
||||
self.toppane.title2_frame.schem_label.config(text = 'Schematic netlist:')
|
||||
|
||||
# If there is a comparison file that post-dates both netlists, load it.
|
||||
self.check_lvs()
|
||||
return True
|
||||
|
||||
def check_layout_out_of_date(self, spipath, layoutpath):
|
||||
# Check if a netlist (spipath) is out-of-date relative to the layouts
|
||||
# (layoutpath). Need to read the netlist and check all of the subcells.
|
||||
need_capture = False
|
||||
if not os.path.isfile(spipath):
|
||||
return True
|
||||
if os.path.isfile(layoutpath):
|
||||
spi_statbuf = os.stat(spipath)
|
||||
lay_statbuf = os.stat(layoutpath)
|
||||
if spi_statbuf.st_mtime < lay_statbuf.st_mtime:
|
||||
# netlist exists but is out-of-date
|
||||
need_capture = True
|
||||
else:
|
||||
# only found that the top-level-layout is older than the
|
||||
# netlist. Now need to read the netlist, find all subcircuits,
|
||||
# and check those dates, too.
|
||||
layoutdir = os.path.split(layoutpath)[0]
|
||||
subrex = re.compile('^[^\*]*[ \t]*.subckt[ \t]+([^ \t]+).*$', re.IGNORECASE)
|
||||
with open(spipath, 'r') as ifile:
|
||||
duttext = ifile.read()
|
||||
|
||||
dutlines = duttext.replace('\n+', ' ').splitlines()
|
||||
for line in dutlines:
|
||||
lmatch = subrex.match(line)
|
||||
if lmatch:
|
||||
subname = lmatch.group(1)
|
||||
sublayout = layoutdir + '/' + subname + '.mag'
|
||||
# subcircuits that cannot be found in the current directory are
|
||||
# assumed to be library components and therefore never out-of-date.
|
||||
if os.path.exists(sublayout):
|
||||
sub_statbuf = os.stat(sublayout)
|
||||
if spi_statbuf.st_mtime < lay_statbuf.st_mtime:
|
||||
# netlist exists but is out-of-date
|
||||
need_capture = True
|
||||
break
|
||||
return need_capture
|
||||
|
||||
def check_schematic_out_of_date(self, spipath, schempath):
|
||||
# Check if a netlist (spipath) is out-of-date relative to the schematics
|
||||
# (schempath). Need to read the netlist and check all of the subcells.
|
||||
need_capture = False
|
||||
if not os.path.isfile(spipath):
|
||||
return True
|
||||
if os.path.isfile(schempath):
|
||||
spi_statbuf = os.stat(spipath)
|
||||
sch_statbuf = os.stat(schempath)
|
||||
if spi_statbuf.st_mtime < sch_statbuf.st_mtime:
|
||||
# netlist exists but is out-of-date
|
||||
need_capture = True
|
||||
else:
|
||||
# only found that the top-level-schematic is older than the
|
||||
# netlist. Now need to read the netlist, find all subcircuits,
|
||||
# and check those dates, too.
|
||||
schemdir = os.path.split(schempath)[0]
|
||||
subrex = re.compile('^[^\*]*[ \t]*.subckt[ \t]+([^ \t]+).*$', re.IGNORECASE)
|
||||
with open(spipath, 'r') as ifile:
|
||||
duttext = ifile.read()
|
||||
|
||||
dutlines = duttext.replace('\n+', ' ').splitlines()
|
||||
for line in dutlines:
|
||||
lmatch = subrex.match(line)
|
||||
if lmatch:
|
||||
subname = lmatch.group(1)
|
||||
# NOTE: Electric uses library:cell internally to track libraries,
|
||||
# and maps the ":" to "__" in the netlist. Not entirely certain that
|
||||
# the double-underscore uniquely identifies the library:cell. . .
|
||||
librex = re.compile('(.*)__(.*)', re.IGNORECASE)
|
||||
lmatch = librex.match(subname)
|
||||
if lmatch:
|
||||
elecpath = os.path.split(os.path.split(schempath)[0])[0]
|
||||
libname = lmatch.group(1)
|
||||
subschem = elecpath + '/' + libname + '.delib/' + lmatch.group(2) + '.sch'
|
||||
else:
|
||||
libname = {}
|
||||
subschem = schemdir + '/' + subname + '.sch'
|
||||
# subcircuits that cannot be found in the current directory are
|
||||
# assumed to be library components and therefore never out-of-date.
|
||||
if os.path.exists(subschem):
|
||||
sub_statbuf = os.stat(subschem)
|
||||
if spi_statbuf.st_mtime < sub_statbuf.st_mtime:
|
||||
# netlist exists but is out-of-date
|
||||
need_capture = True
|
||||
break
|
||||
# mapping of characters to what's allowed in SPICE makes finding
|
||||
# the associated schematic file a bit difficult. Requires wild-card
|
||||
# searching.
|
||||
elif libname:
|
||||
restr = lmatch.group(2) + '.sch'
|
||||
restr = restr.replace('.', '\.')
|
||||
restr = restr.replace('_', '.')
|
||||
schrex = re.compile(restr, re.IGNORECASE)
|
||||
libpath = elecpath + '/' + libname + '.delib'
|
||||
if os.path.exists(libpath):
|
||||
liblist = os.listdir(libpath)
|
||||
for file in liblist:
|
||||
lmatch = schrex.match(file)
|
||||
if lmatch:
|
||||
subschem = libpath + '/' + file
|
||||
sub_statbuf = os.stat(subschem)
|
||||
if spi_statbuf.st_mtime < sch_statbuf.st_mtime:
|
||||
# netlist exists but is out-of-date
|
||||
need_capture = True
|
||||
break
|
||||
return need_capture
|
||||
|
||||
def check_lvs(self):
|
||||
# If both netlists exist, and comp.json is more recent than both, then
|
||||
# load LVS results from comp.json
|
||||
project_path = self.rootpath
|
||||
project_name = self.project
|
||||
layout_path = project_path + '/layout/' + project_name + '.spc'
|
||||
net_path = project_path + '/netlist/' + project_name + '.spi'
|
||||
comp_path = project_path + '/layout/comp.json'
|
||||
|
||||
if os.path.exists(layout_path) and os.path.exists(net_path) and os.path.exists(comp_path):
|
||||
magtime = os.stat(layout_path).st_mtime
|
||||
schemtime = os.stat(net_path).st_mtime
|
||||
comptime = os.stat(comp_path).st_mtime
|
||||
if comptime > magtime and comptime > schemtime:
|
||||
print("Loading LVS results from file.")
|
||||
self.generate(comp_path)
|
||||
|
||||
def generate_layout_netlist(self, layout_path, layout_src, project_path):
|
||||
# Does layout netlist exist and is it current?
|
||||
if self.check_layout_out_of_date(layout_path, layout_src):
|
||||
print('Generating layout netlist.')
|
||||
self.update_idletasks()
|
||||
mproc = subprocess.Popen(['magic', '-dnull', '-noconsole',
|
||||
self.layout], stdin = subprocess.PIPE, stdout = subprocess.PIPE,
|
||||
stderr = subprocess.PIPE, cwd = project_path + '/layout',
|
||||
universal_newlines = True)
|
||||
mproc.stdin.write("select top cell\n")
|
||||
mproc.stdin.write("expand\n")
|
||||
mproc.stdin.write("extract all\n")
|
||||
mproc.stdin.write("ext2spice hierarchy on\n")
|
||||
mproc.stdin.write("ext2spice format ngspice\n")
|
||||
mproc.stdin.write("ext2spice scale off\n")
|
||||
mproc.stdin.write("ext2spice renumber off\n")
|
||||
mproc.stdin.write("ext2spice subcircuit top auto\n")
|
||||
mproc.stdin.write("ext2spice cthresh infinite\n")
|
||||
mproc.stdin.write("ext2spice rthresh infinite\n")
|
||||
mproc.stdin.write("ext2spice blackbox on\n")
|
||||
mproc.stdin.write("ext2spice -o " + self.layout + ".spi\n")
|
||||
mproc.stdin.write("quit -noprompt\n")
|
||||
magicout = mproc.communicate()[0]
|
||||
self.printwarn(magicout)
|
||||
if mproc.returncode != 0:
|
||||
print('Failure to generate new layout netlist.')
|
||||
return False
|
||||
|
||||
# Move .spi netlist to project_dir/netlist/lvs/
|
||||
shutil.move(project_path + '/layout/' + self.layout + '.spi', layout_path)
|
||||
# Remove extraction files
|
||||
for file in os.listdir(project_path + '/layout'):
|
||||
if os.path.splitext(file)[1] == '.ext':
|
||||
os.remove(project_path + '/layout/' + file)
|
||||
else:
|
||||
print('Layout netlist is up-to-date, not regenerating.')
|
||||
return True
|
||||
|
||||
def run_lvs(self, value):
|
||||
# "value" is ignored (?)
|
||||
|
||||
# Check if netlists exist and are current; otherwise create them.
|
||||
# Then run LVS.
|
||||
|
||||
project_path = self.rootpath
|
||||
project_name = self.project
|
||||
comp_path = project_path + '/layout/comp.json'
|
||||
has_vlog = False
|
||||
vlog_path = project_path + '/verilog/' + project_name + '.v'
|
||||
|
||||
layout_path = project_path + '/netlist/lvs/' + self.layout + '.spi'
|
||||
net_path = project_path + '/netlist/schem/' + self.schematic + '.spi'
|
||||
layout_src = project_path + '/layout/' + self.layout + '.mag'
|
||||
|
||||
# Does the setup file exist (this is optional)?
|
||||
if self.lvs_setup != '' and not os.path.isfile('setup.tcl'):
|
||||
print('No technology setup file selected.')
|
||||
|
||||
# Does schematic netlist exist?
|
||||
if not os.path.isfile(vlog_path) and not os.path.isfile(net_path):
|
||||
print('Error: No schematic netlist or verilog netlist.')
|
||||
return
|
||||
|
||||
# Does LVS netlist subdirectory exist?
|
||||
if not os.path.exists(project_path + '/netlist/lvs'):
|
||||
os.makedirs(project_path + '/netlist/lvs')
|
||||
|
||||
# Does layout netlist exist and is it current?
|
||||
if not self.generate_layout_netlist(layout_path, layout_src, project_path):
|
||||
return False
|
||||
|
||||
# Final check
|
||||
if not os.path.isfile(layout_path):
|
||||
print('Error: No netlist generated from magic.')
|
||||
return
|
||||
|
||||
else:
|
||||
# Read in netlist and convert commas from [X,Y] arrays to vertical bars
|
||||
# as something that can be converted back as necessary. ngspice treats
|
||||
# commas as special characters for some reason.
|
||||
with open(layout_path) as ifile:
|
||||
spitext = ifile.read()
|
||||
|
||||
# spilines = spitext.replace(',', '|')
|
||||
# with open(layout_path, 'w') as ofile:
|
||||
# ofile.write(spilines)
|
||||
|
||||
# Check the netlist to see if the cell to match is a subcircuit. If
|
||||
# not, then assume it is the top level.
|
||||
|
||||
is_subckt = False
|
||||
subrex = re.compile('^[^\*]*[ \t]*.subckt[ \t]+([^ \t]+).*$', re.IGNORECASE)
|
||||
dutlines = spitext.replace('\n+', ' ').splitlines()
|
||||
for line in dutlines:
|
||||
lmatch = subrex.match(line)
|
||||
if lmatch:
|
||||
subname = lmatch.group(1)
|
||||
if subname == self.layout:
|
||||
is_subckt = True
|
||||
break
|
||||
|
||||
if is_subckt:
|
||||
layout_arg = layout_path + ' ' + self.layout
|
||||
layout_text = '"' + layout_arg + '"'
|
||||
else:
|
||||
layout_arg = layout_path
|
||||
layout_text = layout_arg
|
||||
|
||||
if has_vlog:
|
||||
schem_arg = vlog_path + ' ' + self.schematic
|
||||
else:
|
||||
schem_arg = net_path + ' ' + self.schematic
|
||||
schem_text = '"' + schem_arg + '"'
|
||||
|
||||
# Remove any previous comparison output file
|
||||
comp_out_path = os.path.splitext(comp_path)[0] + '.out'
|
||||
if os.path.exists(comp_out_path):
|
||||
os.remove(comp_out_path)
|
||||
|
||||
# Run netgen as subprocess
|
||||
print('Running: netgen -batch lvs ' + layout_text +
|
||||
' ' + schem_text + ' ' + self.lvs_setup + ' ' + comp_out_path +
|
||||
' -json -blackbox')
|
||||
# Note: Because arguments to subprocess are list items, the {filename cell}
|
||||
# pair does *not* have to be quoted or braced. Doing so causes a parse
|
||||
# error.
|
||||
self.lvsproc = subprocess.Popen(['netgen', '-batch', 'lvs',
|
||||
layout_arg, schem_arg,
|
||||
self.lvs_setup, comp_out_path, '-json', '-blackbox'],
|
||||
cwd=project_path + '/layout',
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=0)
|
||||
# This is largely unnecessary as netgen usually runs to completion very quickly.
|
||||
self.watchclock(comp_path)
|
||||
|
||||
def watchclock(self, filename):
|
||||
if self.lvsproc == None:
|
||||
return
|
||||
|
||||
lvs_status = self.lvsproc.poll()
|
||||
sresult = select.select([self.lvsproc.stdout, self.lvsproc.stderr], [], [], 0)[0]
|
||||
if self.lvsproc.stdout in sresult:
|
||||
outstring = self.lvsproc.stdout.readline().decode().strip()
|
||||
self.logprint(outstring, doflush=True)
|
||||
print(outstring)
|
||||
elif self.lvsproc.stderr in sresult:
|
||||
errstring = self.lvsproc.stderr.readline().decode().strip()
|
||||
self.logprint(errstring, doflush = True)
|
||||
print(errstring, file=sys.stderr)
|
||||
|
||||
if lvs_status != None:
|
||||
print("netgen LVS exited with status " + str(lvs_status))
|
||||
self.lvsproc = None
|
||||
if lvs_status != 0:
|
||||
print('Errors encountered in LVS.')
|
||||
self.logprint('Errors in LVS, lvs status = ' + str(lvs_status), doflush=True)
|
||||
# Done; now read comp.json and fill the treeview listbox.
|
||||
self.generate(filename)
|
||||
else:
|
||||
self.after(500, lambda: self.watchclock(filename))
|
||||
|
||||
# Generate display from "comp.out" file (json file now preferred)
|
||||
|
||||
def generate_orig(self, lvspath):
|
||||
lefttext = []
|
||||
righttext = []
|
||||
print("Reading LVS output file " + lvspath)
|
||||
if os.path.exists(lvspath):
|
||||
with open(lvspath, 'r') as ifile:
|
||||
lvslines = ifile.read().splitlines()
|
||||
for line in lvslines:
|
||||
if '|' in line:
|
||||
# parts = line.split('|')
|
||||
# lefttext.append(parts[0])
|
||||
# righttext.append(parts[1])
|
||||
lefttext.append(line[0:42].strip())
|
||||
righttext.append(line[44:].strip())
|
||||
else:
|
||||
lefttext.append(line)
|
||||
righttext.append('')
|
||||
# Populate treeview with text
|
||||
self.toppane.lvsreport.repopulate(lefttext, righttext)
|
||||
|
||||
else:
|
||||
print("Error: No output file generated from LVS.")
|
||||
|
||||
# Generate output from LVS report JSON file comp.json
|
||||
|
||||
def generate(self, lvspath):
|
||||
lefttext = []
|
||||
righttext = []
|
||||
print("Reading LVS output file " + lvspath)
|
||||
if os.path.exists(lvspath):
|
||||
with open(lvspath, 'r') as ifile:
|
||||
self.lvsdata = json.load(ifile)
|
||||
|
||||
# Populate treeview with text
|
||||
self.toppane.lvsreport.json_repopulate(self.lvsdata)
|
||||
|
||||
else:
|
||||
print("Error: No output file generated from LVS.")
|
||||
|
||||
def findrecord(self, value):
|
||||
print("Unimplemented function")
|
||||
|
||||
def findrecord_test(self, value):
|
||||
# Check if socket is defined; if not, attempt to open one
|
||||
if not self.msock:
|
||||
try:
|
||||
self.msock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
except:
|
||||
print("No response from layout tool.")
|
||||
|
||||
if self.msock:
|
||||
self.msock.connect(("0.0.0.0", 12946))
|
||||
self.msock.setblocking(False)
|
||||
if self.msock:
|
||||
# Pull name of net or device from 'value'
|
||||
# This is a test:
|
||||
self.msock.sendall(b'box 0 0 100 100\r\n')
|
||||
|
||||
if __name__ == '__main__':
|
||||
options = []
|
||||
arguments = []
|
||||
for item in sys.argv[1:]:
|
||||
if item.find('-', 0) == 0:
|
||||
options.append(item)
|
||||
else:
|
||||
arguments.append(item)
|
||||
|
||||
root = tkinter.Tk()
|
||||
app = LVSManager(root)
|
||||
if arguments:
|
||||
if len(arguments) >= 2:
|
||||
app.set_project(arguments[0], project_name=arguments[1])
|
||||
else:
|
||||
app.set_project(arguments[0])
|
||||
|
||||
root.mainloop()
|
||||
Executable
+86
@@ -0,0 +1,86 @@
|
||||
#!/bin/env python3
|
||||
#
|
||||
# Dialog class for tkinter
|
||||
|
||||
import os
|
||||
import tkinter
|
||||
from tkinter import ttk
|
||||
|
||||
class Dialog(tkinter.Toplevel):
|
||||
|
||||
def __init__(self, parent, message = None, title = None, seed = None, border = 'blue', **kwargs):
|
||||
|
||||
tkinter.Toplevel.__init__(self, parent)
|
||||
self.transient(parent)
|
||||
|
||||
if title:
|
||||
self.title(title)
|
||||
|
||||
self.configure(background=border, padx=2, pady=2)
|
||||
self.obox = ttk.Frame(self)
|
||||
self.obox.pack(side = 'left', fill = 'both', expand = 'true')
|
||||
|
||||
self.parent = parent
|
||||
self.result = None
|
||||
body = ttk.Frame(self.obox)
|
||||
self.initial_focus = self.body(body, message, seed, **kwargs)
|
||||
body.pack(padx = 5, pady = 5)
|
||||
self.buttonbox()
|
||||
self.grab_set()
|
||||
|
||||
if not self.initial_focus:
|
||||
self.initial_focus = self
|
||||
|
||||
self.protocol("WM_DELETE_WINDOW", self.cancel)
|
||||
self.geometry("+%d+%d" % (parent.winfo_rootx() + 50,
|
||||
parent.winfo_rooty() + 50))
|
||||
|
||||
self.initial_focus.focus_set()
|
||||
self.wait_window(self)
|
||||
|
||||
# Construction hooks
|
||||
|
||||
def body(self, master, **kwargs):
|
||||
# Create dialog body. Return widget that should have
|
||||
# initial focus. This method should be overridden
|
||||
pass
|
||||
|
||||
def buttonbox(self):
|
||||
# Add standard button box. Override if you don't want the
|
||||
# standard buttons
|
||||
|
||||
box = ttk.Frame(self.obox)
|
||||
|
||||
self.okb = ttk.Button(box, text="OK", width=10, command=self.ok, default='active')
|
||||
self.okb.pack(side='left', padx=5, pady=5)
|
||||
w = ttk.Button(box, text="Cancel", width=10, command=self.cancel)
|
||||
w.pack(side='left', padx=5, pady=5)
|
||||
|
||||
self.bind("<Return>", self.ok)
|
||||
self.bind("<Escape>", self.cancel)
|
||||
box.pack(fill='x', expand='true')
|
||||
|
||||
# Standard button semantics
|
||||
|
||||
def ok(self, event=None):
|
||||
|
||||
if not self.validate():
|
||||
self.initial_focus.focus_set() # put focus back
|
||||
return
|
||||
|
||||
self.withdraw()
|
||||
self.update_idletasks()
|
||||
self.result = self.apply()
|
||||
self.cancel()
|
||||
|
||||
def cancel(self, event=None):
|
||||
|
||||
# Put focus back to the parent window
|
||||
self.parent.focus_set()
|
||||
self.destroy()
|
||||
|
||||
def validate(self):
|
||||
return 1 # Override this
|
||||
|
||||
def apply(self):
|
||||
return None # Override this
|
||||
Executable
+158
@@ -0,0 +1,158 @@
|
||||
#!/bin/env python3
|
||||
'''Michael Lange <klappnase (at) freakmail (dot) de>
|
||||
The ToolTip class provides a flexible tooltip widget for tkinter; it is based on IDLE's ToolTip
|
||||
module which unfortunately seems to be broken (at least the version I saw).
|
||||
INITIALIZATION OPTIONS:
|
||||
anchor : where the text should be positioned inside the widget, must be on of "n", "s", "e", "w", "nw" and so on;
|
||||
default is "center"
|
||||
bd : borderwidth of the widget; default is 1 (NOTE: don't use "borderwidth" here)
|
||||
bg : background color to use for the widget; default is "lightyellow" (NOTE: don't use "background")
|
||||
delay : time in ms that it takes for the widget to appear on the screen when the mouse pointer has
|
||||
entered the parent widget; default is 1500
|
||||
fg : foreground (i.e. text) color to use; default is "black" (NOTE: don't use "foreground")
|
||||
follow_mouse : if set to 1 the tooltip will follow the mouse pointer instead of being displayed
|
||||
outside of the parent widget; this may be useful if you want to use tooltips for
|
||||
large widgets like listboxes or canvases; default is 0
|
||||
font : font to use for the widget; default is system specific
|
||||
justify : how multiple lines of text will be aligned, must be "left", "right" or "center"; default is "left"
|
||||
padx : extra space added to the left and right within the widget; default is 4
|
||||
pady : extra space above and below the text; default is 2
|
||||
relief : one of "flat", "ridge", "groove", "raised", "sunken" or "solid"; default is "solid"
|
||||
state : must be "normal" or "disabled"; if set to "disabled" the tooltip will not appear; default is "normal"
|
||||
text : the text that is displayed inside the widget
|
||||
textvariable : if set to an instance of tkinter.StringVar() the variable's value will be used as text for the widget
|
||||
width : width of the widget; the default is 0, which means that "wraplength" will be used to limit the widgets width
|
||||
wraplength : limits the number of characters in each line; default is 150
|
||||
|
||||
WIDGET METHODS:
|
||||
configure(**opts) : change one or more of the widget's options as described above; the changes will take effect the
|
||||
next time the tooltip shows up; NOTE: follow_mouse cannot be changed after widget initialization
|
||||
|
||||
Other widget methods that might be useful if you want to subclass ToolTip:
|
||||
enter() : callback when the mouse pointer enters the parent widget
|
||||
leave() : called when the mouse pointer leaves the parent widget
|
||||
motion() : is called when the mouse pointer moves inside the parent widget if follow_mouse is set to 1 and the
|
||||
tooltip has shown up to continually update the coordinates of the tooltip window
|
||||
coords() : calculates the screen coordinates of the tooltip window
|
||||
create_contents() : creates the contents of the tooltip window (by default a tkinter.Label)
|
||||
'''
|
||||
# Ideas gleaned from PySol
|
||||
|
||||
import tkinter
|
||||
|
||||
class ToolTip:
|
||||
def __init__(self, master, text='Your text here', delay=1500, **opts):
|
||||
self.master = master
|
||||
self._opts = {'anchor':'center', 'bd':1, 'bg':'lightyellow', 'delay':delay, 'fg':'black',\
|
||||
'follow_mouse':0, 'font':None, 'justify':'left', 'padx':4, 'pady':2,\
|
||||
'relief':'solid', 'state':'normal', 'text':text, 'textvariable':None,\
|
||||
'width':0, 'wraplength':150}
|
||||
self.configure(**opts)
|
||||
self._tipwindow = None
|
||||
self._id = None
|
||||
self._id1 = self.master.bind("<Enter>", self.enter, '+')
|
||||
self._id2 = self.master.bind("<Leave>", self.leave, '+')
|
||||
self._id3 = self.master.bind("<ButtonPress>", self.leave, '+')
|
||||
self._follow_mouse = 0
|
||||
if self._opts['follow_mouse']:
|
||||
self._id4 = self.master.bind("<Motion>", self.motion, '+')
|
||||
self._follow_mouse = 1
|
||||
|
||||
def configure(self, **opts):
|
||||
for key in opts:
|
||||
if key in self._opts:
|
||||
self._opts[key] = opts[key]
|
||||
else:
|
||||
KeyError = 'KeyError: Unknown option: "%s"' %key
|
||||
raise KeyError
|
||||
|
||||
##----these methods handle the callbacks on "<Enter>", "<Leave>" and "<Motion>"---------------##
|
||||
##----events on the parent widget; override them if you want to change the widget's behavior--##
|
||||
|
||||
def enter(self, event=None):
|
||||
self._schedule()
|
||||
|
||||
def leave(self, event=None):
|
||||
self._unschedule()
|
||||
self._hide()
|
||||
|
||||
def motion(self, event=None):
|
||||
if self._tipwindow and self._follow_mouse:
|
||||
x, y = self.coords()
|
||||
self._tipwindow.wm_geometry("+%d+%d" % (x, y))
|
||||
|
||||
##------the methods that do the work:---------------------------------------------------------##
|
||||
|
||||
def _schedule(self):
|
||||
self._unschedule()
|
||||
if self._opts['state'] == 'disabled':
|
||||
return
|
||||
self._id = self.master.after(self._opts['delay'], self._show)
|
||||
|
||||
def _unschedule(self):
|
||||
id = self._id
|
||||
self._id = None
|
||||
if id:
|
||||
self.master.after_cancel(id)
|
||||
|
||||
def _show(self):
|
||||
if self._opts['state'] == 'disabled':
|
||||
self._unschedule()
|
||||
return
|
||||
if not self._tipwindow:
|
||||
self._tipwindow = tw = tkinter.Toplevel(self.master)
|
||||
# hide the window until we know the geometry
|
||||
tw.withdraw()
|
||||
tw.wm_overrideredirect(1)
|
||||
|
||||
if tw.tk.call("tk", "windowingsystem") == 'aqua':
|
||||
tw.tk.call("::tk::unsupported::MacWindowStyle", "style", tw._w, "help", "none")
|
||||
|
||||
self.create_contents()
|
||||
tw.update_idletasks()
|
||||
x, y = self.coords()
|
||||
tw.wm_geometry("+%d+%d" % (x, y))
|
||||
tw.deiconify()
|
||||
tw.lift()
|
||||
|
||||
def _hide(self):
|
||||
tw = self._tipwindow
|
||||
self._tipwindow = None
|
||||
if tw:
|
||||
tw.destroy()
|
||||
|
||||
##----these methods might be overridden in derived classes:----------------------------------##
|
||||
|
||||
def coords(self):
|
||||
# The tip window must be completely outside the master widget;
|
||||
# otherwise when the mouse enters the tip window we get
|
||||
# a leave event and it disappears, and then we get an enter
|
||||
# event and it reappears, and so on forever :-(
|
||||
# or we take care that the mouse pointer is always outside the tipwindow :-)
|
||||
tw = self._tipwindow
|
||||
twx, twy = tw.winfo_reqwidth(), tw.winfo_reqheight()
|
||||
w, h = tw.winfo_screenwidth(), tw.winfo_screenheight()
|
||||
# calculate the y coordinate:
|
||||
if self._follow_mouse:
|
||||
y = tw.winfo_pointery() + 20
|
||||
# make sure the tipwindow is never outside the screen:
|
||||
if y + twy > h:
|
||||
y = y - twy - 30
|
||||
else:
|
||||
y = self.master.winfo_rooty() + self.master.winfo_height() + 3
|
||||
if y + twy > h:
|
||||
y = self.master.winfo_rooty() - twy - 3
|
||||
# we can use the same x coord in both cases:
|
||||
x = tw.winfo_pointerx() - twx / 2
|
||||
if x < 0:
|
||||
x = 0
|
||||
elif x + twx > w:
|
||||
x = w - twx
|
||||
return x, y
|
||||
|
||||
def create_contents(self):
|
||||
opts = self._opts.copy()
|
||||
for opt in ('delay', 'follow_mouse', 'state'):
|
||||
del opts[opt]
|
||||
label = tkinter.Label(self._tipwindow, **opts)
|
||||
label.pack()
|
||||
Executable
+653
@@ -0,0 +1,653 @@
|
||||
#!/bin/env python3
|
||||
#
|
||||
# Simple ttk treeview with split view, scrollbar, and
|
||||
# row of callback buttons
|
||||
|
||||
import os
|
||||
import re
|
||||
import itertools
|
||||
|
||||
import tkinter
|
||||
from tkinter import ttk
|
||||
|
||||
#------------------------------------------------------
|
||||
# Tree view used as a multi-column list box
|
||||
#------------------------------------------------------
|
||||
|
||||
class TreeViewSplit(ttk.Frame):
|
||||
def __init__(self, parent, fontsize=11, *args, **kwargs):
|
||||
ttk.Frame.__init__(self, parent, *args, **kwargs)
|
||||
s = ttk.Style()
|
||||
s.configure('normal.TLabel', font=('Helvetica', fontsize))
|
||||
s.configure('title.TLabel', font=('Helvetica', fontsize, 'bold'))
|
||||
s.configure('normal.TButton', font=('Helvetica', fontsize),
|
||||
border = 3, relief = 'raised')
|
||||
s.configure('Treeview.Heading', font=('Helvetica', fontsize, 'bold'))
|
||||
s.configure('Treeview.Column', font=('Helvetica', fontsize))
|
||||
self.fontsize = fontsize
|
||||
|
||||
# Last item is a list of 2-item lists, each containing the name of a button
|
||||
# to place along the button bar at the bottom, and a callback function to
|
||||
# run when the button is pressed.
|
||||
|
||||
def populate(self, title1="", item1list=[], title2="", item2list=[], buttons=[], height=10):
|
||||
self.item1list = item1list[:]
|
||||
self.item2list = item2list[:]
|
||||
columns = [0, 1]
|
||||
|
||||
treeFrame = ttk.Frame(self)
|
||||
treeFrame.pack(side='top', padx=5, pady=5, fill='both', expand='true')
|
||||
|
||||
scrollBar = ttk.Scrollbar(treeFrame)
|
||||
scrollBar.pack(side='right', fill='y')
|
||||
self.treeView = ttk.Treeview(treeFrame, selectmode='browse', columns=columns, height=height)
|
||||
self.treeView.pack(side='left', fill='both', expand='true')
|
||||
scrollBar.config(command=self.treeView.yview)
|
||||
self.treeView.config(yscrollcommand=scrollBar.set)
|
||||
self.treeView.column('#0', width=120, stretch='false')
|
||||
self.treeView.heading(0, text=title1, anchor='w')
|
||||
self.treeView.heading(1, text=title2, anchor='w')
|
||||
buttonFrame = ttk.Frame(self)
|
||||
buttonFrame.pack(side='bottom', fill='x')
|
||||
|
||||
self.treeView.tag_configure('select',background='darkslategray',foreground='white')
|
||||
|
||||
# Test type tags
|
||||
self.treeView.tag_configure('error', font=('Helvetica', self.fontsize - 1), foreground = 'red')
|
||||
self.treeView.tag_configure('clean', font=('Helvetica', self.fontsize - 1), foreground = 'green3')
|
||||
self.treeView.tag_configure('normal', font=('Helvetica', self.fontsize - 1), foreground = 'black')
|
||||
self.treeView.tag_configure('prep', font=('Helvetica', self.fontsize, 'bold italic'),
|
||||
foreground = 'black', anchor = 'center')
|
||||
self.treeView.tag_configure('header1', font=('Helvetica', self.fontsize, 'bold italic'),
|
||||
foreground = 'brown', anchor = 'center')
|
||||
self.treeView.tag_configure('header2', font=('Helvetica', self.fontsize - 1, 'bold'),
|
||||
foreground = 'blue', anchor = 'center')
|
||||
self.treeView.tag_configure('header3', font=('Helvetica', self.fontsize - 1, 'italic'),
|
||||
foreground = 'green4', anchor = 'center')
|
||||
self.treeView.tag_configure('header4', font=('Helvetica', self.fontsize - 1),
|
||||
foreground = 'purple', anchor = 'center')
|
||||
|
||||
|
||||
self.func_buttons = []
|
||||
for button in buttons:
|
||||
func = button[2]
|
||||
# Each func_buttons entry is a list of two items; first is the
|
||||
# button widget, and the second is a boolean that is True if the
|
||||
# button is to be present always, False if the button is only
|
||||
# present when there are entries in the itemlists.
|
||||
self.func_buttons.append([ttk.Button(buttonFrame, text=button[0],
|
||||
style = 'normal.TButton',
|
||||
command = lambda func=func: self.func_callback(func)),
|
||||
button[1]])
|
||||
|
||||
self.selectcallback = None
|
||||
self.lastselected = None
|
||||
self.lasttag = None
|
||||
self.repopulate(item1list, item2list)
|
||||
|
||||
def get_button(self, index):
|
||||
if index >= 0 and index < len(self.func_buttons):
|
||||
return self.func_buttons[index][0]
|
||||
else:
|
||||
return None
|
||||
|
||||
def set_title(self, title):
|
||||
self.treeView.heading('#0', text=title, anchor='w')
|
||||
|
||||
def repopulate(self, item1list=[], item2list=[]):
|
||||
|
||||
# Remove all children of treeview
|
||||
self.treeView.delete(*self.treeView.get_children())
|
||||
|
||||
self.item1list = item1list[:]
|
||||
self.item2list = item2list[:]
|
||||
lines = max(len(self.item1list), len(self.item2list))
|
||||
|
||||
# Parse the information coming from comp.out. This is preferably
|
||||
# handled from inside netgen, but that requires development in netgen.
|
||||
# Note: A top-level group is denoted by an empty string.
|
||||
|
||||
nested = ['']
|
||||
if lines > 0:
|
||||
# print("Create item ID 0 parent = ''")
|
||||
self.treeView.insert(nested[-1], 'end', text='-', iid='0',
|
||||
value=['Initialize', 'Initialize'], tags=['prep'])
|
||||
nested.append('0')
|
||||
tagstyle = 'header1'
|
||||
|
||||
emptyrec = re.compile('^[\t ]*$')
|
||||
subrex = re.compile('Subcircuit summary')
|
||||
cktrex = re.compile('Circuit[\t ]+[12]:[\t ]+([^ \t]+)')
|
||||
netrex = re.compile('NET mismatches')
|
||||
devrex = re.compile('DEVICE mismatches')
|
||||
seprex = re.compile('-----')
|
||||
sumrex = re.compile('Netlists ')
|
||||
matchrex = re.compile('.*\*\*Mismatch\*\*')
|
||||
incircuit = False
|
||||
watchgroup = False
|
||||
groupnum = 0
|
||||
|
||||
for item1, item2, index in zip(self.item1list, self.item2list, range(lines)):
|
||||
cname1 = 'Layout' # Placeholder
|
||||
cname2 = 'Schematic' # Placeholder
|
||||
|
||||
# Remove blank lines from the display
|
||||
lmatch = emptyrec.match(item1)
|
||||
if lmatch:
|
||||
lmatch = emptyrec.match(item2)
|
||||
if lmatch:
|
||||
continue
|
||||
index = str(index + 1)
|
||||
# Parse text to determine how to structure and display it.
|
||||
tagstyle = 'normal'
|
||||
nextnest = None
|
||||
lmatch = subrex.match(item1)
|
||||
if lmatch:
|
||||
nested = [''] # pop back to topmost level
|
||||
nextnest = index
|
||||
tagstyle = 'header1'
|
||||
incircuit = False
|
||||
watchgroup = False
|
||||
groupnum = 0
|
||||
item1 = 'Layout compare'
|
||||
item2 = 'Schematic compare'
|
||||
else:
|
||||
lmatch = cktrex.match(item1)
|
||||
if lmatch and not incircuit:
|
||||
# Pick up circuit names and replace them in the title, then use them
|
||||
# for all following titles.
|
||||
cname1 = lmatch.group(1)
|
||||
lmatch = cktrex.match(item2)
|
||||
cname2 = lmatch.group(1)
|
||||
print("Circuit names " + cname1 + " " + cname2)
|
||||
# Rewrite title
|
||||
cktitem = self.treeView.item(nested[-1], values=[cname1 + ' compare',
|
||||
cname2 + ' compare'])
|
||||
nextnest = index
|
||||
tagstyle = 'header2'
|
||||
incircuit = True
|
||||
item1 = cname1 + ' Summary'
|
||||
item2 = cname2 + ' Summary'
|
||||
elif lmatch:
|
||||
continue
|
||||
else:
|
||||
lmatch = netrex.match(item1)
|
||||
if lmatch:
|
||||
if watchgroup:
|
||||
nested = nested[0:-1]
|
||||
nested = nested[0:-1]
|
||||
nextnest = index
|
||||
tagstyle = 'header2'
|
||||
groupnum = 1
|
||||
watchgroup = True
|
||||
item1 = cname1 + ' Net mismatches'
|
||||
item2 = cname2 + ' Net mismatches'
|
||||
else:
|
||||
lmatch = devrex.match(item1)
|
||||
if lmatch:
|
||||
if watchgroup:
|
||||
nested = nested[0:-1]
|
||||
nested = nested[0:-1]
|
||||
nextnest = index
|
||||
tagstyle = 'header2'
|
||||
groupnum = 1
|
||||
watchgroup = True
|
||||
item1 = cname1 + ' Device mismatches'
|
||||
item2 = cname2 + ' Device mismatches'
|
||||
else:
|
||||
lmatch = seprex.match(item1)
|
||||
if lmatch:
|
||||
if watchgroup:
|
||||
tagstyle = 'header3'
|
||||
item1 = 'Group ' + str(groupnum)
|
||||
item2 = 'Group ' + str(groupnum)
|
||||
if groupnum > 1:
|
||||
nested = nested[0:-1]
|
||||
groupnum += 1
|
||||
nextnest = index
|
||||
watchgroup = False
|
||||
else:
|
||||
if groupnum > 0:
|
||||
watchgroup = True
|
||||
continue
|
||||
else:
|
||||
lmatch = sumrex.match(item1)
|
||||
if lmatch:
|
||||
if watchgroup:
|
||||
nested = nested[0:-1]
|
||||
nested = nested[0:-1]
|
||||
watchgroup = False
|
||||
tagstyle = 'header2'
|
||||
groupnum = 0
|
||||
|
||||
lmatch1 = matchrex.match(item1)
|
||||
lmatch2 = matchrex.match(item2)
|
||||
if lmatch1 or lmatch2:
|
||||
tagstyle='error'
|
||||
|
||||
# print("Create item ID " + str(index) + " parent = " + str(nested[-1]))
|
||||
self.treeView.insert(nested[-1], 'end', text=index, iid=index, value=[item1, item2],
|
||||
tags=[tagstyle])
|
||||
|
||||
if nextnest:
|
||||
nested.append(nextnest)
|
||||
|
||||
for button in self.func_buttons:
|
||||
button[0].pack_forget()
|
||||
|
||||
if lines == 0:
|
||||
self.treeView.insert('', 'end', text='-', value=['(no items)', '(no items)'])
|
||||
for button in self.func_buttons:
|
||||
if button[1]:
|
||||
button[0].pack(side='left', padx = 5)
|
||||
else:
|
||||
for button in self.func_buttons:
|
||||
button[0].pack(side='left', padx = 5)
|
||||
|
||||
# Special routine to pull in the JSON file data produced by netgen-1.5.72
|
||||
def json_repopulate(self, lvsdata):
|
||||
|
||||
# Remove all children of treeview
|
||||
self.treeView.delete(*self.treeView.get_children())
|
||||
|
||||
# Parse the information coming from comp.out. This is preferably
|
||||
# handled from inside netgen, but that requires development in netgen.
|
||||
# Note: A top-level group is denoted by an empty string.
|
||||
|
||||
index = 0
|
||||
errtotal = {}
|
||||
errtotal['net'] = 0
|
||||
errtotal['netmatch'] = 0
|
||||
errtotal['device'] = 0
|
||||
errtotal['devmatch'] = 0
|
||||
errtotal['property'] = 0
|
||||
errtotal['pin'] = 0
|
||||
ncells = len(lvsdata)
|
||||
for c in range(0, ncells):
|
||||
cellrec = lvsdata[c]
|
||||
if c == ncells - 1:
|
||||
topcell = True
|
||||
else:
|
||||
topcell = False
|
||||
|
||||
errcell = {}
|
||||
errcell['net'] = 0
|
||||
errcell['netmatch'] = 0
|
||||
errcell['device'] = 0
|
||||
errcell['devmatch'] = 0
|
||||
errcell['property'] = 0
|
||||
errcell['pin'] = 0;
|
||||
|
||||
cname1 = 'Layout'
|
||||
cname2 = 'Schematic'
|
||||
|
||||
# cellrec is a dictionary. Parse the cell summary, then failing nets,
|
||||
# devices, and properties, and finally pins.
|
||||
|
||||
if 'name' in cellrec:
|
||||
names = cellrec['name']
|
||||
cname1 = names[0]
|
||||
cname2 = names[1]
|
||||
else:
|
||||
# This is an error but don't halt the program because of it.
|
||||
cname1 = '(unknown layout)'
|
||||
cname2 = '(unknown schematic)'
|
||||
|
||||
item1 = cname1
|
||||
item2 = cname2
|
||||
tagstyle = 'header1'
|
||||
index += 1
|
||||
nest0 = index
|
||||
self.treeView.insert('', 'end', text=index, iid=index, value=[item1, item2],
|
||||
tags=[tagstyle])
|
||||
|
||||
if 'devices' in cellrec or 'nets' in cellrec:
|
||||
item1 = cname1 + " Summary"
|
||||
item2 = cname2 + " Summary"
|
||||
tagstyle = 'header2'
|
||||
index += 1
|
||||
nest1 = index
|
||||
self.treeView.insert(nest0, 'end', text=index, iid=index, value=[item1, item2],
|
||||
tags=[tagstyle])
|
||||
|
||||
if 'devices' in cellrec:
|
||||
item1 = cname1 + " Devices"
|
||||
item2 = cname2 + " Devices"
|
||||
tagstyle = 'header3'
|
||||
index += 1
|
||||
nest2 = index
|
||||
self.treeView.insert(nest1, 'end', text=index, iid=index, value=[item1, item2],
|
||||
tags=[tagstyle])
|
||||
|
||||
devices = cellrec['devices']
|
||||
devlist = [val for pair in zip(devices[0], devices[1]) for val in pair]
|
||||
devpair = list(devlist[p:p + 2] for p in range(0, len(devlist), 2))
|
||||
for dev in devpair:
|
||||
c1dev = dev[0]
|
||||
c2dev = dev[1]
|
||||
|
||||
item1 = c1dev[0] + "(" + str(c1dev[1]) + ")"
|
||||
item2 = c2dev[0] + "(" + str(c2dev[1]) + ")"
|
||||
|
||||
diffdevs = abs(c1dev[1] - c2dev[1])
|
||||
if diffdevs == 0:
|
||||
tagstyle = 'normal'
|
||||
else:
|
||||
tagstyle = 'error'
|
||||
errcell['device'] += diffdevs
|
||||
if topcell:
|
||||
errtotal['device'] += diffdevs
|
||||
index += 1
|
||||
nest2 = index
|
||||
self.treeView.insert(nest1, 'end', text=index, iid=index,
|
||||
value=[item1, item2], tags=[tagstyle])
|
||||
|
||||
if 'nets' in cellrec:
|
||||
item1 = cname1 + " Nets"
|
||||
item2 = cname2 + " Nets"
|
||||
tagstyle = 'header3'
|
||||
index += 1
|
||||
nest2 = index
|
||||
self.treeView.insert(nest1, 'end', text=index, iid=index, value=[item1, item2],
|
||||
tags=[tagstyle])
|
||||
|
||||
nets = cellrec['nets']
|
||||
|
||||
item1 = nets[0]
|
||||
item2 = nets[1]
|
||||
diffnets = abs(nets[0] - nets[1])
|
||||
if diffnets == 0:
|
||||
tagstyle = 'normal'
|
||||
else:
|
||||
tagstyle = 'error'
|
||||
errcell['net'] = diffnets
|
||||
if topcell:
|
||||
errtotal['net'] += diffnets
|
||||
index += 1
|
||||
nest2 = index
|
||||
self.treeView.insert(nest1, 'end', text=index, iid=index,
|
||||
value=[item1, item2], tags=[tagstyle])
|
||||
|
||||
if 'badnets' in cellrec:
|
||||
badnets = cellrec['badnets']
|
||||
|
||||
if len(badnets) > 0:
|
||||
item1 = cname1 + " Net Mismatches"
|
||||
item2 = cname2 + " Net Mismatches"
|
||||
tagstyle = 'header2'
|
||||
index += 1
|
||||
nest1 = index
|
||||
self.treeView.insert(nest0, 'end', text=index, iid=index,
|
||||
value=[item1, item2], tags=[tagstyle])
|
||||
|
||||
groupnum = 0
|
||||
for group in badnets:
|
||||
groupc1 = group[0]
|
||||
groupc2 = group[1]
|
||||
nnets = len(groupc1)
|
||||
|
||||
groupnum += 1
|
||||
tagstyle = 'header3'
|
||||
index += 1
|
||||
nest2 = index
|
||||
item1 = "Group " + str(groupnum) + ' (' + str(nnets) + ' nets)'
|
||||
self.treeView.insert(nest1, 'end', text=index, iid=index,
|
||||
value=[item1, item1], tags=[tagstyle])
|
||||
|
||||
tagstyle = 'error'
|
||||
errcell['netmatch'] += nnets
|
||||
if topcell:
|
||||
errtotal['netmatch'] += nnets
|
||||
|
||||
for netnum in range(0, nnets):
|
||||
if netnum > 0:
|
||||
item1 = ""
|
||||
index += 1
|
||||
nest3 = index
|
||||
self.treeView.insert(nest2, 'end', text=index, iid=index,
|
||||
value=[item1, item1], tags=[tagstyle])
|
||||
|
||||
net1 = groupc1[netnum]
|
||||
net2 = groupc2[netnum]
|
||||
tagstyle = 'header4'
|
||||
item1 = net1[0]
|
||||
item2 = net2[0]
|
||||
index += 1
|
||||
nest3 = index
|
||||
self.treeView.insert(nest2, 'end', text=index, iid=index,
|
||||
value=[item1, item2], tags=[tagstyle])
|
||||
|
||||
# Pad shorter device list to the length of the longer one
|
||||
netdevs = list(itertools.zip_longest(net1[1], net2[1]))
|
||||
for devpair in netdevs:
|
||||
devc1 = devpair[0]
|
||||
devc2 = devpair[1]
|
||||
tagstyle = 'normal'
|
||||
if devc1 and devc1[0] != "":
|
||||
item1 = devc1[0] + '/' + devc1[1] + ' = ' + str(devc1[2])
|
||||
else:
|
||||
item1 = ""
|
||||
if devc2 and devc2[0] != "":
|
||||
item2 = devc2[0] + '/' + devc2[1] + ' = ' + str(devc2[2])
|
||||
else:
|
||||
item2 = ""
|
||||
index += 1
|
||||
nest3 = index
|
||||
self.treeView.insert(nest2, 'end', text=index, iid=index,
|
||||
value=[item1, item2], tags=[tagstyle])
|
||||
|
||||
if 'badelements' in cellrec:
|
||||
badelements = cellrec['badelements']
|
||||
|
||||
if len(badelements) > 0:
|
||||
item1 = cname1 + " Device Mismatches"
|
||||
item2 = cname2 + " Device Mismatches"
|
||||
tagstyle = 'header2'
|
||||
index += 1
|
||||
nest1 = index
|
||||
self.treeView.insert(nest0, 'end', text=index, iid=index,
|
||||
value=[item1, item2], tags=[tagstyle])
|
||||
|
||||
groupnum = 0
|
||||
for group in badelements:
|
||||
groupc1 = group[0]
|
||||
groupc2 = group[1]
|
||||
ndevs = len(groupc1)
|
||||
|
||||
groupnum += 1
|
||||
tagstyle = 'header3'
|
||||
index += 1
|
||||
nest2 = index
|
||||
item1 = "Group " + str(groupnum) + ' (' + str(ndevs) + ' devices)'
|
||||
self.treeView.insert(nest1, 'end', text=index, iid=index,
|
||||
value=[item1, item1], tags=[tagstyle])
|
||||
|
||||
tagstyle = 'error'
|
||||
errcell['devmatch'] += ndevs
|
||||
if topcell:
|
||||
errtotal['devmatch'] += ndevs
|
||||
|
||||
for elemnum in range(0, ndevs):
|
||||
if elemnum > 0:
|
||||
item1 = ""
|
||||
index += 1
|
||||
nest3 = index
|
||||
self.treeView.insert(nest2, 'end', text=index, iid=index,
|
||||
value=[item1, item1], tags=[tagstyle])
|
||||
|
||||
elem1 = groupc1[elemnum]
|
||||
elem2 = groupc2[elemnum]
|
||||
tagstyle = 'header4'
|
||||
item1 = elem1[0]
|
||||
item2 = elem2[0]
|
||||
index += 1
|
||||
nest3 = index
|
||||
self.treeView.insert(nest2, 'end', text=index, iid=index,
|
||||
value=[item1, item2], tags=[tagstyle])
|
||||
|
||||
# Pad shorter pin list to the length of the longer one
|
||||
elempins = list(itertools.zip_longest(elem1[1], elem2[1]))
|
||||
for pinpair in elempins:
|
||||
pinc1 = pinpair[0]
|
||||
pinc2 = pinpair[1]
|
||||
tagstyle = 'normal'
|
||||
if pinc1 and pinc1[0] != "":
|
||||
item1 = pinc1[0] + ' = ' + str(pinc1[1])
|
||||
else:
|
||||
item1 = ""
|
||||
if pinc2 and pinc2[0] != "":
|
||||
item2 = pinc2[0] + ' = ' + str(pinc2[1])
|
||||
else:
|
||||
item2 = ""
|
||||
index += 1
|
||||
nest3 = index
|
||||
self.treeView.insert(nest2, 'end', text=index, iid=index,
|
||||
value=[item1, item2], tags=[tagstyle])
|
||||
|
||||
if 'properties' in cellrec:
|
||||
properties = cellrec['properties']
|
||||
numproperr = len(properties)
|
||||
if numproperr > 0:
|
||||
item1 = cname1 + " Properties"
|
||||
item2 = cname2 + " Properties"
|
||||
tagstyle = 'header2'
|
||||
index += 1
|
||||
nest1 = index
|
||||
self.treeView.insert(nest0, 'end', text=index, iid=index, value=[item1, item2],
|
||||
tags=[tagstyle])
|
||||
errcell['property'] = numproperr
|
||||
errtotal['property'] += numproperr
|
||||
|
||||
for prop in properties:
|
||||
|
||||
if prop != properties[0]:
|
||||
item1 = ""
|
||||
index += 1
|
||||
nest2 = index
|
||||
self.treeView.insert(nest1, 'end', text=index, iid=index,
|
||||
value=[item1, item1], tags=[tagstyle])
|
||||
|
||||
propc1 = prop[0]
|
||||
propc2 = prop[1]
|
||||
|
||||
tagstyle = 'header3'
|
||||
item1 = propc1[0]
|
||||
item2 = propc2[0]
|
||||
index += 1
|
||||
nest2 = index
|
||||
self.treeView.insert(nest1, 'end', text=index, iid=index,
|
||||
value=[item1, item2], tags=[tagstyle])
|
||||
|
||||
# Pad shorter property list to the length of the longer one
|
||||
elemprops = list(itertools.zip_longest(propc1[1], propc2[1]))
|
||||
for proppair in elemprops:
|
||||
perrc1 = proppair[0]
|
||||
perrc2 = proppair[1]
|
||||
tagstyle = 'normal'
|
||||
if perrc1 and perrc1[0] != "":
|
||||
item1 = perrc1[0] + ' = ' + str(perrc1[1])
|
||||
else:
|
||||
item1 = ""
|
||||
if perrc2 and perrc2[0] != "":
|
||||
item2 = perrc2[0] + ' = ' + str(perrc2[1])
|
||||
else:
|
||||
item2 = ""
|
||||
index += 1
|
||||
nest2 = index
|
||||
self.treeView.insert(nest1, 'end', text=index, iid=index,
|
||||
value=[item1, item2], tags=[tagstyle])
|
||||
|
||||
if 'pins' in cellrec:
|
||||
item1 = cname1 + " Pins"
|
||||
item2 = cname2 + " Pins"
|
||||
tagstyle = 'header2'
|
||||
index += 1
|
||||
nest1 = index
|
||||
self.treeView.insert(nest0, 'end', text=index, iid=index, value=[item1, item2],
|
||||
tags=[tagstyle])
|
||||
|
||||
pins = cellrec['pins']
|
||||
pinlist = [val for pair in zip(pins[0], pins[1]) for val in pair]
|
||||
pinpair = list(pinlist[p:p + 2] for p in range(0, len(pinlist), 2))
|
||||
for pin in pinpair:
|
||||
item1 = pin[0]
|
||||
item2 = pin[1]
|
||||
if item1.lower() == item2.lower():
|
||||
tagstyle = 'header4'
|
||||
else:
|
||||
tagstyle = 'error'
|
||||
errcell['pin'] += 1
|
||||
if topcell:
|
||||
errtotal['pin'] += 1
|
||||
index += 1
|
||||
nest2 = index
|
||||
self.treeView.insert(nest1, 'end', text=index, iid=index,
|
||||
value=[item1, item2], tags=[tagstyle])
|
||||
|
||||
allcellerror = errcell['net'] + errcell['device'] + errcell['property'] + errcell['pin'] + errcell['netmatch'] + errcell['devmatch']
|
||||
if allcellerror > 0:
|
||||
item1 = 'Errors: Net = ' + str(errcell['net']) + ', Device = ' + str(errcell['device']) + ', Property = ' + str(errcell['property']) + ', Pin = ' + str(errcell['pin']) + ', Net match = ' + str(errcell['netmatch']) + ', Device match = ' + str(errcell['devmatch'])
|
||||
tagstyle = 'error'
|
||||
else:
|
||||
item1 = 'LVS Clean'
|
||||
tagstyle = 'clean'
|
||||
|
||||
item2 = ""
|
||||
index += 1
|
||||
nest0 = index
|
||||
self.treeView.insert('', 'end', text=index, iid=index, value=[item1, item2],
|
||||
tags=[tagstyle])
|
||||
|
||||
item1 = "Final LVS result:"
|
||||
item2 = ""
|
||||
tagstyle = 'header1'
|
||||
index += 1
|
||||
nest0 = index
|
||||
self.treeView.insert('', 'end', text=index, iid=index, value=[item1, item2],
|
||||
tags=[tagstyle])
|
||||
|
||||
allerror = errtotal['net'] + errtotal['device'] + errtotal['property'] + errtotal['pin'] + errtotal['netmatch'] + errtotal['devmatch']
|
||||
if allerror > 0:
|
||||
item1 = 'Errors: Net = ' + str(errtotal['net']) + ', Device = ' + str(errtotal['device']) + ', Property = ' + str(errtotal['property']) + ', Pin = ' + str(errtotal['pin']) + ', Net match = ' + str(errtotal['netmatch']) + ', Device match = ' + str(errtotal['devmatch'])
|
||||
tagstyle = 'error'
|
||||
else:
|
||||
item1 = 'LVS Clean'
|
||||
tagstyle = 'clean'
|
||||
|
||||
item2 = ""
|
||||
index += 1
|
||||
nest0 = index
|
||||
self.treeView.insert('', 'end', text=index, iid=index, value=[item1, item2],
|
||||
tags=[tagstyle])
|
||||
|
||||
for button in self.func_buttons:
|
||||
button[0].pack_forget()
|
||||
|
||||
if index == 0:
|
||||
self.treeView.insert('', 'end', text='-', value=['(no items)', '(no items)'])
|
||||
for button in self.func_buttons:
|
||||
if button[1]:
|
||||
button[0].pack(side='left', padx = 5)
|
||||
else:
|
||||
for button in self.func_buttons:
|
||||
button[0].pack(side='left', padx = 5)
|
||||
|
||||
# Return values from the treeview
|
||||
def getlist(self):
|
||||
return self.treeView.get_children()
|
||||
|
||||
def func_callback(self, callback, event=None):
|
||||
callback(self.treeView.item(self.treeView.selection()))
|
||||
|
||||
def bindselect(self, callback):
|
||||
self.selectcallback = callback
|
||||
|
||||
def setselect(self, value):
|
||||
self.treeView.selection_set(value)
|
||||
|
||||
def selected(self):
|
||||
value = self.treeView.item(self.treeView.selection())
|
||||
if value['values']:
|
||||
return value
|
||||
else:
|
||||
return None
|
||||
@@ -1,767 +0,0 @@
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by netgen configure 1.3, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ ./configure
|
||||
|
||||
## --------- ##
|
||||
## Platform. ##
|
||||
## --------- ##
|
||||
|
||||
hostname = stravinsky
|
||||
uname -m = x86_64
|
||||
uname -r = 3.18.3-201.fc21.x86_64
|
||||
uname -s = Linux
|
||||
uname -v = #1 SMP Mon Jan 19 15:59:31 UTC 2015
|
||||
|
||||
/usr/bin/uname -p = x86_64
|
||||
/bin/uname -X = unknown
|
||||
|
||||
/bin/arch = x86_64
|
||||
/usr/bin/arch -k = unknown
|
||||
/usr/convex/getsysinfo = unknown
|
||||
/usr/bin/hostinfo = unknown
|
||||
/bin/machine = unknown
|
||||
/usr/bin/oslevel = unknown
|
||||
/bin/universe = unknown
|
||||
|
||||
PATH: .
|
||||
PATH: /bin
|
||||
PATH: /sbin
|
||||
PATH: /usr/bin
|
||||
PATH: /usr/sbin
|
||||
PATH: /usr/local/bin
|
||||
|
||||
|
||||
## ----------- ##
|
||||
## Core tests. ##
|
||||
## ----------- ##
|
||||
|
||||
configure:2397: checking build system type
|
||||
configure:2411: result: x86_64-unknown-linux-gnu
|
||||
configure:2431: checking host system type
|
||||
configure:2444: result: x86_64-unknown-linux-gnu
|
||||
configure:2464: checking target system type
|
||||
configure:2477: result: x86_64-unknown-linux-gnu
|
||||
configure:2568: checking for gcc
|
||||
configure:2584: found /bin/gcc
|
||||
configure:2595: result: gcc
|
||||
configure:2824: checking for C compiler version
|
||||
configure:2833: gcc --version >&5
|
||||
gcc (GCC) 4.9.2 20141101 (Red Hat 4.9.2-1)
|
||||
Copyright (C) 2014 Free Software Foundation, Inc.
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
configure:2844: $? = 0
|
||||
configure:2833: gcc -v >&5
|
||||
Using built-in specs.
|
||||
COLLECT_GCC=gcc
|
||||
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.9.2/lto-wrapper
|
||||
Target: x86_64-redhat-linux
|
||||
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.9.2-20141101/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.9.2-20141101/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
|
||||
Thread model: posix
|
||||
gcc version 4.9.2 20141101 (Red Hat 4.9.2-1) (GCC)
|
||||
configure:2844: $? = 0
|
||||
configure:2833: gcc -V >&5
|
||||
gcc: error: unrecognized command line option '-V'
|
||||
gcc: fatal error: no input files
|
||||
compilation terminated.
|
||||
configure:2844: $? = 4
|
||||
configure:2833: gcc -qversion >&5
|
||||
gcc: error: unrecognized command line option '-qversion'
|
||||
gcc: fatal error: no input files
|
||||
compilation terminated.
|
||||
configure:2844: $? = 4
|
||||
configure:2864: checking whether the C compiler works
|
||||
configure:2886: gcc -g conftest.c >&5
|
||||
configure:2890: $? = 0
|
||||
configure:2938: result: yes
|
||||
configure:2941: checking for C compiler default output file name
|
||||
configure:2943: result: a.out
|
||||
configure:2949: checking for suffix of executables
|
||||
configure:2956: gcc -o conftest -g conftest.c >&5
|
||||
configure:2960: $? = 0
|
||||
configure:2982: result:
|
||||
configure:3004: checking whether we are cross compiling
|
||||
configure:3012: gcc -o conftest -g conftest.c >&5
|
||||
configure:3016: $? = 0
|
||||
configure:3023: ./conftest
|
||||
configure:3027: $? = 0
|
||||
configure:3042: result: no
|
||||
configure:3047: checking for suffix of object files
|
||||
configure:3069: gcc -c -g conftest.c >&5
|
||||
configure:3073: $? = 0
|
||||
configure:3094: result: o
|
||||
configure:3098: checking whether we are using the GNU C compiler
|
||||
configure:3117: gcc -c -g conftest.c >&5
|
||||
configure:3117: $? = 0
|
||||
configure:3126: result: yes
|
||||
configure:3135: checking whether gcc accepts -g
|
||||
configure:3155: gcc -c -g conftest.c >&5
|
||||
configure:3155: $? = 0
|
||||
configure:3196: result: yes
|
||||
configure:3213: checking for gcc option to accept ISO C89
|
||||
configure:3276: gcc -c -g conftest.c >&5
|
||||
configure:3276: $? = 0
|
||||
configure:3289: result: none needed
|
||||
configure:3314: checking how to run the C preprocessor
|
||||
configure:3345: gcc -E conftest.c
|
||||
configure:3345: $? = 0
|
||||
configure:3359: gcc -E conftest.c
|
||||
conftest.c:11:28: fatal error: ac_nonexistent.h: No such file or directory
|
||||
#include <ac_nonexistent.h>
|
||||
^
|
||||
compilation terminated.
|
||||
configure:3359: $? = 1
|
||||
configure: failed program was:
|
||||
| /* confdefs.h */
|
||||
| #define PACKAGE_NAME "netgen"
|
||||
| #define PACKAGE_TARNAME "netgen"
|
||||
| #define PACKAGE_VERSION "1.3"
|
||||
| #define PACKAGE_STRING "netgen 1.3"
|
||||
| #define PACKAGE_BUGREPORT "[email protected]"
|
||||
| #define PACKAGE_URL ""
|
||||
| #define NETGEN_VERSION "1.5"
|
||||
| #define NETGEN_REVISION "60"
|
||||
| /* end confdefs.h. */
|
||||
| #include <ac_nonexistent.h>
|
||||
configure:3384: result: gcc -E
|
||||
configure:3404: gcc -E conftest.c
|
||||
configure:3404: $? = 0
|
||||
configure:3418: gcc -E conftest.c
|
||||
conftest.c:11:28: fatal error: ac_nonexistent.h: No such file or directory
|
||||
#include <ac_nonexistent.h>
|
||||
^
|
||||
compilation terminated.
|
||||
configure:3418: $? = 1
|
||||
configure: failed program was:
|
||||
| /* confdefs.h */
|
||||
| #define PACKAGE_NAME "netgen"
|
||||
| #define PACKAGE_TARNAME "netgen"
|
||||
| #define PACKAGE_VERSION "1.3"
|
||||
| #define PACKAGE_STRING "netgen 1.3"
|
||||
| #define PACKAGE_BUGREPORT "[email protected]"
|
||||
| #define PACKAGE_URL ""
|
||||
| #define NETGEN_VERSION "1.5"
|
||||
| #define NETGEN_REVISION "60"
|
||||
| /* end confdefs.h. */
|
||||
| #include <ac_nonexistent.h>
|
||||
configure:3447: checking for library containing strerror
|
||||
configure:3478: gcc -o conftest -g conftest.c >&5
|
||||
configure:3478: $? = 0
|
||||
configure:3495: result: none required
|
||||
configure:3517: checking for a BSD-compatible install
|
||||
configure:3585: result: /bin/install -c
|
||||
configure:3639: checking for ranlib
|
||||
configure:3655: found /bin/ranlib
|
||||
configure:3666: result: ranlib
|
||||
configure:3693: checking for gm4
|
||||
configure:3726: result: no
|
||||
configure:3693: checking for gnum4
|
||||
configure:3726: result: no
|
||||
configure:3693: checking for m4
|
||||
configure:3711: found /bin/m4
|
||||
configure:3723: result: /bin/m4
|
||||
configure:3764: checking for ld used by GCC
|
||||
configure:3827: result: /bin/ld
|
||||
configure:3834: checking if the linker (/bin/ld) is GNU ld
|
||||
GNU ld version 2.24
|
||||
configure:3846: result: yes
|
||||
configure:3853: checking for grep that handles long lines and -e
|
||||
configure:3911: result: /bin/grep
|
||||
configure:3916: checking for egrep
|
||||
configure:3978: result: /bin/grep -E
|
||||
configure:3983: checking for ANSI C header files
|
||||
configure:4003: gcc -c -g conftest.c >&5
|
||||
configure:4003: $? = 0
|
||||
configure:4076: gcc -o conftest -g conftest.c >&5
|
||||
configure:4076: $? = 0
|
||||
configure:4076: ./conftest
|
||||
configure:4076: $? = 0
|
||||
configure:4087: result: yes
|
||||
configure:4100: checking for sys/types.h
|
||||
configure:4100: gcc -c -g conftest.c >&5
|
||||
configure:4100: $? = 0
|
||||
configure:4100: result: yes
|
||||
configure:4100: checking for sys/stat.h
|
||||
configure:4100: gcc -c -g conftest.c >&5
|
||||
configure:4100: $? = 0
|
||||
configure:4100: result: yes
|
||||
configure:4100: checking for stdlib.h
|
||||
configure:4100: gcc -c -g conftest.c >&5
|
||||
configure:4100: $? = 0
|
||||
configure:4100: result: yes
|
||||
configure:4100: checking for string.h
|
||||
configure:4100: gcc -c -g conftest.c >&5
|
||||
configure:4100: $? = 0
|
||||
configure:4100: result: yes
|
||||
configure:4100: checking for memory.h
|
||||
configure:4100: gcc -c -g conftest.c >&5
|
||||
configure:4100: $? = 0
|
||||
configure:4100: result: yes
|
||||
configure:4100: checking for strings.h
|
||||
configure:4100: gcc -c -g conftest.c >&5
|
||||
configure:4100: $? = 0
|
||||
configure:4100: result: yes
|
||||
configure:4100: checking for inttypes.h
|
||||
configure:4100: gcc -c -g conftest.c >&5
|
||||
configure:4100: $? = 0
|
||||
configure:4100: result: yes
|
||||
configure:4100: checking for stdint.h
|
||||
configure:4100: gcc -c -g conftest.c >&5
|
||||
configure:4100: $? = 0
|
||||
configure:4100: result: yes
|
||||
configure:4100: checking for unistd.h
|
||||
configure:4100: gcc -c -g conftest.c >&5
|
||||
configure:4100: $? = 0
|
||||
configure:4100: result: yes
|
||||
configure:4116: checking size of void *
|
||||
configure:4121: gcc -o conftest -g conftest.c >&5
|
||||
configure:4121: $? = 0
|
||||
configure:4121: ./conftest
|
||||
configure:4121: $? = 0
|
||||
configure:4135: result: 8
|
||||
configure:4149: checking size of unsigned int
|
||||
configure:4154: gcc -o conftest -g conftest.c >&5
|
||||
configure:4154: $? = 0
|
||||
configure:4154: ./conftest
|
||||
configure:4154: $? = 0
|
||||
configure:4168: result: 4
|
||||
configure:4182: checking size of unsigned long
|
||||
configure:4187: gcc -o conftest -g conftest.c >&5
|
||||
configure:4187: $? = 0
|
||||
configure:4187: ./conftest
|
||||
configure:4187: $? = 0
|
||||
configure:4201: result: 8
|
||||
configure:4215: checking size of unsigned long long
|
||||
configure:4220: gcc -o conftest -g conftest.c >&5
|
||||
configure:4220: $? = 0
|
||||
configure:4220: ./conftest
|
||||
configure:4220: $? = 0
|
||||
configure:4234: result: 8
|
||||
configure:4245: checking whether byte ordering is bigendian
|
||||
configure:4260: gcc -c -g conftest.c >&5
|
||||
conftest.c:26:9: error: unknown type name 'not'
|
||||
not a universal capable compiler
|
||||
^
|
||||
conftest.c:26:15: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'universal'
|
||||
not a universal capable compiler
|
||||
^
|
||||
conftest.c:26:15: error: unknown type name 'universal'
|
||||
configure:4260: $? = 1
|
||||
configure: failed program was:
|
||||
| /* confdefs.h */
|
||||
| #define PACKAGE_NAME "netgen"
|
||||
| #define PACKAGE_TARNAME "netgen"
|
||||
| #define PACKAGE_VERSION "1.3"
|
||||
| #define PACKAGE_STRING "netgen 1.3"
|
||||
| #define PACKAGE_BUGREPORT "[email protected]"
|
||||
| #define PACKAGE_URL ""
|
||||
| #define NETGEN_VERSION "1.5"
|
||||
| #define NETGEN_REVISION "60"
|
||||
| #define STDC_HEADERS 1
|
||||
| #define HAVE_SYS_TYPES_H 1
|
||||
| #define HAVE_SYS_STAT_H 1
|
||||
| #define HAVE_STDLIB_H 1
|
||||
| #define HAVE_STRING_H 1
|
||||
| #define HAVE_MEMORY_H 1
|
||||
| #define HAVE_STRINGS_H 1
|
||||
| #define HAVE_INTTYPES_H 1
|
||||
| #define HAVE_STDINT_H 1
|
||||
| #define HAVE_UNISTD_H 1
|
||||
| #define SIZEOF_VOID_P 8
|
||||
| #define SIZEOF_UNSIGNED_INT 4
|
||||
| #define SIZEOF_UNSIGNED_LONG 8
|
||||
| #define SIZEOF_UNSIGNED_LONG_LONG 8
|
||||
| /* end confdefs.h. */
|
||||
| #ifndef __APPLE_CC__
|
||||
| not a universal capable compiler
|
||||
| #endif
|
||||
| typedef int dummy;
|
||||
|
|
||||
configure:4305: gcc -c -g conftest.c >&5
|
||||
configure:4305: $? = 0
|
||||
configure:4323: gcc -c -g conftest.c >&5
|
||||
conftest.c: In function 'main':
|
||||
conftest.c:32:4: error: unknown type name 'not'
|
||||
not big endian
|
||||
^
|
||||
conftest.c:32:12: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'endian'
|
||||
not big endian
|
||||
^
|
||||
configure:4323: $? = 1
|
||||
configure: failed program was:
|
||||
| /* confdefs.h */
|
||||
| #define PACKAGE_NAME "netgen"
|
||||
| #define PACKAGE_TARNAME "netgen"
|
||||
| #define PACKAGE_VERSION "1.3"
|
||||
| #define PACKAGE_STRING "netgen 1.3"
|
||||
| #define PACKAGE_BUGREPORT "[email protected]"
|
||||
| #define PACKAGE_URL ""
|
||||
| #define NETGEN_VERSION "1.5"
|
||||
| #define NETGEN_REVISION "60"
|
||||
| #define STDC_HEADERS 1
|
||||
| #define HAVE_SYS_TYPES_H 1
|
||||
| #define HAVE_SYS_STAT_H 1
|
||||
| #define HAVE_STDLIB_H 1
|
||||
| #define HAVE_STRING_H 1
|
||||
| #define HAVE_MEMORY_H 1
|
||||
| #define HAVE_STRINGS_H 1
|
||||
| #define HAVE_INTTYPES_H 1
|
||||
| #define HAVE_STDINT_H 1
|
||||
| #define HAVE_UNISTD_H 1
|
||||
| #define SIZEOF_VOID_P 8
|
||||
| #define SIZEOF_UNSIGNED_INT 4
|
||||
| #define SIZEOF_UNSIGNED_LONG 8
|
||||
| #define SIZEOF_UNSIGNED_LONG_LONG 8
|
||||
| /* end confdefs.h. */
|
||||
| #include <sys/types.h>
|
||||
| #include <sys/param.h>
|
||||
|
|
||||
| int
|
||||
| main ()
|
||||
| {
|
||||
| #if BYTE_ORDER != BIG_ENDIAN
|
||||
| not big endian
|
||||
| #endif
|
||||
|
|
||||
| ;
|
||||
| return 0;
|
||||
| }
|
||||
configure:4451: result: no
|
||||
configure:4470: checking for ANSI C header files
|
||||
configure:4574: result: yes
|
||||
configure:4586: checking for setenv
|
||||
configure:4586: gcc -o conftest -g conftest.c >&5
|
||||
configure:4586: $? = 0
|
||||
configure:4586: result: yes
|
||||
configure:4586: checking for putenv
|
||||
configure:4586: gcc -o conftest -g conftest.c >&5
|
||||
configure:4586: $? = 0
|
||||
configure:4586: result: yes
|
||||
configure:4596: checking for vfork
|
||||
configure:4596: gcc -o conftest -g conftest.c >&5
|
||||
configure:4596: $? = 0
|
||||
configure:4596: result: yes
|
||||
configure:4604: checking dirent.h usability
|
||||
configure:4604: gcc -c -g conftest.c >&5
|
||||
configure:4604: $? = 0
|
||||
configure:4604: result: yes
|
||||
configure:4604: checking dirent.h presence
|
||||
configure:4604: gcc -E -x c conftest.c
|
||||
configure:4604: $? = 0
|
||||
configure:4604: result: yes
|
||||
configure:4604: checking for dirent.h
|
||||
configure:4604: result: yes
|
||||
configure:4617: checking limits.h usability
|
||||
configure:4617: gcc -c -g conftest.c >&5
|
||||
configure:4617: $? = 0
|
||||
configure:4617: result: yes
|
||||
configure:4617: checking limits.h presence
|
||||
configure:4617: gcc -E -x c conftest.c
|
||||
configure:4617: $? = 0
|
||||
configure:4617: result: yes
|
||||
configure:4617: checking for limits.h
|
||||
configure:4617: result: yes
|
||||
configure:4630: checking param.h usability
|
||||
configure:4630: gcc -c -g conftest.c >&5
|
||||
conftest.c:63:19: fatal error: param.h: No such file or directory
|
||||
#include <param.h>
|
||||
^
|
||||
compilation terminated.
|
||||
configure:4630: $? = 1
|
||||
configure: failed program was:
|
||||
| /* confdefs.h */
|
||||
| #define PACKAGE_NAME "netgen"
|
||||
| #define PACKAGE_TARNAME "netgen"
|
||||
| #define PACKAGE_VERSION "1.3"
|
||||
| #define PACKAGE_STRING "netgen 1.3"
|
||||
| #define PACKAGE_BUGREPORT "[email protected]"
|
||||
| #define PACKAGE_URL ""
|
||||
| #define NETGEN_VERSION "1.5"
|
||||
| #define NETGEN_REVISION "60"
|
||||
| #define STDC_HEADERS 1
|
||||
| #define HAVE_SYS_TYPES_H 1
|
||||
| #define HAVE_SYS_STAT_H 1
|
||||
| #define HAVE_STDLIB_H 1
|
||||
| #define HAVE_STRING_H 1
|
||||
| #define HAVE_MEMORY_H 1
|
||||
| #define HAVE_STRINGS_H 1
|
||||
| #define HAVE_INTTYPES_H 1
|
||||
| #define HAVE_STDINT_H 1
|
||||
| #define HAVE_UNISTD_H 1
|
||||
| #define SIZEOF_VOID_P 8
|
||||
| #define SIZEOF_UNSIGNED_INT 4
|
||||
| #define SIZEOF_UNSIGNED_LONG 8
|
||||
| #define SIZEOF_UNSIGNED_LONG_LONG 8
|
||||
| #define STDC_HEADERS 1
|
||||
| #define HAVE_SETENV 1
|
||||
| #define HAVE_PUTENV 1
|
||||
| #define HAVE_DIRENT_H 1
|
||||
| #define HAVE_LIMITS_H 1
|
||||
| /* end confdefs.h. */
|
||||
| #include <stdio.h>
|
||||
| #ifdef HAVE_SYS_TYPES_H
|
||||
| # include <sys/types.h>
|
||||
| #endif
|
||||
| #ifdef HAVE_SYS_STAT_H
|
||||
| # include <sys/stat.h>
|
||||
| #endif
|
||||
| #ifdef STDC_HEADERS
|
||||
| # include <stdlib.h>
|
||||
| # include <stddef.h>
|
||||
| #else
|
||||
| # ifdef HAVE_STDLIB_H
|
||||
| # include <stdlib.h>
|
||||
| # endif
|
||||
| #endif
|
||||
| #ifdef HAVE_STRING_H
|
||||
| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
|
||||
| # include <memory.h>
|
||||
| # endif
|
||||
| # include <string.h>
|
||||
| #endif
|
||||
| #ifdef HAVE_STRINGS_H
|
||||
| # include <strings.h>
|
||||
| #endif
|
||||
| #ifdef HAVE_INTTYPES_H
|
||||
| # include <inttypes.h>
|
||||
| #endif
|
||||
| #ifdef HAVE_STDINT_H
|
||||
| # include <stdint.h>
|
||||
| #endif
|
||||
| #ifdef HAVE_UNISTD_H
|
||||
| # include <unistd.h>
|
||||
| #endif
|
||||
| #include <param.h>
|
||||
configure:4630: result: no
|
||||
configure:4630: checking param.h presence
|
||||
configure:4630: gcc -E -x c conftest.c
|
||||
conftest.c:30:19: fatal error: param.h: No such file or directory
|
||||
#include <param.h>
|
||||
^
|
||||
compilation terminated.
|
||||
configure:4630: $? = 1
|
||||
configure: failed program was:
|
||||
| /* confdefs.h */
|
||||
| #define PACKAGE_NAME "netgen"
|
||||
| #define PACKAGE_TARNAME "netgen"
|
||||
| #define PACKAGE_VERSION "1.3"
|
||||
| #define PACKAGE_STRING "netgen 1.3"
|
||||
| #define PACKAGE_BUGREPORT "[email protected]"
|
||||
| #define PACKAGE_URL ""
|
||||
| #define NETGEN_VERSION "1.5"
|
||||
| #define NETGEN_REVISION "60"
|
||||
| #define STDC_HEADERS 1
|
||||
| #define HAVE_SYS_TYPES_H 1
|
||||
| #define HAVE_SYS_STAT_H 1
|
||||
| #define HAVE_STDLIB_H 1
|
||||
| #define HAVE_STRING_H 1
|
||||
| #define HAVE_MEMORY_H 1
|
||||
| #define HAVE_STRINGS_H 1
|
||||
| #define HAVE_INTTYPES_H 1
|
||||
| #define HAVE_STDINT_H 1
|
||||
| #define HAVE_UNISTD_H 1
|
||||
| #define SIZEOF_VOID_P 8
|
||||
| #define SIZEOF_UNSIGNED_INT 4
|
||||
| #define SIZEOF_UNSIGNED_LONG 8
|
||||
| #define SIZEOF_UNSIGNED_LONG_LONG 8
|
||||
| #define STDC_HEADERS 1
|
||||
| #define HAVE_SETENV 1
|
||||
| #define HAVE_PUTENV 1
|
||||
| #define HAVE_DIRENT_H 1
|
||||
| #define HAVE_LIMITS_H 1
|
||||
| /* end confdefs.h. */
|
||||
| #include <param.h>
|
||||
configure:4630: result: no
|
||||
configure:4630: checking for param.h
|
||||
configure:4630: result: no
|
||||
configure:4641: checking for va_copy
|
||||
configure:4659: gcc -o conftest -g conftest.c >&5
|
||||
configure:4659: $? = 0
|
||||
configure:4668: result: yes
|
||||
configure:4676: checking for __va_copy
|
||||
configure:4694: gcc -o conftest -g conftest.c >&5
|
||||
configure:4694: $? = 0
|
||||
configure:4703: result: yes
|
||||
configure:4834: checking for tclConfig.sh
|
||||
configure:4906: result: /usr/lib64/tclConfig.sh
|
||||
configure:4922: checking for tkConfig.sh
|
||||
configure:4995: result: /usr/lib64/tkConfig.sh
|
||||
configure:5128: checking for wish executable
|
||||
configure:5155: result: /usr/bin/wish
|
||||
configure:5161: checking for tclsh executable
|
||||
configure:5187: result: /usr/bin/tclsh
|
||||
configure:5310: checking for X
|
||||
configure:5449: gcc -o conftest -g conftest.c -lX11 >&5
|
||||
configure:5449: $? = 0
|
||||
configure:5499: result: libraries , headers
|
||||
configure:5598: gcc -o conftest -g conftest.c -lX11 >&5
|
||||
configure:5598: $? = 0
|
||||
configure:5696: checking for gethostbyname
|
||||
configure:5696: gcc -o conftest -g conftest.c >&5
|
||||
configure:5696: $? = 0
|
||||
configure:5696: result: yes
|
||||
configure:5793: checking for connect
|
||||
configure:5793: gcc -o conftest -g conftest.c >&5
|
||||
configure:5793: $? = 0
|
||||
configure:5793: result: yes
|
||||
configure:5842: checking for remove
|
||||
configure:5842: gcc -o conftest -g conftest.c >&5
|
||||
configure:5842: $? = 0
|
||||
configure:5842: result: yes
|
||||
configure:5891: checking for shmat
|
||||
configure:5891: gcc -o conftest -g conftest.c >&5
|
||||
configure:5891: $? = 0
|
||||
configure:5891: result: yes
|
||||
configure:5949: checking for IceConnectionNumber in -lICE
|
||||
configure:5974: gcc -o conftest -g conftest.c -lICE >&5
|
||||
configure:5974: $? = 0
|
||||
configure:5983: result: yes
|
||||
configure:6705: creating ./config.status
|
||||
|
||||
## ---------------------- ##
|
||||
## Running config.status. ##
|
||||
## ---------------------- ##
|
||||
|
||||
This file was extended by netgen config.status 1.3, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES =
|
||||
CONFIG_HEADERS =
|
||||
CONFIG_LINKS =
|
||||
CONFIG_COMMANDS =
|
||||
$ ./config.status
|
||||
|
||||
on stravinsky
|
||||
|
||||
config.status:783: creating defs.mak
|
||||
config.status:886: WARNING: 'defs.mak.in' seems to ignore the --datarootdir setting
|
||||
|
||||
## ---------------- ##
|
||||
## Cache variables. ##
|
||||
## ---------------- ##
|
||||
|
||||
ac_cv_build=x86_64-unknown-linux-gnu
|
||||
ac_cv_c___va_copy=yes
|
||||
ac_cv_c_bigendian=no
|
||||
ac_cv_c_compiler_gnu=yes
|
||||
ac_cv_c_va_copy=yes
|
||||
ac_cv_env_CC_set=
|
||||
ac_cv_env_CC_value=
|
||||
ac_cv_env_CFLAGS_set=set
|
||||
ac_cv_env_CFLAGS_value=-g
|
||||
ac_cv_env_CPPFLAGS_set=
|
||||
ac_cv_env_CPPFLAGS_value=
|
||||
ac_cv_env_CPP_set=
|
||||
ac_cv_env_CPP_value=
|
||||
ac_cv_env_LDFLAGS_set=
|
||||
ac_cv_env_LDFLAGS_value=
|
||||
ac_cv_env_LIBS_set=
|
||||
ac_cv_env_LIBS_value=
|
||||
ac_cv_env_XMKMF_set=
|
||||
ac_cv_env_XMKMF_value=
|
||||
ac_cv_env_build_alias_set=
|
||||
ac_cv_env_build_alias_value=
|
||||
ac_cv_env_host_alias_set=
|
||||
ac_cv_env_host_alias_value=
|
||||
ac_cv_env_target_alias_set=
|
||||
ac_cv_env_target_alias_value=
|
||||
ac_cv_func_connect=yes
|
||||
ac_cv_func_gethostbyname=yes
|
||||
ac_cv_func_putenv=yes
|
||||
ac_cv_func_remove=yes
|
||||
ac_cv_func_setenv=yes
|
||||
ac_cv_func_shmat=yes
|
||||
ac_cv_func_vfork=yes
|
||||
ac_cv_have_x='have_x=yes ac_x_includes='\'''\'' ac_x_libraries='\'''\'''
|
||||
ac_cv_header_dirent_h=yes
|
||||
ac_cv_header_inttypes_h=yes
|
||||
ac_cv_header_limits_h=yes
|
||||
ac_cv_header_memory_h=yes
|
||||
ac_cv_header_param_h=no
|
||||
ac_cv_header_stdc=yes
|
||||
ac_cv_header_stdint_h=yes
|
||||
ac_cv_header_stdlib_h=yes
|
||||
ac_cv_header_string_h=yes
|
||||
ac_cv_header_strings_h=yes
|
||||
ac_cv_header_sys_stat_h=yes
|
||||
ac_cv_header_sys_types_h=yes
|
||||
ac_cv_header_unistd_h=yes
|
||||
ac_cv_host=x86_64-unknown-linux-gnu
|
||||
ac_cv_lib_ICE_IceConnectionNumber=yes
|
||||
ac_cv_objext=o
|
||||
ac_cv_path_EGREP='/bin/grep -E'
|
||||
ac_cv_path_GREP=/bin/grep
|
||||
ac_cv_path_LD=/bin/ld
|
||||
ac_cv_path_M4=/bin/m4
|
||||
ac_cv_path_install='/bin/install -c'
|
||||
ac_cv_prog_CPP='gcc -E'
|
||||
ac_cv_prog_ac_ct_CC=gcc
|
||||
ac_cv_prog_ac_ct_RANLIB=ranlib
|
||||
ac_cv_prog_cc_c89=
|
||||
ac_cv_prog_cc_g=yes
|
||||
ac_cv_prog_gnu_ld=yes
|
||||
ac_cv_search_strerror='none required'
|
||||
ac_cv_sizeof_unsigned_int=4
|
||||
ac_cv_sizeof_unsigned_long=8
|
||||
ac_cv_sizeof_unsigned_long_long=8
|
||||
ac_cv_sizeof_void_p=8
|
||||
ac_cv_target=x86_64-unknown-linux-gnu
|
||||
|
||||
## ----------------- ##
|
||||
## Output variables. ##
|
||||
## ----------------- ##
|
||||
|
||||
ALL_TARGET='tcl'
|
||||
CC='gcc'
|
||||
CFLAGS='-g -m64 -fPIC'
|
||||
CPP='gcc -E -x c'
|
||||
CPPFLAGS=''
|
||||
DEFS='-DPACKAGE_NAME=\"netgen\" -DPACKAGE_TARNAME=\"netgen\" -DPACKAGE_VERSION=\"1.3\" -DPACKAGE_STRING=\"netgen\ 1.3\" -DPACKAGE_BUGREPORT=\"[email protected]\" -DPACKAGE_URL=\"\" -DNETGEN_VERSION=\"1.5\" -DNETGEN_REVISION=\"60\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DSIZEOF_VOID_P=8 -DSIZEOF_UNSIGNED_INT=4 -DSIZEOF_UNSIGNED_LONG=8 -DSIZEOF_UNSIGNED_LONG_LONG=8 -DSTDC_HEADERS=1 -DHAVE_SETENV=1 -DHAVE_PUTENV=1 -DHAVE_DIRENT_H=1 -DHAVE_LIMITS_H=1 -DHAVE_VA_COPY=1 -DHAVE___VA_COPY=1 -DDBUG_OFF=1 -DTCL_NETGEN=1 -Dlinux=1 -DSYSV=1 -DISC=1'
|
||||
DEPEND_FLAG='-MM'
|
||||
ECHO_C=''
|
||||
ECHO_N='printf'
|
||||
ECHO_T=''
|
||||
EGREP='/bin/grep -E'
|
||||
EXEEXT=''
|
||||
EXTRA_LIB_SPECS='-ldl'
|
||||
GREP='/bin/grep'
|
||||
INC_SPECS=''
|
||||
INSTALL_DATA='${INSTALL} -m 644'
|
||||
INSTALL_PROGRAM='${INSTALL}'
|
||||
INSTALL_SCRIPT='${INSTALL}'
|
||||
INSTALL_TARGET='install-tcl'
|
||||
LD='/bin/ld'
|
||||
LDDL_FLAGS=' -shared -Wl,-soname,$@ -Wl,--version-script=${NETGENDIR}/netgen/symbol.map'
|
||||
LDFLAGS=''
|
||||
LD_RUN_PATH=''
|
||||
LIBOBJS=''
|
||||
LIBS=''
|
||||
LIB_SPECS=' -L/usr/lib64 -ltkstub8.6 -L/usr/lib64 -ltclstub8.6'
|
||||
LIB_SPECS_NOSTUB=' -L/usr/lib64 -ltk8.6 -L/usr/lib64 -ltcl8.6'
|
||||
LTLIBOBJS=''
|
||||
M4='/bin/m4'
|
||||
OBJEXT='o'
|
||||
PACKAGE='netgen'
|
||||
PACKAGE_BUGREPORT='[email protected]'
|
||||
PACKAGE_NAME='netgen'
|
||||
PACKAGE_STRING='netgen 1.3'
|
||||
PACKAGE_TARNAME='netgen'
|
||||
PACKAGE_URL=''
|
||||
PACKAGE_VERSION='1.3'
|
||||
PATH_SEPARATOR=':'
|
||||
RANLIB='ranlib'
|
||||
SCRIPTS=''
|
||||
SHDLIB_EXT='.so'
|
||||
SHELL='/bin/sh'
|
||||
SHLIB_CFLAGS='-fPIC'
|
||||
SHLIB_LD=''
|
||||
SHLIB_LIB_SPECS=''
|
||||
TCLSH_EXE='/usr/bin/tclsh'
|
||||
TCL_LIB_DIR='/usr/lib'
|
||||
VERSION=''
|
||||
WISH_EXE='/usr/bin/wish'
|
||||
XMKMF=''
|
||||
X_CFLAGS=''
|
||||
X_EXTRA_LIBS=''
|
||||
X_LIBS=''
|
||||
X_PRE_LIBS=' -lSM -lICE'
|
||||
ac_ct_CC='gcc'
|
||||
bindir='${exec_prefix}/bin'
|
||||
build='x86_64-unknown-linux-gnu'
|
||||
build_alias=''
|
||||
build_cpu='x86_64'
|
||||
build_os='linux-gnu'
|
||||
build_vendor='unknown'
|
||||
cadinstall=' tcltk'
|
||||
datadir='${datarootdir}'
|
||||
datarootdir='${prefix}/share'
|
||||
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
|
||||
dvidir='${docdir}'
|
||||
exec_prefix='${prefix}'
|
||||
extra_defs=' -DCAD_DIR=\"${LIBDIR}\" -DTCL_DIR=\"${TCLDIR}\"'
|
||||
extra_libs=' ${NETGENDIR}/tcltk/libtcltk.o'
|
||||
gr_cflags=''
|
||||
gr_dflags=' -DX11 -DXLIB'
|
||||
gr_libs=' -lX11'
|
||||
gr_srcs=' ${TK_SRCS}'
|
||||
host='x86_64-unknown-linux-gnu'
|
||||
host_alias=''
|
||||
host_cpu='x86_64'
|
||||
host_os='linux-gnu'
|
||||
host_vendor='unknown'
|
||||
htmldir='${docdir}'
|
||||
includedir='${prefix}/include'
|
||||
infodir='${datarootdir}/info'
|
||||
ld_extra_libs=''
|
||||
ld_extra_objs=''
|
||||
libdir='${exec_prefix}/lib'
|
||||
libexecdir='${exec_prefix}/libexec'
|
||||
localedir='${datarootdir}/locale'
|
||||
localstatedir='${prefix}/var'
|
||||
mandir='${datarootdir}/man'
|
||||
modules=' tcltk'
|
||||
oldincludedir='/usr/include'
|
||||
pdfdir='${docdir}'
|
||||
prefix='/usr/local'
|
||||
program_transform_name='s,x,x,'
|
||||
programs=' tcltk'
|
||||
psdir='${docdir}'
|
||||
sbindir='${exec_prefix}/sbin'
|
||||
sharedstatedir='${prefix}/com'
|
||||
stub_defs=' -DUSE_TCL_STUBS -DUSE_TK_STUBS'
|
||||
sub_extra_libs=''
|
||||
sysconfdir='${prefix}/etc'
|
||||
target='x86_64-unknown-linux-gnu'
|
||||
target_alias=''
|
||||
target_cpu='x86_64'
|
||||
target_os='linux-gnu'
|
||||
target_vendor='unknown'
|
||||
top_extra_libs=''
|
||||
unused=''
|
||||
|
||||
## ----------- ##
|
||||
## confdefs.h. ##
|
||||
## ----------- ##
|
||||
|
||||
/* confdefs.h */
|
||||
#define PACKAGE_NAME "netgen"
|
||||
#define PACKAGE_TARNAME "netgen"
|
||||
#define PACKAGE_VERSION "1.3"
|
||||
#define PACKAGE_STRING "netgen 1.3"
|
||||
#define PACKAGE_BUGREPORT "[email protected]"
|
||||
#define PACKAGE_URL ""
|
||||
#define NETGEN_VERSION "1.5"
|
||||
#define NETGEN_REVISION "60"
|
||||
#define STDC_HEADERS 1
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
#define HAVE_STDLIB_H 1
|
||||
#define HAVE_STRING_H 1
|
||||
#define HAVE_MEMORY_H 1
|
||||
#define HAVE_STRINGS_H 1
|
||||
#define HAVE_INTTYPES_H 1
|
||||
#define HAVE_STDINT_H 1
|
||||
#define HAVE_UNISTD_H 1
|
||||
#define SIZEOF_VOID_P 8
|
||||
#define SIZEOF_UNSIGNED_INT 4
|
||||
#define SIZEOF_UNSIGNED_LONG 8
|
||||
#define SIZEOF_UNSIGNED_LONG_LONG 8
|
||||
#define STDC_HEADERS 1
|
||||
#define HAVE_SETENV 1
|
||||
#define HAVE_PUTENV 1
|
||||
#define HAVE_DIRENT_H 1
|
||||
#define HAVE_LIMITS_H 1
|
||||
#define HAVE_VA_COPY 1
|
||||
#define HAVE___VA_COPY 1
|
||||
#define DBUG_OFF 1
|
||||
#define TCL_NETGEN 1
|
||||
#define linux 1
|
||||
#define SYSV 1
|
||||
#define ISC 1
|
||||
|
||||
configure: exit 0
|
||||
@@ -1,940 +0,0 @@
|
||||
#! /bin/sh
|
||||
# Generated by configure.
|
||||
# Run this file to recreate the current configuration.
|
||||
# Compiler output produced by configure, useful for debugging
|
||||
# configure, is in config.log if it exists.
|
||||
|
||||
debug=false
|
||||
ac_cs_recheck=false
|
||||
ac_cs_silent=false
|
||||
|
||||
SHELL=${CONFIG_SHELL-/bin/sh}
|
||||
export SHELL
|
||||
## -------------------- ##
|
||||
## M4sh Initialization. ##
|
||||
## -------------------- ##
|
||||
|
||||
# Be more Bourne compatible
|
||||
DUALCASE=1; export DUALCASE # for MKS sh
|
||||
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
|
||||
emulate sh
|
||||
NULLCMD=:
|
||||
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
|
||||
# is contrary to our usage. Disable this feature.
|
||||
alias -g '${1+"$@"}'='"$@"'
|
||||
setopt NO_GLOB_SUBST
|
||||
else
|
||||
case `(set -o) 2>/dev/null` in #(
|
||||
*posix*) :
|
||||
set -o posix ;; #(
|
||||
*) :
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
|
||||
as_nl='
|
||||
'
|
||||
export as_nl
|
||||
# Printing a long string crashes Solaris 7 /usr/bin/printf.
|
||||
as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
|
||||
as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
|
||||
as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
|
||||
# Prefer a ksh shell builtin over an external printf program on Solaris,
|
||||
# but without wasting forks for bash or zsh.
|
||||
if test -z "$BASH_VERSION$ZSH_VERSION" \
|
||||
&& (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
|
||||
as_echo='print -r --'
|
||||
as_echo_n='print -rn --'
|
||||
elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
|
||||
as_echo='printf %s\n'
|
||||
as_echo_n='printf %s'
|
||||
else
|
||||
if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
|
||||
as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
|
||||
as_echo_n='/usr/ucb/echo -n'
|
||||
else
|
||||
as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
|
||||
as_echo_n_body='eval
|
||||
arg=$1;
|
||||
case $arg in #(
|
||||
*"$as_nl"*)
|
||||
expr "X$arg" : "X\\(.*\\)$as_nl";
|
||||
arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
|
||||
esac;
|
||||
expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
|
||||
'
|
||||
export as_echo_n_body
|
||||
as_echo_n='sh -c $as_echo_n_body as_echo'
|
||||
fi
|
||||
export as_echo_body
|
||||
as_echo='sh -c $as_echo_body as_echo'
|
||||
fi
|
||||
|
||||
# The user is always right.
|
||||
if test "${PATH_SEPARATOR+set}" != set; then
|
||||
PATH_SEPARATOR=:
|
||||
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
|
||||
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
|
||||
PATH_SEPARATOR=';'
|
||||
}
|
||||
fi
|
||||
|
||||
|
||||
# IFS
|
||||
# We need space, tab and new line, in precisely that order. Quoting is
|
||||
# there to prevent editors from complaining about space-tab.
|
||||
# (If _AS_PATH_WALK were called with IFS unset, it would disable word
|
||||
# splitting by setting IFS to empty value.)
|
||||
IFS=" "" $as_nl"
|
||||
|
||||
# Find who we are. Look in the path if we contain no directory separator.
|
||||
as_myself=
|
||||
case $0 in #((
|
||||
*[\\/]* ) as_myself=$0 ;;
|
||||
*) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
;;
|
||||
esac
|
||||
# We did not find ourselves, most probably we were run as `sh COMMAND'
|
||||
# in which case we are not to be found in the path.
|
||||
if test "x$as_myself" = x; then
|
||||
as_myself=$0
|
||||
fi
|
||||
if test ! -f "$as_myself"; then
|
||||
$as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Unset variables that we do not need and which cause bugs (e.g. in
|
||||
# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
|
||||
# suppresses any "Segmentation fault" message there. '((' could
|
||||
# trigger a bug in pdksh 5.2.14.
|
||||
for as_var in BASH_ENV ENV MAIL MAILPATH
|
||||
do eval test x\${$as_var+set} = xset \
|
||||
&& ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
|
||||
done
|
||||
PS1='$ '
|
||||
PS2='> '
|
||||
PS4='+ '
|
||||
|
||||
# NLS nuisances.
|
||||
LC_ALL=C
|
||||
export LC_ALL
|
||||
LANGUAGE=C
|
||||
export LANGUAGE
|
||||
|
||||
# CDPATH.
|
||||
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
|
||||
|
||||
|
||||
# as_fn_error STATUS ERROR [LINENO LOG_FD]
|
||||
# ----------------------------------------
|
||||
# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
|
||||
# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
|
||||
# script with STATUS, using 1 if that was 0.
|
||||
as_fn_error ()
|
||||
{
|
||||
as_status=$1; test $as_status -eq 0 && as_status=1
|
||||
if test "$4"; then
|
||||
as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
|
||||
fi
|
||||
$as_echo "$as_me: error: $2" >&2
|
||||
as_fn_exit $as_status
|
||||
} # as_fn_error
|
||||
|
||||
|
||||
# as_fn_set_status STATUS
|
||||
# -----------------------
|
||||
# Set $? to STATUS, without forking.
|
||||
as_fn_set_status ()
|
||||
{
|
||||
return $1
|
||||
} # as_fn_set_status
|
||||
|
||||
# as_fn_exit STATUS
|
||||
# -----------------
|
||||
# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
|
||||
as_fn_exit ()
|
||||
{
|
||||
set +e
|
||||
as_fn_set_status $1
|
||||
exit $1
|
||||
} # as_fn_exit
|
||||
|
||||
# as_fn_unset VAR
|
||||
# ---------------
|
||||
# Portably unset VAR.
|
||||
as_fn_unset ()
|
||||
{
|
||||
{ eval $1=; unset $1;}
|
||||
}
|
||||
as_unset=as_fn_unset
|
||||
# as_fn_append VAR VALUE
|
||||
# ----------------------
|
||||
# Append the text in VALUE to the end of the definition contained in VAR. Take
|
||||
# advantage of any shell optimizations that allow amortized linear growth over
|
||||
# repeated appends, instead of the typical quadratic growth present in naive
|
||||
# implementations.
|
||||
if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
|
||||
eval 'as_fn_append ()
|
||||
{
|
||||
eval $1+=\$2
|
||||
}'
|
||||
else
|
||||
as_fn_append ()
|
||||
{
|
||||
eval $1=\$$1\$2
|
||||
}
|
||||
fi # as_fn_append
|
||||
|
||||
# as_fn_arith ARG...
|
||||
# ------------------
|
||||
# Perform arithmetic evaluation on the ARGs, and store the result in the
|
||||
# global $as_val. Take advantage of shells that can avoid forks. The arguments
|
||||
# must be portable across $(()) and expr.
|
||||
if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
|
||||
eval 'as_fn_arith ()
|
||||
{
|
||||
as_val=$(( $* ))
|
||||
}'
|
||||
else
|
||||
as_fn_arith ()
|
||||
{
|
||||
as_val=`expr "$@" || test $? -eq 1`
|
||||
}
|
||||
fi # as_fn_arith
|
||||
|
||||
|
||||
if expr a : '\(a\)' >/dev/null 2>&1 &&
|
||||
test "X`expr 00001 : '.*\(...\)'`" = X001; then
|
||||
as_expr=expr
|
||||
else
|
||||
as_expr=false
|
||||
fi
|
||||
|
||||
if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
|
||||
as_basename=basename
|
||||
else
|
||||
as_basename=false
|
||||
fi
|
||||
|
||||
if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
|
||||
as_dirname=dirname
|
||||
else
|
||||
as_dirname=false
|
||||
fi
|
||||
|
||||
as_me=`$as_basename -- "$0" ||
|
||||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
|
||||
X"$0" : 'X\(//\)$' \| \
|
||||
X"$0" : 'X\(/\)' \| . 2>/dev/null ||
|
||||
$as_echo X/"$0" |
|
||||
sed '/^.*\/\([^/][^/]*\)\/*$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\/\(\/\/\)$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\/\(\/\).*/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
s/.*/./; q'`
|
||||
|
||||
# Avoid depending upon Character Ranges.
|
||||
as_cr_letters='abcdefghijklmnopqrstuvwxyz'
|
||||
as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
as_cr_Letters=$as_cr_letters$as_cr_LETTERS
|
||||
as_cr_digits='0123456789'
|
||||
as_cr_alnum=$as_cr_Letters$as_cr_digits
|
||||
|
||||
ECHO_C= ECHO_N= ECHO_T=
|
||||
case `echo -n x` in #(((((
|
||||
-n*)
|
||||
case `echo 'xy\c'` in
|
||||
*c*) ECHO_T=' ';; # ECHO_T is single tab character.
|
||||
xy) ECHO_C='\c';;
|
||||
*) echo `echo ksh88 bug on AIX 6.1` > /dev/null
|
||||
ECHO_T=' ';;
|
||||
esac;;
|
||||
*)
|
||||
ECHO_N='-n';;
|
||||
esac
|
||||
|
||||
rm -f conf$$ conf$$.exe conf$$.file
|
||||
if test -d conf$$.dir; then
|
||||
rm -f conf$$.dir/conf$$.file
|
||||
else
|
||||
rm -f conf$$.dir
|
||||
mkdir conf$$.dir 2>/dev/null
|
||||
fi
|
||||
if (echo >conf$$.file) 2>/dev/null; then
|
||||
if ln -s conf$$.file conf$$ 2>/dev/null; then
|
||||
as_ln_s='ln -s'
|
||||
# ... but there are two gotchas:
|
||||
# 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
|
||||
# 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
|
||||
# In both cases, we have to default to `cp -pR'.
|
||||
ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
|
||||
as_ln_s='cp -pR'
|
||||
elif ln conf$$.file conf$$ 2>/dev/null; then
|
||||
as_ln_s=ln
|
||||
else
|
||||
as_ln_s='cp -pR'
|
||||
fi
|
||||
else
|
||||
as_ln_s='cp -pR'
|
||||
fi
|
||||
rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
|
||||
rmdir conf$$.dir 2>/dev/null
|
||||
|
||||
|
||||
# as_fn_mkdir_p
|
||||
# -------------
|
||||
# Create "$as_dir" as a directory, including parents if necessary.
|
||||
as_fn_mkdir_p ()
|
||||
{
|
||||
|
||||
case $as_dir in #(
|
||||
-*) as_dir=./$as_dir;;
|
||||
esac
|
||||
test -d "$as_dir" || eval $as_mkdir_p || {
|
||||
as_dirs=
|
||||
while :; do
|
||||
case $as_dir in #(
|
||||
*\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
|
||||
*) as_qdir=$as_dir;;
|
||||
esac
|
||||
as_dirs="'$as_qdir' $as_dirs"
|
||||
as_dir=`$as_dirname -- "$as_dir" ||
|
||||
$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
|
||||
X"$as_dir" : 'X\(//\)[^/]' \| \
|
||||
X"$as_dir" : 'X\(//\)$' \| \
|
||||
X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
|
||||
$as_echo X"$as_dir" |
|
||||
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)[^/].*/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\).*/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
s/.*/./; q'`
|
||||
test -d "$as_dir" && break
|
||||
done
|
||||
test -z "$as_dirs" || eval "mkdir $as_dirs"
|
||||
} || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
|
||||
|
||||
|
||||
} # as_fn_mkdir_p
|
||||
if mkdir -p . 2>/dev/null; then
|
||||
as_mkdir_p='mkdir -p "$as_dir"'
|
||||
else
|
||||
test -d ./-p && rmdir ./-p
|
||||
as_mkdir_p=false
|
||||
fi
|
||||
|
||||
|
||||
# as_fn_executable_p FILE
|
||||
# -----------------------
|
||||
# Test if FILE is an executable regular file.
|
||||
as_fn_executable_p ()
|
||||
{
|
||||
test -f "$1" && test -x "$1"
|
||||
} # as_fn_executable_p
|
||||
as_test_x='test -x'
|
||||
as_executable_p=as_fn_executable_p
|
||||
|
||||
# Sed expression to map a string onto a valid CPP name.
|
||||
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
|
||||
|
||||
# Sed expression to map a string onto a valid variable name.
|
||||
as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
|
||||
|
||||
|
||||
exec 6>&1
|
||||
## ----------------------------------- ##
|
||||
## Main body of $CONFIG_STATUS script. ##
|
||||
## ----------------------------------- ##
|
||||
# Save the log message, to keep $0 and so on meaningful, and to
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by netgen $as_me 1.3, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
CONFIG_HEADERS = $CONFIG_HEADERS
|
||||
CONFIG_LINKS = $CONFIG_LINKS
|
||||
CONFIG_COMMANDS = $CONFIG_COMMANDS
|
||||
$ $0 $@
|
||||
|
||||
on `(hostname || uname -n) 2>/dev/null | sed 1q`
|
||||
"
|
||||
|
||||
# Files that config.status was made for.
|
||||
config_files=" defs.mak"
|
||||
|
||||
ac_cs_usage="\
|
||||
\`$as_me' instantiates files and other configuration actions
|
||||
from templates according to the current configuration. Unless the files
|
||||
and actions are specified as TAGs, all are instantiated by default.
|
||||
|
||||
Usage: $0 [OPTION]... [TAG]...
|
||||
|
||||
-h, --help print this help, then exit
|
||||
-V, --version print version number and configuration settings, then exit
|
||||
--config print configuration, then exit
|
||||
-q, --quiet, --silent
|
||||
do not print progress messages
|
||||
-d, --debug don't remove temporary files
|
||||
--recheck update $as_me by reconfiguring in the same conditions
|
||||
--file=FILE[:TEMPLATE]
|
||||
instantiate the configuration file FILE
|
||||
|
||||
Configuration files:
|
||||
$config_files
|
||||
|
||||
Report bugs to <[email protected]>."
|
||||
|
||||
ac_cs_config="'CFLAGS=-g'"
|
||||
ac_cs_version="\
|
||||
netgen config.status 1.3
|
||||
configured by ./configure, generated by GNU Autoconf 2.69,
|
||||
with options \"$ac_cs_config\"
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
This config.status script is free software; the Free Software Foundation
|
||||
gives unlimited permission to copy, distribute and modify it."
|
||||
|
||||
ac_pwd='/home/tim/gitsrc/netgen-1.5/scripts'
|
||||
srcdir='..'
|
||||
INSTALL='/bin/install -c'
|
||||
test -n "$AWK" || AWK=awk
|
||||
# The default lists apply if the user does not specify any file.
|
||||
ac_need_defaults=:
|
||||
while test $# != 0
|
||||
do
|
||||
case $1 in
|
||||
--*=?*)
|
||||
ac_option=`expr "X$1" : 'X\([^=]*\)='`
|
||||
ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
|
||||
ac_shift=:
|
||||
;;
|
||||
--*=)
|
||||
ac_option=`expr "X$1" : 'X\([^=]*\)='`
|
||||
ac_optarg=
|
||||
ac_shift=:
|
||||
;;
|
||||
*)
|
||||
ac_option=$1
|
||||
ac_optarg=$2
|
||||
ac_shift=shift
|
||||
;;
|
||||
esac
|
||||
|
||||
case $ac_option in
|
||||
# Handling of the options.
|
||||
-recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
|
||||
ac_cs_recheck=: ;;
|
||||
--version | --versio | --versi | --vers | --ver | --ve | --v | -V )
|
||||
$as_echo "$ac_cs_version"; exit ;;
|
||||
--config | --confi | --conf | --con | --co | --c )
|
||||
$as_echo "$ac_cs_config"; exit ;;
|
||||
--debug | --debu | --deb | --de | --d | -d )
|
||||
debug=: ;;
|
||||
--file | --fil | --fi | --f )
|
||||
$ac_shift
|
||||
case $ac_optarg in
|
||||
*\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
|
||||
'') as_fn_error $? "missing file argument" ;;
|
||||
esac
|
||||
as_fn_append CONFIG_FILES " '$ac_optarg'"
|
||||
ac_need_defaults=false;;
|
||||
--he | --h | --help | --hel | -h )
|
||||
$as_echo "$ac_cs_usage"; exit ;;
|
||||
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
|
||||
| -silent | --silent | --silen | --sile | --sil | --si | --s)
|
||||
ac_cs_silent=: ;;
|
||||
|
||||
# This is an error.
|
||||
-*) as_fn_error $? "unrecognized option: \`$1'
|
||||
Try \`$0 --help' for more information." ;;
|
||||
|
||||
*) as_fn_append ac_config_targets " $1"
|
||||
ac_need_defaults=false ;;
|
||||
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
ac_configure_extra_args=
|
||||
|
||||
if $ac_cs_silent; then
|
||||
exec 6>/dev/null
|
||||
ac_configure_extra_args="$ac_configure_extra_args --silent"
|
||||
fi
|
||||
|
||||
if $ac_cs_recheck; then
|
||||
set X /bin/sh './configure' 'CFLAGS=-g' $ac_configure_extra_args --no-create --no-recursion
|
||||
shift
|
||||
$as_echo "running CONFIG_SHELL=/bin/sh $*" >&6
|
||||
CONFIG_SHELL='/bin/sh'
|
||||
export CONFIG_SHELL
|
||||
exec "$@"
|
||||
fi
|
||||
|
||||
exec 5>>config.log
|
||||
{
|
||||
echo
|
||||
sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
|
||||
## Running $as_me. ##
|
||||
_ASBOX
|
||||
$as_echo "$ac_log"
|
||||
} >&5
|
||||
|
||||
|
||||
# Handling of arguments.
|
||||
for ac_config_target in $ac_config_targets
|
||||
do
|
||||
case $ac_config_target in
|
||||
"defs.mak") CONFIG_FILES="$CONFIG_FILES defs.mak" ;;
|
||||
|
||||
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
|
||||
esac
|
||||
done
|
||||
|
||||
|
||||
# If the user did not use the arguments to specify the items to instantiate,
|
||||
# then the envvar interface is used. Set only those that are not.
|
||||
# We use the long form for the default assignment because of an extremely
|
||||
# bizarre bug on SunOS 4.1.3.
|
||||
if $ac_need_defaults; then
|
||||
test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
|
||||
fi
|
||||
|
||||
# Have a temporary directory for convenience. Make it in the build tree
|
||||
# simply because there is no reason against having it here, and in addition,
|
||||
# creating and moving files from /tmp can sometimes cause problems.
|
||||
# Hook for its removal unless debugging.
|
||||
# Note that there is a small window in which the directory will not be cleaned:
|
||||
# after its creation but before its name has been assigned to `$tmp'.
|
||||
$debug ||
|
||||
{
|
||||
tmp= ac_tmp=
|
||||
trap 'exit_status=$?
|
||||
: "${ac_tmp:=$tmp}"
|
||||
{ test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
|
||||
' 0
|
||||
trap 'as_fn_exit 1' 1 2 13 15
|
||||
}
|
||||
# Create a (secure) tmp directory for tmp files.
|
||||
|
||||
{
|
||||
tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
|
||||
test -d "$tmp"
|
||||
} ||
|
||||
{
|
||||
tmp=./conf$$-$RANDOM
|
||||
(umask 077 && mkdir "$tmp")
|
||||
} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
|
||||
ac_tmp=$tmp
|
||||
|
||||
# Set up the scripts for CONFIG_FILES section.
|
||||
# No need to generate them if there are no CONFIG_FILES.
|
||||
# This happens for instance with `./config.status config.h'.
|
||||
if test -n "$CONFIG_FILES"; then
|
||||
|
||||
|
||||
ac_cr=`echo X | tr X '\015'`
|
||||
# On cygwin, bash can eat \r inside `` if the user requested igncr.
|
||||
# But we know of no other shell where ac_cr would be empty at this
|
||||
# point, so we can use a bashism as a fallback.
|
||||
if test "x$ac_cr" = x; then
|
||||
eval ac_cr=\$\'\\r\'
|
||||
fi
|
||||
ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
|
||||
if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
|
||||
ac_cs_awk_cr='\\r'
|
||||
else
|
||||
ac_cs_awk_cr=$ac_cr
|
||||
fi
|
||||
|
||||
echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
|
||||
cat >>"$ac_tmp/subs1.awk" <<\_ACAWK &&
|
||||
S["LTLIBOBJS"]=""
|
||||
S["LIBOBJS"]=""
|
||||
S["INSTALL_TARGET"]="install-tcl"
|
||||
S["ALL_TARGET"]="tcl"
|
||||
S["LD_RUN_PATH"]=""
|
||||
S["SHLIB_CFLAGS"]="-fPIC"
|
||||
S["DEPEND_FLAG"]="-MM"
|
||||
S["gr_srcs"]=" ${TK_SRCS}"
|
||||
S["gr_libs"]=" -lX11"
|
||||
S["gr_dflags"]=" -DX11 -DXLIB"
|
||||
S["gr_cflags"]=""
|
||||
S["cadinstall"]=" tcltk"
|
||||
S["programs"]=" tcltk"
|
||||
S["unused"]=""
|
||||
S["modules"]=" tcltk"
|
||||
S["sub_extra_libs"]=""
|
||||
S["top_extra_libs"]=""
|
||||
S["ld_extra_objs"]=""
|
||||
S["ld_extra_libs"]=""
|
||||
S["stub_defs"]=" -DUSE_TCL_STUBS -DUSE_TK_STUBS"
|
||||
S["extra_defs"]=" -DCAD_DIR=\\\"${LIBDIR}\\\" -DTCL_DIR=\\\"${TCLDIR}\\\""
|
||||
S["extra_libs"]=" ${NETGENDIR}/tcltk/libtcltk.o"
|
||||
S["SCRIPTS"]=""
|
||||
S["PACKAGE"]="netgen"
|
||||
S["VERSION"]=""
|
||||
S["TCL_LIB_DIR"]="/usr/lib"
|
||||
S["TCLSH_EXE"]="/usr/bin/tclsh"
|
||||
S["WISH_EXE"]="/usr/bin/wish"
|
||||
S["LIB_SPECS_NOSTUB"]=" -L/usr/lib64 -ltk8.6 -L/usr/lib64 -ltcl8.6"
|
||||
S["LIB_SPECS"]=" -L/usr/lib64 -ltkstub8.6 -L/usr/lib64 -ltclstub8.6"
|
||||
S["INC_SPECS"]=""
|
||||
S["EXTRA_LIB_SPECS"]="-ldl"
|
||||
S["SHLIB_LIB_SPECS"]=""
|
||||
S["LDDL_FLAGS"]=" -shared -Wl,-soname,$@ -Wl,--version-script=${NETGENDIR}/netgen/symbol.map"
|
||||
S["LD"]="/bin/ld"
|
||||
S["SHLIB_LD"]=""
|
||||
S["SHDLIB_EXT"]=".so"
|
||||
S["X_EXTRA_LIBS"]=""
|
||||
S["X_LIBS"]=""
|
||||
S["X_PRE_LIBS"]=" -lSM -lICE"
|
||||
S["X_CFLAGS"]=""
|
||||
S["XMKMF"]=""
|
||||
S["EGREP"]="/bin/grep -E"
|
||||
S["GREP"]="/bin/grep"
|
||||
S["M4"]="/bin/m4"
|
||||
S["RANLIB"]="ranlib"
|
||||
S["INSTALL_DATA"]="${INSTALL} -m 644"
|
||||
S["INSTALL_SCRIPT"]="${INSTALL}"
|
||||
S["INSTALL_PROGRAM"]="${INSTALL}"
|
||||
S["CPP"]="gcc -E -x c"
|
||||
S["OBJEXT"]="o"
|
||||
S["EXEEXT"]=""
|
||||
S["ac_ct_CC"]="gcc"
|
||||
S["CPPFLAGS"]=""
|
||||
S["LDFLAGS"]=""
|
||||
S["CFLAGS"]="-g -m64 -fPIC"
|
||||
S["CC"]="gcc"
|
||||
S["target_os"]="linux-gnu"
|
||||
S["target_vendor"]="unknown"
|
||||
S["target_cpu"]="x86_64"
|
||||
S["target"]="x86_64-unknown-linux-gnu"
|
||||
S["host_os"]="linux-gnu"
|
||||
S["host_vendor"]="unknown"
|
||||
S["host_cpu"]="x86_64"
|
||||
S["host"]="x86_64-unknown-linux-gnu"
|
||||
S["build_os"]="linux-gnu"
|
||||
S["build_vendor"]="unknown"
|
||||
S["build_cpu"]="x86_64"
|
||||
S["build"]="x86_64-unknown-linux-gnu"
|
||||
S["target_alias"]=""
|
||||
S["host_alias"]=""
|
||||
S["build_alias"]=""
|
||||
S["LIBS"]=""
|
||||
S["ECHO_T"]=""
|
||||
S["ECHO_N"]="-n"
|
||||
S["ECHO_C"]=""
|
||||
S["DEFS"]="-DPACKAGE_NAME=\\\"netgen\\\" -DPACKAGE_TARNAME=\\\"netgen\\\" -DPACKAGE_VERSION=\\\"1.3\\\" -DPACKAGE_STRING=\\\"netgen\\ 1.3\\\" -DPACKAGE_BUGREPORT=\\\"eda-dev@open"\
|
||||
"circuitdesign.com\\\" -DPACKAGE_URL=\\\"\\\" -DNETGEN_VERSION=\\\"1.5\\\" -DNETGEN_REVISION=\\\"60\\\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -"\
|
||||
"DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DSIZEOF_VOID_P=8 -D"\
|
||||
"SIZEOF_UNSIGNED_INT=4 -DSIZEOF_UNSIGNED_LONG=8 -DSIZEOF_UNSIGNED_LONG_LONG=8 -DSTDC_HEADERS=1 -DHAVE_SETENV=1 -DHAVE_PUTENV=1 -DHAVE_DIRENT_H=1 -DHA"\
|
||||
"VE_LIMITS_H=1 -DHAVE_VA_COPY=1 -DHAVE___VA_COPY=1 -DDBUG_OFF=1 -DTCL_NETGEN=1 -Dlinux=1 -DSYSV=1 -DISC=1"
|
||||
S["mandir"]="${datarootdir}/man"
|
||||
S["localedir"]="${datarootdir}/locale"
|
||||
S["libdir"]="${exec_prefix}/lib"
|
||||
S["psdir"]="${docdir}"
|
||||
S["pdfdir"]="${docdir}"
|
||||
S["dvidir"]="${docdir}"
|
||||
S["htmldir"]="${docdir}"
|
||||
S["infodir"]="${datarootdir}/info"
|
||||
S["docdir"]="${datarootdir}/doc/${PACKAGE_TARNAME}"
|
||||
S["oldincludedir"]="/usr/include"
|
||||
S["includedir"]="${prefix}/include"
|
||||
S["localstatedir"]="${prefix}/var"
|
||||
S["sharedstatedir"]="${prefix}/com"
|
||||
S["sysconfdir"]="${prefix}/etc"
|
||||
S["datadir"]="${datarootdir}"
|
||||
S["datarootdir"]="${prefix}/share"
|
||||
S["libexecdir"]="${exec_prefix}/libexec"
|
||||
S["sbindir"]="${exec_prefix}/sbin"
|
||||
S["bindir"]="${exec_prefix}/bin"
|
||||
S["program_transform_name"]="s,x,x,"
|
||||
S["prefix"]="/usr/local"
|
||||
S["exec_prefix"]="${prefix}"
|
||||
S["PACKAGE_URL"]=""
|
||||
S["PACKAGE_BUGREPORT"]="[email protected]"
|
||||
S["PACKAGE_STRING"]="netgen 1.3"
|
||||
S["PACKAGE_VERSION"]="1.3"
|
||||
S["PACKAGE_TARNAME"]="netgen"
|
||||
S["PACKAGE_NAME"]="netgen"
|
||||
S["PATH_SEPARATOR"]=":"
|
||||
S["SHELL"]="/bin/sh"
|
||||
_ACAWK
|
||||
cat >>"$ac_tmp/subs1.awk" <<_ACAWK &&
|
||||
for (key in S) S_is_set[key] = 1
|
||||
FS = ""
|
||||
|
||||
}
|
||||
{
|
||||
line = $ 0
|
||||
nfields = split(line, field, "@")
|
||||
substed = 0
|
||||
len = length(field[1])
|
||||
for (i = 2; i < nfields; i++) {
|
||||
key = field[i]
|
||||
keylen = length(key)
|
||||
if (S_is_set[key]) {
|
||||
value = S[key]
|
||||
line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
|
||||
len += length(value) + length(field[++i])
|
||||
substed = 1
|
||||
} else
|
||||
len += 1 + keylen
|
||||
}
|
||||
|
||||
print line
|
||||
}
|
||||
|
||||
_ACAWK
|
||||
if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
|
||||
sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
|
||||
else
|
||||
cat
|
||||
fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
|
||||
|| as_fn_error $? "could not setup config files machinery" "$LINENO" 5
|
||||
fi # test -n "$CONFIG_FILES"
|
||||
|
||||
|
||||
eval set X " :F $CONFIG_FILES "
|
||||
shift
|
||||
for ac_tag
|
||||
do
|
||||
case $ac_tag in
|
||||
:[FHLC]) ac_mode=$ac_tag; continue;;
|
||||
esac
|
||||
case $ac_mode$ac_tag in
|
||||
:[FHL]*:*);;
|
||||
:L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
|
||||
:[FH]-) ac_tag=-:-;;
|
||||
:[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
|
||||
esac
|
||||
ac_save_IFS=$IFS
|
||||
IFS=:
|
||||
set x $ac_tag
|
||||
IFS=$ac_save_IFS
|
||||
shift
|
||||
ac_file=$1
|
||||
shift
|
||||
|
||||
case $ac_mode in
|
||||
:L) ac_source=$1;;
|
||||
:[FH])
|
||||
ac_file_inputs=
|
||||
for ac_f
|
||||
do
|
||||
case $ac_f in
|
||||
-) ac_f="$ac_tmp/stdin";;
|
||||
*) # Look for the file first in the build tree, then in the source tree
|
||||
# (if the path is not absolute). The absolute path cannot be DOS-style,
|
||||
# because $ac_f cannot contain `:'.
|
||||
test -f "$ac_f" ||
|
||||
case $ac_f in
|
||||
[\\/$]*) false;;
|
||||
*) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
|
||||
esac ||
|
||||
as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
|
||||
esac
|
||||
case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
|
||||
as_fn_append ac_file_inputs " '$ac_f'"
|
||||
done
|
||||
|
||||
# Let's still pretend it is `configure' which instantiates (i.e., don't
|
||||
# use $as_me), people would be surprised to read:
|
||||
# /* config.h. Generated by config.status. */
|
||||
configure_input='Generated from '`
|
||||
$as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
|
||||
`' by configure.'
|
||||
if test x"$ac_file" != x-; then
|
||||
configure_input="$ac_file. $configure_input"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
|
||||
$as_echo "$as_me: creating $ac_file" >&6;}
|
||||
fi
|
||||
# Neutralize special characters interpreted by sed in replacement strings.
|
||||
case $configure_input in #(
|
||||
*\&* | *\|* | *\\* )
|
||||
ac_sed_conf_input=`$as_echo "$configure_input" |
|
||||
sed 's/[\\\\&|]/\\\\&/g'`;; #(
|
||||
*) ac_sed_conf_input=$configure_input;;
|
||||
esac
|
||||
|
||||
case $ac_tag in
|
||||
*:-:* | *:-) cat >"$ac_tmp/stdin" \
|
||||
|| as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
||||
ac_dir=`$as_dirname -- "$ac_file" ||
|
||||
$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
|
||||
X"$ac_file" : 'X\(//\)[^/]' \| \
|
||||
X"$ac_file" : 'X\(//\)$' \| \
|
||||
X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
|
||||
$as_echo X"$ac_file" |
|
||||
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)[^/].*/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\).*/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
s/.*/./; q'`
|
||||
as_dir="$ac_dir"; as_fn_mkdir_p
|
||||
ac_builddir=.
|
||||
|
||||
case "$ac_dir" in
|
||||
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
|
||||
*)
|
||||
ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
|
||||
# A ".." for each directory in $ac_dir_suffix.
|
||||
ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
|
||||
case $ac_top_builddir_sub in
|
||||
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
|
||||
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
|
||||
esac ;;
|
||||
esac
|
||||
ac_abs_top_builddir=$ac_pwd
|
||||
ac_abs_builddir=$ac_pwd$ac_dir_suffix
|
||||
# for backward compatibility:
|
||||
ac_top_builddir=$ac_top_build_prefix
|
||||
|
||||
case $srcdir in
|
||||
.) # We are building in place.
|
||||
ac_srcdir=.
|
||||
ac_top_srcdir=$ac_top_builddir_sub
|
||||
ac_abs_top_srcdir=$ac_pwd ;;
|
||||
[\\/]* | ?:[\\/]* ) # Absolute name.
|
||||
ac_srcdir=$srcdir$ac_dir_suffix;
|
||||
ac_top_srcdir=$srcdir
|
||||
ac_abs_top_srcdir=$srcdir ;;
|
||||
*) # Relative name.
|
||||
ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
|
||||
ac_top_srcdir=$ac_top_build_prefix$srcdir
|
||||
ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
|
||||
esac
|
||||
ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
|
||||
|
||||
|
||||
case $ac_mode in
|
||||
:F)
|
||||
#
|
||||
# CONFIG_FILE
|
||||
#
|
||||
|
||||
case $INSTALL in
|
||||
[\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
|
||||
*) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
|
||||
esac
|
||||
# If the template does not know about datarootdir, expand it.
|
||||
# FIXME: This hack should be removed a few years after 2.60.
|
||||
ac_datarootdir_hack=; ac_datarootdir_seen=
|
||||
ac_sed_dataroot='
|
||||
/datarootdir/ {
|
||||
p
|
||||
q
|
||||
}
|
||||
/@datadir@/p
|
||||
/@docdir@/p
|
||||
/@infodir@/p
|
||||
/@localedir@/p
|
||||
/@mandir@/p'
|
||||
case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
|
||||
*datarootdir*) ac_datarootdir_seen=yes;;
|
||||
*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
|
||||
$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
|
||||
ac_datarootdir_hack='
|
||||
s&@datadir@&${datarootdir}&g
|
||||
s&@docdir@&${datarootdir}/doc/${PACKAGE_TARNAME}&g
|
||||
s&@infodir@&${datarootdir}/info&g
|
||||
s&@localedir@&${datarootdir}/locale&g
|
||||
s&@mandir@&${datarootdir}/man&g
|
||||
s&\${datarootdir}&${prefix}/share&g' ;;
|
||||
esac
|
||||
ac_sed_extra="
|
||||
|
||||
:t
|
||||
/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
|
||||
s|@configure_input@|$ac_sed_conf_input|;t t
|
||||
s&@top_builddir@&$ac_top_builddir_sub&;t t
|
||||
s&@top_build_prefix@&$ac_top_build_prefix&;t t
|
||||
s&@srcdir@&$ac_srcdir&;t t
|
||||
s&@abs_srcdir@&$ac_abs_srcdir&;t t
|
||||
s&@top_srcdir@&$ac_top_srcdir&;t t
|
||||
s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
|
||||
s&@builddir@&$ac_builddir&;t t
|
||||
s&@abs_builddir@&$ac_abs_builddir&;t t
|
||||
s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
|
||||
s&@INSTALL@&$ac_INSTALL&;t t
|
||||
$ac_datarootdir_hack
|
||||
"
|
||||
eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
|
||||
>$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
|
||||
|
||||
test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
|
||||
{ ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
|
||||
{ ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
|
||||
"$ac_tmp/out"`; test -z "$ac_out"; } &&
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
|
||||
which seems to be undefined. Please make sure it is defined" >&5
|
||||
$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
|
||||
which seems to be undefined. Please make sure it is defined" >&2;}
|
||||
|
||||
rm -f "$ac_tmp/stdin"
|
||||
case $ac_file in
|
||||
-) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
|
||||
*) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
|
||||
esac \
|
||||
|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
|
||||
;;
|
||||
|
||||
|
||||
|
||||
esac
|
||||
|
||||
done # for ac_tag
|
||||
|
||||
|
||||
as_fn_exit 0
|
||||
Vendored
+57
-3
@@ -664,6 +664,7 @@ X_LIBS
|
||||
X_PRE_LIBS
|
||||
X_CFLAGS
|
||||
XMKMF
|
||||
HAVE_PYTHON3
|
||||
EGREP
|
||||
GREP
|
||||
M4
|
||||
@@ -4638,6 +4639,45 @@ fi
|
||||
done
|
||||
|
||||
|
||||
# Extract the first word of "python3", so it can be a program name with args.
|
||||
set dummy python3; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
$as_echo_n "checking for $ac_word... " >&6; }
|
||||
if ${ac_cv_prog_HAVE_PYTHON3+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
if test -n "$HAVE_PYTHON3"; then
|
||||
ac_cv_prog_HAVE_PYTHON3="$HAVE_PYTHON3" # Let the user override the test.
|
||||
else
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_HAVE_PYTHON3="yes"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
test -z "$ac_cv_prog_HAVE_PYTHON3" && ac_cv_prog_HAVE_PYTHON3="no"
|
||||
fi
|
||||
fi
|
||||
HAVE_PYTHON3=$ac_cv_prog_HAVE_PYTHON3
|
||||
if test -n "$HAVE_PYTHON3"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAVE_PYTHON3" >&5
|
||||
$as_echo "$HAVE_PYTHON3" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for va_copy" >&5
|
||||
$as_echo_n "checking for va_copy... " >&6; }
|
||||
if ${ac_cv_c_va_copy+:} false; then :
|
||||
@@ -6081,8 +6121,7 @@ case $target in
|
||||
|
||||
;;
|
||||
*darwin*)
|
||||
$as_echo "#define macosx 1" >>confdefs.h
|
||||
|
||||
$as_echo "#define macosx macos" >> confdefs.h
|
||||
if test "$CPP" = "cc -E" ; then
|
||||
CPPFLAGS="$CPPFLAGS -no-cpp-precomp"
|
||||
fi
|
||||
@@ -6374,7 +6413,7 @@ fi
|
||||
# Not available on all versions: check for include file.
|
||||
SHLIB_CFLAGS="-fpic"
|
||||
LDDL_FLAGS="-shared ${LIB_SPECS}"
|
||||
CFLAGS="${CFLAGS} -l/usr/X11R6/include"
|
||||
CFLAGS="${CFLAGS} -L/usr/X11R6/include"
|
||||
;;
|
||||
|
||||
*-netbsd*|*-openbsd*)
|
||||
@@ -6547,6 +6586,7 @@ fi
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ac_config_files="$ac_config_files defs.mak"
|
||||
@@ -7738,6 +7778,20 @@ else
|
||||
echo
|
||||
fi
|
||||
|
||||
${ECHO_N} "Python3: "
|
||||
if test "${HAVE_PYTHON3}" == "yes"; then
|
||||
echo "yes"
|
||||
else
|
||||
echo "no"
|
||||
echo
|
||||
echo " Without Python3, you cannot run the GUI interface to netgen."
|
||||
echo " This is purely optional, as it contains no features not"
|
||||
echo " available in the command-line (Tcl/Tk) version. If you want"
|
||||
echo " python3 support, make sure that you have installed python3"
|
||||
echo " on your system."
|
||||
echo
|
||||
fi
|
||||
|
||||
echo "-----------------------------------------------------------"
|
||||
echo
|
||||
|
||||
|
||||
+20
-2
@@ -163,6 +163,9 @@ AC_CHECK_HEADERS(limits.h)
|
||||
dnl Check for <param.h>
|
||||
AC_CHECK_HEADERS(param.h)
|
||||
|
||||
dnl Check for Python3
|
||||
AC_CHECK_PROG(HAVE_PYTHON3, python3, yes, no)
|
||||
|
||||
dnl Check for va_copy
|
||||
AC_CACHE_CHECK([for va_copy], ac_cv_c_va_copy,
|
||||
AC_TRY_LINK(
|
||||
@@ -868,7 +871,7 @@ case $target in
|
||||
AC_DEFINE(i386)
|
||||
;;
|
||||
*darwin*)
|
||||
AC_DEFINE(macosx)
|
||||
$as_echo "#define macosx macos" >> confdefs.h
|
||||
if test "$CPP" = "cc -E" ; then
|
||||
CPPFLAGS="$CPPFLAGS -no-cpp-precomp"
|
||||
fi
|
||||
@@ -1117,7 +1120,7 @@ if test $usingTcl ; then
|
||||
# Not available on all versions: check for include file.
|
||||
SHLIB_CFLAGS="-fpic"
|
||||
LDDL_FLAGS="-shared ${LIB_SPECS}"
|
||||
CFLAGS="${CFLAGS} -l/usr/X11R6/include"
|
||||
CFLAGS="${CFLAGS} -L/usr/X11R6/include"
|
||||
;;
|
||||
|
||||
*-netbsd*|*-openbsd*)
|
||||
@@ -1274,6 +1277,7 @@ AC_SUBST(gr_cflags)
|
||||
AC_SUBST(gr_dflags)
|
||||
AC_SUBST(gr_libs)
|
||||
AC_SUBST(gr_srcs)
|
||||
AC_SUBST(HAVE_PYTHON3)
|
||||
|
||||
AC_SUBST(X_LIBS)
|
||||
AC_SUBST(X_CFLAGS)
|
||||
@@ -1314,6 +1318,20 @@ else
|
||||
echo
|
||||
fi
|
||||
|
||||
${ECHO_N} "Python3: "
|
||||
if test "${HAVE_PYTHON3}" == "yes"; then
|
||||
echo "yes"
|
||||
else
|
||||
echo "no"
|
||||
echo
|
||||
echo " Without Python3, you cannot run the GUI interface to netgen."
|
||||
echo " This is purely optional, as it contains no features not"
|
||||
echo " available in the command-line (Tcl/Tk) version. If you want"
|
||||
echo " python3 support, make sure that you have installed python3"
|
||||
echo " on your system."
|
||||
echo
|
||||
fi
|
||||
|
||||
echo "-----------------------------------------------------------"
|
||||
echo
|
||||
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
# defs.mak.in --
|
||||
# source file for autoconf-generated "defs.mak" for netgen
|
||||
|
||||
# defs.mak. Generated from defs.mak.in by configure.
|
||||
# Feel free to change the values in here to suit your needs.
|
||||
# Be aware that running scripts/configure again will overwrite
|
||||
# any changes!
|
||||
|
||||
SHELL = /bin/sh
|
||||
|
||||
prefix = ${BUILDROOT}/usr/local
|
||||
exec_prefix = ${prefix}
|
||||
bindir = ${exec_prefix}/bin
|
||||
libdir = ${exec_prefix}/lib
|
||||
mandir = ${prefix}/share/man
|
||||
|
||||
VERSION =
|
||||
|
||||
SCRIPTS = ${NETGENDIR}/scripts
|
||||
|
||||
INSTALL = /bin/install -c
|
||||
INSTALL_PROGRAM = ${INSTALL}
|
||||
INSTALL_DATA = ${INSTALL} -m 644
|
||||
INSTALL_SCRIPT = ${INSTALL}
|
||||
|
||||
# Override standard "make" target when compiling under TCL
|
||||
ALL_TARGET = tcl
|
||||
INSTALL_TARGET = install-tcl
|
||||
|
||||
# Change CADDIR to install in a different place
|
||||
BINDIR = ${bindir}
|
||||
MANDIR = ${mandir}
|
||||
LIBDIR = ${libdir}
|
||||
DOCDIR = ${libdir}/netgen/doc
|
||||
TCLDIR = ${libdir}/netgen/tcl
|
||||
|
||||
MAIN_EXTRA_LIBS = ${NETGENDIR}/tcltk/libtcltk.o
|
||||
LD_EXTRA_LIBS =
|
||||
LD_SHARED =
|
||||
TOP_EXTRA_LIBS =
|
||||
SUB_EXTRA_LIBS =
|
||||
|
||||
MODULES += tcltk
|
||||
UNUSED_MODULES +=
|
||||
PROGRAMS += tcltk
|
||||
INSTALL_CAD_DIRS += tcltk
|
||||
|
||||
RM = rm -f
|
||||
CP = cp
|
||||
AR = @AR@
|
||||
ARFLAGS = crv
|
||||
LINK = /bin/ld -r
|
||||
LD = /bin/ld
|
||||
M4 = /bin/m4
|
||||
RANLIB = ranlib
|
||||
SHDLIB_EXT = .so
|
||||
LDDL_FLAGS = -shared -Wl,-soname,$@ -Wl,--version-script=${NETGENDIR}/netgen/symbol.map
|
||||
LD_RUN_PATH =
|
||||
LIB_SPECS = -L/usr/lib64 -ltkstub8.6 -L/usr/lib64 -ltclstub8.6
|
||||
LIB_SPECS_NOSTUB = -L/usr/lib64 -ltk8.6 -L/usr/lib64 -ltcl8.6
|
||||
WISH_EXE = /usr/bin/wish
|
||||
TCL_LIB_DIR = /usr/lib
|
||||
|
||||
CC = gcc
|
||||
CPP = gcc -E -x c
|
||||
CXX = @CXX@
|
||||
|
||||
CPPFLAGS = -I. -I${NETGENDIR}
|
||||
DFLAGS = -DCAD_DIR=\"${LIBDIR}\" -DTCL_DIR=\"${TCLDIR}\" -DUSE_TCL_STUBS -DUSE_TK_STUBS -DPACKAGE_NAME=\"netgen\" -DPACKAGE_TARNAME=\"netgen\" -DPACKAGE_VERSION=\"1.3\" -DPACKAGE_STRING=\"netgen\ 1.3\" -DPACKAGE_BUGREPORT=\"[email protected]\" -DPACKAGE_URL=\"\" -DNETGEN_VERSION=\"1.5\" -DNETGEN_REVISION=\"60\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DSIZEOF_VOID_P=8 -DSIZEOF_UNSIGNED_INT=4 -DSIZEOF_UNSIGNED_LONG=8 -DSIZEOF_UNSIGNED_LONG_LONG=8 -DSTDC_HEADERS=1 -DHAVE_SETENV=1 -DHAVE_PUTENV=1 -DHAVE_DIRENT_H=1 -DHAVE_LIMITS_H=1 -DHAVE_VA_COPY=1 -DHAVE___VA_COPY=1 -DDBUG_OFF=1 -DTCL_NETGEN=1 -Dlinux=1 -DSYSV=1 -DISC=1 -DSHDLIB_EXT=\".so\" -DNDEBUG
|
||||
DFLAGS_NOSTUB = -DCAD_DIR=\"${LIBDIR}\" -DTCL_DIR=\"${TCLDIR}\" -DPACKAGE_NAME=\"netgen\" -DPACKAGE_TARNAME=\"netgen\" -DPACKAGE_VERSION=\"1.3\" -DPACKAGE_STRING=\"netgen\ 1.3\" -DPACKAGE_BUGREPORT=\"[email protected]\" -DPACKAGE_URL=\"\" -DNETGEN_VERSION=\"1.5\" -DNETGEN_REVISION=\"60\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DSIZEOF_VOID_P=8 -DSIZEOF_UNSIGNED_INT=4 -DSIZEOF_UNSIGNED_LONG=8 -DSIZEOF_UNSIGNED_LONG_LONG=8 -DSTDC_HEADERS=1 -DHAVE_SETENV=1 -DHAVE_PUTENV=1 -DHAVE_DIRENT_H=1 -DHAVE_LIMITS_H=1 -DHAVE_VA_COPY=1 -DHAVE___VA_COPY=1 -DDBUG_OFF=1 -DTCL_NETGEN=1 -Dlinux=1 -DSYSV=1 -DISC=1 -DSHDLIB_EXT=\".so\" -DNDEBUG
|
||||
CFLAGS = -g -m64 -fPIC -fPIC
|
||||
|
||||
DEPEND_FILE = Depend
|
||||
DEPEND_FLAG = -MM
|
||||
EXEEXT =
|
||||
|
||||
GR_CFLAGS =
|
||||
GR_DFLAGS = -DX11 -DXLIB -DNDEBUG
|
||||
GR_LIBS = -lX11
|
||||
GR_SRCS = ${TK_SRCS}
|
||||
|
||||
OBJS = ${SRCS:.c=.o}
|
||||
LIB_OBJS = ${LIB_SRCS:.c=.o}
|
||||
CLEANS = ${OBJS} ${LIB_OBJS} lib${MODULE}.a lib${MODULE}.o ${MODULE}
|
||||
@@ -33,6 +33,7 @@ MANDIR = ${mandir}
|
||||
LIBDIR = ${libdir}
|
||||
DOCDIR = ${libdir}/netgen/doc
|
||||
TCLDIR = ${libdir}/netgen/tcl
|
||||
PYDIR = ${libdir}/netgen/python
|
||||
|
||||
MAIN_EXTRA_LIBS = @extra_libs@
|
||||
LD_EXTRA_LIBS = @ld_extra_libs@
|
||||
|
||||
-187
@@ -1,187 +0,0 @@
|
||||
#!/bin/csh -f
|
||||
#
|
||||
# makes the "database.h" (1st argument, $1) file from "database.h.in"
|
||||
# (2nd argument, $2), setting various mask operation definitions
|
||||
# according to the number of words implied by the value of TT_MAXTYPES
|
||||
|
||||
# The following mess grabs the value of TT_MAXTYPES from database.h.in
|
||||
#
|
||||
set maxtypes=`sed -n -e '/^#define[[:space:]]*TT_MAXTYPES/s/#define[[:space:]]*TT_MAXTYPES[[:space:]]*//p' < $1 | sed -e 's/\/\*[[:print:]]*\*\/[[:space:]]*//g' `
|
||||
#
|
||||
# Alternative method works with outdated versions of sed/ed.
|
||||
#
|
||||
if ($maxtypes == "") then
|
||||
set maxtypes=`sed -n -e '/^#define[ ]*TT_MAXTYPES/s/#define[ ]*TT_MAXTYPES[ ]*//p' < $1 | sed -e 's/\/\*.*\*\/[ ]*//g' `
|
||||
endif
|
||||
#
|
||||
# If we can't generate database.h correctly, nothing is going to compile.
|
||||
#
|
||||
if ($maxtypes == "") then
|
||||
echo "Bad sed script in scripts/makedbh: Cannot generate database/database.h!"
|
||||
exit
|
||||
endif
|
||||
|
||||
# Find derived values from bits per word
|
||||
# Note that bits-per-word should be determined from the compiler, but
|
||||
# 32 bits per word has always been hardwired into magic.
|
||||
#
|
||||
set bpw = 32
|
||||
|
||||
# @ wordmask=$bpw - 1
|
||||
# set wordshift=`echo "c=l($bpw); d=l(2); scale=0; c/d" | bc -l`
|
||||
# @ maskwords=$maxtypes + $bpw - 1
|
||||
# @ maskwords/=$bpw
|
||||
|
||||
@ maskwords=$maxtypes + $bpw - 1
|
||||
@ maskwords/=$bpw
|
||||
|
||||
|
||||
# Generate the main part of the database.h file from database.h.in
|
||||
cat $1 > $2
|
||||
|
||||
# Generate a list of integers from 0 to the value of "maskwords" - 1
|
||||
set count=""
|
||||
@ maskwords--
|
||||
while (${maskwords} >= 0)
|
||||
set count=`echo ${count} ${maskwords}`
|
||||
@ maskwords--
|
||||
end
|
||||
|
||||
# Definitions
|
||||
|
||||
echo "#define TTMaskZero(m) ( \" >> $2
|
||||
foreach i (${count})
|
||||
echo -n " (m)->tt_words[$i] = 0" >> $2
|
||||
if ($i == 0) then
|
||||
echo ")" >> $2
|
||||
echo "" >> $2
|
||||
else
|
||||
echo ", \" >> $2
|
||||
endif
|
||||
end
|
||||
|
||||
echo "#define TTMaskIsZero(m) ( \" >> $2
|
||||
foreach i (${count})
|
||||
echo -n " (m)->tt_words[$i] == 0" >> $2
|
||||
if ($i == 0) then
|
||||
echo ")" >> $2
|
||||
echo "" >> $2
|
||||
else
|
||||
echo " && \" >> $2
|
||||
endif
|
||||
end
|
||||
|
||||
echo "#define TTMaskEqual(m, n) ( \" >> $2
|
||||
foreach i (${count})
|
||||
echo -n " (m)->tt_words[$i] == (n)->tt_words[$i]" >> $2
|
||||
if ($i == 0) then
|
||||
echo ")" >> $2
|
||||
echo "" >> $2
|
||||
else
|
||||
echo " && \" >> $2
|
||||
endif
|
||||
end
|
||||
|
||||
echo "#define TTMaskIntersect(m, n) ( \" >> $2
|
||||
foreach i (${count})
|
||||
echo -n " ((m)->tt_words[$i] & (n)->tt_words[$i])" >> $2
|
||||
if ($i == 0) then
|
||||
echo ")" >> $2
|
||||
echo "" >> $2
|
||||
else
|
||||
echo " || \" >> $2
|
||||
endif
|
||||
end
|
||||
|
||||
echo "#define TTMaskCom(m) ( \" >> $2
|
||||
foreach i (${count})
|
||||
echo -n " ((m)->tt_words[$i] = ~(m)->tt_words[$i])" >> $2
|
||||
if ($i == 0) then
|
||||
echo ")" >> $2
|
||||
echo "" >> $2
|
||||
else
|
||||
echo ", \" >> $2
|
||||
endif
|
||||
end
|
||||
|
||||
echo "#define TTMaskCom2(m, n) ( \" >> $2
|
||||
foreach i (${count})
|
||||
echo -n " ((m)->tt_words[$i] = ~(n)->tt_words[$i])" >> $2
|
||||
if ($i == 0) then
|
||||
echo ")" >> $2
|
||||
echo "" >> $2
|
||||
else
|
||||
echo ", \" >> $2
|
||||
endif
|
||||
end
|
||||
|
||||
echo "#define TTMaskSetMask(m, n) ( \" >> $2
|
||||
foreach i (${count})
|
||||
echo -n " ((m)->tt_words[$i] |= (n)->tt_words[$i])" >> $2
|
||||
if ($i == 0) then
|
||||
echo ")" >> $2
|
||||
echo "" >> $2
|
||||
else
|
||||
echo ", \" >> $2
|
||||
endif
|
||||
end
|
||||
|
||||
echo "#define TTMaskSetMask3(m, n, o) ( \" >> $2
|
||||
foreach i (${count})
|
||||
echo -n " ((m)->tt_words[$i] |= (n)->tt_words[$i] | (o)->tt_words[$i])" \
|
||||
>> $2
|
||||
if ($i == 0) then
|
||||
echo ")" >> $2
|
||||
echo "" >> $2
|
||||
else
|
||||
echo ", \" >> $2
|
||||
endif
|
||||
end
|
||||
|
||||
echo "#define TTMaskAndMask(m, n) ( \" >> $2
|
||||
foreach i (${count})
|
||||
echo -n " ((m)->tt_words[$i] &= (n)->tt_words[$i])" >> $2
|
||||
if ($i == 0) then
|
||||
echo ")" >> $2
|
||||
echo "" >> $2
|
||||
else
|
||||
echo ", \" >> $2
|
||||
endif
|
||||
end
|
||||
|
||||
echo "#define TTMaskAndMask3(m, n, o) ( \" >> $2
|
||||
foreach i (${count})
|
||||
echo -n " ((m)->tt_words[$i] = (n)->tt_words[$i] & (o)->tt_words[$i])" \
|
||||
>> $2
|
||||
if ($i == 0) then
|
||||
echo ")" >> $2
|
||||
echo "" >> $2
|
||||
else
|
||||
echo ", \" >> $2
|
||||
endif
|
||||
end
|
||||
|
||||
echo "#define TTMaskClearMask(m, n) ( \" >> $2
|
||||
foreach i (${count})
|
||||
echo -n " ((m)->tt_words[$i] &= ~(n)->tt_words[$i])" >> $2
|
||||
if ($i == 0) then
|
||||
echo ")" >> $2
|
||||
echo "" >> $2
|
||||
else
|
||||
echo ", \" >> $2
|
||||
endif
|
||||
end
|
||||
|
||||
echo "#define TTMaskClearMask3(m, n, o) ( \" >> $2
|
||||
foreach i (${count})
|
||||
echo -n " ((m)->tt_words[$i] = (n)->tt_words[$i] & ~(o)->tt_words[$i])" \
|
||||
>> $2
|
||||
if ($i == 0) then
|
||||
echo ")" >> $2
|
||||
else
|
||||
echo ", \" >> $2
|
||||
endif
|
||||
end
|
||||
|
||||
echo "" >> $2
|
||||
echo "#endif /* _DATABASE_H */" >> $2
|
||||
+6
-5
@@ -28,14 +28,15 @@ netgenexec${EXEEXT}: netgenexec.c
|
||||
${LDFLAGS} ${LIBS} ${LIB_SPECS_NOSTUB}
|
||||
|
||||
netgen.tcl: netgen.tcl.in
|
||||
sed -e /TCL_DIR/s%TCL_DIR%${TCLDIR}%g \
|
||||
-e /SHDLIB_EXT/s%SHDLIB_EXT%${SHDLIB_EXT}%g \
|
||||
sed -e 's%TCL_DIR%${TCLDIR}%g' \
|
||||
-e 's%SHDLIB_EXT%${SHDLIB_EXT}%g' \
|
||||
netgen.tcl.in > netgen.tcl
|
||||
|
||||
netgen.sh: netgen.sh.in
|
||||
sed -e /TCL_DIR/s%TCL_DIR%${TCLDIR}%g \
|
||||
-e /TCLLIB_DIR/s%TCLLIB_DIR%${TCL_LIB_DIR}%g \
|
||||
-e /WISH_EXE/s%WISH_EXE%${WISH_EXE}%g \
|
||||
sed -e 's%TCL_DIR%${TCLDIR}%g' \
|
||||
-e 's%PY_DIR%${PYDIR}%g' \
|
||||
-e 's%TCLLIB_DIR%${TCL_LIB_DIR}%g' \
|
||||
-e 's%WISH_EXE%${WISH_EXE}%g' \
|
||||
netgen.sh.in > netgen.sh
|
||||
|
||||
$(DESTDIR)${TCLDIR}/%: %
|
||||
|
||||
+8
-2
@@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
#
|
||||
# For installation, put this file (netgen.sh) in a standard executable path.
|
||||
# Put startup script "netgen.tcl" and shared library "tclnetgen.so"
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
TKCON=true
|
||||
BATCH=
|
||||
GUI=
|
||||
NETGEN_WISH=WISH_EXE
|
||||
export NETGEN_WISH
|
||||
|
||||
@@ -29,6 +30,7 @@ for i in "$@" ; do
|
||||
case $i in
|
||||
-noc*) TKCON=;;
|
||||
-bat*) BATCH=true; TKCON=;;
|
||||
-gui) GUI=true; TKCON=;;
|
||||
*) arglist="$arglist${arglist:+ }\"${i//\"/\\\"}\"";;
|
||||
esac
|
||||
done
|
||||
@@ -40,7 +42,10 @@ if [ $TKCON ]; then
|
||||
-slave "package require Tk; set argc $#; set argv [list $arglist]; \
|
||||
source TCL_DIR/netgen.tcl"
|
||||
|
||||
else
|
||||
# Run the Python LVS manager GUI
|
||||
|
||||
elif [ $GUI ]; then
|
||||
exec PY_DIR/lvs_manager.py $@
|
||||
|
||||
#
|
||||
# Run the stand-in for wish (netgenexec), which acts exactly like "wish"
|
||||
@@ -49,6 +54,7 @@ else
|
||||
# capable of sourcing the startup script.
|
||||
#
|
||||
|
||||
else
|
||||
exec TCL_DIR/netgenexec -- "$@"
|
||||
|
||||
fi
|
||||
|
||||
+31
-16
@@ -20,11 +20,10 @@ foreach i $nlist {
|
||||
}
|
||||
}
|
||||
|
||||
if {${tcl_version} >= 8.6} {
|
||||
load -lazy TCL_DIR/tclnetgenSHDLIB_EXT
|
||||
} else {
|
||||
load TCL_DIR/tclnetgenSHDLIB_EXT
|
||||
}
|
||||
# -lazy option not needed if stubs libraries are handled correctly
|
||||
# load -lazy TCL_DIR/tclnetgenSHDLIB_EXT
|
||||
|
||||
load TCL_DIR/tclnetgenSHDLIB_EXT
|
||||
|
||||
#----------------------------------------------------------------
|
||||
# Convert LVS list result into a JSON file
|
||||
@@ -139,7 +138,7 @@ proc netgen::convert_to_json {filename lvs_final} {
|
||||
foreach net $cktval {
|
||||
incr nidx
|
||||
puts $fjson " \["
|
||||
set netname [lindex $net 0]
|
||||
set netname [string map {"\\" ""} [lindex $net 0]]
|
||||
puts $fjson " \"$netname\","
|
||||
puts $fjson " \["
|
||||
set netconn [lindex $net 1]
|
||||
@@ -170,7 +169,7 @@ proc netgen::convert_to_json {filename lvs_final} {
|
||||
foreach net $cktval {
|
||||
incr nidx
|
||||
puts $fjson " \["
|
||||
set netname [lindex $net 0]
|
||||
set netname [string map {"\\" ""} [lindex $net 0]]
|
||||
puts $fjson " \"$netname\","
|
||||
puts $fjson " \["
|
||||
set netconn [lindex $net 1]
|
||||
@@ -370,7 +369,6 @@ proc netgen::convert_to_json {filename lvs_final} {
|
||||
proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||
set dolist 0
|
||||
set dojson 0
|
||||
puts stdout "Diagnostic version"
|
||||
foreach arg $args {
|
||||
if {$arg == "-list"} {
|
||||
puts stdout "Generating list result"
|
||||
@@ -381,6 +379,9 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -474,15 +475,22 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||
if {$perrors > 0} {
|
||||
puts stdout "Warning: There were errors reading the setup file"
|
||||
}
|
||||
} else {
|
||||
} elseif {[string first nosetup $setupfile] < 0} {
|
||||
netgen::permute default ;# transistors and resistors
|
||||
netgen::property default
|
||||
}
|
||||
|
||||
puts stdout "Comparison output logged to file $logfile"
|
||||
netgen::log file $logfile
|
||||
netgen::log start
|
||||
netgen::log echo off
|
||||
if {[string first nolog $logfile] < 0} {
|
||||
puts stdout "Comparison output logged to file $logfile"
|
||||
netgen::log file $logfile
|
||||
|
||||
netgen::log start
|
||||
netgen::log echo off
|
||||
set dolog true
|
||||
} else {
|
||||
set dolog false
|
||||
}
|
||||
|
||||
if {$dolist == 1} {
|
||||
set endval [netgen::compare -list hierarchical "$fnum1 $cell1" "$fnum2 $cell2"]
|
||||
} else {
|
||||
@@ -527,8 +535,13 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||
} else {
|
||||
# Match pins
|
||||
netgen::log echo off
|
||||
set result [equate pins "$fnum1 [lindex $endval 0]" \
|
||||
"$fnum2 [lindex $endval 1]"]
|
||||
if {$dolist == 1} {
|
||||
set result [equate -list pins "$fnum1 [lindex $endval 0]" \
|
||||
"$fnum2 [lindex $endval 1]"]
|
||||
} else {
|
||||
set result [equate pins "$fnum1 [lindex $endval 0]" \
|
||||
"$fnum2 [lindex $endval 1]"]
|
||||
}
|
||||
if {$result != 0} {
|
||||
equate classes "$fnum1 [lindex $endval 0]" \
|
||||
"$fnum2 [lindex $endval 1]"
|
||||
@@ -560,7 +573,9 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||
if {$properr != {}} {
|
||||
netgen::log put "The following cells had property errors: $properr\n"
|
||||
}
|
||||
netgen::log end
|
||||
if {$dolog} {
|
||||
netgen::log end
|
||||
}
|
||||
puts stdout "LVS Done."
|
||||
if {$dojson == 1} {
|
||||
netgen::convert_to_json $logfile $lvs_final
|
||||
|
||||
+295
-84
@@ -698,11 +698,11 @@ _netgen_readnet(ClientData clientData,
|
||||
{
|
||||
char *formats[] = {
|
||||
"automatic", "ext", "extflat", "sim", "ntk", "spice",
|
||||
"netgen", "actel", "xilinx", NULL
|
||||
"verilog", "netgen", "actel", "xilinx", NULL
|
||||
};
|
||||
enum FormatIdx {
|
||||
AUTO_IDX, EXT_IDX, EXTFLAT_IDX, SIM_IDX, NTK_IDX,
|
||||
SPICE_IDX, NETGEN_IDX, ACTEL_IDX, XILINX_IDX
|
||||
SPICE_IDX, VERILOG_IDX, NETGEN_IDX, ACTEL_IDX, XILINX_IDX
|
||||
};
|
||||
struct nlist *tc;
|
||||
int result, index, filenum = -1;
|
||||
@@ -771,7 +771,7 @@ _netgen_readnet(ClientData clientData,
|
||||
|
||||
if (retstr) savstr = STRDUP(retstr);
|
||||
|
||||
// Check if the file is already loaded
|
||||
// Check if the file is already loaded.
|
||||
|
||||
tc = LookupCell(savstr);
|
||||
if (tc != NULL) {
|
||||
@@ -803,6 +803,9 @@ _netgen_readnet(ClientData clientData,
|
||||
case SPICE_IDX:
|
||||
retstr = ReadSpice(savstr, &filenum);
|
||||
break;
|
||||
case VERILOG_IDX:
|
||||
retstr = ReadVerilog(savstr, &filenum);
|
||||
break;
|
||||
case NETGEN_IDX:
|
||||
retstr = ReadNetgenFile(savstr, &filenum);
|
||||
break;
|
||||
@@ -918,11 +921,13 @@ _netgen_writenet(ClientData clientData,
|
||||
{
|
||||
char *formats[] = {
|
||||
"ext", "sim", "ntk", "actel",
|
||||
"spice", "wombat", "esacap", "netgen", "ccode", "xilinx", NULL
|
||||
"spice", "verilog", "wombat", "esacap", "netgen",
|
||||
"ccode", "xilinx", NULL
|
||||
};
|
||||
enum FormatIdx {
|
||||
EXT_IDX, SIM_IDX, NTK_IDX, ACTEL_IDX,
|
||||
SPICE_IDX, WOMBAT_IDX, ESACAP_IDX, NETGEN_IDX, CCODE_IDX, XILINX_IDX
|
||||
SPICE_IDX, VERILOG_IDX, WOMBAT_IDX, ESACAP_IDX, NETGEN_IDX,
|
||||
CCODE_IDX, XILINX_IDX
|
||||
};
|
||||
int result, index, filenum;
|
||||
char *repstr;
|
||||
@@ -963,6 +968,9 @@ _netgen_writenet(ClientData clientData,
|
||||
case SPICE_IDX:
|
||||
SpiceCell(repstr, filenum, "");
|
||||
break;
|
||||
case VERILOG_IDX:
|
||||
VerilogModule(repstr, filenum, "");
|
||||
break;
|
||||
case WOMBAT_IDX:
|
||||
Wombat(repstr,NULL);
|
||||
break;
|
||||
@@ -1437,9 +1445,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 +1455,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 +1505,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 +1552,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 +1684,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;
|
||||
@@ -2678,10 +2728,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) {
|
||||
@@ -2849,7 +2899,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",
|
||||
@@ -2857,20 +2907,41 @@ _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;
|
||||
}
|
||||
|
||||
// Check for and remove duplicate pins. Normally this is called
|
||||
// from "compare", but since "equate pins" may be called outside
|
||||
// of and before "compare", pin uniqueness needs to be ensured.
|
||||
|
||||
UniquePins(tp1->name, tp1->file);
|
||||
UniquePins(tp2->name, tp2->file);
|
||||
|
||||
result = MatchPins(tp1, tp2, dolist);
|
||||
if (result == 2) {
|
||||
Fprintf(stdout, "Cells have no pins; pin matching not needed.\n");
|
||||
}
|
||||
else if (result > 0) {
|
||||
Fprintf(stdout, "Cell pin lists are equivalent.\n");
|
||||
}
|
||||
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_NewIntObj(result));
|
||||
if (ElementClasses == NULL) {
|
||||
/* Recover temporarily set global variables (see above) */
|
||||
Circuit1 = SaveC1;
|
||||
Circuit2 = SaveC2;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -3086,15 +3157,25 @@ _netcmp_equate(ClientData clientData,
|
||||
/* add --- add new property */
|
||||
/* remove --- delete existing property */
|
||||
/* tolerance --- set property tolerance */
|
||||
/* merge --- set property merge behavior */
|
||||
/* merge --- (deprecated) */
|
||||
/* or */
|
||||
/* netgen::property default */
|
||||
/* or */
|
||||
/* netgen::property <device>|<model> <option> */
|
||||
/* yes|no */
|
||||
/* Where <option> is one of: */
|
||||
/* serial --- allow/prohibit serial combination */
|
||||
/* series --- allow/prohibit series combination */
|
||||
/* parallel --- allow/prohibit parallel combination */
|
||||
/* or */
|
||||
/* netgen::property parallel none */
|
||||
/* --- prohibit parallel combinations by */
|
||||
/* default (for all devices). */
|
||||
/* */
|
||||
/* series|parallel options are: */
|
||||
/* enable|disable|none|{<key> <combine_option>} */
|
||||
/* */
|
||||
/* combine options are: */
|
||||
/* par|add|par_critical|add_critical */
|
||||
/* */
|
||||
/* Formerly: (none) */
|
||||
/* Results: */
|
||||
@@ -3114,11 +3195,11 @@ _netcmp_property(ClientData clientData,
|
||||
|
||||
char *options[] = {
|
||||
"add", "create", "remove", "delete", "tolerance", "merge", "serial",
|
||||
"parallel", NULL
|
||||
"series", "parallel", NULL
|
||||
};
|
||||
enum OptionIdx {
|
||||
ADD_IDX, CREATE_IDX, REMOVE_IDX, DELETE_IDX, TOLERANCE_IDX, MERGE_IDX,
|
||||
SERIAL_IDX, PARALLEL_IDX
|
||||
SERIAL_IDX, SERIES_IDX, PARALLEL_IDX
|
||||
};
|
||||
int result, index, idx2;
|
||||
|
||||
@@ -3129,16 +3210,30 @@ _netcmp_property(ClientData clientData,
|
||||
INTEGER_IDX, DOUBLE_IDX, VALUE_IDX, STRING_IDX
|
||||
};
|
||||
|
||||
/* Note: "merge" has been deprecated, but kept for backwards compatibility. */
|
||||
/* It has been replaced by "combineoptions" below, used with "series" and */
|
||||
/* "parallel". */
|
||||
|
||||
char *mergeoptions[] = {
|
||||
"none", "add", "add_critical", "par", "par_critical",
|
||||
"parallel", "parallel_critical", "ser_critical", "ser",
|
||||
"serial_critical", "serial", NULL
|
||||
"serial_critical", "series_critical", "serial", "series", NULL
|
||||
};
|
||||
|
||||
enum MergeOptionIdx {
|
||||
NONE_IDX, ADD_ONLY_IDX, ADD_CRIT_IDX,
|
||||
PAR_ONLY_IDX, PAR_CRIT_IDX, PAR2_ONLY_IDX, PAR2_CRIT_IDX,
|
||||
SER_CRIT_IDX, SER_IDX, SER2_CRIT_IDX, SER2_IDX
|
||||
SER_CRIT_IDX, SER_IDX, SER2_CRIT_IDX, SER3_CRIT_IDX, SER2_IDX, SER3_IDX
|
||||
};
|
||||
|
||||
char *combineoptions[] = {
|
||||
"none", "par", "add", "critical", NULL
|
||||
};
|
||||
|
||||
enum CombineOptionIdx {
|
||||
COMB_NONE_IDX, COMB_PAR_IDX, COMB_ADD_IDX, COMB_CRITICAL_IDX
|
||||
};
|
||||
|
||||
char *yesno[] = {
|
||||
"on", "yes", "true", "enable", "allow",
|
||||
"off", "no", "false", "disable", "prohibit", NULL
|
||||
@@ -3163,31 +3258,71 @@ _netcmp_property(ClientData clientData,
|
||||
case CLASS_NMOS: case CLASS_PMOS: case CLASS_FET3:
|
||||
case CLASS_NMOS4: case CLASS_PMOS4: case CLASS_FET4:
|
||||
case CLASS_FET:
|
||||
PropertyMerge(tp->name, tp->file, "w", MERGE_ADD_CRIT);
|
||||
PropertyMerge(tp->name, tp->file, "w", MERGE_P_ADD | MERGE_P_CRIT,
|
||||
MERGE_ALL_MASK);
|
||||
PropertyDelete(tp->name, tp->file, "as");
|
||||
PropertyDelete(tp->name, tp->file, "ad");
|
||||
PropertyDelete(tp->name, tp->file, "ps");
|
||||
PropertyDelete(tp->name, tp->file, "pd");
|
||||
break;
|
||||
case CLASS_RES: case CLASS_RES3:
|
||||
PropertyMerge(tp->name, tp->file, "w", MERGE_ADD_CRIT);
|
||||
PropertyMerge(tp->name, tp->file, "l", MERGE_SER_CRIT);
|
||||
tp->flags |= COMB_SERIAL;
|
||||
PropertyMerge(tp->name, tp->file, "w",
|
||||
MERGE_P_PAR | MERGE_S_CRIT, MERGE_ALL_MASK);
|
||||
PropertyMerge(tp->name, tp->file, "l",
|
||||
MERGE_S_ADD | MERGE_P_CRIT, MERGE_ALL_MASK);
|
||||
PropertyMerge(tp->name, tp->file, "value",
|
||||
MERGE_S_ADD | MERGE_P_PAR, MERGE_ALL_MASK);
|
||||
tp->flags |= COMB_SERIES;
|
||||
break;
|
||||
case CLASS_CAP: case CLASS_ECAP: case CLASS_CAP3:
|
||||
// NOTE: No attempt to combine area, width, or length;
|
||||
// only value.
|
||||
PropertyMerge(tp->name, tp->file, "value", MERGE_ADD_CRIT);
|
||||
/* NOTE: No attempt to modify perimeter, length, or width */
|
||||
PropertyMerge(tp->name, tp->file, "area",
|
||||
MERGE_P_ADD | MERGE_S_PAR, MERGE_ALL_MASK);
|
||||
PropertyMerge(tp->name, tp->file, "value",
|
||||
MERGE_P_ADD | MERGE_S_PAR, MERGE_ALL_MASK);
|
||||
tp->flags |= COMB_SERIES;
|
||||
break;
|
||||
case CLASS_INDUCTOR:
|
||||
PropertyMerge(tp->name, tp->file, "value", MERGE_PAR_CRIT);
|
||||
tp->flags |= COMB_SERIAL;
|
||||
PropertyMerge(tp->name, tp->file, "value",
|
||||
MERGE_S_ADD | MERGE_P_PAR, MERGE_ALL_MASK);
|
||||
tp->flags |= COMB_SERIES;
|
||||
break;
|
||||
}
|
||||
tp = NextCell();
|
||||
}
|
||||
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",
|
||||
NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
else if ((objc == 3) && ((!strcmp(Tcl_GetString(objv[1]), "series")) ||
|
||||
(!strcmp(Tcl_GetString(objv[1]), "serial")))) {
|
||||
if (!strcmp(Tcl_GetString(objv[2]), "none")) {
|
||||
SetSeriesCombine(FALSE);
|
||||
}
|
||||
else if (!strcmp(Tcl_GetString(objv[2]), "all")) {
|
||||
SetSeriesCombine(TRUE);
|
||||
}
|
||||
else {
|
||||
Tcl_SetResult(interp, "Bad option, should be property series none|all",
|
||||
NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
result = CommonParseCell(interp, objv[1], &tp, &fnum);
|
||||
if (result != TCL_OK) return result;
|
||||
@@ -3238,10 +3373,11 @@ _netcmp_property(ClientData clientData,
|
||||
|
||||
switch (index) {
|
||||
case SERIAL_IDX:
|
||||
case SERIES_IDX:
|
||||
case PARALLEL_IDX:
|
||||
if (objc == 3) {
|
||||
if (index == SERIAL_IDX) {
|
||||
tobj1 = Tcl_NewBooleanObj((tp->flags & COMB_SERIAL) ? 1 : 0);
|
||||
if (index == SERIAL_IDX || index == SERIES_IDX) {
|
||||
tobj1 = Tcl_NewBooleanObj((tp->flags & COMB_SERIES) ? 1 : 0);
|
||||
Tcl_SetObjResult(interp, tobj1);
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -3251,30 +3387,97 @@ _netcmp_property(ClientData clientData,
|
||||
return TCL_OK;
|
||||
}
|
||||
}
|
||||
else if (objc == 4) {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[3],
|
||||
(CONST84 char **)yesno,
|
||||
"combine", 0, &idx2) != TCL_OK) {
|
||||
Tcl_WrongNumArgs(interp, 3, objv, "enable|disable");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (idx2 <= 4) { /* true, enable, etc. */
|
||||
if (index == SERIAL_IDX)
|
||||
tp->flags |= COMB_SERIAL;
|
||||
else
|
||||
tp->flags &= ~COMB_NO_PARALLEL;
|
||||
}
|
||||
else { /* false, disable, etc. */
|
||||
if (index == SERIAL_IDX)
|
||||
tp->flags &= ~COMB_SERIAL;
|
||||
else
|
||||
tp->flags |= COMB_NO_PARALLEL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "serial|parallel enable|disable");
|
||||
else if (objc < 4) {
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "series|parallel enable|disable");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
for (i = 3; i < objc; i++) {
|
||||
// Each value must be a list of two, or a yes/no answer.
|
||||
|
||||
if (Tcl_GetIndexFromObj(interp, objv[i],
|
||||
(CONST84 char **)yesno,
|
||||
"combine", 0, &idx2) == TCL_OK) {
|
||||
if (idx2 <= 4) { /* true, enable, etc. */
|
||||
if (index == SERIAL_IDX || index == SERIES_IDX)
|
||||
tp->flags |= COMB_SERIES;
|
||||
else
|
||||
tp->flags &= ~COMB_NO_PARALLEL;
|
||||
}
|
||||
else { /* false, disable, etc. */
|
||||
if (index == SERIAL_IDX || index == SERIES_IDX)
|
||||
tp->flags &= ~COMB_SERIES;
|
||||
else
|
||||
tp->flags |= COMB_NO_PARALLEL;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
result = Tcl_ListObjLength(interp, objv[i], &llen);
|
||||
if ((result != TCL_OK) || (llen != 2)) {
|
||||
Tcl_SetResult(interp, "Not a {key merge_type} pair list.",
|
||||
NULL);
|
||||
}
|
||||
else {
|
||||
int mergeval = MERGE_NONE;
|
||||
int mergemask = MERGE_NONE;
|
||||
|
||||
result = Tcl_ListObjIndex(interp, objv[i], 0, &tobj1);
|
||||
if (result != TCL_OK) return result;
|
||||
result = Tcl_ListObjIndex(interp, objv[i], 1, &tobj2);
|
||||
if (result != TCL_OK) return result;
|
||||
|
||||
result = Tcl_GetIndexFromObj(interp, tobj2,
|
||||
(CONST84 char **)combineoptions,
|
||||
"combine_type", 0, &idx2);
|
||||
if (result != TCL_OK) return result;
|
||||
|
||||
if (index == SERIAL_IDX || index == SERIES_IDX) {
|
||||
mergemask = MERGE_S_MASK;
|
||||
switch (idx2) {
|
||||
case COMB_NONE_IDX:
|
||||
mergeval &= ~(MERGE_S_MASK);
|
||||
tp->flags &= ~COMB_SERIES;
|
||||
break;
|
||||
case COMB_PAR_IDX:
|
||||
mergeval = MERGE_S_PAR;
|
||||
tp->flags |= COMB_SERIES;
|
||||
break;
|
||||
case COMB_ADD_IDX:
|
||||
mergeval |= MERGE_S_ADD;
|
||||
tp->flags |= COMB_SERIES;
|
||||
break;
|
||||
case COMB_CRITICAL_IDX:
|
||||
mergeval |= MERGE_S_CRIT;
|
||||
tp->flags |= COMB_SERIES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else { /* index == PARALLEL_IDX */
|
||||
mergemask = MERGE_P_MASK;
|
||||
switch (idx2) {
|
||||
case COMB_NONE_IDX:
|
||||
mergeval &= ~(MERGE_P_MASK);
|
||||
tp->flags |= COMB_NO_PARALLEL;
|
||||
break;
|
||||
case COMB_PAR_IDX:
|
||||
mergeval |= MERGE_P_PAR;
|
||||
tp->flags &= ~COMB_NO_PARALLEL;
|
||||
break;
|
||||
case COMB_ADD_IDX:
|
||||
mergeval |= MERGE_P_ADD;
|
||||
tp->flags &= ~COMB_NO_PARALLEL;
|
||||
break;
|
||||
case COMB_CRITICAL_IDX:
|
||||
mergeval |= MERGE_P_CRIT;
|
||||
tp->flags &= ~COMB_NO_PARALLEL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
PropertyMerge(tp->name, fnum, Tcl_GetString(tobj1), mergeval,
|
||||
mergemask);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ADD_IDX:
|
||||
@@ -3444,6 +3647,11 @@ _netcmp_property(ClientData clientData,
|
||||
break;
|
||||
|
||||
case MERGE_IDX:
|
||||
// NOTE: This command option is deprecated, kept for backwards
|
||||
// compatibility, with updated flag values. This command format
|
||||
// is unable to specify a property as being a critical property
|
||||
// for merging both in series and in parallel.
|
||||
|
||||
if (objc == 3) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "{property_key merge_type} ...");
|
||||
return TCL_ERROR;
|
||||
@@ -3473,29 +3681,32 @@ _netcmp_property(ClientData clientData,
|
||||
mergeval = MERGE_NONE;
|
||||
break;
|
||||
case ADD_ONLY_IDX:
|
||||
mergeval = MERGE_ADD;
|
||||
mergeval = MERGE_P_ADD;
|
||||
break;
|
||||
case ADD_CRIT_IDX:
|
||||
mergeval = MERGE_ADD_CRIT;
|
||||
mergeval = MERGE_P_ADD | MERGE_P_XCRIT;
|
||||
break;
|
||||
case PAR_ONLY_IDX:
|
||||
case PAR2_ONLY_IDX:
|
||||
mergeval = MERGE_PAR;
|
||||
mergeval = MERGE_P_PAR;
|
||||
break;
|
||||
case PAR_CRIT_IDX:
|
||||
case PAR2_CRIT_IDX:
|
||||
mergeval = MERGE_PAR_CRIT;
|
||||
mergeval = MERGE_P_PAR | MERGE_P_XCRIT;
|
||||
break;
|
||||
case SER_CRIT_IDX:
|
||||
case SER2_CRIT_IDX:
|
||||
mergeval = MERGE_SER_CRIT;
|
||||
case SER3_CRIT_IDX:
|
||||
mergeval = MERGE_S_ADD | MERGE_S_XCRIT;
|
||||
break;
|
||||
case SER_IDX:
|
||||
case SER2_IDX:
|
||||
mergeval = MERGE_SER;
|
||||
case SER3_IDX:
|
||||
mergeval = MERGE_S_ADD;
|
||||
break;
|
||||
}
|
||||
PropertyMerge(tp->name, fnum, Tcl_GetString(tobj1), mergeval);
|
||||
PropertyMerge(tp->name, fnum, Tcl_GetString(tobj1), mergeval,
|
||||
MERGE_ALL_MASK);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -3600,8 +3811,8 @@ _netcmp_permute(ClientData clientData,
|
||||
if (PermuteForget(tp->name, fnum, NULL, NULL))
|
||||
Fprintf(stdout, "No permutations on circuit %s\n", tp->name);
|
||||
else
|
||||
Fprintf(stderr, "Unable to reset model %s pin permutation %s, %s.\n",
|
||||
tp->name, pin1, pin2);
|
||||
Fprintf(stderr, "Unable to reset model %s pin permutations.\n",
|
||||
tp->name);
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -3999,7 +4210,7 @@ int Tclnetgen_Init(Tcl_Interp *interp)
|
||||
if (cadroot == NULL) cadroot = CAD_DIR;
|
||||
Tcl_SetVar(interp, "CAD_ROOT", cadroot, TCL_GLOBAL_ONLY);
|
||||
|
||||
Tcl_PkgProvide(interp, "Tclnetgen", "1.1");
|
||||
Tcl_PkgProvide(interp, "Tclnetgen", NETGEN_VERSION);
|
||||
|
||||
if ((consoleinterp = Tcl_GetMaster(interp)) == NULL)
|
||||
consoleinterp = interp;
|
||||
|
||||
+10
-10
@@ -741,9 +741,9 @@ proc ::tkcon::EvalCmd {w cmd} {
|
||||
set tag [UniqueTag $w]
|
||||
$w insert output $res [list stderr $tag] \n stderr
|
||||
$w tag bind $tag <Enter> \
|
||||
[list $w tag configure $tag -under 1]
|
||||
[list $w tag configure $tag -underline 1]
|
||||
$w tag bind $tag <Leave> \
|
||||
[list $w tag configure $tag -under 0]
|
||||
[list $w tag configure $tag -underline 0]
|
||||
$w tag bind $tag <ButtonRelease-1> \
|
||||
"if {!\[info exists tkPriv(mouseMoved)\] || !\$tkPriv(mouseMoved)} \
|
||||
{[list edit -attach [Attach] -type error -- $PRIV(errorInfo)]}"
|
||||
@@ -2472,8 +2472,8 @@ proc ::tkcon::ErrorHighlight w {
|
||||
set tag [UniqueTag $w]
|
||||
$w tag add $tag $start+${c0}c $start+1c+${c1}c
|
||||
$w tag configure $tag -foreground $COLOR(stdout)
|
||||
$w tag bind $tag <Enter> [list $w tag configure $tag -under 1]
|
||||
$w tag bind $tag <Leave> [list $w tag configure $tag -under 0]
|
||||
$w tag bind $tag <Enter> [list $w tag configure $tag -underline 1]
|
||||
$w tag bind $tag <Leave> [list $w tag configure $tag -underline 0]
|
||||
$w tag bind $tag <ButtonRelease-1> "if {!\$tkPriv(mouseMoved)} \
|
||||
{[list edit -attach $app -type proc -find $what -- $cmd]}"
|
||||
}
|
||||
@@ -2501,8 +2501,8 @@ proc ::tkcon::ErrorHighlight w {
|
||||
set tag [UniqueTag $w]
|
||||
$w tag add $tag $ix+1c $start
|
||||
$w tag configure $tag -foreground $COLOR(proc)
|
||||
$w tag bind $tag <Enter> [list $w tag configure $tag -under 1]
|
||||
$w tag bind $tag <Leave> [list $w tag configure $tag -under 0]
|
||||
$w tag bind $tag <Enter> [list $w tag configure $tag -underline 1]
|
||||
$w tag bind $tag <Leave> [list $w tag configure $tag -underline 0]
|
||||
$w tag bind $tag <ButtonRelease-1> "if {!\$tkPriv(mouseMoved)} \
|
||||
{[list edit -attach $app -type proc -- $cmd]}"
|
||||
}
|
||||
@@ -2954,14 +2954,14 @@ proc edit {args} {
|
||||
##
|
||||
set text $w.text
|
||||
set m [menu [::tkcon::MenuButton $menu Edit edit]]
|
||||
$m add command -label "Cut" -under 2 \
|
||||
$m add command -label "Cut" -underline 2 \
|
||||
-command [list tk_textCut $text]
|
||||
$m add command -label "Copy" -under 0 \
|
||||
$m add command -label "Copy" -underline 0 \
|
||||
-command [list tk_textCopy $text]
|
||||
$m add command -label "Paste" -under 0 \
|
||||
$m add command -label "Paste" -underline 0 \
|
||||
-command [list tk_textPaste $text]
|
||||
$m add separator
|
||||
$m add command -label "Find" -under 0 \
|
||||
$m add command -label "Find" -underline 0 \
|
||||
-command [list ::tkcon::FindBox $text]
|
||||
|
||||
## Send To Menu
|
||||
|
||||
+4405
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user