diff --git a/libs/wlgen/wlgen/rta.py b/libs/wlgen/wlgen/rta.py index ceaa8b6fc4937b2108f6add2215dbc8ae1d61368..442b47178134379cefa4adc1ffa7baec376b5c41 100644 --- a/libs/wlgen/wlgen/rta.py +++ b/libs/wlgen/wlgen/rta.py @@ -268,8 +268,10 @@ class RTA(Workload): if self.duration is None: raise ValueError('Workload duration not specified') - target_cpu = self.getTargetCpu(self.loadref) - calibration = self.getCalibrationConf(target_cpu) + calibration = '"CPU0"' + if self.target: + target_cpu = self.getTargetCpu(self.loadref) + calibration = self.getCalibrationConf(target_cpu) self._log.info('Loading custom configuration:') self._log.info(' %s', rtapp_conf) @@ -280,7 +282,6 @@ class RTA(Workload): '__DURATION__' : str(self.duration), '__PVALUE__' : str(calibration), '__LOGDIR__' : str(self.run_dir), - '__WORKDIR__' : '"'+self.target.working_directory+'"', } for line in ifile: @@ -304,7 +305,6 @@ class RTA(Workload): raise ValueError(msg) # Task configuration - target_cpu = self.getTargetCpu(self.loadref) self.rta_profile = { 'tasks': {}, 'global': {} @@ -314,13 +314,16 @@ class RTA(Workload): global_conf = { 'default_policy': 'SCHED_OTHER', 'duration': -1, - 'calibration': 'CPU'+str(target_cpu), 'logdir': self.run_dir, } # Setup calibration data - calibration = self.getCalibrationConf(target_cpu) - global_conf['calibration'] = calibration + target_cpu = None + if self.target: + target_cpu = self.getTargetCpu(self.loadref) + calibration = self.getCalibrationConf(target_cpu) + global_conf['calibration'] = calibration + if self.duration is not None: global_conf['duration'] = self.duration self._log.warn('Limiting workload duration to %d [s]', @@ -376,7 +379,7 @@ class RTA(Workload): self._log.info(' | start delay: %.6f [s]', task['delay']) - self._log.info(' | calibration CPU: %d', target_cpu) + self._log.info(' | calibration CPU: {}'.format(target_cpu)) if 'loops' not in task.keys(): task['loops'] = 1 @@ -525,16 +528,18 @@ class RTA(Workload): elif kind == 'profile': self._confProfile() + # Set and return the test label + self.test_label = '{0:s}_{1:02d}'.format(self.name, self.exc_id) + return self.test_label + + def run(self, *args, **kwargs): # Move configuration file to target self.target.push(self.json, self.run_dir) - self.rta_cmd = self.target.executables_directory + '/rt-app' self.rta_conf = self.run_dir + '/' + self.json self.command = '{0:s} {1:s} 2>&1'.format(self.rta_cmd, self.rta_conf) - # Set and return the test label - self.test_label = '{0:s}_{1:02d}'.format(self.name, self.exc_id) - return self.test_label + super(RTA, self).run(*args, **kwargs) class _TaskBase(object): diff --git a/libs/wlgen/wlgen/workload.py b/libs/wlgen/wlgen/workload.py index 66903f71fc63111ea24f8dd66f44c26b9c30d66b..ef9b7d8fabb69cc1d987998bee6d2bcb3b1ed13e 100644 --- a/libs/wlgen/wlgen/workload.py +++ b/libs/wlgen/wlgen/workload.py @@ -134,10 +134,6 @@ class Workload(object): # Map of task/s parameters self.params = {} - # Initialize run folder - if self.run_dir is None: - self.run_dir = self.target.working_directory - # Configure a profile workload if kind == 'profile': self._log.debug('Configuring a profile-based workload...') @@ -201,6 +197,10 @@ class Workload(object): :type end_pause_s: float """ + # Initialize run folder + if self.run_dir is None: + self.run_dir = self.target.working_directory + self.cgroup = cgroup # Compose the actual execution command starting from the base command diff --git a/tests/lisa/test_wlgen.py b/tests/lisa/test_wlgen.py new file mode 100644 index 0000000000000000000000000000000000000000..ebb83ed40a7cd22108b30209c0c8aad6174a3f90 --- /dev/null +++ b/tests/lisa/test_wlgen.py @@ -0,0 +1,175 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (C) 2016, ARM Limited and contributors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +from collections import OrderedDict +import json +import os +from unittest import TestCase + +from wlgen import RTA, Periodic, Ramp, Step, Pulse # todo remove unused + +dummy_calibration = {} + +class TestProfile(TestCase): + def test_profile_periodic_smoke(self): + """ + Smoke test for a RTA workload using kind='profile' and Periodic + """ + rtapp = RTA(None, 'test', calibration=dummy_calibration) + + rtapp.conf( + kind = 'profile', + params = { + 'task_p20': Periodic( + period_ms = 100, + duty_cycle_pct = 20, + duration_s = 5, + ).get(), + }, + run_dir='test', + ) + + with open(rtapp.json) as f: + conf = json.load(f) + + [phase] = conf['tasks']['task_p20']['phases'].values() + self.assertDictEqual(phase, { + "loop": 50, + "run": 20000, + "timer": { + "period": 100000, + "ref": "task_p20" + } + }) + +class TestComposition(TestCase): + def test_composition_smoke(self): + """ + Smoke test for a RTA workload using __add__ to compose phases + """ + rtapp = RTA(None, 'test', calibration=dummy_calibration) + + light = Periodic(duty_cycle_pct=10, duration_s=1.0, period_ms=10) + + start_pct = 10 + end_pct = 90 + delta_pct = 20 + num_ramp_phases = ((end_pct - start_pct) / delta_pct) + 1 + ramp = Ramp(start_pct=start_pct, end_pct=end_pct, delta_pct=delta_pct, + time_s=1, period_ms=50) + + heavy = Periodic(duty_cycle_pct=90, duration_s=0.1, period_ms=100) + + lrh_task = light + ramp + heavy + + rtapp.conf( + kind = 'profile', + params = { + 'task_ramp': lrh_task.get() + }, + ) + + with open(rtapp.json) as f: + conf = json.load(f, object_pairs_hook=OrderedDict) + + phases = conf['tasks']['task_ramp']['phases'].values() + + exp_phases = [ + # Light phase: + { + "loop": 100, + "run": 1000, + "timer": { + "period": 10000, + "ref": "task_ramp" + } + }, + # Ramp phases: + { + "loop": 20, + "run": 5000, + "timer": { + "period": 50000, + "ref": "task_ramp" + } + }, + { + "loop": 20, + "run": 15000, + "timer": { + "period": 50000, + "ref": "task_ramp" + } + }, + { + "loop": 20, + "run": 25000, + "timer": { + "period": 50000, + "ref": "task_ramp" + } + }, + { + "loop": 20, + "run": 35000, + "timer": { + "period": 50000, + "ref": "task_ramp" + } + }, + { + "loop": 20, + "run": 45000, + "timer": { + "period": 50000, + "ref": "task_ramp" + } + }, + # Heavy phase: + { + "loop": 1, + "run": 90000, + "timer": { + "period": 100000, + "ref": "task_ramp" + } + }] + + self.assertListEqual(phases, exp_phases) + +class TestCustom(TestCase): + def test_custom_smoke(self): + """ + Smoke test for a custom workload + """ + + json_path = os.path.join(os.getenv('LISA_HOME'), + 'assets', 'mp3-short.json') + rtapp = RTA(None, 'test', calibration=dummy_calibration) + + # Configure this RTApp instance to: + rtapp.conf(kind='custom', params=json_path, duration=5, run_dir='test') + + with open(rtapp.json) as f: + conf = json.load(f) + + # Convert to str because unicode + tasks = set([str(k) for k in conf['tasks'].keys()]) + self.assertSetEqual( + tasks, + set(['AudioTick', 'AudioOut', 'AudioTrack', + 'mp3.decoder', 'OMXCall']))