checkpoint from tt submission

This commit is contained in:
Jesse Cirimelli-Low 2026-01-14 12:08:26 -08:00
parent 5a74605117
commit 53d53ec271
18 changed files with 154 additions and 113 deletions

View File

@ -611,10 +611,10 @@ class simulation():
Gets the signal name associated with the bitlines in the bank.
"""
# FIXME: change to a solution that does not depend on the technology
if OPTS.tech_name == "sky130" and len(self.all_ports) == 1:
cell_mod = factory.create(module_type=OPTS.bitcell, version="opt1")
else:
cell_mod = factory.create(module_type=OPTS.bitcell)
#if OPTS.tech_name == "sky130" and len(self.all_ports) == 1:
# cell_mod = factory.create(module_type=OPTS.bitcell, version="opt1")
#else:
cell_mod = factory.create(module_type=OPTS.bitcell)
cell_bl = cell_mod.get_bl_name(port)
cell_br = cell_mod.get_br_name(port)

View File

@ -67,7 +67,7 @@ def parse_args():
dest="num_sim_threads"),
optparse.make_option("-v", "--verbose",
action="count",
dest="verbose_level",
dest="5",
help="Increase the verbosity level"),
optparse.make_option("-t", "--tech",
dest="tech_name",

View File

@ -158,10 +158,35 @@ class bitcell_base_array(design):
height=wl_pin.height())
def route_supplies(self):
vdd_found = False
gnd_found = False
for inst in self.insts:
for pin_name in ["vdd", "gnd"]:
if pin_name in inst.mod.get_pin_names():
self.copy_layout_pin(inst, pin_name)
if 'vdd' in inst.mod.get_pin_names():
vdd_found = True
if 'gnd' in inst.mod.get_pin_names():
gnd_found = True
power_name = 'vdd'
ground_name = 'gnd'
if vdd_found is False or gnd_found is False:
from openram.tech import cell_properties
try:
power_name = cell_properties.power_name
except:
pass
try:
ground_name = cell_properties.ground_name
except:
pass
for inst in self.insts:
if power_name in inst.mod.get_pin_names():
self.copy_layout_pin(inst, power_name, new_name='vdd')
if ground_name in inst.mod.get_pin_names():
self.copy_layout_pin(inst, ground_name , new_name='gnd')
def add_layout_pins(self):
""" Add the layout pins """

View File

@ -107,6 +107,7 @@ class capped_replica_bitcell_array(bitcell_base_array):
self.row_cap_left = factory.create(module_type=row_cap_module_type,
cols=1,
column_offset=0,
row_offset=len(self.left_rbl)+len(self.right_rbl),
rows=self.row_size + self.extra_rows,
location="left")
@ -117,6 +118,7 @@ class capped_replica_bitcell_array(bitcell_base_array):
# + bitcell columns
# + right replica column(s)
column_offset=len(self.left_rbl) + self.column_size + self.rbl[0],
row_offset=len(self.left_rbl)+len(self.right_rbl),
rows=self.row_size + self.extra_rows,
location="right")
@ -181,7 +183,7 @@ class capped_replica_bitcell_array(bitcell_base_array):
# Top/bottom dummy rows or col caps
self.dummy_row_insts = []
self.dummy_row_insts.append(self.add_inst(name="dummy_row_bot",
mod=self.col_cap_bottom))
mod=self.col_cap_bottom,))
self.connect_inst(self.bitline_pin_list + ["gnd"] * len(self.col_cap_bottom.get_wordline_names()) + self.supplies)
self.dummy_row_insts.append(self.add_inst(name="dummy_row_top",
mod=self.col_cap_top))
@ -217,7 +219,7 @@ class capped_replica_bitcell_array(bitcell_base_array):
self.capped_rba_height = self.dummy_col_insts[0].height
#self.route_power_ring(self.supply_stack[2], self.supply_stack[0])
self.route_power_ring(self.supply_stack[2], self.supply_stack[0])
self.route_supplies()
self.route_unused_wordlines()
@ -289,6 +291,7 @@ class capped_replica_bitcell_array(bitcell_base_array):
self.dummy_col_insts[1].place(offset=offset)
def add_layout_pins(self):
for pin_name in self.used_wordline_names + self.bitline_pin_list:
pin = self.replica_bitcell_array_inst.get_pin(pin_name)
@ -308,6 +311,7 @@ class capped_replica_bitcell_array(bitcell_base_array):
offset=pin_offset,
width=pin_width,
height=pin_height)
def route_supplies(self):
@ -322,8 +326,8 @@ class capped_replica_bitcell_array(bitcell_base_array):
if top:
inst = self.dummy_row_insts[1]
if "vdd" in inst.mod.pins:
array_pins = inst.get_pins("vdd")
if 'vdd' in inst.mod.pins:
array_pins = inst.get_pins('vdd')
for array_pin in array_pins:
supply_pin = self.top_vdd_pin
self.add_path(array_pin.layer, [array_pin.center(), vector(array_pin.center()[0], supply_pin.center()[1])])
@ -331,7 +335,7 @@ class capped_replica_bitcell_array(bitcell_base_array):
to_layer = supply_pin.layer,
offset = vector(array_pin.center()[0], supply_pin.center()[1]))
array_pins = inst.get_pins("gnd")
array_pins = inst.get_pins('gnd')
for array_pin in array_pins:
supply_pin = self.top_gnd_pin
self.add_path(array_pin.layer, [array_pin.center(), vector(array_pin.center()[0], supply_pin.center()[1])])
@ -340,8 +344,8 @@ class capped_replica_bitcell_array(bitcell_base_array):
offset = vector(array_pin.center()[0], supply_pin.center()[1]))
if bottom:
inst = self.dummy_row_insts[0]
if "vdd" in inst.mod.pins:
array_pins = inst.get_pins("vdd")
if 'vdd' in inst.mod.pins:
array_pins = inst.get_pins('vdd')
for array_pin in array_pins:
supply_pin = self.bottom_vdd_pin
self.add_path(array_pin.layer, [array_pin.center(), vector(array_pin.center()[0], supply_pin.center()[1])])
@ -349,7 +353,7 @@ class capped_replica_bitcell_array(bitcell_base_array):
to_layer = supply_pin.layer,
offset = vector(array_pin.center()[0], supply_pin.center()[1]))
array_pins = inst.get_pins("gnd")
array_pins = inst.get_pins('gnd')
for array_pin in array_pins:
supply_pin = self.bottom_gnd_pin
self.add_path(array_pin.layer, [array_pin.center(), vector(array_pin.center()[0], supply_pin.center()[1])])
@ -358,8 +362,8 @@ class capped_replica_bitcell_array(bitcell_base_array):
offset = vector(array_pin.center()[0], supply_pin.center()[1]))
if left:
inst = self.dummy_col_insts[0]
if "vdd" in inst.mod.pins:
array_pins = inst.get_pins("vdd")
if 'vnd' in inst.mod.pins:
array_pins = inst.get_pins('vnd')
for array_pin in array_pins:
supply_pin = self.left_vdd_pin
self.add_path(array_pin.layer, [array_pin.center(), vector(supply_pin.center()[0], array_pin.center()[1])])
@ -367,7 +371,7 @@ class capped_replica_bitcell_array(bitcell_base_array):
to_layer = supply_pin.layer,
offset = vector(supply_pin.center()[0], array_pin.center()[1]))
array_pins = inst.get_pins("gnd")
array_pins = inst.get_pins('gnd')
for array_pin in array_pins:
supply_pin = self.left_gnd_pin
self.add_path(array_pin.layer, [array_pin.center(), vector(supply_pin.center()[0], array_pin.center()[1])])
@ -376,8 +380,8 @@ class capped_replica_bitcell_array(bitcell_base_array):
offset = vector(supply_pin.center()[0], array_pin.center()[1]))
if right:
inst = self.dummy_col_insts[1]
if "vdd" in inst.mod.pins:
array_pins = inst.get_pins("vdd")
if 'vdd' in inst.mod.pins:
array_pins = inst.get_pins('vdd')
for array_pin in array_pins:
supply_pin = self.right_vdd_pin
self.add_path(array_pin.layer, [array_pin.center(), vector(supply_pin.center()[0], array_pin.center()[1])])
@ -385,29 +389,30 @@ class capped_replica_bitcell_array(bitcell_base_array):
to_layer = supply_pin.layer,
offset = vector(supply_pin.center()[0], array_pin.center()[1]))
array_pins = inst.get_pins("gnd")
array_pins = inst.get_pins('gnd')
for array_pin in array_pins:
supply_pin = self.right_gnd_pin
self.add_path(array_pin.layer, [array_pin.center(), vector(supply_pin.center()[0], array_pin.center()[1])])
self.add_via_stack_center(from_layer = array_pin.layer,
to_layer = supply_pin.layer,
offset = vector(supply_pin.center()[0], array_pin.center()[1]))
offset = vector(supply_pin.center()[0], array_pin.center()[1]))
def route_unused_wordlines(self):
"""
Connect the unused RBL and dummy wordlines to gnd
"""
# This grounds all the dummy row word lines
for inst in self.dummy_row_insts:
for wl_name in self.col_cap_top.get_wordline_names():
for wl_name in inst.mod.get_wordline_names():
pin = inst.get_pin(wl_name)
self.connect_side_pin(pin, "left", self.left_gnd_locs[0].x)
self.connect_side_pin(pin, "right", self.right_gnd_locs[0].x)
self.connect_side_pin(pin, "left", self.left_gnd_pin.cx())
self.connect_side_pin(pin, "right", self.right_gnd_pin.cx())
# Ground the unused replica wordlines
for wl_name in self.unused_wordline_names:
pin = self.replica_bitcell_array_inst.get_pin(wl_name)
self.connect_side_pin(pin, "left", self.left_gnd_locs[0].x)
self.connect_side_pin(pin, "right", self.right_gnd_locs[0].x)
self.connect_side_pin(pin, "left", self.left_gnd_pin.cx())
self.connect_side_pin(pin, "right", self.right_gnd_pin.cx())
def route_side_pin(self, name, side, offset_multiple=1):
"""

View File

@ -6,7 +6,8 @@
from openram.sram_factory import factory
from openram import OPTS
from .bitcell_base_array import bitcell_base_array
from openram.base import geometry
from .pattern import pattern
class col_cap_array(bitcell_base_array):
"""

View File

@ -14,7 +14,7 @@ class dummy_array(bitcell_base_array):
Generate a dummy row/column for the replica array.
"""
def __init__(self, rows, cols, column_offset=0, row_offset=0 ,mirror=0, location="", name=""):
def __init__(self, rows, cols, column_offset=0, row_offset=0 ,mirror=0, location="", name="", left_rbl=0, right_rbl=0):
super().__init__(rows=rows, cols=cols, column_offset=column_offset, name=name)
self.location = location
self.row_offset = row_offset
@ -57,14 +57,14 @@ class dummy_array(bitcell_base_array):
self.cell_inst={}
if self.cell.mirror.y:
core_block = [[0 for x in range(2)] for y in range(2)]
core_block[(0+self.mirror) %2][0] = geometry.instance("core_0_0", mod=self.dummy_cell, is_bitcell=True)
core_block[(1+self.mirror) %2][0] = geometry.instance("core_1_0", mod=self.dummy_cell, is_bitcell=True, mirror='MX')
core_block[(0+self.mirror) %2][1] = geometry.instance("core_0_1", mod=self.dummy_cell, is_bitcell=True, mirror='MY')
core_block[(1+self.mirror) %2][1] = geometry.instance("core_1_1", mod=self.dummy_cell, is_bitcell=True, mirror='XY')
core_block[(0+self.mirror) %2][(1+self.column_offset+self.row_offset) %2] = geometry.instance("core_0_0", mod=self.dummy_cell, is_bitcell=True, mirror='MX')
core_block[(1+self.mirror) %2][(1+self.column_offset+self.row_offset) %2] = geometry.instance("core_1_0", mod=self.dummy_cell, is_bitcell=True)
core_block[(0+self.mirror) %2][(0+self.column_offset+self.row_offset) %2] = geometry.instance("core_0_1", mod=self.dummy_cell, is_bitcell=True, mirror='XY')
core_block[(1+self.mirror) %2][(0+self.column_offset+self.row_offset) %2] = geometry.instance("core_1_1", mod=self.dummy_cell, is_bitcell=True, mirror='MY')
else:
core_block = [[0 for x in range(1)] for y in range(2)]
core_block[(0+self.mirror) %2][0] = geometry.instance("core_0_0", mod=self.dummy_cell, is_bitcell=True)
core_block[(1+self.mirror) %2][0] = geometry.instance("core_1_0", mod=self.dummy_cell, is_bitcell=True, mirror='MX')
core_block[(0+self.mirror) %2][(1+self.column_offset) %2] = geometry.instance("core_0_0", mod=self.dummy_cell, is_bitcell=True, mirror='MX')
core_block[(1+self.mirror) %2][(1+self.column_offset) %2] = geometry.instance("core_1_0", mod=self.dummy_cell, is_bitcell=True)
self.pattern = pattern(self, "dummy_array", core_block, num_rows=self.row_size, num_cols=self.column_size, name_template="bit_r{0}_c{1}")

View File

@ -187,7 +187,7 @@ class pattern():
inst.place((x, y), inst.mirror, inst.rotate)
def place_array(self):
(self.row_max, self.col_max) = list(self.parent_design.all_inst.keys())[-1]
y = 0
for row in range(self.row_max+1):

View File

@ -95,17 +95,18 @@ class replica_column(bitcell_base_array):
# Replic bit specifies which other bit (in the full range (0,total_size) to make a replica cell.
# All other cells are dummies
if (row == self.replica_bit) or (row >= self.row_start and row < self.row_end):
if current_row % 2 == 0:
if current_row % 2 == 1:
core_block[row][0] = geometry.instance("rbc_{}".format(row), mod=self.replica_cell, is_bitcell=True)
else:
core_block[row][0] = geometry.instance("rbc_{}".format(row), mod=self.replica_cell, is_bitcell=True, mirror='MX')
else:
if current_row % 2 == 0:
if current_row % 2 == 1:
core_block[row][0] = geometry.instance("rbc_{}".format(row), mod=self.dummy_cell, is_bitcell=True)
else:
core_block[row][0] = geometry.instance("rbc_{}".format(row), mod=self.dummy_cell, is_bitcell=True, mirror='MX')
current_row += 1
if self.cell.mirror.y:
for row in range(self.total_size):
if self.column_offset % 2 == 0:

View File

@ -141,12 +141,12 @@ class sram_config:
+ " Bank addr size: {}".format(self.bank_addr_size))
num_ports = OPTS.num_rw_ports + OPTS.num_r_ports + OPTS.num_w_ports
if num_ports == 1:
if ((self.num_cols + num_ports + self.num_spare_cols) % self.array_col_multiple != 0):
debug.error("Invalid number of cols including rbl(s): {}. Total cols must be divisible by {}".format(self.num_cols + num_ports + self.num_spare_cols, self.array_col_multiple), -1)
if ((self.num_rows + num_ports) % self.array_row_multiple != 0):
debug.error("invalid number of rows including dummy row(s): {}. Total cols must be divisible by {}".format(self.num_rows + num_ports, self.array_row_multiple), -1)
#if num_ports == 1:
# if ((self.num_cols + num_ports + self.num_spare_cols) % self.array_col_multiple != 0):
# debug.error("Invalid number of cols including rbl(s): {}. Total cols must be divisible by {}".format(self.num_cols + num_ports + self.num_spare_cols, self.array_col_multiple), -1)#
#
# if ((self.num_rows + num_ports) % self.array_row_multiple != 0):
# debug.error("invalid number of rows including dummy row(s): {}. Total cols must be divisible by {}".format(self.num_rows + num_ports, self.array_row_multiple), -1)
def estimate_words_per_row(self, tentative_num_cols, word_size):
"""

View File

@ -31,7 +31,7 @@ class array_test(openram_test):
num_spare_rows = 0
num_spare_cols = 0
a = factory.create(module_type="bitcell_array", cols=8 + num_spare_cols, rows=8 + num_spare_rows)
a = factory.create(module_type="bitcell_array", cols=2 + num_spare_cols, rows=2 + num_spare_rows)
self.local_check(a)
openram.end_openram()

View File

@ -26,7 +26,7 @@ class capped_replica_bitcell_array_norbl_1rw_test(openram_test):
openram.setup_bitcell()
debug.info(2, "Testing 7x5 capped replica array for 1rw cell without replica column or dummy row")
a = factory.create(module_type="capped_replica_bitcell_array", cols=7, rows=5, rbl=[0, 0])
a = factory.create(module_type="capped_replica_bitcell_array", cols=8, rows=6, rbl=[0, 0])
self.local_check(a)
openram.end_openram()

View File

@ -26,7 +26,7 @@ class replica_bitcell_array_leftrbl_1rw_test(openram_test):
openram.setup_bitcell()
debug.info(2, "Testing 7x5 replica array for 1rw cell with left replica column")
a = factory.create(module_type="replica_bitcell_array", cols=7, rows=5, rbl=[1, 0], left_rbl=[0])
a = factory.create(module_type="replica_bitcell_array", cols=8, rows=8, rbl=[1, 0], left_rbl=[0])
self.local_check(a)
openram.end_openram()

View File

@ -24,7 +24,9 @@ class single_bank_test(openram_test):
from openram import sram_config
c = sram_config(word_size=4,
num_words=16)
num_words=16,
num_spare_cols=1,
num_spare_rows=1)
c.num_words=32
c.words_per_row=2

View File

@ -1,4 +1,7 @@
#!/bin/bash
#CONDA_INSTALLER_URL="https://repo.anaconda.com/miniconda/Miniconda3-py313_25.11.1-1-Linux-x86_64.sh"
#CONDA_INSTALLER_FILE="miniconda_installer_py313.sh"
CONDA_INSTALLER_URL="https://repo.anaconda.com/miniconda/Miniconda3-py38_23.11.0-2-Linux-x86_64.sh"
CONDA_INSTALLER_FILE="miniconda_installer_py38.sh"
CONDA_HOME="${CONDA_HOME:-miniconda}"
@ -6,12 +9,12 @@ CONDA_HOME="${CONDA_HOME:-miniconda}"
# The tool name format is "<tool>=<version>".
# If you want to use the latest version, just use "<tool>".
TOOLS=""
TOOLS+="klayout=0.28.3 "
TOOLS+="magic=8.3.497 "
#TOOLS+="klayout=0.28.3 "
TOOLS+="magic=8.3.587 "
TOOLS+="netgen=1.5.286 "
TOOLS+="ngspice=26 "
TOOLS+="trilinos=12.12.1=1 "
TOOLS+="xyce=7.4=3"
TOOLS+="xyce=7.4"
# Install miniconda if not already installed
if [[ ! -d "${CONDA_HOME}/bin" ]]
@ -24,16 +27,16 @@ then
# Prioritize channels to prevent version conflicts
conda config --add channels conda-forge
conda config --add channels vlsida-eda
# Install iverilog from conda-eda
conda install -q -y -c litex-hub iverilog
#conda install -q -y -c conda-forge trilinos
# Install rest of the tools from vlsida-eda
for tool in ${TOOLS}
do
conda install -q -y -c vlsida-eda ${tool}
done
# Install iverilog from conda-eda
conda install -q -y -c litex-hub iverilog
# Install required Python packages
# (This step isn't required but used to prevent possible issues)
python3 -m pip install -r requirements.txt --ignore-installed

View File

@ -4,12 +4,13 @@ Dual port (1 read/write + 1 read only) 1 kbytes SRAM with byte write.
FIXME: What is this useful for?
FIXME: Why would you want byte write on this?
"""
word_size = 8 # Bits
word_size = 16 # Bits
num_words = 16
human_byte_size = "{:.0f}kbytes".format((word_size * num_words)/1024/8)
# Allow byte writes
write_size = 2 # Bits
write_size = 8 # Bits
words_per_row = 1
# Dual port
num_rw_ports = 1
@ -17,8 +18,11 @@ num_r_ports = 0
num_w_ports = 0
ports_human = '1rw'
num_spare_cols = 1
num_spare_rows = 1
#num_spare_cols = 1
#num_spare_rows = 1
netlist_only = True
num_sim_threads = 1
#analytical_delay = False
import os
exec(open(os.path.join(os.path.dirname(__file__), 'sky130_sram_common.py')).read())

View File

@ -15,19 +15,11 @@ class sky130_col_cap(design):
def __init__(self, version, name="",left_rbl=[],right_rbl=[]):
if version == "colend":
if OPTS.control_logic == "control_logic_delay" or not right_rbl:
cell_name = "sky130_fd_bd_sram__sram_sp_colend"
else:
cell_name = "sky130_fd_bd_sram__openram_sp_colend_replica"
cell_name = "sky130_fd_bd_sram__sram_sp_colend"
prop = props.col_cap_1port_bitcell
elif version == "colenda":
if OPTS.control_logic == "control_logic_delay" or not left_rbl:
cell_name = "sky130_fd_bd_sram__sram_sp_colenda"
else:
cell_name = "sky130_fd_bd_sram__openram_sp_colenda_replica"
cell_name = "sky130_fd_bd_sram__sram_sp_colenda"
prop = props.col_cap_1port_bitcell
elif version == "colend_p_cent":
cell_name = "sky130_fd_bd_sram__sram_sp_colend_p_cent"
prop = props.col_cap_1port_strap_ground
@ -41,5 +33,5 @@ class sky130_col_cap(design):
cell_name = "sky130_fd_bd_sram__sram_sp_colenda_cent"
prop = props.col_cap_1port_strap_power
else:
debug.error("Invalid type for col_end", -1)
debug.error("Invalid type for col_end: {}".format(version), -1)
super().__init__(name=name, cell_name=cell_name, prop=prop)

View File

@ -17,7 +17,7 @@ class sky130_row_cap_array(row_cap_array, sky130_bitcell_base_array):
"""
Generate a dummy row/column for the replica array.
"""
def __init__(self, rows, cols, column_offset=0, mirror=0, location="", name=""):
def __init__(self, rows, cols, column_offset=0, row_offset=0, mirror=0, location="", name=""):
super().__init__(rows, cols, column_offset=column_offset, location=location, name=name)
self.mirror = mirror
self.location = location

View File

@ -24,6 +24,7 @@ File containing the process technology parameters for Skywater 130nm.
# For example: tech_modules["contact"] = "contact_freepdk45"
tech_modules = d.module_type()
# These modules have been hand designed and provided in this repository.
tech_modules["nand2_dec"] = "nand2_dec"
tech_modules["nand3_dec"] = "nand3_dec"
@ -33,23 +34,24 @@ tech_modules["nand4_dec"] = "nand4_dec"
# These are for single port and dual port as a list,
# or for both if there is no list,
# or only applicable to one if there is no list.
tech_modules["bitcell_1port"] = "sky130_bitcell"
tech_modules["replica_bitcell_1port"] = "sky130_replica_bitcell"
tech_modules["dummy_bitcell_1port"] = "sky130_dummy_bitcell"
#tech_modules["bitcell_1port"] = "sky130_bitcell"
#tech_modules["replica_bitcell_1port"] = "sky130_replica_bitcell"
#tech_modules["dummy_bitcell_1port"] = "sky130_dummy_bitcell"
tech_modules["replica_bitcell_2port"] = "replica_bitcell_2port"
tech_modules["dummy_bitcell_2port"] = "dummy_bitcell_2port"
tech_modules["bitcell_2port"] = "bitcell_2port"
tech_modules["bitcell_array"] = ["sky130_bitcell_array", "bitcell_array"]
tech_modules["replica_bitcell_array"] = ["sky130_replica_bitcell_array", "replica_bitcell_array"]
tech_modules["capped_replica_bitcell_array"] = ["sky130_capped_replica_bitcell_array", "capped_replica_bitcell_array"]
tech_modules["dummy_array"] = ["sky130_dummy_array", "dummy_array"]
tech_modules["bitcell_array"] = ["bitcell_array", "bitcell_array"]
tech_modules["replica_bitcell_array"] = ["replica_bitcell_array", "replica_bitcell_array"]
tech_modules["capped_replica_bitcell_array"] = ["capped_replica_bitcell_array", "capped_replica_bitcell_array"]
tech_modules["dummy_array"] = ["dummy_array", "dummy_array"]
tech_modules["replica_column"] = ["sky130_replica_column", "replica_column"]
tech_modules["replica_column"] = ["replica_column", "replica_column"]
tech_modules["col_cap_array"] = ["sky130_col_cap_array", "col_cap_array"]
tech_modules["col_cap"] = ["sky130_col_cap", "col_cap_bitcell_2port"]
tech_modules["col_cap_array"] = ["col_cap_array", "col_cap_array"]
tech_modules["col_cap"] = ["col_cap_bitcell_1port", "col_cap_bitcell_2port"]
tech_modules["corner"] = ["sky130_corner", None]
tech_modules["internal"] = ["sky130_internal", None]
tech_modules["row_cap_array"] = ["sky130_row_cap_array", "row_cap_array"]
@ -68,28 +70,32 @@ tech_modules["and4_dec"] = "and4_dec"
###################################################
cell_properties = d.cell_properties()
cell_properties.bitcell_power_pin_directions = ("H", "H")
cell_properties.power_name = 'VPWR'
cell_properties.ground_name = 'VGND'
cell_properties.bitcell_power_pin_directions = ("V", "V")
cell_properties.bitcell_1port.mirror.x = True
cell_properties.bitcell_1port.mirror.y = True
cell_properties.bitcell_1port.end_caps = True
cell_properties.bitcell_1port.boundary_layer = "mem"
cell_properties.bitcell_1port.port_order = ['bl', 'br', 'gnd', 'vdd', 'vpb', 'vnb', 'wl']
cell_properties.bitcell_1port.port_types = ["OUTPUT", "OUTPUT", "GROUND", "POWER", "BIAS", "BIAS", "INPUT"]
cell_properties.bitcell_1port.end_caps = False
cell_properties.bitcell_1port.boundary_layer = "boundary"
cell_properties.bitcell_1port.port_order = ['bl', 'br', 'wl', 'vdd', 'gnd']
cell_properties.bitcell_1port.port_types = ["INPUT", "INPUT", "GROUND", "POWER", "OUTPUT"]
cell_properties.bitcell_1port.port_map = {'bl': 'BL',
'br': 'BR',
'wl': 'WL',
'gnd': 'VGND',
'vdd': 'VPWR',
'vnb': 'VNB',
'vpb': 'VPB',
'gnd': 'VGND'}
'wl': 'WL'}
cell_properties.bitcell_1port.wl_layer = "m2"
cell_properties.bitcell_1port.bl_layer = "m1"
cell_properties.bitcell_1port.vdd_layer = "m1"
cell_properties.bitcell_1port.vdd_dir = "V"
cell_properties.bitcell_1port.gnd_layer = "m2"
cell_properties.bitcell_1port.gnd_dir = "H"
cell_properties.bitcell_1port.gnd_layer = "m1"
cell_properties.bitcell_1port.gnd_dir = "V"
cell_properties.bitcell_2port.mirror.x = True
cell_properties.bitcell_2port.mirror.y = True
@ -103,47 +109,45 @@ cell_properties.bitcell_2port.port_map = {'bl0': 'BL0',
'wl1': 'WL1',
'vdd': 'VDD',
'gnd': 'GND'}
cell_properties.bitcell_1port.wl_layer = "m2"
cell_properties.bitcell_1port.vdd_layer = "m2"
cell_properties.bitcell_1port.vdd_dir = "H"
cell_properties.bitcell_1port.gnd_layer = "m2"
cell_properties.bitcell_1port.gnd_dir = "H"
cell_properties.bitcell_1port.vdd_layer = "m1"
cell_properties.bitcell_1port.vdd_dir = "V"
cell_properties.bitcell_1port.gnd_layer = "m1"
cell_properties.bitcell_1port.gnd_dir = "V"
cell_properties.bitcell_2port.wl_layer = "m2"
cell_properties.bitcell_2port.vdd_layer = "m1"
cell_properties.bitcell_2port.vdd_dir = "H"
cell_properties.bitcell_2port.gnd_layer = "m2"
cell_properties.bitcell_2port.gnd_dir = "H"
cell_properties.col_cap_1port_bitcell = d.cell(['bl', 'br', 'vdd', 'gnd', 'vpb', 'vnb', 'gate'],
['INPUT', 'INPUT','POWER', 'GROUND', 'BIAS', 'BIAS', 'INPUT'],
cell_properties.col_cap_1port_bitcell = d.cell(['bl', 'br', 'vdd', 'gnd',],
['INPUT', 'INPUT','POWER', 'GROUND', ],
{'bl': 'bl',
'br': 'br',
'vdd': 'vdd',
'gnd': 'gnd',
'vnb': 'vnb',
'vpb': 'vpb',
'gate': 'gate'})
cell_properties.col_cap_1port_bitcell.boundary_layer = "mem"
'gnd': 'gnd',})
cell_properties.col_cap_1port_bitcell.boundary_layer = "boundary"
cell_properties.col_cap_1port_strap_power = d.cell(['vdd', 'vpb', 'vnb'],
['POWER', 'BIAS', 'BIAS'],
{'vnb': 'VNB',
'vpb': 'VPB',
'vdd': 'VPWR'})
cell_properties.col_cap_1port_strap_power.boundary_layer = "mem"
cell_properties.col_cap_1port_strap_power.boundary_layer = "boundary"
cell_properties.col_cap_1port_strap_ground = d.cell(['gnd', 'vpb', 'vnb'],
['GROUND', 'BIAS', 'BIAS'],
{'vnb': 'VNB',
'vpb': 'VPB',
'gnd': 'VGND'})
cell_properties.col_cap_1port_strap_ground.boundary_layer = "mem"
cell_properties.col_cap_1port_strap_ground.boundary_layer = "boundary"
cell_properties.row_cap_1port_cell = d.cell(['vdd', 'wl'],
['POWER', 'INPUT'],
{'wl': 'WL',
'vdd': 'VPWR'})
cell_properties.row_cap_1port_cell.boundary_layer = "mem"
cell_properties.row_cap_1port_cell.boundary_layer = "boundary"
cell_properties.col_cap_2port.port_order = ['bl0', 'br0', 'bl1', 'br1', 'vdd']
cell_properties.col_cap_2port.port_map = {'bl0': 'BL0',
@ -163,7 +167,7 @@ cell_properties.ptx.model_is_subckt = True
cell_properties.pgate.add_implants = True
cell_properties.use_strap = True
cell_properties.use_strap = False
cell_properties.strap_module = "internal"
cell_properties.strap_version = "wlstrap"
@ -219,9 +223,13 @@ cell_properties.write_driver.port_map = {'din': 'DIN',
# If it is a list, the first is single port and the second is dual port.
# If it is string, it is used for both single and dual port.
cell_properties.names["dff"] = "sky130_fd_bd_sram__openram_dff"
cell_properties.names["nand2_dec"] = ["sky130_fd_bd_sram__openram_sp_nand2_dec", "sky130_fd_bd_sram__openram_dp_nand2_dec"]
cell_properties.names["nand3_dec"] = ["sky130_fd_bd_sram__openram_sp_nand3_dec", "sky130_fd_bd_sram__openram_dp_nand3_dec"]
cell_properties.names["nand4_dec"] = ["sky130_fd_bd_sram__openram_sp_nand4_dec", "sky130_fd_bd_sram__openram_dp_nand4_dec"]
cell_properties.names["nand2_dec"] = ["sky130_fd_bd_sram__openram_dp_nand2_dec", "sky130_fd_bd_sram__openram_dp_nand2_dec"]
cell_properties.names["nand3_dec"] = ["sky130_fd_bd_sram__openram_dp_nand3_dec", "sky130_fd_bd_sram__openram_dp_nand3_dec"]
cell_properties.names["nand4_dec"] = ["sky130_fd_bd_sram__openram_dp_nand4_dec", "sky130_fd_bd_sram__openram_dp_nand4_dec"]
cell_properties.names["bitcell_1port"] = "sky130_custom_cell"
cell_properties.names["replica_bitcell_1port"] = "sky130_custom_replica"
cell_properties.names["dummy_bitcell_1port"] = "sky130_custom_dummy"
cell_properties.names["bitcell_2port"] = "sky130_fd_bd_sram__openram_dp_cell"
cell_properties.names["dummy_bitcell_2port"] = "sky130_fd_bd_sram__openram_dp_cell_dummy"
@ -253,7 +261,7 @@ layer_properties.hierarchical_predecode.input_layer = "li"
layer_properties.hierarchical_predecode.output_layer = "m2"
layer_properties.hierarchical_predecode.vertical_supply = True
layer_properties.hierarchical_predecode.force_horizontal_input_contact = True
layer_properties.bank.stack = "m2_stack"
layer_properties.bank.pitch = "m3_pitch"
@ -265,7 +273,7 @@ layer_properties.port_address.supply_offset = True
layer_properties.port_data.enable_layer = "m1"
layer_properties.port_data.channel_route_bitlines = False
layer_properties.replica_column.even_rows = True
layer_properties.replica_column.even_rows = False
layer_properties.wordline_driver.vertical_supply = True