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): for i in range(2):
ff_index = i + self.row_addr_size ff_index = i + self.row_addr_size
current_dout = self.msf_address.dout_positions[ff_index] 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) + self.msf_address_offset)
line_index = self.num_central_bus - 2 + i line_index = self.num_central_bus - 2 + i
@ -922,9 +922,9 @@ class bank(design.design):
elif(self.col_addr_size == 1): elif(self.col_addr_size == 1):
ff_index = self.row_addr_size ff_index = self.row_addr_size
base = self.msf_address_offset - vector(0, 0.5 * drc["minwidth_metal3"]) 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) + 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) + base)
y_offset = self.msf_address_offset.y - self.msf_address.width 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
# 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 + self.msf_address_offset
- vector(0, 0.5 * drc["minwidth_metal3"])) - vector(0, 0.5 * drc["minwidth_metal3"]))
connection_width = (self.central_line_xoffset[line_index] + drc["minwidth_metal2"] 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): for i in range(self.addr_size):
# Route msf address inputs # 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 + self.msf_address_offset
- vector(0, 0.5 * drc["minwidth_metal3"])) - vector(0, 0.5 * drc["minwidth_metal3"]))
address_position = vector(self.left_vdd_x_offset, address_position = vector(self.left_vdd_x_offset,
@ -1083,7 +1083,7 @@ class bank(design.design):
""" CLK connection from central bus to MSF address """ CLK connection from central bus to MSF address
should we move this somewhere else hard to find when modify""" should we move this somewhere else hard to find when modify"""
msf_address_clk_position = (self.msf_address_offset 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"], + vector(- 0.5 * drc["minwidth_metal1"],
2 * drc["minwidth_metal2"])) 2 * drc["minwidth_metal2"]))
clk_connection_position = (self.msf_address_offset clk_connection_position = (self.msf_address_offset

View File

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

View File

@ -146,7 +146,7 @@ class control_logic(design.design):
# Height and width # Height and width
self.height = self.logic_height + self.output_port_gap 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): def add_routing(self):
""" Routing between modules """ """ Routing between modules """
@ -175,11 +175,11 @@ class control_logic(design.design):
# msf_control inputs # msf_control inputs
correct = vector(0, 0.5 * drc["minwidth_metal2"]) correct = vector(0, 0.5 * drc["minwidth_metal2"])
def translate_inputs(pt1,pt2): def translate_inputs(pt1,pt2):
return pt1 + pt2.rotate().scale(1,-1) - correct return pt1 + pt2.rotate_scale(1,-1) - correct
# msf_control outputs # msf_control outputs
def translate_outputs(pt1,pt2): 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) # set CSS WE OE signal groups(in, out, bar)
pt1 = self.offset_msf_control pt1 = self.offset_msf_control
@ -197,21 +197,21 @@ class control_logic(design.design):
# clk , vdd # clk , vdd
base = self.offset_msf_control - vector(0.5 * drc["minwidth_metal2"], 0) 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 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 self.msf_control_vdd_position = base + msf_vdd
# gnd # gnd
self.msf_control_gnd_positions = [] self.msf_control_gnd_positions = []
for gnd_offset in self.msf_control.gnd_positions: for gnd_offset in self.msf_control.gnd_positions:
offset = self.offset_msf_control + vector(self.msf_control.height, offset = self.offset_msf_control + vector(self.msf_control.height,
- gnd_offset[0]) - gnd_offset.x)
self.msf_control_gnd_positions.append(offset - correct) self.msf_control_gnd_positions.append(offset - correct)
def add_1st_row(self,y_off): def add_1st_row(self,y_off):
# inv1 with clk as gate input. # 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.offset_inv1 = vector(msf_control_rotate_x - self.inv4.width, y_off)
self.add_inst(name="clk_inverter", self.add_inst(name="clk_inverter",
mod=self.inv4, mod=self.inv4,
@ -246,7 +246,7 @@ class control_logic(design.design):
self.set_nand2_nor2_pin("nand2",[1,1]) self.set_nand2_nor2_pin("nand2",[1,1])
# REPLICA BITLINE # 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 total_rail_gap = self.rail_offset_gap + self.overall_rail_2_gap
x_off = base_x + total_rail_gap + self.replica_bitline_gap x_off = base_x + total_rail_gap + self.replica_bitline_gap
self.offset_replica_bitline = vector(x_off, y_off) 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): def add_2nd_row(self, y_off):
# Nand3_1 input: OE, clk_bar,CS output: rblk_bar # 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", self.add_inst(name="NAND3_rblk_bar",
mod=self.NAND3, mod=self.NAND3,
offset=self.offset_nand3_1, 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]) self.set_Nand3_pins(nand_name = "nand3_1",nand_scale = [0,-1])
# Nand3_2 input: WE, clk_bar,CS output: w_en_bar # 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", self.add_inst(name="NAND3_w_en_bar",
mod=self.NAND3, mod=self.NAND3,
offset=self.offset_nand3_2, 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]) self.set_Nand3_pins(nand_name = "nand3_2",nand_scale = [0,1])
# connect nand2 and nand3 to inv # 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", self.add_rect(layer="metal1",
offset=self.nand3_1_Z_position, offset=self.nand3_1_Z_position,
width=drc["minwidth_metal1"], width=drc["minwidth_metal1"],
@ -315,7 +315,7 @@ class control_logic(design.design):
height=-nand3_to_inv_connection_height) height=-nand3_to_inv_connection_height)
# inv_2 input: rblk_bar, output: rblk # 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.offset_inv2 = vector(x_off, y_off)
self.add_inst(name="inv_rblk", self.add_inst(name="inv_rblk",
mod=self.inv, mod=self.inv,
@ -336,7 +336,7 @@ class control_logic(design.design):
self.set_inv2345_pins(inv_name="inv3", inv_scale=[1, 1]) self.set_inv2345_pins(inv_name="inv3", inv_scale=[1, 1])
# BUFFER INVERTERS FOR W_EN # 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.offset_inv6 = vector(x_off, y_off)
self.add_inst(name="inv_w_en1", self.add_inst(name="inv_w_en1",
mod=self.inv, mod=self.inv,
@ -344,7 +344,7 @@ class control_logic(design.design):
mirror="RO") mirror="RO")
self.connect_inst(["pre_w_en", "pre_w_en1", "vdd", "gnd"]) 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.offset_inv7 = [x_off, y_off]
self.add_inst(name="inv_w_en2", self.add_inst(name="inv_w_en2",
mod=self.inv, mod=self.inv,
@ -392,7 +392,7 @@ class control_logic(design.design):
def add_msf_control_routing(self): def add_msf_control_routing(self):
# FIRST RAIL : MSF_CONTROL OUTPUT RAIL # 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) self.output_port_gap)
for i in range(self.num_rails_1): for i in range(self.num_rails_1):
correct = vector((i+1) * self.rail_offset_gap, 0) correct = vector((i+1) * self.rail_offset_gap, 0)
@ -401,18 +401,18 @@ class control_logic(design.design):
offset=offset, offset=offset,
width=drc["minwidth_metal2"], width=drc["minwidth_metal2"],
height=self.logic_height) 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) + 3 * self.inv.width + self.rail_offset_gap)
for i in range(self.num_rails_2): for i in range(self.num_rails_2):
offset = [rail2_start_x + i * self.rail_offset_gap, offset = vector(rail2_start_x + i * self.rail_offset_gap,
self.output_port_gap] self.output_port_gap)
self.add_rect(layer="metal2", self.add_rect(layer="metal2",
offset=offset, offset=offset,
width=drc["minwidth_metal2"], width=drc["minwidth_metal2"],
height=self.logic_height) 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): def add_1st_row_routing(self):
# First rail routing left # First rail routing left
@ -425,7 +425,7 @@ class control_logic(design.design):
line_x_offset = self.rail_1_x_offsets[line_indices[i]] line_x_offset = self.rail_1_x_offsets[line_indices[i]]
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=offset, offset=offset,
width=line_x_offset - offset[0] + drc["minwidth_metal2"], width=line_x_offset - offset.x + drc["minwidth_metal2"],
height=drc["minwidth_metal1"]) height=drc["minwidth_metal1"])
correct1 = vector(self.gap_between_rails, - self.via_shift) correct1 = vector(self.gap_between_rails, - self.via_shift)
correct2 = vector(self.contact_shift + drc["minwidth_metal2"],0) 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]) base = vector(line_x_offset, offset[1])
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=base, offset=base,
width=offset[0] - line_x_offset, width=offset.x - line_x_offset,
height=drc["minwidth_metal1"]) height=drc["minwidth_metal1"])
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=base + correct1, offset=base + correct1,
@ -459,18 +459,21 @@ class control_logic(design.design):
# OE_bar [Bus # 1] to nor2 B input # OE_bar [Bus # 1] to nor2 B input
layer_stack = ("metal2", "via1", "metal1") layer_stack = ("metal2", "via1", "metal1")
start = self.nor2_1_B_position start = self.nor2_1_B_position
mid1 = [self.nor2_1_B_position[0] + 2 * drc["minwidth_metal2"], start[1]] mid1 = vector(self.nor2_1_B_position.x+ 2 * drc["minwidth_metal2"],
mid2 = [mid1[0], self.nor2_1_gnd_position[1] - 2 * drc["minwidth_metal1"]] start.y)
mid3 = [self.rail_1_x_offsets[1] + 0.5 * drc["minwidth_metal2"], mid2[1]] mid2 = vector(mid1.x,
end = [mid3[0], self.output_port_gap] 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]) self.add_wire(layer_stack, [start, mid1, mid2, mid3, end])
layer_stack = ("metal1") layer_stack = ("metal1")
start = [self.inv1_Z_position[0], self.inv1_Z_position[1] + 0.5 * drc["minwidth_metal1"]] start = self.inv1_Z_position+ vector(0, + 0.5 * drc["minwidth_metal1"])
mid1 = [start[0] + drc["minwidth_metal2"], start[1]] mid1 = start + vector(drc["minwidth_metal2"], 0)
mid2 = [mid1[0], self.nand2_1_B_position mid2 = vector(mid1.x,
[1] + 0.5 * drc["minwidth_metal1"]] self.nand2_1_B_position.y + 0.5 * drc["minwidth_metal1"])
end = [self.nand2_1_B_position[0], mid2[1]] end = [self.nand2_1_B_position.x, mid2.y]
self.add_path(layer_stack, [start, mid1, mid2, end]) self.add_path(layer_stack, [start, mid1, mid2, end])
def add_2nd_row_routing(self): 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]] line_x_offset = self.rail_2_x_offsets[line_indices[i]]
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=offset, offset=offset,
width=line_x_offset - offset[0] + drc["minwidth_metal2"], width=line_x_offset - offset.x+ drc["minwidth_metal2"],
height=drc["minwidth_metal1"]) height=drc["minwidth_metal1"])
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=[line_x_offset + self.gap_between_rails, offset=[line_x_offset + self.gap_between_rails,
offset[1] - self.via_shift], offset.y- self.via_shift],
rotate=90) rotate=90)
# Replica bitline (rblk to replica bitline input) # Replica bitline (rblk to replica bitline input)
layer_stack = ("metal2", "via1", "metal1") layer_stack = ("metal2", "via1", "metal1")
start = [self.rail_2_x_offsets[1] + 0.5 * drc["minwidth_metal2"], start = vector(self.rail_2_x_offsets[1] + 0.5 * drc["minwidth_metal2"],
self.output_port_gap] self.output_port_gap)
mid1 = [start[0], 0.5 * drc["minwidth_metal1"]] mid1 = vector(start.x, 0.5 * drc["minwidth_metal1"])
end = [self.replica_en_offset[0], mid1[1]] end = vector(self.replica_en_offset.x, mid1.y)
self.add_wire(layer_stack, [start, mid1, end]) 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", self.add_rect(layer="metal1",
offset=end - vector([0.5 * drc["minwidth_metal1"]] * 2), 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) end = self.replica_out_offset - vector(0.5 * drc["minwidth_metal1"],0)
self.add_rect(layer="metal3", self.add_rect(layer="metal3",
offset=start, 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"]) height=drc["minwidth_metal3"])
self.add_via(layers=("metal2", "via2", "metal3"), self.add_via(layers=("metal2", "via2", "metal3"),
offset=start) offset=start)
@ -536,7 +539,7 @@ class control_logic(design.design):
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=self.nand3_2_vdd_position, offset=self.nand3_2_vdd_position,
width=(rail_2_x + drc["minwidth_metal2"] width=(rail_2_x + drc["minwidth_metal2"]
- self.nand3_2_vdd_position[0]), - self.nand3_2_vdd_position.x),
height=drc["minwidth_metal1"]) height=drc["minwidth_metal1"])
# Connection in horizontal metal2 vdd rail # Connection in horizontal metal2 vdd rail
@ -551,10 +554,10 @@ class control_logic(design.design):
# Connection of msf_vdd to inv1 vdd # Connection of msf_vdd to inv1 vdd
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=[self.msf_control_vdd_position[0], offset=[self.msf_control_vdd_position.x,
self.inv1_vdd_position[1]], self.inv1_vdd_position[1]],
width=drc["minwidth_metal1"], 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"]) 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: for gnd_offset in self.msf_control_gnd_positions:
self.add_rect(layer="metal2", self.add_rect(layer="metal2",
offset=gnd_offset, 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"]), + drc["minwidth_metal2"]),
height=drc["minwidth_metal2"]) height=drc["minwidth_metal2"])
# Connect msf_control gnd to nand3 gnd # Connect msf_control gnd to nand3 gnd
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=self.nor2_1_gnd_position, offset=self.nor2_1_gnd_position,
width=self.offset_replica_bitline[0], width=self.offset_replica_bitline.x,
height=drc["minwidth_metal1"]) height=drc["minwidth_metal1"])
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=[self.rail_1_x_offsets[0] + self.gap_between_rails, 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) rotate=90)
# nand3 gnd to replica bitline gnd # nand3 gnd to replica bitline gnd
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=self.nand3_2_gnd_position, offset=self.nand3_2_gnd_position,
width=(self.offset_replica_bitline[0] width=(self.offset_replica_bitline.x
- self.nand3_2_gnd_position[0]), - self.nand3_2_gnd_position.x),
height=drc["minwidth_metal1"]) height=drc["minwidth_metal1"])
def add_input_routing(self): def add_input_routing(self):
@ -598,13 +601,13 @@ class control_logic(design.design):
self.OEb_position = self.msf_control_OEb_position self.OEb_position = self.msf_control_OEb_position
# Clk # 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) self.clk_position = vector(0, clk_y)
# clk port to inv1 A # clk port to inv1 A
layer_stack = ("metal2", "via1", "metal1") layer_stack = ("metal2", "via1", "metal1")
start = self.inv1_A_position + vector(0, 0.5 * drc["minwidth_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) start.y)
mid2 = vector(mid1.x, clk_y) mid2 = vector(mid1.x, clk_y)
self.clk_position = vector(0, mid2[1]) self.clk_position = vector(0, mid2[1])
@ -614,17 +617,17 @@ class control_logic(design.design):
# clk line to msf_control_clk # clk line to msf_control_clk
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=[self.msf_control_clk_position[0], offset=[self.msf_control_clk_position.x,
self.clk_position[1]], self.clk_position[1]],
width=drc["minwidth_metal1"], width=drc["minwidth_metal1"],
height=(self.msf_control_clk_position[1] height=(self.msf_control_clk_position.y
- self.clk_position[1])) - self.clk_position[1]))
# clk connection to nor2 A input # clk connection to nor2 A input
start = [self.inv1_A_position[0] - 2 * drc["minwidth_metal2"], start = self.inv1_A_position + vector(- 2 * drc["minwidth_metal2"],
self.inv1_A_position[1] + 0.5 * drc["minwidth_metal1"]] 0.5 * drc["minwidth_metal1"])
mid1 = [start[0] - 3 * drc["minwidth_metal2"], start[1]] mid1 = start - vector(3 * drc["minwidth_metal2"], 0)
mid2 = [mid1[0], self.nor2_1_A_position[1]] mid2 = [mid1.x, self.nor2_1_A_position.y]
self.add_path("metal1", [start, mid1, mid2, self.nor2_1_A_position]) 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) height=self.nor2_1_Z_position.y + correct.y)
self.add_via(layers=("metal2", "via2", "metal3"), self.add_via(layers=("metal2", "via2", "metal3"),
offset=self.nor2_1_Z_position.scale(1, 0)) 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 # tri_en_bar
correct = vector(drc["minwidth_metal2"], 0) correct = vector(drc["minwidth_metal2"], 0)
@ -671,7 +674,7 @@ class control_logic(design.design):
self.add_rect(layer="metal2", self.add_rect(layer="metal2",
offset=self.tri_en_bar_position, offset=self.tri_en_bar_position,
width=drc["minwidth_metal2"], 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"), self.add_via(layers=("metal2", "via2", "metal3"),
offset=self.tri_en_bar_position) offset=self.tri_en_bar_position)
@ -691,6 +694,6 @@ class control_logic(design.design):
self.add_rect(layer="metal2", self.add_rect(layer="metal2",
offset=self.s_en_position, offset=self.s_en_position,
width=drc["minwidth_metal2"], 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"), self.add_via(layers=("metal2", "via2", "metal3"),
offset=self.s_en_position) 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 tech
import debug import debug
from utils import snap_to_grid from utils import snap_to_grid
from vector import vector
class geometry: class geometry:
""" """
@ -37,7 +38,7 @@ class instance(geometry):
self.mod = mod self.mod = mod
self.gds = mod.gds self.gds = mod.gds
self.rotate = rotate self.rotate = rotate
self.offset = snap_to_grid(offset) self.offset = vector(snap_to_grid(offset))
self.mirror = mirror self.mirror = mirror
@ -104,7 +105,7 @@ class label(geometry):
self.name = "label" self.name = "label"
self.text = text self.text = text
self.layerNumber = layerNumber self.layerNumber = layerNumber
self.offset = snap_to_grid(offset) self.offset = vector(snap_to_grid(offset))
self.zoom = zoom self.zoom = zoom
self.size = 0 self.size = 0
@ -134,7 +135,7 @@ class rectangle(geometry):
geometry.__init__(self) geometry.__init__(self)
self.name = "rect" self.name = "rect"
self.layerNumber = layerNumber self.layerNumber = layerNumber
self.offset = snap_to_grid(offset) self.offset = vector(snap_to_grid(offset))
self.size = snap_to_grid([width, height]) self.size = snap_to_grid([width, height])
self.width = self.size[0] self.width = self.size[0]
self.height = self.size[1] 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 # ADDING LABELS FOR OUTPUT SIDE OF THE 3:8 PRE-DECODER
for inv_3x8 in range(8): for inv_3x8 in range(8):
if (self.num_inputs == 3): 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: else:
xoffset = 0 xoffset = 0
@ -403,7 +403,7 @@ class hierarchical_decoder(design.design):
mirror=mirror) mirror=mirror)
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=[nand.width - correct, 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"], width=drc["minwidth_metal1"],
height=y_dir * 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. # add output label for Row Decoder INVERTER array.
if (self.num_inputs == 4 or self.num_inputs == 5): 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: 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): for row in range(self.rows):
if ((row % 2) == 0): if ((row % 2) == 0):
@ -502,10 +502,10 @@ class hierarchical_decoder(design.design):
+ inv_2x4 * (self.inv.height)) + inv_2x4 * (self.inv.height))
if (inv_2x4 % 2 == 0): if (inv_2x4 % 2 == 0):
pin_y = self.inv.Z_position[1] pin_y = self.inv.Z_position.y
else: else:
pin_y = (self.inv.height - drc["minwidth_metal1"] pin_y = (self.inv.height - drc["minwidth_metal1"]
- self.inv.Z_position[1]) - self.inv.Z_position.y)
yoffset = current_inv_height + pin_y yoffset = current_inv_height + pin_y
self.add_extend_rails(yoffset = yoffset, self.add_extend_rails(yoffset = yoffset,
@ -519,10 +519,10 @@ class hierarchical_decoder(design.design):
+ self.no_of_pre2x4 * self.pre2_4.height + self.no_of_pre2x4 * self.pre2_4.height
if (inv_3x8 % 2 == 0): if (inv_3x8 % 2 == 0):
pin_y = self.inv.Z_position[1] pin_y = self.inv.Z_position.y
else: else:
pin_y = (self.inv.height - drc["minwidth_metal1"] pin_y = (self.inv.height - drc["minwidth_metal1"]
- self.inv.Z_position[1]) - self.inv.Z_position.y)
yoffset = current_inv_height + pin_y yoffset = current_inv_height + pin_y
self.add_extend_rails(yoffset = yoffset, 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) current_inv_height = self.predecoder_height + row_index * (self.inv.height)
if (row_index % 2 == 0): if (row_index % 2 == 0):
yoffset_A = current_inv_height + self.nand2.A_position[1] yoffset_A = current_inv_height + self.nand2.A_position.y
yoffset_B = current_inv_height + self.nand2.B_position[1] yoffset_B = current_inv_height + self.nand2.B_position.y
else: else:
base = current_inv_height + self.inv.height - drc["minwidth_metal1"] base = current_inv_height + self.inv.height - drc["minwidth_metal1"]
yoffset_A = base - self.nand2.A_position[1] yoffset_A = base - self.nand2.A_position.y
yoffset_B = base - self.nand2.B_position[1] yoffset_B = base - self.nand2.B_position.y
row_index = row_index + 1 row_index = row_index + 1
self.add_extend_rails(yoffset =yoffset_A, 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) current_inv_height = self.predecoder_height + row_index * (self.inv.height)
if (row_index % 2 == 0): if (row_index % 2 == 0):
yoffset_A = current_inv_height + self.nand3.A_position[1] yoffset_A = current_inv_height + self.nand3.A_position.y
yoffset_B = current_inv_height + self.nand3.B_position[1] yoffset_B = current_inv_height + self.nand3.B_position.y
yoffset_C = current_inv_height + self.nand3.C_position[1] yoffset_C = current_inv_height + self.nand3.C_position.y
contact_C_yoffset = yoffset_C - self.contact_shift contact_C_yoffset = yoffset_C - self.contact_shift
else: else:
base = current_inv_height + self.inv.height - drc["minwidth_metal1"] base = current_inv_height + self.inv.height - drc["minwidth_metal1"]
yoffset_A = base - self.nand3.A_position[1] yoffset_A = base - self.nand3.A_position.y
yoffset_B = base - self.nand3.B_position[1] yoffset_B = base - self.nand3.B_position.y
yoffset_C = base - self.nand3.C_position[1] yoffset_C = base - self.nand3.C_position.y
contact_C_yoffset = yoffset_C contact_C_yoffset = yoffset_C
row_index = row_index + 1 row_index = row_index + 1

View File

@ -150,12 +150,12 @@ class hierarchical_predecode(design.design):
y_off = nand_input * (self.nand.height) y_off = nand_input * (self.nand.height)
mirror = "R0" mirror = "R0"
offset = [self.x_off_nand + self.nand.width, offset = [self.x_off_nand + self.nand.width,
y_off + self.nand.Z_position[1]] y_off + self.nand.Z_position.y]
else: else:
y_off = (nand_input + 1) * (self.nand.height) y_off = (nand_input + 1) * (self.nand.height)
mirror = "MX" mirror = "MX"
offset =[self.x_off_nand + self.nand.width, 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, self.add_inst(name=name,
mod=self.nand, mod=self.nand,
offset=[self.x_off_nand, y_off], 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): def route_input_inverters_input(self,inv_rout,inv_in_offset):
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=[self.rails_x_offset[inv_rout], offset=[self.rails_x_offset[inv_rout],
inv_in_offset[1]], inv_in_offset.y],
width=inv_in_offset[0] - self.rails_x_offset[inv_rout] + drc["minwidth_metal2"], width=inv_in_offset.x - self.rails_x_offset[inv_rout] + drc["minwidth_metal2"],
height=drc["minwidth_metal1"]) height=drc["minwidth_metal1"])
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=[self.rails_x_offset[inv_rout] + self.gap_between_rails, 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) rotate=90)
def route_input_inverters_vdd(self,inv_vdd_offset): def route_input_inverters_vdd(self,inv_vdd_offset):
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=inv_vdd_offset, 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"]) height=drc["minwidth_metal1"])
def route_input_inverters_gnd(self,inv_gnd_offset): def route_input_inverters_gnd(self,inv_gnd_offset):
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=inv_gnd_offset, 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"]) 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_in_offset = base + self.inv.A_position.scale(1,y_dir)
inv_vdd_offset = base + self.inv.vdd_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) 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_y_mirrored = inv_vdd_offset.y+ output_shift + drc["minwidth_metal1"]
out_offset = [inv_out_offset[0], out_offset = [inv_out_offset.x,
inv_out_offset[1] * (1 + y_dir) / 2 inv_out_offset.y* (1 + y_dir) / 2
+ out_y_mirrored * (1 - y_dir) / 2] + out_y_mirrored * (1 - y_dir) / 2]
# output connection # output connection
correct = y_dir * (output_shift + drc["minwidth_metal1"]) correct = y_dir * (output_shift + drc["minwidth_metal1"])
off_via = [self.rails_x_offset[inv_rout + 4] + self.gap_between_rails, 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", self.add_rect(layer="metal1",
offset=out_offset, offset=out_offset,
width=drc["minwidth_metal1"], 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", self.add_rect(layer="metal1",
offset=[inv_out_offset[0], offset=[inv_out_offset.x,
inv_vdd_offset[1] - correct], inv_vdd_offset.y- correct],
width=self.rails_x_offset[inv_rout + 4] - inv_out_offset[0] + drc["minwidth_metal2"], width=self.rails_x_offset[inv_rout + 4] - inv_out_offset.x+ drc["minwidth_metal2"],
height=drc["minwidth_metal1"]) height=drc["minwidth_metal1"])
self.add_via(layers = ("metal1", "via1", "metal2"), self.add_via(layers = ("metal1", "via1", "metal2"),
offset=off_via, offset=off_via,

View File

@ -49,11 +49,11 @@ class hierarchical_predecode3x8(hierarchical_predecode):
# output connection # output connection
correct = y_dir * (output_shift + drc["minwidth_metal1"]) correct = y_dir * (output_shift + drc["minwidth_metal1"])
off_via = [self.rails_x_offset[inv_rout + 5] + self.gap_between_rails, off_via = [self.rails_x_offset[inv_rout + 5] + self.gap_between_rails,
inv_vdd_offset[1] - self.via_shift - correct] inv_vdd_offset.y - self.via_shift - correct]
path1 = vector(inv_out_offset[0] + 0.5*drc["minwidth_metal1"], path1 = inv_out_offset + vector(0.5*drc["minwidth_metal1"],
inv_out_offset[1]- 1.5*drc["minwidth_metal1"] - correct) - 1.5*drc["minwidth_metal1"] - correct)
path2 = vector(path1.x, 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"], path3 = vector(self.rails_x_offset[inv_rout + 5] + drc["minwidth_metal2"],
path2.y) path2.y)
self.add_path("metal1", [path1,path2,path3]) 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*** #***1,000,000 number is used to avoid empty sequences errors***
# FIXME Is this hard coded value ok?? # FIXME Is this hard coded value ok??
try: try:
lowestx1 = min(rect.offset[0] for rect in self.objs) lowestx1 = min(rect.offset.x for rect in self.objs)
lowesty1 = min(rect.offset[1] for rect in self.objs) lowesty1 = min(rect.offset.y for rect in self.objs)
except: except:
[lowestx1, lowesty1] = [1000000.0, 1000000.0] [lowestx1, lowesty1] = [1000000.0, 1000000.0]
try: try:
lowestx2 = min(inst.offset[0] for inst in self.insts) lowestx2 = min(inst.offset.x for inst in self.insts)
lowesty2 = min(inst.offset[1] for inst in self.insts) lowesty2 = min(inst.offset.y for inst in self.insts)
except: except:
[lowestx2, lowesty2] = [1000000.0, 1000000.0] [lowestx2, lowesty2] = [1000000.0, 1000000.0]
return vector(min(lowestx1, lowestx2), min(lowesty1, lowesty2)) return vector(min(lowestx1, lowestx2), min(lowesty1, lowesty2))
@ -77,21 +77,18 @@ class layout:
for i in range(len(attr_val)): for i in range(len(attr_val)):
# each unit in the list is a list coordinates # each unit in the list is a list coordinates
if isinstance(attr_val[i], (list,vector)): if isinstance(attr_val[i], (list,vector)):
attr_val[i] = vector([attr_val[i][0] - coordinate.x, attr_val[i] = vector(attr_val[i] - coordinate)
attr_val[i][1] - coordinate.y])
# the list itself is a coordinate # the list itself is a coordinate
else: else:
if len(attr_val)!=2: continue if len(attr_val)!=2: continue
for val in attr_val: for val in attr_val:
if not isinstance(val, (int, long, float)): continue if not isinstance(val, (int, long, float)): continue
setattr(self,attr_key, vector([attr_val[0] - coordinate.x, setattr(self,attr_key, vector(attr_val - coordinate))
attr_val[1] - coordinate.y]))
break break
# if is a vector coordinate # if is a vector coordinate
if isinstance(attr_val, vector): if isinstance(attr_val, vector):
setattr(self, attr_key, vector(attr_val[0] - coordinate.x, setattr(self, attr_key, vector(attr_val - coordinate))
attr_val[1] - coordinate.y))
@ -99,11 +96,9 @@ class layout:
"""Translates all 2d cartesian coordinates in a layout given """Translates all 2d cartesian coordinates in a layout given
the (x,y) offset""" the (x,y) offset"""
for obj in self.objs: for obj in self.objs:
obj.offset = snap_to_grid([obj.offset[0] - coordinate.x, obj.offset = vector(snap_to_grid(obj.offset - coordinate))
obj.offset[1] - coordinate.y])
for inst in self.insts: for inst in self.insts:
inst.offset = snap_to_grid([inst.offset[0] - coordinate.x, inst.offset = vector(snap_to_grid(inst.offset - coordinate))
inst.offset[1] - coordinate.y])
# FIXME: Make name optional and pick a random one if not specified # 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): 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: if end_inv < half_length:
end_i_offset = end_inv_offset + \ end_i_offset = end_inv_offset + \
self.inv.input_position.scale(1,-1) 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: else:
end_i_offset = end_inv_offset + \ end_i_offset = end_inv_offset + \
self.inv.input_position.scale(-1,1) 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: if start_inv < half_length and end_inv >= half_length:
mid = [half_length * self.inv.width \ mid = [half_length * self.inv.width \

View File

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

View File

@ -99,7 +99,7 @@ class nand_3(design.design):
def setup_layout_constants(self): def setup_layout_constants(self):
""" setup layout constraints """ """ 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"] \ + 3 * self.pmos1.active_width + drc["active_to_body_active"] \
+ drc["well_enclosure_active"] - self.nmos3.active_contact.width \ + drc["well_enclosure_active"] - self.nmos3.active_contact.width \
+ self.pmos1.active_contact.height + drc["minwidth_metal1"] \ + 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 # determines the spacing between the edge and pmos
self.edge_to_pmos = max(drc["metal1_to_metal1"] 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"] 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.height - 0.5 * drc["minwidth_metal1"]
- self.pmos1.height - self.edge_to_pmos) - self.pmos1.height - self.edge_to_pmos)
self.add_inst(name="pmos1", self.add_inst(name="pmos1",
@ -216,10 +216,10 @@ class nand_3(design.design):
def connect_well_contacts(self): def connect_well_contacts(self):
""" Connect well contacts to vdd and gnd rail """ """ 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[0] xoffset = (self.nwell_contact_position.x
+ self.nwell_contact.second_layer_position[0] + self.nwell_contact.second_layer_position.x
- self.nwell_contact.first_layer_position[0]) - self.nwell_contact.first_layer_position.x)
offset = [xoffset, self.nwell_contact_position.y] offset = [xoffset, self.nwell_contact_position.y]
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=offset, offset=offset,
@ -240,14 +240,14 @@ class nand_3(design.design):
correct = vector(self.pmos1.active_contact.width - drc["minwidth_metal1"], correct = vector(self.pmos1.active_contact.width - drc["minwidth_metal1"],
0).scale(0.5,0) 0).scale(0.5,0)
poffset = self.pmos_position1 + self.pmos1.active_contact_positions[0] + correct 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", self.add_rect(layer="metal1",
offset=poffset, offset=poffset,
width=drc["minwidth_metal1"], width=drc["minwidth_metal1"],
height=temp_height) height=temp_height)
poffset = [self.pmos_position3.x + self.pmos3.active_contact_positions[0].x + correct.x, poffset = [self.pmos_position3.x + self.pmos3.active_contact_positions[0].x + correct.x,
poffset[1]] poffset.y]
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=poffset, offset=poffset,
width=drc["minwidth_metal1"], 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 poly_length = (self.pmos_position1.y + self.pmos1.poly_positions[0].y
- yoffset_nmos1 + drc["minwidth_poly"]) - yoffset_nmos1 + drc["minwidth_poly"])
offset = [self.nmos_position1[0] + self.nmos1.poly_positions[0][0], offset = vector(self.nmos_position1.x + self.nmos1.poly_positions[0].x,
yoffset_nmos1 - drc["minwidth_poly"]] yoffset_nmos1 - drc["minwidth_poly"])
self.add_rect(layer="poly", self.add_rect(layer="poly",
offset=offset, offset=offset,
width=drc["minwidth_poly"], width=drc["minwidth_poly"],
height=poly_length) height=poly_length)
self.add_rect(layer="poly", self.add_rect(layer="poly",
offset=[offset[0] + self.pmos1.active_contact.width + 2 * drc["minwidth_poly"], offset=[offset.x + self.pmos1.active_contact.width + 2 * drc["minwidth_poly"],
offset[1]], offset.y],
width=drc["minwidth_poly"], width=drc["minwidth_poly"],
height=poly_length) height=poly_length)
self.add_rect(layer="poly", self.add_rect(layer="poly",
offset=[offset[0] + 2 * self.pmos1.active_contact.width + 4 * drc["minwidth_poly"], offset=[offset.x + 2 * self.pmos1.active_contact.width + 4 * drc["minwidth_poly"],
offset[1]], offset.y],
width=drc["minwidth_poly"], width=drc["minwidth_poly"],
height=poly_length) height=poly_length)
@ -294,7 +294,7 @@ class nand_3(design.design):
- drc["well_enclosure_active"] - drc["well_enclosure_active"]
+ drc["metal1_to_metal1"]) + drc["metal1_to_metal1"])
drain_length = (self.height - yoffset + 0.5 * drc["minwidth_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") layer_stack = ("metal1", "via1", "metal2")
for position in self.pmos1.active_contact_positions[1:][::2]: for position in self.pmos1.active_contact_positions[1:][::2]:
diff_active_via = self.pmos2.active_contact.width - self.m1m2_via.second_layer_width 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) + diff_active_via / 2)
self.add_via(layer_stack,[xoffset,offset.y]) 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.nmos3.active_width - self.nmos3.active_contact.width / 2)
self.drain_position = vector(xoffset, self.drain_position = vector(xoffset,
drc["minwidth_metal1"] + drc["metal1_to_metal1"]) drc["minwidth_metal1"] + drc["metal1_to_metal1"])
@ -343,11 +343,11 @@ class nand_3(design.design):
rotate=90) rotate=90)
self.add_rect(layer="poly", self.add_rect(layer="poly",
offset=offset + vector(drc["minwidth_poly"] / 2,0), 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) height=self.poly_contact.first_layer_width)
offset = vector(offset.x, 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", self.add_layout_pin(text="A",
layer="metal1", layer="metal1",
offset=offset, offset=offset,
@ -358,9 +358,9 @@ class nand_3(design.design):
def route_input_gate_B(self): def route_input_gate_B(self):
""" routing for input B """ """ routing for input B """
xoffset = self.pmos2.poly_positions[0][0] \ xoffset = self.pmos2.poly_positions[0].x \
+ self.pmos_position2[0] - drc["minwidth_poly"] + self.pmos_position2.x - drc["minwidth_poly"]
yoffset = self.nmos_position1[1] + self.nmos1.height \ yoffset = self.nmos_position1.y + self.nmos1.height \
- drc["well_enclosure_active"] + (self.nmos1.active_contact.height \ - drc["well_enclosure_active"] + (self.nmos1.active_contact.height \
- self.nmos1.active_height) / 2 \ - self.nmos1.active_height) / 2 \
+ drc["metal1_to_metal1"] + drc["metal1_to_metal1"]
@ -369,7 +369,7 @@ class nand_3(design.design):
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=[xoffset,yoffset]) 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 - drc["minwidth_poly"] + self.m1m2_via.width
length = -xoffset + self.m1m2_via.width length = -xoffset + self.m1m2_via.width
self.add_rect(layer="metal2", self.add_rect(layer="metal2",
@ -382,7 +382,7 @@ class nand_3(design.design):
layer="metal1", layer="metal1",
offset=self.B_position) 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 \ - drc["metal1_to_metal1"] + (self.pmos1.active_contact.width \
- self.m1m2_via.second_layer_width) / 2 - self.m1m2_via.second_layer_width) / 2
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
@ -395,9 +395,9 @@ class nand_3(design.design):
def route_input_gate_C(self): def route_input_gate_C(self):
""" routing for input A """ """ routing for input A """
xoffset = self.pmos3.poly_positions[0][0] \ xoffset = self.pmos3.poly_positions[0].x \
+ self.pmos_position3[0] - drc["minwidth_poly"] + self.pmos_position3.x - drc["minwidth_poly"]
yoffset = self.nmos_position1[1] + self.nmos1.height \ yoffset = self.nmos_position1.y + self.nmos1.height \
- drc["well_enclosure_active"] + (self.nmos1.active_contact.height \ - drc["well_enclosure_active"] + (self.nmos1.active_contact.height \
- self.nmos1.active_height) / 2 + drc["metal1_to_metal1"] - 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"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=[xoffset,yoffset]) offset=[xoffset,yoffset])
xoffset = self.pmos3.poly_positions[0][0] \ xoffset = self.pmos3.poly_positions[0].x \
+ self.pmos_position3[0] - drc["minwidth_poly"] \ + self.pmos_position3.x - drc["minwidth_poly"] \
+ self.m1m2_via.width + self.m1m2_via.width
length = -xoffset + self.m1m2_via.width length = -xoffset + self.m1m2_via.width
self.add_rect(layer="metal2", self.add_rect(layer="metal2",
@ -423,14 +423,14 @@ class nand_3(design.design):
width=self.m1m2_via.width, width=self.m1m2_via.width,
height=-drc["minwidth_metal2"] - drc["metal2_to_metal2"]) height=-drc["minwidth_metal2"] - drc["metal2_to_metal2"])
self.C_position = vector(0, 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.second_layer_width
- self.m1m2_via.first_layer_width)) - self.m1m2_via.first_layer_width))
self.add_label(text="C", self.add_label(text="C",
layer="metal1", layer="metal1",
offset=self.C_position) 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 \ - drc["metal1_to_metal1"] + (self.pmos1.active_contact.width \
- self.m1m2_via.second_layer_width) / 2 - self.m1m2_via.second_layer_width) / 2
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
@ -445,7 +445,7 @@ class nand_3(design.design):
def route_output(self): def route_output(self):
""" routing for output Z """ """ 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 + self.nmos3.active_width - self.nmos3.active_contact.width / 2
yoffset = (self.nmos1.height + (self.height - drc["minwidth_metal1"] yoffset = (self.nmos1.height + (self.height - drc["minwidth_metal1"]
- self.pmos1.height - self.nmos1.height) / 2 - self.pmos1.height - self.nmos1.height) / 2
@ -463,11 +463,11 @@ class nand_3(design.design):
def extend_wells(self): def extend_wells(self):
""" extension of well """ """ extension of well """
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.nmos1.well_height + (self.pmos_position1.y
+ self.pmos1.nwell_position[1] + self.pmos1.nwell_position.y
- self.nmos_position1[1] - self.nmos_position1.y
- self.nmos1.pwell_position[1] - self.nmos1.pwell_position.y
- self.nmos1.well_height) / 2 - self.nmos1.well_height) / 2
offset = self.nwell_position = vector(0, middle_point) offset = self.nwell_position = vector(0, middle_point)
self.nwell_height = self.height - middle_point self.nwell_height = self.height - middle_point
@ -508,9 +508,9 @@ class nand_3(design.design):
width=width, width=width,
height=self.pmos1.active_height) height=self.pmos1.active_height)
offset = [self.nmos_position3[0] + self.nmos1.active_position[0], offset = [self.nmos_position3.x + self.nmos1.active_position.x,
self.nmos_position1[1] + self.nmos1.height self.nmos_position1.y + self.nmos1.height
- self.nmos1.active_position[1] - self.nmos1.active_height] - self.nmos1.active_position.y - self.nmos1.active_height]
self.add_rect(layer="active", self.add_rect(layer="active",
offset=offset, offset=offset,
width=self.active_width, 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) 0.5 * gate_to_gate - test_pmos.poly_positions[0].y)
route_margin = .5 * (self.poly_contact.second_layer_width route_margin = .5 * (self.poly_contact.second_layer_width
+ drc["minwidth_metal1"]) + drc["metal1_to_metal1"] + drc["minwidth_metal1"]) + drc["metal1_to_metal1"]
pmos_position = [0, self.height - 0.5 * drc["minwidth_metal1"] pmos_position = vector(0, self.height - 0.5 * drc["minwidth_metal1"]
- edge_to_pmos - test_pmos.height] - edge_to_pmos - test_pmos.height)
nmos_position = [0, 0.5 * drc["minwidth_metal1"] + edge_to_nmos] nmos_position = vector(0, 0.5 * drc["minwidth_metal1"] + edge_to_nmos)
leftspace = (0.7 * (pmos_position[1] - nmos_position[1]) leftspace = (0.7 * (pmos_position.y - nmos_position.y)
- 3 * route_margin - 2 * drc["metal1_to_metal1"]) - 3 * route_margin - 2 * drc["metal1_to_metal1"])
if leftspace >= 0: if leftspace >= 0:
break break
@ -209,10 +209,10 @@ class nor_2(design.design):
self.nwell_contact_position = vector(xoffset, yoffset) 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)) 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 + self.nmos1.active_width
+ drc["active_to_body_active"]) + 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_positions[0].y
- self.nmos1.active_contact.height) - self.nmos1.active_contact.height)
self.pwell_contact_position = vector(xoffset, yoffset) self.pwell_contact_position = vector(xoffset, yoffset)
@ -222,7 +222,7 @@ class nor_2(design.design):
def route(self): def route(self):
self.route_pins() self.route_pins()
self.connect_well_contacts() 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 + .5 * (self.poly_contact.second_layer_width
+ drc["minwidth_metal1"])) + drc["minwidth_metal1"]))
self.connect_tx(M1_track) self.connect_tx(M1_track)
@ -230,11 +230,11 @@ class nor_2(design.design):
def connect_well_contacts(self): def connect_well_contacts(self):
""" Connect well contacts to vdd and gnd rail """ """ 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 xoffset = (self.nwell_contact_position.x
+ self.nwell_contact.second_layer_position.x + self.nwell_contact.second_layer_position.x
- self.nwell_contact.first_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", self.add_rect(layer="metal1",
offset=offset, offset=offset,
width=drc["minwidth_metal1"], width=drc["minwidth_metal1"],
@ -243,7 +243,7 @@ class nor_2(design.design):
offset = (self.pwell_contact_position.scale(1,0) offset = (self.pwell_contact_position.scale(1,0)
+ self.pwell_contact.second_layer_position.scale(1,0) + self.pwell_contact.second_layer_position.scale(1,0)
- self.pwell_contact.first_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", self.add_rect(layer="metal1",
offset=offset, offset=offset,
width=drc["minwidth_metal1"], width=drc["minwidth_metal1"],
@ -257,7 +257,7 @@ class nor_2(design.design):
if i % 2 == 0: if i % 2 == 0:
correct = self.pmos1.active_contact.second_layer_position.scale(1,0) correct = self.pmos1.active_contact.second_layer_position.scale(1,0)
drain_posistion = contact_pos + correct 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", self.add_rect(layer="metal1",
offset=drain_posistion, offset=drain_posistion,
width=drc["minwidth_metal1"], width=drc["minwidth_metal1"],
@ -268,7 +268,7 @@ class nor_2(design.design):
+ vector(self.pmos1.active_contact.second_layer_width, + vector(self.pmos1.active_contact.second_layer_width,
0).scale(.5,0)) 0).scale(.5,0))
source_position = contact_pos + correct 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]) self.add_path("metal1", [source_position, mid])
# the second pmos # the second pmos
@ -279,13 +279,13 @@ class nor_2(design.design):
correct= (self.pmos2.active_contact.second_layer_position.scale(1,0) correct= (self.pmos2.active_contact.second_layer_position.scale(1,0)
+ vector(0.5 * self.pmos2.active_contact.second_layer_width,0)) + vector(0.5 * self.pmos2.active_contact.second_layer_width,0))
source_position = pmos_active + correct 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]) self.add_path("metal1", [source_position, mid])
# two nmos source to gnd # two nmos source to gnd
source_posistion1 = (self.nmos_position1 source_posistion1 = (self.nmos_position1
+ self.nmos1.active_contact_positions[0] + self.nmos1.active_contact_positions[0]
+ self.nmos1.active_contact.second_layer_position.scale(1,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", self.add_rect(layer="metal1",
offset=source_posistion1, offset=source_posistion1,
width=drc["minwidth_metal1"], width=drc["minwidth_metal1"],
@ -294,7 +294,7 @@ class nor_2(design.design):
source_posistion2 = (self.nmos_position2 source_posistion2 = (self.nmos_position2
+ self.nmos2.active_contact_positions[1] + self.nmos2.active_contact_positions[1]
+ self.nmos2.active_contact.second_layer_position.scale(1,0)) + 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", self.add_rect(layer="metal1",
offset=source_posistion2, offset=source_posistion2,
width=drc["minwidth_metal1"], width=drc["minwidth_metal1"],
@ -310,22 +310,22 @@ class nor_2(design.design):
pmos_gate = (self.pmos_position1 pmos_gate = (self.pmos_position1
+ self.pmos1.poly_positions[i] + self.pmos1.poly_positions[i]
+ vector(0.5 * drc["minwidth_poly"], 0)) + 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]) self.add_path("poly", [nmos_gate, mid1, pmos_gate])
# connect pmos2 poly # connect pmos2 poly
nmos_gate = [self.nmos_position2[0] \ nmos_gate = vector(self.nmos_position2[0]
+ self.nmos2.poly_positions[0][0] + self.nmos2.poly_positions[0].x
+ 0.5 * drc["minwidth_poly"], \ + 0.5 * drc["minwidth_poly"],
self.nmos_position1[1] \ self.nmos_position1.y
+ self.nmos1.poly_positions[0][1]] + self.nmos1.poly_positions[0].y)
for i in range(len(self.pmos2.poly_positions)): for i in range(len(self.pmos2.poly_positions)):
pmos_gate = (self.pmos_position2 pmos_gate = (self.pmos_position2
+ self.pmos2.poly_positions[i] + self.pmos2.poly_positions[i]
+ vector(0.5 * drc["minwidth_poly"], 0)) + vector(0.5 * drc["minwidth_poly"], 0))
mid1 = [pmos_gate[0], mid1 = vector(pmos_gate.x,
nmos_gate[1] + self.nmos2.height \ nmos_gate.y + self.nmos2.height
+ drc["poly_to_active"]] + drc["poly_to_active"])
self.add_path("poly", [nmos_gate, mid1, pmos_gate]) self.add_path("poly", [nmos_gate, mid1, pmos_gate])
def route_pins(self): def route_pins(self):
@ -350,15 +350,15 @@ class nor_2(design.design):
rotate=90) rotate=90)
# connect gate input to tx gate # 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) 0.5 * self.poly_contact.width)
self.add_rect(layer="poly", self.add_rect(layer="poly",
offset=offset, 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) height=self.poly_contact.first_layer_width)
# extend the metal to the boundary of the cell # extend the metal to the boundary of the cell
input_length = self.A_position[0] input_length = self.A_position.x
offset = [0, self.A_position[1] - 0.5 * drc["minwidth_metal1"]] offset = [0, self.A_position.y - 0.5 * drc["minwidth_metal1"]]
self.add_layout_pin(text="A", self.add_layout_pin(text="A",
layer="metal1", layer="metal1",
offset=offset, offset=offset,
@ -367,9 +367,9 @@ class nor_2(design.design):
def route_input_B(self): def route_input_B(self):
"""create input B layout """ """create input B layout """
xoffset = self.pmos2.poly_positions[0][0] \ xoffset = self.pmos2.poly_positions[0].x \
+ self.pmos_position2[0] + self.pmos_position2.x
yoffset = self.A_position[1] \ yoffset = self.A_position.y \
+ 0.5 * (self.poly_contact.second_layer_width \ + 0.5 * (self.poly_contact.second_layer_width \
+ drc["minwidth_metal1"]) + drc["metal1_to_metal1"] + drc["minwidth_metal1"]) + drc["metal1_to_metal1"]
self.B_position = vector(xoffset, yoffset) self.B_position = vector(xoffset, yoffset)
@ -380,13 +380,13 @@ class nor_2(design.design):
self.add_rect(layer="poly", self.add_rect(layer="poly",
offset=offset, 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) height=self.poly_contact.first_layer_width)
self.add_layout_pin(text="B", self.add_layout_pin(text="B",
layer="metal1", layer="metal1",
offset=[0, offset=[0,
self.B_position[1] - 0.5 * drc["minwidth_metal1"]], self.B_position.y - 0.5 * drc["minwidth_metal1"]],
width=self.B_position[0], width=self.B_position.x,
height=drc["minwidth_metal1"]) height=drc["minwidth_metal1"])
def route_output(self): def route_output(self):
@ -398,7 +398,7 @@ class nor_2(design.design):
+ self.nmos1.active_contact.second_layer_position + self.nmos1.active_contact.second_layer_position
+ vector(self.nmos1.active_contact.second_layer_width, + vector(self.nmos1.active_contact.second_layer_width,
0).scale(0.5, 0)) 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]) self.add_path("metal1", [self.Z_position, mid, nmos_contact])
for i in range(len(self.pmos2.poly_positions) + 1): 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) offset = pmos_contact - vector(0.5 * self.m1m2_via.width, 0)
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=offset) 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.add_wire(("metal2", "via1", "metal1"),
[self.Z_position, mid, pmos_contact]) [self.Z_position, mid, pmos_contact])
def extend_wells(self): def extend_wells(self):
""" extend well for well contact""" """ extend well for well contact"""
middle_point = (self.nmos_position1[1] middle_point = (self.nmos_position1.y
+ self.nmos1.pwell_position[1] + self.nmos1.pwell_position.y
+ self.nmos1.well_height + self.nmos1.well_height
+ (self.pmos_position1[1] + (self.pmos_position1.y
+ self.pmos1.nwell_position[1] + self.pmos1.nwell_position.y
- self.nmos_position1[1] - self.nmos_position1.y
- self.nmos1.pwell_position[1] - self.nmos1.pwell_position.y
- self.nmos1.well_height) / 2 ) - self.nmos1.well_height) / 2 )
self.nwell_position = vector(0, middle_point) self.nwell_position = vector(0, middle_point)
self.nwell_height = self.height - middle_point self.nwell_height = self.height - middle_point

View File

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

View File

@ -185,7 +185,7 @@ class precharge(design.design):
def add_vdd_rail(self): def add_vdd_rail(self):
"""Adds a vdd rail at the top of the cell""" """Adds a vdd rail at the top of the cell"""
# adds the rail across the width 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.height - drc["minwidth_metal1"])
self.add_layout_pin(text="vdd", self.add_layout_pin(text="vdd",
layer="metal1", 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. # 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? # 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), self.height = max(max(obj.offset.y + obj.height for obj in self.objs),
max(inst.offset[1] + inst.mod.height for inst in self.insts)) max(inst.offset.y + inst.mod.height for inst in self.insts))
self.width = max(max(obj.offset[0] + obj.width for obj in self.objs), self.width = max(max(obj.offset.x + obj.width for obj in self.objs),
max(inst.offset[0] + inst.mod.width for inst in self.insts)) max(inst.offset.x + inst.mod.width for inst in self.insts))
def create_spice(self): def create_spice(self):
self.spice.append("\n.SUBCKT {0} {1}".format(self.name, 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"], self.mults_poly_to_poly = max(2 * drc["contact_to_poly"] + drc["minwidth_contact"],
drc["poly_to_poly"]) drc["poly_to_poly"])
outeractive_to_contact = max(drc["active_enclosure_contact"], outeractive_to_contact = max(drc["active_enclosure_contact"],
(drc["minwidth_active"] - drc["minwidth_contact"]) / 2) (drc["minwidth_active"] - drc["minwidth_contact"]) / 2)
self.active_width = 2 * (outeractive_to_contact \ self.active_width = (2 * (outeractive_to_contact + drc["minwidth_contact"]
+ drc["minwidth_contact"] \ + drc["contact_to_poly"])
+ drc["contact_to_poly"]) \ + drc["minwidth_poly"]
+ drc["minwidth_poly"] \ + (self.mults - 1) * (self.mults_poly_to_poly
+ (self.mults - 1) * ( + drc["minwidth_poly"]))
self.mults_poly_to_poly + drc["minwidth_poly"])
self.active_height = max(drc["minarea_active"] / self.active_width, 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_width = drc["minwidth_poly"] # horizontal
self.poly_height = max(drc["minarea_poly"] / self.poly_width, self.poly_height = max(drc["minarea_poly"] / self.poly_width,
self.gate_width \ self.gate_width
+ 2 * drc["poly_extend_active"]) # vertical + 2 * drc["poly_extend_active"]) # vertical
self.well_width = self.active_width \ self.well_width = (self.active_width
+ 2 * (drc["well_enclosure_active"]) + 2 * (drc["well_enclosure_active"]))
self.well_height = max(self.gate_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): def connect_fingered_poly(self):
poly_connect_length = self.poly_positions[-1][0] + self.poly_width \ poly_connect_length = self.poly_positions[-1].x + self.poly_width \
- self.poly_positions[0][0] - self.poly_positions[0].x
poly_connect_position = [self.poly_positions[0][0], poly_connect_position = self.poly_positions[0] - vector(0, self.poly_width)
self.poly_positions[0][1] - self.poly_width]
if len(self.poly_positions) > 1: if len(self.poly_positions) > 1:
self.add_rect(layer="poly", self.add_rect(layer="poly",
offset=poly_connect_position, offset=poly_connect_position,
@ -127,8 +125,8 @@ class ptx(design.design):
drc["minwidth_metal1"] + drc["minwidth_contact"]), drc["minwidth_metal1"] + drc["minwidth_contact"]),
0.5 * (self.active_contact.height - drc["minwidth_contact"]) 0.5 * (self.active_contact.height - drc["minwidth_contact"])
- drc["metal1_extend_contact"]) - drc["metal1_extend_contact"])
connected=vector(b[0] + drc["minwidth_metal1"], connected=vector(b.x + drc["minwidth_metal1"],
a[1] + self.active_contact.height + drc["metal1_to_metal1"]) a.y + self.active_contact.height + drc["metal1_to_metal1"])
self.source_positions.append(a + correct) self.source_positions.append(a + correct)
self.source_positions.append(vector(a.x + correct.x, connected.y)) self.source_positions.append(vector(a.x + correct.x, connected.y))
self.source_positions.append(vector(b.x + correct.x, self.source_positions.append(vector(b.x + correct.x,
@ -144,10 +142,10 @@ class ptx(design.design):
+ drc["minwidth_contact"]), + drc["minwidth_contact"]),
0.5*(self.active_contact.height - drc["minwidth_contact"]) 0.5*(self.active_contact.height - drc["minwidth_contact"])
- drc["metal1_extend_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 + correct))
self.drain_positions.append(vector(c[0] + correct.x, connected.y)) self.drain_positions.append(vector(c.x + correct.x, connected.y))
self.drain_positions.append(vector(d[0] + correct.x, self.drain_positions.append(vector(d.x + correct.x,
connected.y - 0.5 * drc["minwidth_metal1"])) connected.y - 0.5 * drc["minwidth_metal1"]))
self.drain_positions.append(vector(d + correct)) self.drain_positions.append(vector(d + correct))
@ -165,7 +163,7 @@ class ptx(design.design):
def add_poly(self): def add_poly(self):
# left_most poly # 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"] + drc["minwidth_contact"] + drc["contact_to_poly"]
poly_yoffset = -drc["poly_extend_active"] poly_yoffset = -drc["poly_extend_active"]
self.poly_positions = [] self.poly_positions = []
@ -255,10 +253,10 @@ class ptx(design.design):
# middle contact columns # middle contact columns
for i in range(self.mults - 1): 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) \ + (self.mults_poly_to_poly / 2) \
- (drc["minwidth_contact"] / 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) offset = vector(contact_xoffset, contact_yoffset)
self.add_contact(layers=("active", "contact", "metal1"), self.add_contact(layers=("active", "contact", "metal1"),
offset=offset, offset=offset,
@ -267,9 +265,9 @@ class ptx(design.design):
self.active_contact_positions.append(offset) self.active_contact_positions.append(offset)
# right_most contact column # 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.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) offset = vector(contact_xoffset, contact_yoffset)
self.add_contact(layers=("active", "contact", "metal1"), self.add_contact(layers=("active", "contact", "metal1"),
offset=offset, offset=offset,

View File

@ -68,7 +68,8 @@ class replica_bitline(design.design):
self.inv.height * 0.5) self.inv.height * 0.5)
self.replica_bitline_offset = vector(self.delay_chain_offset.x self.replica_bitline_offset = vector(self.delay_chain_offset.x
+ bitcell_array_spacing, + 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.delay_inv_offset = vector(self.delay_chain_offset.x - self.inv.width,
self.inv.height * 2) 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_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"]) 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 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.create_input()
self.route_BL_t_BL_inv(BL_offset, BL_inv_in) 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_vdd()
self.route_gnd() self.route_gnd()
# route loads after gnd and vdd created # route loads after gnd and vdd created
self.route_loads() self.route_loads(vdd_offset)
self.route_RC() self.route_RC(vdd_offset)
def create_input(self): def create_input(self):
# create routing module based on module offset # create routing module based on module offset
correct = vector(0.5 * drc["minwidth_metal1"], 0) 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 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_path("metal1", [self.en_input_offset, mid1, input_offset])
self.add_label(text="en", self.add_label(text="en",
layer="metal1", layer="metal1",
offset=self.en_input_offset) 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): def route_BL_t_BL_inv(self, BL_offset, BL_inv_in):
# BL_inv input to M3 # BL_inv input to M3
mid1 = [BL_inv_in[0], mid1 = BL_inv_in - vector(0,
BL_inv_in[1] - drc["metal2_to_metal2"] - self.m1m2_via.width] drc["metal2_to_metal2"] + self.m1m2_via.width)
mid2 = [self.en_nor_offset[0] + 3*drc["metal1_to_metal1"], mid2 = vector(self.en_nor_offset.x + 3 * drc["metal1_to_metal1"],
mid1[1]] mid1.y)
mid3 = [mid2[0], mid3 = vector(mid2.x,
self.replica_bitline_offset[1] - self.replica_bitcell.height self.replica_bitline_offset.y - self.replica_bitcell.height
- 0.5 * (self.m1m2_via.height + drc["metal1_to_metal1"]) - 0.5 * (self.m1m2_via.height + drc["metal1_to_metal1"])
- 2 * drc["metal1_to_metal1"]] - 2 * drc["metal1_to_metal1"])
self.add_wire(("metal1", "via1", "metal2"), self.add_wire(layers=("metal1", "via1", "metal2"),
[BL_inv_in, mid1, mid2, mid3]) coordinates=[BL_inv_in, mid1, mid2, mid3])
# need to fix the mid point as this is done with two wire # need to fix the mid point as this is done with two wire
# this seems to cover the metal1 error of the wire # this seems to cover the metal1 error of the wire
@ -246,18 +232,18 @@ class replica_bitline(design.design):
width=drc["minwidth_metal1"], width=drc["minwidth_metal1"],
height=drc["minwidth_metal1"]) height=drc["minwidth_metal1"])
mid4 = [BL_offset[0], mid3[1]] mid4 = [BL_offset.x, mid3.y]
self.add_wire(("metal2", "via1", "metal1"), self.add_wire(layers=("metal2", "via1", "metal1"),
[BL_offset, mid4, mid3]) 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_gate(delay_chain_output)
self.route_tx_drain() self.route_tx_drain(vdd_offset)
self.route_tx_source(BL_inv_in) self.route_tx_source(BL_inv_in)
def route_tx_gate(self, delay_chain_output): def route_tx_gate(self, delay_chain_output):
# gate input for access tx # 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) + self.access_tx_offset)
width = -6 * drc["minwidth_metal1"] width = -6 * drc["minwidth_metal1"]
self.add_rect(layer="poly", 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): def route_access_tx_t_delay_chain(self, offset, delay_chain_output):
m2rail_space = (drc["minwidth_metal2"] + drc["metal2_to_metal2"]) m2rail_space = (drc["minwidth_metal2"] + drc["metal2_to_metal2"])
mid1 = [offset[0], self.delay_chain_offset[1] - 3 * m2rail_space] mid1 = vector(offset.x, self.delay_chain_offset.y - 3 * m2rail_space)
mid2 = [delay_chain_output[0], mid1[1]] mid2 = [delay_chain_output.x, mid1.y]
# Note the inverted wire stack # Note the inverted wire stack
self.add_wire(("metal2", "via1", "metal1"), self.add_wire(layers=("metal2", "via1", "metal1"),
[offset, mid1, mid2, delay_chain_output]) coordinates=[offset, mid1, mid2, delay_chain_output])
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=delay_chain_output, offset=delay_chain_output,
mirror="MX") mirror="MX")
def route_access_tx_t_WL(self, offset): def route_access_tx_t_WL(self, offset):
m1m2_via_offset = offset - vector(0.5 * self.m1m2_via.width, 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"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=m1m2_via_offset) offset=m1m2_via_offset)
# route gate to RC WL # route gate to RC WL
RC_WL = self.replica_bitline_offset - vector(0,1).scale(self.bitcell_chars["WL"]) RC_WL = self.replica_bitline_offset - vector(0,1).scale(self.bitcell_chars["WL"])
mid1 = [offset[0], 0] mid1 = vector(offset.x, 0)
mid2 = [self.en_nor_offset[0] + 3 * drc["metal1_to_metal1"], mid2 = vector(self.en_nor_offset.x + 3 * drc["metal1_to_metal1"],
mid1[1]] mid1.y)
mid3 = [RC_WL[0] - drc["minwidth_metal1"] - self.m1m2_via.height, mid3 = vector(RC_WL.x - drc["minwidth_metal1"] - self.m1m2_via.height,
mid1[1]] mid1.y)
mid4 = [mid3[0], RC_WL[1]] mid4 = vector(mid3.x, RC_WL.y)
self.add_path("metal2", [offset, mid1, mid2, mid3, mid4]) self.add_path("metal2", [offset, mid1, mid2, mid3, mid4])
offset = mid4 - vector([0.5 * drc["minwidth_metal1"]]*2) offset = mid4 - vector([0.5 * drc["minwidth_metal1"]] * 2)
width = RC_WL[0] - offset[0] width = RC_WL.x - offset.x
# enter the bit line array with metal1 # enter the bit line array with metal1
via_offset = [mid4[0] - 0.5 * self.m1m2_via.width, via_offset = [mid4.x - 0.5 * self.m1m2_via.width,
offset[1] - 0.5 * (self.m1m2_via.height offset.y
- 0.5 * (self.m1m2_via.height
- drc["minwidth_metal1"])] - drc["minwidth_metal1"])]
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=via_offset) offset=via_offset)
@ -313,26 +300,24 @@ class replica_bitline(design.design):
width=width, width=width,
height=drc["minwidth_metal1"]) height=drc["minwidth_metal1"])
def route_tx_drain(self): def route_tx_drain(self,vdd_offset):
# route drain to Vdd # route drain to Vdd
active_offset = self.access_tx.active_contact_positions[1].rotate().scale(-1,1) active_offset = self.access_tx.active_contact_positions[1].rotate_scale(-1,1)
correct = vector(drc["minwidth_metal1"], correct = vector(-0.5 * drc["minwidth_metal1"],
self.access_tx.active_contact.width).scale(-0.5, 0.5) 0.5 * self.access_tx.active_contact.width)
drain_offset = self.access_tx_offset + active_offset + correct 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) close_Vdd_offset = self.BL_inv_offset + vector(0, self.inv.height)
self.add_path("metal1", [drain_offset, close_Vdd_offset]) self.add_path("metal1", [drain_offset, close_Vdd_offset])
mid = [vdd_rail[0], close_Vdd_offset[1]] mid = [vdd_offset.x, close_Vdd_offset.y]
self.add_wire(("metal2", "via1", "metal1"), self.add_wire(layers=("metal2", "via1", "metal1"),
[close_Vdd_offset, mid, vdd_rail]) coordinates=[close_Vdd_offset, mid, vdd_offset])
def route_tx_source(self, BL_inv_in): def route_tx_source(self, BL_inv_in):
# route source to BL inv input which is connected to BL # route source to BL inv input which is connected to BL
active_offset = self.access_tx.active_contact_positions[0].rotate().scale(-1,1) active_offset = self.access_tx.active_contact_positions[0].rotate_scale(-1,1)
correct = vector(drc["minwidth_metal1"], correct = vector(-0.5 * drc["minwidth_metal1"],
self.access_tx.active_contact.width).scale(-0.5, 0.5) 0.5 * self.access_tx.active_contact.width)
source_offset = self.access_tx_offset + active_offset + correct source_offset = self.access_tx_offset + active_offset + correct
self.add_path("metal1", [source_offset, BL_inv_in]) 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) start = self.delay_chain_offset - vector(0.5 * self.delay_chain.height, 0)
m1rail_space = (drc["minwidth_metal1"] + drc["metal1_to_metal1"]) m1rail_space = (drc["minwidth_metal1"] + drc["metal1_to_metal1"])
mid1 = start - vector(0, m1rail_space) mid1 = start - vector(0, m1rail_space)
mid2 = [self.delay_chain_offset[0] + 9 * drc["minwidth_metal2"], mid2 = vector(self.delay_chain_offset.x + 9 * drc["minwidth_metal2"],
mid1[1]] mid1.y)
end = [mid2[0], vdd_offset[1]] end = [mid2.x, vdd_offset.y]
self.add_path(("metal1"), [start, mid1, mid2]) self.add_path(layer=("metal1"),
self.add_wire(("metal2", "via1", "metal1"), [mid1, mid2, end]) coordinates=[start, mid1, mid2])
self.add_wire(layers=("metal2", "via1", "metal1"),
coordinates=[mid1, mid2, end])
def route_gnd(self): def route_gnd(self):
"""route gnd of delay chain, en_nor, en_inv and BL_inv""" """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) mid2 = vector(mid1.x, y_off)
share_gnd = vector(self.gnd_position.x, mid2.y) share_gnd = vector(self.gnd_position.x, mid2.y)
# Note the inverted stacks # Note the inverted stacks
self.add_wire(("metal2", "via1", "metal1"), lst = [BL_gnd_offset, mid1, mid2, share_gnd, self.gnd_position]
[BL_gnd_offset, mid1, mid2, share_gnd, self.gnd_position]) self.add_wire(layers=("metal2", "via1", "metal1"),
coordinates=lst)
self.add_label(text="gnd", self.add_label(text="gnd",
layer="metal1", layer="metal1",
offset=self.gnd_position) offset=self.gnd_position)
@ -377,51 +365,51 @@ class replica_bitline(design.design):
offset=offset, offset=offset,
width=drc["minwidth_metal1"], width=drc["minwidth_metal1"],
height=-self.delay_chain.width) height=-self.delay_chain.width)
offset = [offset[0] + self.delay_chain.height, offset = [offset.x + self.delay_chain.height,
mid2[1]] mid2.y]
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=offset, offset=offset,
width=drc["minwidth_metal1"], width=drc["minwidth_metal1"],
height=-self.delay_chain.width) height=-self.delay_chain.width)
def route_loads(self): def route_loads(self,vdd_offset):
"""connect all the loads word line to gnd""" """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"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=vdd_offset, offset=vdd_offset,
mirror="MX") mirror="MX")
gnd_offset = (self.delay_chain_offset 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): for i in range(self.rows):
WL_offset = (self.replica_bitline_offset WL_offset = (self.replica_bitline_offset
+ self.bitline_load.WL_positions[i].scale(0,1)) + self.bitline_load.WL_positions[i].scale(0,1))
mid = [self.delay_chain_offset[0] + 6 * drc["minwidth_metal2"], mid = [self.delay_chain_offset.x + 6 * drc["minwidth_metal2"],
gnd_offset[1]] gnd_offset.y]
self.add_wire(("metal2", "via1", "metal1"), [gnd_offset, mid, WL_offset]) self.add_wire(layers=("metal2", "via1", "metal1"),
coordinates=[gnd_offset, mid, WL_offset])
if i % 2 == 0: if i % 2 == 0:
load_vdd_offset = (self.replica_bitline_offset load_vdd_offset = (self.replica_bitline_offset
+ self.bitline_load.vdd_positions[i]) + self.bitline_load.vdd_positions[i])
mid = [vdd_offset[0], load_vdd_offset[1]] mid = [vdd_offset.x, load_vdd_offset.y]
self.add_wire(("metal2", "via1", "metal1"), [vdd_offset, mid, load_vdd_offset]) 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 """ """route vdd gnd to the replica cell """
# connect vdd # connect vdd
RC_vdd = self.replica_bitline_offset + vector(1,-1).scale(self.bitcell_chars["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"], mid = [vdd_offset.x, RC_vdd.y]
self.height]
mid = [vdd_offset[0], RC_vdd[1]]
# Note the inverted stacks # 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) gnd_offset = self.BL_inv_offset - vector(self.inv.width, 0)
load_gnd = (self.replica_bitline_offset load_gnd = self.replica_bitline_offset + vector(self.bitcell_chars["gnd"][0],
+ vector(self.bitcell_chars["gnd"][0], self.bitline_load.height)) self.bitline_load.height)
mid = [load_gnd[0], gnd_offset[1]] mid = [load_gnd.x, gnd_offset.y]
self.add_wire(("metal2", "via1", "metal1"), [gnd_offset, mid, load_gnd]) self.add_wire(layers=("metal2", "via1", "metal1"),
coordinates=[gnd_offset, mid, load_gnd])
load_gnd = (self.replica_bitline_offset load_gnd = self.replica_bitline_offset + vector(0,
+ vector(0, self.bitline_load.height)) self.bitline_load.height)
mid = [load_gnd[0], gnd_offset[1]] mid = [load_gnd.x, gnd_offset.y]
self.add_wire(("metal2", "via1", "metal1"), [gnd_offset, mid, load_gnd]) 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.poly_offset = (self.nmos1_position
+ self.nmos1.poly_positions[0] + self.nmos1.poly_positions[0]
+ vector(0,self.nmos1.poly_height)) + 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", self.poly = self.add_rect(layer="poly",
offset=self.poly_offset, offset=self.poly_offset,
width=width, width=width,
@ -91,7 +91,7 @@ class single_level_column_mux(design.design):
def connect_to_bitlines(self): def connect_to_bitlines(self):
offset = [self.nmos1.active_contact_positions[0].x + self.m1m2_via.contact_width / 2 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, + 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 offset = self.nmos1_position + offset
connection = vector(0, connection = vector(0,
self.nmos2.active_height+ 2 * drc["poly_extend_active"] \ self.nmos2.active_height+ 2 * drc["poly_extend_active"] \
@ -101,7 +101,7 @@ class single_level_column_mux(design.design):
width=drc["minwidth_metal2"], width=drc["minwidth_metal2"],
height=connection.y - 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) offset.y)
+ connection) + connection)
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
@ -116,10 +116,10 @@ class single_level_column_mux(design.design):
width=drc["minwidth_metal2"], width=drc["minwidth_metal2"],
height=2 * 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", self.add_rect(layer="metal2",
offset=[offset[0], offset=[offset[0],
self.BL_position[1] - 2*drc["minwidth_metal2"]], self.BL_position.y- 2*drc["minwidth_metal2"]],
width=width, width=width,
height=drc["minwidth_metal2"]) height=drc["minwidth_metal2"])
@ -127,24 +127,24 @@ class single_level_column_mux(design.design):
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=offset) offset=offset)
self.add_rect(layer="metal2", 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], 0],
width=drc["minwidth_metal2"], width=drc["minwidth_metal2"],
height=(drc["minwidth_metal2"] + offset[1])) height=(drc["minwidth_metal2"] + offset[1]))
self.add_rect(layer="metal2", 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]], 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"]), + 2 * drc["minwidth_metal2"]),
height=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) 0)
self.add_label(text="bl_out", self.add_label(text="bl_out",
layer="metal2", layer="metal2",
offset=self.BL_out_position) offset=self.BL_out_position)
offset = [self.nmos2.active_contact_positions[1].x - self.m1m2_via.contact_width / 2, 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 offset = self.nmos2_position + offset
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=offset, offset=offset,
@ -152,21 +152,21 @@ class single_level_column_mux(design.design):
mid = offset + vector(drc["minwidth_metal2"],0) mid = offset + vector(drc["minwidth_metal2"],0)
self.add_rect(layer="metal2", self.add_rect(layer="metal2",
offset= mid, 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"]) height=-drc["minwidth_metal2"])
self.add_rect(layer="metal2", self.add_rect(layer="metal2",
offset=[self.bitcell_chars["BR"][0] - 0.5*self.m1m2_via.width, offset=[self.bitcell_chars["BR"][0]- 0.5*self.m1m2_via.width,
offset[1] - drc["metal1_to_metal1"]], offset.y- drc["metal1_to_metal1"]],
width=drc["minwidth_metal2"], width=drc["minwidth_metal2"],
height=2*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.BL_position.y)
self.add_label(text="br", self.add_label(text="br",
layer="metal2", layer="metal2",
offset=self.BR_position) offset=self.BR_position)
offset = self.nmos2_position + self.nmos2.active_contact_positions[0] 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) 0)
self.add_label(text="br_out", self.add_label(text="br_out",
layer="metal2", layer="metal2",
@ -179,12 +179,12 @@ class single_level_column_mux(design.design):
height=drc["minwidth_metal2"]) height=drc["minwidth_metal2"])
self.add_rect(layer="metal2", self.add_rect(layer="metal2",
offset=[self.BR_out_position.x, offset=[self.BR_out_position.x,
offset[1] + drc["minwidth_metal2"]], offset.y+ drc["minwidth_metal2"]],
width=drc["minwidth_metal2"], width=drc["minwidth_metal2"],
height=-(offset[1] + drc["minwidth_metal2"])) height=-(offset.y+ drc["minwidth_metal2"]))
def add_gnd_rail(self): 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) 0)
self.add_layout_pin(text="gnd", self.add_layout_pin(text="gnd",
layer="metal2", layer="metal2",
@ -193,7 +193,7 @@ class single_level_column_mux(design.design):
height=self.BL_position[1]) height=self.BL_position[1])
def add_well_contacts(self): 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.nmos1.poly_height / 2)
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=offset - vector(self.m1m2_via.width / 2, 0), 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) offset_well = self.nmos1_position + vector(self.nmos1.width, 0)
self.add_rect(layer="pwell", self.add_rect(layer="pwell",
offset=offset_well, 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"]) height=self.nmos1.height + drc["minwidth_poly"])
self.add_rect(layer="vtg", self.add_rect(layer="vtg",
offset=offset_well, 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"]) height=self.nmos1.height + drc["minwidth_poly"])
def setup_layout_constants(self): 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.width = self.bank.width + self.control.height + 2*drc["minwidth_metal3"]
self.height = self.bank.height self.height = self.bank.height
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.CSb_position = (self.control.CSb_position.rotate_scale(-1,1)
+self.control_position) +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.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.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) +self.control_position)
for i in range(0, self.word_size): for i in range(0, self.word_size):
self.add_label(text="DATA[{0}]".format(i), self.add_label(text="DATA[{0}]".format(i),
@ -612,7 +612,7 @@ class sram(design.design):
bank_attr = self.sram_property[attr_index] bank_attr = self.sram_property[attr_index]
self.add_rect(layer="metal3", self.add_rect(layer="metal3",
offset=getattr(self,bank_attr)[left_bank_index], 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"]) height=drc["minwidth_metal3"])
self.add_via(layers=("metal2", "via2", "metal3"), self.add_via(layers=("metal2", "via2", "metal3"),
offset=[self.vertical_line_positions[attr_index].x, offset=[self.vertical_line_positions[attr_index].x,
@ -710,17 +710,17 @@ class sram(design.design):
# 0 = s_en # 0 = s_en
control_side = [] 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) + 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) + 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) + 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) + 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) + 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) + self.control_position)
bank_side = [] bank_side = []
@ -763,14 +763,14 @@ class sram(design.design):
msb_line = self.control_size + self.num_banks/2 - 1 - i msb_line = self.control_size + self.num_banks/2 - 1 - i
bank_select_start_line = msb_line + 2 + self.bank_addr_size 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) + self.msf_msb_address_position)
contact_pos = [self.vertical_line_positions[msb_line].x, contact_pos = vector(self.vertical_line_positions[msb_line].x,
msf_msb_din.y - 0.5*self.m2m3_via.width] msf_msb_din.y - 0.5*self.m2m3_via.width)
self.add_rect(layer="metal3", self.add_rect(layer="metal3",
offset=contact_pos, offset=contact_pos,
width=msf_msb_din[0] - contact_pos[0], width=msf_msb_din.x - contact_pos.x,
height=drc["minwidth_metal3"]) height=drc["minwidth_metal3"])
self.add_via(layers=("metal2", "via2", "metal3"), self.add_via(layers=("metal2", "via2", "metal3"),
offset=contact_pos) offset=contact_pos)
@ -785,9 +785,9 @@ class sram(design.design):
height=drc["minwidth_metal1"]) height=drc["minwidth_metal1"])
if(self.num_banks == 2): 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) + 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) + self.msf_msb_address_position)
starts = [msb_msf_dout_bar_position, starts = [msb_msf_dout_bar_position,
msb_msf_dout_position] msb_msf_dout_position]
@ -801,7 +801,7 @@ class sram(design.design):
+ self.msf_msb_address.height + self.msf_msb_address.height
+ 4 * (i + 1) * drc["minwidth_metal2"], + 4 * (i + 1) * drc["minwidth_metal2"],
start.y) 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"]) + 4 * (i + 1) * drc["minwidth_metal2"])
self.add_wire(("metal1", "via1", "metal2"), [start, mid1, end]) self.add_wire(("metal1", "via1", "metal2"), [start, mid1, end])
@ -818,7 +818,7 @@ class sram(design.design):
if(self.num_banks == 4): if(self.num_banks == 4):
for i in range(2): 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) + self.msf_msb_address_position)
msb_decoder_in_position =(self.msb_decoder.A_positions[i].scale(-1, 1) msb_decoder_in_position =(self.msb_decoder.A_positions[i].scale(-1, 1)
+ self.msb_decoder_position + self.msb_decoder_position
@ -827,7 +827,7 @@ class sram(design.design):
start = msb_msf_out_position start = msb_msf_out_position
mid1 = start + vector(4 * (i + 1) * drc["minwidth_metal1"], 0) mid1 = start + vector(4 * (i + 1) * drc["minwidth_metal1"], 0)
mid2 = vector(mid1.x, msb_decoder_in_position.y) 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"], + 3*drc["minwidth_metal3"],
mid2.y) mid2.y)
@ -874,9 +874,9 @@ class sram(design.design):
# control logic # control logic
self.control_vdd1_position = (self.control_position 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 = (self.control_position
+ self.control.vdd2_position.rotate().scale(-1, 1)) + self.control.vdd2_position.rotate_scale(-1, 1))
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=self.control_vdd1_position, offset=self.control_vdd1_position,
@ -974,7 +974,7 @@ class sram(design.design):
# msf_msb_address # msf_msb_address
start = msf_address_vdd_position = (self.msf_msb_address_position 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, mid1 = vector(start.x,
self.msf_msb_address_position.y self.msf_msb_address_position.y
- self.msf_msb_address.width - self.msf_msb_address.width
@ -1029,7 +1029,7 @@ class sram(design.design):
offset=self.gnd_offset) offset=self.gnd_offset)
self.control_gnd_position = (self.control_position 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)) + vector(drc["minwidth_metal2"],0))
self.add_rect(layer="metal3", self.add_rect(layer="metal3",
@ -1070,12 +1070,12 @@ class sram(design.design):
self.add_rect(layer="metal2", self.add_rect(layer="metal2",
offset=self.sram_bank_left_gnd_positions[0], offset=self.sram_bank_left_gnd_positions[0],
width=drc["minwidth_metal2"], 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.sram_bank_left_gnd_positions[0].y)
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=[self.sram_bank_left_gnd_positions[0].x offset=[self.sram_bank_left_gnd_positions[0].x
+ drc["minwidth_metal2"], + drc["minwidth_metal2"],
control_gnd_supply[1]], control_gnd_supply.y],
mirror="R90") mirror="R90")
# Control gnd # Control gnd
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),

View File

@ -92,3 +92,10 @@ class vector():
y_factor=x_factor[1] y_factor=x_factor[1]
x_factor=x_factor[0] x_factor=x_factor[0]
return vector(self.x*x_factor,self.y*y_factor) 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)