mirror of https://github.com/VLSIDA/OpenRAM.git
Cleanup some items with new sram_config. Update unit tests accordingly.
This commit is contained in:
parent
9d8d2b65e4
commit
a346bddd88
|
|
@ -116,6 +116,11 @@ def init_openram(config_file, is_unit_test=True):
|
||||||
|
|
||||||
import_tech()
|
import_tech()
|
||||||
|
|
||||||
|
init_paths()
|
||||||
|
|
||||||
|
# This depends on the tech, so do it after tech is loaded
|
||||||
|
init_config()
|
||||||
|
|
||||||
# Reset the static duplicate name checker for unit tests.
|
# Reset the static duplicate name checker for unit tests.
|
||||||
import hierarchy_design
|
import hierarchy_design
|
||||||
hierarchy_design.hierarchy_design.name_map=[]
|
hierarchy_design.hierarchy_design.name_map=[]
|
||||||
|
|
@ -229,15 +234,6 @@ def read_config(config_file, is_unit_test=True):
|
||||||
OPTS.num_r_ports,
|
OPTS.num_r_ports,
|
||||||
OPTS.tech_name)
|
OPTS.tech_name)
|
||||||
|
|
||||||
# Don't delete the output dir, it may have other files!
|
|
||||||
# make the directory if it doesn't exist
|
|
||||||
try:
|
|
||||||
os.makedirs(OPTS.output_path, 0o750)
|
|
||||||
except OSError as e:
|
|
||||||
if e.errno == 17: # errno.EEXIST
|
|
||||||
os.chmod(OPTS.output_path, 0o750)
|
|
||||||
except:
|
|
||||||
debug.error("Unable to make output directory.",-1)
|
|
||||||
|
|
||||||
|
|
||||||
def end_openram():
|
def end_openram():
|
||||||
|
|
@ -299,12 +295,6 @@ def setup_paths():
|
||||||
|
|
||||||
cleanup_paths()
|
cleanup_paths()
|
||||||
|
|
||||||
# make the directory if it doesn't exist
|
|
||||||
try:
|
|
||||||
os.makedirs(OPTS.openram_temp, 0o750)
|
|
||||||
except OSError as e:
|
|
||||||
if e.errno == 17: # errno.EEXIST
|
|
||||||
os.chmod(OPTS.openram_temp, 0o750)
|
|
||||||
|
|
||||||
|
|
||||||
def is_exe(fpath):
|
def is_exe(fpath):
|
||||||
|
|
@ -321,6 +311,36 @@ def find_exe(check_exe):
|
||||||
return exe
|
return exe
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def init_paths():
|
||||||
|
""" Create the temp and output directory if it doesn't exist """
|
||||||
|
|
||||||
|
# make the directory if it doesn't exist
|
||||||
|
try:
|
||||||
|
os.makedirs(OPTS.openram_temp, 0o750)
|
||||||
|
except OSError as e:
|
||||||
|
if e.errno == 17: # errno.EEXIST
|
||||||
|
os.chmod(OPTS.openram_temp, 0o750)
|
||||||
|
|
||||||
|
# Don't delete the output dir, it may have other files!
|
||||||
|
# make the directory if it doesn't exist
|
||||||
|
try:
|
||||||
|
os.makedirs(OPTS.output_path, 0o750)
|
||||||
|
except OSError as e:
|
||||||
|
if e.errno == 17: # errno.EEXIST
|
||||||
|
os.chmod(OPTS.output_path, 0o750)
|
||||||
|
except:
|
||||||
|
debug.error("Unable to make output directory.",-1)
|
||||||
|
|
||||||
|
def init_config():
|
||||||
|
""" Initialize the SRAM configurations. """
|
||||||
|
# Create the SRAM configuration
|
||||||
|
from sram_config import sram_config
|
||||||
|
OPTS.sram_config = sram_config(OPTS.word_size,
|
||||||
|
OPTS.num_words,
|
||||||
|
OPTS.num_banks)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# imports correct technology directories for testing
|
# imports correct technology directories for testing
|
||||||
def import_tech():
|
def import_tech():
|
||||||
global OPTS
|
global OPTS
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,10 @@ class bank(design.design):
|
||||||
debug.info(2, "create sram of size {0} with {1} words".format(self.word_size,self.num_words))
|
debug.info(2, "create sram of size {0} with {1} words".format(self.word_size,self.num_words))
|
||||||
|
|
||||||
|
|
||||||
|
self.total_write = OPTS.num_rw_ports + OPTS.num_w_ports
|
||||||
|
self.total_read = OPTS.num_rw_ports + OPTS.num_r_ports
|
||||||
|
self.total_ports = OPTS.num_rw_ports + OPTS.num_w_ports + OPTS.num_r_ports
|
||||||
|
|
||||||
# The local control signals are gated when we have bank select logic,
|
# The local control signals are gated when we have bank select logic,
|
||||||
# so this prefix will be added to all of the input signals to create
|
# so this prefix will be added to all of the input signals to create
|
||||||
# the internal gated signals.
|
# the internal gated signals.
|
||||||
|
|
|
||||||
|
|
@ -130,7 +130,7 @@ class hierarchical_decoder(design.design):
|
||||||
self.total_number_of_predecoder_outputs = 4*self.no_of_pre2x4 + 8*self.no_of_pre3x8
|
self.total_number_of_predecoder_outputs = 4*self.no_of_pre2x4 + 8*self.no_of_pre3x8
|
||||||
else:
|
else:
|
||||||
self.total_number_of_predecoder_outputs = 0
|
self.total_number_of_predecoder_outputs = 0
|
||||||
debug.error("Not enough rows for a hierarchical decoder. Non-hierarchical not supported yet.",-1)
|
debug.error("Not enough rows ({}) for a hierarchical decoder. Non-hierarchical not supported yet.".format(self.num_inputs),-1)
|
||||||
|
|
||||||
# Calculates height and width of pre-decoder,
|
# Calculates height and width of pre-decoder,
|
||||||
if self.no_of_pre3x8 > 0:
|
if self.no_of_pre3x8 > 0:
|
||||||
|
|
|
||||||
|
|
@ -52,14 +52,13 @@ print(*output_files,sep="\n")
|
||||||
start_time = datetime.datetime.now()
|
start_time = datetime.datetime.now()
|
||||||
print_time("Start",start_time)
|
print_time("Start",start_time)
|
||||||
|
|
||||||
|
# Configure the SRAM organization
|
||||||
c = sram_config(word_size=OPTS.word_size,
|
c = sram_config(word_size=OPTS.word_size,
|
||||||
num_words=OPTS.num_words,
|
num_words=OPTS.num_words)
|
||||||
num_rw_ports=OPTS.num_rw_ports,
|
|
||||||
num_w_ports=OPTS.num_w_ports,
|
|
||||||
num_r_ports=OPTS.num_r_ports)
|
|
||||||
|
|
||||||
# import SRAM test generation
|
# import SRAM test generation
|
||||||
s = sram(c, OPTS.output_name)
|
s = sram(sram_config=c,
|
||||||
|
name=OPTS.output_name)
|
||||||
|
|
||||||
# Output the files for the resulting SRAM
|
# Output the files for the resulting SRAM
|
||||||
s.save()
|
s.save()
|
||||||
|
|
|
||||||
|
|
@ -55,11 +55,17 @@ class options(optparse.Values):
|
||||||
num_rw_ports = 1
|
num_rw_ports = 1
|
||||||
num_r_ports = 0
|
num_r_ports = 0
|
||||||
num_w_ports = 0
|
num_w_ports = 0
|
||||||
|
|
||||||
# These will get initialized by the the file
|
# These will get initialized by the the file
|
||||||
supply_voltages = ""
|
supply_voltages = ""
|
||||||
temperatures = ""
|
temperatures = ""
|
||||||
process_corners = ""
|
process_corners = ""
|
||||||
|
|
||||||
|
# These are the main configuration parameters that should be over-ridden
|
||||||
|
# in a configuration file.
|
||||||
|
#num_words = 0
|
||||||
|
#num_banks = 1
|
||||||
|
#word_size = 0
|
||||||
|
|
||||||
# These are the default modules that can be over-riden
|
# These are the default modules that can be over-riden
|
||||||
decoder = "hierarchical_decoder"
|
decoder = "hierarchical_decoder"
|
||||||
|
|
|
||||||
|
|
@ -16,17 +16,17 @@ class pbitcell(pgate.pgate):
|
||||||
width = None
|
width = None
|
||||||
height = None
|
height = None
|
||||||
|
|
||||||
def __init__(self, num_rw_ports=OPTS.num_rw_ports, num_w_ports=OPTS.num_w_ports, num_r_ports=OPTS.num_r_ports):
|
def __init__(self):
|
||||||
|
|
||||||
name = "pbitcell_{0}RW_{1}W_{2}R".format(num_rw_ports, num_w_ports, num_r_ports)
|
self.num_rw_ports = OPTS.num_rw_ports
|
||||||
|
self.num_w_ports = OPTS.num_w_ports
|
||||||
|
self.num_r_ports = OPTS.num_r_ports
|
||||||
|
|
||||||
|
name = "pbitcell_{0}RW_{1}W_{2}R".format(self.num_rw_ports, self.num_w_ports, self.num_r_ports)
|
||||||
pgate.pgate.__init__(self, name)
|
pgate.pgate.__init__(self, name)
|
||||||
debug.info(2, "create a multi-port bitcell with {0} rw ports, {1} w ports and {2} r ports".format(num_rw_ports,
|
debug.info(2, "create a multi-port bitcell with {0} rw ports, {1} w ports and {2} r ports".format(self.num_rw_ports,
|
||||||
num_w_ports,
|
self.num_w_ports,
|
||||||
num_r_ports))
|
self.num_r_ports))
|
||||||
|
|
||||||
self.num_rw_ports = num_rw_ports
|
|
||||||
self.num_w_ports = num_w_ports
|
|
||||||
self.num_r_ports = num_r_ports
|
|
||||||
|
|
||||||
self.create_netlist()
|
self.create_netlist()
|
||||||
if not OPTS.netlist_only:
|
if not OPTS.netlist_only:
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,9 @@ class sram():
|
||||||
results.
|
results.
|
||||||
We can later add visualizer and other high-level functions as needed.
|
We can later add visualizer and other high-level functions as needed.
|
||||||
"""
|
"""
|
||||||
def __init__(self, sram_config, name="sram"):
|
def __init__(self, sram_config, name):
|
||||||
|
|
||||||
|
sram_config.compute_sizes()
|
||||||
sram_config.set_local_config(self)
|
sram_config.set_local_config(self)
|
||||||
|
|
||||||
# reset the static duplicate name checker for unit tests
|
# reset the static duplicate name checker for unit tests
|
||||||
|
|
@ -27,6 +28,8 @@ class sram():
|
||||||
start_time = datetime.datetime.now()
|
start_time = datetime.datetime.now()
|
||||||
|
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
|
|
||||||
if self.num_banks == 1:
|
if self.num_banks == 1:
|
||||||
from sram_1bank import sram_1bank as sram
|
from sram_1bank import sram_1bank as sram
|
||||||
elif self.num_banks == 2:
|
elif self.num_banks == 2:
|
||||||
|
|
@ -36,7 +39,7 @@ class sram():
|
||||||
else:
|
else:
|
||||||
debug.error("Invalid number of banks.",-1)
|
debug.error("Invalid number of banks.",-1)
|
||||||
|
|
||||||
self.s = sram(sram_config, name)
|
self.s = sram(name, sram_config)
|
||||||
self.s.create_netlist()
|
self.s.create_netlist()
|
||||||
if not OPTS.netlist_only:
|
if not OPTS.netlist_only:
|
||||||
self.s.create_layout()
|
self.s.create_layout()
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,11 @@ class sram_1bank(sram_base):
|
||||||
"""
|
"""
|
||||||
Procedures specific to a one bank SRAM.
|
Procedures specific to a one bank SRAM.
|
||||||
"""
|
"""
|
||||||
def __init__(self, sram_config, name):
|
def __init__(self, name, sram_config):
|
||||||
sram_base.__init__(self, sram_config, name)
|
sram_base.__init__(self, name, sram_config)
|
||||||
|
|
||||||
|
|
||||||
def create_netlist(self):
|
def create_netlist(self):
|
||||||
self.compute_sizes()
|
|
||||||
sram_base.create_netlist(self)
|
sram_base.create_netlist(self)
|
||||||
self.create_modules()
|
self.create_modules()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ class sram_2bank(sram_base):
|
||||||
"""
|
"""
|
||||||
Procedures specific to a two bank SRAM.
|
Procedures specific to a two bank SRAM.
|
||||||
"""
|
"""
|
||||||
def __init__(self, sram_config, name):
|
def __init__(self, name, sram_config):
|
||||||
sram_base.__init__(self, sram_config, name)
|
sram_base.__init__(self, name, sram_config)
|
||||||
|
|
||||||
def compute_bank_offsets(self):
|
def compute_bank_offsets(self):
|
||||||
""" Compute the overall offsets for a two bank SRAM """
|
""" Compute the overall offsets for a two bank SRAM """
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ class sram_4bank(sram_base):
|
||||||
"""
|
"""
|
||||||
Procedures specific to a four bank SRAM.
|
Procedures specific to a four bank SRAM.
|
||||||
"""
|
"""
|
||||||
def __init__(self, sram_config, name):
|
def __init__(self, name, sram_config):
|
||||||
sram_base.__init__(self, sram_config, name)
|
sram_base.__init__(self, name, sram_config)
|
||||||
|
|
||||||
def compute_bank_offsets(self):
|
def compute_bank_offsets(self):
|
||||||
""" Compute the overall offsets for a four bank SRAM """
|
""" Compute the overall offsets for a four bank SRAM """
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ import datetime
|
||||||
import getpass
|
import getpass
|
||||||
import debug
|
import debug
|
||||||
from importlib import reload
|
from importlib import reload
|
||||||
from math import log,sqrt,ceil
|
|
||||||
from vector import vector
|
from vector import vector
|
||||||
from globals import OPTS, print_time
|
from globals import OPTS, print_time
|
||||||
|
|
||||||
|
|
@ -14,85 +13,14 @@ class sram_base(design):
|
||||||
Dynamically generated SRAM by connecting banks to control logic. The
|
Dynamically generated SRAM by connecting banks to control logic. The
|
||||||
number of banks should be 1 , 2 or 4
|
number of banks should be 1 , 2 or 4
|
||||||
"""
|
"""
|
||||||
def __init__(self, sram_config, name):
|
def __init__(self, name, sram_config):
|
||||||
design.__init__(self, name)
|
design.__init__(self, name)
|
||||||
|
|
||||||
# This is used to compute the sizes of the SRAM
|
|
||||||
# and must be loaded before netlist creation
|
|
||||||
c = reload(__import__(OPTS.bitcell))
|
|
||||||
self.mod_bitcell = getattr(c, OPTS.bitcell)
|
|
||||||
self.bitcell = self.mod_bitcell()
|
|
||||||
|
|
||||||
self.sram_config = sram_config
|
self.sram_config = sram_config
|
||||||
self.sram_config.set_local_config(self)
|
sram_config.set_local_config(self)
|
||||||
|
|
||||||
self.bank_insts = []
|
self.bank_insts = []
|
||||||
|
|
||||||
def compute_sizes(self):
|
|
||||||
""" Computes the organization of the memory using bitcell size by trying to make it square."""
|
|
||||||
|
|
||||||
debug.check(self.num_banks in [1,2,4], "Valid number of banks are 1 , 2 and 4.")
|
|
||||||
|
|
||||||
self.num_words_per_bank = self.num_words/self.num_banks
|
|
||||||
self.num_bits_per_bank = self.word_size*self.num_words_per_bank
|
|
||||||
|
|
||||||
# If this was hard coded, don't dynamically compute it!
|
|
||||||
if self.sram_config.words_per_row:
|
|
||||||
self.words_per_row = self.sram_config.words_per_row
|
|
||||||
else:
|
|
||||||
# Compute the area of the bitcells and estimate a square bank (excluding auxiliary circuitry)
|
|
||||||
self.bank_area = self.bitcell.width*self.bitcell.height*self.num_bits_per_bank
|
|
||||||
self.bank_side_length = sqrt(self.bank_area)
|
|
||||||
|
|
||||||
# Estimate the words per row given the height of the bitcell and the square side length
|
|
||||||
self.tentative_num_cols = int(self.bank_side_length/self.bitcell.width)
|
|
||||||
self.words_per_row = self.estimate_words_per_row(self.tentative_num_cols, self.word_size)
|
|
||||||
|
|
||||||
# Estimate the number of rows given the tentative words per row
|
|
||||||
self.tentative_num_rows = self.num_bits_per_bank / (self.words_per_row*self.word_size)
|
|
||||||
self.words_per_row = self.amend_words_per_row(self.tentative_num_rows, self.words_per_row)
|
|
||||||
|
|
||||||
# Fix the number of columns and rows
|
|
||||||
self.num_cols = int(self.words_per_row*self.word_size)
|
|
||||||
self.num_rows = int(self.num_words_per_bank/self.words_per_row)
|
|
||||||
|
|
||||||
# Compute the address and bank sizes
|
|
||||||
self.row_addr_size = int(log(self.num_rows, 2))
|
|
||||||
self.col_addr_size = int(log(self.words_per_row, 2))
|
|
||||||
self.bank_addr_size = self.col_addr_size + self.row_addr_size
|
|
||||||
self.addr_size = self.bank_addr_size + int(log(self.num_banks, 2))
|
|
||||||
|
|
||||||
self.sram_config.words_per_row = self.words_per_row
|
|
||||||
debug.info(1,"Words per row: {}".format(self.words_per_row))
|
|
||||||
|
|
||||||
def estimate_words_per_row(self,tentative_num_cols, word_size):
|
|
||||||
"""
|
|
||||||
This provides a heuristic rounded estimate for the number of words
|
|
||||||
per row.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if tentative_num_cols < 1.5*word_size:
|
|
||||||
return 1
|
|
||||||
elif tentative_num_cols > 3*word_size:
|
|
||||||
return 4
|
|
||||||
else:
|
|
||||||
return 2
|
|
||||||
|
|
||||||
def amend_words_per_row(self,tentative_num_rows, words_per_row):
|
|
||||||
"""
|
|
||||||
This picks the number of words per row more accurately by limiting
|
|
||||||
it to a minimum and maximum.
|
|
||||||
"""
|
|
||||||
# Recompute the words per row given a hard max
|
|
||||||
if(tentative_num_rows > 512):
|
|
||||||
debug.check(tentative_num_rows*words_per_row <= 2048, "Number of words exceeds 2048")
|
|
||||||
return int(words_per_row*tentative_num_rows/512)
|
|
||||||
# Recompute the words per row given a hard min
|
|
||||||
if(tentative_num_rows < 16):
|
|
||||||
debug.check(tentative_num_rows*words_per_row >= 16, "Minimum number of rows is 16, but given {0}".format(tentative_num_rows))
|
|
||||||
return int(words_per_row*tentative_num_rows/16)
|
|
||||||
|
|
||||||
return words_per_row
|
|
||||||
|
|
||||||
def add_pins(self):
|
def add_pins(self):
|
||||||
""" Add pins for entire SRAM. """
|
""" Add pins for entire SRAM. """
|
||||||
|
|
@ -270,6 +198,9 @@ class sram_base(design):
|
||||||
|
|
||||||
def add_modules(self):
|
def add_modules(self):
|
||||||
""" Create all the modules that will be used """
|
""" 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()
|
||||||
|
|
||||||
c = reload(__import__(OPTS.control_logic))
|
c = reload(__import__(OPTS.control_logic))
|
||||||
self.mod_control_logic = getattr(c, OPTS.control_logic)
|
self.mod_control_logic = getattr(c, OPTS.control_logic)
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,96 @@
|
||||||
|
import debug
|
||||||
|
from math import log,sqrt,ceil
|
||||||
|
from importlib import reload
|
||||||
from globals import OPTS
|
from globals import OPTS
|
||||||
|
|
||||||
class sram_config:
|
class sram_config:
|
||||||
""" This is a structure that is used to hold the SRAM configuration options. """
|
""" This is a structure that is used to hold the SRAM configuration options. """
|
||||||
|
|
||||||
def __init__(self, word_size, num_words, num_banks=1, num_rw_ports=OPTS.num_rw_ports, num_w_ports=OPTS.num_w_ports, num_r_ports=OPTS.num_r_ports):
|
def __init__(self, word_size, num_words, num_banks=1):
|
||||||
self.word_size = word_size
|
self.word_size = word_size
|
||||||
self.num_words = num_words
|
self.num_words = num_words
|
||||||
self.num_banks = num_banks
|
self.num_banks = num_banks
|
||||||
self.num_rw_ports = num_rw_ports
|
|
||||||
self.num_w_ports = num_w_ports
|
|
||||||
self.num_r_ports = num_r_ports
|
|
||||||
|
|
||||||
# This will get over-written when we determine the organization
|
# This will get over-written when we determine the organization
|
||||||
self.num_banks = 1
|
|
||||||
self.words_per_row = None
|
self.words_per_row = None
|
||||||
|
|
||||||
self.total_write = num_rw_ports + num_w_ports
|
# Move the module names to this?
|
||||||
self.total_read = num_rw_ports + num_r_ports
|
|
||||||
self.total_ports = num_rw_ports + num_w_ports + num_r_ports
|
|
||||||
|
|
||||||
|
|
||||||
def set_local_config(self, module):
|
def set_local_config(self, module):
|
||||||
module.word_size = self.word_size
|
""" Copy all of the member variables to the given module for convenience """
|
||||||
module.num_words = self.num_words
|
|
||||||
module.num_banks = self.num_banks
|
|
||||||
module.num_rw_ports = self.num_rw_ports
|
|
||||||
module.num_w_ports = self.num_w_ports
|
|
||||||
module.num_r_ports = self.num_r_ports
|
|
||||||
|
|
||||||
module.words_per_row = self.words_per_row
|
members = [attr for attr in dir(self) if not callable(getattr(self, attr)) and not attr.startswith("__")]
|
||||||
|
|
||||||
module.total_write = self.total_write
|
# Copy all the variables to the local module
|
||||||
module.total_read = self.total_read
|
for member in members:
|
||||||
module.total_ports = self.total_ports
|
setattr(module,member,getattr(self,member))
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
|
||||||
|
debug.check(self.num_banks in [1,2,4], "Valid number of banks are 1 , 2 and 4.")
|
||||||
|
|
||||||
|
self.num_words_per_bank = self.num_words/self.num_banks
|
||||||
|
self.num_bits_per_bank = self.word_size*self.num_words_per_bank
|
||||||
|
|
||||||
|
# If this was hard coded, don't dynamically compute it!
|
||||||
|
if not self.words_per_row:
|
||||||
|
# Compute the area of the bitcells and estimate a square bank (excluding auxiliary circuitry)
|
||||||
|
self.bank_area = self.bitcell.width*self.bitcell.height*self.num_bits_per_bank
|
||||||
|
self.bank_side_length = sqrt(self.bank_area)
|
||||||
|
|
||||||
|
# Estimate the words per row given the height of the bitcell and the square side length
|
||||||
|
self.tentative_num_cols = int(self.bank_side_length/self.bitcell.width)
|
||||||
|
self.words_per_row = self.estimate_words_per_row(self.tentative_num_cols, self.word_size)
|
||||||
|
|
||||||
|
# Estimate the number of rows given the tentative words per row
|
||||||
|
self.tentative_num_rows = self.num_bits_per_bank / (self.words_per_row*self.word_size)
|
||||||
|
self.words_per_row = self.amend_words_per_row(self.tentative_num_rows, self.words_per_row)
|
||||||
|
|
||||||
|
# Fix the number of columns and rows
|
||||||
|
self.num_cols = int(self.words_per_row*self.word_size)
|
||||||
|
self.num_rows = int(self.num_words_per_bank/self.words_per_row)
|
||||||
|
|
||||||
|
# Compute the address and bank sizes
|
||||||
|
self.row_addr_size = int(log(self.num_rows, 2))
|
||||||
|
self.col_addr_size = int(log(self.words_per_row, 2))
|
||||||
|
self.bank_addr_size = self.col_addr_size + self.row_addr_size
|
||||||
|
self.addr_size = self.bank_addr_size + int(log(self.num_banks, 2))
|
||||||
|
|
||||||
|
debug.info(1,"Words per row: {}".format(self.words_per_row))
|
||||||
|
|
||||||
|
def estimate_words_per_row(self,tentative_num_cols, word_size):
|
||||||
|
"""
|
||||||
|
This provides a heuristic rounded estimate for the number of words
|
||||||
|
per row.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if tentative_num_cols < 1.5*word_size:
|
||||||
|
return 1
|
||||||
|
elif tentative_num_cols > 3*word_size:
|
||||||
|
return 4
|
||||||
|
else:
|
||||||
|
return 2
|
||||||
|
|
||||||
|
def amend_words_per_row(self,tentative_num_rows, words_per_row):
|
||||||
|
"""
|
||||||
|
This picks the number of words per row more accurately by limiting
|
||||||
|
it to a minimum and maximum.
|
||||||
|
"""
|
||||||
|
# Recompute the words per row given a hard max
|
||||||
|
if(not OPTS.is_unit_test and tentative_num_rows > 512):
|
||||||
|
debug.check(tentative_num_rows*words_per_row <= 2048, "Number of words exceeds 2048")
|
||||||
|
return int(words_per_row*tentative_num_rows/512)
|
||||||
|
# Recompute the words per row given a hard min
|
||||||
|
if(not OPTS.is_unit_test and tentative_num_rows < 16):
|
||||||
|
debug.check(tentative_num_rows*words_per_row >= 16, "Minimum number of rows is 16, but given {0}".format(tentative_num_rows))
|
||||||
|
return int(words_per_row*tentative_num_rows/16)
|
||||||
|
|
||||||
|
return words_per_row
|
||||||
|
|
|
||||||
|
|
@ -18,47 +18,76 @@ class pbitcell_test(openram_test):
|
||||||
|
|
||||||
def runTest(self):
|
def runTest(self):
|
||||||
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
|
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
|
||||||
import pbitcell
|
from pbitcell import pbitcell
|
||||||
import tech
|
import tech
|
||||||
|
OPTS.sram_config.num_rw_ports=1
|
||||||
|
OPTS.sram_config.num_w_ports=1
|
||||||
|
OPTS.sram_config.num_r_ports=1
|
||||||
debug.info(2, "Bitcell with 1 of each port: read/write, write, and read")
|
debug.info(2, "Bitcell with 1 of each port: read/write, write, and read")
|
||||||
tx = pbitcell.pbitcell(num_rw_ports=1,num_w_ports=1,num_r_ports=1)
|
tx = pbitcell()
|
||||||
self.local_check(tx)
|
self.local_check(tx)
|
||||||
|
|
||||||
|
OPTS.sram_config.num_rw_ports=0
|
||||||
|
OPTS.sram_config.num_w_ports=1
|
||||||
|
OPTS.sram_config.num_r_ports=1
|
||||||
debug.info(2, "Bitcell with 0 read/write ports")
|
debug.info(2, "Bitcell with 0 read/write ports")
|
||||||
tx = pbitcell.pbitcell(num_rw_ports=0,num_w_ports=1,num_r_ports=1)
|
tx = pbitcell()
|
||||||
self.local_check(tx)
|
self.local_check(tx)
|
||||||
|
|
||||||
|
OPTS.sram_config.num_rw_ports=1
|
||||||
|
OPTS.sram_config.num_w_ports=0
|
||||||
|
OPTS.sram_config.num_r_ports=1
|
||||||
debug.info(2, "Bitcell with 0 write ports")
|
debug.info(2, "Bitcell with 0 write ports")
|
||||||
tx = pbitcell.pbitcell(num_rw_ports=1,num_w_ports=0,num_r_ports=1)
|
tx = pbitcell()
|
||||||
self.local_check(tx)
|
self.local_check(tx)
|
||||||
|
|
||||||
|
OPTS.sram_config.num_rw_ports=1
|
||||||
|
OPTS.sram_config.num_w_ports=1
|
||||||
|
OPTS.sram_config.num_r_ports=0
|
||||||
debug.info(2, "Bitcell with 0 read ports")
|
debug.info(2, "Bitcell with 0 read ports")
|
||||||
tx = pbitcell.pbitcell(num_rw_ports=1,num_w_ports=1,num_r_ports=0)
|
tx = pbitcell()
|
||||||
self.local_check(tx)
|
self.local_check(tx)
|
||||||
|
|
||||||
|
OPTS.sram_config.num_rw_ports=1
|
||||||
|
OPTS.sram_config.num_w_ports=0
|
||||||
|
OPTS.sram_config.num_r_ports=0
|
||||||
debug.info(2, "Bitcell with 0 read ports and 0 write ports")
|
debug.info(2, "Bitcell with 0 read ports and 0 write ports")
|
||||||
tx = pbitcell.pbitcell(num_rw_ports=1,num_w_ports=0,num_r_ports=0)
|
tx = pbitcell()
|
||||||
self.local_check(tx)
|
self.local_check(tx)
|
||||||
|
|
||||||
|
OPTS.sram_config.num_rw_ports=2
|
||||||
|
OPTS.sram_config.num_w_ports=2
|
||||||
|
OPTS.sram_config.num_r_ports=2
|
||||||
debug.info(2, "Bitcell with 2 of each port: read/write, write, and read")
|
debug.info(2, "Bitcell with 2 of each port: read/write, write, and read")
|
||||||
tx = pbitcell.pbitcell(num_rw_ports=2,num_w_ports=2,num_r_ports=2)
|
tx = pbitcell()
|
||||||
self.local_check(tx)
|
self.local_check(tx)
|
||||||
|
|
||||||
|
OPTS.sram_config.num_rw_ports=0
|
||||||
|
OPTS.sram_config.num_w_ports=2
|
||||||
|
OPTS.sram_config.num_r_ports=2
|
||||||
debug.info(2, "Bitcell with 0 read/write ports")
|
debug.info(2, "Bitcell with 0 read/write ports")
|
||||||
tx = pbitcell.pbitcell(num_rw_ports=0,num_w_ports=2,num_r_ports=2)
|
tx = pbitcell()
|
||||||
self.local_check(tx)
|
self.local_check(tx)
|
||||||
|
|
||||||
|
OPTS.sram_config.num_rw_ports=2
|
||||||
|
OPTS.sram_config.num_w_ports=0
|
||||||
|
OPTS.sram_config.num_r_ports=2
|
||||||
debug.info(2, "Bitcell with 0 write ports")
|
debug.info(2, "Bitcell with 0 write ports")
|
||||||
tx = pbitcell.pbitcell(num_rw_ports=2,num_w_ports=0,num_r_ports=2)
|
tx = pbitcell()
|
||||||
self.local_check(tx)
|
self.local_check(tx)
|
||||||
|
|
||||||
|
OPTS.sram_config.num_rw_ports=2
|
||||||
|
OPTS.sram_config.num_w_ports=2
|
||||||
|
OPTS.sram_config.num_r_ports=0
|
||||||
debug.info(2, "Bitcell with 0 read ports")
|
debug.info(2, "Bitcell with 0 read ports")
|
||||||
tx = pbitcell.pbitcell(num_rw_ports=2,num_w_ports=2,num_r_ports=0)
|
tx = pbitcell()
|
||||||
self.local_check(tx)
|
self.local_check(tx)
|
||||||
|
|
||||||
|
OPTS.sram_config.num_rw_ports=2
|
||||||
|
OPTS.sram_config.num_w_ports=0
|
||||||
|
OPTS.sram_config.num_r_ports=0
|
||||||
debug.info(2, "Bitcell with 0 read ports and 0 write ports")
|
debug.info(2, "Bitcell with 0 read ports and 0 write ports")
|
||||||
tx = pbitcell.pbitcell(num_rw_ports=2,num_w_ports=0,num_r_ports=0)
|
tx = pbitcell()
|
||||||
self.local_check(tx)
|
self.local_check(tx)
|
||||||
|
|
||||||
globals.end_openram()
|
globals.end_openram()
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ class psingle_bank_test(openram_test):
|
||||||
OPTS.num_r_ports = 1
|
OPTS.num_r_ports = 1
|
||||||
c = sram_config(word_size=4,
|
c = sram_config(word_size=4,
|
||||||
num_words=16)
|
num_words=16)
|
||||||
|
|
||||||
c.words_per_row=1
|
c.words_per_row=1
|
||||||
debug.info(1, "No column mux")
|
debug.info(1, "No column mux")
|
||||||
name = "bank1_{0}rw_{1}w_{2}r_single".format(c.num_rw_ports, c.num_w_ports, c.num_r_ports)
|
name = "bank1_{0}rw_{1}w_{2}r_single".format(c.num_rw_ports, c.num_w_ports, c.num_r_ports)
|
||||||
|
|
|
||||||
|
|
@ -21,27 +21,28 @@ class sram_1bank_test(openram_test):
|
||||||
num_words=16,
|
num_words=16,
|
||||||
num_banks=1)
|
num_banks=1)
|
||||||
|
|
||||||
|
c.words_per_row=1
|
||||||
debug.info(1, "Single bank, no column mux with control logic")
|
debug.info(1, "Single bank, no column mux with control logic")
|
||||||
a = sram(c, name="sram1")
|
a = sram(c, "sram1")
|
||||||
self.local_check(a, final_verification=True)
|
self.local_check(a, final_verification=True)
|
||||||
|
|
||||||
c.num_words=32
|
c.num_words=32
|
||||||
c.words_per_row=2
|
c.words_per_row=2
|
||||||
debug.info(1, "Single bank two way column mux with control logic")
|
debug.info(1, "Single bank two way column mux with control logic")
|
||||||
a = sram(c, name="sram2")
|
a = sram(c, "sram2")
|
||||||
self.local_check(a, final_verification=True)
|
self.local_check(a, final_verification=True)
|
||||||
|
|
||||||
c.num_words=64
|
c.num_words=64
|
||||||
c.words_per_row=4
|
c.words_per_row=4
|
||||||
debug.info(1, "Single bank, four way column mux with control logic")
|
debug.info(1, "Single bank, four way column mux with control logic")
|
||||||
a = sram(c, name="sram3")
|
a = sram(c, "sram3")
|
||||||
self.local_check(a, final_verification=True)
|
self.local_check(a, final_verification=True)
|
||||||
|
|
||||||
c.word_size=2
|
c.word_size=2
|
||||||
c.num_words=128
|
c.num_words=128
|
||||||
c.words_per_row=8
|
c.words_per_row=8
|
||||||
debug.info(1, "Single bank, eight way column mux with control logic")
|
debug.info(1, "Single bank, eight way column mux with control logic")
|
||||||
a = sram(c, name="sram4")
|
a = sram(c, "sram4")
|
||||||
self.local_check(a, final_verification=True)
|
self.local_check(a, final_verification=True)
|
||||||
|
|
||||||
globals.end_openram()
|
globals.end_openram()
|
||||||
|
|
|
||||||
|
|
@ -22,27 +22,28 @@ class sram_2bank_test(openram_test):
|
||||||
num_words=32,
|
num_words=32,
|
||||||
num_banks=2)
|
num_banks=2)
|
||||||
|
|
||||||
|
c.words_per_row=1
|
||||||
debug.info(1, "Two bank, no column mux with control logic")
|
debug.info(1, "Two bank, no column mux with control logic")
|
||||||
a = sram(c, name="sram1")
|
a = sram(c, "sram1")
|
||||||
self.local_check(a, final_verification=True)
|
self.local_check(a, final_verification=True)
|
||||||
|
|
||||||
c.num_words=64
|
c.num_words=64
|
||||||
c.words_per_row=2
|
c.words_per_row=2
|
||||||
debug.info(1, "Two bank two way column mux with control logic")
|
debug.info(1, "Two bank two way column mux with control logic")
|
||||||
a = sram(c, name="sram2")
|
a = sram(c, "sram2")
|
||||||
self.local_check(a, final_verification=True)
|
self.local_check(a, final_verification=True)
|
||||||
|
|
||||||
c.num_words=128
|
c.num_words=128
|
||||||
c.words_per_row=4
|
c.words_per_row=4
|
||||||
debug.info(1, "Two bank, four way column mux with control logic")
|
debug.info(1, "Two bank, four way column mux with control logic")
|
||||||
a = sram(c, name="sram3")
|
a = sram(c, "sram3")
|
||||||
self.local_check(a, final_verification=True)
|
self.local_check(a, final_verification=True)
|
||||||
|
|
||||||
c.word_size=2
|
c.word_size=2
|
||||||
c.num_words=256
|
c.num_words=256
|
||||||
c.words_per_row=8
|
c.words_per_row=8
|
||||||
debug.info(1, "Two bank, eight way column mux with control logic")
|
debug.info(1, "Two bank, eight way column mux with control logic")
|
||||||
a = sram(c, name="sram4")
|
a = sram(c, "sram4")
|
||||||
self.local_check(a, final_verification=True)
|
self.local_check(a, final_verification=True)
|
||||||
|
|
||||||
globals.end_openram()
|
globals.end_openram()
|
||||||
|
|
|
||||||
|
|
@ -23,26 +23,26 @@ class sram_4bank_test(openram_test):
|
||||||
num_banks=4)
|
num_banks=4)
|
||||||
|
|
||||||
debug.info(1, "Four bank, no column mux with control logic")
|
debug.info(1, "Four bank, no column mux with control logic")
|
||||||
a = sram(c, name="sram1")
|
a = sram(c, "sram1")
|
||||||
self.local_check(a, final_verification=True)
|
self.local_check(a, final_verification=True)
|
||||||
|
|
||||||
c.num_words=128
|
c.num_words=128
|
||||||
c.words_per_row=2
|
c.words_per_row=2
|
||||||
debug.info(1, "Four bank two way column mux with control logic")
|
debug.info(1, "Four bank two way column mux with control logic")
|
||||||
a = sram(c, name="sram2")
|
a = sram(c, "sram2")
|
||||||
self.local_check(a, final_verification=True)
|
self.local_check(a, final_verification=True)
|
||||||
|
|
||||||
c.num_words=256
|
c.num_words=256
|
||||||
c.words_per_row=4
|
c.words_per_row=4
|
||||||
debug.info(1, "Four bank, four way column mux with control logic")
|
debug.info(1, "Four bank, four way column mux with control logic")
|
||||||
a = sram(word_size=16, num_words=256, num_banks=4, name="sram3")
|
a = sram(c, "sram3")
|
||||||
self.local_check(a, final_verification=True)
|
self.local_check(a, final_verification=True)
|
||||||
|
|
||||||
c.word_size=2
|
c.word_size=2
|
||||||
c.num_words=256
|
c.num_words=256
|
||||||
c.words_per_row=8
|
c.words_per_row=8
|
||||||
debug.info(1, "Four bank, eight way column mux with control logic")
|
debug.info(1, "Four bank, eight way column mux with control logic")
|
||||||
a = sram.sram(word_size=2, num_words=256, num_banks=4, name="sram4")
|
a = sram.sram(c, "sram4")
|
||||||
self.local_check(a, final_verification=True)
|
self.local_check(a, final_verification=True)
|
||||||
|
|
||||||
globals.end_openram()
|
globals.end_openram()
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ class timing_sram_test(openram_test):
|
||||||
c = sram_config(word_size=1,
|
c = sram_config(word_size=1,
|
||||||
num_words=16,
|
num_words=16,
|
||||||
num_banks=1)
|
num_banks=1)
|
||||||
|
c.words_per_row=1
|
||||||
debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank")
|
debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank")
|
||||||
s = sram(c, name="sram1")
|
s = sram(c, name="sram1")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ class timing_sram_test(openram_test):
|
||||||
c = sram_config(word_size=1,
|
c = sram_config(word_size=1,
|
||||||
num_words=16,
|
num_words=16,
|
||||||
num_banks=1)
|
num_banks=1)
|
||||||
|
c.words_per_row=1
|
||||||
debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank")
|
debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank")
|
||||||
s = sram(c, name="sram1")
|
s = sram(c, name="sram1")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,9 @@ class lib_test(openram_test):
|
||||||
c = sram_config(word_size=2,
|
c = sram_config(word_size=2,
|
||||||
num_words=16,
|
num_words=16,
|
||||||
num_banks=1)
|
num_banks=1)
|
||||||
|
c.words_per_row=1
|
||||||
debug.info(1, "Testing analytical timing for sample 2 bit, 16 words SRAM with 1 bank")
|
debug.info(1, "Testing analytical timing for sample 2 bit, 16 words SRAM with 1 bank")
|
||||||
s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))
|
s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))
|
||||||
|
|
||||||
tempspice = OPTS.openram_temp + "temp.sp"
|
tempspice = OPTS.openram_temp + "temp.sp"
|
||||||
s.sp_write(tempspice)
|
s.sp_write(tempspice)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ class lib_test(openram_test):
|
||||||
c = sram_config(word_size=2,
|
c = sram_config(word_size=2,
|
||||||
num_words=16,
|
num_words=16,
|
||||||
num_banks=1)
|
num_banks=1)
|
||||||
|
c.words_per_row=1
|
||||||
debug.info(1, "Testing pruned timing for sample 2 bit, 16 words SRAM with 1 bank")
|
debug.info(1, "Testing pruned timing for sample 2 bit, 16 words SRAM with 1 bank")
|
||||||
s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))
|
s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ class lib_test(openram_test):
|
||||||
c = sram_config(word_size=2,
|
c = sram_config(word_size=2,
|
||||||
num_words=16,
|
num_words=16,
|
||||||
num_banks=1)
|
num_banks=1)
|
||||||
|
c.words_per_row=1
|
||||||
debug.info(1, "Testing timing for sample 2 bit, 16 words SRAM with 1 bank")
|
debug.info(1, "Testing timing for sample 2 bit, 16 words SRAM with 1 bank")
|
||||||
s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))
|
s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ class lef_test(openram_test):
|
||||||
c = sram_config(word_size=2,
|
c = sram_config(word_size=2,
|
||||||
num_words=16,
|
num_words=16,
|
||||||
num_banks=1)
|
num_banks=1)
|
||||||
|
c.words_per_row=1
|
||||||
debug.info(1, "Testing LEF for sample 2 bit, 16 words SRAM with 1 bank")
|
debug.info(1, "Testing LEF for sample 2 bit, 16 words SRAM with 1 bank")
|
||||||
s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))
|
s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ class verilog_test(openram_test):
|
||||||
c = sram_config(word_size=2,
|
c = sram_config(word_size=2,
|
||||||
num_words=16,
|
num_words=16,
|
||||||
num_banks=1)
|
num_banks=1)
|
||||||
|
c.words_per_row=1
|
||||||
debug.info(1, "Testing Verilog for sample 2 bit, 16 words SRAM with 1 bank")
|
debug.info(1, "Testing Verilog for sample 2 bit, 16 words SRAM with 1 bank")
|
||||||
s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))
|
s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue