From 947e94323d2d453685848f6f7368f66224fd5f62 Mon Sep 17 00:00:00 2001 From: Eren Dogan Date: Mon, 24 Jul 2023 08:03:08 -0700 Subject: [PATCH] Cleanup graph router --- compiler/router/graph.py | 40 +++++++++++++++++++++++---------- compiler/router/graph_router.py | 33 +++++++++++++-------------- compiler/router/router_tech.py | 4 ++-- 3 files changed, 46 insertions(+), 31 deletions(-) diff --git a/compiler/router/graph.py b/compiler/router/graph.py index 2e9d8457..2987bd6e 100644 --- a/compiler/router/graph.py +++ b/compiler/router/graph.py @@ -128,24 +128,20 @@ class graph: # Find the blockages that are in the routing area self.graph_blockages = [] self.find_graph_blockages(region) - for shape in [source, target]: - if shape not in self.graph_blockages: - self.graph_blockages.append(shape) # Find the vias that are in the routing area self.graph_vias = [] - for via in self.router.vias: - # Set the regions's lpp to current via's lpp so that the - # overlaps method works - region.lpp = via.lpp - if region.overlaps(via): - self.graph_vias.append(via) + self.find_graph_vias(region) - # Create the graph + # Generate the cartesian values from shapes in the area x_values, y_values = self.generate_cartesian_values() + # Adjust the routing region to include "edge" shapes region.bbox(self.graph_blockages) + # Find and include edge shapes to prevent DRC errors self.find_graph_blockages(region) + # Generate the graph nodes from cartesian values self.generate_graph_nodes(x_values, y_values) + # Save the graph nodes that lie in source and target shapes self.save_end_nodes() debug.info(3, "Number of blockages detected in the routing region: {}".format(len(self.graph_blockages))) debug.info(3, "Number of vias detected in the routing region: {}".format(len(self.graph_vias))) @@ -156,13 +152,33 @@ class graph: """ Find blockages that overlap the routing region. """ for blockage in self.router.blockages: - # Set the region's lpp to current blockage's lpp so that the - # overlaps method works + # Skip if already included if blockage in self.graph_blockages: continue + # Set the region's lpp to current blockage's lpp so that the + # overlaps method works region.lpp = blockage.lpp if region.overlaps(blockage): self.graph_blockages.append(blockage) + # FIXME: Don't include source and target if they're already included + # in inflated form + for shape in [self.source, self.target]: + if shape not in self.graph_blockages: + self.graph_blockages.append(shape) + + + def find_graph_vias(self, region): + """ Find vias that overlap the routing region. """ + + for via in self.router.vias: + # Skip if already included + if via in self.graph_vias: + continue + # Set the regions's lpp to current via's lpp so that the + # overlaps method works + region.lpp = via.lpp + if region.overlaps(via): + self.graph_vias.append(via) def generate_cartesian_values(self): diff --git a/compiler/router/graph_router.py b/compiler/router/graph_router.py index 7b3f7782..9166b8e1 100644 --- a/compiler/router/graph_router.py +++ b/compiler/router/graph_router.py @@ -97,10 +97,10 @@ class graph_router(router_tech): # Route closest pins according to the minimum spanning tree for source, target in self.get_mst_pairs(list(pins)): # Create the graph - hg = graph(self) - hg.create_graph(source, target) + g = graph(self) + g.create_graph(source, target) # Find the shortest path from source to target - path = hg.find_shortest_path() + 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)) @@ -130,7 +130,6 @@ class graph_router(router_tech): for shape in shape_list: layer, boundary = shape # gdsMill boundaries are in (left, bottom, right, top) order - # so repack and snap to the grid ll = vector(boundary[0], boundary[1]) ur = vector(boundary[2], boundary[3]) rect = [ll, ur] @@ -163,7 +162,6 @@ class graph_router(router_tech): shapes = self.layout.getAllShapes(lpp) for boundary in shapes: # gdsMill boundaries are in (left, bottom, right, top) order - # so repack and snap to the grid ll = vector(boundary[0], boundary[1]) ur = vector(boundary[2], boundary[3]) rect = [ll, ur] @@ -224,7 +222,6 @@ class graph_router(router_tech): shapes = self.layout.getAllShapes(via_lpp) for boundary in shapes: # gdsMill boundaries are in (left, bottom, right, top) order - # so repack and snap to the grid ll = vector(boundary[0], boundary[1]) ur = vector(boundary[2], boundary[3]) rect = [ll, ur] @@ -486,30 +483,32 @@ class graph_router(router_tech): def get_new_pins(self, name): - """ """ + """ Return the new supply pins added by this router. """ return self.new_pins[name] - def write_debug_gds(self, gds_name="debug_route.gds", hg=None, source=None, target=None): - """ """ + def write_debug_gds(self, gds_name="debug_route.gds", g=None, source=None, target=None): + """ Write the debug GDSII file for the router. """ - self.add_router_info(hg, source, target) + self.add_router_info(g, source, target) self.design.gds_write(gds_name) self.del_router_info() - def add_router_info(self, hg=None, source=None, target=None): - """ """ + def add_router_info(self, g=None, source=None, target=None): + """ + Add debug information to the text layer about the graph and router. + """ # Display the inflated blockage - if hg: + if g: for blockage in self.blockages: - if blockage in hg.graph_blockages: + if blockage in g.graph_blockages: self.add_object_info(blockage, "blockage{}++[{}]".format(self.get_zindex(blockage.lpp), blockage.name)) else: self.add_object_info(blockage, "blockage{}[{}]".format(self.get_zindex(blockage.lpp), blockage.name)) - for node in hg.nodes: + for node in g.nodes: offset = (node.center.x, node.center.y) self.design.add_label(text="n{}".format(node.center.z), layer="text", @@ -526,14 +525,14 @@ class graph_router(router_tech): def del_router_info(self): - """ """ + """ Delete router information from the text layer. """ lpp = tech_layer["text"] self.design.objs = [x for x in self.design.objs if x.lpp != lpp] def add_object_info(self, obj, label): - """ """ + """ Add debug information to the text layer about an object. """ ll, ur = obj.rect self.design.add_rect(layer="text", diff --git a/compiler/router/router_tech.py b/compiler/router/router_tech.py index eafdb82e..326a60a9 100644 --- a/compiler/router/router_tech.py +++ b/compiler/router/router_tech.py @@ -124,14 +124,14 @@ class router_tech: return (min_width, min_spacing) def get_layer_width(self, zindex): - """ """ + """ Return the minimum width of a layer. """ layer_name = self.get_layer(zindex) min_wire_width = drc("minwidth_{0}".format(layer_name), 0, math.inf) min_width = self.route_track_width * drc("minwidth_{0}".format(layer_name), self.route_track_width * min_wire_width, math.inf) return min_width def get_layer_space(self, zindex, width): - """ """ + """ Return the minimum spacing of a layer given wire width. """ if width is None: width = self.get_layer_width(zindex) layer_name = self.get_layer(zindex)