Add layer width options to route object

Modify router to use track-width routes.
This commit is contained in:
Matt Guthaus 2018-09-18 14:55:36 -07:00
parent 8d2804b9cb
commit fd9ffe30d6
3 changed files with 62 additions and 34 deletions

View File

@ -312,7 +312,7 @@ class layout(lef.lef):
position_list=coordinates, position_list=coordinates,
width=width) 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 """Connects a routing path on given layer,coordinates,width. The
layers are the (horizontal, via, vertical). add_wire assumes layers are the (horizontal, via, vertical). add_wire assumes
preferred direction routing whereas this includes layers in 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 # add an instance of our path that breaks down into rectangles and contacts
route.route(obj=self, route.route(obj=self,
layer_stack=layers, layer_stack=layers,
path=coordinates) path=coordinates,
layer_widths=layer_widths)
def add_wire(self, layers, coordinates): def add_wire(self, layers, coordinates):

View File

@ -10,15 +10,17 @@ class route(design):
""" """
Object route (used by the router module) Object route (used by the router module)
Add a route of minimium metal width between a set of points. 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 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. The points are the center of the wire.
This can have non-preferred direction routing. This can have non-preferred direction routing.
""" """
unique_route_id = 0 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) name = "route_{0}".format(route.unique_route_id)
route.unique_route_id += 1 route.unique_route_id += 1
design.__init__(self, name) design.__init__(self, name)
@ -26,6 +28,7 @@ class route(design):
self.obj = obj self.obj = obj
self.layer_stack = layer_stack self.layer_stack = layer_stack
self.layer_widths = layer_widths
self.path = path self.path = path
self.setup_layers() self.setup_layers()
@ -33,16 +36,16 @@ class route(design):
def setup_layers(self): def setup_layers(self):
(horiz_layer, via_layer, vert_layer) = self.layer_stack (self.horiz_layer_name, self.via_layer, self.vert_layer_name) = self.layer_stack
self.via_layer_name = via_layer (self.horiz_layer_width, self.num_vias, self.vert_layer_width) = self.layer_widths
self.vert_layer_name = vert_layer if not self.vert_layer_width:
self.vert_layer_width = drc["minwidth_{0}".format(vert_layer)] self.vert_layer_width = drc["minwidth_{0}".format(self.vert_layer_name)]
if not self.horiz_layer_width:
self.horiz_layer_name = horiz_layer self.horiz_layer_width = drc["minwidth_{0}".format(self.horiz_layer_name)]
self.horiz_layer_width = drc["minwidth_{0}".format(horiz_layer)]
# offset this by 1/2 the via size # 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): 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) #via_offset = vector(p0.x+0.5*self.c.width,p0.y+0.5*self.c.height)
# offset if rotated # offset if rotated
via_offset = vector(p0.x+0.5*self.c.height,p0.y-0.5*self.c.width) 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! elif p0.x != p1.x and p0.y != p1.y: # diagonal!
debug.error("Non-changing direction!") debug.error("Non-changing direction!")
else: else:
@ -79,14 +83,36 @@ class route(design):
self.draw_corner_wire(plist[-1][1]) 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): def draw_wire(self, p0, p1):
""" """
This draws a straight wire with layer_minwidth 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 # always route left to right or bottom to top
if p0.z != p1.z: if p0.z != p1.z:
@ -120,8 +146,8 @@ class route(design):
""" This function adds the corner squares since the center """ This function adds the corner squares since the center
line convention only draws to the center of the corner.""" line convention only draws to the center of the corner."""
layer_name = self.layer_stack[2*p0.z] layer_width = self.get_layer_width(p0.z)
layer_width = drc["minwidth_{0}".format(layer_name)] layer_name = self.get_layer_name(p0.z)
offset = vector(p0.x-0.5*layer_width,p0.y-0.5*layer_width) offset = vector(p0.x-0.5*layer_width,p0.y-0.5*layer_width)
self.obj.add_rect(layer=layer_name, self.obj.add_rect(layer=layer_name,
offset=offset, offset=offset,

View File

@ -101,17 +101,15 @@ class router:
vertical. vertical.
""" """
self.layers = layers 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(self.vert_layer_name)]
self.vert_layer_width = tech.drc["minwidth_{0}".format(vert_layer)]
self.vert_layer_spacing = tech.drc[str(self.vert_layer_name)+"_to_"+str(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(self.horiz_layer_name)]
self.horiz_layer_width = tech.drc["minwidth_{0}".format(horiz_layer)]
self.horiz_layer_spacing = tech.drc[str(self.horiz_layer_name)+"_to_"+str(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. # Contacted track spacing.
via_connect = contact(self.layers, (1, 1)) via_connect = contact(self.layers, (1, 1))
@ -127,7 +125,8 @@ class router:
self.track_factor = [1/self.track_width] * 2 self.track_factor = [1/self.track_width] * 2
debug.info(1,"Track factor: {0}".format(self.track_factor)) 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): 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] abs_path = [self.convert_point_to_units(x[0]) for x in path]
debug.info(1,str(abs_path)) debug.info(1,str(abs_path))
# If we had a single grid route (source was equal to target) # If it is only a square, add an enclosure to the track
self.add_enclosure(abs_path[0]) if len(path)==1:
# Otherwise, add teh route and final enclosure self.add_enclosure(abs_path[0])
if len(abs_path)>1: else:
self.cell.add_route(self.layers,abs_path) # Otherwise, add the route which includes enclosures
self.add_enclosure(abs_path[-1]) self.cell.add_route(layers=self.layers,
coordinates=abs_path,
layer_widths=self.layer_widths)
def add_enclosure(self, loc): def add_enclosure(self, loc):
""" """
Add a metal enclosure that is the size of the routing grid minus a spacing on each side. Add a metal enclosure that is the size of the routing grid minus a spacing on each side.