mirror of https://github.com/VLSIDA/OpenRAM.git
Cleaned up graph additions to characterizer.
This commit is contained in:
parent
33c17ac41c
commit
4f3340e973
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue