PEP8 formatting

This commit is contained in:
Matthew Guthaus 2019-11-07 16:33:13 +00:00
parent a2422cc8d4
commit 0dea153919
2 changed files with 468 additions and 419 deletions

View File

@ -7,12 +7,10 @@
# #
from direction import direction from direction import direction
from pin_layout import pin_layout from pin_layout import pin_layout
from vector3d import vector3d
from vector import vector from vector import vector
import grid_utils
from tech import drc
import debug import debug
class pin_group: class pin_group:
""" """
A class to represent a group of rectangular design pin. A class to represent a group of rectangular design pin.
@ -30,19 +28,22 @@ class pin_group:
# Remove any redundant pins (i.e. contained in other pins) # Remove any redundant pins (i.e. contained in other pins)
irredundant_pin_set = self.remove_redundant_shapes(list(pin_set)) 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 # and these are represented by separate lists
self.pins = set(irredundant_pin_set) self.pins = set(irredundant_pin_set)
self.router = router self.router = router
# These are the corresponding pin grids for each pin group. # These are the corresponding pin grids for each pin group.
self.grids = set() 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() self.secondary_grids = set()
# The corresponding set of partially blocked grids for each pin group. # 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 blockages for other nets but unblocked
# These are also blockages if we used a simple enclosure to route to a rail. # for routing this group. These are also blockages if we
# used a simple enclosure to route to a rail.
self.blockages = set() self.blockages = set()
# This is a set of pin_layout shapes to cover the grids # This is a set of pin_layout shapes to cover the grids
@ -88,22 +89,23 @@ class pin_group:
""" """
local_debug = False local_debug = False
if local_debug: 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 # Make a copy of the list to start
new_pin_list = pin_list.copy() new_pin_list = pin_list.copy()
remove_indices = set() remove_indices = set()
# This is n^2, but the number is small # 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 we remove this pin, it can't contain other pins
if index1 in remove_indices: if index1 in remove_indices:
continue continue
for index2,pin2 in enumerate(pin_list): for index2, pin2 in enumerate(pin_list):
# Can't contain yourself, but compare the indices and not the pins # Can't contain yourself,
# but compare the indices and not the pins
# so you can remove duplicate copies. # so you can remove duplicate copies.
if index1==index2: if index1 == index2:
continue continue
# If we already removed it, can't remove it again... # If we already removed it, can't remove it again...
if index2 in remove_indices: if index2 in remove_indices:
@ -111,7 +113,7 @@ class pin_group:
if pin1.contains(pin2): if pin1.contains(pin2):
if local_debug: 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_indices.add(index2)
# Remove them in decreasing order to not invalidate the indices # Remove them in decreasing order to not invalidate the indices
@ -119,7 +121,7 @@ class pin_group:
del new_pin_list[i] del new_pin_list[i]
if local_debug: if local_debug:
debug.info(0,"FINAL : {}".format(new_pin_list)) debug.info(0, "FINAL : {}".format(new_pin_list))
return new_pin_list return new_pin_list
@ -130,15 +132,18 @@ class pin_group:
# Enumerate every possible enclosure # Enumerate every possible enclosure
pin_list = [] pin_list = []
for seed in self.grids: 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) enclosure = self.router.compute_pin_enclosure(ll, ur, ll.z)
pin_list.append(enclosure) 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) enclosure = self.router.compute_pin_enclosure(ll, ur, ll.z)
pin_list.append(enclosure) pin_list.append(enclosure)
# Now simplify the enclosure list # Now simplify the enclosure list
new_pin_list = self.remove_redundant_shapes(pin_list) new_pin_list = self.remove_redundant_shapes(pin_list)
@ -154,9 +159,9 @@ class pin_group:
plc = pin.lc() plc = pin.lc()
prc = pin.rc() prc = pin.rc()
elc = enclosure.lc() elc = enclosure.lc()
erc = enclosure.rc() # erc = enclosure.rc()
ymin = min(plc.y,elc.y) ymin = min(plc.y, elc.y)
ymax = max(plc.y,elc.y) ymax = max(plc.y, elc.y)
ll = vector(plc.x, ymin) ll = vector(plc.x, ymin)
ur = vector(prc.x, ymax) ur = vector(prc.x, ymax)
elif pin.yoverlaps(enclosure): elif pin.yoverlaps(enclosure):
@ -164,9 +169,9 @@ class pin_group:
pbc = pin.bc() pbc = pin.bc()
puc = pin.uc() puc = pin.uc()
ebc = enclosure.bc() ebc = enclosure.bc()
euc = enclosure.uc() # euc = enclosure.uc()
xmin = min(pbc.x,ebc.x) xmin = min(pbc.x, ebc.x)
xmax = max(pbc.x,ebc.x) xmax = max(pbc.x, ebc.x)
ll = vector(xmin, pbc.y) ll = vector(xmin, pbc.y)
ur = vector(xmax, puc.y) ur = vector(xmax, puc.y)
else: else:
@ -180,7 +185,7 @@ class pin_group:
ll = vector(xmin, ymin) ll = vector(xmin, ymin)
ur = vector(xmax, ymax) 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 return None
p = pin_layout(pin.name, [ll, ur], pin.layer) p = pin_layout(pin.name, [ll, ur], pin.layer)
return p return p
@ -202,13 +207,13 @@ class pin_group:
# Find the bottom edge that is next to the pin's top edge # Find the bottom edge that is next to the pin's top edge
above_item = None above_item = None
for item in edge_list: for item in edge_list:
if item.by()>=pin.uy(): if item.by() >= pin.uy():
above_item = item above_item = item
else: else:
break break
# There was nothing # There was nothing
if above_item==None: if not above_item:
return None return None
# If it already overlaps, no connector needed # If it already overlaps, no connector needed
if above_item.overlaps(pin): if above_item.overlaps(pin):
@ -235,13 +240,13 @@ class pin_group:
# Find the upper edge that is next to the pin's bottom edge # Find the upper edge that is next to the pin's bottom edge
bottom_item = None bottom_item = None
for item in edge_list: for item in edge_list:
if item.uy()<=pin.by(): if item.uy() <= pin.by():
bottom_item = item bottom_item = item
else: else:
break break
# There was nothing to the left # There was nothing to the left
if bottom_item==None: if not bottom_item:
return None return None
# If it already overlaps, no connector needed # If it already overlaps, no connector needed
if bottom_item.overlaps(pin): if bottom_item.overlaps(pin):
@ -274,7 +279,7 @@ class pin_group:
break break
# There was nothing to the left # There was nothing to the left
if left_item==None: if not left_item:
return None return None
# If it already overlaps, no connector needed # If it already overlaps, no connector needed
if left_item.overlaps(pin): 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 # Find the left edge that is next to the pin's right edge
right_item = None right_item = None
for item in edge_list: for item in edge_list:
if item.lx()>=pin.rx(): if item.lx() >= pin.rx():
right_item = item right_item = item
else: else:
break break
# There was nothing to the right # There was nothing to the right
if right_item==None: if not right_item:
return None return None
# If it already overlaps, no connector needed # If it already overlaps, no connector needed
if right_item.overlaps(pin): if right_item.overlaps(pin):
@ -319,14 +324,15 @@ class pin_group:
def find_smallest_connector(self, pin_list, shape_list): 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. Return the smallest.
""" """
smallest = None smallest = None
for pin in pin_list: for pin in pin_list:
for enclosure in shape_list: for enclosure in shape_list:
new_enclosure = self.compute_connector(pin, enclosure) new_enclosure = self.compute_connector(pin, enclosure)
if smallest == None or new_enclosure.area()<smallest.area(): if not smallest or new_enclosure.area() < smallest.area():
smallest = new_enclosure smallest = new_enclosure
return smallest return smallest
@ -339,15 +345,14 @@ class pin_group:
smallest_shape = None smallest_shape = None
for pin in pin_list: for pin in pin_list:
overlap_shape = self.find_smallest_overlapping_pin(pin,shape_list) overlap_shape = self.find_smallest_overlapping_pin(pin, shape_list)
if overlap_shape: if overlap_shape:
overlap_length = pin.overlap_length(overlap_shape) # overlap_length = pin.overlap_length(overlap_shape)
if smallest_shape == None or overlap_shape.area()<smallest_shape.area(): if not smallest_shape or overlap_shape.area() < smallest_shape.area():
smallest_shape = overlap_shape smallest_shape = overlap_shape
return smallest_shape return smallest_shape
def find_smallest_overlapping_pin(self, pin, shape_list): def find_smallest_overlapping_pin(self, pin, shape_list):
""" """
Find the smallest area shape in shape_list that overlaps with any Find the smallest area shape in shape_list that overlaps with any
@ -355,14 +360,14 @@ class pin_group:
""" """
smallest_shape = None smallest_shape = None
zindex=self.router.get_zindex(pin.layer_num) zindex = self.router.get_zindex(pin.layer_num)
(min_width,min_space) = self.router.get_layer_width_space(zindex) (min_width, min_space) = self.router.get_layer_width_space(zindex)
# Now compare it with every other shape to check how much they overlap # Now compare it with every other shape to check how much they overlap
for other in shape_list: for other in shape_list:
overlap_length = pin.overlap_length(other) overlap_length = pin.overlap_length(other)
if overlap_length > min_width: if overlap_length > min_width:
if smallest_shape == None or other.area()<smallest_shape.area(): if not smallest_shape or other.area() < smallest_shape.area():
smallest_shape = other smallest_shape = other
return smallest_shape return smallest_shape
@ -378,7 +383,6 @@ class pin_group:
return False return False
def max_pin_layout(self, pin_list): def max_pin_layout(self, pin_list):
""" """
Return the max area pin_layout Return the max area pin_layout
@ -398,8 +402,8 @@ class pin_group:
dir1 and dir2 should be two orthogonal directions. dir1 and dir2 should be two orthogonal directions.
""" """
offset1= direction.get_offset(dir1) offset1 = direction.get_offset(dir1)
offset2= direction.get_offset(dir2) offset2 = direction.get_offset(dir2)
# We may have started with an empty set # We may have started with an empty set
if not self.grids: if not self.grids:
@ -431,13 +435,13 @@ class pin_group:
# Add a shape from ll to ur # Add a shape from ll to ur
ur = row[-1] ur = row[-1]
return (ll,ur) return (ll, ur)
def enclose_pin(self): def enclose_pin(self):
""" """
If there is one set of connected pin shapes, If there is one set of connected pin shapes,
this will find the smallest rectangle enclosure that overlaps with any pin. this will find the smallest rectangle enclosure that
overlaps with any pin.
If there is not, it simply returns all the enclosures. If there is not, it simply returns all the enclosures.
""" """
self.enclosed = True self.enclosed = True
@ -453,40 +457,53 @@ class pin_group:
continue continue
# Find a connector in the cardinal directions # Find a connector in the cardinal directions
# If there is overlap, but it isn't contained, these could all be None # If there is overlap, but it isn't contained,
# These could also be none if the pin is diagonal from the enclosure # these could all be None
# These could also be none if the pin is
# diagonal from the enclosure
left_connector = self.find_left_connector(pin, self.enclosures) left_connector = self.find_left_connector(pin, self.enclosures)
right_connector = self.find_right_connector(pin, self.enclosures) right_connector = self.find_right_connector(pin, self.enclosures)
above_connector = self.find_above_connector(pin, self.enclosures) above_connector = self.find_above_connector(pin, self.enclosures)
below_connector = self.find_below_connector(pin, self.enclosures) below_connector = self.find_below_connector(pin, self.enclosures)
connector_list = [left_connector, right_connector, above_connector, below_connector] connector_list = [left_connector,
filtered_list = list(filter(lambda x: x!=None, connector_list)) right_connector,
if (len(filtered_list)>0): above_connector,
below_connector]
filtered_list = list(filter(lambda x: not x, connector_list))
if (len(filtered_list) > 0):
import copy import copy
bbox_connector = copy.copy(pin) bbox_connector = copy.copy(pin)
bbox_connector.bbox(filtered_list) bbox_connector.bbox(filtered_list)
self.enclosures.append(bbox_connector) self.enclosures.append(bbox_connector)
# Now, make sure each pin touches an enclosure. If not, add another (diagonal) connector. # Now, make sure each pin touches an enclosure.
# This could only happen when there was no enclosure in any cardinal direction from a pin # 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): if not self.overlap_any_shape(self.pins, self.enclosures):
connector = self.find_smallest_connector(self.pins, self.enclosures) connector = self.find_smallest_connector(self.pins,
if connector==None: self.enclosures)
debug.error("Could not find a connector for {} with {}".format(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.router.write_debug_gds("no_connector.gds")
self.enclosures.append(connector) 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() overlap_set = set()
for pin in self.pins: for pin in self.pins:
overlap_set.update(self.transitive_overlap(pin, self.enclosures)) overlap_set.update(self.transitive_overlap(pin, self.enclosures))
# Use the new enclosures and recompute the grids that correspond to them # Use the new enclosures and recompute the grids
if len(overlap_set)<len(self.enclosures): # that correspond to them
if len(overlap_set) < len(self.enclosures):
self.enclosures = overlap_set self.enclosures = overlap_set
self.grids=set() self.grids = set()
# Also update the grid locations with the new (possibly pruned) enclosures # Also update the grid locations with the new
# (possibly pruned) enclosures
for enclosure in self.enclosures: for enclosure in self.enclosures:
(sufficient,insufficient) = self.router.convert_pin_to_tracks(self.name,enclosure) (sufficient, insufficient) = self.router.convert_pin_to_tracks(self.name,
enclosure)
self.grids.update(sufficient) self.grids.update(sufficient)
@ -513,7 +530,6 @@ class pin_group:
if old_shape.overlaps(cur_shape): if old_shape.overlaps(cur_shape):
connected_set.add(cur_shape) connected_set.add(cur_shape)
# Remove the original shape # Remove the original shape
connected_set.remove(shape) connected_set.remove(shape)
@ -525,19 +541,18 @@ class pin_group:
return connected_set return connected_set
def add_enclosure(self, cell): def add_enclosure(self, cell):
""" """
Add the enclosure shape to the given cell. Add the enclosure shape to the given cell.
""" """
for enclosure in self.enclosures: for enclosure in self.enclosures:
debug.info(2,"Adding enclosure {0} {1}".format(self.name, enclosure)) debug.info(2, "Adding enclosure {0} {1}".format(self.name,
enclosure))
cell.add_rect(layer=enclosure.layer, cell.add_rect(layer=enclosure.layer,
offset=enclosure.ll(), offset=enclosure.ll(),
width=enclosure.width(), width=enclosure.width(),
height=enclosure.height()) height=enclosure.height())
def perimeter_grids(self): def perimeter_grids(self):
""" """
Return a list of the grids on the perimeter. Return a list of the grids on the perimeter.
@ -566,7 +581,6 @@ class pin_group:
return False return False
def adjacent_grids(self, other, separation): def adjacent_grids(self, other, separation):
""" """
Determine the sets of grids that are within a separation distance Determine the sets of grids that are within a separation distance
@ -592,44 +606,49 @@ class pin_group:
blockage_set = set() blockage_set = set()
for pin in self.pins: for pin in self.pins:
debug.info(2," Converting {0}".format(pin)) debug.info(2, " Converting {0}".format(pin))
# Determine which tracks the pin overlaps # Determine which tracks the pin overlaps
(sufficient,insufficient)=self.router.convert_pin_to_tracks(self.name, pin) (sufficient, insufficient)=self.router.convert_pin_to_tracks(self.name,
pin)
pin_set.update(sufficient) pin_set.update(sufficient)
partial_set.update(insufficient) partial_set.update(insufficient)
# Blockages will be a super-set of pins since it uses the inflated pin shape. # Blockages will be a super-set of pins since
# it uses the inflated pin shape.
blockage_in_tracks = self.router.convert_blockage(pin) blockage_in_tracks = self.router.convert_blockage(pin)
blockage_set.update(blockage_in_tracks) blockage_set.update(blockage_in_tracks)
# If we have a blockage, we must remove the grids # If we have a blockage, we must remove the grids
# Remember, this excludes the pin blockages already # Remember, this excludes the pin blockages already
shared_set = pin_set & self.router.blocked_grids shared_set = pin_set & self.router.blocked_grids
if len(shared_set)>0: if len(shared_set) > 0:
debug.info(2,"Removing pins {}".format(shared_set)) debug.info(2, "Removing pins {}".format(shared_set))
pin_set.difference_update(shared_set) pin_set.difference_update(shared_set)
shared_set = partial_set & self.router.blocked_grids shared_set = partial_set & self.router.blocked_grids
if len(shared_set)>0: if len(shared_set) > 0:
debug.info(2,"Removing pins {}".format(shared_set)) debug.info(2, "Removing pins {}".format(shared_set))
partial_set.difference_update(shared_set) partial_set.difference_update(shared_set)
shared_set = blockage_set & self.router.blocked_grids shared_set = blockage_set & self.router.blocked_grids
if len(shared_set)>0: if len(shared_set) > 0:
debug.info(2,"Removing blocks {}".format(shared_set)) debug.info(2, "Removing blocks {}".format(shared_set))
blockage_set.difference_update(shared_set) blockage_set.difference_update(shared_set)
# At least one of the groups must have some valid tracks # 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): 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)) # debug.warning("Pin is very close to metal blockage.\nAttempting to expand blocked pin {}".format(self.pins))
for pin in self.pins: for pin in self.pins:
debug.warning(" Expanding conversion {0}".format(pin)) debug.warning(" Expanding conversion {0}".format(pin))
# Determine which tracks the pin overlaps # Determine which tracks the pin overlaps
(sufficient,insufficient)=self.router.convert_pin_to_tracks(self.name, pin, expansion=1) (sufficient,insufficient)=self.router.convert_pin_to_tracks(self.name,
pin,
expansion=1)
pin_set.update(sufficient) pin_set.update(sufficient)
partial_set.update(insufficient) partial_set.update(insufficient)
if len(pin_set)==0 and len(partial_set)==0: if len(pin_set) == 0 and len(partial_set) == 0:
debug.error("Unable to find unblocked pin {} {}".format(self.name, self.pins)) debug.error("Unable to find unblocked pin {} {}".format(self.name,
self.pins))
self.router.write_debug_gds("blocked_pin.gds") self.router.write_debug_gds("blocked_pin.gds")
# Consider all the grids that would be blocked # Consider all the grids that would be blocked
@ -637,8 +656,8 @@ class pin_group:
# Remember the secondary grids for removing adjacent pins # Remember the secondary grids for removing adjacent pins
self.secondary_grids = partial_set self.secondary_grids = partial_set
debug.info(2," pins {}".format(self.grids)) debug.info(2, " pins {}".format(self.grids))
debug.info(2," secondary {}".format(self.secondary_grids)) debug.info(2, " secondary {}".format(self.secondary_grids))

File diff suppressed because it is too large Load Diff