mirror of https://github.com/VLSIDA/OpenRAM.git
Fix ptx active contact orientation to non-default M1 direction.
This commit is contained in:
parent
36cb675150
commit
b7d78ec2ec
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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) \
|
||||||
|
|
|
||||||
|
|
@ -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))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue