• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#    Copyright 2015-2017 ARM Limited
2#
3# 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
16"""Process the output of the power allocator trace in the current
17directory's trace.dat"""
18
19from collections import OrderedDict
20import pandas as pd
21import re
22
23from trappy.base import Base
24from trappy.dynamic import register_ftrace_parser
25
26class Thermal(Base):
27    """Process the thermal framework data in a FTrace dump"""
28
29    unique_word = "thermal_temperature:"
30    """The unique word that will be matched in a trace line"""
31
32    name = "thermal"
33    """The name of the :mod:`pandas.DataFrame` member that will be created in a
34    :mod:`trappy.ftrace.FTrace` object"""
35
36    pivot = "id"
37    """The Pivot along which the data is orthogonal"""
38
39    def plot_temperature(self, control_temperature=None, title="", width=None,
40                         height=None, ylim="range", ax=None, legend_label="",
41                         tz_id=None):
42        """Plot the temperature.
43
44        :param ax: Axis instance
45        :type ax: :mod:`matplotlib.Axis`
46
47        :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
64        :type height: int
65
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
70        """
71        from matplotlib import pyplot as plt
72        from trappy.plot_utils import normalize_title, pre_plot_setup, post_plot_setup
73
74        title = normalize_title("Temperature", title)
75
76        if len(self.data_frame) == 0:
77            raise ValueError("Empty DataFrame")
78
79        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
85        setup_plot = False
86        if not ax:
87            ax = pre_plot_setup(width, height)
88            setup_plot = True
89
90        temp_label = normalize_title("Temperature", legend_label)
91        (thermal_dfr["temp"] / 1000).plot(ax=ax, label=temp_label)
92        if control_temperature is not None:
93            ct_label = normalize_title("Control", legend_label)
94            control_temperature.plot(ax=ax, color="y", linestyle="--",
95                           label=ct_label)
96
97        if setup_plot:
98            post_plot_setup(ax, title=title, ylim=ylim)
99            plt.legend()
100
101    def plot_temperature_hist(self, ax, title):
102        """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        """
110        from trappy.plot_utils import normalize_title, plot_hist
111
112        temps = self.data_frame["temp"] / 1000
113        title = normalize_title("Temperature", title)
114        xlim = (0, temps.max())
115
116        plot_hist(temps, ax, title, "C", 30, "Temperature", xlim, "default")
117
118register_ftrace_parser(Thermal, "thermal")
119
120class ThermalGovernor(Base):
121    """Process the power allocator data in a ftrace dump"""
122
123    unique_word = "thermal_power_allocator:"
124    """The unique word that will be matched in a trace line"""
125
126    name = "thermal_governor"
127    """The name of the :mod:`pandas.DataFrame` member that will be created in a
128    :mod:`trappy.ftrace.FTrace` object"""
129
130    pivot = "thermal_zone_id"
131    """The Pivot along which the data is orthogonal"""
132
133    def plot_temperature(self, title="", width=None, height=None, ylim="range",
134                         ax=None, legend_label=""):
135        """Plot the temperature"""
136        from matplotlib import pyplot as plt
137        from trappy.plot_utils import normalize_title, pre_plot_setup, post_plot_setup
138
139        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
158    def plot_input_power(self, actor_order, title="", width=None, height=None,
159                         ax=None):
160        """Plot input power
161
162        :param ax: Axis instance
163        :type ax: :mod:`matplotlib.Axis`
164
165        :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
184        """
185        from trappy.plot_utils import normalize_title, pre_plot_setup, post_plot_setup
186
187        dfr = self.data_frame
188        in_cols = [s for s in dfr.columns if re.match("req_power[0-9]+", s)]
189
190        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
197        title = normalize_title("Input Power", title)
198
199        if not ax:
200            ax = pre_plot_setup(width, height)
201
202        plot_dfr.plot(ax=ax)
203        post_plot_setup(ax, title=title)
204
205    def plot_weighted_input_power(self, actor_weights, title="", width=None,
206                                  height=None, ax=None):
207        """Plot weighted input power
208
209        :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
214
215        :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
226        """
227        from trappy.plot_utils import normalize_title, pre_plot_setup, post_plot_setup
228
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
246    def plot_output_power(self, actor_order, title="", width=None, height=None,
247                          ax=None):
248        """Plot output power
249
250        :param ax: Axis instance
251        :type ax: :mod:`matplotlib.Axis`
252
253        :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
272        """
273        from trappy.plot_utils import normalize_title, pre_plot_setup, post_plot_setup
274
275        out_cols = [s for s in self.data_frame.columns
276                    if re.match("granted_power[0-9]+", s)]
277
278        # See the note in plot_input_power()
279        plot_dfr = self.data_frame[out_cols]
280        plot_dfr.columns = actor_order
281
282        title = normalize_title("Output Power", title)
283
284        if not ax:
285            ax = pre_plot_setup(width, height)
286
287        plot_dfr.plot(ax=ax)
288        post_plot_setup(ax, title=title)
289
290    def plot_inout_power(self, title=""):
291        """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        """
296        from trappy.plot_utils import normalize_title
297        dfr = self.data_frame
298
299        actors = []
300        for col in dfr.columns:
301            match = re.match("P(.*)_in", col)
302            if match and col != "Ptot_in":
303                actors.append(match.group(1))
304
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)
309
310register_ftrace_parser(ThermalGovernor, "thermal")
311