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

View File

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

View File

@ -64,7 +64,7 @@ class pgate(design.design):
height=height, height=height,
width=source_pin.width()) 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. Route the input gate to the left side of the cell for access.
Position specifies to place the contact the left, center, or 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) left_gate_offset = vector(nmos_gate_pin.lx(), ypos)
# Center is completely symmetric. # Center is completely symmetric.
if rotate: contact_width = contact.polym1.width
contact_width = contact.polym1.height contact_m1_width = contact.polym1.second_layer_width
contact_m1_width = contact.polym1.second_layer_height contact_m1_height = 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")
if position == "center": if position == "center":
contact_offset = left_gate_offset \ contact_offset = left_gate_offset \
@ -115,16 +108,15 @@ class pgate(design.design):
# Non-preferred direction via # Non-preferred direction via
self.add_via_center(layers=self.poly_stack, v=self.add_via_center(layers=self.poly_stack,
offset=contact_offset, offset=contact_offset,
directions=directions) directions = ("V", "H"))
self.add_layout_pin_rect_center(text=name, self.add_layout_pin_rect_center(text=name,
layer="m1", layer="m1",
offset=contact_offset, offset=contact_offset,
width=contact_m1_width, width=contact_m1_width,
height=contact_m1_height) height=contact_m1_height)
# This is to ensure that the contact is # This is to ensure that the contact is
# connected to the gate # connected to the gate
mid_point = contact_offset.scale(0.5, 1) \ 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 # This is not actually instantiated but used for calculations
self.active_contact = factory.create(module_type="contact", self.active_contact = factory.create(module_type="contact",
layer_stack=self.active_stack, layer_stack=self.active_stack,
directions = ("V", "V"),
dimensions=(1, self.num_contacts)) dimensions=(1, self.num_contacts))

View File

@ -30,7 +30,7 @@ class contact_test(openram_test):
# Check single 1 x 1 contact" # Check single 1 x 1 contact"
debug.info(2, "1 x 1 {} test".format(stack_name)) 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) self.local_drc_check(c)
# Check single 1 x 1 contact" # Check single 1 x 1 contact"

View File

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

View File

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