diff --git a/compiler/base/pin_layout.py b/compiler/base/pin_layout.py index 9dfbc443..c5434246 100644 --- a/compiler/base/pin_layout.py +++ b/compiler/base/pin_layout.py @@ -149,7 +149,14 @@ class pin_layout: return False return True - + + def contained_by_any(self, shape_list): + """ Checks if shape is contained by any in the list """ + for shape in shape_list: + if shape.contains(self): + return True + return False + def overlaps(self, other): """ Check if a shape overlaps with a rectangle """ diff --git a/compiler/router/pin_group.py b/compiler/router/pin_group.py index 39fe12c5..7897fdbf 100644 --- a/compiler/router/pin_group.py +++ b/compiler/router/pin_group.py @@ -10,21 +10,22 @@ class pin_group: A class to represent a group of rectangular design pin. It requires a router to define the track widths and blockages which determine how pin shapes get mapped to tracks. + It is initially constructed with a single set of (touching) pins. """ - def __init__(self, name, pin_shapes, router): + def __init__(self, name, pin_set, router): self.name = name # Flag for when it is routed self.routed = False # Flag for when it is enclosed self.enclosed = False + # Remove any redundant pins (i.e. contained in other pins) + irredundant_pin_set = self.remove_redundant_shapes(list(pin_set)) + # This is a list because we can have a pin group of disconnected sets of pins # and these are represented by separate lists - if pin_shapes: - self.pins = [pin_shapes] - else: - self.pins = [] - + self.pins = [set(irredundant_pin_set)] + self.router = router # These are the corresponding pin grids for each pin group. self.grids = set() @@ -35,6 +36,9 @@ class pin_group: # These are blockages for other nets but unblocked for routing this group. self.blockages = set() + # This is a set of pin_layout shapes to cover the grids + self.enclosures = set() + def __str__(self): """ override print function output """ total_string = "(pg {} ".format(self.name) @@ -90,6 +94,7 @@ class pin_group: def remove_redundant_shapes(self, pin_list): """ Remove any pin layout that is contained within another. + Returns a new list without modifying pin_list. """ local_debug = False if local_debug: @@ -144,7 +149,11 @@ class pin_group: enclosure = self.router.compute_pin_enclosure(ll, ur, ll.z) pin_list.append(enclosure) - return pin_list + + # Now simplify the enclosure list + new_pin_list = self.remove_redundant_shapes(pin_list) + + return new_pin_list def compute_connector(self, pin, enclosure): """ @@ -445,13 +454,15 @@ class pin_group: self.enclosed = True # Compute the enclosure pin_layout list of the set of tracks - redundant_enclosures = self.compute_enclosures() - - # Now simplify the enclosure list - self.enclosures = self.remove_redundant_shapes(redundant_enclosures) + self.enclosures = self.compute_enclosures() for pin_list in self.pins: for pin in pin_list: + + # If it is contained, it won't need a connector + if pin.contained_by_any(self.enclosures): + continue + 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) @@ -553,9 +564,11 @@ class pin_group: debug.info(2," Converting {0}".format(pin)) # Determine which tracks the pin overlaps pin_in_tracks=router.convert_pin_to_tracks(self.name, pin) + pin_set.update(pin_in_tracks) # Blockages will be a super-set of pins since it uses the inflated pin shape. blockage_in_tracks = router.convert_blockage(pin) + blockage_set.update(blockage_in_tracks) # If we have a blockage, we must remove the grids diff --git a/compiler/router/router.py b/compiler/router/router.py index c9d1a2c0..f2cb6f22 100644 --- a/compiler/router/router.py +++ b/compiler/router/router.py @@ -98,11 +98,16 @@ class router(router_tech): pin_set = set() for shape in shape_list: (name,layer,boundary)=shape - rect = [vector(boundary[0],boundary[1]),vector(boundary[2],boundary[3])] + # GDSMill boundaries are in (left, bottom, right, top) order + # so repack and snap to the grid + ll = vector(boundary[0],boundary[1]).snap_to_grid() + ur = vector(boundary[2],boundary[3]).snap_to_grid() + rect = [ll,ur] pin = pin_layout(pin_name, rect, layer) pin_set.add(pin) debug.check(len(pin_set)>0,"Did not find any pin shapes for {0}.".format(str(pin_name))) + self.pins[pin_name] = pin_set self.all_pins.update(pin_set) @@ -411,7 +416,7 @@ class router(router_tech): p.set_blocked(value) def get_blockage_tracks(self, ll, ur, z): - debug.info(4,"Converting blockage ll={0} ur={1} z={2}".format(str(ll),str(ur),z)) + debug.info(3,"Converting blockage ll={0} ur={1} z={2}".format(str(ll),str(ur),z)) block_list = [] for x in range(int(ll[0]),int(ur[0])+1): @@ -684,7 +689,7 @@ class router(router_tech): reduced_classes = combine_classes(equiv_classes) if local_debug: debug.info(0,"FINAL ",reduced_classes) - self.pin_groups[pin_name] = [pin_group(name=pin_name, pin_shapes=x, router=self) for x in reduced_classes] + self.pin_groups[pin_name] = [pin_group(name=pin_name, pin_set=x, router=self) for x in reduced_classes] def convert_pins(self, pin_name): """ diff --git a/compiler/router/supply_router.py b/compiler/router/supply_router.py index 84e59b04..1e13fd12 100644 --- a/compiler/router/supply_router.py +++ b/compiler/router/supply_router.py @@ -169,7 +169,7 @@ class supply_router(router): if not new_set: new_set = self.recurse_simple_overlap_enclosure(pin_name, start_set, direction.WEST) - pg = pin_group(name=pin_name, pin_shapes=[], router=self) + pg = pin_group(name=pin_name, pin_set=[], router=self) pg.grids=new_set enclosure_list = pg.compute_enclosures() for pin in enclosure_list: