diff --git a/compiler/router/grid.py b/compiler/router/grid.py index 9b848149..050826e8 100644 --- a/compiler/router/grid.py +++ b/compiler/router/grid.py @@ -26,6 +26,7 @@ class grid: # rather than 2 vias + preferred direction (cost 5) self.VIA_COST = 2 self.NONPREFERRED_COST = 4 + self.PREFERRED_COST = 1 # list of the source/target grid coordinates self.source = [] @@ -109,14 +110,14 @@ class grid: for p in path: self.map[p].path=True - def route(self,cost_bound_factor): + def route(self,detour_scale): """ This does the A* maze routing with preferred direction routing. """ # 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. - cost_bound = cost_bound_factor*self.cost_to_target(self.source[0])*self.NONPREFERRED_COST + cost_bound = detour_scale*self.cost_to_target(self.source[0])*self.PREFERRED_COST # Make sure the queue is empty if we run another route while not self.q.empty(): @@ -159,7 +160,7 @@ class grid: # add the cost to get to this point if we haven't reached it yet self.q.put((predicted_cost,newpath)) - debug.warning("Unable to route path. Expand area?") + debug.warning("Unable to route path. Expand the detour_scale to allow detours.") return (None,None) def is_target(self,point): @@ -276,9 +277,9 @@ class grid: if p0.z != p1.z: # via cost += self.VIA_COST elif p0.x != p1.x: # horizontal - cost += self.NONPREFERRED_COST if (p0.z == 1) else 1 + cost += self.NONPREFERRED_COST if (p0.z == 1) else self.PREFERRED_COST elif p0.y != p1.y: # vertical - cost += self.NONPREFERRED_COST if (p0.z == 0) else 1 + cost += self.NONPREFERRED_COST if (p0.z == 0) else self.PREFERRED_COST else: debug.error("Non-changing direction!") diff --git a/compiler/router/router.py b/compiler/router/router.py index c1ccb270..43e5af90 100644 --- a/compiler/router/router.py +++ b/compiler/router/router.py @@ -6,7 +6,7 @@ import debug import grid from vector import vector from vector3d import vector3d - +from globals import OPTS class router: """A router class to read an obstruction map from a gds and plan a @@ -136,7 +136,7 @@ class router: self.rg.reinit() - def route(self, cell, layers, src, dest, cost_bound_scale=1): + def route(self, cell, layers, src, dest, detour_scale=2): """ Route a single source-destination net and return the simplified rectilinear path. Cost factor is how sub-optimal to explore for a feasible route. @@ -172,7 +172,7 @@ class router: # returns the path in tracks - (path,cost) = self.rg.route(cost_bound_scale) + (path,cost) = self.rg.route(detour_scale) if path: debug.info(1,"Found path: cost={0} ".format(cost)) debug.info(2,str(path)) @@ -180,6 +180,9 @@ class router: return True else: self.write_debug_gds() + # clean up so we can try a reroute + self.clear_pins() + return False @@ -187,6 +190,10 @@ class router: """ Write out a GDS file with the routing grid and search information annotated on it. """ + # Only add the debug info to the gds file if we have any debugging on. + # This is because we may reroute a wire with detours and don't want the debug information. + if OPTS.debug_level==0: return + self.add_router_info() debug.error("Writing debug_route.gds from {0} to {1}".format(self.source_pin,self.target_pin)) self.cell.gds_write("debug_route.gds") diff --git a/compiler/router/tests/08_expand_region_test.py b/compiler/router/tests/08_expand_region_test.py new file mode 100644 index 00000000..f7d3805b --- /dev/null +++ b/compiler/router/tests/08_expand_region_test.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python2.7 +"Run a regresion test the library cells for DRC" + +import unittest +from testutils import header +import sys,os +sys.path.append(os.path.join(sys.path[0],"../..")) +sys.path.append(os.path.join(sys.path[0],"..")) +import globals +import debug +import calibre + +OPTS = globals.OPTS + +class expand_region_test(unittest.TestCase): + """ + Test an infeasible route followed by a feasible route with an expanded region. + """ + + def runTest(self): + globals.init_openram("config_{0}".format(OPTS.tech_name)) + + import design + import router + + class gdscell(design.design): + """ + A generic GDS design that we can route on. + """ + def __init__(self, name): + #design.design.__init__(self, name) + debug.info(2, "Create {0} object".format(name)) + self.name = name + self.gds_file = "{0}/{1}.gds".format(os.path.dirname(os.path.realpath(__file__)),name) + self.sp_file = "{0}/{1}.sp".format(os.path.dirname(os.path.realpath(__file__)),name) + design.hierarchy_layout.layout.__init__(self, name) + design.hierarchy_spice.spice.__init__(self, name) + + class routing(design.design,unittest.TestCase): + """ + A generic GDS design that we can route on. + """ + def __init__(self, name): + design.design.__init__(self, name) + debug.info(2, "Create {0} object".format(name)) + + cell = gdscell(name) + self.add_inst(name=name, + mod=cell, + offset=[0,0]) + self.connect_inst([]) + + self.gdsname = "{0}/{1}.gds".format(os.path.dirname(os.path.realpath(__file__)),name) + r=router.router(self.gdsname) + layer_stack =("metal1","via1","metal2") + # This should be infeasible because it is blocked without a detour. + self.assertFalse(r.route(self,layer_stack,src="A",dest="B",detour_scale=1)) + # This should be feasible because we allow it to detour + self.assertTrue(r.route(self,layer_stack,src="A",dest="B",detour_scale=3)) + + r = routing("08_expand_region_test_{0}".format(OPTS.tech_name)) + self.local_check(r) + + # fails if there are any DRC errors on any cells + globals.end_openram() + + + def local_check(self, r): + tempgds = OPTS.openram_temp + "temp.gds" + r.gds_write(tempgds) + self.assertFalse(calibre.run_drc(r.name, tempgds)) + os.remove(tempgds) + + + + + +# instantiate a copy of the class to actually run the test +if __name__ == "__main__": + (OPTS, args) = globals.parse_args() + del sys.argv[1:] + header(__file__, OPTS.tech_name) + unittest.main() diff --git a/compiler/router/tests/08_expand_region_test_freepdk45.gds b/compiler/router/tests/08_expand_region_test_freepdk45.gds new file mode 100644 index 00000000..a5edcfb9 Binary files /dev/null and b/compiler/router/tests/08_expand_region_test_freepdk45.gds differ diff --git a/compiler/router/tests/08_expand_region_test_scn3me_subm.gds b/compiler/router/tests/08_expand_region_test_scn3me_subm.gds new file mode 100644 index 00000000..a2fdd02e Binary files /dev/null and b/compiler/router/tests/08_expand_region_test_scn3me_subm.gds differ