From 0dea153919e6c3ab5d5fb4b4da58be7ff847cefe Mon Sep 17 00:00:00 2001 From: Matthew Guthaus Date: Thu, 7 Nov 2019 16:33:13 +0000 Subject: [PATCH] PEP8 formatting --- compiler/router/pin_group.py | 231 ++++++------ compiler/router/router.py | 656 ++++++++++++++++++----------------- 2 files changed, 468 insertions(+), 419 deletions(-) diff --git a/compiler/router/pin_group.py b/compiler/router/pin_group.py index 99986e76..df97bf9b 100644 --- a/compiler/router/pin_group.py +++ b/compiler/router/pin_group.py @@ -7,17 +7,15 @@ # from direction import direction from pin_layout import pin_layout -from vector3d import vector3d from vector import vector -import grid_utils -from tech import drc import debug + 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. + 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_set, router): @@ -30,19 +28,22 @@ class pin_group: # 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 + # 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 = set(irredundant_pin_set) self.router = router # These are the corresponding pin grids for each pin group. self.grids = set() - # These are the secondary grids that could or could not be part of the pin + # These are the secondary grids that could + # or could not be part of the pin self.secondary_grids = set() # The corresponding set of partially blocked grids for each pin group. - # These are blockages for other nets but unblocked for routing this group. - # These are also blockages if we used a simple enclosure to route to a rail. + # These are blockages for other nets but unblocked + # for routing this group. These are also blockages if we + # used a simple enclosure to route to a rail. self.blockages = set() # This is a set of pin_layout shapes to cover the grids @@ -88,22 +89,23 @@ class pin_group: """ local_debug = False if local_debug: - debug.info(0,"INITIAL: {}".format(pin_list)) + 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 index1,pin1 in enumerate(pin_list): + for index1, pin1 in enumerate(pin_list): # If we remove this pin, it can't contain other pins if index1 in remove_indices: continue - for index2,pin2 in enumerate(pin_list): - # Can't contain yourself, but compare the indices and not the pins + for index2, pin2 in enumerate(pin_list): + # Can't contain yourself, + # but compare the indices and not the pins # so you can remove duplicate copies. - if index1==index2: + if index1 == index2: continue # If we already removed it, can't remove it again... if index2 in remove_indices: @@ -111,7 +113,7 @@ class pin_group: if pin1.contains(pin2): if local_debug: - debug.info(0,"{0} contains {1}".format(pin1,pin2)) + debug.info(0, "{0} contains {1}".format(pin1, pin2)) remove_indices.add(index2) # Remove them in decreasing order to not invalidate the indices @@ -119,7 +121,7 @@ class pin_group: del new_pin_list[i] if local_debug: - debug.info(0,"FINAL : {}".format(new_pin_list)) + debug.info(0, "FINAL : {}".format(new_pin_list)) return new_pin_list @@ -130,23 +132,26 @@ class pin_group: # Enumerate every possible enclosure pin_list = [] for seed in self.grids: - (ll, ur) = self.enclose_pin_grids(seed, direction.NORTH, direction.EAST) + (ll, ur) = self.enclose_pin_grids(seed, + direction.NORTH, + direction.EAST) enclosure = self.router.compute_pin_enclosure(ll, ur, ll.z) pin_list.append(enclosure) - (ll, ur) = self.enclose_pin_grids(seed, direction.EAST, direction.NORTH) + (ll, ur) = self.enclose_pin_grids(seed, + direction.EAST, + direction.NORTH) enclosure = self.router.compute_pin_enclosure(ll, ur, ll.z) pin_list.append(enclosure) - # Now simplify the enclosure list new_pin_list = self.remove_redundant_shapes(pin_list) return new_pin_list def compute_connector(self, pin, enclosure): - """ - Compute a shape to connect the pin to the enclosure shape. + """ + Compute a shape to connect the pin to the enclosure shape. This assumes the shape will be the dimension of the pin. """ if pin.xoverlaps(enclosure): @@ -154,9 +159,9 @@ class pin_group: plc = pin.lc() prc = pin.rc() elc = enclosure.lc() - erc = enclosure.rc() - ymin = min(plc.y,elc.y) - ymax = max(plc.y,elc.y) + # erc = enclosure.rc() + ymin = min(plc.y, elc.y) + ymax = max(plc.y, elc.y) ll = vector(plc.x, ymin) ur = vector(prc.x, ymax) elif pin.yoverlaps(enclosure): @@ -164,9 +169,9 @@ class pin_group: pbc = pin.bc() puc = pin.uc() ebc = enclosure.bc() - euc = enclosure.uc() - xmin = min(pbc.x,ebc.x) - xmax = max(pbc.x,ebc.x) + # euc = enclosure.uc() + xmin = min(pbc.x, ebc.x) + xmax = max(pbc.x, ebc.x) ll = vector(xmin, pbc.y) ur = vector(xmax, puc.y) else: @@ -180,7 +185,7 @@ class pin_group: ll = vector(xmin, ymin) ur = vector(xmax, ymax) - if ll.x==ur.x or ll.y==ur.y: + if ll.x == ur.x or ll.y == ur.y: return None p = pin_layout(pin.name, [ll, ur], pin.layer) return p @@ -202,13 +207,13 @@ class pin_group: # 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(): + if item.by() >= pin.uy(): above_item = item else: break - # There was nothing - if above_item==None: + # There was nothing + if not above_item: return None # If it already overlaps, no connector needed if above_item.overlaps(pin): @@ -219,7 +224,7 @@ class pin_group: 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. """ @@ -235,13 +240,13 @@ class pin_group: # 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(): + if item.uy() <= pin.by(): bottom_item = item else: break # There was nothing to the left - if bottom_item==None: + if not bottom_item: return None # If it already overlaps, no connector needed if bottom_item.overlaps(pin): @@ -274,7 +279,7 @@ class pin_group: break # There was nothing to the left - if left_item==None: + if not left_item: return None # If it already overlaps, no connector needed if left_item.overlaps(pin): @@ -301,13 +306,13 @@ class pin_group: # 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(): + if item.lx() >= pin.rx(): right_item = item else: break # There was nothing to the right - if right_item==None: + if not right_item: return None # If it already overlaps, no connector needed if right_item.overlaps(pin): @@ -319,50 +324,50 @@ class pin_group: def find_smallest_connector(self, pin_list, shape_list): """ - Compute all of the connectors between the overlapping pins and enclosure shape list.. + Compute all of the connectors between the overlapping + pins and enclosure shape list. Return the smallest. """ smallest = None for pin in pin_list: for enclosure in shape_list: new_enclosure = self.compute_connector(pin, enclosure) - if smallest == None or new_enclosure.area() min_width: - if smallest_shape == None or other.area()0): + connector_list = [left_connector, + right_connector, + above_connector, + below_connector] + filtered_list = list(filter(lambda x: not x, connector_list)) + if (len(filtered_list) > 0): import copy - bbox_connector = copy.copy(pin) + bbox_connector = copy.copy(pin) bbox_connector.bbox(filtered_list) self.enclosures.append(bbox_connector) - # Now, make sure each pin touches an enclosure. If not, add another (diagonal) connector. - # This could only happen when there was no enclosure in any cardinal direction from a pin + # Now, make sure each pin touches an enclosure. + # If not, add another (diagonal) connector. + # This could only happen when there was no enclosure + # in any cardinal direction from a pin if not self.overlap_any_shape(self.pins, self.enclosures): - connector = self.find_smallest_connector(self.pins, self.enclosures) - if connector==None: - debug.error("Could not find a connector for {} with {}".format(self.pins, self.enclosures)) + connector = self.find_smallest_connector(self.pins, + self.enclosures) + if not connector: + debug.error("Could not find a connector for {} with {}".format(self.pins, + self.enclosures)) self.router.write_debug_gds("no_connector.gds") self.enclosures.append(connector) - # At this point, the pins are overlapping, but there might be more than one! + # At this point, the pins are overlapping, + # but there might be more than one! overlap_set = set() for pin in self.pins: overlap_set.update(self.transitive_overlap(pin, self.enclosures)) - # Use the new enclosures and recompute the grids that correspond to them - if len(overlap_set)0: - debug.info(2,"Removing pins {}".format(shared_set)) + if len(shared_set) > 0: + debug.info(2, "Removing pins {}".format(shared_set)) pin_set.difference_update(shared_set) shared_set = partial_set & self.router.blocked_grids - if len(shared_set)>0: - debug.info(2,"Removing pins {}".format(shared_set)) + if len(shared_set) > 0: + debug.info(2, "Removing pins {}".format(shared_set)) partial_set.difference_update(shared_set) shared_set = blockage_set & self.router.blocked_grids - if len(shared_set)>0: - debug.info(2,"Removing blocks {}".format(shared_set)) + if len(shared_set) > 0: + debug.info(2, "Removing blocks {}".format(shared_set)) blockage_set.difference_update(shared_set) # At least one of the groups must have some valid tracks - if (len(pin_set)==0 and len(partial_set)==0 and len(blockage_set)==0): - #debug.warning("Pin is very close to metal blockage.\nAttempting to expand blocked pin {}".format(self.pins)) + if (len(pin_set) == 0 and len(partial_set) == 0 and len(blockage_set) == 0): + # debug.warning("Pin is very close to metal blockage.\nAttempting to expand blocked pin {}".format(self.pins)) for pin in self.pins: debug.warning(" Expanding conversion {0}".format(pin)) - # Determine which tracks the pin overlaps - (sufficient,insufficient)=self.router.convert_pin_to_tracks(self.name, pin, expansion=1) + # Determine which tracks the pin overlaps + (sufficient,insufficient)=self.router.convert_pin_to_tracks(self.name, + pin, + expansion=1) pin_set.update(sufficient) partial_set.update(insufficient) - if len(pin_set)==0 and len(partial_set)==0: - debug.error("Unable to find unblocked pin {} {}".format(self.name, self.pins)) + if len(pin_set) == 0 and len(partial_set) == 0: + debug.error("Unable to find unblocked pin {} {}".format(self.name, + self.pins)) self.router.write_debug_gds("blocked_pin.gds") # Consider all the grids that would be blocked - self.grids = pin_set | partial_set - # Remember the secondary grids for removing adjacent pins - self.secondary_grids = partial_set + self.grids = pin_set | partial_set + # Remember the secondary grids for removing adjacent pins + self.secondary_grids = partial_set - debug.info(2," pins {}".format(self.grids)) - debug.info(2," secondary {}".format(self.secondary_grids)) + debug.info(2, " pins {}".format(self.grids)) + debug.info(2, " secondary {}".format(self.secondary_grids)) diff --git a/compiler/router/router.py b/compiler/router/router.py index fd95def6..15f6f6b3 100644 --- a/compiler/router/router.py +++ b/compiler/router/router.py @@ -5,9 +5,9 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -import sys + import gdsMill -from tech import drc,GDS +from tech import drc, GDS from tech import layer as techlayer import math import debug @@ -15,12 +15,12 @@ from router_tech import router_tech from pin_layout import pin_layout from pin_group import pin_group from vector import vector -from vector3d import vector3d -from globals import OPTS,print_time -from pprint import pformat +from vector3d import vector3d +from globals import OPTS, print_time import grid_utils from datetime import datetime + class router(router_tech): """ A router class to read an obstruction map from a gds and plan a @@ -31,7 +31,8 @@ class router(router_tech): def __init__(self, layers, design, gds_filename=None, rail_track_width=1): """ This will instantiate a copy of the gds file or the module at (0,0) and - route on top of this. The blockages from the gds/module will be considered. + route on top of this. The blockages from the gds/module will be + considered. """ router_tech.__init__(self, layers, rail_track_width) @@ -39,7 +40,7 @@ class router(router_tech): # If didn't specify a gds blockage file, write it out to read the gds # This isn't efficient, but easy for now - #start_time = datetime.now() + # start_time = datetime.now() if not gds_filename: gds_filename = OPTS.openram_temp+"temp.gds" self.cell.gds_write(gds_filename) @@ -49,32 +50,37 @@ class router(router_tech): self.reader = gdsMill.Gds2reader(self.layout) self.reader.loadFromFile(gds_filename) self.top_name = self.layout.rootStructureName - #print_time("GDS read",datetime.now(), start_time) + # print_time("GDS read",datetime.now(), start_time) - ### The pin data structures + # The pin data structures # A map of pin names to a set of pin_layout structures # (i.e. pins with a given label) self.pins = {} - # This is a set of all pins (ignoring names) so that can quickly not create blockages for pins - # (They will be blocked when we are routing other nets based on their name.) + # This is a set of all pins (ignoring names) so that can quickly + # not create blockages for pins + # (They will be blocked when we are routing other + # nets based on their name.) self.all_pins = set() - # The labeled pins above categorized into pin groups that are touching/connected. + # The labeled pins above categorized into pin groups + # that are touching/connected. self.pin_groups = {} - ### The blockage data structures - # A list of metal shapes (using the same pin_layout structure) that are not pins but blockages. - self.blockages=[] + # The blockage data structures + # A list of metal shapes (using the same pin_layout structure) + # that are not pins but blockages. + self.blockages = [] # The corresponding set of blocked grids for above pin shapes self.blocked_grids = set() - ### The routed data structures + # The routed data structures # A list of paths that have been "routed" self.paths = [] # A list of path blockages (they might be expanded for wide metal DRC) self.path_blockages = [] - # The boundary will determine the limits to the size of the routing grid + # The boundary will determine the limits to the size + # of the routing grid self.boundary = self.layout.measureBoundary(self.top_name) # These must be un-indexed to get rid of the matrix type self.ll = vector(self.boundary[0][0], self.boundary[0][1]) @@ -90,90 +96,90 @@ class router(router_tech): self.pin_groups = {} # DO NOT clear the blockages as these don't change self.rg.reinit() - - def set_top(self,top_name): + def set_top(self, top_name): """ If we want to route something besides the top-level cell.""" self.top_name = top_name - - def is_wave(self,path): + def is_wave(self, path): """ - Determines if this is a multi-track width wave (True) or a normal route (False) + Determines if this is a multi-track width wave (True) + # or a normal route (False) """ - return len(path[0])>1 + return len(path[0]) > 1 - - def retrieve_pins(self,pin_name): + def retrieve_pins(self, pin_name): """ Retrieve the pin shapes on metal 3 from the layout. """ - debug.info(2,"Retrieving pins for {}.".format(pin_name)) - shape_list=self.layout.getAllPinShapes(str(pin_name)) + debug.info(2, "Retrieving pins for {}.".format(pin_name)) + shape_list = self.layout.getAllPinShapes(str(pin_name)) pin_set = set() for shape in shape_list: - (layer,boundary)=shape + (layer, boundary) = shape # 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] + 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))) + 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) for pin in self.pins[pin_name]: - debug.info(3,"Retrieved pin {}".format(str(pin))) - + debug.info(3, "Retrieved pin {}".format(str(pin))) def find_blockages(self): """ Iterate through all the layers and write the obstacles to the routing grid. - This doesn't consider whether the obstacles will be pins or not. They get reset later - if they are not actually a blockage. + This doesn't consider whether the obstacles will be pins or not. + They get reset later if they are not actually a blockage. """ - debug.info(1,"Finding blockages.") - for layer in [self.vert_layer_number,self.horiz_layer_number]: + debug.info(1, "Finding blockages.") + for layer in [self.vert_layer_number, self.horiz_layer_number]: self.retrieve_blockages(layer) def find_pins_and_blockages(self, pin_list): """ Find the pins and blockages in the design """ - # This finds the pin shapes and sorts them into "groups" that are connected - # This must come before the blockages, so we can not count the pins themselves + # This finds the pin shapes and sorts them into "groups" that + # are connected. This must come before the blockages, so we + # can not count the pins themselves # as blockages. start_time = datetime.now() for pin_name in pin_list: self.retrieve_pins(pin_name) - print_time("Retrieving pins",datetime.now(), start_time, 4) + print_time("Retrieving pins", datetime.now(), start_time, 4) start_time = datetime.now() for pin_name in pin_list: self.analyze_pins(pin_name) - print_time("Analyzing pins",datetime.now(), start_time, 4) + print_time("Analyzing pins", datetime.now(), start_time, 4) # This will get all shapes as blockages and convert to grid units # This ignores shapes that were pins start_time = datetime.now() self.find_blockages() - print_time("Finding blockages",datetime.now(), start_time, 4) + print_time("Finding blockages", datetime.now(), start_time, 4) # Convert the blockages to grid units start_time = datetime.now() self.convert_blockages() - print_time("Converting blockages",datetime.now(), start_time, 4) + print_time("Converting blockages", datetime.now(), start_time, 4) # This will convert the pins to grid units - # It must be done after blockages to ensure no DRCs between expanded pins and blocked grids + # It must be done after blockages to ensure no DRCs + # between expanded pins and blocked grids start_time = datetime.now() for pin in pin_list: self.convert_pins(pin) - print_time("Converting pins",datetime.now(), start_time, 4) + print_time("Converting pins", datetime.now(), start_time, 4) # Combine adjacent pins into pin groups to reduce run-time # by reducing the number of maze routes. @@ -184,17 +190,18 @@ class router(router_tech): # print_time("Combining adjacent pins",datetime.now(), start_time, 4) - # Separate any adjacent grids of differing net names that overlap + # Separate any adjacent grids of differing net names + # that overlap # Must be done before enclosing pins start_time = datetime.now() self.separate_adjacent_pins(0) - print_time("Separating adjacent pins",datetime.now(), start_time, 4) + print_time("Separating adjacent pins", datetime.now(), start_time, 4) - # Enclose the continguous grid units in a metal rectangle to fix some DRCs + # Enclose the continguous grid units in a metal + # rectangle to fix some DRCs start_time = datetime.now() self.enclose_pins() - print_time("Enclosing pins",datetime.now(), start_time, 4) - + print_time("Enclosing pins", datetime.now(), start_time, 4) # MRG: Removing this code for now. The later compute enclosure code # assumes that all pins are touching and this may produce sets of pins @@ -249,57 +256,63 @@ class router(router_tech): # # Use the new pin group! # self.pin_groups[pin_name] = new_pin_groups # removed_pairs = old_size - len(new_pin_groups) - # debug.info(1, "Combined {0} pin groups for {1}".format(removed_pairs,pin_name)) + # debug.info(1, + # "Combined {0} pin groups for {1}".format(removed_pairs,pin_name)) # return removed_pairs - def separate_adjacent_pins(self, separation): """ - This will try to separate all grid pins by the supplied number of separation - tracks (default is to prevent adjacency). + This will try to separate all grid pins by the supplied + number of separation tracks (default is to prevent adjacency). """ # Commented out to debug with SCMOS - #if separation==0: - # return + # if separation==0: + # return pin_names = self.pin_groups.keys() - for i,pin_name1 in enumerate(pin_names): - for j,pin_name2 in enumerate(pin_names): - if i==j: + for i, pin_name1 in enumerate(pin_names): + for j, pin_name2 in enumerate(pin_names): + if i == j: continue - if i>j: + if i > j: return self.separate_adjacent_pin(pin_name1, pin_name2, separation) def separate_adjacent_pin(self, pin_name1, pin_name2, separation): """ - Go through all of the pin groups and check if any other pin group is + 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. """ - debug.info(1,"Comparing {0} and {1} adjacency".format(pin_name1, pin_name2)) + debug.info(1, + "Comparing {0} and {1} adjacency".format(pin_name1, + pin_name2)) removed_grids = 0 - for index1,pg1 in enumerate(self.pin_groups[pin_name1]): - for index2,pg2 in enumerate(self.pin_groups[pin_name2]): + for index1, pg1 in enumerate(self.pin_groups[pin_name1]): + for index2, pg2 in enumerate(self.pin_groups[pin_name2]): adj_grids = pg1.adjacent_grids(pg2, separation) removed_grids += len(adj_grids) # These should have the same length, so... - if len(adj_grids)>0: - debug.info(3,"Adjacent grids {0} {1} adj={2}".format(index1,index2,adj_grids)) + if len(adj_grids) > 0: + debug.info(3, + "Adjacent grids {0} {1} adj={2}".format(index1, + index2, + adj_grids)) self.remove_adjacent_grid(pg1, pg2, adj_grids) - debug.info(1,"Removed {} adjacent grids.".format(removed_grids)) + debug.info(1, "Removed {} adjacent grids.".format(removed_grids)) def remove_adjacent_grid(self, pg1, pg2, adj_grids): """ Remove one of the adjacent grids in a heuristic manner. - This will try to keep the groups similar sized by removing from the bigger group. + This will try to keep the groups similar sized by + removing from the bigger group. """ - if pg1.size()>pg2.size(): + if pg1.size() > pg2.size(): bigger = pg1 smaller = pg2 else: @@ -309,54 +322,58 @@ class router(router_tech): for adj in adj_grids: - # If the adjacent grids are a subset of the secondary grids (i.e. not necessary) - # remove them from each + # If the adjacent grids are a subset of the secondary + # grids (i.e. not necessary) remove them from each if adj in bigger.secondary_grids: - debug.info(3,"Removing {} from bigger secondary {}".format(adj, bigger)) + debug.info(3,"Removing {} from bigger secondary {}".format(adj, + bigger)) bigger.grids.remove(adj) bigger.secondary_grids.remove(adj) self.blocked_grids.add(adj) elif adj in smaller.secondary_grids: - debug.info(3,"Removing {} from smaller secondary {}".format(adj, smaller)) + debug.info(3,"Removing {} from smaller secondary {}".format(adj, + smaller)) smaller.grids.remove(adj) smaller.secondary_grids.remove(adj) self.blocked_grids.add(adj) else: - # If we couldn't remove from a secondary grid, we must remove from the primary + # If we couldn't remove from a secondary grid, + # we must remove from the primary # grid of at least one pin if adj in bigger.grids: - debug.info(3,"Removing {} from bigger primary {}".format(adj, bigger)) + debug.info(3,"Removing {} from bigger primary {}".format(adj, + bigger)) bigger.grids.remove(adj) elif adj in smaller.grids: - debug.info(3,"Removing {} from smaller primary {}".format(adj, smaller)) + debug.info(3,"Removing {} from smaller primary {}".format(adj, + smaller)) smaller.grids.remove(adj) - - - def prepare_blockages(self, pin_name): """ Reset and add all of the blockages in the design. Names is a list of pins to add as a blockage. """ - debug.info(3,"Preparing blockages.") + debug.info(3, "Preparing blockages.") # Start fresh. Not the best for run-time, but simpler. self.clear_blockages() # This adds the initial blockges of the design - #print("BLOCKING:",self.blocked_grids) - self.set_blockages(self.blocked_grids,True) + #print("BLOCKING:", self.blocked_grids) + self.set_blockages(self.blocked_grids, True) - # Block all of the supply rails (some will be unblocked if they're a target) + # Block all of the supply rails + # (some will be unblocked if they're a target) self.set_supply_rail_blocked(True) - # Block all of the pin components (some will be unblocked if they're a source/target) + # Block all of the pin components + # (some will be unblocked if they're a source/target) # Also block the previous routes for name in self.pin_groups: blockage_grids = {y for x in self.pin_groups[name] for y in x.grids} - self.set_blockages(blockage_grids,True) + self.set_blockages(blockage_grids, True) blockage_grids = {y for x in self.pin_groups[name] for y in x.blockages} - self.set_blockages(blockage_grids,True) + self.set_blockages(blockage_grids, True) # FIXME: These duplicate a bit of work # These are the paths that have already been routed. @@ -366,22 +383,20 @@ class router(router_tech): # directly to a rail, but unblock all the source components so we can # route over them blockage_grids = {y for x in self.pin_groups[pin_name] for y in x.grids} - self.set_blockages(blockage_grids,False) - + self.set_blockages(blockage_grids, False) def convert_shape_to_units(self, shape): - """ - Scale a shape (two vector list) to user units + """ + Scale a shape (two vector list) to user units """ unit_factor = [GDS["unit"][0]] * 2 - ll=shape[0].scale(unit_factor) - ur=shape[1].scale(unit_factor) - return [ll,ur] - + ll = shape[0].scale(unit_factor) + ur = shape[1].scale(unit_factor) + return [ll, ur] def min_max_coord(self, coord): - """ - Find the lowest and highest corner of a Rectangle + """ + Find the lowest and highest corner of a Rectangle """ coordinate = [] minx = min(coord[0][0], coord[1][0], coord[2][0], coord[3][0]) @@ -392,24 +407,24 @@ class router(router_tech): coordinate += [vector(maxx, maxy)] return coordinate - def get_inertia(self,p0,p1): - """ - Sets the direction based on the previous direction we came from. + def get_inertia(self, p0, p1): + """ + Sets the direction based on the previous direction we came from. """ # direction (index) of movement - if p0.x!=p1.x: + if p0.x != p1.x: return 0 - elif p0.y!=p1.y: + elif p0.y != p1.y: return 1 else: # z direction return 2 def clear_blockages(self): - """ + """ Clear all blockages on the grid. """ - debug.info(3,"Clearing all blockages") + debug.info(3, "Clearing all blockages") self.rg.clear_blockages() def set_blockages(self, blockages, value=True): @@ -417,137 +432,142 @@ class router(router_tech): self.rg.set_blocked(blockages, value) def get_blockage_tracks(self, ll, ur, z): - debug.info(3,"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): - for y in range(int(ll[1]),int(ur[1])+1): - block_list.append(vector3d(x,y,z)) + for x in range(int(ll[0]), int(ur[0])+1): + for y in range(int(ll[1]), int(ur[1])+1): + block_list.append(vector3d(x, y, z)) return set(block_list) def convert_blockage(self, blockage): - """ - Convert a pin layout blockage shape to routing grid tracks. + """ + Convert a pin layout blockage shape to routing grid tracks. """ # Inflate the blockage by half a spacing rule - [ll,ur]=self.convert_blockage_to_tracks(blockage.inflate()) + [ll, ur] = self.convert_blockage_to_tracks(blockage.inflate()) zlayer = self.get_zindex(blockage.layer_num) blockage_tracks = self.get_blockage_tracks(ll, ur, zlayer) return blockage_tracks def convert_blockages(self): """ Convert blockages to grid tracks. """ - debug.info(1,"Converting blockages.") + debug.info(1, "Converting blockages.") for blockage in self.blockages: - debug.info(3,"Converting blockage {}".format(str(blockage))) + debug.info(3, "Converting blockage {}".format(str(blockage))) blockage_list = self.convert_blockage(blockage) self.blocked_grids.update(blockage_list) - - def retrieve_blockages(self, layer_num): + def retrieve_blockages(self, layer_num): """ Recursive find boundaries as blockages to the routing grid. """ shapes = self.layout.getAllShapes(layer_num) for boundary in shapes: - ll = vector(boundary[0],boundary[1]) - ur = vector(boundary[2],boundary[3]) - rect = [ll,ur] - new_pin = pin_layout("blockage{}".format(len(self.blockages)),rect,layer_num) + ll = vector(boundary[0], boundary[1]) + ur = vector(boundary[2], boundary[3]) + rect = [ll, ur] + new_pin = pin_layout("blockage{}".format(len(self.blockages)), + rect, + layer_num) - # If there is a rectangle that is the same in the pins, it isn't a blockage! + # If there is a rectangle that is the same in the pins, + # it isn't a blockage! if new_pin not in self.all_pins: self.blockages.append(new_pin) - def convert_point_to_units(self, p): """ Convert a path set of tracks to center line path. """ pt = vector3d(p) - pt = pt.scale(self.track_widths[0],self.track_widths[1],1) + pt = pt.scale(self.track_widths[0], self.track_widths[1], 1) return pt def convert_wave_to_units(self, wave): - """ - Convert a wave to a set of center points + """ + Convert a wave to a set of center points """ return [self.convert_point_to_units(i) for i in wave] - def convert_blockage_to_tracks(self, shape): - """ + """ Convert a rectangular blockage shape into track units. """ - (ll,ur) = shape + (ll, ur) = shape ll = snap_to_grid(ll) ur = snap_to_grid(ur) # to scale coordinates to tracks - debug.info(3,"Converting [ {0} , {1} ]".format(ll,ur)) - old_ll = ll - old_ur = ur - ll=ll.scale(self.track_factor) - ur=ur.scale(self.track_factor) + debug.info(3, "Converting [ {0} , {1} ]".format(ll, ur)) + ll = ll.scale(self.track_factor) + ur = ur.scale(self.track_factor) # We can round since we are using inflated shapes # and the track points are at the center ll = ll.round() ur = ur.round() - return [ll,ur] + return [ll, ur] def convert_pin_to_tracks(self, pin_name, pin, expansion=0): - """ - Convert a rectangular pin shape into a list of track locations,layers. - If no pins are "on-grid" (i.e. sufficient overlap) it makes the one with most overlap if it is not blocked. - If expansion>0, expamine areas beyond the current pin when it is blocked. """ - (ll,ur) = pin.rect - debug.info(3,"Converting pin [ {0} , {1} ]".format(ll,ur)) + Convert a rectangular pin shape into a list of track locations,layers. + If no pins are "on-grid" (i.e. sufficient overlap) + it makes the one with most overlap if it is not blocked. + If expansion>0, expamine areas beyond the current pin + when it is blocked. + """ + (ll, ur) = pin.rect + debug.info(3, "Converting pin [ {0} , {1} ]".format(ll, ur)) # scale the size bigger to include neaby tracks - ll=ll.scale(self.track_factor).floor() - ur=ur.scale(self.track_factor).ceil() + ll = ll.scale(self.track_factor).floor() + ur = ur.scale(self.track_factor).ceil() # Keep tabs on tracks with sufficient and insufficient overlap sufficient_list = set() insufficient_list = set() - zindex=self.get_zindex(pin.layer_num) - for x in range(int(ll[0])+expansion,int(ur[0])+1+expansion): - for y in range(int(ll[1]+expansion),int(ur[1])+1+expansion): - (full_overlap, partial_overlap) = self.convert_pin_coord_to_tracks(pin, vector3d(x,y,zindex)) + zindex = self.get_zindex(pin.layer_num) + for x in range(int(ll[0]) + expansion, int(ur[0]) + 1 + expansion): + for y in range(int(ll[1] + expansion), int(ur[1]) + 1 + expansion): + (full_overlap, partial_overlap) = self.convert_pin_coord_to_tracks(pin, + vector3d(x, + y, + zindex)) if full_overlap: sufficient_list.update([full_overlap]) if partial_overlap: insufficient_list.update([partial_overlap]) - debug.info(2,"Converting [ {0} , {1} ] full={2}".format(x,y, full_overlap)) + debug.info(2, + "Converting [ {0} , {1} ] full={2}".format(x, + y, + full_overlap)) # Return all grids with any potential overlap (sufficient or not) - return (sufficient_list,insufficient_list) - + return (sufficient_list, insufficient_list) def get_all_offgrid_pin(self, pin, insufficient_list): - """ + """ Find a list of all pins with some overlap. """ - #print("INSUFFICIENT LIST",insufficient_list) + # print("INSUFFICIENT LIST",insufficient_list) # Find the coordinate with the most overlap any_overlap = set() for coord in insufficient_list: full_pin = self.convert_track_to_pin(coord) # Compute the overlap with that rectangle - overlap_rect=pin.compute_overlap(full_pin) + overlap_rect = pin.compute_overlap(full_pin) # Determine the max x or y overlap max_overlap = max(overlap_rect) - if max_overlap>0: + if max_overlap > 0: any_overlap.update([coord]) return any_overlap def get_best_offgrid_pin(self, pin, insufficient_list): - """ + """ Find a list of the single pin with the most overlap. """ # Find the coordinate with the most overlap @@ -556,17 +576,17 @@ class router(router_tech): for coord in insufficient_list: full_pin = self.convert_track_to_pin(coord) # Compute the overlap with that rectangle - overlap_rect=pin.compute_overlap(full_pin) + overlap_rect = pin.compute_overlap(full_pin) # Determine the min x or y overlap min_overlap = min(overlap_rect) - if min_overlap>best_overlap: - best_overlap=min_overlap - best_coord=coord + if min_overlap > best_overlap: + best_overlap = min_overlap + best_coord = coord return set([best_coord]) def get_furthest_offgrid_pin(self, pin, insufficient_list): - """ + """ Get a grid cell that is the furthest from the blocked grids. """ @@ -575,14 +595,14 @@ class router(router_tech): best_dist = math.inf for coord in insufficient_list: min_dist = grid_utils.distance_set(coord, self.blocked_grids) - if min_dist 0: - debug.info(2," Overlap: {0} >? {1}".format(overlap_length,0)) - return (coord,None) + if overlap_length == math.inf or overlap_length > 0: + debug.info(2," Overlap: {0} >? {1}".format(overlap_length, 0)) + return (coord, None) # If it overlaps with the inflated pin, it is partial - elif inflated_overlap_length==math.inf or inflated_overlap_length > 0: - debug.info(2," Partial overlap: {0} >? {1}".format(inflated_overlap_length,0)) - return (None,coord) + elif inflated_overlap_length == math.inf or inflated_overlap_length > 0: + debug.info(2," Partial overlap: {0} >? {1}".format(inflated_overlap_length, 0)) + return (None, coord) else: - debug.info(2," No overlap: {0} {1}".format(overlap_length,0)) - return (None,None) - + debug.info(2, " No overlap: {0} {1}".format(overlap_length, 0)) + return (None, None) def convert_track_to_pin(self, track): - """ + """ Convert a grid point into a rectangle shape that is centered track in the track and leaves half a DRC space in each direction. """ - # calculate lower left - x = track.x*self.track_width - 0.5*self.track_width + 0.5*self.track_space - y = track.y*self.track_width - 0.5*self.track_width + 0.5*self.track_space + # calculate lower left + x = track.x * self.track_width - 0.5 * self.track_width + 0.5 * self.track_space + y = track.y * self.track_width - 0.5 * self.track_width + 0.5 * self.track_space ll = snap_to_grid(vector(x,y)) # calculate upper right - x = track.x*self.track_width + 0.5*self.track_width - 0.5*self.track_space - y = track.y*self.track_width + 0.5*self.track_width - 0.5*self.track_space - ur = snap_to_grid(vector(x,y)) + x = track.x * self.track_width + 0.5 * self.track_width - 0.5 * self.track_space + y = track.y * self.track_width + 0.5 * self.track_width - 0.5 * self.track_space + ur = snap_to_grid(vector(x, y)) p = pin_layout("", [ll, ur], self.get_layer(track[2])) return p def convert_track_to_shape_pin(self, track): - """ - Convert a grid point into a rectangle shape that occupies the entire centered - track. + """ + Convert a grid point into a rectangle shape + that occupies the entire centered track. """ # to scale coordinates to tracks x = track[0]*self.track_width - 0.5*self.track_width y = track[1]*self.track_width - 0.5*self.track_width # offset lowest corner object to to (-track halo,-track halo) - ll = snap_to_grid(vector(x,y)) - ur = snap_to_grid(ll + vector(self.track_width,self.track_width)) + ll = snap_to_grid(vector(x, y)) + ur = snap_to_grid(ll + vector(self.track_width, self.track_width)) p = pin_layout("", [ll, ur], self.get_layer(track[2])) return p def convert_track_to_shape(self, track): - """ - Convert a grid point into a rectangle shape that occupies the entire centered - track. + """ + Convert a grid point into a rectangle shape + that occupies the entire centered track. """ # to scale coordinates to tracks try: x = track[0]*self.track_width - 0.5*self.track_width except TypeError: - print(track[0],type(track[0]),self.track_width,type(self.track_width)) + print(track[0], type(track[0]), self.track_width, type(self.track_width)) y = track[1]*self.track_width - 0.5*self.track_width # offset lowest corner object to to (-track halo,-track halo) - ll = snap_to_grid(vector(x,y)) - ur = snap_to_grid(ll + vector(self.track_width,self.track_width)) + ll = snap_to_grid(vector(x, y)) + ur = snap_to_grid(ll + vector(self.track_width, self.track_width)) - return [ll,ur] + return [ll, ur] def convert_track_to_inflated_pin(self, track): - """ - Convert a grid point into a rectangle shape that is inflated by a half DRC space. """ - # calculate lower left + Convert a grid point into a rectangle shape + that is inflated by a half DRC space. + """ + # calculate lower left x = track.x*self.track_width - 0.5*self.track_width - 0.5*self.track_space y = track.y*self.track_width - 0.5*self.track_width - 0.5*self.track_space ll = snap_to_grid(vector(x,y)) @@ -691,16 +719,17 @@ class router(router_tech): # calculate upper right x = track.x*self.track_width + 0.5*self.track_width + 0.5*self.track_space y = track.y*self.track_width + 0.5*self.track_width + 0.5*self.track_space - ur = snap_to_grid(vector(x,y)) + ur = snap_to_grid(vector(x, y)) p = pin_layout("", [ll, ur], self.get_layer(track[2])) return p def analyze_pins(self, pin_name): - """ - Analyze the shapes of a pin and combine them into pin_groups which are connected. """ - debug.info(2,"Analyzing pin groups for {}.".format(pin_name)) + Analyze the shapes of a pin and combine + them into pin_groups which are connected. + """ + debug.info(2, "Analyzing pin groups for {}.".format(pin_name)) pin_set = self.pins[pin_name] # This will be a list of pin tuples that overlap @@ -713,8 +742,8 @@ class router(router_tech): y_coordinates.sort(key=lambda x: x[0]) # Map the pins to the lower indices - bottom_index_map = {x[1]:i for i,x in enumerate(y_coordinates) if x[2]=="bottom"} - top_index_map = {x[1]:i for i,x in enumerate(y_coordinates) if x[2]=="bottom"} + bottom_index_map = {x[1]: i for i, x in enumerate(y_coordinates) if x[2] == "bottom"} + # top_index_map = {x[1]: i for i, x in enumerate(y_coordinates) if x[2] == "bottom"} # Sort the pin list by x coordinate pin_list = list(pin_set) @@ -725,10 +754,10 @@ class router(router_tech): # start at pin's lower y coordinate bottom_index = bottom_index_map[pin] compared_pins = set() - for i in range(bottom_index,len(y_coordinates)): + for i in range(bottom_index, len(y_coordinates)): compare_pin = y_coordinates[i][1] # Don't overlap yourself - if pin==compare_pin: + if pin == compare_pin: continue # Done when we encounter any shape above the pin if compare_pin.by() > pin.uy(): @@ -739,7 +768,7 @@ class router(router_tech): compared_pins.add(compare_pin) # If we overlap, add them to the list if pin.overlaps(compare_pin): - overlap_list.append((pin,compare_pin)) + overlap_list.append((pin, compare_pin)) # Initial unique group assignments group_id = {} @@ -749,33 +778,31 @@ class router(router_tech): gid += 1 for p in overlap_list: - (p1,p2) = p + (p1, p2) = p for pin in pin_list: if group_id[pin] == group_id[p2]: group_id[pin] = group_id[p1] - # For each pin add it to it's group group_map = {} for pin in pin_list: gid = group_id[pin] if gid not in group_map: - group_map[gid] = pin_group(name=pin_name, pin_set=[], router=self) + group_map[gid] = pin_group(name=pin_name, + pin_set=[], + router=self) # We always add it to the first set since they are touching group_map[gid].pins.add(pin) self.pin_groups[pin_name] = list(group_map.values()) - def convert_pins(self, pin_name): - """ + """ Convert the pin groups into pin tracks and blockage tracks. """ - debug.info(1,"Converting pins for {}.".format(pin_name)) + debug.info(1, "Converting pins for {}.".format(pin_name)) for pg in self.pin_groups[pin_name]: pg.convert_pin() - - def enclose_pins(self): """ @@ -784,13 +811,13 @@ class router(router_tech): by other shapes. """ for pin_name in self.pin_groups: - debug.info(1,"Enclosing pins for {}".format(pin_name)) + debug.info(1, "Enclosing pins for {}".format(pin_name)) for pg in self.pin_groups[pin_name]: pg.enclose_pin() pg.add_enclosure(self.cell) def add_source(self, pin_name): - """ + """ This will mark the grids for all pin components as a source. Marking as source or target also clears blockage status. """ @@ -798,7 +825,7 @@ class router(router_tech): self.add_pin_component_source(pin_name, i) def add_target(self, pin_name): - """ + """ This will mark the grids for all pin components as a target. Marking as source or target also clears blockage status. """ @@ -806,44 +833,46 @@ class router(router_tech): self.add_pin_component_target(pin_name, i) def num_pin_components(self, pin_name): - """ + """ This returns how many disconnected pin components there are. """ return len(self.pin_groups[pin_name]) def add_pin_component_source(self, pin_name, index): - """ - This will mark only the pin tracks from the indexed pin component as a source. + """ + This will mark only the pin tracks + from the indexed pin component as a source. It also unsets it as a blockage. """ - debug.check(index1: + if len(self.layers) > 1: self.cell.add_route(layers=self.layers, coordinates=abs_path, layer_widths=self.layer_widths) @@ -908,83 +936,81 @@ class router(router_tech): def add_single_enclosure(self, track): """ - Add a metal enclosure that is the size of the routing grid minus a spacing on each side. + Add a metal enclosure that is the size of + the routing grid minus a spacing on each side. """ pin = self.convert_track_to_pin(track) - (ll,ur) = pin.rect + (ll, ur) = pin.rect self.cell.add_rect(layer=self.get_layer(track.z), offset=ll, width=ur.x-ll.x, height=ur.y-ll.y) - - - def add_via(self,loc,size=1): - """ + def add_via(self, loc, size=1): + """ Add a via centered at the current location """ - loc = self.convert_point_to_units(vector3d(loc[0],loc[1],0)) + loc = self.convert_point_to_units(vector3d(loc[0], loc[1], 0)) self.cell.add_via_center(layers=self.layers, - offset=vector(loc.x,loc.y), - size=(size,size)) + offset=vector(loc.x, loc.y), + size=(size, size)) def compute_pin_enclosure(self, ll, ur, zindex, name=""): """ Enclose the tracks from ll to ur in a single rectangle that meets - the track DRC rules. + the track DRC rules. """ layer = self.get_layer(zindex) - # This finds the pin shape enclosed by the track with DRC spacing on the sides + # This finds the pin shape enclosed by the + # track with DRC spacing on the sides pin = self.convert_track_to_pin(ll) - (abs_ll,unused) = pin.rect + (abs_ll, unused) = pin.rect pin = self.convert_track_to_pin(ur) - (unused,abs_ur) = pin.rect + (unused, abs_ur) = pin.rect pin = pin_layout(name, [abs_ll, abs_ur], layer) return pin - def contract_path(self,path): - """ + def contract_path(self, path): + """ Remove intermediate points in a rectilinear path or a wave. """ # Waves are always linear, so just return the first and last. if self.is_wave(path): - return [path[0],path[-1]] + return [path[0], path[-1]] # Make a list only of points that change inertia of the path newpath = [path[0]] - for i in range(1,len(path)-1): - prev_inertia=self.get_inertia(path[i-1][0],path[i][0]) - next_inertia=self.get_inertia(path[i][0],path[i+1][0]) + for i in range(1, len(path) - 1): + prev_inertia = self.get_inertia(path[i-1][0], path[i][0]) + next_inertia = self.get_inertia(path[i][0], path[i+1][0]) # if we switch directions, add the point, otherwise don't - if prev_inertia!=next_inertia: + if prev_inertia != next_inertia: newpath.append(path[i]) # always add the last path unless it was a single point - if len(path)>1: + if len(path) > 1: newpath.append(path[-1]) return newpath - - def run_router(self, detour_scale): """ - This assumes the blockages, source, and target are all set up. + This assumes the blockages, source, and target are all set up. """ # Double check source and taget are not same node, if so, we are done! - for k,v in self.rg.map.items(): + for k, v in self.rg.map.items(): if v.source and v.target: debug.error("Grid cell is source and target! {}".format(k)) return False # returns the path in tracks - (path,cost) = self.rg.route(detour_scale) + (path, cost) = self.rg.route(detour_scale) if path: - debug.info(1,"Found path: cost={0} ".format(cost)) - debug.info(1,str(path)) + debug.info(1, "Found path: cost={0} ".format(cost)) + debug.info(1, str(path)) self.paths.append(path) self.add_route(path) @@ -998,34 +1024,34 @@ class router(router_tech): return False return True - def annotate_pin_and_tracks(self, pin, tracks): """" Annotate some shapes for debug purposes """ - debug.info(0,"Annotating\n pin {0}\n tracks {1}".format(pin,tracks)) + debug.info(0, "Annotating\n pin {0}\n tracks {1}".format(pin, tracks)) for coord in tracks: - (ll,ur) = self.convert_track_to_shape(coord) + (ll, ur) = self.convert_track_to_shape(coord) self.cell.add_rect(layer="text", offset=ll, width=ur[0]-ll[0], height=ur[1]-ll[1]) - (ll,ur) = self.convert_track_to_pin(coord).rect + (ll, ur) = self.convert_track_to_pin(coord).rect self.cell.add_rect(layer="boundary", offset=ll, width=ur[0]-ll[0], height=ur[1]-ll[1]) - (ll,ur) = pin.rect + (ll, ur) = pin.rect self.cell.add_rect(layer="text", offset=ll, width=ur[0]-ll[0], height=ur[1]-ll[1]) def write_debug_gds(self, gds_name="debug_route.gds", stop_program=True): - """ - Write out a GDS file with the routing grid and search information annotated on it. """ - debug.info(0,"Writing annotated router gds file to {}".format(gds_name)) + Write out a GDS file with the routing grid and + search information annotated on it. + """ + debug.info(0, "Writing annotated router gds file to {}".format(gds_name)) self.del_router_info() self.add_router_info() self.cell.gds_write(gds_name) @@ -1039,41 +1065,41 @@ class router(router_tech): Display grid information in the GDS file for a single grid cell. """ shape = self.convert_track_to_shape(g) - partial_track=vector(0,self.track_width/6.0) + partial_track = vector(0,self.track_width/6.0) self.cell.add_rect(layer="text", offset=shape[0], width=shape[1].x-shape[0].x, height=shape[1].y-shape[0].y) - t=self.rg.map[g].get_type() + t = self.rg.map[g].get_type() # midpoint offset - off=vector((shape[1].x+shape[0].x)/2, + off = vector((shape[1].x+shape[0].x)/2, (shape[1].y+shape[0].y)/2) - if t!=None: - if g[2]==1: + if t != None: + if g[2] == 1: # Upper layer is upper right label - type_off=off+partial_track + type_off = off + partial_track else: # Lower layer is lower left label - type_off=off-partial_track + type_off = off - partial_track self.cell.add_label(text=str(t), layer="text", offset=type_off) - t=self.rg.map[g].get_cost() - partial_track=vector(self.track_width/6.0,0) - if t!=None: - if g[2]==1: + t = self.rg.map[g].get_cost() + partial_track = vector(self.track_width/6.0, 0) + if t: + if g[2] == 1: # Upper layer is right label - type_off=off+partial_track + type_off = off + partial_track else: # Lower layer is left label - type_off=off-partial_track + type_off = off - partial_track self.cell.add_label(text=str(t), layer="text", offset=type_off) - self.cell.add_label(text="{0},{1}".format(g[0],g[1]), + self.cell.add_label(text="{0},{1}".format(g[0], g[1]), layer="text", offset=shape[0], zoom=0.05) @@ -1082,18 +1108,17 @@ class router(router_tech): """ Erase all of the comments on the current level. """ - debug.info(0,"Erasing router info") + debug.info(0, "Erasing router info") layer_num = techlayer["text"] self.cell.objs = [x for x in self.cell.objs if x.layerNumber != layer_num] - def add_router_info(self): """ - Write the routing grid and router cost, blockage, pins on - the boundary layer for debugging purposes. This can only be + Write the routing grid and router cost, blockage, pins on + the boundary layer for debugging purposes. This can only be called once or the labels will overlap. """ - debug.info(0,"Adding router info") + debug.info(0, "Adding router info") show_blockages = False show_blockage_grids = False @@ -1108,14 +1133,14 @@ class router(router_tech): if show_blockages: # Display the inflated blockage for blockage in self.blockages: - debug.info(1,"Adding {}".format(blockage)) - (ll,ur) = blockage.inflate() + debug.info(1, "Adding {}".format(blockage)) + (ll, ur) = blockage.inflate() self.cell.add_rect(layer="text", offset=ll, width=ur.x-ll.x, height=ur.y-ll.y) if show_blockage_grids: - self.set_blockages(self.blocked_grids,True) + self.set_blockages(self.blocked_grids, True) for g in self.rg.map: self.annotate_grid(g) @@ -1125,22 +1150,27 @@ class router(router_tech): if not pg.enclosed: continue for pin in pg.enclosures: - #print("enclosure: ",pin.name,pin.ll(),pin.width(),pin.height()) + # print("enclosure: ", + # pin.name, + # pin.ll(), + # pin.width(), + # pin.height()) self.cell.add_rect(layer="text", offset=pin.ll(), width=pin.width(), height=pin.height()) - -# FIXME: This should be replaced with vector.snap_to_grid at some point + +# FIXME: This should be replaced with vector.snap_to_grid at some point def snap_to_grid(offset): """ Changes the coodrinate to match the grid settings """ xoff = snap_val_to_grid(offset[0]) - yoff = snap_val_to_grid(offset[1]) + yoff = snap_val_to_grid(offset[1]) return vector(xoff, yoff) + def snap_val_to_grid(x): grid = drc("grid") xgrid = int(round(round((x / grid), 2), 0))