Merge branch 'pre-master-45' into bt_dev

This commit is contained in:
Brian Taylor 2025-02-16 12:02:33 -08:00
commit c3f798874d
57 changed files with 91587 additions and 5309 deletions

View File

@ -11,13 +11,6 @@
PROJECT=ngspice
# ADMS variables
ADMSDIR=src/spicelib/devices/adms
XMLPATH=src/spicelib/devices/adms/admst
ADMSXML=${ADMSXML:-admsXml}
ADMS=0
# Exit variable
DIE=0
@ -35,7 +28,6 @@ help()
echo
echo "$PROJECT autogen.sh help"
echo
echo "--adms -a: enables adms feature"
echo "--help -h: print this file"
echo "--version -v: print version"
echo
@ -51,9 +43,6 @@ version()
error_and_exit()
{
echo "Error: $1"
if [ "$ADMS" -eq 1 ]; then
rm -f temp-adms.ac
fi
exit 1
}
@ -95,53 +84,9 @@ check_autoconf()
}
check_adms()
{
($ADMSXML --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "You must have admsXml installed to compile adms models."
echo "See https://sourceforge.net/projects/mot-adms/"
echo "(version 2.3.6, tested for ngspice under MINGW on MS Windows)"
DIE=1
}
}
# check if verilog-a files exist in every adms device directory
check_adms_va()
{
echo
# get the devices directories from configure.ac
admsdirs=`awk '$1 ~ /#VLAMKF/ { print $2 }' < configure.ac`
admsdirs=`echo $admsdirs | sed "s/\/Makefile//g"`
for adms_dir in $admsdirs ; do
FOK=0
if [ -d "$adms_dir" ]; then
ls $adms_dir/admsva/*.va > /dev/null 2>&1
exitcode=$?
if [ $exitcode -ne 0 ]; then
FOK=1
fi
else
FOK=1
fi
if [ "$FOK" -eq 1 ]; then
echo "Error: No *.va file found in $adms_dir/admsva"
echo "Please download patch file ng-adms-va.tar.gz from"
echo "http://ngspice.sourceforge.net/experimental/ngspice-adms-va.7z"
echo "and expand it into the ngspice directory"
echo
DIE=1
fi
done
}
case "$1" in
"--adms" | "-a")
check_adms
check_adms_va
ADMS=1
echo "Warning: adms is no longer available, ignored!"
;;
"--help" | "-h")
@ -170,54 +115,6 @@ fi
exit 1
}
# only for --adms:
if [ "$ADMS" -gt 0 ]; then
check_awk
# add adms related Makefile entries to a configure.ac style file for
# autoconf and automake
# Find all lines with "#VLAMKF" and put the second token of each line
# into a shell variable
adms_Makefiles=`awk '$1 ~ /#VLAMKF/ { print "./" $2 }' < configure.ac`
# just the same, but escape newlines with '\' for the following sed expression
znew=`awk '$1 ~ /#VLAMKF/ { print " " $2 "\\\\" }' < configure.ac`
# Find "tests/vbic/Makefile" and insert the list of Makefiles
# some sed's fail to process the '\n' escape on the RHS,
# thus use an escaped plain newline
sed \
-e "s,tests\\/vbic\\/Makefile,&\\
$znew
," \
configure.ac > temp-adms.ac
for adms_dir in `ls $ADMSDIR` ; do
if [ -d "$ADMSDIR/$adms_dir" ]; then
case "$adms_dir" in
"admst")
# echo "Skipping admst dir"
;;
*)
echo "Entering into directory: $adms_dir"
echo "-->"$ADMSDIR/$adms_dir
(
cd $ADMSDIR/$adms_dir
$ADMSXML `ls admsva/*.va` -Iadmsva -xv -x \
-e ../admst/ngspiceVersion.xml \
-e ../admst/ngspiceMakefile.am.xml
)
;;
esac
fi
done
fi
echo "Running $LIBTOOLIZE"
$LIBTOOLIZE --copy --force \
@ -239,22 +136,10 @@ echo "Running automake -Wall --copy --add-missing"
automake -Wall --copy --add-missing \
|| error_and_exit "automake failed"
if [ "$ADMS" -gt 0 ]; then
echo "Running automake for adms"
automake -Wall --copy --add-missing $adms_Makefiles \
|| error_and_exit "automake failed"
fi
echo "Running autoconf"
if [ "$ADMS" -gt 0 ]; then
autoconf --force temp-adms.ac > configure \
|| error_and_exit "autoconf failed, with adms"
rm -f temp-adms.ac
chmod +x configure
else
autoconf --force \
|| error_and_exit "autoconf failed"
fi
echo "Success."
exit 0

View File

@ -1274,7 +1274,7 @@ else
AC_CHECK_HEADERS([readline/readline.h readline/history.h],
[AC_DEFINE([HAVE_GNUREADLINE], [], [Define if we have GNU readline])],
[AC_MSG_ERROR([Couldn't find GNU readline headers.])])
AC_SEARCH_LIBS([tputs], [ncurses tinfo termcap],
AC_SEARCH_LIBS([tputs], [tinfo termcap ncurses],
[AC_DEFINE([HAVE_TERMCAP], [], [Define if we have ncurses/terminfo or termcap])],
[AC_MSG_ERROR([Found neither ncurses/terminfo or termcap])])
AC_CHECK_LIB([readline], [readline],
@ -1290,7 +1290,7 @@ else
if test -f $dir/include/readline/readline.h && test -f $dir/include/readline/history.h ; then
AC_DEFINE([HAVE_GNUREADLINE], [], [Define if we have GNU readline])
AC_SEARCH_LIBS([tputs], [ncurses tinfo termcap],
AC_SEARCH_LIBS([tputs], [tinfo termcap ncurses],
[AC_DEFINE([HAVE_TERMCAP], [], [Define if we have ncurses/terminfo or termcap])],
[AC_MSG_ERROR([Found neither ncurses/terminfo or termcap])])
AC_CHECK_LIB([readline], [readline],
@ -1312,7 +1312,7 @@ else
AC_CHECK_HEADERS([editline/readline.h],
[AC_DEFINE([HAVE_BSDEDITLINE], [1], [Define to enable BSD editline])],
[AC_MSG_ERROR([Couldn't find BSD editline headers.])])
AC_SEARCH_LIBS([tputs], [ncurses tinfo termcap],
AC_SEARCH_LIBS([tputs], [tinfo termcap ncurses],
[AC_DEFINE([HAVE_TERMCAP], [], [Define if we have ncurses/terminfo or termcap])],
[AC_MSG_ERROR([Found neither ncurses/terminfo or termcap])])
AC_CHECK_LIB([edit], [readline],
@ -1323,7 +1323,7 @@ else
fi
# Use AC_CHECK_HEADERS so the HAVE_*_H symbol gets defined
AC_CHECK_HEADERS([ncurses/termcap.h termcap.h])
AC_CHECK_HEADERS([ncurses/termcap.h termcap.h term.h])
AC_CHECK_HEADERS([sys/sysctl.h])
# Add OpenMP to ngspice.
@ -1443,6 +1443,7 @@ AC_CONFIG_FILES([Makefile
src/xspice/ipc/Makefile
src/xspice/idn/Makefile
src/xspice/verilog/Makefile
src/xspice/vhdl/Makefile
src/osdi/Makefile
tests/Makefile
tests/bsim1/Makefile

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,30 @@
* simple examples using Skywater PDK
PDK sources:
https://github.com/google/skywater-pdk
http://opencircuitdesign.com/open_pdks/
Examples are: a simple inverter, and a benchmark circuit ISCAS85 C7552 with ca. 15k transistors.
These examples serve as low level starters with given ngspice netlist. If you are to design a circuit,
you will be better off with a GUI atop ngspice like XSCHEM, see
http://repo.hu/projects/xschem/xschem_man/tutorial_run_simulation.html and many other web sites and videos.
How to run the circuits in ngspice:
Edit the input files for correcting the path to the Skywater library, as it is user and OS specific.
Create a file .spiceinit in your HOME directory (or in this project directory).
It should contain the following statements:
set num_threads=8 ; number of physical core in your machine
set ngbehavior=hsa ; set compatibility for reading PDK libs
set skywaterpdk ; skip some checks for faster lib loading
set ng_nomodcheck ; trust the models, don't check the model parameters
unset interactive ; run scripts without interruption (default)
set nginfo ; some more info
option KLU ; select KLU solver over Sparse 1.3 solver
Run the simulation by calling
ngspice skywater_inverter.net
A plotting alternative in addition to the internal graphics is gnuplot.

View File

@ -0,0 +1,34 @@
* SkyWater PDK
* simple inverter
* Path to the PDK, to be set by you, the user
*.include "D:\Spice_general\skywater-pdk\libraries\sky130_fd_pr\latest\models\corners/tt.spice"
*.lib "D:\Spice_general\skywater-pdk\libraries\sky130_fd_pr\latest\models\sky130.lib.spice" tt
.lib D:\Spice_general\open_pdks\sky130\sky130A\libs.tech\combined\sky130.lib.spice tt
* the voltage sources:
Vdd vdd gnd DC 1.8
V1 in gnd pulse(0 1.8 0p 200p 100p 1n 2n)
* calling the inverter subcircuit
Xnot1 in vdd gnd out not1
.subckt not1 a vdd vss z
xm01 z a vdd vdd sky130_fd_pr__pfet_01v8_hvt l=0.15 w=0.99 as=0.26235 ad=0.26235 ps=2.51 pd=2.51
xm02 z a vss vss sky130_fd_pr__nfet_01v8 l=0.15 w=0.495 as=0.131175 ad=0.131175 ps=1.52 pd=1.52
c3 a vss 0.384f
c2 z vss 0.576f
.ends
* simulation command:
.tran 1ps 10ns 0 10p
.control
run
rusage time
set xbrushwidth=3
plot in out
*gnuplot interm in out
.endc
.end

View File

@ -0,0 +1,10 @@
VHDL-controlled simple timer.
* This is the model for an RS flip-flop implemented by Icarus Verilog.
.model vlog_ff d_cosim simulation="./timer_core" sim_args=["555"]
* The bulk of the circuit is in a shared file.
.include ../verilator/555.shared
.end

View File

@ -0,0 +1,29 @@
-- Very simple logic for a 555 timer simulation
library ieee;
use ieee.std_logic_1164.all;
entity timer_core is
port (
Trigger, Threshold, Reset : in std_logic;
Q, Qbar : out std_logic
);
end timer_core;
architecture rtl of timer_core is
signal result : std_logic := '0';
signal ireset, go : std_logic;
begin
go <= Trigger and Reset;
ireset <= (Threshold and not go) or not Reset;
Q <= result;
Qbar <= not result;
process (go, ireset)
begin
if rising_edge(go) or rising_edge(ireset) then
result <= go;
end if;
end process;
end rtl;

View File

@ -0,0 +1,4 @@
ngspice -- ghnggen -top timer_core 555.vhd
ngspice ghnggen pwm.vhd
ngspice ghnggen adc.vhd
ngspice ghnggen mc.vhd

View File

@ -0,0 +1 @@
del /q *.obj *.so* *.vpi *.DLL *.cf *.raw

View File

@ -0,0 +1,36 @@
The circuits in this directory illustrate the use of the d_cosim
XSPICE code model as a container for a VHDL simulation using
the GHDL compiler. Use a version of GHDL built with the LLVM back-end.
The circuits and steps below are intended to be used from the directory
containing this file, certainly ouput files from GHDL should be in
the current directory when simulating.
The example circuits are:
555.cir: The probably familiar NE555 oscillator provides a minimal example
of combined simulation with SPICE and GHDL.
The digital part of the IC, a simple SR flip-flop, is expressed in VHDL.
pwm.c: VHDL "wait" statements control a pulse-width modulated output to
generate an approximate sine wave.
adc.cir: Slightly more complex VHDL describes the controlling part
of a switched-capacitor ADC.
mc.cir: A motor-control simulation with the control algorithm written
in non-sythesisable VHDL. It is used as a general-purpose programming
language rather than a HDL. Apart from showing that this is easy to do,
no part should be taken seriously: the algorithm is poor (but simple),
the motor parameters are invented and the voltages and currents representing
mechanical quantities do not match standard units.
Before a simulation can be run, the associated VHDL code must be compiled
and an additional shared library, ghdlng.vpi must be built. A library script
isavailable to simplify the steps, run like this:
ngspice ghnggen adc.vhd
A command interpreter script, ./build or BUILD.CMD, is provided to build
all four examples, with clean/CLEAN.CMD to remove the files created.

View File

@ -0,0 +1,10 @@
Simulation of a switched-capacitor SAR ADC with GHDL and d_cosim.
* Model line for the digital control implemented by GHDL.
.model dut d_cosim simulation="./adc" sim_args=["./adc"]
* The bulk of the circuit is in a shared file.
.include ../verilator/adc.shared
.end

View File

@ -0,0 +1,62 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity adc is
generic ( Bits : integer := 6 );
port (
Clk : in std_logic;
Comp : in std_logic;
Start : in std_logic;
Sample : out std_logic;
Done : out std_logic;
Result : out unsigned(0 to Bits - 1)
);
end entity;
architecture ghdl_adc of adc is
signal SR : unsigned(0 to Bits - 1);
signal Result_Reg : unsigned(0 to Bits - 1);
signal Sample_Reg : std_logic := '0';
signal Running : std_logic := '0';
begin
Result <= Result_Reg;
Sample <= Sample_Reg;
process (Clk)
constant Zeros : unsigned(0 to Bits - 1) := (others => '0');
variable NextSR : unsigned(0 to Bits - 1);
begin
if rising_edge(Clk) then
if Running = '1' then
if Sample_Reg = '1' then
Sample_Reg <= '0';
SR(Bits - 1) <= '1';
Result_Reg(Bits - 1) <= '1';
else
if SR /= 0 then
NextSR := shift_left(SR, 1);
if Comp = '1' then
Result_Reg <= (Result_Reg and not SR) or NextSR;
else
Result_Reg <= Result_Reg or NextSR;
end if;
SR <= NextSR;
else
Running <= '0';
Done <= '1';
end if;
end if;
else
if Start = '1' then
Running <= '1';
Sample_Reg <= '1';
Done <= '0';
SR <= Zeros;
Result_Reg <= Zeros;
end if;
end if;
end if;
end process;
end architecture;

4
examples/xspice/ghdl/build Executable file
View File

@ -0,0 +1,4 @@
ngspice -- ghnggen -top timer_core 555.vhd
ngspice ghnggen pwm.vhd
ngspice ghnggen adc.vhd
ngspice ghnggen mc.vhd

2
examples/xspice/ghdl/clean Executable file
View File

@ -0,0 +1,2 @@
#!/bin/sh
rm -f *~ *.o *.so* *.vpi *.cf *.dylib *.raw

View File

@ -0,0 +1,82 @@
Simulation of elecric motor and controller in behavioural VHDL.
* Power from a wall socket.
Vmains live 0 SIN 0 250 50
* Behavioral power-line zero-crossing detector,
Bcross cross 0 V=(V(live) > -2 && V(live) < 2) ? 5 : 0
* Motor and its rotor
Xmotor live mt1 tacho 0 motor
* A triac to control the motor is replaced by a voltage-controlled switch
* to avoid including a manufacurer's triac library.
*Xtriac mt1 gate 0 BTA16-600B
Striac mt1 0 drive 0 triac off
.model triac sw vt=1.5 vh=1 roff=1meg
* The controller is implemented as VHDL code. The argument "-gTarget=5000"
* in the model line overrides the default target motor speed in the VHDL file.
* Tuning parameters Full_Band and Dead_band may also be set.
Ademo [ cross tacho ] [ drive ] controller
.model controller d_cosim simulation="./mc"
+ sim_args=["./mc.so" "-gTarget=4500"]
* Motor electrical circuit - inductance, resistance and back-EMF
* Loosley based on:
* https://www.precisionmicrodrives.com/content/ab-025-using-spice-to-model-dc-motors/
* No resemblance is claimed to any actual motor, living or dead.
.subckt motor live neutral tacho1 tacho2
+ Lm=0.3 Rm=30 BackC=20 // Electrical
+ TorqueC=30 Linertia=20 Rdrag=20 Load={50} // Mechanical
* Electrical inductance and resistance of the motor.
Lm live internal {Lm}
Rm internal back_emf {Rm}
* Back EMF: here I(Bmech) is proportional to speed, I(Bback) is motor current.
Bback back_emf neutral V=-I(Bmech)*I(Bback)*{BackC}
* Mechanical simulation: torque (V), speed (I), inertia (L) and
* friction/load (R).
* Series (Universal) motor so torque proportional to current squared.
Bmech torque 0 V=I(Bback)*I(Bback)*{TorqueC} // Motor torque
Lmech torque inertia {Linertia}
Rmech inertia load {Rdrag}
* In addition to friction (Rdrag) there is a varying load.
* Delay
* | Rise time
* | | Fall time
* | | | Pulse width
* | | | | Period
* | | | | |
* V V V V V
Vload load 0 PULSE 0 {Load} 1.2 10m 10m 200m 400m
* Tachometer: integrate speed for position and pulse.
Bpos i1 0 I=I(Bmech)
Cpos i1 0 0.01
.ic v(i1)=0
Btach tacho1 tacho2 V=((V(i1) - floor(V(i1)) > 0.5) ? 5 : 0)
.ends
.control
save drive @b.xmotor.bback[i] @b.xmotor.bmech[i] xmotor.load
tran 50u 3
plot @b.xmotor.bback[i] @b.xmotor.bmech[i]*-10 drive xmotor.load/10
.endc
.end

View File

@ -0,0 +1,80 @@
-- Test crude algorithm for a simple motor controller.
library ieee;
use ieee.std_logic_1164.all;
entity mc is
-- Control values that may be overrriden by the "sim_args" option
-- in a netlist's .model line. Intgers are used as GHDL does not
-- support overriding Real values.
generic (
Target : Integer := 4000; -- notional RPM
Dead_Band : Integer := 200;
Full_Band : Integer := 600
);
port (
Zero : in std_logic;
Tach : in std_logic;
Trigger : out std_logic
);
end mc;
architecture mc_arch of mc is
shared variable Speed : Real := 0.0;
begin
Tachometer : process (Tach) is
variable Time : Real := 0.0;
variable Last_pulse : Real := 0.0;
begin
if rising_edge(Tach) or falling_edge(Tach) then
Time := real(now / 1 ns) * 1.0e-9;
Speed := 30.0 / (Time - Last_pulse);
Last_pulse := Time;
end if;
end process Tachometer;
Controller : process (Zero) is
variable Skip : Integer := 0;
variable Count : Integer := 0;
variable Even : Boolean := True;
variable Was_even : Boolean := True;
variable Error : Integer;
begin
-- Trigger triac on zero crossings, preventing DC current.
if rising_edge(Zero) then
Even := not Even;
if (Count >= Skip) and (Even /= Was_even) then
Trigger <= '1';
Was_even := Even;
if Count > Skip then
Count := 0;
else
Count := -1;
end if;
else
Trigger <= '0';
end if;
Count := Count + 1;
-- A very crude feedback mechanism.
Error := integer(Speed) - Target;
if Error > Full_Band then
-- No drive
Skip := 1;
Count := 0;
elsif Error < -Full_Band then
-- Full Drive
Skip := 0;
elsif Error > Dead_Band then
Skip := Skip + 1;
elsif Error < -Dead_Band then
if Skip > 0 then
Skip := Skip - 1;
end if;
end if;
end if;
end process Controller;
end mc_arch;

View File

@ -0,0 +1,12 @@
* Waveform generation by PWM in VHDL.
adut null [ out ] pwm_sin
.model pwm_sin d_cosim simulation="./pwm" sim_args = [ "pwm" ]
r1 out smooth 100k
c1 smooth 0 1u
.control
tran 1m 2
plot out-3.3 smooth
.endc
.end

View File

@ -0,0 +1,37 @@
-- Very simple logic for PWM waveform generation.
library ieee;
use ieee.std_logic_1164.all;
use ieee.math_real.all;
entity pwm is
port ( output : out std_logic := '1');
end pwm;
architecture pwm_impl of pwm is
constant Cycles : Integer := 1000;
constant Samples : Integer := 1000;
constant uSec : Time := 1 us;
begin
process
variable j : Integer := 0;
variable width : Integer := Cycles / 2;
variable sine : Real;
begin
wait for width * uSec;
output <= '0';
wait for (Cycles - width) * uSec;
j := j + 1;
if j = Samples then
j := 0;
end if;
sine := sin(real(j) * MATH_2_PI / real(Samples));
width := integer(real(Samples) * (1.0 + sine) / 2.0);
if width = 0 then
output <= '0';
else
output <= '1';
end if;
end process;
end pwm_impl;

View File

@ -973,6 +973,26 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile)
FILE *fdo = fopen("debug-out2.txt", "w");
if (fdo) {
struct card *tc = NULL;
fprintf(fdo,
"\n\n**************** uncommented deck without source file info "
"**************\n\n");
/* always print first line */
fprintf(fdo, "%6d %s\n", deck->linenum,
deck->line);
/* here without out-commented lines */
for (tc = deck->nextcard; tc; tc = tc->nextcard) {
if (*(tc->line) == '*')
continue;
/* Only truncated .model lines */
if (ciprefix(".model", tc->line)) {
fprintf(fdo, "%6d %.100s ...\n",
tc->linenum, tc->line);
}
else {
fprintf(fdo, "%6d %s\n",
tc->linenum, tc->line);
}
}
fprintf(fdo, "**************** uncommented deck **************\n\n");
/* always print first line */
fprintf(fdo, "%6s %6d %6d %s\n", deck->linesource, deck->linenum_orig, deck->linenum, deck->line);

View File

@ -1231,8 +1231,15 @@ struct card *inp_readall(FILE *fp, const char *dir_name, const char* file_name,
for (t = cc->nextcard; t; t = t->nextcard) {
if (*(t->line) == '*')
continue;
fprintf(fd, "%6d %s\n",
/* Only truncated .model lines */
if (ciprefix(".model", t->line)) {
fprintf(fd, "%6d %.100s ...\n",
t->linenum, t->line);
}
else {
fprintf(fd, "%6d %s\n",
t->linenum, t->line);
}
}
fprintf(fd,
"\n\n**************** uncommented deck "

View File

@ -256,9 +256,6 @@ com_version(wordlist *wl)
#ifdef NGDEBUG
fprintf(cp_out, "** Debugging option (-g) enabled\n");
#endif
#ifdef ADMS
fprintf(cp_out, "** Adms interface enabled\n");
#endif
#ifdef USE_OMP
fprintf(cp_out, "** OpenMP multithreading for BSIM3, BSIM4 enabled\n");
#endif

View File

@ -21,19 +21,6 @@ Author: 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
#include <sys/ioctl.h>
#endif
#ifdef HAVE_TERMCAP
#include <curses.h>
#include <term.h>
#endif
#ifdef HAVE_TERMCAP_H
#include <termcap.h>
#elif HAVE_NCURSES_TERMCAP_H
#include <ncurses/termcap.h>
#endif
#include "ngspice/cpdefs.h"
#include "variable.h"
@ -45,6 +32,22 @@ bool out_isatty = TRUE;
#if !defined (TCL_MODULE) && !defined (SHARED_MODULE)
#ifdef HAVE_TERMCAP
/* The tputs() function was found in a library, but there are several
* candidates for the header file location.
*/
#if HAVE_TERM_H
#include <term.h>
#elif HAVE_TERMCAP_H
#include <termcap.h>
#elif HAVE_NCURSES_TERMCAP_H
#include <ncurses/termcap.h>
#else
#undef HAVE_TERMCAP
#endif
#endif
#ifdef HAVE_TERMCAP
static char *motion_chars;
static char *clear_chars;

View File

@ -88,7 +88,7 @@ void com_optran(wordlist* wl) {
return;
}
else if (!ft_curckt && !dataset && wl == NULL) {
fprintf(stderr, "Error: syntax error with command 'optran'!\n");
fprintf(stderr, "Warning: syntax error with command 'optran'!\n");
fprintf(stderr, " Command ingnored\n");
return;
}
@ -169,7 +169,8 @@ void com_optran(wordlist* wl) {
goto bugquit;
}
if (opstepsize > opfinaltime/50.) {
fprintf(stderr, "Warning: Optran step size potentially too large.\n");
opstepsize = opfinaltime / 50.;
fprintf(stdout, "Note: Optran step size set to %e, (stepsize = finaltime / 50).\n", opstepsize);
}
if (opramptime > opfinaltime) {
fprintf(stderr, "Error: Optran ramp time larger than final time.\n");

View File

@ -137,8 +137,6 @@ libdev_la_SOURCES = \
cktsoachk.c \
limit.c
EXTRA_DIST = adms/admst
AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include -I$(top_srcdir)/src/spicelib/devices
AM_CFLAGS = $(STATIC)

View File

@ -126,16 +126,6 @@ extern struct coreInfo_t coreInfo; /* cmexport.c */
#include "vcvs/vcvsitf.h"
#include "vsrc/vsrcitf.h"
#include "vdmos/vdmositf.h"
#ifdef ADMS
#include "adms/hicum0/hicum0itf.h"
#include "adms/mextram/bjt504titf.h"
#include "adms/ekv/ekvitf.h"
#include "adms/psp102/psp102itf.h"
#include "adms/psp103/psp103itf.h"
#include "adms/bsimbulk/bsimbulkitf.h"
#include "adms/bsimcmg/bsimcmgitf.h"
#include "adms/r2_cmc/r2_cmcitf.h"
#endif
#ifdef CIDER
/* Numerical devices (Cider integration) */
#include "nbjt/nbjtitf.h"
@ -211,17 +201,6 @@ static SPICEdev *(*static_devices[])(void) = {
get_numos_info,
#endif
#ifdef ADMS
(SPICEdev *(*)(void)) get_hicum0_info,
(SPICEdev *(*)(void)) get_bjt504t_info,
(SPICEdev *(*)(void)) get_ekv_info,
(SPICEdev *(*)(void)) get_psp102_info,
(SPICEdev *(*)(void)) get_psp103_info,
(SPICEdev *(*)(void)) get_bsimbulk_info,
(SPICEdev *(*)(void)) get_bsimcmg_info,
(SPICEdev *(*)(void)) get_r2_cmc_info,
#endif
#ifdef NDEV
get_ndev_info,
#endif
@ -303,17 +282,12 @@ SPICEdev ** devices(void)
#ifdef DEVLIB
/*not yet usable*/
#ifdef ADMS
#define DEVICES_USED {"asrc", "bjt", "vbic", "bsim1", "bsim2", "bsim3", "bsim3v32", "bsim3v2", "bsim3v1", "bsim4", "bsim4v5", "bsim4v6", "bsim4v7", \
"bsim4soi", "bsim3soipd", "bsim3soifd", "bsim3soidd", "hisim2", "hisimhv1", "hisimhv2", \
"cap", "cccs", "ccvs", "csw", "dio", "hfet", "hfet2", "ind", "isrc", "jfet", "ltra", "mes", "mesa" ,"mos1", "mos2", "mos3", \
"mos6", "mos9", "res", "soi3", "sw", "tra", "urc", "vccs", "vcvs", "vsrc", "hicum0", "bjt504t", "ekv", "psp102", "psp103", "bsimbulk", "bsimcmg"}
#else
#define DEVICES_USED {"asrc", "bjt", "vbic", "bsim1", "bsim2", "bsim3", "bsim3v32", "bsim3v2", "bsim3v1", "bsim4", "bsim4v5", "bsim4v6", "bsim4v7", \
"bsim4soi", "bsim3soipd", "bsim3soifd", "bsim3soidd", "hisim2", "hisimhv1", "hisimhv2", \
"cap", "cccs", "ccvs", "csw", "dio", "hfet", "hfet2", "ind", "isrc", "jfet", "ltra", "mes", "mesa" ,"mos1", "mos2", "mos3", \
"mos6", "mos9", "res", "soi3", "sw", "tra", "urc", "vccs", "vcvs", "vsrc", "hicum2"}
#endif
int load_dev(char *name) {
char *msg;
char libname[50];

View File

@ -16,6 +16,7 @@ IFparm DIOpTable[] = { /* parameters */
IOPAU("ic", DIO_IC, IF_REAL, "Initial device voltage"),
IOPU("area", DIO_AREA, IF_REAL, "Area factor"),
IOPU("pj", DIO_PJ, IF_REAL, "Perimeter factor"),
IOPUR("perim", DIO_PJ, IF_REAL, "Perimeter factor"),
IOPU("w", DIO_W, IF_REAL, "Diode width"),
IOPU("l", DIO_L, IF_REAL, "Diode length"),
IOPU("m", DIO_M, IF_REAL, "Multiplier"),
@ -49,6 +50,7 @@ IFparm DIOmPTable[] = { /* model parameters */
IOP( "is", DIO_MOD_IS, IF_REAL, "Saturation current"),
IOPR( "js", DIO_MOD_IS, IF_REAL, "Saturation current"),
IOP( "jsw", DIO_MOD_JSW, IF_REAL, "Sidewall Saturation current"),
IOPR( "isw", DIO_MOD_JSW, IF_REAL, "Sidewall Saturation current"),
IOPU( "tnom",DIO_MOD_TNOM,IF_REAL, "Parameter measurement temperature"),
IOPUR("tref",DIO_MOD_TNOM,IF_REAL, "Parameter measurement temperature"),
@ -73,6 +75,7 @@ IFparm DIOmPTable[] = { /* model parameters */
IOP( "cjp", DIO_MOD_CJSW, IF_REAL, "Sidewall junction capacitance"),
IOPR( "cjsw", DIO_MOD_CJSW, IF_REAL, "Sidewall junction capacitance"),
IOP( "php", DIO_MOD_VJSW, IF_REAL, "Sidewall junction potential"),
IOPR( "vjsw", DIO_MOD_VJSW, IF_REAL, "Sidewall junction potential"),
IOP( "mjsw", DIO_MOD_MJSW, IF_REAL, "Sidewall Grading coefficient"),
IOP( "ikf", DIO_MOD_IKF, IF_REAL, "Forward Knee current"),
IOPR( "ik", DIO_MOD_IKF, IF_REAL, "Forward Knee current"),

View File

@ -42,6 +42,10 @@ IFparm VBICpTable[] = { /* parameters */
OP("ib", VBIC_QUEST_CB, IF_REAL, "Base current"),
OP("ie", VBIC_QUEST_CE, IF_REAL, "Emitter current"),
OP("is", VBIC_QUEST_CS, IF_REAL, "Substrate current"),
OP("p", VBIC_QUEST_POWER,IF_REAL, "Power dissipation"),
OPR("power",VBIC_QUEST_POWER,IF_REAL, "Power dissipation"),
OP("beta", VBIC_QUEST_BETA, IF_REAL, "CE current gain DC"),
OPR("betad",VBIC_QUEST_BETA, IF_REAL, "CE current gain DC"),
OP("gm", VBIC_QUEST_GM, IF_REAL, "Small signal transconductance dIc/dVbe"),
OP("go", VBIC_QUEST_GO, IF_REAL, "Small signal output conductance dIc/dVbc"),
OP("gpi", VBIC_QUEST_GPI, IF_REAL, "Small signal input conductance dIb/dVbe"),
@ -53,15 +57,8 @@ IFparm VBICpTable[] = { /* parameters */
OP("cbcx", VBIC_QUEST_CBCX, IF_REAL, "External Base to collector capacitance"),
OP("cbep", VBIC_QUEST_CBEP, IF_REAL, "Parasitic Base to emitter capacitance"),
OP("cbcp", VBIC_QUEST_CBCP, IF_REAL, "Parasitic Base to collector capacitance"),
OP("p", VBIC_QUEST_POWER,IF_REAL, "Power dissipation"),
OPU("geqcb",VBIC_QUEST_GEQCB,IF_REAL, "Internal C-B-base cap. equiv. cond."),
OPU("geqbx",VBIC_QUEST_GEQBX,IF_REAL, "External C-B-base cap. equiv. cond."),
OPU("qbe", VBIC_QUEST_QBE, IF_REAL, "Charge storage B-E junction"),
OPU("cqbe", VBIC_QUEST_CQBE, IF_REAL, "Cap. due to charge storage in B-E jct."),
OPU("qbc", VBIC_QUEST_QBC, IF_REAL, "Charge storage B-C junction"),
OPU("cqbc", VBIC_QUEST_CQBC, IF_REAL, "Cap. due to charge storage in B-C jct."),
OPU("qbx", VBIC_QUEST_QBX, IF_REAL, "Charge storage B-X junction"),
OPU("cqbx", VBIC_QUEST_CQBX, IF_REAL, "Cap. due to charge storage in B-X jct.")
};
IFparm VBICmPTable[] = { /* model parameters */

View File

@ -23,7 +23,7 @@ VBICacLoad(GENmodel *inModel, CKTcircuit *ckt)
VBICinstance *here;
VBICmodel *model = (VBICmodel*)inModel;
double Ibe_Vbei,Ibex_Vbex
,Itzf_Vbei,Itzf_Vbci,Itzr_Vbci,Itzr_Vbei,Ibc_Vbci
,Iciei_Vbei,Iciei_Vbci,Ibc_Vbci
,Ibc_Vbei,Ibep_Vbep,Ircx_Vrcx,Irci_Vrci
,Irci_Vbci,Irci_Vbcx,Irbx_Vrbx,Irbi_Vrbi,Irbi_Vbei
,Irbi_Vbci,Ire_Vre,Irbp_Vrbp,Irbp_Vbep,Irbp_Vbci
@ -32,7 +32,7 @@ VBICacLoad(GENmodel *inModel, CKTcircuit *ckt)
XQbcx_Vbcx, XQbep_Vbep, XQbep_Vbci,
XQbcp_Vbcp, XQbeo_Vbe, XQbco_Vbc;
double Ibe_Vrth, Ibex_Vrth, Itzf_Vrth=0.0, Itzr_Vrth, Ibc_Vrth, Ibep_Vrth,
double Ibe_Vrth, Ibex_Vrth, Iciei_Vrth, Iciei_Vxf2, Ibc_Vrth, Ibep_Vrth,
Ircx_Vrth, Irci_Vrth, Irbx_Vrth, Irbi_Vrth, Ire_Vrth, Irbp_Vrth,
Ibcp_Vrth, Iccp_Vrth, Irs_Vrth, Irth_Vrth, Ith_Vrth,
Ith_Vbei, Ith_Vbci, Ith_Vcei, Ith_Vbex, Ith_Vbep, Ith_Vbcp, Ith_Vcep,
@ -40,42 +40,60 @@ VBICacLoad(GENmodel *inModel, CKTcircuit *ckt)
double XQcth_Vrth, XQbe_Vrth, XQbex_Vrth, XQbc_Vrth, XQbcx_Vrth, XQbep_Vrth, XQbcp_Vrth;
//NQS
double Itxf_Vrxf, Ibc_Vrxf, Ith_Vrxf, Ixzf_Vrth, Ixxf_Vrxf, XQcxf_Vcxf;
double Ixzf_Vbei, Ixzf_Vbci, Xl;
double XQxf1_Vxf1;
double XQxf2_Vxf2;
double Ixf1_Vbei;
double Ixf1_Vbci;
double Ixf1_Vxf2;
double Ixf1_Vxf1;
double Ixf1_Vrth;
double Ixf2_Vxf2;
double Ixf2_Vxf1;
/* loop through all the models */
for( ; model != NULL; model = VBICnextModel(model)) {
/* loop through all the instances of the model */
for( here = VBICinstances(model); here!= NULL;
for( here = VBICinstances(model); here!= NULL;
here = VBICnextInstance(here)) {
Ibe_Vbei = *(ckt->CKTstate0 + here->VBICibe_Vbei);
Ibex_Vbex = *(ckt->CKTstate0 + here->VBICibex_Vbex);
Itzf_Vbei = *(ckt->CKTstate0 + here->VBICitzf_Vbei);
Itzf_Vbci = *(ckt->CKTstate0 + here->VBICitzf_Vbci);
Itzr_Vbci = *(ckt->CKTstate0 + here->VBICitzr_Vbci);
Itzr_Vbei = *(ckt->CKTstate0 + here->VBICitzr_Vbei);
Ibc_Vbci = *(ckt->CKTstate0 + here->VBICibc_Vbci);
Ibc_Vbei = *(ckt->CKTstate0 + here->VBICibc_Vbei);
Ibep_Vbep = *(ckt->CKTstate0 + here->VBICibep_Vbep);
Irci_Vrci = *(ckt->CKTstate0 + here->VBICirci_Vrci);
Irci_Vbci = *(ckt->CKTstate0 + here->VBICirci_Vbci);
Irci_Vbcx = *(ckt->CKTstate0 + here->VBICirci_Vbcx);
Irbi_Vrbi = *(ckt->CKTstate0 + here->VBICirbi_Vrbi);
Irbi_Vbei = *(ckt->CKTstate0 + here->VBICirbi_Vbei);
Irbi_Vbci = *(ckt->CKTstate0 + here->VBICirbi_Vbci);
Irbp_Vrbp = *(ckt->CKTstate0 + here->VBICirbp_Vrbp);
Irbp_Vbep = *(ckt->CKTstate0 + here->VBICirbp_Vbep);
Irbp_Vbci = *(ckt->CKTstate0 + here->VBICirbp_Vbci);
Ibcp_Vbcp = *(ckt->CKTstate0 + here->VBICibcp_Vbcp);
Iccp_Vbep = *(ckt->CKTstate0 + here->VBICiccp_Vbep);
Iccp_Vbci = *(ckt->CKTstate0 + here->VBICiccp_Vbci);
Iccp_Vbcp = *(ckt->CKTstate0 + here->VBICiccp_Vbcp);
Ircx_Vrcx = *(ckt->CKTstate0 + here->VBICircx_Vrcx);
Irbx_Vrbx = *(ckt->CKTstate0 + here->VBICirbx_Vrbx);
Irs_Vrs = *(ckt->CKTstate0 + here->VBICirs_Vrs);
Ire_Vre = *(ckt->CKTstate0 + here->VBICire_Vre);
Ibe_Vbei = *(ckt->CKTstate0 + here->VBICibe_Vbei);
Ibex_Vbex = *(ckt->CKTstate0 + here->VBICibex_Vbex);
Iciei_Vbei = *(ckt->CKTstate0 + here->VBICiciei_Vbei);
Iciei_Vbci = *(ckt->CKTstate0 + here->VBICiciei_Vbci);
Iciei_Vrth = *(ckt->CKTstate0 + here->VBICiciei_Vrth);
Iciei_Vxf2 = *(ckt->CKTstate0 + here->VBICiciei_Vxf2);
Ibc_Vbci = *(ckt->CKTstate0 + here->VBICibc_Vbci);
Ibc_Vbei = *(ckt->CKTstate0 + here->VBICibc_Vbei);
Ibep_Vbep = *(ckt->CKTstate0 + here->VBICibep_Vbep);
Irci_Vrci = *(ckt->CKTstate0 + here->VBICirci_Vrci);
Irci_Vbci = *(ckt->CKTstate0 + here->VBICirci_Vbci);
Irci_Vbcx = *(ckt->CKTstate0 + here->VBICirci_Vbcx);
Irbi_Vrbi = *(ckt->CKTstate0 + here->VBICirbi_Vrbi);
Irbi_Vbei = *(ckt->CKTstate0 + here->VBICirbi_Vbei);
Irbi_Vbci = *(ckt->CKTstate0 + here->VBICirbi_Vbci);
Irbp_Vrbp = *(ckt->CKTstate0 + here->VBICirbp_Vrbp);
Irbp_Vbep = *(ckt->CKTstate0 + here->VBICirbp_Vbep);
Irbp_Vbci = *(ckt->CKTstate0 + here->VBICirbp_Vbci);
Ibcp_Vbcp = *(ckt->CKTstate0 + here->VBICibcp_Vbcp);
Iccp_Vbep = *(ckt->CKTstate0 + here->VBICiccp_Vbep);
Iccp_Vbci = *(ckt->CKTstate0 + here->VBICiccp_Vbci);
Iccp_Vbcp = *(ckt->CKTstate0 + here->VBICiccp_Vbcp);
Ircx_Vrcx = *(ckt->CKTstate0 + here->VBICircx_Vrcx);
Irbx_Vrbx = *(ckt->CKTstate0 + here->VBICirbx_Vrbx);
Irs_Vrs = *(ckt->CKTstate0 + here->VBICirs_Vrs);
Ire_Vre = *(ckt->CKTstate0 + here->VBICire_Vre);
Ixf1_Vbei = *(ckt->CKTstate0 + here->VBICixf1_Vbei);
Ixf1_Vbci = *(ckt->CKTstate0 + here->VBICixf1_Vbci);
Ixf1_Vxf1 = *(ckt->CKTstate0 + here->VBICixf1_Vxf1);
Ixf1_Vxf2 = *(ckt->CKTstate0 + here->VBICixf1_Vxf2);
Ixf1_Vrth = *(ckt->CKTstate0 + here->VBICixf1_Vrth);
Ixf2_Vxf1 = *(ckt->CKTstate0 + here->VBICixf2_Vxf1);
Ixf2_Vxf2 = *(ckt->CKTstate0 + here->VBICixf2_Vxf2);
/*
c The real part
@ -94,32 +112,22 @@ c Stamp element: Ibex
*(here->VBICbaseBXEmitEIPtr) += -Ibex_Vbex;
*(here->VBICemitEIBaseBXPtr) += -Ibex_Vbex;
*(here->VBICemitEIEmitEIPtr) += Ibex_Vbex;
if (!here->VBIC_excessPhase) {
/*
c Stamp element: Itzf
c Stamp element: Iciei
*/
*(here->VBICcollCIBaseBIPtr) += Itzf_Vbei;
*(here->VBICcollCIEmitEIPtr) += -Itzf_Vbei;
*(here->VBICcollCIBaseBIPtr) += Itzf_Vbci;
*(here->VBICcollCICollCIPtr) += -Itzf_Vbci;
*(here->VBICemitEIBaseBIPtr) += -Itzf_Vbei;
*(here->VBICemitEIEmitEIPtr) += Itzf_Vbei;
*(here->VBICemitEIBaseBIPtr) += -Itzf_Vbci;
*(here->VBICemitEICollCIPtr) += Itzf_Vbci;
*(here->VBICcollCIBaseBIPtr) += Iciei_Vbei;
*(here->VBICcollCIEmitEIPtr) += -Iciei_Vbei;
*(here->VBICcollCIBaseBIPtr) += Iciei_Vbci;
*(here->VBICcollCICollCIPtr) += -Iciei_Vbci;
*(here->VBICemitEIBaseBIPtr) += -Iciei_Vbei;
*(here->VBICemitEIEmitEIPtr) += Iciei_Vbei;
*(here->VBICemitEIBaseBIPtr) += -Iciei_Vbci;
*(here->VBICemitEICollCIPtr) += Iciei_Vbci;
if (here->VBIC_excessPhase) {
*(here->VBICcollCIXf2Ptr) += Iciei_Vxf2;
*(here->VBICemitEIXf2Ptr) += -Iciei_Vxf2;
}
/*
c Stamp element: Itzr
*/
*(here->VBICemitEIBaseBIPtr) += Itzr_Vbei;
*(here->VBICemitEIEmitEIPtr) += -Itzr_Vbei;
*(here->VBICemitEIBaseBIPtr) += Itzr_Vbci;
*(here->VBICemitEICollCIPtr) += -Itzr_Vbci;
*(here->VBICcollCIBaseBIPtr) += -Itzr_Vbei;
*(here->VBICcollCIEmitEIPtr) += Itzr_Vbei;
*(here->VBICcollCIBaseBIPtr) += -Itzr_Vbci;
*(here->VBICcollCICollCIPtr) += Itzr_Vbci;
/*
c Stamp element: Ibc
*/
*(here->VBICbaseBIBaseBIPtr) += Ibc_Vbci;
@ -145,7 +153,7 @@ c Stamp element: Rcx
*(here->VBICcollCXCollPtr) += -Ircx_Vrcx;
*(here->VBICcollCollCXPtr) += -Ircx_Vrcx;
/*
c Stamp element: Irci
c Stamp element: Rci
*/
*(here->VBICcollCXCollCXPtr) += Irci_Vrci;
*(here->VBICcollCXCollCIPtr) += -Irci_Vrci;
@ -167,7 +175,7 @@ c Stamp element: Rbx
*(here->VBICbaseBXBasePtr) += -Irbx_Vrbx;
*(here->VBICbaseBaseBXPtr) += -Irbx_Vrbx;
/*
c Stamp element: Irbi
c Stamp element: Rbi
*/
*(here->VBICbaseBXBaseBXPtr) += Irbi_Vrbi;
*(here->VBICbaseBXBaseBIPtr) += -Irbi_Vrbi;
@ -189,7 +197,7 @@ c Stamp element: Re
*(here->VBICemitEIEmitPtr) += -Ire_Vre;
*(here->VBICemitEmitEIPtr) += -Ire_Vre;
/*
c Stamp element: Irbp
c Stamp element: Rbp
*/
*(here->VBICbaseBPBaseBPPtr) += Irbp_Vrbp;
*(here->VBICbaseBPCollCXPtr) += -Irbp_Vrbp;
@ -233,13 +241,23 @@ c Stamp element: Rs
*(here->VBICsubsSISubsPtr) += -Irs_Vrs;
*(here->VBICsubsSubsSIPtr) += -Irs_Vrs;
if (here->VBIC_excessPhase) {
//Ixf1
*(here->VBICxf1BaseBIPtr) += +Ixf1_Vbei;
*(here->VBICxf1EmitEIPtr) += -Ixf1_Vbei;
*(here->VBICxf1BaseBIPtr) += +Ixf1_Vbci;
*(here->VBICxf1CollCIPtr) += -Ixf1_Vbci;
*(here->VBICxf1Xf2Ptr) += +Ixf1_Vxf2;
*(here->VBICxf1Xf1Ptr) += +Ixf1_Vxf1;
//Ixf2
*(here->VBICxf2Xf2Ptr) += +Ixf2_Vxf2;
*(here->VBICxf2Xf1Ptr) += +Ixf2_Vxf1;
}
if (here->VBIC_selfheat) {
Ibe_Vrth = here->VBICibe_Vrth;
Ibex_Vrth = here->VBICibex_Vrth;
if (!here->VBIC_excessPhase)
Itzf_Vrth = here->VBICitzf_vrth;
Itzr_Vrth = here->VBICitzr_Vrth;
Ibc_Vrth = here->VBICibc_Vrth;
Ibep_Vrth = here->VBICibep_Vrth;
Ircx_Vrth = here->VBICircx_Vrth;
@ -279,19 +297,11 @@ c Stamp element: Ibex
*/
*(here->VBICbaseBXtempPtr) += Ibex_Vrth;
*(here->VBICemitEItempPtr) += -Ibex_Vrth;
if (!here->VBIC_excessPhase) {
/*
c Stamp element: Itzf
c Stamp element: Iciei
*/
*(here->VBICcollCItempPtr) += Itzf_Vrth;
*(here->VBICemitEItempPtr) += -Itzf_Vrth;
}
/*
c Stamp element: Itzr
*/
*(here->VBICemitEItempPtr) += Itzr_Vrth;
*(here->VBICcollCItempPtr) += -Itzr_Vrth;
*(here->VBICcollCItempPtr) += Iciei_Vrth;
*(here->VBICemitEItempPtr) += -Iciei_Vrth;
/*
c Stamp element: Ibc
*/
@ -347,6 +357,11 @@ c Stamp element: Rs
*/
*(here->VBICsubsTempPtr) += Irs_Vrth;
*(here->VBICsubsSItempPtr) += -Irs_Vrth;
if (here->VBIC_excessPhase) {
// Stamp element: Ixf1 f_xf1 = +
*(here->VBICxf1TempPtr) += Ixf1_Vrth;
}
/*
c Stamp element: Rth
*/
@ -386,44 +401,6 @@ c Stamp element: Ith
*(here->VBICtempEmitEIPtr) += +Ith_Vre;
*(here->VBICtempSubsPtr) += -Ith_Vrs;
*(here->VBICtempSubsSIPtr) += +Ith_Vrs;
if (here->VBIC_excessPhase) {
Ith_Vrxf = *(ckt->CKTstate0 + here->VBICith_Vrxf);
*(here->VBICtempXf2Ptr) += +Ith_Vrxf;
}
}
if (here->VBIC_excessPhase) {
Itxf_Vrxf = *(ckt->CKTstate0 + here->VBICitxf_Vrxf);
Ibc_Vrxf = *(ckt->CKTstate0 + here->VBICibc_Vrxf);
Ixzf_Vbei = *(ckt->CKTstate0 + here->VBICixzf_Vbei);
Ixzf_Vbci = *(ckt->CKTstate0 + here->VBICixzf_Vbci);
Ixxf_Vrxf = *(ckt->CKTstate0 + here->VBICixxf_Vrxf);
/*
c Stamp element: Itxf
*/
*(here->VBICcollCIXf2Ptr) += Itxf_Vrxf;
*(here->VBICemitEIXf2Ptr) += -Itxf_Vrxf;
/*
c Stamp element: Ibc
*/
*(here->VBICbaseBIXf2Ptr) += Ibc_Vrxf;
*(here->VBICcollCIXf2Ptr) += -Ibc_Vrxf;
/*
c Stamp element: Ixzf, Branch: xf1-ground
*/
*(here->VBICxf1BaseBIPtr) += +Ixzf_Vbei;
*(here->VBICxf1EmitEIPtr) += -Ixzf_Vbei;
*(here->VBICxf1BaseBIPtr) += +Ixzf_Vbci;
*(here->VBICxf1CollCIPtr) += -Ixzf_Vbci;
if (here->VBIC_selfheat) {
Ixzf_Vrth = *(ckt->CKTstate0 + here->VBICixzf_Vrth);
*(here->VBICxf1TempPtr) += Ixzf_Vrth;
}
/*
c Stamp element: Ixxf, Branch: xf2-ground
*/
*(here->VBICxf2Xf2Ptr) += +Ixxf_Vrxf;
}
/*
@ -439,6 +416,8 @@ c The complex part
XQbcp_Vbcp = *(ckt->CKTstate0 + here->VBICcqbcp) * ckt->CKTomega;
XQbeo_Vbe = *(ckt->CKTstate0 + here->VBICcqbeo) * ckt->CKTomega;
XQbco_Vbc = *(ckt->CKTstate0 + here->VBICcqbco) * ckt->CKTomega;
XQxf1_Vxf1 = *(ckt->CKTstate0 + here->VBICcqxf1) * ckt->CKTomega;
XQxf2_Vxf2 = *(ckt->CKTstate0 + here->VBICcqxf2) * ckt->CKTomega;
/*
c Stamp element: Qbe
*/
@ -504,6 +483,13 @@ c Stamp element: Qbco
*(here->VBICbaseCollPtr + 1) += -XQbco_Vbc;
*(here->VBICcollBasePtr + 1) += -XQbco_Vbc;
if (here->VBIC_excessPhase) {
//Qxf1
*(here->VBICxf1Xf1Ptr + 1) += +XQxf1_Vxf1;
//Qxf2
*(here->VBICxf2Xf2Ptr + 1) += +XQxf2_Vxf2;
}
if (here->VBIC_selfheat) {
XQcth_Vrth = here->VBICcapcth * ckt->CKTomega;
XQbe_Vrth = here->VBICcapqbeth * ckt->CKTomega;
@ -528,24 +514,6 @@ c Stamp element: Qbco
*(here->VBICsubsSItempPtr + 1) += XQbcp_Vrth;
*(here->VBICbaseBPtempPtr + 1) += -XQbcp_Vrth;
}
if (here->VBIC_excessPhase) {
/*
c Stamp element: Qcxf
*/
XQcxf_Vcxf = here->VBICcapQcxf * ckt->CKTomega;
*(here->VBICxf1Xf1Ptr + 1) += XQcxf_Vcxf;
/*
c Stamp element: L = TD/3
*/
Xl = here->VBICindInduct * ckt->CKTomega;
*(here->VBICxf1IbrPtr) += 1;
*(here->VBICxf2IbrPtr) -= 1;
*(here->VBICibrXf1Ptr) += 1;
*(here->VBICibrXf2Ptr) -= 1;
*(here->VBICibrIbrPtr + 1) -= Xl;
}
}
}

View File

@ -22,9 +22,11 @@ Spice3 Implementation: 2003 Dietmar Warning DAnalyse GmbH
int
VBICask(CKTcircuit *ckt, GENinstance *instPtr, int which, IFvalue *value, IFvalue *select)
{
IFvalue IC, IB, IE, IS;
NG_IGNORE(select);
VBICinstance *here = (VBICinstance*)instPtr;
IFvalue IC, IB;
switch(which) {
case VBIC_AREA:
value->rValue = here->VBICarea;
@ -75,14 +77,9 @@ VBICask(CKTcircuit *ckt, GENinstance *instPtr, int which, IFvalue *value, IFvalu
value->rValue = *(ckt->CKTstate0 + here->VBICvbci);
return(OK);
case VBIC_QUEST_CC:
if (!here->VBIC_excessPhase)
value->rValue = *(ckt->CKTstate0 + here->VBICitzf) -
*(ckt->CKTstate0 + here->VBICitzr) -
*(ckt->CKTstate0 + here->VBICibc);
else
value->rValue = *(ckt->CKTstate0 + here->VBICitxf) -
*(ckt->CKTstate0 + here->VBICitzr) -
*(ckt->CKTstate0 + here->VBICibc);
value->rValue = *(ckt->CKTstate0 + here->VBICiciei) -
*(ckt->CKTstate0 + here->VBICiccp) -
*(ckt->CKTstate0 + here->VBICibc);
value->rValue *= VBICmodPtr(here)->VBICtype;
return(OK);
case VBIC_QUEST_CB:
@ -94,16 +91,9 @@ VBICask(CKTcircuit *ckt, GENinstance *instPtr, int which, IFvalue *value, IFvalu
value->rValue *= VBICmodPtr(here)->VBICtype;
return(OK);
case VBIC_QUEST_CE:
if (!here->VBIC_excessPhase)
value->rValue = - *(ckt->CKTstate0 + here->VBICibe) -
*(ckt->CKTstate0 + here->VBICibex) -
*(ckt->CKTstate0 + here->VBICitzf) +
*(ckt->CKTstate0 + here->VBICitzr);
else
value->rValue = - *(ckt->CKTstate0 + here->VBICibe) -
*(ckt->CKTstate0 + here->VBICibex) -
*(ckt->CKTstate0 + here->VBICitxf) +
*(ckt->CKTstate0 + here->VBICitzr);
value->rValue = - *(ckt->CKTstate0 + here->VBICibe) -
*(ckt->CKTstate0 + here->VBICibex) -
*(ckt->CKTstate0 + here->VBICiciei);
value->rValue *= VBICmodPtr(here)->VBICtype;
return(OK);
case VBIC_QUEST_CS:
@ -112,48 +102,22 @@ VBICask(CKTcircuit *ckt, GENinstance *instPtr, int which, IFvalue *value, IFvalu
value->rValue *= VBICmodPtr(here)->VBICtype;
return(OK);
case VBIC_QUEST_POWER:
value->rValue = fabs(here->VBICpower);
return(OK);
case VBIC_QUEST_BETA:
VBICask(ckt, instPtr, VBIC_QUEST_CC, &IC, select);
VBICask(ckt, instPtr, VBIC_QUEST_CB, &IB, select);
VBICask(ckt, instPtr, VBIC_QUEST_CE, &IE, select);
VBICask(ckt, instPtr, VBIC_QUEST_CS, &IS, select);
if (!here->VBIC_excessPhase)
value->rValue = fabs(*(ckt->CKTstate0 + here->VBICibe) * *(ckt->CKTstate0 + here->VBICvbei)) +
fabs(*(ckt->CKTstate0 + here->VBICibc) * *(ckt->CKTstate0 + here->VBICvbci)) +
fabs(*(ckt->CKTstate0 + here->VBICitzf) - *(ckt->CKTstate0 + here->VBICitzr))
* fabs(*(ckt->CKTstate0 + here->VBICvbei) - *(ckt->CKTstate0 + here->VBICvbci)) +
fabs(*(ckt->CKTstate0 + here->VBICibex) * *(ckt->CKTstate0 + here->VBICvbex)) +
fabs(*(ckt->CKTstate0 + here->VBICibep) * *(ckt->CKTstate0 + here->VBICvbep)) +
fabs(*(ckt->CKTstate0 + here->VBICibcp) * *(ckt->CKTstate0 + here->VBICvbcp)) +
fabs(*(ckt->CKTstate0 + here->VBICiccp))
* fabs(*(ckt->CKTstate0 + here->VBICvbep) - *(ckt->CKTstate0 + here->VBICvbcp)) +
fabs(IC.rValue * IC.rValue * here->VBICtextCollResist) +
fabs(IC.rValue * *(ckt->CKTstate0 + here->VBICvrci)) +
fabs(IB.rValue * IB.rValue * here->VBICtextBaseResist) +
fabs(IB.rValue * *(ckt->CKTstate0 + here->VBICvrbi)) +
fabs(IE.rValue * IE.rValue * here->VBICtemitterResist) +
fabs(IS.rValue * *(ckt->CKTstate0 + here->VBICvrbp));
else
value->rValue = fabs(*(ckt->CKTstate0 + here->VBICibe) * *(ckt->CKTstate0 + here->VBICvbei)) +
fabs(*(ckt->CKTstate0 + here->VBICibc) * *(ckt->CKTstate0 + here->VBICvbci)) +
fabs(*(ckt->CKTstate0 + here->VBICitxf) - *(ckt->CKTstate0 + here->VBICitzr))
* fabs(*(ckt->CKTstate0 + here->VBICvbei) - *(ckt->CKTstate0 + here->VBICvbci)) +
fabs(*(ckt->CKTstate0 + here->VBICibex) * *(ckt->CKTstate0 + here->VBICvbex)) +
fabs(*(ckt->CKTstate0 + here->VBICibep) * *(ckt->CKTstate0 + here->VBICvbep)) +
fabs(*(ckt->CKTstate0 + here->VBICibcp) * *(ckt->CKTstate0 + here->VBICvbcp)) +
fabs(*(ckt->CKTstate0 + here->VBICiccp))
* fabs(*(ckt->CKTstate0 + here->VBICvbep) - *(ckt->CKTstate0 + here->VBICvbcp)) +
fabs(IC.rValue * IC.rValue * here->VBICtextCollResist) +
fabs(IC.rValue * *(ckt->CKTstate0 + here->VBICvrci)) +
fabs(IB.rValue * IB.rValue * here->VBICtextBaseResist) +
fabs(IB.rValue * *(ckt->CKTstate0 + here->VBICvrbi)) +
fabs(IE.rValue * IE.rValue * here->VBICtemitterResist) +
fabs(IS.rValue * *(ckt->CKTstate0 + here->VBICvrbp));
if (IB.rValue != 0.0) {
value->rValue = IC.rValue/IB.rValue;
} else {
value->rValue = 0.0;
}
return(OK);
case VBIC_QUEST_GM:
value->rValue = *(ckt->CKTstate0 + here->VBICitzf_Vbei);
value->rValue = *(ckt->CKTstate0 + here->VBICiciei_Vbei);
return(OK);
case VBIC_QUEST_GO:
value->rValue = *(ckt->CKTstate0 + here->VBICitzf_Vbci);
value->rValue = *(ckt->CKTstate0 + here->VBICiciei_Vbci);
return(OK);
case VBIC_QUEST_GPI:
value->rValue = *(ckt->CKTstate0 + here->VBICibe_Vbei);

View File

@ -104,27 +104,21 @@ VBICbindCSC (GENmodel *inModel, CKTcircuit *ckt)
CREATE_KLU_BINDING_TABLE(VBICtempSubsSIPtr, VBICtempSubsSIBinding, VBICtempNode, VBICsubsSINode);
CREATE_KLU_BINDING_TABLE(VBICtempTempPtr, VBICtempTempBinding, VBICtempNode, VBICtempNode);
if (here->VBIC_excessPhase) {
CREATE_KLU_BINDING_TABLE(VBICtempXf2Ptr, VBICtempXf2Binding, VBICtempNode, VBICxf2Node);
CREATE_KLU_BINDING_TABLE(VBICxf1TempPtr, VBICxf1TempBinding, VBICxf1Node ,VBICtempNode);
CREATE_KLU_BINDING_TABLE(VBICxf1TempPtr, VBICxf1TempBinding, VBICxf1Node, VBICtempNode);
}
}
if (here->VBIC_excessPhase) {
CREATE_KLU_BINDING_TABLE(VBICxf1Xf1Ptr , VBICxf1Xf1Binding , VBICxf1Node , VBICxf1Node);
CREATE_KLU_BINDING_TABLE(VBICxf1Xf2Ptr , VBICxf1Xf2Binding , VBICxf1Node , VBICxf2Node);
CREATE_KLU_BINDING_TABLE(VBICxf1CollCIPtr, VBICxf1CollCIBinding, VBICxf1Node , VBICcollCINode);
CREATE_KLU_BINDING_TABLE(VBICxf1BaseBIPtr, VBICxf1BaseBIBinding, VBICxf1Node , VBICbaseBINode);
CREATE_KLU_BINDING_TABLE(VBICxf1EmitEIPtr, VBICxf1EmitEIBinding, VBICxf1Node , VBICemitEINode);
CREATE_KLU_BINDING_TABLE(VBICxf2Xf2Ptr , VBICxf2Xf2Binding , VBICxf2Node , VBICxf2Node);
CREATE_KLU_BINDING_TABLE(VBICxf2Xf1Ptr , VBICxf2Xf1Binding , VBICxf2Node , VBICxf1Node);
CREATE_KLU_BINDING_TABLE(VBICcollCIXf2Ptr, VBICcollCIXf2Binding, VBICcollCINode, VBICxf2Node);
CREATE_KLU_BINDING_TABLE(VBICbaseBIXf2Ptr, VBICbaseBIXf2Binding, VBICbaseBINode, VBICxf2Node);
CREATE_KLU_BINDING_TABLE(VBICxf1Xf1Ptr, VBICxf1Xf1Binding, VBICxf1Node, VBICxf1Node);
CREATE_KLU_BINDING_TABLE(VBICxf1BaseBIPtr, VBICxf1BaseBIBinding, VBICxf1Node, VBICbaseBINode);
CREATE_KLU_BINDING_TABLE(VBICxf1EmitEIPtr, VBICxf1EmitEIBinding, VBICxf1Node, VBICemitEINode);
CREATE_KLU_BINDING_TABLE(VBICxf1CollCIPtr, VBICxf1CollCIBinding, VBICxf1Node, VBICcollCINode);
CREATE_KLU_BINDING_TABLE(VBICxf1Xf2Ptr, VBICxf1Xf2Binding, VBICxf1Node, VBICxf2Node);
CREATE_KLU_BINDING_TABLE(VBICxf2Xf1Ptr, VBICxf2Xf1Binding, VBICxf2Node, VBICxf1Node);
CREATE_KLU_BINDING_TABLE(VBICxf2Xf2Ptr, VBICxf2Xf2Binding, VBICxf2Node, VBICxf2Node);
CREATE_KLU_BINDING_TABLE(VBICemitEIXf2Ptr, VBICemitEIXf2Binding, VBICemitEINode, VBICxf2Node);
CREATE_KLU_BINDING_TABLE(VBICxf1IbrPtr , VBICxf1IbrBinding , VBICxf1Node , VBICbrEq);
CREATE_KLU_BINDING_TABLE(VBICxf2IbrPtr , VBICxf2IbrBinding , VBICxf2Node , VBICbrEq);
CREATE_KLU_BINDING_TABLE(VBICibrXf2Ptr , VBICibrXf2Binding , VBICbrEq , VBICxf2Node);
CREATE_KLU_BINDING_TABLE(VBICibrXf1Ptr , VBICibrXf1Binding , VBICbrEq , VBICxf1Node);
CREATE_KLU_BINDING_TABLE(VBICibrIbrPtr , VBICibrIbrBinding , VBICbrEq , VBICbrEq);
CREATE_KLU_BINDING_TABLE(VBICcollCIXf2Ptr, VBICcollCIXf2Binding, VBICcollCINode, VBICxf2Node);
}
}
@ -223,25 +217,21 @@ VBICbindCSCComplex (GENmodel *inModel, CKTcircuit *ckt)
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(VBICtempSubsPtr, VBICtempSubsBinding, VBICtempNode, VBICsubsNode);
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(VBICtempSubsSIPtr, VBICtempSubsSIBinding, VBICtempNode, VBICsubsSINode);
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(VBICtempTempPtr, VBICtempTempBinding, VBICtempNode, VBICtempNode);
if (here->VBIC_excessPhase) {
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(VBICxf1Xf1Ptr , VBICxf1Xf1Binding , VBICxf1Node , VBICxf1Node);
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(VBICxf1Xf2Ptr , VBICxf1Xf2Binding , VBICxf1Node , VBICxf2Node);
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(VBICxf1CollCIPtr, VBICxf1CollCIBinding, VBICxf1Node , VBICcollCINode);
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(VBICxf1BaseBIPtr, VBICxf1BaseBIBinding, VBICxf1Node , VBICbaseBINode);
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(VBICxf1EmitEIPtr, VBICxf1EmitEIBinding, VBICxf1Node , VBICemitEINode);
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(VBICxf2Xf2Ptr , VBICxf2Xf2Binding , VBICxf2Node , VBICxf2Node);
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(VBICxf2Xf1Ptr , VBICxf2Xf1Binding , VBICxf2Node , VBICxf1Node);
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(VBICcollCIXf2Ptr, VBICcollCIXf2Binding, VBICcollCINode, VBICxf2Node);
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(VBICbaseBIXf2Ptr, VBICbaseBIXf2Binding, VBICbaseBINode, VBICxf2Node);
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(VBICemitEIXf2Ptr, VBICemitEIXf2Binding, VBICemitEINode, VBICxf2Node);
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(VBICxf1IbrPtr , VBICxf1IbrBinding , VBICxf1Node , VBICbrEq);
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(VBICxf2IbrPtr , VBICxf2IbrBinding , VBICxf2Node , VBICbrEq);
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(VBICibrXf2Ptr , VBICibrXf2Binding , VBICbrEq , VBICxf2Node);
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(VBICibrXf1Ptr , VBICibrXf1Binding , VBICbrEq , VBICxf1Node);
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(VBICibrIbrPtr , VBICibrIbrBinding , VBICbrEq , VBICbrEq);
if (here->VBIC_excessPhase) {
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICxf1TempPtr, VBICxf1TempBinding, VBICxf1Node, VBICtempNode);
}
}
if (here->VBIC_excessPhase) {
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICxf1Xf1Ptr, VBICxf1Xf1Binding, VBICxf1Node, VBICxf1Node);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICxf1BaseBIPtr, VBICxf1BaseBIBinding, VBICxf1Node, VBICbaseBINode);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICxf1EmitEIPtr, VBICxf1EmitEIBinding, VBICxf1Node, VBICemitEINode);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICxf1CollCIPtr, VBICxf1CollCIBinding, VBICxf1Node, VBICcollCINode);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICxf1Xf2Ptr, VBICxf1Xf2Binding, VBICxf1Node, VBICxf2Node);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICxf2Xf1Ptr, VBICxf2Xf1Binding, VBICxf2Node, VBICxf1Node);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICxf2Xf2Ptr, VBICxf2Xf2Binding, VBICxf2Node, VBICxf2Node);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICemitEIXf2Ptr, VBICemitEIXf2Binding, VBICemitEINode, VBICxf2Node);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICcollCIXf2Ptr, VBICcollCIXf2Binding, VBICcollCINode, VBICxf2Node);
}
}
}
@ -339,24 +329,22 @@ VBICbindCSCComplexToReal (GENmodel *inModel, CKTcircuit *ckt)
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICtempSubsPtr, VBICtempSubsBinding, VBICtempNode, VBICsubsNode);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICtempSubsSIPtr, VBICtempSubsSIBinding, VBICtempNode, VBICsubsSINode);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICtempTempPtr, VBICtempTempBinding, VBICtempNode, VBICtempNode);
if (here->VBIC_excessPhase) {
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICxf1TempPtr, VBICxf1TempBinding, VBICxf1Node, VBICtempNode);
}
}
if (here->VBIC_excessPhase) {
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICxf1Xf1Ptr , VBICxf1Xf1Binding , VBICxf1Node , VBICxf1Node);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICxf1Xf2Ptr , VBICxf1Xf2Binding , VBICxf1Node , VBICxf2Node);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICxf1CollCIPtr, VBICxf1CollCIBinding, VBICxf1Node , VBICcollCINode);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICxf1BaseBIPtr, VBICxf1BaseBIBinding, VBICxf1Node , VBICbaseBINode);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICxf1EmitEIPtr, VBICxf1EmitEIBinding, VBICxf1Node , VBICemitEINode);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICxf2Xf2Ptr , VBICxf2Xf2Binding , VBICxf2Node , VBICxf2Node);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICxf2Xf1Ptr , VBICxf2Xf1Binding , VBICxf2Node , VBICxf1Node);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICcollCIXf2Ptr, VBICcollCIXf2Binding, VBICcollCINode, VBICxf2Node);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICbaseBIXf2Ptr, VBICbaseBIXf2Binding, VBICbaseBINode, VBICxf2Node);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICxf1Xf1Ptr, VBICxf1Xf1Binding, VBICxf1Node, VBICxf1Node);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICxf1BaseBIPtr, VBICxf1BaseBIBinding, VBICxf1Node, VBICbaseBINode);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICxf1EmitEIPtr, VBICxf1EmitEIBinding, VBICxf1Node, VBICemitEINode);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICxf1CollCIPtr, VBICxf1CollCIBinding, VBICxf1Node, VBICcollCINode);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICxf1Xf2Ptr, VBICxf1Xf2Binding, VBICxf1Node, VBICxf2Node);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICxf2Xf1Ptr, VBICxf2Xf1Binding, VBICxf2Node, VBICxf1Node);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICxf2Xf2Ptr, VBICxf2Xf2Binding, VBICxf2Node, VBICxf2Node);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICemitEIXf2Ptr, VBICemitEIXf2Binding, VBICemitEINode, VBICxf2Node);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICxf1IbrPtr , VBICxf1IbrBinding , VBICxf1Node , VBICbrEq);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICxf2IbrPtr , VBICxf2IbrBinding , VBICxf2Node , VBICbrEq);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICibrXf2Ptr , VBICibrXf2Binding , VBICbrEq , VBICxf2Node);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICibrXf1Ptr , VBICibrXf1Binding , VBICbrEq , VBICxf1Node);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICibrIbrPtr , VBICibrIbrBinding , VBICbrEq , VBICbrEq);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VBICcollCIXf2Ptr, VBICcollCIXf2Binding, VBICcollCINode, VBICxf2Node);
}
}

View File

@ -33,8 +33,7 @@ VBICconvTest(GENmodel *inModel, CKTcircuit *ckt)
double delvbcp;
double ibehat;
double ibexhat;
double itzfhat;
double itzrhat;
double icieihat;
double ibchat;
double ibephat;
double ircihat;
@ -43,7 +42,7 @@ VBICconvTest(GENmodel *inModel, CKTcircuit *ckt)
double ibcphat;
double iccphat;
double Vbei, Vbex, Vbci, Vbcx, Vbep, Vrci, Vrbi, Vrbp, Vbcp;
double Ibe, Ibex, Itzf, Itzr, Ibc, Ibep, Irci, Irbi, Irbp, Ibcp, Iccp;
double Ibe, Ibex, Iciei, Ibc, Ibep, Irci, Irbi, Irbp, Ibcp, Iccp;
for( ; model != NULL; model = VBICnextModel(model)) {
for(here=VBICinstances(model);here!=NULL;here = VBICnextInstance(here)) {
@ -88,10 +87,8 @@ VBICconvTest(GENmodel *inModel, CKTcircuit *ckt)
*(ckt->CKTstate0 + here->VBICibe_Vbei)*delvbei;
ibexhat = *(ckt->CKTstate0 + here->VBICibex) +
*(ckt->CKTstate0 + here->VBICibex_Vbex)*delvbex;
itzfhat = *(ckt->CKTstate0 + here->VBICitzf) +
*(ckt->CKTstate0 + here->VBICitzf_Vbei)*delvbei + *(ckt->CKTstate0 + here->VBICitzf_Vbci)*delvbci;
itzrhat = *(ckt->CKTstate0 + here->VBICitzr) +
*(ckt->CKTstate0 + here->VBICitzr_Vbei)*delvbei + *(ckt->CKTstate0 + here->VBICitzr_Vbci)*delvbci;
icieihat = *(ckt->CKTstate0 + here->VBICiciei) +
*(ckt->CKTstate0 + here->VBICiciei_Vbei)*delvbei + *(ckt->CKTstate0 + here->VBICiciei_Vbci)*delvbci;
ibchat = *(ckt->CKTstate0 + here->VBICibc) +
*(ckt->CKTstate0 + here->VBICibc_Vbei)*delvbei + *(ckt->CKTstate0 + here->VBICibc_Vbci)*delvbci;
ibephat = *(ckt->CKTstate0 + here->VBICibep) +
@ -108,8 +105,7 @@ VBICconvTest(GENmodel *inModel, CKTcircuit *ckt)
*(ckt->CKTstate0 + here->VBICiccp_Vbci)*delvbci + *(ckt->CKTstate0 + here->VBICiccp_Vbcp)*delvbcp;
Ibe = *(ckt->CKTstate0 + here->VBICibe);
Ibex = *(ckt->CKTstate0 + here->VBICibex);
Itzf = *(ckt->CKTstate0 + here->VBICitzf);
Itzr = *(ckt->CKTstate0 + here->VBICitzr);
Iciei = *(ckt->CKTstate0 + here->VBICiciei);
Ibc = *(ckt->CKTstate0 + here->VBICibc);
Ibep = *(ckt->CKTstate0 + here->VBICibep);
Irci = *(ckt->CKTstate0 + here->VBICirci);
@ -132,60 +128,53 @@ VBICconvTest(GENmodel *inModel, CKTcircuit *ckt)
ckt->CKTtroubleElt = (GENinstance *) here;
return(OK); /* no reason to continue - we've failed... */
} else {
tol=ckt->CKTreltol*MAX(fabs(itzfhat),fabs(Itzf))+ckt->CKTabstol;
if (fabs(itzfhat-Itzf) > tol) {
tol=ckt->CKTreltol*MAX(fabs(icieihat),fabs(Iciei))+ckt->CKTabstol;
if (fabs(icieihat-Iciei) > tol) {
ckt->CKTnoncon++;
ckt->CKTtroubleElt = (GENinstance *) here;
return(OK); /* no reason to continue - we've failed... */
} else {
tol=ckt->CKTreltol*MAX(fabs(itzrhat),fabs(Itzr))+ckt->CKTabstol;
if (fabs(itzrhat-Itzr) > tol) {
tol=ckt->CKTreltol*MAX(fabs(ibchat),fabs(Ibc))+ckt->CKTabstol;
if (fabs(ibchat-Ibc) > tol) {
ckt->CKTnoncon++;
ckt->CKTtroubleElt = (GENinstance *) here;
return(OK); /* no reason to continue - we've failed... */
} else {
tol=ckt->CKTreltol*MAX(fabs(ibchat),fabs(Ibc))+ckt->CKTabstol;
if (fabs(ibchat-Ibc) > tol) {
tol=ckt->CKTreltol*MAX(fabs(ibephat),fabs(Ibep))+ckt->CKTabstol;
if (fabs(ibephat-Ibep) > tol) {
ckt->CKTnoncon++;
ckt->CKTtroubleElt = (GENinstance *) here;
return(OK); /* no reason to continue - we've failed... */
} else {
tol=ckt->CKTreltol*MAX(fabs(ibephat),fabs(Ibep))+ckt->CKTabstol;
if (fabs(ibephat-Ibep) > tol) {
tol=ckt->CKTreltol*MAX(fabs(ircihat),fabs(Irci))+ckt->CKTabstol;
if (fabs(ircihat-Irci) > tol) {
ckt->CKTnoncon++;
ckt->CKTtroubleElt = (GENinstance *) here;
return(OK); /* no reason to continue - we've failed... */
} else {
tol=ckt->CKTreltol*MAX(fabs(ircihat),fabs(Irci))+ckt->CKTabstol;
if (fabs(ircihat-Irci) > tol) {
tol=ckt->CKTreltol*MAX(fabs(irbihat),fabs(Irbi))+ckt->CKTabstol;
if (fabs(irbihat-Irbi) > tol) {
ckt->CKTnoncon++;
ckt->CKTtroubleElt = (GENinstance *) here;
return(OK); /* no reason to continue - we've failed... */
} else {
tol=ckt->CKTreltol*MAX(fabs(irbihat),fabs(Irbi))+ckt->CKTabstol;
if (fabs(irbihat-Irbi) > tol) {
tol=ckt->CKTreltol*MAX(fabs(irbphat),fabs(Irbp))+ckt->CKTabstol;
if (fabs(irbphat-Irbp) > tol) {
ckt->CKTnoncon++;
ckt->CKTtroubleElt = (GENinstance *) here;
return(OK); /* no reason to continue - we've failed... */
} else {
tol=ckt->CKTreltol*MAX(fabs(irbphat),fabs(Irbp))+ckt->CKTabstol;
if (fabs(irbphat-Irbp) > tol) {
tol=ckt->CKTreltol*MAX(fabs(ibcphat),fabs(Ibcp))+ckt->CKTabstol;
if (fabs(ibcphat-Ibcp) > tol) {
ckt->CKTnoncon++;
ckt->CKTtroubleElt = (GENinstance *) here;
return(OK); /* no reason to continue - we've failed... */
} else {
tol=ckt->CKTreltol*MAX(fabs(ibcphat),fabs(Ibcp))+ckt->CKTabstol;
if (fabs(ibcphat-Ibcp) > tol) {
tol=ckt->CKTreltol*MAX(fabs(iccphat),fabs(Iccp))+ckt->CKTabstol;
if (fabs(iccphat-Iccp) > tol) {
ckt->CKTnoncon++;
ckt->CKTtroubleElt = (GENinstance *) here;
return(OK); /* no reason to continue - we've failed... */
} else {
tol=ckt->CKTreltol*MAX(fabs(iccphat),fabs(Iccp))+ckt->CKTabstol;
if (fabs(iccphat-Iccp) > tol) {
ckt->CKTnoncon++;
ckt->CKTtroubleElt = (GENinstance *) here;
return(OK); /* no reason to continue - we've failed... */
}
}
}
}

View File

@ -62,7 +62,6 @@ typedef struct sVBICinstance {
int VBICsubsSINode; /* number of internal substrate node */
int VBICxf1Node; /* number of internal excess phase 1 node itf */
int VBICxf2Node; /* number of internal excess phase 2 node itf */
int VBICbrEq; /* number of the branch equation added for current */
double VBICarea; /* area factor for the vbic */
double VBICicVBE; /* initial condition voltage B-E*/
@ -241,26 +240,22 @@ typedef struct sVBICinstance {
double *VBICtempTempPtr;
/* excess phase */
double *VBICtempXf2Ptr;
double *VBICxf1TempPtr;
double *VBICxf1Xf1Ptr;
double *VBICxf1Xf2Ptr;
double *VBICxf1CollCIPtr;
double *VBICxf1TempPtr;
double *VBICxf1BaseBIPtr;
double *VBICxf1EmitEIPtr;
double *VBICxf1CollCIPtr;
double *VBICxf1Xf2Ptr;
double *VBICxf2Xf2Ptr;
double *VBICxf2Xf1Ptr;
double *VBICcollCIXf2Ptr;
double *VBICbaseBIXf2Ptr;
double *VBICxf2TempPtr;
double *VBICxf2BaseBIPtr;
double *VBICxf2EmitEIPtr;
double *VBICxf2CollCIPtr;
double *VBICxf2Xf2Ptr;
double *VBICemitXf2Ptr;
double *VBICemitEIXf2Ptr;
double *VBICxf1IbrPtr;
double *VBICxf2IbrPtr;
double *VBICibrXf1Ptr;
double *VBICibrXf2Ptr;
double *VBICibrIbrPtr;
double *VBICcollCIXf2Ptr;
unsigned VBICareaGiven :1; /* flag to indicate area was specified */
unsigned VBICoff :1; /* 'off' flag for vbic */
@ -287,8 +282,6 @@ typedef struct sVBICinstance {
double VBICibe_Vrth;
double VBICibex_Vrth;
double VBICitzf_vrth;
double VBICitzr_Vrth;
double VBICibc_Vrth;
double VBICibep_Vrth;
double VBICircx_Vrth;
@ -319,8 +312,7 @@ typedef struct sVBICinstance {
double VBICith_Vre;
double VBICith_Vrs;
double VBICindInduct;
double VBICcapQcxf;
double VBICpower;
int VBIC_selfheat; /* self-heating enabled */
int VBIC_excessPhase; /* excess phase enabled */
@ -411,24 +403,17 @@ typedef struct sVBICinstance {
BindElement *VBICtempSubsSIBinding ;
BindElement *VBICtempTempBinding ;
BindElement *VBICtempXf2Binding ;
BindElement *VBICxf1TempBinding ;
BindElement *VBICcollCIXf2Binding ;
BindElement *VBICemitEIXf2Binding ;
BindElement *VBICxf1BaseBIBinding ;
BindElement *VBICxf1CollCIBinding ;
BindElement *VBICxf1EmitEIBinding ;
BindElement *VBICxf1TempBinding ;
BindElement *VBICxf1Xf1Binding ;
BindElement *VBICxf1Xf2Binding ;
BindElement *VBICxf1CollCIBinding ;
BindElement *VBICxf1BaseBIBinding ;
BindElement *VBICxf1EmitEIBinding ;
BindElement *VBICxf2Xf2Binding ;
BindElement *VBICxf2Xf1Binding ;
BindElement *VBICcollCIXf2Binding ;
BindElement *VBICbaseBIXf2Binding ;
BindElement *VBICemitEIXf2Binding ;
BindElement *VBICxf1IbrBinding ;
BindElement *VBICxf2IbrBinding ;
BindElement *VBICibrXf2Binding ;
BindElement *VBICibrXf1Binding ;
BindElement *VBICibrIbrBinding ;
BindElement *VBICxf2Xf2Binding ;
#endif
} VBICinstance ;
@ -444,21 +429,20 @@ typedef struct sVBICinstance {
#define VBICvrbi VBICstate+6
#define VBICvrbp VBICstate+7
#define VBICvbcp VBICstate+8
#define VBICvxf1 VBICstate+9
#define VBICvxf2 VBICstate+10
#define VBICibe VBICstate+9
#define VBICibe_Vbei VBICstate+10
#define VBICibe VBICstate+11
#define VBICibe_Vbei VBICstate+12
#define VBICibex VBICstate+11
#define VBICibex_Vbex VBICstate+12
#define VBICibex VBICstate+13
#define VBICibex_Vbex VBICstate+14
#define VBICitzf VBICstate+13
#define VBICitzf_Vbei VBICstate+14
#define VBICitzf_Vbci VBICstate+15
#define VBICitzf_Vrth VBICstate+16
#define VBICitzr VBICstate+17
#define VBICitzr_Vbci VBICstate+18
#define VBICitzr_Vbei VBICstate+19
#define VBICiciei VBICstate+15
#define VBICiciei_Vbei VBICstate+16
#define VBICiciei_Vbci VBICstate+17
#define VBICiciei_Vrth VBICstate+18
#define VBICiciei_Vxf2 VBICstate+19
#define VBICibc VBICstate+20
#define VBICibc_Vbci VBICstate+21
@ -482,7 +466,6 @@ typedef struct sVBICinstance {
#define VBICirbp_Vbep VBICstate+35
#define VBICirbp_Vbci VBICstate+36
#define VBICqbe VBICstate+37
#define VBICcqbe VBICstate+38
#define VBICcqbeci VBICstate+39
@ -530,26 +513,24 @@ typedef struct sVBICinstance {
#define VBICvrth VBICstate+69
#define VBICicth_Vrth VBICstate+70
#define VBICqcxf VBICstate+71
#define VBICcqcxf VBICstate+72
#define VBICgqcxf VBICstate+73
#define VBICqxf1 VBICstate+71
#define VBICcqxf1 VBICstate+72
#define VBICgqxf1 VBICstate+73
#define VBICibc_Vrxf VBICstate+74
#define VBICixf1 VBICstate+74
#define VBICixf1_Vbei VBICstate+75
#define VBICixf1_Vbci VBICstate+76
#define VBICixf1_Vxf1 VBICstate+77
#define VBICixf1_Vxf2 VBICstate+78
#define VBICixf1_Vrth VBICstate+79
#define VBICixzf VBICstate+75
#define VBICixzf_Vbei VBICstate+76
#define VBICixzf_Vbci VBICstate+77
#define VBICixzf_Vrth VBICstate+78
#define VBICqxf2 VBICstate+80
#define VBICcqxf2 VBICstate+81
#define VBICgqxf2 VBICstate+82
#define VBICixxf VBICstate+79
#define VBICixxf_Vrxf VBICstate+80
#define VBICitxf VBICstate+81
#define VBICitxf_Vrxf VBICstate+82
#define VBICith_Vrxf VBICstate+83
#define VBICindFlux VBICstate+84
#define VBICindVolt VBICstate+85
#define VBICixf2 VBICstate+83
#define VBICixf2_Vxf1 VBICstate+84
#define VBICixf2_Vxf2 VBICstate+85
#define VBICnumStates 86
@ -945,8 +926,7 @@ enum {
/* device questions */
enum {
VBIC_QUEST_FT = 221,
VBIC_QUEST_COLLNODE,
VBIC_QUEST_COLLNODE = 221,
VBIC_QUEST_BASENODE,
VBIC_QUEST_EMITNODE,
VBIC_QUEST_SUBSNODE,
@ -963,31 +943,21 @@ enum {
VBIC_QUEST_CB,
VBIC_QUEST_CE,
VBIC_QUEST_CS,
VBIC_QUEST_POWER,
VBIC_QUEST_BETA,
VBIC_QUEST_GM,
VBIC_QUEST_GO,
VBIC_QUEST_GPI,
VBIC_QUEST_GMU,
VBIC_QUEST_GX,
VBIC_QUEST_QBE,
VBIC_QUEST_CQBE,
VBIC_QUEST_QBC,
VBIC_QUEST_CQBC,
VBIC_QUEST_QBX,
VBIC_QUEST_CQBX,
VBIC_QUEST_QBCP,
VBIC_QUEST_CQBCP,
VBIC_QUEST_CEXBC,
VBIC_QUEST_GEQCB,
VBIC_QUEST_GCSUB,
VBIC_QUEST_GDSUB,
VBIC_QUEST_GEQBX,
VBIC_QUEST_CBE,
VBIC_QUEST_CBEX,
VBIC_QUEST_CBC,
VBIC_QUEST_CBCX,
VBIC_QUEST_CBEP,
VBIC_QUEST_CBCP,
VBIC_QUEST_POWER,
VBIC_QUEST_QBE,
VBIC_QUEST_QBC,
};
/* model questions */

File diff suppressed because it is too large Load Diff

View File

@ -127,16 +127,10 @@ VBICnoise (int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt, Ndata *
ckt,THERMNOISE,inst->VBICsubsSINode,inst->VBICsubsNode,
*(ckt->CKTstate0 + inst->VBICirs_Vrs), dtemp);
if (!inst->VBIC_excessPhase) {
NevalSrc(&noizDens[VBICICNOIZ],&lnNdens[VBICICNOIZ],
ckt,SHOTNOISE,inst->VBICcollCINode, inst->VBICemitEINode,
*(ckt->CKTstate0 + inst->VBICitzf));
}
if (inst->VBIC_excessPhase) {
NevalSrc(&noizDens[VBICICNOIZ],&lnNdens[VBICICNOIZ],
ckt,SHOTNOISE,inst->VBICcollCINode, inst->VBICemitEINode,
*(ckt->CKTstate0 + inst->VBICitxf));
}
NevalSrc(&noizDens[VBICICNOIZ],&lnNdens[VBICICNOIZ],
ckt,SHOTNOISE,inst->VBICcollCINode, inst->VBICemitEINode,
*(ckt->CKTstate0 + inst->VBICiciei));
NevalSrc(&noizDens[VBICIBNOIZ],&lnNdens[VBICIBNOIZ],
ckt,SHOTNOISE,inst->VBICbaseBINode, inst->VBICemitEINode,
*(ckt->CKTstate0 + inst->VBICibe));

View File

@ -23,7 +23,7 @@ VBICpzLoad(GENmodel *inModel, CKTcircuit *ckt, SPcomplex *s)
VBICinstance *here;
VBICmodel *model = (VBICmodel*)inModel;
double Ibe_Vbei,Ibex_Vbex
,Itzf_Vbei,Itzf_Vbci,Itzr_Vbci,Itzr_Vbei,Ibc_Vbci
,Iciei_Vbei,Iciei_Vbci,Ibc_Vbci
,Ibc_Vbei,Ibep_Vbep,Ircx_Vrcx,Irci_Vrci
,Irci_Vbci,Irci_Vbcx,Irbx_Vrbx,Irbi_Vrbi,Irbi_Vbei
,Irbi_Vbci,Ire_Vre,Irbp_Vrbp,Irbp_Vbep,Irbp_Vbci
@ -32,7 +32,7 @@ VBICpzLoad(GENmodel *inModel, CKTcircuit *ckt, SPcomplex *s)
XQbcx_Vbcx, XQbep_Vbep, XQbep_Vbci,
XQbcp_Vbcp, XQbeo_Vbe, XQbco_Vbc;
double Ibe_Vrth, Ibex_Vrth, Itzf_Vrth=0.0, Itzr_Vrth, Ibc_Vrth, Ibep_Vrth,
double Ibe_Vrth, Ibex_Vrth, Iciei_Vrth, Iciei_Vxf2, Ibc_Vrth, Ibep_Vrth,
Ircx_Vrth, Irci_Vrth, Irbx_Vrth, Irbi_Vrth, Ire_Vrth, Irbp_Vrth,
Ibcp_Vrth, Iccp_Vrth, Irs_Vrth, Irth_Vrth, Ith_Vrth,
Ith_Vbei, Ith_Vbci, Ith_Vcei, Ith_Vbex, Ith_Vbep, Ith_Vbcp, Ith_Vcep,
@ -40,22 +40,31 @@ VBICpzLoad(GENmodel *inModel, CKTcircuit *ckt, SPcomplex *s)
double XQcth_Vrth, XQbe_Vrth, XQbex_Vrth, XQbc_Vrth, XQbcx_Vrth, XQbep_Vrth, XQbcp_Vrth;
//NQS
double Itxf_Vrxf, Ibc_Vrxf, Ith_Vrxf, Ixzf_Vrth, Ixxf_Vrxf, XQcxf_Vcxf;
double Ixzf_Vbei, Ixzf_Vbci, Xl;
double XQxf1_Vxf1;
double XQxf2_Vxf2;
double Ixf1_Vbei;
double Ixf1_Vbci;
double Ixf1_Vxf2;
double Ixf1_Vxf1;
double Ixf1_Vrth;
double Ixf2_Vxf2;
double Ixf2_Vxf1;
/* loop through all the models */
for( ; model != NULL; model = VBICnextModel(model)) {
/* loop through all the instances of the model */
for( here = VBICinstances(model); here!= NULL;
for( here = VBICinstances(model); here!= NULL;
here = VBICnextInstance(here)) {
Ibe_Vbei = *(ckt->CKTstate0 + here->VBICibe_Vbei);
Ibex_Vbex = *(ckt->CKTstate0 + here->VBICibex_Vbex);
Itzf_Vbei = *(ckt->CKTstate0 + here->VBICitzf_Vbei);
Itzf_Vbci = *(ckt->CKTstate0 + here->VBICitzf_Vbci);
Itzr_Vbci = *(ckt->CKTstate0 + here->VBICitzr_Vbci);
Itzr_Vbei = *(ckt->CKTstate0 + here->VBICitzr_Vbei);
Iciei_Vbei = *(ckt->CKTstate0 + here->VBICiciei_Vbei);
Iciei_Vbci = *(ckt->CKTstate0 + here->VBICiciei_Vbci);
Iciei_Vrth = *(ckt->CKTstate0 + here->VBICiciei_Vrth);
Iciei_Vxf2 = *(ckt->CKTstate0 + here->VBICiciei_Vxf2);
Ibc_Vbci = *(ckt->CKTstate0 + here->VBICibc_Vbci);
Ibc_Vbei = *(ckt->CKTstate0 + here->VBICibc_Vbei);
Ibep_Vbep = *(ckt->CKTstate0 + here->VBICibep_Vbep);
@ -77,6 +86,15 @@ VBICpzLoad(GENmodel *inModel, CKTcircuit *ckt, SPcomplex *s)
Irs_Vrs = *(ckt->CKTstate0 + here->VBICirs_Vrs);
Ire_Vre = *(ckt->CKTstate0 + here->VBICire_Vre);
Ixf1_Vbei = *(ckt->CKTstate0 + here->VBICixf1_Vbei);
Ixf1_Vbci = *(ckt->CKTstate0 + here->VBICixf1_Vbci);
Ixf1_Vxf2 = *(ckt->CKTstate0 + here->VBICixf1_Vxf2);
Ixf1_Vxf1 = *(ckt->CKTstate0 + here->VBICixf1_Vxf1);
Ixf1_Vrth = *(ckt->CKTstate0 + here->VBICixf1_Vrth);
Ixf2_Vxf2 = *(ckt->CKTstate0 + here->VBICixf2_Vxf2);
Ixf2_Vxf1 = *(ckt->CKTstate0 + here->VBICixf2_Vxf1);
/*
c The real part
*/
@ -94,32 +112,22 @@ c Stamp element: Ibex
*(here->VBICbaseBXEmitEIPtr) += -Ibex_Vbex;
*(here->VBICemitEIBaseBXPtr) += -Ibex_Vbex;
*(here->VBICemitEIEmitEIPtr) += Ibex_Vbex;
if (!here->VBIC_excessPhase) {
/*
c Stamp element: Itzf
c Stamp element: Iciei
*/
*(here->VBICcollCIBaseBIPtr) += Itzf_Vbei;
*(here->VBICcollCIEmitEIPtr) += -Itzf_Vbei;
*(here->VBICcollCIBaseBIPtr) += Itzf_Vbci;
*(here->VBICcollCICollCIPtr) += -Itzf_Vbci;
*(here->VBICemitEIBaseBIPtr) += -Itzf_Vbei;
*(here->VBICemitEIEmitEIPtr) += Itzf_Vbei;
*(here->VBICemitEIBaseBIPtr) += -Itzf_Vbci;
*(here->VBICemitEICollCIPtr) += Itzf_Vbci;
*(here->VBICcollCIBaseBIPtr) += Iciei_Vbei;
*(here->VBICcollCIEmitEIPtr) += -Iciei_Vbei;
*(here->VBICcollCIBaseBIPtr) += Iciei_Vbci;
*(here->VBICcollCICollCIPtr) += -Iciei_Vbci;
*(here->VBICemitEIBaseBIPtr) += -Iciei_Vbei;
*(here->VBICemitEIEmitEIPtr) += Iciei_Vbei;
*(here->VBICemitEIBaseBIPtr) += -Iciei_Vbci;
*(here->VBICemitEICollCIPtr) += Iciei_Vbci;
if (here->VBIC_excessPhase) {
*(here->VBICcollCIXf2Ptr) += Iciei_Vxf2;
*(here->VBICemitEIXf2Ptr) += -Iciei_Vxf2;
}
/*
c Stamp element: Itzr
*/
*(here->VBICemitEIBaseBIPtr) += Itzr_Vbci;
*(here->VBICemitEICollCIPtr) += -Itzr_Vbci;
*(here->VBICemitEIBaseBIPtr) += Itzr_Vbei;
*(here->VBICemitEIEmitEIPtr) += -Itzr_Vbei;
*(here->VBICcollCIBaseBIPtr) += -Itzr_Vbci;
*(here->VBICcollCICollCIPtr) += Itzr_Vbci;
*(here->VBICcollCIBaseBIPtr) += -Itzr_Vbei;
*(here->VBICcollCIEmitEIPtr) += Itzr_Vbei;
/*
c Stamp element: Ibc
*/
*(here->VBICbaseBIBaseBIPtr) += Ibc_Vbci;
@ -138,14 +146,14 @@ c Stamp element: Ibep
*(here->VBICbaseBPBaseBXPtr) += -Ibep_Vbep;
*(here->VBICbaseBPBaseBPPtr) += Ibep_Vbep;
/*
c Stamp element: Ircx
c Stamp element: Rcx
*/
*(here->VBICcollCollPtr) += Ircx_Vrcx;
*(here->VBICcollCXCollCXPtr) += Ircx_Vrcx;
*(here->VBICcollCXCollPtr) += -Ircx_Vrcx;
*(here->VBICcollCollCXPtr) += -Ircx_Vrcx;
/*
c Stamp element: Irci
c Stamp element: Rci
*/
*(here->VBICcollCXCollCXPtr) += Irci_Vrci;
*(here->VBICcollCXCollCIPtr) += -Irci_Vrci;
@ -160,14 +168,14 @@ c Stamp element: Irci
*(here->VBICcollCIBaseBIPtr) += -Irci_Vbcx;
*(here->VBICcollCICollCXPtr) += Irci_Vbcx;
/*
c Stamp element: Irbx
c Stamp element: Rbx
*/
*(here->VBICbaseBasePtr) += Irbx_Vrbx;
*(here->VBICbaseBXBaseBXPtr) += Irbx_Vrbx;
*(here->VBICbaseBXBasePtr) += -Irbx_Vrbx;
*(here->VBICbaseBaseBXPtr) += -Irbx_Vrbx;
/*
c Stamp element: Irbi
c Stamp element: Rbi
*/
*(here->VBICbaseBXBaseBXPtr) += Irbi_Vrbi;
*(here->VBICbaseBXBaseBIPtr) += -Irbi_Vrbi;
@ -182,14 +190,14 @@ c Stamp element: Irbi
*(here->VBICbaseBIBaseBIPtr) += -Irbi_Vbci;
*(here->VBICbaseBICollCIPtr) += Irbi_Vbci;
/*
c Stamp element: Ire
c Stamp element: Re
*/
*(here->VBICemitEmitPtr) += Ire_Vre;
*(here->VBICemitEIEmitEIPtr) += Ire_Vre;
*(here->VBICemitEIEmitPtr) += -Ire_Vre;
*(here->VBICemitEmitEIPtr) += -Ire_Vre;
/*
c Stamp element: Irbp
c Stamp element: Rbp
*/
*(here->VBICbaseBPBaseBPPtr) += Irbp_Vrbp;
*(here->VBICbaseBPCollCXPtr) += -Irbp_Vrbp;
@ -226,7 +234,7 @@ c Stamp element: Iccp
*(here->VBICsubsSISubsSIPtr) += -Iccp_Vbcp;
*(here->VBICsubsSIBaseBPPtr) += Iccp_Vbcp;
/*
c Stamp element: Irs
c Stamp element: Rs
*/
*(here->VBICsubsSubsPtr) += Irs_Vrs;
*(here->VBICsubsSISubsSIPtr) += Irs_Vrs;
@ -237,9 +245,6 @@ c Stamp element: Irs
Ibe_Vrth = here->VBICibe_Vrth;
Ibex_Vrth = here->VBICibex_Vrth;
if (!here->VBIC_excessPhase)
Itzf_Vrth = here->VBICitzf_vrth;
Itzr_Vrth = here->VBICitzr_Vrth;
Ibc_Vrth = here->VBICibc_Vrth;
Ibep_Vrth = here->VBICibep_Vrth;
Ircx_Vrth = here->VBICircx_Vrth;
@ -279,19 +284,11 @@ c Stamp element: Ibex
*/
*(here->VBICbaseBXtempPtr) += Ibex_Vrth;
*(here->VBICemitEItempPtr) += -Ibex_Vrth;
if (!here->VBIC_excessPhase) {
/*
c Stamp element: Itzf
c Stamp element: Iciei
*/
*(here->VBICcollCItempPtr) += Itzf_Vrth;
*(here->VBICemitEItempPtr) += -Itzf_Vrth;
}
/*
c Stamp element: Itzr
*/
*(here->VBICemitEItempPtr) += Itzr_Vrth;
*(here->VBICcollCItempPtr) += -Itzr_Vrth;
*(here->VBICcollCItempPtr) += Iciei_Vrth;
*(here->VBICemitEItempPtr) += -Iciei_Vrth;
/*
c Stamp element: Ibc
*/
@ -386,44 +383,19 @@ c Stamp element: Ith
*(here->VBICtempEmitEIPtr) += +Ith_Vre;
*(here->VBICtempSubsPtr) += -Ith_Vrs;
*(here->VBICtempSubsSIPtr) += +Ith_Vrs;
if (here->VBIC_excessPhase) {
Ith_Vrxf = *(ckt->CKTstate0 + here->VBICith_Vrxf);
*(here->VBICtempXf2Ptr) += +Ith_Vrxf;
}
}
if (here->VBIC_excessPhase) {
Itxf_Vrxf = *(ckt->CKTstate0 + here->VBICitxf_Vrxf);
Ibc_Vrxf = *(ckt->CKTstate0 + here->VBICibc_Vrxf);
Ixzf_Vbei = *(ckt->CKTstate0 + here->VBICixzf_Vbei);
Ixzf_Vbci = *(ckt->CKTstate0 + here->VBICixzf_Vbci);
Ixxf_Vrxf = *(ckt->CKTstate0 + here->VBICixxf_Vrxf);
/*
c Stamp element: Itxf
*/
*(here->VBICcollCIXf2Ptr) += Itxf_Vrxf;
*(here->VBICemitEIXf2Ptr) += -Itxf_Vrxf;
/*
c Stamp element: Ibc
*/
*(here->VBICbaseBIXf2Ptr) += Ibc_Vrxf;
*(here->VBICcollCIXf2Ptr) += -Ibc_Vrxf;
/*
c Stamp element: Ixzf, Branch: xf1-ground
*/
*(here->VBICxf1BaseBIPtr) += +Ixzf_Vbei;
*(here->VBICxf1EmitEIPtr) += -Ixzf_Vbei;
*(here->VBICxf1BaseBIPtr) += +Ixzf_Vbci;
*(here->VBICxf1CollCIPtr) += -Ixzf_Vbci;
if (here->VBIC_selfheat) {
Ixzf_Vrth = *(ckt->CKTstate0 + here->VBICixzf_Vrth);
*(here->VBICxf1TempPtr) += Ixzf_Vrth;
}
/*
c Stamp element: Ixxf, Branch: xf2-ground
*/
*(here->VBICxf2Xf2Ptr) += +Ixxf_Vrxf;
//Ixf1
*(here->VBICxf1BaseBIPtr) += +Ixf1_Vbei;
*(here->VBICxf1EmitEIPtr) += -Ixf1_Vbei;
*(here->VBICxf1BaseBIPtr) += +Ixf1_Vbci;
*(here->VBICxf1CollCIPtr) += -Ixf1_Vbci;
*(here->VBICxf1Xf2Ptr) += +Ixf1_Vxf2;
*(here->VBICxf1Xf1Ptr) += +Ixf1_Vxf1;
//Ixf2
*(here->VBICxf2Xf2Ptr) += +Ixf2_Vxf2;
*(here->VBICxf2Xf1Ptr) += +Ixf2_Vxf1;
}
/*
@ -439,6 +411,8 @@ c The complex part
XQbcp_Vbcp = *(ckt->CKTstate0 + here->VBICcqbcp);
XQbeo_Vbe = *(ckt->CKTstate0 + here->VBICcqbeo);
XQbco_Vbc = *(ckt->CKTstate0 + here->VBICcqbco);
XQxf1_Vxf1 = *(ckt->CKTstate0 + here->VBICcqxf1);
XQxf2_Vxf2 = *(ckt->CKTstate0 + here->VBICcqxf2);
/*
c Stamp element: Qbe
*/
@ -545,6 +519,14 @@ c Stamp element: Qbco
*(here->VBICcollBasePtr ) += -XQbco_Vbc * (s->real);
*(here->VBICcollBasePtr + 1) += -XQbco_Vbc * (s->imag);
if (here->VBIC_excessPhase) {
//Qxf1
*(here->VBICxf1Xf1Ptr + 1) += +XQxf1_Vxf1*(s->imag);
*(here->VBICxf1Xf1Ptr) += +XQxf1_Vxf1*(s->real);
//Qxf2
*(here->VBICxf2Xf2Ptr + 1) += +XQxf2_Vxf2*(s->imag);
*(here->VBICxf2Xf2Ptr ) += +XQxf2_Vxf2*(s->real);
}
if (here->VBIC_selfheat) {
XQcth_Vrth = here->VBICcapcth;
XQbe_Vrth = here->VBICcapqbeth;
@ -581,28 +563,12 @@ c Stamp element: Qbco
*(here->VBICsubsSItempPtr + 1) += XQbcp_Vrth * (s->imag);
*(here->VBICbaseBPtempPtr ) += -XQbcp_Vrth * (s->real);
*(here->VBICbaseBPtempPtr + 1) += -XQbcp_Vrth * (s->imag);
if (here->VBIC_excessPhase) {
// Stamp element: Ixf1 f_xf1 = +
*(here->VBICxf1TempPtr) += Ixf1_Vrth;
}
}
if (here->VBIC_excessPhase) {
/*
c Stamp element: Qcxf
*/
XQcxf_Vcxf = here->VBICcapQcxf;
*(here->VBICxf1Xf1Ptr ) += XQcxf_Vcxf * s->real;
*(here->VBICxf1Xf1Ptr + 1) += XQcxf_Vcxf * s->imag;
/*
c Stamp element: L = TD/3
*/
Xl = here->VBICindInduct;
*(here->VBICxf1IbrPtr) += 1;
*(here->VBICxf2IbrPtr) -= 1;
*(here->VBICibrXf1Ptr) += 1;
*(here->VBICibrXf2Ptr) -= 1;
*(here->VBICibrIbrPtr ) -= Xl * s->real;
*(here->VBICibrIbrPtr + 1) -= Xl * s->imag;
}
}
}
return(OK);

View File

@ -483,7 +483,6 @@ VBICsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
model->VBICthermalCapacitance = 1e-12;
if((model->VBICdelayTimeFGiven) && (model->VBICdelayTimeF > 0.0)) {
here->VBICindInduct = model->VBICdelayTimeF / 3.0 / here->VBICm;
here->VBIC_excessPhase = 1;
} else {
here->VBIC_excessPhase = 0;
@ -518,11 +517,6 @@ VBICsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
if(error) return(error);
here->VBICxf2Node = tmp->number;
}
if(here->VBICbrEq == 0) {
error = CKTmkCur(ckt,&tmp,here->VBICname,"branch");
if(error) return(error);
here->VBICbrEq = tmp->number;
}
} else {
here->VBICxf1Node = 0;
here->VBICxf2Node = 0;
@ -612,27 +606,21 @@ do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\
TSTALLOC(VBICtempSubsSIPtr,VBICtempNode,VBICsubsSINode);
TSTALLOC(VBICtempTempPtr,VBICtempNode,VBICtempNode);
if (here->VBIC_excessPhase) {
TSTALLOC(VBICtempXf2Ptr, VBICtempNode, VBICxf2Node);
TSTALLOC(VBICxf1TempPtr, VBICxf1Node ,VBICtempNode);
TSTALLOC(VBICxf1TempPtr ,VBICxf1Node ,VBICtempNode);
}
}
if (here->VBIC_excessPhase) {
TSTALLOC(VBICxf1Xf1Ptr , VBICxf1Node , VBICxf1Node);
TSTALLOC(VBICxf1Xf2Ptr , VBICxf1Node , VBICxf2Node);
TSTALLOC(VBICxf1CollCIPtr, VBICxf1Node , VBICcollCINode);
TSTALLOC(VBICxf1BaseBIPtr, VBICxf1Node , VBICbaseBINode);
TSTALLOC(VBICxf1EmitEIPtr, VBICxf1Node , VBICemitEINode);
TSTALLOC(VBICxf2Xf2Ptr , VBICxf2Node , VBICxf2Node);
TSTALLOC(VBICxf2Xf1Ptr , VBICxf2Node , VBICxf1Node);
TSTALLOC(VBICcollCIXf2Ptr, VBICcollCINode, VBICxf2Node);
TSTALLOC(VBICbaseBIXf2Ptr, VBICbaseBINode, VBICxf2Node);
TSTALLOC(VBICemitEIXf2Ptr, VBICemitEINode, VBICxf2Node);
TSTALLOC(VBICxf1IbrPtr, VBICxf1Node, VBICbrEq);
TSTALLOC(VBICxf2IbrPtr, VBICxf2Node, VBICbrEq);
TSTALLOC(VBICibrXf2Ptr, VBICbrEq, VBICxf2Node);
TSTALLOC(VBICibrXf1Ptr, VBICbrEq, VBICxf1Node);
TSTALLOC(VBICibrIbrPtr, VBICbrEq, VBICbrEq);
TSTALLOC(VBICxf1Xf1Ptr ,VBICxf1Node ,VBICxf1Node);
TSTALLOC(VBICxf1BaseBIPtr,VBICxf1Node ,VBICbaseBINode);
TSTALLOC(VBICxf1EmitEIPtr,VBICxf1Node ,VBICemitEINode);
TSTALLOC(VBICxf1CollCIPtr,VBICxf1Node ,VBICcollCINode);
TSTALLOC(VBICxf1Xf2Ptr ,VBICxf1Node ,VBICxf2Node);
TSTALLOC(VBICxf2Xf1Ptr ,VBICxf2Node ,VBICxf1Node);
TSTALLOC(VBICxf2Xf2Ptr ,VBICxf2Node ,VBICxf2Node);
TSTALLOC(VBICemitEIXf2Ptr,VBICemitEINode,VBICxf2Node);
TSTALLOC(VBICcollCIXf2Ptr,VBICcollCINode,VBICxf2Node);
}
}
@ -694,11 +682,8 @@ VBICunsetup(
if(here->VBICxf2Node > 0)
CKTdltNNum(ckt, here->VBICxf2Node);
here->VBICxf2Node = 0;
if (here->VBICbrEq > 0)
CKTdltNNum(ckt, here->VBICbrEq);
here->VBICbrEq = 0;
}
}
}
return OK;

View File

@ -31,14 +31,6 @@ model_numnodes(int type)
return 6;
}
#ifdef ADMS
if (type == INPtypelook("BSIMBULK") || /* bsimbulk.va */
type == INPtypelook("BSIMCMG")) /* bsimcmg.va */
{
return 5;
}
#endif
if (type == INPtypelook("VDMOS")) /* 3 ; VDMOSnames */
{
return 5;
@ -141,13 +133,6 @@ INP2M(CKTcircuit *ckt, INPtables *tab, struct card *current)
thismodel->INPmodType != INPtypelook("SOI3") &&
#ifdef CIDER
thismodel->INPmodType != INPtypelook("NUMOS") &&
#endif
#ifdef ADMS
thismodel->INPmodType != INPtypelook("ekv") &&
thismodel->INPmodType != INPtypelook("psp102") &&
thismodel->INPmodType != INPtypelook("psp103") &&
thismodel->INPmodType != INPtypelook("bsimbulk") &&
thismodel->INPmodType != INPtypelook("bsimcmg") &&
#endif
thismodel->INPmodType != INPtypelook("HiSIM2") &&
thismodel->INPmodType != INPtypelook("HiSIMHV1") &&

View File

@ -18,11 +18,6 @@ model_max_numnodes(int type)
if (type == INPtypelook("VBIC") ||
type == INPtypelook("hicum2"))
return 5;
#ifdef ADMS
if (type == INPtypelook("hicum0") ||
type == INPtypelook("bjt504t"))
return 5;
#endif
return 4;
}
@ -96,10 +91,6 @@ void INP2Q(CKTcircuit *ckt, INPtables * tab, struct card *current, CKTnode *gnod
#ifdef CIDER
thismodel->INPmodType != INPtypelook("NBJT") &&
thismodel->INPmodType != INPtypelook("NBJT2") &&
#endif
#ifdef ADMS
thismodel->INPmodType != INPtypelook("hicum0") &&
thismodel->INPmodType != INPtypelook("bjt504t") &&
#endif
thismodel->INPmodType != INPtypelook("hicum2") &&
thismodel->INPmodType != INPtypelook("VBIC"))

View File

@ -169,11 +169,8 @@ void INP2R(CKTcircuit *ckt, INPtables * tab, struct card *current)
INPinsert(&model, tab);
current->error = INPgetMod(ckt, model, &thismodel, tab);
if (thismodel != NULL) {
if ((INPtypelook("Resistor") != thismodel->INPmodType)
#ifdef ADMS
&& (INPtypelook("r2_cmc") != thismodel->INPmodType)
#endif
) {
if (INPtypelook("Resistor") != thismodel->INPmodType)
{
LITERR("incorrect model type for resistor");
return;
}

View File

@ -63,22 +63,6 @@ char *INPdomodel(CKTcircuit *ckt, struct card *image, INPtables * tab)
"Device type VBIC not available in this binary\n");
}
break;
#ifdef ADMS
case 6:
type = INPtypelook("bjt504t");
if(type < 0) {
err = INPmkTemp(
"Device type MEXTRAM not available in this binary\n");
}
break;
case 7:
type = INPtypelook("hicum0");
if(type < 0) {
err = INPmkTemp(
"Device type HICUM0 not available in this binary\n");
}
break;
#endif
case 8:
type = INPtypelook("hicum2");
if(type < 0) {
@ -87,13 +71,8 @@ char *INPdomodel(CKTcircuit *ckt, struct card *image, INPtables * tab)
}
break;
default: /* placeholder; use level 4 for the next model */
#ifdef ADMS
err = INPmkTemp(
"Only BJT levels 1-2, 4, 6-9 are supported in this binary\n");
#else
err = INPmkTemp(
"Only BJT levels 1-2, 4, 8, 9 are supported in this binary\n");
#endif
break;
}
@ -341,48 +320,6 @@ char *INPdomodel(CKTcircuit *ckt, struct card *image, INPtables * tab)
("Device type BSIM5 not available in this binary\n");
}
break;
#ifdef ADMS
case 16:
case 77:
type = INPtypelook("BSIMBULK");
if (type < 0) {
err =
INPmkTemp
("Device type BSIMBULK not available in this binary\n");}
break;
case 17:
case 72:
type = INPtypelook("BSIMCMG");
if (type < 0) {
err =
INPmkTemp
("Device type BSIMCMG not available in this binary\n");}
break;
case 44:
type = INPtypelook("ekv");
if (type < 0) {
err =
INPmkTemp
("Device type EKV not available in this binary\n");
}
break;
case 45:
type = INPtypelook("psp102");
if (type < 0) {
err =
INPmkTemp
("Device type PSP102 not available in this binary\n");
}
break;
case 69:
type = INPtypelook("psp103");
if (type < 0) {
err =
INPmkTemp
("Device type PSP103 not available in this binary\n");
}
break;
#endif
case 55:
type = INPtypelook("B3SOIFD");
if (type < 0) {
@ -444,13 +381,8 @@ char *INPdomodel(CKTcircuit *ckt, struct card *image, INPtables * tab)
}
break;
default: /* placeholder; use level xxx for the next model */
#ifdef ADMS
err = INPmkTemp
("Only MOS device levels 1-6,8-10,14,16,17,44,45,49,54-58,60,68,72,73,77 are supported in this binary\n");
#else
err = INPmkTemp
("Only MOS device levels 1-6,8-10,14,49,54-58,60,68,73 are supported in this binary\n");
#endif
break;
}
INPmakeMod(modname, type, image);
@ -481,15 +413,6 @@ char *INPdomodel(CKTcircuit *ckt, struct card *image, INPtables * tab)
("Device type Resistor not available in this binary\n");
}
break;
#ifdef ADMS
case 2:
type = INPtypelook("r2_cmc");
if (type < 0) {
err = INPmkTemp(
"Device type R2_CMC not available in this binary\n");
}
break;
#endif
}
INPmakeMod(modname, type, image);
}

View File

@ -3,13 +3,15 @@
EXTRA_DIST = README examples icm xspice.c .gitignore \
verilog/vlnggen \
verilog/verilator_shim.cpp verilog/verilator_main.cpp \
verilog/libvvp.def verilog/MSVC.CMD verilog/README.txt
verilog/libvvp.def verilog/MSVC.CMD verilog/README.txt \
vhdl/ghnggen \
vhdl/ghdl_shim.h vhdl/ghdl_shim.c vhdl/ghdl_vpi.c
## This is removed because icm relies upon the existance of all other
## libs. It is currently compiled manually, last.
##SUBDIRS = mif cm enh evt ipc idn icm
SUBDIRS = mif cm enh evt ipc idn cmpp icm verilog
SUBDIRS = mif cm enh evt ipc idn cmpp icm verilog vhdl
dist-hook:
rm -f "$(distdir)/icm/makedefs"

View File

@ -55,6 +55,7 @@ NON-STANDARD FEATURES
#include "ngspice/fteext.h"
#include <math.h>
#include <time.h>
#include <locale.h>
@ -511,7 +512,7 @@ static double get_real(int index, double when, struct reals *ctx)
{
struct dvec *dv;
if (index < ctx->last_i) {
if (index <= ctx->last_i) {
/* Starting a new pass. */
if (!ctx->time) {
@ -568,11 +569,9 @@ static double get_real(int index, double when, struct reals *ctx)
/*
* A simple vcd file printer.
* command 'eprvcd a0 a1 a2 b0 b1 b2 clk > myvcd.vcd'
* prints the event nodes listed to file myvcd.vcd
* which then may be viewed with an vcd viewer,
* for example 'gtkwave'
* Still missing:
* hierarchy, vector variables
* prints the event nodes and vector expressions listed to file myvcd.vcd
* which then may be viewed with an vcd viewer, for example 'gtkwave'.
* Still missing: hierarchy, bit vectors.
*/
void
@ -588,7 +587,6 @@ EVTprintvcd(wordlist *wl)
double out_time, last_out_time;
char *node_name[EPRINT_MAXARGS];
int node_index[EPRINT_MAXARGS];
int udn_index[EPRINT_MAXARGS];
@ -621,8 +619,9 @@ EVTprintvcd(wordlist *wl)
double input;
int error = 0;
char* inword = wl->wl_word;
input = INPevaluate(&inword, &error, 0);
tspower = (int)ceil(- 1. * log10(input));
tspower = (int)ceil(-log10(input));
if (tspower < 0)
tspower = 0;
}
@ -654,7 +653,7 @@ EVTprintvcd(wordlist *wl)
fprintf(cp_err, "Error: no circuit loaded.\n");
return;
}
if (!ckt->evt->data.node) {
if (!ckt->evt->data.node && !timesteps) {
fprintf(cp_err, "ERROR - No node data: simulation not yet run?\n");
return;
}
@ -866,7 +865,7 @@ EVTprintvcd(wordlist *wl)
(timesteps && !more))) {
/* Analogue output at each time step, skipping if they would
* appear simulataneous in the output.
* appear simultaneous in the output.
*/
out_time = ctx.time->v_realdata[ctx.v_index + 1];
@ -919,7 +918,6 @@ EVTprintvcd(wordlist *wl)
out_printf("#%lld\n",
(unsigned long long)(out_time * scale));
last_out_time = out_time;;
got_one = 1;
}
@ -942,6 +940,7 @@ EVTprintvcd(wordlist *wl)
tfree(buf);
}
}
last_out_time = out_time;
} /* end while there is more data */
out_printf("\n\n");

View File

@ -94,14 +94,21 @@ static void callback(ARGS, Mif_Callback_Reason_t reason)
if (reason == MIF_CB_DESTROY) {
if (!ip)
return;
if (ip->info.cleanup)
if (ip->info.cleanup) {
DBG("Calling cleanup.");
(*ip->info.cleanup)(&ip->info);
}
if (ip->info.lib_argv)
free((void *)ip->info.lib_argv);
if (ip->info.sim_argv)
free((void *)ip->info.sim_argv);
if (ip->so_handle)
dlclose(ip->so_handle);
if (ip->so_handle) {
DBG("Unloading co-simulation.");
if (dlclose(ip->so_handle)) {
cm_message_printf("Error unloading co-simulation: %s",
dlerror());
}
}
if (ip->q)
free(ip->q);
if (ip->out_vals)
@ -131,6 +138,13 @@ static const char *exts[] = { "", ".so", ".DLL", NULL};
#define NGSPICELIBDIR "C:\\Spice64\\lib\\ngspice" // Defined by configure?
#endif
#elif defined(__APPLE__)
static const char *exts[] = { "", ".so", ".dylib", NULL};
#define CMPFN strcmp
#define TESTFN(f) (access(f, R_OK) == 0)
#define SLIBFILE "dynamic library"
#else
static const char *exts[] = { "", ".so", NULL};
@ -138,6 +152,7 @@ static const char *exts[] = { "", ".so", NULL};
#define TESTFN(f) (access(f, R_OK) == 0)
#define SLIBFILE "shared library"
#endif
#define FLAGS (RTLD_GLOBAL | RTLD_NOW)
static void *cosim_dlopen(const char *fn)
@ -422,6 +437,8 @@ static bool check_input(struct instance *ip, Digital_t *ovp,
while (ip->q_index >= 0 && ip->q[ip->q_index].when >= rp->when)
--ip->q_index;
if (ip->q_index >= 0) {
DBG("Input Q full: d_cosim setting back to %.15g.",
(rp->when + ip->q[ip->q_index].when) / 2);
cm_analog_set_temp_bkpt(
(rp->when + ip->q[ip->q_index].when) / 2);
} else {
@ -473,7 +490,8 @@ void ucm_d_cosim(ARGS)
fn = PARAM(simulation);
handle = cosim_dlopen(fn);
if (!handle) {
cm_message_send("d_cosim failed to load simulation binary.");
cm_message_printf("d_cosim failed to load simulation binary %s.",
fn);
return;
}
ifp = (void (*)(struct co_info *))dlsym(handle, "Cosim_setup");

View File

@ -570,39 +570,23 @@ MIF_INP2A (
}
}
/* check model parameter constraints */
/* some of these should probably be done in MIFgetMod() */
/* to prevent multiple error messages */
/* Check model parameter constraints. */
for(i = 0; i < DEVices[type]->DEVpublic.num_param; i++) {
char* emessage = NULL;
param_info = &(DEVices[type]->DEVpublic.param[i]);
if (mdfast->param[i]->is_null) {
char* emessage = NULL;
if (!param_info->null_allowed) {
emessage = tprintf("Null not allowed for parameter %s "
"on model %s.",
param_info->name, mdfast->gen.GENmodName);
} else if (param_info->default_value_siz == 0) {
if (param_info->type == MIF_STRING)
continue; // Allow NULL
emessage = tprintf("Parameter %s on model %s has no default",
param_info->name, mdfast->gen.GENmodName);
}
if (emessage) {
LITERR(emessage);
tfree(emessage);
gc_end();
return;
}
} else if (param_info->is_array && param_info->has_conn_ref &&
if (!mdfast->param[i]->is_null &&
param_info->is_array && param_info->has_conn_ref &&
fast->conn[param_info->conn_ref]->size !=
fast->param[i]->size) {
LITERR("Array parameter size on model does not match "
"connection size");
emessage = tprintf("Size of array parameter %s on model %s "
"does not match connection size",
param_info->name, mdfast->gen.GENmodName);
}
if (emessage) {
LITERR(emessage);
tfree(emessage);
gc_end();
return;
}
@ -1081,7 +1065,3 @@ copy_gc(char* in)
alltokens[curtoknr++] = newtok;
return newtok;
}

View File

@ -56,6 +56,7 @@ NON-STANDARD FEATURES
#include "ngspice/mifproto.h"
#include "ngspice/mifdefs.h"
#include "ngspice/mifparse.h"
#include "ngspice/mifcmdat.h"
#include "ngspice/suffix.h"
@ -101,8 +102,6 @@ char *MIFgetMod(
char *err2;
MIFmodel *mdfast;
/* Mif_Param_Info_t *param_info;*/
/* =========== First locate the named model in the modtab list ================= */
@ -143,34 +142,46 @@ char *MIFgetMod(
/* ============== and return an appropriate pointer to it ===================== */
/* make sure the type is valid before proceeding */
if(modtmp->INPmodType < 0) {
/* illegal device type, so can't handle */
*model = NULL;
return tprintf("MIF: Unknown device type for model %s\n", name);
}
if (modtmp->INPmodType < 0) {
/* illegal device type, so can't handle */
*model = NULL;
return tprintf("MIF: Unknown device type for model %s\n", name);
}
/* check to see if this model's parameters have been processed */
if(! modtmp->INPmodfast) {
if (!modtmp->INPmodfast) {
struct IFdevice *device;
int num_pars;
/* not already processed, so create data struct */
error = ft_sim->newModel ( ckt, modtmp->INPmodType,
&(modtmp->INPmodfast), modtmp->INPmodName);
if(error)
return(INPerror(error));
/* gtri modification: allocate and initialize MIF specific model struct items */
error = ft_sim->newModel(ckt, modtmp->INPmodType,
&(modtmp->INPmodfast),
modtmp->INPmodName);
if (error)
return INPerror(error);
/* Allocate and initialize MIF specific model struct items. */
mdfast = (MIFmodel*) modtmp->INPmodfast;
mdfast->num_param = DEVices[modtmp->INPmodType]->DEVpublic.num_param;
mdfast->num_param =
DEVices[modtmp->INPmodType]->DEVpublic.num_param;
mdfast->param = TMALLOC(Mif_Param_Data_t *, mdfast->num_param);
for(i = 0; i < mdfast->num_param; i++) {
for (i = 0; i < mdfast->num_param; i++) {
mdfast->param[i] = TMALLOC(Mif_Param_Data_t, 1);
mdfast->param[i]->is_null = MIF_TRUE;
mdfast->param[i]->size = 0;
mdfast->param[i]->element = NULL;
}
/* remaining initializations will be done by MIFmParam() and MIFsetup() */
/* Remaining initializations will be done by
* MIFmParam() and MIFsetup().
*/
/* parameter isolation, identification, binding */
line = modtmp->INPmodLine->line;
INPgetTok(&line,&parm,1); /* throw away '.model' */
tfree(parm);
@ -179,28 +190,39 @@ char *MIFgetMod(
/* throw away the modtype - we don't treat it as a parameter */
/* like SPICE does */
INPgetTok(&line,&parm,1); /* throw away 'modtype' */
INPgetTok(&line, &parm, 1); /* throw away 'modtype' */
tfree(parm);
while(*line != '\0') {
INPgetTok(&line,&parm,1);
for(j=0 ; j < *(ft_sim->devices[modtmp->INPmodType]->numModelParms); j++) {
if (strcmp(parm, ft_sim->devices[modtmp->INPmodType]->modelParms[j].keyword) == 0) {
/* gtri modification: call MIFgetValue instead of INPgetValue */
device = ft_sim->devices[modtmp->INPmodType];
num_pars = *device->numModelParms;
while (*line != '\0') {
INPgetTok(&line, &parm, 1);
if (!parm || !*parm) // May be closing ')'.
break;
for (j = 0; j < num_pars; j++) {
if (strcmp(parm, device->modelParms[j].keyword) == 0) {
err1 = NULL;
val = MIFgetValue(ckt,&line,
ft_sim->devices[modtmp->INPmodType]->modelParms[j].dataType,
val = MIFgetValue(ckt, &line,
device->modelParms[j].dataType,
tab, &err1);
if(err1) {
err2 = tprintf("MIF-ERROR - model: %s - %s\n", name, err1);
return(err2);
if (err1) {
err2 = tprintf("MIF-ERROR - model: %s - %s\n",
name, err1);
return err2;
}
error = ft_sim->setModelParm (ckt,
modtmp->INPmodfast,
ft_sim->devices[modtmp->INPmodType]->modelParms[j].id,
val, NULL);
/* Store the parameter value. */
error =
ft_sim->setModelParm(ckt,
modtmp->INPmodfast,
device->modelParms[j].id,
val, NULL);
/* free val, allocated by MIFgetValue */
int vtype = (ft_sim->devices[modtmp->INPmodType]->modelParms[j].dataType & IF_VARTYPES);
int vtype =
(device->modelParms[j].dataType & IF_VARTYPES);
if (vtype == IF_FLAGVEC || vtype == IF_INTVEC)
tfree(val->v.vec.iVec);
if (vtype == IF_REALVEC)
@ -214,14 +236,16 @@ char *MIFgetMod(
tfree(val->v.vec.sVec[i]);
tfree(val->v.vec.sVec);
}
if(error)
return(INPerror(error));
if (error)
return INPerror(error);
break;
}
}
/* gtri modification: processing of special parameter "level" removed */
if(j >= *(ft_sim->devices[modtmp->INPmodType]->numModelParms)) {
char *temp = tprintf("MIF: unrecognized parameter (%s) - ignored", parm);
if (j >= *(device->numModelParms)) {
char *temp = tprintf("MIF: unrecognized parameter "
"(%s) - ignored",
parm);
err = INPerrCat(err, temp);
}
FREE(parm);
@ -230,20 +254,44 @@ char *MIFgetMod(
modtmp->INPmodLine->error = err;
/* Make some consistency checks. */
for (i = 0; i < mdfast->num_param; i++) {
Mif_Param_Info_t *param_info;
char *emessage;
param_info = device->param + i;
if (mdfast->param[i]->is_null) {
if (!param_info->null_allowed) {
emessage = tprintf("Null not allowed for "
"parameter '%s' on model '%s'.",
param_info->name,
mdfast->gen.GENmodName);
return emessage;
} else if (param_info->default_value_siz == 0) {
if (param_info->type == MIF_STRING)
continue; // Allow NULL
emessage = tprintf("Parameter '%s' on model '%s' "
"has no default.",
param_info->name,
mdfast->gen.GENmodName);
return emessage;
}
}
}
} /* end if model parameters not processed yet */
*model = modtmp;
return(NULL);
return NULL;
} /* end if name matches */
} /* end for all models in modtab linked list */
/* didn't find model - ERROR - return NULL model */
*model = NULL;
err = tprintf(" MIF-ERROR - unable to find definition of model %s\n", name);
return(err);
*model = NULL;
err = tprintf("MIF-ERROR - unable to find definition of model %s\n", name);
return err;
}

View File

@ -62,13 +62,56 @@ static int MIFget_integer(char *token, char **err);
static double MIFget_real(char *token, char **err);
static char *MIFget_string(char *token, char **err);
static IFcomplex MIFget_complex(char *token, Mif_Token_Type_t token_type,
char **line, char **err);
/* Pull a string from a .model card, like MIFget_token() but do not break
* on any special characters except '"' and ']'.
*/
static char *get_string(char **s, int is_array, Mif_Token_Type_t *token_type)
{
char *ret_str; /* storage for returned string */
char *end;
char *beg;
/* Skip over white space. */
while (isspace_c(**s))
(*s)++;
if (!*s) {
*token_type = MIF_NO_TOK;
return NULL;
}
/* If first character is a quote, read until the closing
* quote, or the end of string, discarding the quotes.
*/
if (**s == '"') {
(*s)++;
ret_str = gettok_char(s, '"', FALSE, FALSE);
if (**s == '"')
(*s)++;
} else if (is_array && **s == ']') {
*token_type = MIF_RARRAY_TOK;
(*s)++;
return NULL;
} else {
/* Read to next white-space, end of line, or end of array. */
beg = *s;
while (**s != '\0' && !(isspace_c(**s) || (is_array && **s == ']')))
(*s)++;
end = *s;
ret_str = copy_substring(beg, end);
}
*token_type = MIF_STRING;
return ret_str;
}
/*
MIFgetValue
@ -94,7 +137,6 @@ MIFgetValue (
int btemp;
int itemp;
double rtemp;
char *stemp;
IFcomplex ctemp;
char *token;
@ -114,6 +156,7 @@ MIFgetValue (
/* initialize stuff if array */
if(is_array) {
token = MIFget_token(line, &token_type);
tfree(token);
@ -129,8 +172,10 @@ MIFgetValue (
/* now get the values into val */
for (;;) {
token = MIFget_token(line, &token_type);
if ((value_type & ~IF_VECTOR) == IF_STRING)
token = get_string(line, is_array, &token_type);
else
token = MIFget_token(line, &token_type);
/* exit if no more tokens */
if(token_type == MIF_NO_TOK) {
@ -163,14 +208,14 @@ MIFgetValue (
break;
case IF_STRING:
val.sValue = MIFget_string(token, err);
val.sValue = token;
token = NULL;
break;
case IF_COMPLEX:
val.cValue = MIFget_complex(token, token_type, line, err);
break;
case IF_FLAGVEC:
btemp = MIFget_boolean(token, err);
val.v.vec.iVec = TREALLOC(int, val.v.vec.iVec, val.v.numValue + 1);
@ -193,10 +238,10 @@ MIFgetValue (
break;
case IF_STRINGVEC:
stemp = MIFget_string(token, err);
val.v.vec.sVec = TREALLOC(char *, val.v.vec.sVec, val.v.numValue + 1);
val.v.vec.sVec[val.v.numValue] = stemp;
val.v.vec.sVec[val.v.numValue] = token;
val.v.numValue++;
token = NULL;
break;
case IF_CPLXVEC:
@ -220,7 +265,8 @@ MIFgetValue (
if(! is_array)
break;
tfree(token);
if (token)
tfree(token);
} /* end forever loop */
@ -302,16 +348,6 @@ static double MIFget_real(char *token, char **err)
}
/* *************************************************************** */
static char *MIFget_string(char *token, char **err)
{
char* ctoken = MIFcopy(token);
*err = NULL;
return(ctoken);
}
/* *************************************************************** */
static IFcomplex MIFget_complex(char *token, Mif_Token_Type_t token_type,

View File

@ -36,13 +36,9 @@ NON-STANDARD FEATURES
============================================================================*/
/* #include "prefix.h" */
#include "ngspice/ngspice.h"
#include <stdio.h>
//#include "CONST.h"
//#include "util.h"
#include "ngspice/ifsim.h"
//#include "resdefs.h"
#include "ngspice/devdefs.h"
#include "ngspice/sperror.h"
@ -53,8 +49,48 @@ NON-STANDARD FEATURES
#include "ngspice/mifdefs.h"
#include "ngspice/mifcmdat.h"
/* #include "suffix.h" */
/* Check value constraints from IFS file. */
static int check_int(int v, Mif_Param_Info_t *param_info, const char *name)
{
if (param_info->has_lower_limit && v < param_info->lower_limit.ivalue) {
fprintf(stderr,
"Value %d below limit %d for parameter '%s' of model '%s'.\n",
v, param_info->lower_limit.ivalue,
param_info->name, name);
v = param_info->lower_limit.ivalue;
} else if (param_info->has_upper_limit &&
v > param_info->upper_limit.ivalue) {
fprintf(stderr,
"Value %d exceeds limit %d for parameter '%s' of "
"model '%s'.\n",
v, param_info->upper_limit.ivalue,
param_info->name, name);
v = param_info->upper_limit.ivalue;
}
return v;
}
static double check_double(double v, Mif_Param_Info_t *param_info,
const char *name)
{
if (param_info->has_lower_limit && v < param_info->lower_limit.rvalue) {
fprintf(stderr,
"Value %g below limit %g for parameter '%s' of model '%s'.\n",
v, param_info->lower_limit.rvalue,
param_info->name, name);
v = param_info->lower_limit.rvalue;
} else if (param_info->has_upper_limit &&
v > param_info->upper_limit.rvalue) {
fprintf(stderr,
"Value %g exceeds limit %g for parameter '%s' of "
"model '%s'.\n",
v, param_info->upper_limit.rvalue,
param_info->name, name);
v = param_info->upper_limit.rvalue;
}
return v;
}
/*
MIFmParam
@ -76,139 +112,152 @@ int MIFmParam(
GENmodel *inModel) /* The model structure on which to set the value */
{
MIFmodel *model;
int mod_type;
int value_type;
int i;
MIFmodel *model;
Mif_Value_t *target;
Mif_Param_Info_t *param_info;
int mod_type;
int value_type;
int size, i;
Mif_Boolean_t is_array;
Mif_Boolean_t is_array;
/* Arrange for access to MIF specific data in the model */
model = (MIFmodel *) inModel;
/* Check parameter index for validity */
if ((param_index < 0) || (param_index >= model->num_param))
return(E_BADPARM);
/* Get model type */
/* Get model type and XSPICE parameter info. */
mod_type = model->MIFmodType;
if((mod_type < 0) || (mod_type >= DEVmaxnum))
return(E_BADPARM);
/* Check parameter index for validity */
if((param_index < 0) || (param_index >= model->num_param))
return(E_BADPARM);
param_info = DEVices[mod_type]->DEVpublic.param + param_index;
/* get value type to know which members of unions to access */
value_type = DEVices[mod_type]->DEVpublic.modelParms[param_index].dataType;
value_type &= IF_VARTYPES;
/* determine if the parameter is an array or not */
is_array = value_type & IF_VECTOR;
/* initialize the parameter is_null and size elements and allocate elements */
/* Initialize the parameter is_null. */
model->param[param_index]->is_null = MIF_FALSE;
/* element may exist already, if called from 'altermod' */
FREE(model->param[param_index]->element);
if(is_array) {
model->param[param_index]->size = value->v.numValue;
model->param[param_index]->element = TMALLOC(Mif_Value_t, value->v.numValue);
}
else {
model->param[param_index]->size = 1;
model->param[param_index]->element = TMALLOC(Mif_Value_t, 1);
target = model->param[param_index]->element;
if (is_array) {
size = value->v.numValue;
if (param_info->has_lower_bound && size < param_info->lower_bound) {
fprintf(stderr,
"Too few values for parameter '%s' of model '%s': %s.\n",
param_info->name,
inModel->GENmodName,
target ? "overwriting" : "fatal");
if (!target)
return E_BADPARM;
} else if (param_info->has_upper_bound &&
size > param_info->upper_bound) {
fprintf(stderr,
"Too many values for parameter '%s' of model '%s': "
"truncating.\n",
param_info->name,
inModel->GENmodName);
size = param_info->upper_bound;
}
} else {
size = 1;
}
if (size > model->param[param_index]->size) {
/* Update element count and allocate. */
/* Transfer the values from the SPICE3C1 value union to the param elements */
model->param[param_index]->size = size;
FREE(target);
target = TMALLOC(Mif_Value_t, size);
model->param[param_index]->element = target;
}
/* Copy the values from the SPICE3C1 value union to the param elements */
/* This is analagous to what SPICE3 does with other device types */
if (!is_array) {
switch(value_type) {
case IF_FLAG:
target[0].bvalue = value->iValue;
break;
if(! is_array) {
case IF_INTEGER:
target[0].ivalue = check_int(value->iValue,
param_info, inModel->GENmodName);
break;
switch(value_type) {
case IF_REAL:
target[0].rvalue = check_double(value->rValue,
param_info, inModel->GENmodName);
break;
case IF_FLAG:
model->param[param_index]->element[0].bvalue = value->iValue;
model->param[param_index]->eltype = IF_FLAG;
break;
case IF_STRING:
/* we don't trust the caller to keep the string alive, so copy it */
target[0].svalue =
TMALLOC(char, 1 + strlen(value->sValue));
strcpy(target[0].svalue, value->sValue);
break;
case IF_INTEGER:
model->param[param_index]->element[0].ivalue = value->iValue;
model->param[param_index]->eltype = IF_INTEGER;
break;
case IF_COMPLEX:
/* we don't trust the caller to have a parallel complex structure */
/* so copy the real and imaginary parts explicitly */
case IF_REAL:
model->param[param_index]->element[0].rvalue = value->rValue;
model->param[param_index]->eltype = IF_REAL;
break;
case IF_STRING:
/* we don't trust the caller to keep the string alive, so copy it */
model->param[param_index]->element[0].svalue =
TMALLOC(char, 1 + strlen(value->sValue));
strcpy(model->param[param_index]->element[0].svalue, value->sValue);
model->param[param_index]->eltype = IF_STRING;
break;
case IF_COMPLEX:
/* we don't trust the caller to have a parallel complex structure */
/* so copy the real and imaginary parts explicitly */
model->param[param_index]->element[0].cvalue.real = value->cValue.real;
model->param[param_index]->element[0].cvalue.imag = value->cValue.imag;
model->param[param_index]->eltype = IF_COMPLEX;
break;
target[0].cvalue.real = value->cValue.real;
target[0].cvalue.imag = value->cValue.imag;
break;
default:
return(E_BADPARM);
}
}
else { /* it is an array */
for(i = 0; i < value->v.numValue; i++) {
return E_BADPARM;
}
} else {
for (i = 0; i < size; i++) {
switch(value_type) {
case IF_FLAGVEC:
model->param[param_index]->element[i].bvalue = value->v.vec.iVec[i];
model->param[param_index]->eltype = IF_FLAGVEC;
target[i].ivalue = value->v.vec.iVec[i];
break;
case IF_INTVEC:
model->param[param_index]->element[i].ivalue = value->v.vec.iVec[i];
model->param[param_index]->eltype = IF_INTVEC;
target[i].bvalue = check_int(value->v.vec.iVec[i],
param_info, inModel->GENmodName);
break;
case IF_REALVEC:
model->param[param_index]->element[i].rvalue = value->v.vec.rVec[i];
model->param[param_index]->eltype = IF_REALVEC;
target[i].rvalue = check_double(value->v.vec.rVec[i],
param_info,
inModel->GENmodName);
break;
case IF_STRINGVEC:
/* we don't trust the caller to keep the string alive, so copy it */
model->param[param_index]->element[i].svalue =
TMALLOC(char, 1 + strlen(value->v.vec.sVec[i]));
strcpy(model->param[param_index]->element[i].svalue, value->v.vec.sVec[i]);
model->param[param_index]->eltype = IF_STRINGVEC;
/* Don't trust the caller to keep the string alive, copy it */
target[i].svalue =
TMALLOC(char, 1 + strlen(value->v.vec.sVec[i]));
strcpy(target[i].svalue, value->v.vec.sVec[i]);
break;
case IF_CPLXVEC:
/* we don't trust the caller to have a parallel complex structure */
/* so copy the real and imaginary parts explicitly */
model->param[param_index]->element[i].cvalue.real = value->v.vec.cVec[i].real;
model->param[param_index]->element[i].cvalue.imag = value->v.vec.cVec[i].imag;
model->param[param_index]->eltype = IF_CPLXVEC;
/* Don't trust the caller to have a parallel complex structure,
* so copy the real and imaginary parts explicitly.
*/
target[i].cvalue.real = value->v.vec.cVec[i].real;
target[i].cvalue.imag = value->v.vec.cVec[i].imag;
break;
default:
return(E_BADPARM);
} /* end switch */
} /* end for number of elements of vector */
} /* end else */
return(OK);
return E_BADPARM;
}
}
}
model->param[param_index]->eltype = value_type;
return OK;
}

View File

@ -47,11 +47,6 @@ NON-STANDARD FEATURES
#include "ngspice/miftypes.h"
#include "ngspice/mifproto.h"
/* #include "suffix.h" */
/*
MIFgettok
@ -67,8 +62,7 @@ MIFgettok treats ( and ) like whitespace.
char *MIFgettok(char **s)
{
char *ret_str; /* storage for returned string */
char *ret_str; /* storage for returned string */
char *end;
char *beg;
@ -122,14 +116,12 @@ char *MIFgettok(char **s)
/* else, read until the next delimiter */
else {
beg = *s;
while ((**s != '\0') &&
(!(isspace_c(**s) || (**s == '=') || (**s == '%') ||
(**s == '(') || (**s == ')') || (**s == ',') ||
(**s == '[') || (**s == ']') ||
(**s == '<') || (**s == '>') || (**s == '~')
))) {
while (**s != '\0' &&
!(isspace_c(**s) || **s == '=' || **s == '%' ||
**s == '(' || **s == ')' || **s == ',' ||
**s == '[' || **s == ']' ||
**s == '<' || **s == '>' || **s == '~'))
(*s)++;
}
end = *s;
/* skip over white spaces, '=', '(', ')', and ',' up to next token */
@ -143,94 +135,6 @@ char *MIFgettok(char **s)
}
}
#if 0
/* preliminary fix */
char *MIFgettok(char **s)
{
char *buf; /* temporary storage to copy token into */
char *ret_str; /* storage for returned string */
int i;
/* allocate space big enough for the whole string */
buf = TMALLOC(char, strlen(*s) + 2);
/* FIXME, not yet understood why +1 leads to spurious crash in tfree, if optimized code for Windows*/
/* skip over any white space */
while(isspace_c(**s) || (**s == '=') ||
(**s == '(') || (**s == ')') || (**s == ','))
(*s)++;
/* isolate the next token */
switch(**s) {
case '\0':
FREE(buf);
return(NULL);
case '<':
case '>':
case '[':
case ']':
case '~':
case '%':
buf[0] = **s;
buf[1] = '\0';
(*s)++;
break;
default:
i = 0;
/* if first character is a quote, read until the closing */
/* quote, or the end of string, discarding the quotes */
if(**s == '"') {
(*s)++;
while( (**s != '\0') && (**s != '"') ) {
buf[i] = **s;
i++;
(*s)++;
}
if(**s == '"')
(*s)++;
}
/* else, read until the next delimiter */
else {
while( (**s != '\0') &&
(! ( isspace_c(**s) || (**s == '=') || (**s == '%') ||
(**s == '(') || (**s == ')') || (**s == ',') ||
(**s == '[') || (**s == ']') ||
(**s == '<') || (**s == '>') || (**s == '~')
) ) ) {
buf[i] = **s;
i++;
(*s)++;
}
}
buf[i] = '\0';
break;
}
/* skip over white space up to next token */
while(isspace_c(**s) || (**s == '=') ||
(**s == '(') || (**s == ')') || (**s == ','))
(*s)++;
/* make a copy using only the space needed by the string length */
/* Changed from copy to MIFcopy by SDB on 6.22.2003 */
ret_str = MIFcopy(buf);
FREE(buf);
return(ret_str);
}
#endif
/*
@ -255,7 +159,6 @@ char *MIFget_token(
ret_str = MIFgettok(s);
/* if no next token, return */
if(ret_str == NULL) {

View File

@ -2,6 +2,10 @@
MAINTAINERCLEANFILES = Makefile.in
# Libs for Ngspice are irrelevant here.
LIBS =
# Verilator support: files installed to script directory and below.
initdatadir = $(pkgdatadir)/scripts
@ -13,7 +17,8 @@ initdata1_DATA = verilator_shim.cpp verilator_main.cpp
initdata2dir = $(pkgdatadir)/scripts/src/ngspice
initdata2_DATA = ../../include/ngspice/cosim.h \
../../include/ngspice/miftypes.h \
../../include/ngspice/cmtypes.h
../../include/ngspice/cmtypes.h \
./coroutine.h ./coroutine_cosim.h ./coroutine_shim.h
# Icarus Verilog support: build two shared libraries.

View File

@ -0,0 +1,11 @@
## Process this file with automake to produce Makefile.in
MAINTAINERCLEANFILES = Makefile.in
# GHDL support: files installed to script directory and below.
initdatadir = $(pkgdatadir)/scripts
initdata_DATA = ghnggen
initdata1dir = $(pkgdatadir)/scripts/src
initdata1_DATA = ghdl_shim.h ghdl_shim.c ghdl_vpi.c

281
src/xspice/vhdl/ghdl_shim.c Normal file
View File

@ -0,0 +1,281 @@
/* Main file to be linked with code generated by GHDL to make a shared library
* to be loaded by ngspice's d_cosim code model to connect an instance of a
* VHDL simulation into a Ngspice netlist.
* Licensed on the same terms as Ngspice.
*
* Copyright (c) 2024 Giles Atkinson
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <stdbool.h>
/* The GHDL code runs on its own stack, handled by cr_xxx() functions. */
#include "ngspice/coroutine_shim.h"
#include "ngspice/cmtypes.h" // For Digital_t
#include "ngspice/cosim.h"
/* This header file defines the external (d_cosim) interface. It also contains
* an initial comment that describes how this shared library is used.
*/
#include "ghdl_shim.h"
extern int ghdl_main(int argc, char **argv); // Not in any header.
/* Report fatal errors. */
static void fail(const char *what, int why)
{
fprintf(stderr, "Icarus shim failed in function %s: %s.\n",
what, strerror(why));
abort();
}
static void input(struct co_info *pinfo, unsigned int bit, Digital_t *val)
{
struct ng_ghdl *ctx = (struct ng_ghdl *)pinfo->handle;
struct ngvp_port *pp;
int count, a, b, dirty;
/* Convert the value. */
if (val->strength <= HI_IMPEDANCE && val->state != UNKNOWN) {
a = val->state; // Normal - '0'/'1'.
b = 0;
} else if (val->strength == HI_IMPEDANCE) {
a = 0; // High impedance - 'z'.
b = 1;
} else {
a = 1; // Undefined - 'x'.
b = 1;
}
/* Find the port. */
if (bit >= pinfo->in_count) {
bit -= pinfo->in_count;
if (bit >= pinfo->inout_count)
return;
pp = ctx->ports + ctx->ins + ctx->outs; // Point at inouts.
count = ctx->inouts;
} else {
pp = ctx->ports;
count = ctx->ins;
}
while (count--) {
if (pp[count].position <= bit)
break;
}
pp = pp + count;
bit -= pp->position;
/* Check and update. */
dirty = 0;
bit = pp->bits - bit - 1; // Bit position for big-endian.
a <<= bit;
if (a ^ pp->previous.aval) {
if (a)
pp->previous.aval |= a;
else
pp->previous.aval &= ~(1 << bit);
dirty = 1;
}
b <<= bit;
if (b ^ pp->previous.bval) {
if (b)
pp->previous.bval |= b;
else
pp->previous.bval &= ~(1 << bit);
dirty = 1;
}
if (dirty && !(pp->flags & IN_PENDING)) {
pp->flags |= IN_PENDING;
++ctx->in_pending;
}
}
/* Move the GHDL simulation forward. */
static void step(struct co_info *pinfo)
{
struct ng_ghdl *ctx = (struct ng_ghdl *)pinfo->handle;
int i;
/* Let GHDL run. It will stop when it has caught up with SPICE time
* (pinfo->vtime) or produced output.
*/
cr_yield_to_sim(&ctx->cr_ctx);
/* Check for output. */
if (ctx->out_pending) {
struct ngvp_port *pp;
uint32_t changed, mask;
int limit, i, bit;
limit = ctx->outs + ctx->inouts;
for (i = 0, pp = ctx->ports + ctx->ins; i < limit; ++i, ++pp) {
if (!(pp->flags & OUT_PENDING))
continue;
pp->flags &= ~OUT_PENDING;
changed = (pp->new.aval ^ pp->previous.aval) |
(pp->new.bval ^ pp->previous.bval);
if (changed) {
bit = pp->position;
mask = 1 << (pp->bits - 1);
while (changed) {
if (mask & changed) {
const Digital_t lv_vals[] =
{ {ZERO, STRONG}, {ONE, STRONG},
{ZERO, HI_IMPEDANCE}, {UNKNOWN, STRONG} };
int a, b;
a = (pp->new.aval & mask) != 0;
b = (pp->new.bval & mask) != 0;
a += (b << 1);
pinfo->out_fn(pinfo, bit, (Digital_t *)lv_vals + a);
changed &= ~mask;
}
mask >>= 1;
++bit;
}
pp->previous.aval = pp->new.aval;
pp->previous.bval = pp->new.bval;
}
if (--ctx->out_pending == 0)
break;
}
if (ctx->out_pending)
abort();
}
}
static void cleanup(struct co_info *pinfo)
{
struct ng_ghdl *ctx = (struct ng_ghdl *)pinfo->handle;
if (!ctx)
return;
/* Tell GHDL to exit. */
ctx->stop = 1;
cr_yield_to_sim(&ctx->cr_ctx);
cr_cleanup(&ctx->cr_ctx);
free(ctx->ports);
free(ctx);
pinfo->handle = NULL;
}
/* Thread start function runs the VHDL simulation. */
void *run_ghdl(void *arg)
{
struct co_info *pinfo = (struct co_info *)arg;
struct ng_ghdl *ctx, **ctx_ptr;
const char *file;
void *vpi_handle;
const char *new_argv[pinfo->sim_argc + 2];
int new_argc;
char vpi_buf[256];
cr_safety(); // Make safe with signals.
if (pinfo->sim_argc == 0) {
new_argc = 1;
new_argv[0] = "dummy_arg_0";
} else {
/* Copy the simulation arguments to the extended array. */
for (new_argc = 0; new_argc < pinfo->sim_argc; new_argc++)
new_argv[new_argc] = pinfo->sim_argv[new_argc];
}
/* Determing the file name for our VPI module. */
if (pinfo->lib_argc >= 1 && pinfo->lib_argv[0][0]) // Explicit VPI file.
file = pinfo->lib_argv[0];
else
file = "./ghdlng.vpi";
/* Normally, GHDL would load the VPI module. Here it is preloaded and
* an internal variable is set to point to the shared co_info struct.
*/
ctx_ptr = NULL;
vpi_handle = dlopen(file, RTLD_GLOBAL | RTLD_NOW);
if (vpi_handle)
ctx_ptr = dlsym(vpi_handle, CTX_VAR_NAME);
if (!ctx_ptr) {
fprintf(stderr,
"The GHDL shim can not initialise VPI module %s: %s.\n",
file, dlerror());
return NULL;
}
ctx = (struct ng_ghdl *)pinfo->handle;
*ctx_ptr = ctx;
/* The GHDL code is passed the VPI module name in a command argument. */
snprintf(vpi_buf, sizeof vpi_buf, "--vpi=%s", file);
new_argv[new_argc++] = vpi_buf;
new_argv[new_argc] = NULL;
ghdl_main(new_argc, (char **)new_argv);
/* The simulation has finished. Do nothing until destroyed. */
dlclose(vpi_handle);
ctx->stop = 1;
for (;;)
cr_yield_to_spice(&ctx->cr_ctx);
return NULL;
}
/* Entry point to this shared library. Called by d_cosim. */
void Cosim_setup(struct co_info *pinfo)
{
struct ng_ghdl *context;
struct ngvp_port *last_port;
/* It is assumed that there is no parallel access to this function
* as ngspice initialisation is single-threaded.
*/
context = calloc(1, sizeof (struct ng_ghdl));
if (!context)
fail("malloc", errno);
context->cosim_context = pinfo;
pinfo->handle = context;
/* Set-up the execution stack for the GHDL-generated code and start it. */
cr_init(&context->cr_ctx, run_ghdl, pinfo);
/* Return required values in *pinfo. */
last_port = context->ports + context->ins - 1;
pinfo->in_count = context->ins ? last_port->position + last_port->bits : 0;
last_port += context->outs;
pinfo->out_count =
context->outs ? last_port->position + last_port->bits : 0;
last_port += context->inouts;
pinfo->inout_count =
context->inouts ? last_port->position + last_port->bits : 0;
pinfo->cleanup = cleanup;
pinfo->step = step;
pinfo->in_fn = input;
pinfo->method = Normal;
}

View File

@ -0,0 +1,68 @@
#ifndef _GHDL_SHIM_H_
#define _GHDL_SHIM_H_
/* This is the interface definition file for the shim code (ghdl_shim.c)
* and associated Verilog VPI module (ghdl_shim.vpi).
*
* This software allows execution of VHDL code generated by the GHDL compiler
* inside a SPICE simulation performed by ngspice.
*
* Use of these components starts with a SPICE netlist containing an A-device
* (XSPICE device) whose model card specifies the d_cosim code model and
* parameter 'simulation="some_path/entity_name.so"', where "entity_name"
* represents a top-level entity defined in VHDL. The shared library
* (or DLL) named is built by the "ghdl -e" command using output from
* a VHDL compilation ("ghdl -a") and the provided ghdl_shim.c file.
*
* The VPI module ghdl_vpi.c is called on loading: its first task is to obtain
* the list of ports for the top-level VHDL entity. After that the VPI code
* controls the execution of the VHDL code by blocking execution until
* commanded to proceed by the d_cosim instance, always regaining control
* via a VPI callback before the VHDL code moves ahead of the SPICE simulation.
*/
typedef uint32_t __vpiHandle; // Compatible with GHDL's vpi_user.h
/* Data stored for each port. */
struct ngvp_port {
uint16_t bits; // How many bits?
uint16_t flags; // I/O pending.
uint32_t position; // Number of bits before this port.
struct { // Like struct t_vpi_vecval.
int32_t aval;
int32_t bval;
} previous, new; // Previous and new values.
__vpiHandle *handle; // Handle to the port's variable.
struct ng_ghdl *ctx; // Pointer back to parent.
};
#define IN_PENDING 1
#define OUT_PENDING 2
/* Data strucure used to share context between the ngspice and GHDL threads. */
struct ng_ghdl {
struct cr_ctx cr_ctx; // Coroutine context.
int stop; // Indicates simulation is over.
struct co_info *cosim_context;
uint32_t ins; // Port counts by type.
uint32_t outs;
uint32_t inouts;
double base_time; // SPICE time on entry.
double tick_length; // GHDL's time unit.
__vpiHandle *stop_cb; // Handle to end-of-tick callback.
volatile uint32_t in_pending; // Counts of changed ports.
volatile uint32_t out_pending;
struct ngvp_port *ports; // Port information array.
};
/* The VPI module, ghdlng.vpi, contains a global variable with this name,
* used during initialisation.
*/
#define CTX_VAR GHDLNG_VPI_context
#define STR(s) #s
#define XSTR(s) STR(s) // Puts quotes on its argument.
#define CTX_VAR_NAME XSTR(CTX_VAR)
#endif // _GHDL_SHIM_H_

387
src/xspice/vhdl/ghdl_vpi.c Normal file
View File

@ -0,0 +1,387 @@
/*
* Copyright (c) 2002 Stephen Williams (steve@icarus.com)
* Copyright (c) 2023 Giles Atkinson
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdint.h>
#include <vpi_user.h>
#if defined(__MINGW32__) || defined(_MSC_VER)
#include <windows.h> // Windows has a simple co-routine library - "Fibers"
#else
#include <pthread.h>
#endif
/* The VVP code runs on its own stack, handled by cr_xxx() functions. */
#include "ngspice/coroutine_cosim.h"
#include "ngspice/cmtypes.h" // For Digital_t
#include "ngspice/cosim.h"
/* This header file defines external interfaces. It also contains an initial
* comment that describes how this VPI module is used.
*/
#include "ghdl_shim.h"
/* Debugging printfs(). */
//#define DEBUG
#ifdef DEBUG
#define DBG(...) vpi_printf(__VA_ARGS__)
#else
#define DBG(...)
#endif
/* This global variable is used only during initialisation and safe
* so long as XSPICE instance initialisation is single-threaded. Ugly!
*/
__declspec(dllexport) struct ng_ghdl *CTX_VAR; // Name is a macro.
static PLI_INT32 next_advance_cb(struct t_cb_data *cb);
/* Get current simulation time: no module-specific values. */
static double get_time(struct ng_ghdl *ctx)
{
static struct t_vpi_time now = { .type = vpiSimTime };
uint64_t ticks;
vpi_get_time(NULL, &now);
ticks = ((uint64_t)now.high << 32) + now.low;
return ticks * ctx->tick_length;
}
/* Arrange for end_advance_cb() to be called in the future. */
static vpiHandle set_stop(uint64_t length, struct ng_ghdl *ctx)
{
static struct t_vpi_time now;
static struct t_cb_data cbd = { .cb_rtn = next_advance_cb, .time = &now };
now.type = vpiSimTime;
now.low = length;
now.high = length >> 32;
if (length == 0)
cbd.reason = cbReadWriteSynch;
else
cbd.reason = cbAfterDelay;
/* Callback after delay. */
cbd.user_data = (PLI_BYTE8 *)ctx;
return vpi_register_cb(&cbd);
}
/* Timed callback at end of simulation advance: wait for a command
* from the main thread, and schedule the next callback.
* On return, VHDL runs some more.
*/
static PLI_INT32 next_advance_cb(struct t_cb_data *cb)
{
struct ng_ghdl *ctx = (struct ng_ghdl *)cb->user_data;
struct t_vpi_value val;
double vl_time;
uint64_t ticks;
unsigned int i;
for (;;) {
/* Still wanted? */
if (ctx->stop) {
vpi_control(vpiFinish, 0); // Returns after scheduling $finish.
return 0;
}
/* Save base time for next slice. */
ctx->base_time = ctx->cosim_context->vtime;
/* Repeatedly wait for instructions from the main thread
* until GHDL can advance at least one time unit.
*/
cr_yield_to_spice(&ctx->cr_ctx);
/* Check for input. */
val.format = vpiVectorVal;
i = ctx->ins ? 0 : ctx->outs;
while (ctx->in_pending) {
if (ctx->ports[i].flags & IN_PENDING) {
ctx->ports[i].flags ^= IN_PENDING;
val.value.vector =
(struct t_vpi_vecval *)&ctx->ports[i].previous;
vpi_put_value(ctx->ports[i].handle, &val, NULL, vpiNoDelay);
ctx->in_pending--;
DBG("VPI input %d/%d on %s\n",
val.value.vector->aval, val.value.vector->bval,
vpi_get_str(vpiName, ctx->ports[i].handle));
} else if (++i == ctx->ins) {
i = ctx->ins + ctx->outs; // Now scan inouts
}
}
/* How many GHDL ticks to advance? */
vl_time = get_time(ctx);
if (ctx->cosim_context->vtime < vl_time) {
/* This can occur legitimately as the two times need not
* align exactly. But it should be less than one SPICE timestep.
*/
DBG("VHDL time %.16g ahead of SPICE target %.16g\n",
vl_time, ctx->cosim_context->vtime);
if (ctx->cosim_context->vtime + ctx->tick_length < vl_time) {
fprintf(stderr,
"Error: time reversal (%.10g->%.10g) in "
"GHDL shim VPI!\n",
vl_time, ctx->cosim_context->vtime);
}
continue;
}
ticks = (ctx->cosim_context->vtime - vl_time) / ctx->tick_length;
if (ticks > 0) {
DBG("Advancing from %g (VHDL) to %g (SPICE): %lu ticks\n",
vl_time, ctx->cosim_context->vtime, ticks);
ctx->stop_cb = set_stop(ticks, ctx);
return 0;
}
}
}
/* Callback function - new output value. */
static PLI_INT32 output_cb(struct t_cb_data *cb)
{
struct ngvp_port *pp = (struct ngvp_port *)cb->user_data;
struct ng_ghdl *ctx = pp->ctx;
DBG("Output: %s is %d now %g (VHDL) %g (SPICE)\n",
vpi_get_str(vpiName, cb->obj),
cb->value->value.vector->aval,
get_time(ctx), ctx->cosim_context->vtime);
if (ctx->stop_cb) {
/* First call in the current VHDL cycle: cancel the current
* stop CB and request a new one at the next GHDL time point.
* That allows all output events in the current timestep
* to be gathered before stopping.
*/
vpi_remove_cb(ctx->stop_cb);
ctx->stop_cb = NULL;
set_stop(0, ctx);
/* Set the output time in SPICE format.
* It must not be earlier than entry time.
*/
ctx->cosim_context->vtime = get_time(ctx);
if (ctx->cosim_context->vtime < ctx->base_time)
ctx->cosim_context->vtime = ctx->base_time;
}
/* Record the value. */
pp->new.aval = cb->value->value.vector->aval;
pp->new.bval = cb->value->value.vector->bval;
if (!(pp->flags & OUT_PENDING)) {
pp->flags |= OUT_PENDING;
++ctx->out_pending;
}
return 0;
}
/* Utilty functions for start_cb() - initialise or set watch on a variable.*/
static void init(vpiHandle handle)
{
static struct t_vpi_value val = { .format = vpiIntVal };
DBG("Initialising %s to 0\n", vpi_get_str(vpiName, handle));
vpi_put_value(handle, &val, NULL, vpiNoDelay);
}
static void watch(vpiHandle handle, void *pp)
{
static struct t_vpi_time time = { .type = vpiSimTime };
static struct t_vpi_value val = { .format = vpiVectorVal };
static struct t_cb_data cb = {
.reason = cbValueChange, .cb_rtn = output_cb,
.time = &time, .value = &val
};
cb.obj = handle;
cb.user_data = pp;
vpi_register_cb(&cb);
}
/* Callback function - simulation is starting. */
static PLI_INT32 start_cb(struct t_cb_data *cb)
{
struct ng_ghdl *ctx = (struct ng_ghdl *)cb->user_data;
vpiHandle iter, top, item;
PLI_INT32 direction;
char *name;
int ii, oi, ioi;
DBG("Precision %d\n", vpi_get(vpiTimePrecision, NULL));
ctx->tick_length = pow(10.0, vpi_get(vpiTimePrecision, NULL));
/* Find the (unique?) top-level module. */
iter = vpi_iterate(vpiModule, NULL);
top = vpi_scan(iter);
vpi_free_object(iter);
DBG("Top %s\n", vpi_get_str(vpiName, top));
/* Count the ports. */
iter = vpi_iterate(vpiPort, top);
if (!iter)
vpi_printf("Top module has no ports!\n"); // vpi_scan() aborts.
ctx->ins = ctx->outs = ctx->inouts = 0;
while ((item = vpi_scan(iter))) {
direction = vpi_get(vpiDirection, item);
switch (direction) {
case vpiInput:
++ctx->ins;
break;
case vpiOutput:
++ctx->outs;
break;
case vpiInout:
++ctx->inouts;
break;
default:
break;
}
}
ctx->ports = (struct ngvp_port *)malloc(
(ctx->ins + ctx->outs + ctx->inouts) *
sizeof (struct ngvp_port));
if (!ctx->ports) {
vpi_printf("No memory for ports at " __FILE__ ":%d\n", __LINE__);
abort();
}
/* Get the ports. */
iter = vpi_iterate(vpiPort, top);
ii = oi = ioi = 0;
while ((item = vpi_scan(iter))) {
struct ngvp_port *pp;
int first;
direction = vpi_get(vpiDirection, item);
name = vpi_get_str(vpiName, item);
/* It seems that in GHDL, a port and the underlying net are the
* same object.
*/
DBG("Port %s direction %d size %d, type %d\n",
name, direction, vpi_get(vpiSize, item),
vpi_get(vpiType, item));
switch (direction) {
case vpiInput:
first = !ii;
pp = ctx->ports + ii++;
init(item);
break;
case vpiOutput:
first = !oi;
pp = ctx->ports + ctx->ins + oi++;
watch(item, pp);
break;
case vpiInout:
first = !ioi;
init(item);
pp = ctx->ports + ctx->ins + ctx->outs + ioi++;
watch(item, pp);
break;
default:
continue;
}
pp->bits = vpi_get(vpiSize, item);
pp->flags = 0;
pp->position = first ? 0 : pp[-1].position + pp[-1].bits;
pp->previous.aval = pp->previous.bval = 0;
pp->handle = item;
pp->ctx = ctx;
}
/* Make a direct call to the "end-of-advance" callback to start running. */
cr_init(&ctx->cr_ctx);
cb->user_data = (PLI_BYTE8 *)ctx;
next_advance_cb(cb);
return 0;
}
/* VPI initialisation. */
static void start(void)
{
static struct t_vpi_time now = { .type = vpiSimTime };
static struct t_cb_data cbd = { .reason = cbStartOfSimulation,
.time = &now, .cb_rtn = start_cb };
#ifdef DEBUG
struct t_vpi_vlog_info info;
/* Get the program name. */
if (vpi_get_vlog_info(&info)) {
vpi_printf("Starting vhdlng.vpi in %s\n", info.argv[0]);
for (int i = 0; i < info.argc; ++i)
vpi_printf("%d: %s\n", i, info.argv[i]);
vpi_printf("P: %s V: %s\n", info.product, info.version);
} else {
vpi_printf("Failed to get invocation information.\n");
}
#endif
/* The first step is to find the top-level module and query its ports.
* At this point they do not exist, so request a callback once they do.
*/
cbd.user_data = (PLI_BYTE8 *)CTX_VAR;
vpi_register_cb(&cbd);
}
/* This is a table of registration functions. It is the external symbol
* that the GHDL simulator looks for when loading this .vpi module.
*/
void (*vlog_startup_routines[])(void) = {
start,
0
};

188
src/xspice/vhdl/ghnggen Normal file
View File

@ -0,0 +1,188 @@
*ng_script_with_params
// This Ngspice interpreter script accepts arbitrary arguments to
// the GHDL compiler (VHDL to LLVM) and builds a shared library
// or DLL that can be loaded by the d_cosim XSPICE code model.
// Instances of the model are then digital circuit elements whose
// behaviour is controlled by the Verilog source.
set bad=0
if $?argc = 0
set bad=1
end
if $argc <= 0
set bad=1
end
if $bad
echo Arguments acceptable to GHDL are required.
quit
end
// Disable special processing of '{'.
set noglob
if $oscompiled = 2 | $oscompiled = 3 | $oscompiled = 8 // Windows
set windows=1
set dirsep1="\\"
set dirsep2="/"
else
set windows=0
set dirsep1="/"
if $oscompiled = 7 // MacOS needs an option to allow undefined symbols.
setcs ld_magic="-Wl,-undefined,dynamic_lookup"
else
set ld_magic=""
end
end
// Is there a "-top" option first?
strcmp top "$argv[1]" "-top"
if $top = 0
if $argc < 3
echo There must be at least one source file!
quit
end
set base = "$argv[2]" // The top entity name for "ghdl -e".
shift
shift
else
// Loop through the arguments to find GHDL source: some_path/xxxx.vhd
// or similar. The output file will have the same base name.
let index=1
set off=1 // Avoid error in dowhile
repeat $argc
set base="$argv[$&index]"
let index = index + 1
strstr l "$base" "-" // Is it an option?
if $l = 0
continue
end
strstr l "$base" "" // Get string length
dowhile $off >= 0 // Strip leading directories
strstr off "$base" "$dirsep1"
if $windows
if $off < 0
strstr off "$base" "$dirsep2"
end
end
if $off >= 0
let off=$off+1
strslice base "$base" $&off $l
end
end
strstr off "$base" "." // Strip any file type suffix.
if $off >= 0
strslice base "$base" 0 $off
end
strstr l "$base" "" // Check for zero-length string
if $l > 0
break
end
end
if index - 1 > $argc
echo No file for top-level entity was found.
quit
end
end
// Default base name of output file.
if $windows
setcs tail=".DLL"
else
setcs tail=".so"
end
setcs soname="$base$tail"
// The shared library/DLL contains some ngspice source code as
// well as that created by GHDL. Find it by scanning $sourcepath.
set shimfile=ghdl_shim.c
set shimobj=ghdl_shim.o
set srcdir=src
set hfile="cmtypes.h"
set hpath="ngspice$dirsep1$hfile"
set silent_fileio // Silences fopen complaints
let i=1
repeat $#sourcepath
set stem="$sourcepath[$&i]"
let i = i + 1
set fn="$stem$dirsep1$shimfile"
fopen fh "$fn"
if $fh < 0
// Look in any "src" subdirectory (probably in installed tree).
set stem="$stem$dirsep1$srcdir"
set fn="$stem$dirsep1$shimfile"
fopen fh $fn
end
if $fh > 0
// Found ghdl_shim.c, but it needs header files on relative path.
fclose $fh
set hn="$stem$dirsep1$hpath"
fopen fh "$hn"
if $fh > 0
break
end
echo Ignoring source file "$fn" as "$hn" was not found.
end
end
if $fh > 0
fclose $fh
else
echo Can not find C source file $shimfile
quit
end
// Some header files are with the source.
strstr off "$stem" "."
if $off <> 0
setcs include="-I$stem"
else
setcs include="-I..$dirsep1$stem" // Relative path
end
// Check for ghdl_shim.o in the current directory. If not present, build it.
set silent_fileio
fopen fh ghdl_shim.o
if $fh < 0
shell clang -c -g -fPIC $include -o ghdl_shim.o $stem/ghdl_shim.c
else
fclose $fh
end
unset silent_fileio
// Compile the VHDL code.
shell ghdl -a $argv
strcmp bad "$shellstatus" "0"
if $bad = 0
shell ghdl -e -shared "-Wl,ghdl_shim.o" $base
else
quit
end
// Check for ghdlng.vpi in the current directory. If not present, build it.
set silent_fileio
fopen fh ghdlng.vpi
if $fh < 0
shell ghdl --vpi-compile clang -g -c -fdeclspec -Wno-ignored-attributes $include $stem/ghdl_vpi.c -o ghdl_vpi.o
shell ghdl --vpi-link clang $ld_magic ghdl_vpi.o -o ghdlng.vpi -lm -lpthread
else
fclose $fh
end
unset silent_fileio
quit

View File

@ -79,3 +79,7 @@ copy xspice\verilog\*.cpp %dst%\share\ngspice\scripts\src
copy include\ngspice\cosim.h %dst%\share\ngspice\scripts\src\ngspice
copy include\ngspice\miftypes.h %dst%\share\ngspice\scripts\src\ngspice
copy include\ngspice\cmtypes.h %dst%\share\ngspice\scripts\src\ngspice
copy xspice\verilog\coroutine*.h %dst%\share\ngspice\scripts\src\ngspice
copy xspice\vhdl\ghnggen %dst%\share\ngspice\scripts
copy xspice\vhdl\ghdl_shim.* %dst%\share\ngspice\scripts\src
copy xspice\vhdl\ghdl_vpi.c %dst%\share\ngspice\scripts\src

View File

@ -80,3 +80,7 @@ copy xspice\verilog\*.cpp %dst%\share\ngspice\scripts\src
copy include\ngspice\cosim.h %dst%\share\ngspice\scripts\src\ngspice
copy include\ngspice\miftypes.h %dst%\share\ngspice\scripts\src\ngspice
copy include\ngspice\cmtypes.h %dst%\share\ngspice\scripts\src\ngspice
copy xspice\verilog\coroutine*.h %dst%\share\ngspice\scripts\src\ngspice
copy xspice\vhdl\ghnggen %dst%\share\ngspice\scripts
copy xspice\vhdl\ghdl_shim.* %dst%\share\ngspice\scripts\src
copy xspice\vhdl\ghdl_vpi.c %dst%\share\ngspice\scripts\src

View File

@ -38,10 +38,6 @@
#define CIDER 1
/* don't undef CIDER, otherwise compilation will fail */
/* Support for Verilog-A(MS) models */
/* #undef ADMS */
/* ADMS compilation is not supported with MS Visual Studio */
/* Define if we want debug sensitivity analysis */
/* #undef ASDEBUG */