New algorithm for finding pins. Includes off-grid pin computation.

This commit is contained in:
Matt Guthaus 2017-05-25 10:37:24 -07:00
parent dd9b9d73b8
commit 7e44d8762e
2 changed files with 104 additions and 68 deletions

View File

@ -143,22 +143,18 @@ class grid:
self.map[n].blocked=True self.map[n].blocked=True
def set_source(self,ll,ur,z): def add_source(self,track_list):
debug.info(1,"Adding source ll={0} ur={1} z={2}".format(str(ll),str(ur),z)) debug.info(3,"Adding source list={0}".format(str(track_list)))
for x in range(int(ll[0]),int(ur[0])+1): for n in track_list:
for y in range(int(ll[1]),int(ur[1])+1):
n = vector3d(x,y,z)
self.add_map(n) self.add_map(n)
self.map[n].source=True self.map[n].source=True
# Can't have a blocked target otherwise it's infeasible # Can't have a blocked target otherwise it's infeasible
self.map[n].blocked=False self.map[n].blocked=False
self.source.append(n) self.source.append(n)
def set_target(self,ll,ur,z): def add_target(self,track_list):
debug.info(1,"Adding target ll={0} ur={1} z={2}".format(str(ll),str(ur),z)) debug.info(3,"Adding target list={0}".format(str(track_list)))
for x in range(int(ll[0]),int(ur[0])+1): for n in track_list:
for y in range(int(ll[1]),int(ur[1])+1):
n = vector3d(x,y,z)
self.add_map(n) self.add_map(n)
self.map[n].target=True self.map[n].target=True
# Can't have a blocked target otherwise it's infeasible # Can't have a blocked target otherwise it's infeasible
@ -190,7 +186,7 @@ class grid:
p.blocked=True p.blocked=True
def set_path(self,path): def add_path(self,path):
""" """
Mark the path in the routing grid for visualization Mark the path in the routing grid for visualization
""" """

View File

@ -150,9 +150,9 @@ class router:
# clear the blockage attribute # clear the blockage attribute
self.find_blockages() self.find_blockages()
self.set_source(src) self.add_source(src)
self.set_target(dest) self.add_target(dest)
# View the initial route pins and blockages for debugging # View the initial route pins and blockages for debugging
#self.rg.view() #self.rg.view()
@ -161,7 +161,7 @@ class router:
(self.path,cost) = self.rg.route(cost_bound_scale) (self.path,cost) = self.rg.route(cost_bound_scale)
debug.info(1,"Found path: cost={0} ".format(cost)) debug.info(1,"Found path: cost={0} ".format(cost))
debug.info(2,str(self.path)) debug.info(2,str(self.path))
self.set_path(self.path) self.add_path(self.path)
# View the final route for debugging # View the final route for debugging
#self.rg.view() #self.rg.view()
@ -194,39 +194,33 @@ class router:
debug.info(1,str(contracted_path)) debug.info(1,str(contracted_path))
# Make sure there's a pin enclosure on the source and dest # Make sure there's a pin enclosure on the source and dest
# This should be 1/2 DRC spacing from the edges of the grid add_src_via = contracted_path[0].z!=self.source_pin_zindex
src_shape = self.convert_track_to_shape(contracted_path[0]) self.add_grid_pin(cell,contracted_path[0],add_src_via)
cell.add_rect(layer=self.layers[2*contracted_path[0].z], add_tgt_via = contracted_path[-1].z!=self.target_pin_zindex
offset=src_shape[0], self.add_grid_pin(cell,contracted_path[-1],add_tgt_via)
width=src_shape[1].x-src_shape[0].x,
height=src_shape[1].y-src_shape[0].y)
dest_shape = self.convert_track_to_shape(contracted_path[-1])
cell.add_rect(layer=self.layers[2*contracted_path[-1].z],
offset=dest_shape[0],
width=dest_shape[1].x-dest_shape[0].x,
height=dest_shape[1].y-dest_shape[0].y)
# convert the path back to absolute units from tracks # convert the path back to absolute units from tracks
abs_path = map(self.convert_point_to_units,contracted_path) abs_path = map(self.convert_point_to_units,contracted_path)
debug.info(1,str(abs_path)) debug.info(1,str(abs_path))
cell.add_route(self.layers,abs_path) cell.add_route(self.layers,abs_path)
# Check if a via is needed at the start point
if (contracted_path[0].z!=self.source_pin_zindex): def add_grid_pin(self,cell,point,add_via=False):
"""
Create a rectangle at the grid 3D point that is 1/2 DRC smaller
than the routing grid on all sides.
"""
pin = self.convert_track_to_pin(point)
cell.add_rect(layer=self.layers[2*point.z],
offset=pin[0],
width=pin[1].x-pin[0].x,
height=pin[1].y-pin[0].y)
if add_via:
# offset this by 1/2 the via size # offset this by 1/2 the via size
c=contact(self.layers, (1, 1)) c=contact(self.layers, (1, 1))
via_offset = vector(-0.5*c.width,-0.5*c.height) via_offset = vector(-0.5*c.width,-0.5*c.height)
cell.add_via(self.layers,abs_path[0]+via_offset) cell.add_via(self.layers,vector(point[0],point[1])+via_offset)
# Check if a via is needed at the end point
if (contracted_path[-1].z!=self.target_pin_zindex):
# offset this by 1/2 the via size
c=contact(self.layers, (1, 1))
via_offset = vector(-0.5*c.width,-0.5*c.height)
cell.add_via(self.layers,abs_path[-1]+via_offset)
def create_steiner_routes(self,pins): def create_steiner_routes(self,pins):
@ -306,41 +300,43 @@ class router:
newpath.append(path[-1]) newpath.append(path[-1])
return newpath return newpath
def set_path(self,path): def add_path(self,path):
""" """
Mark the path in the routing grid. Mark the path in the routing grid.
""" """
debug.info(3,"Set path: " + str(path)) debug.info(3,"Set path: " + str(path))
self.rg.set_path(path) self.rg.add_path(path)
def set_source(self,src): def add_source(self,pin):
""" """
Mark the grids that are in the pin rectangle ranges to have the source property. Mark the grids that are in the pin rectangle ranges to have the source property.
pin can be a location or a label.
""" """
(pin_layer,self.source_pin_shapes) = self.find_pin(src) (pin_layer,self.source_pin_shapes) = self.find_pin(pin)
zindex = 0 if pin_layer==self.horiz_layer_number else 1 zindex = 0 if pin_layer==self.horiz_layer_number else 1
self.source_pin_zindex = zindex self.source_pin_zindex = zindex
for shape in self.source_pin_shapes: for shape in self.source_pin_shapes:
shape_in_tracks=self.convert_pin_to_tracks(shape) pin_in_tracks=self.convert_pin_to_tracks(shape,zindex,pin)
debug.info(1,"Set source: " + str(src) + " " + str(shape_in_tracks) + " z=" + str(zindex)) debug.info(1,"Set source: " + str(pin) + " " + str(pin_in_tracks) + " z=" + str(zindex))
self.rg.set_source(shape_in_tracks[0],shape_in_tracks[1],zindex) self.rg.add_source(pin_in_tracks)
def set_target(self,src): def add_target(self,pin):
""" """
Mark the grids that are in the pin rectangle ranges to have the target property. Mark the grids that are in the pin rectangle ranges to have the target property.
pin can be a location or a label.
""" """
(pin_layer,self.target_pin_shapes) = self.find_pin(src) (pin_layer,self.target_pin_shapes) = self.find_pin(pin)
zindex = 0 if pin_layer==self.horiz_layer_number else 1 zindex = 0 if pin_layer==self.horiz_layer_number else 1
self.target_pin_zindex = zindex self.target_pin_zindex = zindex
for shape in self.target_pin_shapes: for shape in self.target_pin_shapes:
shape_in_tracks=self.convert_pin_to_tracks(shape) pin_in_tracks=self.convert_pin_to_tracks(shape,zindex,pin)
debug.info(1,"Set target: " + str(src) + " " + str(shape_in_tracks) + " z=" + str(zindex)) debug.info(1,"Set target: " + str(pin) + " " + str(pin_in_tracks) + " z=" + str(zindex))
self.rg.set_target(shape_in_tracks[0],shape_in_tracks[1],zindex) self.rg.add_target(pin_in_tracks)
def write_obstacle(self, sref, mirr = 1, angle = math.radians(float(0)), xyShift = (0, 0)): def write_obstacle(self, sref, mirr = 1, angle = math.radians(float(0)), xyShift = (0, 0)):
""" """
@ -401,25 +397,69 @@ class router:
#debug.info(1,"Converted [ {0} , {1} ]".format(ll,ur)) #debug.info(1,"Converted [ {0} , {1} ]".format(ll,ur))
return [ll,ur] return [ll,ur]
def convert_pin_to_tracks(self,shape,round_bigger=False): def convert_pin_to_tracks(self,shape,zindex,pin):
""" """
Convert a rectangular pin shape into track units. Convert a rectangular pin shape into a list of track locations,layers.
If no on-grid pins are found, it searches for the nearest off-grid pin(s).
""" """
[ll,ur] = shape [ll,ur] = shape
ll = snap_to_grid(ll) ll = snap_to_grid(ll)
ur = snap_to_grid(ur) ur = snap_to_grid(ur)
# to scale coordinates to tracks
#debug.info(1,"Converting [ {0} , {1} ]".format(ll,ur)) #debug.info(1,"Converting [ {0} , {1} ]".format(ll,ur))
ll=ll.scale(self.track_factor)
ur=ur.scale(self.track_factor) # scale the size bigger to include neaby tracks
ll = ll.ceil() ll=ll.scale(self.track_factor).floor()
ur = ur.floor() ur=ur.scale(self.track_factor).ceil()
# width depends on which layer it is
if zindex==0:
width = self.horiz_layer_width
else:
width = self.vert_layer_width
track_list = []
# include +- 1 track for neighors
for x in range(int(ll[0])-1,int(ur[0])+1):
for y in range(int(ll[1])-1,int(ur[1])+1):
#debug.info(1,"Converting [ {0} , {1} ]".format(x,y))
# get the rectangular pin at a track location
rect = self.convert_track_to_pin(vector3d(x,y,zindex))
#debug.info(1,"Rect {0}".format(rect))
# find the rectangular overlap shape (if any)
# if dimension of overlap is greater than min width in any dimension, add it
if self.compute_max_overlap(shape,rect)>=width:
track_list.append(vector3d(x,y,zindex))
#debug.warning("Off-grid pin for {0}.".format(str(pin)))
#debug.info(1,"Converted [ {0} , {1} ]".format(ll,ur)) #debug.info(1,"Converted [ {0} , {1} ]".format(ll,ur))
return [ll,ur] return track_list
def compute_overlap(self,r1,r2):
""" Calculate the rectangular overlap of two rectangles. """
(r1_ll,r1_ur) = r1
(r2_ll,r2_ur) = r2
#ov_ur = vector(min(r1_ur.x,r2_ur.x),min(r1_ur.y,r2_ur.y))
#ov_ll = vector(max(r1_ll.x,r2_ll.x),max(r1_ll.y,r2_ll.y))
dy = min(r1_ur.y,r2_ur.y)-max(r1_ll.y,r2_ll.y)
dx = min(r1_ur.x,r2_ur.x)-max(r1_ll.x,r2_ll.x)
if dx>0 and dy>0:
return [dx,dy]
else:
return [0,0]
def convert_track_to_shape(self,track): def compute_max_overlap(self,r1,r2):
""" Compute the maximum dimension of rectangular overlap of two rectangles """
overlap=self.compute_overlap(r1,r2)
#debug.info(1,"Overlap [ {0} , {1} ] = {2}".format(r1,r2,overlap))
return max(overlap)
def convert_track_to_pin(self,track):
""" """
Convert a grid point into a rectangle shape that is centered Convert a grid point into a rectangle shape that is centered
track in the track and leaves half a DRC space in each direction. track in the track and leaves half a DRC space in each direction.