diff --git a/examples/memristor/memristor.sp b/examples/memristor/memristor.sp index 0664f1075..c41787430 100644 --- a/examples/memristor/memristor.sp +++ b/examples/memristor/memristor.sp @@ -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 diff --git a/examples/memristor/memristor_x.sp b/examples/memristor/memristor_x.sp index 198cb979b..a9bf93198 100644 --- a/examples/memristor/memristor_x.sp +++ b/examples/memristor/memristor_x.sp @@ -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) diff --git a/examples/optran/F5TurboV2thermal-optran.cir b/examples/optran/F5TurboV2thermal-optran.cir deleted file mode 100644 index a9fc6d0b7..000000000 --- a/examples/optran/F5TurboV2thermal-optran.cir +++ /dev/null @@ -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 diff --git a/examples/optran/F5models.lib b/examples/optran/F5models.lib deleted file mode 100644 index b1e8b3c46..000000000 --- a/examples/optran/F5models.lib +++ /dev/null @@ -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 diff --git a/examples/optran/contents.txt b/examples/optran/contents.txt index 16ac7920a..a9cfbbddb 100644 --- a/examples/optran/contents.txt +++ b/examples/optran/contents.txt @@ -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 diff --git a/examples/optran/script-optran.txt b/examples/optran/script-optran.txt deleted file mode 100644 index 8da005aeb..000000000 --- a/examples/optran/script-optran.txt +++ /dev/null @@ -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 \ No newline at end of file diff --git a/examples/probe/F5models.lib b/examples/probe/F5models.lib index ef74eb2f5..2b9086554 100644 --- a/examples/probe/F5models.lib +++ b/examples/probe/F5models.lib @@ -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 diff --git a/examples/probe/VDMOS_models.lib b/examples/probe/VDMOS_models.lib index b53103398..a95cfe5f5 100644 --- a/examples/probe/VDMOS_models.lib +++ b/examples/probe/VDMOS_models.lib @@ -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 diff --git a/examples/soi/ring51_40.sp b/examples/soi/ring51_40.sp index 0c833466a..fa583f81e 100644 --- a/examples/soi/ring51_40.sp +++ b/examples/soi/ring51_40.sp @@ -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) diff --git a/examples/various/mtimeavg_test.cir b/examples/various/mtimeavg_test.cir new file mode 100644 index 000000000..90b8068b5 --- /dev/null +++ b/examples/various/mtimeavg_test.cir @@ -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 diff --git a/examples/various/transformers1.cir b/examples/various/transformers1.cir index cf26601b4..6e9b224ab 100644 --- a/examples/various/transformers1.cir +++ b/examples/various/transformers1.cir @@ -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 diff --git a/examples/vdmos/100W.sp b/examples/vdmos/100W.sp index c8e7d2962..6fcd63d00 100644 --- a/examples/vdmos/100W.sp +++ b/examples/vdmos/100W.sp @@ -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 diff --git a/examples/vdmos/100W_wingspread.sp b/examples/vdmos/100W_wingspread.sp index 3af6383e5..5e18917db 100644 --- a/examples/vdmos/100W_wingspread.sp +++ b/examples/vdmos/100W_wingspread.sp @@ -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 diff --git a/examples/vdmos/crss_coss_ciss.sp b/examples/vdmos/crss_coss_ciss.sp index 44f44bb94..6ff310399 100644 --- a/examples/vdmos/crss_coss_ciss.sp +++ b/examples/vdmos/crss_coss_ciss.sp @@ -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 diff --git a/examples/vdmos/dcdc.sp b/examples/vdmos/dcdc.sp index 6e32a54de..46b239b89 100644 --- a/examples/vdmos/dcdc.sp +++ b/examples/vdmos/dcdc.sp @@ -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) diff --git a/examples/vdmos/self-heating.sp b/examples/vdmos/self-heating.sp index 5de456a2b..90edbc847 100644 --- a/examples/vdmos/self-heating.sp +++ b/examples/vdmos/self-heating.sp @@ -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 diff --git a/examples/vdmos/soa_chk.sp b/examples/vdmos/soa_chk.sp index ea84d89f2..8d1278185 100644 --- a/examples/vdmos/soa_chk.sp +++ b/examples/vdmos/soa_chk.sp @@ -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 diff --git a/src/Makefile.am b/src/Makefile.am index d1cedb9bf..76dad79db 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 diff --git a/src/frontend/breakp.c b/src/frontend/breakp.c index 5dae629bc..8fd822eef 100644 --- a/src/frontend/breakp.c +++ b/src/frontend/breakp.c @@ -517,7 +517,7 @@ ft_bpcheck(struct plot *runplot, int iteration) if ((howmanysteps > 0) && (--howmanysteps == 0)) { if (steps > 1) - fprintf(cp_err, "Stopped after %d steps.\n", steps); + fprintf(cp_out, "Note: Stopped after %d steps.\n", steps); return (FALSE); } @@ -694,3 +694,14 @@ printcond(struct dbcomm *d, FILE *fp) } } } + + +/* just check if we are in 'step' mode */ +bool +ft_stepcheck(void) +{ + if ((steps > 0) && (howmanysteps == 0)) { + return (TRUE); + } + return (FALSE); +} diff --git a/src/frontend/com_dl.c b/src/frontend/com_dl.c index c2d3f4e49..6cc5202e9 100644 --- a/src/frontend/com_dl.c +++ b/src/frontend/com_dl.c @@ -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); } diff --git a/src/frontend/com_fft.c b/src/frontend/com_fft.c index 2d592525b..062f40977 100644 --- a/src/frontend/com_fft.c +++ b/src/frontend/com_fft.c @@ -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 */ diff --git a/src/frontend/com_measure2.c b/src/frontend/com_measure2.c index 7fa30d352..29b6e63c9 100644 --- a/src/frontend/com_measure2.c +++ b/src/frontend/com_measure2.c @@ -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); diff --git a/src/frontend/evaluate.c b/src/frontend/evaluate.c index 42fc4540b..01127e1d0 100644 --- a/src/frontend/evaluate.c +++ b/src/frontend/evaluate.c @@ -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, diff --git a/src/frontend/fourier.c b/src/frontend/fourier.c index d66efe3ee..5754700a3 100644 --- a/src/frontend/fourier.c +++ b/src/frontend/fourier.c @@ -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; diff --git a/src/frontend/inpc_probe.c b/src/frontend/inpc_probe.c index 600ee1913..5a7a91f54 100644 --- a/src/frontend/inpc_probe.c +++ b/src/frontend/inpc_probe.c @@ -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) diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index c388d667e..be727600e 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -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; diff --git a/src/frontend/linear.c b/src/frontend/linear.c index 3fc903824..ca44d7d8f 100644 --- a/src/frontend/linear.c +++ b/src/frontend/linear.c @@ -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; diff --git a/src/frontend/miscvars.c b/src/frontend/miscvars.c index 9632ef862..c157a9666 100644 --- a/src/frontend/miscvars.c +++ b/src/frontend/miscvars.c @@ -76,6 +76,7 @@ char *ft_setkwords[] = { "lprplot5", "lprps", "maxwins", + "measureprec", "modelcard", "modelline", "moremode", diff --git a/src/frontend/numparam/numparam.h b/src/frontend/numparam/numparam.h index 148311149..fd8935d26 100644 --- a/src/frontend/numparam/numparam.h +++ b/src/frontend/numparam/numparam.h @@ -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; diff --git a/src/frontend/numparam/spicenum.c b/src/frontend/numparam/spicenum.c index 7832a37b7..7c38093c0 100644 --- a/src/frontend/numparam/spicenum.c +++ b/src/frontend/numparam/spicenum.c @@ -672,6 +672,7 @@ nupa_eval(struct card *card) dicoS->srcline = linenum; dicoS->oldline = orig_linenum; + dicoS->cardline = s; c = dicoS->dyncategory[linenum]; diff --git a/src/frontend/numparam/xpressn.c b/src/frontend/numparam/xpressn.c index ec1c55f8b..57fde2af3 100644 --- a/src/frontend/numparam/xpressn.c +++ b/src/frontend/numparam/xpressn.c @@ -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"); diff --git a/src/frontend/options.c b/src/frontend/options.c index 7dfe6f97a..6e14d99b0 100644 --- a/src/frontend/options.c +++ b/src/frontend/options.c @@ -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) { diff --git a/src/frontend/parse.c b/src/frontend/parse.c index f575ecbe7..24cc1e9e7 100644 --- a/src/frontend/parse.c +++ b/src/frontend/parse.c @@ -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 } }; diff --git a/src/frontend/rawfile.c b/src/frontend/rawfile.c index 4a1359163..1ecf834b5 100644 --- a/src/frontend/rawfile.c +++ b/src/frontend/rawfile.c @@ -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"); diff --git a/src/frontend/runcoms2.c b/src/frontend/runcoms2.c index baf43ee79..1e98f0073 100644 --- a/src/frontend/runcoms2.c +++ b/src/frontend/runcoms2.c @@ -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; diff --git a/src/include/cppduals/duals/dual b/src/include/cppduals/duals/dual index 4cb227e84..1e46b4c23 100644 --- a/src/include/cppduals/duals/dual +++ b/src/include/cppduals/duals/dual @@ -485,9 +485,6 @@ struct is_arithmetic> : is_arithmetic {}; #endif // CPPDUALS_ENABLE_IS_ARITHMETIC -/// Duals are compound types. -template -struct is_compound> : true_type {}; // Modification of std::numeric_limits<> per // C++03 17.4.3.1/1, and C++11 18.3.2.3/1. diff --git a/src/include/ngspice/fteext.h b/src/include/ngspice/fteext.h index 541c7f8c0..cb6fffd81 100644 --- a/src/include/ngspice/fteext.h +++ b/src/include/ngspice/fteext.h @@ -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 diff --git a/src/main.c b/src/main.c index c547d5475..01702c1f2 100644 --- a/src/main.c +++ b/src/main.c @@ -755,6 +755,8 @@ show_help(void) " -t, --term=TERM set the terminal type\n" " -h, --help display this help and exit\n" " -v, --version output version information and exit\n" + " -f, --version-full output full version information\n" + " --version-small output small version information\n" "\n" "Report bugs to %s.\n", cp_program, Bug_Addr); } @@ -952,6 +954,8 @@ int main(int argc, char **argv) {"define", required_argument, NULL, 'D'}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'v'}, + {"version-full", no_argument, NULL, 'f'}, + {"version-small", no_argument, NULL, 256}, {"batch", no_argument, NULL, 'b'}, {"autorun", no_argument, NULL, 'a'}, {"circuitfile", required_argument, NULL, 'c'}, @@ -969,7 +973,7 @@ int main(int argc, char **argv) int option_index = 0; - int c = getopt_long(argc, argv, "D:hvbac:ino:pqr:st:", + int c = getopt_long(argc, argv, "D:hvfbac:ino:pqr:st:", long_options, &option_index); if (c == -1) { @@ -1004,6 +1008,22 @@ int main(int argc, char **argv) sp_shutdown(EXIT_INFO); break; + case 'f': /* Full version info */ + { + wordlist wl = { "-f", NULL, NULL }; + com_version(&wl); + sp_shutdown(EXIT_INFO); + } + break; + + case 256: /* --version-small */ + { + wordlist wl = { "-s", NULL, NULL }; + com_version(&wl); + sp_shutdown(EXIT_INFO); + } + break; + case 'b': /* Batch mode */ { bool x_false = FALSE; diff --git a/src/maths/cmaths/cmath2.c b/src/maths/cmaths/cmath2.c index 7af7cd84e..d6ce651af 100644 --- a/src/maths/cmaths/cmath2.c +++ b/src/maths/cmaths/cmath2.c @@ -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) { diff --git a/src/maths/cmaths/cmath4.c b/src/maths/cmaths/cmath4.c index 63b03f0a6..04b0b5142 100644 --- a/src/maths/cmaths/cmath4.c +++ b/src/maths/cmaths/cmath4.c @@ -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); +} + diff --git a/src/maths/cmaths/cmath4.h b/src/maths/cmaths/cmath4.h index 5b52f90b2..f4f9111d4 100644 --- a/src/maths/cmaths/cmath4.h +++ b/src/maths/cmaths/cmath4.h @@ -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 diff --git a/src/ngsconvert.c b/src/ngsconvert.c index c3396f461..01c4d768d 100644 --- a/src/ngsconvert.c +++ b/src/ngsconvert.c @@ -21,6 +21,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group #include +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) { } diff --git a/src/spicelib/analysis/dctran.c b/src/spicelib/analysis/dctran.c index 4c55678d5..033ca6a61 100644 --- a/src/spicelib/analysis/dctran.c +++ b/src/spicelib/analysis/dctran.c @@ -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); +} diff --git a/src/spicelib/analysis/noisean.c b/src/spicelib/analysis/noisean.c index 3eeca41f2..29f880452 100644 --- a/src/spicelib/analysis/noisean.c +++ b/src/spicelib/analysis/noisean.c @@ -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 diff --git a/src/spicelib/devices/bsim4/b4.c b/src/spicelib/devices/bsim4/b4.c index 438c1498b..83f3115e5 100644 --- a/src/spicelib/devices/bsim4/b4.c +++ b/src/spicelib/devices/bsim4/b4.c @@ -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"), diff --git a/src/spicelib/devices/bsim4/b4ask.c b/src/spicelib/devices/bsim4/b4ask.c index d43e1a708..abced660c 100644 --- a/src/spicelib/devices/bsim4/b4ask.c +++ b/src/spicelib/devices/bsim4/b4ask.c @@ -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); diff --git a/src/spicelib/devices/bsim4/b4par.c b/src/spicelib/devices/bsim4/b4par.c index ac4a274c5..44373bfd6 100644 --- a/src/spicelib/devices/bsim4/b4par.c +++ b/src/spicelib/devices/bsim4/b4par.c @@ -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; diff --git a/src/spicelib/devices/bsim4/b4set.c b/src/spicelib/devices/bsim4/b4set.c index 71bc75a81..0e91f37d3 100644 --- a/src/spicelib/devices/bsim4/b4set.c +++ b/src/spicelib/devices/bsim4/b4set.c @@ -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 diff --git a/src/spicelib/devices/bsim4/bsim4def.h b/src/spicelib/devices/bsim4/bsim4def.h index 6d7d652e8..17f810a19 100644 --- a/src/spicelib/devices/bsim4/bsim4def.h +++ b/src/spicelib/devices/bsim4/bsim4def.h @@ -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 diff --git a/src/spicelib/devices/bsim4v5/b4v5.c b/src/spicelib/devices/bsim4v5/b4v5.c index 2d920af47..30d05ac74 100644 --- a/src/spicelib/devices/bsim4v5/b4v5.c +++ b/src/spicelib/devices/bsim4v5/b4v5.c @@ -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"), diff --git a/src/spicelib/devices/bsim4v5/b4v5ask.c b/src/spicelib/devices/bsim4v5/b4v5ask.c index 95ae3c800..829bb3e4c 100644 --- a/src/spicelib/devices/bsim4v5/b4v5ask.c +++ b/src/spicelib/devices/bsim4v5/b4v5ask.c @@ -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); diff --git a/src/spicelib/devices/bsim4v5/b4v5par.c b/src/spicelib/devices/bsim4v5/b4v5par.c index 1013ce700..f3c07dee7 100644 --- a/src/spicelib/devices/bsim4v5/b4v5par.c +++ b/src/spicelib/devices/bsim4v5/b4v5par.c @@ -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; diff --git a/src/spicelib/devices/bsim4v5/b4v5set.c b/src/spicelib/devices/bsim4v5/b4v5set.c index d16f3747b..9214bc3ca 100644 --- a/src/spicelib/devices/bsim4v5/b4v5set.c +++ b/src/spicelib/devices/bsim4v5/b4v5set.c @@ -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 */ diff --git a/src/spicelib/devices/bsim4v5/bsim4v5def.h b/src/spicelib/devices/bsim4v5/bsim4v5def.h index 2120a59d3..f397af3b7 100644 --- a/src/spicelib/devices/bsim4v5/bsim4v5def.h +++ b/src/spicelib/devices/bsim4v5/bsim4v5def.h @@ -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 diff --git a/src/spicelib/devices/bsim4v6/b4v6.c b/src/spicelib/devices/bsim4v6/b4v6.c index 1ecb91625..ee160010d 100644 --- a/src/spicelib/devices/bsim4v6/b4v6.c +++ b/src/spicelib/devices/bsim4v6/b4v6.c @@ -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"), diff --git a/src/spicelib/devices/bsim4v6/b4v6ask.c b/src/spicelib/devices/bsim4v6/b4v6ask.c index 64ce8b7bc..d9a025f0e 100644 --- a/src/spicelib/devices/bsim4v6/b4v6ask.c +++ b/src/spicelib/devices/bsim4v6/b4v6ask.c @@ -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); diff --git a/src/spicelib/devices/bsim4v6/b4v6par.c b/src/spicelib/devices/bsim4v6/b4v6par.c index 795fdc77c..f9430ab78 100644 --- a/src/spicelib/devices/bsim4v6/b4v6par.c +++ b/src/spicelib/devices/bsim4v6/b4v6par.c @@ -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; diff --git a/src/spicelib/devices/bsim4v6/b4v6set.c b/src/spicelib/devices/bsim4v6/b4v6set.c index 4ad739c34..3bf919304 100644 --- a/src/spicelib/devices/bsim4v6/b4v6set.c +++ b/src/spicelib/devices/bsim4v6/b4v6set.c @@ -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 */ diff --git a/src/spicelib/devices/bsim4v6/bsim4v6def.h b/src/spicelib/devices/bsim4v6/bsim4v6def.h index 94ee3b0c0..28f2aba35 100644 --- a/src/spicelib/devices/bsim4v6/bsim4v6def.h +++ b/src/spicelib/devices/bsim4v6/bsim4v6def.h @@ -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 diff --git a/src/spicelib/devices/bsim4v7/b4v7.c b/src/spicelib/devices/bsim4v7/b4v7.c index f1d70b209..cb46a904c 100644 --- a/src/spicelib/devices/bsim4v7/b4v7.c +++ b/src/spicelib/devices/bsim4v7/b4v7.c @@ -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"), diff --git a/src/spicelib/devices/bsim4v7/b4v7ask.c b/src/spicelib/devices/bsim4v7/b4v7ask.c index 19690eda9..f20dc692b 100644 --- a/src/spicelib/devices/bsim4v7/b4v7ask.c +++ b/src/spicelib/devices/bsim4v7/b4v7ask.c @@ -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); diff --git a/src/spicelib/devices/bsim4v7/b4v7par.c b/src/spicelib/devices/bsim4v7/b4v7par.c index d8bdd6d3d..e4c5a099a 100644 --- a/src/spicelib/devices/bsim4v7/b4v7par.c +++ b/src/spicelib/devices/bsim4v7/b4v7par.c @@ -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; diff --git a/src/spicelib/devices/bsim4v7/b4v7set.c b/src/spicelib/devices/bsim4v7/b4v7set.c index ed2fd017f..1d3246b47 100644 --- a/src/spicelib/devices/bsim4v7/b4v7set.c +++ b/src/spicelib/devices/bsim4v7/b4v7set.c @@ -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 */ diff --git a/src/spicelib/devices/bsim4v7/bsim4v7def.h b/src/spicelib/devices/bsim4v7/bsim4v7def.h index e4c1f1adc..073bec7ff 100644 --- a/src/spicelib/devices/bsim4v7/bsim4v7def.h +++ b/src/spicelib/devices/bsim4v7/bsim4v7def.h @@ -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 diff --git a/src/spicelib/devices/dev.c b/src/spicelib/devices/dev.c index 3e07b1beb..b3514919e 100644 --- a/src/spicelib/devices/dev.c +++ b/src/spicelib/devices/dev.c @@ -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; } diff --git a/src/spicelib/devices/dio/dio.c b/src/spicelib/devices/dio/dio.c index 2ebeb2e41..c7b160f79 100644 --- a/src/spicelib/devices/dio/dio.c +++ b/src/spicelib/devices/dio/dio.c @@ -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"), diff --git a/src/spicelib/devices/dio/dioacld.c b/src/spicelib/devices/dio/dioacld.c index 62ad65efd..62116d8f5 100644 --- a/src/spicelib/devices/dio/dioacld.c +++ b/src/spicelib/devices/dio/dioacld.c @@ -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); diff --git a/src/spicelib/devices/dio/dioask.c b/src/spicelib/devices/dio/dioask.c index 67009b889..e40d5c4d0 100644 --- a/src/spicelib/devices/dio/dioask.c +++ b/src/spicelib/devices/dio/dioask.c @@ -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); diff --git a/src/spicelib/devices/dio/diobindCSC.c b/src/spicelib/devices/dio/diobindCSC.c index 29cee9cff..89994448e 100644 --- a/src/spicelib/devices/dio/diobindCSC.c +++ b/src/spicelib/devices/dio/diobindCSC.c @@ -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); + } } } diff --git a/src/spicelib/devices/dio/diodefs.h b/src/spicelib/devices/dio/diodefs.h index 298f330b9..0a1f056a8 100644 --- a/src/spicelib/devices/dio/diodefs.h +++ b/src/spicelib/devices/dio/diodefs.h @@ -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, diff --git a/src/spicelib/devices/dio/dioload.c b/src/spicelib/devices/dio/dioload.c index d7243d5b1..80ade0970 100644 --- a/src/spicelib/devices/dio/dioload.c +++ b/src/spicelib/devices/dio/dioload.c @@ -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); diff --git a/src/spicelib/devices/dio/diomask.c b/src/spicelib/devices/dio/diomask.c index 1f4e11ce5..f786f96c9 100644 --- a/src/spicelib/devices/dio/diomask.c +++ b/src/spicelib/devices/dio/diomask.c @@ -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); diff --git a/src/spicelib/devices/dio/diompar.c b/src/spicelib/devices/dio/diompar.c index 498421160..a6780034b 100644 --- a/src/spicelib/devices/dio/diompar.c +++ b/src/spicelib/devices/dio/diompar.c @@ -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; diff --git a/src/spicelib/devices/dio/diosetup.c b/src/spicelib/devices/dio/diosetup.c index df9555be8..867b7562c 100644 --- a/src/spicelib/devices/dio/diosetup.c +++ b/src/spicelib/devices/dio/diosetup.c @@ -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; diff --git a/src/spicelib/devices/dio/diotrunc.c b/src/spicelib/devices/dio/diotrunc.c index b940528be..04070a1d8 100644 --- a/src/spicelib/devices/dio/diotrunc.c +++ b/src/spicelib/devices/dio/diotrunc.c @@ -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); diff --git a/src/spicelib/devices/isrc/isrcload.c b/src/spicelib/devices/isrc/isrcload.c index d88cc4072..67e96e3bf 100644 --- a/src/spicelib/devices/isrc/isrcload.c +++ b/src/spicelib/devices/isrc/isrcload.c @@ -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 diff --git a/src/spicelib/devices/vdmos/vdmosconv.c b/src/spicelib/devices/vdmos/vdmosconv.c index 49e0ccde8..2bbed8050 100644 --- a/src/spicelib/devices/vdmos/vdmosconv.c +++ b/src/spicelib/devices/vdmos/vdmosconv.c @@ -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) - diff --git a/src/spicelib/devices/vdmos/vdmosset.c b/src/spicelib/devices/vdmos/vdmosset.c index dfc6a2da3..0adfce318 100644 --- a/src/spicelib/devices/vdmos/vdmosset.c +++ b/src/spicelib/devices/vdmos/vdmosset.c @@ -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; diff --git a/src/spicelib/devices/vdmos/vdmostemp.c b/src/spicelib/devices/vdmos/vdmostemp.c index 202a4611a..36010a87f 100644 --- a/src/spicelib/devices/vdmos/vdmostemp.c +++ b/src/spicelib/devices/vdmos/vdmostemp.c @@ -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)); diff --git a/src/spicelib/devices/vsrc/vsrcacct.c b/src/spicelib/devices/vsrc/vsrcacct.c index cd7d1111a..6835cd0df 100644 --- a/src/spicelib/devices/vsrc/vsrcacct.c +++ b/src/spicelib/devices/vsrc/vsrcacct.c @@ -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; diff --git a/src/spicelib/devices/vsrc/vsrcload.c b/src/spicelib/devices/vsrc/vsrcload.c index 0ecf99c25..3e2f86b8e 100644 --- a/src/spicelib/devices/vsrc/vsrcload.c +++ b/src/spicelib/devices/vsrc/vsrcload.c @@ -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 diff --git a/src/spicelib/parser/inp2n.c b/src/spicelib/parser/inp2n.c index ef6c9a742..b01d8b44c 100644 --- a/src/spicelib/parser/inp2n.c +++ b/src/spicelib/parser/inp2n.c @@ -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); diff --git a/src/spicelib/parser/inpdoopt.c b/src/spicelib/parser/inpdoopt.c index 61d44ba0a..84fb5429c 100644 --- a/src/spicelib/parser/inpdoopt.c +++ b/src/spicelib/parser/inpdoopt.c @@ -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); + } } } diff --git a/src/spicelib/parser/inpdpar.c b/src/spicelib/parser/inpdpar.c index 0aab07537..1d2c67ba8 100644 --- a/src/spicelib/parser/inpdpar.c +++ b/src/spicelib/parser/inpdpar.c @@ -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; diff --git a/src/winmain.c b/src/winmain.c index a851f4242..ee19a73c6 100644 --- a/src/winmain.c +++ b/src/winmain.c @@ -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); diff --git a/src/xspice/enh/enhtrans.c b/src/xspice/enh/enhtrans.c index 649724748..44a2b7a59 100644 --- a/src/xspice/enh/enhtrans.c +++ b/src/xspice/enh/enhtrans.c @@ -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); diff --git a/src/xspice/icm/spice2poly/icm_spice2poly/cfunc.mod b/src/xspice/icm/spice2poly/icm_spice2poly/cfunc.mod index df6fdff20..b869d0845 100644 --- a/src/xspice/icm/spice2poly/icm_spice2poly/cfunc.mod +++ b/src/xspice/icm/spice2poly/icm_spice2poly/cfunc.mod @@ -47,7 +47,7 @@ required syntax. This model may also be called directly as follows: a1 [ ] xxx - .model xxx spice2poly ( coef = [ ] ) + .model xxx spice2poly ( coef = [ ] [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 */ diff --git a/src/xspice/icm/spice2poly/icm_spice2poly/ifspec.ifs b/src/xspice/icm/spice2poly/icm_spice2poly/ifspec.ifs index 6aab4de10..02f4b6387 100644 --- a/src/xspice/icm/spice2poly/icm_spice2poly/ifspec.ifs +++ b/src/xspice/icm/spice2poly/icm_spice2poly/ifspec.ifs @@ -16,7 +16,8 @@ AUTHORS 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: diff --git a/visualc/xspice/spice2poly.vcxproj b/visualc/xspice/spice2poly.vcxproj index 0379e7691..408c46b0f 100644 --- a/visualc/xspice/spice2poly.vcxproj +++ b/visualc/xspice/spice2poly.vcxproj @@ -210,6 +210,7 @@ +