Edited delay measures to handle multiple readwrite ports. This commit is not well tested.

This commit is contained in:
Hunter Nichols 2018-08-29 00:01:22 -07:00
parent fa8434e5f0
commit ffe59bdf51
1 changed files with 98 additions and 71 deletions

View File

@ -207,27 +207,19 @@ class delay():
self.sf.close() self.sf.close()
def write_delay_measures(self): def write_delay_measures_one_port(self, port):
""" """
Write the measure statements to quantify the delay and power results. Write the measure statements to quantify the delay and power results for one port.
""" """
self.sf.write("\n* Measure statements for delay and power\n")
# Output some comments to aid where cycles start and
# what is happening
for comment in self.cycle_comments:
self.sf.write("* {}\n".format(comment))
# Trigger on the clk of the appropriate cycle # Trigger on the clk of the appropriate cycle
trig_name = "clk" trig_name = "clk"
targ_port = 0
#Target name should be an input to the function or a member variable. That way, the ports can be singled out for testing #Target name should be an input to the function or a member variable. That way, the ports can be singled out for testing
targ_name = "{0}".format("DOUT_RWP{0}[{1}]".format(targ_port,self.probe_data)) targ_name = "{0}".format("DOUT_{0}[{1}]".format(port,self.probe_data))
trig_val = targ_val = 0.5 * self.vdd_voltage trig_val = targ_val = 0.5 * self.vdd_voltage
# Delay the target to measure after the negative edge # Delay the target to measure after the negative edge
self.stim.gen_meas_delay(meas_name="DELAY_HL", self.stim.gen_meas_delay(meas_name="DELAY_HL_{0}".format(port),
trig_name=trig_name, trig_name=trig_name,
targ_name=targ_name, targ_name=targ_name,
trig_val=trig_val, trig_val=trig_val,
@ -237,7 +229,7 @@ class delay():
trig_td=self.cycle_times[self.read0_cycle], trig_td=self.cycle_times[self.read0_cycle],
targ_td=self.cycle_times[self.read0_cycle]) targ_td=self.cycle_times[self.read0_cycle])
self.stim.gen_meas_delay(meas_name="DELAY_LH", self.stim.gen_meas_delay(meas_name="DELAY_LH_{0}".format(port),
trig_name=trig_name, trig_name=trig_name,
targ_name=targ_name, targ_name=targ_name,
trig_val=trig_val, trig_val=trig_val,
@ -247,7 +239,7 @@ class delay():
trig_td=self.cycle_times[self.read1_cycle], trig_td=self.cycle_times[self.read1_cycle],
targ_td=self.cycle_times[self.read1_cycle]) targ_td=self.cycle_times[self.read1_cycle])
self.stim.gen_meas_delay(meas_name="SLEW_HL", self.stim.gen_meas_delay(meas_name="SLEW_HL_{0}".format(port),
trig_name=targ_name, trig_name=targ_name,
targ_name=targ_name, targ_name=targ_name,
trig_val=0.9*self.vdd_voltage, trig_val=0.9*self.vdd_voltage,
@ -257,7 +249,7 @@ class delay():
trig_td=self.cycle_times[self.read0_cycle], trig_td=self.cycle_times[self.read0_cycle],
targ_td=self.cycle_times[self.read0_cycle]) targ_td=self.cycle_times[self.read0_cycle])
self.stim.gen_meas_delay(meas_name="SLEW_LH", self.stim.gen_meas_delay(meas_name="SLEW_LH_{0}".format(port),
trig_name=targ_name, trig_name=targ_name,
targ_name=targ_name, targ_name=targ_name,
trig_val=0.1*self.vdd_voltage, trig_val=0.1*self.vdd_voltage,
@ -270,28 +262,46 @@ class delay():
# add measure statements for power # add measure statements for power
t_initial = self.cycle_times[self.write0_cycle] t_initial = self.cycle_times[self.write0_cycle]
t_final = self.cycle_times[self.write0_cycle+1] t_final = self.cycle_times[self.write0_cycle+1]
self.stim.gen_meas_power(meas_name="WRITE0_POWER", self.stim.gen_meas_power(meas_name="WRITE0_POWER_{0}".format(port),
t_initial=t_initial, t_initial=t_initial,
t_final=t_final) t_final=t_final)
t_initial = self.cycle_times[self.write1_cycle] t_initial = self.cycle_times[self.write1_cycle]
t_final = self.cycle_times[self.write1_cycle+1] t_final = self.cycle_times[self.write1_cycle+1]
self.stim.gen_meas_power(meas_name="WRITE1_POWER", self.stim.gen_meas_power(meas_name="WRITE1_POWER_{0}".format(port),
t_initial=t_initial, t_initial=t_initial,
t_final=t_final) t_final=t_final)
t_initial = self.cycle_times[self.read0_cycle] t_initial = self.cycle_times[self.read0_cycle]
t_final = self.cycle_times[self.read0_cycle+1] t_final = self.cycle_times[self.read0_cycle+1]
self.stim.gen_meas_power(meas_name="READ0_POWER", self.stim.gen_meas_power(meas_name="READ0_POWER_{0}".format(port),
t_initial=t_initial, t_initial=t_initial,
t_final=t_final) t_final=t_final)
t_initial = self.cycle_times[self.read1_cycle] t_initial = self.cycle_times[self.read1_cycle]
t_final = self.cycle_times[self.read1_cycle+1] t_final = self.cycle_times[self.read1_cycle+1]
self.stim.gen_meas_power(meas_name="READ1_POWER", self.stim.gen_meas_power(meas_name="READ1_POWER_{0}".format(port),
t_initial=t_initial, t_initial=t_initial,
t_final=t_final) t_final=t_final)
def write_delay_measures(self):
"""
Write the measure statements to quantify the delay and power results for all ports.
"""
self.sf.write("\n* Measure statements for delay and power\n")
# Output some comments to aid where cycles start and
# what is happening
for comment in self.cycle_comments:
self.sf.write("* {}\n".format(comment))
for readwrite_port in self.readwrite_ports:
self.write_delay_measures_one_port(readwrite_port)
# for read_port in self.read_ports:
# self.write_delay_measures_one_port(read_ports)
# for write_port in self.write_ports:
# self.write_delay_measures_one_port(write_ports)
def write_power_measures(self): def write_power_measures(self):
""" """
@ -351,37 +361,49 @@ class delay():
works on the trimmed netlist by default, so powers do not works on the trimmed netlist by default, so powers do not
include leakage of all cells. include leakage of all cells.
""" """
result = {}
# Checking from not data_value to data_value # Checking from not data_value to data_value
self.write_delay_stimulus() self.write_delay_stimulus()
self.stim.run_sim() self.stim.run_sim()
delay_hl = parse_spice_list("timing", "delay_hl")
delay_lh = parse_spice_list("timing", "delay_lh")
slew_hl = parse_spice_list("timing", "slew_hl")
slew_lh = parse_spice_list("timing", "slew_lh")
delays = (delay_hl, delay_lh, slew_hl, slew_lh)
read0_power=parse_spice_list("timing", "read0_power") #Only readwrite ports for now. Other to be added later.
write0_power=parse_spice_list("timing", "write0_power") for readwrite_port in self.readwrite_ports:
read1_power=parse_spice_list("timing", "read1_power") readwrite_port = readwrite_port.lower()
write1_power=parse_spice_list("timing", "write1_power") delay_hl = parse_spice_list("timing", "delay_hl_{0}".format(readwrite_port))
delay_lh = parse_spice_list("timing", "delay_lh_{0}".format(readwrite_port))
slew_hl = parse_spice_list("timing", "slew_hl_{0}".format(readwrite_port))
slew_lh = parse_spice_list("timing", "slew_lh_{0}".format(readwrite_port))
delays = (delay_hl, delay_lh, slew_hl, slew_lh)
if not self.check_valid_delays(delays): read0_power=parse_spice_list("timing", "read0_power_{0}".format(readwrite_port))
return (False,{}) write0_power=parse_spice_list("timing", "write0_power_{0}".format(readwrite_port))
read1_power=parse_spice_list("timing", "read1_power_{0}".format(readwrite_port))
write1_power=parse_spice_list("timing", "write1_power_{0}".format(readwrite_port))
# For debug, you sometimes want to inspect each simulation. if not self.check_valid_delays(delays):
#key=raw_input("press return to continue") return (False,{})
# Scale results to ns and mw, respectively #This is to be changed later. Most of the characterization relies that these names are preserved or nothing will work.
result = { "delay_hl" : delay_hl*1e9, #Therefore, changing these names would require changing names in most of delay.py functions and lib.py.
result.update({ "delay_hl" : delay_hl*1e9,
"delay_lh" : delay_lh*1e9, "delay_lh" : delay_lh*1e9,
"slew_hl" : slew_hl*1e9, "slew_hl" : slew_hl*1e9,
"slew_lh" : slew_lh*1e9, "slew_lh" : slew_lh*1e9,
"read0_power" : read0_power*1e3, "read0_power" : read0_power*1e3,
"read1_power" : read1_power*1e3, "read1_power" : read1_power*1e3,
"write0_power" : write0_power*1e3, "write0_power" : write0_power*1e3,
"write1_power" : write1_power*1e3} "write1_power" : write1_power*1e3})
# for read_port in self.read_ports:
# self.write_delay_measures_one_port(read_ports)
# for write_port in self.write_ports:
# self.write_delay_measures_one_port(write_ports)
# For debug, you sometimes want to inspect each simulation.
#key=raw_input("press return to continue")
# Scale results to ns and mw, respectively
# The delay is from the negative edge for our SRAM # The delay is from the negative edge for our SRAM
return (True,result) return (True,result)
@ -484,45 +506,50 @@ class delay():
# Checking from not data_value to data_value # Checking from not data_value to data_value
self.write_delay_stimulus() self.write_delay_stimulus()
self.stim.run_sim() self.stim.run_sim()
delay_hl = parse_spice_list("timing", "delay_hl") #Only readwrite ports for now. Other to be added later.
delay_lh = parse_spice_list("timing", "delay_lh") for readwrite_port in self.readwrite_ports:
slew_hl = parse_spice_list("timing", "slew_hl") readwrite_port = readwrite_port.lower()
slew_lh = parse_spice_list("timing", "slew_lh") delay_hl = parse_spice_list("timing", "delay_hl_{0}".format(readwrite_port))
# if it failed or the read was longer than a period delay_lh = parse_spice_list("timing", "delay_lh_{0}".format(readwrite_port))
if type(delay_hl)!=float or type(delay_lh)!=float or type(slew_lh)!=float or type(slew_hl)!=float: slew_hl = parse_spice_list("timing", "slew_hl_{0}".format(readwrite_port))
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, slew_lh = parse_spice_list("timing", "slew_lh_{0}".format(readwrite_port))
delay_hl,
delay_lh, # if it failed or the read was longer than a period
slew_hl, if type(delay_hl)!=float or type(delay_lh)!=float or type(slew_lh)!=float or type(slew_hl)!=float:
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,
return False delay_hl,
delay_hl *= 1e9 delay_lh,
delay_lh *= 1e9 slew_hl,
slew_hl *= 1e9 slew_lh))
slew_lh *= 1e9
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 relative_compare(delay_lh,feasible_delay_lh,error_tolerance=0.05):
debug.info(2,"Delay too big {0} vs {1}".format(delay_lh,feasible_delay_lh))
return False return False
elif not relative_compare(delay_hl,feasible_delay_hl,error_tolerance=0.05): delay_hl *= 1e9
debug.info(2,"Delay too big {0} vs {1}".format(delay_hl,feasible_delay_hl)) delay_lh *= 1e9
slew_hl *= 1e9
slew_lh *= 1e9
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 return False
else:
if not relative_compare(delay_lh,feasible_delay_lh,error_tolerance=0.05):
debug.info(2,"Delay too big {0} vs {1}".format(delay_lh,feasible_delay_lh))
return False
elif not relative_compare(delay_hl,feasible_delay_hl,error_tolerance=0.05):
debug.info(2,"Delay too big {0} vs {1}".format(delay_hl,feasible_delay_hl))
return False
#key=raw_input("press return to continue") #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(self.period, debug.info(2,"Successful period {0}, Port {5}, delay_hl={1}ns, delay_lh={2}ns slew_hl={3}ns slew_lh={4}ns".format(self.period,
delay_hl, delay_hl,
delay_lh, delay_lh,
slew_hl, slew_hl,
slew_lh)) slew_lh,
readwrite_port))
return True return True
def set_probe(self,probe_address, probe_data): def set_probe(self,probe_address, probe_data):