OpenRAM/technology/sky130/custom/sky130_bitcell_base_array.py

120 lines
4.4 KiB
Python

#!/usr/bin/env python3
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2023 Regents of the University of California
# All rights reserved.
#
from openram import debug
from openram.base import geometry
from openram.modules import bitcell_base_array
from openram.sram_factory import factory
from openram.tech import layer
from openram import OPTS
from openram.modules import pattern
class sky130_bitcell_base_array(bitcell_base_array):
"""
Abstract base class for bitcell-arrays -- bitcell, dummy, replica
"""
def __init__(self, name, rows, cols, column_offset):
super().__init__(name, rows, cols, column_offset)
debug.info(1, "Creating {0} {1} x {2}".format(self.name, rows, cols))
self.cell = factory.create(module_type=OPTS.bitcell, version="opt1")
def get_bitcell_pins(self, row, col, swap = False):
"""
Creates a list of connections in the bitcell,
indexed by column and row, for instance use in bitcell_array
"""
bitcell_pins = []
for port in self.all_ports:
bitcell_pins.extend([x for x in self.get_bitline_names(port) if x.endswith("_{0}".format(col))])
bitcell_pins.append("gnd") # gnd
bitcell_pins.append("vdd") # vdd
bitcell_pins.append("vdd") # vpb
bitcell_pins.append("gnd") # vnb
bitcell_pins.extend([x for x in self.all_wordline_names if x.endswith("_{0}".format(row))])
return bitcell_pins
def get_strap_pins(self, row, col, name=""):
"""
Creates a list of connections in the strap cell,
indexed by column and row, for instance use in bitcell_array
"""
if name and "_p" in name:
strap_pins = ["gnd"]
else:
strap_pins = ["vdd"]
return strap_pins
def get_col_cap_p_pins(self, row, col):
"""
"""
strap_pins = ["gnd", "vdd", "gnd"]
return strap_pins
def get_col_cap_pins(self, row, col):
"""
"""
strap_pins = []
for port in self.all_ports:
strap_pins.extend([x for x in self.get_bitline_names(port) if "bl" in x and x.endswith("_{0}".format(col))])
strap_pins.extend(["vdd", "gnd"])
for port in self.all_ports:
strap_pins.extend([x for x in self.get_bitline_names(port) if "br" in x and x.endswith("_{0}".format(col))])
if row == 0:
strap_pins.extend(["top_gate"])
else:
strap_pins.extend(["bot_gate"])
strap_pins.extend(["vdd", "gnd"])
return strap_pins
def get_row_cap_pins(self, row, col):
"""
"""
strap_pins = ["gnd", "vdd", "gnd"]
return strap_pins
def get_corner_pins(self):
"""
"""
strap_pins = ["vdd", "gnd", "vdd"]
return strap_pins
def route_supplies(self):
# Copy a vdd/gnd layout pin from every cell
super().route_supplies()
for inst in self.insts:
if "VPWR" in inst.mod.pins:
self.copy_layout_pin(inst, "VPWR", "vdd")
if "VGND" in inst.mod.pins:
self.copy_layout_pin(inst, "VGND", "gnd")
if hasattr(self, 'cell_inst'):
for col in range(self.column_size):
inst = self.cell_inst[0,col]
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()))
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())