pmu.hh revision 10905
110461SAndreas.Sandberg@ARM.com/* 210461SAndreas.Sandberg@ARM.com * Copyright (c) 2011-2014 ARM Limited 310461SAndreas.Sandberg@ARM.com * All rights reserved 410461SAndreas.Sandberg@ARM.com * 510461SAndreas.Sandberg@ARM.com * The license below extends only to copyright in the software and shall 610461SAndreas.Sandberg@ARM.com * not be construed as granting a license to any other intellectual 710461SAndreas.Sandberg@ARM.com * property including but not limited to intellectual property relating 810461SAndreas.Sandberg@ARM.com * to a hardware implementation of the functionality of the software 910461SAndreas.Sandberg@ARM.com * licensed hereunder. You may use the software subject to the license 1010461SAndreas.Sandberg@ARM.com * terms below provided that you ensure that this notice is replicated 1110461SAndreas.Sandberg@ARM.com * unmodified and in its entirety in all distributions of the software, 1210461SAndreas.Sandberg@ARM.com * modified or unmodified, in source code or in binary form. 1310461SAndreas.Sandberg@ARM.com * 1410461SAndreas.Sandberg@ARM.com * Redistribution and use in source and binary forms, with or without 1510461SAndreas.Sandberg@ARM.com * modification, are permitted provided that the following conditions are 1610461SAndreas.Sandberg@ARM.com * met: redistributions of source code must retain the above copyright 1710461SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer; 1810461SAndreas.Sandberg@ARM.com * redistributions in binary form must reproduce the above copyright 1910461SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer in the 2010461SAndreas.Sandberg@ARM.com * documentation and/or other materials provided with the distribution; 2110461SAndreas.Sandberg@ARM.com * neither the name of the copyright holders nor the names of its 2210461SAndreas.Sandberg@ARM.com * contributors may be used to endorse or promote products derived from 2310461SAndreas.Sandberg@ARM.com * this software without specific prior written permission. 2410461SAndreas.Sandberg@ARM.com * 2510461SAndreas.Sandberg@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2610461SAndreas.Sandberg@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2710461SAndreas.Sandberg@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2810461SAndreas.Sandberg@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2910461SAndreas.Sandberg@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3010461SAndreas.Sandberg@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3110461SAndreas.Sandberg@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3210461SAndreas.Sandberg@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3310461SAndreas.Sandberg@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3410461SAndreas.Sandberg@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3510461SAndreas.Sandberg@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3610461SAndreas.Sandberg@ARM.com * 3710461SAndreas.Sandberg@ARM.com * Authors: Dam Sunwoo 3810461SAndreas.Sandberg@ARM.com * Matt Horsnell 3910461SAndreas.Sandberg@ARM.com * Andreas Sandberg 4010461SAndreas.Sandberg@ARM.com */ 4110461SAndreas.Sandberg@ARM.com#ifndef __ARCH_ARM_PMU_HH__ 4210461SAndreas.Sandberg@ARM.com#define __ARCH_ARM_PMU_HH__ 4310461SAndreas.Sandberg@ARM.com 4410461SAndreas.Sandberg@ARM.com#include <map> 4510461SAndreas.Sandberg@ARM.com#include <memory> 4610461SAndreas.Sandberg@ARM.com#include <vector> 4710461SAndreas.Sandberg@ARM.com 4810461SAndreas.Sandberg@ARM.com#include "arch/arm/isa_device.hh" 4910461SAndreas.Sandberg@ARM.com#include "arch/arm/registers.hh" 5010461SAndreas.Sandberg@ARM.com#include "sim/probe/probe.hh" 5110461SAndreas.Sandberg@ARM.com#include "sim/sim_object.hh" 5210461SAndreas.Sandberg@ARM.com 5310461SAndreas.Sandberg@ARM.comclass ArmPMUParams; 5410461SAndreas.Sandberg@ARM.comclass Platform; 5510461SAndreas.Sandberg@ARM.comclass ThreadContext; 5610461SAndreas.Sandberg@ARM.com 5710461SAndreas.Sandberg@ARM.comnamespace ArmISA { 5810461SAndreas.Sandberg@ARM.com 5910461SAndreas.Sandberg@ARM.com 6010461SAndreas.Sandberg@ARM.com/** 6110461SAndreas.Sandberg@ARM.com * Model of an ARM PMU version 3 6210461SAndreas.Sandberg@ARM.com * 6310461SAndreas.Sandberg@ARM.com * This class implements a subset of the ARM PMU v3 specification as 6410461SAndreas.Sandberg@ARM.com * described in the ARMv8 reference manual. It supports most of the 6510461SAndreas.Sandberg@ARM.com * features of the PMU, however the following features are known to be 6610461SAndreas.Sandberg@ARM.com * missing: 6710461SAndreas.Sandberg@ARM.com * 6810461SAndreas.Sandberg@ARM.com * <ul> 6910461SAndreas.Sandberg@ARM.com * <li>Event filtering (e.g., from different privilege levels). 7010461SAndreas.Sandberg@ARM.com * <li>Access controls (the PMU currently ignores the execution level). 7110461SAndreas.Sandberg@ARM.com * <li>The chain counter (event no. 0x1E) is unimplemented. 7210461SAndreas.Sandberg@ARM.com * </ul> 7310461SAndreas.Sandberg@ARM.com * 7410461SAndreas.Sandberg@ARM.com * The PMU itself does not implement any events, in merely provides an 7510461SAndreas.Sandberg@ARM.com * interface for the configuration scripts to hook up probes that 7610461SAndreas.Sandberg@ARM.com * drive events. Configuration scripts should call addEventProbe() to 7710461SAndreas.Sandberg@ARM.com * configure custom events or high-level methods to configure 7810461SAndreas.Sandberg@ARM.com * architected events. The Python implementation of addEventProbe() 7910461SAndreas.Sandberg@ARM.com * automatically delays event type registration until after 8010461SAndreas.Sandberg@ARM.com * instantiation. 8110461SAndreas.Sandberg@ARM.com * 8210461SAndreas.Sandberg@ARM.com * In order to support CPU switching and some combined counters (e.g., 8310461SAndreas.Sandberg@ARM.com * memory references synthesized from loads and stores), the PMU 8410461SAndreas.Sandberg@ARM.com * allows multiple probes per event type. When creating a system that 8510461SAndreas.Sandberg@ARM.com * switches between CPU models that share the same PMU, PMU events for 8610461SAndreas.Sandberg@ARM.com * all of the CPU models can be registered with the PMU. 8710461SAndreas.Sandberg@ARM.com * 8810461SAndreas.Sandberg@ARM.com * @see The ARM Architecture Refererence Manual (DDI 0487A) 8910461SAndreas.Sandberg@ARM.com * 9010461SAndreas.Sandberg@ARM.com */ 9110461SAndreas.Sandberg@ARM.comclass PMU : public SimObject, public ArmISA::BaseISADevice { 9210461SAndreas.Sandberg@ARM.com public: 9310461SAndreas.Sandberg@ARM.com PMU(const ArmPMUParams *p); 9410461SAndreas.Sandberg@ARM.com ~PMU(); 9510461SAndreas.Sandberg@ARM.com 9610461SAndreas.Sandberg@ARM.com void addEventProbe(unsigned int id, SimObject *obj, const char *name); 9710461SAndreas.Sandberg@ARM.com 9810461SAndreas.Sandberg@ARM.com public: // SimObject and related interfaces 9910905Sandreas.sandberg@arm.com void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE; 10010905Sandreas.sandberg@arm.com void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE; 10110461SAndreas.Sandberg@ARM.com 10210461SAndreas.Sandberg@ARM.com void drainResume() M5_ATTR_OVERRIDE; 10310461SAndreas.Sandberg@ARM.com 10410461SAndreas.Sandberg@ARM.com 10510461SAndreas.Sandberg@ARM.com public: // ISA Device interface 10610461SAndreas.Sandberg@ARM.com /** 10710461SAndreas.Sandberg@ARM.com * Set a register within the PMU. 10810461SAndreas.Sandberg@ARM.com * 10910461SAndreas.Sandberg@ARM.com * @param misc_reg Register number (see miscregs.hh) 11010461SAndreas.Sandberg@ARM.com * @param val Value to store 11110461SAndreas.Sandberg@ARM.com */ 11210461SAndreas.Sandberg@ARM.com void setMiscReg(int misc_reg, MiscReg val) M5_ATTR_OVERRIDE; 11310461SAndreas.Sandberg@ARM.com /** 11410461SAndreas.Sandberg@ARM.com * Read a register within the PMU. 11510461SAndreas.Sandberg@ARM.com * 11610461SAndreas.Sandberg@ARM.com * @param misc_reg Register number (see miscregs.hh) 11710461SAndreas.Sandberg@ARM.com * @return Register value. 11810461SAndreas.Sandberg@ARM.com */ 11910461SAndreas.Sandberg@ARM.com MiscReg readMiscReg(int misc_reg) M5_ATTR_OVERRIDE; 12010461SAndreas.Sandberg@ARM.com 12110461SAndreas.Sandberg@ARM.com protected: // PMU register types and constants 12210461SAndreas.Sandberg@ARM.com BitUnion32(PMCR_t) 12310461SAndreas.Sandberg@ARM.com // PMU Enable 12410461SAndreas.Sandberg@ARM.com Bitfield<0> e; 12510461SAndreas.Sandberg@ARM.com // Event counter reset 12610461SAndreas.Sandberg@ARM.com Bitfield<1> p; 12710461SAndreas.Sandberg@ARM.com // Cycle counter reset 12810461SAndreas.Sandberg@ARM.com Bitfield<2> c; 12910461SAndreas.Sandberg@ARM.com // Cycle counter divider enable 13010461SAndreas.Sandberg@ARM.com Bitfield<3> d; 13110461SAndreas.Sandberg@ARM.com // Export enable 13210461SAndreas.Sandberg@ARM.com Bitfield<4> x; 13310461SAndreas.Sandberg@ARM.com // Disable PMCCNTR when event counting is prohibited 13410461SAndreas.Sandberg@ARM.com Bitfield<5> dp; 13510461SAndreas.Sandberg@ARM.com // Long Cycle counter enable 13610461SAndreas.Sandberg@ARM.com Bitfield<6> lc; 13710461SAndreas.Sandberg@ARM.com // Number of event counters implemented 13810461SAndreas.Sandberg@ARM.com Bitfield<15, 11> n; 13910461SAndreas.Sandberg@ARM.com // Implementation ID 14010461SAndreas.Sandberg@ARM.com Bitfield<23, 16> idcode; 14110461SAndreas.Sandberg@ARM.com // Implementer code 14210461SAndreas.Sandberg@ARM.com Bitfield<31, 24> imp; 14310461SAndreas.Sandberg@ARM.com EndBitUnion(PMCR_t) 14410461SAndreas.Sandberg@ARM.com 14510461SAndreas.Sandberg@ARM.com BitUnion32(PMSELR_t) 14610461SAndreas.Sandberg@ARM.com // Performance counter selector 14710461SAndreas.Sandberg@ARM.com Bitfield<4, 0> sel; 14810461SAndreas.Sandberg@ARM.com EndBitUnion(PMSELR_t) 14910461SAndreas.Sandberg@ARM.com 15010461SAndreas.Sandberg@ARM.com BitUnion32(PMEVTYPER_t) 15110461SAndreas.Sandberg@ARM.com Bitfield<9, 0> evtCount; 15210461SAndreas.Sandberg@ARM.com 15310461SAndreas.Sandberg@ARM.com // Secure EL3 filtering 15410461SAndreas.Sandberg@ARM.com Bitfield<26> m; 15510461SAndreas.Sandberg@ARM.com // Non-secure EL2 mode filtering 15610461SAndreas.Sandberg@ARM.com Bitfield<27> nsh; 15710461SAndreas.Sandberg@ARM.com // Non-secure EL0 mode filtering 15810461SAndreas.Sandberg@ARM.com Bitfield<28> nsu; 15910461SAndreas.Sandberg@ARM.com // Non-secure EL1 mode filtering 16010461SAndreas.Sandberg@ARM.com Bitfield<29> nsk; 16110461SAndreas.Sandberg@ARM.com // EL0 filtering 16210461SAndreas.Sandberg@ARM.com Bitfield<30> u; 16310461SAndreas.Sandberg@ARM.com // EL1 filtering 16410461SAndreas.Sandberg@ARM.com Bitfield<31> p; 16510461SAndreas.Sandberg@ARM.com EndBitUnion(PMEVTYPER_t) 16610461SAndreas.Sandberg@ARM.com 16710461SAndreas.Sandberg@ARM.com /** 16810461SAndreas.Sandberg@ARM.com * Counter ID within the PMU. 16910461SAndreas.Sandberg@ARM.com * 17010461SAndreas.Sandberg@ARM.com * This value is typically used to index into various registers 17110461SAndreas.Sandberg@ARM.com * controlling interrupts and overflows. The value normally in the 17210461SAndreas.Sandberg@ARM.com * [0, 31] range, where 31 refers to the cycle counter. 17310461SAndreas.Sandberg@ARM.com */ 17410461SAndreas.Sandberg@ARM.com typedef unsigned int CounterId; 17510461SAndreas.Sandberg@ARM.com 17610461SAndreas.Sandberg@ARM.com /** Cycle Count Register Number */ 17710461SAndreas.Sandberg@ARM.com static const CounterId PMCCNTR = 31; 17810461SAndreas.Sandberg@ARM.com 17910461SAndreas.Sandberg@ARM.com /** 18010461SAndreas.Sandberg@ARM.com * Event type ID. 18110461SAndreas.Sandberg@ARM.com * 18210461SAndreas.Sandberg@ARM.com * See the PMU documentation for a list of architected IDs. 18310461SAndreas.Sandberg@ARM.com */ 18410461SAndreas.Sandberg@ARM.com typedef unsigned int EventTypeId; 18510461SAndreas.Sandberg@ARM.com 18610461SAndreas.Sandberg@ARM.com /** ID of the software increment event */ 18710461SAndreas.Sandberg@ARM.com static const EventTypeId ARCH_EVENT_SW_INCR = 0x00; 18810461SAndreas.Sandberg@ARM.com 18910461SAndreas.Sandberg@ARM.com protected: /* High-level register and interrupt handling */ 19010461SAndreas.Sandberg@ARM.com MiscReg readMiscRegInt(int misc_reg); 19110461SAndreas.Sandberg@ARM.com 19210461SAndreas.Sandberg@ARM.com /** 19310461SAndreas.Sandberg@ARM.com * PMCR write handling 19410461SAndreas.Sandberg@ARM.com * 19510461SAndreas.Sandberg@ARM.com * The PMCR register needs special handling since writing to it 19610461SAndreas.Sandberg@ARM.com * changes PMU-global state (e.g., resets all counters). 19710461SAndreas.Sandberg@ARM.com * 19810461SAndreas.Sandberg@ARM.com * @param val New PMCR value 19910461SAndreas.Sandberg@ARM.com */ 20010461SAndreas.Sandberg@ARM.com void setControlReg(PMCR_t val); 20110461SAndreas.Sandberg@ARM.com 20210461SAndreas.Sandberg@ARM.com /** 20310461SAndreas.Sandberg@ARM.com * Reset all event counters excluding the cycle counter to zero. 20410461SAndreas.Sandberg@ARM.com */ 20510461SAndreas.Sandberg@ARM.com void resetEventCounts(); 20610461SAndreas.Sandberg@ARM.com 20710461SAndreas.Sandberg@ARM.com /** 20810461SAndreas.Sandberg@ARM.com * Deliver a PMU interrupt to the GIC 20910461SAndreas.Sandberg@ARM.com */ 21010461SAndreas.Sandberg@ARM.com void raiseInterrupt(); 21110461SAndreas.Sandberg@ARM.com 21210461SAndreas.Sandberg@ARM.com /** 21310461SAndreas.Sandberg@ARM.com * Get the value of a performance counter. 21410461SAndreas.Sandberg@ARM.com * 21510461SAndreas.Sandberg@ARM.com * This method returns the value of a general purpose performance 21610461SAndreas.Sandberg@ARM.com * counter or the fixed-function cycle counter. Non-existing 21710461SAndreas.Sandberg@ARM.com * counters are treated as constant '0'. 21810461SAndreas.Sandberg@ARM.com * 21910461SAndreas.Sandberg@ARM.com * @return Value of the performance counter, 0 if the counter does 22010461SAndreas.Sandberg@ARM.com * not exist. 22110461SAndreas.Sandberg@ARM.com */ 22210461SAndreas.Sandberg@ARM.com uint64_t getCounterValue(CounterId id) const { 22310461SAndreas.Sandberg@ARM.com return isValidCounter(id) ? getCounter(id).value : 0; 22410461SAndreas.Sandberg@ARM.com } 22510461SAndreas.Sandberg@ARM.com 22610461SAndreas.Sandberg@ARM.com /** 22710461SAndreas.Sandberg@ARM.com * Set the value of a performance counter. 22810461SAndreas.Sandberg@ARM.com * 22910461SAndreas.Sandberg@ARM.com * This method sets the value of a general purpose performance 23010461SAndreas.Sandberg@ARM.com * counter or the fixed-function cycle counter. Writes to 23110461SAndreas.Sandberg@ARM.com * non-existing counters are ignored. 23210461SAndreas.Sandberg@ARM.com */ 23310461SAndreas.Sandberg@ARM.com void setCounterValue(CounterId id, uint64_t val); 23410461SAndreas.Sandberg@ARM.com 23510461SAndreas.Sandberg@ARM.com /** 23610461SAndreas.Sandberg@ARM.com * Get the type and filter settings of a counter (PMEVTYPER) 23710461SAndreas.Sandberg@ARM.com * 23810461SAndreas.Sandberg@ARM.com * This method implements a read from a PMEVTYPER register. It 23910461SAndreas.Sandberg@ARM.com * returns the type value and filter settings of a general purpose 24010461SAndreas.Sandberg@ARM.com * performance counter or the cycle counter. Non-existing counters 24110461SAndreas.Sandberg@ARM.com * are treated as constant '0'. 24210461SAndreas.Sandberg@ARM.com * 24310461SAndreas.Sandberg@ARM.com * @param id Counter ID within the PMU. 24410461SAndreas.Sandberg@ARM.com * @return Performance counter type ID. 24510461SAndreas.Sandberg@ARM.com */ 24610461SAndreas.Sandberg@ARM.com PMEVTYPER_t getCounterTypeRegister(CounterId id) const; 24710461SAndreas.Sandberg@ARM.com 24810461SAndreas.Sandberg@ARM.com /** 24910461SAndreas.Sandberg@ARM.com * Set the type and filter settings of a performance counter 25010461SAndreas.Sandberg@ARM.com * (PMEVTYPER) 25110461SAndreas.Sandberg@ARM.com * 25210461SAndreas.Sandberg@ARM.com * This method implements a write to a PMEVTYPER register. It sets 25310461SAndreas.Sandberg@ARM.com * the type value and filter settings of a general purpose 25410461SAndreas.Sandberg@ARM.com * performance counter or the cycle counter. Writes to 25510461SAndreas.Sandberg@ARM.com * non-existing counters are ignored. The method automatically 25610461SAndreas.Sandberg@ARM.com * updates the probes used by the counter if it is enabled. 25710461SAndreas.Sandberg@ARM.com * 25810461SAndreas.Sandberg@ARM.com * @param id Counter ID within the PMU. 25910461SAndreas.Sandberg@ARM.com * @param type Performance counter type and filter configuration.. 26010461SAndreas.Sandberg@ARM.com */ 26110461SAndreas.Sandberg@ARM.com void setCounterTypeRegister(CounterId id, PMEVTYPER_t type); 26210461SAndreas.Sandberg@ARM.com 26310461SAndreas.Sandberg@ARM.com protected: /* Probe handling and counter state */ 26410461SAndreas.Sandberg@ARM.com class ProbeListener : public ProbeListenerArgBase<uint64_t> 26510461SAndreas.Sandberg@ARM.com { 26610461SAndreas.Sandberg@ARM.com public: 26710461SAndreas.Sandberg@ARM.com ProbeListener(PMU &_pmu, CounterId _id, 26810461SAndreas.Sandberg@ARM.com ProbeManager *pm, const std::string &name) 26910461SAndreas.Sandberg@ARM.com : ProbeListenerArgBase(pm, name), 27010461SAndreas.Sandberg@ARM.com pmu(_pmu), id(_id) {} 27110461SAndreas.Sandberg@ARM.com 27210461SAndreas.Sandberg@ARM.com void notify(const uint64_t &val) M5_ATTR_OVERRIDE 27310461SAndreas.Sandberg@ARM.com { 27410461SAndreas.Sandberg@ARM.com pmu.handleEvent(id, val); 27510461SAndreas.Sandberg@ARM.com } 27610461SAndreas.Sandberg@ARM.com 27710461SAndreas.Sandberg@ARM.com protected: 27810461SAndreas.Sandberg@ARM.com PMU &pmu; 27910461SAndreas.Sandberg@ARM.com const CounterId id; 28010461SAndreas.Sandberg@ARM.com }; 28110461SAndreas.Sandberg@ARM.com typedef std::unique_ptr<ProbeListener> ProbeListenerUPtr; 28210461SAndreas.Sandberg@ARM.com 28310461SAndreas.Sandberg@ARM.com /** 28410461SAndreas.Sandberg@ARM.com * Event type configuration 28510461SAndreas.Sandberg@ARM.com * 28610461SAndreas.Sandberg@ARM.com * The main purpose of this class is to describe how a PMU event 28710461SAndreas.Sandberg@ARM.com * type is sampled. It is implemented as a probe factory that 28810461SAndreas.Sandberg@ARM.com * returns a probe attached to the object the event is mointoring. 28910461SAndreas.Sandberg@ARM.com */ 29010461SAndreas.Sandberg@ARM.com struct EventType { 29110461SAndreas.Sandberg@ARM.com /** 29210461SAndreas.Sandberg@ARM.com * @param _obj Target SimObject 29310461SAndreas.Sandberg@ARM.com * @param _name Probe name 29410461SAndreas.Sandberg@ARM.com */ 29510461SAndreas.Sandberg@ARM.com EventType(SimObject *_obj, const std::string &_name) 29610461SAndreas.Sandberg@ARM.com : obj(_obj), name(_name) {} 29710461SAndreas.Sandberg@ARM.com 29810461SAndreas.Sandberg@ARM.com /** 29910461SAndreas.Sandberg@ARM.com * Create and attach a probe used to drive this event. 30010461SAndreas.Sandberg@ARM.com * 30110461SAndreas.Sandberg@ARM.com * @param pmu PMU owning the probe. 30210461SAndreas.Sandberg@ARM.com * @param CounterID counter ID within the PMU. 30310461SAndreas.Sandberg@ARM.com * @return Pointer to a probe listener. 30410461SAndreas.Sandberg@ARM.com */ 30510461SAndreas.Sandberg@ARM.com std::unique_ptr<ProbeListener> create(PMU &pmu, CounterId cid) const 30610461SAndreas.Sandberg@ARM.com { 30710461SAndreas.Sandberg@ARM.com std::unique_ptr<ProbeListener> ptr; 30810461SAndreas.Sandberg@ARM.com ptr.reset(new ProbeListener(pmu, cid, 30910461SAndreas.Sandberg@ARM.com obj->getProbeManager(), name)); 31010461SAndreas.Sandberg@ARM.com return ptr; 31110461SAndreas.Sandberg@ARM.com } 31210461SAndreas.Sandberg@ARM.com 31310461SAndreas.Sandberg@ARM.com /** SimObject being measured by this probe */ 31410461SAndreas.Sandberg@ARM.com SimObject *const obj; 31510461SAndreas.Sandberg@ARM.com /** Probe name within obj */ 31610461SAndreas.Sandberg@ARM.com const std::string name; 31710461SAndreas.Sandberg@ARM.com 31810461SAndreas.Sandberg@ARM.com private: 31910461SAndreas.Sandberg@ARM.com // Disable the default constructor 32010461SAndreas.Sandberg@ARM.com EventType(); 32110461SAndreas.Sandberg@ARM.com }; 32210461SAndreas.Sandberg@ARM.com 32310461SAndreas.Sandberg@ARM.com /** State of a counter within the PMU. */ 32410905Sandreas.sandberg@arm.com struct CounterState : public Serializable { 32510461SAndreas.Sandberg@ARM.com CounterState() 32610609Sandreas.sandberg@arm.com : eventId(0), filter(0), value(0), enabled(false), 32710461SAndreas.Sandberg@ARM.com overflow64(false) { 32810461SAndreas.Sandberg@ARM.com 32910461SAndreas.Sandberg@ARM.com listeners.reserve(4); 33010461SAndreas.Sandberg@ARM.com } 33110461SAndreas.Sandberg@ARM.com 33210905Sandreas.sandberg@arm.com void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE; 33310905Sandreas.sandberg@arm.com void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE; 33410461SAndreas.Sandberg@ARM.com 33510461SAndreas.Sandberg@ARM.com /** 33610461SAndreas.Sandberg@ARM.com * Add an event count to the counter and check for overflow. 33710461SAndreas.Sandberg@ARM.com * 33810461SAndreas.Sandberg@ARM.com * @param delta Number of events to add to the counter. 33910461SAndreas.Sandberg@ARM.com * @return true on overflow, false otherwise. 34010461SAndreas.Sandberg@ARM.com */ 34110461SAndreas.Sandberg@ARM.com bool add(uint64_t delta); 34210461SAndreas.Sandberg@ARM.com 34310461SAndreas.Sandberg@ARM.com public: /* Serializable state */ 34410461SAndreas.Sandberg@ARM.com /** Counter event ID */ 34510461SAndreas.Sandberg@ARM.com EventTypeId eventId; 34610461SAndreas.Sandberg@ARM.com 34710609Sandreas.sandberg@arm.com /** Filtering settings (evtCount is unused) */ 34810609Sandreas.sandberg@arm.com PMEVTYPER_t filter; 34910609Sandreas.sandberg@arm.com 35010461SAndreas.Sandberg@ARM.com /** Current value of the counter */ 35110461SAndreas.Sandberg@ARM.com uint64_t value; 35210461SAndreas.Sandberg@ARM.com 35310461SAndreas.Sandberg@ARM.com /** Is the counter enabled? */ 35410461SAndreas.Sandberg@ARM.com bool enabled; 35510461SAndreas.Sandberg@ARM.com 35610461SAndreas.Sandberg@ARM.com /** Is this a 64-bit counter? */ 35710461SAndreas.Sandberg@ARM.com bool overflow64; 35810461SAndreas.Sandberg@ARM.com 35910461SAndreas.Sandberg@ARM.com public: /* Configuration */ 36010461SAndreas.Sandberg@ARM.com /** Probe listeners driving this counter */ 36110461SAndreas.Sandberg@ARM.com std::vector<ProbeListenerUPtr> listeners; 36210461SAndreas.Sandberg@ARM.com }; 36310461SAndreas.Sandberg@ARM.com 36410461SAndreas.Sandberg@ARM.com /** 36510461SAndreas.Sandberg@ARM.com * Handle an counting event triggered by a probe. 36610461SAndreas.Sandberg@ARM.com * 36710461SAndreas.Sandberg@ARM.com * This method is called by the ProbeListener class whenever an 36810461SAndreas.Sandberg@ARM.com * active probe is triggered. Ths method adds the event count from 36910461SAndreas.Sandberg@ARM.com * the probe to the affected counter, checks for overflows, and 37010461SAndreas.Sandberg@ARM.com * delivers an interrupt if needed. 37110461SAndreas.Sandberg@ARM.com * 37210461SAndreas.Sandberg@ARM.com * @param id Counter ID affected by the probe. 37310461SAndreas.Sandberg@ARM.com * @param delta Counter increment 37410461SAndreas.Sandberg@ARM.com */ 37510461SAndreas.Sandberg@ARM.com void handleEvent(CounterId id, uint64_t delta); 37610461SAndreas.Sandberg@ARM.com 37710461SAndreas.Sandberg@ARM.com /** 37810461SAndreas.Sandberg@ARM.com * Is this a valid counter ID? 37910461SAndreas.Sandberg@ARM.com * 38010461SAndreas.Sandberg@ARM.com * @param id ID of counter within the PMU. 38110461SAndreas.Sandberg@ARM.com * 38210461SAndreas.Sandberg@ARM.com * @return true if counter is within the allowed range or the 38310461SAndreas.Sandberg@ARM.com * cycle counter, false otherwise. 38410461SAndreas.Sandberg@ARM.com */ 38510461SAndreas.Sandberg@ARM.com bool isValidCounter(CounterId id) const { 38610461SAndreas.Sandberg@ARM.com return id < counters.size() || id == PMCCNTR; 38710461SAndreas.Sandberg@ARM.com } 38810461SAndreas.Sandberg@ARM.com 38910461SAndreas.Sandberg@ARM.com /** 39010461SAndreas.Sandberg@ARM.com * Return the state of a counter. 39110461SAndreas.Sandberg@ARM.com * 39210461SAndreas.Sandberg@ARM.com * @param id ID of counter within the PMU. 39310461SAndreas.Sandberg@ARM.com * @return Reference to a CounterState instance representing the 39410461SAndreas.Sandberg@ARM.com * counter. 39510461SAndreas.Sandberg@ARM.com */ 39610461SAndreas.Sandberg@ARM.com CounterState &getCounter(CounterId id) { 39710461SAndreas.Sandberg@ARM.com assert(isValidCounter(id)); 39810461SAndreas.Sandberg@ARM.com return id == PMCCNTR ? cycleCounter : counters[id]; 39910461SAndreas.Sandberg@ARM.com } 40010461SAndreas.Sandberg@ARM.com 40110461SAndreas.Sandberg@ARM.com 40210461SAndreas.Sandberg@ARM.com /** 40310461SAndreas.Sandberg@ARM.com * Return the state of a counter. 40410461SAndreas.Sandberg@ARM.com * 40510461SAndreas.Sandberg@ARM.com * @param id ID of counter within the PMU. 40610461SAndreas.Sandberg@ARM.com * @return Reference to a CounterState instance representing the 40710461SAndreas.Sandberg@ARM.com * counter. 40810461SAndreas.Sandberg@ARM.com */ 40910461SAndreas.Sandberg@ARM.com const CounterState &getCounter(CounterId id) const { 41010461SAndreas.Sandberg@ARM.com assert(isValidCounter(id)); 41110461SAndreas.Sandberg@ARM.com return id == PMCCNTR ? cycleCounter : counters[id]; 41210461SAndreas.Sandberg@ARM.com } 41310461SAndreas.Sandberg@ARM.com 41410461SAndreas.Sandberg@ARM.com /** 41510461SAndreas.Sandberg@ARM.com * Depending on counter configuration, add or remove the probes 41610461SAndreas.Sandberg@ARM.com * driving the counter. 41710461SAndreas.Sandberg@ARM.com * 41810461SAndreas.Sandberg@ARM.com * Look at the state of a counter and (re-)attach the probes 41910461SAndreas.Sandberg@ARM.com * needed to drive a counter if it is currently active. All probes 42010461SAndreas.Sandberg@ARM.com * for the counter are detached if the counter is inactive. 42110461SAndreas.Sandberg@ARM.com * 42210461SAndreas.Sandberg@ARM.com * @param id ID of counter within the PMU. 42310461SAndreas.Sandberg@ARM.com * @param ctr Reference to the counter's state 42410461SAndreas.Sandberg@ARM.com */ 42510461SAndreas.Sandberg@ARM.com void updateCounter(CounterId id, CounterState &ctr); 42610461SAndreas.Sandberg@ARM.com 42710461SAndreas.Sandberg@ARM.com /** 42810609Sandreas.sandberg@arm.com * Check if a counter's settings allow it to be counted. 42910609Sandreas.sandberg@arm.com * 43010609Sandreas.sandberg@arm.com * @param ctr Counter state instance representing this counter. 43110609Sandreas.sandberg@arm.com * @return false if the counter is active, true otherwise. 43210609Sandreas.sandberg@arm.com */ 43310609Sandreas.sandberg@arm.com bool isFiltered(const CounterState &ctr) const; 43410609Sandreas.sandberg@arm.com 43510609Sandreas.sandberg@arm.com /** 43610461SAndreas.Sandberg@ARM.com * Call updateCounter() for each counter in the PMU if the 43710461SAndreas.Sandberg@ARM.com * counter's state has changed.. 43810461SAndreas.Sandberg@ARM.com * 43910461SAndreas.Sandberg@ARM.com * @see updateCounter() 44010461SAndreas.Sandberg@ARM.com */ 44110461SAndreas.Sandberg@ARM.com void updateAllCounters(); 44210461SAndreas.Sandberg@ARM.com 44310461SAndreas.Sandberg@ARM.com protected: /* State that needs to be serialized */ 44410461SAndreas.Sandberg@ARM.com /** Performance Monitor Count Enable Register */ 44510461SAndreas.Sandberg@ARM.com MiscReg reg_pmcnten; 44610461SAndreas.Sandberg@ARM.com 44710461SAndreas.Sandberg@ARM.com /** Performance Monitor Control Register */ 44810461SAndreas.Sandberg@ARM.com PMCR_t reg_pmcr; 44910461SAndreas.Sandberg@ARM.com 45010461SAndreas.Sandberg@ARM.com /** Performance Monitor Selection Register */ 45110461SAndreas.Sandberg@ARM.com PMSELR_t reg_pmselr; 45210461SAndreas.Sandberg@ARM.com 45310461SAndreas.Sandberg@ARM.com /** Performance Monitor Interrupt Enable Register */ 45410461SAndreas.Sandberg@ARM.com MiscReg reg_pminten; 45510461SAndreas.Sandberg@ARM.com 45610461SAndreas.Sandberg@ARM.com /** Performance Monitor Overflow Status Register */ 45710461SAndreas.Sandberg@ARM.com MiscReg reg_pmovsr; 45810461SAndreas.Sandberg@ARM.com 45910461SAndreas.Sandberg@ARM.com /** 46010461SAndreas.Sandberg@ARM.com * Performance counter ID register 46110461SAndreas.Sandberg@ARM.com * 46210461SAndreas.Sandberg@ARM.com * This register contains a bitmask of available architected 46310461SAndreas.Sandberg@ARM.com * counters. 46410461SAndreas.Sandberg@ARM.com */ 46510461SAndreas.Sandberg@ARM.com uint64_t reg_pmceid; 46610461SAndreas.Sandberg@ARM.com 46710461SAndreas.Sandberg@ARM.com /** Remainder part when the clock counter is divided by 64 */ 46810461SAndreas.Sandberg@ARM.com unsigned clock_remainder; 46910461SAndreas.Sandberg@ARM.com 47010461SAndreas.Sandberg@ARM.com /** State of all general-purpose counters supported by PMU */ 47110461SAndreas.Sandberg@ARM.com std::vector<CounterState> counters; 47210461SAndreas.Sandberg@ARM.com /** State of the cycle counter */ 47310461SAndreas.Sandberg@ARM.com CounterState cycleCounter; 47410461SAndreas.Sandberg@ARM.com 47510461SAndreas.Sandberg@ARM.com protected: /* Configuration and constants */ 47610461SAndreas.Sandberg@ARM.com /** Constant (configuration-dependent) part of the PMCR */ 47710461SAndreas.Sandberg@ARM.com PMCR_t reg_pmcr_conf; 47810461SAndreas.Sandberg@ARM.com /** PMCR write mask when accessed from the guest */ 47910461SAndreas.Sandberg@ARM.com static const MiscReg reg_pmcr_wr_mask; 48010461SAndreas.Sandberg@ARM.com 48110461SAndreas.Sandberg@ARM.com /** Performance monitor interrupt number */ 48210461SAndreas.Sandberg@ARM.com const unsigned int pmuInterrupt; 48310461SAndreas.Sandberg@ARM.com /** Platform this device belongs to */ 48410461SAndreas.Sandberg@ARM.com Platform *const platform; 48510461SAndreas.Sandberg@ARM.com 48610461SAndreas.Sandberg@ARM.com /** 48710461SAndreas.Sandberg@ARM.com * Event types supported by this PMU. 48810461SAndreas.Sandberg@ARM.com * 48910461SAndreas.Sandberg@ARM.com * Each event type ID can map to multiple EventType structures, 49010461SAndreas.Sandberg@ARM.com * which enables the PMU to use multiple probes for a single 49110461SAndreas.Sandberg@ARM.com * event. This can be useful in the following cases: 49210461SAndreas.Sandberg@ARM.com * <ul> 49310461SAndreas.Sandberg@ARM.com * <li>Some events can are increment by multiple different probe 49410461SAndreas.Sandberg@ARM.com * points (e.g., the CPU memory access counter gets 49510461SAndreas.Sandberg@ARM.com * incremented for both loads and stores). 49610461SAndreas.Sandberg@ARM.com * 49710461SAndreas.Sandberg@ARM.com * <li>A system switching between multiple CPU models can 49810461SAndreas.Sandberg@ARM.com * register events for all models that will execute a thread 49910461SAndreas.Sandberg@ARM.com * and tehreby ensure that the PMU continues to work. 50010461SAndreas.Sandberg@ARM.com * </ul> 50110461SAndreas.Sandberg@ARM.com */ 50210461SAndreas.Sandberg@ARM.com std::multimap<EventTypeId, EventType> pmuEventTypes; 50310461SAndreas.Sandberg@ARM.com}; 50410461SAndreas.Sandberg@ARM.com 50510461SAndreas.Sandberg@ARM.com} // namespace ArmISA 50610461SAndreas.Sandberg@ARM.com#endif 507