west: add native_sim flash, debugserver command

Add 'west flash' support which in the case of native_sim just start the
built application.
Reuse existing runner and rename it to be more generic as it does more
than just debugging now.

Also add debugserver command.

Fixes #36706

Signed-off-by: Anas Nashif <anas.nashif@intel.com>
diff --git a/boards/native/native_posix/board.cmake b/boards/native/native_posix/board.cmake
index f8c2fd5..c3f7c89 100644
--- a/boards/native/native_posix/board.cmake
+++ b/boards/native/native_posix/board.cmake
@@ -3,5 +3,6 @@
 
 set(SUPPORTED_EMU_PLATFORMS native)
 
-board_set_debugger_ifnset(native_gdb)
-board_finalize_runner_args(native_gdb)
+board_set_debugger_ifnset(native)
+board_set_flasher_ifnset(native)
+board_finalize_runner_args(native)
diff --git a/boards/native/native_sim/board.cmake b/boards/native/native_sim/board.cmake
index d9d444c..ca2d2ab 100644
--- a/boards/native/native_sim/board.cmake
+++ b/boards/native/native_sim/board.cmake
@@ -2,5 +2,6 @@
 
 set(SUPPORTED_EMU_PLATFORMS native)
 
-board_set_debugger_ifnset(native_gdb)
-board_finalize_runner_args(native_gdb)
+board_set_debugger_ifnset(native)
+board_set_flasher_ifnset(native)
+board_finalize_runner_args(native)
diff --git a/boards/native/nrf_bsim/board.cmake b/boards/native/nrf_bsim/board.cmake
index 70a6c0f..e94cde5 100644
--- a/boards/native/nrf_bsim/board.cmake
+++ b/boards/native/nrf_bsim/board.cmake
@@ -3,5 +3,6 @@
 
 set(SUPPORTED_EMU_PLATFORMS native)
 
-board_set_debugger_ifnset(native_gdb)
-board_finalize_runner_args(native_gdb)
+board_set_debugger_ifnset(native)
+board_set_flasher_ifnset(native)
+board_finalize_runner_args(native)
diff --git a/scripts/west_commands/runners/__init__.py b/scripts/west_commands/runners/__init__.py
index 850efcd..7e88d56 100644
--- a/scripts/west_commands/runners/__init__.py
+++ b/scripts/west_commands/runners/__init__.py
@@ -40,7 +40,7 @@
     'linkserver',
     'mdb',
     'misc',
-    'native_gdb',
+    'native',
     'nios2',
     'nrfjprog',
     'nrfutil',
diff --git a/scripts/west_commands/runners/native.py b/scripts/west_commands/runners/native.py
new file mode 100644
index 0000000..2cbcf60
--- /dev/null
+++ b/scripts/west_commands/runners/native.py
@@ -0,0 +1,81 @@
+# Copyright (c) 2023 Nordic Semiconductor
+# SPDX-License-Identifier: Apache-2.0
+
+"""This file provides a ZephyrBinaryRunner that launches GDB and enables
+flashing (running) a native application."""
+
+import argparse
+from runners.core import ZephyrBinaryRunner, RunnerCaps, RunnerConfig
+
+DEFAULT_GDB_PORT = 3333
+
+class NativeSimBinaryRunner(ZephyrBinaryRunner):
+    """Runs the ELF binary under GDB."""
+
+    def __init__(self, cfg,
+                 tui=False,
+                 gdb_port=DEFAULT_GDB_PORT):
+        super().__init__(cfg)
+        self.gdb_port = gdb_port
+
+        if cfg.gdb is None:
+            self.gdb_cmd = None
+        else:
+            self.gdb_cmd = [cfg.gdb] + (['-tui'] if tui else [])
+
+        if self.cfg.gdb is None:
+            raise ValueError("The provided RunnerConfig is missing the required field 'gdb'.")
+
+        if self.cfg.exe_file is None:
+            raise ValueError("The provided RunnerConfig is missing the required field 'exe_file'.")
+
+
+    @classmethod
+    def name(cls):
+        return 'native'
+
+    @classmethod
+    def capabilities(cls):
+        return RunnerCaps(commands={'debug', 'debugserver', 'flash'})
+
+    @classmethod
+    def do_add_parser(cls, parser: argparse.ArgumentParser):
+        parser.add_argument('--tui', default=False, action='store_true',
+                            help='if given, GDB uses -tui')
+        parser.add_argument('--gdb-port', default=DEFAULT_GDB_PORT,
+                            help='gdb port, defaults to {}'.format(
+                                DEFAULT_GDB_PORT))
+
+    @classmethod
+    def do_create(cls, cfg: RunnerConfig, args: argparse.Namespace) -> ZephyrBinaryRunner:
+        return NativeSimBinaryRunner(cfg,
+                                     tui=args.tui,
+                                     gdb_port=args.gdb_port)
+
+    def do_run(self, command: str, **kwargs):
+        if command == 'flash':
+            self.do_flash(**kwargs)
+        elif command == 'debug':
+            self.do_debug(**kwargs)
+        elif command == 'debugserver':
+            self.do_debugserver(**kwargs)
+        else:
+            assert False
+
+    def do_flash(self, **kwargs):
+        cmd = [self.cfg.exe_file]
+        self.check_call(cmd)
+
+    def do_debug(self, **kwargs):
+        # Clues to debug missing RunnerConfig values (in context of `west debug`):
+        #   build/zephyr/runners.yaml is missing `gdb` or `elf_file`.
+        #   board.cmake should have `board_finalize_runner_args(native)`.
+        #   build/CMakeCache.txt should have `CMAKE_GDB`.
+
+        cmd = (self.gdb_cmd + ['--quiet', self.cfg.exe_file])
+        self.check_call(cmd)
+
+    def do_debugserver(self, **kwargs):
+        cmd = (['gdbserver', ':{}'.format(self.gdb_port), self.cfg.exe_file])
+
+        self.check_call(cmd)
diff --git a/scripts/west_commands/runners/native_gdb.py b/scripts/west_commands/runners/native_gdb.py
deleted file mode 100644
index 163fe01..0000000
--- a/scripts/west_commands/runners/native_gdb.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright (c) 2023 Nordic Semiconductor
-# SPDX-License-Identifier: Apache-2.0
-
-"""This file provides a ZephyrBinaryRunner that launches GDB."""
-
-import argparse
-from runners.core import ZephyrBinaryRunner, RunnerCaps, RunnerConfig
-
-class NativeGDBBinaryRunner(ZephyrBinaryRunner):
-    """Runs the ELF binary under GDB."""
-
-    @classmethod
-    def name(cls):
-        return 'native_gdb'
-
-    @classmethod
-    def capabilities(cls):
-        return RunnerCaps(commands={'debug'})
-
-    @classmethod
-    def do_add_parser(cls, parser: argparse.ArgumentParser):
-        pass
-
-    @classmethod
-    def do_create(cls, cfg: RunnerConfig, args: argparse.Namespace) -> ZephyrBinaryRunner:
-        return NativeGDBBinaryRunner(cfg)
-
-    def do_run(self, command: str, **kwargs):
-        assert command == 'debug'
-
-        # Clues to debug missing RunnerConfig values (in context of `west debug`):
-        #   build/zephyr/runners.yaml is missing `gdb` or `elf_file`.
-        #   board.cmake should have `board_finalize_runner_args(native_gdb)`.
-        #   build/CMakeCache.txt should have `CMAKE_GDB`.
-
-        if self.cfg.gdb is None:
-            raise ValueError("The provided RunnerConfig is missing the required field 'gdb'.")
-
-        if self.cfg.exe_file is None:
-            raise ValueError("The provided RunnerConfig is missing the required field 'exe_file'.")
-
-        self.call([
-            self.cfg.gdb,
-            '--quiet',
-            self.cfg.exe_file,
-        ])
diff --git a/scripts/west_commands/tests/test_imports.py b/scripts/west_commands/tests/test_imports.py
index 274840f..89ca44c 100644
--- a/scripts/west_commands/tests/test_imports.py
+++ b/scripts/west_commands/tests/test_imports.py
@@ -31,7 +31,7 @@
                     'mdb-nsim',
                     'mdb-hw',
                     'misc-flasher',
-                    'native_gdb',
+                    'native',
                     'nios2',
                     'nrfjprog',
                     'nrfutil',