pmu.hh revision 12286
110461SAndreas.Sandberg@ARM.com/* 212117Sjose.marinho@arm.com * Copyright (c) 2011-2014, 2017 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" 5012286Sjose.marinho@arm.com#include "arch/arm/system.hh" 5112286Sjose.marinho@arm.com#include "base/cprintf.hh" 5212286Sjose.marinho@arm.com#include "cpu/base.hh" 5312286Sjose.marinho@arm.com#include "debug/PMUVerbose.hh" 5412286Sjose.marinho@arm.com#include "sim/eventq.hh" 5510461SAndreas.Sandberg@ARM.com#include "sim/sim_object.hh" 5612286Sjose.marinho@arm.com#include "sim/system.hh" 5710461SAndreas.Sandberg@ARM.com 5810461SAndreas.Sandberg@ARM.comclass ArmPMUParams; 5910461SAndreas.Sandberg@ARM.comclass Platform; 6010461SAndreas.Sandberg@ARM.comclass ThreadContext; 6110461SAndreas.Sandberg@ARM.com 6210461SAndreas.Sandberg@ARM.comnamespace ArmISA { 6310461SAndreas.Sandberg@ARM.com 6410461SAndreas.Sandberg@ARM.com 6510461SAndreas.Sandberg@ARM.com/** 6610461SAndreas.Sandberg@ARM.com * Model of an ARM PMU version 3 6710461SAndreas.Sandberg@ARM.com * 6810461SAndreas.Sandberg@ARM.com * This class implements a subset of the ARM PMU v3 specification as 6910461SAndreas.Sandberg@ARM.com * described in the ARMv8 reference manual. It supports most of the 7010461SAndreas.Sandberg@ARM.com * features of the PMU, however the following features are known to be 7110461SAndreas.Sandberg@ARM.com * missing: 7210461SAndreas.Sandberg@ARM.com * 7310461SAndreas.Sandberg@ARM.com * <ul> 7410461SAndreas.Sandberg@ARM.com * <li>Event filtering (e.g., from different privilege levels). 7510461SAndreas.Sandberg@ARM.com * <li>Access controls (the PMU currently ignores the execution level). 7610461SAndreas.Sandberg@ARM.com * <li>The chain counter (event no. 0x1E) is unimplemented. 7710461SAndreas.Sandberg@ARM.com * </ul> 7810461SAndreas.Sandberg@ARM.com * 7910461SAndreas.Sandberg@ARM.com * The PMU itself does not implement any events, in merely provides an 8010461SAndreas.Sandberg@ARM.com * interface for the configuration scripts to hook up probes that 8110461SAndreas.Sandberg@ARM.com * drive events. Configuration scripts should call addEventProbe() to 8210461SAndreas.Sandberg@ARM.com * configure custom events or high-level methods to configure 8310461SAndreas.Sandberg@ARM.com * architected events. The Python implementation of addEventProbe() 8410461SAndreas.Sandberg@ARM.com * automatically delays event type registration until after 8510461SAndreas.Sandberg@ARM.com * instantiation. 8610461SAndreas.Sandberg@ARM.com * 8710461SAndreas.Sandberg@ARM.com * In order to support CPU switching and some combined counters (e.g., 8810461SAndreas.Sandberg@ARM.com * memory references synthesized from loads and stores), the PMU 8910461SAndreas.Sandberg@ARM.com * allows multiple probes per event type. When creating a system that 9010461SAndreas.Sandberg@ARM.com * switches between CPU models that share the same PMU, PMU events for 9110461SAndreas.Sandberg@ARM.com * all of the CPU models can be registered with the PMU. 9210461SAndreas.Sandberg@ARM.com * 9310461SAndreas.Sandberg@ARM.com * @see The ARM Architecture Refererence Manual (DDI 0487A) 9410461SAndreas.Sandberg@ARM.com * 9510461SAndreas.Sandberg@ARM.com */ 9610461SAndreas.Sandberg@ARM.comclass PMU : public SimObject, public ArmISA::BaseISADevice { 9710461SAndreas.Sandberg@ARM.com public: 9810461SAndreas.Sandberg@ARM.com PMU(const ArmPMUParams *p); 9910461SAndreas.Sandberg@ARM.com ~PMU(); 10010461SAndreas.Sandberg@ARM.com 10110461SAndreas.Sandberg@ARM.com void addEventProbe(unsigned int id, SimObject *obj, const char *name); 10212286Sjose.marinho@arm.com void addSoftwareIncrementEvent(unsigned int id); 10312286Sjose.marinho@arm.com 10412286Sjose.marinho@arm.com void registerEvent(uint32_t id); 10510461SAndreas.Sandberg@ARM.com 10610461SAndreas.Sandberg@ARM.com public: // SimObject and related interfaces 10711168Sandreas.hansson@arm.com void serialize(CheckpointOut &cp) const override; 10811168Sandreas.hansson@arm.com void unserialize(CheckpointIn &cp) override; 10910461SAndreas.Sandberg@ARM.com 11011168Sandreas.hansson@arm.com void drainResume() override; 11110461SAndreas.Sandberg@ARM.com 11212286Sjose.marinho@arm.com void regProbeListeners() override; 11310461SAndreas.Sandberg@ARM.com 11410461SAndreas.Sandberg@ARM.com public: // ISA Device interface 11510461SAndreas.Sandberg@ARM.com /** 11610461SAndreas.Sandberg@ARM.com * Set a register within the PMU. 11710461SAndreas.Sandberg@ARM.com * 11810461SAndreas.Sandberg@ARM.com * @param misc_reg Register number (see miscregs.hh) 11910461SAndreas.Sandberg@ARM.com * @param val Value to store 12010461SAndreas.Sandberg@ARM.com */ 12111168Sandreas.hansson@arm.com void setMiscReg(int misc_reg, MiscReg val) override; 12210461SAndreas.Sandberg@ARM.com /** 12310461SAndreas.Sandberg@ARM.com * Read a register within the PMU. 12410461SAndreas.Sandberg@ARM.com * 12510461SAndreas.Sandberg@ARM.com * @param misc_reg Register number (see miscregs.hh) 12610461SAndreas.Sandberg@ARM.com * @return Register value. 12710461SAndreas.Sandberg@ARM.com */ 12811168Sandreas.hansson@arm.com MiscReg readMiscReg(int misc_reg) override; 12910461SAndreas.Sandberg@ARM.com 13010461SAndreas.Sandberg@ARM.com protected: // PMU register types and constants 13110461SAndreas.Sandberg@ARM.com BitUnion32(PMCR_t) 13210461SAndreas.Sandberg@ARM.com // PMU Enable 13310461SAndreas.Sandberg@ARM.com Bitfield<0> e; 13410461SAndreas.Sandberg@ARM.com // Event counter reset 13510461SAndreas.Sandberg@ARM.com Bitfield<1> p; 13610461SAndreas.Sandberg@ARM.com // Cycle counter reset 13710461SAndreas.Sandberg@ARM.com Bitfield<2> c; 13810461SAndreas.Sandberg@ARM.com // Cycle counter divider enable 13910461SAndreas.Sandberg@ARM.com Bitfield<3> d; 14010461SAndreas.Sandberg@ARM.com // Export enable 14110461SAndreas.Sandberg@ARM.com Bitfield<4> x; 14210461SAndreas.Sandberg@ARM.com // Disable PMCCNTR when event counting is prohibited 14310461SAndreas.Sandberg@ARM.com Bitfield<5> dp; 14410461SAndreas.Sandberg@ARM.com // Long Cycle counter enable 14510461SAndreas.Sandberg@ARM.com Bitfield<6> lc; 14610461SAndreas.Sandberg@ARM.com // Number of event counters implemented 14710461SAndreas.Sandberg@ARM.com Bitfield<15, 11> n; 14810461SAndreas.Sandberg@ARM.com // Implementation ID 14910461SAndreas.Sandberg@ARM.com Bitfield<23, 16> idcode; 15010461SAndreas.Sandberg@ARM.com // Implementer code 15110461SAndreas.Sandberg@ARM.com Bitfield<31, 24> imp; 15210461SAndreas.Sandberg@ARM.com EndBitUnion(PMCR_t) 15310461SAndreas.Sandberg@ARM.com 15410461SAndreas.Sandberg@ARM.com BitUnion32(PMSELR_t) 15510461SAndreas.Sandberg@ARM.com // Performance counter selector 15610461SAndreas.Sandberg@ARM.com Bitfield<4, 0> sel; 15710461SAndreas.Sandberg@ARM.com EndBitUnion(PMSELR_t) 15810461SAndreas.Sandberg@ARM.com 15910461SAndreas.Sandberg@ARM.com BitUnion32(PMEVTYPER_t) 16012117Sjose.marinho@arm.com Bitfield<15, 0> evtCount; 16110461SAndreas.Sandberg@ARM.com 16210461SAndreas.Sandberg@ARM.com // Secure EL3 filtering 16310461SAndreas.Sandberg@ARM.com Bitfield<26> m; 16410461SAndreas.Sandberg@ARM.com // Non-secure EL2 mode filtering 16510461SAndreas.Sandberg@ARM.com Bitfield<27> nsh; 16610461SAndreas.Sandberg@ARM.com // Non-secure EL0 mode filtering 16710461SAndreas.Sandberg@ARM.com Bitfield<28> nsu; 16810461SAndreas.Sandberg@ARM.com // Non-secure EL1 mode filtering 16910461SAndreas.Sandberg@ARM.com Bitfield<29> nsk; 17010461SAndreas.Sandberg@ARM.com // EL0 filtering 17110461SAndreas.Sandberg@ARM.com Bitfield<30> u; 17210461SAndreas.Sandberg@ARM.com // EL1 filtering 17310461SAndreas.Sandberg@ARM.com Bitfield<31> p; 17410461SAndreas.Sandberg@ARM.com EndBitUnion(PMEVTYPER_t) 17510461SAndreas.Sandberg@ARM.com 17610461SAndreas.Sandberg@ARM.com /** 17710461SAndreas.Sandberg@ARM.com * Counter ID within the PMU. 17810461SAndreas.Sandberg@ARM.com * 17910461SAndreas.Sandberg@ARM.com * This value is typically used to index into various registers 18010461SAndreas.Sandberg@ARM.com * controlling interrupts and overflows. The value normally in the 18110461SAndreas.Sandberg@ARM.com * [0, 31] range, where 31 refers to the cycle counter. 18210461SAndreas.Sandberg@ARM.com */ 18310461SAndreas.Sandberg@ARM.com typedef unsigned int CounterId; 18410461SAndreas.Sandberg@ARM.com 18510461SAndreas.Sandberg@ARM.com /** Cycle Count Register Number */ 18610461SAndreas.Sandberg@ARM.com static const CounterId PMCCNTR = 31; 18710461SAndreas.Sandberg@ARM.com 18810461SAndreas.Sandberg@ARM.com /** 18910461SAndreas.Sandberg@ARM.com * Event type ID. 19010461SAndreas.Sandberg@ARM.com * 19110461SAndreas.Sandberg@ARM.com * See the PMU documentation for a list of architected IDs. 19210461SAndreas.Sandberg@ARM.com */ 19310461SAndreas.Sandberg@ARM.com typedef unsigned int EventTypeId; 19410461SAndreas.Sandberg@ARM.com 19510461SAndreas.Sandberg@ARM.com protected: /* High-level register and interrupt handling */ 19610461SAndreas.Sandberg@ARM.com MiscReg readMiscRegInt(int misc_reg); 19710461SAndreas.Sandberg@ARM.com 19810461SAndreas.Sandberg@ARM.com /** 19910461SAndreas.Sandberg@ARM.com * PMCR write handling 20010461SAndreas.Sandberg@ARM.com * 20110461SAndreas.Sandberg@ARM.com * The PMCR register needs special handling since writing to it 20210461SAndreas.Sandberg@ARM.com * changes PMU-global state (e.g., resets all counters). 20310461SAndreas.Sandberg@ARM.com * 20410461SAndreas.Sandberg@ARM.com * @param val New PMCR value 20510461SAndreas.Sandberg@ARM.com */ 20610461SAndreas.Sandberg@ARM.com void setControlReg(PMCR_t val); 20710461SAndreas.Sandberg@ARM.com 20810461SAndreas.Sandberg@ARM.com /** 20910461SAndreas.Sandberg@ARM.com * Reset all event counters excluding the cycle counter to zero. 21010461SAndreas.Sandberg@ARM.com */ 21110461SAndreas.Sandberg@ARM.com void resetEventCounts(); 21210461SAndreas.Sandberg@ARM.com 21310461SAndreas.Sandberg@ARM.com /** 21410461SAndreas.Sandberg@ARM.com * Deliver a PMU interrupt to the GIC 21510461SAndreas.Sandberg@ARM.com */ 21610461SAndreas.Sandberg@ARM.com void raiseInterrupt(); 21710461SAndreas.Sandberg@ARM.com 21810461SAndreas.Sandberg@ARM.com /** 21910461SAndreas.Sandberg@ARM.com * Get the value of a performance counter. 22010461SAndreas.Sandberg@ARM.com * 22110461SAndreas.Sandberg@ARM.com * This method returns the value of a general purpose performance 22210461SAndreas.Sandberg@ARM.com * counter or the fixed-function cycle counter. Non-existing 22310461SAndreas.Sandberg@ARM.com * counters are treated as constant '0'. 22410461SAndreas.Sandberg@ARM.com * 22510461SAndreas.Sandberg@ARM.com * @return Value of the performance counter, 0 if the counter does 22610461SAndreas.Sandberg@ARM.com * not exist. 22710461SAndreas.Sandberg@ARM.com */ 22810461SAndreas.Sandberg@ARM.com uint64_t getCounterValue(CounterId id) const { 22912286Sjose.marinho@arm.com return isValidCounter(id) ? getCounter(id).getValue() : 0; 23010461SAndreas.Sandberg@ARM.com } 23110461SAndreas.Sandberg@ARM.com 23210461SAndreas.Sandberg@ARM.com /** 23310461SAndreas.Sandberg@ARM.com * Set the value of a performance counter. 23410461SAndreas.Sandberg@ARM.com * 23510461SAndreas.Sandberg@ARM.com * This method sets the value of a general purpose performance 23610461SAndreas.Sandberg@ARM.com * counter or the fixed-function cycle counter. Writes to 23710461SAndreas.Sandberg@ARM.com * non-existing counters are ignored. 23810461SAndreas.Sandberg@ARM.com */ 23910461SAndreas.Sandberg@ARM.com void setCounterValue(CounterId id, uint64_t val); 24010461SAndreas.Sandberg@ARM.com 24110461SAndreas.Sandberg@ARM.com /** 24210461SAndreas.Sandberg@ARM.com * Get the type and filter settings of a counter (PMEVTYPER) 24310461SAndreas.Sandberg@ARM.com * 24410461SAndreas.Sandberg@ARM.com * This method implements a read from a PMEVTYPER register. It 24510461SAndreas.Sandberg@ARM.com * returns the type value and filter settings of a general purpose 24610461SAndreas.Sandberg@ARM.com * performance counter or the cycle counter. Non-existing counters 24710461SAndreas.Sandberg@ARM.com * are treated as constant '0'. 24810461SAndreas.Sandberg@ARM.com * 24910461SAndreas.Sandberg@ARM.com * @param id Counter ID within the PMU. 25010461SAndreas.Sandberg@ARM.com * @return Performance counter type ID. 25110461SAndreas.Sandberg@ARM.com */ 25210461SAndreas.Sandberg@ARM.com PMEVTYPER_t getCounterTypeRegister(CounterId id) const; 25310461SAndreas.Sandberg@ARM.com 25410461SAndreas.Sandberg@ARM.com /** 25510461SAndreas.Sandberg@ARM.com * Set the type and filter settings of a performance counter 25610461SAndreas.Sandberg@ARM.com * (PMEVTYPER) 25710461SAndreas.Sandberg@ARM.com * 25810461SAndreas.Sandberg@ARM.com * This method implements a write to a PMEVTYPER register. It sets 25910461SAndreas.Sandberg@ARM.com * the type value and filter settings of a general purpose 26010461SAndreas.Sandberg@ARM.com * performance counter or the cycle counter. Writes to 26110461SAndreas.Sandberg@ARM.com * non-existing counters are ignored. The method automatically 26210461SAndreas.Sandberg@ARM.com * updates the probes used by the counter if it is enabled. 26310461SAndreas.Sandberg@ARM.com * 26410461SAndreas.Sandberg@ARM.com * @param id Counter ID within the PMU. 26510461SAndreas.Sandberg@ARM.com * @param type Performance counter type and filter configuration.. 26610461SAndreas.Sandberg@ARM.com */ 26710461SAndreas.Sandberg@ARM.com void setCounterTypeRegister(CounterId id, PMEVTYPER_t type); 26810461SAndreas.Sandberg@ARM.com 26910461SAndreas.Sandberg@ARM.com protected: /* Probe handling and counter state */ 27012286Sjose.marinho@arm.com struct CounterState; 27110461SAndreas.Sandberg@ARM.com 27212286Sjose.marinho@arm.com /** 27312286Sjose.marinho@arm.com * Event definition base class 27412286Sjose.marinho@arm.com */ 27512286Sjose.marinho@arm.com struct PMUEvent { 27612286Sjose.marinho@arm.com 27712286Sjose.marinho@arm.com PMUEvent() {} 27812286Sjose.marinho@arm.com 27912286Sjose.marinho@arm.com virtual ~PMUEvent() {} 28012286Sjose.marinho@arm.com 28112286Sjose.marinho@arm.com /** 28212286Sjose.marinho@arm.com * attach this event to a given counter 28312286Sjose.marinho@arm.com * 28412286Sjose.marinho@arm.com * @param a pointer to the counter where to attach this event 28512286Sjose.marinho@arm.com */ 28612286Sjose.marinho@arm.com void attachEvent(PMU::CounterState *user); 28712286Sjose.marinho@arm.com 28812286Sjose.marinho@arm.com /** 28912286Sjose.marinho@arm.com * detach this event from a given counter 29012286Sjose.marinho@arm.com * 29112286Sjose.marinho@arm.com * @param a pointer to the counter where to detach this event from 29212286Sjose.marinho@arm.com */ 29312286Sjose.marinho@arm.com void detachEvent(PMU::CounterState *user); 29412286Sjose.marinho@arm.com 29512286Sjose.marinho@arm.com /** 29612286Sjose.marinho@arm.com * notify an event increment of val units, all the attached counters' 29712286Sjose.marinho@arm.com * value is incremented by val units. 29812286Sjose.marinho@arm.com * 29912286Sjose.marinho@arm.com * @param the quantity by which to increment the attached counter 30012286Sjose.marinho@arm.com * values 30112286Sjose.marinho@arm.com */ 30212286Sjose.marinho@arm.com virtual void increment(const uint64_t val); 30312286Sjose.marinho@arm.com 30412286Sjose.marinho@arm.com /** 30512286Sjose.marinho@arm.com * Enable the current event 30612286Sjose.marinho@arm.com */ 30712286Sjose.marinho@arm.com virtual void enable() = 0; 30812286Sjose.marinho@arm.com 30912286Sjose.marinho@arm.com /** 31012286Sjose.marinho@arm.com * Disable the current event 31112286Sjose.marinho@arm.com */ 31212286Sjose.marinho@arm.com virtual void disable() = 0; 31312286Sjose.marinho@arm.com 31412286Sjose.marinho@arm.com /** 31512286Sjose.marinho@arm.com * Method called immediately before a counter access in order for 31612286Sjose.marinho@arm.com * the associated event to update its state (if required) 31712286Sjose.marinho@arm.com */ 31812286Sjose.marinho@arm.com virtual void updateAttachedCounters() {} 31912286Sjose.marinho@arm.com 32012286Sjose.marinho@arm.com protected: 32112286Sjose.marinho@arm.com 32212286Sjose.marinho@arm.com /** set of counters using this event **/ 32312286Sjose.marinho@arm.com std::set<PMU::CounterState*> userCounters; 32412286Sjose.marinho@arm.com }; 32512286Sjose.marinho@arm.com 32612286Sjose.marinho@arm.com struct RegularEvent : public PMUEvent { 32712286Sjose.marinho@arm.com typedef std::pair<SimObject*, std::string> EventTypeEntry; 32812286Sjose.marinho@arm.com 32912286Sjose.marinho@arm.com void addMicroarchitectureProbe(SimObject* object, 33012286Sjose.marinho@arm.com std::string name) { 33112286Sjose.marinho@arm.com 33212286Sjose.marinho@arm.com panic_if(!object,"malformed probe-point" 33312286Sjose.marinho@arm.com " definition with name %s\n", name); 33412286Sjose.marinho@arm.com 33512286Sjose.marinho@arm.com microArchitectureEventSet.emplace(object, name); 33610461SAndreas.Sandberg@ARM.com } 33710461SAndreas.Sandberg@ARM.com 33810461SAndreas.Sandberg@ARM.com protected: 33912286Sjose.marinho@arm.com struct RegularProbe: public ProbeListenerArgBase<uint64_t> 34012286Sjose.marinho@arm.com { 34112286Sjose.marinho@arm.com RegularProbe(RegularEvent *parent, SimObject* obj, 34212286Sjose.marinho@arm.com std::string name) 34312286Sjose.marinho@arm.com : ProbeListenerArgBase(obj->getProbeManager(), name), 34412286Sjose.marinho@arm.com parentEvent(parent) {} 34512286Sjose.marinho@arm.com 34612286Sjose.marinho@arm.com RegularProbe() = delete; 34712286Sjose.marinho@arm.com 34812286Sjose.marinho@arm.com void notify(const uint64_t &val); 34912286Sjose.marinho@arm.com 35012286Sjose.marinho@arm.com protected: 35112286Sjose.marinho@arm.com RegularEvent *parentEvent; 35212286Sjose.marinho@arm.com }; 35312286Sjose.marinho@arm.com 35412286Sjose.marinho@arm.com /** The set of events driving the event value **/ 35512286Sjose.marinho@arm.com std::set<EventTypeEntry> microArchitectureEventSet; 35612286Sjose.marinho@arm.com 35712286Sjose.marinho@arm.com /** Set of probe listeners tapping onto each of the input micro-arch 35812286Sjose.marinho@arm.com * events which compose this pmu event 35912286Sjose.marinho@arm.com */ 36012286Sjose.marinho@arm.com std::vector<std::unique_ptr<RegularProbe>> attachedProbePointList; 36112286Sjose.marinho@arm.com 36212286Sjose.marinho@arm.com void enable() override; 36312286Sjose.marinho@arm.com 36412286Sjose.marinho@arm.com void disable() override; 36510461SAndreas.Sandberg@ARM.com }; 36612286Sjose.marinho@arm.com 36712286Sjose.marinho@arm.com class SWIncrementEvent : public PMUEvent 36812286Sjose.marinho@arm.com { 36912286Sjose.marinho@arm.com void enable() override {} 37012286Sjose.marinho@arm.com void disable() override {} 37112286Sjose.marinho@arm.com 37212286Sjose.marinho@arm.com public: 37312286Sjose.marinho@arm.com 37412286Sjose.marinho@arm.com /** 37512286Sjose.marinho@arm.com * write on the sw increment register inducing an increment of the 37612286Sjose.marinho@arm.com * counters with this event selected according to the bitfield written. 37712286Sjose.marinho@arm.com * 37812286Sjose.marinho@arm.com * @param the bitfield selecting the counters to increment. 37912286Sjose.marinho@arm.com */ 38012286Sjose.marinho@arm.com void write(uint64_t val); 38112286Sjose.marinho@arm.com }; 38210461SAndreas.Sandberg@ARM.com 38310461SAndreas.Sandberg@ARM.com /** 38412286Sjose.marinho@arm.com * Obtain the event of a given id 38510461SAndreas.Sandberg@ARM.com * 38612286Sjose.marinho@arm.com * @param the id of the event to obtain 38712286Sjose.marinho@arm.com * @return a pointer to the event with id eventId 38810461SAndreas.Sandberg@ARM.com */ 38912286Sjose.marinho@arm.com PMUEvent* getEvent(uint64_t eventId); 39010461SAndreas.Sandberg@ARM.com 39112286Sjose.marinho@arm.com /** State of a counter within the PMU. **/ 39210905Sandreas.sandberg@arm.com struct CounterState : public Serializable { 39312286Sjose.marinho@arm.com CounterState(PMU &pmuReference, uint64_t counter_id) 39412286Sjose.marinho@arm.com : eventId(0), filter(0), enabled(false), 39512286Sjose.marinho@arm.com overflow64(false), sourceEvent(nullptr), 39612286Sjose.marinho@arm.com counterId(counter_id), value(0), resetValue(false), 39712286Sjose.marinho@arm.com pmu(pmuReference) {} 39810461SAndreas.Sandberg@ARM.com 39911168Sandreas.hansson@arm.com void serialize(CheckpointOut &cp) const override; 40011168Sandreas.hansson@arm.com void unserialize(CheckpointIn &cp) override; 40110461SAndreas.Sandberg@ARM.com 40210461SAndreas.Sandberg@ARM.com /** 40310461SAndreas.Sandberg@ARM.com * Add an event count to the counter and check for overflow. 40410461SAndreas.Sandberg@ARM.com * 40510461SAndreas.Sandberg@ARM.com * @param delta Number of events to add to the counter. 40612286Sjose.marinho@arm.com * @return the quantity remaining until a counter overflow occurs. 40710461SAndreas.Sandberg@ARM.com */ 40812286Sjose.marinho@arm.com uint64_t add(uint64_t delta); 40912286Sjose.marinho@arm.com 41012286Sjose.marinho@arm.com bool isFiltered() const; 41112286Sjose.marinho@arm.com 41212286Sjose.marinho@arm.com /** 41312286Sjose.marinho@arm.com * Detach the counter from its event 41412286Sjose.marinho@arm.com */ 41512286Sjose.marinho@arm.com void detach(); 41612286Sjose.marinho@arm.com 41712286Sjose.marinho@arm.com /** 41812286Sjose.marinho@arm.com * Attach this counter to an event 41912286Sjose.marinho@arm.com * 42012286Sjose.marinho@arm.com * @param the event to attach the counter to 42112286Sjose.marinho@arm.com */ 42212286Sjose.marinho@arm.com void attach(PMUEvent* event); 42312286Sjose.marinho@arm.com 42412286Sjose.marinho@arm.com /** 42512286Sjose.marinho@arm.com * Obtain the counter id 42612286Sjose.marinho@arm.com * 42712286Sjose.marinho@arm.com * @return the pysical counter id 42812286Sjose.marinho@arm.com */ 42912286Sjose.marinho@arm.com uint64_t getCounterId() const{ 43012286Sjose.marinho@arm.com return counterId; 43112286Sjose.marinho@arm.com } 43212286Sjose.marinho@arm.com 43312286Sjose.marinho@arm.com /** 43412286Sjose.marinho@arm.com * rReturn the counter value 43512286Sjose.marinho@arm.com * 43612286Sjose.marinho@arm.com * @return the counter value 43712286Sjose.marinho@arm.com */ 43812286Sjose.marinho@arm.com uint64_t getValue() const; 43912286Sjose.marinho@arm.com 44012286Sjose.marinho@arm.com /** 44112286Sjose.marinho@arm.com * overwrite the value of the counter 44212286Sjose.marinho@arm.com * 44312286Sjose.marinho@arm.com * @param the new counter value 44412286Sjose.marinho@arm.com */ 44512286Sjose.marinho@arm.com void setValue(uint64_t val); 44610461SAndreas.Sandberg@ARM.com 44710461SAndreas.Sandberg@ARM.com public: /* Serializable state */ 44810461SAndreas.Sandberg@ARM.com /** Counter event ID */ 44910461SAndreas.Sandberg@ARM.com EventTypeId eventId; 45010461SAndreas.Sandberg@ARM.com 45110609Sandreas.sandberg@arm.com /** Filtering settings (evtCount is unused) */ 45210609Sandreas.sandberg@arm.com PMEVTYPER_t filter; 45310609Sandreas.sandberg@arm.com 45410461SAndreas.Sandberg@ARM.com /** Is the counter enabled? */ 45510461SAndreas.Sandberg@ARM.com bool enabled; 45610461SAndreas.Sandberg@ARM.com 45710461SAndreas.Sandberg@ARM.com /** Is this a 64-bit counter? */ 45810461SAndreas.Sandberg@ARM.com bool overflow64; 45910461SAndreas.Sandberg@ARM.com 46012286Sjose.marinho@arm.com protected: /* Configuration */ 46112286Sjose.marinho@arm.com /** PmuEvent currently in use (if any) **/ 46212286Sjose.marinho@arm.com PMUEvent *sourceEvent; 46312286Sjose.marinho@arm.com 46412286Sjose.marinho@arm.com /** id of the counter instance **/ 46512286Sjose.marinho@arm.com uint64_t counterId; 46612286Sjose.marinho@arm.com 46712286Sjose.marinho@arm.com /** Current value of the counter */ 46812286Sjose.marinho@arm.com uint64_t value; 46912286Sjose.marinho@arm.com 47012286Sjose.marinho@arm.com /** Flag keeping track if the counter has been reset **/ 47112286Sjose.marinho@arm.com bool resetValue; 47212286Sjose.marinho@arm.com 47312286Sjose.marinho@arm.com PMU &pmu; 47412286Sjose.marinho@arm.com 47512286Sjose.marinho@arm.com template <typename ...Args> 47612286Sjose.marinho@arm.com void debugCounter(const char* mainString, Args &...args) const { 47712286Sjose.marinho@arm.com 47812286Sjose.marinho@arm.com std::string userString = csprintf(mainString, args...); 47912286Sjose.marinho@arm.com 48012286Sjose.marinho@arm.com warn("[counterId = %d, eventId = %d, sourceEvent = 0x%x] %s", 48112286Sjose.marinho@arm.com counterId, eventId, sourceEvent, userString.c_str()); 48212286Sjose.marinho@arm.com 48312286Sjose.marinho@arm.com } 48410461SAndreas.Sandberg@ARM.com }; 48510461SAndreas.Sandberg@ARM.com 48610461SAndreas.Sandberg@ARM.com /** 48710461SAndreas.Sandberg@ARM.com * Is this a valid counter ID? 48810461SAndreas.Sandberg@ARM.com * 48910461SAndreas.Sandberg@ARM.com * @param id ID of counter within the PMU. 49010461SAndreas.Sandberg@ARM.com * 49110461SAndreas.Sandberg@ARM.com * @return true if counter is within the allowed range or the 49210461SAndreas.Sandberg@ARM.com * cycle counter, false otherwise. 49310461SAndreas.Sandberg@ARM.com */ 49410461SAndreas.Sandberg@ARM.com bool isValidCounter(CounterId id) const { 49510461SAndreas.Sandberg@ARM.com return id < counters.size() || id == PMCCNTR; 49610461SAndreas.Sandberg@ARM.com } 49710461SAndreas.Sandberg@ARM.com 49810461SAndreas.Sandberg@ARM.com /** 49910461SAndreas.Sandberg@ARM.com * Return the state of a counter. 50010461SAndreas.Sandberg@ARM.com * 50110461SAndreas.Sandberg@ARM.com * @param id ID of counter within the PMU. 50210461SAndreas.Sandberg@ARM.com * @return Reference to a CounterState instance representing the 50310461SAndreas.Sandberg@ARM.com * counter. 50410461SAndreas.Sandberg@ARM.com */ 50510461SAndreas.Sandberg@ARM.com CounterState &getCounter(CounterId id) { 50610461SAndreas.Sandberg@ARM.com assert(isValidCounter(id)); 50710461SAndreas.Sandberg@ARM.com return id == PMCCNTR ? cycleCounter : counters[id]; 50810461SAndreas.Sandberg@ARM.com } 50910461SAndreas.Sandberg@ARM.com 51010461SAndreas.Sandberg@ARM.com /** 51110461SAndreas.Sandberg@ARM.com * Return the state of a counter. 51210461SAndreas.Sandberg@ARM.com * 51310461SAndreas.Sandberg@ARM.com * @param id ID of counter within the PMU. 51410461SAndreas.Sandberg@ARM.com * @return Reference to a CounterState instance representing the 51510461SAndreas.Sandberg@ARM.com * counter. 51610461SAndreas.Sandberg@ARM.com */ 51710461SAndreas.Sandberg@ARM.com const CounterState &getCounter(CounterId id) const { 51810461SAndreas.Sandberg@ARM.com assert(isValidCounter(id)); 51910461SAndreas.Sandberg@ARM.com return id == PMCCNTR ? cycleCounter : counters[id]; 52010461SAndreas.Sandberg@ARM.com } 52110461SAndreas.Sandberg@ARM.com 52210461SAndreas.Sandberg@ARM.com /** 52310461SAndreas.Sandberg@ARM.com * Depending on counter configuration, add or remove the probes 52410461SAndreas.Sandberg@ARM.com * driving the counter. 52510461SAndreas.Sandberg@ARM.com * 52610461SAndreas.Sandberg@ARM.com * Look at the state of a counter and (re-)attach the probes 52710461SAndreas.Sandberg@ARM.com * needed to drive a counter if it is currently active. All probes 52810461SAndreas.Sandberg@ARM.com * for the counter are detached if the counter is inactive. 52910461SAndreas.Sandberg@ARM.com * 53010461SAndreas.Sandberg@ARM.com * @param id ID of counter within the PMU. 53110461SAndreas.Sandberg@ARM.com * @param ctr Reference to the counter's state 53210461SAndreas.Sandberg@ARM.com */ 53312286Sjose.marinho@arm.com void updateCounter(CounterState &ctr); 53410461SAndreas.Sandberg@ARM.com 53510461SAndreas.Sandberg@ARM.com /** 53610609Sandreas.sandberg@arm.com * Check if a counter's settings allow it to be counted. 53710609Sandreas.sandberg@arm.com * 53810609Sandreas.sandberg@arm.com * @param ctr Counter state instance representing this counter. 53910609Sandreas.sandberg@arm.com * @return false if the counter is active, true otherwise. 54010609Sandreas.sandberg@arm.com */ 54110609Sandreas.sandberg@arm.com bool isFiltered(const CounterState &ctr) const; 54210609Sandreas.sandberg@arm.com 54310609Sandreas.sandberg@arm.com /** 54410461SAndreas.Sandberg@ARM.com * Call updateCounter() for each counter in the PMU if the 54510461SAndreas.Sandberg@ARM.com * counter's state has changed.. 54610461SAndreas.Sandberg@ARM.com * 54710461SAndreas.Sandberg@ARM.com * @see updateCounter() 54810461SAndreas.Sandberg@ARM.com */ 54910461SAndreas.Sandberg@ARM.com void updateAllCounters(); 55010461SAndreas.Sandberg@ARM.com 55110461SAndreas.Sandberg@ARM.com protected: /* State that needs to be serialized */ 55210461SAndreas.Sandberg@ARM.com /** Performance Monitor Count Enable Register */ 55310461SAndreas.Sandberg@ARM.com MiscReg reg_pmcnten; 55410461SAndreas.Sandberg@ARM.com 55510461SAndreas.Sandberg@ARM.com /** Performance Monitor Control Register */ 55610461SAndreas.Sandberg@ARM.com PMCR_t reg_pmcr; 55710461SAndreas.Sandberg@ARM.com 55810461SAndreas.Sandberg@ARM.com /** Performance Monitor Selection Register */ 55910461SAndreas.Sandberg@ARM.com PMSELR_t reg_pmselr; 56010461SAndreas.Sandberg@ARM.com 56110461SAndreas.Sandberg@ARM.com /** Performance Monitor Interrupt Enable Register */ 56210461SAndreas.Sandberg@ARM.com MiscReg reg_pminten; 56310461SAndreas.Sandberg@ARM.com 56410461SAndreas.Sandberg@ARM.com /** Performance Monitor Overflow Status Register */ 56510461SAndreas.Sandberg@ARM.com MiscReg reg_pmovsr; 56610461SAndreas.Sandberg@ARM.com 56710461SAndreas.Sandberg@ARM.com /** 56810461SAndreas.Sandberg@ARM.com * Performance counter ID register 56910461SAndreas.Sandberg@ARM.com * 57012117Sjose.marinho@arm.com * These registers contain a bitmask of available architected 57110461SAndreas.Sandberg@ARM.com * counters. 57210461SAndreas.Sandberg@ARM.com */ 57312117Sjose.marinho@arm.com uint64_t reg_pmceid0; 57412117Sjose.marinho@arm.com uint64_t reg_pmceid1; 57510461SAndreas.Sandberg@ARM.com 57610461SAndreas.Sandberg@ARM.com /** Remainder part when the clock counter is divided by 64 */ 57710461SAndreas.Sandberg@ARM.com unsigned clock_remainder; 57810461SAndreas.Sandberg@ARM.com 57912286Sjose.marinho@arm.com /** The number of regular event counters **/ 58012286Sjose.marinho@arm.com uint64_t maximumCounterCount; 58112286Sjose.marinho@arm.com 58210461SAndreas.Sandberg@ARM.com /** State of all general-purpose counters supported by PMU */ 58310461SAndreas.Sandberg@ARM.com std::vector<CounterState> counters; 58412286Sjose.marinho@arm.com 58510461SAndreas.Sandberg@ARM.com /** State of the cycle counter */ 58610461SAndreas.Sandberg@ARM.com CounterState cycleCounter; 58710461SAndreas.Sandberg@ARM.com 58812286Sjose.marinho@arm.com /** The id of the counter hardwired to the cpu cycle counter **/ 58912286Sjose.marinho@arm.com const uint64_t cycleCounterEventId; 59012286Sjose.marinho@arm.com 59112286Sjose.marinho@arm.com /** The event that implements the software increment **/ 59212286Sjose.marinho@arm.com SWIncrementEvent *swIncrementEvent; 59312286Sjose.marinho@arm.com 59410461SAndreas.Sandberg@ARM.com protected: /* Configuration and constants */ 59510461SAndreas.Sandberg@ARM.com /** Constant (configuration-dependent) part of the PMCR */ 59610461SAndreas.Sandberg@ARM.com PMCR_t reg_pmcr_conf; 59712286Sjose.marinho@arm.com 59810461SAndreas.Sandberg@ARM.com /** PMCR write mask when accessed from the guest */ 59910461SAndreas.Sandberg@ARM.com static const MiscReg reg_pmcr_wr_mask; 60010461SAndreas.Sandberg@ARM.com 60110461SAndreas.Sandberg@ARM.com /** Performance monitor interrupt number */ 60210461SAndreas.Sandberg@ARM.com const unsigned int pmuInterrupt; 60310461SAndreas.Sandberg@ARM.com /** Platform this device belongs to */ 60410461SAndreas.Sandberg@ARM.com Platform *const platform; 60510461SAndreas.Sandberg@ARM.com 60610461SAndreas.Sandberg@ARM.com /** 60712286Sjose.marinho@arm.com * List of event types supported by this PMU. 60810461SAndreas.Sandberg@ARM.com */ 60912286Sjose.marinho@arm.com std::map<EventTypeId, PMUEvent*> eventMap; 61010461SAndreas.Sandberg@ARM.com}; 61110461SAndreas.Sandberg@ARM.com 61210461SAndreas.Sandberg@ARM.com} // namespace ArmISA 61310461SAndreas.Sandberg@ARM.com#endif 614