Merge branch 'master' into router

This commit is contained in:
Matt Guthaus 2016-11-15 11:22:30 -08:00
commit d0782df9fe
20 changed files with 454 additions and 466 deletions

View File

@ -867,7 +867,7 @@ class bank(design.design):
for i in range(2):
ff_index = i + self.row_addr_size
current_dout = self.msf_address.dout_positions[ff_index]
msf_row_addr_line_position = (current_dout.rotate().scale(1,-1)
msf_row_addr_line_position = (current_dout.rotate_scale(1,-1)
+ self.msf_address_offset)
line_index = self.num_central_bus - 2 + i
@ -922,9 +922,9 @@ class bank(design.design):
elif(self.col_addr_size == 1):
ff_index = self.row_addr_size
base = self.msf_address_offset - vector(0, 0.5 * drc["minwidth_metal3"])
dout_position = (self.msf_address.dout_positions[ff_index].rotate().scale(1,-1)
dout_position = (self.msf_address.dout_positions[ff_index].rotate_scale(1,-1)
+ base)
dout_bar_position = (self.msf_address.dout_bar_positions[ff_index].rotate().scale(1,-1)
dout_bar_position = (self.msf_address.dout_bar_positions[ff_index].rotate_scale(1,-1)
+ base)
y_offset = self.msf_address_offset.y - self.msf_address.width
@ -988,7 +988,7 @@ class bank(design.design):
# addres translation should take care of the 270 degree CCW rotation
# addres translation should take care of the 270 degree CCW rotation
msf_row_addr_line_position = (self.msf_address.dout_positions[i].rotate().scale(1,-1)
msf_row_addr_line_position = (self.msf_address.dout_positions[i].rotate_scale(1,-1)
+ self.msf_address_offset
- vector(0, 0.5 * drc["minwidth_metal3"]))
connection_width = (self.central_line_xoffset[line_index] + drc["minwidth_metal2"]
@ -1008,7 +1008,7 @@ class bank(design.design):
for i in range(self.addr_size):
# Route msf address inputs
msf_din_position = (self.msf_address.din_positions[i].rotate().scale(1,-1)
msf_din_position = (self.msf_address.din_positions[i].rotate_scale(1,-1)
+ self.msf_address_offset
- vector(0, 0.5 * drc["minwidth_metal3"]))
address_position = vector(self.left_vdd_x_offset,
@ -1083,7 +1083,7 @@ class bank(design.design):
""" CLK connection from central bus to MSF address
should we move this somewhere else hard to find when modify"""
msf_address_clk_position = (self.msf_address_offset
+ self.msf_address.clk_positions[0].rotate().scale(1,-1)
+ self.msf_address.clk_positions[0].rotate_scale(1,-1)
+ vector(- 0.5 * drc["minwidth_metal1"],
2 * drc["minwidth_metal2"]))
clk_connection_position = (self.msf_address_offset

View File

@ -40,8 +40,8 @@ class contact(design.design):
self.offset_attributes(coordinate)
self.translate(coordinate)
self.height = max(obj.offset[1] + obj.height for obj in self.objs)
self.width = max(obj.offset[0] + obj.width for obj in self.objs)
self.height = max(obj.offset.y + obj.height for obj in self.objs)
self.width = max(obj.offset.x + obj.width for obj in self.objs)
def setup_layers(self):
(first_layer, via_layer, second_layer) = self.layer_stack

View File

@ -146,7 +146,7 @@ class control_logic(design.design):
# Height and width
self.height = self.logic_height + self.output_port_gap
self.width = self.offset_replica_bitline[0] + self.replica_bitline.height
self.width = self.offset_replica_bitline.x + self.replica_bitline.height
def add_routing(self):
""" Routing between modules """
@ -175,11 +175,11 @@ class control_logic(design.design):
# msf_control inputs
correct = vector(0, 0.5 * drc["minwidth_metal2"])
def translate_inputs(pt1,pt2):
return pt1 + pt2.rotate().scale(1,-1) - correct
return pt1 + pt2.rotate_scale(1,-1) - correct
# msf_control outputs
def translate_outputs(pt1,pt2):
return pt1 - correct + vector(self.msf_control.height,- pt2[0])
return pt1 - correct + vector(self.msf_control.height,- pt2.x)
# set CSS WE OE signal groups(in, out, bar)
pt1 = self.offset_msf_control
@ -197,21 +197,21 @@ class control_logic(design.design):
# clk , vdd
base = self.offset_msf_control - vector(0.5 * drc["minwidth_metal2"], 0)
msf_clk = self.msf_control.clk_positions[0].rotate().scale(1,-1)
msf_clk = self.msf_control.clk_positions[0].rotate_scale(1,-1)
self.msf_control_clk_position = base + msf_clk
msf_vdd = self.msf_control.vdd_positions[0].rotate().scale(1,-1)
msf_vdd = self.msf_control.vdd_positions[0].rotate_scale(1,-1)
self.msf_control_vdd_position = base + msf_vdd
# gnd
self.msf_control_gnd_positions = []
for gnd_offset in self.msf_control.gnd_positions:
offset = self.offset_msf_control + vector(self.msf_control.height,
- gnd_offset[0])
- gnd_offset.x)
self.msf_control_gnd_positions.append(offset - correct)
def add_1st_row(self,y_off):
# inv1 with clk as gate input.
msf_control_rotate_x = self.offset_msf_control[0] + self.msf_control.height
msf_control_rotate_x = self.offset_msf_control.x + self.msf_control.height
self.offset_inv1 = vector(msf_control_rotate_x - self.inv4.width, y_off)
self.add_inst(name="clk_inverter",
mod=self.inv4,
@ -246,7 +246,7 @@ class control_logic(design.design):
self.set_nand2_nor2_pin("nand2",[1,1])
# REPLICA BITLINE
base_x = self.nand_array_position[0] + self.NAND3.width + 3 * self.inv.width
base_x = self.nand_array_position.x + self.NAND3.width + 3 * self.inv.width
total_rail_gap = self.rail_offset_gap + self.overall_rail_2_gap
x_off = base_x + total_rail_gap + self.replica_bitline_gap
self.offset_replica_bitline = vector(x_off, y_off)
@ -284,7 +284,7 @@ class control_logic(design.design):
def add_2nd_row(self, y_off):
# Nand3_1 input: OE, clk_bar,CS output: rblk_bar
self.offset_nand3_1 = vector(self.nand_array_position[0], y_off)
self.offset_nand3_1 = vector(self.nand_array_position.x, y_off)
self.add_inst(name="NAND3_rblk_bar",
mod=self.NAND3,
offset=self.offset_nand3_1,
@ -294,7 +294,7 @@ class control_logic(design.design):
self.set_Nand3_pins(nand_name = "nand3_1",nand_scale = [0,-1])
# Nand3_2 input: WE, clk_bar,CS output: w_en_bar
self.offset_nand3_2 = vector(self.nand_array_position[0], y_off)
self.offset_nand3_2 = vector(self.nand_array_position.x, y_off)
self.add_inst(name="NAND3_w_en_bar",
mod=self.NAND3,
offset=self.offset_nand3_2,
@ -304,7 +304,7 @@ class control_logic(design.design):
self.set_Nand3_pins(nand_name = "nand3_2",nand_scale = [0,1])
# connect nand2 and nand3 to inv
nand3_to_inv_connection_height = self.NAND3.Z_position[1] - self.inv.A_position[1] + drc["minwidth_metal1"]
nand3_to_inv_connection_height = self.NAND3.Z_position.y- self.inv.A_position.y+ drc["minwidth_metal1"]
self.add_rect(layer="metal1",
offset=self.nand3_1_Z_position,
width=drc["minwidth_metal1"],
@ -315,7 +315,7 @@ class control_logic(design.design):
height=-nand3_to_inv_connection_height)
# inv_2 input: rblk_bar, output: rblk
x_off = self.nand_array_position[0] + self.NAND3.width
x_off = self.nand_array_position.x + self.NAND3.width
self.offset_inv2 = vector(x_off, y_off)
self.add_inst(name="inv_rblk",
mod=self.inv,
@ -336,7 +336,7 @@ class control_logic(design.design):
self.set_inv2345_pins(inv_name="inv3", inv_scale=[1, 1])
# BUFFER INVERTERS FOR W_EN
x_off = self.nand_array_position[0] + self.NAND3.width + self.inv.width
x_off = self.nand_array_position.x + self.NAND3.width + self.inv.width
self.offset_inv6 = vector(x_off, y_off)
self.add_inst(name="inv_w_en1",
mod=self.inv,
@ -344,7 +344,7 @@ class control_logic(design.design):
mirror="RO")
self.connect_inst(["pre_w_en", "pre_w_en1", "vdd", "gnd"])
x_off = self.nand_array_position[0] + self.NAND3.width + 2 * self.inv.width
x_off = self.nand_array_position.x + self.NAND3.width + 2 * self.inv.width
self.offset_inv7 = [x_off, y_off]
self.add_inst(name="inv_w_en2",
mod=self.inv,
@ -392,7 +392,7 @@ class control_logic(design.design):
def add_msf_control_routing(self):
# FIRST RAIL : MSF_CONTROL OUTPUT RAIL
rail1_start = vector(self.msf_control_WE_position[0],
rail1_start = vector(self.msf_control_WE_position.x,
self.output_port_gap)
for i in range(self.num_rails_1):
correct = vector((i+1) * self.rail_offset_gap, 0)
@ -401,18 +401,18 @@ class control_logic(design.design):
offset=offset,
width=drc["minwidth_metal2"],
height=self.logic_height)
self.rail_1_x_offsets.append(offset[0])
self.rail_1_x_offsets.append(offset.x)
rail2_start_x = (self.nand_array_position[0] + self.NAND3.width
rail2_start_x = (self.nand_array_position.x + self.NAND3.width
+ 3 * self.inv.width + self.rail_offset_gap)
for i in range(self.num_rails_2):
offset = [rail2_start_x + i * self.rail_offset_gap,
self.output_port_gap]
offset = vector(rail2_start_x + i * self.rail_offset_gap,
self.output_port_gap)
self.add_rect(layer="metal2",
offset=offset,
width=drc["minwidth_metal2"],
height=self.logic_height)
self.rail_2_x_offsets.append(offset[0])
self.rail_2_x_offsets.append(offset.x)
def add_1st_row_routing(self):
# First rail routing left
@ -425,7 +425,7 @@ class control_logic(design.design):
line_x_offset = self.rail_1_x_offsets[line_indices[i]]
self.add_rect(layer="metal1",
offset=offset,
width=line_x_offset - offset[0] + drc["minwidth_metal2"],
width=line_x_offset - offset.x + drc["minwidth_metal2"],
height=drc["minwidth_metal1"])
correct1 = vector(self.gap_between_rails, - self.via_shift)
correct2 = vector(self.contact_shift + drc["minwidth_metal2"],0)
@ -450,7 +450,7 @@ class control_logic(design.design):
base = vector(line_x_offset, offset[1])
self.add_rect(layer="metal1",
offset=base,
width=offset[0] - line_x_offset,
width=offset.x - line_x_offset,
height=drc["minwidth_metal1"])
self.add_via(layers=("metal1", "via1", "metal2"),
offset=base + correct1,
@ -459,18 +459,21 @@ class control_logic(design.design):
# OE_bar [Bus # 1] to nor2 B input
layer_stack = ("metal2", "via1", "metal1")
start = self.nor2_1_B_position
mid1 = [self.nor2_1_B_position[0] + 2 * drc["minwidth_metal2"], start[1]]
mid2 = [mid1[0], self.nor2_1_gnd_position[1] - 2 * drc["minwidth_metal1"]]
mid3 = [self.rail_1_x_offsets[1] + 0.5 * drc["minwidth_metal2"], mid2[1]]
end = [mid3[0], self.output_port_gap]
mid1 = vector(self.nor2_1_B_position.x+ 2 * drc["minwidth_metal2"],
start.y)
mid2 = vector(mid1.x,
self.nor2_1_gnd_position.y- 2 * drc["minwidth_metal1"])
mid3 = vector(self.rail_1_x_offsets[1] + 0.5 * drc["minwidth_metal2"],
mid2.y)
end = [mid3.x, self.output_port_gap]
self.add_wire(layer_stack, [start, mid1, mid2, mid3, end])
layer_stack = ("metal1")
start = [self.inv1_Z_position[0], self.inv1_Z_position[1] + 0.5 * drc["minwidth_metal1"]]
mid1 = [start[0] + drc["minwidth_metal2"], start[1]]
mid2 = [mid1[0], self.nand2_1_B_position
[1] + 0.5 * drc["minwidth_metal1"]]
end = [self.nand2_1_B_position[0], mid2[1]]
start = self.inv1_Z_position+ vector(0, + 0.5 * drc["minwidth_metal1"])
mid1 = start + vector(drc["minwidth_metal2"], 0)
mid2 = vector(mid1.x,
self.nand2_1_B_position.y + 0.5 * drc["minwidth_metal1"])
end = [self.nand2_1_B_position.x, mid2.y]
self.add_path(layer_stack, [start, mid1, mid2, end])
def add_2nd_row_routing(self):
@ -486,23 +489,23 @@ class control_logic(design.design):
line_x_offset = self.rail_2_x_offsets[line_indices[i]]
self.add_rect(layer="metal1",
offset=offset,
width=line_x_offset - offset[0] + drc["minwidth_metal2"],
width=line_x_offset - offset.x+ drc["minwidth_metal2"],
height=drc["minwidth_metal1"])
self.add_via(layers=("metal1", "via1", "metal2"),
offset=[line_x_offset + self.gap_between_rails,
offset[1] - self.via_shift],
offset.y- self.via_shift],
rotate=90)
# Replica bitline (rblk to replica bitline input)
layer_stack = ("metal2", "via1", "metal1")
start = [self.rail_2_x_offsets[1] + 0.5 * drc["minwidth_metal2"],
self.output_port_gap]
mid1 = [start[0], 0.5 * drc["minwidth_metal1"]]
end = [self.replica_en_offset[0], mid1[1]]
start = vector(self.rail_2_x_offsets[1] + 0.5 * drc["minwidth_metal2"],
self.output_port_gap)
mid1 = vector(start.x, 0.5 * drc["minwidth_metal1"])
end = vector(self.replica_en_offset.x, mid1.y)
self.add_wire(layer_stack, [start, mid1, end])
height = self.replica_en_offset[1] - end[1] + 0.5 * drc["minwidth_metal1"]
height = self.replica_en_offset.y- end.y+ 0.5 * drc["minwidth_metal1"]
self.add_rect(layer="metal1",
offset=end - vector([0.5 * drc["minwidth_metal1"]] * 2),
@ -514,7 +517,7 @@ class control_logic(design.design):
end = self.replica_out_offset - vector(0.5 * drc["minwidth_metal1"],0)
self.add_rect(layer="metal3",
offset=start,
width=self.replica_out_offset[0] - self.rail_2_x_offsets[2],
width=self.replica_out_offset.x- self.rail_2_x_offsets[2],
height=drc["minwidth_metal3"])
self.add_via(layers=("metal2", "via2", "metal3"),
offset=start)
@ -536,7 +539,7 @@ class control_logic(design.design):
self.add_rect(layer="metal1",
offset=self.nand3_2_vdd_position,
width=(rail_2_x + drc["minwidth_metal2"]
- self.nand3_2_vdd_position[0]),
- self.nand3_2_vdd_position.x),
height=drc["minwidth_metal1"])
# Connection in horizontal metal2 vdd rail
@ -551,10 +554,10 @@ class control_logic(design.design):
# Connection of msf_vdd to inv1 vdd
self.add_rect(layer="metal1",
offset=[self.msf_control_vdd_position[0],
offset=[self.msf_control_vdd_position.x,
self.inv1_vdd_position[1]],
width=drc["minwidth_metal1"],
height=self.msf_control_vdd_position[1] - self.inv1_vdd_position[1])
height=self.msf_control_vdd_position.y- self.inv1_vdd_position[1])
vdd_offset = vector(self.replica_bitline.height,3 * drc["minwidth_metal1"])
@ -569,25 +572,25 @@ class control_logic(design.design):
for gnd_offset in self.msf_control_gnd_positions:
self.add_rect(layer="metal2",
offset=gnd_offset,
width=(self.rail_1_x_offsets[0] - gnd_offset[0]
width=(self.rail_1_x_offsets[0] - gnd_offset.x
+ drc["minwidth_metal2"]),
height=drc["minwidth_metal2"])
# Connect msf_control gnd to nand3 gnd
self.add_rect(layer="metal1",
offset=self.nor2_1_gnd_position,
width=self.offset_replica_bitline[0],
width=self.offset_replica_bitline.x,
height=drc["minwidth_metal1"])
self.add_via(layers=("metal1", "via1", "metal2"),
offset=[self.rail_1_x_offsets[0] + self.gap_between_rails,
self.nor2_1_gnd_position[1] - self.via_shift],
self.nor2_1_gnd_position.y- self.via_shift],
rotate=90)
# nand3 gnd to replica bitline gnd
self.add_rect(layer="metal1",
offset=self.nand3_2_gnd_position,
width=(self.offset_replica_bitline[0]
- self.nand3_2_gnd_position[0]),
width=(self.offset_replica_bitline.x
- self.nand3_2_gnd_position.x),
height=drc["minwidth_metal1"])
def add_input_routing(self):
@ -598,13 +601,13 @@ class control_logic(design.design):
self.OEb_position = self.msf_control_OEb_position
# Clk
clk_y = self.inv1_vdd_position[1] + 6 * drc["minwidth_metal1"]
clk_y = self.inv1_vdd_position.y+ 6 * drc["minwidth_metal1"]
self.clk_position = vector(0, clk_y)
# clk port to inv1 A
layer_stack = ("metal2", "via1", "metal1")
start = self.inv1_A_position + vector(0, 0.5 * drc["minwidth_metal1"])
mid1 = vector(self.inv1_A_position[0] - 2 * drc["minwidth_metal2"],
mid1 = vector(self.inv1_A_position.x- 2 * drc["minwidth_metal2"],
start.y)
mid2 = vector(mid1.x, clk_y)
self.clk_position = vector(0, mid2[1])
@ -614,17 +617,17 @@ class control_logic(design.design):
# clk line to msf_control_clk
self.add_rect(layer="metal1",
offset=[self.msf_control_clk_position[0],
offset=[self.msf_control_clk_position.x,
self.clk_position[1]],
width=drc["minwidth_metal1"],
height=(self.msf_control_clk_position[1]
height=(self.msf_control_clk_position.y
- self.clk_position[1]))
# clk connection to nor2 A input
start = [self.inv1_A_position[0] - 2 * drc["minwidth_metal2"],
self.inv1_A_position[1] + 0.5 * drc["minwidth_metal1"]]
mid1 = [start[0] - 3 * drc["minwidth_metal2"], start[1]]
mid2 = [mid1[0], self.nor2_1_A_position[1]]
start = self.inv1_A_position + vector(- 2 * drc["minwidth_metal2"],
0.5 * drc["minwidth_metal1"])
mid1 = start - vector(3 * drc["minwidth_metal2"], 0)
mid2 = [mid1.x, self.nor2_1_A_position.y]
self.add_path("metal1", [start, mid1, mid2, self.nor2_1_A_position])
@ -661,7 +664,7 @@ class control_logic(design.design):
height=self.nor2_1_Z_position.y + correct.y)
self.add_via(layers=("metal2", "via2", "metal3"),
offset=self.nor2_1_Z_position.scale(1, 0))
self.tri_en_position = vector(self.nor2_1_Z_position[0], 0)
self.tri_en_position = vector(self.nor2_1_Z_position.x, 0)
# tri_en_bar
correct = vector(drc["minwidth_metal2"], 0)
@ -671,7 +674,7 @@ class control_logic(design.design):
self.add_rect(layer="metal2",
offset=self.tri_en_bar_position,
width=drc["minwidth_metal2"],
height=self.nand2_1_Z_position[1] + drc["minwidth_metal1"])
height=self.nand2_1_Z_position.y+ drc["minwidth_metal1"])
self.add_via(layers=("metal2", "via2", "metal3"),
offset=self.tri_en_bar_position)
@ -691,6 +694,6 @@ class control_logic(design.design):
self.add_rect(layer="metal2",
offset=self.s_en_position,
width=drc["minwidth_metal2"],
height=self.inv4_Z_position[1] + drc["minwidth_metal1"])
height=self.inv4_Z_position.y+ drc["minwidth_metal1"])
self.add_via(layers=("metal2", "via2", "metal3"),
offset=self.s_en_position)

View File

@ -5,6 +5,7 @@ This provides a set of useful generic types for the gdsMill interface.
import tech
import debug
from utils import snap_to_grid
from vector import vector
class geometry:
"""
@ -37,7 +38,7 @@ class instance(geometry):
self.mod = mod
self.gds = mod.gds
self.rotate = rotate
self.offset = snap_to_grid(offset)
self.offset = vector(snap_to_grid(offset))
self.mirror = mirror
@ -104,7 +105,7 @@ class label(geometry):
self.name = "label"
self.text = text
self.layerNumber = layerNumber
self.offset = snap_to_grid(offset)
self.offset = vector(snap_to_grid(offset))
self.zoom = zoom
self.size = 0
@ -134,7 +135,7 @@ class rectangle(geometry):
geometry.__init__(self)
self.name = "rect"
self.layerNumber = layerNumber
self.offset = snap_to_grid(offset)
self.offset = vector(snap_to_grid(offset))
self.size = snap_to_grid([width, height])
self.width = self.size[0]
self.height = self.size[1]

View File

@ -329,7 +329,7 @@ class hierarchical_decoder(design.design):
# ADDING LABELS FOR OUTPUT SIDE OF THE 3:8 PRE-DECODER
for inv_3x8 in range(8):
if (self.num_inputs == 3):
xoffset = self.pre3_8.x_off_inv_2 + self.inv.Z_position[0]
xoffset = self.pre3_8.x_off_inv_2 + self.inv.Z_position.x
else:
xoffset = 0
@ -403,7 +403,7 @@ class hierarchical_decoder(design.design):
mirror=mirror)
self.add_rect(layer="metal1",
offset=[nand.width - correct,
y_off + y_dir * (nand.Z_position[1]-correct)],
y_off + y_dir * (nand.Z_position.y-correct)],
width=drc["minwidth_metal1"],
height=y_dir * drc["minwidth_metal1"])
@ -454,9 +454,9 @@ class hierarchical_decoder(design.design):
# add output label for Row Decoder INVERTER array.
if (self.num_inputs == 4 or self.num_inputs == 5):
x_off = self.nand2.width + self.inv.Z_position[0]
x_off = self.nand2.width + self.inv.Z_position.x
else:
x_off = self.nand3.width + self.inv.Z_position[0]
x_off = self.nand3.width + self.inv.Z_position.x
for row in range(self.rows):
if ((row % 2) == 0):
@ -502,10 +502,10 @@ class hierarchical_decoder(design.design):
+ inv_2x4 * (self.inv.height))
if (inv_2x4 % 2 == 0):
pin_y = self.inv.Z_position[1]
pin_y = self.inv.Z_position.y
else:
pin_y = (self.inv.height - drc["minwidth_metal1"]
- self.inv.Z_position[1])
- self.inv.Z_position.y)
yoffset = current_inv_height + pin_y
self.add_extend_rails(yoffset = yoffset,
@ -519,10 +519,10 @@ class hierarchical_decoder(design.design):
+ self.no_of_pre2x4 * self.pre2_4.height
if (inv_3x8 % 2 == 0):
pin_y = self.inv.Z_position[1]
pin_y = self.inv.Z_position.y
else:
pin_y = (self.inv.height - drc["minwidth_metal1"]
- self.inv.Z_position[1])
- self.inv.Z_position.y)
yoffset = current_inv_height + pin_y
self.add_extend_rails(yoffset = yoffset,
@ -545,13 +545,13 @@ class hierarchical_decoder(design.design):
current_inv_height = self.predecoder_height + row_index * (self.inv.height)
if (row_index % 2 == 0):
yoffset_A = current_inv_height + self.nand2.A_position[1]
yoffset_B = current_inv_height + self.nand2.B_position[1]
yoffset_A = current_inv_height + self.nand2.A_position.y
yoffset_B = current_inv_height + self.nand2.B_position.y
else:
base = current_inv_height + self.inv.height - drc["minwidth_metal1"]
yoffset_A = base - self.nand2.A_position[1]
yoffset_B = base - self.nand2.B_position[1]
yoffset_A = base - self.nand2.A_position.y
yoffset_B = base - self.nand2.B_position.y
row_index = row_index + 1
self.add_extend_rails(yoffset =yoffset_A,
@ -567,15 +567,15 @@ class hierarchical_decoder(design.design):
current_inv_height = self.predecoder_height + row_index * (self.inv.height)
if (row_index % 2 == 0):
yoffset_A = current_inv_height + self.nand3.A_position[1]
yoffset_B = current_inv_height + self.nand3.B_position[1]
yoffset_C = current_inv_height + self.nand3.C_position[1]
yoffset_A = current_inv_height + self.nand3.A_position.y
yoffset_B = current_inv_height + self.nand3.B_position.y
yoffset_C = current_inv_height + self.nand3.C_position.y
contact_C_yoffset = yoffset_C - self.contact_shift
else:
base = current_inv_height + self.inv.height - drc["minwidth_metal1"]
yoffset_A = base - self.nand3.A_position[1]
yoffset_B = base - self.nand3.B_position[1]
yoffset_C = base - self.nand3.C_position[1]
yoffset_A = base - self.nand3.A_position.y
yoffset_B = base - self.nand3.B_position.y
yoffset_C = base - self.nand3.C_position.y
contact_C_yoffset = yoffset_C
row_index = row_index + 1

View File

@ -150,12 +150,12 @@ class hierarchical_predecode(design.design):
y_off = nand_input * (self.nand.height)
mirror = "R0"
offset = [self.x_off_nand + self.nand.width,
y_off + self.nand.Z_position[1]]
y_off + self.nand.Z_position.y]
else:
y_off = (nand_input + 1) * (self.nand.height)
mirror = "MX"
offset =[self.x_off_nand + self.nand.width,
y_off - self.nand.Z_position[1] - drc["minwidth_metal1"]]
y_off - self.nand.Z_position.y - drc["minwidth_metal1"]]
self.add_inst(name=name,
mod=self.nand,
offset=[self.x_off_nand, y_off],
@ -175,22 +175,22 @@ class hierarchical_predecode(design.design):
def route_input_inverters_input(self,inv_rout,inv_in_offset):
self.add_rect(layer="metal1",
offset=[self.rails_x_offset[inv_rout],
inv_in_offset[1]],
width=inv_in_offset[0] - self.rails_x_offset[inv_rout] + drc["minwidth_metal2"],
inv_in_offset.y],
width=inv_in_offset.x - self.rails_x_offset[inv_rout] + drc["minwidth_metal2"],
height=drc["minwidth_metal1"])
self.add_via(layers=("metal1", "via1", "metal2"),
offset=[self.rails_x_offset[inv_rout] + self.gap_between_rails,
inv_in_offset[1] - self.via_shift],
inv_in_offset.y - self.via_shift],
rotate=90)
def route_input_inverters_vdd(self,inv_vdd_offset):
self.add_rect(layer="metal1",
offset=inv_vdd_offset,
width=self.rails_x_offset[self.number_of_inputs] - inv_vdd_offset[0] + drc["minwidth_metal2"],
width=self.rails_x_offset[self.number_of_inputs] - inv_vdd_offset.x + drc["minwidth_metal2"],
height=drc["minwidth_metal1"])
def route_input_inverters_gnd(self,inv_gnd_offset):
self.add_rect(layer="metal1",
offset=inv_gnd_offset,
width=self.rails_x_offset[self.number_of_inputs+1] - inv_gnd_offset[0] + drc["minwidth_metal2"],
width=self.rails_x_offset[self.number_of_inputs+1] - inv_gnd_offset.x + drc["minwidth_metal2"],
height=drc["minwidth_metal1"])

View File

@ -65,22 +65,22 @@ class hierarchical_predecode2x4(hierarchical_predecode):
inv_in_offset = base + self.inv.A_position.scale(1,y_dir)
inv_vdd_offset = base + self.inv.vdd_position.scale(1,y_dir)
inv_gnd_offset = base + self.inv.gnd_position.scale(1,y_dir)
out_y_mirrored = inv_vdd_offset[1] + output_shift + drc["minwidth_metal1"]
out_offset = [inv_out_offset[0],
inv_out_offset[1] * (1 + y_dir) / 2
out_y_mirrored = inv_vdd_offset.y+ output_shift + drc["minwidth_metal1"]
out_offset = [inv_out_offset.x,
inv_out_offset.y* (1 + y_dir) / 2
+ out_y_mirrored * (1 - y_dir) / 2]
# output connection
correct = y_dir * (output_shift + drc["minwidth_metal1"])
off_via = [self.rails_x_offset[inv_rout + 4] + self.gap_between_rails,
inv_vdd_offset[1] - self.via_shift - correct]
inv_vdd_offset.y- self.via_shift - correct]
self.add_rect(layer="metal1",
offset=out_offset,
width=drc["minwidth_metal1"],
height=(inv_vdd_offset[1] - inv_out_offset[1]) * y_dir - output_shift)
height=(inv_vdd_offset.y- inv_out_offset.y) * y_dir - output_shift)
self.add_rect(layer="metal1",
offset=[inv_out_offset[0],
inv_vdd_offset[1] - correct],
width=self.rails_x_offset[inv_rout + 4] - inv_out_offset[0] + drc["minwidth_metal2"],
offset=[inv_out_offset.x,
inv_vdd_offset.y- correct],
width=self.rails_x_offset[inv_rout + 4] - inv_out_offset.x+ drc["minwidth_metal2"],
height=drc["minwidth_metal1"])
self.add_via(layers = ("metal1", "via1", "metal2"),
offset=off_via,

View File

@ -49,11 +49,11 @@ class hierarchical_predecode3x8(hierarchical_predecode):
# output connection
correct = y_dir * (output_shift + drc["minwidth_metal1"])
off_via = [self.rails_x_offset[inv_rout + 5] + self.gap_between_rails,
inv_vdd_offset[1] - self.via_shift - correct]
path1 = vector(inv_out_offset[0] + 0.5*drc["minwidth_metal1"],
inv_out_offset[1]- 1.5*drc["minwidth_metal1"] - correct)
inv_vdd_offset.y - self.via_shift - correct]
path1 = inv_out_offset + vector(0.5*drc["minwidth_metal1"],
- 1.5*drc["minwidth_metal1"] - correct)
path2 = vector(path1.x,
inv_vdd_offset[1] + 0.5 * drc["minwidth_metal1"] - correct)
inv_vdd_offset.y + 0.5 * drc["minwidth_metal1"] - correct)
path3 = vector(self.rails_x_offset[inv_rout + 5] + drc["minwidth_metal2"],
path2.y)
self.add_path("metal1", [path1,path2,path3])

View File

@ -47,13 +47,13 @@ class layout:
#***1,000,000 number is used to avoid empty sequences errors***
# FIXME Is this hard coded value ok??
try:
lowestx1 = min(rect.offset[0] for rect in self.objs)
lowesty1 = min(rect.offset[1] for rect in self.objs)
lowestx1 = min(rect.offset.x for rect in self.objs)
lowesty1 = min(rect.offset.y for rect in self.objs)
except:
[lowestx1, lowesty1] = [1000000.0, 1000000.0]
try:
lowestx2 = min(inst.offset[0] for inst in self.insts)
lowesty2 = min(inst.offset[1] for inst in self.insts)
lowestx2 = min(inst.offset.x for inst in self.insts)
lowesty2 = min(inst.offset.y for inst in self.insts)
except:
[lowestx2, lowesty2] = [1000000.0, 1000000.0]
return vector(min(lowestx1, lowestx2), min(lowesty1, lowesty2))
@ -77,21 +77,18 @@ class layout:
for i in range(len(attr_val)):
# each unit in the list is a list coordinates
if isinstance(attr_val[i], (list,vector)):
attr_val[i] = vector([attr_val[i][0] - coordinate.x,
attr_val[i][1] - coordinate.y])
attr_val[i] = vector(attr_val[i] - coordinate)
# the list itself is a coordinate
else:
if len(attr_val)!=2: continue
for val in attr_val:
if not isinstance(val, (int, long, float)): continue
setattr(self,attr_key, vector([attr_val[0] - coordinate.x,
attr_val[1] - coordinate.y]))
setattr(self,attr_key, vector(attr_val - coordinate))
break
# if is a vector coordinate
if isinstance(attr_val, vector):
setattr(self, attr_key, vector(attr_val[0] - coordinate.x,
attr_val[1] - coordinate.y))
setattr(self, attr_key, vector(attr_val - coordinate))
@ -99,11 +96,9 @@ class layout:
"""Translates all 2d cartesian coordinates in a layout given
the (x,y) offset"""
for obj in self.objs:
obj.offset = snap_to_grid([obj.offset[0] - coordinate.x,
obj.offset[1] - coordinate.y])
obj.offset = vector(snap_to_grid(obj.offset - coordinate))
for inst in self.insts:
inst.offset = snap_to_grid([inst.offset[0] - coordinate.x,
inst.offset[1] - coordinate.y])
inst.offset = vector(snap_to_grid(inst.offset - coordinate))
# FIXME: Make name optional and pick a random one if not specified
def add_inst(self, name, mod, offset=[0,0], mirror="R0",rotate=0):

View File

@ -160,11 +160,11 @@ class logic_effort_dc(design.design):
if end_inv < half_length:
end_i_offset = end_inv_offset + \
self.inv.input_position.scale(1,-1)
M2_end = [end_i_offset[0], end_i_offset[1] - 0.5 * drc["minwidth_metal2"]]
M2_end = end_i_offset - vector(0, 0.5 * drc["minwidth_metal2"])
else:
end_i_offset = end_inv_offset + \
self.inv.input_position.scale(-1,1)
M2_end = [end_i_offset[0], end_i_offset[1] + 0.5 * drc["minwidth_metal2"]]
M2_end = end_i_offset + vector(0, 0.5 * drc["minwidth_metal2"])
if start_inv < half_length and end_inv >= half_length:
mid = [half_length * self.inv.width \

View File

@ -90,7 +90,7 @@ class nand_2(design.design):
def setup_layout_constants(self):
""" Calculate the layout constraints """
self.well_width = self.pmos1.active_position[0] \
self.well_width = self.pmos1.active_position.x \
+ 2 * self.pmos1.active_width \
+ drc["active_to_body_active"] + \
drc["well_enclosure_active"]
@ -127,9 +127,9 @@ class nand_2(design.design):
# determines the spacing between the edge and nmos (rail to active
# metal or poly_to_poly spacing)
edge_to_nmos = max(drc["metal1_to_metal1"]
- self.nmos1.active_contact_positions[0][1],
- self.nmos1.active_contact_positions[0].y,
0.5 * (drc["poly_to_poly"] - drc["minwidth_metal1"])
- self.nmos1.poly_positions[0][1])
- self.nmos1.poly_positions[0].y)
# determine the position of the first transistor from the left
self.nmos_position1 = vector(0, 0.5 * drc["minwidth_metal1"] + edge_to_nmos)
@ -141,7 +141,7 @@ class nand_2(design.design):
self.connect_inst(["Z", "A", "net1", "gnd"])
self.nmos_position2 = vector(self.nmos2.active_width - self.nmos2.active_contact.width,
self.nmos_position1[1])
self.nmos_position1.y)
offset = self.nmos_position2 + vector(0,self.nmos2.height)
self.add_inst(name="nmos2",
mod=self.nmos2,
@ -151,9 +151,9 @@ class nand_2(design.design):
# determines the spacing between the edge and pmos
edge_to_pmos = max(drc["metal1_to_metal1"] \
- self.pmos1.active_contact_positions[0][1],
- self.pmos1.active_contact_positions[0].y,
0.5 * drc["poly_to_poly"] - 0.5 * drc["minwidth_metal1"] \
- self.pmos1.poly_positions[0][1])
- self.pmos1.poly_positions[0].y)
self.pmos_position1 = vector(0, self.height - 0.5 * drc["minwidth_metal1"]
- edge_to_pmos - self.pmos1.height)
@ -213,13 +213,13 @@ class nand_2(design.design):
correct = vector(self.pmos1.active_contact.width - drc["minwidth_metal1"],
0).scale(.5,0)
poffset = self.pmos_position1 + self.pmos1.active_contact_positions[0] + correct
temp_height = self.height - poffset[1]
temp_height = self.height - poffset.y
self.add_rect(layer="metal1",
offset=poffset, width=drc["minwidth_metal1"],
height=temp_height)
poffset = vector(2 * self.pmos_position2.x + correct.x
+ self.pmos2.active_contact_positions[0].x , poffset[1])
+ self.pmos2.active_contact_positions[0].x , poffset.y)
self.add_rect(layer="metal1",
offset=poffset,
width=drc["minwidth_metal1"],
@ -244,14 +244,14 @@ class nand_2(design.design):
poly_length = (self.pmos_position1.y + self.pmos1.poly_positions[0].y
- yoffset_nmos1 + drc["minwidth_poly"])
for position in self.pmos1.poly_positions:
offset = [position[0],
yoffset_nmos1 - 0.5 * drc["minwidth_poly"]]
offset = vector(position.x,
yoffset_nmos1 - 0.5 * drc["minwidth_poly"])
self.add_rect(layer="poly",
offset=offset, width=drc["minwidth_poly"],
height=poly_length)
self.add_rect(layer="poly",
offset=[offset[0] + self.pmos1.active_contact.width + 2 * drc["minwidth_poly"],
offset[1]],
offset=[offset.x + self.pmos1.active_contact.width + 2 * drc["minwidth_poly"],
offset.y],
width=drc["minwidth_poly"],
height=poly_length)
@ -262,18 +262,18 @@ class nand_2(design.design):
- yoffset - self.pmos1.height + 0.5 * drc["minwidth_metal2"])
for position in self.pmos1.active_contact_positions[1:][::2]:
start = self.drain_position = [position[0] + 0.5 * drc["minwidth_metal1"]
+ self.pmos_position2[0]
+ self.pmos2.active_contact.first_layer_position[0]
start = self.drain_position = vector(position.x + 0.5 * drc["minwidth_metal1"]
+ self.pmos_position2.x
+ self.pmos2.active_contact.first_layer_position.x
+ self.pmos2.active_contact.width / 2,
yoffset]
mid1 = [start[0],
yoffset)
mid1 = vector(start.x,
self.height - drc["minwidth_metal2"] - drc["metal2_to_metal2"] -
self.pmos_size - drc["metal1_to_metal1"] - 0.5 * drc["minwidth_metal1"]]
end = [position[0] + 0.5 * drc["minwidth_metal1"]
+ self.pmos2.active_contact.second_layer_position[0],
self.pmos_position1[1] + self.pmos1.active_contact_positions[0][1]]
mid2 = [end[0], mid1[1]]
self.pmos_size - drc["metal1_to_metal1"] - 0.5 * drc["minwidth_metal1"])
end = vector(position.x + 0.5 * drc["minwidth_metal1"]
+ self.pmos2.active_contact.second_layer_position.x,
self.pmos_position1.y + self.pmos1.active_contact_positions[0].y)
mid2 = vector(end.x, mid1.y)
self.add_path("metal1",[start, mid1, mid2, end])
@ -290,7 +290,7 @@ class nand_2(design.design):
def route_input_gate_A(self):
""" routing for input A """
xoffset = self.pmos1.poly_positions[0][0]
xoffset = self.pmos1.poly_positions[0].x
yoffset = (self.height
- (drc["minwidth_metal1"]
+ drc["metal1_to_metal1"]
@ -298,8 +298,8 @@ class nand_2(design.design):
+ drc["metal1_to_metal1"]
+ self.pmos2.active_contact.second_layer_width))
if (self.nmos_width == drc["minwidth_tx"]):
yoffset = (self.pmos_position1[1]
+ self.pmos1.poly_positions[0][1]
yoffset = (self.pmos_position1.y
+ self.pmos1.poly_positions[0].y
+ drc["poly_extend_active"]
- (self.pmos1.active_contact.height
- self.pmos1.active_height) / 2
@ -312,15 +312,15 @@ class nand_2(design.design):
size=(1,1),
rotate=90)
offset = offset - self.poly_contact.first_layer_position.rotate().scale(1,0)
offset = offset - self.poly_contact.first_layer_position.rotate_scale(1,0)
self.add_rect(layer="poly",
offset=offset,
width=self.poly_contact.first_layer_position[1] + drc["minwidth_poly"],
width=self.poly_contact.first_layer_position.y + drc["minwidth_poly"],
height=self.poly_contact.first_layer_width)
input_length = (self.pmos1.poly_positions[0][0]
input_length = (self.pmos1.poly_positions[0].x
- self.poly_contact.height)
yoffset += self.poly_contact.via_layer_position[0]
yoffset += self.poly_contact.via_layer_position.x
offset = self.input_position1 = vector(0, yoffset)
self.add_rect(layer="metal1",
offset=offset,
@ -332,15 +332,15 @@ class nand_2(design.design):
def route_input_gate_B(self):
""" routing for input B """
xoffset = (self.pmos2.poly_positions[0][0]
+ self.pmos_position2[0] + drc["minwidth_poly"])
xoffset = (self.pmos2.poly_positions[0].x
+ self.pmos_position2.x + drc["minwidth_poly"])
yoffset = (drc["minwidth_metal1"]
+ drc["metal1_to_metal1"]
+ self.nmos2.active_height
+ drc["minwidth_metal1"])
if (self.nmos_width == drc["minwidth_tx"]):
yoffset = (self.nmos_position1[1]
+ self.nmos1.poly_positions[0][1]
yoffset = (self.nmos_position1.y
+ self.nmos1.poly_positions[0].y
+ self.nmos1.poly_height
+ drc["metal1_to_metal1"])
offset = [xoffset, yoffset]
@ -351,18 +351,18 @@ class nand_2(design.design):
input_length = self.pmos2.poly_positions[0].x - self.poly_contact.height
self.input_position2 = vector(xoffset - self.poly_contact.width,
yoffset + self.poly_contact.via_layer_position[0])
yoffset + self.poly_contact.via_layer_position.x)
self.add_layout_pin(text="B",
layer="metal1",
offset=self.input_position2.scale(0,1),
width=(input_length + self.pmos_position2[0] + drc["minwidth_poly"]),
width=(input_length + self.pmos_position2.x + drc["minwidth_poly"]),
height=drc["minwidth_metal1"])
def route_output(self):
""" routing for output Z """
yoffset = (self.nmos1.height - 2 * drc["minwidth_metal1"] / 3 +
(self.height - self.pmos1.height - self.nmos1.height - drc["minwidth_metal1"]) / 2 )
xoffset = self.drain_position[0]
xoffset = self.drain_position.x
offset = self.output_position = vector(xoffset, yoffset)
output_length = self.width - xoffset
self.add_layout_pin(text="Z",
@ -420,9 +420,9 @@ class nand_2(design.design):
width=width,
height=self.pmos1.active_height)
offset = vector(self.nmos_position2[0] + self.nmos1.active_position[0],
self.nmos_position1[1] - self.nmos1.active_height
- self.nmos1.active_position[1] + self.nmos1.height)
offset = vector(self.nmos_position2.x + self.nmos1.active_position.x,
self.nmos_position1.y - self.nmos1.active_height
- self.nmos1.active_position.y + self.nmos1.height)
self.add_rect(layer="active",
offset=offset,
width=self.active_width,

View File

@ -99,7 +99,7 @@ class nand_3(design.design):
def setup_layout_constants(self):
""" setup layout constraints """
self.well_width = self.nmos1.active_position[0] \
self.well_width = self.nmos1.active_position.x \
+ 3 * self.pmos1.active_width + drc["active_to_body_active"] \
+ drc["well_enclosure_active"] - self.nmos3.active_contact.width \
+ self.pmos1.active_contact.height + drc["minwidth_metal1"] \
@ -171,11 +171,11 @@ class nand_3(design.design):
# determines the spacing between the edge and pmos
self.edge_to_pmos = max(drc["metal1_to_metal1"]
- self.pmos1.active_contact_positions[0][1],
- self.pmos1.active_contact_positions[0].y,
0.5 * drc["poly_to_poly"] - 0.5 * drc["minwidth_metal1"]
- self.pmos1.poly_positions[0][1])
- self.pmos1.poly_positions[0].y)
self.pmos_position1 = vector(self.nmos_position1[0],
self.pmos_position1 = vector(self.nmos_position1.x,
self.height - 0.5 * drc["minwidth_metal1"]
- self.pmos1.height - self.edge_to_pmos)
self.add_inst(name="pmos1",
@ -216,10 +216,10 @@ class nand_3(design.design):
def connect_well_contacts(self):
""" Connect well contacts to vdd and gnd rail """
well_tap_length = self.height - self.nwell_contact_position[1]
xoffset = (self.nwell_contact_position[0]
+ self.nwell_contact.second_layer_position[0]
- self.nwell_contact.first_layer_position[0])
well_tap_length = self.height - self.nwell_contact_position.y
xoffset = (self.nwell_contact_position.x
+ self.nwell_contact.second_layer_position.x
- self.nwell_contact.first_layer_position.x)
offset = [xoffset, self.nwell_contact_position.y]
self.add_rect(layer="metal1",
offset=offset,
@ -240,14 +240,14 @@ class nand_3(design.design):
correct = vector(self.pmos1.active_contact.width - drc["minwidth_metal1"],
0).scale(0.5,0)
poffset = self.pmos_position1 + self.pmos1.active_contact_positions[0] + correct
temp_height = self.height - poffset[1]
temp_height = self.height - poffset.y
self.add_rect(layer="metal1",
offset=poffset,
width=drc["minwidth_metal1"],
height=temp_height)
poffset = [self.pmos_position3.x + self.pmos3.active_contact_positions[0].x + correct.x,
poffset[1]]
poffset.y]
self.add_rect(layer="metal1",
offset=poffset,
width=drc["minwidth_metal1"],
@ -271,20 +271,20 @@ class nand_3(design.design):
poly_length = (self.pmos_position1.y + self.pmos1.poly_positions[0].y
- yoffset_nmos1 + drc["minwidth_poly"])
offset = [self.nmos_position1[0] + self.nmos1.poly_positions[0][0],
yoffset_nmos1 - drc["minwidth_poly"]]
offset = vector(self.nmos_position1.x + self.nmos1.poly_positions[0].x,
yoffset_nmos1 - drc["minwidth_poly"])
self.add_rect(layer="poly",
offset=offset,
width=drc["minwidth_poly"],
height=poly_length)
self.add_rect(layer="poly",
offset=[offset[0] + self.pmos1.active_contact.width + 2 * drc["minwidth_poly"],
offset[1]],
offset=[offset.x + self.pmos1.active_contact.width + 2 * drc["minwidth_poly"],
offset.y],
width=drc["minwidth_poly"],
height=poly_length)
self.add_rect(layer="poly",
offset=[offset[0] + 2 * self.pmos1.active_contact.width + 4 * drc["minwidth_poly"],
offset[1]],
offset=[offset.x + 2 * self.pmos1.active_contact.width + 4 * drc["minwidth_poly"],
offset.y],
width=drc["minwidth_poly"],
height=poly_length)
@ -294,7 +294,7 @@ class nand_3(design.design):
- drc["well_enclosure_active"]
+ drc["metal1_to_metal1"])
drain_length = (self.height - yoffset + 0.5 * drc["minwidth_metal1"]
- (self.pmos1.height - self.pmos1.active_contact_positions[0][1]))
- (self.pmos1.height - self.pmos1.active_contact_positions[0].y))
layer_stack = ("metal1", "via1", "metal2")
for position in self.pmos1.active_contact_positions[1:][::2]:
diff_active_via = self.pmos2.active_contact.width - self.m1m2_via.second_layer_width
@ -315,7 +315,7 @@ class nand_3(design.design):
+ diff_active_via / 2)
self.add_via(layer_stack,[xoffset,offset.y])
xoffset = (self.nmos_position3[0] + self.nmos3.active_position[0]
xoffset = (self.nmos_position3.x + self.nmos3.active_position.x
+ self.nmos3.active_width - self.nmos3.active_contact.width / 2)
self.drain_position = vector(xoffset,
drc["minwidth_metal1"] + drc["metal1_to_metal1"])
@ -343,11 +343,11 @@ class nand_3(design.design):
rotate=90)
self.add_rect(layer="poly",
offset=offset + vector(drc["minwidth_poly"] / 2,0),
width=-(self.poly_contact.first_layer_position[1] + drc["minwidth_poly"]),
width=-(self.poly_contact.first_layer_position.y + drc["minwidth_poly"]),
height=self.poly_contact.first_layer_width)
offset = vector(offset.x,
self.pmos_position1[1] + self.pmos1.poly_positions[0][1])
self.pmos_position1.y + self.pmos1.poly_positions[0].y)
self.add_layout_pin(text="A",
layer="metal1",
offset=offset,
@ -358,9 +358,9 @@ class nand_3(design.design):
def route_input_gate_B(self):
""" routing for input B """
xoffset = self.pmos2.poly_positions[0][0] \
+ self.pmos_position2[0] - drc["minwidth_poly"]
yoffset = self.nmos_position1[1] + self.nmos1.height \
xoffset = self.pmos2.poly_positions[0].x \
+ self.pmos_position2.x - drc["minwidth_poly"]
yoffset = self.nmos_position1.y + self.nmos1.height \
- drc["well_enclosure_active"] + (self.nmos1.active_contact.height \
- self.nmos1.active_height) / 2 \
+ drc["metal1_to_metal1"]
@ -369,7 +369,7 @@ class nand_3(design.design):
self.add_via(layers=("metal1", "via1", "metal2"),
offset=[xoffset,yoffset])
xoffset = self.pmos2.poly_positions[0][0] + self.pmos_position2[0] \
xoffset = self.pmos2.poly_positions[0].x + self.pmos_position2.x \
- drc["minwidth_poly"] + self.m1m2_via.width
length = -xoffset + self.m1m2_via.width
self.add_rect(layer="metal2",
@ -382,7 +382,7 @@ class nand_3(design.design):
layer="metal1",
offset=self.B_position)
xoffset = self.pmos_position1[0] + self.pmos1.active_position[0] \
xoffset = self.pmos_position1.x + self.pmos1.active_position.x \
- drc["metal1_to_metal1"] + (self.pmos1.active_contact.width \
- self.m1m2_via.second_layer_width) / 2
self.add_via(layers=("metal1", "via1", "metal2"),
@ -395,9 +395,9 @@ class nand_3(design.design):
def route_input_gate_C(self):
""" routing for input A """
xoffset = self.pmos3.poly_positions[0][0] \
+ self.pmos_position3[0] - drc["minwidth_poly"]
yoffset = self.nmos_position1[1] + self.nmos1.height \
xoffset = self.pmos3.poly_positions[0].x \
+ self.pmos_position3.x - drc["minwidth_poly"]
yoffset = self.nmos_position1.y + self.nmos1.height \
- drc["well_enclosure_active"] + (self.nmos1.active_contact.height \
- self.nmos1.active_height) / 2 + drc["metal1_to_metal1"]
@ -406,8 +406,8 @@ class nand_3(design.design):
self.add_via(layers=("metal1", "via1", "metal2"),
offset=[xoffset,yoffset])
xoffset = self.pmos3.poly_positions[0][0] \
+ self.pmos_position3[0] - drc["minwidth_poly"] \
xoffset = self.pmos3.poly_positions[0].x \
+ self.pmos_position3.x - drc["minwidth_poly"] \
+ self.m1m2_via.width
length = -xoffset + self.m1m2_via.width
self.add_rect(layer="metal2",
@ -423,14 +423,14 @@ class nand_3(design.design):
width=self.m1m2_via.width,
height=-drc["minwidth_metal2"] - drc["metal2_to_metal2"])
self.C_position = vector(0,
self.B_position[1] - drc["metal2_to_metal2"] - drc["minwidth_metal1"] \
self.B_position.y - drc["metal2_to_metal2"] - drc["minwidth_metal1"] \
- (self.m1m2_via.second_layer_width
- self.m1m2_via.first_layer_width))
self.add_label(text="C",
layer="metal1",
offset=self.C_position)
xoffset = self.pmos_position1[0] + self.pmos1.active_position[0] \
xoffset = self.pmos_position1.x + self.pmos1.active_position.x \
- drc["metal1_to_metal1"] + (self.pmos1.active_contact.width \
- self.m1m2_via.second_layer_width) / 2
self.add_via(layers=("metal1", "via1", "metal2"),
@ -445,7 +445,7 @@ class nand_3(design.design):
def route_output(self):
""" routing for output Z """
xoffset = self.nmos_position3[0] + self.nmos3.active_position[0] \
xoffset = self.nmos_position3.x + self.nmos3.active_position.x \
+ self.nmos3.active_width - self.nmos3.active_contact.width / 2
yoffset = (self.nmos1.height + (self.height - drc["minwidth_metal1"]
- self.pmos1.height - self.nmos1.height) / 2
@ -463,11 +463,11 @@ class nand_3(design.design):
def extend_wells(self):
""" extension of well """
middle_point = self.nmos_position1[1] + self.nmos1.pwell_position[1] \
+ self.nmos1.well_height + (self.pmos_position1[1]
+ self.pmos1.nwell_position[1]
- self.nmos_position1[1]
- self.nmos1.pwell_position[1]
middle_point = self.nmos_position1.y + self.nmos1.pwell_position.y \
+ self.nmos1.well_height + (self.pmos_position1.y
+ self.pmos1.nwell_position.y
- self.nmos_position1.y
- self.nmos1.pwell_position.y
- self.nmos1.well_height) / 2
offset = self.nwell_position = vector(0, middle_point)
self.nwell_height = self.height - middle_point
@ -508,9 +508,9 @@ class nand_3(design.design):
width=width,
height=self.pmos1.active_height)
offset = [self.nmos_position3[0] + self.nmos1.active_position[0],
self.nmos_position1[1] + self.nmos1.height
- self.nmos1.active_position[1] - self.nmos1.active_height]
offset = [self.nmos_position3.x + self.nmos1.active_position.x,
self.nmos_position1.y + self.nmos1.height
- self.nmos1.active_position.y - self.nmos1.active_height]
self.add_rect(layer="active",
offset=offset,
width=self.active_width,

View File

@ -81,10 +81,10 @@ class nor_2(design.design):
0.5 * gate_to_gate - test_pmos.poly_positions[0].y)
route_margin = .5 * (self.poly_contact.second_layer_width
+ drc["minwidth_metal1"]) + drc["metal1_to_metal1"]
pmos_position = [0, self.height - 0.5 * drc["minwidth_metal1"]
- edge_to_pmos - test_pmos.height]
nmos_position = [0, 0.5 * drc["minwidth_metal1"] + edge_to_nmos]
leftspace = (0.7 * (pmos_position[1] - nmos_position[1])
pmos_position = vector(0, self.height - 0.5 * drc["minwidth_metal1"]
- edge_to_pmos - test_pmos.height)
nmos_position = vector(0, 0.5 * drc["minwidth_metal1"] + edge_to_nmos)
leftspace = (0.7 * (pmos_position.y - nmos_position.y)
- 3 * route_margin - 2 * drc["metal1_to_metal1"])
if leftspace >= 0:
break
@ -209,10 +209,10 @@ class nor_2(design.design):
self.nwell_contact_position = vector(xoffset, yoffset)
self.nwell_contact=self.add_contact(layer_stack,self.nwell_contact_position,(1,self.pmos1.num_of_tacts))
xoffset = self.nmos_position2[0] + (self.nmos1.active_position[0]
xoffset = self.nmos_position2.x + (self.nmos1.active_position.x
+ self.nmos1.active_width
+ drc["active_to_body_active"])
yoffset = (self.nmos_position1[1] + self.nmos1.height
yoffset = (self.nmos_position1.y + self.nmos1.height
- self.nmos1.active_contact_positions[0].y
- self.nmos1.active_contact.height)
self.pwell_contact_position = vector(xoffset, yoffset)
@ -222,7 +222,7 @@ class nor_2(design.design):
def route(self):
self.route_pins()
self.connect_well_contacts()
M1_track = (self.B_position[1] + drc["metal1_to_metal1"]
M1_track = (self.B_position.y + drc["metal1_to_metal1"]
+ .5 * (self.poly_contact.second_layer_width
+ drc["minwidth_metal1"]))
self.connect_tx(M1_track)
@ -230,11 +230,11 @@ class nor_2(design.design):
def connect_well_contacts(self):
""" Connect well contacts to vdd and gnd rail """
well_tap_length = self.height - self.nwell_contact_position[1]
well_tap_length = self.height - self.nwell_contact_position.y
xoffset = (self.nwell_contact_position.x
+ self.nwell_contact.second_layer_position.x
- self.nwell_contact.first_layer_position.x)
offset = [xoffset, self.nwell_contact_position[1]]
offset = [xoffset, self.nwell_contact_position.y]
self.add_rect(layer="metal1",
offset=offset,
width=drc["minwidth_metal1"],
@ -243,7 +243,7 @@ class nor_2(design.design):
offset = (self.pwell_contact_position.scale(1,0)
+ self.pwell_contact.second_layer_position.scale(1,0)
- self.pwell_contact.first_layer_position.scale(1,0))
well_tap_length = self.pwell_contact_position[1]
well_tap_length = self.pwell_contact_position.y
self.add_rect(layer="metal1",
offset=offset,
width=drc["minwidth_metal1"],
@ -257,7 +257,7 @@ class nor_2(design.design):
if i % 2 == 0:
correct = self.pmos1.active_contact.second_layer_position.scale(1,0)
drain_posistion = contact_pos + correct
height = self.vdd_position[1] - drain_posistion[1]
height = self.vdd_position.y - drain_posistion.y
self.add_rect(layer="metal1",
offset=drain_posistion,
width=drc["minwidth_metal1"],
@ -268,7 +268,7 @@ class nor_2(design.design):
+ vector(self.pmos1.active_contact.second_layer_width,
0).scale(.5,0))
source_position = contact_pos + correct
mid = [self.pmos_position2[0], M1_track]
mid = [self.pmos_position2.x, M1_track]
self.add_path("metal1", [source_position, mid])
# the second pmos
@ -279,13 +279,13 @@ class nor_2(design.design):
correct= (self.pmos2.active_contact.second_layer_position.scale(1,0)
+ vector(0.5 * self.pmos2.active_contact.second_layer_width,0))
source_position = pmos_active + correct
mid = [self.pmos_position2[0], M1_track]
mid = [self.pmos_position2.x, M1_track]
self.add_path("metal1", [source_position, mid])
# two nmos source to gnd
source_posistion1 = (self.nmos_position1
+ self.nmos1.active_contact_positions[0]
+ self.nmos1.active_contact.second_layer_position.scale(1,0))
height = self.gnd_position[1] - source_posistion1[1]
height = self.gnd_position.y - source_posistion1.y
self.add_rect(layer="metal1",
offset=source_posistion1,
width=drc["minwidth_metal1"],
@ -294,7 +294,7 @@ class nor_2(design.design):
source_posistion2 = (self.nmos_position2
+ self.nmos2.active_contact_positions[1]
+ self.nmos2.active_contact.second_layer_position.scale(1,0))
height = self.gnd_position[1] - source_posistion2[1]
height = self.gnd_position.y - source_posistion2.y
self.add_rect(layer="metal1",
offset=source_posistion2,
width=drc["minwidth_metal1"],
@ -310,22 +310,22 @@ class nor_2(design.design):
pmos_gate = (self.pmos_position1
+ self.pmos1.poly_positions[i]
+ vector(0.5 * drc["minwidth_poly"], 0))
mid1 = [pmos_gate[0], pmos_gate[1] - drc["poly_to_active"]]
mid1 = [pmos_gate.x, pmos_gate.y - drc["poly_to_active"]]
self.add_path("poly", [nmos_gate, mid1, pmos_gate])
# connect pmos2 poly
nmos_gate = [self.nmos_position2[0] \
+ self.nmos2.poly_positions[0][0]
+ 0.5 * drc["minwidth_poly"], \
self.nmos_position1[1] \
+ self.nmos1.poly_positions[0][1]]
nmos_gate = vector(self.nmos_position2[0]
+ self.nmos2.poly_positions[0].x
+ 0.5 * drc["minwidth_poly"],
self.nmos_position1.y
+ self.nmos1.poly_positions[0].y)
for i in range(len(self.pmos2.poly_positions)):
pmos_gate = (self.pmos_position2
+ self.pmos2.poly_positions[i]
+ vector(0.5 * drc["minwidth_poly"], 0))
mid1 = [pmos_gate[0],
nmos_gate[1] + self.nmos2.height \
+ drc["poly_to_active"]]
mid1 = vector(pmos_gate.x,
nmos_gate.y + self.nmos2.height
+ drc["poly_to_active"])
self.add_path("poly", [nmos_gate, mid1, pmos_gate])
def route_pins(self):
@ -350,15 +350,15 @@ class nor_2(design.design):
rotate=90)
# connect gate input to tx gate
offset = self.A_position - vector(self.poly_contact.first_layer_position[1],
offset = self.A_position - vector(self.poly_contact.first_layer_position.y,
0.5 * self.poly_contact.width)
self.add_rect(layer="poly",
offset=offset,
width=self.poly_contact.first_layer_position[1] + drc["minwidth_poly"],
width=self.poly_contact.first_layer_position.y + drc["minwidth_poly"],
height=self.poly_contact.first_layer_width)
# extend the metal to the boundary of the cell
input_length = self.A_position[0]
offset = [0, self.A_position[1] - 0.5 * drc["minwidth_metal1"]]
input_length = self.A_position.x
offset = [0, self.A_position.y - 0.5 * drc["minwidth_metal1"]]
self.add_layout_pin(text="A",
layer="metal1",
offset=offset,
@ -367,9 +367,9 @@ class nor_2(design.design):
def route_input_B(self):
"""create input B layout """
xoffset = self.pmos2.poly_positions[0][0] \
+ self.pmos_position2[0]
yoffset = self.A_position[1] \
xoffset = self.pmos2.poly_positions[0].x \
+ self.pmos_position2.x
yoffset = self.A_position.y \
+ 0.5 * (self.poly_contact.second_layer_width \
+ drc["minwidth_metal1"]) + drc["metal1_to_metal1"]
self.B_position = vector(xoffset, yoffset)
@ -380,13 +380,13 @@ class nor_2(design.design):
self.add_rect(layer="poly",
offset=offset,
width=-(self.poly_contact.first_layer_position[1] + drc["minwidth_poly"]),
width=-(self.poly_contact.first_layer_position.y + drc["minwidth_poly"]),
height=self.poly_contact.first_layer_width)
self.add_layout_pin(text="B",
layer="metal1",
offset=[0,
self.B_position[1] - 0.5 * drc["minwidth_metal1"]],
width=self.B_position[0],
self.B_position.y - 0.5 * drc["minwidth_metal1"]],
width=self.B_position.x,
height=drc["minwidth_metal1"])
def route_output(self):
@ -398,7 +398,7 @@ class nor_2(design.design):
+ self.nmos1.active_contact.second_layer_position
+ vector(self.nmos1.active_contact.second_layer_width,
0).scale(0.5, 0))
mid = [nmos_contact[0], self.A_position[1]]
mid = [nmos_contact.x, self.A_position.y]
self.add_path("metal1", [self.Z_position, mid, nmos_contact])
for i in range(len(self.pmos2.poly_positions) + 1):
@ -412,19 +412,19 @@ class nor_2(design.design):
offset = pmos_contact - vector(0.5 * self.m1m2_via.width, 0)
self.add_via(layers=("metal1", "via1", "metal2"),
offset=offset)
mid = [pmos_contact[0], self.Z_position[1]]
mid = [pmos_contact.x, self.Z_position.y]
self.add_wire(("metal2", "via1", "metal1"),
[self.Z_position, mid, pmos_contact])
def extend_wells(self):
""" extend well for well contact"""
middle_point = (self.nmos_position1[1]
+ self.nmos1.pwell_position[1]
middle_point = (self.nmos_position1.y
+ self.nmos1.pwell_position.y
+ self.nmos1.well_height
+ (self.pmos_position1[1]
+ self.pmos1.nwell_position[1]
- self.nmos_position1[1]
- self.nmos1.pwell_position[1]
+ (self.pmos_position1.y
+ self.pmos1.nwell_position.y
- self.nmos_position1.y
- self.nmos1.pwell_position.y
- self.nmos1.well_height) / 2 )
self.nwell_position = vector(0, middle_point)
self.nwell_height = self.height - middle_point

View File

@ -109,7 +109,7 @@ class pinv(design.design):
"""Sets up constant variables"""
# the well width is determined the multi-finger PMOS device width plus
# the well contact width and enclosure
self.well_width = self.pmos.active_position[0] \
self.well_width = self.pmos.active_position.x \
+ self.pmos.active_width \
+ drc["active_to_body_active"] \
+ self.pmos.active_contact.width \
@ -140,10 +140,10 @@ class pinv(design.design):
# determines the spacing between the edge and nmos (rail to active
# metal or poly_to_poly spacing)
edge_to_nmos = max(drc["metal1_to_metal1"] \
- self.nmos.active_contact_positions[0][1],
- self.nmos.active_contact_positions[0].y,
0.5 * drc["poly_to_poly"] \
- 0.5 * drc["minwidth_metal1"] \
- self.nmos.poly_positions[0][1])
- self.nmos.poly_positions[0].y)
self.nmos_position = vector(0, 0.5 * drc["minwidth_metal1"] + edge_to_nmos)
offset = self.nmos_position + vector(0,self.nmos.height)
self.add_inst(name="pinv_nmos",
@ -154,10 +154,10 @@ class pinv(design.design):
# determines the spacing between the edge and pmos
edge_to_pmos = max(drc["metal1_to_metal1"] \
- self.pmos.active_contact_positions[0][1],
- self.pmos.active_contact_positions[0].y,
0.5 * drc["poly_to_poly"] \
- 0.5 * drc["minwidth_metal1"] \
- self.pmos.poly_positions[0][1])
- self.pmos.poly_positions[0].y)
self.pmos_position = vector(0,
self.height - 0.5 * drc["minwidth_metal1"]
- edge_to_pmos - self.pmos.height)
@ -168,9 +168,9 @@ class pinv(design.design):
def extend_wells(self):
"""Extends the n/p wells to cover whole layout"""
nmos_top_yposition = self.nmos_position[1] + self.nmos.height
nmos_top_yposition = self.nmos_position.y + self.nmos.height
# calculates the length between the pmos and nmos
middle_length = self.pmos_position[1] - nmos_top_yposition
middle_length = self.pmos_position.y - nmos_top_yposition
# calculate the middle point between the pmos and nmos
middle_yposition = nmos_top_yposition + 0.5 * middle_length
@ -185,7 +185,7 @@ class pinv(design.design):
width=self.well_width,
height=self.nwell_height)
self.pwell_position = [0, 0]
self.pwell_position = vector(0, 0)
self.pwell_height = middle_yposition
self.add_rect(layer="pwell",
offset=self.pwell_position, width=self.well_width,
@ -239,14 +239,14 @@ class pinv(design.design):
def connect_poly(self):
"""Connects the poly from nmos to pmos (as well if it is multi-fingered)"""
# Calculates the y-coordinate of the top of the poly of the nmos
nmos_top_poly_yposition = self.nmos_position[1] \
nmos_top_poly_yposition = self.nmos_position.y \
+ self.nmos.height \
- self.nmos.poly_positions[0][1]
- self.nmos.poly_positions[0].y
poly_length = self.pmos_position[1] + self.pmos.poly_positions[0][1] \
poly_length = self.pmos_position.y + self.pmos.poly_positions[0].y \
- nmos_top_poly_yposition
for position in self.pmos.poly_positions:
offset = [position[0], nmos_top_poly_yposition]
offset = [position.x, nmos_top_poly_yposition]
self.add_rect(layer="poly",
offset=offset,
width=drc["minwidth_poly"],
@ -257,14 +257,14 @@ class pinv(design.design):
# Determines the top y-coordinate of the nmos drain metal layer
yoffset = self.nmos.height \
- 0.5 * drc["minwidth_metal1"] \
- self.nmos.active_contact_positions[0][1]
- self.nmos.active_contact_positions[0].y
drain_length = self.height - yoffset + drc["minwidth_metal1"] \
- (self.pmos.height
- self.pmos.active_contact_positions[0][1])
- self.pmos.active_contact_positions[0].y)
for position in self.pmos.active_contact_positions[1:][::2]:
offset = [position[0] + self.pmos.active_contact.second_layer_position[0],
offset = [position.x + self.pmos.active_contact.second_layer_position.x,
yoffset]
self.drain_position = offset
self.drain_position = vector(offset)
self.add_rect(layer="metal1",
offset=offset,
width=self.nmos.active_contact.second_layer_width,
@ -273,7 +273,7 @@ class pinv(design.design):
def route_input_gate(self):
"""Routes the input gate to the left side of the cell for access"""
xoffset = self.pmos.poly_positions[0][0]
xoffset = self.pmos.poly_positions[0].x
# Determines the y-coordinate of where to place the gate input poly pin
# (middle in between the pmos and nmos)
yoffset = self.nmos.height + (self.height
@ -285,13 +285,13 @@ class pinv(design.design):
rotate=90)
# Determines the poly coordinate to connect to the poly contact
offset = offset - self.poly_contact.first_layer_position.rotate().scale(1,0)
offset = offset - self.poly_contact.first_layer_position.rotate_scale(1,0)
self.add_rect(layer="poly",
offset=offset,
width=self.poly_contact.first_layer_position[1] + drc["minwidth_poly"],
width=self.poly_contact.first_layer_position.y + drc["minwidth_poly"],
height=self.poly_contact.first_layer_width)
input_length = self.pmos.poly_positions[0][0] \
input_length = self.pmos.poly_positions[0].x \
- self.poly_contact.height
# Determine the y-coordinate for the placement of the metal1 via
self.input_position = vector(0, .5*(self.height - drc["minwidth_metal1"]
@ -305,9 +305,9 @@ class pinv(design.design):
def route_output_drain(self):
"""Routes the output (drain) to the right side of the cell for access"""
# Determines the y-coordinate of the output metal1 via pin
offset = vector(self.drain_position[0]
offset = vector(self.drain_position.x
+ self.nmos.active_contact.second_layer_width,
self.input_position[1])
self.input_position.y)
output_length = self.width - offset.x
if self.route_output == True:
self.output_position = offset + vector(output_length,0)
@ -325,22 +325,18 @@ class pinv(design.design):
"""Adds n/p well taps to the layout"""
layer_stack = ("active", "contact", "metal1")
# Same y-positions of the drain/source metals as the n/p mos
nwell_tap_xposition = self.pmos_position[0] \
+ self.pmos.active_position[0] \
+ self.active_width \
- self.nwell_contact.width
nwell_tap_yposition = self.pmos_position[1] \
+ self.pmos.active_contact_positions[0][1]
self.nwell_contact_position = [nwell_tap_xposition, nwell_tap_yposition]
well_contact_offset = vector(self.pmos.active_position.x
+ self.active_width
- self.nwell_contact.width,
self.pmos.active_contact_positions[0].y)
self.nwell_contact_position = self.pmos_position + well_contact_offset
self.nwell_contact=self.add_contact(layer_stack,self.nwell_contact_position,(1,self.pmos.num_of_tacts))
pwell_tap_xposition = self.nmos_position[0] \
+ self.nmos.active_position[0] \
+ self.active_width \
- self.pwell_contact.width
pwell_tap_yposition = self.nmos_position[1] \
+ self.nmos.active_contact_positions[0][1]
self.pwell_contact_position = [pwell_tap_xposition, pwell_tap_yposition]
well_contact_offset = vector(self.nmos.active_position.x
+ self.active_width
- self.pwell_contact.width,
self.nmos.active_contact_positions[0].y)
self.pwell_contact_position = self.nmos_position + well_contact_offset
self.pwell_contact=self.add_contact(layer_stack,self.pwell_contact_position,(1,self.nmos.num_of_tacts))
def connect_well_contacts(self):
@ -348,7 +344,7 @@ class pinv(design.design):
# calculates the length needed to connect the nwell_tap to vdd
nwell_tap_length = self.height \
- 0.5 * drc["minwidth_metal1"] \
- self.nwell_contact_position[1]
- self.nwell_contact_position.y
# obtains the position for the metal 1 layer in the nwell_tap
offset = self.nwell_contact_position + \
self.nwell_contact.second_layer_position.scale(1,0)
@ -356,10 +352,10 @@ class pinv(design.design):
offset=offset, width=self.nwell_contact.second_layer_width,
height=nwell_tap_length)
pwell_tap_length = self.pwell_contact_position[1] \
pwell_tap_length = self.pwell_contact_position.y \
+ 0.5 * drc["minwidth_metal1"]
offset = [self.pwell_contact_position[0]
+ self.pwell_contact.second_layer_position[0],
offset = [self.pwell_contact_position.x
+ self.pwell_contact.second_layer_position.x,
0.5 * drc["minwidth_metal1"]]
self.add_rect(layer="metal1",
offset=offset,
@ -377,7 +373,7 @@ class pinv(design.design):
- drc["minwidth_metal1"]).scale(.5,.5)
# nmos position of the source metals
noffset = self.nmos_position + self.nmos.active_contact_positions[0] + correct
offset = [self.nmos.active_contact.second_layer_position[0] + noffset[0],
offset = [self.nmos.active_contact.second_layer_position.x + noffset.x,
0.5 * drc["minwidth_metal1"]]
self.add_rect(layer="metal1", offset=offset,
width=self.nmos.active_contact.second_layer_width,
@ -390,7 +386,7 @@ class pinv(design.design):
# pmos position of the source metals
offset = self.pmos_position + self.pmos.active_contact_positions[0]\
+ correct + self.pmos.active_contact.second_layer_position
temp_height = self.height - offset[1] - 0.5 * drc["minwidth_metal1"]
temp_height = self.height - offset.y - 0.5 * drc["minwidth_metal1"]
self.add_rect(layer="metal1",
offset=offset,
width=self.pmos.active_contact.second_layer_width,

View File

@ -185,7 +185,7 @@ class precharge(design.design):
def add_vdd_rail(self):
"""Adds a vdd rail at the top of the cell"""
# adds the rail across the width of the cell
self.vdd_position = vector(self.pclk_position[0],
self.vdd_position = vector(self.pclk_position.x,
self.height - drc["minwidth_metal1"])
self.add_layout_pin(text="vdd",
layer="metal1",

View File

@ -56,10 +56,10 @@ class ptx(design.design):
# We can do this in ptx because we have offset all modules it uses.
# Is this really true considering the paths that connect the src/drain?
self.height = max(max(obj.offset[1] + obj.height for obj in self.objs),
max(inst.offset[1] + inst.mod.height for inst in self.insts))
self.width = max(max(obj.offset[0] + obj.width for obj in self.objs),
max(inst.offset[0] + inst.mod.width for inst in self.insts))
self.height = max(max(obj.offset.y + obj.height for obj in self.objs),
max(inst.offset.y + inst.mod.height for inst in self.insts))
self.width = max(max(obj.offset.x + obj.width for obj in self.objs),
max(inst.offset.x + inst.mod.width for inst in self.insts))
def create_spice(self):
self.spice.append("\n.SUBCKT {0} {1}".format(self.name,
@ -78,29 +78,27 @@ class ptx(design.design):
self.mults_poly_to_poly = max(2 * drc["contact_to_poly"] + drc["minwidth_contact"],
drc["poly_to_poly"])
outeractive_to_contact = max(drc["active_enclosure_contact"],
(drc["minwidth_active"] - drc["minwidth_contact"]) / 2)
self.active_width = 2 * (outeractive_to_contact \
+ drc["minwidth_contact"] \
+ drc["contact_to_poly"]) \
+ drc["minwidth_poly"] \
+ (self.mults - 1) * (
self.mults_poly_to_poly + drc["minwidth_poly"])
(drc["minwidth_active"] - drc["minwidth_contact"]) / 2)
self.active_width = (2 * (outeractive_to_contact + drc["minwidth_contact"]
+ drc["contact_to_poly"])
+ drc["minwidth_poly"]
+ (self.mults - 1) * (self.mults_poly_to_poly
+ drc["minwidth_poly"]))
self.active_height = max(drc["minarea_active"] / self.active_width,
self.gate_width)
self.gate_width)
self.poly_width = drc["minwidth_poly"] # horizontal
self.poly_height = max(drc["minarea_poly"] / self.poly_width,
self.gate_width \
+ 2 * drc["poly_extend_active"]) # vertical
self.well_width = self.active_width \
+ 2 * (drc["well_enclosure_active"])
self.gate_width
+ 2 * drc["poly_extend_active"]) # vertical
self.well_width = (self.active_width
+ 2 * (drc["well_enclosure_active"]))
self.well_height = max(self.gate_width + 2 * (drc["well_enclosure_active"]),
drc["minwidth_well"])
drc["minwidth_well"])
def connect_fingered_poly(self):
poly_connect_length = self.poly_positions[-1][0] + self.poly_width \
- self.poly_positions[0][0]
poly_connect_position = [self.poly_positions[0][0],
self.poly_positions[0][1] - self.poly_width]
poly_connect_length = self.poly_positions[-1].x + self.poly_width \
- self.poly_positions[0].x
poly_connect_position = self.poly_positions[0] - vector(0, self.poly_width)
if len(self.poly_positions) > 1:
self.add_rect(layer="poly",
offset=poly_connect_position,
@ -127,8 +125,8 @@ class ptx(design.design):
drc["minwidth_metal1"] + drc["minwidth_contact"]),
0.5 * (self.active_contact.height - drc["minwidth_contact"])
- drc["metal1_extend_contact"])
connected=vector(b[0] + drc["minwidth_metal1"],
a[1] + self.active_contact.height + drc["metal1_to_metal1"])
connected=vector(b.x + drc["minwidth_metal1"],
a.y + self.active_contact.height + drc["metal1_to_metal1"])
self.source_positions.append(a + correct)
self.source_positions.append(vector(a.x + correct.x, connected.y))
self.source_positions.append(vector(b.x + correct.x,
@ -144,10 +142,10 @@ class ptx(design.design):
+ drc["minwidth_contact"]),
0.5*(self.active_contact.height - drc["minwidth_contact"])
- drc["metal1_extend_contact"])
connected = vector(d[0] + drc["minwidth_metal1"], c[1] - drc["metal1_to_metal1"])
connected = vector(d.x + drc["minwidth_metal1"], c.y - drc["metal1_to_metal1"])
self.drain_positions.append(vector(c + correct))
self.drain_positions.append(vector(c[0] + correct.x, connected.y))
self.drain_positions.append(vector(d[0] + correct.x,
self.drain_positions.append(vector(c.x + correct.x, connected.y))
self.drain_positions.append(vector(d.x + correct.x,
connected.y - 0.5 * drc["minwidth_metal1"]))
self.drain_positions.append(vector(d + correct))
@ -165,7 +163,7 @@ class ptx(design.design):
def add_poly(self):
# left_most poly
poly_xoffset = self.active_contact.via_layer_position[0] \
poly_xoffset = self.active_contact.via_layer_position.x \
+ drc["minwidth_contact"] + drc["contact_to_poly"]
poly_yoffset = -drc["poly_extend_active"]
self.poly_positions = []
@ -255,10 +253,10 @@ class ptx(design.design):
# middle contact columns
for i in range(self.mults - 1):
contact_xoffset = self.poly_positions[i][0] + self.poly_width \
contact_xoffset = self.poly_positions[i].x + self.poly_width \
+ (self.mults_poly_to_poly / 2) \
- (drc["minwidth_contact"] / 2) - \
self.active_contact.via_layer_position[0]
self.active_contact.via_layer_position.x
offset = vector(contact_xoffset, contact_yoffset)
self.add_contact(layers=("active", "contact", "metal1"),
offset=offset,
@ -267,9 +265,9 @@ class ptx(design.design):
self.active_contact_positions.append(offset)
# right_most contact column
contact_xoffset = self.poly_positions[-1][0] \
contact_xoffset = self.poly_positions[-1].x \
+ self.poly_width + drc["contact_to_poly"] - \
self.active_contact.via_layer_position[0]
self.active_contact.via_layer_position.x
offset = vector(contact_xoffset, contact_yoffset)
self.add_contact(layers=("active", "contact", "metal1"),
offset=offset,

View File

@ -68,7 +68,8 @@ class replica_bitline(design.design):
self.inv.height * 0.5)
self.replica_bitline_offset = vector(self.delay_chain_offset.x
+ bitcell_array_spacing,
self.bitcell_chars["height"] + gnd_route_margin)
self.bitcell_chars["height"]
+ gnd_route_margin)
self.delay_inv_offset = vector(self.delay_chain_offset.x - self.inv.width,
self.inv.height * 2)
@ -184,59 +185,44 @@ class replica_bitline(design.design):
BL_inv_in = self.BL_inv_offset + self.inv.A_position + correct
BL_offset = self.replica_bitline_offset + vector(1,0).scale(self.bitcell_chars["BL"])
pin_offset = self.delay_chain.clk_out_offset.rotate().scale(-1,1)
pin_offset = self.delay_chain.clk_out_offset.rotate_scale(-1,1)
delay_chain_output = self.delay_chain_offset + pin_offset
vdd_offset = vector(self.delay_chain_offset.x + 9 * drc["minwidth_metal2"],
self.height)
self.create_input()
self.route_BL_t_BL_inv(BL_offset, BL_inv_in)
self.route_access_tx(delay_chain_output, BL_inv_in)
self.route_access_tx(delay_chain_output, BL_inv_in, vdd_offset)
self.route_vdd()
self.route_gnd()
# route loads after gnd and vdd created
self.route_loads()
self.route_RC()
self.route_loads(vdd_offset)
self.route_RC(vdd_offset)
def create_input(self):
# create routing module based on module offset
correct = vector(0.5 * drc["minwidth_metal1"], 0)
pin_offset = self.delay_chain.clk_in_offset.rotate().scale(-1,1)
pin_offset = self.delay_chain.clk_in_offset.rotate_scale(-1,1)
input_offset = self.delay_chain_offset + pin_offset + correct
mid1 = [input_offset[0], self.en_input_offset[1]]
mid1 = [input_offset.x, self.en_input_offset.y]
self.add_path("metal1", [self.en_input_offset, mid1, input_offset])
self.add_label(text="en",
layer="metal1",
offset=self.en_input_offset)
def route_nor2A_t_dc(self, nor_A, delayed_en_offset):
# delay chain output to m2
dc_offset = [delayed_en_offset[0], delayed_en_offset[1]]
mid1 = [dc_offset[0], self.en_nor_offset
[1] + 3 * drc["minwidth_metal2"]]
mid2 = [self.delay_chain_offset[0] + 3*drc["minwidth_metal2"],
dc_offset[1]]
mid3 = [mid2[0], nor_A[1]]
self.add_wire(("metal2", "via1", "metal1"),
[dc_offset, mid2, mid3, nor_A])
def route_nor2B_t_BL_inv(self, nor_B, BL_inv_out):
mid1 = [nor_B[0] + 0.5 * drc["metal2_to_metal2"], nor_B[1]]
self.add_wire(("metal2", "via1", "metal1"),
[nor_B, mid1, BL_inv_out])
def route_BL_t_BL_inv(self, BL_offset, BL_inv_in):
# BL_inv input to M3
mid1 = [BL_inv_in[0],
BL_inv_in[1] - drc["metal2_to_metal2"] - self.m1m2_via.width]
mid2 = [self.en_nor_offset[0] + 3*drc["metal1_to_metal1"],
mid1[1]]
mid3 = [mid2[0],
self.replica_bitline_offset[1] - self.replica_bitcell.height
- 0.5 * (self.m1m2_via.height + drc["metal1_to_metal1"])
- 2 * drc["metal1_to_metal1"]]
self.add_wire(("metal1", "via1", "metal2"),
[BL_inv_in, mid1, mid2, mid3])
mid1 = BL_inv_in - vector(0,
drc["metal2_to_metal2"] + self.m1m2_via.width)
mid2 = vector(self.en_nor_offset.x + 3 * drc["metal1_to_metal1"],
mid1.y)
mid3 = vector(mid2.x,
self.replica_bitline_offset.y - self.replica_bitcell.height
- 0.5 * (self.m1m2_via.height + drc["metal1_to_metal1"])
- 2 * drc["metal1_to_metal1"])
self.add_wire(layers=("metal1", "via1", "metal2"),
coordinates=[BL_inv_in, mid1, mid2, mid3])
# need to fix the mid point as this is done with two wire
# this seems to cover the metal1 error of the wire
@ -246,18 +232,18 @@ class replica_bitline(design.design):
width=drc["minwidth_metal1"],
height=drc["minwidth_metal1"])
mid4 = [BL_offset[0], mid3[1]]
self.add_wire(("metal2", "via1", "metal1"),
[BL_offset, mid4, mid3])
mid4 = [BL_offset.x, mid3.y]
self.add_wire(layers=("metal2", "via1", "metal1"),
coordinates=[BL_offset, mid4, mid3])
def route_access_tx(self, delay_chain_output, BL_inv_in):
def route_access_tx(self, delay_chain_output, BL_inv_in, vdd_offset):
self.route_tx_gate(delay_chain_output)
self.route_tx_drain()
self.route_tx_drain(vdd_offset)
self.route_tx_source(BL_inv_in)
def route_tx_gate(self, delay_chain_output):
# gate input for access tx
offset = (self.access_tx.poly_positions[0].rotate().scale(0,1)
offset = (self.access_tx.poly_positions[0].rotate_scale(0,1)
+ self.access_tx_offset)
width = -6 * drc["minwidth_metal1"]
self.add_rect(layer="poly",
@ -276,35 +262,36 @@ class replica_bitline(design.design):
def route_access_tx_t_delay_chain(self, offset, delay_chain_output):
m2rail_space = (drc["minwidth_metal2"] + drc["metal2_to_metal2"])
mid1 = [offset[0], self.delay_chain_offset[1] - 3 * m2rail_space]
mid2 = [delay_chain_output[0], mid1[1]]
mid1 = vector(offset.x, self.delay_chain_offset.y - 3 * m2rail_space)
mid2 = [delay_chain_output.x, mid1.y]
# Note the inverted wire stack
self.add_wire(("metal2", "via1", "metal1"),
[offset, mid1, mid2, delay_chain_output])
self.add_wire(layers=("metal2", "via1", "metal1"),
coordinates=[offset, mid1, mid2, delay_chain_output])
self.add_via(layers=("metal1", "via1", "metal2"),
offset=delay_chain_output,
mirror="MX")
offset=delay_chain_output,
mirror="MX")
def route_access_tx_t_WL(self, offset):
m1m2_via_offset = offset - vector(0.5 * self.m1m2_via.width,
0.5 * self.m1m2_via.height)
0.5 * self.m1m2_via.height)
self.add_via(layers=("metal1", "via1", "metal2"),
offset=m1m2_via_offset)
# route gate to RC WL
RC_WL = self.replica_bitline_offset - vector(0,1).scale(self.bitcell_chars["WL"])
mid1 = [offset[0], 0]
mid2 = [self.en_nor_offset[0] + 3 * drc["metal1_to_metal1"],
mid1[1]]
mid3 = [RC_WL[0] - drc["minwidth_metal1"] - self.m1m2_via.height,
mid1[1]]
mid4 = [mid3[0], RC_WL[1]]
mid1 = vector(offset.x, 0)
mid2 = vector(self.en_nor_offset.x + 3 * drc["metal1_to_metal1"],
mid1.y)
mid3 = vector(RC_WL.x - drc["minwidth_metal1"] - self.m1m2_via.height,
mid1.y)
mid4 = vector(mid3.x, RC_WL.y)
self.add_path("metal2", [offset, mid1, mid2, mid3, mid4])
offset = mid4 - vector([0.5 * drc["minwidth_metal1"]]*2)
width = RC_WL[0] - offset[0]
offset = mid4 - vector([0.5 * drc["minwidth_metal1"]] * 2)
width = RC_WL.x - offset.x
# enter the bit line array with metal1
via_offset = [mid4[0] - 0.5 * self.m1m2_via.width,
offset[1] - 0.5 * (self.m1m2_via.height
via_offset = [mid4.x - 0.5 * self.m1m2_via.width,
offset.y
- 0.5 * (self.m1m2_via.height
- drc["minwidth_metal1"])]
self.add_via(layers=("metal1", "via1", "metal2"),
offset=via_offset)
@ -313,26 +300,24 @@ class replica_bitline(design.design):
width=width,
height=drc["minwidth_metal1"])
def route_tx_drain(self):
def route_tx_drain(self,vdd_offset):
# route drain to Vdd
active_offset = self.access_tx.active_contact_positions[1].rotate().scale(-1,1)
correct = vector(drc["minwidth_metal1"],
self.access_tx.active_contact.width).scale(-0.5, 0.5)
active_offset = self.access_tx.active_contact_positions[1].rotate_scale(-1,1)
correct = vector(-0.5 * drc["minwidth_metal1"],
0.5 * self.access_tx.active_contact.width)
drain_offset = self.access_tx_offset + active_offset + correct
vdd_rail = [self.delay_chain_offset[0] + 9 * drc["minwidth_metal2"],
self.height]
close_Vdd_offset = self.BL_inv_offset + vector(0, self.inv.height)
self.add_path("metal1", [drain_offset, close_Vdd_offset])
mid = [vdd_rail[0], close_Vdd_offset[1]]
self.add_wire(("metal2", "via1", "metal1"),
[close_Vdd_offset, mid, vdd_rail])
mid = [vdd_offset.x, close_Vdd_offset.y]
self.add_wire(layers=("metal2", "via1", "metal1"),
coordinates=[close_Vdd_offset, mid, vdd_offset])
def route_tx_source(self, BL_inv_in):
# route source to BL inv input which is connected to BL
active_offset = self.access_tx.active_contact_positions[0].rotate().scale(-1,1)
correct = vector(drc["minwidth_metal1"],
self.access_tx.active_contact.width).scale(-0.5, 0.5)
active_offset = self.access_tx.active_contact_positions[0].rotate_scale(-1,1)
correct = vector(-0.5 * drc["minwidth_metal1"],
0.5 * self.access_tx.active_contact.width)
source_offset = self.access_tx_offset + active_offset + correct
self.add_path("metal1", [source_offset, BL_inv_in])
@ -347,11 +332,13 @@ class replica_bitline(design.design):
start = self.delay_chain_offset - vector(0.5 * self.delay_chain.height, 0)
m1rail_space = (drc["minwidth_metal1"] + drc["metal1_to_metal1"])
mid1 = start - vector(0, m1rail_space)
mid2 = [self.delay_chain_offset[0] + 9 * drc["minwidth_metal2"],
mid1[1]]
end = [mid2[0], vdd_offset[1]]
self.add_path(("metal1"), [start, mid1, mid2])
self.add_wire(("metal2", "via1", "metal1"), [mid1, mid2, end])
mid2 = vector(self.delay_chain_offset.x + 9 * drc["minwidth_metal2"],
mid1.y)
end = [mid2.x, vdd_offset.y]
self.add_path(layer=("metal1"),
coordinates=[start, mid1, mid2])
self.add_wire(layers=("metal2", "via1", "metal1"),
coordinates=[mid1, mid2, end])
def route_gnd(self):
"""route gnd of delay chain, en_nor, en_inv and BL_inv"""
@ -366,8 +353,9 @@ class replica_bitline(design.design):
mid2 = vector(mid1.x, y_off)
share_gnd = vector(self.gnd_position.x, mid2.y)
# Note the inverted stacks
self.add_wire(("metal2", "via1", "metal1"),
[BL_gnd_offset, mid1, mid2, share_gnd, self.gnd_position])
lst = [BL_gnd_offset, mid1, mid2, share_gnd, self.gnd_position]
self.add_wire(layers=("metal2", "via1", "metal1"),
coordinates=lst)
self.add_label(text="gnd",
layer="metal1",
offset=self.gnd_position)
@ -377,51 +365,51 @@ class replica_bitline(design.design):
offset=offset,
width=drc["minwidth_metal1"],
height=-self.delay_chain.width)
offset = [offset[0] + self.delay_chain.height,
mid2[1]]
offset = [offset.x + self.delay_chain.height,
mid2.y]
self.add_rect(layer="metal1",
offset=offset,
width=drc["minwidth_metal1"],
height=-self.delay_chain.width)
def route_loads(self):
def route_loads(self,vdd_offset):
"""connect all the loads word line to gnd"""
vdd_offset = [self.delay_chain_offset[0] + 9*drc["minwidth_metal2"],
self.height]
self.add_via(layers=("metal1", "via1", "metal2"),
offset=vdd_offset,
mirror="MX")
gnd_offset = (self.delay_chain_offset
+ vector([drc["minwidth_metal1"]]*2).scale(-.5,.5))
+ vector([drc["minwidth_metal1"]] * 2).scale(-.5,.5))
for i in range(self.rows):
WL_offset = (self.replica_bitline_offset
+ self.bitline_load.WL_positions[i].scale(0,1))
mid = [self.delay_chain_offset[0] + 6 * drc["minwidth_metal2"],
gnd_offset[1]]
self.add_wire(("metal2", "via1", "metal1"), [gnd_offset, mid, WL_offset])
mid = [self.delay_chain_offset.x + 6 * drc["minwidth_metal2"],
gnd_offset.y]
self.add_wire(layers=("metal2", "via1", "metal1"),
coordinates=[gnd_offset, mid, WL_offset])
if i % 2 == 0:
load_vdd_offset = (self.replica_bitline_offset
+ self.bitline_load.vdd_positions[i])
mid = [vdd_offset[0], load_vdd_offset[1]]
self.add_wire(("metal2", "via1", "metal1"), [vdd_offset, mid, load_vdd_offset])
+ self.bitline_load.vdd_positions[i])
mid = [vdd_offset.x, load_vdd_offset.y]
self.add_wire(layers=("metal2", "via1", "metal1"),
coordinates=[vdd_offset, mid, load_vdd_offset])
def route_RC(self):
def route_RC(self,vdd_offset):
"""route vdd gnd to the replica cell """
# connect vdd
RC_vdd = self.replica_bitline_offset + vector(1,-1).scale(self.bitcell_chars["vdd"])
vdd_offset = [self.delay_chain_offset[0] + 9 * drc["minwidth_metal2"],
self.height]
mid = [vdd_offset[0], RC_vdd[1]]
mid = [vdd_offset.x, RC_vdd.y]
# Note the inverted stacks
self.add_wire(("metal2", "via1", "metal1"), [vdd_offset, mid, RC_vdd])
self.add_wire(layers=("metal2", "via1", "metal1"),
coordinates=[vdd_offset, mid, RC_vdd])
gnd_offset = self.BL_inv_offset - vector(self.inv.width, 0)
load_gnd = (self.replica_bitline_offset
+ vector(self.bitcell_chars["gnd"][0], self.bitline_load.height))
mid = [load_gnd[0], gnd_offset[1]]
self.add_wire(("metal2", "via1", "metal1"), [gnd_offset, mid, load_gnd])
load_gnd = self.replica_bitline_offset + vector(self.bitcell_chars["gnd"][0],
self.bitline_load.height)
mid = [load_gnd.x, gnd_offset.y]
self.add_wire(layers=("metal2", "via1", "metal1"),
coordinates=[gnd_offset, mid, load_gnd])
load_gnd = (self.replica_bitline_offset
+ vector(0, self.bitline_load.height))
mid = [load_gnd[0], gnd_offset[1]]
load_gnd = self.replica_bitline_offset + vector(0,
self.bitline_load.height)
mid = [load_gnd.x, gnd_offset.y]
self.add_wire(("metal2", "via1", "metal1"), [gnd_offset, mid, load_gnd])

View File

@ -79,7 +79,7 @@ class single_level_column_mux(design.design):
self.poly_offset = (self.nmos1_position
+ self.nmos1.poly_positions[0]
+ vector(0,self.nmos1.poly_height))
width=self.nmos2_position[0] - self.nmos1_position[0] + drc["minwidth_poly"]
width=self.nmos2_position.x- self.nmos1_position.x+ drc["minwidth_poly"]
self.poly = self.add_rect(layer="poly",
offset=self.poly_offset,
width=width,
@ -91,7 +91,7 @@ class single_level_column_mux(design.design):
def connect_to_bitlines(self):
offset = [self.nmos1.active_contact_positions[0].x + self.m1m2_via.contact_width / 2
+ 3 * (self.m1m2_via.second_layer_width - self.m1m2_via.first_layer_width) / 2,
self.nmos1.active_position[1] + self.nmos1.active_height]
self.nmos1.active_position.y+ self.nmos1.active_height]
offset = self.nmos1_position + offset
connection = vector(0,
self.nmos2.active_height+ 2 * drc["poly_extend_active"] \
@ -101,7 +101,7 @@ class single_level_column_mux(design.design):
width=drc["minwidth_metal2"],
height=connection.y - drc["minwidth_metal2"])
self.BL_position = (vector(self.bitcell_chars["BL"][0] - 0.5 * self.m1m2_via.width,
self.BL_position = (vector(self.bitcell_chars["BL"][0]- 0.5 * self.m1m2_via.width,
offset.y)
+ connection)
self.add_via(layers=("metal1", "via1", "metal2"),
@ -116,10 +116,10 @@ class single_level_column_mux(design.design):
width=drc["minwidth_metal2"],
height=2 * drc["minwidth_metal2"])
width = self.bitcell_chars["BL"][0] - 0.5 * self.m1m2_via.width - offset[0] + drc["minwidth_metal2"]
width = self.bitcell_chars["BL"][0]- 0.5 * self.m1m2_via.width - offset.x+ drc["minwidth_metal2"]
self.add_rect(layer="metal2",
offset=[offset[0],
self.BL_position[1] - 2*drc["minwidth_metal2"]],
self.BL_position.y- 2*drc["minwidth_metal2"]],
width=width,
height=drc["minwidth_metal2"])
@ -127,24 +127,24 @@ class single_level_column_mux(design.design):
self.add_via(layers=("metal1", "via1", "metal2"),
offset=offset)
self.add_rect(layer="metal2",
offset=[self.bitcell_chars["BL"][0] - 0.5 * self.m1m2_via.width,
offset=[self.bitcell_chars["BL"][0]- 0.5 * self.m1m2_via.width,
0],
width=drc["minwidth_metal2"],
height=(drc["minwidth_metal2"] + offset[1]))
self.add_rect(layer="metal2",
offset=[self.bitcell_chars["BL"][0] - 0.5 * self.m1m2_via.width,
offset=[self.bitcell_chars["BL"][0]- 0.5 * self.m1m2_via.width,
offset[1]],
width=(offset[0] - self.bitcell_chars["BL"][0] - 0.5 * self.m1m2_via.width
width=(offset.x- self.bitcell_chars["BL"][0]- 0.5 * self.m1m2_via.width
+ 2 * drc["minwidth_metal2"]),
height=drc["minwidth_metal2"])
self.BL_out_position = vector(self.bitcell_chars["BL"][0] - 0.5* self.m1m2_via.width,
self.BL_out_position = vector(self.bitcell_chars["BL"][0]- 0.5* self.m1m2_via.width,
0)
self.add_label(text="bl_out",
layer="metal2",
offset=self.BL_out_position)
offset = [self.nmos2.active_contact_positions[1].x - self.m1m2_via.contact_width / 2,
self.nmos2.active_position[1] + self.nmos2.active_height]
self.nmos2.active_position.y+ self.nmos2.active_height]
offset = self.nmos2_position + offset
self.add_via(layers=("metal1", "via1", "metal2"),
offset=offset,
@ -152,21 +152,21 @@ class single_level_column_mux(design.design):
mid = offset + vector(drc["minwidth_metal2"],0)
self.add_rect(layer="metal2",
offset= mid,
width= (self.bitcell_chars["BR"][0] - mid[0] + 0.5*self.m1m2_via.width),
width= (self.bitcell_chars["BR"][0]- mid.x+ 0.5*self.m1m2_via.width),
height=-drc["minwidth_metal2"])
self.add_rect(layer="metal2",
offset=[self.bitcell_chars["BR"][0] - 0.5*self.m1m2_via.width,
offset[1] - drc["metal1_to_metal1"]],
offset=[self.bitcell_chars["BR"][0]- 0.5*self.m1m2_via.width,
offset.y- drc["metal1_to_metal1"]],
width=drc["minwidth_metal2"],
height=2*drc["minwidth_metal2"])
self.BR_position = vector(self.bitcell_chars["BR"][0] - 0.5 * self.m1m2_via.width,
self.BR_position = vector(self.bitcell_chars["BR"][0]- 0.5 * self.m1m2_via.width,
self.BL_position.y)
self.add_label(text="br",
layer="metal2",
offset=self.BR_position)
offset = self.nmos2_position + self.nmos2.active_contact_positions[0]
self.BR_out_position = vector(self.bitcell_chars["BR"][0] - 0.5 * self.m1m2_via.width,
self.BR_out_position = vector(self.bitcell_chars["BR"][0]- 0.5 * self.m1m2_via.width,
0)
self.add_label(text="br_out",
layer="metal2",
@ -179,12 +179,12 @@ class single_level_column_mux(design.design):
height=drc["minwidth_metal2"])
self.add_rect(layer="metal2",
offset=[self.BR_out_position.x,
offset[1] + drc["minwidth_metal2"]],
offset.y+ drc["minwidth_metal2"]],
width=drc["minwidth_metal2"],
height=-(offset[1] + drc["minwidth_metal2"]))
height=-(offset.y+ drc["minwidth_metal2"]))
def add_gnd_rail(self):
self.gnd_position = vector(self.bitcell_chars["gnd"][0] - 0.5 * self.m1m2_via.width,
self.gnd_position = vector(self.bitcell_chars["gnd"][0]- 0.5 * self.m1m2_via.width,
0)
self.add_layout_pin(text="gnd",
layer="metal2",
@ -193,7 +193,7 @@ class single_level_column_mux(design.design):
height=self.BL_position[1])
def add_well_contacts(self):
offset = vector(self.gnd_position[0] + drc["minwidth_metal2"],
offset = vector(self.gnd_position.x+ drc["minwidth_metal2"],
self.nmos1.poly_height / 2)
self.add_via(layers=("metal1", "via1", "metal2"),
offset=offset - vector(self.m1m2_via.width / 2, 0),
@ -212,11 +212,11 @@ class single_level_column_mux(design.design):
offset_well = self.nmos1_position + vector(self.nmos1.width, 0)
self.add_rect(layer="pwell",
offset=offset_well,
width=self.gnd_position[0] + drc["minwidth_metal2"] - offset_well[0],
width=self.gnd_position.x+ drc["minwidth_metal2"] - offset_well[0],
height=self.nmos1.height + drc["minwidth_poly"])
self.add_rect(layer="vtg",
offset=offset_well,
width=self.gnd_position[0] + drc["minwidth_metal2"] - offset_well[0],
width=self.gnd_position.x+ drc["minwidth_metal2"] - offset_well[0],
height=self.nmos1.height + drc["minwidth_poly"])
def setup_layout_constants(self):

View File

@ -380,14 +380,14 @@ class sram(design.design):
self.width = self.bank.width + self.control.height + 2*drc["minwidth_metal3"]
self.height = self.bank.height
self.control.CSb_position.rotate().scale(-1,1)
self.CSb_position = (self.control.CSb_position.rotate().scale(-1,1)
self.control.CSb_position.rotate_scale(-1,1)
self.CSb_position = (self.control.CSb_position.rotate_scale(-1,1)
+self.control_position)
self.OEb_position = (self.control.OEb_position.rotate().scale(-1,1)
self.OEb_position = (self.control.OEb_position.rotate_scale(-1,1)
+self.control_position)
self.WEb_position = (self.control.WEb_position.rotate().scale(-1,1)
self.WEb_position = (self.control.WEb_position.rotate_scale(-1,1)
+self.control_position)
self.clk_position = (self.control.clk_position.rotate().scale(-1,1)
self.clk_position = (self.control.clk_position.rotate_scale(-1,1)
+self.control_position)
for i in range(0, self.word_size):
self.add_label(text="DATA[{0}]".format(i),
@ -612,7 +612,7 @@ class sram(design.design):
bank_attr = self.sram_property[attr_index]
self.add_rect(layer="metal3",
offset=getattr(self,bank_attr)[left_bank_index],
width=getattr(self,bank_attr)[right_bank_index].x - getattr(self,bank_attr)[left_bank_index][0],
width=getattr(self,bank_attr)[right_bank_index].x - getattr(self,bank_attr)[left_bank_index].x,
height=drc["minwidth_metal3"])
self.add_via(layers=("metal2", "via2", "metal3"),
offset=[self.vertical_line_positions[attr_index].x,
@ -710,17 +710,17 @@ class sram(design.design):
# 0 = s_en
control_side = []
control_side.append(self.control.clk_position.rotate().scale(-1, 1)
control_side.append(self.control.clk_position.rotate_scale(-1, 1)
+ self.control_position)
control_side.append(self.control.clk_bar_position.rotate().scale(-1, 1)
control_side.append(self.control.clk_bar_position.rotate_scale(-1, 1)
+ self.control_position)
control_side.append(self.control.tri_en_position.rotate().scale(-1, 1)
control_side.append(self.control.tri_en_position.rotate_scale(-1, 1)
+ self.control_position)
control_side.append(self.control.tri_en_bar_position.rotate().scale(-1, 1)
control_side.append(self.control.tri_en_bar_position.rotate_scale(-1, 1)
+ self.control_position)
control_side.append(self.control.w_en_position.rotate().scale(-1, 1)
control_side.append(self.control.w_en_position.rotate_scale(-1, 1)
+ self.control_position)
control_side.append(self.control.s_en_position.rotate().scale(-1, 1)
control_side.append(self.control.s_en_position.rotate_scale(-1, 1)
+ self.control_position)
bank_side = []
@ -763,14 +763,14 @@ class sram(design.design):
msb_line = self.control_size + self.num_banks/2 - 1 - i
bank_select_start_line = msb_line + 2 + self.bank_addr_size
msf_msb_din = (self.msf_msb_address.din_positions[i].rotate().scale(1, -1)
msf_msb_din = (self.msf_msb_address.din_positions[i].rotate_scale(1, -1)
+ self.msf_msb_address_position)
contact_pos = [self.vertical_line_positions[msb_line].x,
msf_msb_din.y - 0.5*self.m2m3_via.width]
contact_pos = vector(self.vertical_line_positions[msb_line].x,
msf_msb_din.y - 0.5*self.m2m3_via.width)
self.add_rect(layer="metal3",
offset=contact_pos,
width=msf_msb_din[0] - contact_pos[0],
width=msf_msb_din.x - contact_pos.x,
height=drc["minwidth_metal3"])
self.add_via(layers=("metal2", "via2", "metal3"),
offset=contact_pos)
@ -785,9 +785,9 @@ class sram(design.design):
height=drc["minwidth_metal1"])
if(self.num_banks == 2):
msb_msf_dout_position = (self.msf_msb_address.dout_positions[i].rotate().scale(1, -1)
msb_msf_dout_position = (self.msf_msb_address.dout_positions[i].rotate_scale(1, -1)
+ self.msf_msb_address_position)
msb_msf_dout_bar_position = (self.msf_msb_address.dout_bar_positions[i].rotate().scale(1, -1)
msb_msf_dout_bar_position = (self.msf_msb_address.dout_bar_positions[i].rotate_scale(1, -1)
+ self.msf_msb_address_position)
starts = [msb_msf_dout_bar_position,
msb_msf_dout_position]
@ -801,7 +801,7 @@ class sram(design.design):
+ self.msf_msb_address.height
+ 4 * (i + 1) * drc["minwidth_metal2"],
start.y)
end = vector(mid1.x, self.msf_msb_address_position[1]
end = vector(mid1.x, self.msf_msb_address_position.y
+ 4 * (i + 1) * drc["minwidth_metal2"])
self.add_wire(("metal1", "via1", "metal2"), [start, mid1, end])
@ -818,7 +818,7 @@ class sram(design.design):
if(self.num_banks == 4):
for i in range(2):
msb_msf_out_position = (self.msf_msb_address.dout_positions[i].rotate().scale(1, -1)
msb_msf_out_position = (self.msf_msb_address.dout_positions[i].rotate_scale(1, -1)
+ self.msf_msb_address_position)
msb_decoder_in_position =(self.msb_decoder.A_positions[i].scale(-1, 1)
+ self.msb_decoder_position
@ -827,7 +827,7 @@ class sram(design.design):
start = msb_msf_out_position
mid1 = start + vector(4 * (i + 1) * drc["minwidth_metal1"], 0)
mid2 = vector(mid1.x, msb_decoder_in_position.y)
end = vector(self.msb_decoder_position[0]
end = vector(self.msb_decoder_position.x
+ 3*drc["minwidth_metal3"],
mid2.y)
@ -874,9 +874,9 @@ class sram(design.design):
# control logic
self.control_vdd1_position = (self.control_position
+ self.control.vdd1_position.rotate().scale(-1, 1))
+ self.control.vdd1_position.rotate_scale(-1, 1))
self.control_vdd2_position = (self.control_position
+ self.control.vdd2_position.rotate().scale(-1, 1))
+ self.control.vdd2_position.rotate_scale(-1, 1))
self.add_rect(layer="metal1",
offset=self.control_vdd1_position,
@ -974,7 +974,7 @@ class sram(design.design):
# msf_msb_address
start = msf_address_vdd_position = (self.msf_msb_address_position
+ self.msf_msb_address.vdd_positions[0].rotate().scale(1,-1))
+ self.msf_msb_address.vdd_positions[0].rotate_scale(1,-1))
mid1 = vector(start.x,
self.msf_msb_address_position.y
- self.msf_msb_address.width
@ -1029,7 +1029,7 @@ class sram(design.design):
offset=self.gnd_offset)
self.control_gnd_position = (self.control_position
+ self.control.gnd_position.rotate().scale(-1,1)
+ self.control.gnd_position.rotate_scale(-1,1)
+ vector(drc["minwidth_metal2"],0))
self.add_rect(layer="metal3",
@ -1070,12 +1070,12 @@ class sram(design.design):
self.add_rect(layer="metal2",
offset=self.sram_bank_left_gnd_positions[0],
width=drc["minwidth_metal2"],
height=control_gnd_supply[1] + drc["minwidth_metal1"]
height=control_gnd_supply.y + drc["minwidth_metal1"]
- self.sram_bank_left_gnd_positions[0].y)
self.add_via(layers=("metal1", "via1", "metal2"),
offset=[self.sram_bank_left_gnd_positions[0].x
+ drc["minwidth_metal2"],
control_gnd_supply[1]],
control_gnd_supply.y],
mirror="R90")
# Control gnd
self.add_via(layers=("metal1", "via1", "metal2"),

View File

@ -92,3 +92,10 @@ class vector():
y_factor=x_factor[1]
x_factor=x_factor[0]
return vector(self.x*x_factor,self.y*y_factor)
def rotate_scale(self, x_factor, y_factor=None):
""" pass a copy of scaled vector, without altering the vector! """
if y_factor==None:
y_factor=x_factor[1]
x_factor=x_factor[0]
return vector(self.y*x_factor,self.x*y_factor)