Merge branch 'pre-master' into bt_dev

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

73
INSTALL
View File

@ -18,7 +18,7 @@ Table of contents
1.5.1 Most useful options
1.5.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

View File

@ -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

View File

@ -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

View File

@ -135,7 +135,9 @@ VS1 2 0 PULSE (0 5 15.9Ns 0.2Ns 0.2Ns 15.8Ns 32Ns)
VS2 4 0 PULSE (0 5 15.9Ns 0.2Ns 0.2Ns 15.8Ns 32Ns)
.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
*

View File

@ -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

View File

@ -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
*

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -106,7 +106,11 @@ x1 2 3 4 5 6 7 8 9 test
VS1 1 0 PWL(15.9NS 0.0 16.1Ns 5.0 31.9Ns 5.0 32.1Ns 0.0)
.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
*

View File

@ -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

View File

@ -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

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

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

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

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

View File

@ -1,7 +1,6 @@
VBIC Output Test Ic=f(Vc,Ib) vs self heating
.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

View File

@ -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

View File

@ -66,9 +66,10 @@ abridge-w1 [d_divout d_ref d_Un d_D] [s1 s2 u1 d1] dac1 ; change to d_u or d_Un
.control
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

View File

@ -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 );

View File

@ -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 {

View File

@ -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,

View File

@ -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;
}

View File

@ -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();

View File

@ -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);
}
}

View File

@ -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);

View File

@ -136,7 +136,6 @@ static void inp_reorder_params(
static int inp_split_multi_param_lines(struct card *deck, int line_number);
static 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);
}
}

View File

@ -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);

View File

@ -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

View File

@ -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;
}

View File

@ -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 },

View File

@ -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),

View File

@ -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);
}
}
}

View File

@ -1147,7 +1147,9 @@ translate(struct card *deck, char *formal, int flen, char *actual, char *scname,
char *next_name, *name, *t, *nametofree, *paren_ptr;
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]);

View File

@ -93,6 +93,7 @@ extern void *cx_mean(void *, short int , int , int *, short int *);
extern void *cx_stddev(void *, short int , int , int *, short int *);
extern void *cx_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 );

View File

@ -34,7 +34,8 @@ Author: 1986 Thomas L. Quarles
#define E_NOCHANGE 13 /* simulator can't tolerate any more topology changes */
#define E_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 */

View File

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

View File

@ -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. */

View File

@ -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

View File

@ -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 */

View File

@ -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;
}

View File

@ -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,
};
}

View File

@ -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);

View File

@ -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;

View File

@ -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");

View File

@ -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");

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -75,8 +75,8 @@ VBICload(GENmodel *inModel, CKTcircuit *ckt)
,Iccp_Vbci,Iccp_Vbcp,Irs,Irs_Vrs,Irs_Vrth=0.0,Qbcp,Qbcp_Vrth
,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

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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 );
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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:

View File

@ -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) {

View File

@ -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. */

View File

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

View File

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

View File

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

View File

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

View File

@ -935,7 +935,6 @@ lib /machine:x64 /def:..\..\fftw-3.3-dll64\libfftw3-3.def /out:$(IntDir)libfftw3
<ClInclude Include="..\src\frontend\variable.h" />
<ClInclude Include="..\src\frontend\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" />

View File

@ -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" />

View File

@ -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" />