diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index 554d6d36..90d710c6 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -312,7 +312,7 @@ class layout(lef.lef): position_list=coordinates, width=width) - def add_route(self, layers, coordinates): + def add_route(self, layers, coordinates, layer_widths): """Connects a routing path on given layer,coordinates,width. The layers are the (horizontal, via, vertical). add_wire assumes preferred direction routing whereas this includes layers in @@ -323,7 +323,8 @@ class layout(lef.lef): # add an instance of our path that breaks down into rectangles and contacts route.route(obj=self, layer_stack=layers, - path=coordinates) + path=coordinates, + layer_widths=layer_widths) def add_wire(self, layers, coordinates): diff --git a/compiler/base/route.py b/compiler/base/route.py index beff1a58..f8083835 100644 --- a/compiler/base/route.py +++ b/compiler/base/route.py @@ -10,15 +10,17 @@ class route(design): """ Object route (used by the router module) Add a route of minimium metal width between a set of points. + The widths are the layer widths of the layer stack. + (Vias are in numer of vias.) The wire must be completely rectilinear and the - z-dimension of the points refers to the layers (plus via) + z-dimension of the points refers to the layers. The points are the center of the wire. This can have non-preferred direction routing. """ unique_route_id = 0 - def __init__(self, obj, layer_stack, path): + def __init__(self, obj, layer_stack, path, layer_widths=[None,1,None]): name = "route_{0}".format(route.unique_route_id) route.unique_route_id += 1 design.__init__(self, name) @@ -26,6 +28,7 @@ class route(design): self.obj = obj self.layer_stack = layer_stack + self.layer_widths = layer_widths self.path = path self.setup_layers() @@ -33,16 +36,16 @@ class route(design): def setup_layers(self): - (horiz_layer, via_layer, vert_layer) = self.layer_stack - self.via_layer_name = via_layer - - self.vert_layer_name = vert_layer - self.vert_layer_width = drc["minwidth_{0}".format(vert_layer)] - - self.horiz_layer_name = horiz_layer - self.horiz_layer_width = drc["minwidth_{0}".format(horiz_layer)] + (self.horiz_layer_name, self.via_layer, self.vert_layer_name) = self.layer_stack + (self.horiz_layer_width, self.num_vias, self.vert_layer_width) = self.layer_widths + + if not self.vert_layer_width: + self.vert_layer_width = drc["minwidth_{0}".format(self.vert_layer_name)] + if not self.horiz_layer_width: + self.horiz_layer_width = drc["minwidth_{0}".format(self.horiz_layer_name)] + # offset this by 1/2 the via size - self.c=contact(self.layer_stack, (1, 1)) + self.c=contact(self.layer_stack, (self.num_vias, self.num_vias)) def create_wires(self): @@ -63,7 +66,8 @@ class route(design): #via_offset = vector(p0.x+0.5*self.c.width,p0.y+0.5*self.c.height) # offset if rotated via_offset = vector(p0.x+0.5*self.c.height,p0.y-0.5*self.c.width) - self.obj.add_via(self.layer_stack,via_offset,rotate=90) + via_size = [self.num_vias]*2 + self.obj.add_via(self.layer_stack,via_offset,size=via_size,rotate=90) elif p0.x != p1.x and p0.y != p1.y: # diagonal! debug.error("Non-changing direction!") else: @@ -79,14 +83,36 @@ class route(design): self.draw_corner_wire(plist[-1][1]) - + def get_layer_width(self, layer_zindex): + """ + Return the layer width + """ + if layer_zindex==0: + return self.horiz_layer_width + elif layer_zindex==1: + return self.vert_layer_width + else: + debug.error("Incorrect layer zindex.",-1) + + def get_layer_name(self, layer_zindex): + """ + Return the layer name + """ + if layer_zindex==0: + return self.horiz_layer_name + elif layer_zindex==1: + return self.vert_layer_name + else: + debug.error("Incorrect layer zindex.",-1) + def draw_wire(self, p0, p1): """ This draws a straight wire with layer_minwidth """ - layer_name = self.layer_stack[2*p0.z] - layer_width = drc["minwidth_{0}".format(layer_name)] + + layer_width = self.get_layer_width(p0.z) + layer_name = self.get_layer_name(p0.z) # always route left to right or bottom to top if p0.z != p1.z: @@ -120,8 +146,8 @@ class route(design): """ This function adds the corner squares since the center line convention only draws to the center of the corner.""" - layer_name = self.layer_stack[2*p0.z] - layer_width = drc["minwidth_{0}".format(layer_name)] + layer_width = self.get_layer_width(p0.z) + layer_name = self.get_layer_name(p0.z) offset = vector(p0.x-0.5*layer_width,p0.y-0.5*layer_width) self.obj.add_rect(layer=layer_name, offset=offset, diff --git a/compiler/router/router.py b/compiler/router/router.py index 1a955318..062dba5d 100644 --- a/compiler/router/router.py +++ b/compiler/router/router.py @@ -101,17 +101,15 @@ class router: vertical. """ self.layers = layers - (horiz_layer, via_layer, vert_layer) = self.layers + (self.horiz_layer_name, self.via_layer_name, self.vert_layer_name) = self.layers - self.vert_layer_name = vert_layer - self.vert_layer_width = tech.drc["minwidth_{0}".format(vert_layer)] + self.vert_layer_width = tech.drc["minwidth_{0}".format(self.vert_layer_name)] self.vert_layer_spacing = tech.drc[str(self.vert_layer_name)+"_to_"+str(self.vert_layer_name)] - self.vert_layer_number = tech.layer[vert_layer] + self.vert_layer_number = tech.layer[self.vert_layer_name] - self.horiz_layer_name = horiz_layer - self.horiz_layer_width = tech.drc["minwidth_{0}".format(horiz_layer)] + self.horiz_layer_width = tech.drc["minwidth_{0}".format(self.horiz_layer_name)] self.horiz_layer_spacing = tech.drc[str(self.horiz_layer_name)+"_to_"+str(self.horiz_layer_name)] - self.horiz_layer_number = tech.layer[horiz_layer] + self.horiz_layer_number = tech.layer[self.horiz_layer_name] # Contacted track spacing. via_connect = contact(self.layers, (1, 1)) @@ -127,7 +125,8 @@ class router: self.track_factor = [1/self.track_width] * 2 debug.info(1,"Track factor: {0}".format(self.track_factor)) - + # When we actually create the routes, make them the width of the track (minus 1/2 spacing on each side) + self.layer_widths = [self.track_width - self.horiz_layer_spacing, 1, self.track_width - self.vert_layer_spacing] def retrieve_pins(self,pin_name): """ @@ -721,13 +720,15 @@ class router: abs_path = [self.convert_point_to_units(x[0]) for x in path] debug.info(1,str(abs_path)) - # If we had a single grid route (source was equal to target) - self.add_enclosure(abs_path[0]) - # Otherwise, add teh route and final enclosure - if len(abs_path)>1: - self.cell.add_route(self.layers,abs_path) - self.add_enclosure(abs_path[-1]) - + # If it is only a square, add an enclosure to the track + if len(path)==1: + self.add_enclosure(abs_path[0]) + else: + # Otherwise, add the route which includes enclosures + self.cell.add_route(layers=self.layers, + coordinates=abs_path, + layer_widths=self.layer_widths) + def add_enclosure(self, loc): """ Add a metal enclosure that is the size of the routing grid minus a spacing on each side.