<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 RTA workload
The RTA or RTApp workload represents a type of workload obtained using the rt-app test application.
More details on the test application can be found at https
Step1:  Test environment setup
For more details on this please check out examples/utils/testenv_example.ipynb.
Step2:  Workload configuration
To create an instance of an RTApp workload generator you need to provide the following
Step3:  The output of the previous cell reports the main properties of the generated
tasks. Thus for example we see that the first task is configure to be
Step4:  Workload execution
Step5:  Collected results
Step6:  Trace inspection
More information on visualization and trace inspection can be found in examples/trappy.
Step7:  RTApp task performance plots
<ASSISTANT_TASK:>
Python Code:
import logging
from conf import LisaLogging
LisaLogging.setup()
# Generate plots inline
%pylab inline
import json
import os
# Support to initialise and configure your test environment
import devlib
from env import TestEnv
# Support to configure and run RTApp based workloads
from wlgen import RTA, Periodic, Ramp, Step, Pulse
# Suport for FTrace events parsing and visualization
import trappy
# Support for performance analysis of RTApp workloads
from perf_analysis import PerfAnalysis
Explanation: RTA workload
The RTA or RTApp workload represents a type of workload obtained using the rt-app test application.
More details on the test application can be found at https://github.com/scheduler-tools/rt-app.
End of explanation
# Setup a target configuration
my_target_conf = {
    
    # Define the kind of target platform to use for the experiments
    "platform"    : 'linux',  # Linux system, valid other options are:
                              # android - access via ADB
                              # linux   - access via SSH
                              # host    - direct access
    
    # Preload settings for a specific target
    "board"       : 'juno',  # juno - JUNO board with mainline hwmon
    
    # Define devlib module to load
    "modules"     : [
        'bl',           # enable big.LITTLE support
        'cpufreq'       # enable CPUFreq support
    ],
    # Account to access the remote target
    "host"        : '192.168.0.1',
    "username"    : 'root',
    "password"    : 'juno',
    # Comment the following line to force rt-app calibration on your target
    "rtapp-calib" : {
        '0': 361, '1': 138, '2': 138, '3': 352, '4': 360, '5': 353
    }
}
# Setup the required Test Environment supports
my_tests_conf = {
    
    # Binary tools required to run this experiment
    # These tools must be present in the tools/ folder for the architecture
    "tools"   : ['rt-app', 'taskset', 'trace-cmd'],
    
    # FTrace events end buffer configuration
    "ftrace"  : {
         "events" : [
             "sched_switch",
             "cpu_frequency"
         ],
         "buffsize" : 10240
    },
}
# Initialize a test environment using
# - the provided target configuration (my_target_conf)
# - the provided test configuration   (my_test_conf)
te = TestEnv(target_conf=my_target_conf, test_conf=my_tests_conf)
target = te.target
Explanation: Test environment setup
For more details on this please check out examples/utils/testenv_example.ipynb.
End of explanation
# Create a new RTApp workload generator using the calibration values
# reported by the TestEnv module
rtapp = RTA(target, 'simple', calibration=te.calibration())
# Configure this RTApp instance to:
rtapp.conf(
# 1. generate a "profile based" set of tasks
    kind='profile',
    
    # 2. define the "profile" of each task
    params={
        # 3. PERIODIC task
        # 
        # This class defines a task which load is periodic with a configured
        # period and duty-cycle.
        # 
        # This class is a specialization of the 'pulse' class since a periodic
        # load is generated as a sequence of pulse loads.
        # 
        # Args:
        #     cuty_cycle_pct  (int, [0-100]): the pulses load [%]
        #                                     default: 50[%]
        #     duration_s  (float): the duration in [s] of the entire workload
        #                          default: 1.0[s]
        #     period_ms   (float): the period used to define the load in [ms]
        #                          default: 100.0[ms]
        #     delay_s     (float): the delay in [s] before ramp start
        #                          default: 0[s]
        #     sched       (dict):  the scheduler configuration for this task
        #     cpus      (list): the list of CPUs on which task can run
        'task_per20': Periodic(
            period_ms=100,         # period
            duty_cycle_pct=20,     # duty cycle
            duration_s=5,          # duration
            cpus=None,             # run on all CPUS
            sched={
                "policy": "FIFO",  # Run this task as a SCHED_FIFO task
            },
            delay_s=0              # start at the start of RTApp
        ).get(),
        # 4. RAMP task
        #
        # This class defines a task which load is a ramp with a configured number
        # of steps according to the input parameters.
        # 
        # Args:
        #     start_pct (int, [0-100]): the initial load [%], (default 0[%])
        #     end_pct   (int, [0-100]): the final load [%], (default 100[%])
        #     delta_pct (int, [0-100]): the load increase/decrease [%],
        #                               default: 10[%]
        #                               increase if start_prc < end_prc
        #                               decrease  if start_prc > end_prc
        #     time_s    (float): the duration in [s] of each load step
        #                        default: 1.0[s]
        #     period_ms (float): the period used to define the load in [ms]
        #                        default: 100.0[ms]
        #     delay_s   (float): the delay in [s] before ramp start
        #                        default: 0[s]
        #     loops     (int):   number of time to repeat the ramp, with the
        #                        specified delay in between
        #                        default: 0
        #     sched     (dict): the scheduler configuration for this task
        #     cpus      (list): the list of CPUs on which task can run
        'task_rmp20_5-60': Ramp(
            period_ms=100,         # period
            start_pct=5,           # intial load
            end_pct=65,            # end load
            delta_pct=20,          # load % increase...
            time_s=1,              # ... every 1[s]
            cpus="0"               # run just on first CPU
        ).get(),
        
        # 5. STEP task
        # 
        # This class defines a task which load is a step with a configured
        # initial and final load.
        # 
        # Args:
        # start_pct (int, [0-100]): the initial load [%]
        #                               default 0[%])
        # end_pct   (int, [0-100]): the final load [%]
        #                               default 100[%]
        # time_s    (float): the duration in [s] of the start and end load
        #                        default: 1.0[s]
        # period_ms (float): the period used to define the load in [ms]
        #                        default 100.0[ms]
        # delay_s   (float): the delay in [s] before ramp start
        #                        default 0[s]
        # loops     (int):   number of time to repeat the ramp, with the
        #                        specified delay in between
        #                        default: 0
        # sched     (dict): the scheduler configuration for this task
        # cpus      (list): the list of CPUs on which task can run
        'task_stp10-50': Step(
            period_ms=100,         # period
            start_pct=0,           # intial load
            end_pct=50,            # end load
            time_s=1,              # ... every 1[s]
            delay_s=0.5            # start .5[s] after the start of RTApp
        ).get(),
        
        # 6. PULSE task
        #
        # This class defines a task which load is a pulse with a configured
        # initial and final load.
        # 
        # The main difference with the 'step' class is that a pulse workload is
        # by definition a 'step down', i.e. the workload switch from an finial
        # load to a final one which is always lower than the initial one.
        # Moreover, a pulse load does not generate a sleep phase in case of 0[%]
        # load, i.e. the task ends as soon as the non null initial load has
        # completed.
        # 
        # Args:
        #     start_pct (int, [0-100]): the initial load [%]
        #                               default: 0[%]
        #     end_pct   (int, [0-100]): the final load [%]
        #                               default: 100[%]
        #               NOTE: must be lower than start_pct value
        #     time_s    (float): the duration in [s] of the start and end load
        #                        default: 1.0[s]
        #                        NOTE: if end_pct is 0, the task end after the
        #                        start_pct period completed
        #     period_ms (float): the period used to define the load in [ms]
        #                        default: 100.0[ms]
        #     delay_s   (float): the delay in [s] before ramp start
        #                        default: 0[s]
        #     loops     (int):   number of time to repeat the ramp, with the
        #                        specified delay in between
        #                        default: 0
        #     sched     (dict):  the scheduler configuration for this task
        #     cpus      (list):  the list of CPUs on which task can run
        'task_pls5-80': Pulse(
            period_ms=100,         # period
            start_pct=65,          # intial load
            end_pct=5,             # end load
            time_s=1,              # ... every 1[s]
            delay_s=0.5            # start .5[s] after the start of RTApp
        ).get(),
        
        
    },
    
    # 7. use this folder for task logfiles
    run_dir=target.working_directory
    
);
Explanation: Workload configuration
To create an instance of an RTApp workload generator you need to provide the following:
- target: target device configuration
- name: name of workload. This is the name of the JSON configuration file reporting the generated RTApp configuration.
- calibration: CPU load calibration values, measured on each core.
An RTApp workload is defined by specifying a kind, provided below through rtapp.conf, which represents the way we want to define the behavior of each task.
The possible kinds of workloads are profile and custom. It's very important to notice that periodic is no longer considered a "kind" of workload but a "class" within the profile kind.
<br><br>
As you see below, when "kind" is "profile", the tasks generated by this workload have a profile which is defined by a sequence of phases. These phases are defined according to the following grammar:<br>
 - params := {task, ...} <br>
 - task   := NAME : {SCLASS, PRIO, [phase, ...]}<br>
 - phase  := (PTIME, PERIOD, DCYCLE)<br> <br>
There are some pre-defined task classes for the profile kind:
 - Step: the load of this task is a step with a configured initial and final load. 
 - Pulse: the load of this task is a pulse with a configured initial and final load.The main difference with the 'step' class is that a pulse workload is by definition a 'step down', i.e. the workload switches from an initial load to a final one which is always lower than the initial one. Moreover, a pulse load does not generate a sleep phase in case of 0[%] load, i.e. the task ends as soon as the non null initial load has completed.
 - Ramp: the load of this task is a ramp with a configured number of steps determined by the input parameters.
 - Periodic: the load of this task is periodic with a configured period and duty-cycle.<br><br>
The one below is a workload mix having all types of workloads described above, but each of them can also be specified serapately in the RTApp parameters.
End of explanation
# Initial phase and pinning parameters
ramp = Ramp(period_ms=100, start_pct=5, end_pct=65, delta_pct=20, time_s=1, cpus="0")
# Following phases
medium_slow = Periodic(duty_cycle_pct=10, duration_s=5, period_ms=100)
high_fast   = Periodic(duty_cycle_pct=60, duration_s=5, period_ms=10)
medium_fast = Periodic(duty_cycle_pct=10, duration_s=5, period_ms=1)
high_slow   = Periodic(duty_cycle_pct=60, duration_s=5, period_ms=100)
#Compose the task
complex_task = ramp + medium_slow + high_fast + medium_fast + high_slow
# Configure this RTApp instance to:
# rtapp.conf(
#    # 1. generate a "profile based" set of tasks
#    kind='profile',
#    
#    # 2. define the "profile" of each task
#    params={
#        'complex' : complex_task.get()
#    },
#
#    # 6. use this folder for task logfiles
#    run_dir='/tmp'
#)
Explanation: The output of the previous cell reports the main properties of the generated
tasks. Thus for example we see that the first task is configure to be:
 - named task_per20
 - executed as a SCHED_FIFO task
 - generating a load which is calibrated with respect to the CPU 1
 - with one single "phase" which defines a peripodic load for the duration of 5[s]
 - that periodic load consistes of 50 cycles
 - each cycle has a period of 100[ms] and a duty-cycle of 20%,
   which means that the task, for every cycle, will run for 20[ms] and then sleep for 80[ms] 
All these properties are translated into a JSON configuration file for RTApp which you can see in Collected results below.<br>
Workload composition
Another way of specifying the phases of a task is through workload composition, described in the next cell.<br>
NOTE: We are just giving this as an example of specifying a workload, but this configuration won't be the one used for the following execution and analysis cells. You need to uncomment these lines if you want to use the composed workload.
End of explanation
logging.info('#### Setup FTrace')
te.ftrace.start()
logging.info('#### Start energy sampling')
te.emeter.reset()
logging.info('#### Start RTApp execution')
rtapp.run(out_dir=te.res_dir, cgroup="")
logging.info('#### Read energy consumption: %s/energy.json', te.res_dir)
nrg_report = te.emeter.report(out_dir=te.res_dir)
logging.info('#### Stop FTrace')
te.ftrace.stop()
trace_file = os.path.join(te.res_dir, 'trace.dat')
logging.info('#### Save FTrace: %s', trace_file)
te.ftrace.get_trace(trace_file)
logging.info('#### Save platform description: %s/platform.json', te.res_dir)
(plt, plt_file) = te.platform_dump(te.res_dir)
Explanation: Workload execution
End of explanation
# Inspect the JSON file used to run the application
with open('{}/simple_00.json'.format(te.res_dir), 'r') as fh:
    rtapp_json = json.load(fh, )
logging.info('Generated RTApp JSON file:')
print json.dumps(rtapp_json, indent=4, sort_keys=True)
# All data are produced in the output folder defined by the TestEnv module
logging.info('Content of the output folder %s', te.res_dir)
!ls -la {te.res_dir}
# Dump the energy measured for the LITTLE and big clusters
logging.info('Energy: %s', nrg_report.report_file)
print json.dumps(nrg_report.channels, indent=4, sort_keys=True)
# Dump the platform descriptor, which could be useful for further analysis
# of the generated results
logging.info('Platform description: %s', plt_file)
print json.dumps(plt, indent=4, sort_keys=True)
Explanation: Collected results
End of explanation
# NOTE: The interactive trace visualization is available only if you run
#       the workload to generate a new trace-file
trappy.plotter.plot_trace(te.res_dir)
Explanation: Trace inspection
More information on visualization and trace inspection can be found in examples/trappy.
End of explanation
# Parse the RT-App generate log files to compute performance metrics
pa = PerfAnalysis(te.res_dir)
# For each task which has generated a logfile, plot  its performance metrics
for task in pa.tasks():
    pa.plotPerf(task, "Performance plots for task [{}] ".format(task))
Explanation: RTApp task performance plots
End of explanation
<END_TASK>