Fix pbitcell erros

This commit is contained in:
mrg 2020-11-13 15:55:55 -08:00
parent c472a94f1e
commit 8021430122
32 changed files with 236 additions and 500 deletions

View File

@ -5,7 +5,47 @@
# (acting for and on behalf of Oklahoma State University) # (acting for and on behalf of Oklahoma State University)
# All rights reserved. # 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: class _pins:
@ -16,20 +56,6 @@ class _pins:
self.__dict__[k] = v 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: class _mirror_axis:
def __init__(self, x, y): def __init__(self, x, y):
self.x = x self.x = x
@ -47,65 +73,38 @@ class _pgate:
self.add_implants = add_implants self.add_implants = add_implants
class _bitcell: class _bitcell(_cell):
def __init__(self, mirror, cell_1port, cell_2port): def __init__(self, port_order, port_types, port_map=None, storage_nets=["Q", "Q_bar"], mirror=None, end_caps=False):
self.mirror = mirror super().__init__(port_order, port_types, port_map)
self._1rw = cell_1port
self._2rw = cell_2port
def _default(): self._end_caps = end_caps
axis = _mirror_axis(True, False)
cell_1port = _cell({'bl': 'bl', if not mirror:
'br': 'br', self._mirror = _mirror_axis(True, False)
'wl': 'wl'}) else:
self._mirror = mirror
cell_2port = _cell({'bl0': 'bl0', self._storage_nets = storage_nets
'br0': 'br0',
'bl1': 'bl1',
'br1': 'br1',
'wl0': 'wl0',
'wl1': 'wl1'})
return _bitcell(cell_1port=cell_1port,
cell_2port=cell_2port,
mirror=axis)
@property @property
def cell_1port(self): def end_caps(self):
return self._1rw return self._end_caps
@property @property
def cell_2port(self): def mirror(self):
return self._2rw return self._mirror
@property
def storage_nets(self):
return self._storage_nets
class _dff: class _dff(_cell):
def __init__(self, use_custom_ports, custom_port_list, custom_type_list, clk_pin): def __init__(self, clk_pin, port_order, port_types, port_map=None, hard_cell=True):
self.use_custom_ports = use_custom_ports super().__init__(port_order, port_types, port_map, hard_cell)
self.custom_port_list = custom_port_list
self.custom_type_list = custom_type_list
self.clk_pin = clk_pin 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(): class cell_properties():
""" """
This contains meta information about the custom designed cells. For This contains meta information about the custom designed cells. For
@ -126,40 +125,40 @@ class cell_properties():
self.names["row_cap_bitcell_1port"] = "row_cap_cell_1rw" self.names["row_cap_bitcell_1port"] = "row_cap_cell_1rw"
self.names["row_cap_bitcell_2port"] = "row_cap_cell_2rw" self.names["row_cap_bitcell_2port"] = "row_cap_cell_2rw"
self._bitcell = _bitcell._default()
self._ptx = _ptx(model_is_subckt=False, self._ptx = _ptx(model_is_subckt=False,
bin_spice_models=False) bin_spice_models=False)
self._pgate = _pgate(add_implants=False) self._pgate = _pgate(add_implants=False)
self._dff = _dff(use_custom_ports=False, self._nand2_dec = _cell(["A", "B", "Z", "vdd", "gnd"],
custom_port_list=["D", "Q", "clk", "vdd", "gnd"], ["INPUT", "INPUT", "OUTPUT", "POWER", "GROUND"])
custom_type_list=["INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"],
clk_pin="clk")
self._dff_buff = _dff_buff(use_custom_ports=False, self._nand2_dec = _cell(["A", "B", "C", "Z", "vdd", "gnd"],
custom_buff_ports=["D", "qint", "clk", "vdd", "gnd"], ["INPUT", "INPUT", "INPUT", "OUTPUT", "POWER", "GROUND"])
add_body_contacts=False)
self._dff_buff_array = _dff_buff_array(use_custom_ports=False, self._nand2_dec = _cell(["A", "B", "C", "D", "Z", "vdd", "gnd"],
add_body_contacts=False) ["INPUT", "INPUT", "INPUT", "INPUT", "OUTPUT", "POWER", "GROUND"])
self._write_driver = _cell({'din': 'din', self._dff = _dff("clk",
'bl': 'bl', ["D", "Q", "clk", "vdd", "gnd"],
'br': 'br', ["INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"])
'en': 'en'})
self._sense_amp = _cell({'bl': 'bl', self._dff_buf = _dff("clk",
'br': 'br', ["D", "Q", "Qb", "clk", "vdd", "gnd"],
'dout': 'dout', ["INPUT", "OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"],
'en': 'en'}) hard_cell=False)
self._bitcell_array = _bitcell_array(use_custom_cell_arrangement=[]) self._write_driver = _cell(['din', 'bl', 'br', 'en', 'vdd', 'gnd'],
["INPUT", "OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"])
@property self._sense_amp = _cell(['bl', 'br', 'dout', 'en', 'vdd', 'gnd'],
def bitcell(self): ["INPUT", "INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"])
return self._bitcell
self._bitcell_1port = _bitcell(["bl", "br", "wl", "vdd", "gnd"],
["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"])
self._bitcell_2port = _bitcell(["bl0", "br0", "bl1", "br1", "wl0", "wl1", "vdd", "gnd"],
["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", "INPUT", "INPUT", "POWER", "GROUND"])
@property @property
def ptx(self): def ptx(self):
@ -174,12 +173,8 @@ class cell_properties():
return self._dff return self._dff
@property @property
def dff_buff(self): def dff_buf(self):
return self._dff_buff return self._dff_buf
@property
def dff_buff_array(self):
return self._dff_buff_array
@property @property
def write_driver(self): def write_driver(self):
@ -190,13 +185,10 @@ class cell_properties():
return self._sense_amp return self._sense_amp
@property @property
def bitcell_array(self): def bitcell_1port(self):
return self._bitcell_array 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

View File

@ -6,8 +6,9 @@
# All rights reserved. # All rights reserved.
# #
from hierarchy_design import hierarchy_design from hierarchy_design import hierarchy_design
from utils import round_to_grid import utils
import contact import contact
from tech import GDS, layer
from tech import preferred_directions from tech import preferred_directions
from tech import cell_properties as props from tech import cell_properties as props
from globals import OPTS from globals import OPTS
@ -31,6 +32,26 @@ class design(hierarchy_design):
cell_name = name cell_name = name
super().__init__(name, cell_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() self.setup_multiport_constants()
def check_pins(self): def check_pins(self):
@ -232,8 +253,7 @@ class design(hierarchy_design):
#print(contact1) #print(contact1)
pitch = contact_width + layer_space pitch = contact_width + layer_space
return round_to_grid(pitch) return utils.round_to_grid(pitch)
def setup_multiport_constants(self): def setup_multiport_constants(self):
""" """

View File

@ -78,6 +78,7 @@ class spice():
""" Adds a pin_list to the pins list """ """ Adds a pin_list to the pins list """
# The type list can be a single type for all pins # The type list can be a single type for all pins
# or a list that is the same length as the pin list. # or a list that is the same length as the pin list.
if type(pin_type)==str: if type(pin_type)==str:
for pin in pin_list: for pin in pin_list:
debug.check(pin_type in self.valid_signal_types, debug.check(pin_type in self.valid_signal_types,
@ -100,12 +101,12 @@ class spice():
Typically, should only be used for handmade cells. Typically, should only be used for handmade cells.
""" """
# This only works if self.pins == bitcell.pin_names # This only works if self.pins == bitcell.pin_names
if self.pin_names != self.pins: if len(type_list) != len(self.pins):
debug.error("{} spice subcircuit port names do not match pin_names\ debug.error("{} spice subcircuit number of port types does not match number of pins\
\n SPICE names={}\ \n SPICE names={}\
\n Module names={}\ \n Module names={}\
".format(self.name, self.pins, self.pin_names), 1) ".format(self.name, self.pins, type_list), 1)
self.pin_type = {pin: type for pin, type in zip(self.pin_names, type_list)} self.pin_type = {pin: type for pin, type in zip(self.pins, type_list)}
def get_pin_type(self, name): def get_pin_type(self, name):
""" Returns the type of the signal pin. """ """ Returns the type of the signal pin. """

View File

@ -18,53 +18,43 @@ class bitcell_1port(bitcell_base.bitcell_base):
library. 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): def __init__(self, name):
super().__init__(name) super().__init__(name, props.bitcell_1port)
debug.info(2, "Create bitcell") debug.info(2, "Create bitcell")
self.nets_match = self.do_nets_exist(self.storage_nets)
def get_all_wl_names(self): def get_all_wl_names(self):
""" Creates a list of all wordline pin names """ """ 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 return row_pins
def get_all_bitline_names(self): def get_all_bitline_names(self):
""" Creates a list of all bitline pin names (both bl and br) """ """ 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] column_pins = [pin.bl, pin.br]
return column_pins return column_pins
def get_all_bl_names(self): def get_all_bl_names(self):
""" Creates a list of all bl pins names """ """ 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): def get_all_br_names(self):
""" Creates a list of all br pins names """ """ 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): def get_bl_name(self, port=0):
"""Get bl name""" """Get bl name"""
debug.check(port == 0, "One port for bitcell only.") 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): def get_br_name(self, port=0):
"""Get bl name""" """Get bl name"""
debug.check(port == 0, "One port for bitcell only.") 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): def get_wl_name(self, port=0):
"""Get wl name""" """Get wl name"""
debug.check(port == 0, "One port for bitcell only.") 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): def build_graph(self, graph, inst_name, port_nets):
""" """

View File

@ -18,35 +18,20 @@ class bitcell_2port(bitcell_base.bitcell_base):
library. 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): def __init__(self, name):
super().__init__(name) super().__init__(name, props.bitcell_2port)
debug.info(2, "Create bitcell with 2 ports") debug.info(2, "Create bitcell with 2 ports")
self.nets_match = self.do_nets_exist(self.storage_nets) 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]
pin_names = self.pin_names self.wl_names = [props.bitcell_2port.pin.wl0, props.bitcell_2port.pin.wl1]
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]]
def get_bitcell_pins(self, col, row): def get_bitcell_pins(self, col, row):
""" """
Creates a list of connections in the bitcell, Creates a list of connections in the bitcell,
indexed by column and row, for instance use in bitcell_array indexed by column and row, for instance use in bitcell_array
""" """
pin_name = props.bitcell.cell_2port.pin pin_name = props.bitcell_2port.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),
"{0}_{1}".format(pin_name.bl1, 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): def get_all_wl_names(self):
""" Creates a list of all wordline pin names """ """ Creates a list of all wordline pin names """
return [props.bitcell.cell_2port.pin.wl0, return [props.bitcell_2port.pin.wl0,
props.bitcell.cell_2port.pin.wl1] props.bitcell_2port.pin.wl1]
def get_all_bitline_names(self): def get_all_bitline_names(self):
""" Creates a list of all bitline pin names (both bl and br) """ """ Creates a list of all bitline pin names (both bl and br) """
return [props.bitcell.cell_2port.pin.bl0, return [props.bitcell_2port.pin.bl0,
props.bitcell.cell_2port.pin.br0, props.bitcell_2port.pin.br0,
props.bitcell.cell_2port.pin.bl1, props.bitcell_2port.pin.bl1,
props.bitcell.cell_2port.pin.br1] props.bitcell_2port.pin.br1]
def get_all_bl_names(self): def get_all_bl_names(self):
""" Creates a list of all bl pins names """ """ Creates a list of all bl pins names """
return [props.bitcell.cell_2port.pin.bl0, return [props.bitcell_2port.pin.bl0,
props.bitcell.cell_2port.pin.bl1] props.bitcell_2port.pin.bl1]
def get_all_br_names(self): def get_all_br_names(self):
""" Creates a list of all br pins names """ """ Creates a list of all br pins names """
return [props.bitcell.cell_2port.pin.br0, return [props.bitcell_2port.pin.br0,
props.bitcell.cell_2port.pin.br1] props.bitcell_2port.pin.br1]
def get_read_bl_names(self): def get_read_bl_names(self):
""" Creates a list of bl pin names associated with read ports """ """ Creates a list of bl pin names associated with read ports """
return [props.bitcell.cell_2port.pin.bl0, return [props.bitcell_2port.pin.bl0,
props.bitcell.cell_2port.pin.bl1] props.bitcell_2port.pin.bl1]
def get_read_br_names(self): def get_read_br_names(self):
""" Creates a list of br pin names associated with read ports """ """ Creates a list of br pin names associated with read ports """
return [props.bitcell.cell_2port.pin.br0, return [props.bitcell_2port.pin.br0,
props.bitcell.cell_2port.pin.br1] props.bitcell_2port.pin.br1]
def get_write_bl_names(self): def get_write_bl_names(self):
""" Creates a list of bl pin names associated with write ports """ """ 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): def get_write_br_names(self):
""" Creates a list of br pin names asscociated with write ports""" """ 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): def get_bl_name(self, port=0):
"""Get bl name by port""" """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)} pin_dict = {pin: port for pin, port in zip(self.pins, port_nets)}
# Edges hardcoded here. Essentially wl->bl/br for both ports. # Edges hardcoded here. Essentially wl->bl/br for both ports.
# Port 0 edges # 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.bl0], self)
graph.add_edge(pin_dict[pins.wl0], pin_dict[pins.br0], self) graph.add_edge(pin_dict[pins.wl0], pin_dict[pins.br0], self)
# Port 1 edges # Port 1 edges

View File

@ -18,19 +18,22 @@ class bitcell_base(design.design):
""" """
Base bitcell parameters to be over-riden. Base bitcell parameters to be over-riden.
""" """
cell_size_layer = "boundary" def __init__(self, name, prop=None):
def __init__(self, name, hard_cell=True):
design.design.__init__(self, name) 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, (self.width, self.height) = utils.get_libcell_size(self.cell_name,
GDS["unit"], GDS["unit"],
layer[self.cell_size_layer]) layer[prop.boundary_layer])
self.pin_map = utils.get_libcell_pins(self.pin_names, self.pin_map = utils.get_libcell_pins(self.pins,
self.cell_name, self.cell_name,
GDS["unit"]) GDS["unit"])
self.add_pin_types(self.type_list)
def get_stage_effort(self, load): def get_stage_effort(self, load):
parasitic_delay = 1 parasitic_delay = 1

View File

@ -17,15 +17,8 @@ class dummy_bitcell_1port(bitcell_base.bitcell_base):
the layout and netlist should be available in the technology the layout and netlist should be available in the technology
library. 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): def __init__(self, name):
super().__init__(name) super().__init__(name, props.bitcell_1port)
debug.info(2, "Create dummy bitcell") debug.info(2, "Create dummy bitcell")

View File

@ -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 is a hand-made cell, so the layout and netlist should be available in
the technology library. """ 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): def __init__(self, name):
super().__init__(name) super().__init__(name, props.bitcel_2port)
debug.info(2, "Create dummy bitcell 2 port object") debug.info(2, "Create dummy bitcell 2 port object")

View File

@ -8,6 +8,7 @@
import contact import contact
import debug import debug
from tech import drc, parameter, layer from tech import drc, parameter, layer
from tech import cell_properties as props
from vector import vector from vector import vector
from ptx import ptx from ptx import ptx
from globals import OPTS from globals import OPTS
@ -29,8 +30,9 @@ class pbitcell(bitcell_base.bitcell_base):
self.replica_bitcell = replica_bitcell self.replica_bitcell = replica_bitcell
self.dummy_bitcell = dummy_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" fmt_str = "{0} rw ports, {1} w ports and {2} r ports"
info_string = fmt_str.format(self.num_rw_ports, info_string = fmt_str.format(self.num_rw_ports,
self.num_w_ports, self.num_w_ports,

View File

@ -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 is a hand-made cell, so the layout and netlist should be available in
the technology library. """ 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): def __init__(self, name):
super().__init__(name) super().__init__(name, props.bitcell_1port)
debug.info(2, "Create replica bitcell object") debug.info(2, "Create replica bitcell object")
def get_stage_effort(self, load): def get_stage_effort(self, load):

View File

@ -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 is a hand-made cell, so the layout and netlist should be available in
the technology library. """ 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): def __init__(self, name):
super().__init__(name) super().__init__(name, props.bitcell_2port)
debug.info(2, "Create replica bitcell 2 port object") debug.info(2, "Create replica bitcell 2 port object")
def get_stage_effort(self, load): def get_stage_effort(self, load):

View File

@ -6,40 +6,19 @@
# All rights reserved. # All rights reserved.
# #
import design import design
from tech import GDS, layer, spice from tech import spice
from tech import cell_properties as props from tech import cell_properties as props
import utils
class dff(design.design): class dff(design.design):
""" """
Memory address flip-flop 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"): def __init__(self, name="dff"):
super().__init__(name) super().__init__(name)
(width, height) = utils.get_libcell_size(self.cell_name, self.clk_pin = props.dff.clk_pin
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): def analytical_power(self, corner, load):
"""Returns dynamic and leakage power. Results in nW""" """Returns dynamic and leakage power. Results in nW"""
@ -54,9 +33,9 @@ class dff(design.design):
def calculate_effective_capacitance(self, load): def calculate_effective_capacitance(self, load):
"""Computes effective capacitance. Results in fF""" """Computes effective capacitance. Results in fF"""
c_load = load c_load = load
c_para = spice["dff_out_cap"]#ff c_para = spice["dff_out_cap"] # ff
transition_prob = 0.5 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): def build_graph(self, graph, inst_name, port_nets):
"""Adds edges based on inputs/outputs. Overrides base class function.""" """Adds edges based on inputs/outputs. Overrides base class function."""

View File

@ -6,9 +6,8 @@
# All rights reserved. # All rights reserved.
# #
import design import design
from tech import GDS, layer, spice, parameter
import logical_effort import logical_effort
import utils from tech import spice, parameter
class inv_dec(design.design): class inv_dec(design.design):
@ -16,26 +15,9 @@ class inv_dec(design.design):
INV for address decoders. 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): def __init__(self, name="inv_dec", height=None):
super().__init__(name) 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): def analytical_power(self, corner, load):
"""Returns dynamic and leakage power. Results in nW""" """Returns dynamic and leakage power. Results in nW"""
c_eff = self.calculate_effective_capacitance(load) c_eff = self.calculate_effective_capacitance(load)
@ -52,7 +34,7 @@ class inv_dec(design.design):
# In fF # In fF
c_para = spice["min_tx_drain_c"] * (self.nmos_size / parameter["min_tx_size"]) 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): def input_load(self):
""" """

View File

@ -6,9 +6,8 @@
# All rights reserved. # All rights reserved.
# #
import design import design
from tech import GDS, layer, spice, parameter, drc from tech import spice, parameter, drc
import logical_effort import logical_effort
import utils
class nand2_dec(design.design): class nand2_dec(design.design):
@ -16,26 +15,9 @@ class nand2_dec(design.design):
2-input NAND decoder for address decoders. 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): def __init__(self, name="nand2_dec", height=None):
super().__init__(name) 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... # FIXME: For now...
size = 1 size = 1
self.size = size self.size = size

View File

@ -6,9 +6,8 @@
# All rights reserved. # All rights reserved.
# #
import design import design
from tech import GDS, layer, spice, parameter, drc from tech import spice, parameter, drc
import logical_effort import logical_effort
import utils
class nand3_dec(design.design): class nand3_dec(design.design):
@ -16,26 +15,9 @@ class nand3_dec(design.design):
3-input NAND decoder for address decoders. 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): def __init__(self, name="nand3_dec", height=None):
super().__init__(name) 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... # FIXME: For now...
size = 1 size = 1
self.size = size self.size = size

View File

@ -6,36 +6,18 @@
# All rights reserved. # All rights reserved.
# #
import design import design
from tech import GDS, layer, spice, parameter, drc from tech import spice, parameter, drc
import logical_effort import logical_effort
import utils
class nand4_dec(design.design): 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): def __init__(self, name="nand4_dec", height=None):
super().__init__(name) 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... # FIXME: For now...
size = 1 size = 1
self.size = size self.size = size

View File

@ -7,8 +7,7 @@
# #
import design import design
import debug import debug
import utils from tech import parameter, drc
from tech import GDS, layer, parameter, drc
from tech import cell_properties as props from tech import cell_properties as props
import logical_effort import logical_effort
@ -20,32 +19,11 @@ class sense_amp(design.design):
the technology library. the technology library.
Sense amplifier to read a pair of bit-lines. 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"): def __init__(self, name="sense_amp"):
super().__init__(name) super().__init__(name)
debug.info(2, "Create sense_amp") 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): def get_bl_names(self):
return props.sense_amp.pin.bl return props.sense_amp.pin.bl

View File

@ -7,8 +7,7 @@
# #
import debug import debug
import design import design
import utils from tech import spice
from tech import GDS, layer
class tri_gate(design.design): class tri_gate(design.design):
@ -18,10 +17,6 @@ class tri_gate(design.design):
netlist should be available in the technology library. 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 unique_id = 1
def __init__(self, name=""): def __init__(self, name=""):
@ -31,19 +26,6 @@ class tri_gate(design.design):
super().__init__(self, name) super().__init__(self, name)
debug.info(2, "Create tri_gate") 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): def analytical_power(self, corner, load):
"""Returns dynamic and leakage power. Results in nW""" """Returns dynamic and leakage power. Results in nW"""
#Power in this module currently not defined. Returns 0 nW (leakage and dynamic). #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 return total_power
def get_cin(self): 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): def build_graph(self, graph, inst_name, port_nets):
"""Adds edges based on inputs/outputs. Overrides base class function.""" """Adds edges based on inputs/outputs. Overrides base class function."""

View File

@ -7,8 +7,6 @@
# #
import debug import debug
import design import design
import utils
from tech import GDS, layer
from tech import cell_properties as props from tech import cell_properties as props
@ -20,33 +18,10 @@ class write_driver(design.design):
the technology library. 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): def __init__(self, name):
super().__init__(name) super().__init__(name)
debug.info(2, "Create write_driver") 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): def get_bl_names(self):
return props.write_driver.pin.bl return props.write_driver.pin.bl
@ -64,7 +39,7 @@ class write_driver(design.design):
def get_w_en_cin(self): def get_w_en_cin(self):
"""Get the relative capacitance of a single input""" """Get the relative capacitance of a single input"""
# This is approximated from SCMOS. It has roughly 5 3x transistor gates. # 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): def build_graph(self, graph, inst_name, port_nets):
"""Adds edges based on inputs/outputs. Overrides base class function.""" """Adds edges based on inputs/outputs. Overrides base class function."""

View File

@ -7,7 +7,6 @@
# #
import debug import debug
import design import design
from tech import cell_properties
from sram_factory import factory from sram_factory import factory
from globals import OPTS from globals import OPTS
@ -174,7 +173,7 @@ class bitcell_base_array(design.design):
tempx = xoffset tempx = xoffset
dir_y = False dir_y = False
# If we mirror the current cell on the y axis adjust the x position # 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 tempx = xoffset + self.cell.width
dir_y = True dir_y = True
return (tempx, dir_y) return (tempx, dir_y)
@ -183,7 +182,7 @@ class bitcell_base_array(design.design):
tempy = yoffset tempy = yoffset
dir_x = False dir_x = False
# If we mirror the current cell on the x axis adjust the y position # 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 tempy = yoffset + self.cell.height
dir_x = True dir_x = True
return (tempy, dir_x) return (tempy, dir_x)

View File

@ -26,12 +26,9 @@ 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 # This will create a default set of bitline/wordline names
try: self.cell = factory.create(module_type=OPTS.bitcell)
end_caps_enabled = cell_properties.bitcell.end_caps
except AttributeError:
end_caps_enabled = False
if not end_caps_enabled: if not self.cell.end_caps:
self.create_all_wordline_names() self.create_all_wordline_names()
self.create_all_bitline_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.dummy_cell = factory.create(module_type="col_cap_{}".format(OPTS.bitcell))
self.add_mod(self.dummy_cell) self.add_mod(self.dummy_cell)
self.cell = factory.create(module_type=OPTS.bitcell)
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 = {}

View File

@ -662,9 +662,6 @@ class control_logic(design.design):
self.ctrl_dff_inst=self.add_inst(name="ctrl_dffs", self.ctrl_dff_inst=self.add_inst(name="ctrl_dffs",
mod=self.ctrl_dff_array) mod=self.ctrl_dff_array)
inst_pins = self.input_list + self.dff_output_list + ["clk_buf"] + self.supply_list 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) self.connect_inst(inst_pins)
def place_dffs(self): def place_dffs(self):

View File

@ -70,7 +70,7 @@ class dff_array(design.design):
mod=self.dff) mod=self.dff)
instance_ports = [self.get_din_name(row, col), instance_ports = [self.get_din_name(row, col),
self.get_dout_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': if port != 'D' and port != 'Q':
instance_ports.append(port) instance_ports.append(port)
self.connect_inst(instance_ports) self.connect_inst(instance_ports)

View File

@ -72,30 +72,22 @@ class dff_buf(design.design):
self.add_mod(self.inv2) self.add_mod(self.inv2)
def add_pins(self): def add_pins(self):
self.add_pin("D", "INPUT") self.add_pin_list(props.dff_buf.port_names,
self.add_pin("Q", "OUTPUT") props.dff_buf.port_types)
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")
def create_instances(self): def create_instances(self):
self.dff_inst=self.add_inst(name="dff_buf_dff", self.dff_inst=self.add_inst(name="dff_buf_dff",
mod=self.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", self.inv1_inst=self.add_inst(name="dff_buf_inv1",
mod=self.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", self.inv2_inst=self.add_inst(name="dff_buf_inv2",
mod=self.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): def place_instances(self):
# Add the DFF # Add the DFF
@ -129,7 +121,7 @@ class dff_buf(design.design):
self.route_layer = "m1" self.route_layer = "m1"
# Route dff q to inv1 a # 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") a1_pin = self.inv1_inst.get_pin("A")
mid1 = vector(a1_pin.cx(), q_pin.cy()) 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()) 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): def add_layout_pins(self):
# Continous vdd rail along with label. # Continous vdd rail along with label.
vdd_pin=self.dff_inst.get_pin("vdd") vdd_pin=self.dff_inst.get_pin(props.dff.pin.vdd)
self.add_layout_pin(text="vdd", self.add_layout_pin(text=props.dff_buf.pin.vdd,
layer=vdd_pin.layer, layer=vdd_pin.layer,
offset=vdd_pin.ll(), offset=vdd_pin.ll(),
width=self.width, width=self.width,
height=vdd_pin.height()) height=vdd_pin.height())
# Continous gnd rail along with label. # Continous gnd rail along with label.
gnd_pin=self.dff_inst.get_pin("gnd") gnd_pin=self.dff_inst.get_pin(props.dff.pin.gnd)
self.add_layout_pin(text="gnd", self.add_layout_pin(text=props.dff_buf.pin.gnd,
layer=gnd_pin.layer, layer=gnd_pin.layer,
offset=gnd_pin.ll(), offset=gnd_pin.ll(),
width=self.width, width=self.width,
height=vdd_pin.height()) height=vdd_pin.height())
clk_pin = self.dff_inst.get_pin("clk") clk_pin = self.dff_inst.get_pin(props.dff.pin.clk)
self.add_layout_pin(text="clk", self.add_layout_pin(text=props.dff_buf.pin.clk,
layer=clk_pin.layer, layer=clk_pin.layer,
offset=clk_pin.ll(), offset=clk_pin.ll(),
width=clk_pin.width(), width=clk_pin.width(),
height=clk_pin.height()) height=clk_pin.height())
din_pin = self.dff_inst.get_pin("D") din_pin = self.dff_inst.get_pin(props.dff_buf.pin.D)
self.add_layout_pin(text="D", self.add_layout_pin(text=props.dff_buf.pin.D,
layer=din_pin.layer, layer=din_pin.layer,
offset=din_pin.ll(), offset=din_pin.ll(),
width=din_pin.width(), width=din_pin.width(),
@ -178,7 +170,7 @@ class dff_buf(design.design):
dout_pin = self.inv2_inst.get_pin("Z") dout_pin = self.inv2_inst.get_pin("Z")
mid_pos = dout_pin.center() + vector(self.m2_nonpref_pitch, 0) mid_pos = dout_pin.center() + vector(self.m2_nonpref_pitch, 0)
q_pos = mid_pos - vector(0, 2 * self.m2_nonpref_pitch) 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", layer="m2",
offset=q_pos) offset=q_pos)
self.add_path(self.route_layer, [dout_pin.center(), mid_pos, q_pos]) self.add_path(self.route_layer, [dout_pin.center(), mid_pos, q_pos])

View File

@ -65,10 +65,6 @@ class dff_buf_array(design.design):
self.add_pin("vdd", "POWER") self.add_pin("vdd", "POWER")
self.add_pin("gnd", "GROUND") 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): def add_modules(self):
self.dff = factory.create(module_type="dff_buf", self.dff = factory.create(module_type="dff_buf",
inv1_size=self.inv1_size, inv1_size=self.inv1_size,
@ -88,9 +84,6 @@ class dff_buf_array(design.design):
"clk", "clk",
"vdd", "vdd",
"gnd"] "gnd"]
if props.dff_buff_array.add_body_contacts:
inst_ports.append("vpb")
inst_ports.append("vnb")
self.connect_inst(inst_ports) self.connect_inst(inst_ports)
def place_dff_array(self): def place_dff_array(self):
@ -155,7 +148,7 @@ class dff_buf_array(design.design):
def route_supplies(self): def route_supplies(self):
for row in range(self.rows): 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") 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()) self.add_path(vdd0_pin.layer, [vdd0_pin.lc(), vddn_pin.rc()], width=vdd0_pin.height())

View File

@ -10,7 +10,6 @@ import debug
from vector import vector from vector import vector
from sram_factory import factory from sram_factory import factory
from globals import OPTS from globals import OPTS
from tech import cell_properties
class precharge_array(design.design): class precharge_array(design.design):
@ -79,6 +78,8 @@ class precharge_array(design.design):
bitcell_br=self.bitcell_br) bitcell_br=self.bitcell_br)
self.add_mod(self.pc_cell) self.add_mod(self.pc_cell)
self.cell = factory.create(module_type=OPTS.bitcell)
def add_layout_pins(self): def add_layout_pins(self):
en_pin = self.pc_cell.get_pin("en_bar") 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)] self.offsets = [n * self.pc_cell.width for n in range(self.columns)]
for i, xoffset in enumerate(self.offsets): 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" mirror = "MY"
tempx = xoffset + self.pc_cell.width tempx = xoffset + self.pc_cell.width
else: else:

View File

@ -63,13 +63,8 @@ class replica_bitcell_array(bitcell_base_array):
# Two dummy cols plus replica if we add the column # Two dummy cols plus replica if we add the column
self.extra_cols = len(self.left_rbl) + len(self.right_rbl) 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 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_rows += 2
self.extra_cols += 2 self.extra_cols += 2
@ -144,10 +139,6 @@ class replica_bitcell_array(bitcell_base_array):
column_offset=column_offset, column_offset=column_offset,
replica_bit=replica_bit) replica_bit=replica_bit)
self.add_mod(self.replica_columns[port]) self.add_mod(self.replica_columns[port])
try:
end_caps_enabled = cell_properties.bitcell.end_caps
except AttributeError:
end_caps_enabled = False
# Dummy row # Dummy row
self.dummy_row = factory.create(module_type="dummy_array", 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) self.add_mod(self.dummy_row)
# 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 self.cell.end_caps else "dummy_array")
self.col_cap_top = 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,
@ -179,7 +170,7 @@ class replica_bitcell_array(bitcell_base_array):
self.add_mod(self.col_cap_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 self.cell.end_caps else "dummy_array")
self.row_cap_left = factory.create(module_type=row_cap_module_type, self.row_cap_left = factory.create(module_type=row_cap_module_type,
cols=1, cols=1,
@ -240,11 +231,6 @@ class replica_bitcell_array(bitcell_base_array):
self.add_pin_list(self.rbl_bitline_names[port], "INOUT") self.add_pin_list(self.rbl_bitline_names[port], "INOUT")
def add_wordline_pins(self): def add_wordline_pins(self):
try:
end_caps_enabled = cell_properties.bitcell.end_caps
except AttributeError:
end_caps_enabled = False
# Wordlines to ground # Wordlines to ground
self.gnd_wordline_names = [] self.gnd_wordline_names = []
@ -385,14 +371,10 @@ class replica_bitcell_array(bitcell_base_array):
def add_replica_columns(self): def add_replica_columns(self):
""" Add replica columns on left and right of array """ """ 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 # Grow from left to right, toward the array
for bit, port in enumerate(self.left_rbl): 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 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: 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 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) self.replica_col_insts[bit].place(offset)
# Grow to the right of the bitcell array, array outward # Grow to the right of the bitcell array, array outward
for bit, port in enumerate(self.right_rbl): 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) 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: 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) 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): def add_end_caps(self):
""" Add dummy cells or end caps around the array """ """ 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 # FIXME: These depend on the array size itself
# Far top dummy row (first row above array is NOT flipped) # Far top dummy row (first row above array is NOT flipped)
flip_dummy = self.rbl[1] % 2 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() dummy_row_offset = self.bitcell_offset.scale(0, self.rbl[1] + flip_dummy) + self.bitcell_array_inst.ul()
else: else:
dummy_row_offset = self.bitcell_offset.scale(0, self.rbl[1] + flip_dummy) + self.bitcell_array_inst.ul() 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 # FIXME: These depend on the array size itself
# Far bottom dummy row (first row below array IS flipped) # Far bottom dummy row (first row below array IS flipped)
flip_dummy = (self.rbl[0] + 1) % 2 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 dummy_row_offset = self.bitcell_offset.scale(0, -self.rbl[0] - 1 + flip_dummy) + self.unused_offset
else: 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 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") mirror="MX" if flip_dummy else "R0")
# Far left dummy col # Far left dummy col
# Shifted down by the number of left RBLs even if we aren't adding replica column to this bitcell array # 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 dummy_col_offset = self.bitcell_offset.scale(-len(self.left_rbl) - 1, -self.rbl[0] - 1) + self.unused_offset
else: 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)) 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) self.dummy_col_insts[0].place(offset=dummy_col_offset)
# Far right dummy col # Far right dummy col
# Shifted down by the number of left RBLs even if we aren't adding replica column to this bitcell array # 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() dummy_col_offset = self.bitcell_offset.scale(len(self.right_rbl), -self.rbl[0] - 1) + self.bitcell_array_inst.lr()
else: 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() 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()

View File

@ -5,7 +5,7 @@
# #
import debug import debug
from bitcell_base_array import bitcell_base_array 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 sram_factory import factory
from vector import vector from vector import vector
from globals import OPTS from globals import OPTS
@ -30,10 +30,8 @@ class replica_column(bitcell_base_array):
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
self.total_size = self.left_rbl + rows + self.right_rbl self.total_size = self.left_rbl + rows + self.right_rbl
try:
if not cell_properties.bitcell.end_caps: # For end caps
self.total_size += 2
except AttributeError:
self.total_size += 2 self.total_size += 2
self.column_offset = column_offset 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.dummy_cell = factory.create(module_type=OPTS.dummy_bitcell)
self.add_mod(self.dummy_cell) self.add_mod(self.dummy_cell)
try: 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: except AttributeError:
edge_module_type = "dummy" edge_module_type = "dummy"
self.edge_cell = factory.create(module_type=edge_module_type + "_" + OPTS.bitcell) self.edge_cell = factory.create(module_type=edge_module_type + "_" + OPTS.bitcell)
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=OPTS.bitcell) self.cell = factory.create(module_type=OPTS.bitcell)
def create_instances(self): def create_instances(self):
self.cell_inst = {} 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): for row in range(self.total_size):
name="rbc_{0}".format(row) name="rbc_{0}".format(row)
@ -113,7 +108,7 @@ class replica_column(bitcell_base_array):
elif (row == 0 or row == self.total_size - 1): elif (row == 0 or row == self.total_size - 1):
self.cell_inst[row]=self.add_inst(name=name, self.cell_inst[row]=self.add_inst(name=name,
mod=self.edge_cell) mod=self.edge_cell)
if end_caps_enabled: if self.cell.end_caps:
self.connect_inst(self.get_bitcell_pins_col_cap(row, 0)) self.connect_inst(self.get_bitcell_pins_col_cap(row, 0))
else: else:
self.connect_inst(self.get_bitcell_pins(row, 0)) 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. # column that needs to be flipped.
dir_y = False dir_y = False
xoffset = 0 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 dir_y = True
xoffset = self.replica_cell.width xoffset = self.replica_cell.width
for row in range(self.total_size): for row in range(self.total_size):
# name = "bit_r{0}_{1}".format(row, "rbl") # 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)) 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(), width=bl_pin.width(),
height=self.height) height=self.height)
try: if self.cell.end_caps:
end_caps_enabled = cell_properties.bitcell.end_caps
except AttributeError:
end_caps_enabled = False
if end_caps_enabled:
row_range_max = self.total_size - 1 row_range_max = self.total_size - 1
row_range_min = 1 row_range_min = 1
else: else:

View File

@ -10,7 +10,6 @@ from vector import vector
from sram_factory import factory from sram_factory import factory
import debug import debug
from globals import OPTS from globals import OPTS
from tech import cell_properties
class sense_amp_array(design.design): class sense_amp_array(design.design):
@ -92,7 +91,6 @@ class sense_amp_array(design.design):
def add_modules(self): def add_modules(self):
self.amp = factory.create(module_type="sense_amp") self.amp = factory.create(module_type="sense_amp")
self.add_mod(self.amp) self.add_mod(self.amp)
# This is just used for measurements, # This is just used for measurements,
@ -122,7 +120,7 @@ class sense_amp_array(design.design):
self.offsets.append(i * self.bitcell.width) self.offsets.append(i * self.bitcell.width)
for i, xoffset in enumerate(self.offsets[0:self.num_cols:self.words_per_row]): 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" mirror = "MY"
xoffset = xoffset + self.amp_spacing xoffset = xoffset + self.amp_spacing
else: else:
@ -134,7 +132,7 @@ class sense_amp_array(design.design):
# place spare sense amps (will share the same enable as regular sense amps) # place spare sense amps (will share the same enable as regular sense amps)
for i, xoffset in enumerate(self.offsets[self.num_cols:]): for i, xoffset in enumerate(self.offsets[self.num_cols:]):
index = self.word_size + i 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" mirror = "MY"
xoffset = xoffset + self.amp_width xoffset = xoffset + self.amp_width
else: else:

View File

@ -12,7 +12,6 @@ from tech import drc
from sram_factory import factory from sram_factory import factory
from vector import vector from vector import vector
from globals import OPTS from globals import OPTS
from tech import cell_properties
class write_driver_array(design.design): class write_driver_array(design.design):
@ -161,7 +160,7 @@ class write_driver_array(design.design):
self.offsets.append(i * self.driver_spacing) self.offsets.append(i * self.driver_spacing)
for i, xoffset in enumerate(self.offsets[0:self.columns:self.words_per_row]): 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" mirror = "MY"
xoffset = xoffset + self.driver.width xoffset = xoffset + self.driver.width
else: else:
@ -174,7 +173,7 @@ class write_driver_array(design.design):
for i, xoffset in enumerate(self.offsets[self.columns:]): for i, xoffset in enumerate(self.offsets[self.columns:]):
index = self.word_size + i 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" mirror = "MY"
xoffset = xoffset + self.driver.width xoffset = xoffset + self.driver.width
else: else:

View File

@ -31,11 +31,8 @@ tech_modules = module_type()
# Custom cell properties # Custom cell properties
################################################### ###################################################
cell_properties = 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") cell_properties.bitcell_power_pin_directions = ("V", "V")
################################################### ###################################################
# Custom cell properties # Custom cell properties
################################################### ###################################################

View File

@ -30,9 +30,6 @@ tech_modules = module_type()
# Custom cell properties # Custom cell properties
################################################### ###################################################
cell_properties = cell_properties() cell_properties = cell_properties()
cell_properties.bitcell.mirror.x = True
cell_properties.bitcell.mirror.y = False
################################################### ###################################################
# Custom cell properties # Custom cell properties