blob: 475bce5c36b5fa580b72baf668445eb762ec3722 [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 Merino898783c2015-06-16 11:45:16 +010020import pandas as pd
Javi Merinoee56c362014-03-31 17:30:34 +010021import re
Javi Merinoa6399fb2014-03-31 19:17:08 +010022from matplotlib import pyplot as plt
Javi Merino572049d2014-03-31 16:45:23 +010023
Javi Merino91e92dc2015-06-17 17:02:03 +010024from cr2.base import Base
Javi Merino323bb8d2015-04-20 17:09:15 +010025from cr2.run import Run
Javi Merino91e92dc2015-06-17 17:02:03 +010026from cr2.plot_utils import normalize_title, pre_plot_setup, post_plot_setup, plot_hist
Javi Merino51db3632014-06-13 11:24:51 +010027
Dietmar Eggemannb42a50b2014-12-11 20:28:45 +000028class Thermal(Base):
Javi Merino0e83b612014-06-05 11:45:23 +010029 """Process the thermal framework data in a ftrace dump"""
KP Singh7319a882014-12-24 18:18:01 +000030
Javi Merino00dac502015-06-19 16:54:14 +010031 unique_word = "thermal_temperature:"
32 name = "thermal"
KP Singh7319a882014-12-24 18:18:01 +000033
Javi Merino6f34d902015-02-21 11:39:09 +000034 def __init__(self):
Javi Merino00dac502015-06-19 16:54:14 +010035 super(Thermal, self).__init__(unique_word=self.unique_word)
Javi Merino0e83b612014-06-05 11:45:23 +010036
Javi Merino516d5942014-06-26 15:06:04 +010037 def plot_temperature(self, control_temperature=None, title="", width=None,
Javi Merino80114162014-08-08 16:48:32 +010038 height=None, ylim="range", ax=None, legend_label=""):
Javi Merino516d5942014-06-26 15:06:04 +010039 """Plot the temperature.
40
41 If control_temp is a pd.Series() representing the (possible)
42 variation of control_temp during the run, draw it using a
43 dashed yellow line. Otherwise, only the temperature is
44 plotted.
45
46 """
Javi Merinoc68737a2014-06-10 15:21:59 +010047 title = normalize_title("Temperature", title)
48
Javi Merino7e924022015-02-06 17:58:46 +000049 if len(self.data_frame) == 0:
50 raise ValueError("Empty DataFrame")
51
Javi Merino49cbcfe2014-08-08 16:03:49 +010052 setup_plot = False
53 if not ax:
54 ax = pre_plot_setup(width, height)
55 setup_plot = True
56
Javi Merino80114162014-08-08 16:48:32 +010057 temp_label = normalize_title("Temperature", legend_label)
Javi Merino92f4d012014-08-08 17:55:32 +010058 (self.data_frame["temp"] / 1000).plot(ax=ax, label=temp_label)
Javi Merino516d5942014-06-26 15:06:04 +010059 if control_temperature is not None:
Javi Merino80114162014-08-08 16:48:32 +010060 ct_label = normalize_title("Control", legend_label)
Javi Merino516d5942014-06-26 15:06:04 +010061 control_temperature.plot(ax=ax, color="y", linestyle="--",
Javi Merino80114162014-08-08 16:48:32 +010062 label=ct_label)
Javi Merinoc68737a2014-06-10 15:21:59 +010063
Javi Merino49cbcfe2014-08-08 16:03:49 +010064 if setup_plot:
65 post_plot_setup(ax, title=title, ylim=ylim)
66 plt.legend()
Javi Merinoc68737a2014-06-10 15:21:59 +010067
Javi Merinoe5ea60a2014-08-12 16:41:42 +010068 def plot_temperature_hist(self, ax, title):
Javi Merino1a3dca32014-08-11 16:12:50 +010069 """Plot a temperature histogram"""
70
71 temps = self.data_frame["temp"] / 1000
72 title = normalize_title("Temperature", title)
73 xlim = (0, temps.max())
74
Javi Merino23dff5d2015-03-09 19:05:46 +000075 plot_hist(temps, ax, title, "C", 30, "Temperature", xlim, "default")
Javi Merino1a3dca32014-08-11 16:12:50 +010076
Javi Merino323bb8d2015-04-20 17:09:15 +010077Run.register_class(Thermal, "thermal")
78
Dietmar Eggemannb42a50b2014-12-11 20:28:45 +000079class ThermalGovernor(Base):
Javi Merino5bd3d442014-04-08 12:55:13 +010080 """Process the power allocator data in a ftrace dump"""
KP Singh7319a882014-12-24 18:18:01 +000081
Javi Merino00dac502015-06-19 16:54:14 +010082 unique_word = "thermal_power_allocator:"
83 name = "thermal_governor"
Javi Merino6f34d902015-02-21 11:39:09 +000084 def __init__(self):
Javi Merino1e69e2c2014-06-04 18:25:09 +010085 super(ThermalGovernor, self).__init__(
KP Singh7319a882014-12-24 18:18:01 +000086 unique_word=self.unique_word,
Javi Merinoc2ec5682014-04-01 15:16:06 +010087 )
88
Javi Merinof521fba2015-02-06 18:22:09 +000089 def plot_temperature(self, title="", width=None, height=None, ylim="range",
90 ax=None, legend_label=""):
91 """Plot the temperature"""
92 dfr = self.data_frame
93 curr_temp = dfr["current_temperature"]
94 control_temp_series = (curr_temp + dfr["delta_temperature"]) / 1000
95 title = normalize_title("Temperature", title)
96
97 setup_plot = False
98 if not ax:
99 ax = pre_plot_setup(width, height)
100 setup_plot = True
101
102 temp_label = normalize_title("Temperature", legend_label)
103 (curr_temp / 1000).plot(ax=ax, label=temp_label)
104 control_temp_series.plot(ax=ax, color="y", linestyle="--",
105 label="control temperature")
106
107 if setup_plot:
108 post_plot_setup(ax, title=title, ylim=ylim)
109 plt.legend()
110
Javi Merino00dac502015-06-19 16:54:14 +0100111 def plot_input_power(self, actor_order, title="", width=None, height=None,
112 ax=None):
Javi Merinod6d5f892014-07-03 16:24:23 +0100113 """Plot input power
114
Javi Merino00dac502015-06-19 16:54:14 +0100115 actor_order is an array with the order in which the actors
116 were registered.
117
Javi Merinod6d5f892014-07-03 16:24:23 +0100118 """
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 Merino00dac502015-06-19 16:54:14 +0100138 def plot_weighted_input_power(self, actor_weights, title="", width=None,
139 height=None, ax=None):
Javi Merino898783c2015-06-16 11:45:16 +0100140 """Plot weighted input power
141
142 actor_weights is an array of tuples. First element of the
143 tuple is the name of the actor, the second is the weight. The
144 array is in the same order as the req_power appear in the
145 trace.
146
147 """
148
149 dfr = self.data_frame
150 in_cols = [s for s in dfr.columns if re.match(r"req_power\d+", s)]
151
152 plot_dfr_dict = OrderedDict()
153 for in_col, (name, weight) in zip(in_cols, actor_weights):
154 plot_dfr_dict[name] = dfr[in_col] * weight / 1024
155
156 plot_dfr = pd.DataFrame(plot_dfr_dict)
157
158 title = normalize_title("Weighted Input Power", title)
159
160 if not ax:
161 ax = pre_plot_setup(width, height)
162
163 plot_dfr.plot(ax=ax)
164 post_plot_setup(ax, title=title)
165
Javi Merino00dac502015-06-19 16:54:14 +0100166 def plot_output_power(self, actor_order, title="", width=None, height=None,
167 ax=None):
Javi Merinod6d5f892014-07-03 16:24:23 +0100168 """Plot output power
169
Javi Merino00dac502015-06-19 16:54:14 +0100170 actor_order is an array with the order in which the actors
171 were registered.
172
Javi Merinod6d5f892014-07-03 16:24:23 +0100173 """
174
Javi Merino92f4d012014-08-08 17:55:32 +0100175 out_cols = [s for s in self.data_frame.columns
Javi Merinof7968a72014-07-03 15:35:02 +0100176 if re.match("granted_power[0-9]+", s)]
Javi Merinoe0ddf0d2014-05-07 18:40:12 +0100177
Javi Merinod6d5f892014-07-03 16:24:23 +0100178 # See the note in plot_input_power()
Javi Merino92f4d012014-08-08 17:55:32 +0100179 plot_dfr = self.data_frame[out_cols]
Javi Merinod6d5f892014-07-03 16:24:23 +0100180 plot_dfr.columns = actor_order
181
Javi Merinoc00feff2014-04-14 15:41:51 +0100182 title = normalize_title("Output Power", title)
Javi Merino8ecd8172014-07-03 16:09:01 +0100183
Javi Merino6003b252014-08-12 15:32:17 +0100184 if not ax:
185 ax = pre_plot_setup(width, height)
186
Javi Merinod6d5f892014-07-03 16:24:23 +0100187 plot_dfr.plot(ax=ax)
Javi Merino8ecd8172014-07-03 16:09:01 +0100188 post_plot_setup(ax, title=title)
Javi Merinocd4a8272014-04-14 15:50:01 +0100189
Javi Merino00dac502015-06-19 16:54:14 +0100190 def plot_inout_power(self, title=""):
Javi Merino9fc54852014-05-07 19:06:53 +0100191 """Make multiple plots showing input and output power for each actor"""
Javi Merino92f4d012014-08-08 17:55:32 +0100192 dfr = self.data_frame
Javi Merino9fc54852014-05-07 19:06:53 +0100193
194 actors = []
195 for col in dfr.columns:
Javi Merino00dac502015-06-19 16:54:14 +0100196 match = re.match("P(.*)_in", col)
197 if match and col != "Ptot_in":
198 actors.append(match.group(1))
Javi Merino9fc54852014-05-07 19:06:53 +0100199
200 for actor in actors:
201 cols = ["P" + actor + "_in", "P" + actor + "_out"]
202 this_title = normalize_title(actor, title)
203 dfr[cols].plot(title=this_title)
Javi Merino323bb8d2015-04-20 17:09:15 +0100204
205Run.register_class(ThermalGovernor, "thermal")