Merge branch 'pre-master-46' into bt_dev
This commit is contained in:
commit
a044a43dd4
|
|
@ -51,6 +51,7 @@ let newstime = stime/1.4
|
|||
let deltime = newstime/100
|
||||
alter @V1[sin] [ 0 $&vmax $&newfreq ]
|
||||
tran $&deltime $&newstime uic
|
||||
set xbrushwidth=2
|
||||
* the 'programming' currents
|
||||
plot tran1.alli tran2.alli alli title 'Memristor with threshold: Internal Programming currents'
|
||||
* resistance versus time plot
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ let newstime = stime/1.4
|
|||
let deltime = newstime/100
|
||||
alter @V1[sin] [ 0 $&vmax $&newfreq ]
|
||||
tran $&deltime $&newstime uic
|
||||
set xbrushwidth=2
|
||||
* the resistor currents
|
||||
plot tran1.alli tran2.alli alli title 'Memristor with threshold: currents'
|
||||
* calculate resistance (avoid dividing by zero)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -1,10 +1,5 @@
|
|||
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
|
||||
Just a check with three different OpAmps
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -27,7 +27,7 @@ R2 2 3 {value*(1-ratio)+ 1m}
|
|||
+ 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
|
||||
+ tcvth=-0.0065 MU=-1.27 texp0=1.5
|
||||
+ Rthjc=0.4 Cthj=0.1
|
||||
+ mtriode=0.8
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
+ 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
|
||||
+ tcvth=-0.0065 MU=-1.27 texp0=1.5
|
||||
+ Rthjc=0.4 Cthj=0.1
|
||||
+ mtriode=0.8
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ cout buf ss 1pF
|
|||
|
||||
* this is needed
|
||||
.option reltol=1e-4
|
||||
.option ltereltol=1e-4
|
||||
|
||||
.tran 0.2n 16n
|
||||
.print tran v(out25) v(out50)
|
||||
|
|
@ -48,6 +49,7 @@ if $?batchmode
|
|||
else
|
||||
save out25 out50
|
||||
run
|
||||
rusage time
|
||||
plot out25 out50
|
||||
let lin-tstart = 4n $ skip the start-up phase
|
||||
let lin-tstop = 14n $ end earlier(just for demonstration)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -35,7 +35,7 @@ Xtr3 1 0 22 0 tr3
|
|||
.ends
|
||||
|
||||
* 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
|
||||
* mcx nodes of magnetic circuit
|
||||
.subckt tr2 p1 p2 s1 s2
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ plot inoise_spectrum
|
|||
+ 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
|
||||
+ tcvth=-0.0065 MU=-1.27 texp0=1.5
|
||||
+ Rthjc=0.4 Cthj=5e-3
|
||||
+ mtriode=0.8
|
||||
.model IRFP9240 VDMOS pchan
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ end
|
|||
+ 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
|
||||
+ tcvth=-0.0065 MU=-1.27 texp0=1.5
|
||||
*+ Rthjc=0.4 Cthj=5e-3
|
||||
+ mtriode=0.8
|
||||
.model IRFP9240 VDMOS pchan
|
||||
|
|
|
|||
|
|
@ -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
|
||||
+ 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
|
||||
+ tcvth=-0.0065 MU=-1.27 texp0=1.5
|
||||
*+ Rthjc=0.4 Cthj=5e-3
|
||||
+ mtriode=0.8
|
||||
.model IRFP9240 VDMOS pchan
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ V4 out2 0 0.0
|
|||
+ Cgdmax=.2n Cgdmin=.05n a=0.3 Cgs=.12n
|
||||
+ Is=17p N=1.1 Rb=80m XTI=3
|
||||
+ 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)
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ VD D 0 2V
|
|||
+ 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
|
||||
+ tcvth=-0.0065 MU=-1.27 texp0=1.5
|
||||
+ Rthjc=0.02 Cthj=1e-3 Rthca=1000
|
||||
+ mtriode=0.8
|
||||
.control
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ VDMOS SOA check
|
|||
+ 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 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
|
||||
+ Vgs_max=20 Vgd_max=20 Vds_max=200
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ bin_PROGRAMS = ngspice
|
|||
|
||||
if OLDAPPS
|
||||
if !WINGUI
|
||||
bin_PROGRAMS += ngnutmeg ngsconvert ngproc2mod ngmultidec ngmakeidx
|
||||
bin_PROGRAMS += ngsconvert ngproc2mod ngmultidec ngmakeidx
|
||||
helpdatadir = $(pkgdatadir)/helpdir
|
||||
helpdata_DATA = ngspice.txt ngspice.idx
|
||||
if !NO_HELP
|
||||
|
|
@ -220,50 +220,11 @@ endif
|
|||
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --tag=RC --mode=compile $(RC) $(RCFLAGS) $< -o $@
|
||||
|
||||
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
|
||||
if !WINGUI
|
||||
if !SHWIN
|
||||
|
||||
if !NO_X
|
||||
ngnutmeg_LDADD += \
|
||||
frontend/help/libhlp.la
|
||||
endif !NO_X
|
||||
|
||||
## help:
|
||||
|
||||
nghelp_SOURCES = conf.c nghelp.c
|
||||
|
|
|
|||
|
|
@ -517,7 +517,7 @@ ft_bpcheck(struct plot *runplot, int iteration)
|
|||
|
||||
if ((howmanysteps > 0) && (--howmanysteps == 0)) {
|
||||
if (steps > 1)
|
||||
fprintf(cp_err, "Stopped after %d steps.\n", steps);
|
||||
fprintf(cp_out, "Note: Stopped after %d steps.\n", steps);
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ if (wl && wl->wl_word)
|
|||
if (load_opus(wl->wl_word)) {
|
||||
fprintf(stderr, "Error: Library %s couldn't be loaded!\n", wl->wl_word);
|
||||
ft_spiniterror = TRUE;
|
||||
ft_codemodelerror = TRUE;
|
||||
if (ft_stricterror) /* if set in spinit */
|
||||
controlled_exit(EXIT_BAD);
|
||||
}
|
||||
|
|
@ -34,6 +35,7 @@ void com_osdi(wordlist *wl)
|
|||
if (load_osdi(ww->wl_word)) {
|
||||
fprintf(cp_err, "Error: Library %s couldn't be loaded!\n", ww->wl_word);
|
||||
ft_spiniterror = TRUE;
|
||||
ft_osdierror = TRUE;
|
||||
if (ft_stricterror)
|
||||
controlled_exit(EXIT_BAD);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,11 +58,19 @@ com_fft(wordlist *wl)
|
|||
}
|
||||
|
||||
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;
|
||||
span = time[length-1] - time[0];
|
||||
span = time[length-1] - time[0] + time[length-1] - time[length-2];
|
||||
|
||||
#ifdef HAVE_LIBFFTW3
|
||||
fpts = length/2 + 1;
|
||||
scale = ((double)length)/2.0;
|
||||
#else
|
||||
/* size of fft input vector is power of two and larger or equal than spice vector */
|
||||
N = 1;
|
||||
|
|
@ -72,6 +80,7 @@ com_fft(wordlist *wl)
|
|||
M++;
|
||||
}
|
||||
fpts = N/2 + 1;
|
||||
scale = ((double)N)/2;
|
||||
#endif
|
||||
|
||||
win = TMALLOC(double, length);
|
||||
|
|
@ -84,7 +93,7 @@ com_fft(wordlist *wl)
|
|||
order = 2;
|
||||
|
||||
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);
|
||||
vlist = NULL;
|
||||
|
|
@ -178,14 +187,16 @@ com_fft(wordlist *wl)
|
|||
|
||||
fftw_execute(plan_forward);
|
||||
|
||||
scale = (double) fpts - 1.0;
|
||||
fdvec[i][0].cx_real = out[0][0]/scale/2.0;
|
||||
fdvec[i][0].cx_imag = 0.0;
|
||||
for (j = 1; j < fpts; j++) {
|
||||
fdvec[i][j].cx_real = out[j][0]/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);
|
||||
|
|
@ -212,7 +223,6 @@ com_fft(wordlist *wl)
|
|||
rffts(in, M, 1);
|
||||
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]). */
|
||||
fdvec[i][0].cx_real = in[0]/scale/2.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_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;
|
||||
|
||||
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_imag = 0;
|
||||
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_imag = 0;
|
||||
noipower += fdvec[i][j].cx_real;
|
||||
if (!finite(noipower))
|
||||
break;
|
||||
}
|
||||
fdvec[i][fpts-1].cx_real = out[fpts-1][0]*out[fpts-1][0]/intres;
|
||||
fdvec[i][fpts-1].cx_imag = 0;
|
||||
if (length % 2 == 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;
|
||||
|
||||
#else /* Green's FFT */
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
#include "com_measure2.h"
|
||||
#include "breakp2.h"
|
||||
|
||||
int measure_precision = -1;
|
||||
|
||||
typedef enum {
|
||||
MEASUREMENT_OK = 0,
|
||||
MEASUREMENT_FAILURE = 1
|
||||
|
|
@ -86,6 +88,9 @@ measure_get_precision(void)
|
|||
if ((env_ptr = getenv("NGSPICE_MEAS_PRECISION")) != NULL)
|
||||
precision = atoi(env_ptr);
|
||||
|
||||
if (measure_precision > 0)
|
||||
precision = measure_precision;
|
||||
|
||||
return precision;
|
||||
}
|
||||
|
||||
|
|
@ -439,8 +444,13 @@ com_measure_when(
|
|||
sp_check = TRUE;
|
||||
else if (cieq (meas->m_analysis, "dc"))
|
||||
dc_check = TRUE;
|
||||
else
|
||||
else {
|
||||
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++) {
|
||||
|
||||
|
|
@ -697,8 +707,13 @@ measure_at(
|
|||
sp_check = TRUE;
|
||||
else if (cieq (meas->m_analysis, "dc"))
|
||||
dc_check = TRUE;
|
||||
else
|
||||
else {
|
||||
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++) {
|
||||
if (ac_check) {
|
||||
|
|
@ -1800,9 +1815,13 @@ get_measure2(
|
|||
|
||||
// print results
|
||||
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
|
||||
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);
|
||||
|
||||
|
|
@ -1873,9 +1892,9 @@ err_ret1:
|
|||
|
||||
// print results
|
||||
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
|
||||
fprintf(mout,"%-20s= %e\n", mName, meas->m_measured);
|
||||
fprintf(mout,"%-20s= %.*e\n", mName, precision, meas->m_measured);
|
||||
|
||||
*result = meas->m_measured;
|
||||
|
||||
|
|
@ -1914,7 +1933,7 @@ err_ret2:
|
|||
if (out_line)
|
||||
sprintf(out_line, "%-20s= %.*e\n", mName, precision, meas->m_measured);
|
||||
else
|
||||
fprintf(mout, "%-20s= %e\n", mName, meas->m_measured);
|
||||
fprintf(mout, "%-20s= %.*e\n", mName, precision, meas->m_measured);
|
||||
|
||||
*result = meas->m_measured;
|
||||
|
||||
|
|
@ -2002,9 +2021,11 @@ err_ret4:
|
|||
|
||||
// print results
|
||||
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
|
||||
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;
|
||||
|
||||
|
|
@ -2049,17 +2070,21 @@ err_ret5:
|
|||
if ((mFunctionType == AT_MIN) || (mFunctionType == AT_MAX)) {
|
||||
// print results
|
||||
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
|
||||
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;
|
||||
} else {
|
||||
// print results
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
|
@ -2107,9 +2132,11 @@ err_ret6:
|
|||
|
||||
// print results
|
||||
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
|
||||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
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,
|
||||
int *newlength, short int *newtype,
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
|
|||
|
||||
|
||||
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 *nPhase);
|
||||
|
||||
|
|
@ -32,8 +32,8 @@ static int CKTfour(int ndata, int numFreq, double *thd, double *Time, double *Va
|
|||
#define DEF_FOURGRIDSIZE 200
|
||||
|
||||
|
||||
/* CKTfour(ndata, numFreq, thd, Time, Value, FundFreq, Freq, Mag, Phase, nMag, nPhase)
|
||||
* len 10 ? inp inp inp out out out out out
|
||||
/* CKTfour(ndata, numFreq, numPeriod, thd, Time, Value, FundFreq, Freq, Mag, Phase, nMag, nPhase)
|
||||
* len 10 1 ? inp inp inp out out out out out
|
||||
*/
|
||||
|
||||
int
|
||||
|
|
@ -42,7 +42,7 @@ fourier(wordlist *wl, struct plot *current_plot)
|
|||
struct dvec *time, *vec;
|
||||
struct pnode *pn, *names;
|
||||
double fundfreq, *data = NULL;
|
||||
int nfreqs, fourgridsize, polydegree;
|
||||
int nfreqs, nperiods, fourgridsize, polydegree;
|
||||
double *freq, *mag, *phase, *nmag, *nphase; /* Outputs from CKTfour */
|
||||
double thd, *timescale = NULL;
|
||||
char *s;
|
||||
|
|
@ -68,6 +68,8 @@ fourier(wordlist *wl, struct plot *current_plot)
|
|||
|
||||
if (!cp_getvar("nfreqs", CP_NUM, &nfreqs, 0) || nfreqs < 1)
|
||||
nfreqs = 10;
|
||||
if (!cp_getvar("nperiods", CP_NUM, &nperiods, 0) || nperiods < 1)
|
||||
nperiods = 1;
|
||||
if (!cp_getvar("polydegree", CP_NUM, &polydegree, 0) || polydegree < 0)
|
||||
polydegree = 1;
|
||||
if (!cp_getvar("fourgridsize", CP_NUM, &fourgridsize, 0) || fourgridsize < 1)
|
||||
|
|
@ -112,14 +114,16 @@ fourier(wordlist *wl, struct plot *current_plot)
|
|||
|
||||
if (polydegree) {
|
||||
double *dp, d;
|
||||
/* Get fourgridsize points per period */
|
||||
fourgridsize = fourgridsize * nperiods;
|
||||
/* Build the grid... */
|
||||
timescale = TMALLOC(double, fourgridsize);
|
||||
data = TMALLOC(double, fourgridsize);
|
||||
dp = ft_minmax(time, TRUE);
|
||||
/* Now get the last fund freq... */
|
||||
d = 1 / fundfreq; /* The wavelength... */
|
||||
d = nperiods / fundfreq; /* The wavelength... */
|
||||
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;
|
||||
} else if (dp[1] - dp[0] > d) {
|
||||
dp[0] = dp[1] - d;
|
||||
|
|
@ -143,7 +147,7 @@ fourier(wordlist *wl, struct plot *current_plot)
|
|||
timescale = time->v_realdata;
|
||||
}
|
||||
|
||||
err = CKTfour(fourgridsize, nfreqs, &thd, timescale,
|
||||
err = CKTfour(fourgridsize, nfreqs, nperiods, &thd, timescale,
|
||||
data, fundfreq, freq, mag, phase, nmag,
|
||||
nphase);
|
||||
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,
|
||||
" 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,
|
||||
polydegree);
|
||||
polydegree, nperiods);
|
||||
/* Each field will have width cp_numdgt + 6 (or 7
|
||||
* 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
|
||||
Value arrays */
|
||||
int numFreq, /* number of harmonics to calculate */
|
||||
int numPeriod, /* number of periods for detection */
|
||||
double *thd, /* total harmonic distortion (percent)
|
||||
to be returned */
|
||||
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 Time and Value array must be reasonably distributed over at
|
||||
* least one full period of the fundamental Frequency for the
|
||||
* fourier transform to be useful. The function will take the
|
||||
* last period of the frequency as data for the transform.
|
||||
* fourier transform to be useful. The function will take
|
||||
* 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. */
|
||||
int i;
|
||||
int j;
|
||||
|
|
@ -331,10 +337,10 @@ CKTfour(int ndata, /* number of entries in the Time and
|
|||
Phase[i] = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < ndata; i++)
|
||||
for (i = 0; i < ndata ; i++)
|
||||
for (j = 0; j < numFreq; j++) {
|
||||
Mag[j] += Value[i] * sin(j*2.0*M_PI*i/((double)ndata));
|
||||
Phase[j] += Value[i] * cos(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*numPeriod*i/((double)ndata));
|
||||
}
|
||||
|
||||
Mag[0] = Phase[0]/ndata;
|
||||
|
|
|
|||
|
|
@ -247,6 +247,10 @@ void inp_probe(struct card* deck)
|
|||
if (strchr("ehvk", *instname))
|
||||
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.
|
||||
digital nodes should not get V sources in series anyway.) */
|
||||
if ('a' == *instname)
|
||||
|
|
|
|||
|
|
@ -1105,6 +1105,16 @@ struct card *inp_readall(FILE *fp, const char *dir_name, const char* file_name,
|
|||
if (newcompat.ps && newcompat.a)
|
||||
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);
|
||||
|
||||
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 */
|
||||
|
||||
bool found_end = FALSE, shell_eol_continuation = FALSE;
|
||||
static bool biaswarn = FALSE;
|
||||
static bool hdlwarn = FALSE;
|
||||
#ifdef CIDER
|
||||
static int in_cider_model = 0;
|
||||
#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);
|
||||
}
|
||||
|
||||
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 */
|
||||
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
|
||||
/* no lower case letters for lines beginning with: */
|
||||
else if (!ciprefix("write", buffer) &&
|
||||
!ciprefix("wrdata", buffer) &&
|
||||
!ciprefix(".lib", buffer) && !ciprefix(".inc", buffer) &&
|
||||
!ciprefix("codemodel", buffer) &&
|
||||
!ciprefix("osdi", buffer) &&
|
||||
!ciprefix("pre_osdi", buffer) &&
|
||||
!ciprefix("echo", buffer) && !ciprefix("shell", buffer) &&
|
||||
!ciprefix("source", buffer) && !ciprefix("cd ", buffer) &&
|
||||
!ciprefix("load", buffer) && !ciprefix("setcs", buffer)) {
|
||||
else if (!(ciprefix(".lib", buffer) || ciprefix(".inc", buffer) ||
|
||||
((comfile || is_control) && (
|
||||
ciprefix("write", buffer) ||
|
||||
ciprefix("wrdata", buffer) ||
|
||||
ciprefix("codemodel", buffer) ||
|
||||
ciprefix("osdi", buffer) ||
|
||||
ciprefix("pre_osdi", buffer) ||
|
||||
ciprefix("echo", buffer) || ciprefix("shell", buffer) ||
|
||||
ciprefix("source", buffer) ||ciprefix("cd", buffer) ||
|
||||
ciprefix("load", buffer) || ciprefix("setcs", buffer))))) {
|
||||
/* lower case for all other lines */
|
||||
for (s = buffer; *s && (*s != '\n'); 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++)
|
||||
;
|
||||
}
|
||||
/* lower case for variables or vectors in command 'echo' */
|
||||
if (ciprefix("echo", buffer)) {
|
||||
char* p = buffer, *tmpstr;
|
||||
while (p && *p != '\n' && *p != '\0') {
|
||||
p = nexttok(p);
|
||||
/* vectors or variables start with $ */
|
||||
if (p && *p == '$') {
|
||||
for (tmpstr = p; *tmpstr && !isspace_c(*tmpstr); tmpstr++)
|
||||
*tmpstr = tolower_c(*tmpstr);
|
||||
p = tmpstr;
|
||||
if (is_control) {
|
||||
/* lower case for variables or vectors in command 'echo' */
|
||||
if (ciprefix("echo", buffer)) {
|
||||
char* p = buffer, * tmpstr;
|
||||
while (p && *p != '\n' && *p != '\0') {
|
||||
p = nexttok(p);
|
||||
/* vectors or variables start with $ */
|
||||
if (p && *p == '$') {
|
||||
for (tmpstr = p; *tmpstr && !isspace_c(*tmpstr); tmpstr++)
|
||||
*tmpstr = tolower_c(*tmpstr);
|
||||
p = tmpstr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* add Inp_Path to buffer while keeping the sourcepath variable contents */
|
||||
if (ciprefix("set", buffer)) {
|
||||
char *p;
|
||||
/* add Inp_Path to buffer while keeping the sourcepath variable contents */
|
||||
if (ciprefix("set", buffer)) {
|
||||
char* p;
|
||||
|
||||
p = skip_ws(buffer + 3); // Next word
|
||||
if (strncmp(p, "sourcepath", 10) == 0 &&
|
||||
skip_non_ws(p) == p + 10) {
|
||||
p = strchr(buffer, ')');
|
||||
if (p) {
|
||||
*p = 0; // clear ) and insert Inp_Path in between
|
||||
p = tprintf("%s %s ) %s", buffer,
|
||||
p = skip_ws(buffer + 3); // Next word
|
||||
if (strncmp(p, "sourcepath", 10) == 0 &&
|
||||
skip_non_ws(p) == p + 10) {
|
||||
p = strchr(buffer, ')');
|
||||
if (p) {
|
||||
*p = 0; // clear ) and insert Inp_Path in between
|
||||
p = tprintf("%s %s ) %s", buffer,
|
||||
Inp_Path ? Inp_Path : "", p + 1);
|
||||
tfree(buffer);
|
||||
buffer = p;
|
||||
/* s points to end of buffer */
|
||||
for (s = buffer; *s && (*s != '\n'); s++)
|
||||
;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "Warning: no closing parens found in 'set sourcepath' statement\n");
|
||||
tfree(buffer);
|
||||
buffer = p;
|
||||
/* s points to end of buffer */
|
||||
for (s = buffer; *s && (*s != '\n'); s++)
|
||||
;
|
||||
}
|
||||
else {
|
||||
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;
|
||||
|
||||
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");
|
||||
else
|
||||
else {
|
||||
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) {
|
||||
/* process all library section references */
|
||||
|
|
@ -2295,12 +2332,20 @@ static char *readline(FILE *fd)
|
|||
|
||||
static void inp_fix_gnd_name(struct card *c)
|
||||
{
|
||||
bool found_subckt = FALSE;
|
||||
for (; c; c = c->nextcard) {
|
||||
|
||||
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 ((*gnd == '*') || !strstr(gnd, "gnd"))
|
||||
if (found_subckt || (*gnd == '*') || !strstr(gnd, "gnd"))
|
||||
continue;
|
||||
|
||||
// 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[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
|
||||
//
|
||||
// split line up into multiple lines and place those new lines immediately
|
||||
// after the current multi-param line in the deck
|
||||
|
||||
/* Iterate through deck and find lines with more than one parameter defined
|
||||
Split line up into multiple lines and place those new lines immediately
|
||||
after the current multi-param line in the deck */
|
||||
static int inp_split_multi_param_lines(struct card *card, int line_num)
|
||||
{
|
||||
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;
|
||||
|
||||
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);
|
||||
end_param = skip_ws(equal_ptr + 1);
|
||||
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)
|
||||
return;
|
||||
|
||||
if (newcompat.hs && cp_getvar("no_auto_braces", CP_BOOL, NULL, 0))
|
||||
return;
|
||||
|
||||
for (; c && c != end_c; c = c->nextcard) {
|
||||
|
||||
int i, j, num_terminals;
|
||||
|
|
|
|||
|
|
@ -28,7 +28,9 @@ com_linearize(wordlist *wl)
|
|||
struct dvec *newtime, *v;
|
||||
struct dvec *oldtime;
|
||||
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)) {
|
||||
fprintf(cp_err, "Error: plot must be a transient analysis\n");
|
||||
|
|
@ -98,7 +100,34 @@ com_linearize(wordlist *wl)
|
|||
plot_new(new);
|
||||
plot_setcur(new->pl_typename);
|
||||
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),
|
||||
oldtime->v_type,
|
||||
oldtime->v_flags | VF_PERMANENT,
|
||||
|
|
@ -109,12 +138,17 @@ com_linearize(wordlist *wl)
|
|||
newtime->v_realdata[i] = d;
|
||||
new->pl_scale = new->pl_dvecs = newtime;
|
||||
|
||||
if (wl) {
|
||||
if (wl && !nponly) {
|
||||
/* check for vectors given in the command line */
|
||||
while (wl) {
|
||||
if (ciprefix("np=", wl->wl_word)) {
|
||||
wl = wl->wl_next;
|
||||
continue;
|
||||
}
|
||||
v = vec_fromplot(wl->wl_word, old);
|
||||
if (!v) {
|
||||
fprintf(cp_err, "Error: no such vector %s\n",
|
||||
wl->wl_word);
|
||||
fprintf(cp_err, "Error: command 'linearize': no such vector %s\n",
|
||||
wl->wl_word);
|
||||
wl = wl->wl_next;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -122,6 +156,7 @@ com_linearize(wordlist *wl)
|
|||
wl = wl->wl_next;
|
||||
}
|
||||
} else {
|
||||
/* linearize all vectors of the current plot */
|
||||
for (v = old->pl_dvecs; v; v = v->v_next) {
|
||||
if (v == old->pl_scale)
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ char *ft_setkwords[] = {
|
|||
"lprplot5",
|
||||
"lprps",
|
||||
"maxwins",
|
||||
"measureprec",
|
||||
"modelcard",
|
||||
"modelline",
|
||||
"moremode",
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ typedef struct { /* the input scanner data structure */
|
|||
char *dyncategory;
|
||||
int hs_compatibility; /* allow extra keywords */
|
||||
int linecount; /* number of lines in deck */
|
||||
char* cardline; /* line of card treated currently */
|
||||
} dico_t;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -672,6 +672,7 @@ nupa_eval(struct card *card)
|
|||
|
||||
dicoS->srcline = linenum;
|
||||
dicoS->oldline = orig_linenum;
|
||||
dicoS->cardline = s;
|
||||
|
||||
c = dicoS->dyncategory[linenum];
|
||||
|
||||
|
|
|
|||
|
|
@ -229,14 +229,15 @@ message(dico_t *dico, const char *fmt, ...)
|
|||
if (ft_ngdebug) {
|
||||
fprintf
|
||||
(stderr,
|
||||
"Netlist line no. %d, new internal line no. %d:\n",
|
||||
dico->oldline, dico->srcline);
|
||||
"Error in netlist line no. %d, new internal line no. %d:\n"
|
||||
"%s\n\n",
|
||||
dico->srcline, dico->oldline, dico->cardline);
|
||||
}
|
||||
else {
|
||||
fprintf
|
||||
(stderr,
|
||||
"Netlist line no. %d:\n",
|
||||
dico->oldline);
|
||||
"Error in netlist line no. %d, new internal line no. %d:\n\n",
|
||||
dico->srcline, dico->oldline);
|
||||
}
|
||||
}
|
||||
va_start(ap, fmt);
|
||||
|
|
@ -273,6 +274,7 @@ initdico(dico_t *dico)
|
|||
dico->hs_compatibility = 1;
|
||||
else
|
||||
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));
|
||||
|
||||
if (oldstate == S_binop && state == S_binop && c == '-') {
|
||||
ok = 1;
|
||||
negate = 1;
|
||||
continue;
|
||||
}
|
||||
/* c is a sign, + or - are allowed */
|
||||
if (oldstate == S_binop && state == S_binop)
|
||||
if (c == '-') {
|
||||
ok = 1;
|
||||
negate = 1;
|
||||
continue;
|
||||
}
|
||||
else if (c == '+') {
|
||||
ok = 1;
|
||||
negate = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
error = message(dico, " Misplaced operator\n");
|
||||
|
|
|
|||
|
|
@ -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_norefprint = FALSE, ft_skywaterpdk = 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 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;
|
||||
else
|
||||
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")) {
|
||||
if ((var->va_type == CP_BOOL) && (isset == FALSE))
|
||||
cp_numdgt = -1;
|
||||
|
|
@ -350,7 +361,7 @@ cp_usrset(struct variable *var, bool isset)
|
|||
else if (var->va_type == CP_NUM)
|
||||
cp_numdgt = var->va_num;
|
||||
else
|
||||
fprintf(cp_err, "Excuse me??\n");
|
||||
fprintf(cp_err, "Bad 'numdgt' \"%s\"\n", var->va_name);
|
||||
} else if (eq(var->va_name, "unixcom")) {
|
||||
cp_dounixcom = isset;
|
||||
if (isset) {
|
||||
|
|
|
|||
|
|
@ -380,6 +380,7 @@ struct func ft_funcs[] = {
|
|||
{ "integ", (cx_function_t*)(void *) cx_integ },
|
||||
{ "fft", (cx_function_t*)(void *) cx_fft },
|
||||
{ "ifft", (cx_function_t*)(void *) cx_ifft },
|
||||
{ "mtimeavg", (cx_function_t*)(void *) cx_mtimeavg },
|
||||
{ "v", NULL },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ Author: 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
|
|||
#include "ngspice/compatmode.h"
|
||||
|
||||
extern IFsimulator SIMinfo;
|
||||
extern char Spice_Build_Date[];
|
||||
|
||||
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, "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, "Flags: %s%s\n",
|
||||
realflag ? "real" : "complex", raw_padding ? "" : " unpadded");
|
||||
|
|
|
|||
|
|
@ -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 INPmodel *modtab;
|
||||
extern NGHASHPTR modtabhash;
|
||||
extern int DCtran_step_quit(CKTcircuit* ckt);
|
||||
|
||||
#ifdef SHARED_MODULE
|
||||
extern void exec_controls(wordlist *newcontrols);
|
||||
|
|
@ -219,6 +220,10 @@ com_remcirc(wordlist *wl)
|
|||
EVTunsetup(ft_curckt->ci_ckt);
|
||||
#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);
|
||||
for (v = ft_curckt->ci_vars; v; v = next) {
|
||||
next = v->va_next;
|
||||
|
|
|
|||
|
|
@ -485,9 +485,6 @@ struct is_arithmetic<duals::dual<T>> : is_arithmetic<T> {};
|
|||
|
||||
#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
|
||||
// C++03 17.4.3.1/1, and C++11 18.3.2.3/1.
|
||||
|
|
|
|||
|
|
@ -26,9 +26,10 @@ Modified: 1999 Paolo Nenzi - 2000 AlansFixes
|
|||
|
||||
extern void ft_checkkids(void);
|
||||
|
||||
/* breakpoint.c */
|
||||
/* breakp.c */
|
||||
|
||||
extern bool ft_bpcheck(struct plot *runplot, int iteration);
|
||||
extern bool ft_stepcheck(void);
|
||||
extern void dbfree(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_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_mtimeavg(void *, short int , int , int *, short int *, struct plot *, struct plot *, int );
|
||||
|
||||
/* define.c */
|
||||
|
||||
|
|
@ -172,29 +174,6 @@ extern struct dvec *ft_evaluate(struct pnode *node);
|
|||
/* ftesopt.c */
|
||||
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 */
|
||||
|
||||
|
|
@ -269,6 +248,8 @@ extern bool ft_ngdebug;
|
|||
extern bool ft_nginfo;
|
||||
extern bool ft_stricterror;
|
||||
extern bool ft_spiniterror;
|
||||
extern bool ft_codemodelerror;
|
||||
extern bool ft_osdierror;
|
||||
extern bool ft_skywaterpdk;
|
||||
|
||||
/* parse.c */
|
||||
|
|
@ -303,6 +284,9 @@ extern struct plot *raw_read(char *name);
|
|||
extern bool do_measure(char *what, bool chk_only);
|
||||
extern bool check_autostop(char *what);
|
||||
|
||||
/* com_measure2.c*/
|
||||
extern int measure_precision;
|
||||
|
||||
/* resource.c */
|
||||
|
||||
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_setflag;
|
||||
|
||||
/* error.c */
|
||||
|
||||
#endif
|
||||
|
|
|
|||
22
src/main.c
22
src/main.c
|
|
@ -755,6 +755,8 @@ show_help(void)
|
|||
" -t, --term=TERM set the terminal type\n"
|
||||
" -h, --help display this help 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"
|
||||
"Report bugs to %s.\n", cp_program, Bug_Addr);
|
||||
}
|
||||
|
|
@ -952,6 +954,8 @@ int main(int argc, char **argv)
|
|||
{"define", required_argument, NULL, 'D'},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"version", no_argument, NULL, 'v'},
|
||||
{"version-full", no_argument, NULL, 'f'},
|
||||
{"version-small", no_argument, NULL, 256},
|
||||
{"batch", no_argument, NULL, 'b'},
|
||||
{"autorun", no_argument, NULL, 'a'},
|
||||
{"circuitfile", required_argument, NULL, 'c'},
|
||||
|
|
@ -969,7 +973,7 @@ int main(int argc, char **argv)
|
|||
|
||||
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);
|
||||
|
||||
if (c == -1) {
|
||||
|
|
@ -1004,6 +1008,22 @@ int main(int argc, char **argv)
|
|||
sp_shutdown(EXIT_INFO);
|
||||
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 */
|
||||
{
|
||||
bool x_false = FALSE;
|
||||
|
|
|
|||
|
|
@ -369,7 +369,6 @@ cx_avg(void *data, short int type, int length, int *newlength, short int *newtyp
|
|||
void*
|
||||
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;
|
||||
|
||||
if (type == VF_REAL) {
|
||||
|
|
|
|||
|
|
@ -33,6 +33,9 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
|
|||
|
||||
#include "ngspice/sim.h" /* To get SV_TIME */
|
||||
#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 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);
|
||||
|
||||
scale = (double) fpts - 1.0;
|
||||
scale = ((double)length)/2.0;
|
||||
outdata[0].cx_real = out[0][0]/scale/2.0;
|
||||
outdata[0].cx_imag = 0.0;
|
||||
for (i = 1; i < fpts; i++) {
|
||||
outdata[i].cx_real = out[i][0]/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);
|
||||
|
||||
#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);
|
||||
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]). */
|
||||
outdata[0].cx_real = datax[0]/scale/2.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_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;
|
||||
|
||||
#endif
|
||||
|
|
@ -988,3 +994,127 @@ cx_ifft(void *data, short int type, int length, int *newlength, short int *newty
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
void * cx_ifft(void *data, short int type, int length, int *newlength, short int *newtype,
|
||||
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
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
|
|||
|
||||
#include <errno.h>
|
||||
|
||||
int input(FILE *fp);
|
||||
|
||||
FILE *cp_in = NULL;
|
||||
FILE *cp_out = NULL;
|
||||
|
|
@ -40,6 +41,9 @@ bool cp_no_histsubst = FALSE;
|
|||
struct compat newcompat;
|
||||
bool cx_degrees = FALSE;
|
||||
|
||||
IFsimulator *ft_sim = NULL;
|
||||
char Spice_Build_Date[] = " date is not available\n";
|
||||
|
||||
char *cp_program = "sconvert";
|
||||
|
||||
|
||||
|
|
@ -56,6 +60,17 @@ char *cp_program = "sconvert";
|
|||
#define TMALLOC(t, n) (t*) tmalloc(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 *
|
||||
smktemp(char *id)
|
||||
|
|
@ -192,7 +207,11 @@ oldread(char *name)
|
|||
pl->pl_scale = pl->pl_dvecs = v;
|
||||
end = v;
|
||||
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);
|
||||
}
|
||||
for (v = pl->pl_dvecs; v; v = v->v_next) {
|
||||
|
|
@ -380,15 +399,19 @@ oldwrite(char *name, bool app, struct plot *pl)
|
|||
int
|
||||
main(int ac, char **av)
|
||||
{
|
||||
char *sf, *af;
|
||||
char *sf = NULL, *af = NULL;
|
||||
char buf[BSIZE_SP];
|
||||
char t, f;
|
||||
char t = 0, f = 0;
|
||||
struct plot *pl;
|
||||
size_t n;
|
||||
char *infile = NULL;
|
||||
char *outfile = NULL;
|
||||
FILE *fp;
|
||||
|
||||
cp_in = stdin;
|
||||
cp_out = stdout;
|
||||
cp_err = stderr;
|
||||
|
||||
switch (ac) {
|
||||
case 5:
|
||||
sf = av[2];
|
||||
|
|
@ -414,20 +437,32 @@ main(int ac, char **av)
|
|||
|
||||
case 1: printf("Input file: ");
|
||||
(void) fflush(stdout);
|
||||
(void) fgets(buf, BSIZE_SP, stdin);
|
||||
sf = strdup(buf);
|
||||
if (fgets(buf, BSIZE_SP, stdin) != NULL) {
|
||||
sf = strdup(buf);
|
||||
} else {
|
||||
printf("Error reading input file.");
|
||||
}
|
||||
printf("Input type: ");
|
||||
(void) fflush(stdout);
|
||||
(void) fgets(buf, BSIZE_SP, stdin);
|
||||
f = buf[0];
|
||||
if (fgets(buf, BSIZE_SP, stdin) != NULL) {
|
||||
f = buf[0];
|
||||
} else {
|
||||
printf("Error reading input type.");
|
||||
}
|
||||
printf("Output file: ");
|
||||
(void) fflush(stdout);
|
||||
(void) fgets(buf, BSIZE_SP, stdin);
|
||||
af = strdup(buf);
|
||||
if (fgets(buf, BSIZE_SP, stdin) != NULL) {
|
||||
af = strdup(buf);
|
||||
} else {
|
||||
printf("Error reading output file.");
|
||||
}
|
||||
printf("Output type: ");
|
||||
(void) fflush(stdout);
|
||||
(void) fgets(buf, BSIZE_SP, stdin);
|
||||
t = buf[0];
|
||||
if (fgets(buf, BSIZE_SP, stdin) != NULL) {
|
||||
t = buf[0];
|
||||
} else {
|
||||
printf("Error reading output type.");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(cp_err,
|
||||
|
|
@ -488,7 +523,6 @@ main(int ac, char **av)
|
|||
exit(EXIT_NORMAL);
|
||||
}
|
||||
|
||||
|
||||
void cp_pushcontrol(void) { }
|
||||
void cp_popcontrol(void) { }
|
||||
void out_init(void) { }
|
||||
|
|
|
|||
|
|
@ -969,3 +969,22 @@ chkStep:
|
|||
}
|
||||
/* 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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,6 @@ NOISEan(CKTcircuit* ckt, int restart)
|
|||
|
||||
int numNames;
|
||||
IFuid* nameList; /* va: tmalloc'ed list of names */
|
||||
static runDesc* noiPlot = NULL;
|
||||
runDesc* plot = NULL;
|
||||
|
||||
#ifdef XSPICE
|
||||
|
|
|
|||
|
|
@ -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( "ngcon", BSIM4_NGCON, IF_REAL, "Number of gate contacts"),
|
||||
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( "acnqsmod", BSIM4_ACNQSMOD, IF_INTEGER, "AC NQS model selector"),
|
||||
|
|
|
|||
|
|
@ -135,6 +135,9 @@ BSIM4instance *here = (BSIM4instance*)inst;
|
|||
case BSIM4_WNFLAG:
|
||||
value->iValue = here->BSIM4wnflag;
|
||||
return(OK);
|
||||
case BSIM4_DTEMP:
|
||||
value->rValue = here->BSIM4dtemp;
|
||||
return(OK);
|
||||
case BSIM4_XGW:
|
||||
value->rValue = here->BSIM4xgw;
|
||||
return(OK);
|
||||
|
|
|
|||
|
|
@ -165,6 +165,10 @@ IFvalue *select)
|
|||
here->BSIM4wnflag = value->iValue;
|
||||
here->BSIM4wnflagGiven = TRUE;
|
||||
break;
|
||||
case BSIM4_DTEMP:
|
||||
here->BSIM4dtemp = value->rValue;
|
||||
here->BSIM4dtempGiven = TRUE;
|
||||
return(OK);
|
||||
case BSIM4_XGW:
|
||||
here->BSIM4xgw = value->rValue;
|
||||
here->BSIM4xgwGiven = TRUE;
|
||||
|
|
|
|||
|
|
@ -2371,6 +2371,8 @@ BSIM4instance **InstArray;
|
|||
here->BSIM4xgw = model->BSIM4xgw;
|
||||
if (!here->BSIM4ngconGiven)
|
||||
here->BSIM4ngcon = model->BSIM4ngcon;
|
||||
if (!here->BSIM4dtempGiven)
|
||||
here->BSIM4dtemp = 0;
|
||||
|
||||
/* Process instance model selectors, some
|
||||
* may override their global counterparts
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ typedef struct sBSIM4instance
|
|||
int BSIM4wnflag;
|
||||
double BSIM4xgw;
|
||||
double BSIM4ngcon;
|
||||
double BSIM4dtemp;
|
||||
|
||||
/* added here to account stress effect instance dependence */
|
||||
|
||||
|
|
@ -316,6 +317,7 @@ typedef struct sBSIM4instance
|
|||
unsigned BSIM4wnflagGiven :1;
|
||||
unsigned BSIM4xgwGiven :1;
|
||||
unsigned BSIM4ngconGiven :1;
|
||||
unsigned BSIM4dtempGiven : 1;
|
||||
unsigned BSIM4icVDSGiven :1;
|
||||
unsigned BSIM4icVGSGiven :1;
|
||||
unsigned BSIM4icVBSGiven :1;
|
||||
|
|
@ -2884,6 +2886,8 @@ typedef struct sBSIM4model
|
|||
#define BSIM4_WEFF 46
|
||||
#define BSIM4_LEFF 47
|
||||
|
||||
#define BSIM4_DTEMP 48
|
||||
|
||||
/* Global parameters */
|
||||
#define BSIM4_MOD_TEMPEOT 66
|
||||
#define BSIM4_MOD_LEFFEOT 67
|
||||
|
|
|
|||
|
|
@ -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( "xgw", BSIM4v5_XGW, IF_REAL, "Distance from gate contact center to device edge"),
|
||||
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( "acnqsmod", BSIM4v5_ACNQSMOD, IF_INTEGER, "AC NQS model selector"),
|
||||
|
|
|
|||
|
|
@ -112,6 +112,9 @@ BSIM4v5instance *here = (BSIM4v5instance*)inst;
|
|||
case BSIM4v5_MULU0:
|
||||
value->rValue = here->BSIM4v5mulu0;
|
||||
return(OK);
|
||||
case BSIM4v5_DTEMP:
|
||||
value->rValue = here->BSIM4v5dtemp;
|
||||
return(OK);
|
||||
case BSIM4v5_XGW:
|
||||
value->rValue = here->BSIM4v5xgw;
|
||||
return(OK);
|
||||
|
|
|
|||
|
|
@ -139,6 +139,10 @@ IFvalue *select)
|
|||
here->BSIM4v5mulu0 = value->rValue;
|
||||
here->BSIM4v5mulu0Given = TRUE;
|
||||
break;
|
||||
case BSIM4v5_DTEMP:
|
||||
here->BSIM4v5dtemp = value->rValue;
|
||||
here->BSIM4v5dtempGiven = TRUE;
|
||||
return(OK);
|
||||
case BSIM4v5_XGW:
|
||||
here->BSIM4v5xgw = value->rValue;
|
||||
here->BSIM4v5xgwGiven = TRUE;
|
||||
|
|
|
|||
|
|
@ -1751,8 +1751,9 @@ BSIM4v5instance **InstArray;
|
|||
here->BSIM4v5xgw = model->BSIM4v5xgw;
|
||||
if (!here->BSIM4v5ngconGiven)
|
||||
here->BSIM4v5ngcon = model->BSIM4v5ngcon;
|
||||
if (!here->BSIM4v5dtempGiven)
|
||||
here->BSIM4v5dtemp = 0;
|
||||
|
||||
|
||||
/* Process instance model selectors, some
|
||||
* may override their global counterparts
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ typedef struct sBSIM4v5instance
|
|||
double BSIM4v5mulu0;
|
||||
double BSIM4v5xgw;
|
||||
double BSIM4v5ngcon;
|
||||
double BSIM4v5dtemp;
|
||||
|
||||
/* added here to account stress effect instance dependence */
|
||||
double BSIM4v5u0temp;
|
||||
|
|
@ -288,6 +289,7 @@ typedef struct sBSIM4v5instance
|
|||
unsigned BSIM4v5mulu0Given :1;
|
||||
unsigned BSIM4v5xgwGiven :1;
|
||||
unsigned BSIM4v5ngconGiven :1;
|
||||
unsigned BSIM4v5dtempGiven : 1;
|
||||
unsigned BSIM4v5icVDSGiven :1;
|
||||
unsigned BSIM4v5icVGSGiven :1;
|
||||
unsigned BSIM4v5icVBSGiven :1;
|
||||
|
|
@ -2536,6 +2538,7 @@ typedef struct sBSIM4v5model
|
|||
#define BSIM4v5_SC 37
|
||||
#define BSIM4v5_M 38
|
||||
#define BSIM4v5_MULU0 39
|
||||
#define BSIM4v5_DTEMP 40
|
||||
|
||||
/* Global parameters */
|
||||
#define BSIM4v5_MOD_TEMPMOD 89
|
||||
|
|
|
|||
|
|
@ -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( "xgw", BSIM4v6_XGW, IF_REAL, "Distance from gate contact center to device edge"),
|
||||
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( "acnqsmod", BSIM4v6_ACNQSMOD, IF_INTEGER, "AC NQS model selector"),
|
||||
|
|
|
|||
|
|
@ -114,6 +114,9 @@ BSIM4v6instance *here = (BSIM4v6instance*)inst;
|
|||
case BSIM4v6_MULU0:
|
||||
value->rValue = here->BSIM4v6mulu0;
|
||||
return(OK);
|
||||
case BSIM4v6_DTEMP:
|
||||
value->rValue = here->BSIM4v6dtemp;
|
||||
return(OK);
|
||||
case BSIM4v6_XGW:
|
||||
value->rValue = here->BSIM4v6xgw;
|
||||
return(OK);
|
||||
|
|
|
|||
|
|
@ -141,6 +141,10 @@ IFvalue *select)
|
|||
here->BSIM4v6mulu0 = value->rValue;
|
||||
here->BSIM4v6mulu0Given = TRUE;
|
||||
break;
|
||||
case BSIM4v6_DTEMP:
|
||||
here->BSIM4v6dtemp = value->rValue;
|
||||
here->BSIM4v6dtempGiven = TRUE;
|
||||
return(OK);
|
||||
case BSIM4v6_XGW:
|
||||
here->BSIM4v6xgw = value->rValue;
|
||||
here->BSIM4v6xgwGiven = TRUE;
|
||||
|
|
|
|||
|
|
@ -2105,8 +2105,9 @@ BSIM4v6instance **InstArray;
|
|||
here->BSIM4v6xgw = model->BSIM4v6xgw;
|
||||
if (!here->BSIM4v6ngconGiven)
|
||||
here->BSIM4v6ngcon = model->BSIM4v6ngcon;
|
||||
if (!here->BSIM4v6dtempGiven)
|
||||
here->BSIM4v6dtemp = 0;
|
||||
|
||||
|
||||
/* Process instance model selectors, some
|
||||
* may override their global counterparts
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ typedef struct sBSIM4v6instance
|
|||
double BSIM4v6mulu0;
|
||||
double BSIM4v6xgw;
|
||||
double BSIM4v6ngcon;
|
||||
double BSIM4v6dtemp;
|
||||
|
||||
/* added here to account stress effect instance dependence */
|
||||
double BSIM4v6u0temp;
|
||||
|
|
@ -297,6 +298,7 @@ typedef struct sBSIM4v6instance
|
|||
unsigned BSIM4v6mulu0Given :1;
|
||||
unsigned BSIM4v6xgwGiven :1;
|
||||
unsigned BSIM4v6ngconGiven :1;
|
||||
unsigned BSIM4v6dtempGiven : 1;
|
||||
unsigned BSIM4v6icVDSGiven :1;
|
||||
unsigned BSIM4v6icVGSGiven :1;
|
||||
unsigned BSIM4v6icVBSGiven :1;
|
||||
|
|
@ -2713,6 +2715,7 @@ typedef struct sBSIM4v6model
|
|||
#define BSIM4v6_SC 37
|
||||
#define BSIM4v6_M 38
|
||||
#define BSIM4v6_MULU0 39
|
||||
#define BSIM4v6_DTEMP 40
|
||||
|
||||
/* Global parameters */
|
||||
#define BSIM4v6_MOD_TEMPEOT 65
|
||||
|
|
|
|||
|
|
@ -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( "ngcon", BSIM4v7_NGCON, IF_REAL, "Number of gate contacts"),
|
||||
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( "acnqsmod", BSIM4v7_ACNQSMOD, IF_INTEGER, "AC NQS model selector"),
|
||||
|
|
|
|||
|
|
@ -114,6 +114,9 @@ BSIM4v7instance *here = (BSIM4v7instance*)inst;
|
|||
case BSIM4v7_MULU0:
|
||||
value->rValue = here->BSIM4v7mulu0;
|
||||
return(OK);
|
||||
case BSIM4v7_DTEMP:
|
||||
value->rValue = here->BSIM4v7dtemp;
|
||||
return(OK);
|
||||
case BSIM4v7_WNFLAG:
|
||||
value->iValue = here->BSIM4v7wnflag;
|
||||
return(OK);
|
||||
|
|
|
|||
|
|
@ -141,6 +141,10 @@ IFvalue *select)
|
|||
here->BSIM4v7mulu0 = value->rValue;
|
||||
here->BSIM4v7mulu0Given = TRUE;
|
||||
break;
|
||||
case BSIM4v7_DTEMP:
|
||||
here->BSIM4v7dtemp = value->rValue;
|
||||
here->BSIM4v7dtempGiven = TRUE;
|
||||
return(OK);
|
||||
case BSIM4v7_WNFLAG:
|
||||
here->BSIM4v7wnflag = value->iValue;
|
||||
here->BSIM4v7wnflagGiven = TRUE;
|
||||
|
|
|
|||
|
|
@ -2256,8 +2256,9 @@ BSIM4v7instance **InstArray;
|
|||
here->BSIM4v7xgw = model->BSIM4v7xgw;
|
||||
if (!here->BSIM4v7ngconGiven)
|
||||
here->BSIM4v7ngcon = model->BSIM4v7ngcon;
|
||||
if (!here->BSIM4v7dtempGiven)
|
||||
here->BSIM4v7dtemp = 0;
|
||||
|
||||
|
||||
/* Process instance model selectors, some
|
||||
* may override their global counterparts
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ typedef struct sBSIM4v7instance
|
|||
int BSIM4v7wnflag;
|
||||
double BSIM4v7xgw;
|
||||
double BSIM4v7ngcon;
|
||||
double BSIM4v7dtemp;
|
||||
|
||||
/* added here to account stress effect instance dependence */
|
||||
double BSIM4v7u0temp;
|
||||
|
|
@ -302,6 +303,7 @@ typedef struct sBSIM4v7instance
|
|||
unsigned BSIM4v7wnflagGiven :1;
|
||||
unsigned BSIM4v7xgwGiven :1;
|
||||
unsigned BSIM4v7ngconGiven :1;
|
||||
unsigned BSIM4v7dtempGiven : 1;
|
||||
unsigned BSIM4v7icVDSGiven :1;
|
||||
unsigned BSIM4v7icVGSGiven :1;
|
||||
unsigned BSIM4v7icVBSGiven :1;
|
||||
|
|
@ -2843,6 +2845,7 @@ typedef struct sBSIM4v7model
|
|||
#define BSIM4v7_M 38
|
||||
#define BSIM4v7_MULU0 39
|
||||
#define BSIM4v7_WNFLAG 40
|
||||
#define BSIM4v7_DTEMP 41
|
||||
|
||||
/* Global parameters */
|
||||
#define BSIM4v7_MOD_TEMPEOT 65
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ static void free_dlerr_msg(char *msg);
|
|||
#define RTLD_NOW 2 /* immediate function call binding */
|
||||
#define RTLD_GLOBAL 4 /* symbols in this dlopen'ed obj are visible to other
|
||||
* dlopen'ed objs */
|
||||
#define F_OK 0
|
||||
#endif /* ifndef HAS_WINGUI */
|
||||
|
||||
#include "ngspice/dllitf.h" /* the coreInfo Structure*/
|
||||
|
|
@ -405,9 +406,14 @@ int load_opus(const char *name)
|
|||
lib = dlopen(name, RTLD_NOW);
|
||||
// fprintf(stdout, "Lib %s has handle %p\n", name, lib);
|
||||
if (!lib) {
|
||||
msg = dlerror();
|
||||
fprintf(stderr, "Error opening code model \"%s\"\n: %s\n", name, msg);
|
||||
FREE_DLERR_MSG(msg);
|
||||
int acc = access(name, F_OK);
|
||||
if (acc != 0) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/**********
|
||||
Copyright 1990 Regents of the University of California. All rights reserved.
|
||||
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"
|
||||
|
|
@ -122,6 +122,7 @@ IFparm DIOmPTable[] = { /* model parameters */
|
|||
OPU( "cond", DIO_MOD_COND,IF_REAL, "Ohmic conductance"),
|
||||
IOP( "isr", DIO_MOD_ISR, IF_REAL, "Recombination saturation current"),
|
||||
IOP( "nr", DIO_MOD_NR, IF_REAL, "Recombination current emission coefficient"),
|
||||
IOP( "vp", DIO_MOD_VP, IF_REAL, "Soft reverse recovery parameter"),
|
||||
|
||||
/* SOA parameters */
|
||||
IOPX( "fv_max", DIO_MOD_FV_MAX, IF_REAL, "maximum voltage in forward direction"),
|
||||
|
|
|
|||
|
|
@ -91,6 +91,20 @@ DIOacLoad(GENmodel *inModel, CKTcircuit *ckt)
|
|||
(*(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);
|
||||
|
|
|
|||
|
|
@ -75,9 +75,13 @@ DIOask (CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value,
|
|||
return(OK);
|
||||
case DIO_CURRENT:
|
||||
value->rValue = *(ckt->CKTstate0+here->DIOcurrent);
|
||||
if ((here->DIOqpNode > 0) && (here->DIOtTransitTime!=0))
|
||||
value->rValue += here->DIOqpGain * *(ckt->CKTstate0 + here->DIOcqcsr);
|
||||
return(OK);
|
||||
case DIO_CAP:
|
||||
value->rValue = here->DIOcap;
|
||||
if ((here->DIOqpNode > 0) && (here->DIOtTransitTime!=0))
|
||||
value->rValue += here->DIOtTransitTime * *(ckt->CKTstate0+here->DIOconduct);
|
||||
return(OK);
|
||||
case DIO_CHARGE:
|
||||
value->rValue = *(ckt->CKTstate0+here->DIOcapCharge);
|
||||
|
|
|
|||
|
|
@ -54,6 +54,14 @@ DIObindCSC (GENmodel *inModel, CKTcircuit *ckt)
|
|||
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);
|
||||
}
|
||||
}
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/**********
|
||||
Copyright 1990 Regents of the University of California. All rights reserved.
|
||||
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
|
||||
#define DIO
|
||||
|
|
@ -44,6 +44,7 @@ typedef struct sDIOinstance {
|
|||
const int DIOtempNode; /* number of the temperature node of the diode */
|
||||
int DIOposPrimeNode; /* number of positive prime node of diode */
|
||||
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
|
||||
* (positive,positive prime) */
|
||||
|
|
@ -83,9 +84,19 @@ typedef struct sDIOinstance {
|
|||
double *DIOtempPosSwPrimePtr;
|
||||
double *DIOposSwPrimeTempPtr;
|
||||
|
||||
/* rev-rec */
|
||||
double *DIOqpQpPtr;
|
||||
double *DIOqpPosPrimePtr;
|
||||
double *DIOqpNegPtr;
|
||||
double *DIOposPrimeQpPtr;
|
||||
double *DIOnegQpPtr;
|
||||
|
||||
double DIOcap; /* stores the diode 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
|
||||
sensitivity analyis */
|
||||
|
||||
|
|
@ -229,13 +240,19 @@ typedef struct sDIOinstance {
|
|||
/* self heating */
|
||||
BindElement *DIOtempPosBinding;
|
||||
BindElement *DIOtempPosPrimeBinding;
|
||||
BindElement *DIOtempNegBinding;
|
||||
BindElement *DIOtempNegBinding;
|
||||
BindElement *DIOtempTempBinding;
|
||||
BindElement *DIOposTempBinding;
|
||||
BindElement *DIOposPrimeTempBinding;
|
||||
BindElement *DIOnegTempBinding;
|
||||
BindElement *DIOtempPosSwPrimeBinding;
|
||||
BindElement *DIOposSwPrimeTempBinding;
|
||||
/* rev-rec */
|
||||
BindElement *DIOqpQpBinding;
|
||||
BindElement *DIOqpPosPrimeBinding;
|
||||
BindElement *DIOqpNegBinding;
|
||||
BindElement *DIOposPrimeQpBinding;
|
||||
BindElement *DIOnegQpBinding;
|
||||
#endif
|
||||
|
||||
} DIOinstance ;
|
||||
|
|
@ -244,7 +261,6 @@ typedef struct sDIOinstance {
|
|||
#define DIOsenCeq DIOsens + 3 /* stores the perturbed values of ceq */
|
||||
#define DIOdphidp DIOsens + 6
|
||||
|
||||
|
||||
#define DIOvoltage DIOstate
|
||||
#define DIOcurrent DIOstate+1
|
||||
#define DIOconduct DIOstate+2
|
||||
|
|
@ -256,18 +272,25 @@ typedef struct sDIOinstance {
|
|||
#define DIOcapChargeSW DIOstate+8
|
||||
#define DIOcapCurrentSW DIOstate+9
|
||||
|
||||
#define DIOqth DIOstate+10 /* thermal capacitor charge */
|
||||
#define DIOcqth DIOstate+11 /* thermal capacitor current */
|
||||
|
||||
#define DIOdeltemp DIOstate+12 /* thermal voltage over rth0 */
|
||||
#define DIOqth DIOstate+10 /* thermal capacitor charge */
|
||||
#define DIOcqth DIOstate+11 /* thermal capacitor current */
|
||||
#define DIOdeltemp DIOstate+12 /* thermal voltage over rth0 */
|
||||
#define DIOdIdio_dT DIOstate+13
|
||||
#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.
|
||||
* +16 for the derivatives - pointer to the
|
||||
* beginning of the array */
|
||||
#define DIOsensxp DIOstate+22 /* charge sensitivities and their derivatives.
|
||||
* +23 for the derivatives - pointer to the
|
||||
* beginning of the array */
|
||||
|
||||
#define DIOnumSenStates 2
|
||||
|
||||
|
|
@ -342,6 +365,7 @@ typedef struct sDIOmodel { /* model structure for a diode */
|
|||
unsigned DIOte_maxGiven : 1;
|
||||
unsigned DIOrecSatCurGiven : 1;
|
||||
unsigned DIOrecEmissionCoeffGiven : 1;
|
||||
unsigned DIOsoftRevRecParamGiven : 1;
|
||||
|
||||
unsigned DIOrth0Given :1;
|
||||
unsigned DIOcth0Given :1;
|
||||
|
|
@ -418,6 +442,7 @@ typedef struct sDIOmodel { /* model structure for a diode */
|
|||
double DIOte_max; /* maximum temperature */
|
||||
double DIOrecSatCur; /* Recombination saturation current */
|
||||
double DIOrecEmissionCoeff; /* Recombination emission coefficient */
|
||||
double DIOsoftRevRecParam; /* Soft reverse recovery parameter */
|
||||
|
||||
double DIOrth0;
|
||||
double DIOcth0;
|
||||
|
|
@ -526,6 +551,7 @@ enum {
|
|||
DIO_MOD_PD_MAX,
|
||||
DIO_MOD_ISR,
|
||||
DIO_MOD_NR,
|
||||
DIO_MOD_VP,
|
||||
DIO_MOD_RTH0,
|
||||
DIO_MOD_CTH0,
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Copyright 1990 Regents of the University of California. All rights reserved.
|
||||
Author: 1985 Thomas L. Quarles
|
||||
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"
|
||||
|
|
@ -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 dIdioSw_dT=0.0, dIth_dVdioSw=0.0, dIth_dVrssw=0.0, dIrssw_dT=0.0;
|
||||
double argsw_dT, csat_dT, csatsw_dT;
|
||||
/* rev-rec */
|
||||
double cdres, gdres;
|
||||
double vqp;
|
||||
double capsr, gqcsr, cqcsr;
|
||||
|
||||
/* loop through all the diode models */
|
||||
for( ; model != NULL; model = DIOnextModel(model)) {
|
||||
|
|
@ -74,6 +78,7 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
here=DIOnextInstance(here)) {
|
||||
|
||||
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.
|
||||
|
|
@ -120,10 +125,12 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
vd = *(ckt->CKTstate1 + here->DIOvoltage);
|
||||
if (model->DIOresistSWGiven) vdsw = *(ckt->CKTstate1 + here->DIOvoltageSW);
|
||||
delTemp = *(ckt->CKTstate1 + here->DIOdeltemp);
|
||||
vqp = *(ckt->CKTstate1 + here->DIOqp);
|
||||
} else{
|
||||
vd = *(ckt->CKTstate0 + here->DIOvoltage);
|
||||
if (model->DIOresistSWGiven) vdsw = *(ckt->CKTstate0 + here->DIOvoltageSW);
|
||||
delTemp = *(ckt->CKTstate0 + here->DIOdeltemp);
|
||||
vqp = *(ckt->CKTstate0 + here->DIOqp);
|
||||
}
|
||||
|
||||
#ifdef SENSDEBUG
|
||||
|
|
@ -137,24 +144,30 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
vd= *(ckt->CKTstate0 + here->DIOvoltage);
|
||||
if (model->DIOresistSWGiven) vdsw = *(ckt->CKTstate0 + here->DIOvoltageSW);
|
||||
delTemp = *(ckt->CKTstate0 + here->DIOdeltemp);
|
||||
vqp= *(ckt->CKTstate0 + here->DIOqp);
|
||||
} else if (ckt->CKTmode & MODEINITTRAN) {
|
||||
vd= *(ckt->CKTstate1 + here->DIOvoltage);
|
||||
if (model->DIOresistSWGiven) vdsw = *(ckt->CKTstate1 + here->DIOvoltageSW);
|
||||
delTemp = *(ckt->CKTstate1 + here->DIOdeltemp);
|
||||
vqp= *(ckt->CKTstate1 + here->DIOqp);
|
||||
} else if ( (ckt->CKTmode & MODEINITJCT) &&
|
||||
(ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC) ) {
|
||||
vd=here->DIOinitCond;
|
||||
if (model->DIOresistSWGiven) vdsw = here->DIOinitCond;
|
||||
vqp=0;
|
||||
} else if ( (ckt->CKTmode & MODEINITJCT) && here->DIOoff) {
|
||||
vd=vdsw=0;
|
||||
delTemp = 0.0;
|
||||
vqp=0;
|
||||
} else if ( ckt->CKTmode & MODEINITJCT) {
|
||||
vd=here->DIOtVcrit;
|
||||
vdsw=here->DIOtVcritSW;
|
||||
delTemp = 0.0;
|
||||
vqp=0;
|
||||
} else if ( ckt->CKTmode & MODEINITFIX && here->DIOoff) {
|
||||
vd=vdsw=0;
|
||||
delTemp = 0.0;
|
||||
vqp=0;
|
||||
} else {
|
||||
#ifndef PREDICTOR
|
||||
if (ckt->CKTmode & MODEINITPRED) {
|
||||
|
|
@ -177,12 +190,22 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
*(ckt->CKTstate0 + 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 {
|
||||
#endif /* PREDICTOR */
|
||||
vd = *(ckt->CKTrhsOld+here->DIOposPrimeNode)-
|
||||
*(ckt->CKTrhsOld + here->DIOnegNode);
|
||||
if (model->DIOresistSWGiven) vdsw = *(ckt->CKTrhsOld+here->DIOposSwPrimeNode)-
|
||||
*(ckt->CKTrhsOld + here->DIOnegNode);
|
||||
|
||||
if (selfheat)
|
||||
delTemp = *(ckt->CKTrhsOld + here->DIOtempNode);
|
||||
else
|
||||
|
|
@ -192,6 +215,7 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
*(ckt->CKTstate1+here->DIOqth) =
|
||||
*(ckt->CKTstate0+here->DIOqth);
|
||||
}
|
||||
vqp = *(ckt->CKTrhsOld+here->DIOqpNode);
|
||||
#ifndef PREDICTOR
|
||||
}
|
||||
#endif /* PREDICTOR */
|
||||
|
|
@ -238,6 +262,11 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
gdsw= *(ckt->CKTstate0 + here->DIOconductSW);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -304,7 +333,7 @@ next1:
|
|||
|
||||
if (model->DIOsatSWCurGiven) { /* sidewall current */
|
||||
double vds;
|
||||
if (model->DIOresistSWGiven)
|
||||
if (model->DIOresistSWGiven)
|
||||
vds = vdsw; /* sidewall voltage used */
|
||||
else
|
||||
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);
|
||||
cdb = cdb/(1+sqrt_ikx);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( (model->DIOforwardSWKneeCurrentGiven) && (cdsw > 1.0e-18) ) {
|
||||
|
|
@ -493,6 +521,11 @@ next1:
|
|||
dIdioSw_dT = cdsw_dT;
|
||||
}
|
||||
|
||||
cdres = cd;
|
||||
gdres = gd;
|
||||
cqcsr = 0;
|
||||
gqcsr = 0;
|
||||
|
||||
if ((ckt->CKTmode & (MODEDCTRANCURVE | MODETRAN | MODEAC | MODEINITSMSIG)) ||
|
||||
((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC))) {
|
||||
/*
|
||||
|
|
@ -528,22 +561,46 @@ next1:
|
|||
deplcapSW = czof2SW*(here->DIOtF3SW+model->DIOgradingSWCoeff*vdx/here->DIOtJctSWPot);
|
||||
}
|
||||
|
||||
diffcharge = here->DIOtTransitTime*cd;
|
||||
diffcap = here->DIOtTransitTime*gd;
|
||||
if (!model->DIOresistSWGiven) {
|
||||
if (revrec) {
|
||||
/*
|
||||
soft recovery with TT!=0
|
||||
add only depletion capacitance.
|
||||
*/
|
||||
*(ckt->CKTstate0 + here->DIOcapCharge) =
|
||||
diffcharge + deplcharge + deplchargeSW + (here->DIOcmetal + here->DIOcpoly)*vd;
|
||||
capd = diffcap + deplcap + deplcapSW + here->DIOcmetal + here->DIOcpoly;
|
||||
deplcharge + deplchargeSW + (here->DIOcmetal + here->DIOcpoly)*vd;
|
||||
|
||||
capd = deplcap + deplcapSW + here->DIOcmetal + here->DIOcpoly;
|
||||
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 {
|
||||
*(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;
|
||||
/* no soft recovery of soft recovery with TT=0 (i.e. no soft recovery due to TT=0) */
|
||||
diffcharge = here->DIOtTransitTime*cd;
|
||||
diffcap = here->DIOtTransitTime*gd;
|
||||
if (!model->DIOresistSWGiven) {
|
||||
*(ckt->CKTstate0 + here->DIOcapCharge) =
|
||||
diffcharge + deplcharge + deplchargeSW + (here->DIOcmetal + here->DIOcpoly)*vd;
|
||||
capd = diffcap + deplcap + deplcapSW + here->DIOcmetal + here->DIOcpoly;
|
||||
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
|
||||
|
|
@ -564,6 +621,10 @@ next1:
|
|||
*(ckt->CKTstate0 + here->DIOconductSW) = gdsw;
|
||||
*(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
|
||||
printf("storing small signal parameters\n");
|
||||
printf("cd = %.7e,vd = %.7e\n",cd,vd);
|
||||
|
|
@ -580,6 +641,7 @@ next1:
|
|||
*(ckt->CKTstate0 + here->DIOcurrent) = cd;
|
||||
if (model->DIOresistSWGiven)
|
||||
*(ckt->CKTstate0 + here->DIOcurrentSW) = cdsw;
|
||||
*(ckt->CKTstate0 + here->DIOresCurrent) = cdres;
|
||||
#ifdef SENSDEBUG
|
||||
printf("storing parameters for transient sensitivity\n"
|
||||
);
|
||||
|
|
@ -613,6 +675,21 @@ next1:
|
|||
*(ckt->CKTstate1 + 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)
|
||||
{
|
||||
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->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;
|
||||
|
||||
#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;
|
||||
}
|
||||
if (model->DIOresistSWGiven) {
|
||||
cdeq=cdsw-gdsw*vdsw;
|
||||
*(ckt->CKTrhs + here->DIOnegNode) += cdeq;
|
||||
*(ckt->CKTrhs + here->DIOposSwPrimeNode) -= cdeq;
|
||||
double cdeqsw=cdsw-gdsw*vdsw;
|
||||
*(ckt->CKTrhs + here->DIOnegNode) += cdeqsw;
|
||||
*(ckt->CKTrhs + here->DIOposSwPrimeNode) -= cdeqsw;
|
||||
if (selfheat) {
|
||||
*(ckt->CKTrhs + here->DIOposNode) += 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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/**********
|
||||
Copyright 1990 Regents of the University of California. All rights reserved.
|
||||
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:
|
||||
value->rValue = model->DIOrecEmissionCoeff;
|
||||
return(OK);
|
||||
case DIO_MOD_VP:
|
||||
value->rValue = model->DIOsoftRevRecParam;
|
||||
return(OK);
|
||||
case DIO_MOD_RTH0:
|
||||
value->rValue = model->DIOrth0;
|
||||
return(OK);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/**********
|
||||
Copyright 1990 Regents of the University of California. All rights reserved.
|
||||
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->DIOrecEmissionCoeffGiven = TRUE;
|
||||
break;
|
||||
case DIO_MOD_VP:
|
||||
model->DIOsoftRevRecParam = value->rValue;
|
||||
model->DIOsoftRevRecParamGiven = TRUE;
|
||||
break;
|
||||
case DIO_MOD_RTH0:
|
||||
model->DIOrth0 = value->rValue;
|
||||
model->DIOrth0Given = TRUE;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Copyright 1990 Regents of the University of California. All rights reserved.
|
||||
Author: 1985 Thomas L. Quarles
|
||||
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
|
||||
|
|
@ -222,6 +222,9 @@ DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
|
|||
if(!model->DIOrecSatCurGiven) {
|
||||
model->DIOrecSatCur = 1e-14;
|
||||
}
|
||||
if (!model->DIOsoftRevRecParamGiven) {
|
||||
model->DIOsoftRevRecParam = 0.0;
|
||||
}
|
||||
|
||||
/* set lower limit of saturation current */
|
||||
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));
|
||||
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 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);
|
||||
|
|
@ -474,7 +497,7 @@ DIOunsetup(
|
|||
if (here->DIOposPrimeNode > 0
|
||||
&& here->DIOposPrimeNode != here->DIOposNode)
|
||||
CKTdltNNum(ckt, here->DIOposPrimeNode);
|
||||
here->DIOposPrimeNode = 0;
|
||||
here->DIOposPrimeNode = 0;
|
||||
|
||||
if(model->DIOresistSWGiven) {
|
||||
/* separate sidewall */
|
||||
|
|
@ -484,6 +507,11 @@ DIOunsetup(
|
|||
here->DIOposSwPrimeNode = 0;
|
||||
}
|
||||
|
||||
/* rev-rec */
|
||||
if (here->DIOqpNode > 0)
|
||||
CKTdltNNum(ckt, here->DIOqpNode);
|
||||
here->DIOqpNode = 0;
|
||||
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ DIOtrunc(GENmodel *inModel, CKTcircuit *ckt, double *timeStep)
|
|||
for(here=DIOinstances(model);here!=NULL;here = DIOnextInstance(here)){
|
||||
CKTterr(here->DIOcapCharge,ckt,timeStep);
|
||||
if (model->DIOresistSWGiven) CKTterr(here->DIOcapChargeSW,ckt,timeStep);
|
||||
if (model->DIOsoftRevRecParam!=0 && here->DIOtTransitTime!=0)
|
||||
CKTterr(here->DIOsrcapCharge,ckt,timeStep);
|
||||
}
|
||||
}
|
||||
return(OK);
|
||||
|
|
|
|||
|
|
@ -205,18 +205,18 @@ ISRCload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
|
||||
case SFFM: {
|
||||
|
||||
double VO, VA, FM, MDI, FC, TD, PHASEM, PHASEC;
|
||||
double VO, VA, FC, MDI, FM, TD, PHASEM, PHASEC;
|
||||
double phasec;
|
||||
double phasem;
|
||||
static bool warn1 = FALSE, warn2 = FALSE;
|
||||
|
||||
VO = here->ISRCcoeffs[0];
|
||||
VA = here->ISRCcoeffs[1];
|
||||
FM = here->ISRCfunctionOrder > 2
|
||||
FC = here->ISRCfunctionOrder > 2
|
||||
? here->ISRCcoeffs[2] : (5./ckt->CKTfinalTime);
|
||||
MDI = here->ISRCfunctionOrder > 3
|
||||
? here->ISRCcoeffs[3] : 90.0;
|
||||
FC = here->ISRCfunctionOrder > 4
|
||||
FM = here->ISRCfunctionOrder > 4
|
||||
&& here->ISRCcoeffs[4]
|
||||
? here->ISRCcoeffs[4] : (500./ckt->CKTfinalTime);
|
||||
TD = here->ISRCfunctionOrder > 5
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ VDMOSconvTest(GENmodel *inModel, CKTcircuit *ckt)
|
|||
here = VDMOSnextInstance(here)) {
|
||||
|
||||
vgs = model->VDMOStype * (
|
||||
*(ckt->CKTrhs+here->VDMOSgNode) -
|
||||
*(ckt->CKTrhs+here->VDMOSgNodePrime) -
|
||||
*(ckt->CKTrhs+here->VDMOSsNodePrime));
|
||||
vds = model->VDMOStype * (
|
||||
*(ckt->CKTrhs+here->VDMOSdNodePrime) -
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ VDMOSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt,
|
|||
model->VDMOStype = NMOS;
|
||||
|
||||
if (!model->VDMOStransconductanceGiven)
|
||||
model->VDMOStransconductance = 25 + 10 * model->VDMOStype; /* IRF540, 9540 */
|
||||
model->VDMOStransconductance = 15 + 5 * model->VDMOStype; /* IRF540, 9540 */
|
||||
|
||||
if (!model->VDMOSvth0Given)
|
||||
model->VDMOSvth0 = 3 * model->VDMOStype; /* IRF540, 9540 */
|
||||
|
|
@ -128,7 +128,7 @@ VDMOSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt,
|
|||
model->VDMOSrthjc = 1.0;
|
||||
|
||||
if (!model->VDMOSrthcaGiven)
|
||||
model->VDMOSrthca = 1000;
|
||||
model->VDMOSrthca = 23; /* e.g. TO220 case */
|
||||
|
||||
if (!model->VDMOScthjGiven)
|
||||
model->VDMOScthj = 10e-06;
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ void VDMOStempUpdate(VDMOSmodel *inModel, VDMOSinstance *here, double Temp, CKTc
|
|||
here->VDMOStTransconductance = model->VDMOStransconductance
|
||||
* 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));
|
||||
|
||||
|
|
|
|||
|
|
@ -56,20 +56,24 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
|
|||
double phase;
|
||||
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
|
||||
? here->VSRCcoeffs[2] : 0.0;
|
||||
TR = here->VSRCfunctionOrder > 3
|
||||
&& here->VSRCcoeffs[3] != 0.0
|
||||
&& here->VSRCcoeffs[3] > 0.0
|
||||
? here->VSRCcoeffs[3] : ckt->CKTstep;
|
||||
TF = here->VSRCfunctionOrder > 4
|
||||
&& here->VSRCcoeffs[4] != 0.0
|
||||
&& here->VSRCcoeffs[4] > 0.0
|
||||
? here->VSRCcoeffs[4] : ckt->CKTstep;
|
||||
PW = here->VSRCfunctionOrder > 5
|
||||
&& here->VSRCcoeffs[5] >= 0.0
|
||||
? here->VSRCcoeffs[5] : ckt->CKTfinalTime;
|
||||
? here->VSRCcoeffs[5] : 0.0;
|
||||
PER = here->VSRCfunctionOrder > 6
|
||||
&& here->VSRCcoeffs[6] != 0.0
|
||||
? here->VSRCcoeffs[6] : ckt->CKTfinalTime;
|
||||
&& here->VSRCcoeffs[6] > 0.0
|
||||
? here->VSRCcoeffs[6] : TR + TF + PW;
|
||||
PHASE = here->VSRCfunctionOrder > 7
|
||||
? here->VSRCcoeffs[7] : 0.0;
|
||||
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ VSRCload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
} else {
|
||||
time = ckt->CKTtime;
|
||||
}
|
||||
/* use the transient functions */
|
||||
/* use the transient functions. */
|
||||
switch(here->VSRCfunctionType) {
|
||||
|
||||
default:
|
||||
|
|
@ -94,6 +94,12 @@ VSRCload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
break;
|
||||
|
||||
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 basetime = 0;
|
||||
double PHASE;
|
||||
|
|
@ -106,17 +112,17 @@ VSRCload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
TD = here->VSRCfunctionOrder > 2
|
||||
? here->VSRCcoeffs[2] : 0.0;
|
||||
TR = here->VSRCfunctionOrder > 3
|
||||
&& here->VSRCcoeffs[3] != 0.0
|
||||
&& here->VSRCcoeffs[3] > 0.0
|
||||
? here->VSRCcoeffs[3] : ckt->CKTstep;
|
||||
TF = here->VSRCfunctionOrder > 4
|
||||
&& here->VSRCcoeffs[4] != 0.0
|
||||
&& here->VSRCcoeffs[4] > 0.0
|
||||
? here->VSRCcoeffs[4] : ckt->CKTstep;
|
||||
PW = here->VSRCfunctionOrder > 5
|
||||
&& here->VSRCcoeffs[5] >= 0.0
|
||||
? here->VSRCcoeffs[5] : ckt->CKTfinalTime;
|
||||
&& here->VSRCcoeffs[5] >= 0.0
|
||||
? here->VSRCcoeffs[5] : 0.0;
|
||||
PER = here->VSRCfunctionOrder > 6
|
||||
&& here->VSRCcoeffs[6] != 0.0
|
||||
? here->VSRCcoeffs[6] : ckt->CKTfinalTime;
|
||||
&& here->VSRCcoeffs[6] > 0.0
|
||||
? here->VSRCcoeffs[6] : TR + TF + PW;
|
||||
|
||||
/* shift time by delay time TD */
|
||||
time -= TD;
|
||||
|
|
@ -227,18 +233,18 @@ VSRCload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
|
||||
case SFFM: {
|
||||
|
||||
double VO, VA, FM, MDI, FC, TD, PHASEM, PHASEC;
|
||||
double VO, VA, FC, MDI, FM, TD, PHASEM, PHASEC;
|
||||
double phasec;
|
||||
double phasem;
|
||||
static bool warn1 = FALSE, warn2 = FALSE;
|
||||
|
||||
VO = here->VSRCcoeffs[0];
|
||||
VA = here->VSRCcoeffs[1];
|
||||
FM = here->VSRCfunctionOrder > 2
|
||||
FC = here->VSRCfunctionOrder > 2
|
||||
? here->VSRCcoeffs[2] : (5./ckt->CKTfinalTime);
|
||||
MDI = here->VSRCfunctionOrder > 3
|
||||
? 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] : (500./ckt->CKTfinalTime);
|
||||
TD = here->VSRCfunctionOrder > 5
|
||||
|
|
|
|||
|
|
@ -71,7 +71,10 @@ void INP2N(CKTcircuit *ckt, INPtables *tab, struct card *current) {
|
|||
|
||||
if (i >= 2) {
|
||||
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);
|
||||
tfree(c);
|
||||
tfree(token);
|
||||
|
|
|
|||
|
|
@ -67,10 +67,14 @@ INPdoOpts(
|
|||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
errmsg = TMALLOC(char, 100);
|
||||
(void) strcpy(errmsg," Error: unknown option - ignored\n");
|
||||
optCard->error = INPerrCat(optCard->error,errmsg);
|
||||
fprintf(stderr, "%s\n", optCard->error);
|
||||
/* print err message only if it is not just a number */
|
||||
char* ctoken = token;
|
||||
while (*ctoken && strchr("0123456789.e+-", *ctoken))
|
||||
ctoken++;
|
||||
if (*ctoken) {
|
||||
errmsg = tprintf("Error: unknown option %s - ignored\n", token);
|
||||
optCard->error = INPerrCat(optCard->error, errmsg);
|
||||
fprintf(stderr, "%s\n", optCard->error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ INPdevParse(char **line, CKTcircuit *ckt, int dev, GENinstance *fast,
|
|||
errbuf = copy(" unknown parameter ($). Check the compatibility flag!\n");
|
||||
}
|
||||
else {
|
||||
errbuf = tprintf(" unknown parameter (%s) \n", parameter);
|
||||
errbuf = tprintf(" unknown instance parameter (%s) \n", parameter);
|
||||
}
|
||||
rtn = errbuf;
|
||||
goto quit;
|
||||
|
|
|
|||
|
|
@ -1499,7 +1499,7 @@ win_x_fprintf(FILE *stream, const char *format, ...)
|
|||
if ((stream == stdout) || (stream == stderr)) {
|
||||
|
||||
s[0] = SE;
|
||||
result = vsprintf(s, format, args);
|
||||
result = vsnprintf(s, IOBufSize, format, args);
|
||||
win_x_fputs(s, stream);
|
||||
} else
|
||||
result = vfprintf(stream, format, args);
|
||||
|
|
|
|||
|
|
@ -117,10 +117,8 @@ ENHtranslate_poly(
|
|||
l1->nextcard = l2;
|
||||
d->nextcard = l1;
|
||||
|
||||
/* PN 2004: Add original linenumber to ease the debug process
|
||||
* for malfromned netlist
|
||||
*/
|
||||
|
||||
/* Add original linenumber to ease the debug process
|
||||
* for malformed netlist */
|
||||
l1->linenum = d->linenum;
|
||||
l2->linenum = d->linenum;
|
||||
|
||||
|
|
@ -301,7 +299,7 @@ static char *two2three_translate(
|
|||
char **out_conn;
|
||||
char **in_conn;
|
||||
char **coef;
|
||||
|
||||
char* multibeg, *multiend, *multi = NULL;
|
||||
char *card;
|
||||
|
||||
|
||||
|
|
@ -313,6 +311,20 @@ static char *two2three_translate(
|
|||
/* Put the first character into local storage for checking type */
|
||||
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 */
|
||||
num_tokens = count_tokens(orig_card);
|
||||
|
||||
|
|
@ -356,8 +368,8 @@ static char *two2three_translate(
|
|||
|
||||
if(num_coefs < 1) {
|
||||
char *errmsg;
|
||||
printf("ERROR - Number of connections differs from poly dimension\n");
|
||||
printf("ERROR while parsing: %s\n", orig_card);
|
||||
fprintf(stderr, "ERROR - Number of connections differs from poly dimension\n");
|
||||
fprintf(stderr, " while parsing: %s\n", orig_card);
|
||||
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");
|
||||
*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++)
|
||||
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 */
|
||||
|
||||
*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), "]");
|
||||
|
||||
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
|
||||
/* SDB debug statement */
|
||||
printf("In two2three_translate, translated statements:\n%s \n%s \n", *inst_card, *mod_card);
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ required syntax.
|
|||
This model may also be called directly as follows:
|
||||
|
||||
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.
|
||||
|
||||
|
|
@ -102,12 +102,14 @@ void spice2poly (ARGS)
|
|||
double sum; /* Temporary for accumulating sum of terms */
|
||||
double product; /* Temporary for accumulating product */
|
||||
|
||||
|
||||
double mult; /* multplicator for G and F sources */
|
||||
|
||||
/* Get number of input values */
|
||||
|
||||
num_inputs = PORT_SIZE(in);
|
||||
|
||||
mult = PARAM(m);
|
||||
|
||||
/* If this is the first call to the model, allocate the static variable */
|
||||
/* array */
|
||||
|
||||
|
|
@ -165,7 +167,7 @@ void spice2poly (ARGS)
|
|||
/* Add the product times the appropriate coefficient into the sum */
|
||||
sum += coef[i] * product;
|
||||
}
|
||||
OUTPUT(out) = sum;
|
||||
OUTPUT(out) = sum * mult;
|
||||
|
||||
|
||||
/* Compute and output the partials for each input */
|
||||
|
|
@ -201,13 +203,13 @@ void spice2poly (ARGS)
|
|||
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 */
|
||||
/* value in an AC analysis */
|
||||
|
||||
if(ANALYSIS == MIF_DC)
|
||||
STATIC_VAR(acgains[i]) = sum;
|
||||
STATIC_VAR(acgains[i]) = sum * mult;
|
||||
}
|
||||
|
||||
/* Free the allocated items and return */
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@ AUTHORS
|
|||
|
||||
MODIFICATIONS
|
||||
|
||||
<date> <person name> <nature of modifications>
|
||||
11/05/2025 Holger Vogt
|
||||
new parameter m (multiplicator)
|
||||
|
||||
SUMMARY
|
||||
|
||||
|
|
@ -67,6 +68,17 @@ Vector: yes
|
|||
Vector_Bounds: [2 -]
|
||||
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:
|
||||
|
||||
|
|
|
|||
|
|
@ -210,6 +210,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\src\xspice\icm\spice2poly\icm_spice2poly\cfunc.mod" />
|
||||
<None Include="..\..\src\xspice\icm\spice2poly\icm_spice2poly\ifspec.ifs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\include\ngspice\dstring.h" />
|
||||
|
|
|
|||
Loading…
Reference in New Issue