mirror of https://github.com/VLSIDA/OpenRAM.git
Bitcell arrays: Create abstract base class
a lot of functions of dummy- and bitcell-array are either copy-pasted or have just slight differences. Merge all of those into an abstract base class such that we don't have too much duplicate code. Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
This commit is contained in:
parent
e62beae805
commit
3fb2b9c1c3
|
|
@ -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
|
||||
|
|
@ -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."""
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Reference in New Issue