Fix single finger ptx bugs.

This commit is contained in:
Matt Guthaus 2017-11-30 11:56:40 -08:00
parent 6207f2157c
commit 0214cfb48e
6 changed files with 49 additions and 69 deletions

View File

@ -512,7 +512,7 @@ class bank(design.design):
bank_sel_line_pos = vector(xoffset_bank_sel + 0.5*self.m2_width, self.min_point) bank_sel_line_pos = vector(xoffset_bank_sel + 0.5*self.m2_width, self.min_point)
bank_sel_pin_pos=vector(self.left_vdd_x_offset, self.min_point) bank_sel_pin_pos=vector(self.left_vdd_x_offset, self.min_point)
self.add_center_layout_pin_segment(text="bank_sel", self.add_layout_pin_center_segment(text="bank_sel",
layer="metal3", layer="metal3",
start=bank_sel_pin_pos, start=bank_sel_pin_pos,
end=bank_sel_line_pos) end=bank_sel_line_pos)
@ -629,7 +629,7 @@ class bank(design.design):
offset=logic_pos, offset=logic_pos,
rotate=90) rotate=90)
self.add_center_layout_pin_segment(text=input_name, self.add_layout_pin_center_segment(text=input_name,
layer="metal3", layer="metal3",
start=input_pos, start=input_pos,
end=logic_pos) end=logic_pos)

View File

@ -174,7 +174,7 @@ class layout:
new_name = pin.name new_name = pin.name
self.add_layout_pin(new_name, pin.layer, pin.ll(), pin.width(), pin.height()) self.add_layout_pin(new_name, pin.layer, pin.ll(), pin.width(), pin.height())
def add_center_layout_pin_segment(self, text, layer, start, end): def add_layout_pin_center_segment(self, text, layer, start, end):
""" Creates a path like pin with center-line convention """ """ Creates a path like pin with center-line convention """
debug.check(start.x==end.x or start.y==end.y,"Cannot have a non-manhatten layout pin.") debug.check(start.x==end.x or start.y==end.y,"Cannot have a non-manhatten layout pin.")
@ -198,7 +198,7 @@ class layout:
return self.add_layout_pin(text, layer, ll_offset, width, height) return self.add_layout_pin(text, layer, ll_offset, width, height)
def add_center_layout_pin_rect(self, text, layer, offset, width=None, height=None): def add_layout_pin_center_rect(self, text, layer, offset, width=None, height=None):
""" Creates a path like pin with center-line convention """ """ Creates a path like pin with center-line convention """
if width==None: if width==None:
width=drc["minwidth_{0}".format(layer)] width=drc["minwidth_{0}".format(layer)]

View File

@ -142,6 +142,7 @@ class pinv(design.design):
connect_poly=True, connect_poly=True,
connect_active=True) connect_active=True)
self.add_mod(self.nmos) self.add_mod(self.nmos)
self.pmos = ptx(width=self.pmos_width, self.pmos = ptx(width=self.pmos_width,
mults=self.tx_mults, mults=self.tx_mults,
tx_type="pmos", tx_type="pmos",
@ -151,12 +152,12 @@ class pinv(design.design):
def add_supply_rails(self): def add_supply_rails(self):
""" Add vdd/gnd rails to the top and bottom. """ """ Add vdd/gnd rails to the top and bottom. """
self.add_center_layout_pin_rect(text="gnd", self.add_layout_pin_center_rect(text="gnd",
layer="metal1", layer="metal1",
offset=vector(0.5*self.width,0), offset=vector(0.5*self.width,0),
width=self.width) width=self.width)
self.add_center_layout_pin_rect(text="vdd", self.add_layout_pin_center_rect(text="vdd",
layer="metal1", layer="metal1",
offset=vector(0.5*self.width,self.height), offset=vector(0.5*self.width,self.height),
width=self.width) width=self.width)
@ -168,7 +169,6 @@ class pinv(design.design):
""" """
# place PMOS so it is half a poly spacing down from the top # place PMOS so it is half a poly spacing down from the top
# Source should overlap rail if it is fingered!
pmos_position = vector(0,self.height-self.pmos.height-0.5*drc["poly_to_poly"]) pmos_position = vector(0,self.height-self.pmos.height-0.5*drc["poly_to_poly"])
self.pmos_inst=self.add_inst(name="pinv_pmos", self.pmos_inst=self.add_inst(name="pinv_pmos",
mod=self.pmos, mod=self.pmos,
@ -176,7 +176,6 @@ class pinv(design.design):
self.connect_inst(["Z", "A", "vdd", "vdd"]) self.connect_inst(["Z", "A", "vdd", "vdd"])
# place NMOS so that it is half a poly spacing up from the bottom # place NMOS so that it is half a poly spacing up from the bottom
# Source should overlap rail if it is fingered!
nmos_position = vector(0,self.nmos.height+0.5*drc["poly_to_poly"]) nmos_position = vector(0,self.nmos.height+0.5*drc["poly_to_poly"])
self.nmos_inst=self.add_inst(name="pinv_nmos", self.nmos_inst=self.add_inst(name="pinv_nmos",
mod=self.nmos, mod=self.nmos,
@ -256,28 +255,28 @@ class pinv(design.design):
nmos_gate_pin = self.nmos_inst.get_pin("G") nmos_gate_pin = self.nmos_inst.get_pin("G")
pmos_gate_pin = self.pmos_inst.get_pin("G") pmos_gate_pin = self.pmos_inst.get_pin("G")
# Pick point in center of NMOS and connect down to PMOS # Pick point on the left of NMOS and connect down to PMOS
nmos_gate_pos = nmos_gate_pin.ll() + vector(0.5*drc["minwidth_poly"],0) nmos_gate_pos = nmos_gate_pin.ll() + vector(0.5*drc["minwidth_poly"],0)
pmos_gate_pos = vector(nmos_gate_pos.x,pmos_gate_pin.bc().y) pmos_gate_pos = vector(nmos_gate_pos.x,pmos_gate_pin.bc().y)
self.add_path("poly",[nmos_gate_pos,pmos_gate_pos]) self.add_path("poly",[nmos_gate_pos,pmos_gate_pos])
# The midpoint of the vertical poly gate # Add the via to the cell midpoint along the gate
mid_gate_offset = vector(nmos_gate_pos.x,self.middle_position.y) left_gate_offset = vector(nmos_gate_pin.lx(),self.middle_position.y)
contact_offset = mid_gate_offset - vector(0.5*self.poly_contact.height,0) contact_offset = left_gate_offset - vector(0.5*self.poly_contact.height,0)
self.add_center_contact(layers=("poly", "contact", "metal1"), self.add_center_contact(layers=("poly", "contact", "metal1"),
offset=contact_offset, offset=contact_offset,
rotate=90) rotate=90)
self.add_center_layout_pin_segment(text="A", self.add_layout_pin_center_segment(text="A",
layer="metal1", layer="metal1",
start=mid_gate_offset.scale(0,1), start=left_gate_offset.scale(0,1),
end=mid_gate_offset) end=left_gate_offset)
# This is to ensure that the contact is connected to the gate # This is to ensure that the contact is connected to the gate
mid_point = contact_offset.scale(0.5,1)+mid_gate_offset.scale(0.5,0) mid_point = contact_offset.scale(0.5,1)+left_gate_offset.scale(0.5,0)
self.add_center_rect(layer="poly", self.add_center_rect(layer="poly",
offset=mid_point, offset=mid_point,
height=self.poly_contact.first_layer_width, height=self.poly_contact.first_layer_width,
width=mid_gate_offset.x-contact_offset.x) width=left_gate_offset.x-contact_offset.x)
def route_output_drain(self): def route_output_drain(self):
@ -299,7 +298,7 @@ class pinv(design.design):
if self.route_output == True: if self.route_output == True:
# This extends the output to the edge of the cell # This extends the output to the edge of the cell
output_offset = mid_drain_offset.scale(0,1) + vector(self.width,0) output_offset = mid_drain_offset.scale(0,1) + vector(self.width,0)
self.add_center_layout_pin_segment(text="Z", self.add_layout_pin_center_segment(text="Z",
layer="metal1", layer="metal1",
start=mid_drain_offset, start=mid_drain_offset,
end=output_offset) end=output_offset)
@ -375,8 +374,8 @@ class pinv(design.design):
# Only if they don't overlap already # Only if they don't overlap already
if gnd_pin.uy() < nmos_source_pin.by(): if gnd_pin.uy() < nmos_source_pin.by():
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=nmos__pin.ll(), offset=nmos_source_pin.ll(),
height=nmos_source_pin.by()-gnd_pin.uy(), height=-1*nmos_source_pin.by(),
width=nmos_source_pin.width()) width=nmos_source_pin.width())
pmos_source_pin = self.pmos_inst.get_pin("S") pmos_source_pin = self.pmos_inst.get_pin("S")

View File

@ -47,9 +47,6 @@ class ptx(design.design):
# but this may be uncommented for debug purposes # but this may be uncommented for debug purposes
#self.DRC() #self.DRC()
def add_pins(self):
"""Adds pins for spice netlist"""
self.add_pin_list(["D", "G", "S", "B"])
def create_layout(self): def create_layout(self):
"""Calls all functions related to the generation of the layout""" """Calls all functions related to the generation of the layout"""
@ -60,7 +57,7 @@ class ptx(design.design):
self.add_active_contacts() self.add_active_contacts()
def create_spice(self): def create_spice(self):
self.add_pins() self.add_pin_list(["D", "G", "S", "B"])
self.spice.append("\n.SUBCKT {0} {1}".format(self.name, self.spice.append("\n.SUBCKT {0} {1}".format(self.name,
" ".join(self.pins))) " ".join(self.pins)))
@ -160,7 +157,7 @@ class ptx(design.design):
and we will add a single horizontal connection. and we will add a single horizontal connection.
""" """
# Nothing to do if there's one poly gate # Nothing to do if there's one poly gate
if len(poly_positions) == 1: if len(poly_positions)<2:
return return
# The width of the poly is from the left-most to right-most poly gate # The width of the poly is from the left-most to right-most poly gate
@ -190,24 +187,24 @@ class ptx(design.design):
# This is the width of a contact to extend the ends of the pin # This is the width of a contact to extend the ends of the pin
end_offset = vector(self.active_contact.second_layer_width/2,0) end_offset = vector(self.active_contact.second_layer_width/2,0)
if source_positions: # if not an empty set if len(source_positions)>1:
self.remove_layout_pin("S") # remove the individual connections self.remove_layout_pin("S") # remove the individual connections
# Add each vertical segment # Add each vertical segment
for a in source_positions: for a in source_positions:
self.add_path(("metal1"), [a,a+pin_offset]) self.add_path(("metal1"), [a,a+pin_offset])
# Add a single horizontal pin # Add a single horizontal pin
self.add_center_layout_pin_segment(text="S", self.add_layout_pin_center_segment(text="S",
layer="metal1", layer="metal1",
start=source_positions[0]+pin_offset-end_offset, start=source_positions[0]+pin_offset-end_offset,
end=source_positions[-1]+pin_offset+end_offset) end=source_positions[-1]+pin_offset+end_offset)
if drain_positions: # if not an empty set if len(drain_positions)>1:
self.remove_layout_pin("D") # remove the individual connections self.remove_layout_pin("D") # remove the individual connections
# Add each vertical segment # Add each vertical segment
for a in drain_positions: for a in drain_positions:
self.add_path(("metal1"), [a,a-pin_offset]) self.add_path(("metal1"), [a,a-pin_offset])
# Add a single horizontal pin # Add a single horizontal pin
self.add_center_layout_pin_segment(text="D", self.add_layout_pin_center_segment(text="D",
layer="metal1", layer="metal1",
start=drain_positions[0]-pin_offset-end_offset, start=drain_positions[0]-pin_offset-end_offset,
end=drain_positions[-1]-pin_offset+end_offset) end=drain_positions[-1]-pin_offset+end_offset)
@ -223,18 +220,16 @@ class ptx(design.design):
poly_positions = [] poly_positions = []
for i in range(0, self.mults): for i in range(0, self.mults):
if self.connect_poly: # Add this duplicate rectangle in case we remove the pin when joining fingers
# Add the rectangle in case we remove the pin when joining fingers self.add_center_rect(layer="poly",
self.add_center_rect(layer="poly", offset=poly_offset,
offset=poly_offset, height=self.poly_height,
height=self.poly_height, width=self.poly_width)
width=self.poly_width) self.add_layout_pin_center_rect(text="G",
else: layer="poly",
self.add_center_layout_pin_rect(text="G", offset=poly_offset,
layer="poly", height=self.poly_height,
offset=poly_offset, width=self.poly_width)
height=self.poly_height,
width=self.poly_width)
poly_positions.append(poly_offset) poly_positions.append(poly_offset)
poly_offset = poly_offset + vector(self.poly_pitch,0) poly_offset = poly_offset + vector(self.poly_pitch,0)
@ -306,36 +301,22 @@ class ptx(design.design):
contact=self.add_center_contact(layers=("active", "contact", "metal1"), contact=self.add_center_contact(layers=("active", "contact", "metal1"),
offset=pos, offset=pos,
size=(1, self.num_contacts)) size=(1, self.num_contacts))
if self.connect_active: self.add_layout_pin_center_rect(text="S",
# Add this in case the pins get removed when fingers joined layer="metal1",
self.add_center_rect(layer="metal1", offset=pos,
offset=pos, width=contact.second_layer_width,
width=contact.second_layer_width, height=contact.second_layer_height)
height=contact.second_layer_height)
else:
self.add_center_layout_pin_rect(text="S",
layer="metal1",
offset=pos,
width=contact.second_layer_width,
height=contact.second_layer_height)
for pos in drain_positions: for pos in drain_positions:
contact=self.add_center_contact(layers=("active", "contact", "metal1"), contact=self.add_center_contact(layers=("active", "contact", "metal1"),
offset=pos, offset=pos,
size=(1, self.num_contacts)) size=(1, self.num_contacts))
if self.connect_active: self.add_layout_pin_center_rect(text="D",
# Add this in case the pins get removed when fingers joined layer="metal1",
self.add_center_rect(layer="metal1", offset=pos,
offset=pos, width=contact.second_layer_width,
width=contact.second_layer_width, height=contact.second_layer_height)
height=contact.second_layer_height)
else:
self.add_center_layout_pin_rect(text="D",
layer="metal1",
offset=pos,
width=contact.second_layer_width,
height=contact.second_layer_height)
if self.connect_active: if self.connect_active:
self.connect_fingered_active(drain_positions, source_positions) self.connect_fingered_active(drain_positions, source_positions)

View File

@ -167,7 +167,7 @@ class wordline_driver(design.design):
input_offset = vector(0,a_pos.y) input_offset = vector(0,a_pos.y)
mid_via_offset = vector(clk_offset.x,a_pos.y) + vector(0.5*drc["minwidth_metal2"]+drc["metal2_to_metal2"]+0.5*m1m2_via.width,0) mid_via_offset = vector(clk_offset.x,a_pos.y) + vector(0.5*drc["minwidth_metal2"]+drc["metal2_to_metal2"]+0.5*m1m2_via.width,0)
# must under the clk line in M1 # must under the clk line in M1
self.add_center_layout_pin_segment(text="in[{0}]".format(row), self.add_layout_pin_center_segment(text="in[{0}]".format(row),
layer="metal1", layer="metal1",
start=input_offset, start=input_offset,
end=mid_via_offset) end=mid_via_offset)
@ -185,7 +185,7 @@ class wordline_driver(design.design):
# output each WL on the right # output each WL on the right
wl_offset = inv2_inst.get_pin("Z").rc() wl_offset = inv2_inst.get_pin("Z").rc()
self.add_center_layout_pin_segment(text="wl[{0}]".format(row), self.add_layout_pin_center_segment(text="wl[{0}]".format(row),
layer="metal1", layer="metal1",
start=wl_offset, start=wl_offset,
end=wl_offset-vector(drc["minwidth_metal1"],0)) end=wl_offset-vector(drc["minwidth_metal1"],0))