2 * Copyright (c) 2019-2020 Arm Limited
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
14 * Copyright (c) 2003-2005 The Regents of The University of Michigan
15 * Copyright (c) 2017, Centre National de la Recherche Scientifique
16 * All rights reserved.
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 * Declaration of Statistics objects.
49 * Generalized N-dimensinal vector
53 * -- these both can use the same function that prints out a
54 * specific set of stats
55 * VectorStandardDeviation totals
58 #ifndef __BASE_STATISTICS_HH__
59 #define __BASE_STATISTICS_HH__
75 #include "base/stats/group.hh"
76 #include "base/stats/info.hh"
77 #include "base/stats/output.hh"
78 #include "base/stats/types.hh"
79 #include "base/cast.hh"
80 #include "base/cprintf.hh"
81 #include "base/intmath.hh"
82 #include "base/str.hh"
83 #include "base/types.hh"
85 #include "sim/core.hh"
87 /* A namespace for all of the Statistics */
90 template <class Stat, class Base>
91 class InfoProxy : public Base
97 InfoProxy(Stat &stat) : s(stat) {}
99 bool check() const { return s.check(); }
100 void prepare() { s.prepare(); }
101 void reset() { s.reset(); }
103 visit(Output &visitor)
105 visitor.visit(*static_cast<Base *>(this));
107 bool zero() const { return s.zero(); }
110 template <class Stat>
111 class ScalarInfoProxy : public InfoProxy<Stat, ScalarInfo>
114 ScalarInfoProxy(Stat &stat) : InfoProxy<Stat, ScalarInfo>(stat) {}
116 Counter value() const { return this->s.value(); }
117 Result result() const { return this->s.result(); }
118 Result total() const { return this->s.total(); }
121 template <class Stat>
122 class VectorInfoProxy : public InfoProxy<Stat, VectorInfo>
125 mutable VCounter cvec;
126 mutable VResult rvec;
129 VectorInfoProxy(Stat &stat) : InfoProxy<Stat, VectorInfo>(stat) {}
131 size_type size() const { return this->s.size(); }
143 this->s.result(rvec);
147 Result total() const { return this->s.total(); }
150 template <class Stat>
151 class DistInfoProxy : public InfoProxy<Stat, DistInfo>
154 DistInfoProxy(Stat &stat) : InfoProxy<Stat, DistInfo>(stat) {}
157 template <class Stat>
158 class VectorDistInfoProxy : public InfoProxy<Stat, VectorDistInfo>
161 VectorDistInfoProxy(Stat &stat) : InfoProxy<Stat, VectorDistInfo>(stat) {}
163 size_type size() const { return this->s.size(); }
166 template <class Stat>
167 class Vector2dInfoProxy : public InfoProxy<Stat, Vector2dInfo>
170 Vector2dInfoProxy(Stat &stat) : InfoProxy<Stat, Vector2dInfo>(stat) {}
172 Result total() const { return this->s.total(); }
177 virtual ~StorageParams();
186 /** Set up an info class for this statistic */
187 void setInfo(Group *parent, Info *info);
188 /** Save Storage class parameters if any */
189 void setParams(const StorageParams *params);
190 /** Save Storage class parameters if any */
193 /** Grab the information class for this statistic */
195 /** Grab the information class for this statistic */
196 const Info *info() const;
203 * Reset the stat to the default state.
208 * @return true if this stat has a value and satisfies its
209 * requirement as a prereq
211 bool zero() const { return true; }
214 * Check that this stat has been set up properly and is ready for
216 * @return true for success
218 bool check() const { return true; }
221 template <class Derived, template <class> class InfoProxyType>
222 class DataWrap : public InfoAccess
225 typedef InfoProxyType<Derived> Info;
228 Derived &self() { return *static_cast<Derived *>(this); }
234 return safe_cast<Info *>(InfoAccess::info());
241 return safe_cast<const Info *>(InfoAccess::info());
246 DataWrap(const DataWrap &) = delete;
247 DataWrap &operator=(const DataWrap &) = delete;
250 DataWrap(Group *parent, const char *name, const char *desc)
252 auto info = new Info(self());
253 this->setInfo(parent, info);
256 parent->addStat(info);
259 info->setName(parent, name);
260 info->flags.set(display);
268 * Set the name and marks this stat to print at the end of simulation.
269 * @param name The new name.
270 * @return A reference to this stat.
273 name(const std::string &name)
275 Info *info = this->info();
277 info->flags.set(display);
280 const std::string &name() const { return this->info()->name; }
283 * Set the character(s) used between the name and vector number
284 * on vectors, dist, etc.
285 * @param _sep The new separator string
286 * @return A reference to this stat.
289 setSeparator(const std::string &_sep)
291 this->info()->setSeparator(_sep);
294 const std::string &setSeparator() const
296 return this->info()->separatorString;
300 * Set the description and marks this stat to print at the end of
302 * @param desc The new description.
303 * @return A reference to this stat.
306 desc(const std::string &_desc)
308 this->info()->desc = _desc;
313 * Set the precision and marks this stat to print at the end of simulation.
314 * @param _precision The new precision
315 * @return A reference to this stat.
318 precision(int _precision)
320 this->info()->precision = _precision;
325 * Set the flags and marks this stat to print at the end of simulation.
326 * @param f The new flags.
327 * @return A reference to this stat.
332 this->info()->flags.set(_flags);
337 * Set the prerequisite stat and marks this stat to print at the end of
339 * @param prereq The prerequisite stat.
340 * @return A reference to this stat.
342 template <class Stat>
344 prereq(const Stat &prereq)
346 this->info()->prereq = prereq.info();
351 template <class Derived, template <class> class InfoProxyType>
352 class DataWrapVec : public DataWrap<Derived, InfoProxyType>
355 typedef InfoProxyType<Derived> Info;
357 DataWrapVec(Group *parent = nullptr, const char *name = nullptr,
358 const char *desc = nullptr)
359 : DataWrap<Derived, InfoProxyType>(parent, name, desc)
362 // The following functions are specific to vectors. If you use them
363 // in a non vector context, you will get a nice compiler error!
366 * Set the subfield name for the given index, and marks this stat to print
367 * at the end of simulation.
368 * @param index The subfield index.
369 * @param name The new name of the subfield.
370 * @return A reference to this stat.
373 subname(off_type index, const std::string &name)
375 Derived &self = this->self();
376 Info *info = self.info();
378 std::vector<std::string> &subn = info->subnames;
379 if (subn.size() <= index)
380 subn.resize(index + 1);
385 // The following functions are specific to 2d vectors. If you use
386 // them in a non vector context, you will get a nice compiler
387 // error because info doesn't have the right variables.
390 * Set the subfield description for the given index and marks this stat to
391 * print at the end of simulation.
392 * @param index The subfield index.
393 * @param desc The new description of the subfield
394 * @return A reference to this stat.
397 subdesc(off_type index, const std::string &desc)
399 Info *info = this->info();
401 std::vector<std::string> &subd = info->subdescs;
402 if (subd.size() <= index)
403 subd.resize(index + 1);
412 Derived &self = this->self();
413 Info *info = this->info();
415 size_t size = self.size();
416 for (off_type i = 0; i < size; ++i)
417 self.data(i)->prepare(info);
423 Derived &self = this->self();
424 Info *info = this->info();
426 size_t size = self.size();
427 for (off_type i = 0; i < size; ++i)
428 self.data(i)->reset(info);
432 template <class Derived, template <class> class InfoProxyType>
433 class DataWrapVec2d : public DataWrapVec<Derived, InfoProxyType>
436 typedef InfoProxyType<Derived> Info;
438 DataWrapVec2d(Group *parent, const char *name, const char *desc)
439 : DataWrapVec<Derived, InfoProxyType>(parent, name, desc)
444 * @warning This makes the assumption that if you're gonna subnames a 2d
445 * vector, you're subnaming across all y
448 ysubnames(const char **names)
450 Derived &self = this->self();
451 Info *info = this->info();
453 info->y_subnames.resize(self.y);
454 for (off_type i = 0; i < self.y; ++i)
455 info->y_subnames[i] = names[i];
460 ysubname(off_type index, const std::string &subname)
462 Derived &self = this->self();
463 Info *info = this->info();
465 assert(index < self.y);
466 info->y_subnames.resize(self.y);
467 info->y_subnames[index] = subname.c_str();
472 ysubname(off_type i) const
474 return this->info()->y_subnames[i];
479 //////////////////////////////////////////////////////////////////////
483 //////////////////////////////////////////////////////////////////////
486 * Templatized storage and interface for a simple scalar stat.
491 /** The statistic value. */
495 struct Params : public StorageParams {};
499 * Builds this storage element and calls the base constructor of the
507 * The the stat to the given value.
508 * @param val The new value.
510 void set(Counter val) { data = val; }
512 * Increment the stat by the given value.
513 * @param val The new value.
515 void inc(Counter val) { data += val; }
517 * Decrement the stat by the given value.
518 * @param val The new value.
520 void dec(Counter val) { data -= val; }
522 * Return the value of this stat as its base type.
523 * @return The value of this stat.
525 Counter value() const { return data; }
527 * Return the value of this stat as a result type.
528 * @return The value of this stat.
530 Result result() const { return (Result)data; }
532 * Prepare stat data for dumping or serialization
534 void prepare(Info *info) { }
536 * Reset stat value to default
538 void reset(Info *info) { data = Counter(); }
541 * @return true if zero value
543 bool zero() const { return data == Counter(); }
547 * Templatized storage and interface to a per-tick average stat. This keeps
548 * a current count and updates a total (count * ticks) when this count
549 * changes. This allows the quick calculation of a per tick count of the item
550 * being watched. This is good for keeping track of residencies in structures
551 * among other things.
556 /** The current count. */
558 /** The tick of the last reset */
560 /** The total count for all tick. */
561 mutable Result total;
562 /** The tick that current last changed. */
566 struct Params : public StorageParams {};
570 * Build and initializes this stat storage.
573 : current(0), lastReset(0), total(0), last(0)
577 * Set the current count to the one provided, update the total and last
579 * @param val The new count.
584 total += current * (curTick() - last);
590 * Increment the current count by the provided value, calls set.
591 * @param val The amount to increment.
593 void inc(Counter val) { set(current + val); }
596 * Deccrement the current count by the provided value, calls set.
597 * @param val The amount to decrement.
599 void dec(Counter val) { set(current - val); }
602 * Return the current count.
603 * @return The current count.
605 Counter value() const { return current; }
608 * Return the current average.
609 * @return The current average.
614 assert(last == curTick());
615 return (Result)(total + current) / (Result)(curTick() - lastReset + 1);
619 * @return true if zero value
621 bool zero() const { return total == 0.0; }
624 * Prepare stat data for dumping or serialization
629 total += current * (curTick() - last);
634 * Reset stat value to default
641 lastReset = curTick();
647 * Implementation of a scalar stat. The type of stat is determined by the
650 template <class Derived, class Stor>
651 class ScalarBase : public DataWrap<Derived, ScalarInfoProxy>
654 typedef Stor Storage;
655 typedef typename Stor::Params Params;
658 /** The storage of this stat. */
659 M5_ALIGNED(8) char storage[sizeof(Storage)];
663 * Retrieve the storage.
664 * @param index The vector index to access.
665 * @return The storage object at the given index.
670 return reinterpret_cast<Storage *>(storage);
674 * Retrieve a const pointer to the storage.
675 * for the given index.
676 * @param index The vector index to access.
677 * @return A const pointer to the storage object at the given index.
682 return reinterpret_cast<const Storage *>(storage);
688 new (storage) Storage(this->info());
694 * Return the current value of this stat as its base type.
695 * @return The current value.
697 Counter value() const { return data()->value(); }
700 ScalarBase(Group *parent = nullptr, const char *name = nullptr,
701 const char *desc = nullptr)
702 : DataWrap<Derived, ScalarInfoProxy>(parent, name, desc)
708 // Common operators for stats
710 * Increment the stat by 1. This calls the associated storage object inc
713 void operator++() { data()->inc(1); }
715 * Decrement the stat by 1. This calls the associated storage object dec
718 void operator--() { data()->dec(1); }
720 /** Increment the stat by 1. */
721 void operator++(int) { ++*this; }
722 /** Decrement the stat by 1. */
723 void operator--(int) { --*this; }
726 * Set the data value to the given value. This calls the associated storage
727 * object set function.
728 * @param v The new value.
730 template <typename U>
731 void operator=(const U &v) { data()->set(v); }
734 * Increment the stat by the given value. This calls the associated
735 * storage object inc function.
736 * @param v The value to add.
738 template <typename U>
739 void operator+=(const U &v) { data()->inc(v); }
742 * Decrement the stat by the given value. This calls the associated
743 * storage object dec function.
744 * @param v The value to substract.
746 template <typename U>
747 void operator-=(const U &v) { data()->dec(v); }
750 * Return the number of elements, always 1 for a scalar.
753 size_type size() const { return 1; }
755 Counter value() { return data()->value(); }
757 Result result() { return data()->result(); }
759 Result total() { return result(); }
761 bool zero() { return result() == 0.0; }
763 void reset() { data()->reset(this->info()); }
764 void prepare() { data()->prepare(this->info()); }
767 class ProxyInfo : public ScalarInfo
770 std::string str() const { return std::to_string(value()); }
771 size_type size() const { return 1; }
772 bool check() const { return true; }
775 bool zero() const { return value() == 0; }
777 void visit(Output &visitor) { visitor.visit(*this); }
781 class ValueProxy : public ProxyInfo
787 ValueProxy(T &val) : scalar(&val) {}
788 Counter value() const { return *scalar; }
789 Result result() const { return *scalar; }
790 Result total() const { return *scalar; }
793 template <class T, class Enabled=void>
794 class FunctorProxy : public ProxyInfo
800 FunctorProxy(T &func) : functor(&func) {}
801 Counter value() const { return (*functor)(); }
802 Result result() const { return (*functor)(); }
803 Result total() const { return (*functor)(); }
807 * Template specialization for type std::function<Result()> which holds a copy
808 * of its target instead of a pointer to it. This makes it possible to use a
809 * lambda or other type inline without having to keep track of an instance
813 class FunctorProxy<T,
814 typename std::enable_if_t<std::is_constructible<std::function<Result()>,
815 const T &>::value>> : public ProxyInfo
818 std::function<Result()> functor;
821 FunctorProxy(const T &func) : functor(func) {}
822 Counter value() const { return functor(); }
823 Result result() const { return functor(); }
824 Result total() const { return functor(); }
828 * A proxy similar to the FunctorProxy, but allows calling a method of a bound
829 * object, instead of a global free-standing function.
831 template <class T, class V>
832 class MethodProxy : public ProxyInfo
836 typedef V (T::*MethodPointer) () const;
837 MethodPointer method;
840 MethodProxy(T *obj, MethodPointer meth) : object(obj), method(meth) {}
841 Counter value() const { return (object->*method)(); }
842 Result result() const { return (object->*method)(); }
843 Result total() const { return (object->*method)(); }
846 template <class Derived>
847 class ValueBase : public DataWrap<Derived, ScalarInfoProxy>
853 ValueBase(Group *parent, const char *name, const char *desc)
854 : DataWrap<Derived, ScalarInfoProxy>(parent, name, desc),
859 ~ValueBase() { if (proxy) delete proxy; }
865 proxy = new ValueProxy<T>(value);
872 functor(const T &func)
874 proxy = new FunctorProxy<T>(func);
883 proxy = new FunctorProxy<T>(func);
889 * Extended functor that calls the specified method of the provided object.
891 * @param obj Pointer to the object whose method should be called.
892 * @param method Pointer of the function / method of the object.
893 * @return Updated stats item.
895 template <class T, class V>
897 method(T *obj, V (T::*method)() const)
899 proxy = new MethodProxy<T,V>(obj, method);
904 Counter value() { return proxy->value(); }
905 Result result() const { return proxy->result(); }
906 Result total() const { return proxy->total(); };
907 size_type size() const { return proxy->size(); }
909 std::string str() const { return proxy->str(); }
910 bool zero() const { return proxy->zero(); }
911 bool check() const { return proxy != NULL; }
916 //////////////////////////////////////////////////////////////////////
920 //////////////////////////////////////////////////////////////////////
923 * A proxy class to access the stat at a given index in a VectorBase stat.
924 * Behaves like a ScalarBase.
926 template <class Stat>
930 /** Pointer to the parent Vector. */
933 /** The index to access in the parent VectorBase. */
938 * Return the current value of this stat as its base type.
939 * @return The current value.
941 Counter value() const { return stat.data(index)->value(); }
944 * Return the current value of this statas a result type.
945 * @return The current value.
947 Result result() const { return stat.data(index)->result(); }
951 * Create and initialize this proxy, do not register it with the database.
952 * @param i The index to access.
954 ScalarProxy(Stat &s, off_type i)
960 * Create a copy of the provided ScalarProxy.
961 * @param sp The proxy to copy.
963 ScalarProxy(const ScalarProxy &sp)
964 : stat(sp.stat), index(sp.index)
968 * Set this proxy equal to the provided one.
969 * @param sp The proxy to copy.
970 * @return A reference to this proxy.
973 operator=(const ScalarProxy &sp)
981 // Common operators for stats
983 * Increment the stat by 1. This calls the associated storage object inc
986 void operator++() { stat.data(index)->inc(1); }
988 * Decrement the stat by 1. This calls the associated storage object dec
991 void operator--() { stat.data(index)->dec(1); }
993 /** Increment the stat by 1. */
994 void operator++(int) { ++*this; }
995 /** Decrement the stat by 1. */
996 void operator--(int) { --*this; }
999 * Set the data value to the given value. This calls the associated storage
1000 * object set function.
1001 * @param v The new value.
1003 template <typename U>
1005 operator=(const U &v)
1007 stat.data(index)->set(v);
1011 * Increment the stat by the given value. This calls the associated
1012 * storage object inc function.
1013 * @param v The value to add.
1015 template <typename U>
1017 operator+=(const U &v)
1019 stat.data(index)->inc(v);
1023 * Decrement the stat by the given value. This calls the associated
1024 * storage object dec function.
1025 * @param v The value to substract.
1027 template <typename U>
1029 operator-=(const U &v)
1031 stat.data(index)->dec(v);
1035 * Return the number of elements, always 1 for a scalar.
1038 size_type size() const { return 1; }
1044 return csprintf("%s[%d]", stat.info()->name, index);
1049 * Implementation of a vector of stats. The type of stat is determined by the
1050 * Storage class. @sa ScalarBase
1052 template <class Derived, class Stor>
1053 class VectorBase : public DataWrapVec<Derived, VectorInfoProxy>
1056 typedef Stor Storage;
1057 typedef typename Stor::Params Params;
1060 typedef ScalarProxy<Derived> Proxy;
1061 friend class ScalarProxy<Derived>;
1062 friend class DataWrapVec<Derived, VectorInfoProxy>;
1065 /** The storage of this stat. */
1071 * Retrieve the storage.
1072 * @param index The vector index to access.
1073 * @return The storage object at the given index.
1075 Storage *data(off_type index) { return &storage[index]; }
1078 * Retrieve a const pointer to the storage.
1079 * @param index The vector index to access.
1080 * @return A const pointer to the storage object at the given index.
1082 const Storage *data(off_type index) const { return &storage[index]; }
1087 assert(s > 0 && "size must be positive!");
1088 assert(!storage && "already initialized");
1091 char *ptr = new char[_size * sizeof(Storage)];
1092 storage = reinterpret_cast<Storage *>(ptr);
1094 for (off_type i = 0; i < _size; ++i)
1095 new (&storage[i]) Storage(this->info());
1102 value(VCounter &vec) const
1105 for (off_type i = 0; i < size(); ++i)
1106 vec[i] = data(i)->value();
1110 * Copy the values to a local vector and return a reference to it.
1111 * @return A reference to a vector of the stat values.
1114 result(VResult &vec) const
1117 for (off_type i = 0; i < size(); ++i)
1118 vec[i] = data(i)->result();
1122 * Return a total of all entries in this vector.
1123 * @return The total of all vector entries.
1129 for (off_type i = 0; i < size(); ++i)
1130 total += data(i)->result();
1135 * @return the number of elements in this vector.
1137 size_type size() const { return _size; }
1142 for (off_type i = 0; i < size(); ++i)
1143 if (data(i)->zero())
1151 return storage != NULL;
1155 VectorBase(Group *parent, const char *name, const char *desc)
1156 : DataWrapVec<Derived, VectorInfoProxy>(parent, name, desc),
1157 storage(nullptr), _size(0)
1165 for (off_type i = 0; i < _size; ++i)
1166 data(i)->~Storage();
1167 delete [] reinterpret_cast<char *>(storage);
1171 * Set this vector to have the given size.
1172 * @param size The new size.
1173 * @return A reference to this stat.
1176 init(size_type size)
1178 Derived &self = this->self();
1184 * Return a reference (ScalarProxy) to the stat at the given index.
1185 * @param index The vector index to access.
1186 * @return A reference of the stat.
1189 operator[](off_type index)
1191 assert (index < size());
1192 return Proxy(this->self(), index);
1196 template <class Stat>
1205 mutable VResult vec;
1207 typename Stat::Storage *
1208 data(off_type index)
1210 assert(index < len);
1211 return stat.data(offset + index);
1214 const typename Stat::Storage *
1215 data(off_type index) const
1217 assert(index < len);
1218 return stat.data(offset + index);
1227 for (off_type i = 0; i < size(); ++i)
1228 vec[i] = data(i)->result();
1237 for (off_type i = 0; i < size(); ++i)
1238 total += data(i)->result();
1243 VectorProxy(Stat &s, off_type o, size_type l)
1244 : stat(s), offset(o), len(l)
1248 VectorProxy(const VectorProxy &sp)
1249 : stat(sp.stat), offset(sp.offset), len(sp.len)
1254 operator=(const VectorProxy &sp)
1263 operator[](off_type index)
1265 assert (index < size());
1266 return ScalarProxy<Stat>(stat, offset + index);
1269 size_type size() const { return len; }
1272 template <class Derived, class Stor>
1273 class Vector2dBase : public DataWrapVec2d<Derived, Vector2dInfoProxy>
1276 typedef Vector2dInfoProxy<Derived> Info;
1277 typedef Stor Storage;
1278 typedef typename Stor::Params Params;
1279 typedef VectorProxy<Derived> Proxy;
1280 friend class ScalarProxy<Derived>;
1281 friend class VectorProxy<Derived>;
1282 friend class DataWrapVec<Derived, Vector2dInfoProxy>;
1283 friend class DataWrapVec2d<Derived, Vector2dInfoProxy>;
1292 Storage *data(off_type index) { return &storage[index]; }
1293 const Storage *data(off_type index) const { return &storage[index]; }
1296 Vector2dBase(Group *parent, const char *name, const char *desc)
1297 : DataWrapVec2d<Derived, Vector2dInfoProxy>(parent, name, desc),
1298 x(0), y(0), _size(0), storage(nullptr)
1306 for (off_type i = 0; i < _size; ++i)
1307 data(i)->~Storage();
1308 delete [] reinterpret_cast<char *>(storage);
1312 init(size_type _x, size_type _y)
1314 assert(_x > 0 && _y > 0 && "sizes must be positive!");
1315 assert(!storage && "already initialized");
1317 Derived &self = this->self();
1318 Info *info = this->info();
1326 char *ptr = new char[_size * sizeof(Storage)];
1327 storage = reinterpret_cast<Storage *>(ptr);
1329 for (off_type i = 0; i < _size; ++i)
1330 new (&storage[i]) Storage(info);
1338 operator[](off_type index)
1340 off_type offset = index * y;
1341 assert (offset + y <= size());
1342 return Proxy(this->self(), offset, y);
1355 return data(0)->zero();
1359 * Return a total of all entries in this vector.
1360 * @return The total of all vector entries.
1366 for (off_type i = 0; i < size(); ++i)
1367 total += data(i)->result();
1374 Info *info = this->info();
1375 size_type size = this->size();
1377 for (off_type i = 0; i < size; ++i)
1378 data(i)->prepare(info);
1380 info->cvec.resize(size);
1381 for (off_type i = 0; i < size; ++i)
1382 info->cvec[i] = data(i)->value();
1386 * Reset stat value to default
1391 Info *info = this->info();
1392 size_type size = this->size();
1393 for (off_type i = 0; i < size; ++i)
1394 data(i)->reset(info);
1400 return storage != NULL;
1404 //////////////////////////////////////////////////////////////////////
1406 // Non formula statistics
1408 //////////////////////////////////////////////////////////////////////
1409 /** The parameters for a distribution stat. */
1410 struct DistParams : public StorageParams
1412 const DistType type;
1413 DistParams(DistType t) : type(t) {}
1417 * Templatized storage and interface for a distribution stat.
1422 /** The parameters for a distribution stat. */
1423 struct Params : public DistParams
1425 /** The minimum value to track. */
1427 /** The maximum value to track. */
1429 /** The number of entries in each bucket. */
1430 Counter bucket_size;
1431 /** The number of buckets. Equal to (max-min)/bucket_size. */
1434 Params() : DistParams(Dist), min(0), max(0), bucket_size(0),
1439 /** The minimum value to track. */
1441 /** The maximum value to track. */
1443 /** The number of entries in each bucket. */
1444 Counter bucket_size;
1446 /** The smallest value sampled. */
1448 /** The largest value sampled. */
1450 /** The number of values sampled less than min. */
1452 /** The number of values sampled more than max. */
1454 /** The current sum. */
1456 /** The sum of squares. */
1458 /** The number of samples. */
1460 /** Counter for each bucket. */
1464 DistStor(Info *info)
1465 : cvec(safe_cast<const Params *>(info->storageParams)->buckets)
1471 * Add a value to the distribution for the given number of times.
1472 * @param val The value to add.
1473 * @param number The number of times to add the value.
1476 sample(Counter val, int number)
1478 if (val < min_track)
1479 underflow += number;
1480 else if (val > max_track)
1484 (size_type)std::floor((val - min_track) / bucket_size);
1485 assert(index < size());
1486 cvec[index] += number;
1495 sum += val * number;
1496 squares += val * val * number;
1501 * Return the number of buckets in this distribution.
1502 * @return the number of buckets.
1504 size_type size() const { return cvec.size(); }
1507 * Returns true if any calls to sample have been made.
1508 * @return True if any values have been sampled.
1513 return samples == Counter();
1517 prepare(Info *info, DistData &data)
1519 const Params *params = safe_cast<const Params *>(info->storageParams);
1521 assert(params->type == Dist);
1522 data.type = params->type;
1523 data.min = params->min;
1524 data.max = params->max;
1525 data.bucket_size = params->bucket_size;
1527 data.min_val = (min_val == CounterLimits::max()) ? 0 : min_val;
1528 data.max_val = (max_val == CounterLimits::min()) ? 0 : max_val;
1529 data.underflow = underflow;
1530 data.overflow = overflow;
1532 data.cvec.resize(params->buckets);
1533 for (off_type i = 0; i < params->buckets; ++i)
1534 data.cvec[i] = cvec[i];
1537 data.squares = squares;
1538 data.samples = samples;
1542 * Reset stat value to default
1547 const Params *params = safe_cast<const Params *>(info->storageParams);
1548 min_track = params->min;
1549 max_track = params->max;
1550 bucket_size = params->bucket_size;
1552 min_val = CounterLimits::max();
1553 max_val = CounterLimits::min();
1554 underflow = Counter();
1555 overflow = Counter();
1557 size_type size = cvec.size();
1558 for (off_type i = 0; i < size; ++i)
1559 cvec[i] = Counter();
1562 squares = Counter();
1563 samples = Counter();
1568 * Templatized storage and interface for a histogram stat.
1573 /** The parameters for a distribution stat. */
1574 struct Params : public DistParams
1576 /** The number of buckets.. */
1579 Params() : DistParams(Hist), buckets(0) {}
1583 /** The minimum value to track. */
1585 /** The maximum value to track. */
1587 /** The number of entries in each bucket. */
1588 Counter bucket_size;
1590 /** The current sum. */
1592 /** The sum of logarithm of each sample, used to compute geometric mean. */
1594 /** The sum of squares. */
1596 /** The number of samples. */
1598 /** Counter for each bucket. */
1602 HistStor(Info *info)
1603 : cvec(safe_cast<const Params *>(info->storageParams)->buckets)
1610 void grow_convert();
1611 void add(HistStor *);
1614 * Add a value to the distribution for the given number of times.
1615 * @param val The value to add.
1616 * @param number The number of times to add the value.
1619 sample(Counter val, int number)
1621 assert(min_bucket < max_bucket);
1622 if (val < min_bucket) {
1623 if (min_bucket == 0)
1626 while (val < min_bucket)
1628 } else if (val >= max_bucket + bucket_size) {
1629 if (min_bucket == 0) {
1630 while (val >= max_bucket + bucket_size)
1633 while (val >= max_bucket + bucket_size)
1639 (int64_t)std::floor((val - min_bucket) / bucket_size);
1641 assert(index < size());
1642 cvec[index] += number;
1644 sum += val * number;
1645 squares += val * val * number;
1646 logs += log(val) * number;
1651 * Return the number of buckets in this distribution.
1652 * @return the number of buckets.
1654 size_type size() const { return cvec.size(); }
1657 * Returns true if any calls to sample have been made.
1658 * @return True if any values have been sampled.
1663 return samples == Counter();
1667 prepare(Info *info, DistData &data)
1669 const Params *params = safe_cast<const Params *>(info->storageParams);
1671 assert(params->type == Hist);
1672 data.type = params->type;
1673 data.min = min_bucket;
1674 data.max = max_bucket + bucket_size - 1;
1675 data.bucket_size = bucket_size;
1677 data.min_val = min_bucket;
1678 data.max_val = max_bucket;
1680 int buckets = params->buckets;
1681 data.cvec.resize(buckets);
1682 for (off_type i = 0; i < buckets; ++i)
1683 data.cvec[i] = cvec[i];
1687 data.squares = squares;
1688 data.samples = samples;
1692 * Reset stat value to default
1697 const Params *params = safe_cast<const Params *>(info->storageParams);
1699 max_bucket = params->buckets - 1;
1702 size_type size = cvec.size();
1703 for (off_type i = 0; i < size; ++i)
1704 cvec[i] = Counter();
1707 squares = Counter();
1708 samples = Counter();
1714 * Templatized storage and interface for a distribution that calculates mean
1720 struct Params : public DistParams
1722 Params() : DistParams(Deviation) {}
1726 /** The current sum. */
1728 /** The sum of squares. */
1730 /** The number of samples. */
1735 * Create and initialize this storage.
1737 SampleStor(Info *info)
1738 : sum(Counter()), squares(Counter()), samples(Counter())
1742 * Add a value the given number of times to this running average.
1743 * Update the running sum and sum of squares, increment the number of
1744 * values seen by the given number.
1745 * @param val The value to add.
1746 * @param number The number of times to add the value.
1749 sample(Counter val, int number)
1751 sum += val * number;
1752 squares += val * val * number;
1757 * Return the number of entries in this stat, 1
1760 size_type size() const { return 1; }
1763 * Return true if no samples have been added.
1764 * @return True if no samples have been added.
1766 bool zero() const { return samples == Counter(); }
1769 prepare(Info *info, DistData &data)
1771 const Params *params = safe_cast<const Params *>(info->storageParams);
1773 assert(params->type == Deviation);
1774 data.type = params->type;
1776 data.squares = squares;
1777 data.samples = samples;
1781 * Reset stat value to default
1787 squares = Counter();
1788 samples = Counter();
1793 * Templatized storage for distribution that calculates per tick mean and
1799 struct Params : public DistParams
1801 Params() : DistParams(Deviation) {}
1805 /** Current total. */
1807 /** Current sum of squares. */
1812 * Create and initialize this storage.
1814 AvgSampleStor(Info *info)
1815 : sum(Counter()), squares(Counter())
1819 * Add a value to the distribution for the given number of times.
1820 * Update the running sum and sum of squares.
1821 * @param val The value to add.
1822 * @param number The number of times to add the value.
1825 sample(Counter val, int number)
1827 sum += val * number;
1828 squares += val * val * number;
1832 * Return the number of entries, in this case 1.
1835 size_type size() const { return 1; }
1838 * Return true if no samples have been added.
1839 * @return True if the sum is zero.
1841 bool zero() const { return sum == Counter(); }
1844 prepare(Info *info, DistData &data)
1846 const Params *params = safe_cast<const Params *>(info->storageParams);
1848 assert(params->type == Deviation);
1849 data.type = params->type;
1851 data.squares = squares;
1852 data.samples = curTick();
1856 * Reset stat value to default
1862 squares = Counter();
1867 * Implementation of a distribution stat. The type of distribution is
1868 * determined by the Storage template. @sa ScalarBase
1870 template <class Derived, class Stor>
1871 class DistBase : public DataWrap<Derived, DistInfoProxy>
1874 typedef DistInfoProxy<Derived> Info;
1875 typedef Stor Storage;
1876 typedef typename Stor::Params Params;
1879 /** The storage for this stat. */
1880 M5_ALIGNED(8) char storage[sizeof(Storage)];
1884 * Retrieve the storage.
1885 * @return The storage object for this stat.
1890 return reinterpret_cast<Storage *>(storage);
1894 * Retrieve a const pointer to the storage.
1895 * @return A const pointer to the storage object for this stat.
1900 return reinterpret_cast<const Storage *>(storage);
1906 new (storage) Storage(this->info());
1911 DistBase(Group *parent, const char *name, const char *desc)
1912 : DataWrap<Derived, DistInfoProxy>(parent, name, desc)
1917 * Add a value to the distribtion n times. Calls sample on the storage
1919 * @param v The value to add.
1920 * @param n The number of times to add it, defaults to 1.
1922 template <typename U>
1923 void sample(const U &v, int n = 1) { data()->sample(v, n); }
1926 * Return the number of entries in this stat.
1927 * @return The number of entries.
1929 size_type size() const { return data()->size(); }
1931 * Return true if no samples have been added.
1932 * @return True if there haven't been any samples.
1934 bool zero() const { return data()->zero(); }
1939 Info *info = this->info();
1940 data()->prepare(info, info->data);
1944 * Reset stat value to default
1949 data()->reset(this->info());
1953 * Add the argument distribution to the this distribution.
1955 void add(DistBase &d) { data()->add(d.data()); }
1959 template <class Stat>
1962 template <class Derived, class Stor>
1963 class VectorDistBase : public DataWrapVec<Derived, VectorDistInfoProxy>
1966 typedef VectorDistInfoProxy<Derived> Info;
1967 typedef Stor Storage;
1968 typedef typename Stor::Params Params;
1969 typedef DistProxy<Derived> Proxy;
1970 friend class DistProxy<Derived>;
1971 friend class DataWrapVec<Derived, VectorDistInfoProxy>;
1979 data(off_type index)
1981 return &storage[index];
1985 data(off_type index) const
1987 return &storage[index];
1993 assert(s > 0 && "size must be positive!");
1994 assert(!storage && "already initialized");
1997 char *ptr = new char[_size * sizeof(Storage)];
1998 storage = reinterpret_cast<Storage *>(ptr);
2000 Info *info = this->info();
2001 for (off_type i = 0; i < _size; ++i)
2002 new (&storage[i]) Storage(info);
2008 VectorDistBase(Group *parent, const char *name, const char *desc)
2009 : DataWrapVec<Derived, VectorDistInfoProxy>(parent, name, desc),
2018 for (off_type i = 0; i < _size; ++i)
2019 data(i)->~Storage();
2020 delete [] reinterpret_cast<char *>(storage);
2023 Proxy operator[](off_type index)
2025 assert(index < size());
2026 return Proxy(this->self(), index);
2038 for (off_type i = 0; i < size(); ++i)
2039 if (!data(i)->zero())
2047 Info *info = this->info();
2048 size_type size = this->size();
2049 info->data.resize(size);
2050 for (off_type i = 0; i < size; ++i)
2051 data(i)->prepare(info, info->data[i]);
2057 return storage != NULL;
2061 template <class Stat>
2069 typename Stat::Storage *data() { return stat.data(index); }
2070 const typename Stat::Storage *data() const { return stat.data(index); }
2073 DistProxy(Stat &s, off_type i)
2077 DistProxy(const DistProxy &sp)
2078 : stat(sp.stat), index(sp.index)
2082 operator=(const DistProxy &sp)
2090 template <typename U>
2092 sample(const U &v, int n = 1)
2094 data()->sample(v, n);
2106 return data()->zero();
2110 * Proxy has no state. Nothing to reset.
2115 //////////////////////////////////////////////////////////////////////
2119 //////////////////////////////////////////////////////////////////////
2122 * Base class for formula statistic node. These nodes are used to build a tree
2123 * that represents the formula.
2129 * Return the number of nodes in the subtree starting at this node.
2130 * @return the number of nodes in this subtree.
2132 virtual size_type size() const = 0;
2134 * Return the result vector of this subtree.
2135 * @return The result vector of this subtree.
2137 virtual const VResult &result() const = 0;
2139 * Return the total of the result vector.
2140 * @return The total of the result vector.
2142 virtual Result total() const = 0;
2147 virtual std::string str() const = 0;
2152 /** Shared pointer to a function Node. */
2153 typedef std::shared_ptr<Node> NodePtr;
2155 class ScalarStatNode : public Node
2158 const ScalarInfo *data;
2159 mutable VResult vresult;
2162 ScalarStatNode(const ScalarInfo *d) : data(d), vresult(1) {}
2167 vresult[0] = data->result();
2171 Result total() const { return data->result(); };
2173 size_type size() const { return 1; }
2178 std::string str() const { return data->name; }
2181 template <class Stat>
2182 class ScalarProxyNode : public Node
2185 const ScalarProxy<Stat> proxy;
2186 mutable VResult vresult;
2189 ScalarProxyNode(const ScalarProxy<Stat> &p)
2190 : proxy(p), vresult(1)
2196 vresult[0] = proxy.result();
2203 return proxy.result();
2222 class VectorStatNode : public Node
2225 const VectorInfo *data;
2228 VectorStatNode(const VectorInfo *d) : data(d) { }
2229 const VResult &result() const { return data->result(); }
2230 Result total() const { return data->total(); };
2232 size_type size() const { return data->size(); }
2234 std::string str() const { return data->name; }
2238 class ConstNode : public Node
2244 ConstNode(T s) : vresult(1, (Result)s) {}
2245 const VResult &result() const { return vresult; }
2246 Result total() const { return vresult[0]; };
2247 size_type size() const { return 1; }
2248 std::string str() const { return std::to_string(vresult[0]); }
2252 class ConstVectorNode : public Node
2258 ConstVectorNode(const T &s) : vresult(s.begin(), s.end()) {}
2259 const VResult &result() const { return vresult; }
2264 size_type size = this->size();
2266 for (off_type i = 0; i < size; i++)
2271 size_type size() const { return vresult.size(); }
2275 size_type size = this->size();
2276 std::string tmp = "(";
2277 for (off_type i = 0; i < size; i++)
2278 tmp += csprintf("%s ", std::to_string(vresult[i]));
2288 struct OpString<std::plus<Result> >
2290 static std::string str() { return "+"; }
2294 struct OpString<std::minus<Result> >
2296 static std::string str() { return "-"; }
2300 struct OpString<std::multiplies<Result> >
2302 static std::string str() { return "*"; }
2306 struct OpString<std::divides<Result> >
2308 static std::string str() { return "/"; }
2312 struct OpString<std::modulus<Result> >
2314 static std::string str() { return "%"; }
2318 struct OpString<std::negate<Result> >
2320 static std::string str() { return "-"; }
2324 class UnaryNode : public Node
2328 mutable VResult vresult;
2331 UnaryNode(NodePtr &p) : l(p) {}
2336 const VResult &lvec = l->result();
2337 size_type size = lvec.size();
2341 vresult.resize(size);
2343 for (off_type i = 0; i < size; ++i)
2344 vresult[i] = op(lvec[i]);
2352 const VResult &vec = this->result();
2354 for (off_type i = 0; i < size(); i++)
2359 size_type size() const { return l->size(); }
2364 return OpString<Op>::str() + l->str();
2369 class BinaryNode : public Node
2374 mutable VResult vresult;
2377 BinaryNode(NodePtr &a, NodePtr &b) : l(a), r(b) {}
2380 result() const override
2383 const VResult &lvec = l->result();
2384 const VResult &rvec = r->result();
2386 assert(lvec.size() > 0 && rvec.size() > 0);
2388 if (lvec.size() == 1 && rvec.size() == 1) {
2390 vresult[0] = op(lvec[0], rvec[0]);
2391 } else if (lvec.size() == 1) {
2392 size_type size = rvec.size();
2393 vresult.resize(size);
2394 for (off_type i = 0; i < size; ++i)
2395 vresult[i] = op(lvec[0], rvec[i]);
2396 } else if (rvec.size() == 1) {
2397 size_type size = lvec.size();
2398 vresult.resize(size);
2399 for (off_type i = 0; i < size; ++i)
2400 vresult[i] = op(lvec[i], rvec[0]);
2401 } else if (rvec.size() == lvec.size()) {
2402 size_type size = rvec.size();
2403 vresult.resize(size);
2404 for (off_type i = 0; i < size; ++i)
2405 vresult[i] = op(lvec[i], rvec[i]);
2412 total() const override
2414 const VResult &vec = this->result();
2415 const VResult &lvec = l->result();
2416 const VResult &rvec = r->result();
2422 assert(lvec.size() > 0 && rvec.size() > 0);
2423 assert(lvec.size() == rvec.size() ||
2424 lvec.size() == 1 || rvec.size() == 1);
2426 /** If vectors are the same divide their sums (x0+x1)/(y0+y1) */
2427 if (lvec.size() == rvec.size() && lvec.size() > 1) {
2428 for (off_type i = 0; i < size(); ++i) {
2432 return op(lsum, rsum);
2435 /** Otherwise divide each item by the divisor */
2436 for (off_type i = 0; i < size(); ++i) {
2444 size() const override
2446 size_type ls = l->size();
2447 size_type rs = r->size();
2450 } else if (rs == 1) {
2453 assert(ls == rs && "Node vector sizes are not equal");
2459 str() const override
2461 return csprintf("(%s %s %s)", l->str(), OpString<Op>::str(), r->str());
2466 class SumNode : public Node
2470 mutable VResult vresult;
2473 SumNode(NodePtr &p) : l(p), vresult(1) {}
2478 const VResult &lvec = l->result();
2479 size_type size = lvec.size();
2485 for (off_type i = 0; i < size; ++i)
2486 vresult[0] = op(vresult[0], lvec[i]);
2494 const VResult &lvec = l->result();
2495 size_type size = lvec.size();
2498 Result result = 0.0;
2501 for (off_type i = 0; i < size; ++i)
2502 result = op(result, lvec[i]);
2507 size_type size() const { return 1; }
2512 return csprintf("total(%s)", l->str());
2517 //////////////////////////////////////////////////////////////////////
2519 // Visible Statistics Types
2521 //////////////////////////////////////////////////////////////////////
2523 * @defgroup VisibleStats "Statistic Types"
2524 * These are the statistics that are used in the simulator.
2529 * This is a simple scalar statistic, like a counter.
2530 * @sa Stat, ScalarBase, StatStor
2532 class Scalar : public ScalarBase<Scalar, StatStor>
2535 using ScalarBase<Scalar, StatStor>::operator=;
2537 Scalar(Group *parent = nullptr, const char *name = nullptr,
2538 const char *desc = nullptr)
2539 : ScalarBase<Scalar, StatStor>(parent, name, desc)
2545 * A stat that calculates the per tick average of a value.
2546 * @sa Stat, ScalarBase, AvgStor
2548 class Average : public ScalarBase<Average, AvgStor>
2551 using ScalarBase<Average, AvgStor>::operator=;
2553 Average(Group *parent = nullptr, const char *name = nullptr,
2554 const char *desc = nullptr)
2555 : ScalarBase<Average, AvgStor>(parent, name, desc)
2560 class Value : public ValueBase<Value>
2563 Value(Group *parent = nullptr, const char *name = nullptr,
2564 const char *desc = nullptr)
2565 : ValueBase<Value>(parent, name, desc)
2571 * A vector of scalar stats.
2572 * @sa Stat, VectorBase, StatStor
2574 class Vector : public VectorBase<Vector, StatStor>
2577 Vector(Group *parent = nullptr, const char *name = nullptr,
2578 const char *desc = nullptr)
2579 : VectorBase<Vector, StatStor>(parent, name, desc)
2585 * A vector of Average stats.
2586 * @sa Stat, VectorBase, AvgStor
2588 class AverageVector : public VectorBase<AverageVector, AvgStor>
2591 AverageVector(Group *parent = nullptr, const char *name = nullptr,
2592 const char *desc = nullptr)
2593 : VectorBase<AverageVector, AvgStor>(parent, name, desc)
2599 * A 2-Dimensional vecto of scalar stats.
2600 * @sa Stat, Vector2dBase, StatStor
2602 class Vector2d : public Vector2dBase<Vector2d, StatStor>
2605 Vector2d(Group *parent = nullptr, const char *name = nullptr,
2606 const char *desc = nullptr)
2607 : Vector2dBase<Vector2d, StatStor>(parent, name, desc)
2613 * A simple distribution stat.
2614 * @sa Stat, DistBase, DistStor
2616 class Distribution : public DistBase<Distribution, DistStor>
2619 Distribution(Group *parent = nullptr, const char *name = nullptr,
2620 const char *desc = nullptr)
2621 : DistBase<Distribution, DistStor>(parent, name, desc)
2626 * Set the parameters of this distribution. @sa DistStor::Params
2627 * @param min The minimum value of the distribution.
2628 * @param max The maximum value of the distribution.
2629 * @param bkt The number of values in each bucket.
2630 * @return A reference to this distribution.
2633 init(Counter min, Counter max, Counter bkt)
2635 DistStor::Params *params = new DistStor::Params;
2638 params->bucket_size = bkt;
2639 // Division by zero is especially serious in an Aarch64 host,
2640 // where it gets rounded to allocate 32GiB RAM.
2642 params->buckets = (size_type)ceil((max - min + 1.0) / bkt);
2643 this->setParams(params);
2645 return this->self();
2650 * A simple histogram stat.
2651 * @sa Stat, DistBase, HistStor
2653 class Histogram : public DistBase<Histogram, HistStor>
2656 Histogram(Group *parent = nullptr, const char *name = nullptr,
2657 const char *desc = nullptr)
2658 : DistBase<Histogram, HistStor>(parent, name, desc)
2663 * Set the parameters of this histogram. @sa HistStor::Params
2664 * @param size The number of buckets in the histogram
2665 * @return A reference to this histogram.
2668 init(size_type size)
2670 HistStor::Params *params = new HistStor::Params;
2671 params->buckets = size;
2672 this->setParams(params);
2674 return this->self();
2679 * Calculates the mean and variance of all the samples.
2680 * @sa DistBase, SampleStor
2682 class StandardDeviation : public DistBase<StandardDeviation, SampleStor>
2686 * Construct and initialize this distribution.
2688 StandardDeviation(Group *parent = nullptr, const char *name = nullptr,
2689 const char *desc = nullptr)
2690 : DistBase<StandardDeviation, SampleStor>(parent, name, desc)
2692 SampleStor::Params *params = new SampleStor::Params;
2694 this->setParams(params);
2699 * Calculates the per tick mean and variance of the samples.
2700 * @sa DistBase, AvgSampleStor
2702 class AverageDeviation : public DistBase<AverageDeviation, AvgSampleStor>
2706 * Construct and initialize this distribution.
2708 AverageDeviation(Group *parent = nullptr, const char *name = nullptr,
2709 const char *desc = nullptr)
2710 : DistBase<AverageDeviation, AvgSampleStor>(parent, name, desc)
2712 AvgSampleStor::Params *params = new AvgSampleStor::Params;
2714 this->setParams(params);
2719 * A vector of distributions.
2720 * @sa VectorDistBase, DistStor
2722 class VectorDistribution : public VectorDistBase<VectorDistribution, DistStor>
2725 VectorDistribution(Group *parent = nullptr, const char *name = nullptr,
2726 const char *desc = nullptr)
2727 : VectorDistBase<VectorDistribution, DistStor>(parent, name, desc)
2732 * Initialize storage and parameters for this distribution.
2733 * @param size The size of the vector (the number of distributions).
2734 * @param min The minimum value of the distribution.
2735 * @param max The maximum value of the distribution.
2736 * @param bkt The number of values in each bucket.
2737 * @return A reference to this distribution.
2739 VectorDistribution &
2740 init(size_type size, Counter min, Counter max, Counter bkt)
2742 DistStor::Params *params = new DistStor::Params;
2745 params->bucket_size = bkt;
2746 params->buckets = (size_type)ceil((max - min + 1.0) / bkt);
2747 this->setParams(params);
2749 return this->self();
2754 * This is a vector of StandardDeviation stats.
2755 * @sa VectorDistBase, SampleStor
2757 class VectorStandardDeviation
2758 : public VectorDistBase<VectorStandardDeviation, SampleStor>
2761 VectorStandardDeviation(Group *parent = nullptr, const char *name = nullptr,
2762 const char *desc = nullptr)
2763 : VectorDistBase<VectorStandardDeviation, SampleStor>(parent, name,
2769 * Initialize storage for this distribution.
2770 * @param size The size of the vector.
2771 * @return A reference to this distribution.
2773 VectorStandardDeviation &
2774 init(size_type size)
2776 SampleStor::Params *params = new SampleStor::Params;
2778 this->setParams(params);
2779 return this->self();
2784 * This is a vector of AverageDeviation stats.
2785 * @sa VectorDistBase, AvgSampleStor
2787 class VectorAverageDeviation
2788 : public VectorDistBase<VectorAverageDeviation, AvgSampleStor>
2791 VectorAverageDeviation(Group *parent = nullptr, const char *name = nullptr,
2792 const char *desc = nullptr)
2793 : VectorDistBase<VectorAverageDeviation, AvgSampleStor>(parent, name,
2799 * Initialize storage for this distribution.
2800 * @param size The size of the vector.
2801 * @return A reference to this distribution.
2803 VectorAverageDeviation &
2804 init(size_type size)
2806 AvgSampleStor::Params *params = new AvgSampleStor::Params;
2808 this->setParams(params);
2809 return this->self();
2813 template <class Stat>
2814 class FormulaInfoProxy : public InfoProxy<Stat, FormulaInfo>
2817 mutable VResult vec;
2818 mutable VCounter cvec;
2821 FormulaInfoProxy(Stat &stat) : InfoProxy<Stat, FormulaInfo>(stat) {}
2823 size_type size() const { return this->s.size(); }
2828 this->s.result(vec);
2831 Result total() const { return this->s.total(); }
2832 VCounter &value() const { return cvec; }
2834 std::string str() const { return this->s.str(); }
2837 template <class Stat>
2838 class SparseHistInfoProxy : public InfoProxy<Stat, SparseHistInfo>
2841 SparseHistInfoProxy(Stat &stat) : InfoProxy<Stat, SparseHistInfo>(stat) {}
2845 * Implementation of a sparse histogram stat. The storage class is
2846 * determined by the Storage template.
2848 template <class Derived, class Stor>
2849 class SparseHistBase : public DataWrap<Derived, SparseHistInfoProxy>
2852 typedef SparseHistInfoProxy<Derived> Info;
2853 typedef Stor Storage;
2854 typedef typename Stor::Params Params;
2857 /** The storage for this stat. */
2858 char storage[sizeof(Storage)];
2862 * Retrieve the storage.
2863 * @return The storage object for this stat.
2868 return reinterpret_cast<Storage *>(storage);
2872 * Retrieve a const pointer to the storage.
2873 * @return A const pointer to the storage object for this stat.
2878 return reinterpret_cast<const Storage *>(storage);
2884 new (storage) Storage(this->info());
2889 SparseHistBase(Group *parent, const char *name, const char *desc)
2890 : DataWrap<Derived, SparseHistInfoProxy>(parent, name, desc)
2895 * Add a value to the distribtion n times. Calls sample on the storage
2897 * @param v The value to add.
2898 * @param n The number of times to add it, defaults to 1.
2900 template <typename U>
2901 void sample(const U &v, int n = 1) { data()->sample(v, n); }
2904 * Return the number of entries in this stat.
2905 * @return The number of entries.
2907 size_type size() const { return data()->size(); }
2909 * Return true if no samples have been added.
2910 * @return True if there haven't been any samples.
2912 bool zero() const { return data()->zero(); }
2917 Info *info = this->info();
2918 data()->prepare(info, info->data);
2922 * Reset stat value to default
2927 data()->reset(this->info());
2932 * Templatized storage and interface for a sparse histogram stat.
2934 class SparseHistStor
2937 /** The parameters for a sparse histogram stat. */
2938 struct Params : public DistParams
2940 Params() : DistParams(Hist) {}
2944 /** Counter for number of samples */
2946 /** Counter for each bucket. */
2950 SparseHistStor(Info *info)
2956 * Add a value to the distribution for the given number of times.
2957 * @param val The value to add.
2958 * @param number The number of times to add the value.
2961 sample(Counter val, int number)
2963 cmap[val] += number;
2968 * Return the number of buckets in this distribution.
2969 * @return the number of buckets.
2971 size_type size() const { return cmap.size(); }
2974 * Returns true if any calls to sample have been made.
2975 * @return True if any values have been sampled.
2980 return samples == Counter();
2984 prepare(Info *info, SparseHistData &data)
2986 MCounter::iterator it;
2988 for (it = cmap.begin(); it != cmap.end(); it++) {
2989 data.cmap[(*it).first] = (*it).second;
2992 data.samples = samples;
2996 * Reset stat value to default
3006 class SparseHistogram : public SparseHistBase<SparseHistogram, SparseHistStor>
3009 SparseHistogram(Group *parent = nullptr, const char *name = nullptr,
3010 const char *desc = nullptr)
3011 : SparseHistBase<SparseHistogram, SparseHistStor>(parent, name, desc)
3016 * Set the parameters of this histogram. @sa HistStor::Params
3017 * @param size The number of buckets in the histogram
3018 * @return A reference to this histogram.
3021 init(size_type size)
3023 SparseHistStor::Params *params = new SparseHistStor::Params;
3024 this->setParams(params);
3026 return this->self();
3032 * A formula for statistics that is calculated when printed. A formula is
3033 * stored as a tree of Nodes that represent the equation to calculate.
3034 * @sa Stat, ScalarStat, VectorStat, Node, Temp
3036 class Formula : public DataWrapVec<Formula, FormulaInfoProxy>
3039 /** The root of the tree which represents the Formula */
3045 * Create and initialize thie formula, and register it with the database.
3047 Formula(Group *parent = nullptr, const char *name = nullptr,
3048 const char *desc = nullptr);
3050 Formula(Group *parent, const char *name, const char *desc,
3054 * Set an unitialized Formula to the given root.
3055 * @param r The root of the expression tree.
3056 * @return a reference to this formula.
3058 const Formula &operator=(const Temp &r);
3060 template<typename T>
3061 const Formula &operator=(const T &v)
3068 * Add the given tree to the existing one.
3069 * @param r The root of the expression tree.
3070 * @return a reference to this formula.
3072 const Formula &operator+=(Temp r);
3075 * Divide the existing tree by the given one.
3076 * @param r The root of the expression tree.
3077 * @return a reference to this formula.
3079 const Formula &operator/=(Temp r);
3082 * Return the result of the Fomula in a vector. If there were no Vector
3083 * components to the Formula, then the vector is size 1. If there were,
3084 * like x/y with x being a vector of size 3, then the result returned will
3085 * be x[0]/y, x[1]/y, x[2]/y, respectively.
3086 * @return The result vector.
3088 void result(VResult &vec) const;
3091 * Return the total Formula result. If there is a Vector
3092 * component to this Formula, then this is the result of the
3093 * Formula if the formula is applied after summing all the
3094 * components of the Vector. For example, if Formula is x/y where
3095 * x is size 3, then total() will return (x[1]+x[2]+x[3])/y. If
3096 * there is no Vector component, total() returns the same value as
3097 * the first entry in the VResult val() returns.
3098 * @return The total of the result vector.
3100 Result total() const;
3103 * Return the number of elements in the tree.
3105 size_type size() const;
3110 * Formulas don't need to be reset
3119 std::string str() const;
3122 class FormulaNode : public Node
3125 const Formula &formula;
3126 mutable VResult vec;
3129 FormulaNode(const Formula &f) : formula(f) {}
3131 size_type size() const { return formula.size(); }
3132 const VResult &result() const { formula.result(vec); return vec; }
3133 Result total() const { return formula.total(); }
3135 std::string str() const { return formula.str(); }
3139 * Helper class to construct formula node trees.
3145 * Pointer to a Node object.
3151 * Copy the given pointer to this class.
3152 * @param n A pointer to a Node object to copy.
3154 Temp(const NodePtr &n) : node(n) { }
3156 Temp(NodePtr &&n) : node(std::move(n)) { }
3159 * Return the node pointer.
3160 * @return the node pointer.
3162 operator NodePtr&() { return node; }
3165 * Makde gcc < 4.6.3 happy and explicitly get the underlying node.
3167 NodePtr getNodePtr() const { return node; }
3171 * Create a new ScalarStatNode.
3172 * @param s The ScalarStat to place in a node.
3174 Temp(const Scalar &s)
3175 : node(new ScalarStatNode(s.info()))
3179 * Create a new ScalarStatNode.
3180 * @param s The ScalarStat to place in a node.
3182 Temp(const Value &s)
3183 : node(new ScalarStatNode(s.info()))
3187 * Create a new ScalarStatNode.
3188 * @param s The ScalarStat to place in a node.
3190 Temp(const Average &s)
3191 : node(new ScalarStatNode(s.info()))
3195 * Create a new VectorStatNode.
3196 * @param s The VectorStat to place in a node.
3198 Temp(const Vector &s)
3199 : node(new VectorStatNode(s.info()))
3202 Temp(const AverageVector &s)
3203 : node(new VectorStatNode(s.info()))
3209 Temp(const Formula &f)
3210 : node(new FormulaNode(f))
3214 * Create a new ScalarProxyNode.
3215 * @param p The ScalarProxy to place in a node.
3217 template <class Stat>
3218 Temp(const ScalarProxy<Stat> &p)
3219 : node(new ScalarProxyNode<Stat>(p))
3223 * Create a ConstNode
3224 * @param value The value of the const node.
3226 Temp(signed char value)
3227 : node(new ConstNode<signed char>(value))
3231 * Create a ConstNode
3232 * @param value The value of the const node.
3234 Temp(unsigned char value)
3235 : node(new ConstNode<unsigned char>(value))
3239 * Create a ConstNode
3240 * @param value The value of the const node.
3242 Temp(signed short value)
3243 : node(new ConstNode<signed short>(value))
3247 * Create a ConstNode
3248 * @param value The value of the const node.
3250 Temp(unsigned short value)
3251 : node(new ConstNode<unsigned short>(value))
3255 * Create a ConstNode
3256 * @param value The value of the const node.
3258 Temp(signed int value)
3259 : node(new ConstNode<signed int>(value))
3263 * Create a ConstNode
3264 * @param value The value of the const node.
3266 Temp(unsigned int value)
3267 : node(new ConstNode<unsigned int>(value))
3271 * Create a ConstNode
3272 * @param value The value of the const node.
3274 Temp(signed long value)
3275 : node(new ConstNode<signed long>(value))
3279 * Create a ConstNode
3280 * @param value The value of the const node.
3282 Temp(unsigned long value)
3283 : node(new ConstNode<unsigned long>(value))
3287 * Create a ConstNode
3288 * @param value The value of the const node.
3290 Temp(signed long long value)
3291 : node(new ConstNode<signed long long>(value))
3295 * Create a ConstNode
3296 * @param value The value of the const node.
3298 Temp(unsigned long long value)
3299 : node(new ConstNode<unsigned long long>(value))
3303 * Create a ConstNode
3304 * @param value The value of the const node.
3307 : node(new ConstNode<float>(value))
3311 * Create a ConstNode
3312 * @param value The value of the const node.
3315 : node(new ConstNode<double>(value))
3325 operator+(Temp l, Temp r)
3327 return Temp(std::make_shared<BinaryNode<std::plus<Result> > >(l, r));
3331 operator-(Temp l, Temp r)
3333 return Temp(std::make_shared<BinaryNode<std::minus<Result> > >(l, r));
3337 operator*(Temp l, Temp r)
3339 return Temp(std::make_shared<BinaryNode<std::multiplies<Result> > >(l, r));
3343 operator/(Temp l, Temp r)
3345 return Temp(std::make_shared<BinaryNode<std::divides<Result> > >(l, r));
3351 return Temp(std::make_shared<UnaryNode<std::negate<Result> > >(l));
3354 template <typename T>
3358 return Temp(std::make_shared<ConstNode<T> >(val));
3361 template <typename T>
3363 constantVector(T val)
3365 return Temp(std::make_shared<ConstVectorNode<T> >(val));
3371 return Temp(std::make_shared<SumNode<std::plus<Result> > >(val));
3374 /** Dump all statistics data to the registered outputs */
3379 const Info* resolve(const std::string &name);
3382 * Register reset and dump handlers. These are the functions which
3383 * will actually perform the whole statistics reset/dump actions
3384 * including processing the reset/dump callbacks
3386 typedef void (*Handler)();
3388 void registerHandlers(Handler reset_handler, Handler dump_handler);
3391 * Register a callback that should be called whenever statistics are
3394 void registerResetCallback(const std::function<void()> &callback);
3397 * Register a callback that should be called whenever statistics are
3398 * about to be dumped
3400 void registerDumpCallback(const std::function<void()> &callback);
3403 * Process all the callbacks in the reset callbacks queue
3405 void processResetQueue();
3408 * Process all the callbacks in the dump callbacks queue
3410 void processDumpQueue();
3412 std::list<Info *> &statsList();
3414 typedef std::map<const void *, Info *> MapType;
3415 MapType &statsMap();
3417 } // namespace Stats
3419 void debugDumpStats();
3421 #endif // __BASE_STATISTICS_HH__