diff --git a/compiler/router/graph.py b/compiler/router/graph.py index 687b682a..cc6890cd 100644 --- a/compiler/router/graph.py +++ b/compiler/router/graph.py @@ -111,7 +111,7 @@ class graph: return False - def create_graph(self, source, target): + def create_graph(self, source, target, scale=1): """ Create the graph to run routing on later. """ debug.info(2, "Creating the graph for source '{}' and target'{}'.".format(source, target)) @@ -122,6 +122,7 @@ class graph: # Find the region to be routed and only include objects inside that region region = deepcopy(source) region.bbox([target]) + region.multiply(scale) region = region.inflated_pin(spacing=self.router.track_space) debug.info(3, "Routing region is {}".format(region.rect)) @@ -147,6 +148,9 @@ class graph: debug.info(3, "Number of vias detected in the routing region: {}".format(len(self.graph_vias))) debug.info(3, "Number of nodes in the routing graph: {}".format(len(self.nodes))) + # Return the region to scale later if no path is found + return region.rect + def find_graph_blockages(self, region): """ Find blockages that overlap the routing region. """ diff --git a/compiler/router/graph_router.py b/compiler/router/graph_router.py index 733f2804..74fc63de 100644 --- a/compiler/router/graph_router.py +++ b/compiler/router/graph_router.py @@ -96,20 +96,35 @@ class graph_router(router_tech): pins = self.pins[pin_name] # Route closest pins according to the minimum spanning tree for source, target in self.get_mst_pairs(list(pins)): - # Create the graph - g = graph(self) - g.create_graph(source, target) - # Find the shortest path from source to target - path = g.find_shortest_path() - # TODO: Exponentially increase the routing area and retry if no - # path was found - debug.check(path is not None, "Couldn't route from {} to {}".format(source, target)) - # Create the path shapes on layout - self.add_path(path) - # Find the recently added shapes - self.prepare_gds_reader() - self.find_blockages(pin_name) - self.find_vias() + # This is the routing region scale + scale = 1 + while True: + # Create the graph + g = graph(self) + region = g.create_graph(source, target, scale) + # Find the shortest path from source to target + path = g.find_shortest_path() + # If there is no path found, exponentially try again with a + # larger routing region + if path is None: + rll, rur = region + bll, bur = self.ring_bbox + # Stop scaling the region and throw an error + if rll.x < bll.x and rll.y < bll.y and \ + rur.x > bur.x and rur.y > bur.y: + self.write_debug_gds(gds_name="{}error.gds".format(OPTS.openram_temp), g=g, source=source, target=target) + debug.error("Couldn't route from {} to {}.".format(source, target), -1) + # Exponentially scale the region + scale *= 2 + debug.info(0, "Retry routing in larger routing region with scale {}".format(scale)) + continue + # Create the path shapes on layout + self.add_path(path) + # Find the recently added shapes + self.prepare_gds_reader() + self.find_blockages(pin_name) + self.find_vias() + break def prepare_gds_reader(self): diff --git a/compiler/router/graph_shape.py b/compiler/router/graph_shape.py index f38c9f91..b24c0a06 100644 --- a/compiler/router/graph_shape.py +++ b/compiler/router/graph_shape.py @@ -65,6 +65,17 @@ class graph_shape(pin_layout): return graph_shape(self.name, inflated_area, self.layer, self) + def multiply(self, scale): + """ Multiply the width and height with the scale value. """ + + width = (self.width() * (scale - 1)) / 2 + height = (self.height() * (scale - 1)) / 2 + ll, ur = self.rect + newll = vector(ll.x - width, ll.y - height) + newur = vector(ur.x + width, ur.y + height) + self.rect = [snap(newll), snap(newur)] + + def aligns(self, other): """ Return if the other shape aligns with this shape. """