singleport bitcell array laying out

This commit is contained in:
Jesse Cirimelli-Low
2023-08-21 19:24:06 -07:00
parent 9ac894e2ef
commit 5a6c78865d
6 changed files with 94 additions and 304 deletions
@@ -6,11 +6,12 @@
#
from openram import debug
from openram.modules import bitcell_array
from openram.modules import bitcell_array, pattern
from openram.sram_factory import factory
from openram.base import geometry
from openram import OPTS
from .sky130_bitcell_base_array import sky130_bitcell_base_array
from math import ceil
class sky130_bitcell_array(bitcell_array, sky130_bitcell_base_array):
"""
@@ -38,56 +39,29 @@ class sky130_bitcell_array(bitcell_array, sky130_bitcell_base_array):
""" Add the modules used in this design """
# Bitcell for port names only
self.cell = factory.create(module_type=OPTS.bitcell, version="opt1")
self.cell2 = factory.create(module_type=OPTS.bitcell, version="opt1a")
self.cella = factory.create(module_type=OPTS.bitcell, version="opt1a")
self.strap = factory.create(module_type="internal", version="wlstrap")
self.strap2 = factory.create(module_type="internal", version="wlstrap_p")
self.strap3 = factory.create(module_type="internal", version="wlstrapa")
self.strap4 = factory.create(module_type="internal", version="wlstrapa_p")
self.strap_p = factory.create(module_type="internal", version="wlstrap_p")
self.strapa = factory.create(module_type="internal", version="wlstrapa")
self.strapa_p = factory.create(module_type="internal", version="wlstrapa_p")
def create_instances(self):
""" Create the module instances used in this design """
self.cell_inst = {}
self.array_layout = []
alternate_bitcell = (self.row_size) % 2
for row in range(0, self.row_size):
self.all_inst={}
self.cell_inst={}
bit_row_opt1 = [geometry.instance("00_opt1", mod=self.cell, is_bitcell=True)] \
+ [geometry.instance("01_strap", mod=self.strap, is_bitcell=False)]\
+ [geometry.instance("02_opt1", mod=self.cell, is_bitcell=True)] \
+ [geometry.instance("03_strap_p", mod=self.strap_p, is_bitcell=False)]
bit_row_opt1a = [geometry.instance("10_opt1a", mod=self.cella, is_bitcell=True)] \
+ [geometry.instance("11_strapa", mod=self.strapa, is_bitcell=False)] \
+ [geometry.instance("12_opt1a", mod=self.cella, is_bitcell=True)] \
+ [geometry.instance("13_strapa_p", mod=self.strapa_p, is_bitcell=False)]
row_layout = []
bit_block = []
pattern.append_row_to_block(bit_block, bit_row_opt1)
pattern.append_row_to_block(bit_block, bit_row_opt1a)
self.pattern = pattern(self, "bitcell_array", bit_block, num_rows=self.row_size, num_cols=self.column_size, num_cores_x=ceil(self.row_size/2), name_template="bit_r{0}_c{1}")
self.pattern.connect_array()
alternate_strap = (self.row_size+1) % 2
for col in range(0, self.column_size):
if alternate_bitcell == 1:
row_layout.append(self.cell)
self.cell_inst[row, col]=self.add_inst(name="row_{}_col_{}_bitcell".format(row, col),
mod=self.cell)
else:
row_layout.append(self.cell2)
self.cell_inst[row, col]=self.add_inst(name="row_{}_col_{}_bitcell".format(row, col),
mod=self.cell2)
self.connect_inst(self.get_bitcell_pins(row, col))
if col != self.column_size - 1:
if alternate_strap:
if row % 2:
name="row_{}_col_{}_wlstrapa_p".format(row, col)
row_layout.append(self.strap4)
self.add_inst(name=name, mod=self.strap4)
else:
name="row_{}_col_{}_wlstrap_p".format(row, col)
row_layout.append(self.strap2)
self.add_inst(name=name, mod=self.strap2)
alternate_strap = 0
else:
if row % 2:
name="row_{}_col_{}_wlstrapa".format(row, col)
row_layout.append(self.strap3)
self.add_inst(name=name.format(row, col), mod=self.strap3)
else:
name="row_{}_col_{}_wlstrap".format(row, col)
row_layout.append(self.strap)
self.add_inst(name=name.format(row, col), mod=self.strap)
alternate_strap = 1
self.connect_inst(self.get_strap_pins(row, col, name))
if alternate_bitcell == 0:
alternate_bitcell = 1
else:
alternate_bitcell = 0
self.array_layout.append(row_layout)
@@ -23,44 +23,6 @@ class sky130_bitcell_base_array(bitcell_base_array):
self.cell = factory.create(module_type=OPTS.bitcell, version="opt1")
def place_array(self, name_template, row_offset=0, col_offset=0):
yoffset = 0.0
for row in range(0, len(self.array_layout)):
xoffset = 0.0
for col in range(0, len(self.array_layout[row])):
self.place_inst = self.insts[(col) + (row) * len(self.array_layout[row])]
if row % 2 == 0:
if col == 0:
self.place_inst.place(offset=[xoffset, yoffset + self.cell.height], mirror="MX")
elif col % 4 == 0:
self.place_inst.place(offset=[xoffset, yoffset + self.cell.height], mirror="MX")
elif col % 4 == 3 :
self.place_inst.place(offset=[xoffset, yoffset + self.cell.height], mirror="MX")
elif col % 4 == 2:
self.place_inst.place(offset=[xoffset + self.cell.width, yoffset + self.cell.height], mirror="XY")
else:
self.place_inst.place(offset=[xoffset, yoffset + self.cell.height], mirror="MX")
else:
if col == 0:
self.place_inst.place(offset=[xoffset, yoffset])
elif col % 4 == 0:
self.place_inst.place(offset=[xoffset, yoffset])
elif col % 4 == 3 :
self.place_inst.place(offset=[xoffset, yoffset])
elif col % 4 == 2:
self.place_inst.place(offset=[xoffset + self.cell.width, yoffset], mirror="MY")
# self.place_inst.place(offset=[xoffset, yoffset])
else:
self.place_inst.place(offset=[xoffset, yoffset])
xoffset += self.place_inst.width
yoffset += self.place_inst.height
self.width = max([x.rx() for x in self.insts])
self.height = max([x.uy() for x in self.insts])
def get_bitcell_pins(self, row, col, swap = False):
"""
Creates a list of connections in the bitcell,
@@ -139,49 +101,28 @@ class sky130_bitcell_base_array(bitcell_base_array):
for pin_name in ["vdd", "gnd"]:
self.copy_layout_pin(inst, pin_name)
if row == 2: #add only 1 label per col
# if row == 2: #add only 1 label per col
#
# if 'VPB' or 'vpb' in self.cell_inst[row, col].mod.pins:
# pin = inst.get_pin("vpb")
# self.objs.append(geometry.rectangle(layer["nwell"],
# pin.ll(),
# pin.width(),
# pin.height()))
# self.objs.append(geometry.label("vdd", layer["nwell"], pin.center()))
#
# if 'VNB' or 'vnb'in self.cell_inst[row, col].mod.pins:
# try:
# from openram.tech import layer_override
# if layer_override['VNB']:
# pin = inst.get_pin("vnb")
# self.objs.append(geometry.label("gnd", layer["pwellp"], pin.center()))
# self.objs.append(geometry.rectangle(layer["pwellp"],
# pin.ll(),
# pin.width(),
# pin.height()))
# except:
# pin = inst.get_pin("vnb")
# self.add_label("vdd", pin.layer, pin.center())
if 'VPB' or 'vpb' in self.cell_inst[row, col].mod.pins:
pin = inst.get_pin("vpb")
self.objs.append(geometry.rectangle(layer["nwell"],
pin.ll(),
pin.width(),
pin.height()))
self.objs.append(geometry.label("vdd", layer["nwell"], pin.center()))
if 'VNB' or 'vnb'in self.cell_inst[row, col].mod.pins:
try:
from openram.tech import layer_override
if layer_override['VNB']:
pin = inst.get_pin("vnb")
self.objs.append(geometry.label("gnd", layer["pwellp"], pin.center()))
self.objs.append(geometry.rectangle(layer["pwellp"],
pin.ll(),
pin.width(),
pin.height()))
except:
pin = inst.get_pin("vnb")
self.add_label("vdd", pin.layer, pin.center())
def add_bitline_pins(self):
bitline_names = self.cell.get_all_bitline_names()
for col in range(self.column_size):
for port in self.all_ports:
bl_pin = self.cell_inst[0, col].get_pin(bitline_names[2 * port])
text = "bl_{0}_{1}".format(port, col)
#if "Y" in self.cell_inst[0, col].mirror:
# text = text.replace("bl", "br")
self.add_layout_pin(text=text,
layer=bl_pin.layer,
offset=bl_pin.ll().scale(1, 0),
width=bl_pin.width(),
height=self.height)
br_pin = self.cell_inst[0, col].get_pin(bitline_names[2 * port + 1])
text = "br_{0}_{1}".format(port, col)
#if "Y" in self.cell_inst[0, col].mirror:
# text = text.replace("br", "bl")
self.add_layout_pin(text=text,
layer=br_pin.layer,
offset=br_pin.ll().scale(1, 0),
width=br_pin.width(),
height=self.height)