mirror of
https://github.com/RTimothyEdwards/netgen.git
synced 2026-08-22 22:17:22 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7870538ec9 | ||
|
|
e12883037c | ||
|
|
ee4e1e087f | ||
|
|
2d63fd63c1 | ||
|
|
7a8b5e835b | ||
|
|
e557e61a02 | ||
|
|
67da250615 | ||
|
|
77f7a773e3 | ||
|
|
cd013621a7 | ||
|
|
9a48a59f68 | ||
|
|
45712a04f1 | ||
|
|
535b8285e9 | ||
|
|
28a2950439 | ||
|
|
1e1d506697 | ||
|
|
013fff9f37 | ||
|
|
4edaf0813d | ||
|
|
2292ab813b | ||
|
|
a4ae5ed989 | ||
|
|
7e8508db53 | ||
|
|
c9f7b24e0f | ||
|
|
d850586a14 | ||
|
|
95605ebbd4 | ||
|
|
4b5b117100 | ||
|
|
98e6a4bd8f | ||
|
|
c73d9ec4ff | ||
|
|
a5375177c5 | ||
|
|
935e54abe6 | ||
|
|
27b095754e | ||
|
|
49ccf1949a | ||
|
|
db457c562b | ||
|
|
9b84776374 | ||
|
|
06386bee1b | ||
|
|
2af3f2a3f7 | ||
|
|
7cd8d82964 | ||
|
|
738abbdad9 | ||
|
|
3aeea9d164 | ||
|
|
12e1ff295f | ||
|
|
8d7569e9a3 | ||
|
|
2f9e898ec6 | ||
|
|
9663579dd0 | ||
|
|
d9425163e1 | ||
|
|
f02e2b1ee0 | ||
|
|
9ba1dfe814 | ||
|
|
cc5f6d929f | ||
|
|
fadd0ae2fc | ||
|
|
4fa4d046c8 | ||
|
|
153ce0e2b3 | ||
|
|
9297090dc1 | ||
|
|
bfdacab28c | ||
|
|
79e193e0c9 | ||
|
|
7e9bd9f2a0 | ||
|
|
2056b37c95 | ||
|
|
ee92d880d7 | ||
|
|
7550ef9258 | ||
|
|
a795981eff | ||
|
|
d3407b3e56 | ||
|
|
1b6e4e2b36 | ||
|
|
0a94bec191 | ||
|
|
edbe5d6e86 | ||
|
|
4a7b6bf22a | ||
|
|
f8ed4e42e2 | ||
|
|
661c9ee854 | ||
|
|
89ef83c597 | ||
|
|
4e96c84ec6 | ||
|
|
5b21c1be3a | ||
|
|
592c16706e | ||
|
|
e11dbac384 | ||
|
|
bfb01e032f | ||
|
|
d0ec17e442 | ||
|
|
0535128421 | ||
|
|
6195745b45 | ||
|
|
afe0e9f758 | ||
|
|
68ec2b2a7c | ||
|
|
ca49a90ed6 | ||
|
|
e487890641 | ||
|
|
e07a5b416a | ||
|
|
bb44d3f827 | ||
|
|
8094740048 | ||
|
|
c25c4e1160 | ||
|
|
a026d37f11 | ||
|
|
8ed4e3cf38 | ||
|
|
ab614b63f7 | ||
|
|
83dce151d8 | ||
|
|
69838d79e4 | ||
|
|
de18ae85a4 | ||
|
|
fc7c9371e8 | ||
|
|
9908349fdd | ||
|
|
964bb0e91a | ||
|
|
0d19868145 | ||
|
|
cfdc60104b | ||
|
|
879711def3 | ||
|
|
5def9e0ffc | ||
|
|
b5c70decbd | ||
|
|
6b4eb01ee8 | ||
|
|
20f6d76926 | ||
|
|
737b2a73bf | ||
|
|
e4a15f12fb | ||
|
|
c6fb204f0c | ||
|
|
6b8c6d1718 | ||
|
|
c7dfff4bb9 | ||
|
|
12fa080212 | ||
|
|
610eebb758 | ||
|
|
4c4bad08f2 | ||
|
|
23ff2f00a3 | ||
|
|
d09f0dd53b | ||
|
|
56d4d581e7 | ||
|
|
1bb4866226 | ||
|
|
97058c5017 | ||
|
|
625e043eff | ||
|
|
aa120460d0 | ||
|
|
6ceeddf096 | ||
|
|
42b1acc564 | ||
|
|
6d6da9cf5c | ||
|
|
ea5cbacf1c | ||
|
|
bbcc79fc72 | ||
|
|
6d5946eaf2 | ||
|
|
cdd768addc | ||
|
|
18dcac73bc | ||
|
|
1338e3beb5 | ||
|
|
df1c4c5153 | ||
|
|
a05ede99db | ||
|
|
2d6f1f71b5 | ||
|
|
66cf2b82d9 | ||
|
|
d7355cea95 | ||
|
|
bc4192496b | ||
|
|
32585a572c | ||
|
|
168e5502a1 | ||
|
|
e773739e7d | ||
|
|
8d4b621b7d | ||
|
|
583cc3a151 | ||
|
|
bdd7d25943 | ||
|
|
903b813821 | ||
|
|
1f9d4317e3 | ||
|
|
7b8086fc3a | ||
|
|
e80f70e67b | ||
|
|
6cc898b34b | ||
|
|
30bbc28c17 | ||
|
|
5ec0db678a | ||
|
|
e643563d4e | ||
|
|
67f2801aa1 | ||
|
|
f76f2e002a | ||
|
|
9ec613b0cb | ||
|
|
9128eeda60 | ||
|
|
aeedf5fae9 | ||
|
|
f50dfd9261 | ||
|
|
409ce224ad | ||
|
|
f50093e6c6 | ||
|
|
a27ac8c679 | ||
|
|
883755eed3 | ||
|
|
484cb26eee | ||
|
|
7cc6996017 | ||
|
|
7f9acf6a1a | ||
|
|
e1a3ae5619 | ||
|
|
4e75889605 | ||
|
|
e017811239 | ||
|
|
4468d36462 | ||
|
|
b99fb96259 | ||
|
|
ec8299ea14 | ||
|
|
376296eda5 | ||
|
|
30acb8be63 | ||
|
|
7e15a26417 | ||
|
|
ba3e862552 | ||
|
|
21750da6c4 | ||
|
|
cf6dd2a638 | ||
|
|
a332c23524 | ||
|
|
b6d896e73f | ||
|
|
064195ecc9 | ||
|
|
88d53fab15 | ||
|
|
c287b6cd28 | ||
|
|
9251ce2a48 | ||
|
|
0a0a6bcf63 | ||
|
|
72ef2f2637 | ||
|
|
aa82164c08 | ||
|
|
287f5963d1 | ||
|
|
fb7876c7a6 | ||
|
|
a984ac1a4d | ||
|
|
e31caa3500 | ||
|
|
738c1f7b37 | ||
|
|
c3cf6c3765 | ||
|
|
99dcc20c0a | ||
|
|
c1355bee45 | ||
|
|
4bbc496749 | ||
|
|
4fb8b59a2f | ||
|
|
c4f03eabaf | ||
|
|
6a555ad6ed | ||
|
|
626faf22f9 | ||
|
|
1c5457e180 | ||
|
|
7d246c36a6 | ||
|
|
550234dce5 | ||
|
|
92dfa74403 | ||
|
|
a4c0028706 | ||
|
|
d53541d1d3 | ||
|
|
57b2d21221 | ||
|
|
e7ae84bbc8 | ||
|
|
dfabdaa367 | ||
|
|
c5c1306f6a | ||
|
|
43c018f3bc | ||
|
|
0614461c84 | ||
|
|
6e94886b65 | ||
|
|
ca119edc0a | ||
|
|
0556abf3c1 | ||
|
|
84348d2fe1 | ||
|
|
3356dd784e | ||
|
|
813b29cdc4 | ||
|
|
00949970b4 | ||
|
|
ccf4a0a900 | ||
|
|
c83b6def5b | ||
|
|
e34166fdb9 | ||
|
|
8fc2c097d2 | ||
|
|
a13491e358 | ||
|
|
2ac2a3b6f8 | ||
|
|
1d05b8b676 | ||
|
|
759d63cea9 | ||
|
|
476da015f0 | ||
|
|
4aa8a72769 | ||
|
|
e97d6f1aeb | ||
|
|
47e7367c26 | ||
|
|
362fb7120b | ||
|
|
fb4759a8cd | ||
|
|
92e8fed8be | ||
|
|
45d4004d43 | ||
|
|
01b2484be3 | ||
|
|
fe47d84ace | ||
|
|
0b014e6efd | ||
|
|
0a2adeb593 | ||
|
|
330b34139c | ||
|
|
62d0352149 | ||
|
|
9ca713dfd9 | ||
|
|
b1b04b8e87 | ||
|
|
851a1f941e | ||
|
|
6b9d92de65 | ||
|
|
d763ad0e60 | ||
|
|
fd72e24a86 | ||
|
|
20077d3d56 | ||
|
|
fb798d6ce7 | ||
|
|
a21ba820e9 | ||
|
|
792c5e569a | ||
|
|
f92192efd4 | ||
|
|
1f50c7ccc5 | ||
|
|
8282460774 | ||
|
|
a888502038 | ||
|
|
ea07642172 | ||
|
|
e9da037001 | ||
|
|
7ee50a3f8f | ||
|
|
c16258d4d1 | ||
|
|
c7848c9c02 | ||
|
|
5341d7a5fd | ||
|
|
402e1f0f25 | ||
|
|
8395df633c | ||
|
|
19471275df | ||
|
|
e75f5661e2 | ||
|
|
6554063df3 | ||
|
|
a034fc16d6 | ||
|
|
62fbd422e2 | ||
|
|
4416a380b3 | ||
|
|
d0bae6aff4 | ||
|
|
8a7bb7f2ca | ||
|
|
46394b2000 | ||
|
|
0df6c83df5 | ||
|
|
8996fe03dc | ||
|
|
3fe3bc4cfa | ||
|
|
f3cebd9099 | ||
|
|
6661910672 | ||
|
|
920c6e6928 | ||
|
|
e7a36630f6 | ||
|
|
69780aa048 | ||
|
|
f32b0b34a3 | ||
|
|
2a0ebfde93 | ||
|
|
6e9e6abe98 | ||
|
|
6b731ddd7a | ||
|
|
b9769b9f55 | ||
|
|
7e42483986 | ||
|
|
97b0d08e4f | ||
|
|
99e35d8b11 | ||
|
|
d2c356f9e2 | ||
|
|
5e99fd5ef9 | ||
|
|
65b542f0ab | ||
|
|
04dd4a64d5 | ||
|
|
b826870be9 | ||
|
|
50b0e9cb65 | ||
|
|
ed5276d67b | ||
|
|
82be18ec4b | ||
|
|
4ee3a1464b | ||
|
|
69c9d85be7 | ||
|
|
8e215d3b66 | ||
|
|
c45d51e950 | ||
|
|
ad05d059c7 | ||
|
|
85eb34c01e | ||
|
|
8a24c6c3ca | ||
|
|
46cdf48bc4 | ||
|
|
9d542b92b0 | ||
|
|
1b2cd1497c | ||
|
|
71ad228d8d | ||
|
|
339a0d5d4e | ||
|
|
9cebb76787 | ||
|
|
d9d5a46c6e | ||
|
|
251622c8bc | ||
|
|
d73b711e3a | ||
|
|
18739235a9 | ||
|
|
07c493c796 | ||
|
|
cca0e4b3f3 | ||
|
|
1428580109 | ||
|
|
fb0e1d10b0 | ||
|
|
6f81e1d294 | ||
|
|
cec6d89474 | ||
|
|
210dfb25c3 | ||
|
|
9bcca3ac21 | ||
|
|
27f2ab8b3f | ||
|
|
6ae6a246e9 | ||
|
|
d985ea340e | ||
|
|
5ea7916ff1 | ||
|
|
cf9dedb2f7 | ||
|
|
da667c3b17 | ||
|
|
1be00bbd99 | ||
|
|
36aa373fb2 | ||
|
|
18f230fc46 | ||
|
|
03b241a5d4 | ||
|
|
0f5a618353 | ||
|
|
43cebd1ef9 | ||
|
|
983c654086 | ||
|
|
515fccc633 | ||
|
|
0490959b07 | ||
|
|
7d94a7d5f6 | ||
|
|
39b3bb4d96 | ||
|
|
44673a04b6 | ||
|
|
a34f08b20a | ||
|
|
240a276431 | ||
|
|
dc841f3293 | ||
|
|
f7037fc9e6 | ||
|
|
23fb9356f4 | ||
|
|
05bcfede69 | ||
|
|
027b4ae468 | ||
|
|
72ed78e55a | ||
|
|
59bb8a89c0 | ||
|
|
08a442fda2 | ||
|
|
9bdaee652e | ||
|
|
9879b58f83 | ||
|
|
cc0cc512c0 | ||
|
|
9e3b705fcc | ||
|
|
d2c9129242 | ||
|
|
e9c0596dfe | ||
|
|
9a1e295367 | ||
|
|
942f421fa3 | ||
|
|
6bc948d8ba | ||
|
|
d7272e4ea1 | ||
|
|
7f4b5817e2 | ||
|
|
b5ab38d5d7 | ||
|
|
c1ad37f05a | ||
|
|
9edefe7d59 | ||
|
|
bf671937b9 | ||
|
|
a16086d2e9 | ||
|
|
f6b9629521 | ||
|
|
7b2e01f2af | ||
|
|
0e03f0bf97 | ||
|
|
224050f153 | ||
|
|
74e8c3e168 | ||
|
|
f12d03fcff | ||
|
|
95a29fcd8c | ||
|
|
723a950fd3 | ||
|
|
f04c72b984 | ||
|
|
e3368cb22a | ||
|
|
f06e6548bb | ||
|
|
d38bd77825 | ||
|
|
ea4083893c | ||
|
|
72ed19ff36 | ||
|
|
39b8e3d14a | ||
|
|
3dc70148d1 | ||
|
|
b63dfa8638 |
@@ -0,0 +1,40 @@
|
||||
# This is a basic workflow to help you get started with Actions
|
||||
|
||||
name: CI
|
||||
|
||||
# Controls when the workflow will run
|
||||
on:
|
||||
# Triggers the workflow on push or pull request events but only for the master branch
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||
jobs:
|
||||
# This workflow contains a single job called "build"
|
||||
build:
|
||||
# The type of runner that the job will run on
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# Steps represent a sequence of tasks that will be executed as part of the job
|
||||
steps:
|
||||
# Runs a set of commands using the runners shell
|
||||
#- name: Logging into Dockerhub
|
||||
# run: docker login -u ${{ secrets.DOCKERHUB_USERNAME }} -p ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
|
||||
- name: Pulling the docker image
|
||||
run: docker pull vezzal/vezzal:v1
|
||||
|
||||
- name: Start the container with the docker image
|
||||
run: docker run -id --name test_netgen vezzal/vezzal:v1 bash | exit
|
||||
|
||||
- name: Run the testing on the container and send the mail
|
||||
run: docker exec test_netgen /vezzal/test_netgen.sh "[email protected],[email protected]" ${{ secrets.MAILING_KEY }}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -7,8 +7,11 @@ config.log
|
||||
scripts/config.log
|
||||
config.status
|
||||
scripts/config.status
|
||||
python/lvs_manager.py
|
||||
*.o
|
||||
*.so
|
||||
*~
|
||||
*.log
|
||||
UPDATE_ME
|
||||
tcltk/netgen.sh
|
||||
tcltk/netgen.tcl
|
||||
|
||||
@@ -9,7 +9,7 @@ MODULES = base
|
||||
MAKEFLAGS =
|
||||
INSTALL_CAD_DIRS = lib doc
|
||||
|
||||
include defs.mak
|
||||
-include defs.mak
|
||||
|
||||
all: $(ALL_TARGET)
|
||||
|
||||
@@ -51,8 +51,8 @@ depend:
|
||||
install: $(INSTALL_TARGET)
|
||||
|
||||
install-netgen:
|
||||
@echo --- installing executable to $(DESTDIR)${BINDIR}
|
||||
@echo --- installing run-time files to $(DESTDIR)${LIBDIR}
|
||||
@echo --- installing executable to $(DESTDIR)${INSTALL_BINDIR}
|
||||
@echo --- installing run-time files to $(DESTDIR)${INSTALL_LIBDIR}
|
||||
@${MAKE} install-real >> install.log
|
||||
|
||||
install-real: install-dirs
|
||||
@@ -60,15 +60,15 @@ install-real: install-dirs
|
||||
(cd $$dir && ${MAKE} install); done
|
||||
|
||||
install-tcl-dirs:
|
||||
${NETGENDIR}/scripts/mkdirs $(DESTDIR)${BINDIR} \
|
||||
$(DESTDIR)${TCLDIR} $(DESTDIR)${PYDIR}
|
||||
${NETGENDIR}/scripts/mkdirs $(DESTDIR)${INSTALL_BINDIR} \
|
||||
$(DESTDIR)${INSTALL_TCLDIR} $(DESTDIR)${INSTALL_PYDIR}
|
||||
|
||||
install-dirs:
|
||||
${NETGENDIR}/scripts/mkdirs $(DESTDIR)${BINDIR}
|
||||
${NETGENDIR}/scripts/mkdirs $(DESTDIR)${INSTALL_BINDIR}
|
||||
|
||||
install-tcl: install-dirs
|
||||
@echo --- installing executable to $(DESTDIR)${BINDIR}
|
||||
@echo --- installing run-time files to $(DESTDIR)${LIBDIR}
|
||||
@echo --- installing executable to $(DESTDIR)${INSTALL_BINDIR}
|
||||
@echo --- installing run-time files to $(DESTDIR)${INSTALL_LIBDIR}
|
||||
@${MAKE} install-tcl-real 2>&1 >> install.log
|
||||
|
||||
install-tcl-real: install-tcl-dirs
|
||||
|
||||
+48
-1
@@ -1,4 +1,8 @@
|
||||
NETGEN: VERSION 1.5
|
||||

|
||||
|
||||
# NETGEN
|
||||
|
||||
### VERSION 1.5
|
||||
|
||||
NETGEN is a general-purpose netlist management system. It can read
|
||||
and write several netlist formats, including NTK (Caltech, CMU),
|
||||
@@ -87,6 +91,49 @@ and IRSIM version 9.7:
|
||||
|
||||
Note: For FreeBSD, use 'gmake' instead.
|
||||
|
||||
Note: On MacOS (Big Sur) follow the following procedure. If you have installed `xschem` and `magic` already on MacOS then steps (1) and (2) can likely be skipped.
|
||||
|
||||
**1) Build Tcl for X11**
|
||||
|
||||
We are following the instructions from `xschem` (https://github.com/StefanSchippers/xschem/blob/master/README_MacOS.md).
|
||||
|
||||
* Download `Tcl` from https://prdownloads.sourceforge.net/tcl/tcl8.6.10-src.tar.gz
|
||||
|
||||
We are using not `opt` but `opt2` so that this `Tcl` does not interfere with `tcl-tk` from HomeBrew.
|
||||
|
||||
```
|
||||
./configure --prefix=/usr/local/opt2/tcl-tk
|
||||
make
|
||||
make install
|
||||
```
|
||||
|
||||
**2) Build Tk for X11**
|
||||
|
||||
* Download `Tk` from https://prdownloads.sourceforge.net/tcl/tk8.6.10-src.tar.gz
|
||||
|
||||
```
|
||||
./configure --prefix=/usr/local/opt2/tcl-tk \
|
||||
--with-tcl=/usr/local/opt2/tcl-tk/lib --with-x \
|
||||
--x-includes=/opt/X11/include --x-libraries=/opt/X11/lib
|
||||
make
|
||||
make install
|
||||
```
|
||||
|
||||
**3) Build netgen**
|
||||
|
||||
We need to provide this custom-built `tcl-tk` and suppress compilation errors.
|
||||
|
||||
```
|
||||
./configure --with-tcl=/usr/local/opt2/tcl-tk/lib \
|
||||
--with-tk=/usr/local/opt2/tcl-tk/lib \
|
||||
--x-includes=/opt/X11/include \
|
||||
--x-libraries=/opt/X11/lib \
|
||||
CFLAGS=-Wno-error=implicit-function-declaration
|
||||
make
|
||||
make install
|
||||
```
|
||||
|
||||
|
||||
IN CASE OF FAILURE
|
||||
-------------------
|
||||
Please contact me (tim@opencircuitdesign.com) to report compile-time and
|
||||
+1
-1
@@ -131,7 +131,7 @@ if format = 1, use the actel .pin file format
|
||||
struct nlist *tp;
|
||||
struct objlist *ob, *ob2;
|
||||
char *ptr;
|
||||
char physicalpin[200];
|
||||
char physicalpin[MAX_STR_LEN];
|
||||
|
||||
tp = LookupCell(name);
|
||||
if (tp == NULL) return;
|
||||
|
||||
@@ -176,4 +176,6 @@ extern int open(char *path, int oflag, ...); /* HPUX has it in <sys/fcntl.h> */
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#define MAX_STR_LEN 256
|
||||
|
||||
#endif /* _CONFIG_H */
|
||||
|
||||
+3
-3
@@ -629,7 +629,7 @@ struct embed *FlattenEmbeddingTree(struct embed *E)
|
||||
int LenEmbed(char *prefix, struct nlist *np, struct embed *E, int flatten)
|
||||
/* return the number of characters required to print element E */
|
||||
{
|
||||
char longstr[200];
|
||||
char longstr[MAX_STR_LEN];
|
||||
|
||||
if (E == NULL) return(0);
|
||||
if (E->left == NULL && E->right == NULL) {
|
||||
@@ -668,7 +668,7 @@ void PrintEmb(FILE *outfile, char *prefix, struct nlist *np,
|
||||
struct objlist *ob;
|
||||
char *instancename;
|
||||
struct nlist *np2;
|
||||
char name[200];
|
||||
char name[MAX_STR_LEN];
|
||||
|
||||
ob = InstanceNumber(np,E->instancenumber);
|
||||
instancename = ob->instance.name;
|
||||
@@ -706,7 +706,7 @@ void PrintEmbed(FILE *outfile, char *prefix, struct nlist *np,
|
||||
struct objlist *ob;
|
||||
char *instancename;
|
||||
struct nlist *np2;
|
||||
char name[200];
|
||||
char name[MAX_STR_LEN];
|
||||
|
||||
ob = InstanceNumber(np,E->instancenumber);
|
||||
instancename = ob->instance.name;
|
||||
|
||||
+27
-26
@@ -23,12 +23,13 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* for strtod() */
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "netgen.h"
|
||||
#include "hash.h"
|
||||
#include "objlist.h"
|
||||
#include "netfile.h"
|
||||
#include "print.h"
|
||||
#include "hash.h"
|
||||
|
||||
void extCell(char *name, int filenum)
|
||||
{
|
||||
@@ -166,7 +167,7 @@ char *ReadExt(char *fname, int doflat, int *fnum)
|
||||
int filenum;
|
||||
|
||||
if ((filenum = OpenParseFile(fname, *fnum)) < 0) {
|
||||
char name[100];
|
||||
char name[MAX_STR_LEN];
|
||||
|
||||
SetExtension(name, fname, EXT_EXTENSION);
|
||||
if ((filenum = OpenParseFile(name, *fnum)) < 0) {
|
||||
@@ -186,7 +187,7 @@ char *ReadExt(char *fname, int doflat, int *fnum)
|
||||
/* Make sure all .ext file reading is case sensitive */
|
||||
matchfunc = match;
|
||||
matchintfunc = matchfile;
|
||||
hashfunc = hash;
|
||||
hashfunc = hashcase;
|
||||
|
||||
if (LookupCellFile(fname, filenum) != NULL) {
|
||||
Printf("Error: Duplicate cell name \"%s\"!\n", fname);
|
||||
@@ -207,7 +208,7 @@ char *ReadExt(char *fname, int doflat, int *fnum)
|
||||
else if (match(nexttok, "style")) SkipNewLine(NULL);
|
||||
else if (match(nexttok, "resistclasses")) SkipNewLine(NULL);
|
||||
else if (match(nexttok, "node")) {
|
||||
char name[200];
|
||||
char name[MAX_STR_LEN];
|
||||
|
||||
/* No cell is generated until at least one valid "node" or "use" */
|
||||
/* has been read in the file. */
|
||||
@@ -222,8 +223,8 @@ char *ReadExt(char *fname, int doflat, int *fnum)
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
else if (match(nexttok, "equiv")) {
|
||||
char name[200];
|
||||
char name2[200];
|
||||
char name[MAX_STR_LEN];
|
||||
char name2[MAX_STR_LEN];
|
||||
SkipTok(NULL);
|
||||
GetExtName(name, nexttok);
|
||||
if (LookupObject(name,CurrentCell) == NULL) Node(name);
|
||||
@@ -234,8 +235,8 @@ char *ReadExt(char *fname, int doflat, int *fnum)
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
else if (match(nexttok, "device")) {
|
||||
char dev_name[100], dev_class[100];
|
||||
char gate[200], drain[200], source[200], subs[200];
|
||||
char dev_name[MAX_STR_LEN], dev_class[MAX_STR_LEN];
|
||||
char gate[MAX_STR_LEN], drain[MAX_STR_LEN], source[MAX_STR_LEN], subs[MAX_STR_LEN];
|
||||
char inststr[64];
|
||||
SkipTok(NULL);
|
||||
strcpy(dev_class, nexttok);
|
||||
@@ -305,8 +306,8 @@ char *ReadExt(char *fname, int doflat, int *fnum)
|
||||
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 fet_class[MAX_STR_LEN];
|
||||
char gate[MAX_STR_LEN], drain[MAX_STR_LEN], source[MAX_STR_LEN], subs[MAX_STR_LEN];
|
||||
char inststr[64];
|
||||
SkipTok(NULL);
|
||||
strcpy(fet_class, nexttok);
|
||||
@@ -364,7 +365,7 @@ char *ReadExt(char *fname, int doflat, int *fnum)
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
else {
|
||||
char ctop[200], cbot[200], cdummy[200];
|
||||
char ctop[MAX_STR_LEN], cbot[MAX_STR_LEN], cdummy[MAX_STR_LEN];
|
||||
SkipTok(NULL);
|
||||
GetExtName(ctop, nexttok);
|
||||
SkipTok(NULL);
|
||||
@@ -374,8 +375,8 @@ char *ReadExt(char *fname, int doflat, int *fnum)
|
||||
}
|
||||
}
|
||||
else if (match(nexttok, "use")) {
|
||||
char name[200];
|
||||
char instancename[200];
|
||||
char name[MAX_STR_LEN];
|
||||
char instancename[MAX_STR_LEN];
|
||||
char *basename;
|
||||
|
||||
/* No cell is generated until at least one valid "node" or "use" */
|
||||
@@ -389,7 +390,7 @@ char *ReadExt(char *fname, int doflat, int *fnum)
|
||||
SkipTok(NULL);
|
||||
GetExtName(name, nexttok);
|
||||
if ((basename = strrchr(name,'/')) != NULL) {
|
||||
char tmp[200];
|
||||
char tmp[MAX_STR_LEN];
|
||||
strcpy(tmp, basename+1);
|
||||
strcpy(name, tmp);
|
||||
}
|
||||
@@ -404,8 +405,8 @@ char *ReadExt(char *fname, int doflat, int *fnum)
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
else if (match(nexttok, "merge")) {
|
||||
char name[200];
|
||||
char name2[200];
|
||||
char name[MAX_STR_LEN];
|
||||
char name2[MAX_STR_LEN];
|
||||
SkipTok(NULL);
|
||||
GetExtName(name, nexttok);
|
||||
SkipTok(NULL);
|
||||
@@ -639,7 +640,7 @@ char *ReadSim(char *fname, int *fnum)
|
||||
double simscale = 1.0;
|
||||
|
||||
if ((filenum = OpenParseFile(fname, *fnum)) < 0) {
|
||||
char name[100];
|
||||
char name[MAX_STR_LEN];
|
||||
|
||||
SetExtension(name, fname, SIM_EXTENSION);
|
||||
if (OpenParseFile(name, *fnum) < 0) {
|
||||
@@ -652,7 +653,7 @@ char *ReadSim(char *fname, int *fnum)
|
||||
/* Make sure all .sim file reading is case sensitive */
|
||||
matchfunc = match;
|
||||
matchintfunc = matchfile;
|
||||
hashfunc = hash;
|
||||
hashfunc = hashcase;
|
||||
|
||||
CellDef(fname, filenum);
|
||||
|
||||
@@ -669,7 +670,7 @@ char *ReadSim(char *fname, int *fnum)
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
else if (match(nexttok, "n")) {
|
||||
char gate[200], drain[200], source[200];
|
||||
char gate[MAX_STR_LEN], drain[MAX_STR_LEN], source[MAX_STR_LEN];
|
||||
char inststr[25], *instptr = NULL;
|
||||
|
||||
SkipTok(NULL);
|
||||
@@ -713,7 +714,7 @@ char *ReadSim(char *fname, int *fnum)
|
||||
LinkProperties("n", kvlist);
|
||||
}
|
||||
else if (match(nexttok, "p")) {
|
||||
char gate[200], drain[200], source[200];
|
||||
char gate[MAX_STR_LEN], drain[MAX_STR_LEN], source[MAX_STR_LEN];
|
||||
char inststr[25], *instptr = NULL;
|
||||
SkipTok(NULL);
|
||||
GetExtName(gate, nexttok);
|
||||
@@ -753,7 +754,7 @@ char *ReadSim(char *fname, int *fnum)
|
||||
LinkProperties("p", kvlist);
|
||||
}
|
||||
else if (match(nexttok, "e")) { /* 3-port capacitors (poly/poly2) */
|
||||
char gate[200], drain[200], source[200];
|
||||
char gate[MAX_STR_LEN], drain[MAX_STR_LEN], source[MAX_STR_LEN];
|
||||
char inststr[25], *instptr = NULL;
|
||||
SkipTok(NULL);
|
||||
GetExtName(gate, nexttok);
|
||||
@@ -787,7 +788,7 @@ char *ReadSim(char *fname, int *fnum)
|
||||
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 base[MAX_STR_LEN], emitter[MAX_STR_LEN], collector[MAX_STR_LEN];
|
||||
char inststr[25], *instptr = NULL;
|
||||
SkipTok(NULL);
|
||||
GetExtName(base, nexttok);
|
||||
@@ -825,7 +826,7 @@ char *ReadSim(char *fname, int *fnum)
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
else {
|
||||
char ctop[200], cbot[200], cdummy[200];
|
||||
char ctop[MAX_STR_LEN], cbot[MAX_STR_LEN], cdummy[MAX_STR_LEN];
|
||||
SkipTok(NULL);
|
||||
GetExtName(ctop, nexttok);
|
||||
if (LookupObject(ctop, CurrentCell) == NULL)
|
||||
@@ -850,7 +851,7 @@ char *ReadSim(char *fname, int *fnum)
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
else {
|
||||
char rtop[200], rbot[200];
|
||||
char rtop[MAX_STR_LEN], rbot[MAX_STR_LEN];
|
||||
SkipTok(NULL);
|
||||
GetExtName(rtop, nexttok);
|
||||
if (LookupObject(rtop, CurrentCell) == NULL)
|
||||
@@ -874,7 +875,7 @@ char *ReadSim(char *fname, int *fnum)
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
else {
|
||||
char rtop[200], rbot[200], rdummy[200];
|
||||
char rtop[MAX_STR_LEN], rbot[MAX_STR_LEN], rdummy[MAX_STR_LEN];
|
||||
char inststr[25], *instptr = NULL;
|
||||
SkipTok(NULL);
|
||||
GetExtName(rdummy, nexttok);
|
||||
@@ -916,7 +917,7 @@ char *ReadSim(char *fname, int *fnum)
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
else if (match(nexttok, "=")) {
|
||||
char node1[200], node2[200];
|
||||
char node1[MAX_STR_LEN], node2[MAX_STR_LEN];
|
||||
SkipTok(NULL);
|
||||
GetExtName(node1, nexttok);
|
||||
SkipTok(NULL);
|
||||
|
||||
+475
-251
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,8 @@
|
||||
#ifndef _FLATTEN_H
|
||||
#define _FLATTEN_H
|
||||
|
||||
extern int UniquePins(char *name, int filenum);
|
||||
extern void flattenCell(char *name, int file);
|
||||
extern int HasContents(struct nlist *);
|
||||
|
||||
#endif /* _FLATTEN_H */
|
||||
+2
-2
@@ -30,8 +30,8 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#endif
|
||||
|
||||
#include "netgen.h"
|
||||
#include "hash.h"
|
||||
#include "objlist.h"
|
||||
#include "hash.h"
|
||||
|
||||
unsigned long (*hashfunc)(char *, int) = NULL;
|
||||
int (*matchfunc)(char *, char *) = NULL;
|
||||
@@ -148,7 +148,7 @@ unsigned long hashnocase(char *s, int hashsize)
|
||||
return (hashsize == 0) ? hashval : (hashval % hashsize);
|
||||
}
|
||||
|
||||
unsigned long hash(char *s, int hashsize)
|
||||
unsigned long hashcase(char *s, int hashsize)
|
||||
{
|
||||
unsigned long hashval;
|
||||
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ extern void *HashFirst(struct hashdict *dict);
|
||||
extern void *HashNext(struct hashdict *dict);
|
||||
|
||||
extern unsigned long hashnocase(char *s, int hashsize);
|
||||
extern unsigned long hash(char *s, int hashsize);
|
||||
extern unsigned long hashcase(char *s, int hashsize);
|
||||
|
||||
extern int (*matchfunc)(char *, char *);
|
||||
/* matchintfunc() compares based on the name and the first */
|
||||
|
||||
+2
-1
@@ -17,6 +17,7 @@ along with this program; see the file copying. If not, write to
|
||||
the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
/* inetcomp.c -- a simple wrapper to the NETCOMP() function */
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include "netgen.h"
|
||||
@@ -33,7 +34,7 @@ void STRCPY(char *dest, char *source)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char cell1[200], cell2[200];
|
||||
char cell1[MAX_STR_LEN], cell2[MAX_STR_LEN];
|
||||
|
||||
Debug = 0;
|
||||
if (argc != 1) {
|
||||
|
||||
+1540
-524
File diff suppressed because it is too large
Load Diff
+17
-1
@@ -7,6 +7,10 @@ extern struct nlist *Circuit1;
|
||||
extern struct nlist *Circuit2;
|
||||
|
||||
extern int ExhaustiveSubdivision;
|
||||
extern int ExactTopology;
|
||||
|
||||
extern int left_col_end;
|
||||
extern int right_col_end;
|
||||
|
||||
#ifdef TCL_NETGEN
|
||||
#include <tcl.h>
|
||||
@@ -23,6 +27,7 @@ extern void PrintCoreStats(void);
|
||||
extern void ResetState(void);
|
||||
extern void CreateTwoLists(char *name1, int file1, char *name2, int file2,
|
||||
int dolist);
|
||||
extern void DescribeContents(char *name1, int file1, char *name2, int file2);
|
||||
extern int Iterate(void);
|
||||
extern int VerifyMatching(void);
|
||||
extern void PrintAutomorphisms(void);
|
||||
@@ -33,7 +38,8 @@ extern int PermuteSetup(char *model, int filenum, char *pin1, char *pin2);
|
||||
extern int PermuteForget(char *model, int filenum, char *pin1, char *pin2);
|
||||
extern int EquivalenceElements(char *name1, int file1, char *name2, int file2);
|
||||
extern int EquivalenceNodes(char *name1, int file1, char *name2, int file2);
|
||||
extern int EquivalenceClasses(char *name1, int file1, char *name2, int file2);
|
||||
extern int EquivalenceClasses(char *name1, int file1, char *name2, int file2,
|
||||
int dounique);
|
||||
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,
|
||||
@@ -43,6 +49,7 @@ extern int CreateCompareQueue(char *, int, char *, int);
|
||||
extern int GetCompareQueueTop(char **, int *, char **, int *);
|
||||
extern int PeekCompareQueueTop(char **, int *, char **, int *);
|
||||
extern void RemoveCompareQueue();
|
||||
extern int FlattenUnmatched(struct nlist *, char *, int, int);
|
||||
|
||||
extern void PrintIllegalClasses();
|
||||
extern void PrintIllegalNodeClasses();
|
||||
@@ -51,6 +58,15 @@ extern void PrintIllegalElementClasses();
|
||||
extern void DumpNetwork(struct objlist *ob, int cidx);
|
||||
extern void DumpNetworkAll(char *name, int file);
|
||||
|
||||
extern void RegroupDataStructures();
|
||||
extern void FormatIllegalElementClasses();
|
||||
extern void FormatIllegalNodeClasses();
|
||||
extern int ResolveAutomorphsByProperty();
|
||||
extern int ResolveAutomorphsByPin();
|
||||
extern void SummarizeElementClasses(struct ElementClass *EC);
|
||||
extern int remove_group_tags(struct objlist *ob);
|
||||
|
||||
|
||||
#ifdef TCL_NETGEN
|
||||
extern int EquivalentNode();
|
||||
extern int EquivalentElement();
|
||||
|
||||
+269
-35
@@ -47,6 +47,18 @@ static FILE *outfile;
|
||||
static int Graph = 0;
|
||||
int File;
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
/* Structure for stacking nested `if[n]def in verilog */
|
||||
/*------------------------------------------------------*/
|
||||
|
||||
struct ifstack {
|
||||
int invert;
|
||||
struct property *kl;
|
||||
struct ifstack *next;
|
||||
};
|
||||
|
||||
struct ifstack *condstack = NULL;
|
||||
|
||||
extern char *SetExtension(char *buffer, char *path, char *extension)
|
||||
/* add 'extension' to 'path' (overwriting previous extension, if any),
|
||||
write it into buffer (if buffer is null, malloc a buffer).
|
||||
@@ -191,11 +203,14 @@ struct filestack {
|
||||
|
||||
static struct filestack *OpenFiles = NULL;
|
||||
|
||||
struct hashdict *definitions = (struct hashdict *)NULL;
|
||||
|
||||
#define WHITESPACE_DELIMITER " \t\n\r"
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* TrimQuoted() --- */
|
||||
/* Remove spaces from inside single- or double-quoted strings. */
|
||||
/* Ignore verilog constant bits (e.g., "1'b0") when parsing. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
void TrimQuoted(char *line)
|
||||
@@ -211,6 +226,13 @@ void TrimQuoted(char *line)
|
||||
{
|
||||
changed = FALSE;
|
||||
qstart = strchr(lptr, '\'');
|
||||
if (qstart && (qstart > lptr)) {
|
||||
if (isdigit(*(qstart - 1))) {
|
||||
lptr = qstart + 1;
|
||||
changed = TRUE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (qstart)
|
||||
{
|
||||
qend = strchr(qstart + 1, '\'');
|
||||
@@ -251,7 +273,6 @@ void TrimQuoted(char *line)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
@@ -265,39 +286,226 @@ void TrimQuoted(char *line)
|
||||
|
||||
int GetNextLineNoNewline(char *delimiter)
|
||||
{
|
||||
char *newbuf;
|
||||
int testc;
|
||||
char *newbuf;
|
||||
int testc;
|
||||
int nested = 0;
|
||||
int llen;
|
||||
|
||||
if (feof(infile)) return -1;
|
||||
if (feof(infile)) return -1;
|
||||
|
||||
// This is more reliable than feof() ...
|
||||
testc = getc(infile);
|
||||
if (testc == -1) return -1;
|
||||
ungetc(testc, infile);
|
||||
while (1) { /* May loop indefinitely in an `if[n]def conditional */
|
||||
|
||||
if (linesize == 0) {
|
||||
/* Allocate memory for line */
|
||||
linesize = 500;
|
||||
line = (char *)MALLOC(linesize);
|
||||
linetok = (char *)MALLOC(linesize);
|
||||
}
|
||||
fgets(line, linesize, infile);
|
||||
while (strlen(line) == linesize - 1) {
|
||||
newbuf = (char *)MALLOC(linesize + 500);
|
||||
strcpy(newbuf, line);
|
||||
FREE(line);
|
||||
line = newbuf;
|
||||
fgets(line + linesize - 1, 501, infile);
|
||||
linesize += 500;
|
||||
FREE(linetok);
|
||||
linetok = (char *)MALLOC(linesize);
|
||||
}
|
||||
linenum++;
|
||||
strcpy(linetok, line);
|
||||
TrimQuoted(linetok);
|
||||
// This is more reliable than feof() ...
|
||||
testc = getc(infile);
|
||||
if (testc == -1) return -1;
|
||||
ungetc(testc, infile);
|
||||
|
||||
nexttok = strdtok(linetok, WHITESPACE_DELIMITER, delimiter);
|
||||
return 0;
|
||||
if (linesize == 0) {
|
||||
/* Allocate memory for line */
|
||||
linesize = 2000;
|
||||
line = (char *)MALLOC(linesize + 1);
|
||||
linetok = (char *)MALLOC(linesize + 1);
|
||||
}
|
||||
fgets(line, linesize, infile);
|
||||
/* Immediately resolve backslash-EOL */
|
||||
llen = strlen(line);
|
||||
while ((llen > 1) && (llen < linesize - 1) && *(line + llen - 2) == '\\') {
|
||||
*(line + llen - 2) = '\n';
|
||||
fgets(line + llen - 1, linesize - llen + 1, infile);
|
||||
llen = strlen(line);
|
||||
}
|
||||
while (llen == linesize - 1) {
|
||||
newbuf = (char *)MALLOC(linesize + 501);
|
||||
strcpy(newbuf, line);
|
||||
FREE(line);
|
||||
line = newbuf;
|
||||
fgets(line + linesize - 1, 501, infile);
|
||||
llen = strlen(line);
|
||||
while ((llen > 1) && (llen < linesize - 1) && *(line + llen - 2) == '\\') {
|
||||
*(line + llen - 2) = '\n';
|
||||
fgets(line + llen - 1, linesize - llen + 1, infile);
|
||||
llen = strlen(line);
|
||||
}
|
||||
linesize += 500;
|
||||
FREE(linetok);
|
||||
linetok = (char *)MALLOC(linesize + 1);
|
||||
}
|
||||
|
||||
if (definitions == NULL)
|
||||
strcpy(linetok, line);
|
||||
else {
|
||||
char *s, *t, *w, e;
|
||||
struct property *kl;
|
||||
int len, dlen, vlen, addin = 0;
|
||||
int oldlinesize = linesize;
|
||||
unsigned char found = TRUE;
|
||||
|
||||
/* Check for substitutions (verilog only). Make sure linetok is */
|
||||
/* large enough to hold the entire line after substitutions. */
|
||||
|
||||
while (found) { /* Do this recursively, for nested definitions */
|
||||
found = FALSE;
|
||||
|
||||
for (s = line; *s != '\0'; s++) {
|
||||
if (*s == '`') {
|
||||
w = s + 1;
|
||||
while (isalnum(*w) || (*w == '_') || (*w == '$')) w++;
|
||||
e = *w;
|
||||
*w = '\0';
|
||||
kl = (struct property *)HashLookup(s + 1, definitions);
|
||||
if (kl != NULL) {
|
||||
dlen = strlen(s);
|
||||
if (kl->type == PROP_STRING) {
|
||||
vlen = strlen(kl->pdefault.string);
|
||||
}
|
||||
else vlen = 12; /* Leave room for numeric conversion */
|
||||
addin += vlen - dlen + 1;
|
||||
found = TRUE;
|
||||
}
|
||||
*w = e;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
len = strlen(line);
|
||||
if (len + addin > linesize) {
|
||||
while (len + addin > linesize) linesize += 500;
|
||||
FREE(linetok);
|
||||
linetok = (char *)MALLOC(linesize);
|
||||
}
|
||||
}
|
||||
|
||||
/* Make definition substitutions (verilog only) */
|
||||
|
||||
t = linetok;
|
||||
for (s = line; *s != '\0'; s++) {
|
||||
if (*s == '`') {
|
||||
w = s + 1;
|
||||
while (isalnum(*w) || (*w == '_') || (*w == '$')) w++;
|
||||
e = *w;
|
||||
*w = '\0';
|
||||
kl = (struct property *)HashLookup(s + 1, definitions);
|
||||
if (kl != NULL) {
|
||||
if (kl->type == PROP_STRING)
|
||||
strcpy(t, kl->pdefault.string);
|
||||
else if (kl->type == PROP_INTEGER)
|
||||
sprintf(t, "%d", kl->pdefault.ival);
|
||||
else if (kl->type == PROP_DOUBLE)
|
||||
sprintf(t, "%g", kl->pdefault.dval);
|
||||
t += strlen(t);
|
||||
s = w - 1;
|
||||
}
|
||||
else *t++ = *s;
|
||||
*w = e;
|
||||
}
|
||||
else *t++ = *s;
|
||||
}
|
||||
*t = '\0';
|
||||
|
||||
/* Copy substituted linetok back to line and repeat until */
|
||||
/* there are no more substitutions to be made. */
|
||||
|
||||
if (oldlinesize != linesize) {
|
||||
FREE(line);
|
||||
line = (char *)MALLOC(linesize + 501);
|
||||
oldlinesize = linesize;
|
||||
}
|
||||
strcpy(line, linetok);
|
||||
}
|
||||
}
|
||||
|
||||
TrimQuoted(linetok);
|
||||
linenum++;
|
||||
|
||||
nexttok = strdtok(linetok, WHITESPACE_DELIMITER, delimiter);
|
||||
if (nexttok == NULL) return 0;
|
||||
|
||||
/* Handle `ifdef, `ifndef, `elsif, `else, and `endif (verilog */
|
||||
/* only, where indicated by a non-NULL "definitions") */
|
||||
|
||||
if (definitions == NULL) return 0;
|
||||
|
||||
/* If currently skipping through a section, handle conditionals differently */
|
||||
|
||||
if (condstack) {
|
||||
if (((condstack->invert == 0) && (condstack->kl == NULL))
|
||||
|| ((condstack->invert == 1) && (condstack->kl != NULL))) {
|
||||
if (match(nexttok, "`ifdef") || match(nexttok, "`ifndef")) {
|
||||
nested++;
|
||||
continue;
|
||||
}
|
||||
else if (nested > 0) {
|
||||
if (match(nexttok, "`endif")) nested--;
|
||||
continue;
|
||||
}
|
||||
else if (nexttok[0] != '`') continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle conditionals (that is not being skipped over) */
|
||||
|
||||
if (match(nexttok, "`endif")) {
|
||||
if (condstack == NULL) {
|
||||
fprintf(stderr, "Error: `endif without corresponding `if[n]def\n");
|
||||
}
|
||||
else {
|
||||
struct ifstack *iftop = condstack;
|
||||
condstack = condstack->next;
|
||||
FREE(iftop);
|
||||
}
|
||||
}
|
||||
|
||||
/* Note that `if[n]def may be nested. */
|
||||
|
||||
else if (match(nexttok, "`ifdef") || match(nexttok, "`ifndef") ||
|
||||
match(nexttok, "`elsif") || match(nexttok, "`else")) {
|
||||
|
||||
/* Every `ifdef or `ifndef increases condstack by 1 */
|
||||
if (nexttok[1] == 'i') {
|
||||
struct ifstack *newif = (struct ifstack *)MALLOC(sizeof(struct ifstack));
|
||||
newif->next = condstack;
|
||||
condstack = newif;
|
||||
}
|
||||
if (condstack == NULL) {
|
||||
fprintf(stderr, "Error: %s without `if[n]def\n", nexttok);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
if (match(nexttok, "`else")) {
|
||||
/* Invert the sense of the if[n]def scope */
|
||||
condstack->invert = (condstack->invert == 1) ? 0 : 1;
|
||||
}
|
||||
else if (match(nexttok, "`elsif")) {
|
||||
nexttok = strdtok(NULL, WHITESPACE_DELIMITER, delimiter);
|
||||
if (nexttok == NULL) {
|
||||
fprintf(stderr, "Error: `elsif with no conditional.\n");
|
||||
return 0;
|
||||
}
|
||||
/* Keep the same scope but redefine the parameter */
|
||||
condstack->invert = 0;
|
||||
condstack->kl = (struct property *)HashLookup(nexttok, definitions);
|
||||
}
|
||||
else {
|
||||
condstack->invert = (nexttok[3] == 'n') ? 1 : 0;
|
||||
nexttok = strdtok(NULL, WHITESPACE_DELIMITER, delimiter);
|
||||
if (nexttok == NULL) {
|
||||
fprintf(stderr, "Error: %s with no conditional.\n", nexttok);
|
||||
return 0;
|
||||
}
|
||||
condstack->kl = (struct property *)HashLookup(nexttok, definitions);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (condstack) {
|
||||
if (((condstack->invert == 0) && (condstack->kl == NULL))
|
||||
|| ((condstack->invert == 1) && (condstack->kl != NULL)))
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
@@ -312,6 +520,24 @@ void GetNextLine(char *delimiter)
|
||||
} while (nexttok == NULL);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Return a pointer to the line at the position of nexttok */
|
||||
/* This is used only when returning the entire line, untokenized, and */
|
||||
/* is only called by the verilog read routine when reading the value of */
|
||||
/* a `define statement. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
char *GetLineAtTok()
|
||||
{
|
||||
char *lpos;
|
||||
|
||||
if (nexttok == NULL) return NULL;
|
||||
if (line == NULL) return NULL;
|
||||
|
||||
lpos = strstr(line, nexttok);
|
||||
return lpos;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* if nexttok is already NULL, force scanner to read new line */
|
||||
/*----------------------------------------------------------------------*/
|
||||
@@ -489,6 +715,7 @@ char *strdtok(char *pstring, char *delim1, char *delim2)
|
||||
/* accordingly (needs to be done). */
|
||||
|
||||
if (*s == '\\') {
|
||||
s++;
|
||||
while (*s != '\0') {
|
||||
if ((*s == ' ') || (*s == '\\')) {
|
||||
s++;
|
||||
@@ -581,7 +808,7 @@ int OpenParseFile(char *name, int fnum)
|
||||
FILE *locfile;
|
||||
struct filestack *newfile;
|
||||
|
||||
locfile = fopen(name,"r");
|
||||
locfile = fopen(name, "r");
|
||||
linenum = 0;
|
||||
/* reset the token scanner */
|
||||
nexttok = NULL;
|
||||
@@ -666,7 +893,12 @@ char *ReadNetlist(char *fname, int *fnum)
|
||||
{SPICE_EXTENSION, ReadSpice},
|
||||
{SPICE_EXT2, ReadSpice},
|
||||
{SPICE_EXT3, ReadSpice},
|
||||
{SPICE_EXT4, ReadSpice},
|
||||
{SPICE_EXT5, ReadSpice},
|
||||
{SPICE_EXT6, ReadSpice},
|
||||
{SPICE_EXT7, ReadSpice},
|
||||
{VERILOG_EXTENSION, ReadVerilog},
|
||||
{SYS_VERILOG_EXTENSION, ReadVerilog},
|
||||
{NETGEN_EXTENSION, ReadNetgenFile},
|
||||
{NULL, NULL}
|
||||
};
|
||||
@@ -674,13 +906,15 @@ char *ReadNetlist(char *fname, int *fnum)
|
||||
|
||||
/* make first pass looking for extension */
|
||||
for (index = 0; formats[index].extension != NULL; index++) {
|
||||
if (strstr(fname, formats[index].extension) != NULL) {
|
||||
int extlen = strlen(formats[index].extension);
|
||||
int flen = strlen(fname);
|
||||
if (!strcmp(fname + flen - extlen, formats[index].extension)) {
|
||||
return (*(formats[index].proc))(fname, fnum);
|
||||
}
|
||||
}
|
||||
/* try appending extensions in sequence, and testing for file existance */
|
||||
for (index = 0; formats[index].extension != NULL; index++) {
|
||||
char testname[200];
|
||||
char testname[MAX_STR_LEN];
|
||||
strcpy(testname, fname);
|
||||
strcat(testname, formats[index].extension);
|
||||
if (OpenParseFile(testname, *fnum) >= 0) {
|
||||
@@ -785,7 +1019,7 @@ void WriteNetgenFile(char *name, char *filename)
|
||||
|
||||
char *ReadNetgenFile (char *fname, int *fnum)
|
||||
{
|
||||
char name[100];
|
||||
char name[MAX_STR_LEN];
|
||||
char *LastCellRead = NULL;
|
||||
int filenum;
|
||||
|
||||
@@ -1021,7 +1255,7 @@ int READ(void *buf, int bytes)
|
||||
|
||||
char *ReadNetgenFile (char *fname, int *fnum)
|
||||
{
|
||||
char name[100];
|
||||
char name[MAX_STR_LEN];
|
||||
int len, chars;
|
||||
char *LastCellRead = NULL;
|
||||
|
||||
|
||||
+9
-1
@@ -9,11 +9,16 @@
|
||||
#define SIM_EXTENSION ".sim"
|
||||
#define SPICE_EXTENSION ".spice"
|
||||
#define SPICE_EXT2 ".spc"
|
||||
#define SPICE_EXT3 ".fspc"
|
||||
#define SPICE_EXT3 ".sp"
|
||||
#define SPICE_EXT4 ".spi"
|
||||
#define SPICE_EXT5 ".fspc"
|
||||
#define SPICE_EXT6 ".cir"
|
||||
#define SPICE_EXT7 ".ckt"
|
||||
#define NETGEN_EXTENSION ".ntg"
|
||||
#define CCODE_EXTENSION ".c.code"
|
||||
#define ESACAP_EXTENSION ".esa"
|
||||
#define VERILOG_EXTENSION ".v"
|
||||
#define SYS_VERILOG_EXTENSION ".sv"
|
||||
|
||||
#define LINELENGTH 80
|
||||
|
||||
@@ -24,14 +29,17 @@ extern void FlushString (char *format, ...);
|
||||
extern char *SetExtension(char *buffer, char *path, char *extension);
|
||||
|
||||
extern int File;
|
||||
extern struct hashdict *definitions;
|
||||
|
||||
/* input routines */
|
||||
|
||||
extern char *nexttok;
|
||||
#define SKIPTO(a) do {SkipTok(NULL);} while (!match(nexttok,a))
|
||||
extern char *strdtok(char *pstring, char *delim1, char *delim2);
|
||||
extern char *GetLineAtTok();
|
||||
extern void SkipTok(char *delimiter);
|
||||
extern void SkipTokNoNewline(char *delimiter);
|
||||
extern void SkipTokComments(char *delimiter);
|
||||
extern void SkipNewLine(char *delimiter);
|
||||
extern void SpiceTokNoNewline(void); /* handles SPICE "+" continuation line */
|
||||
extern void SpiceSkipNewLine(void); /* handles SPICE "+" continuation line */
|
||||
|
||||
+693
-558
File diff suppressed because it is too large
Load Diff
+13
-1
@@ -39,11 +39,13 @@ 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 PropertyAssociatePin(char *name, int fnum, char *key, char *pin);
|
||||
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 *);
|
||||
extern int PromoteProperty(struct property *, struct valuelist *,
|
||||
struct objlist *, struct nlist *);
|
||||
extern int SetPropertyDefault(struct property *, struct valuelist *);
|
||||
extern struct objlist *LinkProperties(char *model, struct keyvalue *topptr);
|
||||
extern int ReduceExpressions(struct objlist *instprop, struct objlist *parprops,
|
||||
@@ -65,6 +67,15 @@ extern void AssignCircuits(char *name1, int file1, char *name2, int file2);
|
||||
/* flatten.c */
|
||||
extern int PrematchLists(char *, int, char *, int);
|
||||
|
||||
/* verilog.c */
|
||||
struct cellstack {
|
||||
char *cellname;
|
||||
struct cellstack *next;
|
||||
};
|
||||
|
||||
void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr,
|
||||
int blackbox);
|
||||
|
||||
/* Define (enumerate) various device classes, largely based on SPICE */
|
||||
/* model types, mixed with some ext/sim types. */
|
||||
|
||||
@@ -140,6 +151,7 @@ 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 */
|
||||
extern int GlobalParallelOpen; /* If TRUE, parallel combine cells w/no-connects */
|
||||
/* 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??? */
|
||||
|
||||
+2
-2
@@ -181,7 +181,7 @@ void Ntk(char *name, char *filename)
|
||||
|
||||
char *ReadNtk (char *fname, int *fnum)
|
||||
{
|
||||
char model[100], instancename[100], name[100];
|
||||
char model[MAX_STR_LEN], instancename[MAX_STR_LEN], name[MAX_STR_LEN];
|
||||
struct objlist *ob;
|
||||
int CellDefInProgress = 0;
|
||||
int filenum;
|
||||
@@ -218,7 +218,7 @@ char *ReadNtk (char *fname, int *fnum)
|
||||
}
|
||||
}
|
||||
else if (match(nexttok, "s")) {
|
||||
char last[100];
|
||||
char last[MAX_STR_LEN];
|
||||
*last = '\0';
|
||||
if (!CellDefInProgress) {
|
||||
/* fake cell declaration for top-level call */
|
||||
|
||||
+53
-8
@@ -22,6 +22,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#ifdef IBMPC
|
||||
#include <alloc.h>
|
||||
#endif
|
||||
@@ -31,13 +32,13 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#endif
|
||||
|
||||
#include "netgen.h"
|
||||
#include "hash.h"
|
||||
#include "objlist.h"
|
||||
#include "regexp.h"
|
||||
#include "dbug.h"
|
||||
#include "print.h"
|
||||
#include "netfile.h"
|
||||
#include "netcmp.h"
|
||||
#include "hash.h"
|
||||
|
||||
#ifdef TCL_NETGEN
|
||||
extern Tcl_Interp *netgeninterp;
|
||||
@@ -129,6 +130,7 @@ struct property *NewProperty(void)
|
||||
|
||||
kl = (struct property *)CALLOC(1,sizeof(struct property));
|
||||
if (kl == NULL) Fprintf(stderr,"NewProperty: Core allocation error\n");
|
||||
kl->pin = (char *)NULL;
|
||||
return (kl);
|
||||
}
|
||||
|
||||
@@ -288,8 +290,8 @@ static struct hashdict cell_dict;
|
||||
|
||||
void InitCellHashTable(void)
|
||||
{
|
||||
hashfunc = hash;
|
||||
matchfunc = match;
|
||||
hashfunc = hashcase;
|
||||
matchfunc = NULL;
|
||||
matchintfunc = matchfile;
|
||||
InitializeHashTable(&cell_dict, CELLHASHSIZE);
|
||||
}
|
||||
@@ -439,15 +441,32 @@ void RemoveShorted(char *class, int file)
|
||||
RecurseCellFileHashTable(removeshorted, file);
|
||||
}
|
||||
|
||||
/* Remove instances of a deleted class from the database. */
|
||||
/* NOTE: This treats deleted classes as not existing, so it */
|
||||
/* needs to take care of disconnected ports in the same manner */
|
||||
/* as flattenInstancesOf() in disconnecting the port of a */
|
||||
/* parent cell if it connected to nothing other than the */
|
||||
/* deleted instance. */
|
||||
|
||||
int deleteclass(struct hashlist *p, int file)
|
||||
{
|
||||
struct nlist *ptr;
|
||||
struct objlist *ob, *lob, *nob;
|
||||
struct objlist *ob, *lob, *nob, *portnode;
|
||||
unsigned char *checknodes;
|
||||
int i;
|
||||
|
||||
ptr = (struct nlist *)(p->ptr);
|
||||
|
||||
if ((file != -1) && (ptr->file != file)) return 0;
|
||||
|
||||
/* Note: This could be made faster by enumerating all times each
|
||||
* node is used during the full pass, then subtracting each time
|
||||
* the node is deleted in a child, then disconnecting all nodes
|
||||
* that ended up with a zero count.
|
||||
*/
|
||||
checknodes = (unsigned char *)CALLOC(ptr->nodename_cache_maxnodenum + 1,
|
||||
sizeof(unsigned char));
|
||||
|
||||
lob = NULL;
|
||||
for (ob = ptr->cell; ob != NULL;) {
|
||||
nob = ob->next;
|
||||
@@ -455,6 +474,8 @@ int deleteclass(struct hashlist *p, int file)
|
||||
if ((*matchfunc)(ob->model.class, OldCell->name)) {
|
||||
HashDelete(ob->instance.name, &(ptr->instdict));
|
||||
while (1) {
|
||||
if (ob->type >= FIRSTPIN)
|
||||
checknodes[ob->node] = (unsigned char)1;
|
||||
FreeObjectAndHash(ob, ptr);
|
||||
ob = nob;
|
||||
if (ob == NULL) break;
|
||||
@@ -476,6 +497,25 @@ int deleteclass(struct hashlist *p, int file)
|
||||
ob = nob;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i <= ptr->nodename_cache_maxnodenum; i++) {
|
||||
if (checknodes[i] != 0) {
|
||||
portnode = NULL;
|
||||
for (ob = ptr->cell; ob != NULL; ob = ob->next) {
|
||||
if ((ob->type != PORT) && (portnode == NULL))
|
||||
break;
|
||||
else if ((ob->type == PORT) && (ob->node == i))
|
||||
portnode = ob;
|
||||
else if ((ob->type >= FIRSTPIN) && (ob->node == i))
|
||||
break;
|
||||
}
|
||||
if ((ob == NULL) && (portnode != NULL)) {
|
||||
/* Port became disconnected when child was deleted */
|
||||
portnode->node = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
FREE(checknodes);
|
||||
}
|
||||
|
||||
/* Remove all instances of class "class" from the database */
|
||||
@@ -696,7 +736,7 @@ struct nlist *RecurseCellHashTable2(struct nlist *(*foo)(struct hashlist *,
|
||||
|
||||
char *FixTemplate(char *t)
|
||||
{
|
||||
char buffer[200];
|
||||
char buffer[MAX_STR_LEN];
|
||||
char *rstr;
|
||||
int i,j;
|
||||
int InsideBrace;
|
||||
@@ -975,6 +1015,7 @@ struct objlist *CopyObjList(struct objlist *oldlist, unsigned char doforall)
|
||||
newob->model.class = NULL;
|
||||
else
|
||||
newob->model.class = strsave(tmp->model.class);
|
||||
newob->flags = tmp->flags;
|
||||
newob->instance.name = (tmp->instance.name) ?
|
||||
strsave(tmp->instance.name) : NULL;
|
||||
}
|
||||
@@ -1112,13 +1153,17 @@ void FreeObjectAndHash(struct objlist *ob, struct nlist *ptr)
|
||||
|
||||
/*************** GENERAL UTILITIES ****************************/
|
||||
|
||||
int NumberOfPorts(char *cellname)
|
||||
int NumberOfPorts(char *cellname, int file)
|
||||
{
|
||||
struct nlist *tp;
|
||||
struct objlist *ob;
|
||||
int ports;
|
||||
|
||||
tp = LookupCell(cellname);
|
||||
if (file == -1)
|
||||
tp = LookupCell(cellname);
|
||||
else
|
||||
tp = LookupCellFile(cellname, file);
|
||||
|
||||
if (tp == NULL) return(0);
|
||||
ports = 0;
|
||||
for (ob = tp->cell; ob != NULL; ob = ob->next)
|
||||
@@ -1202,7 +1247,7 @@ static char *OldNodeName(struct nlist *tp, int node)
|
||||
struct objlist *firstuniqueglobal;
|
||||
struct objlist *firstglobal;
|
||||
struct objlist *firstpin;
|
||||
static char StrBuffer[100];
|
||||
static char StrBuffer[MAX_STR_LEN];
|
||||
|
||||
#if 0
|
||||
/* make second pass, looking for ports */
|
||||
|
||||
+29
-12
@@ -28,6 +28,8 @@
|
||||
|
||||
#define PROXY (0) /* Used in model.port record of ports */
|
||||
|
||||
#define NO_CONNECT 1 /* Use in object list to flag an isolated net */
|
||||
|
||||
/* Lists of device properties. Order is defined at the time of */
|
||||
/* the cell definition; values are sorted at the time instances */
|
||||
/* are read. */
|
||||
@@ -133,6 +135,7 @@ struct property {
|
||||
unsigned char idx; /* index into valuelist */
|
||||
unsigned char type; /* string, integer, double, value, expression */
|
||||
unsigned char merge; /* how property changes when devices are merged */
|
||||
char *pin; /* associated pin (or NULL if not associated) */
|
||||
union {
|
||||
char *string;
|
||||
double dval;
|
||||
@@ -162,6 +165,7 @@ struct objlist {
|
||||
/* (string) value of property for properties */
|
||||
struct valuelist *props; /* Property record */
|
||||
} instance;
|
||||
unsigned char flags; /* Used by NODE type to flag isolated net */
|
||||
int node; /* the electrical node number of the port/node/pin */
|
||||
struct objlist *next;
|
||||
};
|
||||
@@ -192,9 +196,8 @@ struct Permutation {
|
||||
struct Permutation *next;
|
||||
};
|
||||
|
||||
#define OBJHASHSIZE 997 /* the size of the object and instance hash lists */
|
||||
#define OBJHASHSIZE 42073 /* the size of the object and instance hash lists */
|
||||
/* prime numbers are good choices as hash sizes */
|
||||
/* 101 is a good number for IBMPC */
|
||||
|
||||
/* cell definition for hash table */
|
||||
/* NOTE: "file" must come first for the hash matching by name and file */
|
||||
@@ -204,7 +207,7 @@ struct nlist {
|
||||
char *name;
|
||||
int number; /* number of instances defined */
|
||||
int dumped; /* instance count, and general-purpose marker */
|
||||
unsigned char flags;
|
||||
unsigned short flags;
|
||||
unsigned char class;
|
||||
unsigned long classhash; /* randomized hash value for cell class */
|
||||
struct Permutation *permutes; /* list of permuting pins */
|
||||
@@ -220,17 +223,18 @@ struct nlist {
|
||||
|
||||
/* Defined nlist structure flags */
|
||||
|
||||
#define CELL_MATCHED 0x01 /* cell matched to another */
|
||||
#define CELL_NOCASE 0x02 /* cell is case-insensitive (e.g., SPICE) */
|
||||
#define CELL_TOP 0x04 /* cell is a top-level cell */
|
||||
#define CELL_PLACEHOLDER 0x08 /* cell is a placeholder cell */
|
||||
#define CELL_PROPSMATCHED 0x10 /* properties matched to matching cell */
|
||||
#define CELL_DUPLICATE 0x20 /* cell has a duplicate */
|
||||
#define CELL_MATCHED 0x001 /* cell matched to another */
|
||||
#define CELL_NOCASE 0x002 /* cell is case-insensitive (e.g., SPICE) */
|
||||
#define CELL_TOP 0x004 /* cell is a top-level cell */
|
||||
#define CELL_PLACEHOLDER 0x008 /* cell is a placeholder cell */
|
||||
#define CELL_PROPSMATCHED 0x010 /* properties matched to matching cell */
|
||||
#define CELL_DUPLICATE 0x020 /* cell has a duplicate */
|
||||
#define CELL_VERILOG 0x040 /* cell is verilog module */
|
||||
|
||||
/* Flags for combination allowances and prohibitions */
|
||||
|
||||
#define COMB_SERIES 0x40
|
||||
#define COMB_NO_PARALLEL 0x80
|
||||
#define COMB_SERIES 0x100
|
||||
#define COMB_NO_PARALLEL 0x200
|
||||
|
||||
extern struct nlist *CurrentCell;
|
||||
extern struct objlist *CurrentTail;
|
||||
@@ -242,7 +246,7 @@ extern void FreeObjectAndHash(struct objlist *ob, struct nlist *ptr);
|
||||
extern void FreePorts(char *cellname);
|
||||
extern struct IgnoreList *ClassIgnore;
|
||||
|
||||
extern int NumberOfPorts(char *cellname);
|
||||
extern int NumberOfPorts(char *cellname, int file);
|
||||
extern struct objlist *InstanceNumber(struct nlist *tp, int inst);
|
||||
|
||||
extern struct objlist *List(char *list_template);
|
||||
@@ -310,6 +314,19 @@ extern void GarbageCollect(void);
|
||||
extern void InitGarbageCollection(void);
|
||||
extern void AddToGarbageList(struct objlist *head);
|
||||
|
||||
extern void DeleteProperties(struct keyvalue **topptr);
|
||||
extern void AddProperty(struct keyvalue **topptr, char *key, char *value);
|
||||
extern void AddScaledProperty(struct keyvalue **topptr, char *key, char *value, double scale);
|
||||
extern void DeleteProperties(struct keyvalue **topptr);
|
||||
extern struct objlist *LinkProperties(char *model, struct keyvalue *topptr);
|
||||
|
||||
extern void ClassDelete(char *class, int file);
|
||||
extern void RemoveShorted(char *class, int file);
|
||||
extern void CellRehash(char *name, char *newname, int file);
|
||||
|
||||
/* defined in netgen.c */
|
||||
extern int ConvertStringToInteger(char *string, int *ival);
|
||||
|
||||
#ifdef HAVE_MALLINFO
|
||||
void PrintMemoryStats(void);
|
||||
#endif
|
||||
|
||||
+10
-10
@@ -511,8 +511,8 @@ int OpenEmbeddingFile(char *cellname, char *filename)
|
||||
/* returns 1 if OK */
|
||||
{
|
||||
struct nlist *tp;
|
||||
char outfilename[200];
|
||||
char logfilename[200];
|
||||
char outfilename[MAX_STR_LEN];
|
||||
char logfilename[MAX_STR_LEN];
|
||||
|
||||
tp = LookupCell(cellname);
|
||||
if (tp == NULL) {
|
||||
@@ -783,7 +783,7 @@ void SetupArray(char *prompt1, char *prompt2, char *prompt3, int *data,
|
||||
void (*proc)(void))
|
||||
{
|
||||
int i, oldfanout;
|
||||
char name[100];
|
||||
char name[MAX_STR_LEN];
|
||||
|
||||
Printf(prompt1);
|
||||
for (i = 1; i <= MAX_TREE_DEPTH; i++)
|
||||
@@ -792,7 +792,7 @@ void SetupArray(char *prompt1, char *prompt2, char *prompt3, int *data,
|
||||
|
||||
oldfanout = 1;
|
||||
for (i = 1; i <= MAX_TREE_DEPTH; i++) {
|
||||
char prompt[100];
|
||||
char prompt[MAX_STR_LEN];
|
||||
int newfanout;
|
||||
sprintf(prompt, prompt2, i);
|
||||
promptstring(prompt, name);
|
||||
@@ -822,7 +822,7 @@ void SetupArrayFromString(char *prompt1, char *prompt3, int *data,
|
||||
void (*proc)(void), char *text)
|
||||
{
|
||||
int i, oldfanout, newfanout;
|
||||
char string[100];
|
||||
char string[MAX_STR_LEN];
|
||||
char *ch;
|
||||
char *endch;
|
||||
|
||||
@@ -929,7 +929,7 @@ void ToggleDebug(void)
|
||||
void DescribeCell(char *name, int detail)
|
||||
{
|
||||
Printf("Cell: %s contains %d instances, %d nodes and %d ports\n", name,
|
||||
NumberOfInstances(name), RenumberNodes(name), NumberOfPorts(name));
|
||||
NumberOfInstances(name), RenumberNodes(name), NumberOfPorts(name, -1));
|
||||
PrintEmbeddingTree(stdout,name,detail);
|
||||
}
|
||||
|
||||
@@ -962,7 +962,7 @@ void ProtoPrintParameters(void)
|
||||
void PROTOCHIP(void)
|
||||
/* a simple command interpreter to manage embedding/routing */
|
||||
{
|
||||
char name[100];
|
||||
char name[MAX_STR_LEN];
|
||||
char ch;
|
||||
|
||||
InitializeFanout();
|
||||
@@ -1136,7 +1136,7 @@ void PROTOCHIP(void)
|
||||
|
||||
oldfanout = 1;
|
||||
for (i = 1; i <= MAX_TREE_DEPTH; i++) {
|
||||
char prompt[100];
|
||||
char prompt[MAX_STR_LEN];
|
||||
int newfanout;
|
||||
sprintf(prompt,"Fanout for level %d (0 to quit): ",i);
|
||||
promptstring(prompt, name);
|
||||
@@ -1168,7 +1168,7 @@ void PROTOCHIP(void)
|
||||
|
||||
oldfanout = 1;
|
||||
for (i = 1; i <= MAX_TREE_DEPTH; i++) {
|
||||
char prompt[100];
|
||||
char prompt[MAX_STR_LEN];
|
||||
int newfanout;
|
||||
sprintf(prompt,"Common nodes for level %d (0 to quit): ",i);
|
||||
promptstring(prompt, name);
|
||||
@@ -1200,7 +1200,7 @@ void PROTOCHIP(void)
|
||||
|
||||
oldfanout = 1;
|
||||
for (i = 1; i <= MAX_TREE_DEPTH; i++) {
|
||||
char prompt[100];
|
||||
char prompt[MAX_STR_LEN];
|
||||
int newfanout;
|
||||
sprintf(prompt,"Used leaves for level %d (0 to quit): ",i);
|
||||
promptstring(prompt, name);
|
||||
|
||||
+3
-3
@@ -37,7 +37,7 @@ extern int ColumnBase;
|
||||
|
||||
struct filestr {
|
||||
FILE *f;
|
||||
char buffer[200];
|
||||
char buffer[MAX_STR_LEN];
|
||||
int wrap; /* column to wrap around in, or 0 if no wrap */
|
||||
} file_buffers[MAXFILES];
|
||||
|
||||
@@ -107,7 +107,7 @@ void Fprintf(FILE *f, char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int FileIndex;
|
||||
char tmpstr[200];
|
||||
char tmpstr[MAX_STR_LEN];
|
||||
int bufferlongenough;
|
||||
int linewrapexceeded;
|
||||
|
||||
@@ -203,7 +203,7 @@ void Printf(char *format, ...)
|
||||
void Printf(char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char tmpstr[200];
|
||||
char tmpstr[MAX_STR_LEN];
|
||||
|
||||
va_start(ap, format);
|
||||
vsprintf(tmpstr, format, ap);
|
||||
|
||||
+21
-11
@@ -52,7 +52,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
/*************************************************************************/
|
||||
|
||||
static int SuppressPrompts = 0;
|
||||
static char InputLine[200];
|
||||
static char InputLine[MAX_STR_LEN];
|
||||
|
||||
void typeahead(char *str)
|
||||
{
|
||||
@@ -73,7 +73,7 @@ but reads from 'promptstring_infile' if nec. */
|
||||
/* If interactive, puts out 'prompt' */
|
||||
{
|
||||
char *nexttok;
|
||||
char tmpstr[200];
|
||||
char tmpstr[MAX_STR_LEN];
|
||||
int echo;
|
||||
|
||||
if (promptstring_infile == NULL)
|
||||
@@ -801,9 +801,19 @@ void DescribeInstance(char *name, int file)
|
||||
{
|
||||
if (ob->node > nodemax) nodemax = ob->node;
|
||||
else if ((ob->node == -1) && (ob->model.port != PROXY)) {
|
||||
if (disconnectednodes == 0) Fprintf(stderr, "\n");
|
||||
disconnectednodes++;
|
||||
Fprintf(stderr, "Cell %s disconnected node: %s\n", tp->name, ob->name);
|
||||
|
||||
/* All black-box modules and placeholders by definition have all */
|
||||
/* disconnected pins, so don't report those. */
|
||||
|
||||
if ((!(tp->flags & CELL_PLACEHOLDER)) && (tp->class != CLASS_MODULE)) {
|
||||
// if (disconnectednodes == 0) Fprintf(stderr, "\n");
|
||||
disconnectednodes++;
|
||||
/* Don't report on ports marked "port_match_error", which is just confusing. */
|
||||
if (strcmp(ob->name, "port_match_error")) {
|
||||
Fprintf(stderr, "Cell %s (%d) disconnected node: %s\n",
|
||||
tp->name, tp->file, ob->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
instlist = (unsigned char *) CALLOC((nodemax + 1), sizeof(unsigned char));
|
||||
@@ -900,7 +910,7 @@ void PrintLeavesInCell(char *cellname, int filenum)
|
||||
np->dumped = 1;
|
||||
|
||||
if (np->class != CLASS_SUBCKT) {
|
||||
Printf("%s; %d ports; Primitive.\n", cellname, NumberOfPorts(cellname));
|
||||
Printf("%s; %d ports; Primitive.\n", cellname, NumberOfPorts(cellname, filenum));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -913,7 +923,7 @@ void PrintLeavesInCell(char *cellname, int filenum)
|
||||
am_a_leaf = 0;
|
||||
}
|
||||
|
||||
if (am_a_leaf) Printf("%s; %d ports\n", cellname, NumberOfPorts(cellname));
|
||||
if (am_a_leaf) Printf("%s; %d ports\n", cellname, NumberOfPorts(cellname, filenum));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -949,8 +959,8 @@ void Query(void)
|
||||
{
|
||||
/* little interactive debugger */
|
||||
char reply;
|
||||
char repstr[100];
|
||||
char repstr2[100];
|
||||
char repstr[MAX_STR_LEN];
|
||||
char repstr2[MAX_STR_LEN];
|
||||
float StartTime; /* for elapsed CPU times */
|
||||
int Timing; /* if true, print times of each command */
|
||||
int filenum = -1;
|
||||
@@ -1026,7 +1036,7 @@ void Query(void)
|
||||
break;
|
||||
case 'v':
|
||||
promptstring("Write Verilog: circuit name: ", repstr);
|
||||
VerilogModule(repstr, filenum, "");
|
||||
VerilogTop(repstr, filenum, "");
|
||||
break;
|
||||
case 'E':
|
||||
promptstring("Write ESACAP: circuit name: ", repstr);
|
||||
@@ -1063,7 +1073,7 @@ void Query(void)
|
||||
ActelLib();
|
||||
break;
|
||||
case 'S':
|
||||
promptstring("Read SPICE (.ckt) file? ", repstr);
|
||||
promptstring("Read SPICE (.spice) file? ", repstr);
|
||||
ReadSpice(repstr, &filenum);
|
||||
break;
|
||||
case 'V':
|
||||
|
||||
+181
-131
@@ -26,6 +26,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#endif
|
||||
|
||||
#include <stdlib.h> /* for calloc(), free(), getenv() */
|
||||
#include <ctype.h> /* for toupper(), isascii() */
|
||||
#ifndef IBMPC
|
||||
#include <sys/types.h> /* for getpwnam() tilde expansion */
|
||||
#include <pwd.h>
|
||||
@@ -40,6 +41,8 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include "objlist.h"
|
||||
#include "netfile.h"
|
||||
#include "print.h"
|
||||
#include "query.h"
|
||||
#include "objlist.h"
|
||||
|
||||
// Global storage for parameters from .PARAM
|
||||
struct hashdict spiceparams;
|
||||
@@ -473,15 +476,6 @@ void CleanupSubcell() {
|
||||
SetClass(CLASS_MODULE);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
/* Structure for stacking nested subcircuit definitions */
|
||||
/*------------------------------------------------------*/
|
||||
|
||||
struct cellstack {
|
||||
char *cellname;
|
||||
struct cellstack *next;
|
||||
};
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
/* Push a subcircuit name onto the stack */
|
||||
/*------------------------------------------------------*/
|
||||
@@ -524,13 +518,13 @@ void ReadSpiceFile(char *fname, int filenum, struct cellstack **CellStackPtr,
|
||||
int warnings = 0, update = 0, hasports = 0;
|
||||
char *eqptr, devtype, in_subckt;
|
||||
struct keyvalue *kvlist = NULL;
|
||||
char inst[256], model[256], instname[256];
|
||||
char inst[MAX_STR_LEN], model[MAX_STR_LEN], instname[MAX_STR_LEN];
|
||||
struct nlist *tp;
|
||||
struct objlist *parent, *sobj, *nobj, *lobj, *pobj;
|
||||
|
||||
inst[255] = '\0';
|
||||
model[255] = '\0';
|
||||
instname[255] = '\0';
|
||||
inst[MAX_STR_LEN-1] = '\0';
|
||||
model[MAX_STR_LEN-1] = '\0';
|
||||
instname[MAX_STR_LEN-1] = '\0';
|
||||
in_subckt = (char)0;
|
||||
|
||||
while (!EndParseFile()) {
|
||||
@@ -561,7 +555,7 @@ void ReadSpiceFile(char *fname, int filenum, struct cellstack **CellStackPtr,
|
||||
|
||||
/* Check for existence of the cell. We may need to rename it. */
|
||||
|
||||
snprintf(model, 99, "%s", nexttok);
|
||||
snprintf(model, MAX_STR_LEN-1, "%s", nexttok);
|
||||
tp = LookupCellFile(nexttok, filenum);
|
||||
|
||||
/* Check for name conflict with duplicate cell names */
|
||||
@@ -709,7 +703,7 @@ skip_ends:
|
||||
|
||||
SpiceTokNoNewline();
|
||||
if (nexttok == NULL) continue; /* Ignore if no model name */
|
||||
snprintf(model, 99, "%s", nexttok);
|
||||
snprintf(model, MAX_STR_LEN-1, "%s", nexttok);
|
||||
SpiceTokNoNewline();
|
||||
if (nexttok == NULL) goto baddevice;
|
||||
|
||||
@@ -874,6 +868,17 @@ skip_ends:
|
||||
}
|
||||
}
|
||||
|
||||
/* Ignore anything in a .CONTROL ... .ENDC block */
|
||||
else if (matchnocase(nexttok, ".CONTROL")) {
|
||||
while (1) {
|
||||
SpiceSkipNewLine();
|
||||
SkipTok(NULL);
|
||||
if (EndParseFile()) break;
|
||||
if (matchnocase(nexttok, ".ENDC"))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Blackbox (library) mode---parse only subcircuits and models;
|
||||
// ignore all components.
|
||||
|
||||
@@ -882,29 +887,29 @@ skip_ends:
|
||||
}
|
||||
|
||||
else if (toupper(nexttok[0]) == 'Q') {
|
||||
char emitter[100], base[100], collector[100];
|
||||
emitter[99] = '\0';
|
||||
base[99] = '\0';
|
||||
collector[99] = '\0';
|
||||
char emitter[MAX_STR_LEN], base[MAX_STR_LEN], collector[MAX_STR_LEN];
|
||||
emitter[MAX_STR_LEN-1] = '\0';
|
||||
base[MAX_STR_LEN-1] = '\0';
|
||||
collector[MAX_STR_LEN-1] = '\0';
|
||||
|
||||
if (!(*CellStackPtr)) {
|
||||
CellDef(fname, filenum);
|
||||
PushStack(fname, CellStackPtr);
|
||||
}
|
||||
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
|
||||
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
if (nexttok == NULL) goto baddevice;
|
||||
strncpy(collector, nexttok, 99); SpiceTokNoNewline();
|
||||
strncpy(collector, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
if (nexttok == NULL) goto baddevice;
|
||||
strncpy(base, nexttok, 99); SpiceTokNoNewline();
|
||||
strncpy(base, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
if (nexttok == NULL) goto baddevice;
|
||||
strncpy(emitter, nexttok, 99); SpiceTokNoNewline();
|
||||
strncpy(emitter, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
/* make sure all the nodes exist */
|
||||
if (LookupObject(collector, CurrentCell) == NULL) Node(collector);
|
||||
if (LookupObject(base, CurrentCell) == NULL) Node(base);
|
||||
if (LookupObject(emitter, CurrentCell) == NULL) Node(emitter);
|
||||
|
||||
/* Read the device model */
|
||||
snprintf(model, 99, "%s", nexttok);
|
||||
snprintf(model, MAX_STR_LEN-1, "%s", nexttok);
|
||||
|
||||
while (nexttok != NULL)
|
||||
{
|
||||
@@ -935,30 +940,30 @@ skip_ends:
|
||||
goto baddevice;
|
||||
}
|
||||
|
||||
snprintf(instname, 255, "%s%s", model, inst);
|
||||
snprintf(instname, MAX_STR_LEN-1, "%s:%s", model, inst);
|
||||
Cell(instname, model, collector, base, emitter);
|
||||
pobj = LinkProperties(model, kvlist);
|
||||
ReduceExpressions(pobj, NULL, CurrentCell, TRUE);
|
||||
DeleteProperties(&kvlist);
|
||||
}
|
||||
else if (toupper(nexttok[0]) == 'M') {
|
||||
char drain[100], gate[100], source[100], bulk[100];
|
||||
drain[99] = '\0';
|
||||
gate[99] = '\0';
|
||||
source[99] = '\0';
|
||||
bulk[99] = '\0';
|
||||
char drain[MAX_STR_LEN], gate[MAX_STR_LEN], source[MAX_STR_LEN], bulk[MAX_STR_LEN];
|
||||
drain[MAX_STR_LEN-1] = '\0';
|
||||
gate[MAX_STR_LEN-1] = '\0';
|
||||
source[MAX_STR_LEN-1] = '\0';
|
||||
bulk[MAX_STR_LEN-1] = '\0';
|
||||
|
||||
if (!(*CellStackPtr)) {
|
||||
CellDef(fname, filenum);
|
||||
PushStack(fname, CellStackPtr);
|
||||
}
|
||||
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
|
||||
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
if (nexttok == NULL) goto baddevice;
|
||||
strncpy(drain, nexttok, 99); SpiceTokNoNewline();
|
||||
strncpy(drain, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
if (nexttok == NULL) goto baddevice;
|
||||
strncpy(gate, nexttok, 99); SpiceTokNoNewline();
|
||||
strncpy(gate, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
if (nexttok == NULL) goto baddevice;
|
||||
strncpy(source, nexttok, 99); SpiceTokNoNewline();
|
||||
strncpy(source, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
if (nexttok == NULL) goto baddevice;
|
||||
/* make sure all the nodes exist */
|
||||
if (LookupObject(drain, CurrentCell) == NULL) Node(drain);
|
||||
@@ -966,11 +971,11 @@ skip_ends:
|
||||
if (LookupObject(source, CurrentCell) == NULL) Node(source);
|
||||
|
||||
/* handle the substrate node */
|
||||
strncpy(bulk, nexttok, 99); SpiceTokNoNewline();
|
||||
strncpy(bulk, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
if (LookupObject(bulk, CurrentCell) == NULL) Node(bulk);
|
||||
|
||||
/* Read the device model */
|
||||
snprintf(model, 99, "%s", nexttok);
|
||||
snprintf(model, MAX_STR_LEN-1, "%s", nexttok);
|
||||
|
||||
while (nexttok != NULL)
|
||||
{
|
||||
@@ -1008,7 +1013,7 @@ skip_ends:
|
||||
goto baddevice;
|
||||
}
|
||||
|
||||
snprintf(instname, 255, "%s%s", model, inst);
|
||||
snprintf(instname, MAX_STR_LEN-1, "%s:%s", model, inst);
|
||||
Cell(instname, model, drain, gate, source, bulk);
|
||||
pobj = LinkProperties(model, kvlist);
|
||||
ReduceExpressions(pobj, NULL, CurrentCell, TRUE);
|
||||
@@ -1022,19 +1027,19 @@ skip_ends:
|
||||
SpiceSkipNewLine();
|
||||
}
|
||||
else {
|
||||
char ctop[100], cbot[100];
|
||||
ctop[99] = '\0';
|
||||
cbot[99] = '\0';
|
||||
char ctop[MAX_STR_LEN], cbot[MAX_STR_LEN];
|
||||
ctop[MAX_STR_LEN-1] = '\0';
|
||||
cbot[MAX_STR_LEN-1] = '\0';
|
||||
|
||||
if (!(*CellStackPtr)) {
|
||||
CellDef(fname, filenum);
|
||||
PushStack(fname, CellStackPtr);
|
||||
}
|
||||
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
|
||||
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
if (nexttok == NULL) goto baddevice;
|
||||
strncpy(ctop, nexttok, 99); SpiceTokNoNewline();
|
||||
strncpy(ctop, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
if (nexttok == NULL) goto baddevice;
|
||||
strncpy(cbot, nexttok, 99); SpiceTokNoNewline();
|
||||
strncpy(cbot, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
|
||||
/* make sure all the nodes exist */
|
||||
if (LookupObject(ctop, CurrentCell) == NULL) Node(ctop);
|
||||
@@ -1053,7 +1058,7 @@ skip_ends:
|
||||
|
||||
model[0] = '\0';
|
||||
if ((nexttok != NULL) && ((eqptr = strchr(nexttok, '=')) == NULL))
|
||||
snprintf(model, 99, "%s", nexttok);
|
||||
snprintf(model, MAX_STR_LEN-1, "%s", nexttok);
|
||||
|
||||
/* Any other device properties? */
|
||||
while (nexttok != NULL)
|
||||
@@ -1066,7 +1071,7 @@ skip_ends:
|
||||
}
|
||||
else if (!strncmp(nexttok, "$[", 2)) {
|
||||
// Support for CDL modeled capacitor format
|
||||
snprintf(model, 99, "%s", nexttok + 2);
|
||||
snprintf(model, MAX_STR_LEN-1, "%s", nexttok + 2);
|
||||
if ((eqptr = strchr(model, ']')) != NULL)
|
||||
*eqptr = '\0';
|
||||
}
|
||||
@@ -1099,7 +1104,7 @@ skip_ends:
|
||||
usemodel = 1;
|
||||
}
|
||||
|
||||
snprintf(instname, 255, "%s%s", model, inst);
|
||||
snprintf(instname, MAX_STR_LEN-1, "%s:%s", model, inst);
|
||||
if (usemodel)
|
||||
Cell(instname, model, ctop, cbot);
|
||||
else
|
||||
@@ -1116,19 +1121,19 @@ skip_ends:
|
||||
SpiceSkipNewLine();
|
||||
}
|
||||
else {
|
||||
char rtop[100], rbot[100];
|
||||
rtop[99] = '\0';
|
||||
rbot[99] = '\0';
|
||||
char rtop[MAX_STR_LEN], rbot[MAX_STR_LEN];
|
||||
rtop[MAX_STR_LEN-1] = '\0';
|
||||
rbot[MAX_STR_LEN-1] = '\0';
|
||||
|
||||
if (!(*CellStackPtr)) {
|
||||
CellDef(fname, filenum);
|
||||
PushStack(fname, CellStackPtr);
|
||||
}
|
||||
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
|
||||
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
if (nexttok == NULL) goto baddevice;
|
||||
strncpy(rtop, nexttok, 99); SpiceTokNoNewline();
|
||||
strncpy(rtop, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
if (nexttok == NULL) goto baddevice;
|
||||
strncpy(rbot, nexttok, 99); SpiceTokNoNewline();
|
||||
strncpy(rbot, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
/* make sure all the nodes exist */
|
||||
if (LookupObject(rtop, CurrentCell) == NULL) Node(rtop);
|
||||
if (LookupObject(rbot, CurrentCell) == NULL) Node(rbot);
|
||||
@@ -1147,7 +1152,7 @@ skip_ends:
|
||||
|
||||
model[0] = '\0';
|
||||
if ((nexttok != NULL) && ((eqptr = strchr(nexttok, '=')) == NULL))
|
||||
snprintf(model, 99, "%s", nexttok);
|
||||
snprintf(model, MAX_STR_LEN-1, "%s", nexttok);
|
||||
|
||||
/* Any other device properties? */
|
||||
while (nexttok != NULL) {
|
||||
@@ -1159,7 +1164,7 @@ skip_ends:
|
||||
}
|
||||
else if (!strncmp(nexttok, "$[", 2)) {
|
||||
// Support for CDL modeled resistor format
|
||||
snprintf(model, 99, "%s", nexttok + 2);
|
||||
snprintf(model, MAX_STR_LEN-1, "%s", nexttok + 2);
|
||||
if ((eqptr = strchr(model, ']')) != NULL)
|
||||
*eqptr = '\0';
|
||||
}
|
||||
@@ -1184,7 +1189,7 @@ skip_ends:
|
||||
else if (CountPorts(model, filenum) != 2) {
|
||||
/* Modeled device: Make sure it has the right number of ports */
|
||||
Fprintf(stderr, "Device \"%s\" has wrong number of ports for a "
|
||||
"resistor.\n");
|
||||
"resistor.\n", model);
|
||||
goto baddevice;
|
||||
}
|
||||
usemodel = 1;
|
||||
@@ -1192,7 +1197,7 @@ skip_ends:
|
||||
else
|
||||
strcpy(model, "r"); /* Use default resistor model */
|
||||
|
||||
snprintf(instname, 255, "%s%s", model, inst);
|
||||
snprintf(instname, MAX_STR_LEN-1, "%s:%s", model, inst);
|
||||
if (usemodel)
|
||||
Cell(instname, model, rtop, rbot);
|
||||
else
|
||||
@@ -1203,25 +1208,25 @@ skip_ends:
|
||||
}
|
||||
}
|
||||
else if (toupper(nexttok[0]) == 'D') { /* diode */
|
||||
char cathode[100], anode[100];
|
||||
cathode[99] = '\0';
|
||||
anode[99] = '\0';
|
||||
char cathode[MAX_STR_LEN], anode[MAX_STR_LEN];
|
||||
cathode[MAX_STR_LEN-1] = '\0';
|
||||
anode[MAX_STR_LEN-1] = '\0';
|
||||
|
||||
if (!(*CellStackPtr)) {
|
||||
CellDef(fname, filenum);
|
||||
PushStack(fname, CellStackPtr);
|
||||
}
|
||||
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
|
||||
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
if (nexttok == NULL) goto baddevice;
|
||||
strncpy(anode, nexttok, 99); SpiceTokNoNewline();
|
||||
strncpy(anode, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
if (nexttok == NULL) goto baddevice;
|
||||
strncpy(cathode, nexttok, 99); SpiceTokNoNewline();
|
||||
strncpy(cathode, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
/* make sure all the nodes exist */
|
||||
if (LookupObject(anode, CurrentCell) == NULL) Node(anode);
|
||||
if (LookupObject(cathode, CurrentCell) == NULL) Node(cathode);
|
||||
|
||||
/* Read the device model */
|
||||
snprintf(model, 99, "%s", nexttok);
|
||||
snprintf(model, MAX_STR_LEN-1, "%s", nexttok);
|
||||
|
||||
while (nexttok != NULL)
|
||||
{
|
||||
@@ -1250,7 +1255,7 @@ skip_ends:
|
||||
Fprintf(stderr, "Device \"%s\" has wrong number of ports for a diode.\n");
|
||||
goto baddevice;
|
||||
}
|
||||
snprintf(instname, 255, "%s%s", model, inst);
|
||||
snprintf(instname, MAX_STR_LEN-1, "%s:%s", model, inst);
|
||||
Cell(instname, model, anode, cathode);
|
||||
pobj = LinkProperties(model, kvlist);
|
||||
ReduceExpressions(pobj, NULL, CurrentCell, TRUE);
|
||||
@@ -1263,25 +1268,25 @@ skip_ends:
|
||||
SpiceSkipNewLine();
|
||||
}
|
||||
else {
|
||||
char node1[100], node2[100], node3[100], node4[100];
|
||||
node1[99] = '\0';
|
||||
node2[99] = '\0';
|
||||
node3[99] = '\0';
|
||||
node4[99] = '\0';
|
||||
char node1[MAX_STR_LEN], node2[MAX_STR_LEN], node3[MAX_STR_LEN], node4[MAX_STR_LEN];
|
||||
node1[MAX_STR_LEN-1] = '\0';
|
||||
node2[MAX_STR_LEN-1] = '\0';
|
||||
node3[MAX_STR_LEN-1] = '\0';
|
||||
node4[MAX_STR_LEN-1] = '\0';
|
||||
|
||||
if (!(*CellStackPtr)) {
|
||||
CellDef(fname, filenum);
|
||||
PushStack(fname, CellStackPtr);
|
||||
}
|
||||
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
|
||||
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
if (nexttok == NULL) goto baddevice;
|
||||
strncpy(node1, nexttok, 99); SpiceTokNoNewline();
|
||||
strncpy(node1, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
if (nexttok == NULL) goto baddevice;
|
||||
strncpy(node2, nexttok, 99); SpiceTokNoNewline();
|
||||
strncpy(node2, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
if (nexttok == NULL) goto baddevice;
|
||||
strncpy(node3, nexttok, 99); SpiceTokNoNewline();
|
||||
strncpy(node3, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
if (nexttok == NULL) goto baddevice;
|
||||
strncpy(node4, nexttok, 99); SpiceTokNoNewline();
|
||||
strncpy(node4, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
/* make sure all the nodes exist */
|
||||
if (LookupObject(node1, CurrentCell) == NULL) Node(node1);
|
||||
if (LookupObject(node2, CurrentCell) == NULL) Node(node2);
|
||||
@@ -1293,7 +1298,7 @@ skip_ends:
|
||||
|
||||
model[0] = '\0';
|
||||
if ((nexttok != NULL) && ((eqptr = strchr(nexttok, '=')) == NULL))
|
||||
snprintf(model, 99, "%s", nexttok);
|
||||
snprintf(model, MAX_STR_LEN-1, "%s", nexttok);
|
||||
|
||||
/* Any other device properties? */
|
||||
while (nexttok != NULL) {
|
||||
@@ -1329,7 +1334,7 @@ skip_ends:
|
||||
else
|
||||
strcpy(model, "t"); /* Use default xline model */
|
||||
|
||||
snprintf(instname, 255, "%s%s", model, inst);
|
||||
snprintf(instname, MAX_STR_LEN-1, "%s:%s", model, inst);
|
||||
|
||||
if (usemodel)
|
||||
Cell(instname, model, node1, node2, node3, node4);
|
||||
@@ -1342,20 +1347,20 @@ skip_ends:
|
||||
}
|
||||
}
|
||||
else if (toupper(nexttok[0]) == 'L') { /* inductor */
|
||||
char end_a[100], end_b[100];
|
||||
char end_a[MAX_STR_LEN], end_b[MAX_STR_LEN];
|
||||
int usemodel = 0;
|
||||
end_a[99] = '\0';
|
||||
end_b[99] = '\0';
|
||||
end_a[MAX_STR_LEN-1] = '\0';
|
||||
end_b[MAX_STR_LEN-1] = '\0';
|
||||
|
||||
if (!(*CellStackPtr)) {
|
||||
CellDef(fname, filenum);
|
||||
PushStack(fname, CellStackPtr);
|
||||
}
|
||||
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
|
||||
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
if (nexttok == NULL) goto baddevice;
|
||||
strncpy(end_a, nexttok, 99); SpiceTokNoNewline();
|
||||
strncpy(end_a, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
if (nexttok == NULL) goto baddevice;
|
||||
strncpy(end_b, nexttok, 99); SpiceTokNoNewline();
|
||||
strncpy(end_b, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
/* make sure all the nodes exist */
|
||||
if (LookupObject(end_a, CurrentCell) == NULL) Node(end_a);
|
||||
if (LookupObject(end_b, CurrentCell) == NULL) Node(end_b);
|
||||
@@ -1374,7 +1379,7 @@ skip_ends:
|
||||
|
||||
model[0] = '\0';
|
||||
if ((nexttok != NULL) && ((eqptr = strchr(nexttok, '=')) == NULL))
|
||||
snprintf(model, 99, "%s", nexttok);
|
||||
snprintf(model, MAX_STR_LEN-1, "%s", nexttok);
|
||||
|
||||
/* Any other device properties? */
|
||||
while (nexttok != NULL)
|
||||
@@ -1412,7 +1417,7 @@ skip_ends:
|
||||
else
|
||||
strcpy(model, "l"); /* Use default inductor model */
|
||||
|
||||
snprintf(instname, 255, "%s%s", model, inst);
|
||||
snprintf(instname, MAX_STR_LEN-1, "%s:%s", model, inst);
|
||||
if (usemodel)
|
||||
Cell(instname, model, end_a, end_b);
|
||||
else
|
||||
@@ -1426,25 +1431,38 @@ skip_ends:
|
||||
/* black-box subcircuits (class MODULE): V, I, E */
|
||||
|
||||
else if (toupper(nexttok[0]) == 'V') { /* voltage source */
|
||||
char pos[100], neg[100];
|
||||
pos[99] = '\0';
|
||||
neg[99] = '\0';
|
||||
char pos[MAX_STR_LEN], neg[MAX_STR_LEN];
|
||||
pos[MAX_STR_LEN-1] = '\0';
|
||||
neg[MAX_STR_LEN-1] = '\0';
|
||||
|
||||
if (!(*CellStackPtr)) {
|
||||
CellDef(fname, filenum);
|
||||
PushStack(fname, CellStackPtr);
|
||||
}
|
||||
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
|
||||
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
if (nexttok == NULL) goto baddevice;
|
||||
strncpy(pos, nexttok, 99); SpiceTokNoNewline();
|
||||
strncpy(pos, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
if (nexttok == NULL) goto baddevice;
|
||||
strncpy(neg, nexttok, 99); SpiceTokNoNewline();
|
||||
strncpy(neg, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
if (nexttok == NULL) goto baddevice;
|
||||
/* make sure all the nodes exist */
|
||||
if (LookupObject(pos, CurrentCell) == NULL) Node(pos);
|
||||
if (LookupObject(neg, CurrentCell) == NULL) Node(neg);
|
||||
|
||||
/* Any device properties? */
|
||||
/* Get voltage value (if present); save as property "value" */
|
||||
|
||||
if (nexttok != NULL) {
|
||||
if (matchnocase(nexttok, "DC")) {
|
||||
SpiceTokNoNewline();
|
||||
}
|
||||
}
|
||||
if (nexttok != NULL) {
|
||||
if (StringIsValueOrExpression(nexttok)) {
|
||||
AddProperty(&kvlist, "value", nexttok);
|
||||
}
|
||||
}
|
||||
|
||||
/* Any other device properties? */
|
||||
while (nexttok != NULL)
|
||||
{
|
||||
SpiceTokNoNewline();
|
||||
@@ -1472,7 +1490,7 @@ skip_ends:
|
||||
else if (CountPorts(model, filenum) != 2) {
|
||||
/* Modeled device: Make sure it has the right number of ports */
|
||||
Fprintf(stderr, "Device \"%s\" has wrong number of ports for a "
|
||||
"voltage source.\n");
|
||||
"voltage source.\n", inst);
|
||||
goto baddevice;
|
||||
}
|
||||
Cell(instname, model, pos, neg);
|
||||
@@ -1481,19 +1499,19 @@ skip_ends:
|
||||
DeleteProperties(&kvlist);
|
||||
}
|
||||
else if (toupper(nexttok[0]) == 'I') { /* current source */
|
||||
char pos[100], neg[100];
|
||||
pos[99] = '\0';
|
||||
neg[99] = '\0';
|
||||
char pos[MAX_STR_LEN], neg[MAX_STR_LEN];
|
||||
pos[MAX_STR_LEN-1] = '\0';
|
||||
neg[MAX_STR_LEN-1] = '\0';
|
||||
|
||||
if (!(*CellStackPtr)) {
|
||||
CellDef(fname, filenum);
|
||||
PushStack(fname, CellStackPtr);
|
||||
}
|
||||
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
|
||||
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
if (nexttok == NULL) goto baddevice;
|
||||
strncpy(pos, nexttok, 99); SpiceTokNoNewline();
|
||||
strncpy(pos, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
if (nexttok == NULL) goto baddevice;
|
||||
strncpy(neg, nexttok, 99); SpiceTokNoNewline();
|
||||
strncpy(neg, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
/* make sure all the nodes exist */
|
||||
if (LookupObject(pos, CurrentCell) == NULL) Node(pos);
|
||||
if (LookupObject(neg, CurrentCell) == NULL) Node(neg);
|
||||
@@ -1535,25 +1553,25 @@ skip_ends:
|
||||
DeleteProperties(&kvlist);
|
||||
}
|
||||
else if (toupper(nexttok[0]) == 'E') { /* controlled voltage source */
|
||||
char pos[100], neg[100], ctrlp[100], ctrln[100];
|
||||
pos[99] = '\0';
|
||||
neg[99] = '\0';
|
||||
ctrlp[99] = '\0';
|
||||
ctrln[99] = '\0';
|
||||
char pos[MAX_STR_LEN], neg[MAX_STR_LEN], ctrlp[MAX_STR_LEN], ctrln[MAX_STR_LEN];
|
||||
pos[MAX_STR_LEN-1] = '\0';
|
||||
neg[MAX_STR_LEN-1] = '\0';
|
||||
ctrlp[MAX_STR_LEN-1] = '\0';
|
||||
ctrln[MAX_STR_LEN-1] = '\0';
|
||||
|
||||
if (!(*CellStackPtr)) {
|
||||
CellDef(fname, filenum);
|
||||
PushStack(fname, CellStackPtr);
|
||||
}
|
||||
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
|
||||
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
if (nexttok == NULL) goto baddevice;
|
||||
strncpy(pos, nexttok, 99); SpiceTokNoNewline();
|
||||
strncpy(pos, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
if (nexttok == NULL) goto baddevice;
|
||||
strncpy(neg, nexttok, 99); SpiceTokNoNewline();
|
||||
strncpy(neg, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
if (nexttok == NULL) goto baddevice;
|
||||
strncpy(ctrlp, nexttok, 99); SpiceTokNoNewline();
|
||||
strncpy(ctrlp, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
if (nexttok == NULL) goto baddevice;
|
||||
strncpy(ctrln, nexttok, 99); SpiceTokNoNewline();
|
||||
strncpy(ctrln, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
|
||||
|
||||
/* make sure all the nodes exist */
|
||||
if (LookupObject(pos, CurrentCell) == NULL) Node(pos);
|
||||
@@ -1601,11 +1619,11 @@ skip_ends:
|
||||
}
|
||||
|
||||
else if (toupper(nexttok[0]) == 'X') { /* subcircuit instances */
|
||||
char instancename[100], subcktname[100];
|
||||
char instancename[MAX_STR_LEN], subcktname[MAX_STR_LEN];
|
||||
int itype, in_props;
|
||||
|
||||
instancename[99] = '\0';
|
||||
subcktname[99] = '\0';
|
||||
instancename[MAX_STR_LEN-1] = '\0';
|
||||
subcktname[MAX_STR_LEN-1] = '\0';
|
||||
|
||||
struct portelement {
|
||||
char *name;
|
||||
@@ -1615,8 +1633,8 @@ skip_ends:
|
||||
struct portelement *head, *tail, *scan, *scannext;
|
||||
struct objlist *obptr;
|
||||
|
||||
snprintf(instancename, 99, "%s", nexttok + 1);
|
||||
strncpy(instancename, nexttok + 1, 99);
|
||||
snprintf(instancename, MAX_STR_LEN-1, "%s", nexttok + 1);
|
||||
strncpy(instancename, nexttok + 1, MAX_STR_LEN-1);
|
||||
if (!(*CellStackPtr)) {
|
||||
CellDef(fname, filenum);
|
||||
PushStack(fname, CellStackPtr);
|
||||
@@ -1724,14 +1742,14 @@ skip_ends:
|
||||
/* names. */
|
||||
|
||||
if (strncmp(instancename, scan->name, strlen(scan->name))) {
|
||||
snprintf(subcktname, 99, "%s%s", scan->name, instancename);
|
||||
snprintf(subcktname, MAX_STR_LEN-1, "%s:%s", scan->name, instancename);
|
||||
strcpy(instancename, subcktname);
|
||||
}
|
||||
else {
|
||||
snprintf(subcktname, 99, "/%s", instancename);
|
||||
snprintf(subcktname, MAX_STR_LEN-1, "/%s", instancename);
|
||||
strcpy(instancename, subcktname);
|
||||
}
|
||||
snprintf(subcktname, 99, "%s", scan->name);
|
||||
snprintf(subcktname, MAX_STR_LEN-1, "%s", scan->name);
|
||||
|
||||
if (scan == head) {
|
||||
head = NULL;
|
||||
@@ -1765,6 +1783,18 @@ skip_ends:
|
||||
ReopenCellDef((*CellStackPtr)->cellname, filenum); /* Reopen */
|
||||
update = 1;
|
||||
}
|
||||
else if (tp->flags & CELL_VERILOG) {
|
||||
if (tp->flags & CELL_PLACEHOLDER) {
|
||||
/* Flag this as an error. To do: Rearrange the verilog instance pins to */
|
||||
/* match the SPICE subcircuit pin order. */
|
||||
Fprintf(stderr, "Error: SPICE subcircuit %s should be read before verilog "
|
||||
"module using it, or pins may not match!\n", subcktname);
|
||||
}
|
||||
else {
|
||||
Fprintf(stderr, "Error: SPICE subcircuit %s redefines a verilog module!\n",
|
||||
subcktname);
|
||||
}
|
||||
}
|
||||
|
||||
/* nexttok is now NULL, scan->name points to class */
|
||||
|
||||
@@ -1883,20 +1913,36 @@ char *ReadSpiceTop(char *fname, int *fnum, int blackbox)
|
||||
CurrentCell = NULL;
|
||||
|
||||
if ((filenum = OpenParseFile(fname, *fnum)) < 0) {
|
||||
char name[100];
|
||||
|
||||
SetExtension(name, fname, SPICE_EXTENSION);
|
||||
if ((filenum = OpenParseFile(name, *fnum)) < 0) {
|
||||
Fprintf(stderr,"Error in SPICE file read: No file %s\n",name);
|
||||
if (strrchr(fname, '.') == NULL) {
|
||||
char name[1024];
|
||||
SetExtension(name, fname, SPICE_EXTENSION);
|
||||
if ((filenum = OpenParseFile(name, *fnum)) < 0) {
|
||||
Fprintf(stderr, "Error in SPICE file read: No file %s\n", name);
|
||||
*fnum = filenum;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Fprintf(stderr, "Error in SPICE file read: No file %s\n", fname);
|
||||
*fnum = filenum;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure all SPICE file reading is case insensitive */
|
||||
matchfunc = matchnocase;
|
||||
matchintfunc = matchfilenocase;
|
||||
hashfunc = hashnocase;
|
||||
/* Make sure all SPICE file reading is case insensitive */
|
||||
/* BUT if a verilog file was read before it, then it will */
|
||||
/* be forced to be case sensitive, caveat end-user. */
|
||||
|
||||
if (matchfunc == match) {
|
||||
Printf("Warning: A case-sensitive file has been read and so the "
|
||||
"SPICE netlist must be treated case-sensitive to match.\n");
|
||||
}
|
||||
else {
|
||||
matchfunc = matchnocase;
|
||||
matchintfunc = matchfilenocase;
|
||||
hashfunc = hashnocase;
|
||||
}
|
||||
|
||||
InitializeHashTable(&spiceparams, OBJHASHSIZE);
|
||||
|
||||
@@ -1951,7 +1997,7 @@ void IncludeSpice(char *fname, int parent, struct cellstack **CellStackPtr,
|
||||
int blackbox)
|
||||
{
|
||||
int filenum = -1;
|
||||
char name[256];
|
||||
char name[MAX_STR_LEN];
|
||||
|
||||
/* If fname does not begin with "/", then assume that it is */
|
||||
/* in the same relative path as its parent. */
|
||||
@@ -1980,14 +2026,18 @@ void IncludeSpice(char *fname, int parent, struct cellstack **CellStackPtr,
|
||||
/* helps, if the file didn't have an extension. But */
|
||||
/* really, we're getting desperate at this point. */
|
||||
|
||||
if (strchr(fname, '.') == NULL) {
|
||||
if (strrchr(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;
|
||||
if (filenum < 0) {
|
||||
Fprintf(stderr, "Error in SPICE file include: No file %s\n", name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Fprintf(stderr, "Error in SPICE file include: No file %s\n", fname);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
ReadSpiceFile(fname, parent, CellStackPtr, blackbox);
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef _TECH_H
|
||||
#define _TECH_H
|
||||
|
||||
extern int ActelLibPresent(void);
|
||||
extern void ActelLib(void);
|
||||
extern void VerilogTop(char *name, int fnum, char *filename);
|
||||
|
||||
#endif /* _TECH_H */
|
||||
@@ -34,6 +34,8 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include "print.h"
|
||||
#endif
|
||||
|
||||
extern void Finsert(FILE *f);
|
||||
|
||||
void test_entry(void)
|
||||
{
|
||||
|
||||
|
||||
+950
-395
File diff suppressed because it is too large
Load Diff
+7
-9
@@ -23,6 +23,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef IBMPC
|
||||
#include <stdlib.h> /* for strtol on PC */
|
||||
@@ -33,6 +34,8 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include "netfile.h"
|
||||
#include "hash.h"
|
||||
#include "print.h"
|
||||
#include "xilinx.h"
|
||||
#include "flatten.h"
|
||||
|
||||
#define XILINXHASHSIZE 99
|
||||
static long xilinxhashbase = 0xA00;
|
||||
@@ -132,10 +135,8 @@ char *xilinx_class(model)
|
||||
}
|
||||
return(model);
|
||||
}
|
||||
void
|
||||
Xilinx(cellname, filename)
|
||||
char *cellname;
|
||||
char *filename;
|
||||
|
||||
void Xilinx(char *cellname, char *filename)
|
||||
{
|
||||
char Path[500];
|
||||
char FileName[500];
|
||||
@@ -163,8 +164,7 @@ Xilinx(cellname, filename)
|
||||
CloseFile(FileName);
|
||||
}
|
||||
|
||||
xilinxCell(cell)
|
||||
char *cell;
|
||||
int xilinxCell(char *cell)
|
||||
{
|
||||
struct nlist *nl;
|
||||
struct objlist *ob;
|
||||
@@ -252,9 +252,7 @@ struct objlist *xilinx_gate(ob,nl)
|
||||
return(nob);
|
||||
}
|
||||
|
||||
xilinx_sym(nl,gob)
|
||||
struct nlist *nl;
|
||||
struct objlist *gob;
|
||||
void xilinx_sym(struct nlist *nl, struct objlist *gob)
|
||||
{
|
||||
struct objlist *ob;
|
||||
char *cp,*rindex();
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef _XILINX_H
|
||||
#define _XILINX_H
|
||||
|
||||
extern void xilinx_sym(struct nlist *nl, struct objlist *gob);
|
||||
extern void Xilinx(char *cellname, char *filename);
|
||||
extern int xilinxCell(char *cell);
|
||||
extern int XilinxLibPresent(void);
|
||||
extern void XilinxLib(void);
|
||||
|
||||
#endif /* _XILINX_H */
|
||||
+5
-5
@@ -65,10 +65,10 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
Widget toplevel = NULL;
|
||||
|
||||
char GlobalFileName[100],
|
||||
GlobalCellName[100],
|
||||
GlobalOtherName[100],
|
||||
GlobalDataName[100];
|
||||
char GlobalFileName[MAX_STR_LEN],
|
||||
GlobalCellName[MAX_STR_LEN],
|
||||
GlobalOtherName[MAX_STR_LEN],
|
||||
GlobalDataName[MAX_STR_LEN];
|
||||
|
||||
/*********************************************************
|
||||
* Menu structure: attaches label string to a function,
|
||||
@@ -1708,7 +1708,7 @@ void X_main_loop(int argc, char *argv[])
|
||||
|
||||
XmStringCharSet cs = "ISOLatin1";
|
||||
|
||||
static char prompt_response[100];
|
||||
static char prompt_response[MAX_STR_LEN];
|
||||
int prompt_done;
|
||||
int calling_editor; /* which string are we trying to get ? */
|
||||
#define FILE_NAME 1
|
||||
|
||||
@@ -4,4 +4,6 @@
|
||||
# all of its config scripts in a different directory than the configure
|
||||
# script itself.
|
||||
|
||||
( CFLAGS="-g" ; export CFLAGS ; cd scripts ; ./configure "$@" )
|
||||
export CFLAGS="$CFLAGS -g"
|
||||
cd scripts
|
||||
exec ./configure "$@"
|
||||
|
||||
+7
-7
@@ -2,11 +2,11 @@ NETGENDIR = ..
|
||||
|
||||
include ${NETGENDIR}/defs.mak
|
||||
|
||||
MANDIRS = $(DESTDIR)${MANDIR} $(DESTDIR)${MANDIR}/man1
|
||||
DOCDIRS = $(DESTDIR)${DOCDIR}
|
||||
MANDIRS = $(DESTDIR)${INSTALL_MANDIR} $(DESTDIR)${INSTALL_MANDIR}/man1
|
||||
DOCDIRS = $(DESTDIR)${INSTALL_DOCDIR}
|
||||
|
||||
MANFILES =
|
||||
DOCFILES = $(DESTDIR)${DOCDIR}/netgen.doc
|
||||
DOCFILES = $(DESTDIR)${INSTALL_DOCDIR}/netgen.doc
|
||||
|
||||
install-tcl: ${DOCDIRS} ${DOCFILES}
|
||||
|
||||
@@ -23,8 +23,8 @@ make-doc-dirs:
|
||||
${SCRIPTS}/mkdirs ${DOCDIRS}
|
||||
|
||||
# This file does not actually exist. . .
|
||||
$(DESTDIR)${MANDIR}/man1/netgen.1: netgen.1 ${MANDIRS}
|
||||
${CP} netgen.1 $(DESTDIR)${MANDIR}/man1/netgen.1
|
||||
$(DESTDIR)${INSTALL_MANDIR}/man1/netgen.1: netgen.1 ${MANDIRS}
|
||||
${CP} netgen.1 $(DESTDIR)${INSTALL_MANDIR}/man1/netgen.1
|
||||
|
||||
$(DESTDIR)${DOCDIR}/netgen.doc: netgen.doc ${DOCDIRS}
|
||||
${CP} netgen.doc $(DESTDIR)${DOCDIR}/netgen.doc
|
||||
$(DESTDIR)${INSTALL_DOCDIR}/netgen.doc: netgen.doc ${DOCDIRS}
|
||||
${CP} netgen.doc $(DESTDIR)${INSTALL_DOCDIR}/netgen.doc
|
||||
|
||||
+6
-6
@@ -4,14 +4,14 @@ include ${NETGENDIR}/defs.mak
|
||||
|
||||
LIB_FILES = ntk2adl.sh spice spice.bot spice.top
|
||||
|
||||
LIB_INST_FILES= $(LIB_FILES:%=$(DESTDIR)${LIBDIR}/netgen/%)
|
||||
BIN_INST_FILES= $(BIN_FILES:%=$(DESTDIR)${BINDIR}/%)
|
||||
LIB_INST_FILES= $(LIB_FILES:%=$(DESTDIR)${INSTALL_LIBDIR}/netgen/%)
|
||||
BIN_INST_FILES= $(BIN_FILES:%=$(DESTDIR)${INSTALL_BINDIR}/%)
|
||||
|
||||
install-tcl: ${LIB_INST_FILES}
|
||||
|
||||
install: ${LIB_INST_FILES}
|
||||
|
||||
$(DESTDIR)${LIBDIR}/netgen/%: %
|
||||
../scripts/mkdirs $(DESTDIR)${LIBDIR}/netgen
|
||||
${RM} $(DESTDIR)${LIBDIR}/netgen/$*
|
||||
${CP} $* $(DESTDIR)${LIBDIR}/netgen/$*
|
||||
$(DESTDIR)${INSTALL_LIBDIR}/netgen/%: %
|
||||
../scripts/mkdirs $(DESTDIR)${INSTALL_LIBDIR}/netgen
|
||||
${RM} $(DESTDIR)${INSTALL_LIBDIR}/netgen/$*
|
||||
${CP} $* $(DESTDIR)${INSTALL_LIBDIR}/netgen/$*
|
||||
|
||||
+12
-12
@@ -25,23 +25,23 @@ tclnetgen${SHDLIB_EXT}: ${EXTRA_LIBS}
|
||||
${LD_RUN_PATH} ${EXTRA_LIBS} ${LD_EXTRA_LIBS} \
|
||||
-lc ${LIBS} ${LIB_SPECS} ${LDFLAGS}
|
||||
|
||||
$(DESTDIR)${BINDIR}/netgen:
|
||||
$(DESTDIR)${INSTALL_BINDIR}/netgen:
|
||||
${RM} $@
|
||||
${CP} netgen $@
|
||||
|
||||
$(DESTDIR)${BINDIR}/ntk2adl:
|
||||
$(DESTDIR)${INSTALL_BINDIR}/ntk2adl:
|
||||
${RM} $@
|
||||
${CP} ntk2adl $@
|
||||
|
||||
$(DESTDIR)${BINDIR}/ntk2xnf:
|
||||
$(DESTDIR)${INSTALL_BINDIR}/ntk2xnf:
|
||||
${RM} $@
|
||||
${CP} ntk2xnf $@
|
||||
|
||||
$(DESTDIR)${BINDIR}/netcomp:
|
||||
$(DESTDIR)${INSTALL_BINDIR}/netcomp:
|
||||
${RM} $@
|
||||
${CP} netcomp $@
|
||||
|
||||
$(DESTDIR)${BINDIR}/inetcomp:
|
||||
$(DESTDIR)${INSTALL_BINDIR}/inetcomp:
|
||||
${RM} $@
|
||||
${CP} inetcomp $@
|
||||
|
||||
@@ -61,14 +61,14 @@ ntk2xnf: ntk2xnf.c
|
||||
${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS} ntk2xnf.c -o $@ ${EXTRA_LIBS} \
|
||||
${LIBS} ${LDFLAGS}
|
||||
|
||||
install: $(DESTDIR)${BINDIR}/netgen $(DESTDIR)${BINDIR}/netcomp \
|
||||
$(DESTDIR)${BINDIR}/inetcomp $(DESTDIR)${BINDIR}/ntk2adl \
|
||||
$(DESTDIR)${BINDIR}/ntk2xnf
|
||||
install: $(DESTDIR)${INSTALL_BINDIR}/netgen $(DESTDIR)${INSTALL_BINDIR}/netcomp \
|
||||
$(DESTDIR)${INSTALL_BINDIR}/inetcomp $(DESTDIR)${INSTALL_BINDIR}/ntk2adl \
|
||||
$(DESTDIR)${INSTALL_BINDIR}/ntk2xnf
|
||||
|
||||
install-tcl: $(DESTDIR)${TCLDIR} $(DESTDIR)${TCLDIR}/tclnetgen${SHDLIB_EXT}
|
||||
install-tcl: $(DESTDIR)${INSTALL_TCLDIR} $(DESTDIR)${INSTALL_TCLDIR}/tclnetgen${SHDLIB_EXT}
|
||||
|
||||
$(DESTDIR)${TCLDIR}/tclnetgen${SHDLIB_EXT}: tclnetgen${SHDLIB_EXT}
|
||||
${RM} $(DESTDIR)${TCLDIR}/tclnetgen${SHDLIB_EXT}
|
||||
${CP} tclnetgen${SHDLIB_EXT} $(DESTDIR)${TCLDIR}/tclnetgen${SHDLIB_EXT}
|
||||
$(DESTDIR)${INSTALL_TCLDIR}/tclnetgen${SHDLIB_EXT}: tclnetgen${SHDLIB_EXT}
|
||||
${RM} $(DESTDIR)${INSTALL_TCLDIR}/tclnetgen${SHDLIB_EXT}
|
||||
${CP} tclnetgen${SHDLIB_EXT} $(DESTDIR)${INSTALL_TCLDIR}/tclnetgen${SHDLIB_EXT}
|
||||
|
||||
include ${NETGENDIR}/rules.mak
|
||||
|
||||
+2
-1
@@ -17,6 +17,7 @@ along with this program; see the file copying. If not, write to
|
||||
the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
/* inetcomp.c -- a simple wrapper to the NETCOMP() function */
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include "netgen.h"
|
||||
@@ -33,7 +34,7 @@ void STRCPY(char *dest, char *source)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char cell1[200], cell2[200];
|
||||
char cell1[MAX_STR_LEN], cell2[MAX_STR_LEN];
|
||||
|
||||
Debug = 0;
|
||||
if (argc != 1) {
|
||||
|
||||
+3
-2
@@ -17,6 +17,7 @@ along with this program; see the file copying. If not, write to
|
||||
the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
/* netcomp.c -- a simple wrapper to provide netlist comparison functionality */
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include "netgen.h"
|
||||
@@ -51,7 +52,7 @@ void STRCPY(char *dest, char *source)
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#ifndef HAVE_GETOPT
|
||||
char cell1[200], cell2[200];
|
||||
char cell1[MAX_STR_LEN], cell2[MAX_STR_LEN];
|
||||
int filenum = -1;
|
||||
|
||||
Debug = 0;
|
||||
@@ -67,7 +68,7 @@ int main(int argc, char *argv[])
|
||||
STRCPY(cell2, ReadNetlist(argv[2], &filenum));
|
||||
if (argc == 5) STRCPY(cell2, argv[4]); /* if explicit cell name specified */
|
||||
#else
|
||||
char cell1[200], cell2[200];
|
||||
char cell1[MAX_STR_LEN], cell2[MAX_STR_LEN];
|
||||
int usage = 0;
|
||||
int args;
|
||||
int c;
|
||||
|
||||
@@ -23,6 +23,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include <stdlib.h> /* for getenv */
|
||||
#endif
|
||||
#include "netgen.h"
|
||||
#include "print.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
+3
-1
@@ -20,9 +20,11 @@ along with this program; see the file copying. If not, write to
|
||||
the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
/* ntk2xnf.c -- a simple wrapper to translate .ntk to Xilinx XNF format */
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include "netgen.h"
|
||||
#include "xilinx.h"
|
||||
|
||||
#ifdef HAVE_X11
|
||||
/* the following two X procedures are to permit linking
|
||||
@@ -47,7 +49,7 @@ void STRCPY(char *dest, char *source)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char cellname[200];
|
||||
char cellname[MAX_STR_LEN];
|
||||
int filenum = -1;
|
||||
|
||||
Debug = 0;
|
||||
|
||||
+15
-12
@@ -4,19 +4,21 @@ SRCS =
|
||||
SCRIPTS = consoletext.py helpwindow.py lvs_manager.py treeviewsplit.py
|
||||
SCRIPTS += tksimpledialog.py tooltip.py lvs_help.txt
|
||||
|
||||
SCRIPTINSTALL = $(DESTDIR)${PYDIR}
|
||||
SCRIPTINSTALL = $(DESTDIR)${INSTALL_PYDIR}
|
||||
|
||||
include ${NETGENDIR}/defs.mak
|
||||
|
||||
CLEANS += lvs_manager.py
|
||||
|
||||
main: lvs_manager.py
|
||||
|
||||
tcl-main: lvs_manager.py
|
||||
|
||||
$(DESTDIR)${PYDIR}/consoletext.py:
|
||||
$(DESTDIR)${INSTALL_PYDIR}/consoletext.py:
|
||||
${RM} $@
|
||||
${CP} consoletext.py $@
|
||||
|
||||
$(DESTDIR)${PYDIR}/helpwindow.py:
|
||||
$(DESTDIR)${INSTALL_PYDIR}/helpwindow.py:
|
||||
${RM} $@
|
||||
${CP} helpwindow.py $@
|
||||
|
||||
@@ -24,31 +26,32 @@ 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
|
||||
$(DESTDIR)${INSTALL_PYDIR}/lvs_manager.py: lvs_manager.py
|
||||
${RM} $@
|
||||
${CP} lvs_manager.py $@
|
||||
chmod a+x $@
|
||||
|
||||
$(DESTDIR)${PYDIR}/treeviewsplit.py: treeviewsplit.py
|
||||
$(DESTDIR)${INSTALL_PYDIR}/treeviewsplit.py: treeviewsplit.py
|
||||
${RM} $@
|
||||
${CP} treeviewsplit.py $@
|
||||
|
||||
$(DESTDIR)${PYDIR}/tksimpledialog.py: tksimpledialog.py
|
||||
$(DESTDIR)${INSTALL_PYDIR}/tksimpledialog.py: tksimpledialog.py
|
||||
${RM} $@
|
||||
${CP} tksimpledialog.py $@
|
||||
|
||||
$(DESTDIR)${PYDIR}/tooltip.py: tooltip.py
|
||||
$(DESTDIR)${INSTALL_PYDIR}/tooltip.py: tooltip.py
|
||||
${RM} $@
|
||||
${CP} tooltip.py $@
|
||||
|
||||
$(DESTDIR)${PYDIR}/lvs_help.txt: lvs_help.txt
|
||||
$(DESTDIR)${INSTALL_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
|
||||
install-tcl: $(DESTDIR)${INSTALL_PYDIR} $(DESTDIR)${INSTALL_PYDIR}/consoletext.py \
|
||||
$(DESTDIR)${INSTALL_PYDIR}/helpwindow.py $(DESTDIR)${INSTALL_PYDIR}/lvs_manager.py \
|
||||
$(DESTDIR)${INSTALL_PYDIR}/treeviewsplit.py $(DESTDIR)${INSTALL_PYDIR}/tksimpledialog.py \
|
||||
$(DESTDIR)${INSTALL_PYDIR}/tooltip.py $(DESTDIR)${INSTALL_PYDIR}/lvs_help.txt
|
||||
|
||||
include ${NETGENDIR}/rules.mak
|
||||
|
||||
@@ -1,819 +0,0 @@
|
||||
#!/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()
|
||||
+108
-36
@@ -343,7 +343,7 @@ class LVSManager(ttk.Frame):
|
||||
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)
|
||||
self.toppane.title2_frame.tech_select.config(text = self.tech)
|
||||
|
||||
def choose_layout(self):
|
||||
try:
|
||||
@@ -358,30 +358,37 @@ class LVSManager(ttk.Frame):
|
||||
title = "Choose a layout cell to compare.")
|
||||
if cellname != '':
|
||||
print("Selected compare cell " + cellname)
|
||||
self.layout = cellname
|
||||
cellbase = os.path.split(cellname)[1]
|
||||
self.layout = os.path.splitext(cellbase)[0]
|
||||
self.toppane.title2_frame.layout_select.config(text = self.layout)
|
||||
layoutname = os.path.splitext(cellbase)[0]
|
||||
self.toppane.title2_frame.layout_select.config(text = layoutname)
|
||||
fileext = os.path.splitext(cellbase)[1]
|
||||
if fileext == '.mag':
|
||||
self.toppane.title2_frame.layout_label.config(text = 'Layout:')
|
||||
else:
|
||||
self.toppane.title2_frame.layout_label.config(text = 'Layout netlist:')
|
||||
|
||||
def choose_netlist(self):
|
||||
try:
|
||||
project_path = self.rootpath
|
||||
initdirname = self.rootpath + '/netlist/' + self.project + '.spi'
|
||||
initdirname = self.rootpath + '/netlist/' + self.project + '.spice'
|
||||
except:
|
||||
print('Must choose a project first.')
|
||||
return
|
||||
cellname = filedialog.askopenfilename(multiple=False,
|
||||
initialdir = initdirname,
|
||||
filetypes = (("Spice netlist", "*.spi"),("Verilog netlist", "*.v")),
|
||||
filetypes = (("Spice netlist", "*.spice"),("Verilog netlist", "*.v"),("All Files","*.*")),
|
||||
title = "Choose a netlist to compare.")
|
||||
if cellname != '':
|
||||
print("Selected compare cell " + cellname)
|
||||
self.schematic = cellname
|
||||
cellbase = os.path.split(cellname)[1]
|
||||
self.schematic = os.path.splitext(cellbase)[0]
|
||||
self.toppane.title2_frame.schem_select.config(text = self.schematic)
|
||||
schematic_name = os.path.splitext(cellbase)[0]
|
||||
self.toppane.title2_frame.schem_select.config(text = schematic_name)
|
||||
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':
|
||||
elif fileext == '.sp' or fileext == '.spice' or fileext == '.spi' 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:')
|
||||
@@ -433,7 +440,10 @@ class LVSManager(ttk.Frame):
|
||||
self.logfile = None
|
||||
|
||||
# Put new log file called 'lvs.log' in the mag/ subdirectory
|
||||
self.logfile = open(rootpath + '/layout/lvs.log', 'w')
|
||||
if os.path.exists(rootpath + '/layout'):
|
||||
self.logfile = open(rootpath + '/layout/lvs.log', 'w')
|
||||
else:
|
||||
self.logfile = open(rootpath + '/lvs.log', 'w')
|
||||
# Print some initial information to the logfile.
|
||||
self.logprint('Starting new log file ' + datetime.datetime.now().strftime('%c'),
|
||||
doflush=True)
|
||||
@@ -444,15 +454,23 @@ class LVSManager(ttk.Frame):
|
||||
# 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)
|
||||
layname = os.path.splitext(os.path.split(self.layout)[1])[0]
|
||||
self.toppane.title2_frame.layout_select.config(text = layname)
|
||||
schemname = os.path.splitext(os.path.split(self.schematic)[1])[0]
|
||||
self.toppane.title2_frame.schem_select.config(text = schemname)
|
||||
|
||||
# Update schematic button
|
||||
if os.path.isfile(rootpath + '/verilog/' + self.schematic + '.v'):
|
||||
if os.path.splitext(self.schematic)[1] == '.v':
|
||||
self.toppane.title2_frame.schem_label.config(text = 'Verilog netlist:')
|
||||
else:
|
||||
self.toppane.title2_frame.schem_label.config(text = 'Schematic netlist:')
|
||||
|
||||
# Update layout button
|
||||
if os.path.splitext(self.layout)[1] == '.mag':
|
||||
self.toppane.title2_frame.schem_label.config(text = 'Layout:')
|
||||
else:
|
||||
self.toppane.title2_frame.schem_label.config(text = 'Layout netlist:')
|
||||
|
||||
# If there is a comparison file that post-dates both netlists, load it.
|
||||
self.check_lvs()
|
||||
return True
|
||||
@@ -567,8 +585,8 @@ class LVSManager(ttk.Frame):
|
||||
# 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'
|
||||
layout_path = project_path + '/layout/' + project_name + '.spice'
|
||||
net_path = project_path + '/netlist/' + project_name + '.spice'
|
||||
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):
|
||||
@@ -599,7 +617,7 @@ class LVSManager(ttk.Frame):
|
||||
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("ext2spice -o " + self.layout + ".spice\n")
|
||||
mproc.stdin.write("quit -noprompt\n")
|
||||
magicout = mproc.communicate()[0]
|
||||
self.printwarn(magicout)
|
||||
@@ -607,8 +625,8 @@ class LVSManager(ttk.Frame):
|
||||
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)
|
||||
# Move .spice netlist to project_dir/netlist/lvs/
|
||||
shutil.move(project_path + '/layout/' + self.layout + '.spice', layout_path)
|
||||
# Remove extraction files
|
||||
for file in os.listdir(project_path + '/layout'):
|
||||
if os.path.splitext(file)[1] == '.ext':
|
||||
@@ -625,17 +643,37 @@ class LVSManager(ttk.Frame):
|
||||
|
||||
project_path = self.rootpath
|
||||
project_name = self.project
|
||||
comp_path = project_path + '/layout/comp.json'
|
||||
|
||||
# Diagnostic:
|
||||
print('project_name is ' + project_name)
|
||||
print('project_path is ' + project_path)
|
||||
print('self.layout is ' + self.layout)
|
||||
print('self.schematic is ' + self.schematic)
|
||||
print('self.lvs_setup is ' + self.lvs_setup)
|
||||
|
||||
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'
|
||||
if os.path.isfile(self.layout):
|
||||
layout_path = self.layout
|
||||
layout_src = None
|
||||
else:
|
||||
layout_path = project_path + '/netlist/lvs/' + self.layout + '.spice'
|
||||
layout_src = project_path + '/layout/' + self.layout + '.mag'
|
||||
|
||||
comp_dir = os.path.split(layout_path)[0]
|
||||
comp_path = comp_dir + '/comp.json'
|
||||
|
||||
if os.path.isfile(self.schematic):
|
||||
net_path = self.schematic
|
||||
else:
|
||||
net_path = project_path + '/netlist/schem/' + self.schematic + '.spice'
|
||||
|
||||
# Does the setup file exist (this is optional)?
|
||||
if self.lvs_setup != '' and not os.path.isfile('setup.tcl'):
|
||||
if self.lvs_setup == '' and not os.path.isfile('setup.tcl'):
|
||||
print('No technology setup file selected.')
|
||||
elif not os.path.isfile(self.lvs_setup):
|
||||
print("Can't find technology setup file " + self.lvs_setup)
|
||||
|
||||
# Does schematic netlist exist?
|
||||
if not os.path.isfile(vlog_path) and not os.path.isfile(net_path):
|
||||
@@ -643,14 +681,16 @@ class LVSManager(ttk.Frame):
|
||||
return
|
||||
|
||||
# Does LVS netlist subdirectory exist?
|
||||
if not os.path.exists(project_path + '/netlist/lvs'):
|
||||
os.makedirs(project_path + '/netlist/lvs')
|
||||
if os.path.exists(project_path + '/netlist'):
|
||||
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
|
||||
if layout_src:
|
||||
if not self.generate_layout_netlist(layout_path, layout_src, project_path):
|
||||
return False
|
||||
|
||||
# Final check
|
||||
# Final checks
|
||||
if not os.path.isfile(layout_path):
|
||||
print('Error: No netlist generated from magic.')
|
||||
return
|
||||
@@ -662,26 +702,27 @@ class LVSManager(ttk.Frame):
|
||||
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.
|
||||
|
||||
layoutcell = os.path.splitext(os.path.split(self.layout)[1])[0]
|
||||
is_subckt = False
|
||||
subname = None
|
||||
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:
|
||||
if subname == layoutcell:
|
||||
is_subckt = True
|
||||
break
|
||||
|
||||
if is_subckt:
|
||||
layout_arg = layout_path + ' ' + self.layout
|
||||
layout_arg = self.layout + ' ' + layoutcell
|
||||
layout_text = '"' + layout_arg + '"'
|
||||
elif subname:
|
||||
layout_arg = self.layout + ' ' + subname
|
||||
layout_text = '"' + layout_arg + '"'
|
||||
else:
|
||||
layout_arg = layout_path
|
||||
@@ -690,8 +731,39 @@ class LVSManager(ttk.Frame):
|
||||
if has_vlog:
|
||||
schem_arg = vlog_path + ' ' + self.schematic
|
||||
else:
|
||||
schem_arg = net_path + ' ' + self.schematic
|
||||
schem_text = '"' + schem_arg + '"'
|
||||
# Final checks
|
||||
if not os.path.isfile(net_path):
|
||||
print('Error: No netlist from schematic.')
|
||||
return
|
||||
|
||||
with open(net_path) as ifile:
|
||||
spitext = ifile.read()
|
||||
|
||||
# Check the netlist to see if the cell to match is a subcircuit. If
|
||||
# not, then assume it is the top level.
|
||||
|
||||
schemcell = os.path.splitext(os.path.split(self.schematic)[1])[0]
|
||||
subname = None
|
||||
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 == schemcell:
|
||||
is_subckt = True
|
||||
break
|
||||
|
||||
if is_subckt:
|
||||
schem_arg = self.schematic + ' ' + schemcell
|
||||
schem_text = '"' + schem_arg + '"'
|
||||
elif subname:
|
||||
schem_arg = self.schematic + ' ' + subname
|
||||
schem_text = '"' + schem_arg + '"'
|
||||
else:
|
||||
schem_arg = net_path
|
||||
schem_text = schem_arg
|
||||
|
||||
# Remove any previous comparison output file
|
||||
comp_out_path = os.path.splitext(comp_path)[0] + '.out'
|
||||
@@ -708,7 +780,7 @@ class LVSManager(ttk.Frame):
|
||||
self.lvsproc = subprocess.Popen(['netgen', '-batch', 'lvs',
|
||||
layout_arg, schem_arg,
|
||||
self.lvs_setup, comp_out_path, '-json', '-blackbox'],
|
||||
cwd=project_path + '/layout',
|
||||
cwd=comp_dir,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=0)
|
||||
# This is largely unnecessary as netgen usually runs to completion very quickly.
|
||||
self.watchclock(comp_path)
|
||||
|
||||
Vendored
+42
-3
@@ -633,6 +633,7 @@ gr_srcs
|
||||
gr_libs
|
||||
gr_dflags
|
||||
gr_cflags
|
||||
DIST_DIR
|
||||
cadinstall
|
||||
programs
|
||||
unused
|
||||
@@ -711,6 +712,7 @@ infodir
|
||||
docdir
|
||||
oldincludedir
|
||||
includedir
|
||||
runstatedir
|
||||
localstatedir
|
||||
sharedstatedir
|
||||
sysconfdir
|
||||
@@ -734,6 +736,7 @@ ac_subst_files=''
|
||||
ac_user_opts='
|
||||
enable_option_checking
|
||||
with_gnu_ld
|
||||
with_distdir
|
||||
with_interpreter
|
||||
with_tcl
|
||||
with_tk
|
||||
@@ -792,6 +795,7 @@ datadir='${datarootdir}'
|
||||
sysconfdir='${prefix}/etc'
|
||||
sharedstatedir='${prefix}/com'
|
||||
localstatedir='${prefix}/var'
|
||||
runstatedir='${localstatedir}/run'
|
||||
includedir='${prefix}/include'
|
||||
oldincludedir='/usr/include'
|
||||
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
|
||||
@@ -1044,6 +1048,15 @@ do
|
||||
| -silent | --silent | --silen | --sile | --sil)
|
||||
silent=yes ;;
|
||||
|
||||
-runstatedir | --runstatedir | --runstatedi | --runstated \
|
||||
| --runstate | --runstat | --runsta | --runst | --runs \
|
||||
| --run | --ru | --r)
|
||||
ac_prev=runstatedir ;;
|
||||
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
|
||||
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
|
||||
| --run=* | --ru=* | --r=*)
|
||||
runstatedir=$ac_optarg ;;
|
||||
|
||||
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
|
||||
ac_prev=sbindir ;;
|
||||
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
|
||||
@@ -1181,7 +1194,7 @@ fi
|
||||
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
|
||||
datadir sysconfdir sharedstatedir localstatedir includedir \
|
||||
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
|
||||
libdir localedir mandir
|
||||
libdir localedir mandir runstatedir
|
||||
do
|
||||
eval ac_val=\$$ac_var
|
||||
# Remove trailing slashes.
|
||||
@@ -1334,6 +1347,7 @@ Fine tuning of the installation directories:
|
||||
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
||||
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
||||
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
||||
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
|
||||
--libdir=DIR object code libraries [EPREFIX/lib]
|
||||
--includedir=DIR C header files [PREFIX/include]
|
||||
--oldincludedir=DIR C header files for non-gcc [/usr/include]
|
||||
@@ -1372,6 +1386,7 @@ Optional Packages:
|
||||
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
|
||||
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
|
||||
--with-gnu-ld assume the C compiler uses GNU ld [default=no]
|
||||
--with-distdir=DIR install into location DIR for distribution
|
||||
--with-interpreter=arg enable interpreter
|
||||
--with-tcl=DIR Find tclConfig.sh in DIR
|
||||
--with-tk=DIR Find tkConfig.sh in DIR
|
||||
@@ -4798,6 +4813,24 @@ usingTcl=1
|
||||
usingX11=
|
||||
|
||||
|
||||
# For distributed installs, where the run-time files are installed in a
|
||||
# place that is a temporary staging area, like DESTDIR, but unlike DESTDIR,
|
||||
# the prefix is replaced by the destination directory, rather than appended
|
||||
# to it.
|
||||
DIST_DIR="\${exec_prefix}"
|
||||
|
||||
# Check whether --with-distdir was given.
|
||||
if test "${with_distdir+set}" = set; then :
|
||||
withval=$with_distdir;
|
||||
if test "$withval" = "no" -o "$withval" = "NO" ; then
|
||||
DIST_DIR="\${exec_prefix}"
|
||||
else
|
||||
DIST_DIR=${withval}
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# Check whether --with-interpreter was given.
|
||||
if test "${with_interpreter+set}" = set; then :
|
||||
@@ -6044,7 +6077,6 @@ fi
|
||||
|
||||
|
||||
if test $usingTcl ; then
|
||||
usingX11=1
|
||||
cadinstall="$cadinstall tcltk"
|
||||
modules="$modules tcltk"
|
||||
programs="$programs tcltk"
|
||||
@@ -6054,7 +6086,11 @@ if test $usingTcl ; then
|
||||
|
||||
extra_libs="$extra_libs \${NETGENDIR}/tcltk/libtcltk.o"
|
||||
extra_defs="$extra_defs -DTCL_DIR=\\\"\${TCLDIR}\\\""
|
||||
stub_defs="$stub_defs -DUSE_TCL_STUBS -DUSE_TK_STUBS"
|
||||
if test $usingX11 ; then
|
||||
stub_defs="$stub_defs -DUSE_TCL_STUBS"
|
||||
else
|
||||
stub_defs="$stub_defs -DUSE_TCL_STUBS -DUSE_TK_STUBS"
|
||||
fi
|
||||
else
|
||||
programs="$programs netgen"
|
||||
unused="$unused tcltk"
|
||||
@@ -6139,6 +6175,7 @@ if test $usingTcl ; then
|
||||
# Tk libraries and header files
|
||||
#
|
||||
# -----------------------------------------------------------------------
|
||||
if test $usingX11 ; then
|
||||
if test "${TK_INC_DIR}" != "/usr/include" ; then
|
||||
INC_SPECS="${INC_SPECS} -I${TK_INC_DIR}"
|
||||
fi
|
||||
@@ -6155,6 +6192,7 @@ if test $usingTcl ; then
|
||||
loader_run_path="${TK_LIB_DIR}:${loader_run_path}"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
#
|
||||
@@ -6587,6 +6625,7 @@ fi
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ac_config_files="$ac_config_files defs.mak"
|
||||
|
||||
+22
-2
@@ -249,6 +249,20 @@ usingX11=
|
||||
|
||||
dnl Compile-time options below. . .
|
||||
|
||||
# For distributed installs, where the run-time files are installed in a
|
||||
# place that is a temporary staging area, like DESTDIR, but unlike DESTDIR,
|
||||
# the prefix is replaced by the destination directory, rather than appended
|
||||
# to it.
|
||||
DIST_DIR="\${exec_prefix}"
|
||||
AC_ARG_WITH(distdir,
|
||||
[ --with-distdir=DIR install into location DIR for distribution], [
|
||||
if test "$withval" = "no" -o "$withval" = "NO" ; then
|
||||
DIST_DIR="\${exec_prefix}"
|
||||
else
|
||||
DIST_DIR=${withval}
|
||||
fi
|
||||
], )
|
||||
|
||||
AC_ARG_WITH(interpreter,
|
||||
[ --with-interpreter=[arg] enable interpreter], [
|
||||
if test "$withval" = "no" -o "$withval" = "NO"; then
|
||||
@@ -793,7 +807,6 @@ dnl "make" instead of requiring "make tcl"
|
||||
dnl ----------------------------------------------------------------
|
||||
|
||||
if test $usingTcl ; then
|
||||
usingX11=1
|
||||
cadinstall="$cadinstall tcltk"
|
||||
modules="$modules tcltk"
|
||||
programs="$programs tcltk"
|
||||
@@ -802,7 +815,11 @@ if test $usingTcl ; then
|
||||
AC_DEFINE(TCL_NETGEN)
|
||||
extra_libs="$extra_libs \${NETGENDIR}/tcltk/libtcltk.o"
|
||||
extra_defs="$extra_defs -DTCL_DIR=\\\"\${TCLDIR}\\\""
|
||||
stub_defs="$stub_defs -DUSE_TCL_STUBS -DUSE_TK_STUBS"
|
||||
if test $usingX11 ; then
|
||||
stub_defs="$stub_defs -DUSE_TCL_STUBS"
|
||||
else
|
||||
stub_defs="$stub_defs -DUSE_TCL_STUBS -DUSE_TK_STUBS"
|
||||
fi
|
||||
else
|
||||
programs="$programs netgen"
|
||||
unused="$unused tcltk"
|
||||
@@ -889,6 +906,7 @@ if test $usingTcl ; then
|
||||
# Tk libraries and header files
|
||||
#
|
||||
# -----------------------------------------------------------------------
|
||||
if test $usingX11 ; then
|
||||
if test "${TK_INC_DIR}" != "/usr/include" ; then
|
||||
INC_SPECS="${INC_SPECS} -I${TK_INC_DIR}"
|
||||
fi
|
||||
@@ -905,6 +923,7 @@ if test $usingTcl ; then
|
||||
loader_run_path="${TK_LIB_DIR}:${loader_run_path}"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
#
|
||||
@@ -1272,6 +1291,7 @@ AC_SUBST(modules)
|
||||
AC_SUBST(unused)
|
||||
AC_SUBST(programs)
|
||||
AC_SUBST(cadinstall)
|
||||
AC_SUBST(DIST_DIR)
|
||||
|
||||
AC_SUBST(gr_cflags)
|
||||
AC_SUBST(gr_dflags)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
dnl Use autoconf 2.52 or newer.
|
||||
|
||||
AC_INIT(netgen, 1.3, [email protected])
|
||||
AC_INIT(netgen, 1.3, [email protected])
|
||||
AC_PREREQ(2.52)
|
||||
AC_CONFIG_SRCDIR(rules.mak)
|
||||
AC_CONFIG_AUX_DIR(.)
|
||||
@@ -38,7 +38,7 @@ dnl assert that input files are of type C, or else the preprocessing
|
||||
dnl stage will not execute correctly on the ".in" files in the scmos
|
||||
dnl directory.
|
||||
|
||||
if test "$CPP" = "gcc -E" ; then
|
||||
if test "$CPP" = "$CC -E" ; then
|
||||
CPP="$CPP -x c"
|
||||
fi
|
||||
|
||||
@@ -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(
|
||||
@@ -195,6 +198,7 @@ fi
|
||||
# not ANSI-compliant and won't compile without quite a bit of work.
|
||||
AC_DEFINE(DBUG_OFF)
|
||||
|
||||
stub_defs=""
|
||||
extra_defs="$extra_defs -DCAD_DIR=\\\"\${LIBDIR}\\\""
|
||||
X_LIBS=
|
||||
X_CFLAGS=
|
||||
@@ -245,6 +249,20 @@ usingX11=
|
||||
|
||||
dnl Compile-time options below. . .
|
||||
|
||||
# For distributed installs, where the run-time files are installed in a
|
||||
# place that is a temporary staging area, like DESTDIR, but unlike DESTDIR,
|
||||
# the prefix is replaced by the destination directory, rather than appended
|
||||
# to it.
|
||||
DIST_DIR="\${exec_prefix}"
|
||||
AC_ARG_WITH(distdir,
|
||||
[ --with-distdir=DIR install into location DIR for distribution], [
|
||||
if test "$withval" = "no" -o "$withval" = "NO" ; then
|
||||
DIST_DIR="\${exec_prefix}"
|
||||
else
|
||||
DIST_DIR=${withval}
|
||||
fi
|
||||
], )
|
||||
|
||||
AC_ARG_WITH(interpreter,
|
||||
[ --with-interpreter=[arg] enable interpreter], [
|
||||
if test "$withval" = "no" -o "$withval" = "NO"; then
|
||||
@@ -329,7 +347,7 @@ if test $usingTcl ; then
|
||||
# 1. Search previously named locations.
|
||||
|
||||
for dir in \
|
||||
$prefix \
|
||||
$ac_default_prefix \
|
||||
$exec_prefix
|
||||
do
|
||||
if test -r "$dir/tclConfig.sh" ; then
|
||||
@@ -351,11 +369,10 @@ if test $usingTcl ; then
|
||||
`ls -dr /usr/local/tcl/tcl[[7-9]].[[0-9]]* 2>/dev/null` \
|
||||
/usr/local/tcl \
|
||||
/usr/local/lib \
|
||||
/usr/lib64 \
|
||||
/usr/local \
|
||||
`ls -dr /usr/lib/tcl[[7-9]].[[0-9]]* 2>/dev/null` \
|
||||
/sw/lib \
|
||||
/usr/lib \
|
||||
/usr/lib64 \
|
||||
/usr
|
||||
do
|
||||
if test -r "$dir/tclConfig.sh" ; then
|
||||
@@ -415,7 +432,7 @@ if test $usingTcl ; then
|
||||
# 1. Search previously named locations.
|
||||
#
|
||||
for dir in \
|
||||
$prefix \
|
||||
$ac_default_prefix \
|
||||
$exec_prefix
|
||||
do
|
||||
if test -r "$dir/tkConfig.sh" ; then
|
||||
@@ -434,21 +451,17 @@ if test $usingTcl ; then
|
||||
#
|
||||
if test "x$tk_config_sh" = "x" ; then
|
||||
for dir in \
|
||||
/usr/local \
|
||||
/usr \
|
||||
`ls -dr /usr/local/lib/tk[[7-9]].[[0-9]]* 2>/dev/null` \
|
||||
`ls -dr /usr/lib/tk[[7-9]].[[0-9]]* 2>/dev/null` \
|
||||
`ls -dr /usr/local/tk/tk[[7-9]].[[0-9]]* 2>/dev/null` \
|
||||
`ls -dr /usr/local/tk[[7-9]].[[0-9]]* 2>/dev/null` \
|
||||
/usr/local/tk \
|
||||
`ls -dr /usr/local/lib/tcl[[7-9]].[[0-9]]* 2>/dev/null` \
|
||||
`ls -dr /usr/lib/tcl/tk[[7-9]].[[0-9]]* 2>/dev/null` \
|
||||
`ls -dr /usr/local/tcl/tcl[[7-9]].[[0-9]]* 2>/dev/null` \
|
||||
`ls -dr /usr/share/tcltk/tk[[7-9]].[[0-9]]* 2>/dev/null` \
|
||||
/sw/lib \
|
||||
/usr/lib \
|
||||
`ls -dr /usr/local/tk/tk[[7-9]].[[0-9]]* 2>/dev/null` \
|
||||
/usr/local/tcl \
|
||||
/usr/local/lib \
|
||||
/usr/lib64 \
|
||||
${x_libraries}
|
||||
/usr/local \
|
||||
`ls -dr /usr/lib/tcl[[7-9]].[[0-9]]* 2>/dev/null` \
|
||||
`ls -dr /usr/lib/tk[[7-9]].[[0-9]]* 2>/dev/null` \
|
||||
/sw/lib \
|
||||
${x_libraries} \
|
||||
/usr
|
||||
do
|
||||
if test -r "$dir/tkConfig.sh" ; then
|
||||
tk_config_sh="$dir/tkConfig.sh"
|
||||
@@ -477,6 +490,25 @@ if test $usingTcl ; then
|
||||
. $tcl_config_sh
|
||||
. $tk_config_sh
|
||||
|
||||
# Should probably trust the config file contents, but this configure
|
||||
# file checks the Tcl and Tk include and lib directories. Since
|
||||
# the config file doesn't separate out the libraries from the strings
|
||||
# passed to the compiler/linker, do it manually here.
|
||||
#
|
||||
# Extract TCL_LIB_DIR from TCL_LIB_SPEC
|
||||
# Extract TK_LIB_DIR from TK_LIB_SPEC
|
||||
# Extract TCL_INC_DIR from TCL_INCLUDE_SPEC
|
||||
# Extract TK_INC_DIR from TK_INCLUDE_SPEC
|
||||
#
|
||||
# These will be the defaults unless overridden by configure command line
|
||||
|
||||
tmpstr=${TCL_LIB_SPEC#*-L}
|
||||
TCL_LIB_DIR=${tmpstr% -l*}
|
||||
tmpstr=${TK_LIB_SPEC#*-L}
|
||||
TK_LIB_DIR=${tmpstr% -l*}
|
||||
TCL_INC_DIR=${TCL_INCLUDE_SPEC#*-I}
|
||||
TK_INC_DIR=${TK_INCLUDE_SPEC#*-I}
|
||||
|
||||
if test "$TCL_VERSION" = "7.6" -a "$TK_VERSION" = "4.2" ; then
|
||||
:
|
||||
elif test "$TCL_VERSION" = "7.5" -a "$TK_VERSION" = "4.1" ; then
|
||||
@@ -620,7 +652,7 @@ if test $usingTcl ; then
|
||||
fi
|
||||
done
|
||||
if test "x${TCLSH_EXE}" != "x" ; then
|
||||
break;
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test "x${TCLSH_EXE}" = "x" ; then
|
||||
@@ -670,8 +702,8 @@ if test $usingTcl ; then
|
||||
else
|
||||
for libname in \
|
||||
"${loclib:=${TCL_EXEC_PREFIX}/lib}/lib${TCL_LIB_NAME}${SHDLIB_EXT}" \
|
||||
"${loclib:=${TCL_EXEC_PREFIX}/lib64}/lib${TCL_LIB_NAME}${SHDLIB_EXT}" \
|
||||
"${loclib:=${TCL_EXEC_PREFIX}/lib}/lib${TCL_LIB_NAME}${SHDLIB_EXT_ALT}"
|
||||
"${loclib:=${TCL_EXEC_PREFIX}/lib}/lib${TCL_LIB_NAME}${SHDLIB_EXT_ALT}" \
|
||||
"${loclib:=${TCL_EXEC_PREFIX}/lib64}/lib${TCL_LIB_NAME}${SHDLIB_EXT}"
|
||||
do
|
||||
if test -r "$libname" ; then
|
||||
TCL_LIB_DIR="${TCL_EXEC_PREFIX}/lib"
|
||||
@@ -784,6 +816,7 @@ if test $usingTcl ; then
|
||||
AC_DEFINE(TCL_NETGEN)
|
||||
extra_libs="$extra_libs \${NETGENDIR}/tcltk/libtcltk.o"
|
||||
extra_defs="$extra_defs -DTCL_DIR=\\\"\${TCLDIR}\\\""
|
||||
stub_defs="$stub_defs -DUSE_TCL_STUBS -DUSE_TK_STUBS"
|
||||
else
|
||||
programs="$programs netgen"
|
||||
unused="$unused tcltk"
|
||||
@@ -850,10 +883,9 @@ case $target in
|
||||
*cygwin*)
|
||||
AC_DEFINE(CYGWIN)
|
||||
AC_DEFINE(i386)
|
||||
AC_DEFINE(WIN32)
|
||||
;;
|
||||
*darwin*)
|
||||
AC_DEFINE(macosx)
|
||||
$as_echo "#define macosx macos" >> confdefs.h
|
||||
if test "$CPP" = "cc -E" ; then
|
||||
CPPFLAGS="$CPPFLAGS -no-cpp-precomp"
|
||||
fi
|
||||
@@ -864,6 +896,7 @@ esac
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
if test $usingTcl ; then
|
||||
LIB_SPECS_NOSTUB="${LIB_SPECS}"
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
#
|
||||
@@ -875,9 +908,11 @@ if test $usingTcl ; then
|
||||
fi
|
||||
if test "${TK_LIB_DIR}" = "/usr/lib" -o \
|
||||
"${TK_LIB_DIR}" = "/usr/lib64" ; then
|
||||
LIB_SPECS="${LIB_SPECS} ${TK_LIB_SPEC}"
|
||||
LIB_SPECS_NOSTUB="${LIB_SPECS_NOSTUB} ${TK_LIB_SPEC}"
|
||||
LIB_SPECS="${LIB_SPECS} ${TK_STUB_LIB_SPEC}"
|
||||
else
|
||||
LIB_SPECS="${LIB_SPECS} -L${TK_LIB_DIR} ${TK_LIB_SPEC}"
|
||||
LIB_SPECS_NOSTUB="${LIB_SPECS_NOSTUB} -L${TK_LIB_DIR} ${TK_LIB_SPEC}"
|
||||
LIB_SPECS="${LIB_SPECS} -L${TK_LIB_DIR} ${TK_STUB_LIB_SPEC}"
|
||||
if test "x${loader_run_path}" = "x" ; then
|
||||
loader_run_path="${TK_LIB_DIR}"
|
||||
else
|
||||
@@ -899,11 +934,13 @@ if test $usingTcl ; then
|
||||
fi
|
||||
|
||||
if test "${TCL_LIB_DIR}" = "/usr/lib" -o \
|
||||
"${TCL_LIB_DIR}" = "/usr/lib64" -o \
|
||||
"${TCL_LIB_DIR}" = "/usr/lib64" -o \
|
||||
"${TCL_LIB_DIR}" = "${TK_LIB_DIR}" ; then
|
||||
LIB_SPECS="${LIB_SPECS} ${TCL_LIB_SPEC}"
|
||||
LIB_SPECS_NOSTUB="${LIB_SPECS_NOSTUB} ${TCL_LIB_SPEC}"
|
||||
LIB_SPECS="${LIB_SPECS} ${TCL_STUB_LIB_SPEC}"
|
||||
else
|
||||
LIB_SPECS="${LIB_SPECS} -L${TCL_LIB_DIR} ${TCL_LIB_SPEC}"
|
||||
LIB_SPECS_NOSTUB="${LIB_SPECS_NOSTUB} -L${TCL_LIB_DIR} ${TCL_LIB_SPEC}"
|
||||
LIB_SPECS="${LIB_SPECS} -L${TCL_LIB_DIR} ${TCL_STUB_LIB_SPEC}"
|
||||
if test "x${loader_run_path}" = "x" ; then
|
||||
loader_run_path="${TCL_LIB_DIR}"
|
||||
else
|
||||
@@ -1097,7 +1134,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*)
|
||||
@@ -1222,6 +1259,7 @@ if test $usingTcl ; then
|
||||
AC_SUBST(LDFLAGS)
|
||||
AC_SUBST(INC_SPECS)
|
||||
AC_SUBST(LIB_SPECS)
|
||||
AC_SUBST(LIB_SPECS_NOSTUB)
|
||||
AC_SUBST(WISH_EXE)
|
||||
AC_SUBST(TCLSH_EXE)
|
||||
AC_SUBST(TCL_LIB_DIR)
|
||||
@@ -1239,6 +1277,7 @@ AC_SUBST(PACKAGE)
|
||||
AC_SUBST(SCRIPTS)
|
||||
AC_SUBST(extra_libs)
|
||||
AC_SUBST(extra_defs)
|
||||
AC_SUBST(stub_defs)
|
||||
AC_SUBST(ld_extra_libs)
|
||||
AC_SUBST(ld_extra_objs)
|
||||
AC_SUBST(top_extra_libs)
|
||||
@@ -1247,11 +1286,13 @@ AC_SUBST(modules)
|
||||
AC_SUBST(unused)
|
||||
AC_SUBST(programs)
|
||||
AC_SUBST(cadinstall)
|
||||
AC_SUBST(DIST_DIR)
|
||||
|
||||
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)
|
||||
@@ -1292,6 +1333,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
|
||||
|
||||
@@ -35,6 +35,13 @@ DOCDIR = ${libdir}/netgen/doc
|
||||
TCLDIR = ${libdir}/netgen/tcl
|
||||
PYDIR = ${libdir}/netgen/python
|
||||
|
||||
INSTALL_BINDIR = @DIST_DIR@/bin
|
||||
INSTALL_MANDIR = @DIST_DIR@/share/man
|
||||
INSTALL_LIBDIR = @DIST_DIR@/lib
|
||||
INSTALL_DOCDIR = ${INSTALL_LIBDIR}/netgen/doc
|
||||
INSTALL_TCLDIR = ${INSTALL_LIBDIR}/netgen/tcl
|
||||
INSTALL_PYDIR = ${INSTALL_LIBDIR}/netgen/python
|
||||
|
||||
MAIN_EXTRA_LIBS = @extra_libs@
|
||||
LD_EXTRA_LIBS = @ld_extra_libs@
|
||||
LD_SHARED = @ld_extra_objs@
|
||||
|
||||
+14
-14
@@ -12,20 +12,20 @@ CLEANS += netgen.sh netgen.tcl netgenexec${EXEEXT}
|
||||
CFLAGS += -I${NETGENDIR}/base
|
||||
|
||||
TCL_FILES = \
|
||||
$(DESTDIR)${TCLDIR}/tkcon.tcl \
|
||||
$(DESTDIR)${TCLDIR}/console.tcl \
|
||||
$(DESTDIR)${TCLDIR}/netgen.tcl
|
||||
$(DESTDIR)${INSTALL_TCLDIR}/tkcon.tcl \
|
||||
$(DESTDIR)${INSTALL_TCLDIR}/console.tcl \
|
||||
$(DESTDIR)${INSTALL_TCLDIR}/netgen.tcl
|
||||
|
||||
tcl-main: netgenexec${EXEEXT} netgen.tcl netgen.sh
|
||||
|
||||
install-tcl: netgenexec${EXEEXT} $(DESTDIR)${BINDIR}/netgen.sh ${TCL_FILES}
|
||||
${RM} $(DESTDIR)${TCLDIR}/netgenexec${EXEEXT}
|
||||
${CP} netgenexec${EXEEXT} $(DESTDIR)${TCLDIR}/netgenexec${EXEEXT}
|
||||
install-tcl: netgenexec${EXEEXT} $(DESTDIR)${INSTALL_BINDIR}/netgen.sh ${TCL_FILES}
|
||||
${RM} $(DESTDIR)${INSTALL_TCLDIR}/netgenexec${EXEEXT}
|
||||
${CP} netgenexec${EXEEXT} $(DESTDIR)${INSTALL_TCLDIR}/netgenexec${EXEEXT}
|
||||
|
||||
netgenexec${EXEEXT}: netgenexec.c
|
||||
${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS_NOSTUB} netgenexec.c \
|
||||
-o netgenexec${EXEEXT} \
|
||||
${LDFLAGS} ${LIBS} ${LIB_SPECS_NOSTUB}
|
||||
${LIB_SPECS_NOSTUB} ${LDFLAGS} ${LIBS} ${GR_LIBS}
|
||||
|
||||
netgen.tcl: netgen.tcl.in
|
||||
sed -e 's%TCL_DIR%${TCLDIR}%g' \
|
||||
@@ -39,13 +39,13 @@ netgen.sh: netgen.sh.in
|
||||
-e 's%WISH_EXE%${WISH_EXE}%g' \
|
||||
netgen.sh.in > netgen.sh
|
||||
|
||||
$(DESTDIR)${TCLDIR}/%: %
|
||||
${RM} $(DESTDIR)${TCLDIR}/$*
|
||||
${CP} $* $(DESTDIR)${TCLDIR}/$*
|
||||
$(DESTDIR)${INSTALL_TCLDIR}/%: %
|
||||
${RM} $(DESTDIR)${INSTALL_TCLDIR}/$*
|
||||
${CP} $* $(DESTDIR)${INSTALL_TCLDIR}/$*
|
||||
|
||||
$(DESTDIR)${BINDIR}/netgen.sh: netgen.sh
|
||||
${RM} $(DESTDIR)${BINDIR}/netgen.sh $(DESTDIR)${BINDIR}/netgen
|
||||
${CP} netgen.sh $(DESTDIR)${BINDIR}/netgen
|
||||
(cd $(DESTDIR)${BINDIR}; chmod 0755 netgen)
|
||||
$(DESTDIR)${INSTALL_BINDIR}/netgen.sh: netgen.sh
|
||||
${RM} $(DESTDIR)${INSTALL_BINDIR}/netgen.sh $(DESTDIR)${INSTALL_BINDIR}/netgen
|
||||
${CP} netgen.sh $(DESTDIR)${INSTALL_BINDIR}/netgen
|
||||
(cd $(DESTDIR)${INSTALL_BINDIR}; chmod 0755 netgen)
|
||||
|
||||
include ${NETGENDIR}/rules.mak
|
||||
|
||||
+161
-49
@@ -62,16 +62,18 @@ proc netgen::convert_to_json {filename lvs_final} {
|
||||
puts $fjson " \["
|
||||
set cktval [lindex $value 0]
|
||||
foreach pin [lrange $cktval 0 end-1] {
|
||||
puts $fjson " \"$pin\","
|
||||
set pinstr [string map {"\\" "\\\\"} $pin]
|
||||
puts $fjson " \"$pinstr\","
|
||||
}
|
||||
set pin [lindex $cktval end]
|
||||
set pin [string map {"\\" "\\\\"} [lindex $cktval end]]
|
||||
puts $fjson " \"$pin\""
|
||||
puts $fjson " \], \["
|
||||
set cktval [lindex $value 1]
|
||||
foreach pin [lrange $cktval 0 end-1] {
|
||||
puts $fjson " \"$pin\","
|
||||
set pinstr [string map {"\\" "\\\\"} $pin]
|
||||
puts $fjson " \"$pinstr\","
|
||||
}
|
||||
set pin [lindex $cktval end]
|
||||
set pin [string map {"\\" "\\\\"} [lindex $cktval end]]
|
||||
puts $fjson " \"$pin\""
|
||||
puts $fjson " \]"
|
||||
if {$kidx == $nkeys} {
|
||||
@@ -138,7 +140,7 @@ proc netgen::convert_to_json {filename lvs_final} {
|
||||
foreach net $cktval {
|
||||
incr nidx
|
||||
puts $fjson " \["
|
||||
set netname [string map {"\\" ""} [lindex $net 0]]
|
||||
set netname [string map {"\\" "\\\\"} [lindex $net 0]]
|
||||
puts $fjson " \"$netname\","
|
||||
puts $fjson " \["
|
||||
set netconn [lindex $net 1]
|
||||
@@ -169,7 +171,7 @@ proc netgen::convert_to_json {filename lvs_final} {
|
||||
foreach net $cktval {
|
||||
incr nidx
|
||||
puts $fjson " \["
|
||||
set netname [string map {"\\" ""} [lindex $net 0]]
|
||||
set netname [string map {"\\" "\\\\"} [lindex $net 0]]
|
||||
puts $fjson " \"$netname\","
|
||||
puts $fjson " \["
|
||||
set netconn [lindex $net 1]
|
||||
@@ -221,7 +223,7 @@ proc netgen::convert_to_json {filename lvs_final} {
|
||||
foreach inst $cktval {
|
||||
incr iidx
|
||||
puts $fjson " \["
|
||||
set instname [lindex $inst 0]
|
||||
set instname [string map {"\\" "\\\\"} [lindex $inst 0]]
|
||||
puts $fjson " \"$instname\","
|
||||
puts $fjson " \["
|
||||
set instpins [lindex $inst 1]
|
||||
@@ -250,7 +252,7 @@ proc netgen::convert_to_json {filename lvs_final} {
|
||||
foreach inst $cktval {
|
||||
incr iidx
|
||||
puts $fjson " \["
|
||||
set instname [lindex $inst 0]
|
||||
set instname [string map {"\\" "\\\\"} [lindex $inst 0]]
|
||||
puts $fjson " \"$instname\","
|
||||
puts $fjson " \["
|
||||
set instpins [lindex $inst 1]
|
||||
@@ -292,8 +294,8 @@ proc netgen::convert_to_json {filename lvs_final} {
|
||||
foreach instance $value {
|
||||
incr pidx
|
||||
puts $fjson " \["
|
||||
set instnames [lindex $instance 0]
|
||||
set instname0 [lindex $instnames 0]
|
||||
set instnames [string map {"\\" "\\\\"} [lindex $instance 0]]
|
||||
set instname0 [string map {"\\" "\\\\"} [lindex $instnames 0]]
|
||||
puts $fjson " \["
|
||||
puts $fjson " \"${instname0}\","
|
||||
puts $fjson " \["
|
||||
@@ -310,7 +312,7 @@ proc netgen::convert_to_json {filename lvs_final} {
|
||||
puts $fjson " \[\"${propname}\", \"${propval}\"\]"
|
||||
puts $fjson " \]"
|
||||
puts $fjson " \],"
|
||||
set instname1 [lindex $instnames 1]
|
||||
set instname1 [string map {"\\" "\\\\"} [lindex $instnames 1]]
|
||||
puts $fjson " \["
|
||||
puts $fjson " \"${instname1}\","
|
||||
puts $fjson " \["
|
||||
@@ -352,7 +354,7 @@ proc netgen::convert_to_json {filename lvs_final} {
|
||||
close $fjson
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------
|
||||
#-----------------------------------------------------------------------
|
||||
# Define the "lvs" command as a way of calling the netgen options
|
||||
# for standard compare, essentially the same as the old "netcomp"
|
||||
# standalone program.
|
||||
@@ -361,14 +363,20 @@ proc netgen::convert_to_json {filename lvs_final} {
|
||||
# although if the cells have not been read in yet, then the
|
||||
# original syntax of filename or {filename cellname} is required.
|
||||
#
|
||||
# "args" is passed to verify and may therefore contain only the
|
||||
# value "-list" or nothing. If "-list", then output is returned
|
||||
# as a nested list.
|
||||
#----------------------------------------------------------------
|
||||
# "args" may be "-list", "-json", or "-blackbox".
|
||||
# "-list" returns output as a nested list.
|
||||
# "-json" creates a .json-format output file in addition to stdout.
|
||||
# "-blackbox" treats empty cells as black-box entries.
|
||||
# "-noflatten={list}" is a list of cells not to flatten if mismatched.
|
||||
# i.e., the cells are expected to match and any mismatch cannot be
|
||||
# expected to be resolved by flattening the contents of the mismatched
|
||||
# cells.
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||
set dolist 0
|
||||
set dojson 0
|
||||
set noflat {}
|
||||
foreach arg $args {
|
||||
if {$arg == "-list"} {
|
||||
puts stdout "Generating list result"
|
||||
@@ -382,6 +390,30 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||
} elseif {$arg == "-blackbox"} {
|
||||
puts stdout "Treating empty subcircuits as black-box cells"
|
||||
netgen::model blackbox on
|
||||
} elseif {[string first "-noflatten=" $arg] == 0} {
|
||||
set value [string range $arg 11 end]
|
||||
# If argument is a filename then read the list of cells from it;
|
||||
# otherwise, argument is the list of files itself in quotes or
|
||||
# braces.
|
||||
if {[file exists $value]} {
|
||||
if {![catch {open $value r} fnf]} {
|
||||
while {[gets $fnf line] >= 0} {
|
||||
if {[lindex $line 0] != "#"} {
|
||||
foreach cell $line {
|
||||
lappend noflat $cell
|
||||
}
|
||||
}
|
||||
}
|
||||
close $fnf
|
||||
} else {
|
||||
puts stderr "Cannot open file $value for reading cell list."
|
||||
}
|
||||
} else {
|
||||
set noflat [string trim $value \"\{\}]
|
||||
}
|
||||
if {[llength $noflat] > 0} {
|
||||
puts stdout "Will not flatten these subcells: $noflat"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -501,13 +533,25 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||
return
|
||||
}
|
||||
set properr {}
|
||||
set matcherr {}
|
||||
set childMismatch 0 ;# 1 indicates black-box child subcircuit mismatch
|
||||
while {$endval != {}} {
|
||||
if {$dolist == 1} {
|
||||
netgen::run -list converge
|
||||
} else {
|
||||
netgen::run converge
|
||||
}
|
||||
netgen::log echo on
|
||||
set pinMismatch 0 ;# indicates pin mismatch in top cell
|
||||
set doCheckFlatten 0
|
||||
set doFlatten 0
|
||||
if {[netgen::print queue] == {}} {
|
||||
set doEquatePins 1 ;# run equate pins on top cell
|
||||
} else {
|
||||
set doEquatePins 0 ;# don't run equate pins unless unique match
|
||||
}
|
||||
set forceMatch 0 ;# for pin matching
|
||||
netgen::log echo off
|
||||
|
||||
if {[verify equivalent]} {
|
||||
# Resolve automorphisms by pin and property
|
||||
if {$dolist == 1} {
|
||||
@@ -516,48 +560,105 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||
netgen::run resolve
|
||||
}
|
||||
set uresult [verify unique]
|
||||
# uresult: -3 : unique with property error
|
||||
# -2 : equivalent with port errors
|
||||
# -1 : black box
|
||||
# 0 : equivalent but not unique
|
||||
# 1 : unique
|
||||
if {$uresult == 0} {
|
||||
netgen::log echo on
|
||||
netgen::log put " Networks match locally but not globally.\n"
|
||||
netgen::log put " Probably connections are swapped.\n"
|
||||
netgen::log put " Check the end of logfile ${logfile} for implicated nodes.\n"
|
||||
netgen::log echo off
|
||||
if {$dolist == 1} {
|
||||
verify -list nodes
|
||||
} else {
|
||||
verify nodes
|
||||
}
|
||||
|
||||
# Flatten the non-matching subcircuit (but not the top-level cells)
|
||||
if {[netgen::print queue] != {}} {
|
||||
netgen::log put " Flattening non-matched subcircuits $endval"
|
||||
netgen::flatten class "[lindex $endval 0] $fnum1"
|
||||
netgen::flatten class "[lindex $endval 1] $fnum2"
|
||||
}
|
||||
set doCheckFlatten 1
|
||||
} else {
|
||||
# Match pins
|
||||
netgen::log echo off
|
||||
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]"
|
||||
}
|
||||
netgen::log echo on
|
||||
# Equate pins for black boxes, unique matches (possibly with property
|
||||
# errors), and unique with port errors
|
||||
set doEquatePins 1
|
||||
}
|
||||
if {$uresult == -1} { ;# black box
|
||||
set forceMatch 1
|
||||
} elseif {$uresult == -3} { ;# property error
|
||||
lappend properr [lindex $endval 0]
|
||||
} elseif {$uresult == -2} { ;# unmatched pins
|
||||
set doCheckFlatten 1
|
||||
}
|
||||
if {$uresult == 2} {lappend properr [lindex $endval 0]}
|
||||
} else {
|
||||
# Flatten the non-matching subcircuit (but not the top-level cells)
|
||||
if {[netgen::print queue] != {}} {
|
||||
netgen::log put " Flattening non-matched subcircuits $endval"
|
||||
netgen::flatten class "[lindex $endval 0] $fnum1"
|
||||
netgen::flatten class "[lindex $endval 1] $fnum2"
|
||||
# not equivalent
|
||||
netgen::log echo on
|
||||
# netgen::log put " DEBUG: not equivalent $endval\n"
|
||||
netgen::log echo off
|
||||
set doCheckFlatten 1
|
||||
}
|
||||
if {$doCheckFlatten} {
|
||||
# Flatten the non-matching subcircuit (but not the top-level cell,
|
||||
# or cells explicitly prohibited from flattening)
|
||||
if {[netgen::print queue] != {}} {
|
||||
if {([lsearch $noflat [lindex $endval 0]] == -1) &&
|
||||
([lsearch $noflat [lindex $endval 1]] == -1)} {
|
||||
set doFlatten 1
|
||||
} else {
|
||||
netgen::log echo on
|
||||
netgen::log put " Continuing with black-boxed subcircuits $endval\n"
|
||||
netgen::log echo off
|
||||
lappend matcherr [lindex $endval 0]"($fnum1)"
|
||||
lappend matcherr [lindex $endval 1]"($fnum2)"
|
||||
netgen::flatten prohibit "[lindex $endval 0] $fnum1"
|
||||
netgen::flatten prohibit "[lindex $endval 1] $fnum2"
|
||||
set doEquatePins 1
|
||||
set childMismatch 1
|
||||
set forceMatch 1
|
||||
}
|
||||
}
|
||||
}
|
||||
netgen::log echo off
|
||||
if {$doEquatePins} {
|
||||
# Match pins
|
||||
if {$dolist == 1} {
|
||||
if {$forceMatch} {
|
||||
set result [equate -list -force pins "$fnum1 [lindex $endval 0]" \
|
||||
"$fnum2 [lindex $endval 1]"]
|
||||
} else {
|
||||
set result [equate -list pins "$fnum1 [lindex $endval 0]" \
|
||||
"$fnum2 [lindex $endval 1]"]
|
||||
}
|
||||
} else {
|
||||
if {$forceMatch} {
|
||||
set result [equate -force 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]"
|
||||
}
|
||||
# Do not set pinMismatch for black boxes
|
||||
if {$result < 0} {
|
||||
if {$result == -1 && [netgen::print queue] != {} && $forceMatch != 1} {
|
||||
# flatten pin mismatch, but not empty cells (-2) or top cell or
|
||||
# cells prohibited from flattening.
|
||||
set doFlatten 1
|
||||
}
|
||||
} elseif {[netgen::print queue] == {} && $result == 0} {
|
||||
set pinMismatch 1
|
||||
}
|
||||
}
|
||||
if {$doFlatten} {
|
||||
netgen::log echo on
|
||||
netgen::log put " Flattening non-matched subcircuits $endval\n"
|
||||
netgen::log echo off
|
||||
netgen::flatten class "[lindex $endval 0] $fnum1"
|
||||
netgen::flatten class "[lindex $endval 1] $fnum2"
|
||||
}
|
||||
|
||||
if {$dolist == 1} {
|
||||
catch {lappend lvs_final $lvs_out}
|
||||
set lvs_out {}
|
||||
@@ -566,12 +667,23 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||
set endval [netgen::compare hierarchical]
|
||||
}
|
||||
}
|
||||
netgen::log echo off
|
||||
puts stdout "Result: " nonewline
|
||||
netgen::log echo on
|
||||
verify only
|
||||
netgen::log put "\nFinal result: "
|
||||
if {$pinMismatch || $childMismatch} {
|
||||
if {$childMismatch} {
|
||||
netgen::log put "Subcell(s) failed matching.\n"
|
||||
}
|
||||
if {$pinMismatch} {
|
||||
netgen::log put "Top level cell failed pin matching.\n"
|
||||
}
|
||||
} else {
|
||||
verify only
|
||||
}
|
||||
if {$properr != {}} {
|
||||
netgen::log put "The following cells had property errors: $properr\n"
|
||||
netgen::log put "\nThe following cells had property errors:\n " [regsub -all { } $properr "\n "] "\n"
|
||||
}
|
||||
if {$matcherr != {}} {
|
||||
netgen::log put "\nThe following subcells failed to match:\n " [regsub -all { } $matcherr "\n "] "\n"
|
||||
}
|
||||
if {$dolog} {
|
||||
netgen::log end
|
||||
|
||||
+375
-72
@@ -32,6 +32,9 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include "print.h"
|
||||
#include "query.h" /* for ElementNodes() */
|
||||
#include "hash.h"
|
||||
#include "xilinx.h"
|
||||
#include "tech.h"
|
||||
#include "flatten.h"
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
@@ -85,6 +88,7 @@ int _netcmp_compare(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_iterate(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_summary(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_print(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_format(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_run(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_verify(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_automorphs(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
@@ -93,6 +97,7 @@ int _netcmp_ignore(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_permute(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_property(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_exhaustive(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_symmetry(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_restart(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_global(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_convert(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
@@ -199,6 +204,9 @@ Command netcmp_cmds[] = {
|
||||
{"print", _netcmp_print,
|
||||
"\n "
|
||||
"print netcomp internal data structure"},
|
||||
{"format", _netcmp_format,
|
||||
"<col1_width> <col2_width>\n "
|
||||
"set width of formatted output"},
|
||||
{"run", _netcmp_run,
|
||||
"[converge|resolve]\n "
|
||||
"converge: run netcomp to completion (convergence)\n "
|
||||
@@ -240,6 +248,8 @@ Command netcmp_cmds[] = {
|
||||
{"exhaustive", _netcmp_exhaustive,
|
||||
"\n "
|
||||
"toggle exhaustive subdivision"},
|
||||
{"symmetry", _netcmp_symmetry,
|
||||
"(deprecated)"},
|
||||
{"restart", _netcmp_restart,
|
||||
"\n "
|
||||
"start over (reset data structures)"},
|
||||
@@ -969,7 +979,7 @@ _netgen_writenet(ClientData clientData,
|
||||
SpiceCell(repstr, filenum, "");
|
||||
break;
|
||||
case VERILOG_IDX:
|
||||
VerilogModule(repstr, filenum, "");
|
||||
VerilogTop(repstr, filenum, "");
|
||||
break;
|
||||
case WOMBAT_IDX:
|
||||
Wombat(repstr,NULL);
|
||||
@@ -1046,6 +1056,12 @@ _netgen_flatten(ClientData clientData,
|
||||
FlattenInstancesOf(repstr, filenum);
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv, "prohibit") || !strcmp(argv, "deny")) {
|
||||
tp = GetTopCell(filenum);
|
||||
Printf("Will not flatten instances of %s in file %s\n", repstr, tp->name);
|
||||
/* Mark cell as placeholder so it will not be flattened */
|
||||
tp->flags |= CELL_PLACEHOLDER;
|
||||
}
|
||||
else {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "class valid_cellname");
|
||||
return TCL_ERROR;
|
||||
@@ -1528,23 +1544,24 @@ int
|
||||
_netgen_model(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
{
|
||||
struct nlist *tp;
|
||||
struct nlist *tp, *tp2;
|
||||
char *model, *retclass;
|
||||
unsigned char class;
|
||||
int fnum = -1;
|
||||
int result, index, nports;
|
||||
int result, index, nports, nports2;
|
||||
|
||||
char *modelclasses[] = {
|
||||
"undefined", "nmos", "pmos", "pnp", "npn",
|
||||
"resistor", "capacitor", "diode",
|
||||
"inductor", "module", "blackbox", "xline",
|
||||
"moscap", "mosfet", "bjt", "subcircuit", NULL
|
||||
"moscap", "mosfet", "bjt", "subcircuit", "copy",
|
||||
NULL
|
||||
};
|
||||
enum OptionIdx {
|
||||
UNDEF_IDX, NMOS_IDX, PMOS_IDX, PNP_IDX, NPN_IDX,
|
||||
RES_IDX, CAP_IDX, DIODE_IDX, INDUCT_IDX,
|
||||
MODULE_IDX, BLACKBOX_IDX, XLINE_IDX, MOSCAP_IDX,
|
||||
MOSFET_IDX, BJT_IDX, SUBCKT_IDX
|
||||
MOSFET_IDX, BJT_IDX, SUBCKT_IDX, COPY_IDX
|
||||
};
|
||||
|
||||
if (objc != 3 && objc != 2) {
|
||||
@@ -1576,7 +1593,7 @@ _netgen_model(ClientData clientData,
|
||||
|
||||
if (objc == 3) {
|
||||
model = Tcl_GetString(objv[2]);
|
||||
nports = NumberOfPorts(model);
|
||||
nports = NumberOfPorts(model, fnum);
|
||||
|
||||
if (Tcl_GetIndexFromObj(interp, objv[2], (CONST84 char **)modelclasses,
|
||||
"class", 0, &index) != TCL_OK) {
|
||||
@@ -1640,6 +1657,40 @@ _netgen_model(ClientData clientData,
|
||||
break;
|
||||
case SUBCKT_IDX:
|
||||
class = CLASS_SUBCKT;
|
||||
break;
|
||||
case COPY_IDX:
|
||||
/* "copy" is not a class, but indicates that the cell, */
|
||||
/* if undefined or a module, should have its class */
|
||||
/* taken from the other circuit, if that circuit has a */
|
||||
/* cell of the same name. */
|
||||
if (Circuit1 == NULL || Circuit2 == NULL) {
|
||||
Tcl_SetResult(interp, "Circuits have not been queued for comparison.",
|
||||
NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (tp == Circuit1) {
|
||||
tp2 = LookupCellFile(tp->name, Circuit2->file);
|
||||
nports2 = NumberOfPorts(tp2->name, Circuit2->file);
|
||||
}
|
||||
else if (tp == Circuit2) {
|
||||
tp2 = LookupCellFile(tp->name, Circuit1->file);
|
||||
nports2 = NumberOfPorts(tp2->name, Circuit1->file);
|
||||
}
|
||||
else {
|
||||
Tcl_SetResult(interp, "The referenced netlist is not being compared.",
|
||||
NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
/* Should a non-matching number of ports be considered a fatal error? */
|
||||
// if (nports2 != nports) {
|
||||
// Tcl_SetResult(interp, "The number of ports for this cell does not "
|
||||
// "match between netlists.", NULL);
|
||||
// return TCL_ERROR;
|
||||
// }
|
||||
|
||||
class = tp2->class;
|
||||
/* To do (maybe): Rename tp ports to match tp2? */
|
||||
|
||||
break;
|
||||
}
|
||||
tp->class = class;
|
||||
@@ -1886,9 +1937,17 @@ _netgen_log(ClientData clientData,
|
||||
switch(index) {
|
||||
case START_IDX:
|
||||
LoggingFile = fopen(LogFileName, "w");
|
||||
if (!LoggingFile) {
|
||||
Tcl_SetResult(interp, "Could not open log file.", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
break;
|
||||
case RESUME_IDX:
|
||||
LoggingFile = fopen(LogFileName, "a");
|
||||
if (!LoggingFile) {
|
||||
Tcl_SetResult(interp, "Could not open log file.", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
break;
|
||||
case END_IDX:
|
||||
fclose(LoggingFile);
|
||||
@@ -1897,6 +1956,10 @@ _netgen_log(ClientData clientData,
|
||||
case RESET_IDX:
|
||||
fclose(LoggingFile);
|
||||
LoggingFile = fopen(LogFileName, "w");
|
||||
if (!LoggingFile) {
|
||||
Tcl_SetResult(interp, "Could not open log file.", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
break;
|
||||
case SUSPEND_IDX:
|
||||
fclose(LoggingFile);
|
||||
@@ -1971,6 +2034,62 @@ _netgen_printmem(ClientData clientData,
|
||||
}
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
/* Function name: _netcmp_format */
|
||||
/* Syntax: */
|
||||
/* netgen::format [col1_width [col2_width]] */
|
||||
/* Formerly: (none) */
|
||||
/* Results: */
|
||||
/* Side Effects: */
|
||||
/*------------------------------------------------------*/
|
||||
|
||||
int
|
||||
_netcmp_format(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
{
|
||||
int col1_width = 41, col2_width = 41;
|
||||
|
||||
if (objc > 1) {
|
||||
if (Tcl_GetIntFromObj(interp, objv[1], &col1_width) != TCL_OK)
|
||||
return TCL_ERROR;
|
||||
if (objc > 2) {
|
||||
if (Tcl_GetIntFromObj(interp, objv[2], &col2_width) != TCL_OK)
|
||||
return TCL_ERROR;
|
||||
} else {
|
||||
/* If only one argument is given, then apply it to both columns */
|
||||
col2_width = col1_width;
|
||||
}
|
||||
|
||||
if (col1_width <= 0 || col2_width <= 0) {
|
||||
Tcl_SetResult(interp, "Column width cannot be zero or less\n", NULL);
|
||||
}
|
||||
|
||||
// Default values for left and right columns are 43 and 87
|
||||
left_col_end = col1_width + 2;
|
||||
right_col_end = left_col_end + col2_width + 3;
|
||||
}
|
||||
else if (objc == 1) {
|
||||
Tcl_Obj *lobj, *tobj;
|
||||
|
||||
col1_width = left_col_end - 2;
|
||||
col2_width = right_col_end - col1_width - 5;
|
||||
|
||||
lobj = Tcl_NewListObj(0, NULL);
|
||||
|
||||
tobj = Tcl_NewIntObj(col1_width);
|
||||
Tcl_ListObjAppendElement(interp, lobj, Tcl_NewIntObj(col1_width));
|
||||
Tcl_ListObjAppendElement(interp, lobj, Tcl_NewIntObj(col2_width));
|
||||
|
||||
Tcl_SetObjResult(interp, lobj);
|
||||
return TCL_OK;
|
||||
}
|
||||
else {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "[col1_width [col2_width]]");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
/* The following code breaks up the NETCOMP() command */
|
||||
/* from netcmp.c into individual functions w/arguments */
|
||||
@@ -1994,8 +2113,9 @@ _netcmp_compare(ClientData clientData,
|
||||
int dohierarchy = FALSE;
|
||||
int assignonly = FALSE;
|
||||
int argstart = 1, qresult, llen, result;
|
||||
int hascontents1, hascontents2;
|
||||
struct Correspond *nextcomp;
|
||||
struct nlist *tp;
|
||||
struct nlist *tp1 = NULL, *tp2 = NULL;
|
||||
Tcl_Obj *flist = NULL;
|
||||
|
||||
if (objc > 1) {
|
||||
@@ -2038,24 +2158,24 @@ _netcmp_compare(ClientData clientData,
|
||||
}
|
||||
else if ((objc - argstart) == 2) {
|
||||
|
||||
result = CommonParseCell(interp, objv[argstart], &tp, &fnum1);
|
||||
result = CommonParseCell(interp, objv[argstart], &tp1, &fnum1);
|
||||
if (result != TCL_OK) return TCL_ERROR;
|
||||
else if (fnum1 == -1) {
|
||||
Tcl_SetResult(interp, "Cannot use wildcard with compare command.\n",
|
||||
NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
name1 = tp->name;
|
||||
name1 = tp1->name;
|
||||
argstart++;
|
||||
|
||||
result = CommonParseCell(interp, objv[argstart], &tp, &fnum2);
|
||||
result = CommonParseCell(interp, objv[argstart], &tp2, &fnum2);
|
||||
if (result != TCL_OK) return TCL_ERROR;
|
||||
else if (fnum2 == -1) {
|
||||
Tcl_SetResult(interp, "Cannot use wildcard with compare command.\n",
|
||||
NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
name2 = tp->name;
|
||||
name2 = tp2->name;
|
||||
|
||||
if (dohierarchy) {
|
||||
RemoveCompareQueue();
|
||||
@@ -2094,11 +2214,40 @@ _netcmp_compare(ClientData clientData,
|
||||
ConvertGlobals(name2, fnum2);
|
||||
}
|
||||
|
||||
CreateTwoLists(name1, fnum1, name2, fnum2, dolist);
|
||||
while (PrematchLists(name1, fnum1, name2, fnum2) > 0) {
|
||||
Fprintf(stdout, "Making another compare attempt.\n");
|
||||
CreateTwoLists(name1, fnum1, name2, fnum2, dolist);
|
||||
tp1 = LookupCellFile(name1, fnum1);
|
||||
tp2 = LookupCellFile(name2, fnum2);
|
||||
|
||||
hascontents1 = HasContents(tp1);
|
||||
hascontents2 = HasContents(tp2);
|
||||
|
||||
if (hascontents1 && !hascontents2 && (tp2->flags & CELL_PLACEHOLDER)) {
|
||||
Fprintf(stdout, "\nCircuit 2 cell %s is a black box; will not flatten "
|
||||
"Circuit 1\n", name2);
|
||||
}
|
||||
else if (hascontents2 && !hascontents1 && (tp1->flags & CELL_PLACEHOLDER)) {
|
||||
Fprintf(stdout, "\nCircuit 1 cell %s is a black box; will not flatten "
|
||||
"Circuit 2\n", name1);
|
||||
}
|
||||
else if (!hascontents1 && !hascontents2 && (tp1->flags & CELL_PLACEHOLDER)
|
||||
&& (tp2->flags & CELL_PLACEHOLDER)) {
|
||||
/* Two empty subcircuits, don't flatten anything */
|
||||
Fprintf(stdout, "\nCircuit 1 cell %s and Circuit 2 cell %s are black"
|
||||
" boxes.\n", name1, name2);
|
||||
}
|
||||
else {
|
||||
FlattenUnmatched(tp1, name1, 1, 0);
|
||||
FlattenUnmatched(tp2, name2, 1, 0);
|
||||
DescribeContents(name1, fnum1, name2, fnum2);
|
||||
|
||||
while (PrematchLists(name1, fnum1, name2, fnum2) > 0) {
|
||||
Fprintf(stdout, "Making another compare attempt.\n");
|
||||
Printf("Flattened mismatched instances and attempting compare again.\n");
|
||||
FlattenUnmatched(tp1, name1, 1, 0);
|
||||
FlattenUnmatched(tp2, name2, 1, 0);
|
||||
DescribeContents(name1, fnum1, name2, fnum2);
|
||||
}
|
||||
}
|
||||
CreateTwoLists(name1, fnum1, name2, fnum2, dolist);
|
||||
|
||||
// Return the names of the two cells being compared, if doing "compare
|
||||
// hierarchical". If "-list" was specified, then append the output
|
||||
@@ -2331,6 +2480,8 @@ _netcmp_run(ClientData clientData,
|
||||
else {
|
||||
enable_interrupt();
|
||||
while (!Iterate() && !InterruptPending);
|
||||
ExhaustiveSubdivision = 1;
|
||||
while (!Iterate() && !InterruptPending);
|
||||
if (dolist) {
|
||||
result = _netcmp_verify(clientData, interp, 2, objv - 1);
|
||||
}
|
||||
@@ -2349,38 +2500,40 @@ _netcmp_run(ClientData clientData,
|
||||
else {
|
||||
enable_interrupt();
|
||||
while (!Iterate() && !InterruptPending);
|
||||
ExhaustiveSubdivision = 1;
|
||||
while (!Iterate() && !InterruptPending);
|
||||
automorphisms = VerifyMatching();
|
||||
if (automorphisms == -1)
|
||||
Fprintf(stdout, "Netlists do not match.\n");
|
||||
else if (automorphisms == 0)
|
||||
Fprintf(stdout, "Netlists match uniquely.\n");
|
||||
else {
|
||||
if (automorphisms > 0) {
|
||||
// First try to resolve automorphisms uniquely using
|
||||
// property matching
|
||||
automorphisms = ResolveAutomorphsByProperty();
|
||||
if (automorphisms == 0)
|
||||
Fprintf(stdout, "Netlists match uniquely.\n");
|
||||
else {
|
||||
|
||||
if (automorphisms > 0) {
|
||||
// Next, attempt to resolve automorphisms uniquely by
|
||||
// using the pin names
|
||||
automorphisms = ResolveAutomorphsByPin();
|
||||
}
|
||||
|
||||
if (automorphisms == 0)
|
||||
Fprintf(stdout, "Netlists match uniquely.\n");
|
||||
else
|
||||
if (automorphisms > 0) {
|
||||
// Anything left is truly indistinguishable
|
||||
Fprintf(stdout, "Netlists match with %d symmetr%s.\n",
|
||||
automorphisms, (automorphisms == 1) ? "y" : "ies");
|
||||
|
||||
while ((automorphisms = ResolveAutomorphisms()) > 0);
|
||||
if (automorphisms == -1) Fprintf(stdout, "Netlists do not match.\n");
|
||||
else Fprintf(stdout, "Circuits match correctly.\n");
|
||||
while (ResolveAutomorphisms() > 0);
|
||||
}
|
||||
}
|
||||
if (PropertyErrorDetected) {
|
||||
Fprintf(stdout, "There were property errors.\n");
|
||||
PrintPropertyResults(dolist);
|
||||
|
||||
if (automorphisms == -1)
|
||||
Fprintf(stdout, "Netlists do not match.\n");
|
||||
else if (automorphisms == -2)
|
||||
Fprintf(stdout, "Netlists match uniquely with port errors.\n");
|
||||
else {
|
||||
if (automorphisms == 0)
|
||||
Fprintf(stdout, "Netlists match uniquely");
|
||||
else
|
||||
Fprintf(stdout, "Netlists match with %d symmetr%s",
|
||||
automorphisms, (automorphisms == 1) ? "y" : "ies");
|
||||
if (PropertyErrorDetected) {
|
||||
Fprintf(stdout, " with property errors.\n");
|
||||
PrintPropertyResults(dolist);
|
||||
}
|
||||
else
|
||||
Fprintf(stdout, ".\n");
|
||||
}
|
||||
disable_interrupt();
|
||||
}
|
||||
@@ -2398,8 +2551,14 @@ _netcmp_run(ClientData clientData,
|
||||
/* all, or no option. */
|
||||
/* Formerly: v */
|
||||
/* Results: */
|
||||
/* For only, equivalent, unique: Return 1 if */
|
||||
/* verified, zero if not. */
|
||||
/* For only, equivalent, unique: Return */
|
||||
/* 1: verified */
|
||||
/* 0: not verified */
|
||||
/* -1: no elements or nodes */
|
||||
/* -3: verified with property error */
|
||||
/* equiv option */
|
||||
/* -2: pin mismatch */
|
||||
/* */
|
||||
/* Side Effects: */
|
||||
/* For options elements, nodes, and all without */
|
||||
/* option -list: Write output to log file. */
|
||||
@@ -2493,13 +2652,21 @@ _netcmp_verify(ClientData clientData,
|
||||
else
|
||||
Fprintf(stdout, "Netlists do not match.\n");
|
||||
}
|
||||
else if (automorphisms == -2) {
|
||||
if (index == EQUIV_IDX)
|
||||
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1));
|
||||
else if (index == UNIQUE_IDX)
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(-2));
|
||||
else if (index > 0)
|
||||
Fprintf(stdout, "Circuits match uniquely with port errors.\n");
|
||||
}
|
||||
else {
|
||||
if (automorphisms) {
|
||||
if (index == EQUIV_IDX)
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj((int)automorphisms));
|
||||
else if (index == UNIQUE_IDX)
|
||||
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
|
||||
else
|
||||
else if (index > 0)
|
||||
Printf("Circuits match with %d symmetr%s.\n",
|
||||
automorphisms, (automorphisms == 1) ? "y" : "ies");
|
||||
}
|
||||
@@ -2508,11 +2675,13 @@ _netcmp_verify(ClientData clientData,
|
||||
if (PropertyErrorDetected == 0)
|
||||
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1));
|
||||
else
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(2));
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(-3));
|
||||
}
|
||||
else {
|
||||
else if (index > 0) {
|
||||
Fprintf(stdout, "Circuits match uniquely.\n");
|
||||
if (PropertyErrorDetected != 0)
|
||||
if (PropertyErrorDetected == 0)
|
||||
Fprintf(stdout, ".\n");
|
||||
else
|
||||
Fprintf(stdout, "Property errors were found.\n");
|
||||
}
|
||||
}
|
||||
@@ -2730,11 +2899,13 @@ _netcmp_equate(ClientData clientData,
|
||||
char *name1 = NULL, *name2 = NULL, *optstart;
|
||||
struct nlist *tp1, *tp2, *SaveC1, *SaveC2;
|
||||
struct objlist *ob1, *ob2;
|
||||
struct ElementClass *saveEclass = NULL;
|
||||
struct NodeClass *saveNclass = NULL;
|
||||
int file1, file2;
|
||||
int i, l1, l2, ltest, lent, dolist = 0;
|
||||
int i, l1, l2, ltest, lent, dolist = 0, doforce = 0, dounique = 0;
|
||||
Tcl_Obj *tobj1, *tobj2, *tobj3;
|
||||
|
||||
if (objc > 1) {
|
||||
while (objc > 1) {
|
||||
optstart = Tcl_GetString(objv[1]);
|
||||
if (*optstart == '-') optstart++;
|
||||
if (!strcmp(optstart, "list")) {
|
||||
@@ -2742,6 +2913,18 @@ _netcmp_equate(ClientData clientData,
|
||||
objv++;
|
||||
objc--;
|
||||
}
|
||||
else if (!strcmp(optstart, "force")) {
|
||||
doforce = 1;
|
||||
objv++;
|
||||
objc--;
|
||||
}
|
||||
else if (!strcmp(optstart, "unique")) {
|
||||
dounique = 1;
|
||||
objv++;
|
||||
objc--;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if ((objc != 2) && (objc != 4) && (objc != 6)) {
|
||||
@@ -2899,16 +3082,45 @@ _netcmp_equate(ClientData clientData,
|
||||
break;
|
||||
|
||||
case PINS_IDX:
|
||||
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",
|
||||
name1, name2);
|
||||
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
|
||||
return TCL_OK;
|
||||
if ((ElementClasses != NULL) && (doforce == TRUE)) {
|
||||
saveEclass = ElementClasses;
|
||||
saveNclass = NodeClasses;
|
||||
ElementClasses = NULL;
|
||||
NodeClasses = NULL;
|
||||
}
|
||||
else if (ElementClasses == NULL) {
|
||||
/* This has been called outside of a netlist compare, */
|
||||
if ((ElementClasses == NULL) && (auto_blackbox == FALSE)) {
|
||||
if (CurrentCell == NULL) {
|
||||
Fprintf(stderr, "Equate elements: no current cell.\n");
|
||||
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
|
||||
return TCL_OK;
|
||||
}
|
||||
else if ((tp1->flags & CELL_PLACEHOLDER) ||
|
||||
(tp2->flags & CELL_PLACEHOLDER)) {
|
||||
if (tp1->flags & CELL_PLACEHOLDER) {
|
||||
Fprintf(stdout, "Warning: Equate pins: cell %s "
|
||||
"is a placeholder, treated as a black box.\n", name1);
|
||||
}
|
||||
if (tp2->flags & CELL_PLACEHOLDER) {
|
||||
Fprintf(stdout, "Warning: Equate pins: cell %s "
|
||||
"is a placeholder, treated as a black box.\n", name2);
|
||||
}
|
||||
// If a cell in either circuit is marked as a black box, then
|
||||
// the cells in both circuits should be marked as a black box.
|
||||
tp1->flags |= CELL_PLACEHOLDER;
|
||||
tp2->flags |= CELL_PLACEHOLDER;
|
||||
}
|
||||
else if (doforce != TRUE) {
|
||||
/* When doforce is TRUE, ElementClass has been set to NULL
|
||||
* even though circuits contain elements, so this message
|
||||
* is not correct.
|
||||
*/
|
||||
Fprintf(stdout, "Equate pins: cell %s and/or %s "
|
||||
"has no elements.\n", name1, name2);
|
||||
/* This is not necessarily an error, so go ahead and match pins. */
|
||||
}
|
||||
}
|
||||
if (ElementClasses == NULL) {
|
||||
/* This may have 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 */
|
||||
@@ -2933,6 +3145,13 @@ _netcmp_equate(ClientData clientData,
|
||||
else if (result > 0) {
|
||||
Fprintf(stdout, "Cell pin lists are equivalent.\n");
|
||||
}
|
||||
else if (result == -1) {
|
||||
Fprintf(stdout, "Cell pin lists for %s and %s do not match.\n",
|
||||
name1, name2);
|
||||
}
|
||||
else if (result == -2) {
|
||||
Fprintf(stdout, "Attempt to match empty cell to non-empty cell.\n");
|
||||
}
|
||||
else {
|
||||
Fprintf(stdout, "Cell pin lists for %s and %s altered to match.\n",
|
||||
name1, name2);
|
||||
@@ -2942,6 +3161,12 @@ _netcmp_equate(ClientData clientData,
|
||||
/* Recover temporarily set global variables (see above) */
|
||||
Circuit1 = SaveC1;
|
||||
Circuit2 = SaveC2;
|
||||
|
||||
/* Recover ElementClasses if forcing pins on mismatched circuits */
|
||||
if (doforce == TRUE) {
|
||||
ElementClasses = saveEclass;
|
||||
NodeClasses = saveNclass;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -3122,19 +3347,9 @@ _netcmp_equate(ClientData clientData,
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now that all pins are assigned by name, reorder */
|
||||
/* the pin lists of the 2nd cell to match the */
|
||||
/* order of the 1st. */
|
||||
|
||||
/* Reorder the pin lists of instances of the 2nd */
|
||||
/* cell to match the order of the 1st. */
|
||||
|
||||
// pindata.cell2 = tp2;
|
||||
// RecurseCellHashTable2(pinorder, (void *)(&pindata));
|
||||
}
|
||||
|
||||
if (EquivalenceClasses(tp1->name, file1, tp2->name, file2)) {
|
||||
if (EquivalenceClasses(tp1->name, file1, tp2->name, file2, dounique)) {
|
||||
Fprintf(stdout, "Device classes %s and %s are equivalent.\n",
|
||||
tp1->name, tp2->name);
|
||||
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1));
|
||||
@@ -3157,6 +3372,8 @@ _netcmp_equate(ClientData clientData,
|
||||
/* add --- add new property */
|
||||
/* remove --- delete existing property */
|
||||
/* tolerance --- set property tolerance */
|
||||
/* associate --- associate property with a pin */
|
||||
/* topology --- set exact/relaxed matching */
|
||||
/* merge --- (deprecated) */
|
||||
/* or */
|
||||
/* netgen::property default */
|
||||
@@ -3195,19 +3412,19 @@ _netcmp_property(ClientData clientData,
|
||||
|
||||
char *options[] = {
|
||||
"add", "create", "remove", "delete", "tolerance", "merge", "serial",
|
||||
"series", "parallel", NULL
|
||||
"series", "parallel", "associate", "topology", NULL
|
||||
};
|
||||
enum OptionIdx {
|
||||
ADD_IDX, CREATE_IDX, REMOVE_IDX, DELETE_IDX, TOLERANCE_IDX, MERGE_IDX,
|
||||
SERIAL_IDX, SERIES_IDX, PARALLEL_IDX
|
||||
SERIAL_IDX, SERIES_IDX, PARALLEL_IDX, ASSOCIATE_IDX, TOPOLOGY_IDX
|
||||
};
|
||||
int result, index, idx2;
|
||||
|
||||
char *suboptions[] = {
|
||||
"integer", "double", "value", "string", NULL
|
||||
"integer", "double", "value", "string", "expression", NULL
|
||||
};
|
||||
enum SubOptionIdx {
|
||||
INTEGER_IDX, DOUBLE_IDX, VALUE_IDX, STRING_IDX
|
||||
INTEGER_IDX, DOUBLE_IDX, VALUE_IDX, STRING_IDX, EXPRESSION_IDX
|
||||
};
|
||||
|
||||
/* Note: "merge" has been deprecated, but kept for backwards compatibility. */
|
||||
@@ -3244,6 +3461,10 @@ _netcmp_property(ClientData clientData,
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
char *topo[] = {
|
||||
"strict", "relaxed", NULL
|
||||
};
|
||||
|
||||
/* Check for special command "property default" */
|
||||
if ((objc == 2) && (!strcmp(Tcl_GetString(objv[1]), "default"))) {
|
||||
|
||||
@@ -3301,9 +3522,15 @@ _netcmp_property(ClientData clientData,
|
||||
GlobalParallelNone = FALSE;
|
||||
SetParallelCombine(TRUE);
|
||||
}
|
||||
else if (!strcmp(Tcl_GetString(objv[2]), "connected")) {
|
||||
GlobalParallelOpen = FALSE;
|
||||
}
|
||||
else if (!strcmp(Tcl_GetString(objv[2]), "open")) {
|
||||
GlobalParallelOpen = TRUE;
|
||||
}
|
||||
else {
|
||||
Tcl_SetResult(interp, "Bad option, should be property parallel none|all",
|
||||
NULL);
|
||||
Tcl_SetResult(interp, "Bad option, should be property parallel "
|
||||
"none|all|connected", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return TCL_OK;
|
||||
@@ -3323,6 +3550,36 @@ _netcmp_property(ClientData clientData,
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
else if ((objc > 1) && (!strcmp(Tcl_GetString(objv[1]), "topology"))) {
|
||||
if (objc == 2) {
|
||||
if (ExactTopology)
|
||||
Tcl_SetResult(interp, "Strict topology property matching.",
|
||||
NULL);
|
||||
else
|
||||
Tcl_SetResult(interp, "Relaxed topology property matching.",
|
||||
NULL);
|
||||
}
|
||||
else if (objc == 3) {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[2],
|
||||
(CONST84 char **)topo,
|
||||
"topology", 0, &idx2) == TCL_OK) {
|
||||
if (idx2 == 0)
|
||||
ExactTopology = TRUE;
|
||||
else if (idx2 == 1)
|
||||
ExactTopology = FALSE;
|
||||
else {
|
||||
Tcl_SetResult(interp, "Topology matching type must be "
|
||||
"'strict' or 'relaxed'.", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "strict|relaxed");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
result = CommonParseCell(interp, objv[1], &tp, &fnum);
|
||||
if (result != TCL_OK) return result;
|
||||
@@ -3590,6 +3847,11 @@ _netcmp_property(ClientData clientData,
|
||||
PropertyString(tp->name, fnum,
|
||||
Tcl_GetString(tobj1), ival, NULL);
|
||||
break;
|
||||
case EXPRESSION_IDX:
|
||||
PropertyString(tp->name, fnum,
|
||||
Tcl_GetString(tobj1), 0,
|
||||
Tcl_GetString(tobj3));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -3611,6 +3873,29 @@ _netcmp_property(ClientData clientData,
|
||||
}
|
||||
break;
|
||||
|
||||
case ASSOCIATE_IDX:
|
||||
if (objc == 3) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "{property_key pin_name} ...");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
for (i = 3; i < objc; i++) {
|
||||
// Each value must be a duplet
|
||||
result = Tcl_ListObjLength(interp, objv[i], &llen);
|
||||
if ((result != TCL_OK) || (llen != 2)) {
|
||||
Tcl_SetResult(interp, "Not a {key pin} pair list.",
|
||||
NULL);
|
||||
}
|
||||
else {
|
||||
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;
|
||||
PropertyAssociatePin(tp->name, fnum, Tcl_GetString(tobj1),
|
||||
Tcl_GetString(tobj2));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TOLERANCE_IDX:
|
||||
if (objc == 3) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "{property_key tolerance} ...");
|
||||
@@ -3710,6 +3995,7 @@ _netcmp_property(ClientData clientData,
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return TCL_OK;
|
||||
@@ -3859,6 +4145,23 @@ _netcmp_permute(ClientData clientData,
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
/* Function name: _netcmp_symmetry */
|
||||
/* Syntax: netgen::symmetry [fast|full] */
|
||||
/* Formerly: x */
|
||||
/* Results: */
|
||||
/* Side Effects: */
|
||||
/* Notes: Deprecated, retained for compatibility. */
|
||||
/*------------------------------------------------------*/
|
||||
|
||||
int
|
||||
_netcmp_symmetry(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
{
|
||||
Printf("Symmetry breaking method has been deprecated.\n");
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
/* Function name: _netcmp_exhaustive */
|
||||
/* Syntax: netgen::exhaustive [on|off] */
|
||||
@@ -3880,7 +4183,7 @@ _netcmp_exhaustive(ClientData clientData,
|
||||
int result, index;
|
||||
|
||||
if (objc == 1)
|
||||
index = YES_IDX;
|
||||
index = -1;
|
||||
else {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)yesno,
|
||||
"option", 0, &index) != TCL_OK)
|
||||
|
||||
Reference in New Issue
Block a user