blob: f06fba99323925c5ca7bf2ce6ba41f447c60546c [file] [log] [blame]
Javi Merino491cf732014-03-31 17:34:44 +01001#!/usr/bin/python
Javi Merinoc47d2df2015-02-06 16:04:03 +00002# $Copyright:
3# ----------------------------------------------------------------
4# This confidential and proprietary software may be used only as
5# authorised by a licensing agreement from ARM Limited
6# (C) COPYRIGHT 2015 ARM Limited
7# ALL RIGHTS RESERVED
8# The entire notice above must be reproduced on all authorised
9# copies and copies may only be made to the extent permitted
10# by a licensing agreement from ARM Limited.
11# ----------------------------------------------------------------
12# File: thermal.py
13# ----------------------------------------------------------------
14# $
15#
Javi Merino5bd3d442014-04-08 12:55:13 +010016"""Process the output of the power allocator trace in the current
17directory's trace.dat"""
Javi Merino572049d2014-03-31 16:45:23 +010018
Javi Merino898783c2015-06-16 11:45:16 +010019from collections import OrderedDict
Javi Merino572049d2014-03-31 16:45:23 +010020import os
Javi Merino898783c2015-06-16 11:45:16 +010021import pandas as pd
Javi Merinoee56c362014-03-31 17:30:34 +010022import re
Javi Merinoa6399fb2014-03-31 19:17:08 +010023from matplotlib import pyplot as plt
Javi Merino572049d2014-03-31 16:45:23 +010024
Javi Merino91e92dc2015-06-17 17:02:03 +010025from cr2.base import Base
Javi Merino323bb8d2015-04-20 17:09:15 +010026from cr2.run import Run
Javi Merino91e92dc2015-06-17 17:02:03 +010027from cr2.plot_utils import normalize_title, pre_plot_setup, post_plot_setup, plot_hist
Javi Merino51db3632014-06-13 11:24:51 +010028
Dietmar Eggemannb42a50b2014-12-11 20:28:45 +000029class Thermal(Base):
Javi Merino0e83b612014-06-05 11:45:23 +010030 """Process the thermal framework data in a ftrace dump"""
KP Singh7319a882014-12-24 18:18:01 +000031
32 unique_word="thermal_temperature:"
33 name="thermal"
34
Javi Merino6f34d902015-02-21 11:39:09 +000035 def __init__(self):
Javi Merino0e83b612014-06-05 11:45:23 +010036 super(Thermal, self).__init__(
KP Singh7319a882014-12-24 18:18:01 +000037 unique_word=self.unique_word,
Javi Merino0e83b612014-06-05 11:45:23 +010038 )
39
Javi Merino516d5942014-06-26 15:06:04 +010040 def plot_temperature(self, control_temperature=None, title="", width=None,
Javi Merino80114162014-08-08 16:48:32 +010041 height=None, ylim="range", ax=None, legend_label=""):
Javi Merino516d5942014-06-26 15:06:04 +010042 """Plot the temperature.
43
44 If control_temp is a pd.Series() representing the (possible)
45 variation of control_temp during the run, draw it using a
46 dashed yellow line. Otherwise, only the temperature is
47 plotted.
48
49 """
Javi Merinoc68737a2014-06-10 15:21:59 +010050 title = normalize_title("Temperature", title)
51
Javi Merino7e924022015-02-06 17:58:46 +000052 if len(self.data_frame) == 0:
53 raise ValueError("Empty DataFrame")
54
Javi Merino49cbcfe2014-08-08 16:03:49 +010055 setup_plot = False
56 if not ax:
57 ax = pre_plot_setup(width, height)
58 setup_plot = True
59
Javi Merino80114162014-08-08 16:48:32 +010060 temp_label = normalize_title("Temperature", legend_label)
Javi Merino92f4d012014-08-08 17:55:32 +010061 (self.data_frame["temp"] / 1000).plot(ax=ax, label=temp_label)
Javi Merino516d5942014-06-26 15:06:04 +010062 if control_temperature is not None:
Javi Merino80114162014-08-08 16:48:32 +010063 ct_label = normalize_title("Control", legend_label)
Javi Merino516d5942014-06-26 15:06:04 +010064 control_temperature.plot(ax=ax, color="y", linestyle="--",
Javi Merino80114162014-08-08 16:48:32 +010065 label=ct_label)
Javi Merinoc68737a2014-06-10 15:21:59 +010066
Javi Merino49cbcfe2014-08-08 16:03:49 +010067 if setup_plot:
68 post_plot_setup(ax, title=title, ylim=ylim)
69 plt.legend()
Javi Merinoc68737a2014-06-10 15:21:59 +010070
Javi Merinoe5ea60a2014-08-12 16:41:42 +010071 def plot_temperature_hist(self, ax, title):
Javi Merino1a3dca32014-08-11 16:12:50 +010072 """Plot a temperature histogram"""
73
74 temps = self.data_frame["temp"] / 1000
75 title = normalize_title("Temperature", title)
76 xlim = (0, temps.max())
77
Javi Merino23dff5d2015-03-09 19:05:46 +000078 plot_hist(temps, ax, title, "C", 30, "Temperature", xlim, "default")
Javi Merino1a3dca32014-08-11 16:12:50 +010079
Javi Merino323bb8d2015-04-20 17:09:15 +010080Run.register_class(Thermal, "thermal")
81
Dietmar Eggemannb42a50b2014-12-11 20:28:45 +000082class ThermalGovernor(Base):
Javi Merino5bd3d442014-04-08 12:55:13 +010083 """Process the power allocator data in a ftrace dump"""
KP Singh7319a882014-12-24 18:18:01 +000084
85 unique_word="thermal_power_allocator:"
86 name="thermal_governor"
Javi Merino6f34d902015-02-21 11:39:09 +000087 def __init__(self):
Javi Merino1e69e2c2014-06-04 18:25:09 +010088 super(ThermalGovernor, self).__init__(
KP Singh7319a882014-12-24 18:18:01 +000089 unique_word=self.unique_word,
Javi Merinoc2ec5682014-04-01 15:16:06 +010090 )
91
Javi Merinof521fba2015-02-06 18:22:09 +000092 def plot_temperature(self, title="", width=None, height=None, ylim="range",
93 ax=None, legend_label=""):
94 """Plot the temperature"""
95 dfr = self.data_frame
96 curr_temp = dfr["current_temperature"]
97 control_temp_series = (curr_temp + dfr["delta_temperature"]) / 1000
98 title = normalize_title("Temperature", title)
99
100 setup_plot = False
101 if not ax:
102 ax = pre_plot_setup(width, height)
103 setup_plot = True
104
105 temp_label = normalize_title("Temperature", legend_label)
106 (curr_temp / 1000).plot(ax=ax, label=temp_label)
107 control_temp_series.plot(ax=ax, color="y", linestyle="--",
108 label="control temperature")
109
110 if setup_plot:
111 post_plot_setup(ax, title=title, ylim=ylim)
112 plt.legend()
113
Javi Merino29223812014-08-12 15:24:43 +0100114 def plot_input_power(self, actor_order, title="", width=None, height=None, ax=None):
Javi Merinod6d5f892014-07-03 16:24:23 +0100115 """Plot input power
116
117 actor_order is an array with the order in which the actors were registered.
118 """
119
Javi Merino92f4d012014-08-08 17:55:32 +0100120 dfr = self.data_frame
Javi Merinof7968a72014-07-03 15:35:02 +0100121 in_cols = [s for s in dfr.columns if re.match("req_power[0-9]+", s)]
Javi Merinoe0ddf0d2014-05-07 18:40:12 +0100122
Javi Merinod6d5f892014-07-03 16:24:23 +0100123 plot_dfr = dfr[in_cols]
124 # Rename the columns from "req_power0" to "A15" or whatever is
125 # in actor_order. Note that we can do it just with an
126 # assignment because the columns are already sorted (i.e.:
127 # req_power0, req_power1...)
128 plot_dfr.columns = actor_order
129
Javi Merinoc00feff2014-04-14 15:41:51 +0100130 title = normalize_title("Input Power", title)
Javi Merino8ecd8172014-07-03 16:09:01 +0100131
Javi Merino29223812014-08-12 15:24:43 +0100132 if not ax:
133 ax = pre_plot_setup(width, height)
134
Javi Merinod6d5f892014-07-03 16:24:23 +0100135 plot_dfr.plot(ax=ax)
Javi Merino8ecd8172014-07-03 16:09:01 +0100136 post_plot_setup(ax, title=title)
Javi Merino9c010772014-04-02 16:54:41 +0100137
Javi Merino898783c2015-06-16 11:45:16 +0100138 def plot_weighted_input_power(self, actor_weights, title="", width=None, height=None, ax=None):
139 """Plot weighted input power
140
141 actor_weights is an array of tuples. First element of the
142 tuple is the name of the actor, the second is the weight. The
143 array is in the same order as the req_power appear in the
144 trace.
145
146 """
147
148 dfr = self.data_frame
149 in_cols = [s for s in dfr.columns if re.match(r"req_power\d+", s)]
150
151 plot_dfr_dict = OrderedDict()
152 for in_col, (name, weight) in zip(in_cols, actor_weights):
153 plot_dfr_dict[name] = dfr[in_col] * weight / 1024
154
155 plot_dfr = pd.DataFrame(plot_dfr_dict)
156
157 title = normalize_title("Weighted Input Power", title)
158
159 if not ax:
160 ax = pre_plot_setup(width, height)
161
162 plot_dfr.plot(ax=ax)
163 post_plot_setup(ax, title=title)
164
Javi Merino6003b252014-08-12 15:32:17 +0100165 def plot_output_power(self, actor_order, title="", width=None, height=None, ax=None):
Javi Merinod6d5f892014-07-03 16:24:23 +0100166 """Plot output power
167
168 actor_order is an array with the order in which the actors were registered.
169 """
170
Javi Merino92f4d012014-08-08 17:55:32 +0100171 out_cols = [s for s in self.data_frame.columns
Javi Merinof7968a72014-07-03 15:35:02 +0100172 if re.match("granted_power[0-9]+", s)]
Javi Merinoe0ddf0d2014-05-07 18:40:12 +0100173
Javi Merinod6d5f892014-07-03 16:24:23 +0100174 # See the note in plot_input_power()
Javi Merino92f4d012014-08-08 17:55:32 +0100175 plot_dfr = self.data_frame[out_cols]
Javi Merinod6d5f892014-07-03 16:24:23 +0100176 plot_dfr.columns = actor_order
177
Javi Merinoc00feff2014-04-14 15:41:51 +0100178 title = normalize_title("Output Power", title)
Javi Merino8ecd8172014-07-03 16:09:01 +0100179
Javi Merino6003b252014-08-12 15:32:17 +0100180 if not ax:
181 ax = pre_plot_setup(width, height)
182
Javi Merinod6d5f892014-07-03 16:24:23 +0100183 plot_dfr.plot(ax=ax)
Javi Merino8ecd8172014-07-03 16:09:01 +0100184 post_plot_setup(ax, title=title)
Javi Merinocd4a8272014-04-14 15:50:01 +0100185
Javi Merino9fc54852014-05-07 19:06:53 +0100186 def plot_inout_power(self, title="", width=None, height=None):
187 """Make multiple plots showing input and output power for each actor"""
Javi Merino92f4d012014-08-08 17:55:32 +0100188 dfr = self.data_frame
Javi Merino9fc54852014-05-07 19:06:53 +0100189
190 actors = []
191 for col in dfr.columns:
192 match = re.match("P(.*)_in", col)
193 if match and col != "Ptot_in":
194 actors.append(match.group(1))
195
196 for actor in actors:
197 cols = ["P" + actor + "_in", "P" + actor + "_out"]
198 this_title = normalize_title(actor, title)
199 dfr[cols].plot(title=this_title)
Javi Merino323bb8d2015-04-20 17:09:15 +0100200
201Run.register_class(ThermalGovernor, "thermal")