mirror of https://github.com/VLSIDA/OpenRAM.git
Merge branch 'dev' into datasheet_gen
This commit is contained in:
commit
886dd4d313
|
|
@ -16,7 +16,9 @@ class contact(hierarchy_design.hierarchy_design):
|
|||
hierarchy as the contact.
|
||||
"""
|
||||
|
||||
def __init__(self, layer_stack, dimensions=[1,1], implant_type=None, well_type=None):
|
||||
def __init__(self, layer_stack, dimensions=[1,1], implant_type=None, well_type=None, name=""):
|
||||
# This will ignore the name parameter since we can guarantee a unique name here
|
||||
|
||||
if implant_type or well_type:
|
||||
name = "{0}_{1}_{2}_{3}x{4}_{5}{6}".format(layer_stack[0],
|
||||
layer_stack[1],
|
||||
|
|
@ -164,13 +166,13 @@ class contact(hierarchy_design.hierarchy_design):
|
|||
""" Get total power of a module """
|
||||
return self.return_power()
|
||||
|
||||
|
||||
from sram_factory import factory
|
||||
# This is not instantiated and used for calculations only.
|
||||
# These are static 1x1 contacts to reuse in all the design modules.
|
||||
well = contact(layer_stack=("active", "contact", "metal1"))
|
||||
active = contact(layer_stack=("active", "contact", "poly"))
|
||||
poly = contact(layer_stack=("poly", "contact", "metal1"))
|
||||
m1m2 = contact(layer_stack=("metal1", "via1", "metal2"))
|
||||
m2m3 = contact(layer_stack=("metal2", "via2", "metal3"))
|
||||
m3m4 = contact(layer_stack=("metal3", "via3", "metal4"))
|
||||
well = factory.create(module_type="contact", layer_stack=("active", "contact", "metal1"))
|
||||
active = factory.create(module_type="contact", layer_stack=("active", "contact", "poly"))
|
||||
poly = factory.create(module_type="contact", layer_stack=("poly", "contact", "metal1"))
|
||||
m1m2 = factory.create(module_type="contact", layer_stack=("metal1", "via1", "metal2"))
|
||||
m2m3 = factory.create(module_type="contact", layer_stack=("metal2", "via2", "metal3"))
|
||||
m3m4 = factory.create(module_type="contact", layer_stack=("metal3", "via3", "metal4"))
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import debug
|
|||
import os
|
||||
from globals import OPTS
|
||||
|
||||
|
||||
class design(hierarchy_design):
|
||||
"""
|
||||
This is the same as the hierarchy_design class except it contains
|
||||
|
|
|
|||
|
|
@ -17,20 +17,14 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
|
|||
name_map = []
|
||||
|
||||
def __init__(self, name):
|
||||
try:
|
||||
self.gds_file
|
||||
except AttributeError:
|
||||
self.gds_file = OPTS.openram_tech + "gds_lib/" + name + ".gds"
|
||||
try:
|
||||
self.sp_file
|
||||
except AttributeError:
|
||||
self.sp_file = OPTS.openram_tech + "sp_lib/" + name + ".sp"
|
||||
self.gds_file = OPTS.openram_tech + "gds_lib/" + name + ".gds"
|
||||
self.sp_file = OPTS.openram_tech + "sp_lib/" + name + ".sp"
|
||||
|
||||
self.name = name
|
||||
hierarchy_layout.layout.__init__(self, name)
|
||||
hierarchy_spice.spice.__init__(self, name)
|
||||
|
||||
|
||||
|
||||
# Check if the name already exists, if so, give an error
|
||||
# because each reference must be a unique name.
|
||||
# These modules ensure unique names or have no changes if they
|
||||
|
|
|
|||
|
|
@ -378,11 +378,12 @@ class layout():
|
|||
|
||||
def add_via(self, layers, offset, size=[1,1], mirror="R0", rotate=0, implant_type=None, well_type=None):
|
||||
""" Add a three layer via structure. """
|
||||
import contact
|
||||
via = contact.contact(layer_stack=layers,
|
||||
dimensions=size,
|
||||
implant_type=implant_type,
|
||||
well_type=well_type)
|
||||
from sram_factory import factory
|
||||
via = factory.create(module_type="contact",
|
||||
layer_stack=layers,
|
||||
dimensions=size,
|
||||
implant_type=implant_type,
|
||||
well_type=well_type)
|
||||
self.add_mod(via)
|
||||
inst=self.add_inst(name=via.name,
|
||||
mod=via,
|
||||
|
|
@ -395,11 +396,12 @@ class layout():
|
|||
|
||||
def add_via_center(self, layers, offset, size=[1,1], mirror="R0", rotate=0, implant_type=None, well_type=None):
|
||||
""" Add a three layer via structure by the center coordinate accounting for mirroring and rotation. """
|
||||
import contact
|
||||
via = contact.contact(layer_stack=layers,
|
||||
dimensions=size,
|
||||
implant_type=implant_type,
|
||||
well_type=well_type)
|
||||
from sram_factory import factory
|
||||
via = factory.create(module_type="contact",
|
||||
layer_stack=layers,
|
||||
dimensions=size,
|
||||
implant_type=implant_type,
|
||||
well_type=well_type)
|
||||
height = via.height
|
||||
width = via.width
|
||||
debug.check(mirror=="R0","Use rotate to rotate vias instead of mirror.")
|
||||
|
|
@ -1039,9 +1041,11 @@ class layout():
|
|||
|
||||
# Find the number of vias for this pitch
|
||||
self.supply_vias = 1
|
||||
import contact
|
||||
from sram_factory import factory
|
||||
while True:
|
||||
c=contact.contact(("metal1","via1","metal2"), (self.supply_vias, self.supply_vias))
|
||||
c=factory.create(module_type="contact",
|
||||
layer_stack=("metal1","via1","metal2"),
|
||||
dimensions=(self.supply_vias, self.supply_vias))
|
||||
if c.second_layer_width < self.supply_rail_width and c.second_layer_height < self.supply_rail_width:
|
||||
self.supply_vias += 1
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -16,11 +16,14 @@ class spice():
|
|||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
self.mods = [] # Holds subckts/mods for this module
|
||||
self.pins = [] # Holds the pins for this module
|
||||
self.pin_type = {} # The type map of each pin: INPUT, OUTPUT, INOUT, POWER, GROUND
|
||||
# Holds subckts/mods for this module
|
||||
self.mods = []
|
||||
# Holds the pins for this module
|
||||
self.pins = []
|
||||
# The type map of each pin: INPUT, OUTPUT, INOUT, POWER, GROUND
|
||||
# for each instance, this is the set of nets/nodes that map to the pins for this instance
|
||||
# THIS MUST MATCH THE ORDER OF THE PINS (restriction imposed by the
|
||||
self.pin_type = {}
|
||||
# THE CONNECTIONS MUST MATCH THE ORDER OF THE PINS (restriction imposed by the
|
||||
# Spice format)
|
||||
self.conns = []
|
||||
|
||||
|
|
@ -93,8 +96,8 @@ class spice():
|
|||
from pprint import pformat
|
||||
modpins_string=pformat(self.insts[-1].mod.pins)
|
||||
argpins_string=pformat(args)
|
||||
debug.error("Connections: {}".format(modpins_string))
|
||||
debug.error("Connections: {}".format(argpins_string))
|
||||
debug.error("Mod connections: {}".format(modpins_string))
|
||||
debug.error("Inst connections: {}".format(argpins_string))
|
||||
debug.error("Number of net connections ({0}) does not match last instance ({1})".format(len(self.insts[-1].mod.pins),
|
||||
len(args)), 1)
|
||||
self.conns.append(args)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
from tech import drc
|
||||
import debug
|
||||
from design import design
|
||||
from contact import contact
|
||||
from itertools import tee
|
||||
from vector import vector
|
||||
from vector3d import vector3d
|
||||
from sram_factory import factory
|
||||
|
||||
class route(design):
|
||||
"""
|
||||
|
|
@ -45,7 +45,9 @@ class route(design):
|
|||
self.horiz_layer_width = drc("minwidth_{0}".format(self.horiz_layer_name))
|
||||
|
||||
# offset this by 1/2 the via size
|
||||
self.c=contact(self.layer_stack, (self.num_vias, self.num_vias))
|
||||
self.c=factory.create(module_type="contact",
|
||||
layer_stack=self.layer_stack,
|
||||
dimensions=(self.num_vias, self.num_vias))
|
||||
|
||||
|
||||
def create_wires(self):
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
from tech import drc
|
||||
import debug
|
||||
from contact import contact
|
||||
from path import path
|
||||
from sram_factory import factory
|
||||
|
||||
class wire(path):
|
||||
"""
|
||||
|
|
@ -37,15 +37,18 @@ class wire(path):
|
|||
|
||||
self.horiz_layer_name = horiz_layer
|
||||
self.horiz_layer_width = drc("minwidth_{0}".format(horiz_layer))
|
||||
via_connect = contact(self.layer_stack,
|
||||
(1, 1))
|
||||
via_connect = factory.create(module_type="contact",
|
||||
layer_stack=self.layer_stack,
|
||||
dimensions=(1, 1))
|
||||
self.node_to_node = [drc("minwidth_" + str(self.horiz_layer_name)) + via_connect.width,
|
||||
drc("minwidth_" + str(self.horiz_layer_name)) + via_connect.height]
|
||||
|
||||
# create a 1x1 contact
|
||||
def create_vias(self):
|
||||
""" Add a via and corner square at every corner of the path."""
|
||||
self.c=contact(self.layer_stack, (1, 1))
|
||||
self.c=factory.create(module_type="contact",
|
||||
layer_stack=self.layer_stack,
|
||||
dimensions=(1, 1))
|
||||
c_width = self.c.width
|
||||
c_height = self.c.height
|
||||
|
||||
|
|
|
|||
|
|
@ -15,14 +15,15 @@ class bitcell(design.design):
|
|||
(width,height) = utils.get_libcell_size("cell_6t", GDS["unit"], layer["boundary"])
|
||||
pin_map = utils.get_libcell_pins(pin_names, "cell_6t", GDS["unit"])
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, name=""):
|
||||
# Ignore the name argument
|
||||
design.design.__init__(self, "cell_6t")
|
||||
debug.info(2, "Create bitcell")
|
||||
|
||||
self.width = bitcell.width
|
||||
self.height = bitcell.height
|
||||
self.pin_map = bitcell.pin_map
|
||||
|
||||
|
||||
def analytical_delay(self, slew, load=0, swing = 0.5):
|
||||
# delay of bit cell is not like a driver(from WL)
|
||||
# so the slew used should be 0
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@ class bitcell_1rw_1r(design.design):
|
|||
(width,height) = utils.get_libcell_size("cell_1rw_1r", GDS["unit"], layer["boundary"])
|
||||
pin_map = utils.get_libcell_pins(pin_names, "cell_1rw_1r", GDS["unit"])
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, name=""):
|
||||
# Ignore the name argument
|
||||
design.design.__init__(self, "cell_1rw_1r")
|
||||
debug.info(2, "Create bitcell with 1RW and 1R Port")
|
||||
|
||||
|
|
@ -102,4 +103,4 @@ class bitcell_1rw_1r(design.design):
|
|||
#Calculated in the tech file by summing the widths of all the related gates and dividing by the minimum width.
|
||||
#FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed.
|
||||
access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"]
|
||||
return 2*access_tx_cin
|
||||
return 2*access_tx_cin
|
||||
|
|
|
|||
|
|
@ -12,8 +12,7 @@ class pbitcell(design.design):
|
|||
with a variable number of read/write, write, and read ports
|
||||
"""
|
||||
|
||||
def __init__(self, replica_bitcell=False):
|
||||
|
||||
def __init__(self, name, replica_bitcell=False):
|
||||
self.num_rw_ports = OPTS.num_rw_ports
|
||||
self.num_w_ports = OPTS.num_w_ports
|
||||
self.num_r_ports = OPTS.num_r_ports
|
||||
|
|
@ -21,11 +20,6 @@ class pbitcell(design.design):
|
|||
|
||||
self.replica_bitcell = replica_bitcell
|
||||
|
||||
if self.replica_bitcell:
|
||||
name = "replica_pbitcell_{0}RW_{1}W_{2}R".format(self.num_rw_ports, self.num_w_ports, self.num_r_ports)
|
||||
else:
|
||||
name = "pbitcell_{0}RW_{1}W_{2}R".format(self.num_rw_ports, self.num_w_ports, self.num_r_ports)
|
||||
|
||||
design.design.__init__(self, name)
|
||||
debug.info(2, "create a multi-port bitcell with {0} rw ports, {1} w ports and {2} r ports".format(self.num_rw_ports,
|
||||
self.num_w_ports,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@ class replica_bitcell(design.design):
|
|||
(width,height) = utils.get_libcell_size("replica_cell_6t", GDS["unit"], layer["boundary"])
|
||||
pin_map = utils.get_libcell_pins(pin_names, "replica_cell_6t", GDS["unit"])
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, name=""):
|
||||
# Ignore the name argument
|
||||
design.design.__init__(self, "replica_cell_6t")
|
||||
debug.info(2, "Create replica bitcell object")
|
||||
|
||||
|
|
@ -27,4 +28,4 @@ class replica_bitcell(design.design):
|
|||
#This is a handmade cell so the value must be entered in the tech.py file or estimated.
|
||||
#Calculated in the tech file by summing the widths of all the related gates and dividing by the minimum width.
|
||||
access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"]
|
||||
return 2*access_tx_cin
|
||||
return 2*access_tx_cin
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@ class replica_bitcell_1rw_1r(design.design):
|
|||
(width,height) = utils.get_libcell_size("replica_cell_1rw_1r", GDS["unit"], layer["boundary"])
|
||||
pin_map = utils.get_libcell_pins(pin_names, "replica_cell_1rw_1r", GDS["unit"])
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, name=""):
|
||||
# Ignore the name argument
|
||||
design.design.__init__(self, "replica_cell_1rw_1r")
|
||||
debug.info(2, "Create replica bitcell 1rw+1r object")
|
||||
|
||||
|
|
@ -28,4 +29,4 @@ class replica_bitcell_1rw_1r(design.design):
|
|||
#Calculated in the tech file by summing the widths of all the related gates and dividing by the minimum width.
|
||||
#FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed.
|
||||
access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"]
|
||||
return 2*access_tx_cin
|
||||
return 2*access_tx_cin
|
||||
|
|
|
|||
|
|
@ -3,21 +3,20 @@ import design
|
|||
from tech import drc, spice,parameter
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
from pbitcell import pbitcell
|
||||
from sram_factory import factory
|
||||
|
||||
class replica_pbitcell(design.design):
|
||||
"""
|
||||
Creates a replica bitcell using pbitcell
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
|
||||
def __init__(self, name):
|
||||
self.num_rw_ports = OPTS.num_rw_ports
|
||||
self.num_w_ports = OPTS.num_w_ports
|
||||
self.num_r_ports = OPTS.num_r_ports
|
||||
self.total_ports = self.num_rw_ports + self.num_w_ports + self.num_r_ports
|
||||
|
||||
design.design.__init__(self, "replica_pbitcell")
|
||||
design.design.__init__(self, name)
|
||||
debug.info(1, "create a replica bitcell using pbitcell with {0} rw ports, {1} w ports and {2} r ports".format(self.num_rw_ports,
|
||||
self.num_w_ports,
|
||||
self.num_r_ports))
|
||||
|
|
@ -47,7 +46,7 @@ class replica_pbitcell(design.design):
|
|||
self.add_pin("gnd")
|
||||
|
||||
def add_modules(self):
|
||||
self.prbc = pbitcell(replica_bitcell=True)
|
||||
self.prbc = factory.create(module_type="pbitcell",replica_bitcell=True)
|
||||
self.add_mod(self.prbc)
|
||||
|
||||
self.height = self.prbc.height
|
||||
|
|
@ -83,4 +82,4 @@ class replica_pbitcell(design.design):
|
|||
def get_wl_cin(self):
|
||||
"""Return the relative capacitance of the access transistor gates"""
|
||||
#This module is made using a pbitcell. Get the cin from that module
|
||||
return self.prbc.get_wl_cin()
|
||||
return self.prbc.get_wl_cin()
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
from .gdsPrimitives import *
|
||||
from datetime import *
|
||||
#from mpmath import matrix
|
||||
from numpy import matrix
|
||||
#from numpy import matrix
|
||||
import numpy as np
|
||||
#import gdsPrimitives
|
||||
import debug
|
||||
|
||||
|
|
@ -170,21 +171,20 @@ class VlsiLayout:
|
|||
else:
|
||||
# MRG: Added negative to make CCW rotate 8/29/18
|
||||
angle = math.radians(float(rotateAngle))
|
||||
mRotate = matrix([[math.cos(angle),-math.sin(angle),0.0],
|
||||
mRotate = np.array([[math.cos(angle),-math.sin(angle),0.0],
|
||||
[math.sin(angle),math.cos(angle),0.0],
|
||||
[0.0,0.0,1.0]])
|
||||
#set up the translation matrix
|
||||
translateX = float(coordinates[0])
|
||||
translateY = float(coordinates[1])
|
||||
mTranslate = matrix([[1.0,0.0,translateX],[0.0,1.0,translateY],[0.0,0.0,1.0]])
|
||||
mTranslate = np.array([[1.0,0.0,translateX],[0.0,1.0,translateY],[0.0,0.0,1.0]])
|
||||
#set up the scale matrix (handles mirror X)
|
||||
scaleX = 1.0
|
||||
if(transFlags[0]):
|
||||
scaleY = -1.0
|
||||
else:
|
||||
scaleY = 1.0
|
||||
mScale = matrix([[scaleX,0.0,0.0],[0.0,scaleY,0.0],[0.0,0.0,1.0]])
|
||||
|
||||
mScale = np.array([[scaleX,0.0,0.0],[0.0,scaleY,0.0],[0.0,0.0,1.0]])
|
||||
#we need to keep track of all transforms in the hierarchy
|
||||
#when we add an element to the xy tree, we apply all transforms from the bottom up
|
||||
transformPath.append((mRotate,mScale,mTranslate))
|
||||
|
|
@ -219,27 +219,26 @@ class VlsiLayout:
|
|||
|
||||
def populateCoordinateMap(self):
|
||||
def addToXyTree(startingStructureName = None,transformPath = None):
|
||||
#print("populateCoordinateMap")
|
||||
uVector = matrix([1.0,0.0,0.0]).transpose() #start with normal basis vectors
|
||||
vVector = matrix([0.0,1.0,0.0]).transpose()
|
||||
origin = matrix([0.0,0.0,1.0]).transpose() #and an origin (Z component is 1.0 to indicate position instead of vector)
|
||||
uVector = np.array([[1.0],[0.0],[0.0]]) #start with normal basis vectors
|
||||
vVector = np.array([[0.0],[1.0],[0.0]])
|
||||
origin = np.array([[0.0],[0.0],[1.0]]) #and an origin (Z component is 1.0 to indicate position instead of vector)
|
||||
#make a copy of all the transforms and reverse it
|
||||
reverseTransformPath = transformPath[:]
|
||||
if len(reverseTransformPath) > 1:
|
||||
reverseTransformPath.reverse()
|
||||
reverseTransformPath.reverse()
|
||||
#now go through each transform and apply them to our basis and origin in succession
|
||||
for transform in reverseTransformPath:
|
||||
origin = transform[0] * origin #rotate
|
||||
uVector = transform[0] * uVector #rotate
|
||||
vVector = transform[0] * vVector #rotate
|
||||
origin = transform[1] * origin #scale
|
||||
uVector = transform[1] * uVector #scale
|
||||
vVector = transform[1] * vVector #scale
|
||||
origin = transform[2] * origin #translate
|
||||
origin = np.dot(transform[0], origin) #rotate
|
||||
uVector = np.dot(transform[0], uVector) #rotate
|
||||
vVector = np.dot(transform[0], vVector) #rotate
|
||||
origin = np.dot(transform[1], origin) #scale
|
||||
uVector = np.dot(transform[1], uVector) #scale
|
||||
vVector = np.dot(transform[1], vVector) #scale
|
||||
origin = np.dot(transform[2], origin) #translate
|
||||
#we don't need to do a translation on the basis vectors
|
||||
#uVector = transform[2] * uVector #translate
|
||||
#vVector = transform[2] * vVector #translate
|
||||
#populate the xyTree with each structureName and coordinate space
|
||||
#populate the xyTree with each structureName and coordinate space
|
||||
self.xyTree.append((startingStructureName,origin,uVector,vVector))
|
||||
self.traverseTheHierarchy(delegateFunction = addToXyTree)
|
||||
|
||||
|
|
@ -522,8 +521,7 @@ class VlsiLayout:
|
|||
return True
|
||||
|
||||
|
||||
def fillAreaDensity(self, layerToFill = 0, offsetInMicrons = (0,0), coverageWidth = 100.0, coverageHeight = 100.0,
|
||||
minSpacing = 0.22, blockSize = 1.0):
|
||||
def fillAreaDensity(self, layerToFill = 0, offsetInMicrons = (0,0), coverageWidth = 100.0, coverageHeight = 100.0, minSpacing = 0.22, blockSize = 1.0):
|
||||
effectiveBlock = blockSize+minSpacing
|
||||
widthInBlocks = int(coverageWidth/effectiveBlock)
|
||||
heightInBlocks = int(coverageHeight/effectiveBlock)
|
||||
|
|
@ -810,8 +808,8 @@ class VlsiLayout:
|
|||
# This is fixed to be:
|
||||
# |u[0] v[0]| |x| |x'|
|
||||
# |u[1] v[1]|x|y|=|y'|
|
||||
x=coordinate[0]*uVector[0].item()+coordinate[1]*vVector[0].item()
|
||||
y=coordinate[0]*uVector[1].item()+coordinate[1]*vVector[1].item()
|
||||
x=coordinate[0]*uVector[0][0]+coordinate[1]*vVector[0][0]
|
||||
y=coordinate[0]*uVector[1][0]+coordinate[1]*vVector[1][0]
|
||||
transformCoordinate=[x,y]
|
||||
|
||||
return transformCoordinate
|
||||
|
|
@ -836,5 +834,3 @@ def boundaryArea(A):
|
|||
area_A=(A[2]-A[0])*(A[3]-A[1])
|
||||
return area_A
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -130,6 +130,9 @@ def init_openram(config_file, is_unit_test=True):
|
|||
|
||||
init_paths()
|
||||
|
||||
from sram_factory import factory
|
||||
factory.reset()
|
||||
|
||||
# Reset the static duplicate name checker for unit tests.
|
||||
import hierarchy_design
|
||||
hierarchy_design.hierarchy_design.name_map=[]
|
||||
|
|
|
|||
|
|
@ -6,9 +6,7 @@ import math
|
|||
from math import log,sqrt,ceil
|
||||
import contact
|
||||
import pgates
|
||||
from pinv import pinv
|
||||
from pnand2 import pnand2
|
||||
from pnor2 import pnor2
|
||||
from sram_factory import factory
|
||||
from vector import vector
|
||||
|
||||
from globals import OPTS
|
||||
|
|
@ -396,25 +394,14 @@ class bank(design.design):
|
|||
def add_modules(self):
|
||||
""" Add all the modules using the class loader """
|
||||
|
||||
mod_list = ["bitcell", "decoder", "wordline_driver",
|
||||
"bitcell_array", "sense_amp_array", "precharge_array",
|
||||
"column_mux_array", "write_driver_array",
|
||||
"dff", "bank_select"]
|
||||
from importlib import reload
|
||||
for mod_name in mod_list:
|
||||
config_mod_name = getattr(OPTS, mod_name)
|
||||
class_file = reload(__import__(config_mod_name))
|
||||
mod_class = getattr(class_file , config_mod_name)
|
||||
setattr (self, "mod_"+mod_name, mod_class)
|
||||
|
||||
|
||||
|
||||
self.bitcell_array = self.mod_bitcell_array(cols=self.num_cols,
|
||||
rows=self.num_rows)
|
||||
self.bitcell_array = factory.create(module_type="bitcell_array",
|
||||
cols=self.num_cols,
|
||||
rows=self.num_rows)
|
||||
self.add_mod(self.bitcell_array)
|
||||
|
||||
# create arrays of bitline and bitline_bar names for read, write, or all ports
|
||||
self.bitcell = self.mod_bitcell()
|
||||
self.bitcell = factory.create(module_type="bitcell")
|
||||
self.bl_names = self.bitcell.list_all_bl_names()
|
||||
self.br_names = self.bitcell.list_all_br_names()
|
||||
self.wl_names = self.bitcell.list_all_wl_names()
|
||||
|
|
@ -423,7 +410,11 @@ class bank(design.design):
|
|||
self.precharge_array = []
|
||||
for port in self.all_ports:
|
||||
if port in self.read_ports:
|
||||
self.precharge_array.append(self.mod_precharge_array(columns=self.num_cols, bitcell_bl=self.bl_names[port], bitcell_br=self.br_names[port]))
|
||||
temp_pre = factory.create(module_type="precharge_array",
|
||||
columns=self.num_cols,
|
||||
bitcell_bl=self.bl_names[port],
|
||||
bitcell_br=self.br_names[port])
|
||||
self.precharge_array.append(temp_pre)
|
||||
self.add_mod(self.precharge_array[port])
|
||||
else:
|
||||
self.precharge_array.append(None)
|
||||
|
|
@ -431,32 +422,38 @@ class bank(design.design):
|
|||
if self.col_addr_size > 0:
|
||||
self.column_mux_array = []
|
||||
for port in self.all_ports:
|
||||
self.column_mux_array.append(self.mod_column_mux_array(columns=self.num_cols,
|
||||
word_size=self.word_size,
|
||||
bitcell_bl=self.bl_names[port],
|
||||
bitcell_br=self.br_names[port]))
|
||||
temp_col = factory.create(module_type="column_mux_array",
|
||||
columns=self.num_cols,
|
||||
word_size=self.word_size,
|
||||
bitcell_bl=self.bl_names[port],
|
||||
bitcell_br=self.br_names[port])
|
||||
self.column_mux_array.append(temp_col)
|
||||
self.add_mod(self.column_mux_array[port])
|
||||
|
||||
|
||||
self.sense_amp_array = self.mod_sense_amp_array(word_size=self.word_size,
|
||||
words_per_row=self.words_per_row)
|
||||
self.sense_amp_array = factory.create(module_type="sense_amp_array",
|
||||
word_size=self.word_size,
|
||||
words_per_row=self.words_per_row)
|
||||
self.add_mod(self.sense_amp_array)
|
||||
|
||||
self.write_driver_array = self.mod_write_driver_array(columns=self.num_cols,
|
||||
word_size=self.word_size)
|
||||
self.write_driver_array = factory.create(module_type="write_driver_array",
|
||||
columns=self.num_cols,
|
||||
word_size=self.word_size)
|
||||
self.add_mod(self.write_driver_array)
|
||||
|
||||
self.row_decoder = self.mod_decoder(rows=self.num_rows)
|
||||
self.row_decoder = factory.create(module_type="decoder",
|
||||
rows=self.num_rows)
|
||||
self.add_mod(self.row_decoder)
|
||||
|
||||
self.wordline_driver = self.mod_wordline_driver(rows=self.num_rows)
|
||||
self.wordline_driver = factory.create(module_type="wordline_driver",
|
||||
rows=self.num_rows)
|
||||
self.add_mod(self.wordline_driver)
|
||||
|
||||
self.inv = pinv()
|
||||
self.inv = factory.create(module_type="pinv")
|
||||
self.add_mod(self.inv)
|
||||
|
||||
if(self.num_banks > 1):
|
||||
self.bank_select = self.mod_bank_select()
|
||||
self.bank_select = factory.create(module_type="bank_select")
|
||||
self.add_mod(self.bank_select)
|
||||
|
||||
|
||||
|
|
@ -693,18 +690,17 @@ class bank(design.design):
|
|||
"""
|
||||
Create a 2:4 or 3:8 column address decoder.
|
||||
"""
|
||||
|
||||
dff = factory.create(module_type="dff")
|
||||
|
||||
if self.col_addr_size == 0:
|
||||
return
|
||||
elif self.col_addr_size == 1:
|
||||
from pinvbuf import pinvbuf
|
||||
self.column_decoder = pinvbuf(height=self.mod_dff.height)
|
||||
self.column_decoder = factory.create(module_type="pinvbuf", height=dff.height)
|
||||
elif self.col_addr_size == 2:
|
||||
from hierarchical_predecode2x4 import hierarchical_predecode2x4 as pre2x4
|
||||
self.column_decoder = pre2x4(height=self.mod_dff.height)
|
||||
self.column_decoder = factory.create(module_type="hierarchical_predecode2x4", height=dff.height)
|
||||
elif self.col_addr_size == 3:
|
||||
from hierarchical_predecode3x8 import hierarchical_predecode3x8 as pre3x8
|
||||
self.column_decoder = pre3x8(height=self.mod_dff.height)
|
||||
self.column_decoder = factory.create(module_type="hierarchical_predecode3x8", height=dff.height)
|
||||
else:
|
||||
# No error checking before?
|
||||
debug.error("Invalid column decoder?",-1)
|
||||
|
|
@ -1273,4 +1269,4 @@ class bank(design.design):
|
|||
"""Get the relative capacitance of all the sense amp enable connections in the bank"""
|
||||
#Current bank only uses sen as an enable for the sense amps.
|
||||
total_sen_cin = self.sense_amp_array.get_en_cin()
|
||||
return total_sen_cin
|
||||
return total_sen_cin
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ from pinv import pinv
|
|||
from pnand2 import pnand2
|
||||
from pnor2 import pnor2
|
||||
from vector import vector
|
||||
from sram_factory import factory
|
||||
from globals import OPTS
|
||||
|
||||
class bank_select(design.design):
|
||||
|
|
@ -62,28 +63,25 @@ class bank_select(design.design):
|
|||
|
||||
def add_modules(self):
|
||||
""" Create modules for later instantiation """
|
||||
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")
|
||||
|
||||
height = self.bitcell.height + drc("poly_to_active")
|
||||
|
||||
# 1x Inverter
|
||||
self.inv_sel = pinv(height=height)
|
||||
self.inv_sel = factory.create(module_type="pinv", height=height)
|
||||
self.add_mod(self.inv_sel)
|
||||
|
||||
# 4x Inverter
|
||||
self.inv = self.inv4x = pinv(4)
|
||||
self.inv4x = factory.create(module_type="pinv", height=height, size=4)
|
||||
self.add_mod(self.inv4x)
|
||||
|
||||
self.nor2 = pnor2(height=height)
|
||||
self.nor2 = factory.create(module_type="pnor2", height=height)
|
||||
self.add_mod(self.nor2)
|
||||
|
||||
self.inv4x_nor = pinv(size=4, height=height)
|
||||
self.inv4x_nor = factory.create(module_type="pinv", height=height, size=4)
|
||||
self.add_mod(self.inv4x_nor)
|
||||
|
||||
self.nand2 = pnand2()
|
||||
self.nand2 = factory.create(module_type="pnand2")
|
||||
self.add_mod(self.nand2)
|
||||
|
||||
def calculate_module_offsets(self):
|
||||
|
|
@ -94,7 +92,7 @@ class bank_select(design.design):
|
|||
self.xoffset_bank_sel_inv = 0
|
||||
self.xoffset_inputs = 0
|
||||
|
||||
self.yoffset_maxpoint = self.num_control_lines * self.inv.height
|
||||
self.yoffset_maxpoint = self.num_control_lines * self.inv4x.height
|
||||
# Include the M1 pitches for the supply rails and spacing
|
||||
self.height = self.yoffset_maxpoint + 2*self.m1_pitch
|
||||
self.width = self.xoffset_inv + self.inv4x.width
|
||||
|
|
@ -170,10 +168,10 @@ class bank_select(design.design):
|
|||
if i == 0:
|
||||
y_offset = 0
|
||||
else:
|
||||
y_offset = self.inv4x_nor.height + self.inv.height * (i-1)
|
||||
y_offset = self.inv4x_nor.height + self.inv4x.height * (i-1)
|
||||
|
||||
if i%2:
|
||||
y_offset += self.inv.height
|
||||
y_offset += self.inv4x.height
|
||||
mirror = "MX"
|
||||
else:
|
||||
mirror = ""
|
||||
|
|
@ -223,7 +221,7 @@ class bank_select(design.design):
|
|||
self.add_label_pin(text="bank_sel_bar",
|
||||
layer="metal2",
|
||||
offset=vector(xoffset_bank_sel_bar, 0),
|
||||
height=self.inv.height)
|
||||
height=self.inv4x.height)
|
||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
||||
offset=bank_sel_bar_pin.rc())
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@ import design
|
|||
from tech import drc, spice
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
|
||||
unique_id = 1
|
||||
from sram_factory import factory
|
||||
|
||||
class bitcell_array(design.design):
|
||||
"""
|
||||
|
|
@ -12,13 +11,7 @@ class bitcell_array(design.design):
|
|||
and word line is connected by abutment.
|
||||
Connects the word lines and bit lines.
|
||||
"""
|
||||
unique_id = 1
|
||||
|
||||
def __init__(self, cols, rows, name=""):
|
||||
|
||||
if name == "":
|
||||
name = "bitcell_array_{0}x{1}_{2}".format(rows,cols,bitcell_array.unique_id)
|
||||
bitcell_array.unique_id += 1
|
||||
def __init__(self, cols, rows, name):
|
||||
design.design.__init__(self, name)
|
||||
debug.info(1, "Creating {0} {1} x {2}".format(self.name, rows, cols))
|
||||
|
||||
|
|
@ -83,11 +76,7 @@ class bitcell_array(design.design):
|
|||
|
||||
def add_modules(self):
|
||||
""" Add the modules used in this design """
|
||||
|
||||
from importlib import reload
|
||||
c = reload(__import__(OPTS.bitcell))
|
||||
self.mod_bitcell = getattr(c, OPTS.bitcell)
|
||||
self.cell = self.mod_bitcell()
|
||||
self.cell = factory.create(module_type="bitcell")
|
||||
self.add_mod(self.cell)
|
||||
|
||||
def create_instances(self):
|
||||
|
|
@ -210,4 +199,4 @@ class bitcell_array(design.design):
|
|||
#A single wordline is connected to all the bitcells in a single row meaning the capacitance depends on the # of columns
|
||||
bitcell_wl_cin = self.cell.get_wl_cin()
|
||||
total_cin = bitcell_wl_cin * self.column_size
|
||||
return total_cin
|
||||
return total_cin
|
||||
|
|
|
|||
|
|
@ -3,13 +3,7 @@ import design
|
|||
from tech import drc, parameter
|
||||
import debug
|
||||
import contact
|
||||
from pinv import pinv
|
||||
from pbuf import pbuf
|
||||
from pand2 import pand2
|
||||
from pnand2 import pnand2
|
||||
from pinvbuf import pinvbuf
|
||||
from dff_buf import dff_buf
|
||||
from dff_buf_array import dff_buf_array
|
||||
from sram_factory import factory
|
||||
import math
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
|
|
@ -73,46 +67,56 @@ class control_logic(design.design):
|
|||
def add_modules(self):
|
||||
""" Add all the required modules """
|
||||
|
||||
dff = dff_buf()
|
||||
dff = factory.create(module_type="dff_buf")
|
||||
dff_height = dff.height
|
||||
|
||||
self.ctrl_dff_array = dff_buf_array(rows=self.num_control_signals,columns=1)
|
||||
self.ctrl_dff_array = factory.create(module_type="dff_buf_array",
|
||||
rows=self.num_control_signals,
|
||||
columns=1)
|
||||
|
||||
self.add_mod(self.ctrl_dff_array)
|
||||
|
||||
self.and2 = pand2(size=4,height=dff_height)
|
||||
self.and2 = factory.create(module_type="pand2",
|
||||
size=4,
|
||||
height=dff_height)
|
||||
self.add_mod(self.and2)
|
||||
|
||||
# Special gates: inverters for buffering
|
||||
# Size the clock for the number of rows (fanout)
|
||||
clock_driver_size = max(1,int(self.num_rows/4))
|
||||
self.clkbuf = pbuf(size=clock_driver_size, height=dff_height)
|
||||
self.clkbuf = factory.create(module_type="pbuf",
|
||||
size=clock_driver_size,
|
||||
height=dff_height)
|
||||
|
||||
self.add_mod(self.clkbuf)
|
||||
|
||||
self.buf16 = pbuf(size=16, height=dff_height)
|
||||
self.buf16 = factory.create(module_type="pbuf",
|
||||
size=16,
|
||||
height=dff_height)
|
||||
self.add_mod(self.buf16)
|
||||
|
||||
self.buf8 = pbuf(size=8, height=dff_height)
|
||||
self.buf8 = factory.create(module_type="pbuf",
|
||||
size=8,
|
||||
height=dff_height)
|
||||
self.add_mod(self.buf8)
|
||||
|
||||
self.inv = self.inv1 = pinv(size=1, height=dff_height)
|
||||
self.inv = self.inv1 = factory.create(module_type="pinv",
|
||||
size=1,
|
||||
height=dff_height)
|
||||
self.add_mod(self.inv1)
|
||||
|
||||
self.inv8 = pinv(size=8, height=dff_height)
|
||||
self.inv8 = factory.create(module_type="pinv",
|
||||
size=8,
|
||||
height=dff_height)
|
||||
self.add_mod(self.inv8)
|
||||
|
||||
# self.inv2 = pinv(size=4, height=dff_height)
|
||||
# self.add_mod(self.inv2)
|
||||
#self.inv16 = pinv(size=16, height=dff_height)
|
||||
#self.add_mod(self.inv16)
|
||||
|
||||
if (self.port_type == "rw") or (self.port_type == "r"):
|
||||
from importlib import reload
|
||||
c = reload(__import__(OPTS.replica_bitline))
|
||||
replica_bitline = getattr(c, OPTS.replica_bitline)
|
||||
|
||||
delay_stages_heuristic, delay_fanout_heuristic = self.get_heuristic_delay_chain_size()
|
||||
bitcell_loads = int(math.ceil(self.num_rows / 2.0))
|
||||
self.replica_bitline = replica_bitline([delay_fanout_heuristic]*delay_stages_heuristic, bitcell_loads, name="replica_bitline_"+self.port_type)
|
||||
self.replica_bitline = factory.create(module_type="replica_bitline",
|
||||
delay_fanout_list=[delay_fanout_heuristic]*delay_stages_heuristic,
|
||||
bitcell_loads=bitcell_loads)
|
||||
|
||||
|
||||
if self.sram != None:
|
||||
self.set_sen_wl_delays()
|
||||
|
|
@ -124,8 +128,10 @@ class control_logic(design.design):
|
|||
|
||||
#This resizes based on total delay.
|
||||
delay_stages, delay_fanout = self.get_dynamic_delay_chain_size(delay_stages_heuristic, delay_fanout_heuristic)
|
||||
self.replica_bitline = replica_bitline([delay_fanout]*delay_stages, bitcell_loads, name="replica_bitline_resized_"+self.port_type)
|
||||
|
||||
self.replica_bitline = factory.create(module_type="replica_bitline",
|
||||
delay_fanout_list=[delay_fanout]*delay_stages,
|
||||
bitcell_loads=bitcell_loads)
|
||||
|
||||
self.sen_delay_rise,self.sen_delay_fall = self.get_delays_to_sen() #get the new timing
|
||||
|
||||
self.add_mod(self.replica_bitline)
|
||||
|
|
@ -853,4 +859,4 @@ class control_logic(design.design):
|
|||
last_stage_rise = stage_effort_list[-1].is_rise
|
||||
|
||||
return stage_effort_list
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import debug
|
||||
import design
|
||||
from tech import drc
|
||||
from pinv import pinv
|
||||
from contact import contact
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
from sram_factory import factory
|
||||
|
||||
class delay_chain(design.design):
|
||||
"""
|
||||
|
|
@ -13,12 +13,8 @@ class delay_chain(design.design):
|
|||
Usually, this will be constant, but it could have varied fanout.
|
||||
"""
|
||||
|
||||
unique_id = 1
|
||||
|
||||
def __init__(self, fanout_list, name="delay_chain"):
|
||||
def __init__(self, name, fanout_list):
|
||||
"""init function"""
|
||||
name = name+"_{}".format(delay_chain.unique_id)
|
||||
delay_chain.unique_id += 1
|
||||
design.design.__init__(self, name)
|
||||
|
||||
# Two fanouts are needed so that we can route the vdd/gnd connections
|
||||
|
|
@ -57,7 +53,7 @@ class delay_chain(design.design):
|
|||
self.add_pin("gnd")
|
||||
|
||||
def add_modules(self):
|
||||
self.inv = pinv(route_output=False)
|
||||
self.inv = factory.create(module_type="pinv", route_output=False)
|
||||
self.add_mod(self.inv)
|
||||
|
||||
def create_inverters(self):
|
||||
|
|
@ -238,4 +234,4 @@ class delay_chain(design.design):
|
|||
stage_effort_list.append(stage)
|
||||
last_stage_is_rise = stage.is_rise
|
||||
|
||||
return stage_effort_list
|
||||
return stage_effort_list
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import design
|
|||
from tech import drc
|
||||
from math import log
|
||||
from vector import vector
|
||||
from sram_factory import factory
|
||||
from globals import OPTS
|
||||
|
||||
class dff_array(design.design):
|
||||
|
|
@ -38,10 +39,7 @@ class dff_array(design.design):
|
|||
self.DRC_LVS()
|
||||
|
||||
def add_modules(self):
|
||||
from importlib import reload
|
||||
c = reload(__import__(OPTS.dff))
|
||||
self.mod_dff = getattr(c, OPTS.dff)
|
||||
self.dff = self.mod_dff("dff")
|
||||
self.dff = factory.create(module_type="dff")
|
||||
self.add_mod(self.dff)
|
||||
|
||||
def add_pins(self):
|
||||
|
|
@ -61,7 +59,7 @@ class dff_array(design.design):
|
|||
for col in range(self.columns):
|
||||
name = "dff_r{0}_c{1}".format(row,col)
|
||||
self.dff_insts[row,col]=self.add_inst(name=name,
|
||||
mod=self.dff)
|
||||
mod=self.dff)
|
||||
self.connect_inst([self.get_din_name(row,col),
|
||||
self.get_dout_name(row,col),
|
||||
"clk",
|
||||
|
|
@ -162,4 +160,4 @@ class dff_array(design.design):
|
|||
"""Return the total capacitance (in relative units) that the clock is loaded by in the dff array"""
|
||||
dff_clk_cin = self.dff.get_clk_cin()
|
||||
total_cin = dff_clk_cin * self.rows * self.columns
|
||||
return total_cin
|
||||
return total_cin
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from tech import drc,parameter
|
|||
from math import log
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
from pinv import pinv
|
||||
from sram_factory import factory
|
||||
|
||||
class dff_buf(design.design):
|
||||
"""
|
||||
|
|
@ -50,16 +50,17 @@ class dff_buf(design.design):
|
|||
self.DRC_LVS()
|
||||
|
||||
def add_modules(self):
|
||||
from importlib import reload
|
||||
c = reload(__import__(OPTS.dff))
|
||||
self.mod_dff = getattr(c, OPTS.dff)
|
||||
self.dff = self.mod_dff("dff")
|
||||
self.dff = factory.create(module_type="dff")
|
||||
self.add_mod(self.dff)
|
||||
|
||||
self.inv1 = pinv(size=self.inv1_size,height=self.dff.height)
|
||||
self.inv1 = factory.create(module_type="pinv",
|
||||
size=self.inv1_size,
|
||||
height=self.dff.height)
|
||||
self.add_mod(self.inv1)
|
||||
|
||||
self.inv2 = pinv(size=self.inv2_size,height=self.dff.height)
|
||||
self.inv2 = factory.create(module_type="pinv",
|
||||
size=self.inv2_size,
|
||||
height=self.dff.height)
|
||||
self.add_mod(self.inv2)
|
||||
|
||||
|
||||
|
|
@ -182,4 +183,4 @@ class dff_buf(design.design):
|
|||
#This is a handmade cell so the value must be entered in the tech.py file or estimated.
|
||||
#Calculated in the tech file by summing the widths of all the gates and dividing by the minimum width.
|
||||
#FIXME: Dff changed in a past commit. The parameter need to be updated.
|
||||
return parameter["dff_clk_cin"]
|
||||
return parameter["dff_clk_cin"]
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from tech import drc
|
|||
from math import log
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
import dff_buf
|
||||
from sram_factory import factory
|
||||
|
||||
class dff_buf_array(design.design):
|
||||
"""
|
||||
|
|
@ -54,7 +54,9 @@ class dff_buf_array(design.design):
|
|||
self.add_pin("gnd")
|
||||
|
||||
def add_modules(self):
|
||||
self.dff = dff_buf.dff_buf(self.inv1_size, self.inv2_size)
|
||||
self.dff = factory.create(module_type="dff_buf",
|
||||
inv1_size=self.inv1_size,
|
||||
inv2_size=self.inv2_size)
|
||||
self.add_mod(self.dff)
|
||||
|
||||
def create_dff_array(self):
|
||||
|
|
@ -189,4 +191,4 @@ class dff_buf_array(design.design):
|
|||
"""Return the total capacitance (in relative units) that the clock is loaded by in the dff array"""
|
||||
dff_clk_cin = self.dff.get_clk_cin()
|
||||
total_cin = dff_clk_cin * self.rows * self.columns
|
||||
return total_cin
|
||||
return total_cin
|
||||
|
|
|
|||
|
|
@ -55,13 +55,12 @@ class dff_inv(design.design):
|
|||
self.add_pin("gnd")
|
||||
|
||||
def add_modules(self):
|
||||
from importlib import reload
|
||||
c = reload(__import__(OPTS.dff))
|
||||
self.mod_dff = getattr(c, OPTS.dff)
|
||||
self.dff = self.mod_dff("dff")
|
||||
self.dff = dff_inv.dff_inv(self.inv_size)
|
||||
self.add_mod(self.dff)
|
||||
|
||||
self.inv1 = pinv(size=self.inv_size,height=self.dff.height)
|
||||
self.inv1 = factory.create(module_type="pinv",
|
||||
size=self.inv_size,
|
||||
height=self.dff.height)
|
||||
self.add_mod(self.inv1)
|
||||
|
||||
def create_modules(self):
|
||||
|
|
@ -152,4 +151,4 @@ class dff_inv(design.design):
|
|||
|
||||
def get_clk_cin(self):
|
||||
"""Return the total capacitance (in relative units) that the clock is loaded by in the dff"""
|
||||
return self.dff.get_clk_cin()
|
||||
return self.dff.get_clk_cin()
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ class dff_inv_array(design.design):
|
|||
self.DRC_LVS()
|
||||
|
||||
def add_modules(self):
|
||||
self.dff = dff_inv.dff_inv(self.inv_size)
|
||||
self.dff = factory.create(module_type="dff")
|
||||
self.add_mod(self.dff)
|
||||
|
||||
def add_pins(self):
|
||||
|
|
@ -189,4 +189,4 @@ class dff_inv_array(design.design):
|
|||
"""Return the total capacitance (in relative units) that the clock is loaded by in the dff array"""
|
||||
dff_clk_cin = self.dff.get_clk_cin()
|
||||
total_cin = dff_clk_cin * self.rows * self.columns
|
||||
return total_cin
|
||||
return total_cin
|
||||
|
|
|
|||
|
|
@ -4,12 +4,8 @@ import design
|
|||
from math import log
|
||||
from math import sqrt
|
||||
import math
|
||||
import contact
|
||||
from pnand2 import pnand2
|
||||
from pnand3 import pnand3
|
||||
from pinv import pinv
|
||||
from hierarchical_predecode2x4 import hierarchical_predecode2x4 as pre2x4
|
||||
from hierarchical_predecode3x8 import hierarchical_predecode3x8 as pre3x8
|
||||
import contact
|
||||
from sram_factory import factory
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
|
||||
|
|
@ -17,11 +13,8 @@ class hierarchical_decoder(design.design):
|
|||
"""
|
||||
Dynamically generated hierarchical decoder.
|
||||
"""
|
||||
unique_id = 1
|
||||
|
||||
def __init__(self, rows, height=None):
|
||||
design.design.__init__(self, "hierarchical_decoder_{0}rows_{1}".format(rows,hierarchical_decoder.unique_id))
|
||||
hierarchical_decoder.unique_id += 1
|
||||
def __init__(self, name, rows, height=None):
|
||||
design.design.__init__(self, name)
|
||||
|
||||
self.NAND_FORMAT = "DEC_NAND_{0}"
|
||||
self.INV_FORMAT = "DEC_INV_{0}"
|
||||
|
|
@ -57,21 +50,26 @@ class hierarchical_decoder(design.design):
|
|||
self.DRC_LVS()
|
||||
|
||||
def add_modules(self):
|
||||
self.inv = pinv(height=self.cell_height)
|
||||
self.inv = factory.create(module_type="pinv",
|
||||
height=self.cell_height)
|
||||
self.add_mod(self.inv)
|
||||
self.nand2 = pnand2(height=self.cell_height)
|
||||
self.nand2 = factory.create(module_type="pnand2",
|
||||
height=self.cell_height)
|
||||
self.add_mod(self.nand2)
|
||||
self.nand3 = pnand3(height=self.cell_height)
|
||||
self.nand3 = factory.create(module_type="pnand3",
|
||||
height=self.cell_height)
|
||||
self.add_mod(self.nand3)
|
||||
|
||||
self.add_decoders()
|
||||
|
||||
def add_decoders(self):
|
||||
""" Create the decoders based on the number of pre-decodes """
|
||||
self.pre2_4 = pre2x4(height=self.cell_height)
|
||||
self.pre2_4 = factory.create(module_type="hierarchical_predecode2x4",
|
||||
height=self.cell_height)
|
||||
self.add_mod(self.pre2_4)
|
||||
|
||||
self.pre3_8 = pre3x8(height=self.cell_height)
|
||||
self.pre3_8 = factory.create(module_type="hierarchical_predecode3x8",
|
||||
height=self.cell_height)
|
||||
self.add_mod(self.pre3_8)
|
||||
|
||||
def determine_predecodes(self,num_inputs):
|
||||
|
|
|
|||
|
|
@ -3,24 +3,19 @@ import design
|
|||
import math
|
||||
from tech import drc
|
||||
import contact
|
||||
from pinv import pinv
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
from pnand2 import pnand2
|
||||
from pnand3 import pnand3
|
||||
from sram_factory import factory
|
||||
|
||||
class hierarchical_predecode(design.design):
|
||||
"""
|
||||
Pre 2x4 and 3x8 decoder shared code.
|
||||
"""
|
||||
unique_id = 1
|
||||
|
||||
def __init__(self, input_number, height=None):
|
||||
def __init__(self, name, input_number, height=None):
|
||||
self.number_of_inputs = input_number
|
||||
self.cell_height = height
|
||||
self.number_of_outputs = int(math.pow(2, self.number_of_inputs))
|
||||
design.design.__init__(self, name="pre{0}x{1}_{2}".format(self.number_of_inputs,self.number_of_outputs,hierarchical_predecode.unique_id))
|
||||
hierarchical_predecode.unique_id += 1
|
||||
design.design.__init__(self, name)
|
||||
|
||||
def add_pins(self):
|
||||
for k in range(self.number_of_inputs):
|
||||
|
|
@ -33,7 +28,8 @@ class hierarchical_predecode(design.design):
|
|||
def add_modules(self):
|
||||
""" Add the INV and NAND gate modules """
|
||||
|
||||
self.inv = pinv(height=self.cell_height)
|
||||
self.inv = factory.create(module_type="pinv",
|
||||
height=self.cell_height)
|
||||
self.add_mod(self.inv)
|
||||
|
||||
self.add_nand(self.number_of_inputs)
|
||||
|
|
@ -42,9 +38,11 @@ class hierarchical_predecode(design.design):
|
|||
def add_nand(self,inputs):
|
||||
""" Create the NAND for the predecode input stage """
|
||||
if inputs==2:
|
||||
self.nand = pnand2(height=self.cell_height)
|
||||
self.nand = factory.create(module_type="pnand2",
|
||||
height=self.cell_height)
|
||||
elif inputs==3:
|
||||
self.nand = pnand3(height=self.cell_height)
|
||||
self.nand = factory.create(module_type="pnand3",
|
||||
height=self.cell_height)
|
||||
else:
|
||||
debug.error("Invalid number of predecode inputs: {}".format(inputs),-1)
|
||||
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ class hierarchical_predecode2x4(hierarchical_predecode):
|
|||
"""
|
||||
Pre 2x4 decoder used in hierarchical_decoder.
|
||||
"""
|
||||
def __init__(self, height=None):
|
||||
hierarchical_predecode.__init__(self, 2, height)
|
||||
def __init__(self, name, height=None):
|
||||
hierarchical_predecode.__init__(self, name, 2, height)
|
||||
|
||||
self.create_netlist()
|
||||
if not OPTS.netlist_only:
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ class hierarchical_predecode3x8(hierarchical_predecode):
|
|||
"""
|
||||
Pre 3x8 decoder used in hierarchical_decoder.
|
||||
"""
|
||||
def __init__(self, height=None):
|
||||
hierarchical_predecode.__init__(self, 3, height)
|
||||
def __init__(self, name, height=None):
|
||||
hierarchical_predecode.__init__(self, name, 3, height)
|
||||
|
||||
self.create_netlist()
|
||||
if not OPTS.netlist_only:
|
||||
|
|
|
|||
|
|
@ -5,12 +5,8 @@ import design
|
|||
import math
|
||||
from math import log,sqrt,ceil
|
||||
import contact
|
||||
from pinv import pinv
|
||||
from pnand2 import pnand2
|
||||
from pnor2 import pnor2
|
||||
from vector import vector
|
||||
from pinvbuf import pinvbuf
|
||||
|
||||
from sram_factory import factory
|
||||
from globals import OPTS
|
||||
|
||||
class multibank(design.design):
|
||||
|
|
@ -21,21 +17,8 @@ class multibank(design.design):
|
|||
This module includes the tristate and bank select logic.
|
||||
"""
|
||||
|
||||
def __init__(self, word_size, num_words, words_per_row, num_banks=1, name=""):
|
||||
def __init__(self, name, word_size, num_words, words_per_row, num_banks=1):
|
||||
|
||||
mod_list = ["tri_gate", "bitcell", "decoder", "wordline_driver",
|
||||
"bitcell_array", "sense_amp_array", "precharge_array",
|
||||
"column_mux_array", "write_driver_array", "tri_gate_array",
|
||||
"dff", "bank_select"]
|
||||
from importlib import reload
|
||||
for mod_name in mod_list:
|
||||
config_mod_name = getattr(OPTS, mod_name)
|
||||
class_file = reload(__import__(config_mod_name))
|
||||
mod_class = getattr(class_file , config_mod_name)
|
||||
setattr (self, "mod_"+mod_name, mod_class)
|
||||
|
||||
if name == "":
|
||||
name = "bank_{0}_{1}".format(word_size, num_words)
|
||||
design.design.__init__(self, name)
|
||||
debug.info(2, "create sram of size {0} with {1} words".format(word_size,num_words))
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import design
|
|||
import debug
|
||||
from tech import drc
|
||||
from vector import vector
|
||||
from precharge import precharge
|
||||
from sram_factory import factory
|
||||
from globals import OPTS
|
||||
|
||||
class precharge_array(design.design):
|
||||
|
|
@ -11,11 +11,7 @@ class precharge_array(design.design):
|
|||
of bit line columns, height is the height of the bit-cell array.
|
||||
"""
|
||||
|
||||
unique_id = 1
|
||||
|
||||
def __init__(self, columns, size=1, bitcell_bl="bl", bitcell_br="br"):
|
||||
name = "precharge_array_{}".format(precharge_array.unique_id)
|
||||
precharge_array.unique_id += 1
|
||||
def __init__(self, name, columns, size=1, bitcell_bl="bl", bitcell_br="br"):
|
||||
design.design.__init__(self, name)
|
||||
debug.info(1, "Creating {0}".format(self.name))
|
||||
|
||||
|
|
@ -50,10 +46,12 @@ class precharge_array(design.design):
|
|||
self.DRC_LVS()
|
||||
|
||||
def add_modules(self):
|
||||
self.pc_cell = precharge(name="precharge",
|
||||
size=self.size,
|
||||
bitcell_bl=self.bitcell_bl,
|
||||
bitcell_br=self.bitcell_br)
|
||||
self.pc_cell = factory.create(module_type="precharge",
|
||||
size=self.size,
|
||||
bitcell_bl=self.bitcell_bl,
|
||||
bitcell_br=self.bitcell_br)
|
||||
|
||||
|
||||
self.add_mod(self.pc_cell)
|
||||
|
||||
|
||||
|
|
@ -107,4 +105,4 @@ class precharge_array(design.design):
|
|||
"""Get the relative capacitance of all the clk connections in the precharge array"""
|
||||
#Assume single port
|
||||
precharge_en_cin = self.pc_cell.get_en_cin()
|
||||
return precharge_en_cin*self.columns
|
||||
return precharge_en_cin*self.columns
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
import debug
|
||||
import design
|
||||
from tech import drc
|
||||
from pinv import pinv
|
||||
import contact
|
||||
from bitcell_array import bitcell_array
|
||||
from ptx import ptx
|
||||
from sram_factory import factory
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
|
||||
|
|
@ -15,7 +13,7 @@ class replica_bitline(design.design):
|
|||
line and rows is the height of the replica bit loads.
|
||||
"""
|
||||
|
||||
def __init__(self, delay_fanout_list, bitcell_loads, name="replica_bitline"):
|
||||
def __init__(self, name, delay_fanout_list, bitcell_loads):
|
||||
design.design.__init__(self, name)
|
||||
|
||||
self.bitcell_loads = bitcell_loads
|
||||
|
|
@ -78,29 +76,25 @@ class replica_bitline(design.design):
|
|||
def add_modules(self):
|
||||
""" Add the modules for later usage """
|
||||
|
||||
from importlib import reload
|
||||
#g = reload(__import__(OPTS.delay_chain))
|
||||
#self.mod_delay_chain = getattr(g, OPTS.delay_chain)
|
||||
|
||||
g = reload(__import__(OPTS.replica_bitcell))
|
||||
self.mod_replica_bitcell = getattr(g, OPTS.replica_bitcell)
|
||||
|
||||
self.bitcell = self.replica_bitcell = self.mod_replica_bitcell()
|
||||
self.add_mod(self.bitcell)
|
||||
self.replica_bitcell = factory.create(module_type="replica_bitcell")
|
||||
self.add_mod(self.replica_bitcell)
|
||||
|
||||
# This is the replica bitline load column that is the height of our array
|
||||
self.rbl = bitcell_array(cols=1, rows=self.bitcell_loads)
|
||||
self.rbl = factory.create(module_type="bitcell_array",
|
||||
cols=1,
|
||||
rows=self.bitcell_loads)
|
||||
self.add_mod(self.rbl)
|
||||
|
||||
# FIXME: The FO and depth of this should be tuned
|
||||
from delay_chain import delay_chain
|
||||
self.delay_chain = delay_chain(self.delay_fanout_list)
|
||||
self.delay_chain = factory.create(module_type="delay_chain",
|
||||
fanout_list=self.delay_fanout_list)
|
||||
self.add_mod(self.delay_chain)
|
||||
|
||||
self.inv = pinv()
|
||||
self.inv = factory.create(module_type="pinv")
|
||||
self.add_mod(self.inv)
|
||||
|
||||
self.access_tx = ptx(tx_type="pmos")
|
||||
self.access_tx = factory.create(module_type="ptx",
|
||||
tx_type="pmos")
|
||||
self.add_mod(self.access_tx)
|
||||
|
||||
def create_instances(self):
|
||||
|
|
@ -132,7 +126,6 @@ class replica_bitline(design.design):
|
|||
temp.append("vdd")
|
||||
temp.append("gnd")
|
||||
self.connect_inst(temp)
|
||||
#self.connect_inst(["bl_0", "br_0", "delayed_en", "vdd", "gnd"])
|
||||
|
||||
self.rbl_inst=self.add_inst(name="load",
|
||||
mod=self.rbl)
|
||||
|
|
@ -631,4 +624,4 @@ class replica_bitline(design.design):
|
|||
access_tx_cin = self.access_tx.get_cin()
|
||||
rbc_cin = self.replica_bitcell.get_wl_cin()
|
||||
return access_tx_cin + rbc_cin
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import design
|
||||
from tech import drc
|
||||
from vector import vector
|
||||
from sram_factory import factory
|
||||
import debug
|
||||
from globals import OPTS
|
||||
|
||||
|
|
@ -10,8 +11,8 @@ class sense_amp_array(design.design):
|
|||
Dynamically generated sense amp array for all bitlines.
|
||||
"""
|
||||
|
||||
def __init__(self, word_size, words_per_row):
|
||||
design.design.__init__(self, "sense_amp_array")
|
||||
def __init__(self, name, word_size, words_per_row):
|
||||
design.design.__init__(self, name)
|
||||
debug.info(1, "Creating {0}".format(self.name))
|
||||
|
||||
self.word_size = word_size
|
||||
|
|
@ -51,17 +52,13 @@ class sense_amp_array(design.design):
|
|||
self.add_pin("gnd")
|
||||
|
||||
def add_modules(self):
|
||||
from importlib import reload
|
||||
c = reload(__import__(OPTS.sense_amp))
|
||||
self.mod_sense_amp = getattr(c, OPTS.sense_amp)
|
||||
self.amp = self.mod_sense_amp("sense_amp")
|
||||
self.amp = factory.create(module_type="sense_amp")
|
||||
|
||||
self.add_mod(self.amp)
|
||||
|
||||
# This is just used for measurements,
|
||||
# so don't add the module
|
||||
c = reload(__import__(OPTS.bitcell))
|
||||
self.mod_bitcell = getattr(c, OPTS.bitcell)
|
||||
self.bitcell = self.mod_bitcell()
|
||||
self.bitcell = factory.create(module_type="bitcell")
|
||||
|
||||
def create_sense_amp_array(self):
|
||||
self.local_insts = []
|
||||
|
|
@ -143,4 +140,4 @@ class sense_amp_array(design.design):
|
|||
def get_en_cin(self):
|
||||
"""Get the relative capacitance of all the sense amp enable connections in the array"""
|
||||
sense_amp_en_cin = self.amp.get_en_cin()
|
||||
return sense_amp_en_cin * self.words_per_row
|
||||
return sense_amp_en_cin * self.words_per_row
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
from math import log
|
||||
import design
|
||||
from single_level_column_mux import single_level_column_mux
|
||||
import contact
|
||||
from tech import drc
|
||||
import debug
|
||||
import math
|
||||
from vector import vector
|
||||
from sram_factory import factory
|
||||
from globals import OPTS
|
||||
|
||||
class single_level_column_mux_array(design.design):
|
||||
|
|
@ -14,11 +14,7 @@ class single_level_column_mux_array(design.design):
|
|||
Array of column mux to read the bitlines through the 6T.
|
||||
"""
|
||||
|
||||
unique_id = 1
|
||||
|
||||
def __init__(self, columns, word_size, bitcell_bl="bl", bitcell_br="br"):
|
||||
name="single_level_column_mux_array_{}".format(single_level_column_mux_array.unique_id)
|
||||
single_level_column_mux_array.unique_id += 1
|
||||
def __init__(self, name, columns, word_size, bitcell_bl="bl", bitcell_br="br"):
|
||||
design.design.__init__(self, name)
|
||||
debug.info(1, "Creating {0}".format(self.name))
|
||||
self.columns = columns
|
||||
|
|
@ -61,7 +57,9 @@ class single_level_column_mux_array(design.design):
|
|||
|
||||
|
||||
def add_modules(self):
|
||||
self.mux = single_level_column_mux(bitcell_bl=self.bitcell_bl, bitcell_br=self.bitcell_br)
|
||||
self.mux = factory.create(module_type="single_level_column_mux",
|
||||
bitcell_bl=self.bitcell_bl,
|
||||
bitcell_br=self.bitcell_br)
|
||||
self.add_mod(self.mux)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import debug
|
|||
from tech import drc
|
||||
import design
|
||||
from vector import vector
|
||||
from sram_factory import factory
|
||||
from globals import OPTS
|
||||
|
||||
class tri_gate_array(design.design):
|
||||
|
|
@ -36,10 +37,7 @@ class tri_gate_array(design.design):
|
|||
self.DRC_LVS()
|
||||
|
||||
def add_modules(self):
|
||||
from importlib import reload
|
||||
c = reload(__import__(OPTS.tri_gate))
|
||||
self.mod_tri_gate = getattr(c, OPTS.tri_gate)
|
||||
self.tri = self.mod_tri_gate("tri_gate")
|
||||
self.tri = factory.create(module_type="tri_gate")
|
||||
self.add_mod(self.tri)
|
||||
|
||||
def add_pins(self):
|
||||
|
|
|
|||
|
|
@ -5,9 +5,8 @@ import contact
|
|||
from math import log
|
||||
from math import sqrt
|
||||
import math
|
||||
from pinv import pinv
|
||||
from pnand2 import pnand2
|
||||
from vector import vector
|
||||
from sram_factory import factory
|
||||
from globals import OPTS
|
||||
|
||||
class wordline_driver(design.design):
|
||||
|
|
@ -16,8 +15,8 @@ class wordline_driver(design.design):
|
|||
Generates the wordline-driver to drive the bitcell
|
||||
"""
|
||||
|
||||
def __init__(self, rows):
|
||||
design.design.__init__(self, "wordline_driver")
|
||||
def __init__(self, name, rows):
|
||||
design.design.__init__(self, name)
|
||||
|
||||
self.rows = rows
|
||||
|
||||
|
|
@ -53,13 +52,14 @@ class wordline_driver(design.design):
|
|||
# This is just used for measurements,
|
||||
# so don't add the module
|
||||
|
||||
self.inv = pinv()
|
||||
self.inv = factory.create(module_type="pinv")
|
||||
self.add_mod(self.inv)
|
||||
|
||||
self.inv_no_output = pinv(route_output=False)
|
||||
self.inv_no_output = factory.create(module_type="pinv",
|
||||
route_output=False)
|
||||
self.add_mod(self.inv_no_output)
|
||||
|
||||
self.nand2 = pnand2()
|
||||
self.nand2 = factory.create(module_type="pnand2")
|
||||
self.add_mod(self.nand2)
|
||||
|
||||
|
||||
|
|
@ -237,4 +237,4 @@ class wordline_driver(design.design):
|
|||
"""Get the relative capacitance of all the enable connections in the bank"""
|
||||
#The enable is connected to a nand2 for every row.
|
||||
total_cin = self.nand2.get_cin() * self.rows
|
||||
return total_cin
|
||||
return total_cin
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ from math import log
|
|||
import design
|
||||
from tech import drc
|
||||
import debug
|
||||
from sram_factory import factory
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
|
||||
|
|
@ -11,8 +12,8 @@ class write_driver_array(design.design):
|
|||
Dynamically generated write driver array of all bitlines.
|
||||
"""
|
||||
|
||||
def __init__(self, columns, word_size):
|
||||
design.design.__init__(self, "write_driver_array")
|
||||
def __init__(self, name, columns, word_size):
|
||||
design.design.__init__(self, name)
|
||||
debug.info(1, "Creating {0}".format(self.name))
|
||||
|
||||
self.columns = columns
|
||||
|
|
@ -53,17 +54,12 @@ class write_driver_array(design.design):
|
|||
self.add_pin("gnd")
|
||||
|
||||
def add_modules(self):
|
||||
from importlib import reload
|
||||
c = reload(__import__(OPTS.write_driver))
|
||||
self.mod_write_driver = getattr(c, OPTS.write_driver)
|
||||
self.driver = self.mod_write_driver("write_driver")
|
||||
self.driver = factory.create(module_type="write_driver")
|
||||
self.add_mod(self.driver)
|
||||
|
||||
# This is just used for measurements,
|
||||
# so don't add the module
|
||||
c = reload(__import__(OPTS.bitcell))
|
||||
self.mod_bitcell = getattr(c, OPTS.bitcell)
|
||||
self.bitcell = self.mod_bitcell()
|
||||
self.bitcell = factory.create(module_type="bitcell")
|
||||
|
||||
def create_write_array(self):
|
||||
self.driver_insts = {}
|
||||
|
|
|
|||
|
|
@ -72,23 +72,24 @@ class options(optparse.Values):
|
|||
num_banks = 1
|
||||
|
||||
# These are the default modules that can be over-riden
|
||||
bank_select = "bank_select"
|
||||
bitcell_array = "bitcell_array"
|
||||
bitcell = "bitcell"
|
||||
column_mux_array = "single_level_column_mux_array"
|
||||
control_logic = "control_logic"
|
||||
decoder = "hierarchical_decoder"
|
||||
delay_chain = "delay_chain"
|
||||
dff_array = "dff_array"
|
||||
dff = "dff"
|
||||
control_logic = "control_logic"
|
||||
bitcell_array = "bitcell_array"
|
||||
sense_amp = "sense_amp"
|
||||
sense_amp_array = "sense_amp_array"
|
||||
precharge_array = "precharge_array"
|
||||
column_mux_array = "single_level_column_mux_array"
|
||||
write_driver = "write_driver"
|
||||
write_driver_array = "write_driver_array"
|
||||
tri_gate = "tri_gate"
|
||||
tri_gate_array = "tri_gate_array"
|
||||
wordline_driver = "wordline_driver"
|
||||
replica_bitline = "replica_bitline"
|
||||
ptx = "ptx"
|
||||
replica_bitcell = "replica_bitcell"
|
||||
bitcell = "bitcell"
|
||||
delay_chain = "delay_chain"
|
||||
bank_select = "bank_select"
|
||||
replica_bitline = "replica_bitline"
|
||||
sense_amp_array = "sense_amp_array"
|
||||
sense_amp = "sense_amp"
|
||||
tri_gate_array = "tri_gate_array"
|
||||
tri_gate = "tri_gate"
|
||||
wordline_driver = "wordline_driver"
|
||||
write_driver_array = "write_driver_array"
|
||||
write_driver = "write_driver"
|
||||
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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])
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ import contact
|
|||
import design
|
||||
import debug
|
||||
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,15 +18,12 @@ 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
|
||||
|
||||
|
||||
def connect_pin_to_rail(self,inst,pin,supply):
|
||||
""" Conencts a ptx pin to a supply rail. """
|
||||
""" Connects a ptx pin to a supply rail. """
|
||||
source_pin = inst.get_pin(pin)
|
||||
supply_pin = self.get_pin(supply)
|
||||
if supply_pin.overlaps(source_pin):
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@ import contact
|
|||
import pgate
|
||||
import debug
|
||||
from tech import drc, parameter, spice
|
||||
from ptx import ptx
|
||||
from vector import vector
|
||||
from math import ceil
|
||||
from globals import OPTS
|
||||
from utils import round_to_grid
|
||||
import logical_effort
|
||||
from sram_factory import factory
|
||||
|
||||
class pinv(pgate.pgate):
|
||||
"""
|
||||
|
|
@ -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))
|
||||
|
||||
|
|
@ -86,8 +82,8 @@ class pinv(pgate.pgate):
|
|||
# Sanity check. can we make an inverter in the height with minimum tx sizes?
|
||||
# Assume we need 3 metal 1 pitches (2 power rails, one between the tx for the drain)
|
||||
# plus the tx height
|
||||
nmos = ptx(tx_type="nmos")
|
||||
pmos = ptx(width=drc("minwidth_tx"), tx_type="pmos")
|
||||
nmos = factory.create(module_type="ptx", tx_type="nmos")
|
||||
pmos = factory.create(module_type="ptx", width=drc("minwidth_tx"), tx_type="pmos")
|
||||
tx_height = nmos.poly_height + pmos.poly_height
|
||||
# rotated m1 pitch or poly to active spacing
|
||||
min_channel = max(contact.poly.width + self.m1_space,
|
||||
|
|
@ -147,18 +143,20 @@ class pinv(pgate.pgate):
|
|||
|
||||
def add_ptx(self):
|
||||
""" Create the PMOS and NMOS transistors. """
|
||||
self.nmos = ptx(width=self.nmos_width,
|
||||
mults=self.tx_mults,
|
||||
tx_type="nmos",
|
||||
connect_poly=True,
|
||||
connect_active=True)
|
||||
self.nmos = factory.create(module_type="ptx",
|
||||
width=self.nmos_width,
|
||||
mults=self.tx_mults,
|
||||
tx_type="nmos",
|
||||
connect_poly=True,
|
||||
connect_active=True)
|
||||
self.add_mod(self.nmos)
|
||||
|
||||
self.pmos = ptx(width=self.pmos_width,
|
||||
mults=self.tx_mults,
|
||||
tx_type="pmos",
|
||||
connect_poly=True,
|
||||
connect_active=True)
|
||||
self.pmos = factory.create(module_type="ptx",
|
||||
width=self.pmos_width,
|
||||
mults=self.tx_mults,
|
||||
tx_type="pmos",
|
||||
connect_poly=True,
|
||||
connect_active=True)
|
||||
self.add_mod(self.pmos)
|
||||
|
||||
def route_supply_rails(self):
|
||||
|
|
|
|||
|
|
@ -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,23 +2,18 @@ import contact
|
|||
import pgate
|
||||
import debug
|
||||
from tech import drc, parameter, spice
|
||||
from ptx import ptx
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
import logical_effort
|
||||
from sram_factory import factory
|
||||
|
||||
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))
|
||||
|
||||
|
|
@ -61,18 +56,20 @@ class pnand2(pgate.pgate):
|
|||
|
||||
def add_ptx(self):
|
||||
""" Create the PMOS and NMOS transistors. """
|
||||
self.nmos = ptx(width=self.nmos_width,
|
||||
mults=self.tx_mults,
|
||||
tx_type="nmos",
|
||||
connect_poly=True,
|
||||
connect_active=True)
|
||||
self.nmos = factory.create(module_type="ptx",
|
||||
width=self.nmos_width,
|
||||
mults=self.tx_mults,
|
||||
tx_type="nmos",
|
||||
connect_poly=True,
|
||||
connect_active=True)
|
||||
self.add_mod(self.nmos)
|
||||
|
||||
self.pmos = ptx(width=self.pmos_width,
|
||||
mults=self.tx_mults,
|
||||
tx_type="pmos",
|
||||
connect_poly=True,
|
||||
connect_active=True)
|
||||
self.pmos = factory.create(module_type="ptx",
|
||||
width=self.pmos_width,
|
||||
mults=self.tx_mults,
|
||||
tx_type="pmos",
|
||||
connect_poly=True,
|
||||
connect_active=True)
|
||||
self.add_mod(self.pmos)
|
||||
|
||||
def setup_layout_constants(self):
|
||||
|
|
@ -260,4 +257,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,22 +2,17 @@ import contact
|
|||
import pgate
|
||||
import debug
|
||||
from tech import drc, parameter, spice
|
||||
from ptx import ptx
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
from sram_factory import factory
|
||||
|
||||
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))
|
||||
|
||||
|
|
@ -61,18 +56,20 @@ class pnand3(pgate.pgate):
|
|||
|
||||
def add_ptx(self):
|
||||
""" Create the PMOS and NMOS transistors. """
|
||||
self.nmos = ptx(width=self.nmos_width,
|
||||
mults=self.tx_mults,
|
||||
tx_type="nmos",
|
||||
connect_poly=True,
|
||||
connect_active=True)
|
||||
self.nmos = factory.create(module_type="ptx",
|
||||
width=self.nmos_width,
|
||||
mults=self.tx_mults,
|
||||
tx_type="nmos",
|
||||
connect_poly=True,
|
||||
connect_active=True)
|
||||
self.add_mod(self.nmos)
|
||||
|
||||
self.pmos = ptx(width=self.pmos_width,
|
||||
mults=self.tx_mults,
|
||||
tx_type="pmos",
|
||||
connect_poly=True,
|
||||
connect_active=True)
|
||||
self.pmos = factory.create(module_type="ptx",
|
||||
width=self.pmos_width,
|
||||
mults=self.tx_mults,
|
||||
tx_type="pmos",
|
||||
connect_poly=True,
|
||||
connect_active=True)
|
||||
self.add_mod(self.pmos)
|
||||
|
||||
def setup_layout_constants(self):
|
||||
|
|
@ -93,7 +90,7 @@ class pnand3(pgate.pgate):
|
|||
self.output_pos = vector(0,0.5*self.height)
|
||||
|
||||
# This is the extra space needed to ensure DRC rules to the active contacts
|
||||
nmos = ptx(tx_type="nmos")
|
||||
nmos = factory.create(module_type="ptx", tx_type="nmos")
|
||||
extra_contact_space = max(-nmos.get_pin("D").by(),0)
|
||||
# This is a poly-to-poly of a flipped cell
|
||||
self.top_bottom_space = max(0.5*self.m1_width + self.m1_space + extra_contact_space,
|
||||
|
|
@ -272,4 +269,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,23 +1,18 @@
|
|||
import contact
|
||||
import pgate
|
||||
import debug
|
||||
from tech import drc, parameter, spice
|
||||
from ptx import ptx
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
import contact
|
||||
from sram_factory import factory
|
||||
|
||||
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))
|
||||
|
||||
|
|
@ -58,32 +53,30 @@ class pnor2(pgate.pgate):
|
|||
|
||||
def create_ptx(self):
|
||||
""" Create the PMOS and NMOS transistors. """
|
||||
self.nmos = ptx(width=self.nmos_width,
|
||||
mults=self.tx_mults,
|
||||
tx_type="nmos",
|
||||
connect_poly=True,
|
||||
connect_active=True)
|
||||
self.nmos = factory.create(module_type="ptx",
|
||||
width=self.nmos_width,
|
||||
mults=self.tx_mults,
|
||||
tx_type="nmos",
|
||||
connect_poly=True,
|
||||
connect_active=True)
|
||||
self.add_mod(self.nmos)
|
||||
|
||||
self.pmos = ptx(width=self.pmos_width,
|
||||
mults=self.tx_mults,
|
||||
tx_type="pmos",
|
||||
connect_poly=True,
|
||||
connect_active=True)
|
||||
self.pmos = factory.create(module_type="ptx",
|
||||
width=self.pmos_width,
|
||||
mults=self.tx_mults,
|
||||
tx_type="pmos",
|
||||
connect_poly=True,
|
||||
connect_active=True)
|
||||
self.add_mod(self.pmos)
|
||||
|
||||
def setup_layout_constants(self):
|
||||
""" Pre-compute some handy layout parameters. """
|
||||
|
||||
poly_contact = contact.contact(("poly","contact","metal1"))
|
||||
m1m2_via = contact.contact(("metal1","via1","metal2"))
|
||||
m2m3_via = contact.contact(("metal2","via2","metal3"))
|
||||
|
||||
# metal spacing to allow contacts on any layer
|
||||
self.input_spacing = max(self.poly_space + poly_contact.first_layer_width,
|
||||
self.m1_space + m1m2_via.first_layer_width,
|
||||
self.m2_space + m2m3_via.first_layer_width,
|
||||
self.m3_space + m2m3_via.second_layer_width)
|
||||
self.input_spacing = max(self.poly_space + contact.poly.first_layer_width,
|
||||
self.m1_space + contact.m1m2.first_layer_width,
|
||||
self.m2_space + contact.m2m3.first_layer_width,
|
||||
self.m3_space + contact.m2m3.second_layer_width)
|
||||
|
||||
# Compute the other pmos2 location, but determining offset to overlap the
|
||||
# source and drain pins
|
||||
|
|
|
|||
|
|
@ -2,28 +2,20 @@ import contact
|
|||
import pgate
|
||||
import debug
|
||||
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"]
|
||||
|
|
@ -57,8 +49,9 @@ class precharge(pgate.pgate):
|
|||
"""
|
||||
Initializes the upper and lower pmos
|
||||
"""
|
||||
self.pmos = ptx(width=self.ptx_width,
|
||||
tx_type="pmos")
|
||||
self.pmos = factory.create(module_type="ptx",
|
||||
width=self.ptx_width,
|
||||
tx_type="pmos")
|
||||
self.add_mod(self.pmos)
|
||||
|
||||
|
||||
|
|
@ -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,9 +2,9 @@ import design
|
|||
import debug
|
||||
from tech import drc, spice
|
||||
from vector import vector
|
||||
from contact import contact
|
||||
from globals import OPTS
|
||||
import path
|
||||
from sram_factory import factory
|
||||
|
||||
class ptx(design.design):
|
||||
"""
|
||||
|
|
@ -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
|
||||
|
|
@ -97,8 +97,9 @@ class ptx(design.design):
|
|||
|
||||
|
||||
# This is not actually instantiated but used for calculations
|
||||
self.active_contact = contact(layer_stack=("active", "contact", "metal1"),
|
||||
dimensions=(1, self.num_contacts))
|
||||
self.active_contact = factory.create(module_type="contact",
|
||||
layer_stack=("active", "contact", "metal1"),
|
||||
dimensions=(1, self.num_contacts))
|
||||
|
||||
|
||||
# The contacted poly pitch (or uncontacted in an odd technology)
|
||||
|
|
@ -355,4 +356,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")
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ import debug
|
|||
from tech import drc
|
||||
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 +13,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,16 +43,11 @@ 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")
|
||||
self.nmos = ptx(width=self.ptx_width)
|
||||
self.nmos = factory.create(module_type="ptx", width=self.ptx_width)
|
||||
self.add_mod(self.nmos)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import logical_effort
|
|||
from design import design
|
||||
from verilog import verilog
|
||||
from lef import lef
|
||||
from sram_factory import factory
|
||||
|
||||
class sram_base(design, verilog, lef):
|
||||
"""
|
||||
|
|
@ -239,10 +240,7 @@ class sram_base(design, verilog, lef):
|
|||
|
||||
|
||||
def add_modules(self):
|
||||
""" Create all the modules that will be used """
|
||||
c = reload(__import__(OPTS.bitcell))
|
||||
self.mod_bitcell = getattr(c, OPTS.bitcell)
|
||||
self.bitcell = self.mod_bitcell()
|
||||
self.bitcell = factory.create(module_type=OPTS.bitcell)
|
||||
|
||||
# Create the address and control flops (but not the clk)
|
||||
from dff_array import dff_array
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import debug
|
|||
from math import log,sqrt,ceil
|
||||
from importlib import reload
|
||||
from globals import OPTS
|
||||
from sram_factory import factory
|
||||
|
||||
class sram_config:
|
||||
""" This is a structure that is used to hold the SRAM configuration options. """
|
||||
|
|
@ -29,10 +30,7 @@ class sram_config:
|
|||
def compute_sizes(self):
|
||||
""" Computes the organization of the memory using bitcell size by trying to make it square."""
|
||||
|
||||
c = reload(__import__(OPTS.bitcell))
|
||||
self.mod_bitcell = getattr(c, OPTS.bitcell)
|
||||
# pass a copy of myself for the port numbers
|
||||
self.bitcell = self.mod_bitcell()
|
||||
self.bitcell = factory.create(module_type="bitcell")
|
||||
|
||||
|
||||
debug.check(self.num_banks in [1,2,4], "Valid number of banks are 1 , 2 and 4.")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
import debug
|
||||
from globals import OPTS
|
||||
from importlib import reload
|
||||
|
||||
|
||||
class sram_factory:
|
||||
"""
|
||||
This is a factory pattern to create modules for usage in an SRAM.
|
||||
Since GDSII has a flat namespace, it requires modules to have unique
|
||||
names if their layout differs. This module ensures that any module
|
||||
with different layouts will have different names. It also ensures that
|
||||
identical layouts will share the same name to reduce file size and promote
|
||||
hierarchical sharing.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
# A dictionary of modules indexed by module type
|
||||
self.modules = {}
|
||||
# These are the indices to append to name to make unique object names
|
||||
self.module_indices = {}
|
||||
# A dictionary of instance lists indexed by module type
|
||||
self.objects = {}
|
||||
|
||||
def reset(self):
|
||||
"""
|
||||
Clear the factory instances for testing.
|
||||
"""
|
||||
self.__init__()
|
||||
|
||||
def create(self, module_type, **kwargs):
|
||||
"""
|
||||
A generic function to create a module with a given module_type. The args
|
||||
are passed directly to the module constructor.
|
||||
"""
|
||||
# if name!="":
|
||||
# # This is a special case where the name and type don't match
|
||||
# # Can't be overridden in the config file
|
||||
# module_name = name
|
||||
if hasattr(OPTS, module_type):
|
||||
# Retrieve the name from OPTS if it exists,
|
||||
# otherwise just use the name
|
||||
module_name = getattr(OPTS, module_type)
|
||||
else:
|
||||
module_name = module_type
|
||||
|
||||
# Either retrieve the already loaded module or load it
|
||||
try:
|
||||
mod = self.modules[module_type]
|
||||
except KeyError:
|
||||
c = reload(__import__(module_name))
|
||||
mod = getattr(c, module_name)
|
||||
self.modules[module_type] = mod
|
||||
self.module_indices[module_type] = 0
|
||||
self.objects[module_type] = []
|
||||
|
||||
# Either retreive a previous object or create a new one
|
||||
for obj in self.objects[module_type]:
|
||||
(obj_kwargs, obj_item) = obj
|
||||
# Must have the same dictionary exactly (conservative)
|
||||
if obj_kwargs == kwargs:
|
||||
debug.info(1, "Existing module: type={0} name={1} kwargs={2}".format(module_type, obj_item.name, str(kwargs)))
|
||||
return obj_item
|
||||
|
||||
# Use the default name if there are default arguments
|
||||
# This is especially for library cells so that the spice and gds files can be found.
|
||||
if len(kwargs)>0:
|
||||
# Create a unique name and increment the index
|
||||
module_name = "{0}_{1}".format(module_name, self.module_indices[module_type])
|
||||
self.module_indices[module_type] += 1
|
||||
debug.info(1, "New module: type={0} name={1} kwargs={2}".format(module_type,module_name,str(kwargs)))
|
||||
obj = mod(name=module_name,**kwargs)
|
||||
self.objects[module_type].append((kwargs,obj))
|
||||
return obj
|
||||
|
||||
|
||||
# Make a factory
|
||||
factory = sram_factory()
|
||||
|
||||
|
|
@ -25,17 +25,11 @@ class code_format_test(openram_test):
|
|||
for code in source_codes:
|
||||
if re.search("gdsMill", code):
|
||||
continue
|
||||
if re.search("options.py$", code):
|
||||
continue
|
||||
if re.search("debug.py$", code):
|
||||
continue
|
||||
if re.search("testutils.py$", code):
|
||||
continue
|
||||
if re.search("globals.py$", code):
|
||||
continue
|
||||
if re.search("openram.py$", code):
|
||||
continue
|
||||
if re.search("sram.py$", code):
|
||||
if re.search("testutils.py$", code):
|
||||
continue
|
||||
if re.search("gen_stimulus.py$", code):
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ class pand2_test(openram_test):
|
|||
import pand2
|
||||
|
||||
debug.info(2, "Testing pand2 gate 4x")
|
||||
a = pand2.pand2(4)
|
||||
a = pand2.pand2(name="pand2x4", size=4)
|
||||
self.local_check(a)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@ sys.path.append(os.path.join(sys.path[0],".."))
|
|||
import globals
|
||||
from globals import OPTS
|
||||
import debug
|
||||
|
||||
OPTS = globals.OPTS
|
||||
from sram_factory import factory
|
||||
|
||||
#@unittest.skip("SKIPPING 04_pbitcell_test")
|
||||
class pbitcell_test(openram_test):
|
||||
|
|
@ -19,75 +18,85 @@ class pbitcell_test(openram_test):
|
|||
def runTest(self):
|
||||
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
|
||||
from pbitcell import pbitcell
|
||||
import tech
|
||||
|
||||
OPTS.num_rw_ports=1
|
||||
OPTS.num_w_ports=1
|
||||
OPTS.num_r_ports=1
|
||||
factory.reset()
|
||||
debug.info(2, "Bitcell with 1 of each port: read/write, write, and read")
|
||||
tx = pbitcell()
|
||||
tx = pbitcell(name="pbc")
|
||||
self.local_check(tx)
|
||||
|
||||
OPTS.num_rw_ports=0
|
||||
OPTS.num_w_ports=1
|
||||
OPTS.num_r_ports=1
|
||||
factory.reset()
|
||||
debug.info(2, "Bitcell with 0 read/write ports")
|
||||
tx = pbitcell()
|
||||
tx = pbitcell(name="pbc")
|
||||
self.local_check(tx)
|
||||
|
||||
OPTS.num_rw_ports=1
|
||||
OPTS.num_w_ports=0
|
||||
OPTS.num_r_ports=1
|
||||
factory.reset()
|
||||
debug.info(2, "Bitcell with 0 write ports")
|
||||
tx = pbitcell()
|
||||
tx = pbitcell(name="pbc")
|
||||
self.local_check(tx)
|
||||
|
||||
OPTS.num_rw_ports=1
|
||||
OPTS.num_w_ports=1
|
||||
OPTS.num_r_ports=0
|
||||
factory.reset()
|
||||
debug.info(2, "Bitcell with 0 read ports")
|
||||
tx = pbitcell()
|
||||
tx = pbitcell(name="pbc")
|
||||
self.local_check(tx)
|
||||
|
||||
OPTS.num_rw_ports=1
|
||||
OPTS.num_w_ports=0
|
||||
OPTS.num_r_ports=0
|
||||
factory.reset()
|
||||
debug.info(2, "Bitcell with 0 read ports and 0 write ports")
|
||||
tx = pbitcell()
|
||||
tx = pbitcell(name="pbc")
|
||||
self.local_check(tx)
|
||||
|
||||
OPTS.num_rw_ports=2
|
||||
OPTS.num_w_ports=2
|
||||
OPTS.num_r_ports=2
|
||||
factory.reset()
|
||||
debug.info(2, "Bitcell with 2 of each port: read/write, write, and read")
|
||||
tx = pbitcell()
|
||||
tx = pbitcell(name="pbc")
|
||||
self.local_check(tx)
|
||||
|
||||
OPTS.num_rw_ports=0
|
||||
OPTS.num_w_ports=2
|
||||
OPTS.num_r_ports=2
|
||||
factory.reset()
|
||||
debug.info(2, "Bitcell with 0 read/write ports")
|
||||
tx = pbitcell()
|
||||
tx = pbitcell(name="pbc")
|
||||
self.local_check(tx)
|
||||
|
||||
OPTS.num_rw_ports=2
|
||||
OPTS.num_w_ports=0
|
||||
OPTS.num_r_ports=2
|
||||
factory.reset()
|
||||
debug.info(2, "Bitcell with 0 write ports")
|
||||
tx = pbitcell()
|
||||
tx = pbitcell(name="pbc")
|
||||
self.local_check(tx)
|
||||
|
||||
OPTS.num_rw_ports=2
|
||||
OPTS.num_w_ports=2
|
||||
OPTS.num_r_ports=0
|
||||
factory.reset()
|
||||
debug.info(2, "Bitcell with 0 read ports")
|
||||
tx = pbitcell()
|
||||
tx = pbitcell(name="pbc")
|
||||
self.local_check(tx)
|
||||
|
||||
OPTS.num_rw_ports=2
|
||||
OPTS.num_w_ports=0
|
||||
OPTS.num_r_ports=0
|
||||
factory.reset()
|
||||
debug.info(2, "Bitcell with 0 read ports and 0 write ports")
|
||||
tx = pbitcell()
|
||||
tx = pbitcell(name="pbc")
|
||||
self.local_check(tx)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ class pbuf_test(openram_test):
|
|||
import pbuf
|
||||
|
||||
debug.info(2, "Testing inverter/buffer 4x 8x")
|
||||
a = pbuf.pbuf(8)
|
||||
a = pbuf.pbuf(name="pbufx8", size=8)
|
||||
self.local_check(a)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -23,16 +23,21 @@ class pdriver_test(openram_test):
|
|||
debug.info(2, "Testing inverter/buffer 4x 8x")
|
||||
# a tests the error message for specifying conflicting conditions
|
||||
#a = pdriver.pdriver(fanout_size = 4,size_list = [1,2,4,8])
|
||||
b = pdriver.pdriver(size_list = [1,2,4,8])
|
||||
c = pdriver.pdriver(fanout_size = 50)
|
||||
d = pdriver.pdriver(fanout_size = 50, neg_polarity = True)
|
||||
e = pdriver.pdriver(fanout_size = 64)
|
||||
f = pdriver.pdriver(fanout_size = 64, neg_polarity = True)
|
||||
#self.local_check(a)
|
||||
|
||||
b = pdriver.pdriver(name="pdriver1", size_list = [1,2,4,8])
|
||||
self.local_check(b)
|
||||
|
||||
c = pdriver.pdriver(name="pdriver2", fanout_size = 50)
|
||||
self.local_check(c)
|
||||
|
||||
d = pdriver.pdriver(name="pdriver3", fanout_size = 50, neg_polarity = True)
|
||||
self.local_check(d)
|
||||
|
||||
e = pdriver.pdriver(name="pdriver4", fanout_size = 64)
|
||||
self.local_check(e)
|
||||
|
||||
f = pdriver.pdriver(name="pdriver5", fanout_size = 64, neg_polarity = True)
|
||||
self.local_check(f)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ class pinv_test(openram_test):
|
|||
import tech
|
||||
|
||||
debug.info(2, "Checking 10x inverter")
|
||||
tx = pinv.pinv(size=8)
|
||||
tx = pinv.pinv(name="pinvx10",size=8)
|
||||
self.local_check(tx)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ class pinv_test(openram_test):
|
|||
import tech
|
||||
|
||||
debug.info(2, "Checking 1x beta=3 size inverter")
|
||||
tx = pinv.pinv(size=1, beta=3)
|
||||
tx = pinv.pinv(name="pinvx1b", size=1, beta=3)
|
||||
self.local_check(tx)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class pinv_test(openram_test):
|
|||
import tech
|
||||
|
||||
debug.info(2, "Checking 1x size inverter")
|
||||
tx = pinv.pinv(size=1)
|
||||
tx = pinv.pinv(name="pinvx1", size=1)
|
||||
self.local_check(tx)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ class pinv_test(openram_test):
|
|||
import tech
|
||||
|
||||
debug.info(2, "Checking 2x size inverter")
|
||||
tx = pinv.pinv(size=2)
|
||||
tx = pinv.pinv(name="pinvx2", size=2)
|
||||
self.local_check(tx)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class pinvbuf_test(openram_test):
|
|||
import pinvbuf
|
||||
|
||||
debug.info(2, "Testing inverter/buffer 4x 8x")
|
||||
a = pinvbuf.pinvbuf(8)
|
||||
a = pinvbuf.pinvbuf(name="pinvufx8", size=8)
|
||||
self.local_check(a)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ class pnand2_test(openram_test):
|
|||
import tech
|
||||
|
||||
debug.info(2, "Checking 2-input nand gate")
|
||||
tx = pnand2.pnand2(size=1)
|
||||
tx = pnand2.pnand2(name="pnand2", size=1)
|
||||
self.local_check(tx)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ class pnand3_test(openram_test):
|
|||
import tech
|
||||
|
||||
debug.info(2, "Checking 3-input nand gate")
|
||||
tx = pnand3.pnand3(size=1)
|
||||
tx = pnand3.pnand3(name="pnand3", size=1)
|
||||
self.local_check(tx)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ class pnor2_test(openram_test):
|
|||
import tech
|
||||
|
||||
debug.info(2, "Checking 2-input nor gate")
|
||||
tx = pnor2.pnor2(size=1)
|
||||
tx = pnor2.pnor2(name="pnor2", size=1)
|
||||
self.local_check(tx)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ sys.path.append(os.path.join(sys.path[0],".."))
|
|||
import globals
|
||||
from globals import OPTS
|
||||
import debug
|
||||
from sram_factory import factory
|
||||
|
||||
class precharge_test(openram_test):
|
||||
|
||||
|
|
@ -28,7 +29,8 @@ class precharge_test(openram_test):
|
|||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 1
|
||||
OPTS.num_w_ports = 1
|
||||
|
||||
|
||||
factory.reset()
|
||||
debug.info(2, "Checking precharge for pbitcell (innermost connections)")
|
||||
tx = precharge.precharge(name="precharge_driver", size=1, bitcell_bl="bl0", bitcell_br="br0")
|
||||
self.local_check(tx)
|
||||
|
|
|
|||
|
|
@ -10,29 +10,31 @@ sys.path.append(os.path.join(sys.path[0],".."))
|
|||
import globals
|
||||
from globals import OPTS
|
||||
import debug
|
||||
from sram_factory import factory
|
||||
|
||||
class replica_pbitcell_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
|
||||
import replica_pbitcell
|
||||
import tech
|
||||
|
||||
OPTS.bitcell = "pbitcell"
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 0
|
||||
OPTS.num_w_ports = 0
|
||||
|
||||
|
||||
factory.reset()
|
||||
debug.info(2, "Checking replica bitcell using pbitcell (small cell)")
|
||||
tx = replica_pbitcell.replica_pbitcell()
|
||||
tx = replica_pbitcell.replica_pbitcell(name="rpbc")
|
||||
self.local_check(tx)
|
||||
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 1
|
||||
OPTS.num_w_ports = 1
|
||||
|
||||
|
||||
factory.reset()
|
||||
debug.info(2, "Checking replica bitcell using pbitcell (large cell)")
|
||||
tx = replica_pbitcell.replica_pbitcell()
|
||||
tx = replica_pbitcell.replica_pbitcell(name="rpbc")
|
||||
self.local_check(tx)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ sys.path.append(os.path.join(sys.path[0],".."))
|
|||
import globals
|
||||
from globals import OPTS
|
||||
import debug
|
||||
from sram_factory import factory
|
||||
|
||||
#@unittest.skip("SKIPPING 04_driver_test")
|
||||
|
||||
|
|
@ -22,7 +23,7 @@ class single_level_column_mux_test(openram_test):
|
|||
|
||||
# check single level column mux in single port
|
||||
debug.info(2, "Checking column mux")
|
||||
tx = single_level_column_mux.single_level_column_mux(tx_size=8)
|
||||
tx = single_level_column_mux.single_level_column_mux(name="mux8", tx_size=8)
|
||||
self.local_check(tx)
|
||||
|
||||
# check single level column mux in multi-port
|
||||
|
|
@ -30,13 +31,15 @@ class single_level_column_mux_test(openram_test):
|
|||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 1
|
||||
OPTS.num_w_ports = 1
|
||||
|
||||
|
||||
factory.reset()
|
||||
debug.info(2, "Checking column mux for pbitcell (innermost connections)")
|
||||
tx = single_level_column_mux.single_level_column_mux(tx_size=8, bitcell_bl="bl0", bitcell_br="br0")
|
||||
tx = single_level_column_mux.single_level_column_mux(name="mux8_2", tx_size=8, bitcell_bl="bl0", bitcell_br="br0")
|
||||
self.local_check(tx)
|
||||
|
||||
factory.reset()
|
||||
debug.info(2, "Checking column mux for pbitcell (outermost connections)")
|
||||
tx = single_level_column_mux.single_level_column_mux(tx_size=8, bitcell_bl="bl2", bitcell_br="br2")
|
||||
tx = single_level_column_mux.single_level_column_mux(name="mux8_3", tx_size=8, bitcell_bl="bl2", bitcell_br="br2")
|
||||
self.local_check(tx)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ sys.path.append(os.path.join(sys.path[0],".."))
|
|||
import globals
|
||||
from globals import OPTS
|
||||
import debug
|
||||
from sram_factory import factory
|
||||
|
||||
class hierarchical_decoder_test(openram_test):
|
||||
|
||||
|
|
@ -20,29 +21,29 @@ class hierarchical_decoder_test(openram_test):
|
|||
|
||||
# Doesn't require hierarchical decoder
|
||||
# debug.info(1, "Testing 4 row sample for hierarchical_decoder")
|
||||
# a = hierarchical_decoder.hierarchical_decoder(rows=4)
|
||||
# a = hierarchical_decoder.hierarchical_decoder(name="hd1, rows=4)
|
||||
# self.local_check(a)
|
||||
|
||||
# Doesn't require hierarchical decoder
|
||||
# debug.info(1, "Testing 8 row sample for hierarchical_decoder")
|
||||
# a = hierarchical_decoder.hierarchical_decoder(rows=8)
|
||||
# a = hierarchical_decoder.hierarchical_decoder(name="hd2", rows=8)
|
||||
# self.local_check(a)
|
||||
|
||||
# check hierarchical decoder for single port
|
||||
debug.info(1, "Testing 16 row sample for hierarchical_decoder")
|
||||
a = hierarchical_decoder.hierarchical_decoder(rows=16)
|
||||
a = hierarchical_decoder.hierarchical_decoder(name="hd3", rows=16)
|
||||
self.local_check(a)
|
||||
|
||||
debug.info(1, "Testing 32 row sample for hierarchical_decoder")
|
||||
a = hierarchical_decoder.hierarchical_decoder(rows=32)
|
||||
a = hierarchical_decoder.hierarchical_decoder(name="hd4", rows=32)
|
||||
self.local_check(a)
|
||||
|
||||
debug.info(1, "Testing 128 row sample for hierarchical_decoder")
|
||||
a = hierarchical_decoder.hierarchical_decoder(rows=128)
|
||||
a = hierarchical_decoder.hierarchical_decoder(name="hd5", rows=128)
|
||||
self.local_check(a)
|
||||
|
||||
debug.info(1, "Testing 512 row sample for hierarchical_decoder")
|
||||
a = hierarchical_decoder.hierarchical_decoder(rows=512)
|
||||
a = hierarchical_decoder.hierarchical_decoder(name="hd6", rows=512)
|
||||
self.local_check(a)
|
||||
|
||||
# check hierarchical decoder for multi-port
|
||||
|
|
@ -50,21 +51,22 @@ class hierarchical_decoder_test(openram_test):
|
|||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
OPTS.num_r_ports = 0
|
||||
|
||||
|
||||
factory.reset()
|
||||
debug.info(1, "Testing 16 row sample for hierarchical_decoder (multi-port case)")
|
||||
a = hierarchical_decoder.hierarchical_decoder(rows=16)
|
||||
a = hierarchical_decoder.hierarchical_decoder(name="hd7", rows=16)
|
||||
self.local_check(a)
|
||||
|
||||
debug.info(1, "Testing 32 row sample for hierarchical_decoder (multi-port case)")
|
||||
a = hierarchical_decoder.hierarchical_decoder(rows=32)
|
||||
a = hierarchical_decoder.hierarchical_decoder(name="hd8", rows=32)
|
||||
self.local_check(a)
|
||||
|
||||
debug.info(1, "Testing 128 row sample for hierarchical_decoder (multi-port case)")
|
||||
a = hierarchical_decoder.hierarchical_decoder(rows=128)
|
||||
a = hierarchical_decoder.hierarchical_decoder(name="hd9", rows=128)
|
||||
self.local_check(a)
|
||||
|
||||
debug.info(1, "Testing 512 row sample for hierarchical_decoder (multi-port case)")
|
||||
a = hierarchical_decoder.hierarchical_decoder(rows=512)
|
||||
a = hierarchical_decoder.hierarchical_decoder(name="hd10", rows=512)
|
||||
self.local_check(a)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class hierarchical_predecode2x4_test(openram_test):
|
|||
|
||||
# checking hierarchical precode 2x4 for single port
|
||||
debug.info(1, "Testing sample for hierarchy_predecode2x4")
|
||||
a = pre.hierarchical_predecode2x4()
|
||||
a = pre.hierarchical_predecode2x4(name="pre1")
|
||||
self.local_check(a)
|
||||
|
||||
# checking hierarchical precode 2x4 for multi-port
|
||||
|
|
@ -30,7 +30,7 @@ class hierarchical_predecode2x4_test(openram_test):
|
|||
OPTS.num_r_ports = 0
|
||||
|
||||
debug.info(1, "Testing sample for hierarchy_predecode2x4 (multi-port case)")
|
||||
a = pre.hierarchical_predecode2x4()
|
||||
a = pre.hierarchical_predecode2x4(name="pre2")
|
||||
self.local_check(a)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class hierarchical_predecode3x8_test(openram_test):
|
|||
|
||||
# checking hierarchical precode 3x8 for single port
|
||||
debug.info(1, "Testing sample for hierarchy_predecode3x8")
|
||||
a = pre.hierarchical_predecode3x8()
|
||||
a = pre.hierarchical_predecode3x8(name="pre1")
|
||||
self.local_check(a)
|
||||
|
||||
# checking hierarchical precode 3x8 for multi-port
|
||||
|
|
@ -30,7 +30,7 @@ class hierarchical_predecode3x8_test(openram_test):
|
|||
OPTS.num_r_ports = 0
|
||||
|
||||
debug.info(1, "Testing sample for hierarchy_predecode3x8 (multi-port case)")
|
||||
a = pre.hierarchical_predecode3x8()
|
||||
a = pre.hierarchical_predecode3x8(name="pre2")
|
||||
self.local_check(a)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ sys.path.append(os.path.join(sys.path[0],".."))
|
|||
import globals
|
||||
from globals import OPTS
|
||||
import debug
|
||||
from sram_factory import factory
|
||||
|
||||
class single_level_column_mux_test(openram_test):
|
||||
|
||||
|
|
@ -18,15 +19,15 @@ class single_level_column_mux_test(openram_test):
|
|||
|
||||
# check single level column mux array in single port
|
||||
debug.info(1, "Testing sample for 2-way column_mux_array")
|
||||
a = single_level_column_mux_array.single_level_column_mux_array(columns=16, word_size=8)
|
||||
a = single_level_column_mux_array.single_level_column_mux_array(name="mux1", columns=16, word_size=8)
|
||||
self.local_check(a)
|
||||
|
||||
debug.info(1, "Testing sample for 4-way column_mux_array")
|
||||
a = single_level_column_mux_array.single_level_column_mux_array(columns=16, word_size=4)
|
||||
a = single_level_column_mux_array.single_level_column_mux_array(name="mux2", columns=16, word_size=4)
|
||||
self.local_check(a)
|
||||
|
||||
debug.info(1, "Testing sample for 8-way column_mux_array")
|
||||
a = single_level_column_mux_array.single_level_column_mux_array(columns=32, word_size=4)
|
||||
a = single_level_column_mux_array.single_level_column_mux_array(name="mux3", columns=32, word_size=4)
|
||||
self.local_check(a)
|
||||
|
||||
# check single level column mux array in multi-port
|
||||
|
|
@ -34,21 +35,22 @@ class single_level_column_mux_test(openram_test):
|
|||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 1
|
||||
OPTS.num_w_ports = 1
|
||||
|
||||
|
||||
factory.reset()
|
||||
debug.info(1, "Testing sample for 2-way column_mux_array in multi-port")
|
||||
a = single_level_column_mux_array.single_level_column_mux_array(columns=16, word_size=8, bitcell_bl="bl0", bitcell_br="br0")
|
||||
a = single_level_column_mux_array.single_level_column_mux_array(name="mux4", columns=16, word_size=8, bitcell_bl="bl0", bitcell_br="br0")
|
||||
self.local_check(a)
|
||||
|
||||
debug.info(1, "Testing sample for 4-way column_mux_array in multi-port")
|
||||
a = single_level_column_mux_array.single_level_column_mux_array(columns=16, word_size=4, bitcell_bl="bl0", bitcell_br="br0")
|
||||
a = single_level_column_mux_array.single_level_column_mux_array(name="mux5", columns=16, word_size=4, bitcell_bl="bl0", bitcell_br="br0")
|
||||
self.local_check(a)
|
||||
|
||||
debug.info(1, "Testing sample for 8-way column_mux_array in multi-port (innermost connections)")
|
||||
a = single_level_column_mux_array.single_level_column_mux_array(columns=32, word_size=4, bitcell_bl="bl0", bitcell_br="br0")
|
||||
a = single_level_column_mux_array.single_level_column_mux_array(name="mux6", columns=32, word_size=4, bitcell_bl="bl0", bitcell_br="br0")
|
||||
self.local_check(a)
|
||||
|
||||
debug.info(1, "Testing sample for 8-way column_mux_array in multi-port (outermost connections)")
|
||||
a = single_level_column_mux_array.single_level_column_mux_array(columns=32, word_size=4, bitcell_bl="bl2", bitcell_br="br2")
|
||||
a = single_level_column_mux_array.single_level_column_mux_array(name="mux7", columns=32, word_size=4, bitcell_bl="bl2", bitcell_br="br2")
|
||||
self.local_check(a)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -10,17 +10,17 @@ sys.path.append(os.path.join(sys.path[0],".."))
|
|||
import globals
|
||||
from globals import OPTS
|
||||
import debug
|
||||
from sram_factory import factory
|
||||
|
||||
class precharge_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
|
||||
import precharge_array
|
||||
import tech
|
||||
|
||||
# check precharge array in single port
|
||||
debug.info(2, "Checking 3 column precharge")
|
||||
pc = precharge_array.precharge_array(columns=3)
|
||||
pc = precharge_array.precharge_array(name="pre1", columns=3)
|
||||
self.local_check(pc)
|
||||
|
||||
# check precharge array in multi-port
|
||||
|
|
@ -28,17 +28,18 @@ class precharge_test(openram_test):
|
|||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
|
||||
|
||||
factory.reset()
|
||||
debug.info(2, "Checking 3 column precharge array for 1RW/1R bitcell")
|
||||
pc = precharge_array.precharge_array(columns=3, bitcell_bl="bl0", bitcell_br="br0")
|
||||
pc = precharge_array.precharge_array(name="pre2", columns=3, bitcell_bl="bl0", bitcell_br="br0")
|
||||
self.local_check(pc)
|
||||
|
||||
# debug.info(2, "Checking 3 column precharge array for pbitcell (innermost connections)")
|
||||
# pc = precharge_array.precharge_array(columns=3, bitcell_bl="bl0", bitcell_br="br0")
|
||||
# pc = precharge_array.precharge_array(name="pre3", columns=3, bitcell_bl="bl0", bitcell_br="br0")
|
||||
# self.local_check(pc)
|
||||
|
||||
# debug.info(2, "Checking 3 column precharge array for pbitcell (outermost connections)")
|
||||
# pc = precharge_array.precharge_array(columns=3, bitcell_bl="bl2", bitcell_br="br2")
|
||||
# pc = precharge_array.precharge_array(name="pre4", columns=3, bitcell_bl="bl2", bitcell_br="br2")
|
||||
# self.local_check(pc)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ sys.path.append(os.path.join(sys.path[0],".."))
|
|||
import globals
|
||||
from globals import OPTS
|
||||
import debug
|
||||
from sram_factory import factory
|
||||
|
||||
#@unittest.skip("SKIPPING 04_driver_test")
|
||||
|
||||
|
|
@ -18,11 +19,10 @@ class wordline_driver_test(openram_test):
|
|||
def runTest(self):
|
||||
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
|
||||
import wordline_driver
|
||||
import tech
|
||||
|
||||
# check wordline driver for single port
|
||||
debug.info(2, "Checking driver")
|
||||
tx = wordline_driver.wordline_driver(rows=8)
|
||||
tx = wordline_driver.wordline_driver(name="wld1", rows=8)
|
||||
self.local_check(tx)
|
||||
|
||||
# check wordline driver for multi-port
|
||||
|
|
@ -30,9 +30,10 @@ class wordline_driver_test(openram_test):
|
|||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
OPTS.num_r_ports = 0
|
||||
|
||||
|
||||
factory.reset()
|
||||
debug.info(2, "Checking driver (multi-port case)")
|
||||
tx = wordline_driver.wordline_driver(rows=8)
|
||||
tx = wordline_driver.wordline_driver(name="wld2", rows=8)
|
||||
self.local_check(tx)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ sys.path.append(os.path.join(sys.path[0],".."))
|
|||
import globals
|
||||
from globals import OPTS
|
||||
import debug
|
||||
from sram_factory import factory
|
||||
|
||||
class sense_amp_test(openram_test):
|
||||
|
||||
|
|
@ -19,11 +20,11 @@ class sense_amp_test(openram_test):
|
|||
|
||||
# check sense amp array for single port
|
||||
debug.info(2, "Testing sense_amp_array for word_size=4, words_per_row=2")
|
||||
a = sense_amp_array.sense_amp_array(word_size=4, words_per_row=2)
|
||||
a = sense_amp_array.sense_amp_array(name="sa1", word_size=4, words_per_row=2)
|
||||
self.local_check(a)
|
||||
|
||||
debug.info(2, "Testing sense_amp_array for word_size=4, words_per_row=4")
|
||||
a = sense_amp_array.sense_amp_array(word_size=4, words_per_row=4)
|
||||
a = sense_amp_array.sense_amp_array(name="sa2", word_size=4, words_per_row=4)
|
||||
self.local_check(a)
|
||||
|
||||
# check sense amp array for multi-port
|
||||
|
|
@ -31,13 +32,14 @@ class sense_amp_test(openram_test):
|
|||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
OPTS.num_r_ports = 0
|
||||
|
||||
|
||||
factory.reset()
|
||||
debug.info(2, "Testing sense_amp_array for word_size=4, words_per_row=2 (multi-port case)")
|
||||
a = sense_amp_array.sense_amp_array(word_size=4, words_per_row=2)
|
||||
a = sense_amp_array.sense_amp_array(name="sa3", word_size=4, words_per_row=2)
|
||||
self.local_check(a)
|
||||
|
||||
debug.info(2, "Testing sense_amp_array for word_size=4, words_per_row=4 (multi-port case)")
|
||||
a = sense_amp_array.sense_amp_array(word_size=4, words_per_row=4)
|
||||
a = sense_amp_array.sense_amp_array(name="sa4", word_size=4, words_per_row=4)
|
||||
self.local_check(a)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ sys.path.append(os.path.join(sys.path[0],".."))
|
|||
import globals
|
||||
from globals import OPTS
|
||||
import debug
|
||||
from sram_factory import factory
|
||||
|
||||
class write_driver_test(openram_test):
|
||||
|
||||
|
|
@ -19,11 +20,11 @@ class write_driver_test(openram_test):
|
|||
|
||||
# check write driver array for single port
|
||||
debug.info(2, "Testing write_driver_array for columns=8, word_size=8")
|
||||
a = write_driver_array.write_driver_array(columns=8, word_size=8)
|
||||
a = write_driver_array.write_driver_array(name="wd1", columns=8, word_size=8)
|
||||
self.local_check(a)
|
||||
|
||||
debug.info(2, "Testing write_driver_array for columns=16, word_size=8")
|
||||
a = write_driver_array.write_driver_array(columns=16, word_size=8)
|
||||
a = write_driver_array.write_driver_array(name="wd2", columns=16, word_size=8)
|
||||
self.local_check(a)
|
||||
|
||||
# check write driver array for multi-port
|
||||
|
|
@ -31,13 +32,14 @@ class write_driver_test(openram_test):
|
|||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
OPTS.num_r_ports = 0
|
||||
|
||||
|
||||
factory.reset()
|
||||
debug.info(2, "Testing write_driver_array for columns=8, word_size=8 (multi-port case)")
|
||||
a = write_driver_array.write_driver_array(columns=8, word_size=8)
|
||||
a = write_driver_array.write_driver_array(name="wd3", columns=8, word_size=8)
|
||||
self.local_check(a)
|
||||
|
||||
debug.info(2, "Testing write_driver_array for columns=16, word_size=8 (multi-port case)")
|
||||
a = write_driver_array.write_driver_array(columns=16, word_size=8)
|
||||
a = write_driver_array.write_driver_array(name="wd4", columns=16, word_size=8)
|
||||
self.local_check(a)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class delay_chain_test(openram_test):
|
|||
import delay_chain
|
||||
|
||||
debug.info(2, "Testing delay_chain")
|
||||
a = delay_chain.delay_chain(fanout_list=[4, 4, 4, 4])
|
||||
a = delay_chain.delay_chain(name="dc", fanout_list=[4, 4, 4, 4])
|
||||
self.local_check(a)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ sys.path.append(os.path.join(sys.path[0],".."))
|
|||
import globals
|
||||
from globals import OPTS
|
||||
import debug
|
||||
from sram_factory import factory
|
||||
|
||||
class replica_bitline_multiport_test(openram_test):
|
||||
|
||||
|
|
@ -26,9 +27,10 @@ class replica_bitline_multiport_test(openram_test):
|
|||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
|
||||
|
||||
factory.reset()
|
||||
debug.info(2, "Testing 1rw 1r RBL with {0} FO4 stages, {1} rows".format(stages,rows))
|
||||
a = replica_bitline.replica_bitline(stages*[fanout],rows)
|
||||
a = replica_bitline.replica_bitline(name="rbl1", delay_fanout_list=stages*[fanout], bitcell_loads=rows)
|
||||
self.local_check(a)
|
||||
|
||||
# check replica bitline in pbitcell multi-port
|
||||
|
|
@ -38,16 +40,18 @@ class replica_bitline_multiport_test(openram_test):
|
|||
OPTS.num_w_ports = 0
|
||||
OPTS.num_r_ports = 0
|
||||
|
||||
factory.reset()
|
||||
debug.info(2, "Testing RBL pbitcell 1rw with {0} FO4 stages, {1} rows".format(stages,rows))
|
||||
a = replica_bitline.replica_bitline(stages*[fanout],rows)
|
||||
a = replica_bitline.replica_bitline(name="rbl2", delay_fanout_list=stages*[fanout], bitcell_loads=rows)
|
||||
self.local_check(a)
|
||||
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_w_ports = 1
|
||||
OPTS.num_r_ports = 1
|
||||
|
||||
factory.reset()
|
||||
debug.info(2, "Testing RBL pbitcell 1rw 1w 1r with {0} FO4 stages, {1} rows".format(stages,rows))
|
||||
a = replica_bitline.replica_bitline(stages*[fanout],rows)
|
||||
a = replica_bitline.replica_bitline(name="rbl3", delay_fanout_list=stages*[fanout], bitcell_loads=rows)
|
||||
self.local_check(a)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -22,14 +22,14 @@ class replica_bitline_test(openram_test):
|
|||
fanout=4
|
||||
rows=13
|
||||
debug.info(2, "Testing RBL with {0} FO4 stages, {1} rows".format(stages,rows))
|
||||
a = replica_bitline.replica_bitline(stages*[fanout],rows)
|
||||
a = replica_bitline.replica_bitline(name="rbl1", delay_fanout_list=stages*[fanout], bitcell_loads=rows)
|
||||
self.local_check(a)
|
||||
#debug.error("Exiting...", 1)
|
||||
|
||||
stages=8
|
||||
rows=100
|
||||
debug.info(2, "Testing RBL with {0} FO4 stages, {1} rows".format(stages,rows))
|
||||
a = replica_bitline.replica_bitline(stages*[fanout],rows)
|
||||
a = replica_bitline.replica_bitline(name="rbl2", delay_fanout_list=stages*[fanout], bitcell_loads=rows)
|
||||
self.local_check(a)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -10,15 +10,13 @@ sys.path.append(os.path.join(sys.path[0],".."))
|
|||
import globals
|
||||
from globals import OPTS
|
||||
import debug
|
||||
from sram_factory import factory
|
||||
|
||||
#@unittest.skip("SKIPPING 19_psingle_bank_test")
|
||||
class psingle_bank_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
|
||||
global verify
|
||||
import verify
|
||||
|
||||
from bank import bank
|
||||
from sram_config import sram_config
|
||||
OPTS.bitcell = "pbitcell"
|
||||
|
|
@ -31,6 +29,7 @@ class psingle_bank_test(openram_test):
|
|||
num_words=16)
|
||||
|
||||
c.words_per_row=1
|
||||
factory.reset()
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "No column mux")
|
||||
name = "bank1_{0}rw_{1}w_{2}r_single".format(OPTS.num_rw_ports, OPTS.num_w_ports, OPTS.num_r_ports)
|
||||
|
|
@ -39,6 +38,7 @@ class psingle_bank_test(openram_test):
|
|||
|
||||
c.num_words=32
|
||||
c.words_per_row=2
|
||||
factory.reset()
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Two way column mux")
|
||||
name = "bank2_{0}rw_{1}w_{2}r_single".format(OPTS.num_rw_ports, OPTS.num_w_ports, OPTS.num_r_ports)
|
||||
|
|
@ -47,6 +47,7 @@ class psingle_bank_test(openram_test):
|
|||
|
||||
c.num_words=64
|
||||
c.words_per_row=4
|
||||
factory.reset()
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Four way column mux")
|
||||
name = "bank3_{0}rw_{1}w_{2}r_single".format(OPTS.num_rw_ports, OPTS.num_w_ports, OPTS.num_r_ports)
|
||||
|
|
@ -56,6 +57,7 @@ class psingle_bank_test(openram_test):
|
|||
c.word_size=2
|
||||
c.num_words=128
|
||||
c.words_per_row=8
|
||||
factory.reset()
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Four way column mux")
|
||||
name = "bank4_{0}rw_{1}w_{2}r_single".format(OPTS.num_rw_ports, OPTS.num_w_ports, OPTS.num_r_ports)
|
||||
|
|
|
|||
|
|
@ -4,11 +4,12 @@ equate class {-circuit1 nfet} {-circuit2 n}
|
|||
equate class {-circuit1 pfet} {-circuit2 p}
|
||||
# This circuit has symmetries and needs to be flattened to resolve them
|
||||
# or the banks won't pass
|
||||
flatten class {-circuit1 bitcell_array}
|
||||
flatten class {-circuit1 bitcell_array_0}
|
||||
flatten class {-circuit1 bitcell_array_1}
|
||||
flatten class {-circuit1 precharge_array_0}
|
||||
flatten class {-circuit1 precharge_array_1}
|
||||
flatten class {-circuit1 precharge_array_2}
|
||||
flatten class {-circuit1 precharge_array_3}
|
||||
flatten class {-circuit1 precharge_array_4}
|
||||
property {-circuit1 nfet} remove as ad ps pd
|
||||
property {-circuit1 pfet} remove as ad ps pd
|
||||
property {-circuit2 n} remove as ad ps pd
|
||||
|
|
|
|||
Loading…
Reference in New Issue