2020-01-30 20:44:24 +01:00
|
|
|
# See LICENSE for licensing information.
|
|
|
|
|
#
|
|
|
|
|
# Copyright (c) 2016-2020 Regents of the University of California and The Board
|
|
|
|
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
|
|
|
|
# (acting for and on behalf of Oklahoma State University)
|
|
|
|
|
# All rights reserved.
|
|
|
|
|
#
|
2020-09-23 03:33:03 +02:00
|
|
|
from globals import OPTS
|
2020-02-12 15:03:47 +01:00
|
|
|
|
|
|
|
|
class _pins:
|
|
|
|
|
def __init__(self, pin_dict):
|
|
|
|
|
# make the pins elements of the class to allow "." access.
|
|
|
|
|
# For example: props.bitcell.cell_6t.pin.bl = "foobar"
|
|
|
|
|
for k,v in pin_dict.items():
|
|
|
|
|
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' }
|
|
|
|
|
|
2020-02-12 05:09:40 +01:00
|
|
|
class _mirror_axis:
|
|
|
|
|
def __init__(self, x, y):
|
|
|
|
|
self.x = x
|
|
|
|
|
self.y = y
|
|
|
|
|
|
|
|
|
|
class _bitcell:
|
2020-09-15 03:11:38 +02:00
|
|
|
def __init__(self, mirror, split_wl, cell_s8_6t, cell_6t, cell_1rw1r, cell_1w1r):
|
2020-02-12 05:09:40 +01:00
|
|
|
self.mirror = mirror
|
|
|
|
|
self.split_wl = split_wl
|
2020-09-15 03:11:38 +02:00
|
|
|
self._s8_6t = cell_s8_6t
|
2020-02-12 15:03:47 +01:00
|
|
|
self._6t = cell_6t
|
|
|
|
|
self._1rw1r = cell_1rw1r
|
|
|
|
|
self._1w1r = cell_1w1r
|
|
|
|
|
|
|
|
|
|
def _default():
|
|
|
|
|
axis = _mirror_axis(True, False)
|
2020-09-15 03:11:38 +02:00
|
|
|
|
|
|
|
|
cell_s8_6t = _cell({'bl' : 'bl0',
|
|
|
|
|
'br' : 'bl1',
|
|
|
|
|
'wl0': 'wl0',
|
|
|
|
|
'wl1': 'wl1'})
|
|
|
|
|
|
2020-02-12 15:03:47 +01:00
|
|
|
cell_6t = _cell({'bl' : 'bl',
|
|
|
|
|
'br' : 'br',
|
|
|
|
|
'wl' : 'wl'})
|
|
|
|
|
|
|
|
|
|
cell_1rw1r = _cell({'bl0' : 'bl0',
|
|
|
|
|
'br0' : 'br0',
|
|
|
|
|
'bl1' : 'bl1',
|
|
|
|
|
'br1' : 'br1',
|
|
|
|
|
'wl0' : 'wl0',
|
|
|
|
|
'wl1' : 'wl1'})
|
2020-09-15 03:11:38 +02:00
|
|
|
|
2020-02-12 15:03:47 +01:00
|
|
|
cell_1w1r = _cell({'bl0' : 'bl0',
|
|
|
|
|
'br0' : 'br0',
|
|
|
|
|
'bl1' : 'bl1',
|
|
|
|
|
'br1' : 'br1',
|
|
|
|
|
'wl0' : 'wl0',
|
|
|
|
|
'wl1' : 'wl1'})
|
2020-09-15 03:11:38 +02:00
|
|
|
|
|
|
|
|
return _bitcell(cell_s8_6t=cell_s8_6t,
|
|
|
|
|
cell_6t=cell_6t,
|
2020-02-12 15:03:47 +01:00
|
|
|
cell_1rw1r=cell_1rw1r,
|
|
|
|
|
cell_1w1r=cell_1w1r,
|
|
|
|
|
split_wl = False,
|
|
|
|
|
mirror=axis)
|
|
|
|
|
|
2020-09-15 03:11:38 +02:00
|
|
|
@property
|
|
|
|
|
def cell_s8_6t(self):
|
|
|
|
|
return self._s8_6t
|
|
|
|
|
|
2020-02-12 15:03:47 +01:00
|
|
|
@property
|
|
|
|
|
def cell_6t(self):
|
|
|
|
|
return self._6t
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def cell_1rw1r(self):
|
|
|
|
|
return self._1rw1r
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def cell_1w1r(self):
|
|
|
|
|
return self._1w1r
|
|
|
|
|
|
2020-01-30 20:44:24 +01:00
|
|
|
|
|
|
|
|
class _dff:
|
2020-02-05 08:35:06 +01:00
|
|
|
def __init__(self, use_custom_ports, custom_port_list, custom_type_list, clk_pin):
|
2020-01-30 20:44:24 +01:00
|
|
|
self.use_custom_ports = use_custom_ports
|
|
|
|
|
self.custom_port_list = custom_port_list
|
|
|
|
|
self.custom_type_list = custom_type_list
|
2020-02-05 08:35:06 +01:00
|
|
|
self.clk_pin = clk_pin
|
2020-01-30 20:44:24 +01:00
|
|
|
|
2020-02-10 08:10:33 +01:00
|
|
|
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
|
|
|
|
|
|
2020-09-23 03:33:03 +02:00
|
|
|
class _bitcell_array:
|
|
|
|
|
def __init__(self, use_custom_cell_arrangement):
|
|
|
|
|
self.use_custom_cell_arrangement = use_custom_cell_arrangement
|
|
|
|
|
|
2020-02-12 05:09:40 +01:00
|
|
|
class cell_properties():
|
2020-01-30 20:44:24 +01:00
|
|
|
"""
|
2020-02-12 15:03:47 +01:00
|
|
|
This contains meta information about the custom designed cells. For
|
|
|
|
|
instance, pin names, or the axis on which they need to be mirrored. These
|
|
|
|
|
can be overriden in the tech.py file.
|
2020-01-30 20:44:24 +01:00
|
|
|
"""
|
|
|
|
|
def __init__(self):
|
|
|
|
|
self.names = {}
|
2020-02-12 05:09:40 +01:00
|
|
|
|
2020-02-12 15:03:47 +01:00
|
|
|
self._bitcell = _bitcell._default()
|
2020-02-12 05:09:40 +01:00
|
|
|
|
2020-01-30 20:44:24 +01:00
|
|
|
self._dff = _dff(use_custom_ports = False,
|
2020-02-05 08:35:06 +01:00
|
|
|
custom_port_list = ["D", "Q", "clk", "vdd", "gnd"],
|
|
|
|
|
custom_type_list = ["INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"],
|
|
|
|
|
clk_pin= "clk")
|
2020-02-10 08:10:33 +01:00
|
|
|
|
|
|
|
|
self._dff_buff = _dff_buff(use_custom_ports = False,
|
|
|
|
|
custom_buff_ports = ["D", "qint", "clk", "vdd", "gnd"],
|
|
|
|
|
add_body_contacts = False)
|
|
|
|
|
|
|
|
|
|
self._dff_buff_array = _dff_buff_array(use_custom_ports = False,
|
|
|
|
|
add_body_contacts = False)
|
2020-01-30 20:44:24 +01:00
|
|
|
|
2020-02-17 14:25:00 +01:00
|
|
|
self._write_driver = _cell({'din': 'din',
|
|
|
|
|
'bl' : 'bl',
|
|
|
|
|
'br' : 'br',
|
|
|
|
|
'en' : 'en'})
|
2020-09-23 03:33:03 +02:00
|
|
|
|
2020-02-17 14:27:35 +01:00
|
|
|
self._sense_amp = _cell({'bl' : 'bl',
|
|
|
|
|
'br' : 'br',
|
|
|
|
|
'dout' : 'dout',
|
|
|
|
|
'en' : 'en'})
|
2020-02-17 14:25:00 +01:00
|
|
|
|
2020-09-23 03:33:03 +02:00
|
|
|
self._bitcell_array = _bitcell_array(use_custom_cell_arrangement = [])
|
|
|
|
|
|
2020-02-12 05:09:40 +01:00
|
|
|
@property
|
|
|
|
|
def bitcell(self):
|
|
|
|
|
return self._bitcell
|
|
|
|
|
|
2020-01-30 20:44:24 +01:00
|
|
|
@property
|
|
|
|
|
def dff(self):
|
|
|
|
|
return self._dff
|
2020-02-10 08:10:33 +01:00
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def dff_buff(self):
|
|
|
|
|
return self._dff_buff
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def dff_buff_array(self):
|
2020-02-12 05:09:40 +01:00
|
|
|
return self._dff_buff_array
|
|
|
|
|
|
2020-02-17 14:25:00 +01:00
|
|
|
@property
|
|
|
|
|
def write_driver(self):
|
|
|
|
|
return self._write_driver
|
2020-02-17 14:27:35 +01:00
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def sense_amp(self):
|
|
|
|
|
return self._sense_amp
|
2020-09-23 03:33:03 +02:00
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def bitcell_array(self):
|
|
|
|
|
return self._bitcell_array
|
|
|
|
|
|
|
|
|
|
def use_custom_bitcell_array(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
|