Merge branch 'dev' into datasheet_gen

This commit is contained in:
Jesse Cirimelli-Low 2019-01-22 15:24:44 -08:00
commit 886dd4d313
82 changed files with 619 additions and 629 deletions

View File

@ -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"))

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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)

View File

@ -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):

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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=[]

View File

@ -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

View File

@ -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())

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"]

View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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):

View File

@ -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)

View File

@ -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:

View File

@ -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:

View File

@ -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))

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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):

View File

@ -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

View File

@ -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 = {}

View File

@ -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"

View File

@ -3,28 +3,16 @@ from tech import drc
from math import log
from vector import vector
from globals import OPTS
from pnand2 import pnand2
from pinv import pinv
import pgate
from sram_factory import factory
class pand2(pgate.pgate):
"""
This is a simple buffer used for driving loads.
"""
from importlib import reload
c = reload(__import__(OPTS.bitcell))
bitcell = getattr(c, OPTS.bitcell)
unique_id = 1
def __init__(self, size=1, height=None, name=""):
def __init__(self, name, size=1, height=None):
self.size = size
if name=="":
name = "pand2_{0}_{1}".format(size, pand2.unique_id)
pand2.unique_id += 1
pgate.pgate.__init__(self, name, height)
debug.info(1, "Creating {}".format(self.name))
@ -41,10 +29,10 @@ class pand2(pgate.pgate):
def create_modules(self):
# Shield the cap, but have at least a stage effort of 4
self.nand = pnand2(height=self.height)
self.nand = factory.create(module_type="pnand2",height=self.height)
self.add_mod(self.nand)
self.inv = pinv(size=self.size, height=self.height)
self.inv = factory.create(module_type="pinv", size=self.size, height=self.height)
self.add_mod(self.inv)
def create_layout(self):

View File

@ -3,29 +3,19 @@ from tech import drc
from math import log
from vector import vector
from globals import OPTS
from pinv import pinv
import pgate
from sram_factory import factory
class pbuf(pgate.pgate):
"""
This is a simple buffer used for driving loads.
"""
from importlib import reload
c = reload(__import__(OPTS.bitcell))
bitcell = getattr(c, OPTS.bitcell)
unique_id = 1
def __init__(self, size=4, height=None, name=""):
def __init__(self, name, size=4, height=None):
self.stage_effort = 4
self.size = size
self.height = height
if name=="":
name = "pbuf_{0}_{1}".format(self.size, pbuf.unique_id)
pbuf.unique_id += 1
pgate.pgate.__init__(self, name, height)
debug.info(1, "creating {0} with size of {1}".format(self.name,self.size))
@ -54,10 +44,10 @@ class pbuf(pgate.pgate):
def create_modules(self):
# Shield the cap, but have at least a stage effort of 4
input_size = max(1,int(self.size/self.stage_effort))
self.inv1 = pinv(size=input_size, height=self.height)
self.inv1 = factory.create(module_type="pinv", size=input_size, height=self.height)
self.add_mod(self.inv1)
self.inv2 = pinv(size=self.size, height=self.height)
self.inv2 = factory.create(module_type="pinv", size=self.size, height=self.height)
self.add_mod(self.inv2)
def create_insts(self):
@ -141,4 +131,4 @@ class pbuf(pgate.pgate):
def get_cin(self):
"""Returns the relative capacitance of the input"""
input_cin = self.inv1.get_cin()
return input_cin
return input_cin

View File

@ -5,15 +5,13 @@ from tech import drc
from math import log
from vector import vector
from globals import OPTS
from pinv import pinv
from sram_factory import factory
class pdriver(pgate.pgate):
"""
This instantiates an even or odd number of inverters sized for driving a load.
"""
unique_id = 1
def __init__(self, neg_polarity=False, fanout_size=8, size_list = [], height=None, name=""):
def __init__(self, name, neg_polarity=False, fanout_size=8, size_list = [], height=None):
self.stage_effort = 4
self.height = height
@ -24,10 +22,6 @@ class pdriver(pgate.pgate):
if len(self.size_list) > 0 and (self.fanout_size != 8 or self.neg_polarity):
debug.error("Cannot specify both size_list and neg_polarity or fanout_size.", -1)
if name=="":
name = "pdriver_{}".format(pdriver.unique_id)
pdriver.unique_id += 1
pgate.pgate.__init__(self, name, height)
debug.info(1, "Creating {}".format(self.name))
@ -123,11 +117,13 @@ class pdriver(pgate.pgate):
self.inv_list = []
if len(self.size_list) > 0: # size list specified
for x in range(len(self.size_list)):
self.inv_list.append(pinv(size=self.size_list[x], height=self.height))
temp_inv = factory.create(module_type="pinv", size=self.size_list[x], height=self.height)
self.inv_list.append(temp_inv)
self.add_mod(self.inv_list[x])
else: # find inv sizes
for x in range(len(self.calc_size_list)):
self.inv_list.append(pinv(size=self.calc_size_list[x], height=self.height))
temp_inv = factory.create(module_type="pinv", size=self.calc_size_list[x], height=self.height)
self.inv_list.append(temp_inv)
self.add_mod(self.inv_list[x])

View File

@ -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):

View File

@ -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):

View File

@ -4,16 +4,14 @@ from tech import drc
from math import log
from vector import vector
from globals import OPTS
from pinv import pinv
from sram_factory import factory
class pinvbuf(design.design):
"""
This is a simple inverter/buffer used for driving loads. It is
used in the column decoder for 1:2 decoding and as the clock buffer.
"""
unique_id = 1
def __init__(self, driver_size=4, height=None, name=""):
def __init__(self, name, size=4, height=None):
self.stage_effort = 4
self.row_height = height
@ -22,11 +20,8 @@ class pinvbuf(design.design):
# stage effort of 4 or less
# The pinvbuf has a FO of 2 for the first stage, so the second stage
# should be sized "half" to prevent loading of the first stage
self.driver_size = driver_size
self.predriver_size = max(int(self.driver_size/(self.stage_effort/2)),1)
if name=="":
name = "pinvbuf_{0}_{1}_{2}".format(self.predriver_size, self.driver_size, pinvbuf.unique_id)
pinvbuf.unique_id += 1
self.size = size
self.predriver_size = max(int(self.size/(self.stage_effort/2)),1)
design.design.__init__(self, name)
debug.info(1, "Creating {}".format(self.name))
@ -65,13 +60,13 @@ class pinvbuf(design.design):
# Shield the cap, but have at least a stage effort of 4
input_size = max(1,int(self.predriver_size/self.stage_effort))
self.inv = pinv(size=input_size, height=self.row_height)
self.inv = factory.create(module_type="pinv", size=input_size, height=self.row_height)
self.add_mod(self.inv)
self.inv1 = pinv(size=self.predriver_size, height=self.row_height)
self.inv1 = factory.create(module_type="pinv", size=self.predriver_size, height=self.row_height)
self.add_mod(self.inv1)
self.inv2 = pinv(size=self.driver_size, height=self.row_height)
self.inv2 = factory.create(module_type="pinv", size=self.size, height=self.row_height)
self.add_mod(self.inv2)
def create_insts(self):
@ -217,4 +212,4 @@ class pinvbuf(design.design):
stage3 = self.inv2.get_effort_stage(external_cout, last_stage_is_rise)
stage_effort_list.append(stage3)
return stage_effort_list
return stage_effort_list

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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")

View File

@ -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)

View File

@ -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

View File

@ -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.")

78
compiler/sram_factory.py Normal file
View File

@ -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()

View File

@ -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

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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)

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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)

View File

@ -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)

View File

@ -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