Merge branch 'pre-master' into bt_dev
This commit is contained in:
commit
56272eb68c
73
INSTALL
73
INSTALL
|
|
@ -18,7 +18,7 @@ Table of contents
|
|||
1.5.1 Most useful options
|
||||
1.5.2 Options Specific to Enable Ngspice as a shared library
|
||||
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
|
||||
3 Compiling For Multiple Architectures
|
||||
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
|
||||
internal fft algorithms.
|
||||
|
||||
If you want to compile the source from the git repository you need
|
||||
additional software: autoconf, automake, libtool.
|
||||
If you want to compile the source from the git repository, or if you want to
|
||||
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:
|
||||
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
|
||||
information on ngspice and its usage.
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
$ 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
|
||||
arguments to ../configure are
|
||||
--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.
|
||||
|
||||
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:
|
||||
$ mkdir 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
|
||||
$ 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
|
||||
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
|
||||
$ mkdir debug
|
||||
$ cd debug
|
||||
|
|
@ -148,7 +159,7 @@ This file describes the procedures to install ngspice from sources.
|
|||
$ make
|
||||
$ 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.
|
||||
|
||||
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).
|
||||
|
||||
A fully featured ngspice on LINUX may be obtained with the following commands:
|
||||
$ ./autogen.sh --adms
|
||||
$ ./autogen.sh
|
||||
$ mkdir 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
|
||||
$ 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.
|
||||
|
||||
|
||||
1.4 ngspice as a shared library
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
|
||||
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
|
||||
Hat Like Distributions.pdf", provided by Justin Fisher, available with
|
||||
the ngspice distribution.
|
||||
|
||||
CentOS users may need to add -std=c99 to the CFLAGS in their ../configure
|
||||
statement.
|
||||
|
||||
|
||||
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)
|
||||
|
||||
A fully featured ngspice on Windows may be obtained with the following commands:
|
||||
$ ./autogen.sh --adms
|
||||
$ ./autogen.sh
|
||||
$ mkdir 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
|
||||
|
||||
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
|
||||
$ cd /d/Spice/ngspice
|
||||
Start compiling, e.g. by calling
|
||||
$ ./autogen.sh --adms
|
||||
$ ./autogen.sh
|
||||
$ ./compile_min.sh
|
||||
|
||||
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
|
||||
for the X11 graphics (not available in mingw). A typical configure command
|
||||
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
|
||||
|
||||
|
||||
|
|
@ -708,7 +723,9 @@ cross-compile-shared.sh.
|
|||
3. Execute this command:
|
||||
sudo port install autoconf automake libtool bison flex ncurses
|
||||
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".
|
||||
A complete set of features is:
|
||||
./configure --enable-cider --enable-xspice --enable-openmp --enable-pss --enable-debug=no
|
||||
|
|
|
|||
|
|
@ -9,10 +9,13 @@
|
|||
# for details please see the ngspice manual, chapt. 32.1.
|
||||
# Declare 'compile_linux.sh' executable and start compiling with
|
||||
# './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:
|
||||
# --adms and --enable-adms will install extra HICUM, EKV and MEXTRAM models via the
|
||||
# adms interface. You need to download and install the *.va files via ng-adms-va.tgz
|
||||
# Please see the ngspice manual, chapt. 13, for more info on adms.
|
||||
# --enable-osdi will enable the OSDI interface, which, in conjuction with the
|
||||
# external OpenVAF Verilig-A compiler, will allow access to advanced compact
|
||||
# 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.
|
||||
# --disable-debug will give O2 optimization (versus O0 for debug) and removes all debugging info.
|
||||
|
||||
|
|
@ -39,26 +42,18 @@ fi
|
|||
./autogen.sh
|
||||
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
|
||||
if test "$1" = "d"; then
|
||||
cd debug
|
||||
if [ $? -ne 0 ]; then echo "cd debug failed"; exit 1 ; fi
|
||||
echo "configuring for 64 bit debug"
|
||||
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"
|
||||
else
|
||||
cd release
|
||||
if [ $? -ne 0 ]; then echo "cd release failed"; exit 1 ; fi
|
||||
echo "configuring for 64 bit release"
|
||||
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"
|
||||
fi
|
||||
if [ $? -ne 0 ]; then echo "../configure failed"; exit 1 ; fi
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
MOSdriver -- lossy line LTRA model -- C load
|
||||
m5 0 168 2 0 mn0p9 w = 18.0u l=0.9u
|
||||
m6 1 168 2 1 mp1p0 w = 36.0u l=1.0u
|
||||
m5 2 168 0 0 mn0p9 w = 18.0u l=0.9u
|
||||
m6 2 168 1 1 mp1p0 w = 36.0u l=1.0u
|
||||
CN2 2 0 0.025398e-12
|
||||
CN3 3 0 0.007398e-12
|
||||
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 )
|
||||
.control
|
||||
TRAN 0.2N 47N 0 0.1N
|
||||
rusage
|
||||
plot v(2) v(3) ylimit -0.5 5
|
||||
.endc
|
||||
.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
|
||||
+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
|
||||
+len=16 steplimit compactrel=1.0e-3 compactabs=1.0e-14
|
||||
.end
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
.control
|
||||
option noinit
|
||||
TRAN 0.1N 47.9N
|
||||
rusage
|
||||
plot v(5) v(6) v(7) v(8) v(9) v(10) v(11) v(12)
|
||||
.endc
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
MOSdriver -- 2 lossy lines LTRA model -- C load
|
||||
m5 0 168 2 0 mn0p9 w = 18.0u l=0.9u
|
||||
m6 1 168 2 1 mp1p0 w = 36.0u l=1.0u
|
||||
m1 0 3 4 0 mn0p9 w = 18.0u l=0.9u
|
||||
m2 1 3 4 1 mp1p0 w = 36.0u l=1.0u
|
||||
m5 2 168 0 0 mn0p9 w = 18.0u l=0.9u
|
||||
m6 2 168 1 1 mp1p0 w = 36.0u l=1.0u
|
||||
m1 4 3 0 0 mn0p9 w = 18.0u l=0.9u
|
||||
m2 4 3 1 1 mp1p0 w = 36.0u l=1.0u
|
||||
CN2 2 0 0.025398e-12
|
||||
CN3 3 0 0.007398e-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 )
|
||||
.control
|
||||
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
|
||||
.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
|
||||
|
|
|
|||
|
|
@ -84,6 +84,9 @@ VS2 268 0 PULSE (0 5 15.9N 0.2N 0.2N 15.8N 60N)
|
|||
*
|
||||
.control
|
||||
TRAN 0.2N 47.9NS
|
||||
rusage
|
||||
set color0=white
|
||||
set xbrushwidth=3
|
||||
PLOT v(648) v(651) v(751)
|
||||
.endc
|
||||
*
|
||||
|
|
|
|||
|
|
@ -53,6 +53,9 @@ x3 3 4 10 dioload
|
|||
+reltol=1e-3 abstol=1e-14
|
||||
.control
|
||||
tran 0.1ns 60ns
|
||||
rusage
|
||||
set color0=white
|
||||
set xbrushwidth=3
|
||||
plot v(1) v(2) v(3)
|
||||
.endc
|
||||
|
||||
|
|
|
|||
|
|
@ -60,6 +60,9 @@ x1 2 3 xonecm
|
|||
tran 0.001ns 10ns 0 0.1ns
|
||||
* onecm10
|
||||
*tran 0.001ns 10ns 0 0.01ns
|
||||
rusage
|
||||
set color0=white
|
||||
set xbrushwidth=3
|
||||
plot v(1) v(2) v(3)
|
||||
.endc
|
||||
|
||||
|
|
|
|||
|
|
@ -75,6 +75,9 @@ rt2 5 0 50
|
|||
.options acct reltol=1e-3 abstol=1e-12
|
||||
.control
|
||||
tran 0.1ns 60ns
|
||||
rusage
|
||||
*set color0=white
|
||||
set xbrushwidth=3
|
||||
plot v(2) v(4) v(5)
|
||||
.endc
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
.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)
|
||||
.endc
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
* ISCAS85 benchmark circuit SPICE netlist
|
||||
* ISCAS85 benchmark circuit SPICE netlist, PSP103
|
||||
* generated by spicegen.pl 1.0
|
||||
* by Jingye Xu @ VLSI group, Dept of ECE, UIC
|
||||
* Modified for PSP103 model via OSDI/OpenVAF by Holger Vogt
|
||||
|
||||
* Path to the models
|
||||
.include Modelcards/psp103_nmos-2.mod
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@
|
|||
if $?batchmode
|
||||
else
|
||||
run
|
||||
rusage time
|
||||
plot v(16) v(13) v(17) v(1)+6 v(4)+6 v(3)+6
|
||||
end
|
||||
.endc
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
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
|
||||
vb b 0 1
|
||||
ib 0 b 10u
|
||||
ve e 0 0
|
||||
vs s 0 0
|
||||
vc1 c c1 0
|
||||
|
|
@ -9,42 +8,16 @@ vb1 b b1 0
|
|||
ve1 e e1 0
|
||||
vs1 s s1 0
|
||||
.temp 27
|
||||
Q1 c1 b1 e1 s1 t mod1 area=1
|
||||
.model mod1 npn Level=4
|
||||
+ Tnom=27 RCX=10 RCI=60 VO=2 GAMM=2.e-11
|
||||
+ 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
|
||||
Q1 c1 b1 e1 s1 dt M_BFP780 area=1
|
||||
|
||||
.include Infineon_VBIC.lib
|
||||
|
||||
.control
|
||||
dc vc 0.0 5.0001 0.05 vb 0.7 1.0001 0.05
|
||||
altermod @mod1[RTH]=0
|
||||
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
|
||||
settype temperature v(dt)
|
||||
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
|
||||
.endc
|
||||
.end
|
||||
|
|
|
|||
|
|
@ -18,17 +18,18 @@ xinv7 9 8 1 0 inv
|
|||
xinv8 10 9 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 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 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 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
|
||||
|
||||
run
|
||||
rusage
|
||||
* 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
|
||||
|
||||
.end
|
||||
|
|
|
|||
|
|
@ -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
|
||||
save cont s1 s2 u1 d1
|
||||
set xbrushwidth=2
|
||||
let isbmode = $?batchmode
|
||||
if isbmode = 0
|
||||
iplot cont
|
||||
iplot -w $&simtime cont
|
||||
endif
|
||||
* calculate breakpoint for switching frequency
|
||||
let t1_3 = simtime/3
|
||||
|
|
|
|||
|
|
@ -66,10 +66,31 @@ TWOdestroy(TWOdevice *pDevice)
|
|||
FREE( pElem );
|
||||
}
|
||||
FREE( pDevice->elements );
|
||||
for (int xIndex = 1; xIndex < pDevice->numXNodes; xIndex++) {
|
||||
FREE(pDevice->elemArray[xIndex]);
|
||||
}
|
||||
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 */
|
||||
|
||||
FREE( pDevice );
|
||||
|
|
|
|||
|
|
@ -205,7 +205,26 @@ com_iplot(wordlist *wl)
|
|||
/* settrace(wl, VF_PLOT); */
|
||||
|
||||
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
|
||||
vectors on the same command line and db_next denotes
|
||||
|
|
@ -215,6 +234,7 @@ com_iplot(wordlist *wl)
|
|||
d = TMALLOC(struct dbcomm, 1);
|
||||
d->db_analysis = NULL;
|
||||
d->db_number = debugnumber++;
|
||||
d->db_value1 = window; // Field re-use
|
||||
if (eq(s, "all")) {
|
||||
d->db_type = DB_IPLOTALL;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -426,7 +426,7 @@ struct comm spcp_coms[] = {
|
|||
{ "iplot", com_iplot, TRUE, TRUE,
|
||||
{ 0200, 0200, 0200, 0200 }, E_DEFHMASK, 0, LOTS,
|
||||
NULL,
|
||||
"[all] [node ...] : Incrementally plot a node." } ,
|
||||
"[-w width] [all] [node ...] : Incrementally plot nodes." } ,
|
||||
{ "status", com_sttus, TRUE, FALSE,
|
||||
{ 0, 0, 0, 0 }, E_DEFHMASK, 0, 0,
|
||||
NULL,
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ doop(char what,
|
|||
struct dvec *v1, *v2, *res;
|
||||
ngcomplex_t *c1 = NULL, *c2 = NULL, lc;
|
||||
double *d1 = NULL, *d2 = NULL, ld;
|
||||
int length = 0, i;
|
||||
int length = 0, i, longer;
|
||||
void *data;
|
||||
bool free1 = FALSE, free2 = FALSE, relflag = FALSE;
|
||||
|
||||
|
|
@ -253,6 +253,7 @@ doop(char what,
|
|||
/* Make sure we have data of the same length. */
|
||||
length = ((v1->v_length > v2->v_length) ? v1->v_length : v2->v_length);
|
||||
if (v1->v_length < length) {
|
||||
longer = 2;
|
||||
free1 = TRUE;
|
||||
if (isreal(v1)) {
|
||||
ld = 0.0;
|
||||
|
|
@ -275,6 +276,7 @@ doop(char what,
|
|||
c1[i] = lc;
|
||||
}
|
||||
} else {
|
||||
longer = 0;
|
||||
if (isreal(v1))
|
||||
d1 = v1->v_realdata;
|
||||
else
|
||||
|
|
@ -282,6 +284,7 @@ doop(char what,
|
|||
}
|
||||
|
||||
if (v2->v_length < length) {
|
||||
longer = 1;
|
||||
free2 = TRUE;
|
||||
if (isreal(v2)) {
|
||||
ld = 0.0;
|
||||
|
|
@ -335,10 +338,27 @@ doop(char what,
|
|||
}
|
||||
|
||||
/* This is a non-obvious thing */
|
||||
|
||||
if (v1->v_scale != v2->v_scale) {
|
||||
fprintf(cp_err, "Warning: scales of %s and %s are different.\n",
|
||||
v1->v_name, v2->v_name);
|
||||
res->v_scale = NULL;
|
||||
switch (longer) {
|
||||
case 0:
|
||||
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 {
|
||||
res->v_scale = v1->v_scale;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ cp_init(void)
|
|||
cp_chars[128]
|
||||
cp_maxhistlength (set to 10000 in com_history.c)
|
||||
cp_curin, cp_curout, cp_curerr (defined in streams.c)
|
||||
cp_no_histsubst
|
||||
*/
|
||||
{
|
||||
cp_vset("history", CP_NUM, &cp_maxhistlength);
|
||||
|
|
@ -28,6 +29,10 @@ cp_init(void)
|
|||
cp_curout = stdout;
|
||||
cp_curerr = stderr;
|
||||
|
||||
/* Enable history substitution */
|
||||
if (cp_getvar("histsubst", CP_BOOL, NULL, 0))
|
||||
cp_no_histsubst = FALSE;
|
||||
|
||||
/* io redirection in streams.c:
|
||||
cp_in set to cp_curin etc. */
|
||||
cp_ioreset();
|
||||
|
|
|
|||
|
|
@ -890,23 +890,36 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile)
|
|||
/* handle .if ... .elseif ... .else ... .endif statements. */
|
||||
dotifeval(deck);
|
||||
|
||||
/* get csparams and create vectors, available
|
||||
in plot 'const' of a .control section */
|
||||
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)) {
|
||||
wordlist *wlist = NULL;
|
||||
char *cstoken[3];
|
||||
int i;
|
||||
dd->line[0] = '*';
|
||||
s = skip_ws(dd->line + 8);
|
||||
cstoken[0] = gettok_char(&s, '=', FALSE, FALSE);
|
||||
cstoken[1] = gettok_char(&s, '=', TRUE, FALSE);
|
||||
cstoken[2] = gettok(&s);
|
||||
for (i = 3; --i >= 0; ) {
|
||||
wlist = wl_cons(cstoken[i], wlist);
|
||||
while (s && *s) {
|
||||
char* nexttoken = s;
|
||||
cstoken[0] = gettok_char(&s, '=', FALSE, FALSE);
|
||||
cstoken[1] = gettok_char(&s, '=', TRUE, FALSE);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -895,6 +895,9 @@ void inp_probe(struct card* deck)
|
|||
else if (err == 2) {
|
||||
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;
|
||||
}
|
||||
else if (!haveall) {
|
||||
|
|
@ -1358,6 +1361,15 @@ static int setallvsources(struct card *tmpcard, NGHASHPTR instances, char *instn
|
|||
char nodenumstr[3];
|
||||
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);
|
||||
|
||||
char* vline = tprintf("vcurr_%s:probe_int_%s:%s_%s %s %s 0", instname, nodename1, nodenumstr, strnode1, strnode1, newnode);
|
||||
|
|
|
|||
|
|
@ -136,7 +136,6 @@ static void inp_reorder_params(
|
|||
static int inp_split_multi_param_lines(struct card *deck, int line_number);
|
||||
static void inp_sort_params(struct card *param_cards,
|
||||
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_bsource_compat(struct card *deck);
|
||||
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 inp_fix_macro_param_func_paren_io(struct card *begin_card);
|
||||
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 char *get_quoted_token(char *string, char **token);
|
||||
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_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);
|
||||
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);
|
||||
|
||||
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_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_mvalue(char* line, char* tline);
|
||||
|
||||
static void rem_double_braces(struct card* card);
|
||||
|
||||
extern void inp_probe(struct card* card);
|
||||
#ifndef EXT_ASC
|
||||
static void utf8_syntax_check(struct card *deck);
|
||||
|
|
@ -619,16 +616,19 @@ static char *cat2strings(char *s1, char *s2, bool spa)
|
|||
/* line1
|
||||
+ line2
|
||||
---->
|
||||
line1 line 2
|
||||
line1 line2
|
||||
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) {
|
||||
char *s, c, *buffer;
|
||||
char* s, c;
|
||||
|
||||
for (s = working->line; (c = *s) != '\0' && c <= ' '; s++)
|
||||
;
|
||||
|
|
@ -636,11 +636,110 @@ static void inp_stitch_continuation_lines(struct card *working)
|
|||
#ifdef TRACE
|
||||
/* SDB debug statement */
|
||||
printf("In inp_read, processing linked list element line = %d, s = "
|
||||
"%s . . . \n",
|
||||
working->linenum, s);
|
||||
"%s . . . \n",
|
||||
working->linenum, s);
|
||||
#endif
|
||||
|
||||
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 '*':
|
||||
|
|
@ -653,7 +752,7 @@ static void inp_stitch_continuation_lines(struct card *working)
|
|||
case '+': /* handle continuation */
|
||||
if (!prev) {
|
||||
working->error =
|
||||
copy("Illegal continuation line: ignored.");
|
||||
copy("Illegal continuation line: ignored.");
|
||||
working = working->nextcard;
|
||||
break;
|
||||
}
|
||||
|
|
@ -662,7 +761,7 @@ static void inp_stitch_continuation_lines(struct card *working)
|
|||
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;
|
||||
struct card* tmpl = prev->nextcard->nextcard;
|
||||
line_free_x(prev->nextcard, FALSE);
|
||||
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.
|
||||
When reading a PDK, the following may be called more than 1e6 times. */
|
||||
#if defined (_MSC_VER)
|
||||
/* 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,
|
||||
MINGW is 36. */
|
||||
/* 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,
|
||||
MINGW is 36. */
|
||||
buffer = tprintf("%s %s", prev->line, s + 1);
|
||||
#else
|
||||
/* vsnprintf in Linux is very inefficient, ref. value 24
|
||||
cat2strings() is efficient with ref. speed value 6,
|
||||
MINGW is 12 */
|
||||
/* vsnprintf in Linux is very inefficient, ref. value 24
|
||||
cat2strings() is efficient with ref. speed value 6,
|
||||
MINGW is 12 */
|
||||
buffer = cat2strings(prev->line, s + 1, TRUE);
|
||||
#endif
|
||||
/* replace prev->line by buffer */
|
||||
|
|
@ -687,16 +786,16 @@ static void inp_stitch_continuation_lines(struct card *working)
|
|||
working->nextcard = NULL;
|
||||
/* add original line to prev->actualLine */
|
||||
if (prev->actualLine) {
|
||||
struct card *end;
|
||||
struct card* end;
|
||||
for (end = prev->actualLine; end->nextcard;
|
||||
end = end->nextcard)
|
||||
end = end->nextcard)
|
||||
;
|
||||
end->nextcard = working;
|
||||
tfree(s);
|
||||
}
|
||||
else {
|
||||
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->nextcard = working;
|
||||
}
|
||||
|
|
@ -706,11 +805,15 @@ static void inp_stitch_continuation_lines(struct card *working)
|
|||
default: /* regular one-line card */
|
||||
prev = working;
|
||||
working = working->nextcard;
|
||||
iscmod = is_cider_model(s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
working = working->nextcard;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* search for `=' assignment operator
|
||||
|
|
@ -929,8 +1032,8 @@ struct card *inp_readall(FILE *fp, const char *dir_name,
|
|||
utf8_syntax_check(working);
|
||||
#endif
|
||||
|
||||
/* some syntax checks, including title line */
|
||||
inp_check_syntax(cc);
|
||||
/* some syntax checks, excluding title line */
|
||||
inp_check_syntax(working);
|
||||
|
||||
if (newcompat.lt && newcompat.a)
|
||||
ltspice_compat_a(working);
|
||||
|
|
@ -992,7 +1095,7 @@ struct card *inp_readall(FILE *fp, const char *dir_name,
|
|||
subckt_w_params = NULL;
|
||||
if (!cp_getvar("no_auto_gnd", CP_BOOL, NULL, 0))
|
||||
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. */
|
||||
|
||||
|
|
@ -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. */
|
||||
inp_stripcomments_deck(cc->nextcard, comfile || is_control);
|
||||
|
||||
#ifdef CIDER
|
||||
inp_cider_models(cc->nextcard);
|
||||
#endif
|
||||
|
||||
inp_stitch_continuation_lines(cc->nextcard);
|
||||
|
||||
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
|
||||
*
|
||||
|
|
@ -1924,7 +2030,336 @@ static void inp_fix_gnd_name(struct card *c)
|
|||
* 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;
|
||||
|
||||
|
|
@ -1945,143 +2380,17 @@ static void inp_chk_for_multi_in_vcvs(struct card *c, int *line_number)
|
|||
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 ||
|
||||
(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
|
||||
}
|
||||
}
|
||||
replace_freq(c, line_number);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* If ngspice is started with option -a, then variable 'autorun'
|
||||
* will be set and a control section is inserted to try and ensure
|
||||
* 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)
|
||||
* or
|
||||
* 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)
|
||||
{
|
||||
for (; c; c = c->nextcard)
|
||||
if (ciprefix(".lib", c->line))
|
||||
for (; c; c = c->nextcard) {
|
||||
struct card* p = c;
|
||||
if (ciprefix(".libsave", c->line)) {
|
||||
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
|
||||
inside a pair of square brackets */
|
||||
end_of_str = beg_of_str;
|
||||
while (*end_of_str != ']')
|
||||
while (*end_of_str != ']' && *end_of_str != '\0')
|
||||
end_of_str++;
|
||||
/* string xx yyy from vector [xx yyy] */
|
||||
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
|
||||
brackets around all params inside a pair < > */
|
||||
end_of_str = beg_of_str;
|
||||
while (*end_of_str != '>')
|
||||
while (*end_of_str != '>' && *end_of_str != '\0')
|
||||
end_of_str++;
|
||||
/* string xx yyy from vector [xx yyy] */
|
||||
vec_str = copy_substring(beg_of_str + 1, end_of_str);
|
||||
|
|
@ -4480,7 +4799,8 @@ static int inp_get_param_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 i, j, k;
|
||||
|
|
@ -4488,6 +4808,9 @@ int get_number_terminals(char *c)
|
|||
char nam_buf[128];
|
||||
bool area_found = FALSE;
|
||||
|
||||
if (!c)
|
||||
return 0;
|
||||
|
||||
switch (*c) {
|
||||
case 'r':
|
||||
case 'c':
|
||||
|
|
@ -5917,14 +6240,9 @@ static void inp_compat(struct card *card)
|
|||
/* Find equation, starts with '{', till end of line */
|
||||
str_ptr = strchr(cut_line, '{');
|
||||
if (str_ptr == NULL) {
|
||||
/* if not, equation may start with a '(' */
|
||||
str_ptr = strchr(cut_line, '(');
|
||||
if (str_ptr == NULL) {
|
||||
fprintf(stderr, "ERROR: mal formed R line: %s\n",
|
||||
curr_line);
|
||||
controlled_exit(EXIT_FAILURE);
|
||||
}
|
||||
equation = gettok_char(&str_ptr, ')', TRUE, TRUE);
|
||||
fprintf(stderr, "ERROR: mal formed R line: %s\n", curr_line);
|
||||
fprintf(stderr, " {...} or '...' around equation's right hand side are missing!\n");
|
||||
controlled_exit(EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
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 */
|
||||
str_ptr = strchr(cut_line, '{');
|
||||
if (str_ptr == NULL) {
|
||||
/* if not, equation may start with a '(' */
|
||||
str_ptr = strchr(cut_line, '(');
|
||||
if (str_ptr == NULL) {
|
||||
fprintf(stderr, "ERROR: mal formed C line: %s\n",
|
||||
curr_line);
|
||||
controlled_exit(EXIT_FAILURE);
|
||||
}
|
||||
equation = gettok_char(&str_ptr, ')', TRUE, TRUE);
|
||||
fprintf(stderr, "ERROR: mal formed C line: %s\n", curr_line);
|
||||
fprintf(stderr, " {...} or '...' around equation's right hand side are missing!\n");
|
||||
controlled_exit(EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
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 */
|
||||
str_ptr = strchr(cut_line, '{');
|
||||
if (str_ptr == NULL) {
|
||||
/* if not, equation may start with a '(' */
|
||||
str_ptr = strchr(cut_line, '(');
|
||||
if (str_ptr == NULL) {
|
||||
fprintf(stderr, "ERROR: mal formed L line: %s\n",
|
||||
curr_line);
|
||||
controlled_exit(EXIT_FAILURE);
|
||||
}
|
||||
equation = gettok_char(&str_ptr, ')', TRUE, TRUE);
|
||||
fprintf(stderr, "ERROR: mal formed L line: %s\n", curr_line);
|
||||
fprintf(stderr, " {...} or '...' around equation's right hand side are missing!\n");
|
||||
controlled_exit(EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
equation = gettok_char(&str_ptr, '}', TRUE, TRUE);
|
||||
|
|
@ -6921,6 +7229,27 @@ static void inp_poly_err(struct card *card)
|
|||
|
||||
#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
|
||||
* tprint(working);
|
||||
|
|
@ -8020,14 +8349,14 @@ static void inp_check_syntax(struct card *deck)
|
|||
if (*cut_line == '*' || *cut_line == '\0')
|
||||
continue;
|
||||
// check for unusable leading characters and change them to '*'
|
||||
if (strchr("=[]?()&%$\"!:,\f;", *cut_line)) {
|
||||
if (strchr("=[]?()&%$\"!:,\f", *cut_line)) {
|
||||
if (ft_stricterror) {
|
||||
fprintf(stderr, "Error: '%c' is not allowed as first character in line %s.\n", *cut_line, cut_line);
|
||||
controlled_exit(EXIT_BAD);
|
||||
}
|
||||
else {
|
||||
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, " Check line no %d: %s\n\n", card->linenum_orig, cut_line);
|
||||
check_ch = 1; /* just one warning */
|
||||
|
|
@ -8035,6 +8364,10 @@ static void inp_check_syntax(struct card *deck)
|
|||
*cut_line = '*';
|
||||
}
|
||||
}
|
||||
/* leading end-of-line delimiter ';' silently change to '*' */
|
||||
else if (*cut_line == ';') {
|
||||
*cut_line = '*';
|
||||
}
|
||||
// check for .control ... .endc
|
||||
if (ciprefix(".control", cut_line)) {
|
||||
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 */
|
||||
if (check_control == 0 && strchr("VvIi", *cut_line)) {
|
||||
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)
|
||||
continue;
|
||||
/* skip ac */
|
||||
|
|
@ -8109,17 +8452,20 @@ static void inp_check_syntax(struct card *deck)
|
|||
char* nnacline = nacline;
|
||||
/* get first token after ac */
|
||||
char* numtok = gettok_node(&nnacline);
|
||||
char* numtokfree = numtok;
|
||||
/* Check if token is a parameter, to be filled in later */
|
||||
if (*numtok == '\'' || *numtok == '{') {
|
||||
err = 0;
|
||||
if (numtok) {
|
||||
char* numtokfree = numtok;
|
||||
/* Check if token is a parameter, to be filled in later */
|
||||
if (*numtok == '\'' || *numtok == '{') {
|
||||
err = 0;
|
||||
}
|
||||
else {
|
||||
/* check if token is a valid number */
|
||||
INPevaluate(&numtok, &err, 0);
|
||||
}
|
||||
tfree(numtokfree);
|
||||
}
|
||||
else {
|
||||
/* check if token is a valid number */
|
||||
INPevaluate(&numtok, &err, 0);
|
||||
}
|
||||
|
||||
tfree(numtokfree);
|
||||
else
|
||||
err = 1;
|
||||
}
|
||||
/* if no number, replace 'ac' by 'ac 1 0' */
|
||||
if (err){
|
||||
|
|
@ -8672,7 +9018,7 @@ utf8_syntax_check(struct card *deck)
|
|||
s = utf8_check((unsigned char*)curr_line);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -283,6 +283,22 @@ do_measure(
|
|||
resname = 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 (!chk_only) {
|
||||
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);
|
||||
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 (!chk_only) {
|
||||
fprintf(cp_err, "Error: unrecognized analysis type '%s' for the following .meas statement on line %d:\n", an_type, meas_card->linenum);
|
||||
|
|
|
|||
|
|
@ -1611,8 +1611,12 @@ nupa_subcktcall(dico_t *dico, const char *s, const char *x,
|
|||
jp = getexpress(dico, NULL, &ustr, jp);
|
||||
} else {
|
||||
jp++;
|
||||
if ((unsigned char) (*kp) > ' ')
|
||||
message(dico, "Subckt call, symbol %c not understood\n", *kp);
|
||||
if ((unsigned char)(*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
|
||||
|
|
|
|||
|
|
@ -627,7 +627,7 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr)
|
|||
if (!orflag && !ft_norefprint) {
|
||||
currclock = clock();
|
||||
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);
|
||||
lastclock = currclock;
|
||||
}
|
||||
|
|
@ -640,7 +640,7 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr)
|
|||
if (!orflag && !ft_norefprint) {
|
||||
currclock = clock();
|
||||
if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) {
|
||||
fprintf(stderr, " Reference value : % 12.5e\r",
|
||||
fprintf(stdout, " Reference value : % 12.5e\r",
|
||||
refValue->rValue);
|
||||
lastclock = currclock;
|
||||
}
|
||||
|
|
@ -735,10 +735,10 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr)
|
|||
currclock = clock();
|
||||
if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) {
|
||||
if (run->isComplex) {
|
||||
fprintf(stderr, " Reference value : % 12.5e\r",
|
||||
fprintf(stdout, " Reference value : % 12.5e\r",
|
||||
refValue ? refValue->cValue.real : NAN);
|
||||
} else {
|
||||
fprintf(stderr, " Reference value : % 12.5e\r",
|
||||
fprintf(stdout, " Reference value : % 12.5e\r",
|
||||
refValue ? refValue->rValue : NAN);
|
||||
}
|
||||
lastclock = currclock;
|
||||
|
|
@ -1506,7 +1506,7 @@ InterpFileAdd(runDesc *run, IFvalue *refValue, IFvalue *valuePtr)
|
|||
if (!orflag && !ft_norefprint) {
|
||||
currclock = clock();
|
||||
if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) {
|
||||
fprintf(stderr, " Reference value : % 12.5e\r",
|
||||
fprintf(stdout, " Reference value : % 12.5e\r",
|
||||
refValue->rValue);
|
||||
lastclock = currclock;
|
||||
}
|
||||
|
|
@ -1670,7 +1670,7 @@ InterpPlotAdd(runDesc *run, IFvalue *refValue, IFvalue *valuePtr)
|
|||
if (!orflag && !ft_norefprint) {
|
||||
currclock = clock();
|
||||
if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) {
|
||||
fprintf(stderr, " Reference value : % 12.5e\r",
|
||||
fprintf(stdout, " Reference value : % 12.5e\r",
|
||||
refValue->rValue);
|
||||
lastclock = currclock;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -360,6 +360,7 @@ struct func ft_funcs[] = {
|
|||
{ "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 */
|
||||
{ "vector", cx_vector },
|
||||
{ "cvector", cx_cvector },
|
||||
{ "unitvec", cx_unitvec },
|
||||
{ "length", cx_length },
|
||||
{ "vecmin", cx_min },
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
|
|||
#include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
|
||||
bool cp_no_histsubst = FALSE; /* perform history substitution by default */
|
||||
/* perform history substitution only when variable 'histsubst' is set */
|
||||
bool cp_no_histsubst = TRUE;
|
||||
|
||||
/* Things go as follows:
|
||||
* (1) Read the line and do some initial quoting (by setting the 8th bit),
|
||||
|
|
|
|||
|
|
@ -32,8 +32,7 @@ Author: 1988 Jeffrey M. Hsu
|
|||
|
||||
|
||||
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 unset, short mode);
|
||||
static void set(struct plot *plot, struct dbcomm *db, bool value, short mode);
|
||||
static char *getitright(char *buf, double num);
|
||||
|
||||
/* 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 ??
|
||||
* It would be better to associate a color with an instance using a
|
||||
* 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) {
|
||||
fprintf(cp_err, "Entering iplot, len = %d\n", len);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
struct dvec *v, *xs = pl->pl_scale;
|
||||
double *lims, dy;
|
||||
double start, stop, step;
|
||||
bool changed = FALSE;
|
||||
int yt;
|
||||
double xlims[2], ylims[2];
|
||||
struct dvec *v, *xs = pl->pl_scale;
|
||||
double *lims, dy;
|
||||
double start, stop, step;
|
||||
bool changed = FALSE;
|
||||
int id, yt;
|
||||
double xlims[2], ylims[2];
|
||||
static REQUEST reqst = { checkup_option, NULL };
|
||||
int inited = 0;
|
||||
int n_vec_plot = 0;
|
||||
int inited = 0;
|
||||
int n_vec_plot = 0;
|
||||
|
||||
/* Exit if nothing is being plotted */
|
||||
for (v = pl->pl_dvecs; v; v = v->v_next) {
|
||||
|
|
@ -878,7 +880,8 @@ static int iplot(struct plot *pl, int id)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (len == IPOINTMIN || !id) { /* Do initialization */
|
||||
id = db->db_graphid;
|
||||
if (!id) { /* Do initialization */
|
||||
unsigned int index, node_len;
|
||||
char commandline[4196];
|
||||
|
||||
|
|
@ -889,6 +892,14 @@ static int iplot(struct plot *pl, int id)
|
|||
lims = ft_minmax(xs, TRUE);
|
||||
xlims[0] = lims[0];
|
||||
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[1] = -ylims[0];
|
||||
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) {
|
||||
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]);
|
||||
}
|
||||
|
||||
|
|
@ -943,9 +954,9 @@ static int iplot(struct plot *pl, int id)
|
|||
}
|
||||
inited = 1;
|
||||
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* plot the last points and resize if needed */
|
||||
|
||||
Input(&reqst, NULL);
|
||||
|
||||
/* Window was closed? */
|
||||
|
|
@ -954,6 +965,7 @@ static int iplot(struct plot *pl, int id)
|
|||
return 0;
|
||||
|
||||
/* First see if we have to make the screen bigger */
|
||||
|
||||
dy = (isreal(xs) ? xs->v_realdata[len - 1] :
|
||||
realpart(xs->v_compdata[len - 1]));
|
||||
if (ft_grdb) {
|
||||
|
|
@ -964,8 +976,10 @@ static int iplot(struct plot *pl, int id)
|
|||
stop = HUGE;
|
||||
start = - stop;
|
||||
}
|
||||
|
||||
/* checking for x lo */
|
||||
while (dy < currentgraph->data.xmin) {
|
||||
|
||||
if (dy < currentgraph->data.xmin) {
|
||||
changed = TRUE;
|
||||
if (ft_grdb) {
|
||||
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)
|
||||
* XFACTOR);
|
||||
}
|
||||
|
||||
/* set the new x lo value */
|
||||
currentgraph->data.xmin -=
|
||||
(currentgraph->data.xmax - currentgraph->data.xmin)
|
||||
* XFACTOR;
|
||||
if (currentgraph->data.xmin < start) {
|
||||
currentgraph->data.xmin = start;
|
||||
break;
|
||||
|
||||
if (window) {
|
||||
currentgraph->data.xmin = dy - (window / 3.0);
|
||||
} else {
|
||||
currentgraph->data.xmin -=
|
||||
(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 */
|
||||
while (dy > currentgraph->data.xmax) {
|
||||
|
||||
if (window && changed) {
|
||||
currentgraph->data.xmax = currentgraph->data.xmin + window;
|
||||
} else if (dy > currentgraph->data.xmax) {
|
||||
changed = TRUE;
|
||||
if (ft_grdb) {
|
||||
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)
|
||||
* XFACTOR);
|
||||
}
|
||||
|
||||
/* set the new x hi value */
|
||||
currentgraph->data.xmax +=
|
||||
(currentgraph->data.xmax - currentgraph->data.xmin) *
|
||||
XFACTOR;
|
||||
if (currentgraph->data.xmax > stop) {
|
||||
currentgraph->data.xmax = stop;
|
||||
break;
|
||||
|
||||
if (window) {
|
||||
currentgraph->data.xmax = dy + (window / 3.0);
|
||||
currentgraph->data.xmin = currentgraph->data.xmax - window;
|
||||
} else {
|
||||
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 */
|
||||
|
||||
for (v = pl->pl_dvecs; v; v = v->v_next) {
|
||||
if (!(v->v_flags & VF_PLOT)) {
|
||||
continue;
|
||||
|
|
@ -1034,10 +1063,9 @@ static int iplot(struct plot *pl, int id)
|
|||
/* currentgraph->data.ymin = dy;
|
||||
currentgraph->data.ymin *= (1 + YFACTOR); */
|
||||
}
|
||||
if (currentgraph->data.ymax < currentgraph->data.ymin) {
|
||||
currentgraph->data.ymax = currentgraph->data.ymin;
|
||||
}
|
||||
|
||||
/* checking for y hi */
|
||||
|
||||
while (dy > currentgraph->data.ymax) {
|
||||
changed = TRUE;
|
||||
if (ft_grdb) {
|
||||
|
|
@ -1049,8 +1077,8 @@ static int iplot(struct plot *pl, int id)
|
|||
}
|
||||
/* set the new y hi value */
|
||||
currentgraph->data.ymax +=
|
||||
(currentgraph->data.ymax - currentgraph->data.ymin)
|
||||
* YFACTOR;
|
||||
(currentgraph->data.ymax - currentgraph->data.ymin) *
|
||||
YFACTOR;
|
||||
/* currentgraph->data.ymax +=
|
||||
(dy - currentgraph->data.ymax) * YFACTOR;*/
|
||||
/* 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) {
|
||||
/* Redraw everything. */
|
||||
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 dbcomm *dc;
|
||||
|
||||
if (db->db_type == DB_IPLOTALL || db->db_type == DB_TRACEALL) {
|
||||
for (v = plot->pl_dvecs; v; v = v->v_next)
|
||||
if (unset)
|
||||
v->v_flags &= (short) ~mode;
|
||||
else
|
||||
if (value)
|
||||
v->v_flags |= mode;
|
||||
else
|
||||
v->v_flags &= (short) ~mode;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1113,17 +1144,17 @@ static void set(struct plot *plot, struct dbcomm *db, bool unset, short mode)
|
|||
continue;
|
||||
v = vec_fromplot(dc->db_nodename1, 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",
|
||||
dc->db_nodename1, plot->pl_name);
|
||||
/* note: XXX remove it from dbs, so won't get further errors */
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (unset)
|
||||
v->v_flags &= (short) ~mode;
|
||||
else
|
||||
if (value)
|
||||
v->v_flags |= mode;
|
||||
else
|
||||
v->v_flags &= (short) ~mode;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1176,16 +1207,18 @@ void gr_iplot(struct plot *plot)
|
|||
PushGraphContext(gr);
|
||||
}
|
||||
|
||||
set(plot, db, FALSE, VF_PLOT);
|
||||
/* Temporarily set plot flag on matching vector. */
|
||||
|
||||
set(plot, db, TRUE, VF_PLOT);
|
||||
|
||||
dontpop = 0;
|
||||
if (iplot(plot, db->db_graphid)) {
|
||||
if (iplot(plot, db)) {
|
||||
/* graph just assigned */
|
||||
db->db_graphid = currentgraph->graphid;
|
||||
dontpop = 1;
|
||||
}
|
||||
|
||||
set(plot, db, TRUE, VF_PLOT);
|
||||
set(plot, db, FALSE, VF_PLOT);
|
||||
|
||||
if (!dontpop && db->db_graphid)
|
||||
PopGraphContext();
|
||||
|
|
@ -1195,7 +1228,7 @@ void gr_iplot(struct plot *plot)
|
|||
struct dvec *v, *u;
|
||||
int len;
|
||||
|
||||
set(plot, db, FALSE, VF_PRINT);
|
||||
set(plot, db, TRUE, VF_PRINT);
|
||||
|
||||
len = plot->pl_scale->v_length;
|
||||
|
||||
|
|
@ -1251,7 +1284,7 @@ void gr_iplot(struct plot *plot)
|
|||
printf("\n");
|
||||
}
|
||||
}
|
||||
set(plot, db, TRUE, VF_PRINT);
|
||||
set(plot, db, FALSE, VF_PRINT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1147,7 +1147,9 @@ translate(struct card *deck, char *formal, int flen, char *actual, char *scname,
|
|||
char *next_name, *name, *t, *nametofree, *paren_ptr;
|
||||
int nnodes, i, dim;
|
||||
int rtn = 0;
|
||||
|
||||
#ifdef XSPICE
|
||||
bool got_vnam = FALSE;
|
||||
#endif
|
||||
bxx_init(&buffer);
|
||||
|
||||
/* 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) {
|
||||
bool got_vnam = FALSE;
|
||||
char *s = c->line;
|
||||
char dev_type = tolower_c(s[0]);
|
||||
|
||||
|
|
|
|||
|
|
@ -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_length(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_plus(void *, void *, short int , short int , int );
|
||||
extern void *cx_minus(void *, void *, short int , short int , int );
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@ Author: 1986 Thomas L. Quarles
|
|||
#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_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 */
|
||||
/* the simulator and MUST be accompanied by */
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ typedef struct OsdiRegistryEntry {
|
|||
uint32_t inst_offset;
|
||||
uint32_t dt;
|
||||
uint32_t temp;
|
||||
bool has_m;
|
||||
} OsdiRegistryEntry;
|
||||
|
||||
typedef struct OsdiObjectFile {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
|
|||
**********/
|
||||
|
||||
/** \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
|
||||
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
|
||||
* argument is irrelevent.
|
||||
* argument is irrelevant.
|
||||
*/
|
||||
|
||||
void *
|
||||
|
|
@ -506,6 +506,38 @@ cx_vector(void *data, short int type, int length, int *newlength, short int *new
|
|||
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. */
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ Author: 1985 Thomas L. Quarles
|
|||
void
|
||||
NIdestroy(CKTcircuit *ckt)
|
||||
{
|
||||
int i;
|
||||
if (ckt->CKTmatrix)
|
||||
SMPdestroy(ckt->CKTmatrix);
|
||||
ckt->CKTmatrix = NULL;
|
||||
|
|
@ -36,7 +35,7 @@ NIdestroy(CKTcircuit *ckt)
|
|||
#endif
|
||||
#ifdef PREDICTOR
|
||||
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]);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ Modified: 2001 AlansFixes
|
|||
|
||||
/* Limit the number of 'singular matrix' warnings */
|
||||
static int msgcount = 0;
|
||||
void NIresetwarnmsg(void);
|
||||
|
||||
/* NIiter() - return value is non-zero for convergence failure */
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
* descr->param_opvar to the internal ngspice representation (IFparm).
|
||||
*/
|
||||
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++) {
|
||||
OsdiParamOpvar *para = &descr->param_opvar[i];
|
||||
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;
|
||||
}
|
||||
char *para_name = copy(para->name[j]);
|
||||
if (para_name[0] == '$') {
|
||||
para_name[0] = '_';
|
||||
}
|
||||
strtolower(para_name);
|
||||
(*dst)[j] = (IFparm){.keyword = para_name,
|
||||
.id = (int)i,
|
||||
.description = para->description,
|
||||
.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;
|
||||
}
|
||||
|
||||
|
|
@ -110,6 +121,10 @@ extern SPICEdev *osdi_create_spicedev(const OsdiRegistryEntry *entry) {
|
|||
*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 *dst = instance_para_names;
|
||||
|
||||
|
|
@ -124,9 +139,9 @@ extern SPICEdev *osdi_create_spicedev(const OsdiRegistryEntry *entry) {
|
|||
"Instance temperature"};
|
||||
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,
|
||||
descr->num_params + descr->num_opvars);
|
||||
descr->num_params + descr->num_opvars, true);
|
||||
|
||||
// allocate and fill model params
|
||||
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);
|
||||
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
|
||||
SPICEdev *OSDIinfo = TMALLOC(SPICEdev, 1);
|
||||
|
|
@ -181,7 +197,5 @@ extern SPICEdev *osdi_create_spicedev(const OsdiRegistryEntry *entry) {
|
|||
OSDIinfo->DEVpzLoad = OSDIpzLoad;
|
||||
OSDIinfo->DEVtrunc = OSDItrunc;
|
||||
|
||||
|
||||
|
||||
return OSDIinfo;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -358,12 +358,15 @@ extern OsdiObjectFile load_object_file(const char *input) {
|
|||
const OsdiDescriptor *descr = &OSDI_DESCRIPTORS[i];
|
||||
|
||||
uint32_t dt = descr->num_params + descr->num_opvars;
|
||||
bool has_m = false;
|
||||
uint32_t temp = descr->num_params + descr->num_opvars + 1;
|
||||
for (uint32_t param_id = 0; param_id < descr->num_params; param_id++) {
|
||||
OsdiParamOpvar *param = &descr->param_opvar[param_id];
|
||||
for (uint32_t j = 0; j < 1 + param->num_alias; 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;
|
||||
} else if (!strcasecmp(name, "dtemp") || !strcasecmp(name, "dt")) {
|
||||
dt = param_id;
|
||||
|
|
@ -382,6 +385,7 @@ extern OsdiObjectFile load_object_file(const char *input) {
|
|||
.inst_offset = (uint32_t)inst_off,
|
||||
.dt = dt,
|
||||
.temp = temp,
|
||||
.has_m = has_m,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ int OSDIsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt,
|
|||
OsdiInitInfo init_info;
|
||||
OsdiNgspiceHandle handle;
|
||||
GENmodel *gen_model;
|
||||
int res;
|
||||
int res = (OK);
|
||||
int error;
|
||||
CKTnode *tmp;
|
||||
GENinstance *gen_inst;
|
||||
|
|
@ -304,7 +304,7 @@ extern int OSDItemp(GENmodel *inModel, CKTcircuit *ckt) {
|
|||
OsdiInitInfo init_info;
|
||||
OsdiNgspiceHandle handle;
|
||||
GENmodel *gen_model;
|
||||
int res;
|
||||
int res = (OK);
|
||||
GENinstance *gen_inst;
|
||||
|
||||
OsdiRegistryEntry *entry = osdi_reg_entry_model(inModel);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ Author: 1985 Thomas L. Quarles
|
|||
#include "ngspice/cktdefs.h"
|
||||
#include "ngspice/devdefs.h"
|
||||
#include "ngspice/sperror.h"
|
||||
#include "ngspice/fteext.h"
|
||||
|
||||
#ifdef XSPICE
|
||||
#include "ngspice/enh.h"
|
||||
|
|
@ -43,6 +44,20 @@ CKTsetup(CKTcircuit *ckt)
|
|||
/* gtri - end - Setup for adding rshunt option resistors */
|
||||
#endif
|
||||
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;
|
||||
|
||||
#ifdef WANT_SENSE2
|
||||
|
|
@ -57,7 +72,9 @@ CKTsetup(CKTcircuit *ckt)
|
|||
return E_NOCHANGE;
|
||||
|
||||
error = NIinit(ckt);
|
||||
if (error) return(error);
|
||||
if (error)
|
||||
return(error);
|
||||
|
||||
ckt->CKTisSetup = 1;
|
||||
|
||||
matrix = ckt->CKTmatrix;
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ DCpss(CKTcircuit *ckt,
|
|||
else
|
||||
maxstepsize = ckt->CKTmaxStep;
|
||||
|
||||
ckt->CKTsizeIncr = 10;
|
||||
ckt->CKTsizeIncr = 100;
|
||||
ckt->CKTtimeIndex = -1; /* before the DC soln has been stored */
|
||||
ckt->CKTtimeListSize = (int)(1 / ckt->CKTguessedFreq / maxstepsize + 0.5);
|
||||
ltra_num = CKTtypelook("LTRA");
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ DCtran(CKTcircuit *ckt,
|
|||
else
|
||||
maxstepsize = ckt->CKTmaxStep;
|
||||
|
||||
ckt->CKTsizeIncr = 10;
|
||||
ckt->CKTsizeIncr = 100;
|
||||
ckt->CKTtimeIndex = -1; /* before the DC soln has been stored */
|
||||
ckt->CKTtimeListSize = (int) ceil( ckt->CKTfinalTime / maxstepsize );
|
||||
ltra_num = CKTtypelook("LTRA");
|
||||
|
|
|
|||
|
|
@ -232,16 +232,16 @@ NOISEan(CKTcircuit* ckt, int restart)
|
|||
error = CKTload(ckt);
|
||||
if (error) return(error);
|
||||
|
||||
error = CKTnames(ckt, &numNames, &nameList);
|
||||
if (error) return(error);
|
||||
|
||||
if (ckt->CKTkeepOpInfo) {
|
||||
error = CKTnames(ckt, &numNames, &nameList);
|
||||
if (error) return(error);
|
||||
/* Dump operating point. */
|
||||
error = SPfrontEnd->OUTpBeginPlot(ckt, ckt->CKTcurJob,
|
||||
"NOISE Operating Point",
|
||||
NULL, IF_REAL,
|
||||
numNames, nameList, IF_REAL,
|
||||
&plot);
|
||||
txfree(nameList);
|
||||
if (error) return(error);
|
||||
CKTdump(ckt, 0.0, plot);
|
||||
SPfrontEnd->OUTendPlot(plot);
|
||||
|
|
|
|||
|
|
@ -100,6 +100,11 @@ void com_optran(wordlist* wl) {
|
|||
getdata = TRUE;
|
||||
}
|
||||
|
||||
if (!getdata && !ft_curckt) {
|
||||
/* no circuit, but optran already set */
|
||||
return;
|
||||
}
|
||||
|
||||
int saved = errno;
|
||||
errno = 0;
|
||||
nooptran = FALSE;
|
||||
|
|
@ -159,14 +164,14 @@ void com_optran(wordlist* wl) {
|
|||
if (err || (*stpstr != '\0'))
|
||||
goto bugquit;
|
||||
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;
|
||||
}
|
||||
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) {
|
||||
fprintf(stderr, "Error: Ramp time larger than final time.\n");
|
||||
fprintf(stderr, "Error: Optran ramp time larger than final time.\n");
|
||||
goto bugquit;
|
||||
}
|
||||
/* optran deselected by setting opstepsize to 0 */
|
||||
|
|
@ -362,7 +367,7 @@ OPtran(CKTcircuit *ckt, int oldconverged)
|
|||
else
|
||||
maxstepsize = ckt->CKTmaxStep;
|
||||
|
||||
ckt->CKTsizeIncr = 10;
|
||||
ckt->CKTsizeIncr = 100;
|
||||
ckt->CKTtimeIndex = -1; /* before the DC soln has been stored */
|
||||
ckt->CKTtimeListSize = (int) ceil( opfinaltime / maxstepsize );
|
||||
ltra_num = CKTtypelook("LTRA");
|
||||
|
|
@ -657,7 +662,7 @@ resume:
|
|||
|
||||
/* supply ramping, when 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;
|
||||
NIcomCof(ckt);
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ CKTcrtElt(CKTcircuit *ckt, GENmodel *modPtr, GENinstance **inInstPtr, IFuid name
|
|||
if (instPtr) {
|
||||
if (inInstPtr)
|
||||
*inInstPtr = instPtr;
|
||||
return E_EXISTS;
|
||||
return E_EXISTS_BAD;
|
||||
}
|
||||
|
||||
type = modPtr->GENmodType;
|
||||
|
|
|
|||
|
|
@ -29,16 +29,13 @@ CKTinit(CKTcircuit **ckt) /* new circuit to create */
|
|||
CKTcircuit *sckt = TMALLOC(CKTcircuit, 1);
|
||||
*ckt = sckt;
|
||||
if (sckt == NULL)
|
||||
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 */
|
||||
/* to a ** pointer */
|
||||
return(E_NOMEM);
|
||||
|
||||
/* dynamically allocate the array of model lists */
|
||||
sckt->CKThead = TMALLOC(GENmodel *, DEVmaxnum);
|
||||
if(sckt->CKThead == NULL) return(E_NOMEM);
|
||||
/* gtri - end - dynamically allocate the array of model lists */
|
||||
if(sckt->CKThead == NULL)
|
||||
return(E_NOMEM);
|
||||
|
||||
|
||||
|
||||
for (i = 0; i < DEVmaxnum; i++)
|
||||
sckt->CKThead[i] = NULL;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,285 +10,283 @@ Author: 1990 Jaijeet S. Roychowdhury
|
|||
#include "ngspice/suffix.h"
|
||||
|
||||
int
|
||||
LTRAaccept(CKTcircuit *ckt, GENmodel *inModel)
|
||||
LTRAaccept(CKTcircuit* ckt, GENmodel* inModel)
|
||||
{
|
||||
LTRAmodel *model = (LTRAmodel *) inModel;
|
||||
LTRAinstance *here;
|
||||
double v1, v2, v3, v4;
|
||||
double v5, v6, d1, d2, d3, d4;
|
||||
int tmp_test;
|
||||
int error;
|
||||
int compact = 1;
|
||||
LTRAmodel* model = (LTRAmodel*)inModel;
|
||||
LTRAinstance* here;
|
||||
double v1, v2, v3, v4;
|
||||
double v5, v6, d1, d2, d3, d4;
|
||||
int tmp_test;
|
||||
int error;
|
||||
int compact = 1;
|
||||
|
||||
|
||||
/* loop through all the transmission line models */
|
||||
for (; model != NULL; model = LTRAnextModel(model)) {
|
||||
/* loop through all the transmission line models */
|
||||
for (; model != NULL; model = LTRAnextModel(model)) {
|
||||
|
||||
if (ckt->CKTmode & MODEINITTRAN) {
|
||||
if (ckt->CKTmode & MODEINITTRAN) {
|
||||
|
||||
#define LTRAmemMANAGE(a,b) \
|
||||
if ( a != NULL) FREE(a);\
|
||||
a = TMALLOC(double, b);
|
||||
if ( a != NULL) FREE(a);\
|
||||
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)
|
||||
LTRAmemMANAGE(model->LTRAh2Coeffs, model->LTRAmodelListSize)
|
||||
LTRAmemMANAGE(model->LTRAh3dashCoeffs, model->LTRAmodelListSize)
|
||||
}
|
||||
if (ckt->CKTtimeIndex >= model->LTRAmodelListSize) { /* need more space */
|
||||
model->LTRAmodelListSize += ckt->CKTsizeIncr;
|
||||
model->LTRAh1dashCoeffs = TREALLOC(double, model->LTRAh1dashCoeffs, model->LTRAmodelListSize);
|
||||
model->LTRAh2Coeffs = TREALLOC(double, model->LTRAh2Coeffs, model->LTRAmodelListSize);
|
||||
model->LTRAh3dashCoeffs = TREALLOC(double, model->LTRAh3dashCoeffs, model->LTRAmodelListSize);
|
||||
}
|
||||
/* loop through all the instances of the model */
|
||||
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);
|
||||
model->LTRAh2Coeffs = TREALLOC(double, model->LTRAh2Coeffs, model->LTRAmodelListSize);
|
||||
model->LTRAh3dashCoeffs = TREALLOC(double, model->LTRAh3dashCoeffs, model->LTRAmodelListSize);
|
||||
}
|
||||
/* loop through all the instances of the model */
|
||||
for (here = LTRAinstances(model); here != NULL;
|
||||
here = LTRAnextInstance(here)) {
|
||||
LTRAmemMANAGE(here->LTRAv1, here->LTRAinstListSize)
|
||||
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;
|
||||
|
||||
if (ckt->CKTmode & MODEINITTRAN) {
|
||||
here->LTRAinstListSize = 10;
|
||||
here->LTRAv1 = TREALLOC(double, here->LTRAv1, here->LTRAinstListSize);
|
||||
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)
|
||||
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;
|
||||
if (ckt->CKTtryToCompact && (ckt->CKTtimeIndex >= 2)) {
|
||||
|
||||
here->LTRAv1 = TREALLOC(double, here->LTRAv1, here->LTRAinstListSize);
|
||||
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);
|
||||
/*
|
||||
* figure out if the last 3 points lie on a st. line for all the
|
||||
* terminal variables
|
||||
*/
|
||||
{
|
||||
double t1, t2, t3;
|
||||
|
||||
if (ckt->CKTtryToCompact && (ckt->CKTtimeIndex >= 2)) {
|
||||
t1 = *(ckt->CKTtimePoints + ckt->CKTtimeIndex - 2);
|
||||
t2 = *(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1);
|
||||
t3 = *(ckt->CKTtimePoints + ckt->CKTtimeIndex);
|
||||
|
||||
/*
|
||||
* figure out if the last 3 points lie on a st. line for all the
|
||||
* terminal variables
|
||||
*/
|
||||
{
|
||||
double t1, t2, t3;
|
||||
|
||||
t1 = *(ckt->CKTtimePoints + ckt->CKTtimeIndex - 2);
|
||||
t2 = *(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1);
|
||||
t3 = *(ckt->CKTtimePoints + ckt->CKTtimeIndex);
|
||||
|
||||
if (compact) {
|
||||
compact = LTRAstraightLineCheck(t1,
|
||||
*(here->LTRAv1 + ckt->CKTtimeIndex - 2),
|
||||
t2, *(here->LTRAv1 + ckt->CKTtimeIndex - 1),
|
||||
t3, *(here->LTRAv1 + ckt->CKTtimeIndex),
|
||||
model->LTRAstLineReltol, model->LTRAstLineAbstol);
|
||||
}
|
||||
if (compact) {
|
||||
compact = LTRAstraightLineCheck(t1,
|
||||
*(here->LTRAv2 + ckt->CKTtimeIndex - 2),
|
||||
t2, *(here->LTRAv2 + ckt->CKTtimeIndex - 1),
|
||||
t3, *(here->LTRAv2 + ckt->CKTtimeIndex),
|
||||
model->LTRAstLineReltol, model->LTRAstLineAbstol);
|
||||
}
|
||||
if (compact) {
|
||||
compact = LTRAstraightLineCheck(t1,
|
||||
*(here->LTRAi1 + ckt->CKTtimeIndex - 2),
|
||||
t2, *(here->LTRAi1 + ckt->CKTtimeIndex - 1),
|
||||
t3, *(here->LTRAi1 + ckt->CKTtimeIndex),
|
||||
model->LTRAstLineReltol, model->LTRAstLineAbstol);
|
||||
}
|
||||
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) {
|
||||
if (compact) {
|
||||
compact = LTRAstraightLineCheck(t1,
|
||||
*(here->LTRAv1 + ckt->CKTtimeIndex - 2),
|
||||
t2, *(here->LTRAv1 + ckt->CKTtimeIndex - 1),
|
||||
t3, *(here->LTRAv1 + ckt->CKTtimeIndex),
|
||||
model->LTRAstLineReltol, model->LTRAstLineAbstol);
|
||||
}
|
||||
if (compact) {
|
||||
compact = LTRAstraightLineCheck(t1,
|
||||
*(here->LTRAv2 + ckt->CKTtimeIndex - 2),
|
||||
t2, *(here->LTRAv2 + ckt->CKTtimeIndex - 1),
|
||||
t3, *(here->LTRAv2 + ckt->CKTtimeIndex),
|
||||
model->LTRAstLineReltol, model->LTRAstLineAbstol);
|
||||
}
|
||||
if (compact) {
|
||||
compact = LTRAstraightLineCheck(t1,
|
||||
*(here->LTRAi1 + ckt->CKTtimeIndex - 2),
|
||||
t2, *(here->LTRAi1 + ckt->CKTtimeIndex - 1),
|
||||
t3, *(here->LTRAi1 + ckt->CKTtimeIndex),
|
||||
model->LTRAstLineReltol, model->LTRAstLineAbstol);
|
||||
}
|
||||
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
|
||||
v1 = (*(here->LTRAv1 + ckt->CKTtimeIndex) +
|
||||
*(here->LTRAi1 + ckt->CKTtimeIndex) *
|
||||
model->LTRAimped) * model->LTRAattenuation;
|
||||
v2 = (*(here->LTRAv1 + ckt->CKTtimeIndex - 1) +
|
||||
*(here->LTRAi1 + ckt->CKTtimeIndex - 1)
|
||||
* model->LTRAimped) * model->LTRAattenuation;
|
||||
v3 = (*(here->LTRAv2 + ckt->CKTtimeIndex) +
|
||||
*(here->LTRAi2 + ckt->CKTtimeIndex) *
|
||||
model->LTRAimped) * model->LTRAattenuation;
|
||||
v4 = (*(here->LTRAv2 + ckt->CKTtimeIndex - 1) +
|
||||
*(here->LTRAi2 + ckt->CKTtimeIndex - 1) *
|
||||
model->LTRAimped) * model->LTRAattenuation;
|
||||
if ((fabs(v1 - v2) >= 50 * ckt->CKTreltol *
|
||||
MAX(fabs(v1), fabs(v2)) + 50 * ckt->CKTvoltTol) ||
|
||||
(fabs(v3 - v4) >= 50 * ckt->CKTreltol *
|
||||
MAX(fabs(v3), fabs(v4)) + 50 * ckt->CKTvoltTol)) {
|
||||
/* changing - need to schedule after delay */
|
||||
/*
|
||||
* don't really need this error =
|
||||
* CKTsetBreak(ckt,ckt->CKTtime+model->LTRAtd); if(error)
|
||||
* return(error);
|
||||
*/
|
||||
/* the PREVIOUS point is the real breakpoint */
|
||||
error = CKTsetBreak(ckt,
|
||||
*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1) +
|
||||
model->LTRAtd);
|
||||
CKTbreakDump(ckt);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
v1 = (*(here->LTRAv1 + ckt->CKTtimeIndex) +
|
||||
*(here->LTRAi1 + ckt->CKTtimeIndex) *
|
||||
model->LTRAimped) * model->LTRAattenuation;
|
||||
v2 = (*(here->LTRAv1 + ckt->CKTtimeIndex - 1) +
|
||||
*(here->LTRAi1 + ckt->CKTtimeIndex - 1)
|
||||
* model->LTRAimped) * model->LTRAattenuation;
|
||||
v3 = (*(here->LTRAv2 + ckt->CKTtimeIndex) +
|
||||
*(here->LTRAi2 + ckt->CKTtimeIndex) *
|
||||
model->LTRAimped) * model->LTRAattenuation;
|
||||
v4 = (*(here->LTRAv2 + ckt->CKTtimeIndex - 1) +
|
||||
*(here->LTRAi2 + ckt->CKTtimeIndex - 1) *
|
||||
model->LTRAimped) * model->LTRAattenuation;
|
||||
if ((fabs(v1 - v2) >= 50 * ckt->CKTreltol *
|
||||
MAX(fabs(v1), fabs(v2)) + 50 * ckt->CKTvoltTol) ||
|
||||
(fabs(v3 - v4) >= 50 * ckt->CKTreltol *
|
||||
MAX(fabs(v3), fabs(v4)) + 50 * ckt->CKTvoltTol)) {
|
||||
/* changing - need to schedule after delay */
|
||||
/*
|
||||
* don't really need this error =
|
||||
* CKTsetBreak(ckt,ckt->CKTtime+model->LTRAtd); if(error)
|
||||
* return(error);
|
||||
*/
|
||||
/* the PREVIOUS point is the real breakpoint */
|
||||
error = CKTsetBreak(ckt,
|
||||
*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1) +
|
||||
model->LTRAtd);
|
||||
CKTbreakDump(ckt);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* remove the hack here - store the total inputs for the last 2 or 3
|
||||
* timesteps
|
||||
*/
|
||||
/*
|
||||
* remove the hack here - store the total inputs for the last 2 or 3
|
||||
* timesteps
|
||||
*/
|
||||
|
||||
v1 = (*(here->LTRAv1 + ckt->CKTtimeIndex) +
|
||||
*(here->LTRAi1 + ckt->CKTtimeIndex) *
|
||||
model->LTRAimped) * model->LTRAattenuation;
|
||||
v2 = (*(here->LTRAv1 + ckt->CKTtimeIndex - 1) +
|
||||
*(here->LTRAi1 + ckt->CKTtimeIndex - 1) *
|
||||
model->LTRAimped) * model->LTRAattenuation;
|
||||
v3 = ckt->CKTtimeIndex < 2 ? v2 : (*(here->LTRAv1 + ckt->CKTtimeIndex - 2) +
|
||||
*(here->LTRAi1 + ckt->CKTtimeIndex - 2) *
|
||||
model->LTRAimped) * model->LTRAattenuation;
|
||||
v4 = (*(here->LTRAv2 + ckt->CKTtimeIndex) +
|
||||
*(here->LTRAi2 + ckt->CKTtimeIndex) *
|
||||
model->LTRAimped) * model->LTRAattenuation;
|
||||
v5 = (*(here->LTRAv2 + ckt->CKTtimeIndex - 1) +
|
||||
*(here->LTRAi2 + ckt->CKTtimeIndex - 1) *
|
||||
model->LTRAimped) * model->LTRAattenuation;
|
||||
v6 = ckt->CKTtimeIndex < 2 ? v5 : (*(here->LTRAv2 + ckt->CKTtimeIndex - 2) +
|
||||
*(here->LTRAi2 + ckt->CKTtimeIndex - 2) *
|
||||
model->LTRAimped) * model->LTRAattenuation;
|
||||
v1 = (*(here->LTRAv1 + ckt->CKTtimeIndex) +
|
||||
*(here->LTRAi1 + ckt->CKTtimeIndex) *
|
||||
model->LTRAimped) * model->LTRAattenuation;
|
||||
v2 = (*(here->LTRAv1 + ckt->CKTtimeIndex - 1) +
|
||||
*(here->LTRAi1 + ckt->CKTtimeIndex - 1) *
|
||||
model->LTRAimped) * model->LTRAattenuation;
|
||||
v3 = ckt->CKTtimeIndex < 2 ? v2 : (*(here->LTRAv1 + ckt->CKTtimeIndex - 2) +
|
||||
*(here->LTRAi1 + ckt->CKTtimeIndex - 2) *
|
||||
model->LTRAimped) * model->LTRAattenuation;
|
||||
v4 = (*(here->LTRAv2 + ckt->CKTtimeIndex) +
|
||||
*(here->LTRAi2 + ckt->CKTtimeIndex) *
|
||||
model->LTRAimped) * model->LTRAattenuation;
|
||||
v5 = (*(here->LTRAv2 + ckt->CKTtimeIndex - 1) +
|
||||
*(here->LTRAi2 + ckt->CKTtimeIndex - 1) *
|
||||
model->LTRAimped) * model->LTRAattenuation;
|
||||
v6 = ckt->CKTtimeIndex < 2 ? v5 : (*(here->LTRAv2 + ckt->CKTtimeIndex - 2) +
|
||||
*(here->LTRAi2 + ckt->CKTtimeIndex - 2) *
|
||||
model->LTRAimped) * model->LTRAattenuation;
|
||||
|
||||
d1 = (v1 - v2) / (*(ckt->CKTtimePoints + ckt->CKTtimeIndex) -
|
||||
*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1));
|
||||
d2 = (ckt->CKTtimeIndex < 2)
|
||||
? 0
|
||||
: (v2 - v3) / (*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1) -
|
||||
*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 2));
|
||||
d3 = (v4 - v5) / (*(ckt->CKTtimePoints + ckt->CKTtimeIndex) -
|
||||
*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1));
|
||||
d4 = (ckt->CKTtimeIndex < 2)
|
||||
? 0
|
||||
: (v5 - v6) / (*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1) -
|
||||
*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 2));
|
||||
d1 = (v1 - v2) / (*(ckt->CKTtimePoints + ckt->CKTtimeIndex) -
|
||||
*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1));
|
||||
d2 = (ckt->CKTtimeIndex < 2)
|
||||
? 0
|
||||
: (v2 - v3) / (*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1) -
|
||||
*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 2));
|
||||
d3 = (v4 - v5) / (*(ckt->CKTtimePoints + ckt->CKTtimeIndex) -
|
||||
*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1));
|
||||
d4 = (ckt->CKTtimeIndex < 2)
|
||||
? 0
|
||||
: (v5 - v6) / (*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1) -
|
||||
*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 2));
|
||||
|
||||
/*
|
||||
* here we have a big problem with the scheme boxed by the *s below.
|
||||
* Note the following: if LTRAreltol == 1, (assuming LTRAabstol==0)
|
||||
* then breakpoints are set if and only if d1 and d2 have opposite
|
||||
* signs or one is zero. If LTRAreltol > 2, breakpoints are never
|
||||
* set. The problem is that when the waveform is steady at a value,
|
||||
* small random numerical inaccuracies may produce derivatives of
|
||||
* opposite sign, and breakpoints get set. This can, in practice, get
|
||||
* quite killing... To alleviate this, we try to determine if the
|
||||
* waveform is actually steady using the following tests: 1. Check if
|
||||
* the maximum difference between v1,v2 and v3 is less than
|
||||
* 50*CKTreltol*(the average of v1,v2,and v3) + 50*ckt->CKTabstol
|
||||
* (the 50 has been taken from the NOTDEF section above, reason
|
||||
* unknown - hopefully there is a good reason for it - ask TQ)
|
||||
*
|
||||
* 2. Criterion 1 may be satisfied by a legitimate breakpoint. To
|
||||
* further check, find one more derivative one timepoint ago and see
|
||||
* if that is close to d2. If not, then the likelihood of numerical
|
||||
* inaccuracies is greater...
|
||||
*/
|
||||
/*
|
||||
* here we have a big problem with the scheme boxed by the *s below.
|
||||
* Note the following: if LTRAreltol == 1, (assuming LTRAabstol==0)
|
||||
* then breakpoints are set if and only if d1 and d2 have opposite
|
||||
* signs or one is zero. If LTRAreltol > 2, breakpoints are never
|
||||
* set. The problem is that when the waveform is steady at a value,
|
||||
* small random numerical inaccuracies may produce derivatives of
|
||||
* opposite sign, and breakpoints get set. This can, in practice, get
|
||||
* quite killing... To alleviate this, we try to determine if the
|
||||
* waveform is actually steady using the following tests: 1. Check if
|
||||
* the maximum difference between v1,v2 and v3 is less than
|
||||
* 50*CKTreltol*(the average of v1,v2,and v3) + 50*ckt->CKTabstol
|
||||
* (the 50 has been taken from the NOTDEF section above, reason
|
||||
* unknown - hopefully there is a good reason for it - ask TQ)
|
||||
*
|
||||
* 2. Criterion 1 may be satisfied by a legitimate breakpoint. To
|
||||
* further check, find one more derivative one timepoint ago and see
|
||||
* if that is close to d2. If not, then the likelihood of numerical
|
||||
* inaccuracies is greater...
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
if( (fabs(d1-d2) >= model->LTRAreltol*MAX(fabs(d1),fabs(d2))+
|
||||
model->LTRAabstol) ||
|
||||
(fabs(d3-d4) >= model->LTRAreltol*MAX(fabs(d3),fabs(d4))+
|
||||
model->LTRAabstol) ) {
|
||||
*********************************************************************/
|
||||
/*********************************************************************
|
||||
if( (fabs(d1-d2) >= model->LTRAreltol*MAX(fabs(d1),fabs(d2))+
|
||||
model->LTRAabstol) ||
|
||||
(fabs(d3-d4) >= model->LTRAreltol*MAX(fabs(d3),fabs(d4))+
|
||||
model->LTRAabstol) ) {
|
||||
*********************************************************************/
|
||||
#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) +\
|
||||
ckt->CKTabstol)))
|
||||
fabs(50.0*(ckt->CKTreltol/3.0*(a+b+c) +\
|
||||
ckt->CKTabstol)))
|
||||
|
||||
tmp_test = (fabs(d1 - d2)
|
||||
>= model->LTRAreltol * MAX(fabs(d1), fabs(d2)) +
|
||||
model->LTRAabstol)
|
||||
&& CHECK(v1, v2, v3);
|
||||
if (tmp_test || ((fabs(d3 - d4)
|
||||
>= model->LTRAreltol * MAX(fabs(d3), fabs(d4)) +
|
||||
model->LTRAabstol)
|
||||
&& CHECK(v4, v5, v6))) {
|
||||
/* criterion 2 not implemented yet... */
|
||||
error = CKTsetBreak(ckt,
|
||||
*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1) +
|
||||
model->LTRAtd);
|
||||
/*
|
||||
* this is not necessary - the previous timepoint was the
|
||||
* breakpoint error = CKTsetBreak(ckt, ckt->CKTtime +
|
||||
* model->LTRAtd);
|
||||
*/
|
||||
tmp_test = (fabs(d1 - d2)
|
||||
>= model->LTRAreltol * MAX(fabs(d1), fabs(d2)) +
|
||||
model->LTRAabstol)
|
||||
&& CHECK(v1, v2, v3);
|
||||
if (tmp_test || ((fabs(d3 - d4)
|
||||
>= model->LTRAreltol * MAX(fabs(d3), fabs(d4)) +
|
||||
model->LTRAabstol)
|
||||
&& CHECK(v4, v5, v6))) {
|
||||
/* criterion 2 not implemented yet... */
|
||||
error = CKTsetBreak(ckt,
|
||||
*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1) +
|
||||
model->LTRAtd);
|
||||
/*
|
||||
* this is not necessary - the previous timepoint was the
|
||||
* breakpoint error = CKTsetBreak(ckt, ckt->CKTtime +
|
||||
* model->LTRAtd);
|
||||
*/
|
||||
#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
|
||||
- 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, "\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);
|
||||
fprintf(stdout, "d1 through d4 are %14.14g %14.14g %14.14g %14.14g\n\n", d1, d2, d3, d4);
|
||||
#endif
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
/* } */
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
/* } */
|
||||
#endif /* NOTDEF */
|
||||
}
|
||||
/* ask TQ } */
|
||||
}
|
||||
/* ask TQ } */
|
||||
|
||||
} /* instance */
|
||||
} /* model */
|
||||
} /* instance */
|
||||
} /* 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
|
||||
* compaction
|
||||
*/
|
||||
/*
|
||||
* last three timepoints have variables lying on a straight line, do a
|
||||
* compaction
|
||||
*/
|
||||
|
||||
model = (LTRAmodel *) inModel;
|
||||
for (; model != NULL; model = LTRAnextModel(model)) {
|
||||
for (here = LTRAinstances(model); here != NULL;
|
||||
here = LTRAnextInstance(here)) {
|
||||
*(here->LTRAv1 + ckt->CKTtimeIndex - 1) = *(here->LTRAv1 +
|
||||
ckt->CKTtimeIndex);
|
||||
*(here->LTRAv2 + ckt->CKTtimeIndex - 1) = *(here->LTRAv2 +
|
||||
ckt->CKTtimeIndex);
|
||||
*(here->LTRAi1 + ckt->CKTtimeIndex - 1) = *(here->LTRAi1 +
|
||||
ckt->CKTtimeIndex);
|
||||
*(here->LTRAi2 + ckt->CKTtimeIndex - 1) = *(here->LTRAi2 +
|
||||
ckt->CKTtimeIndex);
|
||||
}
|
||||
}
|
||||
*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1) =
|
||||
*(ckt->CKTtimePoints + ckt->CKTtimeIndex);
|
||||
ckt->CKTtimeIndex--;
|
||||
model = (LTRAmodel*)inModel;
|
||||
for (; model != NULL; model = LTRAnextModel(model)) {
|
||||
for (here = LTRAinstances(model); here != NULL;
|
||||
here = LTRAnextInstance(here)) {
|
||||
*(here->LTRAv1 + ckt->CKTtimeIndex - 1) = *(here->LTRAv1 +
|
||||
ckt->CKTtimeIndex);
|
||||
*(here->LTRAv2 + ckt->CKTtimeIndex - 1) = *(here->LTRAv2 +
|
||||
ckt->CKTtimeIndex);
|
||||
*(here->LTRAi1 + ckt->CKTtimeIndex - 1) = *(here->LTRAi1 +
|
||||
ckt->CKTtimeIndex);
|
||||
*(here->LTRAi2 + ckt->CKTtimeIndex - 1) = *(here->LTRAi2 +
|
||||
ckt->CKTtimeIndex);
|
||||
}
|
||||
}
|
||||
*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1) =
|
||||
*(ckt->CKTtimePoints + ckt->CKTtimeIndex);
|
||||
ckt->CKTtimeIndex--;
|
||||
#ifdef LTRADEBUG
|
||||
fprintf(stdout, "compacted at time=%g\n", *(ckt->CKTtimePoints + ckt->CKTtimeIndex));
|
||||
fflush(stdout);
|
||||
fprintf(stdout, "compacted at time=%g\n", *(ckt->CKTtimePoints + ckt->CKTtimeIndex));
|
||||
fflush(stdout);
|
||||
#endif
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ VBICacLoad(GENmodel *inModel, CKTcircuit *ckt)
|
|||
,Ibcp_Vbcp,Iccp_Vbep,Irs_Vrs,Iccp_Vbci,Iccp_Vbcp;
|
||||
double XQbe_Vbei, XQbe_Vbci, XQbex_Vbex, XQbc_Vbci,
|
||||
XQbcx_Vbcx, XQbep_Vbep, XQbep_Vbci,
|
||||
XQbcp_Vbcp;
|
||||
XQbcp_Vbcp, XQbeo_Vbe, XQbco_Vbc;
|
||||
|
||||
/* loop through all the models */
|
||||
for( ; model != NULL; model = VBICnextModel(model)) {
|
||||
|
|
@ -229,6 +229,8 @@ c The complex part
|
|||
XQbep_Vbep = *(ckt->CKTstate0 + here->VBICcqbep) * ckt->CKTomega;
|
||||
XQbep_Vbci = *(ckt->CKTstate0 + here->VBICcqbepci) * 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
|
||||
*/
|
||||
|
|
@ -279,6 +281,21 @@ c Stamp element: Qbcp
|
|||
*(here->VBICsubsSIBaseBPPtr + 1) += -XQbcp_Vbcp;
|
||||
*(here->VBICbaseBPSubsSIPtr + 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;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,8 +75,8 @@ VBICload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
,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
|
||||
,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
|
||||
,Qcth_Vrth,SCALE;
|
||||
,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=0.0,SCALE;
|
||||
int iret;
|
||||
double vce;
|
||||
#ifndef PREDICTOR
|
||||
|
|
@ -129,7 +129,7 @@ VBICload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
/*
|
||||
* model parameters
|
||||
*/
|
||||
memcpy (&p, &model->VBICtnom, 108*8);
|
||||
memcpy (&p, &model->VBICtnom, sizeof(p));
|
||||
|
||||
p[0] = here->VBICtemp - CONSTCtoK + p[105];
|
||||
/* temperature dependent parameter are already calculated */
|
||||
|
|
@ -714,7 +714,8 @@ VBICload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
here->VBICcapbcx = Qbcx_Vbcx;
|
||||
here->VBICcapbep = Qbep_Vbep;
|
||||
here->VBICcapbcp = Qbcp_Vbcp;
|
||||
here->VBICcapcth = Qcth_Vrth;
|
||||
if (here->VBIC_selfheat)
|
||||
here->VBICcapcth = Qcth_Vrth;
|
||||
|
||||
/*
|
||||
* store small-signal parameters
|
||||
|
|
@ -894,9 +895,11 @@ VBICload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
*(ckt->CKTstate0 + here->VBICirbx_Vrbx) = Irbx_Vrbx;
|
||||
*(ckt->CKTstate0 + here->VBICirs_Vrs) = Irs_Vrs;
|
||||
*(ckt->CKTstate0 + here->VBICire_Vre) = Ire_Vre;
|
||||
*(ckt->CKTstate0 + here->VBICcqcth) = Icth;
|
||||
*(ckt->CKTstate0 + here->VBICicth_Vrth) = Icth_Vrth;
|
||||
|
||||
if (here->VBIC_selfheat)
|
||||
{
|
||||
*(ckt->CKTstate0 + here->VBICcqcth) = Icth;
|
||||
*(ckt->CKTstate0 + here->VBICicth_Vrth) = Icth_Vrth;
|
||||
}
|
||||
load:
|
||||
/*
|
||||
* load current excitation vector and matrix
|
||||
|
|
|
|||
|
|
@ -469,7 +469,7 @@ VBICsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
|
|||
}
|
||||
|
||||
if(model->VBICselftGiven)
|
||||
if(model->VBICselft == 1)
|
||||
if((model->VBICselft == 1) && (model->VBICthermalResistGiven) && (model->VBICthermalResist > 0.0))
|
||||
here->VBIC_selfheat = 1;
|
||||
else
|
||||
here->VBIC_selfheat = 0;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ VBICtemp(GENmodel *inModel, CKTcircuit *ckt)
|
|||
|
||||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -19,9 +19,6 @@ extern void fftFree(void);
|
|||
|
||||
extern bool ft_ngdebug; /* some additional debug info printed */
|
||||
|
||||
#define SAMETIME(a,b) (fabs((a)-(b))<= TIMETOL * PW)
|
||||
#define TIMETOL 1e-7
|
||||
|
||||
int
|
||||
VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
|
||||
/* set up the breakpoint table. */
|
||||
|
|
@ -51,7 +48,6 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
|
|||
case PULSE: {
|
||||
|
||||
double TD, TR, TF, PW, PER;
|
||||
double tshift;
|
||||
double time = 0.;
|
||||
double basetime = 0;
|
||||
double tmax = 1e99;
|
||||
|
|
@ -79,7 +75,6 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
|
|||
|
||||
/* offset time by delay */
|
||||
time = ckt->CKTtime - TD;
|
||||
tshift = TD;
|
||||
|
||||
if (newcompat.xs) {
|
||||
/* normalize phase to 0 - 360° */
|
||||
|
|
@ -90,71 +85,55 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
|
|||
while (deltat > 0)
|
||||
deltat -= PER;
|
||||
time += deltat;
|
||||
tshift = TD - deltat;
|
||||
}
|
||||
else if (PHASE > 0.0) {
|
||||
} else if (PHASE > 0.0) {
|
||||
tmax = PHASE * PER;
|
||||
if (time > tmax)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!newcompat.xs && time > tmax) {
|
||||
/* Do nothing */
|
||||
}
|
||||
else {
|
||||
if (ckt->CKTtime >= here->VSRCbreak_time) {
|
||||
double wait;
|
||||
|
||||
if (time >= PER) {
|
||||
/* repeating signal - figure out where we are */
|
||||
/* in period */
|
||||
/* Repeating signal: where in period are we? */
|
||||
|
||||
basetime = PER * floor(time / PER);
|
||||
time -= basetime;
|
||||
}
|
||||
|
||||
if (time <= 0.0 || time >= TR + PW + TF) {
|
||||
if (ckt->CKTbreak && SAMETIME(time, 0.0)) {
|
||||
error = CKTsetBreak(ckt, basetime + TR + tshift);
|
||||
if (error) return(error);
|
||||
}
|
||||
else if (ckt->CKTbreak && SAMETIME(TR + PW + TF, time)) {
|
||||
error = CKTsetBreak(ckt, basetime + PER + tshift);
|
||||
if (error) return(error);
|
||||
}
|
||||
else if (ckt->CKTbreak && (time == -tshift)) {
|
||||
error = CKTsetBreak(ckt, basetime + tshift);
|
||||
if (error) return(error);
|
||||
}
|
||||
else if (ckt->CKTbreak && SAMETIME(PER, time)) {
|
||||
error = CKTsetBreak(ckt, basetime + tshift + TR + PER);
|
||||
if (error) return(error);
|
||||
}
|
||||
}
|
||||
else if (time >= TR && time <= TR + PW) {
|
||||
if (ckt->CKTbreak && SAMETIME(time, TR)) {
|
||||
error = CKTsetBreak(ckt, basetime + tshift + TR + PW);
|
||||
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);
|
||||
}
|
||||
/* Set next breakpoint. */
|
||||
|
||||
if (time < 0.0) {
|
||||
/* Await first pulse */
|
||||
|
||||
wait = -time;
|
||||
} else if (time < TR) {
|
||||
/* Wait for end of rise. */
|
||||
|
||||
wait = TR - time;
|
||||
} else if (time < TR + PW) {
|
||||
/* Wait for fall. */
|
||||
|
||||
wait = TR + PW - time;
|
||||
} else if (time < TR + PW + TF) {
|
||||
/* Wait for end of fall. */
|
||||
|
||||
wait = TR + PW + TF - time;
|
||||
} else {
|
||||
/* Wait for next pulse. */
|
||||
wait = PER - time;
|
||||
}
|
||||
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;
|
||||
|
|
@ -179,25 +158,46 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
|
|||
}
|
||||
break;
|
||||
|
||||
case PWL: {
|
||||
int i;
|
||||
if(ckt->CKTtime < *(here->VSRCcoeffs)) {
|
||||
if(ckt->CKTbreak) {
|
||||
error = CKTsetBreak(ckt,*(here->VSRCcoeffs));
|
||||
break;
|
||||
case PWL:
|
||||
if (ckt->CKTtime >= here->VSRCbreak_time) {
|
||||
double time, end, period;
|
||||
int i;
|
||||
|
||||
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++) {
|
||||
if ( ckt->CKTbreak && AlmostEqualUlps(*(here->VSRCcoeffs+2*i), ckt->CKTtime, 3 ) ) {
|
||||
error = CKTsetBreak(ckt, *(here->VSRCcoeffs+2*i+2));
|
||||
if(error) return(error);
|
||||
goto bkptset;
|
||||
|
||||
for (i = 0;
|
||||
i < here->VSRCfunctionOrder;
|
||||
i += 2) {
|
||||
if (here->VSRCcoeffs[i] > time) {
|
||||
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;
|
||||
}
|
||||
|
||||
/**** tansient noise routines:
|
||||
/**** transient noise routines:
|
||||
VNoi2 2 0 DC 0 TRNOISE(10n 0.5n 0 0n) : generate gaussian distributed noise
|
||||
rms value, time step, 0 0
|
||||
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: {
|
||||
|
||||
|
||||
struct trnoise_state *state = here -> VSRCtrnoise_state;
|
||||
double TS = state -> TS;
|
||||
double RTSAM = state ->RTSAM;
|
||||
|
|
@ -220,61 +221,55 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
|
|||
fftFree();
|
||||
}
|
||||
#endif
|
||||
|
||||
if(ckt->CKTbreak) {
|
||||
|
||||
int n = (int) floor(ckt->CKTtime / TS + 0.5);
|
||||
volatile double nearest = n * TS;
|
||||
|
||||
if(AlmostEqualUlps(nearest, ckt->CKTtime, 3)) {
|
||||
/* carefull calculate `next'
|
||||
* make sure it is really identical
|
||||
* with the next calculated `nearest' value
|
||||
*/
|
||||
volatile double next = (n+1) * TS;
|
||||
error = CKTsetBreak(ckt, next);
|
||||
if(error)
|
||||
return(error);
|
||||
}
|
||||
if (TS > 0 && ckt->CKTtime >= here->VSRCbreak_time) {
|
||||
if (here->VSRCbreak_time < 0.0)
|
||||
here->VSRCbreak_time = TS;
|
||||
else
|
||||
here->VSRCbreak_time += TS;
|
||||
error = CKTsetBreak(ckt, here->VSRCbreak_time);
|
||||
if (error)
|
||||
return(error);
|
||||
here->VSRCbreak_time -= ckt->CKTminBreak;
|
||||
}
|
||||
|
||||
if (RTSAM > 0) {
|
||||
double RTScapTime = state->RTScapTime;
|
||||
double RTSemTime = state->RTSemTime;
|
||||
double RTSCAPT = state->RTSCAPT;
|
||||
double RTSEMT = state->RTSEMT;
|
||||
if (RTSAM <= 0)
|
||||
break; /* No shot noise. */
|
||||
|
||||
if (ckt->CKTtime == 0) {
|
||||
/* initialzing here again needed for repeated calls to tran command */
|
||||
state->RTScapTime = RTScapTime = exprand(RTSCAPT);
|
||||
state->RTSemTime = RTSemTime = RTScapTime + exprand(RTSEMT);
|
||||
if (ckt->CKTtime == 0) {
|
||||
/* initialzing here again needed for repeated calls to tran command */
|
||||
state->RTScapTime = exprand(state->RTSCAPT);
|
||||
state->RTSemTime =
|
||||
state->RTScapTime + exprand(state->RTSEMT);
|
||||
error = CKTsetBreak(ckt, state->RTScapTime);
|
||||
if(error)
|
||||
return(error);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ckt->CKTbreak) {
|
||||
error = CKTsetBreak(ckt, RTScapTime);
|
||||
if(error)
|
||||
return(error);
|
||||
}
|
||||
}
|
||||
/* Break handling code ends a timestep close to
|
||||
* the requested time.
|
||||
*/
|
||||
|
||||
if(AlmostEqualUlps(RTScapTime, ckt->CKTtime, 3)) {
|
||||
if (ckt->CKTbreak) {
|
||||
error = CKTsetBreak(ckt, RTSemTime);
|
||||
if(error)
|
||||
return(error);
|
||||
}
|
||||
}
|
||||
if (ckt->CKTtime >=
|
||||
state->RTScapTime - ckt->CKTminBreak &&
|
||||
ckt->CKTtime <=
|
||||
state->RTScapTime + ckt->CKTminBreak) {
|
||||
error = CKTsetBreak(ckt, state->RTSemTime);
|
||||
if(error)
|
||||
return(error);
|
||||
}
|
||||
|
||||
if(AlmostEqualUlps(RTSemTime, ckt->CKTtime, 3)) {
|
||||
/* new values */
|
||||
RTScapTime = here -> VSRCtrnoise_state ->RTScapTime = ckt->CKTtime + exprand(RTSCAPT);
|
||||
here -> VSRCtrnoise_state ->RTSemTime = RTScapTime + exprand(RTSEMT);
|
||||
if (ckt->CKTtime >=
|
||||
state->RTSemTime - ckt->CKTminBreak) {
|
||||
/* new values */
|
||||
|
||||
if (ckt->CKTbreak) {
|
||||
error = CKTsetBreak(ckt, RTScapTime);
|
||||
if(error)
|
||||
return(error);
|
||||
}
|
||||
}
|
||||
state->RTScapTime =
|
||||
ckt->CKTtime + exprand(state->RTSCAPT);
|
||||
state->RTSemTime =
|
||||
state->RTScapTime + exprand(state->RTSEMT);
|
||||
error = CKTsetBreak(ckt, state->RTScapTime);
|
||||
if(error)
|
||||
return(error);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -286,30 +281,22 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
|
|||
|
||||
if (ckt->CKTtime == 0 && TD > 0) {
|
||||
error = CKTsetBreak(ckt, TD);
|
||||
here->VSRCbreak_time = TD;
|
||||
if (error)
|
||||
return(error);
|
||||
break;
|
||||
}
|
||||
|
||||
double time = ckt->CKTtime - TD;
|
||||
|
||||
if (time < 0) break;
|
||||
|
||||
if(ckt->CKTbreak) {
|
||||
|
||||
int n = (int) floor(time / TS + 0.5);
|
||||
volatile double nearest = n * TS;
|
||||
|
||||
if(AlmostEqualUlps(nearest, time, 10)) {
|
||||
/* 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);
|
||||
}
|
||||
if (ckt->CKTtime >= here->VSRCbreak_time) {
|
||||
if (here->VSRCbreak_time < 0.0)
|
||||
here->VSRCbreak_time = TS;
|
||||
else
|
||||
here->VSRCbreak_time += TS;
|
||||
error = CKTsetBreak(ckt, here->VSRCbreak_time);
|
||||
if (error)
|
||||
return(error);
|
||||
here->VSRCbreak_time -= ckt->CKTminBreak;
|
||||
state->value = trrandom_state_get(state);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -323,7 +310,6 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
|
|||
|
||||
} // switch
|
||||
} // if ... else
|
||||
bkptset: ;
|
||||
} // for
|
||||
} // for
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ typedef struct sVSRCinstance {
|
|||
int VSRCfunctionType; /* code number of function type for source */
|
||||
int VSRCfunctionOrder; /* order of the function for the source */
|
||||
int VSRCrBreakpt; /* pwl repeat breakpoint index */
|
||||
double VSRCbreak_time; /* time of most-recent breakpoint */
|
||||
double *VSRCcoeffs; /* pointer to array of coefficients */
|
||||
|
||||
double VSRCdcValue; /* DC and TRANSIENT value of source */
|
||||
|
|
|
|||
|
|
@ -298,43 +298,48 @@ VSRCload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
break;
|
||||
|
||||
case PWL: {
|
||||
int i = 0, num_repeat = 0, ii = 0;
|
||||
double foo, repeat_time = 0, end_time, breakpt_time, itime;
|
||||
int i;
|
||||
double end_time, itime;
|
||||
|
||||
time -= here->VSRCrdelay;
|
||||
|
||||
if(time < *(here->VSRCcoeffs)) {
|
||||
foo = *(here->VSRCcoeffs + 1) ;
|
||||
value = foo;
|
||||
goto loadDone;
|
||||
if (time < here->VSRCcoeffs[0]) {
|
||||
value = here->VSRCcoeffs[1];
|
||||
value = value;
|
||||
break;
|
||||
}
|
||||
|
||||
do {
|
||||
for(i=ii ; i<(here->VSRCfunctionOrder/2)-1; i++ ) {
|
||||
itime = *(here->VSRCcoeffs+2*i);
|
||||
if ( AlmostEqualUlps(itime+repeat_time, time, 3 )) {
|
||||
foo = *(here->VSRCcoeffs+2*i+1);
|
||||
value = foo;
|
||||
goto loadDone;
|
||||
} else if ( (*(here->VSRCcoeffs+2*i)+repeat_time < time)
|
||||
&& (*(here->VSRCcoeffs+2*(i+1))+repeat_time > time) ) {
|
||||
foo = *(here->VSRCcoeffs+2*i+1) + (((time-(*(here->VSRCcoeffs+2*i)+repeat_time))/
|
||||
(*(here->VSRCcoeffs+2*(i+1)) - *(here->VSRCcoeffs+2*i))) *
|
||||
(*(here->VSRCcoeffs+2*i+3) - *(here->VSRCcoeffs+2*i+1)));
|
||||
value = foo;
|
||||
goto loadDone;
|
||||
}
|
||||
end_time =
|
||||
here->VSRCcoeffs[here->VSRCfunctionOrder - 2];
|
||||
if (time > end_time) {
|
||||
double period;
|
||||
|
||||
if (here->VSRCrGiven) {
|
||||
/* Repeating. */
|
||||
|
||||
period = end_time -
|
||||
here->VSRCcoeffs[here->VSRCrBreakpt];
|
||||
time -= period * floor(time / period);
|
||||
time += here->VSRCcoeffs[here->VSRCrBreakpt];
|
||||
} else {
|
||||
value =
|
||||
here->VSRCcoeffs[here->VSRCfunctionOrder - 1];
|
||||
break;
|
||||
}
|
||||
foo = *(here->VSRCcoeffs+ here->VSRCfunctionOrder-1) ;
|
||||
value = foo;
|
||||
}
|
||||
|
||||
if ( !here->VSRCrGiven ) goto loadDone;
|
||||
|
||||
end_time = *(here->VSRCcoeffs + here->VSRCfunctionOrder-2);
|
||||
breakpt_time = *(here->VSRCcoeffs + here->VSRCrBreakpt);
|
||||
repeat_time = end_time + (end_time - breakpt_time)*num_repeat++ - breakpt_time;
|
||||
ii = here->VSRCrBreakpt/2;
|
||||
} while ( here->VSRCrGiven );
|
||||
for (i = 2; i < here->VSRCfunctionOrder; i += 2) {
|
||||
itime = here->VSRCcoeffs[i];
|
||||
if (itime >= time) {
|
||||
time -= here->VSRCcoeffs[i - 2];
|
||||
time /= here->VSRCcoeffs[i] -
|
||||
here->VSRCcoeffs[i - 2];
|
||||
value = here->VSRCcoeffs[i - 1];
|
||||
value += time *
|
||||
( here->VSRCcoeffs[i + 1] -
|
||||
here->VSRCcoeffs[i - 1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -418,7 +423,6 @@ VNoi3 3 0 DC 0 TRNOISE(0 0 0 0 15m 22u 50u) : generate RTS noise
|
|||
|
||||
} // switch
|
||||
} // else (line 48)
|
||||
loadDone:
|
||||
|
||||
/* gtri - begin - wbk - modify for supply ramping option */
|
||||
#ifdef XSPICE_EXP
|
||||
|
|
|
|||
|
|
@ -131,6 +131,13 @@ VSRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select)
|
|||
here->VSRCrGiven = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* buggy input? r is not a repetition coefficient */
|
||||
if (!here->VSRCcoeffs || here->VSRCfunctionOrder < 2) {
|
||||
here->VSRCrGiven = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
here->VSRCr = value->rValue;
|
||||
here->VSRCrGiven = TRUE;
|
||||
|
||||
|
|
@ -140,7 +147,7 @@ VSRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select)
|
|||
}
|
||||
|
||||
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 );
|
||||
return ( E_PARMVAL );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ VSRCsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *state)
|
|||
for (here = VSRCinstances(model); here != NULL ;
|
||||
here=VSRCnextInstance(here)) {
|
||||
|
||||
here->VSRCbreak_time = -1.0; // To set initial breakpoint
|
||||
if(here->VSRCposNode == here->VSRCnegNode) {
|
||||
SPfrontEnd->IFerrorf (ERR_FATAL,
|
||||
"instance %s is a shorted VSRC", here->VSRCname);
|
||||
|
|
|
|||
|
|
@ -462,8 +462,10 @@ INPparseNumMod(CKTcircuit *ckt, INPmodel *model, INPtables *tab, char **errMessa
|
|||
/* Add card structure to model */
|
||||
info = INPcardTab[lastType];
|
||||
error = info->newCard(&tmpCard, model->INPmodfast);
|
||||
if (error)
|
||||
if (error) {
|
||||
FREE(cardName);
|
||||
return error;
|
||||
}
|
||||
/* Handle parameter-less cards */
|
||||
} else if (cinprefix(cardName, "title", 3)) {
|
||||
/* Do nothing */
|
||||
|
|
@ -472,6 +474,7 @@ INPparseNumMod(CKTcircuit *ckt, INPmodel *model, INPtables *tab, char **errMessa
|
|||
} else if (cinprefix(cardName, "end", 3)) {
|
||||
/* Terminate parsing */
|
||||
*errMessage = err;
|
||||
FREE(cardName);
|
||||
return 0;
|
||||
} else {
|
||||
/* Error */
|
||||
|
|
@ -479,6 +482,7 @@ INPparseNumMod(CKTcircuit *ckt, INPmodel *model, INPtables *tab, char **errMessa
|
|||
tprintf("Error on card %d : unrecognized name (%s) - ignored",
|
||||
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);
|
||||
if (info->cardParms[idx].dataType & IF_STRING)
|
||||
FREE(value->sValue);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,8 @@ INPgetValue(CKTcircuit *ckt, char **line, int type, INPtables *tab)
|
|||
list[temp.v.numValue - 1] = tmp;
|
||||
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, "%*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);
|
||||
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, "%*s%s\n", (int)(*line - compline), " ", *line);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -148,6 +148,8 @@ INPpas3(CKTcircuit *ckt, struct card *data, INPtables *tab, TSKtask *task,
|
|||
FREE(name);
|
||||
/* Gobble the rest of the token */
|
||||
line = nexttok(line);
|
||||
if (!line)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
ptemp.rValue = INPevaluate(&line,&error,1);
|
||||
|
|
|
|||
|
|
@ -1107,8 +1107,19 @@ INPparseNode *PT_mkfnode(const char *fname, INPparseNode * arg)
|
|||
INPparseNode *p;
|
||||
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. */
|
||||
(void) strcpy(buf, fname);
|
||||
(void)strncpy(buf, fname, 127);
|
||||
buf[127] = 0;
|
||||
strtolower(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);
|
||||
if (ft_stricterror)
|
||||
controlled_exit(EXIT_BAD);
|
||||
|
||||
return mkfirst(NULL, arg);
|
||||
}
|
||||
|
||||
|
|
@ -1250,7 +1260,8 @@ INPparseNode *PT_mksnode(const char *string, void *ckt)
|
|||
INPparseNode *p;
|
||||
|
||||
/* Make sure the case is ok. */
|
||||
(void) strcpy(buf, string);
|
||||
(void) strncpy(buf, string, 127);
|
||||
buf[127] = 0;
|
||||
strtolower(buf);
|
||||
|
||||
p = TMALLOC(INPparseNode, 1);
|
||||
|
|
|
|||
|
|
@ -29,7 +29,10 @@ const char *SPerror(int type)
|
|||
case E_EXISTS:
|
||||
msg = "device already exists, existing one being used";
|
||||
break;
|
||||
case E_NODEV:
|
||||
case E_EXISTS_BAD:
|
||||
msg = "device already exists, bail out";
|
||||
break;
|
||||
case E_NODEV:
|
||||
msg = "no such device";
|
||||
break;
|
||||
case E_NOMOD:
|
||||
|
|
|
|||
|
|
@ -479,17 +479,26 @@ static void EVTbackup_inst_queue(
|
|||
}
|
||||
inst_queue->next_time = next_time;
|
||||
|
||||
/* Update the modified list by looking for any queued events */
|
||||
/* with posted time > last_time */
|
||||
/* Update the modified list by looking for events that were processed
|
||||
* or queued in the current timestep.
|
||||
*/
|
||||
|
||||
for(i = 0, j = 0; i < num_modified; i++) {
|
||||
|
||||
inst_index = inst_queue->modified_index[i];
|
||||
inst = *(inst_queue->last_step[inst_index]);
|
||||
|
||||
while(inst) {
|
||||
if(inst->posted_time > inst_queue->last_time)
|
||||
break;
|
||||
inst = inst->next;
|
||||
if (inst_queue->current[inst_index] ==
|
||||
inst_queue->last_step[inst_index]) {
|
||||
/* Nothing now removed from the queue,
|
||||
* 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) {
|
||||
|
|
|
|||
|
|
@ -88,11 +88,13 @@ struct dvec *EVTfindvec(
|
|||
int udn_index;
|
||||
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_t *head;
|
||||
Evt_Node_t *event;
|
||||
|
||||
Evt_Node_t *head;
|
||||
Evt_Node_t *event;
|
||||
|
||||
double *anal_point_vec;
|
||||
double *value_vec;
|
||||
double value = 0;
|
||||
|
|
@ -102,13 +104,16 @@ struct dvec *EVTfindvec(
|
|||
|
||||
/* Exit immediately if event-driven stuff not allocated yet, */
|
||||
/* or if number of event nodes is zero. */
|
||||
if(! g_mif_info.ckt)
|
||||
|
||||
ckt = g_mif_info.ckt;
|
||||
if(! ckt)
|
||||
return(NULL);
|
||||
if(! g_mif_info.ckt->evt)
|
||||
evt = ckt->evt;
|
||||
if(! evt)
|
||||
return(NULL);
|
||||
if(! g_mif_info.ckt->evt->info.node_table)
|
||||
if(! evt->info.node_table)
|
||||
return(NULL);
|
||||
if(g_mif_info.ckt->evt->counts.num_nodes == 0)
|
||||
if(evt->counts.num_nodes == 0)
|
||||
return(NULL);
|
||||
|
||||
/* Make a copy of the node name. */
|
||||
|
|
@ -134,8 +139,8 @@ struct dvec *EVTfindvec(
|
|||
}
|
||||
|
||||
/* Look for node name in the event-driven node list */
|
||||
num_nodes = g_mif_info.ckt->evt->counts.num_nodes;
|
||||
node_table = g_mif_info.ckt->evt->info.node_table;
|
||||
num_nodes = evt->counts.num_nodes;
|
||||
node_table = evt->info.node_table;
|
||||
|
||||
for(i = 0, found = MIF_FALSE; i < num_nodes; i++) {
|
||||
if(cieq(name, node_table[i]->name)) {
|
||||
|
|
@ -152,14 +157,14 @@ struct dvec *EVTfindvec(
|
|||
/* Get the UDN type 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");
|
||||
tfree(name);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
num_events++;
|
||||
|
|
@ -170,8 +175,7 @@ struct dvec *EVTfindvec(
|
|||
|
||||
/* Iterate through the events and fill the arrays. */
|
||||
/* 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) {
|
||||
|
||||
/* 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. */
|
||||
/* See FTE/OUTinterface.c:plotInit() for initialization example. */
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ sine
|
|||
slew
|
||||
square
|
||||
summer
|
||||
xfer
|
||||
s_xfer
|
||||
triangle
|
||||
file_source
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -404,6 +404,8 @@ void cm_d_pwm(ARGS)
|
|||
|
||||
*t3 = T(1) + (1 - dphase)/frequency;
|
||||
}
|
||||
cm_analog_set_temp_bkpt(*t1);
|
||||
cm_analog_set_temp_bkpt(*t3);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -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\vectors.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\winprint.h" />
|
||||
<ClInclude Include="..\src\frontend\where.h" />
|
||||
|
|
|
|||
|
|
@ -942,7 +942,6 @@
|
|||
<ClInclude Include="..\src\frontend\variable.h" />
|
||||
<ClInclude Include="..\src\frontend\vectors.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\winprint.h" />
|
||||
<ClInclude Include="..\src\frontend\where.h" />
|
||||
|
|
|
|||
|
|
@ -254,6 +254,8 @@
|
|||
<ClCompile Include="icm\analog\file_source\file_source-ifspec.c" />
|
||||
<ClCompile Include="icm\analog\delay\delay-cfunc.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" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
@ -297,6 +299,8 @@
|
|||
<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\ifspec.ifs" />
|
||||
<None Include="..\..\src\xspice\icm\analog\xfer\cfunc.mod" />
|
||||
<None Include="..\..\src\xspice\icm\analog\xfer\ifspec.ifs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\include\ngspice\dstring.h" />
|
||||
|
|
|
|||
Loading…
Reference in New Issue