diff --git a/configs/example/lupv/run_lupv.py b/configs/example/lupv/run_lupv.py index f6f938b16c..57bf6ca6b8 100644 --- a/configs/example/lupv/run_lupv.py +++ b/configs/example/lupv/run_lupv.py @@ -110,8 +110,7 @@ board.set_kernel_disk_workload( # Begin running of the simulation. print("Running with ISA: " + processor.get_isa().name) print() -root = Root(full_system=True, system=board) -board._pre_instantiate() +root = board._pre_instantiate() m5.instantiate() print("Beginning simulation!") diff --git a/src/python/gem5/components/boards/abstract_board.py b/src/python/gem5/components/boards/abstract_board.py index 83ca32d9c0..cd6f559937 100644 --- a/src/python/gem5/components/boards/abstract_board.py +++ b/src/python/gem5/components/boards/abstract_board.py @@ -41,6 +41,7 @@ from m5.objects import ( ClockDomain, IOXBar, Port, + Root, SrcClockDomain, System, VoltageDomain, @@ -117,12 +118,6 @@ class AbstractBoard: # Simulator module. self._checkpoint = None - # Setup the board and memory system's memory ranges. - self._setup_memory_ranges() - - # Setup board properties unique to the board being constructed. - self._setup_board() - # A private variable to record whether `_connect_things` has been # been called. self._connect_things_called = False @@ -194,6 +189,9 @@ class AbstractBoard: """ self._is_fs = is_fs + self._setup_memory_ranges() + self._setup_board() + def is_fullsystem(self) -> bool: """ Returns ``True`` if the board is to be run in FS mode. Otherwise the board @@ -252,11 +250,14 @@ class AbstractBoard: @abstractmethod def _setup_board(self) -> None: """ - This function is called in the AbstractBoard constructor, before the - memory, processor, and cache hierarchy components are incorporated via - ``_connect_thing()``, but after the ``_setup_memory_ranges()`` function. - This function should be overridden by boards to specify components, - connections unique to that board. + This function is called at the end of `_set_fullsystem`. The reason for + this is the board's configuraiton varies significantly depending on + whether it is to be run in FS or SE mode. This function is therefore + called when a workload is set --- after construction but before + `_pre_instantiate` is called. + + As `_setup_memory_ranges()` is set in the constructor, this function + can be considered to have been called prior to `_setup_board """ raise NotImplementedError @@ -330,10 +331,18 @@ class AbstractBoard: """ Set the memory ranges for this board and memory system. - This is called in the constructor, prior to ``_setup_board`` and - ``_connect_things``. It should query the board's memory to determine the - size and the set the memory ranges on the memory system and on the - board. + This is called at the end of the `_set_fullsystem` function but before + `_setup_board`. `_set_fullsystem` is called when the workload is + declared. It is before `_pre_instantiate` (but, obviously after + construction). + + It should query the board's memory + to determine the size and the set the memory ranges on the memory + system and on the board. + + As thisis called at the end of `_set_fullsystem`, the board's memory + can be setup differently depending on whether the board is to be run in + FS or SE mode. The simplest implementation sets the board's memory range to the size of memory and memory system's range to be the same as the board. Full @@ -391,13 +400,42 @@ class AbstractBoard: self.get_cache_hierarchy()._post_instantiate() self.get_memory()._post_instantiate() - def _pre_instantiate(self): + def _pre_instantiate(self, full_system: Optional[bool] = None) -> Root: """To be called immediately before ``m5.instantiate``. This is where - ``_connect_things`` is executed by default.""" + ``_connect_things`` is executed by default and the root object is Root + object is created and returned. - # Connect the memory, processor, and cache hierarchy. + :param full_system: Used to pass the full system flag to the board from + the Simulator module. **Note**: This was + implemented solely to maintain backawards + compatibility with while the Simululator module's + `full_system` flag is in state of deprecation. This + parameter will be removed when it is. When this + occurs whether a simulation is to be run in FS or + SE mode will be determined by the board set.""" + + # 1. Connect the memory, processor, and cache hierarchy. self._connect_things() + # 2. Create the root object + root = Root( + full_system=( + full_system + if full_system is not None + else self.is_fullsystem() + ), + board=self, + ) + + # 3. Call any of the components' `_pre_instantiate` functions. + self.get_processor()._pre_instantiate(root) + self.get_memory()._pre_instantiate(root) + if self.get_cache_hierarchy(): + self.get_cache_hierarchy()._pre_instantiate(root) + + # 4. Return the root object. + return root + def _connect_things_check(self): """ Here we check that connect things has been called and throw an diff --git a/src/python/gem5/components/boards/arm_board.py b/src/python/gem5/components/boards/arm_board.py index c2739ebff7..2da8cd18f2 100644 --- a/src/python/gem5/components/boards/arm_board.py +++ b/src/python/gem5/components/boards/arm_board.py @@ -28,6 +28,7 @@ import os from abc import ABCMeta from typing import ( List, + Optional, Sequence, Tuple, ) @@ -331,8 +332,8 @@ class ArmBoard(ArmSystem, AbstractBoard, KernelDiskWorkload): self.system_port = port @overrides(AbstractBoard) - def _pre_instantiate(self): - super()._pre_instantiate() + def _pre_instantiate(self, full_system: Optional[bool] = None) -> None: + super()._pre_instantiate(full_system=full_system) # Add the PCI devices. self.pci_devices = self._pci_devices diff --git a/src/python/gem5/components/boards/riscv_board.py b/src/python/gem5/components/boards/riscv_board.py index e8e27029f2..e14833c996 100644 --- a/src/python/gem5/components/boards/riscv_board.py +++ b/src/python/gem5/components/boards/riscv_board.py @@ -26,7 +26,10 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import os -from typing import List +from typing import ( + List, + Optional, +) import m5 from m5.objects import ( @@ -498,7 +501,7 @@ class RiscvBoard(AbstractSystemBoard, KernelDiskWorkload): return "/dev/vda" @overrides(AbstractSystemBoard) - def _pre_instantiate(self): + def _pre_instantiate(self, full_system: Optional[bool] = None): if len(self._bootloader) > 0: self.workload.bootloader_addr = 0x0 self.workload.bootloader_filename = self._bootloader[0] @@ -507,7 +510,7 @@ class RiscvBoard(AbstractSystemBoard, KernelDiskWorkload): else: self.workload.kernel_addr = 0x0 self.workload.entry_point = 0x80000000 - self._connect_things() + super()._pre_instantiate(full_system=full_system) @overrides(KernelDiskWorkload) def _add_disk_to_board(self, disk_image: AbstractResource): diff --git a/src/python/gem5/components/cachehierarchies/abstract_cache_hierarchy.py b/src/python/gem5/components/cachehierarchies/abstract_cache_hierarchy.py index b0435543af..dc20c14f70 100644 --- a/src/python/gem5/components/cachehierarchies/abstract_cache_hierarchy.py +++ b/src/python/gem5/components/cachehierarchies/abstract_cache_hierarchy.py @@ -42,7 +42,10 @@ from abc import ( ) from typing import Callable -from m5.objects import SubSystem +from m5.objects import ( + Root, + SubSystem, +) from m5.util.fdthelper import * from ..boards.abstract_board import AbstractBoard @@ -139,6 +142,18 @@ class AbstractCacheHierarchy(SubSystem): """ raise NotImplementedError + def _pre_instantiate(self, root: Root) -> None: + """Called in the `AbstractBoard`'s `_pre_instantiate` method. This is + called after `connect_things`, after the creation of the root object + (which is passed in as an argument), but before `m5.instantiate`). + + Subclasses should override this method to set up any connections. + + At present there is no general task that must be specified here and is + default or applicable to all cache hierarchies. + """ + pass + def _post_instantiate(self): """Called to set up anything needed after ``m5.instantiate``.""" pass diff --git a/src/python/gem5/components/memory/abstract_memory_system.py b/src/python/gem5/components/memory/abstract_memory_system.py index 06fa60cad8..6d24e724b6 100644 --- a/src/python/gem5/components/memory/abstract_memory_system.py +++ b/src/python/gem5/components/memory/abstract_memory_system.py @@ -38,6 +38,7 @@ from m5.objects import ( AddrRange, MemCtrl, Port, + Root, SubSystem, ) @@ -50,6 +51,18 @@ class AbstractMemorySystem(SubSystem): def __init__(self) -> None: super().__init__() + def _pre_instantiate(self, root: Root) -> None: + """Called in the `AbstractBoard`'s `_pre_instantiate` method. This is + called after `connect_things`, after the creation of the root object + (which is passed in as an argument), but before `m5.instantiate`). + + Subclasses should override this method to set up any connections. + + At present there is no general task that must be specified here and is + default or applicable to all memory systems. + """ + pass + @abstractmethod def incorporate_memory(self, board: AbstractBoard) -> None: """This function completes all of the necessary steps to add this diff --git a/src/python/gem5/components/processors/abstract_processor.py b/src/python/gem5/components/processors/abstract_processor.py index 79dba438a2..303b9658f2 100644 --- a/src/python/gem5/components/processors/abstract_processor.py +++ b/src/python/gem5/components/processors/abstract_processor.py @@ -33,7 +33,10 @@ from typing import ( Optional, ) -from m5.objects import SubSystem +from m5.objects import ( + Root, + SubSystem, +) from ...isas import ISA from ...utils.requires import requires @@ -83,3 +86,12 @@ class AbstractProcessor(SubSystem): def _post_instantiate(self) -> None: """Called to set up anything needed after ``m5.instantiate``.""" pass + + def _pre_instantiate(self, root: Root) -> None: + """Called in the `AbstractBoard`'s `_pre_instantiate` method. This is + called after `connect_things`, after the creation of the root object + (which is passed in as an argument), but before `m5.instantiate`). + + Subclasses should override this method to set up any connections. + """ + pass diff --git a/src/python/gem5/components/processors/base_cpu_processor.py b/src/python/gem5/components/processors/base_cpu_processor.py index b1a63ea8ce..674148b409 100644 --- a/src/python/gem5/components/processors/base_cpu_processor.py +++ b/src/python/gem5/components/processors/base_cpu_processor.py @@ -27,12 +27,14 @@ from typing import List +import m5 from m5.objects import ( BaseAtomicSimpleCPU, BaseMinorCPU, BaseNonCachingSimpleCPU, BaseO3CPU, BaseTimingSimpleCPU, + Root, ) from m5.util import warn @@ -99,3 +101,9 @@ class BaseCPUProcessor(AbstractProcessor): board.set_mem_mode(MemMode.ATOMIC) else: raise NotImplementedError + + def _pre_instantiate(self, root: Root) -> None: + super()._pre_instantiate(root) + if any(core.is_kvm_core() for core in self.get_cores()): + m5.ticks.fixGlobalFrequency() + root.sim_quantum = m5.ticks.fromSeconds(0.001) diff --git a/src/python/gem5/components/processors/switchable_processor.py b/src/python/gem5/components/processors/switchable_processor.py index 2436c9e81f..a5a9ae2b6b 100644 --- a/src/python/gem5/components/processors/switchable_processor.py +++ b/src/python/gem5/components/processors/switchable_processor.py @@ -31,6 +31,7 @@ from typing import ( ) import m5 +from m5.objects import Root from ...utils.override import * from ..boards.abstract_board import AbstractBoard @@ -155,3 +156,24 @@ class SwitchableProcessor(AbstractProcessor): # Ensure the current processor is updated. self._current_cores = to_switch + + def _pre_instantiate(self, root: Root) -> None: + super()._pre_instantiate(root) + # The following is a bit of a hack. If a simulation is to use a KVM + # core then the `sim_quantum` value must be set. However, in the + # case of using a SwitchableProcessor the KVM cores may be + # switched out and therefore not accessible via `get_cores()`. + # This is the reason for the `isinstance` check. + # + # We cannot set the `sim_quantum` value in every simulation as + # setting it causes the scheduling of exits to be off by the + # `sim_quantum` value (something necessary if we are using KVM + # cores). Ergo we only set the value of KVM cores are present. + # + # There is still a bug here in that if the user is switching to and + # from KVM and non-KVM cores via the SwitchableProcessor then the + # scheduling of exits for the non-KVM cores will be incorrect. This + # will be fixed at a later date. + if self._prepare_kvm: + m5.ticks.fixGlobalFrequency() + root.sim_quantum = m5.ticks.fromSeconds(0.001) diff --git a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py index 23a7dcc8cb..ba9588c725 100644 --- a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py +++ b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py @@ -313,7 +313,7 @@ class RISCVMatchedBoard( memory.set_memory_range(self.mem_ranges) @overrides(AbstractSystemBoard) - def _pre_instantiate(self): + def _pre_instantiate(self, full_system: Optional[bool] = None) -> None: if self._fs: if len(self._bootloader) > 0: self.workload.bootloader_addr = 0x0 @@ -326,7 +326,7 @@ class RISCVMatchedBoard( self.workload.kernel_addr = 0x0 self.workload.entry_point = 0x80000000 - self._connect_things() + super()._pre_instantiate(full_system=full_system) def generate_device_tree(self, outdir: str) -> None: """Creates the ``dtb`` and ``dts`` files. diff --git a/src/python/gem5/simulate/simulator.py b/src/python/gem5/simulate/simulator.py index 49dfac2bdf..ba74361915 100644 --- a/src/python/gem5/simulate/simulator.py +++ b/src/python/gem5/simulate/simulator.py @@ -117,6 +117,10 @@ class Simulator: behavior. If not set, whether or not to run in FS mode will be determined via the board's ``is_fullsystem()`` function. + **Warning: This parameter is deprecated. The board + determines if the simulation is full system or not. + This parameter will be removed in a future gem5 + release.** :param on_exit_event: An optional map to specify what to execute on each exit event. There are three possibilities here: a generator, a list of functions, or a single function. @@ -291,6 +295,15 @@ class Simulator: """ + if full_system is not None: + warn( + "Setting the full_system parameter via the Simulator " + "constructor is deprecated and will be removed in future " + "releases of gem5. " + "The board determines if the simulation is full system or not " + "via it's `is_fullsystem` method." + ) + self.set_max_ticks(max_ticks) if id: @@ -651,45 +664,12 @@ class Simulator: if not self._instantiated: # Before anything else we run the AbstractBoard's - # `_pre_instantiate` function. - self._board._pre_instantiate() - - root = Root( - full_system=( - self._full_system - if self._full_system is not None - else self._board.is_fullsystem() - ), - board=self._board, + # `_pre_instantiate` function. This returns the root object which + # is required for instantiation. + self._root = self._board._pre_instantiate( + full_system=self._full_system ) - # We take a copy of the Root in case it's required elsewhere - # (for example, in `get_stats()`). - self._root = root - - # The following is a bit of a hack. If a simulation is to use a KVM - # core then the `sim_quantum` value must be set. However, in the - # case of using a SwitchableProcessor the KVM cores may be - # switched out and therefore not accessible via `get_cores()`. - # This is the reason for the `isinstance` check. - # - # We cannot set the `sim_quantum` value in every simulation as - # setting it causes the scheduling of exits to be off by the - # `sim_quantum` value (something necessary if we are using KVM - # cores). Ergo we only set the value of KVM cores are present. - # - # There is still a bug here in that if the user is switching to and - # from KVM and non-KVM cores via the SwitchableProcessor then the - # scheduling of exits for the non-KVM cores will be incorrect. This - # will be fixed at a later date. - processor = self._board.processor - if any(core.is_kvm_core() for core in processor.get_cores()) or ( - isinstance(processor, SwitchableProcessor) - and any(core.is_kvm_core() for core in processor._all_cores()) - ): - m5.ticks.fixGlobalFrequency() - root.sim_quantum = m5.ticks.fromSeconds(0.001) - # m5.instantiate() takes a parameter specifying the path to the # checkpoint directory. If the parameter is None, no checkpoint # will be restored. diff --git a/tests/gem5/kvm_fork_tests/configs/boot_kvm_fork_run.py b/tests/gem5/kvm_fork_tests/configs/boot_kvm_fork_run.py index 8850a27c75..be6e6009e1 100644 --- a/tests/gem5/kvm_fork_tests/configs/boot_kvm_fork_run.py +++ b/tests/gem5/kvm_fork_tests/configs/boot_kvm_fork_run.py @@ -207,15 +207,15 @@ print("Running with ISA: " + processor.get_isa().name) print("Running with protocol: " + get_runtime_coherence_protocol().name) print() -root = Root(full_system=True, system=motherboard) +# Disable the gdb ports. Required for forking. +m5.disableAllListeners() +root = motherboard._pre_instantiate() # TODO: This of annoying. Is there a way to fix this to happen # automatically when running KVM? root.sim_quantum = int(1e9) -# Disable the gdb ports. Required for forking. -m5.disableAllListeners() -motherboard._pre_instantiate() + m5.instantiate() # Simulate the inital boot with the starting KVM cpu diff --git a/tests/gem5/replacement_policies/configs/run_replacement_policy.py b/tests/gem5/replacement_policies/configs/run_replacement_policy.py index 8f52a061f6..f7ecdb71de 100644 --- a/tests/gem5/replacement_policies/configs/run_replacement_policy.py +++ b/tests/gem5/replacement_policies/configs/run_replacement_policy.py @@ -83,9 +83,8 @@ motherboard = TestBoard( memory=memory, cache_hierarchy=cache_hierarchy, ) -root = Root(full_system=False, system=motherboard) -motherboard._pre_instantiate() +root = motherboard._pre_instantiate() m5.instantiate() generator.start_traffic() diff --git a/tests/gem5/replacement_policies/run_replacement_policy.py b/tests/gem5/replacement_policies/run_replacement_policy.py index 8f52a061f6..f7ecdb71de 100644 --- a/tests/gem5/replacement_policies/run_replacement_policy.py +++ b/tests/gem5/replacement_policies/run_replacement_policy.py @@ -83,9 +83,8 @@ motherboard = TestBoard( memory=memory, cache_hierarchy=cache_hierarchy, ) -root = Root(full_system=False, system=motherboard) -motherboard._pre_instantiate() +root = motherboard._pre_instantiate() m5.instantiate() generator.start_traffic() diff --git a/tests/gem5/traffic_gen/configs/simple_traffic_run.py b/tests/gem5/traffic_gen/configs/simple_traffic_run.py index 3a850b497d..7c264cefe9 100644 --- a/tests/gem5/traffic_gen/configs/simple_traffic_run.py +++ b/tests/gem5/traffic_gen/configs/simple_traffic_run.py @@ -202,9 +202,7 @@ motherboard = TestBoard( cache_hierarchy=cache_hierarchy, ) -root = Root(full_system=False, system=motherboard) - -motherboard._pre_instantiate() +root = motherboard._pre_instantiate() m5.instantiate() generator.start_traffic()