pmu.hh (13581:b6dcd0183747) pmu.hh (13638:76cb1cecc057)
1/*
2 * Copyright (c) 2011-2014, 2017-2018 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
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Dam Sunwoo
38 * Matt Horsnell
39 * Andreas Sandberg
40 */
41#ifndef __ARCH_ARM_PMU_HH__
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 "arch/arm/system.hh"
51#include "base/cprintf.hh"
52#include "cpu/base.hh"
53#include "debug/PMUVerbose.hh"
54#include "sim/eventq.hh"
55#include "sim/sim_object.hh"
56#include "sim/system.hh"
57
58class ArmPMUParams;
59class Platform;
60class ThreadContext;
61class ArmInterruptPin;
62
63namespace ArmISA {
64
65
66/**
67 * Model of an ARM PMU version 3
68 *
69 * This class implements a subset of the ARM PMU v3 specification as
70 * described in the ARMv8 reference manual. It supports most of the
71 * features of the PMU, however the following features are known to be
72 * missing:
73 *
74 * <ul>
75 * <li>Event filtering (e.g., from different privilege levels).
76 * <li>Access controls (the PMU currently ignores the execution level).
77 * <li>The chain counter (event no. 0x1E) is unimplemented.
78 * </ul>
79 *
80 * The PMU itself does not implement any events, in merely provides an
81 * interface for the configuration scripts to hook up probes that
82 * drive events. Configuration scripts should call addEventProbe() to
83 * configure custom events or high-level methods to configure
84 * architected events. The Python implementation of addEventProbe()
85 * automatically delays event type registration until after
86 * instantiation.
87 *
88 * In order to support CPU switching and some combined counters (e.g.,
89 * memory references synthesized from loads and stores), the PMU
90 * allows multiple probes per event type. When creating a system that
91 * switches between CPU models that share the same PMU, PMU events for
92 * all of the CPU models can be registered with the PMU.
93 *
94 * @see The ARM Architecture Refererence Manual (DDI 0487A)
95 *
96 */
97class PMU : public SimObject, public ArmISA::BaseISADevice {
98 public:
99 PMU(const ArmPMUParams *p);
100 ~PMU();
101
102 void addEventProbe(unsigned int id, SimObject *obj, const char *name);
103 void addSoftwareIncrementEvent(unsigned int id);
104
105 void registerEvent(uint32_t id);
106
107 public: // SimObject and related interfaces
108 void serialize(CheckpointOut &cp) const override;
109 void unserialize(CheckpointIn &cp) override;
110
111 void drainResume() override;
112
113 void regProbeListeners() override;
114
115 public: // ISA Device interface
116 void setThreadContext(ThreadContext *tc) override;
117
118 /**
119 * Set a register within the PMU.
120 *
121 * @param misc_reg Register number (see miscregs.hh)
122 * @param val Value to store
123 */
124 void setMiscReg(int misc_reg, RegVal val) override;
125 /**
126 * Read a register within the PMU.
127 *
128 * @param misc_reg Register number (see miscregs.hh)
129 * @return Register value.
130 */
131 RegVal readMiscReg(int misc_reg) override;
132
133 protected: // PMU register types and constants
134 BitUnion32(PMCR_t)
135 // PMU Enable
136 Bitfield<0> e;
137 // Event counter reset
138 Bitfield<1> p;
139 // Cycle counter reset
140 Bitfield<2> c;
141 // Cycle counter divider enable
142 Bitfield<3> d;
143 // Export enable
144 Bitfield<4> x;
145 // Disable PMCCNTR when event counting is prohibited
146 Bitfield<5> dp;
147 // Long Cycle counter enable
148 Bitfield<6> lc;
149 // Number of event counters implemented
150 Bitfield<15, 11> n;
151 // Implementation ID
152 Bitfield<23, 16> idcode;
153 // Implementer code
154 Bitfield<31, 24> imp;
155 EndBitUnion(PMCR_t)
156
157 BitUnion32(PMSELR_t)
158 // Performance counter selector
159 Bitfield<4, 0> sel;
160 EndBitUnion(PMSELR_t)
161
162 BitUnion32(PMEVTYPER_t)
163 Bitfield<15, 0> evtCount;
164
165 // Secure EL3 filtering
166 Bitfield<26> m;
167 // Non-secure EL2 mode filtering
168 Bitfield<27> nsh;
169 // Non-secure EL0 mode filtering
170 Bitfield<28> nsu;
171 // Non-secure EL1 mode filtering
172 Bitfield<29> nsk;
173 // EL0 filtering
174 Bitfield<30> u;
175 // EL1 filtering
176 Bitfield<31> p;
177 EndBitUnion(PMEVTYPER_t)
178
179 /**
180 * Counter ID within the PMU.
181 *
182 * This value is typically used to index into various registers
183 * controlling interrupts and overflows. The value normally in the
184 * [0, 31] range, where 31 refers to the cycle counter.
185 */
186 typedef unsigned int CounterId;
187
188 /** Cycle Count Register Number */
189 static const CounterId PMCCNTR = 31;
190
191 /**
192 * Event type ID.
193 *
194 * See the PMU documentation for a list of architected IDs.
195 */
196 typedef unsigned int EventTypeId;
197
198 protected: /* High-level register and interrupt handling */
199 RegVal readMiscRegInt(int misc_reg);
200
201 /**
202 * PMCR write handling
203 *
204 * The PMCR register needs special handling since writing to it
205 * changes PMU-global state (e.g., resets all counters).
206 *
207 * @param val New PMCR value
208 */
209 void setControlReg(PMCR_t val);
210
211 /**
212 * Reset all event counters excluding the cycle counter to zero.
213 */
214 void resetEventCounts();
215
216 /**
217 * Deliver a PMU interrupt to the GIC
218 */
219 void raiseInterrupt();
220
221 /**
222 * Clear a PMU interrupt.
223 */
224 void clearInterrupt();
225
226 /**
227 * Get the value of a performance counter.
228 *
229 * This method returns the value of a general purpose performance
230 * counter or the fixed-function cycle counter. Non-existing
231 * counters are treated as constant '0'.
232 *
233 * @return Value of the performance counter, 0 if the counter does
234 * not exist.
235 */
236 uint64_t getCounterValue(CounterId id) const {
237 return isValidCounter(id) ? getCounter(id).getValue() : 0;
238 }
239
240 /**
241 * Set the value of a performance counter.
242 *
243 * This method sets the value of a general purpose performance
244 * counter or the fixed-function cycle counter. Writes to
245 * non-existing counters are ignored.
246 */
247 void setCounterValue(CounterId id, uint64_t val);
248
249 /**
250 * Get the type and filter settings of a counter (PMEVTYPER)
251 *
252 * This method implements a read from a PMEVTYPER register. It
253 * returns the type value and filter settings of a general purpose
254 * performance counter or the cycle counter. Non-existing counters
255 * are treated as constant '0'.
256 *
257 * @param id Counter ID within the PMU.
258 * @return Performance counter type ID.
259 */
260 PMEVTYPER_t getCounterTypeRegister(CounterId id) const;
261
262 /**
263 * Set the type and filter settings of a performance counter
264 * (PMEVTYPER)
265 *
266 * This method implements a write to a PMEVTYPER register. It sets
267 * the type value and filter settings of a general purpose
268 * performance counter or the cycle counter. Writes to
269 * non-existing counters are ignored. The method automatically
270 * updates the probes used by the counter if it is enabled.
271 *
272 * @param id Counter ID within the PMU.
273 * @param type Performance counter type and filter configuration..
274 */
275 void setCounterTypeRegister(CounterId id, PMEVTYPER_t type);
276
277 /**
278 * Used for writing the Overflow Flag Status Register (SET/CLR)
279 *
280 * This method implements a write to the PMOVSSET/PMOVSCLR registers.
281 * It is capturing change of state in the register bits so that
282 * the overflow interrupt can be raised/cleared as a side effect
283 * of the write.
284 *
285 * @param new_val New value of the Overflow Status Register
286 */
287 void setOverflowStatus(RegVal new_val);
288
289 protected: /* Probe handling and counter state */
290 struct CounterState;
291
292 /**
293 * Event definition base class
294 */
295 struct PMUEvent {
296
297 PMUEvent() {}
298
299 virtual ~PMUEvent() {}
300
301 /**
302 * attach this event to a given counter
303 *
304 * @param a pointer to the counter where to attach this event
305 */
306 void attachEvent(PMU::CounterState *user);
307
308 /**
309 * detach this event from a given counter
310 *
311 * @param a pointer to the counter where to detach this event from
312 */
313 void detachEvent(PMU::CounterState *user);
314
315 /**
316 * notify an event increment of val units, all the attached counters'
317 * value is incremented by val units.
318 *
319 * @param the quantity by which to increment the attached counter
320 * values
321 */
322 virtual void increment(const uint64_t val);
323
324 /**
325 * Enable the current event
326 */
327 virtual void enable() = 0;
328
329 /**
330 * Disable the current event
331 */
332 virtual void disable() = 0;
333
334 /**
335 * Method called immediately before a counter access in order for
336 * the associated event to update its state (if required)
337 */
338 virtual void updateAttachedCounters() {}
339
340 protected:
341
342 /** set of counters using this event **/
343 std::set<PMU::CounterState*> userCounters;
344 };
345
346 struct RegularEvent : public PMUEvent {
347 typedef std::pair<SimObject*, std::string> EventTypeEntry;
348
349 void addMicroarchitectureProbe(SimObject* object,
350 std::string name) {
351
352 panic_if(!object,"malformed probe-point"
353 " definition with name %s\n", name);
354
355 microArchitectureEventSet.emplace(object, name);
356 }
357
358 protected:
359 struct RegularProbe: public ProbeListenerArgBase<uint64_t>
360 {
361 RegularProbe(RegularEvent *parent, SimObject* obj,
362 std::string name)
363 : ProbeListenerArgBase(obj->getProbeManager(), name),
364 parentEvent(parent) {}
365
366 RegularProbe() = delete;
367
368 void notify(const uint64_t &val);
369
370 protected:
371 RegularEvent *parentEvent;
372 };
373
374 /** The set of events driving the event value **/
375 std::set<EventTypeEntry> microArchitectureEventSet;
376
377 /** Set of probe listeners tapping onto each of the input micro-arch
378 * events which compose this pmu event
379 */
380 std::vector<std::unique_ptr<RegularProbe>> attachedProbePointList;
381
382 void enable() override;
383
384 void disable() override;
385 };
386
387 class SWIncrementEvent : public PMUEvent
388 {
389 void enable() override {}
390 void disable() override {}
391
392 public:
393
394 /**
395 * write on the sw increment register inducing an increment of the
396 * counters with this event selected according to the bitfield written.
397 *
398 * @param the bitfield selecting the counters to increment.
399 */
400 void write(uint64_t val);
401 };
402
403 /**
404 * Obtain the event of a given id
405 *
406 * @param the id of the event to obtain
407 * @return a pointer to the event with id eventId
408 */
409 PMUEvent* getEvent(uint64_t eventId);
410
411 /** State of a counter within the PMU. **/
412 struct CounterState : public Serializable {
413 CounterState(PMU &pmuReference, uint64_t counter_id)
414 : eventId(0), filter(0), enabled(false),
415 overflow64(false), sourceEvent(nullptr),
416 counterId(counter_id), value(0), resetValue(false),
417 pmu(pmuReference) {}
418
419 void serialize(CheckpointOut &cp) const override;
420 void unserialize(CheckpointIn &cp) override;
421
422 /**
423 * Add an event count to the counter and check for overflow.
424 *
425 * @param delta Number of events to add to the counter.
426 * @return the quantity remaining until a counter overflow occurs.
427 */
428 uint64_t add(uint64_t delta);
429
430 bool isFiltered() const;
431
432 /**
433 * Detach the counter from its event
434 */
435 void detach();
436
437 /**
438 * Attach this counter to an event
439 *
440 * @param the event to attach the counter to
441 */
442 void attach(PMUEvent* event);
443
444 /**
445 * Obtain the counter id
446 *
447 * @return the pysical counter id
448 */
449 uint64_t getCounterId() const{
450 return counterId;
451 }
452
453 /**
454 * rReturn the counter value
455 *
456 * @return the counter value
457 */
458 uint64_t getValue() const;
459
460 /**
461 * overwrite the value of the counter
462 *
463 * @param the new counter value
464 */
465 void setValue(uint64_t val);
466
467 public: /* Serializable state */
468 /** Counter event ID */
469 EventTypeId eventId;
470
471 /** Filtering settings (evtCount is unused) */
472 PMEVTYPER_t filter;
473
474 /** Is the counter enabled? */
475 bool enabled;
476
477 /** Is this a 64-bit counter? */
478 bool overflow64;
479
480 protected: /* Configuration */
481 /** PmuEvent currently in use (if any) **/
482 PMUEvent *sourceEvent;
483
484 /** id of the counter instance **/
485 uint64_t counterId;
486
487 /** Current value of the counter */
488 uint64_t value;
489
490 /** Flag keeping track if the counter has been reset **/
491 bool resetValue;
492
493 PMU &pmu;
494
495 template <typename ...Args>
496 void debugCounter(const char* mainString, Args &...args) const {
497
498 std::string userString = csprintf(mainString, args...);
499
500 warn("[counterId = %d, eventId = %d, sourceEvent = 0x%x] %s",
501 counterId, eventId, sourceEvent, userString.c_str());
502
503 }
504 };
505
506 /**
507 * Is this a valid counter ID?
508 *
509 * @param id ID of counter within the PMU.
510 *
511 * @return true if counter is within the allowed range or the
512 * cycle counter, false otherwise.
513 */
514 bool isValidCounter(CounterId id) const {
515 return id < counters.size() || id == PMCCNTR;
516 }
517
518 /**
519 * Return the state of a counter.
520 *
521 * @param id ID of counter within the PMU.
522 * @return Reference to a CounterState instance representing the
523 * counter.
524 */
525 CounterState &getCounter(CounterId id) {
526 assert(isValidCounter(id));
527 return id == PMCCNTR ? cycleCounter : counters[id];
528 }
529
530 /**
531 * Return the state of a counter.
532 *
533 * @param id ID of counter within the PMU.
534 * @return Reference to a CounterState instance representing the
535 * counter.
536 */
537 const CounterState &getCounter(CounterId id) const {
538 assert(isValidCounter(id));
539 return id == PMCCNTR ? cycleCounter : counters[id];
540 }
541
542 /**
543 * Depending on counter configuration, add or remove the probes
544 * driving the counter.
545 *
546 * Look at the state of a counter and (re-)attach the probes
547 * needed to drive a counter if it is currently active. All probes
548 * for the counter are detached if the counter is inactive.
549 *
550 * @param id ID of counter within the PMU.
551 * @param ctr Reference to the counter's state
552 */
553 void updateCounter(CounterState &ctr);
554
555 /**
556 * Check if a counter's settings allow it to be counted.
557 *
558 * @param ctr Counter state instance representing this counter.
559 * @return false if the counter is active, true otherwise.
560 */
561 bool isFiltered(const CounterState &ctr) const;
562
563 /**
564 * Call updateCounter() for each counter in the PMU if the
565 * counter's state has changed..
566 *
567 * @see updateCounter()
568 */
569 void updateAllCounters();
570
571 protected: /* State that needs to be serialized */
572 /** Performance Monitor Count Enable Register */
573 RegVal reg_pmcnten;
574
575 /** Performance Monitor Control Register */
576 PMCR_t reg_pmcr;
577
578 /** Performance Monitor Selection Register */
579 PMSELR_t reg_pmselr;
580
581 /** Performance Monitor Interrupt Enable Register */
582 RegVal reg_pminten;
583
584 /** Performance Monitor Overflow Status Register */
585 RegVal reg_pmovsr;
586
587 /**
588 * Performance counter ID register
589 *
590 * These registers contain a bitmask of available architected
591 * counters.
592 */
593 uint64_t reg_pmceid0;
594 uint64_t reg_pmceid1;
595
596 /** Remainder part when the clock counter is divided by 64 */
597 unsigned clock_remainder;
598
599 /** The number of regular event counters **/
600 uint64_t maximumCounterCount;
601
602 /** State of all general-purpose counters supported by PMU */
603 std::vector<CounterState> counters;
604
605 /** State of the cycle counter */
606 CounterState cycleCounter;
607
608 /** The id of the counter hardwired to the cpu cycle counter **/
609 const uint64_t cycleCounterEventId;
610
611 /** The event that implements the software increment **/
612 SWIncrementEvent *swIncrementEvent;
613
614 protected: /* Configuration and constants */
615 /** Constant (configuration-dependent) part of the PMCR */
616 PMCR_t reg_pmcr_conf;
617
618 /** PMCR write mask when accessed from the guest */
619 static const RegVal reg_pmcr_wr_mask;
620
621 /** Performance monitor interrupt number */
1/*
2 * Copyright (c) 2011-2014, 2017-2018 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
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Dam Sunwoo
38 * Matt Horsnell
39 * Andreas Sandberg
40 */
41#ifndef __ARCH_ARM_PMU_HH__
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 "arch/arm/system.hh"
51#include "base/cprintf.hh"
52#include "cpu/base.hh"
53#include "debug/PMUVerbose.hh"
54#include "sim/eventq.hh"
55#include "sim/sim_object.hh"
56#include "sim/system.hh"
57
58class ArmPMUParams;
59class Platform;
60class ThreadContext;
61class ArmInterruptPin;
62
63namespace ArmISA {
64
65
66/**
67 * Model of an ARM PMU version 3
68 *
69 * This class implements a subset of the ARM PMU v3 specification as
70 * described in the ARMv8 reference manual. It supports most of the
71 * features of the PMU, however the following features are known to be
72 * missing:
73 *
74 * <ul>
75 * <li>Event filtering (e.g., from different privilege levels).
76 * <li>Access controls (the PMU currently ignores the execution level).
77 * <li>The chain counter (event no. 0x1E) is unimplemented.
78 * </ul>
79 *
80 * The PMU itself does not implement any events, in merely provides an
81 * interface for the configuration scripts to hook up probes that
82 * drive events. Configuration scripts should call addEventProbe() to
83 * configure custom events or high-level methods to configure
84 * architected events. The Python implementation of addEventProbe()
85 * automatically delays event type registration until after
86 * instantiation.
87 *
88 * In order to support CPU switching and some combined counters (e.g.,
89 * memory references synthesized from loads and stores), the PMU
90 * allows multiple probes per event type. When creating a system that
91 * switches between CPU models that share the same PMU, PMU events for
92 * all of the CPU models can be registered with the PMU.
93 *
94 * @see The ARM Architecture Refererence Manual (DDI 0487A)
95 *
96 */
97class PMU : public SimObject, public ArmISA::BaseISADevice {
98 public:
99 PMU(const ArmPMUParams *p);
100 ~PMU();
101
102 void addEventProbe(unsigned int id, SimObject *obj, const char *name);
103 void addSoftwareIncrementEvent(unsigned int id);
104
105 void registerEvent(uint32_t id);
106
107 public: // SimObject and related interfaces
108 void serialize(CheckpointOut &cp) const override;
109 void unserialize(CheckpointIn &cp) override;
110
111 void drainResume() override;
112
113 void regProbeListeners() override;
114
115 public: // ISA Device interface
116 void setThreadContext(ThreadContext *tc) override;
117
118 /**
119 * Set a register within the PMU.
120 *
121 * @param misc_reg Register number (see miscregs.hh)
122 * @param val Value to store
123 */
124 void setMiscReg(int misc_reg, RegVal val) override;
125 /**
126 * Read a register within the PMU.
127 *
128 * @param misc_reg Register number (see miscregs.hh)
129 * @return Register value.
130 */
131 RegVal readMiscReg(int misc_reg) override;
132
133 protected: // PMU register types and constants
134 BitUnion32(PMCR_t)
135 // PMU Enable
136 Bitfield<0> e;
137 // Event counter reset
138 Bitfield<1> p;
139 // Cycle counter reset
140 Bitfield<2> c;
141 // Cycle counter divider enable
142 Bitfield<3> d;
143 // Export enable
144 Bitfield<4> x;
145 // Disable PMCCNTR when event counting is prohibited
146 Bitfield<5> dp;
147 // Long Cycle counter enable
148 Bitfield<6> lc;
149 // Number of event counters implemented
150 Bitfield<15, 11> n;
151 // Implementation ID
152 Bitfield<23, 16> idcode;
153 // Implementer code
154 Bitfield<31, 24> imp;
155 EndBitUnion(PMCR_t)
156
157 BitUnion32(PMSELR_t)
158 // Performance counter selector
159 Bitfield<4, 0> sel;
160 EndBitUnion(PMSELR_t)
161
162 BitUnion32(PMEVTYPER_t)
163 Bitfield<15, 0> evtCount;
164
165 // Secure EL3 filtering
166 Bitfield<26> m;
167 // Non-secure EL2 mode filtering
168 Bitfield<27> nsh;
169 // Non-secure EL0 mode filtering
170 Bitfield<28> nsu;
171 // Non-secure EL1 mode filtering
172 Bitfield<29> nsk;
173 // EL0 filtering
174 Bitfield<30> u;
175 // EL1 filtering
176 Bitfield<31> p;
177 EndBitUnion(PMEVTYPER_t)
178
179 /**
180 * Counter ID within the PMU.
181 *
182 * This value is typically used to index into various registers
183 * controlling interrupts and overflows. The value normally in the
184 * [0, 31] range, where 31 refers to the cycle counter.
185 */
186 typedef unsigned int CounterId;
187
188 /** Cycle Count Register Number */
189 static const CounterId PMCCNTR = 31;
190
191 /**
192 * Event type ID.
193 *
194 * See the PMU documentation for a list of architected IDs.
195 */
196 typedef unsigned int EventTypeId;
197
198 protected: /* High-level register and interrupt handling */
199 RegVal readMiscRegInt(int misc_reg);
200
201 /**
202 * PMCR write handling
203 *
204 * The PMCR register needs special handling since writing to it
205 * changes PMU-global state (e.g., resets all counters).
206 *
207 * @param val New PMCR value
208 */
209 void setControlReg(PMCR_t val);
210
211 /**
212 * Reset all event counters excluding the cycle counter to zero.
213 */
214 void resetEventCounts();
215
216 /**
217 * Deliver a PMU interrupt to the GIC
218 */
219 void raiseInterrupt();
220
221 /**
222 * Clear a PMU interrupt.
223 */
224 void clearInterrupt();
225
226 /**
227 * Get the value of a performance counter.
228 *
229 * This method returns the value of a general purpose performance
230 * counter or the fixed-function cycle counter. Non-existing
231 * counters are treated as constant '0'.
232 *
233 * @return Value of the performance counter, 0 if the counter does
234 * not exist.
235 */
236 uint64_t getCounterValue(CounterId id) const {
237 return isValidCounter(id) ? getCounter(id).getValue() : 0;
238 }
239
240 /**
241 * Set the value of a performance counter.
242 *
243 * This method sets the value of a general purpose performance
244 * counter or the fixed-function cycle counter. Writes to
245 * non-existing counters are ignored.
246 */
247 void setCounterValue(CounterId id, uint64_t val);
248
249 /**
250 * Get the type and filter settings of a counter (PMEVTYPER)
251 *
252 * This method implements a read from a PMEVTYPER register. It
253 * returns the type value and filter settings of a general purpose
254 * performance counter or the cycle counter. Non-existing counters
255 * are treated as constant '0'.
256 *
257 * @param id Counter ID within the PMU.
258 * @return Performance counter type ID.
259 */
260 PMEVTYPER_t getCounterTypeRegister(CounterId id) const;
261
262 /**
263 * Set the type and filter settings of a performance counter
264 * (PMEVTYPER)
265 *
266 * This method implements a write to a PMEVTYPER register. It sets
267 * the type value and filter settings of a general purpose
268 * performance counter or the cycle counter. Writes to
269 * non-existing counters are ignored. The method automatically
270 * updates the probes used by the counter if it is enabled.
271 *
272 * @param id Counter ID within the PMU.
273 * @param type Performance counter type and filter configuration..
274 */
275 void setCounterTypeRegister(CounterId id, PMEVTYPER_t type);
276
277 /**
278 * Used for writing the Overflow Flag Status Register (SET/CLR)
279 *
280 * This method implements a write to the PMOVSSET/PMOVSCLR registers.
281 * It is capturing change of state in the register bits so that
282 * the overflow interrupt can be raised/cleared as a side effect
283 * of the write.
284 *
285 * @param new_val New value of the Overflow Status Register
286 */
287 void setOverflowStatus(RegVal new_val);
288
289 protected: /* Probe handling and counter state */
290 struct CounterState;
291
292 /**
293 * Event definition base class
294 */
295 struct PMUEvent {
296
297 PMUEvent() {}
298
299 virtual ~PMUEvent() {}
300
301 /**
302 * attach this event to a given counter
303 *
304 * @param a pointer to the counter where to attach this event
305 */
306 void attachEvent(PMU::CounterState *user);
307
308 /**
309 * detach this event from a given counter
310 *
311 * @param a pointer to the counter where to detach this event from
312 */
313 void detachEvent(PMU::CounterState *user);
314
315 /**
316 * notify an event increment of val units, all the attached counters'
317 * value is incremented by val units.
318 *
319 * @param the quantity by which to increment the attached counter
320 * values
321 */
322 virtual void increment(const uint64_t val);
323
324 /**
325 * Enable the current event
326 */
327 virtual void enable() = 0;
328
329 /**
330 * Disable the current event
331 */
332 virtual void disable() = 0;
333
334 /**
335 * Method called immediately before a counter access in order for
336 * the associated event to update its state (if required)
337 */
338 virtual void updateAttachedCounters() {}
339
340 protected:
341
342 /** set of counters using this event **/
343 std::set<PMU::CounterState*> userCounters;
344 };
345
346 struct RegularEvent : public PMUEvent {
347 typedef std::pair<SimObject*, std::string> EventTypeEntry;
348
349 void addMicroarchitectureProbe(SimObject* object,
350 std::string name) {
351
352 panic_if(!object,"malformed probe-point"
353 " definition with name %s\n", name);
354
355 microArchitectureEventSet.emplace(object, name);
356 }
357
358 protected:
359 struct RegularProbe: public ProbeListenerArgBase<uint64_t>
360 {
361 RegularProbe(RegularEvent *parent, SimObject* obj,
362 std::string name)
363 : ProbeListenerArgBase(obj->getProbeManager(), name),
364 parentEvent(parent) {}
365
366 RegularProbe() = delete;
367
368 void notify(const uint64_t &val);
369
370 protected:
371 RegularEvent *parentEvent;
372 };
373
374 /** The set of events driving the event value **/
375 std::set<EventTypeEntry> microArchitectureEventSet;
376
377 /** Set of probe listeners tapping onto each of the input micro-arch
378 * events which compose this pmu event
379 */
380 std::vector<std::unique_ptr<RegularProbe>> attachedProbePointList;
381
382 void enable() override;
383
384 void disable() override;
385 };
386
387 class SWIncrementEvent : public PMUEvent
388 {
389 void enable() override {}
390 void disable() override {}
391
392 public:
393
394 /**
395 * write on the sw increment register inducing an increment of the
396 * counters with this event selected according to the bitfield written.
397 *
398 * @param the bitfield selecting the counters to increment.
399 */
400 void write(uint64_t val);
401 };
402
403 /**
404 * Obtain the event of a given id
405 *
406 * @param the id of the event to obtain
407 * @return a pointer to the event with id eventId
408 */
409 PMUEvent* getEvent(uint64_t eventId);
410
411 /** State of a counter within the PMU. **/
412 struct CounterState : public Serializable {
413 CounterState(PMU &pmuReference, uint64_t counter_id)
414 : eventId(0), filter(0), enabled(false),
415 overflow64(false), sourceEvent(nullptr),
416 counterId(counter_id), value(0), resetValue(false),
417 pmu(pmuReference) {}
418
419 void serialize(CheckpointOut &cp) const override;
420 void unserialize(CheckpointIn &cp) override;
421
422 /**
423 * Add an event count to the counter and check for overflow.
424 *
425 * @param delta Number of events to add to the counter.
426 * @return the quantity remaining until a counter overflow occurs.
427 */
428 uint64_t add(uint64_t delta);
429
430 bool isFiltered() const;
431
432 /**
433 * Detach the counter from its event
434 */
435 void detach();
436
437 /**
438 * Attach this counter to an event
439 *
440 * @param the event to attach the counter to
441 */
442 void attach(PMUEvent* event);
443
444 /**
445 * Obtain the counter id
446 *
447 * @return the pysical counter id
448 */
449 uint64_t getCounterId() const{
450 return counterId;
451 }
452
453 /**
454 * rReturn the counter value
455 *
456 * @return the counter value
457 */
458 uint64_t getValue() const;
459
460 /**
461 * overwrite the value of the counter
462 *
463 * @param the new counter value
464 */
465 void setValue(uint64_t val);
466
467 public: /* Serializable state */
468 /** Counter event ID */
469 EventTypeId eventId;
470
471 /** Filtering settings (evtCount is unused) */
472 PMEVTYPER_t filter;
473
474 /** Is the counter enabled? */
475 bool enabled;
476
477 /** Is this a 64-bit counter? */
478 bool overflow64;
479
480 protected: /* Configuration */
481 /** PmuEvent currently in use (if any) **/
482 PMUEvent *sourceEvent;
483
484 /** id of the counter instance **/
485 uint64_t counterId;
486
487 /** Current value of the counter */
488 uint64_t value;
489
490 /** Flag keeping track if the counter has been reset **/
491 bool resetValue;
492
493 PMU &pmu;
494
495 template <typename ...Args>
496 void debugCounter(const char* mainString, Args &...args) const {
497
498 std::string userString = csprintf(mainString, args...);
499
500 warn("[counterId = %d, eventId = %d, sourceEvent = 0x%x] %s",
501 counterId, eventId, sourceEvent, userString.c_str());
502
503 }
504 };
505
506 /**
507 * Is this a valid counter ID?
508 *
509 * @param id ID of counter within the PMU.
510 *
511 * @return true if counter is within the allowed range or the
512 * cycle counter, false otherwise.
513 */
514 bool isValidCounter(CounterId id) const {
515 return id < counters.size() || id == PMCCNTR;
516 }
517
518 /**
519 * Return the state of a counter.
520 *
521 * @param id ID of counter within the PMU.
522 * @return Reference to a CounterState instance representing the
523 * counter.
524 */
525 CounterState &getCounter(CounterId id) {
526 assert(isValidCounter(id));
527 return id == PMCCNTR ? cycleCounter : counters[id];
528 }
529
530 /**
531 * Return the state of a counter.
532 *
533 * @param id ID of counter within the PMU.
534 * @return Reference to a CounterState instance representing the
535 * counter.
536 */
537 const CounterState &getCounter(CounterId id) const {
538 assert(isValidCounter(id));
539 return id == PMCCNTR ? cycleCounter : counters[id];
540 }
541
542 /**
543 * Depending on counter configuration, add or remove the probes
544 * driving the counter.
545 *
546 * Look at the state of a counter and (re-)attach the probes
547 * needed to drive a counter if it is currently active. All probes
548 * for the counter are detached if the counter is inactive.
549 *
550 * @param id ID of counter within the PMU.
551 * @param ctr Reference to the counter's state
552 */
553 void updateCounter(CounterState &ctr);
554
555 /**
556 * Check if a counter's settings allow it to be counted.
557 *
558 * @param ctr Counter state instance representing this counter.
559 * @return false if the counter is active, true otherwise.
560 */
561 bool isFiltered(const CounterState &ctr) const;
562
563 /**
564 * Call updateCounter() for each counter in the PMU if the
565 * counter's state has changed..
566 *
567 * @see updateCounter()
568 */
569 void updateAllCounters();
570
571 protected: /* State that needs to be serialized */
572 /** Performance Monitor Count Enable Register */
573 RegVal reg_pmcnten;
574
575 /** Performance Monitor Control Register */
576 PMCR_t reg_pmcr;
577
578 /** Performance Monitor Selection Register */
579 PMSELR_t reg_pmselr;
580
581 /** Performance Monitor Interrupt Enable Register */
582 RegVal reg_pminten;
583
584 /** Performance Monitor Overflow Status Register */
585 RegVal reg_pmovsr;
586
587 /**
588 * Performance counter ID register
589 *
590 * These registers contain a bitmask of available architected
591 * counters.
592 */
593 uint64_t reg_pmceid0;
594 uint64_t reg_pmceid1;
595
596 /** Remainder part when the clock counter is divided by 64 */
597 unsigned clock_remainder;
598
599 /** The number of regular event counters **/
600 uint64_t maximumCounterCount;
601
602 /** State of all general-purpose counters supported by PMU */
603 std::vector<CounterState> counters;
604
605 /** State of the cycle counter */
606 CounterState cycleCounter;
607
608 /** The id of the counter hardwired to the cpu cycle counter **/
609 const uint64_t cycleCounterEventId;
610
611 /** The event that implements the software increment **/
612 SWIncrementEvent *swIncrementEvent;
613
614 protected: /* Configuration and constants */
615 /** Constant (configuration-dependent) part of the PMCR */
616 PMCR_t reg_pmcr_conf;
617
618 /** PMCR write mask when accessed from the guest */
619 static const RegVal reg_pmcr_wr_mask;
620
621 /** Performance monitor interrupt number */
622 ArmInterruptPin *const interrupt;
622 ArmInterruptPin *interrupt;
623
624 /**
625 * List of event types supported by this PMU.
626 */
627 std::map<EventTypeId, PMUEvent*> eventMap;
628};
629
630} // namespace ArmISA
631#endif
623
624 /**
625 * List of event types supported by this PMU.
626 */
627 std::map<EventTypeId, PMUEvent*> eventMap;
628};
629
630} // namespace ArmISA
631#endif