diff --git a/src/arch/arm/ArmPMU.py b/src/arch/arm/ArmPMU.py index 3eaed077eb..a07239bb29 100644 --- a/src/arch/arm/ArmPMU.py +++ b/src/arch/arm/ArmPMU.py @@ -1,5 +1,5 @@ # -*- mode:python -*- -# Copyright (c) 2009-2014, 2017, 2020, 2022 Arm Limited +# Copyright (c) 2009-2014, 2017-2018, 2020, 2022-2023 Arm Limited # All rights reserved. # # The license below extends only to copyright in the software and shall @@ -215,11 +215,14 @@ class ArmPMU(SimObject): platform = Param.Platform(Parent.any, "Platform this device is part of.") eventCounters = Param.Int(31, "Number of supported PMU counters") interrupt = Param.ArmInterruptPin("PMU interrupt") + exitOnPMUControl = Param.Bool( + False, "Exit on PMU enable, disable, or reset" + ) # 64-bit PMU event counters are officially supported when # Armv8.5-A FEAT_PMUv3p5 is implemented. This parameter is not a # full implementation of FEAT_PMUv3p5. use64bitCounters = Param.Bool( False, - "Choose whether to use 64-bit or " "32-bit PMEVCNTR_EL0 registers.", + "Choose whether to use 64-bit or 32-bit PMEVCNTR_EL0 registers.", ) diff --git a/src/arch/arm/pmu.cc b/src/arch/arm/pmu.cc index 89dc2c8412..efd641797f 100644 --- a/src/arch/arm/pmu.cc +++ b/src/arch/arm/pmu.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2014, 2017-2019, 2022 Arm Limited + * Copyright (c) 2011-2014, 2017-2019, 2022-2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -46,6 +46,7 @@ #include "dev/arm/base_gic.hh" #include "dev/arm/generic_timer.hh" #include "params/ArmPMU.hh" +#include "sim/sim_exit.hh" namespace gem5 { @@ -66,7 +67,8 @@ PMU::PMU(const ArmPMUParams &p) cycleCounterEventId(p.cycleEventId), swIncrementEvent(nullptr), reg_pmcr_conf(0), - interrupt(nullptr) + interrupt(nullptr), + exitOnPMUControl(p.exitOnPMUControl) { DPRINTF(PMUVerbose, "Initializing the PMU.\n"); @@ -412,6 +414,21 @@ PMU::setControlReg(PMCR_t val) if (reg_pmcr.d != val.d) clock_remainder = 0; + // Optionally exit the simulation on various PMU control events. + // Exit on enable/disable takes precedence over exit on reset. + if (exitOnPMUControl) { + if (!reg_pmcr.e && val.e) { + inform("Exiting simulation: PMU enable detected"); + exitSimLoop("performance counter enabled", 0); + } else if (reg_pmcr.e && !val.e) { + inform("Exiting simulation: PMU disable detected"); + exitSimLoop("performance counter disabled", 0); + } else if (val.p) { + inform("Exiting simulation: PMU reset detected"); + exitSimLoop("performance counter reset", 0); + } + } + reg_pmcr = val & reg_pmcr_wr_mask; updateAllCounters(); } diff --git a/src/arch/arm/pmu.hh b/src/arch/arm/pmu.hh index ec60c6b7f5..49990311c0 100644 --- a/src/arch/arm/pmu.hh +++ b/src/arch/arm/pmu.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2014, 2017-2018, 2022 Arm Limited + * Copyright (c) 2011-2014, 2017-2018, 2022-2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -632,6 +632,12 @@ class PMU : public SimObject, public ArmISA::BaseISADevice * List of event types supported by this PMU. */ std::map> eventMap; + + /** + * Exit simloop on PMU reset or disable + */ + const bool exitOnPMUControl; + }; } // namespace ArmISA diff --git a/src/python/gem5/simulate/exit_event.py b/src/python/gem5/simulate/exit_event.py index 605fb6e556..61462e47aa 100644 --- a/src/python/gem5/simulate/exit_event.py +++ b/src/python/gem5/simulate/exit_event.py @@ -49,6 +49,9 @@ class ExitEvent(Enum): ) SIMPOINT_BEGIN = "simpoint begins" MAX_INSTS = "number of instructions reached" + PERF_COUNTER_ENABLE = "performance counter enabled" + PERF_COUNTER_DISABLE = "performance counter disabled" + PERF_COUNTER_RESET = "performance counter reset" @classmethod def translate_exit_status(cls, exit_string: str) -> "ExitEvent": @@ -90,6 +93,12 @@ class ExitEvent(Enum): return ExitEvent.SIMPOINT_BEGIN elif exit_string == "a thread reached the max instruction count": return ExitEvent.MAX_INSTS + elif exit_string == "performance counter enabled": + return ExitEvent.PERF_COUNTER_ENABLE + elif exit_string == "performance counter disabled": + return ExitEvent.PERF_COUNTER_DISABLE + elif exit_string == "performance counter reset": + return ExitEvent.PERF_COUNTER_RESET elif exit_string.endswith("will terminate the simulation.\n"): # This is for the traffic generator exit event return ExitEvent.EXIT