Go to the documentation of this file.
44 #include "debug/Checkpoint.hh"
45 #include "debug/PMUVerbose.hh"
48 #include "params/ArmPMU.hh"
60 use64bitCounters(
p.use64bitCounters),
61 reg_pmcnten(0), reg_pmcr(0),
62 reg_pmselr(0), reg_pminten(0), reg_pmovsr(0),
63 reg_pmceid0(0),reg_pmceid1(0),
65 maximumCounterCount(
p.eventCounters),
66 cycleCounter(*this, maximumCounterCount,
p.use64bitCounters),
67 cycleCounterEventId(
p.cycleEventId),
68 swIncrementEvent(nullptr),
71 exitOnPMUControl(
p.exitOnPMUControl),
72 exitOnPMUInterrupt(
p.exitOnPMUInterrupt)
74 DPRINTF(PMUVerbose,
"Initializing the PMU.\n");
77 fatal(
"The PMU can only accept 31 counters, %d counters requested.\n",
81 warn_if(!
p.interrupt,
"ARM PMU: No interrupt specified, interrupt " \
82 "delivery disabled.\n");
102 const auto &pmu_params =
static_cast<const ArmPMUParams &
>(
params());
104 if (pmu_params.interrupt)
105 interrupt = pmu_params.interrupt->get(tc);
112 DPRINTF(PMUVerbose,
"PMU: Adding SW increment event with id '0x%x'\n",
id);
117 "Trying to add a software increment event with multiple"
118 "IDs. This is not supported.\n");
123 "been previously defined\n",
id);
134 DPRINTF(PMUVerbose,
"PMU: Adding Probe Driven event with id '0x%x'"
135 "as probe %s:%s\n",
id, obj->
name(), probe_name);
137 std::shared_ptr<RegularEvent>
event;
138 auto event_entry =
eventMap.find(
id);
139 if (event_entry ==
eventMap.end()) {
140 event = std::make_shared<RegularEvent>();
143 event = std::dynamic_pointer_cast<RegularEvent>(event_entry->second);
144 fatal_if(!
event,
"Event with id %d is not probe driven\n",
id);
146 event->addMicroarchitectureProbe(obj, probe_name);
159 }
else if (
id > 0x20 &&
id < 0x40) {
161 }
else if (
id >= 0x4000 &&
id < 0x4020) {
162 reg_pmceid0 |= ((uint64_t)1) << (
id - 0x4000 + 32);
163 }
else if (
id >= 0x4020 &&
id < 0x4040) {
164 reg_pmceid1 |= ((uint64_t)1) << (
id - 0x4020 + 32);
194 DPRINTF(PMUVerbose,
"setMiscReg(%s, 0x%x)\n",
250 DPRINTF(PMUVerbose,
"Setting PMCCFILTR: 0x%x\n",
val);
257 DPRINTF(PMUVerbose,
"Setting counter type: "
258 "[PMSELR: 0x%x, PMSELER.sel: 0x%x, EVTYPER: 0x%x]\n",
296 warn(
"Not doing anything for write to miscreg %s\n",
304 DPRINTF(PMUVerbose,
"readMiscReg(%s): 0x%x\n",
394 warn(
"Not doing anything for read from miscreg %s\n",
402 DPRINTF(PMUVerbose,
"Set Control Reg 0x%08x.\n",
val);
405 DPRINTF(PMUVerbose,
"PMU reset all events to zero.\n");
410 DPRINTF(PMUVerbose,
"PMU reset cycle counter to zero.\n");
422 inform(
"Exiting simulation: PMU enable detected");
425 inform(
"Exiting simulation: PMU disable detected");
428 inform(
"Exiting simulation: PMU reset detected");
440 const bool global_enable(
reg_pmcr.e);
471 for (
auto& counter: userCounters) {
479 userCounters.erase(user);
481 if (userCounters.empty()) {
489 parentEvent->increment(
val);
495 for (
auto& subEvents: microArchitectureEventSet) {
496 attachedProbePointList.emplace_back(
497 new RegularProbe(
this, subEvents.first, subEvents.second));
504 attachedProbePointList.clear();
512 const PMEVTYPER_t filter(this->filter);
514 const bool secure(pmu.isa->inSecureState());
518 return secure ? filter.u : (filter.u != filter.nsu);
521 return secure ? filter.p : (filter.p != filter.nsk);
527 return filter.p != filter.m;
530 panic(
"Unexpected execution level in PMU::isFiltered.\n");
538 sourceEvent->detachEvent(
this);
539 sourceEvent =
nullptr;
541 debugCounter(
"detaching event not currently attached"
554 sourceEvent->attachEvent(
this);
561 sourceEvent->updateAttachedCounters();
563 debugCounter(
"attempted to get value from a counter without"
564 " an associated event\n");
576 sourceEvent->updateAttachedCounters();
578 debugCounter(
"attempted to set value from a counter without"
579 " an associated event\n");
587 DPRINTF(PMUVerbose,
"updateCounter(%i): Disabling counter\n",
592 DPRINTF(PMUVerbose,
"updateCounter(%i): Enable event id 0x%x\n",
596 if (sourceEvent ==
eventMap.end()) {
597 warn(
"Can't enable PMU counter of type '0x%x': "
598 "No such event type.\n", ctr.
eventId);
600 ctr.
attach(sourceEvent->second);
617 warn_once(
"Can't change counter value: Counter %i does not exist.\n",
643 DPRINTF(PMUVerbose,
"Set Event [%d] = 0x%08x\n",
id,
val);
645 warn_once(
"Can't change counter type: Counter %i does not exist.\n",
658 if (
id !=
PMCCNTR && old_event_id !=
val.evtCount) {
668 const bool int_new = new_val != 0;
671 if (int_old && !int_new) {
682 inform(
"Exiting simulation: PMU interrupt detected");
686 DPRINTF(PMUVerbose,
"Delivering PMU interrupt.\n");
689 warn_once(
"Dropping PMU interrupt as no interrupt has "
698 DPRINTF(PMUVerbose,
"Clearing PMU interrupt.\n");
701 warn_once(
"Dropping PMU interrupt as no interrupt has "
709 DPRINTF(Checkpoint,
"Serializing Arm PMU\n");
730 DPRINTF(Checkpoint,
"Unserializing Arm PMU\n");
756 std::shared_ptr<PMU::PMUEvent>
759 auto entry =
eventMap.find(eventId);
762 warn(
"event %d does not exist\n", eventId);
765 return entry->second;
788 uint64_t value_until_overflow;
790 value_until_overflow = UINT64_MAX - value;
792 value_until_overflow = UINT32_MAX - (uint32_t)value;
796 return value_until_overflow;
805 if (delta > value_until_overflow) {
809 pmu.reg_pmovsr |= (1 << counterId);
813 if (pmu.reg_pminten & (1 << counterId)) {
814 pmu.raiseInterrupt();
816 return overflow64 ? UINT64_MAX : UINT32_MAX;
818 return value_until_overflow - delta + 1;
824 for (
auto& counter: userCounters) {
825 if (
val & (0x1 << counter->getCounterId())) {
void addEventProbe(unsigned int id, SimObject *obj, const char *name)
#define fatal(...)
This implements a cprintf based fatal() function.
void serialize(CheckpointOut &cp) const override
Serialize an object.
virtual void enable()=0
Enable the current event.
void setCounterValue(CounterId id, uint64_t val)
Set the value of a performance counter.
void raiseInterrupt()
Deliver a PMU interrupt to the GIC.
void setMiscReg(int misc_reg, RegVal val) override
Set a register within the PMU.
uint64_t maximumCounterCount
The number of regular event counters.
void notify(const uint64_t &val)
State of a counter within the PMU.
#define UNSERIALIZE_SCALAR(scalar)
uint64_t getCounterId() const
Obtain the counter id.
CounterState cycleCounter
State of the cycle counter.
void detachEvent(PMU::CounterState *user)
detach this event from a given counter
void disable() override
Disable the current event.
bool exitOnPMUInterrupt
Exit simloop on PMU interrupt.
PMEVTYPER_t getCounterTypeRegister(CounterId id) const
Get the type and filter settings of a counter (PMEVTYPER)
void serializeSection(CheckpointOut &cp, const char *name) const
Serialize an object into a new section.
bool isFiltered(const CounterState &ctr) const
Check if a counter's settings allow it to be counted.
void updateCounter(CounterState &ctr)
Depending on counter configuration, add or remove the probes driving the counter.
std::shared_ptr< PMUEvent > getEvent(uint64_t eventId)
Obtain the event of a given id.
uint64_t reg_pmceid0
Performance counter ID register.
EventTypeId eventId
Counter event ID.
void setOverflowStatus(RegVal new_val)
Used for writing the Overflow Flag Status Register (SET/CLR)
const char *const miscRegName[]
virtual ContextID contextId() const =0
void setValue(uint64_t val)
overwrite the value of the counter
uint64_t add(uint64_t delta)
Add an event count to the counter and check for overflow.
std::string csprintf(const char *format, const Args &...args)
void attachEvent(PMU::CounterState *user)
attach this event to a given counter
uint64_t getValue() const
rReturn the counter value
void exitSimLoop(const std::string &message, int exit_code, Tick when, Tick repeat, bool serialize)
Schedule an event to exit the simulation loop (returning to Python) at the end of the current cycle (...
std::vector< CounterState > counters
State of all general-purpose counters supported by PMU.
void resetEventCounts()
Reset all event counters excluding the cycle counter to zero.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
static const CounterId PMCCNTR
Cycle Count Register Number.
CounterState & getCounter(CounterId id)
Return the state of a counter.
virtual void updateAttachedCounters()
Method called immediately before a counter access in order for the associated event to update its sta...
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual std::string name() const
void unserializeSection(CheckpointIn &cp, const char *name)
Unserialize an a child object.
const Params & params() const
std::shared_ptr< SWIncrementEvent > swIncrementEvent
The event that implements the software increment.
void clearInterrupt()
Clear a PMU interrupt.
bool enabled
Is the counter enabled?
PMEVTYPER_t filter
Filtering settings (evtCount is unused)
virtual void clear()=0
Clear a signalled interrupt.
PMCR_t reg_pmcr
Performance Monitor Control Register.
void drainResume() override
Resume execution after a successful drain.
@ MISCREG_PMXEVTYPER_PMCCFILTR
#define UNSERIALIZE_OPT_SCALAR(scalar)
void regProbeListeners() override
Register probe listeners for this object.
RegVal reg_pmovsr
Performance Monitor Overflow Status Register.
const uint64_t cycleCounterEventId
The id of the counter hardwired to the cpu cycle counter.
virtual void increment(const uint64_t val)
notify an event increment of val units, all the attached counters' value is incremented by val units.
PMSELR_t reg_pmselr
Performance Monitor Selection Register.
Abstract superclass for simulation objects.
bool isValidCounter(CounterId id) const
Is this a valid counter ID?
void detach()
Detach the counter from its event.
void setCounterTypeRegister(CounterId id, PMEVTYPER_t type)
Set the type and filter settings of a performance counter (PMEVTYPER)
RegVal reg_pmcnten
Performance Monitor Count Enable Register.
uint64_t getCounterValue(CounterId id) const
Get the value of a performance counter.
PMCR_t reg_pmcr_conf
Constant (configuration-dependent) part of the PMCR.
void updateAllCounters()
Call updateCounter() for each counter in the PMU if the counter's state has changed.
void write(uint64_t val)
write on the sw increment register inducing an increment of the counters with this event selected acc...
#define SERIALIZE_SCALAR(scalar)
#define warn_if(cond,...)
Conditional warning macro that checks the supplied condition and only prints a warning if the conditi...
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
const bool exitOnPMUControl
Exit simloop on PMU reset or disable.
void addSoftwareIncrementEvent(unsigned int id)
void enable() override
Enable the current event.
void serialize(CheckpointOut &cp) const override
Serialize an object.
unsigned clock_remainder
Remainder part when the clock counter is divided by 64.
void setControlReg(PMCR_t val)
PMCR write handling.
void paramIn(CheckpointIn &cp, const std::string &name, ExtMachInst &machInst)
void setThreadContext(ThreadContext *tc) override
static const RegVal reg_pmcr_wr_mask
PMCR write mask when accessed from the guest.
ArmInterruptPin * interrupt
Performance monitor interrupt number.
std::ostream CheckpointOut
virtual void raise()=0
Signal an interrupt.
std::set< PMU::CounterState * > userCounters
set of counters using this event
RegVal readMiscRegInt(int misc_reg)
unsigned int EventTypeId
Event type ID.
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
std::map< EventTypeId, std::shared_ptr< PMUEvent > > eventMap
List of event types supported by this PMU.
RegVal reg_pminten
Performance Monitor Interrupt Enable Register.
bool use64bitCounters
Determine whether to use 64-bit or 32-bit counters.
PMU(const ArmPMUParams &p)
void registerEvent(uint32_t id)
RegVal readMiscReg(int misc_reg) override
Read a register within the PMU.
int unflattenMiscReg(int reg)
#define panic(...)
This implements a cprintf based panic() function.
Base class for devices that use the MiscReg interfaces.
void attach(const std::shared_ptr< PMUEvent > &event)
Attach this counter to an event.
Generated on Sun Jul 30 2023 01:56:49 for gem5 by doxygen 1.8.17