Merge branch 'pre-master-46' into bt_dev

This commit is contained in:
Brian Taylor 2026-03-23 19:27:41 -07:00
commit a044a43dd4
89 changed files with 966 additions and 506 deletions

View File

@ -51,6 +51,7 @@ let newstime = stime/1.4
let deltime = newstime/100 let deltime = newstime/100
alter @V1[sin] [ 0 $&vmax $&newfreq ] alter @V1[sin] [ 0 $&vmax $&newfreq ]
tran $&deltime $&newstime uic tran $&deltime $&newstime uic
set xbrushwidth=2
* the 'programming' currents * the 'programming' currents
plot tran1.alli tran2.alli alli title 'Memristor with threshold: Internal Programming currents' plot tran1.alli tran2.alli alli title 'Memristor with threshold: Internal Programming currents'
* resistance versus time plot * resistance versus time plot

View File

@ -65,6 +65,7 @@ let newstime = stime/1.4
let deltime = newstime/100 let deltime = newstime/100
alter @V1[sin] [ 0 $&vmax $&newfreq ] alter @V1[sin] [ 0 $&vmax $&newfreq ]
tran $&deltime $&newstime uic tran $&deltime $&newstime uic
set xbrushwidth=2
* the resistor currents * the resistor currents
plot tran1.alli tran2.alli alli title 'Memristor with threshold: currents' plot tran1.alli tran2.alli alli title 'Memristor with threshold: currents'
* calculate resistance (avoid dividing by zero) * calculate resistance (avoid dividing by zero)

View File

@ -1,79 +0,0 @@
.title KiCad schematic
.include "F5models.lib"
.include "script-optran.txt"
R2 in 0 47.5k
R1 Net-_Q1-Pad2_ in 1k
R5 +32 Net-_P1-Pad1_ 1k
R3 Net-_P3-Pad1_ 0 10
R4 0 Net-_P3-Pad3_ 10
R6 Net-_P2-Pad1_ -32 1k
R7 out Net-_P3-Pad1_ 220
R8 out Net-_P3-Pad1_ 220
R9 out Net-_P3-Pad3_ 220
R10 out Net-_P3-Pad3_ 220
R11 Net-_R11-Pad1_ Net-_P1-Pad1_ 2.2k
R13 Net-_Q3-Pad2_ Net-_P1-Pad1_ 47.5
R15 Net-_Q5-Pad2_ Net-_P2-Pad1_ 47.5
R12 Net-_R12-Pad1_ Net-_P2-Pad1_ 2.2k
R17 +32 Net-_D3a1-Pad1_ 1
R21 Net-_D1a1-Pad2_ -32 1
R18 +32 Net-_D3a1-Pad1_ 1
R22 Net-_D1a1-Pad2_ -32 1
R16 Net-_Q6-Pad2_ Net-_P2-Pad1_ 47.5
R14 Net-_Q4-Pad2_ Net-_P1-Pad1_ 47.5
R19 +32 Net-_D4a1-Pad1_ 1
R23 Net-_D2a1-Pad2_ -32 1
R20 +32 Net-_D4a1-Pad1_ 1
R24 Net-_D2a1-Pad2_ -32 1
Ra2 Net-_Ra1-Pad2_ 0 4
D3a1 +32 Net-_D3a1-Pad1_ DMOD
D1a1 Net-_D1a1-Pad2_ -32 DMOD
D3b1 +32 Net-_D3a1-Pad1_ DMOD
D1b1 Net-_D1a1-Pad2_ -32 DMOD
D4a1 +32 Net-_D4a1-Pad1_ DMOD
D2a1 Net-_D2a1-Pad2_ -32 DMOD
D4b1 +32 Net-_D4a1-Pad1_ DMOD
D2b1 Net-_D2a1-Pad2_ -32 DMOD
XP3 Net-_P3-Pad1_ 0 Net-_P3-Pad3_ RPOT value=200 ratio={rp3}
XP1 Net-_P1-Pad1_ +32 +32 RPOT value=5k ratio={rp1}
XP2 Net-_P2-Pad1_ -32 -32 RPOT value=5k ratio={rp2}
V3 in 0 dc 0 ac 1 sin(0 2 1k 5m)
JQ1 Net-_P1-Pad1_ Net-_Q1-Pad2_ Net-_P3-Pad1_ 2SK170
JQ2 Net-_P2-Pad1_ Net-_Q1-Pad2_ Net-_P3-Pad3_ 2SJ74
MQ5 out Net-_Q5-Pad2_ Net-_D1a1-Pad2_ Q5tj Q5tc IRFP240 thermal
MQ4 out Net-_Q4-Pad2_ Net-_D4a1-Pad1_ Q4tj Q4tc IRFP9240 thermal
MQ6 out Net-_Q6-Pad2_ Net-_D2a1-Pad2_ Q6tj Q6tc IRFP240 thermal
Rj1 Q3tj 0 1G
Rj2 Q4tj 0 1G
Rj3 Q5tj 0 1G
Rj4 Q6tj 0 1G
Rc2 Q3hs Net-_Rc2-Pad2_ {hs}
Rc4 Q4hs Net-_Rc2-Pad2_ {hs}
Rc6 Q5hs Net-_Rc2-Pad2_ {hs}
Rc8 Q6hs Net-_Rc2-Pad2_ {hs}
Rc1 Q3tc Q3hs {chs}
Rc3 Q4tc Q4hs {chs}
Rc5 Q5tc Q5hs {chs}
Rc7 Q6tc Q6hs {chs}
Vt1 Net-_Rc2-Pad2_ 0 {envtemp}
Cc1 Q3hs 0 {hscc}
Cc3 Q5hs 0 {hscc}
Cc4 Q6hs 0 {hscc}
V1 +32 0 dc 32 ; pulse(0 32 0.4m 2m 2m 100 200)
V2 -32 0 dc -32 ; pulse(0 -32 0.4m 2m 2m 100 200)
XTH2 Net-_D1a1-Pad2_ Q5hs Net-_R12-Pad1_ th R25=4.7k
XTH1 Net-_D3a1-Pad1_ Q3hs Net-_R11-Pad1_ th R25=4.7k
MQ3 out Net-_Q3-Pad2_ Net-_D3a1-Pad1_ Q3tj Q3tc IRFP9240 thermal
Vs1 Net-_S1-Pad3_ 0 dc 0 pulse(0 5 6 1m 1m 20 20)
XS1 Net-_Ra1-Pad2_ 0 Net-_S1-Pad3_ 0 genrelay
Cc2 Q4hs 0 {hscc}
Ra1 out Net-_Ra1-Pad2_ 4
.tran 20u 5
.param envtemp=40
.param chs=1
.param hs=1.2
.param hscc=1
.param rp2=0.21
.param rp1=0.36
.param rp3=0.505
.end

View File

@ -1,78 +0,0 @@
* The models of this library are in the public domain
* from https://www.diyaudio.com/forums/solid-state/252973-2sk170-2sj74-spice-model-pass-0-4ma.html
*2SJ74 Dep-Mode 20mA 400mW LowNoise pkg:TO-92B 2,1,3
.MODEL 2SJ74 PJF(Beta=92.12m Rs=7.748 Rd=7.748 Lambda=4.464m
+Vto=-.5428 Cgd=85.67p Pb=.3905 Fc=.5
+Cgs=78.27p Is=12.98p
+Kf=26.64E-18 Af=1)
*2SK170
* 20mA 400mW LowNoise Dep-Mode pkg:TO-92B 3,1,2
.MODEL 2SK170 NJF(Beta=59.86m Rs=4.151 Rd=4.151 Lambda=1.923m
+Vto=-.5024 Cgd=20p Pb=.4746 Fc=.5
+Cgs=25.48p Is=8.477p
+Kf=111.3E-18 Af=1)
.subckt RPOT 1 2 3
R1 1 2 {value*ratio + 1m}
R2 2 3 {value*(1-ratio)+ 1m}
* below are default parameters, which are required by some simulators
.param value=1k
.param ratio=1
.ends
.model IRFP240 VDMOS nchan
+ Vto=4 Kp=5.9 Lambda=.001 Theta=0.015 ksubthres=.27
+ Rd=61m Rs=18m Rg=3 Rds=1e7
+ Cgdmax=2.45n Cgdmin=10p a=0.3 Cgs=1.2n
+ Is=60p N=1.1 Rb=14m XTI=3
+ Cjo=1.5n Vj=0.8 m=0.5
+ tcvth=0.0065 MU=-1.27 texp0=1.5
+ Rthjc=0.4 Cthj=0.1
+ mtriode=0.8
.model IRFP9240 VDMOS pchan
+ Vto=-4 Kp=8.8 Lambda=.003 Theta=0.08 ksubthres=.35
+ Rd=180m Rs=50m Rg=3 Rds=1e7
+ Cgdmax=1.25n Cgdmin=50p a=0.23 Cgs=1.15n
+ Is=150p N=1.3 Rb=16m XTI=2
+ Cjo=1.3n Vj=0.8 m=0.5
+ tcvth=0.004 MU=-1.27 texp0=1.5
+ Rthjc=0.4 Cthj=0.1
+ mtriode=0.6
.model DMOD D
* Thermistor model
.subckt th n1 nt n2
.param B=3977
.param R25=4700
*control node
Ctherm1 n1 0 100p
Ctherm2 n2 0 100p
Rtherm n1 n2 R = {R25*exp(B*(1/(v(nt)+273.15)-1/(25+273.15)))}
.ends
* generic relay model
.subckt genrelay out1 out2 in1 in2
.param ron = 10m
S1 out1 out2 in1 in2 SW
.MODEL SW VSWITCH(VON=4V VOFF=1V RON={ron} ROFF=100K)
.ends
.MODEL IXTH16N10 VDMOS Nchan Vds=100
+ VTO=-3.2 KP=9
+ Lambda=2m
+ Mtriode=1.8
+ Ksubthres=120m
+ subshift=160m
+ Rs=4m Rd=5m Rds=200e6
+ Cgdmax=9000p Cgdmin=300p A=0.25
+ Cgs=5500p Cjo=11000p
+ Is=10e-6 Rb=8m
+ BV=200 IBV=250e-6
+ NBV=4
+ TT=250e-9
+ vq=100
+ rq=0.1
+ Rthjc=0.2 Cthj=0.1

View File

@ -1,10 +1,5 @@
ngspice input files using optran ngspice input files using optran
Pass Labs F5 turbo
thermal simulation
use optran for 4s and coarse steps to obtain stable temperature
then simulate transient with high resolution
HiPass3opamps_optran.cir HiPass3opamps_optran.cir
Just a check with three different OpAmps Just a check with three different OpAmps

View File

@ -1,55 +0,0 @@
.temp {envtemp}
.param envtemp=40
.option savecurrents
.control
set controlswait
if $?sharedmode
* script for shared ngspice
version
rusage
else
*** script for standard ngspice
* Start optran without first iteration,
* without gmin stepping and without src stepping
* optran step size 10 ms, duration 40s,
optran 1 0 0 10m 40 0
* check the first 10 ms, input is switched on after 5 ms
tran 1u 10m
echo
* output power
let po = @ra1[i] * v(out)
meas tran power_rms rms po from=5m to=10m
echo
rusage
* temperature transistor Q6
set xbrushwidth=4
settype temperature q6tj q6tc q6hs
plot q6tj q6tc q6hs q3tj q3tc q3hs ylimit 40 140
set xbrushwidth=2
* input and output voltages
plot in out
* power supply currents
*plot V1#branch V2#branch ylimit -50 50
plot V1#branch V2#branch ylimit -10 10
* output current
plot @ra1[i]
*plot @ra1[i] xlimit 0 5m ylimit -0.3 0.3
* resistance of thermistor2 TH1, TH2
let rth1 = (v("net-_d3a1-pad1_") - v("net-_r11-pad1_")) / (@b.xth1.brtherm[i] + 1n)
let rth2 = (v("net-_d1a1-pad2_") - v("net-_r12-pad1_")) / (@b.xth2.brtherm[i] + 1n)
settype impedance rth1 rth2
plot rth1 rth2 ylimit 0 5k
ac dec 10 1 1Meg
plot db(out)
plot cph(out)
tran 1u 100m
fft out
set xbrushwidth=4
set color0=white
plot mag(out) xlimit 0 10k
* to see the harmonics
plot mag(out) xlimit 0 10k ylimit 0 30m
end
.endc

View File

@ -27,7 +27,7 @@ R2 2 3 {value*(1-ratio)+ 1m}
+ Cgdmax=2.45n Cgdmin=10p a=0.3 Cgs=1.2n + Cgdmax=2.45n Cgdmin=10p a=0.3 Cgs=1.2n
+ Is=60p N=1.1 Rb=14m XTI=3 + Is=60p N=1.1 Rb=14m XTI=3
+ Cjo=1.5n Vj=0.8 m=0.5 + Cjo=1.5n Vj=0.8 m=0.5
+ tcvth=0.0065 MU=-1.27 texp0=1.5 + tcvth=-0.0065 MU=-1.27 texp0=1.5
+ Rthjc=0.4 Cthj=0.1 + Rthjc=0.4 Cthj=0.1
+ mtriode=0.8 + mtriode=0.8

View File

@ -4,7 +4,7 @@
+ Cgdmax=2.45n Cgdmin=10p a=0.3 Cgs=1.2n + Cgdmax=2.45n Cgdmin=10p a=0.3 Cgs=1.2n
+ Is=60p N=1.1 Rb=14m XTI=3 + Is=60p N=1.1 Rb=14m XTI=3
+ Cjo=1.5n Vj=0.8 m=0.5 + Cjo=1.5n Vj=0.8 m=0.5
+ tcvth=0.0065 MU=-1.27 texp0=1.5 + tcvth=-0.0065 MU=-1.27 texp0=1.5
+ Rthjc=0.4 Cthj=0.1 + Rthjc=0.4 Cthj=0.1
+ mtriode=0.8 + mtriode=0.8

View File

@ -14,6 +14,7 @@ cout buf ss 1pF
* this is needed * this is needed
.option reltol=1e-4 .option reltol=1e-4
.option ltereltol=1e-4
.tran 0.2n 16n .tran 0.2n 16n
.print tran v(out25) v(out50) .print tran v(out25) v(out50)
@ -48,6 +49,7 @@ if $?batchmode
else else
save out25 out50 save out25 out50
run run
rusage time
plot out25 out50 plot out25 out50
let lin-tstart = 4n $ skip the start-up phase let lin-tstart = 4n $ skip the start-up phase
let lin-tstop = 14n $ end earlier(just for demonstration) let lin-tstop = 14n $ end earlier(just for demonstration)

View File

@ -0,0 +1,27 @@
test mtimeavg
* noise source
VNoiw 1 0 DC 0 TRNOISE(20n 0.5n 0 0)
.control
tran 0.5n 500n
set color3=orange
set color5=red
set mtimeavgwindow=5n
let filtered5n = mtimeavg(V(1))
set mtimeavgwindow=10n
let filtered10n = mtimeavg(V(1))
set mtimeavgwindow=20n
let filtered20n = mtimeavg(V(1))
set mtimeavgwindow=50n
let filtered50n = mtimeavg(V(1))
set xbrushwidth=2
set color0=white
plot filtered5n filtered10n filtered20n filtered50n ylimit -50n 50n
set xbrushwidth=1
set color3=red
plot V(1) filtered50n ylimit -50n 50n
.endc
.end

View File

@ -35,7 +35,7 @@ Xtr3 1 0 22 0 tr3
.ends .ends
* transformer 2 * transformer 2
* ngspice manual 12.2.20 and 12.2.21 * ngspice manual 8.2.21 and 8.2.22
* px primary nodes, sx secondary nodes of electric circuit * px primary nodes, sx secondary nodes of electric circuit
* mcx nodes of magnetic circuit * mcx nodes of magnetic circuit
.subckt tr2 p1 p2 s1 s2 .subckt tr2 p1 p2 s1 s2

View File

@ -84,7 +84,7 @@ plot inoise_spectrum
+ Cgdmax=2.45n Cgdmin=10p a=0.3 Cgs=1.2n + Cgdmax=2.45n Cgdmin=10p a=0.3 Cgs=1.2n
+ Is=60p N=1.1 Rb=14m XTI=3 + Is=60p N=1.1 Rb=14m XTI=3
+ Cjo=1.5n Vj=0.8 m=0.5 + Cjo=1.5n Vj=0.8 m=0.5
+ tcvth=0.0065 MU=-1.27 texp0=1.5 + tcvth=-0.0065 MU=-1.27 texp0=1.5
+ Rthjc=0.4 Cthj=5e-3 + Rthjc=0.4 Cthj=5e-3
+ mtriode=0.8 + mtriode=0.8
.model IRFP9240 VDMOS pchan .model IRFP9240 VDMOS pchan

View File

@ -67,7 +67,7 @@ end
+ Cgdmax=2.45n Cgdmin=10p a=0.3 Cgs=1.2n + Cgdmax=2.45n Cgdmin=10p a=0.3 Cgs=1.2n
+ Is=60p N=1.1 Rb=14m XTI=3 + Is=60p N=1.1 Rb=14m XTI=3
+ Cjo=1.5n Vj=0.8 m=0.5 + Cjo=1.5n Vj=0.8 m=0.5
+ tcvth=0.0065 MU=-1.27 texp0=1.5 + tcvth=-0.0065 MU=-1.27 texp0=1.5
*+ Rthjc=0.4 Cthj=5e-3 *+ Rthjc=0.4 Cthj=5e-3
+ mtriode=0.8 + mtriode=0.8
.model IRFP9240 VDMOS pchan .model IRFP9240 VDMOS pchan

View File

@ -40,7 +40,7 @@ plot 'i(v6)/deriv(v(d4))' vs v(d2p) xlog xlimit 1 100 ylimit 0 3n title "IRFP924
+ Cgdmax=2.45n Cgdmin=10p a=0.3 Cgs=1.2n + Cgdmax=2.45n Cgdmin=10p a=0.3 Cgs=1.2n
+ Is=60p N=1.1 Rb=14m XTI=3 + Is=60p N=1.1 Rb=14m XTI=3
+ Cjo=1.5n Vj=0.8 m=0.5 + Cjo=1.5n Vj=0.8 m=0.5
+ tcvth=0.0065 MU=-1.27 texp0=1.5 + tcvth=-0.0065 MU=-1.27 texp0=1.5
*+ Rthjc=0.4 Cthj=5e-3 *+ Rthjc=0.4 Cthj=5e-3
+ mtriode=0.8 + mtriode=0.8
.model IRFP9240 VDMOS pchan .model IRFP9240 VDMOS pchan

View File

@ -26,7 +26,7 @@ V4 out2 0 0.0
+ Cgdmax=.2n Cgdmin=.05n a=0.3 Cgs=.12n + Cgdmax=.2n Cgdmin=.05n a=0.3 Cgs=.12n
+ Is=17p N=1.1 Rb=80m XTI=3 + Is=17p N=1.1 Rb=80m XTI=3
+ Cjo=.25n Vj=0.8 m=0.5 + Cjo=.25n Vj=0.8 m=0.5
+ tcvth=0.007 MU=-1.27 texp0=1.5 + tcvth=-0.007 MU=-1.27 texp0=1.5
.model MBRS340 D(Is=22.6u Rs=.042 N=1.094 Cjo=480p M=.61 Eg=.69 Xti=2) .model MBRS340 D(Is=22.6u Rs=.042 N=1.094 Cjo=480p M=.61 Eg=.69 Xti=2)

View File

@ -10,7 +10,7 @@ VD D 0 2V
+ Cgdmax=2.45n Cgdmin=10p a=0.3 Cgs=1.2n + Cgdmax=2.45n Cgdmin=10p a=0.3 Cgs=1.2n
+ Is=60p N=1.1 Rb=14m XTI=3 + Is=60p N=1.1 Rb=14m XTI=3
+ Cjo=1.5n Vj=0.8 m=0.5 + Cjo=1.5n Vj=0.8 m=0.5
+ tcvth=0.0065 MU=-1.27 texp0=1.5 + tcvth=-0.0065 MU=-1.27 texp0=1.5
+ Rthjc=0.02 Cthj=1e-3 Rthca=1000 + Rthjc=0.02 Cthj=1e-3 Rthca=1000
+ mtriode=0.8 + mtriode=0.8
.control .control

View File

@ -5,7 +5,7 @@ VDMOS SOA check
+ Rd=61m Rs=18m Rg=3 Rds=1e7 + Rd=61m Rs=18m Rg=3 Rds=1e7
+ Cgdmax=2.45n Cgdmin=10p a=0.3 Cgs=1.2n + Cgdmax=2.45n Cgdmin=10p a=0.3 Cgs=1.2n
+ Is=60p N=1.1 Rb=14m Cjo=1.5n XTI=3 + Is=60p N=1.1 Rb=14m Cjo=1.5n XTI=3
+ tcvth=0.0065 MU=-1.27 texp0=1.5 + tcvth=-0.0065 MU=-1.27 texp0=1.5
+ mtriode=0.8 + mtriode=0.8
+ Vgs_max=20 Vgd_max=20 Vds_max=200 + Vgs_max=20 Vgd_max=20 Vds_max=200

View File

@ -21,7 +21,7 @@ bin_PROGRAMS = ngspice
if OLDAPPS if OLDAPPS
if !WINGUI if !WINGUI
bin_PROGRAMS += ngnutmeg ngsconvert ngproc2mod ngmultidec ngmakeidx bin_PROGRAMS += ngsconvert ngproc2mod ngmultidec ngmakeidx
helpdatadir = $(pkgdatadir)/helpdir helpdatadir = $(pkgdatadir)/helpdir
helpdata_DATA = ngspice.txt ngspice.idx helpdata_DATA = ngspice.txt ngspice.idx
if !NO_HELP if !NO_HELP
@ -220,50 +220,11 @@ endif
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --tag=RC --mode=compile $(RC) $(RCFLAGS) $< -o $@ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --tag=RC --mode=compile $(RC) $(RCFLAGS) $< -o $@
if OLDAPPS if OLDAPPS
## nutmeg:
ngnutmeg_SOURCES = \
main.c \
conf.c \
conf.h \
ngnutmeg.c
ngnutmeg_CPPFLAGS = $(AM_CPPFLAGS)
if WINGUI
ngnutmeg_SOURCES += winmain.c hist_info.c
endif
ngnutmeg_LDADD = \
frontend/libfte.la
if WINGUI
ngnutmeg_LDADD += \
frontend/wdisp/libwindisp.la
endif
ngnutmeg_LDADD += \
frontend/plotting/libplotting.la \
frontend/parser/libparser.la \
frontend/numparam/libnumparam.la \
frontend/trannoise/libtrannoise.la \
maths/cmaths/libcmaths.la \
maths/misc/libmathmisc.la \
maths/fft/libmathfft.la \
maths/poly/libpoly.la \
misc/libmisc.la \
spicelib/parser/libinp.la
## These programs are not required on Windows ## These programs are not required on Windows
if !WINGUI if !WINGUI
if !SHWIN if !SHWIN
if !NO_X
ngnutmeg_LDADD += \
frontend/help/libhlp.la
endif !NO_X
## help: ## help:
nghelp_SOURCES = conf.c nghelp.c nghelp_SOURCES = conf.c nghelp.c

View File

@ -517,7 +517,7 @@ ft_bpcheck(struct plot *runplot, int iteration)
if ((howmanysteps > 0) && (--howmanysteps == 0)) { if ((howmanysteps > 0) && (--howmanysteps == 0)) {
if (steps > 1) if (steps > 1)
fprintf(cp_err, "Stopped after %d steps.\n", steps); fprintf(cp_out, "Note: Stopped after %d steps.\n", steps);
return (FALSE); return (FALSE);
} }
@ -694,3 +694,14 @@ printcond(struct dbcomm *d, FILE *fp)
} }
} }
} }
/* just check if we are in 'step' mode */
bool
ft_stepcheck(void)
{
if ((steps > 0) && (howmanysteps == 0)) {
return (TRUE);
}
return (FALSE);
}

View File

@ -15,6 +15,7 @@ if (wl && wl->wl_word)
if (load_opus(wl->wl_word)) { if (load_opus(wl->wl_word)) {
fprintf(stderr, "Error: Library %s couldn't be loaded!\n", wl->wl_word); fprintf(stderr, "Error: Library %s couldn't be loaded!\n", wl->wl_word);
ft_spiniterror = TRUE; ft_spiniterror = TRUE;
ft_codemodelerror = TRUE;
if (ft_stricterror) /* if set in spinit */ if (ft_stricterror) /* if set in spinit */
controlled_exit(EXIT_BAD); controlled_exit(EXIT_BAD);
} }
@ -34,6 +35,7 @@ void com_osdi(wordlist *wl)
if (load_osdi(ww->wl_word)) { if (load_osdi(ww->wl_word)) {
fprintf(cp_err, "Error: Library %s couldn't be loaded!\n", ww->wl_word); fprintf(cp_err, "Error: Library %s couldn't be loaded!\n", ww->wl_word);
ft_spiniterror = TRUE; ft_spiniterror = TRUE;
ft_osdierror = TRUE;
if (ft_stricterror) if (ft_stricterror)
controlled_exit(EXIT_BAD); controlled_exit(EXIT_BAD);
} }

View File

@ -58,11 +58,19 @@ com_fft(wordlist *wl)
} }
length = (plot_cur->pl_scale)->v_length; length = (plot_cur->pl_scale)->v_length;
/* in case of tran error */
if (length < 2) {
fprintf(cp_err, "Error: fft needs more than one time point, check the tran simulation!\n");
goto done;
}
time = (plot_cur->pl_scale)->v_realdata; time = (plot_cur->pl_scale)->v_realdata;
span = time[length-1] - time[0]; span = time[length-1] - time[0] + time[length-1] - time[length-2];
#ifdef HAVE_LIBFFTW3 #ifdef HAVE_LIBFFTW3
fpts = length/2 + 1; fpts = length/2 + 1;
scale = ((double)length)/2.0;
#else #else
/* size of fft input vector is power of two and larger or equal than spice vector */ /* size of fft input vector is power of two and larger or equal than spice vector */
N = 1; N = 1;
@ -72,6 +80,7 @@ com_fft(wordlist *wl)
M++; M++;
} }
fpts = N/2 + 1; fpts = N/2 + 1;
scale = ((double)N)/2;
#endif #endif
win = TMALLOC(double, length); win = TMALLOC(double, length);
@ -84,7 +93,7 @@ com_fft(wordlist *wl)
order = 2; order = 2;
if (fft_windows(window, win, time, length, maxt, span, order) == 0) if (fft_windows(window, win, time, length, maxt, span, order) == 0)
goto done; fprintf(cp_err, "Warning: unknown window type %s for fft, set to \"none\" \n", window);
names = ft_getpnames_quotes(wl, TRUE); names = ft_getpnames_quotes(wl, TRUE);
vlist = NULL; vlist = NULL;
@ -178,14 +187,16 @@ com_fft(wordlist *wl)
fftw_execute(plan_forward); fftw_execute(plan_forward);
scale = (double) fpts - 1.0;
fdvec[i][0].cx_real = out[0][0]/scale/2.0; fdvec[i][0].cx_real = out[0][0]/scale/2.0;
fdvec[i][0].cx_imag = 0.0; fdvec[i][0].cx_imag = 0.0;
for (j = 1; j < fpts; j++) { for (j = 1; j < fpts; j++) {
fdvec[i][j].cx_real = out[j][0]/scale; fdvec[i][j].cx_real = out[j][0]/scale;
fdvec[i][j].cx_imag = out[j][1]/scale; fdvec[i][j].cx_imag = out[j][1]/scale;
} }
if (length % 2 == 0) {
fdvec[i][fpts-1].cx_real = out[fpts-1][0]/scale/2.0;
fdvec[i][fpts-1].cx_imag = 0.0;
}
} }
fftw_destroy_plan(plan_forward); fftw_destroy_plan(plan_forward);
@ -212,7 +223,6 @@ com_fft(wordlist *wl)
rffts(in, M, 1); rffts(in, M, 1);
fftFree(); fftFree();
scale = (double) fpts - 1.0;
/* Re(x[0]), Re(x[N/2]), Re(x[1]), Im(x[1]), Re(x[2]), Im(x[2]), ... Re(x[N/2-1]), Im(x[N/2-1]). */ /* Re(x[0]), Re(x[N/2]), Re(x[1]), Im(x[1]), Re(x[2]), Im(x[2]), ... Re(x[N/2-1]), Im(x[N/2-1]). */
fdvec[i][0].cx_real = in[0]/scale/2.0; fdvec[i][0].cx_real = in[0]/scale/2.0;
fdvec[i][0].cx_imag = 0.0; fdvec[i][0].cx_imag = 0.0;
@ -220,7 +230,7 @@ com_fft(wordlist *wl)
fdvec[i][j].cx_real = in[2*j]/scale; fdvec[i][j].cx_real = in[2*j]/scale;
fdvec[i][j].cx_imag = in[2*j+1]/scale; fdvec[i][j].cx_imag = in[2*j+1]/scale;
} }
fdvec[i][fpts-1].cx_real = in[1]/scale; fdvec[i][fpts-1].cx_real = in[1]/scale/2.0;
fdvec[i][fpts-1].cx_imag = 0.0; fdvec[i][fpts-1].cx_imag = 0.0;
tfree(in); tfree(in);
@ -416,15 +426,17 @@ com_psd(wordlist *wl)
fdvec[i][0].cx_real = out[0][0]*out[0][0]/intres; fdvec[i][0].cx_real = out[0][0]*out[0][0]/intres;
fdvec[i][0].cx_imag = 0; fdvec[i][0].cx_imag = 0;
noipower = fdvec[i][0].cx_real; noipower = fdvec[i][0].cx_real;
for (j = 1; j < fpts-1; j++) { for (j = 1; j < fpts; j++) {
fdvec[i][j].cx_real = 2.* (out[j][0]*out[j][0] + out[j][1]*out[j][1])/intres; fdvec[i][j].cx_real = 2.* (out[j][0]*out[j][0] + out[j][1]*out[j][1])/intres;
fdvec[i][j].cx_imag = 0; fdvec[i][j].cx_imag = 0;
noipower += fdvec[i][j].cx_real; noipower += fdvec[i][j].cx_real;
if (!finite(noipower)) if (!finite(noipower))
break; break;
} }
fdvec[i][fpts-1].cx_real = out[fpts-1][0]*out[fpts-1][0]/intres; if (length % 2 == 0) {
fdvec[i][fpts-1].cx_imag = 0; fdvec[i][fpts-1].cx_real = out[fpts-1][0]*out[fpts-1][0]/intres;
fdvec[i][fpts-1].cx_imag = 0;
}
noipower += fdvec[i][fpts-1].cx_real; noipower += fdvec[i][fpts-1].cx_real;
#else /* Green's FFT */ #else /* Green's FFT */

View File

@ -16,6 +16,8 @@
#include "com_measure2.h" #include "com_measure2.h"
#include "breakp2.h" #include "breakp2.h"
int measure_precision = -1;
typedef enum { typedef enum {
MEASUREMENT_OK = 0, MEASUREMENT_OK = 0,
MEASUREMENT_FAILURE = 1 MEASUREMENT_FAILURE = 1
@ -86,6 +88,9 @@ measure_get_precision(void)
if ((env_ptr = getenv("NGSPICE_MEAS_PRECISION")) != NULL) if ((env_ptr = getenv("NGSPICE_MEAS_PRECISION")) != NULL)
precision = atoi(env_ptr); precision = atoi(env_ptr);
if (measure_precision > 0)
precision = measure_precision;
return precision; return precision;
} }
@ -439,8 +444,13 @@ com_measure_when(
sp_check = TRUE; sp_check = TRUE;
else if (cieq (meas->m_analysis, "dc")) else if (cieq (meas->m_analysis, "dc"))
dc_check = TRUE; dc_check = TRUE;
else else {
tran_check = TRUE; tran_check = TRUE;
if (!d->v_realdata) {
fprintf(stderr, "Error: no real data available for measurement (no tran simulation?)\n");
return MEASUREMENT_FAILURE;
}
}
for (i = 0; i < d->v_length; i++) { for (i = 0; i < d->v_length; i++) {
@ -697,8 +707,13 @@ measure_at(
sp_check = TRUE; sp_check = TRUE;
else if (cieq (meas->m_analysis, "dc")) else if (cieq (meas->m_analysis, "dc"))
dc_check = TRUE; dc_check = TRUE;
else else {
tran_check = TRUE; tran_check = TRUE;
if (!d->v_realdata) {
fprintf(stderr, "Error: no real data available for measurement (no tran simulation?)\n");
return MEASUREMENT_FAILURE;
}
}
for (i = 0; i < d->v_length; i++) { for (i = 0; i < d->v_length; i++) {
if (ac_check) { if (ac_check) {
@ -1800,9 +1815,13 @@ get_measure2(
// print results // print results
if (out_line) if (out_line)
sprintf(out_line, "%-20s= %e targ= %e trig= %e\n", mName, (measTarg->m_measured - measTrig->m_measured), measTarg->m_measured, measTrig->m_measured); sprintf(out_line, "%-20s= %.*e targ= %.*e trig= %.*e\n",
mName, precision, (measTarg->m_measured - measTrig->m_measured),
precision, measTarg->m_measured, precision, measTrig->m_measured);
else else
fprintf(mout,"%-20s= %e targ= %e trig= %e\n", mName, (measTarg->m_measured - measTrig->m_measured), measTarg->m_measured, measTrig->m_measured); fprintf(mout,"%-20s= %.*e targ= %.*e trig= %.*e\n", mName, precision,
(measTarg->m_measured - measTrig->m_measured),
precision, measTarg->m_measured, precision, measTrig->m_measured);
*result = (measTarg->m_measured - measTrig->m_measured); *result = (measTarg->m_measured - measTrig->m_measured);
@ -1873,9 +1892,9 @@ err_ret1:
// print results // print results
if (out_line) if (out_line)
sprintf(out_line, "%-20s= %e\n", mName, meas->m_measured); sprintf(out_line, "%-20s= %.*e\n", mName, precision, meas->m_measured);
else else
fprintf(mout,"%-20s= %e\n", mName, meas->m_measured); fprintf(mout,"%-20s= %.*e\n", mName, precision, meas->m_measured);
*result = meas->m_measured; *result = meas->m_measured;
@ -1914,7 +1933,7 @@ err_ret2:
if (out_line) if (out_line)
sprintf(out_line, "%-20s= %.*e\n", mName, precision, meas->m_measured); sprintf(out_line, "%-20s= %.*e\n", mName, precision, meas->m_measured);
else else
fprintf(mout, "%-20s= %e\n", mName, meas->m_measured); fprintf(mout, "%-20s= %.*e\n", mName, precision, meas->m_measured);
*result = meas->m_measured; *result = meas->m_measured;
@ -2002,9 +2021,11 @@ err_ret4:
// print results // print results
if (out_line) if (out_line)
sprintf(out_line, "%-20s= %e from= %e to= %e\n", mName, meas->m_measured, meas->m_at, meas->m_measured_at); sprintf(out_line, "%-20s= %.*e from= %.*e to= %.*e\n", mName,
precision, meas->m_measured, precision, meas->m_at, precision, meas->m_measured_at);
else else
fprintf(mout, "%-20s= %e from= %e to= %e\n", mName, meas->m_measured, meas->m_at, meas->m_measured_at); fprintf(mout, "%-20s= %.*e from= %.*e to= %.*e\n", mName,
precision, meas->m_measured, precision, meas->m_at, precision, meas->m_measured_at);
*result = meas->m_measured; *result = meas->m_measured;
@ -2049,17 +2070,21 @@ err_ret5:
if ((mFunctionType == AT_MIN) || (mFunctionType == AT_MAX)) { if ((mFunctionType == AT_MIN) || (mFunctionType == AT_MAX)) {
// print results // print results
if (out_line) if (out_line)
sprintf(out_line, "%-20s= %e at= %e\n", mName, measTrig->m_measured, measTrig->m_measured_at); sprintf(out_line, "%-20s= %.*e at= %.*e\n",
mName, precision, measTrig->m_measured, precision, measTrig->m_measured_at);
else else
fprintf(mout, "%-20s= %e at= %e\n", mName, measTrig->m_measured, measTrig->m_measured_at); fprintf(mout, "%-20s= %.*e at= %.*e\n",
mName, precision, measTrig->m_measured, precision, measTrig->m_measured_at);
*result = measTrig->m_measured; *result = measTrig->m_measured;
} else { } else {
// print results // print results
if (out_line) if (out_line)
sprintf(out_line, "%-20s= %e with= %e\n", mName, measTrig->m_measured_at, measTrig->m_measured); sprintf(out_line, "%-20s= %.*e with= %.*e\n",
mName, precision, measTrig->m_measured_at, precision, measTrig->m_measured);
else else
fprintf(mout, "%-20s= %e with= %e\n", mName, measTrig->m_measured_at, measTrig->m_measured); fprintf(mout, "%-20s= %.*e with= %.*e\n",
mName, precision, measTrig->m_measured_at, precision, measTrig->m_measured);
*result = measTrig->m_measured_at; *result = measTrig->m_measured_at;
} }
@ -2107,9 +2132,11 @@ err_ret6:
// print results // print results
if (out_line) if (out_line)
sprintf(out_line, "%-20s= %e from= %e to= %e\n", mName, (maxValue - minValue), measTrig->m_from, measTrig->m_to); sprintf(out_line, "%-20s= %.*e from= %.*e to= %.*e\n",
mName, precision, (maxValue - minValue), precision, measTrig->m_from, precision, measTrig->m_to);
else else
fprintf(mout, "%-20s= %e from= %e to= %e\n", mName, (maxValue - minValue), measTrig->m_from, measTrig->m_to); fprintf(mout, "%-20s= %.*e from= %.*e to= %.*e\n",
mName, precision, (maxValue - minValue), precision, measTrig->m_from, precision, measTrig->m_to);
*result = (maxValue - minValue); *result = (maxValue - minValue);

View File

@ -858,7 +858,7 @@ apply_func_funcall(struct func *func, struct dvec *v, int *newlength, short int
/* Modified for passing necessary parameters to the derive function - A.Roldan */ /* Modified for passing necessary parameters to the derive function - A.Roldan */
if (eq(func->fu_name, "interpolate") || eq(func->fu_name, "deriv") || eq(func->fu_name, "group_delay") if (eq(func->fu_name, "interpolate") || eq(func->fu_name, "deriv") || eq(func->fu_name, "group_delay")
|| eq(func->fu_name, "fft") || eq(func->fu_name, "ifft") || eq(func->fu_name, "integ")) || eq(func->fu_name, "fft") || eq(func->fu_name, "ifft") || eq(func->fu_name, "integ") || eq(func->fu_name, "mtimeavg"))
{ {
void * (*f) (void *data, short int type, int length, void * (*f) (void *data, short int type, int length,
int *newlength, short int *newtype, int *newlength, short int *newtype,

View File

@ -23,7 +23,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
static char *pnum(double num); static char *pnum(double num);
static int CKTfour(int ndata, int numFreq, double *thd, double *Time, double *Value, static int CKTfour(int ndata, int numFreq, int numPeriod, double *thd, double *Time, double *Value,
double FundFreq, double *Freq, double *Mag, double *Phase, double *nMag, double FundFreq, double *Freq, double *Mag, double *Phase, double *nMag,
double *nPhase); double *nPhase);
@ -32,8 +32,8 @@ static int CKTfour(int ndata, int numFreq, double *thd, double *Time, double *Va
#define DEF_FOURGRIDSIZE 200 #define DEF_FOURGRIDSIZE 200
/* CKTfour(ndata, numFreq, thd, Time, Value, FundFreq, Freq, Mag, Phase, nMag, nPhase) /* CKTfour(ndata, numFreq, numPeriod, thd, Time, Value, FundFreq, Freq, Mag, Phase, nMag, nPhase)
* len 10 ? inp inp inp out out out out out * len 10 1 ? inp inp inp out out out out out
*/ */
int int
@ -42,7 +42,7 @@ fourier(wordlist *wl, struct plot *current_plot)
struct dvec *time, *vec; struct dvec *time, *vec;
struct pnode *pn, *names; struct pnode *pn, *names;
double fundfreq, *data = NULL; double fundfreq, *data = NULL;
int nfreqs, fourgridsize, polydegree; int nfreqs, nperiods, fourgridsize, polydegree;
double *freq, *mag, *phase, *nmag, *nphase; /* Outputs from CKTfour */ double *freq, *mag, *phase, *nmag, *nphase; /* Outputs from CKTfour */
double thd, *timescale = NULL; double thd, *timescale = NULL;
char *s; char *s;
@ -68,6 +68,8 @@ fourier(wordlist *wl, struct plot *current_plot)
if (!cp_getvar("nfreqs", CP_NUM, &nfreqs, 0) || nfreqs < 1) if (!cp_getvar("nfreqs", CP_NUM, &nfreqs, 0) || nfreqs < 1)
nfreqs = 10; nfreqs = 10;
if (!cp_getvar("nperiods", CP_NUM, &nperiods, 0) || nperiods < 1)
nperiods = 1;
if (!cp_getvar("polydegree", CP_NUM, &polydegree, 0) || polydegree < 0) if (!cp_getvar("polydegree", CP_NUM, &polydegree, 0) || polydegree < 0)
polydegree = 1; polydegree = 1;
if (!cp_getvar("fourgridsize", CP_NUM, &fourgridsize, 0) || fourgridsize < 1) if (!cp_getvar("fourgridsize", CP_NUM, &fourgridsize, 0) || fourgridsize < 1)
@ -112,14 +114,16 @@ fourier(wordlist *wl, struct plot *current_plot)
if (polydegree) { if (polydegree) {
double *dp, d; double *dp, d;
/* Get fourgridsize points per period */
fourgridsize = fourgridsize * nperiods;
/* Build the grid... */ /* Build the grid... */
timescale = TMALLOC(double, fourgridsize); timescale = TMALLOC(double, fourgridsize);
data = TMALLOC(double, fourgridsize); data = TMALLOC(double, fourgridsize);
dp = ft_minmax(time, TRUE); dp = ft_minmax(time, TRUE);
/* Now get the last fund freq... */ /* Now get the last fund freq... */
d = 1 / fundfreq; /* The wavelength... */ d = nperiods / fundfreq; /* The wavelength... */
if (dp[1] - dp[0] < d) { if (dp[1] - dp[0] < d) {
fprintf(cp_err, "Error: wavelength longer than time span\n"); fprintf(cp_err, "Error: (%d * wavelength) longer than time span\n", nperiods);
goto done; goto done;
} else if (dp[1] - dp[0] > d) { } else if (dp[1] - dp[0] > d) {
dp[0] = dp[1] - d; dp[0] = dp[1] - d;
@ -143,7 +147,7 @@ fourier(wordlist *wl, struct plot *current_plot)
timescale = time->v_realdata; timescale = time->v_realdata;
} }
err = CKTfour(fourgridsize, nfreqs, &thd, timescale, err = CKTfour(fourgridsize, nfreqs, nperiods, &thd, timescale,
data, fundfreq, freq, mag, phase, nmag, data, fundfreq, freq, mag, phase, nmag,
nphase); nphase);
if (err != OK) { if (err != OK) {
@ -153,9 +157,10 @@ fourier(wordlist *wl, struct plot *current_plot)
fprintf(cp_out, "Fourier analysis for %s:\n", vec->v_name); fprintf(cp_out, "Fourier analysis for %s:\n", vec->v_name);
fprintf(cp_out, fprintf(cp_out,
" No. Harmonics: %d, THD: %g %%, Gridsize: %d, Interpolation Degree: %d\n\n", " No. Harmonics: %d, THD: %g %%, Gridsize: %d, Interpolation Degree: %d,"
" No. Periods: %d\n\n",
nfreqs, thd, fourgridsize, nfreqs, thd, fourgridsize,
polydegree); polydegree, nperiods);
/* Each field will have width cp_numdgt + 6 (or 7 /* Each field will have width cp_numdgt + 6 (or 7
* with HP-UX) + 1 if there is a - sign. * with HP-UX) + 1 if there is a - sign.
*/ */
@ -288,6 +293,7 @@ static int
CKTfour(int ndata, /* number of entries in the Time and CKTfour(int ndata, /* number of entries in the Time and
Value arrays */ Value arrays */
int numFreq, /* number of harmonics to calculate */ int numFreq, /* number of harmonics to calculate */
int numPeriod, /* number of periods for detection */
double *thd, /* total harmonic distortion (percent) double *thd, /* total harmonic distortion (percent)
to be returned */ to be returned */
double *Time, /* times at which the voltage/current double *Time, /* times at which the voltage/current
@ -313,10 +319,10 @@ CKTfour(int ndata, /* number of entries in the Time and
* The arrays must all be allocated by the caller. * The arrays must all be allocated by the caller.
* The Time and Value array must be reasonably distributed over at * The Time and Value array must be reasonably distributed over at
* least one full period of the fundamental Frequency for the * least one full period of the fundamental Frequency for the
* fourier transform to be useful. The function will take the * fourier transform to be useful. The function will take
* last period of the frequency as data for the transform. * numPeriod periods of the frequency as data for the transform.
* *
* We are assuming that the caller has provided exactly one period * We are assuming that the caller has provided exactly numPeriod periods
* of the fundamental frequency. */ * of the fundamental frequency. */
int i; int i;
int j; int j;
@ -331,10 +337,10 @@ CKTfour(int ndata, /* number of entries in the Time and
Phase[i] = 0; Phase[i] = 0;
} }
for (i = 0; i < ndata; i++) for (i = 0; i < ndata ; i++)
for (j = 0; j < numFreq; j++) { for (j = 0; j < numFreq; j++) {
Mag[j] += Value[i] * sin(j*2.0*M_PI*i/((double)ndata)); Mag[j] += Value[i] * sin(j*2.0*M_PI*numPeriod*i/((double)ndata));
Phase[j] += Value[i] * cos(j*2.0*M_PI*i/((double)ndata)); Phase[j] += Value[i] * cos(j*2.0*M_PI*numPeriod*i/((double)ndata));
} }
Mag[0] = Phase[0]/ndata; Mag[0] = Phase[0]/ndata;

View File

@ -247,6 +247,10 @@ void inp_probe(struct card* deck)
if (strchr("ehvk", *instname)) if (strchr("ehvk", *instname))
continue; continue;
/* exclude B voltage source */
if (strchr("b", *instname) && strstr(curr_line, "v="))
continue;
/* exclude a devices (code models may have special characters in their instance line. /* exclude a devices (code models may have special characters in their instance line.
digital nodes should not get V sources in series anyway.) */ digital nodes should not get V sources in series anyway.) */
if ('a' == *instname) if ('a' == *instname)

View File

@ -1105,6 +1105,16 @@ struct card *inp_readall(FILE *fp, const char *dir_name, const char* file_name,
if (newcompat.ps && newcompat.a) if (newcompat.ps && newcompat.a)
pspice_compat_a(working); pspice_compat_a(working);
/* another warning that codemodels or osdi libs have not been loaded successfully */
if (ft_osdierror) {
fprintf(stderr, "Warning: OSDI libs have not been loaded successfully.\n");
fprintf(stderr, " Any of the following steps may fail, if Verilog A models are involved!.\n\n");
}
if (ft_codemodelerror) {
fprintf(stderr, "Warning: code models like analog.cm have not been loaded successfully.\n");
fprintf(stderr, " Any of the following steps may fail, if code models are involved!.\n\n");
}
struct nscope *root = inp_add_levels(working); struct nscope *root = inp_add_levels(working);
inp_probe(working); inp_probe(working);
@ -1331,6 +1341,8 @@ static struct inp_read_t inp_read(FILE* fp, int call_depth, const char* dir_name
static int is_control = 0; /* We are reading from a .control section */ static int is_control = 0; /* We are reading from a .control section */
bool found_end = FALSE, shell_eol_continuation = FALSE; bool found_end = FALSE, shell_eol_continuation = FALSE;
static bool biaswarn = FALSE;
static bool hdlwarn = FALSE;
#ifdef CIDER #ifdef CIDER
static int in_cider_model = 0; static int in_cider_model = 0;
#endif #endif
@ -1440,6 +1452,26 @@ static struct inp_read_t inp_read(FILE* fp, int call_depth, const char* dir_name
memcpy(buffer, ".inc", 4); memcpy(buffer, ".inc", 4);
} }
if (ciprefix(".hdl", buffer)) {
if (!hdlwarn) {
fprintf(cp_err, "Warning: Dot command .hdl is not supported, ingnored\n");
fprintf(cp_err, " line no. %d, %s", line_number, buffer);
fprintf(cp_err, " file %s\n", file_name);
fprintf(cp_err, " This message will be posted only once!\n\n");
hdlwarn = TRUE;
}
tfree(buffer);
continue;
}
if (ciprefix(".biaschk", buffer)) {
if (!biaswarn) {
fprintf(cp_err, "Warning: Dot command .biaschk is not supported, ingnored\n");
fprintf(cp_err, " This message will be posted only once!\n\n");
biaswarn = TRUE;
}
tfree(buffer);
continue;
}
/* now handle .include statements */ /* now handle .include statements */
if (ciprefix(".include", buffer) || ciprefix(".inc", buffer)) { if (ciprefix(".include", buffer) || ciprefix(".inc", buffer)) {
@ -1752,15 +1784,16 @@ static struct inp_read_t inp_read(FILE* fp, int call_depth, const char* dir_name
} }
#endif #endif
/* no lower case letters for lines beginning with: */ /* no lower case letters for lines beginning with: */
else if (!ciprefix("write", buffer) && else if (!(ciprefix(".lib", buffer) || ciprefix(".inc", buffer) ||
!ciprefix("wrdata", buffer) && ((comfile || is_control) && (
!ciprefix(".lib", buffer) && !ciprefix(".inc", buffer) && ciprefix("write", buffer) ||
!ciprefix("codemodel", buffer) && ciprefix("wrdata", buffer) ||
!ciprefix("osdi", buffer) && ciprefix("codemodel", buffer) ||
!ciprefix("pre_osdi", buffer) && ciprefix("osdi", buffer) ||
!ciprefix("echo", buffer) && !ciprefix("shell", buffer) && ciprefix("pre_osdi", buffer) ||
!ciprefix("source", buffer) && !ciprefix("cd ", buffer) && ciprefix("echo", buffer) || ciprefix("shell", buffer) ||
!ciprefix("load", buffer) && !ciprefix("setcs", buffer)) { ciprefix("source", buffer) ||ciprefix("cd", buffer) ||
ciprefix("load", buffer) || ciprefix("setcs", buffer))))) {
/* lower case for all other lines */ /* lower case for all other lines */
for (s = buffer; *s && (*s != '\n'); s++) for (s = buffer; *s && (*s != '\n'); s++)
*s = tolower_c(*s); *s = tolower_c(*s);
@ -1771,39 +1804,41 @@ static struct inp_read_t inp_read(FILE* fp, int call_depth, const char* dir_name
for (s = buffer; *s && (*s != '\n'); s++) for (s = buffer; *s && (*s != '\n'); s++)
; ;
} }
/* lower case for variables or vectors in command 'echo' */ if (is_control) {
if (ciprefix("echo", buffer)) { /* lower case for variables or vectors in command 'echo' */
char* p = buffer, *tmpstr; if (ciprefix("echo", buffer)) {
while (p && *p != '\n' && *p != '\0') { char* p = buffer, * tmpstr;
p = nexttok(p); while (p && *p != '\n' && *p != '\0') {
/* vectors or variables start with $ */ p = nexttok(p);
if (p && *p == '$') { /* vectors or variables start with $ */
for (tmpstr = p; *tmpstr && !isspace_c(*tmpstr); tmpstr++) if (p && *p == '$') {
*tmpstr = tolower_c(*tmpstr); for (tmpstr = p; *tmpstr && !isspace_c(*tmpstr); tmpstr++)
p = tmpstr; *tmpstr = tolower_c(*tmpstr);
p = tmpstr;
}
} }
} }
} /* add Inp_Path to buffer while keeping the sourcepath variable contents */
/* add Inp_Path to buffer while keeping the sourcepath variable contents */ if (ciprefix("set", buffer)) {
if (ciprefix("set", buffer)) { char* p;
char *p;
p = skip_ws(buffer + 3); // Next word p = skip_ws(buffer + 3); // Next word
if (strncmp(p, "sourcepath", 10) == 0 && if (strncmp(p, "sourcepath", 10) == 0 &&
skip_non_ws(p) == p + 10) { skip_non_ws(p) == p + 10) {
p = strchr(buffer, ')'); p = strchr(buffer, ')');
if (p) { if (p) {
*p = 0; // clear ) and insert Inp_Path in between *p = 0; // clear ) and insert Inp_Path in between
p = tprintf("%s %s ) %s", buffer, p = tprintf("%s %s ) %s", buffer,
Inp_Path ? Inp_Path : "", p + 1); Inp_Path ? Inp_Path : "", p + 1);
tfree(buffer); tfree(buffer);
buffer = p; buffer = p;
/* s points to end of buffer */ /* s points to end of buffer */
for (s = buffer; *s && (*s != '\n'); s++) for (s = buffer; *s && (*s != '\n'); s++)
; ;
} }
else { else {
fprintf(stderr, "Warning: no closing parens found in 'set sourcepath' statement\n"); fprintf(stderr, "Warning: no closing parens found in 'set sourcepath' statement\n");
}
} }
} }
} }
@ -1860,11 +1895,13 @@ static struct inp_read_t inp_read(FILE* fp, int call_depth, const char* dir_name
comfile = TRUE; comfile = TRUE;
if (call_depth == 0 && !comfile) { if (call_depth == 0 && !comfile) {
if (!cp_getvar("no_auto_gnd", CP_BOOL, NULL, 0)) if (!cp_getvar("no_auto_gnd", CP_BOOL, NULL, 0) && !newcompat.ps)
insert_new_line(cc, copy(".global gnd"), 1, 0, "internal"); insert_new_line(cc, copy(".global gnd"), 1, 0, "internal");
else else {
insert_new_line( insert_new_line(
cc, copy("* gnd is not set to 0 automatically "), 1, 0, "internal"); cc, copy("* gnd is not set to 0 automatically "), 1, 0, "internal");
fprintf(stdout, "Note: gnd in a subcircuit is not set to 0 automatically\n");
}
if (!newcompat.lt && !newcompat.ps && !newcompat.s3) { if (!newcompat.lt && !newcompat.ps && !newcompat.s3) {
/* process all library section references */ /* process all library section references */
@ -2295,12 +2332,20 @@ static char *readline(FILE *fd)
static void inp_fix_gnd_name(struct card *c) static void inp_fix_gnd_name(struct card *c)
{ {
bool found_subckt = FALSE;
for (; c; c = c->nextcard) { for (; c; c = c->nextcard) {
char *gnd = c->line; char *gnd = c->line;
// if inside of a subcircuit, and compatmode is ps, don't replace gnd
if (newcompat.ps) {
if (ciprefix(".subckt", c->line))
found_subckt = TRUE;
if (ciprefix(".ends", c->line))
found_subckt = FALSE;
}
// if there is a comment or no gnd, go to next line // if there is a comment or no gnd, go to next line
if ((*gnd == '*') || !strstr(gnd, "gnd")) if (found_subckt || (*gnd == '*') || !strstr(gnd, "gnd"))
continue; continue;
// replace "?gnd?" by "? 0 ?", ? being a ' ' ',' '(' ')'. // replace "?gnd?" by "? 0 ?", ? being a ' ' ',' '(' ')'.
@ -2832,6 +2877,7 @@ static void inp_fix_macro_param_func_paren_io(struct card *card)
str_ptr[3] = 'c'; str_ptr[3] = 'c';
str_ptr[4] = ' '; str_ptr[4] = ' ';
} }
// fprintf(stdout, "%s\n", card->line);
} }
} }
} }
@ -5628,11 +5674,9 @@ static void inp_reorder_params(
} }
// iterate through deck and find lines with multiply defined parameters /* Iterate through deck and find lines with more than one parameter defined
// Split line up into multiple lines and place those new lines immediately
// split line up into multiple lines and place those new lines immediately after the current multi-param line in the deck */
// after the current multi-param line in the deck
static int inp_split_multi_param_lines(struct card *card, int line_num) static int inp_split_multi_param_lines(struct card *card, int line_num)
{ {
for (; card; card = card->nextcard) { for (; card; card = card->nextcard) {
@ -5668,6 +5712,12 @@ static int inp_split_multi_param_lines(struct card *card, int line_num)
int paren_depth = 0; int paren_depth = 0;
beg_param = skip_back_ws(equal_ptr, curr_line); beg_param = skip_back_ws(equal_ptr, curr_line);
/* Special treatment if .param is a .func:
move back to opening '(' */
if (*(beg_param - 1) == ')') {
while (beg_param > curr_line && *beg_param != '(')
beg_param--;
}
beg_param = skip_back_non_ws(beg_param, curr_line); beg_param = skip_back_non_ws(beg_param, curr_line);
end_param = skip_ws(equal_ptr + 1); end_param = skip_ws(equal_ptr + 1);
while (*end_param && !isspace_c(*end_param)) { while (*end_param && !isspace_c(*end_param)) {
@ -8379,6 +8429,9 @@ static void inp_quote_params(struct card *c, struct card *end_c,
if (ft_skywaterpdk) if (ft_skywaterpdk)
return; return;
if (newcompat.hs && cp_getvar("no_auto_braces", CP_BOOL, NULL, 0))
return;
for (; c && c != end_c; c = c->nextcard) { for (; c && c != end_c; c = c->nextcard) {
int i, j, num_terminals; int i, j, num_terminals;

View File

@ -28,7 +28,9 @@ com_linearize(wordlist *wl)
struct dvec *newtime, *v; struct dvec *newtime, *v;
struct dvec *oldtime; struct dvec *oldtime;
struct dvec *lin; struct dvec *lin;
int len, i; int expo, len = 1024, i;
bool nponly = FALSE, np = FALSE;
wordlist * wlnew;
if (!plot_cur || !plot_cur->pl_typename || !ciprefix("tran", plot_cur->pl_typename)) { if (!plot_cur || !plot_cur->pl_typename || !ciprefix("tran", plot_cur->pl_typename)) {
fprintf(cp_err, "Error: plot must be a transient analysis\n"); fprintf(cp_err, "Error: plot must be a transient analysis\n");
@ -98,7 +100,34 @@ com_linearize(wordlist *wl)
plot_new(new); plot_new(new);
plot_setcur(new->pl_typename); plot_setcur(new->pl_typename);
plot_list = new; plot_list = new;
len = (int)((tstop - tstart) / tstep + 1.5);
/* check if "np=" is the only entry in wl.
- If yes, linearize all vectors */
if (wl && ciprefix("np=", wl->wl_word) && wl->wl_next == NULL) {
nponly = TRUE;
}
wlnew = wl;
/* get the new length from 'np=xx' */
while (wlnew) {
char* para = wlnew->wl_word;
if (ciprefix("np=", para)) {
np = TRUE;
para += 3;
len = atoi(para);
if (len == 0 && ciprefix("auto2n", para)) {
/* number of points as 2^n */
expo = (int)round(log2((tstop - tstart) / tstep));
len = 1 << expo;
}
break;
}
wlnew = wlnew->wl_next;
}
if(!np)
len = (int)((tstop - tstart) / tstep + 1.5);
newtime = dvec_alloc(copy(oldtime->v_name), newtime = dvec_alloc(copy(oldtime->v_name),
oldtime->v_type, oldtime->v_type,
oldtime->v_flags | VF_PERMANENT, oldtime->v_flags | VF_PERMANENT,
@ -109,12 +138,17 @@ com_linearize(wordlist *wl)
newtime->v_realdata[i] = d; newtime->v_realdata[i] = d;
new->pl_scale = new->pl_dvecs = newtime; new->pl_scale = new->pl_dvecs = newtime;
if (wl) { if (wl && !nponly) {
/* check for vectors given in the command line */
while (wl) { while (wl) {
if (ciprefix("np=", wl->wl_word)) {
wl = wl->wl_next;
continue;
}
v = vec_fromplot(wl->wl_word, old); v = vec_fromplot(wl->wl_word, old);
if (!v) { if (!v) {
fprintf(cp_err, "Error: no such vector %s\n", fprintf(cp_err, "Error: command 'linearize': no such vector %s\n",
wl->wl_word); wl->wl_word);
wl = wl->wl_next; wl = wl->wl_next;
continue; continue;
} }
@ -122,6 +156,7 @@ com_linearize(wordlist *wl)
wl = wl->wl_next; wl = wl->wl_next;
} }
} else { } else {
/* linearize all vectors of the current plot */
for (v = old->pl_dvecs; v; v = v->v_next) { for (v = old->pl_dvecs; v; v = v->v_next) {
if (v == old->pl_scale) if (v == old->pl_scale)
continue; continue;

View File

@ -76,6 +76,7 @@ char *ft_setkwords[] = {
"lprplot5", "lprplot5",
"lprps", "lprps",
"maxwins", "maxwins",
"measureprec",
"modelcard", "modelcard",
"modelline", "modelline",
"moremode", "moremode",

View File

@ -57,6 +57,7 @@ typedef struct { /* the input scanner data structure */
char *dyncategory; char *dyncategory;
int hs_compatibility; /* allow extra keywords */ int hs_compatibility; /* allow extra keywords */
int linecount; /* number of lines in deck */ int linecount; /* number of lines in deck */
char* cardline; /* line of card treated currently */
} dico_t; } dico_t;

View File

@ -672,6 +672,7 @@ nupa_eval(struct card *card)
dicoS->srcline = linenum; dicoS->srcline = linenum;
dicoS->oldline = orig_linenum; dicoS->oldline = orig_linenum;
dicoS->cardline = s;
c = dicoS->dyncategory[linenum]; c = dicoS->dyncategory[linenum];

View File

@ -229,14 +229,15 @@ message(dico_t *dico, const char *fmt, ...)
if (ft_ngdebug) { if (ft_ngdebug) {
fprintf fprintf
(stderr, (stderr,
"Netlist line no. %d, new internal line no. %d:\n", "Error in netlist line no. %d, new internal line no. %d:\n"
dico->oldline, dico->srcline); "%s\n\n",
dico->srcline, dico->oldline, dico->cardline);
} }
else { else {
fprintf fprintf
(stderr, (stderr,
"Netlist line no. %d:\n", "Error in netlist line no. %d, new internal line no. %d:\n\n",
dico->oldline); dico->srcline, dico->oldline);
} }
} }
va_start(ap, fmt); va_start(ap, fmt);
@ -273,6 +274,7 @@ initdico(dico_t *dico)
dico->hs_compatibility = 1; dico->hs_compatibility = 1;
else else
dico->hs_compatibility = 0; dico->hs_compatibility = 0;
dico->cardline = NULL;
} }
@ -1053,11 +1055,18 @@ formula(dico_t *dico, const char *s, const char *s_end, bool *perror)
((oldstate == S_atom) && (state == S_binop)) || ((oldstate == S_atom) && (state == S_binop)) ||
((oldstate != S_atom) && (state != S_binop)); ((oldstate != S_atom) && (state != S_binop));
if (oldstate == S_binop && state == S_binop && c == '-') { /* c is a sign, + or - are allowed */
ok = 1; if (oldstate == S_binop && state == S_binop)
negate = 1; if (c == '-') {
continue; ok = 1;
} negate = 1;
continue;
}
else if (c == '+') {
ok = 1;
negate = 0;
continue;
}
if (!ok) if (!ok)
error = message(dico, " Misplaced operator\n"); error = message(dico, " Misplaced operator\n");

View File

@ -25,6 +25,7 @@ bool ft_acctprint = FALSE, ft_noacctprint = FALSE, ft_listprint = FALSE;
bool ft_nodesprint = FALSE, ft_optsprint = FALSE, ft_noinitprint = FALSE; bool ft_nodesprint = FALSE, ft_optsprint = FALSE, ft_noinitprint = FALSE;
bool ft_norefprint = FALSE, ft_skywaterpdk = FALSE; bool ft_norefprint = FALSE, ft_skywaterpdk = FALSE;
bool ft_ngdebug = FALSE, ft_nginfo = FALSE, ft_stricterror = FALSE, ft_spiniterror = FALSE; bool ft_ngdebug = FALSE, ft_nginfo = FALSE, ft_stricterror = FALSE, ft_spiniterror = FALSE;
bool ft_codemodelerror = FALSE, ft_osdierror = FALSE;
static void setdb(char *str); static void setdb(char *str);
static struct variable *cp_enqvec_as_var(const char *vec_name, static struct variable *cp_enqvec_as_var(const char *vec_name,
@ -342,6 +343,16 @@ cp_usrset(struct variable *var, bool isset)
raw_prec = var->va_num; raw_prec = var->va_num;
else else
fprintf(cp_err, "Bad 'rawfileprec' \"%s\"\n", var->va_name); fprintf(cp_err, "Bad 'rawfileprec' \"%s\"\n", var->va_name);
}
else if (eq(var->va_name, "measureprec")) {
if ((var->va_type == CP_BOOL) && (isset == FALSE))
measure_precision = -1;
else if (var->va_type == CP_REAL)
measure_precision = (int)floor(var->va_real + 0.5);
else if (var->va_type == CP_NUM)
measure_precision = var->va_num;
else
fprintf(cp_err, "Bad 'measureprec' \"%s\"\n", var->va_name);
} else if (eq(var->va_name, "numdgt")) { } else if (eq(var->va_name, "numdgt")) {
if ((var->va_type == CP_BOOL) && (isset == FALSE)) if ((var->va_type == CP_BOOL) && (isset == FALSE))
cp_numdgt = -1; cp_numdgt = -1;
@ -350,7 +361,7 @@ cp_usrset(struct variable *var, bool isset)
else if (var->va_type == CP_NUM) else if (var->va_type == CP_NUM)
cp_numdgt = var->va_num; cp_numdgt = var->va_num;
else else
fprintf(cp_err, "Excuse me??\n"); fprintf(cp_err, "Bad 'numdgt' \"%s\"\n", var->va_name);
} else if (eq(var->va_name, "unixcom")) { } else if (eq(var->va_name, "unixcom")) {
cp_dounixcom = isset; cp_dounixcom = isset;
if (isset) { if (isset) {

View File

@ -380,6 +380,7 @@ struct func ft_funcs[] = {
{ "integ", (cx_function_t*)(void *) cx_integ }, { "integ", (cx_function_t*)(void *) cx_integ },
{ "fft", (cx_function_t*)(void *) cx_fft }, { "fft", (cx_function_t*)(void *) cx_fft },
{ "ifft", (cx_function_t*)(void *) cx_ifft }, { "ifft", (cx_function_t*)(void *) cx_ifft },
{ "mtimeavg", (cx_function_t*)(void *) cx_mtimeavg },
{ "v", NULL }, { "v", NULL },
{ NULL, NULL } { NULL, NULL }
}; };

View File

@ -22,7 +22,6 @@ Author: 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
#include "ngspice/compatmode.h" #include "ngspice/compatmode.h"
extern IFsimulator SIMinfo; extern IFsimulator SIMinfo;
extern char Spice_Build_Date[];
static void fixdims(struct dvec *v, char *s); static void fixdims(struct dvec *v, char *s);
@ -114,7 +113,8 @@ void raw_write(char *name, struct plot *pl, bool app, bool binary)
fprintf(fp, "Title: %s\n", pl->pl_title); fprintf(fp, "Title: %s\n", pl->pl_title);
fprintf(fp, "Date: %s\n", pl->pl_date); fprintf(fp, "Date: %s\n", pl->pl_date);
fprintf(fp, "Command: %s-%s, Build %s\n", ft_sim->simulator, ft_sim->version, Spice_Build_Date); if (ft_sim) /* not available when old app ngscovert is made */
fprintf(fp, "Command: %s-%s, Build %s\n", ft_sim->simulator, ft_sim->version, Spice_Build_Date);
fprintf(fp, "Plotname: %s\n", pl->pl_name); fprintf(fp, "Plotname: %s\n", pl->pl_name);
fprintf(fp, "Flags: %s%s\n", fprintf(fp, "Flags: %s%s\n",
realflag ? "real" : "complex", raw_padding ? "" : " unpadded"); realflag ? "real" : "complex", raw_padding ? "" : " unpadded");

View File

@ -35,6 +35,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
extern void line_free_x(struct card *deck, bool recurse); extern void line_free_x(struct card *deck, bool recurse);
extern INPmodel *modtab; extern INPmodel *modtab;
extern NGHASHPTR modtabhash; extern NGHASHPTR modtabhash;
extern int DCtran_step_quit(CKTcircuit* ckt);
#ifdef SHARED_MODULE #ifdef SHARED_MODULE
extern void exec_controls(wordlist *newcontrols); extern void exec_controls(wordlist *newcontrols);
@ -219,6 +220,10 @@ com_remcirc(wordlist *wl)
EVTunsetup(ft_curckt->ci_ckt); EVTunsetup(ft_curckt->ci_ckt);
#endif #endif
/* remove remnants of run after incomplete transient sim with 'step' */
if (ft_curckt->ci_ckt)
DCtran_step_quit(ft_curckt->ci_ckt);
if_cktfree(ft_curckt->ci_ckt, ft_curckt->ci_symtab); if_cktfree(ft_curckt->ci_ckt, ft_curckt->ci_symtab);
for (v = ft_curckt->ci_vars; v; v = next) { for (v = ft_curckt->ci_vars; v; v = next) {
next = v->va_next; next = v->va_next;

View File

@ -485,9 +485,6 @@ struct is_arithmetic<duals::dual<T>> : is_arithmetic<T> {};
#endif // CPPDUALS_ENABLE_IS_ARITHMETIC #endif // CPPDUALS_ENABLE_IS_ARITHMETIC
/// Duals are compound types.
template <class T>
struct is_compound<duals::dual<T>> : true_type {};
// Modification of std::numeric_limits<> per // Modification of std::numeric_limits<> per
// C++03 17.4.3.1/1, and C++11 18.3.2.3/1. // C++03 17.4.3.1/1, and C++11 18.3.2.3/1.

View File

@ -26,9 +26,10 @@ Modified: 1999 Paolo Nenzi - 2000 AlansFixes
extern void ft_checkkids(void); extern void ft_checkkids(void);
/* breakpoint.c */ /* breakp.c */
extern bool ft_bpcheck(struct plot *runplot, int iteration); extern bool ft_bpcheck(struct plot *runplot, int iteration);
extern bool ft_stepcheck(void);
extern void dbfree(struct dbcomm *db); extern void dbfree(struct dbcomm *db);
extern void dbfree1(struct dbcomm *db); extern void dbfree1(struct dbcomm *db);
@ -129,6 +130,7 @@ extern void *cx_integ(void *, short int , int , int *, short int *, struct plot
extern void *cx_group_delay(void *, short int , int , int *, short int *, struct plot *, struct plot *, int ); extern void *cx_group_delay(void *, short int , int , int *, short int *, struct plot *, struct plot *, int );
extern void *cx_fft(void *, short int , int , int *, short int *, struct plot *, struct plot *, int ); extern void *cx_fft(void *, short int , int , int *, short int *, struct plot *, struct plot *, int );
extern void *cx_ifft(void *, short int , int , int *, short int *, struct plot *, struct plot *, int ); extern void *cx_ifft(void *, short int , int , int *, short int *, struct plot *, struct plot *, int );
extern void *cx_mtimeavg(void *, short int , int , int *, short int *, struct plot *, struct plot *, int );
/* define.c */ /* define.c */
@ -172,29 +174,6 @@ extern struct dvec *ft_evaluate(struct pnode *node);
/* ftesopt.c */ /* ftesopt.c */
extern struct variable *ft_getstat(struct circ *, char *); extern struct variable *ft_getstat(struct circ *, char *);
/* ginterface.c
extern bool gi_init();
extern bool gi_endpause;
extern bool gi_rottext;
extern int gi_fntheight;
extern int gi_fntwidth;
extern int gi_maxx;
extern int gi_maxy;
extern int gi_nolst;
extern int gi_nocolors;
extern int gi_package;
extern void gi_arc();
extern void gi_clearscreen();
extern void gi_close();
extern void gi_drawline();
extern void gi_redraw();
extern void gi_setcolor();
extern void gi_resetcolor();
extern void gi_setlinestyle();
extern void gi_text();
extern void gi_update();
*/
/* graf.c */ /* graf.c */
@ -269,6 +248,8 @@ extern bool ft_ngdebug;
extern bool ft_nginfo; extern bool ft_nginfo;
extern bool ft_stricterror; extern bool ft_stricterror;
extern bool ft_spiniterror; extern bool ft_spiniterror;
extern bool ft_codemodelerror;
extern bool ft_osdierror;
extern bool ft_skywaterpdk; extern bool ft_skywaterpdk;
/* parse.c */ /* parse.c */
@ -303,6 +284,9 @@ extern struct plot *raw_read(char *name);
extern bool do_measure(char *what, bool chk_only); extern bool do_measure(char *what, bool chk_only);
extern bool check_autostop(char *what); extern bool check_autostop(char *what);
/* com_measure2.c*/
extern int measure_precision;
/* resource.c */ /* resource.c */
extern void ft_ckspace(void); extern void ft_ckspace(void);
@ -379,6 +363,5 @@ extern struct dvec* copycut(struct dvec* ov, struct dvec* newscalevec, int istar
extern bool ft_intrpt; extern bool ft_intrpt;
extern bool ft_setflag; extern bool ft_setflag;
/* error.c */
#endif #endif

View File

@ -755,6 +755,8 @@ show_help(void)
" -t, --term=TERM set the terminal type\n" " -t, --term=TERM set the terminal type\n"
" -h, --help display this help and exit\n" " -h, --help display this help and exit\n"
" -v, --version output version information and exit\n" " -v, --version output version information and exit\n"
" -f, --version-full output full version information\n"
" --version-small output small version information\n"
"\n" "\n"
"Report bugs to %s.\n", cp_program, Bug_Addr); "Report bugs to %s.\n", cp_program, Bug_Addr);
} }
@ -952,6 +954,8 @@ int main(int argc, char **argv)
{"define", required_argument, NULL, 'D'}, {"define", required_argument, NULL, 'D'},
{"help", no_argument, NULL, 'h'}, {"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'v'}, {"version", no_argument, NULL, 'v'},
{"version-full", no_argument, NULL, 'f'},
{"version-small", no_argument, NULL, 256},
{"batch", no_argument, NULL, 'b'}, {"batch", no_argument, NULL, 'b'},
{"autorun", no_argument, NULL, 'a'}, {"autorun", no_argument, NULL, 'a'},
{"circuitfile", required_argument, NULL, 'c'}, {"circuitfile", required_argument, NULL, 'c'},
@ -969,7 +973,7 @@ int main(int argc, char **argv)
int option_index = 0; int option_index = 0;
int c = getopt_long(argc, argv, "D:hvbac:ino:pqr:st:", int c = getopt_long(argc, argv, "D:hvfbac:ino:pqr:st:",
long_options, &option_index); long_options, &option_index);
if (c == -1) { if (c == -1) {
@ -1004,6 +1008,22 @@ int main(int argc, char **argv)
sp_shutdown(EXIT_INFO); sp_shutdown(EXIT_INFO);
break; break;
case 'f': /* Full version info */
{
wordlist wl = { "-f", NULL, NULL };
com_version(&wl);
sp_shutdown(EXIT_INFO);
}
break;
case 256: /* --version-small */
{
wordlist wl = { "-s", NULL, NULL };
com_version(&wl);
sp_shutdown(EXIT_INFO);
}
break;
case 'b': /* Batch mode */ case 'b': /* Batch mode */
{ {
bool x_false = FALSE; bool x_false = FALSE;

View File

@ -369,7 +369,6 @@ cx_avg(void *data, short int type, int length, int *newlength, short int *newtyp
void* void*
cx_m3avg(void* data, short int type, int length, int* newlength, short int* newtype) cx_m3avg(void* data, short int type, int length, int* newlength, short int* newtype)
{ {
double sum_real = 0.0, sum_imag = 0.0;
int i; int i;
if (type == VF_REAL) { if (type == VF_REAL) {

View File

@ -33,6 +33,9 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
#include "ngspice/sim.h" /* To get SV_TIME */ #include "ngspice/sim.h" /* To get SV_TIME */
#include "ngspice/fftext.h" #include "ngspice/fftext.h"
#include "ngspice/cktdefs.h" /* ft_curckt */
#include "ngspice/ftedefs.h" /* ft_curckt */
#include "ngspice/fteext.h" /* ft_curckt */
extern bool cx_degrees; extern bool cx_degrees;
extern void vec_new(struct dvec *d); extern void vec_new(struct dvec *d);
@ -771,14 +774,17 @@ cx_fft(void *data, short int type, int length, int *newlength, short int *newtyp
fftw_execute(plan_forward); fftw_execute(plan_forward);
scale = (double) fpts - 1.0; scale = ((double)length)/2.0;
outdata[0].cx_real = out[0][0]/scale/2.0; outdata[0].cx_real = out[0][0]/scale/2.0;
outdata[0].cx_imag = 0.0; outdata[0].cx_imag = 0.0;
for (i = 1; i < fpts; i++) { for (i = 1; i < fpts; i++) {
outdata[i].cx_real = out[i][0]/scale; outdata[i].cx_real = out[i][0]/scale;
outdata[i].cx_imag = out[i][1]/scale; outdata[i].cx_imag = out[i][1]/scale;
} }
if (length % 2 == 0) {
outdata[fpts-1].cx_real = out[fpts-1][0]/scale/2.0;
outdata[fpts-1].cx_imag = 0.0;
}
fftw_free(ind); fftw_free(ind);
#else /* Green's FFT */ #else /* Green's FFT */
@ -797,7 +803,7 @@ cx_fft(void *data, short int type, int length, int *newlength, short int *newtyp
rffts(datax, M, 1); rffts(datax, M, 1);
fftFree(); fftFree();
scale = (double) fpts - 1.0; scale = ((double)N)/2;
/* Re(x[0]), Re(x[N/2]), Re(x[1]), Im(x[1]), Re(x[2]), Im(x[2]), ... Re(x[N/2-1]), Im(x[N/2-1]). */ /* Re(x[0]), Re(x[N/2]), Re(x[1]), Im(x[1]), Re(x[2]), Im(x[2]), ... Re(x[N/2-1]), Im(x[N/2-1]). */
outdata[0].cx_real = datax[0]/scale/2.0; outdata[0].cx_real = datax[0]/scale/2.0;
outdata[0].cx_imag = 0.0; outdata[0].cx_imag = 0.0;
@ -805,7 +811,7 @@ cx_fft(void *data, short int type, int length, int *newlength, short int *newtyp
outdata[i].cx_real = datax[2*i]/scale; outdata[i].cx_real = datax[2*i]/scale;
outdata[i].cx_imag = datax[2*i+1]/scale; outdata[i].cx_imag = datax[2*i+1]/scale;
} }
outdata[fpts-1].cx_real = datax[1]/scale; outdata[fpts-1].cx_real = datax[1]/scale/2.0;
outdata[fpts-1].cx_imag = 0.0; outdata[fpts-1].cx_imag = 0.0;
#endif #endif
@ -988,3 +994,127 @@ cx_ifft(void *data, short int type, int length, int *newlength, short int *newty
return ((void *) outdata); return ((void *) outdata);
} }
/* Compute the moving average of a vector,
* resulting from a transient simulation,
* over a time window given by variable mtimeavgwindow.
* Create the average over each original time point
* +/- mtimeavgwindow/2.
*/
void*
cx_mtimeavg(void* data, short int type, int length, int* newlength, short int* newtype, struct plot* pl, struct plot* newpl, int grouping)
{
double tdelta = 0.0, tstart=0.0, tstop=0.0, tdeltahalf;
struct dvec *sc;
int i;
double* d, * dd, * dsc;
if (grouping == 0)
grouping = length;
int nlen = length - 1;
if (!pl || !pl->pl_scale || !newpl || !newpl->pl_scale) {
fprintf(cp_err, "Internal error mtimeavg: bad scale\n");
return (NULL);
}
/* Check to see if we have the time vector as scale */
if (!isreal(pl->pl_scale) ||
((pl->pl_scale)->v_type != SV_TIME)) {
fprintf(cp_err, "Error: mtimeavg needs real time scale\n");
return (NULL);
}
if (type != VF_REAL) {
fprintf(cp_err, "Error: mtimeavg needs a real valued vector.\n");
return (NULL);
}
if (!cp_getvar("mtimeavgwindow", CP_REAL, &tdelta, 0)) {
if (ft_curckt == (struct circ*)NULL) {
tdelta = 1e-6;
fprintf(cp_out, "Note: mtimeavgwindow not given, window set to %g s\n", tdelta);
}
else {
CKTcircuit* ckt = ft_curckt->ci_ckt;
tdelta = 10.0 * ckt->CKTstep;
fprintf(cp_out, "Note: mtimeavgwindow not given, window set to %g s\n", tdelta);
}
}
sc = pl->pl_scale;
dsc = sc->v_realdata;
d = alloc_d(length);
dd = (double*)data;
tstart = dsc[0];
tstop = dsc[nlen];
tdeltahalf = tdelta / 2.;
*newtype = VF_REAL;
*newlength = length;
#ifdef USE_OMP
#pragma omp parallel
{
#pragma omp for
#endif
for (i = 0; i < length; i++) {
int j, ibeg, iend, k;
double tbeg, tend, ttruebeg, ttrueend, truedelta;
double integ;
double tmid = dsc[i];
ttruebeg = tmid - tdeltahalf;
ttrueend = tmid + tdeltahalf;
tbeg = tstop;
tend = tstart;
/* start of the interval */
j = i;
while (j > 0 && tbeg > ttruebeg) {
tbeg = dsc[j];
j--;
}
ibeg = j;
/* end of the interval */
j = i;
while (j < nlen && tend < ttrueend) {
tend = dsc[j];
j++;
}
iend = j;
/* integrate the data */
integ = 0.;
for (k = ibeg; k < iend; k++) {
integ = integ + dd[k] * (dsc[k + 1] - dsc[k]);
}
/* cut a little from integ on the lower border, interpolated */
if (ibeg > 0) {
integ = integ - (dsc[ibeg] - ttruebeg) * dd[ibeg];
}
/* add a little to integ on the upper border, interpolated */
if (iend < nlen) {
integ = integ + (dsc[iend] - ttrueend) * dd[iend];
}
/* when on the edges of the vector, set reduced time windows */
if (ibeg == 0)
truedelta = dsc[i] + tdeltahalf;
else if (iend == nlen)
truedelta = dsc[nlen] - dsc[i] + tdeltahalf;
else
truedelta = tdelta;
d[i] = integ / truedelta;
// fprintf(stdout, "%d %d %d %e %e..%e %e\n", i, ibeg, iend, dsc[ibeg], dsc[iend], ttruebeg, ttrueend);
}
#ifdef USE_OMP
}
#endif
return ((void*)d);
}

View File

@ -25,5 +25,7 @@ void * cx_fft(void *data, short int type, int length, int *newlength, short int
struct plot *pl, struct plot *newpl, int grouping); struct plot *pl, struct plot *newpl, int grouping);
void * cx_ifft(void *data, short int type, int length, int *newlength, short int *newtype, void * cx_ifft(void *data, short int type, int length, int *newlength, short int *newtype,
struct plot *pl, struct plot *newpl, int grouping); struct plot *pl, struct plot *newpl, int grouping);
void* cx_mtimeavg(void* data, short int type, int length, int* newlength, short int* newtype,
struct plot* pl, struct plot* newpl, int grouping);
#endif #endif

View File

@ -21,6 +21,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
#include <errno.h> #include <errno.h>
int input(FILE *fp);
FILE *cp_in = NULL; FILE *cp_in = NULL;
FILE *cp_out = NULL; FILE *cp_out = NULL;
@ -40,6 +41,9 @@ bool cp_no_histsubst = FALSE;
struct compat newcompat; struct compat newcompat;
bool cx_degrees = FALSE; bool cx_degrees = FALSE;
IFsimulator *ft_sim = NULL;
char Spice_Build_Date[] = " date is not available\n";
char *cp_program = "sconvert"; char *cp_program = "sconvert";
@ -56,6 +60,17 @@ char *cp_program = "sconvert";
#define TMALLOC(t, n) (t*) tmalloc(sizeof(t) * (size_t)(n)) #define TMALLOC(t, n) (t*) tmalloc(sizeof(t) * (size_t)(n))
#define TREALLOC(t, p, n) (t*) trealloc(p, sizeof(t) * (size_t)(n)) #define TREALLOC(t, p, n) (t*) trealloc(p, sizeof(t) * (size_t)(n))
#if defined(__MINGW32__) || defined(_MSC_VER)
FILE *
newfopen(const char *fn, const char* md)
{
FILE* fp;
if (fn == NULL)
return NULL;
fp = fopen(fn, md);
return fp;
}
#endif
char * char *
smktemp(char *id) smktemp(char *id)
@ -192,7 +207,11 @@ oldread(char *name)
pl->pl_scale = pl->pl_dvecs = v; pl->pl_scale = pl->pl_dvecs = v;
end = v; end = v;
tfread(buf, 1, 8, fp); tfread(buf, 1, 8, fp);
buf[8] = '\0'; for (j = 0; j < 8; j++) {
if (buf[j] == ' ') break;
buf[j] = (char) tolower((unsigned char) buf[j]);
}
buf[j] = '\0';
v->v_name = strdup(buf); v->v_name = strdup(buf);
} }
for (v = pl->pl_dvecs; v; v = v->v_next) { for (v = pl->pl_dvecs; v; v = v->v_next) {
@ -380,15 +399,19 @@ oldwrite(char *name, bool app, struct plot *pl)
int int
main(int ac, char **av) main(int ac, char **av)
{ {
char *sf, *af; char *sf = NULL, *af = NULL;
char buf[BSIZE_SP]; char buf[BSIZE_SP];
char t, f; char t = 0, f = 0;
struct plot *pl; struct plot *pl;
size_t n; size_t n;
char *infile = NULL; char *infile = NULL;
char *outfile = NULL; char *outfile = NULL;
FILE *fp; FILE *fp;
cp_in = stdin;
cp_out = stdout;
cp_err = stderr;
switch (ac) { switch (ac) {
case 5: case 5:
sf = av[2]; sf = av[2];
@ -414,20 +437,32 @@ main(int ac, char **av)
case 1: printf("Input file: "); case 1: printf("Input file: ");
(void) fflush(stdout); (void) fflush(stdout);
(void) fgets(buf, BSIZE_SP, stdin); if (fgets(buf, BSIZE_SP, stdin) != NULL) {
sf = strdup(buf); sf = strdup(buf);
} else {
printf("Error reading input file.");
}
printf("Input type: "); printf("Input type: ");
(void) fflush(stdout); (void) fflush(stdout);
(void) fgets(buf, BSIZE_SP, stdin); if (fgets(buf, BSIZE_SP, stdin) != NULL) {
f = buf[0]; f = buf[0];
} else {
printf("Error reading input type.");
}
printf("Output file: "); printf("Output file: ");
(void) fflush(stdout); (void) fflush(stdout);
(void) fgets(buf, BSIZE_SP, stdin); if (fgets(buf, BSIZE_SP, stdin) != NULL) {
af = strdup(buf); af = strdup(buf);
} else {
printf("Error reading output file.");
}
printf("Output type: "); printf("Output type: ");
(void) fflush(stdout); (void) fflush(stdout);
(void) fgets(buf, BSIZE_SP, stdin); if (fgets(buf, BSIZE_SP, stdin) != NULL) {
t = buf[0]; t = buf[0];
} else {
printf("Error reading output type.");
}
break; break;
default: default:
fprintf(cp_err, fprintf(cp_err,
@ -488,7 +523,6 @@ main(int ac, char **av)
exit(EXIT_NORMAL); exit(EXIT_NORMAL);
} }
void cp_pushcontrol(void) { } void cp_pushcontrol(void) { }
void cp_popcontrol(void) { } void cp_popcontrol(void) { }
void out_init(void) { } void out_init(void) { }

View File

@ -969,3 +969,22 @@ chkStep:
} }
/* NOTREACHED */ /* NOTREACHED */
} }
/* If we have a 'step' command, and then 'quit' before reaching the final time,
remove the run plot memory. */
int
DCtran_step_quit(CKTcircuit* ckt) {
if (!ckt || !ckt->CKTcurJob) /* nothing to delete */
return 0;
if (ckt->CKTcurJob->JOBtype != 4) /* only tran sim */
return 0;
if (!ft_stepcheck()) /* only after 'step' */
return 0;
TRANan* job = (TRANan*)ckt->CKTcurJob;
if (!job->TRANplot) /* already done */
return 0;
SPfrontEnd->OUTendPlot(job->TRANplot);
job->TRANplot = NULL;
return(OK);
}

View File

@ -61,7 +61,6 @@ NOISEan(CKTcircuit* ckt, int restart)
int numNames; int numNames;
IFuid* nameList; /* va: tmalloc'ed list of names */ IFuid* nameList; /* va: tmalloc'ed list of names */
static runDesc* noiPlot = NULL;
runDesc* plot = NULL; runDesc* plot = NULL;
#ifdef XSPICE #ifdef XSPICE

View File

@ -59,6 +59,7 @@ IOP( "mulu0", BSIM4_MULU0, IF_REAL, "Low field mobility multiplier"),
IOP( "xgw", BSIM4_XGW, IF_REAL, "Distance from gate contact center to device edge"), IOP( "xgw", BSIM4_XGW, IF_REAL, "Distance from gate contact center to device edge"),
IOP( "ngcon", BSIM4_NGCON, IF_REAL, "Number of gate contacts"), IOP( "ngcon", BSIM4_NGCON, IF_REAL, "Number of gate contacts"),
IOP( "wnflag", BSIM4_WNFLAG, IF_INTEGER, "W/NF device flag for bin selection"), IOP( "wnflag", BSIM4_WNFLAG, IF_INTEGER, "W/NF device flag for bin selection"),
IOPU("dtemp", BSIM4_DTEMP, IF_REAL, "Instance temperature difference"),
IOP( "trnqsmod", BSIM4_TRNQSMOD, IF_INTEGER, "Transient NQS model selector"), IOP( "trnqsmod", BSIM4_TRNQSMOD, IF_INTEGER, "Transient NQS model selector"),
IOP( "acnqsmod", BSIM4_ACNQSMOD, IF_INTEGER, "AC NQS model selector"), IOP( "acnqsmod", BSIM4_ACNQSMOD, IF_INTEGER, "AC NQS model selector"),

View File

@ -135,6 +135,9 @@ BSIM4instance *here = (BSIM4instance*)inst;
case BSIM4_WNFLAG: case BSIM4_WNFLAG:
value->iValue = here->BSIM4wnflag; value->iValue = here->BSIM4wnflag;
return(OK); return(OK);
case BSIM4_DTEMP:
value->rValue = here->BSIM4dtemp;
return(OK);
case BSIM4_XGW: case BSIM4_XGW:
value->rValue = here->BSIM4xgw; value->rValue = here->BSIM4xgw;
return(OK); return(OK);

View File

@ -165,6 +165,10 @@ IFvalue *select)
here->BSIM4wnflag = value->iValue; here->BSIM4wnflag = value->iValue;
here->BSIM4wnflagGiven = TRUE; here->BSIM4wnflagGiven = TRUE;
break; break;
case BSIM4_DTEMP:
here->BSIM4dtemp = value->rValue;
here->BSIM4dtempGiven = TRUE;
return(OK);
case BSIM4_XGW: case BSIM4_XGW:
here->BSIM4xgw = value->rValue; here->BSIM4xgw = value->rValue;
here->BSIM4xgwGiven = TRUE; here->BSIM4xgwGiven = TRUE;

View File

@ -2371,6 +2371,8 @@ BSIM4instance **InstArray;
here->BSIM4xgw = model->BSIM4xgw; here->BSIM4xgw = model->BSIM4xgw;
if (!here->BSIM4ngconGiven) if (!here->BSIM4ngconGiven)
here->BSIM4ngcon = model->BSIM4ngcon; here->BSIM4ngcon = model->BSIM4ngcon;
if (!here->BSIM4dtempGiven)
here->BSIM4dtemp = 0;
/* Process instance model selectors, some /* Process instance model selectors, some
* may override their global counterparts * may override their global counterparts

View File

@ -121,6 +121,7 @@ typedef struct sBSIM4instance
int BSIM4wnflag; int BSIM4wnflag;
double BSIM4xgw; double BSIM4xgw;
double BSIM4ngcon; double BSIM4ngcon;
double BSIM4dtemp;
/* added here to account stress effect instance dependence */ /* added here to account stress effect instance dependence */
@ -316,6 +317,7 @@ typedef struct sBSIM4instance
unsigned BSIM4wnflagGiven :1; unsigned BSIM4wnflagGiven :1;
unsigned BSIM4xgwGiven :1; unsigned BSIM4xgwGiven :1;
unsigned BSIM4ngconGiven :1; unsigned BSIM4ngconGiven :1;
unsigned BSIM4dtempGiven : 1;
unsigned BSIM4icVDSGiven :1; unsigned BSIM4icVDSGiven :1;
unsigned BSIM4icVGSGiven :1; unsigned BSIM4icVGSGiven :1;
unsigned BSIM4icVBSGiven :1; unsigned BSIM4icVBSGiven :1;
@ -2884,6 +2886,8 @@ typedef struct sBSIM4model
#define BSIM4_WEFF 46 #define BSIM4_WEFF 46
#define BSIM4_LEFF 47 #define BSIM4_LEFF 47
#define BSIM4_DTEMP 48
/* Global parameters */ /* Global parameters */
#define BSIM4_MOD_TEMPEOT 66 #define BSIM4_MOD_TEMPEOT 66
#define BSIM4_MOD_LEFFEOT 67 #define BSIM4_MOD_LEFFEOT 67

View File

@ -49,7 +49,7 @@ IOPR( "delvt0", BSIM4v5_DELVTO, IF_REAL , "Zero bias threshold voltage variat
IOP( "mulu0", BSIM4v5_MULU0, IF_REAL, "Low field mobility multiplier"), IOP( "mulu0", BSIM4v5_MULU0, IF_REAL, "Low field mobility multiplier"),
IOP( "xgw", BSIM4v5_XGW, IF_REAL, "Distance from gate contact center to device edge"), IOP( "xgw", BSIM4v5_XGW, IF_REAL, "Distance from gate contact center to device edge"),
IOP( "ngcon", BSIM4v5_NGCON, IF_REAL, "Number of gate contacts"), IOP( "ngcon", BSIM4v5_NGCON, IF_REAL, "Number of gate contacts"),
IOPU("dtemp", BSIM4v5_DTEMP, IF_REAL, "Instance temperature difference"),
IOP( "trnqsmod", BSIM4v5_TRNQSMOD, IF_INTEGER, "Transient NQS model selector"), IOP( "trnqsmod", BSIM4v5_TRNQSMOD, IF_INTEGER, "Transient NQS model selector"),
IOP( "acnqsmod", BSIM4v5_ACNQSMOD, IF_INTEGER, "AC NQS model selector"), IOP( "acnqsmod", BSIM4v5_ACNQSMOD, IF_INTEGER, "AC NQS model selector"),

View File

@ -112,6 +112,9 @@ BSIM4v5instance *here = (BSIM4v5instance*)inst;
case BSIM4v5_MULU0: case BSIM4v5_MULU0:
value->rValue = here->BSIM4v5mulu0; value->rValue = here->BSIM4v5mulu0;
return(OK); return(OK);
case BSIM4v5_DTEMP:
value->rValue = here->BSIM4v5dtemp;
return(OK);
case BSIM4v5_XGW: case BSIM4v5_XGW:
value->rValue = here->BSIM4v5xgw; value->rValue = here->BSIM4v5xgw;
return(OK); return(OK);

View File

@ -139,6 +139,10 @@ IFvalue *select)
here->BSIM4v5mulu0 = value->rValue; here->BSIM4v5mulu0 = value->rValue;
here->BSIM4v5mulu0Given = TRUE; here->BSIM4v5mulu0Given = TRUE;
break; break;
case BSIM4v5_DTEMP:
here->BSIM4v5dtemp = value->rValue;
here->BSIM4v5dtempGiven = TRUE;
return(OK);
case BSIM4v5_XGW: case BSIM4v5_XGW:
here->BSIM4v5xgw = value->rValue; here->BSIM4v5xgw = value->rValue;
here->BSIM4v5xgwGiven = TRUE; here->BSIM4v5xgwGiven = TRUE;

View File

@ -1751,8 +1751,9 @@ BSIM4v5instance **InstArray;
here->BSIM4v5xgw = model->BSIM4v5xgw; here->BSIM4v5xgw = model->BSIM4v5xgw;
if (!here->BSIM4v5ngconGiven) if (!here->BSIM4v5ngconGiven)
here->BSIM4v5ngcon = model->BSIM4v5ngcon; here->BSIM4v5ngcon = model->BSIM4v5ngcon;
if (!here->BSIM4v5dtempGiven)
here->BSIM4v5dtemp = 0;
/* Process instance model selectors, some /* Process instance model selectors, some
* may override their global counterparts * may override their global counterparts
*/ */

View File

@ -105,6 +105,7 @@ typedef struct sBSIM4v5instance
double BSIM4v5mulu0; double BSIM4v5mulu0;
double BSIM4v5xgw; double BSIM4v5xgw;
double BSIM4v5ngcon; double BSIM4v5ngcon;
double BSIM4v5dtemp;
/* added here to account stress effect instance dependence */ /* added here to account stress effect instance dependence */
double BSIM4v5u0temp; double BSIM4v5u0temp;
@ -288,6 +289,7 @@ typedef struct sBSIM4v5instance
unsigned BSIM4v5mulu0Given :1; unsigned BSIM4v5mulu0Given :1;
unsigned BSIM4v5xgwGiven :1; unsigned BSIM4v5xgwGiven :1;
unsigned BSIM4v5ngconGiven :1; unsigned BSIM4v5ngconGiven :1;
unsigned BSIM4v5dtempGiven : 1;
unsigned BSIM4v5icVDSGiven :1; unsigned BSIM4v5icVDSGiven :1;
unsigned BSIM4v5icVGSGiven :1; unsigned BSIM4v5icVGSGiven :1;
unsigned BSIM4v5icVBSGiven :1; unsigned BSIM4v5icVBSGiven :1;
@ -2536,6 +2538,7 @@ typedef struct sBSIM4v5model
#define BSIM4v5_SC 37 #define BSIM4v5_SC 37
#define BSIM4v5_M 38 #define BSIM4v5_M 38
#define BSIM4v5_MULU0 39 #define BSIM4v5_MULU0 39
#define BSIM4v5_DTEMP 40
/* Global parameters */ /* Global parameters */
#define BSIM4v5_MOD_TEMPMOD 89 #define BSIM4v5_MOD_TEMPMOD 89

View File

@ -55,7 +55,7 @@ IOPR( "delvt0", BSIM4v6_DELVTO, IF_REAL , "Zero bias threshold voltage variat
IOP( "mulu0", BSIM4v6_MULU0, IF_REAL, "Low field mobility multiplier"), IOP( "mulu0", BSIM4v6_MULU0, IF_REAL, "Low field mobility multiplier"),
IOP( "xgw", BSIM4v6_XGW, IF_REAL, "Distance from gate contact center to device edge"), IOP( "xgw", BSIM4v6_XGW, IF_REAL, "Distance from gate contact center to device edge"),
IOP( "ngcon", BSIM4v6_NGCON, IF_REAL, "Number of gate contacts"), IOP( "ngcon", BSIM4v6_NGCON, IF_REAL, "Number of gate contacts"),
IOPU("dtemp", BSIM4v6_DTEMP, IF_REAL, "Instance temperature difference"),
IOP( "trnqsmod", BSIM4v6_TRNQSMOD, IF_INTEGER, "Transient NQS model selector"), IOP( "trnqsmod", BSIM4v6_TRNQSMOD, IF_INTEGER, "Transient NQS model selector"),
IOP( "acnqsmod", BSIM4v6_ACNQSMOD, IF_INTEGER, "AC NQS model selector"), IOP( "acnqsmod", BSIM4v6_ACNQSMOD, IF_INTEGER, "AC NQS model selector"),

View File

@ -114,6 +114,9 @@ BSIM4v6instance *here = (BSIM4v6instance*)inst;
case BSIM4v6_MULU0: case BSIM4v6_MULU0:
value->rValue = here->BSIM4v6mulu0; value->rValue = here->BSIM4v6mulu0;
return(OK); return(OK);
case BSIM4v6_DTEMP:
value->rValue = here->BSIM4v6dtemp;
return(OK);
case BSIM4v6_XGW: case BSIM4v6_XGW:
value->rValue = here->BSIM4v6xgw; value->rValue = here->BSIM4v6xgw;
return(OK); return(OK);

View File

@ -141,6 +141,10 @@ IFvalue *select)
here->BSIM4v6mulu0 = value->rValue; here->BSIM4v6mulu0 = value->rValue;
here->BSIM4v6mulu0Given = TRUE; here->BSIM4v6mulu0Given = TRUE;
break; break;
case BSIM4v6_DTEMP:
here->BSIM4v6dtemp = value->rValue;
here->BSIM4v6dtempGiven = TRUE;
return(OK);
case BSIM4v6_XGW: case BSIM4v6_XGW:
here->BSIM4v6xgw = value->rValue; here->BSIM4v6xgw = value->rValue;
here->BSIM4v6xgwGiven = TRUE; here->BSIM4v6xgwGiven = TRUE;

View File

@ -2105,8 +2105,9 @@ BSIM4v6instance **InstArray;
here->BSIM4v6xgw = model->BSIM4v6xgw; here->BSIM4v6xgw = model->BSIM4v6xgw;
if (!here->BSIM4v6ngconGiven) if (!here->BSIM4v6ngconGiven)
here->BSIM4v6ngcon = model->BSIM4v6ngcon; here->BSIM4v6ngcon = model->BSIM4v6ngcon;
if (!here->BSIM4v6dtempGiven)
here->BSIM4v6dtemp = 0;
/* Process instance model selectors, some /* Process instance model selectors, some
* may override their global counterparts * may override their global counterparts
*/ */

View File

@ -114,6 +114,7 @@ typedef struct sBSIM4v6instance
double BSIM4v6mulu0; double BSIM4v6mulu0;
double BSIM4v6xgw; double BSIM4v6xgw;
double BSIM4v6ngcon; double BSIM4v6ngcon;
double BSIM4v6dtemp;
/* added here to account stress effect instance dependence */ /* added here to account stress effect instance dependence */
double BSIM4v6u0temp; double BSIM4v6u0temp;
@ -297,6 +298,7 @@ typedef struct sBSIM4v6instance
unsigned BSIM4v6mulu0Given :1; unsigned BSIM4v6mulu0Given :1;
unsigned BSIM4v6xgwGiven :1; unsigned BSIM4v6xgwGiven :1;
unsigned BSIM4v6ngconGiven :1; unsigned BSIM4v6ngconGiven :1;
unsigned BSIM4v6dtempGiven : 1;
unsigned BSIM4v6icVDSGiven :1; unsigned BSIM4v6icVDSGiven :1;
unsigned BSIM4v6icVGSGiven :1; unsigned BSIM4v6icVGSGiven :1;
unsigned BSIM4v6icVBSGiven :1; unsigned BSIM4v6icVBSGiven :1;
@ -2713,6 +2715,7 @@ typedef struct sBSIM4v6model
#define BSIM4v6_SC 37 #define BSIM4v6_SC 37
#define BSIM4v6_M 38 #define BSIM4v6_M 38
#define BSIM4v6_MULU0 39 #define BSIM4v6_MULU0 39
#define BSIM4v6_DTEMP 40
/* Global parameters */ /* Global parameters */
#define BSIM4v6_MOD_TEMPEOT 65 #define BSIM4v6_MOD_TEMPEOT 65

View File

@ -57,6 +57,7 @@ IOP( "mulu0", BSIM4v7_MULU0, IF_REAL, "Low field mobility multiplier"),
IOP( "xgw", BSIM4v7_XGW, IF_REAL, "Distance from gate contact center to device edge"), IOP( "xgw", BSIM4v7_XGW, IF_REAL, "Distance from gate contact center to device edge"),
IOP( "ngcon", BSIM4v7_NGCON, IF_REAL, "Number of gate contacts"), IOP( "ngcon", BSIM4v7_NGCON, IF_REAL, "Number of gate contacts"),
IOP( "wnflag", BSIM4v7_WNFLAG, IF_INTEGER, "W/NF device flag for bin selection"), IOP( "wnflag", BSIM4v7_WNFLAG, IF_INTEGER, "W/NF device flag for bin selection"),
IOPU( "dtemp", BSIM4v7_DTEMP, IF_REAL, "Instance temperature difference"),
IOP( "trnqsmod", BSIM4v7_TRNQSMOD, IF_INTEGER, "Transient NQS model selector"), IOP( "trnqsmod", BSIM4v7_TRNQSMOD, IF_INTEGER, "Transient NQS model selector"),
IOP( "acnqsmod", BSIM4v7_ACNQSMOD, IF_INTEGER, "AC NQS model selector"), IOP( "acnqsmod", BSIM4v7_ACNQSMOD, IF_INTEGER, "AC NQS model selector"),

View File

@ -114,6 +114,9 @@ BSIM4v7instance *here = (BSIM4v7instance*)inst;
case BSIM4v7_MULU0: case BSIM4v7_MULU0:
value->rValue = here->BSIM4v7mulu0; value->rValue = here->BSIM4v7mulu0;
return(OK); return(OK);
case BSIM4v7_DTEMP:
value->rValue = here->BSIM4v7dtemp;
return(OK);
case BSIM4v7_WNFLAG: case BSIM4v7_WNFLAG:
value->iValue = here->BSIM4v7wnflag; value->iValue = here->BSIM4v7wnflag;
return(OK); return(OK);

View File

@ -141,6 +141,10 @@ IFvalue *select)
here->BSIM4v7mulu0 = value->rValue; here->BSIM4v7mulu0 = value->rValue;
here->BSIM4v7mulu0Given = TRUE; here->BSIM4v7mulu0Given = TRUE;
break; break;
case BSIM4v7_DTEMP:
here->BSIM4v7dtemp = value->rValue;
here->BSIM4v7dtempGiven = TRUE;
return(OK);
case BSIM4v7_WNFLAG: case BSIM4v7_WNFLAG:
here->BSIM4v7wnflag = value->iValue; here->BSIM4v7wnflag = value->iValue;
here->BSIM4v7wnflagGiven = TRUE; here->BSIM4v7wnflagGiven = TRUE;

View File

@ -2256,8 +2256,9 @@ BSIM4v7instance **InstArray;
here->BSIM4v7xgw = model->BSIM4v7xgw; here->BSIM4v7xgw = model->BSIM4v7xgw;
if (!here->BSIM4v7ngconGiven) if (!here->BSIM4v7ngconGiven)
here->BSIM4v7ngcon = model->BSIM4v7ngcon; here->BSIM4v7ngcon = model->BSIM4v7ngcon;
if (!here->BSIM4v7dtempGiven)
here->BSIM4v7dtemp = 0;
/* Process instance model selectors, some /* Process instance model selectors, some
* may override their global counterparts * may override their global counterparts
*/ */

View File

@ -116,6 +116,7 @@ typedef struct sBSIM4v7instance
int BSIM4v7wnflag; int BSIM4v7wnflag;
double BSIM4v7xgw; double BSIM4v7xgw;
double BSIM4v7ngcon; double BSIM4v7ngcon;
double BSIM4v7dtemp;
/* added here to account stress effect instance dependence */ /* added here to account stress effect instance dependence */
double BSIM4v7u0temp; double BSIM4v7u0temp;
@ -302,6 +303,7 @@ typedef struct sBSIM4v7instance
unsigned BSIM4v7wnflagGiven :1; unsigned BSIM4v7wnflagGiven :1;
unsigned BSIM4v7xgwGiven :1; unsigned BSIM4v7xgwGiven :1;
unsigned BSIM4v7ngconGiven :1; unsigned BSIM4v7ngconGiven :1;
unsigned BSIM4v7dtempGiven : 1;
unsigned BSIM4v7icVDSGiven :1; unsigned BSIM4v7icVDSGiven :1;
unsigned BSIM4v7icVGSGiven :1; unsigned BSIM4v7icVGSGiven :1;
unsigned BSIM4v7icVBSGiven :1; unsigned BSIM4v7icVBSGiven :1;
@ -2843,6 +2845,7 @@ typedef struct sBSIM4v7model
#define BSIM4v7_M 38 #define BSIM4v7_M 38
#define BSIM4v7_MULU0 39 #define BSIM4v7_MULU0 39
#define BSIM4v7_WNFLAG 40 #define BSIM4v7_WNFLAG 40
#define BSIM4v7_DTEMP 41
/* Global parameters */ /* Global parameters */
#define BSIM4v7_MOD_TEMPEOT 65 #define BSIM4v7_MOD_TEMPEOT 65

View File

@ -58,6 +58,7 @@ static void free_dlerr_msg(char *msg);
#define RTLD_NOW 2 /* immediate function call binding */ #define RTLD_NOW 2 /* immediate function call binding */
#define RTLD_GLOBAL 4 /* symbols in this dlopen'ed obj are visible to other #define RTLD_GLOBAL 4 /* symbols in this dlopen'ed obj are visible to other
* dlopen'ed objs */ * dlopen'ed objs */
#define F_OK 0
#endif /* ifndef HAS_WINGUI */ #endif /* ifndef HAS_WINGUI */
#include "ngspice/dllitf.h" /* the coreInfo Structure*/ #include "ngspice/dllitf.h" /* the coreInfo Structure*/
@ -405,9 +406,14 @@ int load_opus(const char *name)
lib = dlopen(name, RTLD_NOW); lib = dlopen(name, RTLD_NOW);
// fprintf(stdout, "Lib %s has handle %p\n", name, lib); // fprintf(stdout, "Lib %s has handle %p\n", name, lib);
if (!lib) { if (!lib) {
msg = dlerror(); int acc = access(name, F_OK);
fprintf(stderr, "Error opening code model \"%s\"\n: %s\n", name, msg); if (acc != 0) {
FREE_DLERR_MSG(msg); fprintf(stderr, "Error opening code model \"%s\": No such file or directory!\n",
name);
}
else
fprintf(stderr, "Error opening code model \"%s\"\n", name);
return 1; return 1;
} }

View File

@ -1,7 +1,7 @@
/********** /**********
Copyright 1990 Regents of the University of California. All rights reserved. Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles Author: 1985 Thomas L. Quarles
Modified by Paolo Nenzi 2003 and Dietmar Warning 2012 Modified by Paolo Nenzi 2003, Dietmar Warning 2012 and Arpad Buermen 2025
**********/ **********/
#include "ngspice/ngspice.h" #include "ngspice/ngspice.h"
@ -122,6 +122,7 @@ IFparm DIOmPTable[] = { /* model parameters */
OPU( "cond", DIO_MOD_COND,IF_REAL, "Ohmic conductance"), OPU( "cond", DIO_MOD_COND,IF_REAL, "Ohmic conductance"),
IOP( "isr", DIO_MOD_ISR, IF_REAL, "Recombination saturation current"), IOP( "isr", DIO_MOD_ISR, IF_REAL, "Recombination saturation current"),
IOP( "nr", DIO_MOD_NR, IF_REAL, "Recombination current emission coefficient"), IOP( "nr", DIO_MOD_NR, IF_REAL, "Recombination current emission coefficient"),
IOP( "vp", DIO_MOD_VP, IF_REAL, "Soft reverse recovery parameter"),
/* SOA parameters */ /* SOA parameters */
IOPX( "fv_max", DIO_MOD_FV_MAX, IF_REAL, "maximum voltage in forward direction"), IOPX( "fv_max", DIO_MOD_FV_MAX, IF_REAL, "maximum voltage in forward direction"),

View File

@ -91,6 +91,20 @@ DIOacLoad(GENmodel *inModel, CKTcircuit *ckt)
(*(here->DIOnegTempPtr) += -dIdioSw_dT); (*(here->DIOnegTempPtr) += -dIdioSw_dT);
} }
} }
if ((here->DIOqpNode > 0) && (model->DIOsoftRevRecParam!=0) && (here->DIOtTransitTime!=0)) {
/* QP subcircuit */
double gdres= *(ckt->CKTstate0 + here->DIOresConduct);
double fac = here->DIOtTransitTime / model->DIOsoftRevRecParam;
double dcrrdvd = fac * gdres;
*(here->DIOqpQpPtr) += 1/model->DIOsoftRevRecParam;
*(here->DIOqpQpPtr + 1) += here->DIOtTransitTime * ckt->CKTomega;
*(here->DIOqpPosPrimePtr) += -dcrrdvd;
*(here->DIOqpNegPtr) += dcrrdvd;
/* Gain of VCVS (1-vp)/tau * j*omega*tau = (1-vp) * j*omega */
double xgain = (1 - model->DIOsoftRevRecParam) * ckt->CKTomega;
*(here->DIOposPrimeQpPtr + 1) += xgain;
*(here->DIOnegQpPtr + 1) += -xgain;
}
} }
} }
return(OK); return(OK);

View File

@ -75,9 +75,13 @@ DIOask (CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value,
return(OK); return(OK);
case DIO_CURRENT: case DIO_CURRENT:
value->rValue = *(ckt->CKTstate0+here->DIOcurrent); value->rValue = *(ckt->CKTstate0+here->DIOcurrent);
if ((here->DIOqpNode > 0) && (here->DIOtTransitTime!=0))
value->rValue += here->DIOqpGain * *(ckt->CKTstate0 + here->DIOcqcsr);
return(OK); return(OK);
case DIO_CAP: case DIO_CAP:
value->rValue = here->DIOcap; value->rValue = here->DIOcap;
if ((here->DIOqpNode > 0) && (here->DIOtTransitTime!=0))
value->rValue += here->DIOtTransitTime * *(ckt->CKTstate0+here->DIOconduct);
return(OK); return(OK);
case DIO_CHARGE: case DIO_CHARGE:
value->rValue = *(ckt->CKTstate0+here->DIOcapCharge); value->rValue = *(ckt->CKTstate0+here->DIOcapCharge);

View File

@ -54,6 +54,14 @@ DIObindCSC (GENmodel *inModel, CKTcircuit *ckt)
CREATE_KLU_BINDING_TABLE(DIOposSwPrimeTempPtr, DIOposSwPrimeTempBinding, DIOposSwPrimeNode, DIOtempNode); CREATE_KLU_BINDING_TABLE(DIOposSwPrimeTempPtr, DIOposSwPrimeTempBinding, DIOposSwPrimeNode, DIOtempNode);
} }
} }
/* rev-rec */
if (model->DIOsoftRevRecParamGiven && model->DIOsoftRevRecParam!=0 && model->DIOtransitTime!=0) {
CREATE_KLU_BINDING_TABLE(DIOqpQpPtr , DIOqpQpBinding , DIOqpNode, DIOqpNode);
CREATE_KLU_BINDING_TABLE(DIOqpPosPrimePtr, DIOqpPosPrimeBinding, DIOqpNode, DIOposPrimeNode);
CREATE_KLU_BINDING_TABLE(DIOqpNegPtr , DIOqpNegBinding , DIOqpNode, DIOnegNode);
CREATE_KLU_BINDING_TABLE(DIOposPrimeQpPtr, DIOposPrimeQpBinding, DIOposPrimeNode, DIOqpNode);
CREATE_KLU_BINDING_TABLE(DIOnegQpPtr , DIOnegQpBinding , DIOnegNode, DIOqpNode);
}
} }
} }
@ -103,6 +111,14 @@ DIObindCSCComplex (GENmodel *inModel, CKTcircuit *ckt)
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(DIOposSwPrimeTempPtr, DIOposSwPrimeTempBinding, DIOposSwPrimeNode, DIOtempNode); CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(DIOposSwPrimeTempPtr, DIOposSwPrimeTempBinding, DIOposSwPrimeNode, DIOtempNode);
} }
} }
/* rev-rec */
if (model->DIOsoftRevRecParamGiven && model->DIOsoftRevRecParam!=0 && model->DIOtransitTime!=0) {
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(DIOqpQpPtr , DIOqpQpBinding , DIOqpNode, DIOqpNode);
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(DIOqpPosPrimePtr, DIOqpPosPrimeBinding, DIOqpNode, DIOposPrimeNode);
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(DIOqpNegPtr , DIOqpNegBinding , DIOqpNode, DIOnegNode);
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(DIOposPrimeQpPtr, DIOposPrimeQpBinding, DIOposPrimeNode, DIOqpNode);
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(DIOnegQpPtr , DIOnegQpBinding , DIOnegNode, DIOqpNode);
}
} }
} }
@ -152,6 +168,14 @@ DIObindCSCComplexToReal (GENmodel *inModel, CKTcircuit *ckt)
CONVERT_KLU_BINDING_TABLE_TO_REAL(DIOposSwPrimeTempPtr, DIOposSwPrimeTempBinding, DIOposSwPrimeNode, DIOtempNode); CONVERT_KLU_BINDING_TABLE_TO_REAL(DIOposSwPrimeTempPtr, DIOposSwPrimeTempBinding, DIOposSwPrimeNode, DIOtempNode);
} }
} }
/* rev-rec */
if (model->DIOsoftRevRecParamGiven && model->DIOsoftRevRecParam!=0 && model->DIOtransitTime!=0) {
CONVERT_KLU_BINDING_TABLE_TO_REAL(DIOqpQpPtr , DIOqpQpBinding , DIOqpNode, DIOqpNode);
CONVERT_KLU_BINDING_TABLE_TO_REAL(DIOqpPosPrimePtr, DIOqpPosPrimeBinding, DIOqpNode, DIOposPrimeNode);
CONVERT_KLU_BINDING_TABLE_TO_REAL(DIOqpNegPtr , DIOqpNegBinding , DIOqpNode, DIOnegNode);
CONVERT_KLU_BINDING_TABLE_TO_REAL(DIOposPrimeQpPtr, DIOposPrimeQpBinding, DIOposPrimeNode, DIOqpNode);
CONVERT_KLU_BINDING_TABLE_TO_REAL(DIOnegQpPtr , DIOnegQpBinding , DIOnegNode, DIOqpNode);
}
} }
} }

View File

@ -1,7 +1,7 @@
/********** /**********
Copyright 1990 Regents of the University of California. All rights reserved. Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles Author: 1985 Thomas L. Quarles
Modified by Paolo Nenzi 2003 and Dietmar Warning 2012 Modified by Paolo Nenzi 2003, Dietmar Warning 2012 and Arpad Buermen 2025
**********/ **********/
#ifndef DIO #ifndef DIO
#define DIO #define DIO
@ -44,6 +44,7 @@ typedef struct sDIOinstance {
const int DIOtempNode; /* number of the temperature node of the diode */ const int DIOtempNode; /* number of the temperature node of the diode */
int DIOposPrimeNode; /* number of positive prime node of diode */ int DIOposPrimeNode; /* number of positive prime node of diode */
int DIOposSwPrimeNode; /* number of positive prime node of diode sidewall */ int DIOposSwPrimeNode; /* number of positive prime node of diode sidewall */
int DIOqpNode; /* number of soft recovery charge node */
double *DIOposPosPrimePtr; /* pointer to sparse matrix at double *DIOposPosPrimePtr; /* pointer to sparse matrix at
* (positive,positive prime) */ * (positive,positive prime) */
@ -83,9 +84,19 @@ typedef struct sDIOinstance {
double *DIOtempPosSwPrimePtr; double *DIOtempPosSwPrimePtr;
double *DIOposSwPrimeTempPtr; double *DIOposSwPrimeTempPtr;
/* rev-rec */
double *DIOqpQpPtr;
double *DIOqpPosPrimePtr;
double *DIOqpNegPtr;
double *DIOposPrimeQpPtr;
double *DIOnegQpPtr;
double DIOcap; /* stores the diode capacitance */ double DIOcap; /* stores the diode capacitance */
double DIOcapSW; /* stores the diode Sw capacitance */ double DIOcapSW; /* stores the diode Sw capacitance */
/* rev-rec */
double DIOqpGain;/* converts iterated diffcharge current */
double *DIOsens; /* stores the perturbed values of geq and ceq in ac double *DIOsens; /* stores the perturbed values of geq and ceq in ac
sensitivity analyis */ sensitivity analyis */
@ -229,13 +240,19 @@ typedef struct sDIOinstance {
/* self heating */ /* self heating */
BindElement *DIOtempPosBinding; BindElement *DIOtempPosBinding;
BindElement *DIOtempPosPrimeBinding; BindElement *DIOtempPosPrimeBinding;
BindElement *DIOtempNegBinding; BindElement *DIOtempNegBinding;
BindElement *DIOtempTempBinding; BindElement *DIOtempTempBinding;
BindElement *DIOposTempBinding; BindElement *DIOposTempBinding;
BindElement *DIOposPrimeTempBinding; BindElement *DIOposPrimeTempBinding;
BindElement *DIOnegTempBinding; BindElement *DIOnegTempBinding;
BindElement *DIOtempPosSwPrimeBinding; BindElement *DIOtempPosSwPrimeBinding;
BindElement *DIOposSwPrimeTempBinding; BindElement *DIOposSwPrimeTempBinding;
/* rev-rec */
BindElement *DIOqpQpBinding;
BindElement *DIOqpPosPrimeBinding;
BindElement *DIOqpNegBinding;
BindElement *DIOposPrimeQpBinding;
BindElement *DIOnegQpBinding;
#endif #endif
} DIOinstance ; } DIOinstance ;
@ -244,7 +261,6 @@ typedef struct sDIOinstance {
#define DIOsenCeq DIOsens + 3 /* stores the perturbed values of ceq */ #define DIOsenCeq DIOsens + 3 /* stores the perturbed values of ceq */
#define DIOdphidp DIOsens + 6 #define DIOdphidp DIOsens + 6
#define DIOvoltage DIOstate #define DIOvoltage DIOstate
#define DIOcurrent DIOstate+1 #define DIOcurrent DIOstate+1
#define DIOconduct DIOstate+2 #define DIOconduct DIOstate+2
@ -256,18 +272,25 @@ typedef struct sDIOinstance {
#define DIOcapChargeSW DIOstate+8 #define DIOcapChargeSW DIOstate+8
#define DIOcapCurrentSW DIOstate+9 #define DIOcapCurrentSW DIOstate+9
#define DIOqth DIOstate+10 /* thermal capacitor charge */ #define DIOqth DIOstate+10 /* thermal capacitor charge */
#define DIOcqth DIOstate+11 /* thermal capacitor current */ #define DIOcqth DIOstate+11 /* thermal capacitor current */
#define DIOdeltemp DIOstate+12 /* thermal voltage over rth0 */
#define DIOdeltemp DIOstate+12 /* thermal voltage over rth0 */
#define DIOdIdio_dT DIOstate+13 #define DIOdIdio_dT DIOstate+13
#define DIOdIdioSW_dT DIOstate+14 #define DIOdIdioSW_dT DIOstate+14
/* rev-rec */
#define DIOsrcapCharge DIOstate+15
#define DIOsrcapCurrent DIOstate+16
#define DIOqp DIOstate+17
#define DIOresCurrent DIOstate+18
#define DIOresConduct DIOstate+19
#define DIOcqcsr DIOstate+20
#define DIOgqcsr DIOstate+21
#define DIOnumStates 15 #define DIOnumStates 22
#define DIOsensxp DIOstate+15 /* charge sensitivities and their derivatives. #define DIOsensxp DIOstate+22 /* charge sensitivities and their derivatives.
* +16 for the derivatives - pointer to the * +23 for the derivatives - pointer to the
* beginning of the array */ * beginning of the array */
#define DIOnumSenStates 2 #define DIOnumSenStates 2
@ -342,6 +365,7 @@ typedef struct sDIOmodel { /* model structure for a diode */
unsigned DIOte_maxGiven : 1; unsigned DIOte_maxGiven : 1;
unsigned DIOrecSatCurGiven : 1; unsigned DIOrecSatCurGiven : 1;
unsigned DIOrecEmissionCoeffGiven : 1; unsigned DIOrecEmissionCoeffGiven : 1;
unsigned DIOsoftRevRecParamGiven : 1;
unsigned DIOrth0Given :1; unsigned DIOrth0Given :1;
unsigned DIOcth0Given :1; unsigned DIOcth0Given :1;
@ -418,6 +442,7 @@ typedef struct sDIOmodel { /* model structure for a diode */
double DIOte_max; /* maximum temperature */ double DIOte_max; /* maximum temperature */
double DIOrecSatCur; /* Recombination saturation current */ double DIOrecSatCur; /* Recombination saturation current */
double DIOrecEmissionCoeff; /* Recombination emission coefficient */ double DIOrecEmissionCoeff; /* Recombination emission coefficient */
double DIOsoftRevRecParam; /* Soft reverse recovery parameter */
double DIOrth0; double DIOrth0;
double DIOcth0; double DIOcth0;
@ -526,6 +551,7 @@ enum {
DIO_MOD_PD_MAX, DIO_MOD_PD_MAX,
DIO_MOD_ISR, DIO_MOD_ISR,
DIO_MOD_NR, DIO_MOD_NR,
DIO_MOD_VP,
DIO_MOD_RTH0, DIO_MOD_RTH0,
DIO_MOD_CTH0, DIO_MOD_CTH0,

View File

@ -2,7 +2,7 @@
Copyright 1990 Regents of the University of California. All rights reserved. Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles Author: 1985 Thomas L. Quarles
Modified: 2000 AlansFixes Modified: 2000 AlansFixes
Modified by Paolo Nenzi 2003 and Dietmar Warning 2012 Modified by Paolo Nenzi 2003, Dietmar Warning 2012 and Arpad Buermen 2025
**********/ **********/
#include "ngspice/ngspice.h" #include "ngspice/ngspice.h"
@ -65,6 +65,10 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
double dIdio_dT, dIth_dVdio=0.0, dIrs_dT=0.0, dIth_dVrs=0.0, dIth_dT=0.0; double dIdio_dT, dIth_dVdio=0.0, dIrs_dT=0.0, dIth_dVrs=0.0, dIth_dT=0.0;
double dIdioSw_dT=0.0, dIth_dVdioSw=0.0, dIth_dVrssw=0.0, dIrssw_dT=0.0; double dIdioSw_dT=0.0, dIth_dVdioSw=0.0, dIth_dVrssw=0.0, dIrssw_dT=0.0;
double argsw_dT, csat_dT, csatsw_dT; double argsw_dT, csat_dT, csatsw_dT;
/* rev-rec */
double cdres, gdres;
double vqp;
double capsr, gqcsr, cqcsr;
/* loop through all the diode models */ /* loop through all the diode models */
for( ; model != NULL; model = DIOnextModel(model)) { for( ; model != NULL; model = DIOnextModel(model)) {
@ -74,6 +78,7 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
here=DIOnextInstance(here)) { here=DIOnextInstance(here)) {
int selfheat = ((here->DIOtempNode > 0) && (here->DIOthermal) && (model->DIOrth0Given)); int selfheat = ((here->DIOtempNode > 0) && (here->DIOthermal) && (model->DIOrth0Given));
int revrec = ((here->DIOqpNode > 0) && (model->DIOsoftRevRecParam!=0) && (here->DIOtTransitTime!=0));
/* /*
* this routine loads diodes for dc and transient analyses. * this routine loads diodes for dc and transient analyses.
@ -120,10 +125,12 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
vd = *(ckt->CKTstate1 + here->DIOvoltage); vd = *(ckt->CKTstate1 + here->DIOvoltage);
if (model->DIOresistSWGiven) vdsw = *(ckt->CKTstate1 + here->DIOvoltageSW); if (model->DIOresistSWGiven) vdsw = *(ckt->CKTstate1 + here->DIOvoltageSW);
delTemp = *(ckt->CKTstate1 + here->DIOdeltemp); delTemp = *(ckt->CKTstate1 + here->DIOdeltemp);
vqp = *(ckt->CKTstate1 + here->DIOqp);
} else{ } else{
vd = *(ckt->CKTstate0 + here->DIOvoltage); vd = *(ckt->CKTstate0 + here->DIOvoltage);
if (model->DIOresistSWGiven) vdsw = *(ckt->CKTstate0 + here->DIOvoltageSW); if (model->DIOresistSWGiven) vdsw = *(ckt->CKTstate0 + here->DIOvoltageSW);
delTemp = *(ckt->CKTstate0 + here->DIOdeltemp); delTemp = *(ckt->CKTstate0 + here->DIOdeltemp);
vqp = *(ckt->CKTstate0 + here->DIOqp);
} }
#ifdef SENSDEBUG #ifdef SENSDEBUG
@ -137,24 +144,30 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
vd= *(ckt->CKTstate0 + here->DIOvoltage); vd= *(ckt->CKTstate0 + here->DIOvoltage);
if (model->DIOresistSWGiven) vdsw = *(ckt->CKTstate0 + here->DIOvoltageSW); if (model->DIOresistSWGiven) vdsw = *(ckt->CKTstate0 + here->DIOvoltageSW);
delTemp = *(ckt->CKTstate0 + here->DIOdeltemp); delTemp = *(ckt->CKTstate0 + here->DIOdeltemp);
vqp= *(ckt->CKTstate0 + here->DIOqp);
} else if (ckt->CKTmode & MODEINITTRAN) { } else if (ckt->CKTmode & MODEINITTRAN) {
vd= *(ckt->CKTstate1 + here->DIOvoltage); vd= *(ckt->CKTstate1 + here->DIOvoltage);
if (model->DIOresistSWGiven) vdsw = *(ckt->CKTstate1 + here->DIOvoltageSW); if (model->DIOresistSWGiven) vdsw = *(ckt->CKTstate1 + here->DIOvoltageSW);
delTemp = *(ckt->CKTstate1 + here->DIOdeltemp); delTemp = *(ckt->CKTstate1 + here->DIOdeltemp);
vqp= *(ckt->CKTstate1 + here->DIOqp);
} else if ( (ckt->CKTmode & MODEINITJCT) && } else if ( (ckt->CKTmode & MODEINITJCT) &&
(ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC) ) { (ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC) ) {
vd=here->DIOinitCond; vd=here->DIOinitCond;
if (model->DIOresistSWGiven) vdsw = here->DIOinitCond; if (model->DIOresistSWGiven) vdsw = here->DIOinitCond;
vqp=0;
} else if ( (ckt->CKTmode & MODEINITJCT) && here->DIOoff) { } else if ( (ckt->CKTmode & MODEINITJCT) && here->DIOoff) {
vd=vdsw=0; vd=vdsw=0;
delTemp = 0.0; delTemp = 0.0;
vqp=0;
} else if ( ckt->CKTmode & MODEINITJCT) { } else if ( ckt->CKTmode & MODEINITJCT) {
vd=here->DIOtVcrit; vd=here->DIOtVcrit;
vdsw=here->DIOtVcritSW; vdsw=here->DIOtVcritSW;
delTemp = 0.0; delTemp = 0.0;
vqp=0;
} else if ( ckt->CKTmode & MODEINITFIX && here->DIOoff) { } else if ( ckt->CKTmode & MODEINITFIX && here->DIOoff) {
vd=vdsw=0; vd=vdsw=0;
delTemp = 0.0; delTemp = 0.0;
vqp=0;
} else { } else {
#ifndef PREDICTOR #ifndef PREDICTOR
if (ckt->CKTmode & MODEINITPRED) { if (ckt->CKTmode & MODEINITPRED) {
@ -177,12 +190,22 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
*(ckt->CKTstate0 + here->DIOdIdioSW_dT) = *(ckt->CKTstate0 + here->DIOdIdioSW_dT) =
*(ckt->CKTstate1 + here->DIOdIdioSW_dT); *(ckt->CKTstate1 + here->DIOdIdioSW_dT);
} }
vqp = DEVpred(ckt,here->DIOqp);
*(ckt->CKTstate0 + here->DIOresCurrent) =
*(ckt->CKTstate1 + here->DIOresCurrent);
*(ckt->CKTstate0 + here->DIOresConduct) =
*(ckt->CKTstate1 + here->DIOresConduct);
*(ckt->CKTstate0 + here->DIOcqcsr) =
*(ckt->CKTstate1 + here->DIOcqcsr);
*(ckt->CKTstate0 + here->DIOgqcsr) =
*(ckt->CKTstate1 + here->DIOgqcsr);
} else { } else {
#endif /* PREDICTOR */ #endif /* PREDICTOR */
vd = *(ckt->CKTrhsOld+here->DIOposPrimeNode)- vd = *(ckt->CKTrhsOld+here->DIOposPrimeNode)-
*(ckt->CKTrhsOld + here->DIOnegNode); *(ckt->CKTrhsOld + here->DIOnegNode);
if (model->DIOresistSWGiven) vdsw = *(ckt->CKTrhsOld+here->DIOposSwPrimeNode)- if (model->DIOresistSWGiven) vdsw = *(ckt->CKTrhsOld+here->DIOposSwPrimeNode)-
*(ckt->CKTrhsOld + here->DIOnegNode); *(ckt->CKTrhsOld + here->DIOnegNode);
if (selfheat) if (selfheat)
delTemp = *(ckt->CKTrhsOld + here->DIOtempNode); delTemp = *(ckt->CKTrhsOld + here->DIOtempNode);
else else
@ -192,6 +215,7 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
*(ckt->CKTstate1+here->DIOqth) = *(ckt->CKTstate1+here->DIOqth) =
*(ckt->CKTstate0+here->DIOqth); *(ckt->CKTstate0+here->DIOqth);
} }
vqp = *(ckt->CKTrhsOld+here->DIOqpNode);
#ifndef PREDICTOR #ifndef PREDICTOR
} }
#endif /* PREDICTOR */ #endif /* PREDICTOR */
@ -238,6 +262,11 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
gdsw= *(ckt->CKTstate0 + here->DIOconductSW); gdsw= *(ckt->CKTstate0 + here->DIOconductSW);
dIdioSw_dT= *(ckt->CKTstate0 + here->DIOdIdioSW_dT); dIdioSw_dT= *(ckt->CKTstate0 + here->DIOdIdioSW_dT);
} }
vqp= *(ckt->CKTstate0 + here->DIOqp);
cdres= *(ckt->CKTstate0 + here->DIOresCurrent);
gdres= *(ckt->CKTstate0 + here->DIOresConduct);
cqcsr= *(ckt->CKTstate0 + here->DIOcqcsr);
gqcsr= *(ckt->CKTstate0 + here->DIOgqcsr);
goto load; goto load;
} }
} }
@ -304,7 +333,7 @@ next1:
if (model->DIOsatSWCurGiven) { /* sidewall current */ if (model->DIOsatSWCurGiven) { /* sidewall current */
double vds; double vds;
if (model->DIOresistSWGiven) if (model->DIOresistSWGiven)
vds = vdsw; /* sidewall voltage used */ vds = vdsw; /* sidewall voltage used */
else else
vds = vd; /* common voltage used */ vds = vd; /* common voltage used */
@ -470,7 +499,6 @@ next1:
gdb = ((1+sqrt_ikx)*gdb + cdb*gdb/(2*sqrt_ikx*ikr_area_m))/(1+2*sqrt_ikx - cdb/ikr_area_m); gdb = ((1+sqrt_ikx)*gdb + cdb*gdb/(2*sqrt_ikx*ikr_area_m))/(1+2*sqrt_ikx - cdb/ikr_area_m);
cdb = cdb/(1+sqrt_ikx); cdb = cdb/(1+sqrt_ikx);
} }
} }
if ( (model->DIOforwardSWKneeCurrentGiven) && (cdsw > 1.0e-18) ) { if ( (model->DIOforwardSWKneeCurrentGiven) && (cdsw > 1.0e-18) ) {
@ -493,6 +521,11 @@ next1:
dIdioSw_dT = cdsw_dT; dIdioSw_dT = cdsw_dT;
} }
cdres = cd;
gdres = gd;
cqcsr = 0;
gqcsr = 0;
if ((ckt->CKTmode & (MODEDCTRANCURVE | MODETRAN | MODEAC | MODEINITSMSIG)) || if ((ckt->CKTmode & (MODEDCTRANCURVE | MODETRAN | MODEAC | MODEINITSMSIG)) ||
((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC))) { ((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC))) {
/* /*
@ -528,22 +561,46 @@ next1:
deplcapSW = czof2SW*(here->DIOtF3SW+model->DIOgradingSWCoeff*vdx/here->DIOtJctSWPot); deplcapSW = czof2SW*(here->DIOtF3SW+model->DIOgradingSWCoeff*vdx/here->DIOtJctSWPot);
} }
diffcharge = here->DIOtTransitTime*cd; if (revrec) {
diffcap = here->DIOtTransitTime*gd; /*
if (!model->DIOresistSWGiven) { soft recovery with TT!=0
add only depletion capacitance.
*/
*(ckt->CKTstate0 + here->DIOcapCharge) = *(ckt->CKTstate0 + here->DIOcapCharge) =
diffcharge + deplcharge + deplchargeSW + (here->DIOcmetal + here->DIOcpoly)*vd; deplcharge + deplchargeSW + (here->DIOcmetal + here->DIOcpoly)*vd;
capd = diffcap + deplcap + deplcapSW + here->DIOcmetal + here->DIOcpoly;
capd = deplcap + deplcapSW + here->DIOcmetal + here->DIOcpoly;
here->DIOcap = capd; here->DIOcap = capd;
/*
DIOcap is now equal only to depletion capacitance + overlap capacitance.
Diffusion capacitance is modelled via Qp so there is no clear way to define it.
*/
/* Now prepare the charge for the capacitor connected to the QP node */
*(ckt->CKTstate0 + here->DIOsrcapCharge) = here->DIOtTransitTime * vqp;
capsr = here->DIOtTransitTime;
} else { } else {
*(ckt->CKTstate0 + here->DIOcapCharge) = /* no soft recovery of soft recovery with TT=0 (i.e. no soft recovery due to TT=0) */
diffcharge + deplcharge + (here->DIOcmetal + here->DIOcpoly)*vd; diffcharge = here->DIOtTransitTime*cd;
capd = diffcap + deplcap + here->DIOcmetal + here->DIOcpoly; diffcap = here->DIOtTransitTime*gd;
here->DIOcap = capd; if (!model->DIOresistSWGiven) {
*(ckt->CKTstate0 + here->DIOcapChargeSW) = *(ckt->CKTstate0 + here->DIOcapCharge) =
deplcapSW; diffcharge + deplcharge + deplchargeSW + (here->DIOcmetal + here->DIOcpoly)*vd;
capdsw = deplcapSW; capd = diffcap + deplcap + deplcapSW + here->DIOcmetal + here->DIOcpoly;
here->DIOcapSW = capdsw; here->DIOcap = capd;
} else {
*(ckt->CKTstate0 + here->DIOcapCharge) =
diffcharge + deplcharge + (here->DIOcmetal + here->DIOcpoly)*vd;
capd = diffcap + deplcap + here->DIOcmetal + here->DIOcpoly;
here->DIOcap = capd;
*(ckt->CKTstate0 + here->DIOcapChargeSW) =
deplcapSW;
capdsw = deplcapSW;
here->DIOcapSW = capdsw;
}
*(ckt->CKTstate0 + here->DIOsrcapCharge) = 0;
capsr = 0;
} }
/* /*
* store small-signal parameters * store small-signal parameters
@ -564,6 +621,10 @@ next1:
*(ckt->CKTstate0 + here->DIOconductSW) = gdsw; *(ckt->CKTstate0 + here->DIOconductSW) = gdsw;
*(ckt->CKTstate0 + here->DIOdIdioSW_dT) = dIdioSw_dT; *(ckt->CKTstate0 + here->DIOdIdioSW_dT) = dIdioSw_dT;
} }
*(ckt->CKTstate0 + here->DIOresCurrent) = cdres;
*(ckt->CKTstate0 + here->DIOresConduct) = gdres;
*(ckt->CKTstate0 + here->DIOcqcsr) = cqcsr;
*(ckt->CKTstate0 + here->DIOgqcsr) = gqcsr;
#ifdef SENSDEBUG #ifdef SENSDEBUG
printf("storing small signal parameters\n"); printf("storing small signal parameters\n");
printf("cd = %.7e,vd = %.7e\n",cd,vd); printf("cd = %.7e,vd = %.7e\n",cd,vd);
@ -580,6 +641,7 @@ next1:
*(ckt->CKTstate0 + here->DIOcurrent) = cd; *(ckt->CKTstate0 + here->DIOcurrent) = cd;
if (model->DIOresistSWGiven) if (model->DIOresistSWGiven)
*(ckt->CKTstate0 + here->DIOcurrentSW) = cdsw; *(ckt->CKTstate0 + here->DIOcurrentSW) = cdsw;
*(ckt->CKTstate0 + here->DIOresCurrent) = cdres;
#ifdef SENSDEBUG #ifdef SENSDEBUG
printf("storing parameters for transient sensitivity\n" printf("storing parameters for transient sensitivity\n"
); );
@ -613,6 +675,21 @@ next1:
*(ckt->CKTstate1 + here->DIOcapCurrentSW) = *(ckt->CKTstate1 + here->DIOcapCurrentSW) =
*(ckt->CKTstate0 + here->DIOcapCurrentSW); *(ckt->CKTstate0 + here->DIOcapCurrentSW);
} }
if (revrec) {
/* soft recovery subcircuit */
if (ckt->CKTmode & MODEINITTRAN) {
*(ckt->CKTstate1 + here->DIOsrcapCharge) =
*(ckt->CKTstate0 + here->DIOsrcapCharge);
}
error = NIintegrate(ckt,&geq,&ceq,capsr,here->DIOsrcapCharge);
if(error) return(error);
gqcsr = geq;
cqcsr = *(ckt->CKTstate0 + here->DIOsrcapCurrent);
if (ckt->CKTmode & MODEINITTRAN) {
*(ckt->CKTstate1 + here->DIOsrcapCurrent) =
*(ckt->CKTstate0 + here->DIOsrcapCurrent);
}
}
if (selfheat) if (selfheat)
{ {
error = NIintegrate(ckt, &gcTt, &ceqqth, model->DIOcth0, here->DIOqth); error = NIintegrate(ckt, &gcTt, &ceqqth, model->DIOcth0, here->DIOqth);
@ -654,6 +731,11 @@ next2: *(ckt->CKTstate0 + here->DIOvoltage) = vd;
*(ckt->CKTstate0 + here->DIOconductSW) = gdsw; *(ckt->CKTstate0 + here->DIOconductSW) = gdsw;
*(ckt->CKTstate0 + here->DIOdIdioSW_dT) = dIdioSw_dT; *(ckt->CKTstate0 + here->DIOdIdioSW_dT) = dIdioSw_dT;
} }
*(ckt->CKTstate0 + here->DIOqp) = vqp;
*(ckt->CKTstate0 + here->DIOresCurrent) = cdres;
*(ckt->CKTstate0 + here->DIOresConduct) = gdres;
*(ckt->CKTstate0 + here->DIOcqcsr) = cqcsr;
*(ckt->CKTstate0 + here->DIOgqcsr) = gqcsr;
if(SenCond) continue; if(SenCond) continue;
#ifndef NOBYPASS #ifndef NOBYPASS
@ -707,9 +789,9 @@ next2: *(ckt->CKTstate0 + here->DIOvoltage) = vd;
*(ckt->CKTrhs + here->DIOtempNode) += Ith - dIth_dVdio*vd - dIth_dVrs*vrs - dIth_dT*delTemp - ceqqth; *(ckt->CKTrhs + here->DIOtempNode) += Ith - dIth_dVdio*vd - dIth_dVrs*vrs - dIth_dT*delTemp - ceqqth;
} }
if (model->DIOresistSWGiven) { if (model->DIOresistSWGiven) {
cdeq=cdsw-gdsw*vdsw; double cdeqsw=cdsw-gdsw*vdsw;
*(ckt->CKTrhs + here->DIOnegNode) += cdeq; *(ckt->CKTrhs + here->DIOnegNode) += cdeqsw;
*(ckt->CKTrhs + here->DIOposSwPrimeNode) -= cdeq; *(ckt->CKTrhs + here->DIOposSwPrimeNode) -= cdeqsw;
if (selfheat) { if (selfheat) {
*(ckt->CKTrhs + here->DIOposNode) += dIrssw_dT*delTemp; *(ckt->CKTrhs + here->DIOposNode) += dIrssw_dT*delTemp;
*(ckt->CKTrhs + here->DIOposSwPrimeNode) += dIdioSw_dT*delTemp - dIrssw_dT*delTemp; *(ckt->CKTrhs + here->DIOposSwPrimeNode) += dIdioSw_dT*delTemp - dIrssw_dT*delTemp;
@ -754,6 +836,29 @@ next2: *(ckt->CKTstate0 + here->DIOvoltage) = vd;
(*(here->DIOnegTempPtr) += -dIdioSw_dT); (*(here->DIOnegTempPtr) += -dIdioSw_dT);
} }
} }
if (revrec) {
double fac, ceqrr, dcrrdvd, grr;
double ceqrrd, geqrrd;
/* QP subcircuit */
fac = here->DIOtTransitTime / model->DIOsoftRevRecParam;
dcrrdvd = fac*gdres;
ceqrr = -fac*cdres + cqcsr + dcrrdvd*vd - gqcsr*vqp;
grr = 1/model->DIOsoftRevRecParam;
*(ckt->CKTrhs + here->DIOqpNode) -= ceqrr;
*(here->DIOqpQpPtr) += grr + gqcsr;
*(here->DIOqpPosPrimePtr) += -dcrrdvd;
*(here->DIOqpNegPtr) += dcrrdvd;
/* Contribution to diode current */
here->DIOqpGain = (1 - model->DIOsoftRevRecParam) / here->DIOtTransitTime;
/* Linear contribution -(1-vp)/tau*ddt(Qp) */
geqrrd = here->DIOqpGain*gqcsr;
ceqrrd = here->DIOqpGain*cqcsr - geqrrd*vqp;
*(ckt->CKTrhs + here->DIOposPrimeNode) -= ceqrrd;
*(ckt->CKTrhs + here->DIOnegNode) += ceqrrd;
*(here->DIOposPrimeQpPtr) += geqrrd;
*(here->DIOnegQpPtr) += -geqrrd;
}
} }
} }
return(OK); return(OK);

View File

@ -1,7 +1,7 @@
/********** /**********
Copyright 1990 Regents of the University of California. All rights reserved. Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles Author: 1985 Thomas L. Quarles
Modified by Paolo Nenzi 2003 and Dietmar Warning 2012 Modified by Paolo Nenzi 2003, Dietmar Warning 2012 and Arpad Buermen 2025
**********/ **********/
/* /*
*/ */
@ -199,6 +199,9 @@ DIOmAsk (CKTcircuit *ckt, GENmodel *inModel, int which, IFvalue *value)
case DIO_MOD_NR: case DIO_MOD_NR:
value->rValue = model->DIOrecEmissionCoeff; value->rValue = model->DIOrecEmissionCoeff;
return(OK); return(OK);
case DIO_MOD_VP:
value->rValue = model->DIOsoftRevRecParam;
return(OK);
case DIO_MOD_RTH0: case DIO_MOD_RTH0:
value->rValue = model->DIOrth0; value->rValue = model->DIOrth0;
return(OK); return(OK);

View File

@ -1,7 +1,7 @@
/********** /**********
Copyright 1990 Regents of the University of California. All rights reserved. Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles Author: 1985 Thomas L. Quarles
Modified by Paolo Nenzi 2003 and Dietmar Warning 2012 Modified by Paolo Nenzi 2003, Dietmar Warning 2012 and Arpad Buermen 2025
**********/ **********/
/* /*
*/ */
@ -245,6 +245,10 @@ DIOmParam(int param, IFvalue *value, GENmodel *inModel)
model->DIOrecEmissionCoeff = value->rValue; model->DIOrecEmissionCoeff = value->rValue;
model->DIOrecEmissionCoeffGiven = TRUE; model->DIOrecEmissionCoeffGiven = TRUE;
break; break;
case DIO_MOD_VP:
model->DIOsoftRevRecParam = value->rValue;
model->DIOsoftRevRecParamGiven = TRUE;
break;
case DIO_MOD_RTH0: case DIO_MOD_RTH0:
model->DIOrth0 = value->rValue; model->DIOrth0 = value->rValue;
model->DIOrth0Given = TRUE; model->DIOrth0Given = TRUE;

View File

@ -2,7 +2,7 @@
Copyright 1990 Regents of the University of California. All rights reserved. Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles Author: 1985 Thomas L. Quarles
Modified: 2000 AlansFixes Modified: 2000 AlansFixes
Modified by Paolo Nenzi 2003 and Dietmar Warning 2012 Modified by Paolo Nenzi 2003, Dietmar Warning 2012 and Arpad Buermen 2025
**********/ **********/
/* load the diode structure with those pointers needed later /* load the diode structure with those pointers needed later
@ -222,6 +222,9 @@ DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
if(!model->DIOrecSatCurGiven) { if(!model->DIOrecSatCurGiven) {
model->DIOrecSatCur = 1e-14; model->DIOrecSatCur = 1e-14;
} }
if (!model->DIOsoftRevRecParamGiven) {
model->DIOsoftRevRecParam = 0.0;
}
/* set lower limit of saturation current */ /* set lower limit of saturation current */
if (model->DIOsatCur < ckt->CKTepsmin) if (model->DIOsatCur < ckt->CKTepsmin)
@ -412,6 +415,18 @@ DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
} }
} }
/* rev-rec */
if (model->DIOsoftRevRecParamGiven && model->DIOsoftRevRecParam!=0 && model->DIOtransitTime!=0) {
if(here->DIOqpNode == 0) {
error = CKTmkVolt(ckt, &tmp, here->DIOname, "qp");
if(error) return(error);
here->DIOqpNode = tmp->number;
}
} else {
here->DIOqpNode = 0;
}
int selfheat = ((here->DIOtempNode > 0) && (here->DIOthermal) && (model->DIOrth0Given)); int selfheat = ((here->DIOtempNode > 0) && (here->DIOthermal) && (model->DIOrth0Given));
/* macro to make elements with built in test for out of memory */ /* macro to make elements with built in test for out of memory */
@ -450,7 +465,15 @@ do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\
TSTALLOC(DIOposSwPrimeTempPtr, DIOposSwPrimeNode, DIOtempNode); TSTALLOC(DIOposSwPrimeTempPtr, DIOposSwPrimeNode, DIOtempNode);
} }
} }
/* rev-rec */
if (model->DIOsoftRevRecParamGiven && model->DIOsoftRevRecParam!=0 && model->DIOtransitTime!=0) {
TSTALLOC(DIOqpQpPtr , DIOqpNode, DIOqpNode);
TSTALLOC(DIOqpPosPrimePtr, DIOqpNode, DIOposPrimeNode);
TSTALLOC(DIOqpNegPtr , DIOqpNode, DIOnegNode);
TSTALLOC(DIOposPrimeQpPtr, DIOposPrimeNode, DIOqpNode);
TSTALLOC(DIOnegQpPtr, DIOnegNode, DIOqpNode);
}
} }
} }
return(OK); return(OK);
@ -474,7 +497,7 @@ DIOunsetup(
if (here->DIOposPrimeNode > 0 if (here->DIOposPrimeNode > 0
&& here->DIOposPrimeNode != here->DIOposNode) && here->DIOposPrimeNode != here->DIOposNode)
CKTdltNNum(ckt, here->DIOposPrimeNode); CKTdltNNum(ckt, here->DIOposPrimeNode);
here->DIOposPrimeNode = 0; here->DIOposPrimeNode = 0;
if(model->DIOresistSWGiven) { if(model->DIOresistSWGiven) {
/* separate sidewall */ /* separate sidewall */
@ -484,6 +507,11 @@ DIOunsetup(
here->DIOposSwPrimeNode = 0; here->DIOposSwPrimeNode = 0;
} }
/* rev-rec */
if (here->DIOqpNode > 0)
CKTdltNNum(ckt, here->DIOqpNode);
here->DIOqpNode = 0;
} }
} }
return OK; return OK;

View File

@ -22,6 +22,8 @@ DIOtrunc(GENmodel *inModel, CKTcircuit *ckt, double *timeStep)
for(here=DIOinstances(model);here!=NULL;here = DIOnextInstance(here)){ for(here=DIOinstances(model);here!=NULL;here = DIOnextInstance(here)){
CKTterr(here->DIOcapCharge,ckt,timeStep); CKTterr(here->DIOcapCharge,ckt,timeStep);
if (model->DIOresistSWGiven) CKTterr(here->DIOcapChargeSW,ckt,timeStep); if (model->DIOresistSWGiven) CKTterr(here->DIOcapChargeSW,ckt,timeStep);
if (model->DIOsoftRevRecParam!=0 && here->DIOtTransitTime!=0)
CKTterr(here->DIOsrcapCharge,ckt,timeStep);
} }
} }
return(OK); return(OK);

View File

@ -205,18 +205,18 @@ ISRCload(GENmodel *inModel, CKTcircuit *ckt)
case SFFM: { case SFFM: {
double VO, VA, FM, MDI, FC, TD, PHASEM, PHASEC; double VO, VA, FC, MDI, FM, TD, PHASEM, PHASEC;
double phasec; double phasec;
double phasem; double phasem;
static bool warn1 = FALSE, warn2 = FALSE; static bool warn1 = FALSE, warn2 = FALSE;
VO = here->ISRCcoeffs[0]; VO = here->ISRCcoeffs[0];
VA = here->ISRCcoeffs[1]; VA = here->ISRCcoeffs[1];
FM = here->ISRCfunctionOrder > 2 FC = here->ISRCfunctionOrder > 2
? here->ISRCcoeffs[2] : (5./ckt->CKTfinalTime); ? here->ISRCcoeffs[2] : (5./ckt->CKTfinalTime);
MDI = here->ISRCfunctionOrder > 3 MDI = here->ISRCfunctionOrder > 3
? here->ISRCcoeffs[3] : 90.0; ? here->ISRCcoeffs[3] : 90.0;
FC = here->ISRCfunctionOrder > 4 FM = here->ISRCfunctionOrder > 4
&& here->ISRCcoeffs[4] && here->ISRCcoeffs[4]
? here->ISRCcoeffs[4] : (500./ckt->CKTfinalTime); ? here->ISRCcoeffs[4] : (500./ckt->CKTfinalTime);
TD = here->ISRCfunctionOrder > 5 TD = here->ISRCfunctionOrder > 5

View File

@ -32,7 +32,7 @@ VDMOSconvTest(GENmodel *inModel, CKTcircuit *ckt)
here = VDMOSnextInstance(here)) { here = VDMOSnextInstance(here)) {
vgs = model->VDMOStype * ( vgs = model->VDMOStype * (
*(ckt->CKTrhs+here->VDMOSgNode) - *(ckt->CKTrhs+here->VDMOSgNodePrime) -
*(ckt->CKTrhs+here->VDMOSsNodePrime)); *(ckt->CKTrhs+here->VDMOSsNodePrime));
vds = model->VDMOStype * ( vds = model->VDMOStype * (
*(ckt->CKTrhs+here->VDMOSdNodePrime) - *(ckt->CKTrhs+here->VDMOSdNodePrime) -

View File

@ -32,7 +32,7 @@ VDMOSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt,
model->VDMOStype = NMOS; model->VDMOStype = NMOS;
if (!model->VDMOStransconductanceGiven) if (!model->VDMOStransconductanceGiven)
model->VDMOStransconductance = 25 + 10 * model->VDMOStype; /* IRF540, 9540 */ model->VDMOStransconductance = 15 + 5 * model->VDMOStype; /* IRF540, 9540 */
if (!model->VDMOSvth0Given) if (!model->VDMOSvth0Given)
model->VDMOSvth0 = 3 * model->VDMOStype; /* IRF540, 9540 */ model->VDMOSvth0 = 3 * model->VDMOStype; /* IRF540, 9540 */
@ -128,7 +128,7 @@ VDMOSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt,
model->VDMOSrthjc = 1.0; model->VDMOSrthjc = 1.0;
if (!model->VDMOSrthcaGiven) if (!model->VDMOSrthcaGiven)
model->VDMOSrthca = 1000; model->VDMOSrthca = 23; /* e.g. TO220 case */
if (!model->VDMOScthjGiven) if (!model->VDMOScthjGiven)
model->VDMOScthj = 10e-06; model->VDMOScthj = 10e-06;

View File

@ -47,7 +47,7 @@ void VDMOStempUpdate(VDMOSmodel *inModel, VDMOSinstance *here, double Temp, CKTc
here->VDMOStTransconductance = model->VDMOStransconductance here->VDMOStTransconductance = model->VDMOStransconductance
* here->VDMOSm * pow(ratio, model->VDMOSmu); * here->VDMOSm * pow(ratio, model->VDMOSmu);
here->VDMOStVth = model->VDMOSvth0 - model->VDMOStype * model->VDMOStcvth * dt; here->VDMOStVth = model->VDMOSvth0 + model->VDMOStcvth * dt;
here->VDMOStksubthres = model->VDMOSksubthres * (1.0 + (model->VDMOStksubthres1 * dt) + (model->VDMOStksubthres2 * dt * dt)); here->VDMOStksubthres = model->VDMOSksubthres * (1.0 + (model->VDMOStksubthres1 * dt) + (model->VDMOStksubthres2 * dt * dt));

View File

@ -56,20 +56,24 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
double phase; double phase;
double deltat; double deltat;
/* TR negative or 0 --> TR = ckt->CKTstep
TF negative or 0 --> TF = ckt->CKTstep
PW < 0 --> PW = 0
PER <= 0 --> PER = TR + TF + PW */
TD = here->VSRCfunctionOrder > 2 TD = here->VSRCfunctionOrder > 2
? here->VSRCcoeffs[2] : 0.0; ? here->VSRCcoeffs[2] : 0.0;
TR = here->VSRCfunctionOrder > 3 TR = here->VSRCfunctionOrder > 3
&& here->VSRCcoeffs[3] != 0.0 && here->VSRCcoeffs[3] > 0.0
? here->VSRCcoeffs[3] : ckt->CKTstep; ? here->VSRCcoeffs[3] : ckt->CKTstep;
TF = here->VSRCfunctionOrder > 4 TF = here->VSRCfunctionOrder > 4
&& here->VSRCcoeffs[4] != 0.0 && here->VSRCcoeffs[4] > 0.0
? here->VSRCcoeffs[4] : ckt->CKTstep; ? here->VSRCcoeffs[4] : ckt->CKTstep;
PW = here->VSRCfunctionOrder > 5 PW = here->VSRCfunctionOrder > 5
&& here->VSRCcoeffs[5] >= 0.0 && here->VSRCcoeffs[5] >= 0.0
? here->VSRCcoeffs[5] : ckt->CKTfinalTime; ? here->VSRCcoeffs[5] : 0.0;
PER = here->VSRCfunctionOrder > 6 PER = here->VSRCfunctionOrder > 6
&& here->VSRCcoeffs[6] != 0.0 && here->VSRCcoeffs[6] > 0.0
? here->VSRCcoeffs[6] : ckt->CKTfinalTime; ? here->VSRCcoeffs[6] : TR + TF + PW;
PHASE = here->VSRCfunctionOrder > 7 PHASE = here->VSRCfunctionOrder > 7
? here->VSRCcoeffs[7] : 0.0; ? here->VSRCcoeffs[7] : 0.0;

View File

@ -86,7 +86,7 @@ VSRCload(GENmodel *inModel, CKTcircuit *ckt)
} else { } else {
time = ckt->CKTtime; time = ckt->CKTtime;
} }
/* use the transient functions */ /* use the transient functions. */
switch(here->VSRCfunctionType) { switch(here->VSRCfunctionType) {
default: default:
@ -94,6 +94,12 @@ VSRCload(GENmodel *inModel, CKTcircuit *ckt)
break; break;
case PULSE: { case PULSE: {
/* Parameter limits :
TR negative or 0 --> TR = ckt->CKTstep
TF negative or 0 --> TF = ckt->CKTstep
PW < 0 --> PW = 0
PER <= 0 --> PER = TR + TF + PW
*/
double V1, V2, TD, TR, TF, PW, PER; double V1, V2, TD, TR, TF, PW, PER;
double basetime = 0; double basetime = 0;
double PHASE; double PHASE;
@ -106,17 +112,17 @@ VSRCload(GENmodel *inModel, CKTcircuit *ckt)
TD = here->VSRCfunctionOrder > 2 TD = here->VSRCfunctionOrder > 2
? here->VSRCcoeffs[2] : 0.0; ? here->VSRCcoeffs[2] : 0.0;
TR = here->VSRCfunctionOrder > 3 TR = here->VSRCfunctionOrder > 3
&& here->VSRCcoeffs[3] != 0.0 && here->VSRCcoeffs[3] > 0.0
? here->VSRCcoeffs[3] : ckt->CKTstep; ? here->VSRCcoeffs[3] : ckt->CKTstep;
TF = here->VSRCfunctionOrder > 4 TF = here->VSRCfunctionOrder > 4
&& here->VSRCcoeffs[4] != 0.0 && here->VSRCcoeffs[4] > 0.0
? here->VSRCcoeffs[4] : ckt->CKTstep; ? here->VSRCcoeffs[4] : ckt->CKTstep;
PW = here->VSRCfunctionOrder > 5 PW = here->VSRCfunctionOrder > 5
&& here->VSRCcoeffs[5] >= 0.0 && here->VSRCcoeffs[5] >= 0.0
? here->VSRCcoeffs[5] : ckt->CKTfinalTime; ? here->VSRCcoeffs[5] : 0.0;
PER = here->VSRCfunctionOrder > 6 PER = here->VSRCfunctionOrder > 6
&& here->VSRCcoeffs[6] != 0.0 && here->VSRCcoeffs[6] > 0.0
? here->VSRCcoeffs[6] : ckt->CKTfinalTime; ? here->VSRCcoeffs[6] : TR + TF + PW;
/* shift time by delay time TD */ /* shift time by delay time TD */
time -= TD; time -= TD;
@ -227,18 +233,18 @@ VSRCload(GENmodel *inModel, CKTcircuit *ckt)
case SFFM: { case SFFM: {
double VO, VA, FM, MDI, FC, TD, PHASEM, PHASEC; double VO, VA, FC, MDI, FM, TD, PHASEM, PHASEC;
double phasec; double phasec;
double phasem; double phasem;
static bool warn1 = FALSE, warn2 = FALSE; static bool warn1 = FALSE, warn2 = FALSE;
VO = here->VSRCcoeffs[0]; VO = here->VSRCcoeffs[0];
VA = here->VSRCcoeffs[1]; VA = here->VSRCcoeffs[1];
FM = here->VSRCfunctionOrder > 2 FC = here->VSRCfunctionOrder > 2
? here->VSRCcoeffs[2] : (5./ckt->CKTfinalTime); ? here->VSRCcoeffs[2] : (5./ckt->CKTfinalTime);
MDI = here->VSRCfunctionOrder > 3 MDI = here->VSRCfunctionOrder > 3
? here->VSRCcoeffs[3] : 90.0; /* 0.9 * FC / FM */ ? here->VSRCcoeffs[3] : 90.0; /* 0.9 * FC / FM */
FC = here->VSRCfunctionOrder > 4 FM = here->VSRCfunctionOrder > 4
&& here->VSRCcoeffs[4] /* test if not 0 */ && here->VSRCcoeffs[4] /* test if not 0 */
? here->VSRCcoeffs[4] : (500./ckt->CKTfinalTime); ? here->VSRCcoeffs[4] : (500./ckt->CKTfinalTime);
TD = here->VSRCfunctionOrder > 5 TD = here->VSRCfunctionOrder > 5

View File

@ -71,7 +71,10 @@ void INP2N(CKTcircuit *ckt, INPtables *tab, struct card *current) {
if (i >= 2) { if (i >= 2) {
c = INPgetMod(ckt, token, &thismodel, tab); c = INPgetMod(ckt, token, &thismodel, tab);
if (c) { /* check if using model binning -- pass in line since need 'l' and 'w' */
if (!thismodel)
txfree(INPgetModBin(ckt, token, &thismodel, tab, line));
if (c && !thismodel) {
LITERR(c); LITERR(c);
tfree(c); tfree(c);
tfree(token); tfree(token);

View File

@ -67,10 +67,14 @@ INPdoOpts(
} }
continue; continue;
} }
/* print err message only if it is not just a number */
errmsg = TMALLOC(char, 100); char* ctoken = token;
(void) strcpy(errmsg," Error: unknown option - ignored\n"); while (*ctoken && strchr("0123456789.e+-", *ctoken))
optCard->error = INPerrCat(optCard->error,errmsg); ctoken++;
fprintf(stderr, "%s\n", optCard->error); if (*ctoken) {
errmsg = tprintf("Error: unknown option %s - ignored\n", token);
optCard->error = INPerrCat(optCard->error, errmsg);
fprintf(stderr, "%s\n", optCard->error);
}
} }
} }

View File

@ -72,7 +72,7 @@ INPdevParse(char **line, CKTcircuit *ckt, int dev, GENinstance *fast,
errbuf = copy(" unknown parameter ($). Check the compatibility flag!\n"); errbuf = copy(" unknown parameter ($). Check the compatibility flag!\n");
} }
else { else {
errbuf = tprintf(" unknown parameter (%s) \n", parameter); errbuf = tprintf(" unknown instance parameter (%s) \n", parameter);
} }
rtn = errbuf; rtn = errbuf;
goto quit; goto quit;

View File

@ -1499,7 +1499,7 @@ win_x_fprintf(FILE *stream, const char *format, ...)
if ((stream == stdout) || (stream == stderr)) { if ((stream == stdout) || (stream == stderr)) {
s[0] = SE; s[0] = SE;
result = vsprintf(s, format, args); result = vsnprintf(s, IOBufSize, format, args);
win_x_fputs(s, stream); win_x_fputs(s, stream);
} else } else
result = vfprintf(stream, format, args); result = vfprintf(stream, format, args);

View File

@ -117,10 +117,8 @@ ENHtranslate_poly(
l1->nextcard = l2; l1->nextcard = l2;
d->nextcard = l1; d->nextcard = l1;
/* PN 2004: Add original linenumber to ease the debug process /* Add original linenumber to ease the debug process
* for malfromned netlist * for malformed netlist */
*/
l1->linenum = d->linenum; l1->linenum = d->linenum;
l2->linenum = d->linenum; l2->linenum = d->linenum;
@ -301,7 +299,7 @@ static char *two2three_translate(
char **out_conn; char **out_conn;
char **in_conn; char **in_conn;
char **coef; char **coef;
char* multibeg, *multiend, *multi = NULL;
char *card; char *card;
@ -313,6 +311,20 @@ static char *two2three_translate(
/* Put the first character into local storage for checking type */ /* Put the first character into local storage for checking type */
type = *orig_card; type = *orig_card;
/* There may be a multiplier m=val
Remove it here, add it later */
multibeg = strstr(orig_card, " m=");
if (multibeg) {
multiend = multibeg + 3;
while (*multiend == ' ')
multiend++;
while (*multiend && *multiend != ' ')
multiend++;
multi = copy_substring(multibeg, multiend);
while (multibeg < multiend)
*(multibeg++) = ' ';
}
/* Count the number of tokens for use in parsing */ /* Count the number of tokens for use in parsing */
num_tokens = count_tokens(orig_card); num_tokens = count_tokens(orig_card);
@ -356,8 +368,8 @@ static char *two2three_translate(
if(num_coefs < 1) { if(num_coefs < 1) {
char *errmsg; char *errmsg;
printf("ERROR - Number of connections differs from poly dimension\n"); fprintf(stderr, "ERROR - Number of connections differs from poly dimension\n");
printf("ERROR while parsing: %s\n", orig_card); fprintf(stderr, " while parsing: %s\n", orig_card);
errmsg = copy("ERROR in two2three_translate -- Argument to poly() is not an integer\n"); errmsg = copy("ERROR in two2three_translate -- Argument to poly() is not an integer\n");
*inst_card = copy("* ERROR - Number of connections differs from poly dimension\n"); *inst_card = copy("* ERROR - Number of connections differs from poly dimension\n");
*mod_card = copy(" * ERROR - Number of connections differs from poly dimension\n"); *mod_card = copy(" * ERROR - Number of connections differs from poly dimension\n");
@ -414,6 +426,9 @@ static char *two2three_translate(
for(i = 0; i < num_coefs; i++) for(i = 0; i < num_coefs; i++)
mod_card_len += strlen(coef[i]) + 1; mod_card_len += strlen(coef[i]) + 1;
if (multi && (type == 'g' || type == 'G' || type == 'f'|| type == 'F'))
mod_card_len += strlen(multi) + 1;
/* Allocate space for the cards and write them into the strings */ /* Allocate space for the cards and write them into the strings */
*inst_card = TMALLOC(char, inst_card_len); *inst_card = TMALLOC(char, inst_card_len);
@ -460,6 +475,17 @@ static char *two2three_translate(
sprintf(*mod_card + strlen(*mod_card), "%s ", coef[i]); sprintf(*mod_card + strlen(*mod_card), "%s ", coef[i]);
sprintf(*mod_card + strlen(*mod_card), "]"); sprintf(*mod_card + strlen(*mod_card), "]");
if (multi && (type == 'g' || type == 'G' || type == 'f' || type == 'F')) {
sprintf(*mod_card + strlen(*mod_card), " %s", multi);
tfree(multi);
}
if (multi && (type == 'e' || type == 'E' || type == 'h' || type == 'H')) {
fprintf(stderr, "Warning: multiplier m not available for E and H poly sources, ignored as\n"
" %s\n", orig_card);
tfree(multi);
}
#ifdef TRACE #ifdef TRACE
/* SDB debug statement */ /* SDB debug statement */
printf("In two2three_translate, translated statements:\n%s \n%s \n", *inst_card, *mod_card); printf("In two2three_translate, translated statements:\n%s \n%s \n", *inst_card, *mod_card);

View File

@ -47,7 +47,7 @@ required syntax.
This model may also be called directly as follows: This model may also be called directly as follows:
a1 [ <input(s)> ] <output> xxx a1 [ <input(s)> ] <output> xxx
.model xxx spice2poly ( coef = [ <list of 2G6 compatible coefficients> ] ) .model xxx spice2poly ( coef = [ <list of 2G6 compatible coefficients> ] [m = val] )
Refer to the 2G6 User Guide for an explanation of the coefficients. Refer to the 2G6 User Guide for an explanation of the coefficients.
@ -102,12 +102,14 @@ void spice2poly (ARGS)
double sum; /* Temporary for accumulating sum of terms */ double sum; /* Temporary for accumulating sum of terms */
double product; /* Temporary for accumulating product */ double product; /* Temporary for accumulating product */
double mult; /* multplicator for G and F sources */
/* Get number of input values */ /* Get number of input values */
num_inputs = PORT_SIZE(in); num_inputs = PORT_SIZE(in);
mult = PARAM(m);
/* If this is the first call to the model, allocate the static variable */ /* If this is the first call to the model, allocate the static variable */
/* array */ /* array */
@ -165,7 +167,7 @@ void spice2poly (ARGS)
/* Add the product times the appropriate coefficient into the sum */ /* Add the product times the appropriate coefficient into the sum */
sum += coef[i] * product; sum += coef[i] * product;
} }
OUTPUT(out) = sum; OUTPUT(out) = sum * mult;
/* Compute and output the partials for each input */ /* Compute and output the partials for each input */
@ -201,13 +203,13 @@ void spice2poly (ARGS)
sum += coef[j] * product; sum += coef[j] * product;
} }
PARTIAL(out,in[i]) = sum; PARTIAL(out,in[i]) = sum * mult;
/* If this is DC analysis, save the partial for use as AC gain */ /* If this is DC analysis, save the partial for use as AC gain */
/* value in an AC analysis */ /* value in an AC analysis */
if(ANALYSIS == MIF_DC) if(ANALYSIS == MIF_DC)
STATIC_VAR(acgains[i]) = sum; STATIC_VAR(acgains[i]) = sum * mult;
} }
/* Free the allocated items and return */ /* Free the allocated items and return */

View File

@ -16,7 +16,8 @@ AUTHORS
MODIFICATIONS MODIFICATIONS
<date> <person name> <nature of modifications> 11/05/2025 Holger Vogt
new parameter m (multiplicator)
SUMMARY SUMMARY
@ -67,6 +68,17 @@ Vector: yes
Vector_Bounds: [2 -] Vector_Bounds: [2 -]
Null_Allowed: no Null_Allowed: no
PARAMETER_TABLE:
Parameter_Name: m
Description: "multiplicator"
Data_Type: real
Default_Value: 1
Limits: -
Vector: no
Vector_Bounds: -
Null_Allowed: yes
STATIC_VAR_TABLE: STATIC_VAR_TABLE:

View File

@ -210,6 +210,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\..\src\xspice\icm\spice2poly\icm_spice2poly\cfunc.mod" /> <None Include="..\..\src\xspice\icm\spice2poly\icm_spice2poly\cfunc.mod" />
<None Include="..\..\src\xspice\icm\spice2poly\icm_spice2poly\ifspec.ifs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\src\include\ngspice\dstring.h" /> <ClInclude Include="..\..\src\include\ngspice\dstring.h" />