summaryrefslogtreecommitdiff
path: root/Windows/spice/examples/Monte_Carlo/MC_ring_ts.sp
diff options
context:
space:
mode:
Diffstat (limited to 'Windows/spice/examples/Monte_Carlo/MC_ring_ts.sp')
-rw-r--r--Windows/spice/examples/Monte_Carlo/MC_ring_ts.sp180
1 files changed, 180 insertions, 0 deletions
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