mirror of
https://github.com/ARM-software/workload-automation.git
synced 2025-01-19 04:21:17 +00:00
f8d5a3e358
assistant_params are now handled consistently with the other kinds of params in TargetDescription, and they are now part of the default config generated.
333 lines
13 KiB
Python
333 lines
13 KiB
Python
from collections import OrderedDict
|
|
from copy import copy
|
|
|
|
from devlib import (LinuxTarget, AndroidTarget, LocalLinuxTarget,
|
|
Platform, Juno, TC2, Gem5SimulationPlatform)
|
|
|
|
from wa.framework import pluginloader
|
|
from wa.framework.exception import PluginLoaderError
|
|
from wa.framework.plugin import Plugin, Parameter
|
|
from wa.framework.target.assistant import LinuxAssistant, AndroidAssistant
|
|
from wa.utils.types import list_of_strings, list_of_ints
|
|
from wa.utils.misc import isiterable
|
|
|
|
def get_target_descriptions(loader=pluginloader):
|
|
targets = {}
|
|
for cls in loader.list_target_descriptors():
|
|
descriptor = cls()
|
|
for desc in descriptor.get_descriptions():
|
|
if desc.name in targets:
|
|
msg = 'Duplicate target "{}" returned by {} and {}'
|
|
prev_dtor = targets[desc.name].source
|
|
raise PluginLoaderError(msg.format(desc.name, prev_dtor.name,
|
|
descriptor.name))
|
|
targets[desc.name] = desc
|
|
return targets.values()
|
|
|
|
|
|
def instantiate_target(tdesc, params, connect=None):
|
|
target_params = {p.name: p for p in tdesc.target_params}
|
|
platform_params = {p.name: p for p in tdesc.platform_params}
|
|
conn_params = {p.name: p for p in tdesc.conn_params}
|
|
assistant_params = {p.name: p for p in tdesc.assistant_params}
|
|
|
|
tp, pp, cp = {}, {}, {}
|
|
|
|
for supported_params, new_params in (target_params, tp), (platform_params, pp), (conn_params, cp):
|
|
for name, value in supported_params.iteritems():
|
|
if value.default:
|
|
new_params[name] = value.default
|
|
|
|
for name, value in params.iteritems():
|
|
if name in target_params:
|
|
tp[name] = value
|
|
elif name in platform_params:
|
|
pp[name] = value
|
|
elif name in conn_params:
|
|
cp[name] = value
|
|
elif name in assistant_params:
|
|
pass
|
|
else:
|
|
msg = 'Unexpected parameter for {}: {}'
|
|
raise ValueError(msg.format(tdesc.name, name))
|
|
|
|
tp['platform'] = (tdesc.platform or Platform)(**pp)
|
|
if cp:
|
|
tp['connection_settings'] = cp
|
|
if tdesc.connection:
|
|
tp['conn_cls'] = tdesc.connection
|
|
if connect is not None:
|
|
tp['connect'] = connect
|
|
|
|
return tdesc.target(**tp)
|
|
|
|
|
|
def instantiate_assistant(tdesc, params, target):
|
|
assistant_params = {}
|
|
for param in tdesc.assistant_params:
|
|
if param.name in params:
|
|
assistant_params[param.name] = params[param.name]
|
|
elif param.default:
|
|
assistant_params[param.name] = param.default
|
|
return tdesc.assistant(target, **assistant_params)
|
|
|
|
|
|
class TargetDescription(object):
|
|
|
|
def __init__(self, name, source, description=None, target=None, platform=None,
|
|
conn=None, assistant=None, target_params=None, platform_params=None,
|
|
conn_params=None, assistant_params=None):
|
|
self.name = name
|
|
self.source = source
|
|
self.description = description
|
|
self.target = target
|
|
self.platform = platform
|
|
self.connection = conn
|
|
self.assistant = assistant
|
|
self._set('target_params', target_params)
|
|
self._set('platform_params', platform_params)
|
|
self._set('conn_params', conn_params)
|
|
self._set('assistant_params', assistant_params)
|
|
|
|
def get_default_config(self):
|
|
param_attrs = ['target_params', 'platform_params',
|
|
'conn_params', 'assistant_params']
|
|
config = {}
|
|
for pattr in param_attrs:
|
|
for n, p in getattr(self, pattr).itervalues():
|
|
config[n] = p.default
|
|
return config
|
|
|
|
def _set(self, attr, vals):
|
|
if vals is None:
|
|
vals = {}
|
|
elif isiterable(vals):
|
|
if not hasattr(vals, 'iteritems'):
|
|
vals = {v.name: v for v in vals}
|
|
else:
|
|
msg = '{} must be iterable; got "{}"'
|
|
raise ValueError(msg.format(attr, vals))
|
|
setattr(self, attr, vals)
|
|
|
|
|
|
class TargetDescriptor(Plugin):
|
|
|
|
kind = 'target_descriptor'
|
|
|
|
def get_descriptions(self):
|
|
return []
|
|
|
|
|
|
COMMON_TARGET_PARAMS = [
|
|
Parameter('working_directory', kind=str,
|
|
description='''
|
|
On-target working directory that will be used by WA. This
|
|
directory must be writable by the user WA logs in as without
|
|
the need for privilege elevation.
|
|
'''),
|
|
Parameter('executables_directory', kind=str,
|
|
description='''
|
|
On-target directory where WA will install its executable
|
|
binaries. This location must allow execution. This location does
|
|
*not* need to be writable by unprivileged users or rooted devices
|
|
(WA will install with elevated privileges as necessary).
|
|
'''),
|
|
Parameter('modules', kind=list_of_strings,
|
|
description='''
|
|
A list of additional modules to be installed for the target.
|
|
|
|
``devlib`` implements functionality for particular subsystems as
|
|
modules. A number of "default" modules (e.g. for cpufreq
|
|
subsystem) are loaded automatically, unless explicitly disabled.
|
|
If additional modules need to be loaded, they may be specified
|
|
using this parameter.
|
|
|
|
Please see ``devlab`` documentation for information on the available
|
|
modules.
|
|
'''),
|
|
Parameter('load_default_modules', kind=bool, default=True,
|
|
description='''
|
|
A number of modules (e.g. for working with the cpufreq subsystem) are
|
|
loaded by default when a Target is instantiated. Setting this to
|
|
``True`` would suppress that, ensuring that only the base Target
|
|
interface is initialized.
|
|
|
|
You may want to set this if there is a problem with one or more default
|
|
modules on your platform (e.g. your device is unrooted and cpufreq is
|
|
not accessible to unprivileged users), or if Target initialization is
|
|
taking too long for your platform.
|
|
'''),
|
|
]
|
|
|
|
COMMON_PLATFORM_PARAMS = [
|
|
Parameter('core_names', kind=list_of_strings,
|
|
description='''
|
|
List of names of CPU cores in the order that they appear to the
|
|
kernel. If not specified, it will be inferred from the platform.
|
|
'''),
|
|
Parameter('core_clusters', kind=list_of_ints,
|
|
description='''
|
|
Cluster mapping corresponding to the cores in ``core_names``.
|
|
Cluster indexing starts at ``0``. If not specified, this will be
|
|
inferred from ``core_names`` -- consecutive cores with the same
|
|
name will be assumed to share a cluster.
|
|
'''),
|
|
Parameter('big_core', kind=str,
|
|
description='''
|
|
The name of the big cores in a big.LITTLE system. If not
|
|
specified, this will be inferred, either from the name (if one of
|
|
the names in ``core_names`` matches known big cores), or by
|
|
assuming that the last cluster is big.
|
|
'''),
|
|
Parameter('model', kind=str,
|
|
description='''
|
|
Hardware model of the platform. If not specified, an attempt will
|
|
be made to read it from target.
|
|
'''),
|
|
Parameter('modules', kind=list_of_strings,
|
|
description='''
|
|
An additional list of modules to be loaded into the target.
|
|
'''),
|
|
]
|
|
|
|
VEXPRESS_PLATFORM_PARAMS = [
|
|
Parameter('serial_port', kind=str,
|
|
description='''
|
|
The serial device/port on the host for the initial connection to
|
|
the target (used for early boot, flashing, etc).
|
|
'''),
|
|
Parameter('baudrate', kind=int,
|
|
description='''
|
|
Baud rate for the serial connection.
|
|
'''),
|
|
Parameter('vemsd_mount', kind=str,
|
|
description='''
|
|
VExpress MicroSD card mount location. This is a MicroSD card in
|
|
the VExpress device that is mounted on the host via USB. The card
|
|
contains configuration files for the platform and firmware and
|
|
kernel images to be flashed.
|
|
'''),
|
|
Parameter('bootloader', kind=str,
|
|
allowed_values=['uefi', 'uefi-shell', 'u-boot', 'bootmon'],
|
|
description='''
|
|
Selects the bootloader mechanism used by the board. Depending on
|
|
firmware version, a number of possible boot mechanisms may be use.
|
|
|
|
Please see ``devlib`` documentation for descriptions.
|
|
'''),
|
|
Parameter('hard_reset_method', kind=str,
|
|
allowed_values=['dtr', 'reboottxt'],
|
|
description='''
|
|
There are a couple of ways to reset VersatileExpress board if the
|
|
software running on the board becomes unresponsive. Both require
|
|
configuration to be enabled (please see ``devlib`` documentation).
|
|
|
|
``dtr``: toggle the DTR line on the serial connection
|
|
``reboottxt``: create ``reboot.txt`` in the root of the VEMSD mount.
|
|
|
|
'''),
|
|
]
|
|
|
|
GEM5_PLATFORM_PARAMS = [
|
|
Parameter('host_output_dir', kind=str, mandatory=True,
|
|
description='''
|
|
Path on the host where gem5 output (e.g. stats file) will be placed.
|
|
'''),
|
|
Parameter('gem5_bin', kind=str, mandatory=True,
|
|
description='''
|
|
Path to the gem5 binary
|
|
'''),
|
|
Parameter('gem5_args', kind=str, mandatory=True,
|
|
description='''
|
|
Arguments to be passed to the gem5 binary
|
|
'''),
|
|
Parameter('gem5_virtio', kind=str, mandatory=True,
|
|
description='''
|
|
VirtIO device setup arguments to be passed to gem5. VirtIO is used
|
|
to transfer files between the simulation and the host.
|
|
'''),
|
|
]
|
|
|
|
# name --> (target_class, params_list, defaults, assistant_class)
|
|
TARGETS = {
|
|
'linux': (LinuxTarget, COMMON_TARGET_PARAMS, None),
|
|
'android': (AndroidTarget, COMMON_TARGET_PARAMS +
|
|
[Parameter('package_data_directory', kind=str, default='/data/data',
|
|
description='''
|
|
Directory containing Android data
|
|
'''),
|
|
], None),
|
|
'local': (LocalLinuxTarget, COMMON_TARGET_PARAMS, None),
|
|
}
|
|
|
|
# name --> assistant
|
|
ASSISTANTS = {
|
|
'linux': LinuxAssistant,
|
|
'android': AndroidAssistant,
|
|
'local': LinuxAssistant,
|
|
}
|
|
|
|
# name --> (platform_class, params_list, defaults)
|
|
PLATFORMS = {
|
|
'generic': (Platform, COMMON_PLATFORM_PARAMS, None),
|
|
'juno': (Juno, COMMON_PLATFORM_PARAMS + VEXPRESS_PLATFORM_PARAMS,
|
|
{
|
|
'vemsd_mount': '/media/JUNO',
|
|
'baudrate': 115200,
|
|
'bootloader': 'u-boot',
|
|
'hard_reset_method': 'dtr',
|
|
}),
|
|
'tc2': (TC2, COMMON_PLATFORM_PARAMS + VEXPRESS_PLATFORM_PARAMS,
|
|
{
|
|
'vemsd_mount': '/media/VEMSD',
|
|
'baudrate': 38400,
|
|
'bootloader': 'bootmon',
|
|
'hard_reset_method': 'reboottxt',
|
|
}),
|
|
'gem5': (Gem5SimulationPlatform, GEM5_PLATFORM_PARAMS, None),
|
|
}
|
|
|
|
|
|
class DefaultTargetDescriptor(TargetDescriptor):
|
|
|
|
name = 'devlib_targets'
|
|
|
|
description = """
|
|
The default target descriptor that provides descriptions in the form
|
|
<platform>_<target>.
|
|
|
|
These map directly onto ``Target``\ s and ``Platform``\ s supplied by ``devlib``.
|
|
|
|
"""
|
|
|
|
def get_descriptions(self):
|
|
result = []
|
|
for target_name, target_tuple in TARGETS.iteritems():
|
|
target, target_params = self._get_item(target_tuple)
|
|
assistant = ASSISTANTS[target_name]
|
|
for platform_name, platform_tuple in PLATFORMS.iteritems():
|
|
platform, platform_params = self._get_item(platform_tuple)
|
|
|
|
name = '{}_{}'.format(platform_name, target_name)
|
|
td = TargetDescription(name, self)
|
|
td.target = target
|
|
td.platform = platform
|
|
td.assistant = assistant
|
|
td.target_params = target_params
|
|
td.platform_params = platform_params
|
|
td.assistant_params = assistant.parameters
|
|
result.append(td)
|
|
return result
|
|
|
|
def _get_item(self, item_tuple):
|
|
cls, params, defaults = item_tuple
|
|
if not defaults:
|
|
return cls, params
|
|
|
|
param_map = OrderedDict((p.name, copy(p)) for p in params)
|
|
for name, value in defaults.iteritems():
|
|
if name not in param_map:
|
|
raise ValueError('Unexpected default "{}"'.format(name))
|
|
param_map[name].default = value
|
|
return cls, param_map.values()
|