Added additional graphing and data collection to script

This commit is contained in:
Hunter Nichols 2019-02-26 20:06:35 -08:00
parent 8c1fe253d5
commit 42bc6efb21
2 changed files with 358 additions and 34 deletions

View File

@ -26,30 +26,34 @@ class model_check(delay):
def create_data_names(self):
self.wl_meas_name, self.wl_model_name = "wl_measures", "wl_model"
self.sae_meas_name, self.sae_model_name = "sae_measures", "sae_model"
self.wl_slew_name, self.sae_slew_name = "wl_slews", "sae_slews"
def create_measurement_names(self):
"""Create measurement names. The names themselves currently define the type of measurement"""
#Create delay measurement names
wl_en_driver_delay_names = ["delay_wl_en_dvr{}_".format(stage) for stage in range(1,self.get_num_wl_en_driver_stages())]
wl_driver_delay_names = ["delay_wl_dvr{}_".format(stage) for stage in range(1,self.get_num_wl_driver_stages())]
sen_driver_delay_names = ["delay_sen_dvr{}_".format(stage) for stage in range(1,self.get_num_sen_driver_stages())]
dc_delay_names = ["delay_delay_chain_stage{}_".format(stage) for stage in range(1,self.get_num_delay_stages()+1)]
wl_en_driver_delay_names = ["delay_wl_en_dvr_{}".format(stage) for stage in range(1,self.get_num_wl_en_driver_stages())]
wl_driver_delay_names = ["delay_wl_dvr_{}".format(stage) for stage in range(1,self.get_num_wl_driver_stages())]
sen_driver_delay_names = ["delay_sen_dvr_{}".format(stage) for stage in range(1,self.get_num_sen_driver_stages())]
dc_delay_names = ["delay_delay_chain_stage_{}".format(stage) for stage in range(1,self.get_num_delay_stages()+1)]
self.wl_delay_meas_names = wl_en_driver_delay_names+["delay_wl_en", "delay_wl_bar"]+wl_driver_delay_names+["delay_wl"]
self.rbl_delay_meas_names = ["delay_gated_clk_nand", "delay_delay_chain_in"]+dc_delay_names
self.sae_delay_meas_names = ["delay_pre_sen"]+sen_driver_delay_names+["delay_sen"]
self.delay_chain_indices = (len(self.rbl_delay_meas_names)-len(dc_delay_names), len(self.rbl_delay_meas_names))
#Create slew measurement names
wl_en_driver_slew_names = ["slew_wl_en_dvr{}_".format(stage) for stage in range(1,self.get_num_wl_en_driver_stages())]
wl_driver_slew_names = ["slew_wl_dvr{}_".format(stage) for stage in range(1,self.get_num_wl_driver_stages())]
sen_driver_slew_names = ["slew_sen_dvr{}_".format(stage) for stage in range(1,self.get_num_sen_driver_stages())]
dc_slew_names = ["slew_delay_chain_stage{}_".format(stage) for stage in range(1,self.get_num_delay_stages()+1)]
wl_en_driver_slew_names = ["slew_wl_en_dvr_{}".format(stage) for stage in range(1,self.get_num_wl_en_driver_stages())]
wl_driver_slew_names = ["slew_wl_dvr_{}".format(stage) for stage in range(1,self.get_num_wl_driver_stages())]
sen_driver_slew_names = ["slew_sen_dvr_{}".format(stage) for stage in range(1,self.get_num_sen_driver_stages())]
dc_slew_names = ["slew_delay_chain_stage_{}".format(stage) for stage in range(1,self.get_num_delay_stages()+1)]
self.wl_slew_meas_names = ["slew_wl_gated_clk_bar"]+wl_en_driver_slew_names+["slew_wl_en", "slew_wl_bar"]+wl_driver_slew_names+["slew_wl"]
self.rbl_slew_meas_names = ["slew_rbl_gated_clk_bar","slew_gated_clk_nand", "slew_delay_chain_in"]+dc_slew_names
self.sae_slew_meas_names = ["slew_replica_bl0", "slew_pre_sen"]+sen_driver_slew_names+["slew_sen"]
def create_signal_names(self):
"""Creates list of the signal names used in the spice file along the wl and sen paths."""
"""Creates list of the signal names used in the spice file along the wl and sen paths.
Names are re-harded coded here; i.e. the names are hardcoded in most of OpenRAM and are
replicated here.
"""
delay.create_signal_names(self)
#Signal names are all hardcoded, need to update to make it work for probe address and different configurations.
wl_en_driver_signals = ["Xsram.Xcontrol0.Xbuf_wl_en.Zb{}_int".format(stage) for stage in range(1,self.get_num_wl_en_driver_stages())]
@ -317,12 +321,14 @@ class model_check(delay):
data_dict[self.wl_model_name] = wl_model_delays
data_dict[self.sae_meas_name] = sae_delays[read_port]
data_dict[self.sae_model_name] = sae_model_delays
data_dict[self.wl_slew_name] = wl_slews[read_port]
data_dict[self.sae_slew_name] = sae_slews[read_port]
#Some evaluations of the model and measured values
debug.info(1, "Comparing wordline measurements and model.")
self.compare_measured_and_model(wl_delays[read_port], wl_model_delays)
debug.info(1, "Comparing SAE measurements and model")
self.compare_measured_and_model(sae_delays[read_port], sae_model_delays)
# debug.info(1, "Comparing wordline measurements and model.")
# self.compare_measured_and_model(wl_delays[read_port], wl_model_delays)
# debug.info(1, "Comparing SAE measurements and model")
# self.compare_measured_and_model(sae_delays[read_port], sae_model_delays)
return data_dict
@ -334,6 +340,8 @@ class model_check(delay):
name_dict[self.wl_model_name] = name_dict["wl_measures"] #model uses same names as measured.
name_dict[self.sae_meas_name] = self.rbl_en_signal_names[1:]+self.sae_signal_names[1:]
name_dict[self.sae_model_name] = name_dict["sae_measures"]
name_dict[self.wl_slew_name] = self.wl_slew_meas_names
name_dict[self.sae_slew_name] = self.rbl_slew_meas_names+self.sae_slew_meas_names
return name_dict

View File

@ -18,6 +18,25 @@ from sram_config import sram_config
MODEL_DIR = "model_data/"
DATASET_CSV_NAME = MODEL_DIR+'datasets.csv'
# Data Collection class
# This module can perform two tasks
# 1) Collect data
# 2) Display data
# Data Collection -
# A single SRAM simulation will collect 6 datasets: wordline (WL) delays, sense amp enable (SAE) delays,
# WL slews, SAE slews, WL model delays, SAE model delays.
# Each dataset is stored in a separate csv file. Each row of the CSV refers to a different corner simulated on.
# The files names are stored in DATASET_CSV_NAME marked above.
# There are 2 main ways the collection is targeted: looking at different delay chain sizes and looking at different SRAM configurations.
# These are separated by different functions and should not be collected together.
#
# Data display -
# There are many functions in this file which will search (or told) for data using DATASET_CSV_NAME as a guide.
# Delay chain data is analyzed in analyze_delay_chain_data, graph_delays_and_inp_slews, and graph_inp_slews_and_delay_var
# WL and SAE graphing is done in analyze_sae_data and graph_delays_and_var
#
# Data collection and each analysis can be run independently, but the one you want needs to be commented in/out.
class data_collection(openram_test):
def runTest(self):
@ -29,7 +48,7 @@ class data_collection(openram_test):
self.run_setup()
self.run_delay_chain_analysis()
#self.run_sae_analysis()
globals.end_openram()
def run_setup(self):
@ -105,6 +124,123 @@ class data_collection(openram_test):
return [df_row[dt] for dt in data_types]
def get_all_filenames(self, data_types):
"""Gets all files from dataset.csv specified by the datatype (model/measure)"""
start_fname_ind = 4 # four query items
datasets_df = pd.read_csv(DATASET_CSV_NAME, encoding='utf-8')
csv_data_types = list(datasets_df)[start_fname_ind:]
if not set(data_types).issubset(set(csv_data_types)):
debug.error("Dataset csv header does not match expected:\nExpected={}\nCSV={}".format(data_types,
csv_data_types),1)
return [list(datasets_df[dt]) for dt in data_types]
def run_sae_analysis(self):
"""Generates sram with different delay chain configs over different corners and
analyzes delay average and variation."""
#config_tuple_list = [(8, 16, 1),(8, 32, 1),(16, 32, 1), (32, 64, 1), (64, 32, 1), (64, 64, 1), (32, 128, 1)]
#config_tuple_list = [(1, 16, 1),(4, 16, 1),(16, 16, 1), (32, 32, 1)]
config_tuple_list = [(1, 16, 1),(4, 16, 1)]
self.save_sram_data_using_configs(config_tuple_list)
self.analyze_sae_data() #Uses all available data
#self.graph_delays_and_var('sae_measures')
#self.graph_delays_and_var('wl_measures')
#self.compare_wl_sae_data()
def save_sram_data_using_configs(self, config_list):
"""Get SRAM data for different configurations"""
for config in config_list:
word_size, num_words, words_per_row = config
self.init_data_gen()
self.save_data_sram_corners(word_size, num_words, words_per_row)
def analyze_sae_data(self):
"""Compare and graph delay chain variations over different configurations."""
delay_avgs_ratio = []
delay_vars_ratio = []
sram_configs = []
data_types = ["sae_measures"]
sae_filenames = self.get_all_filenames(data_types)[0]
sae_dataframes = self.get_csv_data(sae_filenames)
for df in sae_dataframes:
#Each row in df contains sram config. Only use the first one (they should all be the same)
config = df[['word_size', 'num_words', 'words_per_row']].values.tolist()[0]
sram_configs.append(config)
delay_sums = self.get_sum(df)
delay_chain_sums = self.get_delay_chain_sums(df)
delay_avgs_ratio.append(self.get_average(delay_chain_sums)/self.get_average(delay_sums))
delay_vars_ratio.append(self.get_variance(delay_chain_sums)/self.get_variance(delay_sums))
debug.info(1,"DC config={}: avg ratio={} var ratio={}".format(sram_configs[-1],
delay_avgs_ratio[-1],
delay_vars_ratio[-1]))
#Sort by the delays then graph
all_data = zip(delay_avgs_ratio,sram_configs,delay_vars_ratio)
delay_avgs_ratio,sram_configs,delay_vars_ratio = zip(*sorted(all_data))
x_ax_label = '[word_size, num_words, words_per_row]'
y_ax_labels = ['DC/SAE Delay Ratio', 'DC/SAE Var. Ratio']
self.plot_delay_variance_data_sets(sram_configs, x_ax_label, y_ax_labels, delay_avgs_ratio, delay_vars_ratio)
def compare_wl_sae_data(self):
"""Compare and graph delay chain variations over different configurations."""
delay_avgs_ratio = []
delay_vars_ratio = []
sram_configs = []
data_types = ["wl_measures","sae_measures"]
data_filenames = self.get_all_filenames(data_types)
wl_filenames = data_filenames[0]
wl_dataframes = self.get_csv_data(wl_filenames)
sae_filenames = data_filenames[1]
sae_dataframes = self.get_csv_data(sae_filenames)
#Loop through all configurations found
for wl_df,sae_df in zip(wl_dataframes,sae_dataframes):
#Each row in df contains sram config. Only use the first one (they should all be the same)
config = wl_df[['word_size', 'num_words', 'words_per_row']].values.tolist()[0]
sram_configs.append(config)
wl_delays = self.get_sum(wl_df)
sae_delays = self.get_sum(sae_df)
delay_avgs_ratio.append(self.get_average(wl_delays)/self.get_average(sae_delays))
delay_vars_ratio.append(self.get_variance(wl_delays)/self.get_variance(sae_delays))
debug.info(1,"DC config={}: avg ratio={} var ratio={}".format(sram_configs[-1],
delay_avgs_ratio[-1],
delay_vars_ratio[-1]))
#Sort by the delays then graph
all_data = zip(delay_avgs_ratio,sram_configs,delay_vars_ratio)
delay_avgs_ratio,sram_configs,delay_vars_ratio = zip(*sorted(all_data))
x_ax_label = 'SRAM Config'
y_ax_labels = ['WL/SAE Delay Ratio', 'WL/SAE Var. Ratio']
self.plot_delay_variance_data_sets(sram_configs, x_ax_label, y_ax_labels, delay_avgs_ratio, delay_vars_ratio)
def graph_delays_and_var(self, data_type):
delay_avgs = []
delay_vars = []
sram_configs = []
data_filenames = self.get_all_filenames([data_type])[0]
dataframes = self.get_csv_data(data_filenames)
#Loop through all configurations found
for df in dataframes:
#Each row in df contains sram config. Only use the first one (they should all be the same)
config = df[['word_size', 'num_words', 'words_per_row']].values.tolist()[0]
sram_configs.append(config)
delays = self.get_sum(df)
delay_avgs.append(self.get_average(delays))
delay_vars.append(self.get_variance(delays))
debug.info(1,"DC config={}: avg={}, var={}".format(sram_configs[-1],
delay_avgs[-1],
delay_vars[-1]))
#Sort by the delays then graph
all_data = zip(delay_avgs,sram_configs,delay_vars)
delay_avgs,sram_configs,delay_vars = zip(*sorted(all_data))
x_ax_label = 'SRAM Config'
y_ax_labels = ['Avg. Delay', 'Delay Variance']
self.plot_delay_variance_data_sets(sram_configs, x_ax_label, y_ax_labels, delay_avgs, delay_vars)
def run_delay_chain_analysis(self):
"""Generates sram with different delay chain configs over different corners and
analyzes delay average and variation."""
@ -116,10 +252,16 @@ class data_collection(openram_test):
#dc_config_list = [(2,3), (3,3)]
#fanout_configs = [[3,3], [3,3,3]]
previous_dc_configs = [[4,4,4], [2,2,2,2], [3,3,3,3], [4,4],[4,4,4,4], [5,5]]
fanout_configs = [[3,3], [3,3,3], [2,3,2,3], [2,4,2,4], [3,3,3,3]]+previous_dc_configs
old_fanout_configs = []
fanout_configs = [[3,3], [2,3,2,3], [2,4,2,4], [2,2,2,2], [3,3,3,3], [4,4],[4,4,4,4], [5,5], \
[2,2], [2,5,2,5], [2,6,2,6], [2,8,2,8], [3,5,3,5], [4,5,4,5], [2,2,2,2,2,2], [3,3,3,3,3,3],\
[6,6],[7,7],[8,8],[9,9],[10,10],[11,11],
[5,2,5,2], [6,2,6,2], [8,2,8,2], [5,3,5,3], [5,4,5,4], [2,3,4,5], [7,2,7,2]]
analysis_configs = fanout_configs+old_fanout_configs
#self.save_delay_chain_data(word_size, num_words, words_per_row, fanout_configs)
self.analyze_delay_chain_data(word_size, num_words, words_per_row, fanout_configs)
#self.analyze_delay_chain_data(word_size, num_words, words_per_row, analysis_configs)
#self.graph_delays_and_inp_slews(word_size, num_words, words_per_row, analysis_configs)
self.graph_inp_slews_and_delay_var(word_size, num_words, words_per_row, analysis_configs)
def save_delay_chain_data(self, word_size, num_words, words_per_row, fanout_configs):
"""Get the delay data by only varying the delay chain size."""
@ -130,33 +272,207 @@ class data_collection(openram_test):
def analyze_delay_chain_data(self, word_size, num_words, words_per_row, fanout_configs):
"""Compare and graph delay chain variations over different configurations."""
dc_avgs = []
dc_vars = []
if not os.path.exists(DATASET_CSV_NAME):
debug.error("Could not find dataset CSV. Aborting analysis...",1)
dc_avgs, dc_vars = [],[]
rise_avgs, rise_vars = [],[]
fall_avgs, fall_vars = [],[]
for fanouts in fanout_configs:
data_types = ["wl_measures","sae_measures"]
filenames = self.get_filename_by_config(data_types, word_size, num_words, words_per_row, fanouts)
wl_dataframe, sae_dataframe = self.get_csv_data(filenames)
rise_delay, fall_delay = self.get_rise_fall_dc_sum(sae_dataframe)
delay_sums = self.get_delay_chain_sums(sae_dataframe)
dc_avgs.append(self.get_average(delay_sums))
dc_vars.append(self.get_variance(delay_sums))
rise_avgs.append(self.get_average(rise_delay))
rise_vars.append(self.get_variance(rise_delay))
fall_avgs.append(self.get_average(fall_delay))
fall_vars.append(self.get_variance(fall_delay))
debug.info(1,"DC config={}: avg={} variance={}".format(fanouts, dc_avgs[-1], dc_vars[-1]))
self.plot_two_data_sets(fanout_configs, dc_avgs, dc_vars)
#Sort by the delays then graph
config_copy = list(fanout_configs)
all_data = zip(dc_avgs,config_copy,dc_vars)
dc_avgs,config_copy,dc_vars = zip(*sorted(all_data))
x_ax_label = 'DC Fanouts'
y_ax_labels = ['Average Delay (ns)', 'Delay Variance (ns)']
self.plot_delay_variance_data_sets(config_copy, x_ax_label, y_ax_labels, dc_avgs, dc_vars)
def get_delay_chain_sums(self, sae_dataframe):
"""Calculate the total delay of the delay chain over different corners"""
config_copy = list(fanout_configs)
all_data = zip(rise_avgs,config_copy,rise_vars)
rise_avgs,config_copy,rise_vars = zip(*sorted(all_data))
x_ax_label = 'DC Fanouts'
y_ax_labels = ['Average Rise Delay (ns)', 'Rise Delay Variance (ns)']
self.plot_delay_variance_data_sets(config_copy, x_ax_label, y_ax_labels, rise_avgs, rise_vars)
config_copy = list(fanout_configs)
all_data = zip(fall_avgs,config_copy,fall_vars)
fall_avgs,config_copy,fall_vars = zip(*sorted(all_data))
x_ax_label = 'DC Fanouts'
y_ax_labels = ['Average Fall Delay (ns)', 'Fall Delay Variance (ns)']
self.plot_delay_variance_data_sets(config_copy, x_ax_label, y_ax_labels, fall_avgs, fall_vars)
def graph_inp_slews_and_delay_var(self, word_size, num_words, words_per_row, fanout_configs):
"""Compare and graph delay chain variations over different configurations."""
if not os.path.exists(DATASET_CSV_NAME):
debug.error("Could not find dataset CSV. Aborting analysis...",1)
dc_delays_var, dc_slews = [],[]
rise_delay_var, rise_slew_avgs = [],[]
fall_delay_var, fall_slew_avgs = [],[]
for fanouts in fanout_configs:
data_types = ["sae_measures", "sae_slews"]
filenames = self.get_filename_by_config(data_types, word_size, num_words, words_per_row, fanouts)
sae_delay_df, sae_slew_df = self.get_csv_data(filenames)
delay_sums = self.get_delay_chain_sums(sae_delay_df)
slew_sums = self.get_delay_chain_avg(sae_slew_df)
dc_delays_var.append(self.get_variance(delay_sums))
dc_slews.append(self.get_average(slew_sums))
rise_delay, fall_delay = self.get_rise_fall_dc_sum(sae_delay_df)
rise_delay_var.append(self.get_variance(rise_delay))
fall_delay_var.append(self.get_variance(fall_delay))
rise_slews, fall_slews = self.get_rise_fall_dc_avg(sae_slew_df)
rise_slew_avgs.append(self.get_average(rise_slews))
fall_slew_avgs.append(self.get_average(fall_slews))
debug.info(1,"DC config={}: slew avg={} delay var={}".format(fanouts, dc_slews[-1], dc_delays_var[-1]))
#Sort by the delays then graph
config_copy = list(fanout_configs)
all_data = zip(dc_slews,config_copy,dc_delays_var)
dc_slews,config_copy,dc_delays_var = zip(*sorted(all_data))
x_ax_label = 'DC Fanouts'
y_ax_labels = ['Average Input Slew (ns)', 'Delay Variance (ns)']
self.plot_delay_variance_data_sets(config_copy, x_ax_label, y_ax_labels, dc_slews, dc_delays_var)
config_copy = list(fanout_configs)
all_data = zip(rise_slew_avgs,config_copy,rise_delay_var)
rise_slew_avgs,config_copy,rise_delay_var = zip(*sorted(all_data))
x_ax_label = 'DC Fanouts'
y_ax_labels = ['Average Rise Stage Input Slew (ns)', 'Rise Delay Variance (ns)']
self.plot_delay_variance_data_sets(config_copy, x_ax_label, y_ax_labels, rise_slew_avgs, rise_delay_var)
config_copy = list(fanout_configs)
all_data = zip(fall_slew_avgs,config_copy,fall_delay_var)
fall_slew_avgs,config_copy,fall_delay_var = zip(*sorted(all_data))
x_ax_label = 'DC Fanouts'
y_ax_labels = ['Average Fall Stage Input Slew (ns)', 'Fall Delay Variance (ns)']
self.plot_delay_variance_data_sets(config_copy, x_ax_label, y_ax_labels, fall_slew_avgs, fall_delay_var)
def graph_delays_and_inp_slews(self, word_size, num_words, words_per_row, fanout_configs):
"""Compare and graph delay chain variations over different configurations."""
if not os.path.exists(DATASET_CSV_NAME):
debug.error("Could not find dataset CSV. Aborting analysis...",1)
dc_delays, dc_slews = [],[]
rise_delay_avgs, rise_slew_avgs = [],[]
fall_delay_avgs, fall_slew_avgs = [],[]
for fanouts in fanout_configs:
data_types = ["sae_measures", "sae_slews"]
filenames = self.get_filename_by_config(data_types, word_size, num_words, words_per_row, fanouts)
sae_delay_df, sae_slew_df = self.get_csv_data(filenames)
delay_sums = self.get_delay_chain_sums(sae_delay_df)
slew_sums = self.get_delay_chain_avg(sae_slew_df)
dc_delays.append(self.get_average(delay_sums))
dc_slews.append(self.get_average(slew_sums))
rise_delay, fall_delay = self.get_rise_fall_dc_sum(sae_delay_df)
rise_delay_avgs.append(self.get_average(rise_delay))
fall_delay_avgs.append(self.get_average(fall_delay))
rise_slews, fall_slews = self.get_rise_fall_dc_avg(sae_slew_df)
rise_slew_avgs.append(self.get_average(rise_slews))
fall_slew_avgs.append(self.get_average(fall_slews))
debug.info(1,"DC config={}: delay avg={} slew avg={}".format(fanouts, dc_delays[-1], dc_slews[-1]))
#Sort by the delays then graph
config_copy = list(fanout_configs)
all_data = zip(dc_delays,config_copy,dc_slews)
dc_delays,config_copy,dc_slews = zip(*sorted(all_data))
x_ax_label = 'DC Fanouts'
y_ax_labels = ['Average Delay (ns)', 'Average Input Slew (ns)']
self.plot_delay_variance_data_sets(config_copy, x_ax_label, y_ax_labels, dc_delays, dc_slews)
config_copy = list(fanout_configs)
all_data = zip(rise_delay_avgs,config_copy,rise_slew_avgs)
rise_delay_avgs,config_copy,rise_slew_avgs = zip(*sorted(all_data))
x_ax_label = 'DC Fanouts'
y_ax_labels = ['Average Rise Delay (ns)', 'Average Input Slew (ns)']
self.plot_delay_variance_data_sets(config_copy, x_ax_label, y_ax_labels, rise_delay_avgs, rise_slew_avgs)
config_copy = list(fanout_configs)
all_data = zip(fall_delay_avgs,config_copy,fall_slew_avgs)
fall_delay_avgs,config_copy,fall_slew_avgs = zip(*sorted(all_data))
x_ax_label = 'DC Fanouts'
y_ax_labels = ['Average Fall Delay (ns)', 'Average Input Slew (ns)']
self.plot_delay_variance_data_sets(config_copy, x_ax_label, y_ax_labels, fall_delay_avgs, fall_slew_avgs)
def get_delay_chain_data(self, sae_dataframe):
"""Get the data of the delay chain over different corners"""
start_dc_pos = sae_dataframe.columns.get_loc('dc_start_ind')
end_dc_pos = sae_dataframe.columns.get_loc('dc_end_ind')
start_data_pos = len(self.config_fields)+len(self.sae_config_fields)+1 #items before this point are configuration related
delay_sums = []
row_count = 0
delay_data = []
#Get delay sums over different corners
for sae_row in sae_dataframe.itertuples():
start_dc, end_dc = sae_row[start_dc_pos+1], sae_row[end_dc_pos+1]
dc_delays = sae_row[start_data_pos+start_dc:start_data_pos+end_dc]
delay_sums.append(sum(dc_delays))
return delay_sums
delay_data.append(dc_delays)
return delay_data
def get_delay_chain_sums(self, sae_dataframe):
"""Calculate the sum of each delay chain for each corner"""
dc_data = self.get_delay_chain_data(sae_dataframe)
return [sum(data_list) for data_list in dc_data]
def get_delay_chain_avg(self, sae_dataframe):
"""Calculate the average of each delay chain for each corner"""
dc_data = self.get_delay_chain_data(sae_dataframe)
return [sum(data_list)/len(data_list) for data_list in dc_data]
def get_rise_fall_dc_data_per_corner(self,sae_dataframe):
"""Extracts the data from the dataframe which represents the delay chain.
Delay chain data is marked by indices in the CSV.
"""
start_dc_pos = sae_dataframe.columns.get_loc('dc_start_ind')
end_dc_pos = sae_dataframe.columns.get_loc('dc_end_ind')
start_data_pos = len(self.config_fields)+len(self.sae_config_fields)+1 #items before this point are configuration related
rise_data = []
fall_data = []
#Get delay sums over different corners
for sae_row in sae_dataframe.itertuples():
start_dc, end_dc = sae_row[start_dc_pos+1], sae_row[end_dc_pos+1]
fall_list = sae_row[start_data_pos+start_dc:start_data_pos+end_dc:2]
rise_list = sae_row[start_data_pos+start_dc+1:start_data_pos+end_dc:2]
fall_data.append(fall_list)
rise_data.append(rise_list)
return rise_data, fall_data
def get_rise_fall_dc_sum(self,sae_dataframe):
"""Gets the delay/slew sum of the delay chain for every corner"""
#Get list of lists of delay chain data and reduce to sums
rise_data, fall_data = self.get_rise_fall_dc_data_per_corner(sae_dataframe)
rise_sums = [sum(dc_data) for dc_data in rise_data]
fall_sums = [sum(dc_data) for dc_data in fall_data]
return rise_sums,fall_sums
def get_rise_fall_dc_avg(self,sae_dataframe):
"""Gets the delay/slew average of the delay chain for every corner"""
#Get list of lists of delay chain data and reduce to sums
rise_data, fall_data = self.get_rise_fall_dc_data_per_corner(sae_dataframe)
rise_avgs = [sum(dc_data)/len(dc_data) for dc_data in rise_data]
fall_avgs = [sum(dc_data)/len(dc_data) for dc_data in fall_data]
return rise_avgs,fall_avgs
def get_sum(self, dataframe):
"""Get full delay from csv using the sum field in the df"""
return list(dataframe['sum'])
def get_variance(self, nums):
avg = self.get_average(nums)
delay_variance = sum((xi - avg) ** 2 for xi in nums) / len(nums)
@ -173,15 +489,15 @@ class data_collection(openram_test):
plt.plot(data_range, y_values, 'ro')
plt.show()
def plot_two_data_sets(self, x_labels, y1_values, y2_values):
"""Plots two data sets on the same x-axis. Uses hardcoded axis names."""
def plot_delay_variance_data_sets(self, x_labels, x_ax_name, y_labels, y1_delays, y2_vars):
"""Plots two data sets on the same x-axis."""
data_range = [i for i in range(len(x_labels))]
fig, ax1 = plt.subplots()
color = 'tab:red'
ax1.set_xlabel('DC (Stages,Fanout)')
ax1.set_ylabel('Average Delay (ns)', color=color)
ax1.plot(data_range, y1_values, marker='o', color=color, linestyle='')
ax1.set_xlabel(str(x_ax_name))
ax1.set_ylabel(y_labels[0], color=color)
ax1.plot(data_range, y1_delays, marker='o', color=color, linestyle='')
ax1.tick_params(axis='y', labelcolor=color)
ax1.tick_params(axis='x', labelrotation=-90)
@ -189,8 +505,8 @@ class data_collection(openram_test):
color = 'tab:blue'
#ax2.set_xticks(data_range, x_labels)
ax2.set_ylabel('Delay Variance (ns)', color=color) # we already handled the x-label with ax1
ax2.plot(data_range, y2_values, marker='*', color=color, linestyle='')
ax2.set_ylabel(y_labels[1], color=color) # we already handled the x-label with ax1
ax2.plot(data_range, y2_vars, marker='*', color=color, linestyle='')
ax2.tick_params(axis='y', labelcolor=color)
fig.tight_layout() # otherwise the right y-label is slightly clipped