Incomplete precharge layer decoupling

This commit is contained in:
mrg 2020-03-04 22:23:05 +00:00
parent bb2305d56a
commit 7ba9e09e12
5 changed files with 63 additions and 55 deletions

View File

@ -517,12 +517,12 @@ class layout():
self.connect_inst([]) self.connect_inst([])
return inst return inst
def add_via_stack(self, offset, direction, from_layer, to_layer, def add_via_stack(self, offset, from_layer, to_layer,
size=[1,1]): direction=None,
size=[1, 1]):
""" """
Punch a stack of vias from a start layer to a target layer. Punch a stack of vias from a start layer to a target layer.
""" """
return self.__add_via_stack_internal(offset=offset, return self.__add_via_stack_internal(offset=offset,
direction=direction, direction=direction,
from_layer=from_layer, from_layer=from_layer,
@ -531,8 +531,9 @@ class layout():
last_via=None, last_via=None,
size=size) size=size)
def add_via_stack_center(self, offset, direction, from_layer, to_layer, def add_via_stack_center(self, offset, from_layer, to_layer,
size=[1,1]): direction=None,
size=[1, 1]):
""" """
Punch a stack of vias from a start layer to a target layer by the center Punch a stack of vias from a start layer to a target layer by the center
coordinate accounting for mirroring and rotation. coordinate accounting for mirroring and rotation.
@ -545,7 +546,6 @@ class layout():
last_via=None, last_via=None,
size=size) size=size)
def __add_via_stack_internal(self, offset, direction, from_layer, to_layer, def __add_via_stack_internal(self, offset, direction, from_layer, to_layer,
via_func, last_via, size): via_func, last_via, size):
""" """
@ -581,7 +581,6 @@ class layout():
last_via=via, last_via=via,
size=size) size=size)
def add_ptx(self, offset, mirror="R0", rotate=0, width=1, mults=1, tx_type="nmos"): def add_ptx(self, offset, mirror="R0", rotate=0, width=1, mults=1, tx_type="nmos"):
"""Adds a ptx module to the design.""" """Adds a ptx module to the design."""
import ptx import ptx

View File

@ -521,7 +521,7 @@ class hierarchical_decoder(design.design):
""" Add a pin for each row of vdd/gnd which are must-connects next level up. """ """ Add a pin for each row of vdd/gnd which are must-connects next level up. """
# The vias will be placed in the center and right of the cells, respectively. # The vias will be placed in the center and right of the cells, respectively.
xoffset = self.nand_inst[0].cx() xoffset = self.nand_inst[0].rx()
for num in range(0, self.rows): for num in range(0, self.rows):
for pin_name in ["vdd", "gnd"]: for pin_name in ["vdd", "gnd"]:
# The nand and inv are the same height rows... # The nand and inv are the same height rows...

View File

@ -75,8 +75,7 @@ class wordline_driver(design.design):
""" """
# Find the x offsets for where the vias/pins should be placed # Find the x offsets for where the vias/pins should be placed
a_xoffset = self.nand_inst[0].rx() a_xoffset = self.nand_inst[0].lx()
b_xoffset = self.inv2_inst[0].lx()
for num in range(self.rows): for num in range(self.rows):
# this will result in duplicate polygons for rails, but who cares # this will result in duplicate polygons for rails, but who cares
@ -90,7 +89,7 @@ class wordline_driver(design.design):
supply_pin = self.inv2_inst[num].get_pin(name) supply_pin = self.inv2_inst[num].get_pin(name)
# Add pins in two locations # Add pins in two locations
for xoffset in [a_xoffset, b_xoffset]: for xoffset in [a_xoffset]:
pin_pos = vector(xoffset, supply_pin.cy()) pin_pos = vector(xoffset, supply_pin.cy())
self.add_power_pin(name, pin_pos) self.add_power_pin(name, pin_pos)

View File

@ -267,8 +267,8 @@ class pgate(design.design):
def determine_width(self): def determine_width(self):
""" Determine the width based on the well contacts (assumed to be on the right side) """ """ Determine the width based on the well contacts (assumed to be on the right side) """
# Width is determined by well contact and spacing # Width is determined by well contact and spacing and allowing a supply via between each cell
self.width = max(self.nwell_contact.rx(), self.pwell_contact.rx()) + self.m1_space self.width = max(self.nwell_contact.rx(), self.pwell_contact.rx()) + self.m1_space + 0.5 * contact.m1_via.width
self.well_width = self.width + 2 * self.nwell_enclose_active 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.

View File

@ -12,7 +12,7 @@ from tech import parameter
from vector import vector from vector import vector
from globals import OPTS from globals import OPTS
from sram_factory import factory from sram_factory import factory
from tech import drc
class precharge(design.design): class precharge(design.design):
""" """
@ -30,7 +30,10 @@ class precharge(design.design):
self.width = self.bitcell.width self.width = self.bitcell.width
self.bitcell_bl = bitcell_bl self.bitcell_bl = bitcell_bl
self.bitcell_br = bitcell_br self.bitcell_br = bitcell_br
self.bitcell_bl_pin =self.bitcell.get_pin(self.bitcell_bl)
self.bitcell_br_pin =self.bitcell.get_pin(self.bitcell_br)
print(self.bitcell_bl_pin)
print(self.bitcell_br_pin)
# Creates the netlist and layout # Creates the netlist and layout
# Since it has variable height, it is not a pgate. # Since it has variable height, it is not a pgate.
self.create_netlist() self.create_netlist()
@ -50,6 +53,7 @@ class precharge(design.design):
self.create_ptx() self.create_ptx()
def create_layout(self): def create_layout(self):
self.place_ptx() self.place_ptx()
self.connect_poly() self.connect_poly()
self.route_en() self.route_en()
@ -120,17 +124,18 @@ class precharge(design.design):
contact_xdiff = self.pmos.get_pin("S").lx() contact_xdiff = self.pmos.get_pin("S").lx()
# adds the lower pmos to layout # adds the lower pmos to layout
bl_xoffset = self.bitcell.get_pin(self.bitcell_bl).lx() bl_xoffset = self.bitcell_bl_pin.lx()
self.lower_pmos_position = vector(max(bl_xoffset - contact_xdiff, self.lower_pmos_position = vector(max(bl_xoffset - contact_xdiff,
self.nwell_enclose_active), self.nwell_enclose_active),
self.pmos.active_offset.y) self.pmos.active_offset.y)
self.lower_pmos_inst.place(self.lower_pmos_position) self.lower_pmos_inst.place(self.lower_pmos_position)
# adds the upper pmos(s) to layout # adds the upper pmos(s) to layout
ydiff = self.pmos.height + 2 * self.m1_space + contact.poly_contact.width ydiff = self.pmos.height + 4 * self.m2_space
self.upper_pmos1_pos = self.lower_pmos_position + vector(0, ydiff) self.upper_pmos1_pos = self.lower_pmos_position + vector(0, ydiff)
self.upper_pmos1_inst.place(self.upper_pmos1_pos) self.upper_pmos1_inst.place(self.upper_pmos1_pos)
# Second pmos to the right of the first
upper_pmos2_pos = self.upper_pmos1_pos + overlap_offset upper_pmos2_pos = self.upper_pmos1_pos + overlap_offset
self.upper_pmos2_inst.place(upper_pmos2_pos) self.upper_pmos2_inst.place(upper_pmos2_pos)
@ -162,15 +167,24 @@ class precharge(design.design):
Adds the en input rail, en contact/vias, and connects to the pmos Adds the en input rail, en contact/vias, and connects to the pmos
""" """
if self.bitcell_bl_pin.layer == "m1":
layer = "m2"
else:
layer = "m1"
# adds the en contact to connect the gates to the en rail on metal1 # adds the en contact to connect the gates to the en rail on metal1
offset = self.lower_pmos_inst.get_pin("G").ul() \ offset = self.lower_pmos_inst.get_pin("G").ul() \
+ vector(0, 0.5 * self.poly_space) + vector(0, self.m2_pitch)
self.add_via_center(layers=self.poly_stack, self.add_via_center(layers=self.poly_stack,
offset=offset) offset=offset)
if layer == "m2":
self.add_via_center(layers=self.m1_stack,
offset=offset)
# adds the en rail on metal1 # adds the en rail on metal1
self.add_layout_pin_segment_center(text="en_bar", self.add_layout_pin_segment_center(text="en_bar",
layer="m1", layer=layer,
start=offset.scale(0, 1), start=offset.scale(0, 1),
end=offset.scale(0, 1) + vector(self.width, 0)) end=offset.scale(0, 1) + vector(self.width, 0))
@ -201,20 +215,21 @@ class precharge(design.design):
""" """
Adds both bit-line and bit-line-bar to the module Adds both bit-line and bit-line-bar to the module
""" """
layer_width = drc("minwidth_" + self.bitcell_br_pin.layer)
layer_space = drc("{0}_to_{0}".format(self.bitcell_br_pin.layer))
layer = self.bitcell_bl_pin.layer
# adds the BL on metal 2 # adds the BL on metal 2
offset = vector(self.bitcell.get_pin(self.bitcell_bl).cx(), 0) \ offset = vector(layer_space - 0.5 * layer_width, 0)
- vector(0.5 * self.m2_width, 0)
self.bl_pin = self.add_layout_pin(text="bl", self.bl_pin = self.add_layout_pin(text="bl",
layer="m2", layer=layer,
offset=offset, offset=offset,
height=self.height) height=self.height)
# adds the BR on metal 2 # adds the BR on metal 2
offset = vector(self.bitcell.get_pin(self.bitcell_br).cx(), 0) \ offset = vector(self.width - layer_space - 0.5 * layer_width, 0)
- vector(0.5 * self.m2_width, 0)
self.br_pin = self.add_layout_pin(text="br", self.br_pin = self.add_layout_pin(text="br",
layer="m2", layer=layer,
offset=offset, offset=offset,
height=self.height) height=self.height)
@ -225,11 +240,12 @@ class precharge(design.design):
self.add_bitline_contacts() self.add_bitline_contacts()
self.connect_pmos_m2(self.lower_pmos_inst.get_pin("S"), self.connect_pmos_m2(self.lower_pmos_inst.get_pin("S"),
self.get_pin("bl")) self.get_pin("bl"))
self.connect_pmos_m2(self.lower_pmos_inst.get_pin("D"),
self.get_pin("br"))
self.connect_pmos_m2(self.upper_pmos1_inst.get_pin("S"), self.connect_pmos_m2(self.upper_pmos1_inst.get_pin("S"),
self.get_pin("bl")) self.get_pin("bl"))
self.connect_pmos_m1(self.lower_pmos_inst.get_pin("D"), self.connect_pmos_m2(self.upper_pmos2_inst.get_pin("D"),
self.get_pin("br"))
self.connect_pmos_m1(self.upper_pmos2_inst.get_pin("D"),
self.get_pin("br")) self.get_pin("br"))
def add_bitline_contacts(self): def add_bitline_contacts(self):
@ -237,34 +253,28 @@ class precharge(design.design):
Adds contacts/via from metal1 to metal2 for bit-lines Adds contacts/via from metal1 to metal2 for bit-lines
""" """
upper_pin = self.upper_pmos1_inst.get_pin("S")
lower_pin = self.lower_pmos_inst.get_pin("S")
# BL goes up to M2 at the transistor # BL
self.bl_contact =self.add_via_center(layers=self.m1_stack, lower_pin = self.lower_pmos_inst.get_pin("S")
offset=upper_pin.center(), self.lower_via = self.add_via_center(layers=self.m1_stack,
directions=("V", "V"))
self.add_via_center(layers=self.m1_stack,
offset=lower_pin.center(), offset=lower_pin.center(),
directions=("V", "V")) directions=("V", "V"))
# BR routes over on M1 first lower_pin = self.lower_pmos_inst.get_pin("D")
self.add_via_center(layers=self.m1_stack, self.lower_via = self.add_via_center(layers=self.m1_stack,
offset=vector(self.br_pin.cx(), upper_pin.cy()), offset=lower_pin.center(),
directions=("V", "V"))
self.add_via_center(layers=self.m1_stack,
offset=vector(self.br_pin.cx(), lower_pin.cy()),
directions=("V", "V")) directions=("V", "V"))
def connect_pmos_m1(self, pmos_pin, bit_pin): # BR
""" upper_pin = self.upper_pmos1_inst.get_pin("S")
Connect a pmos pin to bitline pin self.upper_via2 = self.add_via_center(layers=self.m1_stack,
""" offset=upper_pin.center(),
directions=("V", "V"))
left_pos = vector(min(pmos_pin.cx(), bit_pin.cx()), pmos_pin.cy()) upper_pin = self.upper_pmos2_inst.get_pin("D")
right_pos = vector(max(pmos_pin.cx(), bit_pin.cx()), pmos_pin.cy()) self.upper_via2 = self.add_via_center(layers=self.m1_stack,
offset=upper_pin.center(),
self.add_path("m1", [left_pos, right_pos] ) directions=("V", "V"))
def connect_pmos_m2(self, pmos_pin, bit_pin): def connect_pmos_m2(self, pmos_pin, bit_pin):
""" """
@ -274,7 +284,7 @@ class precharge(design.design):
left_pos = vector(min(pmos_pin.cx(), bit_pin.cx()), pmos_pin.cy()) left_pos = vector(min(pmos_pin.cx(), bit_pin.cx()), pmos_pin.cy())
right_pos = vector(max(pmos_pin.cx(), bit_pin.cx()), pmos_pin.cy()) right_pos = vector(max(pmos_pin.cx(), bit_pin.cx()), pmos_pin.cy())
self.add_path("m2", [left_pos, right_pos], self.bl_contact.height) self.add_path("m2", [left_pos, right_pos])
def get_en_cin(self): def get_en_cin(self):
"""Get the relative capacitance of the enable in the precharge cell""" """Get the relative capacitance of the enable in the precharge cell"""