mirror of https://github.com/VLSIDA/OpenRAM.git
Fix pbitcell erros
This commit is contained in:
parent
c472a94f1e
commit
8021430122
|
|
@ -5,9 +5,49 @@
|
|||
# (acting for and on behalf of Oklahoma State University)
|
||||
# All rights reserved.
|
||||
#
|
||||
from globals import OPTS
|
||||
|
||||
class _cell:
|
||||
def __init__(self, port_order, port_types, port_map=None, hard_cell=True, boundary_layer="boundary"):
|
||||
# Specifies if this is a hard (i.e. GDS) cell
|
||||
self._hard_cell = hard_cell
|
||||
# Specifies the order in the spice modules
|
||||
self._port_order = port_order
|
||||
# Specifies the port directions
|
||||
self._port_types = port_types
|
||||
# Specifies a map from OpenRAM names to cell names
|
||||
# by default it is 1:1
|
||||
if not port_map:
|
||||
port_map = {}
|
||||
for pin in port_order:
|
||||
port_map[pin] = pin
|
||||
self._pins = _pins(port_map)
|
||||
else:
|
||||
self._pins = _pins(port_map)
|
||||
|
||||
self._port_names = [getattr(self._pins, x) for x in self._port_order]
|
||||
self._boundary_layer = boundary_layer
|
||||
|
||||
@property
|
||||
def pin(self):
|
||||
return self._pins
|
||||
|
||||
@property
|
||||
def hard_cell(self):
|
||||
return self._hard_cell
|
||||
|
||||
@property
|
||||
def port_names(self):
|
||||
return self._port_names
|
||||
|
||||
@property
|
||||
def port_types(self):
|
||||
return self._port_types
|
||||
|
||||
@property
|
||||
def boundary_layer(self):
|
||||
return self._boundary_layer
|
||||
|
||||
|
||||
class _pins:
|
||||
def __init__(self, pin_dict):
|
||||
# make the pins elements of the class to allow "." access.
|
||||
|
|
@ -16,20 +56,6 @@ class _pins:
|
|||
self.__dict__[k] = v
|
||||
|
||||
|
||||
class _cell:
|
||||
def __init__(self, pin_dict):
|
||||
pin_dict.update(self._default_power_pins())
|
||||
self._pins = _pins(pin_dict)
|
||||
|
||||
@property
|
||||
def pin(self):
|
||||
return self._pins
|
||||
|
||||
def _default_power_pins(self):
|
||||
return {'vdd': 'vdd',
|
||||
'gnd': 'gnd'}
|
||||
|
||||
|
||||
class _mirror_axis:
|
||||
def __init__(self, x, y):
|
||||
self.x = x
|
||||
|
|
@ -47,65 +73,38 @@ class _pgate:
|
|||
self.add_implants = add_implants
|
||||
|
||||
|
||||
class _bitcell:
|
||||
def __init__(self, mirror, cell_1port, cell_2port):
|
||||
self.mirror = mirror
|
||||
self._1rw = cell_1port
|
||||
self._2rw = cell_2port
|
||||
class _bitcell(_cell):
|
||||
def __init__(self, port_order, port_types, port_map=None, storage_nets=["Q", "Q_bar"], mirror=None, end_caps=False):
|
||||
super().__init__(port_order, port_types, port_map)
|
||||
|
||||
def _default():
|
||||
axis = _mirror_axis(True, False)
|
||||
|
||||
cell_1port = _cell({'bl': 'bl',
|
||||
'br': 'br',
|
||||
'wl': 'wl'})
|
||||
|
||||
cell_2port = _cell({'bl0': 'bl0',
|
||||
'br0': 'br0',
|
||||
'bl1': 'bl1',
|
||||
'br1': 'br1',
|
||||
'wl0': 'wl0',
|
||||
'wl1': 'wl1'})
|
||||
|
||||
return _bitcell(cell_1port=cell_1port,
|
||||
cell_2port=cell_2port,
|
||||
mirror=axis)
|
||||
self._end_caps = end_caps
|
||||
|
||||
if not mirror:
|
||||
self._mirror = _mirror_axis(True, False)
|
||||
else:
|
||||
self._mirror = mirror
|
||||
|
||||
self._storage_nets = storage_nets
|
||||
|
||||
@property
|
||||
def cell_1port(self):
|
||||
return self._1rw
|
||||
|
||||
def end_caps(self):
|
||||
return self._end_caps
|
||||
|
||||
@property
|
||||
def cell_2port(self):
|
||||
return self._2rw
|
||||
def mirror(self):
|
||||
return self._mirror
|
||||
|
||||
@property
|
||||
def storage_nets(self):
|
||||
return self._storage_nets
|
||||
|
||||
|
||||
class _dff:
|
||||
def __init__(self, use_custom_ports, custom_port_list, custom_type_list, clk_pin):
|
||||
self.use_custom_ports = use_custom_ports
|
||||
self.custom_port_list = custom_port_list
|
||||
self.custom_type_list = custom_type_list
|
||||
|
||||
class _dff(_cell):
|
||||
def __init__(self, clk_pin, port_order, port_types, port_map=None, hard_cell=True):
|
||||
super().__init__(port_order, port_types, port_map, hard_cell)
|
||||
self.clk_pin = clk_pin
|
||||
|
||||
|
||||
class _dff_buff:
|
||||
def __init__(self, use_custom_ports, custom_buff_ports, add_body_contacts):
|
||||
self.use_custom_ports = use_custom_ports
|
||||
self.buf_ports = custom_buff_ports
|
||||
self.add_body_contacts = add_body_contacts
|
||||
|
||||
|
||||
class _dff_buff_array:
|
||||
def __init__(self, use_custom_ports, add_body_contacts):
|
||||
self.use_custom_ports = use_custom_ports
|
||||
self.add_body_contacts = add_body_contacts
|
||||
|
||||
|
||||
class _bitcell_array:
|
||||
def __init__(self, use_custom_cell_arrangement):
|
||||
self.use_custom_cell_arrangement = use_custom_cell_arrangement
|
||||
|
||||
|
||||
|
||||
class cell_properties():
|
||||
"""
|
||||
This contains meta information about the custom designed cells. For
|
||||
|
|
@ -125,41 +124,41 @@ class cell_properties():
|
|||
self.names["col_cap_bitcell_2port"] = "col_cap_cell_2rw"
|
||||
self.names["row_cap_bitcell_1port"] = "row_cap_cell_1rw"
|
||||
self.names["row_cap_bitcell_2port"] = "row_cap_cell_2rw"
|
||||
|
||||
self._bitcell = _bitcell._default()
|
||||
|
||||
self._ptx = _ptx(model_is_subckt=False,
|
||||
bin_spice_models=False)
|
||||
|
||||
self._pgate = _pgate(add_implants=False)
|
||||
|
||||
self._dff = _dff(use_custom_ports=False,
|
||||
custom_port_list=["D", "Q", "clk", "vdd", "gnd"],
|
||||
custom_type_list=["INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"],
|
||||
clk_pin="clk")
|
||||
self._nand2_dec = _cell(["A", "B", "Z", "vdd", "gnd"],
|
||||
["INPUT", "INPUT", "OUTPUT", "POWER", "GROUND"])
|
||||
|
||||
self._nand2_dec = _cell(["A", "B", "C", "Z", "vdd", "gnd"],
|
||||
["INPUT", "INPUT", "INPUT", "OUTPUT", "POWER", "GROUND"])
|
||||
|
||||
self._nand2_dec = _cell(["A", "B", "C", "D", "Z", "vdd", "gnd"],
|
||||
["INPUT", "INPUT", "INPUT", "INPUT", "OUTPUT", "POWER", "GROUND"])
|
||||
|
||||
self._dff = _dff("clk",
|
||||
["D", "Q", "clk", "vdd", "gnd"],
|
||||
["INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"])
|
||||
|
||||
self._dff_buff = _dff_buff(use_custom_ports=False,
|
||||
custom_buff_ports=["D", "qint", "clk", "vdd", "gnd"],
|
||||
add_body_contacts=False)
|
||||
self._dff_buf = _dff("clk",
|
||||
["D", "Q", "Qb", "clk", "vdd", "gnd"],
|
||||
["INPUT", "OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"],
|
||||
hard_cell=False)
|
||||
|
||||
self._write_driver = _cell(['din', 'bl', 'br', 'en', 'vdd', 'gnd'],
|
||||
["INPUT", "OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"])
|
||||
|
||||
self._dff_buff_array = _dff_buff_array(use_custom_ports=False,
|
||||
add_body_contacts=False)
|
||||
self._sense_amp = _cell(['bl', 'br', 'dout', 'en', 'vdd', 'gnd'],
|
||||
["INPUT", "INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"])
|
||||
|
||||
self._write_driver = _cell({'din': 'din',
|
||||
'bl': 'bl',
|
||||
'br': 'br',
|
||||
'en': 'en'})
|
||||
self._bitcell_1port = _bitcell(["bl", "br", "wl", "vdd", "gnd"],
|
||||
["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"])
|
||||
|
||||
self._sense_amp = _cell({'bl': 'bl',
|
||||
'br': 'br',
|
||||
'dout': 'dout',
|
||||
'en': 'en'})
|
||||
|
||||
self._bitcell_array = _bitcell_array(use_custom_cell_arrangement=[])
|
||||
|
||||
@property
|
||||
def bitcell(self):
|
||||
return self._bitcell
|
||||
self._bitcell_2port = _bitcell(["bl0", "br0", "bl1", "br1", "wl0", "wl1", "vdd", "gnd"],
|
||||
["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", "INPUT", "INPUT", "POWER", "GROUND"])
|
||||
|
||||
@property
|
||||
def ptx(self):
|
||||
|
|
@ -174,13 +173,9 @@ class cell_properties():
|
|||
return self._dff
|
||||
|
||||
@property
|
||||
def dff_buff(self):
|
||||
return self._dff_buff
|
||||
|
||||
@property
|
||||
def dff_buff_array(self):
|
||||
return self._dff_buff_array
|
||||
|
||||
def dff_buf(self):
|
||||
return self._dff_buf
|
||||
|
||||
@property
|
||||
def write_driver(self):
|
||||
return self._write_driver
|
||||
|
|
@ -190,13 +185,10 @@ class cell_properties():
|
|||
return self._sense_amp
|
||||
|
||||
@property
|
||||
def bitcell_array(self):
|
||||
return self._bitcell_array
|
||||
def bitcell_1port(self):
|
||||
return self._bitcell_1port
|
||||
|
||||
@property
|
||||
def bitcell_2port(self):
|
||||
return self._bitcell_2port
|
||||
|
||||
def compare_ports(self, port_list):
|
||||
use_custom_arrangement = False
|
||||
for ports in port_list:
|
||||
if ports == "{}R_{}W_{}RW".format(OPTS.num_r_ports, OPTS.num_w_ports, OPTS.num_rw_ports):
|
||||
use_custom_arrangement = True
|
||||
break
|
||||
return use_custom_arrangement
|
||||
|
|
|
|||
|
|
@ -6,8 +6,9 @@
|
|||
# All rights reserved.
|
||||
#
|
||||
from hierarchy_design import hierarchy_design
|
||||
from utils import round_to_grid
|
||||
import utils
|
||||
import contact
|
||||
from tech import GDS, layer
|
||||
from tech import preferred_directions
|
||||
from tech import cell_properties as props
|
||||
from globals import OPTS
|
||||
|
|
@ -31,6 +32,26 @@ class design(hierarchy_design):
|
|||
cell_name = name
|
||||
super().__init__(name, cell_name)
|
||||
|
||||
# This means it is a custom cell...
|
||||
if hasattr(props, name):
|
||||
prop = getattr(props, name)
|
||||
if prop.hard_cell:
|
||||
# The pins get added from the spice file
|
||||
debug.check(prop.port_names == self.pins,
|
||||
"Custom cell pin names do not match spice file:\n{0} vs {1}".format(prop.port_names, self.pins))
|
||||
self.add_pin_types(prop.port_types)
|
||||
|
||||
(width, height) = utils.get_libcell_size(self.cell_name,
|
||||
GDS["unit"],
|
||||
layer[prop.boundary_layer])
|
||||
|
||||
self.pin_map = utils.get_libcell_pins(self.pins,
|
||||
self.cell_name,
|
||||
GDS["unit"])
|
||||
|
||||
self.width = width
|
||||
self.height = height
|
||||
|
||||
self.setup_multiport_constants()
|
||||
|
||||
def check_pins(self):
|
||||
|
|
@ -232,8 +253,7 @@ class design(hierarchy_design):
|
|||
#print(contact1)
|
||||
pitch = contact_width + layer_space
|
||||
|
||||
return round_to_grid(pitch)
|
||||
|
||||
return utils.round_to_grid(pitch)
|
||||
|
||||
def setup_multiport_constants(self):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ class spice():
|
|||
""" Adds a pin_list to the pins list """
|
||||
# The type list can be a single type for all pins
|
||||
# or a list that is the same length as the pin list.
|
||||
|
||||
if type(pin_type)==str:
|
||||
for pin in pin_list:
|
||||
debug.check(pin_type in self.valid_signal_types,
|
||||
|
|
@ -100,12 +101,12 @@ class spice():
|
|||
Typically, should only be used for handmade cells.
|
||||
"""
|
||||
# This only works if self.pins == bitcell.pin_names
|
||||
if self.pin_names != self.pins:
|
||||
debug.error("{} spice subcircuit port names do not match pin_names\
|
||||
if len(type_list) != len(self.pins):
|
||||
debug.error("{} spice subcircuit number of port types does not match number of pins\
|
||||
\n SPICE names={}\
|
||||
\n Module names={}\
|
||||
".format(self.name, self.pins, self.pin_names), 1)
|
||||
self.pin_type = {pin: type for pin, type in zip(self.pin_names, type_list)}
|
||||
".format(self.name, self.pins, type_list), 1)
|
||||
self.pin_type = {pin: type for pin, type in zip(self.pins, type_list)}
|
||||
|
||||
def get_pin_type(self, name):
|
||||
""" Returns the type of the signal pin. """
|
||||
|
|
|
|||
|
|
@ -18,53 +18,43 @@ class bitcell_1port(bitcell_base.bitcell_base):
|
|||
library.
|
||||
"""
|
||||
|
||||
pin_names = [props.bitcell.cell_1port.pin.bl,
|
||||
props.bitcell.cell_1port.pin.br,
|
||||
props.bitcell.cell_1port.pin.wl,
|
||||
props.bitcell.cell_1port.pin.vdd,
|
||||
props.bitcell.cell_1port.pin.gnd]
|
||||
type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]
|
||||
storage_nets = ['Q', 'Q_bar']
|
||||
|
||||
def __init__(self, name):
|
||||
super().__init__(name)
|
||||
super().__init__(name, props.bitcell_1port)
|
||||
debug.info(2, "Create bitcell")
|
||||
|
||||
self.nets_match = self.do_nets_exist(self.storage_nets)
|
||||
|
||||
def get_all_wl_names(self):
|
||||
""" Creates a list of all wordline pin names """
|
||||
row_pins = [props.bitcell.cell_1port.pin.wl]
|
||||
row_pins = [props.bitcell_1port.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_1port.pin
|
||||
pin = props.bitcell_1port.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_1port.pin.bl]
|
||||
return [props.bitcell_1port.pin.bl]
|
||||
|
||||
def get_all_br_names(self):
|
||||
""" Creates a list of all br pins names """
|
||||
return [props.bitcell.cell_1port.pin.br]
|
||||
return [props.bitcell_1port.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_1port.pin.bl
|
||||
return props.bitcell_1port.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_1port.pin.br
|
||||
return props.bitcell_1port.pin.br
|
||||
|
||||
def get_wl_name(self, port=0):
|
||||
"""Get wl name"""
|
||||
debug.check(port == 0, "One port for bitcell only.")
|
||||
return props.bitcell.cell_1port.pin.wl
|
||||
return props.bitcell_1port.pin.wl
|
||||
|
||||
def build_graph(self, graph, inst_name, port_nets):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -18,35 +18,20 @@ class bitcell_2port(bitcell_base.bitcell_base):
|
|||
library.
|
||||
"""
|
||||
|
||||
pin_names = [props.bitcell.cell_2port.pin.bl0,
|
||||
props.bitcell.cell_2port.pin.br0,
|
||||
props.bitcell.cell_2port.pin.bl1,
|
||||
props.bitcell.cell_2port.pin.br1,
|
||||
props.bitcell.cell_2port.pin.wl0,
|
||||
props.bitcell.cell_2port.pin.wl1,
|
||||
props.bitcell.cell_2port.pin.vdd,
|
||||
props.bitcell.cell_2port.pin.gnd]
|
||||
type_list = ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT",
|
||||
"INPUT", "INPUT", "POWER", "GROUND"]
|
||||
storage_nets = ['Q', 'Q_bar']
|
||||
|
||||
def __init__(self, name):
|
||||
super().__init__(name)
|
||||
super().__init__(name, props.bitcell_2port)
|
||||
debug.info(2, "Create bitcell with 2 ports")
|
||||
|
||||
self.nets_match = self.do_nets_exist(self.storage_nets)
|
||||
|
||||
pin_names = self.pin_names
|
||||
self.bl_names = [pin_names[0], pin_names[2]]
|
||||
self.br_names = [pin_names[1], pin_names[3]]
|
||||
self.wl_names = [pin_names[4], pin_names[5]]
|
||||
self.bl_names = [props.bitcell_2port.pin.bl0, props.bitcell_2port.pin.bl1]
|
||||
self.br_names = [props.bitcell_2port.pin.br0, props.bitcell_2port.pin.br1]
|
||||
self.wl_names = [props.bitcell_2port.pin.wl0, props.bitcell_2port.pin.wl1]
|
||||
|
||||
def get_bitcell_pins(self, col, row):
|
||||
"""
|
||||
Creates a list of connections in the bitcell,
|
||||
indexed by column and row, for instance use in bitcell_array
|
||||
"""
|
||||
pin_name = props.bitcell.cell_2port.pin
|
||||
pin_name = props.bitcell_2port.pin
|
||||
bitcell_pins = ["{0}_{1}".format(pin_name.bl0, col),
|
||||
"{0}_{1}".format(pin_name.br0, col),
|
||||
"{0}_{1}".format(pin_name.bl1, col),
|
||||
|
|
@ -59,43 +44,43 @@ class bitcell_2port(bitcell_base.bitcell_base):
|
|||
|
||||
def get_all_wl_names(self):
|
||||
""" Creates a list of all wordline pin names """
|
||||
return [props.bitcell.cell_2port.pin.wl0,
|
||||
props.bitcell.cell_2port.pin.wl1]
|
||||
return [props.bitcell_2port.pin.wl0,
|
||||
props.bitcell_2port.pin.wl1]
|
||||
|
||||
def get_all_bitline_names(self):
|
||||
""" Creates a list of all bitline pin names (both bl and br) """
|
||||
return [props.bitcell.cell_2port.pin.bl0,
|
||||
props.bitcell.cell_2port.pin.br0,
|
||||
props.bitcell.cell_2port.pin.bl1,
|
||||
props.bitcell.cell_2port.pin.br1]
|
||||
return [props.bitcell_2port.pin.bl0,
|
||||
props.bitcell_2port.pin.br0,
|
||||
props.bitcell_2port.pin.bl1,
|
||||
props.bitcell_2port.pin.br1]
|
||||
|
||||
def get_all_bl_names(self):
|
||||
""" Creates a list of all bl pins names """
|
||||
return [props.bitcell.cell_2port.pin.bl0,
|
||||
props.bitcell.cell_2port.pin.bl1]
|
||||
return [props.bitcell_2port.pin.bl0,
|
||||
props.bitcell_2port.pin.bl1]
|
||||
|
||||
def get_all_br_names(self):
|
||||
""" Creates a list of all br pins names """
|
||||
return [props.bitcell.cell_2port.pin.br0,
|
||||
props.bitcell.cell_2port.pin.br1]
|
||||
return [props.bitcell_2port.pin.br0,
|
||||
props.bitcell_2port.pin.br1]
|
||||
|
||||
def get_read_bl_names(self):
|
||||
""" Creates a list of bl pin names associated with read ports """
|
||||
return [props.bitcell.cell_2port.pin.bl0,
|
||||
props.bitcell.cell_2port.pin.bl1]
|
||||
return [props.bitcell_2port.pin.bl0,
|
||||
props.bitcell_2port.pin.bl1]
|
||||
|
||||
def get_read_br_names(self):
|
||||
""" Creates a list of br pin names associated with read ports """
|
||||
return [props.bitcell.cell_2port.pin.br0,
|
||||
props.bitcell.cell_2port.pin.br1]
|
||||
return [props.bitcell_2port.pin.br0,
|
||||
props.bitcell_2port.pin.br1]
|
||||
|
||||
def get_write_bl_names(self):
|
||||
""" Creates a list of bl pin names associated with write ports """
|
||||
return [props.bitcell.cell_2port.pin.bl0]
|
||||
return [props.bitcell_2port.pin.bl0]
|
||||
|
||||
def get_write_br_names(self):
|
||||
""" Creates a list of br pin names asscociated with write ports"""
|
||||
return [props.bitcell.cell_2port.pin.br1]
|
||||
return [props.bitcell_2port.pin.br1]
|
||||
|
||||
def get_bl_name(self, port=0):
|
||||
"""Get bl name by port"""
|
||||
|
|
@ -118,7 +103,7 @@ class bitcell_2port(bitcell_base.bitcell_base):
|
|||
pin_dict = {pin: port for pin, port in zip(self.pins, port_nets)}
|
||||
# Edges hardcoded here. Essentially wl->bl/br for both ports.
|
||||
# Port 0 edges
|
||||
pins = props.bitcell.cell_2port.pin
|
||||
pins = props.bitcell_2port.pin
|
||||
graph.add_edge(pin_dict[pins.wl0], pin_dict[pins.bl0], self)
|
||||
graph.add_edge(pin_dict[pins.wl0], pin_dict[pins.br0], self)
|
||||
# Port 1 edges
|
||||
|
|
|
|||
|
|
@ -18,19 +18,22 @@ class bitcell_base(design.design):
|
|||
"""
|
||||
Base bitcell parameters to be over-riden.
|
||||
"""
|
||||
cell_size_layer = "boundary"
|
||||
|
||||
def __init__(self, name, hard_cell=True):
|
||||
def __init__(self, name, prop=None):
|
||||
design.design.__init__(self, name)
|
||||
|
||||
if hard_cell:
|
||||
if prop:
|
||||
self.pins = prop.port_names
|
||||
self.add_pin_types(prop.port_types)
|
||||
self.nets_match = self.do_nets_exist(prop.storage_nets)
|
||||
self.mirror = prop.mirror
|
||||
self.end_caps = prop.end_caps
|
||||
|
||||
(self.width, self.height) = utils.get_libcell_size(self.cell_name,
|
||||
GDS["unit"],
|
||||
layer[self.cell_size_layer])
|
||||
self.pin_map = utils.get_libcell_pins(self.pin_names,
|
||||
layer[prop.boundary_layer])
|
||||
self.pin_map = utils.get_libcell_pins(self.pins,
|
||||
self.cell_name,
|
||||
GDS["unit"])
|
||||
self.add_pin_types(self.type_list)
|
||||
|
||||
def get_stage_effort(self, load):
|
||||
parasitic_delay = 1
|
||||
|
|
|
|||
|
|
@ -17,15 +17,8 @@ class dummy_bitcell_1port(bitcell_base.bitcell_base):
|
|||
the layout and netlist should be available in the technology
|
||||
library.
|
||||
"""
|
||||
pin_names = [props.bitcell.cell_1port.pin.bl,
|
||||
props.bitcell.cell_1port.pin.br,
|
||||
props.bitcell.cell_1port.pin.wl,
|
||||
props.bitcell.cell_1port.pin.vdd,
|
||||
props.bitcell.cell_1port.pin.gnd]
|
||||
type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]
|
||||
|
||||
def __init__(self, name):
|
||||
super().__init__(name)
|
||||
super().__init__(name, props.bitcell_1port)
|
||||
debug.info(2, "Create dummy bitcell")
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -17,19 +17,8 @@ class dummy_bitcell_2port(bitcell_base.bitcell_base):
|
|||
is a hand-made cell, so the layout and netlist should be available in
|
||||
the technology library. """
|
||||
|
||||
pin_names = [props.bitcell.cell_2port.pin.bl0,
|
||||
props.bitcell.cell_2port.pin.br0,
|
||||
props.bitcell.cell_2port.pin.bl1,
|
||||
props.bitcell.cell_2port.pin.br1,
|
||||
props.bitcell.cell_2port.pin.wl0,
|
||||
props.bitcell.cell_2port.pin.wl1,
|
||||
props.bitcell.cell_2port.pin.vdd,
|
||||
props.bitcell.cell_2port.pin.gnd]
|
||||
type_list = ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT",
|
||||
"INPUT", "INPUT", "POWER", "GROUND"]
|
||||
|
||||
def __init__(self, name):
|
||||
super().__init__(name)
|
||||
super().__init__(name, props.bitcel_2port)
|
||||
debug.info(2, "Create dummy bitcell 2 port object")
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
import contact
|
||||
import debug
|
||||
from tech import drc, parameter, layer
|
||||
from tech import cell_properties as props
|
||||
from vector import vector
|
||||
from ptx import ptx
|
||||
from globals import OPTS
|
||||
|
|
@ -29,8 +30,9 @@ class pbitcell(bitcell_base.bitcell_base):
|
|||
|
||||
self.replica_bitcell = replica_bitcell
|
||||
self.dummy_bitcell = dummy_bitcell
|
||||
self.mirror = props.bitcell_1port.mirror
|
||||
|
||||
bitcell_base.bitcell_base.__init__(self, name, hard_cell=False)
|
||||
bitcell_base.bitcell_base.__init__(self, name)
|
||||
fmt_str = "{0} rw ports, {1} w ports and {2} r ports"
|
||||
info_string = fmt_str.format(self.num_rw_ports,
|
||||
self.num_w_ports,
|
||||
|
|
|
|||
|
|
@ -19,15 +19,8 @@ class replica_bitcell_1port(bitcell_base.bitcell_base):
|
|||
is a hand-made cell, so the layout and netlist should be available in
|
||||
the technology library. """
|
||||
|
||||
pin_names = [props.bitcell.cell_1port.pin.bl,
|
||||
props.bitcell.cell_1port.pin.br,
|
||||
props.bitcell.cell_1port.pin.wl,
|
||||
props.bitcell.cell_1port.pin.vdd,
|
||||
props.bitcell.cell_1port.pin.gnd]
|
||||
type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]
|
||||
|
||||
def __init__(self, name):
|
||||
super().__init__(name)
|
||||
super().__init__(name, props.bitcell_1port)
|
||||
debug.info(2, "Create replica bitcell object")
|
||||
|
||||
def get_stage_effort(self, load):
|
||||
|
|
|
|||
|
|
@ -19,18 +19,8 @@ class replica_bitcell_2port(bitcell_base.bitcell_base):
|
|||
is a hand-made cell, so the layout and netlist should be available in
|
||||
the technology library. """
|
||||
|
||||
pin_names = [props.bitcell.cell_2port.pin.bl0,
|
||||
props.bitcell.cell_2port.pin.br0,
|
||||
props.bitcell.cell_2port.pin.bl1,
|
||||
props.bitcell.cell_2port.pin.br1,
|
||||
props.bitcell.cell_2port.pin.wl0,
|
||||
props.bitcell.cell_2port.pin.wl1,
|
||||
props.bitcell.cell_2port.pin.vdd,
|
||||
props.bitcell.cell_2port.pin.gnd]
|
||||
type_list = ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", "INPUT", "INPUT", "POWER", "GROUND"]
|
||||
|
||||
def __init__(self, name):
|
||||
super().__init__(name)
|
||||
super().__init__(name, props.bitcell_2port)
|
||||
debug.info(2, "Create replica bitcell 2 port object")
|
||||
|
||||
def get_stage_effort(self, load):
|
||||
|
|
|
|||
|
|
@ -6,40 +6,19 @@
|
|||
# All rights reserved.
|
||||
#
|
||||
import design
|
||||
from tech import GDS, layer, spice
|
||||
from tech import spice
|
||||
from tech import cell_properties as props
|
||||
import utils
|
||||
|
||||
|
||||
class dff(design.design):
|
||||
"""
|
||||
Memory address flip-flop
|
||||
"""
|
||||
if not props.dff.use_custom_ports:
|
||||
pin_names = ["D", "Q", "clk", "vdd", "gnd"]
|
||||
type_list = ["INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]
|
||||
clk_pin = "clk"
|
||||
else:
|
||||
pin_names = props.dff.custom_port_list
|
||||
type_list = props.dff.custom_type_list
|
||||
clk_pin = props.dff.clk_pin
|
||||
cell_size_layer = "boundary"
|
||||
|
||||
def __init__(self, name="dff"):
|
||||
super().__init__(name)
|
||||
|
||||
(width, height) = utils.get_libcell_size(self.cell_name,
|
||||
GDS["unit"],
|
||||
layer[self.cell_size_layer])
|
||||
|
||||
pin_map = utils.get_libcell_pins(self.pin_names,
|
||||
self.cell_name,
|
||||
GDS["unit"])
|
||||
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.pin_map = pin_map
|
||||
self.add_pin_types(self.type_list)
|
||||
self.clk_pin = props.dff.clk_pin
|
||||
|
||||
def analytical_power(self, corner, load):
|
||||
"""Returns dynamic and leakage power. Results in nW"""
|
||||
|
|
@ -54,9 +33,9 @@ class dff(design.design):
|
|||
def calculate_effective_capacitance(self, load):
|
||||
"""Computes effective capacitance. Results in fF"""
|
||||
c_load = load
|
||||
c_para = spice["dff_out_cap"]#ff
|
||||
c_para = spice["dff_out_cap"] # ff
|
||||
transition_prob = 0.5
|
||||
return transition_prob*(c_load + c_para)
|
||||
return transition_prob * (c_load + c_para)
|
||||
|
||||
def build_graph(self, graph, inst_name, port_nets):
|
||||
"""Adds edges based on inputs/outputs. Overrides base class function."""
|
||||
|
|
|
|||
|
|
@ -6,9 +6,8 @@
|
|||
# All rights reserved.
|
||||
#
|
||||
import design
|
||||
from tech import GDS, layer, spice, parameter
|
||||
import logical_effort
|
||||
import utils
|
||||
from tech import spice, parameter
|
||||
|
||||
|
||||
class inv_dec(design.design):
|
||||
|
|
@ -16,26 +15,9 @@ class inv_dec(design.design):
|
|||
INV for address decoders.
|
||||
"""
|
||||
|
||||
pin_names = ["A", "Z", "vdd", "gnd"]
|
||||
type_list = ["INPUT", "OUTPUT", "POWER", "GROUND"]
|
||||
cell_size_layer = "boundary"
|
||||
|
||||
def __init__(self, name="inv_dec", height=None):
|
||||
super().__init__(name)
|
||||
|
||||
(width, height) = utils.get_libcell_size(self.cell_name,
|
||||
GDS["unit"],
|
||||
layer[self.cell_size_layer])
|
||||
|
||||
pin_map = utils.get_libcell_pins(self.pin_names,
|
||||
self.cell_name,
|
||||
GDS["unit"])
|
||||
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.pin_map = pin_map
|
||||
self.add_pin_types(self.type_list)
|
||||
|
||||
def analytical_power(self, corner, load):
|
||||
"""Returns dynamic and leakage power. Results in nW"""
|
||||
c_eff = self.calculate_effective_capacitance(load)
|
||||
|
|
@ -52,7 +34,7 @@ class inv_dec(design.design):
|
|||
# In fF
|
||||
c_para = spice["min_tx_drain_c"] * (self.nmos_size / parameter["min_tx_size"])
|
||||
|
||||
return transition_prob * (c_load + c_para)
|
||||
return 0.5 * (c_load + c_para)
|
||||
|
||||
def input_load(self):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -6,9 +6,8 @@
|
|||
# All rights reserved.
|
||||
#
|
||||
import design
|
||||
from tech import GDS, layer, spice, parameter, drc
|
||||
from tech import spice, parameter, drc
|
||||
import logical_effort
|
||||
import utils
|
||||
|
||||
|
||||
class nand2_dec(design.design):
|
||||
|
|
@ -16,26 +15,9 @@ class nand2_dec(design.design):
|
|||
2-input NAND decoder for address decoders.
|
||||
"""
|
||||
|
||||
pin_names = ["A", "B", "Z", "vdd", "gnd"]
|
||||
type_list = ["INPUT", "INPUT", "OUTPUT", "POWER", "GROUND"]
|
||||
cell_size_layer = "boundary"
|
||||
|
||||
def __init__(self, name="nand2_dec", height=None):
|
||||
super().__init__(name)
|
||||
|
||||
(width, height) = utils.get_libcell_size(self.cell_name,
|
||||
GDS["unit"],
|
||||
layer[self.cell_size_layer])
|
||||
|
||||
pin_map = utils.get_libcell_pins(self.pin_names,
|
||||
self.cell_name,
|
||||
GDS["unit"])
|
||||
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.pin_map = pin_map
|
||||
self.add_pin_types(self.type_list)
|
||||
|
||||
# FIXME: For now...
|
||||
size = 1
|
||||
self.size = size
|
||||
|
|
|
|||
|
|
@ -6,9 +6,8 @@
|
|||
# All rights reserved.
|
||||
#
|
||||
import design
|
||||
from tech import GDS, layer, spice, parameter, drc
|
||||
from tech import spice, parameter, drc
|
||||
import logical_effort
|
||||
import utils
|
||||
|
||||
|
||||
class nand3_dec(design.design):
|
||||
|
|
@ -16,26 +15,9 @@ class nand3_dec(design.design):
|
|||
3-input NAND decoder for address decoders.
|
||||
"""
|
||||
|
||||
pin_names = ["A", "B", "C", "Z", "vdd", "gnd"]
|
||||
type_list = ["INPUT", "INPUT", "INPUT", "OUTPUT", "POWER", "GROUND"]
|
||||
cell_size_layer = "boundary"
|
||||
|
||||
def __init__(self, name="nand3_dec", height=None):
|
||||
super().__init__(name)
|
||||
|
||||
(width, height) = utils.get_libcell_size(self.cell_name,
|
||||
GDS["unit"],
|
||||
layer[self.cell_size_layer])
|
||||
|
||||
pin_map = utils.get_libcell_pins(self.pin_names,
|
||||
self.cell_name,
|
||||
GDS["unit"])
|
||||
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.pin_map = pin_map
|
||||
self.add_pin_types(self.type_list)
|
||||
|
||||
# FIXME: For now...
|
||||
size = 1
|
||||
self.size = size
|
||||
|
|
|
|||
|
|
@ -6,36 +6,18 @@
|
|||
# All rights reserved.
|
||||
#
|
||||
import design
|
||||
from tech import GDS, layer, spice, parameter, drc
|
||||
from tech import spice, parameter, drc
|
||||
import logical_effort
|
||||
import utils
|
||||
|
||||
|
||||
class nand4_dec(design.design):
|
||||
"""
|
||||
2-input NAND decoder for address decoders.
|
||||
4-input NAND decoder for address decoders.
|
||||
"""
|
||||
|
||||
pin_names = ["A", "B", "C", "D", "Z", "vdd", "gnd"]
|
||||
type_list = ["INPUT", "INPUT", "INPUT", "INPUT", "OUTPUT", "POWER", "GROUND"]
|
||||
cell_size_layer = "boundary"
|
||||
|
||||
def __init__(self, name="nand4_dec", height=None):
|
||||
super().__init__(name)
|
||||
|
||||
(width, height) = utils.get_libcell_size(self.cell_name,
|
||||
GDS["unit"],
|
||||
layer[self.cell_size_layer])
|
||||
|
||||
pin_map = utils.get_libcell_pins(self.pin_names,
|
||||
self.cell_name,
|
||||
GDS["unit"])
|
||||
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.pin_map = pin_map
|
||||
self.add_pin_types(self.type_list)
|
||||
|
||||
# FIXME: For now...
|
||||
size = 1
|
||||
self.size = size
|
||||
|
|
|
|||
|
|
@ -7,8 +7,7 @@
|
|||
#
|
||||
import design
|
||||
import debug
|
||||
import utils
|
||||
from tech import GDS, layer, parameter, drc
|
||||
from tech import parameter, drc
|
||||
from tech import cell_properties as props
|
||||
import logical_effort
|
||||
|
||||
|
|
@ -20,32 +19,11 @@ class sense_amp(design.design):
|
|||
the technology library.
|
||||
Sense amplifier to read a pair of bit-lines.
|
||||
"""
|
||||
pin_names = [props.sense_amp.pin.bl,
|
||||
props.sense_amp.pin.br,
|
||||
props.sense_amp.pin.dout,
|
||||
props.sense_amp.pin.en,
|
||||
props.sense_amp.pin.vdd,
|
||||
props.sense_amp.pin.gnd]
|
||||
type_list = ["INPUT", "INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]
|
||||
cell_size_layer = "boundary"
|
||||
|
||||
def __init__(self, name="sense_amp"):
|
||||
super().__init__(name)
|
||||
debug.info(2, "Create sense_amp")
|
||||
|
||||
(width, height) = utils.get_libcell_size(self.cell_name,
|
||||
GDS["unit"],
|
||||
layer[self.cell_size_layer])
|
||||
|
||||
pin_map = utils.get_libcell_pins(self.pin_names,
|
||||
self.cell_name,
|
||||
GDS["unit"])
|
||||
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.pin_map = pin_map
|
||||
self.add_pin_types(self.type_list)
|
||||
|
||||
def get_bl_names(self):
|
||||
return props.sense_amp.pin.bl
|
||||
|
||||
|
|
|
|||
|
|
@ -7,8 +7,7 @@
|
|||
#
|
||||
import debug
|
||||
import design
|
||||
import utils
|
||||
from tech import GDS, layer
|
||||
from tech import spice
|
||||
|
||||
|
||||
class tri_gate(design.design):
|
||||
|
|
@ -18,10 +17,6 @@ class tri_gate(design.design):
|
|||
netlist should be available in the technology library.
|
||||
"""
|
||||
|
||||
pin_names = ["in", "out", "en", "en_bar", "vdd", "gnd"]
|
||||
type_list = ["INPUT", "OUTPUT", "INPUT", "INPUT", "POWER", "GROUND"]
|
||||
cell_size_layer = "boundary"
|
||||
|
||||
unique_id = 1
|
||||
|
||||
def __init__(self, name=""):
|
||||
|
|
@ -31,19 +26,6 @@ class tri_gate(design.design):
|
|||
super().__init__(self, name)
|
||||
debug.info(2, "Create tri_gate")
|
||||
|
||||
(width, height) = utils.get_libcell_size(self.cell_name,
|
||||
GDS["unit"],
|
||||
layer[self.cell_size_layer])
|
||||
|
||||
pin_map = utils.get_libcell_pins(self.pin_names,
|
||||
self.cell_name,
|
||||
GDS["unit"])
|
||||
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.pin_map = pin_map
|
||||
self.add_pin_types(self.type_list)
|
||||
|
||||
def analytical_power(self, corner, load):
|
||||
"""Returns dynamic and leakage power. Results in nW"""
|
||||
#Power in this module currently not defined. Returns 0 nW (leakage and dynamic).
|
||||
|
|
@ -51,7 +33,7 @@ class tri_gate(design.design):
|
|||
return total_power
|
||||
|
||||
def get_cin(self):
|
||||
return 9*spice["min_tx_gate_c"]
|
||||
return 9 * spice["min_tx_gate_c"]
|
||||
|
||||
def build_graph(self, graph, inst_name, port_nets):
|
||||
"""Adds edges based on inputs/outputs. Overrides base class function."""
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@
|
|||
#
|
||||
import debug
|
||||
import design
|
||||
import utils
|
||||
from tech import GDS, layer
|
||||
from tech import cell_properties as props
|
||||
|
||||
|
||||
|
|
@ -20,33 +18,10 @@ class write_driver(design.design):
|
|||
the technology library.
|
||||
"""
|
||||
|
||||
pin_names = [props.write_driver.pin.din,
|
||||
props.write_driver.pin.bl,
|
||||
props.write_driver.pin.br,
|
||||
props.write_driver.pin.en,
|
||||
props.write_driver.pin.vdd,
|
||||
props.write_driver.pin.gnd]
|
||||
|
||||
type_list = ["INPUT", "OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]
|
||||
cell_size_layer = "boundary"
|
||||
|
||||
def __init__(self, name):
|
||||
super().__init__(name)
|
||||
debug.info(2, "Create write_driver")
|
||||
|
||||
(width, height) = utils.get_libcell_size(self.cell_name,
|
||||
GDS["unit"],
|
||||
layer[self.cell_size_layer])
|
||||
|
||||
pin_map = utils.get_libcell_pins(self.pin_names,
|
||||
self.cell_name,
|
||||
GDS["unit"])
|
||||
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.pin_map = pin_map
|
||||
self.add_pin_types(self.type_list)
|
||||
|
||||
def get_bl_names(self):
|
||||
return props.write_driver.pin.bl
|
||||
|
||||
|
|
@ -64,7 +39,7 @@ class write_driver(design.design):
|
|||
def get_w_en_cin(self):
|
||||
"""Get the relative capacitance of a single input"""
|
||||
# This is approximated from SCMOS. It has roughly 5 3x transistor gates.
|
||||
return 5*3
|
||||
return 5 * 3
|
||||
|
||||
def build_graph(self, graph, inst_name, port_nets):
|
||||
"""Adds edges based on inputs/outputs. Overrides base class function."""
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
#
|
||||
import debug
|
||||
import design
|
||||
from tech import cell_properties
|
||||
from sram_factory import factory
|
||||
from globals import OPTS
|
||||
|
||||
|
|
@ -174,7 +173,7 @@ class bitcell_base_array(design.design):
|
|||
tempx = xoffset
|
||||
dir_y = False
|
||||
# If we mirror the current cell on the y axis adjust the x position
|
||||
if cell_properties.bitcell.mirror.y and (col + col_offset) % 2:
|
||||
if self.cell.mirror.y and (col + col_offset) % 2:
|
||||
tempx = xoffset + self.cell.width
|
||||
dir_y = True
|
||||
return (tempx, dir_y)
|
||||
|
|
@ -183,7 +182,7 @@ class bitcell_base_array(design.design):
|
|||
tempy = yoffset
|
||||
dir_x = False
|
||||
# If we mirror the current cell on the x axis adjust the y position
|
||||
if cell_properties.bitcell.mirror.x and (row + row_offset) % 2:
|
||||
if self.cell.mirror.x and (row + row_offset) % 2:
|
||||
tempy = yoffset + self.cell.height
|
||||
dir_x = True
|
||||
return (tempy, dir_x)
|
||||
|
|
|
|||
|
|
@ -26,12 +26,9 @@ class col_cap_array(bitcell_base_array):
|
|||
def create_netlist(self):
|
||||
""" Create and connect the netlist """
|
||||
# This will create a default set of bitline/wordline names
|
||||
try:
|
||||
end_caps_enabled = cell_properties.bitcell.end_caps
|
||||
except AttributeError:
|
||||
end_caps_enabled = False
|
||||
self.cell = factory.create(module_type=OPTS.bitcell)
|
||||
|
||||
if not end_caps_enabled:
|
||||
if not self.cell.end_caps:
|
||||
self.create_all_wordline_names()
|
||||
self.create_all_bitline_names()
|
||||
|
||||
|
|
@ -51,8 +48,6 @@ class col_cap_array(bitcell_base_array):
|
|||
self.dummy_cell = factory.create(module_type="col_cap_{}".format(OPTS.bitcell))
|
||||
self.add_mod(self.dummy_cell)
|
||||
|
||||
self.cell = factory.create(module_type=OPTS.bitcell)
|
||||
|
||||
def create_instances(self):
|
||||
""" Create the module instances used in this design """
|
||||
self.cell_inst = {}
|
||||
|
|
|
|||
|
|
@ -662,9 +662,6 @@ class control_logic(design.design):
|
|||
self.ctrl_dff_inst=self.add_inst(name="ctrl_dffs",
|
||||
mod=self.ctrl_dff_array)
|
||||
inst_pins = self.input_list + self.dff_output_list + ["clk_buf"] + self.supply_list
|
||||
if props.dff_buff_array.add_body_contacts:
|
||||
inst_pins.append("vpb")
|
||||
inst_pins.append("vnb")
|
||||
self.connect_inst(inst_pins)
|
||||
|
||||
def place_dffs(self):
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ class dff_array(design.design):
|
|||
mod=self.dff)
|
||||
instance_ports = [self.get_din_name(row, col),
|
||||
self.get_dout_name(row, col)]
|
||||
for port in self.dff.pin_names:
|
||||
for port in self.dff.pins:
|
||||
if port != 'D' and port != 'Q':
|
||||
instance_ports.append(port)
|
||||
self.connect_inst(instance_ports)
|
||||
|
|
|
|||
|
|
@ -72,30 +72,22 @@ class dff_buf(design.design):
|
|||
self.add_mod(self.inv2)
|
||||
|
||||
def add_pins(self):
|
||||
self.add_pin("D", "INPUT")
|
||||
self.add_pin("Q", "OUTPUT")
|
||||
self.add_pin("Qb", "OUTPUT")
|
||||
self.add_pin("clk", "INPUT")
|
||||
self.add_pin("vdd", "POWER")
|
||||
self.add_pin("gnd", "GROUND")
|
||||
|
||||
if props.dff_buff.add_body_contacts:
|
||||
self.add_pin("vpb", "INPUT")
|
||||
self.add_pin("vpn", "INPUT")
|
||||
self.add_pin_list(props.dff_buf.port_names,
|
||||
props.dff_buf.port_types)
|
||||
|
||||
def create_instances(self):
|
||||
self.dff_inst=self.add_inst(name="dff_buf_dff",
|
||||
mod=self.dff)
|
||||
|
||||
self.connect_inst(["D", "qint", "clk", "vdd", "gnd"])
|
||||
self.connect_inst([props.dff_buf.pin.D, "qint", props.dff_buf.pin.clk, props.dff_buf.pin.vdd, props.dff_buf.pin.gnd])
|
||||
|
||||
self.inv1_inst=self.add_inst(name="dff_buf_inv1",
|
||||
mod=self.inv1)
|
||||
self.connect_inst(["qint", "Qb", "vdd", "gnd"])
|
||||
self.connect_inst(["qint", "Qb", props.dff_buf.pin.vdd, props.dff_buf.pin.gnd])
|
||||
|
||||
self.inv2_inst=self.add_inst(name="dff_buf_inv2",
|
||||
mod=self.inv2)
|
||||
self.connect_inst(["Qb", "Q", "vdd", "gnd"])
|
||||
self.connect_inst(["Qb", props.dff_buf.pin.Q, props.dff_buf.pin.vdd, props.dff_buf.pin.gnd])
|
||||
|
||||
def place_instances(self):
|
||||
# Add the DFF
|
||||
|
|
@ -129,7 +121,7 @@ class dff_buf(design.design):
|
|||
self.route_layer = "m1"
|
||||
|
||||
# Route dff q to inv1 a
|
||||
q_pin = self.dff_inst.get_pin("Q")
|
||||
q_pin = self.dff_inst.get_pin(props.dff.pin.Q)
|
||||
a1_pin = self.inv1_inst.get_pin("A")
|
||||
mid1 = vector(a1_pin.cx(), q_pin.cy())
|
||||
self.add_path(q_pin.layer, [q_pin.center(), mid1, a1_pin.center()], width=q_pin.height())
|
||||
|
|
@ -146,30 +138,30 @@ class dff_buf(design.design):
|
|||
def add_layout_pins(self):
|
||||
|
||||
# Continous vdd rail along with label.
|
||||
vdd_pin=self.dff_inst.get_pin("vdd")
|
||||
self.add_layout_pin(text="vdd",
|
||||
vdd_pin=self.dff_inst.get_pin(props.dff.pin.vdd)
|
||||
self.add_layout_pin(text=props.dff_buf.pin.vdd,
|
||||
layer=vdd_pin.layer,
|
||||
offset=vdd_pin.ll(),
|
||||
width=self.width,
|
||||
height=vdd_pin.height())
|
||||
|
||||
# Continous gnd rail along with label.
|
||||
gnd_pin=self.dff_inst.get_pin("gnd")
|
||||
self.add_layout_pin(text="gnd",
|
||||
gnd_pin=self.dff_inst.get_pin(props.dff.pin.gnd)
|
||||
self.add_layout_pin(text=props.dff_buf.pin.gnd,
|
||||
layer=gnd_pin.layer,
|
||||
offset=gnd_pin.ll(),
|
||||
width=self.width,
|
||||
height=vdd_pin.height())
|
||||
|
||||
clk_pin = self.dff_inst.get_pin("clk")
|
||||
self.add_layout_pin(text="clk",
|
||||
clk_pin = self.dff_inst.get_pin(props.dff.pin.clk)
|
||||
self.add_layout_pin(text=props.dff_buf.pin.clk,
|
||||
layer=clk_pin.layer,
|
||||
offset=clk_pin.ll(),
|
||||
width=clk_pin.width(),
|
||||
height=clk_pin.height())
|
||||
|
||||
din_pin = self.dff_inst.get_pin("D")
|
||||
self.add_layout_pin(text="D",
|
||||
din_pin = self.dff_inst.get_pin(props.dff_buf.pin.D)
|
||||
self.add_layout_pin(text=props.dff_buf.pin.D,
|
||||
layer=din_pin.layer,
|
||||
offset=din_pin.ll(),
|
||||
width=din_pin.width(),
|
||||
|
|
@ -178,7 +170,7 @@ class dff_buf(design.design):
|
|||
dout_pin = self.inv2_inst.get_pin("Z")
|
||||
mid_pos = dout_pin.center() + vector(self.m2_nonpref_pitch, 0)
|
||||
q_pos = mid_pos - vector(0, 2 * self.m2_nonpref_pitch)
|
||||
self.add_layout_pin_rect_center(text="Q",
|
||||
self.add_layout_pin_rect_center(text=props.dff_buf.pin.Q,
|
||||
layer="m2",
|
||||
offset=q_pos)
|
||||
self.add_path(self.route_layer, [dout_pin.center(), mid_pos, q_pos])
|
||||
|
|
|
|||
|
|
@ -65,10 +65,6 @@ class dff_buf_array(design.design):
|
|||
self.add_pin("vdd", "POWER")
|
||||
self.add_pin("gnd", "GROUND")
|
||||
|
||||
if props.dff_buff_array.add_body_contacts:
|
||||
self.add_pin("vpb", "INPUT")
|
||||
self.add_pin("vnb", "INPUT")
|
||||
|
||||
def add_modules(self):
|
||||
self.dff = factory.create(module_type="dff_buf",
|
||||
inv1_size=self.inv1_size,
|
||||
|
|
@ -88,9 +84,6 @@ class dff_buf_array(design.design):
|
|||
"clk",
|
||||
"vdd",
|
||||
"gnd"]
|
||||
if props.dff_buff_array.add_body_contacts:
|
||||
inst_ports.append("vpb")
|
||||
inst_ports.append("vnb")
|
||||
self.connect_inst(inst_ports)
|
||||
|
||||
def place_dff_array(self):
|
||||
|
|
@ -155,7 +148,7 @@ class dff_buf_array(design.design):
|
|||
|
||||
def route_supplies(self):
|
||||
for row in range(self.rows):
|
||||
vdd0_pin=self.dff_insts[row, 0].get_pin("vdd")
|
||||
vdd0_pin=self.dff_insts[row, 0].get_pin(props.dff.pin.vdd)
|
||||
vddn_pin=self.dff_insts[row, self.columns - 1].get_pin("vdd")
|
||||
self.add_path(vdd0_pin.layer, [vdd0_pin.lc(), vddn_pin.rc()], width=vdd0_pin.height())
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import debug
|
|||
from vector import vector
|
||||
from sram_factory import factory
|
||||
from globals import OPTS
|
||||
from tech import cell_properties
|
||||
|
||||
|
||||
class precharge_array(design.design):
|
||||
|
|
@ -79,6 +78,8 @@ class precharge_array(design.design):
|
|||
bitcell_br=self.bitcell_br)
|
||||
self.add_mod(self.pc_cell)
|
||||
|
||||
self.cell = factory.create(module_type=OPTS.bitcell)
|
||||
|
||||
def add_layout_pins(self):
|
||||
|
||||
en_pin = self.pc_cell.get_pin("en_bar")
|
||||
|
|
@ -120,7 +121,7 @@ class precharge_array(design.design):
|
|||
self.offsets = [n * self.pc_cell.width for n in range(self.columns)]
|
||||
|
||||
for i, xoffset in enumerate(self.offsets):
|
||||
if cell_properties.bitcell.mirror.y and (i + self.column_offset) % 2:
|
||||
if self.cell.mirror.y and (i + self.column_offset) % 2:
|
||||
mirror = "MY"
|
||||
tempx = xoffset + self.pc_cell.width
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -63,13 +63,8 @@ class replica_bitcell_array(bitcell_base_array):
|
|||
# Two dummy cols plus replica if we add the column
|
||||
self.extra_cols = len(self.left_rbl) + len(self.right_rbl)
|
||||
|
||||
|
||||
try:
|
||||
end_caps_enabled = cell_properties.bitcell.end_caps
|
||||
except AttributeError:
|
||||
end_caps_enabled = False
|
||||
# If we aren't using row/col caps, then we need to use the bitcell
|
||||
if not end_caps_enabled:
|
||||
if not self.cell.end_caps:
|
||||
self.extra_rows += 2
|
||||
self.extra_cols += 2
|
||||
|
||||
|
|
@ -144,10 +139,6 @@ class replica_bitcell_array(bitcell_base_array):
|
|||
column_offset=column_offset,
|
||||
replica_bit=replica_bit)
|
||||
self.add_mod(self.replica_columns[port])
|
||||
try:
|
||||
end_caps_enabled = cell_properties.bitcell.end_caps
|
||||
except AttributeError:
|
||||
end_caps_enabled = False
|
||||
|
||||
# Dummy row
|
||||
self.dummy_row = factory.create(module_type="dummy_array",
|
||||
|
|
@ -159,7 +150,7 @@ class replica_bitcell_array(bitcell_base_array):
|
|||
self.add_mod(self.dummy_row)
|
||||
|
||||
# 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 self.cell.end_caps else "dummy_array")
|
||||
self.col_cap_top = factory.create(module_type=col_cap_module_type,
|
||||
cols=self.column_size,
|
||||
rows=1,
|
||||
|
|
@ -179,7 +170,7 @@ class replica_bitcell_array(bitcell_base_array):
|
|||
self.add_mod(self.col_cap_bottom)
|
||||
|
||||
# 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 self.cell.end_caps else "dummy_array")
|
||||
|
||||
self.row_cap_left = factory.create(module_type=row_cap_module_type,
|
||||
cols=1,
|
||||
|
|
@ -240,11 +231,6 @@ class replica_bitcell_array(bitcell_base_array):
|
|||
self.add_pin_list(self.rbl_bitline_names[port], "INOUT")
|
||||
|
||||
def add_wordline_pins(self):
|
||||
try:
|
||||
end_caps_enabled = cell_properties.bitcell.end_caps
|
||||
except AttributeError:
|
||||
end_caps_enabled = False
|
||||
|
||||
|
||||
# Wordlines to ground
|
||||
self.gnd_wordline_names = []
|
||||
|
|
@ -385,14 +371,10 @@ class replica_bitcell_array(bitcell_base_array):
|
|||
|
||||
def add_replica_columns(self):
|
||||
""" Add replica columns on left and right of array """
|
||||
try:
|
||||
end_caps_enabled = cell_properties.bitcell.end_caps
|
||||
except AttributeError:
|
||||
end_caps_enabled = False
|
||||
|
||||
# Grow from left to right, toward the array
|
||||
for bit, port in enumerate(self.left_rbl):
|
||||
if not end_caps_enabled:
|
||||
if not self.cell.end_caps:
|
||||
offset = self.bitcell_offset.scale(-len(self.left_rbl) + bit, -self.rbl[0] - 1) + self.strap_offset.scale(-len(self.left_rbl) + bit, 0) + self.unused_offset
|
||||
else:
|
||||
offset = self.bitcell_offset.scale(-len(self.left_rbl) + bit, -self.rbl[0] - (self.col_end_offset.y/self.cell.height)) + self.strap_offset.scale(-len(self.left_rbl) + bit, 0) + self.unused_offset
|
||||
|
|
@ -400,7 +382,7 @@ class replica_bitcell_array(bitcell_base_array):
|
|||
self.replica_col_insts[bit].place(offset)
|
||||
# Grow to the right of the bitcell array, array outward
|
||||
for bit, port in enumerate(self.right_rbl):
|
||||
if not end_caps_enabled:
|
||||
if not self.cell.end_caps:
|
||||
offset = self.bitcell_array_inst.lr() + self.bitcell_offset.scale(bit, -self.rbl[0] - 1) + self.strap_offset.scale(bit, -self.rbl[0] - 1)
|
||||
else:
|
||||
offset = self.bitcell_array_inst.lr() + self.bitcell_offset.scale(bit, -self.rbl[0] - (self.col_end_offset.y/self.cell.height)) + self.strap_offset.scale(bit, -self.rbl[0] - 1)
|
||||
|
|
@ -422,15 +404,11 @@ class replica_bitcell_array(bitcell_base_array):
|
|||
|
||||
def add_end_caps(self):
|
||||
""" Add dummy cells or end caps around the array """
|
||||
try:
|
||||
end_caps_enabled = cell_properties.bitcell.end_caps
|
||||
except AttributeError:
|
||||
end_caps_enabled = False
|
||||
|
||||
# FIXME: These depend on the array size itself
|
||||
# Far top dummy row (first row above array is NOT flipped)
|
||||
flip_dummy = self.rbl[1] % 2
|
||||
if not end_caps_enabled:
|
||||
if not self.cell.end_caps:
|
||||
dummy_row_offset = self.bitcell_offset.scale(0, self.rbl[1] + flip_dummy) + self.bitcell_array_inst.ul()
|
||||
else:
|
||||
dummy_row_offset = self.bitcell_offset.scale(0, self.rbl[1] + flip_dummy) + self.bitcell_array_inst.ul()
|
||||
|
|
@ -440,7 +418,7 @@ class replica_bitcell_array(bitcell_base_array):
|
|||
# FIXME: These depend on the array size itself
|
||||
# Far bottom dummy row (first row below array IS flipped)
|
||||
flip_dummy = (self.rbl[0] + 1) % 2
|
||||
if not end_caps_enabled:
|
||||
if not self.cell.end_caps:
|
||||
dummy_row_offset = self.bitcell_offset.scale(0, -self.rbl[0] - 1 + flip_dummy) + self.unused_offset
|
||||
else:
|
||||
dummy_row_offset = self.bitcell_offset.scale(0, -self.rbl[0] - (self.col_end_offset.y/self.cell.height) + flip_dummy) + self.unused_offset
|
||||
|
|
@ -448,7 +426,7 @@ class replica_bitcell_array(bitcell_base_array):
|
|||
mirror="MX" if flip_dummy else "R0")
|
||||
# Far left dummy col
|
||||
# Shifted down by the number of left RBLs even if we aren't adding replica column to this bitcell array
|
||||
if not end_caps_enabled:
|
||||
if not self.cell.end_caps:
|
||||
dummy_col_offset = self.bitcell_offset.scale(-len(self.left_rbl) - 1, -self.rbl[0] - 1) + self.unused_offset
|
||||
else:
|
||||
dummy_col_offset = self.bitcell_offset.scale(-(len(self.left_rbl)*(1+self.strap_offset.x/self.cell.width)) - (self.row_end_offset.x/self.cell.width), -len(self.left_rbl) - (self.col_end_offset.y/self.cell.height))
|
||||
|
|
@ -456,7 +434,7 @@ class replica_bitcell_array(bitcell_base_array):
|
|||
self.dummy_col_insts[0].place(offset=dummy_col_offset)
|
||||
# Far right dummy col
|
||||
# Shifted down by the number of left RBLs even if we aren't adding replica column to this bitcell array
|
||||
if not end_caps_enabled:
|
||||
if not self.cell.end_caps:
|
||||
dummy_col_offset = self.bitcell_offset.scale(len(self.right_rbl), -self.rbl[0] - 1) + self.bitcell_array_inst.lr()
|
||||
else:
|
||||
dummy_col_offset = self.bitcell_offset.scale(len(self.right_rbl)*(1+self.strap_offset.x/self.cell.width), -self.rbl[0] - (self.col_end_offset.y/self.cell.height)) + self.bitcell_array_inst.lr()
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#
|
||||
import debug
|
||||
from bitcell_base_array import bitcell_base_array
|
||||
from tech import cell_properties
|
||||
from tech import cell_properties as props
|
||||
from sram_factory import factory
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
|
|
@ -30,11 +30,9 @@ class replica_column(bitcell_base_array):
|
|||
self.replica_bit = replica_bit
|
||||
# left, right, regular rows plus top/bottom dummy cells
|
||||
self.total_size = self.left_rbl + rows + self.right_rbl
|
||||
try:
|
||||
if not cell_properties.bitcell.end_caps:
|
||||
self.total_size += 2
|
||||
except AttributeError:
|
||||
self.total_size += 2
|
||||
|
||||
# For end caps
|
||||
self.total_size += 2
|
||||
|
||||
self.column_offset = column_offset
|
||||
|
||||
|
|
@ -82,20 +80,17 @@ class replica_column(bitcell_base_array):
|
|||
self.dummy_cell = factory.create(module_type=OPTS.dummy_bitcell)
|
||||
self.add_mod(self.dummy_cell)
|
||||
try:
|
||||
edge_module_type = ("col_cap" if cell_properties.bitcell.end_caps else "dummy")
|
||||
edge_module_type = ("col_cap" if self.cell.end_caps else "dummy")
|
||||
except AttributeError:
|
||||
edge_module_type = "dummy"
|
||||
self.edge_cell = factory.create(module_type=edge_module_type + "_" + OPTS.bitcell)
|
||||
self.add_mod(self.edge_cell)
|
||||
|
||||
# Used for pin names only
|
||||
self.cell = factory.create(module_type=OPTS.bitcell)
|
||||
|
||||
def create_instances(self):
|
||||
self.cell_inst = {}
|
||||
try:
|
||||
end_caps_enabled = cell_properties.bitcell.end_caps
|
||||
except AttributeError:
|
||||
end_caps_enabled = False
|
||||
|
||||
for row in range(self.total_size):
|
||||
name="rbc_{0}".format(row)
|
||||
|
|
@ -113,7 +108,7 @@ class replica_column(bitcell_base_array):
|
|||
elif (row == 0 or row == self.total_size - 1):
|
||||
self.cell_inst[row]=self.add_inst(name=name,
|
||||
mod=self.edge_cell)
|
||||
if end_caps_enabled:
|
||||
if self.cell.end_caps:
|
||||
self.connect_inst(self.get_bitcell_pins_col_cap(row, 0))
|
||||
else:
|
||||
self.connect_inst(self.get_bitcell_pins(row, 0))
|
||||
|
|
@ -131,13 +126,13 @@ class replica_column(bitcell_base_array):
|
|||
# column that needs to be flipped.
|
||||
dir_y = False
|
||||
xoffset = 0
|
||||
if cell_properties.bitcell.mirror.y and self.column_offset % 2:
|
||||
if self.replica_cell.mirror.y and self.column_offset % 2:
|
||||
dir_y = True
|
||||
xoffset = self.replica_cell.width
|
||||
|
||||
for row in range(self.total_size):
|
||||
# name = "bit_r{0}_{1}".format(row, "rbl")
|
||||
dir_x = cell_properties.bitcell.mirror.x and (row + rbl_offset) % 2
|
||||
dir_x = self.replica_cell.mirror.x and (row + rbl_offset) % 2
|
||||
|
||||
offset = vector(xoffset, self.cell.height * (row + (row + rbl_offset) % 2))
|
||||
|
||||
|
|
@ -169,12 +164,7 @@ class replica_column(bitcell_base_array):
|
|||
width=bl_pin.width(),
|
||||
height=self.height)
|
||||
|
||||
try:
|
||||
end_caps_enabled = cell_properties.bitcell.end_caps
|
||||
except AttributeError:
|
||||
end_caps_enabled = False
|
||||
|
||||
if end_caps_enabled:
|
||||
if self.cell.end_caps:
|
||||
row_range_max = self.total_size - 1
|
||||
row_range_min = 1
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ from vector import vector
|
|||
from sram_factory import factory
|
||||
import debug
|
||||
from globals import OPTS
|
||||
from tech import cell_properties
|
||||
|
||||
|
||||
class sense_amp_array(design.design):
|
||||
|
|
@ -92,7 +91,6 @@ class sense_amp_array(design.design):
|
|||
|
||||
def add_modules(self):
|
||||
self.amp = factory.create(module_type="sense_amp")
|
||||
|
||||
self.add_mod(self.amp)
|
||||
|
||||
# This is just used for measurements,
|
||||
|
|
@ -122,7 +120,7 @@ class sense_amp_array(design.design):
|
|||
self.offsets.append(i * self.bitcell.width)
|
||||
|
||||
for i, xoffset in enumerate(self.offsets[0:self.num_cols:self.words_per_row]):
|
||||
if cell_properties.bitcell.mirror.y and (i * self.words_per_row + self.column_offset) % 2:
|
||||
if self.bitcell.mirror.y and (i * self.words_per_row + self.column_offset) % 2:
|
||||
mirror = "MY"
|
||||
xoffset = xoffset + self.amp_spacing
|
||||
else:
|
||||
|
|
@ -134,7 +132,7 @@ class sense_amp_array(design.design):
|
|||
# place spare sense amps (will share the same enable as regular sense amps)
|
||||
for i, xoffset in enumerate(self.offsets[self.num_cols:]):
|
||||
index = self.word_size + i
|
||||
if cell_properties.bitcell.mirror.y and (index + self.column_offset) % 2:
|
||||
if self.bitcell.mirror.y and (index + self.column_offset) % 2:
|
||||
mirror = "MY"
|
||||
xoffset = xoffset + self.amp_width
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ from tech import drc
|
|||
from sram_factory import factory
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
from tech import cell_properties
|
||||
|
||||
|
||||
class write_driver_array(design.design):
|
||||
|
|
@ -161,7 +160,7 @@ class write_driver_array(design.design):
|
|||
self.offsets.append(i * self.driver_spacing)
|
||||
|
||||
for i, xoffset in enumerate(self.offsets[0:self.columns:self.words_per_row]):
|
||||
if cell_properties.bitcell.mirror.y and (i * self.words_per_row + self.column_offset) % 2:
|
||||
if self.bitcell.mirror.y and (i * self.words_per_row + self.column_offset) % 2:
|
||||
mirror = "MY"
|
||||
xoffset = xoffset + self.driver.width
|
||||
else:
|
||||
|
|
@ -174,7 +173,7 @@ class write_driver_array(design.design):
|
|||
for i, xoffset in enumerate(self.offsets[self.columns:]):
|
||||
index = self.word_size + i
|
||||
|
||||
if cell_properties.bitcell.mirror.y and (index + self.column_offset) % 2:
|
||||
if self.bitcell.mirror.y and (index + self.column_offset) % 2:
|
||||
mirror = "MY"
|
||||
xoffset = xoffset + self.driver.width
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -31,11 +31,8 @@ tech_modules = module_type()
|
|||
# Custom cell properties
|
||||
###################################################
|
||||
cell_properties = cell_properties()
|
||||
cell_properties.bitcell.mirror.x = True
|
||||
cell_properties.bitcell.mirror.y = False
|
||||
cell_properties.bitcell_power_pin_directions = ("V", "V")
|
||||
|
||||
|
||||
###################################################
|
||||
# Custom cell properties
|
||||
###################################################
|
||||
|
|
|
|||
|
|
@ -30,9 +30,6 @@ tech_modules = module_type()
|
|||
# Custom cell properties
|
||||
###################################################
|
||||
cell_properties = cell_properties()
|
||||
cell_properties.bitcell.mirror.x = True
|
||||
cell_properties.bitcell.mirror.y = False
|
||||
|
||||
|
||||
###################################################
|
||||
# Custom cell properties
|
||||
|
|
|
|||
Loading…
Reference in New Issue