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