diff options
Diffstat (limited to 'src/sim/probe/probe.hh')
-rw-r--r-- | src/sim/probe/probe.hh | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/src/sim/probe/probe.hh b/src/sim/probe/probe.hh new file mode 100644 index 000000000..0f77ccb1d --- /dev/null +++ b/src/sim/probe/probe.hh @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2013 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Matt Horsnell + */ + +/** + * @file This file describes the base components used for the probe system. + * There are currently 3 components: + * + * ProbePoint: an event probe point i.e. send a notify from the point + * at which an instruction was committed. + * + * ProbeListener: a listener provide a notify method that is called when + * a probe point event occurs. Multiple ProbeListeners + * can be added to each ProbePoint. + * + * ProbeListenerObject: a wrapper around a SimObject that can connect to another + * SimObject on which is will add ProbeListeners. + * + * ProbeManager: used to match up ProbeListeners and ProbePoints. + * At <b>simulation init</b> this is handled by regProbePoints + * followed by regProbeListeners being called on each + * SimObject in hierarchical ordering. + * ProbeListeners can be added/removed dynamically at runtime. + */ + +#ifndef __SIM_PROBE_PROBE_HH__ +#define __SIM_PROBE_PROBE_HH__ + +#include <string> +#include <vector> + +#include "base/trace.hh" +#include "params/ProbeListenerObject.hh" +#include "sim/sim_object.hh" + +/** Forward declare the ProbeManager. */ +class ProbeManager; +class ProbeListener; + +/** + * This class is a minimal wrapper around SimObject. It is used to declare + * a python derived object that can be added as a ProbeListener to any other + * SimObject. + * + * It instantiates manager from a call to Parent.any. + * The vector of listeners is used simply to hold onto listeners until the + * ProbeListenerObject is destroyed. + */ +class ProbeListenerObject : public SimObject +{ + protected: + ProbeManager *manager; + std::vector<ProbeListener *> listeners; + + public: + ProbeListenerObject(const ProbeListenerObjectParams *params); + virtual ~ProbeListenerObject(); + ProbeManager* getProbeManager() { return manager; } +}; + +/** + * ProbeListener base class; here to simplify things like containers + * containing multiple types of ProbeListener. + * + * Note a ProbeListener is added to the ProbePoint in constructor by + * using the ProbeManager passed in. + */ +class ProbeListener +{ + public: + ProbeListener(ProbeManager *manager, const std::string &name); + virtual ~ProbeListener() {} +}; + +/** + * ProbeListener base class; again used to simplify use of ProbePoints + * in containers and used as to define interface for adding removing + * listeners to the ProbePoint. + */ +class ProbePoint +{ + protected: + const std::string name; + public: + ProbePoint(ProbeManager *manager, const std::string &name); + virtual ~ProbePoint() {} + + virtual void addListener(ProbeListener *listener) = 0; + virtual void removeListener(ProbeListener *listener) = 0; + std::string getName() const { return name; } +}; + +/** + * ProbeManager is a conduit class that lives on each SimObject, + * and is used to match up probe listeners with probe points. + */ +class ProbeManager +{ + private: + /** Required for sensible debug messages.*/ + const SimObject *object; + /** Vector for name look-up. */ + std::vector<ProbePoint *> points; + + public: + ProbeManager(SimObject *obj) + : object(obj) + {} + virtual ~ProbeManager() {} + + /** + * @brief Add a ProbeListener to the ProbePoint named by pointName. + * If the name doesn't resolve a ProbePoint return false. + * @param pointName the name of the ProbePoint to add the ProbeListener to. + * @param listener the ProbeListener to add. + * @return true if added, false otherwise. + */ + bool addListener(std::string pointName, ProbeListener &listener); + + /** + * @brief Remove a ProbeListener from the ProbePoint named by pointName. + * If the name doesn't resolve a ProbePoint return false. + * @param pointName the name of the ProbePoint to remove the ProbeListener + * from. + * @param listener the ProbeListener to remove. + * @return true if removed, false otherwise. + */ + bool removeListener(std::string pointName, ProbeListener &listener); + + /** + * @brief Add a ProbePoint to this SimObject ProbeManager. + * @param point the ProbePoint to add. + */ + void addPoint(ProbePoint &point); +}; + +/** + * ProbeListenerArgBase is used to define the base interface to a + * ProbeListenerArg (i.e the notify method on specific type). + * + * It is necessary to split this out from ProbeListenerArg, as that + * templates off the class containing the function that notify calls. + */ +template <class Arg> +class ProbeListenerArgBase : public ProbeListener +{ + public: + ProbeListenerArgBase(ProbeManager *pm, const std::string &name) + : ProbeListener(pm, name) + {} + virtual void notify(const Arg &val) = 0; +}; + +/** + * ProbeListenerArg generates a listener for the class of Arg and the + * class type T which is the class containing the function that notify will + * call. + * + * Note that the function is passed as a pointer on construction. + */ +template <class T, class Arg> +class ProbeListenerArg : public ProbeListenerArgBase<Arg> +{ + private: + T *object; + void (T::* function)(const Arg &); + + public: + /** + * @param obj the class of type Tcontaining the method to call on notify. + * @param name the name of the ProbePoint to add this listener to. + * @param func a pointer to the function on obj (called on notify). + */ + ProbeListenerArg(T *obj, const std::string &name, void (T::* func)(const Arg &)) + : ProbeListenerArgBase<Arg>(obj->getProbeManager(), name), + object(obj), + function(func) + {} + + /** + * @brief called when the ProbePoint calls notify. This is a shim through to + * the function passed during construction. + * @param val the argument value to pass. + */ + virtual void notify(const Arg &val) { (object->*function)(val); } +}; + +/** + * ProbePointArg generates a point for the class of Arg. As ProbePointArgs talk + * directly to ProbeListenerArgs of the same type, we can store the vector of + * ProbeListeners as their Arg type (and not as base type). + * + * Methods are provided to addListener, removeListener and notify. + */ +template <typename Arg> +class ProbePointArg : public ProbePoint +{ + /** The attached listeners. */ + std::vector<ProbeListenerArgBase<Arg> *> listeners; + + public: + ProbePointArg(ProbeManager *manager, std::string name) + : ProbePoint(manager, name) + { + } + + /** + * @brief adds a ProbeListener to this ProbePoints notify list. + * @param l the ProbeListener to add to the notify list. + */ + void addListener(ProbeListener *l) + { + // check listener not already added + if (std::find(listeners.begin(), listeners.end(), l) == listeners.end()) { + listeners.push_back(static_cast<ProbeListenerArgBase<Arg> *>(l)); + } + } + + /** + * @brief remove a ProbeListener from this ProbePoints notify list. + * @param l the ProbeListener to remove from the notify list. + */ + void removeListener(ProbeListener *l) + { + listeners.erase(std::remove(listeners.begin(), listeners.end(), l), + listeners.end()); + } + + /** + * @brief called at the ProbePoint call site, passes arg to each listener. + * @param arg the argument to pass to each listener. + */ + void notify(const Arg &arg) + { + for (auto l = listeners.begin(); l != listeners.end(); ++l) { + (*l)->notify(arg); + } + } +}; +#endif//__SIM_PROBE_PROBE_HH__ |