diff --git a/compiler/modules/base_array.py b/compiler/modules/base_array.py new file mode 100644 index 00000000..db2b1be6 --- /dev/null +++ b/compiler/modules/base_array.py @@ -0,0 +1,107 @@ +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2019 Regents of the University of California and The Board +# of Regents for the Oklahoma Agricultural and Mechanical College +# (acting for and on behalf of Oklahoma State University) +# All rights reserved. +# +import debug +import design + +class bitcell_base_array(design.design): + """ + Abstract base class for bitcell-arrays -- bitcell, dummy + """ + def __init__(self, cols, rows, name): + design.design.__init__(self, name) + debug.info(1, "Creating {0} {1} x {2}".format(self.name, rows, cols)) + self.add_comment("rows: {0} cols: {1}".format(rows, cols)) + + self.column_size = cols + self.row_size = rows + + def add_pins(self): + row_list = self.cell.get_all_wl_names() + column_list = self.cell.get_all_bitline_names() + for col in range(self.column_size): + for cell_column in column_list: + self.add_pin(cell_column+"_{0}".format(col), "INOUT") + for row in range(self.row_size): + for cell_row in row_list: + self.add_pin(cell_row+"_{0}".format(row), "INPUT") + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") + + def get_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.get_all_bitline_names() + for pin in pin_names: + bitcell_pins.append(pin+"_{0}".format(col)) + pin_names = self.cell.get_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 + + def add_layout_pins(self): + """ Add the layout pins """ + + row_list = self.cell.get_all_wl_names() + column_list = self.cell.get_all_bitline_names() + + for col in range(self.column_size): + for cell_column in column_list: + bl_pin = self.cell_inst[0,col].get_pin(cell_column) + self.add_layout_pin(text=cell_column+"_{0}".format(col), + layer=bl_pin.layer, + offset=bl_pin.ll().scale(1,0), + 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,0].get_pin(cell_row) + self.add_layout_pin(text=cell_row+"_{0}".format(row), + layer=wl_pin.layer, + offset=wl_pin.ll().scale(0,1), + 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): + for col in range(self.column_size): + inst = self.cell_inst[row,col] + for pin_name in ["vdd", "gnd"]: + for pin in inst.get_pins(pin_name): + self.add_power_pin(name=pin_name, loc=pin.center(), vertical=True, start_layer=pin.layer) + + + + def place_array(self, name_template, row_offset=0): + # 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.column_size*self.cell.width + + xoffset = 0.0 + for col in range(self.column_size): + yoffset = 0.0 + for row in range(self.row_size): + name = name_template.format(row, col) + + if (row + row_offset) % 2: + tempy = yoffset + self.cell.height + dir_key = "MX" + else: + tempy = yoffset + dir_key = "" + + self.cell_inst[row,col].place(offset=[xoffset, tempy], + mirror=dir_key) + yoffset += self.cell.height + xoffset += self.cell.width diff --git a/compiler/modules/bitcell_array.py b/compiler/modules/bitcell_array.py index bf43736b..4c1c798b 100644 --- a/compiler/modules/bitcell_array.py +++ b/compiler/modules/bitcell_array.py @@ -7,25 +7,21 @@ # import debug import design +from base_array import bitcell_base_array from tech import drc, spice from vector import vector from globals import OPTS from sram_factory import factory import logical_effort -class bitcell_array(design.design): +class bitcell_array(bitcell_base_array): """ Creates a rows x cols array of memory cells. Assumes bit-lines and word line is connected by abutment. Connects the word lines and bit lines. """ def __init__(self, cols, rows, name): - design.design.__init__(self, name) - debug.info(1, "Creating {0} {1} x {2}".format(self.name, rows, cols)) - self.add_comment("rows: {0} cols: {1}".format(rows, cols)) - - self.column_size = cols - self.row_size = rows + super().__init__(cols, rows, name) self.create_netlist() if not OPTS.netlist_only: @@ -44,27 +40,7 @@ class bitcell_array(design.design): 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.column_size*self.cell.width - - xoffset = 0.0 - for col in range(self.column_size): - yoffset = 0.0 - for row in range(self.row_size): - name = "bit_r{0}_c{1}".format(row, col) - - if row % 2: - tempy = yoffset + self.cell.height - dir_key = "MX" - else: - tempy = yoffset - dir_key = "" - - self.cell_inst[row,col].place(offset=[xoffset, tempy], - mirror=dir_key) - yoffset += self.cell.height - xoffset += self.cell.width + self.place_array("bit_r{0}_c{1}") self.add_layout_pins() @@ -72,41 +48,13 @@ class bitcell_array(design.design): self.DRC_LVS() - def add_pins(self): - row_list = self.cell.get_all_wl_names() - column_list = self.cell.get_all_bitline_names() - for col in range(self.column_size): - for cell_column in column_list: - self.add_pin(cell_column+"_{0}".format(col), "INOUT") - for row in range(self.row_size): - for cell_row in row_list: - self.add_pin(cell_row+"_{0}".format(row), "INPUT") - self.add_pin("vdd", "POWER") - self.add_pin("gnd", "GROUND") def add_modules(self): """ Add the modules used in this design """ self.cell = factory.create(module_type="bitcell") self.add_mod(self.cell) - def get_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.get_all_bitline_names() - for pin in pin_names: - bitcell_pins.append(pin+"_{0}".format(col)) - pin_names = self.cell.get_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 - def create_instances(self): """ Create the module instances used in this design """ self.cell_inst = {} @@ -117,37 +65,6 @@ class bitcell_array(design.design): mod=self.cell) self.connect_inst(self.get_bitcell_pins(col, row)) - def add_layout_pins(self): - """ Add the layout pins """ - - row_list = self.cell.get_all_wl_names() - column_list = self.cell.get_all_bitline_names() - - for col in range(self.column_size): - for cell_column in column_list: - bl_pin = self.cell_inst[0,col].get_pin(cell_column) - self.add_layout_pin(text=cell_column+"_{0}".format(col), - layer=bl_pin.layer, - offset=bl_pin.ll().scale(1,0), - 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,0].get_pin(cell_row) - self.add_layout_pin(text=cell_row+"_{0}".format(row), - layer=wl_pin.layer, - offset=wl_pin.ll().scale(0,1), - 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): - for col in range(self.column_size): - inst = self.cell_inst[row,col] - for pin_name in ["vdd", "gnd"]: - for pin in inst.get_pins(pin_name): - self.add_power_pin(name=pin_name, loc=pin.center(), vertical=True, start_layer=pin.layer) def analytical_power(self, corner, load): """Power of Bitcell array and bitline in nW.""" diff --git a/compiler/modules/dummy_array.py b/compiler/modules/dummy_array.py index 1e5a2121..88717b56 100644 --- a/compiler/modules/dummy_array.py +++ b/compiler/modules/dummy_array.py @@ -5,23 +5,19 @@ # import debug import design +from base_array import bitcell_base_array from tech import drc import contact from sram_factory import factory from vector import vector from globals import OPTS -class dummy_array(design.design): +class dummy_array(bitcell_base_array): """ Generate a dummy row/column for the replica array. """ def __init__(self, cols, rows, mirror=0, name=""): - design.design.__init__(self, name) - debug.info(1, "Creating {0} {1} x {2}".format(self.name, rows, cols)) - self.add_comment("rows: {0} cols: {1}".format(rows, cols)) - - self.column_size = cols - self.row_size = rows + super().__init__(cols, rows, name) self.mirror = mirror self.create_netlist() @@ -37,27 +33,7 @@ class dummy_array(design.design): 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.dummy_cell.height - self.width = self.column_size*self.dummy_cell.width - - xoffset = 0.0 - for col in range(self.column_size): - yoffset = 0.0 - for row in range(self.row_size): - name = "dummy_r{0}_c{1}".format(row, col) - - if (row+self.mirror) % 2: - tempy = yoffset + self.dummy_cell.height - dir_key = "MX" - else: - tempy = yoffset - dir_key = "" - - self.cell_inst[row,col].place(offset=[xoffset, tempy], - mirror=dir_key) - yoffset += self.dummy_cell.height - xoffset += self.dummy_cell.width + self.place_array("dummy_r{0}_c{1}", self.mirror) self.add_layout_pins() @@ -65,18 +41,6 @@ class dummy_array(design.design): self.DRC_LVS() - def add_pins(self): - row_list = self.cell.get_all_wl_names() - column_list = self.cell.get_all_bitline_names() - for col in range(self.column_size): - for cell_column in column_list: - self.add_pin(cell_column+"_{0}".format(col), "INOUT") - for row in range(self.row_size): - for cell_row in row_list: - self.add_pin(cell_row+"_{0}".format(row), "INPUT") - self.add_pin("vdd", "POWER") - self.add_pin("gnd", "GROUND") - def add_modules(self): """ Add the modules used in this design """ self.dummy_cell = factory.create(module_type="dummy_bitcell") @@ -84,23 +48,6 @@ class dummy_array(design.design): self.cell = factory.create(module_type="bitcell") - def get_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.get_all_bitline_names() - for pin in pin_names: - bitcell_pins.append(pin+"_{0}".format(col)) - pin_names = self.cell.get_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 - def create_instances(self): """ Create the module instances used in this design """ @@ -111,39 +58,6 @@ class dummy_array(design.design): self.cell_inst[row,col]=self.add_inst(name=name, mod=self.dummy_cell) self.connect_inst(self.get_bitcell_pins(col, row)) - - def add_layout_pins(self): - """ Add the layout pins """ - - row_list = self.cell.get_all_wl_names() - column_list = self.cell.get_all_bitline_names() - - for col in range(self.column_size): - for cell_column in column_list: - bl_pin = self.cell_inst[0,col].get_pin(cell_column) - self.add_layout_pin(text=cell_column+"_{0}".format(col), - layer="m2", - 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,0].get_pin(cell_row) - self.add_layout_pin(text=cell_row+"_{0}".format(row), - layer="m1", - 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): - for col in range(self.column_size): - inst = self.cell_inst[row,col] - for pin_name in ["vdd", "gnd"]: - for pin in inst.get_pins(pin_name): - self.add_power_pin(name=pin_name, loc=pin.center(), vertical=True, start_layer=pin.layer) - def input_load(self): wl_wire = self.gen_wl_wire()