]> git.karo-electronics.de Git - karo-tx-linux.git/blob - tools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py
ACPI / bus: Add INT0002 to list of always-present devices
[karo-tx-linux.git] / tools / power / x86 / intel_pstate_tracer / intel_pstate_tracer.py
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3 #
4 """ This utility can be used to debug and tune the performance of the
5 intel_pstate driver. This utility can be used in two ways:
6 - If there is Linux trace file with pstate_sample events enabled, then
7 this utility can parse the trace file and generate performance plots.
8 - If user has not specified a trace file as input via command line parameters,
9 then this utility enables and collects trace data for a user specified interval
10 and generates performance plots.
11
12 Prerequisites:
13     Python version 2.7.x
14     gnuplot 5.0 or higher
15     gnuplot-py 1.8
16     (Most of the distributions have these required packages. They may be called
17      gnuplot-py, phython-gnuplot. )
18
19     HWP (Hardware P-States are disabled)
20     Kernel config for Linux trace is enabled
21
22     see print_help(): for Usage and Output details
23
24 """
25 from __future__ import print_function
26 from datetime import datetime
27 import subprocess
28 import os
29 import time
30 import re
31 import sys
32 import getopt
33 import Gnuplot
34 from numpy import *
35 from decimal import *
36
37 __author__ = "Srinivas Pandruvada"
38 __copyright__ = " Copyright (c) 2017, Intel Corporation. "
39 __license__ = "GPL version 2"
40
41
42 MAX_CPUS = 256
43
44 # Define the csv file columns
45 C_COMM = 18
46 C_GHZ = 17
47 C_ELAPSED = 16
48 C_SAMPLE = 15
49 C_DURATION = 14
50 C_LOAD = 13
51 C_BOOST = 12
52 C_FREQ = 11
53 C_TSC = 10
54 C_APERF = 9
55 C_MPERF = 8
56 C_TO = 7
57 C_FROM = 6
58 C_SCALED = 5
59 C_CORE = 4
60 C_USEC = 3
61 C_SEC = 2
62 C_CPU = 1
63
64 global sample_num, last_sec_cpu, last_usec_cpu, start_time, testname
65
66 # 11 digits covers uptime to 115 days
67 getcontext().prec = 11
68
69 sample_num =0
70 last_sec_cpu = [0] * MAX_CPUS
71 last_usec_cpu = [0] * MAX_CPUS
72
73 def print_help():
74     print('intel_pstate_tracer.py:')
75     print('  Usage:')
76     print('    If the trace file is available, then to simply parse and plot, use (sudo not required):')
77     print('      ./intel_pstate_tracer.py [-c cpus] -t <trace_file> -n <test_name>')
78     print('    Or')
79     print('      ./intel_pstate_tracer.py [--cpu cpus] ---trace_file <trace_file> --name <test_name>')
80     print('    To generate trace file, parse and plot, use (sudo required):')
81     print('      sudo ./intel_pstate_tracer.py [-c cpus] -i <interval> -n <test_name>')
82     print('    Or')
83     print('      sudo ./intel_pstate_tracer.py [--cpu cpus] --interval <interval> --name <test_name>')
84     print('    Optional argument:')
85     print('      cpus:  comma separated list of CPUs')
86     print('  Output:')
87     print('    If not already present, creates a "results/test_name" folder in the current working directory with:')
88     print('      cpu.csv - comma seperated values file with trace contents and some additional calculations.')
89     print('      cpu???.csv - comma seperated values file for CPU number ???.')
90     print('      *.png - a variety of PNG format plot files created from the trace contents and the additional calculations.')
91     print('  Notes:')
92     print('    Avoid the use of _ (underscore) in test names, because in gnuplot it is a subscript directive.')
93     print('    Maximum number of CPUs is {0:d}. If there are more the script will abort with an error.'.format(MAX_CPUS))
94     print('    Off-line CPUs cause the script to list some warnings, and create some empty files. Use the CPU mask feature for a clean run.')
95     print('    Empty y range warnings for autoscaled plots can occur and can be ignored.')
96
97 def plot_perf_busy_with_sample(cpu_index):
98     """ Plot method to per cpu information """
99
100     file_name = 'cpu{:0>3}.csv'.format(cpu_index)
101     if os.path.exists(file_name):
102         output_png = "cpu%03d_perf_busy_vs_samples.png" % cpu_index
103         g_plot = common_all_gnuplot_settings(output_png)
104         g_plot('set yrange [0:40]')
105         g_plot('set y2range [0:200]')
106         g_plot('set y2tics 0, 10')
107         g_plot('set title "{} : cpu perf busy vs. sample : CPU {:0>3} : {:%F %H:%M}"'.format(testname, cpu_index, datetime.now()))
108 #       Override common
109         g_plot('set xlabel "Samples"')
110         g_plot('set ylabel "P-State"')
111         g_plot('set y2label "Scaled Busy/performance/io-busy(%)"')
112         set_4_plot_linestyles(g_plot)
113         g_plot('plot "' + file_name + '" using {:d}:{:d} with linespoints linestyle 1 axis x1y2 title "performance",\\'.format(C_SAMPLE, C_CORE))
114         g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 2 axis x1y2 title "scaled-busy",\\'.format(C_SAMPLE, C_SCALED))
115         g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 3 axis x1y2 title "io-boost",\\'.format(C_SAMPLE, C_BOOST))
116         g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 4 axis x1y1 title "P-State"'.format(C_SAMPLE, C_TO))
117
118 def plot_perf_busy(cpu_index):
119     """ Plot some per cpu information """
120
121     file_name = 'cpu{:0>3}.csv'.format(cpu_index)
122     if os.path.exists(file_name):
123         output_png = "cpu%03d_perf_busy.png" % cpu_index
124         g_plot = common_all_gnuplot_settings(output_png)
125         g_plot('set yrange [0:40]')
126         g_plot('set y2range [0:200]')
127         g_plot('set y2tics 0, 10')
128         g_plot('set title "{} : perf busy : CPU {:0>3} : {:%F %H:%M}"'.format(testname, cpu_index, datetime.now()))
129         g_plot('set ylabel "P-State"')
130         g_plot('set y2label "Scaled Busy/performance/io-busy(%)"')
131         set_4_plot_linestyles(g_plot)
132         g_plot('plot "' + file_name + '" using {:d}:{:d} with linespoints linestyle 1 axis x1y2 title "performance",\\'.format(C_ELAPSED, C_CORE))
133         g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 2 axis x1y2 title "scaled-busy",\\'.format(C_ELAPSED, C_SCALED))
134         g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 3 axis x1y2 title "io-boost",\\'.format(C_ELAPSED, C_BOOST))
135         g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 4 axis x1y1 title "P-State"'.format(C_ELAPSED, C_TO))
136
137 def plot_durations(cpu_index):
138     """ Plot per cpu durations """
139
140     file_name = 'cpu{:0>3}.csv'.format(cpu_index)
141     if os.path.exists(file_name):
142         output_png = "cpu%03d_durations.png" % cpu_index
143         g_plot = common_all_gnuplot_settings(output_png)
144 #       Should autoscale be used here? Should seconds be used here?
145         g_plot('set yrange [0:5000]')
146         g_plot('set ytics 0, 500')
147         g_plot('set title "{} : durations : CPU {:0>3} : {:%F %H:%M}"'.format(testname, cpu_index, datetime.now()))
148         g_plot('set ylabel "Timer Duration (MilliSeconds)"')
149 #       override common
150         g_plot('set key off')
151         set_4_plot_linestyles(g_plot)
152         g_plot('plot "' + file_name + '" using {:d}:{:d} with linespoints linestyle 1 axis x1y1'.format(C_ELAPSED, C_DURATION))
153
154 def plot_loads(cpu_index):
155     """ Plot per cpu loads """
156
157     file_name = 'cpu{:0>3}.csv'.format(cpu_index)
158     if os.path.exists(file_name):
159         output_png = "cpu%03d_loads.png" % cpu_index
160         g_plot = common_all_gnuplot_settings(output_png)
161         g_plot('set yrange [0:100]')
162         g_plot('set ytics 0, 10')
163         g_plot('set title "{} : loads : CPU {:0>3} : {:%F %H:%M}"'.format(testname, cpu_index, datetime.now()))
164         g_plot('set ylabel "CPU load (percent)"')
165 #       override common
166         g_plot('set key off')
167         set_4_plot_linestyles(g_plot)
168         g_plot('plot "' + file_name + '" using {:d}:{:d} with linespoints linestyle 1 axis x1y1'.format(C_ELAPSED, C_LOAD))
169
170 def plot_pstate_cpu_with_sample():
171     """ Plot all cpu information """
172
173     if os.path.exists('cpu.csv'):
174         output_png = 'all_cpu_pstates_vs_samples.png'
175         g_plot = common_all_gnuplot_settings(output_png)
176         g_plot('set yrange [0:40]')
177 #       override common
178         g_plot('set xlabel "Samples"')
179         g_plot('set ylabel "P-State"')
180         g_plot('set title "{} : cpu pstate vs. sample : {:%F %H:%M}"'.format(testname, datetime.now()))
181         title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ')
182         plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_SAMPLE, C_TO)
183         g_plot('title_list = "{}"'.format(title_list))
184         g_plot(plot_str)
185
186 def plot_pstate_cpu():
187     """ Plot all cpu information from csv files """
188
189     output_png = 'all_cpu_pstates.png'
190     g_plot = common_all_gnuplot_settings(output_png)
191     g_plot('set yrange [0:40]')
192     g_plot('set ylabel "P-State"')
193     g_plot('set title "{} : cpu pstates : {:%F %H:%M}"'.format(testname, datetime.now()))
194
195 #    the following command is really cool, but doesn't work with the CPU masking option because it aborts on the first missing file.
196 #    plot_str = 'plot for [i=0:*] file=sprintf("cpu%03d.csv",i) title_s=sprintf("cpu%03d",i) file using 16:7 pt 7 ps 1 title title_s'
197 #
198     title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ')
199     plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_TO)
200     g_plot('title_list = "{}"'.format(title_list))
201     g_plot(plot_str)
202
203 def plot_load_cpu():
204     """ Plot all cpu loads """
205
206     output_png = 'all_cpu_loads.png'
207     g_plot = common_all_gnuplot_settings(output_png)
208     g_plot('set yrange [0:100]')
209     g_plot('set ylabel "CPU load (percent)"')
210     g_plot('set title "{} : cpu loads : {:%F %H:%M}"'.format(testname, datetime.now()))
211
212     title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ')
213     plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_LOAD)
214     g_plot('title_list = "{}"'.format(title_list))
215     g_plot(plot_str)
216
217 def plot_frequency_cpu():
218     """ Plot all cpu frequencies """
219
220     output_png = 'all_cpu_frequencies.png'
221     g_plot = common_all_gnuplot_settings(output_png)
222     g_plot('set yrange [0:4]')
223     g_plot('set ylabel "CPU Frequency (GHz)"')
224     g_plot('set title "{} : cpu frequencies : {:%F %H:%M}"'.format(testname, datetime.now()))
225
226     title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ')
227     plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_FREQ)
228     g_plot('title_list = "{}"'.format(title_list))
229     g_plot(plot_str)
230
231 def plot_duration_cpu():
232     """ Plot all cpu durations """
233
234     output_png = 'all_cpu_durations.png'
235     g_plot = common_all_gnuplot_settings(output_png)
236     g_plot('set yrange [0:5000]')
237     g_plot('set ytics 0, 500')
238     g_plot('set ylabel "Timer Duration (MilliSeconds)"')
239     g_plot('set title "{} : cpu durations : {:%F %H:%M}"'.format(testname, datetime.now()))
240
241     title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ')
242     plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_DURATION)
243     g_plot('title_list = "{}"'.format(title_list))
244     g_plot(plot_str)
245
246 def plot_scaled_cpu():
247     """ Plot all cpu scaled busy """
248
249     output_png = 'all_cpu_scaled.png'
250     g_plot = common_all_gnuplot_settings(output_png)
251 #   autoscale this one, no set y range
252     g_plot('set ylabel "Scaled Busy (Unitless)"')
253     g_plot('set title "{} : cpu scaled busy : {:%F %H:%M}"'.format(testname, datetime.now()))
254
255     title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ')
256     plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_SCALED)
257     g_plot('title_list = "{}"'.format(title_list))
258     g_plot(plot_str)
259
260 def plot_boost_cpu():
261     """ Plot all cpu IO Boosts """
262
263     output_png = 'all_cpu_boost.png'
264     g_plot = common_all_gnuplot_settings(output_png)
265     g_plot('set yrange [0:100]')
266     g_plot('set ylabel "CPU IO Boost (percent)"')
267     g_plot('set title "{} : cpu io boost : {:%F %H:%M}"'.format(testname, datetime.now()))
268
269     title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ')
270     plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_BOOST)
271     g_plot('title_list = "{}"'.format(title_list))
272     g_plot(plot_str)
273
274 def plot_ghz_cpu():
275     """ Plot all cpu tsc ghz """
276
277     output_png = 'all_cpu_ghz.png'
278     g_plot = common_all_gnuplot_settings(output_png)
279 #   autoscale this one, no set y range
280     g_plot('set ylabel "TSC Frequency (GHz)"')
281     g_plot('set title "{} : cpu TSC Frequencies (Sanity check calculation) : {:%F %H:%M}"'.format(testname, datetime.now()))
282
283     title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ')
284     plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_GHZ)
285     g_plot('title_list = "{}"'.format(title_list))
286     g_plot(plot_str)
287
288 def common_all_gnuplot_settings(output_png):
289     """ common gnuplot settings for multiple CPUs one one graph. """
290
291     g_plot = common_gnuplot_settings()
292     g_plot('set output "' + output_png + '"')
293     return(g_plot)
294
295 def common_gnuplot_settings():
296     """ common gnuplot settings. """
297
298     g_plot = Gnuplot.Gnuplot(persist=1)
299 #   The following line is for rigor only. It seems to be assumed for .csv files
300     g_plot('set datafile separator \",\"')
301     g_plot('set ytics nomirror')
302     g_plot('set xtics nomirror')
303     g_plot('set xtics font ", 10"')
304     g_plot('set ytics font ", 10"')
305     g_plot('set tics out scale 1.0')
306     g_plot('set grid')
307     g_plot('set key out horiz')
308     g_plot('set key bot center')
309     g_plot('set key samplen 2 spacing .8 font ", 9"')
310     g_plot('set term png size 1200, 600')
311     g_plot('set title font ", 11"')
312     g_plot('set ylabel font ", 10"')
313     g_plot('set xlabel font ", 10"')
314     g_plot('set xlabel offset 0, 0.5')
315     g_plot('set xlabel "Elapsed Time (Seconds)"')
316     return(g_plot)
317
318 def set_4_plot_linestyles(g_plot):
319     """ set the linestyles used for 4 plots in 1 graphs. """
320
321     g_plot('set style line 1 linetype 1 linecolor rgb "green" pointtype -1')
322     g_plot('set style line 2 linetype 1 linecolor rgb "red" pointtype -1')
323     g_plot('set style line 3 linetype 1 linecolor rgb "purple" pointtype -1')
324     g_plot('set style line 4 linetype 1 linecolor rgb "blue" pointtype -1')
325
326 def store_csv(cpu_int, time_pre_dec, time_post_dec, core_busy, scaled, _from, _to, mperf, aperf, tsc, freq_ghz, io_boost, common_comm, load, duration_ms, sample_num, elapsed_time, tsc_ghz):
327     """ Store master csv file information """
328
329     global graph_data_present
330
331     if cpu_mask[cpu_int] == 0:
332         return
333
334     try:
335         f_handle = open('cpu.csv', 'a')
336         string_buffer = "CPU_%03u, %05u, %06u, %u, %u, %u, %u, %u, %u, %u, %.4f, %u, %.2f, %.3f, %u, %.3f, %.3f, %s\n" % (cpu_int, int(time_pre_dec), int(time_post_dec), int(core_busy), int(scaled), int(_from), int(_to), int(mperf), int(aperf), int(tsc), freq_ghz, int(io_boost), load, duration_ms, sample_num, elapsed_time, tsc_ghz, common_comm)
337         f_handle.write(string_buffer);
338         f_handle.close()
339     except:
340         print('IO error cpu.csv')
341         return
342
343     graph_data_present = True;
344
345 def split_csv():
346     """ seperate the all csv file into per CPU csv files. """
347
348     global current_max_cpu
349
350     if os.path.exists('cpu.csv'):
351         for index in range(0, current_max_cpu + 1):
352             if cpu_mask[int(index)] != 0:
353                 os.system('grep -m 1 common_cpu cpu.csv > cpu{:0>3}.csv'.format(index))
354                 os.system('grep CPU_{:0>3} cpu.csv >> cpu{:0>3}.csv'.format(index, index))
355
356 def cleanup_data_files():
357     """ clean up existing data files """
358
359     if os.path.exists('cpu.csv'):
360         os.remove('cpu.csv')
361     f_handle = open('cpu.csv', 'a')
362     f_handle.write('common_cpu, common_secs, common_usecs, core_busy, scaled_busy, from, to, mperf, aperf, tsc, freq, boost, load, duration_ms, sample_num, elapsed_time, tsc_ghz, common_comm')
363     f_handle.write('\n')
364     f_handle.close()
365
366 def clear_trace_file():
367     """ Clear trace file """
368
369     try:
370         f_handle = open('/sys/kernel/debug/tracing/trace', 'w')
371         f_handle.close()
372     except:
373         print('IO error clearing trace file ')
374         quit()
375
376 def enable_trace():
377     """ Enable trace """
378
379     try:
380        open('/sys/kernel/debug/tracing/events/power/pstate_sample/enable'
381                  , 'w').write("1")
382     except:
383         print('IO error enabling trace ')
384         quit()
385
386 def disable_trace():
387     """ Disable trace """
388
389     try:
390        open('/sys/kernel/debug/tracing/events/power/pstate_sample/enable'
391                  , 'w').write("0")
392     except:
393         print('IO error disabling trace ')
394         quit()
395
396 def set_trace_buffer_size():
397     """ Set trace buffer size """
398
399     try:
400        open('/sys/kernel/debug/tracing/buffer_size_kb'
401                  , 'w').write("10240")
402     except:
403         print('IO error setting trace buffer size ')
404         quit()
405
406 def read_trace_data(filename):
407     """ Read and parse trace data """
408
409     global current_max_cpu
410     global sample_num, last_sec_cpu, last_usec_cpu, start_time
411
412     try:
413         data = open(filename, 'r').read()
414     except:
415         print('Error opening ', filename)
416         quit()
417
418     for line in data.splitlines():
419         search_obj = \
420             re.search(r'(^(.*?)\[)((\d+)[^\]])(.*?)(\d+)([.])(\d+)(.*?core_busy=)(\d+)(.*?scaled=)(\d+)(.*?from=)(\d+)(.*?to=)(\d+)(.*?mperf=)(\d+)(.*?aperf=)(\d+)(.*?tsc=)(\d+)(.*?freq=)(\d+)'
421                       , line)
422
423         if search_obj:
424             cpu = search_obj.group(3)
425             cpu_int = int(cpu)
426             cpu = str(cpu_int)
427
428             time_pre_dec = search_obj.group(6)
429             time_post_dec = search_obj.group(8)
430             core_busy = search_obj.group(10)
431             scaled = search_obj.group(12)
432             _from = search_obj.group(14)
433             _to = search_obj.group(16)
434             mperf = search_obj.group(18)
435             aperf = search_obj.group(20)
436             tsc = search_obj.group(22)
437             freq = search_obj.group(24)
438             common_comm = search_obj.group(2).replace(' ', '')
439
440             # Not all kernel versions have io_boost field
441             io_boost = '0'
442             search_obj = re.search(r'.*?io_boost=(\d+)', line)
443             if search_obj:
444                 io_boost = search_obj.group(1)
445
446             if sample_num == 0 :
447                 start_time = Decimal(time_pre_dec) + Decimal(time_post_dec) / Decimal(1000000)
448             sample_num += 1
449
450             if last_sec_cpu[cpu_int] == 0 :
451                 last_sec_cpu[cpu_int] = time_pre_dec
452                 last_usec_cpu[cpu_int] = time_post_dec
453             else :
454                 duration_us = (int(time_pre_dec) - int(last_sec_cpu[cpu_int])) * 1000000 + (int(time_post_dec) - int(last_usec_cpu[cpu_int]))
455                 duration_ms = Decimal(duration_us) / Decimal(1000)
456                 last_sec_cpu[cpu_int] = time_pre_dec
457                 last_usec_cpu[cpu_int] = time_post_dec
458                 elapsed_time = Decimal(time_pre_dec) + Decimal(time_post_dec) / Decimal(1000000) - start_time
459                 load = Decimal(int(mperf)*100)/ Decimal(tsc)
460                 freq_ghz = Decimal(freq)/Decimal(1000000)
461 #               Sanity check calculation, typically anomalies indicate missed samples
462 #               However, check for 0 (should never occur)
463                 tsc_ghz = Decimal(0)
464                 if duration_ms != Decimal(0) :
465                     tsc_ghz = Decimal(tsc)/duration_ms/Decimal(1000000)
466                 store_csv(cpu_int, time_pre_dec, time_post_dec, core_busy, scaled, _from, _to, mperf, aperf, tsc, freq_ghz, io_boost, common_comm, load, duration_ms, sample_num, elapsed_time, tsc_ghz)
467
468             if cpu_int > current_max_cpu:
469                 current_max_cpu = cpu_int
470 # End of for each trace line loop
471 # Now seperate the main overall csv file into per CPU csv files.
472     split_csv()
473
474 interval = ""
475 filename = ""
476 cpu_list = ""
477 testname = ""
478 graph_data_present = False;
479
480 valid1 = False
481 valid2 = False
482
483 cpu_mask = zeros((MAX_CPUS,), dtype=int)
484
485 try:
486     opts, args = getopt.getopt(sys.argv[1:],"ht:i:c:n:",["help","trace_file=","interval=","cpu=","name="])
487 except getopt.GetoptError:
488     print_help()
489     sys.exit(2)
490 for opt, arg in opts:
491     if opt == '-h':
492         print()
493         sys.exit()
494     elif opt in ("-t", "--trace_file"):
495         valid1 = True
496         location = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
497         filename = os.path.join(location, arg)
498     elif opt in ("-i", "--interval"):
499         valid1 = True
500         interval = arg
501     elif opt in ("-c", "--cpu"):
502         cpu_list = arg
503     elif opt in ("-n", "--name"):
504         valid2 = True
505         testname = arg
506
507 if not (valid1 and valid2):
508     print_help()
509     sys.exit()
510
511 if cpu_list:
512     for p in re.split("[,]", cpu_list):
513         if int(p) < MAX_CPUS :
514             cpu_mask[int(p)] = 1
515 else:
516     for i in range (0, MAX_CPUS):
517         cpu_mask[i] = 1
518
519 if not os.path.exists('results'):
520     os.mkdir('results')
521
522 os.chdir('results')
523 if os.path.exists(testname):
524     print('The test name directory already exists. Please provide a unique test name. Test re-run not supported, yet.')
525     sys.exit()
526 os.mkdir(testname)
527 os.chdir(testname)
528
529 # Temporary (or perhaps not)
530 cur_version = sys.version_info
531 print('python version (should be >= 2.7):')
532 print(cur_version)
533
534 # Left as "cleanup" for potential future re-run ability.
535 cleanup_data_files()
536
537 if interval:
538     filename = "/sys/kernel/debug/tracing/trace"
539     clear_trace_file()
540     set_trace_buffer_size()
541     enable_trace()
542     print('Sleeping for ', interval, 'seconds')
543     time.sleep(int(interval))
544     disable_trace()
545
546 current_max_cpu = 0
547
548 read_trace_data(filename)
549
550 if graph_data_present == False:
551     print('No valid data to plot')
552     sys.exit(2)
553
554 for cpu_no in range(0, current_max_cpu + 1):
555     plot_perf_busy_with_sample(cpu_no)
556     plot_perf_busy(cpu_no)
557     plot_durations(cpu_no)
558     plot_loads(cpu_no)
559
560 plot_pstate_cpu_with_sample()
561 plot_pstate_cpu()
562 plot_load_cpu()
563 plot_frequency_cpu()
564 plot_duration_cpu()
565 plot_scaled_cpu()
566 plot_boost_cpu()
567 plot_ghz_cpu()
568
569 os.chdir('../../')