Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/characterizer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
if OPTS.spice_exe=="" or OPTS.spice_exe==None:
debug.error("{0} not found. Unable to perform characterization.".format(OPTS.spice_name),1)
else:
(OPTS.spice_name,OPTS.spice_exe) = get_tool("spice",["hspice", "ngspice", "ngspice.exe", "xa"])
(OPTS.spice_name,OPTS.spice_exe) = get_tool("spice",["hspice", "ngspice", "ngspice.exe", "xa", "alps"])

# set the input dir for spice files if using ngspice
if OPTS.spice_name == "ngspice":
Expand Down
3 changes: 3 additions & 0 deletions compiler/characterizer/charutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ 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 == "alps":
# alps using a .measure
full_filename="{0}{1}.measure".format(OPTS.openram_temp, filename)
else:
# ngspice/hspice using a .lis file
full_filename="{0}{1}.lis".format(OPTS.openram_temp, filename)
Expand Down
6 changes: 3 additions & 3 deletions compiler/characterizer/delay.py
Original file line number Diff line number Diff line change
Expand Up @@ -581,8 +581,8 @@ def get_power_measure_variants(self, port, power_obj, operation):
"""Get the measurement values that can either vary port to port (time delays)"""

# Return value is intended to match the power measure format: t_initial, t_final, port
t_initial = self.cycle_times[self.measure_cycles[port][power_obj.meta_str]]
t_final = self.cycle_times[self.measure_cycles[port][power_obj.meta_str]+1]
t_initial = self.cycle_times[self.measure_cycles[port][power_obj.meta_str]]-self.slew/2-self.period*0.05
t_final = self.cycle_times[self.measure_cycles[port][power_obj.meta_str]+1]-self.slew/2-self.period*0.05

return (t_initial, t_final, port)

Expand Down Expand Up @@ -666,7 +666,7 @@ def write_power_measures(self):
t_final = 2*self.period
self.stim.gen_meas_power(meas_name="leakage_power",
t_initial=t_initial,
t_final=t_final)
t_final=t_final, leakage=True)

def find_feasible_period_one_port(self, port):
"""
Expand Down
15 changes: 9 additions & 6 deletions compiler/characterizer/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,25 +325,28 @@ def write_bus(self):
self.lib.write(" base_type : array;\n")
self.lib.write(" data_type : bit;\n")
self.lib.write(" bit_width : {0};\n".format(self.sram.word_size))
self.lib.write(" bit_from : 0;\n")
self.lib.write(" bit_to : {0};\n".format(self.sram.word_size - 1))
self.lib.write(" bit_from : {0};\n".format(self.sram.word_size - 1))
self.lib.write(" bit_to : 0;\n")
self.lib.write(" downto : true;\n")
self.lib.write(" }\n\n")

self.lib.write(" type (addr){\n")
self.lib.write(" base_type : array;\n")
self.lib.write(" data_type : bit;\n")
self.lib.write(" bit_width : {0};\n".format(self.sram.addr_size))
self.lib.write(" bit_from : 0;\n")
self.lib.write(" bit_to : {0};\n".format(self.sram.addr_size - 1))
self.lib.write(" bit_from : {0};\n".format(self.sram.addr_size - 1))
self.lib.write(" bit_to : 0;\n")
self.lib.write(" downto : true;\n")
self.lib.write(" }\n\n")

if self.sram.write_size:
self.lib.write(" type (wmask){\n")
self.lib.write(" base_type : array;\n")
self.lib.write(" data_type : bit;\n")
self.lib.write(" bit_width : {0};\n".format(self.sram.num_wmasks))
self.lib.write(" bit_from : 0;\n")
self.lib.write(" bit_to : {0};\n".format(self.sram.num_wmasks - 1))
self.lib.write(" bit_from : {0};\n".format(self.sram.num_wmasks - 1))
self.lib.write(" bit_to : 0;\n")
self.lib.write(" downto : true;\n")
self.lib.write(" }\n\n")


Expand Down
39 changes: 30 additions & 9 deletions compiler/characterizer/stimuli.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,18 +192,29 @@ def gen_meas_find_voltage_at_time(self, meas_name, targ_name, time_at):
targ_name,
time_at))

def gen_meas_power(self, meas_name, t_initial, t_final):
def gen_meas_power(self, meas_name, t_initial, t_final, leakage=False):
""" Creates the .meas statement for the measurement of avg power """
# power mea cmd is different in different spice:
if OPTS.spice_name == "hspice":
power_exp = "power"
else:
power_exp = "par('(-1*v(" + str(self.vdd_name) + ")*I(v" + str(self.vdd_name) + "))')"
self.sf.write(".meas tran {0} avg {1} from={2}n to={3}n\n\n".format(meas_name,
power_exp,
t_initial,
t_final))

if leakage:
self.sf.write(".meas tran {0} avg {1} from={2}n to={3}n\n".format(meas_name,
power_exp,
t_initial,
t_final))
else:
self.sf.write(".meas tran {0}_total avg {1} from={2}n to={3}n\n".format(meas_name,
power_exp,
t_initial,
t_final))
self.sf.write(".meas tran {0}_leakage avg {1} from={2}n to={3}n\n".format(meas_name,
power_exp,
t_final-0.05*(t_final-t_initial),
t_final))
self.sf.write(".meas tran {0} param='{0}_total - {0}_leakage'\n\n".format(meas_name))

def gen_meas_value(self, meas_name, dout, t_intital, t_final):
measure_string=".meas tran {0} AVG v({1}) FROM={2}n TO={3}n\n\n".format(meas_name, dout, t_intital, t_final)
self.sf.write(measure_string)
Expand All @@ -230,9 +241,11 @@ def write_control(self, end_time, runlvl=4):
# 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(".OPTIONS POST=1 RELTOL={0} PROBE method=gear\n".format(reltol))
self.sf.write(".OPTIONS POST={1} RELTOL={0} PROBE method=gear\n".format(reltol, 0 if OPTS.purge_temp else 1))
elif OPTS.spice_name == "alps":
self.sf.write(".OPTIONS POST={2} RUNLVL={0} RELTOL={1} PROBE LEAST_DISK_SPACE=2000\n".format(runlvl, reltol, 0 if OPTS.purge_temp else 1))
else:
self.sf.write(".OPTIONS POST=1 RUNLVL={0} PROBE\n".format(runlvl))
self.sf.write(".OPTIONS POST={1} RUNLVL={0} PROBE\n".format(runlvl, 0 if OPTS.purge_temp else 1))

# create plots for all signals
self.sf.write("* probe is used for hspice/xa, while plot is used in ngspice\n")
Expand Down Expand Up @@ -297,7 +310,15 @@ def run_sim(self):
valid_retcode=0
elif OPTS.spice_name == "hspice":
# TODO: Should make multithreading parameter a configuration option
cmd = "{0} -mt 2 -i {1} -o {2}timing".format(OPTS.spice_exe,
cmd = "{0} -mt {1} -i {2} -o {3}timing".format(OPTS.spice_exe,
OPTS.num_threads,
temp_stim,
OPTS.openram_temp)
valid_retcode=0
elif OPTS.spice_name == "alps":
# TODO: Should make multithreading parameter a configuration option
cmd = "{0} -mt {1} -i {2} -o {3}timing".format(OPTS.spice_exe,
OPTS.num_threads,
temp_stim,
OPTS.openram_temp)
valid_retcode=0
Expand Down
6 changes: 5 additions & 1 deletion compiler/globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,11 @@ def parse_args():
"--dontpurge",
action="store_false",
dest="purge_temp",
help="Don't purge the contents of the temp directory after a successful run")
help="Don't purge the contents of the temp directory after a successful run"),
optparse.make_option(
"--num_threads",
dest="num_threads",
help="Number of threads used by simulator. Default is 2")
# -h --help is implicit.
}

Expand Down
3 changes: 3 additions & 0 deletions compiler/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ class options(optparse.Values):
spice_name = ""
# The spice executable being used which is derived from the user PATH.
spice_exe = ""

# Thread number for hspice and alps
num_threads = 2
# Variable to select the variant of drc, lvs, pex
drc_name = ""
lvs_name = ""
Expand Down
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
numpy
scipy