Simplify Hanan graph generation

This commit is contained in:
Eren Dogan 2023-05-29 21:49:00 -07:00
parent 6079152092
commit 9f75e68a92
2 changed files with 44 additions and 65 deletions

View File

@ -46,8 +46,8 @@ class hanan_graph:
debug.info(0, "Number of blockages detected in the routing region: {}".format(len(self.graph_blockages))) debug.info(0, "Number of blockages detected in the routing region: {}".format(len(self.graph_blockages)))
# Obtain the x and y values for Hanan grid # Obtain the x and y values for Hanan grid
x_values = [] x_values = set()
y_values = [] y_values = set()
offset = max(self.router.horiz_track_width, self.router.vert_track_width) / 2 offset = max(self.router.horiz_track_width, self.router.vert_track_width) / 2
# Add the source and target pins first # Add the source and target pins first
for shape in [layout_source, layout_target]: for shape in [layout_source, layout_target]:
@ -65,74 +65,52 @@ class hanan_graph:
vector(rc.x - offset, rc.y)] vector(rc.x - offset, rc.y)]
else: # Square-like pin else: # Square-like pin
center = shape.center() center = shape.center()
x_values.append(center.x) x_values.add(center.x)
y_values.append(center.y) y_values.add(center.y)
continue continue
for p in points: for p in points:
x_values.append(p.x) x_values.add(p.x)
y_values.append(p.y) y_values.add(p.y)
# Add corners for blockages # Add corners for blockages
for blockage in self.graph_blockages: for blockage in self.graph_blockages:
ll, ur = blockage.rect ll, ur = blockage.rect
x_values.extend([ll.x - offset, ur.x + offset]) x_values.update([ll.x - offset, ur.x + offset])
y_values.extend([ll.y - offset, ur.y + offset]) y_values.update([ll.y - offset, ur.y + offset])
# Sort x and y values
x_values = list(x_values)
y_values = list(y_values)
x_values.sort()
y_values.sort()
# Generate Hanan points here (cartesian product of all x and y values) # Generate Hanan points here (cartesian product of all x and y values)
hanan_points = [] y_len = len(y_values)
self.nodes = []
for x in x_values: for x in x_values:
for y in y_values: for y in y_values:
hanan_points.append(vector3d(x, y, 0)) below_node = hanan_node([x, y, 0])
hanan_points.append(vector3d(x, y, 1)) above_node = hanan_node([x, y, 1])
# Connect these two neighbors
below_node.add_neighbor(above_node)
# Connect down and left nodes
count = len(self.nodes) // 2
if count % y_len: # Down
below_node.add_neighbor(self.nodes[-2])
above_node.add_neighbor(self.nodes[-1])
if count >= y_len: # Left
below_node.add_neighbor(self.nodes[-(y_len * 2)])
above_node.add_neighbor(self.nodes[-(y_len * 2) + 1])
self.nodes.append(below_node)
self.nodes.append(above_node)
# Remove blocked points # Remove blocked points
for point in hanan_points.copy(): for node in self.nodes.copy():
point = node.center
for blockage in self.graph_blockages: for blockage in self.graph_blockages:
ll, ur = blockage.rect
if self.is_on_same_layer(point, blockage) and is_in_region(point, blockage): if self.is_on_same_layer(point, blockage) and is_in_region(point, blockage):
hanan_points.remove(point) node.remove_all_neighbors()
self.nodes.remove(node)
break break
# Create graph nodes from Hanan points
self.nodes = []
for point in hanan_points:
self.nodes.append(hanan_node(point))
# Connect closest points avoiding blockages
for i in range(len(self.nodes)):
node = self.nodes[i]
for d in direction.cardinal_offsets():
min_dist = float("inf")
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
if min_neighbor:
node.add_neighbor(min_neighbor)
# Connect nodes that are on top of each other
for i in range(len(self.nodes)):
node = self.nodes[i]
for j in range(i + 1, len(self.nodes)):
neighbor = self.nodes[j]
if node.center.x == neighbor.center.x and \
node.center.y == neighbor.center.y and \
node.center.z != neighbor.center.z:
node.add_neighbor(neighbor)
debug.info(0, "Number of nodes in the routing graph: {}".format(len(self.nodes))) debug.info(0, "Number of nodes in the routing graph: {}".format(len(self.nodes)))
@ -144,12 +122,11 @@ class hanan_graph:
# Find source and target nodes # Find source and target nodes
sources = [] sources = []
targets = []
for node in self.nodes: for node in self.nodes:
if self.is_on_same_layer(node.center, source) and is_in_region(node.center, source): if self.is_on_same_layer(node.center, source) and is_in_region(node.center, source):
sources.append(node) sources.append(node)
targets = [] elif self.is_on_same_layer(node.center, target) and is_in_region(node.center, target):
for node in self.nodes:
if self.is_on_same_layer(node.center, target) and is_in_region(node.center, target):
targets.append(node) targets.append(node)
# Heuristic function to calculate the scores # Heuristic function to calculate the scores

View File

@ -24,12 +24,6 @@ class hanan_node:
self.neighbors = [] self.neighbors = []
def __lt__(self, other):
""" Override the default less than behavior. """
return self.center < other.center
def add_neighbor(self, other): def add_neighbor(self, other):
""" Connect two nodes. """ """ Connect two nodes. """
@ -46,6 +40,14 @@ class hanan_node:
other.neighbors.remove(self) other.neighbors.remove(self)
def remove_all_neighbors(self):
""" Disconnect all current neighbors. """
for neighbor in self.neighbors:
self.neighbors.remove(neighbor)
neighbor.neighbors.remove(self)
def get_edge_cost(self, other): def get_edge_cost(self, other):
""" Get the cost of going from this node to the other node. """ """ Get the cost of going from this node to the other node. """