From 388794b1e0ba5a03dd78ab03edec5f3c1230a75c Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Mon, 24 Apr 2017 11:28:36 -0700 Subject: [PATCH] Fix multiple net routing cost reset bug. --- compiler/router/cell.py | 9 +++++++ compiler/router/grid.py | 26 +++++++++++++------- compiler/router/router.py | 50 ++++++++++++++++----------------------- 3 files changed, 46 insertions(+), 39 deletions(-) diff --git a/compiler/router/cell.py b/compiler/router/cell.py index e695122f..68007a84 100644 --- a/compiler/router/cell.py +++ b/compiler/router/cell.py @@ -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" diff --git a/compiler/router/grid.py b/compiler/router/grid.py index 68d543b8..8179967e 100644 --- a/compiler/router/grid.py +++ b/compiler/router/grid.py @@ -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): diff --git a/compiler/router/router.py b/compiler/router/router.py index 5ff7e4f9..75ae3753 100644 --- a/compiler/router/router.py +++ b/compiler/router/router.py @@ -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.