Update signal routing for new blockage and pins.

This commit is contained in:
Matt Guthaus 2018-09-05 16:01:11 -07:00
parent 7ead566154
commit 59956f1446
6 changed files with 148 additions and 121 deletions

View File

@ -713,9 +713,9 @@ class VlsiLayout:
# Convert to user units
new_boundaries = []
for pin_boundary in pin_boundaries:
new_boundaries.append([pin_boundary[0]*self.units[0],pin_boundary[1]*self.units[0],
pin_boundary[2]*self.units[0],pin_boundary[3]*self.units[0]])
new_pin_boundary = [pin_boundary[0]*self.units[0],pin_boundary[1]*self.units[0],
pin_boundary[2]*self.units[0],pin_boundary[3]*self.units[0]]
new_boundaries.append(["p"+str(coordinate)+"_"+str(layer), layer, new_pin_boundary])
return new_boundaries
def getPinShapeByLabel(self,label_name):

View File

@ -34,15 +34,15 @@ class astar_grid(grid.grid):
def add_source(self,track_list):
debug.info(2,"Adding source list={0}".format(str(track_list)))
for n in track_list:
if not self.is_blocked(n):
debug.info(3,"Adding source ={0}".format(str(n)))
self.set_source(n)
debug.info(3,"Adding source ={0}".format(str(n)))
self.set_source(n)
def add_target(self,track_list):
debug.info(2,"Adding target list={0}".format(str(track_list)))
for n in track_list:
if not self.is_blocked(n):
self.set_target(n)
debug.info(3,"Adding target ={0}".format(str(n)))
self.set_target(n)
def is_target(self,point):
"""
@ -73,18 +73,14 @@ class astar_grid(grid.grid):
We will use an A* search, so this cost must be pessimistic.
Cost so far will be the length of the path.
"""
debug.info(4,"Initializing queue.")
# uniquify the source (and target while we are at it)
self.source = list(set(self.source))
self.target = list(set(self.target))
debug.info(1,"Initializing queue.")
# Counter is used to not require data comparison in Python 3.x
# Items will be returned in order they are added during cost ties
self.counter = 0
for s in self.source:
cost = self.cost_to_target(s)
debug.info(1,"Init: cost=" + str(cost) + " " + str([s]))
debug.info(2,"Init: cost=" + str(cost) + " " + str([s]))
heappush(self.q,(cost,self.counter,[s]))
self.counter+=1

View File

@ -63,6 +63,15 @@ class grid:
for p in path:
self.map[p].path=True
def block_path(self,path):
"""
Mark the path in the routing grid as blocked.
Also unsets the path flag.
"""
for p in path:
self.map[p].path=False
self.map[p].blocked=True
def cost(self,path):
"""
The cost of the path is the length plus a penalty for the number

View File

@ -96,12 +96,13 @@ class router:
Pin can either be a label or a location,layer pair: [[x,y],layer].
"""
shape_list=self.layout.getPinShapeByLabel(str(pin_name))
shape_list=self.layout.getAllPinShapesByLabel(str(pin_name))
pin_list = []
for shape in shape_list:
(name,layer,boundary)=shape
rect = [vector(boundary[0],boundary[1]),vector(boundary[2],boundary[3])]
pin = pin_layout(pin_name, rect, layer)
debug.info(2,"Found pin {}".format(str(pin)))
pin_list.append(pin)
debug.check(len(pin_list)>0,"Did not find any pin shapes for {0}.".format(str(pin)))
@ -219,7 +220,7 @@ class router:
for pin in all_pins:
# If the blockage overlaps the pin and is on the same layer,
# it must be connected, so skip it.
if blockage==pin:
if blockage.overlaps(pin):
debug.info(1,"Removing blockage for pin {}".format(str(pin)))
break
else:
@ -288,7 +289,7 @@ class router:
If a pin has insufficent overlap, it returns the blockage list to avoid it.
"""
(ll,ur) = pin.rect
#debug.info(1,"Converting [ {0} , {1} ]".format(ll,ur))
debug.info(1,"Converting [ {0} , {1} ]".format(ll,ur))
# scale the size bigger to include neaby tracks
ll=ll.scale(self.track_factor).floor()
@ -304,31 +305,31 @@ class router:
track_list = []
block_list = []
track_area = self.track_width*self.track_width
for x in range(ll[0],ur[0]):
for y in range(ll[1],ur[1]):
#debug.info(1,"Converting [ {0} , {1} ]".format(x,y))
debug.info(1,"Converting [ {0} , {1} ]".format(x,y))
# however, if there is not enough overlap, then if there is any overlap at all,
# we need to block it to prevent routes coming in on that grid
full_rect = self.convert_track_to_shape(vector3d(x,y,zindex))
track_area = (full_rect[1].x-full_rect[0].x)*(full_rect[1].y-full_rect[0].y)
overlap_rect=self.compute_overlap(pin.rect,full_rect)
overlap_area = overlap_rect[0]*overlap_rect[1]
#debug.info(1,"Check overlap: {0} {1} max={2}".format(shape,rect,max_overlap))
debug.info(1,"Check overlap: {0} {1} max={2}".format(pin.rect,overlap_rect,overlap_area))
# Assume if more than half the area, it is occupied
overlap_ratio = overlap_area/track_area
if overlap_ratio > 0.5:
if overlap_ratio > 0.25:
track_list.append(vector3d(x,y,zindex))
# otherwise, the pin may not be accessible, so block it
elif overlap_ratio > 0:
block_list.append(vector3d(x,y,zindex))
else:
debug.info(4,"No overlap: {0} {1} max={2}".format(pin.rect,rect,max_overlap))
print("H:",x,y)
if x>38 and x<42 and y>42 and y<45:
print(pin)
print(full_rect, overlap_rect, overlap_ratio)
debug.info(4,"No overlap: {0} {1} max={2}".format(pin.rect,overlap_rect,overlap_area))
# print("H:",x,y)
# if x>38 and x<42 and y>42 and y<45:
# print(pin)
# print(full_rect, overlap_rect, overlap_ratio)
#debug.warning("Off-grid pin for {0}.".format(str(pin)))
#debug.info(1,"Converted [ {0} , {1} ]".format(ll,ur))
return (track_list,block_list)
@ -479,6 +480,74 @@ class router:
width=ur.x-ll.x,
height=ur.y-ll.y)
def add_route(self,path):
"""
Add the current wire route to the given design instance.
"""
debug.info(3,"Set path: " + str(path))
# Keep track of path for future blockages
self.paths.append(path)
# This is marked for debug
self.rg.add_path(path)
# For debugging... if the path failed to route.
if False or path==None:
self.write_debug_gds()
# First, simplify the path for
#debug.info(1,str(self.path))
contracted_path = self.contract_path(path)
debug.info(1,str(contracted_path))
# convert the path back to absolute units from tracks
abs_path = map(self.convert_point_to_units,contracted_path)
debug.info(1,str(abs_path))
self.cell.add_route(self.layers,abs_path)
def get_inertia(self,p0,p1):
"""
Sets the direction based on the previous direction we came from.
"""
# direction (index) of movement
if p0.x!=p1.x:
return 0
elif p0.y!=p1.y:
return 1
else:
# z direction
return 2
def contract_path(self,path):
"""
Remove intermediate points in a rectilinear path.
"""
newpath = [path[0]]
for i in range(1,len(path)-1):
prev_inertia=self.get_inertia(path[i-1],path[i])
next_inertia=self.get_inertia(path[i],path[i+1])
# if we switch directions, add the point, otherwise don't
if prev_inertia!=next_inertia:
newpath.append(path[i])
# always add the last path
newpath.append(path[-1])
return newpath
def add_path_blockages(self):
"""
Go through all of the past paths and add them as blockages.
This is so we don't have to write/reload the GDS.
"""
for path in self.paths:
self.rg.block_path(path)
# FIXME: This should be replaced with vector.snap_to_grid at some point

View File

@ -20,6 +20,8 @@ class signal_router(router):
"""
router.__init__(self, gds_name, module)
self.pins = {}
# all the paths we've routed so far (to supplement the blockages)
self.paths = []
@ -45,9 +47,10 @@ class signal_router(router):
"""
debug.info(1,"Running signal router from {0} to {1}...".format(src,dest))
self.cell = cell
self.source_pin_name = src
self.target_pin_name = dest
self.pins[src] = []
self.pins[dest] = []
# Clear the pins if we have previously routed
if (hasattr(self,'rg')):
self.clear_pins()
@ -61,14 +64,15 @@ class signal_router(router):
# This will get all shapes as blockages
self.find_blockages()
# Get the pin shapes
# Now add the blockages (all shapes except the pins)
self.get_pin(src)
self.get_pin(dest)
# Now add the blockages (all shapes except the src/tgt pins)
# Now add the blockages
self.add_blockages()
# Add blockages from previous paths
self.add_path_blockages()
self.add_path_blockages()
# Now add the src/tgt if they are not blocked by other shapes
self.add_pin(src,True)
@ -91,72 +95,6 @@ class signal_router(router):
return False
def add_route(self,path):
"""
Add the current wire route to the given design instance.
"""
debug.info(3,"Set path: " + str(path))
# Keep track of path for future blockages
self.paths.append(path)
# This is marked for debug
self.rg.add_path(path)
# For debugging... if the path failed to route.
if False or path==None:
self.write_debug_gds()
# First, simplify the path for
#debug.info(1,str(self.path))
contracted_path = self.contract_path(path)
debug.info(1,str(contracted_path))
# convert the path back to absolute units from tracks
abs_path = map(self.convert_point_to_units,contracted_path)
debug.info(1,str(abs_path))
self.cell.add_route(self.layers,abs_path)
def get_inertia(self,p0,p1):
"""
Sets the direction based on the previous direction we came from.
"""
# direction (index) of movement
if p0.x!=p1.x:
return 0
elif p0.y!=p1.y:
return 1
else:
# z direction
return 2
def contract_path(self,path):
"""
Remove intermediate points in a rectilinear path.
"""
newpath = [path[0]]
for i in range(1,len(path)-1):
prev_inertia=self.get_inertia(path[i-1],path[i])
next_inertia=self.get_inertia(path[i],path[i+1])
# if we switch directions, add the point, otherwise don't
if prev_inertia!=next_inertia:
newpath.append(path[i])
# always add the last path
newpath.append(path[-1])
return newpath
def add_path_blockages(self):
"""
Go through all of the past paths and add them as blockages.
This is so we don't have to write/reload the GDS.
"""
for path in self.paths:
for grid in path:
self.rg.set_blocked(grid)

View File

@ -34,10 +34,10 @@ class supply_router(router):
self.rg.reinit()
def route(self, cell, layers, vdd_name="vdd", gnd_name="gnd"):
"""
Route a single source-destination net and return
the simplified rectilinear path.
Add power supply rails and connect all pins to these rails.
"""
debug.info(1,"Running supply router on {0} and {1}...".format(vdd_name, gnd_name))
self.cell = cell
@ -61,11 +61,13 @@ class supply_router(router):
self.get_pin(vdd_name)
self.get_pin(gnd_name)
# Now add the blockages (all shapes except the src/tgt pins)
# Now add the blockages (all shapes except the pins)
self.add_blockages()
# Add blockages from previous routes
self.add_path_blockages()
#self.route_supply_rails()
#self.route_supply_pins()
# source pin will be a specific layout pin
# target pin will be the rails only
@ -84,7 +86,38 @@ class supply_router(router):
self.write_debug_gds()
return False
def route_supply_rails(self):
"""
Add supply rails for vdd and gnd alternating in both layers.
Connect cross-over points with vias.
"""
# vdd will be the even grids
# gnd will be the odd grids
pass
def route_supply_pins(self, pin):
"""
This will route all the supply pins to supply rails one at a time.
After each one, it adds the cells to the blockage list.
"""
for pin_name in self.pins.keys():
for pin in self.pins[pin_name]:
route_supply_pin(pin)
def route_supply_pin(self, pin):
"""
This will take a single pin and route it to the appropriate supply rail.
Do not allow other pins to be destinations so that everything is connected
to the rails.
"""
pass
def add_route(self,path):
"""
Add the current wire route to the given design instance.
@ -125,22 +158,4 @@ class supply_router(router):
self.rg = supply_grid.supply_grid()
##########################
# Gridded supply route functions
##########################
def create_grid(self, ll, ur):
""" Create alternating vdd/gnd lines horizontally """
self.create_horizontal_grid()
self.create_vertical_grid()
def create_horizontal_grid(self):
""" Create alternating vdd/gnd lines horizontally """
pass
def create_vertical_grid(self):
""" Create alternating vdd/gnd lines horizontally """
pass