diff -r 38e438a1c534 -r ba8a07a9f4b9 src/base/smartvalue.hh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/base/smartvalue.hh Wed Feb 22 14:05:06 2012 -0600 @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2011 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 + */ + +/* Smart handling of simulator counter values. + * + */ +#ifndef __BASE_SMARTVALUE_HH__ +#define __BASE_SMARTVALUE_HH__ + +#include "base/statistics.hh" + +namespace SmartValue { + +/** + * A simple class to allow increment callbacks. + */ +class Listener +{ + public: + virtual void incrementCallback(Stats::Counter val) = 0; + //virtual void overflowCallback() = 0; +}; + +/** + * Wrapper around a listener to allow callback sorting + */ +class ListenerHandle +{ + private: + Listener *listener; + uint64_t counter; + uint64_t requestCounter; + + public: + ListenerHandle(Listener *_listener, + uint64_t _counter, + uint64_t _requestCounter) + : listener(_listener), + counter(_counter), + requestCounter(_requestCounter) + {} + + Listener *getListener() { return listener; } + uint64_t getCounter() const { return counter; } + uint64_t getRequestCounter() const { return requestCounter; } + + bool + operator<(const ListenerHandle &other) const + { + return getCounter() < other.getCounter(); + } +}; + +/** + * Simple replacement for a Scalar + */ +class Base { + protected: + friend class Stats::Temp; + + private: + uint64_t headCounter, lastStatReset; + + Stats::Value valueStore; + + std::set listeners; + std::set::iterator itr, itrEnd; + + /** + * Increment the counter value. + * Check if the head of the list requires incrementCallback. + */ + void increment(Counter val) + { + headCounter += val; + if (!listeners.empty()) + { + for (itr = listeners.begin(), itrEnd = listeners.end(); + (itr != itrEnd) && ((*itr)->getCounter() < headCounter); + ++itr) + { + (*itr)->getListener()->incrementCallback(val); + } + } + } + + public: + + // The reset functor + void reset() + { + lastStatReset = headCounter; + } + + // The value functor + Stats::Counter value() const + { + // remove lastStatRest to keep consistent with other stats + return headCounter - lastStatReset; + } + + Base() + : headCounter(0), + lastStatReset(0) + {} + + ~Base() + {} + + /** Copy the statistics boilerplate for setting name. */ + Base &name(std::string _name) + { + valueStore.name(_name); + return *this; + } + + /** Copy the statistics boilerplate for setting name. */ + Base &desc(std::string _desc) + { + valueStore.desc(_desc); + return *this; + } + + Base &flags(Stats::Flags _flags) + { + valueStore.flags(_flags); + return *this; + } + + /** Wrap two functors, one for value, the other for reset */ + Base &init() + { + valueStore.member_functor_with_reset(*this, &SmartValue::Base::value, + &SmartValue::Base::reset); + return *this; + } + + /** Return the name of this stat */ + const std::string &name() const { return valueStore.name(); } + + /** Register a listener with this stat */ + void registerListener(Listener *listener, uint64_t count) + { + if (count < 0) + { + panic("Listener must have a positive count\n"); + } + + // remove any current entry + deregisterListener(listener); + // insert a new entry at headCounter increment + count + listeners.insert(new ListenerHandle(listener, headCounter + count, count)); + } + + /** Deregister a listener from this stat */ + void deregisterListener(Listener *listener) + { + // Destroy and remove a currently registered handler. + for (itr = listeners.begin(), itrEnd = listeners.end(); + itr != itrEnd; ++itr) + { + if ((*itr)->getListener() == listener) + { + delete *itr; + listeners.erase(itr); + break; + } + } + } + + /** Returns the number of missed increments. Useful if the + * the corresponding listener needs to update its value but + * the count has not yet triggered a callback. + */ + Stats::Counter missedIncrements(Listener *listener) + { + for (itr = listeners.begin(), itrEnd = listeners.end(); + itr != itrEnd; ++itr) + { + if ((*itr)->getListener() == listener) + { + return (*itr)->getRequestCounter() - + ((*itr)->getCounter() - headCounter); + } + } + return 0; + } + + /** + * Overloaded operators too allow statistic-like use. + */ + void operator++(int) { increment(1); } + void operator++() { increment(1); } + void operator+=(const Counter &other) { increment(other); } + + /** + * Conversion to Stats::Temp is a pre-requisite for some operations. + */ + operator Stats::Temp() { return Stats::Temp(valueStore); } + + Stats::Temp operator*(const Stats::Temp &other) + { + return value() * other; + } + + Stats::Temp operator/(const Stats::Temp &other) + { + return value() / other; + } + +}; + +} // namespace SmartValue + +#endif //__BASE_SMARTVALUE_HH__ diff -r 38e438a1c534 -r ba8a07a9f4b9 src/base/statistics.hh --- a/src/base/statistics.hh Wed Feb 22 14:04:55 2012 -0600 +++ b/src/base/statistics.hh Wed Feb 22 14:05:06 2012 -0600 @@ -1,3 +1,4 @@ + /* * Copyright (c) 2003-2005 The Regents of The University of Michigan * All rights reserved. @@ -57,6 +58,7 @@ #include #include #include +#include #include #include @@ -736,7 +738,7 @@ size_type size() const { return 1; } bool check() const { return true; } void prepare() { } - void reset() { } + virtual void reset() { } bool zero() const { return value() == 0; } void visit(Output &visitor) { visitor.visit(*this); } @@ -768,6 +770,25 @@ Result total() const { return (*functor)(); } }; +template +class MemberFunctorProxy : public ProxyInfo +{ + private: + T *object; + U functor; + V reset_functor; + + public: + MemberFunctorProxy(T &obj, U func, V reset_func) + : object(&obj), functor(func), reset_functor(reset_func) + {} + + Counter value() const { return ((object)->*(functor))(); } + Result result() const { return ((object)->*(functor))(); } + Result total() const { return ((object)->*(functor))(); } + void reset() { ((object)->*(reset_functor))(); } +}; + template class ValueBase : public DataWrap { @@ -796,6 +817,15 @@ return this->self(); } + template + Derived & + member_functor_with_reset(T &object, U func, V reset) + { + proxy = new MemberFunctorProxy(object, func, reset); + this->setInit(); + return this->self(); + } + Counter value() { return proxy->value(); } Result result() const { return proxy->result(); } Result total() const { return proxy->total(); }; @@ -805,7 +835,7 @@ bool zero() const { return proxy->zero(); } bool check() const { return proxy != NULL; } void prepare() { } - void reset() { } + void reset() { return proxy->reset(); } }; ////////////////////////////////////////////////////////////////////// diff -r 38e438a1c534 -r ba8a07a9f4b9 src/sim/sim_object.hh --- a/src/sim/sim_object.hh Wed Feb 22 14:04:55 2012 -0600 +++ b/src/sim/sim_object.hh Wed Feb 22 14:05:06 2012 -0600 @@ -43,6 +43,7 @@ #include #include +#include "base/smartvalue.hh" #include "enums/MemoryMode.hh" #include "params/SimObject.hh" #include "sim/eventq.hh" @@ -80,6 +81,9 @@ // list of all instantiated simulation objects static SimObjectList simObjectList; + // map of smartvalues associated with this object + std::map smartValueMap; + protected: const SimObjectParams *_params; @@ -129,6 +133,10 @@ virtual void regFormulas(); virtual void resetStats(); + // register any smartvalues for this object + void addSmartValue(SmartValue::Base *val); + SmartValue::Base *getSmartValueByName(std::string name); + /** * startup() is the final initialization call before simulation. * All state is initialized (including unserialized state, if any, diff -r 38e438a1c534 -r ba8a07a9f4b9 src/sim/sim_object.cc --- a/src/sim/sim_object.cc Wed Feb 22 14:04:55 2012 -0600 +++ b/src/sim/sim_object.cc Wed Feb 22 14:05:06 2012 -0600 @@ -31,6 +31,7 @@ */ #include +#include #include "base/callback.hh" #include "base/inifile.hh" @@ -114,6 +115,27 @@ { } +SmartValue::Base * +SimObject::getSmartValueByName(std::string statName) +{ + typedef std::map SmartMap; + SmartMap::iterator itr; + std::stringstream ss; + ss << name() << "." << statName; + if ((itr = smartValueMap.find(ss.str())) != smartValueMap.end()) + { + return itr->second; + } + return NULL; +} + +void +SimObject::addSmartValue(SmartValue::Base *val) +{ + smartValueMap.insert( + std::pair(val->name(), val)); +} + // // static function: serialize all SimObjects. //