diff --git a/compiler/characterizer/charutils.py b/compiler/characterizer/charutils.py index 4ceafbcf..b618f0db 100644 --- a/compiler/characterizer/charutils.py +++ b/compiler/characterizer/charutils.py @@ -5,6 +5,7 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # +import os import re import debug from globals import OPTS @@ -20,6 +21,8 @@ def parse_spice_list(filename, key): if OPTS.spice_name == "xa" : # customsim has a different output file name full_filename="{0}xa.meas".format(OPTS.openram_temp) + elif OPTS.spice_name == "spectre": + full_filename = os.path.join(OPTS.openram_temp, "delay_stim.measure") else: # ngspice/hspice using a .lis file full_filename="{0}{1}.lis".format(OPTS.openram_temp, filename) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index e2d7e1d2..4c7f8f8f 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -387,6 +387,9 @@ class delay(simulation): self.delay_stim_sp = "delay_stim.sp" temp_stim = "{0}/{1}".format(OPTS.openram_temp, self.delay_stim_sp) self.sf = open(temp_stim, "w") + + if OPTS.spice_name == "spectre": + self.sf.write("simulator lang=spice\n") self.sf.write("* Delay stimulus for period of {0}n load={1}fF slew={2}ns\n\n".format(self.period, self.load, self.slew)) diff --git a/compiler/characterizer/stimuli.py b/compiler/characterizer/stimuli.py index 035e9e58..5855f236 100644 --- a/compiler/characterizer/stimuli.py +++ b/compiler/characterizer/stimuli.py @@ -247,16 +247,39 @@ class stimuli(): timestep = 10 # ps, was 5ps but ngspice was complaining the timestep was too small in certain tests. # UIC is needed for ngspice to converge - self.sf.write(".TRAN {0}p {1}n UIC\n".format(timestep, end_time)) + self.sf.write(".TEMP {}\n".format(self.temperature)) if OPTS.spice_name == "ngspice": # ngspice sometimes has convergence problems if not using gear method # which is more accurate, but slower than the default trapezoid method # Do not remove this or it may not converge due to some "pa_00" nodes # unless you figure out what these are. + self.sf.write(".TRAN {0}p {1}n UIC\n".format(timestep, end_time)) self.sf.write(".OPTIONS POST=1 RELTOL={0} PROBE method=gear\n".format(reltol)) + elif OPTS.spice_name == "spectre": + self.sf.write("simulator lang=spectre\n") + if OPTS.use_pex: + nestlvl = 1 + spectre_save = "selected" + else: + nestlvl = 10 + spectre_save = "lvlpub" + self.sf.write('saveOptions options save={} nestlvl={} pwr=total \n'.format( + spectre_save, nestlvl)) + self.sf.write("simulatorOptions options reltol=1e-3 vabstol=1e-6 iabstol=1e-12 temp={0} try_fast_op=no " + "rforce=10m maxnotes=10 maxwarns=10 " + " preservenode=all topcheck=fixall " + "digits=5 cols=80 dc_pivot_check=yes pivrel=1e-3 " + " \n".format(self.temperature)) + self.sf.write('tran tran step={} stop={}n ic=node write=spectre.dc errpreset=moderate ' + ' annotate=status maxiters=5 \n'.format("5p", end_time)) + self.sf.write("simulator lang=spice\n") else: + self.sf.write(".TRAN 5p {0}n \n".format(end_time)) self.sf.write(".OPTIONS POST=1 RUNLVL={0} PROBE\n".format(runlvl)) + if OPTS.spice_name == "hspice": # for cadence plots + self.sf.write(".OPTIONS PSF=1 \n") + self.sf.write(".OPTIONS HIER_DELIM=1 \n") # create plots for all signals self.sf.write("* probe is used for hspice/xa, while plot is used in ngspice\n") @@ -314,6 +337,16 @@ class stimuli(): OPTS.openram_temp, OPTS.num_sim_threads) valid_retcode=0 + elif OPTS.spice_name == "spectre": + if OPTS.use_pex: + extra_options = " +dcopt +postlayout " + else: + extra_options = "" + cmd = ("{0} -64 {1} -format psfbin -raw {2} {3} -maxwarnstolog 1000 " + " +mt={4} -maxnotestolog 1000 " + .format(OPTS.spice_exe, temp_stim, OPTS.openram_temp, extra_options, + OPTS.num_sim_threads)) + valid_retcode = 0 elif OPTS.spice_name == "hspice": # TODO: Should make multithreading parameter a configuration option cmd = "{0} -mt {1} -i {2} -o {3}timing".format(OPTS.spice_exe,