Compare commits

..

97 Commits

Author SHA1 Message Date
Tim Edwards b6d896e73f Merge branch 'master' into netgen-1.5 2021-07-12 03:00:10 -04:00
Tim Edwards 9251ce2a48 Merge branch 'master' into netgen-1.5 2021-07-11 03:00:33 -04:00
Tim Edwards aa82164c08 Merge branch 'master' into netgen-1.5 2021-07-09 03:00:34 -04:00
Tim Edwards fb7876c7a6 Merge branch 'master' into netgen-1.5 2021-07-03 03:00:13 -04:00
Tim Edwards e31caa3500 Merge branch 'master' into netgen-1.5 2021-06-26 03:00:10 -04:00
Tim Edwards c1355bee45 Merge branch 'master' into netgen-1.5 2021-06-25 03:00:10 -04:00
Tim Edwards 4fb8b59a2f Merge branch 'master' into netgen-1.5 2021-06-19 03:00:10 -04:00
Tim Edwards 626faf22f9 Merge branch 'master' into netgen-1.5 2021-06-17 03:00:10 -04:00
Tim Edwards 550234dce5 Merge branch 'master' into netgen-1.5 2021-06-15 03:00:36 -04:00
Tim Edwards a4c0028706 Merge branch 'master' into netgen-1.5 2021-06-13 03:00:32 -04:00
Tim Edwards e7ae84bbc8 Merge branch 'master' into netgen-1.5 2021-06-10 03:00:09 -04:00
Tim Edwards 43c018f3bc Merge branch 'master' into netgen-1.5 2021-06-09 03:00:10 -04:00
Tim Edwards ca119edc0a Merge branch 'master' into netgen-1.5 2021-06-04 03:00:10 -04:00
Tim Edwards 84348d2fe1 Merge branch 'master' into netgen-1.5 2021-05-31 03:00:10 -04:00
Tim Edwards 813b29cdc4 Merge branch 'master' into netgen-1.5 2021-05-29 03:00:10 -04:00
Tim Edwards ccf4a0a900 Merge branch 'master' into netgen-1.5 2021-05-27 03:00:32 -04:00
Tim Edwards e34166fdb9 Merge branch 'master' into netgen-1.5 2021-05-26 03:00:32 -04:00
Tim Edwards a13491e358 Merge branch 'master' into netgen-1.5 2021-05-25 03:00:09 -04:00
Tim Edwards 1d05b8b676 Merge branch 'master' into netgen-1.5 2021-05-20 03:00:31 -04:00
Tim Edwards e97d6f1aeb Merge branch 'master' into netgen-1.5 2021-05-14 03:00:10 -04:00
Tim Edwards fb4759a8cd Merge branch 'master' into netgen-1.5 2021-05-04 03:00:10 -04:00
Tim Edwards 45d4004d43 Merge branch 'master' into netgen-1.5 2021-05-02 03:00:09 -04:00
Tim Edwards 0b014e6efd Merge branch 'master' into netgen-1.5 2021-03-20 03:00:09 -04:00
Tim Edwards 9ca713dfd9 Merge branch 'master' into netgen-1.5 2021-03-18 03:00:29 -04:00
Tim Edwards 851a1f941e Merge branch 'master' into netgen-1.5 2021-03-06 03:00:09 -05:00
Tim Edwards fb798d6ce7 Merge branch 'master' into netgen-1.5 2021-03-03 03:00:12 -05:00
Tim Edwards a888502038 Merge branch 'master' into netgen-1.5 2021-03-02 03:00:35 -05:00
Tim Edwards c16258d4d1 Merge branch 'master' into netgen-1.5 2021-02-25 03:00:36 -05:00
Tim Edwards 5341d7a5fd Merge branch 'master' into netgen-1.5 2021-02-17 03:00:31 -05:00
Tim Edwards 8395df633c Merge branch 'master' into netgen-1.5 2021-02-10 03:00:16 -05:00
Tim Edwards 6554063df3 Merge branch 'master' into netgen-1.5 2021-01-22 03:00:40 -05:00
Tim Edwards 4416a380b3 Merge branch 'master' into netgen-1.5 2021-01-18 03:00:51 -05:00
Tim Edwards 46394b2000 Merge branch 'master' into netgen-1.5 2021-01-17 03:00:15 -05:00
Tim Edwards 3fe3bc4cfa Merge branch 'master' into netgen-1.5 2021-01-09 03:00:32 -05:00
Tim Edwards 6661910672 Merge branch 'master' into netgen-1.5 2020-12-21 03:00:30 -05:00
Tim Edwards e7a36630f6 Merge branch 'master' into netgen-1.5 2020-12-16 03:00:54 -05:00
Tim Edwards f32b0b34a3 Merge branch 'master' into netgen-1.5 2020-12-06 03:00:10 -05:00
Tim Edwards 6b731ddd7a Merge branch 'master' into netgen-1.5 2020-12-04 03:00:27 -05:00
Tim Edwards 99e35d8b11 Merge branch 'master' into netgen-1.5 2020-10-09 03:00:25 -04:00
Tim Edwards 65b542f0ab Merge branch 'master' into netgen-1.5 2020-10-08 03:00:22 -04:00
Tim Edwards b826870be9 Merge branch 'master' into netgen-1.5 2020-08-09 03:01:40 -04:00
Tim Edwards ed5276d67b Merge branch 'master' into netgen-1.5 2020-08-04 03:00:31 -04:00
Tim Edwards 69c9d85be7 Merge branch 'master' into netgen-1.5 2020-08-01 03:00:23 -04:00
Tim Edwards ad05d059c7 Merge branch 'master' into netgen-1.5 2020-07-31 03:00:27 -04:00
Tim Edwards 1b2cd1497c Merge branch 'master' into netgen-1.5 2020-07-30 03:00:28 -04:00
Tim Edwards d9d5a46c6e Merge branch 'master' into netgen-1.5 2020-07-25 03:00:09 -04:00
Tim Edwards d73b711e3a Merge branch 'master' into netgen-1.5 2020-07-02 03:00:09 -04:00
Tim Edwards 1428580109 Merge branch 'master' into netgen-1.5 2020-06-17 03:00:38 -04:00
Tim Edwards 210dfb25c3 Merge branch 'master' into netgen-1.5 2020-06-04 03:00:24 -04:00
Tim Edwards 27f2ab8b3f Merge branch 'master' into netgen-1.5 2020-03-28 03:00:24 -04:00
Tim Edwards 1be00bbd99 Merge branch 'master' into netgen-1.5 2020-03-27 03:00:21 -04:00
Tim Edwards 03b241a5d4 Merge branch 'master' into netgen-1.5 2020-03-11 03:00:17 -04:00
Tim Edwards 43cebd1ef9 Merge branch 'master' into netgen-1.5 2020-03-06 03:00:39 -05:00
Tim Edwards 0490959b07 Merge branch 'master' into netgen-1.5 2020-03-05 03:00:09 -05:00
Tim Edwards dc841f3293 Merge branch 'master' into netgen-1.5 2020-02-24 17:35:04 -05:00
Tim Edwards 05bcfede69 Merge branch 'master' into netgen-1.5 2020-02-24 16:39:19 -05:00
Tim Edwards 72ed78e55a Update for change in ocd git script 2020-02-24 15:04:59 -05:00
Tim Edwards 59bb8a89c0 "ocd_git_pure automatic update to repo" 2020-02-24 15:04:27 -05:00
Tim Edwards 9bdaee652e "ocd_git_pure automatic update to repo" 2020-02-18 03:00:14 -05:00
Tim Edwards 9879b58f83 Merge branch 'master' into netgen-1.5 2020-02-18 03:00:13 -05:00
Tim Edwards 9e3b705fcc "ocd_git_pure automatic update to repo" 2020-02-11 03:00:09 -05:00
Tim Edwards d2c9129242 Merge branch 'master' into netgen-1.5 2020-02-11 03:00:09 -05:00
Tim Edwards 942f421fa3 "ocd_git_pure automatic update to repo" 2020-01-30 03:01:39 -05:00
Tim Edwards 6bc948d8ba Merge branch 'master' into netgen-1.5 2020-01-30 03:01:38 -05:00
Tim Edwards c1ad37f05a "ocd_git_pure automatic update to repo" 2020-01-14 03:00:47 -05:00
Tim Edwards 9edefe7d59 Merge branch 'master' into netgen-1.5 2020-01-14 03:00:47 -05:00
Tim Edwards f6b9629521 "ocd_git_pure automatic update to repo" 2019-11-20 03:00:33 -05:00
Tim Edwards 7b2e01f2af Merge branch 'master' into netgen-1.5 2019-11-20 03:00:33 -05:00
Tim Edwards 224050f153 "ocd_git_pure automatic update to repo" 2019-10-09 03:00:08 -04:00
Tim Edwards 74e8c3e168 Merge branch 'master' into netgen-1.5 2019-10-09 03:00:08 -04:00
Tim Edwards 95a29fcd8c "ocd_git_pure automatic update to repo" 2019-09-11 03:00:07 -04:00
Tim Edwards 723a950fd3 Merge branch 'master' into netgen-1.5 2019-09-11 03:00:07 -04:00
Tim Edwards e3368cb22a "ocd_git_pure automatic update to repo" 2019-09-10 03:00:08 -04:00
Tim Edwards f06e6548bb Merge branch 'master' into netgen-1.5 2019-09-10 03:00:08 -04:00
Tim Edwards 72ed19ff36 "ocd_git_pure automatic update to repo" 2019-09-09 03:00:10 -04:00
Tim Edwards 39b8e3d14a Merge branch 'master' into netgen-1.5 2019-09-09 03:00:10 -04:00
Tim Edwards b63dfa8638 "ocd_git_pure automatic update to repo" 2019-08-20 03:00:20 -04:00
Tim Edwards f918f33c51 Merge branch 'master' into netgen-1.5 2019-08-20 03:00:20 -04:00
Tim Edwards 63b2e48ea1 "ocd_git_pure automatic update to repo" 2019-08-13 03:00:08 -04:00
Tim Edwards 6e63f49d53 Merge branch 'master' into netgen-1.5 2019-08-13 03:00:07 -04:00
Tim Edwards 419b6de29a "ocd_git_pure automatic update to repo" 2019-08-11 03:00:07 -04:00
Tim Edwards 205cf2aa58 Merge branch 'master' into netgen-1.5 2019-08-11 03:00:07 -04:00
Tim Edwards 52b6766fc8 "ocd_git_pure automatic update to repo" 2019-08-04 03:00:20 -04:00
Tim Edwards 7b0bdd29e8 Merge branch 'master' into netgen-1.5 2019-08-04 03:00:20 -04:00
Tim Edwards 433cbd090a "ocd_git_pure automatic update to repo" 2019-07-25 03:00:16 -04:00
Tim Edwards 3087bd3337 Merge branch 'master' into netgen-1.5 2019-07-25 03:00:16 -04:00
Tim Edwards b79a29d662 "ocd_git_pure automatic update to repo" 2019-07-15 03:00:27 -04:00
Tim Edwards bf9c61e412 Merge branch 'master' into netgen-1.5 2019-07-15 03:00:27 -04:00
Tim Edwards 8d34bd372d "ocd_git_pure automatic update to repo" 2019-07-03 03:00:22 -04:00
Tim Edwards 229c2931a8 Merge branch 'master' into netgen-1.5 2019-07-03 03:00:22 -04:00
Tim Edwards b8da97deb1 "ocd_git_pure automatic update to repo" 2019-06-16 03:00:15 -04:00
Tim Edwards b7187d5899 Merge branch 'master' into netgen-1.5 2019-06-16 03:00:15 -04:00
Tim Edwards d27d441c58 "ocd_git_pure automatic update to repo" 2019-06-13 03:00:05 -04:00
Tim Edwards 48c9e6b292 Merge branch 'master' into netgen-1.5 2019-06-13 03:00:05 -04:00
Tim Edwards ced5846da3 "ocd_git_pure automatic update to repo" 2019-05-18 03:00:05 -04:00
Tim Edwards b99d33064f Merge branch 'master' into netgen-1.5 2019-05-18 03:00:04 -04:00
Tim Edwards 399472e940 "ocd_git_pure automatic update to repo" 2019-05-07 09:13:00 -04:00
46 changed files with 3478 additions and 8365 deletions

View File

@ -1,40 +0,0 @@
# This is a basic workflow to help you get started with Actions
name: CI
# Controls when the workflow will run
on:
# Triggers the workflow on push or pull request events but only for the master branch
push:
branches: [ master ]
pull_request:
branches: [ master ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Runs a set of commands using the runners shell
#- name: Logging into Dockerhub
# run: docker login -u ${{ secrets.DOCKERHUB_USERNAME }} -p ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Pulling the docker image
run: docker pull vezzal/vezzal:v1
- name: Start the container with the docker image
run: docker run -id --name test_netgen vezzal/vezzal:v1 bash | exit
- name: Run the testing on the container and send the mail
run: docker exec test_netgen /vezzal/test_netgen.sh "tim@opencircuitdesign.com,lankasaicharan123@gmail.com" ${{ secrets.MAILING_KEY }}

1
.gitignore vendored
View File

@ -7,7 +7,6 @@ config.log
scripts/config.log scripts/config.log
config.status config.status
scripts/config.status scripts/config.status
python/lvs_manager.py
*.o *.o
*.so *.so
*~ *~

View File

@ -1,8 +1,4 @@
![Continuous Integration](https://github.com/RTimothyEdwards/netgen/actions/workflows/main.yml/badge.svg) NETGEN: VERSION 1.5
# NETGEN
### VERSION 1.5
NETGEN is a general-purpose netlist management system. It can read NETGEN is a general-purpose netlist management system. It can read
and write several netlist formats, including NTK (Caltech, CMU), and write several netlist formats, including NTK (Caltech, CMU),
@ -91,49 +87,6 @@ and IRSIM version 9.7:
Note: For FreeBSD, use 'gmake' instead. 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 IN CASE OF FAILURE
------------------- -------------------
Please contact me (tim@opencircuitdesign.com) to report compile-time and Please contact me (tim@opencircuitdesign.com) to report compile-time and

View File

@ -1 +1 @@
1.5.323 1.5.195

View File

@ -22,7 +22,6 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <strings.h>
#include <ctype.h> #include <ctype.h>
#ifdef IBMPC #ifdef IBMPC
#include <stdlib.h> /* for strtol on PC */ #include <stdlib.h> /* for strtol on PC */
@ -91,7 +90,7 @@ char *ActelName(char *Name)
/* strip physical-pin information, if it exists */ /* strip physical-pin information, if it exists */
if ((nm = strrchr(name,PHYSICALPIN[0])) != NULL) *nm = '\0'; if ((nm = strrchr(name,PHYSICALPIN[0])) != NULL) *nm = '\0';
if (strlen(name) > 13) { if (strlen(name) > 13) {
ActelIndex = (ActelIndex + 1) % ACTELNAMESIZE; ActelIndex = (++ActelIndex) % ACTELNAMESIZE;
/* format the value of the hashed value of the string */ /* format the value of the hashed value of the string */
sprintf(ActelNames[ActelIndex], "$%lX", ActelNameHash(name)); sprintf(ActelNames[ActelIndex], "$%lX", ActelNameHash(name));
if (Debug) if (Debug)
@ -102,7 +101,7 @@ Printf("ActelNameHash returns %s on name %s\n",ActelNames[ActelIndex], name);
NeedsQuoting = 0; NeedsQuoting = 0;
if (NULL != strpbrk(name, ".,:; \t\"'\n\r")) NeedsQuoting = 1; if (NULL != strpbrk(name, ".,:; \t\"'\n\r")) NeedsQuoting = 1;
ActelIndex = (ActelIndex + 1) % ACTELNAMESIZE; ActelIndex = (++ActelIndex) % ACTELNAMESIZE;
if (!NeedsQuoting) { if (!NeedsQuoting) {
strcpy(ActelNames[ActelIndex], name); strcpy(ActelNames[ActelIndex], name);
return(ActelNames[ActelIndex]); return(ActelNames[ActelIndex]);
@ -132,7 +131,7 @@ if format = 1, use the actel .pin file format
struct nlist *tp; struct nlist *tp;
struct objlist *ob, *ob2; struct objlist *ob, *ob2;
char *ptr; char *ptr;
char physicalpin[MAX_STR_LEN]; char physicalpin[200];
tp = LookupCell(name); tp = LookupCell(name);
if (tp == NULL) return; if (tp == NULL) return;

View File

@ -176,6 +176,4 @@ extern int open(char *path, int oflag, ...); /* HPUX has it in <sys/fcntl.h> */
#define FALSE 0 #define FALSE 0
#endif #endif
#define MAX_STR_LEN 256
#endif /* _CONFIG_H */ #endif /* _CONFIG_H */

View File

@ -629,7 +629,7 @@ struct embed *FlattenEmbeddingTree(struct embed *E)
int LenEmbed(char *prefix, struct nlist *np, struct embed *E, int flatten) int LenEmbed(char *prefix, struct nlist *np, struct embed *E, int flatten)
/* return the number of characters required to print element E */ /* return the number of characters required to print element E */
{ {
char longstr[MAX_STR_LEN]; char longstr[200];
if (E == NULL) return(0); if (E == NULL) return(0);
if (E->left == NULL && E->right == NULL) { if (E->left == NULL && E->right == NULL) {
@ -668,7 +668,7 @@ void PrintEmb(FILE *outfile, char *prefix, struct nlist *np,
struct objlist *ob; struct objlist *ob;
char *instancename; char *instancename;
struct nlist *np2; struct nlist *np2;
char name[MAX_STR_LEN]; char name[200];
ob = InstanceNumber(np,E->instancenumber); ob = InstanceNumber(np,E->instancenumber);
instancename = ob->instance.name; instancename = ob->instance.name;
@ -706,7 +706,7 @@ void PrintEmbed(FILE *outfile, char *prefix, struct nlist *np,
struct objlist *ob; struct objlist *ob;
char *instancename; char *instancename;
struct nlist *np2; struct nlist *np2;
char name[MAX_STR_LEN]; char name[200];
ob = InstanceNumber(np,E->instancenumber); ob = InstanceNumber(np,E->instancenumber);
instancename = ob->instance.name; instancename = ob->instance.name;

View File

@ -23,15 +23,12 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> /* for strtod() */ #include <stdlib.h> /* for strtod() */
#include <stdarg.h> #include <stdarg.h>
#include <ctype.h>
#include "netgen.h" #include "netgen.h"
#include "hash.h"
#include "objlist.h" #include "objlist.h"
#include "netfile.h" #include "netfile.h"
#include "print.h" #include "print.h"
#include "hash.h"
static int invlambda = 100; /* Used in sim and prm files */
void extCell(char *name, int filenum) void extCell(char *name, int filenum)
{ {
@ -169,7 +166,7 @@ char *ReadExt(char *fname, int doflat, int *fnum)
int filenum; int filenum;
if ((filenum = OpenParseFile(fname, *fnum)) < 0) { if ((filenum = OpenParseFile(fname, *fnum)) < 0) {
char name[MAX_STR_LEN]; char name[100];
SetExtension(name, fname, EXT_EXTENSION); SetExtension(name, fname, EXT_EXTENSION);
if ((filenum = OpenParseFile(name, *fnum)) < 0) { if ((filenum = OpenParseFile(name, *fnum)) < 0) {
@ -189,7 +186,7 @@ char *ReadExt(char *fname, int doflat, int *fnum)
/* Make sure all .ext file reading is case sensitive */ /* Make sure all .ext file reading is case sensitive */
matchfunc = match; matchfunc = match;
matchintfunc = matchfile; matchintfunc = matchfile;
hashfunc = hashcase; hashfunc = hash;
if (LookupCellFile(fname, filenum) != NULL) { if (LookupCellFile(fname, filenum) != NULL) {
Printf("Error: Duplicate cell name \"%s\"!\n", fname); Printf("Error: Duplicate cell name \"%s\"!\n", fname);
@ -210,7 +207,7 @@ char *ReadExt(char *fname, int doflat, int *fnum)
else if (match(nexttok, "style")) SkipNewLine(NULL); else if (match(nexttok, "style")) SkipNewLine(NULL);
else if (match(nexttok, "resistclasses")) SkipNewLine(NULL); else if (match(nexttok, "resistclasses")) SkipNewLine(NULL);
else if (match(nexttok, "node")) { else if (match(nexttok, "node")) {
char name[MAX_STR_LEN]; char name[200];
/* No cell is generated until at least one valid "node" or "use" */ /* No cell is generated until at least one valid "node" or "use" */
/* has been read in the file. */ /* has been read in the file. */
@ -225,8 +222,8 @@ char *ReadExt(char *fname, int doflat, int *fnum)
SkipNewLine(NULL); SkipNewLine(NULL);
} }
else if (match(nexttok, "equiv")) { else if (match(nexttok, "equiv")) {
char name[MAX_STR_LEN]; char name[200];
char name2[MAX_STR_LEN]; char name2[200];
SkipTok(NULL); SkipTok(NULL);
GetExtName(name, nexttok); GetExtName(name, nexttok);
if (LookupObject(name,CurrentCell) == NULL) Node(name); if (LookupObject(name,CurrentCell) == NULL) Node(name);
@ -237,8 +234,8 @@ char *ReadExt(char *fname, int doflat, int *fnum)
SkipNewLine(NULL); SkipNewLine(NULL);
} }
else if (match(nexttok, "device")) { else if (match(nexttok, "device")) {
char dev_name[MAX_STR_LEN], dev_class[MAX_STR_LEN]; char dev_name[100], dev_class[100];
char gate[MAX_STR_LEN], drain[MAX_STR_LEN], source[MAX_STR_LEN], subs[MAX_STR_LEN]; char gate[200], drain[200], source[200], subs[200];
char inststr[64]; char inststr[64];
SkipTok(NULL); SkipTok(NULL);
strcpy(dev_class, nexttok); strcpy(dev_class, nexttok);
@ -308,8 +305,8 @@ char *ReadExt(char *fname, int doflat, int *fnum)
SkipNewLine(NULL); SkipNewLine(NULL);
} }
else if (match(nexttok, "fet")) { /* old-style FET record */ else if (match(nexttok, "fet")) { /* old-style FET record */
char fet_class[MAX_STR_LEN]; char fet_class[100];
char gate[MAX_STR_LEN], drain[MAX_STR_LEN], source[MAX_STR_LEN], subs[MAX_STR_LEN]; char gate[200], drain[200], source[200], subs[200];
char inststr[64]; char inststr[64];
SkipTok(NULL); SkipTok(NULL);
strcpy(fet_class, nexttok); strcpy(fet_class, nexttok);
@ -367,7 +364,7 @@ char *ReadExt(char *fname, int doflat, int *fnum)
SkipNewLine(NULL); SkipNewLine(NULL);
} }
else { else {
char ctop[MAX_STR_LEN], cbot[MAX_STR_LEN], cdummy[MAX_STR_LEN]; char ctop[200], cbot[200], cdummy[200];
SkipTok(NULL); SkipTok(NULL);
GetExtName(ctop, nexttok); GetExtName(ctop, nexttok);
SkipTok(NULL); SkipTok(NULL);
@ -377,8 +374,8 @@ char *ReadExt(char *fname, int doflat, int *fnum)
} }
} }
else if (match(nexttok, "use")) { else if (match(nexttok, "use")) {
char name[MAX_STR_LEN]; char name[200];
char instancename[MAX_STR_LEN]; char instancename[200];
char *basename; char *basename;
/* No cell is generated until at least one valid "node" or "use" */ /* No cell is generated until at least one valid "node" or "use" */
@ -392,7 +389,7 @@ char *ReadExt(char *fname, int doflat, int *fnum)
SkipTok(NULL); SkipTok(NULL);
GetExtName(name, nexttok); GetExtName(name, nexttok);
if ((basename = strrchr(name,'/')) != NULL) { if ((basename = strrchr(name,'/')) != NULL) {
char tmp[MAX_STR_LEN]; char tmp[200];
strcpy(tmp, basename+1); strcpy(tmp, basename+1);
strcpy(name, tmp); strcpy(name, tmp);
} }
@ -407,8 +404,8 @@ char *ReadExt(char *fname, int doflat, int *fnum)
SkipNewLine(NULL); SkipNewLine(NULL);
} }
else if (match(nexttok, "merge")) { else if (match(nexttok, "merge")) {
char name[MAX_STR_LEN]; char name[200];
char name2[MAX_STR_LEN]; char name2[200];
SkipTok(NULL); SkipTok(NULL);
GetExtName(name, nexttok); GetExtName(name, nexttok);
SkipTok(NULL); SkipTok(NULL);
@ -452,8 +449,7 @@ void simCell(char *name, int filenum)
struct nlist *tp, *tp2; struct nlist *tp, *tp2;
struct objlist *ob, *ob2; struct objlist *ob, *ob2;
char FileName[500], simclass; char FileName[500], simclass;
char writeLine[1024], paramString[128]; short i;
short i, p, mult;
double l, w, v; double l, w, v;
tp = LookupCellFile(name, filenum); tp = LookupCellFile(name, filenum);
@ -481,9 +477,9 @@ void simCell(char *name, int filenum)
} }
/* print out header list */ /* print out header list */
/* distance units are multiplied by invlambda */ /* distance units are multiplied by 100 (distances are in um) */
FlushString("| units: %d tech: scmos\n", 100 * invlambda); FlushString("| units: 100 tech: scmos\n");
/* now run through cell's contents, print instances */ /* now run through cell's contents, print instances */
for (ob = tp->cell; ob != NULL; ob = ob->next) { for (ob = tp->cell; ob != NULL; ob = ob->next) {
@ -519,12 +515,8 @@ void simCell(char *name, int filenum)
case CLASS_NPN: case CLASS_NPN:
simclass = 'b'; simclass = 'b';
break; break;
case CLASS_SUBCKT:
case CLASS_MODULE:
simclass = 'x';
break;
default: default:
simclass = '|'; simclass = 'x';
break; break;
} }
@ -597,115 +589,6 @@ void simCell(char *name, int filenum)
FlushString(" %g\n", v); FlushString(" %g\n", v);
break; break;
case CLASS_MODULE:
*writeLine = 'x';
*(writeLine + 1) = '\0';
mult = 1;
/* Important---Need to look up the cell definition; if
* the first pin is "drain" then it is a FET, and pins
* get swapped from D-G-S-B to G-S-D-B. Source and drain
* are treated here as equivalent because the .sim format
* has no concept of an asymmetric source and drain.
*/
ob2 = tp2->cell;
if ((*matchfunc)(ob2->next->name, "gate"))
{
strcat(writeLine, " ");
strcat(writeLine, NodeAlias(tp, ob->next));
strcat(writeLine, " ");
strcat(writeLine, NodeAlias(tp, ob));
ob2 = ob->next->next;
}
else
ob2 = ob;
while (ob2 != NULL) {
strcat(writeLine, " ");
strcat(writeLine, NodeAlias(tp, ob2));
ob2 = ob2->next;
if ((ob2 == NULL) || (ob2->type <= FIRSTPIN)) break;
}
if (ob2 && ob2->type == PROPERTY) {
struct valuelist *vl;
/* Only known parameters are L, W, X, and Y */
for (p = 0;; p++) {
vl = (struct valuelist *)(&(ob2->instance.props[p]));
if (vl->type == PROP_ENDLIST) {
strcat(writeLine, " l=1");
break;
}
else if ((*matchfunc)(vl->key, "L")) {
v = vl->value.dval;
sprintf(paramString, " l=%d", (int)(0.5 + (v * invlambda)));
strcat(writeLine, paramString);
break;
}
}
for (p = 0;; p++) {
vl = (struct valuelist *)(&(ob2->instance.props[p]));
if (vl->type == PROP_ENDLIST) {
strcat(writeLine, " w=1");
break;
}
else if ((*matchfunc)(vl->key, "W")) {
v = vl->value.dval;
sprintf(paramString, " w=%d", (int)(0.5 + (v * invlambda)));
strcat(writeLine, paramString);
break;
}
}
for (p = 0;; p++) {
vl = (struct valuelist *)(&(ob2->instance.props[p]));
if (vl->type == PROP_ENDLIST) {
strcat(writeLine, " x=0");
break;
}
else if ((*matchfunc)(vl->key, "X")) {
i = vl->value.ival;
sprintf(paramString, " x=%d", i);
strcat(writeLine, paramString);
break;
}
}
for (p = 0;; p++) {
vl = (struct valuelist *)(&(ob2->instance.props[p]));
if (vl->type == PROP_ENDLIST) {
strcat(writeLine, " y=0");
break;
}
else if ((*matchfunc)(vl->key, "Y")) {
i = vl->value.ival;
sprintf(paramString, " y=%d", i);
strcat(writeLine, paramString);
}
}
for (p = 0;; p++) {
vl = (struct valuelist *)(&(ob2->instance.props[p]));
if (vl->type == PROP_ENDLIST) {
break;
}
else if ((*matchfunc)(vl->key, "M")) {
if (vl->type == PROP_INTEGER)
mult = vl->value.ival;
else
mult = vl->value.dval;
}
}
}
strcat(writeLine, " ");
strcat(writeLine, tp2->name);
strcat(writeLine, "\n");
/* Multiple instances (M != 1) are written multiple times.
* NF is ignored in favor of having a single device with
* the total width.
*/
for (i = 0; i < mult; i++)
FlushString(writeLine);
break;
default: default:
FlushString("| unhandled component %s\n", tp2->name); FlushString("| unhandled component %s\n", tp2->name);
break; break;
@ -742,181 +625,6 @@ int StrIsInt(char *s)
return (1); return (1);
} }
/*------------------------------------------------------*/
/* Read a .prm format file. This is specifically to */
/* get the "device" lines that indicate how a SPICE */
/* subcircuit model or a .sim "x" record needs to be */
/* translated into a specific component type like a */
/* FET, diode, resistor, etc. */
/*------------------------------------------------------*/
char *ReadPrm(char *fname, int *fnum)
{
int filenum;
struct keyvalue *kvlist = NULL;
struct nlist *tp;
if ((filenum = OpenParseFile(fname, *fnum)) < 0) {
char name[MAX_STR_LEN];
SetExtension(name, fname, PRM_EXTENSION);
if (OpenParseFile(name, *fnum) < 0) {
Printf("Error in prm file read: No file %s\n",name);
*fnum = filenum;
return NULL;
}
}
/* Make sure all .prm file reading is case INsensitive */
/* This is because the only reason to read a PRM file */
/* is to find all the subcircuit device types so that */
/* a SPICE file can be read and a SIM file written. */
matchfunc = matchnocase;
matchintfunc = matchfile;
hashfunc = hashnocase;
CellDef(fname, filenum);
while (!EndParseFile()) {
char devicename[MAX_STR_LEN];
SkipTok(NULL);
if (EndParseFile()) break;
if (nexttok[0] == ';') continue; /* Comment line */
else if (nexttok[0] == '\0') continue; /* Blank line */
else if (match(nexttok, "lambda")) {
SkipTok(NULL);
invlambda = (int)(0.5 + (1.0 / atof(nexttok)));
SkipNewLine(NULL); /* skip any attributes */
}
else if (match(nexttok, "device")) {
SkipTok(NULL);
if (match(nexttok, "nfet")) {
SkipTok(NULL);
strcpy(devicename, nexttok);
/* Create 4-terminal nfet subcircuit device record */
if (LookupCellFile(devicename, filenum) == NULL) {
CellDef(devicename, filenum);
Port("drain");
Port("gate");
Port("source");
Port("bulk");
PropertyDouble(devicename, filenum, "l", 0.01, 0.0);
PropertyDouble(devicename, filenum, "w", 0.01, 0.0);
PropertyInteger(devicename, filenum, "nf", 0, 1);
PropertyInteger(devicename, filenum, "m", 0, 1);
SetClass(CLASS_MODULE);
EndCell();
ReopenCellDef(fname, filenum);
}
LinkProperties(devicename, kvlist);
SkipNewLine(NULL); /* skip any attributes */
}
else if (match(nexttok, "pfet")) {
SkipTok(NULL);
strcpy(devicename, nexttok);
/* Create 4-terminal pfet subcircuit device record */
if (LookupCellFile(devicename, filenum) == NULL) {
CellDef(devicename, filenum);
Port("drain");
Port("gate");
Port("source");
Port("well");
PropertyDouble(devicename, filenum, "l", 0.01, 0.0);
PropertyDouble(devicename, filenum, "w", 0.01, 0.0);
PropertyInteger(devicename, filenum, "nf", 0, 1);
PropertyInteger(devicename, filenum, "m", 0, 1);
SetClass(CLASS_MODULE);
EndCell();
ReopenCellDef(fname, filenum);
}
LinkProperties(devicename, kvlist);
SkipNewLine(NULL); /* skip various attributes */
}
else if (match(nexttok, "resistor")) {
SkipTok(NULL);
strcpy(devicename, nexttok);
/* Resistor device has additional record for the value */
/* (Need to do something with this. . . ?) */
SkipTok(NULL);
/* Create resistor subcircuit device record */
if (LookupCellFile(devicename, filenum) == NULL) {
CellDef(devicename, filenum);
Port("end_a");
Port("end_b");
PropertyDouble(devicename, filenum, "value", 0.01, 0.0);
PropertyDouble(devicename, filenum, "l", 0.01, 0.0);
PropertyDouble(devicename, filenum, "w", 0.01, 0.0);
PropertyInteger(devicename, filenum, "m", 0, 1);
SetClass(CLASS_MODULE);
EndCell();
ReopenCellDef(fname, filenum);
}
LinkProperties(devicename, kvlist);
SkipNewLine(NULL); /* skip various attributes */
}
else if (match(nexttok, "capacitor")) {
SkipTok(NULL);
strcpy(devicename, nexttok);
/* Capacitor device has additional record for the value */
/* (Need to do something with this. . . ?) */
SkipTok(NULL);
/* Create capacitor subcircuit device record */
if (LookupCellFile(devicename, filenum) == NULL) {
CellDef(devicename, filenum);
Port("top");
Port("bottom");
PropertyDouble(devicename, filenum, "value", 0.01, 0.0);
PropertyDouble(devicename, filenum, "l", 0.01, 0.0);
PropertyDouble(devicename, filenum, "w", 0.01, 0.0);
PropertyInteger(devicename, filenum, "m", 0, 1);
SetClass(CLASS_MODULE);
EndCell();
ReopenCellDef(fname, filenum); /* Reopen */
}
LinkProperties(devicename, kvlist);
SkipNewLine(NULL);
}
else if (match(nexttok, "diode")) {
SkipTok(NULL);
strcpy(devicename, nexttok);
/* Create diode subcircuit device record */
if (LookupCellFile(devicename, filenum) == NULL) {
CellDef(devicename, filenum);
Port("anode");
Port("cathode");
PropertyInteger(devicename, filenum, "m", 0, 1);
SetClass(CLASS_MODULE);
EndCell();
ReopenCellDef(fname, filenum); /* Reopen */
}
LinkProperties(devicename, kvlist);
SkipNewLine(NULL);
}
else {
Printf("Unknown device type in .prm: '%s'\n", nexttok);
InputParseError(stderr);
SkipNewLine(NULL);
}
}
else {
/* Could spell out all the keywords used in .prm files */
/* but probably not worth the effort. */
SkipNewLine(NULL);
}
DeleteProperties(&kvlist);
}
EndCell();
CloseParseFile();
tp = LookupCellFile(fname, filenum);
if (tp) tp->flags |= CELL_TOP;
*fnum = filenum;
return fname;
}
/*-------------------------*/ /*-------------------------*/
/* Read a .sim format file */ /* Read a .sim format file */
/*-------------------------*/ /*-------------------------*/
@ -931,11 +639,11 @@ char *ReadSim(char *fname, int *fnum)
double simscale = 1.0; double simscale = 1.0;
if ((filenum = OpenParseFile(fname, *fnum)) < 0) { if ((filenum = OpenParseFile(fname, *fnum)) < 0) {
char name[MAX_STR_LEN]; char name[100];
SetExtension(name, fname, SIM_EXTENSION); SetExtension(name, fname, SIM_EXTENSION);
if (OpenParseFile(name, *fnum) < 0) { if (OpenParseFile(name, *fnum) < 0) {
Printf("Error in sim file read: No file %s\n",name); Printf("Error in ext file read: No file %s\n",name);
*fnum = filenum; *fnum = filenum;
return NULL; return NULL;
} }
@ -944,7 +652,7 @@ char *ReadSim(char *fname, int *fnum)
/* Make sure all .sim file reading is case sensitive */ /* Make sure all .sim file reading is case sensitive */
matchfunc = match; matchfunc = match;
matchintfunc = matchfile; matchintfunc = matchfile;
hashfunc = hashcase; hashfunc = hash;
CellDef(fname, filenum); CellDef(fname, filenum);
@ -961,7 +669,7 @@ char *ReadSim(char *fname, int *fnum)
SkipNewLine(NULL); SkipNewLine(NULL);
} }
else if (match(nexttok, "n")) { else if (match(nexttok, "n")) {
char gate[MAX_STR_LEN], drain[MAX_STR_LEN], source[MAX_STR_LEN]; char gate[200], drain[200], source[200];
char inststr[25], *instptr = NULL; char inststr[25], *instptr = NULL;
SkipTok(NULL); SkipTok(NULL);
@ -1005,7 +713,7 @@ char *ReadSim(char *fname, int *fnum)
LinkProperties("n", kvlist); LinkProperties("n", kvlist);
} }
else if (match(nexttok, "p")) { else if (match(nexttok, "p")) {
char gate[MAX_STR_LEN], drain[MAX_STR_LEN], source[MAX_STR_LEN]; char gate[200], drain[200], source[200];
char inststr[25], *instptr = NULL; char inststr[25], *instptr = NULL;
SkipTok(NULL); SkipTok(NULL);
GetExtName(gate, nexttok); GetExtName(gate, nexttok);
@ -1045,7 +753,7 @@ char *ReadSim(char *fname, int *fnum)
LinkProperties("p", kvlist); LinkProperties("p", kvlist);
} }
else if (match(nexttok, "e")) { /* 3-port capacitors (poly/poly2) */ else if (match(nexttok, "e")) { /* 3-port capacitors (poly/poly2) */
char gate[MAX_STR_LEN], drain[MAX_STR_LEN], source[MAX_STR_LEN]; char gate[200], drain[200], source[200];
char inststr[25], *instptr = NULL; char inststr[25], *instptr = NULL;
SkipTok(NULL); SkipTok(NULL);
GetExtName(gate, nexttok); GetExtName(gate, nexttok);
@ -1079,7 +787,7 @@ char *ReadSim(char *fname, int *fnum)
E(fname, instptr, gate, drain, source); E(fname, instptr, gate, drain, source);
} }
else if (match(nexttok, "b")) { /* bipolars added by Tim 7/16/96 */ else if (match(nexttok, "b")) { /* bipolars added by Tim 7/16/96 */
char base[MAX_STR_LEN], emitter[MAX_STR_LEN], collector[MAX_STR_LEN]; char base[200], emitter[200], collector[200];
char inststr[25], *instptr = NULL; char inststr[25], *instptr = NULL;
SkipTok(NULL); SkipTok(NULL);
GetExtName(base, nexttok); GetExtName(base, nexttok);
@ -1117,7 +825,7 @@ char *ReadSim(char *fname, int *fnum)
SkipNewLine(NULL); SkipNewLine(NULL);
} }
else { else {
char ctop[MAX_STR_LEN], cbot[MAX_STR_LEN], cdummy[MAX_STR_LEN]; char ctop[200], cbot[200], cdummy[200];
SkipTok(NULL); SkipTok(NULL);
GetExtName(ctop, nexttok); GetExtName(ctop, nexttok);
if (LookupObject(ctop, CurrentCell) == NULL) if (LookupObject(ctop, CurrentCell) == NULL)
@ -1138,11 +846,11 @@ char *ReadSim(char *fname, int *fnum)
} }
else if (match(nexttok, "r")) { /* 2-port resistors */ else if (match(nexttok, "r")) { /* 2-port resistors */
if (IgnoreRC) { if (IgnoreRC) {
/* ignore all resistances */ /* ignore all capacitances */
SkipNewLine(NULL); SkipNewLine(NULL);
} }
else { else {
char rtop[MAX_STR_LEN], rbot[MAX_STR_LEN]; char rtop[200], rbot[200];
SkipTok(NULL); SkipTok(NULL);
GetExtName(rtop, nexttok); GetExtName(rtop, nexttok);
if (LookupObject(rtop, CurrentCell) == NULL) if (LookupObject(rtop, CurrentCell) == NULL)
@ -1166,7 +874,7 @@ char *ReadSim(char *fname, int *fnum)
SkipNewLine(NULL); SkipNewLine(NULL);
} }
else { else {
char rtop[MAX_STR_LEN], rbot[MAX_STR_LEN], rdummy[MAX_STR_LEN]; char rtop[200], rbot[200], rdummy[200];
char inststr[25], *instptr = NULL; char inststr[25], *instptr = NULL;
SkipTok(NULL); SkipTok(NULL);
GetExtName(rdummy, nexttok); GetExtName(rdummy, nexttok);
@ -1208,7 +916,7 @@ char *ReadSim(char *fname, int *fnum)
SkipNewLine(NULL); SkipNewLine(NULL);
} }
else if (match(nexttok, "=")) { else if (match(nexttok, "=")) {
char node1[MAX_STR_LEN], node2[MAX_STR_LEN]; char node1[200], node2[200];
SkipTok(NULL); SkipTok(NULL);
GetExtName(node1, nexttok); GetExtName(node1, nexttok);
SkipTok(NULL); SkipTok(NULL);

View File

@ -53,7 +53,7 @@ void flattenCell(char *name, int file)
struct nlist *ChildCell; struct nlist *ChildCell;
struct objlist *tmp, *ob2, *ob3; struct objlist *tmp, *ob2, *ob3;
int notdone, rnodenum; int notdone, rnodenum;
char tmpstr[MAX_STR_LEN]; char tmpstr[200];
int nextnode, oldmax; int nextnode, oldmax;
#if !OLDPREFIX #if !OLDPREFIX
int prefixlength; int prefixlength;
@ -66,13 +66,9 @@ void flattenCell(char *name, int file)
else else
ThisCell = LookupCellFile(name, file); ThisCell = LookupCellFile(name, file);
if (ThisCell == NULL) { if (ThisCell == NULL) {
Printf("No cell %s (%d) found.\n", name, file); Printf("No cell %s found.\n", name);
return; return;
} }
/* Placeholder cells must not be flattened */
if (ThisCell->flags & CELL_PLACEHOLDER) return;
FreeNodeNames(ThisCell); FreeNodeNames(ThisCell);
ParentParams = ThisCell->cell; ParentParams = ThisCell->cell;
@ -136,16 +132,17 @@ void flattenCell(char *name, int file)
ob2 = ob2->next; ob2 = ob2->next;
} }
/* delete all port elements from child */ /* delete all port elements from child */
while (IsPort(ChildObjList)) { while (IsPort(ChildObjList)) {
/* delete all ports at beginning of list */ /* delete all ports at beginning of list */
if (Debug) Printf("deleting leading port from child\n"); if (Debug) Printf("deleting leading port from child\n");
tmp = ChildObjList->next; tmp = ChildObjList->next;
FreeObjectAndHash(ChildObjList, ChildCell); FreeObjectAndHash(ChildObjList, ChildCell);
if ((ChildObjList = tmp) == NULL) break; ChildObjList = tmp;
} }
tmp = ChildObjList; tmp = ChildObjList;
while (tmp && (tmp->next != NULL)) { while (tmp->next != NULL) {
if (IsPort(tmp->next)) { if (IsPort(tmp->next)) {
ob2 = (tmp->next)->next; ob2 = (tmp->next)->next;
if (Debug) Printf("deleting a port from child\n"); if (Debug) Printf("deleting a port from child\n");
@ -242,13 +239,6 @@ void flattenCell(char *name, int file)
ThisCell->dumped = 1; /* indicate cell has been flattened */ 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 -- */ /* flattenInstancesOf -- */
/* */ /* */
@ -271,7 +261,6 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
struct nlist *ThisCell; struct nlist *ThisCell;
struct nlist *ChildCell; struct nlist *ChildCell;
struct objlist *tmp, *ob2, *ob3; struct objlist *tmp, *ob2, *ob3;
struct linkednode *checknodes = NULL, *newlnode, *chknode;
int notdone, rnodenum; int notdone, rnodenum;
char tmpstr[1024]; char tmpstr[1024];
int nextnode, oldmax, numflat = 0; int nextnode, oldmax, numflat = 0;
@ -289,18 +278,16 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
} }
else { else {
if (Debug) if (Debug)
Printf("Flattening instances of %s within cell: %s (%d)\n", instance, Printf("Flattening instances of %s within cell: %s\n", instance, name);
name, fnum);
if (fnum == -1) if (fnum == -1)
ThisCell = LookupCell(name); ThisCell = LookupCell(name);
else else
ThisCell = LookupCellFile(name, fnum); ThisCell = LookupCellFile(name, fnum);
if (ThisCell == NULL) { if (ThisCell == NULL) {
Printf("No cell %s (%d) found.\n", name, fnum); Printf("No cell %s found.\n", name);
return 0; return 0;
} }
} }
FreeNodeNames(ThisCell); FreeNodeNames(ThisCell);
ParentParams = ThisCell->cell; ParentParams = ThisCell->cell;
@ -337,10 +324,6 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
LastObj = ParentParams; LastObj = ParentParams;
continue; continue;
} }
if (ChildCell->flags & CELL_PLACEHOLDER) {
LastObj = ParentParams;
continue; // Placeholder cells must not be flattened
}
if (ChildCell == ThisCell) { if (ChildCell == ThisCell) {
LastObj = ParentParams; LastObj = ParentParams;
continue; // Avoid infinite loop continue; // Avoid infinite loop
@ -389,15 +372,21 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
/* update node numbers in child to unique numbers */ /* update node numbers in child to unique numbers */
oldmax = 0; 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 (tmp->node > oldmax) oldmax = tmp->node;
if (tmp->node > 0) tmp->node += (nextnode - 1); 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++;
} }
nextnode += oldmax;
/* copy nodenumbers of ports from parent */ /* copy nodenumbers of ports from parent */
ob2 = ParentParams; ob2 = ParentParams;
for (tmp = ChildStart; tmp && IsPort(tmp); tmp = tmp->next) { for (tmp = ChildStart; tmp != NULL; tmp = tmp->next) {
if (IsPort(tmp)) {
if (tmp->node > 0) { if (tmp->node > 0) {
if (ob2->node == -1) { if (ob2->node == -1) {
@ -425,16 +414,6 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
} }
UpdateNodeNumbers(ChildStart, 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 /* in pathological cases, the lengths of the port lists may
* change. This is an error, but that is no reason to allow * change. This is an error, but that is no reason to allow
@ -445,6 +424,7 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
if (ob2 == NULL) break; if (ob2 == NULL) break;
} }
}
/* Using name == NULL to indicate that a .ext file is being */ /* Using name == NULL to indicate that a .ext file is being */
/* flattened on the fly. This is quick & dirty. */ /* flattened on the fly. This is quick & dirty. */
@ -537,10 +517,11 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
/* Do property inheritance */ /* Do property inheritance */
if (CurrentProp) { /* NOTE: Need to do: Check properties for M > 1 and decrement
int i, mval; * and repeat without moving CurrentProp
struct valuelist *kv; */
if (CurrentProp) {
for (ob2 = ChildStart; ob2 != NULL; ob2=ob2->next) { for (ob2 = ChildStart; ob2 != NULL; ob2=ob2->next) {
/* If the parent cell has properties to declare, then */ /* If the parent cell has properties to declare, then */
@ -548,49 +529,10 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
/* spiceparams dictionary is active (during file */ /* spiceparams dictionary is active (during file */
/* reading only). */ /* reading only). */
if (ob2->type == PROPERTY) { if (ob2->type == PROPERTY)
ReduceExpressions(ob2, CurrentProp, ChildCell, ReduceExpressions(ob2, CurrentProp, ChildCell,
(spiceparams.hashtab == NULL) ? 0 : 1); (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 /* Repeat for each property record, as each property represents a
* unique instance that must be flattened individually. * unique instance that must be flattened individually.
@ -602,11 +544,9 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
else break; else break;
/* Put the child cell at the start of ChildObjList */ /* Put the child cell at the start of ChildObjList */
if (ChildEnd) {
ChildEnd->next = ChildObjList; ChildEnd->next = ChildObjList;
ChildObjList = ChildStart; ChildObjList = ChildStart;
} }
}
/* Put the child cell at the start of ChildObjList */ /* Put the child cell at the start of ChildObjList */
if (ChildEnd) { if (ChildEnd) {
@ -657,29 +597,6 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
NextObj = ParentParams; NextObj = ParentParams;
} /* repeat until no more instances found */ } /* 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); CacheNodeNames(ThisCell);
ThisCell->dumped = 1; /* indicate cell has been flattened */ ThisCell->dumped = 1; /* indicate cell has been flattened */
return numflat; return numflat;
@ -771,7 +688,7 @@ void convertGlobalsOf(char *name, int fnum, char *instance)
else else
ThisCell = LookupCellFile(name, fnum); ThisCell = LookupCellFile(name, fnum);
if (ThisCell == NULL) { if (ThisCell == NULL) {
Printf("No cell %s (%d) found.\n", name, fnum); Printf("No cell %s found.\n", name);
return; return;
} }
} }
@ -1201,7 +1118,7 @@ int UniquePins(char *name, int filenum)
ThisCell = LookupCellFile(name, filenum); ThisCell = LookupCellFile(name, filenum);
if (ThisCell == NULL) { if (ThisCell == NULL) {
Printf("No cell %s (%d) found.\n", name, filenum); Printf("No cell %s found.\n", name);
return 0; return 0;
} }
@ -1223,27 +1140,7 @@ int UniquePins(char *name, int filenum)
if (ob->node > 0) { if (ob->node > 0) {
nodecount[ob->node]++; nodecount[ob->node]++;
if (nodecount[ob->node] == 2) { if (nodecount[ob->node] == 2) {
if (!(*matchfunc)(firstport[ob->node]->name, ob->name)) { Printf("Duplicate pin %s in cell %s\n", ob->name, ThisCell->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]--;
/* Note: Previously there was code here to move the shorted port
* next to the pin it is shorted to. This causes the cell def pins
* to become scrambled with respect to the pin order of its instances.
* Removed the code 9/1/2023. But---Not sure if any code depends
* on shorted pins being adjacent.
*/
/* When two pins are shorted, they are by definition permutable */
PermuteSetup(ThisCell->name, ThisCell->file, ob->name,
firstport[ob->node]->name);
continue;
}
else {
Printf("Duplicate pin %s in cell %s (%d)\n", ob->name,
ThisCell->name, filenum);
}
} }
if (nodecount[ob->node] > 1) { if (nodecount[ob->node] > 1) {
/* Remove this node; prep for removal by marking with UNKNOWN */ /* Remove this node; prep for removal by marking with UNKNOWN */
@ -1308,14 +1205,6 @@ int UniquePins(char *name, int filenum)
return 1; return 1;
} }
/* Structure used below for keeping track of node numbers
* belonging to removed nodes.
*/
struct LinkedNum {
int node;
struct LinkedNum *next;
};
/*------------------------------------------------------*/ /*------------------------------------------------------*/
/* Callback function for CleanupPins */ /* Callback function for CleanupPins */
/* Note that if the first pin of the instance is a */ /* Note that if the first pin of the instance is a */
@ -1328,7 +1217,6 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
struct nlist *ptr; struct nlist *ptr;
struct objlist *ob, *obt, *lob, *nob, *firstpin, *pob; struct objlist *ob, *obt, *lob, *nob, *firstpin, *pob;
struct nlist *tc = (struct nlist *)clientdata; struct nlist *tc = (struct nlist *)clientdata;
struct LinkedNum *newnodenum, *removedNodes = (struct LinkedNum *)NULL;
int pinnum; int pinnum;
char *saveinst = NULL; char *saveinst = NULL;
@ -1384,15 +1272,6 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
saveinst = ob->instance.name; saveinst = ob->instance.name;
} }
if (ob->model.class != NULL) FREE(ob->model.class); if (ob->model.class != NULL) FREE(ob->model.class);
// Record the net number of the pin being removed, to
// check at the end if the net belonged to a pin that
// got orphaned.
newnodenum = (struct LinkedNum *)MALLOC(sizeof(struct LinkedNum));
newnodenum->node = ob->node;
newnodenum->next = removedNodes;
removedNodes = newnodenum;
FREE(ob); FREE(ob);
} }
else { else {
@ -1436,28 +1315,6 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
} }
} }
while (removedNodes != NULL) {
int nodenum = removedNodes->node;
struct objlist *ob2;
/* Only concerned with nodes that are in the pin list of ptr->cell */
for (ob = ptr->cell; ob != NULL; ob = ob->next) {
if (ob->type != PORT) break;
if (ob->node == nodenum) break;
}
if (ob && (ob->type == PORT)) {
/* Check if this node number exists only in the port record */
for (nob = ob->next; nob != NULL; nob = nob->next)
if (nob->node == nodenum) break;
if (nob == NULL) {
ob->node = -1; /* This pin is now disconnected */
}
}
newnodenum = removedNodes;
removedNodes = removedNodes->next;
FREE(newnodenum);
}
if (saveinst != NULL) FREE(saveinst); if (saveinst != NULL) FREE(saveinst);
return NULL; /* Keep the search going */ return NULL; /* Keep the search going */
} }
@ -1482,7 +1339,7 @@ int CleanupPins(char *name, int filenum)
ThisCell = LookupCellFile(name, filenum); ThisCell = LookupCellFile(name, filenum);
if (ThisCell == NULL) { if (ThisCell == NULL) {
Printf("No cell %s (%d) found.\n", name, filenum); Printf("No cell %s found.\n", name);
return 0; return 0;
} }
@ -1564,22 +1421,6 @@ typedef struct ecomplist {
ECompListPtr next; ECompListPtr next;
} ECompList; } 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 */ /* Survey the contents of a cell and sort into a hash */
/*------------------------------------------------------*/ /*------------------------------------------------------*/
@ -1677,9 +1518,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
struct hashdict compdict; struct hashdict compdict;
ECompare *ecomp, *ncomp; ECompare *ecomp, *ncomp;
ECompList *list0X, *listX0; ECompList *list0X, *listX0;
int hascontents1, hascontents2; int match, modified = 0;
int match, modified1 = 0, modified2 = 0;
int not_top;
if (file1 == -1) if (file1 == -1)
tc1 = LookupCell(name1); tc1 = LookupCell(name1);
@ -1694,7 +1533,6 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
if (tc1 == NULL || tc2 == NULL) return 0; if (tc1 == NULL || tc2 == NULL) return 0;
InitializeHashTable(&compdict, OBJHASHSIZE); InitializeHashTable(&compdict, OBJHASHSIZE);
listX0 = list0X = NULL;
// Gather information about instances of cell "name1" // Gather information about instances of cell "name1"
SurveyCell(tc1, &compdict, file1, file2, 0); SurveyCell(tc1, &compdict, file1, file2, 0);
@ -1707,6 +1545,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
// in the hierarchy of each instance contain devices // in the hierarchy of each instance contain devices
// or subcircuits that have more in the compared circuit. // or subcircuits that have more in the compared circuit.
listX0 = list0X = NULL;
ecomp = (ECompare *)HashFirst(&compdict); ecomp = (ECompare *)HashFirst(&compdict);
while (ecomp != NULL) { while (ecomp != NULL) {
@ -1743,39 +1582,25 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
} }
} }
else { else {
// cell exists in one circuit but not the other, so flatten it. match = 0;
// match = 0;
break; break;
} }
} }
} }
if (match) { if (match) {
if (ecomp->cell1 && (ecomp->num1 > 0) && if (ecomp->cell1 && (ecomp->num1 > 0)) {
(!(ecomp->cell1->flags & CELL_PLACEHOLDER))) { Fprintf(stdout, "Flattening instances of %s in cell %s"
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
" makes a better match\n", ecomp->cell1->name, " makes a better match\n", ecomp->cell1->name,
name1, file1); name1);
if (flattenInstancesOf(name1, file1, ecomp->cell1->name) > 0) flattenInstancesOf(name1, file1, ecomp->cell1->name);
modified1++;
} }
else if (ecomp->cell1 && (ecomp->num1 > 0)) { if (ecomp->cell2 && (ecomp->num2 > 0)) {
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)" Fprintf(stdout, "Flattening instances of %s in cell %s"
" would make a better match but is prohibited.\n",
ecomp->cell1->name, name1, file1);
}
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, " makes a better match\n", ecomp->cell2->name,
name2, file2); name2);
if (flattenInstancesOf(name2, file2, ecomp->cell2->name) > 0) flattenInstancesOf(name2, file2, ecomp->cell2->name);
modified2++;
}
else if (ecomp->cell2 && (ecomp->num2 > 0)) {
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
" would make a better match but is prohibited.\n",
ecomp->cell2->name, name2, file2);
} }
modified++;
} }
/* Reset or apply the count adjustments */ /* Reset or apply the count adjustments */
@ -1824,7 +1649,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
} }
/* Case 2: Cell2 class is a subcircuit, and flattening */ /* 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) && else if ((ecomp->num1 != ecomp->num2) && (ecomp->cell2 != NULL) &&
(ecomp->num2 != 0) && (ecomp->cell2->class == CLASS_SUBCKT)) { (ecomp->num2 != 0) && (ecomp->cell2->class == CLASS_SUBCKT)) {
@ -1852,26 +1677,13 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
} }
} }
if (match) { if (match) {
if (ecomp->cell2) {
/* Don't flatten if cell1 is a black box, because it */ Fprintf(stdout, "Flattening instances of %s in cell %s"
/* 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, " makes a better match\n", ecomp->cell2->name,
name2, file2); name2);
if (flattenInstancesOf(name2, file2, ecomp->cell2->name) > 0) flattenInstancesOf(name2, file2, ecomp->cell2->name);
modified2++;
}
else if (ecomp->cell2) {
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
" would make a better match but is prohibited.\n",
ecomp->cell2->name, name2, file2);
}
} }
modified++;
} }
/* Reset or apply the count adjustments */ /* Reset or apply the count adjustments */
@ -1895,7 +1707,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
} }
/* Case 3: Cell1 class is a subcircuit, and flattening */ /* Case 3: Cell1 class is a subcircuit, and flattening */
/* it (without regard to cell2) improves the matching. */ /* (it without regard to cell1) improves the matching. */
else if ((ecomp->num1 != ecomp->num2) && (ecomp->cell1 != NULL) && else if ((ecomp->num1 != ecomp->num2) && (ecomp->cell1 != NULL) &&
(ecomp->num1 != 0) && (ecomp->cell1->class == CLASS_SUBCKT)) { (ecomp->num1 != 0) && (ecomp->cell1->class == CLASS_SUBCKT)) {
@ -1923,26 +1735,13 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
} }
} }
if (match) { if (match) {
if (ecomp->cell1) {
/* Don't flatten if cell2 is a black box, because it */ Fprintf(stdout, "Flattening instances of %s in cell %s"
/* 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, " makes a better match\n", ecomp->cell1->name,
name1, file1); name1);
if (flattenInstancesOf(name1, file1, ecomp->cell1->name) > 0) flattenInstancesOf(name1, file1, ecomp->cell1->name);
modified1++;
}
else if (ecomp->cell1) {
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
" would make a better match but is prohibited.\n",
ecomp->cell1->name, name1, file1);
}
} }
modified++;
} }
/* Reset or apply the count adjustments */ /* Reset or apply the count adjustments */
@ -1970,8 +1769,6 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
// Remove non-matching zero-value devices. This can // Remove non-matching zero-value devices. This can
// be done on a per-instance basis. // be done on a per-instance basis.
not_top = (PeekCompareQueueTop(NULL, NULL, NULL, NULL) == -1) ? FALSE : TRUE;
ecomp = (ECompare *)HashFirst(&compdict); ecomp = (ECompare *)HashFirst(&compdict);
while (ecomp != NULL) { while (ecomp != NULL) {
if ((ecomp->num1 != ecomp->num2) && (ecomp->cell1 != NULL) && if ((ecomp->num1 != ecomp->num2) && (ecomp->cell1 != NULL) &&
@ -2020,65 +1817,17 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
} }
if (found) break; if (found) break;
} }
if (found) {
/* Beware remove shorting devices that */
/* connect two ports. Otherwise the */
/* port lists get screwed up. It is */
/* better in that case to force the */
/* cells to be declared mismatched. */
/* This is ignored for a top-level cell */
/* because it will just show up as a */
/* port mismatch error as it should. */
/* (12/12/2025---disabling this worked; */
/* may need to go back to a failing */
/* example and determine how pin */
/* matching gets scrambled.) */
if ((not_top == TRUE) &&
(ecomp->cell1->class != CLASS_ISOURCE)) {
int found1 = FALSE;
int found2 = FALSE;
for (ob2 = tc1->cell; ob2; ob2 = ob2->next) {
if (!IsPort(ob2)) break;
else if (ob2->node == node1)
found1 = TRUE;
else if (ob2->node == node2)
found2 = TRUE;
if (found1 && found2) {
Fprintf(stdout, "Warning: "
"zero-valued device connects "
"port %s to another port; pin "
"matching may be affected.\n",
ob2->name);
// found = FALSE;
break;
}
}
}
}
if (found) { if (found) {
Fprintf(stdout, "Removing zero-valued device " Fprintf(stdout, "Removing zero-valued device "
"%s from cell %s (%d) makes a better " "%s from cell %s makes a better match\n",
"match\n", tsub1->name,
tsub1->name, tc1->name, tc1->file); tc1->name);
/* A current source is an open, while a */ /* A current source is an open, while a */
/* resistor or voltage source is a short. */ /* resistor or voltage source is a short. */
if (ecomp->cell1->class != CLASS_ISOURCE) { if (ecomp->cell1->class != CLASS_ISOURCE) {
/* merge node of endpoints */ /* 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) { for (ob2 = tc1->cell; ob2; ob2 = ob2->next) {
if (ob2->node == node2) if (ob2->node == node2)
ob2->node = node1; ob2->node = node1;
@ -2105,7 +1854,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
/* Remove from list */ /* Remove from list */
ecomp->num1--; ecomp->num1--;
modified1++; modified++;
ob1 = lob; ob1 = lob;
} }
@ -2177,47 +1926,16 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
break; break;
} }
} }
/* (See comments above about removing shorts */
/* between two ports.) */
if ((not_top == TRUE) &&
(ecomp->cell2->class != CLASS_ISOURCE)) {
int found1 = FALSE;
int found2 = FALSE;
for (ob1 = tc2->cell; ob1; ob1 = ob1->next) {
if (!IsPort(ob1)) break;
else if (ob1->node == node1)
found1 = TRUE;
else if (ob1->node == node2)
found2 = TRUE;
if (found1 && found2) {
found = FALSE;
break;
}
}
}
if (found) break; if (found) break;
} }
if (found) { if (found) {
Fprintf(stdout, "Removing zero-valued device " Fprintf(stdout, "Removing zero-valued device "
"%s from cell %s (%d) makes a better " "%s from cell %s makes a better match\n",
"match\n", tsub2->name,
tsub2->name, tc2->name, tc2->file); tc2->name);
/* merge node of endpoints */ /* merge node of endpoints */
if (ecomp->cell2->class != CLASS_ISOURCE) { 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) { for (ob1 = tc2->cell; ob1; ob1 = ob1->next) {
if (ob1->node == node2) if (ob1->node == node2)
ob1->node = node1; ob1->node = node1;
@ -2243,8 +1961,8 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
} }
/* Remove from list */ /* Remove from list */
ecomp->num2--; ecomp->num1--;
modified2++; modified++;
ob2 = lob; ob2 = lob;
} }
@ -2278,7 +1996,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
// are no other modifications, as this rule is relaxed compared to other // are no other modifications, as this rule is relaxed compared to other
// rules, and the other rules should be exhaustively applied first. // rules, and the other rules should be exhaustively applied first.
if ((listX0 != NULL) && (list0X != NULL) && ((modified1 + modified2) == 0)) { if ((listX0 != NULL) && (list0X != NULL) && (modified == 0)) {
ECompare *ecomp0X, *ecompX0; ECompare *ecomp0X, *ecompX0;
ECompList *elist0X, *elistX0; ECompList *elist0X, *elistX0;
for (elistX0 = listX0; elistX0; elistX0 = elistX0->next) { for (elistX0 = listX0; elistX0; elistX0 = elistX0->next) {
@ -2304,24 +2022,13 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
ecompX0->cell1->file, &compdict); ecompX0->cell1->file, &compdict);
if (dstr) *dstr = '['; if (dstr) *dstr = '[';
if ((ncomp == ecomp0X) && (ecomp0X->num2 <= ecompX0->num1)) { if ((ncomp == ecomp0X) && (ecomp0X->num2 <= ecompX0->num1)) {
if (!(ecompX0->cell1->flags & CELL_PLACEHOLDER)) { Fprintf(stdout, "Flattening instances of %s in cell %s"
Fprintf(stdout, "Flattening instances of %s in cell" " makes a better match\n", ecompX0->cell1->name,
" %s (%d) makes a better match\n", name1);
ecompX0->cell1->name, name1, file1); flattenInstancesOf(name1, file1, ecompX0->cell1->name);
if (flattenInstancesOf(name1, file1,
ecompX0->cell1->name) > 0) {
ecompX0->num1 = 0; ecompX0->num1 = 0;
ecomp0X->num1 += ecompX0->num1; ecomp0X->num1 += ecompX0->num1;
modified1++; modified++;
}
}
else
{
Fprintf(stdout, "Flattening instances of %s in "
"cell %s (%d) would make a better "
"match but is prohibited.\n",
ecompX0->cell1->name, name1, file1);
}
break; break;
} }
} }
@ -2341,23 +2048,13 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
ecomp0X->cell2->file, &compdict); ecomp0X->cell2->file, &compdict);
if (dstr) *dstr = '['; if (dstr) *dstr = '[';
if ((ncomp == ecompX0) && (ecompX0->num1 <= ecomp0X->num2)) { if ((ncomp == ecompX0) && (ecompX0->num1 <= ecomp0X->num2)) {
if (!(ecomp0X->cell2->flags & CELL_PLACEHOLDER)) { Fprintf(stdout, "Flattening instances of %s in cell %s"
Fprintf(stdout, "Flattening instances of %s in cell" " makes a better match\n", ecomp0X->cell2->name,
" %s (%d) makes a better match\n", name2);
ecomp0X->cell2->name, name2, file2); flattenInstancesOf(name2, file2, ecomp0X->cell2->name);
if (flattenInstancesOf(name2, file2,
ecomp0X->cell2->name) > 0) {
ecomp0X->num2 = 0; ecomp0X->num2 = 0;
ecompX0->num2 += ecomp0X->num2; ecompX0->num2 += ecomp0X->num2;
modified2++; modified++;
}
}
else {
Fprintf(stdout, "Flattening instances of %s in "
"cell %s (%d) would make a better "
"match but is prohibited.\n",
ecompX0->cell2->name, name2, file2);
}
break; break;
} }
} }
@ -2367,7 +2064,6 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
} }
} }
done:
// Free the hash table and its contents. // Free the hash table and its contents.
ecomp = (ECompare *)HashFirst(&compdict); ecomp = (ECompare *)HashFirst(&compdict);
@ -2388,17 +2084,5 @@ done:
FREE(list0X); FREE(list0X);
list0X = nextptr; list0X = nextptr;
} }
return modified;
// If either netlist was modified, rebuild its node cache
if (modified1 > 0) {
FreeNodeNames(tc1);
CacheNodeNames(tc1);
}
if (modified2 > 0) {
FreeNodeNames(tc2);
CacheNodeNames(tc2);
}
return modified1 + modified2;
} }

View File

@ -1,8 +0,0 @@
#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 */

View File

@ -30,8 +30,8 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#endif #endif
#include "netgen.h" #include "netgen.h"
#include "objlist.h"
#include "hash.h" #include "hash.h"
#include "objlist.h"
unsigned long (*hashfunc)(char *, int) = NULL; unsigned long (*hashfunc)(char *, int) = NULL;
int (*matchfunc)(char *, char *) = NULL; int (*matchfunc)(char *, char *) = NULL;
@ -137,39 +137,32 @@ static unsigned char uppercase[] = {
// horrible things can happen, as, for example, names AOI12 and OAI12 // horrible things can happen, as, for example, names AOI12 and OAI12
// have exactly the same hash result. Lousy for binning and even // have exactly the same hash result. Lousy for binning and even
// lousier for generating class magic numbers. // lousier for generating class magic numbers.
//
// Updated again 4/2/2026 to the FNV-1a hash, which is better than
// SDBM for this application, according to ChatGPT.
unsigned long hashnocase(char *s, int hashsize) unsigned long hashnocase(char *s, int hashsize)
{ {
unsigned long hashval = 2166136261ul; unsigned long hashval;
for (; *s != '\0'; s++) {
hashval ^= uppercase[*s]; for (hashval = 0; *s != '\0'; )
hashval *= 16777619ul; hashval = uppercase[*s++]
} + (hashval << 6) + (hashval << 16) - hashval;
return (hashsize == 0) ? hashval : (hashval % hashsize); return (hashsize == 0) ? hashval : (hashval % hashsize);
} }
unsigned long hashcase(char *s, int hashsize) unsigned long hash(char *s, int hashsize)
{ {
unsigned long hashval = 2166136261ul; unsigned long hashval;
for (; *s != '\0'; s++) {
hashval ^= (unsigned char)(*s); for (hashval = 0; *s != '\0'; )
hashval *= 16777619ul; hashval = (*s++) + (hashval << 6) + (hashval << 16) - hashval;
}
return (hashsize == 0) ? hashval : (hashval % hashsize); return (hashsize == 0) ? hashval : (hashval % hashsize);
} }
unsigned long genhash(char *s, int c, int hashsize) unsigned long genhash(char *s, int c, int hashsize)
{ {
unsigned long hashval = 2166136261ul; unsigned long hashval;
hashval ^= (unsigned long)c;
hashval *= 16777619ul; for (hashval = (unsigned long)c; *s != '\0'; )
for (; *s != '\0'; s++) { hashval = (*s++) + (hashval << 6) + (hashval << 16) - hashval;
hashval ^= (unsigned char)(*s);
hashval *= 16777619ul;
}
return (hashsize == 0) ? hashval : (hashval % hashsize); return (hashsize == 0) ? hashval : (hashval % hashsize);
} }

View File

@ -48,7 +48,7 @@ extern void *HashFirst(struct hashdict *dict);
extern void *HashNext(struct hashdict *dict); extern void *HashNext(struct hashdict *dict);
extern unsigned long hashnocase(char *s, int hashsize); extern unsigned long hashnocase(char *s, int hashsize);
extern unsigned long hashcase(char *s, int hashsize); extern unsigned long hash(char *s, int hashsize);
extern int (*matchfunc)(char *, char *); extern int (*matchfunc)(char *, char *);
/* matchintfunc() compares based on the name and the first */ /* matchintfunc() compares based on the name and the first */

View File

@ -17,7 +17,6 @@ along with this program; see the file copying. If not, write to
the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* inetcomp.c -- a simple wrapper to the NETCOMP() function */ /* inetcomp.c -- a simple wrapper to the NETCOMP() function */
#include "config.h"
#include <stdio.h> #include <stdio.h>
#include "netgen.h" #include "netgen.h"
@ -34,7 +33,7 @@ void STRCPY(char *dest, char *source)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
char cell1[MAX_STR_LEN], cell2[MAX_STR_LEN]; char cell1[200], cell2[200];
Debug = 0; Debug = 0;
if (argc != 1) { if (argc != 1) {

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,6 @@ extern struct nlist *Circuit1;
extern struct nlist *Circuit2; extern struct nlist *Circuit2;
extern int ExhaustiveSubdivision; extern int ExhaustiveSubdivision;
extern int ExactTopology;
extern int left_col_end; extern int left_col_end;
extern int right_col_end; extern int right_col_end;
@ -27,7 +26,6 @@ extern void PrintCoreStats(void);
extern void ResetState(void); extern void ResetState(void);
extern void CreateTwoLists(char *name1, int file1, char *name2, int file2, extern void CreateTwoLists(char *name1, int file1, char *name2, int file2,
int dolist); int dolist);
extern void DescribeContents(char *name1, int file1, char *name2, int file2);
extern int Iterate(void); extern int Iterate(void);
extern int VerifyMatching(void); extern int VerifyMatching(void);
extern void PrintAutomorphisms(void); extern void PrintAutomorphisms(void);
@ -38,8 +36,7 @@ extern int PermuteSetup(char *model, int filenum, char *pin1, char *pin2);
extern int PermuteForget(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 EquivalenceElements(char *name1, int file1, char *name2, int file2);
extern int EquivalenceNodes(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 IgnoreClass(char *name, int file, unsigned char type);
extern int MatchPins(struct nlist *tp1, struct nlist *tp2, int dolist); extern int MatchPins(struct nlist *tp1, struct nlist *tp2, int dolist);
extern int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, extern int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run,
@ -49,7 +46,6 @@ extern int CreateCompareQueue(char *, int, char *, int);
extern int GetCompareQueueTop(char **, int *, char **, int *); extern int GetCompareQueueTop(char **, int *, char **, int *);
extern int PeekCompareQueueTop(char **, int *, char **, int *); extern int PeekCompareQueueTop(char **, int *, char **, int *);
extern void RemoveCompareQueue(); extern void RemoveCompareQueue();
extern int FlattenUnmatched(struct nlist *, char *, int, int);
extern void PrintIllegalClasses(); extern void PrintIllegalClasses();
extern void PrintIllegalNodeClasses(); extern void PrintIllegalNodeClasses();
@ -58,20 +54,9 @@ extern void PrintIllegalElementClasses();
extern void DumpNetwork(struct objlist *ob, int cidx); extern void DumpNetwork(struct objlist *ob, int cidx);
extern void DumpNetworkAll(char *name, int file); extern void DumpNetworkAll(char *name, int file);
extern void RegroupDataStructures();
extern void FormatIllegalElementClasses();
extern void FormatIllegalNodeClasses();
extern int ResolveAutomorphsByProperty();
extern int ResolveAutomorphsByPin(int match_nets);
extern void SummarizeElementClasses(struct ElementClass *EC);
extern int remove_group_tags(struct objlist *ob);
#ifdef TCL_NETGEN #ifdef TCL_NETGEN
extern int EquivalentNode(); extern int EquivalentNode();
extern int EquivalentElement(); extern int EquivalentElement();
extern void DeriveAreaProperty();
extern void DerivePerimeterProperty();
extern void enable_interrupt(); extern void enable_interrupt();
extern void disable_interrupt(); extern void disable_interrupt();

View File

@ -183,6 +183,7 @@ void CloseFile(char *filename)
fclose(outfile); fclose(outfile);
} }
/* STUFF TO READ INPUT FILES */ /* STUFF TO READ INPUT FILES */
static char *line = NULL; /* actual line read in */ static char *line = NULL; /* actual line read in */
@ -206,21 +207,6 @@ struct hashdict *definitions = (struct hashdict *)NULL;
#define WHITESPACE_DELIMITER " \t\n\r" #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() --- */ /* TrimQuoted() --- */
/* Remove spaces from inside single- or double-quoted strings. */ /* Remove spaces from inside single- or double-quoted strings. */
@ -302,7 +288,7 @@ int GetNextLineNoNewline(char *delimiter)
{ {
char *newbuf; char *newbuf;
int testc; int testc;
static int nested = 0; int nested = 0;
int llen; int llen;
if (feof(infile)) return -1; if (feof(infile)) return -1;
@ -329,11 +315,6 @@ int GetNextLineNoNewline(char *delimiter)
llen = strlen(line); llen = strlen(line);
} }
while (llen == linesize - 1) { while (llen == linesize - 1) {
/* Note that in the rare case where a newline is in the last buffer
* position, we're done.
*/
if (*(line + llen - 1) == '\n') break;
newbuf = (char *)MALLOC(linesize + 501); newbuf = (char *)MALLOC(linesize + 501);
strcpy(newbuf, line); strcpy(newbuf, line);
FREE(line); FREE(line);
@ -350,20 +331,14 @@ int GetNextLineNoNewline(char *delimiter)
linetok = (char *)MALLOC(linesize + 1); linetok = (char *)MALLOC(linesize + 1);
} }
if (definitions == NULL)
strcpy(linetok, line);
else {
char *s, *t, *w, e;
struct property *kl;
int len, dlen, vlen, addin = 0;
int oldlinesize = linesize;
unsigned char found = TRUE;
/* Check for substitutions (verilog only). Make sure linetok is */ /* Check for substitutions (verilog only). Make sure linetok is */
/* large enough to hold the entire line after substitutions. */ /* large enough to hold the entire line after substitutions. */
while (found) { /* Do this recursively, for nested definitions */ if (definitions != NULL) {
found = FALSE; char *s, *w, e;
struct property *kl;
int len, dlen, vlen, addin = 0;
unsigned char found = FALSE;
for (s = line; *s != '\0'; s++) { for (s = line; *s != '\0'; s++) {
if (*s == '`') { if (*s == '`') {
@ -392,9 +367,14 @@ int GetNextLineNoNewline(char *delimiter)
linetok = (char *)MALLOC(linesize); linetok = (char *)MALLOC(linesize);
} }
} }
}
/* Make definition substitutions (verilog only) */ /* Make definition substitutions (verilog only) */
if (definitions != NULL) {
char *s, *t, *w, e;
struct property *kl;
t = linetok; t = linetok;
for (s = line; *s != '\0'; s++) { for (s = line; *s != '\0'; s++) {
if (*s == '`') { if (*s == '`') {
@ -419,18 +399,9 @@ int GetNextLineNoNewline(char *delimiter)
else *t++ = *s; else *t++ = *s;
} }
*t = '\0'; *t = '\0';
/* Copy substituted linetok back to line and repeat until */
/* there are no more substitutions to be made. */
if (oldlinesize != linesize) {
FREE(line);
line = (char *)MALLOC(linesize + 501);
oldlinesize = linesize;
}
strcpy(line, linetok);
}
} }
else
strcpy(linetok, line);
TrimQuoted(linetok); TrimQuoted(linetok);
linenum++; linenum++;
@ -592,31 +563,19 @@ void SkipTokNoNewline(char *delimiter)
/* */ /* */
/* Modified 3/30/2015 to include the condition where a comment line is */ /* Modified 3/30/2015 to include the condition where a comment line is */
/* in the middle of a series of continuation lines. */ /* in the middle of a series of continuation lines. */
/* */
/* Modified 1/3/2024 to avoid skipping two lines if a line has only the */
/* comment character '*' followed by a newline. It seems that '\n' is */
/* being ignored in WHITESPACE_DELIMITER, but it's easier to write the */
/* code to find the exception rather than track down the problem in */
/* GetNextLine(). */
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
void SpiceTokNoNewline(void) void SpiceTokNoNewline(void)
{ {
int contline; int contline;
if ((nexttok = strdtok0(NULL, WHITESPACE_DELIMITER, NULL, FALSE)) != NULL) return; if ((nexttok = strdtok(NULL, WHITESPACE_DELIMITER, NULL)) != NULL) return;
while (nexttok == NULL) { while (nexttok == NULL) {
contline = getc(infile); contline = getc(infile);
if (contline == '*') { if (contline == '*') {
char testline = ' ';
while ((testline == ' ') || (testline == '\t'))
testline = getc(infile);
if (testline != '\n') {
ungetc(testline, infile);
GetNextLine(WHITESPACE_DELIMITER); GetNextLine(WHITESPACE_DELIMITER);
SkipNewLine(NULL); SkipNewLine(NULL);
}
continue; continue;
} }
else if (contline != '+') { else if (contline != '+') {
@ -628,8 +587,7 @@ void SpiceTokNoNewline(void)
} }
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
/* Skip to the next token, ignoring any C-style comments and verilog */ /* Skip to the next token, ignoring any C-style comments. */
/* "(* ... *)"-style comments. */
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
void SkipTokComments(char *delimiter) void SkipTokComments(char *delimiter)
@ -645,11 +603,6 @@ void SkipTokComments(char *delimiter)
SkipTok(delimiter); SkipTok(delimiter);
if (nexttok) SkipTok(delimiter); if (nexttok) SkipTok(delimiter);
} }
else if (match(nexttok, "(*")) {
while (nexttok && !match(nexttok, "*)"))
SkipTok(delimiter);
if (nexttok) SkipTok(delimiter);
}
else break; else break;
} }
} }
@ -685,7 +638,6 @@ void SpiceSkipNewLine(void)
ungetc(contline, infile); ungetc(contline, infile);
} }
#if 0 /* Commented with "#if 0" due to comment characters in the comment */
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
/* Function similar to strtok() for token parsing. The difference is */ /* Function similar to strtok() for token parsing. The difference is */
/* that it takes two sets of delimiters. The first is whitespace */ /* that it takes two sets of delimiters. The first is whitespace */
@ -706,9 +658,8 @@ void SpiceSkipNewLine(void)
/* the first character of the delimiter string in addition to marking */ /* the first character of the delimiter string in addition to marking */
/* the boundary between two-character and one-character delimiters. */ /* the boundary between two-character and one-character delimiters. */
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
#endif
char *strdtok0(char *pstring, char *delim1, char *delim2, char isverilog) char *strdtok(char *pstring, char *delim1, char *delim2)
{ {
static char *stoken = NULL; static char *stoken = NULL;
static char *sstring = NULL; static char *sstring = NULL;
@ -753,10 +704,10 @@ char *strdtok0(char *pstring, char *delim1, char *delim2, char isverilog)
/* should know whether it is parsing SPICE or verilog and handle the syntax */ /* should know whether it is parsing SPICE or verilog and handle the syntax */
/* accordingly (needs to be done). */ /* accordingly (needs to be done). */
if (isverilog && (*s == '\\')) { if (*s == '\\') {
s++; s++;
while (*s != '\0') { while (*s != '\0') {
if ((*s == ' ') || ((*s == '\\') && (*(s + 1) == '\0'))) { if ((*s == ' ') || (*s == '\\')) {
s++; s++;
break; break;
} }
@ -824,17 +775,6 @@ char *strdtok0(char *pstring, char *delim1, char *delim2, char isverilog)
return sstring; return sstring;
} }
/*----------------------------------------------------------------------*/
/* strdtok() is the original string tokenizer. It calls strdtok0() */
/* with isverilog=TRUE, so that tokens are parsed as (potentially) */
/* verilog names, which includes verilog backslash notation. */
/*----------------------------------------------------------------------*/
char *strdtok(char *pstring, char *delim1, char *delim2)
{
return strdtok0(pstring, delim1, delim2, TRUE);
}
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
void InputParseError(FILE *f) void InputParseError(FILE *f)
@ -916,7 +856,7 @@ char *ReadNetlist(char *fname, int *fnum)
}; };
#ifdef mips #ifdef mips
struct filetype formats[8]; struct filetype formats[7];
formats[0].extension = NTK_EXTENSION; formats[0].extension = NTK_EXTENSION;
formats[0].proc = ReadNtk; formats[0].proc = ReadNtk;
@ -924,16 +864,14 @@ char *ReadNetlist(char *fname, int *fnum)
formats[1].proc = ReadExtHier; formats[1].proc = ReadExtHier;
formats[2].extension = SIM_EXTENSION; formats[2].extension = SIM_EXTENSION;
formats[2].proc = ReadSim; formats[2].proc = ReadSim;
formats[3].extension = PRM_EXTENSION; formats[3].extension = SPICE_EXTENSION;
formats[3].proc = ReadPrm; formats[3].proc = ReadSpice;
formats[4].extension = SPICE_EXTENSION; formats[4].extension = NETGEN_EXTENSION;
formats[4].proc = ReadSpice; formats[4].proc = ReadNetgenFile;
formats[5].extension = NETGEN_EXTENSION; formats[5].extension = VERILOG_EXTENSION;
formats[5].proc = ReadNetgenFile; formats[5].proc = ReadVerilogFile;
formats[6].extension = VERILOG_EXTENSION; formats[6].extension = NULL;
formats[6].proc = ReadVerilogFile; formats[6].proc = NULL;
formats[7].extension = NULL;
formats[7].proc = NULL;
#else /* not mips (i.e. compiler with reasonable initializers) */ #else /* not mips (i.e. compiler with reasonable initializers) */
@ -942,7 +880,6 @@ char *ReadNetlist(char *fname, int *fnum)
{NTK_EXTENSION, ReadNtk}, {NTK_EXTENSION, ReadNtk},
{EXT_EXTENSION, ReadExtHier}, {EXT_EXTENSION, ReadExtHier},
{SIM_EXTENSION, ReadSim}, {SIM_EXTENSION, ReadSim},
{PRM_EXTENSION, ReadPrm},
{SPICE_EXTENSION, ReadSpice}, {SPICE_EXTENSION, ReadSpice},
{SPICE_EXT2, ReadSpice}, {SPICE_EXT2, ReadSpice},
{SPICE_EXT3, ReadSpice}, {SPICE_EXT3, ReadSpice},
@ -967,7 +904,7 @@ char *ReadNetlist(char *fname, int *fnum)
} }
/* try appending extensions in sequence, and testing for file existance */ /* try appending extensions in sequence, and testing for file existance */
for (index = 0; formats[index].extension != NULL; index++) { for (index = 0; formats[index].extension != NULL; index++) {
char testname[MAX_STR_LEN]; char testname[200];
strcpy(testname, fname); strcpy(testname, fname);
strcat(testname, formats[index].extension); strcat(testname, formats[index].extension);
if (OpenParseFile(testname, *fnum) >= 0) { if (OpenParseFile(testname, *fnum) >= 0) {
@ -1072,7 +1009,7 @@ void WriteNetgenFile(char *name, char *filename)
char *ReadNetgenFile (char *fname, int *fnum) char *ReadNetgenFile (char *fname, int *fnum)
{ {
char name[MAX_STR_LEN]; char name[100];
char *LastCellRead = NULL; char *LastCellRead = NULL;
int filenum; int filenum;
@ -1308,7 +1245,7 @@ int READ(void *buf, int bytes)
char *ReadNetgenFile (char *fname, int *fnum) char *ReadNetgenFile (char *fname, int *fnum)
{ {
char name[MAX_STR_LEN]; char name[100];
int len, chars; int len, chars;
char *LastCellRead = NULL; char *LastCellRead = NULL;

View File

@ -7,7 +7,6 @@
#define WOMBAT_EXTENSION ".wom" #define WOMBAT_EXTENSION ".wom"
#define EXT_EXTENSION ".ext" #define EXT_EXTENSION ".ext"
#define SIM_EXTENSION ".sim" #define SIM_EXTENSION ".sim"
#define PRM_EXTENSION ".prm"
#define SPICE_EXTENSION ".spice" #define SPICE_EXTENSION ".spice"
#define SPICE_EXT2 ".spc" #define SPICE_EXT2 ".spc"
#define SPICE_EXT3 ".sp" #define SPICE_EXT3 ".sp"
@ -36,7 +35,6 @@ extern struct hashdict *definitions;
extern char *nexttok; extern char *nexttok;
#define SKIPTO(a) do {SkipTok(NULL);} while (!match(nexttok,a)) #define SKIPTO(a) do {SkipTok(NULL);} while (!match(nexttok,a))
extern char *strdtok0(char *pstring, char *delim1, char *delim2, char isverilog);
extern char *strdtok(char *pstring, char *delim1, char *delim2); extern char *strdtok(char *pstring, char *delim1, char *delim2);
extern char *GetLineAtTok(); extern char *GetLineAtTok();
extern void SkipTok(char *delimiter); extern void SkipTok(char *delimiter);
@ -49,7 +47,5 @@ extern void InputParseError(FILE *f);
extern int OpenParseFile(char *name, int fnum); extern int OpenParseFile(char *name, int fnum);
extern int EndParseFile(void); extern int EndParseFile(void);
extern int CloseParseFile(void); extern int CloseParseFile(void);
extern void SeekFile(long offset); /* handles verilog 'for' loops */
extern long TellFile(); /* handles verilog 'for' loops */
#endif /* _NETFILE_H */ #endif /* _NETFILE_H */

View File

@ -25,8 +25,6 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> /* for strtof() */ #include <stdlib.h> /* for strtof() */
#include <stdarg.h> #include <stdarg.h>
#include <string.h>
#include <strings.h>
#include <ctype.h> /* toupper() */ #include <ctype.h> /* toupper() */
#ifdef IBMPC #ifdef IBMPC
#include <alloc.h> #include <alloc.h>
@ -59,7 +57,7 @@ int AddToExistingDefinition = 0; /* default: overwrite cell when reopened */
extern int errno; /* Defined in stdlib.h */ extern int errno; /* Defined in stdlib.h */
#define MAX_STATIC_STRINGS 5 #define MAX_STATIC_STRINGS 5
static char staticstrings[MAX_STATIC_STRINGS][MAX_STR_LEN]; static char staticstrings[MAX_STATIC_STRINGS][200];
static int laststring; static int laststring;
extern struct hashdict spiceparams; /* From spice.c */ extern struct hashdict spiceparams; /* From spice.c */
@ -302,8 +300,6 @@ int ReduceOneExpression(struct valuelist *kv, struct objlist *parprops,
tstr = sstr - 1; tstr = sstr - 1;
numlast = 1; numlast = 1;
} }
/* But might not be. . . */
if ((dval != 0) || (sstr > estr))
break; break;
} }
/* Not a number, so must be arithmetic */ /* Not a number, so must be arithmetic */
@ -324,8 +320,6 @@ int ReduceOneExpression(struct valuelist *kv, struct objlist *parprops,
tstr = sstr - 1; tstr = sstr - 1;
numlast = 1; numlast = 1;
} }
/* But might not be. . . */
if ((dval != 0) || (sstr > estr))
break; break;
} }
/* Not a number, so must be arithmetic */ /* Not a number, so must be arithmetic */
@ -990,51 +984,6 @@ PropertyDelete(char *name, int fnum, char *key)
return 0; 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. */ /* Set the tolerance of a property in the master cell record. */
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
@ -2250,10 +2199,7 @@ int PromoteProperty(struct property *prop, struct valuelist *vl,
if (prop == NULL || vl == NULL) return -1; if (prop == NULL || vl == NULL) return -1;
if (prop->type == vl->type) return 1; /* Nothing to do */ if (prop->type == vl->type) return 1; /* Nothing to do */
result = 0; result = 0;
/* If vl is an expression but prop is not, then try to reduce if (prop->type == PROP_EXPRESSION) {
* the expression in vl.
*/
if (vl->type == PROP_EXPRESSION) {
ReduceOneExpression(vl, ob, tc, FALSE); ReduceOneExpression(vl, ob, tc, FALSE);
} }
switch (prop->type) { switch (prop->type) {
@ -3099,7 +3045,7 @@ void add_balancing_close(struct objlist *ob1, struct objlist *ob2)
for (nob = ob1->next; nob && nob->type != FIRSTPIN; nob = nob->next) for (nob = ob1->next; nob && nob->type != FIRSTPIN; nob = nob->next)
if (nob->type == PROPERTY) if (nob->type == PROPERTY)
break; break;
if (nob == NULL || nob->type != PROPERTY) return; // shouldn't happen if (nob->type != PROPERTY) return; // shouldn't happen
opentags = 0; opentags = 0;
for (; nob->next && nob->next->type == PROPERTY; nob = nob->next) { for (; nob->next && nob->next->type == PROPERTY; nob = nob->next) {
@ -3393,11 +3339,14 @@ int CombineParallel(char *model, int file)
/* Find last non-property record of sob ( = pob) */ /* Find last non-property record of sob ( = pob) */
/* Find first property record of sob ( = spropfirst) */ /* Find first property record of sob ( = spropfirst) */
/* Find last property record of sob ( = sproplast) */
spropfirst = NULL; spropfirst = sproplast = NULL;
for (ob2 = sob; ob2->type > FIRSTPIN || ob2 == sob; ob2 = ob2->next) for (ob2 = sob; ob2->type > FIRSTPIN || ob2 == sob; ob2 = ob2->next)
pob = ob2; pob = ob2;
if (ob2->type == PROPERTY) spropfirst = ob2; if (ob2->type == PROPERTY) spropfirst = ob2;
for (; ob2->type == PROPERTY; ob2 = ob2->next)
sproplast = ob2;
if (spropfirst == NULL) { if (spropfirst == NULL) {
/* Create new property instance record if one doesn't exist */ /* Create new property instance record if one doesn't exist */
@ -3423,9 +3372,8 @@ int CombineParallel(char *model, int file)
nob->next = pob->next; nob->next = pob->next;
pob->next = nob; pob->next = nob;
/* Handle case of contiguous entries */
if (lob == pob) lob = nob; if (lob == pob) lob = nob;
spropfirst = nob; spropfirst = sproplast = nob;
} }
if (propfirst == NULL) { if (propfirst == NULL) {
/* Create new property instance record if one doesn't exist */ /* Create new property instance record if one doesn't exist */
@ -3448,26 +3396,27 @@ int CombineParallel(char *model, int file)
kv->type = PROP_ENDLIST; kv->type = PROP_ENDLIST;
kv->value.ival = 0; kv->value.ival = 0;
/* Prepend to sob's property list */ /* Append to sob's property list */
nob->next = pob->next; nob->next = sproplast->next;
pob->next = nob; sproplast->next = nob;
/* Handle case of contiguous entries */ if (lob == sproplast) lob = nob;
if (lob == pob) lob = nob;
} }
else {
if (propfirst != NULL) {
// Series/Parallel logic: // Series/Parallel logic:
// If spropfirst has _tag in properties, // If propfirst has _tag in properties,
// then add an "open" tag at spropfirst // then add an "open" tag at propfirst
add_prop_tag(spropfirst, '('); add_prop_tag(propfirst, '(');
// if propfirst has _tag in properties then add an "open" tag // if spropfirst has _tag in properties then add an "open" tag
// to propfirst and a "close" tag to spropfirst // to spropfirst and a "close" tag to propfirst
if (add_prop_tag(propfirst, '(')) add_prop_tag(spropfirst, ')'); if (add_prop_tag(spropfirst, '(')) add_prop_tag(propfirst, ')');
/* Prepend ob's property list to sob */ /* Append ob's property list to sob */
proplast->next = pob->next; proplast->next = sproplast->next;
pob->next = propfirst; sproplast->next = propfirst;
if (lob == sproplast) lob = proplast;
} }
/* Link up around object to be removed */ /* Link up around object to be removed */
@ -3480,6 +3429,7 @@ int CombineParallel(char *model, int file)
obr = nob; obr = nob;
} }
dcnt++; dcnt++;
} }
FREE((char *)pstr); FREE((char *)pstr);
} }
@ -3491,8 +3441,7 @@ int CombineParallel(char *model, int file)
} }
HashKill(&devdict); HashKill(&devdict);
if (dcnt > 0) { if (dcnt > 0) {
Fprintf(stdout, "Class %s (%d): Merged %d parallel devices.\n", Fprintf(stdout, "Class %s: Merged %d devices.\n", model, dcnt);
model, file, dcnt);
} }
FREE(nodecount); FREE(nodecount);
return dcnt; return dcnt;
@ -3649,7 +3598,7 @@ int CombineSeries(char *model, int file)
nob->type = PROPERTY; nob->type = PROPERTY;
nob->name = strsave("properties"); nob->name = strsave("properties");
nob->node = -2; /* Don't report as disconnected node */ nob->node = -2; /* Don't report as disconnected node */
nob->model.class = (obp == NULL || obp->model.class == NULL) ? NULL : nob->model.class = (obp->model.class == NULL) ? NULL :
strsave(obp->model.class); strsave(obp->model.class);
nob->instance.props = NewPropValue(2); nob->instance.props = NewPropValue(2);
@ -3789,10 +3738,6 @@ int CombineSeries(char *model, int file)
} }
} }
FREE(instlist); FREE(instlist);
if (scnt > 0) {
Fprintf(stdout, "Class %s (%d): Merged %d series devices.\n",
model, file, scnt);
}
return scnt; return scnt;
} }

View File

@ -39,7 +39,6 @@ extern void SetParallelCombine(int value);
extern void SetSeriesCombine(int value); extern void SetSeriesCombine(int value);
extern int PropertyTolerance(char *name, int fnum, char *key, int ival, extern int PropertyTolerance(char *name, int fnum, char *key, int ival,
double dval); 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, extern int PropertyMerge(char *name, int fnum, char *key, int merge_type,
int merge_mask); int merge_mask);
extern void ResolveProperties(char *name1, int file1, char *name2, int file2); extern void ResolveProperties(char *name1, int file1, char *name2, int file2);
@ -191,7 +190,6 @@ extern char *ReadNtk (char *fname, int *fnum);
extern char *ReadExtHier(char *fname, int *fnum); extern char *ReadExtHier(char *fname, int *fnum);
extern char *ReadExtFlat(char *fname, int *fnum); extern char *ReadExtFlat(char *fname, int *fnum);
extern char *ReadSim(char *fname, int *fnum); extern char *ReadSim(char *fname, int *fnum);
extern char *ReadPrm(char *fname, int *fnum);
extern char *ReadSpice(char *fname, int *fnum); extern char *ReadSpice(char *fname, int *fnum);
extern char *ReadSpiceLib(char *fname, int *fnum); extern char *ReadSpiceLib(char *fname, int *fnum);
extern char *ReadNetgenFile (char *fname, int *fnum); extern char *ReadNetgenFile (char *fname, int *fnum);

View File

@ -181,7 +181,7 @@ void Ntk(char *name, char *filename)
char *ReadNtk (char *fname, int *fnum) char *ReadNtk (char *fname, int *fnum)
{ {
char model[MAX_STR_LEN], instancename[MAX_STR_LEN], name[MAX_STR_LEN]; char model[100], instancename[100], name[100];
struct objlist *ob; struct objlist *ob;
int CellDefInProgress = 0; int CellDefInProgress = 0;
int filenum; int filenum;
@ -218,7 +218,7 @@ char *ReadNtk (char *fname, int *fnum)
} }
} }
else if (match(nexttok, "s")) { else if (match(nexttok, "s")) {
char last[MAX_STR_LEN]; char last[100];
*last = '\0'; *last = '\0';
if (!CellDefInProgress) { if (!CellDefInProgress) {
/* fake cell declaration for top-level call */ /* fake cell declaration for top-level call */

View File

@ -22,7 +22,6 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h> #include <stdio.h>
#include <ctype.h> #include <ctype.h>
#include <limits.h>
#ifdef IBMPC #ifdef IBMPC
#include <alloc.h> #include <alloc.h>
#endif #endif
@ -32,13 +31,13 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#endif #endif
#include "netgen.h" #include "netgen.h"
#include "hash.h"
#include "objlist.h" #include "objlist.h"
#include "regexp.h" #include "regexp.h"
#include "dbug.h" #include "dbug.h"
#include "print.h" #include "print.h"
#include "netfile.h" #include "netfile.h"
#include "netcmp.h" #include "netcmp.h"
#include "hash.h"
#ifdef TCL_NETGEN #ifdef TCL_NETGEN
extern Tcl_Interp *netgeninterp; extern Tcl_Interp *netgeninterp;
@ -130,7 +129,6 @@ struct property *NewProperty(void)
kl = (struct property *)CALLOC(1,sizeof(struct property)); kl = (struct property *)CALLOC(1,sizeof(struct property));
if (kl == NULL) Fprintf(stderr,"NewProperty: Core allocation error\n"); if (kl == NULL) Fprintf(stderr,"NewProperty: Core allocation error\n");
kl->pin = (char *)NULL;
return (kl); return (kl);
} }
@ -223,35 +221,12 @@ int matchnocase(char *st1, char *st2)
{ {
char *sp1 = st1; char *sp1 = st1;
char *sp2 = st2; char *sp2 = st2;
char v1 = FALSE, v2 = FALSE;
/* In case of a property that does not exist in one netlist, matchnocase()
* may be passed a null value, so return 0 to indicate a non-match.
* *Both* values null will also be treated as a mismatch (debatable
* behavior).
*/
if (!sp1 || !sp2) return 0;
/* Verilog back-slash escaped names should match an equivalent non-
* back-slashed name. (NOTE: This behavior needs to be added to match().)
*/
if ((*sp1 == '\\') && (*sp2 != '\\')) {
v1 = TRUE;
sp1++;
}
if ((*sp2 == '\\') && (*sp1 != '\\')) {
v2 = TRUE;
sp2++;
}
while (*sp1 != '\0' && *sp2 != '\0') { while (*sp1 != '\0' && *sp2 != '\0') {
if (to_lower[*sp1] != to_lower[*sp2]) break; if (to_lower[*sp1] != to_lower[*sp2]) break;
sp1++; sp1++;
sp2++; sp2++;
} }
if (v1 && (*sp1 == ' ')) sp1++;
if (v2 && (*sp2 == ' ')) sp2++;
if ((*sp1 != '\0') || (*sp2 != '\0')) return 0; if ((*sp1 != '\0') || (*sp2 != '\0')) return 0;
return 1; return 1;
} }
@ -282,33 +257,6 @@ int matchfilenocase(char *st1, char *st2, int f1, int f2)
return 1; return 1;
} }
/* Delimiter matching---Find an opening delimiter in a string. */
/* Return the position of the first opening delimeter in the string, */
/* like strchr(). Place the actual delimeter character in *delim. */
char *get_array_delimiter(char *name, char *delim)
{
char *stest = name;
while (*stest != '\0')
{
if (to_lower[*stest] == '<') {
*delim = *stest;
return stest;
}
stest++;
}
return NULL;
}
/* Delimiter parsing---Check if a character is an opening array delimiter. */
/* Return TRUE if the character is an opening delimiter, FALSE if not. */
int is_delimiter(char testc)
{
return (to_lower[testc] == '<') ? TRUE : FALSE;
}
#ifdef HAVE_MALLINFO #ifdef HAVE_MALLINFO
void PrintMemoryStats(void) void PrintMemoryStats(void)
{ {
@ -340,7 +288,7 @@ static struct hashdict cell_dict;
void InitCellHashTable(void) void InitCellHashTable(void)
{ {
hashfunc = hashcase; hashfunc = hash;
matchfunc = NULL; matchfunc = NULL;
matchintfunc = matchfile; matchintfunc = matchfile;
InitializeHashTable(&cell_dict, CELLHASHSIZE); InitializeHashTable(&cell_dict, CELLHASHSIZE);
@ -476,7 +424,6 @@ int removeshorted(struct hashlist *p, int file)
ob = nob; ob = nob;
} }
} }
return 1;
} }
/* Remove shorted instances of class "class" from the database */ /* Remove shorted instances of class "class" from the database */
@ -492,32 +439,15 @@ void RemoveShorted(char *class, int file)
RecurseCellFileHashTable(removeshorted, 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) int deleteclass(struct hashlist *p, int file)
{ {
struct nlist *ptr; struct nlist *ptr;
struct objlist *ob, *lob, *nob, *portnode; struct objlist *ob, *lob, *nob;
unsigned char *checknodes;
int i;
ptr = (struct nlist *)(p->ptr); ptr = (struct nlist *)(p->ptr);
if ((file != -1) && (ptr->file != file)) return 0; 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; lob = NULL;
for (ob = ptr->cell; ob != NULL;) { for (ob = ptr->cell; ob != NULL;) {
nob = ob->next; nob = ob->next;
@ -525,8 +455,6 @@ int deleteclass(struct hashlist *p, int file)
if ((*matchfunc)(ob->model.class, OldCell->name)) { if ((*matchfunc)(ob->model.class, OldCell->name)) {
HashDelete(ob->instance.name, &(ptr->instdict)); HashDelete(ob->instance.name, &(ptr->instdict));
while (1) { while (1) {
if (ob->type >= FIRSTPIN)
checknodes[ob->node] = (unsigned char)1;
FreeObjectAndHash(ob, ptr); FreeObjectAndHash(ob, ptr);
ob = nob; ob = nob;
if (ob == NULL) break; if (ob == NULL) break;
@ -548,26 +476,6 @@ int deleteclass(struct hashlist *p, int file)
ob = nob; 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);
return 1;
} }
/* Remove all instances of class "class" from the database */ /* Remove all instances of class "class" from the database */
@ -605,7 +513,6 @@ int renameinstances(struct hashlist *p, int file)
} }
} }
} }
return 1;
} }
void InstanceRename(char *from, char *to, int file) void InstanceRename(char *from, char *to, int file)
@ -628,10 +535,9 @@ int freeprop(struct hashlist *p)
struct property *prop; struct property *prop;
prop = (struct property *)(p->ptr); prop = (struct property *)(p->ptr);
if (prop->type == PROP_STRING) { if (prop->type == PROP_STRING)
if (prop->pdefault.string != NULL) if (prop->pdefault.string != NULL)
FREE(prop->pdefault.string); FREE(prop->pdefault.string);
}
else if (prop->type == PROP_EXPRESSION) { else if (prop->type == PROP_EXPRESSION) {
struct tokstack *stackptr, *nptr; struct tokstack *stackptr, *nptr;
stackptr = prop->pdefault.stack; stackptr = prop->pdefault.stack;
@ -687,7 +593,7 @@ static int PrintCellHashTableElement(struct hashlist *p)
ptr = (struct nlist *)(p->ptr); ptr = (struct nlist *)(p->ptr);
if ((TopFile >= 0) && (ptr->file != TopFile)) return 1; if ((TopFile >= 0) && (ptr->file != TopFile)) return 1;
if ((ptr->class != CLASS_SUBCKT) && (ptr->class != CLASS_MODULE)) { if (ptr->class != CLASS_SUBCKT) {
/* only print primitive cells if Debug is enabled */ /* only print primitive cells if Debug is enabled */
if (Debug == 1) Printf("Cell: %s (instanced %d times); Primitive\n", if (Debug == 1) Printf("Cell: %s (instanced %d times); Primitive\n",
ptr->name, ptr->number); ptr->name, ptr->number);
@ -790,7 +696,7 @@ struct nlist *RecurseCellHashTable2(struct nlist *(*foo)(struct hashlist *,
char *FixTemplate(char *t) char *FixTemplate(char *t)
{ {
char buffer[MAX_STR_LEN]; char buffer[200];
char *rstr; char *rstr;
int i,j; int i,j;
int InsideBrace; int InsideBrace;
@ -1301,7 +1207,7 @@ static char *OldNodeName(struct nlist *tp, int node)
struct objlist *firstuniqueglobal; struct objlist *firstuniqueglobal;
struct objlist *firstglobal; struct objlist *firstglobal;
struct objlist *firstpin; struct objlist *firstpin;
static char StrBuffer[MAX_STR_LEN]; static char StrBuffer[100];
#if 0 #if 0
/* make second pass, looking for ports */ /* make second pass, looking for ports */

View File

@ -135,7 +135,6 @@ struct property {
unsigned char idx; /* index into valuelist */ unsigned char idx; /* index into valuelist */
unsigned char type; /* string, integer, double, value, expression */ unsigned char type; /* string, integer, double, value, expression */
unsigned char merge; /* how property changes when devices are merged */ unsigned char merge; /* how property changes when devices are merged */
char *pin; /* associated pin (or NULL if not associated) */
union { union {
char *string; char *string;
double dval; double dval;
@ -207,7 +206,7 @@ struct nlist {
char *name; char *name;
int number; /* number of instances defined */ int number; /* number of instances defined */
int dumped; /* instance count, and general-purpose marker */ int dumped; /* instance count, and general-purpose marker */
unsigned short flags; unsigned char flags;
unsigned char class; unsigned char class;
unsigned long classhash; /* randomized hash value for cell class */ unsigned long classhash; /* randomized hash value for cell class */
struct Permutation *permutes; /* list of permuting pins */ struct Permutation *permutes; /* list of permuting pins */
@ -223,18 +222,17 @@ struct nlist {
/* Defined nlist structure flags */ /* Defined nlist structure flags */
#define CELL_MATCHED 0x001 /* cell matched to another */ #define CELL_MATCHED 0x01 /* cell matched to another */
#define CELL_NOCASE 0x002 /* cell is case-insensitive (e.g., SPICE) */ #define CELL_NOCASE 0x02 /* cell is case-insensitive (e.g., SPICE) */
#define CELL_TOP 0x004 /* cell is a top-level cell */ #define CELL_TOP 0x04 /* cell is a top-level cell */
#define CELL_PLACEHOLDER 0x008 /* cell is a placeholder cell */ #define CELL_PLACEHOLDER 0x08 /* cell is a placeholder cell */
#define CELL_PROPSMATCHED 0x010 /* properties matched to matching cell */ #define CELL_PROPSMATCHED 0x10 /* properties matched to matching cell */
#define CELL_DUPLICATE 0x020 /* cell has a duplicate */ #define CELL_DUPLICATE 0x20 /* cell has a duplicate */
#define CELL_VERILOG 0x040 /* cell is verilog module */
/* Flags for combination allowances and prohibitions */ /* Flags for combination allowances and prohibitions */
#define COMB_SERIES 0x100 #define COMB_SERIES 0x40
#define COMB_NO_PARALLEL 0x200 #define COMB_NO_PARALLEL 0x80
extern struct nlist *CurrentCell; extern struct nlist *CurrentCell;
extern struct objlist *CurrentTail; extern struct objlist *CurrentTail;
@ -309,26 +307,11 @@ extern int match(char *, char *);
extern int matchnocase(char *, char *); extern int matchnocase(char *, char *);
extern int matchfile(char *, char *, int, int); extern int matchfile(char *, char *, int, int);
extern int matchfilenocase(char *, char *, int, int); extern int matchfilenocase(char *, char *, int, int);
extern int is_delimiter(char);
extern char *get_array_delimiter(char *, char *);
extern void GarbageCollect(void); extern void GarbageCollect(void);
extern void InitGarbageCollection(void); extern void InitGarbageCollection(void);
extern void AddToGarbageList(struct objlist *head); 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 #ifdef HAVE_MALLINFO
void PrintMemoryStats(void); void PrintMemoryStats(void);
#endif #endif

View File

@ -511,8 +511,8 @@ int OpenEmbeddingFile(char *cellname, char *filename)
/* returns 1 if OK */ /* returns 1 if OK */
{ {
struct nlist *tp; struct nlist *tp;
char outfilename[MAX_STR_LEN]; char outfilename[200];
char logfilename[MAX_STR_LEN]; char logfilename[200];
tp = LookupCell(cellname); tp = LookupCell(cellname);
if (tp == NULL) { if (tp == NULL) {
@ -783,7 +783,7 @@ void SetupArray(char *prompt1, char *prompt2, char *prompt3, int *data,
void (*proc)(void)) void (*proc)(void))
{ {
int i, oldfanout; int i, oldfanout;
char name[MAX_STR_LEN]; char name[100];
Printf(prompt1); Printf(prompt1);
for (i = 1; i <= MAX_TREE_DEPTH; i++) for (i = 1; i <= MAX_TREE_DEPTH; i++)
@ -792,7 +792,7 @@ void SetupArray(char *prompt1, char *prompt2, char *prompt3, int *data,
oldfanout = 1; oldfanout = 1;
for (i = 1; i <= MAX_TREE_DEPTH; i++) { for (i = 1; i <= MAX_TREE_DEPTH; i++) {
char prompt[MAX_STR_LEN]; char prompt[100];
int newfanout; int newfanout;
sprintf(prompt, prompt2, i); sprintf(prompt, prompt2, i);
promptstring(prompt, name); promptstring(prompt, name);
@ -822,7 +822,7 @@ void SetupArrayFromString(char *prompt1, char *prompt3, int *data,
void (*proc)(void), char *text) void (*proc)(void), char *text)
{ {
int i, oldfanout, newfanout; int i, oldfanout, newfanout;
char string[MAX_STR_LEN]; char string[100];
char *ch; char *ch;
char *endch; char *endch;
@ -962,7 +962,7 @@ void ProtoPrintParameters(void)
void PROTOCHIP(void) void PROTOCHIP(void)
/* a simple command interpreter to manage embedding/routing */ /* a simple command interpreter to manage embedding/routing */
{ {
char name[MAX_STR_LEN]; char name[100];
char ch; char ch;
InitializeFanout(); InitializeFanout();
@ -1136,7 +1136,7 @@ void PROTOCHIP(void)
oldfanout = 1; oldfanout = 1;
for (i = 1; i <= MAX_TREE_DEPTH; i++) { for (i = 1; i <= MAX_TREE_DEPTH; i++) {
char prompt[MAX_STR_LEN]; char prompt[100];
int newfanout; int newfanout;
sprintf(prompt,"Fanout for level %d (0 to quit): ",i); sprintf(prompt,"Fanout for level %d (0 to quit): ",i);
promptstring(prompt, name); promptstring(prompt, name);
@ -1168,7 +1168,7 @@ void PROTOCHIP(void)
oldfanout = 1; oldfanout = 1;
for (i = 1; i <= MAX_TREE_DEPTH; i++) { for (i = 1; i <= MAX_TREE_DEPTH; i++) {
char prompt[MAX_STR_LEN]; char prompt[100];
int newfanout; int newfanout;
sprintf(prompt,"Common nodes for level %d (0 to quit): ",i); sprintf(prompt,"Common nodes for level %d (0 to quit): ",i);
promptstring(prompt, name); promptstring(prompt, name);
@ -1200,7 +1200,7 @@ void PROTOCHIP(void)
oldfanout = 1; oldfanout = 1;
for (i = 1; i <= MAX_TREE_DEPTH; i++) { for (i = 1; i <= MAX_TREE_DEPTH; i++) {
char prompt[MAX_STR_LEN]; char prompt[100];
int newfanout; int newfanout;
sprintf(prompt,"Used leaves for level %d (0 to quit): ",i); sprintf(prompt,"Used leaves for level %d (0 to quit): ",i);
promptstring(prompt, name); promptstring(prompt, name);

View File

@ -37,7 +37,7 @@ extern int ColumnBase;
struct filestr { struct filestr {
FILE *f; FILE *f;
char buffer[MAX_STR_LEN]; char buffer[200];
int wrap; /* column to wrap around in, or 0 if no wrap */ int wrap; /* column to wrap around in, or 0 if no wrap */
} file_buffers[MAXFILES]; } file_buffers[MAXFILES];
@ -107,7 +107,7 @@ void Fprintf(FILE *f, char *format, ...)
{ {
va_list ap; va_list ap;
int FileIndex; int FileIndex;
char tmpstr[MAX_STR_LEN]; char tmpstr[200];
int bufferlongenough; int bufferlongenough;
int linewrapexceeded; int linewrapexceeded;
@ -203,7 +203,7 @@ void Printf(char *format, ...)
void Printf(char *format, ...) void Printf(char *format, ...)
{ {
va_list ap; va_list ap;
char tmpstr[MAX_STR_LEN]; char tmpstr[200];
va_start(ap, format); va_start(ap, format);
vsprintf(tmpstr, format, ap); vsprintf(tmpstr, format, ap);

View File

@ -52,7 +52,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/*************************************************************************/ /*************************************************************************/
static int SuppressPrompts = 0; static int SuppressPrompts = 0;
static char InputLine[MAX_STR_LEN]; static char InputLine[200];
void typeahead(char *str) void typeahead(char *str)
{ {
@ -73,7 +73,7 @@ but reads from 'promptstring_infile' if nec. */
/* If interactive, puts out 'prompt' */ /* If interactive, puts out 'prompt' */
{ {
char *nexttok; char *nexttok;
char tmpstr[MAX_STR_LEN]; char tmpstr[200];
int echo; int echo;
if (promptstring_infile == NULL) if (promptstring_infile == NULL)
@ -319,7 +319,7 @@ void Fanout(char *cell, char *node, int filter)
while (ob != NULL) { while (ob != NULL) {
char *obname = ob->name; char *obname = ob->name;
if (*obname == '/') obname++; if (*obname == '/') obname++;
if (ob->node == nodenum) { if (ob->node == nodenum)
if (filter == ALLOBJECTS) { if (filter == ALLOBJECTS) {
Printf(" %s (", obname); Printf(" %s (", obname);
PrintObjectType(ob->type); PrintObjectType(ob->type);
@ -331,7 +331,6 @@ void Fanout(char *cell, char *node, int filter)
else if (ob->type == filter) { else if (ob->type == filter) {
Printf(" %s\n", obname); Printf(" %s\n", obname);
} }
}
ob = ob->next; ob = ob->next;
} }
} }
@ -806,14 +805,11 @@ void DescribeInstance(char *name, int file)
/* All black-box modules and placeholders by definition have all */ /* All black-box modules and placeholders by definition have all */
/* disconnected pins, so don't report those. */ /* disconnected pins, so don't report those. */
if ((!(tp->flags & CELL_PLACEHOLDER)) && (tp->class != CLASS_MODULE)) { if (!(tp->flags & CELL_PLACEHOLDER) && (tp->class != CLASS_MODULE))
// if (disconnectednodes == 0) Fprintf(stderr, "\n"); {
if (disconnectednodes == 0) Fprintf(stderr, "\n");
disconnectednodes++; disconnectednodes++;
/* Don't report on ports marked "port_match_error", which is just confusing. */ Fprintf(stderr, "Cell %s disconnected node: %s\n", tp->name, ob->name);
if (strcmp(ob->name, "port_match_error")) {
Fprintf(stderr, "Cell %s (%d) disconnected node: %s\n",
tp->name, tp->file, ob->name);
}
} }
} }
} }
@ -934,7 +930,7 @@ static int PrintLeavesInCellHash(struct hashlist *p)
struct nlist *ptr; struct nlist *ptr;
ptr = (struct nlist *)(p->ptr); ptr = (struct nlist *)(p->ptr);
if (ptr->class == CLASS_SUBCKT) PrintLeavesInCell(ptr->name, ptr->file); if ((ptr->class == CLASS_SUBCKT)) PrintLeavesInCell(ptr->name, ptr->file);
return(0); return(0);
} }
@ -960,8 +956,8 @@ void Query(void)
{ {
/* little interactive debugger */ /* little interactive debugger */
char reply; char reply;
char repstr[MAX_STR_LEN]; char repstr[100];
char repstr2[MAX_STR_LEN]; char repstr2[100];
float StartTime; /* for elapsed CPU times */ float StartTime; /* for elapsed CPU times */
int Timing; /* if true, print times of each command */ int Timing; /* if true, print times of each command */
int filenum = -1; int filenum = -1;
@ -1037,7 +1033,7 @@ void Query(void)
break; break;
case 'v': case 'v':
promptstring("Write Verilog: circuit name: ", repstr); promptstring("Write Verilog: circuit name: ", repstr);
VerilogTop(repstr, filenum, ""); VerilogModule(repstr, filenum, "");
break; break;
case 'E': case 'E':
promptstring("Write ESACAP: circuit name: ", repstr); promptstring("Write ESACAP: circuit name: ", repstr);

View File

@ -21,15 +21,11 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "config.h" #include "config.h"
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#if 0 #if 0
#include <stdarg.h> /* what about varargs, like in pdutils.c ??? */ #include <stdarg.h> /* what about varargs, like in pdutils.c ??? */
#endif #endif
#include <stdlib.h> /* for calloc(), free(), getenv() */ #include <stdlib.h> /* for calloc(), free(), getenv() */
#include <ctype.h> /* for toupper(), isascii() */
#ifndef IBMPC #ifndef IBMPC
#include <sys/types.h> /* for getpwnam() tilde expansion */ #include <sys/types.h> /* for getpwnam() tilde expansion */
#include <pwd.h> #include <pwd.h>
@ -44,9 +40,6 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "objlist.h" #include "objlist.h"
#include "netfile.h" #include "netfile.h"
#include "print.h" #include "print.h"
#include "query.h"
#include "objlist.h"
#include "netcmp.h"
// Global storage for parameters from .PARAM // Global storage for parameters from .PARAM
struct hashdict spiceparams; struct hashdict spiceparams;
@ -196,7 +189,7 @@ void SpiceSubCell(struct nlist *tp, int IsSubCell)
if (ob->type == PROPERTY) { if (ob->type == PROPERTY) {
struct valuelist *vl; struct valuelist *vl;
int i; int i;
for (i = 0;; i++) { for (i == 0;; i++) {
vl = &(ob->instance.props[i]); vl = &(ob->instance.props[i]);
if (vl->type == PROP_ENDLIST) break; if (vl->type == PROP_ENDLIST) break;
else if (vl->type == PROP_VALUE) { else if (vl->type == PROP_VALUE) {
@ -216,7 +209,7 @@ void SpiceSubCell(struct nlist *tp, int IsSubCell)
if (ob->type == PROPERTY) { if (ob->type == PROPERTY) {
struct valuelist *vl; struct valuelist *vl;
int i; int i;
for (i = 0;; i++) { for (i == 0;; i++) {
vl = &(ob->instance.props[i]); vl = &(ob->instance.props[i]);
if (vl->type == PROP_ENDLIST) break; if (vl->type == PROP_ENDLIST) break;
else if (vl->type == PROP_VALUE) { else if (vl->type == PROP_VALUE) {
@ -236,7 +229,7 @@ void SpiceSubCell(struct nlist *tp, int IsSubCell)
if (ob->type == PROPERTY) { if (ob->type == PROPERTY) {
struct valuelist *vl; struct valuelist *vl;
int i; int i;
for (i = 0;; i++) { for (i == 0;; i++) {
vl = &(ob->instance.props[i]); vl = &(ob->instance.props[i]);
if (vl->type == PROP_ENDLIST) break; if (vl->type == PROP_ENDLIST) break;
else if (vl->type == PROP_VALUE) { else if (vl->type == PROP_VALUE) {
@ -399,7 +392,7 @@ int renamepins(struct hashlist *p, int file)
ptr = (struct nlist *)(p->ptr); ptr = (struct nlist *)(p->ptr);
if (ptr->file != file) if (ptr->file != file)
return 0; return 1;
for (ob = ptr->cell; ob != NULL; ob = ob->next) { for (ob = ptr->cell; ob != NULL; ob = ob->next) {
if (ob->type == FIRSTPIN) { if (ob->type == FIRSTPIN) {
@ -426,7 +419,6 @@ int renamepins(struct hashlist *p, int file)
} }
} }
} }
return 1;
} }
/* If any pins are marked unconnected, see if there are */ /* If any pins are marked unconnected, see if there are */
@ -523,27 +515,21 @@ void ReadSpiceFile(char *fname, int filenum, struct cellstack **CellStackPtr,
int warnings = 0, update = 0, hasports = 0; int warnings = 0, update = 0, hasports = 0;
char *eqptr, devtype, in_subckt; char *eqptr, devtype, in_subckt;
struct keyvalue *kvlist = NULL; struct keyvalue *kvlist = NULL;
char inst[MAX_STR_LEN], model[MAX_STR_LEN], instname[MAX_STR_LEN]; char inst[256], model[256], instname[256];
struct nlist *tp, *tpsave; struct nlist *tp;
struct objlist *parent, *sobj, *nobj, *lobj, *pobj; struct objlist *parent, *sobj, *nobj, *lobj, *pobj;
inst[MAX_STR_LEN-1] = '\0'; inst[255] = '\0';
model[MAX_STR_LEN-1] = '\0'; model[255] = '\0';
instname[MAX_STR_LEN-1] = '\0'; instname[255] = '\0';
in_subckt = (char)0; in_subckt = (char)0;
while (!EndParseFile()) { while (!EndParseFile()) {
SkipTok(NULL); /* get the next token */ SkipTok(NULL); /* get the next token */
if ((EndParseFile()) && (nexttok == NULL)) break; if ((EndParseFile()) && (nexttok == NULL)) break;
if (nexttok == NULL) break;
/* Handle comment lines. Note that some variants of CDL format if (nexttok[0] == '*') SkipNewLine(NULL);
* use "*." for information that is transparent to SPICE simulators.
* Handle "*.GLOBAL" entries. All others are ignored.
*/
if ((nexttok[0] == '*') && (!matchnocase(nexttok, "*.GLOBAL")))
SkipNewLine(NULL);
else if (matchnocase(nexttok, ".SUBCKT")) { else if (matchnocase(nexttok, ".SUBCKT")) {
SpiceTokNoNewline(); SpiceTokNoNewline();
@ -566,9 +552,8 @@ void ReadSpiceFile(char *fname, int filenum, struct cellstack **CellStackPtr,
/* Check for existence of the cell. We may need to rename it. */ /* Check for existence of the cell. We may need to rename it. */
snprintf(model, MAX_STR_LEN-1, "%s", nexttok); snprintf(model, 99, "%s", nexttok);
tp = LookupCellFile(nexttok, filenum); tp = LookupCellFile(nexttok, filenum);
tpsave = NULL;
/* Check for name conflict with duplicate cell names */ /* Check for name conflict with duplicate cell names */
/* This may mean that the cell was used before it was */ /* This may mean that the cell was used before it was */
@ -607,47 +592,12 @@ void ReadSpiceFile(char *fname, int filenum, struct cellstack **CellStackPtr,
tp = LookupCellFile(nexttok, filenum); tp = LookupCellFile(nexttok, filenum);
} }
else if (tp != NULL) { /* Make a new definition for an empty cell */ else if (tp != NULL) { /* Make a new definition for an empty cell */
/* Handle issue with SPICE read after verilog, where a placeholder
* was created from the verilog. (1) If the pin names are "1", "2",
* "3", then this is a SPICE placeholder, and just remove the CellDef
* and re-create it. Otherwise, create new cell "_PLACEHOLDER_".
* (2) After encountering .ends, run MatchPins between the two cells.
* (3) delete the original cell and rename the new cell.
*/
int i = 1;
char pname[10];
for (pobj = tp->cell; pobj && pobj->type == PORT; pobj = pobj->next) {
sprintf(pname, "%d", i);
if (!matchnocase(pobj->name, pname)) break;
i++;
}
if ((pobj == NULL) || (pobj->type != PORT)) {
/* This is a SPICE placeholder created because the cell was instanced
* before it was defined. However, the pins can be assumed to be in
* the correct order, and pin reordering does not need to be done.
*/
FreePorts(nexttok); FreePorts(nexttok);
CellDelete(nexttok, filenum); /* This removes any PLACEHOLDER flag */ CellDelete(nexttok, filenum); /* This removes any PLACEHOLDER flag */
CellDef(model, filenum); CellDef(model, filenum);
tp = LookupCellFile(model, filenum); tp = LookupCellFile(model, filenum);
update = 1; /* Will need to update existing instances */ update = 1; /* Will need to update existing instances */
} }
else {
/* This is (probably) a verilog placeholder created because the
* verilog was read before the (SPICE) definitions. The verilog
* netlist should have named the pins of the parent cell. However,
* there is no guarantee the order of pins is correct. The MatchPins()
* routine from netcmp.c can be used here to match the cell against
* the placeholder, and reorder the pins in all instances to match.
* Note that we cannot just reorder the SPICE pins to match the
* verilog order, because there may be other SPICE netlists which
* instance the cell with the correct SPICE port order.
*/
tpsave = tp;
CellDef("_PLACEHOLDER_", filenum);
tp = LookupCellFile("_PLACEHOLDER_", filenum);
}
}
else if (tp == NULL) { /* Completely new cell, no name conflict */ else if (tp == NULL) { /* Completely new cell, no name conflict */
CellDef(model, filenum); CellDef(model, filenum);
tp = LookupCellFile(model, filenum); tp = LookupCellFile(model, filenum);
@ -738,38 +688,6 @@ skip_ends:
if (*CellStackPtr) PopStack(CellStackPtr); if (*CellStackPtr) PopStack(CellStackPtr);
if (*CellStackPtr) ReopenCellDef((*CellStackPtr)->cellname, filenum); if (*CellStackPtr) ReopenCellDef((*CellStackPtr)->cellname, filenum);
SkipNewLine(NULL); SkipNewLine(NULL);
if (tpsave != NULL) {
struct nlist *tpplace;
char *savename;
/* Handle a placeholder from a verilog file that has been replaced
* by a netlist with pins in a different order. The pins need to
* be matched, corrected in the original cell and all instances,
* and the new cell deleted.
*/
Printf("Verilog placeholder %s replaced by SPICE definition\n",
tpsave->name);
tpplace = LookupCellFile("_PLACEHOLDER_", filenum);
/* MatchPins is part of netcmp and normally Circuit2 is the
* circuit being matched, so set Circuit2 to the original
* verilog black-box cell, and MatchPins() will force its
* pins to be rearranged to match the SPICE definition just
* read.
*/
Circuit2 = tpsave;
MatchPins(tpplace, tpsave, 0);
savename = strsave(tpsave->name);
/* Now the original verilog black-box cell can be removed */
FreePorts(savename);
CellDelete(savename, filenum);
/* And _PLACEHOLDER_ is renamed to the original name of the cell. */
CellRehash("_PLACEHOLDER_", savename, filenum);
tpsave = NULL;
Circuit2 = NULL;
FREE(savename);
}
} }
else if (matchnocase(nexttok, ".MODEL")) { else if (matchnocase(nexttok, ".MODEL")) {
unsigned char class = CLASS_SUBCKT; unsigned char class = CLASS_SUBCKT;
@ -782,7 +700,7 @@ skip_ends:
SpiceTokNoNewline(); SpiceTokNoNewline();
if (nexttok == NULL) continue; /* Ignore if no model name */ if (nexttok == NULL) continue; /* Ignore if no model name */
snprintf(model, MAX_STR_LEN-1, "%s", nexttok); snprintf(model, 99, "%s", nexttok);
SpiceTokNoNewline(); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice; if (nexttok == NULL) goto baddevice;
@ -831,10 +749,7 @@ skip_ends:
// Handle some commonly-used cards // Handle some commonly-used cards
/* .GLOBAL and *.GLOBAL. Note that *.GLOBAL is excepted from comment-line else if (matchnocase(nexttok, ".GLOBAL")) {
* handling, above, so any line starting with '*' is "*.GLOBAL".
*/
else if (matchnocase(nexttok, ".GLOBAL") || (nexttok[0] == '*')) {
while (nexttok != NULL) { while (nexttok != NULL) {
int numnodes = 0; int numnodes = 0;
SpiceTokNoNewline(); SpiceTokNoNewline();
@ -969,29 +884,29 @@ skip_ends:
} }
else if (toupper(nexttok[0]) == 'Q') { else if (toupper(nexttok[0]) == 'Q') {
char emitter[MAX_STR_LEN], base[MAX_STR_LEN], collector[MAX_STR_LEN]; char emitter[100], base[100], collector[100];
emitter[MAX_STR_LEN-1] = '\0'; emitter[99] = '\0';
base[MAX_STR_LEN-1] = '\0'; base[99] = '\0';
collector[MAX_STR_LEN-1] = '\0'; collector[99] = '\0';
if (!(*CellStackPtr)) { if (!(*CellStackPtr)) {
CellDef(fname, filenum); CellDef(fname, filenum);
PushStack(fname, CellStackPtr); PushStack(fname, CellStackPtr);
} }
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice; if (nexttok == NULL) goto baddevice;
strncpy(collector, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(collector, nexttok, 99); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice; if (nexttok == NULL) goto baddevice;
strncpy(base, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(base, nexttok, 99); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice; if (nexttok == NULL) goto baddevice;
strncpy(emitter, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(emitter, nexttok, 99); SpiceTokNoNewline();
/* make sure all the nodes exist */ /* make sure all the nodes exist */
if (LookupObject(collector, CurrentCell) == NULL) Node(collector); if (LookupObject(collector, CurrentCell) == NULL) Node(collector);
if (LookupObject(base, CurrentCell) == NULL) Node(base); if (LookupObject(base, CurrentCell) == NULL) Node(base);
if (LookupObject(emitter, CurrentCell) == NULL) Node(emitter); if (LookupObject(emitter, CurrentCell) == NULL) Node(emitter);
/* Read the device model */ /* Read the device model */
snprintf(model, MAX_STR_LEN-1, "%s", nexttok); snprintf(model, 99, "%s", nexttok);
while (nexttok != NULL) while (nexttok != NULL)
{ {
@ -1022,30 +937,30 @@ skip_ends:
goto baddevice; goto baddevice;
} }
snprintf(instname, MAX_STR_LEN-1, "%s:%s", model, inst); snprintf(instname, 255, "%s%s", model, inst);
Cell(instname, model, collector, base, emitter); Cell(instname, model, collector, base, emitter);
pobj = LinkProperties(model, kvlist); pobj = LinkProperties(model, kvlist);
ReduceExpressions(pobj, NULL, CurrentCell, TRUE); ReduceExpressions(pobj, NULL, CurrentCell, TRUE);
DeleteProperties(&kvlist); DeleteProperties(&kvlist);
} }
else if (toupper(nexttok[0]) == 'M') { else if (toupper(nexttok[0]) == 'M') {
char drain[MAX_STR_LEN], gate[MAX_STR_LEN], source[MAX_STR_LEN], bulk[MAX_STR_LEN]; char drain[100], gate[100], source[100], bulk[100];
drain[MAX_STR_LEN-1] = '\0'; drain[99] = '\0';
gate[MAX_STR_LEN-1] = '\0'; gate[99] = '\0';
source[MAX_STR_LEN-1] = '\0'; source[99] = '\0';
bulk[MAX_STR_LEN-1] = '\0'; bulk[99] = '\0';
if (!(*CellStackPtr)) { if (!(*CellStackPtr)) {
CellDef(fname, filenum); CellDef(fname, filenum);
PushStack(fname, CellStackPtr); PushStack(fname, CellStackPtr);
} }
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice; if (nexttok == NULL) goto baddevice;
strncpy(drain, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(drain, nexttok, 99); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice; if (nexttok == NULL) goto baddevice;
strncpy(gate, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(gate, nexttok, 99); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice; if (nexttok == NULL) goto baddevice;
strncpy(source, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(source, nexttok, 99); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice; if (nexttok == NULL) goto baddevice;
/* make sure all the nodes exist */ /* make sure all the nodes exist */
if (LookupObject(drain, CurrentCell) == NULL) Node(drain); if (LookupObject(drain, CurrentCell) == NULL) Node(drain);
@ -1053,11 +968,11 @@ skip_ends:
if (LookupObject(source, CurrentCell) == NULL) Node(source); if (LookupObject(source, CurrentCell) == NULL) Node(source);
/* handle the substrate node */ /* handle the substrate node */
strncpy(bulk, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(bulk, nexttok, 99); SpiceTokNoNewline();
if (LookupObject(bulk, CurrentCell) == NULL) Node(bulk); if (LookupObject(bulk, CurrentCell) == NULL) Node(bulk);
/* Read the device model */ /* Read the device model */
snprintf(model, MAX_STR_LEN-1, "%s", nexttok); snprintf(model, 99, "%s", nexttok);
while (nexttok != NULL) while (nexttok != NULL)
{ {
@ -1095,7 +1010,7 @@ skip_ends:
goto baddevice; goto baddevice;
} }
snprintf(instname, MAX_STR_LEN-1, "%s:%s", model, inst); snprintf(instname, 255, "%s%s", model, inst);
Cell(instname, model, drain, gate, source, bulk); Cell(instname, model, drain, gate, source, bulk);
pobj = LinkProperties(model, kvlist); pobj = LinkProperties(model, kvlist);
ReduceExpressions(pobj, NULL, CurrentCell, TRUE); ReduceExpressions(pobj, NULL, CurrentCell, TRUE);
@ -1109,19 +1024,19 @@ skip_ends:
SpiceSkipNewLine(); SpiceSkipNewLine();
} }
else { else {
char ctop[MAX_STR_LEN], cbot[MAX_STR_LEN]; char ctop[100], cbot[100];
ctop[MAX_STR_LEN-1] = '\0'; ctop[99] = '\0';
cbot[MAX_STR_LEN-1] = '\0'; cbot[99] = '\0';
if (!(*CellStackPtr)) { if (!(*CellStackPtr)) {
CellDef(fname, filenum); CellDef(fname, filenum);
PushStack(fname, CellStackPtr); PushStack(fname, CellStackPtr);
} }
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice; if (nexttok == NULL) goto baddevice;
strncpy(ctop, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(ctop, nexttok, 99); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice; if (nexttok == NULL) goto baddevice;
strncpy(cbot, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(cbot, nexttok, 99); SpiceTokNoNewline();
/* make sure all the nodes exist */ /* make sure all the nodes exist */
if (LookupObject(ctop, CurrentCell) == NULL) Node(ctop); if (LookupObject(ctop, CurrentCell) == NULL) Node(ctop);
@ -1140,7 +1055,7 @@ skip_ends:
model[0] = '\0'; model[0] = '\0';
if ((nexttok != NULL) && ((eqptr = strchr(nexttok, '=')) == NULL)) if ((nexttok != NULL) && ((eqptr = strchr(nexttok, '=')) == NULL))
snprintf(model, MAX_STR_LEN-1, "%s", nexttok); snprintf(model, 99, "%s", nexttok);
/* Any other device properties? */ /* Any other device properties? */
while (nexttok != NULL) while (nexttok != NULL)
@ -1153,7 +1068,7 @@ skip_ends:
} }
else if (!strncmp(nexttok, "$[", 2)) { else if (!strncmp(nexttok, "$[", 2)) {
// Support for CDL modeled capacitor format // Support for CDL modeled capacitor format
snprintf(model, MAX_STR_LEN-1, "%s", nexttok + 2); snprintf(model, 99, "%s", nexttok + 2);
if ((eqptr = strchr(model, ']')) != NULL) if ((eqptr = strchr(model, ']')) != NULL)
*eqptr = '\0'; *eqptr = '\0';
} }
@ -1186,7 +1101,7 @@ skip_ends:
usemodel = 1; usemodel = 1;
} }
snprintf(instname, MAX_STR_LEN-1, "%s:%s", model, inst); snprintf(instname, 255, "%s%s", model, inst);
if (usemodel) if (usemodel)
Cell(instname, model, ctop, cbot); Cell(instname, model, ctop, cbot);
else else
@ -1203,19 +1118,19 @@ skip_ends:
SpiceSkipNewLine(); SpiceSkipNewLine();
} }
else { else {
char rtop[MAX_STR_LEN], rbot[MAX_STR_LEN]; char rtop[100], rbot[100];
rtop[MAX_STR_LEN-1] = '\0'; rtop[99] = '\0';
rbot[MAX_STR_LEN-1] = '\0'; rbot[99] = '\0';
if (!(*CellStackPtr)) { if (!(*CellStackPtr)) {
CellDef(fname, filenum); CellDef(fname, filenum);
PushStack(fname, CellStackPtr); PushStack(fname, CellStackPtr);
} }
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice; if (nexttok == NULL) goto baddevice;
strncpy(rtop, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(rtop, nexttok, 99); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice; if (nexttok == NULL) goto baddevice;
strncpy(rbot, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(rbot, nexttok, 99); SpiceTokNoNewline();
/* make sure all the nodes exist */ /* make sure all the nodes exist */
if (LookupObject(rtop, CurrentCell) == NULL) Node(rtop); if (LookupObject(rtop, CurrentCell) == NULL) Node(rtop);
if (LookupObject(rbot, CurrentCell) == NULL) Node(rbot); if (LookupObject(rbot, CurrentCell) == NULL) Node(rbot);
@ -1234,7 +1149,7 @@ skip_ends:
model[0] = '\0'; model[0] = '\0';
if ((nexttok != NULL) && ((eqptr = strchr(nexttok, '=')) == NULL)) if ((nexttok != NULL) && ((eqptr = strchr(nexttok, '=')) == NULL))
snprintf(model, MAX_STR_LEN-1, "%s", nexttok); snprintf(model, 99, "%s", nexttok);
/* Any other device properties? */ /* Any other device properties? */
while (nexttok != NULL) { while (nexttok != NULL) {
@ -1246,7 +1161,7 @@ skip_ends:
} }
else if (!strncmp(nexttok, "$[", 2)) { else if (!strncmp(nexttok, "$[", 2)) {
// Support for CDL modeled resistor format // Support for CDL modeled resistor format
snprintf(model, MAX_STR_LEN-1, "%s", nexttok + 2); snprintf(model, 99, "%s", nexttok + 2);
if ((eqptr = strchr(model, ']')) != NULL) if ((eqptr = strchr(model, ']')) != NULL)
*eqptr = '\0'; *eqptr = '\0';
} }
@ -1279,7 +1194,7 @@ skip_ends:
else else
strcpy(model, "r"); /* Use default resistor model */ strcpy(model, "r"); /* Use default resistor model */
snprintf(instname, MAX_STR_LEN-1, "%s:%s", model, inst); snprintf(instname, 255, "%s%s", model, inst);
if (usemodel) if (usemodel)
Cell(instname, model, rtop, rbot); Cell(instname, model, rtop, rbot);
else else
@ -1290,25 +1205,25 @@ skip_ends:
} }
} }
else if (toupper(nexttok[0]) == 'D') { /* diode */ else if (toupper(nexttok[0]) == 'D') { /* diode */
char cathode[MAX_STR_LEN], anode[MAX_STR_LEN]; char cathode[100], anode[100];
cathode[MAX_STR_LEN-1] = '\0'; cathode[99] = '\0';
anode[MAX_STR_LEN-1] = '\0'; anode[99] = '\0';
if (!(*CellStackPtr)) { if (!(*CellStackPtr)) {
CellDef(fname, filenum); CellDef(fname, filenum);
PushStack(fname, CellStackPtr); PushStack(fname, CellStackPtr);
} }
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice; if (nexttok == NULL) goto baddevice;
strncpy(anode, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(anode, nexttok, 99); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice; if (nexttok == NULL) goto baddevice;
strncpy(cathode, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(cathode, nexttok, 99); SpiceTokNoNewline();
/* make sure all the nodes exist */ /* make sure all the nodes exist */
if (LookupObject(anode, CurrentCell) == NULL) Node(anode); if (LookupObject(anode, CurrentCell) == NULL) Node(anode);
if (LookupObject(cathode, CurrentCell) == NULL) Node(cathode); if (LookupObject(cathode, CurrentCell) == NULL) Node(cathode);
/* Read the device model */ /* Read the device model */
snprintf(model, MAX_STR_LEN-1, "%s", nexttok); snprintf(model, 99, "%s", nexttok);
while (nexttok != NULL) while (nexttok != NULL)
{ {
@ -1337,7 +1252,7 @@ skip_ends:
Fprintf(stderr, "Device \"%s\" has wrong number of ports for a diode.\n"); Fprintf(stderr, "Device \"%s\" has wrong number of ports for a diode.\n");
goto baddevice; goto baddevice;
} }
snprintf(instname, MAX_STR_LEN-1, "%s:%s", model, inst); snprintf(instname, 255, "%s%s", model, inst);
Cell(instname, model, anode, cathode); Cell(instname, model, anode, cathode);
pobj = LinkProperties(model, kvlist); pobj = LinkProperties(model, kvlist);
ReduceExpressions(pobj, NULL, CurrentCell, TRUE); ReduceExpressions(pobj, NULL, CurrentCell, TRUE);
@ -1350,25 +1265,25 @@ skip_ends:
SpiceSkipNewLine(); SpiceSkipNewLine();
} }
else { else {
char node1[MAX_STR_LEN], node2[MAX_STR_LEN], node3[MAX_STR_LEN], node4[MAX_STR_LEN]; char node1[100], node2[100], node3[100], node4[100];
node1[MAX_STR_LEN-1] = '\0'; node1[99] = '\0';
node2[MAX_STR_LEN-1] = '\0'; node2[99] = '\0';
node3[MAX_STR_LEN-1] = '\0'; node3[99] = '\0';
node4[MAX_STR_LEN-1] = '\0'; node4[99] = '\0';
if (!(*CellStackPtr)) { if (!(*CellStackPtr)) {
CellDef(fname, filenum); CellDef(fname, filenum);
PushStack(fname, CellStackPtr); PushStack(fname, CellStackPtr);
} }
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice; if (nexttok == NULL) goto baddevice;
strncpy(node1, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(node1, nexttok, 99); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice; if (nexttok == NULL) goto baddevice;
strncpy(node2, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(node2, nexttok, 99); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice; if (nexttok == NULL) goto baddevice;
strncpy(node3, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(node3, nexttok, 99); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice; if (nexttok == NULL) goto baddevice;
strncpy(node4, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(node4, nexttok, 99); SpiceTokNoNewline();
/* make sure all the nodes exist */ /* make sure all the nodes exist */
if (LookupObject(node1, CurrentCell) == NULL) Node(node1); if (LookupObject(node1, CurrentCell) == NULL) Node(node1);
if (LookupObject(node2, CurrentCell) == NULL) Node(node2); if (LookupObject(node2, CurrentCell) == NULL) Node(node2);
@ -1380,7 +1295,7 @@ skip_ends:
model[0] = '\0'; model[0] = '\0';
if ((nexttok != NULL) && ((eqptr = strchr(nexttok, '=')) == NULL)) if ((nexttok != NULL) && ((eqptr = strchr(nexttok, '=')) == NULL))
snprintf(model, MAX_STR_LEN-1, "%s", nexttok); snprintf(model, 99, "%s", nexttok);
/* Any other device properties? */ /* Any other device properties? */
while (nexttok != NULL) { while (nexttok != NULL) {
@ -1416,7 +1331,7 @@ skip_ends:
else else
strcpy(model, "t"); /* Use default xline model */ strcpy(model, "t"); /* Use default xline model */
snprintf(instname, MAX_STR_LEN-1, "%s:%s", model, inst); snprintf(instname, 255, "%s%s", model, inst);
if (usemodel) if (usemodel)
Cell(instname, model, node1, node2, node3, node4); Cell(instname, model, node1, node2, node3, node4);
@ -1429,20 +1344,20 @@ skip_ends:
} }
} }
else if (toupper(nexttok[0]) == 'L') { /* inductor */ else if (toupper(nexttok[0]) == 'L') { /* inductor */
char end_a[MAX_STR_LEN], end_b[MAX_STR_LEN]; char end_a[100], end_b[100];
int usemodel = 0; int usemodel = 0;
end_a[MAX_STR_LEN-1] = '\0'; end_a[99] = '\0';
end_b[MAX_STR_LEN-1] = '\0'; end_b[99] = '\0';
if (!(*CellStackPtr)) { if (!(*CellStackPtr)) {
CellDef(fname, filenum); CellDef(fname, filenum);
PushStack(fname, CellStackPtr); PushStack(fname, CellStackPtr);
} }
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice; if (nexttok == NULL) goto baddevice;
strncpy(end_a, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(end_a, nexttok, 99); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice; if (nexttok == NULL) goto baddevice;
strncpy(end_b, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(end_b, nexttok, 99); SpiceTokNoNewline();
/* make sure all the nodes exist */ /* make sure all the nodes exist */
if (LookupObject(end_a, CurrentCell) == NULL) Node(end_a); if (LookupObject(end_a, CurrentCell) == NULL) Node(end_a);
if (LookupObject(end_b, CurrentCell) == NULL) Node(end_b); if (LookupObject(end_b, CurrentCell) == NULL) Node(end_b);
@ -1461,7 +1376,7 @@ skip_ends:
model[0] = '\0'; model[0] = '\0';
if ((nexttok != NULL) && ((eqptr = strchr(nexttok, '=')) == NULL)) if ((nexttok != NULL) && ((eqptr = strchr(nexttok, '=')) == NULL))
snprintf(model, MAX_STR_LEN-1, "%s", nexttok); snprintf(model, 99, "%s", nexttok);
/* Any other device properties? */ /* Any other device properties? */
while (nexttok != NULL) while (nexttok != NULL)
@ -1499,7 +1414,7 @@ skip_ends:
else else
strcpy(model, "l"); /* Use default inductor model */ strcpy(model, "l"); /* Use default inductor model */
snprintf(instname, MAX_STR_LEN-1, "%s:%s", model, inst); snprintf(instname, 255, "%s%s", model, inst);
if (usemodel) if (usemodel)
Cell(instname, model, end_a, end_b); Cell(instname, model, end_a, end_b);
else else
@ -1513,38 +1428,25 @@ skip_ends:
/* black-box subcircuits (class MODULE): V, I, E */ /* black-box subcircuits (class MODULE): V, I, E */
else if (toupper(nexttok[0]) == 'V') { /* voltage source */ else if (toupper(nexttok[0]) == 'V') { /* voltage source */
char pos[MAX_STR_LEN], neg[MAX_STR_LEN]; char pos[100], neg[100];
pos[MAX_STR_LEN-1] = '\0'; pos[99] = '\0';
neg[MAX_STR_LEN-1] = '\0'; neg[99] = '\0';
if (!(*CellStackPtr)) { if (!(*CellStackPtr)) {
CellDef(fname, filenum); CellDef(fname, filenum);
PushStack(fname, CellStackPtr); PushStack(fname, CellStackPtr);
} }
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice; if (nexttok == NULL) goto baddevice;
strncpy(pos, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(pos, nexttok, 99); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice; if (nexttok == NULL) goto baddevice;
strncpy(neg, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(neg, nexttok, 99); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice; if (nexttok == NULL) goto baddevice;
/* make sure all the nodes exist */ /* make sure all the nodes exist */
if (LookupObject(pos, CurrentCell) == NULL) Node(pos); if (LookupObject(pos, CurrentCell) == NULL) Node(pos);
if (LookupObject(neg, CurrentCell) == NULL) Node(neg); if (LookupObject(neg, CurrentCell) == NULL) Node(neg);
/* Get voltage value (if present); save as property "value" */ /* Any device properties? */
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) while (nexttok != NULL)
{ {
SpiceTokNoNewline(); SpiceTokNoNewline();
@ -1572,7 +1474,7 @@ skip_ends:
else if (CountPorts(model, filenum) != 2) { else if (CountPorts(model, filenum) != 2) {
/* Modeled device: Make sure it has the right number of ports */ /* Modeled device: Make sure it has the right number of ports */
Fprintf(stderr, "Device \"%s\" has wrong number of ports for a " Fprintf(stderr, "Device \"%s\" has wrong number of ports for a "
"voltage source.\n", inst); "voltage source.\n");
goto baddevice; goto baddevice;
} }
Cell(instname, model, pos, neg); Cell(instname, model, pos, neg);
@ -1581,19 +1483,19 @@ skip_ends:
DeleteProperties(&kvlist); DeleteProperties(&kvlist);
} }
else if (toupper(nexttok[0]) == 'I') { /* current source */ else if (toupper(nexttok[0]) == 'I') { /* current source */
char pos[MAX_STR_LEN], neg[MAX_STR_LEN]; char pos[100], neg[100];
pos[MAX_STR_LEN-1] = '\0'; pos[99] = '\0';
neg[MAX_STR_LEN-1] = '\0'; neg[99] = '\0';
if (!(*CellStackPtr)) { if (!(*CellStackPtr)) {
CellDef(fname, filenum); CellDef(fname, filenum);
PushStack(fname, CellStackPtr); PushStack(fname, CellStackPtr);
} }
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice; if (nexttok == NULL) goto baddevice;
strncpy(pos, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(pos, nexttok, 99); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice; if (nexttok == NULL) goto baddevice;
strncpy(neg, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(neg, nexttok, 99); SpiceTokNoNewline();
/* make sure all the nodes exist */ /* make sure all the nodes exist */
if (LookupObject(pos, CurrentCell) == NULL) Node(pos); if (LookupObject(pos, CurrentCell) == NULL) Node(pos);
if (LookupObject(neg, CurrentCell) == NULL) Node(neg); if (LookupObject(neg, CurrentCell) == NULL) Node(neg);
@ -1635,25 +1537,25 @@ skip_ends:
DeleteProperties(&kvlist); DeleteProperties(&kvlist);
} }
else if (toupper(nexttok[0]) == 'E') { /* controlled voltage source */ else if (toupper(nexttok[0]) == 'E') { /* controlled voltage source */
char pos[MAX_STR_LEN], neg[MAX_STR_LEN], ctrlp[MAX_STR_LEN], ctrln[MAX_STR_LEN]; char pos[100], neg[100], ctrlp[100], ctrln[100];
pos[MAX_STR_LEN-1] = '\0'; pos[99] = '\0';
neg[MAX_STR_LEN-1] = '\0'; neg[99] = '\0';
ctrlp[MAX_STR_LEN-1] = '\0'; ctrlp[99] = '\0';
ctrln[MAX_STR_LEN-1] = '\0'; ctrln[99] = '\0';
if (!(*CellStackPtr)) { if (!(*CellStackPtr)) {
CellDef(fname, filenum); CellDef(fname, filenum);
PushStack(fname, CellStackPtr); PushStack(fname, CellStackPtr);
} }
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice; if (nexttok == NULL) goto baddevice;
strncpy(pos, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(pos, nexttok, 99); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice; if (nexttok == NULL) goto baddevice;
strncpy(neg, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(neg, nexttok, 99); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice; if (nexttok == NULL) goto baddevice;
strncpy(ctrlp, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(ctrlp, nexttok, 99); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice; if (nexttok == NULL) goto baddevice;
strncpy(ctrln, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline(); strncpy(ctrln, nexttok, 99); SpiceTokNoNewline();
/* make sure all the nodes exist */ /* make sure all the nodes exist */
if (LookupObject(pos, CurrentCell) == NULL) Node(pos); if (LookupObject(pos, CurrentCell) == NULL) Node(pos);
@ -1701,11 +1603,11 @@ skip_ends:
} }
else if (toupper(nexttok[0]) == 'X') { /* subcircuit instances */ else if (toupper(nexttok[0]) == 'X') { /* subcircuit instances */
char instancename[MAX_STR_LEN], subcktname[MAX_STR_LEN]; char instancename[100], subcktname[100];
int itype, in_props; int itype, in_props;
instancename[MAX_STR_LEN-1] = '\0'; instancename[99] = '\0';
subcktname[MAX_STR_LEN-1] = '\0'; subcktname[99] = '\0';
struct portelement { struct portelement {
char *name; char *name;
@ -1715,8 +1617,8 @@ skip_ends:
struct portelement *head, *tail, *scan, *scannext; struct portelement *head, *tail, *scan, *scannext;
struct objlist *obptr; struct objlist *obptr;
snprintf(instancename, MAX_STR_LEN-1, "%s", nexttok + 1); snprintf(instancename, 99, "%s", nexttok + 1);
strncpy(instancename, nexttok + 1, MAX_STR_LEN-1); strncpy(instancename, nexttok + 1, 99);
if (!(*CellStackPtr)) { if (!(*CellStackPtr)) {
CellDef(fname, filenum); CellDef(fname, filenum);
PushStack(fname, CellStackPtr); PushStack(fname, CellStackPtr);
@ -1783,19 +1685,10 @@ skip_ends:
if (scan->next != NULL) scan = scan->next; if (scan->next != NULL) scan = scan->next;
tail->next = NULL; tail->next = NULL;
/* Check for class defined inside itself (self-referential loop) */
if (!strcasecmp(model, scan->name)) {
Fprintf(stderr, "Fatal: Class \"%s\" is instanced inside of itself!\n",
scan->name);
InputParseError(stderr);
return;
}
/* Check for ignored class */ /* Check for ignored class */
if ((itype = IsIgnored(scan->name, filenum)) == IGNORE_CLASS) { if ((itype = IsIgnored(subcktname, filenum)) == IGNORE_CLASS) {
Printf("Class '%s' instanced in input but is being ignored.\n", scan->name); Printf("Class '%s' instanced in input but is being ignored.\n", model);
return; return;
} }
@ -1810,7 +1703,7 @@ skip_ends:
break; break;
} }
if (shorted == (unsigned char)1) { if (shorted == (unsigned char)1) {
Printf("Instance of '%s' is shorted, ignoring.\n", scan->name); Printf("Instance of '%s' is shorted, ignoring.\n", subcktname);
while (head) { while (head) {
p = head->next; p = head->next;
FREE(head); FREE(head);
@ -1833,14 +1726,14 @@ skip_ends:
/* names. */ /* names. */
if (strncmp(instancename, scan->name, strlen(scan->name))) { if (strncmp(instancename, scan->name, strlen(scan->name))) {
snprintf(subcktname, MAX_STR_LEN-1, "%s:%s", scan->name, instancename); snprintf(subcktname, 99, "%s%s", scan->name, instancename);
strcpy(instancename, subcktname); strcpy(instancename, subcktname);
} }
else { else {
snprintf(subcktname, MAX_STR_LEN-1, "/%s", instancename); snprintf(subcktname, 99, "/%s", instancename);
strcpy(instancename, subcktname); strcpy(instancename, subcktname);
} }
snprintf(subcktname, MAX_STR_LEN-1, "%s", scan->name); snprintf(subcktname, 99, "%s", scan->name);
if (scan == head) { if (scan == head) {
head = NULL; head = NULL;
@ -1874,18 +1767,6 @@ skip_ends:
ReopenCellDef((*CellStackPtr)->cellname, filenum); /* Reopen */ ReopenCellDef((*CellStackPtr)->cellname, filenum); /* Reopen */
update = 1; 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 */ /* nexttok is now NULL, scan->name points to class */
@ -2088,7 +1969,7 @@ void IncludeSpice(char *fname, int parent, struct cellstack **CellStackPtr,
int blackbox) int blackbox)
{ {
int filenum = -1; int filenum = -1;
char name[MAX_STR_LEN]; char name[256];
/* If fname does not begin with "/", then assume that it is */ /* If fname does not begin with "/", then assume that it is */
/* in the same relative path as its parent. */ /* in the same relative path as its parent. */

View File

@ -1,8 +0,0 @@
#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 */

View File

@ -34,8 +34,6 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "print.h" #include "print.h"
#endif #endif
extern void Finsert(FILE *f);
void test_entry(void) void test_entry(void)
{ {

File diff suppressed because it is too large Load Diff

View File

@ -23,7 +23,6 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <ctype.h> #include <ctype.h>
#include <time.h>
#ifdef IBMPC #ifdef IBMPC
#include <stdlib.h> /* for strtol on PC */ #include <stdlib.h> /* for strtol on PC */
@ -34,8 +33,6 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "netfile.h" #include "netfile.h"
#include "hash.h" #include "hash.h"
#include "print.h" #include "print.h"
#include "xilinx.h"
#include "flatten.h"
#define XILINXHASHSIZE 99 #define XILINXHASHSIZE 99
static long xilinxhashbase = 0xA00; static long xilinxhashbase = 0xA00;
@ -135,8 +132,10 @@ char *xilinx_class(model)
} }
return(model); return(model);
} }
void
void Xilinx(char *cellname, char *filename) Xilinx(cellname, filename)
char *cellname;
char *filename;
{ {
char Path[500]; char Path[500];
char FileName[500]; char FileName[500];
@ -164,7 +163,8 @@ void Xilinx(char *cellname, char *filename)
CloseFile(FileName); CloseFile(FileName);
} }
int xilinxCell(char *cell) xilinxCell(cell)
char *cell;
{ {
struct nlist *nl; struct nlist *nl;
struct objlist *ob; struct objlist *ob;
@ -252,7 +252,9 @@ struct objlist *xilinx_gate(ob,nl)
return(nob); return(nob);
} }
void xilinx_sym(struct nlist *nl, struct objlist *gob) xilinx_sym(nl,gob)
struct nlist *nl;
struct objlist *gob;
{ {
struct objlist *ob; struct objlist *ob;
char *cp,*rindex(); char *cp,*rindex();

View File

@ -1,10 +0,0 @@
#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 */

View File

@ -65,10 +65,10 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
Widget toplevel = NULL; Widget toplevel = NULL;
char GlobalFileName[MAX_STR_LEN], char GlobalFileName[100],
GlobalCellName[MAX_STR_LEN], GlobalCellName[100],
GlobalOtherName[MAX_STR_LEN], GlobalOtherName[100],
GlobalDataName[MAX_STR_LEN]; GlobalDataName[100];
/********************************************************* /*********************************************************
* Menu structure: attaches label string to a function, * Menu structure: attaches label string to a function,
@ -1708,7 +1708,7 @@ void X_main_loop(int argc, char *argv[])
XmStringCharSet cs = "ISOLatin1"; XmStringCharSet cs = "ISOLatin1";
static char prompt_response[MAX_STR_LEN]; static char prompt_response[100];
int prompt_done; int prompt_done;
int calling_editor; /* which string are we trying to get ? */ int calling_editor; /* which string are we trying to get ? */
#define FILE_NAME 1 #define FILE_NAME 1

View File

@ -17,7 +17,6 @@ along with this program; see the file copying. If not, write to
the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* inetcomp.c -- a simple wrapper to the NETCOMP() function */ /* inetcomp.c -- a simple wrapper to the NETCOMP() function */
#include "config.h"
#include <stdio.h> #include <stdio.h>
#include "netgen.h" #include "netgen.h"
@ -34,7 +33,7 @@ void STRCPY(char *dest, char *source)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
char cell1[MAX_STR_LEN], cell2[MAX_STR_LEN]; char cell1[200], cell2[200];
Debug = 0; Debug = 0;
if (argc != 1) { if (argc != 1) {

View File

@ -17,7 +17,6 @@ along with this program; see the file copying. If not, write to
the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* netcomp.c -- a simple wrapper to provide netlist comparison functionality */ /* netcomp.c -- a simple wrapper to provide netlist comparison functionality */
#include "config.h"
#include <stdio.h> #include <stdio.h>
#include "netgen.h" #include "netgen.h"
@ -52,7 +51,7 @@ void STRCPY(char *dest, char *source)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
#ifndef HAVE_GETOPT #ifndef HAVE_GETOPT
char cell1[MAX_STR_LEN], cell2[MAX_STR_LEN]; char cell1[200], cell2[200];
int filenum = -1; int filenum = -1;
Debug = 0; Debug = 0;
@ -68,7 +67,7 @@ int main(int argc, char *argv[])
STRCPY(cell2, ReadNetlist(argv[2], &filenum)); STRCPY(cell2, ReadNetlist(argv[2], &filenum));
if (argc == 5) STRCPY(cell2, argv[4]); /* if explicit cell name specified */ if (argc == 5) STRCPY(cell2, argv[4]); /* if explicit cell name specified */
#else #else
char cell1[MAX_STR_LEN], cell2[MAX_STR_LEN]; char cell1[200], cell2[200];
int usage = 0; int usage = 0;
int args; int args;
int c; int c;

View File

@ -23,7 +23,6 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdlib.h> /* for getenv */ #include <stdlib.h> /* for getenv */
#endif #endif
#include "netgen.h" #include "netgen.h"
#include "print.h"
int main(int argc, char **argv) int main(int argc, char **argv)
{ {

View File

@ -20,11 +20,9 @@ along with this program; see the file copying. If not, write to
the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* ntk2xnf.c -- a simple wrapper to translate .ntk to Xilinx XNF format */ /* ntk2xnf.c -- a simple wrapper to translate .ntk to Xilinx XNF format */
#include "config.h"
#include <stdio.h> #include <stdio.h>
#include "netgen.h" #include "netgen.h"
#include "xilinx.h"
#ifdef HAVE_X11 #ifdef HAVE_X11
/* the following two X procedures are to permit linking /* the following two X procedures are to permit linking
@ -49,7 +47,7 @@ void STRCPY(char *dest, char *source)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
char cellname[MAX_STR_LEN]; char cellname[200];
int filenum = -1; int filenum = -1;
Debug = 0; Debug = 0;

View File

@ -29,7 +29,6 @@ lvs_manager.py: lvs_manager.py.in
$(DESTDIR)${INSTALL_PYDIR}/lvs_manager.py: lvs_manager.py $(DESTDIR)${INSTALL_PYDIR}/lvs_manager.py: lvs_manager.py
${RM} $@ ${RM} $@
${CP} lvs_manager.py $@ ${CP} lvs_manager.py $@
chmod a+x $@
$(DESTDIR)${INSTALL_PYDIR}/treeviewsplit.py: treeviewsplit.py $(DESTDIR)${INSTALL_PYDIR}/treeviewsplit.py: treeviewsplit.py
${RM} $@ ${RM} $@

1083
scripts/config.guess vendored

File diff suppressed because it is too large Load Diff

2837
scripts/config.sub vendored

File diff suppressed because it is too large Load Diff

74
scripts/configure vendored
View File

@ -668,6 +668,7 @@ XMKMF
HAVE_PYTHON3 HAVE_PYTHON3
EGREP EGREP
GREP GREP
M4
RANLIB RANLIB
INSTALL_DATA INSTALL_DATA
INSTALL_SCRIPT INSTALL_SCRIPT
@ -711,7 +712,6 @@ infodir
docdir docdir
oldincludedir oldincludedir
includedir includedir
runstatedir
localstatedir localstatedir
sharedstatedir sharedstatedir
sysconfdir sysconfdir
@ -794,7 +794,6 @@ datadir='${datarootdir}'
sysconfdir='${prefix}/etc' sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com' sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var' localstatedir='${prefix}/var'
runstatedir='${localstatedir}/run'
includedir='${prefix}/include' includedir='${prefix}/include'
oldincludedir='/usr/include' oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@ -1047,15 +1046,6 @@ do
| -silent | --silent | --silen | --sile | --sil) | -silent | --silent | --silen | --sile | --sil)
silent=yes ;; 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) -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
ac_prev=sbindir ;; ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@ -1193,7 +1183,7 @@ fi
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
datadir sysconfdir sharedstatedir localstatedir includedir \ datadir sysconfdir sharedstatedir localstatedir includedir \
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
libdir localedir mandir runstatedir libdir localedir mandir
do do
eval ac_val=\$$ac_var eval ac_val=\$$ac_var
# Remove trailing slashes. # Remove trailing slashes.
@ -1346,7 +1336,6 @@ Fine tuning of the installation directories:
--sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var] --localstatedir=DIR modifiable single-machine data [PREFIX/var]
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
--libdir=DIR object code libraries [EPREFIX/lib] --libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include] --includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include] --oldincludedir=DIR C header files for non-gcc [/usr/include]
@ -3701,6 +3690,56 @@ else
fi fi
for ac_prog in gm4 gnum4 m4
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_M4+:} false; then :
$as_echo_n "(cached) " >&6
else
case $M4 in
[\\/]* | ?:[\\/]*)
ac_cv_path_M4="$M4" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_M4="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
M4=$ac_cv_path_M4
if test -n "$M4"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $M4" >&5
$as_echo "$M4" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
test -n "$M4" && break
done
test -n "$M4" || M4="no"
if test x$M4 = xno; then
as_fn_error $? "M4 is required" "$LINENO" 5
fi
if test "$CPP" = "$CC -E" ; then if test "$CPP" = "$CC -E" ; then
CPP="$CPP -x c" CPP="$CPP -x c"
@ -6026,6 +6065,7 @@ fi
if test $usingTcl ; then if test $usingTcl ; then
usingX11=1
cadinstall="$cadinstall tcltk" cadinstall="$cadinstall tcltk"
modules="$modules tcltk" modules="$modules tcltk"
programs="$programs tcltk" programs="$programs tcltk"
@ -6035,11 +6075,7 @@ if test $usingTcl ; then
extra_libs="$extra_libs \${NETGENDIR}/tcltk/libtcltk.o" extra_libs="$extra_libs \${NETGENDIR}/tcltk/libtcltk.o"
extra_defs="$extra_defs -DTCL_DIR=\\\"\${TCLDIR}\\\"" extra_defs="$extra_defs -DTCL_DIR=\\\"\${TCLDIR}\\\""
if test $usingX11 ; then
stub_defs="$stub_defs -DUSE_TCL_STUBS"
else
stub_defs="$stub_defs -DUSE_TCL_STUBS -DUSE_TK_STUBS" stub_defs="$stub_defs -DUSE_TCL_STUBS -DUSE_TK_STUBS"
fi
else else
programs="$programs netgen" programs="$programs netgen"
unused="$unused tcltk" unused="$unused tcltk"
@ -6124,7 +6160,6 @@ if test $usingTcl ; then
# Tk libraries and header files # Tk libraries and header files
# #
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
if test $usingX11 ; then
if test "${TK_INC_DIR}" != "/usr/include" ; then if test "${TK_INC_DIR}" != "/usr/include" ; then
INC_SPECS="${INC_SPECS} -I${TK_INC_DIR}" INC_SPECS="${INC_SPECS} -I${TK_INC_DIR}"
fi fi
@ -6141,7 +6176,6 @@ if test $usingX11 ; then
loader_run_path="${TK_LIB_DIR}:${loader_run_path}" loader_run_path="${TK_LIB_DIR}:${loader_run_path}"
fi fi
fi fi
fi
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
# #
@ -6251,7 +6285,7 @@ fi
*darwin*) *darwin*)
SHDLIB_EXT=".dylib" SHDLIB_EXT=".dylib"
LDDL_FLAGS="-dynamiclib -undefined dynamic_lookup" LDDL_FLAGS="-dynamiclib -flat_namespace -undefined suppress -noprebind"
LDFLAGS="${LDFLAGS} ${LIB_SPECS}" LDFLAGS="${LDFLAGS} ${LIB_SPECS}"
CFLAGS="${CFLAGS} ${X_CFLAGS} ${INC_SPECS} -I/sw/include -fno-common" CFLAGS="${CFLAGS} ${X_CFLAGS} ${INC_SPECS} -I/sw/include -fno-common"
;; ;;

View File

@ -26,6 +26,12 @@ AC_ISC_POSIX
AC_PROG_INSTALL AC_PROG_INSTALL
AC_PROG_RANLIB AC_PROG_RANLIB
dnl GNU M4 is preferred due to some of the option switches.
AC_PATH_PROGS([M4], [gm4 gnum4 m4], [no])
if test x$M4 = xno; then
AC_MSG_ERROR([M4 is required])
fi
dnl check size of pointer for correct behavior on 64-bit systems dnl check size of pointer for correct behavior on 64-bit systems
dnl If the C preprocessor is GCC, we need to force the flag to dnl If the C preprocessor is GCC, we need to force the flag to
dnl assert that input files are of type C, or else the preprocessing dnl assert that input files are of type C, or else the preprocessing
@ -801,6 +807,7 @@ dnl "make" instead of requiring "make tcl"
dnl ---------------------------------------------------------------- dnl ----------------------------------------------------------------
if test $usingTcl ; then if test $usingTcl ; then
usingX11=1
cadinstall="$cadinstall tcltk" cadinstall="$cadinstall tcltk"
modules="$modules tcltk" modules="$modules tcltk"
programs="$programs tcltk" programs="$programs tcltk"
@ -809,11 +816,7 @@ if test $usingTcl ; then
AC_DEFINE(TCL_NETGEN) AC_DEFINE(TCL_NETGEN)
extra_libs="$extra_libs \${NETGENDIR}/tcltk/libtcltk.o" extra_libs="$extra_libs \${NETGENDIR}/tcltk/libtcltk.o"
extra_defs="$extra_defs -DTCL_DIR=\\\"\${TCLDIR}\\\"" extra_defs="$extra_defs -DTCL_DIR=\\\"\${TCLDIR}\\\""
if test $usingX11 ; then
stub_defs="$stub_defs -DUSE_TCL_STUBS"
else
stub_defs="$stub_defs -DUSE_TCL_STUBS -DUSE_TK_STUBS" stub_defs="$stub_defs -DUSE_TCL_STUBS -DUSE_TK_STUBS"
fi
else else
programs="$programs netgen" programs="$programs netgen"
unused="$unused tcltk" unused="$unused tcltk"
@ -900,7 +903,6 @@ if test $usingTcl ; then
# Tk libraries and header files # Tk libraries and header files
# #
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
if test $usingX11 ; then
if test "${TK_INC_DIR}" != "/usr/include" ; then if test "${TK_INC_DIR}" != "/usr/include" ; then
INC_SPECS="${INC_SPECS} -I${TK_INC_DIR}" INC_SPECS="${INC_SPECS} -I${TK_INC_DIR}"
fi fi
@ -917,7 +919,6 @@ if test $usingX11 ; then
loader_run_path="${TK_LIB_DIR}:${loader_run_path}" loader_run_path="${TK_LIB_DIR}:${loader_run_path}"
fi fi
fi fi
fi
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
# #
@ -1027,7 +1028,7 @@ fi
*darwin*) *darwin*)
SHDLIB_EXT=".dylib" SHDLIB_EXT=".dylib"
LDDL_FLAGS="-dynamiclib -undefined dynamic_lookup" LDDL_FLAGS="-dynamiclib -flat_namespace -undefined suppress -noprebind"
LDFLAGS="${LDFLAGS} ${LIB_SPECS}" LDFLAGS="${LDFLAGS} ${LIB_SPECS}"
CFLAGS="${CFLAGS} ${X_CFLAGS} ${INC_SPECS} -I/sw/include -fno-common" CFLAGS="${CFLAGS} ${X_CFLAGS} ${INC_SPECS} -I/sw/include -fno-common"
;; ;;

File diff suppressed because it is too large Load Diff

View File

@ -68,7 +68,6 @@ LIB_SPECS = @LIB_SPECS@
LIB_SPECS_NOSTUB = @LIB_SPECS_NOSTUB@ LIB_SPECS_NOSTUB = @LIB_SPECS_NOSTUB@
WISH_EXE = @WISH_EXE@ WISH_EXE = @WISH_EXE@
TCL_LIB_DIR = @TCL_LIB_DIR@ TCL_LIB_DIR = @TCL_LIB_DIR@
EXTRA_CFLAGS =
CC = @CC@ CC = @CC@
CPP = @CPP@ CPP = @CPP@
@ -77,7 +76,7 @@ CXX = @CXX@
CPPFLAGS = -I. -I${NETGENDIR} @CPPFLAGS@ CPPFLAGS = -I. -I${NETGENDIR} @CPPFLAGS@
DFLAGS = @extra_defs@ @stub_defs@ @DEFS@ -DSHDLIB_EXT=\"@SHDLIB_EXT@\" -DNDEBUG DFLAGS = @extra_defs@ @stub_defs@ @DEFS@ -DSHDLIB_EXT=\"@SHDLIB_EXT@\" -DNDEBUG
DFLAGS_NOSTUB = @extra_defs@ @DEFS@ -DSHDLIB_EXT=\"@SHDLIB_EXT@\" -DNDEBUG DFLAGS_NOSTUB = @extra_defs@ @DEFS@ -DSHDLIB_EXT=\"@SHDLIB_EXT@\" -DNDEBUG
CFLAGS = @CFLAGS@ @SHLIB_CFLAGS@ @INC_SPECS@ ${EXTRA_CFLAGS} CFLAGS = @CFLAGS@ @SHLIB_CFLAGS@ @INC_SPECS@
DEPEND_FILE = Depend DEPEND_FILE = Depend
DEPEND_FLAG = @DEPEND_FLAG@ DEPEND_FLAG = @DEPEND_FLAG@

View File

@ -62,18 +62,16 @@ proc netgen::convert_to_json {filename lvs_final} {
puts $fjson " \[" puts $fjson " \["
set cktval [lindex $value 0] set cktval [lindex $value 0]
foreach pin [lrange $cktval 0 end-1] { foreach pin [lrange $cktval 0 end-1] {
set pinstr [string map {"\\" "\\\\"} $pin] puts $fjson " \"$pin\","
puts $fjson " \"$pinstr\","
} }
set pin [string map {"\\" "\\\\"} [lindex $cktval end]] set pin [lindex $cktval end]
puts $fjson " \"$pin\"" puts $fjson " \"$pin\""
puts $fjson " \], \[" puts $fjson " \], \["
set cktval [lindex $value 1] set cktval [lindex $value 1]
foreach pin [lrange $cktval 0 end-1] { foreach pin [lrange $cktval 0 end-1] {
set pinstr [string map {"\\" "\\\\"} $pin] puts $fjson " \"$pin\","
puts $fjson " \"$pinstr\","
} }
set pin [string map {"\\" "\\\\"} [lindex $cktval end]] set pin [lindex $cktval end]
puts $fjson " \"$pin\"" puts $fjson " \"$pin\""
puts $fjson " \]" puts $fjson " \]"
if {$kidx == $nkeys} { if {$kidx == $nkeys} {
@ -395,7 +393,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; # If argument is a filename then read the list of cells from it;
# otherwise, argument is the list of files itself in quotes or # otherwise, argument is the list of files itself in quotes or
# braces. # braces.
if {[file exists $value]} { if {![catch {file exists $value}]} {
if {![catch {open $value r} fnf]} { if {![catch {open $value r} fnf]} {
while {[gets $fnf line] >= 0} { while {[gets $fnf line] >= 0} {
if {[lindex $line 0] != "#"} { if {[lindex $line 0] != "#"} {
@ -429,7 +427,7 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
set file1 $name1 set file1 $name1
set cell1 $name1 set cell1 $name1
} }
puts stdout "Reading netlist file $file1 for $name1" puts stdout "Reading netlist file $file1"
set fnum1 [netgen::readnet $file1] set fnum1 [netgen::readnet $file1]
} else { } else {
set cell1 [lindex $flist1 0] set cell1 [lindex $flist1 0]
@ -446,7 +444,7 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
set file2 $name2 set file2 $name2
set cell2 $name2 set cell2 $name2
} }
puts stdout "Reading netlist file $file2 for $name2" puts stdout "Reading netlist file $file2"
set fnum2 [netgen::readnet $file2] set fnum2 [netgen::readnet $file2]
} else { } else {
set cell2 [lindex $flist2 0] set cell2 [lindex $flist2 0]
@ -461,7 +459,7 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
} }
set clist1 [cells list $fnum1] set clist1 [cells list $fnum1]
set cidx [lsearch -exact $clist1 $cell1] set cidx [lsearch -regexp $clist1 ^$cell1$]
if {$cidx < 0} { if {$cidx < 0} {
puts stderr "Cannot find cell $cell1 in file $file1" puts stderr "Cannot find cell $cell1 in file $file1"
return return
@ -469,7 +467,7 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
set cell1 [lindex $clist1 $cidx] set cell1 [lindex $clist1 $cidx]
} }
set clist2 [cells list $fnum2] set clist2 [cells list $fnum2]
set cidx [lsearch -exact $clist2 $cell2] set cidx [lsearch -regexp $clist2 ^$cell2$]
if {$cidx < 0} { if {$cidx < 0} {
puts stderr "Cannot find cell $cell2 in file $file2" puts stderr "Cannot find cell $cell2 in file $file2"
return return
@ -477,26 +475,10 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
set cell2 [lindex $clist2 $cidx] set cell2 [lindex $clist2 $cidx]
} }
# The "noflat" list is non-file-specific, so run on each file.
foreach cell $noflat {
set cidx [lsearch -regexp $clist1 ^$cell$]
if {$cidx >= 0} {
netgen::flatten prohibit "$fnum1 $cell"
}
set cidx [lsearch -regexp $clist2 ^$cell$]
if {$cidx >= 0} {
netgen::flatten prohibit "$fnum2 $cell"
}
}
netgen::compare assign "$fnum1 $cell1" "$fnum2 $cell2" netgen::compare assign "$fnum1 $cell1" "$fnum2 $cell2"
if {$setupfile == ""} { if {[file exists $setupfile]} {
puts stdout "\nNo setup file specified. Using trivial default setup.\n" puts stdout "Reading setup file $setupfile"
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 # Instead of sourcing the setup file, run each line so we can
# catch individual errors and not let them halt the LVS process # catch individual errors and not let them halt the LVS process
set perrors 0 set perrors 0
@ -516,14 +498,6 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
} }
} }
close $fsetup close $fsetup
if {$command != {}} {
# Incomplete command. Evaluate it to get a meaningful error message
if {[catch {uplevel 1 [list namespace eval netgen $command]} msg]} {
set msg [string trimright $msg "\n"]
puts stderr "Error $setupfile:$sline (ignoring), $msg"
incr perrors
}
}
} else { } else {
puts stdout "Error: Cannot read the setup file $setupfile" puts stdout "Error: Cannot read the setup file $setupfile"
} }
@ -532,10 +506,8 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
puts stdout "Warning: There were errors reading the setup file" puts stdout "Warning: There were errors reading the setup file"
} }
} elseif {[string first nosetup $setupfile] < 0} { } elseif {[string first nosetup $setupfile] < 0} {
puts stderr "\nError: Setup file $setupfile does not exist.\n" netgen::permute default ;# transistors and resistors
return netgen::property default
} else {
puts stderr "\nNo setup file specified. Continuing without a setup.\n"
} }
if {[string first nolog $logfile] < 0} { if {[string first nolog $logfile] < 0} {
@ -560,24 +532,14 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
} }
set properr {} set properr {}
set matcherr {} set matcherr {}
set childMismatch 0 ;# 1 indicates black-box child subcircuit mismatch set pinsgood -1
while {$endval != {}} { while {$endval != {}} {
if {$dolist == 1} { if {$dolist == 1} {
netgen::run -list converge netgen::run -list converge
} else { } else {
netgen::run converge netgen::run converge
} }
set pinMismatch 0 ;# indicates pin mismatch in top cell netgen::log echo on
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]} { if {[verify equivalent]} {
# Resolve automorphisms by pin and property # Resolve automorphisms by pin and property
if {$dolist == 1} { if {$dolist == 1} {
@ -586,113 +548,96 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
netgen::run resolve netgen::run resolve
} }
set uresult [verify unique] 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} { if {$uresult == 0} {
netgen::log echo on
netgen::log put " Networks match locally but not globally.\n" netgen::log put " Networks match locally but not globally.\n"
netgen::log put " Probably connections are swapped.\n" netgen::log put " Probably connections are swapped.\n"
netgen::log put " Check the end of logfile ${logfile} for implicated nodes.\n" netgen::log put " Check the end of logfile ${logfile} for implicated nodes.\n"
netgen::log echo off
if {$dolist == 1} { if {$dolist == 1} {
verify -list nodes verify -list nodes
} else { } else {
verify nodes verify nodes
} }
set doCheckFlatten 1
} else { # Flatten the non-matching subcircuit (but not the top-level cells)
# 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
} elseif {$uresult == -4} { ;# unmatched pins and properties
lappend properr [lindex $endval 0]
set doCheckFlatten 1
}
} else {
# 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 {[netgen::print queue] != {}} {
if {([lsearch $noflat [lindex $endval 0]] == -1) && if {([lsearch $noflat [lindex $endval 0]] == -1) &&
([lsearch $noflat [lindex $endval 1]] == -1)} { ([lsearch $noflat [lindex $endval 1]] == -1)} {
set doFlatten 1 netgen::log put " Flattening non-matched subcircuits $endval"
netgen::flatten class "[lindex $endval 0] $fnum1"
netgen::flatten class "[lindex $endval 1] $fnum2"
} else { } else {
netgen::log echo on netgen::log put " Continuing with black-boxed subcircuits $endval"
netgen::log put " Continuing with black-boxed subcircuits $endval\n" lappend matcherr [lindex $endval 0]
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
}
}
}
if {$doEquatePins} {
# Match pins # Match pins
netgen::log echo off
if {$dolist == 1} { if {$dolist == 1} {
if {$forceMatch} {
set result [equate -list -force pins "$fnum1 [lindex $endval 0]" \ set result [equate -list -force pins "$fnum1 [lindex $endval 0]" \
"$fnum2 [lindex $endval 1]"] "$fnum2 [lindex $endval 1]"]
} else { } else {
set result [equate -list pins "$fnum1 [lindex $endval 0]" \ set result [equate -force pins "$fnum1 [lindex $endval 0]" \
"$fnum2 [lindex $endval 1]"] "$fnum2 [lindex $endval 1]"]
} }
if {$result != 0} {
equate classes "$fnum1 [lindex $endval 0]" \
"$fnum2 [lindex $endval 1]"
}
set pinsgood $result
netgen::log echo on
}
}
} else { } else {
if {$forceMatch} { netgen::log echo off
set result [equate -force pins "$fnum1 [lindex $endval 0]" \ if {$dolist == 1} {
set result [equate -list pins "$fnum1 [lindex $endval 0]" \
"$fnum2 [lindex $endval 1]"] "$fnum2 [lindex $endval 1]"]
} else { } else {
set result [equate pins "$fnum1 [lindex $endval 0]" \ set result [equate pins "$fnum1 [lindex $endval 0]" \
"$fnum2 [lindex $endval 1]"] "$fnum2 [lindex $endval 1]"]
} }
} if {$result != 0} {
if {$result >= 0} {
equate classes "$fnum1 [lindex $endval 0]" \ equate classes "$fnum1 [lindex $endval 0]" \
"$fnum2 [lindex $endval 1]" "$fnum2 [lindex $endval 1]"
} }
# Do not set pinMismatch for black boxes # If $uresult == -1 then these are black-box entries and
if {$result < 0} { # $pinsgood should not be set to the resulting value.
if {$result == -1 && [netgen::print queue] != {} && $forceMatch != 1} { if {$uresult > 0} {
# flatten pin mismatch, but not empty cells (-2) or top cell or set pinsgood $result
# cells prohibited from flattening.
set doFlatten 1
} }
} elseif {[netgen::print queue] == {} && $result == 0} {
set pinMismatch 1
} else {
# This assumes that proxy pins are added correctly. Previously,
# that was not trusted, and so an initial pin mismatch would
# always force subcells to be flattened.
set doFlatten 0
}
}
if {$doFlatten} {
netgen::log echo on netgen::log echo on
netgen::log put " Flattening non-matched subcircuits $endval\n" }
netgen::log echo off 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 0] $fnum1"
netgen::flatten class "[lindex $endval 1] $fnum2" 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
}
}
}
netgen::log echo off
if {$dolist == 1} { if {$dolist == 1} {
catch {lappend lvs_final $lvs_out} catch {lappend lvs_final $lvs_out}
set lvs_out {} set lvs_out {}
@ -701,23 +646,19 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
set endval [netgen::compare hierarchical] set endval [netgen::compare hierarchical]
} }
} }
netgen::log echo off
puts stdout "Result: " nonewline
netgen::log echo on netgen::log echo on
netgen::log put "\nFinal result: " if {$pinsgood == 0} {
if {$pinMismatch || $childMismatch} { netgen::log put "The top level cell failed pin matching.\n"
if {$childMismatch} {
netgen::log put "Subcell(s) failed matching.\n"
}
if {$pinMismatch} {
netgen::log put "Top level cell failed pin matching.\n"
}
} else { } else {
verify only verify only
} }
if {$properr != {}} { if {$properr != {}} {
netgen::log put "\nThe following cells had property errors:\n " [regsub -all { } $properr "\n "] "\n" netgen::log put "The following cells had property errors: $properr\n"
} }
if {$matcherr != {}} { if {$matcherr != {}} {
netgen::log put "\nThe following subcells failed to match:\n " [regsub -all { } $matcherr "\n "] "\n" netgen::log put "The following subcells failed to match: $matcherr\n"
} }
if {$dolog} { if {$dolog} {
netgen::log end netgen::log end
@ -769,19 +710,6 @@ set auto_noexec 1 ;# don't EVER call UNIX commands w/o "shell" in front
# Cross-Application section # Cross-Application section
#---------------------------------------------------------------------- #----------------------------------------------------------------------
# For use with open_pdks, set PDK_ROOT from the environment. If no
# such environment variable exists, check some common locations.
if {[catch {set PDK_ROOT $::env(PDK_ROOT)}]} {
if {[file isdir /usr/local/share/pdk] == 1} {
set PDK_ROOT /usr/local/share/pdk
} elseif {[file isdir /usr/share/pdk] == 1} {
set PDK_ROOT /usr/share/pdk
} elseif {[file isdir /foss/pdk] == 1} {
set PDK_ROOT /foss/pdk
}
}
# Setup IRSIM assuming that the Tcl version is installed. # Setup IRSIM assuming that the Tcl version is installed.
# We do not need to rename procedure irsim to NULL because it is # We do not need to rename procedure irsim to NULL because it is
# redefined in a script, which simply overwrites the original. # redefined in a script, which simply overwrites the original.

File diff suppressed because it is too large Load Diff

View File

@ -44,8 +44,6 @@ exec ${NETGEN_WISH:=wish} "$0" ${1+"$@"}
if {$tcl_version < 8.0} { if {$tcl_version < 8.0} {
return -code error "tkcon requires at least Tcl/Tk8" return -code error "tkcon requires at least Tcl/Tk8"
} else { } else {
# Prevent breaking on version 8.5.2
# package require -exact Tk $tcl_version
package require Tk $tcl_version package require Tk $tcl_version
} }
@ -61,6 +59,18 @@ foreach pkg [info loaded {}] {
} }
catch {unset pkg file name version} catch {unset pkg file name version}
# Tk 8.4 makes previously exposed stuff private.
# FIX: Update tkcon to not rely on the private Tk code.
#
if {![llength [info globals tkPriv]]} {
::tk::unsupported::ExposePrivateVariable tkPriv
}
foreach cmd {SetCursor UpDownLine Transpose ScrollPages} {
if {![llength [info commands tkText$cmd]]} {
::tk::unsupported::ExposePrivateCommand tkText$cmd
}
}
# Initialize the ::tkcon namespace # Initialize the ::tkcon namespace
# #
namespace eval ::tkcon { namespace eval ::tkcon {
@ -186,7 +196,7 @@ proc ::tkcon::Init {} {
tkcon_puts tkcon_gets observe observe_var unalias which what tkcon_puts tkcon_gets observe observe_var unalias which what
} }
version 2.3 version 2.3
RCS {RCS: @(#) $Id: tkcon.tcl,v 1.2 2008/04/18 16:28:13 tim Exp $} RCS {RCS: @(#) $Id: tkcon.tcl,v 1.2 2008/05/23 00:20:17 tim Exp $}
HEADURL {http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/tkcon/tkcon/tkcon.tcl?rev=HEAD} HEADURL {http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/tkcon/tkcon/tkcon.tcl?rev=HEAD}
docs "http://tkcon.sourceforge.net/" docs "http://tkcon.sourceforge.net/"
email {jeff@hobbs.org} email {jeff@hobbs.org}
@ -735,7 +745,7 @@ proc ::tkcon::EvalCmd {w cmd} {
$w tag bind $tag <Leave> \ $w tag bind $tag <Leave> \
[list $w tag configure $tag -underline 0] [list $w tag configure $tag -underline 0]
$w tag bind $tag <ButtonRelease-1> \ $w tag bind $tag <ButtonRelease-1> \
"if {!\[info exists ::tk::Priv(mouseMoved)\] || !\$::tk::Priv(mouseMoved)} \ "if {!\[info exists tkPriv(mouseMoved)\] || !\$tkPriv(mouseMoved)} \
{[list edit -attach [Attach] -type error -- $PRIV(errorInfo)]}" {[list edit -attach [Attach] -type error -- $PRIV(errorInfo)]}"
} else { } else {
$w insert output $res\n stderr $w insert output $res\n stderr
@ -2464,7 +2474,7 @@ proc ::tkcon::ErrorHighlight w {
$w tag configure $tag -foreground $COLOR(stdout) $w tag configure $tag -foreground $COLOR(stdout)
$w tag bind $tag <Enter> [list $w tag configure $tag -underline 1] $w tag bind $tag <Enter> [list $w tag configure $tag -underline 1]
$w tag bind $tag <Leave> [list $w tag configure $tag -underline 0] $w tag bind $tag <Leave> [list $w tag configure $tag -underline 0]
$w tag bind $tag <ButtonRelease-1> "if {!\$::tk::Priv(mouseMoved)} \ $w tag bind $tag <ButtonRelease-1> "if {!\$tkPriv(mouseMoved)} \
{[list edit -attach $app -type proc -find $what -- $cmd]}" {[list edit -attach $app -type proc -find $what -- $cmd]}"
} }
set info [string range $info $c1 end] set info [string range $info $c1 end]
@ -2493,7 +2503,7 @@ proc ::tkcon::ErrorHighlight w {
$w tag configure $tag -foreground $COLOR(proc) $w tag configure $tag -foreground $COLOR(proc)
$w tag bind $tag <Enter> [list $w tag configure $tag -underline 1] $w tag bind $tag <Enter> [list $w tag configure $tag -underline 1]
$w tag bind $tag <Leave> [list $w tag configure $tag -underline 0] $w tag bind $tag <Leave> [list $w tag configure $tag -underline 0]
$w tag bind $tag <ButtonRelease-1> "if {!\$::tk::Priv(mouseMoved)} \ $w tag bind $tag <ButtonRelease-1> "if {!\$tkPriv(mouseMoved)} \
{[list edit -attach $app -type proc -- $cmd]}" {[list edit -attach $app -type proc -- $cmd]}"
} }
} }
@ -2542,8 +2552,8 @@ proc tkcon {cmd args} {
## 'congets' a replacement for [gets stdin] ## 'congets' a replacement for [gets stdin]
# Use the 'gets' alias of 'tkcon_gets' command instead of # Use the 'gets' alias of 'tkcon_gets' command instead of
# calling the *get* methods directly for best compatability # calling the *get* methods directly for best compatability
if {[llength $args] > 1} { if {[llength $args]} {
return -code error "wrong # args: must be \"tkcon congets [pfix]\"" return -code error "wrong # args: must be \"tkcon congets\""
} }
tkcon show tkcon show
set old [bind TkConsole <<TkCon_Eval>>] set old [bind TkConsole <<TkCon_Eval>>]
@ -2551,12 +2561,7 @@ proc tkcon {cmd args} {
set w $::tkcon::PRIV(console) set w $::tkcon::PRIV(console)
# Make sure to move the limit to get the right data # Make sure to move the limit to get the right data
$w mark set insert end $w mark set insert end
if {[llength $args]} {
$w mark set limit insert $w mark set limit insert
$w insert end $args
} else {
$w mark set limit insert
}
$w see end $w see end
vwait ::tkcon::PRIV(wait) vwait ::tkcon::PRIV(wait)
set line [::tkcon::CmdGet $w] set line [::tkcon::CmdGet $w]
@ -2793,19 +2798,13 @@ proc tkcon_puts args {
foreach {arg1 arg2 arg3} $args { break } foreach {arg1 arg2 arg3} $args { break }
if {$len == 1} { if {$len == 1} {
set sarg $arg1 tkcon console insert output "$arg1\n" stdout
set nl 1
set farg stdout
} elseif {$len == 2} { } elseif {$len == 2} {
if {![string compare $arg1 -nonewline]} { if {![string compare $arg1 -nonewline]} {
set sarg $arg2 tkcon console insert output $arg2 stdout
set farg stdout
set nl 0
} elseif {![string compare $arg1 stdout] \ } elseif {![string compare $arg1 stdout] \
|| ![string compare $arg1 stderr]} { || ![string compare $arg1 stderr]} {
set sarg $arg2 tkcon console insert output "$arg2\n" $arg1
set farg $arg1
set nl 1
} else { } else {
set len 0 set len 0
} }
@ -2813,15 +2812,11 @@ proc tkcon_puts args {
if {![string compare $arg1 -nonewline] \ if {![string compare $arg1 -nonewline] \
&& (![string compare $arg2 stdout] \ && (![string compare $arg2 stdout] \
|| ![string compare $arg2 stderr])} { || ![string compare $arg2 stderr])} {
set sarg $arg3 tkcon console insert output $arg3 $arg2
set farg $arg2
set nl 0
} elseif {(![string compare $arg1 stdout] \ } elseif {(![string compare $arg1 stdout] \
|| ![string compare $arg1 stderr]) \ || ![string compare $arg1 stderr]) \
&& ![string compare $arg3 nonewline]} { && ![string compare $arg3 nonewline]} {
set sarg $arg2 tkcon console insert output $arg2 $arg1
set farg $arg1
set nl 0
} else { } else {
set len 0 set len 0
} }
@ -2831,42 +2826,7 @@ proc tkcon_puts args {
## $len == 0 means it wasn't handled by tkcon above. ## $len == 0 means it wasn't handled by tkcon above.
## ##
if {$len == 0} {
if {$len != 0} {
## "poor man's" \r substitution---erase everything on the output
## line and print from character after the \r
set rpt [string last \r $sarg]
if {$rpt >= 0} {
tkcon console delete "insert linestart" "insert lineend"
set sarg [string range $sarg [expr {$rpt + 1}] end]
}
set bpt [string first \b $sarg]
if {$bpt >= 0} {
set narg [string range $sarg [expr {$bpt + 1}] end]
set sarg [string range $sarg 0 [expr {$bpt - 1}]]
set nl 0
}
if {$nl == 0} {
tkcon console insert output $sarg $farg
} else {
tkcon console insert output "$sarg\n" $farg
}
if {$bpt >= 0} {
tkcon console delete "insert -1 char" insert
if {$nl == 0} {
tkcon_puts $farg $narg nonewline
} else {
tkcon_puts $farg $narg
}
}
} else {
global errorCode errorInfo global errorCode errorInfo
if {[catch "tkcon_tcl_puts $args" msg]} { if {[catch "tkcon_tcl_puts $args" msg]} {
regsub tkcon_tcl_puts $msg puts msg regsub tkcon_tcl_puts $msg puts msg
@ -4146,7 +4106,7 @@ proc ::tkcon::Bindings {} {
global tcl_platform tk_version global tcl_platform tk_version
#----------------------------------------------------------------------- #-----------------------------------------------------------------------
# Elements of ::tk::Priv that are used in this file: # Elements of tkPriv that are used in this file:
# #
# char - Character position on the line; kept in order # char - Character position on the line; kept in order
# to allow moving up or down past short lines while # to allow moving up or down past short lines while
@ -4174,9 +4134,6 @@ proc ::tkcon::Bindings {} {
foreach ev [bind Text] { bind TkConsole $ev [bind Text $ev] } foreach ev [bind Text] { bind TkConsole $ev [bind Text $ev] }
## We really didn't want the newline insertion ## We really didn't want the newline insertion
bind TkConsole <Control-Key-o> {} bind TkConsole <Control-Key-o> {}
## in 8.6b3, the virtual events <<NextLine>> and <<PrevLine>>
# mess up our history feature
bind TkConsole <<NextLine>> {} bind TkConsole <<NextLine>> {}
bind TkConsole <<PrevLine>> {} bind TkConsole <<PrevLine>> {}
@ -4385,9 +4342,9 @@ proc ::tkcon::Bindings {} {
bind TkConsole <Control-a> { bind TkConsole <Control-a> {
if {[%W compare {limit linestart} == {insert linestart}]} { if {[%W compare {limit linestart} == {insert linestart}]} {
::tk::TextSetCursor %W limit tkTextSetCursor %W limit
} else { } else {
::tk::TextSetCursor %W {insert linestart} tkTextSetCursor %W {insert linestart}
} }
} }
bind TkConsole <Key-Home> [bind TkConsole <Control-a>] bind TkConsole <Key-Home> [bind TkConsole <Control-a>]
@ -4411,14 +4368,14 @@ proc ::tkcon::Bindings {} {
} }
bind TkConsole <<TkCon_Previous>> { bind TkConsole <<TkCon_Previous>> {
if {[%W compare {insert linestart} != {limit linestart}]} { if {[%W compare {insert linestart} != {limit linestart}]} {
::tk::TextSetCursor %W [::tk::TextUpDownLine %W -1] tkTextSetCursor %W [tkTextUpDownLine %W -1]
} else { } else {
::tkcon::Event -1 ::tkcon::Event -1
} }
} }
bind TkConsole <<TkCon_Next>> { bind TkConsole <<TkCon_Next>> {
if {[%W compare {insert linestart} != {end-1c linestart}]} { if {[%W compare {insert linestart} != {end-1c linestart}]} {
::tk::TextSetCursor %W [::tk::TextUpDownLine %W 1] tkTextSetCursor %W [tkTextUpDownLine %W 1]
} else { } else {
::tkcon::Event 1 ::tkcon::Event 1
} }
@ -4433,7 +4390,7 @@ proc ::tkcon::Bindings {} {
} }
bind TkConsole <<TkCon_Transpose>> { bind TkConsole <<TkCon_Transpose>> {
## Transpose current and previous chars ## Transpose current and previous chars
if {[%W compare insert > "limit+1c"]} { ::tk::TextTranspose %W } if {[%W compare insert > "limit+1c"]} { tkTextTranspose %W }
} }
bind TkConsole <<TkCon_ClearLine>> { bind TkConsole <<TkCon_ClearLine>> {
## Clear command line (Unix shell staple) ## Clear command line (Unix shell staple)
@ -4451,10 +4408,10 @@ proc ::tkcon::Bindings {} {
::tkcon::Insert %W $::tkcon::PRIV(tmp) ::tkcon::Insert %W $::tkcon::PRIV(tmp)
%W see end %W see end
} }
catch {bind TkConsole <Key-Page_Up> { ::tk::TextScrollPages %W -1 }} catch {bind TkConsole <Key-Page_Up> { tkTextScrollPages %W -1 }}
catch {bind TkConsole <Key-Prior> { ::tk::TextScrollPages %W -1 }} catch {bind TkConsole <Key-Prior> { tkTextScrollPages %W -1 }}
catch {bind TkConsole <Key-Page_Down> { ::tk::TextScrollPages %W 1 }} catch {bind TkConsole <Key-Page_Down> { tkTextScrollPages %W 1 }}
catch {bind TkConsole <Key-Next> { ::tk::TextScrollPages %W 1 }} catch {bind TkConsole <Key-Next> { tkTextScrollPages %W 1 }}
bind TkConsole <$PRIV(meta)-d> { bind TkConsole <$PRIV(meta)-d> {
if {[%W compare insert >= limit]} { if {[%W compare insert >= limit]} {
%W delete insert {insert wordend} %W delete insert {insert wordend}
@ -4472,7 +4429,7 @@ proc ::tkcon::Bindings {} {
} }
bind TkConsole <ButtonRelease-2> { bind TkConsole <ButtonRelease-2> {
if { if {
(!$::tk::Priv(mouseMoved) || $tk_strictMotif) && (!$tkPriv(mouseMoved) || $tk_strictMotif) &&
![catch {::tkcon::GetSelection %W} ::tkcon::PRIV(tmp)] ![catch {::tkcon::GetSelection %W} ::tkcon::PRIV(tmp)]
} { } {
if {[%W compare @%x,%y < limit]} { if {[%W compare @%x,%y < limit]} {