mirror of https://github.com/VLSIDA/OpenRAM.git
Created route and add_route for layer assigned wires. It will replace add_wire/wire eventually.
This commit is contained in:
parent
f51e82e75a
commit
55ed6212a1
|
|
@ -168,6 +168,24 @@ class layout:
|
|||
self.connect_inst([])
|
||||
return route
|
||||
|
||||
def add_route(self, layers, coordinates):
|
||||
"""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
|
||||
the coordinates.
|
||||
"""
|
||||
import route
|
||||
debug.info(3,"add route " + str(layers) + " " + str(coordinates))
|
||||
# add an instance of our path that breaks down into rectangles and contacts
|
||||
route = route.route(layer_stack=layers,
|
||||
path=coordinates)
|
||||
self.add_mod(route)
|
||||
self.add_inst(name=route.name,
|
||||
mod=route)
|
||||
# We don't model the logical connectivity of wires/paths
|
||||
self.connect_inst([])
|
||||
return route
|
||||
|
||||
def add_wire(self, layers, coordinates, offset=None):
|
||||
"""Connects a routing path on given layer,coordinates,width.
|
||||
The layers are the (horizontal, via, vertical). """
|
||||
|
|
|
|||
|
|
@ -0,0 +1,119 @@
|
|||
from tech import drc
|
||||
import debug
|
||||
import design
|
||||
from contact import contact
|
||||
from itertools import tee
|
||||
from vector import vector
|
||||
from vector3d import vector3d
|
||||
|
||||
class route(design.design):
|
||||
"""
|
||||
Object route
|
||||
Add a route of minimium metal width between a set of points.
|
||||
The wire must be completely rectilinear and the
|
||||
z-dimension of the points refers to the layers (plus via)
|
||||
The points are the center of the wire.
|
||||
This can have non-preferred direction routing.
|
||||
"""
|
||||
unique_route_id = 1
|
||||
|
||||
def __init__(self, layer_stack, path):
|
||||
name = "route_{0}".format(route.unique_route_id)
|
||||
route.unique_route_id += 1
|
||||
design.design.__init__(self, name)
|
||||
debug.info(3, "create route obj {0}".format(name))
|
||||
|
||||
self.layer_stack = layer_stack
|
||||
self.path = path
|
||||
|
||||
self.setup_layers()
|
||||
self.create_wires()
|
||||
|
||||
|
||||
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)]
|
||||
# offset this by 1/2 the via size
|
||||
self.c=contact(self.layer_stack, (1, 1))
|
||||
|
||||
|
||||
def create_wires(self):
|
||||
"""
|
||||
Add the wire segments of the route.
|
||||
"""
|
||||
|
||||
def pairwise(iterable):
|
||||
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
|
||||
a, b = tee(iterable)
|
||||
next(b, None)
|
||||
return zip(a, b)
|
||||
|
||||
plist = pairwise(self.path)
|
||||
for p0,p1 in plist:
|
||||
if p0.z != p1.z: # via
|
||||
via_offset = vector(p0.x-0.5*self.c.width,p0.y-0.5*self.c.height)
|
||||
self.add_via(self.layer_stack,via_offset)
|
||||
elif p0.x != p1.x and p0.y != p1.y: # diagonal!
|
||||
debug.error("Non-changing direction!")
|
||||
else:
|
||||
# this will draw an extra corner at the end but that is ok
|
||||
self.draw_corner_wire(p1)
|
||||
# draw the point to point wire
|
||||
self.draw_wire(p0,p1)
|
||||
|
||||
|
||||
|
||||
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)]
|
||||
|
||||
# always route left to right or bottom to top
|
||||
if p0.z != p1.z:
|
||||
self.error("Adding a via as a wire!")
|
||||
elif p0.x < p1.x or p0.y < p1.y:
|
||||
start = p0
|
||||
end = p1
|
||||
elif p0.x > p1.x or p0.y > p1.y:
|
||||
start = p1
|
||||
end = p0
|
||||
else:
|
||||
debug.error("Neither horizontal or vertical wire.")
|
||||
|
||||
# now determine the route geometry and offset
|
||||
if start.x != end.x: # horizontal
|
||||
offset = start + vector3d(0,-0.5*layer_width,0)
|
||||
height = layer_width
|
||||
width = end.x - start.x
|
||||
elif start.y != end.y: # vertical
|
||||
offset = start + vector3d(-0.5*layer_width,0,0)
|
||||
height = end.y - start.y
|
||||
width = layer_width
|
||||
|
||||
self.add_rect(layer=layer_name,
|
||||
offset=offset,
|
||||
width=width,
|
||||
height=height)
|
||||
|
||||
|
||||
def draw_corner_wire(self, p0):
|
||||
""" 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)]
|
||||
offset = vector(p0.x-0.5*layer_width,p0.y-0.5*layer_width)
|
||||
self.add_rect(layer=layer_name,
|
||||
offset=offset,
|
||||
width=layer_width,
|
||||
height=layer_width)
|
||||
|
||||
|
||||
|
|
@ -3,9 +3,9 @@ import tech
|
|||
from contact import contact
|
||||
import math
|
||||
import debug
|
||||
from vector import vector
|
||||
import grid
|
||||
|
||||
from vector import vector
|
||||
from vector3d import vector3d
|
||||
|
||||
|
||||
class router:
|
||||
|
|
@ -97,6 +97,7 @@ class router:
|
|||
|
||||
self.pin_shapes[str(pin)]=[]
|
||||
self.pin_names.append(pin_name)
|
||||
self.pin_layers[str(pin)] = pin_layer
|
||||
|
||||
for pin_shape in pin_shapes:
|
||||
debug.info(2,"Find pin {0} layer {1} shape {2}".format(pin_name,str(pin_layer),str(pin_shape)))
|
||||
|
|
@ -104,7 +105,6 @@ class router:
|
|||
shape=[vector(pin_shape[0],pin_shape[1]),vector(pin_shape[2],pin_shape[3])]
|
||||
# convert the pin coordinates to tracks and round the sizes down
|
||||
self.pin_shapes[str(pin)].append(shape)
|
||||
self.pin_layers[str(pin)] = pin_layer
|
||||
self.all_pin_shapes.append(shape)
|
||||
|
||||
return self.pin_shapes[str(pin)]
|
||||
|
|
@ -168,7 +168,7 @@ class router:
|
|||
Add the current wire route to the given design instance.
|
||||
"""
|
||||
# First, simplify the path for
|
||||
debug.info(1,str(self.path))
|
||||
#debug.info(1,str(self.path))
|
||||
contracted_path = self.contract_path(self.path)
|
||||
debug.info(1,str(contracted_path))
|
||||
|
||||
|
|
@ -188,17 +188,17 @@ class router:
|
|||
|
||||
# convert the path back to absolute units from tracks
|
||||
abs_path = map(self.convert_point_to_units,contracted_path)
|
||||
cell.add_wire(self.layers,abs_path)
|
||||
debug.info(1,str(abs_path))
|
||||
cell.add_route(self.layers,abs_path)
|
||||
|
||||
# Check if a via is needed at the start point
|
||||
if (contracted_path[0].z!=contracted_path[1].z):
|
||||
if (contracted_path[0].z!=self.source_pin_layer):
|
||||
# offset this by 1/2 the via size
|
||||
c=contact(self.layers, (1, 1))
|
||||
via_offset = vector(-0.5*c.width,-0.5*c.height)
|
||||
cell.add_via(self.layers,abs_path[0]+via_offset)
|
||||
# Check if a via is needed at the end point
|
||||
if (contracted_path[-1].z!=contracted_path[-2].z):
|
||||
if (contracted_path[-1].z!=self.target_pin_layer):
|
||||
# offset this by 1/2 the via size
|
||||
c=contact(self.layers, (1, 1))
|
||||
via_offset = vector(-0.5*c.width,-0.5*c.height)
|
||||
|
|
@ -294,8 +294,10 @@ class router:
|
|||
"""
|
||||
Mark the grids that are in the pin rectangle ranges to have the source property.
|
||||
"""
|
||||
self.source_pin_name = name
|
||||
shapes = self.find_pin(name)
|
||||
zindex = 0 if self.pin_layers[name]==self.horiz_layer_number else 1
|
||||
self.source_pin_layer = zindex
|
||||
for shape in shapes:
|
||||
shape_in_tracks=self.convert_shape_to_tracks(shape)
|
||||
debug.info(1,"Set source: " + str(name) + " " + str(shape_in_tracks) + " z=" + str(zindex))
|
||||
|
|
@ -306,8 +308,10 @@ class router:
|
|||
"""
|
||||
Mark the grids that are in the pin rectangle ranges to have the target property.
|
||||
"""
|
||||
self.target_pin_name = name
|
||||
shapes = self.find_pin(name)
|
||||
zindex = 0 if self.pin_layers[name]==self.horiz_layer_number else 1
|
||||
self.target_pin_layer = zindex
|
||||
for shape in shapes:
|
||||
shape_in_tracks=self.convert_shape_to_tracks(shape)
|
||||
debug.info(1,"Set target: " + str(name) + " " + str(shape_in_tracks) + " z=" + str(zindex))
|
||||
|
|
@ -353,10 +357,8 @@ class router:
|
|||
"""
|
||||
Convert a path set of tracks to center line path.
|
||||
"""
|
||||
# we can ignore the layers here
|
||||
# add_wire will filter out duplicates
|
||||
pt = vector(p[0],p[1])
|
||||
pt=pt.scale(self.track_widths)
|
||||
pt = vector3d(p)
|
||||
pt=pt.scale(self.track_widths[0],self.track_widths[1],1)
|
||||
return pt
|
||||
|
||||
def convert_shape_to_tracks(self,shape,round_bigger=False):
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ class same_layer_pins_test(unittest.TestCase):
|
|||
layer_stack =("metal1","via1","metal2")
|
||||
r.route(layer_stack,src="A",dest="B")
|
||||
r.add_route(self)
|
||||
self.gds_write("temp.gds")
|
||||
|
||||
r = routing("test1", "03_same_layer_pins_test")
|
||||
self.local_check(r)
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
|
|
@ -56,11 +56,13 @@ class two_nets_test(unittest.TestCase):
|
|||
r.route(layer_stack,src="A",dest="B")
|
||||
r.add_route(self)
|
||||
|
||||
r.route(layer_stack,src="A",dest="B")
|
||||
r.add_route(self)
|
||||
#r.route(layer_stack,src="C",dest="D")
|
||||
#r.add_route(self)
|
||||
|
||||
|
||||
|
||||
r = routing("test1", "05_two_nets_test")
|
||||
r.gds_write("temp.gds")
|
||||
self.local_check(r)
|
||||
|
||||
# fails if there are any DRC errors on any cells
|
||||
|
|
|
|||
Loading…
Reference in New Issue