diff --git a/.gitignore b/.gitignore index c4e15e9d..b16e3d0b 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ *.out *.toc *.synctex.gz +**/model_data \ No newline at end of file diff --git a/compiler/characterizer/model_check.py b/compiler/characterizer/model_check.py index b3e8452f..b791e520 100644 --- a/compiler/characterizer/model_check.py +++ b/compiler/characterizer/model_check.py @@ -227,7 +227,11 @@ class model_check(delay): def get_num_delay_stages(self): """Gets the number of stages in the delay chain from the control logic""" return len(self.sram.control_logic_rw.replica_bitline.delay_fanout_list) - + + def get_num_delay_stage_fanout(self): + """Gets fanout in each stage in the delay chain. Assumes each stage is the same""" + return self.sram.control_logic_rw.replica_bitline.delay_fanout_list[0] + def get_num_wl_en_driver_stages(self): """Gets the number of stages in the wl_en driver from the control logic""" return self.sram.control_logic_rw.wl_en_driver.num_stages diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 295bbca8..e81e44ea 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -30,13 +30,13 @@ class control_logic(design.design): self.port_type = port_type self.num_cols = word_size*words_per_row - self.num_words = num_rows * words_per_row + self.num_words = num_rows*words_per_row - self.enable_delay_chain_resizing = False + self.enable_delay_chain_resizing = True - #self.sram=None #disable re-sizing for debugging, FIXME: resizing is not working, needs to be adjusted for new control logic. - self.wl_timing_tolerance = 1 #Determines how much larger the sen delay should be. Accounts for possible error in model. - self.parasitic_inv_delay = parameter["min_inv_para_delay"] #Keeping 0 for now until further testing. + #Determines how much larger the sen delay should be. Accounts for possible error in model. + self.wl_timing_tolerance = 1 + self.parasitic_inv_delay = parameter["min_inv_para_delay"] self.wl_stage_efforts = None self.sen_stage_efforts = None @@ -159,16 +159,16 @@ class control_logic(design.design): #Resize if necessary, condition depends on resizing method if self.sram != None and self.enable_delay_chain_resizing and not self.does_sen_total_timing_match(): #This resizes to match fall and rise delays, can make the delay chain weird sizes. - # stage_list = self.get_dynamic_delay_fanout_list(delay_stages_heuristic, delay_fanout_heuristic) - # self.replica_bitline = factory.create(module_type="replica_bitline", - # delay_fanout_list=stage_list, - # bitcell_loads=bitcell_loads) + stage_list = self.get_dynamic_delay_fanout_list(delay_stages_heuristic, delay_fanout_heuristic) + self.replica_bitline = factory.create(module_type="replica_bitline", + delay_fanout_list=stage_list, + bitcell_loads=bitcell_loads) #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 = factory.create(module_type="replica_bitline", - delay_fanout_list=[delay_fanout]*delay_stages, - bitcell_loads=bitcell_loads) + # delay_stages, delay_fanout = self.get_dynamic_delay_chain_size(delay_stages_heuristic, delay_fanout_heuristic) + # 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.delay_chain_resized = True @@ -177,13 +177,10 @@ class control_logic(design.design): def get_heuristic_delay_chain_size(self): """Use a basic heuristic to determine the size of the delay chain used for the Sense Amp Enable """ - # FIXME: These should be tuned according to the additional size parameters - delay_fanout = 3 # This can be anything >=2 + delay_fanout = 2 # This can be anything >=2 # Delay stages Must be non-inverting - if self.words_per_row >= 4: - delay_stages = 8 - elif self.words_per_row == 2: - delay_stages = 6 + if self.words_per_row >= 2: + delay_stages = 4 else: delay_stages = 2 @@ -247,6 +244,8 @@ class control_logic(design.design): required_delay_rise = self.wl_delay_rise*self.wl_timing_tolerance - (self.sen_delay_rise-previous_delay_chain_delay/2) debug.info(2,"Required delays from chain: fall={}, rise={}".format(required_delay_fall,required_delay_rise)) + #If the fanout is different between rise/fall by this amount. Stage algorithm is made more pessimistic. + WARNING_FANOUT_DIFF = 5 #The stages need to be equal (or at least a even number of stages with matching rise/fall delays) while True: stages_fall = self.calculate_stages_with_fixed_fanout(required_delay_fall,fanout_fall) @@ -254,7 +253,8 @@ class control_logic(design.design): debug.info(1,"Fall stages={}, rise stages={}".format(stages_fall,stages_rise)) if stages_fall == stages_rise: break - elif abs(stages_fall-stages_rise) == 1: + elif abs(stages_fall-stages_rise) == 1 and WARNING_FANOUT_DIFF < abs(fanout_fall-fanout_rise): + debug.info(1, "Delay chain fanouts between stages are large. Making chain size larger for safety.") break #There should also be a condition to make sure the fanout does not get too large. #Otherwise, increase the fanout of delay with the most stages, calculate new stages diff --git a/compiler/tests/delay_data_collection.py b/compiler/tests/delay_data_collection.py index bd2a61f7..7c98bccf 100644 --- a/compiler/tests/delay_data_collection.py +++ b/compiler/tests/delay_data_collection.py @@ -4,6 +4,7 @@ Run a regression test on various srams """ import csv,sys,os import pandas as pd +import matplotlib.pyplot as plt import unittest from testutils import header,openram_test @@ -19,13 +20,14 @@ MODEL_DIR = "model_data/" class data_collection(openram_test): def runTest(self): - - word_size, num_words, words_per_row = 4, 16, 1 - self.init_data_gen() - self.set_delay_chain(2,3) - self.save_data_sram_corners(word_size, num_words, words_per_row) - wl_dataframe, sae_dataframe = self.get_csv_data() - self.evaluate_data(wl_dataframe, sae_dataframe) + ratio_data = self.calculate_delay_ratios_of_srams() + self.display_data(ratio_data) + # word_size, num_words, words_per_row = 4, 16, 1 + # self.init_data_gen() + # self.set_delay_chain(2,3) + # self.save_data_sram_corners(word_size, num_words, words_per_row) + # wl_dataframe, sae_dataframe = self.get_csv_data() + # self.evaluate_data(wl_dataframe, sae_dataframe) #Run again but with different delay chain sizes # self.init_data_gen() @@ -34,12 +36,27 @@ class data_collection(openram_test): # wl_dataframe, sae_dataframe = self.get_csv_data() # self.evaluate_data(wl_dataframe, sae_dataframe) - model_delay_ratios, meas_delay_ratios, ratio_error = self.compare_model_to_measure() - debug.info(1, "model_delay_ratios={}".format(model_delay_ratios)) - debug.info(1, "meas_delay_ratios={}".format(meas_delay_ratios)) - debug.info(1, "ratio_error={}".format(ratio_error)) - globals.end_openram() + # model_delay_ratios, meas_delay_ratios, ratio_error = self.compare_model_to_measure() + # debug.info(1, "model_delay_ratios={}".format(model_delay_ratios)) + # debug.info(1, "meas_delay_ratios={}".format(meas_delay_ratios)) + # debug.info(1, "ratio_error={}".format(ratio_error)) + # globals.end_openram() + def calculate_delay_ratios_of_srams(self): + """Runs delay measurements on several sram configurations. + Computes the delay ratio for each one.""" + delay_ratio_data = {} + config_tuple_list = [(32, 1024, None)] + #config_tuple_list = [(1, 16, 1),(4, 16, 1), (16, 16, 1), (32, 32, 1)] + for sram_config in config_tuple_list: + word_size, num_words, words_per_row = sram_config + self.init_data_gen() + self.save_data_sram_corners(word_size, num_words, words_per_row) + model_delay_ratios, meas_delay_ratios, ratio_error = self.compare_model_to_measure() + delay_ratio_data[sram_config] = ratio_error + debug.info(1, "Ratio percentage error={}".format(ratio_error)) + return delay_ratio_data + def get_csv_data(self): """Hardcoded Hack to get the measurement data from the csv into lists. """ wl_files_name = [file_name for file_name in self.file_names if "wl_measures" in file_name][0] @@ -79,11 +96,30 @@ class data_collection(openram_test): corner = (wl_meas[proc_pos+1], wl_meas[volt_pos+1], wl_meas[temp_pos+1]) meas_delay_ratios[corner] = wl_meas[wl_sum_pos+1]/sae_meas[sae_sum_pos+1] model_delay_ratios[corner] = wl_model[wl_sum_pos+1]/sae_model[sae_sum_pos+1] - debug.info(1,"wl_model sum={}, sae_model_sum={}".format(wl_model[wl_sum_pos+1], sae_model[sae_sum_pos+1])) - ratio_error[corner] = 100*abs(model_delay_ratios[corner]-meas_delay_ratios[corner])/meas_delay_ratios[corner] + #Not using absolute error, positive error means model was larger, negative error means it was smaller. + ratio_error[corner] = 100*(model_delay_ratios[corner]-meas_delay_ratios[corner])/meas_delay_ratios[corner] return model_delay_ratios, meas_delay_ratios, ratio_error - + + def display_data(self, data): + """Displays the ratio data using matplotlib (requires graphics)""" + config_data = [] + xticks = [] + #Organize data + #First key level if the sram configuration (wordsize, num words, words per row) + for config,corner_data_dict in data.items(): + #Second level is the corner data for that configuration. + for corner, corner_data in corner_data_dict.items(): + #Right now I am only testing with a single corner, will not work with more than 1 corner + config_data.append(corner_data) + xticks.append("{}b,{}w,{}wpr".format(*config)) + #plot data + data_range = [i+1 for i in range(len(data))] + shapes = ['ro', 'bo', 'go', 'co', 'mo'] + plt.xticks(data_range, xticks) + plt.plot(data_range, config_data, 'ro') + plt.show() + def calculate_delay_error(self, wl_dataframe, sae_dataframe): """Calculates the percentage difference in delays between the wordline and sense amp enable""" start_data_pos = len(self.config_fields) #items before this point are configuration related @@ -123,6 +159,9 @@ class data_collection(openram_test): def save_data_sram_corners(self, word_size, num_words, words_per_row): """Performs corner analysis on a single SRAM configuration""" self.create_sram(word_size, num_words, words_per_row) + #Setting to none forces SRAM to determine the value. Must be checked after sram creation + if not words_per_row: + words_per_row = self.sram.s.words_per_row #Run on one size to initialize CSV writing (csv names come from return value). Strange, but it is okay for now. corner_gen = self.corner_combination_generator() init_corner = next(corner_gen) @@ -150,7 +189,7 @@ class data_collection(openram_test): OPTS.trim_netlist = False OPTS.netlist_only = True OPTS.analytical_delay = False - OPTS.use_tech_delay_chain_size = True + #OPTS.use_tech_delay_chain_size = True # This is a hack to reload the characterizer __init__ with the spice version from importlib import reload import characterizer @@ -209,13 +248,16 @@ class data_collection(openram_test): self.csv_files = {} self.csv_writers = {} self.file_names = [] + delay_stages = self.delay_obj.get_num_delay_stages() + delay_stage_fanout = self.delay_obj.get_num_delay_stage_fanout() + for data_name, header_list in header_dict.items(): file_name = '{}data_{}b_{}word_{}way_dc{}x{}_{}.csv'.format(MODEL_DIR, word_size, num_words, words_per_row, - parameter["static_delay_stages"], - parameter["static_fanout_per_stage"], + delay_stages, + delay_stage_fanout, data_name) self.file_names.append(file_name) self.csv_files[data_name] = open(file_name, 'w') @@ -238,13 +280,11 @@ class data_collection(openram_test): self.sram_spice = OPTS.openram_temp + "temp.sp" self.sram.sp_write(self.sram_spice) - debug.info(1, "SRAM column address size={}".format(self.sram.s.col_addr_size)) - def get_sram_data(self, corner): """Generates the delay object using the corner and runs a simulation for data.""" from characterizer import model_check self.delay_obj = model_check(self.sram.s, self.sram_spice, corner) - + import tech #Only 1 at a time probe_address = "1" * self.sram.s.addr_size @@ -253,6 +293,7 @@ class data_collection(openram_test): slews = [tech.spice["rise_time"]*2] sram_data = self.delay_obj.analyze(probe_address,probe_data,slews,loads) + return sram_data def remove_lists_from_dict(self, dict): diff --git a/compiler/tests/model_data/data_4b_16word_1way_dc2x3_sae_measures.csv b/compiler/tests/model_data/data_4b_16word_1way_dc2x3_sae_measures.csv deleted file mode 100644 index e8016aa1..00000000 --- a/compiler/tests/model_data/data_4b_16word_1way_dc2x3_sae_measures.csv +++ /dev/null @@ -1,2 +0,0 @@ -word_size,num_words,words_per_row,dc_resized,process,voltage,temp,Xsram.Xcontrol0.Xand2_rbl_in.zb_int,Xsram.Xcontrol0.rbl_in,Xsram.Xcontrol0.Xreplica_bitline.Xdelay_chain.dout_1,Xsram.Xcontrol0.Xreplica_bitline.delayed_en,Xsram.Xcontrol0.pre_s_en,Xsram.Xcontrol0.Xbuf_s_en.Zb1_int,Xsram.s_en0,sum -4,16,1,False,TT,1.0,25,0.020618,0.0062215,0.018563000000000003,0.017233000000000002,0.007710799999999999,0.0099965,0.045221000000000004,0.12556380000000003 diff --git a/compiler/tests/model_data/data_4b_16word_1way_dc2x3_sae_model.csv b/compiler/tests/model_data/data_4b_16word_1way_dc2x3_sae_model.csv deleted file mode 100644 index 3ed42e60..00000000 --- a/compiler/tests/model_data/data_4b_16word_1way_dc2x3_sae_model.csv +++ /dev/null @@ -1,2 +0,0 @@ -word_size,num_words,words_per_row,dc_resized,process,voltage,temp,Xsram.Xcontrol0.Xand2_rbl_in.zb_int,Xsram.Xcontrol0.rbl_in,Xsram.Xcontrol0.Xreplica_bitline.Xdelay_chain.dout_1,Xsram.Xcontrol0.Xreplica_bitline.delayed_en,Xsram.Xcontrol0.pre_s_en,Xsram.Xcontrol0.Xbuf_s_en.Zb1_int,Xsram.s_en0,sum -4,16,1,False,TT,1.0,25,8.8,2.65,6.4,7.4,3.4,7.15,7.15,42.949999999999996 diff --git a/compiler/tests/model_data/data_4b_16word_1way_dc2x3_wl_measures.csv b/compiler/tests/model_data/data_4b_16word_1way_dc2x3_wl_measures.csv deleted file mode 100644 index 4c0ca0f3..00000000 --- a/compiler/tests/model_data/data_4b_16word_1way_dc2x3_wl_measures.csv +++ /dev/null @@ -1,2 +0,0 @@ -word_size,num_words,words_per_row,dc_resized,process,voltage,temp,Xsram.Xcontrol0.Xbuf_wl_en.Zb1_int,Xsram.Xcontrol0.Xbuf_wl_en.Zb2_int,Xsram.Xcontrol0.Xbuf_wl_en.Zb3_int,Xsram.wl_en0,Xsram.Xbank0.Xwordline_driver0.wl_bar_15,Xsram.Xbank0.wl_15,sum -4,16,1,False,TT,1.0,25,0.010512,0.0089216,0.014109,0.013643,0.014564,0.0086745,0.0704241 diff --git a/compiler/tests/model_data/data_4b_16word_1way_dc2x3_wl_model.csv b/compiler/tests/model_data/data_4b_16word_1way_dc2x3_wl_model.csv deleted file mode 100644 index e9faaeb9..00000000 --- a/compiler/tests/model_data/data_4b_16word_1way_dc2x3_wl_model.csv +++ /dev/null @@ -1,2 +0,0 @@ -word_size,num_words,words_per_row,dc_resized,process,voltage,temp,Xsram.Xcontrol0.Xbuf_wl_en.Zb1_int,Xsram.Xcontrol0.Xbuf_wl_en.Zb2_int,Xsram.Xcontrol0.Xbuf_wl_en.Zb3_int,Xsram.wl_en0,Xsram.Xbank0.Xwordline_driver0.wl_bar_15,Xsram.Xbank0.wl_15,sum -4,16,1,False,TT,1.0,25,5.4,5.4,5.733333333333333,4.4,5.8,5.4,32.13333333333334 diff --git a/compiler/tests/model_data/data_4b_16word_1way_dc4x2_sae_measures.csv b/compiler/tests/model_data/data_4b_16word_1way_dc4x2_sae_measures.csv deleted file mode 100644 index fe82d4e4..00000000 --- a/compiler/tests/model_data/data_4b_16word_1way_dc4x2_sae_measures.csv +++ /dev/null @@ -1,2 +0,0 @@ -word_size,num_words,words_per_row,dc_resized,process,voltage,temp,Xsram.Xcontrol0.Xand2_rbl_in.zb_int,Xsram.Xcontrol0.rbl_in,Xsram.Xcontrol0.Xreplica_bitline.Xdelay_chain.dout_1,Xsram.Xcontrol0.Xreplica_bitline.Xdelay_chain.dout_2,Xsram.Xcontrol0.Xreplica_bitline.Xdelay_chain.dout_3,Xsram.Xcontrol0.Xreplica_bitline.delayed_en,Xsram.Xcontrol0.pre_s_en,Xsram.Xcontrol0.Xbuf_s_en.Zb1_int,Xsram.s_en0,sum -4,16,1,False,TT,1.0,25,0.020572,0.006256,0.015678,0.014110000000000001,0.017755,0.013415,0.0076344,0.010162,0.04153,0.14711239999999998 diff --git a/compiler/tests/model_data/data_4b_16word_1way_dc4x2_sae_model.csv b/compiler/tests/model_data/data_4b_16word_1way_dc4x2_sae_model.csv deleted file mode 100644 index 7cac207f..00000000 --- a/compiler/tests/model_data/data_4b_16word_1way_dc4x2_sae_model.csv +++ /dev/null @@ -1,2 +0,0 @@ -word_size,num_words,words_per_row,dc_resized,process,voltage,temp,Xsram.Xcontrol0.Xand2_rbl_in.zb_int,Xsram.Xcontrol0.rbl_in,Xsram.Xcontrol0.Xreplica_bitline.Xdelay_chain.dout_1,Xsram.Xcontrol0.Xreplica_bitline.Xdelay_chain.dout_2,Xsram.Xcontrol0.Xreplica_bitline.Xdelay_chain.dout_3,Xsram.Xcontrol0.Xreplica_bitline.delayed_en,Xsram.Xcontrol0.pre_s_en,Xsram.Xcontrol0.Xbuf_s_en.Zb1_int,Xsram.s_en0,sum -4,16,1,False,TT,1.0,25,8.8,2.65,5.4,5.4,5.4,6.4,3.4,7.15,7.15,51.74999999999999 diff --git a/compiler/tests/model_data/data_4b_16word_1way_dc4x2_wl_measures.csv b/compiler/tests/model_data/data_4b_16word_1way_dc4x2_wl_measures.csv deleted file mode 100644 index 97844e6d..00000000 --- a/compiler/tests/model_data/data_4b_16word_1way_dc4x2_wl_measures.csv +++ /dev/null @@ -1,2 +0,0 @@ -word_size,num_words,words_per_row,dc_resized,process,voltage,temp,Xsram.Xcontrol0.Xbuf_wl_en.Zb1_int,Xsram.Xcontrol0.Xbuf_wl_en.Zb2_int,Xsram.Xcontrol0.Xbuf_wl_en.Zb3_int,Xsram.wl_en0,Xsram.Xbank0.Xwordline_driver0.wl_bar_15,Xsram.Xbank0.wl_15,sum -4,16,1,False,TT,1.0,25,0.010463,0.0089004,0.014107,0.013630000000000001,0.0146,0.0086902,0.0703906 diff --git a/compiler/tests/model_data/data_4b_16word_1way_dc4x2_wl_model.csv b/compiler/tests/model_data/data_4b_16word_1way_dc4x2_wl_model.csv deleted file mode 100644 index e9faaeb9..00000000 --- a/compiler/tests/model_data/data_4b_16word_1way_dc4x2_wl_model.csv +++ /dev/null @@ -1,2 +0,0 @@ -word_size,num_words,words_per_row,dc_resized,process,voltage,temp,Xsram.Xcontrol0.Xbuf_wl_en.Zb1_int,Xsram.Xcontrol0.Xbuf_wl_en.Zb2_int,Xsram.Xcontrol0.Xbuf_wl_en.Zb3_int,Xsram.wl_en0,Xsram.Xbank0.Xwordline_driver0.wl_bar_15,Xsram.Xbank0.wl_15,sum -4,16,1,False,TT,1.0,25,5.4,5.4,5.733333333333333,4.4,5.8,5.4,32.13333333333334