From 021da25cd6cf51164236e6f4372dcc8640661e45 Mon Sep 17 00:00:00 2001 From: Eren Dogan Date: Sun, 4 Jun 2023 08:46:59 -0700 Subject: [PATCH] Include all blockages inside the routing region --- compiler/router/hanan_graph.py | 25 +++++++++++---------- compiler/router/hanan_router.py | 13 ++++++++--- compiler/router/hanan_shape.py | 39 +++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 15 deletions(-) create mode 100644 compiler/router/hanan_shape.py diff --git a/compiler/router/hanan_graph.py b/compiler/router/hanan_graph.py index eabdaa07..1c094fb5 100644 --- a/compiler/router/hanan_graph.py +++ b/compiler/router/hanan_graph.py @@ -6,7 +6,6 @@ import heapq from copy import deepcopy from openram import debug -from openram.base.pin_layout import pin_layout from openram.base.vector import vector from openram.base.vector3d import vector3d from .direction import direction @@ -61,12 +60,16 @@ class hanan_graph: # Find the region to be routed and only include objects inside that region region = deepcopy(source) - region.bbox([source, target]) + region.bbox([target]) + region = region.inflated_pin(multiple=1) debug.info(0, "Routing region is {}".format(region.rect)) # Find the blockages that are in the routing area self.graph_blockages = [] for blockage in self.router.blockages: + # 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) debug.info(0, "Number of blockages detected in the routing region: {}".format(len(self.graph_blockages))) @@ -80,16 +83,15 @@ class hanan_graph: def generate_cartesian_values(self): """ - Generate x and y values from all the corners of the shapes in this - region. + Generate x and y values from all the corners of the shapes in the + routing region. """ - # Obtain the x and y values for Hanan grid x_values = set() y_values = set() 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 values for shape in [self.source, self.target]: aspect_ratio = shape.width() / shape.height() # If the pin is tall or fat, add two points on the ends @@ -133,8 +135,8 @@ class hanan_graph: orthogonal neighbors. """ - # Generate Hanan points here (cartesian product of all x and y values) y_len = len(y_values) + left_offset = -(y_len * 2) self.nodes = [] for x in x_values: for y in y_values: @@ -144,7 +146,7 @@ class hanan_graph: # Connect these two neighbors below_node.add_neighbor(above_node) - # Find potential neighbor nodes + # Find potential orthogonal neighbor nodes belows = [] aboves = [] count = len(self.nodes) // 2 @@ -152,8 +154,8 @@ class hanan_graph: belows.append(-2) aboves.append(-1) if count >= y_len: # Left - belows.append(-(y_len * 2)) - aboves.append(-(y_len * 2) + 1) + belows.append(left_offset) + aboves.append(left_offset + 1) # Add these connections if not blocked by a blockage for i in belows: @@ -179,7 +181,6 @@ class hanan_graph: def remove_blocked_nodes(self): """ Remove the Hanan nodes that are blocked by a blockage. """ - # Remove blocked points for i in range(len(self.nodes) - 1, -1, -1): node = self.nodes[i] point = node.center @@ -225,7 +226,7 @@ class hanan_graph: # Get the closest node from the queue current = heapq.heappop(queue)[2] - # Continue if already discovered + # Skip this node if already discovered if current in close_set: continue close_set.add(current) diff --git a/compiler/router/hanan_router.py b/compiler/router/hanan_router.py index b609c7df..c27f8e7b 100644 --- a/compiler/router/hanan_router.py +++ b/compiler/router/hanan_router.py @@ -4,7 +4,6 @@ # All rights reserved. # from openram import debug -from openram.base.pin_layout import pin_layout from openram.base.vector import vector from openram.base.vector3d import vector3d from openram.gdsMill import gdsMill @@ -13,6 +12,7 @@ from openram.tech import layer as tech_layer from openram import OPTS from .router_tech import router_tech from .hanan_graph import hanan_graph +from .hanan_shape import hanan_shape class hanan_router(router_tech): @@ -92,7 +92,7 @@ class hanan_router(router_tech): ll = vector(boundary[0], boundary[1]) ur = vector(boundary[2], boundary[3]) rect = [ll, ur] - pin = pin_layout(pin_name, rect, layer) + pin = hanan_shape(pin_name, rect, layer) pin_set.add(pin) # Add these pins to the 'pins' dict self.pins[pin_name] = pin_set @@ -111,7 +111,7 @@ class hanan_router(router_tech): ll = vector(boundary[0], boundary[1]) ur = vector(boundary[2], boundary[3]) rect = [ll, ur] - new_shape = pin_layout("blockage{}".format(len(self.blockages)), + new_shape = hanan_shape("blockage{}".format(len(self.blockages)), rect, lpp) # If there is a rectangle that is the same in the pins, @@ -121,8 +121,15 @@ class hanan_router(router_tech): # Remove blockages contained by this new blockage for i in range(len(self.blockages) - 1, -1, -1): blockage = self.blockages[i] + # Remove the previous blockage contained by this new + # blockage if new_shape.contains(blockage): self.blockages.remove(blockage) + # Merge the previous blockage into this new blockage if + # they are aligning + elif new_shape.aligns(blockage): + new_shape.bbox([blockage]) + self.blockages.remove(blockage) self.blockages.append(new_shape) diff --git a/compiler/router/hanan_shape.py b/compiler/router/hanan_shape.py new file mode 100644 index 00000000..65dabe96 --- /dev/null +++ b/compiler/router/hanan_shape.py @@ -0,0 +1,39 @@ +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz +# All rights reserved. +# +from openram.base.pin_layout import pin_layout + + +class hanan_shape(pin_layout): + """ + This class inherits the pin_layout class to change some of its behavior for + the Hanan router. + """ + + def __init__(self, name, rect, layer_name_pp): + + pin_layout.__init__(self, name, rect, layer_name_pp) + + + def inflated_pin(self, spacing=None, multiple=0.5): + """ Override the default inflated_pin behavior. """ + + inflated_area = self.inflate(spacing, multiple) + return hanan_shape(self.name, inflated_area, self.layer) + + + def aligns(self, other): + """ Return if the other shape aligns with this shape. """ + + # Shapes must overlap to be able to align + if not self.overlaps(other): + return False + ll, ur = self.rect + oll, our = other.rect + if ll.x == oll.x and ur.x == our.x: + return True + if ll.y == oll.y and ur.y == our.y: + return True + return False