mirror of
https://github.com/VLSIDA/OpenRAM.git
synced 2026-09-05 01:01:33 +02:00
First draft of sram_factory code
This commit is contained in:
@@ -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
@@ -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
|
||||
|
||||
@@ -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])
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user