mirror of
https://github.com/RTimothyEdwards/netgen.git
synced 2026-08-22 22:17:22 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bcbc736b51 | ||
|
|
615c55cbe2 | ||
|
|
f5f1240073 | ||
|
|
87d8759a69 | ||
|
|
02d7a1bd01 | ||
|
|
1efa054ac1 | ||
|
|
7878b3cfbc | ||
|
|
609d1de250 | ||
|
|
7f727e6674 | ||
|
|
47c3b34612 | ||
|
|
d111fa0a3b | ||
|
|
66317c9848 | ||
|
|
eeb3c0e5c6 | ||
|
|
490f9f7dbc | ||
|
|
178b172c06 | ||
|
|
40cf82c2cb | ||
|
|
1ac2b592fb | ||
|
|
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 |
@@ -7,6 +7,7 @@ config.log
|
||||
scripts/config.log
|
||||
config.status
|
||||
scripts/config.status
|
||||
python/lvs_manager.py
|
||||
*.o
|
||||
*.so
|
||||
*~
|
||||
|
||||
@@ -91,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);
|
||||
|
||||
+226
-66
@@ -53,7 +53,7 @@ void flattenCell(char *name, int file)
|
||||
struct nlist *ChildCell;
|
||||
struct objlist *tmp, *ob2, *ob3;
|
||||
int notdone, rnodenum;
|
||||
char tmpstr[200];
|
||||
char tmpstr[MAX_STR_LEN];
|
||||
int nextnode, oldmax;
|
||||
#if !OLDPREFIX
|
||||
int prefixlength;
|
||||
@@ -66,9 +66,13 @@ void flattenCell(char *name, int file)
|
||||
else
|
||||
ThisCell = LookupCellFile(name, file);
|
||||
if (ThisCell == NULL) {
|
||||
Printf("No cell %s found.\n", name);
|
||||
Printf("No cell %s (%d) found.\n", name, file);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Placeholder cells must not be flattened */
|
||||
if (ThisCell->flags & CELL_PLACEHOLDER) return;
|
||||
|
||||
FreeNodeNames(ThisCell);
|
||||
|
||||
ParentParams = ThisCell->cell;
|
||||
@@ -239,6 +243,13 @@ void flattenCell(char *name, int file)
|
||||
ThisCell->dumped = 1; /* indicate cell has been flattened */
|
||||
}
|
||||
|
||||
/* Structure used to keep track of nodes needing checking */
|
||||
|
||||
struct linkednode {
|
||||
int node;
|
||||
struct linkednode *next;
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* flattenInstancesOf -- */
|
||||
/* */
|
||||
@@ -261,6 +272,7 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
|
||||
struct nlist *ThisCell;
|
||||
struct nlist *ChildCell;
|
||||
struct objlist *tmp, *ob2, *ob3;
|
||||
struct linkednode *checknodes = NULL, *newlnode, *chknode;
|
||||
int notdone, rnodenum;
|
||||
char tmpstr[1024];
|
||||
int nextnode, oldmax, numflat = 0;
|
||||
@@ -278,16 +290,20 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
|
||||
}
|
||||
else {
|
||||
if (Debug)
|
||||
Printf("Flattening instances of %s within cell: %s\n", instance, name);
|
||||
Printf("Flattening instances of %s within cell: %s (%d)\n", instance,
|
||||
name, fnum);
|
||||
if (fnum == -1)
|
||||
ThisCell = LookupCell(name);
|
||||
else
|
||||
ThisCell = LookupCellFile(name, fnum);
|
||||
if (ThisCell == NULL) {
|
||||
Printf("No cell %s found.\n", name);
|
||||
Printf("No cell %s (%d) found.\n", name, fnum);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Placeholder cells must not be flattened */
|
||||
if (ThisCell->flags & CELL_PLACEHOLDER) return 0;
|
||||
|
||||
FreeNodeNames(ThisCell);
|
||||
|
||||
ParentParams = ThisCell->cell;
|
||||
@@ -372,22 +388,16 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
|
||||
|
||||
/* update node numbers in child to unique numbers */
|
||||
oldmax = 0;
|
||||
for (tmp = ChildStart; tmp != NULL; tmp = tmp->next)
|
||||
for (tmp = ChildStart; tmp != NULL; tmp = tmp->next) {
|
||||
if (tmp->node > oldmax) oldmax = tmp->node;
|
||||
if (nextnode <= oldmax) nextnode = oldmax + 1;
|
||||
|
||||
for (tmp = ChildStart; tmp != NULL; tmp = tmp->next)
|
||||
if (tmp->node <= oldmax && tmp->node > 0) {
|
||||
if (Debug) Printf("Update node %d --> %d\n", tmp->node, nextnode);
|
||||
UpdateNodeNumbers(ChildStart, tmp->node, nextnode);
|
||||
nextnode++;
|
||||
}
|
||||
if (tmp->node > 0) tmp->node += (nextnode - 1);
|
||||
}
|
||||
nextnode += oldmax;
|
||||
|
||||
/* copy nodenumbers of ports from parent */
|
||||
ob2 = ParentParams;
|
||||
for (tmp = ChildStart; tmp != NULL; tmp = tmp->next) {
|
||||
if (IsPort(tmp)) {
|
||||
if (tmp->node > 0) {
|
||||
for (tmp = ChildStart; tmp && IsPort(tmp); tmp = tmp->next) {
|
||||
if (tmp->node > 0) {
|
||||
if (ob2->node == -1) {
|
||||
|
||||
// Before commiting to attaching to a unconnected node, see
|
||||
@@ -413,17 +423,26 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
|
||||
Printf("Update node %d --> %d\n", tmp->node, ob2->node);
|
||||
}
|
||||
UpdateNodeNumbers(ChildStart, tmp->node, ob2->node);
|
||||
}
|
||||
}
|
||||
else if (tmp->node == -1) {
|
||||
/* Opposite case: If child port is an unconnected node, then */
|
||||
/* removing the instance may make the parent node become */
|
||||
/* unconnected. For now, just record the node number. At the */
|
||||
/* end we'll check if these nodes are actually disconnected. */
|
||||
newlnode = (struct linkednode *)MALLOC(sizeof(struct linkednode));
|
||||
newlnode->node = ob2->node;
|
||||
newlnode->next = checknodes;
|
||||
checknodes = newlnode;
|
||||
}
|
||||
|
||||
/* in pathological cases, the lengths of the port lists may
|
||||
* change. This is an error, but that is no reason to allow
|
||||
* the code to core dump. We avoid this by placing a
|
||||
* superfluous check on ob2->type
|
||||
*/
|
||||
if (ob2 != NULL) ob2 = ob2->next;
|
||||
/* in pathological cases, the lengths of the port lists may
|
||||
* change. This is an error, but that is no reason to allow
|
||||
* the code to core dump. We avoid this by placing a
|
||||
* superfluous check on ob2->type
|
||||
*/
|
||||
if (ob2 != NULL) ob2 = ob2->next;
|
||||
|
||||
if (ob2 == NULL) break;
|
||||
}
|
||||
if (ob2 == NULL) break;
|
||||
}
|
||||
|
||||
/* Using name == NULL to indicate that a .ext file is being */
|
||||
@@ -517,11 +536,10 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
|
||||
|
||||
/* Do property inheritance */
|
||||
|
||||
/* NOTE: Need to do: Check properties for M > 1 and decrement
|
||||
* and repeat without moving CurrentProp
|
||||
*/
|
||||
|
||||
if (CurrentProp) {
|
||||
int i, mval;
|
||||
struct valuelist *kv;
|
||||
|
||||
for (ob2 = ChildStart; ob2 != NULL; ob2=ob2->next) {
|
||||
|
||||
/* If the parent cell has properties to declare, then */
|
||||
@@ -529,10 +547,49 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
|
||||
/* spiceparams dictionary is active (during file */
|
||||
/* reading only). */
|
||||
|
||||
if (ob2->type == PROPERTY)
|
||||
if (ob2->type == PROPERTY) {
|
||||
ReduceExpressions(ob2, CurrentProp, ChildCell,
|
||||
(spiceparams.hashtab == NULL) ? 0 : 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for property M. If it exists and is greater than */
|
||||
/* one, reduce it and repeat; i.e., generate multiple */
|
||||
/* child instances to match the M value. Probably this */
|
||||
/* could be done quicker by just creating a new property */
|
||||
/* M for a single child. */
|
||||
|
||||
mval = 0;
|
||||
for (i = 0; ; i++) {
|
||||
kv = &(CurrentProp->instance.props[i]);
|
||||
if (kv->type == PROP_ENDLIST) break;
|
||||
if ((*matchfunc)(kv->key, "M")) {
|
||||
if (kv->type == PROP_INTEGER) {
|
||||
mval = kv->value.ival;
|
||||
kv->value.ival = mval - 1;
|
||||
break;
|
||||
}
|
||||
else if (kv->type == PROP_DOUBLE) {
|
||||
mval = (int)kv->value.dval;
|
||||
kv->value.dval = (double)mval - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mval > 1) {
|
||||
/* Put the child cell at the start of ChildObjList */
|
||||
if (ChildEnd) {
|
||||
ChildEnd->next = ChildObjList;
|
||||
ChildObjList = ChildStart;
|
||||
|
||||
/* Continue without moving CurrentProp */
|
||||
/* Note that if ChildEnd is NULL then the child cell
|
||||
* is optimized out and there is no need to do it
|
||||
* M times.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Repeat for each property record, as each property represents a
|
||||
* unique instance that must be flattened individually.
|
||||
@@ -597,6 +654,29 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
|
||||
NextObj = ParentParams;
|
||||
} /* repeat until no more instances found */
|
||||
}
|
||||
|
||||
/* Check nodes that may have become disconnected after child flattening */
|
||||
while (checknodes != NULL) {
|
||||
struct objlist *portnode = NULL;
|
||||
|
||||
chknode = checknodes;
|
||||
checknodes = checknodes->next;
|
||||
|
||||
for (ob3 = ThisCell->cell; ob3; ob3 = ob3->next) {
|
||||
if ((ob3->type != PORT) && (portnode == NULL))
|
||||
break;
|
||||
else if ((ob3->type == PORT) && (ob3->node == chknode->node))
|
||||
portnode = ob3;
|
||||
else if ((ob3->type >= FIRSTPIN) && (ob3->node == chknode->node))
|
||||
break;
|
||||
}
|
||||
if ((ob3 == NULL) && (portnode != NULL)) {
|
||||
/* Port became disconnected when child was flattened */
|
||||
portnode->node = -1;
|
||||
}
|
||||
FREE(chknode);
|
||||
}
|
||||
|
||||
CacheNodeNames(ThisCell);
|
||||
ThisCell->dumped = 1; /* indicate cell has been flattened */
|
||||
return numflat;
|
||||
@@ -688,7 +768,7 @@ void convertGlobalsOf(char *name, int fnum, char *instance)
|
||||
else
|
||||
ThisCell = LookupCellFile(name, fnum);
|
||||
if (ThisCell == NULL) {
|
||||
Printf("No cell %s found.\n", name);
|
||||
Printf("No cell %s (%d) found.\n", name, fnum);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1118,7 +1198,7 @@ int UniquePins(char *name, int filenum)
|
||||
ThisCell = LookupCellFile(name, filenum);
|
||||
|
||||
if (ThisCell == NULL) {
|
||||
Printf("No cell %s found.\n", name);
|
||||
Printf("No cell %s (%d) found.\n", name, filenum);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1135,12 +1215,33 @@ int UniquePins(char *name, int filenum)
|
||||
firstport = (struct objlist **)CALLOC(maxnode + 1, sizeof(struct objlist *));
|
||||
|
||||
portcount = FIRSTPIN;
|
||||
lob = NULL;
|
||||
for (ob = ThisCell->cell; ob != NULL; ob = ob->next) {
|
||||
if (ob->type != PORT) break;
|
||||
if (ob->node > 0) {
|
||||
nodecount[ob->node]++;
|
||||
if (nodecount[ob->node] == 2) {
|
||||
Printf("Duplicate pin %s in cell %s\n", ob->name, ThisCell->name);
|
||||
if (!(*matchfunc)(firstport[ob->node]->name, ob->name)) {
|
||||
Printf("Pins %s and %s are shorted in cell %s (%d)\n", ob->name,
|
||||
firstport[ob->node]->name, ThisCell->name, ThisCell->file);
|
||||
/* Do not count this as a duplicate pin. */
|
||||
nodecount[ob->node]--;
|
||||
/* Move the pin adjacent to the one it is shorted to (if it
|
||||
* isn't already); this will make the work of MatchPins() easier.
|
||||
*/
|
||||
if (firstport[ob->node]->next != ob) {
|
||||
lob->next = ob->next;
|
||||
ob->next = firstport[ob->node]->next;
|
||||
firstport[ob->node]->next = ob;
|
||||
ob = lob;
|
||||
}
|
||||
lob = ob;
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
Printf("Duplicate pin %s in cell %s (%d)\n", ob->name,
|
||||
ThisCell->name, filenum);
|
||||
}
|
||||
}
|
||||
if (nodecount[ob->node] > 1) {
|
||||
/* Remove this node; prep for removal by marking with UNKNOWN */
|
||||
@@ -1155,6 +1256,7 @@ int UniquePins(char *name, int filenum)
|
||||
}
|
||||
}
|
||||
portcount++;
|
||||
lob = ob;
|
||||
}
|
||||
|
||||
if (needscleanup)
|
||||
@@ -1339,7 +1441,7 @@ int CleanupPins(char *name, int filenum)
|
||||
ThisCell = LookupCellFile(name, filenum);
|
||||
|
||||
if (ThisCell == NULL) {
|
||||
Printf("No cell %s found.\n", name);
|
||||
Printf("No cell %s (%d) found.\n", name, filenum);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1421,6 +1523,22 @@ typedef struct ecomplist {
|
||||
ECompListPtr next;
|
||||
} ECompList;
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Determine if a cell contains at least one device or subcircuit */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
int
|
||||
HasContents(struct nlist *tc)
|
||||
{
|
||||
struct objlist *ob;
|
||||
|
||||
for (ob = tc->cell; ob; ob = ob->next)
|
||||
if (ob->type == FIRSTPIN)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
/* Survey the contents of a cell and sort into a hash */
|
||||
/*------------------------------------------------------*/
|
||||
@@ -1518,6 +1636,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
struct hashdict compdict;
|
||||
ECompare *ecomp, *ncomp;
|
||||
ECompList *list0X, *listX0;
|
||||
int hascontents1, hascontents2;
|
||||
int match, modified = 0;
|
||||
|
||||
if (file1 == -1)
|
||||
@@ -1533,6 +1652,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
if (tc1 == NULL || tc2 == NULL) return 0;
|
||||
|
||||
InitializeHashTable(&compdict, OBJHASHSIZE);
|
||||
listX0 = list0X = NULL;
|
||||
|
||||
// Gather information about instances of cell "name1"
|
||||
SurveyCell(tc1, &compdict, file1, file2, 0);
|
||||
@@ -1545,7 +1665,6 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
// in the hierarchy of each instance contain devices
|
||||
// or subcircuits that have more in the compared circuit.
|
||||
|
||||
listX0 = list0X = NULL;
|
||||
ecomp = (ECompare *)HashFirst(&compdict);
|
||||
while (ecomp != NULL) {
|
||||
|
||||
@@ -1582,25 +1701,29 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
}
|
||||
}
|
||||
else {
|
||||
match = 0;
|
||||
// cell exists in one circuit but not the other, so flatten it.
|
||||
// match = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
if (ecomp->cell1 && (ecomp->num1 > 0)) {
|
||||
Fprintf(stdout, "Flattening instances of %s in cell %s"
|
||||
if (ecomp->cell1 && (ecomp->num1 > 0) &&
|
||||
(!(ecomp->cell1->flags & CELL_PLACEHOLDER))) {
|
||||
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
|
||||
" makes a better match\n", ecomp->cell1->name,
|
||||
name1);
|
||||
name1, file1);
|
||||
flattenInstancesOf(name1, file1, ecomp->cell1->name);
|
||||
modified++;
|
||||
}
|
||||
if (ecomp->cell2 && (ecomp->num2 > 0)) {
|
||||
Fprintf(stdout, "Flattening instances of %s in cell %s"
|
||||
if (ecomp->cell2 && (ecomp->num2 > 0) &&
|
||||
(!(ecomp->cell2->flags & CELL_PLACEHOLDER))) {
|
||||
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
|
||||
" makes a better match\n", ecomp->cell2->name,
|
||||
name2);
|
||||
name2, file2);
|
||||
flattenInstancesOf(name2, file2, ecomp->cell2->name);
|
||||
modified++;
|
||||
}
|
||||
modified++;
|
||||
}
|
||||
|
||||
/* Reset or apply the count adjustments */
|
||||
@@ -1649,7 +1772,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
}
|
||||
|
||||
/* Case 2: Cell2 class is a subcircuit, and flattening */
|
||||
/* (it without regard to cell1) improves the matching. */
|
||||
/* it (without regard to cell1) improves the matching. */
|
||||
|
||||
else if ((ecomp->num1 != ecomp->num2) && (ecomp->cell2 != NULL) &&
|
||||
(ecomp->num2 != 0) && (ecomp->cell2->class == CLASS_SUBCKT)) {
|
||||
@@ -1677,13 +1800,21 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
if (ecomp->cell2) {
|
||||
Fprintf(stdout, "Flattening instances of %s in cell %s"
|
||||
|
||||
/* Don't flatten if cell1 is a black box, because it */
|
||||
/* can't also be flattened. */
|
||||
|
||||
if ((ecomp->num1 == 0) || (ecomp->cell1->class !=
|
||||
CLASS_MODULE)) {
|
||||
|
||||
if (ecomp->cell2 && !(ecomp->cell2->flags & CELL_PLACEHOLDER)) {
|
||||
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
|
||||
" makes a better match\n", ecomp->cell2->name,
|
||||
name2);
|
||||
flattenInstancesOf(name2, file2, ecomp->cell2->name);
|
||||
name2, file2);
|
||||
flattenInstancesOf(name2, file2, ecomp->cell2->name);
|
||||
modified++;
|
||||
}
|
||||
}
|
||||
modified++;
|
||||
}
|
||||
|
||||
/* Reset or apply the count adjustments */
|
||||
@@ -1707,7 +1838,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
}
|
||||
|
||||
/* Case 3: Cell1 class is a subcircuit, and flattening */
|
||||
/* (it without regard to cell1) improves the matching. */
|
||||
/* it (without regard to cell2) improves the matching. */
|
||||
|
||||
else if ((ecomp->num1 != ecomp->num2) && (ecomp->cell1 != NULL) &&
|
||||
(ecomp->num1 != 0) && (ecomp->cell1->class == CLASS_SUBCKT)) {
|
||||
@@ -1735,13 +1866,21 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
if (ecomp->cell1) {
|
||||
Fprintf(stdout, "Flattening instances of %s in cell %s"
|
||||
|
||||
/* Don't flatten if cell2 is a black box, because it */
|
||||
/* can't also be flattened. */
|
||||
|
||||
if ((ecomp->num2 == 0) || (ecomp->cell2->class !=
|
||||
CLASS_MODULE)) {
|
||||
|
||||
if (ecomp->cell1 && !(ecomp->cell1->flags & CELL_PLACEHOLDER)) {
|
||||
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
|
||||
" makes a better match\n", ecomp->cell1->name,
|
||||
name1);
|
||||
flattenInstancesOf(name1, file1, ecomp->cell1->name);
|
||||
name1, file1);
|
||||
flattenInstancesOf(name1, file1, ecomp->cell1->name);
|
||||
modified++;
|
||||
}
|
||||
}
|
||||
modified++;
|
||||
}
|
||||
|
||||
/* Reset or apply the count adjustments */
|
||||
@@ -1819,15 +1958,25 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
}
|
||||
if (found) {
|
||||
Fprintf(stdout, "Removing zero-valued device "
|
||||
"%s from cell %s makes a better match\n",
|
||||
tsub1->name,
|
||||
tc1->name);
|
||||
"%s from cell %s (%d) makes a better "
|
||||
"match\n",
|
||||
tsub1->name, tc1->name, tc1->file);
|
||||
|
||||
/* A current source is an open, while a */
|
||||
/* resistor or voltage source is a short. */
|
||||
|
||||
if (ecomp->cell1->class != CLASS_ISOURCE) {
|
||||
/* merge node of endpoints */
|
||||
/* Prefer a port node over a non-port node */
|
||||
for (ob2 = tc1->cell; ob2; ob2 = ob2->next) {
|
||||
if (!IsPort(ob2)) break;
|
||||
else if (ob2->node == node1) break;
|
||||
else if (ob2->node == node2) {
|
||||
int ntemp = node1;
|
||||
node1 = node2;
|
||||
node2 = ntemp;
|
||||
}
|
||||
}
|
||||
for (ob2 = tc1->cell; ob2; ob2 = ob2->next) {
|
||||
if (ob2->node == node2)
|
||||
ob2->node = node1;
|
||||
@@ -1930,12 +2079,22 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
}
|
||||
if (found) {
|
||||
Fprintf(stdout, "Removing zero-valued device "
|
||||
"%s from cell %s makes a better match\n",
|
||||
tsub2->name,
|
||||
tc2->name);
|
||||
"%s from cell %s (%d) makes a better "
|
||||
"match\n",
|
||||
tsub2->name, tc2->name, tc2->file);
|
||||
|
||||
/* merge node of endpoints */
|
||||
if (ecomp->cell2->class != CLASS_ISOURCE) {
|
||||
/* Prefer a port node over a non-port node */
|
||||
for (ob1 = tc2->cell; ob1; ob1 = ob1->next) {
|
||||
if (!IsPort(ob1)) break;
|
||||
else if (ob1->node == node1) break;
|
||||
else if (ob1->node == node2) {
|
||||
int ntemp = node1;
|
||||
node1 = node2;
|
||||
node2 = ntemp;
|
||||
}
|
||||
}
|
||||
for (ob1 = tc2->cell; ob1; ob1 = ob1->next) {
|
||||
if (ob1->node == node2)
|
||||
ob1->node = node1;
|
||||
@@ -2023,8 +2182,8 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
if (dstr) *dstr = '[';
|
||||
if ((ncomp == ecomp0X) && (ecomp0X->num2 <= ecompX0->num1)) {
|
||||
Fprintf(stdout, "Flattening instances of %s in cell %s"
|
||||
" makes a better match\n", ecompX0->cell1->name,
|
||||
name1);
|
||||
"(%d) makes a better match\n",
|
||||
ecompX0->cell1->name, name1, file1);
|
||||
flattenInstancesOf(name1, file1, ecompX0->cell1->name);
|
||||
ecompX0->num1 = 0;
|
||||
ecomp0X->num1 += ecompX0->num1;
|
||||
@@ -2049,8 +2208,8 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
if (dstr) *dstr = '[';
|
||||
if ((ncomp == ecompX0) && (ecompX0->num1 <= ecomp0X->num2)) {
|
||||
Fprintf(stdout, "Flattening instances of %s in cell %s"
|
||||
" makes a better match\n", ecomp0X->cell2->name,
|
||||
name2);
|
||||
" (%d) makes a better match\n",
|
||||
ecomp0X->cell2->name, name2, file2);
|
||||
flattenInstancesOf(name2, file2, ecomp0X->cell2->name);
|
||||
ecomp0X->num2 = 0;
|
||||
ecompX0->num2 += ecomp0X->num2;
|
||||
@@ -2064,6 +2223,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
// Free the hash table and its contents.
|
||||
|
||||
ecomp = (ECompare *)HashFirst(&compdict);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
+640
-203
File diff suppressed because it is too large
Load Diff
+14
-1
@@ -7,6 +7,7 @@ extern struct nlist *Circuit1;
|
||||
extern struct nlist *Circuit2;
|
||||
|
||||
extern int ExhaustiveSubdivision;
|
||||
extern int ExactTopology;
|
||||
|
||||
extern int left_col_end;
|
||||
extern int right_col_end;
|
||||
@@ -26,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);
|
||||
@@ -36,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,
|
||||
@@ -46,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();
|
||||
@@ -54,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();
|
||||
|
||||
+91
-67
@@ -183,7 +183,6 @@ void CloseFile(char *filename)
|
||||
fclose(outfile);
|
||||
}
|
||||
|
||||
|
||||
/* STUFF TO READ INPUT FILES */
|
||||
|
||||
static char *line = NULL; /* actual line read in */
|
||||
@@ -207,6 +206,21 @@ struct hashdict *definitions = (struct hashdict *)NULL;
|
||||
|
||||
#define WHITESPACE_DELIMITER " \t\n\r"
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Seek and Tell on infile stream, for use with handling generate */
|
||||
/* loops in verilog. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
void SeekFile(long offset)
|
||||
{
|
||||
fseek(infile, offset, SEEK_SET);
|
||||
}
|
||||
|
||||
long TellFile()
|
||||
{
|
||||
return ftell(infile);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* TrimQuoted() --- */
|
||||
/* Remove spaces from inside single- or double-quoted strings. */
|
||||
@@ -331,77 +345,87 @@ int GetNextLineNoNewline(char *delimiter)
|
||||
linetok = (char *)MALLOC(linesize + 1);
|
||||
}
|
||||
|
||||
/* Check for substitutions (verilog only). Make sure linetok is */
|
||||
/* large enough to hold the entire line after substitutions. */
|
||||
|
||||
if (definitions != NULL) {
|
||||
char *s, *w, e;
|
||||
struct property *kl;
|
||||
int len, dlen, vlen, addin = 0;
|
||||
unsigned char 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) */
|
||||
|
||||
if (definitions != NULL) {
|
||||
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;
|
||||
|
||||
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;
|
||||
/* 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;
|
||||
*w = e;
|
||||
}
|
||||
*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;
|
||||
}
|
||||
else *t++ = *s;
|
||||
strcpy(line, linetok);
|
||||
}
|
||||
*t = '\0';
|
||||
}
|
||||
else
|
||||
strcpy(linetok, line);
|
||||
|
||||
TrimQuoted(linetok);
|
||||
linenum++;
|
||||
@@ -904,7 +928,7 @@ char *ReadNetlist(char *fname, int *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) {
|
||||
@@ -1009,7 +1033,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;
|
||||
|
||||
@@ -1245,7 +1269,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;
|
||||
|
||||
|
||||
@@ -47,5 +47,7 @@ extern void InputParseError(FILE *f);
|
||||
extern int OpenParseFile(char *name, int fnum);
|
||||
extern int EndParseFile(void);
|
||||
extern int CloseParseFile(void);
|
||||
extern void SeekFile(long offset); /* handles verilog 'for' loops */
|
||||
extern long TellFile(); /* handles verilog 'for' loops */
|
||||
|
||||
#endif /* _NETFILE_H */
|
||||
|
||||
+72
-26
@@ -57,7 +57,7 @@ int AddToExistingDefinition = 0; /* default: overwrite cell when reopened */
|
||||
extern int errno; /* Defined in stdlib.h */
|
||||
|
||||
#define MAX_STATIC_STRINGS 5
|
||||
static char staticstrings[MAX_STATIC_STRINGS][200];
|
||||
static char staticstrings[MAX_STATIC_STRINGS][MAX_STR_LEN];
|
||||
static int laststring;
|
||||
|
||||
extern struct hashdict spiceparams; /* From spice.c */
|
||||
@@ -984,6 +984,51 @@ PropertyDelete(char *name, int fnum, char *key)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Associate a property with a specific pin */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
int
|
||||
PropertyAssociatePin(char *name, int fnum, char *key, char *pin)
|
||||
{
|
||||
struct property *kl = NULL;
|
||||
struct nlist *tc;
|
||||
struct objlist *ob;
|
||||
int result;
|
||||
|
||||
if ((fnum == -1) && (Circuit1 != NULL) && (Circuit2 != NULL)) {
|
||||
result = PropertyAssociatePin(name, Circuit1->file, key, pin);
|
||||
result = PropertyAssociatePin(name, Circuit2->file, key, pin);
|
||||
return result;
|
||||
}
|
||||
|
||||
tc = LookupCellFile(name, fnum);
|
||||
if (tc == NULL) {
|
||||
Printf("No device %s found for PropertyAssociatePin()\n", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
kl = (struct property *)HashLookup(key, &(tc->propdict));
|
||||
if (kl == NULL) {
|
||||
Printf("No property %s found for device %s\n", key, name);
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
for (ob = tc->cell; ob != NULL; ob = ob->next) {
|
||||
if (ob->type != PORT) break;
|
||||
else if ((*matchfunc)(ob->name, pin)) {
|
||||
kl->pin = ob->name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ob == NULL) {
|
||||
Printf("No pin %s found for device %s\n", pin, name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Set the tolerance of a property in the master cell record. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
@@ -3337,16 +3382,13 @@ int CombineParallel(char *model, int file)
|
||||
/* "sob" to it. If "ob" does not have properties, then */
|
||||
/* create a property record and set property "M" to 1. */
|
||||
|
||||
/* Find last non-property record of sob ( = pob) */
|
||||
/* Find first property record of sob ( = spropfirst) */
|
||||
/* Find last property record of sob ( = sproplast) */
|
||||
/* Find last non-property record of sob ( = pob) */
|
||||
/* Find first property record of sob ( = spropfirst) */
|
||||
|
||||
spropfirst = sproplast = NULL;
|
||||
spropfirst = NULL;
|
||||
for (ob2 = sob; ob2->type > FIRSTPIN || ob2 == sob; ob2 = ob2->next)
|
||||
pob = ob2;
|
||||
if (ob2->type == PROPERTY) spropfirst = ob2;
|
||||
for (; ob2->type == PROPERTY; ob2 = ob2->next)
|
||||
sproplast = ob2;
|
||||
|
||||
if (spropfirst == NULL) {
|
||||
/* Create new property instance record if one doesn't exist */
|
||||
@@ -3372,8 +3414,9 @@ int CombineParallel(char *model, int file)
|
||||
nob->next = pob->next;
|
||||
pob->next = nob;
|
||||
|
||||
/* Handle case of contiguous entries */
|
||||
if (lob == pob) lob = nob;
|
||||
spropfirst = sproplast = nob;
|
||||
spropfirst = nob;
|
||||
}
|
||||
if (propfirst == NULL) {
|
||||
/* Create new property instance record if one doesn't exist */
|
||||
@@ -3396,27 +3439,26 @@ int CombineParallel(char *model, int file)
|
||||
kv->type = PROP_ENDLIST;
|
||||
kv->value.ival = 0;
|
||||
|
||||
/* Append to sob's property list */
|
||||
nob->next = sproplast->next;
|
||||
sproplast->next = nob;
|
||||
if (lob == sproplast) lob = nob;
|
||||
/* Prepend to sob's property list */
|
||||
nob->next = pob->next;
|
||||
pob->next = nob;
|
||||
/* Handle case of contiguous entries */
|
||||
if (lob == pob) lob = nob;
|
||||
}
|
||||
|
||||
if (propfirst != NULL) {
|
||||
else {
|
||||
|
||||
// Series/Parallel logic:
|
||||
// If propfirst has _tag in properties,
|
||||
// then add an "open" tag at propfirst
|
||||
add_prop_tag(propfirst, '(');
|
||||
// If spropfirst has _tag in properties,
|
||||
// then add an "open" tag at spropfirst
|
||||
add_prop_tag(spropfirst, '(');
|
||||
|
||||
// if spropfirst has _tag in properties then add an "open" tag
|
||||
// to spropfirst and a "close" tag to propfirst
|
||||
if (add_prop_tag(spropfirst, '(')) add_prop_tag(propfirst, ')');
|
||||
// if propfirst has _tag in properties then add an "open" tag
|
||||
// to propfirst and a "close" tag to spropfirst
|
||||
if (add_prop_tag(propfirst, '(')) add_prop_tag(spropfirst, ')');
|
||||
|
||||
/* Append ob's property list to sob */
|
||||
proplast->next = sproplast->next;
|
||||
sproplast->next = propfirst;
|
||||
if (lob == sproplast) lob = proplast;
|
||||
/* Prepend ob's property list to sob */
|
||||
proplast->next = pob->next;
|
||||
pob->next = propfirst;
|
||||
}
|
||||
|
||||
/* Link up around object to be removed */
|
||||
@@ -3429,7 +3471,6 @@ int CombineParallel(char *model, int file)
|
||||
obr = nob;
|
||||
}
|
||||
dcnt++;
|
||||
|
||||
}
|
||||
FREE((char *)pstr);
|
||||
}
|
||||
@@ -3441,7 +3482,8 @@ int CombineParallel(char *model, int file)
|
||||
}
|
||||
HashKill(&devdict);
|
||||
if (dcnt > 0) {
|
||||
Fprintf(stdout, "Class %s: Merged %d devices.\n", model, dcnt);
|
||||
Fprintf(stdout, "Class %s (%d): Merged %d parallel devices.\n",
|
||||
model, file, dcnt);
|
||||
}
|
||||
FREE(nodecount);
|
||||
return dcnt;
|
||||
@@ -3738,6 +3780,10 @@ int CombineSeries(char *model, int file)
|
||||
}
|
||||
}
|
||||
FREE(instlist);
|
||||
if (scnt > 0) {
|
||||
Fprintf(stdout, "Class %s (%d): Merged %d series devices.\n",
|
||||
model, file, scnt);
|
||||
}
|
||||
return scnt;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ 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);
|
||||
|
||||
+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 */
|
||||
|
||||
+45
-5
@@ -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,7 +290,7 @@ static struct hashdict cell_dict;
|
||||
|
||||
void InitCellHashTable(void)
|
||||
{
|
||||
hashfunc = hash;
|
||||
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;
|
||||
@@ -1207,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 */
|
||||
|
||||
+24
-9
@@ -135,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;
|
||||
@@ -206,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 */
|
||||
@@ -222,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;
|
||||
@@ -312,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
|
||||
|
||||
+9
-9
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
+12
-9
@@ -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)
|
||||
@@ -805,11 +805,14 @@ void DescribeInstance(char *name, int file)
|
||||
/* 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");
|
||||
if ((!(tp->flags & CELL_PLACEHOLDER)) && (tp->class != CLASS_MODULE)) {
|
||||
// if (disconnectednodes == 0) Fprintf(stderr, "\n");
|
||||
disconnectednodes++;
|
||||
Fprintf(stderr, "Cell %s disconnected node: %s\n", tp->name, ob->name);
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -956,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;
|
||||
@@ -1033,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);
|
||||
|
||||
+135
-107
@@ -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;
|
||||
@@ -515,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()) {
|
||||
@@ -552,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 */
|
||||
@@ -700,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;
|
||||
|
||||
@@ -884,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)
|
||||
{
|
||||
@@ -937,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);
|
||||
@@ -968,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)
|
||||
{
|
||||
@@ -1010,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);
|
||||
@@ -1024,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);
|
||||
@@ -1055,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)
|
||||
@@ -1068,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';
|
||||
}
|
||||
@@ -1101,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
|
||||
@@ -1118,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);
|
||||
@@ -1149,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) {
|
||||
@@ -1161,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';
|
||||
}
|
||||
@@ -1194,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
|
||||
@@ -1205,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)
|
||||
{
|
||||
@@ -1252,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);
|
||||
@@ -1265,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);
|
||||
@@ -1295,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) {
|
||||
@@ -1331,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);
|
||||
@@ -1344,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);
|
||||
@@ -1376,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)
|
||||
@@ -1414,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
|
||||
@@ -1428,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();
|
||||
@@ -1474,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);
|
||||
@@ -1483,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);
|
||||
@@ -1537,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);
|
||||
@@ -1603,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;
|
||||
@@ -1617,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);
|
||||
@@ -1726,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;
|
||||
@@ -1767,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 */
|
||||
|
||||
@@ -1969,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. */
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
|
||||
+776
-222
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
|
||||
|
||||
+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;
|
||||
|
||||
Vendored
+699
-418
File diff suppressed because it is too large
Load Diff
Vendored
+1487
-1430
File diff suppressed because it is too large
Load Diff
Vendored
+20
-3
@@ -712,6 +712,7 @@ infodir
|
||||
docdir
|
||||
oldincludedir
|
||||
includedir
|
||||
runstatedir
|
||||
localstatedir
|
||||
sharedstatedir
|
||||
sysconfdir
|
||||
@@ -794,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}'
|
||||
@@ -1046,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=* \
|
||||
@@ -1183,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.
|
||||
@@ -1336,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]
|
||||
@@ -6065,7 +6077,6 @@ fi
|
||||
|
||||
|
||||
if test $usingTcl ; then
|
||||
usingX11=1
|
||||
cadinstall="$cadinstall tcltk"
|
||||
modules="$modules tcltk"
|
||||
programs="$programs tcltk"
|
||||
@@ -6075,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"
|
||||
@@ -6160,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
|
||||
@@ -6176,6 +6192,7 @@ if test $usingTcl ; then
|
||||
loader_run_path="${TK_LIB_DIR}:${loader_run_path}"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
#
|
||||
|
||||
@@ -807,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"
|
||||
@@ -816,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"
|
||||
@@ -903,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
|
||||
@@ -919,6 +923,7 @@ if test $usingTcl ; then
|
||||
loader_run_path="${TK_LIB_DIR}:${loader_run_path}"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
#
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+123
-93
@@ -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} {
|
||||
@@ -393,7 +395,7 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||
# 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 {![catch {file exists $value}]} {
|
||||
if {[file exists $value]} {
|
||||
if {![catch {open $value r} fnf]} {
|
||||
while {[gets $fnf line] >= 0} {
|
||||
if {[lindex $line 0] != "#"} {
|
||||
@@ -477,8 +479,12 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||
|
||||
netgen::compare assign "$fnum1 $cell1" "$fnum2 $cell2"
|
||||
|
||||
if {[file exists $setupfile]} {
|
||||
puts stdout "Reading setup file $setupfile"
|
||||
if {$setupfile == ""} {
|
||||
puts stdout "\nNo setup file specified. Using trivial default setup.\n"
|
||||
netgen::permute default ;# transistors and resistors
|
||||
netgen::property default
|
||||
} elseif {[file exists $setupfile]} {
|
||||
puts stdout "\nReading setup file $setupfile\n"
|
||||
# Instead of sourcing the setup file, run each line so we can
|
||||
# catch individual errors and not let them halt the LVS process
|
||||
set perrors 0
|
||||
@@ -506,8 +512,10 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||
puts stdout "Warning: There were errors reading the setup file"
|
||||
}
|
||||
} elseif {[string first nosetup $setupfile] < 0} {
|
||||
netgen::permute default ;# transistors and resistors
|
||||
netgen::property default
|
||||
puts stderr "\nError: Setup file $setupfile does not exist.\n"
|
||||
return
|
||||
} else {
|
||||
puts stderr "\nNo setup file specified. Continuing without a setup.\n"
|
||||
}
|
||||
|
||||
if {[string first nolog $logfile] < 0} {
|
||||
@@ -532,14 +540,24 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||
}
|
||||
set properr {}
|
||||
set matcherr {}
|
||||
set pinsgood -1
|
||||
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} {
|
||||
@@ -548,96 +566,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] != {}} {
|
||||
if {([lsearch $noflat [lindex $endval 0]] == -1) &&
|
||||
([lsearch $noflat [lindex $endval 1]] == -1)} {
|
||||
netgen::log put " Flattening non-matched subcircuits $endval"
|
||||
netgen::flatten class "[lindex $endval 0] $fnum1"
|
||||
netgen::flatten class "[lindex $endval 1] $fnum2"
|
||||
} else {
|
||||
netgen::log put " Continuing with black-boxed subcircuits $endval"
|
||||
lappend matcherr [lindex $endval 0]
|
||||
# Match pins
|
||||
netgen::log echo off
|
||||
if {$dolist == 1} {
|
||||
set result [equate -list -force pins "$fnum1 [lindex $endval 0]" \
|
||||
"$fnum2 [lindex $endval 1]"]
|
||||
} else {
|
||||
set result [equate -force pins "$fnum1 [lindex $endval 0]" \
|
||||
"$fnum2 [lindex $endval 1]"]
|
||||
}
|
||||
if {$result != 0} {
|
||||
equate classes "$fnum1 [lindex $endval 0]" \
|
||||
"$fnum2 [lindex $endval 1]"
|
||||
}
|
||||
set pinsgood $result
|
||||
netgen::log echo on
|
||||
}
|
||||
}
|
||||
set doCheckFlatten 1
|
||||
} else {
|
||||
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]"
|
||||
}
|
||||
# If $uresult == -1 then these are black-box entries and
|
||||
# $pinsgood should not be set to the resulting value.
|
||||
if {$uresult > 0} {
|
||||
set pinsgood $result
|
||||
}
|
||||
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] != {}} {
|
||||
if {([lsearch $noflat [lindex $endval 1]] == -1) &&
|
||||
([lsearch $noflat [lindex $endval 1]] == -1)} {
|
||||
netgen::log put " Flattening non-matched subcircuits $endval"
|
||||
netgen::flatten class "[lindex $endval 0] $fnum1"
|
||||
netgen::flatten class "[lindex $endval 1] $fnum2"
|
||||
} else {
|
||||
netgen::log put " Continuing with black-boxed subcircuits $endval"
|
||||
lappend matcherr [lindex $endval 0]
|
||||
netgen::log put " Continuing with black-boxed subcircuits $endval"
|
||||
lappend matcherr [lindex $endval 0]
|
||||
# Match pins
|
||||
netgen::log echo off
|
||||
if {$dolist == 1} {
|
||||
set result [equate -list -force pins "$fnum1 [lindex $endval 0]" \
|
||||
"$fnum2 [lindex $endval 1]"]
|
||||
} else {
|
||||
set result [equate -force pins "$fnum1 [lindex $endval 0]" \
|
||||
"$fnum2 [lindex $endval 1]"]
|
||||
}
|
||||
if {$result != 0} {
|
||||
equate classes "$fnum1 [lindex $endval 0]" \
|
||||
"$fnum2 [lindex $endval 1]"
|
||||
}
|
||||
set pinsgood $result
|
||||
netgen::log echo on
|
||||
# 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 {}
|
||||
@@ -646,20 +673,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
|
||||
if {$pinsgood == 0} {
|
||||
# NOTE: Need to disambiguate these two cases. . .
|
||||
netgen::log put "Cells failed matching, or top level cell failed pin matching.\n"
|
||||
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 "The following subcells failed to match: $matcherr\n"
|
||||
netgen::log put "\nThe following subcells failed to match:\n " [regsub -all { } $matcherr "\n "] "\n"
|
||||
}
|
||||
if {$dolog} {
|
||||
netgen::log end
|
||||
|
||||
+188
-56
@@ -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
|
||||
@@ -976,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);
|
||||
@@ -1053,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;
|
||||
@@ -1928,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);
|
||||
@@ -1939,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);
|
||||
@@ -2066,6 +2087,7 @@ _netcmp_format(ClientData clientData,
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "[col1_width [col2_width]]");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
@@ -2091,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) {
|
||||
@@ -2135,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();
|
||||
@@ -2191,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
|
||||
@@ -2451,39 +2503,37 @@ _netcmp_run(ClientData clientData,
|
||||
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) {
|
||||
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) {
|
||||
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);
|
||||
while (ResolveAutomorphisms() > 0);
|
||||
}
|
||||
if (automorphisms == -1)
|
||||
Fprintf(stdout, "Netlists do not match.\n");
|
||||
else
|
||||
Fprintf(stdout, "Circuits match correctly.\n");
|
||||
}
|
||||
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();
|
||||
}
|
||||
@@ -2501,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. */
|
||||
@@ -2596,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");
|
||||
}
|
||||
@@ -2611,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");
|
||||
}
|
||||
}
|
||||
@@ -2836,7 +2902,7 @@ _netcmp_equate(ClientData clientData,
|
||||
struct ElementClass *saveEclass = NULL;
|
||||
struct NodeClass *saveNclass = NULL;
|
||||
int file1, file2;
|
||||
int i, l1, l2, ltest, lent, dolist = 0, doforce = 0;
|
||||
int i, l1, l2, ltest, lent, dolist = 0, doforce = 0, dounique = 0;
|
||||
Tcl_Obj *tobj1, *tobj2, *tobj3;
|
||||
|
||||
while (objc > 1) {
|
||||
@@ -2852,6 +2918,11 @@ _netcmp_equate(ClientData clientData,
|
||||
objv++;
|
||||
objc--;
|
||||
}
|
||||
else if (!strcmp(optstart, "unique")) {
|
||||
dounique = 1;
|
||||
objv++;
|
||||
objc--;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
@@ -3027,18 +3098,22 @@ _netcmp_equate(ClientData clientData,
|
||||
(tp2->flags & CELL_PLACEHOLDER)) {
|
||||
if (tp1->flags & CELL_PLACEHOLDER) {
|
||||
Fprintf(stdout, "Warning: Equate pins: cell %s "
|
||||
"has no definition, treated as a black box.\n", name1);
|
||||
"is a placeholder, treated as a black box.\n", name1);
|
||||
}
|
||||
if (tp2->flags & CELL_PLACEHOLDER) {
|
||||
Fprintf(stdout, "Warning: Equate pins: cell %s "
|
||||
"has no definition, treated as a black box.\n", name2);
|
||||
"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 {
|
||||
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. */
|
||||
@@ -3070,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);
|
||||
@@ -3265,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));
|
||||
@@ -3300,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 */
|
||||
@@ -3338,11 +3412,11 @@ _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;
|
||||
|
||||
@@ -3387,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"))) {
|
||||
|
||||
@@ -3472,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;
|
||||
@@ -3765,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} ...");
|
||||
@@ -3864,6 +3995,7 @@ _netcmp_property(ClientData clientData,
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return TCL_OK;
|
||||
|
||||
Reference in New Issue
Block a user