Fix multiple net routing cost reset bug.

This commit is contained in:
Matt Guthaus 2017-04-24 11:28:36 -07:00
parent 96f1eb413e
commit 388794b1e0
3 changed files with 46 additions and 39 deletions

View File

@ -14,6 +14,15 @@ class cell:
# -1 means it isn't visited yet
self.min_cost = -1
def reset(self):
"""
Reset the dynamic info about routing. The pins/blockages are not reset so
that they can be reused.
"""
self.visited=False
self.min_cost=-1
self.min_path=None
def get_type(self):
if self.blocked:
return "X"

View File

@ -45,6 +45,8 @@ class grid:
self.convert_pins_to_blockages()
self.reset_cells()
# clear source and target pins
self.source=[]
self.target=[]
@ -163,6 +165,13 @@ class grid:
self.map[n].blocked=False
self.target.append(n)
def reset_cells(self):
"""
Reset the path and costs for all the grid cells.
"""
for p in self.map.values():
p.reset()
def convert_pins_to_blockages(self):
"""
Convert all the pins to blockages and reset the pin sets.
@ -189,16 +198,15 @@ class grid:
for p in path:
self.map[p].path=True
def route(self,cost_bound=0):
def route(self,factor):
"""
This does the A* maze routing with preferred direction routing.
"""
# We set a cost bound of 2.5 x the HPWL for run-time. This can be
# We set a cost bound of the HPWL for run-time. This can be
# over-ridden if the route fails due to pruning a feasible solution.
if (cost_bound==0):
cost_bound = self.cost_to_target(self.source[0])*self.NONPREFERRED_COST
cost_bound = factor*self.cost_to_target(self.source[0])*self.NONPREFERRED_COST
# Make sure the queue is empty if we run another route
while not self.q.empty():
self.q.get()
@ -210,19 +218,18 @@ class grid:
# Keep expanding and adding to the priority queue until we are done
while not self.q.empty():
# should we keep the path in the queue as well or just the final node?
(cost,path) = self.q.get()
debug.info(2,"Queue size: size=" + str(self.q.qsize()) + " " + str(cost))
debug.info(3,"Expanding: cost=" + str(cost) + " " + str(path))
# expand the last element
neighbors = self.expand_dirs(path)
debug.info(4,"Neighbors: " + str(neighbors))
debug.info(3,"Neighbors: " + str(neighbors))
for n in neighbors:
# node is added to the map by the expand routine
newpath = path + [n]
if n not in self.map.keys():
self.map[n]=cell()
# check if we hit the target and are done
if self.is_target(n):
return (newpath,self.cost(newpath))
@ -242,6 +249,7 @@ class grid:
self.q.put((predicted_cost,newpath))
#self.view()
self.view()
debug.error("Unable to route path. Expand area?",-1)
def is_target(self,point):

View File

@ -30,9 +30,6 @@ class router:
self.pin_shapes = {}
# The corresponding layers of the above pin shapes
self.pin_layers = {}
# Used to track which shapes should not become blockages. This
# will contain all of both source and dest pin shapes in units not tracks.
self.all_pin_shapes = []
# The boundary will determine the limits to the size of the routing grid
self.boundary = self.layout.measureBoundary(self.top_name)
@ -105,16 +102,15 @@ class router:
shape=[vector(pin_shape[0],pin_shape[1]),vector(pin_shape[2],pin_shape[3])]
# convert the pin coordinates to tracks and round the sizes down
self.pin_shapes[str(pin)].append(shape)
self.all_pin_shapes.append(shape)
return self.pin_shapes[str(pin)]
def find_blockages(self):
"""
Iterate through all the layers and write the obstacles to the routing grid.
This doesn't consider whether the obstacles will be pins or not. They get reset later
if they are not actually a blockage.
"""
if len(self.pin_names)!=2:
debug.error("Must set pins before creating blockages.",-1)
for layer in self.layers:
self.write_obstacle(self.top_name)
@ -122,50 +118,46 @@ class router:
def clear_pins(self):
"""
Reset the source and destination pins to start a new routing.
Convert the source/dest to blockages.
Keep the other blockages.
Clear other pins from blockages?
Convert the source/dest pins to blockages.
Convert the routed path to blockages.
Keep the other blockages unchanged.
"""
self.pin_names = []
self.pin_shapes = {}
self.pin_layers = {}
self.all_pin_shapes = []
self.rg.reinit()
def route(self, layers, src, dest):
def route(self, layers, src, dest, cost_factor=1):
"""
Route a single source-destination net and return
the simplified rectilinear path.
the simplified rectilinear path. Cost factor is how sub-optimal to explore for a feasible route.
This is used to speed up the routing when there is not much detouring needed.
"""
# Clear the pins if we have previously routed
if (hasattr(self,'rg')):
self.num=self.num+1
self.clear_pins()
else:
self.num=0
# Set up layers and track sizes
self.set_layers(layers)
# Creat a routing grid over the entire area
# FIXME: This could be created only over the routing region,
# but this is simplest for now.
self.create_routing_grid()
# Set up layers and track sizes
self.set_layers(layers)
# Creat a routing grid over the entire area
# FIXME: This could be created only over the routing region,
# but this is simplest for now.
self.create_routing_grid()
# This will write all shapes as blockages, but setting pins will
# clear the blockage attribute
self.find_blockages()
self.set_source(src)
self.set_target(dest)
self.find_blockages()
self.rg.view()
# returns the path in tracks
(self.path,cost) = self.rg.route()
(self.path,cost) = self.rg.route(cost_factor)
debug.info(1,"Found path: cost={0} ".format(cost))
debug.info(2,str(self.path))
self.set_path(self.path)
@ -341,10 +333,8 @@ class router:
# only consider the two layers that we are routing on
if boundary.drawingLayer in [self.vert_layer_number,self.horiz_layer_number]:
zlayer = 0 if boundary.drawingLayer==self.horiz_layer_number else 1
# don't add a blockage if this shape was a pin shape
if shape not in self.all_pin_shapes:
[ll,ur]=self.convert_shape_to_tracks(shape)
self.rg.add_blockage(ll,ur,zlayer)
[ll,ur]=self.convert_shape_to_tracks(shape)
self.rg.add_blockage(ll,ur,zlayer)
# recurse given the mirror, angle, etc.