From f19bcace62b1dd8ce2078ac81c9bdc49adce5765 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Mon, 29 Oct 2018 11:18:12 -0700 Subject: [PATCH] Merged in an old stash. --- compiler/router/pin_group.py | 45 ++++++++++++++++-------- compiler/router/router.py | 59 ++++++++++++++++++++++++++++---- compiler/router/supply_router.py | 2 +- 3 files changed, 83 insertions(+), 23 deletions(-) diff --git a/compiler/router/pin_group.py b/compiler/router/pin_group.py index f14abecb..124a8ebf 100644 --- a/compiler/router/pin_group.py +++ b/compiler/router/pin_group.py @@ -16,7 +16,11 @@ class pin_group: self.routed = False # This is a list because we can have a pin group of disconnected sets of pins # and these are represented by separate lists - self.pins = [pin_shapes] + if pin_shapes: + self.pins = [pin_shapes] + else: + self.pins = [] + self.router = router # These are the corresponding pin grids for each pin group. self.grids = set() @@ -53,28 +57,37 @@ class pin_group: """ Remove any pin layout that is contained within another. """ - local_debug = False + local_debug = True if local_debug: debug.info(0,"INITIAL: {}".format(pin_list)) # Make a copy of the list to start new_pin_list = pin_list.copy() - + + remove_indices = set() # This is n^2, but the number is small - for pin1 in pin_list: - for pin2 in pin_list: + for index1,pin1 in enumerate(pin_list): + if index1 in remove_indices: + continue + + for index2,pin2 in enumerate(pin_list): # Can't contain yourself if pin1 == pin2: continue + if index2 in remove_indices: + continue + if pin2.contains(pin1): if local_debug: debug.info(0,"{0} contains {1}".format(pin1,pin2)) - # It may have already been removed by being enclosed in another pin - if pin1 in new_pin_list: - new_pin_list.remove(pin1) + remove_indices.add(index2) + # Remove them in decreasing order to not invalidate the indices + for i in sorted(remove_indices, reverse=True): + del new_pin_list[i] if local_debug: debug.info(0,"FINAL : {}".format(new_pin_list)) + return new_pin_list # FIXME: This relies on some technology parameters from router which is not clean. @@ -106,6 +119,7 @@ class pin_group: ymax = max(plc.y,elc.y) ll = vector(plc.x, ymin) ur = vector(prc.x, ymax) + print(pin,enclosure,ll,ur) p = pin_layout(pin.name, [ll, ur], pin.layer) elif pin.yoverlaps(enclosure): # Is it horizontal overlap, extend pin shape to enclosure @@ -248,13 +262,13 @@ class pin_group: def enclose_pin(self): """ - This will find the biggest rectangle enclosing some grid squares and - put a rectangle over it. It does not enclose grid squares that are blocked - by other shapes. + If there is one set of connected pin shapes, + this will find the smallest rectangle enclosure that overlaps with any pin. + If there is not, it simply returns all the enclosures. """ # Compute the enclosure pin_layout list of the set of tracks enclosure_list = self.compute_enclosures() - + # A single set of connected pins is easy, so use the optimized set if len(self.pins)==1: smallest = self.find_smallest_overlapping(self.pins[0],enclosure_list) @@ -268,7 +282,7 @@ class pin_group: # debug.error("Unable to enclose pin {}".format(self.pins),-1) else: # Multiple pins is hard, so just use all of the enclosure shapes! - # FIXME: Find the minimum set of enclosures to reduce number of shapes. + # At least none of these are redundant shapes though. self.enclosures = enclosure_list debug.info(2,"Computed enclosure(s) {0}\n {1}\n {2}\n {3}".format(self.name, self.pins, self.grids, self.enclosures)) @@ -305,6 +319,7 @@ class pin_group: # Keep the same groups for each pin pin_set = set() blockage_set = set() + print("PINLIST:",self.pins) for pin_list in self.pins: for pin in pin_list: debug.info(2," Converting {0}".format(pin)) @@ -318,10 +333,10 @@ class pin_group: # If we have a blockage, we must remove the grids # Remember, this excludes the pin blockages already shared_set = pin_set & router.blocked_grids - if shared_set: + if len(shared_set)>0: debug.info(2,"Removing pins {}".format(shared_set)) shared_set = blockage_set & router.blocked_grids - if shared_set: + if len(shared_set)>0: debug.info(2,"Removing blocks {}".format(shared_set)) pin_set.difference_update(router.blocked_grids) blockage_set.difference_update(router.blocked_grids) diff --git a/compiler/router/router.py b/compiler/router/router.py index 0a0d2625..e819b882 100644 --- a/compiler/router/router.py +++ b/compiler/router/router.py @@ -155,19 +155,27 @@ class router(router_tech): for pin in pin_list: self.combine_adjacent_pins(pin) #self.write_debug_gds("debug_combine_pins.gds",stop_program=True) + + # Separate any adjacent grids of differing net names to prevent wide metal DRC violations + self.separate_adjacent_pins(pin) # Enclose the continguous grid units in a metal rectangle to fix some DRCs self.enclose_pins() - def combine_adjacent_pins(self, pin_name): + + def combine_adjacent_pins_pass(self, pin_name): """ - This checks for simple cases where a pin component already overlaps a supply rail. - It will add an enclosure to ensure the overlap in wide DRC rule cases. - """ - # Make a copy since we are going to reduce this list - pin_groups = self.pin_groups[pin_name].copy() + Find pins that have adjacent routing tracks and merge them into a + single pin_group. The pins themselves may not be touching, but + enclose_pis in the next step will ensure they are touching. + """ + # Make a copy since we are going to add to (and then reduce) this list + pin_groups = self.pin_groups[pin_name].copy() + + # Start as None to signal the first iteration remove_indices = set() + for index1,pg1 in enumerate(self.pin_groups[pin_name]): # Cannot combine more than once if index1 in remove_indices: @@ -180,6 +188,7 @@ class router(router_tech): if index2 in remove_indices: continue + # Combine if at least 1 grid cell is adjacent if pg1.adjacent(pg2): combined = pin_group(pin_name, [], self) combined.pins = [*pg1.pins, *pg2.pins] @@ -189,12 +198,48 @@ class router(router_tech): remove_indices.update([index1,index2]) pin_groups.append(combined) + # Remove them in decreasing order to not invalidate the indices + debug.info(2,"Removing {}".format(sorted(remove_indices))) for i in sorted(remove_indices, reverse=True): del pin_groups[i] - + + # Use the new pin group! self.pin_groups[pin_name] = pin_groups + removed_pairs = len(remove_indices)/2 + debug.info(1, "Combined {0} pin pairs for {1}".format(removed_pairs,pin_name)) + + return(removed_pairs) + + def combine_adjacent_pins(self, pin_name): + """ + Make multiple passes of the combine adjacent pins until we have no + more combinations or hit an iteration limit. + """ + + # Start as None to signal the first iteration + num_removed_pairs = None + + # Just used in case there's a circular combination or something weird + for iteration_count in range(10): + num_removed_pairs = self.combine_adjacent_pins_pass(pin_name) + if num_removed_pairs==0: + break + else: + debug.warning("Did not converge combining adjacent pins in supply router.") + + def separate_adjacent_pins(self, pin_name, separation=1): + """ + This will try to separate all grid pins by the supplied number of separation + tracks (default is to prevent adjacency). + Go through all of the pin groups and check if any other pin group is + within a separation of it. + If so, reduce the pin group grid to not include the adjacent grid. + Try to do this intelligently to keep th pins enclosed. + """ + pass + def prepare_blockages(self, pin_name): """ Reset and add all of the blockages in the design. diff --git a/compiler/router/supply_router.py b/compiler/router/supply_router.py index 4f12e16a..093bd1de 100644 --- a/compiler/router/supply_router.py +++ b/compiler/router/supply_router.py @@ -71,7 +71,7 @@ class supply_router(router): # Get the pin shapes self.find_pins_and_blockages([self.vdd_name, self.gnd_name]) - #self.write_debug_gds("pin_enclosures.gds",stop_program=True) + self.write_debug_gds("pin_enclosures.gds",stop_program=True) # Add the supply rails in a mesh network and connect H/V with vias # Block everything