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 vector3d import vector3d
class direction(Enum):
NORTH = 1
@ -7,3 +8,25 @@ class direction(Enum):
WEST = 4
UP = 5
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 vector3d import vector3d
def increment_set(curset, direct):
"""
Return the cells incremented in 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))
offset = direction.get_offset(direct)
newset = set()
for c in curset:
newc = c+offset

View File

@ -1,3 +1,4 @@
from direction import direction
from pin_layout import pin_layout
from vector3d import vector3d
from vector import vector
@ -57,7 +58,7 @@ class pin_group:
"""
Remove any pin layout that is contained within another.
"""
local_debug = True
local_debug = False
if local_debug:
debug.info(0,"INITIAL: {}".format(pin_list))
@ -67,6 +68,7 @@ class pin_group:
remove_indices = set()
# This is n^2, but the number is small
for index1,pin1 in enumerate(pin_list):
# If we remove this pin, it can't contain other pins
if index1 in remove_indices:
continue
@ -74,6 +76,7 @@ class pin_group:
# Can't contain yourself
if pin1 == pin2:
continue
# If we already removed it, can't remove it again...
if index2 in remove_indices:
continue
@ -81,6 +84,7 @@ class pin_group:
if local_debug:
debug.info(0,"{0} contains {1}".format(pin1,pin2))
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]
@ -98,15 +102,19 @@ class pin_group:
# Enumerate every possible enclosure
pin_list = []
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)
pin_list.append(enclosure)
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.
"""
if pin.xoverlaps(enclosure):
@ -155,7 +163,7 @@ class pin_group:
for pin_list in self.pins:
for pin in pin_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():
smallest = new_enclosure
@ -220,30 +228,34 @@ class pin_group:
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
starting with the seed and expanding right 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
if not self.grids:
return None
# Start with the ll and make the widest row
row = [ll]
# Move right while we can
# Move in dir1 while we can
while True:
right = row[-1] + vector3d(1,0,0)
next_cell = row[-1] + offset1
# Can't move if not in the pin shape
if right in self.grids and right not in self.router.blocked_grids:
row.append(right)
if next_cell in self.grids and next_cell not in self.router.blocked_grids:
row.append(next_cell)
else:
break
# Move up while we can
# Move in dir2 while we can
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:
# 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:
@ -313,7 +325,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))

View File

@ -191,8 +191,8 @@ class router(router_tech):
# 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]
combined.grids = pg1.grids | pg2.grids
combined.pins = [*pg1.pins, *pg2.pins] # Join the two lists of pins
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," --> {0}\n {1}\n".format(combined.pins,combined.grids))
remove_indices.update([index1,index2])
@ -210,7 +210,7 @@ class router(router_tech):
removed_pairs = len(remove_indices)/2
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):
"""
@ -564,7 +564,8 @@ class router(router_tech):
Analyze the shapes of a pin and combine them into groups which are connected.
"""
pin_set = self.pins[pin_name]
local_debug=False
local_debug = False
# Put each pin in an equivalence class of it's own
equiv_classes = [set([x]) for x in pin_set]
if local_debug:
@ -595,6 +596,8 @@ class router(router_tech):
def combine_classes(equiv_classes):
""" Recursive function to combine classes. """
local_debug = False
if local_debug:
debug.info(0,"\nRECURSE:\n",pformat(equiv_classes))
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
by other shapes.
"""
# These are used for debugging
self.connector_enclosure = []
self.enclosures = []
for pin_name in self.pin_groups.keys():
debug.info(1,"Enclosing pins for {}".format(pin_name))
for pg in self.pin_groups[pin_name]: