update for end caps

This commit is contained in:
Joey Kunzler 2020-05-27 20:03:11 -07:00
parent 9a6b38b67e
commit 7505fa5aef
9 changed files with 486 additions and 101 deletions

View File

@ -0,0 +1,43 @@
# 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 utils
from tech import GDS, layer
from tech import cell_properties as props
import bitcell_base
class col_cap_bitcell_1rw_1r(bitcell_base.bitcell_base):
"""
todo"""
pin_names = [props.bitcell.cell_1rw1r.pin.bl0,
props.bitcell.cell_1rw1r.pin.br0,
props.bitcell.cell_1rw1r.pin.bl1,
props.bitcell.cell_1rw1r.pin.br1,
props.bitcell.cell_1rw1r.pin.vdd]
type_list = ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT",
"POWER", "GROUND"]
(width, height) = utils.get_libcell_size("col_cap_cell_1rw_1r",
GDS["unit"],
layer["boundary"])
pin_map = utils.get_libcell_pins(pin_names,
"col_cap_cell_1rw_1r",
GDS["unit"])
def __init__(self, name=""):
# Ignore the name argument
bitcell_base.bitcell_base.__init__(self, "col_cap_cell_1rw_1r")
debug.info(2, "Create col_cap bitcell 1rw+1r object")
self.width = col_cap_bitcell_1rw_1r.width
self.height = col_cap_bitcell_1rw_1r.height
self.pin_map = col_cap_bitcell_1rw_1r.pin_map
self.add_pin_types(self.type_list)

View File

@ -0,0 +1,43 @@
# 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 utils
from tech import GDS, layer
from tech import cell_properties as props
import bitcell_base
class row_cap_bitcell_1rw_1r(bitcell_base.bitcell_base):
"""
A single bit cell which is forced to store a 0.
This module implements the single memory cell used in the design. It
is a hand-made cell, so the layout and netlist should be available in
the technology library. """
pin_names = [props.bitcell.cell_1rw1r.pin.wl0,
props.bitcell.cell_1rw1r.pin.wl1,
props.bitcell.cell_1rw1r.pin.gnd]
type_list = ["INPUT", "INPUT", "GROUND"]
(width, height) = utils.get_libcell_size("row_cap_cell_1rw_1r",
GDS["unit"],
layer["boundary"])
pin_map = utils.get_libcell_pins(pin_names,
"row_cap_cell_1rw_1r",
GDS["unit"])
def __init__(self, name=""):
# Ignore the name argument
bitcell_base.bitcell_base.__init__(self, "row_cap_cell_1rw_1r")
debug.info(2, "Create row_cap bitcell 1rw+1r object")
self.width = row_cap_bitcell_1rw_1r.width
self.height = row_cap_bitcell_1rw_1r.height
self.pin_map = row_cap_bitcell_1rw_1r.pin_map
self.add_pin_types(self.type_list)

View File

@ -108,16 +108,23 @@ class bitcell_base_array(design.design):
except AttributeError: except AttributeError:
bitcell_power_pin_directions = None bitcell_power_pin_directions = None
# For specific technologies, there is no vdd via within the bitcell. Instead vdd is connect via end caps.
try:
bitcell_no_vdd_pin = cell_properties.bitcell.no_vdd_via
except AttributeError:
bitcell_no_vdd_pin = False
# Add vdd/gnd via stacks # Add vdd/gnd via stacks
for row in range(self.row_size): for row in range(self.row_size):
for col in range(self.column_size): for col in range(self.column_size):
inst = self.cell_inst[row,col] inst = self.cell_inst[row,col]
for pin_name in ["vdd", "gnd"]: for pin_name in ["vdd", "gnd"]:
for pin in inst.get_pins(pin_name): for pin in inst.get_pins(pin_name):
self.add_power_pin(name=pin_name, if not (pin_name == "vdd" and bitcell_no_vdd_pin):
loc=pin.center(), self.add_power_pin(name=pin_name,
directions=bitcell_power_pin_directions, loc=pin.center(),
start_layer=pin.layer) directions=bitcell_power_pin_directions,
start_layer=pin.layer)
def _adjust_x_offset(self, xoffset, col, col_offset): def _adjust_x_offset(self, xoffset, col, col_offset):
tempx = xoffset tempx = xoffset

View File

@ -0,0 +1,103 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California
# All rights reserved.
#
from bitcell_base_array import bitcell_base_array
from sram_factory import factory
from globals import OPTS
from tech import cell_properties
class col_cap_array(bitcell_base_array):
"""
Generate a dummy row/column for the replica array.
"""
def __init__(self, cols, rows, column_offset=0, mirror=0, name=""):
super().__init__(cols, rows, name, column_offset)
self.mirror = mirror
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_array("dummy_r{0}_c{1}", self.mirror)
self.add_layout_pins()
self.add_boundary()
self.DRC_LVS()
def add_modules(self):
""" Add the modules used in this design """
# self.dummy_cell = factory.create(module_type="col_cap_bitcell_1rw_1r") # TODO: make module_type generic
self.dummy_cell = factory.create(module_type="col_cap_bitcell")
self.add_mod(self.dummy_cell)
self.cell = factory.create(module_type="bitcell")
def create_instances(self):
""" Create the module instances used in this design """
self.cell_inst = {}
for col in range(self.column_size):
for row in range(self.row_size):
name = "bit_r{0}_c{1}".format(row, col)
self.cell_inst[row,col]=self.add_inst(name=name,
mod=self.dummy_cell)
self.connect_inst(self.get_bitcell_pins(col, row))
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
"""
pin_name = cell_properties.bitcell.cell_1rw1r.pin
bitcell_pins = ["{0}_{1}".format(pin_name.bl0, col),
"{0}_{1}".format(pin_name.br0, col),
"{0}_{1}".format(pin_name.bl1, col),
"{0}_{1}".format(pin_name.br1, col),
"vdd"]
return bitcell_pins
def add_layout_pins(self):
""" Add the layout pins """
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)
# Add vdd/gnd via stacks
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(),
start_layer=pin.layer)
# def input_load(self):
# wl_wire = self.gen_wl_wire()
# return wl_wire.return_input_cap()
#
# def get_wordline_cin(self):
# """Get the relative input capacitance from the wordline connections in all the bitcell"""
# #A single wordline is connected to all the bitcells in a single row meaning the capacitance depends on the # of columns
# bitcell_wl_cin = self.cell.get_wl_cin()
# total_cin = bitcell_wl_cin * self.column_size
# return total_cin

View File

@ -1,12 +1,12 @@
# See LICENSE for licensing information. # See LICENSE for licensing information.
# #
# Copyright (c) 2016-2019 Regents of the University of California # Copyright (c) 2016-2019 Regents of the University of California
# All rights reserved. # All rights reserved.
# #
import debug import debug
import design import design
from tech import drc, spice from tech import drc, spice, cell_properties
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
@ -34,11 +34,11 @@ class replica_bitcell_array(design.design):
debug.check(left_rbl+right_rbl==len(self.all_ports),"Invalid number of RBLs for port configuration.") debug.check(left_rbl+right_rbl==len(self.all_ports),"Invalid number of RBLs for port configuration.")
debug.check(left_rbl+right_rbl==len(self.bitcell_ports),"Bitcell ports must match total RBLs.") debug.check(left_rbl+right_rbl==len(self.bitcell_ports),"Bitcell ports must match total RBLs.")
# Two dummy rows/cols plus replica for each port # Two dummy rows/cols plus replica for each port
self.extra_rows = 2 + left_rbl + right_rbl self.extra_rows = 2 + left_rbl + right_rbl
self.extra_cols = 2 + left_rbl + right_rbl self.extra_cols = 2 + left_rbl + right_rbl
self.create_netlist() self.create_netlist()
if not OPTS.netlist_only: if not OPTS.netlist_only:
self.create_layout() self.create_layout()
@ -46,8 +46,8 @@ class replica_bitcell_array(design.design):
# We don't offset this because we need to align # We don't offset this because we need to align
# the replica bitcell in the control logic # the replica bitcell in the control logic
#self.offset_all_coordinates() #self.offset_all_coordinates()
def create_netlist(self): def create_netlist(self):
""" Create and connect the netlist """ """ Create and connect the netlist """
self.add_modules() self.add_modules()
@ -55,15 +55,15 @@ class replica_bitcell_array(design.design):
self.create_instances() self.create_instances()
def add_modules(self): def add_modules(self):
""" Array and dummy/replica columns """ Array and dummy/replica columns
d or D = dummy cell (caps to distinguish grouping) d or D = dummy cell (caps to distinguish grouping)
r or R = replica cell (caps to distinguish grouping) r or R = replica cell (caps to distinguish grouping)
b or B = bitcell b or B = bitcell
replica columns 1 replica columns 1
v v v v
bdDDDDDDDDDDDDDDdb <- Dummy row bdDDDDDDDDDDDDDDdb <- Dummy row
bdDDDDDDDDDDDDDDrb <- Dummy row bdDDDDDDDDDDDDDDrb <- Dummy row
br--------------rb br--------------rb
br| Array |rb br| Array |rb
br| row x col |rb br| row x col |rb
@ -106,7 +106,7 @@ class replica_bitcell_array(design.design):
column_offset=column_offset, column_offset=column_offset,
replica_bit=replica_bit) replica_bit=replica_bit)
self.add_mod(self.replica_columns[bit]) self.add_mod(self.replica_columns[bit])
# Dummy row # Dummy row
self.dummy_row = factory.create(module_type="dummy_array", self.dummy_row = factory.create(module_type="dummy_array",
cols=self.column_size, cols=self.column_size,
@ -116,15 +116,35 @@ class replica_bitcell_array(design.design):
mirror=0) mirror=0)
self.add_mod(self.dummy_row) self.add_mod(self.dummy_row)
# Dummy col (mirror starting at first if odd replica+dummy rows)
self.dummy_col_left = factory.create(module_type="dummy_array", # If there are bitcell end caps, replace the dummy cells on the edge of the bitcell array with end caps.
try:
end_caps_enabled = cell_properties.bitcell.end_caps
except AttributeError:
end_caps_enabled = False
# Dummy Row or Col Cap, depending on bitcell array properties
edge_row_module_type = ("col_cap_array" if end_caps_enabled else "dummy_array")
self.edge_row = factory.create(module_type=edge_row_module_type,
cols=self.column_size,
rows=1,
# dummy column + left replica column
column_offset=1 + self.left_rbl,
mirror=0)
self.add_mod(self.edge_row)
# Dummy Col or Row Cap, depending on bitcell array properties
edge_col_module_type = ("row_cap_array" if end_caps_enabled else "dummy_array")
self.edge_col_left = factory.create(module_type=edge_col_module_type,
cols=1, cols=1,
column_offset=0, column_offset=0,
rows=self.row_size + self.extra_rows, rows=self.row_size + self.extra_rows,
mirror=(self.left_rbl+1)%2) mirror=(self.left_rbl+1)%2)
self.add_mod(self.dummy_col_left) self.add_mod(self.edge_col_left)
self.dummy_col_right = factory.create(module_type="dummy_array", self.edge_col_right = factory.create(module_type=edge_col_module_type,
cols=1, cols=1,
# dummy column # dummy column
# + left replica column # + left replica column
@ -133,9 +153,7 @@ class replica_bitcell_array(design.design):
column_offset=1 + self.left_rbl + self.column_size + self.right_rbl, column_offset=1 + self.left_rbl + self.column_size + self.right_rbl,
rows=self.row_size + self.extra_rows, rows=self.row_size + self.extra_rows,
mirror=(self.left_rbl+1)%2) mirror=(self.left_rbl+1)%2)
self.add_mod(self.dummy_col_right) self.add_mod(self.edge_col_right)
def add_pins(self): def add_pins(self):
self.bitcell_array_wl_names = self.bitcell_array.get_all_wordline_names() self.bitcell_array_wl_names = self.bitcell_array.get_all_wordline_names()
@ -150,7 +168,7 @@ class replica_bitcell_array(design.design):
self.rbl_bl_names = {} self.rbl_bl_names = {}
self.rbl_br_names = {} self.rbl_br_names = {}
self.rbl_wl_names = {} self.rbl_wl_names = {}
# Create the full WL names include dummy, replica, and regular bit cells # Create the full WL names include dummy, replica, and regular bit cells
self.replica_col_wl_names = [] self.replica_col_wl_names = []
self.replica_col_wl_names.extend(["{0}_bot".format(x) for x in self.dummy_cell_wl_names]) self.replica_col_wl_names.extend(["{0}_bot".format(x) for x in self.dummy_cell_wl_names])
@ -193,7 +211,7 @@ class replica_bitcell_array(design.design):
wl_names = ["rbl_{0}_{1}".format(x,port) for x in self.cell.get_all_wl_names()] wl_names = ["rbl_{0}_{1}".format(x,port) for x in self.cell.get_all_wl_names()]
#wl_names[port] = "rbl_wl{}".format(port) #wl_names[port] = "rbl_wl{}".format(port)
self.replica_wl_names[port] = wl_names self.replica_wl_names[port] = wl_names
# External pins # External pins
self.add_pin_list(self.bitcell_array_bl_names, "INOUT") self.add_pin_list(self.bitcell_array_bl_names, "INOUT")
@ -204,22 +222,22 @@ class replica_bitcell_array(design.design):
self.add_pin(bl_name,"OUTPUT") self.add_pin(bl_name,"OUTPUT")
self.add_pin(br_name,"OUTPUT") self.add_pin(br_name,"OUTPUT")
self.add_pin_list(self.bitcell_array_wl_names, "INPUT") self.add_pin_list(self.bitcell_array_wl_names, "INPUT")
# Need to sort by port order since dictionary values may not be in order # Need to sort by port order since dictionary values may not be in order
wl_names = [self.rbl_wl_names[x] for x in sorted(self.rbl_wl_names.keys())] wl_names = [self.rbl_wl_names[x] for x in sorted(self.rbl_wl_names.keys())]
for pin_name in wl_names: for pin_name in wl_names:
self.add_pin(pin_name,"INPUT") self.add_pin(pin_name,"INPUT")
self.add_pin("vdd", "POWER") self.add_pin("vdd", "POWER")
self.add_pin("gnd", "GROUND") self.add_pin("gnd", "GROUND")
def create_instances(self): def create_instances(self):
""" Create the module instances used in this design """ """ Create the module instances used in this design """
supplies = ["vdd", "gnd"] supplies = ["vdd", "gnd"]
# Used for names/dimensions only # Used for names/dimensions only
self.cell = factory.create(module_type="bitcell") self.cell = factory.create(module_type="bitcell")
# Main array # Main array
self.bitcell_array_inst=self.add_inst(name="bitcell_array", self.bitcell_array_inst=self.add_inst(name="bitcell_array",
mod=self.bitcell_array) mod=self.bitcell_array)
@ -231,35 +249,33 @@ class replica_bitcell_array(design.design):
self.replica_col_inst[port]=self.add_inst(name="replica_col_{}".format(port), self.replica_col_inst[port]=self.add_inst(name="replica_col_{}".format(port),
mod=self.replica_columns[port]) mod=self.replica_columns[port])
self.connect_inst(self.replica_bl_names[port] + self.replica_col_wl_names + supplies) self.connect_inst(self.replica_bl_names[port] + self.replica_col_wl_names + supplies)
# Dummy rows under the bitcell array (connected with with the replica cell wl) # Dummy rows under the bitcell array (connected with with the replica cell wl)
self.dummy_row_replica_inst = {} self.dummy_row_replica_inst = {}
for port in range(self.left_rbl+self.right_rbl): for port in range(self.left_rbl+self.right_rbl):
self.dummy_row_replica_inst[port]=self.add_inst(name="dummy_row_{}".format(port), self.dummy_row_replica_inst[port]=self.add_inst(name="dummy_row_{}".format(port),
mod=self.dummy_row) mod=self.dummy_row)
self.connect_inst(self.dummy_row_bl_names + self.replica_wl_names[port] + supplies) self.connect_inst(self.dummy_row_bl_names + self.replica_wl_names[port] + supplies)
# Top/bottom dummy rows # Top/bottom dummy rows or col caps
self.dummy_row_bot_inst=self.add_inst(name="dummy_row_bot", self.dummy_row_bot_inst=self.add_inst(name="dummy_row_bot",
mod=self.dummy_row) mod=self.edge_row)
self.connect_inst(self.dummy_row_bl_names + [x+"_bot" for x in self.dummy_cell_wl_names] + supplies) self.connect_inst(self.dummy_row_bl_names + [x+"_bot" for x in self.dummy_cell_wl_names] + supplies)
self.dummy_row_top_inst=self.add_inst(name="dummy_row_top", self.dummy_row_top_inst=self.add_inst(name="dummy_row_top",
mod=self.dummy_row) mod=self.edge_row)
self.connect_inst(self.dummy_row_bl_names + [x+"_top" for x in self.dummy_cell_wl_names] + supplies) self.connect_inst(self.dummy_row_bl_names + [x+"_top" for x in self.dummy_cell_wl_names] + supplies)
# Left/right Dummy columns # Left/right Dummy columns
self.dummy_col_left_inst=self.add_inst(name="dummy_col_left", self.dummy_col_left_inst=self.add_inst(name="dummy_col_left",
mod=self.dummy_col_left) mod=self.edge_col_left)
self.connect_inst([x+"_left" for x in self.dummy_cell_bl_names] + self.dummy_col_wl_names + supplies) self.connect_inst([x+"_left" for x in self.dummy_cell_bl_names] + self.dummy_col_wl_names + supplies)
self.dummy_col_right_inst=self.add_inst(name="dummy_col_right", self.dummy_col_right_inst=self.add_inst(name="dummy_col_right",
mod=self.dummy_col_right) mod=self.edge_col_right)
self.connect_inst([x+"_right" for x in self.dummy_cell_bl_names] + self.dummy_col_wl_names + supplies) self.connect_inst([x+"_right" for x in self.dummy_cell_bl_names] + self.dummy_col_wl_names + supplies)
def create_layout(self): def create_layout(self):
self.height = (self.row_size+self.extra_rows)*self.dummy_row.height self.height = (self.row_size+self.extra_rows)*self.dummy_row.height
@ -267,7 +283,7 @@ class replica_bitcell_array(design.design):
# This is a bitcell x bitcell offset to scale # This is a bitcell x bitcell offset to scale
offset = vector(self.cell.width, self.cell.height) offset = vector(self.cell.width, self.cell.height)
self.bitcell_array_inst.place(offset=[0,0]) self.bitcell_array_inst.place(offset=[0,0])
# To the left of the bitcell array # To the left of the bitcell array
@ -276,7 +292,6 @@ class replica_bitcell_array(design.design):
# To the right of the bitcell array # To the right of the bitcell array
for bit in range(self.right_rbl): for bit in range(self.right_rbl):
self.replica_col_inst[self.left_rbl+bit].place(offset=offset.scale(bit,-self.left_rbl-1)+self.bitcell_array_inst.lr()) self.replica_col_inst[self.left_rbl+bit].place(offset=offset.scale(bit,-self.left_rbl-1)+self.bitcell_array_inst.lr())
# Far top dummy row (first row above array is NOT flipped) # Far top dummy row (first row above array is NOT flipped)
flip_dummy = self.right_rbl%2 flip_dummy = self.right_rbl%2
@ -298,17 +313,17 @@ class replica_bitcell_array(design.design):
for bit in range(self.right_rbl): for bit in range(self.right_rbl):
self.dummy_row_replica_inst[self.left_rbl+bit].place(offset=offset.scale(0,bit+bit%2)+self.bitcell_array_inst.ul(), self.dummy_row_replica_inst[self.left_rbl+bit].place(offset=offset.scale(0,bit+bit%2)+self.bitcell_array_inst.ul(),
mirror="MX" if bit%2 else "R0") mirror="MX" if bit%2 else "R0")
self.translate_all(offset.scale(-1-self.left_rbl,-1-self.left_rbl)) self.translate_all(offset.scale(-1-self.left_rbl,-1-self.left_rbl))
self.add_layout_pins() self.add_layout_pins()
self.add_boundary() self.add_boundary()
self.DRC_LVS() self.DRC_LVS()
def add_layout_pins(self): def add_layout_pins(self):
""" Add the layout pins """ """ Add the layout pins """
@ -341,10 +356,10 @@ class replica_bitcell_array(design.design):
for (pin_name,wl_name) in zip(self.cell.get_all_wl_names(),self.replica_wl_names[port]): for (pin_name,wl_name) in zip(self.cell.get_all_wl_names(),self.replica_wl_names[port]):
# +1 for dummy row # +1 for dummy row
pin_bit = port+1 pin_bit = port+1
# +row_size if above the array # +row_size if above the array
if port>=self.left_rbl: if port>=self.left_rbl:
pin_bit += self.row_size pin_bit += self.row_size
pin_name += "_{}".format(pin_bit) pin_name += "_{}".format(pin_bit)
pin = inst.get_pin(pin_name) pin = inst.get_pin(pin_name)
if wl_name in self.rbl_wl_names.values(): if wl_name in self.rbl_wl_names.values():
@ -368,20 +383,27 @@ class replica_bitcell_array(design.design):
offset=pin.ll().scale(1, 0), offset=pin.ll().scale(1, 0),
width=pin.width(), width=pin.width(),
height=self.height) height=self.height)
# For specific technologies, there is no vdd via within the bitcell. Instead vdd is connect via end caps.
try:
bitcell_no_vdd_pin = cell_properties.bitcell.no_vdd_via
except AttributeError:
bitcell_no_vdd_pin = False
for pin_name in ["vdd", "gnd"]: for pin_name in ["vdd", "gnd"]:
for inst in self.insts: for inst in self.insts:
pin_list = inst.get_pins(pin_name) pin_list = inst.get_pins(pin_name)
for pin in pin_list: for pin in pin_list:
self.add_power_pin(name=pin_name, if not (pin_name == "vdd" and bitcell_no_vdd_pin):
loc=pin.center(), self.add_power_pin(name=pin_name,
directions=("V", "V"), loc=pin.center(),
start_layer=pin.layer) directions=("V", "V"),
start_layer=pin.layer)
def get_rbl_wl_name(self, port): def get_rbl_wl_name(self, port):
""" Return the WL for the given RBL port """ """ Return the WL for the given RBL port """
return self.rbl_wl_names[port] return self.rbl_wl_names[port]
def get_rbl_bl_name(self, port): def get_rbl_bl_name(self, port):
""" Return the BL for the given RBL port """ """ Return the BL for the given RBL port """
return self.rbl_bl_names[port] return self.rbl_bl_names[port]
@ -393,17 +415,17 @@ class replica_bitcell_array(design.design):
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."""
from tech import drc, parameter from tech import drc, parameter
# Dynamic Power from Bitline # Dynamic Power from Bitline
bl_wire = self.gen_bl_wire() bl_wire = self.gen_bl_wire()
cell_load = 2 * bl_wire.return_input_cap() cell_load = 2 * bl_wire.return_input_cap()
bl_swing = OPTS.rbl_delay_percentage bl_swing = OPTS.rbl_delay_percentage
freq = spice["default_event_frequency"] freq = spice["default_event_frequency"]
bitline_dynamic = self.calc_dynamic_power(corner, cell_load, freq, swing=bl_swing) bitline_dynamic = self.calc_dynamic_power(corner, cell_load, freq, swing=bl_swing)
#Calculate the bitcell power which currently only includes leakage #Calculate the bitcell power which currently only includes leakage
cell_power = self.cell.analytical_power(corner, load) cell_power = self.cell.analytical_power(corner, load)
#Leakage power grows with entire array and bitlines. #Leakage power grows with entire array and bitlines.
total_power = self.return_power(cell_power.dynamic + bitline_dynamic * self.column_size, total_power = self.return_power(cell_power.dynamic + bitline_dynamic * self.column_size,
cell_power.leakage * self.column_size * self.row_size) cell_power.leakage * self.column_size * self.row_size)
@ -429,13 +451,13 @@ class replica_bitcell_array(design.design):
def graph_exclude_bits(self, targ_row, targ_col): def graph_exclude_bits(self, targ_row, targ_col):
"""Excludes bits in column from being added to graph except target""" """Excludes bits in column from being added to graph except target"""
self.bitcell_array.graph_exclude_bits(targ_row, targ_col) self.bitcell_array.graph_exclude_bits(targ_row, targ_col)
def graph_exclude_replica_col_bits(self): def graph_exclude_replica_col_bits(self):
"""Exclude all replica/dummy cells in the replica columns except the replica bit.""" """Exclude all replica/dummy cells in the replica columns except the replica bit."""
for port in range(self.left_rbl+self.right_rbl): for port in range(self.left_rbl+self.right_rbl):
self.replica_columns[port].exclude_all_but_replica() self.replica_columns[port].exclude_all_but_replica()
def get_cell_name(self, inst_name, row, col): def get_cell_name(self, inst_name, row, col):
"""Gets the spice name of the target bitcell.""" """Gets the spice name of the target bitcell."""
return self.bitcell_array.get_cell_name(inst_name+'.x'+self.bitcell_array_inst.name, row, col) return self.bitcell_array.get_cell_name(inst_name+'.x'+self.bitcell_array_inst.name, row, col)

View File

@ -1,11 +1,11 @@
# See LICENSE for licensing information. # See LICENSE for licensing information.
# #
# Copyright (c) 2016-2019 Regents of the University of California # Copyright (c) 2016-2019 Regents of the University of California
# All rights reserved. # All rights reserved.
# #
import debug import debug
import design import design
from tech import drc from tech import drc, cell_properties
import contact import contact
from sram_factory import factory from sram_factory import factory
from vector import vector from vector import vector
@ -16,7 +16,7 @@ class replica_column(design.design):
Generate a replica bitline column for the replica array. Generate a replica bitline column for the replica array.
Rows is the total number of rows i the main array. Rows is the total number of rows i the main array.
Left_rbl and right_rbl are the number of left and right replica bitlines. Left_rbl and right_rbl are the number of left and right replica bitlines.
Replica bit specifies which replica column this is (to determine where to put the Replica bit specifies which replica column this is (to determine where to put the
replica cell. replica cell.
""" """
@ -31,15 +31,15 @@ class replica_column(design.design):
# left, right, regular rows plus top/bottom dummy cells # left, right, regular rows plus top/bottom dummy cells
self.total_size = self.left_rbl+rows+self.right_rbl+2 self.total_size = self.left_rbl+rows+self.right_rbl+2
self.column_offset = column_offset self.column_offset = column_offset
debug.check(replica_bit!=0 and replica_bit!=rows,"Replica bit cannot be the dummy row.") debug.check(replica_bit!=0 and replica_bit!=rows,"Replica bit cannot be the dummy row.")
debug.check(replica_bit<=left_rbl or replica_bit>=self.total_size-right_rbl-1, debug.check(replica_bit<=left_rbl or replica_bit>=self.total_size-right_rbl-1,
"Replica bit cannot be in the regular array.") "Replica bit cannot be in the regular array.")
self.create_netlist() self.create_netlist()
if not OPTS.netlist_only: if not OPTS.netlist_only:
self.create_layout() self.create_layout()
def create_netlist(self): def create_netlist(self):
self.add_modules() self.add_modules()
self.add_pins() self.add_pins()
@ -47,7 +47,7 @@ class replica_column(design.design):
def create_layout(self): def create_layout(self):
self.height = self.total_size*self.cell.height self.height = self.total_size*self.cell.height
self.width = self.cell.width self.width = self.cell.width
self.place_instances() self.place_instances()
self.add_layout_pins() self.add_layout_pins()
@ -55,7 +55,7 @@ class replica_column(design.design):
self.DRC_LVS() self.DRC_LVS()
def add_pins(self): def add_pins(self):
for bl_name in self.cell.get_all_bitline_names(): for bl_name in self.cell.get_all_bitline_names():
# In the replica column, these are only outputs! # In the replica column, these are only outputs!
self.add_pin("{0}_{1}".format(bl_name,0), "OUTPUT") self.add_pin("{0}_{1}".format(bl_name,0), "OUTPUT")
@ -63,7 +63,7 @@ class replica_column(design.design):
for row in range(self.total_size): for row in range(self.total_size):
for wl_name in self.cell.get_all_wl_names(): for wl_name in self.cell.get_all_wl_names():
self.add_pin("{0}_{1}".format(wl_name,row), "INPUT") self.add_pin("{0}_{1}".format(wl_name,row), "INPUT")
self.add_pin("vdd", "POWER") self.add_pin("vdd", "POWER")
self.add_pin("gnd", "GROUND") self.add_pin("gnd", "GROUND")
@ -72,27 +72,49 @@ class replica_column(design.design):
self.add_mod(self.replica_cell) self.add_mod(self.replica_cell)
self.dummy_cell = factory.create(module_type="dummy_bitcell") self.dummy_cell = factory.create(module_type="dummy_bitcell")
self.add_mod(self.dummy_cell) self.add_mod(self.dummy_cell)
try:
edge_module_type = ("col_cap_bitcell" if cell_properties.bitcell.end_caps else "dummy_bitcell")
except AttributeError:
edge_module_type = "dummy_bitcell"
self.edge_cell = factory.create(module_type=edge_module_type)
self.add_mod(self.edge_cell)
# Used for pin names only # Used for pin names only
self.cell = factory.create(module_type="bitcell") self.cell = factory.create(module_type="bitcell")
def create_instances(self): def create_instances(self):
try:
end_caps_enabled = cell_properties.bitcell.end_caps
except AttributeError:
end_caps_enabled = False
self.cell_inst = {} self.cell_inst = {}
for row in range(self.total_size): for row in range(self.total_size):
name="rbc_{0}".format(row) name="rbc_{0}".format(row)
# Top/bottom cell are always dummy cells. # Top/bottom cell are always dummy cells.
# Regular array cells are replica cells (>left_rbl and <rows-right_rbl) # Regular array cells are replica cells (>left_rbl and <rows-right_rbl)
# Replic bit specifies which other bit (in the full range (0,rows) to make a replica cell. # Replic bit specifies which other bit (in the full range (0,rows) to make a replica cell.
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))
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))
elif (row == 0 or row == self.total_size - 1):
self.cell_inst[row]=self.add_inst(name=name,
mod=self.edge_cell)
if end_caps_enabled:
self.connect_inst(self.get_bitcell_pins_col_cap(0, row))
else:
self.connect_inst(self.get_bitcell_pins(0, row))
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(0, row))
def place_instances(self): def place_instances(self):
from tech import cell_properties from tech import cell_properties
# Flip the mirrors if we have an odd number of replica+dummy rows at the bottom # Flip the mirrors if we have an odd number of replica+dummy rows at the bottom
@ -131,36 +153,36 @@ class replica_column(design.design):
def add_layout_pins(self): def add_layout_pins(self):
""" Add the layout pins """ """ Add the layout pins """
for bl_name in self.cell.get_all_bitline_names(): for bl_name in self.cell.get_all_bitline_names():
bl_pin = self.cell_inst[0].get_pin(bl_name) bl_pin = self.cell_inst[1].get_pin(bl_name)
self.add_layout_pin(text=bl_name, self.add_layout_pin(text=bl_name,
layer="m2", layer=bl_pin.layer,
offset=bl_pin.ll(), offset=bl_pin.ll(),
width=bl_pin.width(), width=bl_pin.width(),
height=self.height) height=self.height)
for row in range(self.total_size): for row in range(1, self.total_size - 1):
for wl_name in self.cell.get_all_wl_names(): for wl_name in self.cell.get_all_wl_names():
wl_pin = self.cell_inst[row].get_pin(wl_name) wl_pin = self.cell_inst[row].get_pin(wl_name)
self.add_layout_pin(text="{0}_{1}".format(wl_name,row), self.add_layout_pin(text="{0}_{1}".format(wl_name,row),
layer="m1", layer=wl_pin.layer,
offset=wl_pin.ll().scale(0,1), offset=wl_pin.ll().scale(0,1),
width=self.width, width=self.width,
height=wl_pin.height()) height=wl_pin.height())
# For every second row and column, add a via for gnd and vdd # For every second row and column, add a via for gnd and vdd
for row in range(self.total_size): for row in range(1, self.total_size - 1):
inst = self.cell_inst[row] inst = self.cell_inst[row]
for pin_name in ["vdd", "gnd"]: for pin_name in ["vdd", "gnd"]:
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, col, row):
""" 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 """
bitcell_pins = [] bitcell_pins = []
pin_names = self.cell.get_all_bitline_names() pin_names = self.cell.get_all_bitline_names()
for pin in pin_names: for pin in pin_names:
bitcell_pins.append(pin+"_{0}".format(col)) bitcell_pins.append(pin+"_{0}".format(col))
@ -169,12 +191,26 @@ class replica_column(design.design):
bitcell_pins.append(pin+"_{0}".format(row)) bitcell_pins.append(pin+"_{0}".format(row))
bitcell_pins.append("vdd") bitcell_pins.append("vdd")
bitcell_pins.append("gnd") bitcell_pins.append("gnd")
return bitcell_pins return bitcell_pins
def get_bitcell_pins_col_cap(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))
bitcell_pins.append("vdd")
return bitcell_pins
def exclude_all_but_replica(self): def exclude_all_but_replica(self):
"""Excludes all bits except the replica cell (self.replica_bit).""" """Excludes all bits except the replica cell (self.replica_bit)."""
for row, cell in self.cell_inst.items(): for row, cell in self.cell_inst.items():
if row != self.replica_bit: if row != self.replica_bit:
self.graph_inst_exclude.add(cell) self.graph_inst_exclude.add(cell)

View File

@ -0,0 +1,128 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California
# All rights reserved.
#
from bitcell_base_array import bitcell_base_array
from sram_factory import factory
from globals import OPTS
from tech import cell_properties
class row_cap_array(bitcell_base_array):
"""
Generate a dummy row/column for the replica array.
"""
def __init__(self, cols, rows, column_offset=0, mirror=0, name=""):
super().__init__(cols, rows, name, column_offset)
self.mirror = mirror
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_array("dummy_r{0}_c{1}", self.mirror)
self.add_layout_pins()
self.add_boundary()
self.DRC_LVS()
def add_modules(self):
""" Add the modules used in this design """
self.dummy_cell = factory.create(module_type="row_cap_bitcell_1rw_1r") # TODO: make module_type generic
self.add_mod(self.dummy_cell)
self.cell = factory.create(module_type="bitcell")
def create_instances(self):
""" Create the module instances used in this design """
self.cell_inst = {}
for col in range(self.column_size):
for row in range(1, self.row_size - 1):
name = "bit_r{0}_c{1}".format(row, col)
self.cell_inst[row,col]=self.add_inst(name=name,
mod=self.dummy_cell)
self.connect_inst(self.get_bitcell_pins(col, row))
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
"""
pin_name = cell_properties.bitcell.cell_1rw1r.pin
bitcell_pins = ["{0}_{1}".format(pin_name.wl0, row),
"{0}_{1}".format(pin_name.wl1, row),
"gnd"]
return bitcell_pins
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 = self.cell.height
tempx, dir_y = self._adjust_x_offset(xoffset, col, self.column_offset)
for row in range(1, self.row_size - 1):
name = name_template.format(row, col)
tempy, dir_x = self._adjust_y_offset(yoffset, row, row_offset)
if dir_x and dir_y:
dir_key = "XY"
elif dir_x:
dir_key = "MX"
elif dir_y:
dir_key = "MY"
else:
dir_key = ""
self.cell_inst[row,col].place(offset=[tempx, tempy],
mirror=dir_key)
yoffset += self.cell.height
xoffset += self.cell.width
def add_layout_pins(self):
""" Add the layout pins """
row_list = self.cell.get_all_wl_names()
for row in range(1, self.row_size - 1):
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())
# Add vdd/gnd via stacks
for row in range(1, self.row_size - 1):
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(),
start_layer=pin.layer)
# def input_load(self):
# wl_wire = self.gen_wl_wire()
# return wl_wire.return_input_cap()
#
# def get_wordline_cin(self):
# """Get the relative input capacitance from the wordline connections in all the bitcell"""
# #A single wordline is connected to all the bitcells in a single row meaning the capacitance depends on the # of columns
# bitcell_wl_cin = self.cell.get_wl_cin()
# total_cin = bitcell_wl_cin * self.column_size
# return total_cin

View File

@ -21,10 +21,10 @@ class options(optparse.Values):
################### ###################
# This is the technology directory. # This is the technology directory.
openram_tech = "" openram_tech = ""
# This is the name of the technology. # This is the name of the technology.
tech_name = "" tech_name = ""
# Port configuration (1-2 ports allowed) # Port configuration (1-2 ports allowed)
num_rw_ports = 1 num_rw_ports = 1
num_r_ports = 0 num_r_ports = 0
@ -32,7 +32,7 @@ class options(optparse.Values):
# Write mask size, default will be overwritten with word_size if not user specified # Write mask size, default will be overwritten with word_size if not user specified
write_size = None write_size = None
# These will get initialized by the user or the tech file # These will get initialized by the user or the tech file
nominal_corner_only = False nominal_corner_only = False
supply_voltages = "" supply_voltages = ""
@ -50,17 +50,17 @@ class options(optparse.Values):
################### ###################
# Approximate percentage of delay compared to bitlines # Approximate percentage of delay compared to bitlines
rbl_delay_percentage = 0.5 rbl_delay_percentage = 0.5
# Allow manual adjustment of the delay chain over automatic # Allow manual adjustment of the delay chain over automatic
use_tech_delay_chain_size = False use_tech_delay_chain_size = False
delay_chain_stages = 9 delay_chain_stages = 9
delay_chain_fanout_per_stage = 4 delay_chain_fanout_per_stage = 4
################### ###################
# Debug options. # Debug options.
################### ###################
# This is the temp directory where all intermediate results are stored. # This is the temp directory where all intermediate results are stored.
try: try:
# If user defined the temporary location in their environment, use it # If user defined the temporary location in their environment, use it
@ -91,7 +91,7 @@ class options(optparse.Values):
# Run with extracted parasitics # Run with extracted parasitics
use_pex = False use_pex = False
################### ###################
# Tool options # Tool options
################### ###################
@ -108,7 +108,7 @@ class options(optparse.Values):
drc_exe = None drc_exe = None
lvs_exe = None lvs_exe = None
pex_exe = None pex_exe = None
# Should we print out the banner at startup # Should we print out the banner at startup
print_banner = True print_banner = True
@ -127,6 +127,7 @@ class options(optparse.Values):
bank_select = "bank_select" bank_select = "bank_select"
bitcell_array = "bitcell_array" bitcell_array = "bitcell_array"
bitcell = "bitcell" bitcell = "bitcell"
col_cap_bitcell = "col_cap_bitcell"
column_mux_array = "single_level_column_mux_array" column_mux_array = "single_level_column_mux_array"
control_logic = "control_logic" control_logic = "control_logic"
decoder = "hierarchical_decoder" decoder = "hierarchical_decoder"
@ -138,6 +139,7 @@ class options(optparse.Values):
ptx = "ptx" ptx = "ptx"
replica_bitcell = "replica_bitcell" replica_bitcell = "replica_bitcell"
replica_bitline = "replica_bitline" replica_bitline = "replica_bitline"
row_cap_bitcell = "row_cap_bitcell"
sense_amp_array = "sense_amp_array" sense_amp_array = "sense_amp_array"
sense_amp = "sense_amp" sense_amp = "sense_amp"
tri_gate_array = "tri_gate_array" tri_gate_array = "tri_gate_array"
@ -146,4 +148,3 @@ class options(optparse.Values):
write_driver_array = "write_driver_array" write_driver_array = "write_driver_array"
write_driver = "write_driver" write_driver = "write_driver"
write_mask_and_array = "write_mask_and_array" write_mask_and_array = "write_mask_and_array"

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# See LICENSE for licensing information. # See LICENSE for licensing information.
# #
# Copyright (c) 2016-2019 Regents of the University of California # Copyright (c) 2016-2019 Regents of the University of California
# All rights reserved. # All rights reserved.
# #
import unittest import unittest
@ -22,13 +22,15 @@ class replica_bitcell_array_test(openram_test):
OPTS.bitcell = "bitcell_1rw_1r" OPTS.bitcell = "bitcell_1rw_1r"
OPTS.replica_bitcell = "replica_bitcell_1rw_1r" OPTS.replica_bitcell = "replica_bitcell_1rw_1r"
OPTS.dummy_bitcell="dummy_bitcell_1rw_1r" OPTS.dummy_bitcell="dummy_bitcell_1rw_1r"
OPTS.col_cap_bitcell="col_cap_bitcell_1rw_1r"
OPTS.row_cap_bitcell="row_cap_bitcell_1rw_1r"
OPTS.num_rw_ports = 1 OPTS.num_rw_ports = 1
OPTS.num_r_ports = 1 OPTS.num_r_ports = 1
OPTS.num_w_ports = 0 OPTS.num_w_ports = 0
debug.info(2, "Testing 4x4 array for cell_1rw_1r") # debug.info(2, "Testing 4x4 array for cell_1rw_1r")
a = factory.create(module_type="replica_bitcell_array", cols=4, rows=4, left_rbl=2, right_rbl=0, bitcell_ports=[0,1]) # a = factory.create(module_type="replica_bitcell_array", cols=4, rows=4, left_rbl=2, right_rbl=0, bitcell_ports=[0,1])
self.local_check(a) # self.local_check(a)
debug.info(2, "Testing 4x4 array for cell_1rw_1r") debug.info(2, "Testing 4x4 array for cell_1rw_1r")
a = factory.create(module_type="replica_bitcell_array", cols=4, rows=4, left_rbl=1, right_rbl=1, bitcell_ports=[0,1]) a = factory.create(module_type="replica_bitcell_array", cols=4, rows=4, left_rbl=1, right_rbl=1, bitcell_ports=[0,1])