diff --git a/boards/common/renode.board.cmake b/boards/common/renode.board.cmake new file mode 100644 index 00000000000..c7c9b02ec59 --- /dev/null +++ b/boards/common/renode.board.cmake @@ -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) diff --git a/boards/microchip/m2gl025_miv/board.cmake b/boards/microchip/m2gl025_miv/board.cmake index 2919ac78742..74cca86292d 100644 --- a/boards/microchip/m2gl025_miv/board.cmake +++ b/boards/microchip/m2gl025_miv/board.cmake @@ -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) diff --git a/boards/sifive/hifive1/board.cmake b/boards/sifive/hifive1/board.cmake index 4f39320870c..29ec8b2e6ab 100644 --- a/boards/sifive/hifive1/board.cmake +++ b/boards/sifive/hifive1/board.cmake @@ -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) diff --git a/cmake/flash/CMakeLists.txt b/cmake/flash/CMakeLists.txt index 392274891f1..bdfa7fd5f87 100644 --- a/cmake/flash/CMakeLists.txt +++ b/cmake/flash/CMakeLists.txt @@ -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() diff --git a/cmake/modules/extensions.cmake b/cmake/modules/extensions.cmake index 315890732c3..6c0231676a2 100644 --- a/cmake/modules/extensions.cmake +++ b/cmake/modules/extensions.cmake @@ -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. # diff --git a/doc/develop/west/build-flash-debug.rst b/doc/develop/west/build-flash-debug.rst index 8356d95cade..4456151aa06 100644 --- a/doc/develop/west/build-flash-debug.rst +++ b/doc/develop/west/build-flash-debug.rst @@ -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 ******* diff --git a/scripts/west-commands.yml b/scripts/west-commands.yml index 6cd0c511fb3..54254c381fa 100644 --- a/scripts/west-commands.yml +++ b/scripts/west-commands.yml @@ -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 diff --git a/scripts/west_commands/run_common.py b/scripts/west_commands/run_common.py index 8656d090767..7cd30c86fe6 100644 --- a/scripts/west_commands/run_common.py +++ b/scripts/west_commands/run_common.py @@ -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 diff --git a/scripts/west_commands/runners/__init__.py b/scripts/west_commands/runners/__init__.py index aa5686f73b0..53df19d0550 100644 --- a/scripts/west_commands/runners/__init__.py +++ b/scripts/west_commands/runners/__init__.py @@ -48,6 +48,7 @@ _names = [ 'nxp_s32dbg', 'openocd', 'pyocd', + 'renode', 'qemu', 'silabs_commander', 'spi_burn', diff --git a/scripts/west_commands/runners/core.py b/scripts/west_commands/runners/core.py index d77784486d0..618cb4e1ee2 100644 --- a/scripts/west_commands/runners/core.py +++ b/scripts/west_commands/runners/core.py @@ -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 diff --git a/scripts/west_commands/runners/renode.py b/scripts/west_commands/runners/renode.py new file mode 100644 index 00000000000..8937199420c --- /dev/null +++ b/scripts/west_commands/runners/renode.py @@ -0,0 +1,62 @@ +# Copyright (c) 2024 Antmicro +# +# 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) diff --git a/scripts/west_commands/simulate.py b/scripts/west_commands/simulate.py new file mode 100644 index 00000000000..ad3d9073303 --- /dev/null +++ b/scripts/west_commands/simulate.py @@ -0,0 +1,29 @@ +# Copyright (c) 2024 Antmicro +# +# 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) diff --git a/scripts/west_commands/tests/test_imports.py b/scripts/west_commands/tests/test_imports.py index b101ab42fe6..c842df0cd51 100644 --- a/scripts/west_commands/tests/test_imports.py +++ b/scripts/west_commands/tests/test_imports.py @@ -39,6 +39,7 @@ def test_runner_imports(): 'openocd', 'pyocd', 'qemu', + 'renode', 'silabs_commander', 'spi_burn', 'stm32cubeprogrammer',