mirror of https://github.com/VLSIDA/OpenRAM.git
Added debug measurements along main delay paths in SRAM. WIP.
This commit is contained in:
parent
84ba5c55d1
commit
eaf285639a
|
|
@ -117,6 +117,14 @@ class timing_graph():
|
|||
cur_slew = delays[-1].slew
|
||||
|
||||
return delays
|
||||
|
||||
def get_edge_mods(self, path):
|
||||
"""Return all edge mods associated with path"""
|
||||
|
||||
if len(path) == 0:
|
||||
return []
|
||||
|
||||
return [self.edge_mods[(path[i], path[i+1])] for i in range(len(path)-1)]
|
||||
|
||||
def __str__(self):
|
||||
""" override print function output """
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ class delay(simulation):
|
|||
read_measures.append(self.create_bitline_measurement_objects())
|
||||
read_measures.append(self.create_debug_measurement_objects())
|
||||
read_measures.append(self.create_read_bit_measures())
|
||||
read_measures.append(self.create_sen_and_bitline_path_measures())
|
||||
|
||||
return read_measures
|
||||
|
||||
|
|
@ -249,6 +250,95 @@ class delay(simulation):
|
|||
qbar_meas = voltage_at_measure("v_qbar_{}".format(meas_tag), qbar_name)
|
||||
|
||||
return {bit_polarity.NONINVERTING: q_meas, bit_polarity.INVERTING: qbar_meas}
|
||||
|
||||
def create_sen_and_bitline_path_measures(self):
|
||||
"""Create measurements for the s_en and bitline paths for individual delays per stage."""
|
||||
|
||||
# FIXME: There should be a default_read_port variable in this case, pathing is done with this
|
||||
# but is never mentioned otherwise
|
||||
port = self.read_ports[0]
|
||||
sen_and_port = self.sen_name+str(port)
|
||||
bl_and_port = self.bl_name.format(port) # bl_name contains a '{}' for the port
|
||||
# Isolate the s_en and bitline paths
|
||||
debug.info(1, "self.bl_name = {}".format(self.bl_name))
|
||||
debug.info(1, "self.graph.all_paths = {}".format(self.graph.all_paths))
|
||||
sen_paths = [path for path in self.graph.all_paths if sen_and_port in path]
|
||||
bl_paths = [path for path in self.graph.all_paths if bl_and_port in path]
|
||||
debug.check(len(sen_paths)==1, 'Found {} paths which contain the s_en net.'.format(len(sen_paths)))
|
||||
debug.check(len(bl_paths)==1, 'Found {} paths which contain the bitline net.'.format(len(bl_paths)))
|
||||
sen_path = sen_paths[0]
|
||||
bitline_path = bl_paths[0]
|
||||
|
||||
# Get the measures
|
||||
self.sen_path_meas = self.create_delay_path_measures(sen_path)
|
||||
self.bl_path_meas = self.create_delay_path_measures(bitline_path)
|
||||
all_meas = self.sen_path_meas + self.bl_path_meas
|
||||
|
||||
# Paths could have duplicate measurements, remove them before they go to the stim file
|
||||
all_meas = self.remove_duplicate_meas_names(all_meas)
|
||||
# FIXME: duplicate measurements still exist in the member variables, since they have the same
|
||||
# name it will still work, but this could cause an issue in the future.
|
||||
|
||||
return all_meas
|
||||
|
||||
def remove_duplicate_meas_names(self, measures):
|
||||
"""Returns new list of measurements without duplicate names"""
|
||||
|
||||
name_set = set()
|
||||
unique_measures = []
|
||||
for meas in measures:
|
||||
if meas.name not in name_set:
|
||||
name_set.add(meas.name)
|
||||
unique_measures.append(meas)
|
||||
|
||||
return unique_measures
|
||||
|
||||
def create_delay_path_measures(self, path):
|
||||
"""Creates measurements for each net along given path."""
|
||||
|
||||
# Determine the directions (RISE/FALL) of signals
|
||||
path_dirs = self.get_meas_directions(path)
|
||||
|
||||
# Create the measurements
|
||||
path_meas = []
|
||||
for i in range(len(path)-1):
|
||||
cur_net, next_net = path[i], path[i+1]
|
||||
cur_dir, next_dir = path_dirs[i], path_dirs[i+1]
|
||||
meas_name = "delay_{}_to_{}".format(cur_net, next_net)
|
||||
path_meas.append(delay_measure(meas_name, cur_net, next_net, cur_dir, next_dir, measure_scale=1e9, has_port=False))
|
||||
# Some bitcell logic is hardcoded for only read zeroes, force that here as well.
|
||||
path_meas[-1].meta_str = sram_op.READ_ZERO
|
||||
path_meas[-1].meta_add_delay = True
|
||||
|
||||
return path_meas
|
||||
|
||||
def get_meas_directions(self, path):
|
||||
"""Returns SPICE measurements directions based on path."""
|
||||
|
||||
# Get the edges modules which define the path
|
||||
edge_mods = self.graph.get_edge_mods(path)
|
||||
|
||||
# Convert to booleans based on function of modules (inverting/non-inverting)
|
||||
mod_type_bools = [mod.is_non_inverting() for mod in edge_mods]
|
||||
|
||||
#FIXME: obtuse hack to differentiate s_en input from bitline in sense amps
|
||||
if self.sen_name in path:
|
||||
# Force the sense amp to be inverting for s_en->DOUT.
|
||||
# bitline->DOUT is non-inverting, but the module cannot differentiate inputs.
|
||||
s_en_index = path.index(self.sen_name)
|
||||
mod_type_bools[s_en_index] = False
|
||||
debug.info(2,'Forcing sen->dout to be inverting.')
|
||||
|
||||
# Use these to determine direction list assuming delay start on neg. edge of clock (FALL)
|
||||
# Also, use shorthand that 'FALL' == False, 'RISE' == True to simplify logic
|
||||
bool_dirs = [False]
|
||||
cur_dir = False # All Paths start on FALL edge of clock
|
||||
for mod_bool in mod_type_bools:
|
||||
cur_dir = (cur_dir == mod_bool)
|
||||
bool_dirs.append(cur_dir)
|
||||
|
||||
# Convert from boolean to string
|
||||
return ['RISE' if dbool else 'FALL' for dbool in bool_dirs]
|
||||
|
||||
def set_load_slew(self, load, slew):
|
||||
""" Set the load and slew """
|
||||
|
|
|
|||
Loading…
Reference in New Issue