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:
Michał Szprejda 2024-03-07 10:30:09 +01:00 committed by Alberto Escolar
commit 80900cbc3b
13 changed files with 172 additions and 7 deletions

View 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)

View file

@ -3,3 +3,6 @@
set(SUPPORTED_EMU_PLATFORMS renode)
set(RENODE_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/support/m2gl025_miv.resc)
set(RENODE_UART sysbus.uart)
set_ifndef(BOARD_SIM_RUNNER renode)
include(${ZEPHYR_BASE}/boards/common/renode.board.cmake)

View file

@ -28,3 +28,6 @@ elseif("${BOARD_REVISION}" STREQUAL "B")
board_runner_args(jlink "--tool-opt=-autoconnect 1")
include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
endif()
set_ifndef(BOARD_SIM_RUNNER renode)
include(${ZEPHYR_BASE}/boards/common/renode.board.cmake)

View file

@ -97,6 +97,10 @@ function(create_runners_yaml)
runners_yaml_append("\n# Default debug runner if --runner is not given.")
runners_yaml_append("debug-runner: ${BOARD_DEBUG_RUNNER}")
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.
runners_yaml_append_config()

View file

@ -705,9 +705,10 @@ endfunction()
# This section provides glue between CMake and the Python code that
# manages the runners.
set(TYPES "FLASH" "DEBUG" "SIM")
function(_board_check_runner_type type) # private helper
if (NOT (("${type}" STREQUAL "FLASH") OR ("${type}" STREQUAL "DEBUG")))
message(FATAL_ERROR "invalid type ${type}; should be FLASH or DEBUG")
if (NOT "${type}" IN_LIST TYPES)
message(FATAL_ERROR "invalid type ${type}; should be one of: ${TYPES}")
endif()
endfunction()
@ -723,8 +724,8 @@ endfunction()
#
# This would set the board's flash runner to "pyocd".
#
# In general, "type" is FLASH or DEBUG, and "runner" is the name of a
# runner.
# In general, "type" is FLASH, DEBUG or SIM and "runner" is
# the name of a runner.
function(board_set_runner type runner)
_board_check_runner_type(${type})
if (DEFINED BOARD_${type}_RUNNER)
@ -765,6 +766,11 @@ macro(board_set_debugger_ifnset runner)
board_set_runner_ifnset(DEBUG ${runner})
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
# CMakeLists.txt files.
#

View file

@ -698,6 +698,49 @@ determined by the imported subclasses of ``ZephyrBinaryRunner``.
runner implementations are in other submodules, such as ``runners.nrfjprog``,
``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
*******

View file

@ -66,3 +66,8 @@ west-commands:
- name: bindesc
class: Bindesc
help: work with Binary Descriptors
- file: scripts/west_commands/simulate.py
commands:
- name: simulate
class: Simulate
help: simulate board

View file

@ -512,7 +512,7 @@ def runners_yaml_path(build_dir, board):
ret = Path(build_dir) / 'zephyr' / 'runners.yaml'
if not ret.is_file():
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)')
return ret

View file

@ -48,6 +48,7 @@ _names = [
'nxp_s32dbg',
'openocd',
'pyocd',
'renode',
'qemu',
'silabs_commander',
'spi_burn',

View file

@ -200,7 +200,7 @@ class MissingProgram(FileNotFoundError):
super().__init__(errno.ENOENT, os.strerror(errno.ENOENT), program)
_RUNNERCAPS_COMMANDS = {'flash', 'debug', 'debugserver', 'attach'}
_RUNNERCAPS_COMMANDS = {'flash', 'debug', 'debugserver', 'attach', 'simulate'}
@dataclass
class RunnerCaps:
@ -212,7 +212,7 @@ class RunnerCaps:
Available capabilities:
- 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
-i, --dev-id option. This is useful when the user has multiple debuggers

View 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)

View 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)

View file

@ -39,6 +39,7 @@ def test_runner_imports():
'openocd',
'pyocd',
'qemu',
'renode',
'silabs_commander',
'spi_burn',
'stm32cubeprogrammer',