mirror of https://github.com/VLSIDA/OpenRAM.git
Fix duplicate paths for timing checks
This commit is contained in:
parent
80df996720
commit
0bb41b8a5d
|
|
@ -10,7 +10,8 @@ from vector import vector
|
||||||
from pin_layout import pin_layout
|
from pin_layout import pin_layout
|
||||||
|
|
||||||
class timing_graph():
|
class timing_graph():
|
||||||
"""Implements a directed graph
|
"""
|
||||||
|
Implements a directed graph
|
||||||
Nodes are currently just Strings.
|
Nodes are currently just Strings.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
@ -20,30 +21,34 @@ class timing_graph():
|
||||||
|
|
||||||
def add_edge(self, src_node, dest_node):
|
def add_edge(self, src_node, dest_node):
|
||||||
"""Adds edge to graph. Nodes added as well if they do not exist."""
|
"""Adds edge to graph. Nodes added as well if they do not exist."""
|
||||||
|
|
||||||
src_node = src_node.lower()
|
src_node = src_node.lower()
|
||||||
dest_node = dest_node.lower()
|
dest_node = dest_node.lower()
|
||||||
self.graph[src_node].add(dest_node)
|
self.graph[src_node].add(dest_node)
|
||||||
|
|
||||||
def add_node(self, node):
|
def add_node(self, node):
|
||||||
"""Add node to graph with no edges"""
|
"""Add node to graph with no edges"""
|
||||||
|
|
||||||
node = node.lower()
|
node = node.lower()
|
||||||
if not node in self.graph:
|
if not node in self.graph:
|
||||||
self.graph[node] = set()
|
self.graph[node] = set()
|
||||||
|
|
||||||
def remove_edges(self, node):
|
def remove_edges(self, node):
|
||||||
|
|
||||||
"""Helper function to remove edges, useful for removing vdd/gnd"""
|
"""Helper function to remove edges, useful for removing vdd/gnd"""
|
||||||
node = node.lower()
|
node = node.lower()
|
||||||
self.graph[node] = set()
|
self.graph[node] = set()
|
||||||
|
|
||||||
def get_all_paths(self, src_node, dest_node, rmv_rail_nodes=True):
|
def get_all_paths(self, src_node, dest_node, remove_rail_nodes=True, reduce_paths=True):
|
||||||
"""Traverse all paths from source to destination"""
|
"""Traverse all paths from source to destination"""
|
||||||
|
|
||||||
src_node = src_node.lower()
|
src_node = src_node.lower()
|
||||||
dest_node = dest_node.lower()
|
dest_node = dest_node.lower()
|
||||||
|
|
||||||
#Remove vdd and gnd by default
|
# Remove vdd and gnd by default
|
||||||
#Will require edits if separate supplies are implemented.
|
# Will require edits if separate supplies are implemented.
|
||||||
if rmv_rail_nodes:
|
if remove_rail_nodes:
|
||||||
#Names are also assumed.
|
# Names are also assumed.
|
||||||
self.remove_edges('vdd')
|
self.remove_edges('vdd')
|
||||||
self.remove_edges('gnd')
|
self.remove_edges('gnd')
|
||||||
|
|
||||||
|
|
@ -58,10 +63,19 @@ class timing_graph():
|
||||||
self.get_all_paths_util(src_node, dest_node, visited, path)
|
self.get_all_paths_util(src_node, dest_node, visited, path)
|
||||||
debug.info(2, "Paths found={}".format(len(self.all_paths)))
|
debug.info(2, "Paths found={}".format(len(self.all_paths)))
|
||||||
|
|
||||||
|
if reduce_paths:
|
||||||
|
self.reduce_paths()
|
||||||
|
|
||||||
return self.all_paths
|
return self.all_paths
|
||||||
|
|
||||||
|
def reduce_paths(self):
|
||||||
|
""" Remove any path that is a subset of another path """
|
||||||
|
|
||||||
|
self.all_paths = [p1 for p1 in self.all_paths if not any(set(p1)<=set(p2) for p2 in self.all_paths if p1 is not p2)]
|
||||||
|
|
||||||
def get_all_paths_util(self, cur_node, dest_node, visited, path):
|
def get_all_paths_util(self, cur_node, dest_node, visited, path):
|
||||||
"""Recursive function to find all paths in a Depth First Search manner"""
|
"""Recursive function to find all paths in a Depth First Search manner"""
|
||||||
|
|
||||||
# Mark the current node as visited and store in path
|
# Mark the current node as visited and store in path
|
||||||
visited.add(cur_node)
|
visited.add(cur_node)
|
||||||
path.append(cur_node)
|
path.append(cur_node)
|
||||||
|
|
@ -72,7 +86,7 @@ class timing_graph():
|
||||||
self.all_paths.append(copy.deepcopy(path))
|
self.all_paths.append(copy.deepcopy(path))
|
||||||
else:
|
else:
|
||||||
# If current vertex is not destination
|
# If current vertex is not destination
|
||||||
#Recur for all the vertices adjacent to this vertex
|
# Recur for all the vertices adjacent to this vertex
|
||||||
for node in self.graph[cur_node]:
|
for node in self.graph[cur_node]:
|
||||||
if node not in visited:
|
if node not in visited:
|
||||||
self.get_all_paths_util(node, dest_node, visited, path)
|
self.get_all_paths_util(node, dest_node, visited, path)
|
||||||
|
|
@ -83,4 +97,5 @@ class timing_graph():
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
""" override print function output """
|
""" override print function output """
|
||||||
|
|
||||||
return "Nodes: {}\nEdges:{} ".format(list(self.graph), self.graph)
|
return "Nodes: {}\nEdges:{} ".format(list(self.graph), self.graph)
|
||||||
|
|
@ -909,6 +909,7 @@ class control_logic(design.design):
|
||||||
|
|
||||||
def get_wl_sen_delays(self):
|
def get_wl_sen_delays(self):
|
||||||
"""Gets a list of the stages and delays in order of their path."""
|
"""Gets a list of the stages and delays in order of their path."""
|
||||||
|
|
||||||
if self.sen_stage_efforts == None or self.wl_stage_efforts == None:
|
if self.sen_stage_efforts == None or self.wl_stage_efforts == None:
|
||||||
debug.error("Model delays not calculated for SRAM.", 1)
|
debug.error("Model delays not calculated for SRAM.", 1)
|
||||||
wl_delays = logical_effort.calculate_delays(self.wl_stage_efforts)
|
wl_delays = logical_effort.calculate_delays(self.wl_stage_efforts)
|
||||||
|
|
@ -917,6 +918,7 @@ class control_logic(design.design):
|
||||||
|
|
||||||
def analytical_delay(self, corner, slew, load):
|
def analytical_delay(self, corner, slew, load):
|
||||||
"""Gets the analytical delay from clk input to wl_en output"""
|
"""Gets the analytical delay from clk input to wl_en output"""
|
||||||
|
|
||||||
stage_effort_list = []
|
stage_effort_list = []
|
||||||
#Calculate the load on clk_buf_bar
|
#Calculate the load on clk_buf_bar
|
||||||
ext_clk_buf_cout = self.sram.get_clk_bar_cin()
|
ext_clk_buf_cout = self.sram.get_clk_bar_cin()
|
||||||
|
|
@ -944,8 +946,10 @@ class control_logic(design.design):
|
||||||
return stage_effort_list
|
return stage_effort_list
|
||||||
|
|
||||||
def get_clk_buf_cin(self):
|
def get_clk_buf_cin(self):
|
||||||
"""Get the loads that are connected to the buffered clock.
|
"""
|
||||||
Includes all the DFFs and some logic."""
|
Get the loads that are connected to the buffered clock.
|
||||||
|
Includes all the DFFs and some logic.
|
||||||
|
"""
|
||||||
|
|
||||||
#Control logic internal load
|
#Control logic internal load
|
||||||
int_clk_buf_cap = self.inv.get_cin() + self.ctrl_dff_array.get_clk_cin() + self.and2.get_cin()
|
int_clk_buf_cap = self.inv.get_cin() + self.ctrl_dff_array.get_clk_cin() + self.and2.get_cin()
|
||||||
|
|
@ -957,6 +961,7 @@ class control_logic(design.design):
|
||||||
|
|
||||||
def get_gated_clk_bar_cin(self):
|
def get_gated_clk_bar_cin(self):
|
||||||
"""Get intermediates net gated_clk_bar's capacitance"""
|
"""Get intermediates net gated_clk_bar's capacitance"""
|
||||||
|
|
||||||
total_cin = 0
|
total_cin = 0
|
||||||
total_cin += self.wl_en_driver.get_cin()
|
total_cin += self.wl_en_driver.get_cin()
|
||||||
if self.port_type == 'rw':
|
if self.port_type == 'rw':
|
||||||
|
|
@ -965,4 +970,6 @@ class control_logic(design.design):
|
||||||
|
|
||||||
def graph_exclude_dffs(self):
|
def graph_exclude_dffs(self):
|
||||||
"""Exclude dffs from graph as they do not represent critical path"""
|
"""Exclude dffs from graph as they do not represent critical path"""
|
||||||
|
|
||||||
self.graph_inst_exclude.add(self.ctrl_dff_inst)
|
self.graph_inst_exclude.add(self.ctrl_dff_inst)
|
||||||
|
self.graph_inst_exclude.add(self.w_en_gate_inst)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue