mirror of https://github.com/VLSIDA/OpenRAM.git
Update pgate well and well contacts.
Extend well left and right past a cell boundary. Use asymmetric well contacts.
This commit is contained in:
parent
04d254542d
commit
596302d9a9
|
|
@ -134,10 +134,10 @@ class pgate(design.design):
|
||||||
# Add a rail width to extend the well to the top of the rail
|
# Add a rail width to extend the well to the top of the rail
|
||||||
nwell_max_offset = max(self.find_highest_layer_coords("nwell").y,
|
nwell_max_offset = max(self.find_highest_layer_coords("nwell").y,
|
||||||
self.height + 0.5 * self.m1_width)
|
self.height + 0.5 * self.m1_width)
|
||||||
nwell_position = middle_position
|
nwell_position = middle_position - vector(self.well_extend_active, 0)
|
||||||
nwell_height = nwell_max_offset - middle_position.y
|
nwell_height = nwell_max_offset - middle_position.y
|
||||||
self.add_rect(layer="nwell",
|
self.add_rect(layer="nwell",
|
||||||
offset=middle_position,
|
offset=nwell_position,
|
||||||
width=self.well_width,
|
width=self.well_width,
|
||||||
height=nwell_height)
|
height=nwell_height)
|
||||||
if "vtg" in layer:
|
if "vtg" in layer:
|
||||||
|
|
@ -150,7 +150,7 @@ class pgate(design.design):
|
||||||
if "pwell" in layer:
|
if "pwell" in layer:
|
||||||
pwell_min_offset = min(self.find_lowest_layer_coords("pwell").y,
|
pwell_min_offset = min(self.find_lowest_layer_coords("pwell").y,
|
||||||
-0.5 * self.m1_width)
|
-0.5 * self.m1_width)
|
||||||
pwell_position = vector(0, pwell_min_offset)
|
pwell_position = vector(-self.well_extend_active, pwell_min_offset)
|
||||||
pwell_height = middle_position.y - pwell_position.y
|
pwell_height = middle_position.y - pwell_position.y
|
||||||
self.add_rect(layer="pwell",
|
self.add_rect(layer="pwell",
|
||||||
offset=pwell_position,
|
offset=pwell_position,
|
||||||
|
|
@ -183,7 +183,6 @@ class pgate(design.design):
|
||||||
0.5 * pmos.active_contact.first_layer_height)
|
0.5 * pmos.active_contact.first_layer_height)
|
||||||
self.nwell_contact = self.add_via_center(layers=layer_stack,
|
self.nwell_contact = self.add_via_center(layers=layer_stack,
|
||||||
offset=contact_offset,
|
offset=contact_offset,
|
||||||
directions=("H", "V"),
|
|
||||||
implant_type="n",
|
implant_type="n",
|
||||||
well_type="n")
|
well_type="n")
|
||||||
self.add_rect_center(layer="m1",
|
self.add_rect_center(layer="m1",
|
||||||
|
|
@ -237,7 +236,6 @@ class pgate(design.design):
|
||||||
0.5 * nmos.active_contact.first_layer_height)
|
0.5 * nmos.active_contact.first_layer_height)
|
||||||
self.pwell_contact= self.add_via_center(layers=layer_stack,
|
self.pwell_contact= self.add_via_center(layers=layer_stack,
|
||||||
offset=contact_offset,
|
offset=contact_offset,
|
||||||
directions=("H", "V"),
|
|
||||||
implant_type="p",
|
implant_type="p",
|
||||||
well_type="p")
|
well_type="p")
|
||||||
self.add_rect_center(layer="m1",
|
self.add_rect_center(layer="m1",
|
||||||
|
|
|
||||||
|
|
@ -52,10 +52,10 @@ class pinv(pgate.pgate):
|
||||||
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 """
|
||||||
self.setup_layout_constants()
|
self.setup_layout_constants()
|
||||||
self.route_supply_rails()
|
|
||||||
self.place_ptx()
|
self.place_ptx()
|
||||||
self.add_well_contacts()
|
self.add_well_contacts()
|
||||||
self.extend_wells(self.well_pos)
|
self.extend_wells(self.well_pos)
|
||||||
|
self.route_supply_rails()
|
||||||
self.connect_rails()
|
self.connect_rails()
|
||||||
self.route_input_gate(self.pmos_inst,
|
self.route_input_gate(self.pmos_inst,
|
||||||
self.nmos_inst,
|
self.nmos_inst,
|
||||||
|
|
@ -104,8 +104,9 @@ class pinv(pgate.pgate):
|
||||||
extra_contact_space = max(-nmos.get_pin("D").by(), 0)
|
extra_contact_space = max(-nmos.get_pin("D").by(), 0)
|
||||||
# This is a poly-to-poly of a flipped cell
|
# This is a poly-to-poly of a flipped cell
|
||||||
self.top_bottom_space = max(0.5*self.m1_width + self.m1_space + extra_contact_space,
|
self.top_bottom_space = max(0.5*self.m1_width + self.m1_space + extra_contact_space,
|
||||||
self.poly_extend_active, self.poly_space)
|
self.poly_extend_active + self.poly_space)
|
||||||
total_height = tx_height + min_channel + 2 * self.top_bottom_space
|
total_height = tx_height + min_channel + 2 * self.top_bottom_space
|
||||||
|
|
||||||
debug.check(self.height > total_height,
|
debug.check(self.height > total_height,
|
||||||
"Cell height {0} too small for simple min height {1}.".format(self.height,
|
"Cell height {0} too small for simple min height {1}.".format(self.height,
|
||||||
total_height))
|
total_height))
|
||||||
|
|
@ -148,14 +149,15 @@ class pinv(pgate.pgate):
|
||||||
|
|
||||||
def setup_layout_constants(self):
|
def setup_layout_constants(self):
|
||||||
"""
|
"""
|
||||||
Pre-compute some handy layout parameters.
|
Compute the width and height
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# the well width is determined the multi-finger PMOS device width plus
|
# the width is determined the multi-finger PMOS device width plus
|
||||||
# the well contact width and half well enclosure on both sides
|
# the well contact width, spacing between them
|
||||||
self.well_width = self.pmos.active_width + self.pmos.active_contact.width \
|
self.width = self.pmos.active_offset.x + self.pmos.active_width \
|
||||||
+ self.active_space + 2*self.nwell_enclose_active
|
+ contact.nwell_contact.width + self.active_space + 0.5 * self.nwell_enclose_active
|
||||||
self.width = self.well_width
|
# This includes full enclosures on each end
|
||||||
|
self.well_width = self.width + 2*self.nwell_enclose_active
|
||||||
# Height is an input parameter, so it is not recomputed.
|
# Height is an input parameter, so it is not recomputed.
|
||||||
|
|
||||||
def add_ptx(self):
|
def add_ptx(self):
|
||||||
|
|
|
||||||
|
|
@ -98,11 +98,11 @@ class pnand2(pgate.pgate):
|
||||||
|
|
||||||
# Two PMOS devices and a well contact. Separation between each.
|
# Two PMOS devices and a well contact. Separation between each.
|
||||||
# Enclosure space on the sides.
|
# Enclosure space on the sides.
|
||||||
self.well_width = 2 * self.pmos.active_width + contact.active_contact.width \
|
self.width = 2 * self.pmos.active_width + contact.active_contact.width \
|
||||||
+ 2 * self.active_space \
|
+ 2 * self.active_space \
|
||||||
+ 2 * self.nwell_enclose_active
|
+ 0.5 * self.nwell_enclose_active
|
||||||
|
|
||||||
self.width = self.well_width
|
self.well_width = self.width + 2 * self.nwell_enclose_active
|
||||||
# Height is an input parameter, so it is not recomputed.
|
# Height is an input parameter, so it is not recomputed.
|
||||||
|
|
||||||
# This is the extra space needed to ensure DRC rules
|
# This is the extra space needed to ensure DRC rules
|
||||||
|
|
|
||||||
|
|
@ -91,10 +91,10 @@ class pnand3(pgate.pgate):
|
||||||
|
|
||||||
# Two PMOS devices and a well contact. Separation between each.
|
# Two PMOS devices and a well contact. Separation between each.
|
||||||
# Enclosure space on the sides.
|
# Enclosure space on the sides.
|
||||||
self.well_width = 3 * self.pmos.active_width + self.pmos.active_contact.width \
|
self.width = 3 * self.pmos.active_width + self.pmos.active_contact.width \
|
||||||
+ 2 * self.active_space + 2 * self.nwell_enclose_active \
|
+ 2 * self.active_space + 0.5 * self.nwell_enclose_active \
|
||||||
- self.overlap_offset.x
|
- self.overlap_offset.x
|
||||||
self.width = self.well_width
|
self.well_width = self.width + 2 * self.nwell_enclose_active
|
||||||
# Height is an input parameter, so it is not recomputed.
|
# Height is an input parameter, so it is not recomputed.
|
||||||
|
|
||||||
# This is the extra space needed to ensure DRC rules
|
# This is the extra space needed to ensure DRC rules
|
||||||
|
|
@ -245,10 +245,10 @@ class pnand3(pgate.pgate):
|
||||||
offset=nmos3_pin.center())
|
offset=nmos3_pin.center())
|
||||||
|
|
||||||
# PMOS3 and NMOS3 are drain aligned
|
# PMOS3 and NMOS3 are drain aligned
|
||||||
self.add_path("m2", [pmos3_pin.bc(), nmos3_pin.uc()])
|
self.add_path("m2", [pmos3_pin.center(), nmos3_pin.uc()])
|
||||||
# Route in the A input track (top track)
|
# Route in the A input track (top track)
|
||||||
mid_offset = vector(nmos3_pin.center().x, self.inputA_yoffset)
|
mid_offset = vector(nmos3_pin.center().x, self.inputA_yoffset)
|
||||||
self.add_path("m2", [pmos1_pin.bc(), mid_offset, nmos3_pin.uc()])
|
self.add_path("m2", [pmos1_pin.center(), mid_offset, nmos3_pin.uc()])
|
||||||
|
|
||||||
# This extends the output to the edge of the cell
|
# This extends the output to the edge of the cell
|
||||||
self.add_via_center(layers=self.m1_stack,
|
self.add_via_center(layers=self.m1_stack,
|
||||||
|
|
|
||||||
|
|
@ -95,11 +95,11 @@ class pnor2(pgate.pgate):
|
||||||
|
|
||||||
# Two PMOS devices and a well contact. Separation between each.
|
# Two PMOS devices and a well contact. Separation between each.
|
||||||
# Enclosure space on the sides.
|
# Enclosure space on the sides.
|
||||||
self.well_width = 2 * self.pmos.active_width \
|
self.width = 2 * self.pmos.active_width \
|
||||||
+ self.pmos.active_contact.width \
|
+ self.pmos.active_contact.width \
|
||||||
+ 2 * self.active_space \
|
+ 2 * self.active_space \
|
||||||
+ 2 * self.nwell_enclose_active
|
+ 0.5 * self.nwell_enclose_active
|
||||||
self.width = self.well_width
|
self.well_width = self.width + 2 * self.nwell_enclose_active
|
||||||
# Height is an input parameter, so it is not recomputed.
|
# Height is an input parameter, so it is not recomputed.
|
||||||
|
|
||||||
# This is the extra space needed to ensure DRC rules
|
# This is the extra space needed to ensure DRC rules
|
||||||
|
|
@ -225,7 +225,7 @@ class pnor2(pgate.pgate):
|
||||||
|
|
||||||
# PMOS1 to mid-drain to NMOS2 drain
|
# PMOS1 to mid-drain to NMOS2 drain
|
||||||
self.add_path("m2",
|
self.add_path("m2",
|
||||||
[pmos_pin.bc(), mid2_offset, mid3_offset])
|
[pmos_pin.center(), mid2_offset, mid3_offset])
|
||||||
self.add_path("m2",
|
self.add_path("m2",
|
||||||
[nmos_pin.rc(), mid1_offset, mid2_offset])
|
[nmos_pin.rc(), mid1_offset, mid2_offset])
|
||||||
# This extends the output to the edge of the cell
|
# This extends the output to the edge of the cell
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue