mirror of https://github.com/VLSIDA/OpenRAM.git
Precharge updates.
Enable different layers for bitlines. Jog bitlines to fit precharge transistors for close proximity bitlines. PEP8 cleanup.
This commit is contained in:
parent
7ba9e09e12
commit
287a31f598
|
|
@ -316,7 +316,7 @@ class layout():
|
|||
You can optionally rename the pin to a new name.
|
||||
"""
|
||||
for pin_name in self.pin_map.keys():
|
||||
self.copy_layout_pin(instance, pin_name, prefix+pin_name)
|
||||
self.copy_layout_pin(instance, pin_name, prefix + pin_name)
|
||||
|
||||
def add_layout_pin_segment_center(self, text, layer, start, end):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ from vector import vector
|
|||
from sram_factory import factory
|
||||
from globals import OPTS
|
||||
|
||||
|
||||
class precharge_array(design.design):
|
||||
"""
|
||||
Dynamically generated precharge array of all bitlines. Cols is number
|
||||
|
|
@ -68,11 +69,8 @@ class precharge_array(design.design):
|
|||
size=self.size,
|
||||
bitcell_bl=self.bitcell_bl,
|
||||
bitcell_br=self.bitcell_br)
|
||||
|
||||
|
||||
self.add_mod(self.pc_cell)
|
||||
|
||||
|
||||
def add_layout_pins(self):
|
||||
|
||||
self.add_layout_pin(text="en_bar",
|
||||
|
|
@ -86,20 +84,9 @@ class precharge_array(design.design):
|
|||
|
||||
for i in range(len(self.local_insts)):
|
||||
inst = self.local_insts[i]
|
||||
bl_pin = inst.get_pin("bl")
|
||||
self.add_layout_pin(text="bl_{0}".format(i),
|
||||
layer="m2",
|
||||
offset=bl_pin.ll(),
|
||||
width=drc("minwidth_m2"),
|
||||
height=bl_pin.height())
|
||||
br_pin = inst.get_pin("br")
|
||||
self.add_layout_pin(text="br_{0}".format(i),
|
||||
layer="m2",
|
||||
offset=br_pin.ll(),
|
||||
width=drc("minwidth_m2"),
|
||||
height=bl_pin.height())
|
||||
self.copy_layout_pin(inst, "bl", "bl_{0}".format(i))
|
||||
self.copy_layout_pin(inst, "br", "br_{0}".format(i))
|
||||
|
||||
|
||||
def create_insts(self):
|
||||
"""Creates a precharge array by horizontally tiling the precharge cell"""
|
||||
self.local_insts = []
|
||||
|
|
@ -112,7 +99,6 @@ class precharge_array(design.design):
|
|||
self.local_insts.append(inst)
|
||||
self.connect_inst(["bl_{0}".format(i), "br_{0}".format(i), "en_bar", "vdd"])
|
||||
|
||||
|
||||
def place_insts(self):
|
||||
""" Places precharge array by horizontally tiling the precharge cell"""
|
||||
from tech import cell_properties
|
||||
|
|
@ -130,8 +116,11 @@ class precharge_array(design.design):
|
|||
xoffset = xoffset + self.pc_cell.width
|
||||
|
||||
def get_en_cin(self):
|
||||
"""Get the relative capacitance of all the clk connections in the precharge array"""
|
||||
#Assume single port
|
||||
"""
|
||||
Get the relative capacitance of all the clk connections
|
||||
in the precharge array
|
||||
"""
|
||||
# Assume single port
|
||||
precharge_en_cin = self.pc_cell.get_en_cin()
|
||||
return precharge_en_cin*self.columns
|
||||
return precharge_en_cin * self.columns
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ from globals import OPTS
|
|||
from sram_factory import factory
|
||||
from tech import drc
|
||||
|
||||
|
||||
class precharge(design.design):
|
||||
"""
|
||||
Creates a single precharge cell
|
||||
|
|
@ -32,8 +33,14 @@ class precharge(design.design):
|
|||
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)
|
||||
|
||||
if self.bitcell_bl_pin.layer == "m1":
|
||||
self.bitline_layer = "m1"
|
||||
self.en_layer = "m2"
|
||||
else:
|
||||
self.bitline_layer = "m2"
|
||||
self.en_layer = "m1"
|
||||
|
||||
# Creates the netlist and layout
|
||||
# Since it has variable height, it is not a pgate.
|
||||
self.create_netlist()
|
||||
|
|
@ -82,18 +89,24 @@ class precharge(design.design):
|
|||
|
||||
# Adds the rail across the width of the cell
|
||||
vdd_position = vector(0.5 * self.width, self.height)
|
||||
self.add_rect_center(layer="m1",
|
||||
layer_width = drc("minwidth_" + self.en_layer)
|
||||
self.add_rect_center(layer=self.en_layer,
|
||||
offset=vdd_position,
|
||||
width=self.width,
|
||||
height=self.m1_width)
|
||||
height=layer_width)
|
||||
|
||||
pmos_pin = self.upper_pmos2_inst.get_pin("S")
|
||||
# center of vdd rail
|
||||
pmos_vdd_pos = vector(pmos_pin.cx(), vdd_position.y)
|
||||
self.add_path("m1", [pmos_pin.uc(), pmos_vdd_pos])
|
||||
if self.en_layer != "m1":
|
||||
self.add_via_center(layers=self.m1_stack,
|
||||
offset=pmos_vdd_pos)
|
||||
|
||||
|
||||
|
||||
# Add vdd pin above the transistor
|
||||
self.add_power_pin("vdd", pmos_pin.center(), vertical=True)
|
||||
self.add_power_pin("vdd", self.well_contact_pos, vertical=True)
|
||||
|
||||
def create_ptx(self):
|
||||
"""
|
||||
|
|
@ -117,6 +130,8 @@ class precharge(design.design):
|
|||
Place both the upper_pmos and lower_pmos to the module
|
||||
"""
|
||||
|
||||
# reserve some offset to jog the bitlines
|
||||
self.initial_yoffset = self.pmos.active_offset.y + self.m2_pitch
|
||||
# Compute the other pmos2 location,
|
||||
# but determining offset to overlap the source and drain pins
|
||||
overlap_offset = self.pmos.get_pin("D").ll() - self.pmos.get_pin("S").ll()
|
||||
|
|
@ -127,11 +142,11 @@ class precharge(design.design):
|
|||
bl_xoffset = self.bitcell_bl_pin.lx()
|
||||
self.lower_pmos_position = vector(max(bl_xoffset - contact_xdiff,
|
||||
self.nwell_enclose_active),
|
||||
self.pmos.active_offset.y)
|
||||
self.initial_yoffset)
|
||||
self.lower_pmos_inst.place(self.lower_pmos_position)
|
||||
|
||||
# adds the upper pmos(s) to layout
|
||||
ydiff = self.pmos.height + 4 * self.m2_space
|
||||
# adds the upper pmos(s) to layout with 2 M2 tracks
|
||||
ydiff = self.pmos.height + self.m2_pitch
|
||||
self.upper_pmos1_pos = self.lower_pmos_position + vector(0, ydiff)
|
||||
self.upper_pmos1_inst.place(self.upper_pmos1_pos)
|
||||
|
||||
|
|
@ -167,24 +182,20 @@ class precharge(design.design):
|
|||
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
|
||||
# midway in the 4 M2 tracks
|
||||
offset = self.lower_pmos_inst.get_pin("G").ul() \
|
||||
+ vector(0, self.m2_pitch)
|
||||
+ vector(0, 0.5 * self.m2_pitch)
|
||||
self.add_via_center(layers=self.poly_stack,
|
||||
offset=offset)
|
||||
if layer == "m2":
|
||||
if self.en_layer == "m2":
|
||||
self.add_via_center(layers=self.m1_stack,
|
||||
offset=offset)
|
||||
|
||||
|
||||
# adds the en rail on metal1
|
||||
self.add_layout_pin_segment_center(text="en_bar",
|
||||
layer=layer,
|
||||
layer=self.en_layer,
|
||||
start=offset.scale(0, 1),
|
||||
end=offset.scale(0, 1) + vector(self.width, 0))
|
||||
|
||||
|
|
@ -194,16 +205,15 @@ class precharge(design.design):
|
|||
"""
|
||||
|
||||
# adds the contact from active to metal1
|
||||
well_contact_pos = self.upper_pmos1_inst.get_pin("D").center().scale(1, 0) \
|
||||
+ vector(0, self.upper_pmos1_inst.uy() + contact.active_contact.height / 2 \
|
||||
+ self.nwell_extend_active)
|
||||
self.well_contact_pos = self.upper_pmos1_inst.get_pin("D").center().scale(1, 0) \
|
||||
+ vector(0, self.upper_pmos1_inst.uy() + contact.active_contact.height / 2 \
|
||||
+ self.nwell_extend_active)
|
||||
self.add_via_center(layers=self.active_stack,
|
||||
offset=well_contact_pos,
|
||||
offset=self.well_contact_pos,
|
||||
implant_type="n",
|
||||
well_type="n")
|
||||
|
||||
# leave an extra pitch for the height
|
||||
self.height = well_contact_pos.y + contact.active_contact.height + self.m1_pitch
|
||||
self.height = self.well_contact_pos.y + contact.active_contact.height + self.m1_space
|
||||
|
||||
# nwell should span the whole design since it is pmos only
|
||||
self.add_rect(layer="nwell",
|
||||
|
|
@ -215,44 +225,59 @@ class precharge(design.design):
|
|||
"""
|
||||
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
|
||||
layer_width = drc("minwidth_" + self.bitline_layer)
|
||||
layer_space = drc("{0}_to_{0}".format(self.bitline_layer))
|
||||
|
||||
# adds the BL on metal 2
|
||||
offset = vector(layer_space - 0.5 * layer_width, 0)
|
||||
self.bl_pin = self.add_layout_pin(text="bl",
|
||||
layer=layer,
|
||||
offset=offset,
|
||||
height=self.height)
|
||||
|
||||
# adds the BR on metal 2
|
||||
offset = vector(self.width - layer_space - 0.5 * layer_width, 0)
|
||||
self.br_pin = self.add_layout_pin(text="br",
|
||||
layer=layer,
|
||||
offset=offset,
|
||||
height=self.height)
|
||||
yoffset = self.initial_yoffset - 0.5 * self.m2_pitch
|
||||
# adds the BL
|
||||
self.bl_xoffset = layer_space + 0.5 * layer_width
|
||||
top_pos = vector(self.bl_xoffset, self.height)
|
||||
mid1_pos = vector(self.bl_xoffset, yoffset)
|
||||
mid2_pos = vector(self.bitcell_bl_pin.cx(), yoffset)
|
||||
pin_pos = vector(self.bitcell_bl_pin.cx(), 0)
|
||||
self.add_path(self.bitline_layer,
|
||||
[top_pos, mid1_pos, mid2_pos, pin_pos])
|
||||
self.bl_pin = self.add_layout_pin_segment_center(text="bl",
|
||||
layer=self.bitline_layer,
|
||||
start=pin_pos,
|
||||
end=mid2_pos)
|
||||
|
||||
# adds the BR
|
||||
self.br_xoffset = self.width - layer_space - 0.5 * layer_width
|
||||
top_pos = vector(self.br_xoffset, self.height)
|
||||
mid1_pos = vector(self.br_xoffset, yoffset)
|
||||
mid2_pos = vector(self.bitcell_br_pin.cx(), yoffset)
|
||||
pin_pos = vector(self.bitcell_br_pin.cx(), 0)
|
||||
self.add_path(self.bitline_layer,
|
||||
[top_pos, mid1_pos, mid2_pos, pin_pos])
|
||||
self.br_pin = self.add_layout_pin_segment_center(text="br",
|
||||
layer=self.bitline_layer,
|
||||
start=pin_pos,
|
||||
end=mid2_pos)
|
||||
|
||||
def connect_to_bitlines(self):
|
||||
"""
|
||||
Connect the bitlines to the devices
|
||||
"""
|
||||
self.add_bitline_contacts()
|
||||
self.connect_pmos_m2(self.lower_pmos_inst.get_pin("S"),
|
||||
self.get_pin("bl"))
|
||||
self.connect_pmos_m2(self.lower_pmos_inst.get_pin("D"),
|
||||
self.get_pin("br"))
|
||||
self.connect_pmos(self.lower_pmos_inst.get_pin("S"),
|
||||
self.bl_xoffset)
|
||||
self.connect_pmos(self.lower_pmos_inst.get_pin("D"),
|
||||
self.br_xoffset)
|
||||
|
||||
self.connect_pmos_m2(self.upper_pmos1_inst.get_pin("S"),
|
||||
self.get_pin("bl"))
|
||||
self.connect_pmos_m2(self.upper_pmos2_inst.get_pin("D"),
|
||||
self.get_pin("br"))
|
||||
self.connect_pmos(self.upper_pmos1_inst.get_pin("S"),
|
||||
self.bl_xoffset)
|
||||
self.connect_pmos(self.upper_pmos2_inst.get_pin("D"),
|
||||
self.br_xoffset)
|
||||
|
||||
def add_bitline_contacts(self):
|
||||
"""
|
||||
Adds contacts/via from metal1 to metal2 for bit-lines
|
||||
"""
|
||||
|
||||
# No contacts needed if M1
|
||||
if self.bitline_layer == "m1":
|
||||
return
|
||||
|
||||
# BL
|
||||
lower_pin = self.lower_pmos_inst.get_pin("S")
|
||||
|
|
@ -276,15 +301,17 @@ class precharge(design.design):
|
|||
offset=upper_pin.center(),
|
||||
directions=("V", "V"))
|
||||
|
||||
def connect_pmos_m2(self, pmos_pin, bit_pin):
|
||||
def connect_pmos(self, pmos_pin, bit_xoffset):
|
||||
"""
|
||||
Connect a pmos pin to bitline pin
|
||||
"""
|
||||
|
||||
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())
|
||||
left_pos = vector(min(pmos_pin.cx(), bit_xoffset), pmos_pin.cy())
|
||||
right_pos = vector(max(pmos_pin.cx(), bit_xoffset), pmos_pin.cy())
|
||||
|
||||
self.add_path("m2", [left_pos, right_pos])
|
||||
self.add_path(self.bitline_layer,
|
||||
[left_pos, right_pos],
|
||||
width=pmos_pin.height())
|
||||
|
||||
def get_en_cin(self):
|
||||
"""Get the relative capacitance of the enable in the precharge cell"""
|
||||
|
|
|
|||
Loading…
Reference in New Issue