110023Smatt.horsnell@ARM.com/*
210023Smatt.horsnell@ARM.com * Copyright (c) 2013 ARM Limited
310023Smatt.horsnell@ARM.com * All rights reserved
410023Smatt.horsnell@ARM.com *
510023Smatt.horsnell@ARM.com * The license below extends only to copyright in the software and shall
610023Smatt.horsnell@ARM.com * not be construed as granting a license to any other intellectual
710023Smatt.horsnell@ARM.com * property including but not limited to intellectual property relating
810023Smatt.horsnell@ARM.com * to a hardware implementation of the functionality of the software
910023Smatt.horsnell@ARM.com * licensed hereunder.  You may use the software subject to the license
1010023Smatt.horsnell@ARM.com * terms below provided that you ensure that this notice is replicated
1110023Smatt.horsnell@ARM.com * unmodified and in its entirety in all distributions of the software,
1210023Smatt.horsnell@ARM.com * modified or unmodified, in source code or in binary form.
1310023Smatt.horsnell@ARM.com *
1410023Smatt.horsnell@ARM.com * Redistribution and use in source and binary forms, with or without
1510023Smatt.horsnell@ARM.com * modification, are permitted provided that the following conditions are
1610023Smatt.horsnell@ARM.com * met: redistributions of source code must retain the above copyright
1710023Smatt.horsnell@ARM.com * notice, this list of conditions and the following disclaimer;
1810023Smatt.horsnell@ARM.com * redistributions in binary form must reproduce the above copyright
1910023Smatt.horsnell@ARM.com * notice, this list of conditions and the following disclaimer in the
2010023Smatt.horsnell@ARM.com * documentation and/or other materials provided with the distribution;
2110023Smatt.horsnell@ARM.com * neither the name of the copyright holders nor the names of its
2210023Smatt.horsnell@ARM.com * contributors may be used to endorse or promote products derived from
2310023Smatt.horsnell@ARM.com * this software without specific prior written permission.
2410023Smatt.horsnell@ARM.com *
2510023Smatt.horsnell@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2610023Smatt.horsnell@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2710023Smatt.horsnell@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2810023Smatt.horsnell@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2910023Smatt.horsnell@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3010023Smatt.horsnell@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3110023Smatt.horsnell@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3210023Smatt.horsnell@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3310023Smatt.horsnell@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3410023Smatt.horsnell@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3510023Smatt.horsnell@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3610023Smatt.horsnell@ARM.com *
3710023Smatt.horsnell@ARM.com * Authors: Matt Horsnell
3810023Smatt.horsnell@ARM.com  */
3910023Smatt.horsnell@ARM.com
4010023Smatt.horsnell@ARM.com/**
4110023Smatt.horsnell@ARM.com * @file This file describes the base components used for the probe system.
4210023Smatt.horsnell@ARM.com * There are currently 3 components:
4310023Smatt.horsnell@ARM.com *
4410023Smatt.horsnell@ARM.com * ProbePoint:          an event probe point i.e. send a notify from the point
4510023Smatt.horsnell@ARM.com *                      at which an instruction was committed.
4610023Smatt.horsnell@ARM.com *
4710023Smatt.horsnell@ARM.com * ProbeListener:       a listener provide a notify method that is called when
4810023Smatt.horsnell@ARM.com *                      a probe point event occurs. Multiple ProbeListeners
4910023Smatt.horsnell@ARM.com *                      can be added to each ProbePoint.
5010023Smatt.horsnell@ARM.com *
5110023Smatt.horsnell@ARM.com * ProbeListenerObject: a wrapper around a SimObject that can connect to another
5210023Smatt.horsnell@ARM.com *                      SimObject on which is will add ProbeListeners.
5310023Smatt.horsnell@ARM.com *
5410023Smatt.horsnell@ARM.com * ProbeManager:        used to match up ProbeListeners and ProbePoints.
5510023Smatt.horsnell@ARM.com *                      At <b>simulation init</b> this is handled by regProbePoints
5610023Smatt.horsnell@ARM.com *                      followed by regProbeListeners being called on each
5710023Smatt.horsnell@ARM.com *                      SimObject in hierarchical ordering.
5810023Smatt.horsnell@ARM.com *                      ProbeListeners can be added/removed dynamically at runtime.
5910023Smatt.horsnell@ARM.com */
6010023Smatt.horsnell@ARM.com
6110023Smatt.horsnell@ARM.com#ifndef __SIM_PROBE_PROBE_HH__
6210023Smatt.horsnell@ARM.com#define __SIM_PROBE_PROBE_HH__
6310023Smatt.horsnell@ARM.com
6410023Smatt.horsnell@ARM.com#include <string>
6510023Smatt.horsnell@ARM.com#include <vector>
6610023Smatt.horsnell@ARM.com
6711800Sbrandon.potter@amd.com#include "base/compiler.hh"
6810023Smatt.horsnell@ARM.com#include "base/trace.hh"
6910023Smatt.horsnell@ARM.com#include "sim/sim_object.hh"
7010023Smatt.horsnell@ARM.com
7110023Smatt.horsnell@ARM.com/** Forward declare the ProbeManager. */
7210023Smatt.horsnell@ARM.comclass ProbeManager;
7310023Smatt.horsnell@ARM.comclass ProbeListener;
7411800Sbrandon.potter@amd.comclass ProbeListenerObjectParams;
7510023Smatt.horsnell@ARM.com
7610023Smatt.horsnell@ARM.com/**
7710460SAndreas.Sandberg@ARM.com * Name space containing shared probe point declarations.
7810460SAndreas.Sandberg@ARM.com *
7910460SAndreas.Sandberg@ARM.com * Probe types that are shared between multiple types of SimObjects
8010460SAndreas.Sandberg@ARM.com * should live in this name space. This makes it possible to use a
8110460SAndreas.Sandberg@ARM.com * common instrumentation interface for devices such as PMUs that have
8210460SAndreas.Sandberg@ARM.com * different implementations in different ISAs.
8310460SAndreas.Sandberg@ARM.com */
8410460SAndreas.Sandberg@ARM.comnamespace ProbePoints {
8510460SAndreas.Sandberg@ARM.com/* Note: This is only here for documentation purposes, new probe
8610460SAndreas.Sandberg@ARM.com * points should normally be declared in their own header files. See
8710460SAndreas.Sandberg@ARM.com * for example pmu.hh.
8810460SAndreas.Sandberg@ARM.com */
8910460SAndreas.Sandberg@ARM.com}
9010460SAndreas.Sandberg@ARM.com
9110460SAndreas.Sandberg@ARM.com/**
9210023Smatt.horsnell@ARM.com * This class is a minimal wrapper around SimObject. It is used to declare
9310023Smatt.horsnell@ARM.com * a python derived object that can be added as a ProbeListener to any other
9410023Smatt.horsnell@ARM.com * SimObject.
9510023Smatt.horsnell@ARM.com *
9610023Smatt.horsnell@ARM.com * It instantiates manager from a call to Parent.any.
9710023Smatt.horsnell@ARM.com * The vector of listeners is used simply to hold onto listeners until the
9810023Smatt.horsnell@ARM.com * ProbeListenerObject is destroyed.
9910023Smatt.horsnell@ARM.com */
10010023Smatt.horsnell@ARM.comclass ProbeListenerObject : public SimObject
10110023Smatt.horsnell@ARM.com{
10210023Smatt.horsnell@ARM.com  protected:
10310023Smatt.horsnell@ARM.com    ProbeManager *manager;
10410023Smatt.horsnell@ARM.com    std::vector<ProbeListener *> listeners;
10510023Smatt.horsnell@ARM.com
10610023Smatt.horsnell@ARM.com  public:
10710023Smatt.horsnell@ARM.com    ProbeListenerObject(const ProbeListenerObjectParams *params);
10810023Smatt.horsnell@ARM.com    virtual ~ProbeListenerObject();
10910023Smatt.horsnell@ARM.com    ProbeManager* getProbeManager() { return manager; }
11010023Smatt.horsnell@ARM.com};
11110023Smatt.horsnell@ARM.com
11210023Smatt.horsnell@ARM.com/**
11310023Smatt.horsnell@ARM.com * ProbeListener base class; here to simplify things like containers
11410023Smatt.horsnell@ARM.com * containing multiple types of ProbeListener.
11510023Smatt.horsnell@ARM.com *
11610023Smatt.horsnell@ARM.com * Note a ProbeListener is added to the ProbePoint in constructor by
11710023Smatt.horsnell@ARM.com * using the ProbeManager passed in.
11810023Smatt.horsnell@ARM.com */
11910023Smatt.horsnell@ARM.comclass ProbeListener
12010023Smatt.horsnell@ARM.com{
12110023Smatt.horsnell@ARM.com  public:
12210023Smatt.horsnell@ARM.com    ProbeListener(ProbeManager *manager, const std::string &name);
12310365SAndreas.Sandberg@ARM.com    virtual ~ProbeListener();
12410365SAndreas.Sandberg@ARM.com
12510365SAndreas.Sandberg@ARM.com  protected:
12610365SAndreas.Sandberg@ARM.com    ProbeManager *const manager;
12710365SAndreas.Sandberg@ARM.com    const std::string name;
12810023Smatt.horsnell@ARM.com};
12910023Smatt.horsnell@ARM.com
13010023Smatt.horsnell@ARM.com/**
13110023Smatt.horsnell@ARM.com * ProbeListener base class; again used to simplify use of ProbePoints
13210023Smatt.horsnell@ARM.com * in containers and used as to define interface for adding removing
13310023Smatt.horsnell@ARM.com * listeners to the ProbePoint.
13410023Smatt.horsnell@ARM.com */
13510023Smatt.horsnell@ARM.comclass ProbePoint
13610023Smatt.horsnell@ARM.com{
13710023Smatt.horsnell@ARM.com  protected:
13810023Smatt.horsnell@ARM.com    const std::string name;
13910023Smatt.horsnell@ARM.com  public:
14010023Smatt.horsnell@ARM.com    ProbePoint(ProbeManager *manager, const std::string &name);
14110023Smatt.horsnell@ARM.com    virtual ~ProbePoint() {}
14210023Smatt.horsnell@ARM.com
14310023Smatt.horsnell@ARM.com    virtual void addListener(ProbeListener *listener) = 0;
14410023Smatt.horsnell@ARM.com    virtual void removeListener(ProbeListener *listener) = 0;
14510023Smatt.horsnell@ARM.com    std::string getName() const { return name; }
14610023Smatt.horsnell@ARM.com};
14710023Smatt.horsnell@ARM.com
14810023Smatt.horsnell@ARM.com/**
14910023Smatt.horsnell@ARM.com * ProbeManager is a conduit class that lives on each SimObject,
15010023Smatt.horsnell@ARM.com *  and is used to match up probe listeners with probe points.
15110023Smatt.horsnell@ARM.com */
15210023Smatt.horsnell@ARM.comclass ProbeManager
15310023Smatt.horsnell@ARM.com{
15410023Smatt.horsnell@ARM.com  private:
15510023Smatt.horsnell@ARM.com    /** Required for sensible debug messages.*/
15610104Smitch.hayenga@arm.com    const M5_CLASS_VAR_USED SimObject *object;
15710023Smatt.horsnell@ARM.com    /** Vector for name look-up. */
15810023Smatt.horsnell@ARM.com    std::vector<ProbePoint *> points;
15910023Smatt.horsnell@ARM.com
16010023Smatt.horsnell@ARM.com  public:
16110023Smatt.horsnell@ARM.com    ProbeManager(SimObject *obj)
16210023Smatt.horsnell@ARM.com        : object(obj)
16310023Smatt.horsnell@ARM.com    {}
16410023Smatt.horsnell@ARM.com    virtual ~ProbeManager() {}
16510023Smatt.horsnell@ARM.com
16610023Smatt.horsnell@ARM.com    /**
16710023Smatt.horsnell@ARM.com     * @brief Add a ProbeListener to the ProbePoint named by pointName.
16810023Smatt.horsnell@ARM.com     *        If the name doesn't resolve a ProbePoint return false.
16910023Smatt.horsnell@ARM.com     * @param pointName the name of the ProbePoint to add the ProbeListener to.
17010023Smatt.horsnell@ARM.com     * @param listener the ProbeListener to add.
17110023Smatt.horsnell@ARM.com     * @return true if added, false otherwise.
17210023Smatt.horsnell@ARM.com     */
17310023Smatt.horsnell@ARM.com    bool addListener(std::string pointName, ProbeListener &listener);
17410023Smatt.horsnell@ARM.com
17510023Smatt.horsnell@ARM.com    /**
17610023Smatt.horsnell@ARM.com     * @brief Remove a ProbeListener from the ProbePoint named by pointName.
17710023Smatt.horsnell@ARM.com     *        If the name doesn't resolve a ProbePoint return false.
17810023Smatt.horsnell@ARM.com     * @param pointName the name of the ProbePoint to remove the ProbeListener
17910023Smatt.horsnell@ARM.com     *        from.
18010023Smatt.horsnell@ARM.com     * @param listener the ProbeListener to remove.
18110023Smatt.horsnell@ARM.com     * @return true if removed, false otherwise.
18210023Smatt.horsnell@ARM.com     */
18310023Smatt.horsnell@ARM.com    bool removeListener(std::string pointName, ProbeListener &listener);
18410023Smatt.horsnell@ARM.com
18510023Smatt.horsnell@ARM.com    /**
18610023Smatt.horsnell@ARM.com     * @brief Add a ProbePoint to this SimObject ProbeManager.
18710023Smatt.horsnell@ARM.com     * @param point the ProbePoint to add.
18810023Smatt.horsnell@ARM.com     */
18910023Smatt.horsnell@ARM.com    void addPoint(ProbePoint &point);
19010023Smatt.horsnell@ARM.com};
19110023Smatt.horsnell@ARM.com
19210023Smatt.horsnell@ARM.com/**
19310023Smatt.horsnell@ARM.com * ProbeListenerArgBase is used to define the base interface to a
19410023Smatt.horsnell@ARM.com * ProbeListenerArg (i.e the notify method on specific type).
19510023Smatt.horsnell@ARM.com *
19610023Smatt.horsnell@ARM.com * It is necessary to split this out from ProbeListenerArg, as that
19710023Smatt.horsnell@ARM.com * templates off the class containing the function that notify calls.
19810023Smatt.horsnell@ARM.com */
19910023Smatt.horsnell@ARM.comtemplate <class Arg>
20010023Smatt.horsnell@ARM.comclass ProbeListenerArgBase : public ProbeListener
20110023Smatt.horsnell@ARM.com{
20210023Smatt.horsnell@ARM.com  public:
20310023Smatt.horsnell@ARM.com    ProbeListenerArgBase(ProbeManager *pm, const std::string &name)
20410023Smatt.horsnell@ARM.com        : ProbeListener(pm, name)
20510023Smatt.horsnell@ARM.com    {}
20610023Smatt.horsnell@ARM.com    virtual void notify(const Arg &val) = 0;
20710023Smatt.horsnell@ARM.com};
20810023Smatt.horsnell@ARM.com
20910023Smatt.horsnell@ARM.com/**
21010023Smatt.horsnell@ARM.com * ProbeListenerArg generates a listener for the class of Arg and the
21110023Smatt.horsnell@ARM.com * class type T which is the class containing the function that notify will
21210023Smatt.horsnell@ARM.com * call.
21310023Smatt.horsnell@ARM.com *
21410023Smatt.horsnell@ARM.com * Note that the function is passed as a pointer on construction.
21510023Smatt.horsnell@ARM.com */
21610023Smatt.horsnell@ARM.comtemplate <class T, class Arg>
21710023Smatt.horsnell@ARM.comclass ProbeListenerArg : public ProbeListenerArgBase<Arg>
21810023Smatt.horsnell@ARM.com{
21910023Smatt.horsnell@ARM.com  private:
22010023Smatt.horsnell@ARM.com    T *object;
22110023Smatt.horsnell@ARM.com    void (T::* function)(const Arg &);
22210023Smatt.horsnell@ARM.com
22310023Smatt.horsnell@ARM.com  public:
22410023Smatt.horsnell@ARM.com    /**
22510023Smatt.horsnell@ARM.com     * @param obj the class of type Tcontaining the method to call on notify.
22610023Smatt.horsnell@ARM.com     * @param name the name of the ProbePoint to add this listener to.
22710023Smatt.horsnell@ARM.com     * @param func a pointer to the function on obj (called on notify).
22810023Smatt.horsnell@ARM.com     */
22910023Smatt.horsnell@ARM.com    ProbeListenerArg(T *obj, const std::string &name, void (T::* func)(const Arg &))
23010023Smatt.horsnell@ARM.com        : ProbeListenerArgBase<Arg>(obj->getProbeManager(), name),
23110023Smatt.horsnell@ARM.com          object(obj),
23210023Smatt.horsnell@ARM.com          function(func)
23310023Smatt.horsnell@ARM.com    {}
23410023Smatt.horsnell@ARM.com
23510023Smatt.horsnell@ARM.com    /**
23610023Smatt.horsnell@ARM.com     * @brief called when the ProbePoint calls notify. This is a shim through to
23710023Smatt.horsnell@ARM.com     *        the function passed during construction.
23810023Smatt.horsnell@ARM.com     * @param val the argument value to pass.
23910023Smatt.horsnell@ARM.com     */
24010023Smatt.horsnell@ARM.com    virtual void notify(const Arg &val) { (object->*function)(val); }
24110023Smatt.horsnell@ARM.com};
24210023Smatt.horsnell@ARM.com
24310023Smatt.horsnell@ARM.com/**
24410023Smatt.horsnell@ARM.com * ProbePointArg generates a point for the class of Arg. As ProbePointArgs talk
24510023Smatt.horsnell@ARM.com * directly to ProbeListenerArgs of the same type, we can store the vector of
24610023Smatt.horsnell@ARM.com * ProbeListeners as their Arg type (and not as base type).
24710023Smatt.horsnell@ARM.com *
24810023Smatt.horsnell@ARM.com * Methods are provided to addListener, removeListener and notify.
24910023Smatt.horsnell@ARM.com */
25010023Smatt.horsnell@ARM.comtemplate <typename Arg>
25110023Smatt.horsnell@ARM.comclass ProbePointArg : public ProbePoint
25210023Smatt.horsnell@ARM.com{
25310023Smatt.horsnell@ARM.com    /** The attached listeners. */
25410023Smatt.horsnell@ARM.com    std::vector<ProbeListenerArgBase<Arg> *> listeners;
25510023Smatt.horsnell@ARM.com
25610023Smatt.horsnell@ARM.com  public:
25710023Smatt.horsnell@ARM.com    ProbePointArg(ProbeManager *manager, std::string name)
25810023Smatt.horsnell@ARM.com        : ProbePoint(manager, name)
25910023Smatt.horsnell@ARM.com    {
26010023Smatt.horsnell@ARM.com    }
26110023Smatt.horsnell@ARM.com
26210023Smatt.horsnell@ARM.com    /**
26310023Smatt.horsnell@ARM.com     * @brief adds a ProbeListener to this ProbePoints notify list.
26410023Smatt.horsnell@ARM.com     * @param l the ProbeListener to add to the notify list.
26510023Smatt.horsnell@ARM.com     */
26610023Smatt.horsnell@ARM.com    void addListener(ProbeListener *l)
26710023Smatt.horsnell@ARM.com    {
26810023Smatt.horsnell@ARM.com        // check listener not already added
26910023Smatt.horsnell@ARM.com        if (std::find(listeners.begin(), listeners.end(), l) == listeners.end()) {
27010023Smatt.horsnell@ARM.com            listeners.push_back(static_cast<ProbeListenerArgBase<Arg> *>(l));
27110023Smatt.horsnell@ARM.com        }
27210023Smatt.horsnell@ARM.com    }
27310023Smatt.horsnell@ARM.com
27410023Smatt.horsnell@ARM.com    /**
27510023Smatt.horsnell@ARM.com     * @brief remove a ProbeListener from this ProbePoints notify list.
27610023Smatt.horsnell@ARM.com     * @param l the ProbeListener to remove from the notify list.
27710023Smatt.horsnell@ARM.com     */
27810023Smatt.horsnell@ARM.com    void removeListener(ProbeListener *l)
27910023Smatt.horsnell@ARM.com    {
28010023Smatt.horsnell@ARM.com        listeners.erase(std::remove(listeners.begin(), listeners.end(), l),
28110023Smatt.horsnell@ARM.com                        listeners.end());
28210023Smatt.horsnell@ARM.com    }
28310023Smatt.horsnell@ARM.com
28410023Smatt.horsnell@ARM.com    /**
28510023Smatt.horsnell@ARM.com     * @brief called at the ProbePoint call site, passes arg to each listener.
28610023Smatt.horsnell@ARM.com     * @param arg the argument to pass to each listener.
28710023Smatt.horsnell@ARM.com     */
28810023Smatt.horsnell@ARM.com    void notify(const Arg &arg)
28910023Smatt.horsnell@ARM.com    {
29010023Smatt.horsnell@ARM.com        for (auto l = listeners.begin(); l != listeners.end(); ++l) {
29110023Smatt.horsnell@ARM.com            (*l)->notify(arg);
29210023Smatt.horsnell@ARM.com        }
29310023Smatt.horsnell@ARM.com    }
29410023Smatt.horsnell@ARM.com};
29510023Smatt.horsnell@ARM.com#endif//__SIM_PROBE_PROBE_HH__
296