Merge branch 'pre-master-46' into bt_dev

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

View File

@ -51,6 +51,7 @@ let newstime = stime/1.4
let deltime = newstime/100
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

View File

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

View File

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

View File

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

View File

@ -1,10 +1,5 @@
ngspice input files using optran
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

View File

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

View File

@ -27,7 +27,7 @@ R2 2 3 {value*(1-ratio)+ 1m}
+ Cgdmax=2.45n Cgdmin=10p a=0.3 Cgs=1.2n
+ 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

View File

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

View File

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

View File

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

View File

@ -35,7 +35,7 @@ Xtr3 1 0 22 0 tr3
.ends
* 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

View File

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

View File

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

View File

@ -40,7 +40,7 @@ plot 'i(v6)/deriv(v(d4))' vs v(d2p) xlog xlimit 1 100 ylimit 0 3n title "IRFP924
+ Cgdmax=2.45n Cgdmin=10p a=0.3 Cgs=1.2n
+ 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -858,7 +858,7 @@ apply_func_funcall(struct func *func, struct dvec *v, int *newlength, short int
/* Modified for passing necessary parameters to the derive function - A.Roldan */
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,

View File

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

View File

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

View File

@ -1105,6 +1105,16 @@ struct card *inp_readall(FILE *fp, const char *dir_name, const char* file_name,
if (newcompat.ps && newcompat.a)
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;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -25,6 +25,7 @@ bool ft_acctprint = FALSE, ft_noacctprint = FALSE, ft_listprint = FALSE;
bool ft_nodesprint = FALSE, ft_optsprint = FALSE, ft_noinitprint = FALSE;
bool ft_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) {

View File

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

View File

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

View File

@ -35,6 +35,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
extern void line_free_x(struct card *deck, bool recurse);
extern 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;

View File

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

View File

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

View File

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

View File

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

View File

@ -33,6 +33,9 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
#include "ngspice/sim.h" /* To get SV_TIME */
#include "ngspice/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);
}

View File

@ -25,5 +25,7 @@ void * cx_fft(void *data, short int type, int length, int *newlength, short int
struct plot *pl, struct plot *newpl, int grouping);
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

View File

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

View File

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

View File

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

View File

@ -59,6 +59,7 @@ IOP( "mulu0", BSIM4_MULU0, IF_REAL, "Low field mobility multiplier"),
IOP( "xgw", BSIM4_XGW, IF_REAL, "Distance from gate contact center to device edge"),
IOP( "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"),

View File

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

View File

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

View File

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

View File

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

View File

@ -49,7 +49,7 @@ IOPR( "delvt0", BSIM4v5_DELVTO, IF_REAL , "Zero bias threshold voltage variat
IOP( "mulu0", BSIM4v5_MULU0, IF_REAL, "Low field mobility multiplier"),
IOP( "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"),

View File

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

View File

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

View File

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

View File

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

View File

@ -55,7 +55,7 @@ IOPR( "delvt0", BSIM4v6_DELVTO, IF_REAL , "Zero bias threshold voltage variat
IOP( "mulu0", BSIM4v6_MULU0, IF_REAL, "Low field mobility multiplier"),
IOP( "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"),

View File

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

View File

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

View File

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

View File

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

View File

@ -57,6 +57,7 @@ IOP( "mulu0", BSIM4v7_MULU0, IF_REAL, "Low field mobility multiplier"),
IOP( "xgw", BSIM4v7_XGW, IF_REAL, "Distance from gate contact center to device edge"),
IOP( "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"),

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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