Merge branch 'pre-master' into bt_dev

This commit is contained in:
Brian Taylor 2023-06-04 08:03:24 -07:00
commit 56272eb68c
72 changed files with 2021 additions and 874 deletions

73
INSTALL
View File

@ -18,7 +18,7 @@ Table of contents
1.5.1 Most useful options 1.5.1 Most useful options
1.5.2 Options Specific to Enable Ngspice as a shared library 1.5.2 Options Specific to Enable Ngspice as a shared library
1.5.3 Options Useful for Debugging Ngspice 1.5.3 Options Useful for Debugging Ngspice
1.6 Installation on Red Hat, Oracle or Centos Linux 1.6 Installation on Red Hat, Oracle or CentOS Linux
2 Compilers and Options 2 Compilers and Options
3 Compiling For Multiple Architectures 3 Compiling For Multiple Architectures
4 Installation Names 4 Installation Names
@ -67,32 +67,40 @@ This file describes the procedures to install ngspice from sources.
If libfftw is detected on your system, it will be used instead of the If libfftw is detected on your system, it will be used instead of the
internal fft algorithms. internal fft algorithms.
If you want to compile the source from the git repository you need If you want to compile the source from the git repository, or if you want to
additional software: autoconf, automake, libtool. use the compile script ./compile_linux.sh, you will need additional software:
autoconf, automake, libtool.
The following software may be needed when enabling additional features: The following software may be needed when enabling additional features:
editline, tcl/tk, adms. editline, tcl/tk.
Please have a look at the actual ngspice manual, downloadable at Please have a look at the current ngspice manual, downloadable at
http://ngspice.sourceforge.net/docs.html, which gives you much more http://ngspice.sourceforge.net/docs.html, which gives you much more
information on ngspice and its usage. information on ngspice and its usage.
For compiling ngspice as a shared library, see section 1.4. For compiling ngspice as a shared library, see section 1.4.
1.2 Install from tarball (e.g. ngspice-36.tar.gz) 1.2 Install from tarball (e.g. ngspice-40.tar.gz)
This covers installation from a release distribution (for example This covers installation from a release distribution (for example
ngspice-36.tar.gz, the so called tar ball). ngspice-40.tar.gz, the so called tar ball).
After downloading the tar ball to a local directory unpack it using: After downloading the tar ball to a local directory, unpack it by command:
$ tar -zxvf ngspice-36.tar.gz $ tar -zxvf ngspice-40.tar.gz
Now change directories in to the top-level source directory (where this Now change directories in to the top-level source directory (where this
INSTALL file can be found). INSTALL file can be found).
You should be able to do: The most comfortable way to compile ngspice is running the compile script
compile_linux.sh within the terminal window by ./compile_linux.sh. Admin
rights are required to allow the installation included in the script.
CentOS users may need to add -std=c99 to the CFLAGS in the ../configure
statement.
If you want to compile ngspice manually, you should be able to do:
$ mkdir release $ mkdir release
$ cd release $ cd release
@ -105,18 +113,15 @@ This file describes the procedures to install ngspice from sources.
A simple ../configure might be sufficient for a basic ngspice, but the preferred A simple ../configure might be sufficient for a basic ngspice, but the preferred
arguments to ../configure are arguments to ../configure are
--with-x --with-readline=yes and --disable-debug --with-x --with-readline=yes and --disable-debug
providing you with a comfortably working ngspice (see section 1.4 for details). providing you with a comfortably working ngspice.
See the section titled 'Advanced Install' for instructions about additional arguments See the section 1.5 titled 'Advanced Install' for instructions about additional arguments
that can be passed to ../configure to customise the build and installation. that can be passed to ../configure to customise the build and installation.
Do not use the script ./autogen.sh, because it is not required for
compiling and installing ngspice from the tarball.
A fully featured ngspice on LINUX may be obtained with the following commands: A fully featured ngspice on LINUX may be obtained with the following commands:
$ mkdir release $ mkdir release
$ cd release $ cd release
$ ../configure --with-x --enable-xspice --disable-debug --enable-cider --with-readline=yes --enable-openmp $ ../configure --with-x --enable-xspice --disable-debug --enable-cider --with-readline=yes --enable-osdi --enable-openmp
$ make 2>&1 | tee make.log $ make 2>&1 | tee make.log
$ sudo make install $ sudo make install
@ -141,6 +146,12 @@ This file describes the procedures to install ngspice from sources.
The project uses the GNU build process. The compile output should go into a separate The project uses the GNU build process. The compile output should go into a separate
directory, so to e.g. maintain separate debug and release versions. directory, so to e.g. maintain separate debug and release versions.
The most comfortable way to compile ngspice is running the compile script
compile_linux.sh within the terminal window by ./compile_linux.sh. Admin
rights are required to allow the installation included in the script.
If you want to copile ngspice manually, you may run
$ ./autogen.sh $ ./autogen.sh
$ mkdir debug $ mkdir debug
$ cd debug $ cd debug
@ -148,7 +159,7 @@ This file describes the procedures to install ngspice from sources.
$ make $ make
$ sudo make install $ sudo make install
See the section titled 'Advanced Install' for instructions about arguments See the section 1.5 titled 'Advanced Install' for instructions about arguments
that can be passed to ./configure to customize the build and installation. that can be passed to ./configure to customize the build and installation.
Preferred arguments to ./configure to obtain a comfortably working ngspice may be Preferred arguments to ./configure to obtain a comfortably working ngspice may be
@ -156,21 +167,21 @@ This file describes the procedures to install ngspice from sources.
executable). executable).
A fully featured ngspice on LINUX may be obtained with the following commands: A fully featured ngspice on LINUX may be obtained with the following commands:
$ ./autogen.sh --adms $ ./autogen.sh
$ mkdir release $ mkdir release
$ cd release $ cd release
$ ../configure --with-x --enable-xspice --disable-debug --enable-cider --with-readline=yes --enable-openmp --enable-adms $ ../configure --with-x --enable-xspice --disable-debug --enable-cider --with-readline=yes --enable-openmp --enable-osdi
$ make 2>&1 | tee make.log $ make 2>&1 | tee make.log
$ sudo make install $ sudo make install
A bash script compile_linux.sh is available including all useful options, The bash script compile_linux.sh includes all the useful options,
compiling and installation procedures. compiling and installation procedures.
1.4 ngspice as a shared library 1.4 ngspice as a shared library
The relevant configure options for the ngspice shared library are: The relevant configure options for the ngspice shared library are:
$ --with-ngshared --enable-xspice --disable-debug --enable-cider --enable-openmp $ --with-ngshared --enable-xspice --disable-debug --enable-cider --enable-osdi --enable-openmp
Typically the two aliases libngspice.so, libngspice.so.0 and the compiled Typically the two aliases libngspice.so, libngspice.so.0 and the compiled
library libngspice.so.0.0.1 are made. The install locations depend on library libngspice.so.0.0.1 are made. The install locations depend on
@ -312,13 +323,17 @@ This file describes the procedures to install ngspice from sources.
problem yourself, then the development team will love to hear from you. problem yourself, then the development team will love to hear from you.
1.6 Installation on Red Hat, Oracle or Centos 1.6 Installation on Red Hat, Oracle or CentOS
These OSs, widely distributed among commercial users, require some These OSs, widely distributed among commercial users, but offering
only an old gcc compiler, e.g. version 4.8, will require some
special considerations. There is an extra document, "NGSPICE on Red special considerations. There is an extra document, "NGSPICE on Red
Hat Like Distributions.pdf", provided by Justin Fisher, available with Hat Like Distributions.pdf", provided by Justin Fisher, available with
the ngspice distribution. the ngspice distribution.
CentOS users may need to add -std=c99 to the CFLAGS in their ../configure
statement.
2 Compilers and Options 2 Compilers and Options
===================== =====================
@ -502,10 +517,10 @@ This file describes the procedures to install ngspice from sources.
--disable-debug (-O2 optimization, no debug information) --disable-debug (-O2 optimization, no debug information)
A fully featured ngspice on Windows may be obtained with the following commands: A fully featured ngspice on Windows may be obtained with the following commands:
$ ./autogen.sh --adms $ ./autogen.sh
$ mkdir release $ mkdir release
$ cd release $ cd release
$ ../configure --with-wingui --enable-cider --disable-debug --enable-openmp --enable-xspice --enable-adms $ ../configure --with-wingui --enable-cider --disable-debug --enable-openmp --enable-xspice --enable-osdi
$ make install $ make install
However, to compile code extracted from the git repository the procedure is However, to compile code extracted from the git repository the procedure is
@ -523,7 +538,7 @@ This file describes the procedures to install ngspice from sources.
Go to directory ngspice Go to directory ngspice
$ cd /d/Spice/ngspice $ cd /d/Spice/ngspice
Start compiling, e.g. by calling Start compiling, e.g. by calling
$ ./autogen.sh --adms $ ./autogen.sh
$ ./compile_min.sh $ ./compile_min.sh
Update the ngspice files: Update the ngspice files:
@ -680,7 +695,7 @@ This file describes the procedures to install ngspice from sources.
You then will not have any graphics interface. In CYGWIN you may add --with-x You then will not have any graphics interface. In CYGWIN you may add --with-x
for the X11 graphics (not available in mingw). A typical configure command for the X11 graphics (not available in mingw). A typical configure command
may look like may look like
./configure --enable-adms --enable-xspice --enable-cider --enable-openmp ./configure --enable-osdi --enable-xspice --enable-cider --enable-openmp
--disable-debug CFLAGS=-m64 LDFLAGS=-m64 prefix=C:/Spice64 --disable-debug CFLAGS=-m64 LDFLAGS=-m64 prefix=C:/Spice64
@ -708,7 +723,9 @@ cross-compile-shared.sh.
3. Execute this command: 3. Execute this command:
sudo port install autoconf automake libtool bison flex ncurses sudo port install autoconf automake libtool bison flex ncurses
readline fontconfig freetype libomp xorg-libXaw readline fontconfig freetype libomp xorg-libXaw
4. Use one of the scripts provided: compile_macos.sh or build-for-mac-os.sh 4. Use one of the scripts provided: compile_macos_clang.sh or compile_macos_gcc.sh
gcc may be installed from Homebre at https://formulae.brew.sh/formula/gcc, with the
advantage that it supports OpenMP.
5. Or run the commands manually: Configure NGSPICE invoking "./configure". 5. Or run the commands manually: Configure NGSPICE invoking "./configure".
A complete set of features is: A complete set of features is:
./configure --enable-cider --enable-xspice --enable-openmp --enable-pss --enable-debug=no ./configure --enable-cider --enable-xspice --enable-openmp --enable-pss --enable-debug=no

View File

@ -9,10 +9,13 @@
# for details please see the ngspice manual, chapt. 32.1. # for details please see the ngspice manual, chapt. 32.1.
# Declare 'compile_linux.sh' executable and start compiling with # Declare 'compile_linux.sh' executable and start compiling with
# './compile_linux.sh' or './compile_linux.sh d' from the ngspice directory. # './compile_linux.sh' or './compile_linux.sh d' from the ngspice directory.
# CentOS users may need to add -std=c99 to the CFLAGS in the ../configure
# statement.
# Options: # Options:
# --adms and --enable-adms will install extra HICUM, EKV and MEXTRAM models via the # --enable-osdi will enable the OSDI interface, which, in conjuction with the
# adms interface. You need to download and install the *.va files via ng-adms-va.tgz # external OpenVAF Verilig-A compiler, will allow access to advanced compact
# Please see the ngspice manual, chapt. 13, for more info on adms. # device models writen in Verilog-A.
# Please see the ngspice manual, chapt. 13, for more info on using OSDI/OpenVAF.
# CIDER, XSPICE, and OpenMP may be selected at will. # CIDER, XSPICE, and OpenMP may be selected at will.
# --disable-debug will give O2 optimization (versus O0 for debug) and removes all debugging info. # --disable-debug will give O2 optimization (versus O0 for debug) and removes all debugging info.
@ -39,26 +42,18 @@ fi
./autogen.sh ./autogen.sh
if [ $? -ne 0 ]; then echo "./autogen.sh failed"; exit 1 ; fi if [ $? -ne 0 ]; then echo "./autogen.sh failed"; exit 1 ; fi
# Alternatively, if compiling sources from git, and want to add adms created devices,
# you may need to uncomment the following two lines (and don't forget to add adms option
# to the ../configure statement):
#./autogen.sh --adms
#if [ $? -ne 0 ]; then echo "./autogen.sh failed"; exit 1 ; fi
echo echo
if test "$1" = "d"; then if test "$1" = "d"; then
cd debug cd debug
if [ $? -ne 0 ]; then echo "cd debug failed"; exit 1 ; fi if [ $? -ne 0 ]; then echo "cd debug failed"; exit 1 ; fi
echo "configuring for 64 bit debug" echo "configuring for 64 bit debug"
echo echo
# You may add --enable-adms to the following command for adding adms generated devices
../configure --with-x --enable-xspice --enable-cider --enable-predictor --enable-osdi --with-readline=yes --enable-openmp CFLAGS="-g -m64 -O0 -Wall -Wno-unused-but-set-variable" LDFLAGS="-m64 -g" ../configure --with-x --enable-xspice --enable-cider --enable-predictor --enable-osdi --with-readline=yes --enable-openmp CFLAGS="-g -m64 -O0 -Wall -Wno-unused-but-set-variable" LDFLAGS="-m64 -g"
else else
cd release cd release
if [ $? -ne 0 ]; then echo "cd release failed"; exit 1 ; fi if [ $? -ne 0 ]; then echo "cd release failed"; exit 1 ; fi
echo "configuring for 64 bit release" echo "configuring for 64 bit release"
echo echo
# You may add --enable-adms to the following command for adding adms generated devices
../configure --with-x --enable-xspice --enable-cider --enable-predictor --enable-osdi --with-readline=yes --enable-openmp --disable-debug CFLAGS="-m64 -O2" LDFLAGS="-m64 -s" ../configure --with-x --enable-xspice --enable-cider --enable-predictor --enable-osdi --with-readline=yes --enable-openmp --disable-debug CFLAGS="-m64 -O2" LDFLAGS="-m64 -s"
fi fi
if [ $? -ne 0 ]; then echo "../configure failed"; exit 1 ; fi if [ $? -ne 0 ]; then echo "../configure failed"; exit 1 ; fi

View File

@ -1,6 +1,6 @@
MOSdriver -- lossy line LTRA model -- C load MOSdriver -- lossy line LTRA model -- C load
m5 0 168 2 0 mn0p9 w = 18.0u l=0.9u m5 2 168 0 0 mn0p9 w = 18.0u l=0.9u
m6 1 168 2 1 mp1p0 w = 36.0u l=1.0u m6 2 168 1 1 mp1p0 w = 36.0u l=1.0u
CN2 2 0 0.025398e-12 CN2 2 0 0.025398e-12
CN3 3 0 0.007398e-12 CN3 3 0 0.007398e-12
o1 2 0 3 0 lline o1 2 0 3 0 lline
@ -8,12 +8,13 @@ vdd 1 0 dc 5.0
VS 168 0 PULSE (0 5 15.9NS 0.2NS 0.2NS 15.8NS 32NS ) VS 168 0 PULSE (0 5 15.9NS 0.2NS 0.2NS 15.8NS 32NS )
.control .control
TRAN 0.2N 47N 0 0.1N TRAN 0.2N 47N 0 0.1N
rusage
plot v(2) v(3) ylimit -0.5 5 plot v(2) v(3) ylimit -0.5 5
.endc .endc
.MODEL mn0p9 NMOS VTO=0.8 KP=48U GAMMA=0.30 PHI=0.55 .MODEL mn0p9 NMOS VTO=0.8 KP=48U GAMMA=0.30 PHI=0.55
+LAMBDA=0.00 CGSO=0 CGDO=0 CJ=0 CJSW=0 TOX=18000N LD=0.0U +LAMBDA=0.00 CGSO=0 CGDO=0 CJ=0 CJSW=0 TOX=18N LD=0.0U
.MODEL mp1p0 PMOS VTO=-0.8 KP=21U GAMMA=0.45 PHI=0.61 .MODEL mp1p0 PMOS VTO=-0.8 KP=21U GAMMA=0.45 PHI=0.61
+LAMBDA=0.00 CGSO=0 CGDO=0 CJ=0 CJSW=0 TOX=18000N LD=0.0U +LAMBDA=0.00 CGSO=0 CGDO=0 CJ=0 CJSW=0 TOX=18N LD=0.0U
.model lline ltra rel=1 r=12.45 g=0 l=8.972e-9 c=0.468e-12 .model lline ltra rel=1 r=12.45 g=0 l=8.972e-9 c=0.468e-12
+len=16 steplimit compactrel=1.0e-3 compactabs=1.0e-14 +len=16 steplimit compactrel=1.0e-3 compactabs=1.0e-14
.end .end

View File

@ -135,7 +135,9 @@ VS1 2 0 PULSE (0 5 15.9Ns 0.2Ns 0.2Ns 15.8Ns 32Ns)
VS2 4 0 PULSE (0 5 15.9Ns 0.2Ns 0.2Ns 15.8Ns 32Ns) VS2 4 0 PULSE (0 5 15.9Ns 0.2Ns 0.2Ns 15.8Ns 32Ns)
.control .control
option noinit
TRAN 0.1N 47.9N TRAN 0.1N 47.9N
rusage
plot v(5) v(6) v(7) v(8) v(9) v(10) v(11) v(12) plot v(5) v(6) v(7) v(8) v(9) v(10) v(11) v(12)
.endc .endc
* *

View File

@ -1,8 +1,8 @@
MOSdriver -- 2 lossy lines LTRA model -- C load MOSdriver -- 2 lossy lines LTRA model -- C load
m5 0 168 2 0 mn0p9 w = 18.0u l=0.9u m5 2 168 0 0 mn0p9 w = 18.0u l=0.9u
m6 1 168 2 1 mp1p0 w = 36.0u l=1.0u m6 2 168 1 1 mp1p0 w = 36.0u l=1.0u
m1 0 3 4 0 mn0p9 w = 18.0u l=0.9u m1 4 3 0 0 mn0p9 w = 18.0u l=0.9u
m2 1 3 4 1 mp1p0 w = 36.0u l=1.0u m2 4 3 1 1 mp1p0 w = 36.0u l=1.0u
CN2 2 0 0.025398e-12 CN2 2 0 0.025398e-12
CN3 3 0 0.007398e-12 CN3 3 0 0.007398e-12
CN4 4 0 0.025398e-12 CN4 4 0 0.025398e-12
@ -13,7 +13,9 @@ vdd 1 0 dc 5.0
VS 168 0 PULSE (0 5 15.9NS 0.2NS 0.2NS 15.8NS 32NS ) VS 168 0 PULSE (0 5 15.9NS 0.2NS 0.2NS 15.8NS 32NS )
.control .control
TRAN 0.2N 47N 0 0.1N TRAN 0.2N 47N 0 0.1N
plot v(2) v(3) v(4) v(5) rusage
set xbrushwidth=3
plot v(168) v(2) v(3) v(4) v(5)
.endc .endc
.MODEL mn0p9 NMOS VTO=0.8 KP=48U GAMMA=0.30 PHI=0.55 .MODEL mn0p9 NMOS VTO=0.8 KP=48U GAMMA=0.30 PHI=0.55
+LAMBDA=0.00 CGSO=0 CGDO=0 CJ=0 CJSW=0 TOX=18000N LD=0.0U +LAMBDA=0.00 CGSO=0 CGDO=0 CJ=0 CJSW=0 TOX=18000N LD=0.0U

View File

@ -84,6 +84,9 @@ VS2 268 0 PULSE (0 5 15.9N 0.2N 0.2N 15.8N 60N)
* *
.control .control
TRAN 0.2N 47.9NS TRAN 0.2N 47.9NS
rusage
set color0=white
set xbrushwidth=3
PLOT v(648) v(651) v(751) PLOT v(648) v(651) v(751)
.endc .endc
* *

View File

@ -53,6 +53,9 @@ x3 3 4 10 dioload
+reltol=1e-3 abstol=1e-14 +reltol=1e-3 abstol=1e-14
.control .control
tran 0.1ns 60ns tran 0.1ns 60ns
rusage
set color0=white
set xbrushwidth=3
plot v(1) v(2) v(3) plot v(1) v(2) v(3)
.endc .endc

View File

@ -60,6 +60,9 @@ x1 2 3 xonecm
tran 0.001ns 10ns 0 0.1ns tran 0.001ns 10ns 0 0.1ns
* onecm10 * onecm10
*tran 0.001ns 10ns 0 0.01ns *tran 0.001ns 10ns 0 0.01ns
rusage
set color0=white
set xbrushwidth=3
plot v(1) v(2) v(3) plot v(1) v(2) v(3)
.endc .endc

View File

@ -75,6 +75,9 @@ rt2 5 0 50
.options acct reltol=1e-3 abstol=1e-12 .options acct reltol=1e-3 abstol=1e-12
.control .control
tran 0.1ns 60ns tran 0.1ns 60ns
rusage
*set color0=white
set xbrushwidth=3
plot v(2) v(4) v(5) plot v(2) v(4) v(5)
.endc .endc

View File

@ -106,7 +106,11 @@ x1 2 3 4 5 6 7 8 9 test
VS1 1 0 PWL(15.9NS 0.0 16.1Ns 5.0 31.9Ns 5.0 32.1Ns 0.0) VS1 1 0 PWL(15.9NS 0.0 16.1Ns 5.0 31.9Ns 5.0 32.1Ns 0.0)
.control .control
TRAN 0.2NS 50NS option noinit
TRAN 0.2NS 50NS
rusage
*set color0=white
set xbrushwidth=3
plot v(1) v(2) v(6) v(7) v(8) v(9) plot v(1) v(2) v(6) v(7) v(8) v(9)
.endc .endc
* *

View File

@ -1,6 +1,7 @@
* ISCAS85 benchmark circuit SPICE netlist * ISCAS85 benchmark circuit SPICE netlist, PSP103
* generated by spicegen.pl 1.0 * generated by spicegen.pl 1.0
* by Jingye Xu @ VLSI group, Dept of ECE, UIC * by Jingye Xu @ VLSI group, Dept of ECE, UIC
* Modified for PSP103 model via OSDI/OpenVAF by Holger Vogt
* Path to the models * Path to the models
.include Modelcards/psp103_nmos-2.mod .include Modelcards/psp103_nmos-2.mod

View File

@ -86,6 +86,7 @@
if $?batchmode if $?batchmode
else else
run run
rusage time
plot v(16) v(13) v(17) v(1)+6 v(4)+6 v(3)+6 plot v(16) v(13) v(17) v(1)+6 v(4)+6 v(3)+6
end end
.endc .endc

185
examples/sp/filter.lib Normal file
View File

@ -0,0 +1,185 @@
.SUBCKT filter 1 2 3
*2-port S-parameter file
*Title: * simple test for xfer code model: comparison
*Generated by ngspice at Tue May 23 06:49:31 2023
* Hz S RI R
* Z1=50.000000 Z2=50.000000
R1N 1 10 -5.000000e+01
R1P 10 11 1.000000e+02
R2N 2 20 -5.000000e+01
R2P 20 21 1.000000e+02
*S11 FREQ DB PHASE
E11 11 12 FREQ {V(10,3)}= DB
+( 1.000000e+07Hz, 3.654967e-07, -7.619541e+01)
+( 1.487179e+07Hz, 1.964030e-07, -1.157703e+02)
+( 1.974359e+07Hz, -1.084219e-07, -1.569277e+02)
+( 2.461538e+07Hz, -5.321598e-06, -1.985756e+02)
+( 2.948718e+07Hz, -1.265047e-05, -2.395114e+02)
+( 3.435897e+07Hz, -2.727603e-05, -2.792878e+02)
+( 3.923077e+07Hz, -6.620604e-05, -3.184596e+02)
+( 4.410256e+07Hz, -1.624082e-04, -3.582070e+02)
+( 4.897436e+07Hz, -3.755273e-04, -3.996839e+02)
+( 5.384615e+07Hz, -7.725656e-04, -4.432805e+02)
+( 5.871795e+07Hz, -1.320643e-03, -4.881884e+02)
+( 6.358974e+07Hz, -1.599290e-03, -5.330311e+02)
+( 6.846154e+07Hz, -4.631092e-04, -5.776220e+02)
+( 7.333333e+07Hz, -1.388239e-02, -6.262936e+02)
+( 7.820513e+07Hz, -1.245578e+01, -8.015034e+02)
+( 8.307692e+07Hz, -1.142468e+00, -6.888087e+02)
+( 8.794872e+07Hz, -1.292324e+00, -7.542062e+02)
+( 9.282051e+07Hz, -2.163078e+00, -8.283885e+02)
+( 9.769231e+07Hz, -3.764829e+00, -9.213357e+02)
+( 1.025641e+08Hz, -4.165673e+00, -1.041098e+03)
+( 1.074359e+08Hz, -2.143343e+00, -1.139856e+03)
+( 1.123077e+08Hz, -1.084156e+00, -1.201868e+03)
+( 1.171795e+08Hz, -7.962690e-01, -1.249480e+03)
+( 1.220513e+08Hz, -1.204024e+00, -1.318959e+03)
+( 1.269231e+08Hz, -4.148462e-01, -1.169292e+03)
+( 1.317949e+08Hz, -1.026085e-02, -1.240330e+03)
+( 1.366667e+08Hz, -1.360661e-04, -1.265793e+03)
+( 1.415385e+08Hz, -2.410965e-03, -1.281511e+03)
+( 1.464103e+08Hz, -3.787891e-03, -1.293132e+03)
+( 1.512821e+08Hz, -3.602264e-03, -1.302433e+03)
+( 1.561538e+08Hz, -2.547410e-03, -1.310211e+03)
+( 1.610256e+08Hz, -1.530232e-03, -1.316893e+03)
+( 1.658974e+08Hz, -8.667728e-04, -1.322741e+03)
+( 1.707692e+08Hz, -4.905888e-04, -1.327928e+03)
+( 1.756410e+08Hz, -2.840626e-04, -1.332578e+03)
+( 1.805128e+08Hz, -1.688713e-04, -1.336783e+03)
+( 1.853846e+08Hz, -1.041703e-04, -1.340612e+03)
+( 1.902564e+08Hz, -6.546576e-05, -1.344121e+03)
+( 1.951282e+08Hz, -4.228835e-05, -1.347353e+03)
+( 2.000000e+08Hz, -2.867354e-05, -1.350343e+03)
*S12 FREQ DB PHASE
E12 12 3 FREQ {V(20,3)}= DB
+( 1.000000e+07Hz, -1.248758e+02, -1.373971e+02)
+( 1.487179e+07Hz, -9.831399e+01, -1.647281e+02)
+( 1.974359e+07Hz, -7.673566e+01, -2.026127e+02)
+( 2.461538e+07Hz, -5.898226e+01, -2.906518e+02)
+( 2.948718e+07Hz, -5.542440e+01, -3.666485e+02)
+( 3.435897e+07Hz, -5.204910e+01, -4.009490e+02)
+( 3.923077e+07Hz, -4.814977e+01, -4.271950e+02)
+( 4.410256e+07Hz, -4.426072e+01, -4.514100e+02)
+( 4.897436e+07Hz, -4.063346e+01, -4.755494e+02)
+( 5.384615e+07Hz, -3.749934e+01, -5.003303e+02)
+( 5.871795e+07Hz, -3.516924e+01, -5.256223e+02)
+( 6.358974e+07Hz, -3.433887e+01, -5.509590e+02)
+( 6.846154e+07Hz, -3.971774e+01, -5.765977e+02)
+( 7.333333e+07Hz, -2.496027e+01, -4.260244e+02)
+( 7.820513e+07Hz, -2.540060e-01, -5.317362e+02)
+( 8.307692e+07Hz, -6.358120e+00, -6.335796e+02)
+( 8.794872e+07Hz, -5.894279e+00, -6.719727e+02)
+( 9.282051e+07Hz, -4.063864e+00, -7.129969e+02)
+( 9.769231e+07Hz, -2.367660e+00, -7.603597e+02)
+( 1.025641e+08Hz, -2.098602e+00, -8.143919e+02)
+( 1.074359e+08Hz, -4.094614e+00, -8.636479e+02)
+( 1.123077e+08Hz, -6.557734e+00, -8.998592e+02)
+( 1.171795e+08Hz, -7.759301e+00, -9.295624e+02)
+( 1.220513e+08Hz, -6.159604e+00, -9.703161e+02)
+( 1.269231e+08Hz, -1.040475e+01, -1.077742e+03)
+( 1.317949e+08Hz, -2.627115e+01, -1.123641e+03)
+( 1.366667e+08Hz, -4.503397e+01, -9.675219e+02)
+( 1.415385e+08Hz, -3.255698e+01, -9.893598e+02)
+( 1.464103e+08Hz, -3.059532e+01, -1.012566e+03)
+( 1.512821e+08Hz, -3.081422e+01, -1.036661e+03)
+( 1.561538e+08Hz, -3.231825e+01, -1.058931e+03)
+( 1.610256e+08Hz, -3.453111e+01, -1.077318e+03)
+( 1.658974e+08Hz, -3.699828e+01, -1.091740e+03)
+( 1.707692e+08Hz, -3.947129e+01, -1.103061e+03)
+( 1.756410e+08Hz, -4.184769e+01, -1.112161e+03)
+( 1.805128e+08Hz, -4.409577e+01, -1.119694e+03)
+( 1.853846e+08Hz, -4.621280e+01, -1.126103e+03)
+( 1.902564e+08Hz, -4.820666e+01, -1.131686e+03)
+( 1.951282e+08Hz, -5.008836e+01, -1.136645e+03)
+( 2.000000e+08Hz, -5.186916e+01, -1.141123e+03)
*S21 FREQ DB PHASE
E21 21 22 FREQ {V(10,3)}= DB
+( 1.000000e+07Hz, -1.248758e+02, -1.373971e+02)
+( 1.487179e+07Hz, -9.831399e+01, -1.647281e+02)
+( 1.974359e+07Hz, -7.673566e+01, -2.026127e+02)
+( 2.461538e+07Hz, -5.898226e+01, -2.906518e+02)
+( 2.948718e+07Hz, -5.542440e+01, -3.666485e+02)
+( 3.435897e+07Hz, -5.204910e+01, -4.009490e+02)
+( 3.923077e+07Hz, -4.814977e+01, -4.271950e+02)
+( 4.410256e+07Hz, -4.426072e+01, -4.514100e+02)
+( 4.897436e+07Hz, -4.063346e+01, -4.755494e+02)
+( 5.384615e+07Hz, -3.749934e+01, -5.003303e+02)
+( 5.871795e+07Hz, -3.516924e+01, -5.256223e+02)
+( 6.358974e+07Hz, -3.433887e+01, -5.509590e+02)
+( 6.846154e+07Hz, -3.971774e+01, -5.765977e+02)
+( 7.333333e+07Hz, -2.496027e+01, -4.260244e+02)
+( 7.820513e+07Hz, -2.540060e-01, -5.317362e+02)
+( 8.307692e+07Hz, -6.358120e+00, -6.335796e+02)
+( 8.794872e+07Hz, -5.894279e+00, -6.719727e+02)
+( 9.282051e+07Hz, -4.063864e+00, -7.129969e+02)
+( 9.769231e+07Hz, -2.367660e+00, -7.603597e+02)
+( 1.025641e+08Hz, -2.098602e+00, -8.143919e+02)
+( 1.074359e+08Hz, -4.094614e+00, -8.636479e+02)
+( 1.123077e+08Hz, -6.557734e+00, -8.998592e+02)
+( 1.171795e+08Hz, -7.759301e+00, -9.295624e+02)
+( 1.220513e+08Hz, -6.159604e+00, -9.703161e+02)
+( 1.269231e+08Hz, -1.040475e+01, -1.077742e+03)
+( 1.317949e+08Hz, -2.627115e+01, -1.123641e+03)
+( 1.366667e+08Hz, -4.503397e+01, -9.675219e+02)
+( 1.415385e+08Hz, -3.255698e+01, -9.893598e+02)
+( 1.464103e+08Hz, -3.059532e+01, -1.012566e+03)
+( 1.512821e+08Hz, -3.081422e+01, -1.036661e+03)
+( 1.561538e+08Hz, -3.231825e+01, -1.058931e+03)
+( 1.610256e+08Hz, -3.453111e+01, -1.077318e+03)
+( 1.658974e+08Hz, -3.699828e+01, -1.091740e+03)
+( 1.707692e+08Hz, -3.947129e+01, -1.103061e+03)
+( 1.756410e+08Hz, -4.184769e+01, -1.112161e+03)
+( 1.805128e+08Hz, -4.409577e+01, -1.119694e+03)
+( 1.853846e+08Hz, -4.621280e+01, -1.126103e+03)
+( 1.902564e+08Hz, -4.820666e+01, -1.131686e+03)
+( 1.951282e+08Hz, -5.008836e+01, -1.136645e+03)
+( 2.000000e+08Hz, -5.186916e+01, -1.141123e+03)
*S22 FREQ DB PHASE
E22 22 3 FREQ {V(20,3)}= DB
+( 1.000000e+07Hz, 1.633257e-07, -1.859873e+01)
+( 1.487179e+07Hz, -1.597472e-07, -3.368599e+01)
+( 1.974359e+07Hz, -9.840549e-08, -6.829764e+01)
+( 2.461538e+07Hz, -5.748843e-06, -2.027281e+02)
+( 2.948718e+07Hz, -1.209271e-05, -3.137855e+02)
+( 3.435897e+07Hz, -2.686288e-05, -3.426102e+02)
+( 3.923077e+07Hz, -6.619051e-05, -3.559304e+02)
+( 4.410256e+07Hz, -1.626503e-04, -3.646130e+02)
+( 4.897436e+07Hz, -3.750315e-04, -3.714149e+02)
+( 5.384615e+07Hz, -7.720713e-04, -3.773802e+02)
+( 5.871795e+07Hz, -1.321131e-03, -3.830562e+02)
+( 6.358974e+07Hz, -1.599127e-03, -3.888868e+02)
+( 6.846154e+07Hz, -4.639695e-04, -3.955734e+02)
+( 7.333333e+07Hz, -1.388161e-02, -4.057551e+02)
+( 7.820513e+07Hz, -1.245578e+01, -4.419690e+02)
+( 8.307692e+07Hz, -1.142468e+00, -3.983505e+02)
+( 8.794872e+07Hz, -1.292324e+00, -4.097393e+02)
+( 9.282051e+07Hz, -2.163078e+00, -4.176053e+02)
+( 9.769231e+07Hz, -3.764828e+00, -4.193838e+02)
+( 1.025641e+08Hz, -4.165672e+00, -4.076855e+02)
+( 1.074359e+08Hz, -2.143343e+00, -4.074397e+02)
+( 1.123077e+08Hz, -1.084156e+00, -4.178506e+02)
+( 1.171795e+08Hz, -7.962687e-01, -4.296447e+02)
+( 1.220513e+08Hz, -1.204024e+00, -4.416736e+02)
+( 1.269231e+08Hz, -4.148459e-01, -4.461929e+02)
+( 1.317949e+08Hz, -1.026073e-02, -4.669521e+02)
+( 1.366667e+08Hz, -1.361528e-04, -4.892508e+02)
+( 1.415385e+08Hz, -2.411138e-03, -5.172082e+02)
+( 1.464103e+08Hz, -3.788042e-03, -5.519999e+02)
+( 1.512821e+08Hz, -3.601989e-03, -5.908887e+02)
+( 1.561538e+08Hz, -2.547212e-03, -6.276516e+02)
+( 1.610256e+08Hz, -1.529976e-03, -6.577430e+02)
+( 1.658974e+08Hz, -8.674572e-04, -6.807399e+02)
+( 1.707692e+08Hz, -4.901623e-04, -6.981937e+02)
+( 1.756410e+08Hz, -2.836349e-04, -7.117446e+02)
+( 1.805128e+08Hz, -1.694495e-04, -7.226059e+02)
+( 1.853846e+08Hz, -1.034247e-04, -7.315943e+02)
+( 1.902564e+08Hz, -6.587183e-05, -7.392507e+02)
+( 1.951282e+08Hz, -4.251059e-05, -7.459375e+02)
+( 2.000000e+08Hz, -2.798303e-05, -7.519027e+02)
.ENDS

91
examples/sp/filter.sp Normal file
View File

@ -0,0 +1,91 @@
* Simple test for xfer code model: comparison
*
* This circuit compares the results of an AC analysis of a filter (node out)
* with those from a behavioural model controlled by measured S-parameters
* of that circuit (node xout). The AC analysis has more data points than
* that used to measure the S-parameters, to prevent the results from matching
* exactly.
* The use of S-parameters to create a behavioural simulation of a component
* was discussed here:
* https://sourceforge.net/p/ngspice/discussion/120973/thread/51228e0b01/
* Circuit from:
* Novarianti, Dini. (2019).
* Design and Implementation of Chebyshev Band Pass Filter with
* M-Derived Section in Frequency Band 88 - 108 MHz.
* Jurnal Jartel: Jurnal Jaringan Telekomunikasi. 8. 7-11.
* 10.33795/jartel.v8i1.147.
*
* https://www.researchgate.net/publication/352822864_Design_and_Implementation_of_Chebyshev_Band_Pass_Filter_with_M-Derived_Section_in_Frequency_Band_88_-_108_MHz
* Set this parameter to 1 to generate a Touchstone file that can be used
* to generate the behavioural part of the circuit, filter.lib
.param do_sp=0
.csparam do_sp=do_sp
.if (do_sp)
.csparam Rbase=50 ; This is required by "wrs2p", below.
vgen 1 0 dc 0 ac 1 portnum 1
.else
vgen in 0 dc 0 ac 1
rs in 1 50
.endif
l1 1 2 0.058u
c2 2 0 40.84p
l3 2 3 0.128u
c4 3 0 47.91p
l5 3 4 0.128u
c6 4 0 40.48p
l7 4 5 0.058u
la 5 6 0.044u
lb 6 a 0.078u
cb a 0 17.61p
lc 6 b 0.151u
cc b 0 34.12p
c7 6 7 26.035p
l8 7 0 0.0653u
c8 7 8 20.8p
l9 8 0 0.055u
c9 8 9 20.8p
l10 9 0 0.653u
c10 9 out 45.64p
.if (do_sp)
vl out 0 dc 0 ac 0 portnum 2
.else
rl out 0 50
* Behavioural circuit, for comparison.
.inc filter.lib
R1 in port1 50
xsp port1 xout 0 filter
R2 xout 0 50
.endif
.control
if $&do_sp
sp lin 40 10meg 200meg
wrs2p filter.s2p
plot S_1_1 S_2_2 polar
else
ac lin 400 10meg 200meg
plot db(mag(out)) 5*unwrap(ph(out)) db(mag(xout)) 5*unwrap(ph(xout))
end
.endc
.end

View File

@ -1,7 +1,6 @@
VBIC Output Test Ic=f(Vc,Ib) vs self heating VBIC Output Test Ic=f(Vc,Ib) vs self heating
.option absmos=1e-12 relmos=1e-6 relv=1e-6 absv=1e-9 post
vc c 0 0 vc c 0 0
vb b 0 1 ib 0 b 10u
ve e 0 0 ve e 0 0
vs s 0 0 vs s 0 0
vc1 c c1 0 vc1 c c1 0
@ -9,42 +8,16 @@ vb1 b b1 0
ve1 e e1 0 ve1 e e1 0
vs1 s s1 0 vs1 s s1 0
.temp 27 .temp 27
Q1 c1 b1 e1 s1 t mod1 area=1 Q1 c1 b1 e1 s1 dt M_BFP780 area=1
.model mod1 npn Level=4
+ Tnom=27 RCX=10 RCI=60 VO=2 GAMM=2.e-11 .include Infineon_VBIC.lib
+ HRCF=2 RBX=10 RBI=40 RE=2
+ RS=20 RBP=40 IS=1e-16 NF=1.00000e+00
+ NR=1.00000e+00 FC=9.00000e-01 CBEO=0
+ CJE=1.e-13 PE=0.75 ME=0.33
+ AJE=-5.00000e-01 CBCO=0 CJC=2e-14
+ QCO=1e-12 CJEP=1e-13 PC=7.50000e-01
+ MC=3.30000e-01 AJC=-5.00000e-01 CJCP=4e-13
+ PS=7.50000e-01 MS=3.30000e-01 AJS=-5.00000e-01
+ IBEI=1e-18 WBE=1.0000 NEI=1.00000e+00
+ IBEN=5e-15 NEN=2.00000e+00 IBCI=2e-17
+ NCI=1.00000e+00 IBCN=5e-15 NCN=2.00000e+00
+ AVC1=2 AVC2=15 ISP=1e-15
+ WSP=1.000e+00 NFP=1.00000e+00 IBEIP=0
+ IBENP=0 IBCIP=0 NCIP=1.00000e+00
+ IBCNP=0 NCNP=2.00000e+00 VEF=10
+ VER=4 IKF=0.002 IKR=0.0002 IKP=0.0002
+ TF=1.e-11 QTF=0 XTF=20
+ VTF=0 ITF=0.08 TR=1e-10
+ KFN=0 AFN=1.0e+00
+ BFN=1.0000e+00 XRE=0 XRB=0
+ XRC=0 XRS=0 XVO=0
+ EA=1.12000e+00 EAIE=1.12000e+00
+ EANE=1.12000e+00 EANC=1.12000e+00
+ EANS=1.12000e+00 XIS=3.00000e+00
+ XII=3.00000e+00 XIN=3.00000e+00
+ TNF=0 TAVC=0
+ RTH=300 CTH=0
+ TD=0
*+ TD=2.e-11
.control .control
dc vc 0.0 5.0001 0.05 vb 0.7 1.0001 0.05 dc vc 0.0 5.0 0.05 ib 50u 500u 50u
altermod @mod1[RTH]=0 settype temperature v(dt)
dc vc 0.0 5.0001 0.05 vb 0.7 1.0001 0.05 plot v(dt)
altermod @M_BFP780[RTH]=0
dc vc 0.0 5.0 0.05 ib 50u 500u 50u
plot dc1.vc1#branch dc2.vc1#branch plot dc1.vc1#branch dc2.vc1#branch
.endc .endc
.end .end

View File

@ -18,17 +18,18 @@ xinv7 9 8 1 0 inv
xinv8 10 9 1 0 inv xinv8 10 9 1 0 inv
xinv9 2 10 1 0 inv xinv9 2 10 1 0 inv
.model N1 vdmos cgdmin=0.05p cgdmax=0.2p a=1.2 cgs=0.15p rg=10 kp=1e-5 rb=1e7 cjo=1n ksubthres=0.2 .model N1 vdmos vto=1 cgdmin=0.05p cgdmax=0.2p a=1.2 cgs=0.15p rg=10 kp=1e-5 rb=1e7 cjo=1n ksubthres=0.2
.model P1 vdmos cgdmin=0.05p cgdmax=0.2p a=1.2 cgs=0.15p rg=10 kp=1e-5 rb=1e7 cjo=1n pchan ksubthres=0.2 .model P1 vdmos vto=-1 cgdmin=0.05p cgdmax=0.2p a=1.2 cgs=0.15p rg=10 kp=1e-5 rb=1e7 cjo=1n pchan ksubthres=0.2
.tran 0.1n 5u .tran 0.1n 10u
.ic v(6)=2.5
.control .control
run run
rusage rusage
* current and output in a single plot * current and output in a single plot
plot v(6) 1000*(-I(vdd)) ylimit -1 6 plot v(6) 50000*(-I(vdd)) ylimit -1 6
.endc .endc
.end .end

View File

@ -66,9 +66,10 @@ abridge-w1 [d_divout d_ref d_Un d_D] [s1 s2 u1 d1] dac1 ; change to d_u or d_Un
.control .control
save cont s1 s2 u1 d1 save cont s1 s2 u1 d1
set xbrushwidth=2
let isbmode = $?batchmode let isbmode = $?batchmode
if isbmode = 0 if isbmode = 0
iplot cont iplot -w $&simtime cont
endif endif
* calculate breakpoint for switching frequency * calculate breakpoint for switching frequency
let t1_3 = simtime/3 let t1_3 = simtime/3

View File

@ -66,10 +66,31 @@ TWOdestroy(TWOdevice *pDevice)
FREE( pElem ); FREE( pElem );
} }
FREE( pDevice->elements ); FREE( pDevice->elements );
for (int xIndex = 1; xIndex < pDevice->numXNodes; xIndex++) {
FREE(pDevice->elemArray[xIndex]);
}
FREE( pDevice->elemArray ); FREE( pDevice->elemArray );
} }
/* destroy the contacts & channels */ if (pDevice->pMaterials) {
TWOmaterial* pMtmp = pDevice->pMaterials;
while (pMtmp) {
TWOmaterial* pMtmpnext = pMtmp->next;
FREE(pMtmp);
pMtmp = pMtmpnext;
}
}
if (pDevice->pFirstContact) {
struct sTWOcontact* pFCtmp = pDevice->pFirstContact;
while (pFCtmp) {
struct sTWOcontact* pFCtmpnext = pFCtmp->next;
FREE(pFCtmp);
pFCtmp = pFCtmpnext;
}
}
/* destroy the channels */
/* NOT IMPLEMENTED */ /* NOT IMPLEMENTED */
FREE( pDevice ); FREE( pDevice );

View File

@ -205,7 +205,26 @@ com_iplot(wordlist *wl)
/* settrace(wl, VF_PLOT); */ /* settrace(wl, VF_PLOT); */
struct dbcomm *d, *td, *currentdb = NULL; struct dbcomm *d, *td, *currentdb = NULL;
char *s; double window;
char *s;
/* Look for "-w window-size" at the front, indicating a windowed iplot. */
if (wl->wl_next && !strcmp("-w", wl->wl_word)) {
char *cp;
int error;
wl = wl->wl_next;
cp = wl->wl_word;
window = INPevaluate(&cp, &error, 0);
if (error || window <= 0) {
fprintf(cp_err, "Incremental plot width must be positive.\n");
return;
}
wl = wl->wl_next;
} else {
window = 0.0;
}
/* We use a modified ad-hoc algorithm here where db_also denotes /* We use a modified ad-hoc algorithm here where db_also denotes
vectors on the same command line and db_next denotes vectors on the same command line and db_next denotes
@ -215,6 +234,7 @@ com_iplot(wordlist *wl)
d = TMALLOC(struct dbcomm, 1); d = TMALLOC(struct dbcomm, 1);
d->db_analysis = NULL; d->db_analysis = NULL;
d->db_number = debugnumber++; d->db_number = debugnumber++;
d->db_value1 = window; // Field re-use
if (eq(s, "all")) { if (eq(s, "all")) {
d->db_type = DB_IPLOTALL; d->db_type = DB_IPLOTALL;
} else { } else {

View File

@ -426,7 +426,7 @@ struct comm spcp_coms[] = {
{ "iplot", com_iplot, TRUE, TRUE, { "iplot", com_iplot, TRUE, TRUE,
{ 0200, 0200, 0200, 0200 }, E_DEFHMASK, 0, LOTS, { 0200, 0200, 0200, 0200 }, E_DEFHMASK, 0, LOTS,
NULL, NULL,
"[all] [node ...] : Incrementally plot a node." } , "[-w width] [all] [node ...] : Incrementally plot nodes." } ,
{ "status", com_sttus, TRUE, FALSE, { "status", com_sttus, TRUE, FALSE,
{ 0, 0, 0, 0 }, E_DEFHMASK, 0, 0, { 0, 0, 0, 0 }, E_DEFHMASK, 0, 0,
NULL, NULL,

View File

@ -191,7 +191,7 @@ doop(char what,
struct dvec *v1, *v2, *res; struct dvec *v1, *v2, *res;
ngcomplex_t *c1 = NULL, *c2 = NULL, lc; ngcomplex_t *c1 = NULL, *c2 = NULL, lc;
double *d1 = NULL, *d2 = NULL, ld; double *d1 = NULL, *d2 = NULL, ld;
int length = 0, i; int length = 0, i, longer;
void *data; void *data;
bool free1 = FALSE, free2 = FALSE, relflag = FALSE; bool free1 = FALSE, free2 = FALSE, relflag = FALSE;
@ -253,6 +253,7 @@ doop(char what,
/* Make sure we have data of the same length. */ /* Make sure we have data of the same length. */
length = ((v1->v_length > v2->v_length) ? v1->v_length : v2->v_length); length = ((v1->v_length > v2->v_length) ? v1->v_length : v2->v_length);
if (v1->v_length < length) { if (v1->v_length < length) {
longer = 2;
free1 = TRUE; free1 = TRUE;
if (isreal(v1)) { if (isreal(v1)) {
ld = 0.0; ld = 0.0;
@ -275,6 +276,7 @@ doop(char what,
c1[i] = lc; c1[i] = lc;
} }
} else { } else {
longer = 0;
if (isreal(v1)) if (isreal(v1))
d1 = v1->v_realdata; d1 = v1->v_realdata;
else else
@ -282,6 +284,7 @@ doop(char what,
} }
if (v2->v_length < length) { if (v2->v_length < length) {
longer = 1;
free2 = TRUE; free2 = TRUE;
if (isreal(v2)) { if (isreal(v2)) {
ld = 0.0; ld = 0.0;
@ -335,10 +338,27 @@ doop(char what,
} }
/* This is a non-obvious thing */ /* This is a non-obvious thing */
if (v1->v_scale != v2->v_scale) { if (v1->v_scale != v2->v_scale) {
fprintf(cp_err, "Warning: scales of %s and %s are different.\n", switch (longer) {
v1->v_name, v2->v_name); case 0:
res->v_scale = NULL; if (!v1->v_scale)
res->v_scale = v2->v_scale;
else if (!v2->v_scale)
res->v_scale = v1->v_scale;
else
fprintf(cp_err,
"Warning: scales of %s and %s are different.\n",
v1->v_name, v2->v_name);
res->v_scale = v1->v_scale; // Do something!
break;
case 1:
res->v_scale = v1->v_scale;
break;
case 2:
res->v_scale = v2->v_scale;
break;
}
} else { } else {
res->v_scale = v1->v_scale; res->v_scale = v1->v_scale;
} }

View File

@ -20,6 +20,7 @@ cp_init(void)
cp_chars[128] cp_chars[128]
cp_maxhistlength (set to 10000 in com_history.c) cp_maxhistlength (set to 10000 in com_history.c)
cp_curin, cp_curout, cp_curerr (defined in streams.c) cp_curin, cp_curout, cp_curerr (defined in streams.c)
cp_no_histsubst
*/ */
{ {
cp_vset("history", CP_NUM, &cp_maxhistlength); cp_vset("history", CP_NUM, &cp_maxhistlength);
@ -28,6 +29,10 @@ cp_init(void)
cp_curout = stdout; cp_curout = stdout;
cp_curerr = stderr; cp_curerr = stderr;
/* Enable history substitution */
if (cp_getvar("histsubst", CP_BOOL, NULL, 0))
cp_no_histsubst = FALSE;
/* io redirection in streams.c: /* io redirection in streams.c:
cp_in set to cp_curin etc. */ cp_in set to cp_curin etc. */
cp_ioreset(); cp_ioreset();

View File

@ -890,23 +890,36 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile)
/* handle .if ... .elseif ... .else ... .endif statements. */ /* handle .if ... .elseif ... .else ... .endif statements. */
dotifeval(deck); dotifeval(deck);
/* get csparams and create vectors, available
in plot 'const' of a .control section */
for (dd = deck; dd; dd = dd->nextcard) { for (dd = deck; dd; dd = dd->nextcard) {
/* get csparams and create vectors, being
available in .control section, in plot 'const' */
if (ciprefix(".csparam", dd->line)) { if (ciprefix(".csparam", dd->line)) {
wordlist *wlist = NULL; wordlist *wlist = NULL;
char *cstoken[3]; char *cstoken[3];
int i; int i;
dd->line[0] = '*'; dd->line[0] = '*';
s = skip_ws(dd->line + 8); s = skip_ws(dd->line + 8);
cstoken[0] = gettok_char(&s, '=', FALSE, FALSE); while (s && *s) {
cstoken[1] = gettok_char(&s, '=', TRUE, FALSE); char* nexttoken = s;
cstoken[2] = gettok(&s); cstoken[0] = gettok_char(&s, '=', FALSE, FALSE);
for (i = 3; --i >= 0; ) { cstoken[1] = gettok_char(&s, '=', TRUE, FALSE);
wlist = wl_cons(cstoken[i], wlist); cstoken[2] = gettok(&s);
/* guard against buggy input line */
if (!cstoken[0] || !cstoken[1] || !cstoken[2] || strchr(cstoken[2],'=')) {
fprintf(stderr, "Warning: bad csparam definition, %s skipped!\n", nexttoken);
fprintf(stderr, " See line %d, .%s\n\n", dd->linenum, dd->line + 1);
tfree(cstoken[0]);
tfree(cstoken[1]);
tfree(cstoken[2]);
break;
}
for (i = 3; --i >= 0; ) {
wlist = wl_cons(cstoken[i], wlist);
}
com_let(wlist);
wl_free(wlist);
wlist = NULL;
} }
com_let(wlist);
wl_free(wlist);
} }
} }

View File

@ -895,6 +895,9 @@ void inp_probe(struct card* deck)
else if (err == 2) { else if (err == 2) {
fprintf(stderr, "Warning: Zero voltage sources already set,\n .probe %s will be ignored\n", wltmp->wl_word); fprintf(stderr, "Warning: Zero voltage sources already set,\n .probe %s will be ignored\n", wltmp->wl_word);
} }
else if (err == 3) {
fprintf(stderr, "Warning: Number of nodes mismatch,\n .probe %s will be ignored\n", wltmp->wl_word);
}
continue; continue;
} }
else if (!haveall) { else if (!haveall) {
@ -1358,6 +1361,15 @@ static int setallvsources(struct card *tmpcard, NGHASHPTR instances, char *instn
char nodenumstr[3]; char nodenumstr[3];
char *nodename1 = get_terminal_name(instname, itoa10(nodenum, nodenumstr), instances); char *nodename1 = get_terminal_name(instname, itoa10(nodenum, nodenumstr), instances);
if (!nodename1) {
tfree(begstr);
tfree(strnode1);
ds_free(&BVrefline);
ds_free(&Bpowerline);
ds_free(&Bpowersave);
return 3;
}
newline = tprintf("%s %s %s", begstr, newnode, instline); newline = tprintf("%s %s %s", begstr, newnode, instline);
char* vline = tprintf("vcurr_%s:probe_int_%s:%s_%s %s %s 0", instname, nodename1, nodenumstr, strnode1, strnode1, newnode); char* vline = tprintf("vcurr_%s:probe_int_%s:%s_%s %s %s 0", instname, nodename1, nodenumstr, strnode1, strnode1, newnode);

View File

@ -136,7 +136,6 @@ static void inp_reorder_params(
static int inp_split_multi_param_lines(struct card *deck, int line_number); static int inp_split_multi_param_lines(struct card *deck, int line_number);
static void inp_sort_params(struct card *param_cards, static void inp_sort_params(struct card *param_cards,
struct card *card_bf_start, struct card *s_c, struct card *e_c); struct card *card_bf_start, struct card *s_c, struct card *e_c);
char *inp_remove_ws(char *s);
static void inp_compat(struct card *deck); static void inp_compat(struct card *deck);
static void inp_bsource_compat(struct card *deck); static void inp_bsource_compat(struct card *deck);
static bool inp_temper_compat(struct card *card); static bool inp_temper_compat(struct card *card);
@ -153,7 +152,7 @@ static char inp_get_elem_ident(char *type);
static void rem_mfg_from_models(struct card *start_card); static void rem_mfg_from_models(struct card *start_card);
static void inp_fix_macro_param_func_paren_io(struct card *begin_card); static void inp_fix_macro_param_func_paren_io(struct card *begin_card);
static void inp_fix_gnd_name(struct card *deck); static void inp_fix_gnd_name(struct card *deck);
static void inp_chk_for_multi_in_vcvs(struct card *deck, int *line_number); static void inp_chk_for_e_source_to_xspice(struct card *deck, int *line_number);
static void inp_add_control_section(struct card *deck, int *line_number); static void inp_add_control_section(struct card *deck, int *line_number);
static char *get_quoted_token(char *string, char **token); static char *get_quoted_token(char *string, char **token);
static void replace_token(char *string, char *token, int where, int total); static void replace_token(char *string, char *token, int where, int total);
@ -167,7 +166,6 @@ static void inp_check_syntax(struct card *deck);
static char *inp_spawn_brace(char *s); static char *inp_spawn_brace(char *s);
static char *inp_pathresolve_at(const char *name, const char *dir); static char *inp_pathresolve_at(const char *name, const char *dir);
char *search_plain_identifier(char *str, const char *identifier);
struct nscope *inp_add_levels(struct card *deck); struct nscope *inp_add_levels(struct card *deck);
static struct card_assoc *find_subckt(struct nscope *scope, const char *name); static struct card_assoc *find_subckt(struct nscope *scope, const char *name);
@ -177,6 +175,7 @@ static struct modellist *inp_find_model(
struct nscope *scope, const char *name); struct nscope *scope, const char *name);
void tprint(struct card *deck); void tprint(struct card *deck);
static char* libprint(struct card* t, const char *dir);
static void inp_repair_dc_ps(struct card* oldcard); static void inp_repair_dc_ps(struct card* oldcard);
static void inp_get_w_l_x(struct card* oldcard); static void inp_get_w_l_x(struct card* oldcard);
@ -185,8 +184,6 @@ static char* eval_m(char* line, char* tline);
static char* eval_tc(char* line, char* tline); static char* eval_tc(char* line, char* tline);
static char* eval_mvalue(char* line, char* tline); static char* eval_mvalue(char* line, char* tline);
static void rem_double_braces(struct card* card);
extern void inp_probe(struct card* card); extern void inp_probe(struct card* card);
#ifndef EXT_ASC #ifndef EXT_ASC
static void utf8_syntax_check(struct card *deck); static void utf8_syntax_check(struct card *deck);
@ -619,16 +616,19 @@ static char *cat2strings(char *s1, char *s2, bool spa)
/* line1 /* line1
+ line2 + line2
----> ---->
line1 line 2 line1 line2
Proccedure: store regular card in prev, skip comment lines (*..) and some Proccedure: store regular card in prev, skip comment lines (*..) and some
others others, add tokens from + lines to prev using dstring.
*/ */
static void inp_stitch_continuation_lines(struct card *working) static void inp_stitch_continuation_lines(struct card* working)
{ {
struct card *prev = NULL; struct card* prev = NULL;
bool firsttime = TRUE;
DS_CREATE(newline, 200);
while (working) { while (working) {
char *s, c, *buffer; char* s, c;
for (s = working->line; (c = *s) != '\0' && c <= ' '; s++) for (s = working->line; (c = *s) != '\0' && c <= ' '; s++)
; ;
@ -636,11 +636,110 @@ static void inp_stitch_continuation_lines(struct card *working)
#ifdef TRACE #ifdef TRACE
/* SDB debug statement */ /* SDB debug statement */
printf("In inp_read, processing linked list element line = %d, s = " printf("In inp_read, processing linked list element line = %d, s = "
"%s . . . \n", "%s . . . \n",
working->linenum, s); working->linenum, s);
#endif #endif
switch (c) { switch (c) {
case '#':
case '$':
case '*':
case '\0':
/* skip these cards, and keep prev as the last regular card */
working = working->nextcard; /* for these chars, go to next
card */
break;
case '+': /* handle continuation */
if (!prev) {
working->error =
copy("Illegal continuation line: ignored.");
working = working->nextcard;
break;
}
/* We now may have lept over some comment lines, which are
located among the continuation lines. We have to delete them
here to prevent a memory leak */
while (prev->nextcard != working) {
struct card* tmpl = prev->nextcard->nextcard;
line_free_x(prev->nextcard, FALSE);
prev->nextcard = tmpl;
}
if (firsttime) {
sadd(&newline, prev->line);
firsttime = FALSE;
}
else {
/* replace '+' by space */
*s = ' ';
sadd(&newline, s);
/* mark for later removal */
*s = '*';
}
break;
default: /* regular one-line card */
if (!firsttime) {
tfree(prev->line);
prev->line = copy(ds_get_buf(&newline));
ds_clear(&newline);
firsttime = TRUE;
/* remove final used '+' line, if regular line is following */
struct card* tmpl = prev->nextcard->nextcard;
line_free_x(prev->nextcard, FALSE);
prev->nextcard = tmpl;
}
prev = working;
working = working->nextcard;
break;
}
}
/* remove final used '+' line when no regular line is following */
if (!firsttime) {
tfree(prev->line);
prev->line = copy(ds_get_buf(&newline));
}
ds_free(&newline);
}
#ifdef CIDER
/* Only if we have a CIDER .model line with regular structure
'.model modname modtype level',
with modtype being one of numos, numd, nbjt:
Concatenate lines
line1
+ line2
---->
line1 line 2
Store the original lines in card->actualLine, to be used for
CIDER model parameter parsing in INPparseNumMod() of inpgmod.c
*/
static void inp_cider_models(struct card* working)
{
struct card* prev = NULL;
bool iscmod = FALSE;
while (working) {
char *s, c, *buffer;
for (s = working->line; (c = *s) != '\0' && c <= ' '; s++)
;
if(!iscmod)
iscmod = is_cider_model(s);
#ifdef TRACE
/* SDB debug statement */
printf("In inp_read, processing linked list element line = %d, s = "
"%s . . . \n",
working->linenum, s);
#endif
if (iscmod) {
switch (c) {
case '#': case '#':
case '$': case '$':
case '*': case '*':
@ -653,7 +752,7 @@ static void inp_stitch_continuation_lines(struct card *working)
case '+': /* handle continuation */ case '+': /* handle continuation */
if (!prev) { if (!prev) {
working->error = working->error =
copy("Illegal continuation line: ignored."); copy("Illegal continuation line: ignored.");
working = working->nextcard; working = working->nextcard;
break; break;
} }
@ -662,7 +761,7 @@ static void inp_stitch_continuation_lines(struct card *working)
located among the continuation lines. We have to delete them located among the continuation lines. We have to delete them
here to prevent a memory leak */ here to prevent a memory leak */
while (prev->nextcard != working) { while (prev->nextcard != working) {
struct card *tmpl = prev->nextcard->nextcard; struct card* tmpl = prev->nextcard->nextcard;
line_free_x(prev->nextcard, FALSE); line_free_x(prev->nextcard, FALSE);
prev->nextcard = tmpl; prev->nextcard = tmpl;
} }
@ -670,14 +769,14 @@ static void inp_stitch_continuation_lines(struct card *working)
/* create buffer and write last and current line into it. /* create buffer and write last and current line into it.
When reading a PDK, the following may be called more than 1e6 times. */ When reading a PDK, the following may be called more than 1e6 times. */
#if defined (_MSC_VER) #if defined (_MSC_VER)
/* vsnprintf (used by tprintf) in Windows is efficient, VS2019 arb. referencevalue 7, /* vsnprintf (used by tprintf) in Windows is efficient, VS2019 arb. referencevalue 7,
cat2strings() yields ref. speed value 12 only, CYGWIN is 12 in both cases, cat2strings() yields ref. speed value 12 only, CYGWIN is 12 in both cases,
MINGW is 36. */ MINGW is 36. */
buffer = tprintf("%s %s", prev->line, s + 1); buffer = tprintf("%s %s", prev->line, s + 1);
#else #else
/* vsnprintf in Linux is very inefficient, ref. value 24 /* vsnprintf in Linux is very inefficient, ref. value 24
cat2strings() is efficient with ref. speed value 6, cat2strings() is efficient with ref. speed value 6,
MINGW is 12 */ MINGW is 12 */
buffer = cat2strings(prev->line, s + 1, TRUE); buffer = cat2strings(prev->line, s + 1, TRUE);
#endif #endif
/* replace prev->line by buffer */ /* replace prev->line by buffer */
@ -687,16 +786,16 @@ static void inp_stitch_continuation_lines(struct card *working)
working->nextcard = NULL; working->nextcard = NULL;
/* add original line to prev->actualLine */ /* add original line to prev->actualLine */
if (prev->actualLine) { if (prev->actualLine) {
struct card *end; struct card* end;
for (end = prev->actualLine; end->nextcard; for (end = prev->actualLine; end->nextcard;
end = end->nextcard) end = end->nextcard)
; ;
end->nextcard = working; end->nextcard = working;
tfree(s); tfree(s);
} }
else { else {
prev->actualLine = prev->actualLine =
insert_new_line(NULL, s, prev->linenum, 0); insert_new_line(NULL, s, prev->linenum, 0);
prev->actualLine->level = prev->level; prev->actualLine->level = prev->level;
prev->actualLine->nextcard = working; prev->actualLine->nextcard = working;
} }
@ -706,11 +805,15 @@ static void inp_stitch_continuation_lines(struct card *working)
default: /* regular one-line card */ default: /* regular one-line card */
prev = working; prev = working;
working = working->nextcard; working = working->nextcard;
iscmod = is_cider_model(s);
break; break;
}
} }
else
working = working->nextcard;
} }
} }
#endif
/* /*
* search for `=' assignment operator * search for `=' assignment operator
@ -929,8 +1032,8 @@ struct card *inp_readall(FILE *fp, const char *dir_name,
utf8_syntax_check(working); utf8_syntax_check(working);
#endif #endif
/* some syntax checks, including title line */ /* some syntax checks, excluding title line */
inp_check_syntax(cc); inp_check_syntax(working);
if (newcompat.lt && newcompat.a) if (newcompat.lt && newcompat.a)
ltspice_compat_a(working); ltspice_compat_a(working);
@ -992,7 +1095,7 @@ struct card *inp_readall(FILE *fp, const char *dir_name,
subckt_w_params = NULL; subckt_w_params = NULL;
if (!cp_getvar("no_auto_gnd", CP_BOOL, NULL, 0)) if (!cp_getvar("no_auto_gnd", CP_BOOL, NULL, 0))
inp_fix_gnd_name(working); inp_fix_gnd_name(working);
inp_chk_for_multi_in_vcvs(working, &rv.line_number); inp_chk_for_e_source_to_xspice(working, &rv.line_number);
/* "addcontrol" variable is set if "ngspice -a file" was used. */ /* "addcontrol" variable is set if "ngspice -a file" was used. */
@ -1587,6 +1690,10 @@ struct inp_read_t inp_read( FILE *fp, int call_depth, const char *dir_name,
if this is a command file or called from within a .control section. */ if this is a command file or called from within a .control section. */
inp_stripcomments_deck(cc->nextcard, comfile || is_control); inp_stripcomments_deck(cc->nextcard, comfile || is_control);
#ifdef CIDER
inp_cider_models(cc->nextcard);
#endif
inp_stitch_continuation_lines(cc->nextcard); inp_stitch_continuation_lines(cc->nextcard);
rv.line_number = line_number; rv.line_number = line_number;
@ -1906,7 +2013,6 @@ static void inp_fix_gnd_name(struct card *c)
} }
} }
/* /*
* transform a VCVS "gate" instance into a XSPICE instance * transform a VCVS "gate" instance into a XSPICE instance
* *
@ -1924,7 +2030,336 @@ static void inp_fix_gnd_name(struct card *c)
* the x,y list is fixed to length 2 * the x,y list is fixed to length 2
*/ */
static void inp_chk_for_multi_in_vcvs(struct card *c, int *line_number) static int inp_chk_for_multi_in_vcvs(struct card *c, int *line_number)
{
char *fcn_b, *line;
line = c->line;
if (((fcn_b = strstr(line, "nand(")) != NULL ||
(fcn_b = strstr(line, "and(")) != NULL ||
(fcn_b = strstr(line, "nor(")) != NULL ||
(fcn_b = strstr(line, "or(")) != NULL) &&
isspace_c(fcn_b[-1])) {
#ifndef XSPICE
fprintf(stderr,
"\n"
"Error: XSPICE is required to run the 'multi-input "
"pwl' option in line %d\n"
" %s\n"
"\n"
"See manual chapt. 31 for installation "
"instructions\n",
*line_number, line);
controlled_exit(EXIT_BAD);
#else
char keep, *comma_ptr, *xy_values1[5], *xy_values2[5];
char *out_str, *ctrl_nodes_str,
*xy_values1_b = NULL, *ref_str, *fcn_name,
*fcn_e = NULL, *out_b, *out_e, *ref_e;
char *m_instance, *m_model;
char *xy_values2_b = NULL, *xy_values1_e = NULL,
*ctrl_nodes_b = NULL, *ctrl_nodes_e = NULL;
int xy_count1, xy_count2;
bool ok = FALSE;
do {
ref_e = skip_non_ws(line);
out_b = skip_ws(ref_e);
out_e = skip_back_ws(fcn_b, out_b);
if (out_e <= out_b)
break;
fcn_e = strchr(fcn_b, '(');
ctrl_nodes_b = strchr(fcn_e, ')');
if (!ctrl_nodes_b)
break;
ctrl_nodes_b = skip_ws(ctrl_nodes_b + 1);
comma_ptr = strchr(ctrl_nodes_b, ',');
if (!comma_ptr)
break;
xy_values1_b = skip_back_ws(comma_ptr, ctrl_nodes_b);
if (xy_values1_b[-1] == '}') {
while (--xy_values1_b >= ctrl_nodes_b)
if (*xy_values1_b == '{')
break;
} else {
xy_values1_b = skip_back_non_ws(xy_values1_b, ctrl_nodes_b);
}
if (xy_values1_b <= ctrl_nodes_b)
break;
ctrl_nodes_e = skip_back_ws(xy_values1_b, ctrl_nodes_b);
if (ctrl_nodes_e <= ctrl_nodes_b)
break;
xy_values1_e = skip_ws(comma_ptr + 1);
if (*xy_values1_e == '{') {
xy_values1_e = inp_spawn_brace(xy_values1_e);
} else {
xy_values1_e = skip_non_ws(xy_values1_e);
}
if (!xy_values1_e)
break;
xy_values2_b = skip_ws(xy_values1_e);
ok = TRUE;
} while (0);
if (!ok) {
fprintf(stderr, "ERROR: malformed line: %s\n", line);
controlled_exit(EXIT_FAILURE);
}
ref_str = copy_substring(line, ref_e);
out_str = copy_substring(out_b, out_e);
fcn_name = copy_substring(fcn_b, fcn_e);
ctrl_nodes_str = copy_substring(ctrl_nodes_b, ctrl_nodes_e);
keep = *xy_values1_e;
*xy_values1_e = '\0';
xy_count1 =
get_comma_separated_values(xy_values1, xy_values1_b);
*xy_values1_e = keep;
xy_count2 = get_comma_separated_values(xy_values2, xy_values2_b);
// place restrictions on only having 2 point values; this can
// change later
if (xy_count1 != 2 && xy_count2 != 2)
fprintf(stderr,
"ERROR: only expecting 2 pair values for "
"multi-input vcvs!\n");
m_instance = tprintf("%s %%vd[ %s ] %%vd( %s ) %s", ref_str,
ctrl_nodes_str, out_str, ref_str);
m_instance[0] = 'a';
m_model = tprintf(".model %s multi_input_pwl ( x = [%s %s] y "
"= [%s %s] model = \"%s\" )",
ref_str, xy_values1[0], xy_values2[0], xy_values1[1],
xy_values2[1], fcn_name);
tfree(ref_str);
tfree(out_str);
tfree(fcn_name);
tfree(ctrl_nodes_str);
tfree(xy_values1[0]);
tfree(xy_values1[1]);
tfree(xy_values2[0]);
tfree(xy_values2[1]);
*c->line = '*';
c = insert_new_line(c, m_instance, (*line_number)++, c->linenum_orig);
c = insert_new_line(c, m_model, (*line_number)++, c->linenum_orig);
#endif
return 1;
} else {
return 0; // No keyword match. */
}
}
/* replace the E and G source FREQ function by an XSPICE xfer instance
* (used by Touchstone to netlist converter programs).
* E1 n1 n2 FREQ {expression} = DB values ...
* will become
* B1_gen 1_gen 0 v = expression
* A1_gen 1_gen %d(n1 n2) 1_gen
* .model 1_gen xfer db=true table=[ values ]
*/
static void replace_freq(struct card *c, int *line_number)
{
#ifdef XSPICE
char *line, *e, *e_e, *n1, *n1_e, *n2, *n2_e, *freq;
char *expr, *expr_e, *in, *in_e, *keywd, *cp, *list, *list_e;
int db, ri, rad, got_key, diff;
char pt, key[4];
line = c->line;
/* First token is a node name. */
e = line + 1;
e_e = skip_non_ws(e);
n1 = skip_ws(e_e);
n1_e = skip_non_ws(n1);
freq = strstr(n1_e, "freq");
if (!freq || !isspace_c(freq[-1]) || !isspace_c(freq[4]))
return;
n2 = skip_ws(n1_e);
if (n2 == freq) {
n2 = NULL;
} else {
n2_e = skip_non_ws(n2);
if (freq != skip_ws(n2_e)) // Three nodes or another keyword.
return;
}
/* Isolate the input expression. */
expr = skip_ws(freq + 4);
if (*expr != '{')
return;
expr = skip_ws(expr + 1);
expr_e = strchr(expr, '}');
if (!expr_e)
return;
skip_back_ws(expr_e, expr);
/* Is the expression just a node name, or v(node) or v(node1, node2)? */
in = NULL;
diff = 0;
if (*expr < '0' || *expr > '9') {
for (in_e = expr; in_e < expr_e; ++in_e) {
if ((*in_e < '0' || *in_e > '9') && (*in_e < 'a' || *in_e > 'z') &&
*in_e != '_')
break;
}
if (in_e == expr_e) {
/* A simple identifier. */
in = expr;
}
}
if (expr[0] == 'v' && expr[1] == '(' && expr_e[-1] == ')') {
in = expr + 2;
in_e = expr_e - 1;
cp = strchr(in, ',');
diff = (cp && cp < in_e); // Assume v(n1, n2)
}
/* Look for a keyword. Previous processing may put braces around it. */
keywd = skip_ws(expr_e + 1);
if (*keywd == '=')
keywd = skip_ws(keywd + 1);
db = 1;
rad = 0;
ri = 0;
do {
if (!keywd)
return;
list = keywd; // Perhaps not keyword
if (*keywd == '{')
++keywd;
cp = key;
while (*keywd && !isspace_c(*keywd) && *keywd != '}' &&
cp - key < sizeof key - 1) {
*cp++ = *keywd++;
}
*cp = 0;
if (*keywd == '}')
++keywd;
if (!isspace_c(*keywd))
return;
/* Parse the format keyword, if any. */
got_key = 0;
if (!strcmp(key, "mag")) {
db = 0;
got_key = 1;
} else if (!strcmp(key, "db")) {
db = 1;
got_key = 1;
} else if (!strcmp(key, "rad")) {
rad = 1;
got_key = 1;
} else if (!strcmp(key, "deg")) {
rad = 0;
got_key = 1;
} else if (!strcmp(key, "r_i")) {
ri = 1;
got_key = 1;
}
/* Get the list of values. */
if (got_key)
list = skip_ws(keywd);
if (!list)
return;
keywd = list;
} while(got_key);
list_e = list + strlen(list) - 1;
skip_back_ws(list_e, list);
if (list >= list_e)
return;
/* All good, rewrite the line.
* Macro BSTR is used to pass counted string arguments to tprintf().
*/
#define BSTR(s) (int)(s##_e - s), s
pt = (*line == 'e') ? 'v' : 'i';
*line = '*'; // Make a comment
if (in) {
/* Connect input nodes directly. */
if (diff) {
/* Differential input. */
if (n2) {
line = tprintf("a_gen_%.*s %%vd(%.*s) %%%cd(%.*s %.*s) "
"gen_model_%.*s",
BSTR(e), BSTR(in), pt, BSTR(n1), BSTR(n2), BSTR(e));
} else {
line = tprintf("a_gen_%.*s %%vd(%.*s) %%%c(%.*s) "
"gen_model_%.*s",
BSTR(e), BSTR(in), pt, BSTR(n1), BSTR(e));
}
} else {
/* Single node input. */
if (n2) {
line = tprintf("a_gen_%.*s %.*s %%%cd(%.*s %.*s) "
"gen_model_%.*s",
BSTR(e), BSTR(in), pt, BSTR(n1), BSTR(n2),
BSTR(e));
} else {
line = tprintf("a_gen_%.*s %.*s %%%c(%.*s) gen_model_%.*s",
BSTR(e), BSTR(in), pt, BSTR(n1), BSTR(e));
}
}
} else {
/* Use a B-source for input. */
line = tprintf("b_gen_%.*s gen_node_%.*s 0 v=%.*s",
BSTR(e), BSTR(e), BSTR(expr));
c = insert_new_line(c, line, (*line_number)++, c->linenum_orig);
if (n2) {
line = tprintf("a_gen_%.*s gen_node_%.*s %%%cd(%.*s %.*s) "
"gen_model_%.*s",
BSTR(e), BSTR(e), pt, BSTR(n1), BSTR(n2), BSTR(e));
} else {
line = tprintf("a_gen_%.*s gen_node_%.*s %%%c(%.*s) "
"gen_model_%.*s",
BSTR(e), BSTR(e), pt, BSTR(n1), BSTR(e));
}
}
c = insert_new_line(c, line, (*line_number)++, c->linenum_orig);
line = tprintf(".model gen_model_%.*s xfer %s table = [%.*s]",
BSTR(e),
ri ? "r_i=true" : rad ? "rad=true" : !db ? "db=false" : "",
BSTR(list));
c = insert_new_line(c, line, (*line_number)++, c->linenum_orig);
#endif
}
/* Convert some E and G-source variants to XSPICE code models. */
static void inp_chk_for_e_source_to_xspice(struct card *c, int *line_number)
{ {
int skip_control = 0; int skip_control = 0;
@ -1945,143 +2380,17 @@ static void inp_chk_for_multi_in_vcvs(struct card *c, int *line_number)
continue; continue;
} }
if (*line == 'e') { if (*line == 'e' && inp_chk_for_multi_in_vcvs(c, line_number))
continue;
if (*line != 'e' && *line != 'g')
continue;
char *fcn_b; /* Is it the FREQ form with S-parameter table? */
if (((fcn_b = strstr(line, "nand(")) != NULL || replace_freq(c, line_number);
(fcn_b = strstr(line, "and(")) != NULL ||
(fcn_b = strstr(line, "nor(")) != NULL ||
(fcn_b = strstr(line, "or(")) != NULL) &&
isspace_c(fcn_b[-1])) {
#ifndef XSPICE
fprintf(stderr,
"\n"
"Error: XSPICE is required to run the 'multi-input "
"pwl' option in line %d\n"
" %s\n"
"\n"
"See manual chapt. 31 for installation "
"instructions\n",
*line_number, line);
controlled_exit(EXIT_BAD);
#else
char keep, *comma_ptr, *xy_values1[5], *xy_values2[5];
char *out_str, *ctrl_nodes_str,
*xy_values1_b = NULL, *ref_str, *fcn_name,
*fcn_e = NULL, *out_b, *out_e, *ref_e;
char *m_instance, *m_model;
char *xy_values2_b = NULL, *xy_values1_e = NULL,
*ctrl_nodes_b = NULL, *ctrl_nodes_e = NULL;
int xy_count1, xy_count2;
bool ok = FALSE;
do {
ref_e = skip_non_ws(line);
out_b = skip_ws(ref_e);
out_e = skip_back_ws(fcn_b, out_b);
if (out_e <= out_b)
break;
fcn_e = strchr(fcn_b, '(');
ctrl_nodes_b = strchr(fcn_e, ')');
if (!ctrl_nodes_b)
break;
ctrl_nodes_b = skip_ws(ctrl_nodes_b + 1);
comma_ptr = strchr(ctrl_nodes_b, ',');
if (!comma_ptr)
break;
xy_values1_b = skip_back_ws(comma_ptr, ctrl_nodes_b);
if (xy_values1_b[-1] == '}') {
while (--xy_values1_b >= ctrl_nodes_b)
if (*xy_values1_b == '{')
break;
}
else {
xy_values1_b =
skip_back_non_ws(xy_values1_b, ctrl_nodes_b);
}
if (xy_values1_b <= ctrl_nodes_b)
break;
ctrl_nodes_e = skip_back_ws(xy_values1_b, ctrl_nodes_b);
if (ctrl_nodes_e <= ctrl_nodes_b)
break;
xy_values1_e = skip_ws(comma_ptr + 1);
if (*xy_values1_e == '{') {
xy_values1_e = inp_spawn_brace(xy_values1_e);
}
else {
xy_values1_e = skip_non_ws(xy_values1_e);
}
if (!xy_values1_e)
break;
xy_values2_b = skip_ws(xy_values1_e);
ok = TRUE;
} while (0);
if (!ok) {
fprintf(stderr, "ERROR: malformed line: %s\n", line);
controlled_exit(EXIT_FAILURE);
}
ref_str = copy_substring(line, ref_e);
out_str = copy_substring(out_b, out_e);
fcn_name = copy_substring(fcn_b, fcn_e);
ctrl_nodes_str = copy_substring(ctrl_nodes_b, ctrl_nodes_e);
keep = *xy_values1_e;
*xy_values1_e = '\0';
xy_count1 =
get_comma_separated_values(xy_values1, xy_values1_b);
*xy_values1_e = keep;
xy_count2 =
get_comma_separated_values(xy_values2, xy_values2_b);
// place restrictions on only having 2 point values; this can
// change later
if (xy_count1 != 2 && xy_count2 != 2)
fprintf(stderr,
"ERROR: only expecting 2 pair values for "
"multi-input vcvs!\n");
m_instance = tprintf("%s %%vd[ %s ] %%vd( %s ) %s", ref_str,
ctrl_nodes_str, out_str, ref_str);
m_instance[0] = 'a';
m_model = tprintf(".model %s multi_input_pwl ( x = [%s %s] y "
"= [%s %s] model = \"%s\" )",
ref_str, xy_values1[0], xy_values2[0], xy_values1[1],
xy_values2[1], fcn_name);
tfree(ref_str);
tfree(out_str);
tfree(fcn_name);
tfree(ctrl_nodes_str);
tfree(xy_values1[0]);
tfree(xy_values1[1]);
tfree(xy_values2[0]);
tfree(xy_values2[1]);
*c->line = '*';
c = insert_new_line(c, m_instance, (*line_number)++, c->linenum_orig);
c = insert_new_line(c, m_model, (*line_number)++, c->linenum_orig);
#endif
}
}
} }
} }
/* If ngspice is started with option -a, then variable 'autorun' /* If ngspice is started with option -a, then variable 'autorun'
* will be set and a control section is inserted to try and ensure * will be set and a control section is inserted to try and ensure
* some analysis is done; * some analysis is done;
@ -3300,13 +3609,23 @@ static struct card *expand_section_ref(struct card *c, const char *dir_name)
* every library section reference (when the given section_name_ === NULL) * every library section reference (when the given section_name_ === NULL)
* or * or
* just those references occuring in the given library section definition * just those references occuring in the given library section definition
*
* Command .libsave saves the loaded and parsed lib, to be read by .include
*/ */
static void expand_section_references(struct card *c, const char *dir_name) static void expand_section_references(struct card *c, const char *dir_name)
{ {
for (; c; c = c->nextcard) for (; c; c = c->nextcard) {
if (ciprefix(".lib", c->line)) struct card* p = c;
if (ciprefix(".libsave", c->line)) {
c = expand_section_ref(c, dir_name); c = expand_section_ref(c, dir_name);
char *filename = libprint(p, dir_name);
fprintf(stdout, "\nLibrary\n%s\nsaved to %s\n", p->line + 9, filename);
tfree(filename);
}
else if (ciprefix(".lib", c->line))
c = expand_section_ref(c, dir_name);
}
} }
@ -4239,7 +4558,7 @@ static void inp_fix_param_values(struct card *c)
brackets around all params brackets around all params
inside a pair of square brackets */ inside a pair of square brackets */
end_of_str = beg_of_str; end_of_str = beg_of_str;
while (*end_of_str != ']') while (*end_of_str != ']' && *end_of_str != '\0')
end_of_str++; end_of_str++;
/* string xx yyy from vector [xx yyy] */ /* string xx yyy from vector [xx yyy] */
tmp_str = vec_str = tmp_str = vec_str =
@ -4315,7 +4634,7 @@ static void inp_fix_param_values(struct card *c)
/* A complex value following the '=' token: code to put curly /* A complex value following the '=' token: code to put curly
brackets around all params inside a pair < > */ brackets around all params inside a pair < > */
end_of_str = beg_of_str; end_of_str = beg_of_str;
while (*end_of_str != '>') while (*end_of_str != '>' && *end_of_str != '\0')
end_of_str++; end_of_str++;
/* string xx yyy from vector [xx yyy] */ /* string xx yyy from vector [xx yyy] */
vec_str = copy_substring(beg_of_str + 1, end_of_str); vec_str = copy_substring(beg_of_str + 1, end_of_str);
@ -4480,7 +4799,8 @@ static int inp_get_param_level(
return level; return level;
} }
/* Return the number of terminals for a given device, characterized by
the first letter of its instance line. Returns 0 upon error. */
int get_number_terminals(char *c) int get_number_terminals(char *c)
{ {
int i, j, k; int i, j, k;
@ -4488,6 +4808,9 @@ int get_number_terminals(char *c)
char nam_buf[128]; char nam_buf[128];
bool area_found = FALSE; bool area_found = FALSE;
if (!c)
return 0;
switch (*c) { switch (*c) {
case 'r': case 'r':
case 'c': case 'c':
@ -5917,14 +6240,9 @@ static void inp_compat(struct card *card)
/* Find equation, starts with '{', till end of line */ /* Find equation, starts with '{', till end of line */
str_ptr = strchr(cut_line, '{'); str_ptr = strchr(cut_line, '{');
if (str_ptr == NULL) { if (str_ptr == NULL) {
/* if not, equation may start with a '(' */ fprintf(stderr, "ERROR: mal formed R line: %s\n", curr_line);
str_ptr = strchr(cut_line, '('); fprintf(stderr, " {...} or '...' around equation's right hand side are missing!\n");
if (str_ptr == NULL) { controlled_exit(EXIT_FAILURE);
fprintf(stderr, "ERROR: mal formed R line: %s\n",
curr_line);
controlled_exit(EXIT_FAILURE);
}
equation = gettok_char(&str_ptr, ')', TRUE, TRUE);
} }
else else
equation = gettok_char(&str_ptr, '}', TRUE, TRUE); equation = gettok_char(&str_ptr, '}', TRUE, TRUE);
@ -6001,14 +6319,9 @@ static void inp_compat(struct card *card)
/* Find equation, starts with '{', till end of line */ /* Find equation, starts with '{', till end of line */
str_ptr = strchr(cut_line, '{'); str_ptr = strchr(cut_line, '{');
if (str_ptr == NULL) { if (str_ptr == NULL) {
/* if not, equation may start with a '(' */ fprintf(stderr, "ERROR: mal formed C line: %s\n", curr_line);
str_ptr = strchr(cut_line, '('); fprintf(stderr, " {...} or '...' around equation's right hand side are missing!\n");
if (str_ptr == NULL) { controlled_exit(EXIT_FAILURE);
fprintf(stderr, "ERROR: mal formed C line: %s\n",
curr_line);
controlled_exit(EXIT_FAILURE);
}
equation = gettok_char(&str_ptr, ')', TRUE, TRUE);
} }
else else
equation = gettok_char(&str_ptr, '}', TRUE, TRUE); equation = gettok_char(&str_ptr, '}', TRUE, TRUE);
@ -6076,14 +6389,9 @@ static void inp_compat(struct card *card)
/* Find equation, starts with '{', till end of line */ /* Find equation, starts with '{', till end of line */
str_ptr = strchr(cut_line, '{'); str_ptr = strchr(cut_line, '{');
if (str_ptr == NULL) { if (str_ptr == NULL) {
/* if not, equation may start with a '(' */ fprintf(stderr, "ERROR: mal formed L line: %s\n", curr_line);
str_ptr = strchr(cut_line, '('); fprintf(stderr, " {...} or '...' around equation's right hand side are missing!\n");
if (str_ptr == NULL) { controlled_exit(EXIT_FAILURE);
fprintf(stderr, "ERROR: mal formed L line: %s\n",
curr_line);
controlled_exit(EXIT_FAILURE);
}
equation = gettok_char(&str_ptr, ')', TRUE, TRUE);
} }
else else
equation = gettok_char(&str_ptr, '}', TRUE, TRUE); equation = gettok_char(&str_ptr, '}', TRUE, TRUE);
@ -6921,6 +7229,27 @@ static void inp_poly_err(struct card *card)
#endif #endif
/* Print the parsed library to lib_out?.lib, with ? a growing number
if multiple libs are saved in a single run. Don't save the .libsave line.*/
static char* libprint(struct card* t, const char *dir_name)
{
struct card* tmp;
static int npr = 1;
char *outfile = tprintf("%s/lib_out%d.lib", dir_name, npr);
npr++;
FILE* fd = fopen(outfile, "w");
if (fd) {
for (tmp = t; tmp; tmp = tmp->nextcard)
if (*(tmp->line) != '*' && !ciprefix(".libsave", tmp->line))
fprintf(fd, "%s\n", tmp->line);
fclose(fd);
}
else {
fprintf(stderr, "Warning: Can't open file %s \n command .libsave ignored!\n", outfile);
}
return outfile;
}
/* Used for debugging. You may add /* Used for debugging. You may add
* tprint(working); * tprint(working);
@ -8020,14 +8349,14 @@ static void inp_check_syntax(struct card *deck)
if (*cut_line == '*' || *cut_line == '\0') if (*cut_line == '*' || *cut_line == '\0')
continue; continue;
// check for unusable leading characters and change them to '*' // check for unusable leading characters and change them to '*'
if (strchr("=[]?()&%$\"!:,\f;", *cut_line)) { if (strchr("=[]?()&%$\"!:,\f", *cut_line)) {
if (ft_stricterror) { if (ft_stricterror) {
fprintf(stderr, "Error: '%c' is not allowed as first character in line %s.\n", *cut_line, cut_line); fprintf(stderr, "Error: '%c' is not allowed as first character in line %s.\n", *cut_line, cut_line);
controlled_exit(EXIT_BAD); controlled_exit(EXIT_BAD);
} }
else { else {
if (!check_ch) { if (!check_ch) {
fprintf(stderr, "Warning: Unusual leading characters like '%c' or others out of '= [] ? () & %% $\"!:,;\\f'\n", *cut_line); fprintf(stderr, "Warning: Unusual leading characters like '%c' or others out of '= [] ? () & %% $\"!:,\\f'\n", *cut_line);
fprintf(stderr, " in netlist or included files, will be replaced with '*'.\n"); fprintf(stderr, " in netlist or included files, will be replaced with '*'.\n");
fprintf(stderr, " Check line no %d: %s\n\n", card->linenum_orig, cut_line); fprintf(stderr, " Check line no %d: %s\n\n", card->linenum_orig, cut_line);
check_ch = 1; /* just one warning */ check_ch = 1; /* just one warning */
@ -8035,6 +8364,10 @@ static void inp_check_syntax(struct card *deck)
*cut_line = '*'; *cut_line = '*';
} }
} }
/* leading end-of-line delimiter ';' silently change to '*' */
else if (*cut_line == ';') {
*cut_line = '*';
}
// check for .control ... .endc // check for .control ... .endc
if (ciprefix(".control", cut_line)) { if (ciprefix(".control", cut_line)) {
if (check_control > 0) { if (check_control > 0) {
@ -8092,7 +8425,17 @@ static void inp_check_syntax(struct card *deck)
/* check for missing ac <val> in voltage or current source */ /* check for missing ac <val> in voltage or current source */
if (check_control == 0 && strchr("VvIi", *cut_line)) { if (check_control == 0 && strchr("VvIi", *cut_line)) {
int err = 0; int err = 0;
char* acline = search_plain_identifier(cut_line, "ac"); char* acline;
/* skip instance name and nodes */
acline = nexttok(cut_line);
acline = nexttok(acline);
acline = nexttok(acline);
if (!acline) {
fprintf(stderr, "Error in line %s\n", cut_line);
fprintf(stderr, " Not enough parameters\n");
controlled_exit(EXIT_BAD);
}
acline = search_plain_identifier(acline, "ac");
if (acline == NULL) if (acline == NULL)
continue; continue;
/* skip ac */ /* skip ac */
@ -8109,17 +8452,20 @@ static void inp_check_syntax(struct card *deck)
char* nnacline = nacline; char* nnacline = nacline;
/* get first token after ac */ /* get first token after ac */
char* numtok = gettok_node(&nnacline); char* numtok = gettok_node(&nnacline);
char* numtokfree = numtok; if (numtok) {
/* Check if token is a parameter, to be filled in later */ char* numtokfree = numtok;
if (*numtok == '\'' || *numtok == '{') { /* Check if token is a parameter, to be filled in later */
err = 0; if (*numtok == '\'' || *numtok == '{') {
err = 0;
}
else {
/* check if token is a valid number */
INPevaluate(&numtok, &err, 0);
}
tfree(numtokfree);
} }
else { else
/* check if token is a valid number */ err = 1;
INPevaluate(&numtok, &err, 0);
}
tfree(numtokfree);
} }
/* if no number, replace 'ac' by 'ac 1 0' */ /* if no number, replace 'ac' by 'ac 1 0' */
if (err){ if (err){
@ -8672,7 +9018,7 @@ utf8_syntax_check(struct card *deck)
s = utf8_check((unsigned char*)curr_line); s = utf8_check((unsigned char*)curr_line);
if (s) { if (s) {
fprintf(stderr, "Error: UTF-8 syntax error in line %d at %s\n", card->linenum_orig, s); fprintf(stderr, "Error: UTF-8 syntax error in input deck,\n line %d at token/word %s\n", card->linenum_orig, s);
controlled_exit(1); controlled_exit(1);
} }
} }

View File

@ -283,6 +283,22 @@ do_measure(
resname = gettok(&line); resname = gettok(&line);
meastype = gettok(&line); meastype = gettok(&line);
if (!an_type){
fprintf(cp_err, "\nWarning: Incomplete measurement statement in line\n %s\nignored!\n", meas_card->line);
continue;
}
if (!resname){
fprintf(cp_err, "\nWarning: Incomplete measurement statement in line\n %s\nignored!\n", meas_card->line);
tfree(an_type);
continue;
}
if (!meastype) {
fprintf(cp_err, "\nWarning: Incomplete measurement statement in line\n %s\nignored!\n", meas_card->line);
tfree(an_type);
tfree(resname);
continue;
}
if (chkAnalysisType(an_type) != TRUE) { if (chkAnalysisType(an_type) != TRUE) {
if (!chk_only) { if (!chk_only) {
fprintf(cp_err, "Error: unrecognized analysis type '%s' for the following .meas statement on line %d:\n", an_type, meas_card->linenum); fprintf(cp_err, "Error: unrecognized analysis type '%s' for the following .meas statement on line %d:\n", an_type, meas_card->linenum);
@ -399,6 +415,20 @@ do_measure(
resname = gettok(&line); resname = gettok(&line);
meastype = gettok(&line); meastype = gettok(&line);
if (!an_type) {
/* Warnings have already been issued in first pass */
continue;
}
if (!resname) {
tfree(an_type);
continue;
}
if (!meastype) {
tfree(an_type);
tfree(resname);
continue;
}
if (chkAnalysisType(an_type) != TRUE) { if (chkAnalysisType(an_type) != TRUE) {
if (!chk_only) { if (!chk_only) {
fprintf(cp_err, "Error: unrecognized analysis type '%s' for the following .meas statement on line %d:\n", an_type, meas_card->linenum); fprintf(cp_err, "Error: unrecognized analysis type '%s' for the following .meas statement on line %d:\n", an_type, meas_card->linenum);

View File

@ -1611,8 +1611,12 @@ nupa_subcktcall(dico_t *dico, const char *s, const char *x,
jp = getexpress(dico, NULL, &ustr, jp); jp = getexpress(dico, NULL, &ustr, jp);
} else { } else {
jp++; jp++;
if ((unsigned char) (*kp) > ' ') if ((unsigned char)(*kp) > ' ') {
message(dico, "Subckt call, symbol %c not understood\n", *kp); fprintf(stderr, "Error in line: %s\n", x);
fprintf(stderr, " near %s\n", kp);
message(dico, "Subckt call, symbol %c not understood\n\n", *kp);
}
} }
/* Substitute the parameter for one of the '$' characters /* Substitute the parameter for one of the '$' characters

View File

@ -627,7 +627,7 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr)
if (!orflag && !ft_norefprint) { if (!orflag && !ft_norefprint) {
currclock = clock(); currclock = clock();
if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) { if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) {
fprintf(stderr, " Reference value : % 12.5e\r", fprintf(stdout, " Reference value : % 12.5e\r",
refValue->cValue.real); refValue->cValue.real);
lastclock = currclock; lastclock = currclock;
} }
@ -640,7 +640,7 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr)
if (!orflag && !ft_norefprint) { if (!orflag && !ft_norefprint) {
currclock = clock(); currclock = clock();
if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) { if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) {
fprintf(stderr, " Reference value : % 12.5e\r", fprintf(stdout, " Reference value : % 12.5e\r",
refValue->rValue); refValue->rValue);
lastclock = currclock; lastclock = currclock;
} }
@ -735,10 +735,10 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr)
currclock = clock(); currclock = clock();
if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) { if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) {
if (run->isComplex) { if (run->isComplex) {
fprintf(stderr, " Reference value : % 12.5e\r", fprintf(stdout, " Reference value : % 12.5e\r",
refValue ? refValue->cValue.real : NAN); refValue ? refValue->cValue.real : NAN);
} else { } else {
fprintf(stderr, " Reference value : % 12.5e\r", fprintf(stdout, " Reference value : % 12.5e\r",
refValue ? refValue->rValue : NAN); refValue ? refValue->rValue : NAN);
} }
lastclock = currclock; lastclock = currclock;
@ -1506,7 +1506,7 @@ InterpFileAdd(runDesc *run, IFvalue *refValue, IFvalue *valuePtr)
if (!orflag && !ft_norefprint) { if (!orflag && !ft_norefprint) {
currclock = clock(); currclock = clock();
if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) { if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) {
fprintf(stderr, " Reference value : % 12.5e\r", fprintf(stdout, " Reference value : % 12.5e\r",
refValue->rValue); refValue->rValue);
lastclock = currclock; lastclock = currclock;
} }
@ -1670,7 +1670,7 @@ InterpPlotAdd(runDesc *run, IFvalue *refValue, IFvalue *valuePtr)
if (!orflag && !ft_norefprint) { if (!orflag && !ft_norefprint) {
currclock = clock(); currclock = clock();
if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) { if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) {
fprintf(stderr, " Reference value : % 12.5e\r", fprintf(stdout, " Reference value : % 12.5e\r",
refValue->rValue); refValue->rValue);
lastclock = currclock; lastclock = currclock;
} }

View File

@ -360,6 +360,7 @@ struct func ft_funcs[] = {
{ "avg", cx_avg }, /* A.Roldan 03/06/05 incremental average new function */ { "avg", cx_avg }, /* A.Roldan 03/06/05 incremental average new function */
{ "group_delay", (cx_function_t*)(void *) cx_group_delay }, /* A.Roldan 10/06/05 group delay new function */ { "group_delay", (cx_function_t*)(void *) cx_group_delay }, /* A.Roldan 10/06/05 group delay new function */
{ "vector", cx_vector }, { "vector", cx_vector },
{ "cvector", cx_cvector },
{ "unitvec", cx_unitvec }, { "unitvec", cx_unitvec },
{ "length", cx_length }, { "length", cx_length },
{ "vecmin", cx_min }, { "vecmin", cx_min },

View File

@ -37,8 +37,8 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
#include <sys/wait.h> #include <sys/wait.h>
#endif #endif
/* perform history substitution only when variable 'histsubst' is set */
bool cp_no_histsubst = FALSE; /* perform history substitution by default */ bool cp_no_histsubst = TRUE;
/* Things go as follows: /* Things go as follows:
* (1) Read the line and do some initial quoting (by setting the 8th bit), * (1) Read the line and do some initial quoting (by setting the 8th bit),

View File

@ -32,8 +32,7 @@ Author: 1988 Jeffrey M. Hsu
static void gr_start_internal(struct dvec *dv, bool copyvec); static void gr_start_internal(struct dvec *dv, bool copyvec);
static int iplot(struct plot *pl, int id); static void set(struct plot *plot, struct dbcomm *db, bool value, short mode);
static void set(struct plot *plot, struct dbcomm *db, bool unset, short mode);
static char *getitright(char *buf, double num); static char *getitright(char *buf, double num);
/* for legends, set in gr_start, reset in gr_iplot and gr_init */ /* for legends, set in gr_start, reset in gr_iplot and gr_init */
@ -844,28 +843,31 @@ void gr_restoretext(GRAPH *graph)
* XXX Or maybe even something more drastic ?? * XXX Or maybe even something more drastic ??
* It would be better to associate a color with an instance using a * It would be better to associate a color with an instance using a
* vector than the vector itself, for which color is something artificial. */ * vector than the vector itself, for which color is something artificial. */
static int iplot(struct plot *pl, int id) static int iplot(struct plot *pl, struct dbcomm *db)
{ {
int len = pl->pl_scale->v_length; double window;
int len = pl->pl_scale->v_length;
if (ft_grdb) { if (ft_grdb) {
fprintf(cp_err, "Entering iplot, len = %d\n", len); fprintf(cp_err, "Entering iplot, len = %d\n", len);
} }
/* Do simple check for exit first */ /* Do simple check for exit first */
if (len < IPOINTMIN) { /* Nothing yet */
window = db->db_value1;
if (len < 2 || (window == 0.0 && len < IPOINTMIN)) { /* Nothing yet */
return 0; return 0;
} }
struct dvec *v, *xs = pl->pl_scale; struct dvec *v, *xs = pl->pl_scale;
double *lims, dy; double *lims, dy;
double start, stop, step; double start, stop, step;
bool changed = FALSE; bool changed = FALSE;
int yt; int id, yt;
double xlims[2], ylims[2]; double xlims[2], ylims[2];
static REQUEST reqst = { checkup_option, NULL }; static REQUEST reqst = { checkup_option, NULL };
int inited = 0; int inited = 0;
int n_vec_plot = 0; int n_vec_plot = 0;
/* Exit if nothing is being plotted */ /* Exit if nothing is being plotted */
for (v = pl->pl_dvecs; v; v = v->v_next) { for (v = pl->pl_dvecs; v; v = v->v_next) {
@ -878,7 +880,8 @@ static int iplot(struct plot *pl, int id)
return 0; return 0;
} }
if (len == IPOINTMIN || !id) { /* Do initialization */ id = db->db_graphid;
if (!id) { /* Do initialization */
unsigned int index, node_len; unsigned int index, node_len;
char commandline[4196]; char commandline[4196];
@ -889,6 +892,14 @@ static int iplot(struct plot *pl, int id)
lims = ft_minmax(xs, TRUE); lims = ft_minmax(xs, TRUE);
xlims[0] = lims[0]; xlims[0] = lims[0];
xlims[1] = lims[1]; xlims[1] = lims[1];
if (window) {
if (xlims[1] - xlims[0] > window) {
xlims[1] += window / 3.0; // Assume increasing scale.
xlims[0] = xlims[1] - window;
} else {
xlims[1] = xlims[0] + window;
}
}
ylims[0] = HUGE; ylims[0] = HUGE;
ylims[1] = -ylims[0]; ylims[1] = -ylims[0];
for (v = pl->pl_dvecs; v; v = v->v_next) { for (v = pl->pl_dvecs; v; v = v->v_next) {
@ -918,7 +929,7 @@ static int iplot(struct plot *pl, int id)
if (ft_grdb) { if (ft_grdb) {
fprintf(cp_err, fprintf(cp_err,
"iplot: after 5, xlims = %G, %G, ylims = %G, %G\n", "iplot: at start xlims = %G, %G, ylims = %G, %G\n",
xlims[0], xlims[1], ylims[0], ylims[1]); xlims[0], xlims[1], ylims[0], ylims[1]);
} }
@ -943,9 +954,9 @@ static int iplot(struct plot *pl, int id)
} }
inited = 1; inited = 1;
} } else {
else {
/* plot the last points and resize if needed */ /* plot the last points and resize if needed */
Input(&reqst, NULL); Input(&reqst, NULL);
/* Window was closed? */ /* Window was closed? */
@ -954,6 +965,7 @@ static int iplot(struct plot *pl, int id)
return 0; return 0;
/* First see if we have to make the screen bigger */ /* First see if we have to make the screen bigger */
dy = (isreal(xs) ? xs->v_realdata[len - 1] : dy = (isreal(xs) ? xs->v_realdata[len - 1] :
realpart(xs->v_compdata[len - 1])); realpart(xs->v_compdata[len - 1]));
if (ft_grdb) { if (ft_grdb) {
@ -964,8 +976,10 @@ static int iplot(struct plot *pl, int id)
stop = HUGE; stop = HUGE;
start = - stop; start = - stop;
} }
/* checking for x lo */ /* checking for x lo */
while (dy < currentgraph->data.xmin) {
if (dy < currentgraph->data.xmin) {
changed = TRUE; changed = TRUE;
if (ft_grdb) { if (ft_grdb) {
fprintf(cp_err, "resize: xlo %G -> %G\n", fprintf(cp_err, "resize: xlo %G -> %G\n",
@ -974,20 +988,25 @@ static int iplot(struct plot *pl, int id)
(currentgraph->data.xmax - currentgraph->data.xmin) (currentgraph->data.xmax - currentgraph->data.xmin)
* XFACTOR); * XFACTOR);
} }
/* set the new x lo value */ /* set the new x lo value */
currentgraph->data.xmin -=
(currentgraph->data.xmax - currentgraph->data.xmin) if (window) {
* XFACTOR; currentgraph->data.xmin = dy - (window / 3.0);
if (currentgraph->data.xmin < start) { } else {
currentgraph->data.xmin = start; currentgraph->data.xmin -=
break; (currentgraph->data.xmax - currentgraph->data.xmin) *
XFACTOR;
} }
if (currentgraph->data.xmin < start)
currentgraph->data.xmin = start;
} }
if (currentgraph->data.xmax < currentgraph->data.xmin) {
currentgraph->data.xmax = currentgraph->data.xmin;
}
/* checking for x hi */ /* checking for x hi */
while (dy > currentgraph->data.xmax) {
if (window && changed) {
currentgraph->data.xmax = currentgraph->data.xmin + window;
} else if (dy > currentgraph->data.xmax) {
changed = TRUE; changed = TRUE;
if (ft_grdb) { if (ft_grdb) {
fprintf(cp_err, "resize: xhi %G -> %G\n", fprintf(cp_err, "resize: xhi %G -> %G\n",
@ -996,16 +1015,26 @@ static int iplot(struct plot *pl, int id)
(currentgraph->data.xmax - currentgraph->data.xmin) (currentgraph->data.xmax - currentgraph->data.xmin)
* XFACTOR); * XFACTOR);
} }
/* set the new x hi value */ /* set the new x hi value */
currentgraph->data.xmax +=
(currentgraph->data.xmax - currentgraph->data.xmin) * if (window) {
XFACTOR; currentgraph->data.xmax = dy + (window / 3.0);
if (currentgraph->data.xmax > stop) { currentgraph->data.xmin = currentgraph->data.xmax - window;
currentgraph->data.xmax = stop; } else {
break; currentgraph->data.xmax +=
(currentgraph->data.xmax - currentgraph->data.xmin) *
XFACTOR;
} }
if (currentgraph->data.xmax > stop)
currentgraph->data.xmax = stop;
} }
if (currentgraph->data.xmax < currentgraph->data.xmin)
currentgraph->data.xmax = currentgraph->data.xmin;
/* checking for all y values */ /* checking for all y values */
for (v = pl->pl_dvecs; v; v = v->v_next) { for (v = pl->pl_dvecs; v; v = v->v_next) {
if (!(v->v_flags & VF_PLOT)) { if (!(v->v_flags & VF_PLOT)) {
continue; continue;
@ -1034,10 +1063,9 @@ static int iplot(struct plot *pl, int id)
/* currentgraph->data.ymin = dy; /* currentgraph->data.ymin = dy;
currentgraph->data.ymin *= (1 + YFACTOR); */ currentgraph->data.ymin *= (1 + YFACTOR); */
} }
if (currentgraph->data.ymax < currentgraph->data.ymin) {
currentgraph->data.ymax = currentgraph->data.ymin;
}
/* checking for y hi */ /* checking for y hi */
while (dy > currentgraph->data.ymax) { while (dy > currentgraph->data.ymax) {
changed = TRUE; changed = TRUE;
if (ft_grdb) { if (ft_grdb) {
@ -1049,8 +1077,8 @@ static int iplot(struct plot *pl, int id)
} }
/* set the new y hi value */ /* set the new y hi value */
currentgraph->data.ymax += currentgraph->data.ymax +=
(currentgraph->data.ymax - currentgraph->data.ymin) (currentgraph->data.ymax - currentgraph->data.ymin) *
* YFACTOR; YFACTOR;
/* currentgraph->data.ymax += /* currentgraph->data.ymax +=
(dy - currentgraph->data.ymax) * YFACTOR;*/ (dy - currentgraph->data.ymax) * YFACTOR;*/
/* currentgraph->data.ymax = dy; /* currentgraph->data.ymax = dy;
@ -1058,6 +1086,9 @@ static int iplot(struct plot *pl, int id)
} }
} }
if (currentgraph->data.ymax < currentgraph->data.ymin)
currentgraph->data.ymax = currentgraph->data.ymin;
if (changed) { if (changed) {
/* Redraw everything. */ /* Redraw everything. */
gr_pmsg("Resizing screen"); gr_pmsg("Resizing screen");
@ -1094,17 +1125,17 @@ static int iplot(struct plot *pl, int id)
} }
static void set(struct plot *plot, struct dbcomm *db, bool unset, short mode) static void set(struct plot *plot, struct dbcomm *db, bool value, short mode)
{ {
struct dvec *v; struct dvec *v;
struct dbcomm *dc; struct dbcomm *dc;
if (db->db_type == DB_IPLOTALL || db->db_type == DB_TRACEALL) { if (db->db_type == DB_IPLOTALL || db->db_type == DB_TRACEALL) {
for (v = plot->pl_dvecs; v; v = v->v_next) for (v = plot->pl_dvecs; v; v = v->v_next)
if (unset) if (value)
v->v_flags &= (short) ~mode;
else
v->v_flags |= mode; v->v_flags |= mode;
else
v->v_flags &= (short) ~mode;
return; return;
} }
@ -1113,17 +1144,17 @@ static void set(struct plot *plot, struct dbcomm *db, bool unset, short mode)
continue; continue;
v = vec_fromplot(dc->db_nodename1, plot); v = vec_fromplot(dc->db_nodename1, plot);
if (!v || v->v_plot != plot) { if (!v || v->v_plot != plot) {
if (!eq(dc->db_nodename1, "0") && !unset) { if (!eq(dc->db_nodename1, "0") && value) {
fprintf(cp_err, "Warning: node %s non-existent in %s.\n", fprintf(cp_err, "Warning: node %s non-existent in %s.\n",
dc->db_nodename1, plot->pl_name); dc->db_nodename1, plot->pl_name);
/* note: XXX remove it from dbs, so won't get further errors */ /* note: XXX remove it from dbs, so won't get further errors */
} }
continue; continue;
} }
if (unset) if (value)
v->v_flags &= (short) ~mode;
else
v->v_flags |= mode; v->v_flags |= mode;
else
v->v_flags &= (short) ~mode;
} }
} }
@ -1176,16 +1207,18 @@ void gr_iplot(struct plot *plot)
PushGraphContext(gr); PushGraphContext(gr);
} }
set(plot, db, FALSE, VF_PLOT); /* Temporarily set plot flag on matching vector. */
set(plot, db, TRUE, VF_PLOT);
dontpop = 0; dontpop = 0;
if (iplot(plot, db->db_graphid)) { if (iplot(plot, db)) {
/* graph just assigned */ /* graph just assigned */
db->db_graphid = currentgraph->graphid; db->db_graphid = currentgraph->graphid;
dontpop = 1; dontpop = 1;
} }
set(plot, db, TRUE, VF_PLOT); set(plot, db, FALSE, VF_PLOT);
if (!dontpop && db->db_graphid) if (!dontpop && db->db_graphid)
PopGraphContext(); PopGraphContext();
@ -1195,7 +1228,7 @@ void gr_iplot(struct plot *plot)
struct dvec *v, *u; struct dvec *v, *u;
int len; int len;
set(plot, db, FALSE, VF_PRINT); set(plot, db, TRUE, VF_PRINT);
len = plot->pl_scale->v_length; len = plot->pl_scale->v_length;
@ -1251,7 +1284,7 @@ void gr_iplot(struct plot *plot)
printf("\n"); printf("\n");
} }
} }
set(plot, db, TRUE, VF_PRINT); set(plot, db, FALSE, VF_PRINT);
} }
} }
} }

View File

@ -1147,7 +1147,9 @@ translate(struct card *deck, char *formal, int flen, char *actual, char *scname,
char *next_name, *name, *t, *nametofree, *paren_ptr; char *next_name, *name, *t, *nametofree, *paren_ptr;
int nnodes, i, dim; int nnodes, i, dim;
int rtn = 0; int rtn = 0;
#ifdef XSPICE
bool got_vnam = FALSE;
#endif
bxx_init(&buffer); bxx_init(&buffer);
/* settrans builds the table holding the translated netnames. */ /* settrans builds the table holding the translated netnames. */
@ -1165,7 +1167,6 @@ translate(struct card *deck, char *formal, int flen, char *actual, char *scname,
} }
for (c = deck; c; c = c->nextcard) { for (c = deck; c; c = c->nextcard) {
bool got_vnam = FALSE;
char *s = c->line; char *s = c->line;
char dev_type = tolower_c(s[0]); char dev_type = tolower_c(s[0]);

View File

@ -93,6 +93,7 @@ extern void *cx_mean(void *, short int , int , int *, short int *);
extern void *cx_stddev(void *, short int , int , int *, short int *); extern void *cx_stddev(void *, short int , int , int *, short int *);
extern void *cx_length(void *, short int , int , int *, short int *); extern void *cx_length(void *, short int , int , int *, short int *);
extern void *cx_vector(void *, short int , int , int *, short int *); extern void *cx_vector(void *, short int , int , int *, short int *);
extern void *cx_cvector(void *, short int , int , int *, short int *);
extern void *cx_unitvec(void *, short int , int , int *, short int *); extern void *cx_unitvec(void *, short int , int , int *, short int *);
extern void *cx_plus(void *, void *, short int , short int , int ); extern void *cx_plus(void *, void *, short int , short int , int );
extern void *cx_minus(void *, void *, short int , short int , int ); extern void *cx_minus(void *, void *, short int , short int , int );

View File

@ -34,7 +34,8 @@ Author: 1986 Thomas L. Quarles
#define E_NOCHANGE 13 /* simulator can't tolerate any more topology changes */ #define E_NOCHANGE 13 /* simulator can't tolerate any more topology changes */
#define E_NOTFOUND 14 /* simulator can't find something it was looking for */ #define E_NOTFOUND 14 /* simulator can't find something it was looking for */
#define E_BAD_DOMAIN 15 /* output interface begin/end domain calls mismatched */ #define E_BAD_DOMAIN 15 /* output interface begin/end domain calls mismatched */
#define E_EXISTS_BAD 16 /* error - attempt to create duplicate */
/* instance or model. Bail out. */
#define E_PRIVATE 100 /* messages above this number are private to */ #define E_PRIVATE 100 /* messages above this number are private to */
/* the simulator and MUST be accompanied by */ /* the simulator and MUST be accompanied by */

View File

@ -19,6 +19,7 @@ typedef struct OsdiRegistryEntry {
uint32_t inst_offset; uint32_t inst_offset;
uint32_t dt; uint32_t dt;
uint32_t temp; uint32_t temp;
bool has_m;
} OsdiRegistryEntry; } OsdiRegistryEntry;
typedef struct OsdiObjectFile { typedef struct OsdiObjectFile {

View File

@ -4,7 +4,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
**********/ **********/
/** \file cmath2.c /** \file cmath2.c
\brief functions for the control language parser: norm, uminus, rnd, sunif, sgauss, poisson, exponential, mean, stddev, length, vector, unitvec, plus, minus, times, mod, max, min, d, avg, floor, ceil, nint \brief functions for the control language parser: norm, uminus, rnd, sunif, sgauss, poisson, exponential, mean, stddev, length, vector, cvector, unitvec, plus, minus, times, mod, max, min, d, avg, floor, ceil, nint
Routines to do complex mathematical functions. These routines require Routines to do complex mathematical functions. These routines require
the -lm libraries. We sacrifice a lot of space to be able the -lm libraries. We sacrifice a lot of space to be able
@ -479,7 +479,7 @@ cx_length(void *data, short int type, int length, int *newlength, short int *new
/* Return a vector from 0 to the magnitude of the argument. Length of the /* Return a vector from 0 to the magnitude of the argument. Length of the
* argument is irrelevent. * argument is irrelevant.
*/ */
void * void *
@ -506,6 +506,38 @@ cx_vector(void *data, short int type, int length, int *newlength, short int *new
return ((void *) d); return ((void *) d);
} }
/* Return a complex vector. Argument sets the length of the vector.
The real part ranges from 0 to the magnitude of the argument. The imaginary
part is set to 0.
*/
void*
cx_cvector(void* data, short int type, int length, int* newlength, short int* newtype)
{
ngcomplex_t* cc = (ngcomplex_t*)data;
double* dd = (double*)data;
int i, len;
ngcomplex_t* d;
NG_IGNORE(length);
if (type == VF_REAL)
len = (int)fabs(*dd);
else
len = (int)cmag(*cc);
if (len == 0)
len = 1;
d = alloc_c(len);
*newlength = len;
*newtype = VF_COMPLEX;
for (i = 0; i < len; i++) {
realpart(d[i]) = i;
imagpart(d[i]) = 0;
}
return ((void*)d);
}
/* Create a vector of the given length composed of all ones. */ /* Create a vector of the given length composed of all ones. */

View File

@ -16,7 +16,6 @@ Author: 1985 Thomas L. Quarles
void void
NIdestroy(CKTcircuit *ckt) NIdestroy(CKTcircuit *ckt)
{ {
int i;
if (ckt->CKTmatrix) if (ckt->CKTmatrix)
SMPdestroy(ckt->CKTmatrix); SMPdestroy(ckt->CKTmatrix);
ckt->CKTmatrix = NULL; ckt->CKTmatrix = NULL;
@ -36,7 +35,7 @@ NIdestroy(CKTcircuit *ckt)
#endif #endif
#ifdef PREDICTOR #ifdef PREDICTOR
if(ckt->CKTpred) FREE(ckt->CKTpred); if(ckt->CKTpred) FREE(ckt->CKTpred);
for( i=0;i<8;i++) { for(int i=0;i<8;i++) {
if(ckt->CKTsols[i]) FREE(ckt->CKTsols[i]); if(ckt->CKTsols[i]) FREE(ckt->CKTsols[i]);
} }
#endif #endif

View File

@ -22,7 +22,6 @@ Modified: 2001 AlansFixes
/* Limit the number of 'singular matrix' warnings */ /* Limit the number of 'singular matrix' warnings */
static int msgcount = 0; static int msgcount = 0;
void NIresetwarnmsg(void);
/* NIiter() - return value is non-zero for convergence failure */ /* NIiter() - return value is non-zero for convergence failure */

View File

@ -32,7 +32,7 @@
* descr->param_opvar to the internal ngspice representation (IFparm). * descr->param_opvar to the internal ngspice representation (IFparm).
*/ */
static int write_param_info(IFparm **dst, const OsdiDescriptor *descr, static int write_param_info(IFparm **dst, const OsdiDescriptor *descr,
uint32_t start, uint32_t end) { uint32_t start, uint32_t end, bool has_m) {
for (uint32_t i = start; i < end; i++) { for (uint32_t i = start; i < end; i++) {
OsdiParamOpvar *para = &descr->param_opvar[i]; OsdiParamOpvar *para = &descr->param_opvar[i];
uint32_t num_names = para->num_alias + 1; uint32_t num_names = para->num_alias + 1;
@ -68,12 +68,23 @@ static int write_param_info(IFparm **dst, const OsdiDescriptor *descr,
dataType |= IF_UNINTERESTING; dataType |= IF_UNINTERESTING;
} }
char *para_name = copy(para->name[j]); char *para_name = copy(para->name[j]);
if (para_name[0] == '$') {
para_name[0] = '_';
}
strtolower(para_name); strtolower(para_name);
(*dst)[j] = (IFparm){.keyword = para_name, (*dst)[j] = (IFparm){.keyword = para_name,
.id = (int)i, .id = (int)i,
.description = para->description, .description = para->description,
.dataType = dataType}; .dataType = dataType};
} }
if (!has_m && !strcmp(para->name[0], "$mfactor")) {
(*dst)[num_names] = (IFparm){.keyword = "m",
.id = (int)i,
.description = para->description,
.dataType = dataType};
*dst += 1;
}
*dst += num_names; *dst += num_names;
} }
@ -110,6 +121,10 @@ extern SPICEdev *osdi_create_spicedev(const OsdiRegistryEntry *entry) {
*num_instance_para_names += 1; *num_instance_para_names += 1;
} }
if (!entry->has_m) {
*num_instance_para_names += 1;
}
IFparm *instance_para_names = TMALLOC(IFparm, *num_instance_para_names); IFparm *instance_para_names = TMALLOC(IFparm, *num_instance_para_names);
IFparm *dst = instance_para_names; IFparm *dst = instance_para_names;
@ -124,9 +139,9 @@ extern SPICEdev *osdi_create_spicedev(const OsdiRegistryEntry *entry) {
"Instance temperature"}; "Instance temperature"};
dst += 1; dst += 1;
} }
write_param_info(&dst, descr, 0, descr->num_instance_params); write_param_info(&dst, descr, 0, descr->num_instance_params, entry->has_m);
write_param_info(&dst, descr, descr->num_params, write_param_info(&dst, descr, descr->num_params,
descr->num_params + descr->num_opvars); descr->num_params + descr->num_opvars, true);
// allocate and fill model params // allocate and fill model params
int *num_model_para_names = TMALLOC(int, 1); int *num_model_para_names = TMALLOC(int, 1);
@ -135,7 +150,8 @@ extern SPICEdev *osdi_create_spicedev(const OsdiRegistryEntry *entry) {
} }
IFparm *model_para_names = TMALLOC(IFparm, *num_model_para_names); IFparm *model_para_names = TMALLOC(IFparm, *num_model_para_names);
dst = model_para_names; dst = model_para_names;
write_param_info(&dst, descr, descr->num_instance_params, descr->num_params); write_param_info(&dst, descr, descr->num_instance_params, descr->num_params,
true);
// Allocate SPICE device // Allocate SPICE device
SPICEdev *OSDIinfo = TMALLOC(SPICEdev, 1); SPICEdev *OSDIinfo = TMALLOC(SPICEdev, 1);
@ -181,7 +197,5 @@ extern SPICEdev *osdi_create_spicedev(const OsdiRegistryEntry *entry) {
OSDIinfo->DEVpzLoad = OSDIpzLoad; OSDIinfo->DEVpzLoad = OSDIpzLoad;
OSDIinfo->DEVtrunc = OSDItrunc; OSDIinfo->DEVtrunc = OSDItrunc;
return OSDIinfo; return OSDIinfo;
} }

View File

@ -358,12 +358,15 @@ extern OsdiObjectFile load_object_file(const char *input) {
const OsdiDescriptor *descr = &OSDI_DESCRIPTORS[i]; const OsdiDescriptor *descr = &OSDI_DESCRIPTORS[i];
uint32_t dt = descr->num_params + descr->num_opvars; uint32_t dt = descr->num_params + descr->num_opvars;
bool has_m = false;
uint32_t temp = descr->num_params + descr->num_opvars + 1; uint32_t temp = descr->num_params + descr->num_opvars + 1;
for (uint32_t param_id = 0; param_id < descr->num_params; param_id++) { for (uint32_t param_id = 0; param_id < descr->num_params; param_id++) {
OsdiParamOpvar *param = &descr->param_opvar[param_id]; OsdiParamOpvar *param = &descr->param_opvar[param_id];
for (uint32_t j = 0; j < 1 + param->num_alias; j++) { for (uint32_t j = 0; j < 1 + param->num_alias; j++) {
char *name = param->name[j]; char *name = param->name[j];
if (!strcmp(name, "dt")) { if (!strcmp(name, "m")) {
has_m = true;
} else if (!strcmp(name, "dt")) {
dt = UINT32_MAX; dt = UINT32_MAX;
} else if (!strcasecmp(name, "dtemp") || !strcasecmp(name, "dt")) { } else if (!strcasecmp(name, "dtemp") || !strcasecmp(name, "dt")) {
dt = param_id; dt = param_id;
@ -382,6 +385,7 @@ extern OsdiObjectFile load_object_file(const char *input) {
.inst_offset = (uint32_t)inst_off, .inst_offset = (uint32_t)inst_off,
.dt = dt, .dt = dt,
.temp = temp, .temp = temp,
.has_m = has_m,
}; };
} }

View File

@ -186,7 +186,7 @@ int OSDIsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt,
OsdiInitInfo init_info; OsdiInitInfo init_info;
OsdiNgspiceHandle handle; OsdiNgspiceHandle handle;
GENmodel *gen_model; GENmodel *gen_model;
int res; int res = (OK);
int error; int error;
CKTnode *tmp; CKTnode *tmp;
GENinstance *gen_inst; GENinstance *gen_inst;
@ -304,7 +304,7 @@ extern int OSDItemp(GENmodel *inModel, CKTcircuit *ckt) {
OsdiInitInfo init_info; OsdiInitInfo init_info;
OsdiNgspiceHandle handle; OsdiNgspiceHandle handle;
GENmodel *gen_model; GENmodel *gen_model;
int res; int res = (OK);
GENinstance *gen_inst; GENinstance *gen_inst;
OsdiRegistryEntry *entry = osdi_reg_entry_model(inModel); OsdiRegistryEntry *entry = osdi_reg_entry_model(inModel);

View File

@ -14,6 +14,7 @@ Author: 1985 Thomas L. Quarles
#include "ngspice/cktdefs.h" #include "ngspice/cktdefs.h"
#include "ngspice/devdefs.h" #include "ngspice/devdefs.h"
#include "ngspice/sperror.h" #include "ngspice/sperror.h"
#include "ngspice/fteext.h"
#ifdef XSPICE #ifdef XSPICE
#include "ngspice/enh.h" #include "ngspice/enh.h"
@ -43,6 +44,20 @@ CKTsetup(CKTcircuit *ckt)
/* gtri - end - Setup for adding rshunt option resistors */ /* gtri - end - Setup for adding rshunt option resistors */
#endif #endif
SMPmatrix *matrix; SMPmatrix *matrix;
if (!ckt->CKThead) {
fprintf(stderr, "Error: No model list found, device setup not possible!\n");
if (ft_stricterror)
controlled_exit(EXIT_BAD);
return E_PANIC;
}
if (!DEVices) {
fprintf(stderr, "Error: No device list found, device setup not possible!\n");
if (ft_stricterror)
controlled_exit(EXIT_BAD);
return E_PANIC;
}
ckt->CKTnumStates=0; ckt->CKTnumStates=0;
#ifdef WANT_SENSE2 #ifdef WANT_SENSE2
@ -57,7 +72,9 @@ CKTsetup(CKTcircuit *ckt)
return E_NOCHANGE; return E_NOCHANGE;
error = NIinit(ckt); error = NIinit(ckt);
if (error) return(error); if (error)
return(error);
ckt->CKTisSetup = 1; ckt->CKTisSetup = 1;
matrix = ckt->CKTmatrix; matrix = ckt->CKTmatrix;

View File

@ -194,7 +194,7 @@ DCpss(CKTcircuit *ckt,
else else
maxstepsize = ckt->CKTmaxStep; maxstepsize = ckt->CKTmaxStep;
ckt->CKTsizeIncr = 10; ckt->CKTsizeIncr = 100;
ckt->CKTtimeIndex = -1; /* before the DC soln has been stored */ ckt->CKTtimeIndex = -1; /* before the DC soln has been stored */
ckt->CKTtimeListSize = (int)(1 / ckt->CKTguessedFreq / maxstepsize + 0.5); ckt->CKTtimeListSize = (int)(1 / ckt->CKTguessedFreq / maxstepsize + 0.5);
ltra_num = CKTtypelook("LTRA"); ltra_num = CKTtypelook("LTRA");

View File

@ -123,7 +123,7 @@ DCtran(CKTcircuit *ckt,
else else
maxstepsize = ckt->CKTmaxStep; maxstepsize = ckt->CKTmaxStep;
ckt->CKTsizeIncr = 10; ckt->CKTsizeIncr = 100;
ckt->CKTtimeIndex = -1; /* before the DC soln has been stored */ ckt->CKTtimeIndex = -1; /* before the DC soln has been stored */
ckt->CKTtimeListSize = (int) ceil( ckt->CKTfinalTime / maxstepsize ); ckt->CKTtimeListSize = (int) ceil( ckt->CKTfinalTime / maxstepsize );
ltra_num = CKTtypelook("LTRA"); ltra_num = CKTtypelook("LTRA");

View File

@ -232,16 +232,16 @@ NOISEan(CKTcircuit* ckt, int restart)
error = CKTload(ckt); error = CKTload(ckt);
if (error) return(error); if (error) return(error);
error = CKTnames(ckt, &numNames, &nameList);
if (error) return(error);
if (ckt->CKTkeepOpInfo) { if (ckt->CKTkeepOpInfo) {
error = CKTnames(ckt, &numNames, &nameList);
if (error) return(error);
/* Dump operating point. */ /* Dump operating point. */
error = SPfrontEnd->OUTpBeginPlot(ckt, ckt->CKTcurJob, error = SPfrontEnd->OUTpBeginPlot(ckt, ckt->CKTcurJob,
"NOISE Operating Point", "NOISE Operating Point",
NULL, IF_REAL, NULL, IF_REAL,
numNames, nameList, IF_REAL, numNames, nameList, IF_REAL,
&plot); &plot);
txfree(nameList);
if (error) return(error); if (error) return(error);
CKTdump(ckt, 0.0, plot); CKTdump(ckt, 0.0, plot);
SPfrontEnd->OUTendPlot(plot); SPfrontEnd->OUTendPlot(plot);

View File

@ -100,6 +100,11 @@ void com_optran(wordlist* wl) {
getdata = TRUE; getdata = TRUE;
} }
if (!getdata && !ft_curckt) {
/* no circuit, but optran already set */
return;
}
int saved = errno; int saved = errno;
errno = 0; errno = 0;
nooptran = FALSE; nooptran = FALSE;
@ -159,14 +164,14 @@ void com_optran(wordlist* wl) {
if (err || (*stpstr != '\0')) if (err || (*stpstr != '\0'))
goto bugquit; goto bugquit;
if (opstepsize > opfinaltime) { if (opstepsize > opfinaltime) {
fprintf(stderr, "Error: Step size larger than final time.\n"); fprintf(stderr, "Error: Optran step size larger than final time.\n");
goto bugquit; goto bugquit;
} }
if (opstepsize > opfinaltime/50.) { if (opstepsize > opfinaltime/50.) {
fprintf(stderr, "Warning: Step size potentially too small.\n"); fprintf(stderr, "Warning: Optran step size potentially too large.\n");
} }
if (opramptime > opfinaltime) { if (opramptime > opfinaltime) {
fprintf(stderr, "Error: Ramp time larger than final time.\n"); fprintf(stderr, "Error: Optran ramp time larger than final time.\n");
goto bugquit; goto bugquit;
} }
/* optran deselected by setting opstepsize to 0 */ /* optran deselected by setting opstepsize to 0 */
@ -362,7 +367,7 @@ OPtran(CKTcircuit *ckt, int oldconverged)
else else
maxstepsize = ckt->CKTmaxStep; maxstepsize = ckt->CKTmaxStep;
ckt->CKTsizeIncr = 10; ckt->CKTsizeIncr = 100;
ckt->CKTtimeIndex = -1; /* before the DC soln has been stored */ ckt->CKTtimeIndex = -1; /* before the DC soln has been stored */
ckt->CKTtimeListSize = (int) ceil( opfinaltime / maxstepsize ); ckt->CKTtimeListSize = (int) ceil( opfinaltime / maxstepsize );
ltra_num = CKTtypelook("LTRA"); ltra_num = CKTtypelook("LTRA");
@ -657,7 +662,7 @@ resume:
/* supply ramping, when opramptime > 0 */ /* supply ramping, when opramptime > 0 */
if (opramptime > 0) if (opramptime > 0)
ckt->CKTsrcFact = MIN(1., optime / opramptime); ckt->CKTsrcFact = 0.5 * (1 - cos(M_PI * optime / opramptime));
ckt->CKTdeltaOld[0]=ckt->CKTdelta; ckt->CKTdeltaOld[0]=ckt->CKTdelta;
NIcomCof(ckt); NIcomCof(ckt);

View File

@ -32,7 +32,7 @@ CKTcrtElt(CKTcircuit *ckt, GENmodel *modPtr, GENinstance **inInstPtr, IFuid name
if (instPtr) { if (instPtr) {
if (inInstPtr) if (inInstPtr)
*inInstPtr = instPtr; *inInstPtr = instPtr;
return E_EXISTS; return E_EXISTS_BAD;
} }
type = modPtr->GENmodType; type = modPtr->GENmodType;

View File

@ -29,16 +29,13 @@ CKTinit(CKTcircuit **ckt) /* new circuit to create */
CKTcircuit *sckt = TMALLOC(CKTcircuit, 1); CKTcircuit *sckt = TMALLOC(CKTcircuit, 1);
*ckt = sckt; *ckt = sckt;
if (sckt == NULL) if (sckt == NULL)
return(E_NOMEM); return(E_NOMEM);
/* gtri - begin - dynamically allocate the array of model lists */
/* CKThead used to be statically sized in CKTdefs.h, but has been changed */ /* dynamically allocate the array of model lists */
/* to a ** pointer */
sckt->CKThead = TMALLOC(GENmodel *, DEVmaxnum); sckt->CKThead = TMALLOC(GENmodel *, DEVmaxnum);
if(sckt->CKThead == NULL) return(E_NOMEM); if(sckt->CKThead == NULL)
/* gtri - end - dynamically allocate the array of model lists */ return(E_NOMEM);
for (i = 0; i < DEVmaxnum; i++) for (i = 0; i < DEVmaxnum; i++)
sckt->CKThead[i] = NULL; sckt->CKThead[i] = NULL;

View File

@ -10,285 +10,283 @@ Author: 1990 Jaijeet S. Roychowdhury
#include "ngspice/suffix.h" #include "ngspice/suffix.h"
int int
LTRAaccept(CKTcircuit *ckt, GENmodel *inModel) LTRAaccept(CKTcircuit* ckt, GENmodel* inModel)
{ {
LTRAmodel *model = (LTRAmodel *) inModel; LTRAmodel* model = (LTRAmodel*)inModel;
LTRAinstance *here; LTRAinstance* here;
double v1, v2, v3, v4; double v1, v2, v3, v4;
double v5, v6, d1, d2, d3, d4; double v5, v6, d1, d2, d3, d4;
int tmp_test; int tmp_test;
int error; int error;
int compact = 1; int compact = 1;
/* loop through all the transmission line models */ /* loop through all the transmission line models */
for (; model != NULL; model = LTRAnextModel(model)) { for (; model != NULL; model = LTRAnextModel(model)) {
if (ckt->CKTmode & MODEINITTRAN) { if (ckt->CKTmode & MODEINITTRAN) {
#define LTRAmemMANAGE(a,b) \ #define LTRAmemMANAGE(a,b) \
if ( a != NULL) FREE(a);\ if ( a != NULL) FREE(a);\
a = TMALLOC(double, b); a = TMALLOC(double, b);
model->LTRAmodelListSize = 10; model->LTRAmodelListSize = 100;
LTRAmemMANAGE(model->LTRAh1dashCoeffs, model->LTRAmodelListSize)
LTRAmemMANAGE(model->LTRAh2Coeffs, model->LTRAmodelListSize)
LTRAmemMANAGE(model->LTRAh3dashCoeffs, model->LTRAmodelListSize)
}
if (ckt->CKTtimeIndex >= model->LTRAmodelListSize) { /* need more space */
model->LTRAmodelListSize += ckt->CKTsizeIncr;
LTRAmemMANAGE(model->LTRAh1dashCoeffs, model->LTRAmodelListSize) model->LTRAh1dashCoeffs = TREALLOC(double, model->LTRAh1dashCoeffs, model->LTRAmodelListSize);
LTRAmemMANAGE(model->LTRAh2Coeffs, model->LTRAmodelListSize) model->LTRAh2Coeffs = TREALLOC(double, model->LTRAh2Coeffs, model->LTRAmodelListSize);
LTRAmemMANAGE(model->LTRAh3dashCoeffs, model->LTRAmodelListSize) model->LTRAh3dashCoeffs = TREALLOC(double, model->LTRAh3dashCoeffs, model->LTRAmodelListSize);
} }
if (ckt->CKTtimeIndex >= model->LTRAmodelListSize) { /* need more space */ /* loop through all the instances of the model */
model->LTRAmodelListSize += ckt->CKTsizeIncr; for (here = LTRAinstances(model); here != NULL;
here = LTRAnextInstance(here)) {
if (ckt->CKTmode & MODEINITTRAN) {
here->LTRAinstListSize = (int)MAX(10, ckt->CKTtimeListSize);
model->LTRAh1dashCoeffs = TREALLOC(double, model->LTRAh1dashCoeffs, model->LTRAmodelListSize); LTRAmemMANAGE(here->LTRAv1, here->LTRAinstListSize)
model->LTRAh2Coeffs = TREALLOC(double, model->LTRAh2Coeffs, model->LTRAmodelListSize); LTRAmemMANAGE(here->LTRAi1, here->LTRAinstListSize)
model->LTRAh3dashCoeffs = TREALLOC(double, model->LTRAh3dashCoeffs, model->LTRAmodelListSize); LTRAmemMANAGE(here->LTRAv2, here->LTRAinstListSize)
} LTRAmemMANAGE(here->LTRAi2, here->LTRAinstListSize)
/* loop through all the instances of the model */ }
for (here = LTRAinstances(model); here != NULL; /*
here = LTRAnextInstance(here)) { * why is this here? ask TQ
*
* if (ckt->CKTtimeIndex == 0? 1: (ckt->CKTtime-
* (ckt->CKTtimePoints+ckt->CKTtimeIndex-1) > ckt->CKTminBreak)) {
*
*/
if (ckt->CKTtimeIndex >= here->LTRAinstListSize) { /* need more space */
here->LTRAinstListSize += ckt->CKTsizeIncr;
if (ckt->CKTmode & MODEINITTRAN) { here->LTRAv1 = TREALLOC(double, here->LTRAv1, here->LTRAinstListSize);
here->LTRAinstListSize = 10; here->LTRAi1 = TREALLOC(double, here->LTRAi1, here->LTRAinstListSize);
here->LTRAi2 = TREALLOC(double, here->LTRAi2, here->LTRAinstListSize);
here->LTRAv2 = TREALLOC(double, here->LTRAv2, here->LTRAinstListSize);
}
*(here->LTRAv1 + ckt->CKTtimeIndex) = *(ckt->CKTrhsOld +
here->LTRAposNode1) - *(ckt->CKTrhsOld +
here->LTRAnegNode1);
*(here->LTRAv2 + ckt->CKTtimeIndex) = *(ckt->CKTrhsOld +
here->LTRAposNode2) - *(ckt->CKTrhsOld +
here->LTRAnegNode2);
*(here->LTRAi1 + ckt->CKTtimeIndex) = *(ckt->CKTrhsOld +
here->LTRAbrEq1);
*(here->LTRAi2 + ckt->CKTtimeIndex) = *(ckt->CKTrhsOld +
here->LTRAbrEq2);
LTRAmemMANAGE(here->LTRAv1, here->LTRAinstListSize) if (ckt->CKTtryToCompact && (ckt->CKTtimeIndex >= 2)) {
LTRAmemMANAGE(here->LTRAi1, here->LTRAinstListSize)
LTRAmemMANAGE(here->LTRAv2, here->LTRAinstListSize)
LTRAmemMANAGE(here->LTRAi2, here->LTRAinstListSize)
}
/*
* why is this here? ask TQ
*
* if (ckt->CKTtimeIndex == 0? 1: (ckt->CKTtime-
* (ckt->CKTtimePoints+ckt->CKTtimeIndex-1) > ckt->CKTminBreak)) {
*
*/
if (ckt->CKTtimeIndex >= here->LTRAinstListSize) { /* need more space */
here->LTRAinstListSize += ckt->CKTsizeIncr;
here->LTRAv1 = TREALLOC(double, here->LTRAv1, here->LTRAinstListSize); /*
here->LTRAi1 = TREALLOC(double, here->LTRAi1, here->LTRAinstListSize); * figure out if the last 3 points lie on a st. line for all the
here->LTRAi2 = TREALLOC(double, here->LTRAi2, here->LTRAinstListSize); * terminal variables
here->LTRAv2 = TREALLOC(double, here->LTRAv2, here->LTRAinstListSize); */
} {
*(here->LTRAv1 + ckt->CKTtimeIndex) = *(ckt->CKTrhsOld + double t1, t2, t3;
here->LTRAposNode1) - *(ckt->CKTrhsOld +
here->LTRAnegNode1);
*(here->LTRAv2 + ckt->CKTtimeIndex) = *(ckt->CKTrhsOld +
here->LTRAposNode2) - *(ckt->CKTrhsOld +
here->LTRAnegNode2);
*(here->LTRAi1 + ckt->CKTtimeIndex) = *(ckt->CKTrhsOld +
here->LTRAbrEq1);
*(here->LTRAi2 + ckt->CKTtimeIndex) = *(ckt->CKTrhsOld +
here->LTRAbrEq2);
if (ckt->CKTtryToCompact && (ckt->CKTtimeIndex >= 2)) { t1 = *(ckt->CKTtimePoints + ckt->CKTtimeIndex - 2);
t2 = *(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1);
t3 = *(ckt->CKTtimePoints + ckt->CKTtimeIndex);
/* if (compact) {
* figure out if the last 3 points lie on a st. line for all the compact = LTRAstraightLineCheck(t1,
* terminal variables *(here->LTRAv1 + ckt->CKTtimeIndex - 2),
*/ t2, *(here->LTRAv1 + ckt->CKTtimeIndex - 1),
{ t3, *(here->LTRAv1 + ckt->CKTtimeIndex),
double t1, t2, t3; model->LTRAstLineReltol, model->LTRAstLineAbstol);
}
t1 = *(ckt->CKTtimePoints + ckt->CKTtimeIndex - 2); if (compact) {
t2 = *(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1); compact = LTRAstraightLineCheck(t1,
t3 = *(ckt->CKTtimePoints + ckt->CKTtimeIndex); *(here->LTRAv2 + ckt->CKTtimeIndex - 2),
t2, *(here->LTRAv2 + ckt->CKTtimeIndex - 1),
if (compact) { t3, *(here->LTRAv2 + ckt->CKTtimeIndex),
compact = LTRAstraightLineCheck(t1, model->LTRAstLineReltol, model->LTRAstLineAbstol);
*(here->LTRAv1 + ckt->CKTtimeIndex - 2), }
t2, *(here->LTRAv1 + ckt->CKTtimeIndex - 1), if (compact) {
t3, *(here->LTRAv1 + ckt->CKTtimeIndex), compact = LTRAstraightLineCheck(t1,
model->LTRAstLineReltol, model->LTRAstLineAbstol); *(here->LTRAi1 + ckt->CKTtimeIndex - 2),
} t2, *(here->LTRAi1 + ckt->CKTtimeIndex - 1),
if (compact) { t3, *(here->LTRAi1 + ckt->CKTtimeIndex),
compact = LTRAstraightLineCheck(t1, model->LTRAstLineReltol, model->LTRAstLineAbstol);
*(here->LTRAv2 + ckt->CKTtimeIndex - 2), }
t2, *(here->LTRAv2 + ckt->CKTtimeIndex - 1), if (compact) {
t3, *(here->LTRAv2 + ckt->CKTtimeIndex), compact = LTRAstraightLineCheck(t1,
model->LTRAstLineReltol, model->LTRAstLineAbstol); *(here->LTRAi2 + ckt->CKTtimeIndex - 2),
} t2, *(here->LTRAi2 + ckt->CKTtimeIndex - 1),
if (compact) { t3, *(here->LTRAi2 + ckt->CKTtimeIndex),
compact = LTRAstraightLineCheck(t1, model->LTRAstLineReltol, model->LTRAstLineAbstol);
*(here->LTRAi1 + ckt->CKTtimeIndex - 2), }
t2, *(here->LTRAi1 + ckt->CKTtimeIndex - 1), }
t3, *(here->LTRAi1 + ckt->CKTtimeIndex), }
model->LTRAstLineReltol, model->LTRAstLineAbstol); if (ckt->CKTtimeIndex > 0) {
}
if (compact) {
compact = LTRAstraightLineCheck(t1,
*(here->LTRAi2 + ckt->CKTtimeIndex - 2),
t2, *(here->LTRAi2 + ckt->CKTtimeIndex - 1),
t3, *(here->LTRAi2 + ckt->CKTtimeIndex),
model->LTRAstLineReltol, model->LTRAstLineAbstol);
}
}
}
if (ckt->CKTtimeIndex > 0) {
#ifdef NOTDEF #ifdef NOTDEF
v1 = (*(here->LTRAv1 + ckt->CKTtimeIndex) + v1 = (*(here->LTRAv1 + ckt->CKTtimeIndex) +
*(here->LTRAi1 + ckt->CKTtimeIndex) * *(here->LTRAi1 + ckt->CKTtimeIndex) *
model->LTRAimped) * model->LTRAattenuation; model->LTRAimped) * model->LTRAattenuation;
v2 = (*(here->LTRAv1 + ckt->CKTtimeIndex - 1) + v2 = (*(here->LTRAv1 + ckt->CKTtimeIndex - 1) +
*(here->LTRAi1 + ckt->CKTtimeIndex - 1) *(here->LTRAi1 + ckt->CKTtimeIndex - 1)
* model->LTRAimped) * model->LTRAattenuation; * model->LTRAimped) * model->LTRAattenuation;
v3 = (*(here->LTRAv2 + ckt->CKTtimeIndex) + v3 = (*(here->LTRAv2 + ckt->CKTtimeIndex) +
*(here->LTRAi2 + ckt->CKTtimeIndex) * *(here->LTRAi2 + ckt->CKTtimeIndex) *
model->LTRAimped) * model->LTRAattenuation; model->LTRAimped) * model->LTRAattenuation;
v4 = (*(here->LTRAv2 + ckt->CKTtimeIndex - 1) + v4 = (*(here->LTRAv2 + ckt->CKTtimeIndex - 1) +
*(here->LTRAi2 + ckt->CKTtimeIndex - 1) * *(here->LTRAi2 + ckt->CKTtimeIndex - 1) *
model->LTRAimped) * model->LTRAattenuation; model->LTRAimped) * model->LTRAattenuation;
if ((fabs(v1 - v2) >= 50 * ckt->CKTreltol * if ((fabs(v1 - v2) >= 50 * ckt->CKTreltol *
MAX(fabs(v1), fabs(v2)) + 50 * ckt->CKTvoltTol) || MAX(fabs(v1), fabs(v2)) + 50 * ckt->CKTvoltTol) ||
(fabs(v3 - v4) >= 50 * ckt->CKTreltol * (fabs(v3 - v4) >= 50 * ckt->CKTreltol *
MAX(fabs(v3), fabs(v4)) + 50 * ckt->CKTvoltTol)) { MAX(fabs(v3), fabs(v4)) + 50 * ckt->CKTvoltTol)) {
/* changing - need to schedule after delay */ /* changing - need to schedule after delay */
/* /*
* don't really need this error = * don't really need this error =
* CKTsetBreak(ckt,ckt->CKTtime+model->LTRAtd); if(error) * CKTsetBreak(ckt,ckt->CKTtime+model->LTRAtd); if(error)
* return(error); * return(error);
*/ */
/* the PREVIOUS point is the real breakpoint */ /* the PREVIOUS point is the real breakpoint */
error = CKTsetBreak(ckt, error = CKTsetBreak(ckt,
*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1) + *(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1) +
model->LTRAtd); model->LTRAtd);
CKTbreakDump(ckt); CKTbreakDump(ckt);
if (error) if (error)
return (error); return (error);
} }
#else #else
/* /*
* remove the hack here - store the total inputs for the last 2 or 3 * remove the hack here - store the total inputs for the last 2 or 3
* timesteps * timesteps
*/ */
v1 = (*(here->LTRAv1 + ckt->CKTtimeIndex) + v1 = (*(here->LTRAv1 + ckt->CKTtimeIndex) +
*(here->LTRAi1 + ckt->CKTtimeIndex) * *(here->LTRAi1 + ckt->CKTtimeIndex) *
model->LTRAimped) * model->LTRAattenuation; model->LTRAimped) * model->LTRAattenuation;
v2 = (*(here->LTRAv1 + ckt->CKTtimeIndex - 1) + v2 = (*(here->LTRAv1 + ckt->CKTtimeIndex - 1) +
*(here->LTRAi1 + ckt->CKTtimeIndex - 1) * *(here->LTRAi1 + ckt->CKTtimeIndex - 1) *
model->LTRAimped) * model->LTRAattenuation; model->LTRAimped) * model->LTRAattenuation;
v3 = ckt->CKTtimeIndex < 2 ? v2 : (*(here->LTRAv1 + ckt->CKTtimeIndex - 2) + v3 = ckt->CKTtimeIndex < 2 ? v2 : (*(here->LTRAv1 + ckt->CKTtimeIndex - 2) +
*(here->LTRAi1 + ckt->CKTtimeIndex - 2) * *(here->LTRAi1 + ckt->CKTtimeIndex - 2) *
model->LTRAimped) * model->LTRAattenuation; model->LTRAimped) * model->LTRAattenuation;
v4 = (*(here->LTRAv2 + ckt->CKTtimeIndex) + v4 = (*(here->LTRAv2 + ckt->CKTtimeIndex) +
*(here->LTRAi2 + ckt->CKTtimeIndex) * *(here->LTRAi2 + ckt->CKTtimeIndex) *
model->LTRAimped) * model->LTRAattenuation; model->LTRAimped) * model->LTRAattenuation;
v5 = (*(here->LTRAv2 + ckt->CKTtimeIndex - 1) + v5 = (*(here->LTRAv2 + ckt->CKTtimeIndex - 1) +
*(here->LTRAi2 + ckt->CKTtimeIndex - 1) * *(here->LTRAi2 + ckt->CKTtimeIndex - 1) *
model->LTRAimped) * model->LTRAattenuation; model->LTRAimped) * model->LTRAattenuation;
v6 = ckt->CKTtimeIndex < 2 ? v5 : (*(here->LTRAv2 + ckt->CKTtimeIndex - 2) + v6 = ckt->CKTtimeIndex < 2 ? v5 : (*(here->LTRAv2 + ckt->CKTtimeIndex - 2) +
*(here->LTRAi2 + ckt->CKTtimeIndex - 2) * *(here->LTRAi2 + ckt->CKTtimeIndex - 2) *
model->LTRAimped) * model->LTRAattenuation; model->LTRAimped) * model->LTRAattenuation;
d1 = (v1 - v2) / (*(ckt->CKTtimePoints + ckt->CKTtimeIndex) - d1 = (v1 - v2) / (*(ckt->CKTtimePoints + ckt->CKTtimeIndex) -
*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1)); *(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1));
d2 = (ckt->CKTtimeIndex < 2) d2 = (ckt->CKTtimeIndex < 2)
? 0 ? 0
: (v2 - v3) / (*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1) - : (v2 - v3) / (*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1) -
*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 2)); *(ckt->CKTtimePoints + ckt->CKTtimeIndex - 2));
d3 = (v4 - v5) / (*(ckt->CKTtimePoints + ckt->CKTtimeIndex) - d3 = (v4 - v5) / (*(ckt->CKTtimePoints + ckt->CKTtimeIndex) -
*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1)); *(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1));
d4 = (ckt->CKTtimeIndex < 2) d4 = (ckt->CKTtimeIndex < 2)
? 0 ? 0
: (v5 - v6) / (*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1) - : (v5 - v6) / (*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1) -
*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 2)); *(ckt->CKTtimePoints + ckt->CKTtimeIndex - 2));
/* /*
* here we have a big problem with the scheme boxed by the *s below. * here we have a big problem with the scheme boxed by the *s below.
* Note the following: if LTRAreltol == 1, (assuming LTRAabstol==0) * Note the following: if LTRAreltol == 1, (assuming LTRAabstol==0)
* then breakpoints are set if and only if d1 and d2 have opposite * then breakpoints are set if and only if d1 and d2 have opposite
* signs or one is zero. If LTRAreltol > 2, breakpoints are never * signs or one is zero. If LTRAreltol > 2, breakpoints are never
* set. The problem is that when the waveform is steady at a value, * set. The problem is that when the waveform is steady at a value,
* small random numerical inaccuracies may produce derivatives of * small random numerical inaccuracies may produce derivatives of
* opposite sign, and breakpoints get set. This can, in practice, get * opposite sign, and breakpoints get set. This can, in practice, get
* quite killing... To alleviate this, we try to determine if the * quite killing... To alleviate this, we try to determine if the
* waveform is actually steady using the following tests: 1. Check if * waveform is actually steady using the following tests: 1. Check if
* the maximum difference between v1,v2 and v3 is less than * the maximum difference between v1,v2 and v3 is less than
* 50*CKTreltol*(the average of v1,v2,and v3) + 50*ckt->CKTabstol * 50*CKTreltol*(the average of v1,v2,and v3) + 50*ckt->CKTabstol
* (the 50 has been taken from the NOTDEF section above, reason * (the 50 has been taken from the NOTDEF section above, reason
* unknown - hopefully there is a good reason for it - ask TQ) * unknown - hopefully there is a good reason for it - ask TQ)
* *
* 2. Criterion 1 may be satisfied by a legitimate breakpoint. To * 2. Criterion 1 may be satisfied by a legitimate breakpoint. To
* further check, find one more derivative one timepoint ago and see * further check, find one more derivative one timepoint ago and see
* if that is close to d2. If not, then the likelihood of numerical * if that is close to d2. If not, then the likelihood of numerical
* inaccuracies is greater... * inaccuracies is greater...
*/ */
/********************************************************************* /*********************************************************************
if( (fabs(d1-d2) >= model->LTRAreltol*MAX(fabs(d1),fabs(d2))+ if( (fabs(d1-d2) >= model->LTRAreltol*MAX(fabs(d1),fabs(d2))+
model->LTRAabstol) || model->LTRAabstol) ||
(fabs(d3-d4) >= model->LTRAreltol*MAX(fabs(d3),fabs(d4))+ (fabs(d3-d4) >= model->LTRAreltol*MAX(fabs(d3),fabs(d4))+
model->LTRAabstol) ) { model->LTRAabstol) ) {
*********************************************************************/ *********************************************************************/
#define CHECK(a,b,c) (MAX(MAX(a,b),c)-MIN(MIN(a,b),c) >= \ #define CHECK(a,b,c) (MAX(MAX(a,b),c)-MIN(MIN(a,b),c) >= \
fabs(50.0*(ckt->CKTreltol/3.0*(a+b+c) +\ fabs(50.0*(ckt->CKTreltol/3.0*(a+b+c) +\
ckt->CKTabstol))) ckt->CKTabstol)))
tmp_test = (fabs(d1 - d2) tmp_test = (fabs(d1 - d2)
>= model->LTRAreltol * MAX(fabs(d1), fabs(d2)) + >= model->LTRAreltol * MAX(fabs(d1), fabs(d2)) +
model->LTRAabstol) model->LTRAabstol)
&& CHECK(v1, v2, v3); && CHECK(v1, v2, v3);
if (tmp_test || ((fabs(d3 - d4) if (tmp_test || ((fabs(d3 - d4)
>= model->LTRAreltol * MAX(fabs(d3), fabs(d4)) + >= model->LTRAreltol * MAX(fabs(d3), fabs(d4)) +
model->LTRAabstol) model->LTRAabstol)
&& CHECK(v4, v5, v6))) { && CHECK(v4, v5, v6))) {
/* criterion 2 not implemented yet... */ /* criterion 2 not implemented yet... */
error = CKTsetBreak(ckt, error = CKTsetBreak(ckt,
*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1) + *(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1) +
model->LTRAtd); model->LTRAtd);
/* /*
* this is not necessary - the previous timepoint was the * this is not necessary - the previous timepoint was the
* breakpoint error = CKTsetBreak(ckt, ckt->CKTtime + * breakpoint error = CKTsetBreak(ckt, ckt->CKTtime +
* model->LTRAtd); * model->LTRAtd);
*/ */
#ifdef LTRADEBUG #ifdef LTRADEBUG
fprintf(stdout, "\nbreakpoints set at %14.14g at %14.14g at time %14.14g\n", ckt->CKTtime + model->LTRAtd, *(ckt->CKTtimePoints + ckt->CKTtimeIndex fprintf(stdout, "\nbreakpoints set at %14.14g at %14.14g at time %14.14g\n", ckt->CKTtime + model->LTRAtd, *(ckt->CKTtimePoints + ckt->CKTtimeIndex
- 1) + model->LTRAtd, ckt->CKTtime); - 1) + model->LTRAtd, ckt->CKTtime);
fprintf(stdout, "d1 through d4 are %14.14g %14.14g %14.14g %14.14g\n\n", d1, d2, d3, d4); fprintf(stdout, "d1 through d4 are %14.14g %14.14g %14.14g %14.14g\n\n", d1, d2, d3, d4);
#endif #endif
if (error) if (error)
return (error); return (error);
} }
/* } */ /* } */
#endif /* NOTDEF */ #endif /* NOTDEF */
} }
/* ask TQ } */ /* ask TQ } */
} /* instance */ } /* instance */
} /* model */ } /* model */
if (ckt->CKTtryToCompact && compact && (ckt->CKTtimeIndex >= 2)) { if (ckt->CKTtryToCompact && compact && (ckt->CKTtimeIndex >= 2)) {
/* /*
* last three timepoints have variables lying on a straight line, do a * last three timepoints have variables lying on a straight line, do a
* compaction * compaction
*/ */
model = (LTRAmodel *) inModel; model = (LTRAmodel*)inModel;
for (; model != NULL; model = LTRAnextModel(model)) { for (; model != NULL; model = LTRAnextModel(model)) {
for (here = LTRAinstances(model); here != NULL; for (here = LTRAinstances(model); here != NULL;
here = LTRAnextInstance(here)) { here = LTRAnextInstance(here)) {
*(here->LTRAv1 + ckt->CKTtimeIndex - 1) = *(here->LTRAv1 + *(here->LTRAv1 + ckt->CKTtimeIndex - 1) = *(here->LTRAv1 +
ckt->CKTtimeIndex); ckt->CKTtimeIndex);
*(here->LTRAv2 + ckt->CKTtimeIndex - 1) = *(here->LTRAv2 + *(here->LTRAv2 + ckt->CKTtimeIndex - 1) = *(here->LTRAv2 +
ckt->CKTtimeIndex); ckt->CKTtimeIndex);
*(here->LTRAi1 + ckt->CKTtimeIndex - 1) = *(here->LTRAi1 + *(here->LTRAi1 + ckt->CKTtimeIndex - 1) = *(here->LTRAi1 +
ckt->CKTtimeIndex); ckt->CKTtimeIndex);
*(here->LTRAi2 + ckt->CKTtimeIndex - 1) = *(here->LTRAi2 + *(here->LTRAi2 + ckt->CKTtimeIndex - 1) = *(here->LTRAi2 +
ckt->CKTtimeIndex); ckt->CKTtimeIndex);
} }
} }
*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1) = *(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1) =
*(ckt->CKTtimePoints + ckt->CKTtimeIndex); *(ckt->CKTtimePoints + ckt->CKTtimeIndex);
ckt->CKTtimeIndex--; ckt->CKTtimeIndex--;
#ifdef LTRADEBUG #ifdef LTRADEBUG
fprintf(stdout, "compacted at time=%g\n", *(ckt->CKTtimePoints + ckt->CKTtimeIndex)); fprintf(stdout, "compacted at time=%g\n", *(ckt->CKTtimePoints + ckt->CKTtimeIndex));
fflush(stdout); fflush(stdout);
#endif #endif
} }
return (OK); return (OK);
} }

View File

@ -30,7 +30,7 @@ VBICacLoad(GENmodel *inModel, CKTcircuit *ckt)
,Ibcp_Vbcp,Iccp_Vbep,Irs_Vrs,Iccp_Vbci,Iccp_Vbcp; ,Ibcp_Vbcp,Iccp_Vbep,Irs_Vrs,Iccp_Vbci,Iccp_Vbcp;
double XQbe_Vbei, XQbe_Vbci, XQbex_Vbex, XQbc_Vbci, double XQbe_Vbei, XQbe_Vbci, XQbex_Vbex, XQbc_Vbci,
XQbcx_Vbcx, XQbep_Vbep, XQbep_Vbci, XQbcx_Vbcx, XQbep_Vbep, XQbep_Vbci,
XQbcp_Vbcp; XQbcp_Vbcp, XQbeo_Vbe, XQbco_Vbc;
/* loop through all the models */ /* loop through all the models */
for( ; model != NULL; model = VBICnextModel(model)) { for( ; model != NULL; model = VBICnextModel(model)) {
@ -229,6 +229,8 @@ c The complex part
XQbep_Vbep = *(ckt->CKTstate0 + here->VBICcqbep) * ckt->CKTomega; XQbep_Vbep = *(ckt->CKTstate0 + here->VBICcqbep) * ckt->CKTomega;
XQbep_Vbci = *(ckt->CKTstate0 + here->VBICcqbepci) * ckt->CKTomega; XQbep_Vbci = *(ckt->CKTstate0 + here->VBICcqbepci) * ckt->CKTomega;
XQbcp_Vbcp = *(ckt->CKTstate0 + here->VBICcqbcp) * ckt->CKTomega; XQbcp_Vbcp = *(ckt->CKTstate0 + here->VBICcqbcp) * ckt->CKTomega;
XQbeo_Vbe = *(ckt->CKTstate0 + here->VBICcqbeo) * ckt->CKTomega;
XQbco_Vbc = *(ckt->CKTstate0 + here->VBICcqbco) * ckt->CKTomega;
/* /*
c Stamp element: Qbe c Stamp element: Qbe
*/ */
@ -279,6 +281,21 @@ c Stamp element: Qbcp
*(here->VBICsubsSIBaseBPPtr + 1) += -XQbcp_Vbcp; *(here->VBICsubsSIBaseBPPtr + 1) += -XQbcp_Vbcp;
*(here->VBICbaseBPSubsSIPtr + 1) += -XQbcp_Vbcp; *(here->VBICbaseBPSubsSIPtr + 1) += -XQbcp_Vbcp;
*(here->VBICbaseBPBaseBPPtr + 1) += XQbcp_Vbcp; *(here->VBICbaseBPBaseBPPtr + 1) += XQbcp_Vbcp;
/*
c Stamp element: Qbeo
*/
*(here->VBICbaseBasePtr + 1) += XQbeo_Vbe;
*(here->VBICemitEmitPtr + 1) += XQbeo_Vbe;
*(here->VBICbaseEmitPtr + 1) += -XQbeo_Vbe;
*(here->VBICemitBasePtr + 1) += -XQbeo_Vbe;
/*
c Stamp element: Qbco
*/
*(here->VBICbaseBasePtr + 1) += XQbco_Vbc;
*(here->VBICcollCollPtr + 1) += XQbco_Vbc;
*(here->VBICbaseCollPtr + 1) += -XQbco_Vbc;
*(here->VBICcollBasePtr + 1) += -XQbco_Vbc;
} }
} }

View File

@ -75,8 +75,8 @@ VBICload(GENmodel *inModel, CKTcircuit *ckt)
,Iccp_Vbci,Iccp_Vbcp,Irs,Irs_Vrs,Irs_Vrth=0.0,Qbcp,Qbcp_Vrth ,Iccp_Vbci,Iccp_Vbcp,Irs,Irs_Vrs,Irs_Vrth=0.0,Qbcp,Qbcp_Vrth
,Qbcp_Vbcp,Irth,Irth_Vrth=0.0,Ith=0.0,Ith_Vrth=0.0,Ith_Vbei=0.0,Ith_Vbci=0.0 ,Qbcp_Vbcp,Irth,Irth_Vrth=0.0,Ith=0.0,Ith_Vrth=0.0,Ith_Vbei=0.0,Ith_Vbci=0.0
,Ith_Vcei=0.0,Ith_Vbex=0.0,Ith_Vbep=0.0,Ith_Vrs=0.0,Ith_Vbcp=0.0,Ith_Vcep=0.0,Ith_Vrcx=0.0 ,Ith_Vcei=0.0,Ith_Vbex=0.0,Ith_Vbep=0.0,Ith_Vrs=0.0,Ith_Vbcp=0.0,Ith_Vcep=0.0,Ith_Vrcx=0.0
,Ith_Vrci=0.0,Ith_Vbcx=0.0,Ith_Vrbx=0.0,Ith_Vrbi=0.0,Ith_Vre=0.0,Ith_Vrbp=0.0,Qcth ,Ith_Vrci=0.0,Ith_Vbcx=0.0,Ith_Vrbx=0.0,Ith_Vrbi=0.0,Ith_Vre=0.0,Ith_Vrbp=0.0,Qcth=0.0
,Qcth_Vrth,SCALE; ,Qcth_Vrth=0.0,SCALE;
int iret; int iret;
double vce; double vce;
#ifndef PREDICTOR #ifndef PREDICTOR
@ -129,7 +129,7 @@ VBICload(GENmodel *inModel, CKTcircuit *ckt)
/* /*
* model parameters * model parameters
*/ */
memcpy (&p, &model->VBICtnom, 108*8); memcpy (&p, &model->VBICtnom, sizeof(p));
p[0] = here->VBICtemp - CONSTCtoK + p[105]; p[0] = here->VBICtemp - CONSTCtoK + p[105];
/* temperature dependent parameter are already calculated */ /* temperature dependent parameter are already calculated */
@ -714,7 +714,8 @@ VBICload(GENmodel *inModel, CKTcircuit *ckt)
here->VBICcapbcx = Qbcx_Vbcx; here->VBICcapbcx = Qbcx_Vbcx;
here->VBICcapbep = Qbep_Vbep; here->VBICcapbep = Qbep_Vbep;
here->VBICcapbcp = Qbcp_Vbcp; here->VBICcapbcp = Qbcp_Vbcp;
here->VBICcapcth = Qcth_Vrth; if (here->VBIC_selfheat)
here->VBICcapcth = Qcth_Vrth;
/* /*
* store small-signal parameters * store small-signal parameters
@ -894,9 +895,11 @@ VBICload(GENmodel *inModel, CKTcircuit *ckt)
*(ckt->CKTstate0 + here->VBICirbx_Vrbx) = Irbx_Vrbx; *(ckt->CKTstate0 + here->VBICirbx_Vrbx) = Irbx_Vrbx;
*(ckt->CKTstate0 + here->VBICirs_Vrs) = Irs_Vrs; *(ckt->CKTstate0 + here->VBICirs_Vrs) = Irs_Vrs;
*(ckt->CKTstate0 + here->VBICire_Vre) = Ire_Vre; *(ckt->CKTstate0 + here->VBICire_Vre) = Ire_Vre;
*(ckt->CKTstate0 + here->VBICcqcth) = Icth; if (here->VBIC_selfheat)
*(ckt->CKTstate0 + here->VBICicth_Vrth) = Icth_Vrth; {
*(ckt->CKTstate0 + here->VBICcqcth) = Icth;
*(ckt->CKTstate0 + here->VBICicth_Vrth) = Icth_Vrth;
}
load: load:
/* /*
* load current excitation vector and matrix * load current excitation vector and matrix

View File

@ -469,7 +469,7 @@ VBICsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
} }
if(model->VBICselftGiven) if(model->VBICselftGiven)
if(model->VBICselft == 1) if((model->VBICselft == 1) && (model->VBICthermalResistGiven) && (model->VBICthermalResist > 0.0))
here->VBIC_selfheat = 1; here->VBIC_selfheat = 1;
else else
here->VBIC_selfheat = 0; here->VBIC_selfheat = 0;

View File

@ -42,7 +42,7 @@ VBICtemp(GENmodel *inModel, CKTcircuit *ckt)
TAMB = here->VBICtemp - CONSTCtoK; TAMB = here->VBICtemp - CONSTCtoK;
memcpy (&pnom, &model->VBICtnom, 108*8); memcpy (&pnom, &model->VBICtnom, sizeof(pnom));
iret = vbic_4T_et_cf_t(p,pnom,&TAMB); iret = vbic_4T_et_cf_t(p,pnom,&TAMB);

View File

@ -19,9 +19,6 @@ extern void fftFree(void);
extern bool ft_ngdebug; /* some additional debug info printed */ extern bool ft_ngdebug; /* some additional debug info printed */
#define SAMETIME(a,b) (fabs((a)-(b))<= TIMETOL * PW)
#define TIMETOL 1e-7
int int
VSRCaccept(CKTcircuit *ckt, GENmodel *inModel) VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
/* set up the breakpoint table. */ /* set up the breakpoint table. */
@ -51,7 +48,6 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
case PULSE: { case PULSE: {
double TD, TR, TF, PW, PER; double TD, TR, TF, PW, PER;
double tshift;
double time = 0.; double time = 0.;
double basetime = 0; double basetime = 0;
double tmax = 1e99; double tmax = 1e99;
@ -79,7 +75,6 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
/* offset time by delay */ /* offset time by delay */
time = ckt->CKTtime - TD; time = ckt->CKTtime - TD;
tshift = TD;
if (newcompat.xs) { if (newcompat.xs) {
/* normalize phase to 0 - 360° */ /* normalize phase to 0 - 360° */
@ -90,71 +85,55 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
while (deltat > 0) while (deltat > 0)
deltat -= PER; deltat -= PER;
time += deltat; time += deltat;
tshift = TD - deltat; } else if (PHASE > 0.0) {
}
else if (PHASE > 0.0) {
tmax = PHASE * PER; tmax = PHASE * PER;
if (time > tmax)
break;
} }
if (!newcompat.xs && time > tmax) { if (ckt->CKTtime >= here->VSRCbreak_time) {
/* Do nothing */ double wait;
}
else {
if (time >= PER) { if (time >= PER) {
/* repeating signal - figure out where we are */ /* Repeating signal: where in period are we? */
/* in period */
basetime = PER * floor(time / PER); basetime = PER * floor(time / PER);
time -= basetime; time -= basetime;
} }
if (time <= 0.0 || time >= TR + PW + TF) { /* Set next breakpoint. */
if (ckt->CKTbreak && SAMETIME(time, 0.0)) {
error = CKTsetBreak(ckt, basetime + TR + tshift); if (time < 0.0) {
if (error) return(error); /* Await first pulse */
}
else if (ckt->CKTbreak && SAMETIME(TR + PW + TF, time)) { wait = -time;
error = CKTsetBreak(ckt, basetime + PER + tshift); } else if (time < TR) {
if (error) return(error); /* Wait for end of rise. */
}
else if (ckt->CKTbreak && (time == -tshift)) { wait = TR - time;
error = CKTsetBreak(ckt, basetime + tshift); } else if (time < TR + PW) {
if (error) return(error); /* Wait for fall. */
}
else if (ckt->CKTbreak && SAMETIME(PER, time)) { wait = TR + PW - time;
error = CKTsetBreak(ckt, basetime + tshift + TR + PER); } else if (time < TR + PW + TF) {
if (error) return(error); /* Wait for end of fall. */
}
} wait = TR + PW + TF - time;
else if (time >= TR && time <= TR + PW) { } else {
if (ckt->CKTbreak && SAMETIME(time, TR)) { /* Wait for next pulse. */
error = CKTsetBreak(ckt, basetime + tshift + TR + PW); wait = PER - time;
if (error) return(error);
}
else if (ckt->CKTbreak && SAMETIME(TR + PW, time)) {
error = CKTsetBreak(ckt, basetime + tshift + TR + PW + TF);
if (error) return(error);
}
}
else if (time > 0 && time < TR) {
if (ckt->CKTbreak && SAMETIME(time, 0)) {
error = CKTsetBreak(ckt, basetime + tshift + TR);
if (error) return(error);
}
else if (ckt->CKTbreak && SAMETIME(time, TR)) {
error = CKTsetBreak(ckt, basetime + tshift + TR + PW);
if (error) return(error);
}
}
else { /* time > TR + PW && < TR + PW + TF */
if (ckt->CKTbreak && SAMETIME(time, TR + PW)) {
error = CKTsetBreak(ckt, basetime + tshift + TR + PW + TF);
if (error) return(error);
}
else if (ckt->CKTbreak && SAMETIME(time, TR + PW + TF)) {
error = CKTsetBreak(ckt, basetime + tshift + PER);
if (error) return(error);
}
} }
here->VSRCbreak_time = ckt->CKTtime + wait;
error = CKTsetBreak(ckt, here->VSRCbreak_time);
if (error)
return error;
/* If a timestep ends just before the break time,
* the break request may be ignored.
* Set threshold for requesting following break.
*/
here->VSRCbreak_time -= ckt->CKTminBreak;
} }
} }
break; break;
@ -179,25 +158,46 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
} }
break; break;
case PWL: { case PWL:
int i; if (ckt->CKTtime >= here->VSRCbreak_time) {
if(ckt->CKTtime < *(here->VSRCcoeffs)) { double time, end, period;
if(ckt->CKTbreak) { int i;
error = CKTsetBreak(ckt,*(here->VSRCcoeffs));
break; time = ckt->CKTtime - here->VSRCrdelay;
end =
here->VSRCcoeffs[here->VSRCfunctionOrder - 2];
if (time > end) {
if (here->VSRCrGiven) {
/* Repeating. */
period = end -
here->VSRCcoeffs[here->VSRCrBreakpt];
time -= period * floor(time / period);
} else {
here->VSRCbreak_time = ckt->CKTfinalTime;
break;
}
} }
}
for(i=0;i<(here->VSRCfunctionOrder/2)-1;i++) { for (i = 0;
if ( ckt->CKTbreak && AlmostEqualUlps(*(here->VSRCcoeffs+2*i), ckt->CKTtime, 3 ) ) { i < here->VSRCfunctionOrder;
error = CKTsetBreak(ckt, *(here->VSRCcoeffs+2*i+2)); i += 2) {
if(error) return(error); if (here->VSRCcoeffs[i] > time) {
goto bkptset; here->VSRCbreak_time =
ckt->CKTtime +
here->VSRCcoeffs[i] - time;
error = CKTsetBreak(ckt,
here->VSRCbreak_time);
if (error)
return error;
here->VSRCbreak_time -= ckt->CKTminBreak;
break;
}
} }
} }
break; break;
}
/**** tansient noise routines: /**** transient noise routines:
VNoi2 2 0 DC 0 TRNOISE(10n 0.5n 0 0n) : generate gaussian distributed noise VNoi2 2 0 DC 0 TRNOISE(10n 0.5n 0 0n) : generate gaussian distributed noise
rms value, time step, 0 0 rms value, time step, 0 0
VNoi1 1 0 DC 0 TRNOISE(0n 0.5n 1 10n) : generate 1/f noise VNoi1 1 0 DC 0 TRNOISE(0n 0.5n 1 10n) : generate 1/f noise
@ -205,6 +205,7 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
*/ */
case TRNOISE: { case TRNOISE: {
struct trnoise_state *state = here -> VSRCtrnoise_state; struct trnoise_state *state = here -> VSRCtrnoise_state;
double TS = state -> TS; double TS = state -> TS;
double RTSAM = state ->RTSAM; double RTSAM = state ->RTSAM;
@ -220,61 +221,55 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
fftFree(); fftFree();
} }
#endif #endif
if (TS > 0 && ckt->CKTtime >= here->VSRCbreak_time) {
if(ckt->CKTbreak) { if (here->VSRCbreak_time < 0.0)
here->VSRCbreak_time = TS;
int n = (int) floor(ckt->CKTtime / TS + 0.5); else
volatile double nearest = n * TS; here->VSRCbreak_time += TS;
error = CKTsetBreak(ckt, here->VSRCbreak_time);
if(AlmostEqualUlps(nearest, ckt->CKTtime, 3)) { if (error)
/* carefull calculate `next' return(error);
* make sure it is really identical here->VSRCbreak_time -= ckt->CKTminBreak;
* with the next calculated `nearest' value
*/
volatile double next = (n+1) * TS;
error = CKTsetBreak(ckt, next);
if(error)
return(error);
}
} }
if (RTSAM > 0) { if (RTSAM <= 0)
double RTScapTime = state->RTScapTime; break; /* No shot noise. */
double RTSemTime = state->RTSemTime;
double RTSCAPT = state->RTSCAPT;
double RTSEMT = state->RTSEMT;
if (ckt->CKTtime == 0) { if (ckt->CKTtime == 0) {
/* initialzing here again needed for repeated calls to tran command */ /* initialzing here again needed for repeated calls to tran command */
state->RTScapTime = RTScapTime = exprand(RTSCAPT); state->RTScapTime = exprand(state->RTSCAPT);
state->RTSemTime = RTSemTime = RTScapTime + exprand(RTSEMT); state->RTSemTime =
state->RTScapTime + exprand(state->RTSEMT);
error = CKTsetBreak(ckt, state->RTScapTime);
if(error)
return(error);
break;
}
if (ckt->CKTbreak) { /* Break handling code ends a timestep close to
error = CKTsetBreak(ckt, RTScapTime); * the requested time.
if(error) */
return(error);
}
}
if(AlmostEqualUlps(RTScapTime, ckt->CKTtime, 3)) { if (ckt->CKTtime >=
if (ckt->CKTbreak) { state->RTScapTime - ckt->CKTminBreak &&
error = CKTsetBreak(ckt, RTSemTime); ckt->CKTtime <=
if(error) state->RTScapTime + ckt->CKTminBreak) {
return(error); error = CKTsetBreak(ckt, state->RTSemTime);
} if(error)
} return(error);
}
if(AlmostEqualUlps(RTSemTime, ckt->CKTtime, 3)) { if (ckt->CKTtime >=
/* new values */ state->RTSemTime - ckt->CKTminBreak) {
RTScapTime = here -> VSRCtrnoise_state ->RTScapTime = ckt->CKTtime + exprand(RTSCAPT); /* new values */
here -> VSRCtrnoise_state ->RTSemTime = RTScapTime + exprand(RTSEMT);
if (ckt->CKTbreak) { state->RTScapTime =
error = CKTsetBreak(ckt, RTScapTime); ckt->CKTtime + exprand(state->RTSCAPT);
if(error) state->RTSemTime =
return(error); state->RTScapTime + exprand(state->RTSEMT);
} error = CKTsetBreak(ckt, state->RTScapTime);
} if(error)
return(error);
} }
} }
break; break;
@ -286,30 +281,22 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
if (ckt->CKTtime == 0 && TD > 0) { if (ckt->CKTtime == 0 && TD > 0) {
error = CKTsetBreak(ckt, TD); error = CKTsetBreak(ckt, TD);
here->VSRCbreak_time = TD;
if (error) if (error)
return(error); return(error);
break;
} }
double time = ckt->CKTtime - TD; if (ckt->CKTtime >= here->VSRCbreak_time) {
if (here->VSRCbreak_time < 0.0)
if (time < 0) break; here->VSRCbreak_time = TS;
else
if(ckt->CKTbreak) { here->VSRCbreak_time += TS;
error = CKTsetBreak(ckt, here->VSRCbreak_time);
int n = (int) floor(time / TS + 0.5); if (error)
volatile double nearest = n * TS; return(error);
here->VSRCbreak_time -= ckt->CKTminBreak;
if(AlmostEqualUlps(nearest, time, 10)) { state->value = trrandom_state_get(state);
/* carefully calculate `next'
* make sure it is really identical
* with the next calculated `nearest' value
*/
volatile double next = (n+1) * TS + TD;
error = CKTsetBreak(ckt, next);
if(error)
return(error);
state->value = trrandom_state_get(state);
}
} }
} }
break; break;
@ -323,7 +310,6 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
} // switch } // switch
} // if ... else } // if ... else
bkptset: ;
} // for } // for
} // for } // for

View File

@ -50,6 +50,7 @@ typedef struct sVSRCinstance {
int VSRCfunctionType; /* code number of function type for source */ int VSRCfunctionType; /* code number of function type for source */
int VSRCfunctionOrder; /* order of the function for the source */ int VSRCfunctionOrder; /* order of the function for the source */
int VSRCrBreakpt; /* pwl repeat breakpoint index */ int VSRCrBreakpt; /* pwl repeat breakpoint index */
double VSRCbreak_time; /* time of most-recent breakpoint */
double *VSRCcoeffs; /* pointer to array of coefficients */ double *VSRCcoeffs; /* pointer to array of coefficients */
double VSRCdcValue; /* DC and TRANSIENT value of source */ double VSRCdcValue; /* DC and TRANSIENT value of source */

View File

@ -298,43 +298,48 @@ VSRCload(GENmodel *inModel, CKTcircuit *ckt)
break; break;
case PWL: { case PWL: {
int i = 0, num_repeat = 0, ii = 0; int i;
double foo, repeat_time = 0, end_time, breakpt_time, itime; double end_time, itime;
time -= here->VSRCrdelay; time -= here->VSRCrdelay;
if (time < here->VSRCcoeffs[0]) {
if(time < *(here->VSRCcoeffs)) { value = here->VSRCcoeffs[1];
foo = *(here->VSRCcoeffs + 1) ; value = value;
value = foo; break;
goto loadDone;
} }
do { end_time =
for(i=ii ; i<(here->VSRCfunctionOrder/2)-1; i++ ) { here->VSRCcoeffs[here->VSRCfunctionOrder - 2];
itime = *(here->VSRCcoeffs+2*i); if (time > end_time) {
if ( AlmostEqualUlps(itime+repeat_time, time, 3 )) { double period;
foo = *(here->VSRCcoeffs+2*i+1);
value = foo; if (here->VSRCrGiven) {
goto loadDone; /* Repeating. */
} else if ( (*(here->VSRCcoeffs+2*i)+repeat_time < time)
&& (*(here->VSRCcoeffs+2*(i+1))+repeat_time > time) ) { period = end_time -
foo = *(here->VSRCcoeffs+2*i+1) + (((time-(*(here->VSRCcoeffs+2*i)+repeat_time))/ here->VSRCcoeffs[here->VSRCrBreakpt];
(*(here->VSRCcoeffs+2*(i+1)) - *(here->VSRCcoeffs+2*i))) * time -= period * floor(time / period);
(*(here->VSRCcoeffs+2*i+3) - *(here->VSRCcoeffs+2*i+1))); time += here->VSRCcoeffs[here->VSRCrBreakpt];
value = foo; } else {
goto loadDone; value =
} here->VSRCcoeffs[here->VSRCfunctionOrder - 1];
break;
} }
foo = *(here->VSRCcoeffs+ here->VSRCfunctionOrder-1) ; }
value = foo;
if ( !here->VSRCrGiven ) goto loadDone; for (i = 2; i < here->VSRCfunctionOrder; i += 2) {
itime = here->VSRCcoeffs[i];
end_time = *(here->VSRCcoeffs + here->VSRCfunctionOrder-2); if (itime >= time) {
breakpt_time = *(here->VSRCcoeffs + here->VSRCrBreakpt); time -= here->VSRCcoeffs[i - 2];
repeat_time = end_time + (end_time - breakpt_time)*num_repeat++ - breakpt_time; time /= here->VSRCcoeffs[i] -
ii = here->VSRCrBreakpt/2; here->VSRCcoeffs[i - 2];
} while ( here->VSRCrGiven ); value = here->VSRCcoeffs[i - 1];
value += time *
( here->VSRCcoeffs[i + 1] -
here->VSRCcoeffs[i - 1]);
break;
}
}
break; break;
} }
@ -418,7 +423,6 @@ VNoi3 3 0 DC 0 TRNOISE(0 0 0 0 15m 22u 50u) : generate RTS noise
} // switch } // switch
} // else (line 48) } // else (line 48)
loadDone:
/* gtri - begin - wbk - modify for supply ramping option */ /* gtri - begin - wbk - modify for supply ramping option */
#ifdef XSPICE_EXP #ifdef XSPICE_EXP

View File

@ -131,6 +131,13 @@ VSRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select)
here->VSRCrGiven = FALSE; here->VSRCrGiven = FALSE;
break; break;
} }
/* buggy input? r is not a repetition coefficient */
if (!here->VSRCcoeffs || here->VSRCfunctionOrder < 2) {
here->VSRCrGiven = FALSE;
break;
}
here->VSRCr = value->rValue; here->VSRCr = value->rValue;
here->VSRCrGiven = TRUE; here->VSRCrGiven = TRUE;
@ -140,7 +147,7 @@ VSRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select)
} }
end_time = *(here->VSRCcoeffs + here->VSRCfunctionOrder-2); end_time = *(here->VSRCcoeffs + here->VSRCfunctionOrder-2);
if ( here->VSRCr > end_time ) { if ( here->VSRCr >= end_time ) {
fprintf(stderr, "ERROR: repeat start time value %g for pwl voltage source must be smaller than final time point given!\n", here->VSRCr ); fprintf(stderr, "ERROR: repeat start time value %g for pwl voltage source must be smaller than final time point given!\n", here->VSRCr );
return ( E_PARMVAL ); return ( E_PARMVAL );
} }

View File

@ -31,6 +31,7 @@ VSRCsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *state)
for (here = VSRCinstances(model); here != NULL ; for (here = VSRCinstances(model); here != NULL ;
here=VSRCnextInstance(here)) { here=VSRCnextInstance(here)) {
here->VSRCbreak_time = -1.0; // To set initial breakpoint
if(here->VSRCposNode == here->VSRCnegNode) { if(here->VSRCposNode == here->VSRCnegNode) {
SPfrontEnd->IFerrorf (ERR_FATAL, SPfrontEnd->IFerrorf (ERR_FATAL,
"instance %s is a shorted VSRC", here->VSRCname); "instance %s is a shorted VSRC", here->VSRCname);

View File

@ -462,8 +462,10 @@ INPparseNumMod(CKTcircuit *ckt, INPmodel *model, INPtables *tab, char **errMessa
/* Add card structure to model */ /* Add card structure to model */
info = INPcardTab[lastType]; info = INPcardTab[lastType];
error = info->newCard(&tmpCard, model->INPmodfast); error = info->newCard(&tmpCard, model->INPmodfast);
if (error) if (error) {
FREE(cardName);
return error; return error;
}
/* Handle parameter-less cards */ /* Handle parameter-less cards */
} else if (cinprefix(cardName, "title", 3)) { } else if (cinprefix(cardName, "title", 3)) {
/* Do nothing */ /* Do nothing */
@ -472,6 +474,7 @@ INPparseNumMod(CKTcircuit *ckt, INPmodel *model, INPtables *tab, char **errMessa
} else if (cinprefix(cardName, "end", 3)) { } else if (cinprefix(cardName, "end", 3)) {
/* Terminate parsing */ /* Terminate parsing */
*errMessage = err; *errMessage = err;
FREE(cardName);
return 0; return 0;
} else { } else {
/* Error */ /* Error */
@ -479,6 +482,7 @@ INPparseNumMod(CKTcircuit *ckt, INPmodel *model, INPtables *tab, char **errMessa
tprintf("Error on card %d : unrecognized name (%s) - ignored", tprintf("Error on card %d : unrecognized name (%s) - ignored",
cardNum, cardName)); cardNum, cardName));
} }
FREE(cardName);
} }
} }
@ -525,6 +529,8 @@ INPparseNumMod(CKTcircuit *ckt, INPmodel *model, INPtables *tab, char **errMessa
} }
error = info->setCardParm(info->cardParms[idx].id, value, tmpCard); error = info->setCardParm(info->cardParms[idx].id, value, tmpCard);
if (info->cardParms[idx].dataType & IF_STRING)
FREE(value->sValue);
if (error) if (error)
return error; return error;
} }

View File

@ -53,7 +53,8 @@ INPgetValue(CKTcircuit *ckt, char **line, int type, INPtables *tab)
list[temp.v.numValue - 1] = tmp; list[temp.v.numValue - 1] = tmp;
tmp = INPevaluate(line, &error, 1); tmp = INPevaluate(line, &error, 1);
} }
if (error && ft_ngdebug && !eq(*line, "") && !prefix(")", *line)) { if (error && ft_ngdebug && !eq(*line, "") && !prefix(")", *line) &&
temp.v.numValue > 1) {
fprintf(stderr, "\nWarning: Reading a vector without limiting parens may be dangerous\n%s\nat\n", compline); fprintf(stderr, "\nWarning: Reading a vector without limiting parens may be dangerous\n%s\nat\n", compline);
fprintf(stderr, "%*s%s\n", (int)(*line - compline)," ", *line); fprintf(stderr, "%*s%s\n", (int)(*line - compline)," ", *line);
} }
@ -76,7 +77,8 @@ INPgetValue(CKTcircuit *ckt, char **line, int type, INPtables *tab)
ilist[temp.v.numValue - 1] = (int) floor(0.5 + tmp); ilist[temp.v.numValue - 1] = (int) floor(0.5 + tmp);
tmp = INPevaluate(line, &error, 1); tmp = INPevaluate(line, &error, 1);
} }
if (error && ft_ngdebug && !eq(*line, "") && !prefix(")", *line)) { if (error && ft_ngdebug && !eq(*line, "") && !prefix(")", *line) &&
temp.v.numValue > 1) {
fprintf(stderr, "\nWarning: Reading a vector without limiting parens may be dangerous\n%s\nat\n", compline); fprintf(stderr, "\nWarning: Reading a vector without limiting parens may be dangerous\n%s\nat\n", compline);
fprintf(stderr, "%*s%s\n", (int)(*line - compline), " ", *line); fprintf(stderr, "%*s%s\n", (int)(*line - compline), " ", *line);
} }

View File

@ -148,6 +148,8 @@ INPpas3(CKTcircuit *ckt, struct card *data, INPtables *tab, TSKtask *task,
FREE(name); FREE(name);
/* Gobble the rest of the token */ /* Gobble the rest of the token */
line = nexttok(line); line = nexttok(line);
if (!line)
break;
continue; continue;
} }
ptemp.rValue = INPevaluate(&line,&error,1); ptemp.rValue = INPevaluate(&line,&error,1);

View File

@ -1107,8 +1107,19 @@ INPparseNode *PT_mkfnode(const char *fname, INPparseNode * arg)
INPparseNode *p; INPparseNode *p;
char buf[128]; char buf[128];
if (!fname) {
fprintf(stderr, "Error: bogus function name \n");
return mkfirst(NULL, arg);
}
if (!arg) {
fprintf(stderr, "Error: bad function arguments \n");
return mkfirst(NULL, arg);
}
/* Make sure the case is ok. */ /* Make sure the case is ok. */
(void) strcpy(buf, fname); (void)strncpy(buf, fname, 127);
buf[127] = 0;
strtolower(buf); strtolower(buf);
if(!strcmp("ternary_fcn", buf)) { if(!strcmp("ternary_fcn", buf)) {
@ -1142,7 +1153,6 @@ INPparseNode *PT_mkfnode(const char *fname, INPparseNode * arg)
fprintf(stderr, "Error: no such function '%s'\n", buf); fprintf(stderr, "Error: no such function '%s'\n", buf);
if (ft_stricterror) if (ft_stricterror)
controlled_exit(EXIT_BAD); controlled_exit(EXIT_BAD);
return mkfirst(NULL, arg); return mkfirst(NULL, arg);
} }
@ -1250,7 +1260,8 @@ INPparseNode *PT_mksnode(const char *string, void *ckt)
INPparseNode *p; INPparseNode *p;
/* Make sure the case is ok. */ /* Make sure the case is ok. */
(void) strcpy(buf, string); (void) strncpy(buf, string, 127);
buf[127] = 0;
strtolower(buf); strtolower(buf);
p = TMALLOC(INPparseNode, 1); p = TMALLOC(INPparseNode, 1);

View File

@ -29,7 +29,10 @@ const char *SPerror(int type)
case E_EXISTS: case E_EXISTS:
msg = "device already exists, existing one being used"; msg = "device already exists, existing one being used";
break; break;
case E_NODEV: case E_EXISTS_BAD:
msg = "device already exists, bail out";
break;
case E_NODEV:
msg = "no such device"; msg = "no such device";
break; break;
case E_NOMOD: case E_NOMOD:

View File

@ -479,17 +479,26 @@ static void EVTbackup_inst_queue(
} }
inst_queue->next_time = next_time; inst_queue->next_time = next_time;
/* Update the modified list by looking for any queued events */ /* Update the modified list by looking for events that were processed
/* with posted time > last_time */ * or queued in the current timestep.
*/
for(i = 0, j = 0; i < num_modified; i++) { for(i = 0, j = 0; i < num_modified; i++) {
inst_index = inst_queue->modified_index[i]; inst_index = inst_queue->modified_index[i];
inst = *(inst_queue->last_step[inst_index]); inst = *(inst_queue->last_step[inst_index]);
while(inst) { if (inst_queue->current[inst_index] ==
if(inst->posted_time > inst_queue->last_time) inst_queue->last_step[inst_index]) {
break; /* Nothing now removed from the queue,
inst = inst->next; * but it may have been modified by an addition.
*/
while (inst) {
if (inst->posted_time > inst_queue->last_time)
break;
inst = inst->next;
}
} }
if(! inst) { if(! inst) {

View File

@ -88,11 +88,13 @@ struct dvec *EVTfindvec(
int udn_index; int udn_index;
int num_events; int num_events;
Mif_Boolean_t found; Mif_Boolean_t found;
Evt_Ckt_Data_t *evt;
CKTcircuit *ckt;
Evt_Node_Info_t **node_table; Evt_Node_Info_t **node_table;
Evt_Node_t *head; Evt_Node_t *head;
Evt_Node_t *event; Evt_Node_t *event;
double *anal_point_vec; double *anal_point_vec;
double *value_vec; double *value_vec;
double value = 0; double value = 0;
@ -102,13 +104,16 @@ struct dvec *EVTfindvec(
/* Exit immediately if event-driven stuff not allocated yet, */ /* Exit immediately if event-driven stuff not allocated yet, */
/* or if number of event nodes is zero. */ /* or if number of event nodes is zero. */
if(! g_mif_info.ckt)
ckt = g_mif_info.ckt;
if(! ckt)
return(NULL); return(NULL);
if(! g_mif_info.ckt->evt) evt = ckt->evt;
if(! evt)
return(NULL); return(NULL);
if(! g_mif_info.ckt->evt->info.node_table) if(! evt->info.node_table)
return(NULL); return(NULL);
if(g_mif_info.ckt->evt->counts.num_nodes == 0) if(evt->counts.num_nodes == 0)
return(NULL); return(NULL);
/* Make a copy of the node name. */ /* Make a copy of the node name. */
@ -134,8 +139,8 @@ struct dvec *EVTfindvec(
} }
/* Look for node name in the event-driven node list */ /* Look for node name in the event-driven node list */
num_nodes = g_mif_info.ckt->evt->counts.num_nodes; num_nodes = evt->counts.num_nodes;
node_table = g_mif_info.ckt->evt->info.node_table; node_table = evt->info.node_table;
for(i = 0, found = MIF_FALSE; i < num_nodes; i++) { for(i = 0, found = MIF_FALSE; i < num_nodes; i++) {
if(cieq(name, node_table[i]->name)) { if(cieq(name, node_table[i]->name)) {
@ -152,14 +157,14 @@ struct dvec *EVTfindvec(
/* Get the UDN type index */ /* Get the UDN type index */
udn_index = node_table[i]->udn_index; udn_index = node_table[i]->udn_index;
if (!g_mif_info.ckt->evt->data.node) { if (!evt->data.node) {
// fprintf(stderr, "Warning: No event data available! \n Simulation not yet run?\n"); // fprintf(stderr, "Warning: No event data available! \n Simulation not yet run?\n");
tfree(name); tfree(name);
return(NULL); return(NULL);
} }
/* Count the number of events */ /* Count the number of events */
head = g_mif_info.ckt->evt->data.node->head[i]; head = evt->data.node->head[i];
for(event = head, num_events = 0; event; event = event->next) for(event = head, num_events = 0; event; event = event->next)
num_events++; num_events++;
@ -170,8 +175,7 @@ struct dvec *EVTfindvec(
/* Iterate through the events and fill the arrays. */ /* Iterate through the events and fill the arrays. */
/* Note that we create vertical segments every time an event occurs. */ /* Note that we create vertical segments every time an event occurs. */
/* Need to modify this in the future to complete the vector out to the */
/* last analysis point... */
for(i = 0, event = head; event; event = event->next) { for(i = 0, event = head; event; event = event->next) {
/* If not first point, put the second value of the horizontal line in the vectors */ /* If not first point, put the second value of the horizontal line in the vectors */
@ -194,6 +198,11 @@ struct dvec *EVTfindvec(
} }
/* Add one more point so that the line will extend to the end of the plot. */
anal_point_vec[i] = ckt->CKTtime;
value_vec[i++] = value;
/* Allocate dvec structures and assign the vectors into them. */ /* Allocate dvec structures and assign the vectors into them. */
/* See FTE/OUTinterface.c:plotInit() for initialization example. */ /* See FTE/OUTinterface.c:plotInit() for initialization example. */

View File

@ -14,6 +14,7 @@ sine
slew slew
square square
summer summer
xfer
s_xfer s_xfer
triangle triangle
file_source file_source

View File

@ -0,0 +1,130 @@
/* Transfer function block for AC simulation, based on s_xfer code model. */
#include <stdlib.h>
#define PI 3.141592653589793238462643383279502884197
/* How the table information is stored internally. */
struct data_pt {
double f; /* Frequency, radians/sec. */
Mif_Complex_t s; /* The S-parameter. */
};
static void cleanup(ARGS, Mif_Callback_Reason_t reason)
{
struct data_pt *table;
switch (reason) {
case MIF_CB_DESTROY:
table = (struct data_pt *)STATIC_VAR(table);
if (table) {
free(table);
STATIC_VAR(table) = NULL;
}
break;
}
}
void cm_xfer(ARGS) /* structure holding parms, inputs, outputs, etc. */
{
struct data_pt *table;
Mif_Complex_t ac_gain;
double factor;
int span, size, i;
span = PARAM(span);
if (INIT) {
Mif_Boolean_t ri, db, rad;
int offset, bad = 0, j;
/* Validate table. */
offset = PARAM(offset);
size = PARAM_SIZE(table);
bad = size % span;
if (!bad) {
for (i = 0; i < size - span; i += span) {
if (PARAM(table[i]) < 0 ||
PARAM(table[i + span]) < PARAM(table[i])) {
bad = 1;
break;
}
}
}
if (bad) {
cm_message_send("Warning: badly formed table.");
return;
}
/* Allocate the internal table. */
size /= span;
table = (struct data_pt *)calloc(size, sizeof(struct data_pt));
STATIC_VAR(table) = table;
CALLBACK = cleanup;
/* Fill it. */
ri = PARAM(r_i);
db = PARAM(db);
rad = PARAM(rad);
for (i = 0, j = 0; i < size; i++, j += span) {
table[i].f = PARAM(table[j]) * 2.0 * PI;
if (ri) {
table[i].s.real = PARAM(table[j + offset]);
table[i].s.imag = PARAM(table[j + offset + 1]);
} else {
double phase, mag;
mag = PARAM(table[j + offset]);
if (db)
mag = pow(10, mag / 20);
phase = PARAM(table[j + offset + 1]);
if (!rad)
phase *= 2 * PI / 360;
table[i].s.real = mag * cos(phase);
table[i].s.imag = mag * sin(phase);
}
}
}
table = (struct data_pt *)STATIC_VAR(table);
if (!table)
return;
if (ANALYSIS == MIF_AC) {
double rv;
size = PARAM_SIZE(table) / span;
rv = RAD_FREQ;
if (rv <= table[0].f) {
ac_gain = table[0].s;
} else if (rv >= table[size - 1].f) {
ac_gain = table[size - 1].s;
} else {
for (i = 0; i < size; i++) {
if (table[i].f > rv)
break;
}
/* Linear interpolation. */
factor = (rv - table[i - 1].f) / (table[i].f - table[i - 1].f);
ac_gain.real = table[i - 1].s.real +
factor * (table[i].s.real - table[i - 1].s.real);
ac_gain.imag = table[i - 1].s.imag +
factor * (table[i].s.imag - table[i - 1].s.imag);
}
AC_GAIN(out, in) = ac_gain;
} else { /* DC, transient ... */
if (ANALYSIS == MIF_TRAN) {
if (!STATIC_VAR(warned)) {
STATIC_VAR(warned) = 1;
cm_message_send("The xfer code model does not support "
"transient analysis.");
}
}
OUTPUT(out) = table[0].s.real * INPUT(in);
}
}

View File

@ -0,0 +1,91 @@
/* Interface specification for PWL transfer function code model. */
NAME_TABLE:
Spice_Model_Name: xfer
C_Function_Name: cm_xfer
Description: "AC transfer function block"
PORT_TABLE:
Port_Name: in out
Description: "input" "output"
Direction: in out
Default_Type: v v
Allowed_Types: [v,vd,i,id] [v,vd,i,id]
Vector: no no
Vector_Bounds: - -
Null_Allowed: no no
PARAMETER_TABLE:
Parameter_Name: table
Description: "PWL table: frequency/magnitude/phase"
Data_Type: real
Default_Value: -
Limits: -
Vector: yes
Vector_Bounds: [3 -]
Null_Allowed: no
PARAMETER_TABLE:
Parameter_Name: r_i
Description: "table is in real/imaginary format"
Data_Type: boolean
Default_Value: false
Limits: -
Vector: no
Vector_Bounds: -
Null_Allowed: yes
PARAMETER_TABLE:
Parameter_Name: db
Description: "table is in magnitude(dB)/phase format"
Data_Type: boolean
Default_Value: true
Limits: -
Vector: no
Vector_Bounds: -
Null_Allowed: yes
PARAMETER_TABLE:
Parameter_Name: rad
Description: "phase in radians, not degrees"
Data_Type: boolean
Default_Value: false
Limits: -
Vector: no
Vector_Bounds: -
Null_Allowed: yes
PARAMETER_TABLE:
Parameter_Name: span offset
Description: "Length of table rows" "Offset within row"
Data_Type: int int
Default_Value: 3 1
Limits: [ 3 - ] [ 1 - ]
Vector: no no
Vector_Bounds: - -
Null_Allowed: yes yes
/* This is used internally to store the table in compact complex form. */
STATIC_VAR_TABLE:
Static_Var_Name: table
Description: "Internal copy of data"
Data_Type: pointer
/* Only warn once about use in transient analysis. */
STATIC_VAR_TABLE:
Static_Var_Name: warned
Description: "Warning indicator"
Data_Type: int

View File

@ -404,6 +404,8 @@ void cm_d_pwm(ARGS)
*t3 = T(1) + (1 - dphase)/frequency; *t3 = T(1) + (1 - dphase)/frequency;
} }
cm_analog_set_temp_bkpt(*t1);
cm_analog_set_temp_bkpt(*t3);
} }
break; break;

View File

@ -935,7 +935,6 @@ lib /machine:x64 /def:..\..\fftw-3.3-dll64\libfftw3-3.def /out:$(IntDir)libfftw3
<ClInclude Include="..\src\frontend\variable.h" /> <ClInclude Include="..\src\frontend\variable.h" />
<ClInclude Include="..\src\frontend\vectors.h" /> <ClInclude Include="..\src\frontend\vectors.h" />
<ClInclude Include="..\src\frontend\wdisp\ftegraf.h" /> <ClInclude Include="..\src\frontend\wdisp\ftegraf.h" />
<ClInclude Include="..\src\frontend\wdisp\wincolor.h" />
<ClInclude Include="..\src\frontend\wdisp\windisp.h" /> <ClInclude Include="..\src\frontend\wdisp\windisp.h" />
<ClInclude Include="..\src\frontend\wdisp\winprint.h" /> <ClInclude Include="..\src\frontend\wdisp\winprint.h" />
<ClInclude Include="..\src\frontend\where.h" /> <ClInclude Include="..\src\frontend\where.h" />

View File

@ -942,7 +942,6 @@
<ClInclude Include="..\src\frontend\variable.h" /> <ClInclude Include="..\src\frontend\variable.h" />
<ClInclude Include="..\src\frontend\vectors.h" /> <ClInclude Include="..\src\frontend\vectors.h" />
<ClInclude Include="..\src\frontend\wdisp\ftegraf.h" /> <ClInclude Include="..\src\frontend\wdisp\ftegraf.h" />
<ClInclude Include="..\src\frontend\wdisp\wincolor.h" />
<ClInclude Include="..\src\frontend\wdisp\windisp.h" /> <ClInclude Include="..\src\frontend\wdisp\windisp.h" />
<ClInclude Include="..\src\frontend\wdisp\winprint.h" /> <ClInclude Include="..\src\frontend\wdisp\winprint.h" />
<ClInclude Include="..\src\frontend\where.h" /> <ClInclude Include="..\src\frontend\where.h" />

View File

@ -254,6 +254,8 @@
<ClCompile Include="icm\analog\file_source\file_source-ifspec.c" /> <ClCompile Include="icm\analog\file_source\file_source-ifspec.c" />
<ClCompile Include="icm\analog\delay\delay-cfunc.c" /> <ClCompile Include="icm\analog\delay\delay-cfunc.c" />
<ClCompile Include="icm\analog\delay\delay-ifspec.c" /> <ClCompile Include="icm\analog\delay\delay-ifspec.c" />
<ClCompile Include="icm\analog\xfer\xfer-cfunc.c" />
<ClCompile Include="icm\analog\xfer\xfer-ifspec.c" />
<ClCompile Include="..\..\src\xspice\icm\dlmain.c" /> <ClCompile Include="..\..\src\xspice\icm\dlmain.c" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -297,6 +299,8 @@
<None Include="..\..\src\xspice\icm\analog\file_source\ifspec.ifs" /> <None Include="..\..\src\xspice\icm\analog\file_source\ifspec.ifs" />
<None Include="..\..\src\xspice\icm\analog\delay\cfunc.mod" /> <None Include="..\..\src\xspice\icm\analog\delay\cfunc.mod" />
<None Include="..\..\src\xspice\icm\analog\delay\ifspec.ifs" /> <None Include="..\..\src\xspice\icm\analog\delay\ifspec.ifs" />
<None Include="..\..\src\xspice\icm\analog\xfer\cfunc.mod" />
<None Include="..\..\src\xspice\icm\analog\xfer\ifspec.ifs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\src\include\ngspice\dstring.h" /> <ClInclude Include="..\..\src\include\ngspice\dstring.h" />