import sys sys.path.append('Dev_Config') sys.path.append('User_Config') import uhal import bit_operations_r3v0p5 as bit_operations import time import json import pdb # REV: 18 March 2020 # To do: ('+' = done, '-' = still working on it, '|' = info) # # -Workout how equalizer works (why so many bits?) # # + Update bit_operations to automatically place bitfields # + -- Change writing to mask-based rather than length-based, # + or do a conversion between the two # + Did the conversion method. Works for now, but won't in the # + case of a mask with gaps (ie 0b01110110) # # + Work out serial number ip address configuration # + Now can do both; user specifies the serial numbers in each slot # # -Add eye diagram action # - may be finishedu, need to check with pawel # - also need to dump output to separate files # # |Eye Diagram Actoin - MGT Channel selector chooses GT channel to do. I have gt channels available, # | so I can iterate over links and do it for each one # # -add htm->hub optical links # - Did a first attempt, need to test if its correct. find link action will be useful for this # # -test optical links # # -put in option for delaying writes (to avoid udp packet errors) # # -add action for finding link connections (ie this tx goes to that rx) def decode(parameter, value, device_type, log): decode_dict = { "prbs-select" : {"PRBS-31" : {"GTH" : "0b101", "GTY" : "0b101", "GTX" : "0b100", }, "PRBS-23" : {"GTH" : "0b100", "GTY" : "0b100", "GTX" : "0b011", }, "PRBS-15" : {"GTH" : "0b011", "GTY" : "0b011", "GTX" : "0b010", }, # HTM doesn't have PRBS-9 Patterns #"PRBS-9" : {"GTH" : "0b010", # "GTX" : "0xN", # }, "PRBS-7" : {"GTH" : "0b001", "GTY" : "0b001", "GTX" : "0b001", }, "OFF" : {"GTH" : "0b000", "GTY" : "0b000", "GTX" : "0b000", }, }, "loopback" : {"Normal Operation" : {"GTH" : "0b000", "GTY" : "0b000", "GTX" : "0b000", }, "Near-End PCS" : {"GTH" : "0b001", "GTY" : "0b001", "GTX" : "0b001", }, "Near-End PMA" : {"GTH" : "0b010", "GTY" : "0b010", "GTX" : "0b010", }, "Far-End PMA" : {"GTH" : "0b100", "GTY" : "0b100", "GTX" : "0b100", }, "Far-End PCS" : {"GTH" : "0b110", "GTY" : "0b110", "GTX" : "0b110", }, }, "DFE" : {"ON" : {"GTH" : "0b1", "GTY" : "0b1", "GTX" : "0b1", }, "OFF" : {"GTH" : "0b0", "GTY" : "0b0", "GTX" : "0b0", }, }, "mgt equalizer" : {"ON" : {"GTH" : "0b1", "GTY" : "0b1", "GTX" : "0b1", }, "OFF" : {"GTH" : "0b0", "GTY" : "0b0", "GTX" : "0b0", }, }, } if parameter == "swing": if device_type == "GTX": value_range = [269, 336, 407, 474, 543, 609, 677, 741, 807, 866, 924, 973, 1018, 1056, 1092, 1119] elif device_type == "GTH": value_range = [170, 250, 320, 390, 460, 530, 600, 660, 730, 780, 840, 900, 950, 1000, 1040, 1080] elif device_type == "GTY": value_range = [191, 223, 254, 286, 315, 347, 378, 408, 439, 470, 499, 529, 556, 585, 613, 640, 669, 695, 720, 744, 766, 788, 809, 828, 846, 863, 878, 892, 903, 914, 924, 933] else: raise ValueError("Invalid device type: %s"%device_type) return decode_range(value, value_range, "int") if parameter == "pre-emphasis": if (device_type == "GTX") or (device_type == "GTH") or (device_type == "GTY"): value_range = [0, 0.22, 0.45, 0.68, 0.92, 1.16, 1.41, 1.67, 1.94, 2.21, 2.50, 2.79, 3.10, 3.41, 3.74, 4.08, 4.44, 4.81, 5.19, 5.60, 6.02, 6.02, 6.02, 6.02, 6.02, 6.02, 6.02, 6.02, 6.02, 6.02, 6.02, 6.02] else: raise ValueError("Invalid device type: %s"%device_type) return decode_range(value, value_range, "float") if parameter == "post-emphasis": if (device_type == "GTX") or (device_type == "GTH") or (device_type == "GTY"): value_range = [0, 0.22, 0.45, 0.68, 0.92, 1.16, 1.41, 1.67, 1.94, 2.21, 2.50, 2.79, 3.10, 3.41, 3.74, 4.08, 4.44, 4.81, 5.19, 5.60, 6.02, 6.02, 6.47, 6.94, 7.43, 7.96, 8.52, 9.12, 9.76, 10.46, 11.21, 12.04, 12.96] else: raise ValueError("Invalid device type: %s"%device_type) return decode_range(value, value_range, "float") if parameter in decode_dict.keys(): if value in decode_dict[parameter].keys(): return decode_dict[parameter][value][device_type] elif (value[0:2] == "0b") or (value[0:2] == "0x"): return value else: log.write("ERROR - Value '{}' ".format(value)) log.write("for parameter '{}' not recognized\n".format(parameter)) log.write("Exiting ...\n") log.flush() sys.exit() else: log.write("ERROR - Parameter '{}' not recognized\n".format(parameter)) log.flush() sys.exit() def decode_range(value, value_range, value_type): # For decoding pre/post emphasis, swing, etc # Things where the actual discrete values are not so meaningful if value_type == "int": value = int(value) elif value_type == "float": value = float(value) else: pass # ERROR - Invalid value type no_of_values = len(value_range) i = 1 while i < no_of_values: if value < ((value_range[i] + value_range[i-1])/2): return bin(i-1) i += 1 return bin(i-1) def perform_actions(action_list, action_timing, log): for action in action_list: if action.lower() == "report errors": report_errors(link_list, log) elif action.lower() == "inject errors": inject_errors(link_list, log) elif action.lower() == "collect eye diagram": if eye_log_name: eye_log = bit_operations.Log("Results/" + eye_log_name) get_eye_diagram(link_list, eye_log) else: get_eye_diagram(link_list, log) elif action.lower() == "find link routes": find_link_routes(link_list, log) elif action.lower() == "dummy name": pass else: log.write("Invalid action name '{}'\n".format(action)) # Change to log log.flush() return def initialize(link_list, log, initialization_parameters): ## Should make note of any resets that don't behave as expected log.write("="*70 + "\n") log.write("|{:^68}|\n".format("Performing Initialization")) log.write("="*70 + "\n\n") log.flush() # Log initialization parameters log.write("Using the following initialization parameters: \n") log.write(json.dumps(initialization_parameters, indent=4) + "\n") log.flush() # Test that initialization parameters are implemented and decodable for parameter in initialization_parameters: test_val = initialization_parameters[parameter] gth_test_val = decode(parameter, test_val, "GTH", log) gty_test_val = decode(parameter, test_val, "GTY", log) gtx_test_val = decode(parameter, test_val, "GTX", log) if verbose_output: log.write("[VERBOSE] Translation of Parameters into register values:\n") for parameter in initialization_parameters: log.write(" Parameter: %s\n"%parameter) log.write(" GTH Value: %s\n"%gth_test_val) log.write(" GTY Value: %s\n"%gty_test_val) log.write(" GTX Value: %s\n"%gtx_test_val) log.write("Writing Initialization Parameters ... \n") log.flush() # Writing Initialization Values (Phase 1 in Release 1 Style) for link in link_list: prbs_val = initialization_parameters["prbs-select"] dfe_val = initialization_parameters["DFE"] pre_emph_val = initialization_parameters["pre-emphasis"] post_emph_val = initialization_parameters["post-emphasis"] swing_val = initialization_parameters["swing"] source_dict = link_dict[link]["source"] # Check if link source is implemented (ie not a minipod or rod) if source_dict is not None: tx_dev = source_dict["card"] tx = tx_dev[source_dict["channel"]] tx_type = source_dict["type"] txprbs_val = decode("prbs-select", prbs_val, tx_type, log) tx_pre_emph_val = decode("pre-emphasis", pre_emph_val, tx_type, log) tx_post_emph_val = decode("post-emphasis", post_emph_val, tx_type, log) tx_swing_val = decode("swing", swing_val, tx_type, log) tx.set_txprbssel(txprbs_val) #tx_dev["csr"]["control"]["mgt_equ_en"].write() tx["tx_setup"]["pre_emphasis"].write(tx_pre_emph_val) tx["tx_setup"]["post_emphasis"].write(tx_post_emph_val) tx["tx_setup"]["swing"].write(tx_swing_val) dest_dict = link_dict[link]["source"] # Check if link dest is implemented (ie not a minipod or rod) if dest_dict is not None: rx_dev = source_dict["card"] rx = rx_dev[dest_dict["channel"]] rx_type = dest_dict["type"] rxprbs_val = decode("prbs-select", prbs_val, rx_type, log) rx_dfe_val = decode("DFE", dfe_val, rx_type, log) rx.set_rxprbssel(rxprbs_val) rx["rx_setup"]["dfe_on_off"].write(rx_dfe_val) log.write("Performing TX MGT Resets ... \n") log.flush() # Lowering TX MGT Resets for link in link_list: source_dict = link_dict[link]["source"] if source_dict is not None: tx_dev = source_dict["card"] tx = tx_dev[source_dict["channel"]] tx["common_reset"]["reset_master"].lower_bits() # Waiting before raising TX MGT Resets time.sleep(5) # Raising TX MGT Resets for link in link_list: source_dict = link_dict[link]["source"] if source_dict is not None: tx_dev = source_dict["card"] tx = tx_dev[source_dict["channel"]] tx["common_reset"]["reset_master"].raise_bits() # Waiting before lowering TX MGT Resets time.sleep(5) # Lowering TX MGT Resets for link in link_list: source_dict = link_dict[link]["source"] if source_dict is not None: tx_dev = source_dict["card"] tx = tx_dev[source_dict["channel"]] tx["common_reset"]["reset_master"].lower_bits() # Waiting before moving on to RX MGTs time.sleep(5) #! --- Implement dev check (as above) for rx mgt reset # Lowering RX MGT Resets for link in link_list: dest_dict = link_dict[link]["dest"] if dest_dict is not None: rx = dest_dict["card"][dest_dict["channel"]] rx["common_reset"]["reset_master"].lower_bits() # Waiting before raising RX MGT Resets time.sleep(5) log.write("Performing RX MGT Resets ... \n") log.flush() # Raising RX MGT Resets for link in link_list: dest_dict = link_dict[link]["dest"] if dest_dict is not None: rx = dest_dict["card"][dest_dict["channel"]] rx["common_reset"]["reset_master"].raise_bits() # Waiting before lowering RX MGT Resets time.sleep(5) # Lowering RX MGT Resets for link in link_list: dest_dict = link_dict[link]["dest"] if dest_dict is not None: rx = dest_dict["card"][dest_dict["channel"]] rx["common_reset"]["reset_master"].lower_bits() # Waiting Before Moving On time.sleep(5) log.write("Checking Init Done Bit ... \n") log.flush() # Check Setup (Phase 2) link_init_done_low_list = [] # Checking init done for link in link_list: source_dict = link_dict[link]["source"] if source_dict is not None: tx = source_dict["card"][source_dict["channel"]] tx_init_done = tx.get_init_done() if int(tx_init_done, 2) != 1: link_init_done_low_list.append((link_dict[link]["name"], "source")) dest_dict = link_dict[link]["dest"] if dest_dict is not None: rx = dest_dict["card"][dest_dict["channel"]] rx_init_done = rx.get_init_done() if int(rx_init_done, 2) != 1: link_init_done_low_list.append((link_dict[link]["name"], "dest")) if link_init_done_low_list: log.write("WARNING - Init done bit is low on the following transmitters/receivers: \n") for link_name_loc_pair in link_init_done_low_list: log.write(" Link: {} | {}\n".format(link_name_loc_pair[0], link_name_loc_pair[1])) else: log.write("Initialization Succesful for All Links\n") log.flush() # Resetting Error Counts log.write("Resetting Error Counts ... \n") log.flush() # Raising reset error count for link in link_list: dest_dict = link_dict[link]["dest"] if dest_dict is not None: rx = dest_dict["card"][dest_dict["channel"]] rx["rx_reset"]["rxprbscntreset"].raise_bits() time.sleep(5) # Lowering reset error count for link in link_list: dest_dict = link_dict[link]["dest"] if dest_dict is not None: rx = dest_dict["card"][dest_dict["channel"]] rx["rx_reset"]["rxprbscntreset"].lower_bits() return def report_errors(link_list, log): log.write(("="*70) + "\n") log.write("|" + "{:^68}".format("Error Report") + "|\n") log.write(("="*70) + "\n") link_error_list = [] for link in link_list: dest_dict = link_dict[link]["dest"] if dest_dict is not None: rx = dest_dict["card"][dest_dict["channel"]] error_count = rx.get_error_count() if int(error_count, 2) != 0: link_error_list.append((link_dict[link]["name"], int(error_count, 2))) if len(link_error_list) == 0: log.write("No errors to report. All links good.\n") else: ##### Redundant if the error list only includes channels with errors ## Print off which channels had errors #log.write("Errors on the following links: ") #for link_count_pair in link_error_list: # log.write("%s, "%link_count_pair[0]) #log.write("\n\n") log.write("List of Channels with Errors:\n") for link_count_pair in link_error_list: log.write("Link: {:<40} | Error Count: {}\n".format(link_count_pair[0], link_count_pair[1])) log.flush() log.write("Error Report Finished\n") log.flush() return def inject_errors(link_list, log): log.write(("="*70) + "\n") log.write("|" + "{:^68}".format("Inject Errors") + "|\n") log.write(("="*70) + "\n") log.flush() # Raising Force Error Bit log.write("Raising force error bits ...") log.flush() for link in link_list: source_dict = link_dict[link]["source"] if source_dict is not None: tx = source_dict["card"][source_dict["channel"]] tx["tx_force_err"]["txprbsforceerr"].raise_bits() time.sleep(1) # Lowering Force Error Bit log.write("Lowering force error bits ...") log.flush() for link in link_list: source_dict = link_dict[link]["source"] if source_dict is not None: tx = source_dict["card"][source_dict["channel"]] tx["tx_force_err"]["txprbsforceerr"].lower_bits() log.write("Error Injection Finished\n") log.flush() return def get_eye_diagram(link_list, log): # Banner log.write("="*70 + "\n") log.write("|{:^68}|\n".format("Eye Diagram Collection")) log.write("="*70 + "\n\n") log.flush() for link in link_list: link_name = link_dict[link]["name"] log.write("-"*70 + "\n") log.write("Collection of eye diagram for link: %s\n"%link_name) log.write("-"*70 + "\n") log.flush() dest_dict = link_dict[link]["dest"] if dest_dict is not None: card = dest_dict["card"] channel = dest_dict["channel"] rx = card[channel] # Select MGT Channel channel_number_only = channel[5:] channel_number_hex = hex(int(channel_number_only)) log.write("Selecting channel ...\n") if verbose_output: log.write("[DEBUG] Writing value %s to register/bitfield %s\n"%(channel_number_hex, card["csr"]["mgt_select"]["mgtchselect"])) log.flush() card["csr"]["mgt_select"]["mgtchselect"].write(channel_number_hex) # Reset Eye Diagram Machinery log.write("Resetting eye diagram machinery ...\n") if verbose_output: log.write("[DEBUG] Performing reset on register: %s\n"%rx["eye_control"]["eye_rstrtl"]) log.flush() eye_rstrtl_init = rx["eye_control"]["eye_rstrtl"].lower_bits() time.sleep(3) eye_rstrtl_mid = rx["eye_control"]["eye_rstrtl"].raise_bits() time.sleep(3) eye_rstrtl_final = rx["eye_control"]["eye_rstrtl"].lower_bits() eye_rstrtl_tup = (eye_rstrtl_init, eye_rstrtl_mid, eye_rstrtl_final) if verbose_output: log.write("[DEBUG] Values of %s throughout reset: %s\n"%( rx["eye_control"]["eye_rstrtl"], eye_rstrtl_tup)) log.flush() log.write("Starting eye diagram machinery ...\n") if verbose_output: log.write("[DEBUG] Writing to register: %s\n"%rx["eye_control"]["eye_go"]) log.flush() eye_go = rx["eye_control"]["eye_go"].raise_bits() if verbose_output: log.write("[DEBUG] Value of %s after raising bit: %s"%(rx["eye_control"]["eye_go"], eye_go)) log.flush() time.sleep(5) log.write("Collecting raw data ...\n") log.flush() # Since eye diagrams are stored in block memory, we have # to read them differently than a normal register eye_diagram1_uhal = card["eye_diagram1"].get_uhal() eye_diagram2_uhal = card["eye_diagram2"].get_uhal() eye_diagram3_uhal = card["eye_diagram3"].get_uhal() eye_diagram1_list = eye_diagram1_uhal.readBlock(256) eye_diagram2_list = eye_diagram2_uhal.readBlock(256) eye_diagram3_list = eye_diagram3_uhal.readBlock(256) card.get_uhal().dispatch() log.write("Stopping eye diagram machinery ...\n") if verbose_output: log.write("[DEBUG] Writing to register: %s\n"%rx["eye_control"]["eye_go"]) log.flush() eye_go = rx["eye_control"]["eye_go"].lower_bits() if verbose_output: log.write("[DEBUG] Value of %s after lowering bit: %s"%(rx["eye_control"]["eye_go"], eye_go)) log.flush() log.write("Data Collected for link: %s\n"%link_name) log.write("Sample | Error | Horizontal Data | Vertical Data | State | DRP Address\n") i = 0 while i < 256: eye_diagram1_entry = bin(eye_diagram1_list[i])[2:].zfill(32) eye_diagram2_entry = bin(eye_diagram2_list[i])[2:].zfill(32) eye_diagram3_entry = bin(eye_diagram3_list[i])[2:].zfill(32) sample = int(eye_diagram1_entry[:16], 2) error = int(eye_diagram1_entry[16:], 2) horzdata = int(eye_diagram2_entry[10:21], 2) vertdata = int(eye_diagram2_entry[21:], 2) state = int(eye_diagram3_entry[17:22], 2) drpaddr = int(eye_diagram3_entry[22:], 2) log.write("%s,%s,%s,%s,%s,%s\n"%(sample, error, horzdata, vertdata, state, drpaddr)) i += 1 log.write("\n") log.flush() def find_link_routes(link_list, log): # Structure: Check for errors on any links. Keep the ones that have errors in a list # For each Channel: # Inject an error, check all receiver links, find which one shows the error # # Error injection will be done by changing txprbsval. That way, HTMs can inject errors as well # Banner log.write("="*70 + "\n") log.write("|{:^68}|\n".format("Finding Link Routes")) log.write("="*70 + "\n\n") log.flush() # Get links with initial errors links_with_initial_errors = [] for link in link_list: dest_dict = link_dict[link]["dest"] # Check if link destination is implemented if dest_dict is not None: rx_dev = dest_dict["card"] rx = rx_dev[dest_dict["channel"]] rx_type = dest_dict["type"] error_count = rx.get_error_count() if (int(error_count, 2) != 0): links_with_initial_errors.append(link) log.write("Links with initial errors:\n") if links_with_initial_errors: for error_link in links_with_initial_errors: log.write(" %s\n"%error_link) else: log.write(" None\n") log.write("\n") log.write("-"*70 + "\n\n") log.flush() # Inject errrors on each tx and check each rx for source_link in link_list: source_dict = link_dict[source_link]["source"] links_with_errors_from_source = [] # Check if link source is implemented if source_dict is not None: tx_dev = source_dict["card"] tx = tx_dev[source_dict["channel"]] tx_type = source_dict["type"] # Inject Error txprbs_val_init = tx.get_txprbssel() txprbs_val_off = decode("prbs-select", "OFF", tx_type, log) tx.set_txprbssel(txprbs_val_off) time.sleep(0.5) tx.set_txprbssel(txprbs_val_init) for dest_link in link_list: dest_dict = link_dict[dest_link]["dest"] # Check if link destination is implemented if dest_dict is not None: rx_dev = dest_dict["card"] rx = rx_dev[dest_dict["channel"]] rx_type = dest_dict["type"] error_count = rx.get_error_count() # Check if link receiver has errors if (int(error_count, 2) != 0) and (dest_link not in links_with_initial_errors): # Make note that link has errors links_with_errors_from_source.append(dest_link) # Log list of links that had errrors originating from the source log.write("Source Link: %s\n"%source_link) log.write(" Link(s) with associated errors:\n") if links_with_errors_from_source: for error_link in links_with_errors_from_source: log.write(" %s\n"%error_link) else: log.write(" None\n") # Reset error counters so they are not picked up in subsequent tests for error_link in links_with_errors_from_source: dest_dict = link_dict[error_link]["dest"] if dest_dict is not None: rx_dev = dest_dict["card"] rx = rx_dev[dest_dict["channel"]] rx["rx_reset"]["rxprbscntreset"].raise_bits() time.sleep(0.5) rx["rx_reset"]["rxprbscntreset"].lower_bits() log.write("\n") log.flush() # Action Ideas # # get_registers/bitfields - Get the values of all registers or all bitfields of each link # # def show_usage(): print """ Usage: python ibert_ipbus_test_r2v0p2.py -h|--help -l|--log_name -e|--eye_log_name -c|--user_config_file -v|--verbose --hub1_SN --hub2_SN Options: -h, --help Display this message and exit -l, --log_name [log name] Save output to ./Results/[log name] -e, --eye_log_name [eye log name] Save eye diagram collection output to ./Results/[eye log name] -c, --user_config_file -v, --verbose --hub1_SN [Serial Number] Specify serial number of hub1 (for log) --hub2_SN [Serial Number] Specify serial number of hub2 (for log) """ sys.exit() if __name__ == "__main__": # Set default parameters log_name = "" eye_log_name = "" user_config_file = "" hub1_serial_no = "" hub2_serial_no = "" hub1_serial_no_argument = "" hub2_serial_no_argument = "" verbose_output = False # Get command line arguments cmd_line_arg = sys.argv[1:] if ( len (cmd_line_arg) >= 1 ) : # build explicit do loop (instead of "for i in range...") to allow "i=i+1" i = 0 # Loop for all other parameters while ( i < len(cmd_line_arg) ) : # Help if ((cmd_line_arg[i] == "-h" ) or (cmd_line_arg[i] == "--help")): show_usage() sys.exit() # Log Name elif ((cmd_line_arg[i] == "-l" ) or (cmd_line_arg[i] == "--log_name")): try: i += 1 log_name = cmd_line_arg[i] i += 1 continue except: print(" ** Argument for log name not given; exiting ** ") sys.exit() # Eye Diagram Log Name elif ((cmd_line_arg[i] == "-e" ) or (cmd_line_arg[i] == "--eye_log_name")): try: i += 1 eye_log_name = cmd_line_arg[i] i += 1 continue except: print(" ** Argument for eye diagram log name not given; exiting ** ") sys.exit() # User Config File elif ((cmd_line_arg[i] == "-c" ) or (cmd_line_arg[i] == "--user_config_file")): try: i += 1 user_config_file = cmd_line_arg[i] i += 1 continue except: print(" ** Argument for user config file not given; exiting ** ") sys.exit() # Verbose Output elif ((cmd_line_arg[i] == "-v" ) or (cmd_line_arg[i] == "--verbose")): verbose_output = True i += 1 continue # Hub 1 Serial No elif (cmd_line_arg[i] == "--hub1_SN" ): try: i += 1 hub1_serial_no_argument = cmd_line_arg[i] i += 1 continue except: print(" ** Argument for hub1_SN not given; exiting ** ") sys.exit() # Hub 2 Serial No elif (cmd_line_arg[i] == "--hub2_SN" ): try: i += 1 hub2_serial_no_argument = cmd_line_arg[i] i += 1 continue except: print(" ** Argument for hub2_SN not given; exiting ** ") sys.exit() # Illegal Argument else: print(" ** Illegal argument '%s' **"%(cmd_line_arg[i])) sys.exit() # Create Log if log_name: log = bit_operations.Log("Results/" + log_name) else: log = bit_operations.Log("") if user_config_file: execfile (user_config_file) else: execfile ("Dev_Config/user_config.conf") # Execute Configuartion Files execfile ("Dev_Config/dev_config.conf") # Opening Header log.write(("="*70) + "\n") log.write("|" + "{:^68}".format("IBERT Test - Release 3") + "|\n") log.write("|" + " "*68 + "|\n") # Write Hub Serial Numbers in Head # Check command line arguments first, if none then use configuration file if hub1_serial_no_argument: hub1_serial_no_str = "Hub1 SN: {}".format(hub1_serial_no_argument) else: hub1_serial_no_str = "Hub1 SN: {}".format(hub1_serial_no) if hub2_serial_no_argument: hub2_serial_no_str = "Hub2 SN: {}".format(hub2_serial_no_argument) else: hub2_serial_no_str = "Hub2 SN: {}".format(hub2_serial_no) log.write("|" + "{:^34}{:^34}".format(hub1_serial_no_str, hub2_serial_no_str) + "|\n") log.write(("="*70) + "\n\n") log.flush() # Log cards used and serial numbers if serial_number_based_ip_addresses: log.write("Cards in use:\n") all_card_list = ["hub1", "hub2", "htm3", "htm4", "htm5", "htm6", "htm7", "htm8", "htm9", "htm10", "htm11", "htm12", "htm13", "htm14"] log.write(" Card | Serial/Slot Number\n") for card in all_card_list: serial_or_slot_number = slot_to_serial_number_dict[card] if serial_or_slot_number is not None: log.write(" %-5s | %s\n"%(card, serial_or_slot_number)) log.write("\n\n") log.flush() # Log list of links being tested log.write("Links being tested:\n\n") for link in link_list: link_name = link_dict[link]["name"] log.write(" %s\n"%link_name) log.write("\n\n") log.flush() # Initialization (Phase 1) if perform_initialization: initialize(link_list, log, initialization_parameters) # Actions time.sleep(action_timing["start time"]) perform_actions(action_list, action_timing, log) if action_timing["periodic"]: periods_remaining = action_timing["no of periods"] - 1 while periods_remaining: time.sleep(action_timing["period"]) perform_actions(action_list, action_timing, log) periods_remaining -= 1