110461SAndreas.Sandberg@ARM.com/* 212973Sandreas.sandberg@arm.com * Copyright (c) 2011-2014, 2017-2018 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; 6112973Sandreas.sandberg@arm.comclass ArmInterruptPin; 6210461SAndreas.Sandberg@ARM.com 6310461SAndreas.Sandberg@ARM.comnamespace ArmISA { 6410461SAndreas.Sandberg@ARM.com 6510461SAndreas.Sandberg@ARM.com 6610461SAndreas.Sandberg@ARM.com/** 6710461SAndreas.Sandberg@ARM.com * Model of an ARM PMU version 3 6810461SAndreas.Sandberg@ARM.com * 6910461SAndreas.Sandberg@ARM.com * This class implements a subset of the ARM PMU v3 specification as 7010461SAndreas.Sandberg@ARM.com * described in the ARMv8 reference manual. It supports most of the 7110461SAndreas.Sandberg@ARM.com * features of the PMU, however the following features are known to be 7210461SAndreas.Sandberg@ARM.com * missing: 7310461SAndreas.Sandberg@ARM.com * 7410461SAndreas.Sandberg@ARM.com * <ul> 7510461SAndreas.Sandberg@ARM.com * <li>Event filtering (e.g., from different privilege levels). 7610461SAndreas.Sandberg@ARM.com * <li>Access controls (the PMU currently ignores the execution level). 7710461SAndreas.Sandberg@ARM.com * <li>The chain counter (event no. 0x1E) is unimplemented. 7810461SAndreas.Sandberg@ARM.com * </ul> 7910461SAndreas.Sandberg@ARM.com * 8010461SAndreas.Sandberg@ARM.com * The PMU itself does not implement any events, in merely provides an 8110461SAndreas.Sandberg@ARM.com * interface for the configuration scripts to hook up probes that 8210461SAndreas.Sandberg@ARM.com * drive events. Configuration scripts should call addEventProbe() to 8310461SAndreas.Sandberg@ARM.com * configure custom events or high-level methods to configure 8410461SAndreas.Sandberg@ARM.com * architected events. The Python implementation of addEventProbe() 8510461SAndreas.Sandberg@ARM.com * automatically delays event type registration until after 8610461SAndreas.Sandberg@ARM.com * instantiation. 8710461SAndreas.Sandberg@ARM.com * 8810461SAndreas.Sandberg@ARM.com * In order to support CPU switching and some combined counters (e.g., 8910461SAndreas.Sandberg@ARM.com * memory references synthesized from loads and stores), the PMU 9010461SAndreas.Sandberg@ARM.com * allows multiple probes per event type. When creating a system that 9110461SAndreas.Sandberg@ARM.com * switches between CPU models that share the same PMU, PMU events for 9210461SAndreas.Sandberg@ARM.com * all of the CPU models can be registered with the PMU. 9310461SAndreas.Sandberg@ARM.com * 9410461SAndreas.Sandberg@ARM.com * @see The ARM Architecture Refererence Manual (DDI 0487A) 9510461SAndreas.Sandberg@ARM.com * 9610461SAndreas.Sandberg@ARM.com */ 9710461SAndreas.Sandberg@ARM.comclass PMU : public SimObject, public ArmISA::BaseISADevice { 9810461SAndreas.Sandberg@ARM.com public: 9910461SAndreas.Sandberg@ARM.com PMU(const ArmPMUParams *p); 10010461SAndreas.Sandberg@ARM.com ~PMU(); 10110461SAndreas.Sandberg@ARM.com 10210461SAndreas.Sandberg@ARM.com void addEventProbe(unsigned int id, SimObject *obj, const char *name); 10312286Sjose.marinho@arm.com void addSoftwareIncrementEvent(unsigned int id); 10412286Sjose.marinho@arm.com 10512286Sjose.marinho@arm.com void registerEvent(uint32_t id); 10610461SAndreas.Sandberg@ARM.com 10710461SAndreas.Sandberg@ARM.com public: // SimObject and related interfaces 10811168Sandreas.hansson@arm.com void serialize(CheckpointOut &cp) const override; 10911168Sandreas.hansson@arm.com void unserialize(CheckpointIn &cp) override; 11010461SAndreas.Sandberg@ARM.com 11111168Sandreas.hansson@arm.com void drainResume() override; 11210461SAndreas.Sandberg@ARM.com 11312286Sjose.marinho@arm.com void regProbeListeners() override; 11410461SAndreas.Sandberg@ARM.com 11510461SAndreas.Sandberg@ARM.com public: // ISA Device interface 11612973Sandreas.sandberg@arm.com void setThreadContext(ThreadContext *tc) override; 11712973Sandreas.sandberg@arm.com 11810461SAndreas.Sandberg@ARM.com /** 11910461SAndreas.Sandberg@ARM.com * Set a register within the PMU. 12010461SAndreas.Sandberg@ARM.com * 12110461SAndreas.Sandberg@ARM.com * @param misc_reg Register number (see miscregs.hh) 12210461SAndreas.Sandberg@ARM.com * @param val Value to store 12310461SAndreas.Sandberg@ARM.com */ 12413581Sgabeblack@google.com void setMiscReg(int misc_reg, RegVal val) override; 12510461SAndreas.Sandberg@ARM.com /** 12610461SAndreas.Sandberg@ARM.com * Read a register within the PMU. 12710461SAndreas.Sandberg@ARM.com * 12810461SAndreas.Sandberg@ARM.com * @param misc_reg Register number (see miscregs.hh) 12910461SAndreas.Sandberg@ARM.com * @return Register value. 13010461SAndreas.Sandberg@ARM.com */ 13113581Sgabeblack@google.com RegVal readMiscReg(int misc_reg) override; 13210461SAndreas.Sandberg@ARM.com 13310461SAndreas.Sandberg@ARM.com protected: // PMU register types and constants 13410461SAndreas.Sandberg@ARM.com BitUnion32(PMCR_t) 13510461SAndreas.Sandberg@ARM.com // PMU Enable 13610461SAndreas.Sandberg@ARM.com Bitfield<0> e; 13710461SAndreas.Sandberg@ARM.com // Event counter reset 13810461SAndreas.Sandberg@ARM.com Bitfield<1> p; 13910461SAndreas.Sandberg@ARM.com // Cycle counter reset 14010461SAndreas.Sandberg@ARM.com Bitfield<2> c; 14110461SAndreas.Sandberg@ARM.com // Cycle counter divider enable 14210461SAndreas.Sandberg@ARM.com Bitfield<3> d; 14310461SAndreas.Sandberg@ARM.com // Export enable 14410461SAndreas.Sandberg@ARM.com Bitfield<4> x; 14510461SAndreas.Sandberg@ARM.com // Disable PMCCNTR when event counting is prohibited 14610461SAndreas.Sandberg@ARM.com Bitfield<5> dp; 14710461SAndreas.Sandberg@ARM.com // Long Cycle counter enable 14810461SAndreas.Sandberg@ARM.com Bitfield<6> lc; 14910461SAndreas.Sandberg@ARM.com // Number of event counters implemented 15010461SAndreas.Sandberg@ARM.com Bitfield<15, 11> n; 15110461SAndreas.Sandberg@ARM.com // Implementation ID 15210461SAndreas.Sandberg@ARM.com Bitfield<23, 16> idcode; 15310461SAndreas.Sandberg@ARM.com // Implementer code 15410461SAndreas.Sandberg@ARM.com Bitfield<31, 24> imp; 15510461SAndreas.Sandberg@ARM.com EndBitUnion(PMCR_t) 15610461SAndreas.Sandberg@ARM.com 15710461SAndreas.Sandberg@ARM.com BitUnion32(PMSELR_t) 15810461SAndreas.Sandberg@ARM.com // Performance counter selector 15910461SAndreas.Sandberg@ARM.com Bitfield<4, 0> sel; 16010461SAndreas.Sandberg@ARM.com EndBitUnion(PMSELR_t) 16110461SAndreas.Sandberg@ARM.com 16210461SAndreas.Sandberg@ARM.com BitUnion32(PMEVTYPER_t) 16312117Sjose.marinho@arm.com Bitfield<15, 0> evtCount; 16410461SAndreas.Sandberg@ARM.com 16510461SAndreas.Sandberg@ARM.com // Secure EL3 filtering 16610461SAndreas.Sandberg@ARM.com Bitfield<26> m; 16710461SAndreas.Sandberg@ARM.com // Non-secure EL2 mode filtering 16810461SAndreas.Sandberg@ARM.com Bitfield<27> nsh; 16910461SAndreas.Sandberg@ARM.com // Non-secure EL0 mode filtering 17010461SAndreas.Sandberg@ARM.com Bitfield<28> nsu; 17110461SAndreas.Sandberg@ARM.com // Non-secure EL1 mode filtering 17210461SAndreas.Sandberg@ARM.com Bitfield<29> nsk; 17310461SAndreas.Sandberg@ARM.com // EL0 filtering 17410461SAndreas.Sandberg@ARM.com Bitfield<30> u; 17510461SAndreas.Sandberg@ARM.com // EL1 filtering 17610461SAndreas.Sandberg@ARM.com Bitfield<31> p; 17710461SAndreas.Sandberg@ARM.com EndBitUnion(PMEVTYPER_t) 17810461SAndreas.Sandberg@ARM.com 17910461SAndreas.Sandberg@ARM.com /** 18010461SAndreas.Sandberg@ARM.com * Counter ID within the PMU. 18110461SAndreas.Sandberg@ARM.com * 18210461SAndreas.Sandberg@ARM.com * This value is typically used to index into various registers 18310461SAndreas.Sandberg@ARM.com * controlling interrupts and overflows. The value normally in the 18410461SAndreas.Sandberg@ARM.com * [0, 31] range, where 31 refers to the cycle counter. 18510461SAndreas.Sandberg@ARM.com */ 18610461SAndreas.Sandberg@ARM.com typedef unsigned int CounterId; 18710461SAndreas.Sandberg@ARM.com 18810461SAndreas.Sandberg@ARM.com /** Cycle Count Register Number */ 18910461SAndreas.Sandberg@ARM.com static const CounterId PMCCNTR = 31; 19010461SAndreas.Sandberg@ARM.com 19110461SAndreas.Sandberg@ARM.com /** 19210461SAndreas.Sandberg@ARM.com * Event type ID. 19310461SAndreas.Sandberg@ARM.com * 19410461SAndreas.Sandberg@ARM.com * See the PMU documentation for a list of architected IDs. 19510461SAndreas.Sandberg@ARM.com */ 19610461SAndreas.Sandberg@ARM.com typedef unsigned int EventTypeId; 19710461SAndreas.Sandberg@ARM.com 19810461SAndreas.Sandberg@ARM.com protected: /* High-level register and interrupt handling */ 19913581Sgabeblack@google.com RegVal readMiscRegInt(int misc_reg); 20010461SAndreas.Sandberg@ARM.com 20110461SAndreas.Sandberg@ARM.com /** 20210461SAndreas.Sandberg@ARM.com * PMCR write handling 20310461SAndreas.Sandberg@ARM.com * 20410461SAndreas.Sandberg@ARM.com * The PMCR register needs special handling since writing to it 20510461SAndreas.Sandberg@ARM.com * changes PMU-global state (e.g., resets all counters). 20610461SAndreas.Sandberg@ARM.com * 20710461SAndreas.Sandberg@ARM.com * @param val New PMCR value 20810461SAndreas.Sandberg@ARM.com */ 20910461SAndreas.Sandberg@ARM.com void setControlReg(PMCR_t val); 21010461SAndreas.Sandberg@ARM.com 21110461SAndreas.Sandberg@ARM.com /** 21210461SAndreas.Sandberg@ARM.com * Reset all event counters excluding the cycle counter to zero. 21310461SAndreas.Sandberg@ARM.com */ 21410461SAndreas.Sandberg@ARM.com void resetEventCounts(); 21510461SAndreas.Sandberg@ARM.com 21610461SAndreas.Sandberg@ARM.com /** 21710461SAndreas.Sandberg@ARM.com * Deliver a PMU interrupt to the GIC 21810461SAndreas.Sandberg@ARM.com */ 21910461SAndreas.Sandberg@ARM.com void raiseInterrupt(); 22010461SAndreas.Sandberg@ARM.com 22110461SAndreas.Sandberg@ARM.com /** 22213104Sgiacomo.travaglini@arm.com * Clear a PMU interrupt. 22313104Sgiacomo.travaglini@arm.com */ 22413104Sgiacomo.travaglini@arm.com void clearInterrupt(); 22513104Sgiacomo.travaglini@arm.com 22613104Sgiacomo.travaglini@arm.com /** 22710461SAndreas.Sandberg@ARM.com * Get the value of a performance counter. 22810461SAndreas.Sandberg@ARM.com * 22910461SAndreas.Sandberg@ARM.com * This method returns the value of a general purpose performance 23010461SAndreas.Sandberg@ARM.com * counter or the fixed-function cycle counter. Non-existing 23110461SAndreas.Sandberg@ARM.com * counters are treated as constant '0'. 23210461SAndreas.Sandberg@ARM.com * 23310461SAndreas.Sandberg@ARM.com * @return Value of the performance counter, 0 if the counter does 23410461SAndreas.Sandberg@ARM.com * not exist. 23510461SAndreas.Sandberg@ARM.com */ 23610461SAndreas.Sandberg@ARM.com uint64_t getCounterValue(CounterId id) const { 23712286Sjose.marinho@arm.com return isValidCounter(id) ? getCounter(id).getValue() : 0; 23810461SAndreas.Sandberg@ARM.com } 23910461SAndreas.Sandberg@ARM.com 24010461SAndreas.Sandberg@ARM.com /** 24110461SAndreas.Sandberg@ARM.com * Set the value of a performance counter. 24210461SAndreas.Sandberg@ARM.com * 24310461SAndreas.Sandberg@ARM.com * This method sets the value of a general purpose performance 24410461SAndreas.Sandberg@ARM.com * counter or the fixed-function cycle counter. Writes to 24510461SAndreas.Sandberg@ARM.com * non-existing counters are ignored. 24610461SAndreas.Sandberg@ARM.com */ 24710461SAndreas.Sandberg@ARM.com void setCounterValue(CounterId id, uint64_t val); 24810461SAndreas.Sandberg@ARM.com 24910461SAndreas.Sandberg@ARM.com /** 25010461SAndreas.Sandberg@ARM.com * Get the type and filter settings of a counter (PMEVTYPER) 25110461SAndreas.Sandberg@ARM.com * 25210461SAndreas.Sandberg@ARM.com * This method implements a read from a PMEVTYPER register. It 25310461SAndreas.Sandberg@ARM.com * returns the type value and filter settings of a general purpose 25410461SAndreas.Sandberg@ARM.com * performance counter or the cycle counter. Non-existing counters 25510461SAndreas.Sandberg@ARM.com * are treated as constant '0'. 25610461SAndreas.Sandberg@ARM.com * 25710461SAndreas.Sandberg@ARM.com * @param id Counter ID within the PMU. 25810461SAndreas.Sandberg@ARM.com * @return Performance counter type ID. 25910461SAndreas.Sandberg@ARM.com */ 26010461SAndreas.Sandberg@ARM.com PMEVTYPER_t getCounterTypeRegister(CounterId id) const; 26110461SAndreas.Sandberg@ARM.com 26210461SAndreas.Sandberg@ARM.com /** 26310461SAndreas.Sandberg@ARM.com * Set the type and filter settings of a performance counter 26410461SAndreas.Sandberg@ARM.com * (PMEVTYPER) 26510461SAndreas.Sandberg@ARM.com * 26610461SAndreas.Sandberg@ARM.com * This method implements a write to a PMEVTYPER register. It sets 26710461SAndreas.Sandberg@ARM.com * the type value and filter settings of a general purpose 26810461SAndreas.Sandberg@ARM.com * performance counter or the cycle counter. Writes to 26910461SAndreas.Sandberg@ARM.com * non-existing counters are ignored. The method automatically 27010461SAndreas.Sandberg@ARM.com * updates the probes used by the counter if it is enabled. 27110461SAndreas.Sandberg@ARM.com * 27210461SAndreas.Sandberg@ARM.com * @param id Counter ID within the PMU. 27310461SAndreas.Sandberg@ARM.com * @param type Performance counter type and filter configuration.. 27410461SAndreas.Sandberg@ARM.com */ 27510461SAndreas.Sandberg@ARM.com void setCounterTypeRegister(CounterId id, PMEVTYPER_t type); 27610461SAndreas.Sandberg@ARM.com 27713104Sgiacomo.travaglini@arm.com /** 27813104Sgiacomo.travaglini@arm.com * Used for writing the Overflow Flag Status Register (SET/CLR) 27913104Sgiacomo.travaglini@arm.com * 28013104Sgiacomo.travaglini@arm.com * This method implements a write to the PMOVSSET/PMOVSCLR registers. 28113104Sgiacomo.travaglini@arm.com * It is capturing change of state in the register bits so that 28213104Sgiacomo.travaglini@arm.com * the overflow interrupt can be raised/cleared as a side effect 28313104Sgiacomo.travaglini@arm.com * of the write. 28413104Sgiacomo.travaglini@arm.com * 28513104Sgiacomo.travaglini@arm.com * @param new_val New value of the Overflow Status Register 28613104Sgiacomo.travaglini@arm.com */ 28713581Sgabeblack@google.com void setOverflowStatus(RegVal new_val); 28813104Sgiacomo.travaglini@arm.com 28910461SAndreas.Sandberg@ARM.com protected: /* Probe handling and counter state */ 29012286Sjose.marinho@arm.com struct CounterState; 29110461SAndreas.Sandberg@ARM.com 29212286Sjose.marinho@arm.com /** 29312286Sjose.marinho@arm.com * Event definition base class 29412286Sjose.marinho@arm.com */ 29512286Sjose.marinho@arm.com struct PMUEvent { 29612286Sjose.marinho@arm.com 29712286Sjose.marinho@arm.com PMUEvent() {} 29812286Sjose.marinho@arm.com 29912286Sjose.marinho@arm.com virtual ~PMUEvent() {} 30012286Sjose.marinho@arm.com 30112286Sjose.marinho@arm.com /** 30212286Sjose.marinho@arm.com * attach this event to a given counter 30312286Sjose.marinho@arm.com * 30412286Sjose.marinho@arm.com * @param a pointer to the counter where to attach this event 30512286Sjose.marinho@arm.com */ 30612286Sjose.marinho@arm.com void attachEvent(PMU::CounterState *user); 30712286Sjose.marinho@arm.com 30812286Sjose.marinho@arm.com /** 30912286Sjose.marinho@arm.com * detach this event from a given counter 31012286Sjose.marinho@arm.com * 31112286Sjose.marinho@arm.com * @param a pointer to the counter where to detach this event from 31212286Sjose.marinho@arm.com */ 31312286Sjose.marinho@arm.com void detachEvent(PMU::CounterState *user); 31412286Sjose.marinho@arm.com 31512286Sjose.marinho@arm.com /** 31612286Sjose.marinho@arm.com * notify an event increment of val units, all the attached counters' 31712286Sjose.marinho@arm.com * value is incremented by val units. 31812286Sjose.marinho@arm.com * 31912286Sjose.marinho@arm.com * @param the quantity by which to increment the attached counter 32012286Sjose.marinho@arm.com * values 32112286Sjose.marinho@arm.com */ 32212286Sjose.marinho@arm.com virtual void increment(const uint64_t val); 32312286Sjose.marinho@arm.com 32412286Sjose.marinho@arm.com /** 32512286Sjose.marinho@arm.com * Enable the current event 32612286Sjose.marinho@arm.com */ 32712286Sjose.marinho@arm.com virtual void enable() = 0; 32812286Sjose.marinho@arm.com 32912286Sjose.marinho@arm.com /** 33012286Sjose.marinho@arm.com * Disable the current event 33112286Sjose.marinho@arm.com */ 33212286Sjose.marinho@arm.com virtual void disable() = 0; 33312286Sjose.marinho@arm.com 33412286Sjose.marinho@arm.com /** 33512286Sjose.marinho@arm.com * Method called immediately before a counter access in order for 33612286Sjose.marinho@arm.com * the associated event to update its state (if required) 33712286Sjose.marinho@arm.com */ 33812286Sjose.marinho@arm.com virtual void updateAttachedCounters() {} 33912286Sjose.marinho@arm.com 34012286Sjose.marinho@arm.com protected: 34112286Sjose.marinho@arm.com 34212286Sjose.marinho@arm.com /** set of counters using this event **/ 34312286Sjose.marinho@arm.com std::set<PMU::CounterState*> userCounters; 34412286Sjose.marinho@arm.com }; 34512286Sjose.marinho@arm.com 34612286Sjose.marinho@arm.com struct RegularEvent : public PMUEvent { 34712286Sjose.marinho@arm.com typedef std::pair<SimObject*, std::string> EventTypeEntry; 34812286Sjose.marinho@arm.com 34912286Sjose.marinho@arm.com void addMicroarchitectureProbe(SimObject* object, 35012286Sjose.marinho@arm.com std::string name) { 35112286Sjose.marinho@arm.com 35212286Sjose.marinho@arm.com panic_if(!object,"malformed probe-point" 35312286Sjose.marinho@arm.com " definition with name %s\n", name); 35412286Sjose.marinho@arm.com 35512286Sjose.marinho@arm.com microArchitectureEventSet.emplace(object, name); 35610461SAndreas.Sandberg@ARM.com } 35710461SAndreas.Sandberg@ARM.com 35810461SAndreas.Sandberg@ARM.com protected: 35912286Sjose.marinho@arm.com struct RegularProbe: public ProbeListenerArgBase<uint64_t> 36012286Sjose.marinho@arm.com { 36112286Sjose.marinho@arm.com RegularProbe(RegularEvent *parent, SimObject* obj, 36212286Sjose.marinho@arm.com std::string name) 36312286Sjose.marinho@arm.com : ProbeListenerArgBase(obj->getProbeManager(), name), 36412286Sjose.marinho@arm.com parentEvent(parent) {} 36512286Sjose.marinho@arm.com 36612286Sjose.marinho@arm.com RegularProbe() = delete; 36712286Sjose.marinho@arm.com 36812286Sjose.marinho@arm.com void notify(const uint64_t &val); 36912286Sjose.marinho@arm.com 37012286Sjose.marinho@arm.com protected: 37112286Sjose.marinho@arm.com RegularEvent *parentEvent; 37212286Sjose.marinho@arm.com }; 37312286Sjose.marinho@arm.com 37412286Sjose.marinho@arm.com /** The set of events driving the event value **/ 37512286Sjose.marinho@arm.com std::set<EventTypeEntry> microArchitectureEventSet; 37612286Sjose.marinho@arm.com 37712286Sjose.marinho@arm.com /** Set of probe listeners tapping onto each of the input micro-arch 37812286Sjose.marinho@arm.com * events which compose this pmu event 37912286Sjose.marinho@arm.com */ 38012286Sjose.marinho@arm.com std::vector<std::unique_ptr<RegularProbe>> attachedProbePointList; 38112286Sjose.marinho@arm.com 38212286Sjose.marinho@arm.com void enable() override; 38312286Sjose.marinho@arm.com 38412286Sjose.marinho@arm.com void disable() override; 38510461SAndreas.Sandberg@ARM.com }; 38612286Sjose.marinho@arm.com 38712286Sjose.marinho@arm.com class SWIncrementEvent : public PMUEvent 38812286Sjose.marinho@arm.com { 38912286Sjose.marinho@arm.com void enable() override {} 39012286Sjose.marinho@arm.com void disable() override {} 39112286Sjose.marinho@arm.com 39212286Sjose.marinho@arm.com public: 39312286Sjose.marinho@arm.com 39412286Sjose.marinho@arm.com /** 39512286Sjose.marinho@arm.com * write on the sw increment register inducing an increment of the 39612286Sjose.marinho@arm.com * counters with this event selected according to the bitfield written. 39712286Sjose.marinho@arm.com * 39812286Sjose.marinho@arm.com * @param the bitfield selecting the counters to increment. 39912286Sjose.marinho@arm.com */ 40012286Sjose.marinho@arm.com void write(uint64_t val); 40112286Sjose.marinho@arm.com }; 40210461SAndreas.Sandberg@ARM.com 40310461SAndreas.Sandberg@ARM.com /** 40412286Sjose.marinho@arm.com * Obtain the event of a given id 40510461SAndreas.Sandberg@ARM.com * 40612286Sjose.marinho@arm.com * @param the id of the event to obtain 40712286Sjose.marinho@arm.com * @return a pointer to the event with id eventId 40810461SAndreas.Sandberg@ARM.com */ 40912286Sjose.marinho@arm.com PMUEvent* getEvent(uint64_t eventId); 41010461SAndreas.Sandberg@ARM.com 41112286Sjose.marinho@arm.com /** State of a counter within the PMU. **/ 41210905Sandreas.sandberg@arm.com struct CounterState : public Serializable { 41312286Sjose.marinho@arm.com CounterState(PMU &pmuReference, uint64_t counter_id) 41412286Sjose.marinho@arm.com : eventId(0), filter(0), enabled(false), 41512286Sjose.marinho@arm.com overflow64(false), sourceEvent(nullptr), 41612286Sjose.marinho@arm.com counterId(counter_id), value(0), resetValue(false), 41712286Sjose.marinho@arm.com pmu(pmuReference) {} 41810461SAndreas.Sandberg@ARM.com 41911168Sandreas.hansson@arm.com void serialize(CheckpointOut &cp) const override; 42011168Sandreas.hansson@arm.com void unserialize(CheckpointIn &cp) override; 42110461SAndreas.Sandberg@ARM.com 42210461SAndreas.Sandberg@ARM.com /** 42310461SAndreas.Sandberg@ARM.com * Add an event count to the counter and check for overflow. 42410461SAndreas.Sandberg@ARM.com * 42510461SAndreas.Sandberg@ARM.com * @param delta Number of events to add to the counter. 42612286Sjose.marinho@arm.com * @return the quantity remaining until a counter overflow occurs. 42710461SAndreas.Sandberg@ARM.com */ 42812286Sjose.marinho@arm.com uint64_t add(uint64_t delta); 42912286Sjose.marinho@arm.com 43012286Sjose.marinho@arm.com bool isFiltered() const; 43112286Sjose.marinho@arm.com 43212286Sjose.marinho@arm.com /** 43312286Sjose.marinho@arm.com * Detach the counter from its event 43412286Sjose.marinho@arm.com */ 43512286Sjose.marinho@arm.com void detach(); 43612286Sjose.marinho@arm.com 43712286Sjose.marinho@arm.com /** 43812286Sjose.marinho@arm.com * Attach this counter to an event 43912286Sjose.marinho@arm.com * 44012286Sjose.marinho@arm.com * @param the event to attach the counter to 44112286Sjose.marinho@arm.com */ 44212286Sjose.marinho@arm.com void attach(PMUEvent* event); 44312286Sjose.marinho@arm.com 44412286Sjose.marinho@arm.com /** 44512286Sjose.marinho@arm.com * Obtain the counter id 44612286Sjose.marinho@arm.com * 44712286Sjose.marinho@arm.com * @return the pysical counter id 44812286Sjose.marinho@arm.com */ 44912286Sjose.marinho@arm.com uint64_t getCounterId() const{ 45012286Sjose.marinho@arm.com return counterId; 45112286Sjose.marinho@arm.com } 45212286Sjose.marinho@arm.com 45312286Sjose.marinho@arm.com /** 45412286Sjose.marinho@arm.com * rReturn the counter value 45512286Sjose.marinho@arm.com * 45612286Sjose.marinho@arm.com * @return the counter value 45712286Sjose.marinho@arm.com */ 45812286Sjose.marinho@arm.com uint64_t getValue() const; 45912286Sjose.marinho@arm.com 46012286Sjose.marinho@arm.com /** 46112286Sjose.marinho@arm.com * overwrite the value of the counter 46212286Sjose.marinho@arm.com * 46312286Sjose.marinho@arm.com * @param the new counter value 46412286Sjose.marinho@arm.com */ 46512286Sjose.marinho@arm.com void setValue(uint64_t val); 46610461SAndreas.Sandberg@ARM.com 46710461SAndreas.Sandberg@ARM.com public: /* Serializable state */ 46810461SAndreas.Sandberg@ARM.com /** Counter event ID */ 46910461SAndreas.Sandberg@ARM.com EventTypeId eventId; 47010461SAndreas.Sandberg@ARM.com 47110609Sandreas.sandberg@arm.com /** Filtering settings (evtCount is unused) */ 47210609Sandreas.sandberg@arm.com PMEVTYPER_t filter; 47310609Sandreas.sandberg@arm.com 47410461SAndreas.Sandberg@ARM.com /** Is the counter enabled? */ 47510461SAndreas.Sandberg@ARM.com bool enabled; 47610461SAndreas.Sandberg@ARM.com 47710461SAndreas.Sandberg@ARM.com /** Is this a 64-bit counter? */ 47810461SAndreas.Sandberg@ARM.com bool overflow64; 47910461SAndreas.Sandberg@ARM.com 48012286Sjose.marinho@arm.com protected: /* Configuration */ 48112286Sjose.marinho@arm.com /** PmuEvent currently in use (if any) **/ 48212286Sjose.marinho@arm.com PMUEvent *sourceEvent; 48312286Sjose.marinho@arm.com 48412286Sjose.marinho@arm.com /** id of the counter instance **/ 48512286Sjose.marinho@arm.com uint64_t counterId; 48612286Sjose.marinho@arm.com 48712286Sjose.marinho@arm.com /** Current value of the counter */ 48812286Sjose.marinho@arm.com uint64_t value; 48912286Sjose.marinho@arm.com 49012286Sjose.marinho@arm.com /** Flag keeping track if the counter has been reset **/ 49112286Sjose.marinho@arm.com bool resetValue; 49212286Sjose.marinho@arm.com 49312286Sjose.marinho@arm.com PMU &pmu; 49412286Sjose.marinho@arm.com 49512286Sjose.marinho@arm.com template <typename ...Args> 49612286Sjose.marinho@arm.com void debugCounter(const char* mainString, Args &...args) const { 49712286Sjose.marinho@arm.com 49812286Sjose.marinho@arm.com std::string userString = csprintf(mainString, args...); 49912286Sjose.marinho@arm.com 50012286Sjose.marinho@arm.com warn("[counterId = %d, eventId = %d, sourceEvent = 0x%x] %s", 50112286Sjose.marinho@arm.com counterId, eventId, sourceEvent, userString.c_str()); 50212286Sjose.marinho@arm.com 50312286Sjose.marinho@arm.com } 50410461SAndreas.Sandberg@ARM.com }; 50510461SAndreas.Sandberg@ARM.com 50610461SAndreas.Sandberg@ARM.com /** 50710461SAndreas.Sandberg@ARM.com * Is this a valid counter ID? 50810461SAndreas.Sandberg@ARM.com * 50910461SAndreas.Sandberg@ARM.com * @param id ID of counter within the PMU. 51010461SAndreas.Sandberg@ARM.com * 51110461SAndreas.Sandberg@ARM.com * @return true if counter is within the allowed range or the 51210461SAndreas.Sandberg@ARM.com * cycle counter, false otherwise. 51310461SAndreas.Sandberg@ARM.com */ 51410461SAndreas.Sandberg@ARM.com bool isValidCounter(CounterId id) const { 51510461SAndreas.Sandberg@ARM.com return id < counters.size() || id == PMCCNTR; 51610461SAndreas.Sandberg@ARM.com } 51710461SAndreas.Sandberg@ARM.com 51810461SAndreas.Sandberg@ARM.com /** 51910461SAndreas.Sandberg@ARM.com * Return the state of a counter. 52010461SAndreas.Sandberg@ARM.com * 52110461SAndreas.Sandberg@ARM.com * @param id ID of counter within the PMU. 52210461SAndreas.Sandberg@ARM.com * @return Reference to a CounterState instance representing the 52310461SAndreas.Sandberg@ARM.com * counter. 52410461SAndreas.Sandberg@ARM.com */ 52510461SAndreas.Sandberg@ARM.com CounterState &getCounter(CounterId id) { 52610461SAndreas.Sandberg@ARM.com assert(isValidCounter(id)); 52710461SAndreas.Sandberg@ARM.com return id == PMCCNTR ? cycleCounter : counters[id]; 52810461SAndreas.Sandberg@ARM.com } 52910461SAndreas.Sandberg@ARM.com 53010461SAndreas.Sandberg@ARM.com /** 53110461SAndreas.Sandberg@ARM.com * Return the state of a counter. 53210461SAndreas.Sandberg@ARM.com * 53310461SAndreas.Sandberg@ARM.com * @param id ID of counter within the PMU. 53410461SAndreas.Sandberg@ARM.com * @return Reference to a CounterState instance representing the 53510461SAndreas.Sandberg@ARM.com * counter. 53610461SAndreas.Sandberg@ARM.com */ 53710461SAndreas.Sandberg@ARM.com const CounterState &getCounter(CounterId id) const { 53810461SAndreas.Sandberg@ARM.com assert(isValidCounter(id)); 53910461SAndreas.Sandberg@ARM.com return id == PMCCNTR ? cycleCounter : counters[id]; 54010461SAndreas.Sandberg@ARM.com } 54110461SAndreas.Sandberg@ARM.com 54210461SAndreas.Sandberg@ARM.com /** 54310461SAndreas.Sandberg@ARM.com * Depending on counter configuration, add or remove the probes 54410461SAndreas.Sandberg@ARM.com * driving the counter. 54510461SAndreas.Sandberg@ARM.com * 54610461SAndreas.Sandberg@ARM.com * Look at the state of a counter and (re-)attach the probes 54710461SAndreas.Sandberg@ARM.com * needed to drive a counter if it is currently active. All probes 54810461SAndreas.Sandberg@ARM.com * for the counter are detached if the counter is inactive. 54910461SAndreas.Sandberg@ARM.com * 55010461SAndreas.Sandberg@ARM.com * @param id ID of counter within the PMU. 55110461SAndreas.Sandberg@ARM.com * @param ctr Reference to the counter's state 55210461SAndreas.Sandberg@ARM.com */ 55312286Sjose.marinho@arm.com void updateCounter(CounterState &ctr); 55410461SAndreas.Sandberg@ARM.com 55510461SAndreas.Sandberg@ARM.com /** 55610609Sandreas.sandberg@arm.com * Check if a counter's settings allow it to be counted. 55710609Sandreas.sandberg@arm.com * 55810609Sandreas.sandberg@arm.com * @param ctr Counter state instance representing this counter. 55910609Sandreas.sandberg@arm.com * @return false if the counter is active, true otherwise. 56010609Sandreas.sandberg@arm.com */ 56110609Sandreas.sandberg@arm.com bool isFiltered(const CounterState &ctr) const; 56210609Sandreas.sandberg@arm.com 56310609Sandreas.sandberg@arm.com /** 56410461SAndreas.Sandberg@ARM.com * Call updateCounter() for each counter in the PMU if the 56510461SAndreas.Sandberg@ARM.com * counter's state has changed.. 56610461SAndreas.Sandberg@ARM.com * 56710461SAndreas.Sandberg@ARM.com * @see updateCounter() 56810461SAndreas.Sandberg@ARM.com */ 56910461SAndreas.Sandberg@ARM.com void updateAllCounters(); 57010461SAndreas.Sandberg@ARM.com 57110461SAndreas.Sandberg@ARM.com protected: /* State that needs to be serialized */ 57210461SAndreas.Sandberg@ARM.com /** Performance Monitor Count Enable Register */ 57313581Sgabeblack@google.com RegVal reg_pmcnten; 57410461SAndreas.Sandberg@ARM.com 57510461SAndreas.Sandberg@ARM.com /** Performance Monitor Control Register */ 57610461SAndreas.Sandberg@ARM.com PMCR_t reg_pmcr; 57710461SAndreas.Sandberg@ARM.com 57810461SAndreas.Sandberg@ARM.com /** Performance Monitor Selection Register */ 57910461SAndreas.Sandberg@ARM.com PMSELR_t reg_pmselr; 58010461SAndreas.Sandberg@ARM.com 58110461SAndreas.Sandberg@ARM.com /** Performance Monitor Interrupt Enable Register */ 58213581Sgabeblack@google.com RegVal reg_pminten; 58310461SAndreas.Sandberg@ARM.com 58410461SAndreas.Sandberg@ARM.com /** Performance Monitor Overflow Status Register */ 58513581Sgabeblack@google.com RegVal reg_pmovsr; 58610461SAndreas.Sandberg@ARM.com 58710461SAndreas.Sandberg@ARM.com /** 58810461SAndreas.Sandberg@ARM.com * Performance counter ID register 58910461SAndreas.Sandberg@ARM.com * 59012117Sjose.marinho@arm.com * These registers contain a bitmask of available architected 59110461SAndreas.Sandberg@ARM.com * counters. 59210461SAndreas.Sandberg@ARM.com */ 59312117Sjose.marinho@arm.com uint64_t reg_pmceid0; 59412117Sjose.marinho@arm.com uint64_t reg_pmceid1; 59510461SAndreas.Sandberg@ARM.com 59610461SAndreas.Sandberg@ARM.com /** Remainder part when the clock counter is divided by 64 */ 59710461SAndreas.Sandberg@ARM.com unsigned clock_remainder; 59810461SAndreas.Sandberg@ARM.com 59912286Sjose.marinho@arm.com /** The number of regular event counters **/ 60012286Sjose.marinho@arm.com uint64_t maximumCounterCount; 60112286Sjose.marinho@arm.com 60210461SAndreas.Sandberg@ARM.com /** State of all general-purpose counters supported by PMU */ 60310461SAndreas.Sandberg@ARM.com std::vector<CounterState> counters; 60412286Sjose.marinho@arm.com 60510461SAndreas.Sandberg@ARM.com /** State of the cycle counter */ 60610461SAndreas.Sandberg@ARM.com CounterState cycleCounter; 60710461SAndreas.Sandberg@ARM.com 60812286Sjose.marinho@arm.com /** The id of the counter hardwired to the cpu cycle counter **/ 60912286Sjose.marinho@arm.com const uint64_t cycleCounterEventId; 61012286Sjose.marinho@arm.com 61112286Sjose.marinho@arm.com /** The event that implements the software increment **/ 61212286Sjose.marinho@arm.com SWIncrementEvent *swIncrementEvent; 61312286Sjose.marinho@arm.com 61410461SAndreas.Sandberg@ARM.com protected: /* Configuration and constants */ 61510461SAndreas.Sandberg@ARM.com /** Constant (configuration-dependent) part of the PMCR */ 61610461SAndreas.Sandberg@ARM.com PMCR_t reg_pmcr_conf; 61712286Sjose.marinho@arm.com 61810461SAndreas.Sandberg@ARM.com /** PMCR write mask when accessed from the guest */ 61913581Sgabeblack@google.com static const RegVal reg_pmcr_wr_mask; 62010461SAndreas.Sandberg@ARM.com 62110461SAndreas.Sandberg@ARM.com /** Performance monitor interrupt number */ 62213638Sgiacomo.travaglini@arm.com ArmInterruptPin *interrupt; 62310461SAndreas.Sandberg@ARM.com 62410461SAndreas.Sandberg@ARM.com /** 62512286Sjose.marinho@arm.com * List of event types supported by this PMU. 62610461SAndreas.Sandberg@ARM.com */ 62712286Sjose.marinho@arm.com std::map<EventTypeId, PMUEvent*> eventMap; 62810461SAndreas.Sandberg@ARM.com}; 62910461SAndreas.Sandberg@ARM.com 63010461SAndreas.Sandberg@ARM.com} // namespace ArmISA 63110461SAndreas.Sandberg@ARM.com#endif 632