mirror of https://github.com/VLSIDA/OpenRAM.git
Merge branch 'dev' into gridless_router
This commit is contained in:
commit
53d00f5b34
2
Makefile
2
Makefile
|
|
@ -13,7 +13,7 @@ SRAM_LIB_GIT_REPO ?= https://github.com/vlsida/sky130_fd_bd_sram.git
|
|||
# Use this for development
|
||||
#SRAM_LIB_GIT_REPO ?= git@github.com:VLSIDA/sky130_fd_bd_sram.git
|
||||
#SRAM_LIB_GIT_REPO ?= https://github.com/google/skywater-pdk-libs-sky130_fd_bd_sram.git
|
||||
SRAM_LIB_GIT_COMMIT ?= a83b6468c48434d927b90058b22047843c58027b
|
||||
SRAM_LIB_GIT_COMMIT ?= 060f3638be6269dd9aa82cfbbdfd9525943c1582
|
||||
|
||||
# Open PDKs
|
||||
OPEN_PDKS_DIR ?= $(PDK_ROOT)/open_pdks
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ class spice():
|
|||
self.trim_insts = set()
|
||||
# Keep track of any comments to add the the spice
|
||||
try:
|
||||
self.commments
|
||||
self.comments
|
||||
except AttributeError:
|
||||
self.comments = []
|
||||
|
||||
|
|
@ -82,7 +82,7 @@ class spice():
|
|||
""" Add a comment to the spice file """
|
||||
|
||||
try:
|
||||
self.commments
|
||||
self.comments
|
||||
except AttributeError:
|
||||
self.comments = []
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ class wire_spice_model():
|
|||
def cal_wire_c(self, wire_length, wire_width):
|
||||
from openram.tech import spice
|
||||
# Convert the F/um^2 to fF/um^2 then multiple by width and length
|
||||
# FIXME: shouldn't it be 1e15?
|
||||
total_c = (spice["wire_unit_c"]*1e12) * wire_length * wire_width
|
||||
wire_c = total_c / self.lump_num
|
||||
return wire_c
|
||||
|
|
|
|||
|
|
@ -594,7 +594,7 @@ class simulation():
|
|||
for path in paths:
|
||||
aliases = self.sram.find_aliases(self.sram_instance_name, self.pins, path, internal_net, mod, exclusion_set)
|
||||
if net_found and len(aliases) >= 1:
|
||||
debug.error('Found multiple paths with {} net.'.format(internal_net), 1)
|
||||
pass #debug.error('Found multiple paths with {} net.'.format(internal_net), 1)
|
||||
elif len(aliases) > 1:
|
||||
debug.error('Found multiple {} nets in single path.'.format(internal_net), 1)
|
||||
elif not net_found and len(aliases) == 1:
|
||||
|
|
|
|||
|
|
@ -85,7 +85,8 @@ class bank(design):
|
|||
for bit in range(self.word_size + self.num_spare_cols):
|
||||
self.add_pin("dout{0}_{1}".format(port, bit), "OUTPUT")
|
||||
for port in self.all_ports:
|
||||
self.add_pin("rbl_bl_{0}_{0}".format(port), "OUTPUT")
|
||||
if self.has_rbl:
|
||||
self.add_pin("rbl_bl_{0}_{0}".format(port), "OUTPUT")
|
||||
for port in self.write_ports:
|
||||
for bit in range(self.word_size + self.num_spare_cols):
|
||||
self.add_pin("din{0}_{1}".format(port, bit), "INPUT")
|
||||
|
|
@ -114,11 +115,10 @@ class bank(design):
|
|||
""" Create routing amoung the modules """
|
||||
self.route_central_bus()
|
||||
|
||||
self.route_unused_wordlines()
|
||||
|
||||
for port in self.all_ports:
|
||||
self.route_bitlines(port)
|
||||
self.route_rbl(port)
|
||||
if self.has_rbl:
|
||||
self.route_rbl(port)
|
||||
self.route_port_address(port)
|
||||
self.route_column_address_lines(port)
|
||||
self.route_control_lines(port)
|
||||
|
|
@ -360,6 +360,18 @@ class bank(design):
|
|||
def add_modules(self):
|
||||
""" Add all the modules using the class loader """
|
||||
|
||||
# delay control logic does not have RBLs
|
||||
if OPTS.control_logic != "control_logic_delay":
|
||||
self.has_rbl = True
|
||||
rbl = [1, 1 if len(self.all_ports)>1 else 0]
|
||||
left_rbl = [0]
|
||||
right_rbl = [1] if len(self.all_ports)>1 else []
|
||||
else:
|
||||
self.has_rbl = False
|
||||
rbl = [0, 0]
|
||||
left_rbl = []
|
||||
right_rbl = []
|
||||
|
||||
local_array_size = OPTS.local_array_size
|
||||
|
||||
if local_array_size > 0:
|
||||
|
|
@ -372,21 +384,25 @@ class bank(design):
|
|||
cols.append(local_array_size + final_size)
|
||||
self.bitcell_array = factory.create(module_type="global_bitcell_array",
|
||||
cols=cols,
|
||||
rows=self.num_rows)
|
||||
rows=self.num_rows,
|
||||
rbl=rbl,
|
||||
left_rbl=left_rbl,
|
||||
right_rbl=right_rbl)
|
||||
else:
|
||||
self.bitcell_array = factory.create(module_type="capped_replica_bitcell_array",
|
||||
cols=self.num_cols + self.num_spare_cols,
|
||||
rows=self.num_rows,
|
||||
rbl=[1, 1 if len(self.all_ports)>1 else 0],
|
||||
left_rbl=[0],
|
||||
right_rbl=[1] if len(self.all_ports)>1 else [])
|
||||
rbl=rbl,
|
||||
left_rbl=left_rbl,
|
||||
right_rbl=right_rbl)
|
||||
|
||||
self.port_address = []
|
||||
for port in self.all_ports:
|
||||
self.port_address.append(factory.create(module_type="port_address",
|
||||
cols=self.num_cols + self.num_spare_cols,
|
||||
rows=self.num_rows,
|
||||
port=port))
|
||||
port=port,
|
||||
has_rbl=self.has_rbl))
|
||||
|
||||
self.port_data = []
|
||||
self.bit_offsets = self.get_column_offsets()
|
||||
|
|
@ -394,6 +410,7 @@ class bank(design):
|
|||
self.port_data.append(factory.create(module_type="port_data",
|
||||
sram_config=self.sram_config,
|
||||
port=port,
|
||||
has_rbl=self.has_rbl,
|
||||
bit_offsets=self.bit_offsets))
|
||||
|
||||
def create_bitcell_array(self):
|
||||
|
|
@ -407,9 +424,10 @@ class bank(design):
|
|||
# gnd
|
||||
temp = self.bitcell_array.get_inouts()
|
||||
|
||||
temp.append("rbl_wl0")
|
||||
if self.has_rbl:
|
||||
temp.append("rbl_wl0")
|
||||
temp.extend(self.bitcell_array.get_wordline_names())
|
||||
if len(self.all_ports) > 1:
|
||||
if len(self.all_ports) > 1 and self.has_rbl:
|
||||
temp.append("rbl_wl1")
|
||||
|
||||
temp.append("vdd")
|
||||
|
|
@ -432,7 +450,8 @@ class bank(design):
|
|||
mod=self.port_data[port])
|
||||
|
||||
temp = []
|
||||
temp.extend(["rbl_bl_{0}_{0}".format(port), "rbl_br_{0}_{0}".format(port)])
|
||||
if self.has_rbl:
|
||||
temp.extend(["rbl_bl_{0}_{0}".format(port), "rbl_br_{0}_{0}".format(port)])
|
||||
temp.extend(self.bitcell_array.get_bitline_names(port))
|
||||
if port in self.read_ports:
|
||||
for bit in range(self.word_size + self.num_spare_cols):
|
||||
|
|
@ -480,7 +499,8 @@ class bank(design):
|
|||
temp.append("wl_en{}".format(port))
|
||||
wordline_names = self.bitcell_array.get_wordline_names(port)
|
||||
temp.extend(wordline_names)
|
||||
temp.append("rbl_wl{}".format(port))
|
||||
if self.has_rbl:
|
||||
temp.append("rbl_wl{}".format(port))
|
||||
temp.extend(["vdd", "gnd"])
|
||||
self.connect_inst(temp)
|
||||
|
||||
|
|
@ -719,8 +739,9 @@ class bank(design):
|
|||
inst2_br_name=inst2_br_name)
|
||||
|
||||
# Connect the replica bitlines
|
||||
for (array_name, data_name) in zip(["rbl_bl_{0}_{0}".format(port), "rbl_br_{0}_{0}".format(port)], ["rbl_bl", "rbl_br"]):
|
||||
self.connect_bitline(inst1, inst2, array_name, data_name)
|
||||
if self.has_rbl:
|
||||
for (array_name, data_name) in zip(["rbl_bl_{0}_{0}".format(port), "rbl_br_{0}_{0}".format(port)], ["rbl_bl", "rbl_br"]):
|
||||
self.connect_bitline(inst1, inst2, array_name, data_name)
|
||||
|
||||
def route_port_data_out(self, port):
|
||||
""" Add pins for the port data out """
|
||||
|
|
@ -841,8 +862,13 @@ class bank(design):
|
|||
def route_port_address_out(self, port, side="left"):
|
||||
""" Connecting Wordline driver output to Bitcell WL connection """
|
||||
|
||||
driver_names = ["wl_{}".format(x) for x in range(self.num_rows)] + ["rbl_wl"]
|
||||
rbl_wl_name = self.bitcell_array.get_rbl_wordline_names(port)[port]
|
||||
driver_names = ["wl_{}".format(x) for x in range(self.num_rows)]
|
||||
if self.has_rbl:
|
||||
driver_names = driver_names + ["rbl_wl"]
|
||||
rbl_wl_name = self.bitcell_array.get_rbl_wordline_names(port)[port]
|
||||
else:
|
||||
rbl_wl_name = None
|
||||
# rbl_wl in next line will be ignored by zip once driver_names is exhausted in the no rbl case
|
||||
for (driver_name, array_name) in zip(driver_names, self.bitcell_array.get_wordline_names(port) + [rbl_wl_name]):
|
||||
# The mid guarantees we exit the input cell to the right.
|
||||
driver_wl_pin = self.port_address_inst[port].get_pin(driver_name)
|
||||
|
|
@ -875,7 +901,10 @@ class bank(design):
|
|||
def route_port_address_right(self, port):
|
||||
""" Connecting Wordline driver output to Bitcell WL connection """
|
||||
|
||||
driver_names = ["wl_{}".format(x) for x in range(self.num_rows)] + ["rbl_wl"]
|
||||
driver_names = ["wl_{}".format(x) for x in range(self.num_rows)]
|
||||
if self.has_rbl:
|
||||
driver_names = driver_names + ["rbl_wl"]
|
||||
# rbl_wl in next two lines will be ignored by zip once driver_names is exhausted in the no rbl case
|
||||
rbl_wl_name = self.bitcell_array.get_rbl_wordline_names(port)[port]
|
||||
for (driver_name, array_name) in zip(driver_names, self.bitcell_array.get_wordline_names(port) + [rbl_wl_name]):
|
||||
# The mid guarantees we exit the input cell to the right.
|
||||
|
|
@ -971,36 +1000,6 @@ class bank(design):
|
|||
# layer="m1",
|
||||
# offset=data_pin.center())
|
||||
|
||||
def route_unused_wordlines(self):
|
||||
""" Connect the unused RBL and dummy wordlines to gnd """
|
||||
gnd_wl_names = []
|
||||
return
|
||||
# Connect unused RBL WL to gnd
|
||||
# All RBL WL names
|
||||
array_rbl_names = set(self.bitcell_array.get_rbl_wordline_names())
|
||||
# List of used RBL WL names
|
||||
rbl_wl_names = set()
|
||||
for port in self.all_ports:
|
||||
rbl_wl_names.add(self.bitcell_array.get_rbl_wordline_names(port)[port])
|
||||
gnd_wl_names = list((array_rbl_names - rbl_wl_names))
|
||||
|
||||
for wl_name in gnd_wl_names:
|
||||
pin = self.bitcell_array_inst.get_pin(wl_name)
|
||||
pin_layer = pin.layer
|
||||
layer_pitch = 1.5 * getattr(self, "{}_pitch".format(pin_layer))
|
||||
left_pin_loc = pin.lc()
|
||||
right_pin_loc = pin.rc()
|
||||
|
||||
# Place the pins a track outside of the array
|
||||
left_loc = left_pin_loc - vector(layer_pitch, 0)
|
||||
right_loc = right_pin_loc + vector(layer_pitch, 0)
|
||||
self.add_power_pin("gnd", left_loc, directions=("H", "H"))
|
||||
self.add_power_pin("gnd", right_loc, directions=("H", "H"))
|
||||
|
||||
# Add a path to connect to the array
|
||||
self.add_path(pin_layer, [left_loc, left_pin_loc])
|
||||
self.add_path(pin_layer, [right_loc, right_pin_loc])
|
||||
|
||||
def route_control_lines(self, port):
|
||||
""" Route the control lines of the entire bank """
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,10 @@ class capped_replica_bitcell_array(bitcell_base_array):
|
|||
self.column_size = cols
|
||||
self.row_size = rows
|
||||
# This is how many RBLs are in all the arrays
|
||||
self.rbl = rbl
|
||||
if rbl is not None:
|
||||
self.rbl = rbl
|
||||
else:
|
||||
self.rbl = [0] * len(self.all_ports)
|
||||
# This specifies which RBL to put on the left or right by port number
|
||||
# This could be an empty list
|
||||
if left_rbl is not None:
|
||||
|
|
@ -64,28 +67,7 @@ class capped_replica_bitcell_array(bitcell_base_array):
|
|||
self.create_instances()
|
||||
|
||||
def add_modules(self):
|
||||
""" Array and dummy/replica columns
|
||||
|
||||
d or D = dummy cell (caps to distinguish grouping)
|
||||
r or R = replica cell (caps to distinguish grouping)
|
||||
b or B = bitcell
|
||||
replica columns 1
|
||||
v v
|
||||
bdDDDDDDDDDDDDDDdb <- Dummy row
|
||||
bdDDDDDDDDDDDDDDrb <- Dummy row
|
||||
br--------------rb
|
||||
br| Array |rb
|
||||
br| row x col |rb
|
||||
br--------------rb
|
||||
brDDDDDDDDDDDDDDdb <- Dummy row
|
||||
bdDDDDDDDDDDDDDDdb <- Dummy row
|
||||
|
||||
^^^^^^^^^^^^^^^
|
||||
dummy rows cols x 1
|
||||
|
||||
^ dummy columns ^
|
||||
1 x (rows + 4)
|
||||
"""
|
||||
""" Array and cap rows/columns """
|
||||
|
||||
self.replica_bitcell_array = factory.create(module_type="replica_bitcell_array",
|
||||
cols=self.column_size,
|
||||
|
|
@ -132,7 +114,7 @@ class capped_replica_bitcell_array(bitcell_base_array):
|
|||
# + right replica column(s)
|
||||
column_offset=1 + len(self.left_rbl) + self.column_size + self.rbl[0],
|
||||
rows=self.row_size + self.extra_rows,
|
||||
mirror=(self.rbl[0] + 1) %2)
|
||||
mirror=(self.rbl[0] + 1) % 2)
|
||||
|
||||
def add_pins(self):
|
||||
|
||||
|
|
@ -219,6 +201,7 @@ class capped_replica_bitcell_array(bitcell_base_array):
|
|||
# row-based or column based power and ground lines.
|
||||
self.vertical_pitch = 1.1 * getattr(self, "{}_pitch".format(self.supply_stack[0]))
|
||||
self.horizontal_pitch = 1.1 * getattr(self, "{}_pitch".format(self.supply_stack[2]))
|
||||
# FIXME: custom sky130 replica module has a better version of this offset
|
||||
self.unused_offset = vector(0.25, 0.25)
|
||||
|
||||
# This is a bitcell x bitcell offset to scale
|
||||
|
|
|
|||
|
|
@ -118,8 +118,6 @@ class control_logic(control_logic_base):
|
|||
# list of output control signals (for making a vertical bus)
|
||||
if self.port_type == "rw":
|
||||
self.internal_bus_list = ["rbl_bl_delay_bar", "rbl_bl_delay", "gated_clk_bar", "gated_clk_buf", "we", "we_bar", "clk_buf", "cs"]
|
||||
elif self.port_type == "r":
|
||||
self.internal_bus_list = ["rbl_bl_delay_bar", "rbl_bl_delay", "gated_clk_bar", "gated_clk_buf", "clk_buf", "cs_bar", "cs"]
|
||||
else:
|
||||
self.internal_bus_list = ["rbl_bl_delay_bar", "rbl_bl_delay", "gated_clk_bar", "gated_clk_buf", "clk_buf", "cs"]
|
||||
# leave space for the bus plus one extra space
|
||||
|
|
|
|||
|
|
@ -328,8 +328,6 @@ class control_logic_base(design):
|
|||
def route_dffs(self):
|
||||
if self.port_type == "rw":
|
||||
dff_out_map = zip(["dout_bar_0", "dout_bar_1", "dout_1"], ["cs", "we", "we_bar"])
|
||||
elif self.port_type == "r":
|
||||
dff_out_map = zip(["dout_bar_0", "dout_0"], ["cs", "cs_bar"])
|
||||
else:
|
||||
dff_out_map = zip(["dout_bar_0"], ["cs"])
|
||||
self.connect_vertical_bus(dff_out_map, self.ctrl_dff_inst, self.input_bus, self.m2_stack[::-1])
|
||||
|
|
|
|||
|
|
@ -0,0 +1,469 @@
|
|||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||
# (acting for and on behalf of Oklahoma State University)
|
||||
# All rights reserved.
|
||||
#
|
||||
|
||||
import math
|
||||
from openram import debug
|
||||
from openram import OPTS
|
||||
from openram.base import design
|
||||
from openram.base import vector
|
||||
from openram.base import logical_effort, convert_farad_to_relative_c
|
||||
from openram.tech import drc, spice
|
||||
from openram.sram_factory import factory
|
||||
from .control_logic_base import control_logic_base
|
||||
|
||||
|
||||
class control_logic_delay(control_logic_base):
|
||||
"""
|
||||
Dynamically generated Control logic for the total SRAM circuit.
|
||||
Variant: delay-based
|
||||
"""
|
||||
|
||||
def __init__(self, num_rows, words_per_row, word_size, spare_columns=None, sram=None, port_type="rw", name=""):
|
||||
""" Constructor """
|
||||
super().__init__(num_rows, words_per_row, word_size, spare_columns, sram, port_type, name)
|
||||
|
||||
def add_pins(self):
|
||||
""" Add the pins to the control logic module. """
|
||||
self.add_pin_list(self.input_list + ["clk"], "INPUT")
|
||||
self.add_pin_list(self.output_list, "OUTPUT")
|
||||
self.add_pin("vdd", "POWER")
|
||||
self.add_pin("gnd", "GROUND")
|
||||
|
||||
def add_modules(self):
|
||||
""" Add all the required modules """
|
||||
|
||||
self.dff = factory.create(module_type="dff_buf")
|
||||
dff_height = self.dff.height
|
||||
|
||||
self.ctrl_dff_array = factory.create(module_type="dff_buf_array",
|
||||
rows=self.num_control_signals,
|
||||
columns=1)
|
||||
|
||||
self.and2 = factory.create(module_type="pand2",
|
||||
size=12,
|
||||
height=dff_height)
|
||||
|
||||
# clk_buf drives a flop for every address
|
||||
addr_flops = math.log(self.num_words, 2) + math.log(self.words_per_row, 2)
|
||||
# plus data flops and control flops
|
||||
num_flops = addr_flops + self.word_size + self.num_spare_cols + self.num_control_signals
|
||||
# each flop internally has a FO 5 approximately
|
||||
# plus about 5 fanouts for the control logic
|
||||
clock_fanout = 5 * num_flops + 5
|
||||
self.clk_buf_driver = factory.create(module_type="pdriver",
|
||||
fanout=clock_fanout,
|
||||
height=dff_height)
|
||||
|
||||
# We will use the maximum since this same value is used to size the wl_en
|
||||
# and the p_en_bar drivers
|
||||
# max_fanout = max(self.num_rows, self.num_cols)
|
||||
|
||||
# wl_en drives every row in the bank
|
||||
# this calculation is from the rbl control logic, it may not be optimal in this circuit
|
||||
size_list = [max(int(self.num_rows / 9), 1), max(int(self.num_rows / 3), 1)]
|
||||
self.wl_en_driver = factory.create(module_type="pdriver",
|
||||
size_list=size_list,
|
||||
height=dff_height)
|
||||
|
||||
# this is the weak timing signal that feeds wl_en_driver
|
||||
self.wl_en_and = factory.create(module_type="pand2",
|
||||
size=1,
|
||||
height=dff_height)
|
||||
|
||||
# w_en drives every write driver
|
||||
self.wen_and = factory.create(module_type="pand3",
|
||||
size=self.word_size + 8,
|
||||
height=dff_height)
|
||||
|
||||
# s_en drives every sense amp
|
||||
self.sen_and3 = factory.create(module_type="pand3",
|
||||
size=self.word_size + self.num_spare_cols,
|
||||
height=dff_height)
|
||||
|
||||
# used to generate inverted signals with low fanout
|
||||
self.inv = factory.create(module_type="pinv",
|
||||
size=1,
|
||||
height=dff_height)
|
||||
|
||||
# p_en_bar drives every column in the bitcell array
|
||||
# but it is sized the same as the wl_en driver with
|
||||
# prepended 3 inverter stages to guarantee it is slower and odd polarity
|
||||
self.p_en_bar_driver = factory.create(module_type="pdriver",
|
||||
fanout=self.num_cols,
|
||||
height=dff_height)
|
||||
|
||||
self.nand2 = factory.create(module_type="pnand2",
|
||||
height=dff_height)
|
||||
|
||||
self.compute_delay_chain_size()
|
||||
self.delay_chain = factory.create(module_type="multi_delay_chain",
|
||||
fanout_list=self.delay_chain_fanout_list,
|
||||
pinout_list=self.delay_chain_pinout_list)
|
||||
|
||||
def compute_delay_chain_size(self):
|
||||
"""
|
||||
calculate the pinouts needed for the delay chain based on
|
||||
wordline, bitline, and precharge delays
|
||||
delays 0 & 1 need to be even for polarity
|
||||
delays 2 - 4 need to be odd for polarity
|
||||
"""
|
||||
bitcell = factory.create(module_type=OPTS.bitcell)
|
||||
# TODO: check that these spice values are up to date in tech files and if not figure out how to update them
|
||||
# 2 access tx gate per cell
|
||||
wordline_area = bitcell.width * drc("minwidth_m1")
|
||||
wordline_cap_ff = self.num_cols * (2 * spice["min_tx_gate_c"] + spice["wire_unit_c"] * 1e15 * wordline_area)
|
||||
wordline_cap = convert_farad_to_relative_c(wordline_cap_ff)
|
||||
# 1 access tx drain per cell
|
||||
bitline_area = bitcell.height * drc("minwidth_m2")
|
||||
bitline_cap_ff = self.num_rows * (spice["min_tx_drain_c"] + spice["wire_unit_c"] * 1e15 * bitline_area)
|
||||
bitline_cap = convert_farad_to_relative_c(bitline_cap_ff)
|
||||
# 3 pmos gate per cell
|
||||
pen_cap_ff = self.num_cols * (3 * spice["min_tx_gate_c"] + spice["wire_unit_c"] * 1e15 * wordline_area)
|
||||
pen_cap = convert_farad_to_relative_c(pen_cap_ff)
|
||||
# number of stages in the p_en driver
|
||||
pen_stages = self.p_en_bar_driver.num_stages
|
||||
|
||||
inverter_stage_delay = logical_effort("inv", 1, 1, OPTS.delay_chain_fanout_per_stage, 1, True).get_absolute_delay()
|
||||
# model precharge as a minimum sized inverter with the bitline as its load
|
||||
precharge_delay = logical_effort("precharge", 1, 1, bitline_cap, 1, True).get_absolute_delay()
|
||||
# exponential horn delay from logical effort paper (converted to absolute delay)
|
||||
pen_signal_delay = logical_effort.tau * (pen_stages * (pen_cap ** (1 / pen_stages) + 1))
|
||||
# size is a pessimistic version of wordline_driver module's FO4 sizing
|
||||
wordline_driver_size = int(self.num_cols / 4) + 1
|
||||
wordline_delay = logical_effort("wordline", wordline_driver_size, 1, wordline_cap, 1, True).get_absolute_delay()
|
||||
# wl_en driver is always two stages so add each independently?
|
||||
wlen_signal_delay = logical_effort("wlen_driver", self.wl_en_driver.size_list[0], 1, self.wl_en_driver.size_list[1], 1, True).get_absolute_delay()
|
||||
wlen_signal_delay += logical_effort("wlen_driver", self.wl_en_driver.size_list[1], 1, wordline_driver_size * self.num_rows, 1, True).get_absolute_delay()
|
||||
# time for bitline to drop from vdd by threshold voltage once wordline enabled
|
||||
bitline_vth_swing = (spice["nom_supply_voltage"] - spice["nom_threshold"]) / spice["nom_supply_voltage"]
|
||||
bitline_vth_delay = abs(math.log(1 - bitline_vth_swing)) * spice["wire_unit_r"] * bitline_area * bitline_cap_ff
|
||||
# print("delays: delay_stage {} precharge {} pen {} wl {} wlen {} vth {}".format(inverter_stage_delay, precharge_delay, pen_signal_delay, wordline_delay, wlen_signal_delay, bitline_vth_delay))
|
||||
|
||||
delays = [None] * 5
|
||||
# keepout between p_en rising and wl_en falling
|
||||
delays[0] = (wlen_signal_delay + wordline_delay) / inverter_stage_delay # could possibly subtract pen_signal_delay?
|
||||
delays[0] = int(delays[0] * OPTS.delay_control_scaling_factor)
|
||||
# round up to nearest even integer
|
||||
delays[0] += delays[0] % 2
|
||||
delays[2] = delays[0] + (pen_signal_delay + precharge_delay) / inverter_stage_delay
|
||||
delays[2] *= OPTS.delay_control_scaling_factor
|
||||
# round up to nearest odd integer
|
||||
delays[2] = int(1 - (2 * ((1 - delays[2]) // 2)))
|
||||
# delays[1] can be any even value less than delays[2]
|
||||
delays[1] = delays[2] - 1
|
||||
# keepout between p_en falling and wl_en rising
|
||||
delays[3] = delays[2] + pen_signal_delay / inverter_stage_delay
|
||||
delays[3] *= OPTS.delay_control_scaling_factor
|
||||
delays[3] = int(1 - (2 * ((1 - delays[3]) // 2)))
|
||||
delays[4] = delays[3] + (wlen_signal_delay + wordline_delay + bitline_vth_delay) / inverter_stage_delay
|
||||
delays[4] *= OPTS.delay_control_scaling_factor
|
||||
delays[4] = int(1 - (2 * ((1 - delays[4]) // 2)))
|
||||
self.delay_chain_pinout_list = delays
|
||||
# FIXME: fanout should be used to control delay chain height
|
||||
# for now, use default/user-defined fanout constant
|
||||
self.delay_chain_fanout_list = self.delay_chain_pinout_list[-1] * [OPTS.delay_chain_fanout_per_stage]
|
||||
|
||||
def setup_signal_busses(self):
|
||||
""" Setup bus names, determine the size of the busses etc """
|
||||
|
||||
# List of input control signals
|
||||
if self.port_type == "rw":
|
||||
self.input_list = ["csb", "web"]
|
||||
else:
|
||||
self.input_list = ["csb"]
|
||||
|
||||
if self.port_type == "rw":
|
||||
self.dff_output_list = ["cs_bar", "cs", "we_bar", "we"]
|
||||
else:
|
||||
self.dff_output_list = ["cs_bar", "cs"]
|
||||
|
||||
# list of output control signals (for making a vertical bus)
|
||||
if self.port_type == "rw":
|
||||
self.internal_bus_list = ["glitch1", "glitch2", "delay0", "delay1", "delay2", "delay3", "delay4", "gated_clk_bar", "gated_clk_buf", "we", "we_bar", "clk_buf", "cs"]
|
||||
else:
|
||||
self.internal_bus_list = ["glitch1", "glitch2", "delay0", "delay1", "delay2", "delay3", "delay4", "gated_clk_bar", "gated_clk_buf", "clk_buf", "cs"]
|
||||
# leave space for the bus plus one extra space
|
||||
self.internal_bus_width = (len(self.internal_bus_list) + 1) * self.m2_pitch
|
||||
|
||||
# Outputs to the bank
|
||||
if self.port_type == "rw":
|
||||
self.output_list = ["s_en", "w_en"]
|
||||
elif self.port_type == "r":
|
||||
self.output_list = ["s_en"]
|
||||
else:
|
||||
self.output_list = ["w_en"]
|
||||
self.output_list.append("p_en_bar")
|
||||
self.output_list.append("wl_en")
|
||||
self.output_list.append("clk_buf")
|
||||
|
||||
self.supply_list = ["vdd", "gnd"]
|
||||
|
||||
def create_instances(self):
|
||||
""" Create all the instances """
|
||||
self.create_dffs()
|
||||
self.create_clk_buf_row()
|
||||
self.create_gated_clk_bar_row()
|
||||
self.create_gated_clk_buf_row()
|
||||
self.create_delay()
|
||||
self.create_glitches()
|
||||
self.create_wlen_row()
|
||||
if (self.port_type == "rw") or (self.port_type == "w"):
|
||||
self.create_wen_row()
|
||||
if (self.port_type == "rw") or (self.port_type == "r"):
|
||||
self.create_sen_row()
|
||||
self.create_pen_row()
|
||||
|
||||
def place_logic_rows(self):
|
||||
row = 0
|
||||
self.place_clk_buf_row(row)
|
||||
row += 1
|
||||
self.place_gated_clk_bar_row(row)
|
||||
row += 1
|
||||
self.place_gated_clk_buf_row(row)
|
||||
row += 1
|
||||
if (self.port_type == "rw") or (self.port_type == "r"):
|
||||
self.place_sen_row(row)
|
||||
row += 1
|
||||
if (self.port_type == "rw") or (self.port_type == "w"):
|
||||
self.place_wen_row(row)
|
||||
row += 1
|
||||
self.place_pen_row(row)
|
||||
row += 1
|
||||
self.place_wlen_row(row)
|
||||
row += 1
|
||||
self.place_glitch1_row(row)
|
||||
row += 1
|
||||
self.place_glitch2_row(row)
|
||||
|
||||
self.control_center_y = self.glitch2_nand_inst.uy() + self.m3_pitch
|
||||
|
||||
def route_all(self):
|
||||
""" Routing between modules """
|
||||
self.route_rails()
|
||||
self.route_dffs()
|
||||
self.route_wlen()
|
||||
if (self.port_type == "rw") or (self.port_type == "w"):
|
||||
self.route_wen()
|
||||
if (self.port_type == "rw") or (self.port_type == "r"):
|
||||
self.route_sen()
|
||||
self.route_delay()
|
||||
self.route_pen()
|
||||
self.route_glitches()
|
||||
self.route_clk_buf()
|
||||
self.route_gated_clk_bar()
|
||||
self.route_gated_clk_buf()
|
||||
self.route_supplies()
|
||||
|
||||
def create_delay(self):
|
||||
""" Create the delay chain """
|
||||
self.delay_inst=self.add_inst(name="multi_delay_chain",
|
||||
mod=self.delay_chain)
|
||||
self.connect_inst(["gated_clk_buf", "delay0", "delay1", "delay2", "delay3", "delay4", "vdd", "gnd"])
|
||||
|
||||
def route_delay(self):
|
||||
# this is a bit of a hack because I would prefer to just name these pins delay in the layout
|
||||
# instead I have this which duplicates the out_pin naming logic from multi_delay_chain.py
|
||||
out_pins = ["out{}".format(str(pin)) for pin in self.delay_chain.pinout_list]
|
||||
delay_map = zip(["in", out_pins[0], out_pins[1], out_pins[2], out_pins[3], out_pins[4]], \
|
||||
["gated_clk_buf", "delay0", "delay1", "delay2", "delay3", "delay4"])
|
||||
|
||||
self.connect_vertical_bus(delay_map,
|
||||
self.delay_inst,
|
||||
self.input_bus,
|
||||
self.m2_stack[::-1])
|
||||
|
||||
# glitch{0-2} are internal timing signals based on different in/out
|
||||
# points on the delay chain for adjustable start time and duration
|
||||
def create_glitches(self):
|
||||
self.glitch0_nand_inst = self.add_inst(name="nand2_glitch0",
|
||||
mod=self.nand2)
|
||||
self.connect_inst(["delay0", "delay2", "glitch0", "vdd", "gnd"])
|
||||
|
||||
self.glitch1_nand_inst = self.add_inst(name="nand2_glitch1",
|
||||
mod=self.nand2)
|
||||
self.connect_inst(["gated_clk_buf", "delay3", "glitch1", "vdd", "gnd"])
|
||||
|
||||
self.glitch2_nand_inst = self.add_inst(name="nand2_glitch2",
|
||||
mod=self.nand2)
|
||||
self.connect_inst(["delay1", "delay4", "glitch2", "vdd", "gnd"])
|
||||
|
||||
# glitch0 is placed in place_pen_row()
|
||||
|
||||
def place_glitch1_row(self, row):
|
||||
x_offset = self.control_x_offset
|
||||
|
||||
x_offset = self.place_util(self.glitch1_nand_inst, x_offset, row)
|
||||
|
||||
self.row_end_inst.append(self.glitch1_nand_inst)
|
||||
|
||||
def place_glitch2_row(self, row):
|
||||
x_offset = self.control_x_offset
|
||||
|
||||
x_offset = self.place_util(self.glitch2_nand_inst, x_offset, row)
|
||||
|
||||
self.row_end_inst.append(self.glitch2_nand_inst)
|
||||
|
||||
def route_glitches(self):
|
||||
glitch1_map = zip(["A", "B", "Z"], ["gated_clk_buf", "delay3", "glitch1"])
|
||||
|
||||
self.connect_vertical_bus(glitch1_map, self.glitch1_nand_inst, self.input_bus)
|
||||
|
||||
glitch2_map = zip(["A", "B", "Z"], ["delay1", "delay4", "glitch2"])
|
||||
|
||||
self.connect_vertical_bus(glitch2_map, self.glitch2_nand_inst, self.input_bus)
|
||||
|
||||
def create_wlen_row(self):
|
||||
self.wl_en_unbuf_and_inst = self.add_inst(name="and_wl_en_unbuf",
|
||||
mod=self.wl_en_and)
|
||||
self.connect_inst(["cs", "glitch1", "wl_en_unbuf", "vdd", "gnd"])
|
||||
|
||||
self.wl_en_driver_inst=self.add_inst(name="buf_wl_en",
|
||||
mod=self.wl_en_driver)
|
||||
self.connect_inst(["wl_en_unbuf", "wl_en", "vdd", "gnd"])
|
||||
|
||||
def place_wlen_row(self, row):
|
||||
x_offset = self.control_x_offset
|
||||
|
||||
x_offset = self.place_util(self.wl_en_unbuf_and_inst, x_offset, row)
|
||||
x_offset = self.place_util(self.wl_en_driver_inst, x_offset, row)
|
||||
|
||||
self.row_end_inst.append(self.wl_en_driver_inst)
|
||||
|
||||
def route_wlen(self):
|
||||
in_map = zip(["A", "B"], ["cs", "glitch1"])
|
||||
self.connect_vertical_bus(in_map, self.wl_en_unbuf_and_inst, self.input_bus)
|
||||
|
||||
out_pin = self.wl_en_unbuf_and_inst.get_pin("Z")
|
||||
out_pos = out_pin.center()
|
||||
in_pin = self.wl_en_driver_inst.get_pin("A")
|
||||
in_pos = in_pin.center()
|
||||
mid1 = vector(out_pos.x, in_pos.y)
|
||||
self.add_path(out_pin.layer, [out_pos, mid1, in_pos])
|
||||
self.add_via_stack_center(from_layer=out_pin.layer,
|
||||
to_layer=in_pin.layer,
|
||||
offset=in_pin.center())
|
||||
self.connect_output(self.wl_en_driver_inst, "Z", "wl_en")
|
||||
|
||||
def create_pen_row(self):
|
||||
self.p_en_bar_driver_inst=self.add_inst(name="buf_p_en_bar",
|
||||
mod=self.p_en_bar_driver)
|
||||
self.connect_inst(["glitch0", "p_en_bar", "vdd", "gnd"])
|
||||
|
||||
def place_pen_row(self, row):
|
||||
x_offset = self.control_x_offset
|
||||
|
||||
x_offset = self.place_util(self.glitch0_nand_inst, x_offset, row)
|
||||
x_offset = self.place_util(self.p_en_bar_driver_inst, x_offset, row)
|
||||
|
||||
self.row_end_inst.append(self.p_en_bar_driver_inst)
|
||||
|
||||
def route_pen(self):
|
||||
in_map = zip(["A", "B"], ["delay0", "delay2"])
|
||||
self.connect_vertical_bus(in_map, self.glitch0_nand_inst, self.input_bus)
|
||||
|
||||
out_pin = self.glitch0_nand_inst.get_pin("Z") # same code here as wl_en, refactor?
|
||||
out_pos = out_pin.center()
|
||||
in_pin = self.p_en_bar_driver_inst.get_pin("A")
|
||||
in_pos = in_pin.center()
|
||||
mid1 = vector(in_pos.x, out_pos.y)
|
||||
self.add_path(out_pin.layer, [out_pos, mid1, in_pos])
|
||||
self.add_via_stack_center(from_layer=out_pin.layer,
|
||||
to_layer=in_pin.layer,
|
||||
offset=in_pin.center())
|
||||
|
||||
self.connect_output(self.p_en_bar_driver_inst, "Z", "p_en_bar")
|
||||
|
||||
def create_sen_row(self):
|
||||
if self.port_type=="rw":
|
||||
input_name = "we_bar"
|
||||
else:
|
||||
input_name = "cs"
|
||||
|
||||
self.s_en_gate_inst = self.add_inst(name="and_s_en",
|
||||
mod=self.sen_and3)
|
||||
self.connect_inst(["glitch2", "gated_clk_bar", input_name, "s_en", "vdd", "gnd"])
|
||||
|
||||
def place_sen_row(self, row):
|
||||
x_offset = self.control_x_offset
|
||||
|
||||
x_offset = self.place_util(self.s_en_gate_inst, x_offset, row)
|
||||
|
||||
self.row_end_inst.append(self.s_en_gate_inst)
|
||||
|
||||
def route_sen(self):
|
||||
|
||||
if self.port_type=="rw": # this is repeated many times in here, refactor?
|
||||
input_name = "we_bar"
|
||||
else:
|
||||
input_name = "cs"
|
||||
|
||||
sen_map = zip(["A", "B", "C"], ["glitch2", "gated_clk_bar", input_name])
|
||||
self.connect_vertical_bus(sen_map, self.s_en_gate_inst, self.input_bus)
|
||||
|
||||
self.connect_output(self.s_en_gate_inst, "Z", "s_en")
|
||||
|
||||
def create_wen_row(self):
|
||||
self.glitch2_bar_inv_inst = self.add_inst(name="inv_glitch2_bar",
|
||||
mod=self.inv)
|
||||
self.connect_inst(["glitch2", "glitch2_bar", "vdd", "gnd"])
|
||||
|
||||
if self.port_type == "rw":
|
||||
input_name = "we"
|
||||
else:
|
||||
input_name = "cs"
|
||||
|
||||
self.w_en_gate_inst = self.add_inst(name="and_w_en",
|
||||
mod=self.wen_and)
|
||||
self.connect_inst([input_name, "glitch1", "glitch2_bar", "w_en", "vdd", "gnd"])
|
||||
|
||||
def place_wen_row(self, row):
|
||||
x_offset = self.control_x_offset
|
||||
|
||||
x_offset = self.place_util(self.glitch2_bar_inv_inst, x_offset, row)
|
||||
x_offset = self.place_util(self.w_en_gate_inst, x_offset, row)
|
||||
|
||||
self.row_end_inst.append(self.w_en_gate_inst)
|
||||
|
||||
def route_wen(self): # w_en comes from a 3and but one of the inputs needs to be inverted
|
||||
glitch2_map = zip(["A"], ["glitch2"])
|
||||
self.connect_vertical_bus(glitch2_map, self.glitch2_bar_inv_inst, self.input_bus)
|
||||
|
||||
out_pin = self.glitch2_bar_inv_inst.get_pin("Z")
|
||||
out_pos = out_pin.center()
|
||||
in_pin = self.w_en_gate_inst.get_pin("C")
|
||||
in_pos = in_pin.center()
|
||||
mid1 = vector(in_pos.x, out_pos.y)
|
||||
self.add_path(out_pin.layer, [out_pos, mid1, in_pos])
|
||||
self.add_via_stack_center(from_layer=out_pin.layer,
|
||||
to_layer=in_pin.layer,
|
||||
offset=in_pos)
|
||||
|
||||
if self.port_type == "rw":
|
||||
input_name = "we"
|
||||
else:
|
||||
input_name = "cs"
|
||||
|
||||
# This is the second gate over, so it needs to be on M3
|
||||
wen_map = zip(["A", "B"], [input_name, "glitch1"])
|
||||
self.connect_vertical_bus(wen_map,
|
||||
self.w_en_gate_inst,
|
||||
self.input_bus,
|
||||
self.m2_stack[::-1])
|
||||
|
||||
# The pins are on M1, so we need more vias as well
|
||||
a_pin = self.w_en_gate_inst.get_pin("A")
|
||||
self.add_via_stack_center(from_layer=a_pin.layer,
|
||||
to_layer="m3",
|
||||
offset=a_pin.center())
|
||||
|
||||
b_pin = self.w_en_gate_inst.get_pin("B")
|
||||
self.add_via_stack_center(from_layer=b_pin.layer,
|
||||
to_layer="m3",
|
||||
offset=b_pin.center())
|
||||
|
||||
self.connect_output(self.w_en_gate_inst, "Z", "w_en")
|
||||
|
|
@ -20,14 +20,31 @@ class global_bitcell_array(bitcell_base_array):
|
|||
Rows is an integer number for all local arrays.
|
||||
Cols is a list of the array widths.
|
||||
"""
|
||||
def __init__(self, rows, cols, name=""):
|
||||
def __init__(self, rows, cols, rbl=None, left_rbl=None, right_rbl=None, name=""):
|
||||
# The total of all columns will be the number of columns
|
||||
super().__init__(name=name, rows=rows, cols=sum(cols), column_offset=0)
|
||||
self.column_sizes = cols
|
||||
self.col_offsets = [0] + list(cumsum(cols)[:-1])
|
||||
|
||||
debug.check(len(self.all_ports)<=2, "Only support dual port or less in global bitcell array.")
|
||||
self.rbl = [1, 1 if len(self.all_ports)>1 else 0]
|
||||
debug.check(len(self.all_ports) < 3, "Only support dual port or less in global bitcell array.")
|
||||
|
||||
# This is how many RBLs are in all the arrays
|
||||
if rbl is not None:
|
||||
self.rbl = rbl
|
||||
else:
|
||||
self.rbl = [0] * len(self.all_ports)
|
||||
# This specifies which RBL to put on the left or right by port number
|
||||
# This could be an empty list
|
||||
if left_rbl is not None:
|
||||
self.left_rbl = left_rbl
|
||||
else:
|
||||
self.left_rbl = []
|
||||
# This could be an empty list
|
||||
if right_rbl is not None:
|
||||
self.right_rbl = right_rbl
|
||||
else:
|
||||
self.right_rbl=[]
|
||||
self.rbls = self.left_rbl + self.right_rbl
|
||||
|
||||
self.create_netlist()
|
||||
if not OPTS.netlist_only:
|
||||
|
|
@ -56,14 +73,13 @@ class global_bitcell_array(bitcell_base_array):
|
|||
self.local_mods = []
|
||||
|
||||
# Special case of a single local array
|
||||
# so it should contain the left and possibly right RBL
|
||||
if len(self.column_sizes) == 1:
|
||||
la = factory.create(module_type="local_bitcell_array",
|
||||
rows=self.row_size,
|
||||
cols=self.column_sizes[0],
|
||||
rbl=self.rbl,
|
||||
left_rbl=[0],
|
||||
right_rbl=[1] if len(self.all_ports) > 1 else [])
|
||||
left_rbl=self.left_rbl,
|
||||
right_rbl=self.right_rbl)
|
||||
self.local_mods.append(la)
|
||||
return
|
||||
|
||||
|
|
@ -74,14 +90,14 @@ class global_bitcell_array(bitcell_base_array):
|
|||
rows=self.row_size,
|
||||
cols=cols,
|
||||
rbl=self.rbl,
|
||||
left_rbl=[0])
|
||||
# Add the right RBL to the last subarray
|
||||
elif i == len(self.column_sizes) - 1 and len(self.all_ports) > 1:
|
||||
left_rbl=self.left_rbl)
|
||||
# Add the right RBLs to the last subarray
|
||||
elif i == len(self.column_sizes) - 1:
|
||||
la = factory.create(module_type="local_bitcell_array",
|
||||
rows=self.row_size,
|
||||
cols=cols,
|
||||
rbl=self.rbl,
|
||||
right_rbl=[1])
|
||||
right_rbl=self.right_rbl)
|
||||
# Middle subarrays do not have any RBLs
|
||||
else:
|
||||
la = factory.create(module_type="local_bitcell_array",
|
||||
|
|
@ -100,13 +116,16 @@ class global_bitcell_array(bitcell_base_array):
|
|||
self.add_pin("gnd", "GROUND")
|
||||
|
||||
def add_bitline_pins(self):
|
||||
# FIXME: aren't these already defined via inheritence by bitcell base array?
|
||||
self.bitline_names = [[] for x in self.all_ports]
|
||||
self.rbl_bitline_names = [[] for x in self.all_ports]
|
||||
|
||||
for port in self.all_ports:
|
||||
self.rbl_bitline_names[0].append("rbl_bl_{}_0".format(port))
|
||||
for port in self.all_ports:
|
||||
self.rbl_bitline_names[0].append("rbl_br_{}_0".format(port))
|
||||
# The bit is which port the RBL is for
|
||||
for bit in self.rbls:
|
||||
for port in self.all_ports:
|
||||
self.rbl_bitline_names[bit].append("rbl_bl_{0}_{1}".format(port, bit))
|
||||
for port in self.all_ports:
|
||||
self.rbl_bitline_names[bit].append("rbl_br_{0}_{1}".format(port, bit))
|
||||
|
||||
for col in range(self.column_size):
|
||||
for port in self.all_ports:
|
||||
|
|
@ -114,21 +133,16 @@ class global_bitcell_array(bitcell_base_array):
|
|||
for port in self.all_ports:
|
||||
self.bitline_names[port].append("br_{0}_{1}".format(port, col))
|
||||
|
||||
if len(self.all_ports) > 1:
|
||||
for port in self.all_ports:
|
||||
self.rbl_bitline_names[1].append("rbl_bl_{}_1".format(port))
|
||||
for port in self.all_ports:
|
||||
self.rbl_bitline_names[1].append("rbl_br_{}_1".format(port))
|
||||
|
||||
# Make a flat list too
|
||||
self.all_bitline_names = [x for sl in zip(*self.bitline_names) for x in sl]
|
||||
# Make a flat list too
|
||||
self.all_rbl_bitline_names = [x for sl in zip(*self.rbl_bitline_names) for x in sl]
|
||||
|
||||
self.add_pin_list(self.rbl_bitline_names[0], "INOUT")
|
||||
for port in self.left_rbl:
|
||||
self.add_pin_list(self.rbl_bitline_names[port], "INOUT")
|
||||
self.add_pin_list(self.all_bitline_names, "INOUT")
|
||||
if len(self.all_ports) > 1:
|
||||
self.add_pin_list(self.rbl_bitline_names[1], "INOUT")
|
||||
for port in self.right_rbl:
|
||||
self.add_pin_list(self.rbl_bitline_names[port], "INOUT")
|
||||
|
||||
def add_wordline_pins(self):
|
||||
|
||||
|
|
@ -137,6 +151,8 @@ class global_bitcell_array(bitcell_base_array):
|
|||
self.wordline_names = [[] for x in self.all_ports]
|
||||
|
||||
for bit in self.all_ports:
|
||||
if self.rbl[bit] == 0:
|
||||
continue
|
||||
for port in self.all_ports:
|
||||
self.rbl_wordline_names[port].append("rbl_wl_{0}_{1}".format(port, bit))
|
||||
|
||||
|
|
@ -239,17 +255,18 @@ class global_bitcell_array(bitcell_base_array):
|
|||
start=left_pin.lc(),
|
||||
end=right_pin.rc())
|
||||
|
||||
# Replica bitlines
|
||||
self.copy_layout_pin(self.local_insts[0], "rbl_bl_0_0")
|
||||
self.copy_layout_pin(self.local_insts[0], "rbl_br_0_0")
|
||||
if len(self.rbls) > 0:
|
||||
# Replica bitlines
|
||||
self.copy_layout_pin(self.local_insts[0], "rbl_bl_0_0")
|
||||
self.copy_layout_pin(self.local_insts[0], "rbl_br_0_0")
|
||||
|
||||
if len(self.all_ports) > 1:
|
||||
self.copy_layout_pin(self.local_insts[0], "rbl_bl_1_0")
|
||||
self.copy_layout_pin(self.local_insts[0], "rbl_br_1_0")
|
||||
self.copy_layout_pin(self.local_insts[-1], "rbl_bl_0_1")
|
||||
self.copy_layout_pin(self.local_insts[-1], "rbl_br_0_1")
|
||||
self.copy_layout_pin(self.local_insts[-1], "rbl_bl_1_1")
|
||||
self.copy_layout_pin(self.local_insts[-1], "rbl_br_1_1")
|
||||
if len(self.all_ports) > 1:
|
||||
self.copy_layout_pin(self.local_insts[0], "rbl_bl_1_0")
|
||||
self.copy_layout_pin(self.local_insts[0], "rbl_br_1_0")
|
||||
self.copy_layout_pin(self.local_insts[-1], "rbl_bl_0_1")
|
||||
self.copy_layout_pin(self.local_insts[-1], "rbl_br_0_1")
|
||||
self.copy_layout_pin(self.local_insts[-1], "rbl_bl_1_1")
|
||||
self.copy_layout_pin(self.local_insts[-1], "rbl_br_1_1")
|
||||
|
||||
for inst in self.insts:
|
||||
self.copy_power_pins(inst, "vdd")
|
||||
|
|
|
|||
|
|
@ -31,7 +31,10 @@ class local_bitcell_array(bitcell_base_array):
|
|||
self.rows = rows
|
||||
self.cols = cols
|
||||
# This is how many RBLs are in all the arrays
|
||||
self.rbl = rbl
|
||||
if rbl is not None:
|
||||
self.rbl = rbl
|
||||
else:
|
||||
self.rbl = [0] * len(self.all_ports)
|
||||
# This specifies which RBL to put on the left or right by port number
|
||||
# This could be an empty list
|
||||
if left_rbl is not None:
|
||||
|
|
@ -84,8 +87,11 @@ class local_bitcell_array(bitcell_base_array):
|
|||
left_rbl=self.left_rbl,
|
||||
right_rbl=self.right_rbl)
|
||||
|
||||
# FIXME: this won't allow asymetric configurations such as rbl=[0, 1]
|
||||
# but neither does a lot of this code...
|
||||
rows = self.rows + (sum(self.rbl) != 0)
|
||||
self.wl_array = factory.create(module_type="wordline_buffer_array",
|
||||
rows=self.rows + 1,
|
||||
rows=rows,
|
||||
cols=self.cols)
|
||||
|
||||
def add_pins(self):
|
||||
|
|
@ -136,7 +142,8 @@ class local_bitcell_array(bitcell_base_array):
|
|||
self.wl_insts.append(self.add_inst(name="wl_driver{}".format(port),
|
||||
mod=self.wl_array))
|
||||
temp = []
|
||||
temp += [self.get_rbl_wordline_names(port)[port]]
|
||||
if self.rbl[port] != 0:
|
||||
temp += [self.get_rbl_wordline_names(port)[port]]
|
||||
if port == 0:
|
||||
temp += self.get_wordline_names(port)
|
||||
else:
|
||||
|
|
@ -180,8 +187,9 @@ class local_bitcell_array(bitcell_base_array):
|
|||
self.bitcell_array_inst.place(bitcell_array_offset)
|
||||
|
||||
if len(self.all_ports) > 1:
|
||||
rbl_wl_adder = self.cell.height * (self.rbl[1] != 0)
|
||||
wl_offset = vector(self.bitcell_array_inst.rx() + self.wl_array.width + driver_to_array_spacing,
|
||||
self.bitcell_array.get_replica_bottom() + self.wl_array.height + self.cell.height)
|
||||
self.bitcell_array.get_replica_bottom() + self.wl_array.height + rbl_wl_adder)
|
||||
self.wl_insts[1].place(wl_offset,
|
||||
mirror="XY")
|
||||
|
||||
|
|
@ -209,10 +217,16 @@ class local_bitcell_array(bitcell_base_array):
|
|||
|
||||
# Route the global wordlines
|
||||
for port in self.all_ports:
|
||||
if port == 0:
|
||||
wordline_names = [self.get_rbl_wordline_names(port)[port]] + self.get_wordline_names(port)
|
||||
if self.rbl[port] != 0:
|
||||
if port == 0:
|
||||
wordline_names = [self.get_rbl_wordline_names(port)[port]] + self.get_wordline_names(port)
|
||||
else:
|
||||
wordline_names = [self.get_rbl_wordline_names(port)[port]] + self.get_wordline_names(port)[::-1]
|
||||
else:
|
||||
wordline_names = [self.get_rbl_wordline_names(port)[port]] + self.get_wordline_names(port)[::-1]
|
||||
if port == 0:
|
||||
wordline_names = self.get_wordline_names(port)
|
||||
else:
|
||||
wordline_names = self.get_wordline_names(port)[::-1]
|
||||
|
||||
wordline_pins = self.wl_array.get_inputs()
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,229 @@
|
|||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||
# (acting for and on behalf of Oklahoma State University)
|
||||
# All rights reserved.
|
||||
#
|
||||
from openram import debug
|
||||
from openram.base import design
|
||||
from openram.base import vector
|
||||
from openram.sram_factory import factory
|
||||
from openram import OPTS
|
||||
|
||||
|
||||
class multi_delay_chain(design):
|
||||
"""
|
||||
Generate a delay chain with the given number of stages, fanout, and output pins.
|
||||
Fanout list contains the electrical effort (fanout) of each stage.
|
||||
Usually, this will be constant, but it could have varied fanout.
|
||||
Pinout list contains the inverter stages which have an output pin attached.
|
||||
Supplying an empty pinout list will result in an output only on the last stage.
|
||||
"""
|
||||
|
||||
def __init__(self, name, fanout_list, pinout_list=None):
|
||||
"""init function"""
|
||||
super().__init__(name)
|
||||
debug.info(1, "creating delay chain with {0}".format("fanouts: " + str(fanout_list) + " pinouts: " + str(pinout_list)))
|
||||
self.add_comment("fanouts: {0}".format(str(fanout_list)))
|
||||
self.add_comment("pinouts: {0}".format(str(pinout_list)))
|
||||
|
||||
# Two fanouts are needed so that we can route the vdd/gnd connections
|
||||
for f in fanout_list:
|
||||
debug.check(f>=2, "Must have >=2 fanouts for each stage.")
|
||||
|
||||
# number of inverters including any fanout loads.
|
||||
self.fanout_list = fanout_list
|
||||
self.rows = len(self.fanout_list)
|
||||
|
||||
# defaults to signle output at end of delay chain
|
||||
if not pinout_list:
|
||||
self.pinout_list = [self.rows] # TODO: check for off-by-one here
|
||||
else:
|
||||
self.pinout_list = pinout_list
|
||||
|
||||
# TODO: would like to sort and check pinout list for valid format but don't have time now
|
||||
# Check pinout bounds
|
||||
# debug.check(self.pinout_list[-1] <= self.rows,
|
||||
# "Ouput pin cannot exceed delay chain length.")
|
||||
# debug.check(self.pinout_list[0] > 0,
|
||||
# "Delay chain output pin numbers must be positive")
|
||||
|
||||
self.create_netlist()
|
||||
if not OPTS.netlist_only:
|
||||
self.create_layout()
|
||||
|
||||
def create_netlist(self):
|
||||
self.add_modules()
|
||||
self.add_pins()
|
||||
self.create_inverters()
|
||||
|
||||
def create_layout(self):
|
||||
# Each stage is a row
|
||||
self.height = self.rows * self.inv.height
|
||||
|
||||
# The width is determined by the largest fanout plus the driver
|
||||
self.width = (max(self.fanout_list) + 1) * self.inv.width
|
||||
|
||||
self.place_inverters()
|
||||
self.route_inverters()
|
||||
self.route_supplies()
|
||||
self.add_layout_pins()
|
||||
self.add_boundary()
|
||||
self.DRC_LVS()
|
||||
|
||||
def add_pins(self):
|
||||
""" Add the pins of the delay chain"""
|
||||
self.add_pin("in", "INPUT")
|
||||
for pin_stage in self.pinout_list:
|
||||
self.add_pin("out{}".format(pin_stage), "OUTPUT")
|
||||
self.add_pin("vdd", "POWER")
|
||||
self.add_pin("gnd", "GROUND")
|
||||
|
||||
def add_modules(self):
|
||||
|
||||
self.dff = factory.create(module_type="dff_buf")
|
||||
dff_height = self.dff.height
|
||||
|
||||
self.inv = factory.create(module_type="pinv",
|
||||
height=dff_height)
|
||||
|
||||
def create_inverters(self):
|
||||
""" Create the inverters and connect them based on the stage list """
|
||||
self.driver_inst_list = []
|
||||
self.load_inst_map = {}
|
||||
for stage_num, fanout_size in zip(range(self.rows), self.fanout_list):
|
||||
# Add the inverter
|
||||
cur_driver=self.add_inst(name="dinv{}".format(stage_num),
|
||||
mod=self.inv)
|
||||
# keep track of the inverter instances so we can use them to get the pins
|
||||
self.driver_inst_list.append(cur_driver)
|
||||
|
||||
# Hook up the driver
|
||||
stageout_name = "out{}".format(stage_num + 1) # TODO: check for off-by-one here
|
||||
if stage_num == 0:
|
||||
stagein_name = "in"
|
||||
else:
|
||||
stagein_name = "out{}".format(stage_num)
|
||||
self.connect_inst([stagein_name, stageout_name, "vdd", "gnd"])
|
||||
|
||||
# Now add the dummy loads to the right
|
||||
self.load_inst_map[cur_driver]=[]
|
||||
for i in range(fanout_size):
|
||||
cur_load=self.add_inst(name="dload_{0}_{1}".format(stage_num, i),
|
||||
mod=self.inv)
|
||||
# Fanout stage is always driven by driver and output is disconnected
|
||||
disconnect_name = "n_{0}_{1}".format(stage_num, i)
|
||||
self.connect_inst([stageout_name, disconnect_name, "vdd", "gnd"])
|
||||
|
||||
# Keep track of all the loads to connect their inputs as a load
|
||||
self.load_inst_map[cur_driver].append(cur_load)
|
||||
|
||||
def place_inverters(self):
|
||||
""" Place the inverters and connect them based on the stage list """
|
||||
for stage_num, fanout_size in zip(range(self.rows), self.fanout_list):
|
||||
if stage_num % 2:
|
||||
inv_mirror = "MX"
|
||||
inv_offset = vector(0, (stage_num + 1) * self.inv.height)
|
||||
else:
|
||||
inv_mirror = "R0"
|
||||
inv_offset = vector(0, stage_num * self.inv.height)
|
||||
|
||||
# Add the inverter
|
||||
cur_driver=self.driver_inst_list[stage_num]
|
||||
cur_driver.place(offset=inv_offset,
|
||||
mirror=inv_mirror)
|
||||
|
||||
# Now add the dummy loads to the right
|
||||
load_list = self.load_inst_map[cur_driver]
|
||||
for i in range(fanout_size):
|
||||
inv_offset += vector(self.inv.width, 0)
|
||||
load_list[i].place(offset=inv_offset,
|
||||
mirror=inv_mirror)
|
||||
|
||||
def add_route(self, pin1, pin2):
|
||||
""" This guarantees that we route from the top to bottom row correctly. """
|
||||
pin1_pos = pin1.center()
|
||||
pin2_pos = pin2.center()
|
||||
if pin1_pos.y == pin2_pos.y:
|
||||
self.add_path("m2", [pin1_pos, pin2_pos])
|
||||
else:
|
||||
mid_point = vector(pin2_pos.x, 0.5 * (pin1_pos.y + pin2_pos.y))
|
||||
# Written this way to guarantee it goes right first if we are switching rows
|
||||
self.add_path("m2", [pin1_pos, vector(pin1_pos.x, mid_point.y), mid_point, vector(mid_point.x, pin2_pos.y), pin2_pos])
|
||||
|
||||
def route_inverters(self):
|
||||
""" Add metal routing for each of the fanout stages """
|
||||
|
||||
for i in range(len(self.driver_inst_list)):
|
||||
inv = self.driver_inst_list[i]
|
||||
for load in self.load_inst_map[inv]:
|
||||
# Drop a via on each A pin
|
||||
a_pin = load.get_pin("A")
|
||||
self.add_via_stack_center(from_layer=a_pin.layer,
|
||||
to_layer="m3",
|
||||
offset=a_pin.center())
|
||||
|
||||
# Route an M3 horizontal wire to the furthest
|
||||
z_pin = inv.get_pin("Z")
|
||||
a_pin = inv.get_pin("A")
|
||||
a_max = self.load_inst_map[inv][-1].get_pin("A")
|
||||
self.add_via_stack_center(from_layer=a_pin.layer,
|
||||
to_layer="m2",
|
||||
offset=a_pin.center())
|
||||
self.add_via_stack_center(from_layer=z_pin.layer,
|
||||
to_layer="m3",
|
||||
offset=z_pin.center())
|
||||
self.add_path("m3", [z_pin.center(), a_max.center()])
|
||||
|
||||
# Route Z to the A of the next stage
|
||||
if i + 1 < len(self.driver_inst_list):
|
||||
z_pin = inv.get_pin("Z")
|
||||
next_inv = self.driver_inst_list[i + 1]
|
||||
next_a_pin = next_inv.get_pin("A")
|
||||
y_mid = (z_pin.cy() + next_a_pin.cy()) / 2
|
||||
mid1_point = vector(z_pin.cx(), y_mid)
|
||||
mid2_point = vector(next_a_pin.cx(), y_mid)
|
||||
self.add_path("m2", [z_pin.center(), mid1_point, mid2_point, next_a_pin.center()])
|
||||
|
||||
def route_supplies(self):
|
||||
# Add power and ground to all the cells except:
|
||||
# the fanout driver, the right-most load
|
||||
# The routing to connect the loads is over the first and last cells
|
||||
# We have an even number of drivers and must only do every other
|
||||
# supply rail
|
||||
|
||||
for inst in self.driver_inst_list:
|
||||
load_list = self.load_inst_map[inst]
|
||||
for pin_name in ["vdd", "gnd"]:
|
||||
pin = load_list[0].get_pin(pin_name)
|
||||
self.copy_power_pin(pin, loc=pin.rc() - vector(self.m1_pitch, 0))
|
||||
|
||||
pin = load_list[-2].get_pin(pin_name)
|
||||
self.copy_power_pin(pin, loc=pin.rc() - vector(self.m1_pitch, 0))
|
||||
|
||||
def add_layout_pins(self):
|
||||
# input is A pin of first inverter
|
||||
# It gets routed down a bit to prevent overlapping adjacent
|
||||
# M3 when connecting to vertical bus
|
||||
a_pin = self.driver_inst_list[0].get_pin("A")
|
||||
mid_loc = vector(a_pin.cx(), a_pin.cy() - self.m3_pitch)
|
||||
self.add_via_stack_center(from_layer=a_pin.layer,
|
||||
to_layer="m3",
|
||||
offset=mid_loc)
|
||||
self.add_path("m2", [a_pin.center(), mid_loc])
|
||||
|
||||
self.add_layout_pin_rect_center(text="in",
|
||||
layer="m3",
|
||||
offset=mid_loc)
|
||||
|
||||
for pin_number in self.pinout_list:
|
||||
# pin is A pin of right-most load/fanout inverter
|
||||
output_driver_inst = self.driver_inst_list[pin_number - 1]
|
||||
a_pin = self.load_inst_map[output_driver_inst][-1].get_pin("A")
|
||||
self.add_via_stack_center(from_layer=a_pin.layer,
|
||||
to_layer="m3",
|
||||
offset=a_pin.center())
|
||||
self.add_layout_pin_rect_center(text="out{}".format(str(pin_number)),
|
||||
layer="m3",
|
||||
offset=a_pin.center())
|
||||
|
|
@ -18,11 +18,12 @@ class port_address(design):
|
|||
Create the address port (row decoder and wordline driver)..
|
||||
"""
|
||||
|
||||
def __init__(self, cols, rows, port, name=""):
|
||||
def __init__(self, cols, rows, port, has_rbl, name=""):
|
||||
|
||||
self.num_cols = cols
|
||||
self.num_rows = rows
|
||||
self.port = port
|
||||
self.has_rbl = has_rbl
|
||||
self.addr_size = ceil(log(self.num_rows, 2))
|
||||
|
||||
if name == "":
|
||||
|
|
@ -41,7 +42,8 @@ class port_address(design):
|
|||
self.add_modules()
|
||||
self.create_row_decoder()
|
||||
self.create_wordline_driver()
|
||||
self.create_rbl_driver()
|
||||
if self.has_rbl:
|
||||
self.create_rbl_driver()
|
||||
|
||||
def create_layout(self):
|
||||
if "li" in layer:
|
||||
|
|
@ -63,7 +65,8 @@ class port_address(design):
|
|||
for bit in range(self.num_rows):
|
||||
self.add_pin("wl_{0}".format(bit), "OUTPUT")
|
||||
|
||||
self.add_pin("rbl_wl", "OUTPUT")
|
||||
if self.has_rbl:
|
||||
self.add_pin("rbl_wl", "OUTPUT")
|
||||
|
||||
self.add_pin("vdd", "POWER")
|
||||
self.add_pin("gnd", "GROUND")
|
||||
|
|
@ -76,12 +79,13 @@ class port_address(design):
|
|||
|
||||
def route_supplies(self):
|
||||
""" Propagate all vdd/gnd pins up to this level for all modules """
|
||||
if layer_props.wordline_driver.vertical_supply:
|
||||
self.copy_layout_pin(self.rbl_driver_inst, "vdd")
|
||||
else:
|
||||
rbl_pos = self.rbl_driver_inst.get_pin("vdd").rc()
|
||||
self.add_power_pin("vdd", rbl_pos)
|
||||
self.add_path("m4", [rbl_pos, self.wordline_driver_array_inst.get_pins("vdd")[0].rc()])
|
||||
if self.has_rbl:
|
||||
if layer_props.wordline_driver.vertical_supply:
|
||||
self.copy_layout_pin(self.rbl_driver_inst, "vdd")
|
||||
else:
|
||||
rbl_pos = self.rbl_driver_inst.get_pin("vdd").rc()
|
||||
self.add_power_pin("vdd", rbl_pos)
|
||||
self.add_path("m4", [rbl_pos, self.wordline_driver_array_inst.get_pins("vdd")[0].rc()])
|
||||
|
||||
self.copy_layout_pin(self.wordline_driver_array_inst, "vdd")
|
||||
self.copy_layout_pin(self.wordline_driver_array_inst, "gnd")
|
||||
|
|
@ -90,11 +94,12 @@ class port_address(design):
|
|||
self.copy_layout_pin(self.row_decoder_inst, "gnd")
|
||||
|
||||
# Also connect the B input of the RBL and_dec to vdd
|
||||
if OPTS.local_array_size == 0:
|
||||
rbl_b_pin = self.rbl_driver_inst.get_pin("B")
|
||||
rbl_loc = rbl_b_pin.center() - vector(3 * self.m1_pitch, 0)
|
||||
self.add_path(rbl_b_pin.layer, [rbl_b_pin.center(), rbl_loc])
|
||||
self.add_power_pin("vdd", rbl_loc, start_layer=rbl_b_pin.layer)
|
||||
if self.has_rbl:
|
||||
if OPTS.local_array_size == 0:
|
||||
rbl_b_pin = self.rbl_driver_inst.get_pin("B")
|
||||
rbl_loc = rbl_b_pin.center() - vector(3 * self.m1_pitch, 0)
|
||||
self.add_path(rbl_b_pin.layer, [rbl_b_pin.center(), rbl_loc])
|
||||
self.add_power_pin("vdd", rbl_loc, start_layer=rbl_b_pin.layer)
|
||||
|
||||
def route_pins(self):
|
||||
for row in range(self.addr_size):
|
||||
|
|
@ -105,7 +110,8 @@ class port_address(design):
|
|||
driver_name = "wl_{}".format(row)
|
||||
self.copy_layout_pin(self.wordline_driver_array_inst, driver_name)
|
||||
|
||||
self.copy_layout_pin(self.rbl_driver_inst, "Z", "rbl_wl")
|
||||
if self.has_rbl:
|
||||
self.copy_layout_pin(self.rbl_driver_inst, "Z", "rbl_wl")
|
||||
|
||||
def route_internal(self):
|
||||
for row in range(self.num_rows):
|
||||
|
|
@ -130,19 +136,25 @@ class port_address(design):
|
|||
en_pos = en_pin.bc()
|
||||
else:
|
||||
en_pos = en_pin.uc()
|
||||
rbl_in_pin = self.rbl_driver_inst.get_pin("A")
|
||||
rbl_in_pos = rbl_in_pin.center()
|
||||
|
||||
self.add_via_stack_center(from_layer=rbl_in_pin.layer,
|
||||
to_layer=en_pin.layer,
|
||||
offset=rbl_in_pos)
|
||||
self.add_zjog(layer=en_pin.layer,
|
||||
start=rbl_in_pos,
|
||||
end=en_pos,
|
||||
first_direction="V")
|
||||
if self.has_rbl:
|
||||
rbl_in_pin = self.rbl_driver_inst.get_pin("A")
|
||||
rbl_in_pos = rbl_in_pin.center()
|
||||
wl_en_offset = rbl_in_pos
|
||||
|
||||
self.add_via_stack_center(from_layer=rbl_in_pin.layer,
|
||||
to_layer=en_pin.layer,
|
||||
offset=rbl_in_pos)
|
||||
self.add_zjog(layer=en_pin.layer,
|
||||
start=rbl_in_pos,
|
||||
end=en_pos,
|
||||
first_direction="V")
|
||||
else:
|
||||
wl_en_offset = en_pos
|
||||
|
||||
self.add_layout_pin_rect_center(text="wl_en",
|
||||
layer=en_pin.layer,
|
||||
offset=rbl_in_pos)
|
||||
offset=wl_en_offset)
|
||||
|
||||
def add_modules(self):
|
||||
|
||||
|
|
@ -164,16 +176,17 @@ class port_address(design):
|
|||
# to compensate for the local array inverters
|
||||
b = factory.create(module_type=OPTS.bitcell)
|
||||
|
||||
if local_array_size > 0:
|
||||
# The local wordline driver will change the polarity
|
||||
self.rbl_driver = factory.create(module_type="inv_dec",
|
||||
size=driver_size,
|
||||
height=b.height)
|
||||
else:
|
||||
# There is no local wordline driver
|
||||
self.rbl_driver = factory.create(module_type="and2_dec",
|
||||
size=driver_size,
|
||||
height=b.height)
|
||||
if self.has_rbl:
|
||||
if local_array_size > 0:
|
||||
# The local wordline driver will change the polarity
|
||||
self.rbl_driver = factory.create(module_type="inv_dec",
|
||||
size=driver_size,
|
||||
height=b.height)
|
||||
else:
|
||||
# There is no local wordline driver
|
||||
self.rbl_driver = factory.create(module_type="and2_dec",
|
||||
size=driver_size,
|
||||
height=b.height)
|
||||
|
||||
def create_row_decoder(self):
|
||||
""" Create the hierarchical row decoder """
|
||||
|
|
@ -231,16 +244,17 @@ class port_address(design):
|
|||
wordline_driver_array_offset = vector(self.row_decoder_inst.rx(), 0)
|
||||
self.wordline_driver_array_inst.place(wordline_driver_array_offset)
|
||||
|
||||
# This m4_pitch corresponds to the offset space for jog routing in the
|
||||
# wordline_driver_array
|
||||
rbl_driver_offset = wordline_driver_array_offset + vector(2 * self.m4_pitch, 0)
|
||||
if self.has_rbl:
|
||||
# This m4_pitch corresponds to the offset space for jog routing in the
|
||||
# wordline_driver_array
|
||||
rbl_driver_offset = wordline_driver_array_offset + vector(2 * self.m4_pitch, 0)
|
||||
|
||||
if self.port == 0:
|
||||
self.rbl_driver_inst.place(rbl_driver_offset, "MX")
|
||||
else:
|
||||
rbl_driver_offset += vector(0,
|
||||
self.wordline_driver_array.height)
|
||||
self.rbl_driver_inst.place(rbl_driver_offset)
|
||||
if self.port == 0:
|
||||
self.rbl_driver_inst.place(rbl_driver_offset, "MX")
|
||||
else:
|
||||
rbl_driver_offset += vector(0,
|
||||
self.wordline_driver_array.height)
|
||||
self.rbl_driver_inst.place(rbl_driver_offset)
|
||||
|
||||
# Pass this up
|
||||
self.predecoder_height = self.row_decoder.predecoder_height
|
||||
|
|
|
|||
|
|
@ -18,13 +18,14 @@ from openram import OPTS
|
|||
class port_data(design):
|
||||
"""
|
||||
Create the data port (column mux, sense amps, write driver, etc.) for the given port number.
|
||||
Port 0 always has the RBL on the left while port 1 is on the right.
|
||||
When RBLs present: port 0 always has the RBL on the left while port 1 is on the right.
|
||||
"""
|
||||
|
||||
def __init__(self, sram_config, port, num_spare_cols=None, bit_offsets=None, name="",):
|
||||
def __init__(self, sram_config, port, has_rbl, num_spare_cols=None, bit_offsets=None, name="",):
|
||||
|
||||
sram_config.set_local_config(self)
|
||||
self.port = port
|
||||
self.has_rbl = has_rbl
|
||||
if self.write_size != self.word_size:
|
||||
self.num_wmasks = int(math.ceil(self.word_size / self.write_size))
|
||||
else:
|
||||
|
|
@ -115,8 +116,9 @@ class port_data(design):
|
|||
def add_pins(self):
|
||||
""" Adding pins for port data module"""
|
||||
|
||||
self.add_pin("rbl_bl", "INOUT")
|
||||
self.add_pin("rbl_br", "INOUT")
|
||||
if self.has_rbl:
|
||||
self.add_pin("rbl_bl", "INOUT")
|
||||
self.add_pin("rbl_br", "INOUT")
|
||||
for bit in range(self.num_cols):
|
||||
self.add_pin("bl_{0}".format(bit), "INOUT")
|
||||
self.add_pin("br_{0}".format(bit), "INOUT")
|
||||
|
|
@ -202,15 +204,19 @@ class port_data(design):
|
|||
precharge_width = cell.width + strap.width
|
||||
else:
|
||||
precharge_width = cell.width
|
||||
if self.port == 0:
|
||||
# Append an offset on the left
|
||||
precharge_bit_offsets = [self.bit_offsets[0] - precharge_width] + self.bit_offsets
|
||||
if self.has_rbl:
|
||||
if self.port == 0:
|
||||
# Append an offset on the left
|
||||
precharge_bit_offsets = [self.bit_offsets[0] - precharge_width] + self.bit_offsets
|
||||
else:
|
||||
# Append an offset on the right
|
||||
precharge_bit_offsets = self.bit_offsets + [self.bit_offsets[-1] + precharge_width]
|
||||
else:
|
||||
# Append an offset on the right
|
||||
precharge_bit_offsets = self.bit_offsets + [self.bit_offsets[-1] + precharge_width]
|
||||
precharge_bit_offsets = self.bit_offsets
|
||||
|
||||
# has_rbl is a boolean treated as 1 if true 0 if false typical python
|
||||
self.precharge_array = factory.create(module_type="precharge_array",
|
||||
columns=self.num_cols + self.num_spare_cols + 1,
|
||||
columns=self.num_cols + self.num_spare_cols + self.has_rbl,
|
||||
offsets=precharge_bit_offsets,
|
||||
bitcell_bl=self.bl_names[self.port],
|
||||
bitcell_br=self.br_names[self.port],
|
||||
|
|
@ -294,7 +300,7 @@ class port_data(design):
|
|||
mod=self.precharge_array)
|
||||
temp = []
|
||||
# Use left BLs for RBL
|
||||
if self.port==0:
|
||||
if self.port==0 and self.has_rbl:
|
||||
temp.append("rbl_bl")
|
||||
temp.append("rbl_br")
|
||||
for bit in range(self.num_cols):
|
||||
|
|
@ -306,7 +312,7 @@ class port_data(design):
|
|||
temp.append("sparebr_{0}".format(bit))
|
||||
|
||||
# Use right BLs for RBL
|
||||
if self.port==1:
|
||||
if self.port==1 and self.has_rbl:
|
||||
temp.append("rbl_bl")
|
||||
temp.append("rbl_br")
|
||||
temp.extend(["p_en_bar", "vdd"])
|
||||
|
|
@ -537,7 +543,7 @@ class port_data(design):
|
|||
if self.col_addr_size==0:
|
||||
return
|
||||
|
||||
start_bit = 1 if self.port == 0 else 0
|
||||
start_bit = 1 if self.port == 0 and self.has_rbl else 0
|
||||
|
||||
self.connect_bitlines(inst1=self.column_mux_array_inst,
|
||||
inst2=self.precharge_array_inst,
|
||||
|
|
@ -558,7 +564,7 @@ class port_data(design):
|
|||
inst1 = self.precharge_array_inst
|
||||
inst1_bls_templ="{inst}_{bit}"
|
||||
|
||||
if self.port==0:
|
||||
if self.port==0 and self.has_rbl:
|
||||
start_bit=1
|
||||
else:
|
||||
start_bit=0
|
||||
|
|
@ -683,11 +689,11 @@ class port_data(design):
|
|||
""" Add the bitline pins for the given port """
|
||||
|
||||
# Connect one bitline to the RBL and offset the indices for the other BLs
|
||||
if self.port==0:
|
||||
if self.port==0 and self.has_rbl:
|
||||
self.copy_layout_pin(self.precharge_array_inst, "bl_0", "rbl_bl")
|
||||
self.copy_layout_pin(self.precharge_array_inst, "br_0", "rbl_br")
|
||||
bit_offset=1
|
||||
elif self.port==1:
|
||||
elif self.port==1 and self.has_rbl:
|
||||
self.copy_layout_pin(self.precharge_array_inst, "bl_{}".format(self.num_cols + self.num_spare_cols), "rbl_bl")
|
||||
self.copy_layout_pin(self.precharge_array_inst, "br_{}".format(self.num_cols + self.num_spare_cols), "rbl_br")
|
||||
bit_offset=0
|
||||
|
|
|
|||
|
|
@ -16,11 +16,11 @@ from .bitcell_base_array import bitcell_base_array
|
|||
class replica_bitcell_array(bitcell_base_array):
|
||||
"""
|
||||
Creates a bitcell array of cols x rows and then adds the replica
|
||||
and dummy columns and rows. Replica columns are on the left and
|
||||
columns and dummy rows. Replica columns are on the left and
|
||||
right, respectively and connected to the given bitcell ports.
|
||||
Dummy are the outside columns/rows with WL and BL tied to gnd.
|
||||
Requires a regular bitcell array, replica bitcell, and dummy
|
||||
bitcell (BL/BR disconnected).
|
||||
Dummy rows are on the top and bottom passing through the RBL WLs.
|
||||
Requires a regular bitcell array and (if using replica topology)
|
||||
replica bitcell and dummy bitcell (BL/BR disconnected).
|
||||
"""
|
||||
def __init__(self, rows, cols, rbl=None, left_rbl=None, right_rbl=None, name=""):
|
||||
super().__init__(name=name, rows=rows, cols=cols, column_offset=0)
|
||||
|
|
@ -36,22 +36,29 @@ class replica_bitcell_array(bitcell_base_array):
|
|||
self.column_size = cols
|
||||
self.row_size = rows
|
||||
# This is how many RBLs are in all the arrays
|
||||
self.rbl = rbl
|
||||
# This specifies which RBL to put on the left or right by port number
|
||||
# This could be an empty list
|
||||
# Even if the RBL is not placed in this array, the module still needs
|
||||
# to place dummy rows with rbl wordlines so that they will have the same
|
||||
# load as the regular wordlines (and so the arrays are the same size)
|
||||
if rbl is not None:
|
||||
self.rbl = rbl
|
||||
else:
|
||||
self.rbl = [0] * len(self.all_ports)
|
||||
# This specifies how many RBLs to put on the left by port number.
|
||||
# For example, left_rbl = [0, 1] means there will be two
|
||||
# RBLs on the left, one for port 0 and another for port 1.
|
||||
if left_rbl is not None:
|
||||
self.left_rbl = left_rbl
|
||||
else:
|
||||
self.left_rbl = []
|
||||
# This could be an empty list
|
||||
# Similar to left_rbl but on the right side of the array
|
||||
if right_rbl is not None:
|
||||
self.right_rbl = right_rbl
|
||||
else:
|
||||
self.right_rbl=[]
|
||||
self.right_rbl = []
|
||||
self.rbls = self.left_rbl + self.right_rbl
|
||||
|
||||
debug.check(sum(self.rbl) >= len(self.left_rbl) + len(self.right_rbl),
|
||||
"Invalid number of RBLs for port configuration.")
|
||||
"Cannot have more left + right RBLs than total RBLs")
|
||||
|
||||
self.create_netlist()
|
||||
if not OPTS.netlist_only:
|
||||
|
|
@ -64,28 +71,7 @@ class replica_bitcell_array(bitcell_base_array):
|
|||
self.create_instances()
|
||||
|
||||
def add_modules(self):
|
||||
""" Array and dummy/replica columns
|
||||
|
||||
d or D = dummy cell (caps to distinguish grouping)
|
||||
r or R = replica cell (caps to distinguish grouping)
|
||||
b or B = bitcell
|
||||
replica columns 1
|
||||
v v
|
||||
bdDDDDDDDDDDDDDDdb <- Dummy row
|
||||
bdDDDDDDDDDDDDDDrb <- Dummy row
|
||||
br--------------rb
|
||||
br| Array |rb
|
||||
br| row x col |rb
|
||||
br--------------rb
|
||||
brDDDDDDDDDDDDDDdb <- Dummy row
|
||||
bdDDDDDDDDDDDDDDdb <- Dummy row
|
||||
|
||||
^^^^^^^^^^^^^^^
|
||||
dummy rows cols x 1
|
||||
|
||||
^ dummy columns ^
|
||||
1 x (rows + 4)
|
||||
"""
|
||||
""" Array and dummy/replica columns """
|
||||
# Bitcell array
|
||||
self.bitcell_array = factory.create(module_type="bitcell_array",
|
||||
column_offset=1 + len(self.left_rbl),
|
||||
|
|
@ -96,18 +82,14 @@ class replica_bitcell_array(bitcell_base_array):
|
|||
self.replica_columns = {}
|
||||
|
||||
for port in self.all_ports:
|
||||
# We will always have self.rbl[0] dummy rows below the array
|
||||
# for the replica wordlines.
|
||||
if port in self.left_rbl:
|
||||
# We will always have self.rbl[0] rows of replica wordlines below
|
||||
# the array.
|
||||
# These go from the top (where the bitcell array starts ) down
|
||||
# These go top down starting from the bottom of the bitcell array.
|
||||
replica_bit = self.rbl[0] - port - 1
|
||||
column_offset = len(self.left_rbl)
|
||||
|
||||
elif port in self.right_rbl:
|
||||
|
||||
# We will always have self.rbl[0] rows of replica wordlines below
|
||||
# the array.
|
||||
# These go from the bottom up
|
||||
# These go bottom up starting from the top of the bitcell array.
|
||||
replica_bit = self.rbl[0] + self.row_size + port - 1
|
||||
column_offset = len(self.left_rbl) + self.column_size + 1
|
||||
else:
|
||||
|
|
@ -119,11 +101,13 @@ class replica_bitcell_array(bitcell_base_array):
|
|||
column_offset=column_offset,
|
||||
replica_bit=replica_bit)
|
||||
|
||||
# Dummy row
|
||||
# Dummy row (for replica wordlines)
|
||||
self.dummy_row = factory.create(module_type="dummy_array",
|
||||
cols=self.column_size,
|
||||
rows=1,
|
||||
# dummy column + left replica column
|
||||
# cap column + left replica column
|
||||
# FIXME: these col offsets should really start at 0 because
|
||||
# this is the left edge of the array... but changing them all is work
|
||||
column_offset=1 + len(self.left_rbl),
|
||||
mirror=0)
|
||||
|
||||
|
|
@ -148,7 +132,7 @@ class replica_bitcell_array(bitcell_base_array):
|
|||
self.add_pin("gnd", "GROUND")
|
||||
|
||||
def add_bitline_pins(self):
|
||||
# The bit is which port the RBL is for
|
||||
# The bit represents which port the RBL is for
|
||||
for bit in self.rbls:
|
||||
for port in self.all_ports:
|
||||
self.rbl_bitline_names[bit].append("rbl_bl_{0}_{1}".format(port, bit))
|
||||
|
|
@ -175,6 +159,8 @@ class replica_bitcell_array(bitcell_base_array):
|
|||
self.unused_wordline_names = []
|
||||
|
||||
for port in self.all_ports:
|
||||
if self.rbl[port] == 0:
|
||||
continue # TODO: there's probably a better way to do this check
|
||||
for bit in self.all_ports:
|
||||
self.rbl_wordline_names[port].append("rbl_wl_{0}_{1}".format(port, bit))
|
||||
if bit != port:
|
||||
|
|
@ -225,9 +211,12 @@ class replica_bitcell_array(bitcell_base_array):
|
|||
self.dummy_row_replica_insts = []
|
||||
# Note, this is the number of left and right even if we aren't adding the columns to this bitcell array!
|
||||
for port in self.all_ports: # TODO: tie to self.rbl or whatever
|
||||
self.dummy_row_replica_insts.append(self.add_inst(name="dummy_row_{}".format(port),
|
||||
mod=self.dummy_row))
|
||||
self.connect_inst(self.all_bitline_names + self.rbl_wordline_names[port] + self.supplies)
|
||||
if self.rbl[port] != 0:
|
||||
self.dummy_row_replica_insts.append(self.add_inst(name="dummy_row_{}".format(port),
|
||||
mod=self.dummy_row))
|
||||
self.connect_inst(self.all_bitline_names + self.rbl_wordline_names[port] + self.supplies)
|
||||
else:
|
||||
self.dummy_row_replica_insts.append(None)
|
||||
|
||||
def create_layout(self):
|
||||
|
||||
|
|
@ -249,8 +238,8 @@ class replica_bitcell_array(bitcell_base_array):
|
|||
# Array was at (0, 0) but move everything so it is at the lower left
|
||||
# We move DOWN the number of left RBL even if we didn't add the column to this bitcell array
|
||||
# Note that this doesn't include the row/col cap
|
||||
array_offset = self.bitcell_offset.scale(len(self.left_rbl), self.rbl[0])
|
||||
self.translate_all(array_offset.scale(-1, -1))
|
||||
array_offset = self.bitcell_offset.scale(-len(self.left_rbl), -self.rbl[0])
|
||||
self.translate_all(array_offset)
|
||||
|
||||
self.add_layout_pins()
|
||||
|
||||
|
|
@ -359,7 +348,7 @@ class replica_bitcell_array(bitcell_base_array):
|
|||
height=self.height)
|
||||
|
||||
def route_supplies(self):
|
||||
|
||||
""" just copy supply pins from all instances """
|
||||
for inst in self.insts:
|
||||
for pin_name in ["vdd", "gnd"]:
|
||||
self.copy_layout_pin(inst, pin_name)
|
||||
|
|
|
|||
|
|
@ -49,6 +49,9 @@ class sram_1bank(design, verilog, lef):
|
|||
# Route a M3/M4 grid
|
||||
self.supply_stack = self.m3_stack
|
||||
|
||||
# delay control logic does not have RBLs
|
||||
self.has_rbl = OPTS.control_logic != "control_logic_delay"
|
||||
|
||||
def add_pins(self):
|
||||
""" Add pins for entire SRAM. """
|
||||
|
||||
|
|
@ -518,8 +521,9 @@ class sram_1bank(design, verilog, lef):
|
|||
for port in self.read_ports:
|
||||
for bit in range(self.word_size + self.num_spare_cols):
|
||||
temp.append("dout{0}[{1}]".format(port, bit))
|
||||
for port in self.all_ports:
|
||||
temp.append("rbl_bl{0}".format(port))
|
||||
if self.has_rbl:
|
||||
for port in self.all_ports:
|
||||
temp.append("rbl_bl{0}".format(port))
|
||||
for port in self.write_ports:
|
||||
for bit in range(self.word_size + self.num_spare_cols):
|
||||
temp.append("bank_din{0}_{1}".format(port, bit))
|
||||
|
|
@ -694,7 +698,8 @@ class sram_1bank(design, verilog, lef):
|
|||
if port in self.readwrite_ports:
|
||||
temp.append("web{}".format(port))
|
||||
temp.append("clk{}".format(port))
|
||||
temp.append("rbl_bl{}".format(port))
|
||||
if self.has_rbl:
|
||||
temp.append("rbl_bl{}".format(port))
|
||||
|
||||
# Outputs
|
||||
if port in self.read_ports:
|
||||
|
|
@ -1293,18 +1298,19 @@ class sram_1bank(design, verilog, lef):
|
|||
dest_pin = self.bank_inst.get_pin(signal + "{}".format(port))
|
||||
self.connect_vbus(src_pin, dest_pin)
|
||||
|
||||
for port in self.all_ports:
|
||||
# Only input (besides pins) is the replica bitline
|
||||
src_pin = self.control_logic_insts[port].get_pin("rbl_bl")
|
||||
dest_pin = self.bank_inst.get_pin("rbl_bl_{0}_{0}".format(port))
|
||||
self.add_wire(self.m3_stack,
|
||||
[src_pin.center(), vector(src_pin.cx(), dest_pin.cy()), dest_pin.rc()])
|
||||
self.add_via_stack_center(from_layer=src_pin.layer,
|
||||
to_layer="m4",
|
||||
offset=src_pin.center())
|
||||
self.add_via_stack_center(from_layer=dest_pin.layer,
|
||||
to_layer="m3",
|
||||
offset=dest_pin.center())
|
||||
if self.has_rbl:
|
||||
for port in self.all_ports:
|
||||
# Only input (besides pins) is the replica bitline
|
||||
src_pin = self.control_logic_insts[port].get_pin("rbl_bl")
|
||||
dest_pin = self.bank_inst.get_pin("rbl_bl_{0}_{0}".format(port))
|
||||
self.add_wire(self.m3_stack,
|
||||
[src_pin.center(), vector(src_pin.cx(), dest_pin.cy()), dest_pin.rc()])
|
||||
self.add_via_stack_center(from_layer=src_pin.layer,
|
||||
to_layer="m4",
|
||||
offset=src_pin.center())
|
||||
self.add_via_stack_center(from_layer=dest_pin.layer,
|
||||
to_layer="m3",
|
||||
offset=dest_pin.center())
|
||||
|
||||
def route_row_addr_dff(self):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -68,9 +68,13 @@ class options(optparse.Values):
|
|||
# Approximate percentage of delay compared to bitlines
|
||||
rbl_delay_percentage = 0.5
|
||||
|
||||
# Allow manual adjustment of the delay chain over automatic
|
||||
auto_delay_chain_sizing = False
|
||||
# delay chain is automatically sized in delay based control logic
|
||||
# this multiplier can be used to add a guard band to the standard timing
|
||||
# lowering it can improve performance but may cause sram to fail
|
||||
delay_control_scaling_factor = 1.0
|
||||
# stages for delay chain in rbl control logic only
|
||||
delay_chain_stages = 9
|
||||
# fanout per stage for any control logic
|
||||
delay_chain_fanout_per_stage = 4
|
||||
|
||||
accuracy_requirement = 0.75
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ from openram.sram_factory import factory
|
|||
from openram import OPTS
|
||||
|
||||
|
||||
class capped_replica_bitcell_array_1rw_1r_test(openram_test):
|
||||
class capped_replica_bitcell_array_bothrbl_1rw_1r_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
|
|
@ -25,13 +25,8 @@ class capped_replica_bitcell_array_1rw_1r_test(openram_test):
|
|||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 4x4 array left and right replica for dp cell")
|
||||
a = factory.create(module_type="capped_replica_bitcell_array",
|
||||
cols=4,
|
||||
rows=4,
|
||||
rbl=[1, 1],
|
||||
left_rbl=[0],
|
||||
right_rbl=[1])
|
||||
debug.info(2, "Testing 4x4 capped replica array for 1rw1r cell with both replica columns")
|
||||
a = factory.create(module_type="capped_replica_bitcell_array", cols=4, rows=4, rbl=[1, 1], left_rbl=[0], right_rbl=[1])
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env python3
|
||||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz
|
||||
# All rights reserved.
|
||||
#
|
||||
import sys, os
|
||||
import unittest
|
||||
from testutils import *
|
||||
|
||||
import openram
|
||||
from openram import debug
|
||||
from openram.sram_factory import factory
|
||||
from openram import OPTS
|
||||
|
||||
|
||||
class capped_replica_bitcell_array_dummies_1rw_1r_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
openram.init_openram(config_file, is_unit_test=True)
|
||||
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 4x4 capped replica array for 1rw1r cell with dummy rows only")
|
||||
a = factory.create(module_type="capped_replica_bitcell_array", cols=4, rows=4, rbl=[1, 1])
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main(testRunner=debugTestRunner())
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env python3
|
||||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz
|
||||
# All rights reserved.
|
||||
#
|
||||
import sys, os
|
||||
import unittest
|
||||
from testutils import *
|
||||
|
||||
import openram
|
||||
from openram import debug
|
||||
from openram.sram_factory import factory
|
||||
from openram import OPTS
|
||||
|
||||
|
||||
class capped_replica_bitcell_array_dummies_1rw_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
openram.init_openram(config_file, is_unit_test=True)
|
||||
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 0
|
||||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 7x5 capped replica array for 1rw cell with dummy row only")
|
||||
a = factory.create(module_type="capped_replica_bitcell_array", cols=7, rows=5, rbl=[1, 0])
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main(testRunner=debugTestRunner())
|
||||
|
|
@ -14,7 +14,7 @@ from openram.sram_factory import factory
|
|||
from openram import OPTS
|
||||
|
||||
|
||||
class capped_replica_bitcell_array_1rw_1r_test(openram_test):
|
||||
class capped_replica_bitcell_array_leftrbl_1rw_1r_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
|
|
@ -25,16 +25,13 @@ class capped_replica_bitcell_array_1rw_1r_test(openram_test):
|
|||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 4x4 left replica array for dp cell")
|
||||
a = factory.create(module_type="capped_replica_bitcell_array",
|
||||
cols=4,
|
||||
rows=4,
|
||||
rbl=[1, 1],
|
||||
left_rbl=[0])
|
||||
debug.info(2, "Testing 4x4 capped replica array for 1rw1r cell with left replica column")
|
||||
a = factory.create(module_type="capped_replica_bitcell_array", cols=4, rows=4, rbl=[1, 1], left_rbl=[0])
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ from openram.sram_factory import factory
|
|||
from openram import OPTS
|
||||
|
||||
|
||||
class capped_replica_bitcell_array_test(openram_test):
|
||||
class capped_replica_bitcell_array_leftrbl_1rw_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
|
|
@ -23,8 +23,9 @@ class capped_replica_bitcell_array_test(openram_test):
|
|||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 0
|
||||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 4x4 array for bitcell")
|
||||
debug.info(2, "Testing 7x5 capped replica array for 1rw cell with left replica column")
|
||||
a = factory.create(module_type="capped_replica_bitcell_array", cols=7, rows=5, rbl=[1, 0], left_rbl=[0])
|
||||
self.local_check(a)
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ from openram.sram_factory import factory
|
|||
from openram import OPTS
|
||||
|
||||
|
||||
class capped_replica_bitcell_array_1rw_1r_test(openram_test):
|
||||
class capped_replica_bitcell_array_norbl_1rw_1r_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
|
|
@ -25,11 +25,8 @@ class capped_replica_bitcell_array_1rw_1r_test(openram_test):
|
|||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 4x4 non-replica array for dp cell")
|
||||
a = factory.create(module_type="capped_replica_bitcell_array",
|
||||
cols=4,
|
||||
rows=4,
|
||||
rbl=[1, 1])
|
||||
debug.info(2, "Testing 4x4 capped replica array for 1rw1r cell without replica columns or dummy rows")
|
||||
a = factory.create(module_type="capped_replica_bitcell_array", cols=4, rows=4, rbl=[0, 0])
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ from openram.sram_factory import factory
|
|||
from openram import OPTS
|
||||
|
||||
|
||||
class capped_replica_bitcell_array_test(openram_test):
|
||||
class capped_replica_bitcell_array_norbl_1rw_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
|
|
@ -23,9 +23,10 @@ class capped_replica_bitcell_array_test(openram_test):
|
|||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 0
|
||||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 4x4 array for bitcell")
|
||||
a = factory.create(module_type="capped_replica_bitcell_array", cols=7, rows=5, rbl=[1, 0])
|
||||
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])
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ from openram.sram_factory import factory
|
|||
from openram import OPTS
|
||||
|
||||
|
||||
class capped_replica_bitcell_array_1rw_1r_test(openram_test):
|
||||
class capped_replica_bitcell_array_rightrbl_1rw_1r_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
|
|
@ -25,16 +25,13 @@ class capped_replica_bitcell_array_1rw_1r_test(openram_test):
|
|||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 4x4 left replica array for dp cell")
|
||||
a = factory.create(module_type="capped_replica_bitcell_array",
|
||||
cols=4,
|
||||
rows=4,
|
||||
rbl=[1, 1],
|
||||
right_rbl=[1])
|
||||
debug.info(2, "Testing 4x4 capped replica array for 1rw1r cell with right replica column")
|
||||
a = factory.create(module_type="capped_replica_bitcell_array", cols=4, rows=4, rbl=[1, 1], right_rbl=[1])
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ from openram.sram_factory import factory
|
|||
from openram import OPTS
|
||||
|
||||
|
||||
class replica_bitcell_array_1rw_1r_test(openram_test):
|
||||
class replica_bitcell_array_bothrbl_1rw_1r_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
|
|
@ -25,13 +25,8 @@ class replica_bitcell_array_1rw_1r_test(openram_test):
|
|||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 4x4 array left and right replica for dp cell")
|
||||
a = factory.create(module_type="replica_bitcell_array",
|
||||
cols=4,
|
||||
rows=4,
|
||||
rbl=[1, 1],
|
||||
left_rbl=[0],
|
||||
right_rbl=[1])
|
||||
debug.info(2, "Testing 4x4 replica array for 1rw1r cell with both replica columns")
|
||||
a = factory.create(module_type="replica_bitcell_array", cols=4, rows=4, rbl=[1, 1], left_rbl=[0], right_rbl=[1])
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env python3
|
||||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz
|
||||
# All rights reserved.
|
||||
#
|
||||
import sys, os
|
||||
import unittest
|
||||
from testutils import *
|
||||
|
||||
import openram
|
||||
from openram import debug
|
||||
from openram.sram_factory import factory
|
||||
from openram import OPTS
|
||||
|
||||
|
||||
class replica_bitcell_array_dummies_1rw_1r_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
openram.init_openram(config_file, is_unit_test=True)
|
||||
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 4x4 replica array for 1rw1r cell with dummy rows only")
|
||||
a = factory.create(module_type="replica_bitcell_array", cols=4, rows=4, rbl=[1, 1])
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main(testRunner=debugTestRunner())
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env python3
|
||||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz
|
||||
# All rights reserved.
|
||||
#
|
||||
import sys, os
|
||||
import unittest
|
||||
from testutils import *
|
||||
|
||||
import openram
|
||||
from openram import debug
|
||||
from openram.sram_factory import factory
|
||||
from openram import OPTS
|
||||
|
||||
|
||||
class replica_bitcell_array_dummies_1rw_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
openram.init_openram(config_file, is_unit_test=True)
|
||||
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 0
|
||||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 7x5 replica array for 1rw cell with dummy row only")
|
||||
a = factory.create(module_type="replica_bitcell_array", cols=7, rows=5, rbl=[1, 0])
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main(testRunner=debugTestRunner())
|
||||
|
|
@ -14,7 +14,7 @@ from openram.sram_factory import factory
|
|||
from openram import OPTS
|
||||
|
||||
|
||||
class replica_bitcell_array_1rw_1r_test(openram_test):
|
||||
class replica_bitcell_array_leftrbl_1rw_1r_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
|
|
@ -25,16 +25,13 @@ class replica_bitcell_array_1rw_1r_test(openram_test):
|
|||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 4x4 left replica array for dp cell")
|
||||
a = factory.create(module_type="replica_bitcell_array",
|
||||
cols=4,
|
||||
rows=4,
|
||||
rbl=[1, 1],
|
||||
left_rbl=[0])
|
||||
debug.info(2, "Testing 4x4 replica array for 1rw1r cell with left replica column")
|
||||
a = factory.create(module_type="replica_bitcell_array", cols=4, rows=4, rbl=[1, 1], left_rbl=[0])
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ from openram.sram_factory import factory
|
|||
from openram import OPTS
|
||||
|
||||
|
||||
class replica_bitcell_array_test(openram_test):
|
||||
class replica_bitcell_array_leftrbl_1rw_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
|
|
@ -23,8 +23,9 @@ class replica_bitcell_array_test(openram_test):
|
|||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 0
|
||||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 4x4 array for 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])
|
||||
self.local_check(a)
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ from openram.sram_factory import factory
|
|||
from openram import OPTS
|
||||
|
||||
|
||||
class replica_bitcell_array_1rw_1r_test(openram_test):
|
||||
class replica_bitcell_array_norbl_1rw_1r_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
|
|
@ -25,11 +25,8 @@ class replica_bitcell_array_1rw_1r_test(openram_test):
|
|||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 4x4 non-replica array for dp cell")
|
||||
a = factory.create(module_type="replica_bitcell_array",
|
||||
cols=4,
|
||||
rows=4,
|
||||
rbl=[1, 1])
|
||||
debug.info(2, "Testing 4x4 replica array for 1rw1r cell without replica columns or dummy rows")
|
||||
a = factory.create(module_type="replica_bitcell_array", cols=4, rows=4, rbl=[0, 0])
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ from openram.sram_factory import factory
|
|||
from openram import OPTS
|
||||
|
||||
|
||||
class replica_bitcell_array_test(openram_test):
|
||||
class replica_bitcell_array_norbl_1rw_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
|
|
@ -23,9 +23,10 @@ class replica_bitcell_array_test(openram_test):
|
|||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 0
|
||||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 4x4 array for bitcell")
|
||||
a = factory.create(module_type="replica_bitcell_array", cols=7, rows=5, rbl=[1, 0])
|
||||
debug.info(2, "Testing 7x5 replica array for 1rw cell without replica column or dummy row")
|
||||
a = factory.create(module_type="replica_bitcell_array", cols=7, rows=5, rbl=[0, 0])
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ from openram.sram_factory import factory
|
|||
from openram import OPTS
|
||||
|
||||
|
||||
class replica_bitcell_array_1rw_1r_test(openram_test):
|
||||
class replica_bitcell_array_rightrbl_1rw_1r_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
|
|
@ -25,16 +25,13 @@ class replica_bitcell_array_1rw_1r_test(openram_test):
|
|||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 4x4 left replica array for dp cell")
|
||||
a = factory.create(module_type="replica_bitcell_array",
|
||||
cols=4,
|
||||
rows=4,
|
||||
rbl=[1, 1],
|
||||
right_rbl=[1])
|
||||
debug.info(2, "Testing 4x4 replica array for 1rw1r cell with right replica column")
|
||||
a = factory.create(module_type="replica_bitcell_array", cols=4, rows=4, rbl=[1, 1], right_rbl=[1])
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env python3
|
||||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz
|
||||
# All rights reserved.
|
||||
#
|
||||
import sys, os
|
||||
import unittest
|
||||
from testutils import *
|
||||
|
||||
import openram
|
||||
from openram import debug
|
||||
from openram.sram_factory import factory
|
||||
from openram import OPTS
|
||||
|
||||
|
||||
class global_bitcell_array_norbl_1rw_1r_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
openram.init_openram(config_file, is_unit_test=True)
|
||||
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 2 x 4x4 global bitcell array for 1rw1r cell without replica columns")
|
||||
a = factory.create(module_type="global_bitcell_array", cols=[4, 4, 4], rows=4, rbl=[0, 0], left_rbl=[], right_rbl=[])
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main(testRunner=debugTestRunner())
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env python3
|
||||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz
|
||||
# All rights reserved.
|
||||
#
|
||||
import sys, os
|
||||
import unittest
|
||||
from testutils import *
|
||||
|
||||
import openram
|
||||
from openram import debug
|
||||
from openram.sram_factory import factory
|
||||
from openram import OPTS
|
||||
|
||||
|
||||
class global_bitcell_array_norbl_1rw_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
openram.init_openram(config_file, is_unit_test=True)
|
||||
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 0
|
||||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 2 x 4x4 global bitcell array for 1rw cell without replica column")
|
||||
a = factory.create(module_type="global_bitcell_array", cols=[4, 4], rows=4, rbl=[0, 0], left_rbl=[])
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main(testRunner=debugTestRunner())
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env python3
|
||||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz
|
||||
# All rights reserved.
|
||||
#
|
||||
import sys, os
|
||||
import unittest
|
||||
from testutils import *
|
||||
|
||||
import openram
|
||||
from openram import debug
|
||||
from openram.sram_factory import factory
|
||||
from openram import OPTS
|
||||
|
||||
|
||||
class global_bitcell_array_rbl_1rw_1r_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
openram.init_openram(config_file, is_unit_test=True)
|
||||
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 2 x 4x4 global bitcell array for 1rw1r cell with replica columns")
|
||||
a = factory.create(module_type="global_bitcell_array", cols=[4, 4, 4], rows=4, rbl=[1, 1], left_rbl=[0], right_rbl=[1])
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main(testRunner=debugTestRunner())
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env python3
|
||||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz
|
||||
# All rights reserved.
|
||||
#
|
||||
import sys, os
|
||||
import unittest
|
||||
from testutils import *
|
||||
|
||||
import openram
|
||||
from openram import debug
|
||||
from openram.sram_factory import factory
|
||||
from openram import OPTS
|
||||
|
||||
|
||||
class global_bitcell_array_rbl_1rw_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
openram.init_openram(config_file, is_unit_test=True)
|
||||
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 0
|
||||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 2 x 4x4 global bitcell array for 1rw cell with left replica column")
|
||||
a = factory.create(module_type="global_bitcell_array", cols=[4, 4], rows=4, rbl=[1, 0], left_rbl=[0])
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main(testRunner=debugTestRunner())
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||
# (acting for and on behalf of Oklahoma State University)
|
||||
# All rights reserved.
|
||||
#
|
||||
import sys, os
|
||||
import unittest
|
||||
from testutils import *
|
||||
|
||||
import openram
|
||||
from openram import debug
|
||||
from openram.sram_factory import factory
|
||||
from openram import OPTS
|
||||
|
||||
|
||||
# @unittest.skip("SKIPPING 05_local_bitcell_array_test")
|
||||
class local_bitcell_array_1rw_1r_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
openram.init_openram(config_file, is_unit_test=True)
|
||||
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 4x4 local bitcell array for cell_1rw_1r without replica")
|
||||
a = factory.create(module_type="local_bitcell_array", cols=4, rows=4, rbl=[1, 1])
|
||||
self.local_check(a)
|
||||
|
||||
debug.info(2, "Testing 4x4 local bitcell array for cell_1rw_1r with replica column")
|
||||
a = factory.create(module_type="local_bitcell_array", cols=4, rows=4, rbl=[1, 1], right_rbl=[1])
|
||||
self.local_check(a)
|
||||
|
||||
debug.info(2, "Testing 4x4 local bitcell array for cell_1rw_1r with replica column")
|
||||
a = factory.create(module_type="local_bitcell_array", cols=4, rows=4, rbl=[1, 1], left_rbl=[0])
|
||||
self.local_check(a)
|
||||
|
||||
debug.info(2, "Testing 4x4 local bitcell array for cell_1rw_1r with replica column")
|
||||
a = factory.create(module_type="local_bitcell_array", cols=4, rows=4, rbl=[1, 1], left_rbl=[0], right_rbl=[1])
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main(testRunner=debugTestRunner())
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env python3
|
||||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz
|
||||
# All rights reserved.
|
||||
#
|
||||
import sys, os
|
||||
import unittest
|
||||
from testutils import *
|
||||
|
||||
import openram
|
||||
from openram import debug
|
||||
from openram.sram_factory import factory
|
||||
from openram import OPTS
|
||||
|
||||
|
||||
class local_bitcell_array_bothrbl_1rw_1r_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
openram.init_openram(config_file, is_unit_test=True)
|
||||
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 4x4 local bitcell array for 1rw1r cell with both replica columns")
|
||||
a = factory.create(module_type="local_bitcell_array", cols=4, rows=4, rbl=[1, 1], left_rbl=[0], right_rbl=[1])
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main(testRunner=debugTestRunner())
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env python3
|
||||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz
|
||||
# All rights reserved.
|
||||
#
|
||||
import sys, os
|
||||
import unittest
|
||||
from testutils import *
|
||||
|
||||
import openram
|
||||
from openram import debug
|
||||
from openram.sram_factory import factory
|
||||
from openram import OPTS
|
||||
|
||||
|
||||
class local_bitcell_array_dummies_1rw_1r_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
openram.init_openram(config_file, is_unit_test=True)
|
||||
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 4x4 local bitcell array for 1rw1r cell with dummy rows only")
|
||||
a = factory.create(module_type="local_bitcell_array", cols=4, rows=4, rbl=[1, 1])
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main(testRunner=debugTestRunner())
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env python3
|
||||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz
|
||||
# All rights reserved.
|
||||
#
|
||||
import sys, os
|
||||
import unittest
|
||||
from testutils import *
|
||||
|
||||
import openram
|
||||
from openram import debug
|
||||
from openram.sram_factory import factory
|
||||
from openram import OPTS
|
||||
|
||||
|
||||
class local_bitcell_array_dummies_1rw_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
openram.init_openram(config_file, is_unit_test=True)
|
||||
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 0
|
||||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 7x5 local bitcell array for 1rw cell with dummy row only")
|
||||
a = factory.create(module_type="local_bitcell_array", cols=7, rows=5, rbl=[1, 0])
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main(testRunner=debugTestRunner())
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env python3
|
||||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz
|
||||
# All rights reserved.
|
||||
#
|
||||
import sys, os
|
||||
import unittest
|
||||
from testutils import *
|
||||
|
||||
import openram
|
||||
from openram import debug
|
||||
from openram.sram_factory import factory
|
||||
from openram import OPTS
|
||||
|
||||
|
||||
class local_bitcell_array_leftrbl_1rw_1r_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
openram.init_openram(config_file, is_unit_test=True)
|
||||
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 4x4 local bitcell array for 1rw1r cell with left replica column")
|
||||
a = factory.create(module_type="local_bitcell_array", cols=4, rows=4, rbl=[1, 1], left_rbl=[0])
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main(testRunner=debugTestRunner())
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env python3
|
||||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz
|
||||
# All rights reserved.
|
||||
#
|
||||
import sys, os
|
||||
import unittest
|
||||
from testutils import *
|
||||
|
||||
import openram
|
||||
from openram import debug
|
||||
from openram.sram_factory import factory
|
||||
from openram import OPTS
|
||||
|
||||
|
||||
class local_bitcell_array_leftrbl_1rw_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
openram.init_openram(config_file, is_unit_test=True)
|
||||
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 0
|
||||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 7x5 local bitcell array for 1rw cell with left replica column")
|
||||
a = factory.create(module_type="local_bitcell_array", cols=7, rows=5, rbl=[1, 0], left_rbl=[0])
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main(testRunner=debugTestRunner())
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env python3
|
||||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz
|
||||
# All rights reserved.
|
||||
#
|
||||
import sys, os
|
||||
import unittest
|
||||
from testutils import *
|
||||
|
||||
import openram
|
||||
from openram import debug
|
||||
from openram.sram_factory import factory
|
||||
from openram import OPTS
|
||||
|
||||
|
||||
class local_bitcell_array_norbl_1rw_1r_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
openram.init_openram(config_file, is_unit_test=True)
|
||||
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 4x4 local bitcell array for 1rw1r cell without replica columns or dummy rows")
|
||||
a = factory.create(module_type="local_bitcell_array", cols=4, rows=4, rbl=[0, 0])
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main(testRunner=debugTestRunner())
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env python3
|
||||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz
|
||||
# All rights reserved.
|
||||
#
|
||||
import sys, os
|
||||
import unittest
|
||||
from testutils import *
|
||||
|
||||
import openram
|
||||
from openram import debug
|
||||
from openram.sram_factory import factory
|
||||
from openram import OPTS
|
||||
|
||||
|
||||
class local_bitcell_array_norbl_1rw_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
openram.init_openram(config_file, is_unit_test=True)
|
||||
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 0
|
||||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 7x5 local bitcell array for 1rw cell without replica column or dummy row")
|
||||
a = factory.create(module_type="local_bitcell_array", cols=7, rows=5, rbl=[0, 0])
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main(testRunner=debugTestRunner())
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env python3
|
||||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz
|
||||
# All rights reserved.
|
||||
#
|
||||
import sys, os
|
||||
import unittest
|
||||
from testutils import *
|
||||
|
||||
import openram
|
||||
from openram import debug
|
||||
from openram.sram_factory import factory
|
||||
from openram import OPTS
|
||||
|
||||
|
||||
class local_bitcell_array_rightrbl_1rw_1r_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
openram.init_openram(config_file, is_unit_test=True)
|
||||
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 4x4 local bitcell array for 1rw1r cell with right replica column")
|
||||
a = factory.create(module_type="local_bitcell_array", cols=4, rows=4, rbl=[1, 1], right_rbl=[1])
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main(testRunner=debugTestRunner())
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
#!/usr/bin/env python3
|
||||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||
# (acting for and on behalf of Oklahoma State University)
|
||||
# All rights reserved.
|
||||
#
|
||||
"""
|
||||
Run a regression test on a control_logic_delay
|
||||
"""
|
||||
|
||||
import sys, os
|
||||
import unittest
|
||||
from testutils import header,openram_test
|
||||
|
||||
import openram
|
||||
from openram import debug
|
||||
from openram.sram_factory import factory
|
||||
from openram import OPTS
|
||||
|
||||
|
||||
class control_logic_delay_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
openram.init_openram(config_file, is_unit_test=True)
|
||||
|
||||
# check control logic for multi-port
|
||||
OPTS.bitcell = "pbitcell"
|
||||
OPTS.replica_bitcell = "replica_pbitcell"
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_w_ports = 1
|
||||
OPTS.num_r_ports = 1
|
||||
|
||||
debug.info(1, "Testing sample for control_logic_delay for multiport, combined read-write control logic")
|
||||
a = factory.create(module_type="control_logic_delay", num_rows=128, words_per_row=1, word_size=8, port_type="rw")
|
||||
self.local_check(a)
|
||||
|
||||
# OPTS.num_rw_ports = 0
|
||||
# OPTS.num_w_ports = 1
|
||||
debug.info(1, "Testing sample for control_logic_delay for multiport, only write control logic")
|
||||
a = factory.create(module_type="control_logic_delay", num_rows=128, words_per_row=1, word_size=8, port_type="w")
|
||||
self.local_check(a)
|
||||
|
||||
# OPTS.num_w_ports = 0
|
||||
# OPTS.num_r_ports = 1
|
||||
debug.info(1, "Testing sample for control_logic_delay for multiport, only read control logic")
|
||||
a = factory.create(module_type="control_logic_delay", num_rows=128, words_per_row=1, word_size=8, port_type="r")
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main()
|
||||
|
|
@ -11,29 +11,23 @@ import unittest
|
|||
from testutils import *
|
||||
|
||||
import openram
|
||||
from openram.sram_factory import factory
|
||||
from openram import debug
|
||||
from openram.sram_factory import factory
|
||||
from openram import OPTS
|
||||
|
||||
|
||||
# @unittest.skip("SKIPPING 05_global_bitcell_array_test")
|
||||
class global_bitcell_array_test(openram_test):
|
||||
class control_logic_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
openram.init_openram(config_file, is_unit_test=True)
|
||||
|
||||
# debug.info(2, "Testing 2 x 4x4 global bitcell array for 6t_cell")
|
||||
# a = factory.create(module_type="global_bitcell_array", cols=[4, 4], rows=4)
|
||||
# self.local_check(a)
|
||||
|
||||
debug.info(2, "Testing 2 x 4x4 global bitcell array for 6t_cell")
|
||||
a = factory.create(module_type="global_bitcell_array", cols=[10, 6], rows=4)
|
||||
debug.info(1, "Testing sample for control_logic_r")
|
||||
a = factory.create(module_type="control_logic_delay", num_rows=128, words_per_row=1, word_size=32, port_type="r")
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
|
|
@ -16,24 +16,18 @@ from openram.sram_factory import factory
|
|||
from openram import OPTS
|
||||
|
||||
|
||||
# @unittest.skip("SKIPPING 05_local_bitcell_array_test")
|
||||
class local_bitcell_array_test(openram_test):
|
||||
class control_logic_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
openram.init_openram(config_file, is_unit_test=True)
|
||||
|
||||
debug.info(2, "Testing 4x4 local bitcell array for 6t_cell without replica")
|
||||
a = factory.create(module_type="local_bitcell_array", cols=4, rows=4, rbl=[1, 0])
|
||||
self.local_check(a)
|
||||
|
||||
debug.info(2, "Testing 4x4 local bitcell array for 6t_cell with replica column")
|
||||
a = factory.create(module_type="local_bitcell_array", cols=4, rows=4, rbl=[1, 0], left_rbl=[0])
|
||||
debug.info(1, "Testing sample for control_logic_rw")
|
||||
a = factory.create(module_type="control_logic_delay", num_rows=128, words_per_row=1, word_size=32)
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
#!/usr/bin/env python3
|
||||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||
# (acting for and on behalf of Oklahoma State University)
|
||||
# All rights reserved.
|
||||
#
|
||||
import sys, os
|
||||
import unittest
|
||||
from testutils import *
|
||||
|
||||
import openram
|
||||
from openram import debug
|
||||
from openram.sram_factory import factory
|
||||
from openram import OPTS
|
||||
|
||||
|
||||
class control_logic_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
openram.init_openram(config_file, is_unit_test=True)
|
||||
|
||||
debug.info(1, "Testing sample for control_logic_w")
|
||||
a = factory.create(module_type="control_logic_delay", num_rows=128, words_per_row=1, word_size=32, port_type="w")
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main(testRunner=debugTestRunner())
|
||||
|
|
@ -33,7 +33,7 @@ class control_logic_test(openram_test):
|
|||
OPTS.num_w_ports = 1
|
||||
OPTS.num_r_ports = 1
|
||||
|
||||
debug.info(1, "Testing sample for control_logic for multiport, only write control logic")
|
||||
debug.info(1, "Testing sample for control_logic for multiport, combined read-write control logic")
|
||||
a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=8, port_type="rw")
|
||||
self.local_check(a)
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class port_address_1rw_1r_test(openram_test):
|
|||
openram.setup_bitcell()
|
||||
|
||||
debug.info(1, "Port address 16 rows")
|
||||
a = factory.create("port_address", cols=16, rows=16, port=0)
|
||||
a = factory.create("port_address", cols=16, rows=16, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ class port_address_test(openram_test):
|
|||
openram.init_openram(config_file, is_unit_test=True)
|
||||
|
||||
debug.info(1, "Port address 16 rows")
|
||||
a = factory.create("port_address", cols=16, rows=16, port=0)
|
||||
a = factory.create("port_address", cols=16, rows=16, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class port_address_1rw_1r_test(openram_test):
|
|||
openram.setup_bitcell()
|
||||
|
||||
debug.info(1, "Port address 256 rows")
|
||||
a = factory.create("port_address", cols=256, rows=256, port=1)
|
||||
a = factory.create("port_address", cols=256, rows=256, port=1, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ class port_address_test(openram_test):
|
|||
openram.init_openram(config_file, is_unit_test=True)
|
||||
|
||||
debug.info(1, "Port address 512 rows")
|
||||
a = factory.create("port_address", cols=256, rows=512, port=0)
|
||||
a = factory.create("port_address", cols=256, rows=512, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
|
|
|||
|
|
@ -34,9 +34,9 @@ class port_data_1rw_1r_test(openram_test):
|
|||
c.words_per_row=16
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Sixteen way column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
a = factory.create("port_data", sram_config=c, port=1)
|
||||
a = factory.create("port_data", sram_config=c, port=1, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ class port_data_test(openram_test):
|
|||
c.words_per_row=16
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Sixteen way column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ class port_data_1rw_1r_test(openram_test):
|
|||
c.words_per_row=2
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Two way column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
a = factory.create("port_data", sram_config=c, port=1)
|
||||
a = factory.create("port_data", sram_config=c, port=1, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ class port_data_test(openram_test):
|
|||
c.words_per_row=2
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Two way column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ class port_data_1rw_1r_test(openram_test):
|
|||
c.words_per_row=4
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Four way column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
a = factory.create("port_data", sram_config=c, port=1)
|
||||
a = factory.create("port_data", sram_config=c, port=1, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ class port_data_test(openram_test):
|
|||
c.words_per_row=4
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Four way column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
|
|
|||
|
|
@ -34,9 +34,9 @@ class port_data_1rw_1r_test(openram_test):
|
|||
c.words_per_row=8
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Eight way column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
a = factory.create("port_data", sram_config=c, port=1)
|
||||
a = factory.create("port_data", sram_config=c, port=1, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ class port_data_test(openram_test):
|
|||
c.words_per_row=8
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Eight way column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
|
|
|||
|
|
@ -32,9 +32,9 @@ class port_data_1rw_1r_test(openram_test):
|
|||
c.words_per_row=1
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "No column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
a = factory.create("port_data", sram_config=c, port=1)
|
||||
a = factory.create("port_data", sram_config=c, port=1, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ class port_data_test(openram_test):
|
|||
c.words_per_row=1
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "No column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
|
|
|||
|
|
@ -28,14 +28,14 @@ class port_data_spare_cols_test(openram_test):
|
|||
c.words_per_row=1
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "No column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
c.num_words=32
|
||||
c.words_per_row=2
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Two way column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
c.num_words=64
|
||||
|
|
@ -43,7 +43,7 @@ class port_data_spare_cols_test(openram_test):
|
|||
c.num_spare_cols=3
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Four way column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
c.word_size=2
|
||||
|
|
@ -52,7 +52,7 @@ class port_data_spare_cols_test(openram_test):
|
|||
c.num_spare_cols=4
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Eight way column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
OPTS.num_rw_ports = 0
|
||||
|
|
@ -64,27 +64,27 @@ class port_data_spare_cols_test(openram_test):
|
|||
c.words_per_row=1
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "No column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
a = factory.create("port_data", sram_config=c, port=1)
|
||||
a = factory.create("port_data", sram_config=c, port=1, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
c.num_words=32
|
||||
c.words_per_row=2
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Two way column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
a = factory.create("port_data", sram_config=c, port=1)
|
||||
a = factory.create("port_data", sram_config=c, port=1, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
c.num_words=64
|
||||
c.words_per_row=4
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Four way column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
a = factory.create("port_data", sram_config=c, port=1)
|
||||
a = factory.create("port_data", sram_config=c, port=1, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
c.word_size=2
|
||||
|
|
@ -92,9 +92,9 @@ class port_data_spare_cols_test(openram_test):
|
|||
c.words_per_row=8
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Eight way column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
a = factory.create("port_data", sram_config=c, port=1)
|
||||
a = factory.create("port_data", sram_config=c, port=1, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
|
|
|||
|
|
@ -33,28 +33,28 @@ class port_data_wmask_1rw_1r_test(openram_test):
|
|||
c.words_per_row = 1
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "No column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
c.num_words = 32
|
||||
c.words_per_row = 2
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Two way column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
c.num_words = 64
|
||||
c.words_per_row = 4
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Four way column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
c.num_words = 128
|
||||
c.words_per_row = 8
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Eight way column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
OPTS.num_rw_ports = 0
|
||||
|
|
@ -66,27 +66,27 @@ class port_data_wmask_1rw_1r_test(openram_test):
|
|||
c.words_per_row = 1
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "No column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
a = factory.create("port_data", sram_config=c, port=1)
|
||||
a = factory.create("port_data", sram_config=c, port=1, has_rbl=True)
|
||||
self.local_check(a)
|
||||
#
|
||||
c.num_words = 32
|
||||
c.words_per_row = 2
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Two way column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
a = factory.create("port_data", sram_config=c, port=1)
|
||||
a = factory.create("port_data", sram_config=c, port=1, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
c.num_words = 64
|
||||
c.words_per_row = 4
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Four way column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
a = factory.create("port_data", sram_config=c, port=1)
|
||||
a = factory.create("port_data", sram_config=c, port=1, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
c.word_size = 8
|
||||
|
|
@ -94,9 +94,9 @@ class port_data_wmask_1rw_1r_test(openram_test):
|
|||
c.words_per_row = 8
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Eight way column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
a = factory.create("port_data", sram_config=c, port=1)
|
||||
a = factory.create("port_data", sram_config=c, port=1, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
|
|
|||
|
|
@ -37,28 +37,28 @@ class port_data_wmask_test(openram_test):
|
|||
c.words_per_row = 1
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "No column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
c.num_words = 32
|
||||
c.words_per_row = 2
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Two way column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
c.num_words = 64
|
||||
c.words_per_row = 4
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Four way column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
c.num_words = 128
|
||||
c.words_per_row = 8
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Eight way column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
OPTS.num_rw_ports = 0
|
||||
|
|
@ -70,27 +70,27 @@ class port_data_wmask_test(openram_test):
|
|||
c.words_per_row = 1
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "No column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
a = factory.create("port_data", sram_config=c, port=1)
|
||||
a = factory.create("port_data", sram_config=c, port=1, has_rbl=True)
|
||||
self.local_check(a)
|
||||
#
|
||||
c.num_words = 32
|
||||
c.words_per_row = 2
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Two way column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
a = factory.create("port_data", sram_config=c, port=1)
|
||||
a = factory.create("port_data", sram_config=c, port=1, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
c.num_words = 64
|
||||
c.words_per_row = 4
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Four way column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
a = factory.create("port_data", sram_config=c, port=1)
|
||||
a = factory.create("port_data", sram_config=c, port=1, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
c.word_size = 8
|
||||
|
|
@ -98,9 +98,9 @@ class port_data_wmask_test(openram_test):
|
|||
c.words_per_row = 8
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Eight way column mux")
|
||||
a = factory.create("port_data", sram_config=c, port=0)
|
||||
a = factory.create("port_data", sram_config=c, port=0, has_rbl=True)
|
||||
self.local_check(a)
|
||||
a = factory.create("port_data", sram_config=c, port=1)
|
||||
a = factory.create("port_data", sram_config=c, port=1, has_rbl=True)
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
|
|
|||
|
|
@ -16,25 +16,27 @@ from openram.sram_factory import factory
|
|||
from openram import OPTS
|
||||
|
||||
|
||||
# @unittest.skip("SKIPPING 05_global_bitcell_array_test")
|
||||
class global_bitcell_array_test(openram_test):
|
||||
class single_bank_nomux_norbl_1rw_1r_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
openram.init_openram(config_file, is_unit_test=True)
|
||||
from openram import sram_config
|
||||
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
debug.info(2, "Testing 2 x 4x4 global bitcell array for cell_1rw_1r")
|
||||
a = factory.create(module_type="global_bitcell_array", cols=[4, 4], rows=4)
|
||||
self.local_check(a)
|
||||
c = sram_config(word_size=4,
|
||||
num_words=16)
|
||||
|
||||
# debug.info(2, "Testing 4x4 local bitcell array for 6t_cell with replica column")
|
||||
# a = factory.create(module_type="local_bitcell_array", cols=4, left_rbl=1, rows=4, ports=[0])
|
||||
# self.local_check(a)
|
||||
c.words_per_row=1
|
||||
OPTS.control_logic = "control_logic_delay"
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "No column mux")
|
||||
a = factory.create(module_type="bank", sram_config=c)
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
#!/usr/bin/env python3
|
||||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||
# (acting for and on behalf of Oklahoma State University)
|
||||
# All rights reserved.
|
||||
#
|
||||
import sys, os
|
||||
import unittest
|
||||
from testutils import *
|
||||
|
||||
import openram
|
||||
from openram import debug
|
||||
from openram.sram_factory import factory
|
||||
from openram import OPTS
|
||||
|
||||
|
||||
class single_bank_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
openram.init_openram(config_file, is_unit_test=True)
|
||||
from openram import sram_config
|
||||
|
||||
if OPTS.tech_name == "sky130":
|
||||
num_spare_rows = 1
|
||||
num_spare_cols = 1
|
||||
else:
|
||||
num_spare_rows = 0
|
||||
num_spare_cols = 0
|
||||
|
||||
c = sram_config(word_size=4,
|
||||
num_words=16,
|
||||
num_spare_cols=num_spare_cols,
|
||||
num_spare_rows=num_spare_rows)
|
||||
|
||||
c.words_per_row=1
|
||||
OPTS.control_logic = "control_logic_delay"
|
||||
factory.reset()
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "No column mux")
|
||||
a = factory.create("bank", sram_config=c)
|
||||
self.local_check(a)
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main(testRunner=debugTestRunner())
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
#!/usr/bin/env python3
|
||||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||
# (acting for and on behalf of Oklahoma State University)
|
||||
# All rights reserved.
|
||||
#
|
||||
import sys, os
|
||||
import unittest
|
||||
from testutils import *
|
||||
|
||||
import openram
|
||||
from openram import debug
|
||||
from openram.sram_factory import factory
|
||||
from openram import OPTS
|
||||
|
||||
|
||||
class sram_1bank_nomux_norbl_1rw_1r_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
openram.init_openram(config_file, is_unit_test=True)
|
||||
from openram import sram_config
|
||||
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
c = sram_config(word_size=4,
|
||||
num_words=16,
|
||||
num_banks=1)
|
||||
|
||||
c.words_per_row=1
|
||||
OPTS.control_logic = "control_logic_delay"
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Layout test for {}rw,{}r,{}w sram "
|
||||
"with {} bit words, {} words, {} words per "
|
||||
"row, {} banks".format(OPTS.num_rw_ports,
|
||||
OPTS.num_r_ports,
|
||||
OPTS.num_w_ports,
|
||||
c.word_size,
|
||||
c.num_words,
|
||||
c.words_per_row,
|
||||
c.num_banks))
|
||||
a = factory.create(module_type="sram", sram_config=c)
|
||||
self.local_check(a, final_verification=True)
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main(testRunner=debugTestRunner())
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
#!/usr/bin/env python3
|
||||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||
# (acting for and on behalf of Oklahoma State University)
|
||||
# All rights reserved.
|
||||
#
|
||||
import sys, os
|
||||
import unittest
|
||||
from testutils import *
|
||||
|
||||
import openram
|
||||
from openram import debug
|
||||
from openram.sram_factory import factory
|
||||
from openram import OPTS
|
||||
|
||||
|
||||
class sram_1bank_nomux_norbl_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
openram.init_openram(config_file, is_unit_test=True)
|
||||
from openram import sram_config
|
||||
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 0
|
||||
OPTS.num_w_ports = 0
|
||||
openram.setup_bitcell()
|
||||
|
||||
c = sram_config(word_size=4,
|
||||
num_words=16,
|
||||
num_banks=1)
|
||||
|
||||
c.words_per_row=1
|
||||
OPTS.control_logic = "control_logic_delay"
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Layout test for {}rw,{}r,{}w sram "
|
||||
"with {} bit words, {} words, {} words per "
|
||||
"row, {} banks".format(OPTS.num_rw_ports,
|
||||
OPTS.num_r_ports,
|
||||
OPTS.num_w_ports,
|
||||
c.word_size,
|
||||
c.num_words,
|
||||
c.words_per_row,
|
||||
c.num_banks))
|
||||
a = factory.create(module_type="sram", sram_config=c)
|
||||
self.local_check(a, final_verification=True)
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main(testRunner=debugTestRunner())
|
||||
|
|
@ -32,6 +32,7 @@ BROKEN_STAMPS = \
|
|||
%/20_psram_1bank_2mux_test.ok \
|
||||
%/21_hspice_delay_test.ok \
|
||||
%/21_hspice_setuphold_test.ok \
|
||||
%/21_xyce_delay_test.ok \
|
||||
%/22_psram_1bank_2mux_func_test.ok \
|
||||
%/22_psram_1bank_4mux_func_test.ok \
|
||||
%/22_psram_1bank_8mux_func_test.ok \
|
||||
|
|
@ -69,8 +70,11 @@ BROKEN_STAMPS = \
|
|||
freepdk45/10_rom_wordline_driver_array_test.ok \
|
||||
freepdk45/14_rom_array_test.ok \
|
||||
freepdk45/16_rom_control_logic_test.ok \
|
||||
freepdk45/16_control_logic_delay_multiport_test.ok \
|
||||
freepdk45/16_control_logic_delay_rw_test.ok \
|
||||
freepdk45/16_control_logic_delay_r_test.ok \
|
||||
freepdk45/16_control_logic_delay_w_test.ok \
|
||||
freepdk45/19_rom_bank_test.ok \
|
||||
freepdk45/21_xyce_delay_test.ok \
|
||||
scn4m_subm/06_rom_decoder_test.ok \
|
||||
scn4m_subm/07_rom_column_mux_array_test.ok \
|
||||
scn4m_subm/08_rom_decoder_buffer_array_test.ok \
|
||||
|
|
@ -80,8 +84,8 @@ BROKEN_STAMPS = \
|
|||
scn4m_subm/16_rom_control_logic_test.ok \
|
||||
scn4m_subm/19_rom_bank_test.ok \
|
||||
scn4m_subm/19_single_bank_global_bitline_test.ok \
|
||||
scn4m_subm/21_xyce_delay_test.ok \
|
||||
sky130/01_library_test.ok \
|
||||
sky130/03_wire_test.ok \
|
||||
sky130/04_column_mux_pbitcell_test.ok \
|
||||
sky130/04_dummy_pbitcell_test.ok \
|
||||
sky130/04_pbitcell_test.ok \
|
||||
|
|
@ -89,15 +93,78 @@ BROKEN_STAMPS = \
|
|||
sky130/04_pand4_test.ok \
|
||||
sky130/04_precharge_pbitcell_test.ok \
|
||||
sky130/04_replica_pbitcell_test.ok \
|
||||
sky130/04_dummy_pbitcell_1rw1r1w_test.ok \
|
||||
sky130/04_dummy_pbitcell_1rw_test.ok \
|
||||
sky130/04_replica_pbitcell_1rw1r1w_test.ok \
|
||||
sky130/04_replica_pbitcell_1rw_test.ok \
|
||||
sky130/05_pbitcell_array_test.ok \
|
||||
sky130/05_bitcell_array_test.ok \
|
||||
sky130/05_bitcell_array_1rw_1r_test.ok \
|
||||
sky130/05_dummy_array_test.ok \
|
||||
sky130/06_hierarchical_decoder_132row_test.ok \
|
||||
sky130/06_hierarchical_decoder_512row_test.ok \
|
||||
sky130/06_hierarchical_decoder_64row_test.ok \
|
||||
sky130/06_hierarchical_decoder_pbitcell_test.ok \
|
||||
sky130/07_column_mux_array_pbitcell_test.ok \
|
||||
sky130/10_write_driver_array_spare_cols_test.ok \
|
||||
sky130/10_write_driver_array_wmask_spare_cols_test.ok \
|
||||
sky130/14_capped_replica_bitcell_array_dummies_1rw_test.ok \
|
||||
sky130/14_capped_replica_bitcell_array_leftrbl_1rw_test.ok \
|
||||
sky130/14_capped_replica_bitcell_array_norbl_1rw_1r_test.ok \
|
||||
sky130/14_capped_replica_bitcell_array_norbl_1rw_test.ok \
|
||||
sky130/14_replica_bitcell_array_dummies_1rw_test.ok \
|
||||
sky130/14_replica_bitcell_array_leftrbl_1rw_test.ok \
|
||||
sky130/14_replica_bitcell_array_norbl_1rw_1r_test.ok \
|
||||
sky130/14_replica_bitcell_array_norbl_1rw_test.ok \
|
||||
sky130/14_replica_column_1rw_1r_test.ok \
|
||||
sky130/14_replica_column_1rw_test.ok \
|
||||
sky130/14_replica_pbitcell_1rw1r_array_test.ok \
|
||||
sky130/14_replica_pbitcell_1rw_array_test.ok \
|
||||
sky130/15_global_bitcell_array_norbl_1rw_1r_test.ok \
|
||||
sky130/15_global_bitcell_array_norbl_1rw_test.ok \
|
||||
sky130/15_global_bitcell_array_rbl_1rw_1r_test.ok \
|
||||
sky130/15_global_bitcell_array_rbl_1rw_test.ok \
|
||||
sky130/15_local_bitcell_array_dummies_1rw_test.ok \
|
||||
sky130/15_local_bitcell_array_leftrbl_1rw_test.ok \
|
||||
sky130/15_local_bitcell_array_norbl_1rw_1r_test.ok \
|
||||
sky130/15_local_bitcell_array_norbl_1rw_test.ok \
|
||||
sky130/16_control_logic_delay_multiport_test.ok \
|
||||
sky130/16_control_logic_delay_rw_test.ok \
|
||||
sky130/16_control_logic_delay_r_test.ok \
|
||||
sky130/16_control_logic_delay_w_test.ok \
|
||||
sky130/18_port_address_512rows_test.ok \
|
||||
sky130/18_port_data_spare_cols_test.ok \
|
||||
sky130/19_single_bank_2mux_test.ok \
|
||||
sky130/19_single_bank_4mux_test.ok \
|
||||
sky130/19_single_bank_8mux_test.ok \
|
||||
sky130/19_single_bank_global_bitline_test.ok \
|
||||
sky130/19_single_bank_nomux_test.ok \
|
||||
sky130/19_single_bank_nomux_norbl_1rw_1r_test.ok \
|
||||
sky130/19_single_bank_nomux_norbl_test.ok \
|
||||
sky130/19_single_bank_spare_cols_test.ok \
|
||||
sky130/19_single_bank_wmask_test.ok \
|
||||
sky130/19_pmulti_bank_test.ok \
|
||||
sky130/19_psingle_bank_test.ok \
|
||||
sky130/19_bank_select_pbitcell_test.ok \
|
||||
sky130/20_psram_1bank_4mux_1rw_1r_test.ok \
|
||||
sky130/20_sram_1bank_2mux_1rw_1r_spare_cols_test.ok \
|
||||
sky130/20_sram_1bank_2mux_1w_1r_spare_cols_test.ok \
|
||||
sky130/20_sram_1bank_2mux_global_test.ok \
|
||||
sky130/20_sram_1bank_2mux_test.ok \
|
||||
sky130/20_sram_1bank_2mux_wmask_spare_cols_test.ok \
|
||||
sky130/20_sram_1bank_2mux_wmask_test.ok \
|
||||
sky130/20_sram_1bank_4mux_test.ok \
|
||||
sky130/20_sram_1bank_8mux_test.ok \
|
||||
sky130/20_sram_1bank_nomux_norbl_1rw_1r_test.ok \
|
||||
sky130/20_sram_1bank_nomux_norbl_test.ok \
|
||||
sky130/20_sram_1bank_nomux_spare_cols_test.ok \
|
||||
sky130/20_sram_1bank_nomux_test.ok \
|
||||
sky130/20_sram_1bank_nomux_wmask_test.ok \
|
||||
sky130/20_sram_1bank_ring_test.ok \
|
||||
sky130/21_model_delay_test.ok \
|
||||
sky130/21_ngspice_delay_extra_rows_test.ok \
|
||||
sky130/21_ngspice_delay_test.ok \
|
||||
sky130/21_regression_delay_test.ok \
|
||||
sky130/22_psram_1bank_2mux_func_test.ok \
|
||||
sky130/22_psram_1bank_4mux_func_test.ok \
|
||||
sky130/22_psram_1bank_8mux_func_test.ok \
|
||||
|
|
@ -107,54 +174,6 @@ BROKEN_STAMPS = \
|
|||
sky130/23_lib_sram_model_test.ok \
|
||||
sky130/23_lib_sram_prune_test.ok \
|
||||
sky130/23_lib_sram_test.ok \
|
||||
sky130/03_wire_test.ok \
|
||||
sky130/04_dummy_pbitcell_1rw1r1w_test.ok \
|
||||
sky130/04_dummy_pbitcell_1rw_test.ok \
|
||||
sky130/04_replica_pbitcell_1rw1r1w_test.ok \
|
||||
sky130/04_replica_pbitcell_1rw_test.ok \
|
||||
sky130/06_hierarchical_decoder_132row_test.ok \
|
||||
sky130/06_hierarchical_decoder_512row_test.ok \
|
||||
sky130/06_hierarchical_decoder_64row_test.ok \
|
||||
sky130/06_hierarchical_decoder_pbitcell_test.ok \
|
||||
sky130/10_write_driver_array_spare_cols_test.ok \
|
||||
sky130/10_write_driver_array_wmask_spare_cols_test.ok \
|
||||
sky130/14_capped_replica_bitcell_array_leftrbl_1rw_test.ok \
|
||||
sky130/14_capped_replica_bitcell_array_norbl_1rw_test.ok \
|
||||
sky130/14_replica_bitcell_array_leftrbl_1rw_test.ok \
|
||||
sky130/14_replica_bitcell_array_norbl_1rw_test.ok \
|
||||
sky130/14_replica_column_1rw_1r_test.ok \
|
||||
sky130/14_replica_column_1rw_test.ok \
|
||||
sky130/14_replica_pbitcell_1rw1r_array_test.ok \
|
||||
sky130/14_replica_pbitcell_1rw_array_test.ok \
|
||||
sky130/15_global_bitcell_array_1rw_1r_test.ok \
|
||||
sky130/15_global_bitcell_array_test.ok \
|
||||
sky130/15_local_bitcell_array_test.ok \
|
||||
sky130/18_port_address_512rows_test.ok \
|
||||
sky130/18_port_data_spare_cols_test.ok \
|
||||
sky130/19_single_bank_2mux_test.ok \
|
||||
sky130/19_single_bank_4mux_test.ok \
|
||||
sky130/19_single_bank_8mux_test.ok \
|
||||
sky130/19_single_bank_global_bitline_test.ok \
|
||||
sky130/19_single_bank_nomux_test.ok \
|
||||
sky130/19_single_bank_spare_cols_test.ok \
|
||||
sky130/19_single_bank_wmask_test.ok \
|
||||
sky130/20_sram_1bank_2mux_1rw_1r_spare_cols_test.ok \
|
||||
sky130/20_sram_1bank_2mux_1w_1r_spare_cols_test.ok \
|
||||
sky130/20_sram_1bank_2mux_global_test.ok \
|
||||
sky130/20_sram_1bank_2mux_test.ok \
|
||||
sky130/20_sram_1bank_2mux_wmask_spare_cols_test.ok \
|
||||
sky130/20_sram_1bank_2mux_wmask_test.ok \
|
||||
sky130/20_sram_1bank_4mux_test.ok \
|
||||
sky130/20_sram_1bank_8mux_test.ok \
|
||||
sky130/20_sram_1bank_nomux_spare_cols_test.ok \
|
||||
sky130/20_sram_1bank_nomux_test.ok \
|
||||
sky130/20_sram_1bank_nomux_wmask_test.ok \
|
||||
sky130/20_sram_1bank_ring_test.ok \
|
||||
sky130/21_model_delay_test.ok \
|
||||
sky130/21_ngspice_delay_extra_rows_test.ok \
|
||||
sky130/21_ngspice_delay_test.ok \
|
||||
sky130/21_regression_delay_test.ok \
|
||||
sky130/21_xyce_delay_test.ok \
|
||||
sky130/25_verilog_multibank_test.ok \
|
||||
sky130/25_verilog_sram_test.ok \
|
||||
sky130/30_openram_back_end_library_test.ok \
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ Commercial tools (optional):
|
|||
* Michael Grimes
|
||||
* Jennifer Sowash
|
||||
* Jesse Cirimelli-Low
|
||||
<img align="right" height="100" src="../assets/images/logos/vlsida.png">https://www.youtube.com/watch?v=rd5j8mG24H4&t=0s
|
||||
<img align="right" height="100" src="../assets/images/logos/vlsida.png">
|
||||
* Many other past students:
|
||||
* Jeff Butera
|
||||
* Tom Golubev
|
||||
|
|
|
|||
|
|
@ -30,9 +30,19 @@ class sky130_capped_replica_bitcell_array(sky130_bitcell_base_array):
|
|||
self.add_comment("rows: {0} cols: {1}".format(rows, cols))
|
||||
self.add_comment("rbl: {0} left_rbl: {1} right_rbl: {2}".format(rbl, left_rbl, right_rbl))
|
||||
|
||||
# This is how many RBLs are in all the arrays
|
||||
self.rbl = rbl
|
||||
self.left_rbl = left_rbl
|
||||
self.right_rbl = right_rbl
|
||||
# This specifies which RBL to put on the left or right by port number
|
||||
# This could be an empty list
|
||||
if left_rbl is not None:
|
||||
self.left_rbl = left_rbl
|
||||
else:
|
||||
self.left_rbl = []
|
||||
# This could be an empty list
|
||||
if right_rbl is not None:
|
||||
self.right_rbl = right_rbl
|
||||
else:
|
||||
self.right_rbl = []
|
||||
|
||||
self.create_netlist()
|
||||
if not OPTS.netlist_only:
|
||||
|
|
|
|||
Loading…
Reference in New Issue