10e343479SDjordje Todorovic#!/usr/bin/env python3 20e343479SDjordje Todorovic 30e343479SDjordje Todorovicimport argparse 40e343479SDjordje Todorovicimport sys 5*402f91bcSMilica Maticimport os 60e343479SDjordje Todorovicfrom json import loads 70e343479SDjordje Todorovicfrom subprocess import Popen, PIPE 80e343479SDjordje Todorovic 90e343479SDjordje Todorovic# Holds code regions statistics. 100e343479SDjordje Todorovicclass Summary: 110e343479SDjordje Todorovic def __init__( 120e343479SDjordje Todorovic self, 130e343479SDjordje Todorovic name, 140e343479SDjordje Todorovic block_rthroughput, 150e343479SDjordje Todorovic dispatch_width, 160e343479SDjordje Todorovic ipc, 170e343479SDjordje Todorovic instructions, 180e343479SDjordje Todorovic iterations, 190e343479SDjordje Todorovic total_cycles, 200e343479SDjordje Todorovic total_uops, 210e343479SDjordje Todorovic uops_per_cycle, 220e343479SDjordje Todorovic iteration_resource_pressure, 230e343479SDjordje Todorovic name_target_info_resources, 240e343479SDjordje Todorovic ): 250e343479SDjordje Todorovic self.name = name 260e343479SDjordje Todorovic self.block_rthroughput = block_rthroughput 270e343479SDjordje Todorovic self.dispatch_width = dispatch_width 280e343479SDjordje Todorovic self.ipc = ipc 290e343479SDjordje Todorovic self.instructions = instructions 300e343479SDjordje Todorovic self.iterations = iterations 310e343479SDjordje Todorovic self.total_cycles = total_cycles 320e343479SDjordje Todorovic self.total_uops = total_uops 330e343479SDjordje Todorovic self.uops_per_cycle = uops_per_cycle 340e343479SDjordje Todorovic self.iteration_resource_pressure = iteration_resource_pressure 350e343479SDjordje Todorovic self.name_target_info_resources = name_target_info_resources 360e343479SDjordje Todorovic 370e343479SDjordje Todorovic 380e343479SDjordje Todorovic# Parse the program arguments. 390e343479SDjordje Todorovicdef parse_program_args(parser): 400e343479SDjordje Todorovic parser.add_argument( 410e343479SDjordje Todorovic "file_names", 420e343479SDjordje Todorovic nargs="+", 430e343479SDjordje Todorovic type=str, 440e343479SDjordje Todorovic help="Names of files which llvm-mca tool process.", 450e343479SDjordje Todorovic ) 460e343479SDjordje Todorovic parser.add_argument( 470e343479SDjordje Todorovic "--llvm-mca-binary", 480e343479SDjordje Todorovic nargs=1, 490e343479SDjordje Todorovic required=True, 500e343479SDjordje Todorovic type=str, 510e343479SDjordje Todorovic action="store", 520e343479SDjordje Todorovic metavar="[=<path to llvm-mca>]", 530e343479SDjordje Todorovic help="Specified relative path to binary of llvm-mca.", 540e343479SDjordje Todorovic ) 550e343479SDjordje Todorovic parser.add_argument( 560e343479SDjordje Todorovic "--args", 570e343479SDjordje Todorovic nargs=1, 580e343479SDjordje Todorovic type=str, 590e343479SDjordje Todorovic action="store", 600e343479SDjordje Todorovic metavar="[='-option1=<arg> -option2=<arg> ...']", 610e343479SDjordje Todorovic default=["-"], 620e343479SDjordje Todorovic help="Forward options to lvm-mca tool.", 630e343479SDjordje Todorovic ) 640e343479SDjordje Todorovic parser.add_argument( 65*402f91bcSMilica Matic "-plot", 66*402f91bcSMilica Matic action="store_true", 67*402f91bcSMilica Matic default=False, 68*402f91bcSMilica Matic help="Draw plots of statistics for input files.", 69*402f91bcSMilica Matic ) 70*402f91bcSMilica Matic parser.add_argument( 71*402f91bcSMilica Matic "-plot-resource-pressure", 72*402f91bcSMilica Matic action="store_true", 73*402f91bcSMilica Matic default=False, 74*402f91bcSMilica Matic help="Draw plots of resource pressure per iterations for input files.", 75*402f91bcSMilica Matic ) 76*402f91bcSMilica Matic parser.add_argument( 77*402f91bcSMilica Matic "--plot-path", 78*402f91bcSMilica Matic nargs=1, 79*402f91bcSMilica Matic type=str, 80*402f91bcSMilica Matic action="store", 81*402f91bcSMilica Matic metavar="[=<path>]", 82*402f91bcSMilica Matic default=["-"], 83*402f91bcSMilica Matic help="Specify relative path where you want to save the plots.", 84*402f91bcSMilica Matic ) 85*402f91bcSMilica Matic parser.add_argument( 860e343479SDjordje Todorovic "-v", 870e343479SDjordje Todorovic action="store_true", 880e343479SDjordje Todorovic default=False, 890e343479SDjordje Todorovic help="More details about the running lvm-mca tool.", 900e343479SDjordje Todorovic ) 910e343479SDjordje Todorovic return parser.parse_args() 920e343479SDjordje Todorovic 930e343479SDjordje Todorovic 94*402f91bcSMilica Matic# Verify that the program inputs meet the requirements. 95*402f91bcSMilica Maticdef verify_program_inputs(opts): 96*402f91bcSMilica Matic if opts.plot_path[0] != "-" and not opts.plot and not opts.plot_resource_pressure: 97*402f91bcSMilica Matic print( 98*402f91bcSMilica Matic "error: Please specify --plot-path only with the -plot or -plot-resource-pressure options." 99*402f91bcSMilica Matic ) 100*402f91bcSMilica Matic return False 101*402f91bcSMilica Matic 102*402f91bcSMilica Matic return True 103*402f91bcSMilica Matic 104*402f91bcSMilica Matic 1050e343479SDjordje Todorovic# Returns the name of the file to be analyzed from the path it is on. 1060e343479SDjordje Todorovicdef get_filename_from_path(path): 1070e343479SDjordje Todorovic index_of_slash = path.rfind("/") 1080e343479SDjordje Todorovic return path[(index_of_slash + 1) : len(path)] 1090e343479SDjordje Todorovic 1100e343479SDjordje Todorovic 1110e343479SDjordje Todorovic# Returns the results of the running llvm-mca tool for the input file. 1120e343479SDjordje Todorovicdef run_llvm_mca_tool(opts, file_name): 1130e343479SDjordje Todorovic # Get the path of the llvm-mca binary file. 1140e343479SDjordje Todorovic llvm_mca_cmd = opts.llvm_mca_binary[0] 1150e343479SDjordje Todorovic 1160e343479SDjordje Todorovic # The statistics llvm-mca options. 1170e343479SDjordje Todorovic if opts.args[0] != "-": 1180e343479SDjordje Todorovic llvm_mca_cmd += " " + opts.args[0] 1190e343479SDjordje Todorovic llvm_mca_cmd += " -json" 1200e343479SDjordje Todorovic 1210e343479SDjordje Todorovic # Set file which llvm-mca tool will process. 1220e343479SDjordje Todorovic llvm_mca_cmd += " " + file_name 1230e343479SDjordje Todorovic 1240e343479SDjordje Todorovic if opts.v: 1250e343479SDjordje Todorovic print("run: $ " + llvm_mca_cmd + "\n") 1260e343479SDjordje Todorovic 1270e343479SDjordje Todorovic # Generate the stats with the llvm-mca. 1280e343479SDjordje Todorovic subproc = Popen( 1290e343479SDjordje Todorovic llvm_mca_cmd.split(" "), 1300e343479SDjordje Todorovic stdin=PIPE, 1310e343479SDjordje Todorovic stdout=PIPE, 1320e343479SDjordje Todorovic stderr=PIPE, 1330e343479SDjordje Todorovic universal_newlines=True, 1340e343479SDjordje Todorovic ) 1350e343479SDjordje Todorovic 1360e343479SDjordje Todorovic cmd_stdout, cmd_stderr = subproc.communicate() 1370e343479SDjordje Todorovic 1380e343479SDjordje Todorovic try: 1390e343479SDjordje Todorovic json_parsed = loads(cmd_stdout) 1400e343479SDjordje Todorovic except: 1410e343479SDjordje Todorovic print("error: No valid llvm-mca statistics found.") 1420e343479SDjordje Todorovic print(cmd_stderr) 1430e343479SDjordje Todorovic sys.exit(1) 1440e343479SDjordje Todorovic 1450e343479SDjordje Todorovic if opts.v: 1460e343479SDjordje Todorovic print("Simulation Parameters: ") 1470e343479SDjordje Todorovic simulation_parameters = json_parsed["SimulationParameters"] 1480e343479SDjordje Todorovic for key in simulation_parameters: 1490e343479SDjordje Todorovic print(key, ":", simulation_parameters[key]) 1500e343479SDjordje Todorovic print("\n") 1510e343479SDjordje Todorovic 1520e343479SDjordje Todorovic code_regions_len = len(json_parsed["CodeRegions"]) 1530e343479SDjordje Todorovic array_of_code_regions = [None] * code_regions_len 1540e343479SDjordje Todorovic 1550e343479SDjordje Todorovic for i in range(code_regions_len): 1560e343479SDjordje Todorovic code_region_instructions_len = len( 1570e343479SDjordje Todorovic json_parsed["CodeRegions"][i]["Instructions"] 1580e343479SDjordje Todorovic ) 1590e343479SDjordje Todorovic target_info_resources_len = len(json_parsed["TargetInfo"]["Resources"]) 1600e343479SDjordje Todorovic iteration_resource_pressure = ["-" for k in range(target_info_resources_len)] 1610e343479SDjordje Todorovic resource_pressure_info = json_parsed["CodeRegions"][i]["ResourcePressureView"][ 1620e343479SDjordje Todorovic "ResourcePressureInfo" 1630e343479SDjordje Todorovic ] 1640e343479SDjordje Todorovic 165*402f91bcSMilica Matic name_target_info_resources = json_parsed["TargetInfo"]["Resources"] 1660e343479SDjordje Todorovic 1670e343479SDjordje Todorovic for s in range(len(resource_pressure_info)): 1680e343479SDjordje Todorovic obj_of_resource_pressure_info = resource_pressure_info[s] 1690e343479SDjordje Todorovic if ( 1700e343479SDjordje Todorovic obj_of_resource_pressure_info["InstructionIndex"] 1710e343479SDjordje Todorovic == code_region_instructions_len 1720e343479SDjordje Todorovic ): 1730e343479SDjordje Todorovic iteration_resource_pressure[ 1740e343479SDjordje Todorovic obj_of_resource_pressure_info["ResourceIndex"] 1750e343479SDjordje Todorovic ] = str(round(obj_of_resource_pressure_info["ResourceUsage"], 2)) 1760e343479SDjordje Todorovic 1770e343479SDjordje Todorovic array_of_code_regions[i] = Summary( 1780e343479SDjordje Todorovic file_name, 1790e343479SDjordje Todorovic json_parsed["CodeRegions"][i]["SummaryView"]["BlockRThroughput"], 1800e343479SDjordje Todorovic json_parsed["CodeRegions"][i]["SummaryView"]["DispatchWidth"], 1810e343479SDjordje Todorovic json_parsed["CodeRegions"][i]["SummaryView"]["IPC"], 1820e343479SDjordje Todorovic json_parsed["CodeRegions"][i]["SummaryView"]["Instructions"], 1830e343479SDjordje Todorovic json_parsed["CodeRegions"][i]["SummaryView"]["Iterations"], 1840e343479SDjordje Todorovic json_parsed["CodeRegions"][i]["SummaryView"]["TotalCycles"], 1850e343479SDjordje Todorovic json_parsed["CodeRegions"][i]["SummaryView"]["TotaluOps"], 1860e343479SDjordje Todorovic json_parsed["CodeRegions"][i]["SummaryView"]["uOpsPerCycle"], 1870e343479SDjordje Todorovic iteration_resource_pressure, 1880e343479SDjordje Todorovic name_target_info_resources, 1890e343479SDjordje Todorovic ) 1900e343479SDjordje Todorovic 1910e343479SDjordje Todorovic return array_of_code_regions 1920e343479SDjordje Todorovic 1930e343479SDjordje Todorovic 1940e343479SDjordje Todorovic# Print statistics in console for single file or for multiple files. 1950e343479SDjordje Todorovicdef console_print_results(matrix_of_code_regions, opts): 1960e343479SDjordje Todorovic try: 1970e343479SDjordje Todorovic import termtables as tt 1980e343479SDjordje Todorovic except ImportError: 1990e343479SDjordje Todorovic print("error: termtables not found.") 2000e343479SDjordje Todorovic sys.exit(1) 2010e343479SDjordje Todorovic 2020e343479SDjordje Todorovic headers_names = [None] * (len(opts.file_names) + 1) 2030e343479SDjordje Todorovic headers_names[0] = " " 2040e343479SDjordje Todorovic 2050e343479SDjordje Todorovic max_code_regions = 0 2060e343479SDjordje Todorovic 2070e343479SDjordje Todorovic print("Input files:") 2080e343479SDjordje Todorovic for i in range(len(matrix_of_code_regions)): 2090e343479SDjordje Todorovic if max_code_regions < len(matrix_of_code_regions[i]): 2100e343479SDjordje Todorovic max_code_regions = len(matrix_of_code_regions[i]) 2110e343479SDjordje Todorovic print("[f" + str(i + 1) + "]: " + get_filename_from_path(opts.file_names[i])) 2120e343479SDjordje Todorovic headers_names[i + 1] = "[f" + str(i + 1) + "]: " 2130e343479SDjordje Todorovic 2140e343479SDjordje Todorovic print("\nITERATIONS: " + str(matrix_of_code_regions[0][0].iterations) + "\n") 2150e343479SDjordje Todorovic 2160e343479SDjordje Todorovic for i in range(max_code_regions): 2170e343479SDjordje Todorovic 2180e343479SDjordje Todorovic print( 2190e343479SDjordje Todorovic "\n-----------------------------------------\nCode region: " 2200e343479SDjordje Todorovic + str(i + 1) 2210e343479SDjordje Todorovic + "\n" 2220e343479SDjordje Todorovic ) 2230e343479SDjordje Todorovic 2240e343479SDjordje Todorovic table_values = [ 2250e343479SDjordje Todorovic [[None] for i in range(len(matrix_of_code_regions) + 1)] for j in range(7) 2260e343479SDjordje Todorovic ] 2270e343479SDjordje Todorovic 2280e343479SDjordje Todorovic table_values[0][0] = "Instructions: " 2290e343479SDjordje Todorovic table_values[1][0] = "Total Cycles: " 2300e343479SDjordje Todorovic table_values[2][0] = "Total uOps: " 2310e343479SDjordje Todorovic table_values[3][0] = "Dispatch Width: " 2320e343479SDjordje Todorovic table_values[4][0] = "uOps Per Cycle: " 2330e343479SDjordje Todorovic table_values[5][0] = "IPC: " 2340e343479SDjordje Todorovic table_values[6][0] = "Block RThroughput: " 2350e343479SDjordje Todorovic 2360e343479SDjordje Todorovic for j in range(len(matrix_of_code_regions)): 2370e343479SDjordje Todorovic if len(matrix_of_code_regions[j]) > i: 2380e343479SDjordje Todorovic table_values[0][j + 1] = str(matrix_of_code_regions[j][i].instructions) 2390e343479SDjordje Todorovic table_values[1][j + 1] = str(matrix_of_code_regions[j][i].total_cycles) 2400e343479SDjordje Todorovic table_values[2][j + 1] = str(matrix_of_code_regions[j][i].total_uops) 2410e343479SDjordje Todorovic table_values[3][j + 1] = str( 2420e343479SDjordje Todorovic matrix_of_code_regions[j][i].dispatch_width 2430e343479SDjordje Todorovic ) 2440e343479SDjordje Todorovic table_values[4][j + 1] = str( 2450e343479SDjordje Todorovic round(matrix_of_code_regions[j][i].uops_per_cycle, 2) 2460e343479SDjordje Todorovic ) 2470e343479SDjordje Todorovic table_values[5][j + 1] = str(round(matrix_of_code_regions[j][i].ipc, 2)) 2480e343479SDjordje Todorovic table_values[6][j + 1] = str( 2490e343479SDjordje Todorovic round(matrix_of_code_regions[j][i].block_rthroughput, 2) 2500e343479SDjordje Todorovic ) 2510e343479SDjordje Todorovic else: 2520e343479SDjordje Todorovic table_values[0][j + 1] = "-" 2530e343479SDjordje Todorovic table_values[1][j + 1] = "-" 2540e343479SDjordje Todorovic table_values[2][j + 1] = "-" 2550e343479SDjordje Todorovic table_values[3][j + 1] = "-" 2560e343479SDjordje Todorovic table_values[4][j + 1] = "-" 2570e343479SDjordje Todorovic table_values[5][j + 1] = "-" 2580e343479SDjordje Todorovic table_values[6][j + 1] = "-" 2590e343479SDjordje Todorovic 2600e343479SDjordje Todorovic tt.print( 2610e343479SDjordje Todorovic table_values, 2620e343479SDjordje Todorovic header=headers_names, 2630e343479SDjordje Todorovic style=tt.styles.ascii_thin_double, 2640e343479SDjordje Todorovic padding=(0, 1), 2650e343479SDjordje Todorovic ) 2660e343479SDjordje Todorovic 2670e343479SDjordje Todorovic print("\nResource pressure per iteration: \n") 2680e343479SDjordje Todorovic 2690e343479SDjordje Todorovic table_values = [ 2700e343479SDjordje Todorovic [ 2710e343479SDjordje Todorovic [None] 2720e343479SDjordje Todorovic for i in range( 2730e343479SDjordje Todorovic len(matrix_of_code_regions[0][0].iteration_resource_pressure) + 1 2740e343479SDjordje Todorovic ) 2750e343479SDjordje Todorovic ] 2760e343479SDjordje Todorovic for j in range(len(matrix_of_code_regions) + 1) 2770e343479SDjordje Todorovic ] 2780e343479SDjordje Todorovic 279*402f91bcSMilica Matic table_values[0] = [" "] + matrix_of_code_regions[0][ 280*402f91bcSMilica Matic 0 281*402f91bcSMilica Matic ].name_target_info_resources 2820e343479SDjordje Todorovic 2830e343479SDjordje Todorovic for j in range(len(matrix_of_code_regions)): 2840e343479SDjordje Todorovic if len(matrix_of_code_regions[j]) > i: 2850e343479SDjordje Todorovic table_values[j + 1] = [ 2860e343479SDjordje Todorovic "[f" + str(j + 1) + "]: " 2870e343479SDjordje Todorovic ] + matrix_of_code_regions[j][i].iteration_resource_pressure 2880e343479SDjordje Todorovic else: 2890e343479SDjordje Todorovic table_values[j + 1] = ["[f" + str(j + 1) + "]: "] + len( 2900e343479SDjordje Todorovic matrix_of_code_regions[0][0].iteration_resource_pressure 2910e343479SDjordje Todorovic ) * ["-"] 2920e343479SDjordje Todorovic 2930e343479SDjordje Todorovic tt.print( 2940e343479SDjordje Todorovic table_values, 2950e343479SDjordje Todorovic style=tt.styles.ascii_thin_double, 2960e343479SDjordje Todorovic padding=(0, 1), 2970e343479SDjordje Todorovic ) 2980e343479SDjordje Todorovic print("\n") 2990e343479SDjordje Todorovic 3000e343479SDjordje Todorovic 301*402f91bcSMilica Matic# Based on the obtained results (summary view) of llvm-mca tool, draws plots for multiple input files. 302*402f91bcSMilica Maticdef draw_plot_files_summary(array_of_summary, opts): 303*402f91bcSMilica Matic try: 304*402f91bcSMilica Matic import matplotlib.pyplot as plt 305*402f91bcSMilica Matic except ImportError: 306*402f91bcSMilica Matic print("error: matplotlib.pyplot not found.") 307*402f91bcSMilica Matic sys.exit(1) 308*402f91bcSMilica Matic try: 309*402f91bcSMilica Matic from matplotlib.cm import get_cmap 310*402f91bcSMilica Matic except ImportError: 311*402f91bcSMilica Matic print("error: get_cmap (matplotlib.cm) not found.") 312*402f91bcSMilica Matic sys.exit(1) 313*402f91bcSMilica Matic 314*402f91bcSMilica Matic names = [ 315*402f91bcSMilica Matic "Block RThroughput", 316*402f91bcSMilica Matic "Dispatch Width", 317*402f91bcSMilica Matic "IPC", 318*402f91bcSMilica Matic "uOps Per Cycle", 319*402f91bcSMilica Matic "Instructions", 320*402f91bcSMilica Matic "Total Cycles", 321*402f91bcSMilica Matic "Total uOps", 322*402f91bcSMilica Matic ] 323*402f91bcSMilica Matic 324*402f91bcSMilica Matic rows, cols = (len(opts.file_names), 7) 325*402f91bcSMilica Matic 326*402f91bcSMilica Matic values = [[0 for x in range(cols)] for y in range(rows)] 327*402f91bcSMilica Matic 328*402f91bcSMilica Matic for i in range(len(opts.file_names)): 329*402f91bcSMilica Matic values[i][0] = array_of_summary[i].block_rthroughput 330*402f91bcSMilica Matic values[i][1] = array_of_summary[i].dispatch_width 331*402f91bcSMilica Matic values[i][2] = array_of_summary[i].ipc 332*402f91bcSMilica Matic values[i][3] = array_of_summary[i].uops_per_cycle 333*402f91bcSMilica Matic values[i][4] = array_of_summary[i].instructions 334*402f91bcSMilica Matic values[i][5] = array_of_summary[i].total_cycles 335*402f91bcSMilica Matic values[i][6] = array_of_summary[i].total_uops 336*402f91bcSMilica Matic 337*402f91bcSMilica Matic fig, axs = plt.subplots(4, 2) 338*402f91bcSMilica Matic fig.suptitle( 339*402f91bcSMilica Matic "Machine code statistics", fontsize=20, fontweight="bold", color="black" 340*402f91bcSMilica Matic ) 341*402f91bcSMilica Matic i = 0 342*402f91bcSMilica Matic 343*402f91bcSMilica Matic for x in range(4): 344*402f91bcSMilica Matic for y in range(2): 345*402f91bcSMilica Matic cmap = get_cmap("tab20") 346*402f91bcSMilica Matic colors = cmap.colors 347*402f91bcSMilica Matic if not (x == 0 and y == 1) and i < 7: 348*402f91bcSMilica Matic axs[x][y].grid(True, color="grey", linestyle="--") 349*402f91bcSMilica Matic maxValue = 0 350*402f91bcSMilica Matic if i == 0: 351*402f91bcSMilica Matic for j in range(len(opts.file_names)): 352*402f91bcSMilica Matic if maxValue < values[j][i]: 353*402f91bcSMilica Matic maxValue = values[j][i] 354*402f91bcSMilica Matic axs[x][y].bar( 355*402f91bcSMilica Matic 0.3 * j, 356*402f91bcSMilica Matic values[j][i], 357*402f91bcSMilica Matic width=0.1, 358*402f91bcSMilica Matic color=colors[j], 359*402f91bcSMilica Matic label=get_filename_from_path(opts.file_names[j]), 360*402f91bcSMilica Matic ) 361*402f91bcSMilica Matic else: 362*402f91bcSMilica Matic for j in range(len(opts.file_names)): 363*402f91bcSMilica Matic if maxValue < values[j][i]: 364*402f91bcSMilica Matic maxValue = values[j][i] 365*402f91bcSMilica Matic axs[x][y].bar(0.3 * j, values[j][i], width=0.1, color=colors[j]) 366*402f91bcSMilica Matic axs[x][y].set_axisbelow(True) 367*402f91bcSMilica Matic axs[x][y].set_xlim([-0.3, len(opts.file_names) / 3]) 368*402f91bcSMilica Matic axs[x][y].set_ylim([0, maxValue + (maxValue / 2)]) 369*402f91bcSMilica Matic axs[x][y].set_title(names[i], fontsize=15, fontweight="bold") 370*402f91bcSMilica Matic axs[x][y].axes.xaxis.set_visible(False) 371*402f91bcSMilica Matic for j in range(len(opts.file_names)): 372*402f91bcSMilica Matic axs[x][y].text( 373*402f91bcSMilica Matic 0.3 * j, 374*402f91bcSMilica Matic values[j][i] + (maxValue / 40), 375*402f91bcSMilica Matic s=str(values[j][i]), 376*402f91bcSMilica Matic color="black", 377*402f91bcSMilica Matic fontweight="bold", 378*402f91bcSMilica Matic fontsize=4, 379*402f91bcSMilica Matic ) 380*402f91bcSMilica Matic i = i + 1 381*402f91bcSMilica Matic 382*402f91bcSMilica Matic axs[0][1].set_visible(False) 383*402f91bcSMilica Matic fig.legend(prop={"size": 15}) 384*402f91bcSMilica Matic figg = plt.gcf() 385*402f91bcSMilica Matic figg.set_size_inches((25, 15), forward=False) 386*402f91bcSMilica Matic if opts.plot_path[0] == "-": 387*402f91bcSMilica Matic plt.savefig("llvm-mca-plot.png", dpi=500) 388*402f91bcSMilica Matic print("The plot was saved within llvm-mca-plot.png") 389*402f91bcSMilica Matic else: 390*402f91bcSMilica Matic plt.savefig( 391*402f91bcSMilica Matic os.path.normpath(os.path.join(opts.plot_path[0], "llvm-mca-plot.png")), 392*402f91bcSMilica Matic dpi=500, 393*402f91bcSMilica Matic ) 394*402f91bcSMilica Matic print( 395*402f91bcSMilica Matic "The plot was saved within {}.".format( 396*402f91bcSMilica Matic os.path.normpath(os.path.join(opts.plot_path[0], "llvm-mca-plot.png")) 397*402f91bcSMilica Matic ) 398*402f91bcSMilica Matic ) 399*402f91bcSMilica Matic 400*402f91bcSMilica Matic 401*402f91bcSMilica Matic# Calculates the average value (summary view) per region. 402*402f91bcSMilica Maticdef summary_average_code_region(array_of_code_regions, file_name): 403*402f91bcSMilica Matic summary = Summary(file_name, 0, 0, 0, 0, 0, 0, 0, 0, None, None) 404*402f91bcSMilica Matic for i in range(len(array_of_code_regions)): 405*402f91bcSMilica Matic summary.block_rthroughput += array_of_code_regions[i].block_rthroughput 406*402f91bcSMilica Matic summary.dispatch_width += array_of_code_regions[i].dispatch_width 407*402f91bcSMilica Matic summary.ipc += array_of_code_regions[i].ipc 408*402f91bcSMilica Matic summary.instructions += array_of_code_regions[i].instructions 409*402f91bcSMilica Matic summary.iterations += array_of_code_regions[i].iterations 410*402f91bcSMilica Matic summary.total_cycles += array_of_code_regions[i].total_cycles 411*402f91bcSMilica Matic summary.total_uops += array_of_code_regions[i].total_uops 412*402f91bcSMilica Matic summary.uops_per_cycle += array_of_code_regions[i].uops_per_cycle 413*402f91bcSMilica Matic summary.block_rthroughput = round( 414*402f91bcSMilica Matic summary.block_rthroughput / len(array_of_code_regions), 2 415*402f91bcSMilica Matic ) 416*402f91bcSMilica Matic summary.dispatch_width = round( 417*402f91bcSMilica Matic summary.dispatch_width / len(array_of_code_regions), 2 418*402f91bcSMilica Matic ) 419*402f91bcSMilica Matic summary.ipc = round(summary.ipc / len(array_of_code_regions), 2) 420*402f91bcSMilica Matic summary.instructions = round(summary.instructions / len(array_of_code_regions), 2) 421*402f91bcSMilica Matic summary.iterations = round(summary.iterations / len(array_of_code_regions), 2) 422*402f91bcSMilica Matic summary.total_cycles = round(summary.total_cycles / len(array_of_code_regions), 2) 423*402f91bcSMilica Matic summary.total_uops = round(summary.total_uops / len(array_of_code_regions), 2) 424*402f91bcSMilica Matic summary.uops_per_cycle = round( 425*402f91bcSMilica Matic summary.uops_per_cycle / len(array_of_code_regions), 2 426*402f91bcSMilica Matic ) 427*402f91bcSMilica Matic return summary 428*402f91bcSMilica Matic 429*402f91bcSMilica Matic 430*402f91bcSMilica Matic# Based on the obtained results (resource pressure per iter) of llvm-mca tool, draws plots for multiple input files. 431*402f91bcSMilica Maticdef draw_plot_resource_pressure( 432*402f91bcSMilica Matic array_average_resource_pressure_per_file, opts, name_target_info_resources 433*402f91bcSMilica Matic): 434*402f91bcSMilica Matic try: 435*402f91bcSMilica Matic import matplotlib.pyplot as plt 436*402f91bcSMilica Matic except ImportError: 437*402f91bcSMilica Matic print("error: matplotlib.pyplot not found.") 438*402f91bcSMilica Matic sys.exit(1) 439*402f91bcSMilica Matic try: 440*402f91bcSMilica Matic from matplotlib.cm import get_cmap 441*402f91bcSMilica Matic except ImportError: 442*402f91bcSMilica Matic print("error: get_cmap (matplotlib.cm) not found.") 443*402f91bcSMilica Matic sys.exit(1) 444*402f91bcSMilica Matic 445*402f91bcSMilica Matic fig, axs = plt.subplots() 446*402f91bcSMilica Matic fig.suptitle( 447*402f91bcSMilica Matic "Resource pressure per iterations", 448*402f91bcSMilica Matic fontsize=20, 449*402f91bcSMilica Matic fontweight="bold", 450*402f91bcSMilica Matic color="black", 451*402f91bcSMilica Matic ) 452*402f91bcSMilica Matic 453*402f91bcSMilica Matic maxValue = 0 454*402f91bcSMilica Matic for j in range(len(opts.file_names)): 455*402f91bcSMilica Matic if maxValue < max(array_average_resource_pressure_per_file[j]): 456*402f91bcSMilica Matic maxValue = max(array_average_resource_pressure_per_file[j]) 457*402f91bcSMilica Matic 458*402f91bcSMilica Matic cmap = get_cmap("tab20") 459*402f91bcSMilica Matic colors = cmap.colors 460*402f91bcSMilica Matic 461*402f91bcSMilica Matic xticklabels = [None] * len(opts.file_names) * len(name_target_info_resources) 462*402f91bcSMilica Matic index = 0 463*402f91bcSMilica Matic 464*402f91bcSMilica Matic for j in range(len(name_target_info_resources)): 465*402f91bcSMilica Matic for i in range(len(opts.file_names)): 466*402f91bcSMilica Matic if i == 0: 467*402f91bcSMilica Matic axs.bar( 468*402f91bcSMilica Matic j * len(opts.file_names) * 10 + i * 10, 469*402f91bcSMilica Matic array_average_resource_pressure_per_file[i][j], 470*402f91bcSMilica Matic width=1, 471*402f91bcSMilica Matic color=colors[j], 472*402f91bcSMilica Matic label=name_target_info_resources[j], 473*402f91bcSMilica Matic ) 474*402f91bcSMilica Matic else: 475*402f91bcSMilica Matic axs.bar( 476*402f91bcSMilica Matic j * len(opts.file_names) * 10 + i * 10, 477*402f91bcSMilica Matic array_average_resource_pressure_per_file[i][j], 478*402f91bcSMilica Matic width=1, 479*402f91bcSMilica Matic color=colors[j], 480*402f91bcSMilica Matic ) 481*402f91bcSMilica Matic axs.text( 482*402f91bcSMilica Matic j * len(opts.file_names) * 10 + i * 10, 483*402f91bcSMilica Matic array_average_resource_pressure_per_file[i][j] + (maxValue / 40), 484*402f91bcSMilica Matic s=str(array_average_resource_pressure_per_file[i][j]), 485*402f91bcSMilica Matic color=colors[j], 486*402f91bcSMilica Matic fontweight="bold", 487*402f91bcSMilica Matic fontsize=3, 488*402f91bcSMilica Matic ) 489*402f91bcSMilica Matic xticklabels[index] = opts.file_names[i] 490*402f91bcSMilica Matic index = index + 1 491*402f91bcSMilica Matic 492*402f91bcSMilica Matic axs.set_xticks( 493*402f91bcSMilica Matic [ 494*402f91bcSMilica Matic j * len(opts.file_names) * 10 + i * 10 495*402f91bcSMilica Matic for j in range(len(name_target_info_resources)) 496*402f91bcSMilica Matic for i in range(len(opts.file_names)) 497*402f91bcSMilica Matic ] 498*402f91bcSMilica Matic ) 499*402f91bcSMilica Matic axs.set_xticklabels(xticklabels, rotation=65) 500*402f91bcSMilica Matic 501*402f91bcSMilica Matic axs.set_axisbelow(True) 502*402f91bcSMilica Matic axs.set_xlim([-0.5, len(opts.file_names) * len(name_target_info_resources) * 10]) 503*402f91bcSMilica Matic axs.set_ylim([0, maxValue + maxValue / 10]) 504*402f91bcSMilica Matic 505*402f91bcSMilica Matic fig.legend(prop={"size": 15}) 506*402f91bcSMilica Matic figg = plt.gcf() 507*402f91bcSMilica Matic figg.set_size_inches((25, 15), forward=False) 508*402f91bcSMilica Matic if opts.plot_path[0] == "-": 509*402f91bcSMilica Matic plt.savefig("llvm-mca-plot-resource-pressure.png", dpi=500) 510*402f91bcSMilica Matic print("The plot was saved within llvm-mca-plot-resource-pressure.png") 511*402f91bcSMilica Matic else: 512*402f91bcSMilica Matic plt.savefig( 513*402f91bcSMilica Matic os.path.normpath( 514*402f91bcSMilica Matic os.path.join(opts.plot_path[0], "llvm-mca-plot-resource-pressure.png") 515*402f91bcSMilica Matic ), 516*402f91bcSMilica Matic dpi=500, 517*402f91bcSMilica Matic ) 518*402f91bcSMilica Matic print( 519*402f91bcSMilica Matic "The plot was saved within {}.".format( 520*402f91bcSMilica Matic os.path.normpath( 521*402f91bcSMilica Matic os.path.join( 522*402f91bcSMilica Matic opts.plot_path[0], "llvm-mca-plot-resource-pressure.png" 523*402f91bcSMilica Matic ) 524*402f91bcSMilica Matic ) 525*402f91bcSMilica Matic ) 526*402f91bcSMilica Matic ) 527*402f91bcSMilica Matic 528*402f91bcSMilica Matic 529*402f91bcSMilica Matic# Calculates the average value (resource pressure per iter) per region. 530*402f91bcSMilica Maticdef average_code_region_resource_pressure(array_of_code_regions, file_name): 531*402f91bcSMilica Matic resource_pressure_per_iter_one_file = [0] * len( 532*402f91bcSMilica Matic array_of_code_regions[0].iteration_resource_pressure 533*402f91bcSMilica Matic ) 534*402f91bcSMilica Matic for i in range(len(array_of_code_regions)): 535*402f91bcSMilica Matic for j in range(len(array_of_code_regions[i].iteration_resource_pressure)): 536*402f91bcSMilica Matic if array_of_code_regions[i].iteration_resource_pressure[j] != "-": 537*402f91bcSMilica Matic resource_pressure_per_iter_one_file[j] += float( 538*402f91bcSMilica Matic array_of_code_regions[i].iteration_resource_pressure[j] 539*402f91bcSMilica Matic ) 540*402f91bcSMilica Matic for i in range(len(resource_pressure_per_iter_one_file)): 541*402f91bcSMilica Matic resource_pressure_per_iter_one_file[i] = round( 542*402f91bcSMilica Matic resource_pressure_per_iter_one_file[i] / len(array_of_code_regions), 2 543*402f91bcSMilica Matic ) 544*402f91bcSMilica Matic return resource_pressure_per_iter_one_file 545*402f91bcSMilica Matic 546*402f91bcSMilica Matic 5470e343479SDjordje Todorovicdef Main(): 5480e343479SDjordje Todorovic parser = argparse.ArgumentParser() 5490e343479SDjordje Todorovic opts = parse_program_args(parser) 5500e343479SDjordje Todorovic 551*402f91bcSMilica Matic if not verify_program_inputs(opts): 552*402f91bcSMilica Matic parser.print_help() 553*402f91bcSMilica Matic sys.exit(1) 554*402f91bcSMilica Matic 5550e343479SDjordje Todorovic matrix_of_code_regions = [None] * len(opts.file_names) 5560e343479SDjordje Todorovic 5570e343479SDjordje Todorovic for i in range(len(opts.file_names)): 5580e343479SDjordje Todorovic matrix_of_code_regions[i] = run_llvm_mca_tool(opts, opts.file_names[i]) 559*402f91bcSMilica Matic if not opts.plot and not opts.plot_resource_pressure: 5600e343479SDjordje Todorovic console_print_results(matrix_of_code_regions, opts) 561*402f91bcSMilica Matic else: 562*402f91bcSMilica Matic if opts.plot: 563*402f91bcSMilica Matic array_average_summary_per_file = [None] * len(matrix_of_code_regions) 564*402f91bcSMilica Matic for j in range(len(matrix_of_code_regions)): 565*402f91bcSMilica Matic array_average_summary_per_file[j] = summary_average_code_region( 566*402f91bcSMilica Matic matrix_of_code_regions[j], opts.file_names[j] 567*402f91bcSMilica Matic ) 568*402f91bcSMilica Matic draw_plot_files_summary(array_average_summary_per_file, opts) 569*402f91bcSMilica Matic if opts.plot_resource_pressure: 570*402f91bcSMilica Matic array_average_resource_pressure_per_file = [None] * len( 571*402f91bcSMilica Matic matrix_of_code_regions 572*402f91bcSMilica Matic ) 573*402f91bcSMilica Matic for j in range(len(matrix_of_code_regions)): 574*402f91bcSMilica Matic array_average_resource_pressure_per_file[ 575*402f91bcSMilica Matic j 576*402f91bcSMilica Matic ] = average_code_region_resource_pressure( 577*402f91bcSMilica Matic matrix_of_code_regions[j], opts.file_names[j] 578*402f91bcSMilica Matic ) 579*402f91bcSMilica Matic draw_plot_resource_pressure( 580*402f91bcSMilica Matic array_average_resource_pressure_per_file, 581*402f91bcSMilica Matic opts, 582*402f91bcSMilica Matic matrix_of_code_regions[0][0].name_target_info_resources, 583*402f91bcSMilica Matic ) 5840e343479SDjordje Todorovic 5850e343479SDjordje Todorovic 5860e343479SDjordje Todorovicif __name__ == "__main__": 5870e343479SDjordje Todorovic Main() 5880e343479SDjordje Todorovic sys.exit(0) 589