From b67f06a65a703de2a596a5a26fff540ccc42fc88 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 14 Jun 2019 12:15:16 -0700 Subject: [PATCH] Add replica column for inclusion in replica bitcell array --- compiler/modules/replica_column.py | 142 +++++++++++++++++++++++ compiler/tests/05_replica_column_test.py | 32 +++++ 2 files changed, 174 insertions(+) create mode 100644 compiler/modules/replica_column.py create mode 100755 compiler/tests/05_replica_column_test.py diff --git a/compiler/modules/replica_column.py b/compiler/modules/replica_column.py new file mode 100644 index 00000000..91f2881a --- /dev/null +++ b/compiler/modules/replica_column.py @@ -0,0 +1,142 @@ +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2019 Regents of the University of California +# All rights reserved. +# +import debug +import design +from tech import drc +import contact +from sram_factory import factory +from vector import vector +from globals import OPTS + +class replica_column(design.design): + """ + Generate a replica bitline column for the replica array. + """ + + def __init__(self, name, rows): + design.design.__init__(self, name) + + # One extra row for the dummy row + self.row_size = rows + 1 + + self.create_netlist() + if not OPTS.netlist_only: + self.create_layout() + + def create_netlist(self): + self.add_modules() + self.add_pins() + self.create_instances() + + def create_layout(self): + self.place_instances() + self.add_layout_pins() + + self.add_boundary() + self.DRC_LVS() + + def add_pins(self): + column_list = self.cell.list_all_bitline_names() + for cell_column in column_list: + self.add_pin("{0}_{1}".format(cell_column,0)) + row_list = self.cell.list_all_wl_names() + for row in range(self.row_size): + for cell_row in row_list: + self.add_pin("{0}_{1}".format(cell_row,row)) + + self.add_pin("vdd") + self.add_pin("gnd") + + def add_modules(self): + self.replica_cell = factory.create(module_type="replica_bitcell") + self.add_mod(self.replica_cell) + # Used for pin names only + self.cell = factory.create(module_type="bitcell") + + def create_instances(self): + self.cell_inst = {} + for row in range(self.row_size): + name="rbc_{0}".format(row) + self.cell_inst[row]=self.add_inst(name=name, + mod=self.replica_cell) + self.connect_inst(self.list_bitcell_pins(0, row)) + + def create_layout(self): + + # We increase it by a well enclosure so the precharges don't overlap our wells + self.height = self.row_size*self.cell.height + self.width = self.cell.width + + yoffset = 0.0 + for row in range(self.row_size): + name = "bit_r{0}_{1}".format(row,"rbl") + + # This is opposite of a bitcell array since we will be 1 row off + if not row % 2: + tempy = yoffset + self.cell.height + dir_key = "MX" + else: + tempy = yoffset + dir_key = "" + + self.cell_inst[row].place(offset=[0.0, tempy], + mirror=dir_key) + yoffset += self.cell.height + + self.add_layout_pins() + + self.add_boundary() + + self.DRC_LVS() + + + def add_layout_pins(self): + """ Add the layout pins """ + + row_list = self.cell.list_all_wl_names() + column_list = self.cell.list_all_bitline_names() + + col = "rbl" + for cell_column in column_list: + bl_pin = self.cell_inst[0].get_pin(cell_column) + self.add_layout_pin(text=cell_column+"_{0}".format(col), + layer="metal2", + offset=bl_pin.ll(), + width=bl_pin.width(), + height=self.height) + + for row in range(self.row_size): + for cell_row in row_list: + wl_pin = self.cell_inst[row].get_pin(cell_row) + self.add_layout_pin(text=cell_row+"_{0}".format(row), + layer="metal1", + offset=wl_pin.ll(), + width=self.width, + height=wl_pin.height()) + + # For every second row and column, add a via for gnd and vdd + for row in range(self.row_size): + inst = self.cell_inst[row] + for pin_name in ["vdd", "gnd"]: + self.copy_layout_pin(inst, pin_name) + + def list_bitcell_pins(self, col, row): + """ Creates a list of connections in the bitcell, + indexed by column and row, for instance use in bitcell_array """ + + bitcell_pins = [] + + pin_names = self.cell.list_all_bitline_names() + for pin in pin_names: + bitcell_pins.append(pin+"_{0}".format(col)) + pin_names = self.cell.list_all_wl_names() + for pin in pin_names: + bitcell_pins.append(pin+"_{0}".format(row)) + bitcell_pins.append("vdd") + bitcell_pins.append("gnd") + + return bitcell_pins + diff --git a/compiler/tests/05_replica_column_test.py b/compiler/tests/05_replica_column_test.py new file mode 100755 index 00000000..8a9f03bb --- /dev/null +++ b/compiler/tests/05_replica_column_test.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2019 Regents of the University of California +# All rights reserved. +# +import unittest +from testutils import * +import sys,os +sys.path.append(os.getenv("OPENRAM_HOME")) +import globals +from globals import OPTS +from sram_factory import factory +import debug + +class replica_column_test(openram_test): + + def runTest(self): + globals.init_openram("config_{0}".format(OPTS.tech_name)) + + debug.info(2, "Testing replica column for 6t_cell") + a = factory.create(module_type="replica_column", rows=4) + 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())