blob: 80de3df418d1341756ecb03d4e42642335516687 [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
31 unique_word="thermal_temperature:"
32 name="thermal"
33
Javi Merino6f34d902015-02-21 11:39:09 +000034 def __init__(self):
Javi Merino0e83b612014-06-05 11:45:23 +010035 super(Thermal, self).__init__(
KP Singh7319a882014-12-24 18:18:01 +000036 unique_word=self.unique_word,
Javi Merino0e83b612014-06-05 11:45:23 +010037 )
38
Javi Merino516d5942014-06-26 15:06:04 +010039 def plot_temperature(self, control_temperature=None, title="", width=None,
Javi Merino80114162014-08-08 16:48:32 +010040 height=None, ylim="range", ax=None, legend_label=""):
Javi Merino516d5942014-06-26 15:06:04 +010041 """Plot the temperature.
42
43 If control_temp is a pd.Series() representing the (possible)
44 variation of control_temp during the run, draw it using a
45 dashed yellow line. Otherwise, only the temperature is
46 plotted.
47
48 """
Javi Merinoc68737a2014-06-10 15:21:59 +010049 title = normalize_title("Temperature", title)
50
Javi Merino7e924022015-02-06 17:58:46 +000051 if len(self.data_frame) == 0:
52 raise ValueError("Empty DataFrame")
53
Javi Merino49cbcfe2014-08-08 16:03:49 +010054 setup_plot = False
55 if not ax:
56 ax = pre_plot_setup(width, height)
57 setup_plot = True
58
Javi Merino80114162014-08-08 16:48:32 +010059 temp_label = normalize_title("Temperature", legend_label)
Javi Merino92f4d012014-08-08 17:55:32 +010060 (self.data_frame["temp"] / 1000).plot(ax=ax, label=temp_label)
Javi Merino516d5942014-06-26 15:06:04 +010061 if control_temperature is not None:
Javi Merino80114162014-08-08 16:48:32 +010062 ct_label = normalize_title("Control", legend_label)
Javi Merino516d5942014-06-26 15:06:04 +010063 control_temperature.plot(ax=ax, color="y", linestyle="--",
Javi Merino80114162014-08-08 16:48:32 +010064 label=ct_label)
Javi Merinoc68737a2014-06-10 15:21:59 +010065
Javi Merino49cbcfe2014-08-08 16:03:49 +010066 if setup_plot:
67 post_plot_setup(ax, title=title, ylim=ylim)
68 plt.legend()
Javi Merinoc68737a2014-06-10 15:21:59 +010069
Javi Merinoe5ea60a2014-08-12 16:41:42 +010070 def plot_temperature_hist(self, ax, title):
Javi Merino1a3dca32014-08-11 16:12:50 +010071 """Plot a temperature histogram"""
72
73 temps = self.data_frame["temp"] / 1000
74 title = normalize_title("Temperature", title)
75 xlim = (0, temps.max())
76
Javi Merino23dff5d2015-03-09 19:05:46 +000077 plot_hist(temps, ax, title, "C", 30, "Temperature", xlim, "default")
Javi Merino1a3dca32014-08-11 16:12:50 +010078
Javi Merino323bb8d2015-04-20 17:09:15 +010079Run.register_class(Thermal, "thermal")
80
Dietmar Eggemannb42a50b2014-12-11 20:28:45 +000081class ThermalGovernor(Base):
Javi Merino5bd3d442014-04-08 12:55:13 +010082 """Process the power allocator data in a ftrace dump"""
KP Singh7319a882014-12-24 18:18:01 +000083
84 unique_word="thermal_power_allocator:"
85 name="thermal_governor"
Javi Merino6f34d902015-02-21 11:39:09 +000086 def __init__(self):
Javi Merino1e69e2c2014-06-04 18:25:09 +010087 super(ThermalGovernor, self).__init__(
KP Singh7319a882014-12-24 18:18:01 +000088 unique_word=self.unique_word,
Javi Merinoc2ec5682014-04-01 15:16:06 +010089 )
90
Javi Merinof521fba2015-02-06 18:22:09 +000091 def plot_temperature(self, title="", width=None, height=None, ylim="range",
92 ax=None, legend_label=""):
93 """Plot the temperature"""
94 dfr = self.data_frame
95 curr_temp = dfr["current_temperature"]
96 control_temp_series = (curr_temp + dfr["delta_temperature"]) / 1000
97 title = normalize_title("Temperature", title)
98
99 setup_plot = False
100 if not ax:
101 ax = pre_plot_setup(width, height)
102 setup_plot = True
103
104 temp_label = normalize_title("Temperature", legend_label)
105 (curr_temp / 1000).plot(ax=ax, label=temp_label)
106 control_temp_series.plot(ax=ax, color="y", linestyle="--",
107 label="control temperature")
108
109 if setup_plot:
110 post_plot_setup(ax, title=title, ylim=ylim)
111 plt.legend()
112
Javi Merino29223812014-08-12 15:24:43 +0100113 def plot_input_power(self, actor_order, title="", width=None, height=None, ax=None):
Javi Merinod6d5f892014-07-03 16:24:23 +0100114 """Plot input power
115
116 actor_order is an array with the order in which the actors were registered.
117 """
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 Merino898783c2015-06-16 11:45:16 +0100137 def plot_weighted_input_power(self, actor_weights, title="", width=None, height=None, ax=None):
138 """Plot weighted input power
139
140 actor_weights is an array of tuples. First element of the
141 tuple is the name of the actor, the second is the weight. The
142 array is in the same order as the req_power appear in the
143 trace.
144
145 """
146
147 dfr = self.data_frame
148 in_cols = [s for s in dfr.columns if re.match(r"req_power\d+", s)]
149
150 plot_dfr_dict = OrderedDict()
151 for in_col, (name, weight) in zip(in_cols, actor_weights):
152 plot_dfr_dict[name] = dfr[in_col] * weight / 1024
153
154 plot_dfr = pd.DataFrame(plot_dfr_dict)
155
156 title = normalize_title("Weighted Input Power", title)
157
158 if not ax:
159 ax = pre_plot_setup(width, height)
160
161 plot_dfr.plot(ax=ax)
162 post_plot_setup(ax, title=title)
163
Javi Merino6003b252014-08-12 15:32:17 +0100164 def plot_output_power(self, actor_order, title="", width=None, height=None, ax=None):
Javi Merinod6d5f892014-07-03 16:24:23 +0100165 """Plot output power
166
167 actor_order is an array with the order in which the actors were registered.
168 """
169
Javi Merino92f4d012014-08-08 17:55:32 +0100170 out_cols = [s for s in self.data_frame.columns
Javi Merinof7968a72014-07-03 15:35:02 +0100171 if re.match("granted_power[0-9]+", s)]
Javi Merinoe0ddf0d2014-05-07 18:40:12 +0100172
Javi Merinod6d5f892014-07-03 16:24:23 +0100173 # See the note in plot_input_power()
Javi Merino92f4d012014-08-08 17:55:32 +0100174 plot_dfr = self.data_frame[out_cols]
Javi Merinod6d5f892014-07-03 16:24:23 +0100175 plot_dfr.columns = actor_order
176
Javi Merinoc00feff2014-04-14 15:41:51 +0100177 title = normalize_title("Output Power", title)
Javi Merino8ecd8172014-07-03 16:09:01 +0100178
Javi Merino6003b252014-08-12 15:32:17 +0100179 if not ax:
180 ax = pre_plot_setup(width, height)
181
Javi Merinod6d5f892014-07-03 16:24:23 +0100182 plot_dfr.plot(ax=ax)
Javi Merino8ecd8172014-07-03 16:09:01 +0100183 post_plot_setup(ax, title=title)
Javi Merinocd4a8272014-04-14 15:50:01 +0100184
Javi Merino9fc54852014-05-07 19:06:53 +0100185 def plot_inout_power(self, title="", width=None, height=None):
186 """Make multiple plots showing input and output power for each actor"""
Javi Merino92f4d012014-08-08 17:55:32 +0100187 dfr = self.data_frame
Javi Merino9fc54852014-05-07 19:06:53 +0100188
189 actors = []
190 for col in dfr.columns:
191 match = re.match("P(.*)_in", col)
192 if match and col != "Ptot_in":
193 actors.append(match.group(1))
194
195 for actor in actors:
196 cols = ["P" + actor + "_in", "P" + actor + "_out"]
197 this_title = normalize_title(actor, title)
198 dfr[cols].plot(title=this_title)
Javi Merino323bb8d2015-04-20 17:09:15 +0100199
200Run.register_class(ThermalGovernor, "thermal")