blob: bde69be7e80781ba4291487173d0c2a08a1fecf4 [file] [log] [blame]
Brendan Jackmane81fdcb2017-01-04 17:10:29 +00001# Copyright 2015-2017 ARM Limited
Javi Merinoc47d2df2015-02-06 16:04:03 +00002#
Javi Merinoaace7c02015-08-10 14:10:47 +01003# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
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 Merino898783c2015-06-16 11:45:16 +010020import pandas as pd
Javi Merinoee56c362014-03-31 17:30:34 +010021import re
Javi Merino572049d2014-03-31 16:45:23 +010022
Javi Merino435457c2015-08-10 15:59:10 +010023from trappy.base import Base
Javi Merino094e7422016-03-22 11:53:55 +000024from trappy.dynamic import register_ftrace_parser
Javi Merino51db3632014-06-13 11:24:51 +010025
Dietmar Eggemannb42a50b2014-12-11 20:28:45 +000026class Thermal(Base):
Kapileshwar Singhe1764fb2015-09-09 14:50:14 +010027 """Process the thermal framework data in a FTrace dump"""
KP Singh7319a882014-12-24 18:18:01 +000028
Javi Merino00dac502015-06-19 16:54:14 +010029 unique_word = "thermal_temperature:"
Kapileshwar Singhe1764fb2015-09-09 14:50:14 +010030 """The unique word that will be matched in a trace line"""
31
Javi Merino00dac502015-06-19 16:54:14 +010032 name = "thermal"
Kapileshwar Singhe1764fb2015-09-09 14:50:14 +010033 """The name of the :mod:`pandas.DataFrame` member that will be created in a
Javi Merinoc26a3232015-12-11 18:00:30 +000034 :mod:`trappy.ftrace.FTrace` object"""
Kapileshwar Singhe1764fb2015-09-09 14:50:14 +010035
Kapileshwar Singh01ed9102015-08-14 01:31:22 +010036 pivot = "id"
Kapileshwar Singhe1764fb2015-09-09 14:50:14 +010037 """The Pivot along which the data is orthogonal"""
KP Singh7319a882014-12-24 18:18:01 +000038
Javi Merino516d5942014-06-26 15:06:04 +010039 def plot_temperature(self, control_temperature=None, title="", width=None,
Javi Merino1217c652016-08-22 20:04:15 +010040 height=None, ylim="range", ax=None, legend_label="",
41 tz_id=None):
Javi Merino516d5942014-06-26 15:06:04 +010042 """Plot the temperature.
43
Kapileshwar Singhe1764fb2015-09-09 14:50:14 +010044 :param ax: Axis instance
45 :type ax: :mod:`matplotlib.Axis`
Javi Merino516d5942014-06-26 15:06:04 +010046
Kapileshwar Singhe1764fb2015-09-09 14:50:14 +010047 :param legend_label: Label for the legend
48 :type legend_label: str
49
50 :param title: The title of the plot
51 :type title: str
52
53 :param control_temperature: If control_temp is a
54 :mod:`pd.Series` representing the (possible)
55 variation of :code:`control_temp` during the
56 run, draw it using a dashed yellow line.
57 Otherwise, only the temperature is plotted.
58 :type control_temperature: :mod:`pandas.Series`
59
60 :param width: The width of the plot
61 :type width: int
62
63 :param height: The height of the plot
Javi Merino5d91edf2016-08-22 19:41:37 +010064 :type height: int
Javi Merino1217c652016-08-22 20:04:15 +010065
66 :param tz_id: thermal zone id as it appears in the id field of
67 the thermal_temperature trace event
68 :type tz_id: int
69
Javi Merino516d5942014-06-26 15:06:04 +010070 """
Javi Merinoec2ffe02015-12-07 15:05:13 +000071 from matplotlib import pyplot as plt
72 from trappy.plot_utils import normalize_title, pre_plot_setup, post_plot_setup
73
Javi Merinoc68737a2014-06-10 15:21:59 +010074 title = normalize_title("Temperature", title)
75
Javi Merino7e924022015-02-06 17:58:46 +000076 if len(self.data_frame) == 0:
77 raise ValueError("Empty DataFrame")
78
Javi Merino1217c652016-08-22 20:04:15 +010079 thermal_dfr = self.data_frame
80 if tz_id is not None:
81 thermal_dfr = thermal_dfr[thermal_dfr["id"] == tz_id]
82 if len(thermal_dfr) == 0:
83 raise ValueError("No thermal_temperature trace for thermal zone {}".format(tz_id))
84
Javi Merino49cbcfe2014-08-08 16:03:49 +010085 setup_plot = False
86 if not ax:
87 ax = pre_plot_setup(width, height)
88 setup_plot = True
89
Javi Merino80114162014-08-08 16:48:32 +010090 temp_label = normalize_title("Temperature", legend_label)
Javi Merino1217c652016-08-22 20:04:15 +010091 (thermal_dfr["temp"] / 1000).plot(ax=ax, label=temp_label)
Javi Merino516d5942014-06-26 15:06:04 +010092 if control_temperature is not None:
Javi Merino80114162014-08-08 16:48:32 +010093 ct_label = normalize_title("Control", legend_label)
Javi Merino516d5942014-06-26 15:06:04 +010094 control_temperature.plot(ax=ax, color="y", linestyle="--",
Javi Merino80114162014-08-08 16:48:32 +010095 label=ct_label)
Javi Merinoc68737a2014-06-10 15:21:59 +010096
Javi Merino49cbcfe2014-08-08 16:03:49 +010097 if setup_plot:
98 post_plot_setup(ax, title=title, ylim=ylim)
99 plt.legend()
Javi Merinoc68737a2014-06-10 15:21:59 +0100100
Javi Merinoe5ea60a2014-08-12 16:41:42 +0100101 def plot_temperature_hist(self, ax, title):
Kapileshwar Singhe1764fb2015-09-09 14:50:14 +0100102 """Plot a temperature histogram
103
104 :param ax: Axis instance
105 :type ax: :mod:`matplotlib.Axis`
106
107 :param title: The title of the plot
108 :type title: str
109 """
Javi Merinoec2ffe02015-12-07 15:05:13 +0000110 from trappy.plot_utils import normalize_title, plot_hist
Javi Merino1a3dca32014-08-11 16:12:50 +0100111
112 temps = self.data_frame["temp"] / 1000
113 title = normalize_title("Temperature", title)
114 xlim = (0, temps.max())
115
Javi Merino23dff5d2015-03-09 19:05:46 +0000116 plot_hist(temps, ax, title, "C", 30, "Temperature", xlim, "default")
Javi Merino1a3dca32014-08-11 16:12:50 +0100117
Javi Merino094e7422016-03-22 11:53:55 +0000118register_ftrace_parser(Thermal, "thermal")
Javi Merino323bb8d2015-04-20 17:09:15 +0100119
Dietmar Eggemannb42a50b2014-12-11 20:28:45 +0000120class ThermalGovernor(Base):
Javi Merino5bd3d442014-04-08 12:55:13 +0100121 """Process the power allocator data in a ftrace dump"""
KP Singh7319a882014-12-24 18:18:01 +0000122
Javi Merino00dac502015-06-19 16:54:14 +0100123 unique_word = "thermal_power_allocator:"
Kapileshwar Singhe1764fb2015-09-09 14:50:14 +0100124 """The unique word that will be matched in a trace line"""
125
Javi Merino00dac502015-06-19 16:54:14 +0100126 name = "thermal_governor"
Kapileshwar Singhe1764fb2015-09-09 14:50:14 +0100127 """The name of the :mod:`pandas.DataFrame` member that will be created in a
Javi Merinoc26a3232015-12-11 18:00:30 +0000128 :mod:`trappy.ftrace.FTrace` object"""
Kapileshwar Singhe1764fb2015-09-09 14:50:14 +0100129
Kapileshwar Singh01ed9102015-08-14 01:31:22 +0100130 pivot = "thermal_zone_id"
Kapileshwar Singhe1764fb2015-09-09 14:50:14 +0100131 """The Pivot along which the data is orthogonal"""
Kapileshwar Singh01ed9102015-08-14 01:31:22 +0100132
Javi Merinof521fba2015-02-06 18:22:09 +0000133 def plot_temperature(self, title="", width=None, height=None, ylim="range",
134 ax=None, legend_label=""):
135 """Plot the temperature"""
Javi Merinoec2ffe02015-12-07 15:05:13 +0000136 from matplotlib import pyplot as plt
137 from trappy.plot_utils import normalize_title, pre_plot_setup, post_plot_setup
138
Javi Merinof521fba2015-02-06 18:22:09 +0000139 dfr = self.data_frame
140 curr_temp = dfr["current_temperature"]
141 control_temp_series = (curr_temp + dfr["delta_temperature"]) / 1000
142 title = normalize_title("Temperature", title)
143
144 setup_plot = False
145 if not ax:
146 ax = pre_plot_setup(width, height)
147 setup_plot = True
148
149 temp_label = normalize_title("Temperature", legend_label)
150 (curr_temp / 1000).plot(ax=ax, label=temp_label)
151 control_temp_series.plot(ax=ax, color="y", linestyle="--",
152 label="control temperature")
153
154 if setup_plot:
155 post_plot_setup(ax, title=title, ylim=ylim)
156 plt.legend()
157
Javi Merino00dac502015-06-19 16:54:14 +0100158 def plot_input_power(self, actor_order, title="", width=None, height=None,
159 ax=None):
Javi Merinod6d5f892014-07-03 16:24:23 +0100160 """Plot input power
161
Kapileshwar Singhe1764fb2015-09-09 14:50:14 +0100162 :param ax: Axis instance
163 :type ax: :mod:`matplotlib.Axis`
Javi Merino00dac502015-06-19 16:54:14 +0100164
Kapileshwar Singhe1764fb2015-09-09 14:50:14 +0100165 :param title: The title of the plot
166 :type title: str
167
168 :param width: The width of the plot
169 :type width: int
170
171 :param height: The height of the plot
172 :type int: int
173
174 :param actor_order: An array showing the order in which the actors
175 were registered. The array values are the labels that
176 will be used in the input and output power plots.
177
178 For Example:
179 ::
180
181 ["GPU", "A15", "A7"]
182
183 :type actor_order: list
Javi Merinod6d5f892014-07-03 16:24:23 +0100184 """
Javi Merinoec2ffe02015-12-07 15:05:13 +0000185 from trappy.plot_utils import normalize_title, pre_plot_setup, post_plot_setup
Javi Merinod6d5f892014-07-03 16:24:23 +0100186
Javi Merino92f4d012014-08-08 17:55:32 +0100187 dfr = self.data_frame
Javi Merinof7968a72014-07-03 15:35:02 +0100188 in_cols = [s for s in dfr.columns if re.match("req_power[0-9]+", s)]
Javi Merinoe0ddf0d2014-05-07 18:40:12 +0100189
Javi Merinod6d5f892014-07-03 16:24:23 +0100190 plot_dfr = dfr[in_cols]
191 # Rename the columns from "req_power0" to "A15" or whatever is
192 # in actor_order. Note that we can do it just with an
193 # assignment because the columns are already sorted (i.e.:
194 # req_power0, req_power1...)
195 plot_dfr.columns = actor_order
196
Javi Merinoc00feff2014-04-14 15:41:51 +0100197 title = normalize_title("Input Power", title)
Javi Merino8ecd8172014-07-03 16:09:01 +0100198
Javi Merino29223812014-08-12 15:24:43 +0100199 if not ax:
200 ax = pre_plot_setup(width, height)
201
Javi Merinod6d5f892014-07-03 16:24:23 +0100202 plot_dfr.plot(ax=ax)
Javi Merino8ecd8172014-07-03 16:09:01 +0100203 post_plot_setup(ax, title=title)
Javi Merino9c010772014-04-02 16:54:41 +0100204
Javi Merino00dac502015-06-19 16:54:14 +0100205 def plot_weighted_input_power(self, actor_weights, title="", width=None,
206 height=None, ax=None):
Javi Merino898783c2015-06-16 11:45:16 +0100207 """Plot weighted input power
208
Kapileshwar Singhe1764fb2015-09-09 14:50:14 +0100209 :param actor_weights: An array of tuples. First element of the
210 tuple is the name of the actor, the second is the weight. The
211 array is in the same order as the :code:`req_power` appear in the
212 trace.
213 :type actor_weights: list
Javi Merino898783c2015-06-16 11:45:16 +0100214
Kapileshwar Singhe1764fb2015-09-09 14:50:14 +0100215 :param ax: Axis instance
216 :type ax: :mod:`matplotlib.Axis`
217
218 :param title: The title of the plot
219 :type title: str
220
221 :param width: The width of the plot
222 :type width: int
223
224 :param height: The height of the plot
225 :type int: int
Javi Merino898783c2015-06-16 11:45:16 +0100226 """
Javi Merinoec2ffe02015-12-07 15:05:13 +0000227 from trappy.plot_utils import normalize_title, pre_plot_setup, post_plot_setup
Javi Merino898783c2015-06-16 11:45:16 +0100228
229 dfr = self.data_frame
230 in_cols = [s for s in dfr.columns if re.match(r"req_power\d+", s)]
231
232 plot_dfr_dict = OrderedDict()
233 for in_col, (name, weight) in zip(in_cols, actor_weights):
234 plot_dfr_dict[name] = dfr[in_col] * weight / 1024
235
236 plot_dfr = pd.DataFrame(plot_dfr_dict)
237
238 title = normalize_title("Weighted Input Power", title)
239
240 if not ax:
241 ax = pre_plot_setup(width, height)
242
243 plot_dfr.plot(ax=ax)
244 post_plot_setup(ax, title=title)
245
Javi Merino00dac502015-06-19 16:54:14 +0100246 def plot_output_power(self, actor_order, title="", width=None, height=None,
247 ax=None):
Javi Merinod6d5f892014-07-03 16:24:23 +0100248 """Plot output power
249
Kapileshwar Singhe1764fb2015-09-09 14:50:14 +0100250 :param ax: Axis instance
251 :type ax: :mod:`matplotlib.Axis`
Javi Merino00dac502015-06-19 16:54:14 +0100252
Kapileshwar Singhe1764fb2015-09-09 14:50:14 +0100253 :param title: The title of the plot
254 :type title: str
255
256 :param width: The width of the plot
257 :type width: int
258
259 :param height: The height of the plot
260 :type int: int
261
262 :param actor_order: An array showing the order in which the actors
263 were registered. The array values are the labels that
264 will be used in the input and output power plots.
265
266 For Example:
267 ::
268
269 ["GPU", "A15", "A7"]
270
271 :type actor_order: list
Javi Merinod6d5f892014-07-03 16:24:23 +0100272 """
Javi Merinoec2ffe02015-12-07 15:05:13 +0000273 from trappy.plot_utils import normalize_title, pre_plot_setup, post_plot_setup
Javi Merinod6d5f892014-07-03 16:24:23 +0100274
Javi Merino92f4d012014-08-08 17:55:32 +0100275 out_cols = [s for s in self.data_frame.columns
Javi Merinof7968a72014-07-03 15:35:02 +0100276 if re.match("granted_power[0-9]+", s)]
Javi Merinoe0ddf0d2014-05-07 18:40:12 +0100277
Javi Merinod6d5f892014-07-03 16:24:23 +0100278 # See the note in plot_input_power()
Javi Merino92f4d012014-08-08 17:55:32 +0100279 plot_dfr = self.data_frame[out_cols]
Javi Merinod6d5f892014-07-03 16:24:23 +0100280 plot_dfr.columns = actor_order
281
Javi Merinoc00feff2014-04-14 15:41:51 +0100282 title = normalize_title("Output Power", title)
Javi Merino8ecd8172014-07-03 16:09:01 +0100283
Javi Merino6003b252014-08-12 15:32:17 +0100284 if not ax:
285 ax = pre_plot_setup(width, height)
286
Javi Merinod6d5f892014-07-03 16:24:23 +0100287 plot_dfr.plot(ax=ax)
Javi Merino8ecd8172014-07-03 16:09:01 +0100288 post_plot_setup(ax, title=title)
Javi Merinocd4a8272014-04-14 15:50:01 +0100289
Javi Merino00dac502015-06-19 16:54:14 +0100290 def plot_inout_power(self, title=""):
Kapileshwar Singhe1764fb2015-09-09 14:50:14 +0100291 """Make multiple plots showing input and output power for each actor
292
293 :param title: The title of the plot
294 :type title: str
295 """
Javi Merinoec2ffe02015-12-07 15:05:13 +0000296 from trappy.plot_utils import normalize_title
Javi Merino92f4d012014-08-08 17:55:32 +0100297 dfr = self.data_frame
Javi Merino9fc54852014-05-07 19:06:53 +0100298
299 actors = []
300 for col in dfr.columns:
Javi Merino00dac502015-06-19 16:54:14 +0100301 match = re.match("P(.*)_in", col)
302 if match and col != "Ptot_in":
303 actors.append(match.group(1))
Javi Merino9fc54852014-05-07 19:06:53 +0100304
305 for actor in actors:
306 cols = ["P" + actor + "_in", "P" + actor + "_out"]
307 this_title = normalize_title(actor, title)
308 dfr[cols].plot(title=this_title)
Javi Merino323bb8d2015-04-20 17:09:15 +0100309
Javi Merino094e7422016-03-22 11:53:55 +0000310register_ftrace_parser(ThermalGovernor, "thermal")