mirror of https://github.com/VLSIDA/OpenRAM.git
Reduce number of parameters in function calls for delay.py.
This commit is contained in:
parent
4dc1f57881
commit
23f06bfa9a
|
|
@ -35,6 +35,11 @@ class delay():
|
|||
self.num_banks = self.sram.num_banks
|
||||
self.sp_file = spfile
|
||||
|
||||
# These are the member variables for a simulation
|
||||
self.period = 0
|
||||
self.load = 0
|
||||
self.slew = 0
|
||||
|
||||
self.set_corner(corner)
|
||||
|
||||
def set_corner(self,corner):
|
||||
|
|
@ -56,7 +61,7 @@ class delay():
|
|||
if not isinstance(self.probe_data, int) or self.probe_data>self.word_size or self.probe_data<0:
|
||||
debug.error("Given probe_data is not an integer to specify a data bit",1)
|
||||
|
||||
def write_generic_stimulus(self, load):
|
||||
def write_generic_stimulus(self):
|
||||
""" Create the instance, supplies, loads, and access transistors. """
|
||||
|
||||
# add vdd/gnd statements
|
||||
|
|
@ -71,14 +76,14 @@ class delay():
|
|||
|
||||
self.sf.write("\n* SRAM output loads\n")
|
||||
for i in range(self.word_size):
|
||||
self.sf.write("CD{0} d[{0}] 0 {1}f\n".format(i,load))
|
||||
self.sf.write("CD{0} d[{0}] 0 {1}f\n".format(i,self.load))
|
||||
|
||||
# add access transistors for data-bus
|
||||
self.sf.write("\n* Transmission Gates for data-bus and control signals\n")
|
||||
self.stim.inst_accesstx(dbits=self.word_size)
|
||||
|
||||
|
||||
def write_delay_stimulus(self, period, load, slew):
|
||||
def write_delay_stimulus(self):
|
||||
""" Creates a stimulus file for simulations to probe a bitcell at a given clock period.
|
||||
Address and bit were previously set with set_probe().
|
||||
Input slew (in ns) and output capacitive load (in fF) are required for charaterization.
|
||||
|
|
@ -86,71 +91,72 @@ class delay():
|
|||
self.check_arguments()
|
||||
|
||||
# obtains list of time-points for each rising clk edge
|
||||
self.obtain_cycle_times(period)
|
||||
self.obtain_cycle_times()
|
||||
|
||||
# creates and opens stimulus file for writing
|
||||
temp_stim = "{0}/stim.sp".format(OPTS.openram_temp)
|
||||
self.sf = open(temp_stim, "w")
|
||||
self.sf.write("* Delay stimulus for period of {0}n load={1}fF slew={2}ns\n\n".format(period,load,slew))
|
||||
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))
|
||||
self.stim = stimuli.stimuli(self.sf, self.corner)
|
||||
# include files in stimulus file
|
||||
self.stim.write_include(self.trim_sp_file)
|
||||
|
||||
self.write_generic_stimulus(load)
|
||||
self.write_generic_stimulus()
|
||||
|
||||
# generate data and addr signals
|
||||
self.sf.write("\n* Generation of data and address signals\n")
|
||||
for i in range(self.word_size):
|
||||
if i == self.probe_data:
|
||||
self.gen_data(clk_times=self.cycle_times,
|
||||
sig_name="data[{0}]".format(i),
|
||||
period=period,
|
||||
slew=slew)
|
||||
sig_name="data[{0}]".format(i))
|
||||
|
||||
|
||||
else:
|
||||
self.stim.gen_constant(sig_name="d[{0}]".format(i),
|
||||
v_val=0)
|
||||
|
||||
self.gen_addr(clk_times=self.cycle_times,
|
||||
addr=self.probe_address,
|
||||
period=period,
|
||||
slew=slew)
|
||||
addr=self.probe_address)
|
||||
|
||||
|
||||
# generate control signals
|
||||
self.sf.write("\n* Generation of control signals\n")
|
||||
self.gen_csb(self.cycle_times, period, slew)
|
||||
self.gen_web(self.cycle_times, period, slew)
|
||||
self.gen_oeb(self.cycle_times, period, slew)
|
||||
self.gen_csb(self.cycle_times)
|
||||
self.gen_web(self.cycle_times)
|
||||
self.gen_oeb(self.cycle_times)
|
||||
|
||||
self.sf.write("\n* Generation of global clock signal\n")
|
||||
self.stim.gen_pulse(sig_name="CLK",
|
||||
v1=0,
|
||||
v2=self.vdd_voltage,
|
||||
offset=period,
|
||||
period=period,
|
||||
t_rise=slew,
|
||||
t_fall=slew)
|
||||
offset=self.period,
|
||||
period=self.period,
|
||||
t_rise=self.slew,
|
||||
t_fall=self.slew)
|
||||
|
||||
self.write_delay_measures(period)
|
||||
self.write_delay_measures()
|
||||
|
||||
# run until the end of the cycle time
|
||||
self.stim.write_control(self.cycle_times[-1] + period)
|
||||
self.stim.write_control(self.cycle_times[-1] + self.period)
|
||||
|
||||
self.sf.close()
|
||||
|
||||
|
||||
def write_power_stimulus(self, period, load, trim):
|
||||
def write_power_stimulus(self, trim):
|
||||
""" Creates a stimulus file to measure leakage power only.
|
||||
This works on the *untrimmed netlist*.
|
||||
"""
|
||||
self.check_arguments()
|
||||
|
||||
# obtains list of time-points for each rising clk edge
|
||||
self.obtain_cycle_times(period)
|
||||
self.obtain_cycle_times()
|
||||
|
||||
# creates and opens stimulus file for writing
|
||||
temp_stim = "{0}/stim.sp".format(OPTS.openram_temp)
|
||||
self.sf = open(temp_stim, "w")
|
||||
self.sf.write("* Power stimulus for period of {0}n\n\n".format(period))
|
||||
self.sf.write("* Power stimulus for period of {0}n\n\n".format(self.period))
|
||||
self.stim = stimuli.stimuli(self.sf, self.corner)
|
||||
|
||||
# include UNTRIMMED files in stimulus file
|
||||
|
|
@ -159,7 +165,7 @@ class delay():
|
|||
else:
|
||||
self.stim.write_include(self.sim_sp_file)
|
||||
|
||||
self.write_generic_stimulus(load)
|
||||
self.write_generic_stimulus()
|
||||
|
||||
# generate data and addr signals
|
||||
self.sf.write("\n* Generation of data and address signals\n")
|
||||
|
|
@ -179,14 +185,14 @@ class delay():
|
|||
self.sf.write("\n* Generation of global clock signal\n")
|
||||
self.stim.gen_constant(sig_name="CLK", v_val=0)
|
||||
|
||||
self.write_power_measures(period)
|
||||
self.write_power_measures()
|
||||
|
||||
# run until the end of the cycle time
|
||||
self.stim.write_control(2*period)
|
||||
self.stim.write_control(2*self.period)
|
||||
|
||||
self.sf.close()
|
||||
|
||||
def write_delay_measures(self,period):
|
||||
def write_delay_measures(self):
|
||||
"""
|
||||
Write the measure statements to quantify the delay and power results.
|
||||
"""
|
||||
|
|
@ -212,7 +218,7 @@ class delay():
|
|||
trig_dir="FALL",
|
||||
targ_dir="FALL",
|
||||
trig_td=self.cycle_times[self.read0_cycle],
|
||||
targ_td=self.cycle_times[self.read0_cycle]+0.5*period)
|
||||
targ_td=self.cycle_times[self.read0_cycle]+0.5*self.period)
|
||||
|
||||
self.stim.gen_meas_delay(meas_name="DELAY_LH",
|
||||
trig_name=trig_name,
|
||||
|
|
@ -222,7 +228,7 @@ class delay():
|
|||
trig_dir="FALL",
|
||||
targ_dir="RISE",
|
||||
trig_td=self.cycle_times[self.read1_cycle],
|
||||
targ_td=self.cycle_times[self.read1_cycle]+0.5*period)
|
||||
targ_td=self.cycle_times[self.read1_cycle]+0.5*self.period)
|
||||
|
||||
self.stim.gen_meas_delay(meas_name="SLEW_HL",
|
||||
trig_name=targ_name,
|
||||
|
|
@ -232,7 +238,7 @@ class delay():
|
|||
trig_dir="FALL",
|
||||
targ_dir="FALL",
|
||||
trig_td=self.cycle_times[self.read0_cycle],
|
||||
targ_td=self.cycle_times[self.read0_cycle]+0.5*period)
|
||||
targ_td=self.cycle_times[self.read0_cycle]+0.5*self.period)
|
||||
|
||||
self.stim.gen_meas_delay(meas_name="SLEW_LH",
|
||||
trig_name=targ_name,
|
||||
|
|
@ -242,7 +248,7 @@ class delay():
|
|||
trig_dir="RISE",
|
||||
targ_dir="RISE",
|
||||
trig_td=self.cycle_times[self.read1_cycle],
|
||||
targ_td=self.cycle_times[self.read1_cycle]+0.5*period)
|
||||
targ_td=self.cycle_times[self.read1_cycle]+0.5*self.period)
|
||||
|
||||
# add measure statements for power
|
||||
t_initial = self.cycle_times[self.write0_cycle]
|
||||
|
|
@ -270,7 +276,7 @@ class delay():
|
|||
t_final=t_final)
|
||||
|
||||
|
||||
def write_power_measures(self,period):
|
||||
def write_power_measures(self):
|
||||
"""
|
||||
Write the measure statements to quantify the leakage power only.
|
||||
"""
|
||||
|
|
@ -278,13 +284,13 @@ class delay():
|
|||
self.sf.write("\n* Measure statements for idle leakage power\n")
|
||||
|
||||
# add measure statements for power
|
||||
t_initial = period
|
||||
t_final = 2*period
|
||||
t_initial = self.period
|
||||
t_final = 2*self.period
|
||||
self.stim.gen_meas_power(meas_name="leakage_power",
|
||||
t_initial=t_initial,
|
||||
t_final=t_final)
|
||||
|
||||
def find_feasible_period(self, load, slew):
|
||||
def find_feasible_period(self):
|
||||
"""
|
||||
Uses an initial period and finds a feasible period before we
|
||||
run the binary search algorithm to find min period. We check if
|
||||
|
|
@ -301,25 +307,26 @@ class delay():
|
|||
|
||||
if (time_out <= 0):
|
||||
debug.error("Timed out, could not find a feasible period.",2)
|
||||
|
||||
(success, results)=self.run_delay_simulation(feasible_period,load,slew)
|
||||
self.period = feasible_period
|
||||
(success, results)=self.run_delay_simulation()
|
||||
if not success:
|
||||
feasible_period = 2 * feasible_period
|
||||
continue
|
||||
feasible_delay_lh = results["delay_lh"]
|
||||
feasible_slew_lh = results["slew_lh"]
|
||||
feasible_delay_hl = results["delay_hl"]
|
||||
feasible_slew_hl = results["slew_hl"]
|
||||
if not success:
|
||||
feasible_period = 2 * feasible_period
|
||||
continue
|
||||
|
||||
debug.info(1, "Found feasible_period: {0}ns feasible_delay_lh/0 {1}ns/{2}ns slew {3}ns/{4}ns".format(feasible_period,
|
||||
feasible_delay_lh,
|
||||
feasible_delay_hl,
|
||||
feasible_slew_lh,
|
||||
feasible_slew_hl))
|
||||
return (feasible_period, feasible_delay_lh, feasible_delay_hl)
|
||||
feasible_delay_lh,
|
||||
feasible_delay_hl,
|
||||
feasible_slew_lh,
|
||||
feasible_slew_hl))
|
||||
self.period = feasible_period
|
||||
return (feasible_delay_lh, feasible_delay_hl)
|
||||
|
||||
|
||||
def run_delay_simulation(self, period, load, slew):
|
||||
def run_delay_simulation(self):
|
||||
"""
|
||||
This tries to simulate a period and checks if the result works. If
|
||||
so, it returns True and the delays, slews, and powers. It
|
||||
|
|
@ -328,7 +335,7 @@ class delay():
|
|||
"""
|
||||
|
||||
# Checking from not data_value to data_value
|
||||
self.write_delay_stimulus(period, load, slew)
|
||||
self.write_delay_stimulus()
|
||||
self.stim.run_sim()
|
||||
delay_hl = ch.parse_output("timing", "delay_hl")
|
||||
delay_lh = ch.parse_output("timing", "delay_lh")
|
||||
|
|
@ -341,7 +348,7 @@ class delay():
|
|||
read1_power=ch.parse_output("timing", "read1_power")
|
||||
write1_power=ch.parse_output("timing", "write1_power")
|
||||
|
||||
if not self.check_valid_delays(period, load, slew, delays):
|
||||
if not self.check_valid_delays(delays):
|
||||
return (False,{})
|
||||
|
||||
# For debug, you sometimes want to inspect each simulation.
|
||||
|
|
@ -361,19 +368,19 @@ class delay():
|
|||
return (True,result)
|
||||
|
||||
|
||||
def run_power_simulation(self, period, load):
|
||||
def run_power_simulation(self):
|
||||
"""
|
||||
This simulates a disabled SRAM to get the leakage power when it is off.
|
||||
|
||||
"""
|
||||
|
||||
self.write_power_stimulus(period, load, trim=False)
|
||||
self.write_power_stimulus(trim=False)
|
||||
self.stim.run_sim()
|
||||
leakage_power=ch.parse_output("timing", "leakage_power")
|
||||
debug.check(leakage_power!="Failed","Could not measure leakage power.")
|
||||
|
||||
|
||||
self.write_power_stimulus(period, load, trim=True)
|
||||
self.write_power_stimulus(trim=True)
|
||||
self.stim.run_sim()
|
||||
trim_leakage_power=ch.parse_output("timing", "leakage_power")
|
||||
debug.check(trim_leakage_power!="Failed","Could not measure leakage power.")
|
||||
|
|
@ -382,52 +389,52 @@ class delay():
|
|||
#key=raw_input("press return to continue")
|
||||
return (leakage_power*1e3, trim_leakage_power*1e3)
|
||||
|
||||
def check_valid_delays(self, period, load, slew, (delay_hl, delay_lh, slew_hl, slew_lh)):
|
||||
def check_valid_delays(self, (delay_hl, delay_lh, slew_hl, slew_lh)):
|
||||
""" Check if the measurements are defined and if they are valid. """
|
||||
|
||||
# if it failed or the read was longer than a period
|
||||
if type(delay_hl)!=float or type(delay_lh)!=float or type(slew_lh)!=float or type(slew_hl)!=float:
|
||||
debug.info(2,"Failed simulation: period {0} load {1} slew {2}, delay_hl={3}n delay_lh={4}ns slew_hl={5}n slew_lh={6}n".format(period,
|
||||
load,
|
||||
slew,
|
||||
delay_hl,
|
||||
delay_lh,
|
||||
slew_hl,
|
||||
slew_lh))
|
||||
debug.info(2,"Failed simulation: period {0} load {1} slew {2}, delay_hl={3}n delay_lh={4}ns slew_hl={5}n slew_lh={6}n".format(self.period,
|
||||
self.load,
|
||||
self.slew,
|
||||
delay_hl,
|
||||
delay_lh,
|
||||
slew_hl,
|
||||
slew_lh))
|
||||
return False
|
||||
# Scale delays to ns (they previously could have not been floats)
|
||||
delay_hl *= 1e9
|
||||
delay_lh *= 1e9
|
||||
slew_hl *= 1e9
|
||||
slew_lh *= 1e9
|
||||
if delay_hl>period or delay_lh>period or slew_hl>period or slew_lh>period:
|
||||
debug.info(2,"UNsuccessful simulation: period {0} load {1} slew {2}, delay_hl={3}n delay_lh={4}ns slew_hl={5}n slew_lh={6}n".format(period,
|
||||
load,
|
||||
slew,
|
||||
delay_hl,
|
||||
delay_lh,
|
||||
slew_hl,
|
||||
slew_lh))
|
||||
if delay_hl>self.period or delay_lh>self.period or slew_hl>self.period or slew_lh>self.period:
|
||||
debug.info(2,"UNsuccessful simulation: period {0} load {1} slew {2}, delay_hl={3}n delay_lh={4}ns slew_hl={5}n slew_lh={6}n".format(self.period,
|
||||
self.load,
|
||||
self.slew,
|
||||
delay_hl,
|
||||
delay_lh,
|
||||
slew_hl,
|
||||
slew_lh))
|
||||
return False
|
||||
else:
|
||||
debug.info(2,"Successful simulation: period {0} load {1} slew {2}, delay_hl={3}n delay_lh={4}ns slew_hl={5}n slew_lh={6}n".format(period,
|
||||
load,
|
||||
slew,
|
||||
delay_hl,
|
||||
delay_lh,
|
||||
slew_hl,
|
||||
slew_lh))
|
||||
debug.info(2,"Successful simulation: period {0} load {1} slew {2}, delay_hl={3}n delay_lh={4}ns slew_hl={5}n slew_lh={6}n".format(self.period,
|
||||
self.load,
|
||||
self.slew,
|
||||
delay_hl,
|
||||
delay_lh,
|
||||
slew_hl,
|
||||
slew_lh))
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def find_min_period(self,feasible_period, load, slew, feasible_delay_lh, feasible_delay_hl):
|
||||
def find_min_period(self, feasible_delay_lh, feasible_delay_hl):
|
||||
"""
|
||||
Searches for the smallest period with output delays being within 5% of
|
||||
long period.
|
||||
"""
|
||||
|
||||
previous_period = ub_period = feasible_period
|
||||
previous_period = ub_period = self.period
|
||||
lb_period = 0.0
|
||||
|
||||
# Binary search algorithm to find the min period (max frequency) of design
|
||||
|
|
@ -438,11 +445,12 @@ class delay():
|
|||
debug.error("Timed out, could not converge on minimum period.",2)
|
||||
|
||||
target_period = 0.5 * (ub_period + lb_period)
|
||||
self.period = target_period
|
||||
debug.info(1, "MinPeriod Search: {0}ns (ub: {1} lb: {2})".format(target_period,
|
||||
ub_period,
|
||||
lb_period))
|
||||
|
||||
if self.try_period(target_period, load, slew, feasible_delay_lh, feasible_delay_hl):
|
||||
if self.try_period(feasible_delay_lh, feasible_delay_hl):
|
||||
ub_period = target_period
|
||||
else:
|
||||
lb_period = target_period
|
||||
|
|
@ -452,14 +460,14 @@ class delay():
|
|||
return ub_period
|
||||
|
||||
|
||||
def try_period(self, period, load, slew, feasible_delay_lh, feasible_delay_hl):
|
||||
def try_period(self, feasible_delay_lh, feasible_delay_hl):
|
||||
"""
|
||||
This tries to simulate a period and checks if the result
|
||||
works. If it does and the delay is within 5% still, it returns True.
|
||||
"""
|
||||
|
||||
# Checking from not data_value to data_value
|
||||
self.write_delay_stimulus(period,load,slew)
|
||||
self.write_delay_stimulus()
|
||||
self.stim.run_sim()
|
||||
delay_hl = ch.parse_output("timing", "delay_hl")
|
||||
delay_lh = ch.parse_output("timing", "delay_lh")
|
||||
|
|
@ -467,22 +475,22 @@ class delay():
|
|||
slew_lh = ch.parse_output("timing", "slew_lh")
|
||||
# if it failed or the read was longer than a period
|
||||
if type(delay_hl)!=float or type(delay_lh)!=float or type(slew_lh)!=float or type(slew_hl)!=float:
|
||||
debug.info(2,"Invalid measures: Period {0}, delay_hl={1}ns, delay_lh={2}ns slew_hl={3}ns slew_lh={4}ns".format(period,
|
||||
delay_hl,
|
||||
delay_lh,
|
||||
slew_hl,
|
||||
slew_lh))
|
||||
debug.info(2,"Invalid measures: Period {0}, delay_hl={1}ns, delay_lh={2}ns slew_hl={3}ns slew_lh={4}ns".format(self.period,
|
||||
delay_hl,
|
||||
delay_lh,
|
||||
slew_hl,
|
||||
slew_lh))
|
||||
return False
|
||||
delay_hl *= 1e9
|
||||
delay_lh *= 1e9
|
||||
slew_hl *= 1e9
|
||||
slew_lh *= 1e9
|
||||
if delay_hl>period or delay_lh>period or slew_hl>period or slew_lh>period:
|
||||
debug.info(2,"Too long delay/slew: Period {0}, delay_hl={1}ns, delay_lh={2}ns slew_hl={3}ns slew_lh={4}ns".format(period,
|
||||
delay_hl,
|
||||
delay_lh,
|
||||
slew_hl,
|
||||
slew_lh))
|
||||
if delay_hl>self.period or delay_lh>self.period or slew_hl>self.period or slew_lh>self.period:
|
||||
debug.info(2,"Too long delay/slew: Period {0}, delay_hl={1}ns, delay_lh={2}ns slew_hl={3}ns slew_lh={4}ns".format(self.period,
|
||||
delay_hl,
|
||||
delay_lh,
|
||||
slew_hl,
|
||||
slew_lh))
|
||||
return False
|
||||
else:
|
||||
if not ch.relative_compare(delay_lh,feasible_delay_lh,error_tolerance=0.05):
|
||||
|
|
@ -495,11 +503,11 @@ class delay():
|
|||
|
||||
#key=raw_input("press return to continue")
|
||||
|
||||
debug.info(2,"Successful period {0}, delay_hl={1}ns, delay_lh={2}ns slew_hl={3}ns slew_lh={4}ns".format(period,
|
||||
delay_hl,
|
||||
delay_lh,
|
||||
slew_hl,
|
||||
slew_lh))
|
||||
debug.info(2,"Successful period {0}, delay_hl={1}ns, delay_lh={2}ns slew_hl={3}ns slew_lh={4}ns".format(self.period,
|
||||
delay_hl,
|
||||
delay_lh,
|
||||
slew_hl,
|
||||
slew_lh))
|
||||
return True
|
||||
|
||||
def set_probe(self,probe_address, probe_data):
|
||||
|
|
@ -548,15 +556,17 @@ class delay():
|
|||
# feasible_delay_hl=0.17953789
|
||||
# load=1.6728
|
||||
# slew=0.04
|
||||
# self.try_period(target_period, load, slew, feasible_delay_lh, feasible_delay_hl)
|
||||
# self.try_period(target_period, feasible_delay_lh, feasible_delay_hl)
|
||||
# sys.exit(1)
|
||||
|
||||
|
||||
# 1) Find a feasible period and it's corresponding delays using the trimmed array.
|
||||
(feasible_period, feasible_delay_lh, feasible_delay_hl) = self.find_feasible_period(max(loads), max(slews))
|
||||
self.load=max(loads)
|
||||
self.slew=max(slews)
|
||||
(feasible_delay_lh, feasible_delay_hl) = self.find_feasible_period()
|
||||
debug.check(feasible_delay_lh>0,"Negative delay may not be possible")
|
||||
debug.check(feasible_delay_hl>0,"Negative delay may not be possible")
|
||||
|
||||
|
||||
# 2) Measure the delay, slew and power for all slew/load pairs.
|
||||
# Make a list for each type of measurement to append results to
|
||||
char_data = {}
|
||||
|
|
@ -565,29 +575,31 @@ class delay():
|
|||
char_data[m]=[]
|
||||
full_array_leakage = {}
|
||||
trim_array_leakage = {}
|
||||
for load in loads:
|
||||
for self.load in loads:
|
||||
# 2a) Find the leakage power of the trimmmed and UNtrimmed arrays.
|
||||
(full_leak, trim_leak)=self.run_power_simulation(feasible_period, load)
|
||||
full_array_leakage[load]=full_leak
|
||||
trim_array_leakage[load]=trim_leak
|
||||
char_data["leakage_power"].append(full_array_leakage[load])
|
||||
(full_leak, trim_leak)=self.run_power_simulation()
|
||||
full_array_leakage[self.load]=full_leak
|
||||
trim_array_leakage[self.load]=trim_leak
|
||||
char_data["leakage_power"].append(full_array_leakage[self.load])
|
||||
|
||||
for slew in slews:
|
||||
for load in loads:
|
||||
for self.slew in slews:
|
||||
for self.load in loads:
|
||||
# 2c) Find the delay, dynamic power, and leakage power of the trimmed array.
|
||||
(success, delay_results) = self.run_delay_simulation(feasible_period, load, slew)
|
||||
debug.check(success,"Couldn't run a simulation. slew={0} load={1}\n".format(slew,load))
|
||||
(success, delay_results) = self.run_delay_simulation()
|
||||
debug.check(success,"Couldn't run a simulation. slew={0} load={1}\n".format(self.slew,self.load))
|
||||
for k,v in delay_results.items():
|
||||
if "power" in k:
|
||||
# Subtract partial array leakage and add full array leakage for the power measures
|
||||
char_data[k].append(v - trim_array_leakage[load] + full_array_leakage[load])
|
||||
char_data[k].append(v - trim_array_leakage[self.load] + full_array_leakage[self.load])
|
||||
else:
|
||||
char_data[k].append(v)
|
||||
|
||||
|
||||
|
||||
# 3) Finds the minimum period without degrading the delays by X%
|
||||
min_period = self.find_min_period(feasible_period, max(loads), max(slews), feasible_delay_lh, feasible_delay_hl)
|
||||
self.load=max(loads)
|
||||
self.slew=max(slews)
|
||||
min_period = self.find_min_period(feasible_delay_lh, feasible_delay_hl)
|
||||
debug.check(type(min_period)==float,"Couldn't find minimum period.")
|
||||
debug.info(1, "Min Period: {0}n with a delay of {1} / {2}".format(min_period, feasible_delay_lh, feasible_delay_hl))
|
||||
|
||||
|
|
@ -599,7 +611,7 @@ class delay():
|
|||
|
||||
|
||||
|
||||
def obtain_cycle_times(self, period):
|
||||
def obtain_cycle_times(self):
|
||||
"""Returns a list of key time-points [ns] of the waveform (each rising edge)
|
||||
of the cycles to do a timing evaluation. The last time is the end of the simulation
|
||||
and does not need a rising edge."""
|
||||
|
|
@ -611,87 +623,87 @@ class delay():
|
|||
# idle cycle, no operation
|
||||
msg = "Idle cycle (no clock)"
|
||||
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(0,
|
||||
t_current,
|
||||
msg))
|
||||
t_current,
|
||||
msg))
|
||||
self.cycle_times.append(t_current)
|
||||
t_current += period
|
||||
t_current += self.period
|
||||
|
||||
# One period
|
||||
msg = "W data 1 address 11..11 to initialize cell"
|
||||
self.cycle_times.append(t_current)
|
||||
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
|
||||
t_current,
|
||||
msg))
|
||||
t_current += period
|
||||
t_current,
|
||||
msg))
|
||||
t_current += self.period
|
||||
|
||||
# One period
|
||||
msg = "W data 0 address 11..11 (to ensure a write of value works)"
|
||||
self.cycle_times.append(t_current)
|
||||
self.write0_cycle=len(self.cycle_times)-1
|
||||
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
|
||||
t_current,
|
||||
msg))
|
||||
t_current += period
|
||||
t_current,
|
||||
msg))
|
||||
t_current += self.period
|
||||
|
||||
# One period
|
||||
msg = "W data 1 address 00..00 (to clear bus caps)"
|
||||
self.cycle_times.append(t_current)
|
||||
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
|
||||
t_current,
|
||||
msg))
|
||||
t_current += period
|
||||
t_current,
|
||||
msg))
|
||||
t_current += self.period
|
||||
|
||||
# One period
|
||||
msg = "R data 0 address 11..11 to check W0 worked"
|
||||
self.cycle_times.append(t_current)
|
||||
self.read0_cycle=len(self.cycle_times)-1
|
||||
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
|
||||
t_current,
|
||||
msg))
|
||||
t_current += period
|
||||
t_current,
|
||||
msg))
|
||||
t_current += self.period
|
||||
|
||||
# One period
|
||||
msg = "Idle cycle"
|
||||
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
|
||||
t_current,
|
||||
msg))
|
||||
t_current,
|
||||
msg))
|
||||
self.cycle_times.append(t_current)
|
||||
self.idle_cycle=len(self.cycle_times)-1
|
||||
t_current += period
|
||||
t_current += self.period
|
||||
|
||||
# One period
|
||||
msg = "W data 1 address 11..11 (to ensure a write of value worked)"
|
||||
self.cycle_times.append(t_current)
|
||||
self.write1_cycle=len(self.cycle_times)-1
|
||||
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
|
||||
t_current,
|
||||
msg))
|
||||
t_current += period
|
||||
t_current,
|
||||
msg))
|
||||
t_current += self.period
|
||||
|
||||
# One period
|
||||
msg = "W data 0 address 00..00 (to clear bus caps)"
|
||||
self.cycle_times.append(t_current)
|
||||
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
|
||||
t_current,
|
||||
msg))
|
||||
t_current += period
|
||||
t_current,
|
||||
msg))
|
||||
t_current += self.period
|
||||
|
||||
# One period
|
||||
msg = "R data 1 address 11..11 to check W1 worked"
|
||||
self.cycle_times.append(t_current)
|
||||
self.read1_cycle=len(self.cycle_times)-1
|
||||
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
|
||||
t_current,
|
||||
msg))
|
||||
t_current += period
|
||||
t_current,
|
||||
msg))
|
||||
t_current += self.period
|
||||
|
||||
# One period
|
||||
msg = "Idle cycle"
|
||||
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
|
||||
t_current,
|
||||
msg))
|
||||
t_current,
|
||||
msg))
|
||||
self.cycle_times.append(t_current)
|
||||
t_current += period
|
||||
t_current += self.period
|
||||
|
||||
|
||||
|
||||
|
|
@ -702,9 +714,9 @@ class delay():
|
|||
delay_hl = []
|
||||
slew_lh = []
|
||||
slew_hl = []
|
||||
for slew in slews:
|
||||
for load in loads:
|
||||
bank_delay = sram.analytical_delay(slew,load)
|
||||
for self.slew in slews:
|
||||
for self.load in loads:
|
||||
bank_delay = sram.analytical_delay(self.slew,self.load)
|
||||
# Convert from ps to ns
|
||||
delay_lh.append(bank_delay.delay/1e3)
|
||||
delay_hl.append(bank_delay.delay/1e3)
|
||||
|
|
@ -723,15 +735,15 @@ class delay():
|
|||
}
|
||||
return data
|
||||
|
||||
def gen_data(self, clk_times, sig_name, period, slew):
|
||||
def gen_data(self, clk_times, sig_name):
|
||||
""" Generates the PWL data inputs for a simulation timing test. """
|
||||
# values for NOP, W1, W0, W1, R0, NOP, W1, W0, R1, NOP
|
||||
# we are asserting the opposite value on the other side of the tx gate during
|
||||
# the read to be "worst case". Otherwise, it can actually assist the read.
|
||||
values = [0, 1, 0, 1, 1, 1, 1, 0, 0, 0 ]
|
||||
self.stim.gen_pwl(sig_name, clk_times, values, period, slew, 0.05)
|
||||
self.stim.gen_pwl(sig_name, clk_times, values, self.period, self.slew, 0.05)
|
||||
|
||||
def gen_addr(self, clk_times, addr, period, slew):
|
||||
def gen_addr(self, clk_times, addr):
|
||||
"""
|
||||
Generates the address inputs for a simulation timing test.
|
||||
This alternates between all 1's and all 0's for the address.
|
||||
|
|
@ -743,34 +755,34 @@ class delay():
|
|||
for i in range(len(addr)):
|
||||
sig_name = "A[{0}]".format(i)
|
||||
if addr[i]=="1":
|
||||
self.stim.gen_pwl(sig_name, clk_times, ones_values, period, slew, 0.05)
|
||||
self.stim.gen_pwl(sig_name, clk_times, ones_values, self.period, self.slew, 0.05)
|
||||
else:
|
||||
self.stim.gen_pwl(sig_name, clk_times, zero_values, period, slew, 0.05)
|
||||
self.stim.gen_pwl(sig_name, clk_times, zero_values, self.period, self.slew, 0.05)
|
||||
|
||||
|
||||
def gen_csb(self, clk_times, period, slew):
|
||||
def gen_csb(self, clk_times):
|
||||
""" Generates the PWL CSb signal """
|
||||
# values for NOP, W1, W0, W1, R0, NOP, W1, W0, R1, NOP
|
||||
# Keep CSb asserted in NOP for measuring >1 period
|
||||
values = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
self.stim.gen_pwl("csb", clk_times, values, period, slew, 0.05)
|
||||
self.stim.gen_pwl("csb", clk_times, values, self.period, self.slew, 0.05)
|
||||
|
||||
def gen_web(self, clk_times, period, slew):
|
||||
def gen_web(self, clk_times):
|
||||
""" Generates the PWL WEb signal """
|
||||
# values for NOP, W1, W0, W1, R0, NOP, W1, W0, R1, NOP
|
||||
# Keep WEb deasserted in NOP for measuring >1 period
|
||||
values = [1, 0, 0, 0, 1, 1, 0, 0, 1, 1]
|
||||
self.stim.gen_pwl("web", clk_times, values, period, slew, 0.05)
|
||||
self.stim.gen_pwl("web", clk_times, values, self.period, self.slew, 0.05)
|
||||
|
||||
# Keep acc_en deasserted in NOP for measuring >1 period
|
||||
values = [1, 0, 0, 0, 1, 1, 0, 0, 1, 1]
|
||||
self.stim.gen_pwl("acc_en", clk_times, values, period, slew, 0)
|
||||
self.stim.gen_pwl("acc_en", clk_times, values, self.period, self.slew, 0)
|
||||
values = [0, 1, 1, 1, 0, 0, 1, 1, 0, 0]
|
||||
self.stim.gen_pwl("acc_en_inv", clk_times, values, period, slew, 0)
|
||||
self.stim.gen_pwl("acc_en_inv", clk_times, values, self.period, self.slew, 0)
|
||||
|
||||
def gen_oeb(self, clk_times, period, slew):
|
||||
def gen_oeb(self, clk_times):
|
||||
""" Generates the PWL WEb signal """
|
||||
# values for NOP, W1, W0, W1, R0, W1, W0, R1, NOP
|
||||
# Keep OEb asserted in NOP for measuring >1 period
|
||||
values = [1, 1, 1, 1, 0, 0, 1, 1, 0, 0]
|
||||
self.stim.gen_pwl("oeb", clk_times, values, period, slew, 0.05)
|
||||
self.stim.gen_pwl("oeb", clk_times, values, self.period, self.slew, 0.05)
|
||||
|
|
|
|||
Loading…
Reference in New Issue