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 debug
|
||||||
import design
|
import design
|
||||||
|
from base_array import bitcell_base_array
|
||||||
from tech import drc, spice
|
from tech import drc, spice
|
||||||
from vector import vector
|
from vector import vector
|
||||||
from globals import OPTS
|
from globals import OPTS
|
||||||
from sram_factory import factory
|
from sram_factory import factory
|
||||||
import logical_effort
|
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
|
Creates a rows x cols array of memory cells. Assumes bit-lines
|
||||||
and word line is connected by abutment.
|
and word line is connected by abutment.
|
||||||
Connects the word lines and bit lines.
|
Connects the word lines and bit lines.
|
||||||
"""
|
"""
|
||||||
def __init__(self, cols, rows, name):
|
def __init__(self, cols, rows, name):
|
||||||
design.design.__init__(self, name)
|
super().__init__(cols, rows, 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
|
|
||||||
|
|
||||||
self.create_netlist()
|
self.create_netlist()
|
||||||
if not OPTS.netlist_only:
|
if not OPTS.netlist_only:
|
||||||
|
|
@ -44,27 +40,7 @@ class bitcell_array(design.design):
|
||||||
|
|
||||||
def create_layout(self):
|
def create_layout(self):
|
||||||
|
|
||||||
# We increase it by a well enclosure so the precharges don't overlap our wells
|
self.place_array("bit_r{0}_c{1}")
|
||||||
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.add_layout_pins()
|
self.add_layout_pins()
|
||||||
|
|
||||||
|
|
@ -72,40 +48,12 @@ class bitcell_array(design.design):
|
||||||
|
|
||||||
self.DRC_LVS()
|
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):
|
def add_modules(self):
|
||||||
""" Add the modules used in this design """
|
""" Add the modules used in this design """
|
||||||
self.cell = factory.create(module_type="bitcell")
|
self.cell = factory.create(module_type="bitcell")
|
||||||
self.add_mod(self.cell)
|
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):
|
def create_instances(self):
|
||||||
""" Create the module instances used in this design """
|
""" Create the module instances used in this design """
|
||||||
|
|
@ -117,37 +65,6 @@ class bitcell_array(design.design):
|
||||||
mod=self.cell)
|
mod=self.cell)
|
||||||
self.connect_inst(self.get_bitcell_pins(col, row))
|
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):
|
def analytical_power(self, corner, load):
|
||||||
"""Power of Bitcell array and bitline in nW."""
|
"""Power of Bitcell array and bitline in nW."""
|
||||||
|
|
|
||||||
|
|
@ -5,23 +5,19 @@
|
||||||
#
|
#
|
||||||
import debug
|
import debug
|
||||||
import design
|
import design
|
||||||
|
from base_array import bitcell_base_array
|
||||||
from tech import drc
|
from tech import drc
|
||||||
import contact
|
import contact
|
||||||
from sram_factory import factory
|
from sram_factory import factory
|
||||||
from vector import vector
|
from vector import vector
|
||||||
from globals import OPTS
|
from globals import OPTS
|
||||||
|
|
||||||
class dummy_array(design.design):
|
class dummy_array(bitcell_base_array):
|
||||||
"""
|
"""
|
||||||
Generate a dummy row/column for the replica array.
|
Generate a dummy row/column for the replica array.
|
||||||
"""
|
"""
|
||||||
def __init__(self, cols, rows, mirror=0, name=""):
|
def __init__(self, cols, rows, mirror=0, name=""):
|
||||||
design.design.__init__(self, name)
|
super().__init__(cols, rows, 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
|
|
||||||
self.mirror = mirror
|
self.mirror = mirror
|
||||||
|
|
||||||
self.create_netlist()
|
self.create_netlist()
|
||||||
|
|
@ -37,27 +33,7 @@ class dummy_array(design.design):
|
||||||
|
|
||||||
def create_layout(self):
|
def create_layout(self):
|
||||||
|
|
||||||
# We increase it by a well enclosure so the precharges don't overlap our wells
|
self.place_array("dummy_r{0}_c{1}", self.mirror)
|
||||||
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.add_layout_pins()
|
self.add_layout_pins()
|
||||||
|
|
||||||
|
|
@ -65,18 +41,6 @@ class dummy_array(design.design):
|
||||||
|
|
||||||
self.DRC_LVS()
|
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):
|
def add_modules(self):
|
||||||
""" Add the modules used in this design """
|
""" Add the modules used in this design """
|
||||||
self.dummy_cell = factory.create(module_type="dummy_bitcell")
|
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")
|
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):
|
def create_instances(self):
|
||||||
""" Create the module instances used in this design """
|
""" Create the module instances used in this design """
|
||||||
|
|
@ -112,39 +59,6 @@ class dummy_array(design.design):
|
||||||
mod=self.dummy_cell)
|
mod=self.dummy_cell)
|
||||||
self.connect_inst(self.get_bitcell_pins(col, row))
|
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):
|
def input_load(self):
|
||||||
wl_wire = self.gen_wl_wire()
|
wl_wire = self.gen_wl_wire()
|
||||||
return wl_wire.return_input_cap()
|
return wl_wire.return_input_cap()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue