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([])
|
self.connect_inst([])
|
||||||
return route
|
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):
|
def add_wire(self, layers, coordinates, offset=None):
|
||||||
"""Connects a routing path on given layer,coordinates,width.
|
"""Connects a routing path on given layer,coordinates,width.
|
||||||
The layers are the (horizontal, via, vertical). """
|
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
|
from contact import contact
|
||||||
import math
|
import math
|
||||||
import debug
|
import debug
|
||||||
from vector import vector
|
|
||||||
import grid
|
import grid
|
||||||
|
from vector import vector
|
||||||
|
from vector3d import vector3d
|
||||||
|
|
||||||
|
|
||||||
class router:
|
class router:
|
||||||
|
|
@ -97,6 +97,7 @@ class router:
|
||||||
|
|
||||||
self.pin_shapes[str(pin)]=[]
|
self.pin_shapes[str(pin)]=[]
|
||||||
self.pin_names.append(pin_name)
|
self.pin_names.append(pin_name)
|
||||||
|
self.pin_layers[str(pin)] = pin_layer
|
||||||
|
|
||||||
for pin_shape in pin_shapes:
|
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)))
|
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])]
|
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
|
# convert the pin coordinates to tracks and round the sizes down
|
||||||
self.pin_shapes[str(pin)].append(shape)
|
self.pin_shapes[str(pin)].append(shape)
|
||||||
self.pin_layers[str(pin)] = pin_layer
|
|
||||||
self.all_pin_shapes.append(shape)
|
self.all_pin_shapes.append(shape)
|
||||||
|
|
||||||
return self.pin_shapes[str(pin)]
|
return self.pin_shapes[str(pin)]
|
||||||
|
|
@ -168,7 +168,7 @@ class router:
|
||||||
Add the current wire route to the given design instance.
|
Add the current wire route to the given design instance.
|
||||||
"""
|
"""
|
||||||
# First, simplify the path for
|
# First, simplify the path for
|
||||||
debug.info(1,str(self.path))
|
#debug.info(1,str(self.path))
|
||||||
contracted_path = self.contract_path(self.path)
|
contracted_path = self.contract_path(self.path)
|
||||||
debug.info(1,str(contracted_path))
|
debug.info(1,str(contracted_path))
|
||||||
|
|
||||||
|
|
@ -188,17 +188,17 @@ class router:
|
||||||
|
|
||||||
# convert the path back to absolute units from tracks
|
# convert the path back to absolute units from tracks
|
||||||
abs_path = map(self.convert_point_to_units,contracted_path)
|
abs_path = map(self.convert_point_to_units,contracted_path)
|
||||||
cell.add_wire(self.layers,abs_path)
|
|
||||||
debug.info(1,str(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
|
# 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
|
# offset this by 1/2 the via size
|
||||||
c=contact(self.layers, (1, 1))
|
c=contact(self.layers, (1, 1))
|
||||||
via_offset = vector(-0.5*c.width,-0.5*c.height)
|
via_offset = vector(-0.5*c.width,-0.5*c.height)
|
||||||
cell.add_via(self.layers,abs_path[0]+via_offset)
|
cell.add_via(self.layers,abs_path[0]+via_offset)
|
||||||
# Check if a via is needed at the end point
|
# 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
|
# offset this by 1/2 the via size
|
||||||
c=contact(self.layers, (1, 1))
|
c=contact(self.layers, (1, 1))
|
||||||
via_offset = vector(-0.5*c.width,-0.5*c.height)
|
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.
|
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)
|
shapes = self.find_pin(name)
|
||||||
zindex = 0 if self.pin_layers[name]==self.horiz_layer_number else 1
|
zindex = 0 if self.pin_layers[name]==self.horiz_layer_number else 1
|
||||||
|
self.source_pin_layer = zindex
|
||||||
for shape in shapes:
|
for shape in shapes:
|
||||||
shape_in_tracks=self.convert_shape_to_tracks(shape)
|
shape_in_tracks=self.convert_shape_to_tracks(shape)
|
||||||
debug.info(1,"Set source: " + str(name) + " " + str(shape_in_tracks) + " z=" + str(zindex))
|
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.
|
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)
|
shapes = self.find_pin(name)
|
||||||
zindex = 0 if self.pin_layers[name]==self.horiz_layer_number else 1
|
zindex = 0 if self.pin_layers[name]==self.horiz_layer_number else 1
|
||||||
|
self.target_pin_layer = zindex
|
||||||
for shape in shapes:
|
for shape in shapes:
|
||||||
shape_in_tracks=self.convert_shape_to_tracks(shape)
|
shape_in_tracks=self.convert_shape_to_tracks(shape)
|
||||||
debug.info(1,"Set target: " + str(name) + " " + str(shape_in_tracks) + " z=" + str(zindex))
|
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.
|
Convert a path set of tracks to center line path.
|
||||||
"""
|
"""
|
||||||
# we can ignore the layers here
|
pt = vector3d(p)
|
||||||
# add_wire will filter out duplicates
|
pt=pt.scale(self.track_widths[0],self.track_widths[1],1)
|
||||||
pt = vector(p[0],p[1])
|
|
||||||
pt=pt.scale(self.track_widths)
|
|
||||||
return pt
|
return pt
|
||||||
|
|
||||||
def convert_shape_to_tracks(self,shape,round_bigger=False):
|
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")
|
layer_stack =("metal1","via1","metal2")
|
||||||
r.route(layer_stack,src="A",dest="B")
|
r.route(layer_stack,src="A",dest="B")
|
||||||
r.add_route(self)
|
r.add_route(self)
|
||||||
self.gds_write("temp.gds")
|
|
||||||
|
|
||||||
r = routing("test1", "03_same_layer_pins_test")
|
r = routing("test1", "03_same_layer_pins_test")
|
||||||
self.local_check(r)
|
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.route(layer_stack,src="A",dest="B")
|
||||||
r.add_route(self)
|
r.add_route(self)
|
||||||
|
|
||||||
r.route(layer_stack,src="A",dest="B")
|
#r.route(layer_stack,src="C",dest="D")
|
||||||
r.add_route(self)
|
#r.add_route(self)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
r = routing("test1", "05_two_nets_test")
|
r = routing("test1", "05_two_nets_test")
|
||||||
|
r.gds_write("temp.gds")
|
||||||
self.local_check(r)
|
self.local_check(r)
|
||||||
|
|
||||||
# fails if there are any DRC errors on any cells
|
# fails if there are any DRC errors on any cells
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue