-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
WIP Change-Id: Id1ff08273f90a5b6cbba55f652a70b3756c72981
- Loading branch information
1 parent
579413f
commit c3995d6
Showing
3 changed files
with
338 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,322 @@ | ||
# Copyright (c) 2024 The Regents of the University of California | ||
# All rights reserved. | ||
# | ||
# Redistribution and use in source and binary forms, with or without | ||
# modification, are permitted provided that the following conditions are | ||
# met: redistributions of source code must retain the above copyright | ||
# notice, this list of conditions and the following disclaimer; | ||
# redistributions in binary form must reproduce the above copyright | ||
# notice, this list of conditions and the following disclaimer in the | ||
# documentation and/or other materials provided with the distribution; | ||
# neither the name of the copyright holders nor the names of its | ||
# contributors may be used to endorse or promote products derived from | ||
# this software without specific prior written permission. | ||
# | ||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
|
||
import m5 | ||
from m5.util import warn | ||
|
||
from _m5.event import GlobalSimLoopExitEvent | ||
|
||
from gem5.components.boards.abstract_board import AbstractBoard | ||
from gem5.components.processors.switchable_processor import SwitchableProcessor | ||
|
||
from .exit_event import ExitEvent | ||
|
||
|
||
def translate_exit_event(event: GlobalSimLoopExitEvent) -> "SimLoopExitEvent": | ||
"""This function translates the GlobalSimLoopExitEvent into a a | ||
SimLoopExitEvent object. Right now this works through a process of | ||
the SimLoopExitEvent subclass via the GlobalSimLoopExitEvent's `clause` | ||
property. | ||
:param event: The GlobalSimLoopExitEvent to translate. | ||
""" | ||
|
||
exit_string = event.getClause() | ||
|
||
if ( | ||
exit_string == "m5_workbegin instruction encountered" | ||
or exit_string == "workbegin" | ||
): | ||
return WorkBeginExit(event) | ||
elif ( | ||
exit_string == "m5_workend instruction encountered" | ||
or exit_string == "workend" | ||
): | ||
return WorkEndExit(event) | ||
elif exit_string == "simulate() limit reached": | ||
return MaxTickExit(event) | ||
elif exit_string == "Tick exit reached": | ||
return ScheduledTickExit(event) | ||
elif exit_string == "checkpoint": | ||
return CheckpointExit | ||
elif exit_string == "user interupt received": | ||
return UserInterruptExit(event) | ||
elif exit_string == "switchcpu": | ||
return SwitchCpuExit(event) | ||
elif exit_string == "simpoint starting point found": | ||
return SimpointBeginExit(event) | ||
elif exit_string == "a thread reached the max instruction count": | ||
return MaxInstructionsExit(event) | ||
|
||
else: | ||
# By default, we return a SimLoopExit object. | ||
return SimLoopExit(event) | ||
|
||
|
||
class SimLoopExit: | ||
"""The base class for all SimLoopExit objects. This is the most basic | ||
implementation of the SimLoopExitEvent object. It is a simple wrapper. It | ||
exits the simulator by default and does nothing else. | ||
""" | ||
|
||
# TODO: It would be good if there was an `info` called when each exit event | ||
# was handled. This would be useful for debugging and logging purposes. | ||
|
||
def __init__(self, event: GlobalSimLoopExitEvent): | ||
"""The constructor for the SimLoopExit object. The | ||
GlobalSimLoopExitEvent returned by the CPP Simuluator loop is passed | ||
here and stored in the object for reference. | ||
:param event: The GlobalSimLoopExitEvent that was returned by the | ||
simulator loop. | ||
""" | ||
self._event = event | ||
|
||
def get_event(self): | ||
"""Returns the GlobalSimLoopExitEvent that was passed to the object.""" | ||
return self._event | ||
|
||
def get_exit_event_enum(self) -> ExitEvent: | ||
"""Returns the ExitEvent enum that corresponds to the exit event | ||
that was passed to the object. By default this is ExitEvent.Exit but | ||
may be overridden by subclasses. | ||
""" | ||
return ExitEvent.Exit | ||
|
||
def default_exit_simulator(self) -> bool: | ||
"""The default behavior for whether the simulator should exit back to | ||
the Simulation configuration script. By default this is True (ergo, the | ||
simulator will exit back to the Simulation configuration script). This | ||
may be overridden by subclasses. | ||
""" | ||
return True | ||
|
||
def get_trigger_string(self) -> str: | ||
"""Returns a string explaining the trigger for the event. Used | ||
primarily for debugging and logging purposes. | ||
""" | ||
return "" # TODO: Implement this method and in the subclasses. | ||
|
||
def default_behavior(self, board: AbstractBoard) -> None: | ||
"""The default behavior for the SimLoopExitEvent. By default this does | ||
nothing but may be overridden by subclasses. | ||
""" | ||
pass | ||
|
||
|
||
class WorkBeginExit(SimLoopExit): | ||
"""An Exit that is triggerd by a ROI of a workload being entered. This, | ||
by default, the simulator module will not exit and the statistics will be | ||
reset, to be dumped with the next WorkEndExit event. | ||
""" | ||
|
||
def __init__(self, event: GlobalSimLoopExitEvent): | ||
super().__init__(event) | ||
|
||
def get_exit_event_enum(self) -> ExitEvent: | ||
return ExitEvent.WORKBEGIN | ||
|
||
def default_exit_simulator(self) -> bool: | ||
return False | ||
|
||
def default_behavior(self, board: AbstractBoard) -> None: | ||
m5.stats.reset() | ||
|
||
|
||
class WorkEndExit(SimLoopExit): | ||
"""An Exit that is triggerd by a ROI of a workload exiting. This, | ||
by default, the simulator module will exit and the statistics will be | ||
dumped. | ||
""" | ||
|
||
def __init__(self, event: GlobalSimLoopExitEvent): | ||
super().__init__(event) | ||
|
||
def get_exit_event_enum(self) -> ExitEvent: | ||
return ExitEvent.WORKEND | ||
|
||
def default_exit_simulator(self) -> bool: | ||
return True | ||
|
||
def default_behavior(self, board: AbstractBoard) -> None: | ||
m5.stats.dump() | ||
|
||
|
||
class CheckpointExit(SimLoopExit): | ||
"""An exit that is triggered by the simulated system with the intent of | ||
creating a checkpoint of the system state. This, by default, will dump a | ||
checkpoint and not exit the simulator. | ||
""" | ||
|
||
def __init__(self, event: GlobalSimLoopExitEvent): | ||
super().__init__(event) | ||
|
||
def get_exit_event_enum(self) -> ExitEvent: | ||
return ExitEvent.CHECKPOINT | ||
|
||
def default_exit_simulator(self) -> bool: | ||
return False | ||
|
||
def default_behavior(self, board: AbstractBoard) -> None: | ||
m5.checkpoint(m5.output_dir + "/cpt." + str(m5.curTick())) | ||
|
||
|
||
class SwitchCpuExit(SimLoopExit): | ||
"""An exit that is triggered to switch the CPUs in the system. The default | ||
behavior is to switch the CPUs in the board (if the board is using a | ||
switchable) processor. By default the Simulator will not be exit. | ||
""" | ||
|
||
def __init__(self, event: GlobalSimLoopExitEvent): | ||
super().__init__(event) | ||
|
||
def get_exit_event_enum(self) -> ExitEvent: | ||
return ExitEvent.SWITCHCPU | ||
|
||
def default_exit_simulator(self) -> bool: | ||
return False | ||
|
||
def default_behavior(self, board: AbstractBoard) -> None: | ||
if isinstance(board.processor(), SwitchableProcessor): | ||
board.processor().switch() | ||
else: | ||
warn( | ||
"The board was not setup with a switchable processor. " | ||
f"Ignoring switch event at tick {m5.curTick()}." | ||
) | ||
|
||
|
||
class UserInterruptExit(SimLoopExit): | ||
"""An exit that is triggered by a user interrupt. The default behavior is | ||
to exit the simulation entirely by throwing an exception | ||
""" | ||
|
||
def __init__(self, event: GlobalSimLoopExitEvent): | ||
super().__init__(event) | ||
|
||
def get_exit_event_enum(self) -> ExitEvent: | ||
return ExitEvent.USER_INTERRUPT | ||
|
||
def default_exit_simulator(self) -> bool: | ||
return True | ||
|
||
def default_behavior(self, board: AbstractBoard) -> None: | ||
raise KeyboardInterrupt( | ||
"User interrupt received at tick {m5.curTick()}." | ||
) | ||
|
||
|
||
class ScheduledTickExit(SimLoopExit): | ||
"""An exit that is triggered by the simulated system reaching a scheduled | ||
tick count. The default behavior is to exit the simulation loop. | ||
""" | ||
|
||
def __init__(self, event: GlobalSimLoopExitEvent): | ||
super().__init__(event) | ||
|
||
def get_exit_event_enum(self) -> ExitEvent: | ||
return ExitEvent.SCHEDULED_TICK | ||
|
||
def default_exit_simulator(self) -> bool: | ||
return True | ||
|
||
|
||
class MaxTickExit(ScheduledTickExit): | ||
"""An exit that is triggered by the simulated system reaching the maximum | ||
tick count. The default behavior is the same as a ScheduledTickExit. | ||
""" | ||
|
||
def __init__(self, event: GlobalSimLoopExitEvent): | ||
super().__init__(event) | ||
|
||
def get_exit_event_enum(self) -> ExitEvent: | ||
return ExitEvent.MAX_TICK | ||
|
||
|
||
class SimpointBeginExit(SimLoopExit): | ||
"""An exit that is triggered by the simulated system reaching the beginning | ||
of a simpoint. The default behavior is to exit the simulation loop. | ||
""" | ||
|
||
def __init__(self, event: GlobalSimLoopExitEvent): | ||
super().__init__(event) | ||
|
||
def get_exit_event_enum(self) -> ExitEvent: | ||
return ExitEvent.SIMPOINT_BEGIN | ||
|
||
def default_exit_simulator(self) -> bool: | ||
return True | ||
|
||
|
||
class MaxInstructionsExit(SimLoopExit): | ||
"""An exit that is triggered by the simulated system reaching the maximum | ||
instruction count. The default behavior is to exit the simulation loop. | ||
""" | ||
|
||
def __init__(self, event: GlobalSimLoopExitEvent): | ||
super().__init__(event) | ||
|
||
def get_exit_event_enum(self) -> ExitEvent: | ||
return ExitEvent.MAX_INSTS | ||
|
||
def default_exit_simulator(self) -> bool: | ||
return True | ||
|
||
|
||
class FailExit(SimLoopExit): | ||
"""An exit that is triggered by a simulation failure. The behavior is the | ||
same as the default SimLoopExit event. | ||
""" | ||
|
||
def __init__(self, event: GlobalSimLoopExitEvent): | ||
super().__init__(event) | ||
|
||
def get_exit_event_enum(self) -> ExitEvent: | ||
return ExitEvent.FAIL | ||
|
||
|
||
class KernelPanicExit(FailExit): | ||
"""An exit that is triggered by the simulated system experiencing a kernel | ||
panic. The default behavior is the same as the default FailExit. | ||
""" | ||
|
||
def __init__(self, event: GlobalSimLoopExitEvent): | ||
super().__init__(event) | ||
|
||
def get_exit_event_enum(self) -> ExitEvent: | ||
return ExitEvent.KERNEL_PANIC | ||
|
||
|
||
class KernelOopsExit(FailExit): | ||
"""An exit that is triggered by the simulated system experiencing a kernel | ||
oops. The default behavior is the same as the default FailExit. | ||
""" | ||
|
||
def __init__(self, event: GlobalSimLoopExitEvent): | ||
super().__init__(event) | ||
|
||
def get_exit_event_enum(self) -> ExitEvent: | ||
return ExitEvent.KERNEL_OOPS |
Oops, something went wrong.