Skip to content

Commit

Permalink
stdlib: Add SimLoopExit event
Browse files Browse the repository at this point in the history
WIP

Change-Id: Id1ff08273f90a5b6cbba55f652a70b3756c72981
  • Loading branch information
BobbyRBruce committed Mar 19, 2024
1 parent 579413f commit c3995d6
Show file tree
Hide file tree
Showing 3 changed files with 338 additions and 56 deletions.
322 changes: 322 additions & 0 deletions src/python/gem5/simulate/sim_loop_exit.py
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

0 comments on commit c3995d6

Please sign in to comment.