pmu.hh (12117:f50d7e4998e9) pmu.hh (12286:fb69c03c88e1)
1/*
2 * Copyright (c) 2011-2014, 2017 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software

--- 33 unchanged lines hidden (view full) ---

42#define __ARCH_ARM_PMU_HH__
43
44#include <map>
45#include <memory>
46#include <vector>
47
48#include "arch/arm/isa_device.hh"
49#include "arch/arm/registers.hh"
1/*
2 * Copyright (c) 2011-2014, 2017 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software

--- 33 unchanged lines hidden (view full) ---

42#define __ARCH_ARM_PMU_HH__
43
44#include <map>
45#include <memory>
46#include <vector>
47
48#include "arch/arm/isa_device.hh"
49#include "arch/arm/registers.hh"
50#include "sim/probe/probe.hh"
50#include "arch/arm/system.hh"
51#include "base/cprintf.hh"
52#include "cpu/base.hh"
53#include "debug/PMUVerbose.hh"
54#include "sim/eventq.hh"
51#include "sim/sim_object.hh"
55#include "sim/sim_object.hh"
56#include "sim/system.hh"
52
53class ArmPMUParams;
54class Platform;
55class ThreadContext;
56
57namespace ArmISA {
58
59

--- 29 unchanged lines hidden (view full) ---

89 *
90 */
91class PMU : public SimObject, public ArmISA::BaseISADevice {
92 public:
93 PMU(const ArmPMUParams *p);
94 ~PMU();
95
96 void addEventProbe(unsigned int id, SimObject *obj, const char *name);
57
58class ArmPMUParams;
59class Platform;
60class ThreadContext;
61
62namespace ArmISA {
63
64

--- 29 unchanged lines hidden (view full) ---

94 *
95 */
96class PMU : public SimObject, public ArmISA::BaseISADevice {
97 public:
98 PMU(const ArmPMUParams *p);
99 ~PMU();
100
101 void addEventProbe(unsigned int id, SimObject *obj, const char *name);
102 void addSoftwareIncrementEvent(unsigned int id);
97
103
104 void registerEvent(uint32_t id);
105
98 public: // SimObject and related interfaces
99 void serialize(CheckpointOut &cp) const override;
100 void unserialize(CheckpointIn &cp) override;
101
102 void drainResume() override;
103
106 public: // SimObject and related interfaces
107 void serialize(CheckpointOut &cp) const override;
108 void unserialize(CheckpointIn &cp) override;
109
110 void drainResume() override;
111
112 void regProbeListeners() override;
104
105 public: // ISA Device interface
106 /**
107 * Set a register within the PMU.
108 *
109 * @param misc_reg Register number (see miscregs.hh)
110 * @param val Value to store
111 */

--- 66 unchanged lines hidden (view full) ---

178
179 /**
180 * Event type ID.
181 *
182 * See the PMU documentation for a list of architected IDs.
183 */
184 typedef unsigned int EventTypeId;
185
113
114 public: // ISA Device interface
115 /**
116 * Set a register within the PMU.
117 *
118 * @param misc_reg Register number (see miscregs.hh)
119 * @param val Value to store
120 */

--- 66 unchanged lines hidden (view full) ---

187
188 /**
189 * Event type ID.
190 *
191 * See the PMU documentation for a list of architected IDs.
192 */
193 typedef unsigned int EventTypeId;
194
186 /** ID of the software increment event */
187 static const EventTypeId ARCH_EVENT_SW_INCR = 0x00;
188
189 protected: /* High-level register and interrupt handling */
190 MiscReg readMiscRegInt(int misc_reg);
191
192 /**
193 * PMCR write handling
194 *
195 * The PMCR register needs special handling since writing to it
196 * changes PMU-global state (e.g., resets all counters).

--- 18 unchanged lines hidden (view full) ---

215 * This method returns the value of a general purpose performance
216 * counter or the fixed-function cycle counter. Non-existing
217 * counters are treated as constant '0'.
218 *
219 * @return Value of the performance counter, 0 if the counter does
220 * not exist.
221 */
222 uint64_t getCounterValue(CounterId id) const {
195 protected: /* High-level register and interrupt handling */
196 MiscReg readMiscRegInt(int misc_reg);
197
198 /**
199 * PMCR write handling
200 *
201 * The PMCR register needs special handling since writing to it
202 * changes PMU-global state (e.g., resets all counters).

--- 18 unchanged lines hidden (view full) ---

221 * This method returns the value of a general purpose performance
222 * counter or the fixed-function cycle counter. Non-existing
223 * counters are treated as constant '0'.
224 *
225 * @return Value of the performance counter, 0 if the counter does
226 * not exist.
227 */
228 uint64_t getCounterValue(CounterId id) const {
223 return isValidCounter(id) ? getCounter(id).value : 0;
229 return isValidCounter(id) ? getCounter(id).getValue() : 0;
224 }
225
226 /**
227 * Set the value of a performance counter.
228 *
229 * This method sets the value of a general purpose performance
230 * counter or the fixed-function cycle counter. Writes to
231 * non-existing counters are ignored.

--- 24 unchanged lines hidden (view full) ---

256 * updates the probes used by the counter if it is enabled.
257 *
258 * @param id Counter ID within the PMU.
259 * @param type Performance counter type and filter configuration..
260 */
261 void setCounterTypeRegister(CounterId id, PMEVTYPER_t type);
262
263 protected: /* Probe handling and counter state */
230 }
231
232 /**
233 * Set the value of a performance counter.
234 *
235 * This method sets the value of a general purpose performance
236 * counter or the fixed-function cycle counter. Writes to
237 * non-existing counters are ignored.

--- 24 unchanged lines hidden (view full) ---

262 * updates the probes used by the counter if it is enabled.
263 *
264 * @param id Counter ID within the PMU.
265 * @param type Performance counter type and filter configuration..
266 */
267 void setCounterTypeRegister(CounterId id, PMEVTYPER_t type);
268
269 protected: /* Probe handling and counter state */
264 class ProbeListener : public ProbeListenerArgBase<uint64_t>
265 {
266 public:
267 ProbeListener(PMU &_pmu, CounterId _id,
268 ProbeManager *pm, const std::string &name)
269 : ProbeListenerArgBase(pm, name),
270 pmu(_pmu), id(_id) {}
270 struct CounterState;
271
271
272 void notify(const uint64_t &val) override
273 {
274 pmu.handleEvent(id, val);
275 }
276
277 protected:
278 PMU &pmu;
279 const CounterId id;
280 };
281 typedef std::unique_ptr<ProbeListener> ProbeListenerUPtr;
282
283 /**
272 /**
284 * Event type configuration
285 *
286 * The main purpose of this class is to describe how a PMU event
287 * type is sampled. It is implemented as a probe factory that
288 * returns a probe attached to the object the event is mointoring.
273 * Event definition base class
289 */
274 */
290 struct EventType {
275 struct PMUEvent {
276
277 PMUEvent() {}
278
279 virtual ~PMUEvent() {}
280
291 /**
281 /**
292 * @param _obj Target SimObject
293 * @param _name Probe name
282 * attach this event to a given counter
283 *
284 * @param a pointer to the counter where to attach this event
294 */
285 */
295 EventType(SimObject *_obj, const std::string &_name)
296 : obj(_obj), name(_name) {}
286 void attachEvent(PMU::CounterState *user);
297
298 /**
287
288 /**
299 * Create and attach a probe used to drive this event.
289 * detach this event from a given counter
300 *
290 *
301 * @param pmu PMU owning the probe.
302 * @param CounterID counter ID within the PMU.
303 * @return Pointer to a probe listener.
291 * @param a pointer to the counter where to detach this event from
304 */
292 */
305 std::unique_ptr<ProbeListener> create(PMU &pmu, CounterId cid) const
306 {
307 std::unique_ptr<ProbeListener> ptr;
308 ptr.reset(new ProbeListener(pmu, cid,
309 obj->getProbeManager(), name));
310 return ptr;
311 }
293 void detachEvent(PMU::CounterState *user);
312
294
313 /** SimObject being measured by this probe */
314 SimObject *const obj;
315 /** Probe name within obj */
316 const std::string name;
295 /**
296 * notify an event increment of val units, all the attached counters'
297 * value is incremented by val units.
298 *
299 * @param the quantity by which to increment the attached counter
300 * values
301 */
302 virtual void increment(const uint64_t val);
317
303
318 private:
319 // Disable the default constructor
320 EventType();
304 /**
305 * Enable the current event
306 */
307 virtual void enable() = 0;
308
309 /**
310 * Disable the current event
311 */
312 virtual void disable() = 0;
313
314 /**
315 * Method called immediately before a counter access in order for
316 * the associated event to update its state (if required)
317 */
318 virtual void updateAttachedCounters() {}
319
320 protected:
321
322 /** set of counters using this event **/
323 std::set<PMU::CounterState*> userCounters;
321 };
322
324 };
325
323 /** State of a counter within the PMU. */
324 struct CounterState : public Serializable {
325 CounterState()
326 : eventId(0), filter(0), value(0), enabled(false),
327 overflow64(false) {
326 struct RegularEvent : public PMUEvent {
327 typedef std::pair<SimObject*, std::string> EventTypeEntry;
328
328
329 listeners.reserve(4);
329 void addMicroarchitectureProbe(SimObject* object,
330 std::string name) {
331
332 panic_if(!object,"malformed probe-point"
333 " definition with name %s\n", name);
334
335 microArchitectureEventSet.emplace(object, name);
330 }
331
336 }
337
338 protected:
339 struct RegularProbe: public ProbeListenerArgBase<uint64_t>
340 {
341 RegularProbe(RegularEvent *parent, SimObject* obj,
342 std::string name)
343 : ProbeListenerArgBase(obj->getProbeManager(), name),
344 parentEvent(parent) {}
345
346 RegularProbe() = delete;
347
348 void notify(const uint64_t &val);
349
350 protected:
351 RegularEvent *parentEvent;
352 };
353
354 /** The set of events driving the event value **/
355 std::set<EventTypeEntry> microArchitectureEventSet;
356
357 /** Set of probe listeners tapping onto each of the input micro-arch
358 * events which compose this pmu event
359 */
360 std::vector<std::unique_ptr<RegularProbe>> attachedProbePointList;
361
362 void enable() override;
363
364 void disable() override;
365 };
366
367 class SWIncrementEvent : public PMUEvent
368 {
369 void enable() override {}
370 void disable() override {}
371
372 public:
373
374 /**
375 * write on the sw increment register inducing an increment of the
376 * counters with this event selected according to the bitfield written.
377 *
378 * @param the bitfield selecting the counters to increment.
379 */
380 void write(uint64_t val);
381 };
382
383 /**
384 * Obtain the event of a given id
385 *
386 * @param the id of the event to obtain
387 * @return a pointer to the event with id eventId
388 */
389 PMUEvent* getEvent(uint64_t eventId);
390
391 /** State of a counter within the PMU. **/
392 struct CounterState : public Serializable {
393 CounterState(PMU &pmuReference, uint64_t counter_id)
394 : eventId(0), filter(0), enabled(false),
395 overflow64(false), sourceEvent(nullptr),
396 counterId(counter_id), value(0), resetValue(false),
397 pmu(pmuReference) {}
398
332 void serialize(CheckpointOut &cp) const override;
333 void unserialize(CheckpointIn &cp) override;
334
335 /**
336 * Add an event count to the counter and check for overflow.
337 *
338 * @param delta Number of events to add to the counter.
399 void serialize(CheckpointOut &cp) const override;
400 void unserialize(CheckpointIn &cp) override;
401
402 /**
403 * Add an event count to the counter and check for overflow.
404 *
405 * @param delta Number of events to add to the counter.
339 * @return true on overflow, false otherwise.
406 * @return the quantity remaining until a counter overflow occurs.
340 */
407 */
341 bool add(uint64_t delta);
408 uint64_t add(uint64_t delta);
342
409
410 bool isFiltered() const;
411
412 /**
413 * Detach the counter from its event
414 */
415 void detach();
416
417 /**
418 * Attach this counter to an event
419 *
420 * @param the event to attach the counter to
421 */
422 void attach(PMUEvent* event);
423
424 /**
425 * Obtain the counter id
426 *
427 * @return the pysical counter id
428 */
429 uint64_t getCounterId() const{
430 return counterId;
431 }
432
433 /**
434 * rReturn the counter value
435 *
436 * @return the counter value
437 */
438 uint64_t getValue() const;
439
440 /**
441 * overwrite the value of the counter
442 *
443 * @param the new counter value
444 */
445 void setValue(uint64_t val);
446
343 public: /* Serializable state */
344 /** Counter event ID */
345 EventTypeId eventId;
346
347 /** Filtering settings (evtCount is unused) */
348 PMEVTYPER_t filter;
349
447 public: /* Serializable state */
448 /** Counter event ID */
449 EventTypeId eventId;
450
451 /** Filtering settings (evtCount is unused) */
452 PMEVTYPER_t filter;
453
350 /** Current value of the counter */
351 uint64_t value;
352
353 /** Is the counter enabled? */
354 bool enabled;
355
356 /** Is this a 64-bit counter? */
357 bool overflow64;
358
454 /** Is the counter enabled? */
455 bool enabled;
456
457 /** Is this a 64-bit counter? */
458 bool overflow64;
459
359 public: /* Configuration */
360 /** Probe listeners driving this counter */
361 std::vector<ProbeListenerUPtr> listeners;
460 protected: /* Configuration */
461 /** PmuEvent currently in use (if any) **/
462 PMUEvent *sourceEvent;
463
464 /** id of the counter instance **/
465 uint64_t counterId;
466
467 /** Current value of the counter */
468 uint64_t value;
469
470 /** Flag keeping track if the counter has been reset **/
471 bool resetValue;
472
473 PMU &pmu;
474
475 template <typename ...Args>
476 void debugCounter(const char* mainString, Args &...args) const {
477
478 std::string userString = csprintf(mainString, args...);
479
480 warn("[counterId = %d, eventId = %d, sourceEvent = 0x%x] %s",
481 counterId, eventId, sourceEvent, userString.c_str());
482
483 }
362 };
363
364 /**
484 };
485
486 /**
365 * Handle an counting event triggered by a probe.
366 *
367 * This method is called by the ProbeListener class whenever an
368 * active probe is triggered. Ths method adds the event count from
369 * the probe to the affected counter, checks for overflows, and
370 * delivers an interrupt if needed.
371 *
372 * @param id Counter ID affected by the probe.
373 * @param delta Counter increment
374 */
375 void handleEvent(CounterId id, uint64_t delta);
376
377 /**
378 * Is this a valid counter ID?
379 *
380 * @param id ID of counter within the PMU.
381 *
382 * @return true if counter is within the allowed range or the
383 * cycle counter, false otherwise.
384 */
385 bool isValidCounter(CounterId id) const {

--- 7 unchanged lines hidden (view full) ---

393 * @return Reference to a CounterState instance representing the
394 * counter.
395 */
396 CounterState &getCounter(CounterId id) {
397 assert(isValidCounter(id));
398 return id == PMCCNTR ? cycleCounter : counters[id];
399 }
400
487 * Is this a valid counter ID?
488 *
489 * @param id ID of counter within the PMU.
490 *
491 * @return true if counter is within the allowed range or the
492 * cycle counter, false otherwise.
493 */
494 bool isValidCounter(CounterId id) const {

--- 7 unchanged lines hidden (view full) ---

502 * @return Reference to a CounterState instance representing the
503 * counter.
504 */
505 CounterState &getCounter(CounterId id) {
506 assert(isValidCounter(id));
507 return id == PMCCNTR ? cycleCounter : counters[id];
508 }
509
401
402 /**
403 * Return the state of a counter.
404 *
405 * @param id ID of counter within the PMU.
406 * @return Reference to a CounterState instance representing the
407 * counter.
408 */
409 const CounterState &getCounter(CounterId id) const {

--- 7 unchanged lines hidden (view full) ---

417 *
418 * Look at the state of a counter and (re-)attach the probes
419 * needed to drive a counter if it is currently active. All probes
420 * for the counter are detached if the counter is inactive.
421 *
422 * @param id ID of counter within the PMU.
423 * @param ctr Reference to the counter's state
424 */
510 /**
511 * Return the state of a counter.
512 *
513 * @param id ID of counter within the PMU.
514 * @return Reference to a CounterState instance representing the
515 * counter.
516 */
517 const CounterState &getCounter(CounterId id) const {

--- 7 unchanged lines hidden (view full) ---

525 *
526 * Look at the state of a counter and (re-)attach the probes
527 * needed to drive a counter if it is currently active. All probes
528 * for the counter are detached if the counter is inactive.
529 *
530 * @param id ID of counter within the PMU.
531 * @param ctr Reference to the counter's state
532 */
425 void updateCounter(CounterId id, CounterState &ctr);
533 void updateCounter(CounterState &ctr);
426
427 /**
428 * Check if a counter's settings allow it to be counted.
429 *
430 * @param ctr Counter state instance representing this counter.
431 * @return false if the counter is active, true otherwise.
432 */
433 bool isFiltered(const CounterState &ctr) const;

--- 29 unchanged lines hidden (view full) ---

463 * counters.
464 */
465 uint64_t reg_pmceid0;
466 uint64_t reg_pmceid1;
467
468 /** Remainder part when the clock counter is divided by 64 */
469 unsigned clock_remainder;
470
534
535 /**
536 * Check if a counter's settings allow it to be counted.
537 *
538 * @param ctr Counter state instance representing this counter.
539 * @return false if the counter is active, true otherwise.
540 */
541 bool isFiltered(const CounterState &ctr) const;

--- 29 unchanged lines hidden (view full) ---

571 * counters.
572 */
573 uint64_t reg_pmceid0;
574 uint64_t reg_pmceid1;
575
576 /** Remainder part when the clock counter is divided by 64 */
577 unsigned clock_remainder;
578
579 /** The number of regular event counters **/
580 uint64_t maximumCounterCount;
581
471 /** State of all general-purpose counters supported by PMU */
472 std::vector<CounterState> counters;
582 /** State of all general-purpose counters supported by PMU */
583 std::vector<CounterState> counters;
584
473 /** State of the cycle counter */
474 CounterState cycleCounter;
475
585 /** State of the cycle counter */
586 CounterState cycleCounter;
587
588 /** The id of the counter hardwired to the cpu cycle counter **/
589 const uint64_t cycleCounterEventId;
590
591 /** The event that implements the software increment **/
592 SWIncrementEvent *swIncrementEvent;
593
476 protected: /* Configuration and constants */
477 /** Constant (configuration-dependent) part of the PMCR */
478 PMCR_t reg_pmcr_conf;
594 protected: /* Configuration and constants */
595 /** Constant (configuration-dependent) part of the PMCR */
596 PMCR_t reg_pmcr_conf;
597
479 /** PMCR write mask when accessed from the guest */
480 static const MiscReg reg_pmcr_wr_mask;
481
482 /** Performance monitor interrupt number */
483 const unsigned int pmuInterrupt;
484 /** Platform this device belongs to */
485 Platform *const platform;
486
487 /**
598 /** PMCR write mask when accessed from the guest */
599 static const MiscReg reg_pmcr_wr_mask;
600
601 /** Performance monitor interrupt number */
602 const unsigned int pmuInterrupt;
603 /** Platform this device belongs to */
604 Platform *const platform;
605
606 /**
488 * Event types supported by this PMU.
489 *
490 * Each event type ID can map to multiple EventType structures,
491 * which enables the PMU to use multiple probes for a single
492 * event. This can be useful in the following cases:
493 * <ul>
494 * <li>Some events can are increment by multiple different probe
495 * points (e.g., the CPU memory access counter gets
496 * incremented for both loads and stores).
497 *
498 * <li>A system switching between multiple CPU models can
499 * register events for all models that will execute a thread
500 * and tehreby ensure that the PMU continues to work.
501 * </ul>
607 * List of event types supported by this PMU.
502 */
608 */
503 std::multimap<EventTypeId, EventType> pmuEventTypes;
609 std::map<EventTypeId, PMUEvent*> eventMap;
504};
505
506} // namespace ArmISA
507#endif
610};
611
612} // namespace ArmISA
613#endif