Merge remote-tracking branch 'private/dev' into dev

This commit is contained in:
mrg 2020-10-16 13:54:43 -07:00
commit db1bcd0774
20 changed files with 338 additions and 1189 deletions

View File

@ -44,21 +44,16 @@ class lib:
def prepare_tables(self): def prepare_tables(self):
""" Determine the load/slews if they aren't specified in the config file. """ """ Determine the load/slews if they aren't specified in the config file. """
# These are the parameters to determine the table sizes # These are the parameters to determine the table sizes
#self.load_scales = np.array([0.1, 0.25, 0.5, 1, 2, 4, 8]) self.load_scales = np.array(OPTS.load_scales)
self.load_scales = np.array([0.25, 1, 4])
#self.load_scales = np.array([0.25, 1])
self.load = tech.spice["dff_in_cap"] self.load = tech.spice["dff_in_cap"]
self.loads = self.load_scales * self.load self.loads = self.load_scales * self.load
debug.info(1, "Loads: {0}".format(self.loads)) debug.info(1, "Loads: {0}".format(self.loads))
#self.slew_scales = np.array([0.1, 0.25, 0.5, 1, 2, 4, 8]) self.slew_scales = np.array(OPTS.slew_scales)
self.slew_scales = np.array([0.25, 1, 8])
#self.slew_scales = np.array([0.25, 1])
self.slew = tech.spice["rise_time"] self.slew = tech.spice["rise_time"]
self.slews = self.slew_scales * self.slew self.slews = self.slew_scales * self.slew
debug.info(1, "Slews: {0}".format(self.slews)) debug.info(1, "Slews: {0}".format(self.slews))
def create_corners(self): def create_corners(self):
""" Create corners for characterization. """ """ Create corners for characterization. """
# Get the corners from the options file # Get the corners from the options file

View File

@ -1,103 +0,0 @@
# 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 s8_bitcell(bitcell_base.bitcell_base):
"""
A single bit cell (6T, 8T, etc.) 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.
"""
# If we have a split WL bitcell, if not be backwards
# compatible in the tech file
if props.compare_ports(props.bitcell.split_wl):
pin_names = ["bl0", "bl1", "wl0", "wl1", "vpwr", "vgnd"]
type_list = ["OUTPUT", "OUTPUT", "INPUT", "INPUT", "POWER", "GROUND"]
else:
pin_names = [props.bitcell.cell_s8_6t.pin.bl,
props.bitcell.cell_s8_6t.pin.br,
props.bitcell.cell_s8_6t.pin.wl,
"vpwr",
"vgnd"]
type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]
storage_nets = ['Q', 'Q_bar']
def __init__(self, version, name=""):
# Ignore the name argument
if version == "opt1":
self.name = "s8sram_cell_opt1"
elif version == "opt1a":
self.name = "s8sram_cell_opt1a"
bitcell_base.bitcell_base.__init__(self, self.name)
debug.info(2, "Create bitcell")
self.pin_map = utils.get_libcell_pins(self.pin_names, self.name, GDS["unit"])
self.add_pin_types(self.type_list)
self.nets_match = self.do_nets_exist(self.storage_nets)
(self.width, self.height) = utils.get_libcell_size(self.name,
GDS["unit"],
layer["mem"])
def get_all_wl_names(self):
""" Creates a list of all wordline pin names """
if props.compare_ports(props.bitcell.split_wl):
row_pins = ["wl0", "wl1"]
else:
row_pins = [props.bitcell.cell_s8_6t.pin.wl]
return row_pins
def get_all_bitline_names(self):
""" Creates a list of all bitline pin names (both bl and br) """
pin = props.bitcell.cell_s8_6t.pin
column_pins = [pin.bl, pin.br]
return column_pins
def get_all_bl_names(self):
""" Creates a list of all bl pins names """
return [props.bitcell.cell_s8_6t.pin.bl]
def get_all_br_names(self):
""" Creates a list of all br pins names """
return [props.bitcell.cell_s8_6t.pin.br]
def get_bl_name(self, port=0):
"""Get bl name"""
debug.check(port == 0, "One port for bitcell only.")
return props.bitcell.cell_s8_6t.pin.bl
def get_br_name(self, port=0):
"""Get bl name"""
debug.check(port == 0, "One port for bitcell only.")
return props.bitcell.cell_s8_6t.pin.br
def get_wl_name(self, port=0):
"""Get wl name"""
if props.compare_ports(props.bitcell.split_wl):
return "wl{}".format(port)
else:
debug.check(port == 0, "One port for bitcell only.")
return props.bitcell.cell_s8_6t.pin.wl
def build_graph(self, graph, inst_name, port_nets):
"""
Adds edges based on inputs/outputs.
Overrides base class function.
"""
self.add_graph_edges(graph, port_nets)

View File

@ -1,137 +0,0 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California
# All rights reserved.
#
import design
from sram_factory import factory
from globals import OPTS
from tech import cell_properties
class s8_col_cap_array(design.design):
"""
Generate a dummy row/column for the replica array.
"""
def __init__(self, rows, cols, location, column_offset=0, mirror=0, name=""):
super().__init__(name)
self.rows = rows
self.cols = cols
self.location = location
self.column_offset = column_offset
self.mirror = mirror
self.no_instances = True
self.all_wordline_names = []
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("col_cap_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 """
if self.location == "top":
self.colend1 = factory.create(module_type="s8_col_end", version = "colend")
self.add_mod(self.colend1)
self.colend2 = factory.create(module_type="s8_col_end", version = "colend_p_cent")
self.add_mod(self.colend2)
elif self.location == "bottom":
self.colend1 = factory.create(module_type="s8_col_end", version = "colenda")
self.add_mod(self.colend1)
self.colend2 = factory.create(module_type="s8_col_end", version = "colenda_p_cent")
self.add_mod(self.colend2)
self.cell = factory.create(module_type="s8_bitcell", version = "opt1")
def create_instances(self):
""" Create the module instances used in this design """
self.cell_inst = {}
self.array_layout = []
alternate_bitcell = 0
for col in range((self.cols * 2 )-1):
row_layout = []
name="rca_{0}".format(col)
# Top/bottom cell are always dummy cells.
# 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.
if alternate_bitcell == 0:
row_layout.append(self.colend1)
self.cell_inst[col]=self.add_inst(name=name, mod=self.colend1)
#self.connect_inst(self.get_bitcell_pins(row, 0))
alternate_bitcell = 1
else:
row_layout.append(self.colend2)
self.cell_inst[col]=self.add_inst(name=name,mod=self.colend2)
#self.connect_inst(self.get_bitcell_pins(row, 0))
alternate_bitcell = 0
self.array_layout.append(row_layout)
def get_bitcell_pins(self, row, col):
"""
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_6t.pin
bitcell_pins = ["{0}_{1}".format(pin_name.bl0, col),
"{0}_{1}".format(pin_name.br0, col),
"vdd"]
return bitcell_pins
def place_array(self, name_template, row_offset=0):
self.height = self.colend1.height
self.width = (self.colend1.width + self.colend2.width) * self.cols - self.colend2.width
yoffset = 0.0
xoffset = 0.0
for row in range(0, len(self.array_layout)):
inst = self.insts[row]
inst.place(offset=[xoffset, yoffset])
xoffset += inst.width
def add_pins(self):
for row in range(self.cols):
for port in self.all_ports:
self.add_pin("bl{}_{}".format(port, row), "OUTPUT")
self.add_pin("br{}_{}".format(port, row), "OUTPUT")
self.add_pin("vpwr", "POWER")
self.add_pin("vgnd", "GROUND")
def add_layout_pins(self):
""" Add the layout pins """
return
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)

View File

@ -1,37 +0,0 @@
# 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
import utils
from tech import layer, GDS
class s8_col_end(design.design):
def __init__(self, version, name=""):
super().__init__(name)
if version == "colend":
self.name = "s8sram16x16_colend"
elif version == "colend_p_cent":
self.name = "s8sram16x16_colend_p_cent"
elif version == "colenda":
self.name = "s8sram16x16_colenda"
elif version == "colenda_p_cent":
self.name = "s8sram16x16_colenda_p_cent"
else:
debug.error("Invalid type for col_end", -1)
design.design.__init__(self, name=self.name)
(self.width, self.height) = utils.get_libcell_size(self.name,
GDS["unit"],
layer["mem"])
# pin_map = utils.get_libcell_pins(pin_names, self.name, GDS["unit"])

View File

@ -1,34 +0,0 @@
# 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
import utils
from tech import layer, GDS
class s8_corner(design.design):
def __init__(self, location, name=""):
super().__init__(name)
if location == "ul":
self.name = "s8sram16x16_corner"
elif location == "ur":
self.name = "s8sram16x16_cornerb"
elif location == "ll":
self.name = "s8sram16x16_cornera"
elif location == "lr":
self.name = "s8sram16x16_cornera"
else:
debug.error("Invalid s8_corner location", -1)
design.design.__init__(self, name=self.name)
(self.width, self.height) = utils.get_libcell_size(self.name,
GDS["unit"],
layer["mem"])
# pin_map = utils.get_libcell_pins(pin_names, self.name, GDS["unit"])

View File

@ -1,52 +0,0 @@
# 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 design
import debug
import utils
from tech import GDS,layer,drc,parameter,cell_properties
from tech import cell_properties as props
import bitcell_base
from globals import OPTS
class s8_dummy_bitcell(bitcell_base.bitcell_base):
"""
A single bit cell (6T, 8T, etc.) 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.
"""
if props.compare_ports(props.bitcell.split_wl):
pin_names = ["bl", "br", "wl0", "wl1", "vdd", "gnd"]
type_list = ["OUTPUT", "OUTPUT", "INPUT", "INPUT" , "POWER", "GROUND"]
else:
pin_names = [props.bitcell.cell_s8_6t.pin.bl,
props.bitcell.cell_s8_6t.pin.br,
props.bitcell.cell_s8_6t.pin.wl,
"vpwr",
"vgnd"]
def __init__(self, version, name=""):
# Ignore the name argument
if version == "opt1":
self.name = "s8sram_cell_opt1"
self.border_structure = "s8sram_cell"
elif version == "opt1a":
self.name = "s8sram_cell_opt1a"
self.border_structure = "s8sram_cell"
bitcell_base.bitcell_base.__init__(self, self.name)
debug.info(2, "Create dummy bitcell")
(self.width, self.height) = utils.get_libcell_size(self.name,
GDS["unit"],
layer["mem"],
"s8sram_cell\x00")
self.pin_map = utils.get_libcell_pins(self.pin_names, self.name, GDS["unit"])

View File

@ -1,32 +0,0 @@
# 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
import utils
from tech import layer, GDS
class s8_internal(design.design):
def __init__(self, version, name=""):
super().__init__(name)
if version == "wlstrap":
self.name = "s8sram_wlstrap"
elif version == "wlstrap_p":
self.name = "s8sram16x16_wlstrap_p"
elif version == "wlstrapa":
self.name = "s8sram_wlstrapa"
else:
debug.error("Invalid version", -1)
design.design.__init__(self, name=self.name)
(self.width, self.height) = utils.get_libcell_size(self.name,
GDS["unit"],
layer["mem"])
# pin_map = utils.get_libcell_pins(pin_names, self.name, GDS["unit"])

View File

@ -1,81 +0,0 @@
# 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 design
import debug
import utils
from tech import GDS, layer, drc, parameter, cell_properties
from tech import cell_properties as props
from globals import OPTS
class replica_bitcell(design.design):
"""
A single bit cell (6T, 8T, etc.)
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. """
if props.compare_ports(props.bitcell.split_wl):
pin_names = ["bl", "br", "wl0", "wl1", "vdd", "gnd"]
type_list = ["OUTPUT", "OUTPUT", "INPUT", "INPUT" , "POWER", "GROUND"]
else:
pin_names = [props.bitcell.cell_6t.pin.bl,
props.bitcell.cell_6t.pin.br,
props.bitcell.cell_6t.pin.wl,
props.bitcell.cell_6t.pin.vdd,
props.bitcell.cell_6t.pin.gnd]
type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]
def __init__(self, version, name=""):
# Ignore the name argument
if version == "opt1":
self.name = "s8sram_cell_opt1"
self.border_structure = "s8sram_cell"
elif version == "opt1a":
self.name = "s8sram_cell_opt1a"
self.border_structure = "s8sram_cell"
self.pin_map = utils.get_libcell_pins(self.pin_names, self.name, GDS["unit"])
design.design.__init__(self, "replica_cell_6t")
debug.info(2, "Create replica bitcell object")
self.pin_map = utils.get_libcell_pins(self.pin_names, self.name, GDS["unit"])
self.add_pin_types(self.type_list)
(self.width, self.height) = utils.get_libcell_size(self.name,
GDS["unit"],
layer["mem"])
def get_stage_effort(self, load):
parasitic_delay = 1
size = 0.5 #This accounts for bitline being drained thought the access TX and internal node
cin = 3 #Assumes always a minimum sizes inverter. Could be specified in the tech.py file.
read_port_load = 0.5 #min size NMOS gate load
return logical_effort.logical_effort('bitline', size, cin, load+read_port_load, parasitic_delay, False)
def input_load(self):
"""Return the relative capacitance of the access transistor gates"""
# FIXME: This applies to bitline capacitances as well.
access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"]
return 2*access_tx_cin
def analytical_power(self, corner, load):
"""Bitcell power in nW. Only characterizes leakage."""
from tech import spice
leakage = spice["bitcell_leakage"]
dynamic = 0 #temporary
total_power = self.return_power(dynamic, leakage)
return total_power
def build_graph(self, graph, inst_name, port_nets):
"""Adds edges based on inputs/outputs. Overrides base class function."""
self.add_graph_edges(graph, port_nets)

View File

@ -1,162 +0,0 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California
# All rights reserved.
#
import design
from sram_factory import factory
from globals import OPTS
from tech import cell_properties
class s8_row_cap_array(design.design):
"""
Generate a dummy row/column for the replica array.
"""
def __init__(self, rows, cols, column_offset=0, mirror=0, name=""):
super().__init__(name)
self.rows = rows
self.cols = cols
self.column_offset = column_offset
self.mirror = mirror
self.no_instances = True
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 """
if self.column_offset == 0:
self.top_corner = factory.create(module_type="s8_corner", location = "ul")
self.add_mod(self.top_corner)
self.bottom_corner =factory.create(module_type="s8_corner", location = "ll")
self.add_mod(self.bottom_corner)
else:
self.top_corner = factory.create(module_type="s8_corner", location = "ur")
self.add_mod(self.top_corner)
self.bottom_corner = factory.create(module_type="s8_corner", location = "lr")
self.add_mod(self.bottom_corner)
self.rowend1 = factory.create(module_type="s8_row_end", version = "rowend")
self.add_mod(self.rowend1)
self.rowend2 = factory.create(module_type="s8_row_end", version = "rowenda")
self.add_mod(self.rowend2)
self.cell = factory.create(module_type="s8_bitcell", version = "opt1")
def create_instances(self):
""" Create the module instances used in this design """
self.cell_inst = {}
self.array_layout = []
alternate_bitcell = 0
for row in range(self.rows):
row_layout = []
name="rca_{0}".format(row)
# Top/bottom cell are always dummy cells.
# 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.
if (row < self.rows -1 and row >0):
if alternate_bitcell == 0:
row_layout.append(self.rowend1)
self.cell_inst[row]=self.add_inst(name=name, mod=self.rowend1)
self.connect_inst(["wl_0_{}".format(row-1), "vpwr"])
alternate_bitcell = 1
else:
row_layout.append(self.rowend2)
self.cell_inst[row]=self.add_inst(name=name,mod=self.rowend2)
self.connect_inst(["wl_0_{}".format(row-1), "vpwr"])
alternate_bitcell = 0
elif (row == 0):
row_layout.append(self.bottom_corner)
self.cell_inst[row]=self.add_inst(name=name, mod=self.bottom_corner)
self.connect_inst([])
elif (row == self.rows - 1):
row_layout.append(self.top_corner)
self.cell_inst[row]=self.add_inst(name=name, mod=self.top_corner)
self.connect_inst([])
self.array_layout.append(row_layout)
def get_bitcell_pins(self, row, col):
"""
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):
self.width = 0
self.height = 0
for inst in self.insts:
self.height += inst.height
if inst.width > self.width:
self.width = inst.width
yoffset = 0.0
for row in range(0, len(self.array_layout)):
xoffset = 0.0
for col in range(0, len(self.array_layout[row])):
inst = self.insts[col + row*len(self.array_layout[row])]
inst.place(offset=[xoffset, yoffset])
xoffset += inst.width
yoffset += inst.height
def add_pins(self):
for row in range(self.rows - 2):
for port in self.all_ports:
self.add_pin("wl_{}_{}".format(port, row), "OUTPUT")
self.add_pin("vpwr", "POWER")
self.add_pin("vgnd", "GROUND")
def add_layout_pins(self):
""" Add the layout pins """
if self.column_offset == 0:
row_list = self.cell.get_all_wl_names()
for row in range(1, self.rows-1):
if row > 0 and row < self.rows:
for cell_row in row_list:
wl_pin = self.cell_inst[row].get_pin(cell_row)
self.add_layout_pin(text=cell_row + "_0_{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.rows):
inst = self.cell_inst[row]
for pin_name in ["vpwr", "vgnd"]:
for pin in inst.get_pins(pin_name):
self.add_power_pin(name=pin.name,
loc=pin.center(),
start_layer=pin.layer)

View File

@ -1,38 +0,0 @@
# 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
import utils
from globals import OPTS
from tech import parameter, drc, layer, GDS
class s8_row_end(design.design):
def __init__(self, version, name=""):
super().__init__(name)
pin_names = ["wl", "vpwr"]
type_list = ["OUTPUT", "POWER"]
if version == "rowend":
self.name = "s8sram16x16_rowend"
elif version == "rowenda":
self.name = "s8sram16x16_rowenda"
else:
debug.error("Invalid type for row_end", -1)
design.design.__init__(self, name=self.name)
(self.width, self.height) = utils.get_libcell_size(self.name,
GDS["unit"],
layer["mem"],
"s8sram16x16_rowend_ce\x00")
self.pin_map = utils.get_libcell_pins(pin_names, self.name, GDS["unit"])
self.add_pin("wl", "OUTPUT")
self.add_pin("vpwr", "POWER")

View File

@ -7,8 +7,11 @@ process_corners = ["TT"]
supply_voltages = [1.0] supply_voltages = [1.0]
temperatures = [25] temperatures = [25]
route_supplies = True route_supplies = False
check_lvsdrc = True check_lvsdrc = True
# nominal_corners_only = True
load_scales = [0.5, 1, 4]
slew_scales = [0.5, 1]
output_path = "temp" output_path = "temp"
output_name = "sram_{0}_{1}_{2}".format(word_size, output_name = "sram_{0}_{1}_{2}".format(word_size,

View File

@ -459,17 +459,33 @@ def set_default_corner():
OPTS.process_corners = ["TT"] OPTS.process_corners = ["TT"]
else: else:
OPTS.process_corners = tech.spice["fet_models"].keys() OPTS.process_corners = tech.spice["fet_models"].keys()
if (OPTS.supply_voltages == ""): if (OPTS.supply_voltages == ""):
if OPTS.nominal_corner_only: if OPTS.nominal_corner_only:
OPTS.supply_voltages = [tech.spice["supply_voltages"][1]] OPTS.supply_voltages = [tech.spice["supply_voltages"][1]]
else: else:
OPTS.supply_voltages = tech.spice["supply_voltages"] OPTS.supply_voltages = tech.spice["supply_voltages"]
if (OPTS.temperatures == ""): if (OPTS.temperatures == ""):
if OPTS.nominal_corner_only: if OPTS.nominal_corner_only:
OPTS.temperatures = [tech.spice["temperatures"][1]] OPTS.temperatures = [tech.spice["temperatures"][1]]
else: else:
OPTS.temperatures = tech.spice["temperatures"] OPTS.temperatures = tech.spice["temperatures"]
# Load scales are fanout multiples of the DFF input cap
if (OPTS.load_scales == ""):
if OPTS.nominal_corner_only:
OPTS.load_scales = [4]
else:
OPTS.load_scales = [0.25, 1, 4]
# Load scales are fanout multiples of the default spice input slew
if (OPTS.slew_scales == ""):
if OPTS.nominal_corner_only:
OPTS.slew_scales = [1]
else:
OPTS.slew_scales = [0.25, 1, 4]
def import_tech(): def import_tech():
""" Dynamically adds the tech directory to the path and imports it. """ """ Dynamically adds the tech directory to the path and imports it. """

View File

@ -7,9 +7,7 @@
# #
import debug import debug
from bitcell_base_array import bitcell_base_array from bitcell_base_array import bitcell_base_array
from s8_corner import s8_corner
from tech import drc, spice from tech import drc, spice
from tech import cell_properties as props
from globals import OPTS from globals import OPTS
from sram_factory import factory from sram_factory import factory
@ -54,31 +52,18 @@ class bitcell_array(bitcell_base_array):
def add_modules(self): def add_modules(self):
""" Add the modules used in this design """ """ Add the modules used in this design """
if not props.compare_ports(props.bitcell_array.use_custom_cell_arrangement):
self.cell = factory.create(module_type="bitcell") self.cell = factory.create(module_type="bitcell")
self.add_mod(self.cell) self.add_mod(self.cell)
else:
self.cell = factory.create(module_type="s8_bitcell", version = "opt1")
self.add_mod(self.cell)
self.add_mod(factory.create(module_type="s8_bitcell", version = "opt1a"))
self.add_mod(factory.create(module_type="s8_internal", version = "wlstrap"))
self.add_mod(factory.create(module_type="s8_internal", version = "wlstrap_p"))
def create_instances(self): def create_instances(self):
""" Create the module instances used in this design """ """ Create the module instances used in this design """
self.cell_inst = {} self.cell_inst = {}
if not props.compare_ports(props.bitcell_array.use_custom_cell_arrangement):
for col in range(self.column_size): for col in range(self.column_size):
for row in range(self.row_size): for row in range(self.row_size):
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(row, col)) self.connect_inst(self.get_bitcell_pins(row, col))
else:
from tech import custom_cell_arrangement
custom_cell_arrangement(self)
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

@ -9,7 +9,6 @@ import debug
import design import design
from tech import cell_properties from tech import cell_properties
from sram_factory import factory from sram_factory import factory
from globals import OPTS
class bitcell_base_array(design.design): class bitcell_base_array(design.design):
@ -25,13 +24,7 @@ class bitcell_base_array(design.design):
self.column_offset = column_offset self.column_offset = column_offset
# Bitcell for port names only # Bitcell for port names only
if not cell_properties.compare_ports(cell_properties.bitcell_array.use_custom_cell_arrangement):
self.cell = factory.create(module_type="bitcell") self.cell = factory.create(module_type="bitcell")
else:
self.cell = factory.create(module_type="s8_bitcell", version="opt1")
self.cell2 = factory.create(module_type="s8_bitcell", version="opt1a")
self.strap = factory.create(module_type="s8_internal", version="wlstrap")
self.strap2 = factory.create(module_type="s8_internal", version="wlstrap_p")
self.wordline_names = [[] for port in self.all_ports] self.wordline_names = [[] for port in self.all_ports]
self.all_wordline_names = [] self.all_wordline_names = []
@ -42,8 +35,10 @@ class bitcell_base_array(design.design):
self.rbl_wordline_names = [[] for port in self.all_ports] self.rbl_wordline_names = [[] for port in self.all_ports]
self.all_rbl_wordline_names = [] self.all_rbl_wordline_names = []
def get_all_bitline_names(self, prefix=""): # The supply pin namesn
return [prefix + x for x in self.all_bitline_names] self.bitcell_supplies = ["vdd", "gnd"]
# If the technology needs renaming of the supplies
self.supplies = self.bitcell_supplies
def create_all_bitline_names(self): def create_all_bitline_names(self):
for col in range(self.column_size): for col in range(self.column_size):
@ -53,17 +48,10 @@ class bitcell_base_array(design.design):
# Make a flat list too # Make a flat list too
self.all_bitline_names = [x for sl in zip(*self.bitline_names) for x in sl] self.all_bitline_names = [x for sl in zip(*self.bitline_names) for x in sl]
# def get_all_wordline_names(self, prefix=""): def create_all_wordline_names(self, remove_num_wordlines=0):
# return [prefix + x for x in self.all_wordline_names] for row in range(self.row_size - remove_num_wordlines):
def create_all_wordline_names(self, num_remove_wordline=0):
for row in range(self.row_size - num_remove_wordline):
for port in self.all_ports: for port in self.all_ports:
if not cell_properties.compare_ports(cell_properties.bitcell.split_wl):
self.wordline_names[port].append("wl_{0}_{1}".format(port, row)) self.wordline_names[port].append("wl_{0}_{1}".format(port, row))
else:
self.wordline_names[port].append("wl0_{0}_{1}".format(port, row))
self.wordline_names[port].append("wl1_{0}_{1}".format(port, row))
self.all_wordline_names = [x for sl in zip(*self.wordline_names) for x in sl] self.all_wordline_names = [x for sl in zip(*self.wordline_names) for x in sl]
@ -72,22 +60,20 @@ class bitcell_base_array(design.design):
self.add_pin(bl_name, "INOUT") self.add_pin(bl_name, "INOUT")
for wl_name in self.get_wordline_names(): for wl_name in self.get_wordline_names():
self.add_pin(wl_name, "INPUT") self.add_pin(wl_name, "INPUT")
if not cell_properties.compare_ports(cell_properties.bitcell_array.use_custom_cell_arrangement): self.add_pin(self.supplies[0], "POWER")
self.add_pin("vdd", "POWER") self.add_pin(self.supplies[1], "GROUND")
self.add_pin("gnd", "GROUND")
else:
self.add_pin("vpwr", "POWER")
self.add_pin("vgnd", "GROUND")
def get_bitcell_pins(self, row, col): def get_bitcell_pins(self, row, col):
""" Creates a list of connections in the bitcell, """
indexed by column and row, for instance use in bitcell_array """ Creates a list of connections in the bitcell,
indexed by column and row, for instance use in bitcell_array
"""
bitcell_pins = [] bitcell_pins = []
for port in self.all_ports: for port in self.all_ports:
bitcell_pins.extend([x for x in self.get_bitline_names(port) if x.endswith("_{0}".format(col))]) bitcell_pins.extend([x for x in self.get_bitline_names(port) if x.endswith("_{0}".format(col))])
bitcell_pins.extend([x for x in self.all_wordline_names if x.endswith("_{0}".format(row))]) bitcell_pins.extend([x for x in self.all_wordline_names if x.endswith("_{0}".format(row))])
bitcell_pins.append("vdd") bitcell_pins.append(self.bitcell_supplies[0])
bitcell_pins.append("gnd") bitcell_pins.append(self.bitcell_supplies[1])
return bitcell_pins return bitcell_pins
@ -173,24 +159,13 @@ class bitcell_base_array(design.design):
width=self.width, width=self.width,
height=wl_pin.height()) height=wl_pin.height())
if not cell_properties.compare_ports(cell_properties.bitcell_array.use_custom_cell_arrangement):
# Copy a vdd/gnd layout pin from every cell # Copy a vdd/gnd layout pin from every cell
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, new_name) in zip(self.bitcell_supplies, self.supplies):
self.copy_layout_pin(inst, pin_name) self.copy_layout_pin(inst, pin_name, new_name)
else:
# Copy a vdd/gnd layout pin from every cell
for row in range(self.row_size):
for col in range(self.column_size):
inst = self.cell_inst[row, col]
for pin_name in ["vpwr", "vgnd"]:
self.copy_layout_pin(inst, pin_name)
def _adjust_x_offset(self, xoffset, col, col_offset): def _adjust_x_offset(self, xoffset, col, col_offset):
tempx = xoffset tempx = xoffset
dir_y = False dir_y = False
@ -211,7 +186,6 @@ class bitcell_base_array(design.design):
def place_array(self, name_template, row_offset=0): def place_array(self, name_template, row_offset=0):
# We increase it by a well enclosure so the precharges don't overlap our wells # We increase it by a well enclosure so the precharges don't overlap our wells
if not cell_properties.compare_ports(cell_properties.bitcell_array.use_custom_cell_arrangement):
self.height = self.row_size * self.cell.height self.height = self.row_size * self.cell.height
self.width = self.column_size * self.cell.width self.width = self.column_size * self.cell.width
@ -236,9 +210,6 @@ class bitcell_base_array(design.design):
mirror=dir_key) mirror=dir_key)
yoffset += self.cell.height yoffset += self.cell.height
xoffset += self.cell.width xoffset += self.cell.width
else:
from tech import custom_cell_placement
custom_cell_placement(self)
def get_column_offsets(self): def get_column_offsets(self):
""" """

View File

@ -13,9 +13,10 @@ class col_cap_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, rows, cols, column_offset=0, mirror=0, name=""): def __init__(self, rows, cols, column_offset=0, mirror=0, location="", name=""):
super().__init__(rows=rows, cols=cols, column_offset=column_offset, name=name) super().__init__(rows=rows, cols=cols, column_offset=column_offset, name=name)
self.mirror = mirror self.mirror = mirror
self.location = location
self.no_instances = True self.no_instances = True
self.create_netlist() self.create_netlist()
@ -24,6 +25,10 @@ class col_cap_array(bitcell_base_array):
def create_netlist(self): def create_netlist(self):
""" Create and connect the netlist """ """ Create and connect the netlist """
# This will create a default set of bitline/wordline names
self.create_all_wordline_names()
self.create_all_bitline_names()
self.add_modules() self.add_modules()
self.add_pins() self.add_pins()
self.create_instances() self.create_instances()
@ -58,6 +63,12 @@ class col_cap_array(bitcell_base_array):
indexed by column and row, for instance use in bitcell_array indexed by column and row, for instance use in bitcell_array
""" """
if len(self.ports) == 1:
pin_name = cell_properties.bitcell.cell_6t.pin
bitcell_pins = ["{0}_{1}".format(pin_name.bl0, col),
"{0}_{1}".format(pin_name.br0, col),
"vdd"]
else:
pin_name = cell_properties.bitcell.cell_1rw1r.pin pin_name = cell_properties.bitcell.cell_1rw1r.pin
bitcell_pins = ["{0}_{1}".format(pin_name.bl0, col), bitcell_pins = ["{0}_{1}".format(pin_name.bl0, col),
"{0}_{1}".format(pin_name.br0, col), "{0}_{1}".format(pin_name.br0, col),

View File

@ -5,7 +5,6 @@
# #
from bitcell_base_array import bitcell_base_array from bitcell_base_array import bitcell_base_array
from sram_factory import factory from sram_factory import factory
from tech import GDS,layer,drc,parameter,cell_properties
from tech import cell_properties as props from tech import cell_properties as props
from globals import OPTS from globals import OPTS
@ -14,20 +13,20 @@ 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, rows, cols, column_offset=0, mirror=0, name=""): def __init__(self, rows, cols, column_offset=0, mirror=0, location="", name=""):
super().__init__(rows=rows, cols=cols, column_offset=column_offset, name=name) super().__init__(rows=rows, cols=cols, column_offset=column_offset, name=name)
self.mirror = mirror self.mirror = mirror
# This will create a default set of bitline/wordline names
self.create_all_bitline_names()
self.create_all_wordline_names()
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):
""" Create and connect the netlist """ """ Create and connect the netlist """
# This will create a default set of bitline/wordline names
self.create_all_bitline_names()
self.create_all_wordline_names()
self.add_modules() self.add_modules()
self.add_pins() self.add_pins()
self.create_instances() self.create_instances()
@ -45,31 +44,19 @@ class dummy_array(bitcell_base_array):
def add_modules(self): def add_modules(self):
""" Add the modules used in this design """ """ Add the modules used in this design """
if not props.compare_ports(props.bitcell_array.use_custom_cell_arrangement):
self.dummy_cell = factory.create(module_type="dummy_{}".format(OPTS.bitcell)) self.dummy_cell = factory.create(module_type="dummy_{}".format(OPTS.bitcell))
self.cell = factory.create(module_type="bitcell") self.cell = factory.create(module_type="bitcell")
else:
self.dummy_cell = factory.create(module_type="s8_bitcell", version = "opt1")
self.dummy_cell2 = factory.create(module_type="s8_bitcell", version = "opt1a")
self.add_mod(factory.create(module_type="s8_internal", version = "wlstrap"))
self.add_mod(factory.create(module_type="s8_internal", version = "wlstrap_p"))
self.cell = factory.create(module_type="s8_bitcell", version = "opt1")
self.add_mod(self.dummy_cell2)
self.add_mod(self.dummy_cell) self.add_mod(self.dummy_cell)
def create_instances(self): def create_instances(self):
""" Create the module instances used in this design """ """ Create the module instances used in this design """
self.cell_inst = {} self.cell_inst = {}
if not props.compare_ports(props.bitcell_array.use_custom_cell_arrangement):
for col in range(self.column_size): for col in range(self.column_size):
for row in range(self.row_size): for row in range(self.row_size):
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(row, col)) self.connect_inst(self.get_bitcell_pins(row, col))
else:
from tech import custom_cell_arrangement
custom_cell_arrangement(self)
def add_pins(self): def add_pins(self):
# bitline pins are not added because they are floating # bitline pins are not added because they are floating
@ -119,18 +106,11 @@ class dummy_array(bitcell_base_array):
height=wl_pin.height()) height=wl_pin.height())
# Copy a vdd/gnd layout pin from every cell # Copy a vdd/gnd layout pin from every cell
if not props.compare_ports(props.bitcell_array.use_custom_cell_arrangement):
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"]:
self.copy_layout_pin(inst, pin_name) self.copy_layout_pin(inst, pin_name)
else:
for row in range(self.row_size):
for col in range(self.column_size):
inst = self.cell_inst[row, col]
for pin_name in ["vpwr", "vgnd"]:
self.copy_layout_pin(inst, pin_name)
def input_load(self): def input_load(self):

View File

@ -5,14 +5,14 @@
# #
import debug import debug
import bitcell_base_array from bitcell_base_array import bitcell_base_array
from tech import drc, spice, cell_properties 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
class replica_bitcell_array(bitcell_base_array.bitcell_base_array): class replica_bitcell_array(bitcell_base_array):
""" """
Creates a bitcell arrow of cols x rows and then adds the replica Creates a bitcell arrow of cols x rows and then adds the replica
and dummy columns and rows. Replica columns are on the left and and dummy columns and rows. Replica columns are on the left and
@ -147,17 +147,26 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array):
column_offset=1 + len(self.left_rbl), column_offset=1 + len(self.left_rbl),
mirror=0) mirror=0)
self.add_mod(self.dummy_row) self.add_mod(self.dummy_row)
if not cell_properties.compare_ports(cell_properties.bitcell_array.use_custom_cell_arrangement):
# Dummy Row or Col Cap, depending on bitcell array properties # Dummy Row or Col Cap, depending on bitcell array properties
col_cap_module_type = ("col_cap_array" if end_caps_enabled else "dummy_array") col_cap_module_type = ("col_cap_array" if end_caps_enabled else "dummy_array")
self.col_cap = factory.create(module_type=col_cap_module_type, self.col_cap_top = factory.create(module_type=col_cap_module_type,
cols=self.column_size, cols=self.column_size,
rows=1, rows=1,
# dummy column + left replica column # dummy column + left replica column(s)
column_offset=1 + len(self.left_rbl), column_offset=1 + len(self.left_rbl),
mirror=0) mirror=0,
self.add_mod(self.col_cap) location="top")
self.add_mod(self.col_cap_top)
self.col_cap_bottom = factory.create(module_type=col_cap_module_type,
cols=self.column_size,
rows=1,
# dummy column + left replica column(s)
column_offset=1 + len(self.left_rbl),
mirror=0,
location="bottom")
self.add_mod(self.col_cap_bottom)
# Dummy Col or Row Cap, depending on bitcell array properties # Dummy Col or Row Cap, depending on bitcell array properties
row_cap_module_type = ("row_cap_array" if end_caps_enabled else "dummy_array") row_cap_module_type = ("row_cap_array" if end_caps_enabled else "dummy_array")
@ -179,46 +188,6 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array):
rows=self.row_size + self.extra_rows, rows=self.row_size + self.extra_rows,
mirror=(self.rbl[0] + 1) %2) mirror=(self.rbl[0] + 1) %2)
self.add_mod(self.row_cap_right) self.add_mod(self.row_cap_right)
else:
# Dummy Row or Col Cap, depending on bitcell array properties
col_cap_module_type = ("s8_col_cap_array" if end_caps_enabled else "dummy_array")
self.col_cap_top = factory.create(module_type=col_cap_module_type,
cols=self.column_size,
rows=1,
# dummy column + left replica column(s)
column_offset=1 + len(self.left_rbl),
mirror=0,
location="top")
self.add_mod(self.col_cap_top)
self.col_cap_bottom = factory.create(module_type=col_cap_module_type,
cols=self.column_size,
rows=1,
# dummy column + left replica column(s)
column_offset=1 + len(self.left_rbl),
mirror=0,
location="bottom")
self.add_mod(self.col_cap_bottom)
# Dummy Col or Row Cap, depending on bitcell array properties
row_cap_module_type = ("s8_row_cap_array" if end_caps_enabled else "dummy_array")
self.row_cap_left = factory.create(module_type=row_cap_module_type,
cols=1,
column_offset=0,
rows=self.row_size + self.extra_rows,
mirror=0)
self.add_mod(self.row_cap_left)
self.row_cap_right = factory.create(module_type=row_cap_module_type,
cols=1,
# dummy column
# + left replica column(s)
# + bitcell columns
# + right replica column(s)
column_offset = 1 + len(self.left_rbl) + self.column_size + self.rbl[0],
rows=self.row_size + self.extra_rows,
mirror=0)
self.add_mod(self.row_cap_right)
def add_pins(self): def add_pins(self):
@ -279,15 +248,13 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array):
# All wordlines including dummy and RBL # All wordlines including dummy and RBL
self.replica_array_wordline_names = [] self.replica_array_wordline_names = []
if not cell_properties.compare_ports(cell_properties.bitcell_array.use_custom_cell_arrangement): self.replica_array_wordline_names.extend(["gnd"] * len(self.col_cap_top.get_wordline_names()))
self.replica_array_wordline_names.extend(["gnd"] * len(self.col_cap.get_wordline_names()))
for bit in range(self.rbl[0]): for bit in range(self.rbl[0]):
self.replica_array_wordline_names.extend([x if x not in self.gnd_wordline_names else "gnd" for x in self.rbl_wordline_names[bit]]) self.replica_array_wordline_names.extend([x if x not in self.gnd_wordline_names else "gnd" for x in self.rbl_wordline_names[bit]])
self.replica_array_wordline_names.extend(self.all_wordline_names) self.replica_array_wordline_names.extend(self.all_wordline_names)
for bit in range(self.rbl[1]): for bit in range(self.rbl[1]):
self.replica_array_wordline_names.extend([x if x not in self.gnd_wordline_names else "gnd" for x in self.rbl_wordline_names[self.rbl[0] + bit]]) self.replica_array_wordline_names.extend([x if x not in self.gnd_wordline_names else "gnd" for x in self.rbl_wordline_names[self.rbl[0] + bit]])
if not cell_properties.compare_ports(cell_properties.bitcell_array.use_custom_cell_arrangement): self.replica_array_wordline_names.extend(["gnd"] * len(self.col_cap_top.get_wordline_names()))
self.replica_array_wordline_names.extend(["gnd"] * len(self.col_cap.get_wordline_names()))
for port in range(self.rbl[0]): for port in range(self.rbl[0]):
self.add_pin(self.rbl_wordline_names[port][port], "INPUT") self.add_pin(self.rbl_wordline_names[port][port], "INPUT")
@ -297,8 +264,6 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array):
def create_instances(self): def create_instances(self):
""" Create the module instances used in this design """ """ Create the module instances used in this design """
if not cell_properties.compare_ports(cell_properties.bitcell_array.use_custom_cell_arrangement):
self.supplies = ["vdd", "gnd"] self.supplies = ["vdd", "gnd"]
# Used for names/dimensions only # Used for names/dimensions only
@ -330,11 +295,11 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array):
# Top/bottom dummy rows or col caps # Top/bottom dummy rows or col caps
self.dummy_row_insts = [] self.dummy_row_insts = []
self.dummy_row_insts.append(self.add_inst(name="dummy_row_bot", self.dummy_row_insts.append(self.add_inst(name="dummy_row_bot",
mod=self.col_cap)) mod=self.col_cap_bottom))
self.connect_inst(["gnd"] * len(self.col_cap.get_wordline_names()) + self.supplies) self.connect_inst(["gnd"] * len(self.col_cap_bottom.get_wordline_names()) + self.supplies)
self.dummy_row_insts.append(self.add_inst(name="dummy_row_top", self.dummy_row_insts.append(self.add_inst(name="dummy_row_top",
mod=self.col_cap)) mod=self.col_cap_top))
self.connect_inst(["gnd"] * len(self.col_cap.get_wordline_names()) + self.supplies) self.connect_inst(["gnd"] * len(self.col_cap_top.get_wordline_names()) + self.supplies)
# Left/right Dummy columns # Left/right Dummy columns
self.dummy_col_insts = [] self.dummy_col_insts = []
@ -344,9 +309,6 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array):
self.dummy_col_insts.append(self.add_inst(name="dummy_col_right", self.dummy_col_insts.append(self.add_inst(name="dummy_col_right",
mod=self.row_cap_right)) mod=self.row_cap_right))
self.connect_inst(self.replica_array_wordline_names + self.supplies) self.connect_inst(self.replica_array_wordline_names + self.supplies)
else:
from tech import custom_replica_bitcell_array_arrangement
custom_replica_bitcell_array_arrangement(self)
def create_layout(self): def create_layout(self):
@ -357,26 +319,15 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array):
self.unused_offset = vector(self.unused_pitch, 0) self.unused_offset = vector(self.unused_pitch, 0)
# Add extra width on the left and right for the unused WLs # Add extra width on the left and right for the unused WLs
if not cell_properties.compare_ports(cell_properties.bitcell_array.use_custom_cell_arrangement):
self.height = (self.row_size + self.extra_rows) * self.dummy_row.height self.height = (self.row_size + self.extra_rows) * self.dummy_row.height
self.width = (self.column_size + self.extra_cols) * self.cell.width + 2 * self.unused_pitch self.width = (self.column_size + self.extra_cols) * self.cell.width + 2 * self.unused_pitch
else:
self.width = self.row_cap_left.width + self.row_cap_right.width + self.col_cap_top.width
for rbl in range(self.rbl[0] + self.rbl[1]):
self.width += self.replica_col_insts[rbl].width
self.height = self.row_cap_left.height
# This is a bitcell x bitcell offset to scale # This is a bitcell x bitcell offset to scale
self.bitcell_offset = vector(self.cell.width, self.cell.height) self.bitcell_offset = vector(self.cell.width, self.cell.height)
if not cell_properties.compare_ports(cell_properties.bitcell_array.use_custom_cell_arrangement):
self.strap_offset = vector(0, 0) self.strap_offset = vector(0, 0)
self.col_end_offset = vector(self.cell.width, self.cell.height) self.col_end_offset = vector(self.cell.width, self.cell.height)
self.row_end_offset = vector(self.cell.width, self.cell.height) self.row_end_offset = vector(self.cell.width, self.cell.height)
else:
self.strap_offset = vector(self.replica_col_insts[0].mod.strap1.width, self.replica_col_insts[0].mod.strap1.height)
self.col_end_offset = vector(self.dummy_row_insts[0].mod.colend1.width, self.dummy_row_insts[0].mod.colend1.height)
self.row_end_offset = vector(self.dummy_col_insts[0].mod.rowend1.width, self.dummy_col_insts[0].mod.rowend1.height)
# Everything is computed with the main array at (self.unused_pitch, 0) to start # Everything is computed with the main array at (self.unused_pitch, 0) to start
self.bitcell_array_inst.place(offset=self.unused_offset) self.bitcell_array_inst.place(offset=self.unused_offset)
@ -503,7 +454,6 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array):
#All wordlines #All wordlines
#Main array wl and bl/br #Main array wl and bl/br
if not cell_properties.compare_ports(cell_properties.bitcell_array.use_custom_cell_arrangement):
for pin_name in self.all_wordline_names: for pin_name in self.all_wordline_names:
pin_list = self.bitcell_array_inst.get_pins(pin_name) pin_list = self.bitcell_array_inst.get_pins(pin_name)
@ -525,27 +475,6 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array):
offset=pin.ll().scale(0, 1), offset=pin.ll().scale(0, 1),
width=self.width, width=self.width,
height=pin.height()) height=pin.height())
else:
for pin_name in self.all_wordline_names:
pin_list = self.dummy_col_insts[0].get_pins(pin_name)
for pin in pin_list:
self.add_layout_pin(text=pin_name,
layer=pin.layer,
offset=pin.ll().scale(0, 1),
width=self.width,
height=pin.height())
# Replica wordlines (go by the row instead of replica column because we may have to add a pin
# even though the column is in another local bitcell array)
for (names, inst) in zip(self.rbl_wordline_names, self.dummy_row_replica_insts):
for (wl_name, pin_name) in zip(names, self.dummy_row.get_wordline_names()):
if wl_name in self.gnd_wordline_names:
continue
pin = inst.get_pin(pin_name)
self.add_layout_pin(text=wl_name,
layer=pin.layer,
offset=pin.ll().scale(0, 1),
width=self.width,
height=pin.height())
for pin_name in self.all_bitline_names: for pin_name in self.all_bitline_names:
pin_list = self.bitcell_array_inst.get_pins(pin_name) pin_list = self.bitcell_array_inst.get_pins(pin_name)
@ -603,10 +532,9 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array):
def route_unused_wordlines(self): def route_unused_wordlines(self):
""" Connect the unused RBL and dummy wordlines to gnd """ """ Connect the unused RBL and dummy wordlines to gnd """
if not cell_properties.compare_ports(cell_properties.bitcell_array.use_custom_cell_arrangement):
# This grounds all the dummy row word lines # This grounds all the dummy row word lines
for inst in self.dummy_row_insts: for inst in self.dummy_row_insts:
for wl_name in self.col_cap.get_wordline_names(): for wl_name in self.col_cap_top.get_wordline_names():
self.ground_pin(inst, wl_name) self.ground_pin(inst, wl_name)
# Ground the unused replica wordlines # Ground the unused replica wordlines

View File

@ -28,10 +28,8 @@ class replica_column(bitcell_base_array):
self.right_rbl = rbl[1] self.right_rbl = rbl[1]
self.replica_bit = replica_bit self.replica_bit = replica_bit
# left, right, regular rows plus top/bottom dummy cells # left, right, regular rows plus top/bottom dummy cells
if not cell_properties.compare_ports(cell_properties.bitcell_array.use_custom_cell_arrangement):
self.total_size = self.left_rbl + rows + self.right_rbl + 2
else:
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, debug.check(replica_bit != 0 and replica_bit != rows,
@ -67,7 +65,7 @@ class replica_column(bitcell_base_array):
try: try:
if cell_properties.bitcell.end_caps: if cell_properties.bitcell.end_caps:
# remove 2 wordlines to account for top/bot # remove 2 wordlines to account for top/bot
self.create_all_wordline_names(num_remove_wordlines=2) self.create_all_wordline_names(remove_num_wordlines=2)
else: else:
self.create_all_wordline_names() self.create_all_wordline_names()
except AttributeError: except AttributeError:
@ -80,7 +78,6 @@ class replica_column(bitcell_base_array):
self.add_pin("gnd", "GROUND") self.add_pin("gnd", "GROUND")
def add_modules(self): def add_modules(self):
if not cell_properties.compare_ports(cell_properties.bitcell_array.use_custom_cell_arrangement):
self.replica_cell = factory.create(module_type="replica_{}".format(OPTS.bitcell)) self.replica_cell = factory.create(module_type="replica_{}".format(OPTS.bitcell))
self.add_mod(self.replica_cell) self.add_mod(self.replica_cell)
self.dummy_cell = factory.create(module_type="dummy_{}".format(OPTS.bitcell)) self.dummy_cell = factory.create(module_type="dummy_{}".format(OPTS.bitcell))
@ -93,34 +90,10 @@ class replica_column(bitcell_base_array):
self.add_mod(self.edge_cell) 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")
else:
self.replica_cell = factory.create(module_type="s8_bitcell", version = "opt1")
self.add_mod(self.replica_cell)
self.cell = self.replica_cell
self.replica_cell2 = factory.create(module_type="s8_bitcell", version = "opt1a")
self.add_mod(self.replica_cell2)
self.dummy_cell = factory.create(module_type="s8_bitcell", version = "opt1")
self.dummy_cell2 = factory.create(module_type="s8_bitcell", version = "opt1")
self.strap1 = factory.create(module_type="s8_internal", version = "wlstrap")
self.add_mod(self.strap1)
self.strap2 = factory.create(module_type="s8_internal", version = "wlstrap_p")
self.add_mod(self.strap2)
self.colend = factory.create(module_type="s8_col_end", version = "colenda")
self.edge_cell = self.colend
self.add_mod(self.colend)
self.colenda = factory.create(module_type="s8_col_end", version = "colenda")
self.add_mod(self.colenda)
self.colend_p_cent = factory.create(module_type="s8_col_end", version = "colend_p_cent")
self.add_mod(self.colend_p_cent)
self.colenda_p_cent = factory.create(module_type="s8_col_end", version = "colenda_p_cent")
self.add_mod(self.colenda_p_cent)
def create_instances(self): def create_instances(self):
self.cell_inst = {} self.cell_inst = {}
if not cell_properties.compare_ports(cell_properties.bitcell_array.use_custom_cell_arrangement):
try: try:
end_caps_enabled = cell_properties.bitcell.end_caps end_caps_enabled = cell_properties.bitcell.end_caps
except AttributeError: except AttributeError:
@ -150,13 +123,8 @@ class replica_column(bitcell_base_array):
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(row, 0)) self.connect_inst(self.get_bitcell_pins(row, 0))
else:
from tech import custom_replica_column_arrangement
custom_replica_column_arrangement(self)
def place_instances(self): def place_instances(self):
if not cell_properties.compare_ports(cell_properties.bitcell_array.use_custom_cell_arrangement):
# 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
# so that we will start with mirroring rather than not mirroring # so that we will start with mirroring rather than not mirroring
rbl_offset = (self.left_rbl + 1) %2 rbl_offset = (self.left_rbl + 1) %2
@ -186,13 +154,10 @@ class replica_column(bitcell_base_array):
self.cell_inst[row].place(offset=offset, self.cell_inst[row].place(offset=offset,
mirror=dir_key) mirror=dir_key)
else:
from tech import custom_replica_cell_placement
custom_replica_cell_placement(self)
def add_layout_pins(self): def add_layout_pins(self):
""" Add the layout pins """ """ Add the layout pins """
if not cell_properties.compare_ports(cell_properties.bitcell_array.use_custom_cell_arrangement):
for port in self.all_ports: for port in self.all_ports:
bl_pin = self.cell_inst[0].get_pin(self.cell.get_bl_name(port)) bl_pin = self.cell_inst[0].get_pin(self.cell.get_bl_name(port))
self.add_layout_pin(text="bl_{0}_{1}".format(port, 0), self.add_layout_pin(text="bl_{0}_{1}".format(port, 0),
@ -235,41 +200,6 @@ class replica_column(bitcell_base_array):
self.copy_power_pins(inst, pin_name) self.copy_power_pins(inst, pin_name)
else: else:
self.copy_layout_pin(inst, pin_name) self.copy_layout_pin(inst, pin_name)
else:
for port in self.all_ports:
bl_pin = self.cell_inst[2].get_pin(self.cell.get_bl_name(port))
self.add_layout_pin(text="bl_{0}_{1}".format(port, 0),
layer=bl_pin.layer,
offset=bl_pin.ll().scale(1, 0),
width=bl_pin.width(),
height=self.height)
bl_pin = self.cell_inst[2].get_pin(self.cell.get_br_name(port))
self.add_layout_pin(text="br_{0}_{1}".format(port, 0),
layer=bl_pin.layer,
offset=bl_pin.ll().scale(1, 0),
width=bl_pin.width(),
height=self.height)
row_range_max = self.total_size - 1
row_range_min = 1
for port in self.all_ports:
for row in range(row_range_min, row_range_max):
wl_pin = self.cell_inst[row].get_pin(self.cell.get_wl_name(port))
self.add_layout_pin(text="wl_{0}_{1}".format(port, row),
layer=wl_pin.layer,
offset=wl_pin.ll().scale(0, 1),
width=self.width,
height=wl_pin.height())
# Supplies are only connected in the ends
for (index, inst) in self.cell_inst.items():
for pin_name in ["vpwr", "vgnd"]:
if inst in [self.cell_inst[0], self.cell_inst[self.total_size - 1]]:
self.copy_power_pins(inst, pin_name)
else:
self.copy_layout_pin(inst, pin_name)
def get_bitline_names(self, port=None): def get_bitline_names(self, port=None):
if port == None: if port == None:

View File

@ -23,6 +23,10 @@ class row_cap_array(bitcell_base_array):
def create_netlist(self): def create_netlist(self):
""" Create and connect the netlist """ """ Create and connect the netlist """
# This will create a default set of bitline/wordline names
self.create_all_wordline_names()
self.create_all_bitline_names()
self.add_modules() self.add_modules()
self.add_pins() self.add_pins()
self.create_instances() self.create_instances()

View File

@ -42,6 +42,8 @@ class options(optparse.Values):
supply_voltages = "" supply_voltages = ""
temperatures = "" temperatures = ""
process_corners = "" process_corners = ""
load_scales = ""
slew_scales = ""
# Size parameters must be specified by user in config file. # Size parameters must be specified by user in config file.
# num_words = 0 # num_words = 0