Draft local and global arrays. Ensure rows before cols in usage.

This commit is contained in:
mrg 2020-07-23 14:43:14 -07:00
parent 58846a4a25
commit e1967dc548
12 changed files with 328 additions and 21 deletions

View File

@ -17,8 +17,8 @@ class bitcell_array(bitcell_base_array):
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, column_offset=0): def __init__(self, rows, cols, column_offset=0, name=""):
super().__init__(cols, rows, name, column_offset) super().__init__(rows=rows, cols=cols, column_offset=column_offset, name=name)
self.create_netlist() self.create_netlist()
if not OPTS.netlist_only: if not OPTS.netlist_only:
@ -57,8 +57,8 @@ class bitcell_array(bitcell_base_array):
name = "bit_r{0}_c{1}".format(row, col) name = "bit_r{0}_c{1}".format(row, col)
self.cell_inst[row, col]=self.add_inst(name=name, self.cell_inst[row, col]=self.add_inst(name=name,
mod=self.cell) mod=self.cell)
self.connect_inst(self.get_bitcell_pins(col, row)) self.connect_inst(self.get_bitcell_pins(row, col))
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."""

View File

@ -14,7 +14,7 @@ class bitcell_base_array(design.design):
""" """
Abstract base class for bitcell-arrays -- bitcell, dummy Abstract base class for bitcell-arrays -- bitcell, dummy
""" """
def __init__(self, cols, rows, name, column_offset): def __init__(self, name, rows, cols, column_offset):
design.design.__init__(self, name) design.design.__init__(self, name)
debug.info(1, "Creating {0} {1} x {2}".format(self.name, rows, cols)) debug.info(1, "Creating {0} {1} x {2}".format(self.name, rows, cols))
self.add_comment("rows: {0} cols: {1}".format(rows, cols)) self.add_comment("rows: {0} cols: {1}".format(rows, cols))
@ -61,7 +61,7 @@ class bitcell_base_array(design.design):
self.add_pin("vdd", "POWER") self.add_pin("vdd", "POWER")
self.add_pin("gnd", "GROUND") self.add_pin("gnd", "GROUND")
def get_bitcell_pins(self, col, row): def get_bitcell_pins(self, row, col):
""" Creates a list of connections in the bitcell, """ Creates a list of connections in the bitcell,
indexed by column and row, for instance use in bitcell_array """ indexed by column and row, for instance use in bitcell_array """

View File

@ -50,9 +50,9 @@ class col_cap_array(bitcell_base_array):
name = "bit_r{0}_c{1}".format(row, col) name = "bit_r{0}_c{1}".format(row, col)
self.cell_inst[row, col]=self.add_inst(name=name, self.cell_inst[row, col]=self.add_inst(name=name,
mod=self.dummy_cell) mod=self.dummy_cell)
self.connect_inst(self.get_bitcell_pins(col, row)) self.connect_inst(self.get_bitcell_pins(row, col))
def get_bitcell_pins(self, col, row): def get_bitcell_pins(self, row, col):
""" """
Creates a list of connections in the bitcell, Creates a list of connections in the bitcell,
indexed by column and row, for instance use in bitcell_array indexed by column and row, for instance use in bitcell_array

View File

@ -12,8 +12,8 @@ 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, column_offset=0, mirror=0, name=""): def __init__(self, rows, cols, column_offset=0, mirror=0, name=""):
super().__init__(cols, rows, name, column_offset) super().__init__(rows=rows, cols=cols, column_offset=column_offset, name=name)
self.mirror = mirror self.mirror = mirror
self.create_netlist() self.create_netlist()
@ -51,7 +51,7 @@ class dummy_array(bitcell_base_array):
name = "bit_r{0}_c{1}".format(row, col) name = "bit_r{0}_c{1}".format(row, col)
self.cell_inst[row, col]=self.add_inst(name=name, self.cell_inst[row, col]=self.add_inst(name=name,
mod=self.dummy_cell) mod=self.dummy_cell)
self.connect_inst(self.get_bitcell_pins(col, row)) self.connect_inst(self.get_bitcell_pins(row, col))
def input_load(self): def input_load(self):
wl_wire = self.gen_wl_wire() wl_wire = self.gen_wl_wire()

View File

@ -0,0 +1,66 @@
# 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.
#
from bitcell_base_array import bitcell_base_array
from tech import drc, spice
from globals import OPTS
from sram_factory import factory
import debug
class global_bitcell_array(bitcell_base_array):
"""
Creates a global bitcell array with a number
of local arrays of a sizes given by a tuple in the list.
"""
def __init__(self, sizes, name=""):
# Each bank will have the same number of rows
self.rows = sizes[0][0]
for (r, c) in sizes:
debug.check(r[0] == self.rows, "Cannot have non-uniform number of rows in global array.")
# The total of all columns will be the number of columns
self.cols = sum(x[1] for x in sizes)
self.sizes = sizes
super().__init__(rows=self.rows, cols=self.cols, name=name)
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 create_layout(self):
self.place()
self.add_layout_pins()
self.add_boundary()
self.DRC_LVS()
def add_modules(self):
""" Add the modules used in this design """
self.local_mods = []
for (row, col) in self.sizes:
la = factory.create(module_type="local_bitcell_array", rows=row, cols=col)
self.add_mod(la)
self.local_mods.append(la)
def create_instances(self):
""" Create the module instances used in this design """
self.local_inst = {}
for i in range(self.sizes):
name = "local_array_{0}".format(i)
self.local_inst.append(self.add_inst(name=name,
mod=self.local_mods[i])
self.connect_inst(self.get_bitcell_pins(row, col))

View File

@ -0,0 +1,66 @@
# 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.
#
from bitcell_base_array import bitcell_base_array
from tech import drc, spice
from globals import OPTS
from sram_factory import factory
class local_bitcell_array(bitcell_base_array):
"""
A local wordline array is a bitcell array with a wordline driver.
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, name, rows, cols):
super().__init__(name, rows, cols)
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()
self.add_pins()
self.create_instances()
def create_layout(self):
self.place_array("bit_r{0}_c{1}")
self.add_layout_pins()
self.add_boundary()
self.DRC_LVS()
def add_modules(self):
""" Add the modules used in this design """
self.bit_array = factory.create(module_type="bitcell_array",
rows=self.rows,
cols=self.cols,
column_offset=self.column_offset)
self.add_mod(self.bit_array)
self.wl_array = factory.create(module_type="wordline_driver_array",
rows=self.rows,
cols=self.cols)
self.add_mod(self.wl_array)
def create_instances(self):
""" Create the module instances used in this design """
self.bitcell_inst = self.add_inst(mod=self.bitcell_array)
self.connect_inst(self.get_bitcell_pins(row, col))
self.wl_inst = self.add_inst(mod=self.wl_array)
self.connect_inst(self.get_bitcell_pins(row, col))

View File

@ -21,7 +21,7 @@ class replica_bitcell_array(design.design):
Requires a regular bitcell array, replica bitcell, and dummy Requires a regular bitcell array, replica bitcell, and dummy
bitcell (Bl/BR disconnected). bitcell (Bl/BR disconnected).
""" """
def __init__(self, cols, rows, left_rbl, right_rbl, bitcell_ports, name): def __init__(self, rows, cols, left_rbl, right_rbl, bitcell_ports, name):
design.design.__init__(self, name) design.design.__init__(self, name)
debug.info(1, "Creating {0} {1} x {2}".format(self.name, rows, cols)) debug.info(1, "Creating {0} {1} x {2}".format(self.name, rows, cols))
self.add_comment("rows: {0} cols: {1}".format(rows, cols)) self.add_comment("rows: {0} cols: {1}".format(rows, cols))

View File

@ -102,22 +102,22 @@ class replica_column(design.design):
if (row > self.left_rbl and row < self.total_size - self.right_rbl - 1): if (row > self.left_rbl and row < self.total_size - self.right_rbl - 1):
self.cell_inst[row]=self.add_inst(name=name, self.cell_inst[row]=self.add_inst(name=name,
mod=self.replica_cell) mod=self.replica_cell)
self.connect_inst(self.get_bitcell_pins(0, row)) self.connect_inst(self.get_bitcell_pins(row, 0))
elif row==self.replica_bit: elif row==self.replica_bit:
self.cell_inst[row]=self.add_inst(name=name, self.cell_inst[row]=self.add_inst(name=name,
mod=self.replica_cell) mod=self.replica_cell)
self.connect_inst(self.get_bitcell_pins(0, row)) self.connect_inst(self.get_bitcell_pins(row, 0))
elif (row == 0 or row == self.total_size - 1): elif (row == 0 or row == self.total_size - 1):
self.cell_inst[row]=self.add_inst(name=name, self.cell_inst[row]=self.add_inst(name=name,
mod=self.edge_cell) mod=self.edge_cell)
if end_caps_enabled: if end_caps_enabled:
self.connect_inst(self.get_bitcell_pins_col_cap(0, row)) self.connect_inst(self.get_bitcell_pins_col_cap(row, 0))
else: else:
self.connect_inst(self.get_bitcell_pins(0, row)) self.connect_inst(self.get_bitcell_pins(row, 0))
else: else:
self.cell_inst[row]=self.add_inst(name=name, self.cell_inst[row]=self.add_inst(name=name,
mod=self.dummy_cell) mod=self.dummy_cell)
self.connect_inst(self.get_bitcell_pins(0, row)) self.connect_inst(self.get_bitcell_pins(row, 0))
def place_instances(self): def place_instances(self):
from tech import cell_properties from tech import cell_properties
@ -191,7 +191,7 @@ class replica_column(design.design):
else: else:
self.copy_layout_pin(inst, pin_name) self.copy_layout_pin(inst, pin_name)
def get_bitcell_pins(self, col, row): def get_bitcell_pins(self, row, col):
""" Creates a list of connections in the bitcell, """ Creates a list of connections in the bitcell,
indexed by column and row, for instance use in bitcell_array """ indexed by column and row, for instance use in bitcell_array """
@ -208,7 +208,7 @@ class replica_column(design.design):
return bitcell_pins return bitcell_pins
def get_bitcell_pins_col_cap(self, col, row): def get_bitcell_pins_col_cap(self, row, col):
""" Creates a list of connections in the bitcell, """ Creates a list of connections in the bitcell,
indexed by column and row, for instance use in bitcell_array """ indexed by column and row, for instance use in bitcell_array """

View File

@ -49,9 +49,9 @@ class row_cap_array(bitcell_base_array):
name = "bit_r{0}_c{1}".format(row, col) name = "bit_r{0}_c{1}".format(row, col)
self.cell_inst[row, col]=self.add_inst(name=name, self.cell_inst[row, col]=self.add_inst(name=name,
mod=self.dummy_cell) mod=self.dummy_cell)
self.connect_inst(self.get_bitcell_pins(col, row)) self.connect_inst(self.get_bitcell_pins(row, col))
def get_bitcell_pins(self, col, row): def get_bitcell_pins(self, row, col):
""" """
Creates a list of connections in the bitcell, Creates a list of connections in the bitcell,
indexed by column and row, for instance use in bitcell_array indexed by column and row, for instance use in bitcell_array

View File

@ -0,0 +1,137 @@
# 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
from tech import drc, layer
from vector import vector
from sram_factory import factory
from globals import OPTS
class wordline_buffer_array(design.design):
"""
Creates a Wordline Buffer/Inverter array
"""
def __init__(self, name, rows, cols):
design.design.__init__(self, name)
debug.info(1, "Creating {0}".format(self.name))
self.add_comment("rows: {0} cols: {1}".format(rows, cols))
self.rows = rows
self.cols = cols
self.create_netlist()
if not OPTS.netlist_only:
self.create_layout()
def create_netlist(self):
self.add_modules()
self.add_pins()
self.create_drivers()
def create_layout(self):
if "li" in layer:
self.route_layer = "li"
else:
self.route_layer = "m1"
self.place_drivers()
self.route_layout()
self.route_vdd_gnd()
self.offset_all_coordinates()
self.add_boundary()
self.DRC_LVS()
def add_pins(self):
# inputs to wordline_driver.
for i in range(self.rows):
self.add_pin("in_{0}".format(i), "INPUT")
# Outputs from wordline_driver.
for i in range(self.rows):
self.add_pin("wl_{0}".format(i), "OUTPUT")
self.add_pin("vdd", "POWER")
self.add_pin("gnd", "GROUND")
def add_modules(self):
self.wl_driver = factory.create(module_type="inv_dec",
size=self.cols)
self.add_mod(self.wl_driver)
def route_vdd_gnd(self):
"""
Add a pin for each row of vdd/gnd which
are must-connects next level up.
"""
if OPTS.tech_name == "sky130":
for name in ["vdd", "gnd"]:
supply_pins = self.wld_inst[0].get_pins(name)
for pin in supply_pins:
self.add_layout_pin_segment_center(text=name,
layer=pin.layer,
start=pin.bc(),
end=vector(pin.cx(), self.height))
else:
# Find the x offsets for where the vias/pins should be placed
xoffset_list = [self.wld_inst[0].rx()]
for num in range(self.rows):
# this will result in duplicate polygons for rails, but who cares
# use the inverter offset even though it will be the and's too
(gate_offset, y_dir) = self.get_gate_offset(0,
self.wl_driver.height,
num)
# Route both supplies
for name in ["vdd", "gnd"]:
supply_pin = self.wld_inst[num].get_pin(name)
# Add pins in two locations
for xoffset in xoffset_list:
pin_pos = vector(xoffset, supply_pin.cy())
self.add_power_pin(name, pin_pos)
def create_drivers(self):
self.wld_inst = []
for row in range(self.rows):
self.wld_inst.append(self.add_inst(name="wld{0}".format(row),
mod=self.wl_driver))
self.connect_inst(["in_{0}".format(row),
"wl_{0}".format(row),
"vdd", "gnd"])
def place_drivers(self):
for row in range(self.rows):
if (row % 2):
y_offset = self.wl_driver.height * (row + 1)
inst_mirror = "MX"
else:
y_offset = self.wl_driver.height * row
inst_mirror = "R0"
offset = [0, y_offset]
self.wld_inst[row].place(offset=offset,
mirror=inst_mirror)
self.width = self.wl_driver.width
self.height = self.wl_driver.height * self.rows
def route_layout(self):
""" Route all of the signals """
for row in range(self.rows):
inst = self.wld_inst[row]
self.copy_layout_pin(inst, "A", "in_{0}".format(row))
# output each WL on the right
wl_offset = inst.get_pin("Z").rc()
self.add_layout_pin_segment_center(text="wl_{0}".format(row),
layer=self.route_layer,
start=wl_offset,
end=wl_offset - vector(self.m1_width, 0))

View File

@ -12,6 +12,7 @@ from vector import vector
from sram_factory import factory from sram_factory import factory
from globals import OPTS from globals import OPTS
class wordline_driver_array(design.design): class wordline_driver_array(design.design):
""" """
Creates a Wordline Driver Creates a Wordline Driver

View File

@ -0,0 +1,37 @@
#!/usr/bin/env python3
# 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 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 wordline_buffer_array_test(openram_test):
def runTest(self):
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
globals.init_openram(config_file)
# check wordline driver for single port
debug.info(2, "Checking driver")
tx = factory.create(module_type="wordline_buffer_array", rows=8, cols=32)
self.local_check(tx)
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())