blob: 132001ef94db9ee43215be28f7196271f3f162fc [file] [log] [blame]
Javi Merinoc47d2df2015-02-06 16:04:03 +00001# $Copyright:
2# ----------------------------------------------------------------
3# This confidential and proprietary software may be used only as
4# authorised by a licensing agreement from ARM Limited
5# (C) COPYRIGHT 2015 ARM Limited
6# ALL RIGHTS RESERVED
7# The entire notice above must be reproduced on all authorised
8# copies and copies may only be made to the extent permitted
9# by a licensing agreement from ARM Limited.
10# ----------------------------------------------------------------
11# File: thermal.py
12# ----------------------------------------------------------------
13# $
14#
Javi Merino5bd3d442014-04-08 12:55:13 +010015"""Process the output of the power allocator trace in the current
16directory's trace.dat"""
Javi Merino572049d2014-03-31 16:45:23 +010017
Javi Merino898783c2015-06-16 11:45:16 +010018from collections import OrderedDict
Javi Merino898783c2015-06-16 11:45:16 +010019import pandas as pd
Javi Merinoee56c362014-03-31 17:30:34 +010020import re
Javi Merinoa6399fb2014-03-31 19:17:08 +010021from matplotlib import pyplot as plt
Javi Merino572049d2014-03-31 16:45:23 +010022
Javi Merino91e92dc2015-06-17 17:02:03 +010023from cr2.base import Base
Javi Merino323bb8d2015-04-20 17:09:15 +010024from cr2.run import Run
Javi Merino91e92dc2015-06-17 17:02:03 +010025from cr2.plot_utils import normalize_title, pre_plot_setup, post_plot_setup, plot_hist
Javi Merino51db3632014-06-13 11:24:51 +010026
Dietmar Eggemannb42a50b2014-12-11 20:28:45 +000027class Thermal(Base):
Javi Merino0e83b612014-06-05 11:45:23 +010028 """Process the thermal framework data in a ftrace dump"""
KP Singh7319a882014-12-24 18:18:01 +000029
Javi Merino00dac502015-06-19 16:54:14 +010030 unique_word = "thermal_temperature:"
31 name = "thermal"
KP Singh7319a882014-12-24 18:18:01 +000032
Javi Merino6f34d902015-02-21 11:39:09 +000033 def __init__(self):
Javi Merino00dac502015-06-19 16:54:14 +010034 super(Thermal, self).__init__(unique_word=self.unique_word)
Javi Merino0e83b612014-06-05 11:45:23 +010035
Javi Merino516d5942014-06-26 15:06:04 +010036 def plot_temperature(self, control_temperature=None, title="", width=None,
Javi Merino80114162014-08-08 16:48:32 +010037 height=None, ylim="range", ax=None, legend_label=""):
Javi Merino516d5942014-06-26 15:06:04 +010038 """Plot the temperature.
39
40 If control_temp is a pd.Series() representing the (possible)
41 variation of control_temp during the run, draw it using a
42 dashed yellow line. Otherwise, only the temperature is
43 plotted.
44
45 """
Javi Merinoc68737a2014-06-10 15:21:59 +010046 title = normalize_title("Temperature", title)
47
Javi Merino7e924022015-02-06 17:58:46 +000048 if len(self.data_frame) == 0:
49 raise ValueError("Empty DataFrame")
50
Javi Merino49cbcfe2014-08-08 16:03:49 +010051 setup_plot = False
52 if not ax:
53 ax = pre_plot_setup(width, height)
54 setup_plot = True
55
Javi Merino80114162014-08-08 16:48:32 +010056 temp_label = normalize_title("Temperature", legend_label)
Javi Merino92f4d012014-08-08 17:55:32 +010057 (self.data_frame["temp"] / 1000).plot(ax=ax, label=temp_label)
Javi Merino516d5942014-06-26 15:06:04 +010058 if control_temperature is not None:
Javi Merino80114162014-08-08 16:48:32 +010059 ct_label = normalize_title("Control", legend_label)
Javi Merino516d5942014-06-26 15:06:04 +010060 control_temperature.plot(ax=ax, color="y", linestyle="--",
Javi Merino80114162014-08-08 16:48:32 +010061 label=ct_label)
Javi Merinoc68737a2014-06-10 15:21:59 +010062
Javi Merino49cbcfe2014-08-08 16:03:49 +010063 if setup_plot:
64 post_plot_setup(ax, title=title, ylim=ylim)
65 plt.legend()
Javi Merinoc68737a2014-06-10 15:21:59 +010066
Javi Merinoe5ea60a2014-08-12 16:41:42 +010067 def plot_temperature_hist(self, ax, title):
Javi Merino1a3dca32014-08-11 16:12:50 +010068 """Plot a temperature histogram"""
69
70 temps = self.data_frame["temp"] / 1000
71 title = normalize_title("Temperature", title)
72 xlim = (0, temps.max())
73
Javi Merino23dff5d2015-03-09 19:05:46 +000074 plot_hist(temps, ax, title, "C", 30, "Temperature", xlim, "default")
Javi Merino1a3dca32014-08-11 16:12:50 +010075
Javi Merino323bb8d2015-04-20 17:09:15 +010076Run.register_class(Thermal, "thermal")
77
Dietmar Eggemannb42a50b2014-12-11 20:28:45 +000078class ThermalGovernor(Base):
Javi Merino5bd3d442014-04-08 12:55:13 +010079 """Process the power allocator data in a ftrace dump"""
KP Singh7319a882014-12-24 18:18:01 +000080
Javi Merino00dac502015-06-19 16:54:14 +010081 unique_word = "thermal_power_allocator:"
82 name = "thermal_governor"
Javi Merino6f34d902015-02-21 11:39:09 +000083 def __init__(self):
Javi Merino1e69e2c2014-06-04 18:25:09 +010084 super(ThermalGovernor, self).__init__(
KP Singh7319a882014-12-24 18:18:01 +000085 unique_word=self.unique_word,
Javi Merinoc2ec5682014-04-01 15:16:06 +010086 )
87
Javi Merinof521fba2015-02-06 18:22:09 +000088 def plot_temperature(self, title="", width=None, height=None, ylim="range",
89 ax=None, legend_label=""):
90 """Plot the temperature"""
91 dfr = self.data_frame
92 curr_temp = dfr["current_temperature"]
93 control_temp_series = (curr_temp + dfr["delta_temperature"]) / 1000
94 title = normalize_title("Temperature", title)
95
96 setup_plot = False
97 if not ax:
98 ax = pre_plot_setup(width, height)
99 setup_plot = True
100
101 temp_label = normalize_title("Temperature", legend_label)
102 (curr_temp / 1000).plot(ax=ax, label=temp_label)
103 control_temp_series.plot(ax=ax, color="y", linestyle="--",
104 label="control temperature")
105
106 if setup_plot:
107 post_plot_setup(ax, title=title, ylim=ylim)
108 plt.legend()
109
Javi Merino00dac502015-06-19 16:54:14 +0100110 def plot_input_power(self, actor_order, title="", width=None, height=None,
111 ax=None):
Javi Merinod6d5f892014-07-03 16:24:23 +0100112 """Plot input power
113
Javi Merino00dac502015-06-19 16:54:14 +0100114 actor_order is an array with the order in which the actors
115 were registered.
116
Javi Merinod6d5f892014-07-03 16:24:23 +0100117 """
118
Javi Merino92f4d012014-08-08 17:55:32 +0100119 dfr = self.data_frame
Javi Merinof7968a72014-07-03 15:35:02 +0100120 in_cols = [s for s in dfr.columns if re.match("req_power[0-9]+", s)]
Javi Merinoe0ddf0d2014-05-07 18:40:12 +0100121
Javi Merinod6d5f892014-07-03 16:24:23 +0100122 plot_dfr = dfr[in_cols]
123 # Rename the columns from "req_power0" to "A15" or whatever is
124 # in actor_order. Note that we can do it just with an
125 # assignment because the columns are already sorted (i.e.:
126 # req_power0, req_power1...)
127 plot_dfr.columns = actor_order
128
Javi Merinoc00feff2014-04-14 15:41:51 +0100129 title = normalize_title("Input Power", title)
Javi Merino8ecd8172014-07-03 16:09:01 +0100130
Javi Merino29223812014-08-12 15:24:43 +0100131 if not ax:
132 ax = pre_plot_setup(width, height)
133
Javi Merinod6d5f892014-07-03 16:24:23 +0100134 plot_dfr.plot(ax=ax)
Javi Merino8ecd8172014-07-03 16:09:01 +0100135 post_plot_setup(ax, title=title)
Javi Merino9c010772014-04-02 16:54:41 +0100136
Javi Merino00dac502015-06-19 16:54:14 +0100137 def plot_weighted_input_power(self, actor_weights, title="", width=None,
138 height=None, ax=None):
Javi Merino898783c2015-06-16 11:45:16 +0100139 """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 Merino00dac502015-06-19 16:54:14 +0100165 def plot_output_power(self, actor_order, title="", width=None, height=None,
166 ax=None):
Javi Merinod6d5f892014-07-03 16:24:23 +0100167 """Plot output power
168
Javi Merino00dac502015-06-19 16:54:14 +0100169 actor_order is an array with the order in which the actors
170 were registered.
171
Javi Merinod6d5f892014-07-03 16:24:23 +0100172 """
173
Javi Merino92f4d012014-08-08 17:55:32 +0100174 out_cols = [s for s in self.data_frame.columns
Javi Merinof7968a72014-07-03 15:35:02 +0100175 if re.match("granted_power[0-9]+", s)]
Javi Merinoe0ddf0d2014-05-07 18:40:12 +0100176
Javi Merinod6d5f892014-07-03 16:24:23 +0100177 # See the note in plot_input_power()
Javi Merino92f4d012014-08-08 17:55:32 +0100178 plot_dfr = self.data_frame[out_cols]
Javi Merinod6d5f892014-07-03 16:24:23 +0100179 plot_dfr.columns = actor_order
180
Javi Merinoc00feff2014-04-14 15:41:51 +0100181 title = normalize_title("Output Power", title)
Javi Merino8ecd8172014-07-03 16:09:01 +0100182
Javi Merino6003b252014-08-12 15:32:17 +0100183 if not ax:
184 ax = pre_plot_setup(width, height)
185
Javi Merinod6d5f892014-07-03 16:24:23 +0100186 plot_dfr.plot(ax=ax)
Javi Merino8ecd8172014-07-03 16:09:01 +0100187 post_plot_setup(ax, title=title)
Javi Merinocd4a8272014-04-14 15:50:01 +0100188
Javi Merino00dac502015-06-19 16:54:14 +0100189 def plot_inout_power(self, title=""):
Javi Merino9fc54852014-05-07 19:06:53 +0100190 """Make multiple plots showing input and output power for each actor"""
Javi Merino92f4d012014-08-08 17:55:32 +0100191 dfr = self.data_frame
Javi Merino9fc54852014-05-07 19:06:53 +0100192
193 actors = []
194 for col in dfr.columns:
Javi Merino00dac502015-06-19 16:54:14 +0100195 match = re.match("P(.*)_in", col)
196 if match and col != "Ptot_in":
197 actors.append(match.group(1))
Javi Merino9fc54852014-05-07 19:06:53 +0100198
199 for actor in actors:
200 cols = ["P" + actor + "_in", "P" + actor + "_out"]
201 this_title = normalize_title(actor, title)
202 dfr[cols].plot(title=this_title)
Javi Merino323bb8d2015-04-20 17:09:15 +0100203
204Run.register_class(ThermalGovernor, "thermal")