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 |