From 8e890c2014476ad26bf97d2605841888051383a7 Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 11 Aug 2020 15:00:29 -0700 Subject: [PATCH] Replica bitcell with all the fixings --- compiler/modules/bank.py | 2 +- compiler/modules/local_bitcell_array.py | 55 +++- compiler/modules/replica_bitcell_array.py | 273 +++++++++--------- compiler/modules/replica_column.py | 2 - compiler/modules/wordline_buffer_array.py | 5 +- compiler/tests/05_local_bitcell_array_test.py | 8 +- 6 files changed, 197 insertions(+), 148 deletions(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index b0707edb..4d0b09fb 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -392,7 +392,7 @@ class bank(design.design): def create_bitcell_array(self): """ Creating Bitcell Array """ - + import pdb; pdb.set_trace() self.bitcell_array_inst=self.add_inst(name="replica_bitcell_array", mod=self.bitcell_array) diff --git a/compiler/modules/local_bitcell_array.py b/compiler/modules/local_bitcell_array.py index ba19ad5e..da203de7 100644 --- a/compiler/modules/local_bitcell_array.py +++ b/compiler/modules/local_bitcell_array.py @@ -5,22 +5,22 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -import design +import bitcell_base_array from globals import OPTS from sram_factory import factory +from vector import vector import debug - -class local_bitcell_array(design.design): +class local_bitcell_array(bitcell_base_array.bitcell_base_array): """ A local bitcell array is a bitcell array with a wordline driver. This can either be a single aray on its own if there is no hierarchical WL or it can be combined into a larger array with hierarchical WL. """ - def __init__(self, rows, cols, ports, left_rbl=0, right_rbl=0, name=""): - design.design.__init__(self, name) - debug.info(2, "create sram of size {0} with {1} words".format(self.word_size, - self.num_words)) + def __init__(self, rows, cols, ports, left_rbl=0, right_rbl=0, add_replica=True, name=""): + super().__init__(name, rows, cols, 0) + debug.info(2, "create local array of size {} rows x {} cols words".format(rows, + cols + left_rbl + right_rbl)) self.rows = rows self.cols = cols @@ -66,16 +66,47 @@ class local_bitcell_array(design.design): self.add_mod(self.bitcell_array) self.wl_array = factory.create(module_type="wordline_buffer_array", - rows=self.rows, + rows=self.rows + len(self.all_ports), cols=self.cols) self.add_mod(self.wl_array) + def add_pins(self): + + self.bitline_names = self.bitcell_array.get_all_bitline_names() + self.add_pin_list(self.bitline_names, "INOUT") + self.wordline_names = self.bitcell_array.get_all_wordline_names() + self.add_pin_list(self.wordline_names, "INPUT") + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") + def create_instances(self): """ Create the module instances used in this design """ - self.wl_inst = self.add_inst(mod=self.wl_array) - self.connect_inst(self.pins) + internal_wl_names = [x + "i" for x in self.wordline_names] + self.wl_inst = self.add_inst(name="wl_driver", + mod=self.wl_array) + self.connect_inst(self.wordline_names + internal_wl_names + ["vdd", "gnd"]) - self.array_inst = self.add_inst(mod=self.bitcell_array, + self.array_inst = self.add_inst(name="array", + mod=self.bitcell_array, offset=self.wl_inst.lr()) - self.connect_inst(self.pins) + self.connect_inst(self.bitline_names + internal_wl_names + ["vdd", "gnd"]) + + def place(self): + """ Place the bitcelll array to the right of the wl driver. """ + + self.wl_inst.place(vector(0, 0)) + self.array_inst.place(self.wl_inst.lr()) + + self.height = self.bitcell_array.height + self.width = self.array_inst.rx() + + def add_layout_pins(self): + + for (x, y) in zip(self.bitline_names, self.bitcell_array.get_inouts()): + self.copy_layout_pin(self.array_inst, y, x) + + for (x, y) in zip(self.wordline_names, self.wl_array.get_inputs()): + self.copy_layout_pin(self.wl_inst, y, x) + + diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index d035f7b4..2511ea80 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -42,9 +42,9 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): self.add_left_rbl = 0 self.add_right_rbl = 0 - debug.check(left_rbl + right_rbl == len(self.all_ports), + debug.check(left_rbl + right_rbl <= len(self.all_ports), "Invalid number of RBLs for port configuration.") - debug.check(left_rbl + right_rbl == len(self.bitcell_ports), + debug.check(left_rbl + right_rbl <= len(self.bitcell_ports), "Bitcell ports must match total RBLs.") # Two dummy rows plus replica even if we don't add the column @@ -134,27 +134,26 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): end_caps_enabled = False # Dummy Row or Col Cap, depending on bitcell array properties - edge_row_module_type = ("col_cap_array" if end_caps_enabled else "dummy_array") - - self.edge_row = factory.create(module_type=edge_row_module_type, + col_cap_module_type = ("col_cap_array" if end_caps_enabled else "dummy_array") + self.col_cap = factory.create(module_type=col_cap_module_type, cols=self.column_size, rows=1, # dummy column + left replica column(s) column_offset=1 + self.add_left_rbl, mirror=0) - self.add_mod(self.edge_row) + self.add_mod(self.col_cap) # Dummy Col or Row Cap, depending on bitcell array properties - edge_col_module_type = ("row_cap_array" if end_caps_enabled else "dummy_array") + row_cap_module_type = ("row_cap_array" if end_caps_enabled else "dummy_array") - self.edge_col_left = factory.create(module_type=edge_col_module_type, + self.row_cap_left = factory.create(module_type=row_cap_module_type, cols=1, column_offset=0, rows=self.row_size + self.extra_rows, mirror=(self.left_rbl + 1) % 2) - self.add_mod(self.edge_col_left) + self.add_mod(self.row_cap_left) - self.edge_col_right = factory.create(module_type=edge_col_module_type, + self.row_cap_right = factory.create(module_type=row_cap_module_type, cols=1, # dummy column # + left replica column(s) @@ -163,100 +162,111 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): column_offset = 1 + self.add_left_rbl + self.column_size + self.add_right_rbl, rows=self.row_size + self.extra_rows, mirror=(self.left_rbl + 1) %2) - self.add_mod(self.edge_col_right) + self.add_mod(self.row_cap_right) def add_pins(self): - self.bitcell_array_wl_names = self.bitcell_array.get_all_wordline_names() - self.bitcell_array_bl_names = self.bitcell_array.get_all_bitline_names() + + self.add_bitline_pins() + self.add_wordline_pins() + + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") + + def add_bitline_pins(self): + + # All bitline names for all ports + self.bitline_names = [] + # Bitline names for each port + self.bitline_names_by_port = [[] for x in self.all_ports] + # Replica wordlines by port + self.replica_bitline_names = [[] for x in self.all_ports] + # Replica wordlines by port (bl only) + self.replica_bl_names = [[] for x in self.all_ports] + # Dummy wordlines by port + self.dummy_bitline_names = [] + + # Regular array bitline names + self.bitcell_array_bitline_names = self.bitcell_array.get_all_bitline_names() # These are the non-indexed names - self.dummy_cell_wl_names = ["dummy_" + x for x in self.cell.get_all_wl_names()] - self.dummy_cell_bl_names = ["dummy_" + x for x in self.cell.get_all_bitline_names()] - self.dummy_row_bl_names = self.bitcell_array_bl_names + dummy_bitline_names = ["dummy_" + x for x in self.cell.get_all_bitline_names()] + self.dummy_bitline_names.append([x+"_left" for x in dummy_bitline_names]) + self.dummy_bitline_names.append([x+"_right" for x in dummy_bitline_names]) - # A dictionary because some ports may have nothing - self.rbl_bl_names = {} - self.rbl_br_names = {} - self.rbl_wl_names = {} - - # Create the full WL names include dummy, replica, and regular bit cells - self.replica_col_wl_names = [] - self.replica_col_wl_names.extend(["{0}_bot".format(x) for x in self.dummy_cell_wl_names]) - # Left port WLs (one dummy for each port when we allow >1 port) - for port in range(self.add_left_rbl): - # Make names for all RBLs - wl_names=["rbl_{0}_{1}".format(self.cell.get_wl_name(x), port) for x in range(len(self.cell.get_all_wl_names()))] - # Keep track of the pin that is the RBL - self.rbl_wl_names[port]=wl_names[self.bitcell_ports[port]] - self.replica_col_wl_names.extend(wl_names) - # Regular WLs - self.replica_col_wl_names.extend(self.bitcell_array_wl_names) - # Right port WLs (one dummy for each port when we allow >1 port) - for port in range(self.add_left_rbl, self.add_left_rbl + self.add_right_rbl): - # Make names for all RBLs - wl_names=["rbl_{0}_{1}".format(self.cell.get_wl_name(x), port) for x in range(len(self.cell.get_all_wl_names()))] - # Keep track of the pin that is the RBL - self.rbl_wl_names[port]=wl_names[self.bitcell_ports[port]] - self.replica_col_wl_names.extend(wl_names) - self.replica_col_wl_names.extend(["{0}_top".format(x) for x in self.dummy_cell_wl_names]) - - # Create the full WL names include dummy, replica, and regular bit cells - # Left/right dummy columns are connected identically to the replica column - self.dummy_col_wl_names = [] - self.dummy_col_wl_names.extend(["{0}_bot".format(x) for x in self.dummy_cell_wl_names]) - # Left port WLs (one dummy for each port when we allow >1 port) - for port in range(self.left_rbl): - # Make names for all RBLs - wl_names=["rbl_{0}_{1}".format(self.cell.get_wl_name(x), port) for x in range(len(self.cell.get_all_wl_names()))] - # Keep track of the pin that is the RBL - self.rbl_wl_names[port]=wl_names[self.bitcell_ports[port]] - self.dummy_col_wl_names.extend(wl_names) - # Regular WLs - self.dummy_col_wl_names.extend(self.bitcell_array_wl_names) - # Right port WLs (one dummy for each port when we allow >1 port) - for port in range(self.left_rbl, self.left_rbl + self.right_rbl): - # Make names for all RBLs - wl_names=["rbl_{0}_{1}".format(self.cell.get_wl_name(x), port) for x in range(len(self.cell.get_all_wl_names()))] - # Keep track of the pin that is the RBL - self.rbl_wl_names[port]=wl_names[self.bitcell_ports[port]] - self.dummy_col_wl_names.extend(wl_names) - self.dummy_col_wl_names.extend(["{0}_top".format(x) for x in self.dummy_cell_wl_names]) - - # Per port bitline names - self.replica_bl_names = {} - self.replica_wl_names = {} # Array of all port bitline names for port in range(self.add_left_rbl + self.add_right_rbl): left_names=["rbl_{0}_{1}".format(self.cell.get_bl_name(x), port) for x in range(len(self.all_ports))] right_names=["rbl_{0}_{1}".format(self.cell.get_br_name(x), port) for x in range(len(self.all_ports))] # Keep track of the left pins that are the RBL - self.rbl_bl_names[port]=left_names[self.bitcell_ports[port]] - self.rbl_br_names[port]=right_names[self.bitcell_ports[port]] + self.replica_bl_names[port]=left_names[self.bitcell_ports[port]] # Interleave the left and right lists - bl_names = [x for t in zip(left_names, right_names) for x in t] - self.replica_bl_names[port] = bl_names + bitline_names = [x for t in zip(left_names, right_names) for x in t] + self.replica_bitline_names[port] = bitline_names + + # Dummy bitlines are not connected to anything + # br pins are not connected to anything + for port in range(self.add_left_rbl): + self.bitline_names.extend(self.replica_bitline_names[port]) + self.bitline_names.extend(self.bitcell_array_bitline_names) + # br pins are not connected to anything + for port in range(self.left_rbl, self.left_rbl + self.right_rbl): + self.bitline_names.extend(self.replica_bitline_names[port]) + + self.add_pin_list(self.bitline_names, "INOUT") + + def add_wordline_pins(self): + + # All wordline names for all ports + self.wordline_names = [] + # Wordline names for each port + self.wordline_names_by_port = [[] for x in self.all_ports] + # Replica wordlines by port + self.replica_wordline_names = [[] for x in self.all_ports] + # Dummy wordlines + self.dummy_wordline_names = {} + + # Regular array wordline names + self.bitcell_array_wordline_names = self.bitcell_array.get_all_wordline_names() + + # These are the non-indexed names + dummy_cell_wl_names = ["dummy_" + x for x in self.cell.get_all_wl_names()] + + # Create the full WL names include dummy, replica, and regular bit cells + self.wordline_names = [] + + self.dummy_wordline_names["bot"] = ["{0}_bot".format(x) for x in dummy_cell_wl_names] + self.wordline_names.extend(self.dummy_wordline_names["bot"]) + + # Left port WLs + for port in range(self.left_rbl): + # Make names for all RBLs + wl_names=["rbl_{0}_{1}".format(self.cell.get_wl_name(x), port) for x in range(len(self.cell.get_all_wl_names()))] + # Keep track of the pin that is the RBL + self.replica_wordline_names[port] = wl_names + self.wordline_names.extend(wl_names) + + # Regular WLs + self.wordline_names.extend(self.bitcell_array_wordline_names) + + # Right port WLs + for port in range(self.left_rbl, self.left_rbl + self.right_rbl): + # Make names for all RBLs + wl_names=["rbl_{0}_{1}".format(self.cell.get_wl_name(x), port) for x in range(len(self.cell.get_all_wl_names()))] + # Keep track of the pin that is the RBL + self.replica_wordline_names[port] = wl_names + self.wordline_names.extend(wl_names) + + + self.dummy_wordline_names["top"] = ["{0}_top".format(x) for x in dummy_cell_wl_names] + self.wordline_names.extend(self.dummy_wordline_names["top"]) # Array of all port wl names for port in range(self.left_rbl + self.right_rbl): wl_names = ["rbl_{0}_{1}".format(x, port) for x in self.cell.get_all_wl_names()] - self.replica_wl_names[port] = wl_names - - # External pins - self.add_pin_list(self.bitcell_array_bl_names, "INOUT") - # Need to sort by port order since dictionary values may not be in order - bl_names = [self.rbl_bl_names[x] for x in sorted(self.rbl_bl_names.keys())] - br_names = [self.rbl_br_names[x] for x in sorted(self.rbl_br_names.keys())] - for (bl_name, br_name) in zip(bl_names, br_names): - self.add_pin(bl_name, "OUTPUT") - self.add_pin(br_name, "OUTPUT") - self.add_pin_list(self.bitcell_array_wl_names, "INPUT") - # Need to sort by port order since dictionary values may not be in order - wl_names = [self.rbl_wl_names[x] for x in sorted(self.rbl_wl_names.keys())] - for pin_name in wl_names: - self.add_pin(pin_name, "INPUT") - self.add_pin("vdd", "POWER") - self.add_pin("gnd", "GROUND") + self.replica_wordline_names[port] = wl_names + self.add_pin_list(self.wordline_names, "INPUT") + def create_instances(self): """ Create the module instances used in this design """ @@ -268,14 +278,14 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): # Main array self.bitcell_array_inst=self.add_inst(name="bitcell_array", mod=self.bitcell_array) - self.connect_inst(self.bitcell_array_bl_names + self.bitcell_array_wl_names + supplies) + self.connect_inst(self.bitcell_array_bitline_names + self.bitcell_array_wordline_names + supplies) # Replica columns self.replica_col_inst = {} for port in range(self.add_left_rbl + self.add_right_rbl): self.replica_col_inst[port]=self.add_inst(name="replica_col_{}".format(port), mod=self.replica_columns[port]) - self.connect_inst(self.replica_bl_names[port] + self.replica_col_wl_names + supplies) + self.connect_inst(self.replica_bitline_names[port] + self.wordline_names + supplies) # Dummy rows under the bitcell array (connected with with the replica cell wl) self.dummy_row_replica_inst = {} @@ -283,23 +293,27 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): for port in range(self.left_rbl + self.right_rbl): self.dummy_row_replica_inst[port]=self.add_inst(name="dummy_row_{}".format(port), mod=self.dummy_row) - self.connect_inst(self.dummy_row_bl_names + self.replica_wl_names[port] + supplies) + self.connect_inst(self.bitcell_array_bitline_names + self.replica_wordline_names[port] + supplies) # Top/bottom dummy rows or col caps self.dummy_row_bot_inst=self.add_inst(name="dummy_row_bot", - mod=self.edge_row) - self.connect_inst(self.dummy_row_bl_names + [x + "_bot" for x in self.dummy_cell_wl_names] + supplies) + mod=self.col_cap) + self.connect_inst(self.bitcell_array_bitline_names + + self.dummy_wordline_names["bot"] + + supplies) self.dummy_row_top_inst=self.add_inst(name="dummy_row_top", - mod=self.edge_row) - self.connect_inst(self.dummy_row_bl_names + [x + "_top" for x in self.dummy_cell_wl_names] + supplies) + mod=self.col_cap) + self.connect_inst(self.bitcell_array_bitline_names + + self.dummy_wordline_names["top"] + + supplies) # Left/right Dummy columns self.dummy_col_left_inst=self.add_inst(name="dummy_col_left", - mod=self.edge_col_left) - self.connect_inst([x + "_left" for x in self.dummy_cell_bl_names] + self.dummy_col_wl_names + supplies) + mod=self.row_cap_left) + self.connect_inst(self.dummy_bitline_names[0] + self.wordline_names + supplies) self.dummy_col_right_inst=self.add_inst(name="dummy_col_right", - mod=self.edge_col_right) - self.connect_inst([x + "_right" for x in self.dummy_cell_bl_names] + self.dummy_col_wl_names + supplies) + mod=self.row_cap_right) + self.connect_inst(self.dummy_bitline_names[-1] + self.wordline_names + supplies) def create_layout(self): @@ -372,19 +386,20 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): def add_layout_pins(self): """ Add the layout pins """ + # All wordlines # Main array wl and bl/br pin_names = self.bitcell_array.get_pin_names() for pin_name in pin_names: - for wl in self.bitcell_array_wl_names: + for wl in self.bitcell_array_wordline_names: if wl in pin_name: pin_list = self.bitcell_array_inst.get_pins(pin_name) for pin in pin_list: self.add_layout_pin(text=pin_name, - layer=pin.layer, + layer=pin.layer, offset=pin.ll().scale(0, 1), width=self.width, height=pin.height()) - for bitline in self.bitcell_array_bl_names: + for bitline in self.bitcell_array_bitline_names: if bitline in pin_name: pin_list = self.bitcell_array_inst.get_pins(pin_name) for pin in pin_list: @@ -394,32 +409,35 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): width=pin.width(), height=self.height) - # Replica wordlines - for port in range(self.add_left_rbl + self.add_right_rbl): - inst = self.replica_col_inst[port] - for (pin_name, wl_name) in zip(self.cell.get_all_wl_names(), self.replica_wl_names[port]): - # +1 for dummy row - pin_bit = port + 1 - # +row_size if above the array - if port>=self.add_left_rbl: - pin_bit += self.row_size + # Dummy wordlines + for (name, inst) in [("bot", self.dummy_row_bot_inst), ("top", self.dummy_row_top_inst)]: + for (pin_name, wl_name) in zip(self.cell.get_all_wl_names(), self.dummy_wordline_names[name]): + # It's always a single row + pin = inst.get_pin(pin_name + "_0") + self.add_layout_pin(text=wl_name, + layer=pin.layer, + offset=pin.ll().scale(0, 1), + width=self.width, + height=pin.height()) + + # Replica wordlines (go by the row instead of replica column because we may have to add a pin + # even though the column is in another local bitcell array) + for (port, inst) in list(self.dummy_row_replica_inst.items()): + for (pin_name, wl_name) in zip(self.cell.get_all_wl_names(), self.replica_wordline_names[port]): + pin = inst.get_pin(pin_name + "_0") + self.add_layout_pin(text=wl_name, + layer=pin.layer, + offset=pin.ll().scale(0, 1), + width=self.width, + height=pin.height()) - pin_name += "_{}".format(pin_bit) - pin = inst.get_pin(pin_name) - if wl_name in self.rbl_wl_names.values(): - self.add_layout_pin(text=wl_name, - layer=pin.layer, - offset=pin.ll().scale(0, 1), - width=self.width, - height=pin.height()) - # Replica bitlines for port in range(self.add_left_rbl + self.add_right_rbl): inst = self.replica_col_inst[port] - for (pin_name, bl_name) in zip(self.cell.get_all_bitline_names(), self.replica_bl_names[port]): + for (pin_name, bl_name) in zip(self.cell.get_all_bitline_names(), self.replica_bitline_names[port]): pin = inst.get_pin(pin_name) - if bl_name in self.rbl_bl_names or bl_name in self.rbl_br_names: + if bl_name in self.replica_bl_names: name = bl_name else: name = "rbl_{0}_{1}".format(pin_name, port) @@ -441,22 +459,17 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): loc=pin.center(), directions=("V", "V"), start_layer=pin.layer) - + for inst in list(self.replica_col_inst.values()): self.copy_layout_pin(inst, pin_name) - self.copy_layout_pin(inst, pin_name) def get_rbl_wl_name(self, port): """ Return the WL for the given RBL port """ - return self.rbl_wl_names[port] + return self.replica_wordline_names[port] def get_rbl_bl_name(self, port): """ Return the BL for the given RBL port """ - return self.rbl_bl_names[port] - - def get_rbl_br_name(self, port): - """ Return the BR for the given RBL port """ - return self.rbl_br_names[port] + return self.replica_bl_names[port] def analytical_power(self, corner, load): """Power of Bitcell array and bitline in nW.""" diff --git a/compiler/modules/replica_column.py b/compiler/modules/replica_column.py index c75bc9ee..eb3116d3 100644 --- a/compiler/modules/replica_column.py +++ b/compiler/modules/replica_column.py @@ -188,8 +188,6 @@ class replica_column(design.design): for pin_name in ["vdd", "gnd"]: if inst in [self.cell_inst[0], self.cell_inst[self.total_size - 1]]: self.copy_power_pins(inst, pin_name) - else: - self.copy_layout_pin(inst, pin_name) def get_bitcell_pins(self, row, col): """ Creates a list of connections in the bitcell, diff --git a/compiler/modules/wordline_buffer_array.py b/compiler/modules/wordline_buffer_array.py index be0fe1f7..7a1bf8d1 100644 --- a/compiler/modules/wordline_buffer_array.py +++ b/compiler/modules/wordline_buffer_array.py @@ -58,8 +58,11 @@ class wordline_buffer_array(design.design): self.add_pin("gnd", "GROUND") def add_modules(self): + b = factory.create(module_type="bitcell") + self.wl_driver = factory.create(module_type="inv_dec", - size=self.cols) + size=self.cols, + height=b.height) self.add_mod(self.wl_driver) def route_vdd_gnd(self): diff --git a/compiler/tests/05_local_bitcell_array_test.py b/compiler/tests/05_local_bitcell_array_test.py index 99227694..664d9ef8 100755 --- a/compiler/tests/05_local_bitcell_array_test.py +++ b/compiler/tests/05_local_bitcell_array_test.py @@ -22,10 +22,14 @@ class local_bitcell_array_test(openram_test): config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) globals.init_openram(config_file) - debug.info(2, "Testing 4x4 local bitcell array for 6t_cell") - a = factory.create(module_type="local_bitcell_array", cols=4, rows=4) + 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, ports=[0], add_replica=False) 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, left_rbl=1, rows=4, ports=[0]) + self.local_check(a) + globals.end_openram()