mirror of https://github.com/VLSIDA/OpenRAM.git
merge dev
This commit is contained in:
commit
bcc956ecdc
|
|
@ -32,13 +32,13 @@ class functional(simulation):
|
||||||
if not spfile:
|
if not spfile:
|
||||||
# self.sp_file is assigned in base class
|
# self.sp_file is assigned in base class
|
||||||
sram.sp_write(self.sp_file, trim=OPTS.trim_netlist)
|
sram.sp_write(self.sp_file, trim=OPTS.trim_netlist)
|
||||||
|
|
||||||
if not corner:
|
if not corner:
|
||||||
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||||
|
|
||||||
if period:
|
if period:
|
||||||
self.period = period
|
self.period = period
|
||||||
|
|
||||||
if not output_path:
|
if not output_path:
|
||||||
self.output_path = OPTS.openram_temp
|
self.output_path = OPTS.openram_temp
|
||||||
else:
|
else:
|
||||||
|
|
@ -63,11 +63,12 @@ class functional(simulation):
|
||||||
self.addr_spare_index = self.addr_size
|
self.addr_spare_index = self.addr_size
|
||||||
# If trim is set, specify the valid addresses
|
# If trim is set, specify the valid addresses
|
||||||
self.valid_addresses = set()
|
self.valid_addresses = set()
|
||||||
self.max_address = 2**self.addr_size - 1 + (self.num_spare_rows * self.words_per_row)
|
# Don't base off address with since we may have a couple spare columns
|
||||||
|
self.max_address = self.num_rows * self.words_per_row
|
||||||
if OPTS.trim_netlist:
|
if OPTS.trim_netlist:
|
||||||
for i in range(self.words_per_row):
|
for i in range(self.words_per_row):
|
||||||
self.valid_addresses.add(i)
|
self.valid_addresses.add(i)
|
||||||
self.valid_addresses.add(self.max_address - i)
|
self.valid_addresses.add(self.max_address - i - 1)
|
||||||
self.probe_address, self.probe_data = '0' * self.addr_size, 0
|
self.probe_address, self.probe_data = '0' * self.addr_size, 0
|
||||||
self.set_corner(corner)
|
self.set_corner(corner)
|
||||||
self.set_spice_constants()
|
self.set_spice_constants()
|
||||||
|
|
@ -87,7 +88,7 @@ class functional(simulation):
|
||||||
self.num_cycles = cycles
|
self.num_cycles = cycles
|
||||||
# This is to have ordered keys for random selection
|
# This is to have ordered keys for random selection
|
||||||
self.stored_words = collections.OrderedDict()
|
self.stored_words = collections.OrderedDict()
|
||||||
self.stored_spares = collections.OrderedDict()
|
self.stored_spares = collections.OrderedDict()
|
||||||
self.read_check = []
|
self.read_check = []
|
||||||
self.read_results = []
|
self.read_results = []
|
||||||
|
|
||||||
|
|
@ -128,11 +129,12 @@ class functional(simulation):
|
||||||
name))
|
name))
|
||||||
|
|
||||||
def create_random_memory_sequence(self):
|
def create_random_memory_sequence(self):
|
||||||
|
# Select randomly, but have 3x more reads to increase probability
|
||||||
if self.write_size:
|
if self.write_size:
|
||||||
rw_ops = ["noop", "write", "partial_write", "read"]
|
rw_ops = ["noop", "write", "partial_write", "read", "read", "read"]
|
||||||
w_ops = ["noop", "write", "partial_write"]
|
w_ops = ["noop", "write", "partial_write"]
|
||||||
else:
|
else:
|
||||||
rw_ops = ["noop", "write", "read"]
|
rw_ops = ["noop", "write", "read", "read", "read"]
|
||||||
w_ops = ["noop", "write"]
|
w_ops = ["noop", "write"]
|
||||||
r_ops = ["noop", "read"]
|
r_ops = ["noop", "read"]
|
||||||
|
|
||||||
|
|
@ -295,13 +297,37 @@ class functional(simulation):
|
||||||
self.read_results.append([sp_read_value, dout_port, eo_period, check_count])
|
self.read_results.append([sp_read_value, dout_port, eo_period, check_count])
|
||||||
return (1, "SUCCESS")
|
return (1, "SUCCESS")
|
||||||
|
|
||||||
|
def format_value(self, value):
|
||||||
|
""" Format in better readable manner """
|
||||||
|
|
||||||
|
def delineate(word):
|
||||||
|
# Create list of chars in reverse order
|
||||||
|
split_word = list(reversed([x for x in word]))
|
||||||
|
# Add underscore every 4th char
|
||||||
|
split_word2 = [x + '_' * (n != 0 and n % 4 == 0) for n, x in enumerate(split_word)]
|
||||||
|
# Join the word unreversed back together
|
||||||
|
new_word = ''.join(reversed(split_word2))
|
||||||
|
return(new_word)
|
||||||
|
|
||||||
|
# Split extra cols
|
||||||
|
vals = value[:-self.num_spare_cols]
|
||||||
|
spare_vals = value[-self.num_spare_cols:]
|
||||||
|
|
||||||
|
# Insert underscores
|
||||||
|
vals = delineate(vals)
|
||||||
|
spare_vals = delineate(spare_vals)
|
||||||
|
|
||||||
|
return vals + "+" + spare_vals
|
||||||
|
|
||||||
def check_stim_results(self):
|
def check_stim_results(self):
|
||||||
for i in range(len(self.read_check)):
|
for i in range(len(self.read_check)):
|
||||||
if self.read_check[i][0] != self.read_results[i][0]:
|
if self.read_check[i][0] != self.read_results[i][0]:
|
||||||
|
read_val = self.format_value(self.read_results[i][0])
|
||||||
|
correct_val = self.format_value(self.read_check[i][0])
|
||||||
str = "FAILED: {0} read value {1} does not match written value {2} during cycle {3} at time {4}n"
|
str = "FAILED: {0} read value {1} does not match written value {2} during cycle {3} at time {4}n"
|
||||||
error = str.format(self.read_results[i][1],
|
error = str.format(self.read_results[i][1],
|
||||||
self.read_results[i][0],
|
read_val,
|
||||||
self.read_check[i][0],
|
correct_val,
|
||||||
int((self.read_results[i][2] - self.period) / self.period),
|
int((self.read_results[i][2] - self.period) / self.period),
|
||||||
self.read_results[i][2])
|
self.read_results[i][2])
|
||||||
return(0, error)
|
return(0, error)
|
||||||
|
|
@ -483,5 +509,3 @@ class functional(simulation):
|
||||||
qbar_name = cell_name + OPTS.hier_seperator + str(storage_names[1])
|
qbar_name = cell_name + OPTS.hier_seperator + str(storage_names[1])
|
||||||
|
|
||||||
return (q_name, qbar_name)
|
return (q_name, qbar_name)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,8 @@ class simulation():
|
||||||
self.read_ports = self.sram.read_ports
|
self.read_ports = self.sram.read_ports
|
||||||
self.write_ports = self.sram.write_ports
|
self.write_ports = self.sram.write_ports
|
||||||
self.words_per_row = self.sram.words_per_row
|
self.words_per_row = self.sram.words_per_row
|
||||||
|
self.num_rows = self.sram.num_rows
|
||||||
|
self.num_cols = self.sram.num_cols
|
||||||
if self.write_size:
|
if self.write_size:
|
||||||
self.num_wmasks = int(math.ceil(self.word_size / self.write_size))
|
self.num_wmasks = int(math.ceil(self.word_size / self.write_size))
|
||||||
else:
|
else:
|
||||||
|
|
@ -536,7 +538,7 @@ class simulation():
|
||||||
if self.words_per_row > 1:
|
if self.words_per_row > 1:
|
||||||
self.sram.graph_clear_column_mux(port)
|
self.sram.graph_clear_column_mux(port)
|
||||||
self.sram.graph_exclude_column_mux(self.bitline_column, port)
|
self.sram.graph_exclude_column_mux(self.bitline_column, port)
|
||||||
|
|
||||||
# Generate new graph every analysis as edges might change depending on test bit
|
# Generate new graph every analysis as edges might change depending on test bit
|
||||||
self.graph = graph_util.timing_graph()
|
self.graph = graph_util.timing_graph()
|
||||||
self.sram_instance_name = "X{}".format(self.sram.name)
|
self.sram_instance_name = "X{}".format(self.sram.name)
|
||||||
|
|
|
||||||
|
|
@ -374,10 +374,11 @@ class stimuli():
|
||||||
else:
|
else:
|
||||||
mpi_cmd = ""
|
mpi_cmd = ""
|
||||||
|
|
||||||
cmd = "{0} {1} -o {3}timing.lis {2}".format(mpi_cmd,
|
# Xyce can save a raw file while doing timing, so keep it around
|
||||||
OPTS.spice_exe,
|
cmd = "{0} {1} -r {3}timing.raw -o {3}timing.lis {2}".format(mpi_cmd,
|
||||||
temp_stim,
|
OPTS.spice_exe,
|
||||||
OPTS.openram_temp)
|
temp_stim,
|
||||||
|
OPTS.openram_temp)
|
||||||
|
|
||||||
valid_retcode=0
|
valid_retcode=0
|
||||||
else:
|
else:
|
||||||
|
|
@ -399,7 +400,7 @@ class stimuli():
|
||||||
spice_stdout = open("{0}spice_stdout.log".format(OPTS.openram_temp), 'w')
|
spice_stdout = open("{0}spice_stdout.log".format(OPTS.openram_temp), 'w')
|
||||||
spice_stderr = open("{0}spice_stderr.log".format(OPTS.openram_temp), 'w')
|
spice_stderr = open("{0}spice_stderr.log".format(OPTS.openram_temp), 'w')
|
||||||
|
|
||||||
debug.info(3, cmd)
|
debug.info(2, cmd)
|
||||||
retcode = subprocess.call(cmd, stdout=spice_stdout, stderr=spice_stderr, shell=True)
|
retcode = subprocess.call(cmd, stdout=spice_stdout, stderr=spice_stderr, shell=True)
|
||||||
|
|
||||||
spice_stdout.close()
|
spice_stdout.close()
|
||||||
|
|
|
||||||
|
|
@ -160,6 +160,8 @@ class bitcell_base_array(design.design):
|
||||||
for row in range(self.row_size):
|
for row in range(self.row_size):
|
||||||
for col in range(self.column_size):
|
for col in range(self.column_size):
|
||||||
inst = self.cell_inst[row, col]
|
inst = self.cell_inst[row, col]
|
||||||
|
for pin_name in ["vdd", "gnd"]:
|
||||||
|
self.copy_layout_pin(inst, pin_name)
|
||||||
if row == 2: #add only 1 label per col
|
if row == 2: #add only 1 label per col
|
||||||
for pin_name in ["vdd", "gnd"]:
|
for pin_name in ["vdd", "gnd"]:
|
||||||
self.copy_layout_pin(inst, pin_name)
|
self.copy_layout_pin(inst, pin_name)
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,6 @@ import debug
|
||||||
from math import log, sqrt, ceil
|
from math import log, sqrt, ceil
|
||||||
from globals import OPTS
|
from globals import OPTS
|
||||||
from sram_factory import factory
|
from sram_factory import factory
|
||||||
from tech import array_row_multiple
|
|
||||||
from tech import array_col_multiple
|
|
||||||
|
|
||||||
|
|
||||||
class sram_config:
|
class sram_config:
|
||||||
|
|
@ -24,6 +22,18 @@ class sram_config:
|
||||||
self.num_spare_rows = num_spare_rows
|
self.num_spare_rows = num_spare_rows
|
||||||
self.num_spare_cols = num_spare_cols
|
self.num_spare_cols = num_spare_cols
|
||||||
|
|
||||||
|
try:
|
||||||
|
from tech import array_row_multiple
|
||||||
|
self.array_row_multiple = array_row_multiple
|
||||||
|
except ImportError:
|
||||||
|
self.array_row_multiple = 1
|
||||||
|
try:
|
||||||
|
from tech import array_col_multiple
|
||||||
|
self.array_col_multiple = array_col_multiple
|
||||||
|
except ImportError:
|
||||||
|
self.array_col_multiple = 1
|
||||||
|
|
||||||
|
|
||||||
# This will get over-written when we determine the organization
|
# This will get over-written when we determine the organization
|
||||||
self.words_per_row = words_per_row
|
self.words_per_row = words_per_row
|
||||||
|
|
||||||
|
|
@ -69,7 +79,6 @@ class sram_config:
|
||||||
OPTS.words_per_row = self.words_per_row
|
OPTS.words_per_row = self.words_per_row
|
||||||
debug.info(1, "Set SRAM Words Per Row={}".format(OPTS.words_per_row))
|
debug.info(1, "Set SRAM Words Per Row={}".format(OPTS.words_per_row))
|
||||||
|
|
||||||
|
|
||||||
def recompute_sizes(self):
|
def recompute_sizes(self):
|
||||||
"""
|
"""
|
||||||
Calculate the auxiliary values assuming fixed number of words per row.
|
Calculate the auxiliary values assuming fixed number of words per row.
|
||||||
|
|
@ -100,11 +109,11 @@ class sram_config:
|
||||||
|
|
||||||
num_ports = OPTS.num_rw_ports + OPTS.num_r_ports + OPTS.num_w_ports
|
num_ports = OPTS.num_rw_ports + OPTS.num_r_ports + OPTS.num_w_ports
|
||||||
if num_ports == 1:
|
if num_ports == 1:
|
||||||
if ((self.num_cols + num_ports + self.num_spare_cols) % array_col_multiple != 0):
|
if ((self.num_cols + num_ports + self.num_spare_cols) % self.array_col_multiple != 0):
|
||||||
debug.error("Invalid number of cols including rbl(s): {}. Total cols must be divisible by {}".format(self.num_cols + num_ports + self.num_spare_cols, array_col_multiple), -1)
|
debug.error("Invalid number of cols including rbl(s): {}. Total cols must be divisible by {}".format(self.num_cols + num_ports + self.num_spare_cols, self.array_col_multiple), -1)
|
||||||
|
|
||||||
if ((self.num_rows + num_ports) % array_row_multiple != 0):
|
if ((self.num_rows + num_ports) % self.array_row_multiple != 0):
|
||||||
debug.error("invalid number of rows including dummy row(s): {}. Total cols must be divisible by {}".format(self.num_rows + num_ports, array_row_multiple), -1)
|
debug.error("invalid number of rows including dummy row(s): {}. Total cols must be divisible by {}".format(self.num_rows + num_ports, self.array_row_multiple), -1)
|
||||||
|
|
||||||
def estimate_words_per_row(self, tentative_num_cols, word_size):
|
def estimate_words_per_row(self, tentative_num_cols, word_size):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -465,6 +465,3 @@ lvs_name = "calibre"
|
||||||
pex_name = "calibre"
|
pex_name = "calibre"
|
||||||
|
|
||||||
blackbox_bitcell = False
|
blackbox_bitcell = False
|
||||||
|
|
||||||
array_row_multiple = 1
|
|
||||||
array_col_multiple = 1
|
|
||||||
|
|
@ -412,6 +412,3 @@ lvs_name = "netgen"
|
||||||
pex_name = "magic"
|
pex_name = "magic"
|
||||||
|
|
||||||
blackbox_bitcell = False
|
blackbox_bitcell = False
|
||||||
|
|
||||||
array_row_multiple = 1
|
|
||||||
array_col_multiple = 1
|
|
||||||
Loading…
Reference in New Issue