From fe0cfac6c822d0ffa01500036af40095369cba6d Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Wed, 7 Sep 2022 12:39:01 -0700 Subject: [PATCH 01/42] tests for new capped array module --- ...apped_bitcell_array_bothrbl_1rw_1r_test.py | 44 +++++++++++++++++++ ...apped_bitcell_array_leftrbl_1rw_1r_test.py | 43 ++++++++++++++++++ ..._capped_bitcell_array_norbl_1rw_1r_test.py | 42 ++++++++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 compiler/tests/14_capped_bitcell_array_bothrbl_1rw_1r_test.py create mode 100644 compiler/tests/14_capped_bitcell_array_leftrbl_1rw_1r_test.py create mode 100644 compiler/tests/14_capped_bitcell_array_norbl_1rw_1r_test.py diff --git a/compiler/tests/14_capped_bitcell_array_bothrbl_1rw_1r_test.py b/compiler/tests/14_capped_bitcell_array_bothrbl_1rw_1r_test.py new file mode 100644 index 00000000..29920124 --- /dev/null +++ b/compiler/tests/14_capped_bitcell_array_bothrbl_1rw_1r_test.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2021 Regents of the University of California +# All rights reserved. +# +import unittest +from testutils import * +import sys, os + +import globals +from globals import OPTS +from sram_factory import factory +import debug + + +class capped_bitcell_array_1rw_1r_test(openram_test): + + def runTest(self): + config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) + globals.init_openram(config_file) + + OPTS.num_rw_ports = 1 + OPTS.num_r_ports = 1 + OPTS.num_w_ports = 0 + globals.setup_bitcell() + + debug.info(2, "Testing 4x4 array left and right replica for dp cell") + a = factory.create(module_type="capped_bitcell_array", + cols=4, + rows=4, + rbl=[1, 1], + left_rbl=[0], + right_rbl=[1]) + self.local_check(a) + + globals.end_openram() + +# run the test from the command line +if __name__ == "__main__": + (OPTS, args) = globals.parse_args() + del sys.argv[1:] + header(__file__, OPTS.tech_name) + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/14_capped_bitcell_array_leftrbl_1rw_1r_test.py b/compiler/tests/14_capped_bitcell_array_leftrbl_1rw_1r_test.py new file mode 100644 index 00000000..3d414a33 --- /dev/null +++ b/compiler/tests/14_capped_bitcell_array_leftrbl_1rw_1r_test.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2021 Regents of the University of California +# All rights reserved. +# +import unittest +from testutils import * +import sys, os + +import globals +from globals import OPTS +from sram_factory import factory +import debug + + +class capped_bitcell_array_1rw_1r_test(openram_test): + + def runTest(self): + config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) + globals.init_openram(config_file) + + OPTS.num_rw_ports = 1 + OPTS.num_r_ports = 1 + OPTS.num_w_ports = 0 + globals.setup_bitcell() + + debug.info(2, "Testing 4x4 left replica array for dp cell") + a = factory.create(module_type="capped_bitcell_array", + cols=4, + rows=4, + rbl=[1, 1], + left_rbl=[0]) + self.local_check(a) + + globals.end_openram() + +# run the test from the command line +if __name__ == "__main__": + (OPTS, args) = globals.parse_args() + del sys.argv[1:] + header(__file__, OPTS.tech_name) + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/14_capped_bitcell_array_norbl_1rw_1r_test.py b/compiler/tests/14_capped_bitcell_array_norbl_1rw_1r_test.py new file mode 100644 index 00000000..7c4fd9bb --- /dev/null +++ b/compiler/tests/14_capped_bitcell_array_norbl_1rw_1r_test.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2021 Regents of the University of California +# All rights reserved. +# +import unittest +from testutils import * +import sys, os + +import globals +from globals import OPTS +from sram_factory import factory +import debug + + +class capped_bitcell_array_1rw_1r_test(openram_test): + + def runTest(self): + config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) + globals.init_openram(config_file) + + OPTS.num_rw_ports = 1 + OPTS.num_r_ports = 1 + OPTS.num_w_ports = 0 + globals.setup_bitcell() + + debug.info(2, "Testing 4x4 non-replica array for dp cell") + a = factory.create(module_type="capped_bitcell_array", + cols=4, + rows=4, + rbl=[1, 1]) + self.local_check(a) + + globals.end_openram() + +# run the test from the command line +if __name__ == "__main__": + (OPTS, args) = globals.parse_args() + del sys.argv[1:] + header(__file__, OPTS.tech_name) + unittest.main(testRunner=debugTestRunner()) From 3ef52789bea987aada977877011cb867c9da1d90 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Wed, 7 Sep 2022 12:39:35 -0700 Subject: [PATCH 02/42] first pass splitting replica array into capped and replica array modules --- compiler/modules/capped_bitcell_array.py | 539 ++++++++++++++++++++++ compiler/modules/replica_bitcell_array.py | 323 +------------ 2 files changed, 546 insertions(+), 316 deletions(-) create mode 100644 compiler/modules/capped_bitcell_array.py diff --git a/compiler/modules/capped_bitcell_array.py b/compiler/modules/capped_bitcell_array.py new file mode 100644 index 00000000..7891c91b --- /dev/null +++ b/compiler/modules/capped_bitcell_array.py @@ -0,0 +1,539 @@ +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2021 Regents of the University of California +# All rights reserved. +# + +import debug +from base import vector +from base import contact +from .bitcell_base_array import bitcell_base_array +from tech import drc, spice +from tech import cell_properties as props +from globals import OPTS +from sram_factory import factory + + +class capped_bitcell_array(bitcell_base_array): + """ + Creates a replica bitcell array then adds the row and column caps to all + sides of a bitcell array. + """ + def __init__(self, rows, cols, rbl=None, left_rbl=None, right_rbl=None, name=""): + super().__init__(name, rows, cols, column_offset=0) + debug.info(1, "Creating {0} {1} x {2} rbls: {3} left_rbl: {4} right_rbl: {5}".format(self.name, + rows, + cols, + rbl, + left_rbl, + right_rbl)) + 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)) + + self.column_size = cols + self.row_size = rows + # This is how many RBLs are in all the arrays + if rbl: + self.rbl = rbl + else: + self.rbl=[1, 1 if len(self.all_ports)>1 else 0] + # This specifies which RBL to put on the left or right + # by port number + # This could be an empty list + if left_rbl != None: + self.left_rbl = left_rbl + else: + self.left_rbl = [0] + # This could be an empty list + if right_rbl != None: + self.right_rbl = right_rbl + else: + self.right_rbl=[1] if len(self.all_ports) > 1 else [] + self.rbls = self.left_rbl + self.right_rbl + + # Two dummy rows plus replica even if we don't add the column + self.extra_rows = sum(self.rbl) + # If we aren't using row/col caps, then we need to use the bitcell + if not self.cell.end_caps: + self.extra_rows += 2 + + self.create_netlist() + if not OPTS.netlist_only: + self.create_layout() + + def create_netlist(self): + """ Create and connect the netlist """ + self.add_modules() + self.add_pins() + 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) + """ + + self.replica_bitcell_array = factory.create(module_type="replica_bitcell_array", + column_offset=1, + cols=self.column_size, + rows=self.row_size) + + # Dummy Row or Col Cap, depending on bitcell array properties + col_cap_module_type = ("col_cap_array" if self.cell.end_caps else "dummy_array") + + self.col_cap_top = factory.create(module_type=col_cap_module_type, + cols=self.column_size, + rows=1, + # dummy column + left replica column(s) + column_offset=1 + len(self.left_rbl), + mirror=0, + location="top") + + self.col_cap_bottom = factory.create(module_type=col_cap_module_type, + cols=self.column_size, + rows=1, + # dummy column + left replica column(s) + column_offset=1 + len(self.left_rbl), + mirror=0, + location="bottom") + + # Dummy Col or Row Cap, depending on bitcell array properties + row_cap_module_type = ("row_cap_array" if self.cell.end_caps else "dummy_array") + + 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.rbl[0] + 1) % 2) + + self.row_cap_right = factory.create(module_type=row_cap_module_type, + cols=1, + # dummy column + # + left replica column(s) + # + bitcell columns + # + 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) + + def add_pins(self): + + # Arrays are always: + # bitlines (column first then port order) + # word lines (row first then port order) + # dummy wordlines + # replica wordlines + # regular wordlines (bottom to top) + # # dummy bitlines + # replica bitlines (port order) + # regular bitlines (left to right port order) + # + # vdd + # gnd + + self.add_bitline_pins() + self.add_wordline_pins() + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") + + def add_bitline_pins(self): + self.all_bitline_names = self.replica_bitcell_array.all_bitline_names + + self.add_pin_list(self.all_bitline_names, "INOUT") + + def add_wordline_pins(self): + self.all_wordline_names = self.replica_bitcell_array.all_wordline_names + + self.capped_array_wordline_names = [] + self.capped_array_wordline_names.extend(["gnd"] * len(self.col_cap_top.get_wordline_names())) + self.capped_array_wordline_names.extend(self.all_wordline_names) + self.capped_array_wordline_names.extend(["gnd"] * len(self.col_cap_bottom.get_wordline_names())) + + self.add_pin_list(self.all_wordline_names, "INPUT") + + def create_instances(self): + """ Create the module instances used in this design """ + self.supplies = ["vdd", "gnd"] + + # Main array + self.replica_bitcell_array_inst=self.add_inst(name="replica_bitcell_array", + mod=self.replica_bitcell_array) + self.connect_inst(self.all_bitline_names + self.all_wordline_names + self.supplies) + + # Top/bottom dummy rows or col caps + self.dummy_row_insts = [] + self.dummy_row_insts.append(self.add_inst(name="dummy_row_bot", + mod=self.col_cap_bottom)) + self.connect_inst(self.all_bitline_names + ["gnd"] * len(self.col_cap_bottom.get_wordline_names()) + self.supplies) + self.dummy_row_insts.append(self.add_inst(name="dummy_row_top", + mod=self.col_cap_top)) + self.connect_inst(self.all_bitline_names + ["gnd"] * len(self.col_cap_top.get_wordline_names()) + self.supplies) + + # Left/right Dummy columns + self.dummy_col_insts = [] + self.dummy_col_insts.append(self.add_inst(name="dummy_col_left", + mod=self.row_cap_left)) + self.connect_inst(["dummy_left_" + bl for bl in self.row_cap_left.all_bitline_names] + self.capped_array_wordline_names + self.supplies) + self.dummy_col_insts.append(self.add_inst(name="dummy_col_right", + mod=self.row_cap_right)) + self.connect_inst(["dummy_right_" + bl for bl in self.row_cap_right.all_bitline_names] + self.capped_array_wordline_names + self.supplies) + + def create_layout(self): + + # This creates space for the unused wordline connections as well as the + # 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])) + self.unused_offset = vector(0.25, 0.25) + + # This is a bitcell x bitcell offset to scale + self.bitcell_offset = vector(self.cell.width, self.cell.height) + self.col_end_offset = vector(self.cell.width, self.cell.height) + self.row_end_offset = vector(self.cell.width, self.cell.height) + + # Everything is computed with the replica array + self.replica_bitcell_array_inst.place(offset=self.unused_offset) + + self.add_end_caps() + + # 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(1 + len(self.left_rbl), 1 + self.rbl[0]) + self.translate_all(array_offset.scale(-1, -1)) + + # Add extra width on the left and right for the unused WLs + + self.width = self.dummy_col_insts[1].rx() + self.unused_offset.x + self.height = self.dummy_row_insts[1].uy() + + self.copy_layout_pins() + + self.route_supplies() + + self.route_unused_wordlines() + + lower_left = self.find_lowest_coords() + upper_right = self.find_highest_coords() + self.width = upper_right.x - lower_left.x + self.height = upper_right.y - lower_left.y + self.translate_all(lower_left) + + self.add_boundary() + + self.DRC_LVS() + + def get_main_array_top(self): + return self.replica_bitcell_array_inst.get_main_array_top() + + def get_main_array_bottom(self): + return self.replica_bitcell_array_inst.get_main_array_bottom() + + def get_main_array_left(self): + return self.replica_bitcell_array_inst.get_main_array_left() + + def get_main_array_right(self): + return self.replica_bitcell_array_inst.get_main_array_right() + + def get_replica_top(self): + return self.replica_bitcell_array_inst.get_replica_top() + + def get_replica_bottom(self): + return self.replica_bitcell_array_inst.get_replica_bottom() + + def get_replica_left(self): + return self.replica_bitcell_array_inst.get_replica_left() + + def get_replica_right(self): + return self.replica_bitcell_array_inst.get_replica_right() + + def get_column_offsets(self): + return self.replica_bitcell_array_inst.get_column_offsets() + + def add_end_caps(self): + """ Add dummy cells or end caps around the array """ + + # Far top dummy row (first row above array is NOT flipped if even number of rows) + flip_dummy = (self.row_size + self.rbl[1]) % 2 + dummy_row_offset = self.bitcell_offset.scale(0, self.rbl[1] + flip_dummy) + self.bitcell_array_inst.ul() + self.dummy_row_insts[1].place(offset=dummy_row_offset, + mirror="MX" if flip_dummy else "R0") + + # Far bottom dummy row (first row below array IS flipped) + flip_dummy = (self.rbl[0] + 1) % 2 + dummy_row_offset = self.bitcell_offset.scale(0, -self.rbl[0] - 1 + flip_dummy) + self.unused_offset + self.dummy_row_insts[0].place(offset=dummy_row_offset, + mirror="MX" if flip_dummy else "R0") + # Far left dummy col + # Shifted down by the number of left RBLs even if we aren't adding replica column to this bitcell array + dummy_col_offset = self.bitcell_offset.scale(-len(self.left_rbl) - 1, -self.rbl[0] - 1) + self.unused_offset + self.dummy_col_insts[0].place(offset=dummy_col_offset) + + # Far right dummy col + # Shifted down by the number of left RBLs even if we aren't adding replica column to this bitcell array + dummy_col_offset = self.bitcell_offset.scale(len(self.right_rbl), -self.rbl[0] - 1) + self.bitcell_array_inst.lr() + self.dummy_col_insts[1].place(offset=dummy_col_offset) + + def copy_layout_pins(self): + for pin_name in self.replica_bitcell_array_inst.get_layout_pins(): + if pin_name in ["vdd", "gnd"]: + continue + self.copy_layout_pin(self.replica_bitcell_array_inst, pin_name) + + def route_supplies(self): + + if OPTS.bitcell == "pbitcell": + bitcell = factory.create(module_type="pbitcell") + else: + bitcell = getattr(props, "bitcell_{}port".format(OPTS.num_ports)) + + vdd_dir = bitcell.vdd_dir + gnd_dir = bitcell.gnd_dir + + # vdd/gnd are only connected in the perimeter cells + supply_insts = self.dummy_col_insts + self.dummy_row_insts + + # For the wordlines + top_bot_mult = 1 + left_right_mult = 1 + + # There are always vertical pins for the WLs on the left/right if we have unused wordlines + self.left_gnd_locs = self.route_side_pin("gnd", "left", left_right_mult) + self.right_gnd_locs = self.route_side_pin("gnd", "right", left_right_mult) + # This needs to be big enough so that they aren't in the same supply routing grid + left_right_mult = 4 + + if gnd_dir == "V": + self.top_gnd_locs = self.route_side_pin("gnd", "top", top_bot_mult) + self.bot_gnd_locs = self.route_side_pin("gnd", "bot", top_bot_mult) + # This needs to be big enough so that they aren't in the same supply routing grid + top_bot_mult = 4 + + if vdd_dir == "V": + self.top_vdd_locs = self.route_side_pin("vdd", "top", top_bot_mult) + self.bot_vdd_locs = self.route_side_pin("vdd", "bot", top_bot_mult) + elif vdd_dir == "H": + self.left_vdd_locs = self.route_side_pin("vdd", "left", left_right_mult) + self.right_vdd_locs = self.route_side_pin("vdd", "right", left_right_mult) + else: + debug.error("Invalid vdd direction {}".format(vdd_dir), -1) + + for inst in supply_insts: + for pin in inst.get_pins("vdd"): + if vdd_dir == "V": + self.connect_side_pin(pin, "top", self.top_vdd_locs[0].y) + self.connect_side_pin(pin, "bot", self.bot_vdd_locs[0].y) + elif vdd_dir == "H": + self.connect_side_pin(pin, "left", self.left_vdd_locs[0].x) + self.connect_side_pin(pin, "right", self.right_vdd_locs[0].x) + + for inst in supply_insts: + for pin in inst.get_pins("gnd"): + if gnd_dir == "V": + self.connect_side_pin(pin, "top", self.top_gnd_locs[0].y) + self.connect_side_pin(pin, "bot", self.bot_gnd_locs[0].y) + elif gnd_dir == "H": + self.connect_side_pin(pin, "left", self.left_gnd_locs[0].x) + self.connect_side_pin(pin, "right", self.right_gnd_locs[0].x) + + def route_unused_wordlines(self): + """ Connect the unused RBL and dummy wordlines to gnd """ + # This grounds all the dummy row word lines + for inst in self.dummy_row_insts: + for wl_name in self.col_cap_top.get_wordline_names(): + pin = inst.get_pin(wl_name) + self.connect_side_pin(pin, "left", self.left_gnd_locs[0].x) + self.connect_side_pin(pin, "right", self.right_gnd_locs[0].x) + + # Ground the unused replica wordlines + for (names, inst) in zip(self.replica_bitcell_array_inst.rbl_wordline_names, self.replica_bitcell_array_inst.dummy_row_replica_insts): + for (wl_name, pin_name) in zip(names, self.replica_bitcell_array_inst.dummy_row.get_wordline_names()): + if wl_name in self.replica_bitcell_array_inst.gnd_wordline_names: + pin = inst.get_pin(pin_name) + self.connect_side_pin(pin, "left", self.left_gnd_locs[0].x) + self.connect_side_pin(pin, "right", self.right_gnd_locs[0].x) + + def route_side_pin(self, name, side, offset_multiple=1): + """ + Routes a vertical or horizontal pin on the side of the bbox. + The multiple specifies how many track offsets to be away from the side assuming + (0,0) (self.width, self.height) + """ + if side in ["left", "right"]: + return self.route_vertical_side_pin(name, side, offset_multiple) + elif side in ["top", "bottom", "bot"]: + return self.route_horizontal_side_pin(name, side, offset_multiple) + else: + debug.error("Invalid side {}".format(side), -1) + + def route_vertical_side_pin(self, name, side, offset_multiple=1): + """ + Routes a vertical pin on the side of the bbox. + """ + if side == "left": + bot_loc = vector(-offset_multiple * self.vertical_pitch, 0) + top_loc = vector(-offset_multiple * self.vertical_pitch, self.height) + elif side == "right": + bot_loc = vector(self.width + offset_multiple * self.vertical_pitch, 0) + top_loc = vector(self.width + offset_multiple * self.vertical_pitch, self.height) + + layer = self.supply_stack[2] + top_via = contact(layer_stack=self.supply_stack, + directions=("H", "H")) + + +# self.add_layout_pin_rect_ends(text=name, +# layer=layer, +# start=bot_loc, +# end=top_loc) + self.add_layout_pin_segment_center(text=name, + layer=layer, + start=bot_loc, + end=top_loc, + width=top_via.second_layer_width) + + return (bot_loc, top_loc) + + def route_horizontal_side_pin(self, name, side, offset_multiple=1): + """ + Routes a horizontal pin on the side of the bbox. + """ + if side in ["bottom", "bot"]: + left_loc = vector(0, -offset_multiple * self.horizontal_pitch) + right_loc = vector(self.width, -offset_multiple * self.horizontal_pitch) + elif side == "top": + left_loc = vector(0, self.height + offset_multiple * self.horizontal_pitch) + right_loc = vector(self.width, self.height + offset_multiple * self.horizontal_pitch) + + layer = self.supply_stack[0] + side_via = contact(layer_stack=self.supply_stack, + directions=("V", "V")) + +# self.add_layout_pin_rect_ends(text=name, +# layer=layer, +# start=left_loc, +# end=right_loc) + self.add_layout_pin_segment_center(text=name, + layer=layer, + start=left_loc, + end=right_loc, + width=side_via.first_layer_height) + + return (left_loc, right_loc) + + def connect_side_pin(self, pin, side, offset): + """ + Used to connect horizontal layers of pins to the left/right straps + locs provides the offsets of the pin strip end points. + """ + if side in ["left", "right"]: + self.connect_vertical_side_pin(pin, side, offset) + elif side in ["top", "bottom", "bot"]: + self.connect_horizontal_side_pin(pin, side, offset) + else: + debug.error("Invalid side {}".format(side), -1) + + def connect_horizontal_side_pin(self, pin, side, yoffset): + """ + Used to connect vertical layers of pins to the top/bottom horizontal straps + """ + cell_loc = pin.center() + pin_loc = vector(cell_loc.x, yoffset) + + # Place the pins a track outside of the array + self.add_via_stack_center(offset=pin_loc, + from_layer=pin.layer, + to_layer=self.supply_stack[0], + directions=("V", "V")) + + # Add a path to connect to the array + self.add_path(pin.layer, [cell_loc, pin_loc]) + + + def connect_vertical_side_pin(self, pin, side, xoffset): + """ + Used to connect vertical layers of pins to the top/bottom vertical straps + """ + cell_loc = pin.center() + pin_loc = vector(xoffset, cell_loc.y) + + # Place the pins a track outside of the array + self.add_via_stack_center(offset=pin_loc, + from_layer=pin.layer, + to_layer=self.supply_stack[2], + directions=("H", "H")) + + # Add a path to connect to the array + self.add_path(pin.layer, [cell_loc, pin_loc]) + + def analytical_power(self, corner, load): + """Power of Bitcell array and bitline in nW.""" + # Dynamic Power from Bitline + bl_wire = self.gen_bl_wire() + cell_load = 2 * bl_wire.return_input_cap() + bl_swing = OPTS.rbl_delay_percentage + freq = spice["default_event_frequency"] + bitline_dynamic = self.calc_dynamic_power(corner, cell_load, freq, swing=bl_swing) + + # Calculate the bitcell power which currently only includes leakage + cell_power = self.cell.analytical_power(corner, load) + + # Leakage power grows with entire array and bitlines. + total_power = self.return_power(cell_power.dynamic + bitline_dynamic * self.column_size, + cell_power.leakage * self.column_size * self.row_size) + return total_power + + + def gen_bl_wire(self): + if OPTS.netlist_only: + height = 0 + else: + height = self.height + bl_pos = 0 + bl_wire = self.generate_rc_net(int(self.row_size - bl_pos), height, drc("minwidth_m1")) + bl_wire.wire_c =spice["min_tx_drain_c"] + bl_wire.wire_c # 1 access tx d/s per cell + return bl_wire + + def graph_exclude_bits(self, targ_row=None, targ_col=None): + """ + Excludes bits in column from being added to graph except target + """ + self.bitcell_array.graph_exclude_bits(targ_row, targ_col) + + def graph_exclude_replica_col_bits(self): + """ + Exclude all replica/dummy cells in the replica columns except the replica bit. + """ + + for port in self.left_rbl + self.right_rbl: + self.replica_columns[port].exclude_all_but_replica() + + def get_cell_name(self, inst_name, row, col): + """ + Gets the spice name of the target bitcell. + """ + return self.bitcell_array.get_cell_name(inst_name + "{}x".format(OPTS.hier_seperator) + self.bitcell_array_inst.name, row, col) + + def clear_exclude_bits(self): + """ + Clears the bit exclusions + """ + self.bitcell_array.init_graph_params() diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index f3725489..acb03f2a 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -16,15 +16,15 @@ from sram_factory import factory class replica_bitcell_array(bitcell_base_array): """ - Creates a bitcell arrow of cols x rows and then adds the replica + 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 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). + bitcell (BL/BR disconnected). """ def __init__(self, rows, cols, rbl=None, left_rbl=None, right_rbl=None, name=""): - super().__init__(name, rows, cols, column_offset=0) + super().__init__(name=name, rows=rows, cols=cols, column_offset=0) debug.info(1, "Creating {0} {1} x {2} rbls: {3} left_rbl: {4} right_rbl: {5}".format(self.name, rows, cols, @@ -37,47 +37,22 @@ 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 - if rbl: - self.rbl = rbl - else: - self.rbl=[1, 1 if len(self.all_ports)>1 else 0] + self.rbl = rbl # This specifies which RBL to put on the left or right # by port number # This could be an empty list - if left_rbl != None: - self.left_rbl = left_rbl - else: - self.left_rbl = [0] + self.left_rbl = left_rbl # This could be an empty list - if right_rbl != None: - self.right_rbl = right_rbl - else: - self.right_rbl=[1] if len(self.all_ports) > 1 else [] + self.right_rbl = right_rbl self.rbls = self.left_rbl + self.right_rbl - debug.check(sum(self.rbl) == len(self.all_ports), - "Invalid number of RBLs for port configuration.") debug.check(sum(self.rbl) >= len(self.left_rbl) + len(self.right_rbl), "Invalid number of RBLs for port configuration.") - # Two dummy rows plus replica even if we don't add the column - self.extra_rows = sum(self.rbl) - # Two dummy cols plus replica if we add the column - self.extra_cols = len(self.left_rbl) + len(self.right_rbl) - - # If we aren't using row/col caps, then we need to use the bitcell - if not self.cell.end_caps: - self.extra_rows += 2 - self.extra_cols += 2 - self.create_netlist() if not OPTS.netlist_only: self.create_layout() - # We don't offset this because we need to align - # the replica bitcell in the control logic - # self.offset_all_coordinates() - def create_netlist(self): """ Create and connect the netlist """ self.add_modules() @@ -109,7 +84,7 @@ class replica_bitcell_array(bitcell_base_array): """ # Bitcell array self.bitcell_array = factory.create(module_type="bitcell_array", - column_offset=1 + len(self.left_rbl), + column_offset=len(self.left_rbl), cols=self.column_size, rows=self.row_size) @@ -148,43 +123,6 @@ class replica_bitcell_array(bitcell_base_array): column_offset=1 + len(self.left_rbl), mirror=0) - # Dummy Row or Col Cap, depending on bitcell array properties - col_cap_module_type = ("col_cap_array" if self.cell.end_caps else "dummy_array") - self.col_cap_top = factory.create(module_type=col_cap_module_type, - cols=self.column_size, - rows=1, - # dummy column + left replica column(s) - column_offset=1 + len(self.left_rbl), - mirror=0, - location="top") - - self.col_cap_bottom = factory.create(module_type=col_cap_module_type, - cols=self.column_size, - rows=1, - # dummy column + left replica column(s) - column_offset=1 + len(self.left_rbl), - mirror=0, - location="bottom") - - # Dummy Col or Row Cap, depending on bitcell array properties - row_cap_module_type = ("row_cap_array" if self.cell.end_caps else "dummy_array") - - 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.rbl[0] + 1) % 2) - - self.row_cap_right = factory.create(module_type=row_cap_module_type, - cols=1, - # dummy column - # + left replica column(s) - # + bitcell columns - # + 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) - def add_pins(self): # Arrays are always: @@ -243,13 +181,11 @@ class replica_bitcell_array(bitcell_base_array): # All wordlines including dummy and RBL self.replica_array_wordline_names = [] - self.replica_array_wordline_names.extend(["gnd"] * len(self.col_cap_top.get_wordline_names())) for bit in range(self.rbl[0]): self.replica_array_wordline_names.extend([x if x not in self.gnd_wordline_names else "gnd" for x in self.rbl_wordline_names[bit]]) self.replica_array_wordline_names.extend(self.all_wordline_names) for bit in range(self.rbl[1]): self.replica_array_wordline_names.extend([x if x not in self.gnd_wordline_names else "gnd" for x in self.rbl_wordline_names[self.rbl[0] + bit]]) - self.replica_array_wordline_names.extend(["gnd"] * len(self.col_cap_top.get_wordline_names())) for port in range(self.rbl[0]): self.add_pin(self.rbl_wordline_names[port][port], "INPUT") @@ -261,9 +197,6 @@ class replica_bitcell_array(bitcell_base_array): """ Create the module instances used in this design """ self.supplies = ["vdd", "gnd"] - # Used for names/dimensions only - self.cell = factory.create(module_type=OPTS.bitcell) - # Main array self.bitcell_array_inst=self.add_inst(name="bitcell_array", mod=self.bitcell_array) @@ -287,24 +220,6 @@ class replica_bitcell_array(bitcell_base_array): mod=self.dummy_row)) self.connect_inst(self.all_bitline_names + [x if x not in self.gnd_wordline_names else "gnd" for x in self.rbl_wordline_names[port]] + self.supplies) - # Top/bottom dummy rows or col caps - self.dummy_row_insts = [] - self.dummy_row_insts.append(self.add_inst(name="dummy_row_bot", - mod=self.col_cap_bottom)) - self.connect_inst(self.all_bitline_names + ["gnd"] * len(self.col_cap_bottom.get_wordline_names()) + self.supplies) - self.dummy_row_insts.append(self.add_inst(name="dummy_row_top", - mod=self.col_cap_top)) - self.connect_inst(self.all_bitline_names + ["gnd"] * len(self.col_cap_top.get_wordline_names()) + self.supplies) - - # Left/right Dummy columns - self.dummy_col_insts = [] - self.dummy_col_insts.append(self.add_inst(name="dummy_col_left", - mod=self.row_cap_left)) - self.connect_inst(["dummy_left_" + bl for bl in self.row_cap_left.all_bitline_names] + self.replica_array_wordline_names + self.supplies) - self.dummy_col_insts.append(self.add_inst(name="dummy_col_right", - mod=self.row_cap_right)) - self.connect_inst(["dummy_right_" + bl for bl in self.row_cap_right.all_bitline_names] + self.replica_array_wordline_names + self.supplies) - def create_layout(self): # This creates space for the unused wordline connections as well as the @@ -323,25 +238,14 @@ class replica_bitcell_array(bitcell_base_array): self.add_replica_columns() - self.add_end_caps() - # 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(1 + len(self.left_rbl), 1 + self.rbl[0]) self.translate_all(array_offset.scale(-1, -1)) - # Add extra width on the left and right for the unused WLs - - self.width = self.dummy_col_insts[1].rx() + self.unused_offset.x - self.height = self.dummy_row_insts[1].uy() - self.add_layout_pins() - self.route_supplies() - - self.route_unused_wordlines() - lower_left = self.find_lowest_coords() upper_right = self.find_highest_coords() self.width = upper_right.x - lower_left.x @@ -416,30 +320,6 @@ class replica_bitcell_array(bitcell_base_array): self.dummy_row_replica_insts[self.rbl[0] + bit].place(offset=dummy_offset, mirror="MX" if (self.row_size + bit) % 2 else "R0") - def add_end_caps(self): - """ Add dummy cells or end caps around the array """ - - # Far top dummy row (first row above array is NOT flipped if even number of rows) - flip_dummy = (self.row_size + self.rbl[1]) % 2 - dummy_row_offset = self.bitcell_offset.scale(0, self.rbl[1] + flip_dummy) + self.bitcell_array_inst.ul() - self.dummy_row_insts[1].place(offset=dummy_row_offset, - mirror="MX" if flip_dummy else "R0") - - # Far bottom dummy row (first row below array IS flipped) - flip_dummy = (self.rbl[0] + 1) % 2 - dummy_row_offset = self.bitcell_offset.scale(0, -self.rbl[0] - 1 + flip_dummy) + self.unused_offset - self.dummy_row_insts[0].place(offset=dummy_row_offset, - mirror="MX" if flip_dummy else "R0") - # Far left dummy col - # Shifted down by the number of left RBLs even if we aren't adding replica column to this bitcell array - dummy_col_offset = self.bitcell_offset.scale(-len(self.left_rbl) - 1, -self.rbl[0] - 1) + self.unused_offset - self.dummy_col_insts[0].place(offset=dummy_col_offset) - - # Far right dummy col - # Shifted down by the number of left RBLs even if we aren't adding replica column to this bitcell array - dummy_col_offset = self.bitcell_offset.scale(len(self.right_rbl), -self.rbl[0] - 1) + self.bitcell_array_inst.lr() - self.dummy_col_insts[1].place(offset=dummy_col_offset) - def add_layout_pins(self): """ Add the layout pins """ @@ -488,195 +368,6 @@ class replica_bitcell_array(bitcell_base_array): width=pin.width(), height=self.height) - def route_supplies(self): - - if OPTS.bitcell == "pbitcell": - bitcell = factory.create(module_type="pbitcell") - else: - bitcell = getattr(props, "bitcell_{}port".format(OPTS.num_ports)) - - vdd_dir = bitcell.vdd_dir - gnd_dir = bitcell.gnd_dir - - # vdd/gnd are only connected in the perimeter cells - supply_insts = self.dummy_col_insts + self.dummy_row_insts - - # For the wordlines - top_bot_mult = 1 - left_right_mult = 1 - - # There are always vertical pins for the WLs on the left/right if we have unused wordlines - self.left_gnd_locs = self.route_side_pin("gnd", "left", left_right_mult) - self.right_gnd_locs = self.route_side_pin("gnd","right", left_right_mult) - # This needs to be big enough so that they aren't in the same supply routing grid - left_right_mult = 4 - - if gnd_dir == "V": - self.top_gnd_locs = self.route_side_pin("gnd", "top", top_bot_mult) - self.bot_gnd_locs = self.route_side_pin("gnd", "bot", top_bot_mult) - # This needs to be big enough so that they aren't in the same supply routing grid - top_bot_mult = 4 - - if vdd_dir == "V": - self.top_vdd_locs = self.route_side_pin("vdd", "top", top_bot_mult) - self.bot_vdd_locs = self.route_side_pin("vdd", "bot", top_bot_mult) - elif vdd_dir == "H": - self.left_vdd_locs = self.route_side_pin("vdd", "left", left_right_mult) - self.right_vdd_locs = self.route_side_pin("vdd", "right", left_right_mult) - else: - debug.error("Invalid vdd direction {}".format(vdd_dir), -1) - - - for inst in supply_insts: - for pin in inst.get_pins("vdd"): - if vdd_dir == "V": - self.connect_side_pin(pin, "top", self.top_vdd_locs[0].y) - self.connect_side_pin(pin, "bot", self.bot_vdd_locs[0].y) - elif vdd_dir == "H": - self.connect_side_pin(pin, "left", self.left_vdd_locs[0].x) - self.connect_side_pin(pin, "right", self.right_vdd_locs[0].x) - - - for inst in supply_insts: - for pin in inst.get_pins("gnd"): - if gnd_dir == "V": - self.connect_side_pin(pin, "top", self.top_gnd_locs[0].y) - self.connect_side_pin(pin, "bot", self.bot_gnd_locs[0].y) - elif gnd_dir == "H": - self.connect_side_pin(pin, "left", self.left_gnd_locs[0].x) - self.connect_side_pin(pin, "right", self.right_gnd_locs[0].x) - - - def route_unused_wordlines(self): - """ Connect the unused RBL and dummy wordlines to gnd """ - # This grounds all the dummy row word lines - for inst in self.dummy_row_insts: - for wl_name in self.col_cap_top.get_wordline_names(): - pin = inst.get_pin(wl_name) - self.connect_side_pin(pin, "left", self.left_gnd_locs[0].x) - self.connect_side_pin(pin, "right", self.right_gnd_locs[0].x) - - # Ground the unused replica wordlines - for (names, inst) in zip(self.rbl_wordline_names, self.dummy_row_replica_insts): - for (wl_name, pin_name) in zip(names, self.dummy_row.get_wordline_names()): - if wl_name in self.gnd_wordline_names: - pin = inst.get_pin(pin_name) - self.connect_side_pin(pin, "left", self.left_gnd_locs[0].x) - self.connect_side_pin(pin, "right", self.right_gnd_locs[0].x) - - def route_side_pin(self, name, side, offset_multiple=1): - """ - Routes a vertical or horizontal pin on the side of the bbox. - The multiple specifies how many track offsets to be away from the side assuming - (0,0) (self.width, self.height) - """ - if side in ["left", "right"]: - return self.route_vertical_side_pin(name, side, offset_multiple) - elif side in ["top", "bottom", "bot"]: - return self.route_horizontal_side_pin(name, side, offset_multiple) - else: - debug.error("Invalid side {}".format(side), -1) - - def route_vertical_side_pin(self, name, side, offset_multiple=1): - """ - Routes a vertical pin on the side of the bbox. - """ - if side == "left": - bot_loc = vector(-offset_multiple * self.vertical_pitch, 0) - top_loc = vector(-offset_multiple * self.vertical_pitch, self.height) - elif side == "right": - bot_loc = vector(self.width + offset_multiple * self.vertical_pitch, 0) - top_loc = vector(self.width + offset_multiple * self.vertical_pitch, self.height) - - layer = self.supply_stack[2] - top_via = contact(layer_stack=self.supply_stack, - directions=("H", "H")) - - -# self.add_layout_pin_rect_ends(text=name, -# layer=layer, -# start=bot_loc, -# end=top_loc) - self.add_layout_pin_segment_center(text=name, - layer=layer, - start=bot_loc, - end=top_loc, - width=top_via.second_layer_width) - - return (bot_loc, top_loc) - - def route_horizontal_side_pin(self, name, side, offset_multiple=1): - """ - Routes a horizontal pin on the side of the bbox. - """ - if side in ["bottom", "bot"]: - left_loc = vector(0, -offset_multiple * self.horizontal_pitch) - right_loc = vector(self.width, -offset_multiple * self.horizontal_pitch) - elif side == "top": - left_loc = vector(0, self.height + offset_multiple * self.horizontal_pitch) - right_loc = vector(self.width, self.height + offset_multiple * self.horizontal_pitch) - - layer = self.supply_stack[0] - side_via = contact(layer_stack=self.supply_stack, - directions=("V", "V")) - -# self.add_layout_pin_rect_ends(text=name, -# layer=layer, -# start=left_loc, -# end=right_loc) - self.add_layout_pin_segment_center(text=name, - layer=layer, - start=left_loc, - end=right_loc, - width=side_via.first_layer_height) - - return (left_loc, right_loc) - - def connect_side_pin(self, pin, side, offset): - """ - Used to connect horizontal layers of pins to the left/right straps - locs provides the offsets of the pin strip end points. - """ - if side in ["left", "right"]: - self.connect_vertical_side_pin(pin, side, offset) - elif side in ["top", "bottom", "bot"]: - self.connect_horizontal_side_pin(pin, side, offset) - else: - debug.error("Invalid side {}".format(side), -1) - - def connect_horizontal_side_pin(self, pin, side, yoffset): - """ - Used to connect vertical layers of pins to the top/bottom horizontal straps - """ - cell_loc = pin.center() - pin_loc = vector(cell_loc.x, yoffset) - - # Place the pins a track outside of the array - self.add_via_stack_center(offset=pin_loc, - from_layer=pin.layer, - to_layer=self.supply_stack[0], - directions=("V", "V")) - - # Add a path to connect to the array - self.add_path(pin.layer, [cell_loc, pin_loc]) - - - def connect_vertical_side_pin(self, pin, side, xoffset): - """ - Used to connect vertical layers of pins to the top/bottom vertical straps - """ - cell_loc = pin.center() - pin_loc = vector(xoffset, cell_loc.y) - - # Place the pins a track outside of the array - self.add_via_stack_center(offset=pin_loc, - from_layer=pin.layer, - to_layer=self.supply_stack[2], - directions=("H", "H")) - - # Add a path to connect to the array - self.add_path(pin.layer, [cell_loc, pin_loc]) - def analytical_power(self, corner, load): """Power of Bitcell array and bitline in nW.""" # Dynamic Power from Bitline From f1f18b3b54b91cead43e2ab439790f54e4698349 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Wed, 7 Sep 2022 19:32:25 -0700 Subject: [PATCH 03/42] replica code working but failing lvs --- compiler/modules/capped_bitcell_array.py | 8 +++++--- compiler/modules/replica_bitcell_array.py | 4 +++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/compiler/modules/capped_bitcell_array.py b/compiler/modules/capped_bitcell_array.py index 7891c91b..9313dd9f 100644 --- a/compiler/modules/capped_bitcell_array.py +++ b/compiler/modules/capped_bitcell_array.py @@ -92,9 +92,11 @@ class capped_bitcell_array(bitcell_base_array): """ self.replica_bitcell_array = factory.create(module_type="replica_bitcell_array", - column_offset=1, cols=self.column_size, - rows=self.row_size) + rows=self.row_size, + rbl=self.rbl, + left_rbl=self.left_rbl, + right_rbl=self.right_rbl) # Dummy Row or Col Cap, depending on bitcell array properties col_cap_module_type = ("col_cap_array" if self.cell.end_caps else "dummy_array") @@ -164,7 +166,7 @@ class capped_bitcell_array(bitcell_base_array): self.capped_array_wordline_names = [] self.capped_array_wordline_names.extend(["gnd"] * len(self.col_cap_top.get_wordline_names())) - self.capped_array_wordline_names.extend(self.all_wordline_names) + self.capped_array_wordline_names.extend(self.all_wordline_names) # TODO: I think I need rblwls here too self.capped_array_wordline_names.extend(["gnd"] * len(self.col_cap_bottom.get_wordline_names())) self.add_pin_list(self.all_wordline_names, "INPUT") diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index acb03f2a..c67544ee 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -84,7 +84,7 @@ class replica_bitcell_array(bitcell_base_array): """ # Bitcell array self.bitcell_array = factory.create(module_type="bitcell_array", - column_offset=len(self.left_rbl), + column_offset=1 + len(self.left_rbl), cols=self.column_size, rows=self.row_size) @@ -181,11 +181,13 @@ class replica_bitcell_array(bitcell_base_array): # All wordlines including dummy and RBL self.replica_array_wordline_names = [] + self.replica_array_wordline_names.extend(["gnd"] * len(self.all_ports)) for bit in range(self.rbl[0]): self.replica_array_wordline_names.extend([x if x not in self.gnd_wordline_names else "gnd" for x in self.rbl_wordline_names[bit]]) self.replica_array_wordline_names.extend(self.all_wordline_names) for bit in range(self.rbl[1]): self.replica_array_wordline_names.extend([x if x not in self.gnd_wordline_names else "gnd" for x in self.rbl_wordline_names[self.rbl[0] + bit]]) + self.replica_array_wordline_names.extend(["gnd"] * len(self.all_ports)) for port in range(self.rbl[0]): self.add_pin(self.rbl_wordline_names[port][port], "INPUT") From 8bc3903a049972929d31609050f0804cdc75dc91 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Mon, 26 Sep 2022 14:23:09 -0700 Subject: [PATCH 04/42] remove end caps from replica column (will not pass sky130 drc) --- compiler/modules/replica_column.py | 51 +++++-------------- .../tests/14_replica_column_1rw_1r_test.py | 8 +-- compiler/tests/14_replica_column_test.py | 2 +- 3 files changed, 17 insertions(+), 44 deletions(-) diff --git a/compiler/modules/replica_column.py b/compiler/modules/replica_column.py index 5f59c016..04072eab 100644 --- a/compiler/modules/replica_column.py +++ b/compiler/modules/replica_column.py @@ -26,11 +26,9 @@ class replica_column(bitcell_base_array): # Row size is the number of rows with word lines self.row_size = sum(rbl) + rows # Start of regular word line rows - self.row_start = rbl[0] + 1 + self.row_start = rbl[0] # End of regular word line rows self.row_end = self.row_start + rows - if not self.cell.end_caps: - self.row_size += 2 super().__init__(rows=self.row_size, cols=1, column_offset=column_offset, name=name) self.rows = rows @@ -38,15 +36,14 @@ class replica_column(bitcell_base_array): self.right_rbl = rbl[1] self.replica_bit = replica_bit - # Total size includes the replica rows and column cap rows - self.total_size = self.left_rbl + rows + self.right_rbl + 2 + # Total size includes the replica rows + self.total_size = self.left_rbl + rows + self.right_rbl self.column_offset = column_offset - debug.check(replica_bit != 0 and replica_bit != self.total_size - 1, - "Replica bit cannot be the dummy/cap row.") debug.check(replica_bit < self.row_start or replica_bit >= self.row_end, "Replica bit cannot be in the regular array.") + if layer_props.replica_column.even_rows: debug.check(rows % 2 == 0 and (self.left_rbl + 1) % 2 == 0, "sky130 currently requires rows to be even and to start with X mirroring" @@ -90,44 +87,28 @@ class replica_column(bitcell_base_array): self.dummy_cell = factory.create(module_type=OPTS.dummy_bitcell) - try: - edge_module_type = ("col_cap" if self.cell.end_caps else "dummy") - except AttributeError: - edge_module_type = "dummy" - self.edge_cell = factory.create(module_type=edge_module_type + "_" + OPTS.bitcell) - def create_instances(self): self.cell_inst = [] for row in range(self.total_size): - name="rbc_{0}".format(row) - real_row = row - if self.cell.end_caps: - real_row -= 1 + name = "rbc_{0}".format(row) # Regular array cells are replica cells # Replic bit specifies which other bit (in the full range (0,total_size) to make a replica cell. - if (row == 0 or row == self.total_size - 1): - self.cell_inst.append(self.add_inst(name=name, - mod=self.edge_cell)) - if self.cell.end_caps: - self.connect_inst(self.get_bitcell_pins_col_cap(real_row, 0)) - else: - self.connect_inst(self.get_bitcell_pins(real_row, 0)) - elif (row==self.replica_bit) or (row >= self.row_start and row < self.row_end): + # All other cells are dummies + if (row == self.replica_bit) or (row >= self.row_start and row < self.row_end): self.cell_inst.append(self.add_inst(name=name, mod=self.replica_cell)) - self.connect_inst(self.get_bitcell_pins(real_row, 0)) + self.connect_inst(self.get_bitcell_pins(row, 0)) else: - # Top/bottom cell are always dummy/cap cells. self.cell_inst.append(self.add_inst(name=name, mod=self.dummy_cell)) - self.connect_inst(self.get_bitcell_pins(real_row, 0)) + self.connect_inst(self.get_bitcell_pins(row, 0)) def place_instances(self): # Flip the mirrors if we have an odd number of replica+dummy rows at the bottom # so that we will start with mirroring rather than not mirroring - rbl_offset = (self.left_rbl + 1) %2 + rbl_offset = (self.left_rbl) % 2 # if our bitcells are mirrored on the y axis, check if we are in global # column that needs to be flipped. @@ -156,7 +137,6 @@ class replica_column(bitcell_base_array): mirror=dir_key) def add_layout_pins(self): - """ Add the layout pins """ for port in self.all_ports: bl_pin = self.cell_inst[0].get_pin(self.cell.get_bl_name(port)) self.add_layout_pin(text="bl_{0}_{1}".format(port, 0), @@ -171,17 +151,10 @@ class replica_column(bitcell_base_array): width=bl_pin.width(), height=self.height) - if self.cell.end_caps: - row_range_max = self.total_size - 1 - row_range_min = 1 - else: - row_range_max = self.total_size - row_range_min = 0 - for port in self.all_ports: - for row in range(row_range_min, row_range_max): + for row in range(self.total_size): wl_pin = self.cell_inst[row].get_pin(self.cell.get_wl_name(port)) - self.add_layout_pin(text="wl_{0}_{1}".format(port, row - row_range_min), + self.add_layout_pin(text="wl_{0}_{1}".format(port, row), layer=wl_pin.layer, offset=wl_pin.ll().scale(0, 1), width=self.width, diff --git a/compiler/tests/14_replica_column_1rw_1r_test.py b/compiler/tests/14_replica_column_1rw_1r_test.py index 6d67bef9..e5356d62 100755 --- a/compiler/tests/14_replica_column_1rw_1r_test.py +++ b/compiler/tests/14_replica_column_1rw_1r_test.py @@ -26,19 +26,19 @@ class replica_column_test(openram_test): globals.setup_bitcell() debug.info(2, "Testing one left replica column for dual port") - a = factory.create(module_type="replica_column", rows=4, rbl=[1, 0], replica_bit=1) + a = factory.create(module_type="replica_column", rows=4, rbl=[1, 0], replica_bit=0) self.local_check(a) debug.info(2, "Testing one right replica column for dual port") - a = factory.create(module_type="replica_column", rows=4, rbl=[0, 1], replica_bit=5) + a = factory.create(module_type="replica_column", rows=4, rbl=[0, 1], replica_bit=4) self.local_check(a) debug.info(2, "Testing two (left, right) replica columns for dual port") - a = factory.create(module_type="replica_column", rows=4, rbl=[1, 1], replica_bit=1) + a = factory.create(module_type="replica_column", rows=4, rbl=[1, 1], replica_bit=0) self.local_check(a) debug.info(2, "Testing two (left, right) replica columns for dual port") - a = factory.create(module_type="replica_column", rows=4, rbl=[1, 1], replica_bit=6) + a = factory.create(module_type="replica_column", rows=4, rbl=[1, 1], replica_bit=5) self.local_check(a) globals.end_openram() diff --git a/compiler/tests/14_replica_column_test.py b/compiler/tests/14_replica_column_test.py index 73825e39..07eeb16c 100755 --- a/compiler/tests/14_replica_column_test.py +++ b/compiler/tests/14_replica_column_test.py @@ -30,7 +30,7 @@ class replica_column_test(openram_test): a = factory.create(module_type="replica_column", rows=4 + num_spare_rows, rbl=[1, 0], - replica_bit=1, + replica_bit=0, column_offset=num_spare_cols) self.local_check(a) From cfd52a6065dbdd18d9780ce9228251570af6ec7d Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Mon, 26 Sep 2022 14:24:16 -0700 Subject: [PATCH 05/42] fix offsets so array ends up at 0,0 --- compiler/modules/replica_bitcell_array.py | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index c67544ee..ef8d3381 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -96,7 +96,7 @@ class replica_bitcell_array(bitcell_base_array): # 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 - replica_bit = self.rbl[0] - port + replica_bit = self.rbl[0] - port - 1 column_offset = self.rbl[0] elif port in self.right_rbl: @@ -104,7 +104,7 @@ class replica_bitcell_array(bitcell_base_array): # We will always have self.rbl[0] rows of replica wordlines below # the array. # These go from the bottom up - replica_bit = self.rbl[0] + self.row_size + port + replica_bit = self.rbl[0] + self.row_size + port - 1 column_offset = self.rbl[0] + self.column_size + 1 else: continue @@ -181,13 +181,11 @@ class replica_bitcell_array(bitcell_base_array): # All wordlines including dummy and RBL self.replica_array_wordline_names = [] - self.replica_array_wordline_names.extend(["gnd"] * len(self.all_ports)) for bit in range(self.rbl[0]): self.replica_array_wordline_names.extend([x if x not in self.gnd_wordline_names else "gnd" for x in self.rbl_wordline_names[bit]]) self.replica_array_wordline_names.extend(self.all_wordline_names) for bit in range(self.rbl[1]): self.replica_array_wordline_names.extend([x if x not in self.gnd_wordline_names else "gnd" for x in self.rbl_wordline_names[self.rbl[0] + bit]]) - self.replica_array_wordline_names.extend(["gnd"] * len(self.all_ports)) for port in range(self.rbl[0]): self.add_pin(self.rbl_wordline_names[port][port], "INPUT") @@ -228,7 +226,6 @@ class 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])) - self.unused_offset = vector(0.25, 0.25) # This is a bitcell x bitcell offset to scale self.bitcell_offset = vector(self.cell.width, self.cell.height) @@ -236,7 +233,7 @@ class replica_bitcell_array(bitcell_base_array): self.row_end_offset = vector(self.cell.width, self.cell.height) # Everything is computed with the main array - self.bitcell_array_inst.place(offset=self.unused_offset) + self.bitcell_array_inst.place(offset=0) self.add_replica_columns() @@ -302,18 +299,18 @@ class replica_bitcell_array(bitcell_base_array): # Grow from left to right, toward the array for bit, port in enumerate(self.left_rbl): - offset = self.bitcell_offset.scale(-len(self.left_rbl) + bit, -self.rbl[0] - 1) + self.unused_offset + offset = self.bitcell_offset.scale(-len(self.left_rbl) + bit, -self.rbl[0]) self.replica_col_insts[bit].place(offset) # Grow to the right of the bitcell array, array outward for bit, port in enumerate(self.right_rbl): - offset = self.bitcell_array_inst.lr() + self.bitcell_offset.scale(bit, -self.rbl[0] - 1) + offset = self.bitcell_array_inst.lr() + self.bitcell_offset.scale(bit, -self.rbl[0]) self.replica_col_insts[self.rbl[0] + bit].place(offset) # Replica dummy rows # Add the dummy rows even if we aren't adding the replica column to this bitcell array # These grow up, toward the array for bit in range(self.rbl[0]): - dummy_offset = self.bitcell_offset.scale(0, -self.rbl[0] + bit + (-self.rbl[0] + bit) % 2) + self.unused_offset + dummy_offset = self.bitcell_offset.scale(0, -self.rbl[0] + bit + (-self.rbl[0] + bit) % 2) self.dummy_row_replica_insts[bit].place(offset=dummy_offset, mirror="MX" if (-self.rbl[0] + bit) % 2 else "R0") # These grow up, away from the array @@ -332,7 +329,7 @@ class replica_bitcell_array(bitcell_base_array): for pin in pin_list: self.add_layout_pin(text=pin_name, layer=pin.layer, - offset=pin.ll().scale(0, 1), + offset=pin.ll(), width=self.width, height=pin.height()) @@ -345,7 +342,7 @@ class replica_bitcell_array(bitcell_base_array): pin = inst.get_pin(pin_name) self.add_layout_pin(text=wl_name, layer=pin.layer, - offset=pin.ll().scale(0, 1), + offset=pin.ll(), width=self.width, height=pin.height()) @@ -354,7 +351,7 @@ class replica_bitcell_array(bitcell_base_array): for pin in pin_list: self.add_layout_pin(text=pin_name, layer=pin.layer, - offset=pin.ll().scale(1, 0), + offset=pin.ll(), width=pin.width(), height=self.height) @@ -366,7 +363,7 @@ class replica_bitcell_array(bitcell_base_array): pin = inst.get_pin(pin_name) self.add_layout_pin(text=bl_name, layer=pin.layer, - offset=pin.ll().scale(1, 0), + offset=pin.ll(), width=pin.width(), height=self.height) From a1ca7c312dbccd6c4d30c9d357ac01f85abd19c5 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Tue, 11 Oct 2022 11:43:26 -0700 Subject: [PATCH 06/42] remove grounded WLs from replica array --- compiler/modules/replica_bitcell_array.py | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index ef8d3381..0f188533 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -165,14 +165,9 @@ class replica_bitcell_array(bitcell_base_array): def add_wordline_pins(self): - # Wordlines to ground - self.gnd_wordline_names = [] - for port in self.all_ports: for bit in self.all_ports: self.rbl_wordline_names[port].append("rbl_wl_{0}_{1}".format(port, bit)) - if bit != port: - self.gnd_wordline_names.append("rbl_wl_{0}_{1}".format(port, bit)) self.all_rbl_wordline_names = [x for sl in self.rbl_wordline_names for x in sl] @@ -182,10 +177,10 @@ class replica_bitcell_array(bitcell_base_array): # All wordlines including dummy and RBL self.replica_array_wordline_names = [] for bit in range(self.rbl[0]): - self.replica_array_wordline_names.extend([x if x not in self.gnd_wordline_names else "gnd" for x in self.rbl_wordline_names[bit]]) + self.replica_array_wordline_names.extend([x for x in self.rbl_wordline_names[bit]]) self.replica_array_wordline_names.extend(self.all_wordline_names) for bit in range(self.rbl[1]): - self.replica_array_wordline_names.extend([x if x not in self.gnd_wordline_names else "gnd" for x in self.rbl_wordline_names[self.rbl[0] + bit]]) + self.replica_array_wordline_names.extend([x for x in self.rbl_wordline_names[self.rbl[0] + bit]]) for port in range(self.rbl[0]): self.add_pin(self.rbl_wordline_names[port][port], "INPUT") @@ -218,7 +213,7 @@ class replica_bitcell_array(bitcell_base_array): for port in self.all_ports: 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 + [x if x not in self.gnd_wordline_names else "gnd" for x in self.rbl_wordline_names[port]] + self.supplies) + self.connect_inst(self.all_bitline_names + [x for x in self.rbl_wordline_names[port]] + self.supplies) def create_layout(self): @@ -337,8 +332,6 @@ class replica_bitcell_array(bitcell_base_array): # even though the column is in another local bitcell array) for (names, inst) in zip(self.rbl_wordline_names, self.dummy_row_replica_insts): for (wl_name, pin_name) in zip(names, self.dummy_row.get_wordline_names()): - if wl_name in self.gnd_wordline_names: - continue pin = inst.get_pin(pin_name) self.add_layout_pin(text=wl_name, layer=pin.layer, From f9419e8ff796d70c888237c41e43aa87701f4aea Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Mon, 17 Oct 2022 20:51:42 -0700 Subject: [PATCH 07/42] fix self.rbls and fix handling of rbl WLs (kinda) --- compiler/modules/capped_bitcell_array.py | 6 +++--- compiler/modules/replica_bitcell_array.py | 14 ++++++++++++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/compiler/modules/capped_bitcell_array.py b/compiler/modules/capped_bitcell_array.py index 9313dd9f..666ffb70 100644 --- a/compiler/modules/capped_bitcell_array.py +++ b/compiler/modules/capped_bitcell_array.py @@ -40,12 +40,12 @@ class capped_bitcell_array(bitcell_base_array): # This specifies which RBL to put on the left or right # by port number # This could be an empty list - if left_rbl != None: + if left_rbl is not None: self.left_rbl = left_rbl else: self.left_rbl = [0] # This could be an empty list - if right_rbl != None: + if right_rbl is not None: self.right_rbl = right_rbl else: self.right_rbl=[1] if len(self.all_ports) > 1 else [] @@ -166,7 +166,7 @@ class capped_bitcell_array(bitcell_base_array): self.capped_array_wordline_names = [] self.capped_array_wordline_names.extend(["gnd"] * len(self.col_cap_top.get_wordline_names())) - self.capped_array_wordline_names.extend(self.all_wordline_names) # TODO: I think I need rblwls here too + self.capped_array_wordline_names.extend(self.replica_array_wordline_names) self.capped_array_wordline_names.extend(["gnd"] * len(self.col_cap_bottom.get_wordline_names())) self.add_pin_list(self.all_wordline_names, "INPUT") diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 0f188533..f27dcb95 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -41,9 +41,15 @@ class replica_bitcell_array(bitcell_base_array): # This specifies which RBL to put on the left or right # by port number # This could be an empty list - self.left_rbl = left_rbl + if left_rbl is not None: + self.left_rbl = left_rbl + else: + self.left_rbl = [] # This could be an empty list - self.right_rbl = right_rbl + if right_rbl is not None: + self.right_rbl = right_rbl + else: + self.right_rbl=[] self.rbls = self.left_rbl + self.right_rbl debug.check(sum(self.rbl) >= len(self.left_rbl) + len(self.right_rbl), @@ -164,10 +170,14 @@ class replica_bitcell_array(bitcell_base_array): self.add_pin_list(self.rbl_bitline_names[port], "INOUT") def add_wordline_pins(self): + # Wordlines to be grounded by capped_bitcell_array + self.gnd_wordline_names = [] for port in self.all_ports: for bit in self.all_ports: self.rbl_wordline_names[port].append("rbl_wl_{0}_{1}".format(port, bit)) + if bit != port: + self.gnd_wordline_names.append("rbl_wl_{0}_{1}".format(port, bit)) self.all_rbl_wordline_names = [x for sl in self.rbl_wordline_names for x in sl] From 55d89fbae8af531323879bf98841921735a14e53 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Wed, 19 Oct 2022 17:13:54 -0700 Subject: [PATCH 08/42] copy supply pins to top level in replica array, now passing tests --- compiler/modules/replica_bitcell_array.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index f27dcb95..93fcf3cb 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -204,7 +204,7 @@ class replica_bitcell_array(bitcell_base_array): # Main array self.bitcell_array_inst=self.add_inst(name="bitcell_array", - mod=self.bitcell_array) + mod=self.bitcell_array) self.connect_inst(self.all_bitline_names + self.all_wordline_names + self.supplies) # Replica columns @@ -217,7 +217,7 @@ class replica_bitcell_array(bitcell_base_array): else: self.replica_col_insts.append(None) - # Dummy rows under the bitcell array (connected with with the replica cell wl) + # Dummy rows above/below the bitcell array (connected with the replica cell wl) 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: @@ -250,6 +250,8 @@ class replica_bitcell_array(bitcell_base_array): self.add_layout_pins() + self.route_supplies() + lower_left = self.find_lowest_coords() upper_right = self.find_highest_coords() self.width = upper_right.x - lower_left.x @@ -370,6 +372,12 @@ class replica_bitcell_array(bitcell_base_array): width=pin.width(), height=self.height) + def route_supplies(self): + + for inst in self.insts: + for pin_name in ["vdd", "gnd"]: + self.copy_layout_pin(inst, pin_name) + def analytical_power(self, corner, load): """Power of Bitcell array and bitline in nW.""" # Dynamic Power from Bitline From 5a82c45a33e02887fe42fece2b825965b0fda848 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Mon, 24 Oct 2022 20:08:13 -0700 Subject: [PATCH 09/42] Change how lists of BLs and WLs are named and organized for proper connection between these modules --- compiler/modules/capped_bitcell_array.py | 45 +++++++++++--------- compiler/modules/replica_bitcell_array.py | 51 +++++++++++++---------- 2 files changed, 54 insertions(+), 42 deletions(-) diff --git a/compiler/modules/capped_bitcell_array.py b/compiler/modules/capped_bitcell_array.py index 666ffb70..ae38d048 100644 --- a/compiler/modules/capped_bitcell_array.py +++ b/compiler/modules/capped_bitcell_array.py @@ -157,19 +157,22 @@ class capped_bitcell_array(bitcell_base_array): self.add_pin("gnd", "GROUND") def add_bitline_pins(self): - self.all_bitline_names = self.replica_bitcell_array.all_bitline_names + self.all_bitcell_bitline_names = self.replica_bitcell_array.all_bitcell_bitline_names + self.replica_array_bitline_names = self.replica_bitcell_array.all_bitline_names - self.add_pin_list(self.all_bitline_names, "INOUT") + self.add_pin_list(self.replica_array_bitline_names, "INOUT") def add_wordline_pins(self): - self.all_wordline_names = self.replica_bitcell_array.all_wordline_names + self.used_wordline_names = self.replica_bitcell_array.used_wordline_names + self.unused_wordline_names = self.replica_bitcell_array.unused_wordline_names + self.replica_array_wordline_names = self.replica_bitcell_array.all_wordline_names - self.capped_array_wordline_names = [] - self.capped_array_wordline_names.extend(["gnd"] * len(self.col_cap_top.get_wordline_names())) - self.capped_array_wordline_names.extend(self.replica_array_wordline_names) - self.capped_array_wordline_names.extend(["gnd"] * len(self.col_cap_bottom.get_wordline_names())) + self.all_wordline_names = [] + self.all_wordline_names.extend(["gnd"] * len(self.col_cap_top.get_wordline_names())) + self.all_wordline_names.extend(self.replica_array_wordline_names) + self.all_wordline_names.extend(["gnd"] * len(self.col_cap_bottom.get_wordline_names())) - self.add_pin_list(self.all_wordline_names, "INPUT") + self.add_pin_list(self.used_wordline_names, "INPUT") def create_instances(self): """ Create the module instances used in this design """ @@ -178,25 +181,28 @@ class capped_bitcell_array(bitcell_base_array): # Main array self.replica_bitcell_array_inst=self.add_inst(name="replica_bitcell_array", mod=self.replica_bitcell_array) - self.connect_inst(self.all_bitline_names + self.all_wordline_names + self.supplies) + self.connect_inst(self.replica_array_bitline_names + ["gnd" if x in self.unused_wordline_names else x for x in self.replica_array_wordline_names] + self.supplies) # Top/bottom dummy rows or col caps self.dummy_row_insts = [] self.dummy_row_insts.append(self.add_inst(name="dummy_row_bot", mod=self.col_cap_bottom)) - self.connect_inst(self.all_bitline_names + ["gnd"] * len(self.col_cap_bottom.get_wordline_names()) + self.supplies) + self.connect_inst(self.all_bitcell_bitline_names + ["gnd"] * len(self.col_cap_bottom.get_wordline_names()) + self.supplies) self.dummy_row_insts.append(self.add_inst(name="dummy_row_top", mod=self.col_cap_top)) - self.connect_inst(self.all_bitline_names + ["gnd"] * len(self.col_cap_top.get_wordline_names()) + self.supplies) + self.connect_inst(self.all_bitcell_bitline_names + ["gnd"] * len(self.col_cap_top.get_wordline_names()) + self.supplies) # Left/right Dummy columns self.dummy_col_insts = [] self.dummy_col_insts.append(self.add_inst(name="dummy_col_left", mod=self.row_cap_left)) - self.connect_inst(["dummy_left_" + bl for bl in self.row_cap_left.all_bitline_names] + self.capped_array_wordline_names + self.supplies) + self.connect_inst(["dummy_left_" + bl for bl in self.row_cap_left.all_bitline_names] + self.all_wordline_names + self.supplies) self.dummy_col_insts.append(self.add_inst(name="dummy_col_right", mod=self.row_cap_right)) - self.connect_inst(["dummy_right_" + bl for bl in self.row_cap_right.all_bitline_names] + self.capped_array_wordline_names + self.supplies) + self.connect_inst(["dummy_right_" + bl for bl in self.row_cap_right.all_bitline_names] + self.all_wordline_names + self.supplies) + + # bitcell array needed for some offset calculations + self.bitcell_array_inst = self.replica_bitcell_array.bitcell_array_inst def create_layout(self): @@ -227,7 +233,7 @@ class capped_bitcell_array(bitcell_base_array): self.width = self.dummy_col_insts[1].rx() + self.unused_offset.x self.height = self.dummy_row_insts[1].uy() - self.copy_layout_pins() + # self.copy_layout_pins() self.route_supplies() @@ -294,11 +300,12 @@ class capped_bitcell_array(bitcell_base_array): dummy_col_offset = self.bitcell_offset.scale(len(self.right_rbl), -self.rbl[0] - 1) + self.bitcell_array_inst.lr() self.dummy_col_insts[1].place(offset=dummy_col_offset) - def copy_layout_pins(self): - for pin_name in self.replica_bitcell_array_inst.get_layout_pins(): - if pin_name in ["vdd", "gnd"]: - continue - self.copy_layout_pin(self.replica_bitcell_array_inst, pin_name) + # FIXME: what does this do and where did it come from ?? commenting out for now 10/24 + # def copy_layout_pins(self): + # for pin_name in self.replica_bitcell_array_inst.get_layout_pins(): + # if pin_name in ["vdd", "gnd"]: + # continue + # self.copy_layout_pin(self.replica_bitcell_array_inst, pin_name) def route_supplies(self): diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 93fcf3cb..612155ce 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -159,44 +159,49 @@ class replica_bitcell_array(bitcell_base_array): # Make a flat list too self.all_rbl_bitline_names = [x for sl in self.rbl_bitline_names for x in sl] - self.bitline_names = self.bitcell_array.bitline_names + self.bitcell_bitline_names = self.bitcell_array.bitline_names # Make a flat list too - self.all_bitline_names = [x for sl in zip(*self.bitline_names) for x in sl] + self.all_bitcell_bitline_names = [x for sl in zip(*self.bitcell_bitline_names) for x in sl] + self.all_bitline_names = [] 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") + self.all_bitline_names.extend(self.rbl_bitline_names[port]) + self.all_bitline_names.extend(self.all_bitcell_bitline_names) for port in self.right_rbl: - self.add_pin_list(self.rbl_bitline_names[port], "INOUT") + self.all_bitline_names.extend(self.rbl_bitline_names[port]) + + self.add_pin_list(self.all_bitline_names, "INOUT") def add_wordline_pins(self): - # Wordlines to be grounded by capped_bitcell_array - self.gnd_wordline_names = [] + # Unused wordlines are connected to ground at the next level of hierarchy + self.unused_wordline_names = [] for port in self.all_ports: for bit in self.all_ports: self.rbl_wordline_names[port].append("rbl_wl_{0}_{1}".format(port, bit)) if bit != port: - self.gnd_wordline_names.append("rbl_wl_{0}_{1}".format(port, bit)) + self.unused_wordline_names.append("rbl_wl_{0}_{1}".format(port, bit)) self.all_rbl_wordline_names = [x for sl in self.rbl_wordline_names for x in sl] - self.wordline_names = self.bitcell_array.wordline_names - self.all_wordline_names = self.bitcell_array.all_wordline_names + self.all_bitcell_wordline_names = self.bitcell_array.all_wordline_names - # All wordlines including dummy and RBL - self.replica_array_wordline_names = [] + # All wordlines including RBL + self.all_wordline_names = [] for bit in range(self.rbl[0]): - self.replica_array_wordline_names.extend([x for x in self.rbl_wordline_names[bit]]) - self.replica_array_wordline_names.extend(self.all_wordline_names) + self.all_wordline_names.extend(self.rbl_wordline_names[bit]) + self.all_wordline_names.extend(self.all_bitcell_wordline_names) for bit in range(self.rbl[1]): - self.replica_array_wordline_names.extend([x for x in self.rbl_wordline_names[self.rbl[0] + bit]]) + self.all_wordline_names.extend(self.rbl_wordline_names[self.rbl[0] + bit]) + self.used_wordline_names = [] for port in range(self.rbl[0]): - self.add_pin(self.rbl_wordline_names[port][port], "INPUT") - self.add_pin_list(self.all_wordline_names, "INPUT") + self.used_wordline_names.append(self.rbl_wordline_names[port][port]) + self.used_wordline_names.extend(self.all_bitcell_wordline_names) for port in range(self.rbl[0], self.rbl[0] + self.rbl[1]): - self.add_pin(self.rbl_wordline_names[port][port], "INPUT") + self.used_wordline_names.append(self.rbl_wordline_names[port][port]) + + self.add_pin_list(self.all_wordline_names, "INPUT") def create_instances(self): """ Create the module instances used in this design """ @@ -205,7 +210,7 @@ class replica_bitcell_array(bitcell_base_array): # Main array self.bitcell_array_inst=self.add_inst(name="bitcell_array", mod=self.bitcell_array) - self.connect_inst(self.all_bitline_names + self.all_wordline_names + self.supplies) + self.connect_inst(self.all_bitcell_bitline_names + self.all_bitcell_wordline_names + self.supplies) # Replica columns self.replica_col_insts = [] @@ -213,7 +218,7 @@ class replica_bitcell_array(bitcell_base_array): if port in self.rbls: self.replica_col_insts.append(self.add_inst(name="replica_col_{}".format(port), mod=self.replica_columns[port])) - self.connect_inst(self.rbl_bitline_names[port] + self.replica_array_wordline_names + self.supplies) + self.connect_inst(self.rbl_bitline_names[port] + self.all_wordline_names + self.supplies) else: self.replica_col_insts.append(None) @@ -223,7 +228,7 @@ class replica_bitcell_array(bitcell_base_array): for port in self.all_ports: 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 + [x for x in self.rbl_wordline_names[port]] + self.supplies) + self.connect_inst(self.all_bitcell_bitline_names + self.rbl_wordline_names[port] + self.supplies) def create_layout(self): @@ -331,7 +336,7 @@ class replica_bitcell_array(bitcell_base_array): # All wordlines # Main array wl and bl/br - for pin_name in self.all_wordline_names: + for pin_name in self.all_bitcell_wordline_names: pin_list = self.bitcell_array_inst.get_pins(pin_name) for pin in pin_list: self.add_layout_pin(text=pin_name, @@ -351,7 +356,7 @@ class replica_bitcell_array(bitcell_base_array): width=self.width, height=pin.height()) - for pin_name in self.all_bitline_names: + for pin_name in self.all_bitcell_bitline_names: pin_list = self.bitcell_array_inst.get_pins(pin_name) for pin in pin_list: self.add_layout_pin(text=pin_name, From ac8a15acc01f166e47ec23b4a94c7f4213debb6b Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Mon, 21 Nov 2022 17:42:50 -0800 Subject: [PATCH 10/42] fix get_replica_top and get_replica_left return values --- compiler/modules/replica_bitcell_array.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 612155ce..d9b28fcd 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -285,7 +285,7 @@ class replica_bitcell_array(bitcell_base_array): def get_replica_top(self): """ Return the top of all replica columns. """ - return self.dummy_row_insts[0].by() + return self.dummy_row_insts[1].by() def get_replica_bottom(self): """ Return the bottom of all replica columns. """ @@ -293,7 +293,7 @@ class replica_bitcell_array(bitcell_base_array): def get_replica_left(self): """ Return the left of all replica columns. """ - return self.dummy_col_insts[0].rx() + return self.dummy_col_insts[0].lx() def get_replica_right(self): """ Return the right of all replica columns. """ From 68fb4e3c63521e68866fd995bb8cd3a8a0de5054 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Fri, 2 Dec 2022 09:42:33 -0800 Subject: [PATCH 11/42] introduced some other bugs but scmos tiling is correct --- compiler/modules/capped_bitcell_array.py | 44 +++++++++++------------ compiler/modules/replica_bitcell_array.py | 2 +- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/compiler/modules/capped_bitcell_array.py b/compiler/modules/capped_bitcell_array.py index ae38d048..44885512 100644 --- a/compiler/modules/capped_bitcell_array.py +++ b/compiler/modules/capped_bitcell_array.py @@ -101,8 +101,10 @@ class capped_bitcell_array(bitcell_base_array): # Dummy Row or Col Cap, depending on bitcell array properties col_cap_module_type = ("col_cap_array" if self.cell.end_caps else "dummy_array") + # TODO: remove redundancy from arguments in pairs below (top/bottom, left/right) + # for example, cols takes the same value for top/bottom self.col_cap_top = factory.create(module_type=col_cap_module_type, - cols=self.column_size, + cols=self.column_size + len(self.rbls), rows=1, # dummy column + left replica column(s) column_offset=1 + len(self.left_rbl), @@ -110,7 +112,7 @@ class capped_bitcell_array(bitcell_base_array): location="top") self.col_cap_bottom = factory.create(module_type=col_cap_module_type, - cols=self.column_size, + cols=self.column_size + len(self.rbls), rows=1, # dummy column + left replica column(s) column_offset=1 + len(self.left_rbl), @@ -157,7 +159,7 @@ class capped_bitcell_array(bitcell_base_array): self.add_pin("gnd", "GROUND") def add_bitline_pins(self): - self.all_bitcell_bitline_names = self.replica_bitcell_array.all_bitcell_bitline_names + self.all_bitline_names = self.replica_bitcell_array.all_bitline_names self.replica_array_bitline_names = self.replica_bitcell_array.all_bitline_names self.add_pin_list(self.replica_array_bitline_names, "INOUT") @@ -187,10 +189,10 @@ class capped_bitcell_array(bitcell_base_array): self.dummy_row_insts = [] self.dummy_row_insts.append(self.add_inst(name="dummy_row_bot", mod=self.col_cap_bottom)) - self.connect_inst(self.all_bitcell_bitline_names + ["gnd"] * len(self.col_cap_bottom.get_wordline_names()) + self.supplies) + self.connect_inst(self.all_bitline_names + ["gnd"] * len(self.col_cap_bottom.get_wordline_names()) + self.supplies) self.dummy_row_insts.append(self.add_inst(name="dummy_row_top", mod=self.col_cap_top)) - self.connect_inst(self.all_bitcell_bitline_names + ["gnd"] * len(self.col_cap_top.get_wordline_names()) + self.supplies) + self.connect_inst(self.all_bitline_names + ["gnd"] * len(self.col_cap_top.get_wordline_names()) + self.supplies) # Left/right Dummy columns self.dummy_col_insts = [] @@ -210,7 +212,6 @@ class capped_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])) - self.unused_offset = vector(0.25, 0.25) # This is a bitcell x bitcell offset to scale self.bitcell_offset = vector(self.cell.width, self.cell.height) @@ -218,7 +219,7 @@ class capped_bitcell_array(bitcell_base_array): self.row_end_offset = vector(self.cell.width, self.cell.height) # Everything is computed with the replica array - self.replica_bitcell_array_inst.place(offset=self.unused_offset) + self.replica_bitcell_array_inst.place(offset=self.bitcell_offset.scale(-1, -1)) # may need to depend on rbl self.add_end_caps() @@ -230,10 +231,10 @@ class capped_bitcell_array(bitcell_base_array): # Add extra width on the left and right for the unused WLs - self.width = self.dummy_col_insts[1].rx() + self.unused_offset.x + self.width = self.dummy_col_insts[1].rx() self.height = self.dummy_row_insts[1].uy() - # self.copy_layout_pins() + self.copy_layout_pins() self.route_supplies() @@ -281,31 +282,30 @@ class capped_bitcell_array(bitcell_base_array): # Far top dummy row (first row above array is NOT flipped if even number of rows) flip_dummy = (self.row_size + self.rbl[1]) % 2 - dummy_row_offset = self.bitcell_offset.scale(0, self.rbl[1] + flip_dummy) + self.bitcell_array_inst.ul() + dummy_row_offset = self.bitcell_offset.scale(1, self.rbl[1] + flip_dummy) + self.replica_bitcell_array_inst.ul() + vector(0, -0.8) self.dummy_row_insts[1].place(offset=dummy_row_offset, mirror="MX" if flip_dummy else "R0") # Far bottom dummy row (first row below array IS flipped) flip_dummy = (self.rbl[0] + 1) % 2 - dummy_row_offset = self.bitcell_offset.scale(0, -self.rbl[0] - 1 + flip_dummy) + self.unused_offset + dummy_row_offset = self.bitcell_offset.scale(0, -self.rbl[0] + flip_dummy) self.dummy_row_insts[0].place(offset=dummy_row_offset, mirror="MX" if flip_dummy else "R0") # Far left dummy col # Shifted down by the number of left RBLs even if we aren't adding replica column to this bitcell array - dummy_col_offset = self.bitcell_offset.scale(-len(self.left_rbl) - 1, -self.rbl[0] - 1) + self.unused_offset + dummy_col_offset = self.bitcell_offset.scale(-len(self.left_rbl), -self.rbl[0]) self.dummy_col_insts[0].place(offset=dummy_col_offset) # Far right dummy col # Shifted down by the number of left RBLs even if we aren't adding replica column to this bitcell array - dummy_col_offset = self.bitcell_offset.scale(len(self.right_rbl), -self.rbl[0] - 1) + self.bitcell_array_inst.lr() + dummy_col_offset = self.bitcell_offset.scale(len(self.right_rbl), -self.rbl[0] + 1) + self.replica_bitcell_array_inst.lr() self.dummy_col_insts[1].place(offset=dummy_col_offset) - # FIXME: what does this do and where did it come from ?? commenting out for now 10/24 - # def copy_layout_pins(self): - # for pin_name in self.replica_bitcell_array_inst.get_layout_pins(): - # if pin_name in ["vdd", "gnd"]: - # continue - # self.copy_layout_pin(self.replica_bitcell_array_inst, pin_name) + def copy_layout_pins(self): + for pin_name in self.replica_bitcell_array.get_layout_pins(): + if pin_name in ["vdd", "gnd"]: + continue + self.copy_layout_pin(self.replica_bitcell_array_inst, pin_name) def route_supplies(self): @@ -373,9 +373,9 @@ class capped_bitcell_array(bitcell_base_array): self.connect_side_pin(pin, "right", self.right_gnd_locs[0].x) # Ground the unused replica wordlines - for (names, inst) in zip(self.replica_bitcell_array_inst.rbl_wordline_names, self.replica_bitcell_array_inst.dummy_row_replica_insts): - for (wl_name, pin_name) in zip(names, self.replica_bitcell_array_inst.dummy_row.get_wordline_names()): - if wl_name in self.replica_bitcell_array_inst.gnd_wordline_names: + for (names, inst) in zip(self.replica_bitcell_array.rbl_wordline_names, self.replica_bitcell_array.dummy_row_replica_insts): + for (wl_name, pin_name) in zip(names, self.replica_bitcell_array.dummy_row.get_wordline_names()): + if wl_name in self.replica_bitcell_array.unused_wordline_names: pin = inst.get_pin(pin_name) self.connect_side_pin(pin, "left", self.left_gnd_locs[0].x) self.connect_side_pin(pin, "right", self.right_gnd_locs[0].x) diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index d9b28fcd..89661ad4 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -261,7 +261,7 @@ class replica_bitcell_array(bitcell_base_array): upper_right = self.find_highest_coords() self.width = upper_right.x - lower_left.x self.height = upper_right.y - lower_left.y - self.translate_all(lower_left) + # self.translate_all(lower_left) self.add_boundary() From d224c06b251f17a24e6d38f633c158c5b57bb107 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Sat, 10 Dec 2022 19:03:55 -0800 Subject: [PATCH 12/42] placement positions problem fixed, incorrect w,h calculations were the problem --- compiler/modules/capped_bitcell_array.py | 8 ++++---- compiler/modules/replica_bitcell_array.py | 23 ++++++++++++----------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/compiler/modules/capped_bitcell_array.py b/compiler/modules/capped_bitcell_array.py index 44885512..f04eb60f 100644 --- a/compiler/modules/capped_bitcell_array.py +++ b/compiler/modules/capped_bitcell_array.py @@ -219,7 +219,7 @@ class capped_bitcell_array(bitcell_base_array): self.row_end_offset = vector(self.cell.width, self.cell.height) # Everything is computed with the replica array - self.replica_bitcell_array_inst.place(offset=self.bitcell_offset.scale(-1, -1)) # may need to depend on rbl + self.replica_bitcell_array_inst.place(offset=0) self.add_end_caps() @@ -282,7 +282,7 @@ class capped_bitcell_array(bitcell_base_array): # Far top dummy row (first row above array is NOT flipped if even number of rows) flip_dummy = (self.row_size + self.rbl[1]) % 2 - dummy_row_offset = self.bitcell_offset.scale(1, self.rbl[1] + flip_dummy) + self.replica_bitcell_array_inst.ul() + vector(0, -0.8) + dummy_row_offset = self.bitcell_offset.scale(0, self.rbl[1] - 1 + flip_dummy) + self.replica_bitcell_array_inst.ul() self.dummy_row_insts[1].place(offset=dummy_row_offset, mirror="MX" if flip_dummy else "R0") @@ -298,11 +298,11 @@ class capped_bitcell_array(bitcell_base_array): # Far right dummy col # Shifted down by the number of left RBLs even if we aren't adding replica column to this bitcell array - dummy_col_offset = self.bitcell_offset.scale(len(self.right_rbl), -self.rbl[0] + 1) + self.replica_bitcell_array_inst.lr() + dummy_col_offset = self.bitcell_offset.scale(len(self.right_rbl) - 1, -self.rbl[0]) + self.replica_bitcell_array_inst.lr() self.dummy_col_insts[1].place(offset=dummy_col_offset) def copy_layout_pins(self): - for pin_name in self.replica_bitcell_array.get_layout_pins(): + for pin_name in self.replica_bitcell_array_inst.get_pins(): if pin_name in ["vdd", "gnd"]: continue self.copy_layout_pin(self.replica_bitcell_array_inst, pin_name) diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 89661ad4..fb0c2935 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -250,18 +250,18 @@ 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(1 + len(self.left_rbl), 1 + self.rbl[0]) + array_offset = self.bitcell_offset.scale(len(self.left_rbl), self.rbl[0]) self.translate_all(array_offset.scale(-1, -1)) + self.width = self.dummy_col_insts[1].rx() + self.unused_offset.x + self.height = self.dummy_row_insts[1].uy() + self.add_layout_pins() self.route_supplies() - lower_left = self.find_lowest_coords() - upper_right = self.find_highest_coords() - self.width = upper_right.x - lower_left.x - self.height = upper_right.y - lower_left.y - # self.translate_all(lower_left) + self.width = (len(self.rbls) + self.column_size) * self.cell.width + self.height = (len(self.rbls) + self.row_size) * self.cell.height self.add_boundary() @@ -335,13 +335,13 @@ class replica_bitcell_array(bitcell_base_array): """ Add the layout pins """ # All wordlines - # Main array wl and bl/br + # Main array wl for pin_name in self.all_bitcell_wordline_names: 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, - offset=pin.ll(), + offset=pin.ll().scale(0, 1), width=self.width, height=pin.height()) @@ -352,16 +352,17 @@ class replica_bitcell_array(bitcell_base_array): pin = inst.get_pin(pin_name) self.add_layout_pin(text=wl_name, layer=pin.layer, - offset=pin.ll(), + offset=pin.ll().scale(0, 1), width=self.width, height=pin.height()) + # Main array bl/br for pin_name in self.all_bitcell_bitline_names: 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, - offset=pin.ll(), + offset=pin.ll().scale(1, 0), width=pin.width(), height=self.height) @@ -373,7 +374,7 @@ class replica_bitcell_array(bitcell_base_array): pin = inst.get_pin(pin_name) self.add_layout_pin(text=bl_name, layer=pin.layer, - offset=pin.ll(), + offset=pin.ll().scale(1, 0), width=pin.width(), height=self.height) From 119bcb9197a51641580f947b225b3f54daa8c437 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Wed, 14 Dec 2022 08:12:55 -0800 Subject: [PATCH 13/42] route unused wordlines (still failing lvs) --- compiler/modules/capped_bitcell_array.py | 10 ++++++---- compiler/modules/replica_bitcell_array.py | 7 ++----- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/compiler/modules/capped_bitcell_array.py b/compiler/modules/capped_bitcell_array.py index f04eb60f..1c9d2d51 100644 --- a/compiler/modules/capped_bitcell_array.py +++ b/compiler/modules/capped_bitcell_array.py @@ -226,7 +226,7 @@ class capped_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(1 + len(self.left_rbl), 1 + self.rbl[0]) + array_offset = self.bitcell_offset.scale(len(self.left_rbl), self.rbl[0]) self.translate_all(array_offset.scale(-1, -1)) # Add extra width on the left and right for the unused WLs @@ -302,8 +302,10 @@ class capped_bitcell_array(bitcell_base_array): self.dummy_col_insts[1].place(offset=dummy_col_offset) def copy_layout_pins(self): - for pin_name in self.replica_bitcell_array_inst.get_pins(): - if pin_name in ["vdd", "gnd"]: + excluded_pins = ["vdd", "gnd"] + excluded_pins.extend(self.unused_wordline_names) + for pin_name in self.replica_bitcell_array.get_pin_names(): + if pin_name in excluded_pins: continue self.copy_layout_pin(self.replica_bitcell_array_inst, pin_name) @@ -375,7 +377,7 @@ class capped_bitcell_array(bitcell_base_array): # Ground the unused replica wordlines for (names, inst) in zip(self.replica_bitcell_array.rbl_wordline_names, self.replica_bitcell_array.dummy_row_replica_insts): for (wl_name, pin_name) in zip(names, self.replica_bitcell_array.dummy_row.get_wordline_names()): - if wl_name in self.replica_bitcell_array.unused_wordline_names: + if wl_name in self.unused_wordline_names: pin = inst.get_pin(pin_name) self.connect_side_pin(pin, "left", self.left_gnd_locs[0].x) self.connect_side_pin(pin, "right", self.right_gnd_locs[0].x) diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index fb0c2935..07cbc405 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -225,7 +225,7 @@ class replica_bitcell_array(bitcell_base_array): # Dummy rows above/below the bitcell array (connected with the replica cell wl) 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: + 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_bitcell_bitline_names + self.rbl_wordline_names[port] + self.supplies) @@ -253,15 +253,12 @@ class replica_bitcell_array(bitcell_base_array): array_offset = self.bitcell_offset.scale(len(self.left_rbl), self.rbl[0]) self.translate_all(array_offset.scale(-1, -1)) - self.width = self.dummy_col_insts[1].rx() + self.unused_offset.x - self.height = self.dummy_row_insts[1].uy() - self.add_layout_pins() self.route_supplies() - self.width = (len(self.rbls) + self.column_size) * self.cell.width self.height = (len(self.rbls) + self.row_size) * self.cell.height + self.width = (len(self.rbls) + self.column_size) * self.cell.width self.add_boundary() From f651b484c596de44052499738470728775033c6d Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Wed, 14 Dec 2022 08:48:12 -0800 Subject: [PATCH 14/42] fix capped array tests after dev merge --- ...apped_bitcell_array_bothrbl_1rw_1r_test.py | 21 ++++++++++--------- ...apped_bitcell_array_leftrbl_1rw_1r_test.py | 20 +++++++++--------- ..._capped_bitcell_array_norbl_1rw_1r_test.py | 21 ++++++++++--------- 3 files changed, 32 insertions(+), 30 deletions(-) diff --git a/compiler/tests/14_capped_bitcell_array_bothrbl_1rw_1r_test.py b/compiler/tests/14_capped_bitcell_array_bothrbl_1rw_1r_test.py index 29920124..1b860a64 100644 --- a/compiler/tests/14_capped_bitcell_array_bothrbl_1rw_1r_test.py +++ b/compiler/tests/14_capped_bitcell_array_bothrbl_1rw_1r_test.py @@ -1,29 +1,29 @@ #!/usr/bin/env python3 # See LICENSE for licensing information. # -# Copyright (c) 2016-2021 Regents of the University of California +# Copyright (c) 2016-2022 Regents of the University of California, Santa Cruz # All rights reserved. # +import sys, os import unittest from testutils import * -import sys, os -import globals -from globals import OPTS -from sram_factory import factory -import debug +import openram +from openram import debug +from openram.sram_factory import factory +from openram import OPTS class capped_bitcell_array_1rw_1r_test(openram_test): def runTest(self): config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) - globals.init_openram(config_file) + openram.init_openram(config_file, is_unit_test=True) OPTS.num_rw_ports = 1 OPTS.num_r_ports = 1 OPTS.num_w_ports = 0 - globals.setup_bitcell() + openram.setup_bitcell() debug.info(2, "Testing 4x4 array left and right replica for dp cell") a = factory.create(module_type="capped_bitcell_array", @@ -34,11 +34,12 @@ class capped_bitcell_array_1rw_1r_test(openram_test): right_rbl=[1]) self.local_check(a) - globals.end_openram() + openram.end_openram() + # run the test from the command line if __name__ == "__main__": - (OPTS, args) = globals.parse_args() + (OPTS, args) = openram.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/14_capped_bitcell_array_leftrbl_1rw_1r_test.py b/compiler/tests/14_capped_bitcell_array_leftrbl_1rw_1r_test.py index 3d414a33..de0d9177 100644 --- a/compiler/tests/14_capped_bitcell_array_leftrbl_1rw_1r_test.py +++ b/compiler/tests/14_capped_bitcell_array_leftrbl_1rw_1r_test.py @@ -1,29 +1,29 @@ #!/usr/bin/env python3 # See LICENSE for licensing information. # -# Copyright (c) 2016-2021 Regents of the University of California +# Copyright (c) 2016-2022 Regents of the University of California, Santa Cruz # All rights reserved. # +import sys, os import unittest from testutils import * -import sys, os -import globals -from globals import OPTS -from sram_factory import factory -import debug +import openram +from openram import debug +from openram.sram_factory import factory +from openram import OPTS class capped_bitcell_array_1rw_1r_test(openram_test): def runTest(self): config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) - globals.init_openram(config_file) + openram.init_openram(config_file, is_unit_test=True) OPTS.num_rw_ports = 1 OPTS.num_r_ports = 1 OPTS.num_w_ports = 0 - globals.setup_bitcell() + openram.setup_bitcell() debug.info(2, "Testing 4x4 left replica array for dp cell") a = factory.create(module_type="capped_bitcell_array", @@ -33,11 +33,11 @@ class capped_bitcell_array_1rw_1r_test(openram_test): left_rbl=[0]) self.local_check(a) - globals.end_openram() + openram.end_openram() # run the test from the command line if __name__ == "__main__": - (OPTS, args) = globals.parse_args() + (OPTS, args) = openram.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/14_capped_bitcell_array_norbl_1rw_1r_test.py b/compiler/tests/14_capped_bitcell_array_norbl_1rw_1r_test.py index 7c4fd9bb..b2a8d97c 100644 --- a/compiler/tests/14_capped_bitcell_array_norbl_1rw_1r_test.py +++ b/compiler/tests/14_capped_bitcell_array_norbl_1rw_1r_test.py @@ -1,29 +1,29 @@ #!/usr/bin/env python3 # See LICENSE for licensing information. # -# Copyright (c) 2016-2021 Regents of the University of California +# Copyright (c) 2016-2022 Regents of the University of California, Santa Cruz # All rights reserved. # +import sys, os import unittest from testutils import * -import sys, os -import globals -from globals import OPTS -from sram_factory import factory -import debug +import openram +from openram import debug +from openram.sram_factory import factory +from openram import OPTS class capped_bitcell_array_1rw_1r_test(openram_test): def runTest(self): config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) - globals.init_openram(config_file) + openram.init_openram(config_file, is_unit_test=True) OPTS.num_rw_ports = 1 OPTS.num_r_ports = 1 OPTS.num_w_ports = 0 - globals.setup_bitcell() + openram.setup_bitcell() debug.info(2, "Testing 4x4 non-replica array for dp cell") a = factory.create(module_type="capped_bitcell_array", @@ -32,11 +32,12 @@ class capped_bitcell_array_1rw_1r_test(openram_test): rbl=[1, 1]) self.local_check(a) - globals.end_openram() + openram.end_openram() + # run the test from the command line if __name__ == "__main__": - (OPTS, args) = globals.parse_args() + (OPTS, args) = openram.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) unittest.main(testRunner=debugTestRunner()) From d8e0f4275d566bf12dc975ce72ab5d9d21e113de Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Wed, 14 Dec 2022 14:20:54 -0800 Subject: [PATCH 15/42] fix capped array after merge with dev --- compiler/modules/capped_bitcell_array.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/modules/capped_bitcell_array.py b/compiler/modules/capped_bitcell_array.py index 1c9d2d51..1751fd71 100644 --- a/compiler/modules/capped_bitcell_array.py +++ b/compiler/modules/capped_bitcell_array.py @@ -4,14 +4,14 @@ # All rights reserved. # -import debug -from base import vector -from base import contact +from openram import debug +from openram.base import vector +from openram.base import contact +from openram.sram_factory import factory +from openram.tech import drc, spice +from openram.tech import cell_properties as props +from openram import OPTS from .bitcell_base_array import bitcell_base_array -from tech import drc, spice -from tech import cell_properties as props -from globals import OPTS -from sram_factory import factory class capped_bitcell_array(bitcell_base_array): From 29c79abaf8888f3b67f7c8cf5366616aebddd02e Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Thu, 15 Dec 2022 02:38:00 -0800 Subject: [PATCH 16/42] move layout pins when copying them --- compiler/base/hierarchy_layout.py | 5 +++-- compiler/modules/capped_bitcell_array.py | 10 +++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index 86cf6e43..ce9c5407 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -631,10 +631,11 @@ class layout(): """ return self.pins - def copy_layout_pin(self, instance, pin_name, new_name=""): + def copy_layout_pin(self, instance, pin_name, new_name="", relative_offset=vector(0, 0)): """ Create a copied version of the layout pin at the current level. You can optionally rename the pin to a new name. + You can optionally add an offset vector by which to move the pin. """ pins = instance.get_pins(pin_name) @@ -646,7 +647,7 @@ class layout(): new_name = pin_name self.add_layout_pin(new_name, pin.layer, - pin.ll(), + pin.ll() + relative_offset, pin.width(), pin.height()) diff --git a/compiler/modules/capped_bitcell_array.py b/compiler/modules/capped_bitcell_array.py index 1751fd71..cee1885b 100644 --- a/compiler/modules/capped_bitcell_array.py +++ b/compiler/modules/capped_bitcell_array.py @@ -307,7 +307,15 @@ class capped_bitcell_array(bitcell_base_array): for pin_name in self.replica_bitcell_array.get_pin_names(): if pin_name in excluded_pins: continue - self.copy_layout_pin(self.replica_bitcell_array_inst, pin_name) + # move pins to edges of cap cells + if "wl" in pin_name: + pin_offset = self.bitcell_offset.scale(-1, 0) + else: + pin_offset = self.bitcell_offset.scale(0, -1) + + self.copy_layout_pin(instance=self.replica_bitcell_array_inst, + pin_name=pin_name, + relative_offset=pin_offset) def route_supplies(self): From b5cddb93941351b205f4962123f6394de959a110 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Mon, 16 Jan 2023 17:54:17 -0800 Subject: [PATCH 17/42] fix remaining lvs issues by adding an offset to pins gotten from subinstances and appropriately grounding wls in cap cells --- compiler/modules/capped_bitcell_array.py | 27 ++++++++++++------------ 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/compiler/modules/capped_bitcell_array.py b/compiler/modules/capped_bitcell_array.py index cee1885b..58fd163a 100644 --- a/compiler/modules/capped_bitcell_array.py +++ b/compiler/modules/capped_bitcell_array.py @@ -168,10 +168,11 @@ class capped_bitcell_array(bitcell_base_array): self.used_wordline_names = self.replica_bitcell_array.used_wordline_names self.unused_wordline_names = self.replica_bitcell_array.unused_wordline_names self.replica_array_wordline_names = self.replica_bitcell_array.all_wordline_names + self.replica_array_wordline_names_with_grounded_wls = ["gnd" if x in self.unused_wordline_names else x for x in self.replica_array_wordline_names] self.all_wordline_names = [] self.all_wordline_names.extend(["gnd"] * len(self.col_cap_top.get_wordline_names())) - self.all_wordline_names.extend(self.replica_array_wordline_names) + self.all_wordline_names.extend(self.replica_array_wordline_names_with_grounded_wls) self.all_wordline_names.extend(["gnd"] * len(self.col_cap_bottom.get_wordline_names())) self.add_pin_list(self.used_wordline_names, "INPUT") @@ -183,7 +184,7 @@ class capped_bitcell_array(bitcell_base_array): # Main array self.replica_bitcell_array_inst=self.add_inst(name="replica_bitcell_array", mod=self.replica_bitcell_array) - self.connect_inst(self.replica_array_bitline_names + ["gnd" if x in self.unused_wordline_names else x for x in self.replica_array_wordline_names] + self.supplies) + self.connect_inst(self.replica_array_bitline_names + self.replica_array_wordline_names_with_grounded_wls + self.supplies) # Top/bottom dummy rows or col caps self.dummy_row_insts = [] @@ -226,8 +227,8 @@ class capped_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)) + self.array_offset = self.bitcell_offset.scale(len(self.left_rbl), self.rbl[0]) + self.translate_all(self.array_offset.scale(-1, -1)) # Add extra width on the left and right for the unused WLs @@ -387,8 +388,8 @@ class capped_bitcell_array(bitcell_base_array): for (wl_name, pin_name) in zip(names, self.replica_bitcell_array.dummy_row.get_wordline_names()): if wl_name in self.unused_wordline_names: pin = inst.get_pin(pin_name) - self.connect_side_pin(pin, "left", self.left_gnd_locs[0].x) - self.connect_side_pin(pin, "right", self.right_gnd_locs[0].x) + self.connect_side_pin(pin, "left", self.left_gnd_locs[0].x, self.array_offset) + self.connect_side_pin(pin, "right", self.right_gnd_locs[0].x, self.array_offset) def route_side_pin(self, name, side, offset_multiple=1): """ @@ -458,23 +459,23 @@ class capped_bitcell_array(bitcell_base_array): return (left_loc, right_loc) - def connect_side_pin(self, pin, side, offset): + def connect_side_pin(self, pin, side, offset, inst_offset=vector(0, 0)): """ Used to connect horizontal layers of pins to the left/right straps locs provides the offsets of the pin strip end points. """ if side in ["left", "right"]: - self.connect_vertical_side_pin(pin, side, offset) + self.connect_vertical_side_pin(pin, side, offset, inst_offset) elif side in ["top", "bottom", "bot"]: - self.connect_horizontal_side_pin(pin, side, offset) + self.connect_horizontal_side_pin(pin, side, offset, inst_offset) else: debug.error("Invalid side {}".format(side), -1) - def connect_horizontal_side_pin(self, pin, side, yoffset): + def connect_horizontal_side_pin(self, pin, side, yoffset, inst_offset=vector(0, 0)): """ Used to connect vertical layers of pins to the top/bottom horizontal straps """ - cell_loc = pin.center() + cell_loc = pin.center() + inst_offset pin_loc = vector(cell_loc.x, yoffset) # Place the pins a track outside of the array @@ -487,11 +488,11 @@ class capped_bitcell_array(bitcell_base_array): self.add_path(pin.layer, [cell_loc, pin_loc]) - def connect_vertical_side_pin(self, pin, side, xoffset): + def connect_vertical_side_pin(self, pin, side, xoffset, inst_offset=vector(0, 0)): """ Used to connect vertical layers of pins to the top/bottom vertical straps """ - cell_loc = pin.center() + cell_loc = pin.center() + inst_offset pin_loc = vector(xoffset, cell_loc.y) # Place the pins a track outside of the array From 78cabf9ca3c051499ae6f1849300d80038299509 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Tue, 17 Jan 2023 10:09:45 -0800 Subject: [PATCH 18/42] make capped array name more descriptive and add x mode to tests --- ...apped_bitcell_array.py => capped_replica_bitcell_array.py} | 2 +- ...=> 14_capped_replica_bitcell_array_bothrbl_1rw_1r_test.py} | 4 ++-- ...=> 14_capped_replica_bitcell_array_leftrbl_1rw_1r_test.py} | 4 ++-- ...y => 14_capped_replica_bitcell_array_norbl_1rw_1r_test.py} | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) rename compiler/modules/{capped_bitcell_array.py => capped_replica_bitcell_array.py} (99%) rename compiler/tests/{14_capped_bitcell_array_bothrbl_1rw_1r_test.py => 14_capped_replica_bitcell_array_bothrbl_1rw_1r_test.py} (89%) mode change 100644 => 100755 rename compiler/tests/{14_capped_bitcell_array_leftrbl_1rw_1r_test.py => 14_capped_replica_bitcell_array_leftrbl_1rw_1r_test.py} (89%) mode change 100644 => 100755 rename compiler/tests/{14_capped_bitcell_array_norbl_1rw_1r_test.py => 14_capped_replica_bitcell_array_norbl_1rw_1r_test.py} (88%) mode change 100644 => 100755 diff --git a/compiler/modules/capped_bitcell_array.py b/compiler/modules/capped_replica_bitcell_array.py similarity index 99% rename from compiler/modules/capped_bitcell_array.py rename to compiler/modules/capped_replica_bitcell_array.py index 58fd163a..d9cb256e 100644 --- a/compiler/modules/capped_bitcell_array.py +++ b/compiler/modules/capped_replica_bitcell_array.py @@ -14,7 +14,7 @@ from openram import OPTS from .bitcell_base_array import bitcell_base_array -class capped_bitcell_array(bitcell_base_array): +class capped_replica_bitcell_array(bitcell_base_array): """ Creates a replica bitcell array then adds the row and column caps to all sides of a bitcell array. diff --git a/compiler/tests/14_capped_bitcell_array_bothrbl_1rw_1r_test.py b/compiler/tests/14_capped_replica_bitcell_array_bothrbl_1rw_1r_test.py old mode 100644 new mode 100755 similarity index 89% rename from compiler/tests/14_capped_bitcell_array_bothrbl_1rw_1r_test.py rename to compiler/tests/14_capped_replica_bitcell_array_bothrbl_1rw_1r_test.py index 1b860a64..55157f93 --- a/compiler/tests/14_capped_bitcell_array_bothrbl_1rw_1r_test.py +++ b/compiler/tests/14_capped_replica_bitcell_array_bothrbl_1rw_1r_test.py @@ -14,7 +14,7 @@ from openram.sram_factory import factory from openram import OPTS -class capped_bitcell_array_1rw_1r_test(openram_test): +class capped_replica_bitcell_array_1rw_1r_test(openram_test): def runTest(self): config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) @@ -26,7 +26,7 @@ class capped_bitcell_array_1rw_1r_test(openram_test): openram.setup_bitcell() debug.info(2, "Testing 4x4 array left and right replica for dp cell") - a = factory.create(module_type="capped_bitcell_array", + a = factory.create(module_type="capped_replica_bitcell_array", cols=4, rows=4, rbl=[1, 1], diff --git a/compiler/tests/14_capped_bitcell_array_leftrbl_1rw_1r_test.py b/compiler/tests/14_capped_replica_bitcell_array_leftrbl_1rw_1r_test.py old mode 100644 new mode 100755 similarity index 89% rename from compiler/tests/14_capped_bitcell_array_leftrbl_1rw_1r_test.py rename to compiler/tests/14_capped_replica_bitcell_array_leftrbl_1rw_1r_test.py index de0d9177..663f4950 --- a/compiler/tests/14_capped_bitcell_array_leftrbl_1rw_1r_test.py +++ b/compiler/tests/14_capped_replica_bitcell_array_leftrbl_1rw_1r_test.py @@ -14,7 +14,7 @@ from openram.sram_factory import factory from openram import OPTS -class capped_bitcell_array_1rw_1r_test(openram_test): +class capped_replica_bitcell_array_1rw_1r_test(openram_test): def runTest(self): config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) @@ -26,7 +26,7 @@ class capped_bitcell_array_1rw_1r_test(openram_test): openram.setup_bitcell() debug.info(2, "Testing 4x4 left replica array for dp cell") - a = factory.create(module_type="capped_bitcell_array", + a = factory.create(module_type="capped_replica_bitcell_array", cols=4, rows=4, rbl=[1, 1], diff --git a/compiler/tests/14_capped_bitcell_array_norbl_1rw_1r_test.py b/compiler/tests/14_capped_replica_bitcell_array_norbl_1rw_1r_test.py old mode 100644 new mode 100755 similarity index 88% rename from compiler/tests/14_capped_bitcell_array_norbl_1rw_1r_test.py rename to compiler/tests/14_capped_replica_bitcell_array_norbl_1rw_1r_test.py index b2a8d97c..e7d8d4fd --- a/compiler/tests/14_capped_bitcell_array_norbl_1rw_1r_test.py +++ b/compiler/tests/14_capped_replica_bitcell_array_norbl_1rw_1r_test.py @@ -14,7 +14,7 @@ from openram.sram_factory import factory from openram import OPTS -class capped_bitcell_array_1rw_1r_test(openram_test): +class capped_replica_bitcell_array_1rw_1r_test(openram_test): def runTest(self): config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) @@ -26,7 +26,7 @@ class capped_bitcell_array_1rw_1r_test(openram_test): openram.setup_bitcell() debug.info(2, "Testing 4x4 non-replica array for dp cell") - a = factory.create(module_type="capped_bitcell_array", + a = factory.create(module_type="capped_replica_bitcell_array", cols=4, rows=4, rbl=[1, 1]) From 8522f32e433823a36343c5461f4c111aca075704 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Wed, 18 Jan 2023 20:32:40 -0800 Subject: [PATCH 19/42] radically simplify unused wordline routing code... bit of a facepalm tbh --- .../modules/capped_replica_bitcell_array.py | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/compiler/modules/capped_replica_bitcell_array.py b/compiler/modules/capped_replica_bitcell_array.py index d9cb256e..7745e432 100644 --- a/compiler/modules/capped_replica_bitcell_array.py +++ b/compiler/modules/capped_replica_bitcell_array.py @@ -384,12 +384,10 @@ class capped_replica_bitcell_array(bitcell_base_array): self.connect_side_pin(pin, "right", self.right_gnd_locs[0].x) # Ground the unused replica wordlines - for (names, inst) in zip(self.replica_bitcell_array.rbl_wordline_names, self.replica_bitcell_array.dummy_row_replica_insts): - for (wl_name, pin_name) in zip(names, self.replica_bitcell_array.dummy_row.get_wordline_names()): - if wl_name in self.unused_wordline_names: - pin = inst.get_pin(pin_name) - self.connect_side_pin(pin, "left", self.left_gnd_locs[0].x, self.array_offset) - self.connect_side_pin(pin, "right", self.right_gnd_locs[0].x, self.array_offset) + for wl_name in self.unused_wordline_names: + pin = self.replica_bitcell_array_inst.get_pin(wl_name) + self.connect_side_pin(pin, "left", self.left_gnd_locs[0].x) + self.connect_side_pin(pin, "right", self.right_gnd_locs[0].x) def route_side_pin(self, name, side, offset_multiple=1): """ @@ -459,23 +457,23 @@ class capped_replica_bitcell_array(bitcell_base_array): return (left_loc, right_loc) - def connect_side_pin(self, pin, side, offset, inst_offset=vector(0, 0)): + def connect_side_pin(self, pin, side, offset): """ Used to connect horizontal layers of pins to the left/right straps locs provides the offsets of the pin strip end points. """ if side in ["left", "right"]: - self.connect_vertical_side_pin(pin, side, offset, inst_offset) + self.connect_vertical_side_pin(pin, side, offset) elif side in ["top", "bottom", "bot"]: - self.connect_horizontal_side_pin(pin, side, offset, inst_offset) + self.connect_horizontal_side_pin(pin, side, offset) else: debug.error("Invalid side {}".format(side), -1) - def connect_horizontal_side_pin(self, pin, side, yoffset, inst_offset=vector(0, 0)): + def connect_horizontal_side_pin(self, pin, side, yoffset): """ Used to connect vertical layers of pins to the top/bottom horizontal straps """ - cell_loc = pin.center() + inst_offset + cell_loc = pin.center() pin_loc = vector(cell_loc.x, yoffset) # Place the pins a track outside of the array @@ -488,11 +486,11 @@ class capped_replica_bitcell_array(bitcell_base_array): self.add_path(pin.layer, [cell_loc, pin_loc]) - def connect_vertical_side_pin(self, pin, side, xoffset, inst_offset=vector(0, 0)): + def connect_vertical_side_pin(self, pin, side, xoffset): """ Used to connect vertical layers of pins to the top/bottom vertical straps """ - cell_loc = pin.center() + inst_offset + cell_loc = pin.center() pin_loc = vector(xoffset, cell_loc.y) # Place the pins a track outside of the array From 7021b8050697d7ed95471aa5a0c8ee26e932379f Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Wed, 18 Jan 2023 20:36:36 -0800 Subject: [PATCH 20/42] remove unused side argument from side routing functions --- compiler/modules/capped_replica_bitcell_array.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/modules/capped_replica_bitcell_array.py b/compiler/modules/capped_replica_bitcell_array.py index 7745e432..77f89f69 100644 --- a/compiler/modules/capped_replica_bitcell_array.py +++ b/compiler/modules/capped_replica_bitcell_array.py @@ -463,13 +463,13 @@ class capped_replica_bitcell_array(bitcell_base_array): locs provides the offsets of the pin strip end points. """ if side in ["left", "right"]: - self.connect_vertical_side_pin(pin, side, offset) + self.connect_vertical_side_pin(pin, offset) elif side in ["top", "bottom", "bot"]: - self.connect_horizontal_side_pin(pin, side, offset) + self.connect_horizontal_side_pin(pin, offset) else: debug.error("Invalid side {}".format(side), -1) - def connect_horizontal_side_pin(self, pin, side, yoffset): + def connect_horizontal_side_pin(self, pin, yoffset): """ Used to connect vertical layers of pins to the top/bottom horizontal straps """ @@ -486,7 +486,7 @@ class capped_replica_bitcell_array(bitcell_base_array): self.add_path(pin.layer, [cell_loc, pin_loc]) - def connect_vertical_side_pin(self, pin, side, xoffset): + def connect_vertical_side_pin(self, pin, xoffset): """ Used to connect vertical layers of pins to the top/bottom vertical straps """ From 78c4ba5fc03e49aa5e365181a4e5fc959835682b Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Wed, 18 Jan 2023 21:01:30 -0800 Subject: [PATCH 21/42] clean up comments --- .../modules/capped_replica_bitcell_array.py | 22 ++++++------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/compiler/modules/capped_replica_bitcell_array.py b/compiler/modules/capped_replica_bitcell_array.py index 77f89f69..b52dd6d9 100644 --- a/compiler/modules/capped_replica_bitcell_array.py +++ b/compiler/modules/capped_replica_bitcell_array.py @@ -375,7 +375,9 @@ class capped_replica_bitcell_array(bitcell_base_array): self.connect_side_pin(pin, "right", self.right_gnd_locs[0].x) def route_unused_wordlines(self): - """ Connect the unused RBL and dummy wordlines to gnd """ + """ + Connect the unused RBL and dummy wordlines to gnd + """ # This grounds all the dummy row word lines for inst in self.dummy_row_insts: for wl_name in self.col_cap_top.get_wordline_names(): @@ -417,11 +419,6 @@ class capped_replica_bitcell_array(bitcell_base_array): top_via = contact(layer_stack=self.supply_stack, directions=("H", "H")) - -# self.add_layout_pin_rect_ends(text=name, -# layer=layer, -# start=bot_loc, -# end=top_loc) self.add_layout_pin_segment_center(text=name, layer=layer, start=bot_loc, @@ -445,10 +442,6 @@ class capped_replica_bitcell_array(bitcell_base_array): side_via = contact(layer_stack=self.supply_stack, directions=("V", "V")) -# self.add_layout_pin_rect_ends(text=name, -# layer=layer, -# start=left_loc, -# end=right_loc) self.add_layout_pin_segment_center(text=name, layer=layer, start=left_loc, @@ -459,8 +452,8 @@ class capped_replica_bitcell_array(bitcell_base_array): def connect_side_pin(self, pin, side, offset): """ - Used to connect horizontal layers of pins to the left/right straps - locs provides the offsets of the pin strip end points. + Used to connect a pin to the a horizontal or vertical strap + offset gives the location of the strap """ if side in ["left", "right"]: self.connect_vertical_side_pin(pin, offset) @@ -471,7 +464,7 @@ class capped_replica_bitcell_array(bitcell_base_array): def connect_horizontal_side_pin(self, pin, yoffset): """ - Used to connect vertical layers of pins to the top/bottom horizontal straps + Used to connect a pin to the top/bottom horizontal straps """ cell_loc = pin.center() pin_loc = vector(cell_loc.x, yoffset) @@ -485,10 +478,9 @@ class capped_replica_bitcell_array(bitcell_base_array): # Add a path to connect to the array self.add_path(pin.layer, [cell_loc, pin_loc]) - def connect_vertical_side_pin(self, pin, xoffset): """ - Used to connect vertical layers of pins to the top/bottom vertical straps + Used to connect a pin to the left/right vertical straps """ cell_loc = pin.center() pin_loc = vector(xoffset, cell_loc.y) From d460eacfcc629d9e8f5f182537da548afec80587 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Wed, 18 Jan 2023 22:43:37 -0800 Subject: [PATCH 22/42] standardize rbl arguments interface --- compiler/modules/capped_replica_bitcell_array.py | 12 ++++-------- compiler/modules/replica_bitcell_array.py | 3 +-- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/compiler/modules/capped_replica_bitcell_array.py b/compiler/modules/capped_replica_bitcell_array.py index b52dd6d9..068afcc0 100644 --- a/compiler/modules/capped_replica_bitcell_array.py +++ b/compiler/modules/capped_replica_bitcell_array.py @@ -33,22 +33,18 @@ 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 - if rbl: - self.rbl = rbl - else: - self.rbl=[1, 1 if len(self.all_ports)>1 else 0] - # This specifies which RBL to put on the left or right - # by port number + self.rbl = 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 = [0] + self.left_rbl = [] # This could be an empty list if right_rbl is not None: self.right_rbl = right_rbl else: - self.right_rbl=[1] if len(self.all_ports) > 1 else [] + self.right_rbl=[] self.rbls = self.left_rbl + self.right_rbl # Two dummy rows plus replica even if we don't add the column diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index d78181fe..105258ef 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -37,8 +37,7 @@ class replica_bitcell_array(bitcell_base_array): 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 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 From 5573c6b241b6f0d297bb55fecde143641f9ccfac Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Wed, 18 Jan 2023 22:44:32 -0800 Subject: [PATCH 23/42] fix pin shape issue --- .../modules/capped_replica_bitcell_array.py | 35 +++++++++++-------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/compiler/modules/capped_replica_bitcell_array.py b/compiler/modules/capped_replica_bitcell_array.py index 068afcc0..7d4d86f7 100644 --- a/compiler/modules/capped_replica_bitcell_array.py +++ b/compiler/modules/capped_replica_bitcell_array.py @@ -231,7 +231,7 @@ class capped_replica_bitcell_array(bitcell_base_array): self.width = self.dummy_col_insts[1].rx() self.height = self.dummy_row_insts[1].uy() - self.copy_layout_pins() + self.add_layout_pins() self.route_supplies() @@ -298,21 +298,26 @@ class capped_replica_bitcell_array(bitcell_base_array): dummy_col_offset = self.bitcell_offset.scale(len(self.right_rbl) - 1, -self.rbl[0]) + self.replica_bitcell_array_inst.lr() self.dummy_col_insts[1].place(offset=dummy_col_offset) - def copy_layout_pins(self): - excluded_pins = ["vdd", "gnd"] - excluded_pins.extend(self.unused_wordline_names) - for pin_name in self.replica_bitcell_array.get_pin_names(): - if pin_name in excluded_pins: - continue - # move pins to edges of cap cells - if "wl" in pin_name: - pin_offset = self.bitcell_offset.scale(-1, 0) - else: - pin_offset = self.bitcell_offset.scale(0, -1) + def add_layout_pins(self): + for pin_name in self.used_wordline_names + self.all_bitline_names: + pin = self.replica_bitcell_array_inst.get_pin(pin_name) - self.copy_layout_pin(instance=self.replica_bitcell_array_inst, - pin_name=pin_name, - relative_offset=pin_offset) + if "wl" in pin_name: + # wordlines + pin_offset = pin.ll().scale(0, 1) + pin_width = self.width + pin_height = pin.height() + else: + # bitlines + pin_offset = pin.ll().scale(1, 0) + pin_width = pin.width() + pin_height = self.height + + self.add_layout_pin(text=pin_name, + layer=pin.layer, + offset=pin_offset, + width=pin_width, + height=pin_height) def route_supplies(self): From ebe163c57ea86214461f60605011af5a97bb02b4 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Tue, 24 Jan 2023 11:07:52 -0800 Subject: [PATCH 24/42] fix placement bug for cap cells including wrong height from replica array --- compiler/modules/capped_replica_bitcell_array.py | 8 ++++---- compiler/modules/replica_bitcell_array.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/modules/capped_replica_bitcell_array.py b/compiler/modules/capped_replica_bitcell_array.py index 7d4d86f7..4b137e39 100644 --- a/compiler/modules/capped_replica_bitcell_array.py +++ b/compiler/modules/capped_replica_bitcell_array.py @@ -279,23 +279,23 @@ class capped_replica_bitcell_array(bitcell_base_array): # Far top dummy row (first row above array is NOT flipped if even number of rows) flip_dummy = (self.row_size + self.rbl[1]) % 2 - dummy_row_offset = self.bitcell_offset.scale(0, self.rbl[1] - 1 + flip_dummy) + self.replica_bitcell_array_inst.ul() + dummy_row_offset = self.bitcell_offset.scale(0, flip_dummy) + self.replica_bitcell_array_inst.ul() self.dummy_row_insts[1].place(offset=dummy_row_offset, mirror="MX" if flip_dummy else "R0") # Far bottom dummy row (first row below array IS flipped) flip_dummy = (self.rbl[0] + 1) % 2 - dummy_row_offset = self.bitcell_offset.scale(0, -self.rbl[0] + flip_dummy) + dummy_row_offset = self.bitcell_offset.scale(0, flip_dummy - 1) self.dummy_row_insts[0].place(offset=dummy_row_offset, mirror="MX" if flip_dummy else "R0") # Far left dummy col # Shifted down by the number of left RBLs even if we aren't adding replica column to this bitcell array - dummy_col_offset = self.bitcell_offset.scale(-len(self.left_rbl), -self.rbl[0]) + dummy_col_offset = self.bitcell_offset.scale(-1, -1) self.dummy_col_insts[0].place(offset=dummy_col_offset) # Far right dummy col # Shifted down by the number of left RBLs even if we aren't adding replica column to this bitcell array - dummy_col_offset = self.bitcell_offset.scale(len(self.right_rbl) - 1, -self.rbl[0]) + self.replica_bitcell_array_inst.lr() + dummy_col_offset = self.bitcell_offset.scale(0, -1) + self.replica_bitcell_array_inst.lr() self.dummy_col_insts[1].place(offset=dummy_col_offset) def add_layout_pins(self): diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 105258ef..b13310f3 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -255,7 +255,7 @@ class replica_bitcell_array(bitcell_base_array): self.route_supplies() - self.height = (len(self.rbls) + self.row_size) * self.cell.height + self.height = (len(self.rbl) + self.row_size) * self.cell.height self.width = (len(self.rbls) + self.column_size) * self.cell.width self.add_boundary() From 8fc93bc91a6a89f1610072be10d89028112c0829 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Tue, 24 Jan 2023 11:09:57 -0800 Subject: [PATCH 25/42] point local array to new capped array module --- compiler/modules/local_bitcell_array.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/modules/local_bitcell_array.py b/compiler/modules/local_bitcell_array.py index 30defe29..656568db 100644 --- a/compiler/modules/local_bitcell_array.py +++ b/compiler/modules/local_bitcell_array.py @@ -67,7 +67,7 @@ class local_bitcell_array(bitcell_base_array): # This is just used for names self.cell = factory.create(module_type=OPTS.bitcell) - self.bitcell_array = factory.create(module_type="replica_bitcell_array", + self.bitcell_array = factory.create(module_type="capped_replica_bitcell_array", cols=self.cols, rows=self.rows, rbl=self.rbl, From 03adf94b6a90aa8de0c5ae9e20e79ec118b4cb7e Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Thu, 26 Jan 2023 12:31:14 -0800 Subject: [PATCH 26/42] fix offsets to match original replica array, and make array translation statically sized --- .../modules/capped_replica_bitcell_array.py | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/compiler/modules/capped_replica_bitcell_array.py b/compiler/modules/capped_replica_bitcell_array.py index 4b137e39..fb4a078b 100644 --- a/compiler/modules/capped_replica_bitcell_array.py +++ b/compiler/modules/capped_replica_bitcell_array.py @@ -209,6 +209,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])) + self.unused_offset = vector(0.25, 0.25) # This is a bitcell x bitcell offset to scale self.bitcell_offset = vector(self.cell.width, self.cell.height) @@ -216,19 +217,14 @@ class capped_replica_bitcell_array(bitcell_base_array): self.row_end_offset = vector(self.cell.width, self.cell.height) # Everything is computed with the replica array - self.replica_bitcell_array_inst.place(offset=0) + self.replica_bitcell_array_inst.place(offset=self.unused_offset) self.add_end_caps() - # 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 - self.array_offset = self.bitcell_offset.scale(len(self.left_rbl), self.rbl[0]) - self.translate_all(self.array_offset.scale(-1, -1)) + # shift everything up and right to account for cap cells + self.translate_all(self.bitcell_offset.scale(-1, -1)) - # Add extra width on the left and right for the unused WLs - - self.width = self.dummy_col_insts[1].rx() + self.width = self.dummy_col_insts[1].rx() + self.unused_offset.x self.height = self.dummy_row_insts[1].uy() self.add_layout_pins() @@ -285,12 +281,12 @@ class capped_replica_bitcell_array(bitcell_base_array): # Far bottom dummy row (first row below array IS flipped) flip_dummy = (self.rbl[0] + 1) % 2 - dummy_row_offset = self.bitcell_offset.scale(0, flip_dummy - 1) + dummy_row_offset = self.bitcell_offset.scale(0, flip_dummy - 1) + self.unused_offset self.dummy_row_insts[0].place(offset=dummy_row_offset, mirror="MX" if flip_dummy else "R0") # Far left dummy col # Shifted down by the number of left RBLs even if we aren't adding replica column to this bitcell array - dummy_col_offset = self.bitcell_offset.scale(-1, -1) + dummy_col_offset = self.bitcell_offset.scale(-1, -1) + self.unused_offset self.dummy_col_insts[0].place(offset=dummy_col_offset) # Far right dummy col From cc408447b1a433cd2d427a439605a1311989db29 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Thu, 26 Jan 2023 14:14:25 -0800 Subject: [PATCH 27/42] standardize names and content of tests in the 14_* group --- ..._replica_bitcell_array_leftrbl_1rw_test.py | 40 +++++++++++++++++ ...ed_replica_bitcell_array_norbl_1rw_test.py | 40 +++++++++++++++++ ...lica_bitcell_array_rightrbl_1rw_1r_test.py | 43 +++++++++++++++++++ ..._replica_bitcell_array_leftrbl_1rw_test.py | 40 +++++++++++++++++ ...4_replica_bitcell_array_norbl_1rw_test.py} | 0 ...lica_bitcell_array_rightrbl_1rw_1r_test.py | 43 +++++++++++++++++++ ..._test.py => 14_replica_column_1rw_test.py} | 0 7 files changed, 206 insertions(+) create mode 100755 compiler/tests/14_capped_replica_bitcell_array_leftrbl_1rw_test.py create mode 100755 compiler/tests/14_capped_replica_bitcell_array_norbl_1rw_test.py create mode 100755 compiler/tests/14_capped_replica_bitcell_array_rightrbl_1rw_1r_test.py create mode 100755 compiler/tests/14_replica_bitcell_array_leftrbl_1rw_test.py rename compiler/tests/{14_replica_bitcell_array_test.py => 14_replica_bitcell_array_norbl_1rw_test.py} (100%) create mode 100755 compiler/tests/14_replica_bitcell_array_rightrbl_1rw_1r_test.py rename compiler/tests/{14_replica_column_test.py => 14_replica_column_1rw_test.py} (100%) diff --git a/compiler/tests/14_capped_replica_bitcell_array_leftrbl_1rw_test.py b/compiler/tests/14_capped_replica_bitcell_array_leftrbl_1rw_test.py new file mode 100755 index 00000000..bd810cc6 --- /dev/null +++ b/compiler/tests/14_capped_replica_bitcell_array_leftrbl_1rw_test.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2022 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_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 + + factory.reset() + debug.info(2, "Testing 4x4 array for bitcell") + a = factory.create(module_type="capped_replica_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()) diff --git a/compiler/tests/14_capped_replica_bitcell_array_norbl_1rw_test.py b/compiler/tests/14_capped_replica_bitcell_array_norbl_1rw_test.py new file mode 100755 index 00000000..6f34785f --- /dev/null +++ b/compiler/tests/14_capped_replica_bitcell_array_norbl_1rw_test.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2022 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_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 + + factory.reset() + debug.info(2, "Testing 4x4 array for bitcell") + 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()) diff --git a/compiler/tests/14_capped_replica_bitcell_array_rightrbl_1rw_1r_test.py b/compiler/tests/14_capped_replica_bitcell_array_rightrbl_1rw_1r_test.py new file mode 100755 index 00000000..68b5ef17 --- /dev/null +++ b/compiler/tests/14_capped_replica_bitcell_array_rightrbl_1rw_1r_test.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2022 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_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 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]) + 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()) diff --git a/compiler/tests/14_replica_bitcell_array_leftrbl_1rw_test.py b/compiler/tests/14_replica_bitcell_array_leftrbl_1rw_test.py new file mode 100755 index 00000000..7b66e46b --- /dev/null +++ b/compiler/tests/14_replica_bitcell_array_leftrbl_1rw_test.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2022 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_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 + + factory.reset() + debug.info(2, "Testing 4x4 array for bitcell") + a = factory.create(module_type="replica_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()) diff --git a/compiler/tests/14_replica_bitcell_array_test.py b/compiler/tests/14_replica_bitcell_array_norbl_1rw_test.py similarity index 100% rename from compiler/tests/14_replica_bitcell_array_test.py rename to compiler/tests/14_replica_bitcell_array_norbl_1rw_test.py diff --git a/compiler/tests/14_replica_bitcell_array_rightrbl_1rw_1r_test.py b/compiler/tests/14_replica_bitcell_array_rightrbl_1rw_1r_test.py new file mode 100755 index 00000000..cf908e97 --- /dev/null +++ b/compiler/tests/14_replica_bitcell_array_rightrbl_1rw_1r_test.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2022 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_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 left replica array for dp cell") + 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() + del sys.argv[1:] + header(__file__, OPTS.tech_name) + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/14_replica_column_test.py b/compiler/tests/14_replica_column_1rw_test.py similarity index 100% rename from compiler/tests/14_replica_column_test.py rename to compiler/tests/14_replica_column_1rw_test.py From 2f795f8068bed59970f3a2264627eba145f9b137 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Thu, 26 Jan 2023 17:38:24 -0800 Subject: [PATCH 28/42] fix height calculation bug for replica array --- compiler/modules/replica_bitcell_array.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index b13310f3..b6eabc3d 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -255,7 +255,7 @@ class replica_bitcell_array(bitcell_base_array): self.route_supplies() - self.height = (len(self.rbl) + self.row_size) * self.cell.height + self.height = (sum(self.rbl) + self.row_size) * self.cell.height self.width = (len(self.rbls) + self.column_size) * self.cell.width self.add_boundary() From 3dac89d041b08dfad9acc9cf3cefe49c685828c3 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Sat, 4 Feb 2023 21:06:41 -0800 Subject: [PATCH 29/42] fixing named variables passed between array modules --- .../modules/capped_replica_bitcell_array.py | 22 +++++++++++++++---- compiler/modules/local_bitcell_array.py | 18 +++++++-------- compiler/modules/replica_bitcell_array.py | 5 ++--- 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/compiler/modules/capped_replica_bitcell_array.py b/compiler/modules/capped_replica_bitcell_array.py index fb4a078b..8f7fb28d 100644 --- a/compiler/modules/capped_replica_bitcell_array.py +++ b/compiler/modules/capped_replica_bitcell_array.py @@ -155,15 +155,28 @@ class capped_replica_bitcell_array(bitcell_base_array): self.add_pin("gnd", "GROUND") def add_bitline_pins(self): - self.all_bitline_names = self.replica_bitcell_array.all_bitline_names - self.replica_array_bitline_names = self.replica_bitcell_array.all_bitline_names + # some of these are just included for compatibility with modules instantiating this module + self.bitcell_bitline_names = self.replica_bitcell_array.bitcell_bitline_names + self.all_bitcell_bitline_names = self.replica_bitcell_array.all_bitcell_bitline_names + self.rbl_bitline_names = self.replica_bitcell_array.rbl_bitline_names + self.all_rbl_bitline_names = self.replica_bitcell_array.all_rbl_bitline_names - self.add_pin_list(self.replica_array_bitline_names, "INOUT") + self.bitline_names = self.replica_bitcell_array.bitline_names + self.all_bitline_names = self.replica_bitcell_array.all_bitline_names + + self.add_pin_list(self.all_bitline_names, "INOUT") def add_wordline_pins(self): + # some of these are just included for compatibility with modules instantiating this module + self.rbl_wordline_names = self.replica_bitcell_array.rbl_wordline_names + self.all_rbl_wordline_names = self.replica_bitcell_array.all_rbl_wordline_names + self.bitcell_wordline_names = self.replica_bitcell_array.wordline_names + self.all_bitcell_wordline_names = self.replica_bitcell_array.all_wordline_names + self.used_wordline_names = self.replica_bitcell_array.used_wordline_names self.unused_wordline_names = self.replica_bitcell_array.unused_wordline_names self.replica_array_wordline_names = self.replica_bitcell_array.all_wordline_names + self.replica_array_all_wordline_names = self.replica_bitcell_array.wordline_names self.replica_array_wordline_names_with_grounded_wls = ["gnd" if x in self.unused_wordline_names else x for x in self.replica_array_wordline_names] self.all_wordline_names = [] @@ -180,7 +193,7 @@ class capped_replica_bitcell_array(bitcell_base_array): # Main array self.replica_bitcell_array_inst=self.add_inst(name="replica_bitcell_array", mod=self.replica_bitcell_array) - self.connect_inst(self.replica_array_bitline_names + self.replica_array_wordline_names_with_grounded_wls + self.supplies) + self.connect_inst(self.all_bitline_names + self.replica_array_wordline_names_with_grounded_wls + self.supplies) # Top/bottom dummy rows or col caps self.dummy_row_insts = [] @@ -243,6 +256,7 @@ class capped_replica_bitcell_array(bitcell_base_array): self.DRC_LVS() + # TODO: I think I gotta offset these to account for the stupid instances not knowing where they are def get_main_array_top(self): return self.replica_bitcell_array_inst.get_main_array_top() diff --git a/compiler/modules/local_bitcell_array.py b/compiler/modules/local_bitcell_array.py index 656568db..00206730 100644 --- a/compiler/modules/local_bitcell_array.py +++ b/compiler/modules/local_bitcell_array.py @@ -19,7 +19,7 @@ class local_bitcell_array(bitcell_base_array): 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, rbl, left_rbl=[], right_rbl=[], name=""): + 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) debug.info(2, "Creating {0} {1}x{2} rbl: {3} left_rbl: {4} right_rbl: {5}".format(name, rows, @@ -84,11 +84,11 @@ class local_bitcell_array(bitcell_base_array): # Inputs to the bitcell array (by port) self.array_wordline_inputs = [] - self.wordline_names = self.bitcell_array.wordline_names - self.all_wordline_names = self.bitcell_array.all_wordline_names + self.wordline_names = self.bitcell_array.bitcell_wordline_names + self.all_wordline_names = self.bitcell_array.bitcell_all_wordline_names - self.bitline_names = self.bitcell_array.bitline_names - self.all_bitline_names = self.bitcell_array.all_bitline_names + self.bitline_names = self.bitcell_array.bitcell_bitline_names + self.all_bitline_names = self.bitcell_array.all_bitcell_bitline_names self.rbl_wordline_names = self.bitcell_array.rbl_wordline_names self.all_rbl_wordline_names = self.bitcell_array.all_rbl_wordline_names @@ -163,7 +163,7 @@ class local_bitcell_array(bitcell_base_array): # FIXME: Replace this with a tech specific parameter driver_to_array_spacing = 3 * self.m3_pitch - wl_offset = vector(0, self.bitcell_array.get_replica_bottom()) + wl_offset = vector(0, self.bitcell_array.get_replica_bottom()) # look for offset problems here self.wl_insts[0].place(wl_offset) bitcell_array_offset = vector(self.wl_insts[0].rx() + driver_to_array_spacing, 0) @@ -171,7 +171,7 @@ class local_bitcell_array(bitcell_base_array): if len(self.all_ports) > 1: 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 + self.cell.height) # look for offset problems here self.wl_insts[1].place(wl_offset, mirror="XY") @@ -273,7 +273,7 @@ class local_bitcell_array(bitcell_base_array): def get_main_array_right(self): return self.bitcell_array_inst.lx() + self.bitcell_array.get_main_array_right() - def get_column_offsets(self): + def get_column_offsets(self): # TODO: copy this style when fixing getters in capped_replica_bitcell_array.py """ Return an array of the x offsets of all the regular bits """ @@ -294,7 +294,7 @@ class local_bitcell_array(bitcell_base_array): self.bitcell_array.graph_exclude_replica_col_bits() - def get_cell_name(self, inst_name, row, col): + def get_cell_name(self, inst_name, row, col): # TODO: no shot this'll work... """Gets the spice name of the target bitcell.""" return self.bitcell_array.get_cell_name(inst_name + "{}x".format(OPTS.hier_seperator) + self.bitcell_array_inst.name, row, col) diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index b6eabc3d..2211bd55 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -182,10 +182,9 @@ class replica_bitcell_array(bitcell_base_array): self.all_rbl_wordline_names = [x for sl in self.rbl_wordline_names for x in sl] + self.bitcell_wordline_names = self.bitcell_array.wordline_names self.all_bitcell_wordline_names = self.bitcell_array.all_wordline_names - - # All wordlines including RBL - self.all_wordline_names = [] +# All wordlines including RBL self.all_wordline_names = [] for bit in range(self.rbl[0]): self.all_wordline_names.extend(self.rbl_wordline_names[bit]) self.all_wordline_names.extend(self.all_bitcell_wordline_names) From 92a9a1729e5b8a085fee5518944dfc2dd0bddf39 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Mon, 6 Feb 2023 19:19:02 -0800 Subject: [PATCH 30/42] untested update to get_cell_name function used by characterizer --- compiler/modules/capped_replica_bitcell_array.py | 2 +- compiler/modules/local_bitcell_array.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/modules/capped_replica_bitcell_array.py b/compiler/modules/capped_replica_bitcell_array.py index 8f7fb28d..6293c7c4 100644 --- a/compiler/modules/capped_replica_bitcell_array.py +++ b/compiler/modules/capped_replica_bitcell_array.py @@ -551,7 +551,7 @@ class capped_replica_bitcell_array(bitcell_base_array): """ Gets the spice name of the target bitcell. """ - return self.bitcell_array.get_cell_name(inst_name + "{}x".format(OPTS.hier_seperator) + self.bitcell_array_inst.name, row, col) + return self.replica_bitcell_array.get_cell_name(inst_name + "{}x".format(OPTS.hier_seperator) + self.replica_bitcell_array_inst.name, row, col) def clear_exclude_bits(self): """ diff --git a/compiler/modules/local_bitcell_array.py b/compiler/modules/local_bitcell_array.py index 00206730..50ab945d 100644 --- a/compiler/modules/local_bitcell_array.py +++ b/compiler/modules/local_bitcell_array.py @@ -294,7 +294,7 @@ class local_bitcell_array(bitcell_base_array): self.bitcell_array.graph_exclude_replica_col_bits() - def get_cell_name(self, inst_name, row, col): # TODO: no shot this'll work... + def get_cell_name(self, inst_name, row, col): """Gets the spice name of the target bitcell.""" return self.bitcell_array.get_cell_name(inst_name + "{}x".format(OPTS.hier_seperator) + self.bitcell_array_inst.name, row, col) From 4a22c5c56fc1abd296feb9fbad96249ba53643f9 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Mon, 6 Feb 2023 19:40:37 -0800 Subject: [PATCH 31/42] add instance offset to capped array offset getters --- .../modules/capped_replica_bitcell_array.py | 24 +++++++++++-------- compiler/modules/local_bitcell_array.py | 2 +- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/compiler/modules/capped_replica_bitcell_array.py b/compiler/modules/capped_replica_bitcell_array.py index 6293c7c4..c1f9c83f 100644 --- a/compiler/modules/capped_replica_bitcell_array.py +++ b/compiler/modules/capped_replica_bitcell_array.py @@ -256,33 +256,37 @@ class capped_replica_bitcell_array(bitcell_base_array): self.DRC_LVS() - # TODO: I think I gotta offset these to account for the stupid instances not knowing where they are def get_main_array_top(self): - return self.replica_bitcell_array_inst.get_main_array_top() + return self.replica_bitcell_array_inst.by() + self.replica_bitcell_array_inst.get_main_array_top() def get_main_array_bottom(self): - return self.replica_bitcell_array_inst.get_main_array_bottom() + return self.replica_bitcell_array_inst.by() + self.replica_bitcell_array_inst.get_main_array_bottom() def get_main_array_left(self): - return self.replica_bitcell_array_inst.get_main_array_left() + return self.replica_bitcell_array_inst.lx() + self.replica_bitcell_array_inst.get_main_array_left() def get_main_array_right(self): - return self.replica_bitcell_array_inst.get_main_array_right() + return self.replica_bitcell_array_inst.lx() + self.replica_bitcell_array_inst.get_main_array_right() def get_replica_top(self): - return self.replica_bitcell_array_inst.get_replica_top() + return self.replica_bitcell_array_inst.by() + self.replica_bitcell_array_inst.get_replica_top() def get_replica_bottom(self): - return self.replica_bitcell_array_inst.get_replica_bottom() + return self.replica_bitcell_array_inst.by() + self.replica_bitcell_array_inst.get_replica_bottom() def get_replica_left(self): - return self.replica_bitcell_array_inst.get_replica_left() + return self.replica_bitcell_array_inst.lx() + self.replica_bitcell_array_inst.get_replica_left() def get_replica_right(self): - return self.replica_bitcell_array_inst.get_replica_right() + return self.replica_bitcell_array_inst.lx() + self.replica_bitcell_array_inst.get_replica_right() def get_column_offsets(self): - return self.replica_bitcell_array_inst.get_column_offsets() + """ + Return an array of the x offsets of all the regular bits + """ + # must add the offset of the instance + offsets = [self.replica_bitcell_array_inst.lx() + x for x in self.replica_bitcell_array.get_column_offsets()] + return offsets def add_end_caps(self): """ Add dummy cells or end caps around the array """ diff --git a/compiler/modules/local_bitcell_array.py b/compiler/modules/local_bitcell_array.py index 50ab945d..ef7da9af 100644 --- a/compiler/modules/local_bitcell_array.py +++ b/compiler/modules/local_bitcell_array.py @@ -273,7 +273,7 @@ class local_bitcell_array(bitcell_base_array): def get_main_array_right(self): return self.bitcell_array_inst.lx() + self.bitcell_array.get_main_array_right() - def get_column_offsets(self): # TODO: copy this style when fixing getters in capped_replica_bitcell_array.py + def get_column_offsets(self): """ Return an array of the x offsets of all the regular bits """ From c256a5eb440857d6566c00ff0043264a3dd3f893 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Mon, 6 Feb 2023 19:57:42 -0800 Subject: [PATCH 32/42] fix coppied functions from replica array to work correctly in capped array --- compiler/modules/capped_replica_bitcell_array.py | 8 +++----- compiler/modules/local_bitcell_array.py | 4 ++-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/compiler/modules/capped_replica_bitcell_array.py b/compiler/modules/capped_replica_bitcell_array.py index c1f9c83f..1814e310 100644 --- a/compiler/modules/capped_replica_bitcell_array.py +++ b/compiler/modules/capped_replica_bitcell_array.py @@ -541,15 +541,13 @@ class capped_replica_bitcell_array(bitcell_base_array): """ Excludes bits in column from being added to graph except target """ - self.bitcell_array.graph_exclude_bits(targ_row, targ_col) + self.replica_bitcell_array.graph_exclude_bits(targ_row, targ_col) def graph_exclude_replica_col_bits(self): """ Exclude all replica/dummy cells in the replica columns except the replica bit. """ - - for port in self.left_rbl + self.right_rbl: - self.replica_columns[port].exclude_all_but_replica() + self.replica_bitcell_array.graph_exclude_replica_col_bits() def get_cell_name(self, inst_name, row, col): """ @@ -561,4 +559,4 @@ class capped_replica_bitcell_array(bitcell_base_array): """ Clears the bit exclusions """ - self.bitcell_array.init_graph_params() + self.replica_bitcell_array.clear_exclude_bits() diff --git a/compiler/modules/local_bitcell_array.py b/compiler/modules/local_bitcell_array.py index ef7da9af..b9823e9d 100644 --- a/compiler/modules/local_bitcell_array.py +++ b/compiler/modules/local_bitcell_array.py @@ -163,7 +163,7 @@ class local_bitcell_array(bitcell_base_array): # FIXME: Replace this with a tech specific parameter driver_to_array_spacing = 3 * self.m3_pitch - wl_offset = vector(0, self.bitcell_array.get_replica_bottom()) # look for offset problems here + wl_offset = vector(0, self.bitcell_array.get_replica_bottom()) self.wl_insts[0].place(wl_offset) bitcell_array_offset = vector(self.wl_insts[0].rx() + driver_to_array_spacing, 0) @@ -171,7 +171,7 @@ class local_bitcell_array(bitcell_base_array): if len(self.all_ports) > 1: 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) # look for offset problems here + self.bitcell_array.get_replica_bottom() + self.wl_array.height + self.cell.height) self.wl_insts[1].place(wl_offset, mirror="XY") From 796b1913cf484b0c2b2cf8368a9d33ccb3241d53 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Mon, 6 Feb 2023 20:01:49 -0800 Subject: [PATCH 33/42] fix typo in wordline var --- compiler/modules/local_bitcell_array.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/modules/local_bitcell_array.py b/compiler/modules/local_bitcell_array.py index b9823e9d..e72a9d6e 100644 --- a/compiler/modules/local_bitcell_array.py +++ b/compiler/modules/local_bitcell_array.py @@ -85,7 +85,7 @@ class local_bitcell_array(bitcell_base_array): self.array_wordline_inputs = [] self.wordline_names = self.bitcell_array.bitcell_wordline_names - self.all_wordline_names = self.bitcell_array.bitcell_all_wordline_names + self.all_wordline_names = self.bitcell_array.all_bitcell_wordline_names self.bitline_names = self.bitcell_array.bitcell_bitline_names self.all_bitline_names = self.bitcell_array.all_bitcell_bitline_names From 2948b08e6604e0bbf198014df99e2b70b5cc251a Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Mon, 6 Feb 2023 20:04:54 -0800 Subject: [PATCH 34/42] copy rbl default values logic from lower array modules --- compiler/modules/local_bitcell_array.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/compiler/modules/local_bitcell_array.py b/compiler/modules/local_bitcell_array.py index e72a9d6e..f52248b2 100644 --- a/compiler/modules/local_bitcell_array.py +++ b/compiler/modules/local_bitcell_array.py @@ -30,9 +30,19 @@ 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 - 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=[] debug.check(len(self.all_ports) < 3, "Local bitcell array only supports dual port or less.") From 8d6d8f2f8ca8f970e70cfebca3ca96f29c7ea859 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Tue, 7 Feb 2023 11:32:02 -0800 Subject: [PATCH 35/42] revert variable names to those inherited from bitcell base array --- .../modules/capped_replica_bitcell_array.py | 41 +++++++++--------- compiler/modules/local_bitcell_array.py | 8 ++-- compiler/modules/replica_bitcell_array.py | 42 ++++++++++--------- 3 files changed, 45 insertions(+), 46 deletions(-) diff --git a/compiler/modules/capped_replica_bitcell_array.py b/compiler/modules/capped_replica_bitcell_array.py index 1814e310..def4ab2a 100644 --- a/compiler/modules/capped_replica_bitcell_array.py +++ b/compiler/modules/capped_replica_bitcell_array.py @@ -155,34 +155,31 @@ class capped_replica_bitcell_array(bitcell_base_array): self.add_pin("gnd", "GROUND") def add_bitline_pins(self): - # some of these are just included for compatibility with modules instantiating this module - self.bitcell_bitline_names = self.replica_bitcell_array.bitcell_bitline_names - self.all_bitcell_bitline_names = self.replica_bitcell_array.all_bitcell_bitline_names + # these four are only included for compatibility with other modules + self.bitline_names = self.replica_bitcell_array.bitline_names + self.all_bitline_names = self.replica_bitcell_array.all_bitline_names self.rbl_bitline_names = self.replica_bitcell_array.rbl_bitline_names self.all_rbl_bitline_names = self.replica_bitcell_array.all_rbl_bitline_names - self.bitline_names = self.replica_bitcell_array.bitline_names - self.all_bitline_names = self.replica_bitcell_array.all_bitline_names - - self.add_pin_list(self.all_bitline_names, "INOUT") + # this one is actually used (obviously) + self.bitline_pin_list = self.replica_bitcell_array.bitline_pin_list + self.add_pin_list(self.bitline_pin_list, "INOUT") def add_wordline_pins(self): # some of these are just included for compatibility with modules instantiating this module self.rbl_wordline_names = self.replica_bitcell_array.rbl_wordline_names self.all_rbl_wordline_names = self.replica_bitcell_array.all_rbl_wordline_names - self.bitcell_wordline_names = self.replica_bitcell_array.wordline_names - self.all_bitcell_wordline_names = self.replica_bitcell_array.all_wordline_names + self.wordline_names = self.replica_bitcell_array.wordline_names + self.all_wordline_names = self.replica_bitcell_array.all_wordline_names self.used_wordline_names = self.replica_bitcell_array.used_wordline_names self.unused_wordline_names = self.replica_bitcell_array.unused_wordline_names - self.replica_array_wordline_names = self.replica_bitcell_array.all_wordline_names - self.replica_array_all_wordline_names = self.replica_bitcell_array.wordline_names - self.replica_array_wordline_names_with_grounded_wls = ["gnd" if x in self.unused_wordline_names else x for x in self.replica_array_wordline_names] + self.replica_array_wordline_names_with_grounded_wls = ["gnd" if x in self.unused_wordline_names else x for x in self.replica_bitcell_array.wordline_pin_list] - self.all_wordline_names = [] - self.all_wordline_names.extend(["gnd"] * len(self.col_cap_top.get_wordline_names())) - self.all_wordline_names.extend(self.replica_array_wordline_names_with_grounded_wls) - self.all_wordline_names.extend(["gnd"] * len(self.col_cap_bottom.get_wordline_names())) + self.wordline_pin_list = [] + self.wordline_pin_list.extend(["gnd"] * len(self.col_cap_top.get_wordline_names())) + self.wordline_pin_list.extend(self.replica_array_wordline_names_with_grounded_wls) + self.wordline_pin_list.extend(["gnd"] * len(self.col_cap_bottom.get_wordline_names())) self.add_pin_list(self.used_wordline_names, "INPUT") @@ -193,25 +190,25 @@ class capped_replica_bitcell_array(bitcell_base_array): # Main array self.replica_bitcell_array_inst=self.add_inst(name="replica_bitcell_array", mod=self.replica_bitcell_array) - self.connect_inst(self.all_bitline_names + self.replica_array_wordline_names_with_grounded_wls + self.supplies) + self.connect_inst(self.bitline_pin_list + self.replica_array_wordline_names_with_grounded_wls + self.supplies) # Top/bottom dummy rows or col caps self.dummy_row_insts = [] self.dummy_row_insts.append(self.add_inst(name="dummy_row_bot", mod=self.col_cap_bottom)) - self.connect_inst(self.all_bitline_names + ["gnd"] * len(self.col_cap_bottom.get_wordline_names()) + self.supplies) + self.connect_inst(self.bitline_pin_list + ["gnd"] * len(self.col_cap_bottom.get_wordline_names()) + self.supplies) self.dummy_row_insts.append(self.add_inst(name="dummy_row_top", mod=self.col_cap_top)) - self.connect_inst(self.all_bitline_names + ["gnd"] * len(self.col_cap_top.get_wordline_names()) + self.supplies) + self.connect_inst(self.bitline_pin_list + ["gnd"] * len(self.col_cap_top.get_wordline_names()) + self.supplies) # Left/right Dummy columns self.dummy_col_insts = [] self.dummy_col_insts.append(self.add_inst(name="dummy_col_left", mod=self.row_cap_left)) - self.connect_inst(["dummy_left_" + bl for bl in self.row_cap_left.all_bitline_names] + self.all_wordline_names + self.supplies) + self.connect_inst(["dummy_left_" + bl for bl in self.row_cap_left.all_bitline_names] + self.wordline_pin_list + self.supplies) self.dummy_col_insts.append(self.add_inst(name="dummy_col_right", mod=self.row_cap_right)) - self.connect_inst(["dummy_right_" + bl for bl in self.row_cap_right.all_bitline_names] + self.all_wordline_names + self.supplies) + self.connect_inst(["dummy_right_" + bl for bl in self.row_cap_right.all_bitline_names] + self.wordline_pin_list + self.supplies) # bitcell array needed for some offset calculations self.bitcell_array_inst = self.replica_bitcell_array.bitcell_array_inst @@ -313,7 +310,7 @@ class capped_replica_bitcell_array(bitcell_base_array): self.dummy_col_insts[1].place(offset=dummy_col_offset) def add_layout_pins(self): - for pin_name in self.used_wordline_names + self.all_bitline_names: + for pin_name in self.used_wordline_names + self.bitline_pin_list: pin = self.replica_bitcell_array_inst.get_pin(pin_name) if "wl" in pin_name: diff --git a/compiler/modules/local_bitcell_array.py b/compiler/modules/local_bitcell_array.py index f52248b2..def5a78f 100644 --- a/compiler/modules/local_bitcell_array.py +++ b/compiler/modules/local_bitcell_array.py @@ -94,11 +94,11 @@ class local_bitcell_array(bitcell_base_array): # Inputs to the bitcell array (by port) self.array_wordline_inputs = [] - self.wordline_names = self.bitcell_array.bitcell_wordline_names - self.all_wordline_names = self.bitcell_array.all_bitcell_wordline_names + self.wordline_names = self.bitcell_array.wordline_names + self.all_wordline_names = self.bitcell_array.all_wordline_names - self.bitline_names = self.bitcell_array.bitcell_bitline_names - self.all_bitline_names = self.bitcell_array.all_bitcell_bitline_names + self.bitline_names = self.bitcell_array.bitline_names + self.all_bitline_names = self.bitcell_array.all_bitline_names self.rbl_wordline_names = self.bitcell_array.rbl_wordline_names self.all_rbl_wordline_names = self.bitcell_array.all_rbl_wordline_names diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 2211bd55..e10dcbd2 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -157,18 +157,18 @@ class replica_bitcell_array(bitcell_base_array): # Make a flat list too self.all_rbl_bitline_names = [x for sl in self.rbl_bitline_names for x in sl] - self.bitcell_bitline_names = self.bitcell_array.bitline_names + self.bitline_names = self.bitcell_array.bitline_names # Make a flat list too - self.all_bitcell_bitline_names = [x for sl in zip(*self.bitcell_bitline_names) for x in sl] + self.all_bitline_names = [x for sl in zip(*self.bitline_names) for x in sl] - self.all_bitline_names = [] + self.bitline_pin_list = [] for port in self.left_rbl: - self.all_bitline_names.extend(self.rbl_bitline_names[port]) - self.all_bitline_names.extend(self.all_bitcell_bitline_names) + self.bitline_pin_list.extend(self.rbl_bitline_names[port]) + self.bitline_pin_list.extend(self.all_bitline_names) for port in self.right_rbl: - self.all_bitline_names.extend(self.rbl_bitline_names[port]) + self.bitline_pin_list.extend(self.rbl_bitline_names[port]) - self.add_pin_list(self.all_bitline_names, "INOUT") + self.add_pin_list(self.bitline_pin_list, "INOUT") def add_wordline_pins(self): # Unused wordlines are connected to ground at the next level of hierarchy @@ -182,23 +182,25 @@ class replica_bitcell_array(bitcell_base_array): self.all_rbl_wordline_names = [x for sl in self.rbl_wordline_names for x in sl] - self.bitcell_wordline_names = self.bitcell_array.wordline_names - self.all_bitcell_wordline_names = self.bitcell_array.all_wordline_names -# All wordlines including RBL self.all_wordline_names = [] + self.wordline_names = self.bitcell_array.wordline_names + self.all_wordline_names = self.bitcell_array.all_wordline_names + + # All wordlines including RBL + self.wordline_pin_list = [] for bit in range(self.rbl[0]): - self.all_wordline_names.extend(self.rbl_wordline_names[bit]) - self.all_wordline_names.extend(self.all_bitcell_wordline_names) + self.wordline_pin_list.extend(self.rbl_wordline_names[bit]) + self.wordline_pin_list.extend(self.all_wordline_names) for bit in range(self.rbl[1]): - self.all_wordline_names.extend(self.rbl_wordline_names[self.rbl[0] + bit]) + self.wordline_pin_list.extend(self.rbl_wordline_names[self.rbl[0] + bit]) self.used_wordline_names = [] for port in range(self.rbl[0]): self.used_wordline_names.append(self.rbl_wordline_names[port][port]) - self.used_wordline_names.extend(self.all_bitcell_wordline_names) + self.used_wordline_names.extend(self.all_wordline_names) for port in range(self.rbl[0], self.rbl[0] + self.rbl[1]): self.used_wordline_names.append(self.rbl_wordline_names[port][port]) - self.add_pin_list(self.all_wordline_names, "INPUT") + self.add_pin_list(self.wordline_pin_list, "INPUT") def create_instances(self): """ Create the module instances used in this design """ @@ -207,7 +209,7 @@ class replica_bitcell_array(bitcell_base_array): # Main array self.bitcell_array_inst=self.add_inst(name="bitcell_array", mod=self.bitcell_array) - self.connect_inst(self.all_bitcell_bitline_names + self.all_bitcell_wordline_names + self.supplies) + self.connect_inst(self.all_bitline_names + self.all_wordline_names + self.supplies) # Replica columns self.replica_col_insts = [] @@ -215,7 +217,7 @@ class replica_bitcell_array(bitcell_base_array): if port in self.rbls: self.replica_col_insts.append(self.add_inst(name="replica_col_{}".format(port), mod=self.replica_columns[port])) - self.connect_inst(self.rbl_bitline_names[port] + self.all_wordline_names + self.supplies) + self.connect_inst(self.rbl_bitline_names[port] + self.wordline_pin_list + self.supplies) else: self.replica_col_insts.append(None) @@ -225,7 +227,7 @@ class replica_bitcell_array(bitcell_base_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_bitcell_bitline_names + self.rbl_wordline_names[port] + self.supplies) + self.connect_inst(self.all_bitline_names + self.rbl_wordline_names[port] + self.supplies) def create_layout(self): @@ -330,7 +332,7 @@ class replica_bitcell_array(bitcell_base_array): # All wordlines # Main array wl - for pin_name in self.all_bitcell_wordline_names: + for pin_name in self.all_wordline_names: pin_list = self.bitcell_array_inst.get_pins(pin_name) for pin in pin_list: self.add_layout_pin(text=pin_name, @@ -351,7 +353,7 @@ class replica_bitcell_array(bitcell_base_array): height=pin.height()) # Main array bl/br - for pin_name in self.all_bitcell_bitline_names: + for pin_name in self.all_bitline_names: pin_list = self.bitcell_array_inst.get_pins(pin_name) for pin in pin_list: self.add_layout_pin(text=pin_name, From 2565305158eeb409628f519eff0d89ad3a129cee Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Tue, 7 Feb 2023 11:58:11 -0800 Subject: [PATCH 36/42] fix positional getters --- .../modules/capped_replica_bitcell_array.py | 18 ++++++++++-------- compiler/modules/replica_bitcell_array.py | 16 ---------------- 2 files changed, 10 insertions(+), 24 deletions(-) diff --git a/compiler/modules/capped_replica_bitcell_array.py b/compiler/modules/capped_replica_bitcell_array.py index def4ab2a..d1f5d005 100644 --- a/compiler/modules/capped_replica_bitcell_array.py +++ b/compiler/modules/capped_replica_bitcell_array.py @@ -254,28 +254,30 @@ class capped_replica_bitcell_array(bitcell_base_array): self.DRC_LVS() def get_main_array_top(self): - return self.replica_bitcell_array_inst.by() + self.replica_bitcell_array_inst.get_main_array_top() + return self.replica_bitcell_array_inst.by() + self.replica_bitcell_array.get_main_array_top() def get_main_array_bottom(self): - return self.replica_bitcell_array_inst.by() + self.replica_bitcell_array_inst.get_main_array_bottom() + return self.replica_bitcell_array_inst.by() + self.replica_bitcell_array.get_main_array_bottom() def get_main_array_left(self): - return self.replica_bitcell_array_inst.lx() + self.replica_bitcell_array_inst.get_main_array_left() + return self.replica_bitcell_array_inst.lx() + self.replica_bitcell_array.get_main_array_left() def get_main_array_right(self): - return self.replica_bitcell_array_inst.lx() + self.replica_bitcell_array_inst.get_main_array_right() + return self.replica_bitcell_array_inst.lx() + self.replica_bitcell_array.get_main_array_right() + # FIXME: these names need to be changed to reflect what they're actually returning def get_replica_top(self): - return self.replica_bitcell_array_inst.by() + self.replica_bitcell_array_inst.get_replica_top() + return self.dummy_row_insts[1].by() def get_replica_bottom(self): - return self.replica_bitcell_array_inst.by() + self.replica_bitcell_array_inst.get_replica_bottom() + return self.dummy_row_insts[0].uy() def get_replica_left(self): - return self.replica_bitcell_array_inst.lx() + self.replica_bitcell_array_inst.get_replica_left() + return self.dummy_col_insts[0].lx() def get_replica_right(self): - return self.replica_bitcell_array_inst.lx() + self.replica_bitcell_array_inst.get_replica_right() + return self.dummy_col_insts[1].rx() + def get_column_offsets(self): """ diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index e10dcbd2..3a3dca4f 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -279,22 +279,6 @@ class replica_bitcell_array(bitcell_base_array): """ Return the right of the main bitcell array. """ return self.bitcell_array_inst.rx() - def get_replica_top(self): - """ Return the top of all replica columns. """ - return self.dummy_row_insts[1].by() - - def get_replica_bottom(self): - """ Return the bottom of all replica columns. """ - return self.dummy_row_insts[0].uy() - - def get_replica_left(self): - """ Return the left of all replica columns. """ - return self.dummy_col_insts[0].lx() - - def get_replica_right(self): - """ Return the right of all replica columns. """ - return self.dummy_col_insts[1].rx() - def get_column_offsets(self): """ Return an array of the x offsets of all the regular bits From 51a7161cd762be3780850f7c4ddbcfabb9131e2f Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Tue, 14 Feb 2023 10:59:00 -0800 Subject: [PATCH 37/42] fix mirroring of cap cells in cap rows --- compiler/modules/capped_replica_bitcell_array.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/modules/capped_replica_bitcell_array.py b/compiler/modules/capped_replica_bitcell_array.py index d1f5d005..9a452d3d 100644 --- a/compiler/modules/capped_replica_bitcell_array.py +++ b/compiler/modules/capped_replica_bitcell_array.py @@ -103,7 +103,7 @@ class capped_replica_bitcell_array(bitcell_base_array): cols=self.column_size + len(self.rbls), rows=1, # dummy column + left replica column(s) - column_offset=1 + len(self.left_rbl), + column_offset=1, mirror=0, location="top") @@ -111,7 +111,7 @@ class capped_replica_bitcell_array(bitcell_base_array): cols=self.column_size + len(self.rbls), rows=1, # dummy column + left replica column(s) - column_offset=1 + len(self.left_rbl), + column_offset=1, mirror=0, location="bottom") From 52dcd81a083a9fd22aa49846220b91a6b66edcd9 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Mon, 20 Feb 2023 17:28:24 -0800 Subject: [PATCH 38/42] use left_rbl instead of rbl to calculate replica column mirroring (column offset) --- compiler/modules/replica_bitcell_array.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 3a3dca4f..c6919770 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -101,7 +101,7 @@ class replica_bitcell_array(bitcell_base_array): # the array. # These go from the top (where the bitcell array starts ) down replica_bit = self.rbl[0] - port - 1 - column_offset = self.rbl[0] + column_offset = len(self.left_rbl) elif port in self.right_rbl: @@ -109,7 +109,7 @@ class replica_bitcell_array(bitcell_base_array): # the array. # These go from the bottom up replica_bit = self.rbl[0] + self.row_size + port - 1 - column_offset = self.rbl[0] + self.column_size + 1 + column_offset = len(self.left_rbl) + self.column_size + 1 else: continue From ad4b4f66dc1381bb0a2b6164a5f2e16f0b713a78 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Tue, 21 Feb 2023 09:58:46 -0800 Subject: [PATCH 39/42] use capped array to create banks --- compiler/modules/bank.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 80b03bb2..8cf92961 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -374,9 +374,12 @@ class bank(design): cols=cols, rows=self.num_rows) else: - self.bitcell_array = factory.create(module_type="replica_bitcell_array", + self.bitcell_array = factory.create(module_type="capped_replica_bitcell_array", cols=self.num_cols + self.num_spare_cols, - rows=self.num_rows) + 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 []) self.port_address = [] for port in self.all_ports: From e90964fbda816342949189795de40502d17d7645 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Tue, 21 Feb 2023 14:04:31 -0800 Subject: [PATCH 40/42] update copyright --- compiler/modules/capped_replica_bitcell_array.py | 2 +- .../14_capped_replica_bitcell_array_bothrbl_1rw_1r_test.py | 2 +- .../14_capped_replica_bitcell_array_leftrbl_1rw_1r_test.py | 2 +- .../tests/14_capped_replica_bitcell_array_leftrbl_1rw_test.py | 2 +- .../tests/14_capped_replica_bitcell_array_norbl_1rw_1r_test.py | 2 +- .../tests/14_capped_replica_bitcell_array_norbl_1rw_test.py | 2 +- .../14_capped_replica_bitcell_array_rightrbl_1rw_1r_test.py | 2 +- compiler/tests/14_replica_bitcell_array_leftrbl_1rw_test.py | 2 +- compiler/tests/14_replica_bitcell_array_rightrbl_1rw_1r_test.py | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler/modules/capped_replica_bitcell_array.py b/compiler/modules/capped_replica_bitcell_array.py index 9a452d3d..65193bab 100644 --- a/compiler/modules/capped_replica_bitcell_array.py +++ b/compiler/modules/capped_replica_bitcell_array.py @@ -1,6 +1,6 @@ # See LICENSE for licensing information. # -# Copyright (c) 2016-2021 Regents of the University of California +# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz # All rights reserved. # diff --git a/compiler/tests/14_capped_replica_bitcell_array_bothrbl_1rw_1r_test.py b/compiler/tests/14_capped_replica_bitcell_array_bothrbl_1rw_1r_test.py index 55157f93..a2f57e45 100755 --- a/compiler/tests/14_capped_replica_bitcell_array_bothrbl_1rw_1r_test.py +++ b/compiler/tests/14_capped_replica_bitcell_array_bothrbl_1rw_1r_test.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # See LICENSE for licensing information. # -# Copyright (c) 2016-2022 Regents of the University of California, Santa Cruz +# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz # All rights reserved. # import sys, os diff --git a/compiler/tests/14_capped_replica_bitcell_array_leftrbl_1rw_1r_test.py b/compiler/tests/14_capped_replica_bitcell_array_leftrbl_1rw_1r_test.py index 663f4950..3e1bd805 100755 --- a/compiler/tests/14_capped_replica_bitcell_array_leftrbl_1rw_1r_test.py +++ b/compiler/tests/14_capped_replica_bitcell_array_leftrbl_1rw_1r_test.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # See LICENSE for licensing information. # -# Copyright (c) 2016-2022 Regents of the University of California, Santa Cruz +# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz # All rights reserved. # import sys, os diff --git a/compiler/tests/14_capped_replica_bitcell_array_leftrbl_1rw_test.py b/compiler/tests/14_capped_replica_bitcell_array_leftrbl_1rw_test.py index bd810cc6..b4ba91d1 100755 --- a/compiler/tests/14_capped_replica_bitcell_array_leftrbl_1rw_test.py +++ b/compiler/tests/14_capped_replica_bitcell_array_leftrbl_1rw_test.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # See LICENSE for licensing information. # -# Copyright (c) 2016-2022 Regents of the University of California, Santa Cruz +# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz # All rights reserved. # import sys, os diff --git a/compiler/tests/14_capped_replica_bitcell_array_norbl_1rw_1r_test.py b/compiler/tests/14_capped_replica_bitcell_array_norbl_1rw_1r_test.py index e7d8d4fd..bc432c6b 100755 --- a/compiler/tests/14_capped_replica_bitcell_array_norbl_1rw_1r_test.py +++ b/compiler/tests/14_capped_replica_bitcell_array_norbl_1rw_1r_test.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # See LICENSE for licensing information. # -# Copyright (c) 2016-2022 Regents of the University of California, Santa Cruz +# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz # All rights reserved. # import sys, os diff --git a/compiler/tests/14_capped_replica_bitcell_array_norbl_1rw_test.py b/compiler/tests/14_capped_replica_bitcell_array_norbl_1rw_test.py index 6f34785f..175689c3 100755 --- a/compiler/tests/14_capped_replica_bitcell_array_norbl_1rw_test.py +++ b/compiler/tests/14_capped_replica_bitcell_array_norbl_1rw_test.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # See LICENSE for licensing information. # -# Copyright (c) 2016-2022 Regents of the University of California, Santa Cruz +# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz # All rights reserved. # import sys, os diff --git a/compiler/tests/14_capped_replica_bitcell_array_rightrbl_1rw_1r_test.py b/compiler/tests/14_capped_replica_bitcell_array_rightrbl_1rw_1r_test.py index 68b5ef17..deac7075 100755 --- a/compiler/tests/14_capped_replica_bitcell_array_rightrbl_1rw_1r_test.py +++ b/compiler/tests/14_capped_replica_bitcell_array_rightrbl_1rw_1r_test.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # See LICENSE for licensing information. # -# Copyright (c) 2016-2022 Regents of the University of California, Santa Cruz +# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz # All rights reserved. # import sys, os diff --git a/compiler/tests/14_replica_bitcell_array_leftrbl_1rw_test.py b/compiler/tests/14_replica_bitcell_array_leftrbl_1rw_test.py index 7b66e46b..f77a571d 100755 --- a/compiler/tests/14_replica_bitcell_array_leftrbl_1rw_test.py +++ b/compiler/tests/14_replica_bitcell_array_leftrbl_1rw_test.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # See LICENSE for licensing information. # -# Copyright (c) 2016-2022 Regents of the University of California, Santa Cruz +# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz # All rights reserved. # import sys, os diff --git a/compiler/tests/14_replica_bitcell_array_rightrbl_1rw_1r_test.py b/compiler/tests/14_replica_bitcell_array_rightrbl_1rw_1r_test.py index cf908e97..8d1d8f23 100755 --- a/compiler/tests/14_replica_bitcell_array_rightrbl_1rw_1r_test.py +++ b/compiler/tests/14_replica_bitcell_array_rightrbl_1rw_1r_test.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # See LICENSE for licensing information. # -# Copyright (c) 2016-2022 Regents of the University of California, Santa Cruz +# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz # All rights reserved. # import sys, os From 7d3015868a71c12a2899ec1dd462ea67d1a73748 Mon Sep 17 00:00:00 2001 From: Eren Dogan Date: Tue, 21 Feb 2023 19:13:30 -0800 Subject: [PATCH 41/42] Don't run regress on pull requests --- .github/workflows/regress.yml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/workflows/regress.yml b/.github/workflows/regress.yml index 1da43009..b98153ab 100644 --- a/.github/workflows/regress.yml +++ b/.github/workflows/regress.yml @@ -3,14 +3,11 @@ on: push: branches-ignore: - stable - pull_request: - branches-ignore: - - stable jobs: # All tests should be run from this job regression_test: # This job runs on pull requests or any push that doesn't have a new version - if: ${{ github.event_name == 'pull_request' || startsWith(github.event.head_commit.message, 'Bump version:') == false }} + if: ${{ startsWith(github.event.head_commit.message, 'Bump version:') == false }} runs-on: self-hosted steps: - name: Checkout code @@ -52,14 +49,14 @@ jobs: path: ${{ github.workspace }}/compiler/tests/results/* # This job triggers sync.yml workflow sync_trigger: - if: ${{ always() && github.event_name == 'push' && github.ref_name == 'dev' && github.repository == 'VLSIDA/PrivateRAM' && needs.regression_test.result == 'failure' }} + if: ${{ always() && github.ref_name == 'dev' && github.repository == 'VLSIDA/PrivateRAM' && needs.regression_test.result == 'failure' }} needs: regression_test uses: ./.github/workflows/sync.yml secrets: WORKFLOW_ACCESS_TOKEN: ${{ secrets.WORKFLOW_ACCESS_TOKEN }} # This job triggers version.yml workflow version_trigger: - if: ${{ github.event_name == 'push' && github.ref_name == 'dev' }} + if: ${{ github.ref_name == 'dev' }} needs: regression_test uses: ./.github/workflows/version.yml secrets: From 63ba8647fb31be14c13e833e25b66b630c0be8e3 Mon Sep 17 00:00:00 2001 From: Eren Dogan Date: Thu, 23 Feb 2023 15:05:26 -0800 Subject: [PATCH 42/42] Add common.py for top-level scripts --- common.py | 31 +++++++++++++++++++++++++++++++ sram_compiler.py | 19 +++++-------------- 2 files changed, 36 insertions(+), 14 deletions(-) create mode 100644 common.py diff --git a/common.py b/common.py new file mode 100644 index 00000000..e6ec2d73 --- /dev/null +++ b/common.py @@ -0,0 +1,31 @@ +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz +# All rights reserved. +# +""" +Common functions for top-level scripts +""" + +import sys +import os + + +def make_openram_package(): + """ Make sure that OpenRAM can be used as a Python package. """ + + import importlib.util + + # Find the package loader from python/site-packages + openram_loader = importlib.util.find_spec("openram") + + # If openram library isn't found as a python package, import it from + # the $OPENRAM_HOME path. + if openram_loader is None: + OPENRAM_HOME = os.getenv("OPENRAM_HOME") + # Import using spec since the directory can be named something other + # than "openram". + spec = importlib.util.spec_from_file_location("openram", "{}/../__init__.py".format(OPENRAM_HOME)) + module = importlib.util.module_from_spec(spec) + sys.modules["openram"] = module + spec.loader.exec_module(module) diff --git a/sram_compiler.py b/sram_compiler.py index 9031621c..389418b0 100755 --- a/sram_compiler.py +++ b/sram_compiler.py @@ -19,20 +19,11 @@ a Liberty (.lib) file for timing analysis/optimization import sys import os import datetime -try: - import openram -except: - # If openram library isn't found as a python package, - # import it from the $OPENRAM_HOME path. - import importlib.util - OPENRAM_HOME = os.getenv("OPENRAM_HOME") - # Import using spec since the directory can be named something - # other than "openram". - spec = importlib.util.spec_from_file_location("openram", "{}/../__init__.py".format(OPENRAM_HOME)) - module = importlib.util.module_from_spec(spec) - sys.modules["openram"] = module - spec.loader.exec_module(module) - import openram + +# You don't need the next two lines if you're sure that openram package is installed +from common import * +make_openram_package() +import openram (OPTS, args) = openram.parse_args()