stdlib: Implicitly determine FS/SE mode via workload

Setting whether FS or SE mode is to be used explicitly is not necessary
as we can determine this depending on what kind of workload is set.

Change-Id: Icc0ac749df231eaa9af8ba2363b466fcb405ccea
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/59571
Maintainer: Jason Lowe-Power <power.jg@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
diff --git a/configs/example/gem5_library/arm-hello.py b/configs/example/gem5_library/arm-hello.py
index 264731f..d94fb33 100644
--- a/configs/example/gem5_library/arm-hello.py
+++ b/configs/example/gem5_library/arm-hello.py
@@ -88,7 +88,7 @@
 )
 
 # Lastly we run the simulation.
-simulator = Simulator(board=board, full_system=False)
+simulator = Simulator(board=board)
 simulator.run()
 
 print(
diff --git a/src/python/gem5/components/boards/abstract_board.py b/src/python/gem5/components/boards/abstract_board.py
index 30fbfca..9ab6780 100644
--- a/src/python/gem5/components/boards/abstract_board.py
+++ b/src/python/gem5/components/boards/abstract_board.py
@@ -86,6 +86,12 @@
         self.memory = memory
         self.cache_hierarchy = cache_hierarchy
 
+        # This variable determines whether the board is to be executed in
+        # full-system or syscall-emulation mode. This is set when the workload
+        # is defined. Whether or not the board is to be run in FS mode is
+        # determined by which kind of workload is set.
+        self._is_fs = None
+
         # Setup the board and memory system's memory ranges.
         self._setup_memory_ranges()
 
@@ -140,6 +146,33 @@
         """
         return self.clk_domain
 
+    def _set_fullsystem(self, is_fs: bool) -> None:
+        """
+        Sets whether this board is to be run in FS or SE mode. This is set
+        via the workload (the workload specified determines whether this will
+        be run in FS mode or not). This is not intended to be set in a
+        configuration script ergo, it's private.
+
+        :param is_fs: Set whether the board is to be run in FS mode or SE mode.
+        """
+        self._is_fs = is_fs
+
+    def is_fullsystem(self) -> bool:
+        """
+        Returns True if the board is to be run in FS mode. Otherwise the board
+        is to be run in Se mode. An exception will be thrown if this has not
+        been set.
+
+        This function is used by the Simulator module to setup the simulation
+        correctly.
+        """
+        if self._is_fs  == None:
+            raise Exception("The workload for this board not yet to be set. "
+                            "Whether the board is to be executed in FS or SE "
+                            "mode is determined by which 'set workload' "
+                            "function is run.")
+        return self._is_fs
+
     @abstractmethod
     def _setup_board(self) -> None:
         """
diff --git a/src/python/gem5/components/boards/kernel_disk_workload.py b/src/python/gem5/components/boards/kernel_disk_workload.py
index 031fc60..1f4b8d7 100644
--- a/src/python/gem5/components/boards/kernel_disk_workload.py
+++ b/src/python/gem5/components/boards/kernel_disk_workload.py
@@ -26,6 +26,7 @@
 
 from abc import abstractmethod
 
+from .abstract_board import AbstractBoard
 from ...resources.resource import AbstractResource
 
 from typing import List, Optional
@@ -156,6 +157,14 @@
         items. True by default.
         """
 
+        # We assume this this is in a multiple-inheritance setup with an
+        # Abstract board. This function will not work otherwise.
+        assert(isinstance(self,AbstractBoard))
+
+        # If we are setting a workload of this type, we need to run as a
+        # full-system simulation.
+        self._set_fullsystem(True)
+
         # Set the kernel to use.
         self.workload.object_file = kernel.get_local_path()
 
diff --git a/src/python/gem5/components/boards/se_binary_workload.py b/src/python/gem5/components/boards/se_binary_workload.py
index 485c1a3..c166add 100644
--- a/src/python/gem5/components/boards/se_binary_workload.py
+++ b/src/python/gem5/components/boards/se_binary_workload.py
@@ -24,6 +24,7 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+from .abstract_board import AbstractBoard
 from ...resources.resource import AbstractResource
 
 from m5.objects import SEWorkload, Process
@@ -49,6 +50,14 @@
         :param binary: The resource encapsulating the binary to be run.
         """
 
+        # We assume this this is in a multiple-inheritance setup with an
+        # Abstract board. This function will not work otherwise.
+        assert(isinstance(self,AbstractBoard))
+
+        # If we are setting a workload of this type, we need to run as a
+        # SE-mode simulation.
+        self._set_fullsystem(False)
+
         self.workload = SEWorkload.init_compatible(binary.get_local_path())
 
         process = Process()
diff --git a/src/python/gem5/simulate/simulator.py b/src/python/gem5/simulate/simulator.py
index 1645dfc..c0ee38f 100644
--- a/src/python/gem5/simulate/simulator.py
+++ b/src/python/gem5/simulate/simulator.py
@@ -71,7 +71,7 @@
     def __init__(
         self,
         board: AbstractBoard,
-        full_system: bool = True,
+        full_system: Optional[bool] = None,
         on_exit_event: Optional[
             Dict[Union[str, ExitEvent], Generator[Optional[bool], None, None]]
         ] = None,
@@ -79,9 +79,10 @@
     ) -> None:
         """
         :param board: The board to be simulated.
-        :param full_system: Whether to run in full-system simulation or not. If
-        False, the simulation will run in Syscall-Execution mode. True by
-        default.
+        :param full_system: Whether to run as a full-system simulation or not.
+        This is optional and used to override default behavior. If not set,
+        whether or not to run in FS mode will be determined via the board's
+        `is_fullsystem()` function.
         :param on_exit_event: An optional map to specify the generator to
         execute on each exit event. The generator may yield a boolean which,
         if True, will have the Simulator exit the run loop.
@@ -264,7 +265,12 @@
         """
 
         if not self._instantiated:
-            root = Root(full_system=self._full_system, board=self._board)
+            root = Root(
+                full_system=self._full_system
+                if self._full_system is not None
+                else self._board.is_fullsystem(),
+                board=self._board,
+            )
 
             # We take a copy of the Root in case it's required elsewhere
             # (for example, in `get_stats()`).
diff --git a/tests/gem5/configs/simple_binary_run.py b/tests/gem5/configs/simple_binary_run.py
index 854fc66..ebe833a 100644
--- a/tests/gem5/configs/simple_binary_run.py
+++ b/tests/gem5/configs/simple_binary_run.py
@@ -100,7 +100,7 @@
 motherboard.set_se_binary_workload(binary)
 
 # Run the simulation
-simulator = Simulator(board=motherboard, full_system=False)
+simulator = Simulator(board=motherboard)
 simulator.run()
 
 print(