Merge branch 'pre-master-42' into bt_dev

This commit is contained in:
Brian Taylor 2023-09-03 09:25:11 -07:00
commit 717cc075e8
448 changed files with 366141 additions and 754 deletions

View File

@ -116,7 +116,9 @@ Table of Contents
11 S-parameter analysis
Evaluate s-parameters on any port of a multiport circuit, store the resulting
Evaluate S parameters on any port of a multiport circuit, store the resulting
data in a Touchstone file
Load S parameters from s2p file into code model, and do ac simulation on an
automatically generated lumped element circuit.

22
FAQ
View File

@ -1,7 +1,7 @@
Ngspice F.A.Q.Version 2.9 (ngspice-40 release)
Ngspice F.A.Q.Version 2.9 (ngspice-41 release)
Maintained by Holger Vogt
Last update: Mar 24 2023
Last update: Aug 11 2023
This document contains the Frequently Asked Questions (and Answers)
for ngspice project.
@ -96,7 +96,7 @@
from a tcl script and vector plotted or post processed using tcl. A small
GUI may be built by the user to analyze a circuit or a set of circuits.
Tclspice is obtained compiling ngspice activating an additional option.
This has not been used and tested for some time.
This has not been used and tested for recently.
1.4 Why resurrecting Berkeley's Spice?
@ -165,7 +165,7 @@
Vivid discussion are going on in the ngspice discussion groups.
They are found at https://sourceforge.net/p/ngspice/discussion/
A new group 'ngspice tips and examples' will present interesting
A special group 'ngspice tips and examples' will present interesting
ngspice tips (your input is welcome!)
@ -218,12 +218,14 @@
https://sourceforge.net/projects/ngspice/files/ng-spice-rework/
Nearly all distributions for MINGW, Cygwin, Linux, macOS and
others offer install-ready copies of ngspice.
others offer install-ready copies of ngspice. Please see
https://repology.org/project/ngspice/packages for packages
available.
1.12 Where should I look on the World Wide Web for ngspice stuff?
Look at the official Ngpice Web Page:
Have a look at the official Ngpice Web Page:
https://ngspice.sourceforge.io
@ -235,6 +237,8 @@
Others docs are assembled at:
https://ngspice.sourceforge.io/literature.html
https://ngspice.sourceforge.io/tutorials.html
https://ngspice.sourceforge.io/books.html
1.14 Are there some (official) tutorials available?
@ -252,7 +256,7 @@
The latest version released is:
* ngspice-40 (released on Mar 26 2023)
ngspice-41 (released on Aug 13 2023)
2.2. What are the latest features in the current release?
@ -289,7 +293,9 @@
2.6. How can I join the development?
To join the development just code the feature you want to add and send
your patch in the mailing list. Before you start coding check the
your patch to the dev discussion group, open a ticket at the ngspice
Patches page or post a merge request
with Sourceforge. Before you start coding check the
latest development release of ngspice from our git repository.
It might be that your feature has already been implemented.

47
INSTALL
View File

@ -1,8 +1,9 @@
Ngspice installation instructions
=================================
Important notice: since ngspice-39 there has been an update
to the XSPICE code models (analog.cm etc.). Therefore it
Important notice: If you upgrade from ngspice-38 or older
there there is an update required for the XSPICE code
models (analog.cm etc.). Therefore it
is not sufficient to only re-make the main executable,
you will have to compile and install the code models as well,
e.g. with --enable-xspice.
@ -50,16 +51,20 @@ This file describes the procedures to install ngspice from sources.
is needed. Almost any LINUX offers a complete C development environment.
Ngspice is developed on GNU/Linux with gcc and GNU make.
Ngspice may be compiled in three different variant, each with its own
Ngspice may be compiled in three different variants, each with its own
configure settings. Standard ngsoice executable, ngspice as a shared
library and ngspice as a tcl/tk library.
Compilation to 64 bit is recommended and available per default in
the ./compile_linux.sh compule script. 32 bit might be possible,
but is not tested.
The following software must be installed in your system to compile
ngspice as a standard executable (command-line input, file and graphics
output):
bison, flex, X11 headers and libs, Xaw, Xmu, Xext, Xft, FontConfig,
Xrender, and freetype headers (e.g. libX11-devel) and libs (e.g. libX11-6),
and readline.
Xrender, freetype headers and readline.
Typically one needs the headers (e.g. libX11-devel) and the libs (e.g. libX11-6).
ngspice as a shared library (no graphics and no command-line interfaces)
will need bison and flex only.
@ -68,7 +73,7 @@ This file describes the procedures to install ngspice from sources.
internal fft algorithms.
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:
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:
@ -81,21 +86,22 @@ This file describes the procedures to install ngspice from sources.
For compiling ngspice as a shared library, see section 1.4.
1.2 Install from tarball (e.g. ngspice-40.tar.gz)
1.2 Install from tarball (e.g. ngspice-41.tar.gz)
This covers installation from a release distribution (for example
ngspice-40.tar.gz, the so called tar ball).
ngspice-41.tar.gz, the so called tar ball).
After downloading the tar ball to a local directory, unpack it by command:
$ tar -zxvf ngspice-40.tar.gz
$ tar -zxvf ngspice-41.tar.gz
Now change directories in to the top-level source directory (where this
INSTALL file can be found).
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.
compile_linux.sh within the terminal window by ./compile_linux.sh. The
script has to be declared as 'executable', and admin
rights are required to allow the installation of ngspice.
CentOS users may need to add -std=c99 to the CFLAGS in the ../configure
statement.
@ -108,7 +114,9 @@ This file describes the procedures to install ngspice from sources.
$ make
$ sudo make install
The default install directory for executables is /usr/local/bin.
The default install directory for executables is /usr/local/bin, the XSPICE
code models will be installed in /usr/local/lib/ngspice. Some distros use lib64
instead.
A simple ../configure might be sufficient for a basic ngspice, but the preferred
arguments to ../configure are
@ -121,7 +129,7 @@ This file describes the procedures to install ngspice from sources.
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-osdi --enable-openmp
$ ../configure --with-x --enable-xspice --disable-debug --enable-cider --with-readline=yes --enable-predictor --enable-osdi --enable-openmp
$ make 2>&1 | tee make.log
$ sudo make install
@ -170,7 +178,7 @@ This file describes the procedures to install ngspice from sources.
$ ./autogen.sh
$ mkdir release
$ cd release
$ ../configure --with-x --enable-xspice --disable-debug --enable-cider --with-readline=yes --enable-openmp --enable-osdi
$ ../configure --with-x --enable-xspice --disable-debug --enable-cider --with-readline=yes --enable-openmp --enable-predictor --enable-osdi
$ make 2>&1 | tee make.log
$ sudo make install
@ -291,10 +299,8 @@ This file describes the procedures to install ngspice from sources.
--enable-cpdebug
Enable ngspice shell code debug.
--disable-debug
This option will remove the '-g' option passed to the compiler.
This speeds up compilation a *lot*, and is recommended for
normal use.
--disable-sp
Disable S Parameter Analysis
--enable-ftedebug
Enable ngspice frontend debug.
@ -602,9 +608,8 @@ This file describes the procedures to install ngspice from sources.
CIDER and XSPICE are included, the code models for XSPICE
(*.cm) are made as well.
There is currently no installation procedure provided, you may
however install the executable manually as described in the
installation tree below.
ngspice is installed into C:\Spice64\ (release version) or
C:\Spice64d\ (debug version).
The directory (visualc) with its files
vngspice.sln (project starter) and

View File

@ -17,21 +17,21 @@ CODE ORGANIZATION
"visualc/" project files to enable compilation with MS Visual Studio.
"src/" and its subdirectories contain all of the C source code.
It contains the top level files "main.c" used by ngspice and
It contains the top level files "main.c" used by ngspice and
"sharedspice.c" used by ngspice as shared library.
There are also main files for outdated ngnutmeg, nghelp, ngmultidec,
ngproc2mod, and ngsconvert.
"src/ciderlib" hosts the code for the CIDER extension to ngspice, a
2D process simulator offering connection between process and devices
to be simulated by ngspice.
"src/xspice" contains the code for the XSPICE extension to ngspice, an
interface to analog and digital code models for true mixed signal simulation.
interface to analog and digital code models for true mixed signal simulation.
"src/misc" Miscellaneous utility and portability routines.
"src/include" Header files for all *.c files of ngspice.
"src/include" Header files for all *.c files of ngspice.
"src/spicelib" is the device library and analysis portion of ngspice. Within
it are the following subdirectories:
@ -39,7 +39,7 @@ CODE ORGANIZATION
each device implementation.
analysis/ All of the analysis code.
parser/ To set up the matrix derived from the netlist.
"src/maths" contains all maths functions of ngspice with
ni/ Numerical algorithms (used by ckt routines).
sparse/ Sparse matrix package (used by ckt and ni).
@ -49,20 +49,23 @@ CODE ORGANIZATION
misc/ Various math support algorithms
deriv/ Various partial derivatives used by some device models (bjt, MOS1-9)
dense/ Matrix operations used by S-parameter simulation
"src/frontend" contains the code for interfacing ngspice to its input and output.
Files com_*.c contain the control language commands. outitf.c organizes the
output file structure, rawfile.c writes output files, parse.c is the control
language function parser. svg and postscript output are handled as well.
inp.c, inpcom.c and subckt.c serve the main input handling functions:
reading the netlist, parsing it, dealing with compatibility, expanding
inp.c, inpcom.c and subckt.c serve the main input handling functions:
reading the netlist, parsing it, dealing with compatibility, expanding
subcircuits and preparing the internal circuit structure.
Furthermore it contains subdirs
Furthermore it contains subdirs
help/ The windowed help system (outdated).
numparam/ Parser for .param and .func statements.
parser/ More front end -- "C shell".
wdisp/ MS Windows GUI
trannoise/ random number and noise generator
plotting/ plot interface to X11, gnuplot, and preparing output graphs
plotting/ plot interface to X11, gnuplot, and preparing output graphs
(curves and grid), interpreter for 'plot' command (plotit.c)
"src/osdi" contains the code for interfacing ngspice to the OpenVAF compiled
Verilog-A compact device models.

33
NEWS
View File

@ -1,3 +1,36 @@
Ngspice-41, Aug 13th, 2023
============
- New features:
+ Add support for PSpice DLYLINE
+ eprvcd [-a] [-t timescale] node node ..., new options
+ Completely renew XSPICE d_osc code model
+ Read Touchstone file for S parameter simulation
+ Analog node changes in VCD file output
+ Add variable "csnumprec" to allow setting the precision of vectors
and variables
+ option nginfo to enable a status report during simulation (MS Windows GUI)
+ Returned status of the "shell" command available as interpreter
variable "shellstatus"
+ New default colors for Linux, macOS plot windows.
+ Update to commands setscale and compose
+ New function cvector for creating complex vectors
+ Add an option FREQ to the E- and G-sources
+ Improve error messages: More verbose, better user information
+ iplot: new option -w to set width for the window, and -d to set
starting of the plot
+ New dot command .libsave to save a parsed PDK for speeding up
later usage.
+ Speed up parsing of large PDKs (e.g. Skywater)
+ Update VBIC device model
+ Prepare noise capability of XSPICE code models
+ Command 'listing': new extension 'listing r' writes parsed netlist
without further formatting, ready to be be loaded and run again.
- Bug fixes:
+ Several crash bugs (double delete, access NULL pointer etc) removed
which have occurred mostly due to incomplete or faulty inputs.
+ Memory leaks for CIDER removed
Ngspice-40, Mar 31st, 2023
============
- New features:

0
compile_linux_dist.sh Normal file → Executable file
View File

76
compile_linux_klu.sh Executable file
View File

@ -0,0 +1,76 @@
#!/bin/bash
# ngspice-klu build script for Linux, release or debug version, 64 bit
# compile_linux_klu.sh <d>
# https://ieeexplore.ieee.org/document/6226278
# Procedure:
# Install gcc, bison, flex, libtool, autoconf, automake,
# libx11 and libx11-dev (headers), libXaw and libXaw-dev, libreadline and dev
# xmu, xet, xt, libxft, libxrender, libfreetype, libfontconfig
# for details please see the ngspice manual, chapt. 32.1.
# Declare 'compile_linux_klu.sh' executable and start compiling with
# './compile_linux_klu.sh' or './compile_linux_klu.sh d' from the ngspice directory.
# Options:
# XSPICE (--enable-xspice) may be selected at will.
# --disable-debug will give O2 optimization (versus O0 for debug) and removes all debugging info.
# OSDI (--enable-osdi) is not yet supported by KLU
# ngspice as shared library:
# Replace --with-x by --with-ngshared in line ../configure ... .
# Add (optionally) --enable-relpath to avoid absolute paths when searching for code models.
# It might be necessary to uncomment and run ./autogen.sh .
SECONDS=0
# We need to remove all remnants of a previous compile
if test "$1" = "d"; then
rm -f -r debug
mkdir debug
if [ $? -ne 0 ]; then echo "mkdir debug failed"; exit 1 ; fi
else
rm -f -r release
mkdir release
if [ $? -ne 0 ]; then echo "mkdir release failed"; exit 1 ; fi
fi
# If compiling sources from tarball, you may comment out the following two lines:
./autogen.sh
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
../configure --with-x --enable-cider --with-readline=yes --enable-openmp --enable-xspice --enable-klu --enable-predictor --enable-osdi 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
../configure --with-x --enable-cider --with-readline=yes --enable-openmp --enable-xspice --enable-klu --enable-predictor --enable-osdi --disable-debug CFLAGS="-m64 -O2" LDFLAGS="-m64 -s"
fi
if [ $? -ne 0 ]; then echo "../configure failed"; exit 1 ; fi
echo
# make clean is required for properly making the code models
echo "cleaning (see make_clean.log)"
make clean 2>&1 -j8 | tee make_clean.log
exitcode=${PIPESTATUS[0]}
if [ $exitcode -ne 0 ]; then echo "make clean failed"; exit 1 ; fi
echo "compiling (see make.log)"
make 2>&1 -j8 | tee make.log
exitcode=${PIPESTATUS[0]}
if [ $exitcode -ne 0 ]; then echo "make failed"; exit 1 ; fi
# Install to /usr/local
echo "installing (see make_install.log)"
make install 2>&1 | tee make_install.log
exitcode=${PIPESTATUS[0]}
if [ $exitcode -ne 0 ]; then echo "make install failed"; exit 1 ; fi
ELAPSED="Elapsed compile time: $(($SECONDS / 3600))hrs $((($SECONDS / 60) % 60))min $(($SECONDS % 60))sec"
echo
echo $ELAPSED
echo "success"
exit 0

View File

@ -53,14 +53,18 @@ if test "$1" = "d"; then
echo "configuring for 64 bit debug"
echo
# You may add --enable-adms to the following command for adding adms generated devices
../configure --with-wingui --enable-xspice --enable-cider --enable-openmp --enable-osdi --enable-predictor prefix="C:/Spice64d" CFLAGS="-g -m64 -O0 -Wall -Wno-unused-but-set-variable" LDFLAGS="-g -m64"
../configure --with-wingui --enable-xspice --enable-cider --enable-klu --enable-openmp --enable-osdi --enable-predictor prefix="C:/Spice64d" CFLAGS="-g -m64 -O0 -Wall -Wno-unused-but-set-variable" LDFLAGS="-g -m64"
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
<<<<<<< HEAD
../configure --with-wingui --enable-xspice --enable-cider --enable-openmp --enable-osdi --enable-predictor --disable-debug prefix="C:/Spice64" CFLAGS="-m64 -O2" LDFLAGS="-m64 -s"
=======
../configure --with-wingui --enable-xspice --enable-cider --enable-klu --enable-openmp --disable-debug prefix="C:/Spice64" CFLAGS="-m64 -O2" LDFLAGS="-m64 -s"
>>>>>>> compile_min.sh, add KLU dependency for MINGW compilation
fi
if [ $? -ne 0 ]; then echo "../configure failed"; exit 1 ; fi

View File

@ -16,7 +16,7 @@
# problem to the user.
AC_PREREQ([2.59])
m4_define([ngspice_major_version], [40+])
m4_define([ngspice_major_version], [41+])
m4_define([ngspice_minor_version], [0])
m4_define([ngspice_version],
[ngspice_major_version])
@ -117,7 +117,7 @@ LT_INIT([shared static])
# --> Set 'LT_NGSPICE_AGE' to 0.
LT_NGSPICE_CURRENT=0
LT_NGSPICE_REVISION=7
LT_NGSPICE_REVISION=8
LT_NGSPICE_AGE=1
LIBNGSPICE_SO_VERSION=$LT_NGSPICE_CURRENT.$LT_NGSPICE_REVISION.$LT_NGSPICE_AGE
@ -304,6 +304,17 @@ if test "x$with_editline" = xyes; then
fi
fi
# --enable-klu: Use KLU linear systems solver
AC_ARG_ENABLE([klu],
[AS_HELP_STRING([--enable-klu], [Use KLU linear systems solver])])
# Add KLU solver to ngspice
if test "x$enable_klu" = xyes; then
AC_DEFINE(KLU, [], [Define if we want KLU linear systems solver])
AC_MSG_WARN([KLU solver enabled])
fi
AM_CONDITIONAL([KLU_WANTED], [test "x$enable_klu" = xyes])
# Enable maintainer commands only if requested
AM_MAINTAINER_MODE([enable])
@ -1460,6 +1471,7 @@ AC_CONFIG_FILES([Makefile
src/maths/poly/Makefile
src/maths/sparse/Makefile
src/maths/dense/Makefile
src/maths/KLU/Makefile
src/misc/Makefile
src/xspice/Makefile
src/xspice/cm/Makefile

View File

@ -0,0 +1,721 @@
* ISCAS85 benchmark circuit SPICE netlist
* generated by spicegen.pl 1.0
* by Jingye Xu @ VLSI group, Dept of ECE, UIC
.INCLUDE ../../technology/45nm_HP.pm
.OPTIONS GMIN=1e-015 ABSTOL=1e-13 ACCT
* the voltage souces:
Vdd vdd gnd DC 1.8
* the input voltage sources
V1 g21 gnd pulse(0 1 0p 200p 200p 1n 2n)
V2 g18 gnd pulse(0 1 0p 200p 200p 1n 2n)
V3 g31 gnd pulse(0 1 0p 200p 200p 1n 2n)
V4 g17 gnd pulse(0 1 0p 200p 200p 1n 2n)
V5 g27 gnd pulse(0 1 0p 200p 200p 1n 2n)
V6 g11 gnd pulse(0 1 0p 200p 200p 1n 2n)
V7 g22 gnd pulse(0 1 0p 200p 200p 1n 2n)
V8 g32 gnd pulse(0 1 0p 200p 200p 1n 2n)
V9 g30 gnd pulse(0 1 0p 200p 200p 1n 2n)
V10 g4 gnd pulse(0 1 0p 200p 200p 1n 2n)
V11 g12 gnd pulse(0 1 0p 200p 200p 1n 2n)
V12 g29 gnd pulse(0 1 0p 200p 200p 1n 2n)
V13 g24 gnd pulse(0 1 0p 200p 200p 1n 2n)
V14 g39 gnd pulse(0 1 0p 200p 200p 1n 2n)
V15 g38 gnd pulse(0 1 0p 200p 200p 1n 2n)
V16 g20 gnd pulse(0 1 0p 200p 200p 1n 2n)
V17 g5 gnd pulse(0 1 0p 200p 200p 1n 2n)
V18 g35 gnd pulse(0 1 0p 200p 200p 1n 2n)
V19 g23 gnd pulse(0 1 0p 200p 200p 1n 2n)
V20 g13 gnd pulse(0 1 0p 200p 200p 1n 2n)
V21 g2 gnd pulse(0 1 0p 200p 200p 1n 2n)
V22 g37 gnd pulse(0 1 0p 200p 200p 1n 2n)
V23 g41 gnd pulse(0 1 0p 200p 200p 1n 2n)
V24 g9 gnd pulse(0 1 0p 200p 200p 1n 2n)
V25 g40 gnd pulse(0 1 0p 200p 200p 1n 2n)
V26 g14 gnd pulse(0 1 0p 200p 200p 1n 2n)
V27 g36 gnd pulse(0 1 0p 200p 200p 1n 2n)
V28 g19 gnd pulse(0 1 0p 200p 200p 1n 2n)
V29 g8 gnd pulse(0 1 0p 200p 200p 1n 2n)
V30 g3 gnd pulse(0 1 0p 200p 200p 1n 2n)
V31 g26 gnd pulse(0 1 0p 200p 200p 1n 2n)
V32 g16 gnd pulse(0 1 0p 200p 200p 1n 2n)
V33 g10 gnd pulse(0 1 0p 200p 200p 1n 2n)
V34 g6 gnd pulse(0 1 0p 200p 200p 1n 2n)
V35 g1 gnd pulse(0 1 0p 200p 200p 1n 2n)
V36 g28 gnd pulse(0 1 0p 200p 200p 1n 2n)
V37 g25 gnd pulse(0 1 0p 200p 200p 1n 2n)
V38 g15 gnd pulse(0 1 0p 200p 200p 1n 2n)
V39 g33 gnd pulse(0 1 0p 200p 200p 1n 2n)
V40 g7 gnd pulse(0 1 0p 200p 200p 1n 2n)
V41 g34 gnd pulse(0 1 0p 200p 200p 1n 2n)
X101 g20 g356 vdd gnd g422 nand2
X366 g975 g991 vdd gnd x72 and2
X467 g17 g1180 vdd gnd g1260 nand2
X194 g588 g589 vdd gnd g645 nand2
X2 g34 g41 vdd gnd g245 and2
X505 g1240 g1241 vdd gnd g1298 nand2
X254 g712 g748 vdd gnd g767 nand2
X428 g26 g1111 vdd gnd g1207 nand2
X234 g245 g721 vdd gnd g733 nand2
X414 g12 g1069 vdd gnd g1165 nand2
X285 g660 g812 vdd gnd g830 nand2
X130 g412 g413 vdd gnd g501 nand2
X144 g468 g471 vdd gnd g543 nand2
X159 g444 g531 vdd gnd g576 nand2
X120 g392 g393 vdd gnd g471 nand2
X31 g4 g8 vdd gnd g332 nand2
X554 g1315 vdd gnd g1347 not1
X314 g899 vdd gnd g955 not1
X189 g578 g579 vdd gnd g622 nand2
X518 g1266 g1267 vdd gnd g1311 nand2
X471 g19 g1186 vdd gnd g1264 nand2
X504 g1238 g1239 vdd gnd g1297 nand2
X302 g873 vdd gnd g943 not1
X526 g1282 g1283 vdd gnd g1319 nand2
X328 g899 vdd gnd g969 not1
X202 g612 g617 vdd gnd g669 nand2
X170 g477 g546 vdd gnd g587 nand2
X415 g13 g1072 vdd gnd g1168 nand2
X61 g21 g296 vdd gnd g382 nand2
X377 g860 g1001 vdd gnd g1054 and2
X439 g3 g1138 vdd gnd g1232 nand2
X293 g828 g829 vdd gnd g886 nand2
X89 g17 g338 vdd gnd g410 nand2
X275 g645 g797 vdd gnd g820 nand2
X280 g779 g803 vdd gnd g825 nand2
X523 g1276 g1277 vdd gnd g1316 nand2
X246 g724 g736 vdd gnd g759 nand2
X325 g899 vdd gnd g966 not1
X67 g27 g305 vdd gnd g388 nand2
X558 g1319 vdd gnd g1351 not1
X543 g1304 vdd gnd g1336 not1
X398 g899 g1026 vdd gnd g1117 and2
X218 g627 g678 vdd gnd g699 nand2
X46 g6 g272 vdd gnd g367 nand2
X228 g696 g697 vdd gnd g715 nand2
X15 g13 g14 vdd gnd g284 nand2
X58 g18 g290 vdd gnd g379 nand2
X374 g873 g996 vdd gnd g1045 and2
X113 g378 g379 vdd gnd g450 nand2
X396 g886 g1026 vdd gnd g1111 and2
X125 g402 g403 vdd gnd g486 nand2
X5 g37 g41 vdd gnd g254 and2
X383 g834 g1011 vdd gnd g1072 and2
X308 g873 vdd gnd g949 not1
X40 g28 g32 vdd gnd g359 nand2
X457 g12 g1165 vdd gnd g1250 nand2
X260 g760 g761 vdd gnd g779 nand2
X214 g612 g672 vdd gnd g695 nand2
X79 g10 g323 vdd gnd g400 nand2
X182 g513 g564 vdd gnd g599 nand2
X139 g438 g441 vdd gnd g528 nand2
X420 g18 g1087 vdd gnd g1183 nand2
X266 g645 g773 vdd gnd g797 nand2
X358 x41 x42 vdd gnd g1011 and2
X283 g657 g809 vdd gnd g828 nand2
X365 g974 g847 g860 vdd gnd x71 and3
X268 g651 g779 vdd gnd g803 nand2
X551 g1312 vdd gnd g1344 not1
X470 g1087 g1183 vdd gnd g1263 nand2
X185 g570 g571 vdd gnd g602 nand2
X44 g4 g269 vdd gnd g365 nand2
X86 g8 g332 vdd gnd g407 nand2
X14 g11 g12 vdd gnd g281 nand2
X438 g1039 g1135 vdd gnd g1231 nand2
X73 g1 g314 vdd gnd g394 nand2
X30 g11 g15 vdd gnd g329 nand2
X94 g22 g344 vdd gnd g415 nand2
X62 g22 g296 vdd gnd g383 nand2
X417 g15 g1078 vdd gnd g1174 nand2
X121 g394 g395 vdd gnd g474 nand2
X57 g17 g290 vdd gnd g378 nand2
X136 g424 g425 vdd gnd g519 nand2
X506 g1242 g1243 vdd gnd g1299 nand2
X66 g26 g302 vdd gnd g387 nand2
X368 g976 g847 g977 vdd gnd x81 and3
X236 g251 g727 vdd gnd g739 nand2
X233 g242 g718 vdd gnd g730 nand2
X525 g1280 g1281 vdd gnd g1318 nand2
X290 g820 g821 vdd gnd g847 nand2
X473 g20 g1189 vdd gnd g1266 nand2
X95 g26 g347 vdd gnd g416 nand2
X503 g1236 g1237 vdd gnd g1296 nand2
X480 g1102 g1198 vdd gnd g1273 nand2
X442 g1045 g1141 vdd gnd g1235 nand2
X47 g7 g275 vdd gnd g368 nand2
X179 g504 g561 vdd gnd g596 nand2
X276 g773 g797 vdd gnd g821 nand2
X345 g978 g979 g980 g981 vdd gnd g986 or4
X197 g594 g595 vdd gnd g654 nand2
X495 g31 g1222 vdd gnd g1288 nand2
X430 g28 g1117 vdd gnd g1213 nand2
X153 g426 g522 vdd gnd g570 nand2
X81 g3 g326 vdd gnd g402 nand2
X315 g925 vdd gnd g956 not1
X371 g834 g996 vdd gnd g1036 and2
X529 g1288 g1289 vdd gnd g1322 nand2
X397 g912 g1026 vdd gnd g1114 and2
X143 g462 g465 vdd gnd g540 nand2
X309 g886 vdd gnd g950 not1
X78 g6 g320 vdd gnd g399 nand2
X406 g4 g1045 vdd gnd g1141 nand2
X56 g16 g287 vdd gnd g377 nand2
X20 g23 g24 vdd gnd g299 nand2
X384 g847 g1011 vdd gnd g1075 and2
X209 g602 g666 vdd gnd g690 nand2
X423 g21 g1096 vdd gnd g1192 nand2
X100 g31 g353 vdd gnd g421 nand2
X510 g1250 g1251 vdd gnd g1303 nand2
X464 g1078 g1174 vdd gnd g1257 nand2
X201 g602 g607 vdd gnd g666 nand2
X537 g1298 vdd gnd g1330 not1
X265 g642 g770 vdd gnd g794 nand2
X429 g27 g1114 vdd gnd g1210 nand2
X245 g248 g736 vdd gnd g758 nand2
X517 g1264 g1265 vdd gnd g1310 nand2
X138 g432 g435 vdd gnd g525 nand2
X27 g2 g6 vdd gnd g320 nand2
X301 g847 vdd gnd g942 not1
X114 g380 g381 vdd gnd g453 nand2
X122 g396 g397 vdd gnd g477 nand2
X102 g24 g356 vdd gnd g423 nand2
X494 g1123 g1219 vdd gnd g1287 nand2
X4 g36 g41 vdd gnd g251 and2
X219 g632 g681 vdd gnd g700 nand2
X296 g826 g827 vdd gnd g925 nand2
X230 g700 g701 vdd gnd g721 nand2
X213 g602 g672 vdd gnd g694 nand2
X400 g886 g1031 vdd gnd g1123 and2
X200 g600 g601 vdd gnd g663 nand2
X108 g368 g369 vdd gnd g435 nand2
X444 g1048 g1144 vdd gnd g1237 nand2
X522 g1274 g1275 vdd gnd g1315 nand2
X156 g435 g525 vdd gnd g573 nand2
X351 g899 g986 vdd gnd x22 and2
X412 g10 g1063 vdd gnd g1159 nand2
X132 g416 g417 vdd gnd g507 nand2
X437 g2 g1135 vdd gnd g1230 nand2
X180 g507 g561 vdd gnd g597 nand2
X141 g450 g453 vdd gnd g534 nand2
X41 g1 g266 vdd gnd g362 nand2
X278 g776 g800 vdd gnd g823 nand2
X295 g830 g831 vdd gnd g912 nand2
X13 g9 g10 vdd gnd g278 nand2
X37 g19 g23 vdd gnd g350 nand2
X382 g873 g1006 vdd gnd g1069 and2
X252 g709 g745 vdd gnd g765 nand2
X552 g1313 vdd gnd g1345 not1
X240 g263 g715 vdd gnd g751 nand2
X107 g366 g367 vdd gnd g432 nand2
X481 g24 g1201 vdd gnd g1274 nand2
X544 g1305 vdd gnd g1337 not1
X164 g459 g537 vdd gnd g581 nand2
X60 g20 g293 vdd gnd g381 nand2
X247 g251 g739 vdd gnd g760 nand2
X469 g18 g1183 vdd gnd g1262 nand2
X524 g1278 g1279 vdd gnd g1317 nand2
X49 g9 g278 vdd gnd g370 nand2
X264 g768 g769 vdd gnd g791 nand2
X443 g5 g1144 vdd gnd g1236 nand2
X241 g242 g730 vdd gnd g754 nand2
X279 g651 g803 vdd gnd g824 nand2
X375 g834 g1001 vdd gnd g1048 and2
X326 g886 vdd gnd g967 not1
X39 g20 g24 vdd gnd g356 nand2
X116 g384 g385 vdd gnd g459 nand2
X225 g690 g691 vdd gnd g706 nand2
X172 g483 g549 vdd gnd g589 nand2
X426 g24 g1105 vdd gnd g1201 nand2
X93 g18 g344 vdd gnd g414 nand2
X465 g16 g1177 vdd gnd g1258 nand2
X344 g925 g967 g968 g969 vdd gnd g985 and4
X29 g3 g7 vdd gnd g326 nand2
X9 g1 g2 vdd gnd g266 nand2
X157 g438 g528 vdd gnd g574 nand2
X323 g925 vdd gnd g964 not1
X284 g785 g809 vdd gnd g829 nand2
X300 g834 vdd gnd g941 not1
X546 g1307 vdd gnd g1339 not1
X74 g5 g314 vdd gnd g395 nand2
X488 g1114 g1210 vdd gnd g1281 nand2
X316 g912 vdd gnd g957 not1
X472 g1090 g1186 vdd gnd g1265 nand2
X51 g11 g281 vdd gnd g372 nand2
X557 g1318 vdd gnd g1350 not1
X69 g29 g308 vdd gnd g390 nand2
X408 g6 g1051 vdd gnd g1147 nand2
X208 g627 g637 vdd gnd g687 nand2
X431 g29 g1120 vdd gnd g1216 nand2
X154 g429 g522 vdd gnd g571 nand2
X390 g899 g1016 vdd gnd g1093 and2
X493 g30 g1219 vdd gnd g1286 nand2
X332 g860 vdd gnd g973 not1
X210 g607 g666 vdd gnd g691 nand2
X381 g860 g1006 vdd gnd g1066 and2
X256 g715 g751 vdd gnd g769 nand2
X177 g498 g558 vdd gnd g594 nand2
X387 g925 g1016 vdd gnd g1084 and2
X196 g592 g593 vdd gnd g651 nand2
X498 g1129 g1225 vdd gnd g1291 nand2
X287 g663 g815 vdd gnd g832 nand2
X59 g19 g293 vdd gnd g380 nand2
X451 g9 g1156 vdd gnd g1244 nand2
X450 g1057 g1153 vdd gnd g1243 nand2
X68 g28 g305 vdd gnd g389 nand2
X92 g29 g341 vdd gnd g413 nand2
X131 g414 g415 vdd gnd g504 nand2
X401 g912 g1031 vdd gnd g1126 and2
X422 g20 g1093 vdd gnd g1189 nand2
X445 g6 g1147 vdd gnd g1238 nand2
X337 g938 g939 g940 g873 vdd gnd g978 and4
X255 g263 g751 vdd gnd g768 nand2
X352 x21 x22 vdd gnd g1001 and2
X342 g961 g962 g912 g963 vdd gnd g983 and4
X48 g8 g275 vdd gnd g369 nand2
X475 g21 g1192 vdd gnd g1268 nand2
X212 g617 g669 vdd gnd g693 nand2
X38 g27 g31 vdd gnd g353 nand2
X75 g9 g317 vdd gnd g396 nand2
X363 g873 g991 vdd gnd x62 and2
X21 g25 g26 vdd gnd g302 nand2
X8 g40 g41 vdd gnd g263 and2
X80 g14 g323 vdd gnd g401 nand2
X3 g35 g41 vdd gnd g248 and2
X292 g824 g825 vdd gnd g873 nand2
X198 g596 g597 vdd gnd g657 nand2
X12 g7 g8 vdd gnd g275 nand2
X413 g11 g1066 vdd gnd g1162 nand2
X373 g860 g996 vdd gnd g1042 and2
X253 g260 g748 vdd gnd g766 nand2
X360 g971 g991 vdd gnd x52 and2
X391 g925 g1021 vdd gnd g1096 and2
X123 g398 g399 vdd gnd g480 nand2
X183 g516 g567 vdd gnd g600 nand2
X188 g576 g577 vdd gnd g617 nand2
X330 g873 vdd gnd g971 not1
X399 g925 g1031 vdd gnd g1120 and2
X378 g873 g1001 vdd gnd g1057 and2
X462 g1075 g1171 vdd gnd g1255 nand2
X339 g944 g847 g945 g946 vdd gnd g980 and4
X545 g1306 vdd gnd g1338 not1
X281 g654 g806 vdd gnd g826 nand2
X211 g612 g669 vdd gnd g692 nand2
X171 g480 g549 vdd gnd g588 nand2
X409 g7 g1054 vdd gnd g1150 nand2
X191 g582 g583 vdd gnd g632 nand2
X150 g504 g507 vdd gnd g561 nand2
X427 g25 g1108 vdd gnd g1204 nand2
X514 g1258 g1259 vdd gnd g1307 nand2
X468 g1084 g1180 vdd gnd g1261 nand2
X317 g925 vdd gnd g958 not1
X88 g16 g335 vdd gnd g409 nand2
X235 g248 g724 vdd gnd g736 nand2
X207 g622 g632 vdd gnd g684 nand2
X343 g964 g886 g965 g966 vdd gnd g984 and4
X124 g400 g401 vdd gnd g483 nand2
X178 g501 g558 vdd gnd g595 nand2
X519 g1268 g1269 vdd gnd g1312 nand2
X482 g1105 g1201 vdd gnd g1275 nand2
X226 g692 g693 vdd gnd g709 nand2
X306 g847 vdd gnd g947 not1
X238 g257 g709 vdd gnd g745 nand2
X263 g766 g767 vdd gnd g788 nand2
X158 g441 g528 vdd gnd g575 nand2
X319 g912 vdd gnd g960 not1
X36 g26 g30 vdd gnd g347 nand2
X436 g1036 g1132 vdd gnd g1229 nand2
X489 g28 g1213 vdd gnd g1282 nand2
X199 g598 g599 vdd gnd g660 nand2
X388 g886 g1016 vdd gnd g1087 and2
X410 g8 g1057 vdd gnd g1153 nand2
X338 g941 g942 g860 g943 vdd gnd g979 and4
X261 g762 g763 vdd gnd g782 nand2
X35 g18 g22 vdd gnd g344 nand2
X215 g607 g675 vdd gnd g696 nand2
X322 g899 vdd gnd g963 not1
X453 g10 g1159 vdd gnd g1246 nand2
X96 g30 g347 vdd gnd g417 nand2
X446 g1051 g1147 vdd gnd g1239 nand2
X70 g30 g308 vdd gnd g391 nand2
X500 g1230 g1231 vdd gnd g1293 nand2
X535 g1296 vdd gnd g1328 not1
X324 g912 vdd gnd g965 not1
X369 g873 g991 vdd gnd x82 and2
X492 g1120 g1216 vdd gnd g1285 nand2
X299 g860 vdd gnd g940 not1
X559 g1320 vdd gnd g1352 not1
X539 g1300 vdd gnd g1332 not1
X389 g912 g1016 vdd gnd g1090 and2
X305 g873 vdd gnd g946 not1
X1 g33 g41 vdd gnd g242 and2
X105 g362 g363 vdd gnd g426 nand2
X353 g954 g886 g912 vdd gnd x31 and3
X206 g632 g637 vdd gnd g681 nand2
X229 g698 g699 vdd gnd g718 nand2
X509 g1248 g1249 vdd gnd g1302 nand2
X186 g572 g573 vdd gnd g607 nand2
X549 g1310 vdd gnd g1342 not1
X163 g456 g537 vdd gnd g580 nand2
X392 g886 g1021 vdd gnd g1099 and2
X531 g1292 vdd gnd g1324 not1
X329 g847 vdd gnd g970 not1
X402 g899 g1031 vdd gnd g1129 and2
X483 g25 g1204 vdd gnd g1276 nand2
X269 g654 g782 vdd gnd g806 nand2
X117 g386 g387 vdd gnd g462 nand2
X341 g958 g959 g960 g899 vdd gnd g982 and4
X223 g627 g687 vdd gnd g704 nand2
X129 g410 g411 vdd gnd g498 nand2
X550 g1311 vdd gnd g1343 not1
X76 g13 g317 vdd gnd g397 nand2
X23 g29 g30 vdd gnd g308 nand2
X271 g660 g788 vdd gnd g812 nand2
X311 g886 vdd gnd g952 not1
X555 g1316 vdd gnd g1348 not1
X82 g7 g326 vdd gnd g403 nand2
X259 g758 g759 vdd gnd g776 nand2
X289 g818 g819 vdd gnd g834 nand2
X441 g4 g1141 vdd gnd g1234 nand2
X165 g462 g540 vdd gnd g582 nand2
X318 g886 vdd gnd g959 not1
X42 g2 g266 vdd gnd g363 nand2
X155 g432 g525 vdd gnd g572 nand2
X243 g245 g733 vdd gnd g756 nand2
X435 g1 g1132 vdd gnd g1228 nand2
X133 g418 g419 vdd gnd g510 nand2
X91 g25 g341 vdd gnd g412 nand2
X258 g756 g757 vdd gnd g773 nand2
X474 g1093 g1189 vdd gnd g1267 nand2
X237 g254 g706 vdd gnd g742 nand2
X347 g925 g950 g912 vdd gnd x11 and3
X548 g1309 vdd gnd g1341 not1
X174 g489 g552 vdd gnd g591 nand2
X424 g22 g1099 vdd gnd g1195 nand2
X491 g29 g1216 vdd gnd g1284 nand2
X115 g382 g383 vdd gnd g456 nand2
X10 g3 g4 vdd gnd g269 nand2
X521 g1272 g1273 vdd gnd g1314 nand2
X181 g510 g564 vdd gnd g598 nand2
X257 g754 g755 vdd gnd g770 nand2
X34 g25 g29 vdd gnd g341 nand2
X77 g2 g320 vdd gnd g398 nand2
X249 g254 g742 vdd gnd g762 nand2
X540 g1301 vdd gnd g1333 not1
X33 g17 g21 vdd gnd g338 nand2
X128 g408 g409 vdd gnd g495 nand2
X166 g465 g540 vdd gnd g583 nand2
X248 g727 g739 vdd gnd g761 nand2
X562 g1323 vdd gnd g1355 not1
X142 g456 g459 vdd gnd g537 nand2
X168 g471 g543 vdd gnd g585 nand2
X224 g637 g687 vdd gnd g705 nand2
X277 g648 g800 vdd gnd g822 nand2
X106 g364 g365 vdd gnd g429 nand2
X118 g388 g389 vdd gnd g465 nand2
X354 g955 g986 vdd gnd x32 and2
X149 g498 g501 vdd gnd g558 nand2
X90 g21 g338 vdd gnd g411 nand2
X335 g834 vdd gnd g976 not1
X376 g847 g1001 vdd gnd g1051 and2
X393 g912 g1021 vdd gnd g1102 and2
X251 g257 g745 vdd gnd g764 nand2
X530 g1290 g1291 vdd gnd g1323 nand2
X83 g11 g329 vdd gnd g404 nand2
X463 g15 g1174 vdd gnd g1256 nand2
X321 g886 vdd gnd g962 not1
X270 g657 g785 vdd gnd g809 nand2
X286 g788 g812 vdd gnd g831 nand2
X547 g1308 vdd gnd g1340 not1
X458 g1069 g1165 vdd gnd g1251 nand2
X22 g27 g28 vdd gnd g305 nand2
X147 g486 g489 vdd gnd g552 nand2
X340 g834 g947 g948 g949 vdd gnd g981 and4
X43 g3 g269 vdd gnd g364 nand2
X418 g16 g1081 vdd gnd g1177 nand2
X310 g899 vdd gnd g951 not1
X459 g13 g1168 vdd gnd g1252 nand2
X411 g9 g1060 vdd gnd g1156 nand2
X193 g586 g587 vdd gnd g642 nand2
X380 g847 g1006 vdd gnd g1063 and2
X242 g718 g730 vdd gnd g755 nand2
X111 g374 g375 vdd gnd g444 nand2
X513 g1256 g1257 vdd gnd g1306 nand2
X477 g22 g1195 vdd gnd g1270 nand2
X28 g10 g14 vdd gnd g323 nand2
X536 g1297 vdd gnd g1329 not1
X50 g10 g278 vdd gnd g371 nand2
X152 g516 g519 vdd gnd g567 nand2
X499 g1228 g1229 vdd gnd g1292 nand2
X440 g1042 g1138 vdd gnd g1233 nand2
X205 g622 g627 vdd gnd g678 nand2
X294 g832 g833 vdd gnd g899 nand2
X52 g12 g281 vdd gnd g373 nand2
X173 g486 g552 vdd gnd g590 nand2
X272 g663 g791 vdd gnd g815 nand2
X452 g1060 g1156 vdd gnd g1245 nand2
X476 g1096 g1192 vdd gnd g1269 nand2
X484 g1108 g1204 vdd gnd g1277 nand2
X447 g7 g1150 vdd gnd g1240 nand2
X448 g1054 g1150 vdd gnd g1241 nand2
X331 g847 vdd gnd g972 not1
X348 g951 g986 vdd gnd x12 and2
X520 g1270 g1271 vdd gnd g1313 nand2
X162 g453 g534 vdd gnd g579 nand2
X355 x31 x32 vdd gnd g1006 and2
X364 x61 x62 vdd gnd g1021 and2
X403 g1 g1036 vdd gnd g1132 nand2
X385 g860 g1011 vdd gnd g1078 and2
X320 g925 vdd gnd g961 not1
X87 g12 g335 vdd gnd g408 nand2
X356 g956 g886 g957 vdd gnd x41 and3
X184 g519 g567 vdd gnd g601 nand2
X507 g1244 g1245 vdd gnd g1300 nand2
X359 g834 g970 g860 vdd gnd x51 and3
X135 g422 g423 vdd gnd g516 nand2
X63 g23 g299 vdd gnd g384 nand2
X282 g782 g806 vdd gnd g827 nand2
X333 g834 vdd gnd g974 not1
X291 g822 g823 vdd gnd g860 nand2
X167 g468 g543 vdd gnd g584 nand2
X455 g11 g1162 vdd gnd g1248 nand2
X556 g1317 vdd gnd g1349 not1
X460 g1072 g1168 vdd gnd g1253 nand2
X103 g28 g359 vdd gnd g424 nand2
X239 g260 g712 vdd gnd g748 nand2
X434 g32 g1129 vdd gnd g1225 nand2
X145 g474 g477 vdd gnd g546 nand2
X16 g15 g16 vdd gnd g287 nand2
X312 g912 vdd gnd g953 not1
X487 g27 g1210 vdd gnd g1280 nand2
X497 g32 g1225 vdd gnd g1290 nand2
X65 g25 g302 vdd gnd g386 nand2
X407 g5 g1048 vdd gnd g1144 nand2
X425 g23 g1102 vdd gnd g1198 nand2
X127 g406 g407 vdd gnd g492 nand2
X72 g32 g311 vdd gnd g393 nand2
X404 g2 g1039 vdd gnd g1135 nand2
X288 g791 g815 vdd gnd g833 nand2
X386 g873 g1011 vdd gnd g1081 and2
X516 g1262 g1263 vdd gnd g1309 nand2
X533 g1294 vdd gnd g1326 not1
X112 g376 g377 vdd gnd g447 nand2
X303 g834 vdd gnd g944 not1
X541 g1302 vdd gnd g1334 not1
X304 g860 vdd gnd g945 not1
X313 g925 vdd gnd g954 not1
X137 g426 g429 vdd gnd g522 nand2
X327 g912 vdd gnd g968 not1
X532 g1293 vdd gnd g1325 not1
X478 g1099 g1195 vdd gnd g1271 nand2
X146 g480 g483 vdd gnd g549 nand2
X511 g1252 g1253 vdd gnd g1304 nand2
X55 g15 g287 vdd gnd g376 nand2
X25 g1 g5 vdd gnd g314 nand2
X84 g15 g329 vdd gnd g405 nand2
X19 g21 g22 vdd gnd g296 nand2
X367 x71 x72 vdd gnd g1026 and2
X273 g642 g794 vdd gnd g818 nand2
X372 g847 g996 vdd gnd g1039 and2
X394 g899 g1021 vdd gnd g1105 and2
X349 x11 x12 vdd gnd g996 and2
X161 g450 g534 vdd gnd g578 nand2
X490 g1117 g1213 vdd gnd g1283 nand2
X528 g1286 g1287 vdd gnd g1321 nand2
X538 g1299 vdd gnd g1331 not1
X160 g447 g531 vdd gnd g577 nand2
X190 g580 g581 vdd gnd g627 nand2
X449 g8 g1153 vdd gnd g1242 nand2
X336 g860 vdd gnd g977 not1
X297 g834 vdd gnd g938 not1
X502 g1234 g1235 vdd gnd g1295 nand2
X553 g1314 vdd gnd g1346 not1
X7 g39 g41 vdd gnd g260 and2
X560 g1321 vdd gnd g1353 not1
X216 g617 g675 vdd gnd g697 nand2
X176 g495 g555 vdd gnd g593 nand2
X98 g23 g350 vdd gnd g419 nand2
X204 g607 g617 vdd gnd g675 nand2
X221 g622 g684 vdd gnd g702 nand2
X232 g704 g705 vdd gnd g727 nand2
X26 g9 g13 vdd gnd g317 nand2
X54 g14 g284 vdd gnd g375 nand2
X244 g721 g733 vdd gnd g757 nand2
X262 g764 g765 vdd gnd g785 nand2
X18 g19 g20 vdd gnd g293 nand2
X419 g17 g1084 vdd gnd g1180 nand2
X298 g847 vdd gnd g939 not1
X461 g14 g1171 vdd gnd g1254 nand2
X126 g404 g405 vdd gnd g489 nand2
X203 g602 g612 vdd gnd g672 nand2
X433 g31 g1126 vdd gnd g1222 nand2
X220 g637 g681 vdd gnd g701 nand2
X110 g372 g373 vdd gnd g441 nand2
X362 g834 g972 g973 vdd gnd x61 and3
X379 g834 g1006 vdd gnd g1060 and2
X53 g13 g284 vdd gnd g374 nand2
X346 g982 g983 g984 g985 vdd gnd g991 or4
X496 g1126 g1222 vdd gnd g1289 nand2
X501 g1232 g1233 vdd gnd g1294 nand2
X134 g420 g421 vdd gnd g513 nand2
X17 g17 g18 vdd gnd g290 nand2
X187 g574 g575 vdd gnd g612 nand2
X334 g873 vdd gnd g975 not1
X485 g26 g1207 vdd gnd g1278 nand2
X6 g38 g41 vdd gnd g257 and2
X64 g24 g299 vdd gnd g385 nand2
X109 g370 g371 vdd gnd g438 nand2
X97 g19 g350 vdd gnd g418 nand2
X32 g12 g16 vdd gnd g335 nand2
X192 g584 g585 vdd gnd g637 nand2
X405 g3 g1042 vdd gnd g1138 nand2
X71 g31 g311 vdd gnd g392 nand2
X140 g444 g447 vdd gnd g531 nand2
X148 g492 g495 vdd gnd g555 nand2
X274 g770 g794 vdd gnd g819 nand2
X222 g632 g684 vdd gnd g703 nand2
X534 g1295 vdd gnd g1327 not1
X466 g1081 g1177 vdd gnd g1259 nand2
X432 g30 g1123 vdd gnd g1219 nand2
X24 g31 g32 vdd gnd g311 nand2
X515 g1260 g1261 vdd gnd g1308 nand2
X151 g510 g513 vdd gnd g564 nand2
X227 g694 g695 vdd gnd g712 nand2
X486 g1111 g1207 vdd gnd g1279 nand2
X85 g4 g332 vdd gnd g406 nand2
X267 g648 g776 vdd gnd g800 nand2
X370 x81 x82 vdd gnd g1031 and2
X169 g474 g546 vdd gnd g586 nand2
X11 g5 g6 vdd gnd g272 nand2
X350 g925 g952 g953 vdd gnd x21 and3
X456 g1066 g1162 vdd gnd g1249 nand2
X217 g622 g678 vdd gnd g698 nand2
X307 g860 vdd gnd g948 not1
X542 g1303 vdd gnd g1335 not1
X527 g1284 g1285 vdd gnd g1320 nand2
X250 g706 g742 vdd gnd g763 nand2
X195 g590 g591 vdd gnd g648 nand2
X421 g19 g1090 vdd gnd g1186 nand2
X357 g899 g986 vdd gnd x42 and2
X119 g390 g391 vdd gnd g468 nand2
X99 g27 g353 vdd gnd g420 nand2
X45 g5 g272 vdd gnd g366 nand2
X454 g1063 g1159 vdd gnd g1247 nand2
X508 g1246 g1247 vdd gnd g1301 nand2
X512 g1254 g1255 vdd gnd g1305 nand2
X231 g702 g703 vdd gnd g724 nand2
X175 g492 g555 vdd gnd g592 nand2
X479 g23 g1198 vdd gnd g1272 nand2
X395 g925 g1026 vdd gnd g1108 and2
X104 g32 g359 vdd gnd g425 nand2
X416 g14 g1075 vdd gnd g1171 nand2
X361 x51 x52 vdd gnd g1016 and2
X561 g1322 vdd gnd g1354 not1
.subckt and3 a b c vdd vss z
m01 08 a vdd vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m02 n1 a vss vss nmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m03 vdd b 08 vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m04 sig6 b n1 vss nmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m05 08 c vdd vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m06 08 c sig6 vss nmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m07 vdd 08 z vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m08 vss 08 z vss nmos l=0.12u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
c4 08 vss 1.142f
c5 a vss 0.539f
c7 b vss 0.609f
c8 c vss 0.651f
c3 z vss 0.745f
.ends
.subckt or4 a b c d vdd vss z
m01 sig8 a vdd vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m02 vdd a 05 vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m03 sig1 a vss vss nmos l=0.12u w=0.33u as=0.08745p ad=0.08745p ps=1.19u pd=1.19u
m04 n2 b sig8 vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m05 05 b 08 vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m06 vss b sig1 vss nmos l=0.12u w=0.33u as=0.08745p ad=0.08745p ps=1.19u pd=1.19u
m07 10 c n2 vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m08 08 c 11 vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m09 sig1 c vss vss nmos l=0.12u w=0.33u as=0.08745p ad=0.08745p ps=1.19u pd=1.19u
m10 sig1 d 10 vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m11 11 d sig1 vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m12 vss d sig1 vss nmos l=0.12u w=0.33u as=0.08745p ad=0.08745p ps=1.19u pd=1.19u
m13 vdd sig1 z vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m14 vss sig1 z vss nmos l=0.12u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
c4 a vss 1.356f
c5 b vss 1.229f
c6 c vss 1.043f
c7 d vss 0.797f
c1 sig1 vss 1.003f
c3 z vss 0.701f
.ends
.subckt xnr2v0x1 a b vdd vss z
m01 z b sig3 vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m02 bn sig3 z vss nmos l=0.12u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
m03 sig3 a vdd vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m04 vdd b bn vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m05 z bn sig3 vss nmos l=0.12u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
m06 vdd sig3 n1 vdd pmos l=0.12u w=1.54u as=0.4081p ad=0.4081p ps=3.61u pd=3.61u
m07 sig3 a vss vss nmos l=0.12u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
m08 n1 bn z vdd pmos l=0.12u w=1.54u as=0.4081p ad=0.4081p ps=3.61u pd=3.61u
m09 vss b bn vss nmos l=0.12u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
c4 a vss 0.389f
c2 bn vss 1.593f
c5 b vss 0.840f
c3 sig3 vss 0.618f
c6 z vss 0.627f
.ends
.subckt nand2 a b vdd vss z
m01 vdd a z vdd pmos l=0.12u w=0.77u as=0.20405p ad=0.20405p ps=2.07u pd=2.07u
m02 vss a sig3 vss nmos l=0.12u w=0.66u as=0.1749p ad=0.1749p ps=1.85u pd=1.85u
m03 z b vdd vdd pmos l=0.12u w=0.77u as=0.20405p ad=0.20405p ps=2.07u pd=2.07u
m04 sig3 b z vss nmos l=0.12u w=0.66u as=0.1749p ad=0.1749p ps=1.85u pd=1.85u
c4 a vss 0.549f
c5 b vss 0.578f
c1 z vss 0.609f
.ends
.subckt and4 a b c d vdd vss z
m01 10 a vdd vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m02 n1 a vss vss nmos l=0.12u w=0.88u as=0.2332p ad=0.2332p ps=2.29u pd=2.29u
m03 vdd b 10 vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m04 sig7 b n1 vss nmos l=0.12u w=0.88u as=0.2332p ad=0.2332p ps=2.29u pd=2.29u
m05 10 c vdd vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m06 n3 c sig7 vss nmos l=0.12u w=0.88u as=0.2332p ad=0.2332p ps=2.29u pd=2.29u
m07 vdd d 10 vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m08 10 d n3 vss nmos l=0.12u w=0.88u as=0.2332p ad=0.2332p ps=2.29u pd=2.29u
m09 vdd 10 z vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m10 vss 10 z vss nmos l=0.12u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
c4 10 vss 0.940f
c5 a vss 0.674f
c8 b vss 0.541f
c9 c vss 0.622f
c10 d vss 0.791f
c3 z vss 0.765f
.ends
.subckt and2 a b vdd vss z
m01 06 a vdd vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m02 n1 a vss vss nmos l=0.12u w=0.605u as=0.160325p ad=0.160325p ps=1.74u pd=1.74u
m03 vdd b 06 vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m04 06 b n1 vss nmos l=0.12u w=0.605u as=0.160325p ad=0.160325p ps=1.74u pd=1.74u
m05 vdd 06 z vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m06 vss 06 z vss nmos l=0.12u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
c4 06 vss 0.724f
c5 a vss 0.663f
c6 b vss 0.538f
c3 z vss 0.595f
.ends
.subckt not1 a vdd vss z
m01 vdd a z vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m02 vss a z vss nmos l=0.12u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
c3 a vss 0.384f
c2 z vss 0.576f
.ends
* simulation command:
.tran 1ps 1ns
.print tran V(g1326) V(g1339) V(g1349) V(g1352) V(g1350) V(g1340) V(g1332) V(g1351) V(g1327) V(g1345) V(g1324) V(g1333) V(g1344) V(g1334) V(g1346) V(g1325) V(g1343) V(g1347) V(g1335) V(g1342) V(g1353) V(g1354) V(g1329) V(g1348) V(g1328) V(g1341) V(g1336) V(g1330) V(g1337) V(g1331) V(g1338) V(g1355)
.end

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,429 @@
* ISCAS85 benchmark circuit SPICE netlist
* generated by spicegen.pl 1.0
* by Jingye Xu @ VLSI group, Dept of ECE, UIC
.INCLUDE ../../technology/45nm_HP.pm
.OPTIONS GMIN=1e-015 ABSTOL=1e-13 ACCT
* the voltage souces:
Vdd vdd gnd DC 1.8
* the input voltage sources
V1 g35 gnd pulse(0 1 0p 200p 200p 1n 2n)
V2 g21 gnd pulse(0 1 0p 200p 200p 1n 2n)
V3 g18 gnd pulse(0 1 0p 200p 200p 1n 2n)
V4 g23 gnd pulse(0 1 0p 200p 200p 1n 2n)
V5 g13 gnd pulse(0 1 0p 200p 200p 1n 2n)
V6 g2 gnd pulse(0 1 0p 200p 200p 1n 2n)
V7 g31 gnd pulse(0 1 0p 200p 200p 1n 2n)
V8 g9 gnd pulse(0 1 0p 200p 200p 1n 2n)
V9 g17 gnd pulse(0 1 0p 200p 200p 1n 2n)
V10 g27 gnd pulse(0 1 0p 200p 200p 1n 2n)
V11 g14 gnd pulse(0 1 0p 200p 200p 1n 2n)
V12 g36 gnd pulse(0 1 0p 200p 200p 1n 2n)
V13 g19 gnd pulse(0 1 0p 200p 200p 1n 2n)
V14 g8 gnd pulse(0 1 0p 200p 200p 1n 2n)
V15 g3 gnd pulse(0 1 0p 200p 200p 1n 2n)
V16 g26 gnd pulse(0 1 0p 200p 200p 1n 2n)
V17 g16 gnd pulse(0 1 0p 200p 200p 1n 2n)
V18 g11 gnd pulse(0 1 0p 200p 200p 1n 2n)
V19 g22 gnd pulse(0 1 0p 200p 200p 1n 2n)
V20 g32 gnd pulse(0 1 0p 200p 200p 1n 2n)
V21 g30 gnd pulse(0 1 0p 200p 200p 1n 2n)
V22 g10 gnd pulse(0 1 0p 200p 200p 1n 2n)
V23 g6 gnd pulse(0 1 0p 200p 200p 1n 2n)
V24 g1 gnd pulse(0 1 0p 200p 200p 1n 2n)
V25 g28 gnd pulse(0 1 0p 200p 200p 1n 2n)
V26 g25 gnd pulse(0 1 0p 200p 200p 1n 2n)
V27 g4 gnd pulse(0 1 0p 200p 200p 1n 2n)
V28 g15 gnd pulse(0 1 0p 200p 200p 1n 2n)
V29 g12 gnd pulse(0 1 0p 200p 200p 1n 2n)
V30 g29 gnd pulse(0 1 0p 200p 200p 1n 2n)
V31 g33 gnd pulse(0 1 0p 200p 200p 1n 2n)
V32 g7 gnd pulse(0 1 0p 200p 200p 1n 2n)
V33 g24 gnd pulse(0 1 0p 200p 200p 1n 2n)
V34 g34 gnd pulse(0 1 0p 200p 200p 1n 2n)
V35 g20 gnd pulse(0 1 0p 200p 200p 1n 2n)
V36 g5 gnd pulse(0 1 0p 200p 200p 1n 2n)
X101 x246 y246 vdd gnd g246 nand2
X261 g378 g418 g421 g425 vdd gnd g432 nand4
X194 g308 g281 vdd gnd g339 xor2
X215 g333 g303 vdd gnd g350 nand2
X35 g17 g131 vdd gnd g188 nor2
X2 g2 vdd gnd g119 not1
X96 g203 g177 vdd gnd g246 xor2
X70 g203 g165 vdd gnd g232 xor2
X254 g383 g390 g404 g417 vdd gnd g425 nand4
X234 g2 g241 g332 g368 vdd gnd g377 nand4
X130 g242 g194 vdd gnd g292 nand2
X144 g293 vdd gnd g306 not1
X159 x329 y329 vdd gnd g329 nand2
X120 g235 g189 vdd gnd g272 nand2
X31 g9 g123 vdd gnd g184 nor2
X189 g278 vdd gnd z337 not1
X202 g308 vdd gnd w341 not1
X170 g269 w331 vdd gnd y331 nand2
X1 g1 vdd gnd g118 not1
X61 g203 z226 vdd gnd x226 nand2
X105 g180 vdd gnd z250 not1
X229 g358 g21 vdd gnd g372 nand2
X206 x341 y341 vdd gnd g341 nand2
X186 g318 g11 vdd gnd g336 nand2
X89 g203 g174 vdd gnd g242 xor2
X163 g308 z330 vdd gnd x330 nand2
X246 x41 x42 vdd gnd g413 and2
X117 g226 g183 vdd gnd g263 nand2
X67 g203 z229 vdd gnd x229 nand2
X223 x31 x32 x33 vdd gnd g355 and3
X129 g238 g192 vdd gnd g291 nand2
X218 g339 g306 vdd gnd g353 nand2
X46 g154 g159 g162 vdd gnd x11 and3
X228 g358 g17 vdd gnd g371 nand2
X15 g28 vdd gnd g146 not1
X58 g203 g159 vdd gnd g226 xor2
X76 g203 g168 vdd gnd g235 xor2
X113 g213 g28 vdd gnd g257 nand2
X125 g226 g184 vdd gnd g287 nand2
X23 g126 g10 vdd gnd g162 nand2
X5 g8 vdd gnd g126 not1
X40 g27 g143 vdd gnd g193 nor2
X82 g203 g171 vdd gnd g238 xor2
X259 g378 g383 g418 g396 vdd gnd g430 nand4
X260 g378 g383 g421 g424 vdd gnd g431 nand4
X165 x330 y330 vdd gnd g330 nand2
X214 g331 g302 vdd gnd g349 nand2
X79 g203 z235 vdd gnd x235 nand2
X155 g308 vdd gnd w329 not1
X42 g31 g147 vdd gnd g195 nor2
X182 g275 vdd gnd z335 not1
X243 g377 vdd gnd g412 not1
X133 g259 g263 g266 vdd gnd x21 and3
X91 g174 vdd gnd z242 not1
X258 g412 g413 vdd gnd g429 nor2
X139 g288 vdd gnd g301 not1
X237 g253 g338 g371 g14 vdd gnd g390 nand4
X174 g308 vdd gnd w333 not1
X115 g223 g157 vdd gnd g259 nand2
X10 g18 vdd gnd g135 not1
X257 g355 vdd gnd g428 not1
X181 g308 vdd gnd w335 not1
X34 g15 g131 vdd gnd g187 nor2
X77 g203 vdd gnd w235 not1
X185 x335 y335 vdd gnd g335 nand2
X44 g35 g151 vdd gnd g197 nor2
X249 g404 vdd gnd g416 not1
X86 g171 w238 vdd gnd y238 nand2
X14 g26 vdd gnd g143 not1
X33 g13 g127 vdd gnd g186 nor2
X128 g235 g190 vdd gnd g290 nand2
X73 g203 z232 vdd gnd x232 nand2
X30 g7 g123 vdd gnd g183 nor2
X248 g401 vdd gnd g415 not1
X166 g308 g269 vdd gnd g331 xor2
X94 x242 y242 vdd gnd g242 nand2
X62 g159 w226 vdd gnd y226 nand2
X121 g238 g191 vdd gnd g275 nand2
X57 x223 y223 vdd gnd g223 nand2
X224 g355 vdd gnd g358 not1
X168 g269 vdd gnd z331 not1
X142 g291 vdd gnd g304 not1
X136 x21 x22 x23 vdd gnd g295 and3
X106 g203 z250 vdd gnd x250 nand2
X66 g162 vdd gnd z229 not1
X118 g229 g185 vdd gnd g266 nand2
X149 g308 vdd gnd w328 not1
X90 g203 vdd gnd w242 not1
X236 g249 g336 g370 g10 vdd gnd g383 nand4
X233 g358 g36 vdd gnd g376 nand2
X251 g383 g414 vdd gnd g418 nand2
X95 g213 g4 vdd gnd g245 nand2
X83 g203 vdd gnd w238 not1
X47 g165 g168 g171 vdd gnd x12 and3
X179 g318 g7 vdd gnd g334 nand2
X197 g308 z339 vdd gnd x339 nand2
X153 x328 y328 vdd gnd g328 nand2
X22 g122 g6 vdd gnd g159 nand2
X81 x235 y235 vdd gnd g235 nand2
X147 g295 vdd gnd g318 not1
X43 g33 g147 vdd gnd g196 nor2
X143 g292 vdd gnd g305 not1
X193 g318 g15 vdd gnd g338 nand2
X242 g258 g345 g376 g34 vdd gnd g411 nand4
X78 g168 vdd gnd z235 not1
X111 g213 g20 vdd gnd g255 nand2
X28 g146 g30 vdd gnd g177 nand2
X56 g154 w223 vdd gnd y223 nand2
X152 g259 w328 vdd gnd y328 nand2
X50 g199 vdd gnd g203 not1
X20 g3 g119 vdd gnd g157 nor2
X205 g284 w341 vdd gnd y341 nand2
X209 g318 g31 vdd gnd g344 nand2
X173 g308 g272 vdd gnd g333 xor2
X100 g177 w246 vdd gnd y246 nand2
X52 g203 g154 vdd gnd g223 xor2
X201 g308 g284 vdd gnd g341 xor2
X245 g401 g404 g408 g411 vdd gnd x42 and4
X138 g287 vdd gnd g300 not1
X27 g142 g26 vdd gnd g174 nand2
X114 g213 g32 vdd gnd g258 nand2
X122 g242 g193 vdd gnd g278 nand2
X102 g213 g8 vdd gnd g249 nand2
X4 g6 vdd gnd g123 not1
X162 g266 vdd gnd z330 not1
X219 g341 g307 vdd gnd g354 nand2
X230 g358 g25 vdd gnd g373 nand2
X213 g330 g301 vdd gnd g348 nand2
X87 x238 y238 vdd gnd g238 nand2
X108 x250 y250 vdd gnd g250 nand2
X200 g318 g19 vdd gnd g340 nand2
X184 g275 w335 vdd gnd y335 nand2
X156 g263 vdd gnd z329 not1
X132 g250 g198 vdd gnd g294 nand2
X135 g278 g281 g284 vdd gnd x23 and3
X63 x226 y226 vdd gnd g226 nand2
X167 g308 vdd gnd w331 not1
X180 g308 g275 vdd gnd g335 xor2
X141 g290 vdd gnd g303 not1
X41 g29 g143 vdd gnd g194 nor2
X103 g203 g180 vdd gnd g250 xor2
X239 g255 g342 g373 g22 vdd gnd g401 nand4
X13 g24 vdd gnd g142 not1
X145 g294 vdd gnd g307 not1
X16 g30 vdd gnd g147 not1
X37 g21 g135 vdd gnd g190 nor2
X252 g383 g390 g415 g396 vdd gnd g421 nand4
X240 g256 g343 g374 g26 vdd gnd g404 nand4
X107 g180 w250 vdd gnd y250 nand2
X65 g203 vdd gnd w229 not1
X164 g266 w330 vdd gnd y330 nand2
X60 g159 vdd gnd z226 not1
X247 g390 vdd gnd g414 not1
X72 g165 vdd gnd z232 not1
X127 g232 g188 vdd gnd g289 nand2
X49 x11 x12 x13 vdd gnd g199 and3
X241 g257 g344 g375 g30 vdd gnd g408 nand4
X39 g25 g139 vdd gnd g192 nor2
X112 g213 g24 vdd gnd g256 nand2
X116 g223 g158 vdd gnd g262 nand2
X225 g5 g358 vdd gnd g368 nand2
X137 g262 vdd gnd g299 not1
X172 g3 g318 vdd gnd g332 nand2
X93 g174 w242 vdd gnd y242 nand2
X29 g150 g34 vdd gnd g180 nand2
X146 g295 vdd gnd g308 not1
X9 g16 vdd gnd g134 not1
X25 g134 g18 vdd gnd g168 nand2
X55 g203 z223 vdd gnd x223 nand2
X157 g308 z329 vdd gnd x329 nand2
X84 g171 vdd gnd z238 not1
X19 g118 g2 vdd gnd g154 nand2
X74 g165 w232 vdd gnd y232 nand2
X161 g308 vdd gnd w330 not1
X51 g199 vdd gnd g213 not1
X160 g308 g266 vdd gnd g330 xor2
X190 g308 z337 vdd gnd x337 nand2
X69 x229 y229 vdd gnd g229 nand2
X208 g318 g27 vdd gnd g343 nand2
X154 g308 g263 vdd gnd g329 xor2
X7 g12 vdd gnd g130 not1
X210 g318 g35 vdd gnd g345 nand2
X256 g295 vdd gnd g427 not1
X216 g335 g304 vdd gnd g351 nand2
X177 g272 w333 vdd gnd y333 nand2
X98 g177 vdd gnd z246 not1
X176 g308 z333 vdd gnd x333 nand2
X204 g308 z341 vdd gnd x341 nand2
X221 g349 g350 g351 vdd gnd x32 and3
X232 g358 g33 vdd gnd g375 nand2
X196 g281 vdd gnd z339 not1
X26 g138 g22 vdd gnd g171 nand2
X59 g203 vdd gnd w226 not1
X54 g154 vdd gnd z223 not1
X244 g378 g383 g390 g396 vdd gnd x41 and4
X18 g34 vdd gnd g151 not1
X126 g229 g186 vdd gnd g288 nand2
X203 g284 vdd gnd z341 not1
X220 g346 g347 g348 vdd gnd x31 and3
X68 g162 w229 vdd gnd y229 nand2
X110 g213 g16 vdd gnd g254 nand2
X53 g203 vdd gnd w223 not1
X92 g203 z242 vdd gnd x242 nand2
X131 g246 g196 vdd gnd g293 nand2
X255 g199 vdd gnd g426 not1
X17 g32 vdd gnd g150 not1
X134 g269 g272 g275 vdd gnd x22 and3
X187 g308 g278 vdd gnd g337 xor2
X48 g174 g177 g180 vdd gnd x13 and3
X6 g10 vdd gnd g127 not1
X212 g329 g300 vdd gnd g347 nand2
X64 g203 g162 vdd gnd g229 xor2
X38 g23 g139 vdd gnd g191 nor2
X109 g213 g12 vdd gnd g253 nand2
X32 g11 g127 vdd gnd g185 nor2
X97 g203 vdd gnd w246 not1
X192 x337 y337 vdd gnd g337 nand2
X75 x232 y232 vdd gnd g232 nand2
X21 g5 g119 vdd gnd g158 nor2
X80 g168 w235 vdd gnd y235 nand2
X8 g14 vdd gnd g131 not1
X3 g4 vdd gnd g122 not1
X198 g281 w339 vdd gnd y339 nand2
X71 g203 vdd gnd w232 not1
X12 g22 vdd gnd g139 not1
X140 g289 vdd gnd g302 not1
X253 g396 g390 g416 vdd gnd g424 nand3
X148 g308 g259 vdd gnd g328 xor2
X123 g246 g195 vdd gnd g281 nand2
X183 g308 z335 vdd gnd x335 nand2
X222 g352 g353 g354 vdd gnd x33 and3
X188 g308 vdd gnd w337 not1
X24 g130 g14 vdd gnd g165 nand2
X151 g308 z328 vdd gnd x328 nand2
X227 g358 g13 vdd gnd g370 nand2
X85 g203 z238 vdd gnd x238 nand2
X171 x331 y331 vdd gnd g331 nand2
X211 g328 g299 vdd gnd g346 nand2
X11 g20 vdd gnd g138 not1
X169 g308 z331 vdd gnd x331 nand2
X191 g278 w337 vdd gnd y337 nand2
X217 g337 g305 vdd gnd g352 nand2
X150 g259 vdd gnd z328 not1
X88 g1 g213 vdd gnd g241 nand2
X250 g408 vdd gnd g417 not1
X235 g245 g334 g369 g6 vdd gnd g378 nand4
X207 g318 g23 vdd gnd g342 nand2
X195 g308 vdd gnd w339 not1
X124 g250 g197 vdd gnd g284 nand2
X178 x333 y333 vdd gnd g333 nand2
X99 g203 z246 vdd gnd x246 nand2
X119 g232 g187 vdd gnd g269 nand2
X45 g36 g151 vdd gnd g198 nor2
X226 g358 g9 vdd gnd g369 nand2
X238 g254 g340 g372 g18 vdd gnd g396 nand4
X231 g358 g29 vdd gnd g374 nand2
X158 g263 w329 vdd gnd y329 nand2
X175 g272 vdd gnd z333 not1
X36 g19 g135 vdd gnd g189 nor2
X104 g203 vdd gnd w250 not1
X199 x339 y339 vdd gnd g339 nand2
.subckt nor2 a b vdd vss z
m01 vdd a 01 vdd pmos l=0.12u w=1.54u as=0.4081p ad=0.4081p ps=3.61u pd=3.61u
m02 vss a z vss nmos l=0.12u w=0.44u as=0.1166p ad=0.1166p ps=1.41u pd=1.41u
m03 01 b z vdd pmos l=0.12u w=1.54u as=0.4081p ad=0.4081p ps=3.61u pd=3.61u
m04 z b vss vss nmos l=0.12u w=0.44u as=0.1166p ad=0.1166p ps=1.41u pd=1.41u
c4 a vss 0.341f
c3 b vss 0.433f
c2 z vss 0.677f
.ends
.subckt and4 a b c d vdd vss z
m01 10 a vdd vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m02 n1 a vss vss nmos l=0.12u w=0.88u as=0.2332p ad=0.2332p ps=2.29u pd=2.29u
m03 vdd b 10 vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m04 sig7 b n1 vss nmos l=0.12u w=0.88u as=0.2332p ad=0.2332p ps=2.29u pd=2.29u
m05 10 c vdd vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m06 n3 c sig7 vss nmos l=0.12u w=0.88u as=0.2332p ad=0.2332p ps=2.29u pd=2.29u
m07 vdd d 10 vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m08 10 d n3 vss nmos l=0.12u w=0.88u as=0.2332p ad=0.2332p ps=2.29u pd=2.29u
m09 vdd 10 z vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m10 vss 10 z vss nmos l=0.12u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
c4 10 vss 0.940f
c5 a vss 0.674f
c8 b vss 0.541f
c9 c vss 0.622f
c10 d vss 0.791f
c3 z vss 0.765f
.ends
.subckt not1 a vdd vss z
m01 vdd a z vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m02 vss a z vss nmos l=0.12u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
c3 a vss 0.384f
c2 z vss 0.576f
.ends
.subckt xor2 a b vdd vss z
m01 04 a vdd vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m02 04 a vss vss nmos l=0.12u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
m03 vdd b bn vdd pmos l=0.12u w=1.485u as=0.393525p ad=0.393525p ps=3.5u pd=3.5u
m04 z b 04 vss nmos l=0.12u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
m05 vss b bn vss nmos l=0.12u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
m06 bn 04 z vdd pmos l=0.12u w=1.485u as=0.393525p ad=0.393525p ps=3.5u pd=3.5u
m07 vss 04 09 vss nmos l=0.12u w=0.66u as=0.1749p ad=0.1749p ps=1.85u pd=1.85u
m08 z bn 04 vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m09 09 bn z vss nmos l=0.12u w=0.66u as=0.1749p ad=0.1749p ps=1.85u pd=1.85u
c6 04 vss 0.683f
c4 a vss 0.590f
c1 bn vss 0.910f
c3 b vss 1.149f
c5 z vss 0.680f
.ends
.subckt and3 a b c vdd vss z
m01 08 a vdd vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m02 n1 a vss vss nmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m03 vdd b 08 vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m04 sig6 b n1 vss nmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m05 08 c vdd vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m06 08 c sig6 vss nmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m07 vdd 08 z vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m08 vss 08 z vss nmos l=0.12u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
c4 08 vss 1.142f
c5 a vss 0.539f
c7 b vss 0.609f
c8 c vss 0.651f
c3 z vss 0.745f
.ends
.subckt nand4 a b c d vdd vss z
m01 vdd a z vdd pmos l=0.12u w=0.935u as=0.247775p ad=0.247775p ps=2.4u pd=2.4u
m02 vss a sig7 vss nmos l=0.12u w=1.1u as=0.2915p ad=0.2915p ps=2.73u pd=2.73u
m03 z b vdd vdd pmos l=0.12u w=0.935u as=0.247775p ad=0.247775p ps=2.4u pd=2.4u
m04 sig7 b sig3 vss nmos l=0.12u w=1.1u as=0.2915p ad=0.2915p ps=2.73u pd=2.73u
m05 vdd c z vdd pmos l=0.12u w=0.935u as=0.247775p ad=0.247775p ps=2.4u pd=2.4u
m06 sig3 c sig2 vss nmos l=0.12u w=1.1u as=0.2915p ad=0.2915p ps=2.73u pd=2.73u
m07 z d vdd vdd pmos l=0.12u w=0.935u as=0.247775p ad=0.247775p ps=2.4u pd=2.4u
m08 sig2 d z vss nmos l=0.12u w=1.1u as=0.2915p ad=0.2915p ps=2.73u pd=2.73u
c9 a vss 0.610f
c8 b vss 0.677f
c6 c vss 0.603f
c5 d vss 0.638f
c1 z vss 0.948f
.ends
.subckt nand3 a b c vdd vss z
m01 vdd a z vdd pmos l=0.12u w=1.1u as=0.2915p ad=0.2915p ps=2.73u pd=2.73u
m02 vss a sig2 vss nmos l=0.12u w=1.1u as=0.2915p ad=0.2915p ps=2.73u pd=2.73u
m03 z b vdd vdd pmos l=0.12u w=1.1u as=0.2915p ad=0.2915p ps=2.73u pd=2.73u
m04 sig2 b sig3 vss nmos l=0.12u w=1.1u as=0.2915p ad=0.2915p ps=2.73u pd=2.73u
m05 vdd c z vdd pmos l=0.12u w=1.1u as=0.2915p ad=0.2915p ps=2.73u pd=2.73u
m06 sig3 c z vss nmos l=0.12u w=1.1u as=0.2915p ad=0.2915p ps=2.73u pd=2.73u
c5 a vss 0.491f
c6 b vss 0.400f
c7 c vss 0.478f
c1 z vss 0.850f
.ends
.subckt nand2 a b vdd vss z
m01 vdd a z vdd pmos l=0.12u w=0.77u as=0.20405p ad=0.20405p ps=2.07u pd=2.07u
m02 vss a sig3 vss nmos l=0.12u w=0.66u as=0.1749p ad=0.1749p ps=1.85u pd=1.85u
m03 z b vdd vdd pmos l=0.12u w=0.77u as=0.20405p ad=0.20405p ps=2.07u pd=2.07u
m04 sig3 b z vss nmos l=0.12u w=0.66u as=0.1749p ad=0.1749p ps=1.85u pd=1.85u
c4 a vss 0.549f
c5 b vss 0.578f
c1 z vss 0.609f
.ends
.subckt and2 a b vdd vss z
m01 06 a vdd vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m02 n1 a vss vss nmos l=0.12u w=0.605u as=0.160325p ad=0.160325p ps=1.74u pd=1.74u
m03 vdd b 06 vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m04 06 b n1 vss nmos l=0.12u w=0.605u as=0.160325p ad=0.160325p ps=1.74u pd=1.74u
m05 vdd 06 z vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m06 vss 06 z vss nmos l=0.12u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
c4 06 vss 0.724f
c5 a vss 0.663f
c6 b vss 0.538f
c3 z vss 0.595f
.ends
* simulation command:
.tran 1ps 1ns
.print tran V(g430) V(g426) V(g429) V(g431) V(g428) V(g427) V(g432)
.end

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,793 @@
* ISCAS85 benchmark circuit SPICE netlist
* generated by spicegen.pl 1.0
* by Jingye Xu @ VLSI group, Dept of ECE, UIC
.INCLUDE ../../technology/45nm_HP.pm
.OPTIONS GMIN=1e-015 ABSTOL=1e-13 ACCT
* the voltage souces:
Vdd vdd gnd DC 1.8
* the input voltage sources
V1 g21 gnd pulse(0 1 0p 200p 200p 1n 2n)
V2 g18 gnd pulse(0 1 0p 200p 200p 1n 2n)
V3 g31 gnd pulse(0 1 0p 200p 200p 1n 2n)
V4 g17 gnd pulse(0 1 0p 200p 200p 1n 2n)
V5 g27 gnd pulse(0 1 0p 200p 200p 1n 2n)
V6 g11 gnd pulse(0 1 0p 200p 200p 1n 2n)
V7 g22 gnd pulse(0 1 0p 200p 200p 1n 2n)
V8 g32 gnd pulse(0 1 0p 200p 200p 1n 2n)
V9 g30 gnd pulse(0 1 0p 200p 200p 1n 2n)
V10 g4 gnd pulse(0 1 0p 200p 200p 1n 2n)
V11 g12 gnd pulse(0 1 0p 200p 200p 1n 2n)
V12 g29 gnd pulse(0 1 0p 200p 200p 1n 2n)
V13 g24 gnd pulse(0 1 0p 200p 200p 1n 2n)
V14 g39 gnd pulse(0 1 0p 200p 200p 1n 2n)
V15 g38 gnd pulse(0 1 0p 200p 200p 1n 2n)
V16 g20 gnd pulse(0 1 0p 200p 200p 1n 2n)
V17 g5 gnd pulse(0 1 0p 200p 200p 1n 2n)
V18 g35 gnd pulse(0 1 0p 200p 200p 1n 2n)
V19 g23 gnd pulse(0 1 0p 200p 200p 1n 2n)
V20 g13 gnd pulse(0 1 0p 200p 200p 1n 2n)
V21 g2 gnd pulse(0 1 0p 200p 200p 1n 2n)
V22 g37 gnd pulse(0 1 0p 200p 200p 1n 2n)
V23 g41 gnd pulse(0 1 0p 200p 200p 1n 2n)
V24 g9 gnd pulse(0 1 0p 200p 200p 1n 2n)
V25 g40 gnd pulse(0 1 0p 200p 200p 1n 2n)
V26 g14 gnd pulse(0 1 0p 200p 200p 1n 2n)
V27 g36 gnd pulse(0 1 0p 200p 200p 1n 2n)
V28 g19 gnd pulse(0 1 0p 200p 200p 1n 2n)
V29 g8 gnd pulse(0 1 0p 200p 200p 1n 2n)
V30 g3 gnd pulse(0 1 0p 200p 200p 1n 2n)
V31 g26 gnd pulse(0 1 0p 200p 200p 1n 2n)
V32 g16 gnd pulse(0 1 0p 200p 200p 1n 2n)
V33 g10 gnd pulse(0 1 0p 200p 200p 1n 2n)
V34 g6 gnd pulse(0 1 0p 200p 200p 1n 2n)
V35 g1 gnd pulse(0 1 0p 200p 200p 1n 2n)
V36 g28 gnd pulse(0 1 0p 200p 200p 1n 2n)
V37 g25 gnd pulse(0 1 0p 200p 200p 1n 2n)
V38 g15 gnd pulse(0 1 0p 200p 200p 1n 2n)
V39 g33 gnd pulse(0 1 0p 200p 200p 1n 2n)
V40 g7 gnd pulse(0 1 0p 200p 200p 1n 2n)
V41 g34 gnd pulse(0 1 0p 200p 200p 1n 2n)
X101 g2 z172 vdd gnd x172 nand2
X366 g217 z325 vdd gnd x325 nand2
X615 g29 vdd gnd w496 not1
X467 g286 g426 vdd gnd g460 and2
X194 g156 vdd gnd w201 not1
X2 g2 vdd gnd z146 not1
X505 g7 vdd gnd w474 not1
X254 g192 vdd gnd w219 not1
X629 x498 y498 vdd gnd g498 nand2
X575 g21 vdd gnd w488 not1
X428 g356 g299 g357 vdd gnd x41 and3
X234 g180 vdd gnd w215 not1
X414 g361 g362 g312 g363 vdd gnd g383 and4
X285 g207 vdd gnd z225 not1
X130 g21 vdd gnd z178 not1
X144 g26 vdd gnd w181 not1
X591 g459 vdd gnd z491 not1
X159 g20 vdd gnd w184 not1
X120 g8 vdd gnd z176 not1
X31 g13 vdd gnd w152 not1
X554 x483 y483 vdd gnd g483 nand2
X314 g167 vdd gnd w231 not1
X189 g154 vdd gnd w198 not1
X578 g456 w488 vdd gnd y488 nand2
X518 g444 w476 vdd gnd y476 nand2
X471 g286 g431 vdd gnd g464 and2
X504 x473 y473 vdd gnd g473 nand2
X584 x489 y489 vdd gnd g489 nand2
X302 g224 w228 vdd gnd y228 nand2
X526 g446 vdd gnd z478 not1
X328 x233 y233 vdd gnd g233 nand2
X202 g159 w204 vdd gnd y204 nand2
X170 g147 vdd gnd z186 not1
X415 g364 g299 g365 g366 vdd gnd g384 and4
X597 g25 z492 vdd gnd x492 nand2
X61 g25 vdd gnd w158 not1
X377 g273 vdd gnd g346 not1
X439 x71 x72 vdd gnd g426 and2
X293 x226 y226 vdd gnd g226 nand2
X89 g1 vdd gnd w170 not1
X275 g207 vdd gnd z223 not1
X280 g204 vdd gnd z224 not1
X523 g445 w477 vdd gnd y477 nand2
X246 g184 z217 vdd gnd x217 nand2
X325 g221 vdd gnd z233 not1
X67 g28 vdd gnd z159 not1
X558 g452 w484 vdd gnd y484 nand2
X543 g449 w481 vdd gnd y481 nand2
X398 g299 vdd gnd g367 not1
X218 x211 y211 vdd gnd g211 nand2
X46 g19 vdd gnd w155 not1
X228 x213 y213 vdd gnd g213 nand2
X15 x148 y148 vdd gnd g148 nand2
X58 g23 z157 vdd gnd x157 nand2
X374 g273 vdd gnd g343 not1
X113 x174 y174 vdd gnd g174 nand2
X396 g312 vdd gnd g365 not1
X125 g16 vdd gnd z177 not1
X5 x146 y146 vdd gnd g146 nand2
X383 g299 vdd gnd g352 not1
X308 x229 y229 vdd gnd g229 nand2
X40 x153 y153 vdd gnd g153 nand2
X586 g458 vdd gnd z490 not1
X457 g260 g411 vdd gnd g450 and2
X260 g192 vdd gnd z220 not1
X214 g172 vdd gnd w211 not1
X79 g32 w161 vdd gnd y161 nand2
X182 g151 w192 vdd gnd y192 nand2
X139 g18 vdd gnd w180 not1
X420 g351 g386 vdd gnd x12 and2
X633 g467 w499 vdd gnd y499 nand2
X266 g189 z221 vdd gnd x221 nand2
X564 x485 y485 vdd gnd g485 nand2
X358 x299 y299 vdd gnd g299 nand2
X585 g23 vdd gnd w490 not1
X283 x224 y224 vdd gnd g224 nand2
X365 g233 vdd gnd z325 not1
X268 x221 y221 vdd gnd g221 nand2
X596 g460 vdd gnd z492 not1
X622 g30 z497 vdd gnd x497 nand2
X614 x495 y495 vdd gnd g495 nand2
X551 g451 vdd gnd z483 not1
X470 g325 g426 vdd gnd g463 and2
X185 g153 vdd gnd z195 not1
X44 g18 w154 vdd gnd y154 nand2
X86 g38 g41 vdd gnd g167 and2
X14 g6 w148 vdd gnd y148 nand2
X438 g375 g391 vdd gnd x72 and2
X73 g29 z160 vdd gnd x160 nand2
X30 x151 y151 vdd gnd g151 nand2
X94 g9 vdd gnd w171 not1
X62 g26 vdd gnd z158 not1
X417 g378 g379 g380 g381 vdd gnd g386 or4
X121 g4 z176 vdd gnd x176 nand2
X57 g24 vdd gnd z157 not1
X609 x494 y494 vdd gnd g494 nand2
X136 g25 z179 vdd gnd x179 nand2
X506 g442 vdd gnd z474 not1
X66 g27 vdd gnd w159 not1
X632 g32 z499 vdd gnd x499 nand2
X599 x492 y492 vdd gnd g492 nand2
X368 x325 y325 vdd gnd g325 nand2
X236 g180 z215 vdd gnd x215 nand2
X624 x497 y497 vdd gnd g497 nand2
X233 x214 y214 vdd gnd g214 nand2
X590 g24 vdd gnd w491 not1
X569 x486 y486 vdd gnd g486 nand2
X525 g11 vdd gnd w478 not1
X290 g222 vdd gnd z226 not1
X473 g312 g431 vdd gnd g466 and2
X95 g13 vdd gnd z171 not1
X503 g441 w473 vdd gnd y473 nand2
X480 g2 vdd gnd w469 not1
X442 x81 x82 vdd gnd g431 and2
X47 g20 vdd gnd z155 not1
X179 g150 vdd gnd w192 not1
X276 g204 z223 vdd gnd x223 nand2
X345 g229 vdd gnd z273 not1
X197 g157 w201 vdd gnd y201 nand2
X495 g5 vdd gnd w472 not1
X430 x41 x42 vdd gnd g411 and2
X153 x182 y182 vdd gnd g182 nand2
X81 g33 g41 vdd gnd g162 and2
X315 g219 vdd gnd z231 not1
X371 g260 vdd gnd g340 not1
X529 x478 y478 vdd gnd g478 nand2
X397 g325 vdd gnd g366 not1
X143 x180 y180 vdd gnd g180 nand2
X309 g166 vdd gnd w230 not1
X78 g31 z161 vdd gnd x161 nand2
X406 g273 vdd gnd g375 not1
X56 g23 vdd gnd w157 not1
X20 x149 y149 vdd gnd g149 nand2
X384 g312 vdd gnd g353 not1
X209 g170 vdd gnd w210 not1
X423 g325 g386 vdd gnd x22 and2
X100 g6 vdd gnd z172 not1
X510 g8 vdd gnd w475 not1
X464 g299 g421 vdd gnd g457 and2
X201 g158 z204 vdd gnd x204 nand2
X537 g13 z480 vdd gnd x480 nand2
X265 g195 vdd gnd z221 not1
X429 g325 g386 vdd gnd x42 and2
X245 g185 vdd gnd z217 not1
X603 g461 w493 vdd gnd y493 nand2
X517 g9 z476 vdd gnd x476 nand2
X138 x179 y179 vdd gnd g179 nand2
X27 g12 vdd gnd z151 not1
X577 g21 z488 vdd gnd x488 nand2
X301 g164 z228 vdd gnd x228 nand2
X114 g11 vdd gnd w175 not1
X122 g8 w176 vdd gnd y176 nand2
X102 g6 w172 vdd gnd y172 nand2
X494 x471 y471 vdd gnd g471 nand2
X4 g2 w146 vdd gnd y146 nand2
X219 g174 vdd gnd w212 not1
X296 g163 z227 vdd gnd x227 nand2
X230 g179 vdd gnd z214 not1
X213 x210 y210 vdd gnd g210 nand2
X400 g325 vdd gnd g369 not1
X200 g159 vdd gnd z204 not1
X108 x173 y173 vdd gnd g173 nand2
X444 g247 g396 vdd gnd g437 and2
X522 g10 z477 vdd gnd x477 nand2
X156 g27 z183 vdd gnd x183 nand2
X612 g28 z495 vdd gnd x495 nand2
X351 g214 z286 vdd gnd x286 nand2
X412 g234 g347 g348 g349 vdd gnd g381 and4
X132 g21 w178 vdd gnd y178 nand2
X631 g467 vdd gnd z499 not1
X437 g374 g247 g260 vdd gnd x71 and3
X180 g151 vdd gnd z192 not1
X141 g18 z180 vdd gnd x180 nand2
X41 g17 vdd gnd w154 not1
X618 g464 w496 vdd gnd y496 nand2
X278 x223 y223 vdd gnd g223 nand2
X295 g223 vdd gnd z227 not1
X13 g5 z148 vdd gnd x148 nand2
X37 g16 vdd gnd z153 not1
X382 g325 vdd gnd g351 not1
X252 g189 w218 vdd gnd y218 nand2
X552 g16 z483 vdd gnd x483 nand2
X240 g183 vdd gnd z216 not1
X107 g14 w173 vdd gnd y173 nand2
X608 g462 w494 vdd gnd y494 nand2
X481 g437 vdd gnd z469 not1
X544 x481 y481 vdd gnd g481 nand2
X164 g28 vdd gnd w185 not1
X60 x157 y157 vdd gnd g157 nand2
X247 g185 w217 vdd gnd y217 nand2
X469 g312 g426 vdd gnd g462 and2
X524 x477 y477 vdd gnd g477 nand2
X49 g20 w155 vdd gnd y155 nand2
X264 g189 vdd gnd w221 not1
X443 g234 g396 vdd gnd g436 and2
X241 g182 z216 vdd gnd x216 nand2
X279 g198 vdd gnd w224 not1
X375 g234 vdd gnd g344 not1
X326 g169 z233 vdd gnd x233 nand2
X39 g16 w153 vdd gnd y153 nand2
X116 g11 z175 vdd gnd x175 nand2
X225 g177 vdd gnd z213 not1
X566 g454 vdd gnd z486 not1
X172 g147 w186 vdd gnd y186 nand2
X426 g355 g386 vdd gnd x32 and2
X93 x170 y170 vdd gnd g170 nand2
X465 g312 g421 vdd gnd g458 and2
X344 g213 vdd gnd w273 not1
X29 g12 w151 vdd gnd y151 nand2
X9 g4 w147 vdd gnd y147 nand2
X157 g31 w183 vdd gnd y183 nand2
X323 x232 y232 vdd gnd g232 nand2
X284 g201 vdd gnd w225 not1
X300 g224 vdd gnd z228 not1
X546 g450 vdd gnd z482 not1
X74 g30 w160 vdd gnd y160 nand2
X594 x491 y491 vdd gnd g491 nand2
X488 g438 w470 vdd gnd y470 nand2
X574 x487 y487 vdd gnd g487 nand2
X316 g167 z231 vdd gnd x231 nand2
X472 g299 g431 vdd gnd g465 and2
X51 g21 vdd gnd w156 not1
X557 g17 z484 vdd gnd x484 nand2
X69 g28 w159 vdd gnd y159 nand2
X408 g260 vdd gnd g377 not1
X634 x499 y499 vdd gnd g499 nand2
X208 x207 y207 vdd gnd g207 nand2
X431 g234 g370 g260 vdd gnd x51 and3
X154 g27 vdd gnd w183 not1
X390 g299 vdd gnd g359 not1
X493 g439 w471 vdd gnd y471 nand2
X332 g226 w234 vdd gnd y234 nand2
X210 g171 vdd gnd z210 not1
X381 g299 vdd gnd g350 not1
X256 g192 z219 vdd gnd x219 nand2
X177 g149 w189 vdd gnd y189 nand2
X387 g286 vdd gnd g356 not1
X196 g156 z201 vdd gnd x201 nand2
X576 g456 vdd gnd z488 not1
X498 g440 w472 vdd gnd y472 nand2
X621 g465 vdd gnd z497 not1
X287 g207 w225 vdd gnd y225 nand2
X59 g24 w157 vdd gnd y157 nand2
X451 g234 g406 vdd gnd g444 and2
X625 g31 vdd gnd w498 not1
X579 x488 y488 vdd gnd g488 nand2
X450 g273 g401 vdd gnd g443 and2
X68 g27 z159 vdd gnd x159 nand2
X92 g5 w170 vdd gnd y170 nand2
X131 g17 z178 vdd gnd x178 nand2
X401 g247 vdd gnd g370 not1
X422 g286 g352 g353 vdd gnd x21 and3
X445 g260 g396 vdd gnd g438 and2
X337 g227 w247 vdd gnd y247 nand2
X616 g464 vdd gnd z496 not1
X255 g195 vdd gnd z219 not1
X352 g230 w286 vdd gnd y286 nand2
X342 g228 w260 vdd gnd y260 nand2
X48 g19 z155 vdd gnd x155 nand2
X475 g1 vdd gnd w468 not1
X212 g171 w210 vdd gnd y210 nand2
X38 g15 z153 vdd gnd x153 nand2
X75 x160 y160 vdd gnd g160 nand2
X363 x312 y312 vdd gnd g312 nand2
X21 g9 vdd gnd w150 not1
X8 g3 z147 vdd gnd x147 nand2
X80 x161 y161 vdd gnd g161 nand2
X3 g1 z146 vdd gnd x146 nand2
X292 g222 w226 vdd gnd y226 nand2
X198 x201 y201 vdd gnd g201 nand2
X12 g6 vdd gnd z148 not1
X413 g358 g359 g360 g325 vdd gnd g382 and4
X373 g247 vdd gnd g342 not1
X253 x218 y218 vdd gnd g218 nand2
X360 g232 vdd gnd z312 not1
X391 g312 vdd gnd g360 not1
X123 x176 y176 vdd gnd g176 nand2
X183 x192 y192 vdd gnd g192 nand2
X188 x195 y195 vdd gnd g195 nand2
X330 g226 vdd gnd z234 not1
X399 g312 vdd gnd g368 not1
X617 g29 z496 vdd gnd x496 nand2
X378 g247 vdd gnd g347 not1
X462 g325 g416 vdd gnd g455 and2
X339 g212 vdd gnd w260 not1
X545 g15 vdd gnd w482 not1
X281 g198 z224 vdd gnd x224 nand2
X211 g170 z210 vdd gnd x210 nand2
X171 g146 z186 vdd gnd x186 nand2
X409 g338 g339 g340 g273 vdd gnd g378 and4
X191 g154 z198 vdd gnd x198 nand2
X150 g23 vdd gnd z182 not1
X427 x31 x32 vdd gnd g406 and2
X514 x475 y475 vdd gnd g475 nand2
X468 g299 g426 vdd gnd g461 and2
X317 g219 w231 vdd gnd y231 nand2
X88 g40 g41 vdd gnd g169 and2
X235 g181 vdd gnd z215 not1
X207 g161 w207 vdd gnd y207 nand2
X343 x260 y260 vdd gnd g260 nand2
X124 g12 vdd gnd w177 not1
X178 x189 y189 vdd gnd g189 nand2
X519 x476 y476 vdd gnd g476 nand2
X482 g2 z469 vdd gnd x469 nand2
X226 g176 z213 vdd gnd x213 nand2
X306 g165 z229 vdd gnd x229 nand2
X238 x215 y215 vdd gnd g215 nand2
X565 g19 vdd gnd w486 not1
X263 x220 y220 vdd gnd g220 nand2
X158 x183 y183 vdd gnd g183 nand2
X319 g168 vdd gnd w232 not1
X36 g15 vdd gnd w153 not1
X436 x61 x62 vdd gnd g421 and2
X489 x470 y470 vdd gnd g470 nand2
X199 g158 vdd gnd w204 not1
X388 g312 vdd gnd g357 not1
X410 g341 g342 g260 g343 vdd gnd g379 and4
X605 g27 vdd gnd w494 not1
X338 x247 y247 vdd gnd g247 nand2
X261 g186 z220 vdd gnd x220 nand2
X35 x152 y152 vdd gnd g152 nand2
X215 g173 vdd gnd z211 not1
X322 g220 w232 vdd gnd y232 nand2
X453 g260 g406 vdd gnd g446 and2
X96 g9 z171 vdd gnd x171 nand2
X600 g26 vdd gnd w493 not1
X446 g273 g396 vdd gnd g439 and2
X70 x159 y159 vdd gnd g159 nand2
X500 g6 vdd gnd w473 not1
X535 g13 vdd gnd w480 not1
X589 x490 y490 vdd gnd g490 nand2
X324 g169 vdd gnd w233 not1
X369 g234 vdd gnd g338 not1
X626 g466 vdd gnd z498 not1
X492 g4 z471 vdd gnd x471 nand2
X299 g164 vdd gnd w228 not1
X559 x484 y484 vdd gnd g484 nand2
X539 x480 y480 vdd gnd g480 nand2
X389 g286 vdd gnd g358 not1
X305 g225 vdd gnd z229 not1
X611 g463 vdd gnd z495 not1
X1 g1 vdd gnd w146 not1
X105 g14 vdd gnd z173 not1
X353 x286 y286 vdd gnd g286 nand2
X206 g160 z207 vdd gnd x207 nand2
X229 g178 vdd gnd w214 not1
X572 g20 z487 vdd gnd x487 nand2
X509 x474 y474 vdd gnd g474 nand2
X186 g152 z195 vdd gnd x195 nand2
X549 x482 y482 vdd gnd g482 nand2
X163 x184 y184 vdd gnd g184 nand2
X392 g286 vdd gnd g361 not1
X531 g447 vdd gnd z479 not1
X329 g210 vdd gnd w234 not1
X402 g273 vdd gnd g371 not1
X483 g437 w469 vdd gnd y469 nand2
X269 g198 vdd gnd w222 not1
X628 g466 w498 vdd gnd y498 nand2
X117 g15 w175 vdd gnd y175 nand2
X341 g212 z260 vdd gnd x260 nand2
X592 g24 z491 vdd gnd x491 nand2
X223 x212 y212 vdd gnd g212 nand2
X129 g17 vdd gnd w178 not1
X550 g16 vdd gnd w483 not1
X76 g31 vdd gnd w161 not1
X23 g9 z150 vdd gnd x150 nand2
X271 g198 z222 vdd gnd x222 nand2
X311 g166 z230 vdd gnd x230 nand2
X555 g17 vdd gnd w484 not1
X82 g34 g41 vdd gnd g163 and2
X259 g186 vdd gnd w220 not1
X289 g162 vdd gnd w226 not1
X441 g273 g391 vdd gnd x82 and2
X165 g32 vdd gnd z185 not1
X318 x231 y231 vdd gnd g231 nand2
X42 g18 vdd gnd z154 not1
X155 g31 vdd gnd z183 not1
X243 x216 y216 vdd gnd g216 nand2
X435 g273 g391 vdd gnd x62 and2
X133 x178 y178 vdd gnd g178 nand2
X619 x496 y496 vdd gnd g496 nand2
X91 g1 z170 vdd gnd x170 nand2
X258 x219 y219 vdd gnd g219 nand2
X474 g325 g431 vdd gnd g467 and2
X237 g181 w215 vdd gnd y215 nand2
X347 g229 w273 vdd gnd y273 nand2
X548 g450 w482 vdd gnd y482 nand2
X567 g19 z486 vdd gnd x486 nand2
X174 g148 vdd gnd w189 not1
X424 x21 x22 vdd gnd g401 and2
X606 g462 vdd gnd z494 not1
X491 g439 vdd gnd z471 not1
X115 g15 vdd gnd z175 not1
X10 x147 y147 vdd gnd g147 nand2
X582 g22 z489 vdd gnd x489 nand2
X521 g445 vdd gnd z477 not1
X181 g150 z192 vdd gnd x192 nand2
X257 g195 w219 vdd gnd y219 nand2
X34 g14 w152 vdd gnd y152 nand2
X77 g32 vdd gnd z161 not1
X249 g186 vdd gnd w218 not1
X540 g14 vdd gnd w481 not1
X33 g13 z152 vdd gnd x152 nand2
X128 x177 y177 vdd gnd g177 nand2
X610 g28 vdd gnd w495 not1
X166 g28 z185 vdd gnd x185 nand2
X248 x217 y217 vdd gnd g217 nand2
X562 g18 z485 vdd gnd x485 nand2
X142 g22 w180 vdd gnd y180 nand2
X168 x185 y185 vdd gnd g185 nand2
X224 g176 vdd gnd w213 not1
X277 g207 w223 vdd gnd y223 nand2
X106 g10 z173 vdd gnd x173 nand2
X118 x175 y175 vdd gnd g175 nand2
X354 g215 vdd gnd w299 not1
X149 g19 vdd gnd w182 not1
X90 g5 vdd gnd z170 not1
X335 g227 vdd gnd z247 not1
X376 g260 vdd gnd g345 not1
X623 g465 w497 vdd gnd y497 nand2
X393 g299 vdd gnd g362 not1
X251 g186 z218 vdd gnd x218 nand2
X570 g20 vdd gnd w487 not1
X530 g12 vdd gnd w479 not1
X607 g27 z494 vdd gnd x494 nand2
X83 g35 g41 vdd gnd g164 and2
X463 g286 g421 vdd gnd g456 and2
X321 g168 z232 vdd gnd x232 nand2
X270 g201 vdd gnd z222 not1
X286 g201 z225 vdd gnd x225 nand2
X547 g15 z482 vdd gnd x482 nand2
X458 g273 g411 vdd gnd g451 and2
X22 g10 vdd gnd z150 not1
X147 g30 w181 vdd gnd y181 nand2
X340 g228 vdd gnd z260 not1
X43 g17 z154 vdd gnd x154 nand2
X418 g382 g383 g384 g385 vdd gnd g391 or4
X310 g218 vdd gnd z230 not1
X459 g286 g416 vdd gnd g452 and2
X411 g344 g247 g345 g346 vdd gnd g380 and4
X193 x198 y198 vdd gnd g198 nand2
X380 g273 vdd gnd g349 not1
X242 g183 w216 vdd gnd y216 nand2
X111 g3 z174 vdd gnd x174 nand2
X513 g443 w475 vdd gnd y475 nand2
X477 g1 z468 vdd gnd x468 nand2
X28 g11 z151 vdd gnd x151 nand2
X536 g448 vdd gnd z480 not1
X573 g455 w487 vdd gnd y487 nand2
X50 x155 y155 vdd gnd g155 nand2
X152 g23 w182 vdd gnd y182 nand2
X568 g454 w486 vdd gnd y486 nand2
X499 x472 y472 vdd gnd g472 nand2
X440 g376 g247 g377 vdd gnd x81 and3
X205 g161 vdd gnd z207 not1
X294 g163 vdd gnd w227 not1
X52 g22 vdd gnd z156 not1
X173 x186 y186 vdd gnd g186 nand2
X272 g201 w222 vdd gnd y222 nand2
X452 g247 g406 vdd gnd g445 and2
X476 g436 vdd gnd z468 not1
X484 x469 y469 vdd gnd g469 nand2
X447 g234 g401 vdd gnd g440 and2
X448 g247 g401 vdd gnd g441 and2
X331 g210 z234 vdd gnd x234 nand2
X348 x273 y273 vdd gnd g273 nand2
X627 g31 z498 vdd gnd x498 nand2
X595 g25 vdd gnd w492 not1
X520 g10 vdd gnd w477 not1
X162 g24 w184 vdd gnd y184 nand2
X355 g231 vdd gnd z299 not1
X364 g217 vdd gnd w325 not1
X403 g247 vdd gnd g372 not1
X385 g286 vdd gnd g354 not1
X320 g220 vdd gnd z232 not1
X87 g39 g41 vdd gnd g168 and2
X356 g215 z299 vdd gnd x299 nand2
X184 g152 vdd gnd w195 not1
X507 g7 z474 vdd gnd x474 nand2
X359 g216 vdd gnd w312 not1
X135 g29 vdd gnd z179 not1
X63 g25 z158 vdd gnd x158 nand2
X282 g204 w224 vdd gnd y224 nand2
X333 x234 y234 vdd gnd g234 nand2
X291 g162 z226 vdd gnd x226 nand2
X167 g32 w185 vdd gnd y185 nand2
X563 g453 w485 vdd gnd y485 nand2
X455 g234 g411 vdd gnd g448 and2
X556 g452 vdd gnd z484 not1
X460 g299 g416 vdd gnd g453 and2
X103 x172 y172 vdd gnd g172 nand2
X593 g459 w491 vdd gnd y491 nand2
X239 g182 vdd gnd w216 not1
X434 g234 g372 g373 vdd gnd x61 and3
X145 g30 vdd gnd z181 not1
X16 g7 vdd gnd w149 not1
X602 g26 z493 vdd gnd x493 nand2
X598 g460 w492 vdd gnd y492 nand2
X312 g218 w230 vdd gnd y230 nand2
X487 g3 z470 vdd gnd x470 nand2
X583 g457 w489 vdd gnd y489 nand2
X497 g5 z472 vdd gnd x472 nand2
X65 x158 y158 vdd gnd g158 nand2
X407 g234 vdd gnd g376 not1
X425 g354 g299 g312 vdd gnd x31 and3
X127 g16 w177 vdd gnd y177 nand2
X72 g30 vdd gnd z160 not1
X404 g260 vdd gnd g373 not1
X288 x225 y225 vdd gnd g225 nand2
X386 g325 vdd gnd g355 not1
X516 g444 vdd gnd z476 not1
X533 g447 w479 vdd gnd y479 nand2
X112 g7 w174 vdd gnd y174 nand2
X303 x228 y228 vdd gnd g228 nand2
X541 g449 vdd gnd z481 not1
X304 g165 vdd gnd w229 not1
X313 x230 y230 vdd gnd g230 nand2
X137 g29 w179 vdd gnd y179 nand2
X588 g458 w490 vdd gnd y490 nand2
X327 g221 w233 vdd gnd y233 nand2
X532 g12 z479 vdd gnd x479 nand2
X478 g436 w468 vdd gnd y468 nand2
X146 g26 z181 vdd gnd x181 nand2
X511 g443 vdd gnd z475 not1
X55 x156 y156 vdd gnd g156 nand2
X25 x150 y150 vdd gnd g150 nand2
X84 g36 g41 vdd gnd g165 and2
X19 g8 w149 vdd gnd y149 nand2
X367 g233 w325 vdd gnd y325 nand2
X273 x222 y222 vdd gnd g222 nand2
X372 g234 vdd gnd g341 not1
X394 g325 vdd gnd g363 not1
X349 g214 vdd gnd w286 not1
X161 g20 z184 vdd gnd x184 nand2
X490 g4 vdd gnd w471 not1
X528 g446 w478 vdd gnd y478 nand2
X538 g448 w480 vdd gnd y480 nand2
X160 g24 vdd gnd z184 not1
X190 g155 vdd gnd z198 not1
X449 g260 g401 vdd gnd g442 and2
X336 g211 z247 vdd gnd x247 nand2
X297 g223 w227 vdd gnd y227 nand2
X613 g463 w495 vdd gnd y495 nand2
X502 g6 z473 vdd gnd x473 nand2
X553 g451 w483 vdd gnd y483 nand2
X7 g4 vdd gnd z147 not1
X560 g18 vdd gnd w485 not1
X216 g172 z211 vdd gnd x211 nand2
X176 g148 z189 vdd gnd x189 nand2
X98 x171 y171 vdd gnd g171 nand2
X204 g160 vdd gnd w207 not1
X221 g174 z212 vdd gnd x212 nand2
X232 g179 w214 vdd gnd y214 nand2
X604 x493 y493 vdd gnd g493 nand2
X26 g11 vdd gnd w151 not1
X54 g22 w156 vdd gnd y156 nand2
X244 g184 vdd gnd w217 not1
X262 g192 w220 vdd gnd y220 nand2
X18 g7 z149 vdd gnd x149 nand2
X419 g286 g350 g312 vdd gnd x11 and3
X298 x227 y227 vdd gnd g227 nand2
X461 g312 g416 vdd gnd g454 and2
X126 g12 z177 vdd gnd x177 nand2
X203 x204 y204 vdd gnd g204 nand2
X433 x51 x52 vdd gnd g416 and2
X220 g175 vdd gnd z212 not1
X110 g7 vdd gnd z174 not1
X362 g232 w312 vdd gnd y312 nand2
X379 g260 vdd gnd g348 not1
X53 g21 z156 vdd gnd x156 nand2
X346 g213 z273 vdd gnd x273 nand2
X496 g440 vdd gnd z472 not1
X501 g441 vdd gnd z473 not1
X134 g25 vdd gnd w179 not1
X17 g8 vdd gnd z149 not1
X587 g23 z490 vdd gnd x490 nand2
X187 g153 w195 vdd gnd y195 nand2
X334 g211 vdd gnd w247 not1
X485 g3 vdd gnd w470 not1
X6 g3 vdd gnd w147 not1
X64 g26 w158 vdd gnd y158 nand2
X109 g3 vdd gnd w174 not1
X97 g13 w171 vdd gnd y171 nand2
X32 g14 vdd gnd z152 not1
X192 g155 w198 vdd gnd y198 nand2
X405 g234 vdd gnd g374 not1
X71 g29 vdd gnd w160 not1
X140 g22 vdd gnd z180 not1
X148 x181 y181 vdd gnd g181 nand2
X274 g204 vdd gnd w223 not1
X222 g175 w212 vdd gnd y212 nand2
X534 x479 y479 vdd gnd g479 nand2
X466 g325 g421 vdd gnd g459 and2
X620 g30 vdd gnd w497 not1
X432 g371 g391 vdd gnd x52 and2
X24 g10 w150 vdd gnd y150 nand2
X515 g9 vdd gnd w476 not1
X151 g19 z182 vdd gnd x182 nand2
X227 g177 w213 vdd gnd y213 nand2
X486 g438 vdd gnd z470 not1
X85 g37 g41 vdd gnd g166 and2
X267 g195 w221 vdd gnd y221 nand2
X581 g457 vdd gnd z489 not1
X370 g247 vdd gnd g339 not1
X169 g146 vdd gnd w186 not1
X11 g5 vdd gnd w148 not1
X350 g230 vdd gnd z286 not1
X456 g247 g411 vdd gnd g449 and2
X217 g173 w211 vdd gnd y211 nand2
X307 g225 w229 vdd gnd y229 nand2
X542 g14 z481 vdd gnd x481 nand2
X580 g22 vdd gnd w489 not1
X527 g11 z478 vdd gnd x478 nand2
X250 g189 vdd gnd z218 not1
X601 g461 vdd gnd z493 not1
X195 g157 vdd gnd z201 not1
X421 x11 x12 vdd gnd g396 and2
X357 g231 w299 vdd gnd y299 nand2
X571 g455 vdd gnd z487 not1
X119 g4 vdd gnd w176 not1
X99 g2 vdd gnd w172 not1
X45 x154 y154 vdd gnd g154 nand2
X454 g273 g406 vdd gnd g447 and2
X630 g32 vdd gnd w499 not1
X508 g442 w474 vdd gnd y474 nand2
X512 g8 z475 vdd gnd x475 nand2
X231 g178 z214 vdd gnd x214 nand2
X175 g149 vdd gnd z189 not1
X479 x468 y468 vdd gnd g468 nand2
X395 g286 vdd gnd g364 not1
X104 g10 vdd gnd w173 not1
X416 g286 g367 g368 g369 vdd gnd g385 and4
X361 g216 z312 vdd gnd x312 nand2
X561 g453 vdd gnd z485 not1
.subckt and3 a b c vdd vss z
m01 08 a vdd vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m02 n1 a vss vss nmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m03 vdd b 08 vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m04 sig6 b n1 vss nmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m05 08 c vdd vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m06 08 c sig6 vss nmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m07 vdd 08 z vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m08 vss 08 z vss nmos l=0.12u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
c4 08 vss 1.142f
c5 a vss 0.539f
c7 b vss 0.609f
c8 c vss 0.651f
c3 z vss 0.745f
.ends
.subckt or4 a b c d vdd vss z
m01 sig8 a vdd vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m02 vdd a 05 vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m03 sig1 a vss vss nmos l=0.12u w=0.33u as=0.08745p ad=0.08745p ps=1.19u pd=1.19u
m04 n2 b sig8 vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m05 05 b 08 vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m06 vss b sig1 vss nmos l=0.12u w=0.33u as=0.08745p ad=0.08745p ps=1.19u pd=1.19u
m07 10 c n2 vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m08 08 c 11 vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m09 sig1 c vss vss nmos l=0.12u w=0.33u as=0.08745p ad=0.08745p ps=1.19u pd=1.19u
m10 sig1 d 10 vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m11 11 d sig1 vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m12 vss d sig1 vss nmos l=0.12u w=0.33u as=0.08745p ad=0.08745p ps=1.19u pd=1.19u
m13 vdd sig1 z vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m14 vss sig1 z vss nmos l=0.12u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
c4 a vss 1.356f
c5 b vss 1.229f
c6 c vss 1.043f
c7 d vss 0.797f
c1 sig1 vss 1.003f
c3 z vss 0.701f
.ends
.subckt xnr2v0x1 a b vdd vss z
m01 z b sig3 vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m02 bn sig3 z vss nmos l=0.12u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
m03 sig3 a vdd vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m04 vdd b bn vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m05 z bn sig3 vss nmos l=0.12u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
m06 vdd sig3 n1 vdd pmos l=0.12u w=1.54u as=0.4081p ad=0.4081p ps=3.61u pd=3.61u
m07 sig3 a vss vss nmos l=0.12u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
m08 n1 bn z vdd pmos l=0.12u w=1.54u as=0.4081p ad=0.4081p ps=3.61u pd=3.61u
m09 vss b bn vss nmos l=0.12u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
c4 a vss 0.389f
c2 bn vss 1.593f
c5 b vss 0.840f
c3 sig3 vss 0.618f
c6 z vss 0.627f
.ends
.subckt nand2 a b vdd vss z
m01 vdd a z vdd pmos l=0.12u w=0.77u as=0.20405p ad=0.20405p ps=2.07u pd=2.07u
m02 vss a sig3 vss nmos l=0.12u w=0.66u as=0.1749p ad=0.1749p ps=1.85u pd=1.85u
m03 z b vdd vdd pmos l=0.12u w=0.77u as=0.20405p ad=0.20405p ps=2.07u pd=2.07u
m04 sig3 b z vss nmos l=0.12u w=0.66u as=0.1749p ad=0.1749p ps=1.85u pd=1.85u
c4 a vss 0.549f
c5 b vss 0.578f
c1 z vss 0.609f
.ends
.subckt and4 a b c d vdd vss z
m01 10 a vdd vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m02 n1 a vss vss nmos l=0.12u w=0.88u as=0.2332p ad=0.2332p ps=2.29u pd=2.29u
m03 vdd b 10 vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m04 sig7 b n1 vss nmos l=0.12u w=0.88u as=0.2332p ad=0.2332p ps=2.29u pd=2.29u
m05 10 c vdd vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m06 n3 c sig7 vss nmos l=0.12u w=0.88u as=0.2332p ad=0.2332p ps=2.29u pd=2.29u
m07 vdd d 10 vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m08 10 d n3 vss nmos l=0.12u w=0.88u as=0.2332p ad=0.2332p ps=2.29u pd=2.29u
m09 vdd 10 z vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m10 vss 10 z vss nmos l=0.12u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
c4 10 vss 0.940f
c5 a vss 0.674f
c8 b vss 0.541f
c9 c vss 0.622f
c10 d vss 0.791f
c3 z vss 0.765f
.ends
.subckt and2 a b vdd vss z
m01 06 a vdd vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m02 n1 a vss vss nmos l=0.12u w=0.605u as=0.160325p ad=0.160325p ps=1.74u pd=1.74u
m03 vdd b 06 vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m04 06 b n1 vss nmos l=0.12u w=0.605u as=0.160325p ad=0.160325p ps=1.74u pd=1.74u
m05 vdd 06 z vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m06 vss 06 z vss nmos l=0.12u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
c4 06 vss 0.724f
c5 a vss 0.663f
c6 b vss 0.538f
c3 z vss 0.595f
.ends
.subckt not1 a vdd vss z
m01 vdd a z vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m02 vss a z vss nmos l=0.12u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
c3 a vss 0.384f
c2 z vss 0.576f
.ends
* simulation command:
.tran 1ps 1ns
.print tran V(g470) V(g483) V(g493) V(g496) V(g494) V(g484) V(g476) V(g495) V(g471) V(g489) V(g468) V(g477) V(g488) V(g478) V(g490) V(g469) V(g487) V(g491) V(g479) V(g486) V(g497) V(g498) V(g473) V(g492) V(g472) V(g485) V(g480) V(g474) V(g481) V(g475) V(g482) V(g499)
.end

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,553 @@
* ISCAS85 benchmark circuit SPICE netlist
* generated by spicegen.pl 1.0
* by Jingye Xu @ VLSI group, Dept of ECE, UIC
.INCLUDE ../../technology/45nm_HP.pm
.OPTIONS GMIN=1e-015 ABSTOL=1e-13 ACCT
* the voltage souces:
Vdd vdd gnd DC 1.8
* the input voltage sources
V1 g44 gnd pulse(0 1 0p 200p 200p 1n 2n)
V2 g57 gnd pulse(0 1 0p 200p 200p 1n 2n)
V3 g35 gnd pulse(0 1 0p 200p 200p 1n 2n)
V4 g21 gnd pulse(0 1 0p 200p 200p 1n 2n)
V5 g18 gnd pulse(0 1 0p 200p 200p 1n 2n)
V6 g23 gnd pulse(0 1 0p 200p 200p 1n 2n)
V7 g13 gnd pulse(0 1 0p 200p 200p 1n 2n)
V8 g53 gnd pulse(0 1 0p 200p 200p 1n 2n)
V9 g41 gnd pulse(0 1 0p 200p 200p 1n 2n)
V10 g37 gnd pulse(0 1 0p 200p 200p 1n 2n)
V11 g2 gnd pulse(0 1 0p 200p 200p 1n 2n)
V12 g31 gnd pulse(0 1 0p 200p 200p 1n 2n)
V13 g9 gnd pulse(0 1 0p 200p 200p 1n 2n)
V14 g17 gnd pulse(0 1 0p 200p 200p 1n 2n)
V15 g27 gnd pulse(0 1 0p 200p 200p 1n 2n)
V16 g60 gnd pulse(0 1 0p 200p 200p 1n 2n)
V17 g40 gnd pulse(0 1 0p 200p 200p 1n 2n)
V18 g14 gnd pulse(0 1 0p 200p 200p 1n 2n)
V19 g47 gnd pulse(0 1 0p 200p 200p 1n 2n)
V20 g36 gnd pulse(0 1 0p 200p 200p 1n 2n)
V21 g46 gnd pulse(0 1 0p 200p 200p 1n 2n)
V22 g19 gnd pulse(0 1 0p 200p 200p 1n 2n)
V23 g58 gnd pulse(0 1 0p 200p 200p 1n 2n)
V24 g8 gnd pulse(0 1 0p 200p 200p 1n 2n)
V25 g3 gnd pulse(0 1 0p 200p 200p 1n 2n)
V26 g26 gnd pulse(0 1 0p 200p 200p 1n 2n)
V27 g59 gnd pulse(0 1 0p 200p 200p 1n 2n)
V28 g54 gnd pulse(0 1 0p 200p 200p 1n 2n)
V29 g16 gnd pulse(0 1 0p 200p 200p 1n 2n)
V30 g11 gnd pulse(0 1 0p 200p 200p 1n 2n)
V31 g22 gnd pulse(0 1 0p 200p 200p 1n 2n)
V32 g32 gnd pulse(0 1 0p 200p 200p 1n 2n)
V33 g50 gnd pulse(0 1 0p 200p 200p 1n 2n)
V34 g30 gnd pulse(0 1 0p 200p 200p 1n 2n)
V35 g10 gnd pulse(0 1 0p 200p 200p 1n 2n)
V36 g45 gnd pulse(0 1 0p 200p 200p 1n 2n)
V37 g6 gnd pulse(0 1 0p 200p 200p 1n 2n)
V38 g1 gnd pulse(0 1 0p 200p 200p 1n 2n)
V39 g48 gnd pulse(0 1 0p 200p 200p 1n 2n)
V40 g28 gnd pulse(0 1 0p 200p 200p 1n 2n)
V41 g55 gnd pulse(0 1 0p 200p 200p 1n 2n)
V42 g42 gnd pulse(0 1 0p 200p 200p 1n 2n)
V43 g51 gnd pulse(0 1 0p 200p 200p 1n 2n)
V44 g25 gnd pulse(0 1 0p 200p 200p 1n 2n)
V45 g4 gnd pulse(0 1 0p 200p 200p 1n 2n)
V46 g15 gnd pulse(0 1 0p 200p 200p 1n 2n)
V47 g12 gnd pulse(0 1 0p 200p 200p 1n 2n)
V48 g29 gnd pulse(0 1 0p 200p 200p 1n 2n)
V49 g33 gnd pulse(0 1 0p 200p 200p 1n 2n)
V50 g7 gnd pulse(0 1 0p 200p 200p 1n 2n)
V51 g49 gnd pulse(0 1 0p 200p 200p 1n 2n)
V52 g24 gnd pulse(0 1 0p 200p 200p 1n 2n)
V53 g39 gnd pulse(0 1 0p 200p 200p 1n 2n)
V54 g56 gnd pulse(0 1 0p 200p 200p 1n 2n)
V55 g52 gnd pulse(0 1 0p 200p 200p 1n 2n)
V56 g34 gnd pulse(0 1 0p 200p 200p 1n 2n)
V57 g38 gnd pulse(0 1 0p 200p 200p 1n 2n)
V58 g20 gnd pulse(0 1 0p 200p 200p 1n 2n)
V59 g5 gnd pulse(0 1 0p 200p 200p 1n 2n)
V60 g43 gnd pulse(0 1 0p 200p 200p 1n 2n)
X338 g51 g827 vdd gnd g835 and2
X101 g400 g401 vdd gnd g415 and2
X366 g354 vdd gnd g863 not1
X261 g52 g702 vdd gnd g739 and2
X194 g54 g542 vdd gnd g590 and2
X322 g51 g808 vdd gnd g819 and2
X215 g575 vdd gnd g647 not1
X35 g4 g8 vdd gnd g323 and2
X2 g1 g5 g3 g4 vdd gnd g270 nand4
X96 g382 vdd gnd g410 not1
X70 g303 g304 vdd gnd g360 nand2
X254 g682 vdd gnd g732 not1
X234 g629 g626 vdd gnd g702 and2
X285 g744 g745 vdd gnd g770 nor2
X130 g32 g445 vdd gnd g484 or2
X324 g810 g764 g697 g512 vdd gnd g821 nand4
X369 g395 vdd gnd g866 not1
X144 g29 g451 vdd gnd g498 and2
X159 g436 g47 vdd gnd g513 nand2
X120 g39 g417 vdd gnd g466 and2
X31 g4 g34 vdd gnd g317 and2
X299 g677 g779 vdd gnd g789 nor2
X314 g338 g793 vdd gnd g811 nor2
X189 g538 g41 vdd gnd g575 nand2
X305 g604 g779 vdd gnd g795 nand2
X302 g51 g786 vdd gnd g792 and2
X328 g813 g814 vdd gnd g825 nor2
X202 g554 g45 vdd gnd g613 or2
X170 g501 g502 vdd gnd g528 nor2
X1 g1 g2 g3 g4 vdd gnd g269 nand4
X61 g280 g285 vdd gnd g349 or2
X353 g846 vdd gnd g850 not1
X105 g389 g287 g10 vdd gnd g427 nand3
X377 g838 vdd gnd g874 not1
X229 g616 g511 vdd gnd g689 nor2
X206 g54 g558 vdd gnd g625 and2
X186 g529 g532 vdd gnd g572 and2
X293 g613 g756 vdd gnd g778 nand2
X89 g363 vdd gnd g403 not1
X275 g724 g725 vdd gnd g753 nor2
X163 g309 g487 vdd gnd g521 nor2
X280 g738 g746 g718 vdd gnd g761 nand3
X329 g815 g816 vdd gnd g826 nor2
X269 g620 g698 vdd gnd g747 nand2
X246 g52 g658 vdd gnd g724 and2
X117 g310 g422 vdd gnd g463 and2
X325 g811 g768 g706 g513 vdd gnd g822 nand4
X67 g22 g298 vdd gnd g355 nand2
X341 g830 vdd gnd g838 not1
X223 g600 g509 vdd gnd g671 nor2
X129 g32 g445 vdd gnd g483 nand2
X218 g582 vdd gnd g655 not1
X46 g50 g26 vdd gnd g334 and2
X228 g613 g610 vdd gnd g685 and2
X15 g11 g16 g8 vdd gnd g294 and3
X58 g276 vdd gnd g346 not1
X76 g326 g327 vdd gnd g379 nand2
X374 g646 vdd gnd g871 not1
X113 g432 g406 vdd gnd g451 nand2
X125 g369 g427 vdd gnd g475 or2
X23 g26 g27 vdd gnd g304 or2
X5 g1 g2 g9 g4 vdd gnd g279 nand4
X383 g854 vdd gnd g880 not1
X308 g723 g750 g751 g797 vdd gnd g798 nand4
X271 g594 g672 vdd gnd g749 nand2
X311 g789 g790 vdd gnd g808 nor2
X40 g45 g46 vdd gnd g328 nand2
X82 g348 g14 vdd gnd g396 and2
X289 g693 g761 vdd gnd g774 and2
X259 g53 g690 vdd gnd g737 and2
X318 g658 g802 vdd gnd g815 nor2
X260 g698 vdd gnd g738 not1
X165 g317 g491 vdd gnd g523 nor2
X214 g572 g574 vdd gnd g646 nor2
X79 g270 g343 vdd gnd g388 or2
X155 g436 g43 vdd gnd g509 and2
X42 g47 g48 vdd gnd g330 nand2
X182 g475 g527 vdd gnd g562 nand2
X243 g52 g650 vdd gnd g721 and2
X133 g24 g451 vdd gnd g487 and2
X91 g363 g366 vdd gnd g405 and2
X258 g52 g693 vdd gnd g736 and2
X139 g27 g451 vdd gnd g493 and2
X237 g639 g636 vdd gnd g712 and2
X347 g836 vdd gnd g844 not1
X266 g52 g712 vdd gnd g744 and2
X174 g518 vdd gnd g536 not1
X358 g290 vdd gnd g855 not1
X283 g739 g740 vdd gnd g768 nor2
X365 g353 vdd gnd g862 not1
X268 g629 g707 vdd gnd g746 nand2
X115 g310 g422 vdd gnd g461 and2
X10 g6 g16 g17 vdd gnd g287 and3
X257 g690 vdd gnd g735 not1
X181 g474 g526 vdd gnd g558 nand2
X77 g328 g329 vdd gnd g382 nand2
X34 g4 g8 vdd gnd g322 nor2
X185 g532 vdd gnd g571 not1
X44 g50 g24 vdd gnd g332 and2
X249 g52 g667 vdd gnd g727 and2
X86 g357 vdd gnd g400 not1
X14 g11 g16 g17 vdd gnd g293 and3
X33 g11 g40 vdd gnd g319 nand2
X128 g412 g435 vdd gnd g480 nor2
X73 g310 vdd gnd g369 not1
X30 g9 g34 vdd gnd g316 and2
X248 g663 vdd gnd g726 not1
X166 g318 g493 vdd gnd g524 nor2
X94 g379 vdd gnd g408 not1
X62 g280 g286 vdd gnd g350 or2
X121 g310 g422 vdd gnd g467 and2
X57 g276 vdd gnd g345 not1
X224 g601 vdd gnd g672 not1
X168 g497 g498 vdd gnd g526 nor2
X142 g28 g451 vdd gnd g496 and2
X277 g730 g731 vdd gnd g755 nor2
X136 g462 g463 vdd gnd g490 nor2
X106 g375 g11 g40 g389 vdd gnd g432 nand4
X66 g296 vdd gnd g354 not1
X354 g847 vdd gnd g851 not1
X118 g37 g417 vdd gnd g464 and2
X149 g32 g477 vdd gnd g503 nand2
X368 g388 vdd gnd g865 not1
X90 g366 vdd gnd g404 not1
X236 g636 vdd gnd g707 not1
X335 g720 g824 vdd gnd g832 and2
X233 g626 vdd gnd g698 not1
X376 g837 vdd gnd g873 not1
X290 g702 g765 vdd gnd g775 nor2
X251 g672 vdd gnd g729 not1
X95 g376 g379 vdd gnd g409 and2
X83 g349 vdd gnd g397 not1
X47 g50 g27 vdd gnd g335 and2
X321 g667 g805 vdd gnd g818 and2
X179 g524 g494 vdd gnd g550 nand2
X270 g620 g629 g707 vdd gnd g748 nand3
X286 g685 g756 vdd gnd g771 nor2
X276 g727 g728 vdd gnd g754 nor2
X345 g332 g834 vdd gnd g842 nor2
X197 g54 g546 vdd gnd g600 and2
X153 g436 g41 vdd gnd g507 and2
X22 g26 g27 vdd gnd g303 nand2
X81 g346 vdd gnd g395 not1
X315 g794 vdd gnd g812 not1
X147 g39 g468 vdd gnd g501 and2
X371 g398 vdd gnd g868 not1
X340 g829 vdd gnd g837 not1
X43 g47 g48 vdd gnd g331 or2
X310 g729 g795 vdd gnd g805 nand2
X143 g36 g468 vdd gnd g497 and2
X193 g542 g42 vdd gnd g585 or2
X309 g726 g749 g796 vdd gnd g802 nand3
X380 g848 vdd gnd g877 not1
X242 g647 vdd gnd g720 not1
X78 g330 g331 vdd gnd g385 nand2
X111 g402 g415 vdd gnd g445 nor2
X28 g2 g34 vdd gnd g309 and2
X56 g270 g273 vdd gnd g344 or2
X152 g480 g49 vdd gnd g506 or2
X50 g50 g29 vdd gnd g338 and2
X20 g24 g25 vdd gnd g301 nand2
X294 g778 g732 vdd gnd g779 nand2
X205 g558 g46 vdd gnd g620 or2
X209 g54 g562 vdd gnd g635 and2
X272 g585 g663 vdd gnd g750 nand2
X173 g515 vdd gnd g535 not1
X100 g396 vdd gnd g414 not1
X52 g50 g30 vdd gnd g340 and2
X201 g554 g45 vdd gnd g610 nand2
X265 g712 g58 vdd gnd g743 and2
X245 g655 vdd gnd g723 not1
X138 g464 g465 vdd gnd g492 nor2
X27 g30 g31 vdd gnd g308 or2
X301 g51 g785 vdd gnd g791 and2
X114 g35 g417 vdd gnd g460 and2
X348 g841 g752 g654 vdd gnd g845 nand3
X331 g334 g819 vdd gnd g828 nor2
X122 g433 g1 vdd gnd g468 nand2
X102 g403 g404 vdd gnd g416 and2
X4 g1 g5 g9 vdd gnd g276 and3
X162 g485 g486 vdd gnd g518 nand2
X219 g585 g582 vdd gnd g658 and2
X296 g773 g774 vdd gnd g786 nor2
X364 g351 vdd gnd g861 not1
X355 g849 vdd gnd g852 not1
X320 g667 g805 vdd gnd g817 nor2
X230 g617 vdd gnd g690 not1
X213 g537 g573 vdd gnd g645 nor2
X356 g850 vdd gnd g853 not1
X87 g360 vdd gnd g401 not1
X200 g54 g550 vdd gnd g609 and2
X108 g407 g408 vdd gnd g434 and2
X184 g529 vdd gnd g570 not1
X359 g291 vdd gnd g856 not1
X156 g436 g44 vdd gnd g510 and2
X351 g844 vdd gnd g848 not1
X132 g448 g33 vdd gnd g486 or2
X135 g25 g451 vdd gnd g489 and2
X333 g821 vdd gnd g830 not1
X282 g741 g717 vdd gnd g765 nand2
X63 g293 vdd gnd g351 not1
X291 g702 g765 vdd gnd g776 and2
X167 g495 g496 vdd gnd g525 nor2
X180 g473 g525 vdd gnd g554 nand2
X141 g35 g468 vdd gnd g495 and2
X41 g45 g46 vdd gnd g329 or2
X278 g735 g747 g748 g719 vdd gnd g756 nand4
X103 g319 g389 g10 vdd gnd g417 and3
X239 g639 g58 vdd gnd g717 nand2
X295 g771 g772 vdd gnd g785 nor2
X13 g6 g7 g8 vdd gnd g292 and3
X145 g37 g468 vdd gnd g499 and2
X16 g11 g7 g17 vdd gnd g295 and3
X37 g41 g42 vdd gnd g325 or2
X382 g853 vdd gnd g879 not1
X252 g52 g677 vdd gnd g730 and2
X240 g629 g639 g58 vdd gnd g718 nand3
X312 g335 g791 vdd gnd g809 nor2
X107 g389 g319 g4 vdd gnd g433 nand3
X65 g295 vdd gnd g353 not1
X164 g316 g489 vdd gnd g522 nor2
X60 g280 g284 vdd gnd g348 nor2
X247 g53 g655 vdd gnd g725 and2
X72 g307 g308 vdd gnd g366 nand2
X127 g409 g434 vdd gnd g477 nor2
X49 g55 g56 vdd gnd g337 and2
X264 g712 g58 vdd gnd g742 nor2
X241 g620 g629 g639 g58 vdd gnd g719 nand4
X288 g693 g761 vdd gnd g773 nor2
X279 g733 g734 vdd gnd g760 nor2
X375 g823 vdd gnd g872 not1
X326 g812 vdd gnd g823 not1
X303 g51 g787 vdd gnd g793 and2
X39 g43 g44 vdd gnd g327 or2
X112 g405 g416 vdd gnd g448 nor2
X116 g36 g417 vdd gnd g462 and2
X313 g336 g792 vdd gnd g810 nor2
X304 g788 g770 g716 g514 vdd gnd g794 nand4
X225 g604 g601 vdd gnd g677 and2
X137 g26 g451 vdd gnd g491 and2
X327 g798 g578 vdd gnd g824 nand2
X172 g505 g506 vdd gnd g532 nand2
X93 g376 vdd gnd g407 not1
X344 g413 g833 vdd gnd g841 nor2
X29 g60 vdd gnd g310 not1
X146 g30 g451 vdd gnd g500 and2
X9 g11 g12 g15 vdd gnd g286 nand3
X25 g28 g29 vdd gnd g306 or2
X55 g273 vdd gnd g343 not1
X157 g436 g45 vdd gnd g511 and2
X323 g809 g760 g689 vdd gnd g820 nand3
X284 g742 g743 vdd gnd g769 nor2
X84 g350 vdd gnd g398 not1
X300 g677 g779 vdd gnd g790 and2
X19 g20 g21 vdd gnd g298 or2
X367 g356 vdd gnd g864 not1
X273 g585 g594 g672 vdd gnd g751 nand3
X372 g399 vdd gnd g869 not1
X74 g322 g323 vdd gnd g375 nor2
X349 g842 g753 g662 vdd gnd g846 nand3
X316 g650 g798 vdd gnd g813 nor2
X161 g483 g484 vdd gnd g515 nand2
X190 g538 g41 vdd gnd g578 or2
X51 g55 g57 vdd gnd g339 and2
X160 g436 g48 vdd gnd g514 nand2
X69 g301 g302 vdd gnd g357 nand2
X336 g51 g825 vdd gnd g833 and2
X208 g562 g47 vdd gnd g629 or2
X297 g775 g776 vdd gnd g787 nor2
X154 g436 g42 vdd gnd g508 and2
X332 g820 vdd gnd g829 not1
X210 g566 g48 vdd gnd g636 nand2
X7 g11 g8 g12 g13 vdd gnd g284 nand4
X381 g852 vdd gnd g878 not1
X256 g53 g682 vdd gnd g734 and2
X216 g578 g575 vdd gnd g650 and2
X177 g522 g490 vdd gnd g542 nand2
X204 g558 g46 vdd gnd g617 nand2
X176 g521 g488 vdd gnd g538 nand2
X98 g382 g385 vdd gnd g412 and2
X221 g591 vdd gnd g663 not1
X232 g337 g625 vdd gnd g697 nor2
X196 g546 g43 vdd gnd g594 or2
X26 g30 g31 vdd gnd g307 nand2
X287 g685 g756 vdd gnd g772 and2
X59 g279 vdd gnd g347 not1
X54 g269 vdd gnd g342 not1
X244 g53 g647 vdd gnd g722 and2
X262 g53 g698 vdd gnd g740 and2
X18 g18 g19 vdd gnd g297 and2
X298 g340 g777 vdd gnd g788 nor2
X126 g369 g427 vdd gnd g476 or2
X203 g54 g554 vdd gnd g616 and2
X220 g590 g508 vdd gnd g662 nor2
X379 g840 vdd gnd g876 not1
X362 g342 vdd gnd g859 not1
X68 g23 g298 vdd gnd g356 and2
X110 g414 vdd gnd g436 not1
X53 g55 g59 vdd gnd g341 and2
X92 g347 g352 vdd gnd g406 nand2
X346 g333 g835 vdd gnd g843 nor2
X131 g448 g33 vdd gnd g485 nand2
X337 g51 g826 vdd gnd g834 and2
X255 g52 g685 vdd gnd g733 and2
X17 g11 g7 g8 vdd gnd g296 and3
X134 g460 g461 vdd gnd g488 nor2
X352 g845 vdd gnd g849 not1
X342 g831 vdd gnd g839 not1
X187 g535 g536 vdd gnd g573 and2
X334 g822 vdd gnd g831 not1
X48 g50 g28 vdd gnd g336 and2
X212 g54 g566 vdd gnd g644 and2
X6 g1 g2 g3 g10 vdd gnd g280 nand4
X64 g294 vdd gnd g352 not1
X38 g43 g44 vdd gnd g326 nand2
X109 g410 g411 vdd gnd g435 and2
X192 g542 g42 vdd gnd g582 nand2
X32 g38 g34 vdd gnd g318 and2
X97 g385 vdd gnd g411 not1
X75 g324 g325 vdd gnd g376 nand2
X363 g344 vdd gnd g860 not1
X21 g24 g25 vdd gnd g302 or2
X8 g6 g12 vdd gnd g285 nand2
X80 g345 vdd gnd g389 not1
X3 g6 g7 g8 vdd gnd g273 and3
X292 g51 g769 vdd gnd g777 and2
X198 g550 g44 vdd gnd g601 nand2
X12 g6 g7 g17 vdd gnd g291 and3
X71 g305 g306 vdd gnd g363 nand2
X373 g645 vdd gnd g870 not1
X140 g466 g467 vdd gnd g494 nor2
X253 g53 g672 vdd gnd g731 and2
X360 g292 vdd gnd g857 not1
X148 g31 g451 vdd gnd g502 and2
X274 g721 g722 vdd gnd g752 nor2
X183 g476 g528 vdd gnd g566 nand2
X123 g369 g427 vdd gnd g473 or2
X222 g594 g591 vdd gnd g667 and2
X188 g570 g571 vdd gnd g574 and2
X330 g817 g818 vdd gnd g827 nor2
X24 g28 g29 vdd gnd g305 nand2
X151 g480 g49 vdd gnd g505 nand2
X378 g839 vdd gnd g875 not1
X227 g610 vdd gnd g682 not1
X339 g828 g755 g681 vdd gnd g836 nand3
X267 g53 g707 vdd gnd g745 and2
X85 g355 vdd gnd g399 not1
X370 g397 vdd gnd g867 not1
X281 g736 g737 vdd gnd g764 nor2
X211 g566 g48 vdd gnd g639 or2
X171 g503 g504 vdd gnd g529 nand2
X11 g6 g16 g8 vdd gnd g290 and3
X169 g499 g500 vdd gnd g527 nor2
X191 g54 g538 vdd gnd g581 and2
X350 g843 g754 g671 vdd gnd g847 nand3
X217 g581 g507 vdd gnd g654 nor2
X307 g585 g594 g604 g779 vdd gnd g797 nand4
X150 g32 g477 vdd gnd g504 or2
X317 g650 g798 vdd gnd g814 and2
X88 g357 g360 vdd gnd g402 and2
X250 g53 g663 vdd gnd g728 and2
X235 g339 g635 vdd gnd g706 nor2
X207 g562 g47 vdd gnd g626 nand2
X195 g546 g43 vdd gnd g591 nand2
X343 g832 vdd gnd g840 not1
X124 g369 g427 vdd gnd g474 or2
X357 g851 vdd gnd g854 not1
X178 g523 g492 vdd gnd g546 nand2
X99 g50 g369 vdd gnd g413 and2
X119 g310 g422 vdd gnd g465 and2
X45 g50 g25 vdd gnd g333 and2
X226 g609 g510 vdd gnd g681 nor2
X306 g594 g604 g779 vdd gnd g796 nand3
X238 g341 g644 vdd gnd g716 nor2
X263 g707 vdd gnd g741 not1
X231 g620 g617 vdd gnd g693 and2
X158 g436 g46 vdd gnd g512 nand2
X319 g658 g802 vdd gnd g816 and2
X175 g515 g518 vdd gnd g537 and2
X36 g41 g42 vdd gnd g324 nand2
X104 g389 g4 g287 vdd gnd g422 and3
X199 g550 g44 vdd gnd g604 or2
X361 g297 vdd gnd g858 not1
.subckt and3 a b c vdd vss z
m01 08 a vdd vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m02 n1 a vss vss nmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m03 vdd b 08 vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m04 sig6 b n1 vss nmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m05 08 c vdd vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m06 08 c sig6 vss nmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m07 vdd 08 z vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m08 vss 08 z vss nmos l=0.12u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
c4 08 vss 1.142f
c5 a vss 0.539f
c7 b vss 0.609f
c8 c vss 0.651f
c3 z vss 0.745f
.ends
.subckt nand3 a b c vdd vss z
m01 vdd a z vdd pmos l=0.12u w=1.1u as=0.2915p ad=0.2915p ps=2.73u pd=2.73u
m02 vss a sig2 vss nmos l=0.12u w=1.1u as=0.2915p ad=0.2915p ps=2.73u pd=2.73u
m03 z b vdd vdd pmos l=0.12u w=1.1u as=0.2915p ad=0.2915p ps=2.73u pd=2.73u
m04 sig2 b sig3 vss nmos l=0.12u w=1.1u as=0.2915p ad=0.2915p ps=2.73u pd=2.73u
m05 vdd c z vdd pmos l=0.12u w=1.1u as=0.2915p ad=0.2915p ps=2.73u pd=2.73u
m06 sig3 c z vss nmos l=0.12u w=1.1u as=0.2915p ad=0.2915p ps=2.73u pd=2.73u
c5 a vss 0.491f
c6 b vss 0.400f
c7 c vss 0.478f
c1 z vss 0.850f
.ends
.subckt nor2 a b vdd vss z
m01 vdd a 01 vdd pmos l=0.12u w=1.54u as=0.4081p ad=0.4081p ps=3.61u pd=3.61u
m02 vss a z vss nmos l=0.12u w=0.44u as=0.1166p ad=0.1166p ps=1.41u pd=1.41u
m03 01 b z vdd pmos l=0.12u w=1.54u as=0.4081p ad=0.4081p ps=3.61u pd=3.61u
m04 z b vss vss nmos l=0.12u w=0.44u as=0.1166p ad=0.1166p ps=1.41u pd=1.41u
c4 a vss 0.341f
c3 b vss 0.433f
c2 z vss 0.677f
.ends
.subckt nand4 a b c d vdd vss z
m01 vdd a z vdd pmos l=0.12u w=0.935u as=0.247775p ad=0.247775p ps=2.4u pd=2.4u
m02 vss a sig7 vss nmos l=0.12u w=1.1u as=0.2915p ad=0.2915p ps=2.73u pd=2.73u
m03 z b vdd vdd pmos l=0.12u w=0.935u as=0.247775p ad=0.247775p ps=2.4u pd=2.4u
m04 sig7 b sig3 vss nmos l=0.12u w=1.1u as=0.2915p ad=0.2915p ps=2.73u pd=2.73u
m05 vdd c z vdd pmos l=0.12u w=0.935u as=0.247775p ad=0.247775p ps=2.4u pd=2.4u
m06 sig3 c sig2 vss nmos l=0.12u w=1.1u as=0.2915p ad=0.2915p ps=2.73u pd=2.73u
m07 z d vdd vdd pmos l=0.12u w=0.935u as=0.247775p ad=0.247775p ps=2.4u pd=2.4u
m08 sig2 d z vss nmos l=0.12u w=1.1u as=0.2915p ad=0.2915p ps=2.73u pd=2.73u
c9 a vss 0.610f
c8 b vss 0.677f
c6 c vss 0.603f
c5 d vss 0.638f
c1 z vss 0.948f
.ends
.subckt or2 a b vdd vss z
m01 03 a vdd vdd pmos l=0.12u w=1.155u as=0.306075p ad=0.306075p ps=2.84u pd=2.84u
m02 sig1 a vss vss nmos l=0.12u w=0.33u as=0.08745p ad=0.08745p ps=1.19u pd=1.19u
m03 sig1 b 03 vdd pmos l=0.12u w=1.155u as=0.306075p ad=0.306075p ps=2.84u pd=2.84u
m04 vss b sig1 vss nmos l=0.12u w=0.33u as=0.08745p ad=0.08745p ps=1.19u pd=1.19u
m5 vdd sig1 z vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m6 vss sig1 z vss nmos l=0.12u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
c4 a vss 0.464f
c5 b vss 0.507f
c1 sig1 vss 0.619f
c3 z vss 0.593f
.ends
.subckt nand2 a b vdd vss z
m01 vdd a z vdd pmos l=0.12u w=0.77u as=0.20405p ad=0.20405p ps=2.07u pd=2.07u
m02 vss a sig3 vss nmos l=0.12u w=0.66u as=0.1749p ad=0.1749p ps=1.85u pd=1.85u
m03 z b vdd vdd pmos l=0.12u w=0.77u as=0.20405p ad=0.20405p ps=2.07u pd=2.07u
m04 sig3 b z vss nmos l=0.12u w=0.66u as=0.1749p ad=0.1749p ps=1.85u pd=1.85u
c4 a vss 0.549f
c5 b vss 0.578f
c1 z vss 0.609f
.ends
.subckt and2 a b vdd vss z
m01 06 a vdd vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m02 n1 a vss vss nmos l=0.12u w=0.605u as=0.160325p ad=0.160325p ps=1.74u pd=1.74u
m03 vdd b 06 vdd pmos l=0.12u w=0.715u as=0.189475p ad=0.189475p ps=1.96u pd=1.96u
m04 06 b n1 vss nmos l=0.12u w=0.605u as=0.160325p ad=0.160325p ps=1.74u pd=1.74u
m05 vdd 06 z vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m06 vss 06 z vss nmos l=0.12u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
c4 06 vss 0.724f
c5 a vss 0.663f
c6 b vss 0.538f
c3 z vss 0.595f
.ends
.subckt not1 a vdd vss z
m01 vdd a z vdd pmos l=0.12u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
m02 vss a z vss nmos l=0.12u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
c3 a vss 0.384f
c2 z vss 0.576f
.ends
* simulation command:
.tran 1ps 1ns
.print tran V(g859) V(g861) V(g865) V(g870) V(g864) V(g866) V(g878) V(g862) V(g860) V(g869) V(g874) V(g863) V(g877) V(g876) V(g857) V(g871) V(g868) V(g856) V(g880) V(g873) V(g872) V(g875) V(g867) V(g858) V(g879) V(g855)
.end

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,101 @@
.subckt not1 a vdd vss z
Mn z a vss vss nmos W={Wmin} L={Lmin} AS={Ldiff*Wmin} AD={Ldiff*Wmin} PS={2*(Ldiff+Wmin)} PD={2*(Ldiff+Wmin)}
Mp z a vdd vdd pmos W={2*Wmin} L={Lmin} AS={Ldiff*2*Wmin} AD={Ldiff*2*Wmin} PS={2*(Ldiff+2*Wmin)} PD={2*(Ldiff+2*Wmin)}
.ends
.subckt buf1 a vdd vss z
Xnot1 a vdd vss out not1
Xnot2 out vdd vss z not1
.ends
.subckt nand2 a b vdd vss z
Mn1 z a SD vss nmos W={2*Wmin} L={Lmin} AS={2*Wmin*Ldiff} AD={2*Wmin*Ldiff} PS={2*(Ldiff+2*Wmin)} PD={2*(Ldiff+2*Wmin)}
Mn2 SD b vss vss nmos W={2*Wmin} L={Lmin} AS={2*Wmin*Ldiff} AD={2*Wmin*Ldiff} PS={2*(Ldiff+2*Wmin)} PD={2*(Ldiff+2*Wmin)}
Mp1 z a vdd vdd pmos W={2*Wmin} L={Lmin} AS={2*Wmin*Ldiff} AD={2*Wmin*Ldiff} PS={2*(Ldiff+2*Wmin)} PD={2*(Ldiff+2*Wmin)}
Mp2 z b vdd vdd pmos W={2*Wmin} L={Lmin} AS={2*Wmin*Ldiff} AD={2*Wmin*Ldiff} PS={2*(Ldiff+2*Wmin)} PD={2*(Ldiff+2*Wmin)}
.ends
.subckt nand3 a b c vdd vss z
Mn1 z a SD1 vss nmos W={3*Wmin} L={Lmin} AS={3*Wmin*Ldiff} AD={3*Wmin*Ldiff} PS={2*(Ldiff+3*Wmin)} PD={2*(Ldiff+3*Wmin)}
Mn2 SD1 b SD2 vss nmos W={3*Wmin} L={Lmin} AS={3*Wmin*Ldiff} AD={3*Wmin*Ldiff} PS={2*(Ldiff+3*Wmin)} PD={2*(Ldiff+3*Wmin)}
Mn3 SD2 c vss vss nmos W={3*Wmin} L={Lmin} AS={3*Wmin*Ldiff} AD={3*Wmin*Ldiff} PS={2*(Ldiff+3*Wmin)} PD={2*(Ldiff+3*Wmin)}
Mp1 z a vdd vdd pmos W={2*Wmin} L={Lmin} AS={2*Wmin*Ldiff} AD={2*Wmin*Ldiff} PS={2*(Ldiff+2*Wmin)} PD={2*(Ldiff+2*Wmin)}
Mp2 z b vdd vdd pmos W={2*Wmin} L={Lmin} AS={2*Wmin*Ldiff} AD={2*Wmin*Ldiff} PS={2*(Ldiff+2*Wmin)} PD={2*(Ldiff+2*Wmin)}
Mp3 z c vdd vdd pmos W={2*Wmin} L={Lmin} AS={2*Wmin*Ldiff} AD={2*Wmin*Ldiff} PS={2*(Ldiff+2*Wmin)} PD={2*(Ldiff+2*Wmin)}
.ends
.subckt nand4 a b c d vdd vss z
Mn1 z a SD1 vss nmos W={4*Wmin} L={Lmin} AS={4*Wmin*Ldiff} AD={4*Wmin*Ldiff} PS={2*(Ldiff+4*Wmin)} PD={2*(Ldiff+4*Wmin)}
Mn2 SD1 b SD2 vss nmos W={4*Wmin} L={Lmin} AS={4*Wmin*Ldiff} AD={4*Wmin*Ldiff} PS={2*(Ldiff+4*Wmin)} PD={2*(Ldiff+4*Wmin)}
Mn3 SD2 c SD3 vss nmos W={4*Wmin} L={Lmin} AS={4*Wmin*Ldiff} AD={4*Wmin*Ldiff} PS={2*(Ldiff+4*Wmin)} PD={2*(Ldiff+4*Wmin)}
Mn4 SD3 d vss vss nmos W={4*Wmin} L={Lmin} AS={4*Wmin*Ldiff} AD={4*Wmin*Ldiff} PS={2*(Ldiff+4*Wmin)} PD={2*(Ldiff+4*Wmin)}
Mp1 z a vdd vdd pmos W={2*Wmin} L={Lmin} AS={2*Wmin*Ldiff} AD={2*Wmin*Ldiff} PS={2*(Ldiff+2*Wmin)} PD={2*(Ldiff+2*Wmin)}
Mp2 z b vdd vdd pmos W={2*Wmin} L={Lmin} AS={2*Wmin*Ldiff} AD={2*Wmin*Ldiff} PS={2*(Ldiff+2*Wmin)} PD={2*(Ldiff+2*Wmin)}
Mp3 z c vdd vdd pmos W={2*Wmin} L={Lmin} AS={2*Wmin*Ldiff} AD={2*Wmin*Ldiff} PS={2*(Ldiff+2*Wmin)} PD={2*(Ldiff+2*Wmin)}
Mp4 z d vdd vdd pmos W={2*Wmin} L={Lmin} AS={2*Wmin*Ldiff} AD={2*Wmin*Ldiff} PS={2*(Ldiff+2*Wmin)} PD={2*(Ldiff+2*Wmin)}
.ends
.subckt and2 a b vdd vss z
Xnand a b vdd vss out nand2
Xnot out vdd vss z not1
.ends
.subckt and3 a b c vdd vss z
Xnand a b c vdd vss out nand3
Xnot out vdd vss z not1
.ends
.subckt and4 a b c d vdd vss z
Xnand a b c d vdd vss out nand4
Xnot out vdd vss z not1
.ends
.subckt nor2 a b vdd vss z
Mn1 z a vss vss nmos W={1*Wmin} L={Lmin} AS={1*Wmin*Ldiff} AD={1*Wmin*Ldiff} PS={2*(Ldiff+1*Wmin)} PD={2*(Ldiff+1*Wmin)}
Mn2 z b vss vss nmos W={1*Wmin} L={Lmin} AS={1*Wmin*Ldiff} AD={1*Wmin*Ldiff} PS={2*(Ldiff+1*Wmin)} PD={2*(Ldiff+1*Wmin)}
Mp1 SD a vdd vdd pmos W={4*Wmin} L={Lmin} AS={4*Wmin*Ldiff} AD={4*Wmin*Ldiff} PS={2*(Ldiff+4*Wmin)} PD={2*(Ldiff+4*Wmin)}
Mp2 z b SD vdd pmos W={4*Wmin} L={Lmin} AS={4*Wmin*Ldiff} AD={4*Wmin*Ldiff} PS={2*(Ldiff+4*Wmin)} PD={2*(Ldiff+4*Wmin)}
.ends
.subckt nor3 a b c vdd vss z
Mn1 out a vss vss nmos W={1*Wmin} L={Lmin} AS={1*Wmin*Ldiff} AD={1*Wmin*Ldiff} PS={2*(Ldiff+1*Wmin)} PD={2*(Ldiff+1*Wmin)}
Mn2 out b vss vss nmos W={1*Wmin} L={Lmin} AS={1*Wmin*Ldiff} AD={1*Wmin*Ldiff} PS={2*(Ldiff+1*Wmin)} PD={2*(Ldiff+1*Wmin)}
Mn3 out c vss vss nmos W={1*Wmin} L={Lmin} AS={1*Wmin*Ldiff} AD={1*Wmin*Ldiff} PS={2*(Ldiff+1*Wmin)} PD={2*(Ldiff+1*Wmin)}
Mp1 SD1 a vdd vdd pmos W={6*Wmin} L={Lmin} AS={6*Wmin*Ldiff} AD={6*Wmin*Ldiff} PS={2*(Ldiff+6*Wmin)} PD={2*(Ldiff+6*Wmin)}
Mp2 SD2 b SD1 vdd pmos W={6*Wmin} L={Lmin} AS={6*Wmin*Ldiff} AD={6*Wmin*Ldiff} PS={2*(Ldiff+6*Wmin)} PD={2*(Ldiff+6*Wmin)}
Mp3 out c SD2 vdd pmos W={6*Wmin} L={Lmin} AS={6*Wmin*Ldiff} AD={6*Wmin*Ldiff} PS={2*(Ldiff+6*Wmin)} PD={2*(Ldiff+6*Wmin)}
.ends
.subckt nor4 a b c d vdd vss z
Mn1 z A vss vss nmos W={1*Wmin} L={Lmin} AS={1*Wmin*Ldiff} AD={1*Wmin*Ldiff} PS={2*(Ldiff+1*Wmin)} PD={2*(Ldiff+1*Wmin)}
Mn2 z B vss vss nmos W={1*Wmin} L={Lmin} AS={1*Wmin*Ldiff} AD={1*Wmin*Ldiff} PS={2*(Ldiff+1*Wmin)} PD={2*(Ldiff+1*Wmin)}
Mn3 z C vss vss nmos W={1*Wmin} L={Lmin} AS={1*Wmin*Ldiff} AD={1*Wmin*Ldiff} PS={2*(Ldiff+1*Wmin)} PD={2*(Ldiff+1*Wmin)}
Mn4 z D vss vss nmos W={1*Wmin} L={Lmin} AS={1*Wmin*Ldiff} AD={1*Wmin*Ldiff} PS={2*(Ldiff+1*Wmin)} PD={2*(Ldiff+1*Wmin)}
Mp1 SD1 A vdd vdd pmos W={8*Wmin} L={Lmin} AS={8*Wmin*Ldiff} AD={8*Wmin*Ldiff} PS={2*(Ldiff+8*Wmin)} PD={2*(Ldiff+8*Wmin)}
Mp2 SD2 B SD1 vdd pmos W={8*Wmin} L={Lmin} AS={8*Wmin*Ldiff} AD={8*Wmin*Ldiff} PS={2*(Ldiff+8*Wmin)} PD={2*(Ldiff+8*Wmin)}
Mp3 SD3 C SD2 vdd pmos W={8*Wmin} L={Lmin} AS={8*Wmin*Ldiff} AD={8*Wmin*Ldiff} PS={2*(Ldiff+8*Wmin)} PD={2*(Ldiff+8*Wmin)}
Mp4 z D SD3 vdd pmos W={8*Wmin} L={Lmin} AS={8*Wmin*Ldiff} AD={8*Wmin*Ldiff} PS={2*(Ldiff+8*Wmin)} PD={2*(Ldiff+8*Wmin)}
.ends
.subckt or2 a b vdd vss z
Xnor a b vdd vss out nor2
Xnot out vdd vss z not1
.ends
.subckt or3 a b c vdd vss z
Xnor a b c vdd vss out nor3
Xnot out vdd vss z not1
.ends
.subckt or4 a b c d vdd vss z
Xnor a b c d vdd vss out nor4
Xnot out vdd vss z not1
.ends
.subckt xor2 a b vdd vss z
Xor a b vdd vss out1 or2
Xnand a b vdd vss out2 nand2
Xand out1 out2 vdd vss z and2
.ends

View File

@ -0,0 +1,357 @@
* Spice description of an2v0x1
* Spice driver version 134999461
* Date 1/01/2008 at 16:33:58
* wsclib 0.13um values
.subckt an2v0x1 a b vdd vss z
M01 06 a vdd vdd pmos L=0.12U W=0.715U AS=0.189475P AD=0.189475P PS=1.96U PD=1.96U
M02 n1 a vss vss nmos L=0.12U W=0.605U AS=0.160325P AD=0.160325P PS=1.74U PD=1.74U
M03 vdd b 06 vdd pmos L=0.12U W=0.715U AS=0.189475P AD=0.189475P PS=1.96U PD=1.96U
M04 06 b n1 vss nmos L=0.12U W=0.605U AS=0.160325P AD=0.160325P PS=1.74U PD=1.74U
M05 vdd 06 z vdd pmos L=0.12U W=0.99U AS=0.26235P AD=0.26235P PS=2.51U PD=2.51U
M06 vss 06 z vss nmos L=0.12U W=0.495U AS=0.131175P AD=0.131175P PS=1.52U PD=1.52U
C4 06 vss 0.724f
C5 a vss 0.663f
C6 b vss 0.538f
C3 z vss 0.595f
.ends
* Spice description of an3v0x1
* Spice driver version 134999461
* Date 1/01/2008 at 16:35:14
* wsclib 0.13um values
.subckt an3v0x1 a b c vdd vss z
M01 08 a vdd vdd pmos L=0.12U W=0.715U AS=0.189475P AD=0.189475P PS=1.96U PD=1.96U
M02 n1 a vss vss nmos L=0.12U W=0.715U AS=0.189475P AD=0.189475P PS=1.96U PD=1.96U
M03 vdd b 08 vdd pmos L=0.12U W=0.715U AS=0.189475P AD=0.189475P PS=1.96U PD=1.96U
M04 sig6 b n1 vss nmos L=0.12U W=0.715U AS=0.189475P AD=0.189475P PS=1.96U PD=1.96U
M05 08 c vdd vdd pmos L=0.12U W=0.715U AS=0.189475P AD=0.189475P PS=1.96U PD=1.96U
M06 08 c sig6 vss nmos L=0.12U W=0.715U AS=0.189475P AD=0.189475P PS=1.96U PD=1.96U
M07 vdd 08 z vdd pmos L=0.12U W=0.99U AS=0.26235P AD=0.26235P PS=2.51U PD=2.51U
M08 vss 08 z vss nmos L=0.12U W=0.495U AS=0.131175P AD=0.131175P PS=1.52U PD=1.52U
C4 08 vss 1.142f
C5 a vss 0.539f
C7 b vss 0.609f
C8 c vss 0.651f
C3 z vss 0.745f
.ends
* Spice description of an4v0x1
* Spice driver version 134999461
* Date 1/01/2008 at 16:35:56
* wsclib 0.13um values
.subckt an4v0x1 a b c d vdd vss z
M01 10 a vdd vdd pmos L=0.12U W=0.715U AS=0.189475P AD=0.189475P PS=1.96U PD=1.96U
M02 n1 a vss vss nmos L=0.12U W=0.88U AS=0.2332P AD=0.2332P PS=2.29U PD=2.29U
M03 vdd b 10 vdd pmos L=0.12U W=0.715U AS=0.189475P AD=0.189475P PS=1.96U PD=1.96U
M04 sig7 b n1 vss nmos L=0.12U W=0.88U AS=0.2332P AD=0.2332P PS=2.29U PD=2.29U
M05 10 c vdd vdd pmos L=0.12U W=0.715U AS=0.189475P AD=0.189475P PS=1.96U PD=1.96U
M06 n3 c sig7 vss nmos L=0.12U W=0.88U AS=0.2332P AD=0.2332P PS=2.29U PD=2.29U
M07 vdd d 10 vdd pmos L=0.12U W=0.715U AS=0.189475P AD=0.189475P PS=1.96U PD=1.96U
M08 10 d n3 vss nmos L=0.12U W=0.88U AS=0.2332P AD=0.2332P PS=2.29U PD=2.29U
M09 vdd 10 z vdd pmos L=0.12U W=0.99U AS=0.26235P AD=0.26235P PS=2.51U PD=2.51U
M10 vss 10 z vss nmos L=0.12U W=0.495U AS=0.131175P AD=0.131175P PS=1.52U PD=1.52U
C4 10 vss 0.940f
C5 a vss 0.674f
C8 b vss 0.541f
C9 c vss 0.622f
C10 d vss 0.791f
C3 z vss 0.765f
.ends
* Spice description of bf1v0x1
* Spice driver version 134999461
* Date 1/01/2008 at 16:39:34
* wsclib 0.13um values
.subckt bf1v0x1 a vdd vss z
M01 an a vdd vdd pmos L=0.12U W=0.715U AS=0.189475P AD=0.189475P PS=1.96U PD=1.96U
M02 an a vss vss nmos L=0.12U W=0.44U AS=0.1166P AD=0.1166P PS=1.41U PD=1.41U
M03 vdd an z vdd pmos L=0.12U W=0.99U AS=0.26235P AD=0.26235P PS=2.51U PD=2.51U
M04 vss an z vss nmos L=0.12U W=0.495U AS=0.131175P AD=0.131175P PS=1.52U PD=1.52U
C2 an vss 0.554f
C4 a vss 0.449f
C3 z vss 0.506f
.ends
.subckt dff cp d vdd vss z
*01-JAN-08 SPICE3 file created from dfnt1v0x2.ext - technology: scmos
m00 vdd zn z vdd pmos w=1.54u l=0.13u ad=0.409794p pd=3.3124u as=0.4928p ps=3.83u
m01 zn n4 vdd vdd pmos w=0.77u l=0.13u ad=0.24035p pd=2.29u as=0.204897p ps=1.6562u
m02 w1 zn vdd vdd pmos w=0.33u l=0.13u ad=0.042075p pd=0.585u as=0.087813p ps=0.7098u
m03 n4 ci w1 vdd pmos w=0.33u l=0.13u ad=0.07535p pd=0.72u as=0.042075p ps=0.585u
m04 n2 cn n4 vdd pmos w=0.66u l=0.13u ad=0.1386p pd=1.08u as=0.1507p ps=1.44u
m05 vdd n1 n2 vdd pmos w=0.66u l=0.13u ad=0.175626p pd=1.4196u as=0.1386p ps=1.08u
m06 w2 n2 vdd vdd pmos w=0.33u l=0.13u ad=0.042075p pd=0.585u as=0.087813p ps=0.7098u
m07 n1 cn w2 vdd pmos w=0.33u l=0.13u ad=0.0759868p pd=0.716842u as=0.042075p ps=0.585u
m08 vss zn z vss nmos w=0.77u l=0.13u ad=0.223765p pd=2.21828u as=0.24035p ps=2.29u
m09 vss n4 zn vss nmos w=0.385u l=0.13u ad=0.111882p pd=1.10914u as=0.138325p ps=1.52u
m10 w3 ci n1 vdd pmos w=0.715u l=0.13u ad=0.0911625p pd=0.97u as=0.164638p ps=1.55316u
m11 vdd d w3 vdd pmos w=0.715u l=0.13u ad=0.190262p pd=1.5379u as=0.0911625p ps=0.97u
m12 ci cn vdd vdd pmos w=0.605u l=0.13u ad=0.196625p pd=1.96u as=0.160991p ps=1.3013u
m13 cn cp vdd vdd pmos w=0.55u l=0.13u ad=0.18205p pd=1.85u as=0.146355p ps=1.183u
m14 vss cn ci vss nmos w=0.33u l=0.13u ad=0.0958992p pd=0.95069u as=0.12375p ps=1.41u
m15 w4 zn vss vss nmos w=0.33u l=0.13u ad=0.042075p pd=0.585u as=0.0958992p ps=0.95069u
m16 n4 cn w4 vss nmos w=0.33u l=0.13u ad=0.0693p pd=0.75u as=0.042075p ps=0.585u
m17 n2 ci n4 vss nmos w=0.33u l=0.13u ad=0.0693p pd=0.75u as=0.0693p ps=0.75u
m18 vss n1 n2 vss nmos w=0.33u l=0.13u ad=0.0958992p pd=0.95069u as=0.0693p ps=0.75u
m19 w5 n2 vss vss nmos w=0.33u l=0.13u ad=0.042075p pd=0.585u as=0.0958992p ps=0.95069u
m20 n1 ci w5 vss nmos w=0.33u l=0.13u ad=0.0693p pd=0.75u as=0.042075p ps=0.585u
m21 w6 cn n1 vss nmos w=0.33u l=0.13u ad=0.042075p pd=0.585u as=0.0693p ps=0.75u
m22 vss d w6 vss nmos w=0.33u l=0.13u ad=0.0958992p pd=0.95069u as=0.042075p ps=0.585u
m23 cn cp vss vss nmos w=0.385u l=0.13u ad=0.144375p pd=1.52u as=0.111882p ps=1.10914u
C0 ci cn 0.246f
C1 vdd cn 0.074f
C2 vdd z 0.030f
C3 ci n4 0.090f
C4 ci n1 0.179f
C5 n4 w4 0.010f
C6 n4 vdd 0.041f
C7 vdd n1 0.043f
C8 zn cn 0.055f
C9 d cp 0.006f
C10 ci n2 0.120f
C11 w5 n1 0.008f
C12 ci d 0.190f
C13 zn z 0.050f
C14 vdd n2 0.012f
C15 d vdd 0.003f
C16 n4 zn 0.116f
C17 ci w3 0.005f
C18 n4 cn 0.011f
C19 cn n1 0.076f
C20 ci cp 0.027f
C21 cp vdd 0.023f
C22 cn n2 0.073f
C23 d cn 0.105f
C24 ci vdd 0.039f
C25 n4 w1 0.008f
C26 n4 n2 0.019f
C27 n1 n2 0.167f
C28 ci zn 0.050f
C29 w2 n1 0.003f
C30 cp cn 0.128f
C31 vdd zn 0.007f
C32 w6 vss 0.004f
C33 w5 vss 0.002f
C34 w4 vss 0.002f
C35 cp vss 0.114f
C36 w3 vss 0.004f
C37 w2 vss 0.001f
C38 n4 vss 0.213f
C39 d vss 0.119f
C40 ci vss 0.377f
C41 n2 vss 0.184f
C42 n1 vss 0.247f
C43 z vss 0.142f
C44 cn vss 0.439f
C45 zn vss 0.251f
.ends
* Spice description of iv1v0x1
* Spice driver version 134999461
* Date 1/01/2008 at 16:44:01
* wsclib 0.13um values
.subckt iv1v0x1 a vdd vss z
M01 vdd a z vdd pmos L=0.12U W=0.99U AS=0.26235P AD=0.26235P PS=2.51U PD=2.51U
M02 vss a z vss nmos L=0.12U W=0.495U AS=0.131175P AD=0.131175P PS=1.52U PD=1.52U
C3 a vss 0.384f
C2 z vss 0.576f
.ends
* Spice description of nd2v0x1
* Spice driver version 134999461
* Date 1/01/2008 at 16:49:53
* wsclib 0.13um values
.subckt nd2v0x1 a b vdd vss z
M01 vdd a z vdd pmos L=0.12U W=0.77U AS=0.20405P AD=0.20405P PS=2.07U PD=2.07U
M02 vss a sig3 vss nmos L=0.12U W=0.66U AS=0.1749P AD=0.1749P PS=1.85U PD=1.85U
M03 z b vdd vdd pmos L=0.12U W=0.77U AS=0.20405P AD=0.20405P PS=2.07U PD=2.07U
M04 sig3 b z vss nmos L=0.12U W=0.66U AS=0.1749P AD=0.1749P PS=1.85U PD=1.85U
C4 a vss 0.549f
C5 b vss 0.578f
C1 z vss 0.609f
.ends
* Spice description of nd3v0x1
* Spice driver version 134999461
* Date 1/01/2008 at 16:52:51
* wsclib 0.13um values
.subckt nd3v0x1 a b c vdd vss z
M01 vdd a z vdd pmos L=0.12U W=1.1U AS=0.2915P AD=0.2915P PS=2.73U PD=2.73U
M02 vss a sig2 vss nmos L=0.12U W=1.1U AS=0.2915P AD=0.2915P PS=2.73U PD=2.73U
M03 z b vdd vdd pmos L=0.12U W=1.1U AS=0.2915P AD=0.2915P PS=2.73U PD=2.73U
M04 sig2 b sig3 vss nmos L=0.12U W=1.1U AS=0.2915P AD=0.2915P PS=2.73U PD=2.73U
M05 vdd c z vdd pmos L=0.12U W=1.1U AS=0.2915P AD=0.2915P PS=2.73U PD=2.73U
M06 sig3 c z vss nmos L=0.12U W=1.1U AS=0.2915P AD=0.2915P PS=2.73U PD=2.73U
C5 a vss 0.491f
C6 b vss 0.400f
C7 c vss 0.478f
C1 z vss 0.850f
.ends
* Spice description of nd4v0x1
* Spice driver version 134999461
* Date 1/01/2008 at 16:54:03
* wsclib 0.13um values
.subckt nd4v0x1 a b c d vdd vss z
M01 vdd a z vdd pmos L=0.12U W=0.935U AS=0.247775P AD=0.247775P PS=2.4U PD=2.4U
M02 vss a sig7 vss nmos L=0.12U W=1.1U AS=0.2915P AD=0.2915P PS=2.73U PD=2.73U
M03 z b vdd vdd pmos L=0.12U W=0.935U AS=0.247775P AD=0.247775P PS=2.4U PD=2.4U
M04 sig7 b sig3 vss nmos L=0.12U W=1.1U AS=0.2915P AD=0.2915P PS=2.73U PD=2.73U
M05 vdd c z vdd pmos L=0.12U W=0.935U AS=0.247775P AD=0.247775P PS=2.4U PD=2.4U
M06 sig3 c sig2 vss nmos L=0.12U W=1.1U AS=0.2915P AD=0.2915P PS=2.73U PD=2.73U
M07 z d vdd vdd pmos L=0.12U W=0.935U AS=0.247775P AD=0.247775P PS=2.4U PD=2.4U
M08 sig2 d z vss nmos L=0.12U W=1.1U AS=0.2915P AD=0.2915P PS=2.73U PD=2.73U
C9 a vss 0.610f
C8 b vss 0.677f
C6 c vss 0.603f
C5 d vss 0.638f
C1 z vss 0.948f
.ends
* Spice description of nr2v0x1
* Spice driver version 134999461
* Date 1/01/2008 at 16:55:05
* wsclib 0.13um values
.subckt nr2v0x1 a b vdd vss z
M01 vdd a 01 vdd pmos L=0.12U W=1.54U AS=0.4081P AD=0.4081P PS=3.61U PD=3.61U
M02 vss a z vss nmos L=0.12U W=0.44U AS=0.1166P AD=0.1166P PS=1.41U PD=1.41U
M03 01 b z vdd pmos L=0.12U W=1.54U AS=0.4081P AD=0.4081P PS=3.61U PD=3.61U
M04 z b vss vss nmos L=0.12U W=0.44U AS=0.1166P AD=0.1166P PS=1.41U PD=1.41U
C4 a vss 0.341f
C3 b vss 0.433f
C2 z vss 0.677f
.ends
* Spice description of nr3v0x1
* Spice driver version 134999461
* Date 1/01/2008 at 16:56:49
* wsclib 0.13um values
.subckt nr3v0x1 a b c vdd vss z
M01 sig6 a vdd vdd pmos L=0.12U W=1.54U AS=0.4081P AD=0.4081P PS=3.61U PD=3.61U
M02 vdd a 02 vdd pmos L=0.12U W=1.54U AS=0.4081P AD=0.4081P PS=3.61U PD=3.61U
M03 vss a z vss nmos L=0.12U W=0.55U AS=0.14575P AD=0.14575P PS=1.63U PD=1.63U
M04 04 b sig6 vdd pmos L=0.12U W=1.54U AS=0.4081P AD=0.4081P PS=3.61U PD=3.61U
M05 02 b 08 vdd pmos L=0.12U W=1.54U AS=0.4081P AD=0.4081P PS=3.61U PD=3.61U
M06 z b vss vss nmos L=0.12U W=0.55U AS=0.14575P AD=0.14575P PS=1.63U PD=1.63U
M07 z c 04 vdd pmos L=0.12U W=1.54U AS=0.4081P AD=0.4081P PS=3.61U PD=3.61U
M08 08 c z vdd pmos L=0.12U W=1.54U AS=0.4081P AD=0.4081P PS=3.61U PD=3.61U
M09 vss c z vss nmos L=0.12U W=0.55U AS=0.14575P AD=0.14575P PS=1.63U PD=1.63U
C3 a vss 0.957f
C4 b vss 0.895f
C5 c vss 0.693f
C2 z vss 0.834f
.ends
* Spice description of nr4v0x1
* Spice driver version 134999461
* Date 1/01/2008 at 16:57:25
* wsclib 0.13um values
.subckt nr4v0x1 a b c d vdd vss z
M1a 1b a vdd vdd pmos L=0.12U W=1.375U AS=0.364375P AD=0.364375P PS=3.28U PD=3.28U
M1b sig8 b 1b vdd pmos L=0.12U W=1.375U AS=0.364375P AD=0.364375P PS=3.28U PD=3.28U
M1c 1d c sig8 vdd pmos L=0.12U W=1.375U AS=0.364375P AD=0.364375P PS=3.28U PD=3.28U
M1d z d 1d vdd pmos L=0.12U W=1.375U AS=0.364375P AD=0.364375P PS=3.28U PD=3.28U
M2a vdd a 2a vdd pmos L=0.12U W=0.99U AS=0.26235P AD=0.26235P PS=2.51U PD=2.51U
M2b 2a b sig11 vdd pmos L=0.12U W=0.99U AS=0.26235P AD=0.26235P PS=2.51U PD=2.51U
M2c sig11 c 2c vdd pmos L=0.12U W=0.99U AS=0.26235P AD=0.26235P PS=2.51U PD=2.51U
M2d 2c d z vdd pmos L=0.12U W=0.99U AS=0.26235P AD=0.26235P PS=2.51U PD=2.51U
M3a z a vss vss nmos L=0.12U W=0.33U AS=0.08745P AD=0.08745P PS=1.19U PD=1.19U
M3b vss b z vss nmos L=0.12U W=0.33U AS=0.08745P AD=0.08745P PS=1.19U PD=1.19U
M3c z c vss vss nmos L=0.12U W=0.33U AS=0.08745P AD=0.08745P PS=1.19U PD=1.19U
M3d vss d z vss nmos L=0.12U W=0.33U AS=0.08745P AD=0.08745P PS=1.19U PD=1.19U
C4 a vss 1.510f
C3 b vss 1.102f
C6 c vss 0.817f
C5 d vss 0.806f
C2 z vss 0.935f
.ends
* Spice description of or2v0x1
* Spice driver version 134999461
* Date 1/01/2008 at 17:00:11
* wsclib 0.13um values
.subckt or2v0x1 a b vdd vss z
M01 03 a vdd vdd pmos L=0.12U W=1.155U AS=0.306075P AD=0.306075P PS=2.84U PD=2.84U
M02 sig1 a vss vss nmos L=0.12U W=0.33U AS=0.08745P AD=0.08745P PS=1.19U PD=1.19U
M03 sig1 b 03 vdd pmos L=0.12U W=1.155U AS=0.306075P AD=0.306075P PS=2.84U PD=2.84U
M04 vss b sig1 vss nmos L=0.12U W=0.33U AS=0.08745P AD=0.08745P PS=1.19U PD=1.19U
M5 vdd sig1 z vdd pmos L=0.12U W=0.99U AS=0.26235P AD=0.26235P PS=2.51U PD=2.51U
M6 vss sig1 z vss nmos L=0.12U W=0.495U AS=0.131175P AD=0.131175P PS=1.52U PD=1.52U
C4 a vss 0.464f
C5 b vss 0.507f
C1 sig1 vss 0.619f
C3 z vss 0.593f
.ends
* Spice description of or3v0x1
* Spice driver version 134999461
* Date 1/01/2008 at 17:00:59
* wsclib 0.13um values
.subckt or3v0x1 a b c vdd vss z
M01 01 a vdd vdd pmos L=0.12U W=1.54U AS=0.4081P AD=0.4081P PS=3.61U PD=3.61U
M02 sig1 a vss vss nmos L=0.12U W=0.33U AS=0.08745P AD=0.08745P PS=1.19U PD=1.19U
M03 03 b 01 vdd pmos L=0.12U W=1.54U AS=0.4081P AD=0.4081P PS=3.61U PD=3.61U
M04 vss b sig1 vss nmos L=0.12U W=0.33U AS=0.08745P AD=0.08745P PS=1.19U PD=1.19U
M05 sig1 c 03 vdd pmos L=0.12U W=1.54U AS=0.4081P AD=0.4081P PS=3.61U PD=3.61U
M06 sig1 c vss vss nmos L=0.12U W=0.33U AS=0.08745P AD=0.08745P PS=1.19U PD=1.19U
M07 vdd sig1 z vdd pmos L=0.12U W=1.045U AS=0.276925P AD=0.276925P PS=2.62U PD=2.62U
M08 vss sig1 z vss nmos L=0.12U W=0.495U AS=0.131175P AD=0.131175P PS=1.52U PD=1.52U
C4 a vss 0.544f
C5 b vss 0.535f
C6 c vss 0.625f
C1 sig1 vss 0.995f
C3 z vss 0.544f
.ends
* Spice description of or4v0x1
* Spice driver version 134999461
* Date 1/01/2008 at 17:01:43
* wsclib 0.13um values
.subckt or4v0x1 a b c d vdd vss z
M01 sig8 a vdd vdd pmos L=0.12U W=0.99U AS=0.26235P AD=0.26235P PS=2.51U PD=2.51U
M02 vdd a 05 vdd pmos L=0.12U W=0.99U AS=0.26235P AD=0.26235P PS=2.51U PD=2.51U
M03 sig1 a vss vss nmos L=0.12U W=0.33U AS=0.08745P AD=0.08745P PS=1.19U PD=1.19U
M04 n2 b sig8 vdd pmos L=0.12U W=0.99U AS=0.26235P AD=0.26235P PS=2.51U PD=2.51U
M05 05 b 08 vdd pmos L=0.12U W=0.99U AS=0.26235P AD=0.26235P PS=2.51U PD=2.51U
M06 vss b sig1 vss nmos L=0.12U W=0.33U AS=0.08745P AD=0.08745P PS=1.19U PD=1.19U
M07 10 c n2 vdd pmos L=0.12U W=0.99U AS=0.26235P AD=0.26235P PS=2.51U PD=2.51U
M08 08 c 11 vdd pmos L=0.12U W=0.99U AS=0.26235P AD=0.26235P PS=2.51U PD=2.51U
M09 sig1 c vss vss nmos L=0.12U W=0.33U AS=0.08745P AD=0.08745P PS=1.19U PD=1.19U
M10 sig1 d 10 vdd pmos L=0.12U W=0.99U AS=0.26235P AD=0.26235P PS=2.51U PD=2.51U
M11 11 d sig1 vdd pmos L=0.12U W=0.99U AS=0.26235P AD=0.26235P PS=2.51U PD=2.51U
M12 vss d sig1 vss nmos L=0.12U W=0.33U AS=0.08745P AD=0.08745P PS=1.19U PD=1.19U
M13 vdd sig1 z vdd pmos L=0.12U W=0.99U AS=0.26235P AD=0.26235P PS=2.51U PD=2.51U
M14 vss sig1 z vss nmos L=0.12U W=0.495U AS=0.131175P AD=0.131175P PS=1.52U PD=1.52U
C4 a vss 1.356f
C5 b vss 1.229f
C6 c vss 1.043f
C7 d vss 0.797f
C1 sig1 vss 1.003f
C3 z vss 0.701f
.ends
* Spice description of xnr2v0x1
* Spice driver version 134999461
* Date 1/01/2008 at 17:04:32
* wsclib 0.13um values
.subckt xnr2v0x1 a b vdd vss z
M01 z b sig3 vdd pmos L=0.12U W=0.99U AS=0.26235P AD=0.26235P PS=2.51U PD=2.51U
M02 bn sig3 z vss nmos L=0.12U W=0.495U AS=0.131175P AD=0.131175P PS=1.52U PD=1.52U
M03 sig3 a vdd vdd pmos L=0.12U W=0.99U AS=0.26235P AD=0.26235P PS=2.51U PD=2.51U
M04 vdd b bn vdd pmos L=0.12U W=0.99U AS=0.26235P AD=0.26235P PS=2.51U PD=2.51U
M05 z bn sig3 vss nmos L=0.12U W=0.495U AS=0.131175P AD=0.131175P PS=1.52U PD=1.52U
M06 vdd sig3 n1 vdd pmos L=0.12U W=1.54U AS=0.4081P AD=0.4081P PS=3.61U PD=3.61U
M07 sig3 a vss vss nmos L=0.12U W=0.495U AS=0.131175P AD=0.131175P PS=1.52U PD=1.52U
M08 n1 bn z vdd pmos L=0.12U W=1.54U AS=0.4081P AD=0.4081P PS=3.61U PD=3.61U
M09 vss b bn vss nmos L=0.12U W=0.495U AS=0.131175P AD=0.131175P PS=1.52U PD=1.52U
C4 a vss 0.389f
C2 bn vss 1.593f
C5 b vss 0.840f
C3 sig3 vss 0.618f
C6 z vss 0.627f
.ends
* Spice description of xor2v0x1
* Spice driver version 134999461
* Date 1/01/2008 at 17:06:20
* wsclib 0.13um values
.subckt xor2v0x1 a b vdd vss z
M01 04 a vdd vdd pmos L=0.12U W=0.99U AS=0.26235P AD=0.26235P PS=2.51U PD=2.51U
M02 04 a vss vss nmos L=0.12U W=0.495U AS=0.131175P AD=0.131175P PS=1.52U PD=1.52U
M03 vdd b bn vdd pmos L=0.12U W=1.485U AS=0.393525P AD=0.393525P PS=3.5U PD=3.5U
M04 z b 04 vss nmos L=0.12U W=0.495U AS=0.131175P AD=0.131175P PS=1.52U PD=1.52U
M05 vss b bn vss nmos L=0.12U W=0.495U AS=0.131175P AD=0.131175P PS=1.52U PD=1.52U
M06 bn 04 z vdd pmos L=0.12U W=1.485U AS=0.393525P AD=0.393525P PS=3.5U PD=3.5U
M07 vss 04 09 vss nmos L=0.12U W=0.66U AS=0.1749P AD=0.1749P PS=1.85U PD=1.85U
M08 z bn 04 vdd pmos L=0.12U W=0.99U AS=0.26235P AD=0.26235P PS=2.51U PD=2.51U
M09 09 bn z vss nmos L=0.12U W=0.66U AS=0.1749P AD=0.1749P PS=1.85U PD=1.85U
C6 04 vss 0.683f
C4 a vss 0.590f
C1 bn vss 0.910f
C3 b vss 1.149f
C5 z vss 0.680f
.ends

View File

@ -0,0 +1,146 @@
* PTM High Performance 45nm Metal Gate / High-K / Strained-Si
* nominal Vdd = 1.0V
.model nmos nmos level = 54
+version = 4.7.0 binunit = 1 paramchk= 1 mobmod = 0
+capmod = 2 igcmod = 1 igbmod = 1 geomod = 1
+diomod = 1 rdsmod = 0 rbodymod= 1 rgatemod= 1
+permod = 1 acnqsmod= 0 trnqsmod= 0
+tnom = 27 toxe = 1.25e-009 toxp = 1e-009 toxm = 1.25e-009
+dtox = 2.5e-010 epsrox = 3.9 wint = 5e-009 lint = 3.75e-009
+ll = 0 wl = 0 lln = 1 wln = 1
+lw = 0 ww = 0 lwn = 1 wwn = 1
+lwl = 0 wwl = 0 xpart = 0 toxref = 1.25e-009
+xl = -20e-9
+vth0 = 0.46893 k1 = 0.4 k2 = 0 k3 = 0
+k3b = 0 w0 = 2.5e-006 dvt0 = 1 dvt1 = 2
+dvt2 = 0 dvt0w = 0 dvt1w = 0 dvt2w = 0
+dsub = 0.1 minv = 0.05 voffl = 0 dvtp0 = 1e-010
+dvtp1 = 0.1 lpe0 = 0 lpeb = 0 xj = 1.4e-008
+ngate = 1e+023 ndep = 3.24e+018 nsd = 2e+020 phin = 0
+cdsc = 0 cdscb = 0 cdscd = 0 cit = 0
+voff = -0.13 nfactor = 2.22 eta0 = 0.0055 etab = 0
+vfb = -0.55 u0 = 0.054 ua = 6e-010 ub = 1.2e-018
+uc = 0 vsat = 170000 a0 = 1 ags = 0
+a1 = 0 a2 = 1 b0 = 0 b1 = 0
+keta = 0.04 dwg = 0 dwb = 0 pclm = 0.02
+pdiblc1 = 0.001 pdiblc2 = 0.001 pdiblcb = -0.005 drout = 0.5
+pvag = 1e-020 delta = 0.01 pscbe1 = 8.14e+008 pscbe2 = 1e-007
+fprout = 0.2 pdits = 0.08 pditsd = 0.23 pditsl = 2300000
+rsh = 5 rdsw = 155 rsw = 80 rdw = 80
+rdswmin = 0 rdwmin = 0 rswmin = 0 prwg = 0
+prwb = 0 wr = 1 alpha0 = 0.074 alpha1 = 0.005
+beta0 = 30 agidl = 0.0002 bgidl = 2.1e+009 cgidl = 0.0002
+egidl = 0.8 aigbacc = 0.012 bigbacc = 0.0028 cigbacc = 0.002
+nigbacc = 1 aigbinv = 0.014 bigbinv = 0.004 cigbinv = 0.004
+eigbinv = 1.1 nigbinv = 3 aigc = 0.02 bigc = 0.0025
+cigc = 0.002 aigsd = 0.02 bigsd = 0.0025 cigsd = 0.002
+nigc = 1 poxedge = 1 pigcd = 1 ntox = 1
+xrcrg1 = 12 xrcrg2 = 5
+cgso = 1.1e-010 cgdo = 1.1e-010 cgbo = 2.56e-011 cgdl = 2.653e-010
+cgsl = 2.653e-010 ckappas = 0.03 ckappad = 0.03 acde = 1
+moin = 15 noff = 0.9 voffcv = 0.02
+kt1 = -0.11 kt1l = 0 kt2 = 0.022 ute = -1.5
+ua1 = 4.31e-009 ub1 = 7.61e-018 uc1 = -5.6e-011 prt = 0
+at = 33000
+fnoimod = 1 tnoimod = 0
+jss = 0.0001 jsws = 1e-011 jswgs = 1e-010 njs = 1
+ijthsfwd= 0.01 ijthsrev= 0.001 bvs = 10 xjbvs = 1
+jsd = 0.0001 jswd = 1e-011 jswgd = 1e-010 njd = 1
+ijthdfwd= 0.01 ijthdrev= 0.001 bvd = 10 xjbvd = 1
+pbs = 1 cjs = 0.0005 mjs = 0.5 pbsws = 1
+cjsws = 5e-010 mjsws = 0.33 pbswgs = 1 cjswgs = 3e-010
+mjswgs = 0.33 pbd = 1 cjd = 0.0005 mjd = 0.5
+pbswd = 1 cjswd = 5e-010 mjswd = 0.33 pbswgd = 1
+cjswgd = 5e-010 mjswgd = 0.33 tpb = 0.005 tcj = 0.001
+tpbsw = 0.005 tcjsw = 0.001 tpbswg = 0.005 tcjswg = 0.001
+xtis = 3 xtid = 3
+dmcg = 0 dmci = 0 dmdg = 0 dmcgt = 0
+dwj = 0 xgw = 0 xgl = 0
+rshg = 0.4 gbmin = 1e-010 rbpb = 5 rbpd = 15
+rbps = 15 rbdb = 15 rbsb = 15 ngcon = 1
.model pmos pmos level = 54
+version = 4.7.0 binunit = 1 paramchk= 1 mobmod = 0
+capmod = 2 igcmod = 1 igbmod = 1 geomod = 1
+diomod = 1 rdsmod = 0 rbodymod= 1 rgatemod= 1
+permod = 1 acnqsmod= 0 trnqsmod= 0
+tnom = 27 toxe = 1.3e-009 toxp = 1e-009 toxm = 1.3e-009
+dtox = 3e-010 epsrox = 3.9 wint = 5e-009 lint = 3.75e-009
+ll = 0 wl = 0 lln = 1 wln = 1
+lw = 0 ww = 0 lwn = 1 wwn = 1
+lwl = 0 wwl = 0 xpart = 0 toxref = 1.3e-009
+xl = -20e-9
+vth0 = -0.49158 k1 = 0.4 k2 = -0.01 k3 = 0
+k3b = 0 w0 = 2.5e-006 dvt0 = 1 dvt1 = 2
+dvt2 = -0.032 dvt0w = 0 dvt1w = 0 dvt2w = 0
+dsub = 0.1 minv = 0.05 voffl = 0 dvtp0 = 1e-011
+dvtp1 = 0.05 lpe0 = 0 lpeb = 0 xj = 1.4e-008
+ngate = 1e+023 ndep = 2.44e+018 nsd = 2e+020 phin = 0
+cdsc = 0 cdscb = 0 cdscd = 0 cit = 0
+voff = -0.126 nfactor = 2.1 eta0 = 0.0055 etab = 0
+vfb = 0.55 u0 = 0.02 ua = 2e-009 ub = 5e-019
+uc = 0 vsat = 150000 a0 = 1 ags = 1e-020
+a1 = 0 a2 = 1 b0 = 0 b1 = 0
+keta = -0.047 dwg = 0 dwb = 0 pclm = 0.12
+pdiblc1 = 0.001 pdiblc2 = 0.001 pdiblcb = 3.4e-008 drout = 0.56
+pvag = 1e-020 delta = 0.01 pscbe1 = 8.14e+008 pscbe2 = 9.58e-007
+fprout = 0.2 pdits = 0.08 pditsd = 0.23 pditsl = 2300000
+rsh = 5 rdsw = 155 rsw = 75 rdw = 75
+rdswmin = 0 rdwmin = 0 rswmin = 0 prwg = 0
+prwb = 0 wr = 1 alpha0 = 0.074 alpha1 = 0.005
+beta0 = 30 agidl = 0.0002 bgidl = 2.1e+009 cgidl = 0.0002
+egidl = 0.8 aigbacc = 0.012 bigbacc = 0.0028 cigbacc = 0.002
+nigbacc = 1 aigbinv = 0.014 bigbinv = 0.004 cigbinv = 0.004
+eigbinv = 1.1 nigbinv = 3 aigc = 0.010687 bigc = 0.0012607
+cigc = 0.0008 aigsd = 0.010687 bigsd = 0.0012607 cigsd = 0.0008
+nigc = 1 poxedge = 1 pigcd = 1 ntox = 1
+xrcrg1 = 12 xrcrg2 = 5
+cgso = 1.1e-010 cgdo = 1.1e-010 cgbo = 2.56e-011 cgdl = 2.653e-010
+cgsl = 2.653e-010 ckappas = 0.03 ckappad = 0.03 acde = 1
+moin = 15 noff = 0.9 voffcv = 0.02
+kt1 = -0.11 kt1l = 0 kt2 = 0.022 ute = -1.5
+ua1 = 4.31e-009 ub1 = 7.61e-018 uc1 = -5.6e-011 prt = 0
+at = 33000
+fnoimod = 1 tnoimod = 0
+jss = 0.0001 jsws = 1e-011 jswgs = 1e-010 njs = 1
+ijthsfwd= 0.01 ijthsrev= 0.001 bvs = 10 xjbvs = 1
+jsd = 0.0001 jswd = 1e-011 jswgd = 1e-010 njd = 1
+ijthdfwd= 0.01 ijthdrev= 0.001 bvd = 10 xjbvd = 1
+pbs = 1 cjs = 0.0005 mjs = 0.5 pbsws = 1
+cjsws = 5e-010 mjsws = 0.33 pbswgs = 1 cjswgs = 3e-010
+mjswgs = 0.33 pbd = 1 cjd = 0.0005 mjd = 0.5
+pbswd = 1 cjswd = 5e-010 mjswd = 0.33 pbswgd = 1
+cjswgd = 5e-010 mjswgd = 0.33 tpb = 0.005 tcj = 0.001
+tpbsw = 0.005 tcjsw = 0.001 tpbswg = 0.005 tcjswg = 0.001
+xtis = 3 xtid = 3
+dmcg = 0 dmci = 0 dmdg = 0 dmcgt = 0
+dwj = 0 xgw = 0 xgl = 0
+rshg = 0.4 gbmin = 1e-010 rbpb = 5 rbpd = 15
+rbps = 15 rbdb = 15 rbsb = 15 ngcon = 1

View File

@ -1,5 +1,6 @@
******** BSIM-MG 105 Sample Modelcard for NMOS ********
** Source: BSIMCMG110.0.0_20160101.tar.gz
** http://bsim.berkeley.edu/models/bsimcmg/
** The BSIM-MG sample modelcard below was not extracted/obtained
** from/based on any real technologies. It should not be used for any
** other purposes except for benchmarking the implementation of BSIM-MG
@ -76,12 +77,14 @@
+ ETAMOB = 2
+ ETAQM = 0.54
+ EU = 1.2
+ FPITCH = 4.00E-08
+ HFIN = 3.00E-08
+ IGT = 2.5
+ K1RSCE = 0
+ KSATIV = 2
+ KT1 = 0
+ KT1L = 0
+ L = 2.50E-08
+ LINT = -2.00E-09
+ LPE0 = 0
+ LCDSCD = 5.00E-05
@ -117,6 +120,7 @@
+ RTH0 = 0.225
+ TBGASUB = 0.000473
+ TBGBSUB = 636
+ TFIN = 1.40E-08
+ TGIDL = -0.007
+ TMEXP = 0
+ TNOM = 25

View File

@ -1,13 +1,13 @@
******** BSIM-MG 105 Sample Modelcard for PMOS ********
** source BSIMCMG110.0.0_20160101.tar.gz
** http://bsim.berkeley.edu/models/bsimcmg/
** The BSIM-MG sample modelcard below was not extracted/obtained
** from/based on any real technologies. It should not be used for any
** other purposes except for benchmarking the implementation of BSIM-MG
** against BSIM Team's standard results
*.model pmos1 PMOS level=17
.model BSIMCMG_osdi_P BSIMCMG_va
+BULKMOD = 1
+ BULKMOD = 1
+ CGEOMOD = 0
+ TYPE = 0
+ GEOMOD = 0
@ -77,12 +77,14 @@
+ ETAMOB = 4
+ ETAQM = 0.54
+ EU = 0.05
+ FPITCH = 4.00E-08
+ HFIN = 3.00E-08
+ IGT = 3.5
+ K1RSCE = 0
+ KSATIV = 1.592
+ KT1 = 0.08387
+ KT1L = 0
+ L = 2.50E-08
+ LINT = -2.5E-09
+ LPE0 = 0
+ LCDSCD = 0
@ -118,6 +120,7 @@
+ RTH0 = 0.15
+ TBGASUB = 0.000473
+ TBGBSUB = 636
+ TFIN = 1.40E-08
+ TGIDL = -0.01
+ TMEXP = 0
+ TNOM = 25

View File

@ -21,7 +21,8 @@ NN1 vout vin 0 0 BSIMCMG_osdi_N
* pre_osdi ../osdi_libs/bsimcmg.osdi
set xbrushwidth=3
run
plot v(vout) v(vin)
let gain:10 = deriv(-V(vout))/10
plot v(vout) gain:10
.endc
.end

View File

@ -0,0 +1,287 @@
***************************************************************
* Comments for the user:
* The VBIC Model includes the self heating effect and the user can switch selfheating on or off.
* a) no self heating: set Rth = 0
* b) with self heating: set Rth=80K/W + Rth_PCB (customer)
* Note: Rth = 80 K/W includes only the thermal resistance of die and package and
* the thermal resistance of the customer PCB must be added (Rth=80K/W + Rth_PCB)
* Infineon Technologies AG
* VBIC MODEL IN SPICE 2G6 SYNTAX
* VALID UP TO 10 GHZ
* >>> BFP780 <<<
* (C) 2015 Infineon Technologies AG
* Version 1.1 October 2015
***************************************************************
*.OPTION TNOM=25, GMIN= 1.00e-12
*BFP780 C B E1 E2
.SUBCKT BFP780 1 2 3 4
*
CCEPAR 11 33 800E-015
*
LEx 30 35 3E-011
LBx 20 2 3E-011
LCx 10 1 3E-011
*
CBPAD 22 44 30E-015
CCPAD 11 44 30E-015
CEPAD 33 44 30E-015
*
LB 22 20 777E-12
LC 10 11 777E-12
*
CBEPCK 20 30 5.703E-015
CBCPCK 10 20 1.497E-014
CCEPCK 10 30 6.032E-014
*
RE1 35 3 1E-03
RE2 35 4 1E-03
*
Rsub1 44 30 0.2144
Rps 44 33 0.07306
*
D1 33 22 Diode_fb
D2 44 22 Diode_fbd
*
.MODEL Diode_fb D(
+ IS=3.5E-015
+ N=1
+ CJO=10e-15
+ RS=6.1
+ Tnom=25)
*
.MODEL Diode_fbd D(
+ IS=1E-015
+ N=1
+ CJO=10E-15
+ RS=1
+ Tnom=25)
*
Q1 11 22 33 44 M_BFP780
*
.ENDS BFP780
.MODEL M_BFP780 NPN (Level=4
+ Tnom=25
+ Cbeo=2.47E-012
+ Cje=561.3E-015
+ Pe=0.7
+ Me=0.333
+ Aje=-1
+ Wbe=1
+ Cbco=10E-015
+ Cjc=668.6E-015
+ Pc=0.54
+ Mc=0.333
+ Ajc=-1
+ Cjep=2.616E-015
+ Cjcp=900E-015
+ Ps=0.6
+ Ms=0.3
+ Ajs=-0.5
+ Fc=0.94
+ Vef=545.4
+ Ver=3.291
+ Is=2.3E-015
+ Nf=0.9855
+ Ibei=1.893E-018
+ Nei=0.9399
+ Iben=4.77E-015
+ Nen=1.361
+ Ikf=1
+ Nr=0.9912
+ Ibci=157.5E-018
+ Nci=1.1
+ Ibcn=4.929E-015
+ Ncn=1.463
+ Ikr=0.01178
+ Wsp=1
+ Isp=1E-015
+ Nfp=1
+ Ibcip=1E-015
+ Ncip=1.029
+ Ibcnp=1E-015
+ Ncnp=1
+ Ikp=1E-3
+ Ibeip=1E-015
+ Ibenp=1E-015
+ Re=0.15
+ Rcx=0.01
+ Rci=2.665
+ Qco=1E-015
+ Vo=0.0005022
+ Gamm=5.659E-012
+ Hrcf=0.21
+ Rbx=5
+ Rbi=1.964
+ Rbp=265.5
+ Rs=26.56
+ Avc1=3.97
+ Avc2=29.52
+ Tf=1.6E-012
+ Qtf=50E-3
+ Xtf=30
+ Vtf=0.7
+ Itf=1
+ Tr=1E-015
+ Td=500E-015
+ Cth=0
+ Rth=0
+ Ea=1.12
+ Eaie=1.12
+ Eaic=1.12
+ Eais=1
+ Eane=1.12
+ Eanc=1.12
+ Eans=1
+ Xre=0
+ Xrb=0
+ Xrc=0
+ Xrs=0
+ Xvo=0
+ Xis=-1.631
+ Xii=0
+ Xin=0
+ Tnf=0
+ Tavc=0.002613
+ Kfn=0
+ Afn=1
+ Bfn=1 )
***************************************************************
*
*.ENDS BFP780
***************************************************************
* Comments for the user:
* The VBIC Model includes the self heating effect and the user can switch selfheating on or off.
* a) no self heating: set Rth = 0
* b) with self heating: set Rth=20K/W + Rth_PCB (customer)
* Note: Rth = 20 K/W includes only the thermal resistance of die and package and
* the thermal resistance of the customer PCB must be added (Rth=20K/W + Rth_PCB)
* Infineon Technologies AG
* VBIC MODEL
* VALID UP TO 6 GHZ
* >>> BFQ790 <<<
* (C) 2015 Infineon Technologies AG
* Version 1.0 Juni 2015
***************************************************************
*.OPTION TNOM=25, GMIN= 1.00e-12
*BFQ790 C B E
* without access to the external thermal node (Rth to be adjusted by the customer in the model parameter list for the transistor
.SUBCKT BFQ790 1 2 3
*
* with access to external thermal node
*.SUBCKT BFQ790 1 2 3 55
*
CCSPAR 11 44 1.375E-012
LEx 30 3 4.36882E-011
LBx 20 2 2.77681E-011
LCx 10 1 4.265E-011
CBEPCK 20 30 1.105E-013
CBCPCK 10 20 1E-014
CCEPCK 10 30 1E-015
LB 222 20 1.02449E-009
LC 10 11 1.89901E-009
*
RBL 222 22 45
CBL 222 22 3E-011
*
Rsub1 44 30 0.000500184
Rps 44 33 0.102733
*
*
* without access to the external thermal node
Q1 11 22 33 44 M_BFQ790
*
* with access to the thermal node
* Q1 11 22 33 44 55 M_BFQ790
*
.MODEL M_BFQ790 NPN Level=4(
+ Tnom=25
+ Cbeo=9.31E-012
+ Cje=7.693E-013
+ Pe=0.5892
+ Me=0.3115
+ Aje=-0.5
+ Wbe=1
+ Cbco=1.966E-013
+ Cjc=1E-015
+ Pc=0.5095
+ Mc=0.2797
+ Ajc=-0.5
+ Cjep=1.875E-012
+ Cjcp=2.067E-012
+ Ps=0.5086
+ Ms=0.2865
+ Ajs=-0.5
+ Fc=0.93
+ Vef=615.1
+ Ver=5.61838
+ Is=9.704E-015
+ Nf=1.001
+ Ibei=5E-017
+ Nei=1.013
+ Iben=3.609E-014
+ Nen=1.46
+ Ikf=2
+ Nr=0.9958
+ Ibci=1.001E-017
+ Nci=1.015
+ Ibcn=2.918E-014
+ Ncn=1.399
+ Ikr=0.2301
+ Wsp=1
+ Isp=1E-015
+ Nfp=1
+ Ibcip=2E-017
+ Ncip=1
+ Ibcnp=1.7E-015
+ Ncnp=1.67
+ Ikp=0.0002
+ Ibeip=7E-017
+ Ibenp=2.4E-014
+ Re=0.2
+ Rcx=0.02559
+ Rci=1.168
+ Qco=4E-015
+ Vo=0.4234
+ Gamm=2.199E-012
+ Hrcf=0.1907
+ Rbx=0.2825
+ Rbi=1.868
+ Rbp=0.001
+ Rs=10
+ Avc1=1
+ Avc2=25.84
+ Tf=3E-012
+ Qtf=0.6758
+ Xtf=0.01293
+ Vtf=0.5
+ Itf=0.1948
+ Tr=1E-015
+ Td=1E-015
+ Cth=0
+ Rth=0
+ Ea=1.12
+ Eaie=1.12
+ Eaic=1.12
+ Eais=1.12
+ Eane=1.12
+ Eanc=1.12
+ Eans=1.12
+ Xre=0
+ Xrb=0
+ Xrc=0
+ Xrs=0
+ Xvo=0
+ Xis=1.907
+ Xii=4.963
+ Xin=-2.837
+ Tnf=1E-006
+ Tavc=0.006705
+ Kfn=0
+ Afn=1
+ Bfn=1 )
***************************************************************
*
.ENDS BFQ790

View File

@ -0,0 +1,23 @@
VBIC Output Test Ic=f(Vc,Ib) vs self heating
vc c 0 0
ib 0 b 10u
ve e 0 0
vs s 0 0
vc1 c c1 0
vb1 b b1 0
ve1 e e1 0
vs1 s s1 0
.temp 27
Q1 c1 b1 e1 s1 dt M_BFP780 area=1
.include Infineon_VBIC_RTH_0.lib
.control
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

@ -193,7 +193,13 @@ ngspice_LDADD += \
maths/misc/libmathmisc.la \
maths/fft/libmathfft.la \
maths/poly/libpoly.la \
maths/ni/libni.la \
maths/ni/libni.la
if KLU_WANTED
ngspice_LDADD += maths/KLU/libKLU.la
endif
ngspice_LDADD += \
maths/sparse/libsparse.la \
misc/libmisc.la
@ -317,6 +323,10 @@ ngmultidec_LDADD = \
maths/sparse/libsparse.la \
misc/libmisc.la
if KLU_WANTED
ngmultidec_LDADD += maths/KLU/libKLU.la
endif
## ngmakeidx:
@ -469,9 +479,12 @@ libspice_la_LIBADD += \
ciderlib/support/libcidersuprt.la
endif
if OSDI_WANTED
libspice_la_LIBADD += osdi/libosdi.la
libspice_la_LIBADD += osdi/libosdi.la
endif
if KLU_WANTED
libspice_la_LIBADD += maths/KLU/libKLU.la
endif
libspice_la_LIBADD += \
@ -597,6 +610,10 @@ if OSDI_WANTED
libngspice_la_LIBADD += osdi/libosdi.la
endif
if KLU_WANTED
libngspice_la_LIBADD += maths/KLU/libKLU.la
endif
libngspice_la_LIBADD += \
maths/deriv/libderiv.la \
maths/cmaths/libcmaths.la \

View File

@ -116,30 +116,54 @@ NUMDadmittance(ONEdevice *pDevice, double omega, SPcomplex *yd)
pDevice->rhs[pNode->pEqn] -= pEdge->dJpDpsiP1;
}
ONE_jacLoad(pDevice);
spSetComplex(pDevice->matrix);
for (index = 1; index < pDevice->numNodes; index++) {
pElem = pDevice->elemArray[index];
if (pElem->elemType == SEMICON) {
for (i = 0; i <= 1; i++) {
pNode = pElem->pNodes[i];
if (pNode->nodeType != CONTACT) {
spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -0.5 * pElem->dx * omega);
spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, 0.5 * pElem->dx * omega);
}
}
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = KLUMatrixComplex ;
} else {
#endif
spSetComplex (pDevice->matrix->SPmatrix) ;
for (index = 1; index < pDevice->numNodes; index++) {
pElem = pDevice->elemArray[index];
if (pElem->elemType == SEMICON) {
for (i = 0; i <= 1; i++) {
pNode = pElem->pNodes[i];
if (pNode->nodeType != CONTACT) {
spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -0.5 * pElem->dx * omega);
spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, 0.5 * pElem->dx * omega);
}
}
}
}
#ifdef KLU
}
#endif
pDevice->pStats->loadTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
/* FACTOR */
startTime = SPfrontEnd->IFseconds();
spFactor(pDevice->matrix);
#ifdef KLU
SMPluFacKLUforCIDER (pDevice->matrix) ;
#else
SMPcLUfac(pDevice->matrix, 0);
#endif
pDevice->pStats->factorTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
/* SOLVE */
startTime = SPfrontEnd->IFseconds();
spSolve(pDevice->matrix, pDevice->rhs, solutionReal,
pDevice->rhsImag, solutionImag);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, solutionReal, pDevice->rhsImag, solutionImag) ;
#else
SMPcSolveForCIDER (pDevice->matrix, pDevice->rhs, solutionReal, pDevice->rhsImag, solutionImag) ;
#endif
pDevice->pStats->solveTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
}
/* MISC */
@ -288,30 +312,54 @@ NBJTadmittance(ONEdevice *pDevice, double omega, SPcomplex *yIeVce,
pDevice->rhs[pNode->nEqn] -= pEdge->dJnDpsiP1;
pDevice->rhs[pNode->pEqn] -= pEdge->dJpDpsiP1;
}
spSetComplex(pDevice->matrix);
for (index = 1; index < pDevice->numNodes; index++) {
pElem = pDevice->elemArray[index];
if (pElem->elemType == SEMICON) {
for (i = 0; i <= 1; i++) {
pNode = pElem->pNodes[i];
if (pNode->nodeType != CONTACT) {
spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -0.5 * pElem->dx * omega);
spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, 0.5 * pElem->dx * omega);
}
}
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = KLUMatrixComplex ;
} else {
#endif
spSetComplex (pDevice->matrix->SPmatrix) ;
for (index = 1; index < pDevice->numNodes; index++) {
pElem = pDevice->elemArray[index];
if (pElem->elemType == SEMICON) {
for (i = 0; i <= 1; i++) {
pNode = pElem->pNodes[i];
if (pNode->nodeType != CONTACT) {
spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -0.5 * pElem->dx * omega);
spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, 0.5 * pElem->dx * omega);
}
}
}
}
#ifdef KLU
}
#endif
pDevice->pStats->loadTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
/* FACTOR */
startTime = SPfrontEnd->IFseconds();
spFactor(pDevice->matrix);
#ifdef KLU
SMPluFacKLUforCIDER (pDevice->matrix) ;
#else
SMPcLUfac(pDevice->matrix, 0);
#endif
pDevice->pStats->factorTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
/* SOLVE */
startTime = SPfrontEnd->IFseconds();
spSolve(pDevice->matrix, pDevice->rhs, solutionReal,
pDevice->rhsImag, solutionImag);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, solutionReal, pDevice->rhsImag, solutionImag) ;
#else
SMPcSolveForCIDER (pDevice->matrix, pDevice->rhs, solutionReal, pDevice->rhsImag, solutionImag) ;
#endif
pDevice->pStats->solveTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
/* MISC */
@ -345,8 +393,13 @@ NBJTadmittance(ONEdevice *pDevice, double omega, SPcomplex *yIeVce,
/* SOLVE */
startTime = SPfrontEnd->IFseconds();
spSolve(pDevice->matrix, pDevice->rhs, solutionReal,
pDevice->rhsImag, solutionImag);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, solutionReal, pDevice->rhsImag, solutionImag) ;
#else
SMPcSolveForCIDER (pDevice->matrix, pDevice->rhs, solutionReal, pDevice->rhsImag, solutionImag) ;
#endif
pDevice->pStats->solveTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
}
/* MISC */
@ -418,7 +471,11 @@ ONEsorSolve(ONEdevice *pDevice, double *xReal, double *xImag, double omega)
rhsSOR[index] += pDevice->rhs[index];
}
/* compute xReal(k+1). solution stored in rhsSOR */
spSolve(pDevice->matrix, rhsSOR, rhsSOR, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsSOR, rhsSOR, NULL, NULL) ;
#else
SMPsolve(pDevice->matrix, rhsSOR, rhsSOR);
#endif
/* modify solution when wRelax is not 1 */
if (wRelax != 1) {
@ -454,8 +511,12 @@ ONEsorSolve(ONEdevice *pDevice, double *xReal, double *xImag, double omega)
}
}
/* compute xImag(k+1) */
spSolve(pDevice->matrix, rhsSOR, rhsSOR,
NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsSOR, rhsSOR, NULL, NULL) ;
#else
SMPsolve(pDevice->matrix, rhsSOR, rhsSOR);
#endif
/* modify solution when wRelax is not 1 */
if (wRelax != 1) {
for (index = 1; index <= numEqns; index++) {
@ -516,25 +577,44 @@ NUMDys(ONEdevice *pDevice, SPcomplex *s, SPcomplex *yd)
pDevice->rhs[pNode->nEqn] -= pEdge->dJnDpsiP1;
pDevice->rhs[pNode->pEqn] -= pEdge->dJpDpsiP1;
}
spSetComplex(pDevice->matrix);
for (index = 1; index < pDevice->numNodes; index++) {
pElem = pDevice->elemArray[index];
if (pElem->elemType == SEMICON) {
for (i = 0; i <= 1; i++) {
pNode = pElem->pNodes[i];
if (pNode->nodeType != CONTACT) {
CMPLX_MULT_SCALAR(temp, cOmega, 0.5 * pElem->dx);
spADD_COMPLEX_ELEMENT(pNode->fNN, -temp.real, -temp.imag);
spADD_COMPLEX_ELEMENT(pNode->fPP, temp.real, temp.imag);
}
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = KLUMatrixComplex ;
} else {
#endif
spSetComplex (pDevice->matrix->SPmatrix) ;
for (index = 1; index < pDevice->numNodes; index++) {
pElem = pDevice->elemArray[index];
if (pElem->elemType == SEMICON) {
for (i = 0; i <= 1; i++) {
pNode = pElem->pNodes[i];
if (pNode->nodeType != CONTACT) {
CMPLX_MULT_SCALAR(temp, cOmega, 0.5 * pElem->dx);
spADD_COMPLEX_ELEMENT(pNode->fNN, -temp.real, -temp.imag);
spADD_COMPLEX_ELEMENT(pNode->fPP, temp.real, temp.imag);
}
}
}
}
#ifdef KLU
}
#endif
#ifdef KLU
SMPluFacKLUforCIDER (pDevice->matrix) ;
#else
SMPcLUfac (pDevice->matrix, 0) ;
#endif
spFactor(pDevice->matrix);
spSolve(pDevice->matrix, pDevice->rhs, solutionReal,
pDevice->rhsImag, solutionImag);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, solutionReal, pDevice->rhsImag, solutionImag) ;
#else
SMPcSolveForCIDER (pDevice->matrix, pDevice->rhs, solutionReal, pDevice->rhsImag, solutionImag) ;
#endif
pElem = pDevice->elemArray[1];
pNode = pElem->pLeftNode;
@ -584,24 +664,45 @@ NBJTys(ONEdevice *pDevice, SPcomplex *s, SPcomplex *yIeVce,
pDevice->rhs[pNode->nEqn] -= pEdge->dJnDpsiP1;
pDevice->rhs[pNode->pEqn] -= pEdge->dJpDpsiP1;
}
spSetComplex(pDevice->matrix);
for (index = 1; index < pDevice->numNodes; index++) {
pElem = pDevice->elemArray[index];
if (pElem->elemType == SEMICON) {
for (i = 0; i <= 1; i++) {
pNode = pElem->pNodes[i];
if (pNode->nodeType != CONTACT) {
CMPLX_MULT_SCALAR(temp, cOmega, 0.5 * pElem->dx);
spADD_COMPLEX_ELEMENT(pNode->fNN, -temp.real, -temp.imag);
spADD_COMPLEX_ELEMENT(pNode->fPP, temp.real, temp.imag);
}
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = KLUMatrixComplex ;
} else {
#endif
spSetComplex (pDevice->matrix->SPmatrix) ;
for (index = 1; index < pDevice->numNodes; index++) {
pElem = pDevice->elemArray[index];
if (pElem->elemType == SEMICON) {
for (i = 0; i <= 1; i++) {
pNode = pElem->pNodes[i];
if (pNode->nodeType != CONTACT) {
CMPLX_MULT_SCALAR(temp, cOmega, 0.5 * pElem->dx);
spADD_COMPLEX_ELEMENT(pNode->fNN, -temp.real, -temp.imag);
spADD_COMPLEX_ELEMENT(pNode->fPP, temp.real, temp.imag);
}
}
}
}
}
spFactor(pDevice->matrix);
spSolve(pDevice->matrix, pDevice->rhs, solutionReal,
pDevice->rhsImag, solutionImag);
#ifdef KLU
}
#endif
#ifdef KLU
SMPluFacKLUforCIDER (pDevice->matrix) ;
#else
SMPcLUfac (pDevice->matrix, 0) ;
#endif
#ifdef KLU
SMPsolveKLUforCIDER(pDevice->matrix, pDevice->rhs, solutionReal, pDevice->rhsImag, solutionImag);
#else
SMPcSolveForCIDER (pDevice->matrix, pDevice->rhs, solutionReal, pDevice->rhsImag, solutionImag) ;
#endif
pElem = pDevice->elemArray[1];
pNode = pElem->pLeftNode;
y = computeAdmittance(pNode, FALSE, solutionReal, solutionImag, &cOmega);
@ -624,8 +725,12 @@ NBJTys(ONEdevice *pDevice, SPcomplex *s, SPcomplex *yIeVce,
}
/* don't need to LU factor the jacobian since it exists */
spSolve(pDevice->matrix, pDevice->rhs, solutionReal,
pDevice->rhsImag, solutionImag);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, solutionReal, pDevice->rhsImag, solutionImag) ;
#else
SMPcSolveForCIDER (pDevice->matrix, pDevice->rhs, solutionReal, pDevice->rhsImag, solutionImag) ;
#endif
pElem = pDevice->elemArray[1];
pNode = pElem->pLeftNode;
y = computeAdmittance(pNode, FALSE, solutionReal, solutionImag, &cOmega);

View File

@ -42,7 +42,12 @@ NUMDconductance(ONEdevice *pDevice, BOOLEAN tranAnalysis,
pDevice->rhs[pNode->pEqn] = -pEdge->dJpDpsiP1;
}
incVpn = pDevice->dcDeltaSolution;
spSolve(pDevice->matrix, pDevice->rhs, incVpn, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVpn, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVpn) ;
#endif
pElem = pDevice->elemArray[1];
pNode = pElem->pRightNode;
@ -95,7 +100,12 @@ NBJTconductance(ONEdevice *pDevice, BOOLEAN tranAnalysis, double *intCoeff,
pDevice->rhs[pNode->pEqn] = -pEdge->dJpDpsiP1;
}
incVce = pDevice->dcDeltaSolution;
spSolve(pDevice->matrix, pDevice->rhs, incVce, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVce, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVce) ;
#endif
/* zero the rhs before loading in the new rhs base contribution */
for (index = 1; index <= pDevice->numEqns; index++) {
@ -114,7 +124,12 @@ NBJTconductance(ONEdevice *pDevice, BOOLEAN tranAnalysis, double *intCoeff,
}
incVbe = pDevice->copiedSolution;
spSolve(pDevice->matrix, pDevice->rhs, incVbe, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVbe, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVbe) ;
#endif
pElem = pDevice->elemArray[1];/* first element */
pEdge = pElem->pEdge;

View File

@ -15,6 +15,10 @@ Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
#include "ngspice/cidersupt.h"
#include "../../maths/misc/bernoull.h"
#ifdef KLU
#include "ngspice/klu-binding.h"
#endif
/* functions to setup and solve the continuity equations */
/* Both continuity equations are solved */
@ -39,21 +43,76 @@ ONE_jacBuild(ONEdevice *pDevice)
pNode = pElem->pNodes[index];
/* get poisson pointer */
psiEqn = pNode->psiEqn;
pNode->fPsiPsi = spGetElement(matrix, psiEqn, psiEqn);
#ifdef KLU
pNode->fPsiPsi = SMPmakeEltKLUforCIDER (matrix, psiEqn, psiEqn) ;
pNode->fPsiPsiBinding = NULL ;
#else
pNode->fPsiPsi = SMPmakeElt(matrix, psiEqn, psiEqn);
#endif
if (pElem->elemType == SEMICON) {
/* get continuity-coupling terms */
nEqn = pNode->nEqn;
pEqn = pNode->pEqn;
/* pointers for additional terms */
pNode->fPsiN = spGetElement(matrix, psiEqn, nEqn);
pNode->fPsiP = spGetElement(matrix, psiEqn, pEqn);
pNode->fNPsi = spGetElement(matrix, nEqn, psiEqn);
pNode->fNN = spGetElement(matrix, nEqn, nEqn);
pNode->fNP = spGetElement(matrix, nEqn, pEqn);
pNode->fPPsi = spGetElement(matrix, pEqn, psiEqn);
pNode->fPP = spGetElement(matrix, pEqn, pEqn);
pNode->fPN = spGetElement(matrix, pEqn, nEqn);
#ifdef KLU
pNode->fPsiN = SMPmakeEltKLUforCIDER (matrix, psiEqn, nEqn) ;
pNode->fPsiNBinding = NULL ;
#else
pNode->fPsiN = SMPmakeElt(matrix, psiEqn, nEqn);
#endif
#ifdef KLU
pNode->fPsiP = SMPmakeEltKLUforCIDER (matrix, psiEqn, pEqn) ;
pNode->fPsiPBinding = NULL ;
#else
pNode->fPsiP = SMPmakeElt(matrix, psiEqn, pEqn);
#endif
#ifdef KLU
pNode->fNPsi = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqn) ;
pNode->fNPsiBinding = NULL ;
#else
pNode->fNPsi = SMPmakeElt(matrix, nEqn, psiEqn);
#endif
#ifdef KLU
pNode->fNN = SMPmakeEltKLUforCIDER (matrix, nEqn, nEqn) ;
pNode->fNNBinding = NULL ;
#else
pNode->fNN = SMPmakeElt(matrix, nEqn, nEqn);
#endif
#ifdef KLU
pNode->fNP = SMPmakeEltKLUforCIDER (matrix, nEqn, pEqn) ;
pNode->fNPBinding = NULL ;
#else
pNode->fNP = SMPmakeElt(matrix, nEqn, pEqn);
#endif
#ifdef KLU
pNode->fPPsi = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqn) ;
pNode->fPPsiBinding = NULL ;
#else
pNode->fPPsi = SMPmakeElt(matrix, pEqn, psiEqn);
#endif
#ifdef KLU
pNode->fPP = SMPmakeEltKLUforCIDER (matrix, pEqn, pEqn) ;
pNode->fPPBinding = NULL ;
#else
pNode->fPP = SMPmakeElt(matrix, pEqn, pEqn);
#endif
#ifdef KLU
pNode->fPN = SMPmakeEltKLUforCIDER (matrix, pEqn, nEqn) ;
pNode->fPNBinding = NULL ;
#else
pNode->fPN = SMPmakeElt(matrix, pEqn, nEqn);
#endif
} else {
nEqn = 0;
pEqn = 0;
@ -73,34 +132,231 @@ ONE_jacBuild(ONEdevice *pDevice)
/* now terms to couple to adjacent nodes */
pNode = pElem->pLeftNode;
pNode->fPsiPsiiP1 = spGetElement(matrix, psiEqnL, psiEqnR);
#ifdef KLU
pNode->fPsiPsiiP1 = SMPmakeEltKLUforCIDER (matrix, psiEqnL, psiEqnR) ;
pNode->fPsiPsiiP1Binding = NULL ;
#else
pNode->fPsiPsiiP1 = SMPmakeElt(matrix, psiEqnL, psiEqnR);
#endif
if (pElem->elemType == SEMICON) {
/* pointers for additional terms */
pNode->fNPsiiP1 = spGetElement(matrix, nEqnL, psiEqnR);
pNode->fNNiP1 = spGetElement(matrix, nEqnL, nEqnR);
pNode->fPPsiiP1 = spGetElement(matrix, pEqnL, psiEqnR);
pNode->fPPiP1 = spGetElement(matrix, pEqnL, pEqnR);
#ifdef KLU
pNode->fNPsiiP1 = SMPmakeEltKLUforCIDER (matrix, nEqnL, psiEqnR) ;
pNode->fNPsiiP1Binding = NULL ;
#else
pNode->fNPsiiP1 = SMPmakeElt(matrix, nEqnL, psiEqnR);
#endif
#ifdef KLU
pNode->fNNiP1 = SMPmakeEltKLUforCIDER (matrix, nEqnL, nEqnR) ;
pNode->fNNiP1Binding = NULL ;
#else
pNode->fNNiP1 = SMPmakeElt(matrix, nEqnL, nEqnR);
#endif
#ifdef KLU
pNode->fPPsiiP1 = SMPmakeEltKLUforCIDER (matrix, pEqnL, psiEqnR) ;
pNode->fPPsiiP1Binding = NULL ;
#else
pNode->fPPsiiP1 = SMPmakeElt(matrix, pEqnL, psiEqnR);
#endif
#ifdef KLU
pNode->fPPiP1 = SMPmakeEltKLUforCIDER (matrix, pEqnL, pEqnR) ;
pNode->fPPiP1Binding = NULL ;
#else
pNode->fPPiP1 = SMPmakeElt(matrix, pEqnL, pEqnR);
#endif
if (AvalancheGen) {
pNode->fNPiP1 = spGetElement(matrix, nEqnL, pEqnR);
pNode->fPNiP1 = spGetElement(matrix, pEqnL, nEqnR);
#ifdef KLU
pNode->fNPiP1 = SMPmakeEltKLUforCIDER (matrix, nEqnL, pEqnR) ;
pNode->fNPiP1Binding = NULL ;
#else
pNode->fNPiP1 = SMPmakeElt(matrix, nEqnL, pEqnR);
#endif
#ifdef KLU
pNode->fPNiP1 = SMPmakeEltKLUforCIDER (matrix, pEqnL, nEqnR) ;
pNode->fPNiP1Binding = NULL ;
#else
pNode->fPNiP1 = SMPmakeElt(matrix, pEqnL, nEqnR);
#endif
}
}
pNode = pElem->pRightNode;
pNode->fPsiPsiiM1 = spGetElement(matrix, psiEqnR, psiEqnL);
#ifdef KLU
pNode->fPsiPsiiM1 = SMPmakeEltKLUforCIDER (matrix, psiEqnR, psiEqnL) ;
pNode->fPsiPsiiM1Binding = NULL ;
#else
pNode->fPsiPsiiM1 = SMPmakeElt(matrix, psiEqnR, psiEqnL);
#endif
if (pElem->elemType == SEMICON) {
/* pointers for additional terms */
pNode->fNPsiiM1 = spGetElement(matrix, nEqnR, psiEqnL);
pNode->fNNiM1 = spGetElement(matrix, nEqnR, nEqnL);
pNode->fPPsiiM1 = spGetElement(matrix, pEqnR, psiEqnL);
pNode->fPPiM1 = spGetElement(matrix, pEqnR, pEqnL);
#ifdef KLU
pNode->fNPsiiM1 = SMPmakeEltKLUforCIDER (matrix, nEqnR, psiEqnL) ;
pNode->fNPsiiM1Binding = NULL ;
#else
pNode->fNPsiiM1 = SMPmakeElt(matrix, nEqnR, psiEqnL);
#endif
#ifdef KLU
pNode->fNNiM1 = SMPmakeEltKLUforCIDER (matrix, nEqnR, nEqnL) ;
pNode->fNNiM1Binding = NULL ;
#else
pNode->fNNiM1 = SMPmakeElt(matrix, nEqnR, nEqnL);
#endif
#ifdef KLU
pNode->fPPsiiM1 = SMPmakeEltKLUforCIDER (matrix, pEqnR, psiEqnL) ;
pNode->fPPsiiM1Binding = NULL ;
#else
pNode->fPPsiiM1 = SMPmakeElt(matrix, pEqnR, psiEqnL);
#endif
#ifdef KLU
pNode->fPPiM1 = SMPmakeEltKLUforCIDER (matrix, pEqnR, pEqnL) ;
pNode->fPPiM1Binding = NULL ;
#else
pNode->fPPiM1 = SMPmakeElt(matrix, pEqnR, pEqnL);
#endif
if (AvalancheGen) {
pNode->fNPiM1 = spGetElement(matrix, nEqnR, pEqnL);
pNode->fPNiM1 = spGetElement(matrix, pEqnR, nEqnL);
#ifdef KLU
pNode->fNPiM1 = SMPmakeEltKLUforCIDER (matrix, nEqnR, pEqnL) ;
pNode->fNPiM1Binding = NULL ;
#else
pNode->fNPiM1 = SMPmakeElt(matrix, nEqnR, pEqnL);
#endif
#ifdef KLU
pNode->fPNiM1 = SMPmakeEltKLUforCIDER (matrix, pEqnR, nEqnL) ;
pNode->fPNiM1Binding = NULL ;
#else
pNode->fPNiM1 = SMPmakeElt(matrix, pEqnR, nEqnL);
#endif
}
}
}
}
#ifdef KLU
void
ONEbindCSC (ONEdevice *pDevice)
{
ONEelem *pElem;
ONEnode *pNode;
int index, eIndex;
int psiEqn, nEqn, pEqn; /* scratch for deref'd eqn numbers */
int psiEqnL=0, nEqnL=0, pEqnL=0;
int psiEqnR=0, nEqnR=0, pEqnR=0;
BindElementKLUforCIDER i, *matched, *BindStruct, *BindStructCSC ;
size_t nz ;
BindStruct = pDevice->matrix->SMPkluMatrix->KLUmatrixBindStructForCIDER ;
nz = pDevice->matrix->SMPkluMatrix->KLUmatrixNZ ;
BindStructCSC = (BindElementKLUforCIDER *) malloc (nz * sizeof (BindElementKLUforCIDER)) ;
for (index = 0 ; index < (int)nz ; index++) {
BindStructCSC [index] = BindStruct [index] ;
}
for (eIndex = 1; eIndex < pDevice->numNodes; eIndex++) {
pElem = pDevice->elemArray[eIndex];
/* first the self terms */
for (index = 0; index <= 1; index++) {
pNode = pElem->pNodes[index];
/* get poisson pointer */
psiEqn = pNode->psiEqn;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsi, fPsiPsiBinding, psiEqn, psiEqn) ;
if (pElem->elemType == SEMICON) {
/* get continuity-coupling terms */
nEqn = pNode->nEqn;
pEqn = pNode->pEqn;
/* pointers for additional terms */
CREATE_KLU_BINDING_TABLE_CIDER(fPsiN, fPsiNBinding, psiEqn, nEqn) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiP, fPsiPBinding, psiEqn, pEqn) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsi, fNPsiBinding, nEqn, psiEqn) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNN, fNNBinding, nEqn, nEqn) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNP, fNPBinding, nEqn, pEqn) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsi, fPPsiBinding, pEqn, psiEqn) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPP, fPPBinding, pEqn, pEqn) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPN, fPNBinding, pEqn, nEqn) ;
} else {
nEqn = 0;
pEqn = 0;
}
/* save indices */
if (index == 0) { /* left node */
psiEqnL = psiEqn;
nEqnL = nEqn;
pEqnL = pEqn;
} else {
psiEqnR = psiEqn;
nEqnR = nEqn;
pEqnR = pEqn;
}
}
/* now terms to couple to adjacent nodes */
pNode = pElem->pLeftNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsiiP1, fPsiPsiiP1Binding, psiEqnL, psiEqnR) ;
if (pElem->elemType == SEMICON) {
/* pointers for additional terms */
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiiP1, fNPsiiP1Binding, nEqnL, psiEqnR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNNiP1, fNNiP1Binding, nEqnL, nEqnR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiiP1, fPPsiiP1Binding, pEqnL, psiEqnR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPiP1, fPPiP1Binding, pEqnL, pEqnR) ;
if (AvalancheGen) {
CREATE_KLU_BINDING_TABLE_CIDER(fNPiP1, fNPiP1Binding, nEqnL, pEqnR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPNiP1, fPNiP1Binding, pEqnL, nEqnR) ;
}
}
pNode = pElem->pRightNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsiiM1, fPsiPsiiM1Binding, psiEqnR, psiEqnL) ;
if (pElem->elemType == SEMICON) {
/* pointers for additional terms */
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiiM1, fNPsiiM1Binding, nEqnR, psiEqnL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNNiM1, fNNiM1Binding, nEqnR, nEqnL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiiM1, fPPsiiM1Binding, pEqnR, psiEqnL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPiM1, fPPiM1Binding, pEqnR, pEqnL) ;
if (AvalancheGen) {
CREATE_KLU_BINDING_TABLE_CIDER(fNPiM1, fNPiM1Binding, nEqnR, pEqnL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPNiM1, fPNiM1Binding, pEqnR, nEqnL) ;
}
}
}
free (BindStructCSC) ;
}
#endif
void
ONE_sysLoad(ONEdevice *pDevice, BOOLEAN tranAnalysis,
@ -131,7 +387,17 @@ ONE_sysLoad(ONEdevice *pDevice, BOOLEAN tranAnalysis,
}
/* zero the matrix */
spClear(pDevice->matrix);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
SMPclearKLUforCIDER (pDevice->matrix) ;
} else {
#endif
SMPclear(pDevice->matrix);
#ifdef KLU
}
#endif
for (eIndex = 1; eIndex < pDevice->numNodes; eIndex++) {
pElem = pDevice->elemArray[eIndex];
@ -275,7 +541,17 @@ ONE_jacLoad(ONEdevice *pDevice)
ONE_commonTerms(pDevice, FALSE, FALSE, NULL);
/* zero the matrix */
spClear(pDevice->matrix);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
SMPclearKLUforCIDER (pDevice->matrix) ;
} else {
#endif
SMPclear(pDevice->matrix);
#ifdef KLU
}
#endif
for (eIndex = 1; eIndex < pDevice->numNodes; eIndex++) {
pElem = pDevice->elemArray[eIndex];

View File

@ -35,7 +35,15 @@ ONEdestroy(ONEdevice *pDevice)
FREE(pDevice->copiedSolution);
FREE(pDevice->rhs);
FREE(pDevice->rhsImag);
spDestroy(pDevice->matrix);
#ifdef KLU
SMPdestroyKLUforCIDER (pDevice->matrix) ;
#else
SMPdestroy (pDevice->matrix) ;
#endif
FREE (pDevice->matrix) ;
break;
case SLV_EQUIL:
/* free up the vectors allocated in the equilibrium solution */
@ -43,7 +51,15 @@ ONEdestroy(ONEdevice *pDevice)
FREE(pDevice->dcDeltaSolution);
FREE(pDevice->copiedSolution);
FREE(pDevice->rhs);
spDestroy(pDevice->matrix);
#ifdef KLU
SMPdestroyKLUforCIDER (pDevice->matrix) ;
#else
SMPdestroy (pDevice->matrix) ;
#endif
FREE (pDevice->matrix) ;
break;
case SLV_NONE:
break;

View File

@ -115,5 +115,9 @@ extern void ONEjacCheck(ONEdevice *, BOOLEAN, ONEtranInfo *);
extern void ONEpredict(ONEdevice *, ONEtranInfo *);
extern BOOLEAN ONEdeviceConverged(ONEdevice *);
#ifdef KLU
void ONEbindCSC (ONEdevice *) ;
void ONEQbindCSC (ONEdevice *) ;
#endif
#endif

View File

@ -12,6 +12,10 @@ Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
#include "oneddefs.h"
#include "ngspice/spmatrix.h"
#ifdef KLU
#include "ngspice/klu-binding.h"
#endif
/* Functions to setup and solve the 1D poisson equation. */
@ -27,16 +31,84 @@ ONEQjacBuild(ONEdevice *pDevice)
for (index = 1; index < pDevice->numNodes; index++) {
pElem = pDevice->elemArray[index];
pNode = pElem->pLeftNode;
pNode->fPsiPsi = spGetElement(matrix, pNode->poiEqn, pNode->poiEqn);
#ifdef KLU
pNode->fPsiPsi = SMPmakeEltKLUforCIDER (matrix, pNode->poiEqn, pNode->poiEqn) ;
pNode->fPsiPsiBinding = NULL ;
#else
pNode->fPsiPsi = SMPmakeElt(matrix, pNode->poiEqn, pNode->poiEqn);
#endif
pNode1 = pElem->pRightNode;
pNode->fPsiPsiiP1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn);
#ifdef KLU
pNode->fPsiPsiiP1 = SMPmakeEltKLUforCIDER (matrix, pNode->poiEqn, pNode1->poiEqn) ;
pNode->fPsiPsiiP1Binding = NULL ;
#else
pNode->fPsiPsiiP1 = SMPmakeElt(matrix, pNode->poiEqn, pNode1->poiEqn);
#endif
pNode = pElem->pRightNode;
pNode->fPsiPsi = spGetElement(matrix, pNode->poiEqn, pNode->poiEqn);
#ifdef KLU
pNode->fPsiPsi = SMPmakeEltKLUforCIDER (matrix, pNode->poiEqn, pNode->poiEqn) ;
pNode->fPsiPsiBinding = NULL ;
#else
pNode->fPsiPsi = SMPmakeElt(matrix, pNode->poiEqn, pNode->poiEqn);
#endif
pNode1 = pElem->pLeftNode;
pNode->fPsiPsiiM1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn);
#ifdef KLU
pNode->fPsiPsiiM1 = SMPmakeEltKLUforCIDER (matrix, pNode->poiEqn, pNode1->poiEqn) ;
pNode->fPsiPsiiM1Binding = NULL ;
#else
pNode->fPsiPsiiM1 = SMPmakeElt(matrix, pNode->poiEqn, pNode1->poiEqn);
#endif
}
}
#ifdef KLU
void
ONEQbindCSC (ONEdevice *pDevice)
{
ONEelem *pElem ;
ONEnode *pNode, *pNode1 ;
int index ;
BindElementKLUforCIDER i, *matched, *BindStruct, *BindStructCSC ;
size_t nz ;
BindStruct = pDevice->matrix->SMPkluMatrix->KLUmatrixBindStructForCIDER ;
nz = pDevice->matrix->SMPkluMatrix->KLUmatrixNZ ;
BindStructCSC = (BindElementKLUforCIDER *) malloc (nz * sizeof (BindElementKLUforCIDER)) ;
for (index = 0 ; index < (int)nz ; index++) {
BindStructCSC [index] = BindStruct [index] ;
}
for (index = 1 ; index < pDevice->numNodes ; index++) {
pElem = pDevice->elemArray [index] ;
pNode = pElem->pLeftNode ;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsi, fPsiPsiBinding, pNode->poiEqn, pNode->poiEqn) ;
pNode1 = pElem->pRightNode ;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsiiP1, fPsiPsiiP1Binding, pNode->poiEqn, pNode1->poiEqn) ;
pNode = pElem->pRightNode ;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsi, fPsiPsiBinding, pNode->poiEqn, pNode->poiEqn) ;
pNode1 = pElem->pLeftNode ;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsiiM1, fPsiPsiiM1Binding, pNode->poiEqn, pNode1->poiEqn) ;
}
free (BindStructCSC) ;
}
#endif
void
ONEQsysLoad(ONEdevice *pDevice)
@ -58,7 +130,17 @@ ONEQsysLoad(ONEdevice *pDevice)
}
/* zero the matrix */
spClear(pDevice->matrix);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
SMPclearKLUforCIDER (pDevice->matrix) ;
} else {
#endif
SMPclear(pDevice->matrix);
#ifdef KLU
}
#endif
for (index = 1; index < pDevice->numNodes; index++) {
pElem = pDevice->elemArray[index];

View File

@ -52,7 +52,12 @@ NUMDproject(ONEdevice *pDevice, double delV)
pDevice->rhs[pNode->pEqn] = -pEdge->dJpDpsiP1;
}
incVpn = pDevice->dcDeltaSolution;
spSolve(pDevice->matrix, pDevice->rhs, incVpn, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVpn, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVpn) ;
#endif
for (index = 1; index < pDevice->numNodes; index++) {
pElem = pDevice->elemArray[index];
@ -128,7 +133,12 @@ NBJTproject(ONEdevice *pDevice, double delVce, double delVbe,
pDevice->rhs[pNode->pEqn] = -pEdge->dJpDpsiP1;
}
incVce = pDevice->dcDeltaSolution;
spSolve(pDevice->matrix, pDevice->rhs, incVce, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVce, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVce) ;
#endif
for (index = 1; index < pDevice->numNodes; index++) {
pElem = pDevice->elemArray[index];
@ -179,7 +189,12 @@ NBJTproject(ONEdevice *pDevice, double delVce, double delVbe,
}
incVbe = pDevice->copiedSolution;
spSolve(pDevice->matrix, pDevice->rhs, incVbe, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVbe, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVbe) ;
#endif
for (index = 1; index < pDevice->numNodes; index++) {
pElem = pDevice->elemArray[index];

View File

@ -22,6 +22,9 @@ Author: 1991 David A. Gates, U. C. Berkeley CAD Group
#include "../../maths/misc/norm.h"
#include "ngspice/ifsim.h"
#include "ngspice/cktdefs.h"
#include "ngspice/ftedefs.h"
extern IFfrontEnd *SPfrontEnd;
@ -91,7 +94,13 @@ ONEdcSolve(ONEdevice *pDevice, int iterationLimit, BOOLEAN newSolver,
}
/* FACTOR */
startTime = SPfrontEnd->IFseconds();
error = spFactor(pDevice->matrix);
#ifdef KLU
error = SMPreorderKLUforCIDER (pDevice->matrix) ;
#else
error = SMPluFacForCIDER (pDevice->matrix) ;
#endif
factorTime += SPfrontEnd->IFseconds() - startTime;
if (newSolver) {
if (pDevice->iterationNumber == 1) {
@ -110,7 +119,7 @@ ONEdcSolve(ONEdevice *pDevice, int iterationLimit, BOOLEAN newSolver,
if (foundError(error)) {
if (error == spSINGULAR) {
int badRow, badCol;
spWhereSingular(pDevice->matrix, &badRow, &badCol);
SMPgetError(pDevice->matrix, &badCol, &badRow);
printf("***** singular at (%d,%d)\n", badRow, badCol);
}
/* Should probably try to recover now, but we'll punt instead. */
@ -118,7 +127,13 @@ ONEdcSolve(ONEdevice *pDevice, int iterationLimit, BOOLEAN newSolver,
}
/* SOLVE */
startTime = SPfrontEnd->IFseconds();
spSolve(pDevice->matrix, rhs, delta, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhs, delta, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, rhs, delta) ;
#endif
solveTime += SPfrontEnd->IFseconds() - startTime;
/* UPDATE */
@ -441,7 +456,13 @@ ONEresetJacobian(ONEdevice *pDevice)
ONE_jacLoad(pDevice);
error = spFactor(pDevice->matrix);
#ifdef KLU
error = SMPreorderKLUforCIDER (pDevice->matrix) ;
#else
error = SMPluFacForCIDER (pDevice->matrix) ;
#endif
if (foundError(error)) {
exit(-1);
}
@ -539,7 +560,6 @@ ONEequilSolve(ONEdevice *pDevice)
ONEnode *pNode;
double startTime, setupTime, miscTime;
setupTime = miscTime = 0.0;
/* SETUP */
@ -553,7 +573,15 @@ ONEequilSolve(ONEdevice *pDevice)
FREE(pDevice->copiedSolution);
FREE(pDevice->rhs);
FREE(pDevice->rhsImag);
spDestroy(pDevice->matrix);
#ifdef KLU
SMPdestroyKLUforCIDER (pDevice->matrix) ;
#else
SMPdestroy (pDevice->matrix) ;
#endif
FREE (pDevice->matrix) ;
/* FALLTHRU */
case SLV_NONE:
pDevice->poissonOnly = TRUE;
@ -562,15 +590,62 @@ ONEequilSolve(ONEdevice *pDevice)
XCALLOC(pDevice->dcDeltaSolution, double, pDevice->dimEquil);
XCALLOC(pDevice->copiedSolution, double, pDevice->dimEquil);
XCALLOC(pDevice->rhs, double, pDevice->dimEquil);
pDevice->matrix = spCreate(pDevice->numEqns, 0, &error);
pDevice->matrix = TMALLOC (SMPmatrix, 1) ;
#ifdef KLU
pDevice->matrix->CKTkluMODE = ft_curckt->ci_ckt->CKTkluMODE ;
error = SMPnewMatrixKLUforCIDER (pDevice->matrix, pDevice->numEqns, KLUmatrixReal) ;
#else
error = SMPnewMatrixForCIDER (pDevice->matrix, pDevice->numEqns, 0) ;
#endif
if (error == spNO_MEMORY) {
printf("ONEequilSolve: Out of Memory\n");
exit(-1);
}
newSolver = TRUE;
spSetReal(pDevice->matrix);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = KLUmatrixReal ;
} else {
#endif
spSetReal (pDevice->matrix->SPmatrix) ;
#ifdef KLU
}
#endif
ONEQjacBuild(pDevice);
pDevice->numOrigEquil = spElementCount(pDevice->matrix);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
/* Convert the COO Storage to CSC for KLU and Fill the Binding Table */
SMPconvertCOOtoCSCKLUforCIDER (pDevice->matrix) ;
/* Bind the KLU Pointers */
ONEQbindCSC (pDevice) ;
/* Perform KLU Matrix Analysis */
pDevice->matrix->SMPkluMatrix->KLUmatrixSymbolic = klu_analyze ((int)pDevice->matrix->SMPkluMatrix->KLUmatrixN, pDevice->matrix->SMPkluMatrix->KLUmatrixAp,
pDevice->matrix->SMPkluMatrix->KLUmatrixAi, pDevice->matrix->SMPkluMatrix->KLUmatrixCommon) ;
if (pDevice->matrix->SMPkluMatrix->KLUmatrixSymbolic == NULL) {
printf ("CIDER: KLU Failed\n") ;
if (pDevice->matrix->SMPkluMatrix->KLUmatrixCommon->status == KLU_EMPTY_MATRIX) {
return ; // Francesco Lannutti - Fix KLU return values
}
}
pDevice->numOrigEquil = (int)pDevice->matrix->SMPkluMatrix->KLUmatrixNZ ;
} else {
pDevice->numOrigEquil = spElementCount (pDevice->matrix->SPmatrix) ;
}
#else
pDevice->numOrigEquil = spElementCount (pDevice->matrix->SPmatrix) ;
#endif
pDevice->numFillEquil = 0;
/* FALLTHRU */
case SLV_EQUIL:
@ -590,7 +665,20 @@ ONEequilSolve(ONEdevice *pDevice)
/* MISCELLANEOUS */
startTime = SPfrontEnd->IFseconds();
if (newSolver) {
pDevice->numFillEquil = spFillinCount(pDevice->matrix);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
pDevice->numFillEquil = pDevice->matrix->SMPkluMatrix->KLUmatrixNumeric->lnz + pDevice->matrix->SMPkluMatrix->KLUmatrixNumeric->unz
- (int)pDevice->matrix->SMPkluMatrix->KLUmatrixNZ ;
} else {
#endif
pDevice->numFillEquil = spFillinCount(pDevice->matrix->SPmatrix);
#ifdef KLU
}
#endif
}
if (pDevice->converged) {
ONEQcommonTerms(pDevice);
@ -642,7 +730,15 @@ ONEbiasSolve(ONEdevice *pDevice, int iterationLimit,
FREE(pDevice->dcDeltaSolution);
FREE(pDevice->copiedSolution);
FREE(pDevice->rhs);
spDestroy(pDevice->matrix);
#ifdef KLU
SMPdestroyKLUforCIDER (pDevice->matrix) ;
#else
SMPdestroy (pDevice->matrix) ;
#endif
FREE (pDevice->matrix) ;
/* FALLTHRU */
case SLV_NONE:
pDevice->poissonOnly = FALSE;
@ -652,18 +748,65 @@ ONEbiasSolve(ONEdevice *pDevice, int iterationLimit,
XCALLOC(pDevice->copiedSolution, double, pDevice->dimBias);
XCALLOC(pDevice->rhs, double, pDevice->dimBias);
XCALLOC(pDevice->rhsImag, double, pDevice->dimBias);
pDevice->matrix = spCreate(pDevice->numEqns, 1, &error);
pDevice->matrix = TMALLOC (SMPmatrix, 1) ;
#ifdef KLU
pDevice->matrix->CKTkluMODE = ft_curckt->ci_ckt->CKTkluMODE ;
error = SMPnewMatrixKLUforCIDER (pDevice->matrix, pDevice->numEqns, KLUMatrixComplex) ;
#else
error = SMPnewMatrixForCIDER (pDevice->matrix, pDevice->numEqns, 1) ;
#endif
if (error == spNO_MEMORY) {
exit(-1);
}
newSolver = TRUE;
ONE_jacBuild(pDevice);
pDevice->numOrigBias = spElementCount(pDevice->matrix);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
/* Convert the COO Storage to CSC for KLU and Fill the Binding Table */
SMPconvertCOOtoCSCKLUforCIDER (pDevice->matrix) ;
/* Bind the KLU Pointers */
ONEbindCSC (pDevice) ;
/* Perform KLU Matrix Analysis */
pDevice->matrix->SMPkluMatrix->KLUmatrixSymbolic = klu_analyze ((int)pDevice->matrix->SMPkluMatrix->KLUmatrixN, pDevice->matrix->SMPkluMatrix->KLUmatrixAp,
pDevice->matrix->SMPkluMatrix->KLUmatrixAi, pDevice->matrix->SMPkluMatrix->KLUmatrixCommon) ;
if (pDevice->matrix->SMPkluMatrix->KLUmatrixSymbolic == NULL) {
if (pDevice->matrix->SMPkluMatrix->KLUmatrixCommon->status == KLU_EMPTY_MATRIX) {
printf ("CIDER: KLU failed\n") ;
return ; // Francesco Lannutti - Fix KLU return values
}
}
pDevice->numOrigBias = (int)pDevice->matrix->SMPkluMatrix->KLUmatrixNZ ;
} else {
pDevice->numOrigBias = spElementCount(pDevice->matrix->SPmatrix);
}
#else
pDevice->numOrigBias = spElementCount (pDevice->matrix->SPmatrix) ;
#endif
pDevice->numFillBias = 0;
ONEstoreInitialGuess(pDevice);
/* FALLTHRU */
case SLV_SMSIG:
spSetReal(pDevice->matrix);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = KLUmatrixReal ;
} else {
#endif
spSetReal (pDevice->matrix->SPmatrix) ;
#ifdef KLU
}
#endif
/* FALLTHRU */
case SLV_BIAS:
pDevice->solverType = SLV_BIAS;
@ -681,7 +824,20 @@ ONEbiasSolve(ONEdevice *pDevice, int iterationLimit,
/* MISCELLANEOUS */
startTime = SPfrontEnd->IFseconds();
if (newSolver) {
pDevice->numFillBias = spFillinCount(pDevice->matrix);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
pDevice->numFillBias = pDevice->matrix->SMPkluMatrix->KLUmatrixNumeric->lnz + pDevice->matrix->SMPkluMatrix->KLUmatrixNumeric->unz
- (int)pDevice->matrix->SMPkluMatrix->KLUmatrixNZ ;
} else {
#endif
pDevice->numFillBias = spFillinCount (pDevice->matrix->SPmatrix) ; // Francesco Lannutti - Fix for KLU
#ifdef KLU
}
#endif
}
solution = pDevice->dcSolution;
if ((!pDevice->converged) && iterationLimit > 1) {
@ -999,8 +1155,12 @@ double
ONEnuNorm(ONEdevice *pDevice)
{
/* The LU Decomposed matrix is available. Use it to calculate x. */
spSolve(pDevice->matrix, pDevice->rhs, pDevice->rhsImag,
NULL, NULL);
#ifdef KLU
printf ("CIDER: KLU to be fixed ONEnuNorm\n") ;
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, pDevice->rhsImag, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, pDevice->rhsImag) ;
#endif
/* Compute L2-norm of the solution vector (stored in rhsImag) */
return (l2Norm(pDevice->rhsImag, pDevice->numEqns));
@ -1041,7 +1201,14 @@ ONEjacCheck(ONEdevice *pDevice, BOOLEAN tranAnalysis, ONEtranInfo *info)
pDevice->dcSolution[index] = pDevice->copiedSolution[index];
for (rIndex = 1; rIndex <= pDevice->numEqns; rIndex++) {
diff = (pDevice->rhsImag[rIndex] - pDevice->rhs[rIndex]) / del;
dptr = spFindElement(pDevice->matrix, rIndex, index);
#ifdef KLU
printf ("CIDER: KLU to be fixed: spFindElement") ;
dptr = NULL ;
#else
dptr = spFindElement(pDevice->matrix->SPmatrix, rIndex, index); // Francesco Lannutti - Fix for KLU
#endif
/*
* if ( dptr ISNOT NULL ) { fprintf( stderr, "[%d][%d]: FD =
* %11.4e, AJ = %11.4e\n", rIndex, index, diff, *dptr ); } else {

View File

@ -102,36 +102,61 @@ NUMD2admittance(TWOdevice *pDevice, double omega, SPcomplex *yd)
}
storeNewRhs(pDevice, pDevice->pLastContact);
spSetComplex(pDevice->matrix);
for (eIndex = 1; eIndex <= pDevice->numElems; eIndex++) {
pElem = pDevice->elements[eIndex];
if (pElem->elemType == SEMICON) {
dxdy = 0.25 * pElem->dx * pElem->dy;
for (index = 0; index <= 3; index++) {
pNode = pElem->pNodes[index];
if (pNode->nodeType != CONTACT) {
if (!OneCarrier) {
spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -dxdy * omega);
spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, dxdy * omega);
} else if (OneCarrier == N_TYPE) {
spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -dxdy * omega);
} else if (OneCarrier == P_TYPE) {
spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, dxdy * omega);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
// Francesco Lannutti - To be completed
pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = KLUMatrixComplex ;
} else {
#endif
spSetComplex(pDevice->matrix->SPmatrix);
for (eIndex = 1; eIndex <= pDevice->numElems; eIndex++) {
pElem = pDevice->elements[eIndex];
if (pElem->elemType == SEMICON) {
dxdy = 0.25 * pElem->dx * pElem->dy;
for (index = 0; index <= 3; index++) {
pNode = pElem->pNodes[index];
if (pNode->nodeType != CONTACT) {
if (!OneCarrier) {
spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -dxdy * omega);
spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, dxdy * omega);
} else if (OneCarrier == N_TYPE) {
spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -dxdy * omega);
} else if (OneCarrier == P_TYPE) {
spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, dxdy * omega);
}
}
}
}
}
}
#ifdef KLU
}
#endif
pDevice->pStats->loadTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
/* FACTOR */
startTime = SPfrontEnd->IFseconds();
spFactor(pDevice->matrix);
#ifdef KLU
SMPluFacKLUforCIDER (pDevice->matrix) ;
#else
SMPcLUfac(pDevice->matrix, 0);
#endif
pDevice->pStats->factorTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
/* SOLVE */
startTime = SPfrontEnd->IFseconds();
spSolve(pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#else
SMPcSolveForCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#endif
pDevice->pStats->solveTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
}
/* MISC */
@ -263,36 +288,61 @@ NBJT2admittance(TWOdevice *pDevice, double omega, SPcomplex *yIeVce,
TWOPjacLoad(pDevice);
}
storeNewRhs(pDevice, pColContact);
spSetComplex(pDevice->matrix);
for (eIndex = 1; eIndex <= pDevice->numElems; eIndex++) {
pElem = pDevice->elements[eIndex];
if (pElem->elemType == SEMICON) {
dxdy = 0.25 * pElem->dx * pElem->dy;
for (index = 0; index <= 3; index++) {
pNode = pElem->pNodes[index];
if (pNode->nodeType != CONTACT) {
if (!OneCarrier) {
spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -dxdy * omega);
spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, dxdy * omega);
} else if (OneCarrier == N_TYPE) {
spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -dxdy * omega);
} else if (OneCarrier == P_TYPE) {
spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, dxdy * omega);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
// Francesco Lannutti - To be completed
pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = KLUMatrixComplex ;
} else {
#endif
spSetComplex(pDevice->matrix->SPmatrix);
for (eIndex = 1; eIndex <= pDevice->numElems; eIndex++) {
pElem = pDevice->elements[eIndex];
if (pElem->elemType == SEMICON) {
dxdy = 0.25 * pElem->dx * pElem->dy;
for (index = 0; index <= 3; index++) {
pNode = pElem->pNodes[index];
if (pNode->nodeType != CONTACT) {
if (!OneCarrier) {
spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -dxdy * omega);
spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, dxdy * omega);
} else if (OneCarrier == N_TYPE) {
spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -dxdy * omega);
} else if (OneCarrier == P_TYPE) {
spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, dxdy * omega);
}
}
}
}
}
}
#ifdef KLU
}
#endif
pDevice->pStats->loadTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
/* FACTOR */
startTime = SPfrontEnd->IFseconds();
spFactor(pDevice->matrix);
#ifdef KLU
SMPluFacKLUforCIDER (pDevice->matrix) ;
#else
SMPcLUfac(pDevice->matrix, 0);
#endif
pDevice->pStats->factorTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
/* SOLVE */
startTime = SPfrontEnd->IFseconds();
spSolve(pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#else
SMPcSolveForCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#endif
pDevice->pStats->solveTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
/* MISC */
@ -317,7 +367,13 @@ NBJT2admittance(TWOdevice *pDevice, double omega, SPcomplex *yIeVce,
/* SOLVE */
startTime = SPfrontEnd->IFseconds();
spSolve(pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#else
SMPcSolveForCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#endif
pDevice->pStats->solveTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
}
/* MISC */
@ -517,36 +573,62 @@ NUMOSadmittance(TWOdevice *pDevice, double omega, struct mosAdmittances *yAc)
} else if (OneCarrier == P_TYPE) {
TWOPjacLoad(pDevice);
}
spSetComplex(pDevice->matrix);
for (eIndex = 1; eIndex <= pDevice->numElems; eIndex++) {
pElem = pDevice->elements[eIndex];
if (pElem->elemType == SEMICON) {
dxdy = 0.25 * pElem->dx * pElem->dy;
for (index = 0; index <= 3; index++) {
pNode = pElem->pNodes[index];
if (pNode->nodeType != CONTACT) {
if (!OneCarrier) {
spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -dxdy * omega);
spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, dxdy * omega);
} else if (OneCarrier == N_TYPE) {
spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -dxdy * omega);
} else if (OneCarrier == P_TYPE) {
spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, dxdy * omega);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
// Francesco Lannutti - To be completed
pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = KLUMatrixComplex ;
} else {
#endif
spSetComplex(pDevice->matrix->SPmatrix);
for (eIndex = 1; eIndex <= pDevice->numElems; eIndex++) {
pElem = pDevice->elements[eIndex];
if (pElem->elemType == SEMICON) {
dxdy = 0.25 * pElem->dx * pElem->dy;
for (index = 0; index <= 3; index++) {
pNode = pElem->pNodes[index];
if (pNode->nodeType != CONTACT) {
if (!OneCarrier) {
spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -dxdy * omega);
spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, dxdy * omega);
} else if (OneCarrier == N_TYPE) {
spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -dxdy * omega);
} else if (OneCarrier == P_TYPE) {
spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, dxdy * omega);
}
}
}
}
}
}
#ifdef KLU
}
#endif
pDevice->pStats->loadTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
/* FACTOR */
startTime = SPfrontEnd->IFseconds();
spFactor(pDevice->matrix);
#ifdef KLU
SMPluFacKLUforCIDER (pDevice->matrix) ;
#else
SMPcLUfac(pDevice->matrix, 0);
#endif
pDevice->pStats->factorTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
/* SOLVE */
startTime = SPfrontEnd->IFseconds();
spSolve(pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#else
SMPcSolveForCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#endif
pDevice->pStats->solveTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
/* MISC */
@ -574,7 +656,13 @@ NUMOSadmittance(TWOdevice *pDevice, double omega, struct mosAdmittances *yAc)
/* SOLVE */
startTime = SPfrontEnd->IFseconds();
spSolve(pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#else
SMPcSolveForCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#endif
pDevice->pStats->solveTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
/* MISC */
@ -602,7 +690,13 @@ NUMOSadmittance(TWOdevice *pDevice, double omega, struct mosAdmittances *yAc)
/* SOLVE */
startTime = SPfrontEnd->IFseconds();
spSolve(pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#else
SMPcSolveForCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#endif
pDevice->pStats->solveTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
}
/* MISC */
@ -687,7 +781,12 @@ TWOsorSolve(TWOdevice *pDevice, double *xReal, double *xImag,
}
/* compute xReal(k+1). solution stored in rhsImag */
spSolve(pDevice->matrix, rhsSOR, rhsSOR, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsSOR, rhsSOR, NULL, NULL) ;
#else
SMPsolve(pDevice->matrix, rhsSOR, rhsSOR);
#endif
/* modify solution when wRelax is not 1 */
if (wRelax != 1) {
for (index = 1; index <= numEqns; index++) {
@ -729,7 +828,12 @@ TWOsorSolve(TWOdevice *pDevice, double *xReal, double *xImag,
}
}
/* compute xImag(k+1) */
spSolve(pDevice->matrix, rhsSOR, rhsSOR, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsSOR, rhsSOR, NULL, NULL) ;
#else
SMPsolve(pDevice->matrix, rhsSOR, rhsSOR);
#endif
/* modify solution when wRelax is not 1 */
if (wRelax != 1) {
for (index = 1; index <= numEqns; index++) {
@ -1073,32 +1177,54 @@ NUMD2ys(TWOdevice *pDevice, SPcomplex *s, SPcomplex *yIn)
}
storeNewRhs(pDevice, pDevice->pLastContact);
spSetComplex(pDevice->matrix);
for (eIndex = 1; eIndex <= pDevice->numElems; eIndex++) {
pElem = pDevice->elements[eIndex];
if (pElem->elemType == SEMICON) {
dxdy = 0.25 * pElem->dx * pElem->dy;
for (index = 0; index <= 3; index++) {
pNode = pElem->pNodes[index];
if (pNode->nodeType != CONTACT) {
if (!OneCarrier) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fNN, -temp.real, -temp.imag);
spADD_COMPLEX_ELEMENT(pNode->fPP, temp.real, temp.imag);
} else if (OneCarrier == N_TYPE) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fNN, -temp.real, -temp.imag);
} else if (OneCarrier == P_TYPE) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fPP, temp.real, temp.imag);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
// Francesco Lannutti - To be completed
pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = KLUMatrixComplex ;
} else {
#endif
spSetComplex(pDevice->matrix->SPmatrix);
for (eIndex = 1; eIndex <= pDevice->numElems; eIndex++) {
pElem = pDevice->elements[eIndex];
if (pElem->elemType == SEMICON) {
dxdy = 0.25 * pElem->dx * pElem->dy;
for (index = 0; index <= 3; index++) {
pNode = pElem->pNodes[index];
if (pNode->nodeType != CONTACT) {
if (!OneCarrier) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fNN, -temp.real, -temp.imag);
spADD_COMPLEX_ELEMENT(pNode->fPP, temp.real, temp.imag);
} else if (OneCarrier == N_TYPE) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fNN, -temp.real, -temp.imag);
} else if (OneCarrier == P_TYPE) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fPP, temp.real, temp.imag);
}
}
}
}
}
}
}
spFactor(pDevice->matrix);
spSolve(pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag);
#ifdef KLU
}
#endif
#ifdef KLU
SMPluFacKLUforCIDER (pDevice->matrix) ;
#else
SMPcLUfac(pDevice->matrix, 0);
#endif
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#else
SMPcSolveForCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#endif
y = contactAdmittance(pDevice, pDevice->pFirstContact, deltaVContact,
solnReal, solnImag, &cOmega);
CMPLX_ASSIGN_VALUE(yAc, y->real, y->imag);
@ -1147,31 +1273,54 @@ NBJT2ys(TWOdevice *pDevice, SPcomplex *s, SPcomplex *yIeVce, SPcomplex *yIcVce,
TWOPjacLoad(pDevice);
}
storeNewRhs(pDevice, pColContact);
spSetComplex(pDevice->matrix);
for (eIndex = 1; eIndex <= pDevice->numElems; eIndex++) {
pElem = pDevice->elements[eIndex];
if (pElem->elemType == SEMICON) {
dxdy = 0.25 * pElem->dx * pElem->dy;
for (index = 0; index <= 3; index++) {
pNode = pElem->pNodes[index];
if (pNode->nodeType != CONTACT) {
if (!OneCarrier) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fNN, -temp.real, -temp.imag);
spADD_COMPLEX_ELEMENT(pNode->fPP, temp.real, temp.imag);
} else if (OneCarrier == N_TYPE) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fNN, -temp.real, -temp.imag);
} else if (OneCarrier == P_TYPE) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fPP, temp.real, temp.imag);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
// Francesco Lannutti - To be completed
pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = KLUMatrixComplex ;
} else {
#endif
spSetComplex(pDevice->matrix->SPmatrix);
for (eIndex = 1; eIndex <= pDevice->numElems; eIndex++) {
pElem = pDevice->elements[eIndex];
if (pElem->elemType == SEMICON) {
dxdy = 0.25 * pElem->dx * pElem->dy;
for (index = 0; index <= 3; index++) {
pNode = pElem->pNodes[index];
if (pNode->nodeType != CONTACT) {
if (!OneCarrier) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fNN, -temp.real, -temp.imag);
spADD_COMPLEX_ELEMENT(pNode->fPP, temp.real, temp.imag);
} else if (OneCarrier == N_TYPE) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fNN, -temp.real, -temp.imag);
} else if (OneCarrier == P_TYPE) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fPP, temp.real, temp.imag);
}
}
}
}
}
}
#ifdef KLU
}
spFactor(pDevice->matrix);
spSolve(pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag);
#endif
#ifdef KLU
SMPluFacKLUforCIDER (pDevice->matrix) ;
#else
SMPcLUfac(pDevice->matrix, 0);
#endif
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#else
SMPcSolveForCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#endif
y = contactAdmittance(pDevice, pEmitContact, FALSE,
solnReal, solnImag, &cOmega);
@ -1184,7 +1333,13 @@ NBJT2ys(TWOdevice *pDevice, SPcomplex *s, SPcomplex *yIeVce, SPcomplex *yIcVce,
}
storeNewRhs(pDevice, pBaseContact);
/* don't need to LU factor the jacobian since it exists */
spSolve(pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#else
SMPcSolveForCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#endif
y = contactAdmittance(pDevice, pEmitContact, FALSE,
solnReal, solnImag, &cOmega);
CMPLX_ASSIGN_VALUE(pIeVbe, y->real, y->imag);
@ -1240,33 +1395,54 @@ NUMOSys(TWOdevice *pDevice, SPcomplex *s, struct mosAdmittances *yAc)
TWOPjacLoad(pDevice);
}
storeNewRhs(pDevice, pDContact);
spSetComplex(pDevice->matrix);
for (eIndex = 1; eIndex <= pDevice->numElems; eIndex++) {
pElem = pDevice->elements[eIndex];
if (pElem->elemType == SEMICON) {
dxdy = 0.25 * pElem->dx * pElem->dy;
for (index = 0; index <= 3; index++) {
pNode = pElem->pNodes[index];
if (pNode->nodeType != CONTACT) {
if (!OneCarrier) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fNN, -temp.real, -temp.imag);
spADD_COMPLEX_ELEMENT(pNode->fPP, temp.real, temp.imag);
} else if (OneCarrier == N_TYPE) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fNN, -temp.real, -temp.imag);
} else if (OneCarrier == P_TYPE) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fPP, temp.real, temp.imag);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
// Francesco Lannutti - To be completed
pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = KLUMatrixComplex ;
} else {
#endif
spSetComplex(pDevice->matrix->SPmatrix);
for (eIndex = 1; eIndex <= pDevice->numElems; eIndex++) {
pElem = pDevice->elements[eIndex];
if (pElem->elemType == SEMICON) {
dxdy = 0.25 * pElem->dx * pElem->dy;
for (index = 0; index <= 3; index++) {
pNode = pElem->pNodes[index];
if (pNode->nodeType != CONTACT) {
if (!OneCarrier) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fNN, -temp.real, -temp.imag);
spADD_COMPLEX_ELEMENT(pNode->fPP, temp.real, temp.imag);
} else if (OneCarrier == N_TYPE) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fNN, -temp.real, -temp.imag);
} else if (OneCarrier == P_TYPE) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fPP, temp.real, temp.imag);
}
}
}
}
}
}
}
spFactor(pDevice->matrix);
spSolve(pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag);
#ifdef KLU
}
#endif
#ifdef KLU
SMPluFacKLUforCIDER (pDevice->matrix) ;
#else
SMPcLUfac(pDevice->matrix, 0);
#endif
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#else
SMPcSolveForCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#endif
y = contactAdmittance(pDevice, pDContact, TRUE,
solnReal, solnImag, &cOmega);
@ -1283,7 +1459,13 @@ NUMOSys(TWOdevice *pDevice, SPcomplex *s, struct mosAdmittances *yAc)
}
storeNewRhs(pDevice, pSContact);
/* don't need to LU factor the jacobian since it exists */
spSolve(pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#else
SMPcSolveForCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#endif
y = contactAdmittance(pDevice, pDContact, FALSE,
solnReal, solnImag, &cOmega);
CMPLX_ASSIGN_VALUE(yAc->yIdVsb, y->real, y->imag);
@ -1297,7 +1479,13 @@ NUMOSys(TWOdevice *pDevice, SPcomplex *s, struct mosAdmittances *yAc)
rhsImag[index] = 0.0;
}
storeNewRhs(pDevice, pGContact);
spSolve(pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#else
SMPcSolveForCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#endif
y = contactAdmittance(pDevice, pDContact, FALSE,
solnReal, solnImag, &cOmega);
CMPLX_ASSIGN_VALUE(yAc->yIdVgb, y->real, y->imag);

View File

@ -30,8 +30,13 @@ void
*/
incVpn = pDevice->dcDeltaSolution;
storeNewRhs( pDevice, pDevice->pLastContact );
spSolve( pDevice->matrix, pDevice->rhs, incVpn, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVpn, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVpn) ;
#endif
incVpn = pDevice->dcDeltaSolution;
*gd = contactConductance( pDevice, pContact, deltaVContact, incVpn,
tranAnalysis, intCoeff );
@ -58,9 +63,20 @@ void
incVce = pDevice->dcDeltaSolution;
incVbe = pDevice->copiedSolution;
storeNewRhs( pDevice, pColContact );
spSolve( pDevice->matrix, pDevice->rhs, incVce, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVce, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVce) ;
#endif
storeNewRhs( pDevice, pBaseContact );
spSolve( pDevice->matrix, pDevice->rhs, incVbe, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVbe, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVbe) ;
#endif
*dIeDVce = contactConductance( pDevice, pEmitContact, FALSE, incVce,
tranAnalysis, intCoeff );
@ -96,11 +112,28 @@ void
incVsb = pDevice->copiedSolution;
incVgb = pDevice->rhsImag;
storeNewRhs( pDevice, pDContact );
spSolve( pDevice->matrix, pDevice->rhs, incVdb, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVdb, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVdb) ;
#endif
storeNewRhs( pDevice, pSContact );
spSolve( pDevice->matrix, pDevice->rhs, incVsb, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVsb, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVsb) ;
#endif
storeNewRhs( pDevice, pGContact );
spSolve( pDevice->matrix, pDevice->rhs, incVgb, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVgb, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVgb) ;
#endif
dIdV->dIdDVdb = contactConductance( pDevice, pDContact, TRUE,
incVdb, tranAnalysis, intCoeff );

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,16 @@ TWOdestroy(TWOdevice *pDevice)
FREE( pDevice->copiedSolution );
FREE( pDevice->rhs );
FREE( pDevice->rhsImag );
spDestroy( pDevice->matrix );
#ifdef KLU
SMPdestroyKLUforCIDER (pDevice->matrix) ;
#else
SMPdestroy (pDevice->matrix) ;
#endif
if (pDevice->matrix) {
FREE(pDevice->matrix);
}
break;
case SLV_EQUIL:
/* free up the vectors allocated in the equilibrium solution */
@ -41,7 +50,16 @@ TWOdestroy(TWOdevice *pDevice)
FREE( pDevice->dcDeltaSolution );
FREE( pDevice->copiedSolution );
FREE( pDevice->rhs );
spDestroy( pDevice->matrix );
#ifdef KLU
SMPdestroyKLUforCIDER (pDevice->matrix) ;
#else
SMPdestroy (pDevice->matrix) ;
#endif
if (pDevice->matrix) {
FREE(pDevice->matrix);
}
break;
case SLV_NONE:
break;

View File

@ -166,4 +166,11 @@ extern BOOLEAN TWOpsiDeltaConverged(TWOdevice *);
extern double TWOnuNorm(TWOdevice *);
extern void TWOjacCheck(TWOdevice *, BOOLEAN, TWOtranInfo *);
#ifdef KLU
void TWObindCSC (TWOdevice *) ;
void TWONbindCSC (TWOdevice *) ;
void TWOPbindCSC (TWOdevice *) ;
void TWOQbindCSC (TWOdevice *) ;
#endif
#endif

View File

@ -16,6 +16,9 @@ Author: 1991 David A. Gates, U. C. Berkeley CAD Group
#include "ngspice/cidersupt.h"
#include "../../maths/misc/bernoull.h"
#ifdef KLU
#include "ngspice/klu-binding.h"
#endif
/*
* Functions to setup and solve the continuity equations.
@ -54,16 +57,41 @@ void
pNode = pElem->pNodes[ nIndex ];
/* get poisson-only pointer */
psiEqn = pNode->psiEqn;
pNode->fPsiPsi = spGetElement( matrix, psiEqn, psiEqn );
#ifdef KLU
pNode->fPsiPsi = SMPmakeEltKLUforCIDER (matrix, psiEqn, psiEqn) ;
pNode->fPsiPsiBinding = NULL ;
#else
pNode->fPsiPsi = SMPmakeElt(matrix, psiEqn, psiEqn);
#endif
if ( pElem->elemType == SEMICON ) {
/* get continuity-coupling terms */
nEqn = pNode->nEqn;
pNode->pEqn = 0; /* Throw pEqn number into garbage. */
/* pointers for additional terms */
pNode->fPsiN = spGetElement( matrix, psiEqn, nEqn );
pNode->fNPsi = spGetElement( matrix, nEqn, psiEqn );
pNode->fNN = spGetElement( matrix, nEqn, nEqn );
#ifdef KLU
pNode->fPsiN = SMPmakeEltKLUforCIDER (matrix, psiEqn, nEqn) ;
pNode->fPsiNBinding = NULL ;
#else
pNode->fPsiN = SMPmakeElt(matrix, psiEqn, nEqn);
#endif
#ifdef KLU
pNode->fNPsi = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqn) ;
pNode->fNPsiBinding = NULL ;
#else
pNode->fNPsi = SMPmakeElt(matrix, nEqn, psiEqn);
#endif
#ifdef KLU
pNode->fNN = SMPmakeEltKLUforCIDER (matrix, nEqn, nEqn) ;
pNode->fNNBinding = NULL ;
#else
pNode->fNN = SMPmakeElt(matrix, nEqn, nEqn);
#endif
} else {
nEqn = 0;
}
@ -92,66 +120,270 @@ void
/* now terms to couple to adjacent nodes */
pNode = pElem->pTLNode;
pNode->fPsiPsiiP1 = spGetElement(matrix, psiEqnTL, psiEqnTR );
pNode->fPsiPsijP1 = spGetElement(matrix, psiEqnTL, psiEqnBL );
#ifdef KLU
pNode->fPsiPsiiP1 = SMPmakeEltKLUforCIDER (matrix, psiEqnTL, psiEqnTR) ;
pNode->fPsiPsiiP1Binding = NULL ;
#else
pNode->fPsiPsiiP1 = SMPmakeElt(matrix, psiEqnTL, psiEqnTR);
#endif
#ifdef KLU
pNode->fPsiPsijP1 = SMPmakeEltKLUforCIDER (matrix, psiEqnTL, psiEqnBL) ;
pNode->fPsiPsijP1Binding = NULL ;
#else
pNode->fPsiPsijP1 = SMPmakeElt(matrix, psiEqnTL, psiEqnBL);
#endif
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
pNode->fNPsiiP1 = spGetElement( matrix, nEqnTL, psiEqnTR );
pNode->fNNiP1 = spGetElement( matrix, nEqnTL, nEqnTR );
pNode->fNPsijP1 = spGetElement( matrix, nEqnTL, psiEqnBL );
pNode->fNNjP1 = spGetElement( matrix, nEqnTL, nEqnBL );
#ifdef KLU
pNode->fNPsiiP1 = SMPmakeEltKLUforCIDER (matrix, nEqnTL, psiEqnTR) ;
pNode->fNPsiiP1Binding = NULL ;
#else
pNode->fNPsiiP1 = SMPmakeElt(matrix, nEqnTL, psiEqnTR);
#endif
#ifdef KLU
pNode->fNNiP1 = SMPmakeEltKLUforCIDER (matrix, nEqnTL, nEqnTR) ;
pNode->fNNiP1Binding = NULL ;
#else
pNode->fNNiP1 = SMPmakeElt(matrix, nEqnTL, nEqnTR);
#endif
#ifdef KLU
pNode->fNPsijP1 = SMPmakeEltKLUforCIDER (matrix, nEqnTL, psiEqnBL) ;
pNode->fNPsijP1Binding = NULL ;
#else
pNode->fNPsijP1 = SMPmakeElt(matrix, nEqnTL, psiEqnBL);
#endif
#ifdef KLU
pNode->fNNjP1 = SMPmakeEltKLUforCIDER (matrix, nEqnTL, nEqnBL) ;
pNode->fNNjP1Binding = NULL ;
#else
pNode->fNNjP1 = SMPmakeElt(matrix, nEqnTL, nEqnBL);
#endif
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
pNode->fNPsiiP1jP1 = spGetElement( matrix, nEqnTL, psiEqnBR );
pNode->fNNiP1jP1 = spGetElement( matrix, nEqnTL, nEqnBR );
#ifdef KLU
pNode->fNPsiiP1jP1 = SMPmakeEltKLUforCIDER (matrix, nEqnTL, psiEqnBR) ;
pNode->fNPsiiP1jP1Binding = NULL ;
#else
pNode->fNPsiiP1jP1 = SMPmakeElt(matrix, nEqnTL, psiEqnBR);
#endif
#ifdef KLU
pNode->fNNiP1jP1 = SMPmakeEltKLUforCIDER (matrix, nEqnTL, nEqnBR) ;
pNode->fNNiP1jP1Binding = NULL ;
#else
pNode->fNNiP1jP1 = SMPmakeElt(matrix, nEqnTL, nEqnBR);
#endif
}
}
pNode = pElem->pTRNode;
pNode->fPsiPsiiM1 = spGetElement(matrix, psiEqnTR, psiEqnTL );
pNode->fPsiPsijP1 = spGetElement(matrix, psiEqnTR, psiEqnBR );
#ifdef KLU
pNode->fPsiPsiiM1 = SMPmakeEltKLUforCIDER (matrix, psiEqnTR, psiEqnTL) ;
pNode->fPsiPsiiM1Binding = NULL ;
#else
pNode->fPsiPsiiM1 = SMPmakeElt(matrix, psiEqnTR, psiEqnTL);
#endif
#ifdef KLU
pNode->fPsiPsijP1 = SMPmakeEltKLUforCIDER (matrix, psiEqnTR, psiEqnBR) ;
pNode->fPsiPsijP1Binding = NULL ;
#else
pNode->fPsiPsijP1 = SMPmakeElt(matrix, psiEqnTR, psiEqnBR);
#endif
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
pNode->fNPsiiM1 = spGetElement( matrix, nEqnTR, psiEqnTL );
pNode->fNNiM1 = spGetElement( matrix, nEqnTR, nEqnTL );
pNode->fNPsijP1 = spGetElement( matrix, nEqnTR, psiEqnBR );
pNode->fNNjP1 = spGetElement( matrix, nEqnTR, nEqnBR );
#ifdef KLU
pNode->fNPsiiM1 = SMPmakeEltKLUforCIDER (matrix, nEqnTR, psiEqnTL) ;
pNode->fNPsiiM1Binding = NULL ;
#else
pNode->fNPsiiM1 = SMPmakeElt(matrix, nEqnTR, psiEqnTL);
#endif
#ifdef KLU
pNode->fNNiM1 = SMPmakeEltKLUforCIDER (matrix, nEqnTR, nEqnTL) ;
pNode->fNNiM1Binding = NULL ;
#else
pNode->fNNiM1 = SMPmakeElt(matrix, nEqnTR, nEqnTL);
#endif
#ifdef KLU
pNode->fNPsijP1 = SMPmakeEltKLUforCIDER (matrix, nEqnTR, psiEqnBR) ;
pNode->fNPsijP1Binding = NULL ;
#else
pNode->fNPsijP1 = SMPmakeElt(matrix, nEqnTR, psiEqnBR);
#endif
#ifdef KLU
pNode->fNNjP1 = SMPmakeEltKLUforCIDER (matrix, nEqnTR, nEqnBR) ;
pNode->fNNjP1Binding = NULL ;
#else
pNode->fNNjP1 = SMPmakeElt(matrix, nEqnTR, nEqnBR);
#endif
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
pNode->fNPsiiM1jP1 = spGetElement( matrix, nEqnTR, psiEqnBL );
pNode->fNNiM1jP1 = spGetElement( matrix, nEqnTR, nEqnBL );
#ifdef KLU
pNode->fNPsiiM1jP1 = SMPmakeEltKLUforCIDER (matrix, nEqnTR, psiEqnBL) ;
pNode->fNPsiiM1jP1Binding = NULL ;
#else
pNode->fNPsiiM1jP1 = SMPmakeElt(matrix, nEqnTR, psiEqnBL);
#endif
#ifdef KLU
pNode->fNNiM1jP1 = SMPmakeEltKLUforCIDER (matrix, nEqnTR, nEqnBL) ;
pNode->fNNiM1jP1Binding = NULL ;
#else
pNode->fNNiM1jP1 = SMPmakeElt(matrix, nEqnTR, nEqnBL);
#endif
}
}
pNode = pElem->pBRNode;
pNode->fPsiPsiiM1 = spGetElement(matrix, psiEqnBR, psiEqnBL );
pNode->fPsiPsijM1 = spGetElement(matrix, psiEqnBR, psiEqnTR );
#ifdef KLU
pNode->fPsiPsiiM1 = SMPmakeEltKLUforCIDER (matrix, psiEqnBR, psiEqnBL) ;
pNode->fPsiPsiiM1Binding = NULL ;
#else
pNode->fPsiPsiiM1 = SMPmakeElt(matrix, psiEqnBR, psiEqnBL);
#endif
#ifdef KLU
pNode->fPsiPsijM1 = SMPmakeEltKLUforCIDER (matrix, psiEqnBR, psiEqnTR) ;
pNode->fPsiPsijM1Binding = NULL ;
#else
pNode->fPsiPsijM1 = SMPmakeElt(matrix, psiEqnBR, psiEqnTR);
#endif
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
pNode->fNPsiiM1 = spGetElement( matrix, nEqnBR, psiEqnBL );
pNode->fNNiM1 = spGetElement( matrix, nEqnBR, nEqnBL );
pNode->fNPsijM1 = spGetElement( matrix, nEqnBR, psiEqnTR );
pNode->fNNjM1 = spGetElement( matrix, nEqnBR, nEqnTR );
#ifdef KLU
pNode->fNPsiiM1 = SMPmakeEltKLUforCIDER (matrix, nEqnBR, psiEqnBL) ;
pNode->fNPsiiM1Binding = NULL ;
#else
pNode->fNPsiiM1 = SMPmakeElt(matrix, nEqnBR, psiEqnBL);
#endif
#ifdef KLU
pNode->fNNiM1 = SMPmakeEltKLUforCIDER (matrix, nEqnBR, nEqnBL) ;
pNode->fNNiM1Binding = NULL ;
#else
pNode->fNNiM1 = SMPmakeElt(matrix, nEqnBR, nEqnBL);
#endif
#ifdef KLU
pNode->fNPsijM1 = SMPmakeEltKLUforCIDER (matrix, nEqnBR, psiEqnTR) ;
pNode->fNPsijM1Binding = NULL ;
#else
pNode->fNPsijM1 = SMPmakeElt(matrix, nEqnBR, psiEqnTR);
#endif
#ifdef KLU
pNode->fNNjM1 = SMPmakeEltKLUforCIDER (matrix, nEqnBR, nEqnTR) ;
pNode->fNNjM1Binding = NULL ;
#else
pNode->fNNjM1 = SMPmakeElt(matrix, nEqnBR, nEqnTR);
#endif
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
pNode->fNPsiiM1jM1 = spGetElement( matrix, nEqnBR, psiEqnTL );
pNode->fNNiM1jM1 = spGetElement( matrix, nEqnBR, nEqnTL );
#ifdef KLU
pNode->fNPsiiM1jM1 = SMPmakeEltKLUforCIDER (matrix, nEqnBR, psiEqnTL) ;
pNode->fNPsiiM1jM1Binding = NULL ;
#else
pNode->fNPsiiM1jM1 = SMPmakeElt(matrix, nEqnBR, psiEqnTL);
#endif
#ifdef KLU
pNode->fNNiM1jM1 = SMPmakeEltKLUforCIDER (matrix, nEqnBR, nEqnTL) ;
pNode->fNNiM1jM1Binding = NULL ;
#else
pNode->fNNiM1jM1 = SMPmakeElt(matrix, nEqnBR, nEqnTL);
#endif
}
}
pNode = pElem->pBLNode;
pNode->fPsiPsiiP1 = spGetElement(matrix, psiEqnBL, psiEqnBR );
pNode->fPsiPsijM1 = spGetElement(matrix, psiEqnBL, psiEqnTL );
#ifdef KLU
pNode->fPsiPsiiP1 = SMPmakeEltKLUforCIDER (matrix, psiEqnBL, psiEqnBR) ;
pNode->fPsiPsiiP1Binding = NULL ;
#else
pNode->fPsiPsiiP1 = SMPmakeElt(matrix, psiEqnBL, psiEqnBR);
#endif
#ifdef KLU
pNode->fPsiPsijM1 = SMPmakeEltKLUforCIDER (matrix, psiEqnBL, psiEqnTL) ;
pNode->fPsiPsijM1Binding = NULL ;
#else
pNode->fPsiPsijM1 = SMPmakeElt(matrix, psiEqnBL, psiEqnTL);
#endif
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
pNode->fNPsiiP1 = spGetElement( matrix, nEqnBL, psiEqnBR );
pNode->fNNiP1 = spGetElement( matrix, nEqnBL, nEqnBR );
pNode->fNPsijM1 = spGetElement( matrix, nEqnBL, psiEqnTL );
pNode->fNNjM1 = spGetElement( matrix, nEqnBL, nEqnTL );
#ifdef KLU
pNode->fNPsiiP1 = SMPmakeEltKLUforCIDER (matrix, nEqnBL, psiEqnBR) ;
pNode->fNPsiiP1Binding = NULL ;
#else
pNode->fNPsiiP1 = SMPmakeElt(matrix, nEqnBL, psiEqnBR);
#endif
#ifdef KLU
pNode->fNNiP1 = SMPmakeEltKLUforCIDER (matrix, nEqnBL, nEqnBR) ;
pNode->fNNiP1Binding = NULL ;
#else
pNode->fNNiP1 = SMPmakeElt(matrix, nEqnBL, nEqnBR);
#endif
#ifdef KLU
pNode->fNPsijM1 = SMPmakeEltKLUforCIDER (matrix, nEqnBL, psiEqnTL) ;
pNode->fNPsijM1Binding = NULL ;
#else
pNode->fNPsijM1 = SMPmakeElt(matrix, nEqnBL, psiEqnTL);
#endif
#ifdef KLU
pNode->fNNjM1 = SMPmakeEltKLUforCIDER (matrix, nEqnBL, nEqnTL) ;
pNode->fNNjM1Binding = NULL ;
#else
pNode->fNNjM1 = SMPmakeElt(matrix, nEqnBL, nEqnTL);
#endif
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
pNode->fNPsiiP1jM1 = spGetElement( matrix, nEqnBL, psiEqnTR );
pNode->fNNiP1jM1 = spGetElement( matrix, nEqnBL, nEqnTR );
#ifdef KLU
pNode->fNPsiiP1jM1 = SMPmakeEltKLUforCIDER (matrix, nEqnBL, psiEqnTR) ;
pNode->fNPsiiP1jM1Binding = NULL ;
#else
pNode->fNPsiiP1jM1 = SMPmakeElt(matrix, nEqnBL, psiEqnTR);
#endif
#ifdef KLU
pNode->fNNiP1jM1 = SMPmakeEltKLUforCIDER (matrix, nEqnBL, nEqnTR) ;
pNode->fNNiP1jM1Binding = NULL ;
#else
pNode->fNNiP1jM1 = SMPmakeElt(matrix, nEqnBL, nEqnTR);
#endif
}
}
}
@ -200,27 +432,135 @@ void
nEqn = pNode->nEqn;
if ( pCh->type % 2 == 0 ) { /* Vertical Slice */
if ( nIndex == 0 || nIndex == 3 ) { /* Left Side */
pNode->fNPsiIn = spGetElement( matrix, nEqn, psiEqnInM );
pNode->fNPsiInP1 = spGetElement( matrix, nEqn, psiEqnInP );
pNode->fNPsiOx = spGetElement( matrix, nEqn, psiEqnOxM );
pNode->fNPsiOxP1 = spGetElement( matrix, nEqn, psiEqnOxP );
#ifdef KLU
pNode->fNPsiIn = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnInM) ;
pNode->fNPsiInBinding = NULL ;
#else
pNode->fNPsiIn = SMPmakeElt(matrix, nEqn, psiEqnInM);
#endif
#ifdef KLU
pNode->fNPsiInP1 = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnInP) ;
pNode->fNPsiInP1Binding = NULL ;
#else
pNode->fNPsiInP1 = SMPmakeElt(matrix, nEqn, psiEqnInP);
#endif
#ifdef KLU
pNode->fNPsiOx = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnOxM) ;
pNode->fNPsiOxBinding = NULL ;
#else
pNode->fNPsiOx = SMPmakeElt(matrix, nEqn, psiEqnOxM);
#endif
#ifdef KLU
pNode->fNPsiOxP1 = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnOxP) ;
pNode->fNPsiOxP1Binding = NULL ;
#else
pNode->fNPsiOxP1 = SMPmakeElt(matrix, nEqn, psiEqnOxP);
#endif
} else { /* Right Side */
pNode->fNPsiInM1 = spGetElement( matrix, nEqn, psiEqnInM );
pNode->fNPsiIn = spGetElement( matrix, nEqn, psiEqnInP );
pNode->fNPsiOxM1 = spGetElement( matrix, nEqn, psiEqnOxM );
pNode->fNPsiOx = spGetElement( matrix, nEqn, psiEqnOxP );
#ifdef KLU
pNode->fNPsiInM1 = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnInM) ;
pNode->fNPsiInM1Binding = NULL ;
#else
pNode->fNPsiInM1 = SMPmakeElt(matrix, nEqn, psiEqnInM);
#endif
#ifdef KLU
pNode->fNPsiIn = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnInP) ;
pNode->fNPsiInBinding = NULL ;
#else
pNode->fNPsiIn = SMPmakeElt(matrix, nEqn, psiEqnInP);
#endif
#ifdef KLU
pNode->fNPsiOxM1 = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnOxM) ;
pNode->fNPsiOxM1Binding = NULL ;
#else
pNode->fNPsiOxM1 = SMPmakeElt(matrix, nEqn, psiEqnOxM);
#endif
#ifdef KLU
pNode->fNPsiOx = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnOxP) ;
pNode->fNPsiOxBinding = NULL ;
#else
pNode->fNPsiOx = SMPmakeElt(matrix, nEqn, psiEqnOxP);
#endif
}
} else { /* Horizontal Slice */
if ( nIndex == 0 || nIndex == 3 ) { /* Left (Top?) Side : bug 483 */
pNode->fNPsiIn = spGetElement( matrix, nEqn, psiEqnInM );
pNode->fNPsiInP1 = spGetElement( matrix, nEqn, psiEqnInP );
pNode->fNPsiOx = spGetElement( matrix, nEqn, psiEqnOxM );
pNode->fNPsiOxP1 = spGetElement( matrix, nEqn, psiEqnOxP );
// <<<<<<< HEAD
// if ( nIndex == 0 || nIndex == 3 ) { /* Left (Top?) Side : bug 483 */
// pNode->fNPsiIn = spGetElement( matrix, nEqn, psiEqnInM );
// pNode->fNPsiInP1 = spGetElement( matrix, nEqn, psiEqnInP );
// pNode->fNPsiOx = spGetElement( matrix, nEqn, psiEqnOxM );
// pNode->fNPsiOxP1 = spGetElement( matrix, nEqn, psiEqnOxP );
// =======
if ( nIndex <= 1 ) { /* Top Side */
//
// #ifdef KLU
// pNode->fNPsiIn = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnInM) ;
// pNode->fNPsiInBinding = NULL ;
// #else
// pNode->fNPsiIn = SMPmakeElt(matrix, nEqn, psiEqnInM);
// #endif
//
// #ifdef KLU
// pNode->fNPsiInP1 = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnInP) ;
// pNode->fNPsiInP1Binding = NULL ;
// #else
// pNode->fNPsiInP1 = SMPmakeElt(matrix, nEqn, psiEqnInP);
// #endif
//
// #ifdef KLU
// pNode->fNPsiOx = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnOxM) ;
// pNode->fNPsiOxBinding = NULL ;
// #else
// pNode->fNPsiOx = SMPmakeElt(matrix, nEqn, psiEqnOxM);
// #endif
//
// #ifdef KLU
// pNode->fNPsiOxP1 = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnOxP) ;
// pNode->fNPsiOxP1Binding = NULL ;
// #else
// pNode->fNPsiOxP1 = SMPmakeElt(matrix, nEqn, psiEqnOxP);
// #endif
//
// >>>>>>> First KLU support of CIDER TWOD simulations
} else { /* Bottom Side */
pNode->fNPsiInM1 = spGetElement( matrix, nEqn, psiEqnInM );
pNode->fNPsiIn = spGetElement( matrix, nEqn, psiEqnInP );
pNode->fNPsiOxM1 = spGetElement( matrix, nEqn, psiEqnOxM );
pNode->fNPsiOx = spGetElement( matrix, nEqn, psiEqnOxP );
#ifdef KLU
pNode->fNPsiInM1 = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnInM) ;
pNode->fNPsiInM1Binding = NULL ;
#else
pNode->fNPsiInM1 = SMPmakeElt(matrix, nEqn, psiEqnInM);
#endif
#ifdef KLU
pNode->fNPsiIn = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnInP) ;
pNode->fNPsiInBinding = NULL ;
#else
pNode->fNPsiIn = SMPmakeElt(matrix, nEqn, psiEqnInP);
#endif
#ifdef KLU
pNode->fNPsiOxM1 = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnOxM) ;
pNode->fNPsiOxM1Binding = NULL ;
#else
pNode->fNPsiOxM1 = SMPmakeElt(matrix, nEqn, psiEqnOxM);
#endif
#ifdef KLU
pNode->fNPsiOx = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnOxP) ;
pNode->fNPsiOxBinding = NULL ;
#else
pNode->fNPsiOx = SMPmakeElt(matrix, nEqn, psiEqnOxP);
#endif
}
}
} /* endfor nIndex */
@ -230,6 +570,256 @@ void
} /* endif SurfaceMobility */
}
#ifdef KLU
void
TWONbindCSC (TWOdevice *pDevice)
{
TWOelem *pElem;
TWOnode *pNode;
TWOchannel *pCh;
BindElementKLUforCIDER i, *matched, *BindStruct, *BindStructCSC ;
int index ;
size_t nz ;
int eIndex, nIndex;
int nextIndex; /* index of node to find next element */
int psiEqn, nEqn; /* scratch for deref'd eqn numbers */
int psiEqnTL = 0, nEqnTL = 0;
int psiEqnTR = 0, nEqnTR = 0;
int psiEqnBR = 0, nEqnBR = 0;
int psiEqnBL = 0, nEqnBL = 0;
int psiEqnInM = 0, psiEqnInP = 0; /* scratch for deref'd surface eqns */
int psiEqnOxM = 0, psiEqnOxP = 0; /* M= more negative, P= more positive */
BindStruct = pDevice->matrix->SMPkluMatrix->KLUmatrixBindStructForCIDER ;
nz = pDevice->matrix->SMPkluMatrix->KLUmatrixNZ ;
BindStructCSC = (BindElementKLUforCIDER *) malloc (nz * sizeof (BindElementKLUforCIDER)) ;
for (index = 0 ; index < (int)nz ; index++) {
BindStructCSC [index] = BindStruct [index] ;
}
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];
/* first the self terms */
for ( nIndex = 0; nIndex <= 3; nIndex++ ) {
pNode = pElem->pNodes[ nIndex ];
/* get poisson-only pointer */
psiEqn = pNode->psiEqn;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsi, fPsiPsiBinding, psiEqn, psiEqn) ;
if ( pElem->elemType == SEMICON ) {
/* get continuity-coupling terms */
nEqn = pNode->nEqn;
pNode->pEqn = 0; /* Throw pEqn number into garbage. */
/* pointers for additional terms */
CREATE_KLU_BINDING_TABLE_CIDER(fPsiN, fPsiNBinding, psiEqn, nEqn) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsi, fNPsiBinding, nEqn, psiEqn) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNN, fNNBinding, nEqn, nEqn) ;
} else {
nEqn = 0;
}
/* save equation indices */
switch ( nIndex ) {
case 0: /* TL Node */
psiEqnTL = psiEqn;
nEqnTL = nEqn;
break;
case 1: /* TR Node */
psiEqnTR = psiEqn;
nEqnTR = nEqn;
break;
case 2: /* BR Node */
psiEqnBR = psiEqn;
nEqnBR = nEqn;
break;
case 3: /* BL Node */
psiEqnBL = psiEqn;
nEqnBL = nEqn;
break;
default:
break;
}
}
/* now terms to couple to adjacent nodes */
pNode = pElem->pTLNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsiiP1, fPsiPsiiP1Binding, psiEqnTL, psiEqnTR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsijP1, fPsiPsijP1Binding, psiEqnTL, psiEqnBL) ;
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiiP1, fNPsiiP1Binding, nEqnTL, psiEqnTR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNNiP1, fNNiP1Binding, nEqnTL, nEqnTR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsijP1, fNPsijP1Binding, nEqnTL, psiEqnBL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNNjP1, fNNjP1Binding, nEqnTL, nEqnBL) ;
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiiP1jP1, fNPsiiP1jP1Binding, nEqnTL, psiEqnBR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNNiP1jP1, fNNiP1jP1Binding, nEqnTL, nEqnBR) ;
}
}
pNode = pElem->pTRNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsiiM1, fPsiPsiiM1Binding, psiEqnTR, psiEqnTL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsijP1, fPsiPsijP1Binding, psiEqnTR, psiEqnBR) ;
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiiM1, fNPsiiM1Binding, nEqnTR, psiEqnTL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNNiM1, fNNiM1Binding, nEqnTR, nEqnTL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsijP1, fNPsijP1Binding, nEqnTR, psiEqnBR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNNjP1, fNNjP1Binding, nEqnTR, nEqnBR) ;
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiiM1jP1, fNPsiiM1jP1Binding, nEqnTR, psiEqnBL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNNiM1jP1, fNNiM1jP1Binding, nEqnTR, nEqnBL) ;
}
}
pNode = pElem->pBRNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsiiM1, fPsiPsiiM1Binding, psiEqnBR, psiEqnBL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsijM1, fPsiPsijM1Binding, psiEqnBR, psiEqnTR) ;
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiiM1, fNPsiiM1Binding, nEqnBR, psiEqnBL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNNiM1, fNNiM1Binding, nEqnBR, nEqnBL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsijM1, fNPsijM1Binding, nEqnBR, psiEqnTR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNNjM1, fNNjM1Binding, nEqnBR, nEqnTR) ;
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiiM1jM1, fNPsiiM1jM1Binding, nEqnBR, psiEqnTL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNNiM1jM1, fNNiM1jM1Binding, nEqnBR, nEqnTL) ;
}
}
pNode = pElem->pBLNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsiiP1, fPsiPsiiP1Binding, psiEqnBL, psiEqnBR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsijM1, fPsiPsijM1Binding, psiEqnBL, psiEqnTL) ;
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiiP1, fNPsiiP1Binding, nEqnBL, psiEqnBR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNNiP1, fNNiP1Binding, nEqnBL, nEqnBR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsijM1, fNPsijM1Binding, nEqnBL, psiEqnTL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNNjM1, fNNjM1Binding, nEqnBL, nEqnTL) ;
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiiP1jM1, fNPsiiP1jM1Binding, nEqnBL, psiEqnTR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNNiP1jM1, fNNiP1jM1Binding, nEqnBL, nEqnTR) ;
}
}
}
/*
* Add terms for surface-field of inversion-layer mobility model.
* Elements MUST be made from silicon for this to work.
* No empty elements are allowed.
* Don't need these pointers if SurfaceMobility isn't set.
*/
if ( MobDeriv && SurfaceMobility ) {
for ( pCh = pDevice->pChannel; pCh != NULL;
pCh = pCh->next ) {
pElem = pCh->pNElem;
switch (pCh->type) {
case 0:
psiEqnInM = pElem->pBLNode->psiEqn;
psiEqnInP = pElem->pBRNode->psiEqn;
psiEqnOxM = pElem->pTLNode->psiEqn;
psiEqnOxP = pElem->pTRNode->psiEqn;
break;
case 1:
psiEqnInM = pElem->pTLNode->psiEqn;
psiEqnInP = pElem->pBLNode->psiEqn;
psiEqnOxM = pElem->pTRNode->psiEqn;
psiEqnOxP = pElem->pBRNode->psiEqn;
break;
case 2:
psiEqnInM = pElem->pTLNode->psiEqn;
psiEqnInP = pElem->pTRNode->psiEqn;
psiEqnOxM = pElem->pBLNode->psiEqn;
psiEqnOxP = pElem->pBRNode->psiEqn;
break;
case 3:
psiEqnInM = pElem->pTRNode->psiEqn;
psiEqnInP = pElem->pBRNode->psiEqn;
psiEqnOxM = pElem->pTLNode->psiEqn;
psiEqnOxP = pElem->pBLNode->psiEqn;
break;
}
pElem = pCh->pSeed;
nextIndex = (pCh->type + 2)%4;
while (pElem && pElem->channel == pCh->id) {
for ( nIndex = 0; nIndex <= 3; nIndex++ ) {
pNode = pElem->pNodes[ nIndex ];
psiEqn = pNode->psiEqn;
nEqn = pNode->nEqn;
if ( pCh->type % 2 == 0 ) { /* Vertical Slice */
if ( nIndex == 0 || nIndex == 3 ) { /* Left Side */
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiIn, fNPsiInBinding, nEqn, psiEqnInM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiInP1, fNPsiInP1Binding, nEqn, psiEqnInP) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiOx, fNPsiOxBinding, nEqn, psiEqnOxM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiOxP1, fNPsiOxP1Binding, nEqn, psiEqnOxP) ;
} else { /* Right Side */
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiInM1, fNPsiInM1Binding, nEqn, psiEqnInM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiIn, fNPsiInBinding, nEqn, psiEqnInP) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiOxM1, fNPsiOxM1Binding, nEqn, psiEqnOxM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiOx, fNPsiOxBinding, nEqn, psiEqnOxP) ;
}
} else { /* Horizontal Slice */
if ( nIndex <= 1 ) { /* Top Side */
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiIn, fNPsiInBinding, nEqn, psiEqnInM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiInP1, fNPsiInP1Binding, nEqn, psiEqnInP) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiOx, fNPsiOxBinding, nEqn, psiEqnOxM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiOxP1, fNPsiOxP1Binding, nEqn, psiEqnOxP) ;
} else { /* Bottom Side */
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiInM1, fNPsiInM1Binding, nEqn, psiEqnInM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiIn, fNPsiInBinding, nEqn, psiEqnInP) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiOxM1, fNPsiOxM1Binding, nEqn, psiEqnOxM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiOx, fNPsiOxBinding, nEqn, psiEqnOxP) ;
}
}
} /* endfor nIndex */
pElem = pElem->pElems[ nextIndex ];
} /* endwhile pElem */
} /* endfor pCh */
} /* endif SurfaceMobility */
free (BindStructCSC) ;
}
#endif
/*
* The Jacobian and Rhs are loaded by the following function.
@ -269,7 +859,17 @@ void
}
/* zero the matrix */
spClear( pDevice->matrix );
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
SMPclearKLUforCIDER (pDevice->matrix) ;
} else {
#endif
SMPclear(pDevice->matrix);
#ifdef KLU
}
#endif
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];
@ -434,7 +1034,17 @@ void
TWONcommonTerms( pDevice, FALSE, FALSE, NULL );
/* zero the matrix */
spClear( pDevice->matrix );
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
SMPclearKLUforCIDER (pDevice->matrix) ;
} else {
#endif
SMPclear(pDevice->matrix);
#ifdef KLU
}
#endif
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];

View File

@ -16,6 +16,10 @@ Author: 1991 David A. Gates, U. C. Berkeley CAD Group
#include "ngspice/cidersupt.h"
#include "../../maths/misc/bernoull.h"
#ifdef KLU
#include "ngspice/klu-binding.h"
#endif
/*
* Functions to setup and solve the continuity equations.
* Both continuity equations are solved.
@ -53,16 +57,41 @@ void
pNode = pElem->pNodes[ nIndex ];
/* get poisson-only pointer */
psiEqn = pNode->psiEqn;
pNode->fPsiPsi = spGetElement( matrix, psiEqn, psiEqn );
#ifdef KLU
pNode->fPsiPsi = SMPmakeEltKLUforCIDER (matrix, psiEqn, psiEqn) ;
pNode->fPsiPsiBinding = NULL ;
#else
pNode->fPsiPsi = SMPmakeElt(matrix, psiEqn, psiEqn);
#endif
if ( pElem->elemType == SEMICON ) {
/* get continuity-coupling terms */
pEqn = pNode->pEqn;
pNode->nEqn = 0;
/* pointers for additional terms */
pNode->fPsiP = spGetElement( matrix, psiEqn, pEqn );
pNode->fPPsi = spGetElement( matrix, pEqn, psiEqn );
pNode->fPP = spGetElement( matrix, pEqn, pEqn );
#ifdef KLU
pNode->fPsiP = SMPmakeEltKLUforCIDER (matrix, psiEqn, pEqn) ;
pNode->fPsiPBinding = NULL ;
#else
pNode->fPsiP = SMPmakeElt(matrix, psiEqn, pEqn);
#endif
#ifdef KLU
pNode->fPPsi = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqn) ;
pNode->fPPsiBinding = NULL ;
#else
pNode->fPPsi = SMPmakeElt(matrix, pEqn, psiEqn);
#endif
#ifdef KLU
pNode->fPP = SMPmakeEltKLUforCIDER (matrix, pEqn, pEqn) ;
pNode->fPPBinding = NULL ;
#else
pNode->fPP = SMPmakeElt(matrix, pEqn, pEqn);
#endif
} else {
pEqn = 0;
}
@ -91,66 +120,270 @@ void
/* now terms to couple to adjacent nodes */
pNode = pElem->pTLNode;
pNode->fPsiPsiiP1 = spGetElement(matrix, psiEqnTL, psiEqnTR );
pNode->fPsiPsijP1 = spGetElement(matrix, psiEqnTL, psiEqnBL );
#ifdef KLU
pNode->fPsiPsiiP1 = SMPmakeEltKLUforCIDER (matrix, psiEqnTL, psiEqnTR) ;
pNode->fPsiPsiiP1Binding = NULL ;
#else
pNode->fPsiPsiiP1 = SMPmakeElt(matrix, psiEqnTL, psiEqnTR);
#endif
#ifdef KLU
pNode->fPsiPsijP1 = SMPmakeEltKLUforCIDER (matrix, psiEqnTL, psiEqnBL) ;
pNode->fPsiPsijP1Binding = NULL ;
#else
pNode->fPsiPsijP1 = SMPmakeElt(matrix, psiEqnTL, psiEqnBL);
#endif
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
pNode->fPPsiiP1 = spGetElement( matrix, pEqnTL, psiEqnTR );
pNode->fPPiP1 = spGetElement( matrix, pEqnTL, pEqnTR );
pNode->fPPsijP1 = spGetElement( matrix, pEqnTL, psiEqnBL );
pNode->fPPjP1 = spGetElement( matrix, pEqnTL, pEqnBL );
#ifdef KLU
pNode->fPPsiiP1 = SMPmakeEltKLUforCIDER (matrix, pEqnTL, psiEqnTR) ;
pNode->fPPsiiP1Binding = NULL ;
#else
pNode->fPPsiiP1 = SMPmakeElt(matrix, pEqnTL, psiEqnTR);
#endif
#ifdef KLU
pNode->fPPiP1 = SMPmakeEltKLUforCIDER (matrix, pEqnTL, pEqnTR) ;
pNode->fPPiP1Binding = NULL ;
#else
pNode->fPPiP1 = SMPmakeElt(matrix, pEqnTL, pEqnTR);
#endif
#ifdef KLU
pNode->fPPsijP1 = SMPmakeEltKLUforCIDER (matrix, pEqnTL, psiEqnBL) ;
pNode->fPPsijP1Binding = NULL ;
#else
pNode->fPPsijP1 = SMPmakeElt(matrix, pEqnTL, psiEqnBL);
#endif
#ifdef KLU
pNode->fPPjP1 = SMPmakeEltKLUforCIDER (matrix, pEqnTL, pEqnBL) ;
pNode->fPPjP1Binding = NULL ;
#else
pNode->fPPjP1 = SMPmakeElt(matrix, pEqnTL, pEqnBL);
#endif
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
pNode->fPPsiiP1jP1 = spGetElement( matrix, pEqnTL, psiEqnBR );
pNode->fPPiP1jP1 = spGetElement( matrix, pEqnTL, pEqnBR );
#ifdef KLU
pNode->fPPsiiP1jP1 = SMPmakeEltKLUforCIDER (matrix, pEqnTL, psiEqnBR) ;
pNode->fPPsiiP1jP1Binding = NULL ;
#else
pNode->fPPsiiP1jP1 = SMPmakeElt(matrix, pEqnTL, psiEqnBR);
#endif
#ifdef KLU
pNode->fPPiP1jP1 = SMPmakeEltKLUforCIDER (matrix, pEqnTL, pEqnBR) ;
pNode->fPPiP1jP1Binding = NULL ;
#else
pNode->fPPiP1jP1 = SMPmakeElt(matrix, pEqnTL, pEqnBR);
#endif
}
}
pNode = pElem->pTRNode;
pNode->fPsiPsiiM1 = spGetElement(matrix, psiEqnTR, psiEqnTL );
pNode->fPsiPsijP1 = spGetElement(matrix, psiEqnTR, psiEqnBR );
#ifdef KLU
pNode->fPsiPsiiM1 = SMPmakeEltKLUforCIDER (matrix, psiEqnTR, psiEqnTL) ;
pNode->fPsiPsiiM1Binding = NULL ;
#else
pNode->fPsiPsiiM1 = SMPmakeElt(matrix, psiEqnTR, psiEqnTL);
#endif
#ifdef KLU
pNode->fPsiPsijP1 = SMPmakeEltKLUforCIDER (matrix, psiEqnTR, psiEqnBR) ;
pNode->fPsiPsijP1Binding = NULL ;
#else
pNode->fPsiPsijP1 = SMPmakeElt(matrix, psiEqnTR, psiEqnBR);
#endif
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
pNode->fPPsiiM1 = spGetElement( matrix, pEqnTR, psiEqnTL );
pNode->fPPiM1 = spGetElement( matrix, pEqnTR, pEqnTL );
pNode->fPPsijP1 = spGetElement( matrix, pEqnTR, psiEqnBR );
pNode->fPPjP1 = spGetElement( matrix, pEqnTR, pEqnBR );
#ifdef KLU
pNode->fPPsiiM1 = SMPmakeEltKLUforCIDER (matrix, pEqnTR, psiEqnTL) ;
pNode->fPPsiiM1Binding = NULL ;
#else
pNode->fPPsiiM1 = SMPmakeElt(matrix, pEqnTR, psiEqnTL);
#endif
#ifdef KLU
pNode->fPPiM1 = SMPmakeEltKLUforCIDER (matrix, pEqnTR, pEqnTL) ;
pNode->fPPiM1Binding = NULL ;
#else
pNode->fPPiM1 = SMPmakeElt(matrix, pEqnTR, pEqnTL);
#endif
#ifdef KLU
pNode->fPPsijP1 = SMPmakeEltKLUforCIDER (matrix, pEqnTR, psiEqnBR) ;
pNode->fPPsijP1Binding = NULL ;
#else
pNode->fPPsijP1 = SMPmakeElt(matrix, pEqnTR, psiEqnBR);
#endif
#ifdef KLU
pNode->fPPjP1 = SMPmakeEltKLUforCIDER (matrix, pEqnTR, pEqnBR) ;
pNode->fPPjP1Binding = NULL ;
#else
pNode->fPPjP1 = SMPmakeElt(matrix, pEqnTR, pEqnBR);
#endif
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
pNode->fPPsiiM1jP1 = spGetElement( matrix, pEqnTR, psiEqnBL );
pNode->fPPiM1jP1 = spGetElement( matrix, pEqnTR, pEqnBL );
#ifdef KLU
pNode->fPPsiiM1jP1 = SMPmakeEltKLUforCIDER (matrix, pEqnTR, psiEqnBL) ;
pNode->fPPsiiM1jP1Binding = NULL ;
#else
pNode->fPPsiiM1jP1 = SMPmakeElt(matrix, pEqnTR, psiEqnBL);
#endif
#ifdef KLU
pNode->fPPiM1jP1 = SMPmakeEltKLUforCIDER (matrix, pEqnTR, pEqnBL) ;
pNode->fPPiM1jP1Binding = NULL ;
#else
pNode->fPPiM1jP1 = SMPmakeElt(matrix, pEqnTR, pEqnBL);
#endif
}
}
pNode = pElem->pBRNode;
pNode->fPsiPsiiM1 = spGetElement(matrix, psiEqnBR, psiEqnBL );
pNode->fPsiPsijM1 = spGetElement(matrix, psiEqnBR, psiEqnTR );
#ifdef KLU
pNode->fPsiPsiiM1 = SMPmakeEltKLUforCIDER (matrix, psiEqnBR, psiEqnBL) ;
pNode->fPsiPsiiM1Binding = NULL ;
#else
pNode->fPsiPsiiM1 = SMPmakeElt(matrix, psiEqnBR, psiEqnBL);
#endif
#ifdef KLU
pNode->fPsiPsijM1 = SMPmakeEltKLUforCIDER (matrix, psiEqnBR, psiEqnTR) ;
pNode->fPsiPsijM1Binding = NULL ;
#else
pNode->fPsiPsijM1 = SMPmakeElt(matrix, psiEqnBR, psiEqnTR);
#endif
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
pNode->fPPsiiM1 = spGetElement( matrix, pEqnBR, psiEqnBL );
pNode->fPPiM1 = spGetElement( matrix, pEqnBR, pEqnBL );
pNode->fPPsijM1 = spGetElement( matrix, pEqnBR, psiEqnTR );
pNode->fPPjM1 = spGetElement( matrix, pEqnBR, pEqnTR );
#ifdef KLU
pNode->fPPsiiM1 = SMPmakeEltKLUforCIDER (matrix, pEqnBR, psiEqnBL) ;
pNode->fPPsiiM1Binding = NULL ;
#else
pNode->fPPsiiM1 = SMPmakeElt(matrix, pEqnBR, psiEqnBL);
#endif
#ifdef KLU
pNode->fPPiM1 = SMPmakeEltKLUforCIDER (matrix, pEqnBR, pEqnBL) ;
pNode->fPPiM1Binding = NULL ;
#else
pNode->fPPiM1 = SMPmakeElt(matrix, pEqnBR, pEqnBL);
#endif
#ifdef KLU
pNode->fPPsijM1 = SMPmakeEltKLUforCIDER (matrix, pEqnBR, psiEqnTR) ;
pNode->fPPsijM1Binding = NULL ;
#else
pNode->fPPsijM1 = SMPmakeElt(matrix, pEqnBR, psiEqnTR);
#endif
#ifdef KLU
pNode->fPPjM1 = SMPmakeEltKLUforCIDER (matrix, pEqnBR, pEqnTR) ;
pNode->fPPjM1Binding = NULL ;
#else
pNode->fPPjM1 = SMPmakeElt(matrix, pEqnBR, pEqnTR);
#endif
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
pNode->fPPsiiM1jM1 = spGetElement( matrix, pEqnBR, psiEqnTL );
pNode->fPPiM1jM1 = spGetElement( matrix, pEqnBR, pEqnTL );
#ifdef KLU
pNode->fPPsiiM1jM1 = SMPmakeEltKLUforCIDER (matrix, pEqnBR, psiEqnTL) ;
pNode->fPPsiiM1jM1Binding = NULL ;
#else
pNode->fPPsiiM1jM1 = SMPmakeElt(matrix, pEqnBR, psiEqnTL);
#endif
#ifdef KLU
pNode->fPPiM1jM1 = SMPmakeEltKLUforCIDER (matrix, pEqnBR, pEqnTL) ;
pNode->fPPiM1jM1Binding = NULL ;
#else
pNode->fPPiM1jM1 = SMPmakeElt(matrix, pEqnBR, pEqnTL);
#endif
}
}
pNode = pElem->pBLNode;
pNode->fPsiPsiiP1 = spGetElement(matrix, psiEqnBL, psiEqnBR );
pNode->fPsiPsijM1 = spGetElement(matrix, psiEqnBL, psiEqnTL );
#ifdef KLU
pNode->fPsiPsiiP1 = SMPmakeEltKLUforCIDER (matrix, psiEqnBL, psiEqnBR) ;
pNode->fPsiPsiiP1Binding = NULL ;
#else
pNode->fPsiPsiiP1 = SMPmakeElt(matrix, psiEqnBL, psiEqnBR);
#endif
#ifdef KLU
pNode->fPsiPsijM1 = SMPmakeEltKLUforCIDER (matrix, psiEqnBL, psiEqnTL) ;
pNode->fPsiPsijM1Binding = NULL ;
#else
pNode->fPsiPsijM1 = SMPmakeElt(matrix, psiEqnBL, psiEqnTL);
#endif
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
pNode->fPPsiiP1 = spGetElement( matrix, pEqnBL, psiEqnBR );
pNode->fPPiP1 = spGetElement( matrix, pEqnBL, pEqnBR );
pNode->fPPsijM1 = spGetElement( matrix, pEqnBL, psiEqnTL );
pNode->fPPjM1 = spGetElement( matrix, pEqnBL, pEqnTL );
#ifdef KLU
pNode->fPPsiiP1 = SMPmakeEltKLUforCIDER (matrix, pEqnBL, psiEqnBR) ;
pNode->fPPsiiP1Binding = NULL ;
#else
pNode->fPPsiiP1 = SMPmakeElt(matrix, pEqnBL, psiEqnBR);
#endif
#ifdef KLU
pNode->fPPiP1 = SMPmakeEltKLUforCIDER (matrix, pEqnBL, pEqnBR) ;
pNode->fPPiP1Binding = NULL ;
#else
pNode->fPPiP1 = SMPmakeElt(matrix, pEqnBL, pEqnBR);
#endif
#ifdef KLU
pNode->fPPsijM1 = SMPmakeEltKLUforCIDER (matrix, pEqnBL, psiEqnTL) ;
pNode->fPPsijM1Binding = NULL ;
#else
pNode->fPPsijM1 = SMPmakeElt(matrix, pEqnBL, psiEqnTL);
#endif
#ifdef KLU
pNode->fPPjM1 = SMPmakeEltKLUforCIDER (matrix, pEqnBL, pEqnTL) ;
pNode->fPPjM1Binding = NULL ;
#else
pNode->fPPjM1 = SMPmakeElt(matrix, pEqnBL, pEqnTL);
#endif
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
pNode->fPPsiiP1jM1 = spGetElement( matrix, pEqnBL, psiEqnTR );
pNode->fPPiP1jM1 = spGetElement( matrix, pEqnBL, pEqnTR );
#ifdef KLU
pNode->fPPsiiP1jM1 = SMPmakeEltKLUforCIDER (matrix, pEqnBL, psiEqnTR) ;
pNode->fPPsiiP1jM1Binding = NULL ;
#else
pNode->fPPsiiP1jM1 = SMPmakeElt(matrix, pEqnBL, psiEqnTR);
#endif
#ifdef KLU
pNode->fPPiP1jM1 = SMPmakeEltKLUforCIDER (matrix, pEqnBL, pEqnTR) ;
pNode->fPPiP1jM1Binding = NULL ;
#else
pNode->fPPiP1jM1 = SMPmakeElt(matrix, pEqnBL, pEqnTR);
#endif
}
}
}
@ -199,27 +432,135 @@ void
pEqn = pNode->pEqn;
if ( pCh->type % 2 == 0 ) { /* Vertical Slice */
if ( nIndex == 0 || nIndex == 3 ) { /* Left Side */
pNode->fPPsiIn = spGetElement( matrix, pEqn, psiEqnInM );
pNode->fPPsiInP1 = spGetElement( matrix, pEqn, psiEqnInP );
pNode->fPPsiOx = spGetElement( matrix, pEqn, psiEqnOxM );
pNode->fPPsiOxP1 = spGetElement( matrix, pEqn, psiEqnOxP );
#ifdef KLU
pNode->fPPsiIn = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnInM) ;
pNode->fPPsiInBinding = NULL ;
#else
pNode->fPPsiIn = SMPmakeElt(matrix, pEqn, psiEqnInM);
#endif
#ifdef KLU
pNode->fPPsiInP1 = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnInP) ;
pNode->fPPsiInP1Binding = NULL ;
#else
pNode->fPPsiInP1 = SMPmakeElt(matrix, pEqn, psiEqnInP);
#endif
#ifdef KLU
pNode->fPPsiOx = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnOxM) ;
pNode->fPPsiOxBinding = NULL ;
#else
pNode->fPPsiOx = SMPmakeElt(matrix, pEqn, psiEqnOxM);
#endif
#ifdef KLU
pNode->fPPsiOxP1 = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnOxP) ;
pNode->fPPsiOxP1Binding = NULL ;
#else
pNode->fPPsiOxP1 = SMPmakeElt(matrix, pEqn, psiEqnOxP);
#endif
} else { /* Right Side */
pNode->fPPsiInM1 = spGetElement( matrix, pEqn, psiEqnInM );
pNode->fPPsiIn = spGetElement( matrix, pEqn, psiEqnInP );
pNode->fPPsiOxM1 = spGetElement( matrix, pEqn, psiEqnOxM );
pNode->fPPsiOx = spGetElement( matrix, pEqn, psiEqnOxP );
#ifdef KLU
pNode->fPPsiInM1 = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnInM) ;
pNode->fPPsiInM1Binding = NULL ;
#else
pNode->fPPsiInM1 = SMPmakeElt(matrix, pEqn, psiEqnInM);
#endif
#ifdef KLU
pNode->fPPsiIn = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnInP) ;
pNode->fPPsiInBinding = NULL ;
#else
pNode->fPPsiIn = SMPmakeElt(matrix, pEqn, psiEqnInP);
#endif
#ifdef KLU
pNode->fPPsiOxM1 = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnOxM) ;
pNode->fPPsiOxM1Binding = NULL ;
#else
pNode->fPPsiOxM1 = SMPmakeElt(matrix, pEqn, psiEqnOxM);
#endif
#ifdef KLU
pNode->fPPsiOx = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnOxP) ;
pNode->fPPsiOxBinding = NULL ;
#else
pNode->fPPsiOx = SMPmakeElt(matrix, pEqn, psiEqnOxP);
#endif
}
} else { /* Horizontal Slice */
if ( nIndex == 0 || nIndex == 3 ) { /* Left (Top?) Side : bug 483 */
pNode->fPPsiIn = spGetElement( matrix, pEqn, psiEqnInM );
pNode->fPPsiInP1 = spGetElement( matrix, pEqn, psiEqnInP );
pNode->fPPsiOx = spGetElement( matrix, pEqn, psiEqnOxM );
pNode->fPPsiOxP1 = spGetElement( matrix, pEqn, psiEqnOxP );
// <<<<<<< HEAD
// if ( nIndex == 0 || nIndex == 3 ) { /* Left (Top?) Side : bug 483 */
// pNode->fPPsiIn = spGetElement( matrix, pEqn, psiEqnInM );
// pNode->fPPsiInP1 = spGetElement( matrix, pEqn, psiEqnInP );
// pNode->fPPsiOx = spGetElement( matrix, pEqn, psiEqnOxM );
// pNode->fPPsiOxP1 = spGetElement( matrix, pEqn, psiEqnOxP );
// =======
if ( nIndex <= 1 ) { /* Top Side */
//
// #ifdef KLU
// pNode->fPPsiIn = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnInM) ;
// pNode->fPPsiInBinding = NULL ;
// #else
// pNode->fPPsiIn = SMPmakeElt(matrix, pEqn, psiEqnInM);
// #endif
//
// #ifdef KLU
// pNode->fPPsiInP1 = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnInP) ;
// pNode->fPPsiInP1Binding = NULL ;
// #else
// pNode->fPPsiInP1 = SMPmakeElt(matrix, pEqn, psiEqnInP);
// #endif
//
// #ifdef KLU
// pNode->fPPsiOx = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnOxM) ;
// pNode->fPPsiOxBinding = NULL ;
// #else
// pNode->fPPsiOx = SMPmakeElt(matrix, pEqn, psiEqnOxM);
// #endif
//
// #ifdef KLU
// pNode->fPPsiOxP1 = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnOxP) ;
// pNode->fPPsiOxP1Binding = NULL ;
// #else
// pNode->fPPsiOxP1 = SMPmakeElt(matrix, pEqn, psiEqnOxP);
// #endif
//
// >>>>>>> First KLU support of CIDER TWOD simulations
} else { /* Bottom Side */
pNode->fPPsiInM1 = spGetElement( matrix, pEqn, psiEqnInM );
pNode->fPPsiIn = spGetElement( matrix, pEqn, psiEqnInP );
pNode->fPPsiOxM1 = spGetElement( matrix, pEqn, psiEqnOxM );
pNode->fPPsiOx = spGetElement( matrix, pEqn, psiEqnOxP );
#ifdef KLU
pNode->fPPsiInM1 = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnInM) ;
pNode->fPPsiInM1Binding = NULL ;
#else
pNode->fPPsiInM1 = SMPmakeElt(matrix, pEqn, psiEqnInM);
#endif
#ifdef KLU
pNode->fPPsiIn = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnInP) ;
pNode->fPPsiInBinding = NULL ;
#else
pNode->fPPsiIn = SMPmakeElt(matrix, pEqn, psiEqnInP);
#endif
#ifdef KLU
pNode->fPPsiOxM1 = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnOxM) ;
pNode->fPPsiOxM1Binding = NULL ;
#else
pNode->fPPsiOxM1 = SMPmakeElt(matrix, pEqn, psiEqnOxM);
#endif
#ifdef KLU
pNode->fPPsiOx = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnOxP) ;
pNode->fPPsiOxBinding = NULL ;
#else
pNode->fPPsiOx = SMPmakeElt(matrix, pEqn, psiEqnOxP);
#endif
}
}
} /* endfor nIndex */
@ -229,6 +570,256 @@ void
} /* endif SurfaceMobility */
}
#ifdef KLU
void
TWOPbindCSC (TWOdevice *pDevice)
{
TWOelem *pElem;
TWOnode *pNode;
TWOchannel *pCh;
BindElementKLUforCIDER i, *matched, *BindStruct, *BindStructCSC ;
int index ;
size_t nz ;
int eIndex, nIndex;
int nextIndex; /* index of node to find next element */
int psiEqn, pEqn; /* scratch for deref'd eqn numbers */
int psiEqnTL = 0, pEqnTL = 0;
int psiEqnTR = 0, pEqnTR = 0;
int psiEqnBR = 0, pEqnBR = 0;
int psiEqnBL = 0, pEqnBL = 0;
int psiEqnInM = 0, psiEqnInP = 0; /* scratch for deref'd surface eqns */
int psiEqnOxM = 0, psiEqnOxP = 0; /* M= more negative, P= more positive */
BindStruct = pDevice->matrix->SMPkluMatrix->KLUmatrixBindStructForCIDER ;
nz = pDevice->matrix->SMPkluMatrix->KLUmatrixNZ ;
BindStructCSC = (BindElementKLUforCIDER *) malloc (nz * sizeof (BindElementKLUforCIDER)) ;
for (index = 0 ; index < (int)nz ; index++) {
BindStructCSC [index] = BindStruct [index] ;
}
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];
/* first the self terms */
for ( nIndex = 0; nIndex <= 3; nIndex++ ) {
pNode = pElem->pNodes[ nIndex ];
/* get poisson-only pointer */
psiEqn = pNode->psiEqn;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsi, fPsiPsiBinding, psiEqn, psiEqn) ;
if ( pElem->elemType == SEMICON ) {
/* get continuity-coupling terms */
pEqn = pNode->pEqn;
pNode->nEqn = 0;
/* pointers for additional terms */
CREATE_KLU_BINDING_TABLE_CIDER(fPsiP, fPsiPBinding, psiEqn, pEqn) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsi, fPPsiBinding, pEqn, psiEqn) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPP, fPPBinding, pEqn, pEqn) ;
} else {
pEqn = 0;
}
/* save equation indices */
switch ( nIndex ) {
case 0: /* TL Node */
psiEqnTL = psiEqn;
pEqnTL = pEqn;
break;
case 1: /* TR Node */
psiEqnTR = psiEqn;
pEqnTR = pEqn;
break;
case 2: /* BR Node */
psiEqnBR = psiEqn;
pEqnBR = pEqn;
break;
case 3: /* BL Node */
psiEqnBL = psiEqn;
pEqnBL = pEqn;
break;
default:
break;
}
}
/* now terms to couple to adjacent nodes */
pNode = pElem->pTLNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsiiP1, fPsiPsiiP1Binding, psiEqnTL, psiEqnTR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsijP1, fPsiPsijP1Binding, psiEqnTL, psiEqnBL) ;
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiiP1, fPPsiiP1Binding, pEqnTL, psiEqnTR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPiP1, fPPiP1Binding, pEqnTL, pEqnTR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsijP1, fPPsijP1Binding, pEqnTL, psiEqnBL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPjP1, fPPjP1Binding, pEqnTL, pEqnBL) ;
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiiP1jP1, fPPsiiP1jP1Binding, pEqnTL, psiEqnBR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPiP1jP1, fPPiP1jP1Binding, pEqnTL, pEqnBR) ;
}
}
pNode = pElem->pTRNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsiiM1, fPsiPsiiM1Binding, psiEqnTR, psiEqnTL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsijP1, fPsiPsijP1Binding, psiEqnTR, psiEqnBR) ;
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiiM1, fPPsiiM1Binding, pEqnTR, psiEqnTL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPiM1, fPPiM1Binding, pEqnTR, pEqnTL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsijP1, fPPsijP1Binding, pEqnTR, psiEqnBR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPjP1, fPPjP1Binding, pEqnTR, pEqnBR) ;
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiiM1jP1, fPPsiiM1jP1Binding, pEqnTR, psiEqnBL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPiM1jP1, fPPiM1jP1Binding, pEqnTR, pEqnBL) ;
}
}
pNode = pElem->pBRNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsiiM1, fPsiPsiiM1Binding, psiEqnBR, psiEqnBL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsijM1, fPsiPsijM1Binding, psiEqnBR, psiEqnTR) ;
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiiM1, fPPsiiM1Binding, pEqnBR, psiEqnBL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPiM1, fPPiM1Binding, pEqnBR, pEqnBL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsijM1, fPPsijM1Binding, pEqnBR, psiEqnTR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPjM1, fPPjM1Binding, pEqnBR, pEqnTR) ;
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiiM1jM1, fPPsiiM1jM1Binding, pEqnBR, psiEqnTL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPiM1jM1, fPPiM1jM1Binding, pEqnBR, pEqnTL) ;
}
}
pNode = pElem->pBLNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsiiP1, fPsiPsiiP1Binding, psiEqnBL, psiEqnBR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsijM1, fPsiPsijM1Binding, psiEqnBL, psiEqnTL) ;
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiiP1, fPPsiiP1Binding, pEqnBL, psiEqnBR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPiP1, fPPiP1Binding, pEqnBL, pEqnBR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsijM1, fPPsijM1Binding, pEqnBL, psiEqnTL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPjM1, fPPjM1Binding, pEqnBL, pEqnTL) ;
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiiP1jM1, fPPsiiP1jM1Binding, pEqnBL, psiEqnTR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPiP1jM1, fPPiP1jM1Binding, pEqnBL, pEqnTR) ;
}
}
}
/*
* Add terms for surface-field of inversion-layer mobility model.
* Elements MUST be made from silicon for this to work.
* No empty elements are allowed.
* Don't need these pointers if SurfaceMobility isn't set.
*/
if ( MobDeriv && SurfaceMobility ) {
for ( pCh = pDevice->pChannel; pCh != NULL;
pCh = pCh->next ) {
pElem = pCh->pNElem;
switch (pCh->type) {
case 0:
psiEqnInM = pElem->pBLNode->psiEqn;
psiEqnInP = pElem->pBRNode->psiEqn;
psiEqnOxM = pElem->pTLNode->psiEqn;
psiEqnOxP = pElem->pTRNode->psiEqn;
break;
case 1:
psiEqnInM = pElem->pTLNode->psiEqn;
psiEqnInP = pElem->pBLNode->psiEqn;
psiEqnOxM = pElem->pTRNode->psiEqn;
psiEqnOxP = pElem->pBRNode->psiEqn;
break;
case 2:
psiEqnInM = pElem->pTLNode->psiEqn;
psiEqnInP = pElem->pTRNode->psiEqn;
psiEqnOxM = pElem->pBLNode->psiEqn;
psiEqnOxP = pElem->pBRNode->psiEqn;
break;
case 3:
psiEqnInM = pElem->pTRNode->psiEqn;
psiEqnInP = pElem->pBRNode->psiEqn;
psiEqnOxM = pElem->pTLNode->psiEqn;
psiEqnOxP = pElem->pBLNode->psiEqn;
break;
}
pElem = pCh->pSeed;
nextIndex = (pCh->type + 2)%4;
while (pElem && pElem->channel == pCh->id) {
for ( nIndex = 0; nIndex <= 3; nIndex++ ) {
pNode = pElem->pNodes[ nIndex ];
psiEqn = pNode->psiEqn;
pEqn = pNode->pEqn;
if ( pCh->type % 2 == 0 ) { /* Vertical Slice */
if ( nIndex == 0 || nIndex == 3 ) { /* Left Side */
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiIn, fPPsiInBinding, pEqn, psiEqnInM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiInP1, fPPsiInP1Binding, pEqn, psiEqnInP) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiOx, fPPsiOxBinding, pEqn, psiEqnOxM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiOxP1, fPPsiOxP1Binding, pEqn, psiEqnOxP) ;
} else { /* Right Side */
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiInM1, fPPsiInM1Binding, pEqn, psiEqnInM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiIn, fPPsiInBinding, pEqn, psiEqnInP) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiOxM1, fPPsiOxM1Binding, pEqn, psiEqnOxM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiOx, fPPsiOxBinding, pEqn, psiEqnOxP) ;
}
} else { /* Horizontal Slice */
if ( nIndex <= 1 ) { /* Top Side */
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiIn, fPPsiInBinding, pEqn, psiEqnInM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiInP1, fPPsiInP1Binding, pEqn, psiEqnInP) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiOx, fPPsiOxBinding, pEqn, psiEqnOxM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiOxP1, fPPsiOxP1Binding, pEqn, psiEqnOxP) ;
} else { /* Bottom Side */
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiInM1, fPPsiInM1Binding, pEqn, psiEqnInM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiIn, fPPsiInBinding, pEqn, psiEqnInP) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiOxM1, fPPsiOxM1Binding, pEqn, psiEqnOxM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiOx, fPPsiOxBinding, pEqn, psiEqnOxP) ;
}
}
} /* endfor nIndex */
pElem = pElem->pElems[ nextIndex ];
} /* endwhile pElem */
} /* endfor pCh */
} /* endif SurfaceMobility */
free (BindStructCSC) ;
}
#endif
/*
* The Jacobian and Rhs are loaded by the following function.
@ -268,7 +859,17 @@ void
}
/* zero the matrix */
spClear( pDevice->matrix );
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
SMPclearKLUforCIDER (pDevice->matrix) ;
} else {
#endif
SMPclear(pDevice->matrix);
#ifdef KLU
}
#endif
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];
@ -432,7 +1033,17 @@ void
TWOPcommonTerms( pDevice, FALSE, FALSE, NULL );
/* zero the matrix */
spClear( pDevice->matrix );
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
SMPclearKLUforCIDER (pDevice->matrix) ;
} else {
#endif
SMPclear(pDevice->matrix);
#ifdef KLU
}
#endif
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];

View File

@ -13,6 +13,9 @@ Author: 1991 David A. Gates, U. C. Berkeley CAD Group
#include "twoddefs.h"
#include "twodext.h"
#ifdef KLU
#include "ngspice/klu-binding.h"
#endif
/* functions to setup and solve the 2D poisson equation */
@ -31,7 +34,14 @@ TWOQjacBuild(TWOdevice *pDevice)
for ( nIndex = 0; nIndex <= 3; nIndex++ ) {
if ( pElem->evalNodes[ nIndex ] ) {
pNode = pElem->pNodes[ nIndex ];
pNode->fPsiPsi = spGetElement( matrix, pNode->poiEqn, pNode->poiEqn );
#ifdef KLU
pNode->fPsiPsi = SMPmakeEltKLUforCIDER (matrix, pNode->poiEqn, pNode->poiEqn) ;
pNode->fPsiPsiBinding = NULL ;
#else
pNode->fPsiPsi = SMPmakeElt(matrix, pNode->poiEqn, pNode->poiEqn);
#endif
}
}
}
@ -40,24 +50,80 @@ TWOQjacBuild(TWOdevice *pDevice)
pNode = pElem->pTLNode;
pNode1 = pElem->pTRNode;
pNode->fPsiPsiiP1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn );
#ifdef KLU
pNode->fPsiPsiiP1 = SMPmakeEltKLUforCIDER (matrix, pNode->poiEqn, pNode1->poiEqn) ;
pNode->fPsiPsiiP1Binding = NULL ;
#else
pNode->fPsiPsiiP1 = SMPmakeElt(matrix, pNode->poiEqn, pNode1->poiEqn);
#endif
pNode1 = pElem->pBLNode;
pNode->fPsiPsijP1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn );
#ifdef KLU
pNode->fPsiPsijP1 = SMPmakeEltKLUforCIDER (matrix, pNode->poiEqn, pNode1->poiEqn) ;
pNode->fPsiPsijP1Binding = NULL ;
#else
pNode->fPsiPsijP1 = SMPmakeElt(matrix, pNode->poiEqn, pNode1->poiEqn);
#endif
pNode = pElem->pTRNode;
pNode1 = pElem->pTLNode;
pNode->fPsiPsiiM1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn );
#ifdef KLU
pNode->fPsiPsiiM1 = SMPmakeEltKLUforCIDER (matrix, pNode->poiEqn, pNode1->poiEqn) ;
pNode->fPsiPsiiM1Binding = NULL ;
#else
pNode->fPsiPsiiM1 = SMPmakeElt(matrix, pNode->poiEqn, pNode1->poiEqn);
#endif
pNode1 = pElem->pBRNode;
pNode->fPsiPsijP1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn );
#ifdef KLU
pNode->fPsiPsijP1 = SMPmakeEltKLUforCIDER (matrix, pNode->poiEqn, pNode1->poiEqn) ;
pNode->fPsiPsijP1Binding = NULL ;
#else
pNode->fPsiPsijP1 = SMPmakeElt(matrix, pNode->poiEqn, pNode1->poiEqn);
#endif
pNode = pElem->pBRNode;
pNode1 = pElem->pBLNode;
pNode->fPsiPsiiM1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn );
#ifdef KLU
pNode->fPsiPsiiM1 = SMPmakeEltKLUforCIDER (matrix, pNode->poiEqn, pNode1->poiEqn) ;
pNode->fPsiPsiiM1Binding = NULL ;
#else
pNode->fPsiPsiiM1 = SMPmakeElt(matrix, pNode->poiEqn, pNode1->poiEqn);
#endif
pNode1 = pElem->pTRNode;
pNode->fPsiPsijM1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn );
#ifdef KLU
pNode->fPsiPsijM1 = SMPmakeEltKLUforCIDER (matrix, pNode->poiEqn, pNode1->poiEqn) ;
pNode->fPsiPsijM1Binding = NULL ;
#else
pNode->fPsiPsijM1 = SMPmakeElt(matrix, pNode->poiEqn, pNode1->poiEqn);
#endif
pNode = pElem->pBLNode;
pNode1 = pElem->pBRNode;
pNode->fPsiPsiiP1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn );
#ifdef KLU
pNode->fPsiPsiiP1 = SMPmakeEltKLUforCIDER (matrix, pNode->poiEqn, pNode1->poiEqn) ;
pNode->fPsiPsiiP1Binding = NULL ;
#else
pNode->fPsiPsiiP1 = SMPmakeElt(matrix, pNode->poiEqn, pNode1->poiEqn);
#endif
pNode1 = pElem->pTLNode;
pNode->fPsiPsijM1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn );
#ifdef KLU
pNode->fPsiPsijM1 = SMPmakeEltKLUforCIDER (matrix, pNode->poiEqn, pNode1->poiEqn) ;
pNode->fPsiPsijM1Binding = NULL ;
#else
pNode->fPsiPsijM1 = SMPmakeElt(matrix, pNode->poiEqn, pNode1->poiEqn);
#endif
}
/*
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
@ -91,6 +157,81 @@ TWOQjacBuild(TWOdevice *pDevice)
*/
}
#ifdef KLU
void
TWOQbindCSC (TWOdevice *pDevice)
{
TWOelem *pElem;
TWOnode *pNode, *pNode1;
int eIndex, nIndex;
int index ;
BindElementKLUforCIDER i, *matched, *BindStruct, *BindStructCSC ;
size_t nz ;
BindStruct = pDevice->matrix->SMPkluMatrix->KLUmatrixBindStructForCIDER ;
nz = pDevice->matrix->SMPkluMatrix->KLUmatrixNZ ;
BindStructCSC = (BindElementKLUforCIDER *) malloc (nz * sizeof (BindElementKLUforCIDER)) ;
for (index = 0 ; index < (int)nz ; index++) {
BindStructCSC [index] = BindStruct [index] ;
}
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];
for ( nIndex = 0; nIndex <= 3; nIndex++ ) {
if ( pElem->evalNodes[ nIndex ] ) {
pNode = pElem->pNodes[ nIndex ];
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsi, fPsiPsiBinding, pNode->poiEqn, pNode->poiEqn) ;
}
}
}
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];
pNode = pElem->pTLNode;
pNode1 = pElem->pTRNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsiiP1, fPsiPsiiP1Binding, pNode->poiEqn, pNode1->poiEqn) ;
pNode1 = pElem->pBLNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsijP1, fPsiPsijP1Binding, pNode->poiEqn, pNode1->poiEqn) ;
pNode = pElem->pTRNode;
pNode1 = pElem->pTLNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsiiM1, fPsiPsiiM1Binding, pNode->poiEqn, pNode1->poiEqn) ;
pNode1 = pElem->pBRNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsijP1, fPsiPsijP1Binding, pNode->poiEqn, pNode1->poiEqn) ;
pNode = pElem->pBRNode;
pNode1 = pElem->pBLNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsiiM1, fPsiPsiiM1Binding, pNode->poiEqn, pNode1->poiEqn) ;
pNode1 = pElem->pTRNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsijM1, fPsiPsijM1Binding, pNode->poiEqn, pNode1->poiEqn) ;
pNode = pElem->pBLNode;
pNode1 = pElem->pBRNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsiiP1, fPsiPsiiP1Binding, pNode->poiEqn, pNode1->poiEqn) ;
pNode1 = pElem->pTLNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsijM1, fPsiPsijM1Binding, pNode->poiEqn, pNode1->poiEqn) ;
}
free (BindStructCSC) ;
}
#endif
void
TWOQsysLoad(TWOdevice *pDevice)
{
@ -109,7 +250,17 @@ TWOQsysLoad(TWOdevice *pDevice)
}
/* zero the matrix */
spClear( pDevice->matrix );
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
SMPclearKLUforCIDER (pDevice->matrix) ;
} else {
#endif
SMPclear(pDevice->matrix);
#ifdef KLU
}
#endif
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];

View File

@ -52,8 +52,13 @@ void NUMD2project(TWOdevice *pDevice, double delV)
}
incVpn = pDevice->dcDeltaSolution;
storeNewRhs( pDevice, pContact );
spSolve( pDevice->matrix, pDevice->rhs, incVpn, NULL, NULL );
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVpn, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVpn) ;
#endif
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];
for ( index = 0; index <= 3; index++ ) {
@ -131,8 +136,13 @@ void NBJT2project(TWOdevice *pDevice, double delVce, double delVbe)
if ( ABS( delVce ) > MIN_DELV ) {
incVce = pDevice->dcDeltaSolution;
storeNewRhs( pDevice, pColContact );
spSolve( pDevice->matrix, pDevice->rhs, incVce, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVce, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVce) ;
#endif
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];
for ( index = 0; index <= 3; index++ ) {
@ -175,8 +185,13 @@ void NBJT2project(TWOdevice *pDevice, double delVce, double delVbe)
if ( ABS( delVbe ) > MIN_DELV ) {
incVbe = pDevice->copiedSolution;
storeNewRhs( pDevice, pBaseContact );
spSolve( pDevice->matrix, pDevice->rhs, incVbe, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVbe, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVbe) ;
#endif
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];
for ( index = 0; index <= 3; index++ ) {
@ -265,8 +280,13 @@ void NUMOSproject(TWOdevice *pDevice, double delVdb, double delVsb,
incVdb = pDevice->dcDeltaSolution;
storeNewRhs( pDevice, pDContact );
spSolve( pDevice->matrix, pDevice->rhs, incVdb, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVdb, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVdb) ;
#endif
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];
for ( index = 0; index <= 3; index++ ) {
@ -310,8 +330,13 @@ void NUMOSproject(TWOdevice *pDevice, double delVdb, double delVsb,
incVsb = pDevice->dcDeltaSolution;
storeNewRhs( pDevice, pSContact );
spSolve( pDevice->matrix, pDevice->rhs, incVsb, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVsb, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVsb) ;
#endif
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];
for ( index = 0; index <= 3; index++ ) {
@ -354,8 +379,13 @@ void NUMOSproject(TWOdevice *pDevice, double delVdb, double delVsb,
incVgb = pDevice->dcDeltaSolution;
storeNewRhs( pDevice, pGContact );
spSolve( pDevice->matrix, pDevice->rhs, incVgb, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVgb, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVgb) ;
#endif
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];
for ( index = 0; index <= 3; index++ ) {

View File

@ -18,6 +18,9 @@ Author: 1991 David A. Gates, U. C. Berkeley CAD Group
#include "ngspice/twomesh.h"
#include "twoddefs.h"
#include "twodext.h"
#include "ngspice/cktdefs.h"
#include "ngspice/ftedefs.h"
extern IFfrontEnd *SPfrontEnd;
@ -92,7 +95,13 @@ TWOdcSolve(TWOdevice *pDevice, int iterationLimit, BOOLEAN newSolver,
/* FACTOR */
startTime = SPfrontEnd->IFseconds();
error = spFactor(pDevice->matrix);
#ifdef KLU
error = SMPreorderKLUforCIDER (pDevice->matrix) ;
#else
error = SMPluFacForCIDER (pDevice->matrix) ;
#endif
factorTime += SPfrontEnd->IFseconds() - startTime;
if (newSolver) {
if (pDevice->iterationNumber == 1) {
@ -116,7 +125,7 @@ TWOdcSolve(TWOdevice *pDevice, int iterationLimit, BOOLEAN newSolver,
if (foundError(error)) {
if (error == spSINGULAR) {
int badRow, badCol;
spWhereSingular(pDevice->matrix, &badRow, &badCol);
SMPgetError(pDevice->matrix, &badRow, &badCol);
printf("***** singular at (%d,%d)\n", badRow, badCol);
}
pDevice->converged = FALSE;
@ -126,7 +135,13 @@ TWOdcSolve(TWOdevice *pDevice, int iterationLimit, BOOLEAN newSolver,
/* SOLVE */
startTime = SPfrontEnd->IFseconds();
spSolve(pDevice->matrix, rhs, delta, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhs, delta, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, rhs, delta) ;
#endif
solveTime += SPfrontEnd->IFseconds() - startTime;
/* UPDATE */
@ -362,7 +377,13 @@ TWOresetJacobian(TWOdevice *pDevice)
printf("TWOresetJacobian: unknown carrier type\n");
exit(-1);
}
error = spFactor(pDevice->matrix);
#ifdef KLU
error = SMPreorderKLUforCIDER (pDevice->matrix) ;
#else
error = SMPluFacForCIDER (pDevice->matrix) ;
#endif
if (foundError(error)) {
exit(-1);
}
@ -464,7 +485,16 @@ int TWOequilSolve(TWOdevice *pDevice)
FREE(pDevice->copiedSolution);
FREE(pDevice->rhs);
FREE(pDevice->rhsImag);
spDestroy(pDevice->matrix);
#ifdef KLU
SMPdestroyKLUforCIDER (pDevice->matrix) ;
#else
SMPdestroy (pDevice->matrix) ;
#endif
if (pDevice->matrix) {
FREE(pDevice->matrix);
}
/* FALLTHROUGH */
case SLV_NONE: {
/* Allocate memory needed for an equilibrium solution */
@ -476,15 +506,63 @@ int TWOequilSolve(TWOdevice *pDevice)
XCALLOC(pDevice->dcDeltaSolution, double, n_dim);
XCALLOC(pDevice->copiedSolution, double, n_dim);
XCALLOC(pDevice->rhs, double, n_dim);
pDevice->matrix = spCreate(n_eqn, 0, &error);
pDevice->matrix = TMALLOC (SMPmatrix, 1) ;
#ifdef KLU
pDevice->matrix->CKTkluMODE = ft_curckt->ci_ckt->CKTkluMODE ;
error = SMPnewMatrixKLUforCIDER (pDevice->matrix, pDevice->numEqns, KLUmatrixReal) ;
#else
error = SMPnewMatrixForCIDER (pDevice->matrix, pDevice->numEqns, 0) ;
#endif
if (error == spNO_MEMORY) {
(void) fprintf(cp_err, "TWOequilSolve: Out of Memory\n");
return E_NOMEM;
}
newSolver = TRUE;
spSetReal(pDevice->matrix); /* set to a real matrix */
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = KLUmatrixReal ;
} else {
#endif
spSetReal (pDevice->matrix->SPmatrix) ;
#ifdef KLU
}
#endif
TWOQjacBuild(pDevice);
pDevice->numOrigEquil = spElementCount(pDevice->matrix);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
/* Convert the COO Storage to CSC for KLU and Fill the Binding Table */
SMPconvertCOOtoCSCKLUforCIDER (pDevice->matrix) ;
/* Bind the KLU Pointers */
TWOQbindCSC (pDevice) ;
/* Perform KLU Matrix Analysis */
pDevice->matrix->SMPkluMatrix->KLUmatrixSymbolic = klu_analyze ((int)pDevice->matrix->SMPkluMatrix->KLUmatrixN, pDevice->matrix->SMPkluMatrix->KLUmatrixAp,
pDevice->matrix->SMPkluMatrix->KLUmatrixAi, pDevice->matrix->SMPkluMatrix->KLUmatrixCommon) ;
if (pDevice->matrix->SMPkluMatrix->KLUmatrixSymbolic == NULL) {
printf ("CIDER: KLU Failed\n") ;
if (pDevice->matrix->SMPkluMatrix->KLUmatrixCommon->status == KLU_EMPTY_MATRIX) {
return E_NOMEM ; // Francesco Lannutti - Fix KLU return values
}
}
pDevice->numOrigEquil = (int)pDevice->matrix->SMPkluMatrix->KLUmatrixNZ ;
} else {
pDevice->numOrigEquil = spElementCount (pDevice->matrix->SPmatrix) ;
}
#else
pDevice->numOrigEquil = spElementCount (pDevice->matrix->SPmatrix) ;
#endif
pDevice->numFillEquil = 0;
pDevice->solverType = SLV_EQUIL;
break;
@ -504,7 +582,20 @@ int TWOequilSolve(TWOdevice *pDevice)
/* MISCELLANEOUS */
startTime = SPfrontEnd->IFseconds();
if (newSolver) {
pDevice->numFillEquil = spFillinCount(pDevice->matrix);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
pDevice->numFillEquil = pDevice->matrix->SMPkluMatrix->KLUmatrixNumeric->lnz + pDevice->matrix->SMPkluMatrix->KLUmatrixNumeric->unz
- (int)pDevice->matrix->SMPkluMatrix->KLUmatrixNZ ;
} else {
#endif
pDevice->numFillEquil = spFillinCount(pDevice->matrix->SPmatrix);
#ifdef KLU
}
#endif
}
if (pDevice->converged) {
TWOQcommonTerms(pDevice);
@ -557,7 +648,16 @@ TWObiasSolve(TWOdevice *pDevice, int iterationLimit, BOOLEAN tranAnalysis,
FREE(pDevice->dcDeltaSolution);
FREE(pDevice->copiedSolution);
FREE(pDevice->rhs);
spDestroy(pDevice->matrix);
#ifdef KLU
SMPdestroyKLUforCIDER (pDevice->matrix) ;
#else
SMPdestroy (pDevice->matrix) ;
#endif
if (pDevice->matrix) {
FREE(pDevice->matrix);
}
/* FALLTHROUGH */
case SLV_NONE:
/* Set up for bias */
@ -568,7 +668,16 @@ TWObiasSolve(TWOdevice *pDevice, int iterationLimit, BOOLEAN tranAnalysis,
XCALLOC(pDevice->copiedSolution, double, pDevice->dimBias);
XCALLOC(pDevice->rhs, double, pDevice->dimBias);
XCALLOC(pDevice->rhsImag, double, pDevice->dimBias);
pDevice->matrix = spCreate(pDevice->numEqns, 1, &error);
pDevice->matrix = TMALLOC (SMPmatrix, 1) ;
#ifdef KLU
pDevice->matrix->CKTkluMODE = ft_curckt->ci_ckt->CKTkluMODE ;
error = SMPnewMatrixKLUforCIDER (pDevice->matrix, pDevice->numEqns, KLUMatrixComplex) ;
#else
error = SMPnewMatrixForCIDER (pDevice->matrix, pDevice->numEqns, 1) ;
#endif
if (error == spNO_MEMORY) {
printf("TWObiasSolve: Out of Memory\n");
exit(-1);
@ -581,12 +690,56 @@ TWObiasSolve(TWOdevice *pDevice, int iterationLimit, BOOLEAN tranAnalysis,
} else if (OneCarrier == P_TYPE) {
TWOPjacBuild(pDevice);
}
pDevice->numOrigBias = spElementCount(pDevice->matrix);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
/* Convert the COO Storage to CSC for KLU and Fill the Binding Table */
SMPconvertCOOtoCSCKLUforCIDER (pDevice->matrix) ;
/* Bind the KLU Pointers */
if (!OneCarrier) {
TWObindCSC (pDevice) ;
} else if (OneCarrier == N_TYPE) {
TWONbindCSC (pDevice) ;
} else if (OneCarrier == P_TYPE) {
TWOPbindCSC (pDevice) ;
}
/* Perform KLU Matrix Analysis */
pDevice->matrix->SMPkluMatrix->KLUmatrixSymbolic = klu_analyze ((int)pDevice->matrix->SMPkluMatrix->KLUmatrixN, pDevice->matrix->SMPkluMatrix->KLUmatrixAp,
pDevice->matrix->SMPkluMatrix->KLUmatrixAi, pDevice->matrix->SMPkluMatrix->KLUmatrixCommon) ;
if (pDevice->matrix->SMPkluMatrix->KLUmatrixSymbolic == NULL) {
if (pDevice->matrix->SMPkluMatrix->KLUmatrixCommon->status == KLU_EMPTY_MATRIX) {
printf ("CIDER: KLU failed\n") ;
return ; // Francesco Lannutti - Fix KLU return values
}
}
pDevice->numOrigBias = (int)pDevice->matrix->SMPkluMatrix->KLUmatrixNZ ;
} else {
pDevice->numOrigBias = spElementCount(pDevice->matrix->SPmatrix);
}
#else
pDevice->numOrigBias = spElementCount (pDevice->matrix->SPmatrix) ;
#endif
pDevice->numFillBias = 0;
TWOstoreInitialGuess(pDevice);
/* FALLTHROUGH */
case SLV_SMSIG:
spSetReal(pDevice->matrix);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = KLUmatrixReal ;
} else {
#endif
spSetReal (pDevice->matrix->SPmatrix) ;
#ifdef KLU
}
#endif
pDevice->solverType = SLV_BIAS;
break;
case SLV_BIAS:
@ -604,7 +757,20 @@ TWObiasSolve(TWOdevice *pDevice, int iterationLimit, BOOLEAN tranAnalysis,
/* MISCELLANEOUS */
startTime = SPfrontEnd->IFseconds();
if (newSolver) {
pDevice->numFillBias = spFillinCount(pDevice->matrix);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
pDevice->numFillBias = pDevice->matrix->SMPkluMatrix->KLUmatrixNumeric->lnz + pDevice->matrix->SMPkluMatrix->KLUmatrixNumeric->unz
- (int)pDevice->matrix->SMPkluMatrix->KLUmatrixNZ ;
} else {
#endif
pDevice->numFillBias = spFillinCount (pDevice->matrix->SPmatrix) ;
#ifdef KLU
}
#endif
}
if ((!pDevice->converged) && iterationLimit > 1) {
printf("TWObiasSolve: No Convergence\n");
@ -1142,9 +1308,12 @@ TWOnuNorm(TWOdevice *pDevice)
int index;
/* the LU Decomposed matrix is available. use it to calculate x */
spSolve(pDevice->matrix, pDevice->rhs, pDevice->rhsImag,
NULL, NULL);
#ifdef KLU
printf ("CIDER: KLU to be fixed TWOnuNorm\n") ;
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, pDevice->rhsImag, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, pDevice->rhsImag) ;
#endif
/* the solution is in the rhsImag vector */
/* compute L2-norm of the rhsImag vector */
@ -1202,7 +1371,14 @@ TWOjacCheck(TWOdevice *pDevice, BOOLEAN tranAnalysis, TWOtranInfo *info)
pDevice->dcSolution[index] = pDevice->copiedSolution[index];
for (rIndex = 1; rIndex <= pDevice->numEqns; rIndex++) {
diff = (pDevice->rhsImag[rIndex] - pDevice->rhs[rIndex]) / del;
dptr = spFindElement(pDevice->matrix, rIndex, index);
#ifdef KLU
printf ("CIDER: KLU to be fixed: spFindElement") ;
dptr = NULL ;
#else
dptr = spFindElement(pDevice->matrix->SPmatrix, rIndex, index); // Francesco Lannutti - Fix for KLU
#endif
if (dptr != NULL) {
tol = (1e-4 * pDevice->abstol) + (1e-2 * MAX(ABS(diff), ABS(*dptr)));
if ((diff != 0.0) && (ABS(diff - *dptr) > tol)) {

View File

@ -2363,6 +2363,8 @@ static double
agauss(double nominal_val, double abs_variation, double sigma)
{
double stdvar;
if (abs_variation <= 0 || sigma <= 0)
return nominal_val;
stdvar = abs_variation / sigma;
return (nominal_val + stdvar * gauss1());
}
@ -2372,6 +2374,8 @@ static double
gauss(double nominal_val, double rel_variation, double sigma)
{
double stdvar;
if (rel_variation <= 0 || sigma <= 0)
return nominal_val;
stdvar = nominal_val * rel_variation / sigma;
return (nominal_val + stdvar * gauss1());
}

View File

@ -183,6 +183,13 @@ com_version(wordlist *wl)
fprintf(cp_out,
"******\n"
"** %s-%s : %s\n"
#ifdef KLU
"** Compiled with KLU Direct Linear Solver\n"
#else
"** Compiled with Sparse Direct Linear Solver\n"
#endif
"** The U. C. Berkeley CAD Group\n"
"** Copyright 1985-1994, Regents of the University of California.\n"
"** Copyright 2001-2023, The ngspice team.\n"
@ -220,6 +227,13 @@ com_version(wordlist *wl)
fprintf(cp_out,
"******\n"
"** %s-%s : %s\n"
#ifdef KLU
"** Compiled with KLU Direct Linear Solver\n"
#else
"** Compiled with Sparse Direct Linear Solver\n"
#endif
"** The U. C. Berkeley CAD Group\n"
"** Copyright 1985-1994, Regents of the University of California.\n"
"** Copyright 2001-2023, The ngspice team.\n"

View File

@ -47,6 +47,8 @@ static double
agauss(double nominal_val, double abs_variation, double sigma)
{
double stdvar;
if (abs_variation <= 0 || sigma <= 0)
return nominal_val;
stdvar = abs_variation / sigma;
return (nominal_val + stdvar * gauss1());
}
@ -56,6 +58,8 @@ static double
gauss(double nominal_val, double rel_variation, double sigma)
{
double stdvar;
if (rel_variation <= 0 || sigma <= 0)
return nominal_val;
stdvar = nominal_val * rel_variation / sigma;
return (nominal_val + stdvar * gauss1());
}

View File

@ -737,6 +737,7 @@ static void wl_modify_word(wordlist *wl_node, unsigned int n_input,
p_dst += n_char_word_cur;
}
*p_dst = '\0';
tfree(pp_word[0]);
}
}

View File

@ -0,0 +1,151 @@
/* ========================================================================== */
/* === UFconfig.h =========================================================== */
/* ========================================================================== */
/* Configuration file for SuiteSparse: a Suite of Sparse matrix packages
* (AMD, COLAMD, CCOLAMD, CAMD, CHOLMOD, UMFPACK, CXSparse, and others).
*
* UFconfig.h provides the definition of the long integer. On most systems,
* a C program can be compiled in LP64 mode, in which long's and pointers are
* both 64-bits, and int's are 32-bits. Windows 64, however, uses the LLP64
* model, in which int's and long's are 32-bits, and long long's and pointers
* are 64-bits.
*
* SuiteSparse packages that include long integer versions are
* intended for the LP64 mode. However, as a workaround for Windows 64
* (and perhaps other systems), the long integer can be redefined.
*
* If _WIN64 is defined, then the __int64 type is used instead of long.
*
* The long integer can also be defined at compile time. For example, this
* could be added to UFconfig.mk:
*
* CFLAGS = -O -D'UF_long=long long' -D'UF_long_max=9223372036854775801' \
* -D'UF_long_idd="lld"'
*
* This file defines UF_long as either long (on all but _WIN64) or
* __int64 on Windows 64. The intent is that a UF_long is always a 64-bit
* integer in a 64-bit code. ptrdiff_t might be a better choice than long;
* it is always the same size as a pointer.
*
* This file also defines the SUITESPARSE_VERSION and related definitions.
*
* Copyright (c) 2007, University of Florida. No licensing restrictions
* apply to this file or to the UFconfig directory. Author: Timothy A. Davis.
*/
#ifndef _UFCONFIG_H
#define _UFCONFIG_H
#ifdef __cplusplus
extern "C" {
#endif
#include <limits.h>
#include <stdlib.h>
/* ========================================================================== */
/* === UF_long ============================================================== */
/* ========================================================================== */
#ifndef UF_long
#ifdef _WIN64
#define UF_long __int64
#define UF_long_max _I64_MAX
#define UF_long_idd "I64d"
#else
#define UF_long long
#define UF_long_max LONG_MAX
#define UF_long_idd "ld"
#endif
#define UF_long_id "%" UF_long_idd
#endif
/* ========================================================================== */
/* === UFconfig parameters and functions ==================================== */
/* ========================================================================== */
/* SuiteSparse-wide parameters will be placed in this struct. So far, they
are only used by RBio. */
typedef struct UFconfig_struct
{
void *(*malloc_memory) (size_t) ; /* pointer to malloc */
void *(*realloc_memory) (void *, size_t) ; /* pointer to realloc */
void (*free_memory) (void *) ; /* pointer to free */
void *(*calloc_memory) (size_t, size_t) ; /* pointer to calloc */
} UFconfig ;
void *UFmalloc /* pointer to allocated block of memory */
(
size_t nitems, /* number of items to malloc (>=1 is enforced) */
size_t size_of_item, /* sizeof each item */
int *ok, /* TRUE if successful, FALSE otherwise */
UFconfig *config /* SuiteSparse-wide configuration */
) ;
void *UFfree /* always returns NULL */
(
void *p, /* block to free */
UFconfig *config /* SuiteSparse-wide configuration */
) ;
/* ========================================================================== */
/* === SuiteSparse version ================================================== */
/* ========================================================================== */
/* SuiteSparse is not a package itself, but a collection of packages, some of
* which must be used together (UMFPACK requires AMD, CHOLMOD requires AMD,
* COLAMD, CAMD, and CCOLAMD, etc). A version number is provided here for the
* collection itself. The versions of packages within each version of
* SuiteSparse are meant to work together. Combining one packge from one
* version of SuiteSparse, with another package from another version of
* SuiteSparse, may or may not work.
*
* SuiteSparse Version 3.7.0 contains the following packages:
*
* UFconfig version 3.7.0 (version always the same as SuiteSparse)
* AMD version 2.2.3
* CAMD version 2.2.3
* CCOLAMD version 2.7.4
* COLAMD version 2.7.4
* BTF version 1.1.3
* CHOLMOD version 1.7.4
* CSparse3 version 3.0.2
* CSparse version 2.2.6
* CXSparse version 2.2.6
* KLU version 1.1.3
* LDL version 2.0.4
* RBio version 2.0.2
* SPQR version 1.2.3 (also called SuiteSparseQR)
* UFcollection version 1.6.0
* UMFPACK version 5.5.2
* SSMULT version 2.0.3
* spqr_rank version 1.0.0
* MATLAB_Tools various packages & M-files. No specific version number.
*
* Other package dependencies:
* BLAS required by CHOLMOD and UMFPACK
* LAPACK required by CHOLMOD
* METIS 4.0.1 required by CHOLMOD (optional) and KLU (optional)
*/
#define SUITESPARSE_DATE "Dec 15, 2011"
#define SUITESPARSE_VER_CODE(main,sub) ((main) * 1000 + (sub))
#define SUITESPARSE_MAIN_VERSION 3
#define SUITESPARSE_SUB_VERSION 7
#define SUITESPARSE_SUBSUB_VERSION 0
#define SUITESPARSE_VERSION \
SUITESPARSE_VER_CODE(SUITESPARSE_MAIN_VERSION,SUITESPARSE_SUB_VERSION)
#ifdef __cplusplus
}
#endif
#endif

412
src/include/ngspice/amd.h Normal file
View File

@ -0,0 +1,412 @@
/* ========================================================================= */
/* === AMD: approximate minimum degree ordering =========================== */
/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/* AMD Version 2.2, Copyright (c) 2007 by Timothy A. Davis, */
/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */
/* web: http://www.cise.ufl.edu/research/sparse/amd */
/* ------------------------------------------------------------------------- */
/* AMD finds a symmetric ordering P of a matrix A so that the Cholesky
* factorization of P*A*P' has fewer nonzeros and takes less work than the
* Cholesky factorization of A. If A is not symmetric, then it performs its
* ordering on the matrix A+A'. Two sets of user-callable routines are
* provided, one for int integers and the other for UF_long integers.
*
* The method is based on the approximate minimum degree algorithm, discussed
* in Amestoy, Davis, and Duff, "An approximate degree ordering algorithm",
* SIAM Journal of Matrix Analysis and Applications, vol. 17, no. 4, pp.
* 886-905, 1996. This package can perform both the AMD ordering (with
* aggressive absorption), and the AMDBAR ordering (without aggressive
* absorption) discussed in the above paper. This package differs from the
* Fortran codes discussed in the paper:
*
* (1) it can ignore "dense" rows and columns, leading to faster run times
* (2) it computes the ordering of A+A' if A is not symmetric
* (3) it is followed by a depth-first post-ordering of the assembly tree
* (or supernodal elimination tree)
*
* For historical reasons, the Fortran versions, amd.f and amdbar.f, have
* been left (nearly) unchanged. They compute the identical ordering as
* described in the above paper.
*/
#ifndef AMD_H
#define AMD_H
/* make it easy for C++ programs to include AMD */
#ifdef __cplusplus
extern "C" {
#endif
/* get the definition of size_t: */
#include <stddef.h>
/* define UF_long */
#include "UFconfig.h"
int amd_order /* returns AMD_OK, AMD_OK_BUT_JUMBLED,
* AMD_INVALID, or AMD_OUT_OF_MEMORY */
(
int n, /* A is n-by-n. n must be >= 0. */
const int Ap [ ], /* column pointers for A, of size n+1 */
const int Ai [ ], /* row indices of A, of size nz = Ap [n] */
int P [ ], /* output permutation, of size n */
double Control [ ], /* input Control settings, of size AMD_CONTROL */
double Info [ ] /* output Info statistics, of size AMD_INFO */
) ;
UF_long amd_l_order /* see above for description of arguments */
(
UF_long n,
const UF_long Ap [ ],
const UF_long Ai [ ],
UF_long P [ ],
double Control [ ],
double Info [ ]
) ;
/* Input arguments (not modified):
*
* n: the matrix A is n-by-n.
* Ap: an int/UF_long array of size n+1, containing column pointers of A.
* Ai: an int/UF_long array of size nz, containing the row indices of A,
* where nz = Ap [n].
* Control: a double array of size AMD_CONTROL, containing control
* parameters. Defaults are used if Control is NULL.
*
* Output arguments (not defined on input):
*
* P: an int/UF_long array of size n, containing the output permutation. If
* row i is the kth pivot row, then P [k] = i. In MATLAB notation,
* the reordered matrix is A (P,P).
* Info: a double array of size AMD_INFO, containing statistical
* information. Ignored if Info is NULL.
*
* On input, the matrix A is stored in column-oriented form. The row indices
* of nonzero entries in column j are stored in Ai [Ap [j] ... Ap [j+1]-1].
*
* If the row indices appear in ascending order in each column, and there
* are no duplicate entries, then amd_order is slightly more efficient in
* terms of time and memory usage. If this condition does not hold, a copy
* of the matrix is created (where these conditions do hold), and the copy is
* ordered. This feature is new to v2.0 (v1.2 and earlier required this
* condition to hold for the input matrix).
*
* Row indices must be in the range 0 to
* n-1. Ap [0] must be zero, and thus nz = Ap [n] is the number of nonzeros
* in A. The array Ap is of size n+1, and the array Ai is of size nz = Ap [n].
* The matrix does not need to be symmetric, and the diagonal does not need to
* be present (if diagonal entries are present, they are ignored except for
* the output statistic Info [AMD_NZDIAG]). The arrays Ai and Ap are not
* modified. This form of the Ap and Ai arrays to represent the nonzero
* pattern of the matrix A is the same as that used internally by MATLAB.
* If you wish to use a more flexible input structure, please see the
* umfpack_*_triplet_to_col routines in the UMFPACK package, at
* http://www.cise.ufl.edu/research/sparse/umfpack.
*
* Restrictions: n >= 0. Ap [0] = 0. Ap [j] <= Ap [j+1] for all j in the
* range 0 to n-1. nz = Ap [n] >= 0. Ai [0..nz-1] must be in the range 0
* to n-1. Finally, Ai, Ap, and P must not be NULL. If any of these
* restrictions are not met, AMD returns AMD_INVALID.
*
* AMD returns:
*
* AMD_OK if the matrix is valid and sufficient memory can be allocated to
* perform the ordering.
*
* AMD_OUT_OF_MEMORY if not enough memory can be allocated.
*
* AMD_INVALID if the input arguments n, Ap, Ai are invalid, or if P is
* NULL.
*
* AMD_OK_BUT_JUMBLED if the matrix had unsorted columns, and/or duplicate
* entries, but was otherwise valid.
*
* The AMD routine first forms the pattern of the matrix A+A', and then
* computes a fill-reducing ordering, P. If P [k] = i, then row/column i of
* the original is the kth pivotal row. In MATLAB notation, the permuted
* matrix is A (P,P), except that 0-based indexing is used instead of the
* 1-based indexing in MATLAB.
*
* The Control array is used to set various parameters for AMD. If a NULL
* pointer is passed, default values are used. The Control array is not
* modified.
*
* Control [AMD_DENSE]: controls the threshold for "dense" rows/columns.
* A dense row/column in A+A' can cause AMD to spend a lot of time in
* ordering the matrix. If Control [AMD_DENSE] >= 0, rows/columns
* with more than Control [AMD_DENSE] * sqrt (n) entries are ignored
* during the ordering, and placed last in the output order. The
* default value of Control [AMD_DENSE] is 10. If negative, no
* rows/columns are treated as "dense". Rows/columns with 16 or
* fewer off-diagonal entries are never considered "dense".
*
* Control [AMD_AGGRESSIVE]: controls whether or not to use aggressive
* absorption, in which a prior element is absorbed into the current
* element if is a subset of the current element, even if it is not
* adjacent to the current pivot element (refer to Amestoy, Davis,
* & Duff, 1996, for more details). The default value is nonzero,
* which means to perform aggressive absorption. This nearly always
* leads to a better ordering (because the approximate degrees are
* more accurate) and a lower execution time. There are cases where
* it can lead to a slightly worse ordering, however. To turn it off,
* set Control [AMD_AGGRESSIVE] to 0.
*
* Control [2..4] are not used in the current version, but may be used in
* future versions.
*
* The Info array provides statistics about the ordering on output. If it is
* not present, the statistics are not returned. This is not an error
* condition.
*
* Info [AMD_STATUS]: the return value of AMD, either AMD_OK,
* AMD_OK_BUT_JUMBLED, AMD_OUT_OF_MEMORY, or AMD_INVALID.
*
* Info [AMD_N]: n, the size of the input matrix
*
* Info [AMD_NZ]: the number of nonzeros in A, nz = Ap [n]
*
* Info [AMD_SYMMETRY]: the symmetry of the matrix A. It is the number
* of "matched" off-diagonal entries divided by the total number of
* off-diagonal entries. An entry A(i,j) is matched if A(j,i) is also
* an entry, for any pair (i,j) for which i != j. In MATLAB notation,
* S = spones (A) ;
* B = tril (S, -1) + triu (S, 1) ;
* symmetry = nnz (B & B') / nnz (B) ;
*
* Info [AMD_NZDIAG]: the number of entries on the diagonal of A.
*
* Info [AMD_NZ_A_PLUS_AT]: the number of nonzeros in A+A', excluding the
* diagonal. If A is perfectly symmetric (Info [AMD_SYMMETRY] = 1)
* with a fully nonzero diagonal, then Info [AMD_NZ_A_PLUS_AT] = nz-n
* (the smallest possible value). If A is perfectly unsymmetric
* (Info [AMD_SYMMETRY] = 0, for an upper triangular matrix, for
* example) with no diagonal, then Info [AMD_NZ_A_PLUS_AT] = 2*nz
* (the largest possible value).
*
* Info [AMD_NDENSE]: the number of "dense" rows/columns of A+A' that were
* removed from A prior to ordering. These are placed last in the
* output order P.
*
* Info [AMD_MEMORY]: the amount of memory used by AMD, in bytes. In the
* current version, this is 1.2 * Info [AMD_NZ_A_PLUS_AT] + 9*n
* times the size of an integer. This is at most 2.4nz + 9n. This
* excludes the size of the input arguments Ai, Ap, and P, which have
* a total size of nz + 2*n + 1 integers.
*
* Info [AMD_NCMPA]: the number of garbage collections performed.
*
* Info [AMD_LNZ]: the number of nonzeros in L (excluding the diagonal).
* This is a slight upper bound because mass elimination is combined
* with the approximate degree update. It is a rough upper bound if
* there are many "dense" rows/columns. The rest of the statistics,
* below, are also slight or rough upper bounds, for the same reasons.
* The post-ordering of the assembly tree might also not exactly
* correspond to a true elimination tree postordering.
*
* Info [AMD_NDIV]: the number of divide operations for a subsequent LDL'
* or LU factorization of the permuted matrix A (P,P).
*
* Info [AMD_NMULTSUBS_LDL]: the number of multiply-subtract pairs for a
* subsequent LDL' factorization of A (P,P).
*
* Info [AMD_NMULTSUBS_LU]: the number of multiply-subtract pairs for a
* subsequent LU factorization of A (P,P), assuming that no numerical
* pivoting is required.
*
* Info [AMD_DMAX]: the maximum number of nonzeros in any column of L,
* including the diagonal.
*
* Info [14..19] are not used in the current version, but may be used in
* future versions.
*/
/* ------------------------------------------------------------------------- */
/* direct interface to AMD */
/* ------------------------------------------------------------------------- */
/* amd_2 is the primary AMD ordering routine. It is not meant to be
* user-callable because of its restrictive inputs and because it destroys
* the user's input matrix. It does not check its inputs for errors, either.
* However, if you can work with these restrictions it can be faster than
* amd_order and use less memory (assuming that you can create your own copy
* of the matrix for AMD to destroy). Refer to AMD/Source/amd_2.c for a
* description of each parameter. */
void amd_2
(
int n,
int Pe [ ],
int Iw [ ],
int Len [ ],
int iwlen,
int pfree,
int Nv [ ],
int Next [ ],
int Last [ ],
int Head [ ],
int Elen [ ],
int Degree [ ],
int W [ ],
double Control [ ],
double Info [ ]
) ;
void amd_l2
(
UF_long n,
UF_long Pe [ ],
UF_long Iw [ ],
UF_long Len [ ],
UF_long iwlen,
UF_long pfree,
UF_long Nv [ ],
UF_long Next [ ],
UF_long Last [ ],
UF_long Head [ ],
UF_long Elen [ ],
UF_long Degree [ ],
UF_long W [ ],
double Control [ ],
double Info [ ]
) ;
/* ------------------------------------------------------------------------- */
/* amd_valid */
/* ------------------------------------------------------------------------- */
/* Returns AMD_OK or AMD_OK_BUT_JUMBLED if the matrix is valid as input to
* amd_order; the latter is returned if the matrix has unsorted and/or
* duplicate row indices in one or more columns. Returns AMD_INVALID if the
* matrix cannot be passed to amd_order. For amd_order, the matrix must also
* be square. The first two arguments are the number of rows and the number
* of columns of the matrix. For its use in AMD, these must both equal n.
*
* NOTE: this routine returned TRUE/FALSE in v1.2 and earlier.
*/
int amd_valid
(
int n_row, /* # of rows */
int n_col, /* # of columns */
const int Ap [ ], /* column pointers, of size n_col+1 */
const int Ai [ ] /* row indices, of size Ap [n_col] */
) ;
UF_long amd_l_valid
(
UF_long n_row,
UF_long n_col,
const UF_long Ap [ ],
const UF_long Ai [ ]
) ;
/* ------------------------------------------------------------------------- */
/* AMD memory manager and printf routines */
/* ------------------------------------------------------------------------- */
/* The user can redefine these to change the malloc, free, and printf routines
* that AMD uses. */
#ifndef EXTERN
#define EXTERN extern
#endif
EXTERN void *(*amd_malloc) (size_t) ; /* pointer to malloc */
EXTERN void (*amd_free) (void *) ; /* pointer to free */
EXTERN void *(*amd_realloc) (void *, size_t) ; /* pointer to realloc */
EXTERN void *(*amd_calloc) (size_t, size_t) ; /* pointer to calloc */
EXTERN int (*amd_printf) (const char *, ...) ; /* pointer to printf */
/* ------------------------------------------------------------------------- */
/* AMD Control and Info arrays */
/* ------------------------------------------------------------------------- */
/* amd_defaults: sets the default control settings */
void amd_defaults (double Control [ ]) ;
void amd_l_defaults (double Control [ ]) ;
/* amd_control: prints the control settings */
void amd_control (double Control [ ]) ;
void amd_l_control (double Control [ ]) ;
/* amd_info: prints the statistics */
void amd_info (double Info [ ]) ;
void amd_l_info (double Info [ ]) ;
#define AMD_CONTROL 5 /* size of Control array */
#define AMD_INFO 20 /* size of Info array */
/* contents of Control */
#define AMD_DENSE 0 /* "dense" if degree > Control [0] * sqrt (n) */
#define AMD_AGGRESSIVE 1 /* do aggressive absorption if Control [1] != 0 */
/* default Control settings */
#define AMD_DEFAULT_DENSE 10.0 /* default "dense" degree 10*sqrt(n) */
#define AMD_DEFAULT_AGGRESSIVE 1 /* do aggressive absorption by default */
/* contents of Info */
#define AMD_STATUS 0 /* return value of amd_order and amd_l_order */
#define AMD_N 1 /* A is n-by-n */
#define AMD_NZ 2 /* number of nonzeros in A */
#define AMD_SYMMETRY 3 /* symmetry of pattern (1 is sym., 0 is unsym.) */
#define AMD_NZDIAG 4 /* # of entries on diagonal */
#define AMD_NZ_A_PLUS_AT 5 /* nz in A+A' */
#define AMD_NDENSE 6 /* number of "dense" rows/columns in A */
#define AMD_MEMORY 7 /* amount of memory used by AMD */
#define AMD_NCMPA 8 /* number of garbage collections in AMD */
#define AMD_LNZ 9 /* approx. nz in L, excluding the diagonal */
#define AMD_NDIV 10 /* number of fl. point divides for LU and LDL' */
#define AMD_NMULTSUBS_LDL 11 /* number of fl. point (*,-) pairs for LDL' */
#define AMD_NMULTSUBS_LU 12 /* number of fl. point (*,-) pairs for LU */
#define AMD_DMAX 13 /* max nz. in any column of L, incl. diagonal */
/* ------------------------------------------------------------------------- */
/* return values of AMD */
/* ------------------------------------------------------------------------- */
#define AMD_OK 0 /* success */
#define AMD_OUT_OF_MEMORY -1 /* malloc failed, or problem too large */
#define AMD_INVALID -2 /* input arguments are not valid */
#define AMD_OK_BUT_JUMBLED 1 /* input matrix is OK for amd_order, but
* columns were not sorted, and/or duplicate entries were present. AMD had
* to do extra work before ordering the matrix. This is a warning, not an
* error. */
/* ========================================================================== */
/* === AMD version ========================================================== */
/* ========================================================================== */
/* AMD Version 1.2 and later include the following definitions.
* As an example, to test if the version you are using is 1.2 or later:
*
* #ifdef AMD_VERSION
* if (AMD_VERSION >= AMD_VERSION_CODE (1,2)) ...
* #endif
*
* This also works during compile-time:
*
* #if defined(AMD_VERSION) && (AMD_VERSION >= AMD_VERSION_CODE (1,2))
* printf ("This is version 1.2 or later\n") ;
* #else
* printf ("This is an early version\n") ;
* #endif
*
* Versions 1.1 and earlier of AMD do not include a #define'd version number.
*/
#define AMD_DATE "Dec 7, 2011"
#define AMD_VERSION_CODE(main,sub) ((main) * 1000 + (sub))
#define AMD_MAIN_VERSION 2
#define AMD_SUB_VERSION 2
#define AMD_SUBSUB_VERSION 3
#define AMD_VERSION AMD_VERSION_CODE(AMD_MAIN_VERSION,AMD_SUB_VERSION)
#ifdef __cplusplus
}
#endif
#endif

263
src/include/ngspice/btf.h Normal file
View File

@ -0,0 +1,263 @@
/* ========================================================================== */
/* === BTF package ========================================================== */
/* ========================================================================== */
/* BTF_MAXTRANS: find a column permutation Q to give A*Q a zero-free diagonal
* BTF_STRONGCOMP: find a symmetric permutation P to put P*A*P' into block
* upper triangular form.
* BTF_ORDER: do both of the above (btf_maxtrans then btf_strongcomp).
*
* Copyright (c) 2004-2007. Tim Davis, University of Florida,
* with support from Sandia National Laboratories. All Rights Reserved.
*/
/* ========================================================================== */
/* === BTF_MAXTRANS ========================================================= */
/* ========================================================================== */
/* BTF_MAXTRANS: finds a permutation of the columns of a matrix so that it has a
* zero-free diagonal. The input is an m-by-n sparse matrix in compressed
* column form. The array Ap of size n+1 gives the starting and ending
* positions of the columns in the array Ai. Ap[0] must be zero. The array Ai
* contains the row indices of the nonzeros of the matrix A, and is of size
* Ap[n]. The row indices of column j are located in Ai[Ap[j] ... Ap[j+1]-1].
* Row indices must be in the range 0 to m-1. Duplicate entries may be present
* in any given column. The input matrix is not checked for validity (row
* indices out of the range 0 to m-1 will lead to an undeterminate result -
* possibly a core dump, for example). Row indices in any given column need
* not be in sorted order. However, if they are sorted and the matrix already
* has a zero-free diagonal, then the identity permutation is returned.
*
* The output of btf_maxtrans is an array Match of size n. If row i is matched
* with column j, then A(i,j) is nonzero, and then Match[i] = j. If the matrix
* is structurally nonsingular, all entries in the Match array are unique, and
* Match can be viewed as a column permutation if A is square. That is, column
* k of the original matrix becomes column Match[k] of the permuted matrix. In
* MATLAB, this can be expressed as (for non-structurally singular matrices):
*
* Match = maxtrans (A) ;
* B = A (:, Match) ;
*
* except of course here the A matrix and Match vector are all 0-based (rows
* and columns in the range 0 to n-1), not 1-based (rows/cols in range 1 to n).
* The MATLAB dmperm routine returns a row permutation. See the maxtrans
* mexFunction for more details.
*
* If row i is not matched to any column, then Match[i] is == -1. The
* btf_maxtrans routine returns the number of nonzeros on diagonal of the
* permuted matrix.
*
* In the MATLAB mexFunction interface to btf_maxtrans, 1 is added to the Match
* array to obtain a 1-based permutation. Thus, in MATLAB where A is m-by-n:
*
* q = maxtrans (A) ; % has entries in the range 0:n
* q % a column permutation (only if sprank(A)==n)
* B = A (:, q) ; % permuted matrix (only if sprank(A)==n)
* sum (q > 0) ; % same as "sprank (A)"
*
* This behaviour differs from p = dmperm (A) in MATLAB, which returns the
* matching as p(j)=i if row i and column j are matched, and p(j)=0 if column j
* is unmatched.
*
* p = dmperm (A) ; % has entries in the range 0:m
* p % a row permutation (only if sprank(A)==m)
* B = A (p, :) ; % permuted matrix (only if sprank(A)==m)
* sum (p > 0) ; % definition of sprank (A)
*
* This algorithm is based on the paper "On Algorithms for obtaining a maximum
* transversal" by Iain Duff, ACM Trans. Mathematical Software, vol 7, no. 1,
* pp. 315-330, and "Algorithm 575: Permutations for a zero-free diagonal",
* same issue, pp. 387-390. Algorithm 575 is MC21A in the Harwell Subroutine
* Library. This code is not merely a translation of the Fortran code into C.
* It is a completely new implementation of the basic underlying method (depth
* first search over a subgraph with nodes corresponding to columns matched so
* far, and cheap matching). This code was written with minimal observation of
* the MC21A/B code itself. See comments below for a comparison between the
* maxtrans and MC21A/B codes.
*
* This routine operates on a column-form matrix and produces a column
* permutation. MC21A uses a row-form matrix and produces a row permutation.
* The difference is merely one of convention in the comments and interpretation
* of the inputs and outputs. If you want a row permutation, simply pass a
* compressed-row sparse matrix to this routine and you will get a row
* permutation (just like MC21A). Similarly, you can pass a column-oriented
* matrix to MC21A and it will happily return a column permutation.
*/
#ifndef _BTF_H
#define _BTF_H
/* make it easy for C++ programs to include BTF */
#ifdef __cplusplus
extern "C" {
#endif
#include "UFconfig.h"
int btf_maxtrans /* returns # of columns matched */
(
/* --- input, not modified: --- */
int nrow, /* A is nrow-by-ncol in compressed column form */
int ncol,
int Ap [ ], /* size ncol+1 */
int Ai [ ], /* size nz = Ap [ncol] */
double maxwork, /* maximum amount of work to do is maxwork*nnz(A); no limit
* if <= 0 */
/* --- output, not defined on input --- */
double *work, /* work = -1 if maxwork > 0 and the total work performed
* reached the maximum of maxwork*nnz(A).
* Otherwise, work = the total work performed. */
int Match [ ], /* size nrow. Match [i] = j if column j matched to row i
* (see above for the singular-matrix case) */
/* --- workspace, not defined on input or output --- */
int Work [ ] /* size 5*ncol */
) ;
/* long integer version (all "int" parameters become "UF_long") */
UF_long btf_l_maxtrans (UF_long, UF_long, UF_long *, UF_long *, double,
double *, UF_long *, UF_long *) ;
/* ========================================================================== */
/* === BTF_STRONGCOMP ======================================================= */
/* ========================================================================== */
/* BTF_STRONGCOMP finds the strongly connected components of a graph, returning
* a symmetric permutation. The matrix A must be square, and is provided on
* input in compressed-column form (see BTF_MAXTRANS, above). The diagonal of
* the input matrix A (or A*Q if Q is provided on input) is ignored.
*
* If Q is not NULL on input, then the strongly connected components of A*Q are
* found. Q may be flagged on input, where Q[k] < 0 denotes a flagged column k.
* The permutation is j = BTF_UNFLIP (Q [k]). On output, Q is modified (the
* flags are preserved) so that P*A*Q is in block upper triangular form.
*
* If Q is NULL, then the permutation P is returned so that P*A*P' is in upper
* block triangular form.
*
* The vector R gives the block boundaries, where block b is in rows/columns
* R[b] to R[b+1]-1 of the permuted matrix, and where b ranges from 1 to the
* number of strongly connected components found.
*/
int btf_strongcomp /* return # of strongly connected components */
(
/* input, not modified: */
int n, /* A is n-by-n in compressed column form */
int Ap [ ], /* size n+1 */
int Ai [ ], /* size nz = Ap [n] */
/* optional input, modified (if present) on output: */
int Q [ ], /* size n, input column permutation */
/* output, not defined on input */
int P [ ], /* size n. P [k] = j if row and column j are kth row/col
* in permuted matrix. */
int R [ ], /* size n+1. block b is in rows/cols R[b] ... R[b+1]-1 */
/* workspace, not defined on input or output */
int Work [ ] /* size 4n */
) ;
UF_long btf_l_strongcomp (UF_long, UF_long *, UF_long *, UF_long *, UF_long *,
UF_long *, UF_long *) ;
/* ========================================================================== */
/* === BTF_ORDER ============================================================ */
/* ========================================================================== */
/* BTF_ORDER permutes a square matrix into upper block triangular form. It
* does this by first finding a maximum matching (or perhaps a limited matching
* if the work is limited), via the btf_maxtrans function. If a complete
* matching is not found, BTF_ORDER completes the permutation, but flags the
* columns of P*A*Q to denote which columns are not matched. If the matrix is
* structurally rank deficient, some of the entries on the diagonal of the
* permuted matrix will be zero. BTF_ORDER then calls btf_strongcomp to find
* the strongly-connected components.
*
* On output, P and Q are the row and column permutations, where i = P[k] if
* row i of A is the kth row of P*A*Q, and j = BTF_UNFLIP(Q[k]) if column j of
* A is the kth column of P*A*Q. If Q[k] < 0, then the (k,k)th entry in P*A*Q
* is structurally zero.
*
* The vector R gives the block boundaries, where block b is in rows/columns
* R[b] to R[b+1]-1 of the permuted matrix, and where b ranges from 1 to the
* number of strongly connected components found.
*/
int btf_order /* returns number of blocks found */
(
/* --- input, not modified: --- */
int n, /* A is n-by-n in compressed column form */
int Ap [ ], /* size n+1 */
int Ai [ ], /* size nz = Ap [n] */
double maxwork, /* do at most maxwork*nnz(A) work in the maximum
* transversal; no limit if <= 0 */
/* --- output, not defined on input --- */
double *work, /* return value from btf_maxtrans */
int P [ ], /* size n, row permutation */
int Q [ ], /* size n, column permutation */
int R [ ], /* size n+1. block b is in rows/cols R[b] ... R[b+1]-1 */
int *nmatch, /* # nonzeros on diagonal of P*A*Q */
/* --- workspace, not defined on input or output --- */
int Work [ ] /* size 5n */
) ;
UF_long btf_l_order (UF_long, UF_long *, UF_long *, double , double *,
UF_long *, UF_long *, UF_long *, UF_long *, UF_long *) ;
/* ========================================================================== */
/* === BTF marking of singular columns ====================================== */
/* ========================================================================== */
/* BTF_FLIP is a "negation about -1", and is used to mark an integer j
* that is normally non-negative. BTF_FLIP (-1) is -1. BTF_FLIP of
* a number > -1 is negative, and BTF_FLIP of a number < -1 is positive.
* BTF_FLIP (BTF_FLIP (j)) = j for all integers j. UNFLIP (j) acts
* like an "absolute value" operation, and is always >= -1. You can test
* whether or not an integer j is "flipped" with the BTF_ISFLIPPED (j)
* macro.
*/
#define BTF_FLIP(j) (-(j)-2)
#define BTF_ISFLIPPED(j) ((j) < -1)
#define BTF_UNFLIP(j) ((BTF_ISFLIPPED (j)) ? BTF_FLIP (j) : (j))
/* ========================================================================== */
/* === BTF version ========================================================== */
/* ========================================================================== */
/* All versions of BTF include these definitions.
* As an example, to test if the version you are using is 1.2 or later:
*
* if (BTF_VERSION >= BTF_VERSION_CODE (1,2)) ...
*
* This also works during compile-time:
*
* #if (BTF >= BTF_VERSION_CODE (1,2))
* printf ("This is version 1.2 or later\n") ;
* #else
* printf ("This is an early version\n") ;
* #endif
*/
#define BTF_DATE "Dec 7, 2011"
#define BTF_VERSION_CODE(main,sub) ((main) * 1000 + (sub))
#define BTF_MAIN_VERSION 1
#define BTF_SUB_VERSION 1
#define BTF_SUBSUB_VERSION 3
#define BTF_VERSION BTF_VERSION_CODE(BTF_MAIN_VERSION,BTF_SUB_VERSION)
#ifdef __cplusplus
}
#endif
#endif

View File

@ -325,6 +325,11 @@ struct CKTcircuit {
NGHASHPTR MODnameHash;
GENinstance *noise_input; /* identify the input vsrc/isrc during noise analysis */
#ifdef KLU
unsigned int CKTkluMODE:1;
double CKTkluMemGrowFactor ;
#endif
};

View File

@ -0,0 +1,255 @@
/* ========================================================================== */
/* === colamd/symamd prototypes and definitions ============================= */
/* ========================================================================== */
/* COLAMD / SYMAMD include file
You must include this file (colamd.h) in any routine that uses colamd,
symamd, or the related macros and definitions.
Authors:
The authors of the code itself are Stefan I. Larimore and Timothy A.
Davis (davis at cise.ufl.edu), University of Florida. The algorithm was
developed in collaboration with John Gilbert, Xerox PARC, and Esmond
Ng, Oak Ridge National Laboratory.
Acknowledgements:
This work was supported by the National Science Foundation, under
grants DMS-9504974 and DMS-9803599.
Notice:
Copyright (c) 1998-2007, Timothy A. Davis, All Rights Reserved.
THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
Permission is hereby granted to use, copy, modify, and/or distribute
this program, provided that the Copyright, this License, and the
Availability of the original version is retained on all copies and made
accessible to the end-user of any code or package that includes COLAMD
or any modified version of COLAMD.
Availability:
The colamd/symamd library is available at
http://www.cise.ufl.edu/research/sparse/colamd/
This is the http://www.cise.ufl.edu/research/sparse/colamd/colamd.h
file. It is required by the colamd.c, colamdmex.c, and symamdmex.c
files, and by any C code that calls the routines whose prototypes are
listed below, or that uses the colamd/symamd definitions listed below.
*/
#ifndef COLAMD_H
#define COLAMD_H
/* make it easy for C++ programs to include COLAMD */
#ifdef __cplusplus
extern "C" {
#endif
/* ========================================================================== */
/* === Include files ======================================================== */
/* ========================================================================== */
#include <stdlib.h>
/* ========================================================================== */
/* === COLAMD version ======================================================= */
/* ========================================================================== */
/* COLAMD Version 2.4 and later will include the following definitions.
* As an example, to test if the version you are using is 2.4 or later:
*
* #ifdef COLAMD_VERSION
* if (COLAMD_VERSION >= COLAMD_VERSION_CODE (2,4)) ...
* #endif
*
* This also works during compile-time:
*
* #if defined(COLAMD_VERSION) && (COLAMD_VERSION >= COLAMD_VERSION_CODE (2,4))
* printf ("This is version 2.4 or later\n") ;
* #else
* printf ("This is an early version\n") ;
* #endif
*
* Versions 2.3 and earlier of COLAMD do not include a #define'd version number.
*/
#define COLAMD_DATE "Dec 7, 2011"
#define COLAMD_VERSION_CODE(main,sub) ((main) * 1000 + (sub))
#define COLAMD_MAIN_VERSION 2
#define COLAMD_SUB_VERSION 7
#define COLAMD_SUBSUB_VERSION 4
#define COLAMD_VERSION \
COLAMD_VERSION_CODE(COLAMD_MAIN_VERSION,COLAMD_SUB_VERSION)
/* ========================================================================== */
/* === Knob and statistics definitions ====================================== */
/* ========================================================================== */
/* size of the knobs [ ] array. Only knobs [0..1] are currently used. */
#define COLAMD_KNOBS 20
/* number of output statistics. Only stats [0..6] are currently used. */
#define COLAMD_STATS 20
/* knobs [0] and stats [0]: dense row knob and output statistic. */
#define COLAMD_DENSE_ROW 0
/* knobs [1] and stats [1]: dense column knob and output statistic. */
#define COLAMD_DENSE_COL 1
/* knobs [2]: aggressive absorption */
#define COLAMD_AGGRESSIVE 2
/* stats [2]: memory defragmentation count output statistic */
#define COLAMD_DEFRAG_COUNT 2
/* stats [3]: colamd status: zero OK, > 0 warning or notice, < 0 error */
#define COLAMD_STATUS 3
/* stats [4..6]: error info, or info on jumbled columns */
#define COLAMD_INFO1 4
#define COLAMD_INFO2 5
#define COLAMD_INFO3 6
/* error codes returned in stats [3]: */
#define COLAMD_OK (0)
#define COLAMD_OK_BUT_JUMBLED (1)
#define COLAMD_ERROR_A_not_present (-1)
#define COLAMD_ERROR_p_not_present (-2)
#define COLAMD_ERROR_nrow_negative (-3)
#define COLAMD_ERROR_ncol_negative (-4)
#define COLAMD_ERROR_nnz_negative (-5)
#define COLAMD_ERROR_p0_nonzero (-6)
#define COLAMD_ERROR_A_too_small (-7)
#define COLAMD_ERROR_col_length_negative (-8)
#define COLAMD_ERROR_row_index_out_of_bounds (-9)
#define COLAMD_ERROR_out_of_memory (-10)
#define COLAMD_ERROR_internal_error (-999)
/* ========================================================================== */
/* === Prototypes of user-callable routines ================================= */
/* ========================================================================== */
/* define UF_long */
#include "UFconfig.h"
size_t colamd_recommended /* returns recommended value of Alen, */
/* or 0 if input arguments are erroneous */
(
int nnz, /* nonzeros in A */
int n_row, /* number of rows in A */
int n_col /* number of columns in A */
) ;
size_t colamd_l_recommended /* returns recommended value of Alen, */
/* or 0 if input arguments are erroneous */
(
UF_long nnz, /* nonzeros in A */
UF_long n_row, /* number of rows in A */
UF_long n_col /* number of columns in A */
) ;
void colamd_set_defaults /* sets default parameters */
( /* knobs argument is modified on output */
double knobs [COLAMD_KNOBS] /* parameter settings for colamd */
) ;
void colamd_l_set_defaults /* sets default parameters */
( /* knobs argument is modified on output */
double knobs [COLAMD_KNOBS] /* parameter settings for colamd */
) ;
int colamd /* returns (1) if successful, (0) otherwise*/
( /* A and p arguments are modified on output */
int n_row, /* number of rows in A */
int n_col, /* number of columns in A */
int Alen, /* size of the array A */
int A [], /* row indices of A, of size Alen */
int p [], /* column pointers of A, of size n_col+1 */
double knobs [COLAMD_KNOBS],/* parameter settings for colamd */
int stats [COLAMD_STATS] /* colamd output statistics and error codes */
) ;
UF_long colamd_l /* returns (1) if successful, (0) otherwise*/
( /* A and p arguments are modified on output */
UF_long n_row, /* number of rows in A */
UF_long n_col, /* number of columns in A */
UF_long Alen, /* size of the array A */
UF_long A [], /* row indices of A, of size Alen */
UF_long p [], /* column pointers of A, of size n_col+1 */
double knobs [COLAMD_KNOBS],/* parameter settings for colamd */
UF_long stats [COLAMD_STATS]/* colamd output statistics and error codes */
) ;
int symamd /* return (1) if OK, (0) otherwise */
(
int n, /* number of rows and columns of A */
int A [], /* row indices of A */
int p [], /* column pointers of A */
int perm [], /* output permutation, size n_col+1 */
double knobs [COLAMD_KNOBS], /* parameters (uses defaults if NULL) */
int stats [COLAMD_STATS], /* output statistics and error codes */
void * (*allocate) (size_t, size_t),
/* pointer to calloc (ANSI C) or */
/* mxCalloc (for MATLAB mexFunction) */
void (*release) (void *)
/* pointer to free (ANSI C) or */
/* mxFree (for MATLAB mexFunction) */
) ;
UF_long symamd_l /* return (1) if OK, (0) otherwise */
(
UF_long n, /* number of rows and columns of A */
UF_long A [], /* row indices of A */
UF_long p [], /* column pointers of A */
UF_long perm [], /* output permutation, size n_col+1 */
double knobs [COLAMD_KNOBS], /* parameters (uses defaults if NULL) */
UF_long stats [COLAMD_STATS], /* output statistics and error codes */
void * (*allocate) (size_t, size_t),
/* pointer to calloc (ANSI C) or */
/* mxCalloc (for MATLAB mexFunction) */
void (*release) (void *)
/* pointer to free (ANSI C) or */
/* mxFree (for MATLAB mexFunction) */
) ;
void colamd_report
(
int stats [COLAMD_STATS]
) ;
void colamd_l_report
(
UF_long stats [COLAMD_STATS]
) ;
void symamd_report
(
int stats [COLAMD_STATS]
) ;
void symamd_l_report
(
UF_long stats [COLAMD_STATS]
) ;
#ifndef EXTERN
#define EXTERN extern
#endif
EXTERN int (*colamd_printf) (const char *, ...) ;
#ifdef __cplusplus
}
#endif
#endif /* COLAMD_H */

View File

@ -117,6 +117,15 @@ typedef struct SPICEdev {
int *DEVinstSize; /* size of an instance */
int *DEVmodSize; /* size of a model */
#ifdef KLU
int (*DEVbindCSC)(GENmodel *, CKTcircuit *);
/* routine to convert Sparse linked list to Real CSC array */
int (*DEVbindCSCComplex)(GENmodel *, CKTcircuit *);
/* routine to convert Real CSC array to Complex CSC array */
int (*DEVbindCSCComplexToReal)(GENmodel *, CKTcircuit *);
/* routine to convert Complex CSC array to Real CSC array */
#endif
} SPICEdev; /* instance of structure for each possible type of device */

View File

@ -6,6 +6,7 @@
#ifndef ngspice_DLLITF_H
#define ngspice_DLLITF_H
#include "ngspice/config.h"
#include "ngspice/mifproto.h"
#include "ngspice/cmproto.h"
@ -82,6 +83,12 @@ struct coreInfo_t {
void * ((*dllitf_tmalloc)(size_t));
void * ((*dllitf_trealloc)(const void *, size_t));
void ((*dllitf_txfree)(const void *));
#ifdef KLU
int ((*dllitf_MIFbindCSC) (GENmodel *, CKTcircuit *)) ;
int ((*dllitf_MIFbindCSCComplex) (GENmodel *, CKTcircuit *)) ;
int ((*dllitf_MIFbindCSCComplexToReal) (GENmodel *, CKTcircuit *)) ;
#endif
};
#endif

View File

@ -0,0 +1,155 @@
#ifndef _KLU_BINDING_H
#define _KLU_BINDING_H
#include "ngspice/klu.h"
#define CREATE_KLU_BINDING_TABLE(ptr, binding, a, b) \
if ((here->a > 0) && (here->b > 0)) { \
i.COO = here->ptr ; \
i.CSC = NULL ; \
i.CSC_Complex = NULL ; \
matched = (BindElement *) bsearch (&i, BindStruct, nz, sizeof (BindElement), BindCompare) ; \
if (matched == NULL) { \
printf ("Ptr %p not found in BindStruct Table\n", here->ptr) ; \
} \
here->binding = matched ; \
here->ptr = matched->CSC ; \
}
#define CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(ptr, binding, a, b) \
if ((here->a > 0) && (here->b > 0)) \
here->ptr = here->binding->CSC_Complex ;
#define CONVERT_KLU_BINDING_TABLE_TO_REAL(ptr, binding, a, b) \
if ((here->a > 0) && (here->b > 0)) \
here->ptr = here->binding->CSC ;
#ifdef XSPICE
#define CREATE_KLU_BINDING_TABLE_XSPICE_OUTPUTS(ptr, binding, a, b) \
if ((smp_data_out->a > 0) && (smp_data_out->b > 0)) { \
i.COO = smp_data_out->ptr ; \
i.CSC = NULL ; \
i.CSC_Complex = NULL ; \
matched = (BindElement *) bsearch (&i, BindStruct, nz, sizeof (BindElement), BindCompare) ; \
smp_data_out->binding = matched ; \
smp_data_out->ptr = matched->CSC ; \
}
#define CONVERT_KLU_BINDING_TABLE_TO_COMPLEX_XSPICE_OUTPUTS(ptr, binding, a, b) \
if ((smp_data_out->a > 0) && (smp_data_out->b > 0)) \
smp_data_out->ptr = smp_data_out->binding->CSC_Complex ;
#define CONVERT_KLU_BINDING_TABLE_TO_REAL_XSPICE_OUTPUTS(ptr, binding, a, b) \
if ((smp_data_out->a > 0) && (smp_data_out->b > 0)) \
smp_data_out->ptr = smp_data_out->binding->CSC ;
#define CREATE_KLU_BINDING_TABLE_XSPICE_INPUTS_E(ptr, binding, a, b) \
if ((smp_data_out->a > 0) && (smp_data_cntl->b > 0)) { \
i.COO = smp_data_out->input[k].port[l].ptr ; \
i.CSC = NULL ; \
i.CSC_Complex = NULL ; \
matched = (BindElement *) bsearch (&i, BindStruct, nz, sizeof (BindElement), BindCompare) ; \
smp_data_out->input[k].port[l].e.binding = matched ; \
smp_data_out->input[k].port[l].ptr = matched->CSC ; \
}
#define CONVERT_KLU_BINDING_TABLE_TO_COMPLEX_XSPICE_INPUTS_E(ptr, binding, a, b) \
if ((smp_data_out->a > 0) && (smp_data_cntl->b > 0)) \
smp_data_out->input[k].port[l].ptr = smp_data_out->input[k].port[l].e.binding->CSC_Complex ;
#define CONVERT_KLU_BINDING_TABLE_TO_REAL_XSPICE_INPUTS_E(ptr, binding, a, b) \
if ((smp_data_out->a > 0) && (smp_data_cntl->b > 0)) \
smp_data_out->input[k].port[l].ptr = smp_data_out->input[k].port[l].e.binding->CSC ;
#define CREATE_KLU_BINDING_TABLE_XSPICE_INPUTS_F(ptr, binding, a, b) \
if ((smp_data_out->a > 0) && (smp_data_cntl->b > 0)) { \
i.COO = smp_data_out->input[k].port[l].ptr ; \
i.CSC = NULL ; \
i.CSC_Complex = NULL ; \
matched = (BindElement *) bsearch (&i, BindStruct, nz, sizeof (BindElement), BindCompare) ; \
smp_data_out->input[k].port[l].f.binding = matched ; \
smp_data_out->input[k].port[l].ptr = matched->CSC ; \
}
#define CONVERT_KLU_BINDING_TABLE_TO_COMPLEX_XSPICE_INPUTS_F(ptr, binding, a, b) \
if ((smp_data_out->a > 0) && (smp_data_cntl->b > 0)) \
smp_data_out->input[k].port[l].ptr = smp_data_out->input[k].port[l].f.binding->CSC_Complex ;
#define CONVERT_KLU_BINDING_TABLE_TO_REAL_XSPICE_INPUTS_F(ptr, binding, a, b) \
if ((smp_data_out->a > 0) && (smp_data_cntl->b > 0)) \
smp_data_out->input[k].port[l].ptr = smp_data_out->input[k].port[l].f.binding->CSC ;
#define CREATE_KLU_BINDING_TABLE_XSPICE_INPUTS_G(ptr, binding, a, b) \
if ((smp_data_out->a > 0) && (smp_data_cntl->b > 0)) { \
i.COO = smp_data_out->input[k].port[l].ptr ; \
i.CSC = NULL ; \
i.CSC_Complex = NULL ; \
matched = (BindElement *) bsearch (&i, BindStruct, nz, sizeof (BindElement), BindCompare) ; \
smp_data_out->input[k].port[l].g.binding = matched ; \
smp_data_out->input[k].port[l].ptr = matched->CSC ; \
}
#define CONVERT_KLU_BINDING_TABLE_TO_COMPLEX_XSPICE_INPUTS_G(ptr, binding, a, b) \
if ((smp_data_out->a > 0) && (smp_data_cntl->b > 0)) \
smp_data_out->input[k].port[l].ptr = smp_data_out->input[k].port[l].g.binding->CSC_Complex ;
#define CONVERT_KLU_BINDING_TABLE_TO_REAL_XSPICE_INPUTS_G(ptr, binding, a, b) \
if ((smp_data_out->a > 0) && (smp_data_cntl->b > 0)) \
smp_data_out->input[k].port[l].ptr = smp_data_out->input[k].port[l].g.binding->CSC ;
#define CREATE_KLU_BINDING_TABLE_XSPICE_INPUTS_H(ptr, binding, a, b) \
if ((smp_data_out->a > 0) && (smp_data_cntl->b > 0)) { \
i.COO = smp_data_out->input[k].port[l].ptr ; \
i.CSC = NULL ; \
i.CSC_Complex = NULL ; \
matched = (BindElement *) bsearch (&i, BindStruct, nz, sizeof (BindElement), BindCompare) ; \
smp_data_out->input[k].port[l].h.binding = matched ; \
smp_data_out->input[k].port[l].ptr = matched->CSC ; \
}
#define CONVERT_KLU_BINDING_TABLE_TO_COMPLEX_XSPICE_INPUTS_H(ptr, binding, a, b) \
if ((smp_data_out->a > 0) && (smp_data_cntl->b > 0)) \
smp_data_out->input[k].port[l].ptr = smp_data_out->input[k].port[l].h.binding->CSC_Complex ;
#define CONVERT_KLU_BINDING_TABLE_TO_REAL_XSPICE_INPUTS_H(ptr, binding, a, b) \
if ((smp_data_out->a > 0) && (smp_data_cntl->b > 0)) \
smp_data_out->input[k].port[l].ptr = smp_data_out->input[k].port[l].h.binding->CSC ;
#endif
#ifdef CIDER
#define CREATE_KLU_BINDING_TABLE_CIDER(ptr, binding, a, b) \
if ((a > 0) && (b > 0)) { \
if (pNode->binding != NULL) { \
if (pNode->binding->CSC_Complex != NULL) { \
qsort (BindStructCSC, nz, sizeof (BindElementKLUforCIDER), BindKluCompareCSCKLUforCIDER) ; \
i.COO = NULL ; \
i.CSC_Complex = pNode->binding->CSC_Complex ; \
matched = (BindElementKLUforCIDER *) bsearch (&i, BindStructCSC, nz, sizeof (BindElementKLUforCIDER), BindKluCompareCSCKLUforCIDER) ; \
if (matched == NULL) { \
i.COO = pNode->ptr ; \
i.CSC_Complex = NULL ; \
matched = (BindElementKLUforCIDER *) bsearch (&i, BindStruct, nz, sizeof (BindElementKLUforCIDER), BindCompareKLUforCIDER) ; \
if (matched != NULL) { \
pNode->binding = matched ; \
pNode->ptr = matched->CSC_Complex ; \
} \
} \
} else { \
i.COO = pNode->ptr ; \
i.CSC_Complex = NULL ; \
matched = (BindElementKLUforCIDER *) bsearch (&i, BindStruct, nz, sizeof (BindElementKLUforCIDER), BindCompareKLUforCIDER) ; \
pNode->binding = matched ; \
pNode->ptr = matched->CSC_Complex ; \
} \
} else { \
i.COO = pNode->ptr ; \
i.CSC_Complex = NULL ; \
matched = (BindElementKLUforCIDER *) bsearch (&i, BindStruct, nz, sizeof (BindElementKLUforCIDER), BindCompareKLUforCIDER) ; \
pNode->binding = matched ; \
pNode->ptr = matched->CSC_Complex ; \
} \
}
#endif
#endif

1027
src/include/ngspice/klu.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -46,7 +46,11 @@ NON-STANDARD FEATURES
#include "ngspice/typedefs.h"
#include "ngspice/miftypes.h"
#include "ngspice/miftypes.h"
#ifdef KLU
#include "ngspice/smpdefs.h"
#endif
/* ************************************************************************** */
@ -61,6 +65,11 @@ typedef struct Mif_E_Ptr_s {
double *branch_poscntl; /* Branch row, positive controlling column */
double *branch_negcntl; /* Branch row, negative controlling column */
#ifdef KLU
BindElement *branch_poscntlBinding ;
BindElement *branch_negcntlBinding ;
#endif
} Mif_E_Ptr_t;
@ -74,6 +83,11 @@ typedef struct Mif_F_Ptr_s {
double *pos_ibranchcntl; /* Positive row, controlling branch column */
double *neg_ibranchcntl; /* Negative row, controlling branch column */
#ifdef KLU
BindElement *pos_ibranchcntlBinding ;
BindElement *neg_ibranchcntlBinding ;
#endif
} Mif_F_Ptr_t;
@ -89,6 +103,13 @@ typedef struct Mif_G_Ptr_s {
double *neg_poscntl; /* Negative row, positive controlling column */
double *neg_negcntl; /* Negative row, negative controlling column */
#ifdef KLU
BindElement *pos_poscntlBinding ;
BindElement *pos_negcntlBinding ;
BindElement *neg_poscntlBinding ;
BindElement *neg_negcntlBinding ;
#endif
} Mif_G_Ptr_t;
@ -100,6 +121,10 @@ typedef struct Mif_H_Ptr_s {
double *branch_ibranchcntl; /* Branch row, controlling branch column */
#ifdef KLU
BindElement *branch_ibranchcntlBinding ;
#endif
} Mif_H_Ptr_t;
@ -168,6 +193,17 @@ typedef struct Mif_Smp_Ptr_s {
/* array of pointer info required for putting partials into the matrix */
Mif_Conn_Ptr_t *input; /* Matrix pointers associated with inputs */
#ifdef KLU
BindElement *pos_branchBinding ;
BindElement *neg_branchBinding ;
BindElement *branch_posBinding ;
BindElement *branch_negBinding ;
BindElement *pos_ibranchBinding ;
BindElement *neg_ibranchBinding ;
BindElement *ibranch_posBinding ;
BindElement *ibranch_negBinding ;
#endif
} Mif_Smp_Ptr_t;

View File

@ -43,11 +43,10 @@ NON-STANDARD FEATURES
=========================================================================== */
#include "ngspice/mifcmdat.h"
#include "ngspice/gendefs.h"
#include "ngspice/mifcmdat.h"
#include "ngspice/gendefs.h"
#include "ngspice/ifsim.h"
/* The per-instance data structure */
struct MIFinstance {
@ -84,7 +83,6 @@ struct MIFinstance {
int inst_index; /* Index into inst_table in evt struct in ckt */
Mif_Callback_t callback; /* instance callback function */
};

View File

@ -154,6 +154,11 @@ extern Mif_Cntl_Src_Type_t MIFget_cntl_src_type(
extern char *MIFcopy(char *);
#ifdef KLU
extern int MIFbindCSC (GENmodel*, CKTcircuit*) ;
extern int MIFbindCSCComplex (GENmodel*, CKTcircuit*) ;
extern int MIFbindCSCComplexToReal (GENmodel*, CKTcircuit*) ;
#endif
#ifndef CM_IGNORE
#define CM_IGNORE(x) (void) (x)

View File

@ -16,6 +16,10 @@ Authors: 1987 Karti Mayaram, 1991 David Gates
#include "ngspice/material.h"
#ifdef KLU
#include "ngspice/klu.h"
#endif
typedef struct sONEelem {
struct sONEelem *pElems[2]; /* array to store neighbor elements */
struct sONEnode *pNodes[2]; /* array to store the element nodes */
@ -27,6 +31,20 @@ typedef struct sONEelem {
ONEmaterial *matlInfo; /* material information */
double epsRel; /* epsilon of material rel to Semicon */
int evalNodes[2]; /* nodes to be evaluated in elem */
#ifdef KLU
double *KLUleftLeftNode ;
double *KLUleftRightNode ;
double *KLUrightLeftNode ;
double *KLUrightRightNode ;
BindElementKLUforCIDER *KLUleftLeftNodeBinding ;
BindElementKLUforCIDER *KLUleftRightNodeBinding ;
BindElementKLUforCIDER *KLUrightLeftNodeBinding ;
BindElementKLUforCIDER *KLUrightRightNodeBinding ;
#endif
} ONEelem;
#define pLeftElem pElems[0]
@ -112,6 +130,33 @@ typedef struct sONEnode {
double *fPNiM1;
double *fPN;
double *fPNiP1;
#ifdef KLU
BindElementKLUforCIDER *fPsiPsiiM1Binding ;
BindElementKLUforCIDER *fPsiPsiBinding ;
BindElementKLUforCIDER *fPsiPsiiP1Binding ;
BindElementKLUforCIDER *fPsiNBinding ;
BindElementKLUforCIDER *fPsiPBinding ;
BindElementKLUforCIDER *fNPsiiM1Binding ;
BindElementKLUforCIDER *fNPsiBinding ;
BindElementKLUforCIDER *fNPsiiP1Binding ;
BindElementKLUforCIDER *fNNiM1Binding ;
BindElementKLUforCIDER *fNNBinding ;
BindElementKLUforCIDER *fNNiP1Binding ;
BindElementKLUforCIDER *fNPiM1Binding ;
BindElementKLUforCIDER *fNPBinding ;
BindElementKLUforCIDER *fNPiP1Binding ;
BindElementKLUforCIDER *fPPsiiM1Binding ;
BindElementKLUforCIDER *fPPsiBinding ;
BindElementKLUforCIDER *fPPsiiP1Binding ;
BindElementKLUforCIDER *fPPiM1Binding ;
BindElementKLUforCIDER *fPPBinding ;
BindElementKLUforCIDER *fPPiP1Binding ;
BindElementKLUforCIDER *fPNiM1Binding ;
BindElementKLUforCIDER *fPNBinding ;
BindElementKLUforCIDER *fPNiP1Binding ;
#endif
} ONEnode;

View File

@ -121,6 +121,12 @@ enum {
OPT_INDVERBOSITY,
OPT_EPSMIN,
OPT_CSHUNT,
#ifdef KLU
OPT_SPARSE,
OPT_KLU_MEMGROW_FACTOR,
#endif
};
#ifdef XSPICE

View File

@ -11,6 +11,7 @@
#pragma once
#include "ngspice/config.h"
#include "ngspice/devdefs.h"
#include <stdint.h>
@ -19,7 +20,13 @@ typedef struct OsdiRegistryEntry {
uint32_t inst_offset;
uint32_t dt;
uint32_t temp;
bool has_m;
#ifdef KLU
uint32_t matrix_ptr_offset;
#endif
} OsdiRegistryEntry;
typedef struct OsdiObjectFile {

View File

@ -97,7 +97,7 @@ are of type bool if sharedspice.h is used externally.
*/
#ifndef NGSPICE_PACKAGE_VERSION
#define NGSPICE_PACKAGE_VERSION "40"
#define NGSPICE_PACKAGE_VERSION "41+"
#endif
/* we have NG_BOOL instead of BOOL */
#ifndef HAS_NG_BOOL

View File

@ -1,8 +1,12 @@
#ifndef ngspice_SMPDEFS_H
#define ngspice_SMPDEFS_H
/* Typedef removed by Francesco Lannutti (2012-02) to create the new SMPmatrix structure */
/*
typedef struct MatrixFrame SMPmatrix;
typedef struct MatrixElement SMPelement;
*/
typedef struct MatrixFrame MatrixFrame;
typedef struct MatrixElement *SMPelement;
/**********
Copyright 1990 Regents of the University of California. All rights reserved.
@ -14,7 +18,46 @@ Modified: 2000 AlansFixes
#include <math.h>
#include "ngspice/complex.h"
int SMPaddElt( SMPmatrix *, int , int , double );
#ifdef KLU
#include "ngspice/klu.h"
#include "ngspice/spmatrix.h"
#endif
/* SMPmatrix structure - Francesco Lannutti (2012-02) */
typedef struct sSMPmatrix {
MatrixFrame *SPmatrix ; /* pointer to sparse matrix */
#ifdef KLU
KLUmatrix *SMPkluMatrix ; /* KLU Pointer to the KLU Matrix Data Structure (only for CIDER, for the moment) */
unsigned int CKTkluMODE:1 ; /* KLU MODE parameter to enable KLU or not from the heuristic */
#define CKTkluON 1 /* KLU MODE ON definition */
#define CKTkluOFF 0 /* KLU MODE OFF definition */
double CKTkluMemGrowFactor ; /* KLU Memory Grow Factor - default = 1.2 */
#endif
} SMPmatrix ;
#ifdef KLU
void spDeterminant_KLU (SMPmatrix *, int *, double *, double *) ;
void SMPconvertCOOtoCSC (SMPmatrix *) ;
#ifdef CIDER
void SMPsolveKLUforCIDER (SMPmatrix *, double [], double [], double [], double []) ;
int SMPreorderKLUforCIDER (SMPmatrix *) ;
double *SMPmakeEltKLUforCIDER (SMPmatrix *, int, int) ;
void SMPclearKLUforCIDER (SMPmatrix *) ;
void SMPconvertCOOtoCSCKLUforCIDER (SMPmatrix *) ;
void SMPdestroyKLUforCIDER (SMPmatrix *) ;
int SMPnewMatrixKLUforCIDER (SMPmatrix *, int, unsigned int) ;
int SMPluFacKLUforCIDER (SMPmatrix *) ;
void SMPprintKLUforCIDER (SMPmatrix *, char *) ;
#endif
#else
int SMPaddElt (SMPmatrix *, int, int, double) ;
#endif
double * SMPmakeElt( SMPmatrix * , int , int );
void SMPcClear( SMPmatrix *);
void SMPclear( SMPmatrix *);
@ -27,7 +70,7 @@ void SMPcaSolve(SMPmatrix *Matrix, double RHS[], double iRHS[],
void SMPcSolve( SMPmatrix *, double [], double [], double [], double []);
void SMPsolve( SMPmatrix *, double [], double []);
int SMPmatSize( SMPmatrix *);
int SMPnewMatrix( SMPmatrix **, int );
int SMPnewMatrix( SMPmatrix *, int );
void SMPdestroy( SMPmatrix *);
int SMPpreOrder( SMPmatrix *);
void SMPprint( SMPmatrix * , char *);
@ -42,4 +85,12 @@ int SMPzeroRow(SMPmatrix *Matrix, int Row);
void SMPconstMult(SMPmatrix *, double);
void SMPmultiply(SMPmatrix *, double *, double *, double *, double *);
#ifdef CIDER
void SMPcSolveForCIDER (SMPmatrix *, double [], double [], double [], double []) ;
int SMPluFacForCIDER (SMPmatrix *) ;
int SMPnewMatrixForCIDER (SMPmatrix *, int, int) ;
void SMPsolveForCIDER (SMPmatrix *, double [], double []) ;
#endif
#endif

View File

@ -35,6 +35,8 @@
*/
/* Francesco Lannutti 2012-09 - NGSPICE Configuration File Inclusion */
#include "ngspice/config.h"
#ifndef spOKAY
@ -294,4 +296,7 @@ extern void spMultTransposed(MatrixPtr,spREAL*,spREAL*,spREAL*,spREAL*);
extern void spSolve( MatrixPtr, spREAL*, spREAL*, spREAL*, spREAL* );
extern void spSolveTransposed(MatrixPtr,spREAL*,spREAL*,spREAL*,spREAL*);
/* ------------------------------------------------------ */
#endif /* spOKAY */

View File

@ -73,6 +73,12 @@ struct TSKtask {
double TSKabsDv; /* abs limit for iter-iter voltage change */
double TSKrelDv; /* rel limit for iter-iter voltage change */
double TSKepsmin; /* minimum value for log */
#ifdef KLU
unsigned int TSKkluMODE:1;
double TSKkluMemGrowFactor ;
#endif
};
#endif

View File

@ -16,6 +16,10 @@ Authors: 1987 Karti Mayaram, 1991 David Gates
#include "ngspice/material.h"
#ifdef KLU
#include "ngspice/klu.h"
#endif
typedef struct sTWOelem
{
struct sTWOelem *pElems[4]; /* array to store the element neighbors */
@ -44,6 +48,19 @@ typedef struct sTWOelem
int direction; /* direction of flow for channels */
int evalNodes[4]; /* nodes to be evaluated in elem */
int evalEdges[4]; /* edges to be evaluated in elem */
#ifdef KLU
double *KLUleftLeftNode ;
double *KLUleftRightNode ;
double *KLUrightLeftNode ;
double *KLUrightRightNode ;
BindElementKLUforCIDER *KLUleftLeftNodeBinding ;
BindElementKLUforCIDER *KLUleftRightNodeBinding ;
BindElementKLUforCIDER *KLUrightLeftNodeBinding ;
BindElementKLUforCIDER *KLUrightRightNodeBinding ;
#endif
} TWOelem;
#define pTopElem pElems[0]
@ -193,6 +210,67 @@ typedef struct sTWOnode {
double *fPPsiOxM1;
double *fPPsiOx;
double *fPPsiOxP1;
#ifdef KLU
BindElementKLUforCIDER *fPsiPsiBinding ;
BindElementKLUforCIDER *fPsiNBinding ;
BindElementKLUforCIDER *fPsiPBinding ;
BindElementKLUforCIDER *fNPsiBinding ;
BindElementKLUforCIDER *fNNBinding ;
BindElementKLUforCIDER *fNPBinding ;
BindElementKLUforCIDER *fPPsiBinding ;
BindElementKLUforCIDER *fPNBinding ;
BindElementKLUforCIDER *fPPBinding ;
BindElementKLUforCIDER *fPsiPsiiP1Binding ;
BindElementKLUforCIDER *fPsiPsijP1Binding ;
BindElementKLUforCIDER *fNPsiiP1Binding ;
BindElementKLUforCIDER *fNNiP1Binding ;
BindElementKLUforCIDER *fNPsijP1Binding ;
BindElementKLUforCIDER *fNNjP1Binding ;
BindElementKLUforCIDER *fPPsiiP1Binding ;
BindElementKLUforCIDER *fPPiP1Binding ;
BindElementKLUforCIDER *fPPsijP1Binding ;
BindElementKLUforCIDER *fPPjP1Binding ;
BindElementKLUforCIDER *fNPsiiP1jP1Binding ;
BindElementKLUforCIDER *fNNiP1jP1Binding ;
BindElementKLUforCIDER *fPPsiiP1jP1Binding ;
BindElementKLUforCIDER *fPPiP1jP1Binding ;
BindElementKLUforCIDER *fPsiPsiiM1Binding ;
BindElementKLUforCIDER *fNPsiiM1Binding ;
BindElementKLUforCIDER *fNNiM1Binding ;
BindElementKLUforCIDER *fPPsiiM1Binding ;
BindElementKLUforCIDER *fPPiM1Binding ;
BindElementKLUforCIDER *fNPsiiM1jP1Binding ;
BindElementKLUforCIDER *fNNiM1jP1Binding ;
BindElementKLUforCIDER *fPPsiiM1jP1Binding ;
BindElementKLUforCIDER *fPPiM1jP1Binding ;
BindElementKLUforCIDER *fPsiPsijM1Binding ;
BindElementKLUforCIDER *fNPsijM1Binding ;
BindElementKLUforCIDER *fNNjM1Binding ;
BindElementKLUforCIDER *fPPsijM1Binding ;
BindElementKLUforCIDER *fPPjM1Binding ;
BindElementKLUforCIDER *fNPsiiM1jM1Binding ;
BindElementKLUforCIDER *fNNiM1jM1Binding ;
BindElementKLUforCIDER *fPPsiiM1jM1Binding ;
BindElementKLUforCIDER *fPPiM1jM1Binding ;
BindElementKLUforCIDER *fNPsiiP1jM1Binding ;
BindElementKLUforCIDER *fNNiP1jM1Binding ;
BindElementKLUforCIDER *fPPsiiP1jM1Binding ;
BindElementKLUforCIDER *fPPiP1jM1Binding ;
BindElementKLUforCIDER *fNPsiInBinding ;
BindElementKLUforCIDER *fNPsiInP1Binding ;
BindElementKLUforCIDER *fNPsiOxBinding ;
BindElementKLUforCIDER *fNPsiOxP1Binding ;
BindElementKLUforCIDER *fPPsiInBinding ;
BindElementKLUforCIDER *fPPsiInP1Binding ;
BindElementKLUforCIDER *fPPsiOxBinding ;
BindElementKLUforCIDER *fPPsiOxP1Binding ;
BindElementKLUforCIDER *fNPsiInM1Binding ;
BindElementKLUforCIDER *fNPsiOxM1Binding ;
BindElementKLUforCIDER *fPPsiInM1Binding ;
BindElementKLUforCIDER *fPPsiOxM1Binding ;
#endif
} TWOnode;
#define pTLElem pElems[0]

79
src/maths/KLU/Makefile.am Normal file
View File

@ -0,0 +1,79 @@
## Process this file with automake to produce Makefile.in
noinst_LTLIBRARIES = libKLU_real.la libKLU_complex.la libKLU.la
libKLU_real_la_SOURCES = \
klu.c \
klu_diagnostics.c \
klu_dump.c \
klu_extract.c \
klu_factor.c \
klu_free_numeric.c \
klu_kernel.c \
klu_multiply.c \
klu_refactor.c \
klu_scale.c \
klu_solve.c \
klu_sort.c \
klu_tsolve.c \
klu_utils.c
libKLU_real_la_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include
libKLU_complex_la_SOURCES = \
klu.c \
klu_diagnostics.c \
klu_dump.c \
klu_extract.c \
klu_factor.c \
klu_free_numeric.c \
klu_kernel.c \
klu_multiply.c \
klu_refactor.c \
klu_scale.c \
klu_solve.c \
klu_sort.c \
klu_tsolve.c \
klu_utils.c
libKLU_complex_la_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include -DCOMPLEX
libKLU_la_SOURCES = \
amd_1.c \
amd_2.c \
amd_aat.c \
amd_control.c \
amd_defaults.c \
amd_dump.c \
amd_global.c \
amd_info.c \
amd_order.c \
amd_postorder.c \
amd_post_tree.c \
amd_preprocess.c \
amd_valid.c \
btf_maxtrans.c \
btf_order.c \
btf_strongcomp.c \
colamd.c \
colamd_global.c \
klu_analyze.c \
klu_analyze_given.c \
klu_defaults.c \
klu_free_symbolic.c \
klu_memory.c \
klusmp.c
libKLU_la_LIBADD = \
libKLU_real.la \
libKLU_complex.la
libKLU_la_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include
AM_CFLAGS = $(STATIC)
MAINTAINERCLEANFILES = Makefile.in

View File

@ -0,0 +1,43 @@
<2016-07-03 So>
old/archived source from
http://faculty.cse.tamu.edu/davis/suitesparse.html
http://faculty.cse.tamu.edu/davis/SuiteSparse/SuiteSparse-3.7.0.tar.gz
inject source files from there :
(compile "tar=../../../SuiteSparse-3.7.0.tar.gz
for dir in SuiteSparse/KLU/Source SuiteSparse/KLU/Include \\
SuiteSparse/AMD/Source SuiteSparse/AMD/Include \\
SuiteSparse/BTF/Source SuiteSparse/BTF/Include \\
SuiteSparse/COLAMD/Source SuiteSparse/COLAMD/Include
do
tar -zxf $tar $dir
files=$(cd $dir && ls -1 *.c *.h)
mv $dir/*.c $dir/*.h .
git add $files
done
file=SuiteSparse/UFconfig/UFconfig.h
tar -zxf $tar $file
mv $file .
git add $(basename $file)
")
(compile "for file in colamd.h amd.h btf.h klu.h UFconfig.h
do
git mv $file ../../include/ngspice/$file
done
")
delete-trailing-whitespace and untabify :
(loop for file in (process-lines "git" "ls-files")
do (with-temp-file file
(insert-file-contents file)
(delete-trailing-whitespace)
;; (untabify (point-min) (point-max))
))

181
src/maths/KLU/amd_1.c Normal file
View File

@ -0,0 +1,181 @@
/* ========================================================================= */
/* === AMD_1 =============================================================== */
/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/* AMD, Copyright (c) Timothy A. Davis, */
/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */
/* web: http://www.cise.ufl.edu/research/sparse/amd */
/* ------------------------------------------------------------------------- */
/* AMD_1: Construct A+A' for a sparse matrix A and perform the AMD ordering.
*
* The n-by-n sparse matrix A can be unsymmetric. It is stored in MATLAB-style
* compressed-column form, with sorted row indices in each column, and no
* duplicate entries. Diagonal entries may be present, but they are ignored.
* Row indices of column j of A are stored in Ai [Ap [j] ... Ap [j+1]-1].
* Ap [0] must be zero, and nz = Ap [n] is the number of entries in A. The
* size of the matrix, n, must be greater than or equal to zero.
*
* This routine must be preceded by a call to AMD_aat, which computes the
* number of entries in each row/column in A+A', excluding the diagonal.
* Len [j], on input, is the number of entries in row/column j of A+A'. This
* routine constructs the matrix A+A' and then calls AMD_2. No error checking
* is performed (this was done in AMD_valid).
*/
#include "amd_internal.h"
GLOBAL void AMD_1
(
Int n, /* n > 0 */
const Int Ap [ ], /* input of size n+1, not modified */
const Int Ai [ ], /* input of size nz = Ap [n], not modified */
Int P [ ], /* size n output permutation */
Int Pinv [ ], /* size n output inverse permutation */
Int Len [ ], /* size n input, undefined on output */
Int slen, /* slen >= sum (Len [0..n-1]) + 7n,
* ideally slen = 1.2 * sum (Len) + 8n */
Int S [ ], /* size slen workspace */
double Control [ ], /* input array of size AMD_CONTROL */
double Info [ ] /* output array of size AMD_INFO */
)
{
Int i, j, k, p, pfree, iwlen, pj, p1, p2, pj2, *Iw, *Pe, *Nv, *Head,
*Elen, *Degree, *s, *W, *Sp, *Tp ;
/* --------------------------------------------------------------------- */
/* construct the matrix for AMD_2 */
/* --------------------------------------------------------------------- */
ASSERT (n > 0) ;
iwlen = slen - 6*n ;
s = S ;
Pe = s ; s += n ;
Nv = s ; s += n ;
Head = s ; s += n ;
Elen = s ; s += n ;
Degree = s ; s += n ;
W = s ; s += n ;
Iw = s ; s += iwlen ;
ASSERT (AMD_valid (n, n, Ap, Ai) == AMD_OK) ;
/* construct the pointers for A+A' */
Sp = Nv ; /* use Nv and W as workspace for Sp and Tp [ */
Tp = W ;
pfree = 0 ;
for (j = 0 ; j < n ; j++)
{
Pe [j] = pfree ;
Sp [j] = pfree ;
pfree += Len [j] ;
}
/* Note that this restriction on iwlen is slightly more restrictive than
* what is strictly required in AMD_2. AMD_2 can operate with no elbow
* room at all, but it will be very slow. For better performance, at
* least size-n elbow room is enforced. */
ASSERT (iwlen >= pfree + n) ;
#ifndef NDEBUG
for (p = 0 ; p < iwlen ; p++) Iw [p] = EMPTY ;
#endif
for (k = 0 ; k < n ; k++)
{
AMD_DEBUG1 (("Construct row/column k= "ID" of A+A'\n", k)) ;
p1 = Ap [k] ;
p2 = Ap [k+1] ;
/* construct A+A' */
for (p = p1 ; p < p2 ; )
{
/* scan the upper triangular part of A */
j = Ai [p] ;
ASSERT (j >= 0 && j < n) ;
if (j < k)
{
/* entry A (j,k) in the strictly upper triangular part */
ASSERT (Sp [j] < (j == n-1 ? pfree : Pe [j+1])) ;
ASSERT (Sp [k] < (k == n-1 ? pfree : Pe [k+1])) ;
Iw [Sp [j]++] = k ;
Iw [Sp [k]++] = j ;
p++ ;
}
else if (j == k)
{
/* skip the diagonal */
p++ ;
break ;
}
else /* j > k */
{
/* first entry below the diagonal */
break ;
}
/* scan lower triangular part of A, in column j until reaching
* row k. Start where last scan left off. */
ASSERT (Ap [j] <= Tp [j] && Tp [j] <= Ap [j+1]) ;
pj2 = Ap [j+1] ;
for (pj = Tp [j] ; pj < pj2 ; )
{
i = Ai [pj] ;
ASSERT (i >= 0 && i < n) ;
if (i < k)
{
/* A (i,j) is only in the lower part, not in upper */
ASSERT (Sp [i] < (i == n-1 ? pfree : Pe [i+1])) ;
ASSERT (Sp [j] < (j == n-1 ? pfree : Pe [j+1])) ;
Iw [Sp [i]++] = j ;
Iw [Sp [j]++] = i ;
pj++ ;
}
else if (i == k)
{
/* entry A (k,j) in lower part and A (j,k) in upper */
pj++ ;
break ;
}
else /* i > k */
{
/* consider this entry later, when k advances to i */
break ;
}
}
Tp [j] = pj ;
}
Tp [k] = p ;
}
/* clean up, for remaining mismatched entries */
for (j = 0 ; j < n ; j++)
{
for (pj = Tp [j] ; pj < Ap [j+1] ; pj++)
{
i = Ai [pj] ;
ASSERT (i >= 0 && i < n) ;
/* A (i,j) is only in the lower part, not in upper */
ASSERT (Sp [i] < (i == n-1 ? pfree : Pe [i+1])) ;
ASSERT (Sp [j] < (j == n-1 ? pfree : Pe [j+1])) ;
Iw [Sp [i]++] = j ;
Iw [Sp [j]++] = i ;
}
}
#ifndef NDEBUG
for (j = 0 ; j < n-1 ; j++) ASSERT (Sp [j] == Pe [j+1]) ;
ASSERT (Sp [n-1] == pfree) ;
#endif
/* Tp and Sp no longer needed ] */
/* --------------------------------------------------------------------- */
/* order the matrix */
/* --------------------------------------------------------------------- */
AMD_2 (n, Pe, Iw, Len, iwlen, pfree,
Nv, Pinv, P, Head, Elen, Degree, W, Control, Info) ;
}

1842
src/maths/KLU/amd_2.c Normal file

File diff suppressed because it is too large Load Diff

185
src/maths/KLU/amd_aat.c Normal file
View File

@ -0,0 +1,185 @@
/* ========================================================================= */
/* === AMD_aat ============================================================= */
/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/* AMD, Copyright (c) Timothy A. Davis, */
/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */
/* web: http://www.cise.ufl.edu/research/sparse/amd */
/* ------------------------------------------------------------------------- */
/* AMD_aat: compute the symmetry of the pattern of A, and count the number of
* nonzeros each column of A+A' (excluding the diagonal). Assumes the input
* matrix has no errors, with sorted columns and no duplicates
* (AMD_valid (n, n, Ap, Ai) must be AMD_OK, but this condition is not
* checked).
*/
#include "amd_internal.h"
GLOBAL size_t AMD_aat /* returns nz in A+A' */
(
Int n,
const Int Ap [ ],
const Int Ai [ ],
Int Len [ ], /* Len [j]: length of column j of A+A', excl diagonal*/
Int Tp [ ], /* workspace of size n */
double Info [ ]
)
{
Int p1, p2, p, i, j, pj, pj2, k, nzdiag, nzboth, nz ;
double sym ;
size_t nzaat ;
#ifndef NDEBUG
AMD_debug_init ("AMD AAT") ;
for (k = 0 ; k < n ; k++) Tp [k] = EMPTY ;
ASSERT (AMD_valid (n, n, Ap, Ai) == AMD_OK) ;
#endif
if (Info != (double *) NULL)
{
/* clear the Info array, if it exists */
for (i = 0 ; i < AMD_INFO ; i++)
{
Info [i] = EMPTY ;
}
Info [AMD_STATUS] = AMD_OK ;
}
for (k = 0 ; k < n ; k++)
{
Len [k] = 0 ;
}
nzdiag = 0 ;
nzboth = 0 ;
nz = Ap [n] ;
for (k = 0 ; k < n ; k++)
{
p1 = Ap [k] ;
p2 = Ap [k+1] ;
AMD_DEBUG2 (("\nAAT Column: "ID" p1: "ID" p2: "ID"\n", k, p1, p2)) ;
/* construct A+A' */
for (p = p1 ; p < p2 ; )
{
/* scan the upper triangular part of A */
j = Ai [p] ;
if (j < k)
{
/* entry A (j,k) is in the strictly upper triangular part,
* add both A (j,k) and A (k,j) to the matrix A+A' */
Len [j]++ ;
Len [k]++ ;
AMD_DEBUG3 ((" upper ("ID","ID") ("ID","ID")\n", j,k, k,j));
p++ ;
}
else if (j == k)
{
/* skip the diagonal */
p++ ;
nzdiag++ ;
break ;
}
else /* j > k */
{
/* first entry below the diagonal */
break ;
}
/* scan lower triangular part of A, in column j until reaching
* row k. Start where last scan left off. */
ASSERT (Tp [j] != EMPTY) ;
ASSERT (Ap [j] <= Tp [j] && Tp [j] <= Ap [j+1]) ;
pj2 = Ap [j+1] ;
for (pj = Tp [j] ; pj < pj2 ; )
{
i = Ai [pj] ;
if (i < k)
{
/* A (i,j) is only in the lower part, not in upper.
* add both A (i,j) and A (j,i) to the matrix A+A' */
Len [i]++ ;
Len [j]++ ;
AMD_DEBUG3 ((" lower ("ID","ID") ("ID","ID")\n",
i,j, j,i)) ;
pj++ ;
}
else if (i == k)
{
/* entry A (k,j) in lower part and A (j,k) in upper */
pj++ ;
nzboth++ ;
break ;
}
else /* i > k */
{
/* consider this entry later, when k advances to i */
break ;
}
}
Tp [j] = pj ;
}
/* Tp [k] points to the entry just below the diagonal in column k */
Tp [k] = p ;
}
/* clean up, for remaining mismatched entries */
for (j = 0 ; j < n ; j++)
{
for (pj = Tp [j] ; pj < Ap [j+1] ; pj++)
{
i = Ai [pj] ;
/* A (i,j) is only in the lower part, not in upper.
* add both A (i,j) and A (j,i) to the matrix A+A' */
Len [i]++ ;
Len [j]++ ;
AMD_DEBUG3 ((" lower cleanup ("ID","ID") ("ID","ID")\n",
i,j, j,i)) ;
}
}
/* --------------------------------------------------------------------- */
/* compute the symmetry of the nonzero pattern of A */
/* --------------------------------------------------------------------- */
/* Given a matrix A, the symmetry of A is:
* B = tril (spones (A), -1) + triu (spones (A), 1) ;
* sym = nnz (B & B') / nnz (B) ;
* or 1 if nnz (B) is zero.
*/
if (nz == nzdiag)
{
sym = 1 ;
}
else
{
sym = (2 * (double) nzboth) / ((double) (nz - nzdiag)) ;
}
nzaat = 0 ;
for (k = 0 ; k < n ; k++)
{
nzaat += Len [k] ;
}
AMD_DEBUG1 (("AMD nz in A+A', excluding diagonal (nzaat) = %g\n",
(double) nzaat)) ;
AMD_DEBUG1 ((" nzboth: "ID" nz: "ID" nzdiag: "ID" symmetry: %g\n",
nzboth, nz, nzdiag, sym)) ;
if (Info != (double *) NULL)
{
Info [AMD_STATUS] = AMD_OK ;
Info [AMD_N] = n ;
Info [AMD_NZ] = nz ;
Info [AMD_SYMMETRY] = sym ; /* symmetry of pattern of A */
Info [AMD_NZDIAG] = nzdiag ; /* nonzeros on diagonal of A */
Info [AMD_NZ_A_PLUS_AT] = nzaat ; /* nonzeros in A+A' */
}
return (nzaat) ;
}

View File

@ -0,0 +1,64 @@
/* ========================================================================= */
/* === AMD_control ========================================================= */
/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/* AMD, Copyright (c) Timothy A. Davis, */
/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */
/* web: http://www.cise.ufl.edu/research/sparse/amd */
/* ------------------------------------------------------------------------- */
/* User-callable. Prints the control parameters for AMD. See amd.h
* for details. If the Control array is not present, the defaults are
* printed instead.
*/
#include "amd_internal.h"
GLOBAL void AMD_control
(
double Control [ ]
)
{
double alpha ;
Int aggressive ;
if (Control != (double *) NULL)
{
alpha = Control [AMD_DENSE] ;
aggressive = Control [AMD_AGGRESSIVE] != 0 ;
}
else
{
alpha = AMD_DEFAULT_DENSE ;
aggressive = AMD_DEFAULT_AGGRESSIVE ;
}
PRINTF (("\nAMD version %d.%d.%d, %s: approximate minimum degree ordering\n"
" dense row parameter: %g\n", AMD_MAIN_VERSION, AMD_SUB_VERSION,
AMD_SUBSUB_VERSION, AMD_DATE, alpha)) ;
if (alpha < 0)
{
PRINTF ((" no rows treated as dense\n")) ;
}
else
{
PRINTF ((
" (rows with more than max (%g * sqrt (n), 16) entries are\n"
" considered \"dense\", and placed last in output permutation)\n",
alpha)) ;
}
if (aggressive)
{
PRINTF ((" aggressive absorption: yes\n")) ;
}
else
{
PRINTF ((" aggressive absorption: no\n")) ;
}
PRINTF ((" size of AMD integer: %d\n\n", sizeof (Int))) ;
}

View File

@ -0,0 +1,38 @@
/* ========================================================================= */
/* === AMD_defaults ======================================================== */
/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/* AMD, Copyright (c) Timothy A. Davis, */
/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */
/* web: http://www.cise.ufl.edu/research/sparse/amd */
/* ------------------------------------------------------------------------- */
/* User-callable. Sets default control parameters for AMD. See amd.h
* for details.
*/
#include "amd_internal.h"
/* ========================================================================= */
/* === AMD defaults ======================================================== */
/* ========================================================================= */
GLOBAL void AMD_defaults
(
double Control [ ]
)
{
Int i ;
if (Control != (double *) NULL)
{
for (i = 0 ; i < AMD_CONTROL ; i++)
{
Control [i] = 0 ;
}
Control [AMD_DENSE] = AMD_DEFAULT_DENSE ;
Control [AMD_AGGRESSIVE] = AMD_DEFAULT_AGGRESSIVE ;
}
}

180
src/maths/KLU/amd_dump.c Normal file
View File

@ -0,0 +1,180 @@
/* ========================================================================= */
/* === AMD_dump ============================================================ */
/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/* AMD, Copyright (c) Timothy A. Davis, */
/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */
/* web: http://www.cise.ufl.edu/research/sparse/amd */
/* ------------------------------------------------------------------------- */
/* Debugging routines for AMD. Not used if NDEBUG is not defined at compile-
* time (the default). See comments in amd_internal.h on how to enable
* debugging. Not user-callable.
*/
#include "amd_internal.h"
#ifndef NDEBUG
/* This global variable is present only when debugging */
GLOBAL Int AMD_debug = -999 ; /* default is no debug printing */
/* ========================================================================= */
/* === AMD_debug_init ====================================================== */
/* ========================================================================= */
/* Sets the debug print level, by reading the file debug.amd (if it exists) */
GLOBAL void AMD_debug_init ( char *s )
{
FILE *f ;
f = fopen ("debug.amd", "r") ;
if (f == (FILE *) NULL)
{
AMD_debug = -999 ;
}
else
{
fscanf (f, ID, &AMD_debug) ;
fclose (f) ;
}
if (AMD_debug >= 0)
{
printf ("%s: AMD_debug_init, D= "ID"\n", s, AMD_debug) ;
}
}
/* ========================================================================= */
/* === AMD_dump ============================================================ */
/* ========================================================================= */
/* Dump AMD's data structure, except for the hash buckets. This routine
* cannot be called when the hash buckets are non-empty.
*/
GLOBAL void AMD_dump (
Int n, /* A is n-by-n */
Int Pe [ ], /* pe [0..n-1]: index in iw of start of row i */
Int Iw [ ], /* workspace of size iwlen, iwlen [0..pfree-1]
* holds the matrix on input */
Int Len [ ], /* len [0..n-1]: length for row i */
Int iwlen, /* length of iw */
Int pfree, /* iw [pfree ... iwlen-1] is empty on input */
Int Nv [ ], /* nv [0..n-1] */
Int Next [ ], /* next [0..n-1] */
Int Last [ ], /* last [0..n-1] */
Int Head [ ], /* head [0..n-1] */
Int Elen [ ], /* size n */
Int Degree [ ], /* size n */
Int W [ ], /* size n */
Int nel
)
{
Int i, pe, elen, nv, len, e, p, k, j, deg, w, cnt, ilast ;
if (AMD_debug < 0) return ;
ASSERT (pfree <= iwlen) ;
AMD_DEBUG3 (("\nAMD dump, pfree: "ID"\n", pfree)) ;
for (i = 0 ; i < n ; i++)
{
pe = Pe [i] ;
elen = Elen [i] ;
nv = Nv [i] ;
len = Len [i] ;
w = W [i] ;
if (elen >= EMPTY)
{
if (nv == 0)
{
AMD_DEBUG3 (("\nI "ID": nonprincipal: ", i)) ;
ASSERT (elen == EMPTY) ;
if (pe == EMPTY)
{
AMD_DEBUG3 ((" dense node\n")) ;
ASSERT (w == 1) ;
}
else
{
ASSERT (pe < EMPTY) ;
AMD_DEBUG3 ((" i "ID" -> parent "ID"\n", i, FLIP (Pe[i])));
}
}
else
{
AMD_DEBUG3 (("\nI "ID": active principal supervariable:\n",i));
AMD_DEBUG3 ((" nv(i): "ID" Flag: %d\n", nv, (nv < 0))) ;
ASSERT (elen >= 0) ;
ASSERT (nv > 0 && pe >= 0) ;
p = pe ;
AMD_DEBUG3 ((" e/s: ")) ;
if (elen == 0) AMD_DEBUG3 ((" : ")) ;
ASSERT (pe + len <= pfree) ;
for (k = 0 ; k < len ; k++)
{
j = Iw [p] ;
AMD_DEBUG3 ((" "ID"", j)) ;
ASSERT (j >= 0 && j < n) ;
if (k == elen-1) AMD_DEBUG3 ((" : ")) ;
p++ ;
}
AMD_DEBUG3 (("\n")) ;
}
}
else
{
e = i ;
if (w == 0)
{
AMD_DEBUG3 (("\nE "ID": absorbed element: w "ID"\n", e, w)) ;
ASSERT (nv > 0 && pe < 0) ;
AMD_DEBUG3 ((" e "ID" -> parent "ID"\n", e, FLIP (Pe [e]))) ;
}
else
{
AMD_DEBUG3 (("\nE "ID": unabsorbed element: w "ID"\n", e, w)) ;
ASSERT (nv > 0 && pe >= 0) ;
p = pe ;
AMD_DEBUG3 ((" : ")) ;
ASSERT (pe + len <= pfree) ;
for (k = 0 ; k < len ; k++)
{
j = Iw [p] ;
AMD_DEBUG3 ((" "ID"", j)) ;
ASSERT (j >= 0 && j < n) ;
p++ ;
}
AMD_DEBUG3 (("\n")) ;
}
}
}
/* this routine cannot be called when the hash buckets are non-empty */
AMD_DEBUG3 (("\nDegree lists:\n")) ;
if (nel >= 0)
{
cnt = 0 ;
for (deg = 0 ; deg < n ; deg++)
{
if (Head [deg] == EMPTY) continue ;
ilast = EMPTY ;
AMD_DEBUG3 ((ID": \n", deg)) ;
for (i = Head [deg] ; i != EMPTY ; i = Next [i])
{
AMD_DEBUG3 ((" "ID" : next "ID" last "ID" deg "ID"\n",
i, Next [i], Last [i], Degree [i])) ;
ASSERT (i >= 0 && i < n && ilast == Last [i] &&
deg == Degree [i]) ;
cnt += Nv [i] ;
ilast = i ;
}
AMD_DEBUG3 (("\n")) ;
}
ASSERT (cnt == n - nel) ;
}
}
#endif

View File

@ -0,0 +1,84 @@
/* ========================================================================= */
/* === amd_global ========================================================== */
/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/* AMD, Copyright (c) Timothy A. Davis, */
/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */
/* web: http://www.cise.ufl.edu/research/sparse/amd */
/* ------------------------------------------------------------------------- */
#include <stdlib.h>
#ifdef MATLAB_MEX_FILE
#include "mex.h"
#include "matrix.h"
#endif
#ifndef NULL
#define NULL 0
#endif
/* ========================================================================= */
/* === Default AMD memory manager ========================================== */
/* ========================================================================= */
/* The user can redefine these global pointers at run-time to change the memory
* manager used by AMD. AMD only uses malloc and free; realloc and calloc are
* include for completeness, in case another package wants to use the same
* memory manager as AMD.
*
* If compiling as a MATLAB mexFunction, the default memory manager is mxMalloc.
* You can also compile AMD as a standard ANSI-C library and link a mexFunction
* against it, and then redefine these pointers at run-time, in your
* mexFunction.
*
* If -DNMALLOC is defined at compile-time, no memory manager is specified at
* compile-time. You must then define these functions at run-time, before
* calling AMD, for AMD to work properly.
*/
#ifndef NMALLOC
#ifdef MATLAB_MEX_FILE
/* MATLAB mexFunction: */
void *(*amd_malloc) (size_t) = mxMalloc ;
void (*amd_free) (void *) = mxFree ;
void *(*amd_realloc) (void *, size_t) = mxRealloc ;
void *(*amd_calloc) (size_t, size_t) = mxCalloc ;
#else
/* standard ANSI-C: */
void *(*amd_malloc) (size_t) = malloc ;
void (*amd_free) (void *) = free ;
void *(*amd_realloc) (void *, size_t) = realloc ;
void *(*amd_calloc) (size_t, size_t) = calloc ;
#endif
#else
/* no memory manager defined at compile-time; you MUST define one at run-time */
void *(*amd_malloc) (size_t) = NULL ;
void (*amd_free) (void *) = NULL ;
void *(*amd_realloc) (void *, size_t) = NULL ;
void *(*amd_calloc) (size_t, size_t) = NULL ;
#endif
/* ========================================================================= */
/* === Default AMD printf routine ========================================== */
/* ========================================================================= */
/* The user can redefine this global pointer at run-time to change the printf
* routine used by AMD. If NULL, no printing occurs.
*
* If -DNPRINT is defined at compile-time, stdio.h is not included. Printing
* can then be enabled at run-time by setting amd_printf to a non-NULL function.
*/
#ifndef NPRINT
#ifdef MATLAB_MEX_FILE
int (*amd_printf) (const char *, ...) = mexPrintf ;
#else
#include <stdio.h>
int (*amd_printf) (const char *, ...) = printf ;
#endif
#else
int (*amd_printf) (const char *, ...) = NULL ;
#endif

120
src/maths/KLU/amd_info.c Normal file
View File

@ -0,0 +1,120 @@
/* ========================================================================= */
/* === AMD_info ============================================================ */
/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/* AMD, Copyright (c) Timothy A. Davis, */
/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */
/* web: http://www.cise.ufl.edu/research/sparse/amd */
/* ------------------------------------------------------------------------- */
/* User-callable. Prints the output statistics for AMD. See amd.h
* for details. If the Info array is not present, nothing is printed.
*/
#include "amd_internal.h"
#define PRI(format,x) { if (x >= 0) { PRINTF ((format, x)) ; }}
GLOBAL void AMD_info
(
double Info [ ]
)
{
double n, ndiv, nmultsubs_ldl, nmultsubs_lu, lnz, lnzd ;
PRINTF (("\nAMD version %d.%d.%d, %s, results:\n",
AMD_MAIN_VERSION, AMD_SUB_VERSION, AMD_SUBSUB_VERSION, AMD_DATE)) ;
if (!Info)
{
return ;
}
n = Info [AMD_N] ;
ndiv = Info [AMD_NDIV] ;
nmultsubs_ldl = Info [AMD_NMULTSUBS_LDL] ;
nmultsubs_lu = Info [AMD_NMULTSUBS_LU] ;
lnz = Info [AMD_LNZ] ;
lnzd = (n >= 0 && lnz >= 0) ? (n + lnz) : (-1) ;
/* AMD return status */
PRINTF ((" status: ")) ;
if (Info [AMD_STATUS] == AMD_OK)
{
PRINTF (("OK\n")) ;
}
else if (Info [AMD_STATUS] == AMD_OUT_OF_MEMORY)
{
PRINTF (("out of memory\n")) ;
}
else if (Info [AMD_STATUS] == AMD_INVALID)
{
PRINTF (("invalid matrix\n")) ;
}
else if (Info [AMD_STATUS] == AMD_OK_BUT_JUMBLED)
{
PRINTF (("OK, but jumbled\n")) ;
}
else
{
PRINTF (("unknown\n")) ;
}
/* statistics about the input matrix */
PRI (" n, dimension of A: %.20g\n", n);
PRI (" nz, number of nonzeros in A: %.20g\n",
Info [AMD_NZ]) ;
PRI (" symmetry of A: %.4f\n",
Info [AMD_SYMMETRY]) ;
PRI (" number of nonzeros on diagonal: %.20g\n",
Info [AMD_NZDIAG]) ;
PRI (" nonzeros in pattern of A+A' (excl. diagonal): %.20g\n",
Info [AMD_NZ_A_PLUS_AT]) ;
PRI (" # dense rows/columns of A+A': %.20g\n",
Info [AMD_NDENSE]) ;
/* statistics about AMD's behavior */
PRI (" memory used, in bytes: %.20g\n",
Info [AMD_MEMORY]) ;
PRI (" # of memory compactions: %.20g\n",
Info [AMD_NCMPA]) ;
/* statistics about the ordering quality */
PRINTF (("\n"
" The following approximate statistics are for a subsequent\n"
" factorization of A(P,P) + A(P,P)'. They are slight upper\n"
" bounds if there are no dense rows/columns in A+A', and become\n"
" looser if dense rows/columns exist.\n\n")) ;
PRI (" nonzeros in L (excluding diagonal): %.20g\n",
lnz) ;
PRI (" nonzeros in L (including diagonal): %.20g\n",
lnzd) ;
PRI (" # divide operations for LDL' or LU: %.20g\n",
ndiv) ;
PRI (" # multiply-subtract operations for LDL': %.20g\n",
nmultsubs_ldl) ;
PRI (" # multiply-subtract operations for LU: %.20g\n",
nmultsubs_lu) ;
PRI (" max nz. in any column of L (incl. diagonal): %.20g\n",
Info [AMD_DMAX]) ;
/* total flop counts for various factorizations */
if (n >= 0 && ndiv >= 0 && nmultsubs_ldl >= 0 && nmultsubs_lu >= 0)
{
PRINTF (("\n"
" chol flop count for real A, sqrt counted as 1 flop: %.20g\n"
" LDL' flop count for real A: %.20g\n"
" LDL' flop count for complex A: %.20g\n"
" LU flop count for real A (with no pivoting): %.20g\n"
" LU flop count for complex A (with no pivoting): %.20g\n\n",
n + ndiv + 2*nmultsubs_ldl,
ndiv + 2*nmultsubs_ldl,
9*ndiv + 8*nmultsubs_ldl,
ndiv + 2*nmultsubs_lu,
9*ndiv + 8*nmultsubs_lu)) ;
}
}

View File

@ -0,0 +1,350 @@
/* ========================================================================= */
/* === amd_internal.h ====================================================== */
/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/* AMD, Copyright (c) Timothy A. Davis, */
/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */
/* web: http://www.cise.ufl.edu/research/sparse/amd */
/* ------------------------------------------------------------------------- */
/* This file is for internal use in AMD itself, and does not normally need to
* be included in user code (it is included in UMFPACK, however). All others
* should use amd.h instead.
*
* The following compile-time definitions affect how AMD is compiled.
*
* -DNPRINT
*
* Disable all printing. stdio.h will not be included. Printing can
* be re-enabled at run-time by setting the global pointer amd_printf
* to printf (or mexPrintf for a MATLAB mexFunction).
*
* -DNMALLOC
*
* No memory manager is defined at compile-time. You MUST define the
* function pointers amd_malloc, amd_free, amd_realloc, and
* amd_calloc at run-time for AMD to work properly.
*/
/* ========================================================================= */
/* === NDEBUG ============================================================== */
/* ========================================================================= */
/*
* Turning on debugging takes some work (see below). If you do not edit this
* file, then debugging is always turned off, regardless of whether or not
* -DNDEBUG is specified in your compiler options.
*
* If AMD is being compiled as a mexFunction, then MATLAB_MEX_FILE is defined,
* and mxAssert is used instead of assert. If debugging is not enabled, no
* MATLAB include files or functions are used. Thus, the AMD library libamd.a
* can be safely used in either a stand-alone C program or in another
* mexFunction, without any change.
*/
/*
AMD will be exceedingly slow when running in debug mode. The next three
lines ensure that debugging is turned off.
*/
#ifndef NDEBUG
#define NDEBUG
#endif
/*
To enable debugging, uncomment the following line:
#undef NDEBUG
*/
/* ------------------------------------------------------------------------- */
/* ANSI include files */
/* ------------------------------------------------------------------------- */
/* from stdlib.h: size_t, malloc, free, realloc, and calloc */
#include <stdlib.h>
#if !defined(NPRINT) || !defined(NDEBUG)
/* from stdio.h: printf. Not included if NPRINT is defined at compile time.
* fopen and fscanf are used when debugging. */
#include <stdio.h>
#endif
/* from limits.h: INT_MAX and LONG_MAX */
#include <limits.h>
/* from math.h: sqrt */
#include <math.h>
/* ------------------------------------------------------------------------- */
/* MATLAB include files (only if being used in or via MATLAB) */
/* ------------------------------------------------------------------------- */
#ifdef MATLAB_MEX_FILE
#include "matrix.h"
#include "mex.h"
#endif
/* ------------------------------------------------------------------------- */
/* basic definitions */
/* ------------------------------------------------------------------------- */
#ifdef FLIP
#undef FLIP
#endif
#ifdef MAX
#undef MAX
#endif
#ifdef MIN
#undef MIN
#endif
#ifdef EMPTY
#undef EMPTY
#endif
#ifdef GLOBAL
#undef GLOBAL
#endif
#ifdef PRIVATE
#undef PRIVATE
#endif
/* FLIP is a "negation about -1", and is used to mark an integer i that is
* normally non-negative. FLIP (EMPTY) is EMPTY. FLIP of a number > EMPTY
* is negative, and FLIP of a number < EMTPY is positive. FLIP (FLIP (i)) = i
* for all integers i. UNFLIP (i) is >= EMPTY. */
#define EMPTY (-1)
#define FLIP(i) (-(i)-2)
#define UNFLIP(i) ((i < EMPTY) ? FLIP (i) : (i))
/* for integer MAX/MIN, or for doubles when we don't care how NaN's behave: */
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
/* logical expression of p implies q: */
#define IMPLIES(p,q) (!(p) || (q))
/* Note that the IBM RS 6000 xlc predefines TRUE and FALSE in <types.h>. */
/* The Compaq Alpha also predefines TRUE and FALSE. */
#ifdef TRUE
#undef TRUE
#endif
#ifdef FALSE
#undef FALSE
#endif
#define TRUE (1)
#define FALSE (0)
#define PRIVATE static
#define GLOBAL
#define EMPTY (-1)
/* Note that Linux's gcc 2.96 defines NULL as ((void *) 0), but other */
/* compilers (even gcc 2.95.2 on Solaris) define NULL as 0 or (0). We */
/* need to use the ANSI standard value of 0. */
#ifdef NULL
#undef NULL
#endif
#define NULL 0
/* largest value of size_t */
#ifndef SIZE_T_MAX
#define SIZE_T_MAX ((size_t) (-1))
#endif
/* ------------------------------------------------------------------------- */
/* integer type for AMD: int or UF_long */
/* ------------------------------------------------------------------------- */
/* define UF_long */
#include "ngspice/UFconfig.h"
#if defined (DLONG) || defined (ZLONG)
#define Int UF_long
#define ID UF_long_id
#define Int_MAX UF_long_max
#define AMD_order amd_l_order
#define AMD_defaults amd_l_defaults
#define AMD_control amd_l_control
#define AMD_info amd_l_info
#define AMD_1 amd_l1
#define AMD_2 amd_l2
#define AMD_valid amd_l_valid
#define AMD_aat amd_l_aat
#define AMD_postorder amd_l_postorder
#define AMD_post_tree amd_l_post_tree
#define AMD_dump amd_l_dump
#define AMD_debug amd_l_debug
#define AMD_debug_init amd_l_debug_init
#define AMD_preprocess amd_l_preprocess
#else
#define Int int
#define ID "%d"
#define Int_MAX INT_MAX
#define AMD_order amd_order
#define AMD_defaults amd_defaults
#define AMD_control amd_control
#define AMD_info amd_info
#define AMD_1 amd_1
#define AMD_2 amd_2
#define AMD_valid amd_valid
#define AMD_aat amd_aat
#define AMD_postorder amd_postorder
#define AMD_post_tree amd_post_tree
#define AMD_dump amd_dump
#define AMD_debug amd_debug
#define AMD_debug_init amd_debug_init
#define AMD_preprocess amd_preprocess
#endif
/* ========================================================================= */
/* === PRINTF macro ======================================================== */
/* ========================================================================= */
/* All output goes through the PRINTF macro. */
#define PRINTF(params) { if (amd_printf != NULL) (void) amd_printf params ; }
/* ------------------------------------------------------------------------- */
/* AMD routine definitions (user-callable) */
/* ------------------------------------------------------------------------- */
#include "ngspice/amd.h"
/* ------------------------------------------------------------------------- */
/* AMD routine definitions (not user-callable) */
/* ------------------------------------------------------------------------- */
GLOBAL size_t AMD_aat
(
Int n,
const Int Ap [ ],
const Int Ai [ ],
Int Len [ ],
Int Tp [ ],
double Info [ ]
) ;
GLOBAL void AMD_1
(
Int n,
const Int Ap [ ],
const Int Ai [ ],
Int P [ ],
Int Pinv [ ],
Int Len [ ],
Int slen,
Int S [ ],
double Control [ ],
double Info [ ]
) ;
GLOBAL void AMD_postorder
(
Int nn,
Int Parent [ ],
Int Npiv [ ],
Int Fsize [ ],
Int Order [ ],
Int Child [ ],
Int Sibling [ ],
Int Stack [ ]
) ;
GLOBAL Int AMD_post_tree
(
Int root,
Int k,
Int Child [ ],
const Int Sibling [ ],
Int Order [ ],
Int Stack [ ]
#ifndef NDEBUG
, Int nn
#endif
) ;
GLOBAL void AMD_preprocess
(
Int n,
const Int Ap [ ],
const Int Ai [ ],
Int Rp [ ],
Int Ri [ ],
Int W [ ],
Int Flag [ ]
) ;
/* ------------------------------------------------------------------------- */
/* debugging definitions */
/* ------------------------------------------------------------------------- */
#ifndef NDEBUG
/* from assert.h: assert macro */
#include <assert.h>
#ifndef EXTERN
#define EXTERN extern
#endif
EXTERN Int AMD_debug ;
GLOBAL void AMD_debug_init ( char *s ) ;
GLOBAL void AMD_dump
(
Int n,
Int Pe [ ],
Int Iw [ ],
Int Len [ ],
Int iwlen,
Int pfree,
Int Nv [ ],
Int Next [ ],
Int Last [ ],
Int Head [ ],
Int Elen [ ],
Int Degree [ ],
Int W [ ],
Int nel
) ;
#ifdef ASSERT
#undef ASSERT
#endif
/* Use mxAssert if AMD is compiled into a mexFunction */
#ifdef MATLAB_MEX_FILE
#define ASSERT(expression) (mxAssert ((expression), ""))
#else
#define ASSERT(expression) (assert (expression))
#endif
#define AMD_DEBUG0(params) { PRINTF (params) ; }
#define AMD_DEBUG1(params) { if (AMD_debug >= 1) PRINTF (params) ; }
#define AMD_DEBUG2(params) { if (AMD_debug >= 2) PRINTF (params) ; }
#define AMD_DEBUG3(params) { if (AMD_debug >= 3) PRINTF (params) ; }
#define AMD_DEBUG4(params) { if (AMD_debug >= 4) PRINTF (params) ; }
#else
/* no debugging */
#define ASSERT(expression)
#define AMD_DEBUG0(params)
#define AMD_DEBUG1(params)
#define AMD_DEBUG2(params)
#define AMD_DEBUG3(params)
#define AMD_DEBUG4(params)
#endif

200
src/maths/KLU/amd_order.c Normal file
View File

@ -0,0 +1,200 @@
/* ========================================================================= */
/* === AMD_order =========================================================== */
/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/* AMD, Copyright (c) Timothy A. Davis, */
/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */
/* web: http://www.cise.ufl.edu/research/sparse/amd */
/* ------------------------------------------------------------------------- */
/* User-callable AMD minimum degree ordering routine. See amd.h for
* documentation.
*/
#include "amd_internal.h"
/* ========================================================================= */
/* === AMD_order =========================================================== */
/* ========================================================================= */
GLOBAL Int AMD_order
(
Int n,
const Int Ap [ ],
const Int Ai [ ],
Int P [ ],
double Control [ ],
double Info [ ]
)
{
Int *Len, *S, nz, i, *Pinv, info, status, *Rp, *Ri, *Cp, *Ci, ok ;
size_t nzaat, slen ;
double mem = 0 ;
#ifndef NDEBUG
AMD_debug_init ("amd") ;
#endif
/* clear the Info array, if it exists */
info = Info != (double *) NULL ;
if (info)
{
for (i = 0 ; i < AMD_INFO ; i++)
{
Info [i] = EMPTY ;
}
Info [AMD_N] = n ;
Info [AMD_STATUS] = AMD_OK ;
}
/* make sure inputs exist and n is >= 0 */
if (Ai == (Int *) NULL || Ap == (Int *) NULL || P == (Int *) NULL || n < 0)
{
if (info) Info [AMD_STATUS] = AMD_INVALID ;
return (AMD_INVALID) ; /* arguments are invalid */
}
if (n == 0)
{
return (AMD_OK) ; /* n is 0 so there's nothing to do */
}
nz = Ap [n] ;
if (info)
{
Info [AMD_NZ] = nz ;
}
if (nz < 0)
{
if (info) Info [AMD_STATUS] = AMD_INVALID ;
return (AMD_INVALID) ;
}
/* check if n or nz will cause size_t overflow */
if (((size_t) n) >= SIZE_T_MAX / sizeof (Int)
|| ((size_t) nz) >= SIZE_T_MAX / sizeof (Int))
{
if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ;
return (AMD_OUT_OF_MEMORY) ; /* problem too large */
}
/* check the input matrix: AMD_OK, AMD_INVALID, or AMD_OK_BUT_JUMBLED */
status = AMD_valid (n, n, Ap, Ai) ;
if (status == AMD_INVALID)
{
if (info) Info [AMD_STATUS] = AMD_INVALID ;
return (AMD_INVALID) ; /* matrix is invalid */
}
/* allocate two size-n integer workspaces */
Len = amd_malloc (n * sizeof (Int)) ;
Pinv = amd_malloc (n * sizeof (Int)) ;
mem += n ;
mem += n ;
if (!Len || !Pinv)
{
/* :: out of memory :: */
amd_free (Len) ;
amd_free (Pinv) ;
if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ;
return (AMD_OUT_OF_MEMORY) ;
}
if (status == AMD_OK_BUT_JUMBLED)
{
/* sort the input matrix and remove duplicate entries */
AMD_DEBUG1 (("Matrix is jumbled\n")) ;
Rp = amd_malloc ((n+1) * sizeof (Int)) ;
Ri = amd_malloc (MAX (nz,1) * sizeof (Int)) ;
mem += (n+1) ;
mem += MAX (nz,1) ;
if (!Rp || !Ri)
{
/* :: out of memory :: */
amd_free (Rp) ;
amd_free (Ri) ;
amd_free (Len) ;
amd_free (Pinv) ;
if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ;
return (AMD_OUT_OF_MEMORY) ;
}
/* use Len and Pinv as workspace to create R = A' */
AMD_preprocess (n, Ap, Ai, Rp, Ri, Len, Pinv) ;
Cp = Rp ;
Ci = Ri ;
}
else
{
/* order the input matrix as-is. No need to compute R = A' first */
Rp = NULL ;
Ri = NULL ;
Cp = (Int *) Ap ;
Ci = (Int *) Ai ;
}
/* --------------------------------------------------------------------- */
/* determine the symmetry and count off-diagonal nonzeros in A+A' */
/* --------------------------------------------------------------------- */
nzaat = AMD_aat (n, Cp, Ci, Len, P, Info) ;
AMD_DEBUG1 (("nzaat: %g\n", (double) nzaat)) ;
ASSERT ((MAX (nz-n, 0) <= nzaat) && (nzaat <= 2 * (size_t) nz)) ;
/* --------------------------------------------------------------------- */
/* allocate workspace for matrix, elbow room, and 6 size-n vectors */
/* --------------------------------------------------------------------- */
S = NULL ;
slen = nzaat ; /* space for matrix */
ok = ((slen + nzaat/5) >= slen) ; /* check for size_t overflow */
slen += nzaat/5 ; /* add elbow room */
for (i = 0 ; ok && i < 7 ; i++)
{
ok = ((slen + n) > slen) ; /* check for size_t overflow */
slen += n ; /* size-n elbow room, 6 size-n work */
}
mem += slen ;
ok = ok && (slen < SIZE_T_MAX / sizeof (Int)) ; /* check for overflow */
ok = ok && (slen < Int_MAX) ; /* S[i] for Int i must be OK */
if (ok)
{
S = amd_malloc (slen * sizeof (Int)) ;
}
AMD_DEBUG1 (("slen %g\n", (double) slen)) ;
if (!S)
{
/* :: out of memory :: (or problem too large) */
amd_free (Rp) ;
amd_free (Ri) ;
amd_free (Len) ;
amd_free (Pinv) ;
if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ;
return (AMD_OUT_OF_MEMORY) ;
}
if (info)
{
/* memory usage, in bytes. */
Info [AMD_MEMORY] = mem * sizeof (Int) ;
}
/* --------------------------------------------------------------------- */
/* order the matrix */
/* --------------------------------------------------------------------- */
AMD_1 (n, Cp, Ci, P, Pinv, Len, slen, S, Control, Info) ;
/* --------------------------------------------------------------------- */
/* free the workspace */
/* --------------------------------------------------------------------- */
amd_free (Rp) ;
amd_free (Ri) ;
amd_free (Len) ;
amd_free (Pinv) ;
amd_free (S) ;
if (info) Info [AMD_STATUS] = status ;
return (status) ; /* successful ordering */
}

View File

@ -0,0 +1,121 @@
/* ========================================================================= */
/* === AMD_post_tree ======================================================= */
/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/* AMD, Copyright (c) Timothy A. Davis, */
/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */
/* web: http://www.cise.ufl.edu/research/sparse/amd */
/* ------------------------------------------------------------------------- */
/* Post-ordering of a supernodal elimination tree. */
#include "amd_internal.h"
GLOBAL Int AMD_post_tree
(
Int root, /* root of the tree */
Int k, /* start numbering at k */
Int Child [ ], /* input argument of size nn, undefined on
* output. Child [i] is the head of a link
* list of all nodes that are children of node
* i in the tree. */
const Int Sibling [ ], /* input argument of size nn, not modified.
* If f is a node in the link list of the
* children of node i, then Sibling [f] is the
* next child of node i.
*/
Int Order [ ], /* output order, of size nn. Order [i] = k
* if node i is the kth node of the reordered
* tree. */
Int Stack [ ] /* workspace of size nn */
#ifndef NDEBUG
, Int nn /* nodes are in the range 0..nn-1. */
#endif
)
{
Int f, head, h, i ;
#if 0
/* --------------------------------------------------------------------- */
/* recursive version (Stack [ ] is not used): */
/* --------------------------------------------------------------------- */
/* this is simple, but can caouse stack overflow if nn is large */
i = root ;
for (f = Child [i] ; f != EMPTY ; f = Sibling [f])
{
k = AMD_post_tree (f, k, Child, Sibling, Order, Stack, nn) ;
}
Order [i] = k++ ;
return (k) ;
#endif
/* --------------------------------------------------------------------- */
/* non-recursive version, using an explicit stack */
/* --------------------------------------------------------------------- */
/* push root on the stack */
head = 0 ;
Stack [0] = root ;
while (head >= 0)
{
/* get head of stack */
ASSERT (head < nn) ;
i = Stack [head] ;
AMD_DEBUG1 (("head of stack "ID" \n", i)) ;
ASSERT (i >= 0 && i < nn) ;
if (Child [i] != EMPTY)
{
/* the children of i are not yet ordered */
/* push each child onto the stack in reverse order */
/* so that small ones at the head of the list get popped first */
/* and the biggest one at the end of the list gets popped last */
for (f = Child [i] ; f != EMPTY ; f = Sibling [f])
{
head++ ;
ASSERT (head < nn) ;
ASSERT (f >= 0 && f < nn) ;
}
h = head ;
ASSERT (head < nn) ;
for (f = Child [i] ; f != EMPTY ; f = Sibling [f])
{
ASSERT (h > 0) ;
Stack [h--] = f ;
AMD_DEBUG1 (("push "ID" on stack\n", f)) ;
ASSERT (f >= 0 && f < nn) ;
}
ASSERT (Stack [h] == i) ;
/* delete child list so that i gets ordered next time we see it */
Child [i] = EMPTY ;
}
else
{
/* the children of i (if there were any) are already ordered */
/* remove i from the stack and order it. Front i is kth front */
head-- ;
AMD_DEBUG1 (("pop "ID" order "ID"\n", i, k)) ;
Order [i] = k++ ;
ASSERT (k <= nn) ;
}
#ifndef NDEBUG
AMD_DEBUG1 (("\nStack:")) ;
for (h = head ; h >= 0 ; h--)
{
Int j = Stack [h] ;
AMD_DEBUG1 ((" "ID, j)) ;
ASSERT (j >= 0 && j < nn) ;
}
AMD_DEBUG1 (("\n\n")) ;
ASSERT (head < nn) ;
#endif
}
return (k) ;
}

View File

@ -0,0 +1,207 @@
/* ========================================================================= */
/* === AMD_postorder ======================================================= */
/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/* AMD, Copyright (c) Timothy A. Davis, */
/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */
/* web: http://www.cise.ufl.edu/research/sparse/amd */
/* ------------------------------------------------------------------------- */
/* Perform a postordering (via depth-first search) of an assembly tree. */
#include "amd_internal.h"
GLOBAL void AMD_postorder
(
/* inputs, not modified on output: */
Int nn, /* nodes are in the range 0..nn-1 */
Int Parent [ ], /* Parent [j] is the parent of j, or EMPTY if root */
Int Nv [ ], /* Nv [j] > 0 number of pivots represented by node j,
* or zero if j is not a node. */
Int Fsize [ ], /* Fsize [j]: size of node j */
/* output, not defined on input: */
Int Order [ ], /* output post-order */
/* workspaces of size nn: */
Int Child [ ],
Int Sibling [ ],
Int Stack [ ]
)
{
Int i, j, k, parent, frsize, f, fprev, maxfrsize, bigfprev, bigf, fnext ;
for (j = 0 ; j < nn ; j++)
{
Child [j] = EMPTY ;
Sibling [j] = EMPTY ;
}
/* --------------------------------------------------------------------- */
/* place the children in link lists - bigger elements tend to be last */
/* --------------------------------------------------------------------- */
for (j = nn-1 ; j >= 0 ; j--)
{
if (Nv [j] > 0)
{
/* this is an element */
parent = Parent [j] ;
if (parent != EMPTY)
{
/* place the element in link list of the children its parent */
/* bigger elements will tend to be at the end of the list */
Sibling [j] = Child [parent] ;
Child [parent] = j ;
}
}
}
#ifndef NDEBUG
{
Int nels, ff, nchild ;
AMD_DEBUG1 (("\n\n================================ AMD_postorder:\n"));
nels = 0 ;
for (j = 0 ; j < nn ; j++)
{
if (Nv [j] > 0)
{
AMD_DEBUG1 (( ""ID" : nels "ID" npiv "ID" size "ID
" parent "ID" maxfr "ID"\n", j, nels,
Nv [j], Fsize [j], Parent [j], Fsize [j])) ;
/* this is an element */
/* dump the link list of children */
nchild = 0 ;
AMD_DEBUG1 ((" Children: ")) ;
for (ff = Child [j] ; ff != EMPTY ; ff = Sibling [ff])
{
AMD_DEBUG1 ((ID" ", ff)) ;
ASSERT (Parent [ff] == j) ;
nchild++ ;
ASSERT (nchild < nn) ;
}
AMD_DEBUG1 (("\n")) ;
parent = Parent [j] ;
if (parent != EMPTY)
{
ASSERT (Nv [parent] > 0) ;
}
nels++ ;
}
}
}
AMD_DEBUG1 (("\n\nGo through the children of each node, and put\n"
"the biggest child last in each list:\n")) ;
#endif
/* --------------------------------------------------------------------- */
/* place the largest child last in the list of children for each node */
/* --------------------------------------------------------------------- */
for (i = 0 ; i < nn ; i++)
{
if (Nv [i] > 0 && Child [i] != EMPTY)
{
#ifndef NDEBUG
Int nchild ;
AMD_DEBUG1 (("Before partial sort, element "ID"\n", i)) ;
nchild = 0 ;
for (f = Child [i] ; f != EMPTY ; f = Sibling [f])
{
ASSERT (f >= 0 && f < nn) ;
AMD_DEBUG1 ((" f: "ID" size: "ID"\n", f, Fsize [f])) ;
nchild++ ;
ASSERT (nchild <= nn) ;
}
#endif
/* find the biggest element in the child list */
fprev = EMPTY ;
maxfrsize = EMPTY ;
bigfprev = EMPTY ;
bigf = EMPTY ;
for (f = Child [i] ; f != EMPTY ; f = Sibling [f])
{
ASSERT (f >= 0 && f < nn) ;
frsize = Fsize [f] ;
if (frsize >= maxfrsize)
{
/* this is the biggest seen so far */
maxfrsize = frsize ;
bigfprev = fprev ;
bigf = f ;
}
fprev = f ;
}
ASSERT (bigf != EMPTY) ;
fnext = Sibling [bigf] ;
AMD_DEBUG1 (("bigf "ID" maxfrsize "ID" bigfprev "ID" fnext "ID
" fprev " ID"\n", bigf, maxfrsize, bigfprev, fnext, fprev)) ;
if (fnext != EMPTY)
{
/* if fnext is EMPTY then bigf is already at the end of list */
if (bigfprev == EMPTY)
{
/* delete bigf from the element of the list */
Child [i] = fnext ;
}
else
{
/* delete bigf from the middle of the list */
Sibling [bigfprev] = fnext ;
}
/* put bigf at the end of the list */
Sibling [bigf] = EMPTY ;
ASSERT (Child [i] != EMPTY) ;
ASSERT (fprev != bigf) ;
ASSERT (fprev != EMPTY) ;
Sibling [fprev] = bigf ;
}
#ifndef NDEBUG
AMD_DEBUG1 (("After partial sort, element "ID"\n", i)) ;
for (f = Child [i] ; f != EMPTY ; f = Sibling [f])
{
ASSERT (f >= 0 && f < nn) ;
AMD_DEBUG1 ((" "ID" "ID"\n", f, Fsize [f])) ;
ASSERT (Nv [f] > 0) ;
nchild-- ;
}
ASSERT (nchild == 0) ;
#endif
}
}
/* --------------------------------------------------------------------- */
/* postorder the assembly tree */
/* --------------------------------------------------------------------- */
for (i = 0 ; i < nn ; i++)
{
Order [i] = EMPTY ;
}
k = 0 ;
for (i = 0 ; i < nn ; i++)
{
if (Parent [i] == EMPTY && Nv [i] > 0)
{
AMD_DEBUG1 (("Root of assembly tree "ID"\n", i)) ;
k = AMD_post_tree (i, k, Child, Sibling, Order, Stack
#ifndef NDEBUG
, nn
#endif
) ;
}
}
}

View File

@ -0,0 +1,119 @@
/* ========================================================================= */
/* === AMD_preprocess ====================================================== */
/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/* AMD, Copyright (c) Timothy A. Davis, */
/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */
/* web: http://www.cise.ufl.edu/research/sparse/amd */
/* ------------------------------------------------------------------------- */
/* Sorts, removes duplicate entries, and transposes from the nonzero pattern of
* a column-form matrix A, to obtain the matrix R. The input matrix can have
* duplicate entries and/or unsorted columns (AMD_valid (n,Ap,Ai) must not be
* AMD_INVALID).
*
* This input condition is NOT checked. This routine is not user-callable.
*/
#include "amd_internal.h"
/* ========================================================================= */
/* === AMD_preprocess ====================================================== */
/* ========================================================================= */
/* AMD_preprocess does not check its input for errors or allocate workspace.
* On input, the condition (AMD_valid (n,n,Ap,Ai) != AMD_INVALID) must hold.
*/
GLOBAL void AMD_preprocess
(
Int n, /* input matrix: A is n-by-n */
const Int Ap [ ], /* size n+1 */
const Int Ai [ ], /* size nz = Ap [n] */
/* output matrix R: */
Int Rp [ ], /* size n+1 */
Int Ri [ ], /* size nz (or less, if duplicates present) */
Int W [ ], /* workspace of size n */
Int Flag [ ] /* workspace of size n */
)
{
/* --------------------------------------------------------------------- */
/* local variables */
/* --------------------------------------------------------------------- */
Int i, j, p, p2 ;
ASSERT (AMD_valid (n, n, Ap, Ai) != AMD_INVALID) ;
/* --------------------------------------------------------------------- */
/* count the entries in each row of A (excluding duplicates) */
/* --------------------------------------------------------------------- */
for (i = 0 ; i < n ; i++)
{
W [i] = 0 ; /* # of nonzeros in row i (excl duplicates) */
Flag [i] = EMPTY ; /* Flag [i] = j if i appears in column j */
}
for (j = 0 ; j < n ; j++)
{
p2 = Ap [j+1] ;
for (p = Ap [j] ; p < p2 ; p++)
{
i = Ai [p] ;
if (Flag [i] != j)
{
/* row index i has not yet appeared in column j */
W [i]++ ; /* one more entry in row i */
Flag [i] = j ; /* flag row index i as appearing in col j*/
}
}
}
/* --------------------------------------------------------------------- */
/* compute the row pointers for R */
/* --------------------------------------------------------------------- */
Rp [0] = 0 ;
for (i = 0 ; i < n ; i++)
{
Rp [i+1] = Rp [i] + W [i] ;
}
for (i = 0 ; i < n ; i++)
{
W [i] = Rp [i] ;
Flag [i] = EMPTY ;
}
/* --------------------------------------------------------------------- */
/* construct the row form matrix R */
/* --------------------------------------------------------------------- */
/* R = row form of pattern of A */
for (j = 0 ; j < n ; j++)
{
p2 = Ap [j+1] ;
for (p = Ap [j] ; p < p2 ; p++)
{
i = Ai [p] ;
if (Flag [i] != j)
{
/* row index i has not yet appeared in column j */
Ri [W [i]++] = j ; /* put col j in row i */
Flag [i] = j ; /* flag row index i as appearing in col j*/
}
}
}
#ifndef NDEBUG
ASSERT (AMD_valid (n, n, Rp, Ri) == AMD_OK) ;
for (j = 0 ; j < n ; j++)
{
ASSERT (W [j] == Rp [j+1]) ;
}
#endif
}

93
src/maths/KLU/amd_valid.c Normal file
View File

@ -0,0 +1,93 @@
/* ========================================================================= */
/* === AMD_valid =========================================================== */
/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/* AMD, Copyright (c) Timothy A. Davis, */
/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */
/* web: http://www.cise.ufl.edu/research/sparse/amd */
/* ------------------------------------------------------------------------- */
/* Check if a column-form matrix is valid or not. The matrix A is
* n_row-by-n_col. The row indices of entries in column j are in
* Ai [Ap [j] ... Ap [j+1]-1]. Required conditions are:
*
* n_row >= 0
* n_col >= 0
* nz = Ap [n_col] >= 0 number of entries in the matrix
* Ap [0] == 0
* Ap [j] <= Ap [j+1] for all j in the range 0 to n_col.
* Ai [0 ... nz-1] must be in the range 0 to n_row-1.
*
* If any of the above conditions hold, AMD_INVALID is returned. If the
* following condition holds, AMD_OK_BUT_JUMBLED is returned (a warning,
* not an error):
*
* row indices in Ai [Ap [j] ... Ap [j+1]-1] are not sorted in ascending
* order, and/or duplicate entries exist.
*
* Otherwise, AMD_OK is returned.
*
* In v1.2 and earlier, this function returned TRUE if the matrix was valid
* (now returns AMD_OK), or FALSE otherwise (now returns AMD_INVALID or
* AMD_OK_BUT_JUMBLED).
*/
#include "amd_internal.h"
GLOBAL Int AMD_valid
(
/* inputs, not modified on output: */
Int n_row, /* A is n_row-by-n_col */
Int n_col,
const Int Ap [ ], /* column pointers of A, of size n_col+1 */
const Int Ai [ ] /* row indices of A, of size nz = Ap [n_col] */
)
{
Int nz, j, p1, p2, ilast, i, p, result = AMD_OK ;
if (n_row < 0 || n_col < 0 || Ap == NULL || Ai == NULL)
{
return (AMD_INVALID) ;
}
nz = Ap [n_col] ;
if (Ap [0] != 0 || nz < 0)
{
/* column pointers must start at Ap [0] = 0, and Ap [n] must be >= 0 */
AMD_DEBUG0 (("column 0 pointer bad or nz < 0\n")) ;
return (AMD_INVALID) ;
}
for (j = 0 ; j < n_col ; j++)
{
p1 = Ap [j] ;
p2 = Ap [j+1] ;
AMD_DEBUG2 (("\nColumn: "ID" p1: "ID" p2: "ID"\n", j, p1, p2)) ;
if (p1 > p2)
{
/* column pointers must be ascending */
AMD_DEBUG0 (("column "ID" pointer bad\n", j)) ;
return (AMD_INVALID) ;
}
ilast = EMPTY ;
for (p = p1 ; p < p2 ; p++)
{
i = Ai [p] ;
AMD_DEBUG3 (("row: "ID"\n", i)) ;
if (i < 0 || i >= n_row)
{
/* row index out of range */
AMD_DEBUG0 (("index out of range, col "ID" row "ID"\n", j, i));
return (AMD_INVALID) ;
}
if (i <= ilast)
{
/* row index unsorted, or duplicate entry present */
AMD_DEBUG1 (("index unsorted/dupl col "ID" row "ID"\n", j, i));
result = AMD_OK_BUT_JUMBLED ;
}
ilast = i ;
}
}
return (result) ;
}

View File

@ -0,0 +1,64 @@
/* ========================================================================== */
/* === btf_internal include file ============================================ */
/* ========================================================================== */
#ifndef _BTF_INTERNAL_H
#define _BTF_INTERNAL_H
/*
* Copyright (c) 2004-2007. Tim Davis, University of Florida,
* with support from Sandia National Laboratories. All Rights Reserved.
*/
/* Not to be included in any user program. */
#ifdef DLONG
#define Int UF_long
#define Int_id UF_long_id
#define BTF(name) btf_l_ ## name
#else
#define Int int
#define Int_id "%d"
#define BTF(name) btf_ ## name
#endif
/* ========================================================================== */
/* make sure debugging and printing is turned off */
#ifndef NDEBUG
#define NDEBUG
#endif
#ifndef NPRINT
#define NPRINT
#endif
/* To enable debugging and assertions, uncomment this line:
#undef NDEBUG
*/
/* To enable diagnostic printing, uncomment this line:
#undef NPRINT
*/
/* ========================================================================== */
#include <stdio.h>
#include <assert.h>
#define ASSERT(a) assert(a)
#undef TRUE
#undef FALSE
#undef PRINTF
#undef MIN
#ifndef NPRINT
#define PRINTF(s) { printf s ; } ;
#else
#define PRINTF(s)
#endif
#define TRUE 1
#define FALSE 0
#define EMPTY (-1)
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif

View File

@ -0,0 +1,387 @@
/* ========================================================================== */
/* === BTF_MAXTRANS ========================================================= */
/* ========================================================================== */
/* Finds a column permutation that maximizes the number of entries on the
* diagonal of a sparse matrix. See btf.h for more information.
*
* This function is identical to cs_maxtrans in CSparse, with the following
* exceptions:
*
* (1) cs_maxtrans finds both jmatch and imatch, where jmatch [i] = j and
* imatch [j] = i if row i is matched to column j. This function returns
* just jmatch (the Match array). The MATLAB interface to cs_maxtrans
* (the single-output cs_dmperm) returns imatch, not jmatch to the MATLAB
* caller.
*
* (2) cs_maxtrans includes a pre-pass that counts the number of non-empty
* rows and columns (m2 and n2, respectively), and computes the matching
* using the transpose of A if m2 < n2. cs_maxtrans also returns quickly
* if the diagonal of the matrix is already zero-free. This pre-pass
* allows cs_maxtrans to be much faster than maxtrans, if the use of the
* transpose is warranted.
*
* However, for square structurally non-singular matrices with one or more
* zeros on the diagonal, the pre-pass is a waste of time, and for these
* matrices, maxtrans can be twice as fast as cs_maxtrans. Since the
* maxtrans function is intended primarily for square matrices that are
* typically structurally nonsingular, the pre-pass is not included here.
* If this maxtrans function is used on a matrix with many more columns
* than rows, consider passing the transpose to this function, or use
* cs_maxtrans instead.
*
* (3) cs_maxtrans can operate as a randomized algorithm, to help avoid
* rare cases of excessive run-time.
*
* (4) this maxtrans function includes an option that limits the total work
* performed. If this limit is reached, the maximum transveral might not
* be found.
*
* Thus, for general usage, cs_maxtrans is preferred. For square matrices that
* are typically structurally non-singular, maxtrans is preferred. A partial
* maxtrans can still be very useful when solving a sparse linear system.
*
* Copyright (c) 2004-2007. Tim Davis, University of Florida,
* with support from Sandia National Laboratories. All Rights Reserved.
*/
#include "ngspice/btf.h"
#include "btf_internal.h"
/* ========================================================================== */
/* === augment ============================================================== */
/* ========================================================================== */
/* Perform a depth-first-search starting at column k, to find an augmenting
* path. An augmenting path is a sequence of row/column pairs (i1,k), (i2,j1),
* (i3,j2), ..., (i(s+1), js), such that all of the following properties hold:
*
* * column k is not matched to any row
* * entries in the path are nonzero
* * the pairs (i1,j1), (i2,j2), (i3,j3) ..., (is,js) have been
* previously matched to each other
* * (i(s+1), js) is nonzero, and row i(s+1) is not matched to any column
*
* Once this path is found, the matching can be changed to the set of pairs
* path. An augmenting path is a sequence of row/column pairs
*
* (i1,k), (i2,j1), (i3,j2), ..., (i(s+1), js)
*
* Once a row is matched with a column it remains matched with some column, but
* not necessarily the column it was first matched with.
*
* In the worst case, this function can examine every nonzero in A. Since it
* is called n times by maxtrans, the total time of maxtrans can be as high as
* O(n*nnz(A)). To limit this work, pass a value of maxwork > 0. Then at
* most O((maxwork+1)*nnz(A)) work will be performed; the maximum matching might
* not be found, however.
*
* This routine is very similar to the dfs routine in klu_kernel.c, in the
* KLU sparse LU factorization package. It is essentially identical to the
* cs_augment routine in CSparse, and its recursive version (augment function
* in cs_maxtransr_mex.c), except that this routine allows for the search to be
* terminated early if too much work is being performed.
*
* The algorithm is based on the paper "On Algorithms for obtaining a maximum
* transversal" by Iain Duff, ACM Trans. Mathematical Software, vol 7, no. 1,
* pp. 315-330, and "Algorithm 575: Permutations for a zero-free diagonal",
* same issue, pp. 387-390. The code here is a new implementation of that
* algorithm, with different data structures and control flow. After writing
* this code, I carefully compared my algorithm with MC21A/B (ACM Algorithm 575)
* Some of the comparisons are partial because I didn't dig deeply into all of
* the details of MC21A/B, such as how the stack is maintained. The following
* arguments are essentially identical between this code and MC21A:
*
* maxtrans MC21A,B
* -------- -------
* n N identical
* k JORD identical
* Ap IP column / row pointers
* Ai ICN row / column indices
* Ap[n] LICN length of index array (# of nonzeros in A)
* Match IPERM output column / row permutation
* nmatch NUMNZ # of nonzeros on diagonal of permuted matrix
* Flag CV mark a node as visited by the depth-first-search
*
* The following are different, but analogous:
*
* Cheap ARP indicates what part of the a column / row has
* already been matched.
*
* The following arguments are very different:
*
* - LENR # of entries in each row/column (unused in maxtrans)
* Pstack OUT Pstack keeps track of where we are in the depth-
* first-search scan of column j. I think that OUT
* plays a similar role in MC21B, but I'm unsure.
* Istack PR keeps track of the rows in the path. PR is a link
* list, though, whereas Istack is a stack. Maxtrans
* does not use any link lists.
* Jstack OUT? PR? the stack for nodes in the path (unsure)
*
* The following control structures are roughly comparable:
*
* maxtrans MC21B
* -------- -----
* for (k = 0 ; k < n ; k++) DO 100 JORD=1,N
* while (head >= 0) DO 70 K=1,JORD
* for (p = Cheap [j] ; ...) DO 20 II=IN1,IN2
* for (p = head ; ...) DO 90 K=1,JORD
*/
static Int augment
(
Int k, /* which stage of the main loop we're in */
Int Ap [ ], /* column pointers, size n+1 */
Int Ai [ ], /* row indices, size nz = Ap [n] */
Int Match [ ], /* size n, Match [i] = j if col j matched to i */
Int Cheap [ ], /* rows Ai [Ap [j] .. Cheap [j]-1] alread matched */
Int Flag [ ], /* Flag [j] = k if j already visited this stage */
Int Istack [ ], /* size n. Row index stack. */
Int Jstack [ ], /* size n. Column index stack. */
Int Pstack [ ], /* size n. Keeps track of position in adjacency list */
double *work, /* work performed by the depth-first-search */
double maxwork /* maximum work allowed */
)
{
/* local variables, but "global" to all DFS levels: */
Int found ; /* true if match found. */
Int head ; /* top of stack */
/* variables that are purely local to any one DFS level: */
Int j2 ; /* the next DFS goes to node j2 */
Int pend ; /* one past the end of the adjacency list for node j */
Int pstart ;
Int quick ;
/* variables that need to be pushed then popped from the stack: */
Int i ; /* the row tentatively matched to i if DFS successful */
Int j ; /* the DFS is at the current node j */
Int p ; /* current index into the adj. list for node j */
/* the variables i, j, and p are stacked in Istack, Jstack, and Pstack */
quick = (maxwork > 0) ;
/* start a DFS to find a match for column k */
found = FALSE ;
i = EMPTY ;
head = 0 ;
Jstack [0] = k ;
ASSERT (Flag [k] != k) ;
while (head >= 0)
{
j = Jstack [head] ;
pend = Ap [j+1] ;
if (Flag [j] != k) /* a node is not yet visited */
{
/* -------------------------------------------------------------- */
/* prework for node j */
/* -------------------------------------------------------------- */
/* first time that j has been visited */
Flag [j] = k ;
/* cheap assignment: find the next unmatched row in col j. This
* loop takes at most O(nnz(A)) time for the sum total of all
* calls to augment. */
for (p = Cheap [j] ; p < pend && !found ; p++)
{
i = Ai [p] ;
found = (Match [i] == EMPTY) ;
}
Cheap [j] = p ;
/* -------------------------------------------------------------- */
/* prepare for DFS */
if (found)
{
/* end of augmenting path, column j matched with row i */
Istack [head] = i ;
break ;
}
/* set Pstack [head] to the first entry in column j to scan */
Pstack [head] = Ap [j] ;
}
/* ------------------------------------------------------------------ */
/* quick return if too much work done */
/* ------------------------------------------------------------------ */
if (quick && *work > maxwork)
{
/* too much work has been performed; abort the search */
return (EMPTY) ;
}
/* ------------------------------------------------------------------ */
/* DFS for nodes adjacent to j */
/* ------------------------------------------------------------------ */
/* If cheap assignment not made, continue the depth-first search. All
* rows in column j are already matched. Add the adjacent nodes to the
* stack by iterating through until finding another non-visited node.
*
* It is the following loop that can force maxtrans to take
* O(n*nnz(A)) time. */
pstart = Pstack [head] ;
for (p = pstart ; p < pend ; p++)
{
i = Ai [p] ;
j2 = Match [i] ;
ASSERT (j2 != EMPTY) ;
if (Flag [j2] != k)
{
/* Node j2 is not yet visited, start a depth-first search on
* node j2. Keep track of where we left off in the scan of adj
* list of node j so we can restart j where we left off. */
Pstack [head] = p + 1 ;
/* Push j2 onto the stack and immediately break so we can
* recurse on node j2. Also keep track of row i which (if this
* search for an augmenting path works) will be matched with the
* current node j. */
Istack [head] = i ;
Jstack [++head] = j2 ;
break ;
}
}
/* ------------------------------------------------------------------ */
/* determine how much work was just performed */
/* ------------------------------------------------------------------ */
*work += (p - pstart + 1) ;
/* ------------------------------------------------------------------ */
/* node j is done, but the postwork is postponed - see below */
/* ------------------------------------------------------------------ */
if (p == pend)
{
/* If all adjacent nodes of j are already visited, pop j from
* stack and continue. We failed to find a match. */
head-- ;
}
}
/* postwork for all nodes j in the stack */
/* unwind the path and make the corresponding matches */
if (found)
{
for (p = head ; p >= 0 ; p--)
{
j = Jstack [p] ;
i = Istack [p] ;
/* -------------------------------------------------------------- */
/* postwork for node j */
/* -------------------------------------------------------------- */
/* if found, match row i with column j */
Match [i] = j ;
}
}
return (found) ;
}
/* ========================================================================== */
/* === maxtrans ============================================================= */
/* ========================================================================== */
Int BTF(maxtrans) /* returns # of columns in the matching */
(
/* --- input --- */
Int nrow, /* A is nrow-by-ncol in compressed column form */
Int ncol,
Int Ap [ ], /* size ncol+1 */
Int Ai [ ], /* size nz = Ap [ncol] */
double maxwork, /* do at most maxwork*nnz(A) work; no limit if <= 0. This
* work limit excludes the O(nnz(A)) cheap-match phase. */
/* --- output --- */
double *work, /* work = -1 if maxwork > 0 and the total work performed
* reached the maximum of maxwork*nnz(A)).
* Otherwise, work = the total work performed. */
Int Match [ ], /* size nrow. Match [i] = j if column j matched to row i */
/* --- workspace --- */
Int Work [ ] /* size 5*ncol */
)
{
Int *Cheap, *Flag, *Istack, *Jstack, *Pstack ;
Int i, j, k, nmatch, work_limit_reached, result ;
/* ---------------------------------------------------------------------- */
/* get workspace and initialize */
/* ---------------------------------------------------------------------- */
Cheap = Work ; Work += ncol ;
Flag = Work ; Work += ncol ;
/* stack for non-recursive depth-first search in augment function */
Istack = Work ; Work += ncol ;
Jstack = Work ; Work += ncol ;
Pstack = Work ;
/* in column j, rows Ai [Ap [j] .. Cheap [j]-1] are known to be matched */
for (j = 0 ; j < ncol ; j++)
{
Cheap [j] = Ap [j] ;
Flag [j] = EMPTY ;
}
/* all rows and columns are currently unmatched */
for (i = 0 ; i < nrow ; i++)
{
Match [i] = EMPTY ;
}
if (maxwork > 0)
{
maxwork *= Ap [ncol] ;
}
*work = 0 ;
/* ---------------------------------------------------------------------- */
/* find a matching row for each column k */
/* ---------------------------------------------------------------------- */
nmatch = 0 ;
work_limit_reached = FALSE ;
for (k = 0 ; k < ncol ; k++)
{
/* find an augmenting path to match some row i to column k */
result = augment (k, Ap, Ai, Match, Cheap, Flag, Istack, Jstack, Pstack,
work, maxwork) ;
if (result == TRUE)
{
/* we found it. Match [i] = k for some row i has been done. */
nmatch++ ;
}
else if (result == EMPTY)
{
/* augment gave up because of too much work, and no match found */
work_limit_reached = TRUE ;
}
}
/* ---------------------------------------------------------------------- */
/* return the Match, and the # of matches made */
/* ---------------------------------------------------------------------- */
/* At this point, row i is matched to j = Match [i] if j >= 0. i is an
* unmatched row if Match [i] == EMPTY. */
if (work_limit_reached)
{
/* return -1 if the work limit of maxwork*nnz(A) was reached */
*work = EMPTY ;
}
return (nmatch) ;
}

132
src/maths/KLU/btf_order.c Normal file
View File

@ -0,0 +1,132 @@
/* ========================================================================== */
/* === BTF_ORDER ============================================================ */
/* ========================================================================== */
/* Find a permutation P and Q to permute a square sparse matrix into upper block
* triangular form. A(P,Q) will contain a zero-free diagonal if A has
* structural full-rank. Otherwise, the number of nonzeros on the diagonal of
* A(P,Q) will be maximized, and will equal the structural rank of A.
*
* Q[k] will be "flipped" if a zero-free diagonal was not found. Q[k] will be
* negative, and j = BTF_UNFLIP (Q [k]) gives the corresponding permutation.
*
* R defines the block boundaries of A(P,Q). The kth block consists of rows
* and columns R[k] to R[k+1]-1.
*
* If maxwork > 0 on input, then the work performed in btf_maxtrans is limited
* to maxwork*nnz(A) (excluding the "cheap match" phase, which can take another
* nnz(A) work). On output, the work parameter gives the actual work performed,
* or -1 if the limit was reached. In the latter case, the diagonal of A(P,Q)
* might not be zero-free, and the number of nonzeros on the diagonal of A(P,Q)
* might not be equal to the structural rank.
*
* See btf.h for more details.
*
* Copyright (c) 2004-2007. Tim Davis, University of Florida,
* with support from Sandia National Laboratories. All Rights Reserved.
*/
#include "ngspice/btf.h"
#include "btf_internal.h"
/* This function only operates on square matrices (either structurally full-
* rank, or structurally rank deficient). */
Int BTF(order) /* returns number of blocks found */
(
/* input, not modified: */
Int n, /* A is n-by-n in compressed column form */
Int Ap [ ], /* size n+1 */
Int Ai [ ], /* size nz = Ap [n] */
double maxwork, /* do at most maxwork*nnz(A) work in the maximum
* transversal; no limit if <= 0 */
/* output, not defined on input */
double *work, /* work performed in maxtrans, or -1 if limit reached */
Int P [ ], /* size n, row permutation */
Int Q [ ], /* size n, column permutation */
Int R [ ], /* size n+1. block b is in rows/cols R[b] ... R[b+1]-1 */
Int *nmatch, /* # nonzeros on diagonal of P*A*Q */
/* workspace, not defined on input or output */
Int Work [ ] /* size 5n */
)
{
Int *Flag ;
Int nblocks, i, j, nbadcol ;
/* ---------------------------------------------------------------------- */
/* compute the maximum matching */
/* ---------------------------------------------------------------------- */
/* if maxwork > 0, then a maximum matching might not be found */
*nmatch = BTF(maxtrans) (n, n, Ap, Ai, maxwork, work, Q, Work) ;
/* ---------------------------------------------------------------------- */
/* complete permutation if the matrix is structurally singular */
/* ---------------------------------------------------------------------- */
/* Since the matrix is square, ensure BTF_UNFLIP(Q[0..n-1]) is a
* permutation of the columns of A so that A has as many nonzeros on the
* diagonal as possible.
*/
if (*nmatch < n)
{
/* get a size-n work array */
Flag = Work + n ;
for (j = 0 ; j < n ; j++)
{
Flag [j] = 0 ;
}
/* flag all matched columns */
for (i = 0 ; i < n ; i++)
{
j = Q [i] ;
if (j != EMPTY)
{
/* row i and column j are matched to each other */
Flag [j] = 1 ;
}
}
/* make a list of all unmatched columns, in Work [0..nbadcol-1] */
nbadcol = 0 ;
for (j = n-1 ; j >= 0 ; j--)
{
if (!Flag [j])
{
/* j is matched to nobody */
Work [nbadcol++] = j ;
}
}
ASSERT (*nmatch + nbadcol == n) ;
/* make an assignment for each unmatched row */
for (i = 0 ; i < n ; i++)
{
if (Q [i] == EMPTY && nbadcol > 0)
{
/* get an unmatched column j */
j = Work [--nbadcol] ;
/* assign j to row i and flag the entry by "flipping" it */
Q [i] = BTF_FLIP (j) ;
}
}
}
/* The permutation of a square matrix can be recovered as follows: Row i is
* matched with column j, where j = BTF_UNFLIP (Q [i]) and where j
* will always be in the valid range 0 to n-1. The entry A(i,j) is zero
* if BTF_ISFLIPPED (Q [i]) is true, and nonzero otherwise. nmatch
* is the number of entries in the Q array that are non-negative. */
/* ---------------------------------------------------------------------- */
/* find the strongly connected components */
/* ---------------------------------------------------------------------- */
nblocks = BTF(strongcomp) (n, Ap, Ai, Q, P, R, Work) ;
return (nblocks) ;
}

View File

@ -0,0 +1,593 @@
/* ========================================================================== */
/* === BTF_STRONGCOMP ======================================================= */
/* ========================================================================== */
/* Finds the strongly connected components of a graph, or equivalently, permutes
* the matrix into upper block triangular form. See btf.h for more details.
* Input matrix and Q are not checked on input.
*
* Copyright (c) 2004-2007. Tim Davis, University of Florida,
* with support from Sandia National Laboratories. All Rights Reserved.
*/
#include "ngspice/btf.h"
#include "btf_internal.h"
#define UNVISITED (-2) /* Flag [j] = UNVISITED if node j not visited yet */
#define UNASSIGNED (-1) /* Flag [j] = UNASSIGNED if node j has been visited,
* but not yet assigned to a strongly-connected
* component (aka block). Flag [j] = k (k in the
* range 0 to nblocks-1) if node j has been visited
* (and completed, with its postwork done) and
* assigned to component k. */
/* This file contains two versions of the depth-first-search, a recursive one
* and a non-recursive one. By default, the non-recursive one is used. */
#ifndef RECURSIVE
/* ========================================================================== */
/* === dfs: non-recursive version (default) ================================= */
/* ========================================================================== */
/* Perform a depth-first-search of a graph, stored in an adjacency-list form.
* The row indices of column j (equivalently, the out-adjacency list of node j)
* are stored in Ai [Ap[j] ... Ap[j+1]-1]. Self-edge (diagonal entries) are
* ignored. Ap[0] must be zero, and thus nz = Ap[n] is the number of entries
* in the matrix (or edges in the graph). The row indices in each column need
* not be in any particular order. If an input column permutation is given,
* node j (in the permuted matrix A*Q) is located in
* Ai [Ap[Q[j]] ... Ap[Q[j]+1]-1]. This Q can be the same as the Match array
* output from the maxtrans routine, for a square matrix that is structurally
* full rank.
*
* The algorithm is from the paper by Robert E. Tarjan, "Depth-first search and
* linear graph algorithms," SIAM Journal on Computing, vol. 1, no. 2,
* pp. 146-160, 1972. The time taken by strongcomp is O(nnz(A)).
*
* See also MC13A/B in the Harwell subroutine library (Iain S. Duff and John
* K. Reid, "Algorithm 529: permutations to block triangular form," ACM Trans.
* on Mathematical Software, vol. 4, no. 2, pp. 189-192, 1978, and "An
* implementation of Tarjan's algorithm for the block triangular form of a
* matrix," same journal, pp. 137-147. This code is implements the same
* algorithm as MC13A/B, except that the data structures are very different.
* Also, unlike MC13A/B, the output permutation preserves the natural ordering
* within each block.
*/
static void dfs
(
/* inputs, not modified on output: */
Int j, /* start the DFS at node j */
Int Ap [ ], /* size n+1, column pointers for the matrix A */
Int Ai [ ], /* row indices, size nz = Ap [n] */
Int Q [ ], /* input column permutation */
/* inputs, modified on output (each array is of size n): */
Int Time [ ], /* Time [j] = "time" that node j was first visited */
Int Flag [ ], /* Flag [j]: see above */
Int Low [ ], /* Low [j]: see definition below */
Int *p_nblocks, /* number of blocks (aka strongly-connected-comp.)*/
Int *p_timestamp, /* current "time" */
/* workspace, not defined on input or output: */
Int Cstack [ ], /* size n, output stack to hold nodes of components */
Int Jstack [ ], /* size n, stack for the variable j */
Int Pstack [ ] /* size n, stack for the variable p */
)
{
/* ---------------------------------------------------------------------- */
/* local variables, and initializations */
/* ---------------------------------------------------------------------- */
/* local variables, but "global" to all DFS levels: */
Int chead ; /* top of Cstack */
Int jhead ; /* top of Jstack and Pstack */
/* variables that are purely local to any one DFS level: */
Int i ; /* edge (j,i) considered; i can be next node to traverse */
Int parent ; /* parent of node j in the DFS tree */
Int pend ; /* one past the end of the adjacency list for node j */
Int jj ; /* column j of A*Q is column jj of the input matrix A */
/* variables that need to be pushed then popped from the stack: */
Int p ; /* current index into the adj. list for node j */
/* the variables j and p are stacked in Jstack and Pstack */
/* local copies of variables in the calling routine */
Int nblocks = *p_nblocks ;
Int timestamp = *p_timestamp ;
/* ---------------------------------------------------------------------- */
/* start a DFS at node j (same as the recursive call dfs (EMPTY, j)) */
/* ---------------------------------------------------------------------- */
chead = 0 ; /* component stack is empty */
jhead = 0 ; /* Jstack and Pstack are empty */
Jstack [0] = j ; /* put the first node j on the Jstack */
ASSERT (Flag [j] == UNVISITED) ;
while (jhead >= 0)
{
j = Jstack [jhead] ; /* grab the node j from the top of Jstack */
/* determine which column jj of the A is column j of A*Q */
jj = (Q == (Int *) NULL) ? (j) : (BTF_UNFLIP (Q [j])) ;
pend = Ap [jj+1] ; /* j's row index list ends at Ai [pend-1] */
if (Flag [j] == UNVISITED)
{
/* -------------------------------------------------------------- */
/* prework at node j */
/* -------------------------------------------------------------- */
/* node j is being visited for the first time */
Cstack [++chead] = j ; /* push j onto the stack */
timestamp++ ; /* get a timestamp */
Time [j] = timestamp ; /* give the timestamp to node j */
Low [j] = timestamp ;
Flag [j] = UNASSIGNED ; /* flag node j as visited */
/* -------------------------------------------------------------- */
/* set Pstack [jhead] to the first entry in column j to scan */
/* -------------------------------------------------------------- */
Pstack [jhead] = Ap [jj] ;
}
/* ------------------------------------------------------------------ */
/* DFS rooted at node j (start it, or continue where left off) */
/* ------------------------------------------------------------------ */
for (p = Pstack [jhead] ; p < pend ; p++)
{
i = Ai [p] ; /* examine the edge from node j to node i */
if (Flag [i] == UNVISITED)
{
/* Node i has not been visited - start a DFS at node i.
* Keep track of where we left off in the scan of adjacency list
* of node j so we can restart j where we left off. */
Pstack [jhead] = p + 1 ;
/* Push i onto the stack and immediately break
* so we can recurse on node i. */
Jstack [++jhead] = i ;
ASSERT (Time [i] == EMPTY) ;
ASSERT (Low [i] == EMPTY) ;
/* break here to do what the recursive call dfs (j,i) does */
break ;
}
else if (Flag [i] == UNASSIGNED)
{
/* Node i has been visited, but still unassigned to a block
* this is a back or cross edge if Time [i] < Time [j].
* Note that i might equal j, in which case this code does
* nothing. */
ASSERT (Time [i] > 0) ;
ASSERT (Low [i] > 0) ;
Low [j] = MIN (Low [j], Time [i]) ;
}
}
if (p == pend)
{
/* If all adjacent nodes of j are already visited, pop j from
* Jstack and do the post work for node j. This also pops p
* from the Pstack. */
jhead-- ;
/* -------------------------------------------------------------- */
/* postwork at node j */
/* -------------------------------------------------------------- */
/* determine if node j is the head of a component */
if (Low [j] == Time [j])
{
/* pop all nodes in this SCC from Cstack */
while (TRUE)
{
ASSERT (chead >= 0) ; /* stack not empty (j in it) */
i = Cstack [chead--] ; /* pop a node from the Cstack */
ASSERT (i >= 0) ;
ASSERT (Flag [i] == UNASSIGNED) ;
Flag [i] = nblocks ; /* assign i to current block */
if (i == j) break ; /* current block ends at j */
}
nblocks++ ; /* one more block has been found */
}
/* update Low [parent], if the parent exists */
if (jhead >= 0)
{
parent = Jstack [jhead] ;
Low [parent] = MIN (Low [parent], Low [j]) ;
}
}
}
/* ---------------------------------------------------------------------- */
/* cleanup: update timestamp and nblocks */
/* ---------------------------------------------------------------------- */
*p_timestamp = timestamp ;
*p_nblocks = nblocks ;
}
#else
/* ========================================================================== */
/* === dfs: recursive version (only for illustration) ======================= */
/* ========================================================================== */
/* The following is a recursive version of dfs, which computes identical results
* as the non-recursive dfs. It is included here because it is easier to read.
* Compare the comments in the code below with the identical comments in the
* non-recursive code above, and that will help you see the correlation between
* the two routines.
*
* This routine can cause stack overflow, and is thus not recommended for heavy
* usage, particularly for large matrices. To help in delaying stack overflow,
* global variables are used, reducing the amount of information each call to
* dfs places on the call/return stack (the integers i, j, p, parent, and the
* return address). Note that this means the recursive code is not thread-safe.
* To try this version, compile the code with -DRECURSIVE or include the
* following line at the top of this file:
#define RECURSIVE
*/
static Int /* for recursive illustration only, not for production use */
chead, timestamp, nblocks, n, *Ap, *Ai, *Flag, *Cstack, *Time, *Low,
*P, *R, *Q ;
static void dfs
(
Int parent, /* came from parent node */
Int j /* at node j in the DFS */
)
{
Int p ; /* current index into the adj. list for node j */
Int i ; /* edge (j,i) considered; i can be next node to traverse */
Int jj ; /* column j of A*Q is column jj of the input matrix A */
/* ---------------------------------------------------------------------- */
/* prework at node j */
/* ---------------------------------------------------------------------- */
/* node j is being visited for the first time */
Cstack [++chead] = j ; /* push j onto the stack */
timestamp++ ; /* get a timestamp */
Time [j] = timestamp ; /* give the timestamp to node j */
Low [j] = timestamp ;
Flag [j] = UNASSIGNED ; /* flag node j as visited */
/* ---------------------------------------------------------------------- */
/* DFS rooted at node j */
/* ---------------------------------------------------------------------- */
/* determine which column jj of the A is column j of A*Q */
jj = (Q == (Int *) NULL) ? (j) : (BTF_UNFLIP (Q [j])) ;
for (p = Ap [jj] ; p < Ap [jj+1] ; p++)
{
i = Ai [p] ; /* examine the edge from node j to node i */
if (Flag [i] == UNVISITED)
{
/* Node i has not been visited - start a DFS at node i. */
dfs (j, i) ;
}
else if (Flag [i] == UNASSIGNED)
{
/* Node i has been visited, but still unassigned to a block
* this is a back or cross edge if Time [i] < Time [j].
* Note that i might equal j, in which case this code does
* nothing. */
Low [j] = MIN (Low [j], Time [i]) ;
}
}
/* ---------------------------------------------------------------------- */
/* postwork at node j */
/* ---------------------------------------------------------------------- */
/* determine if node j is the head of a component */
if (Low [j] == Time [j])
{
/* pop all nodes in this strongly connected component from Cstack */
while (TRUE)
{
i = Cstack [chead--] ; /* pop a node from the Cstack */
Flag [i] = nblocks ; /* assign node i to current block */
if (i == j) break ; /* current block ends at node j */
}
nblocks++ ; /* one more block has been found */
}
/* update Low [parent] */
if (parent != EMPTY)
{
/* Note that this could be done with Low[j] = MIN(Low[j],Low[i]) just
* after the dfs (j,i) statement above, and then parent would not have
* to be an input argument. Putting it here places all the postwork
* for node j in one place, thus making the non-recursive DFS easier. */
Low [parent] = MIN (Low [parent], Low [j]) ;
}
}
#endif
/* ========================================================================== */
/* === btf_strongcomp ======================================================= */
/* ========================================================================== */
#ifndef RECURSIVE
Int BTF(strongcomp) /* return # of strongly connected components */
(
/* input, not modified: */
Int n, /* A is n-by-n in compressed column form */
Int Ap [ ], /* size n+1 */
Int Ai [ ], /* size nz = Ap [n] */
/* optional input, modified (if present) on output: */
Int Q [ ], /* size n, input column permutation. The permutation Q can
* include a flag which indicates an unmatched row.
* jold = BTF_UNFLIP (Q [jnew]) is the permutation;
* this function ingnores these flags. On output, it is
* modified according to the permutation P. */
/* output, not defined on input: */
Int P [ ], /* size n. P [k] = j if row and column j are kth row/col
* in permuted matrix. */
Int R [ ], /* size n+1. kth block is in rows/cols R[k] ... R[k+1]-1
* of the permuted matrix. */
/* workspace, not defined on input or output: */
Int Work [ ] /* size 4n */
)
#else
Int BTF(strongcomp) /* recursive version - same as above except for Work size */
(
Int n_in,
Int Ap_in [ ],
Int Ai_in [ ],
Int Q_in [ ],
Int P_in [ ],
Int R_in [ ],
Int Work [ ] /* size 2n */
)
#endif
{
Int j, k, b ;
#ifndef RECURSIVE
Int timestamp, nblocks, *Flag, *Cstack, *Time, *Low, *Jstack, *Pstack ;
#else
n = n_in ;
Ap = Ap_in ;
Ai = Ai_in ;
Q = Q_in ;
P = P_in ;
R = R_in ;
chead = EMPTY ;
#endif
/* ---------------------------------------------------------------------- */
/* get and initialize workspace */
/* ---------------------------------------------------------------------- */
/* timestamp is incremented each time a new node is visited.
*
* Time [j] is the timestamp given to node j.
*
* Low [j] is the lowest timestamp of any node reachable from j via either
* a path to any descendent of j in the DFS tree, or via a single edge to
* an either an ancestor (a back edge) or another node that's neither an
* ancestor nor a descendant (a cross edge). If Low [j] is equal to
* the timestamp of node j (Time [j]), then node j is the "head" of a
* strongly connected component (SCC). That is, it is the first node
* visited in its strongly connected component, and the DFS subtree rooted
* at node j spans all the nodes of the strongly connected component.
*
* The term "block" and "component" are used interchangebly in this code;
* "block" being a matrix term and "component" being a graph term for the
* same thing.
*
* When a node is visited, it is placed on the Cstack (for "component"
* stack). When node j is found to be an SCC head, all the nodes from the
* top of the stack to node j itself form the nodes in the SCC. This Cstack
* is used for both the recursive and non-recursive versions.
*/
Time = Work ; Work += n ;
Flag = Work ; Work += n ;
Low = P ; /* use output array P as workspace for Low */
Cstack = R ; /* use output array R as workspace for Cstack */
#ifndef RECURSIVE
/* stack for non-recursive dfs */
Jstack = Work ; Work += n ; /* stack for j */
Pstack = Work ; /* stack for p */
#endif
for (j = 0 ; j < n ; j++)
{
Flag [j] = UNVISITED ;
Low [j] = EMPTY ;
Time [j] = EMPTY ;
#ifndef NDEBUG
Cstack [j] = EMPTY ;
#ifndef RECURSIVE
Jstack [j] = EMPTY ;
Pstack [j] = EMPTY ;
#endif
#endif
}
timestamp = 0 ; /* each node given a timestamp when it is visited */
nblocks = 0 ; /* number of blocks found so far */
/* ---------------------------------------------------------------------- */
/* find the connected components via a depth-first-search */
/* ---------------------------------------------------------------------- */
for (j = 0 ; j < n ; j++)
{
/* node j is unvisited or assigned to a block. Cstack is empty. */
ASSERT (Flag [j] == UNVISITED || (Flag [j] >= 0 && Flag [j] < nblocks));
if (Flag [j] == UNVISITED)
{
#ifndef RECURSIVE
/* non-recursive dfs (default) */
dfs (j, Ap, Ai, Q, Time, Flag, Low, &nblocks, &timestamp,
Cstack, Jstack, Pstack) ;
#else
/* recursive dfs (for illustration only) */
ASSERT (chead == EMPTY) ;
dfs (EMPTY, j) ;
ASSERT (chead == EMPTY) ;
#endif
}
}
ASSERT (timestamp == n) ;
/* ---------------------------------------------------------------------- */
/* construct the block boundary array, R */
/* ---------------------------------------------------------------------- */
for (b = 0 ; b < nblocks ; b++)
{
R [b] = 0 ;
}
for (j = 0 ; j < n ; j++)
{
/* node j has been assigned to block b = Flag [j] */
ASSERT (Time [j] > 0 && Time [j] <= n) ;
ASSERT (Low [j] > 0 && Low [j] <= n) ;
ASSERT (Flag [j] >= 0 && Flag [j] < nblocks) ;
R [Flag [j]]++ ;
}
/* R [b] is now the number of nodes in block b. Compute cumulative sum
* of R, using Time [0 ... nblocks-1] as workspace. */
Time [0] = 0 ;
for (b = 1 ; b < nblocks ; b++)
{
Time [b] = Time [b-1] + R [b-1] ;
}
for (b = 0 ; b < nblocks ; b++)
{
R [b] = Time [b] ;
}
R [nblocks] = n ;
/* ---------------------------------------------------------------------- */
/* construct the permutation, preserving the natural order */
/* ---------------------------------------------------------------------- */
#ifndef NDEBUG
for (k = 0 ; k < n ; k++)
{
P [k] = EMPTY ;
}
#endif
for (j = 0 ; j < n ; j++)
{
/* place column j in the permutation */
P [Time [Flag [j]]++] = j ;
}
#ifndef NDEBUG
for (k = 0 ; k < n ; k++)
{
ASSERT (P [k] != EMPTY) ;
}
#endif
/* Now block b consists of the nodes k1 to k2-1 in the permuted matrix,
* where k1 = R [b] and k2 = R [b+1]. Row and column j of the original
* matrix becomes row and column P [k] of the permuted matrix. The set of
* of rows/columns (nodes) in block b is given by P [k1 ... k2-1], and this
* set is sorted in ascending order. Thus, if the matrix consists of just
* one block, P is the identity permutation. */
/* ---------------------------------------------------------------------- */
/* if Q is present on input, set Q = Q*P' */
/* ---------------------------------------------------------------------- */
if (Q != (Int *) NULL)
{
/* We found a symmetric permutation P for the matrix A*Q. The overall
* permutation is thus P*(A*Q)*P'. Set Q=Q*P' so that the final
* permutation is P*A*Q. Use Time as workspace. Note that this
* preserves the negative values of Q if the matrix is structurally
* singular. */
for (k = 0 ; k < n ; k++)
{
Time [k] = Q [P [k]] ;
}
for (k = 0 ; k < n ; k++)
{
Q [k] = Time [k] ;
}
}
/* ---------------------------------------------------------------------- */
/* how to traverse the permuted matrix */
/* ---------------------------------------------------------------------- */
/* If Q is not present, the following code can be used to traverse the
* permuted matrix P*A*P'
*
* // compute the inverse of P
* for (knew = 0 ; knew < n ; knew++)
* {
* // row and column kold in the old matrix is row/column knew
* // in the permuted matrix P*A*P'
* kold = P [knew] ;
* Pinv [kold] = knew ;
* }
* for (b = 0 ; b < nblocks ; b++)
* {
* // traverse block b of the permuted matrix P*A*P'
* k1 = R [b] ;
* k2 = R [b+1] ;
* nk = k2 - k1 ;
* for (jnew = k1 ; jnew < k2 ; jnew++)
* {
* jold = P [jnew] ;
* for (p = Ap [jold] ; p < Ap [jold+1] ; p++)
* {
* iold = Ai [p] ;
* inew = Pinv [iold] ;
* // Entry in the old matrix is A (iold, jold), and its
* // position in the new matrix P*A*P' is (inew, jnew).
* // Let B be the bth diagonal block of the permuted
* // matrix. If inew >= k1, then this entry is in row/
* // column (inew-k1, jnew-k1) of the nk-by-nk matrix B.
* // Otherwise, the entry is in the upper block triangular
* // part, not in any diagonal block.
* }
* }
* }
*
* If Q is present replace the above statement
* jold = P [jnew] ;
* with
* jold = Q [jnew] ;
* or
* jold = BTF_UNFLIP (Q [jnew]) ;
*
* then entry A (iold,jold) in the old (unpermuted) matrix is at (inew,jnew)
* in the permuted matrix P*A*Q. Everything else remains the same as the
* above (simply replace P*A*P' with P*A*Q in the above comments).
*/
/* ---------------------------------------------------------------------- */
/* return # of blocks / # of strongly connected components */
/* ---------------------------------------------------------------------- */
return (nblocks) ;
}

3611
src/maths/KLU/colamd.c Normal file

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More