1#    Copyright 2015-2016 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"""A thermal specific library to assert certain thermal
16behaviours
17"""
18
19from bart.common import Utils
20from bart.common.Analyzer import Analyzer
21import numpy as np
22
23
24# pylint: disable=invalid-name
25# pylint: disable=too-many-arguments
26class ThermalAssert(object):
27
28    """A class that accepts a TRAPpy FTrace object and
29    provides assertions for thermal behaviours
30
31    :param ftrace: A path to the trace file or a TRAPpy FTrace object
32    :type ftrace: str, :mod:`trappy.ftrace.FTrace`
33    """
34
35    def __init__(self, ftrace, config=None):
36
37        self._ftrace = Utils.init_ftrace(ftrace)
38        self._analyzer = Analyzer(self._ftrace, config)
39
40    def getThermalResidency(self, temp_range, window, percent=False):
41        """Return the total time spent in a given temperature range
42
43        :param temp_range: A tuple of (low_temp, high_temp)
44            which specifies the range of temperature that
45            one intends to calculate the residency for.
46        :type temp_range: tuple
47
48        :param window: A (start, end) tuple to limit the scope of the
49            residency calculation.
50        :type window: tuple
51
52        :param percent: Returns the residency as a percentage of the total
53            duration of the trace
54        :type percent: bool
55
56        .. seealso:
57
58            :mod:`bart.thermal.ThermalAssert.ThermalAssert.assertThermalResidency`
59        """
60
61        # Get a pivoted thermal temperature data using the grammar
62        data = self._analyzer.getStatement("trappy.thermal.Thermal:temp")
63
64        result = {}
65        for pivot, data_frame in data.groupby(axis=1, level=0):
66
67            series = data_frame[pivot]
68            series = Utils.select_window(series, window)
69            mask = (series >= temp_range[0]) & (series <= temp_range[1])
70            index = series.index.values
71            # pylint fails to recognize numpy members.
72            # pylint: disable=no-member
73            shift_index = np.roll(index, 1)
74            # pylint: enable=no-member
75            shift_index[0] = 0
76
77            result[pivot] = sum((index - shift_index)[mask.values])
78
79            if percent:
80                result[pivot] = (
81                    result[pivot] * 100.0) / self._ftrace.get_duration()
82
83        return result
84
85    def assertThermalResidency(
86            self,
87            expected_value,
88            operator,
89            temp_range,
90            window,
91            percent=False):
92        """
93        :param expected_value: The expected value of the residency
94        :type expected_value: double
95
96        :param operator: A binary operator function that returns
97            a boolean. For example:
98            ::
99
100                import operator
101                op = operator.ge
102                assertThermalResidency(temp_range, expected_value, op)
103
104            Will do the following check:
105            ::
106
107                getThermalResidency(temp_range) >= expected_value
108
109            A custom function can also be passed:
110            ::
111
112                THRESHOLD=5
113                def between_threshold(a, expected):
114                    return abs(a - expected) <= THRESHOLD
115
116        :param temp_range: A tuple of (low_temp, high_temp)
117            which specifies the range of temperature that
118            one intends to calculate the residency for.
119        :type temp_range: tuple
120
121        :param window: A (start, end) tuple to limit the scope of the
122            residency calculation.
123        :type window: tuple
124
125        :param percent: Returns the residency as a percentage of the total
126            duration of the trace
127        :type percent: bool
128
129        .. seealso:
130
131            :mod:`bart.thermal.ThermalAssert.ThermalAssert.assertThermalResidency`
132        """
133
134        residency = self.getThermalResidency(temp_range, window, percent)
135        return operator(residency, expected_value)
136