Cleaned up graph additions to characterizer.

This commit is contained in:
Hunter Nichols 2019-06-25 16:37:35 -07:00
parent 33c17ac41c
commit 4f3340e973
4 changed files with 18 additions and 55 deletions

View File

@ -56,7 +56,7 @@ class timing_graph():
# Call the recursive helper function to print all paths
self.get_all_paths_util(src_node, dest_node, visited, path)
debug.info(1, "Paths found={}".format(len(self.all_paths)))
debug.info(2, "Paths found={}".format(len(self.all_paths)))
return self.all_paths
@ -69,7 +69,6 @@ class timing_graph():
# If current vertex is same as destination, then print
# current path[]
if cur_node == dest_node:
debug.info(1,"{}".format(path))
self.all_paths.append(copy.deepcopy(path))
else:
# If current vertex is not destination
@ -82,20 +81,6 @@ class timing_graph():
path.pop()
visited.remove(cur_node)
def get_path_preconvergence_point(self, path1, path2):
"""Assuming the inputs paths have the same starting point and end point, the
paths should split and converge at some point before/at the last stage. Finds the
point before convergence."""
debug.check(path1[0] == path2[0], "Paths must start from the same point.")
debug.check(path1[-1] == path2[-1], "Paths must end from the same point.")
#Paths must end at the same point, so the paths are traversed backwards to find
#point of convergence. There could be multiple points, only finds first.
for point1,point2 in zip(reversed(path1), reversed(path2)):
if point1 != point2:
return (point1,point2)
debug.info(1,"Pre-convergence point not found, paths are equals.")
return path1[0],path2[0]
def __str__(self):
""" override print function output """
return "Nodes: {}\nEdges:{} ".format(list(self.graph), self.graph)

View File

@ -147,7 +147,6 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
"""Given a list of nets, will compare the internal alias of a mod to determine
if the nets have a connection to this mod's net (but not inst).
"""
#path_nets = ['xsram_0.xbank0.bl0_7']
if exclusion_set == None:
exclusion_set = set()
try:
@ -155,31 +154,17 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
except AttributeError:
self.name_dict = {}
self.build_names(self.name_dict, inst_name, port_nets)
#debug.info(1,"names={}".format(list(self.name_dict)))
aliases = []
for net in path_nets:
net = net.lower()
int_net = self.name_dict[net]['int_net']
int_mod = self.name_dict[net]['mod']
# debug.info(1,"int_net={}".format(int_net))
# debug.info(1,"int_mod={}".format(int_mod.name))
# debug.info(1,"alias_net={}".format(alias))
# debug.info(1,"alias_mod={}".format(alias_mod.name))
# debug.info(1,"mod id={}".format(id(alias_mod)))
if int_mod.is_net_alias(int_net, alias, alias_mod, exclusion_set):
aliases.append(net)
# debug.info(1,"Alias found\n")
# else:
# debug.info(1,"Alias not found\n")
debug.info(1,"Aliases Found={}".format(aliases))
return aliases
def is_net_alias(self, known_net, net_alias, mod, exclusion_set):
"""Checks if the alias_net in mod is the same as the input net."""
# debug.info(1,"self name={}".format(self.name))
# debug.info(1,"self mod id={}".format(id(self)))
# debug.info(1,"self pins={}".format(self.pins))
# debug.info(1,"known_net={}".format(known_net))
"""Checks if the alias_net in input mod is the same as the input net for this mod (self)."""
if self in exclusion_set:
return False
#Check ports of this mod
@ -193,8 +178,6 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
if self.is_net_alias_name_check(known_net, inst_conn, net_alias, mod):
return True
elif inst_conn.lower() == known_net.lower() and subinst.mod not in mod_set:
# debug.info(1,"found matching conn={}".format(inst_conn))
# debug.info(1,"Setting known pin={}".format(mod_pin))
if subinst.mod.is_net_alias(mod_pin, net_alias, mod, exclusion_set):
return True
mod_set.add(subinst.mod)

View File

@ -216,16 +216,18 @@ class delay(simulation):
self.graph = graph_util.timing_graph()
self.sram_spc_name = "X{}".format(self.sram.name)
self.sram.build_graph(self.graph,self.sram_spc_name,self.pins)
#debug.info(1,"{}".format(self.graph))
def set_internal_spice_names(self):
"""Sets important names for characterization such as Sense amp enable and internal bit nets."""
port = 0
self.graph.get_all_paths('{}{}'.format(tech.spice["clk"], port), \
'{}{}_{}'.format(self.dout_name, port, self.probe_data))
self.sen_name = self.get_sen_name(self.graph.all_paths)
debug.info(1,"s_en name = {}".format(self.sen_name))
debug.info(2,"s_en name = {}".format(self.sen_name))
self.bl_name,self.br_name = self.get_bl_name(self.graph.all_paths)
debug.info(1,"bl name={}, br name={}".format(self.bl_name,self.br_name))
debug.info(2,"bl name={}, br name={}".format(self.bl_name,self.br_name))
def get_sen_name(self, paths):
"""Gets the signal name associated with the sense amp enable from input paths.
@ -245,13 +247,7 @@ class delay(simulation):
cell_mod = self.get_primary_cell_mod(cell_mods)
elif len(cell_mods)==0:
debug.error("No bitcells found. Cannot determine bitline names.", 1)
#Any sense amp instantiated should be identical, any change to that
#will require some identification to determine the mod desired.
# debug.check(self.are_mod_pins_equal(cell_mods), "Only expected one type of bitcell. Cannot perform bitline checks")
# debug.info(1,"num pbitcells={}".format(len(cell_mods)))
# debug.info(1,"cell ids={}".format([id(i) for i in cell_mods]))
#cell_mods = cell_mods[1:]
cell_bl = cell_mod.get_bl_name()
cell_br = cell_mod.get_br_name()
@ -705,9 +701,8 @@ class delay(simulation):
def check_sen_measure(self, port):
"""Checks that the sen occurred within a half-period"""
self.sen_meas
sen_val = self.sen_meas.retrieve_measure(port=port)
debug.info(1,"S_EN delay={} ns".format(sen_val))
debug.info(2,"S_EN delay={} ns".format(sen_val))
if self.sen_meas.meta_add_delay:
max_delay = self.period/2
else:
@ -729,7 +724,7 @@ class delay(simulation):
elif self.br_name == meas.targ_name_no_port:
br_vals[meas.meta_str] = val
debug.info(1,"{}={}".format(meas.name,val))
debug.info(2,"{}={}".format(meas.name,val))
bl_check = False
for meas in self.debug_volt_meas:
@ -762,24 +757,23 @@ class delay(simulation):
for polarity, meas_list in self.bit_meas.items():
for meas in meas_list:
val = meas.retrieve_measure()
debug.info(1,"{}={}".format(meas.name, val))
debug.info(2,"{}={}".format(meas.name, val))
if type(val) != float:
continue
meas_cycle = meas.meta_str
#Loose error conditions. Assume it's not metastable but account for noise during reads.
if (meas_cycle == sram_op.READ_ZERO and polarity == bit_polarity.NONINVERTING) or\
(meas_cycle == sram_op.READ_ONE and polarity == bit_polarity.INVERTING):
success = val < self.vdd_voltage*.1
success = val < self.vdd_voltage/2
elif (meas_cycle == sram_op.READ_ZERO and polarity == bit_polarity.INVERTING) or\
(meas_cycle == sram_op.READ_ONE and polarity == bit_polarity.NONINVERTING):
success = val > self.vdd_voltage*.9
success = val > self.vdd_voltage/2
if not success:
debug.info(1,("Wrong value detected on probe bit during read cycle. "
"Check writes and control logic for bugs.\n measure={}, op={}, "
"bit_storage={}").format(meas.name, meas_cycle.name, polarity.name))
"bit_storage={}, V(bit)={}").format(meas.name, meas_cycle.name, polarity.name,val))
return success
def check_bitline_meas(self, v_discharged_bl, v_charged_bl):
"""Checks the value of the discharging bitline. Confirms s_en timing errors.
Returns true if the bitlines are at there expected value."""
@ -991,6 +985,7 @@ class delay(simulation):
"""Sets values which are dependent on the data address/bit being tested."""
self.set_probe(probe_address, probe_data)
self.create_graph()
self.set_internal_spice_names()
self.create_measurement_names()
self.create_measurement_objects()

View File

@ -18,7 +18,7 @@ class pand2(pgate.pgate):
This is a simple buffer used for driving loads.
"""
def __init__(self, name, size=1, height=None):
debug.info(1, "reating pnand2 {}".format(name))
debug.info(1, "Creating pnand2 {}".format(name))
self.add_comment("size: {}".format(size))
self.size = size