From d31b1862a31f0f6e64013139a6b79e04afe58672 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 31 May 2017 13:59:49 -0700 Subject: [PATCH] Improved router debugging and return error if unable to route. --- compiler/router/cell.py | 2 +- compiler/router/grid.py | 87 +----------------- compiler/router/router.py | 51 ++++++---- compiler/router/tests/01_no_blockages_test.py | 6 +- compiler/router/tests/02_blockages_test.py | 8 +- .../router/tests/03_same_layer_pins_test.py | 8 +- .../router/tests/04_diff_layer_pins_test.py | 6 +- compiler/router/tests/05_two_nets_test.py | 14 +-- .../tests/05_two_nets_test_freepdk45.gds | Bin 4096 -> 4096 bytes .../tests/05_two_nets_test_scn3me_subm.gds | Bin 6144 -> 6144 bytes compiler/router/tests/06_pin_location_test.py | 6 +- 11 files changed, 66 insertions(+), 122 deletions(-) diff --git a/compiler/router/cell.py b/compiler/router/cell.py index 41ca6556..0cbb200a 100644 --- a/compiler/router/cell.py +++ b/compiler/router/cell.py @@ -40,4 +40,4 @@ class cell: if self.min_cost > 0: return self.min_cost - return "." + return None diff --git a/compiler/router/grid.py b/compiler/router/grid.py index 4f907c80..0199c5b6 100644 --- a/compiler/router/grid.py +++ b/compiler/router/grid.py @@ -54,84 +54,6 @@ class grid: # clear the queue while (not self.q.empty()): 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): @@ -142,7 +64,6 @@ class grid: self.add_map(n) self.map[n].blocked=True - def add_source(self,track_list): debug.info(3,"Adding source list={0}".format(str(track_list))) for n in track_list: @@ -175,6 +96,8 @@ class grid: for p in self.map.values(): if (p.source or p.target): p.blocked=True + p.source=False + p.target=False 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)) # add the cost to get to this point if we haven't reached it yet self.q.put((predicted_cost,newpath)) - #self.view() - # View the unable to route result. - self.view() - debug.error("Unable to route path. Expand area?",-1) + debug.warning("Unable to route path. Expand area?") + return (None,None) def is_target(self,point): """ diff --git a/compiler/router/router.py b/compiler/router/router.py index 2aafdcba..a68b51fc 100644 --- a/compiler/router/router.py +++ b/compiler/router/router.py @@ -154,24 +154,24 @@ class router: self.add_target(dest) - # View the initial route pins and blockages for debugging - #self.rg.view() - # returns the path in tracks (self.path,cost) = self.rg.route(cost_bound_scale) - debug.info(1,"Found path: cost={0} ".format(cost)) - debug.info(2,str(self.path)) - self.add_path(self.path) - # View the final route for debugging - #self.rg.view() - - return + if self.path!=None: + debug.info(1,"Found path: cost={0} ".format(cost)) + debug.info(2,str(self.path)) + self.add_path(self.path) + return True - def add_grid_map(self,cell): + return False + + 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() + partial_track=vector(0,self.track_width/6.0) for g in grid_keys: shape = self.convert_full_track_to_shape(g) cell.add_rect(layer="boundary", @@ -180,11 +180,20 @@ class router: height=shape[1].y-shape[0].y) t=self.rg.map[g].get_type() - if (type(t)==str): - cell.add_label(text=t, - layer="text", - offset=vector((shape[1].x+shape[0].x)/2, - (shape[1].y+shape[0].y)/2)) + if t == None: continue + + # 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", + offset=off) def add_route(self,cell): @@ -193,7 +202,7 @@ class router: """ # For debugging... - self.add_grid_map(cell) + #self.add_router_info(cell) # First, simplify the path for #debug.info(1,str(self.path)) @@ -330,7 +339,7 @@ class router: if (len(pin_in_tracks)>0): found_pin=True debug.info(1,"Set source: " + str(pin) + " " + str(pin_in_tracks) + " z=" + str(zindex)) self.rg.add_source(pin_in_tracks) - + debug.check(found_pin,"Unable to find source pin on grid.") def add_target(self,pin): @@ -349,8 +358,10 @@ class router: if (len(pin_in_tracks)>0): found_pin=True debug.info(1,"Set target: " + str(pin) + " " + str(pin_in_tracks) + " z=" + str(zindex)) self.rg.add_target(pin_in_tracks) - + 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)): """ diff --git a/compiler/router/tests/01_no_blockages_test.py b/compiler/router/tests/01_no_blockages_test.py index a5efebc4..978a5262 100644 --- a/compiler/router/tests/01_no_blockages_test.py +++ b/compiler/router/tests/01_no_blockages_test.py @@ -53,8 +53,10 @@ class no_blockages_test(unittest.TestCase): self.gdsname = "{0}/{1}.gds".format(os.path.dirname(os.path.realpath(__file__)),gdsname) r=router.router(self.gdsname) layer_stack =("metal1","via1","metal2") - r.route(layer_stack,src="A",dest="B") - r.add_route(self) + if r.route(layer_stack,src="A",dest="B"): + r.add_route(self) + else: + self.assertTrue(False) r = routing("test1", "01_no_blockages_test_{0}".format(OPTS.tech_name)) self.local_check(r) diff --git a/compiler/router/tests/02_blockages_test.py b/compiler/router/tests/02_blockages_test.py index 25bfd145..36f4dc3f 100644 --- a/compiler/router/tests/02_blockages_test.py +++ b/compiler/router/tests/02_blockages_test.py @@ -53,9 +53,11 @@ class blockages_test(unittest.TestCase): self.gdsname = "{0}/{1}.gds".format(os.path.dirname(os.path.realpath(__file__)),gdsname) r=router.router(self.gdsname) layer_stack =("metal1","via1","metal2") - r.route(layer_stack,src="A",dest="B") - r.add_route(self) - + if r.route(layer_stack,src="A",dest="B"): + r.add_route(self) + else: + self.assertTrue(False) + r = routing("test1", "02_blockages_test_{0}".format(OPTS.tech_name)) self.local_check(r) diff --git a/compiler/router/tests/03_same_layer_pins_test.py b/compiler/router/tests/03_same_layer_pins_test.py index fdff815a..2bf51262 100644 --- a/compiler/router/tests/03_same_layer_pins_test.py +++ b/compiler/router/tests/03_same_layer_pins_test.py @@ -52,9 +52,11 @@ class same_layer_pins_test(unittest.TestCase): self.gdsname = "{0}/{1}.gds".format(os.path.dirname(os.path.realpath(__file__)),gdsname) r=router.router(self.gdsname) layer_stack =("metal1","via1","metal2") - r.route(layer_stack,src="A",dest="B") - r.add_route(self) - + if r.route(layer_stack,src="A",dest="B"): + r.add_route(self) + else: + self.assertTrue(False) + r = routing("test1", "03_same_layer_pins_test_{0}".format(OPTS.tech_name)) self.local_check(r) diff --git a/compiler/router/tests/04_diff_layer_pins_test.py b/compiler/router/tests/04_diff_layer_pins_test.py index 6ce2f30a..6fc8da15 100644 --- a/compiler/router/tests/04_diff_layer_pins_test.py +++ b/compiler/router/tests/04_diff_layer_pins_test.py @@ -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) r=router.router(self.gdsname) layer_stack =("metal1","via1","metal2") - r.route(layer_stack,src="A",dest="B") - r.add_route(self) + if r.route(layer_stack,src="A",dest="B"): + r.add_route(self) + else: + self.assertTrue(False) r = routing("test1", "04_diff_layer_pins_test_{0}".format(OPTS.tech_name)) self.local_check(r) diff --git a/compiler/router/tests/05_two_nets_test.py b/compiler/router/tests/05_two_nets_test.py index d9120465..c306edf3 100644 --- a/compiler/router/tests/05_two_nets_test.py +++ b/compiler/router/tests/05_two_nets_test.py @@ -54,14 +54,16 @@ class two_nets_test(unittest.TestCase): self.gdsname = "{0}/{1}.gds".format(os.path.dirname(os.path.realpath(__file__)),gdsname) r=router.router(self.gdsname) layer_stack =("metal1","via1","metal2") - r.route(layer_stack,src="A",dest="B") - r.add_route(self) + if r.route(layer_stack,src="A",dest="B"): + r.add_route(self) + else: + self.assertTrue(False) - r.route(layer_stack,src="C",dest="D") - r.add_route(self) + if r.route(layer_stack,src="C",dest="D"): + r.add_route(self) + else: + debug.error("Unable to route") - - r = routing("test1", "05_two_nets_test_{0}".format(OPTS.tech_name)) self.local_check(r) diff --git a/compiler/router/tests/05_two_nets_test_freepdk45.gds b/compiler/router/tests/05_two_nets_test_freepdk45.gds index a93e92bfaf7098b6b9a33407e20d2e09d38ef40f..c585b5b82402c3b35824ad0b041a23c742245f83 100644 GIT binary patch delta 432 zcmX|*KS%;$7{(vZ`@Xv?F*T`-Ad3cx!y)Y7a>!w0EjEP|f=We1gwYlb?Pf1X&{|L; zEkQIiR#QV$H3lsP;i%N$*9Yf0{P?}^126AWik6}$ktK$4gfW46_!OSY7qSOCMIh{D zR`l`w@+;k1oXiZrF4rG0#uSX89|Q17W)Vd1wzB>`*jv!Y`Qg@nej`!Y3!6f;-T|%b zSbq|t{Ry~sbFBbY}Lmo9nQy~pf6e%S_5Jsy*e?W2|BAcRu z#Hk?q0~$rz`U8TX2*;oXUsv$yaQNJNxQBbH(Q5Q8yrPni{1l)d8M4?b6nBox6{1N+ zv!XBc+xPXK%yd5Zy4LK_lqOS%MroW3R*G|jY;EgvVzAJN5GMymh3zCRrNo%y{I-e2 z1BtL$hEI;n(VOFRPl~`4K<6BY9paq_)@ZHuu80X#m2XsMUz#Q ztvHeP!EekyTRcCrT)MuAb7=uW_Tx&j5R(0I?#Eq(*=Ngf{&KxwpRRAh)FZRk+`Pz_ zOlO8KDnq({w}`f96L%gP`yLB1W?5N8U958d6e7%$nnGR6Ag5W_&=a`u8c2F~5%Z?e R(bIU+mr&J>#~W{6`~#{vl~e!# diff --git a/compiler/router/tests/05_two_nets_test_scn3me_subm.gds b/compiler/router/tests/05_two_nets_test_scn3me_subm.gds index 03d837c6b3edfafcc08eae83332e1a889c2b7fce..e0616789ea56709fd058f81279f3cae6a4923a3e 100644 GIT binary patch delta 432 zcma)!y-EX76ohB*n%zWpFNvfu7%*U`A;upREtd6SrAsQYNULf)5v26 zEAW(a&^+8fX&nQ3I~8o4uWmoxeynXi%=d5VWfW8Y-d@I^x#62}$LSokn|n)~&6@Qz z;P?s)aI^wY&f0^)*EbL~e!05^q+fv{hkexGvRkKi116549uwMz7k0o%sD+7=tU}gQ zKu=>5x59B=SUwE7>z6 g>?&;OHe+pA(jnjckbOU3>>KvA@K3MrTG=c22MWJ;VE_OC delta 406 zcmZoLXfTLlU}IncVi`szhFS(z1_=gU25ANv20<`egh30)<6&Y;Nli;E%_(7E5MgGu zbL=$tKDPXgrOOWe1+$|Z7-U$P7$mXkm7N&(Sx|xjWQ;5W7aLo7W>IRq@#JId)|1b( zOHSU#ZZx@tU1;(WmY~UHEDn>+Sez#RV0M_igV}C!8MD)53n2ZC$!YQqCLo{5Ve&Sh z8p7&;`he=cF*>O+1TZl8Br`C8=%CLG3>;SwG)&wldGa!@h{<(a4wLPG_#dak##bsRuppfo{cPLmxtbSD1-dTb3}$>armc9Y}yoF*&qIZS@Q>o9o% WuifN(Kt858&*T(Fhs`+xQ`iA8?{cXC diff --git a/compiler/router/tests/06_pin_location_test.py b/compiler/router/tests/06_pin_location_test.py index 4ba9a81c..c44516b7 100644 --- a/compiler/router/tests/06_pin_location_test.py +++ b/compiler/router/tests/06_pin_location_test.py @@ -56,9 +56,11 @@ class pin_location_test(unittest.TestCase): # these are user coordinates and layers src_pin = [[0.52, 4.099],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.add_route(self) + if r.route(layer_stack,src=src_pin,dest=tgt_pin): + r.add_route(self) + else: + debug.error("Unable to route") # This only works for freepdk45 since the coordinates are hard coded if OPTS.tech_name == "freepdk45":