Connect graph nodes better by hopping over removed nodes

This commit is contained in:
Eren Dogan 2023-07-17 15:02:36 -07:00
parent e501e0ef4f
commit 38110a55e1
2 changed files with 45 additions and 35 deletions

View File

@ -90,7 +90,6 @@ class graph:
# Create the graph # Create the graph
x_values, y_values = self.generate_cartesian_values() x_values, y_values = self.generate_cartesian_values()
self.generate_graph_nodes(x_values, y_values) self.generate_graph_nodes(x_values, y_values)
self.remove_blocked_nodes()
self.save_end_nodes() self.save_end_nodes()
debug.info(3, "Number of nodes in the routing graph: {}".format(len(self.nodes))) debug.info(3, "Number of nodes in the routing graph: {}".format(len(self.nodes)))
@ -109,6 +108,7 @@ class graph:
y_offset = vector(0, self.router.offset) y_offset = vector(0, self.router.offset)
for shape in [self.source, self.target]: for shape in [self.source, self.target]:
aspect_ratio = shape.width() / shape.height() aspect_ratio = shape.width() / shape.height()
# FIXME: Aspect ratio may not be the best way to determine this
# If the pin is tall or fat, add two points on the ends # If the pin is tall or fat, add two points on the ends
if aspect_ratio <= 0.5: # Tall pin if aspect_ratio <= 0.5: # Tall pin
points = [shape.bc() + y_offset, shape.uc() - y_offset] points = [shape.bc() + y_offset, shape.uc() - y_offset]
@ -124,7 +124,7 @@ class graph:
offset = drc["grid"] offset = drc["grid"]
for blockage in self.graph_blockages: for blockage in self.graph_blockages:
ll, ur = blockage.rect ll, ur = blockage.rect
# Add minimum offset to the blockage corner nodes to prevent overlaps # Add minimum offset to the blockage corner nodes to prevent overlap
x_values.update([ll.x - offset, ur.x + offset]) x_values.update([ll.x - offset, ur.x + offset])
y_values.update([ll.y - offset, ur.y + offset]) y_values.update([ll.y - offset, ur.y + offset])
@ -143,44 +143,45 @@ class graph:
orthogonal neighbors. orthogonal neighbors.
""" """
y_len = len(y_values) # Generate all nodes
left_offset = -(y_len * 2)
self.nodes = [] self.nodes = []
for x in x_values: for x in x_values:
for y in y_values: for y in y_values:
below_node = graph_node([x, y, 0]) for z in [0, 1]:
above_node = graph_node([x, y, 1]) self.nodes.append(graph_node([x, y, z]))
# Connect these two neighbors # Mark nodes that will be removed
below_node.add_neighbor(above_node) self.mark_blocked_nodes()
# Find potential orthogonal neighbor nodes # Connect closest nodes that won't be removed
belows = [] def search(index, condition, shift):
aboves = [] """ Search and connect neighbor nodes. """
count = len(self.nodes) // 2 base_nodes = self.nodes[index:index+2]
if count % y_len: # Down found = [hasattr(base_nodes[0], "remove"),
belows.append(-2) hasattr(base_nodes[1], "remove")]
aboves.append(-1) while condition(index) and not all(found):
if count >= y_len: # Left nodes = self.nodes[index - shift:index - shift + 2]
belows.append(left_offset) for k in range(2):
aboves.append(left_offset + 1) if not found[k] and not hasattr(nodes[k], "remove"):
found[k] = True
if not self.is_probe_blocked(base_nodes[k].center, nodes[k].center):
base_nodes[k].add_neighbor(nodes[k])
index -= shift
y_len = len(y_values)
for i in range(0, len(self.nodes), 2):
search(i, lambda count: (count / 2) % y_len, 2) # Down
search(i, lambda count: (count / 2) >= y_len, y_len * 2) # Left
# FIXME: Avoid vias for inter-layer edges
if not hasattr(self.nodes[i], "remove") and \
not hasattr(self.nodes[i + 1], "remove"):
self.nodes[i].add_neighbor(self.nodes[i + 1])
# Add these connections if not blocked by a blockage # Remove marked nodes
for i in belows: self.remove_blocked_nodes()
node = self.nodes[i]
if not self.is_probe_blocked(below_node.center, node.center):
below_node.add_neighbor(node)
for i in aboves:
node = self.nodes[i]
if not self.is_probe_blocked(above_node.center, node.center):
above_node.add_neighbor(node)
self.nodes.append(below_node)
self.nodes.append(above_node)
def remove_blocked_nodes(self): def mark_blocked_nodes(self):
""" Remove the graph nodes that are blocked by a blockage. """ """ Mark graph nodes to be removed that are blocked by a blockage. """
for i in range(len(self.nodes) - 1, -1, -1): for i in range(len(self.nodes) - 1, -1, -1):
node = self.nodes[i] node = self.nodes[i]
@ -190,11 +191,20 @@ class graph:
# If the blockage is an inflated routable, remove if outside # If the blockage is an inflated routable, remove if outside
# the routable shape # the routable shape
if self.inside_shape(point, blockage) and (not self.is_routable(blockage) or not self.inside_shape(point, blockage.inflated_from)): if self.inside_shape(point, blockage) and (not self.is_routable(blockage) or not self.inside_shape(point, blockage.inflated_from)):
node.remove_all_neighbors() node.remove = True
self.nodes.remove(node)
break break
def remove_blocked_nodes(self):
""" Remove graph nodes that are marked to be removed. """
for i in range(len(self.nodes) - 1, -1, -1):
node = self.nodes[i]
if hasattr(node, "remove"):
node.remove_all_neighbors()
self.nodes.remove(node)
def save_end_nodes(self): def save_end_nodes(self):
""" Save graph nodes that are inside source and target pins. """ """ Save graph nodes that are inside source and target pins. """

View File

@ -152,7 +152,7 @@ class graph_router(router_tech):
def find_blockages(self, shape_name=None): def find_blockages(self, shape_name=None):
""" Find all blockages in the routing layers. """ """ Find all blockages in the routing layers. """
debug.info(1, "Finding blockages...") debug.info(2, "Finding blockages...")
# Keep current blockages here # Keep current blockages here
prev_blockages = self.blockages[:] prev_blockages = self.blockages[:]