West: Add west simulate
command
Introduce `simulate `command for running samples on a simulator of choice. Initial implementation consists of one runner, dedicated for Renode. Signed-off-by: Michał Szprejda <mszprejda@antmicro.com>
This commit is contained in:
parent
f155ff596c
commit
80900cbc3b
13 changed files with 172 additions and 7 deletions
8
boards/common/renode.board.cmake
Normal file
8
boards/common/renode.board.cmake
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
board_set_sim_runner_ifnset(renode)
|
||||||
|
|
||||||
|
board_runner_args(renode "--renode-command=$elf=@${PROJECT_BINARY_DIR}/${KERNEL_ELF_NAME}")
|
||||||
|
board_runner_args(renode "--renode-command=include @${RENODE_SCRIPT}")
|
||||||
|
|
||||||
|
board_finalize_runner_args(renode)
|
|
@ -3,3 +3,6 @@
|
||||||
set(SUPPORTED_EMU_PLATFORMS renode)
|
set(SUPPORTED_EMU_PLATFORMS renode)
|
||||||
set(RENODE_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/support/m2gl025_miv.resc)
|
set(RENODE_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/support/m2gl025_miv.resc)
|
||||||
set(RENODE_UART sysbus.uart)
|
set(RENODE_UART sysbus.uart)
|
||||||
|
|
||||||
|
set_ifndef(BOARD_SIM_RUNNER renode)
|
||||||
|
include(${ZEPHYR_BASE}/boards/common/renode.board.cmake)
|
||||||
|
|
|
@ -28,3 +28,6 @@ elseif("${BOARD_REVISION}" STREQUAL "B")
|
||||||
board_runner_args(jlink "--tool-opt=-autoconnect 1")
|
board_runner_args(jlink "--tool-opt=-autoconnect 1")
|
||||||
include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
|
include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set_ifndef(BOARD_SIM_RUNNER renode)
|
||||||
|
include(${ZEPHYR_BASE}/boards/common/renode.board.cmake)
|
||||||
|
|
|
@ -97,6 +97,10 @@ function(create_runners_yaml)
|
||||||
runners_yaml_append("\n# Default debug runner if --runner is not given.")
|
runners_yaml_append("\n# Default debug runner if --runner is not given.")
|
||||||
runners_yaml_append("debug-runner: ${BOARD_DEBUG_RUNNER}")
|
runners_yaml_append("debug-runner: ${BOARD_DEBUG_RUNNER}")
|
||||||
endif()
|
endif()
|
||||||
|
if(DEFINED BOARD_SIM_RUNNER)
|
||||||
|
runners_yaml_append("\n# Default simulation runner if --runner is not given.")
|
||||||
|
runners_yaml_append("sim-runner: ${BOARD_SIM_RUNNER}")
|
||||||
|
endif()
|
||||||
|
|
||||||
# Sets up common runner configuration values.
|
# Sets up common runner configuration values.
|
||||||
runners_yaml_append_config()
|
runners_yaml_append_config()
|
||||||
|
|
|
@ -705,9 +705,10 @@ endfunction()
|
||||||
# This section provides glue between CMake and the Python code that
|
# This section provides glue between CMake and the Python code that
|
||||||
# manages the runners.
|
# manages the runners.
|
||||||
|
|
||||||
|
set(TYPES "FLASH" "DEBUG" "SIM")
|
||||||
function(_board_check_runner_type type) # private helper
|
function(_board_check_runner_type type) # private helper
|
||||||
if (NOT (("${type}" STREQUAL "FLASH") OR ("${type}" STREQUAL "DEBUG")))
|
if (NOT "${type}" IN_LIST TYPES)
|
||||||
message(FATAL_ERROR "invalid type ${type}; should be FLASH or DEBUG")
|
message(FATAL_ERROR "invalid type ${type}; should be one of: ${TYPES}")
|
||||||
endif()
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
@ -723,8 +724,8 @@ endfunction()
|
||||||
#
|
#
|
||||||
# This would set the board's flash runner to "pyocd".
|
# This would set the board's flash runner to "pyocd".
|
||||||
#
|
#
|
||||||
# In general, "type" is FLASH or DEBUG, and "runner" is the name of a
|
# In general, "type" is FLASH, DEBUG or SIM and "runner" is
|
||||||
# runner.
|
# the name of a runner.
|
||||||
function(board_set_runner type runner)
|
function(board_set_runner type runner)
|
||||||
_board_check_runner_type(${type})
|
_board_check_runner_type(${type})
|
||||||
if (DEFINED BOARD_${type}_RUNNER)
|
if (DEFINED BOARD_${type}_RUNNER)
|
||||||
|
@ -765,6 +766,11 @@ macro(board_set_debugger_ifnset runner)
|
||||||
board_set_runner_ifnset(DEBUG ${runner})
|
board_set_runner_ifnset(DEBUG ${runner})
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
|
# A convenience macro for board_set_runner_ifnset(SIM ${runner}).
|
||||||
|
macro(board_set_sim_runner_ifnset runner)
|
||||||
|
board_set_runner_ifnset(SIM ${runner})
|
||||||
|
endmacro()
|
||||||
|
|
||||||
# This function is intended for board.cmake files and application
|
# This function is intended for board.cmake files and application
|
||||||
# CMakeLists.txt files.
|
# CMakeLists.txt files.
|
||||||
#
|
#
|
||||||
|
|
|
@ -698,6 +698,49 @@ determined by the imported subclasses of ``ZephyrBinaryRunner``.
|
||||||
runner implementations are in other submodules, such as ``runners.nrfjprog``,
|
runner implementations are in other submodules, such as ``runners.nrfjprog``,
|
||||||
``runners.openocd``, etc.
|
``runners.openocd``, etc.
|
||||||
|
|
||||||
|
Simulating a board with: ``west simulate``
|
||||||
|
******************************************
|
||||||
|
|
||||||
|
Basics
|
||||||
|
======
|
||||||
|
|
||||||
|
Currently the command supports only one runner which is using Renode,
|
||||||
|
but can be easily extended by adding other runners.
|
||||||
|
|
||||||
|
From a Zephyr build directory, to run the built binary::
|
||||||
|
|
||||||
|
west simulate --runner=renode
|
||||||
|
|
||||||
|
This will start Renode and configure simulation based on a default ``.resc`` script
|
||||||
|
for the current platform with the zephyr.elf file loaded by default. The simulation
|
||||||
|
then can be started by typing "start" or "s" in Renode's Monitor. This can also be
|
||||||
|
done by passing a command to Renode, using an argument provided by the runner:
|
||||||
|
|
||||||
|
west simulate --runner=renode --renode-command start
|
||||||
|
|
||||||
|
To pass an argument to Renode itself, for example to start Renode in console mode
|
||||||
|
intead of a separate window:
|
||||||
|
|
||||||
|
west simulate --runner=renode --renode-arg="--console"
|
||||||
|
|
||||||
|
From that point on Renode can be used normally in both console and window modes.
|
||||||
|
For details on using Renode see `Renode - documentation`_.
|
||||||
|
|
||||||
|
.. _Renode - documentation:
|
||||||
|
http://docs.renode.io
|
||||||
|
|
||||||
|
Runner-Specific Overrides
|
||||||
|
=========================
|
||||||
|
|
||||||
|
To view all of the available options supported by the runners, as well
|
||||||
|
as their usage information, use ``--context`` (or``-H``)::
|
||||||
|
|
||||||
|
west simulate --runner=renode --context
|
||||||
|
|
||||||
|
To view all available options Renode supports, use::
|
||||||
|
|
||||||
|
west simulate --runner=renode --renode-help
|
||||||
|
|
||||||
Hacking
|
Hacking
|
||||||
*******
|
*******
|
||||||
|
|
||||||
|
|
|
@ -66,3 +66,8 @@ west-commands:
|
||||||
- name: bindesc
|
- name: bindesc
|
||||||
class: Bindesc
|
class: Bindesc
|
||||||
help: work with Binary Descriptors
|
help: work with Binary Descriptors
|
||||||
|
- file: scripts/west_commands/simulate.py
|
||||||
|
commands:
|
||||||
|
- name: simulate
|
||||||
|
class: Simulate
|
||||||
|
help: simulate board
|
||||||
|
|
|
@ -512,7 +512,7 @@ def runners_yaml_path(build_dir, board):
|
||||||
ret = Path(build_dir) / 'zephyr' / 'runners.yaml'
|
ret = Path(build_dir) / 'zephyr' / 'runners.yaml'
|
||||||
if not ret.is_file():
|
if not ret.is_file():
|
||||||
log.die(f'either a pristine build is needed, or board {board} '
|
log.die(f'either a pristine build is needed, or board {board} '
|
||||||
"doesn't support west flash/debug "
|
"doesn't support west flash/debug/simulate "
|
||||||
'(no ZEPHYR_RUNNERS_YAML in CMake cache)')
|
'(no ZEPHYR_RUNNERS_YAML in CMake cache)')
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@ _names = [
|
||||||
'nxp_s32dbg',
|
'nxp_s32dbg',
|
||||||
'openocd',
|
'openocd',
|
||||||
'pyocd',
|
'pyocd',
|
||||||
|
'renode',
|
||||||
'qemu',
|
'qemu',
|
||||||
'silabs_commander',
|
'silabs_commander',
|
||||||
'spi_burn',
|
'spi_burn',
|
||||||
|
|
|
@ -200,7 +200,7 @@ class MissingProgram(FileNotFoundError):
|
||||||
super().__init__(errno.ENOENT, os.strerror(errno.ENOENT), program)
|
super().__init__(errno.ENOENT, os.strerror(errno.ENOENT), program)
|
||||||
|
|
||||||
|
|
||||||
_RUNNERCAPS_COMMANDS = {'flash', 'debug', 'debugserver', 'attach'}
|
_RUNNERCAPS_COMMANDS = {'flash', 'debug', 'debugserver', 'attach', 'simulate'}
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class RunnerCaps:
|
class RunnerCaps:
|
||||||
|
@ -212,7 +212,7 @@ class RunnerCaps:
|
||||||
Available capabilities:
|
Available capabilities:
|
||||||
|
|
||||||
- commands: set of supported commands; default is {'flash',
|
- commands: set of supported commands; default is {'flash',
|
||||||
'debug', 'debugserver', 'attach'}.
|
'debug', 'debugserver', 'attach', 'simulate'}.
|
||||||
|
|
||||||
- dev_id: whether the runner supports device identifiers, in the form of an
|
- dev_id: whether the runner supports device identifiers, in the form of an
|
||||||
-i, --dev-id option. This is useful when the user has multiple debuggers
|
-i, --dev-id option. This is useful when the user has multiple debuggers
|
||||||
|
|
62
scripts/west_commands/runners/renode.py
Normal file
62
scripts/west_commands/runners/renode.py
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
# Copyright (c) 2024 Antmicro <www.antmicro.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
'''Runner stub for Renode.'''
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
from runners.core import ZephyrBinaryRunner, RunnerCaps
|
||||||
|
|
||||||
|
|
||||||
|
class RenodeRunner(ZephyrBinaryRunner):
|
||||||
|
'''Place-holder for Renode runner customizations.'''
|
||||||
|
|
||||||
|
def __init__(self, cfg, args):
|
||||||
|
super().__init__(cfg)
|
||||||
|
self.renode_arg = args.renode_arg
|
||||||
|
self.renode_command = args.renode_command
|
||||||
|
self.renode_help = args.renode_help
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def name(cls):
|
||||||
|
return 'renode'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def capabilities(cls):
|
||||||
|
return RunnerCaps(commands={'simulate'}, hide_load_files=True)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def do_add_parser(cls, parser):
|
||||||
|
parser.add_argument('--renode-arg',
|
||||||
|
metavar='ARG',
|
||||||
|
action='append',
|
||||||
|
help='additional argument passed to Renode; `--help` will print all possible arguments')
|
||||||
|
parser.add_argument('--renode-command',
|
||||||
|
metavar='COMMAND',
|
||||||
|
action='append',
|
||||||
|
help='additional command passed to Renode\'s simulation')
|
||||||
|
parser.add_argument('--renode-help',
|
||||||
|
default=False,
|
||||||
|
action='store_true',
|
||||||
|
help='print all possible `Renode` arguments')
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def do_create(cls, cfg, args):
|
||||||
|
return RenodeRunner(cfg, args)
|
||||||
|
|
||||||
|
def do_run(self, command, **kwargs):
|
||||||
|
self.run_test(**kwargs)
|
||||||
|
|
||||||
|
def run_test(self, **kwargs):
|
||||||
|
cmd = ['renode']
|
||||||
|
if self.renode_help is True:
|
||||||
|
cmd.append('--help')
|
||||||
|
else:
|
||||||
|
if self.renode_arg is not None:
|
||||||
|
for arg in self.renode_arg:
|
||||||
|
cmd.append(arg)
|
||||||
|
if self.renode_command is not None:
|
||||||
|
for command in self.renode_command:
|
||||||
|
cmd.append('-e')
|
||||||
|
cmd.append(command)
|
||||||
|
subprocess.run(cmd, check=True)
|
29
scripts/west_commands/simulate.py
Normal file
29
scripts/west_commands/simulate.py
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
# Copyright (c) 2024 Antmicro <www.antmicro.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
from west.commands import WestCommand
|
||||||
|
from run_common import add_parser_common, do_run_common
|
||||||
|
|
||||||
|
EXPORT_DESCRIPTION = '''\
|
||||||
|
Simulate the board on a runner of choice using generated artifacts.
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
class Simulate(WestCommand):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(Simulate, self).__init__(
|
||||||
|
'simulate',
|
||||||
|
# Keep this in sync with the string in west-commands.yml.
|
||||||
|
'simulate board',
|
||||||
|
EXPORT_DESCRIPTION,
|
||||||
|
accepts_unknown_args=True)
|
||||||
|
|
||||||
|
self.runner_key = 'sim-runner' # in runners.yaml
|
||||||
|
|
||||||
|
def do_add_parser(self, parser_adder):
|
||||||
|
return add_parser_common(self, parser_adder)
|
||||||
|
|
||||||
|
def do_run(self, my_args, runner_args):
|
||||||
|
do_run_common(self, my_args, runner_args)
|
|
@ -39,6 +39,7 @@ def test_runner_imports():
|
||||||
'openocd',
|
'openocd',
|
||||||
'pyocd',
|
'pyocd',
|
||||||
'qemu',
|
'qemu',
|
||||||
|
'renode',
|
||||||
'silabs_commander',
|
'silabs_commander',
|
||||||
'spi_burn',
|
'spi_burn',
|
||||||
'stm32cubeprogrammer',
|
'stm32cubeprogrammer',
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue