Improved router debugging and return error if unable to route.

This commit is contained in:
Matt Guthaus 2017-05-31 13:59:49 -07:00
parent 8cc63560f8
commit d31b1862a3
11 changed files with 66 additions and 122 deletions

View File

@ -40,4 +40,4 @@ class cell:
if self.min_cost > 0: if self.min_cost > 0:
return self.min_cost return self.min_cost
return "." return None

View File

@ -55,84 +55,6 @@ class grid:
while (not self.q.empty()): while (not self.q.empty()):
self.q.get(False) self.q.get(False)
def view(self):
"""
View the data as text array.
"""
#os.system('clear')
xmin=-10
xmax=10
ymin=-10
ymax=10
for v in self.map.keys():
xmin = min(xmin,v.x)
xmax = max(xmax,v.x)
ymin = min(ymin,v.y)
ymax = max(ymax,v.y)
xoffset=0
if xmin < 0:
xoffset=xmin
yoffset=0
if ymin < 0:
yoffset=ymin
v_map = {}
h_map = {}
fieldwidth = 3
for h in self.map.keys():
fieldwidth = max(fieldwidth,len(self.map[h].get_type()))
for v in self.map.keys():
fieldwidth = max(fieldwidth,len(self.map[v].get_type()))
# for x in range(width):
# for y in range(height):
# v_map[x,y]="."
# h_map[x,y]="."
# h = vector3d(x+xoffset,y+yoffset,0)
# v = vector3d(x+xoffset,y+yoffset,1)
# if (h in self.map.keys()):
# h_map[x,y] = self.map[h].get_type()
# fieldwidth = max(fieldwidth,len(h_map[x,y]))
# if (v in self.map.keys()):
# v_map[x,y] = self.map[v].get_type()
# fieldwidth = max(fieldwidth,len(v_map[x,y]))
# display lower layer
print '='*80
print '='*80
self.print_grid(0,xmin,xmax,ymin,ymax,fieldwidth)
print '='*80
self.print_grid(1,xmin,xmax,ymin,ymax,fieldwidth)
print '='*80
print '='*80
raw_input("Press Enter to continue...")
def print_grid(self,layer,xmin,xmax,ymin,ymax,fieldwidth):
"""
Display a text representation of a layer of the routing grid.
"""
print "".center(fieldwidth),
for x in range(xmin,xmax+1):
print str(x).center(fieldwidth),
print ""
for y in reversed(range(ymin,ymax+1)):
print str(y).center(fieldwidth),
for x in range(xmin,xmax+1):
n = vector3d(x,y,layer)
if n in self.map.keys():
print str(self.map[n].get_type()).center(fieldwidth),
else:
print ".".center(fieldwidth),
print ""
def add_blockage(self,ll,ur,z): def add_blockage(self,ll,ur,z):
debug.info(3,"Adding blockage ll={0} ur={1} z={2}".format(str(ll),str(ur),z)) debug.info(3,"Adding blockage ll={0} ur={1} z={2}".format(str(ll),str(ur),z))
@ -142,7 +64,6 @@ class grid:
self.add_map(n) self.add_map(n)
self.map[n].blocked=True self.map[n].blocked=True
def add_source(self,track_list): def add_source(self,track_list):
debug.info(3,"Adding source list={0}".format(str(track_list))) debug.info(3,"Adding source list={0}".format(str(track_list)))
for n in track_list: for n in track_list:
@ -175,6 +96,8 @@ class grid:
for p in self.map.values(): for p in self.map.values():
if (p.source or p.target): if (p.source or p.target):
p.blocked=True p.blocked=True
p.source=False
p.target=False
def convert_path_to_blockages(self): def convert_path_to_blockages(self):
""" """
@ -243,11 +166,9 @@ class grid:
debug.info(3,"Enqueuing: cost=" + str(current_cost) + "+" + str(target_cost) + " " + str(newpath)) debug.info(3,"Enqueuing: cost=" + str(current_cost) + "+" + str(target_cost) + " " + str(newpath))
# add the cost to get to this point if we haven't reached it yet # add the cost to get to this point if we haven't reached it yet
self.q.put((predicted_cost,newpath)) self.q.put((predicted_cost,newpath))
#self.view()
# View the unable to route result. debug.warning("Unable to route path. Expand area?")
self.view() return (None,None)
debug.error("Unable to route path. Expand area?",-1)
def is_target(self,point): def is_target(self,point):
""" """

View File

@ -154,24 +154,24 @@ class router:
self.add_target(dest) self.add_target(dest)
# View the initial route pins and blockages for debugging
#self.rg.view()
# returns the path in tracks # returns the path in tracks
(self.path,cost) = self.rg.route(cost_bound_scale) (self.path,cost) = self.rg.route(cost_bound_scale)
if self.path!=None:
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.add_path(self.path) self.add_path(self.path)
# View the final route for debugging return True
#self.rg.view()
return return False
def add_grid_map(self,cell): def add_router_info(self,cell):
""" """
Write the routing grid as the boundary layer for debugging purposes. Write the routing grid and router cost, blockage, pins on
the boundary layer for debugging purposes. This can only be
called once or the labels will overlap.
""" """
grid_keys=self.rg.map.keys() grid_keys=self.rg.map.keys()
partial_track=vector(0,self.track_width/6.0)
for g in grid_keys: for g in grid_keys:
shape = self.convert_full_track_to_shape(g) shape = self.convert_full_track_to_shape(g)
cell.add_rect(layer="boundary", cell.add_rect(layer="boundary",
@ -180,11 +180,20 @@ class router:
height=shape[1].y-shape[0].y) height=shape[1].y-shape[0].y)
t=self.rg.map[g].get_type() t=self.rg.map[g].get_type()
if (type(t)==str): if t == None: continue
cell.add_label(text=t,
# midpoint offset
off=vector((shape[1].x+shape[0].x)/2,
(shape[1].y+shape[0].y)/2)
if g[2]==1:
# Upper layer is upper right label
off+=partial_track
else:
# Lower layer is lower left label
off-=partial_track
cell.add_label(text=str(t),
layer="text", layer="text",
offset=vector((shape[1].x+shape[0].x)/2, offset=off)
(shape[1].y+shape[0].y)/2))
def add_route(self,cell): def add_route(self,cell):
@ -193,7 +202,7 @@ class router:
""" """
# For debugging... # For debugging...
self.add_grid_map(cell) #self.add_router_info(cell)
# First, simplify the path for # First, simplify the path for
#debug.info(1,str(self.path)) #debug.info(1,str(self.path))
@ -352,6 +361,8 @@ class router:
debug.check(found_pin,"Unable to find source pin on grid.") debug.check(found_pin,"Unable to find source pin on grid.")
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)):
""" """
Recursive write boundaries as blockages to the routing grid. Recursive write boundaries as blockages to the routing grid.

View File

@ -53,8 +53,10 @@ class no_blockages_test(unittest.TestCase):
self.gdsname = "{0}/{1}.gds".format(os.path.dirname(os.path.realpath(__file__)),gdsname) self.gdsname = "{0}/{1}.gds".format(os.path.dirname(os.path.realpath(__file__)),gdsname)
r=router.router(self.gdsname) r=router.router(self.gdsname)
layer_stack =("metal1","via1","metal2") layer_stack =("metal1","via1","metal2")
r.route(layer_stack,src="A",dest="B") if r.route(layer_stack,src="A",dest="B"):
r.add_route(self) r.add_route(self)
else:
self.assertTrue(False)
r = routing("test1", "01_no_blockages_test_{0}".format(OPTS.tech_name)) r = routing("test1", "01_no_blockages_test_{0}".format(OPTS.tech_name))
self.local_check(r) self.local_check(r)

View File

@ -53,8 +53,10 @@ class blockages_test(unittest.TestCase):
self.gdsname = "{0}/{1}.gds".format(os.path.dirname(os.path.realpath(__file__)),gdsname) self.gdsname = "{0}/{1}.gds".format(os.path.dirname(os.path.realpath(__file__)),gdsname)
r=router.router(self.gdsname) r=router.router(self.gdsname)
layer_stack =("metal1","via1","metal2") layer_stack =("metal1","via1","metal2")
r.route(layer_stack,src="A",dest="B") if r.route(layer_stack,src="A",dest="B"):
r.add_route(self) r.add_route(self)
else:
self.assertTrue(False)
r = routing("test1", "02_blockages_test_{0}".format(OPTS.tech_name)) r = routing("test1", "02_blockages_test_{0}".format(OPTS.tech_name))
self.local_check(r) self.local_check(r)

View File

@ -52,8 +52,10 @@ class same_layer_pins_test(unittest.TestCase):
self.gdsname = "{0}/{1}.gds".format(os.path.dirname(os.path.realpath(__file__)),gdsname) self.gdsname = "{0}/{1}.gds".format(os.path.dirname(os.path.realpath(__file__)),gdsname)
r=router.router(self.gdsname) r=router.router(self.gdsname)
layer_stack =("metal1","via1","metal2") layer_stack =("metal1","via1","metal2")
r.route(layer_stack,src="A",dest="B") if r.route(layer_stack,src="A",dest="B"):
r.add_route(self) r.add_route(self)
else:
self.assertTrue(False)
r = routing("test1", "03_same_layer_pins_test_{0}".format(OPTS.tech_name)) r = routing("test1", "03_same_layer_pins_test_{0}".format(OPTS.tech_name))
self.local_check(r) self.local_check(r)

View File

@ -54,8 +54,10 @@ class diff_layer_pins_test(unittest.TestCase):
self.gdsname = "{0}/{1}.gds".format(os.path.dirname(os.path.realpath(__file__)),gdsname) self.gdsname = "{0}/{1}.gds".format(os.path.dirname(os.path.realpath(__file__)),gdsname)
r=router.router(self.gdsname) r=router.router(self.gdsname)
layer_stack =("metal1","via1","metal2") layer_stack =("metal1","via1","metal2")
r.route(layer_stack,src="A",dest="B") if r.route(layer_stack,src="A",dest="B"):
r.add_route(self) r.add_route(self)
else:
self.assertTrue(False)
r = routing("test1", "04_diff_layer_pins_test_{0}".format(OPTS.tech_name)) r = routing("test1", "04_diff_layer_pins_test_{0}".format(OPTS.tech_name))
self.local_check(r) self.local_check(r)

View File

@ -54,13 +54,15 @@ class two_nets_test(unittest.TestCase):
self.gdsname = "{0}/{1}.gds".format(os.path.dirname(os.path.realpath(__file__)),gdsname) self.gdsname = "{0}/{1}.gds".format(os.path.dirname(os.path.realpath(__file__)),gdsname)
r=router.router(self.gdsname) r=router.router(self.gdsname)
layer_stack =("metal1","via1","metal2") layer_stack =("metal1","via1","metal2")
r.route(layer_stack,src="A",dest="B") if r.route(layer_stack,src="A",dest="B"):
r.add_route(self) r.add_route(self)
else:
self.assertTrue(False)
r.route(layer_stack,src="C",dest="D") if r.route(layer_stack,src="C",dest="D"):
r.add_route(self) r.add_route(self)
else:
debug.error("Unable to route")
r = routing("test1", "05_two_nets_test_{0}".format(OPTS.tech_name)) r = routing("test1", "05_two_nets_test_{0}".format(OPTS.tech_name))
self.local_check(r) self.local_check(r)

View File

@ -56,9 +56,11 @@ class pin_location_test(unittest.TestCase):
# these are user coordinates and layers # these are user coordinates and layers
src_pin = [[0.52, 4.099],11] src_pin = [[0.52, 4.099],11]
tgt_pin = [[3.533, 1.087],11] tgt_pin = [[3.533, 1.087],11]
r.route(layer_stack,src=src_pin,dest=tgt_pin)
#r.route(layer_stack,src="A",dest="B") #r.route(layer_stack,src="A",dest="B")
if r.route(layer_stack,src=src_pin,dest=tgt_pin):
r.add_route(self) r.add_route(self)
else:
debug.error("Unable to route")
# This only works for freepdk45 since the coordinates are hard coded # This only works for freepdk45 since the coordinates are hard coded
if OPTS.tech_name == "freepdk45": if OPTS.tech_name == "freepdk45":