Fix ptx active contact orientation to non-default M1 direction.

This commit is contained in:
Matt Guthaus 2019-12-19 12:54:10 -08:00
parent 36cb675150
commit b7d78ec2ec
7 changed files with 20 additions and 31 deletions

View File

@ -388,19 +388,15 @@ class layout():
def get_preferred_direction(self, layer):
""" Return the preferred routing directions """
if layer in ["m1", "m3", "m5"]:
return "H"
elif layer in ["active", "poly", "li", "m2", "m4"]:
return "V"
else:
debug.error("Unable to find preferred direction for {}".format(layer))
from tech import preferred_directions
return preferred_directions[layer]
def add_via(self, layers, offset, size=[1,1], directions=None, implant_type=None, well_type=None):
""" Add a three layer via structure. """
if directions==None:
directions = (self.get_preferred_direction(layers[0]), self.get_preferred_direction(layers[2]))
directions = (self.get_preferred_direction(layers[0]),
self.get_preferred_direction(layers[2]))
from sram_factory import factory
via = factory.create(module_type="contact",
@ -421,7 +417,8 @@ class layout():
""" Add a three layer via structure by the center coordinate accounting for mirroring and rotation. """
if directions==None:
directions = (self.get_preferred_direction(layers[0]), self.get_preferred_direction(layers[2]))
directions = (self.get_preferred_direction(layers[0]),
self.get_preferred_direction(layers[2]))
from sram_factory import factory
via = factory.create(module_type="contact",

View File

@ -199,7 +199,6 @@ class pbitcell(bitcell_base.bitcell_base):
def calculate_spacing(self):
""" Calculate transistor spacings """
# calculate metal contact extensions over transistor active
readwrite_nmos_contact_extension = 0.5 * \
(self.readwrite_nmos.active_contact.height - self.readwrite_nmos.active_height)
@ -263,7 +262,7 @@ class pbitcell(bitcell_base.bitcell_base):
# spacing for vdd
implant_constraint = max(inverter_pmos_contact_extension, 0) \
+ 2 * self.implant_enclose_active \
+ 0.5 * (contact.activem1.width - self.m1_width)
+ 0.5*(self.inverter_pmos.active_contact.height - self.m1_width)
metal1_constraint = max(inverter_pmos_contact_extension, 0) + self.m1_space
self.vdd_offset = max(implant_constraint, metal1_constraint) + 0.5*self.m1_width
@ -367,11 +366,11 @@ class pbitcell(bitcell_base.bitcell_base):
self.add_path("m1",
[self.inverter_nmos_left.get_pin("D").uc(),
self.inverter_pmos_left.get_pin("D").bc()],
width=contact.activem1.second_layer_width)
width=self.inverter_nmos_left.get_pin("D").width())
self.add_path("m1",
[self.inverter_nmos_right.get_pin("S").uc(),
self.inverter_pmos_right.get_pin("S").bc()],
width=contact.activem1.second_layer_width)
width=self.inverter_nmos_right.get_pin("S").width())
# add contacts to connect gate poly to drain/source
# metal1 (to connect Q to Q_bar)

View File

@ -64,7 +64,7 @@ class pgate(design.design):
height=height,
width=source_pin.width())
def route_input_gate(self, pmos_inst, nmos_inst, ypos, name, position="left", rotate=False):
def route_input_gate(self, pmos_inst, nmos_inst, ypos, name, position="left"):
"""
Route the input gate to the left side of the cell for access.
Position specifies to place the contact the left, center, or
@ -87,16 +87,9 @@ class pgate(design.design):
left_gate_offset = vector(nmos_gate_pin.lx(), ypos)
# Center is completely symmetric.
if rotate:
contact_width = contact.polym1.height
contact_m1_width = contact.polym1.second_layer_height
contact_m1_height = contact.polym1.second_layer_width
directions = ("H", "V")
else:
contact_width = contact.polym1.width
contact_m1_width = contact.polym1.second_layer_width
contact_m1_height = contact.polym1.second_layer_height
directions = ("V", "H")
contact_width = contact.polym1.width
contact_m1_width = contact.polym1.second_layer_width
contact_m1_height = contact.polym1.second_layer_height
if position == "center":
contact_offset = left_gate_offset \
@ -115,16 +108,15 @@ class pgate(design.design):
# Non-preferred direction via
self.add_via_center(layers=self.poly_stack,
offset=contact_offset,
directions=directions)
v=self.add_via_center(layers=self.poly_stack,
offset=contact_offset,
directions = ("V", "H"))
self.add_layout_pin_rect_center(text=name,
layer="m1",
offset=contact_offset,
width=contact_m1_width,
height=contact_m1_height)
# This is to ensure that the contact is
# connected to the gate
mid_point = contact_offset.scale(0.5, 1) \

View File

@ -125,6 +125,7 @@ class ptx(design.design):
# This is not actually instantiated but used for calculations
self.active_contact = factory.create(module_type="contact",
layer_stack=self.active_stack,
directions = ("V", "V"),
dimensions=(1, self.num_contacts))

View File

@ -30,7 +30,7 @@ class contact_test(openram_test):
# Check single 1 x 1 contact"
debug.info(2, "1 x 1 {} test".format(stack_name))
c = factory.create(module_type="contact", layer_stack=layer_stack, dimensions=(1, 1))
c = factory.create(module_type="contact", layer_stack=layer_stack, dimensions=(1, 1), directions=("H", "H"))
self.local_drc_check(c)
# Check single 1 x 1 contact"

View File

@ -57,7 +57,7 @@ beol_stacks = [m1_stack,
layer_stacks = feol_stacks + beol_stacks
preferred_directions = {"poly": "V",
"active": "H",
"active": "V",
"m1": "H",
"m2": "V",
"m3": "H",

View File

@ -57,7 +57,7 @@ beol_stacks = [m1_stack,
layer_stacks = feol_stacks + beol_stacks
preferred_directions = {"poly": "V",
"active": "H",
"active": "V",
"m1": "H",
"m2": "V",
"m3": "H",