1de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman#    Copyright 2017-2017 ARM Limited
2de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman#
3de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman# Licensed under the Apache License, Version 2.0 (the "License");
4de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman# you may not use this file except in compliance with the License.
5de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman# You may obtain a copy of the License at
6de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman#
7de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman#     http://www.apache.org/licenses/LICENSE-2.0
8de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman#
9de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman# Unless required by applicable law or agreed to in writing, software
10de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman# distributed under the License is distributed on an "AS IS" BASIS,
11de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman# See the License for the specific language governing permissions and
13de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman# limitations under the License.
14de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman#
15de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman
16de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackmanfrom bart.common.Utils import select_window
17de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman
18de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackmanfrom test import LisaTest, experiment_test
19de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman
20de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan JackmanWORKLOAD_DURATION_S = 5
21de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman
220bf208ed092a93371533f1001f3694c0f56ea43bBrendan JackmanREQUIRED_CPU_ACTIVE_TIME_PCT = 95
23de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman
24de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackmanclass HeavyLoadTest(LisaTest):
25de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman    """
26de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman    Test an EAS system under heavy load
27de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman
28de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman    Runs N 100% RT-App threads where N is the number of CPUs, and checks that
29de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman    those tasks were spread across all CPUs in the system by asserting that all
30de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman    CPUs were fully utilized up until the first task completed.
31de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman    """
32de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman
33de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman    test_conf = {
34de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman        'ftrace' : {
35de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman            'events' : ['cpu_idle', 'sched_switch'],
36de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman        },
37de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman        'modules' : ['cgroups'], # Required by freeze_userspace flag
38de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman    }
39de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman
40de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman    experiments_conf = {
41de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman        "wloads" : {
42de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman            "n_heavy_tasks" : {
43de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman                "type" : "rt-app",
44de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman                "conf" : {
45de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman                    "class" : "profile",
46de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman                    "params" : {
47de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman                        "wmig" : {
48de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman                            "kind" : "Periodic",
49de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman                            "params" : {
50de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman                                "duty_cycle_pct": 100,
51de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman                                "duration_s": WORKLOAD_DURATION_S,
52de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman                            },
53de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman                            # Create one task for each cpu
54de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman                            "tasks" : "cpus",
55de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman                        },
56de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman                    },
57de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman                },
58de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman            },
59de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman        },
60de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman        "confs" : [{
61de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman            'tag' : 'energy_aware',
62de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman            'flags' : ['ftrace', 'freeze_userspace'],
63de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman            'sched_features' : 'ENERGY_AWARE',
64de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman        }]
65de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman    }
66de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman
67de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman    @classmethod
68de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman    def setUpClass(cls, *args, **kwargs):
6907c24985f8c4964a11483db44e383d0ddf602566Brendan Jackman        super(HeavyLoadTest, cls).runExperiments(*args, **kwargs)
70de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman
71de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman    @experiment_test
72de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman    def test_tasks_spread(self, experiment, tasks):
73de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman        trace = self.get_trace(experiment)
74de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman        start, _ = self.get_window(experiment)
75de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman        end = min(self.get_end_times(experiment).values())
76de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman        duration = end - start
77de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman
78de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman        total_cpu_time = 0
79de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman        active_proportions = []
80de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman        for cpu, _ in enumerate(self.target.core_names):
81de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman            cpu_active = trace.getCPUActiveSignal(cpu)
82bb71199099bfa011bb026ccd7935246b2d0afed1Brendan Jackman            if cpu_active is None:
83bb71199099bfa011bb026ccd7935246b2d0afed1Brendan Jackman                raise RuntimeError(
84bb71199099bfa011bb026ccd7935246b2d0afed1Brendan Jackman                    "Couldn't get CPU-active signal. "
85bb71199099bfa011bb026ccd7935246b2d0afed1Brendan Jackman                    "Is the 'cpu_idle' ftrace event enabled in the kernel?")
86de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman
87de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman            # Add extra events to cpu_active signal so that it matches the
88de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman            # window exactly
89de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman            new_index = sorted(cpu_active.index.tolist() + [start, end])
90de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman            cpu_active = cpu_active.reindex(new_index, method='ffill')
91de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman
92de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman            active_time = trace.integrate_square_wave(cpu_active[start:end])
93de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman            active_proportions.append(active_time / duration)
94de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman
95de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman        if any(a < (REQUIRED_CPU_ACTIVE_TIME_PCT / 100.)
96de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman               for a in active_proportions):
97de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman
98de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman            proportions_str = ""
99de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman            for cpu, _ in enumerate(self.target.core_names):
100de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman                proportions_str += " {:3d} {:5.1f}%\n".format(
101de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman                    cpu, active_proportions[cpu]*100)
102de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman
103de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman            raise AssertionError(
104de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman                "Some CPUs were less than {}% utilized\n"
105de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman                " CPU active proportions:\n{}".format(
106de5e7f755d9df0946207c08a1740a9eca7a38da5Brendan Jackman                    REQUIRED_CPU_ACTIVE_TIME_PCT, proportions_str))
107