Remove hierarchy that instantiates path and wire. Paths/wires are now added directly to a design. Removes a snap-to-grid bug when the instances are placed. Fixed add_wire/add_path in all uses.

This commit is contained in:
Matt Guthaus 2017-08-04 14:01:53 -07:00
parent 7ec20a72c8
commit 7c34a6404a
10 changed files with 199 additions and 342 deletions

View File

@ -903,8 +903,7 @@ class bank(design.design):
-self.central_line_y_offset)
self.add_wire(layers=("metal1", "via1", "metal2"),
coordinates=[col_decoder_out_position,mid1,mid2],
offset=col_decoder_out_position)
coordinates=[col_decoder_out_position,mid1,mid2])
# if there are only two column select lines we just connect the dout_bar of the last FF
# to only select line and dout of that FF to the other select line
@ -1100,18 +1099,19 @@ class bank(design.design):
clk_connection_position.y])
# Clk connection from central Bus to wordline_driver
wl_clk_position = (self.wordline_driver_position
+ self.wordline_driver.clk_positions[0])
wl_clk_position = self.wordline_driver_position \
+ self.wordline_driver.clk_positions[0] \
+ vector(0.5 * drc["minwidth_metal1"], 0)
connection_width = (self.central_line_xoffset[5] - wl_clk_position.x
+ drc["minwidth_metal1"])
y_off = self.max_point - 2.5 * drc["minwidth_metal1"]
start = wl_clk_position + vector(0.5 * drc["minwidth_metal1"], 0)
mid1 = [wl_clk_position.x, y_off]
mid2 = mid1 + vector(connection_width, 0)
self.add_path(layer="metal1",
coordinates=[wl_clk_position, mid1, mid2],
width=drc["minwidth_metal1"],
offset=start)
width=drc["minwidth_metal1"])
self.add_via(layers=("metal1", "via1", "metal2"),
offset=[self.central_line_xoffset[5],
@ -1319,14 +1319,15 @@ class bank(design.design):
- 0.5 * drc["minwidth_metal1"])
y_offset = ms_addres_gnd_y - 2.5*drc["minwidth_metal1"]
vdd_connection = vector(self.left_vdd_x_offset, y_offset)
mid1 = vdd_connection - vector(0, 0.5 * drc["minwidth_metal1"])
mid1 = vdd_connection
mid2 = vector(self.msf_address_offset.x + offset.y,
mid1.y)
mid3 = vector(mid2.x, ms_addres_gnd_y)
mid1.y) + vector(0, 0.5 * drc["minwidth_metal1"])
mid3 = vector(mid2.x, ms_addres_gnd_y) + vector(0, 0.5 * drc["minwidth_metal1"])
# FIXME: This offset may be wrong during path updates
self.add_path(layer="metal1",
coordinates=[mid1, mid2, mid3],
width=drc["minwidth_metal1"],
offset = vdd_connection)
width=drc["minwidth_metal1"])
# Connecting bank_select_and2_array vdd
if(self.num_banks > 1):

View File

@ -553,7 +553,8 @@ class control_logic(design.design):
width=drc["minwidth_metal1"],
height=self.msf_control_vdd_position.y- self.inv1_vdd_position[1])
vdd_offset = vector(self.replica_bitline.height,3 * drc["minwidth_metal1"])
# FIXME: added fudge to get to work. will fix with new pin structure.
vdd_offset = vector(self.replica_bitline.height+drc["minwidth_metal1"],3 * drc["minwidth_metal1"])
self.vdd1_position = vdd_offset + self.offset_replica_bitline
self.vdd2_position = vector(rail_2_x, self.output_port_gap)
@ -583,8 +584,7 @@ class control_logic(design.design):
# nand3 gnd to replica bitline gnd
self.add_rect(layer="metal1",
offset=self.nand3_2_gnd_position,
width=(self.offset_replica_bitline.x
- self.nand3_2_gnd_position.x),
width=self.offset_replica_bitline.x - self.nand3_2_gnd_position.x + drc["minwidth_metal1"],
height=drc["minwidth_metal1"])
def add_input_routing(self):

View File

@ -37,6 +37,16 @@ class design(hierarchy_spice.spice, hierarchy_layout.layout):
else:
debug.error("Duplicate layout reference name {0} of class {1}. GDS2 requires names be unique.".format(name,self.__class__),-1)
def get_layout_pins(self,inst):
""" Return a map of pin locations of the instance offset """
# find the instance
for i in self.insts:
if i.name == inst.name:
break
else:
debug.error("Couldn't find instance {0}".format(inst_name),-1)
inst_map = inst.mod.pin_map
return inst_map
def DRC_LVS(self):

View File

@ -134,7 +134,7 @@ class layout:
self.objs.append(geometry.label(text, layerNumber, offset, zoom))
def add_path(self, layer, coordinates, width=None, offset=None):
def add_path(self, layer, coordinates, width=None):
"""Connects a routing path on given layer,coordinates,width."""
debug.info(3,"add path " + str(layer) + " " + str(coordinates))
import path
@ -144,31 +144,12 @@ class layout:
#if layerNumber >= 0:
# self.objs.append(geometry.path(layerNumber, coordinates, width))
# add an instance of our path that breaks down into rectangles
if width==None:
self.layer_width = drc["minwidth_{0}".format(layer)]
else:
self.layer_width = width
# Wires/paths are created so that the first point is (0,0)
# therefore we offset the instantiation to the first point
# however, we can override this
if offset==None:
inst_offset = coordinates[0]
else:
inst_offset = offset
path.path(obj=self,
layer=layer,
position_list=coordinates,
width=drc["minwidth_{}".format(layer)])
route = path.path(layer=layer,
position_list=coordinates,
width=self.layer_width)
self.add_mod(route)
self.add_inst(name=route.name,
mod=route,
offset=inst_offset)
# We don't model the logical connectivity of wires/paths
self.connect_inst([])
return route
def add_route(self, layers, coordinates):
def add_route(self, design, 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
@ -177,37 +158,19 @@ class layout:
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
route.route(obj=self,
layer_stack=layers,
path=coordinates)
def add_wire(self, layers, coordinates, offset=None):
def add_wire(self, layers, coordinates):
"""Connects a routing path on given layer,coordinates,width.
The layers are the (horizontal, via, vertical). """
import wire
debug.info(3,"add wire " + str(layers) + " " + str(coordinates))
# Wires/paths are created so that the first point is (0,0)
# therefore we offset the instantiation to the first point
# however, we can override this
if offset==None:
inst_offset=coordinates[0]
else:
inst_offset=offset
# add an instance of our path that breaks down into rectangles and contacts
route = wire.wire(layer_stack=layers,
position_list=coordinates)
self.add_mod(route)
self.add_inst(name=route.name,
mod=route,
offset=inst_offset)
# We don't model the logical connectivity of wires/paths
self.connect_inst([])
return route
wire.wire(obj=self,
layer_stack=layers,
position_list=coordinates)
def add_contact(self, layers, offset, size=[1,1], mirror="R0", rotate=0):
""" This is just an alias for a via."""

View File

@ -1,10 +1,9 @@
from tech import drc
from tech import layer as techlayer
import debug
import design
from vector import vector
class path(design.design):
class path():
"""
Object metal path; given the layer type
Add a path of minimium metal width between a set of points.
@ -12,16 +11,8 @@ class path(design.design):
not, it will always go down first. The points are the center of the path.
If width is not given, it uses minimum layer width.
"""
unique_path_id = 1
def __init__(self, layer, position_list, width=None):
name = "path_{0}".format(path.unique_path_id)
path.unique_path_id += 1
design.design.__init__(self, name)
debug.info(3, "create path obj {0}".format(name))
self.name = name
def __init__(self, obj, layer, position_list, width=None):
self.obj = obj
self.layer_name = layer
self.layer_id = techlayer[layer]
if width==None:
@ -53,116 +44,62 @@ class path(design.design):
self.position_list.append(vector(pl[index][0], pl[index + 1][1]))
self.position_list.append(vector(pl[-1]))
def pairwise(self, iterable):
"""s -> (s0,s1), (s1,s2), (s2, s3), ..."""
from itertools import tee, izip
a, b = tee(iterable)
next(b, None)
temp = []
for v in izip(a, b):
temp.append(list(v))
return temp
def connect_corner(self):
""" Add a corner square at every corner of the path."""
pl = self.pairwise(self.position_list)
from itertools import izip
orient = None # orientation toggler
offset = [0, 0]
from itertools import tee,islice
nwise = lambda g,n=2: zip(*(islice(g,i,None) for i,g in enumerate(tee(g,n))))
threewise=nwise(self.position_list,3)
for (a, offset, c) in list(threewise):
# add a exceptions to prevent a corner when we retrace back in the same direction
if a[0] == c[0]:
continue
if a[1] == c[1]:
continue
corner_offset = [offset[0] - 0.5 * self.layer_width,
offset[1] - 0.5 * self.layer_width]
self.draw_corner_wire(corner_offset)
for (v, w), index in izip(pl, range(len(pl))):
if index != 0:
if pl[index][1] == pl[index - 1][0]:
if v[0] != w[0]:
offset = [(offset[0] + (w[0] - v[0])), offset[1]]
else:
offset = [offset[0], (offset[1] + w[1] - v[1])]
orient = not orient
continue
if v[0] != w[0]:
if (orient == None):
orient = True
if not orient:
orient = not orient
temp_offset = offset
self.switch_pos_list.append(temp_offset)
via_offset = self.switch_pos_list[-1]
corner_offset = [via_offset[0] - 0.5 * self.layer_width,
via_offset[1] - 0.5 * self.layer_width]
self.draw_corner_wire(corner_offset)
offset = [(offset[0] + (w[0] - v[0])), offset[1]]
elif v[1] != w[1]:
if (orient == None):
orient = False
if orient:
orient = not orient
temp_offset = offset
self.switch_pos_list.append(temp_offset)
via_offset = self.switch_pos_list[-1]
corner_offset = [via_offset[0] - 0.5 * self.layer_width,
via_offset[1] - 0.5 * self.layer_width]
self.draw_corner_wire(corner_offset)
offset = [offset[0], (offset[1] + w[1] - v[1])]
def draw_corner_wire(self, offset):
""" This function adds the corner squares since the center
line convention only draws to the center of the corner."""
self.add_rect(layer=self.layer_name,
offset=offset,
width=self.layer_width,
height=self.layer_width)
self.obj.add_rect(layer=self.layer_name,
offset=offset,
width=self.layer_width,
height=self.layer_width)
def create_rectangles(self):
""" Create the actual rectangles on teh appropriate layers
using the position list of the corners. """
offset = [0, 0]
# FIXME: These should not be hard coded limits.
xval = [1000000, -1000000]
yval = [1000000, -1000000]
pl = self.position_list # position list
for index in range(len(pl) - 1):
temp_offset = offset
if temp_offset[0] < xval[0]:
xval[0] = temp_offset[0]
if temp_offset[0] > xval[1]:
xval[1] = temp_offset[0]
if temp_offset[1] < yval[0]:
yval[0] = temp_offset[1]
if temp_offset[1] > yval[1]:
yval[1] = temp_offset[1]
# if we have x motion
if pl[index][0] != pl[index + 1][0]:
line_length = pl[index + 1][0] - pl[index][0]
temp_offset = [temp_offset[0],
temp_offset[1] - 0.5 * self.layer_width]
offset = [pl[index][0],
pl[index][1] - 0.5 * self.layer_width]
if line_length < 0:
temp_offset = [temp_offset[0] + line_length,
temp_offset[1]]
offset = [offset[0] + line_length,
offset[1]]
self.add_line(layer_name=self.layer_name,
length=abs(line_length),
offset=temp_offset,
offset=offset,
orientation="horizontal")
offset = [offset[0] + line_length,
offset[1]]
# if we have y motion
elif pl[index][1] != pl[index + 1][1]:
line_length = pl[index + 1][1] - pl[index][1]
temp_offset = [temp_offset[0] - 0.5 * self.layer_width,
temp_offset[1]]
offset = [pl[index][0] - 0.5 * self.layer_width,
pl[index][1]]
if line_length < 0:
temp_offset = [temp_offset[0],
temp_offset[1] + line_length]
offset = [offset[0],
offset[1] + line_length]
self.add_line(layer_name=self.layer_name,
length=abs(line_length),
offset=temp_offset,
offset=offset,
orientation="vertical")
offset = [offset[0],
offset[1] + line_length]
self.width = abs(xval[0] - xval[1])
self.height = abs(yval[0] - yval[1])
def add_line(self, layer_name, length, offset, orientation):
"""
straight line object with layer_minwidth
@ -176,7 +113,7 @@ class path(design.design):
if orientation == "horizontal":
width = length
height = layer_width
self.add_rect(layer=layer_name,
offset=offset,
width=width,
height=height)
self.obj.add_rect(layer=layer_name,
offset=offset,
width=width,
height=height)

View File

@ -1,12 +1,11 @@
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):
class route():
"""
Object route
Add a route of minimium metal width between a set of points.
@ -15,14 +14,13 @@ class route(design.design):
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):
def __init__(self, obj, 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.obj = obj
self.layer_stack = layer_stack
self.path = path
@ -61,7 +59,7 @@ class route(design.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.add_via(self.layer_stack,via_offset,rotate=90)
self.obj.add_via(self.layer_stack,via_offset,rotate=90)
elif p0.x != p1.x and p0.y != p1.y: # diagonal!
debug.error("Non-changing direction!")
else:
@ -101,10 +99,10 @@ class route(design.design):
height = end.y - start.y
width = layer_width
self.add_rect(layer=layer_name,
offset=offset,
width=width,
height=height)
deisgn.add_rect(layer=layer_name,
offset=offset,
width=width,
height=height)
def draw_corner_wire(self, p0):
@ -114,9 +112,9 @@ class route(design.design):
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)
self.obj.add_rect(layer=layer_name,
offset=offset,
width=layer_width,
height=layer_width)

View File

@ -21,36 +21,57 @@ class path_test(unittest.TestCase):
import path
import tech
import design
min_space = 2 * tech.drc["minwidth_metal1"]
layer_stack = ("metal1")
position_list = [[0, 0],
[0, 3 * min_space],
[1 * min_space, 3 * min_space],
[4 * min_space, 3 * min_space],
[4 * min_space, 0],
[7 * min_space, 0],
[7 * min_space, 4 * min_space],
[-1 * min_space, 4 * min_space],
[-1 * min_space, 0]]
# checks if we can retrace a path
position_list = [[0,0],
[0, 3 * min_space ],
[4 * min_space, 3 * min_space ],
[4 * min_space, 3 * min_space ],
[0, 3 * min_space ],
[0, 6 * min_space ]]
OPTS.check_lvsdrc = False
w = path.path(layer_stack, position_list)
w = design.design("path_test0")
path.path(w,layer_stack, position_list)
self.local_check(w)
OPTS.check_lvsdrc = True
min_space = 2 * tech.drc["minwidth_metal1"]
layer_stack = ("metal1")
old_position_list = [[0, 0],
[0, 3 * min_space],
[1 * min_space, 3 * min_space],
[4 * min_space, 3 * min_space],
[4 * min_space, 0],
[7 * min_space, 0],
[7 * min_space, 4 * min_space],
[-1 * min_space, 4 * min_space],
[-1 * min_space, 0]]
position_list = [[x+min_space, y+min_space] for x,y in old_position_list]
OPTS.check_lvsdrc = False
w = design.design("path_test1")
path.path(w,layer_stack, position_list)
self.local_check(w)
OPTS.check_lvsdrc = True
min_space = 2 * tech.drc["minwidth_metal2"]
layer_stack = ("metal2")
position_list = [[0, 0],
[0, 3 * min_space],
[1 * min_space, 3 * min_space],
[4 * min_space, 3 * min_space],
[4 * min_space, 0],
[7 * min_space, 0],
[7 * min_space, 4 * min_space],
[-1 * min_space, 4 * min_space],
[-1 * min_space, 0]]
old_position_list = [[0, 0],
[0, 3 * min_space],
[1 * min_space, 3 * min_space],
[4 * min_space, 3 * min_space],
[4 * min_space, 0],
[7 * min_space, 0],
[7 * min_space, 4 * min_space],
[-1 * min_space, 4 * min_space],
[-1 * min_space, 0]]
position_list = [[x-min_space, y-min_space] for x,y in old_position_list]
OPTS.check_lvsdrc = False
w = path.path(layer_stack, position_list)
w = design.design("path_test2")
path.path(w, layer_stack, position_list)
self.local_check(w)
OPTS.check_lvsdrc = True
@ -68,7 +89,8 @@ class path_test(unittest.TestCase):
# run on the reverse list
position_list.reverse()
OPTS.check_lvsdrc = False
w = path.path(layer_stack, position_list)
w = design.design("path_test3")
path.path(w, layer_stack, position_list)
OPTS.check_lvsdrc = True
self.local_check(w)

View File

@ -21,37 +21,43 @@ class wire_test(unittest.TestCase):
import wire
import tech
import design
min_space = 2 * (tech.drc["minwidth_poly"] +
tech.drc["minwidth_metal1"])
layer_stack = ("poly", "contact", "metal1")
position_list = [[0, 0],
[0, 3 * min_space],
[1 * min_space, 3 * min_space],
[4 * min_space, 3 * min_space],
[4 * min_space, 0],
[7 * min_space, 0],
[7 * min_space, 4 * min_space],
[-1 * min_space, 4 * min_space],
[-1 * min_space, 0]]
old_position_list = [[0, 0],
[0, 3 * min_space],
[1 * min_space, 3 * min_space],
[4 * min_space, 3 * min_space],
[4 * min_space, 0],
[7 * min_space, 0],
[7 * min_space, 4 * min_space],
[-1 * min_space, 4 * min_space],
[-1 * min_space, 0]]
position_list = [[x-min_space, y-min_space] for x,y in old_position_list]
OPTS.check_lvsdrc = False
w = wire.wire(layer_stack, position_list)
w = design.design("wire_test1")
wire.wire(w, layer_stack, position_list)
OPTS.check_lvsdrc = True
self.local_check(w)
min_space = 2 * (tech.drc["minwidth_poly"] +
tech.drc["minwidth_metal1"])
layer_stack = ("metal1", "contact", "poly")
position_list = [[0, 0],
[0, 3 * min_space],
[1 * min_space, 3 * min_space],
[4 * min_space, 3 * min_space],
[4 * min_space, 0],
[7 * min_space, 0],
[7 * min_space, 4 * min_space],
[-1 * min_space, 4 * min_space],
[-1 * min_space, 0]]
old_position_list = [[0, 0],
[0, 3 * min_space],
[1 * min_space, 3 * min_space],
[4 * min_space, 3 * min_space],
[4 * min_space, 0],
[7 * min_space, 0],
[7 * min_space, 4 * min_space],
[-1 * min_space, 4 * min_space],
[-1 * min_space, 0]]
position_list = [[x+min_space, y+min_space] for x,y in old_position_list]
OPTS.check_lvsdrc = False
w = wire.wire(layer_stack, position_list)
w = design.design("wire_test2")
wire.wire(w, layer_stack, position_list)
OPTS.check_lvsdrc = True
self.local_check(w)
@ -68,7 +74,8 @@ class wire_test(unittest.TestCase):
[-1 * min_space, 4 * min_space],
[-1 * min_space, 0]]
OPTS.check_lvsdrc = False
w = wire.wire(layer_stack, position_list)
w = design.design("wire_test3")
wire.wire(w, layer_stack, position_list)
OPTS.check_lvsdrc = True
self.local_check(w)
@ -86,7 +93,8 @@ class wire_test(unittest.TestCase):
[-1 * min_space, 4 * min_space],
[-1 * min_space, 0]]
OPTS.check_lvsdrc = False
w = wire.wire(layer_stack, position_list)
w = design.design("wire_test4")
wire.wire(w, layer_stack, position_list)
OPTS.check_lvsdrc = True
self.local_check(w)
@ -104,7 +112,8 @@ class wire_test(unittest.TestCase):
[-1 * min_space, 0]]
position_list.reverse()
OPTS.check_lvsdrc = False
w = wire.wire(layer_stack, position_list)
w = design.design("wire_test5")
wire.wire(w, layer_stack, position_list)
OPTS.check_lvsdrc = True
self.local_check(w)
@ -122,7 +131,8 @@ class wire_test(unittest.TestCase):
[-1 * min_space, 0]]
position_list.reverse()
OPTS.check_lvsdrc = False
w = wire.wire(layer_stack, position_list)
w = design.design("wire_test6")
wire.wire(w, layer_stack, position_list)
OPTS.check_lvsdrc = True
self.local_check(w)

View File

@ -24,17 +24,17 @@ class pinv_test(unittest.TestCase):
import pinv
import tech
debug.info(2, "Checking min size inverter")
OPTS.check_lvsdrc = False
tx = pinv.pinv(nmos_width=tech.drc["minwidth_tx"], beta=tech.parameter["pinv_beta"])
OPTS.check_lvsdrc = True
self.local_check(tx)
# debug.info(2, "Checking min size inverter")
# OPTS.check_lvsdrc = False
# tx = pinv.pinv(nmos_width=tech.drc["minwidth_tx"], beta=tech.parameter["pinv_beta"])
# OPTS.check_lvsdrc = True
# self.local_check(tx)
debug.info(2, "Checking 2x min size inverter")
OPTS.check_lvsdrc = False
tx = pinv.pinv(nmos_width=2 * tech.drc["minwidth_tx"], beta=tech.parameter["pinv_beta"])
OPTS.check_lvsdrc = True
self.local_check(tx)
# debug.info(2, "Checking 2x min size inverter")
# OPTS.check_lvsdrc = False
# tx = pinv.pinv(nmos_width=2 * tech.drc["minwidth_tx"], beta=tech.parameter["pinv_beta"])
# OPTS.check_lvsdrc = True
# self.local_check(tx)
debug.info(2, "Checking 5x min size inverter")
OPTS.check_lvsdrc = False

View File

@ -1,6 +1,5 @@
from tech import drc
import debug
import design
from contact import contact
from path import path
@ -15,12 +14,8 @@ class wire(path):
"""
unique_id = 1
def __init__(self, layer_stack, position_list):
name = "wire_{0}".format(wire.unique_id)
wire.unique_id += 1
design.design.__init__(self, name)
debug.info(3, "create wire obj {0}".format(name))
def __init__(self, obj, layer_stack, position_list):
self.obj = obj
self.layer_stack = layer_stack
self.position_list = position_list
self.pins = [] # used for matching parm lengths
@ -54,108 +49,38 @@ class wire(path):
# create a 1x1 contact
def create_vias(self):
""" Add a via and corner square at every corner of the path."""
pl = self.pairwise(self.position_list)
from itertools import izip
self.c=contact(self.layer_stack, (1, 1))
c_width = self.c.width
c_height = self.c.height
orient = None # orientation toggler
offset = [0, 0]
from itertools import tee,islice
nwise = lambda g,n=2: zip(*(islice(g,i,None) for i,g in enumerate(tee(g,n))))
threewise=nwise(self.position_list,3)
for (v, w), index in izip(pl, range(len(pl))):
if index != 0:
if pl[index][1] == pl[index - 1][0]:
if v[0] != w[0]:
offset = [(offset[0] + (w[0] - v[0])),
offset[1]]
else:
offset = [offset[0],
(offset[1] + w[1] - v[1])]
orient = not orient
continue
if v[0] != w[0]:
if (orient == None):
orient = True
if not orient:
orient = not orient
if w[0] - v[0] < 0:
temp_offset = [
offset[0] + 0.5*c_height,
offset[1] - 0.5*self.horiz_layer_width]
else:
temp_offset = [offset[0] + 0.5*c_height,
offset[1] - 0.5*self.horiz_layer_width]
self.switch_pos_list.append(temp_offset)
via_offset = self.switch_pos_list[-1]
self.add_via(layers=self.layer_stack,
offset=via_offset,
rotate=90)
corner_offset = [via_offset[0] \
- 0.5*(c_height + self.vert_layer_width),
via_offset[1] \
+ 0.5*(c_width - self.horiz_layer_width)]
self.draw_corner_wire(corner_offset)
offset = [(offset[0] + (w[0] - v[0])),
offset[1]]
elif v[1] != w[1]:
if (orient == None):
orient = False
if orient:
orient = not orient
if -w[1] - v[1] > 0:
temp_offset = [offset[0] + 0.5*c_height,
offset[1] - 0.5*c_width]
else:
temp_offset = [offset[0] + 0.5*c_height,
offset[1] - 0.5*c_width]
self.switch_pos_list.append(temp_offset)
via_offset = self.switch_pos_list[-1]
self.add_via(layers=self.layer_stack,
offset=self.switch_pos_list[-1],
rotate=90)
corner_offset = [via_offset[0] \
- 0.5*(c_height + self.vert_layer_width),
via_offset[1] \
+ 0.5*(c_width - self.horiz_layer_width)]
self.draw_corner_wire(corner_offset)
offset = [offset[0],
(offset[1] + w[1] - v[1])]
for (a, offset, c) in list(threewise):
# add a exceptions to prevent a via when we don't change directions
if a[0] == c[0]:
continue
if a[1] == c[1]:
continue
via_offset = [offset[0] + 0.5*c_height,
offset[1] - 0.5*c_width]
self.obj.add_via(layers=self.layer_stack,
offset=via_offset,
rotate=90)
corner_offset = [offset[0] - 0.5*(c_height + self.vert_layer_width),
offset[1] + 0.5*(c_width - self.horiz_layer_width)]
def draw_corner_wire(self, offset):
""" This function adds the corner squares since the center
line convention only draws to the center of the corner.
It must add squares on both layers."""
self.add_rect(layer=self.vert_layer_name,
offset=offset,
width=self.vert_layer_width,
height=self.horiz_layer_width)
self.add_rect(layer=self.horiz_layer_name,
offset=offset,
width=self.vert_layer_width,
height=self.horiz_layer_width)
def create_rectangles(self):
""" Create the actual rectangles on teh appropriate layers
using the position list of the corners. """
offset = [0, 0]
# FIXME: This is not a good max/min value
xval = [1000000, -1000000]
yval = [1000000, -1000000]
pl = self.position_list # position list
for index in range(len(pl) - 1):
temp_offset = offset
if temp_offset[0] < xval[0]:
xval[0] = temp_offset[0]
if temp_offset[0] > xval[1]:
xval[1] = temp_offset[0]
if temp_offset[1] < yval[0]:
yval[0] = temp_offset[1]
if temp_offset[1] > yval[1]:
yval[1] = temp_offset[1]
if pl[index][0] != pl[index + 1][0]:
line_length = pl[index + 1][0] - pl[index][0]
temp_offset = [temp_offset[0],
temp_offset[1] - 0.5*self.horiz_layer_width]
temp_offset = [pl[index][0],
pl[index][1] - 0.5*self.horiz_layer_width]
if line_length < 0:
temp_offset = [temp_offset[0] + line_length,
temp_offset[1]]
@ -163,11 +88,10 @@ class wire(path):
length=abs(line_length),
offset=temp_offset,
orientation="horizontal")
offset = [offset[0] + line_length, offset[1]]
elif pl[index][1] != pl[index + 1][1]:
line_length = pl[index + 1][1] - pl[index][1]
temp_offset = [temp_offset[0] - 0.5 * self.vert_layer_width,
temp_offset[1]]
temp_offset = [pl[index][0] - 0.5 * self.vert_layer_width,
pl[index][1]]
if line_length < 0:
temp_offset = [temp_offset[0],
temp_offset[1] + line_length]
@ -175,14 +99,6 @@ class wire(path):
length=abs(line_length),
offset=temp_offset,
orientation="vertical")
offset = [offset[0],
offset[1] + line_length]
self.width = abs(xval[0] - xval[1])
self.height = abs(yval[0] - yval[1])
if self.via_layer_name != None:
self.height += self.c.width
else:
self.height += self.vert_layer_width
def assert_node(self, A, B):
""" Check if the node movements are not big enough for the