diff --git a/compiler/base/pin_layout.py b/compiler/base/pin_layout.py index 5199265b..9dfbc443 100644 --- a/compiler/base/pin_layout.py +++ b/compiler/base/pin_layout.py @@ -118,6 +118,20 @@ class pin_layout: return y_overlaps + def xcontains(self, other): + """ Check if shape contains the x overlap """ + (ll,ur) = self.rect + (oll,our) = other.rect + + return (oll.x >= ll.x and our.x <= ur.x) + + def ycontains(self, other): + """ Check if shape contains the y overlap """ + (ll,ur) = self.rect + (oll,our) = other.rect + + return (oll.y >= ll.y and our.y <= ur.y) + def contains(self, other): """ Check if a shape contains another rectangle """ # If it is the same shape entirely, it is contained! @@ -127,23 +141,13 @@ class pin_layout: # Can only overlap on the same layer if self.layer != other.layer: return False - - (ll,ur) = self.rect - (oll,our) = other.rect - - # Check if the oll is inside the y range - if not (oll.y >= ll.y and oll.y <= ur.y): + + if not self.xcontains(other): return False - # Check if the oll is inside the x range - if not (oll.x >= ll.x and oll.x <= ur.x): + + if not self.ycontains(other): return False - # Check if the our is inside the y range - if not (our.y >= ll.y and our.y <= ur.y): - return False - # Check if the our is inside the x range - if not (our.x >= ll.x and our.x <= ur.x): - return False - + return True diff --git a/compiler/router/pin_group.py b/compiler/router/pin_group.py index 9203ed11..61ebf410 100644 --- a/compiler/router/pin_group.py +++ b/compiler/router/pin_group.py @@ -114,10 +114,10 @@ class pin_group: if index2 in remove_indices: continue - if pin2.contains(pin1): + if pin1.contains(pin2): if local_debug: debug.info(0,"{0} contains {1}".format(pin1,pin2)) - remove_indices.add(index2) + remove_indices.add(index2) # Remove them in decreasing order to not invalidate the indices for i in sorted(remove_indices, reverse=True): @@ -144,7 +144,7 @@ class pin_group: enclosure = self.router.compute_pin_enclosure(ll, ur, ll.z) pin_list.append(enclosure) - return self.remove_redundant_shapes(pin_list) + return pin_list def compute_connector(self, pin, enclosure): """ @@ -187,6 +187,138 @@ class pin_group: return p + def find_above_connector(self, pin, enclosures): + """ + Find the enclosure that is to above the pin + and make a connector to it's upper edge. + """ + # Create the list of shapes that contain the pin edge + edge_list = [] + for shape in enclosures: + if shape.xcontains(pin): + edge_list.append(shape) + + # Sort them by their bottom edge + edge_list.sort(key=lambda x: x.by(), reverse=True) + + # Find the bottom edge that is next to the pin's top edge + above_item = None + for item in edge_list: + if item.by()>=pin.uy(): + above_item = item + else: + break + + # There was nothing + if above_item==None: + return None + # If it already overlaps, no connector needed + if above_item.overlaps(pin): + return None + + # Otherwise, make a connector to the item + p = self.compute_connector(pin, above_item) + return p + + def find_below_connector(self, pin, enclosures): + """ + Find the enclosure that is below the pin + and make a connector to it's upper edge. + """ + # Create the list of shapes that contain the pin edge + edge_list = [] + for shape in enclosures: + if shape.xcontains(pin): + edge_list.append(shape) + + # Sort them by their upper edge + edge_list.sort(key=lambda x: x.uy()) + + # Find the upper edge that is next to the pin's bottom edge + bottom_item = None + for item in edge_list: + if item.uy()<=pin.by(): + bottom_item = item + else: + break + + # There was nothing to the left + if bottom_item==None: + return None + # If it already overlaps, no connector needed + if bottom_item.overlaps(pin): + return None + + # Otherwise, make a connector to the item + p = self.compute_connector(pin, bottom_item) + return p + + def find_left_connector(self, pin, enclosures): + """ + Find the enclosure that is to the left of the pin + and make a connector to it's right edge. + """ + # Create the list of shapes that contain the pin edge + edge_list = [] + for shape in enclosures: + if shape.ycontains(pin): + edge_list.append(shape) + + # Sort them by their right edge + edge_list.sort(key=lambda x: x.rx()) + + # Find the right edge that is to the pin's left edge + left_item = None + for item in edge_list: + if item.rx()<=pin.lx(): + left_item = item + else: + break + + # There was nothing to the left + if left_item==None: + return None + # If it already overlaps, no connector needed + if left_item.overlaps(pin): + return None + + # Otherwise, make a connector to the item + p = self.compute_connector(pin, left_item) + return p + + def find_right_connector(self, pin, enclosures): + """ + Find the enclosure that is to the right of the pin + and make a connector to it's left edge. + """ + # Create the list of shapes that contain the pin edge + edge_list = [] + for shape in enclosures: + if shape.ycontains(pin): + edge_list.append(shape) + + # Sort them by their right edge + edge_list.sort(key=lambda x: x.lx(), reverse=True) + + # Find the left edge that is next to the pin's right edge + right_item = None + for item in edge_list: + if item.lx()>=pin.rx(): + right_item = item + else: + break + + # There was nothing to the right + if right_item==None: + return None + # If it already overlaps, no connector needed + if right_item.overlaps(pin): + return None + + # Otherwise, make a connector to the item + p = self.compute_connector(pin, right_item) + return p + def find_smallest_connector(self, pin_list, shape_list): """ Compute all of the connectors between the overlapping pins and enclosure shape list.. @@ -313,16 +445,30 @@ class pin_group: self.enclosed = True # Compute the enclosure pin_layout list of the set of tracks - self.enclosures = self.compute_enclosures() + redundant_enclosures = self.compute_enclosures() + + # Now simplify the enclosure list + self.enclosures = self.remove_redundant_shapes(redundant_enclosures) + + for pin_list in self.pins: + for pin in pin_list: + left_connector = self.find_left_connector(pin, self.enclosures) + right_connector = self.find_right_connector(pin, self.enclosures) + above_connector = self.find_above_connector(pin, self.enclosures) + below_connector = self.find_below_connector(pin, self.enclosures) + for connector in [left_connector, right_connector, above_connector, below_connector]: + if connector: + self.enclosures.append(connector) # Now, make sure each pin touches an enclosure. If not, add a connector. + # This could only happen when there was no enclosure in any cardinal direction from a pin for pin_list in self.pins: if not self.overlap_any_shape(pin_list, self.enclosures): connector = self.find_smallest_connector(pin_list, self.enclosures) debug.check(connector!=None, "Could not find a connector for {} with {}".format(pin_list, self.enclosures)) self.enclosures.append(connector) - + debug.info(3,"Computed enclosure(s) {0}\n {1}\n {2}\n {3}".format(self.name, self.pins, self.grids, diff --git a/compiler/router/router.py b/compiler/router/router.py index 5a879e69..e7340178 100644 --- a/compiler/router/router.py +++ b/compiler/router/router.py @@ -707,7 +707,7 @@ class router(router_tech): pg.enclose_pin() pg.add_enclosure(self.cell) - #self.write_debug_gds("pin_debug.gds", True) + #self.write_debug_gds("pin_debug.gds", False) def add_source(self, pin_name): """