Avoid blockages when connecting Hanan points

This commit is contained in:
Eren Dogan 2023-05-22 18:16:49 -07:00
parent 648a631a28
commit 33f1b924a4
4 changed files with 50 additions and 27 deletions

View File

@ -78,13 +78,19 @@ class navigation_graph:
min_neighbor = None
for j in range(i + 1, len(self.nodes)):
neighbor = self.nodes[j]
# Skip if not on the same layer
if node.center.z != neighbor.center.z:
continue
# Calculate the distance vector and distance value
distance_vector = neighbor.center - node.center
distance = node.center.distance(neighbor.center)
# Skip if not connected rectilinearly
if (distance_vector.x or (distance_vector.y * d.y <= 0)) and \
(distance_vector.y or (distance_vector.x * d.x <= 0)):
continue
# Skip if this connection is blocked by a blockage
if is_probe_blocked(node.center, neighbor.center, self.graph_blockages):
continue
if distance < min_dist:
min_dist = distance
min_neighbor = neighbor
@ -156,7 +162,7 @@ class navigation_graph:
# Update neighbor scores
for node in current.neighbors:
tentative_score = self.get_edge_cost(current, node) + g_scores[current.id]
tentative_score = current.get_edge_cost(node) + g_scores[current.id]
if node.id not in g_scores or tentative_score < g_scores[node.id]:
came_from[node.id] = current
g_scores[node.id] = tentative_score
@ -165,16 +171,3 @@ class navigation_graph:
# Return None if not connected
return None
def get_edge_cost(self, source, target):
""" """
if target in source.neighbors:
is_vertical = source.center.x == target.center.x
layer_dist = source.center.distance(target.center)
if is_vertical != bool(source.center.z):
layer_dist *= 2
via_dist = abs(source.center.z - target.center.z) * 2
return layer_dist + via_dist
return float("inf")

View File

@ -40,9 +40,14 @@ class navigation_node:
node.neighbors.remove(self)
def get_edge_cost(self, node):
""" Return the cost of going to node. """
def get_edge_cost(self, other):
""" Get the cost of going from this node to the other node. """
if node in self.neighbors:
return self.center.distance(node.center) + abs(self.center.z - node.center.z)
if other in self.neighbors:
is_vertical = self.center.x == other.center.x
layer_dist = self.center.distance(other.center)
if is_vertical != bool(self.center.z):
layer_dist *= 2
via_dist = abs(self.center.z - other.center.z) * 2
return layer_dist + via_dist
return float("inf")

View File

@ -35,7 +35,8 @@ class navigation_router(router_tech):
def route(self, vdd_name="vdd", gnd_name="gnd"):
""" Route the given pins in the given order. """
debug.info(1, "Running router for {}...".format(pins))
#debug.info(1, "Running router for {}...".format(pins))
self.write_debug_gds(gds_name="before.gds")
# Prepare gdsMill to find pins and blockages
self.design.gds_write(self.gds_filename)
@ -63,7 +64,7 @@ class navigation_router(router_tech):
# Create the path shapes on layout
self.add_path(path)
self.write_debug_gds(source=vdd_0, target=vdd_1)
self.write_debug_gds(gds_name="after.gds", source=vdd_0, target=vdd_1)
def find_pins(self, pin_name):
@ -142,13 +143,14 @@ class navigation_router(router_tech):
""" """
# Display the inflated blockage
for blockage in self.nav.graph_blockages:
self.add_object_info(blockage, "blockage")
for node in self.nav.nodes:
offset = (node.center.x, node.center.y)
self.design.add_label(text="O",
layer="text",
offset=offset)
if "nav" in self.__dict__:
for blockage in self.nav.graph_blockages:
self.add_object_info(blockage, "blockage")
for node in self.nav.nodes:
offset = (node.center.x, node.center.y)
self.design.add_label(text="O",
layer="text",
offset=offset)
if source:
self.add_object_info(source, "source")
if target:

View File

@ -7,6 +7,29 @@
Utility functions for navigation router.
"""
def is_probe_blocked(p1, p2, blockages):
"""
Return if a probe sent from p1 to p2 encounters a blockage.
The probe must be sent vertically or horizontally.
This method assumes that blockages are rectangular.
"""
# Check if any blockage blocks this probe
for blockage in blockages:
ll, ur = blockage.rect
right_x = ur[0]
upper_y = ur[1]
left_x = ll[0]
lower_y = ll[1]
# Check if blocked vertically
if is_between(left_x, right_x, p1.x) and (is_between(p1.y, p2.y, upper_y) or is_between(p1.y, p2.y, lower_y)):
return True
# Check if blocked horizontally
if is_between(upper_y, lower_y, p1.y) and (is_between(p1.x, p2.x, left_x) or is_between(p1.x, p2.x, right_x)):
return True
return False
def is_in_region(point, region):
""""""