First draft of sram_factory code

This commit is contained in:
Matt Guthaus
2019-01-16 16:15:38 -08:00
parent e210ef2a41
commit a418431a42
74 changed files with 410 additions and 503 deletions
+4 -16
View File
@@ -3,28 +3,16 @@ from tech import drc
from math import log
from vector import vector
from globals import OPTS
from pnand2 import pnand2
from pinv import pinv
import pgate
from sram_factory import factory
class pand2(pgate.pgate):
"""
This is a simple buffer used for driving loads.
"""
from importlib import reload
c = reload(__import__(OPTS.bitcell))
bitcell = getattr(c, OPTS.bitcell)
unique_id = 1
def __init__(self, size=1, height=None, name=""):
def __init__(self, name, size=1, height=None):
self.size = size
if name=="":
name = "pand2_{0}_{1}".format(size, pand2.unique_id)
pand2.unique_id += 1
pgate.pgate.__init__(self, name, height)
debug.info(1, "Creating {}".format(self.name))
@@ -41,10 +29,10 @@ class pand2(pgate.pgate):
def create_modules(self):
# Shield the cap, but have at least a stage effort of 4
self.nand = pnand2(height=self.height)
self.nand = factory.create(module_type="pnand2",height=self.height)
self.add_mod(self.nand)
self.inv = pinv(size=self.size, height=self.height)
self.inv = factory.create(module_type="pinv", size=self.size, height=self.height)
self.add_mod(self.inv)
def create_layout(self):
+6 -16
View File
@@ -3,29 +3,19 @@ from tech import drc
from math import log
from vector import vector
from globals import OPTS
from pinv import pinv
import pgate
from sram_factory import factory
class pbuf(pgate.pgate):
"""
This is a simple buffer used for driving loads.
"""
from importlib import reload
c = reload(__import__(OPTS.bitcell))
bitcell = getattr(c, OPTS.bitcell)
unique_id = 1
def __init__(self, size=4, height=None, name=""):
def __init__(self, name, size=4, height=None):
self.stage_effort = 4
self.size = size
self.height = height
if name=="":
name = "pbuf_{0}_{1}".format(self.size, pbuf.unique_id)
pbuf.unique_id += 1
pgate.pgate.__init__(self, name, height)
debug.info(1, "creating {0} with size of {1}".format(self.name,self.size))
@@ -54,10 +44,10 @@ class pbuf(pgate.pgate):
def create_modules(self):
# Shield the cap, but have at least a stage effort of 4
input_size = max(1,int(self.size/self.stage_effort))
self.inv1 = pinv(size=input_size, height=self.height)
self.inv1 = factory.create(module_type="pinv", size=input_size, height=self.height)
self.add_mod(self.inv1)
self.inv2 = pinv(size=self.size, height=self.height)
self.inv2 = factory.create(module_type="pinv", size=self.size, height=self.height)
self.add_mod(self.inv2)
def create_insts(self):
@@ -141,4 +131,4 @@ class pbuf(pgate.pgate):
def get_cin(self):
"""Returns the relative capacitance of the input"""
input_cin = self.inv1.get_cin()
return input_cin
return input_cin
+6 -10
View File
@@ -5,15 +5,13 @@ from tech import drc
from math import log
from vector import vector
from globals import OPTS
from pinv import pinv
from sram_factory import factory
class pdriver(pgate.pgate):
"""
This instantiates an even or odd number of inverters sized for driving a load.
"""
unique_id = 1
def __init__(self, neg_polarity=False, fanout_size=8, size_list = [], height=None, name=""):
def __init__(self, name, neg_polarity=False, fanout_size=8, size_list = [], height=None):
self.stage_effort = 4
self.height = height
@@ -24,10 +22,6 @@ class pdriver(pgate.pgate):
if len(self.size_list) > 0 and (self.fanout_size != 8 or self.neg_polarity):
debug.error("Cannot specify both size_list and neg_polarity or fanout_size.", -1)
if name=="":
name = "pdriver_{}".format(pdriver.unique_id)
pdriver.unique_id += 1
pgate.pgate.__init__(self, name, height)
debug.info(1, "Creating {}".format(self.name))
@@ -123,11 +117,13 @@ class pdriver(pgate.pgate):
self.inv_list = []
if len(self.size_list) > 0: # size list specified
for x in range(len(self.size_list)):
self.inv_list.append(pinv(size=self.size_list[x], height=self.height))
temp_inv = factory.create(module_type="pinv", size=self.size_list[x], height=self.height)
self.inv_list.append(temp_inv)
self.add_mod(self.inv_list[x])
else: # find inv sizes
for x in range(len(self.calc_size_list)):
self.inv_list.append(pinv(size=self.calc_size_list[x], height=self.height))
temp_inv = factory.create(module_type="pinv", size=self.calc_size_list[x], height=self.height)
self.inv_list.append(temp_inv)
self.add_mod(self.inv_list[x])
+2 -4
View File
@@ -5,6 +5,7 @@ from tech import drc, parameter, spice
from ptx import ptx
from vector import vector
from globals import OPTS
from sram_factory import factory
class pgate(design.design):
"""
@@ -18,10 +19,7 @@ class pgate(design.design):
if height:
self.height = height
elif not height:
from importlib import reload
c = reload(__import__(OPTS.bitcell))
bitcell = getattr(c, OPTS.bitcell)
b = bitcell()
b = factory.create(module_type="bitcell")
self.height = b.height
+1 -5
View File
@@ -19,15 +19,11 @@ class pinv(pgate.pgate):
output to the right side of the cell for easier access.
"""
unique_id = 1
def __init__(self, size=1, beta=parameter["beta"], height=None, route_output=True):
def __init__(self, name, size=1, beta=parameter["beta"], height=None, route_output=True):
# We need to keep unique names because outputting to GDSII
# will use the last record with a given name. I.e., you will
# over-write a design in GDS if one has and the other doesn't
# have poly connected, for example.
name = "pinv_{}".format(pinv.unique_id)
pinv.unique_id += 1
pgate.pgate.__init__(self, name, height)
debug.info(2, "create pinv structure {0} with size of {1}".format(name, size))
+8 -13
View File
@@ -4,16 +4,14 @@ from tech import drc
from math import log
from vector import vector
from globals import OPTS
from pinv import pinv
from sram_factory import factory
class pinvbuf(design.design):
"""
This is a simple inverter/buffer used for driving loads. It is
used in the column decoder for 1:2 decoding and as the clock buffer.
"""
unique_id = 1
def __init__(self, driver_size=4, height=None, name=""):
def __init__(self, name, size=4, height=None):
self.stage_effort = 4
self.row_height = height
@@ -22,11 +20,8 @@ class pinvbuf(design.design):
# stage effort of 4 or less
# The pinvbuf has a FO of 2 for the first stage, so the second stage
# should be sized "half" to prevent loading of the first stage
self.driver_size = driver_size
self.predriver_size = max(int(self.driver_size/(self.stage_effort/2)),1)
if name=="":
name = "pinvbuf_{0}_{1}_{2}".format(self.predriver_size, self.driver_size, pinvbuf.unique_id)
pinvbuf.unique_id += 1
self.size = size
self.predriver_size = max(int(self.size/(self.stage_effort/2)),1)
design.design.__init__(self, name)
debug.info(1, "Creating {}".format(self.name))
@@ -65,13 +60,13 @@ class pinvbuf(design.design):
# Shield the cap, but have at least a stage effort of 4
input_size = max(1,int(self.predriver_size/self.stage_effort))
self.inv = pinv(size=input_size, height=self.row_height)
self.inv = factory.create(module_type="pinv", size=input_size, height=self.row_height)
self.add_mod(self.inv)
self.inv1 = pinv(size=self.predriver_size, height=self.row_height)
self.inv1 = factory.create(module_type="pinv", size=self.predriver_size, height=self.row_height)
self.add_mod(self.inv1)
self.inv2 = pinv(size=self.driver_size, height=self.row_height)
self.inv2 = factory.create(module_type="pinv", size=self.size, height=self.row_height)
self.add_mod(self.inv2)
def create_insts(self):
@@ -217,4 +212,4 @@ class pinvbuf(design.design):
stage3 = self.inv2.get_effort_stage(external_cout, last_stage_is_rise)
stage_effort_list.append(stage3)
return stage_effort_list
return stage_effort_list
+2 -7
View File
@@ -12,13 +12,8 @@ class pnand2(pgate.pgate):
This module generates gds of a parametrically sized 2-input nand.
This model use ptx to generate a 2-input nand within a cetrain height.
"""
unique_id = 1
def __init__(self, size=1, height=None):
def __init__(self, name, size=1, height=None):
""" Creates a cell for a simple 2 input nand """
name = "pnand2_{0}".format(pnand2.unique_id)
pnand2.unique_id += 1
pgate.pgate.__init__(self, name, height)
debug.info(2, "create pnand2 structure {0} with size of {1}".format(name, size))
@@ -260,4 +255,4 @@ class pnand2(pgate.pgate):
Optional is_rise refers to the input direction rise/fall. Input inverted by this stage.
"""
parasitic_delay = 2
return logical_effort.logical_effort(self.size, self.get_cin(), cout, parasitic_delay, not inp_is_rise)
return logical_effort.logical_effort(self.size, self.get_cin(), cout, parasitic_delay, not inp_is_rise)
+2 -7
View File
@@ -11,13 +11,8 @@ class pnand3(pgate.pgate):
This module generates gds of a parametrically sized 2-input nand.
This model use ptx to generate a 2-input nand within a cetrain height.
"""
unique_id = 1
def __init__(self, size=1, height=None):
def __init__(self, name, size=1, height=None):
""" Creates a cell for a simple 3 input nand """
name = "pnand3_{0}".format(pnand3.unique_id)
pnand3.unique_id += 1
pgate.pgate.__init__(self, name, height)
debug.info(2, "create pnand3 structure {0} with size of {1}".format(name, size))
@@ -272,4 +267,4 @@ class pnand3(pgate.pgate):
Optional is_rise refers to the input direction rise/fall. Input inverted by this stage.
"""
parasitic_delay = 3
return logical_effort.logical_effort(self.size, self.get_cin(), cout, parasitic_delay, not inp_is_rise)
return logical_effort.logical_effort(self.size, self.get_cin(), cout, parasitic_delay, not inp_is_rise)
+1 -6
View File
@@ -11,13 +11,8 @@ class pnor2(pgate.pgate):
This module generates gds of a parametrically sized 2-input nor.
This model use ptx to generate a 2-input nor within a cetrain height.
"""
unique_id = 1
def __init__(self, size=1, height=None):
def __init__(self, name, size=1, height=None):
""" Creates a cell for a simple 2 input nor """
name = "pnor2_{0}".format(pnor2.unique_id)
pnor2.unique_id += 1
pgate.pgate.__init__(self, name, height)
debug.info(2, "create pnor2 structure {0} with size of {1}".format(name, size))
+3 -10
View File
@@ -5,25 +5,18 @@ from tech import drc, parameter
from ptx import ptx
from vector import vector
from globals import OPTS
from sram_factory import factory
class precharge(pgate.pgate):
"""
Creates a single precharge cell
This module implements the precharge bitline cell used in the design.
"""
unique_id = 1
def __init__(self, name, size=1, bitcell_bl="bl", bitcell_br="br"):
name = name+"_{}".format(precharge.unique_id)
precharge.unique_id += 1
pgate.pgate.__init__(self, name)
debug.info(2, "create single precharge cell: {0}".format(name))
from importlib import reload
c = reload(__import__(OPTS.bitcell))
self.mod_bitcell = getattr(c, OPTS.bitcell)
self.bitcell = self.mod_bitcell()
self.bitcell = factory.create(module_type="bitcell")
self.beta = parameter["beta"]
self.ptx_width = self.beta*parameter["min_tx_size"]
@@ -268,4 +261,4 @@ class precharge(pgate.pgate):
#The enable connect to three pmos gates. They all use the same size pmos.
pmos_cin = self.pmos.get_cin()
return 3*pmos_cin
+2 -2
View File
@@ -15,7 +15,7 @@ class ptx(design.design):
you to connect the fingered gates and active for parallel devices.
"""
def __init__(self, width=drc("minwidth_tx"), mults=1, tx_type="nmos", connect_active=False, connect_poly=False, num_contacts=None):
def __init__(self, name="", width=drc("minwidth_tx"), mults=1, tx_type="nmos", connect_active=False, connect_poly=False, num_contacts=None):
# We need to keep unique names because outputting to GDSII
# will use the last record with a given name. I.e., you will
# over-write a design in GDS if one has and the other doesn't
@@ -355,4 +355,4 @@ class ptx(design.design):
def get_cin(self):
"""Returns the relative gate cin of the tx"""
return self.tx_width/drc("minwidth_tx")
return self.tx_width/drc("minwidth_tx")
+4 -12
View File
@@ -5,6 +5,7 @@ from vector import vector
import contact
from ptx import ptx
from globals import OPTS
from sram_factory import factory
class single_level_column_mux(design.design):
"""
@@ -13,14 +14,10 @@ class single_level_column_mux(design.design):
to minimum size. Default is 8x. Per Samira and Hodges-Jackson book:
Column-mux transistors driven by the decoder must be sized for optimal speed
"""
def __init__(self, name, tx_size=8, bitcell_bl="bl", bitcell_br="br"):
# This is needed for different bitline spacings
unique_id = 1
def __init__(self, tx_size=8, bitcell_bl="bl", bitcell_br="br"):
self.tx_size = int(tx_size)
name="single_level_column_mux_{}_{}".format(self.tx_size,single_level_column_mux.unique_id)
single_level_column_mux.unique_id += 1
design.design.__init__(self, name)
debug.info(2, "create single column mux cell: {0}".format(name))
@@ -47,12 +44,7 @@ class single_level_column_mux(design.design):
self.add_wells()
def add_modules(self):
# This is just used for measurements,
# so don't add the module
from importlib import reload
c = reload(__import__(OPTS.bitcell))
self.mod_bitcell = getattr(c, OPTS.bitcell)
self.bitcell = self.mod_bitcell()
self.bitcell = factory.create(module_type="bitcell")
# Adds nmos_lower,nmos_upper to the module
self.ptx_width = self.tx_size*drc("minwidth_tx")