Expand blocked pins to neighbor grid cells.

This commit is contained in:
Matt Guthaus 2018-11-09 14:25:10 -08:00
parent 11873c03cd
commit de61630962
3 changed files with 80 additions and 12 deletions

View File

@ -316,7 +316,43 @@ class pin_layout:
return [dx,dy]
else:
return [0,0]
def distance(self, other):
"""
Calculate the distance to another pin layout.
"""
(r1_ll,r1_ur) = self.rect
(r2_ll,r2_ur) = other.rect
def dist(x1, y1, x2, y2):
return sqrt((x2-x1)**2 + (y2-y1)**2)
left = r2_ur.x < r1_ll.x
right = r1_ur.x < r2_ll.x
bottom = r2_ur.y < r1_ll.y
top = r1_ur.y < r2_ll.y
if top and left:
return dist(r1_ll.x, r1_ur.y, r2_ur.x, r2_ll.y)
elif left and bottom:
return dist(r1_ll.x, r1_ll.y, r2_ur.x, r2_ur.y)
elif bottom and right:
return dist(r1_ur.x, r1_ll.y, r2_ll.x, r2_ur.y)
elif right and top:
return dist(r1_ur.x, r1_ur.y, r2_ll.x, r2_ll.y)
elif left:
return r1_ll.x - r2_ur.x
elif right:
return r2_ll.x - r1.ur.x
elif bottom:
return r1_ll.y - r2_ur.y
elif top:
return r2_ll.y - r1_ur.y
else:
# rectangles intersect
return 0
def overlap_length(self, other):
"""
Calculate the intersection segment and determine its length

View File

@ -566,11 +566,10 @@ class pin_group:
debug.info(2," Converting {0}".format(pin))
# Determine which tracks the pin overlaps
pin_in_tracks=self.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 = self.router.convert_blockage(pin)
blockage_set.update(blockage_in_tracks)
# If we have a blockage, we must remove the grids
@ -578,17 +577,26 @@ class pin_group:
shared_set = pin_set & self.router.blocked_grids
if len(shared_set)>0:
debug.info(2,"Removing pins {}".format(shared_set))
pin_set.difference_update(self.router.blocked_grids)
pin_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))
blockage_set.difference_update(self.router.blocked_grids)
blockage_set.difference_update(shared_set)
# At least one of the groups must have some valid tracks
if (len(pin_set)==0 and len(blockage_set)==0):
debug.error("Unable to find unblocked pin {} {}".format(self.name, self.pins))
self.router.write_debug_gds("blocked_pin.gds")
debug.warning("Pin is very close to metal blockage.\nAttempting to expand blocked pin {}".format(self.pins))
for pin_list in self.pins:
for pin in pin_list:
debug.info(2," Converting {0}".format(pin))
# Determine which tracks the pin overlaps
pin_in_tracks=self.router.convert_pin_to_tracks(self.name, pin, expansion=1)
pin_set.update(pin_in_tracks)
if len(pin_set)==0:
debug.error("Unable to find unblocked pin {} {}".format(self.name, self.pins))
self.router.write_debug_gds("blocked_pin.gds")
# We need to route each of the components, so don't combine the groups
self.grids = pin_set | blockage_set

View File

@ -495,10 +495,11 @@ class router(router_tech):
# debug.info(0,"Pin {}".format(pin))
return [ll,ur]
def convert_pin_to_tracks(self, pin_name, pin):
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))
@ -512,8 +513,8 @@ class router(router_tech):
insufficient_list = set()
zindex=self.get_zindex(pin.layer_num)
for x in range(int(ll[0]),int(ur[0])+1):
for y in range(int(ll[1]),int(ur[1])+1):
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):
debug.info(4,"Converting [ {0} , {1} ]".format(x,y))
(full_overlap,partial_overlap) = self.convert_pin_coord_to_tracks(pin, vector3d(x,y,zindex))
if full_overlap:
@ -523,9 +524,14 @@ class router(router_tech):
if len(sufficient_list)>0:
return sufficient_list
elif len(insufficient_list)>0:
# If there wasn't a sufficient grid, find the best and patch it to be on grid.
elif expansion==0 and len(insufficient_list)>0:
#Remove blockages and return the best to be patched
insufficient_list.difference_update(self.blocked_grids)
return self.get_best_offgrid_pin(pin, insufficient_list)
elif expansion>0:
#Remove blockages and return the nearest
insufficient_list.difference_update(self.blocked_grids)
return self.get_nearest_offgrid_pin(pin, insufficient_list)
else:
debug.error("Unable to find any overlapping grids.", -1)
@ -555,6 +561,24 @@ class router(router_tech):
return set([best_coord])
def get_nearest_offgrid_pin(self, pin, insufficient_list):
"""
Given a pin and a list of grid cells (probably non-overlapping),
return the nearest grid cell (center to center).
"""
#print("INSUFFICIENT LIST",insufficient_list)
# Find the coordinate with the most overlap
best_coord = None
best_dist = math.inf
for coord in insufficient_list:
track_pin = self.convert_track_to_pin(coord)
min_dist = pin.distance(track_pin)
if min_dist<best_dist:
best_dist=min_dist
best_coord=coord
return set([best_coord])
def convert_pin_coord_to_tracks(self, pin, coord):
"""