From 56bee27ee32596f2aead7d2bd0eceb6d6d5745dd Mon Sep 17 00:00:00 2001 From: Eren Dogan Date: Tue, 29 Aug 2023 21:45:52 -0700 Subject: [PATCH] Don't write/read gds files unnecessarily for router --- compiler/router/router.py | 62 +++++++++++++++++-------- compiler/router/signal_escape_router.py | 9 ++-- compiler/router/supply_router.py | 9 ++-- 3 files changed, 50 insertions(+), 30 deletions(-) diff --git a/compiler/router/router.py b/compiler/router/router.py index fe445ae1..c498a815 100644 --- a/compiler/router/router.py +++ b/compiler/router/router.py @@ -59,6 +59,8 @@ class router(router_tech): def prepare_gds_reader(self): """ Write the current layout to a temporary file to read the layout. """ + # NOTE: Avoid using this function if possible since it is too slow to + # write/read these files self.design.gds_write(self.gds_filename) self.layout = gdsMill.VlsiLayout(units=GDS["unit"]) self.reader = gdsMill.Gds2reader(self.layout) @@ -109,16 +111,26 @@ class router(router_tech): self.all_pins.update(pin_set) - def find_blockages(self, name="blockage"): + def find_blockages(self, name="blockage", shape_list=None): """ Find all blockages in the routing layers. """ debug.info(2, "Finding blockages...") for lpp in [self.vert_lpp, self.horiz_lpp]: - shapes = self.layout.getAllShapes(lpp) + # If the list of shapes is given, don't get them from gdsMill + if shape_list is None: + shapes = self.layout.getAllShapes(lpp) + else: + shapes = shape_list for boundary in shapes: - # gdsMill boundaries are in (left, bottom, right, top) order - ll = vector(boundary[0], boundary[1]) - ur = vector(boundary[2], boundary[3]) + if shape_list is not None: + if boundary.lpp != lpp: + continue + ll = boundary.ll() + ur = boundary.ur() + else: + # gdsMill boundaries are in (left, bottom, right, top) order + ll = vector(boundary[0], boundary[1]) + ur = vector(boundary[2], boundary[3]) rect = [ll, ur] new_shape = graph_shape(name, rect, lpp) new_shape = self.inflate_shape(new_shape) @@ -132,20 +144,28 @@ class router(router_tech): self.blockages.append(new_shape) - def find_vias(self): + def find_vias(self, shape_list=None): """ Find all vias in the routing layers. """ debug.info(2, "Finding vias...") # Prepare lpp values here from openram.tech import layer via_lpp = layer[self.via_layer_name] - valid_lpp = self.horiz_lpp + valid_lpp = self.horiz_lpp # Just a temporary lpp to prevent errors - shapes = self.layout.getAllShapes(via_lpp) + # If the list of shapes is given, don't get them from gdsMill + if shape_list is None: + shapes = self.layout.getAllShapes(via_lpp) + else: + shapes = shape_list for boundary in shapes: - # gdsMill boundaries are in (left, bottom, right, top) order - ll = vector(boundary[0], boundary[1]) - ur = vector(boundary[2], boundary[3]) + if shape_list is not None: + ll = boundary.ll() + ur = boundary.ur() + else: + # gdsMill boundaries are in (left, bottom, right, top) order + ll = vector(boundary[0], boundary[1]) + ur = vector(boundary[2], boundary[3]) rect = [ll, ur] new_shape = graph_shape("via", rect, valid_lpp) # Skip this via if it's contained by an existing via blockage @@ -264,7 +284,8 @@ class router(router_tech): working for this router. """ - new_shapes = [] + new_wires = [] + new_vias = [] for i in range(0, len(nodes) - 1): start = nodes[i].center end = nodes[i + 1].center @@ -275,15 +296,16 @@ class router(router_tech): offset.y - self.half_wire) if direction == (1, 1): # Via offset = vector(start.x, start.y) - self.design.add_via_center(layers=self.layers, - offset=offset) + via = self.design.add_via_center(layers=self.layers, + offset=offset) + new_vias.append(via) else: # Wire - shape = self.design.add_rect(layer=self.get_layer(start.z), - offset=offset, - width=abs(diff.x) + self.track_wire, - height=abs(diff.y) + self.track_wire) - new_shapes.append(shape) - return new_shapes + wire = self.design.add_rect(layer=self.get_layer(start.z), + offset=offset, + width=abs(diff.x) + self.track_wire, + height=abs(diff.y) + self.track_wire) + new_wires.append(wire) + return new_wires, new_vias def write_debug_gds(self, gds_name, g=None, source=None, target=None): diff --git a/compiler/router/signal_escape_router.py b/compiler/router/signal_escape_router.py index 18a3d45e..21cae924 100644 --- a/compiler/router/signal_escape_router.py +++ b/compiler/router/signal_escape_router.py @@ -67,12 +67,11 @@ class signal_escape_router(router): 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) # Create the path shapes on layout - new_shapes = self.add_path(path) - self.new_pins[source.name] = new_shapes[-1] + new_wires, new_vias = self.add_path(path) + self.new_pins[source.name] = new_wires[-1] # Find the recently added shapes - self.prepare_gds_reader() - self.find_blockages(name) - self.find_vias() + self.find_blockages(name, new_wires) + self.find_vias(new_vias) self.replace_layout_pins() diff --git a/compiler/router/supply_router.py b/compiler/router/supply_router.py index 037e8868..3cdcc4e6 100644 --- a/compiler/router/supply_router.py +++ b/compiler/router/supply_router.py @@ -73,7 +73,7 @@ class supply_router(router): for source, target in self.get_mst_pairs(list(pins)): # Create the graph g = graph(self) - region = g.create_graph(source, target) + g.create_graph(source, target) # Find the shortest path from source to target path = g.find_shortest_path() # If no path is found, throw an error @@ -81,11 +81,10 @@ class supply_router(router): 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) # Create the path shapes on layout - self.add_path(path) + new_wires, new_vias = self.add_path(path) # Find the recently added shapes - self.prepare_gds_reader() - self.find_blockages(pin_name) - self.find_vias() + self.find_blockages(pin_name, new_wires) + self.find_vias(new_vias) def add_side_pin(self, pin_name, side, num_vias=3, num_fake_pins=4):