mirror of https://github.com/VLSIDA/OpenRAM.git
Added incorrect read checking in characterizer.
This commit is contained in:
parent
d54074d68e
commit
b4cce65889
|
|
@ -1,4 +1,4 @@
|
||||||
import sys,re,shutil
|
import sys,re,shutil,copy
|
||||||
import debug
|
import debug
|
||||||
import tech
|
import tech
|
||||||
import math
|
import math
|
||||||
|
|
@ -48,32 +48,33 @@ class delay(simulation):
|
||||||
|
|
||||||
def create_measurement_objects(self):
|
def create_measurement_objects(self):
|
||||||
"""Create the measurements used for read and write ports"""
|
"""Create the measurements used for read and write ports"""
|
||||||
self.create_read_port_measurement_objects()
|
self.read_meas_lists = self.create_read_port_measurement_objects()
|
||||||
self.create_write_port_measurement_objects()
|
self.write_meas_lists = self.create_write_port_measurement_objects()
|
||||||
|
|
||||||
def create_read_port_measurement_objects(self):
|
def create_read_port_measurement_objects(self):
|
||||||
"""Create the measurements used for read ports: delays, slews, powers"""
|
"""Create the measurements used for read ports: delays, slews, powers"""
|
||||||
|
|
||||||
self.read_meas_objs = []
|
self.read_lib_meas = []
|
||||||
trig_delay_name = "clk{0}"
|
trig_delay_name = "clk{0}"
|
||||||
targ_name = "{0}{1}_{2}".format(self.dout_name,"{}",self.probe_data) #Empty values are the port and probe data bit
|
targ_name = "{0}{1}_{2}".format(self.dout_name,"{}",self.probe_data) #Empty values are the port and probe data bit
|
||||||
self.read_meas_objs.append(delay_measure("delay_lh", trig_delay_name, targ_name, "RISE", "RISE", measure_scale=1e9))
|
self.read_lib_meas.append(delay_measure("delay_lh", trig_delay_name, targ_name, "RISE", "RISE", measure_scale=1e9))
|
||||||
self.read_meas_objs[-1].meta_str = "read1" #Used to index time delay values when measurements written to spice file.
|
self.read_lib_meas[-1].meta_str = "read1" #Used to index time delay values when measurements written to spice file.
|
||||||
self.read_meas_objs.append(delay_measure("delay_hl", trig_delay_name, targ_name, "FALL", "FALL", measure_scale=1e9))
|
self.read_lib_meas.append(delay_measure("delay_hl", trig_delay_name, targ_name, "FALL", "FALL", measure_scale=1e9))
|
||||||
self.read_meas_objs[-1].meta_str = "read0"
|
self.read_lib_meas[-1].meta_str = "read0"
|
||||||
|
self.delay_meas = self.read_lib_meas[:] #For debugging, kept separated
|
||||||
|
|
||||||
self.read_meas_objs.append(slew_measure("slew_lh", targ_name, "RISE", measure_scale=1e9))
|
self.read_lib_meas.append(slew_measure("slew_lh", targ_name, "RISE", measure_scale=1e9))
|
||||||
self.read_meas_objs[-1].meta_str = "read1"
|
self.read_lib_meas[-1].meta_str = "read1"
|
||||||
self.read_meas_objs.append(slew_measure("slew_hl", targ_name, "FALL", measure_scale=1e9))
|
self.read_lib_meas.append(slew_measure("slew_hl", targ_name, "FALL", measure_scale=1e9))
|
||||||
self.read_meas_objs[-1].meta_str = "read0"
|
self.read_lib_meas[-1].meta_str = "read0"
|
||||||
|
|
||||||
self.read_meas_objs.append(power_measure("read1_power", "RISE", measure_scale=1e3))
|
self.read_lib_meas.append(power_measure("read1_power", "RISE", measure_scale=1e3))
|
||||||
self.read_meas_objs[-1].meta_str = "read1"
|
self.read_lib_meas[-1].meta_str = "read1"
|
||||||
self.read_meas_objs.append(power_measure("read0_power", "FALL", measure_scale=1e3))
|
self.read_lib_meas.append(power_measure("read0_power", "FALL", measure_scale=1e3))
|
||||||
self.read_meas_objs[-1].meta_str = "read0"
|
self.read_lib_meas[-1].meta_str = "read0"
|
||||||
|
|
||||||
#This will later add a half-period to the spice time delay. Only for reading 0.
|
#This will later add a half-period to the spice time delay. Only for reading 0.
|
||||||
for obj in self.read_meas_objs:
|
for obj in self.read_lib_meas:
|
||||||
if obj.meta_str is "read0":
|
if obj.meta_str is "read0":
|
||||||
obj.meta_add_delay = True
|
obj.meta_add_delay = True
|
||||||
|
|
||||||
|
|
@ -85,17 +86,22 @@ class delay(simulation):
|
||||||
|
|
||||||
bl_name = "Xsram.Xbank0.bl{}_{}".format(port_format, self.bitline_column)
|
bl_name = "Xsram.Xbank0.bl{}_{}".format(port_format, self.bitline_column)
|
||||||
br_name = "Xsram.Xbank0.br{}_{}".format(port_format, self.bitline_column)
|
br_name = "Xsram.Xbank0.br{}_{}".format(port_format, self.bitline_column)
|
||||||
# self.read_meas_objs.append(voltage_when_measure(self.voltage_when_names[0], trig_name, bl_name, "RISE", .5))
|
# self.read_lib_meas.append(voltage_when_measure(self.voltage_when_names[0], trig_name, bl_name, "RISE", .5))
|
||||||
# self.read_meas_objs.append(voltage_when_measure(self.voltage_when_names[1], trig_name, br_name, "RISE", .5))
|
# self.read_lib_meas.append(voltage_when_measure(self.voltage_when_names[1], trig_name, br_name, "RISE", .5))
|
||||||
|
|
||||||
#These are read values but need to be separated for unique error checking.
|
read_measures = []
|
||||||
self.create_bitline_delay_measurement_objects()
|
read_measures.append(self.read_lib_meas)
|
||||||
|
#Other measurements associated with the read port not included in the liberty file
|
||||||
|
read_measures.append(self.create_bitline_delay_measurement_objects())
|
||||||
|
read_measures.append(self.create_debug_measurement_objects())
|
||||||
|
|
||||||
|
return read_measures
|
||||||
|
|
||||||
def create_bitline_delay_measurement_objects(self):
|
def create_bitline_delay_measurement_objects(self):
|
||||||
"""Create the measurements used for bitline delay values. Due to unique error checking, these are separated from other measurements.
|
"""Create the measurements used for bitline delay values. Due to unique error checking, these are separated from other measurements.
|
||||||
These measurements are only associated with read values
|
These measurements are only associated with read values
|
||||||
"""
|
"""
|
||||||
self.bitline_delay_objs = []
|
self.bitline_delay_meas = []
|
||||||
trig_name = "clk{0}"
|
trig_name = "clk{0}"
|
||||||
if len(self.all_ports) == 1: #special naming case for single port sram bitlines which does not include the port in name
|
if len(self.all_ports) == 1: #special naming case for single port sram bitlines which does not include the port in name
|
||||||
port_format = ""
|
port_format = ""
|
||||||
|
|
@ -106,23 +112,51 @@ class delay(simulation):
|
||||||
targ_val = (self.vdd_voltage - tech.spice["v_threshold_typical"])/self.vdd_voltage #Calculate as a percentage of vdd
|
targ_val = (self.vdd_voltage - tech.spice["v_threshold_typical"])/self.vdd_voltage #Calculate as a percentage of vdd
|
||||||
|
|
||||||
targ_name = "{0}{1}_{2}".format(self.dout_name,"{}",self.probe_data) #Empty values are the port and probe data bit
|
targ_name = "{0}{1}_{2}".format(self.dout_name,"{}",self.probe_data) #Empty values are the port and probe data bit
|
||||||
# self.bitline_delay_objs.append(delay_measure(self.bitline_delay_names[0], trig_name, bl_name, "FALL", "FALL", targ_vdd=targ_val, measure_scale=1e9))
|
# self.bitline_delay_meas.append(delay_measure(self.bitline_delay_names[0], trig_name, bl_name, "FALL", "FALL", targ_vdd=targ_val, measure_scale=1e9))
|
||||||
# self.bitline_delay_objs[-1].meta_str = "read0"
|
# self.bitline_delay_meas[-1].meta_str = "read0"
|
||||||
# self.bitline_delay_objs.append(delay_measure(self.bitline_delay_names[1], trig_name, br_name, "FALL", "FALL", targ_vdd=targ_val, measure_scale=1e9))
|
# self.bitline_delay_meas.append(delay_measure(self.bitline_delay_names[1], trig_name, br_name, "FALL", "FALL", targ_vdd=targ_val, measure_scale=1e9))
|
||||||
# self.bitline_delay_objs[-1].meta_str = "read1"
|
# self.bitline_delay_meas[-1].meta_str = "read1"
|
||||||
#Enforces the time delay on the bitline measurements for read0 or read1
|
#Enforces the time delay on the bitline measurements for read0 or read1
|
||||||
for obj in self.bitline_delay_objs:
|
for obj in self.bitline_delay_meas:
|
||||||
obj.meta_add_delay = True
|
obj.meta_add_delay = True
|
||||||
|
|
||||||
|
return self.bitline_delay_meas
|
||||||
|
|
||||||
def create_write_port_measurement_objects(self):
|
def create_write_port_measurement_objects(self):
|
||||||
"""Create the measurements used for read ports: delays, slews, powers"""
|
"""Create the measurements used for read ports: delays, slews, powers"""
|
||||||
self.write_meas_objs = []
|
self.write_lib_meas = []
|
||||||
|
|
||||||
self.write_meas_objs.append(power_measure("write1_power", "RISE", measure_scale=1e3))
|
self.write_lib_meas.append(power_measure("write1_power", "RISE", measure_scale=1e3))
|
||||||
self.write_meas_objs[-1].meta_str = "write1"
|
self.write_lib_meas[-1].meta_str = "write1"
|
||||||
self.write_meas_objs.append(power_measure("write0_power", "FALL", measure_scale=1e3))
|
self.write_lib_meas.append(power_measure("write0_power", "FALL", measure_scale=1e3))
|
||||||
self.write_meas_objs[-1].meta_str = "write0"
|
self.write_lib_meas[-1].meta_str = "write0"
|
||||||
|
|
||||||
|
write_measures = []
|
||||||
|
write_measures.append(self.write_lib_meas)
|
||||||
|
return write_measures
|
||||||
|
|
||||||
|
def create_debug_measurement_objects(self):
|
||||||
|
"""Create debug measurement to help identify failures."""
|
||||||
|
|
||||||
|
self.debug_delay_meas = []
|
||||||
|
self.debug_volt_meas = []
|
||||||
|
for meas in self.delay_meas:
|
||||||
|
debug_meas = copy.deepcopy(meas)
|
||||||
|
debug_meas.name = debug_meas.name+'_debug'
|
||||||
|
#This particular debugs check if output value is flipped, so TARG_DIR is flipped
|
||||||
|
if meas.targ_dir_str == 'FALL':
|
||||||
|
debug_meas.targ_dir_str = 'RISE'
|
||||||
|
else:
|
||||||
|
debug_meas.targ_dir_str = 'FALL'
|
||||||
|
#inserting debug member variable
|
||||||
|
debug_meas.parent = meas.name
|
||||||
|
self.debug_delay_meas.append(debug_meas)
|
||||||
|
|
||||||
|
self.debug_volt_meas.append(voltage_at_measure("v_{}".format(debug_meas.meta_str),
|
||||||
|
debug_meas.targ_name_no_port))
|
||||||
|
self.debug_volt_meas[-1].meta_str = debug_meas.meta_str
|
||||||
|
return self.debug_delay_meas+self.debug_volt_meas
|
||||||
|
|
||||||
def create_signal_names(self):
|
def create_signal_names(self):
|
||||||
self.addr_name = "A"
|
self.addr_name = "A"
|
||||||
self.din_name = "DIN"
|
self.din_name = "DIN"
|
||||||
|
|
@ -284,6 +318,8 @@ class delay(simulation):
|
||||||
return self.get_power_measure_variants(port, measure_obj, "read")
|
return self.get_power_measure_variants(port, measure_obj, "read")
|
||||||
elif meas_type is voltage_when_measure:
|
elif meas_type is voltage_when_measure:
|
||||||
return self.get_volt_when_measure_variants(port, measure_obj)
|
return self.get_volt_when_measure_variants(port, measure_obj)
|
||||||
|
elif meas_type is voltage_at_measure:
|
||||||
|
return self.get_volt_at_measure_variants(port, measure_obj)
|
||||||
else:
|
else:
|
||||||
debug.error("Input function not defined for measurement type={}".format(meas_type))
|
debug.error("Input function not defined for measurement type={}".format(meas_type))
|
||||||
|
|
||||||
|
|
@ -299,6 +335,7 @@ class delay(simulation):
|
||||||
else:
|
else:
|
||||||
debug.error("Unrecognised delay Index={}".format(delay_obj.meta_str),1)
|
debug.error("Unrecognised delay Index={}".format(delay_obj.meta_str),1)
|
||||||
|
|
||||||
|
#These measurements have there time further delayed to the neg. edge of the clock.
|
||||||
if delay_obj.meta_add_delay:
|
if delay_obj.meta_add_delay:
|
||||||
meas_cycle_delay += self.period/2
|
meas_cycle_delay += self.period/2
|
||||||
|
|
||||||
|
|
@ -312,7 +349,21 @@ class delay(simulation):
|
||||||
|
|
||||||
return (t_initial, t_final, port)
|
return (t_initial, t_final, port)
|
||||||
|
|
||||||
def get_volt_when_measure_variants(self, port, power_obj):
|
def get_volt_at_measure_variants(self, port, volt_meas):
|
||||||
|
"""Get the measurement values that can either vary port to port (time delays)"""
|
||||||
|
#Only checking 0 value reads for now.
|
||||||
|
if volt_meas.meta_str == "read0":
|
||||||
|
#Falling delay are measured starting from neg. clk edge. Delay adjusted to that.
|
||||||
|
meas_cycle = self.cycle_times[self.measure_cycles[port][volt_meas.meta_str]]
|
||||||
|
elif volt_meas.meta_str == "read1":
|
||||||
|
meas_cycle = self.cycle_times[self.measure_cycles[port][volt_meas.meta_str]]
|
||||||
|
else:
|
||||||
|
debug.error("Unrecognised delay Index={}".format(volt_meas.meta_str),1)
|
||||||
|
#Measurement occurs at the end of the period -> current period start + period
|
||||||
|
at_time = meas_cycle+self.period
|
||||||
|
return (at_time, port)
|
||||||
|
|
||||||
|
def get_volt_when_measure_variants(self, port, volt_meas):
|
||||||
"""Get the measurement values that can either vary port to port (time delays)"""
|
"""Get the measurement values that can either vary port to port (time delays)"""
|
||||||
#Only checking 0 value reads for now.
|
#Only checking 0 value reads for now.
|
||||||
t_trig = meas_cycle_delay = self.cycle_times[self.measure_cycles[port]["read0"]]
|
t_trig = meas_cycle_delay = self.cycle_times[self.measure_cycles[port]["read0"]]
|
||||||
|
|
@ -324,9 +375,10 @@ class delay(simulation):
|
||||||
Write the measure statements to quantify the delay and power results for a read port.
|
Write the measure statements to quantify the delay and power results for a read port.
|
||||||
"""
|
"""
|
||||||
# add measure statements for delays/slews
|
# add measure statements for delays/slews
|
||||||
for measure in self.read_meas_objs+self.bitline_delay_objs:
|
for meas_list in self.read_meas_lists:
|
||||||
measure_variant_inp_tuple = self.get_read_measure_variants(port, measure)
|
for measure in meas_list:
|
||||||
measure.write_measure(self.stim, measure_variant_inp_tuple)
|
measure_variant_inp_tuple = self.get_read_measure_variants(port, measure)
|
||||||
|
measure.write_measure(self.stim, measure_variant_inp_tuple)
|
||||||
|
|
||||||
def get_write_measure_variants(self, port, measure_obj):
|
def get_write_measure_variants(self, port, measure_obj):
|
||||||
"""Checks the measurement object and calls respective function for related measurement inputs."""
|
"""Checks the measurement object and calls respective function for related measurement inputs."""
|
||||||
|
|
@ -341,9 +393,10 @@ class delay(simulation):
|
||||||
Write the measure statements to quantify the power results for a write port.
|
Write the measure statements to quantify the power results for a write port.
|
||||||
"""
|
"""
|
||||||
# add measure statements for power
|
# add measure statements for power
|
||||||
for measure in self.write_meas_objs:
|
for meas_list in self.write_meas_lists:
|
||||||
measure_variant_inp_tuple = self.get_write_measure_variants(port, measure)
|
for measure in meas_list:
|
||||||
measure.write_measure(self.stim, measure_variant_inp_tuple)
|
measure_variant_inp_tuple = self.get_write_measure_variants(port, measure)
|
||||||
|
measure.write_measure(self.stim, measure_variant_inp_tuple)
|
||||||
|
|
||||||
def write_delay_measures(self):
|
def write_delay_measures(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -462,6 +515,7 @@ class delay(simulation):
|
||||||
#Sanity Check
|
#Sanity Check
|
||||||
debug.check(self.period > 0, "Target simulation period non-positive")
|
debug.check(self.period > 0, "Target simulation period non-positive")
|
||||||
|
|
||||||
|
sim_passed = True
|
||||||
result = [{} for i in self.all_ports]
|
result = [{} for i in self.all_ports]
|
||||||
# Checking from not data_value to data_value
|
# Checking from not data_value to data_value
|
||||||
self.write_delay_stimulus()
|
self.write_delay_stimulus()
|
||||||
|
|
@ -471,17 +525,18 @@ class delay(simulation):
|
||||||
#Loop through all targeted ports and collect delays and powers.
|
#Loop through all targeted ports and collect delays and powers.
|
||||||
#Too much duplicate code here. Try reducing
|
#Too much duplicate code here. Try reducing
|
||||||
for port in self.targ_read_ports:
|
for port in self.targ_read_ports:
|
||||||
debug.info(2, "Check delay values for port {}".format(port))
|
debug.info(2, "Checking delay values for port {}".format(port))
|
||||||
read_port_dict = {}
|
read_port_dict = {}
|
||||||
#Get measurements from output file
|
#Get measurements from output file
|
||||||
for measure in self.read_meas_objs:
|
for measure in self.read_lib_meas:
|
||||||
read_port_dict[measure.name] = measure.retrieve_measure(port=port)
|
read_port_dict[measure.name] = measure.retrieve_measure(port=port)
|
||||||
|
debug_passed = self.check_debug_measures(port, read_port_dict)
|
||||||
|
|
||||||
#Check timing for read ports. Power is only checked if it was read correctly
|
#Check timing for read ports. Power is only checked if it was read correctly
|
||||||
if not self.check_valid_delays(read_port_dict):
|
if not self.check_valid_delays(read_port_dict) or not debug_passed:
|
||||||
return (False,{})
|
return (False,{})
|
||||||
if not check_dict_values_is_float(read_port_dict):
|
if not check_dict_values_is_float(read_port_dict):
|
||||||
debug.error("Failed to Measure Read Port Values:\n\t\t{0}".format(read_port_dict),1) #Printing the entire dict looks bad.
|
debug.error("Failed to Measure Read Port Values:\n\t\t{0}".format(read_port_dict),1) #Printing the entire dict looks bad.
|
||||||
|
|
||||||
result[port].update(read_port_dict)
|
result[port].update(read_port_dict)
|
||||||
|
|
||||||
|
|
@ -490,7 +545,7 @@ class delay(simulation):
|
||||||
|
|
||||||
for port in self.targ_write_ports:
|
for port in self.targ_write_ports:
|
||||||
write_port_dict = {}
|
write_port_dict = {}
|
||||||
for measure in self.write_meas_objs:
|
for measure in self.write_lib_meas:
|
||||||
write_port_dict[measure.name] = measure.retrieve_measure(port=port)
|
write_port_dict[measure.name] = measure.retrieve_measure(port=port)
|
||||||
|
|
||||||
if not check_dict_values_is_float(write_port_dict):
|
if not check_dict_values_is_float(write_port_dict):
|
||||||
|
|
@ -498,13 +553,54 @@ class delay(simulation):
|
||||||
result[port].update(write_port_dict)
|
result[port].update(write_port_dict)
|
||||||
|
|
||||||
# The delay is from the negative edge for our SRAM
|
# The delay is from the negative edge for our SRAM
|
||||||
return (True,result)
|
return (sim_passed,result)
|
||||||
|
|
||||||
|
def check_debug_measures(self, port, read_measures):
|
||||||
|
"""Debug measures that indicate special conditions."""
|
||||||
|
#Currently, only check if the opposite than intended value was read during
|
||||||
|
# the read cycles i.e. neither of these measurements should pass.
|
||||||
|
success = True
|
||||||
|
for meas in self.debug_delay_meas:
|
||||||
|
val = meas.retrieve_measure(port=port)
|
||||||
|
debug.info(2,"{}={}".format(meas.name, val))
|
||||||
|
if type(val) != float:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if meas.meta_add_delay:
|
||||||
|
max_delay = self.period/2
|
||||||
|
else:
|
||||||
|
max_delay = self.period
|
||||||
|
|
||||||
|
#If the debug measurement occurs after the original (and passes other conditions)
|
||||||
|
#then it fails i.e. the debug value represents the final (but failing) state of the output
|
||||||
|
parent_compare = type(read_measures[meas.parent]) != float or val > read_measures[meas.parent]
|
||||||
|
if 0 < val < max_delay and parent_compare:
|
||||||
|
success = False
|
||||||
|
debug.info(1, "Debug measurement failed. Incorrect Value found on output.")
|
||||||
|
break
|
||||||
|
|
||||||
|
for meas in self.debug_volt_meas:
|
||||||
|
val = meas.retrieve_measure(port=port)
|
||||||
|
debug.info(2,"{}={}".format(meas.name, val))
|
||||||
|
if type(val) != float:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if meas.meta_str == 'read1' and val < tech.spice["v_threshold_typical"]:
|
||||||
|
success = False
|
||||||
|
debug.info(1, "Debug measurement failed. Value {}v was read on read 1 cycle.".format(val))
|
||||||
|
break
|
||||||
|
elif meas.meta_str == 'read0' and val > self.vdd_voltage-tech.spice["v_threshold_typical"]:
|
||||||
|
success = False
|
||||||
|
debug.info(1, "Debug measurement failed. Value {}v was read on read 0 cycle.".format(val))
|
||||||
|
break
|
||||||
|
|
||||||
|
return success
|
||||||
|
|
||||||
def evaluate_bitline_delay(self, port):
|
def evaluate_bitline_delay(self, port):
|
||||||
"""Parse and check the bitline delay. One of the measurements is expected to fail which warrants its own function."""
|
"""Parse and check the bitline delay. One of the measurements is expected to fail which warrants its own function."""
|
||||||
bl_delay_meas_dict = {}
|
bl_delay_meas_dict = {}
|
||||||
values_added = 0 #For error checking
|
values_added = 0 #For error checking
|
||||||
for measure in self.bitline_delay_objs:
|
for measure in self.bitline_delay_meas:
|
||||||
bl_delay_val = measure.retrieve_measure(port=port)
|
bl_delay_val = measure.retrieve_measure(port=port)
|
||||||
if type(bl_delay_val) != float or 0 > bl_delay_val or bl_delay_val > self.period/2: #Only add if value is valid, do not error.
|
if type(bl_delay_val) != float or 0 > bl_delay_val or bl_delay_val > self.period/2: #Only add if value is valid, do not error.
|
||||||
debug.error("Bitline delay measurement failed: half-period={}, {}={}".format(self.period/2, measure.name, bl_delay_val),1)
|
debug.error("Bitline delay measurement failed: half-period={}, {}={}".format(self.period/2, measure.name, bl_delay_val),1)
|
||||||
|
|
@ -556,7 +652,8 @@ class delay(simulation):
|
||||||
delays_str = "delay_hl={0} delay_lh={1}".format(delay_hl, delay_lh)
|
delays_str = "delay_hl={0} delay_lh={1}".format(delay_hl, delay_lh)
|
||||||
slews_str = "slew_hl={0} slew_lh={1}".format(slew_hl,slew_lh)
|
slews_str = "slew_hl={0} slew_lh={1}".format(slew_hl,slew_lh)
|
||||||
half_period = self.period/2 #high-to-low delays start at neg. clk edge, so they need to be less than half_period
|
half_period = self.period/2 #high-to-low delays start at neg. clk edge, so they need to be less than half_period
|
||||||
if abs(delay_hl)>half_period or abs(delay_lh)>self.period or abs(slew_hl)>half_period or abs(slew_lh)>self.period:
|
if abs(delay_hl)>half_period or abs(delay_lh)>self.period or abs(slew_hl)>half_period or abs(slew_lh)>self.period \
|
||||||
|
or delay_hl<0 or delay_lh<0 or slew_hl<0 or slew_lh<0:
|
||||||
debug.info(2,"UNsuccessful simulation (in ns):\n\t\t{0}\n\t\t{1}\n\t\t{2}".format(period_load_slew_str,
|
debug.info(2,"UNsuccessful simulation (in ns):\n\t\t{0}\n\t\t{1}\n\t\t{2}".format(period_load_slew_str,
|
||||||
delays_str,
|
delays_str,
|
||||||
slews_str))
|
slews_str))
|
||||||
|
|
|
||||||
|
|
@ -156,4 +156,32 @@ class voltage_when_measure(spice_measurement):
|
||||||
|
|
||||||
trig_voltage = self.trig_val_of_vdd*vdd_voltage
|
trig_voltage = self.trig_val_of_vdd*vdd_voltage
|
||||||
|
|
||||||
return (meas_name,trig_name,targ_name,trig_voltage,self.trig_dir_str,trig_td)
|
return (meas_name,trig_name,targ_name,trig_voltage,self.trig_dir_str,trig_td)
|
||||||
|
|
||||||
|
class voltage_at_measure(spice_measurement):
|
||||||
|
"""Generates a spice measurement to measure the voltage at a specific time.
|
||||||
|
The time is considered variant with different periods."""
|
||||||
|
|
||||||
|
def __init__(self, measure_name, targ_name, measure_scale=None):
|
||||||
|
spice_measurement.__init__(self, measure_name, measure_scale)
|
||||||
|
self.set_meas_constants(targ_name)
|
||||||
|
|
||||||
|
def get_measure_function(self):
|
||||||
|
return stimuli.gen_meas_find_voltage_at_time
|
||||||
|
|
||||||
|
def set_meas_constants(self, targ_name):
|
||||||
|
"""Sets values useful for power simulations. This value is only meta related to the lib file (rise/fall)"""
|
||||||
|
self.targ_name_no_port = targ_name
|
||||||
|
|
||||||
|
def get_measure_values(self, time_at, port=None):
|
||||||
|
"""Constructs inputs to stimulus measurement function. Variant values are inputs here."""
|
||||||
|
if port != None:
|
||||||
|
#For dictionary indexing reasons, the name is formatted differently than the signals
|
||||||
|
meas_name = "{}{}".format(self.name, port)
|
||||||
|
targ_name = self.targ_name_no_port.format(port)
|
||||||
|
else:
|
||||||
|
meas_name = self.name
|
||||||
|
targ_name = self.targ_name_no_port
|
||||||
|
|
||||||
|
return (meas_name,targ_name,time_at)
|
||||||
|
|
||||||
|
|
@ -226,6 +226,13 @@ class stimuli():
|
||||||
trig_dir,
|
trig_dir,
|
||||||
trig_td))
|
trig_td))
|
||||||
|
|
||||||
|
def gen_meas_find_voltage_at_time(self, meas_name, targ_name, time_at):
|
||||||
|
""" Creates the .meas statement for voltage at time"""
|
||||||
|
measure_string=".meas tran {0} FIND v({1}) AT={2}n \n\n"
|
||||||
|
self.sf.write(measure_string.format(meas_name,
|
||||||
|
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):
|
||||||
""" Creates the .meas statement for the measurement of avg power """
|
""" Creates the .meas statement for the measurement of avg power """
|
||||||
# power mea cmd is different in different spice:
|
# power mea cmd is different in different spice:
|
||||||
|
|
|
||||||
|
|
@ -26,10 +26,15 @@ class timing_sram_test(openram_test):
|
||||||
reload(characterizer)
|
reload(characterizer)
|
||||||
from characterizer import delay
|
from characterizer import delay
|
||||||
from sram_config import sram_config
|
from sram_config import sram_config
|
||||||
c = sram_config(word_size=1,
|
# c = sram_config(word_size=1,
|
||||||
num_words=16,
|
# num_words=16,
|
||||||
|
# num_banks=1)
|
||||||
|
# c.words_per_row=1
|
||||||
|
c = sram_config(word_size=32,
|
||||||
|
num_words=256,
|
||||||
num_banks=1)
|
num_banks=1)
|
||||||
c.words_per_row=1
|
c.words_per_row=2
|
||||||
|
OPTS.use_tech_delay_chain_size = True
|
||||||
c.recompute_sizes()
|
c.recompute_sizes()
|
||||||
debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank")
|
debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank")
|
||||||
s = factory.create(module_type="sram", sram_config=c)
|
s = factory.create(module_type="sram", sram_config=c)
|
||||||
|
|
@ -42,13 +47,13 @@ class timing_sram_test(openram_test):
|
||||||
s.s.graph_exclude_data_dff()
|
s.s.graph_exclude_data_dff()
|
||||||
s.s.graph_exclude_ctrl_dffs()
|
s.s.graph_exclude_ctrl_dffs()
|
||||||
|
|
||||||
debug.info(1,'pins={}'.format(s.s.pins))
|
# debug.info(1,'pins={}'.format(s.s.pins))
|
||||||
import graph_util
|
# import graph_util
|
||||||
graph = graph_util.timing_graph()
|
# graph = graph_util.timing_graph()
|
||||||
pins=['DIN0[0]', 'ADDR0[0]', 'ADDR0[1]', 'ADDR0[2]', 'ADDR0[3]', 'csb0', 'web0', 'clk0', 'DOUT0[0]', 'vdd', 'gnd']
|
# pins=['DIN0[0]', 'ADDR0[0]', 'ADDR0[1]', 'ADDR0[2]', 'ADDR0[3]', 'csb0', 'web0', 'clk0', 'DOUT0[0]', 'vdd', 'gnd']
|
||||||
s.s.build_graph(graph,"Xsram",pins)
|
# s.s.build_graph(graph,"Xsram",pins)
|
||||||
#debug.info(1,"{}".format(graph))
|
# #debug.info(1,"{}".format(graph))
|
||||||
graph.print_all_paths('clk0', 'DOUT0[0]')
|
# graph.print_all_paths('clk0', 'DOUT0[0]')
|
||||||
# import sys
|
# import sys
|
||||||
# sys.exit(1)
|
# sys.exit(1)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue