diff options
author | rahulp13 | 2020-03-03 05:31:58 +0530 |
---|---|---|
committer | rahulp13 | 2020-03-03 05:31:58 +0530 |
commit | dfc268e0863c913a1b8726cd54eea3b40caf7c67 (patch) | |
tree | 1cd82634684da5ae86b558d44756189e080545d4 /Windows/spice/examples/Monte_Carlo | |
parent | fd62c52150c7d1f81da8060b2f5db6b94d174ccf (diff) | |
download | eSim-dfc268e0863c913a1b8726cd54eea3b40caf7c67.tar.gz eSim-dfc268e0863c913a1b8726cd54eea3b40caf7c67.tar.bz2 eSim-dfc268e0863c913a1b8726cd54eea3b40caf7c67.zip |
upgrade ngspice to v31
Diffstat (limited to 'Windows/spice/examples/Monte_Carlo')
-rw-r--r-- | Windows/spice/examples/Monte_Carlo/MC_2_control.sp | 22 | ||||
-rw-r--r-- | Windows/spice/examples/Monte_Carlo/MC_ring.sp | 129 | ||||
-rw-r--r-- | Windows/spice/examples/Monte_Carlo/MC_ring_ts.sp | 180 | ||||
-rw-r--r-- | Windows/spice/examples/Monte_Carlo/MonteCarlo.sp | 16 | ||||
-rw-r--r-- | Windows/spice/examples/Monte_Carlo/OpWien.sp | 8 | ||||
-rw-r--r-- | Windows/spice/examples/Monte_Carlo/mc_ring_circ.net | 56 | ||||
-rw-r--r-- | Windows/spice/examples/Monte_Carlo/mc_ring_lib_complete_actual.cir | 212 | ||||
-rw-r--r-- | Windows/spice/examples/Monte_Carlo/rand_numb_test.cir | 40 |
8 files changed, 595 insertions, 68 deletions
diff --git a/Windows/spice/examples/Monte_Carlo/MC_2_control.sp b/Windows/spice/examples/Monte_Carlo/MC_2_control.sp index 9b9f3606..d155c877 100644 --- a/Windows/spice/examples/Monte_Carlo/MC_2_control.sp +++ b/Windows/spice/examples/Monte_Carlo/MC_2_control.sp @@ -1,16 +1,16 @@ +*ng_script * Perform Monte Carlo simulation in ngspice * script for use with 25 stage Ring-Osc. BSIM3 * circuit is in MC_2_circ.sp -* edit 'set sourcepath' for your path to circuit file +* edit 'setcs sourcepath' for your path to circuit file * start script by 'ngspice -o MC_2_control.log MC_2_control.sp' * .control - save buf $ we just need output vector buf, save memory by more than 10x - let mc_runs = 100 $ number of runs for monte carlo - let run = 1 $ number of the actual run + let mc_runs = 10 $ number of runs for monte carlo + let run = 1 $ number of the actual run * Where to find the circuit netlist file MC_2_circ.sp - set sourcepath = ( D:\Spice_general\ngspice\examples\Monte_Carlo ) + setcs sourcepath = ( D:\Spice_general\ngspice\examples\Monte_Carlo ) * create file for frequency information echo Monte Carlo, frequency of R.O. > MC_frequ.log @@ -19,10 +19,14 @@ dowhile run <= mc_runs * without the reset switch there is some strange drift * towards lower and lower frequencies - reset - set run ="$&run" $ create a variable from the vector - set rndseed = $run $ set the rnd seed value to the loop index - source MC_2_circ.sp $ load the circuit, including model data + set run = $&run $ create a variable from the vector + setseed $run $ set the rnd seed value to the loop index + if run = 1 + source MC_2_circ.sp $ load the circuit once from file, including model data + else + mc_source $ re-load the circuit from internal storage + end + save buf $ we just need output vector buf, save memory by more than 10x tran 15p 200n 0 write mc_ring{$run}.out buf $ write each sim output to its own rawfile linearize buf $ lienarize buf to allow fft diff --git a/Windows/spice/examples/Monte_Carlo/MC_ring.sp b/Windows/spice/examples/Monte_Carlo/MC_ring.sp index 58e5c141..3ffab2a3 100644 --- a/Windows/spice/examples/Monte_Carlo/MC_ring.sp +++ b/Windows/spice/examples/Monte_Carlo/MC_ring.sp @@ -1,5 +1,9 @@ Perform Monte Carlo simulation in ngspice -* 25 stage Ring-Osc. BSIM3 +* 25 stage Ring-Osc. BSIM3 with statistical variation of various model parameters +* cd into ngspice/examples/Monte_Carlo +* start in interactive mode 'ngspice MC_ring.sp' with several plots for output +* or start in batch mode, controlled by .control section (Control mode) +* with 'ngspice -b -r MC_ring.raw -o MC_ring.log MC_ring.sp'. vin in out dc 0.5 pulse 0.5 0 0.1n 5n 1 1 1 vdd dd 0 dc 3.3 @@ -31,7 +35,7 @@ cout buf ss 0.2pF .options noacct .control save buf $ we just need buf, save memory by more than 10x - let mc_runs = 10 $ number of runs for monte carlo + let mc_runs = 30 $ number of runs for monte carlo let run = 0 $ number of actual run set curplot = new $ create a new plot set curplottitle = "Transient outputs" @@ -60,52 +64,64 @@ cout buf ss 0.2pF * of the BSIM3 model for the NMOS and PMOS transistors. * We may obtain the nominal values (nom) by manually extracting them from * the parameter set. Here we get them automatically and store them into -* variables. This has the advantage that you may change the parameter set +* vectors. This has the advantage that you may change the parameter set * without having to look up the values again. - set n1vth0=@n1[vth0] - set n1u0=@n1[u0] - set n1tox=@n1[tox] - set n1lint=@n1[lint] - set n1wint=@n1[wint] - set p1vth0=@p1[vth0] - set p1u0=@p1[u0] - set p1tox=@p1[tox] - set p1lint=@p1[lint] - set p1wint=@p1[wint] + let n1vth0=@n1[vth0] + let n1u0=@n1[u0] + let n1tox=@n1[tox] + let n1lint=@n1[lint] + let n1wint=@n1[wint] + let p1vth0=@p1[vth0] + let p1u0=@p1[u0] + let p1tox=@p1[tox] + let p1lint=@p1[lint] + let p1wint=@p1[wint] + * * run the simulation loop dowhile run <= mc_runs - * without the reset switch there is some strange drift - * towards lower and lower frequencies - reset * run=0 simulates with nominal parameters if run > 0 - altermod @n1[vth0]=gauss($n1vth0, 0.1, 3) - altermod @n1[u0]=gauss($n1u0, 0.05, 3) - altermod @n1[tox]=gauss($n1tox, 0.1, 3) - altermod @n1[lint]=gauss($n1lint, 0.1, 3) - altermod @n1[wint]=gauss($n1wint, 0.1, 3) - altermod @p1[vth0]=gauss($p1vth0, 0.1, 3) - altermod @p1[u0]=gauss($p1u0, 0.1, 3) - altermod @p1[tox]=gauss($p1tox, 0.1, 3) - altermod @p1[lint]=gauss($p1lint, 0.1, 3) - altermod @p1[wint]=gauss($p1wint, 0.1, 3) + setplot $max_fft + altermod @n1[vth0] = gauss(n1vth0, 0.1, 3) + altermod @n1[u0] = gauss(n1u0, 0.05, 3) + altermod @n1[tox] = gauss(n1tox, 0.1, 3) + altermod @n1[lint] = gauss(n1lint, 0.1, 3) + altermod @n1[wint] = gauss(n1wint, 0.1, 3) + altermod @p1[vth0] = gauss(p1vth0, 0.1, 3) + altermod @p1[u0] = gauss(p1u0, 0.1, 3) + altermod @p1[tox] = gauss(p1tox, 0.1, 3 ) + altermod @p1[lint] = gauss(p1lint, 0.1, 3) + altermod @p1[wint] = gauss(p1wint, 0.1, 3) end - tran 15p 50n 0 -* select stop and step so that number of data points after linearization is not too + tran 15p 100n 0 +* select stop and step so that number of data points after linearization is not too * close to 8192, which would yield varying number of line length and thus scale for fft. * * We have to figure out what to do if a single simulation will not converge. -* Is there a variable which may be set if there is no convergence? -* Then we might skip this run and continue with a new run. It does not exist for now. -* So we have to rely on the robustness of the following steps not leading -* to a seg fault if the tran data are missing. +* There is the variable 'sim_status' which is set to 1 if the simulation +* fails with ’xx simulation(s) aborted’, e.g. because of non-convergence. +* Then we might skip this run and continue with a new run. * + echo Simulation status $sim_status + let simstat = $sim_status + if simstat = 1 + if run = mc_runs + echo go to end + else + echo go to next run + end + destroy $curplot + goto next + end + set run ="$&run" $ create a variable from the vector set mc_runs ="$&mc_runs" $ create a variable from the vector echo simulation run no. $run of $mc_runs + set dt = $curplot * save the linearized data for having equal time scales for all runs linearize buf $ linearize only buf, no other vectors needed + destroy $dt $ delete the tran i plot set dt = $curplot $ store the current plot to dt (tran i+1) setplot $plot_out $ make 'plt_out' the active plot * firstly save the time scale once to become the default scale @@ -115,11 +131,14 @@ cout buf ss 0.2pF let vout{$run}={$dt}.buf $ store the output vector to plot 'plot_out' setplot $dt $ go back to the previous plot (tran i+1) fft buf $ run fft on vector buf + destroy $dt $ delete the tran i+1 plot let buf2=db(mag(buf)) * find the frequency where buf has its maximum of the fft signal meas sp fft_max MAX_AT buf2 from=0.1G to=0.7G * find the frequency where buf is -40dB at rising fft signal - meas sp fft_40 WHEN buf2=-40 RISE=1 from=0.1G to=0.7G + meas sp fft_40 WHEN buf2=-40 RISE=1 from=0.1G to=0.7G + echo + echo * store the fft vector set dt = $curplot $ store the current plot to dt (spec i) setplot $plot_fft $ make 'plot_fft' the active plot @@ -130,19 +149,26 @@ cout buf ss 0.2pF * store the measured value setplot $max_fft $ make 'max_fft' the active plot let maxffts[{$run}]={$dt}.fft_max - let halfffts[{$run}]={$dt}.fft_40 -* setplot $plot_out -* The following command does not work here. Why not? Probably not a real copy. -* destroy $dt $ save memory, we don't need this plot (spec) any more - setplot $dt $ go back to the previous plot + let halfffts[{$run}]={$dt}.fft_40 let run = run + 1 + label next + reset end ***** plotting ********************************************************** -* plot {$plot_out}.allv - plot {$plot_out}.vout0 $ just plot the tran output with nominal parameters -* setplot $plot_fft -* plot db(mag(ally)) xlimit .1G 1G ylimit -80 10 - plot db(mag({$plot_fft}.ally)) xlimit .1G 1G ylimit -80 10 +if $?batchmode + echo + echo Plotting not available in batch mode + echo Write linearized vout0 to vout{$mc_runs} to rawfile $rawfile + echo + write $rawfile {$plot_out}.allv + rusage + quit +else + setplot $plot_out + plot vout0 ylabel 'RO output, original parameters' $ just plot the tran output with nominal parameters + setplot $plot_fft + settype decibel ally + plot db(mag(ally)) xlimit .1G 1G ylimit -80 10 ylabel 'fft output' * * create a histogram from vector maxffts setplot $max_fft $ make 'max_fft' the active plot @@ -158,7 +184,7 @@ cout buf ss 0.2pF * put data into the correct bins let run = 0 dowhile run < mc_runs - set run = "$&run" $ create a variable from the vector + set run = $&run $ create a variable from the vector let val = maxffts[{$run}] let part = 0 * Check if val fits into a bin. If yes, raise bin by 1 @@ -171,13 +197,22 @@ cout buf ss 0.2pF end let run = run + 1 end + * plot the histogram set plotstyle=combplot - plot yvec-1 vs xvec $ subtract 1 because with started with unitvec containing ones + plot yvec-1 vs xvec xlabel 'oscillation frequency' ylabel 'bin count' $ subtract 1 because we started with unitvec containing ones + + * plot simulation series + set plotstyle=linplot + let xx = vector(mc_runsp) + settype frequency maxffts + plot maxffts vs xx xlabel 'iteration no.' ylabel 'RO frequency' + * calculate jitter let diff40 = (vecmax(halfffts) - vecmin(halfffts))*1e-6 echo echo Max. jitter is "$&diff40" MHz +end rusage .endc ******************************************************************************** @@ -193,11 +228,11 @@ cout buf ss 0.2pF +k3b=2.233 +vsat=86301.58 ua=6.47e-9 ub=4.23e-18 uc=-4.706281e-11 +rdsw=650 u0=388.3203 wr=1 -+a0=.3496967 ags=.1 b0=0.546 b1=1 ++a0=.3496967 ags=.1 b0=0.546 b1=1 +dwg=-6.0e-09 dwb=-3.56e-09 prwb=-.213 +keta=-3.605872e-02 a1=2.778747e-02 a2=.9 +voff=-6.735529e-02 nfactor=1.139926 cit=1.622527e-04 -+cdsc=-2.147181e-05 ++cdsc=-2.147181e-05 +cdscb=0 dvt0w=0 dvt1w=0 dvt2w=0 +cdscd=0 prwg=0 +eta0=1.0281729e-02 etab=-5.042203e-03 diff --git a/Windows/spice/examples/Monte_Carlo/MC_ring_ts.sp b/Windows/spice/examples/Monte_Carlo/MC_ring_ts.sp new file mode 100644 index 00000000..ee88c329 --- /dev/null +++ b/Windows/spice/examples/Monte_Carlo/MC_ring_ts.sp @@ -0,0 +1,180 @@ +*ng_script +* Example script for Monte Carlo with commercial HSPICE-compatible libraries +* The circuit in mc_ring_circ.net is a 25-stage inverter ring oscillator. +* Add your library to mc_ring_circ.net and choose transistors accordingly. +* Add the source file and the library path. +* A simple BSIM3 inverter R.O. serves as an MC example wtihout need for a library. +.control +begin + let mc_runs = 30 $ number of runs for monte carlo + let run = 0 $ number of actual run + set curplot = new $ create a new plot + set curplottitle = "Transient outputs" + set plot_out = $curplot $ store its name to 'plot_out' + set curplot = new $ create a new plot + set curplottitle = "FFT outputs" + set plot_fft = $curplot $ store its name to 'plot_fft' + set curplot = new $ create a new plot + set curplottitle = "Oscillation frequency" + set max_fft = $curplot $ store its name to 'max_fft' + let mc_runsp = mc_runs + 1 + let maxffts = unitvec(mc_runsp) $ vector for storing max measure results + let halfffts = unitvec(mc_runsp)$ vector for storing measure results at -40dB rising + unlet mc_runsp + + set mc_runs = $&mc_runs $ create a variable from the vector + let seeds = mc_runs + 2 + setseed $&seeds + unlet seeds + + echo source the input file +* Path of your circuit file and library file here +* Will be added to the already existing sourcepath + setcs sourcepath = ( $inputdir $sourcepath ./ngspice/examples/Monte_Carlo ) +* source with file name of your circuit file + source mc_ring_circ.net + + save buf $ we just need buf, save memory by more than 10x + +* Output path (directory has already to be there) +* set outputpath = 'D:\Spice_general\ngspice\examples\Monte_Carlo\out' +* If your current directory is the 'ngspice' directory +* set outputpath = './examples/Monte_Carlo/out' $ LINUX alternative +* run the simulation loop + +* We have to figure out what to do if a single simulation will not converge. +* There is now the variable sim_status, that is 0 if simulation ended regularly, +* and 1 if the simulation has been aborted with error message '...simulation(s) aborted'. +* Then we skip the rest of the run and continue with a new run. + + dowhile run <= mc_runs + + set run = $&run $ create a variable from the vector + + * run=0 simulates with nominal parameters + if run > 0 + echo + echo * * * * * * + echo Source the circuit again internally for run no. $run + echo * * * * * * + setseed $run + mc_source $ re-source the input file + else + echo run no. $run + end + echo simulation run no. $run of $mc_runs + tran 100p 1000n 0 + echo Simulation status $sim_status + let simstat = $sim_status + if simstat = 1 + if run = mc_runs + echo go to end + else + echo go to next run + end + destroy $curplot + goto next + end + +* select stop and step so that number of data points after linearization is not too +* close to 8192, which would yield varying number of line length and thus scale for fft. +* + set dt0 = $curplot + * save the linearized data for having equal time scales for all runs + linearize buf $ linearize only buf, no other vectors needed + set dt1 = $curplot $ store the current plot to dt (tran i+1) + setplot $plot_out $ make 'plt_out' the active plot + * firstly save the time scale once to become the default scale + if run=0 + let time={$dt1}.time + end + let vout{$run}={$dt1}.buf $ store the output vector to plot 'plot_out' + setplot $dt1 $ go back to the previous plot (tran i+1) + fft buf $ run fft on vector buf + let buf2=db(mag(buf)) + * find the frequency where buf has its maximum of the fft signal + meas sp fft_max MAX_AT buf2 from=0.05G to=0.7G + * find the frequency where buf is -40dB at rising fft signal + meas sp fft_40 WHEN buf2=-40 RISE=1 from=0.05G to=0.7G + * store the fft vector + set dt2 = $curplot $ store the current plot to dt (spec i) + setplot $plot_fft $ make 'plot_fft' the active plot + if run=0 + let frequency={$dt2}.frequency + end + let fft{$run}={$dt2}.buf $ store the output vector to plot 'plot_fft' + settype decibel fft{$run} + * store the measured value + setplot $max_fft $ make 'max_fft' the active plot + let maxffts[{$run}]={$dt2}.fft_max + let halfffts[{$run}]={$dt2}.fft_40 + destroy $dt0 $dt1 $dt2 $ save memory, we don't need this plot (spec) any more + + label next + remcirc + let run = run + 1 + end +***** plotting ********************************************************** +if $?batchmode + echo + echo Plotting not available in batch mode + echo Write linearized vout0 to vout{$mc_runs} to rawfile $rawfile + echo + write $rawfile {$plot_out}.allv + rusage + quit +else + if $?sharedmode or $?win_console + gnuplot xnp_pl1 {$plot_out}.vout0 $ just plot the tran output with nominal parameters + else + plot {$plot_out}.vout0 $ just plot the tran output with nominal parameters + end + setplot $plot_fft + if $?sharedmode or $?win_console + gnuplot xnp_pl2 db(mag(ally)) xlimit 0 1G ylimit -80 10 + else + plot db(mag(ally)) xlimit 0 1G ylimit -80 10 + end +* +* create a histogram from vector maxffts + setplot $max_fft $ make 'max_fft' the active plot + set startfreq=50MEG + set bin_size=1MEG + set bin_count=100 + compose osc_frequ start=$startfreq step=$bin_size lin=$bin_count $ requires variables as parameters + settype frequency osc_frequ + let bin_count=$bin_count $ create a vector from the variable + let yvec=unitvec(bin_count) $ requires vector as parameter + let startfreq=$startfreq + let bin_size=$bin_size + * put data into the correct bins + let run = 0 + dowhile run < mc_runs + set run = $&run $ create a variable from the vector + let val = maxffts[{$run}] + let part = 0 + * Check if val fits into a bin. If yes, raise bin by 1 + dowhile part < bin_count + if ((val < (startfreq + (part+1)*bin_size)) & (val >= (startfreq + part*bin_size))) + let yvec[part] = yvec[part] + 1 + break + end + let part = part + 1 + end + let run = run + 1 + end + * plot the histogram + let count = yvec - 1 $ subtract 1 because we started with unitvec containing ones + if $?sharedmode or $?win_console + gnuplot np_pl3 count vs osc_frequ combplot + else + plot count vs osc_frequ combplot + end +* calculate jitter + let diff40 = (vecmax(halfffts) - vecmin(halfffts))*1e-6 + echo + echo Max. jitter is "$&diff40" MHz +end + rusage +* quit +end diff --git a/Windows/spice/examples/Monte_Carlo/MonteCarlo.sp b/Windows/spice/examples/Monte_Carlo/MonteCarlo.sp index 608dc4cf..e079893f 100644 --- a/Windows/spice/examples/Monte_Carlo/MonteCarlo.sp +++ b/Windows/spice/examples/Monte_Carlo/MonteCarlo.sp @@ -15,9 +15,9 @@ R2 0 OUT 141 let run = 0 set curplot=new $ create a new plot set scratch=$curplot $ store its name to 'scratch' - setplot $scratch $ make 'scratch' the active plot + setplot $scratch $ make 'scratch' the active plot let bwh=unitvec(mc_runs) $ create a vector in plot 'scratch' to store bandwidth data - + * define distributions for random numbers: * unif: uniform distribution, deviation relativ to nominal value * aunif: uniform distribution, deviation absolut @@ -47,19 +47,19 @@ R2 0 OUT 141 alter c3 = limit(250e-12, 25e-12) * ac oct 100 250K 10Meg -* +* * measure bandwidth at -10 dB meas ac bw trig vdb(out) val=-10 rise=1 targ vdb(out) val=-10 fall=1 -* - set run ="$&run" $ create a variable from the vector +* + set run = $&run $ create a variable from the vector set dt = $curplot $ store the current plot to dt setplot $scratch $ make 'scratch' the active plot let vout{$run}={$dt}.v(out) $ store the output vector to plot 'scratch' - let bwh[run]={$dt}.bw $ store bw to vector bwh in plot 'scratch' + let bwh[run]={$dt}.bw $ store bw to vector bwh in plot 'scratch' setplot $dt $ go back to the previous plot - let run = run + 1 + let run = run + 1 end $ loop ends here -* +* plot db({$scratch}.allv) echo print {$scratch}.bwh diff --git a/Windows/spice/examples/Monte_Carlo/OpWien.sp b/Windows/spice/examples/Monte_Carlo/OpWien.sp index 91b45d08..b6ada544 100644 --- a/Windows/spice/examples/Monte_Carlo/OpWien.sp +++ b/Windows/spice/examples/Monte_Carlo/OpWien.sp @@ -17,18 +17,18 @@ OPWIEN.CIR - OPAMP WIEN-BRIDGE OSCILLATOR IS 0 3 dc 0 PWL(0US 0MA 10US 0.1MA 40US 0.1MA 50US 0MA 10MS 0MA) * * RC TUNING -VR2 r2 0 dc 0 trrandom (2 'ttime10' 0 1) $ Gauss controlling voltage +VR2 r2 0 dc 0 trrandom (2 'ttime10' 0 1) ; Gauss controlling voltage * -*VR2 r2 0 dc 0 trrandom (1 'ttime10' 0 3) $ Uniform within -3 3 +*VR2 r2 0 dc 0 trrandom (1 'ttime10' 0 3) ; Uniform within -3 3 * * If Gauss, factor 0.033 is 10% equivalent to 3 sigma * if uniform, uniform between +/- 10% -R2 4 6 R = 'res + 0.033 * res*V(r2)' $ behavioral resistor +R2 4 6 R = 'res + 0.033 * res*V(r2)' ; behavioral resistor *R2 4 6 'res' $ constant R VC2 c2 0 dc 0 trrandom (2 'ttime10' 0 1) *C2 6 3'cn' $ constant C -C2 6 3 C = 'cn + 0.033 * cn*V(c2)' $ behavioral capacitor +C2 6 3 C = 'cn + 0.033 * cn*V(c2)' ; behavioral capacitor VR1 r1 0 dc 0 trrandom (2 'ttime10' 0 1) *VR1 r1 0 dc 0 trrandom (1 'ttime10' 0 3) diff --git a/Windows/spice/examples/Monte_Carlo/mc_ring_circ.net b/Windows/spice/examples/Monte_Carlo/mc_ring_circ.net new file mode 100644 index 00000000..cd058a5e --- /dev/null +++ b/Windows/spice/examples/Monte_Carlo/mc_ring_circ.net @@ -0,0 +1,56 @@ +Perform Monte Carlo simulation in ngspice +* 25 stage Ring-Osc. BSIM3 or 4 with statistical variation of model parameters +* Model parameters are varied according to the PDK selection. +* Tested with 3 different commercial HSPICE libraries from 2 vendors. +* To be started with script MC_ring_ts.sp + +.options noacct seedinfo + +vin in out dc 0.5 pulse 0.5 0 0.1n 5n 1 1 1 +vdd dd 0 dc 3.3 +vss ss 0 dc 0 +ve sub 0 dc 0 +vpe well 0 dc 3.3 + +* transistors to be selected according to the library (here: p33ll and n33ll or pch_5_mac and nch_5_mac +* or pe3 and ne3 or p1 and n1 (these models see below)) +.subckt inv1 dd ss sub well in out +*XMP1 out in dd well p33ll w=5u l=800n m=3 nf=1 ad=1.35p as=1.35p pd=9.6u ps=9.6u mosmis_mod=1 +*XMN1 out in ss sub n33ll w=5u l=800n m=1 nf=3 ad=0.9p as=0.9p pd=6.6u ps=6.6u mosmis_mod=1 +*XMP1 out in dd well pch_5_mac w=5u l=800n m=3 nf=1 ad=1.35p as=1.35p pd=9.6u ps=9.6u mosmis_mod=1 +*XMN1 out in ss sub nch_5_mac w=5u l=800n m=1 nf=3 ad=0.9p as=0.9p pd=6.6u ps=6.6u mosmis_mod=1 +*XMP1 out in dd well pe3 w=5u l=800n m=3 nf=1 ad=1.35p as=1.35p pd=9.6u ps=9.6u mosmis_mod=1 +*XMN1 out in ss sub ne3 w=5u l=800n m=1 nf=3 ad=0.9p as=0.9p pd=6.6u ps=6.6u mosmis_mod=1 +MP1 out in dd well p1 w=5u l=800n m=3 ad=1.35p as=1.35p pd=9.6u ps=9.6u +MN1 out in ss sub n1 w=5u l=800n m=1 ad=0.9p as=0.9p pd=6.6u ps=6.6u +.ends inv1 + +.subckt inv5 dd ss sub well in out +xinv1 dd ss sub well in 1 inv1 +xinv2 dd ss sub well 1 2 inv1 +xinv3 dd ss sub well 2 3 inv1 +xinv4 dd ss sub well 3 4 inv1 +xinv5 dd ss sub well 4 out inv1 +.ends inv5 + +xinv1 dd ss sub well in out5 inv5 +xinv2 dd ss sub well out5 out10 inv5 +xinv3 dd ss sub well out10 out15 inv5 +xinv4 dd ss sub well out15 out20 inv5 +xinv5 dd ss sub well out20 out inv5 +xinv11 dd 0 sub well out buf inv1 +cout buf ss 0.2pF + + *** Model library files. +* Add your library here +* Chose the transistors for XMP1 and XMN1 accordingly +*.lib "jc_usage.l" MC_LIB +*.lib "my_ts_usage.l" MC_LIB +*.lib "x_usage.l" MC_LIB + +* or use the BSIM3 model with internal parameters except Vth0 +* that varies the threshold voltage +-3 sigma around a mean of +-0.6V +.model p1 PMOS version=3.3.0 Level=8 Vth0=agauss(-0.6, 0.1, 3) +.model n1 NMOS version=3.3.0 Level=8 Vth0=agauss(0.6, 0.1, 3) + +.end diff --git a/Windows/spice/examples/Monte_Carlo/mc_ring_lib_complete_actual.cir b/Windows/spice/examples/Monte_Carlo/mc_ring_lib_complete_actual.cir new file mode 100644 index 00000000..9fd239e4 --- /dev/null +++ b/Windows/spice/examples/Monte_Carlo/mc_ring_lib_complete_actual.cir @@ -0,0 +1,212 @@ +Perform Monte Carlo simulation in ngspice +* 25 stage Ring-Osc. BSIM3 or 4 with statistical variation of model parameters +* Model parameters are varied according to the PDK selection. +* Tested with 3 different commercial HSPICE libraries from 2 vendors. +* Add your library to mc_ring_circ.net and choose transistors accordingly. +* Add the library path to the .LIB statement. +* A simple BSIM3 inverter R.O. serves as an MC example. + +.options noacct + +vin in out dc 0.5 pulse 0.5 0 0.1n 5n 1 1 1 +vdd dd 0 dc 3.3 +vss ss 0 dc 0 +ve sub 0 dc 0 +vpe well 0 dc 3.3 + +* transistors to be selected according to the library (here: p33ll and n33ll or pch_5_mac and nch_5_mac +* or pe3 and ne3 or p1 and n1 (these models see below)) +.subckt inv1 dd ss sub well in out +*XMP1 out in dd well p33ll w=5u l=800n m=3 nf=1 ad=1.35p as=1.35p pd=9.6u ps=9.6u mosmis_mod=1 +*XMN1 out in ss sub n33ll w=5u l=800n m=1 nf=3 ad=0.9p as=0.9p pd=6.6u ps=6.6u mosmis_mod=1 +XMP1 out in dd well pch_5_mac w=5u l=800n m=3 nf=1 ad=1.35p as=1.35p pd=9.6u ps=9.6u mosmis_mod=1 +XMN1 out in ss sub nch_5_mac w=5u l=800n m=1 nf=3 ad=0.9p as=0.9p pd=6.6u ps=6.6u mosmis_mod=1 +*XMP1 out in dd well pe3 w=5u l=800n m=3 nf=1 ad=1.35p as=1.35p pd=9.6u ps=9.6u mosmis_mod=1 +*XMN1 out in ss sub ne3 w=5u l=800n m=1 nf=3 ad=0.9p as=0.9p pd=6.6u ps=6.6u mosmis_mod=1 +*MP1 out in dd well p1 w=5u l=800n m=3 ad=1.35p as=1.35p pd=9.6u ps=9.6u +*MN1 out in ss sub n1 w=5u l=800n m=1 ad=0.9p as=0.9p pd=6.6u ps=6.6u +.ends inv1 + +.subckt inv5 dd ss sub well in out +xinv1 dd ss sub well in 1 inv1 +xinv2 dd ss sub well 1 2 inv1 +xinv3 dd ss sub well 2 3 inv1 +xinv4 dd ss sub well 3 4 inv1 +xinv5 dd ss sub well 4 out inv1 +.ends inv5 + +xinv1 dd ss sub well in out5 inv5 +xinv2 dd ss sub well out5 out10 inv5 +xinv3 dd ss sub well out10 out15 inv5 +xinv4 dd ss sub well out15 out20 inv5 +xinv5 dd ss sub well out20 out inv5 +xinv11 dd 0 sub well out buf inv1 +cout buf ss 0.2pF + + *** Model library files. +* Add your library here (full path required, or path relative to path +* of ngspice executable (interactive mode), or relative to path of +* input file (batch mode)) +* Chose the transistors for XMP1 and XMN1 according to the library +*.lib "jc_usage.l" MC_LIB +*.lib "../../../various/lib-test/my_usage.l" MC_LIB +.lib "D:\Spice_general\tests\lib-test\ts14\my_ts_usage.l" MC_LIB +*.lib "x_usage.l" MC_LIB + +* or use the BSIM3 model with internal parameters except Vth0 +* that varies the threshold voltage +-3 sigma around a mean of +-0.6V +*.model p1 PMOS version=3.3.0 Level=8 Vth0=agauss(-0.6, 0.1, 3) +*.model n1 NMOS version=3.3.0 Level=8 Vth0=agauss(0.6, 0.1, 3) + +.control + let mc_runs = 10 $ number of runs for monte carlo + let run = 0 $ number of actual run + set curplot = new $ create a new plot + set curplottitle = "Transient outputs" + set plot_out = $curplot $ store its name to 'plot_out' + set curplot = new $ create a new plot + set curplottitle = "FFT outputs" + set plot_fft = $curplot $ store its name to 'plot_fft' + set curplot = new $ create a new plot + set curplottitle = "Oscillation frequency" + set max_fft = $curplot $ store its name to 'max_fft' + let mc_runsp = mc_runs + 1 + let maxffts = unitvec(mc_runsp) $ vector for storing max measure results + let halfffts = unitvec(mc_runsp)$ vector for storing measure results at -40dB rising + unlet mc_runsp + + set mc_runs = $&mc_runs $ create a variable from the vector + let seeds = mc_runs + 2 + setseed $&seeds + unlet seeds + + save buf $ we just need buf, save memory by more than 10x + +* run the simulation loop + +* We have to figure out what to do if a single simulation will not converge. +* There is now the variable sim_status, that is 0 if simulation ended regularly, +* and 1 if the simulation has been aborted with error message '...simulation(s) aborted'. +* Then we skip the rest of the run and continue with a new run. + + dowhile run <= mc_runs + + set run = $&run $ create a variable from the vector + + * run=0 simulates with nominal parameters + if run > 0 + echo + echo * * * * * * + echo Source the circuit again internally for run no. $run + echo * * * * * * + setseed $run + mc_source $ re-source the input file + else + echo run no. $run + end + echo simulation run no. $run of $mc_runs + tran 100p 1000n 0 + echo Simulation status $sim_status + let simstat = $sim_status + if simstat = 1 + if run = mc_runs + echo go to end + else + echo go to next run + end + destroy $curplot + goto next + end + +* select stop and step so that number of data points after linearization is not too +* close to 8192, which would yield varying number of line length and thus scale for fft. +* + set dt0 = $curplot + * save the linearized data for having equal time scales for all runs + linearize buf $ linearize only buf, no other vectors needed + set dt1 = $curplot $ store the current plot to dt (tran i+1) + setplot $plot_out $ make 'plt_out' the active plot + * firstly save the time scale once to become the default scale + if run=0 + let time={$dt1}.time + end + let vout{$run}={$dt1}.buf $ store the output vector to plot 'plot_out' + setplot $dt1 $ go back to the previous plot (tran i+1) + fft buf $ run fft on vector buf + let buf2=db(mag(buf)) + * find the frequency where buf has its maximum of the fft signal + meas sp fft_max MAX_AT buf2 from=0.05G to=0.7G + * find the frequency where buf is -40dB at rising fft signal + meas sp fft_40 WHEN buf2=-40 RISE=1 from=0.05G to=0.7G + * store the fft vector + set dt2 = $curplot $ store the current plot to dt (spec i) + setplot $plot_fft $ make 'plot_fft' the active plot + if run=0 + let frequency={$dt2}.frequency + end + let fft{$run}={$dt2}.buf $ store the output vector to plot 'plot_fft' + * store the measured value + setplot $max_fft $ make 'max_fft' the active plot + let maxffts[{$run}]={$dt2}.fft_max + let halfffts[{$run}]={$dt2}.fft_40 + destroy $dt0 $dt1 $dt2 $ save memory, we don't need this plot (spec) any more + + label next + remcirc + let run = run + 1 + end +***** plotting ********************************************************** +if $?batchmode + echo + echo Plotting not available in batch mode + echo Write linearized vout0 to vout{$mc_runs} to rawfile $rawfile + echo + write $rawfile {$plot_out}.allv + rusage + quit +else + plot {$plot_out}.vout0 $ just plot the tran output with run 0 parameters + setplot $plot_fft + plot db(mag(ally)) xlimit 0 1G ylimit -80 10 +* +* create a histogram from vector maxffts + setplot $max_fft $ make 'max_fft' the active plot + set startfreq=50MEG + set bin_size=1MEG + set bin_count=100 + compose osc_frequ start=$startfreq step=$bin_size lin=$bin_count $ requires variables as parameters + settype frequency osc_frequ + let bin_count=$bin_count $ create a vector from the variable + let yvec=unitvec(bin_count) $ requires vector as parameter + let startfreq=$startfreq + let bin_size=$bin_size + * put data into the correct bins + let run = 0 + dowhile run < mc_runs + set run = $&run $ create a variable from the vector + let val = maxffts[{$run}] + let part = 0 + * Check if val fits into a bin. If yes, raise bin by 1 + dowhile part < bin_count + if ((val < (startfreq + (part+1)*bin_size)) & (val > (startfreq + part*bin_size))) + let yvec[part] = yvec[part] + 1 + break + end + let part = part + 1 + end + let run = run + 1 + end + * plot the histogram + set plotstyle=combplot + let counts = yvec - 1 $ subtract 1 because we started with unitvec containing ones + plot counts vs osc_frequ +* calculate jitter + let diff40 = (vecmax(halfffts) - vecmin(halfffts))*1e-6 + echo + echo Max. jitter is "$&diff40" MHz +end + rusage +* quit +.endc + +.end diff --git a/Windows/spice/examples/Monte_Carlo/rand_numb_test.cir b/Windows/spice/examples/Monte_Carlo/rand_numb_test.cir new file mode 100644 index 00000000..dac4b5b6 --- /dev/null +++ b/Windows/spice/examples/Monte_Carlo/rand_numb_test.cir @@ -0,0 +1,40 @@ +*** random number test for scope-inpcom-8 + +*** Start value of seed for random number generator: variable 'rndseed' is set to 1 +*** and random number generator is seeded with this value. +*** You may override this value by adding 'setseed 5' or similar to file .spiceinit. + +*** print a message when the random number generator gets a new seed +.option seedinfo + +*** like HSPICE: set rndseed to (number of seconds since 1.1.1970 - 1470000000) +*** and seed the random number generator with rndseed +*.option seed = random + +*** like HSPICE: set rndseed to 55 +*** and seed the random number generator with rndseed (here 55) +.option seed = 55 + +*** the 'circuit' +.param myval = agauss(0, 1, 1) +v1 1 0 'myval' + +*** the .control script +.control + +*** set variable rndseed to value 11 +*set rndseed = 11 +*** seed the random number generator with value from variable rndseed +*setseed + +*** seed the random number generator with value 12 and set rndseed to 12 +setseed 12 + +*** reload circuit and re-evaluate all random functions (agauss etc.) +mc_source +*** simulate and print result +op +print v(1) +.endc + +.end |