diff --git a/compiler/router/hanan_graph.py b/compiler/router/hanan_graph.py index 96f7c818..67698d6a 100644 --- a/compiler/router/hanan_graph.py +++ b/compiler/router/hanan_graph.py @@ -29,6 +29,32 @@ class hanan_graph: return point.z == self.router.get_zindex(shape.lpp) + def is_probe_blocked(self, p1, p2): + """ + Return if a probe sent from p1 to p2 encounters a blockage. + The probe must be sent vertically or horizontally. + This function assumes that p1 and p2 are on the same layer. + This function assumes that blockages are rectangular. + """ + + # Check if any blockage blocks this probe + for blockage in self.graph_blockages: + if not self.is_on_same_layer(p1, blockage): + continue + 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 create_graph(self, source, target): """ Create the Hanan graph to run routing on later. """ debug.info(0, "Creating the Hanan graph for source '{0}' and target'{1}'.".format(source, target)) @@ -114,16 +140,31 @@ class hanan_graph: for y in y_values: below_node = hanan_node([x, y, 0]) above_node = hanan_node([x, y, 1]) + # Connect these two neighbors below_node.add_neighbor(above_node) - # Connect down and left nodes + + # Find potential neighbor nodes + belows = [] + aboves = [] count = len(self.nodes) // 2 if count % y_len: # Down - below_node.add_neighbor(self.nodes[-2]) - above_node.add_neighbor(self.nodes[-1]) + belows.append(-2) + aboves.append(-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]) + belows.append(-(y_len * 2)) + aboves.append(-(y_len * 2) + 1) + + # Add these connections if not blocked by a blockage + for i in belows: + 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) @@ -136,6 +177,7 @@ class hanan_graph: node = self.nodes[i] point = node.center for blockage in self.graph_blockages: + # Remove if the node is inside a blockage if self.is_on_same_layer(point, blockage) and is_in_region(point, blockage): node.remove_all_neighbors() self.nodes.remove(node) diff --git a/compiler/router/hanan_router.py b/compiler/router/hanan_router.py index 707b2e41..9b4d6c75 100644 --- a/compiler/router/hanan_router.py +++ b/compiler/router/hanan_router.py @@ -116,18 +116,23 @@ class hanan_router(router_tech): lpp) # If there is a rectangle that is the same in the pins, # it isn't a blockage - if new_shape not in self.all_pins and not self.pin_contains(new_shape): + if new_shape not in self.all_pins and not new_shape.contained_by_any(self.all_pins) and not self.blockage_contains(new_shape): new_shape = new_shape.inflated_pin(multiple=1) + # Remove blockages contained by this new blockage + for i in range(len(self.blockages) - 1, -1, -1): + blockage = self.blockages[i] + if new_shape.contains(blockage): + self.blockages.remove(blockage) self.blockages.append(new_shape) - def pin_contains(self, shape): + def blockage_contains(self, shape): """ - Return if this pin contains another pin or is contained by another pin. + Return if this shape is contained by a blockage. """ - for pin in self.all_pins: - if pin.contains(shape) or shape.contains(pin): + for blockage in self.blockages: + if blockage.contains(shape): return True return False @@ -153,12 +158,12 @@ class hanan_router(router_tech): """ """ # Display the inflated blockage - if "nav" in self.__dict__: + if "hg" in self.__dict__: for blockage in self.hg.graph_blockages: - self.add_object_info(blockage, "blockage") + self.add_object_info(blockage, "blockage{}".format(self.get_zindex(blockage.lpp))) for node in self.hg.nodes: offset = (node.center.x, node.center.y) - self.design.add_label(text="O", + self.design.add_label(text="n{}".format(node.center.z), layer="text", offset=offset) if source: diff --git a/compiler/router/hanan_utils.py b/compiler/router/hanan_utils.py index 051b7740..14092bbe 100644 --- a/compiler/router/hanan_utils.py +++ b/compiler/router/hanan_utils.py @@ -7,29 +7,6 @@ Utility functions for Hanan 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): """ Return if a point is in the given region. """