Enumerate more enclosures.

This commit is contained in:
Matt Guthaus 2018-10-29 13:49:29 -07:00
parent cd87df8f76
commit fa272be3bd
4 changed files with 58 additions and 36 deletions

View File

@ -1,4 +1,5 @@
from enum import Enum from enum import Enum
from vector3d import vector3d
class direction(Enum): class direction(Enum):
NORTH = 1 NORTH = 1
@ -7,3 +8,25 @@ class direction(Enum):
WEST = 4 WEST = 4
UP = 5 UP = 5
DOWN = 6 DOWN = 6
def get_offset(direct):
"""
Returns the vector offset for a given direction.
"""
if direct==direction.NORTH:
offset = vector3d(0,1,0)
elif direct==direction.SOUTH:
offset = vector3d(0,-1,0)
elif direct==direction.EAST:
offset = vector3d(1,0,0)
elif direct==direction.WEST:
offset = vector3d(-1,0,0)
elif direct==direction.UP:
offset = vector3d(0,0,1)
elif direct==direction.DOWN:
offset = vector3d(0,0,-1)
else:
debug.error("Invalid direction {}".format(dirct))
return offset

View File

@ -6,25 +6,13 @@ import debug
from direction import direction from direction import direction
from vector3d import vector3d from vector3d import vector3d
def increment_set(curset, direct): def increment_set(curset, direct):
""" """
Return the cells incremented in given direction Return the cells incremented in given direction
""" """
if direct==direction.NORTH: offset = direction.get_offset(direct)
offset = vector3d(0,1,0)
elif direct==direction.SOUTH:
offset = vector3d(0,-1,0)
elif direct==direction.EAST:
offset = vector3d(1,0,0)
elif direct==direction.WEST:
offset = vector3d(-1,0,0)
elif direct==direction.UP:
offset = vector3d(0,0,1)
elif direct==direction.DOWN:
offset = vector3d(0,0,-1)
else:
debug.error("Invalid direction {}".format(dirct))
newset = set() newset = set()
for c in curset: for c in curset:
newc = c+offset newc = c+offset

View File

@ -1,3 +1,4 @@
from direction import direction
from pin_layout import pin_layout from pin_layout import pin_layout
from vector3d import vector3d from vector3d import vector3d
from vector import vector from vector import vector
@ -57,7 +58,7 @@ class pin_group:
""" """
Remove any pin layout that is contained within another. Remove any pin layout that is contained within another.
""" """
local_debug = True local_debug = False
if local_debug: if local_debug:
debug.info(0,"INITIAL: {}".format(pin_list)) debug.info(0,"INITIAL: {}".format(pin_list))
@ -67,6 +68,7 @@ class pin_group:
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 index1 in remove_indices: if index1 in remove_indices:
continue continue
@ -74,6 +76,7 @@ class pin_group:
# Can't contain yourself # Can't contain yourself
if pin1 == pin2: if pin1 == pin2:
continue continue
# If we already removed it, can't remove it again...
if index2 in remove_indices: if index2 in remove_indices:
continue continue
@ -81,6 +84,7 @@ class pin_group:
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
for i in sorted(remove_indices, reverse=True): for i in sorted(remove_indices, reverse=True):
del new_pin_list[i] del new_pin_list[i]
@ -98,15 +102,19 @@ 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) (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)
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)
return self.remove_redundant_shapes(pin_list) return self.remove_redundant_shapes(pin_list)
def compute_enclosure(self, pin, enclosure): def compute_connector(self, pin, enclosure):
""" """
Compute an enclosure 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. This assumes the shape will be the dimension of the pin.
""" """
if pin.xoverlaps(enclosure): if pin.xoverlaps(enclosure):
@ -155,7 +163,7 @@ class pin_group:
for pin_list in self.pins: for pin_list in self.pins:
for pin in pin_list: for pin in pin_list:
for enclosure in enclosure_list: for enclosure in enclosure_list:
new_enclosure = self.compute_enclosure(pin, enclosure) new_enclosure = self.compute_connector(pin, enclosure)
if smallest == None or new_enclosure.area()<smallest.area(): if smallest == None or new_enclosure.area()<smallest.area():
smallest = new_enclosure smallest = new_enclosure
@ -220,30 +228,34 @@ class pin_group:
return pin return pin
def enclose_pin_grids(self, ll): def enclose_pin_grids(self, ll, dir1=direction.NORTH, dir2=direction.EAST):
""" """
This encloses a single pin component with a rectangle This encloses a single pin component with a rectangle
starting with the seed and expanding right until blocked starting with the seed and expanding right until blocked
and then up until blocked. and then up until blocked.
dir1 and dir2 should be two orthogonal directions.
""" """
offset1= direction.get_offset(dir1)
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:
return None return None
# Start with the ll and make the widest row # Start with the ll and make the widest row
row = [ll] row = [ll]
# Move right while we can # Move in dir1 while we can
while True: while True:
right = row[-1] + vector3d(1,0,0) next_cell = row[-1] + offset1
# Can't move if not in the pin shape # Can't move if not in the pin shape
if right in self.grids and right not in self.router.blocked_grids: if next_cell in self.grids and next_cell not in self.router.blocked_grids:
row.append(right) row.append(next_cell)
else: else:
break break
# Move up while we can # Move in dir2 while we can
while True: while True:
next_row = [x+vector3d(0,1,0) for x in row] next_row = [x+offset2 for x in row]
for cell in next_row: for cell in next_row:
# Can't move if any cell is not in the pin shape # Can't move if any cell is not in the pin shape
if cell not in self.grids or cell in self.router.blocked_grids: if cell not in self.grids or cell in self.router.blocked_grids:
@ -313,7 +325,7 @@ class pin_group:
# Keep the same groups for each pin # Keep the same groups for each pin
pin_set = set() pin_set = set()
blockage_set = set() blockage_set = set()
print("PINLIST:",self.pins)
for pin_list in self.pins: for pin_list in self.pins:
for pin in pin_list: for pin in pin_list:
debug.info(2," Converting {0}".format(pin)) debug.info(2," Converting {0}".format(pin))

View File

@ -191,8 +191,8 @@ class router(router_tech):
# Combine if at least 1 grid cell is adjacent # Combine if at least 1 grid cell is adjacent
if pg1.adjacent(pg2): if pg1.adjacent(pg2):
combined = pin_group(pin_name, [], self) combined = pin_group(pin_name, [], self)
combined.pins = [*pg1.pins, *pg2.pins] combined.pins = [*pg1.pins, *pg2.pins] # Join the two lists of pins
combined.grids = pg1.grids | pg2.grids combined.grids = pg1.grids | pg2.grids # OR the set of grid locations
debug.info(2,"Combining {0}:\n {1}\n {2}".format(pin_name, pg1.pins, pg2.pins)) debug.info(2,"Combining {0}:\n {1}\n {2}".format(pin_name, pg1.pins, pg2.pins))
debug.info(2," --> {0}\n {1}\n".format(combined.pins,combined.grids)) debug.info(2," --> {0}\n {1}\n".format(combined.pins,combined.grids))
remove_indices.update([index1,index2]) remove_indices.update([index1,index2])
@ -210,7 +210,7 @@ class router(router_tech):
removed_pairs = len(remove_indices)/2 removed_pairs = len(remove_indices)/2
debug.info(1, "Combined {0} pin pairs for {1}".format(removed_pairs,pin_name)) debug.info(1, "Combined {0} pin pairs for {1}".format(removed_pairs,pin_name))
return(removed_pairs) return removed_pairs
def combine_adjacent_pins(self, pin_name): def combine_adjacent_pins(self, pin_name):
""" """
@ -564,7 +564,8 @@ class router(router_tech):
Analyze the shapes of a pin and combine them into groups which are connected. Analyze the shapes of a pin and combine them into groups which are connected.
""" """
pin_set = self.pins[pin_name] pin_set = self.pins[pin_name]
local_debug=False local_debug = False
# Put each pin in an equivalence class of it's own # Put each pin in an equivalence class of it's own
equiv_classes = [set([x]) for x in pin_set] equiv_classes = [set([x]) for x in pin_set]
if local_debug: if local_debug:
@ -595,6 +596,8 @@ class router(router_tech):
def combine_classes(equiv_classes): def combine_classes(equiv_classes):
""" Recursive function to combine classes. """ """ Recursive function to combine classes. """
local_debug = False
if local_debug: if local_debug:
debug.info(0,"\nRECURSE:\n",pformat(equiv_classes)) debug.info(0,"\nRECURSE:\n",pformat(equiv_classes))
if len(equiv_classes)==1: if len(equiv_classes)==1:
@ -634,10 +637,6 @@ class router(router_tech):
put a rectangle over it. It does not enclose grid squares that are blocked put a rectangle over it. It does not enclose grid squares that are blocked
by other shapes. by other shapes.
""" """
# These are used for debugging
self.connector_enclosure = []
self.enclosures = []
for pin_name in self.pin_groups.keys(): for pin_name in self.pin_groups.keys():
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]: for pg in self.pin_groups[pin_name]: