mirror of https://github.com/VLSIDA/OpenRAM.git
Merge remote-tracking branch 'private/dev' into dev
This commit is contained in:
commit
db1bcd0774
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
||||||
|
|
@ -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"])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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"])
|
|
||||||
|
|
@ -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"])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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"])
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
||||||
|
|
@ -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")
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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. """
|
||||||
|
|
|
||||||
|
|
@ -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."""
|
||||||
|
|
|
||||||
|
|
@ -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):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -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),
|
||||||
|
|
|
||||||
|
|
@ -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):
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue