Go to the documentation of this file.
44 #include "debug/Checkpoint.hh"
45 #include "debug/PMUVerbose.hh"
48 #include "params/ArmPMU.hh"
56 reg_pmcnten(0), reg_pmcr(0),
57 reg_pmselr(0), reg_pminten(0), reg_pmovsr(0),
58 reg_pmceid0(0),reg_pmceid1(0),
60 maximumCounterCount(
p->eventCounters),
61 cycleCounter(*this, maximumCounterCount),
62 cycleCounterEventId(
p->cycleEventId),
63 swIncrementEvent(nullptr),
67 DPRINTF(PMUVerbose,
"Initializing the PMU.\n");
70 fatal(
"The PMU can only accept 31 counters, %d counters requested.\n",
74 warn_if(!
p->interrupt,
"ARM PMU: No interrupt specified, interrupt " \
75 "delivery disabled.\n");
95 auto pmu_params =
static_cast<const ArmPMUParams *
>(
params());
97 if (pmu_params->interrupt)
98 interrupt = pmu_params->interrupt->get(tc);
105 DPRINTF(PMUVerbose,
"PMU: Adding SW increment event with id '0x%x'\n",
id);
110 "Trying to add a software increment event with multiple"
111 "IDs. This is not supported.\n");
116 "been previously defined\n",
id);
127 DPRINTF(PMUVerbose,
"PMU: Adding Probe Driven event with id '0x%x'"
128 "as probe %s:%s\n",
id, obj->
name(), probe_name);
131 auto event_entry =
eventMap.find(
id);
132 if (event_entry ==
eventMap.end()) {
138 event =
dynamic_cast<RegularEvent*
>(event_entry->second);
140 fatal(
"Event with id %d is not probe driven\n",
id);
143 event->addMicroarchitectureProbe(obj, probe_name);
156 }
else if (
id > 0x20 &&
id < 0x40) {
158 }
else if (
id >= 0x4000 &&
id < 0x4020) {
159 reg_pmceid0 |= ((uint64_t)1) << (
id - 0x4000 + 32);
160 }
else if (
id >= 0x4020 &&
id < 0x4040) {
161 reg_pmceid1 |= ((uint64_t)1) << (
id - 0x4020 + 32);
191 DPRINTF(PMUVerbose,
"setMiscReg(%s, 0x%x)\n",
247 DPRINTF(PMUVerbose,
"Setting PMCCFILTR: 0x%x\n",
val);
254 DPRINTF(PMUVerbose,
"Setting counter type: "
255 "[PMSELR: 0x%x, PMSELER.sel: 0x%x, EVTYPER: 0x%x]\n",
293 warn(
"Not doing anything for write to miscreg %s\n",
301 DPRINTF(PMUVerbose,
"readMiscReg(%s): 0x%x\n",
391 warn(
"Not doing anything for read from miscreg %s\n",
399 DPRINTF(PMUVerbose,
"Set Control Reg 0x%08x.\n",
val);
402 DPRINTF(PMUVerbose,
"PMU reset all events to zero.\n");
407 DPRINTF(PMUVerbose,
"PMU reset cycle counter to zero.\n");
422 const bool global_enable(
reg_pmcr.e);
453 for (
auto& counter: userCounters) {
461 userCounters.erase(user);
463 if (userCounters.empty()) {
471 parentEvent->increment(
val);
477 for (
auto& subEvents: microArchitectureEventSet) {
478 attachedProbePointList.emplace_back(
479 new RegularProbe(
this, subEvents.first, subEvents.second));
486 attachedProbePointList.clear();
494 const PMEVTYPER_t filter(this->filter);
495 const SCR scr(pmu.isa->readMiscRegNoEffect(
MISCREG_SCR));
496 const CPSR cpsr(pmu.isa->readMiscRegNoEffect(
MISCREG_CPSR));
502 return secure ? filter.u : (filter.u != filter.nsu);
505 return secure ? filter.p : (filter.p != filter.nsk);
511 return filter.p != filter.m;
514 panic(
"Unexpected execution level in PMU::isFiltered.\n");
522 sourceEvent->detachEvent(
this);
523 sourceEvent =
nullptr;
525 debugCounter(
"detaching event not currently attached"
538 sourceEvent->attachEvent(
this);
545 sourceEvent->updateAttachedCounters();
547 debugCounter(
"attempted to get value from a counter without"
548 " an associated event\n");
560 sourceEvent->updateAttachedCounters();
562 debugCounter(
"attempted to set value from a counter without"
563 " an associated event\n");
571 DPRINTF(PMUVerbose,
"updateCounter(%i): Disabling counter\n",
576 DPRINTF(PMUVerbose,
"updateCounter(%i): Enable event id 0x%x\n",
580 if (sourceEvent ==
eventMap.end()) {
581 warn(
"Can't enable PMU counter of type '0x%x': "
582 "No such event type.\n", ctr.
eventId);
584 ctr.
attach(sourceEvent->second);
601 warn_once(
"Can't change counter value: Counter %i does not exist.\n",
627 DPRINTF(PMUVerbose,
"Set Event [%d] = 0x%08x\n",
id,
val);
629 warn_once(
"Can't change counter type: Counter %i does not exist.\n",
642 if (
id !=
PMCCNTR && old_event_id !=
val.evtCount) {
652 const bool int_new = new_val != 0;
655 if (int_old && !int_new) {
666 DPRINTF(PMUVerbose,
"Delivering PMU interrupt.\n");
669 warn_once(
"Dropping PMU interrupt as no interrupt has "
678 DPRINTF(PMUVerbose,
"Clearing PMU interrupt.\n");
681 warn_once(
"Dropping PMU interrupt as no interrupt has "
689 DPRINTF(Checkpoint,
"Serializing Arm PMU\n");
709 DPRINTF(Checkpoint,
"Unserializing Arm PMU\n");
737 auto entry =
eventMap.find(eventId);
740 warn(
"event %d does not exist\n", eventId);
743 return entry->second;
766 uint64_t value_until_overflow;
768 value_until_overflow = UINT64_MAX - value;
770 value_until_overflow = UINT32_MAX - (uint32_t)value;
774 return value_until_overflow;
783 if (delta > value_until_overflow) {
787 pmu.reg_pmovsr |= (1 << counterId);
791 if (pmu.reg_pminten & (1 << counterId)) {
792 pmu.raiseInterrupt();
794 return overflow64 ? UINT64_MAX : UINT32_MAX;
796 return value_until_overflow - delta + 1;
802 for (
auto& counter: userCounters) {
803 if (
val & (0x1 << counter->getCounterId())) {
812 ArmPMUParams::create()
#define fatal(...)
This implements a cprintf based fatal() function.
void registerEvent(uint32_t id)
void attach(PMUEvent *event)
Attach this counter to an event.
void unserializeSection(CheckpointIn &cp, const char *name)
Unserialize an a child object.
void regProbeListeners() override
Register probe listeners for this object.
uint64_t maximumCounterCount
The number of regular event counters.
uint64_t getValue() const
rReturn the counter value
#define UNSERIALIZE_SCALAR(scalar)
Base class for devices that use the MiscReg interfaces.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
PMU(const ArmPMUParams *p)
void addEventProbe(unsigned int id, SimObject *obj, const char *name)
uint64_t getCounterValue(CounterId id) const
Get the value of a performance counter.
CounterState & getCounter(CounterId id)
Return the state of a counter.
virtual void clear()=0
Clear a signalled interrupt.
static ExceptionLevel currEL(const ThreadContext *tc)
virtual void raise()=0
Signal an interrupt.
void addSoftwareIncrementEvent(unsigned int id)
void drainResume() override
Resume execution after a successful drain.
void write(uint64_t val)
write on the sw increment register inducing an increment of the counters with this event selected acc...
static bool inSecureState(SCR scr, CPSR cpsr)
void updateCounter(CounterState &ctr)
Depending on counter configuration, add or remove the probes driving the counter.
PMEVTYPER_t getCounterTypeRegister(CounterId id) const
Get the type and filter settings of a counter (PMEVTYPER)
State of a counter within the PMU.
virtual void updateAttachedCounters()
Method called immediately before a counter access in order for the associated event to update its sta...
RegVal reg_pmcnten
Performance Monitor Count Enable Register.
int unflattenMiscReg(int reg)
const char *const miscRegName[]
std::map< EventTypeId, PMUEvent * > eventMap
List of event types supported by this PMU.
void serializeSection(CheckpointOut &cp, const char *name) const
Serialize an object into a new section.
void resetEventCounts()
Reset all event counters excluding the cycle counter to zero.
unsigned clock_remainder
Remainder part when the clock counter is divided by 64.
void notify(const uint64_t &val)
virtual void increment(const uint64_t val)
notify an event increment of val units, all the attached counters' value is incremented by val units.
bool isFiltered(const CounterState &ctr) const
Check if a counter's settings allow it to be counted.
std::set< PMU::CounterState * > userCounters
set of counters using this event
EventTypeId eventId
Counter event ID.
uint64_t reg_pmceid0
Performance counter ID register.
void setMiscReg(int misc_reg, RegVal val) override
Set a register within the PMU.
void clearInterrupt()
Clear a PMU interrupt.
Model of an ARM PMU version 3.
ThreadContext is the external interface to all thread state for anything outside of the CPU.
bool isValidCounter(CounterId id) const
Is this a valid counter ID?
const uint64_t cycleCounterEventId
The id of the counter hardwired to the cpu cycle counter.
ProbePointArg< uint64_t > PMU
PMU probe point.
void serialize(CheckpointOut &cp) const override
Serialize an object.
CounterState cycleCounter
State of the cycle counter.
#define UNSERIALIZE_OPT_SCALAR(scalar)
uint64_t add(uint64_t delta)
Add an event count to the counter and check for overflow.
Event definition base class.
void disable() override
Disable the current event.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
virtual ContextID contextId() const =0
void updateAllCounters()
Call updateCounter() for each counter in the PMU if the counter's state has changed.
void setControlReg(PMCR_t val)
PMCR write handling.
unsigned int EventTypeId
Event type ID.
uint64_t getCounterId() const
Obtain the counter id.
void detach()
Detach the counter from its event.
void enable() override
Enable the current event.
const Params * params() const
RegVal readMiscRegInt(int misc_reg)
#define SERIALIZE_SCALAR(scalar)
std::vector< CounterState > counters
State of all general-purpose counters supported by PMU.
void setCounterValue(CounterId id, uint64_t val)
Set the value of a performance counter.
void setOverflowStatus(RegVal new_val)
Used for writing the Overflow Flag Status Register (SET/CLR)
void attachEvent(PMU::CounterState *user)
attach this event to a given counter
virtual const std::string name() const
#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...
PMUEvent * getEvent(uint64_t eventId)
Obtain the event of a given id.
void detachEvent(PMU::CounterState *user)
detach this event from a given counter
bool enabled
Is the counter enabled?
SWIncrementEvent * swIncrementEvent
The event that implements the software increment.
PMSELR_t reg_pmselr
Performance Monitor Selection Register.
void setValue(uint64_t val)
overwrite the value of the counter
PMCR_t reg_pmcr
Performance Monitor Control Register.
RegVal reg_pminten
Performance Monitor Interrupt Enable Register.
PMCR_t reg_pmcr_conf
Constant (configuration-dependent) part of the PMCR.
@ MISCREG_PMXEVTYPER_PMCCFILTR
void paramIn(CheckpointIn &cp, const string &name, ExtMachInst &machInst)
static const CounterId PMCCNTR
Cycle Count Register Number.
virtual void enable()=0
Enable the current event.
std::ostream CheckpointOut
void setThreadContext(ThreadContext *tc) override
ArmInterruptPin * interrupt
Performance monitor interrupt number.
RegVal readMiscReg(int misc_reg) override
Read a register within the PMU.
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
void raiseInterrupt()
Deliver a PMU interrupt to the GIC.
PMEVTYPER_t filter
Filtering settings (evtCount is unused)
RegVal reg_pmovsr
Performance Monitor Overflow Status Register.
std::string csprintf(const char *format, const Args &...args)
static const RegVal reg_pmcr_wr_mask
PMCR write mask when accessed from the guest.
void serialize(CheckpointOut &cp) const override
Serialize an object.
#define panic(...)
This implements a cprintf based panic() function.
void setCounterTypeRegister(CounterId id, PMEVTYPER_t type)
Set the type and filter settings of a performance counter (PMEVTYPER)
Abstract superclass for simulation objects.
Generated on Wed Sep 30 2020 14:02:01 for gem5 by doxygen 1.8.17