2 * Copyright (c) 2003-2005 The Regents of The University of Michigan
3 * Copyright (c) 2017, Centre National de la Recherche Scientifique
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * Authors: Nathan Binkert
34 * Declaration of Statistics objects.
40 * Generalized N-dimensinal vector
44 * -- these both can use the same function that prints out a
45 * specific set of stats
46 * VectorStandardDeviation totals
49 #ifndef __BASE_STATISTICS_HH__
50 #define __BASE_STATISTICS_HH__
66 #include "base/stats/info.hh"
67 #include "base/stats/output.hh"
68 #include "base/stats/types.hh"
69 #include "base/cast.hh"
70 #include "base/cprintf.hh"
71 #include "base/intmath.hh"
72 #include "base/str.hh"
73 #include "base/types.hh"
77 /** The current simulated tick. */
78 extern Tick curTick();
80 /* A namespace for all of the Statistics */
83 template <class Stat, class Base>
84 class InfoProxy : public Base
90 InfoProxy(Stat &stat) : s(stat) {}
92 bool check() const { return s.check(); }
93 void prepare() { s.prepare(); }
94 void reset() { s.reset(); }
96 visit(Output &visitor)
98 visitor.visit(*static_cast<Base *>(this));
100 bool zero() const { return s.zero(); }
103 template <class Stat>
104 class ScalarInfoProxy : public InfoProxy<Stat, ScalarInfo>
107 ScalarInfoProxy(Stat &stat) : InfoProxy<Stat, ScalarInfo>(stat) {}
109 Counter value() const { return this->s.value(); }
110 Result result() const { return this->s.result(); }
111 Result total() const { return this->s.total(); }
114 template <class Stat>
115 class VectorInfoProxy : public InfoProxy<Stat, VectorInfo>
118 mutable VCounter cvec;
119 mutable VResult rvec;
122 VectorInfoProxy(Stat &stat) : InfoProxy<Stat, VectorInfo>(stat) {}
124 size_type size() const { return this->s.size(); }
136 this->s.result(rvec);
140 Result total() const { return this->s.total(); }
143 template <class Stat>
144 class DistInfoProxy : public InfoProxy<Stat, DistInfo>
147 DistInfoProxy(Stat &stat) : InfoProxy<Stat, DistInfo>(stat) {}
150 template <class Stat>
151 class VectorDistInfoProxy : public InfoProxy<Stat, VectorDistInfo>
154 VectorDistInfoProxy(Stat &stat) : InfoProxy<Stat, VectorDistInfo>(stat) {}
156 size_type size() const { return this->s.size(); }
159 template <class Stat>
160 class Vector2dInfoProxy : public InfoProxy<Stat, Vector2dInfo>
163 Vector2dInfoProxy(Stat &stat) : InfoProxy<Stat, Vector2dInfo>(stat) {}
165 Result total() const { return this->s.total(); }
170 virtual ~StorageParams();
176 /** Set up an info class for this statistic */
177 void setInfo(Info *info);
178 /** Save Storage class parameters if any */
179 void setParams(const StorageParams *params);
180 /** Save Storage class parameters if any */
183 /** Grab the information class for this statistic */
185 /** Grab the information class for this statistic */
186 const Info *info() const;
190 * Reset the stat to the default state.
195 * @return true if this stat has a value and satisfies its
196 * requirement as a prereq
198 bool zero() const { return true; }
201 * Check that this stat has been set up properly and is ready for
203 * @return true for success
205 bool check() const { return true; }
208 template <class Derived, template <class> class InfoProxyType>
209 class DataWrap : public InfoAccess
212 typedef InfoProxyType<Derived> Info;
215 Derived &self() { return *static_cast<Derived *>(this); }
221 return safe_cast<Info *>(InfoAccess::info());
228 return safe_cast<const Info *>(InfoAccess::info());
233 * Copy constructor, copies are not allowed.
235 DataWrap(const DataWrap &stat) = delete;
240 void operator=(const DataWrap &) {}
245 this->setInfo(new Info(self()));
249 * Set the name and marks this stat to print at the end of simulation.
250 * @param name The new name.
251 * @return A reference to this stat.
254 name(const std::string &name)
256 Info *info = this->info();
258 info->flags.set(display);
261 const std::string &name() const { return this->info()->name; }
264 * Set the character(s) used between the name and vector number
265 * on vectors, dist, etc.
266 * @param _sep The new separator string
267 * @return A reference to this stat.
270 setSeparator(const std::string &_sep)
272 this->info()->setSeparator(_sep);
275 const std::string &setSeparator() const
277 return this->info()->separatorString;
281 * Set the description and marks this stat to print at the end of
283 * @param desc The new description.
284 * @return A reference to this stat.
287 desc(const std::string &_desc)
289 this->info()->desc = _desc;
294 * Set the precision and marks this stat to print at the end of simulation.
295 * @param _precision The new precision
296 * @return A reference to this stat.
299 precision(int _precision)
301 this->info()->precision = _precision;
306 * Set the flags and marks this stat to print at the end of simulation.
307 * @param f The new flags.
308 * @return A reference to this stat.
313 this->info()->flags.set(_flags);
318 * Set the prerequisite stat and marks this stat to print at the end of
320 * @param prereq The prerequisite stat.
321 * @return A reference to this stat.
323 template <class Stat>
325 prereq(const Stat &prereq)
327 this->info()->prereq = prereq.info();
332 template <class Derived, template <class> class InfoProxyType>
333 class DataWrapVec : public DataWrap<Derived, InfoProxyType>
336 typedef InfoProxyType<Derived> Info;
341 DataWrapVec(const DataWrapVec &ref)
344 void operator=(const DataWrapVec &)
347 // The following functions are specific to vectors. If you use them
348 // in a non vector context, you will get a nice compiler error!
351 * Set the subfield name for the given index, and marks this stat to print
352 * at the end of simulation.
353 * @param index The subfield index.
354 * @param name The new name of the subfield.
355 * @return A reference to this stat.
358 subname(off_type index, const std::string &name)
360 Derived &self = this->self();
361 Info *info = self.info();
363 std::vector<std::string> &subn = info->subnames;
364 if (subn.size() <= index)
365 subn.resize(index + 1);
370 // The following functions are specific to 2d vectors. If you use
371 // them in a non vector context, you will get a nice compiler
372 // error because info doesn't have the right variables.
375 * Set the subfield description for the given index and marks this stat to
376 * print at the end of simulation.
377 * @param index The subfield index.
378 * @param desc The new description of the subfield
379 * @return A reference to this stat.
382 subdesc(off_type index, const std::string &desc)
384 Info *info = this->info();
386 std::vector<std::string> &subd = info->subdescs;
387 if (subd.size() <= index)
388 subd.resize(index + 1);
397 Derived &self = this->self();
398 Info *info = this->info();
400 size_t size = self.size();
401 for (off_type i = 0; i < size; ++i)
402 self.data(i)->prepare(info);
408 Derived &self = this->self();
409 Info *info = this->info();
411 size_t size = self.size();
412 for (off_type i = 0; i < size; ++i)
413 self.data(i)->reset(info);
417 template <class Derived, template <class> class InfoProxyType>
418 class DataWrapVec2d : public DataWrapVec<Derived, InfoProxyType>
421 typedef InfoProxyType<Derived> Info;
424 * @warning This makes the assumption that if you're gonna subnames a 2d
425 * vector, you're subnaming across all y
428 ysubnames(const char **names)
430 Derived &self = this->self();
431 Info *info = this->info();
433 info->y_subnames.resize(self.y);
434 for (off_type i = 0; i < self.y; ++i)
435 info->y_subnames[i] = names[i];
440 ysubname(off_type index, const std::string &subname)
442 Derived &self = this->self();
443 Info *info = this->info();
445 assert(index < self.y);
446 info->y_subnames.resize(self.y);
447 info->y_subnames[index] = subname.c_str();
452 ysubname(off_type i) const
454 return this->info()->y_subnames[i];
459 //////////////////////////////////////////////////////////////////////
463 //////////////////////////////////////////////////////////////////////
466 * Templatized storage and interface for a simple scalar stat.
471 /** The statistic value. */
475 struct Params : public StorageParams {};
479 * Builds this storage element and calls the base constructor of the
487 * The the stat to the given value.
488 * @param val The new value.
490 void set(Counter val) { data = val; }
492 * Increment the stat by the given value.
493 * @param val The new value.
495 void inc(Counter val) { data += val; }
497 * Decrement the stat by the given value.
498 * @param val The new value.
500 void dec(Counter val) { data -= val; }
502 * Return the value of this stat as its base type.
503 * @return The value of this stat.
505 Counter value() const { return data; }
507 * Return the value of this stat as a result type.
508 * @return The value of this stat.
510 Result result() const { return (Result)data; }
512 * Prepare stat data for dumping or serialization
514 void prepare(Info *info) { }
516 * Reset stat value to default
518 void reset(Info *info) { data = Counter(); }
521 * @return true if zero value
523 bool zero() const { return data == Counter(); }
527 * Templatized storage and interface to a per-tick average stat. This keeps
528 * a current count and updates a total (count * ticks) when this count
529 * changes. This allows the quick calculation of a per tick count of the item
530 * being watched. This is good for keeping track of residencies in structures
531 * among other things.
536 /** The current count. */
538 /** The tick of the last reset */
540 /** The total count for all tick. */
541 mutable Result total;
542 /** The tick that current last changed. */
546 struct Params : public StorageParams {};
550 * Build and initializes this stat storage.
553 : current(0), lastReset(0), total(0), last(0)
557 * Set the current count to the one provided, update the total and last
559 * @param val The new count.
564 total += current * (curTick() - last);
570 * Increment the current count by the provided value, calls set.
571 * @param val The amount to increment.
573 void inc(Counter val) { set(current + val); }
576 * Deccrement the current count by the provided value, calls set.
577 * @param val The amount to decrement.
579 void dec(Counter val) { set(current - val); }
582 * Return the current count.
583 * @return The current count.
585 Counter value() const { return current; }
588 * Return the current average.
589 * @return The current average.
594 assert(last == curTick());
595 return (Result)(total + current) / (Result)(curTick() - lastReset + 1);
599 * @return true if zero value
601 bool zero() const { return total == 0.0; }
604 * Prepare stat data for dumping or serialization
609 total += current * (curTick() - last);
614 * Reset stat value to default
621 lastReset = curTick();
627 * Implementation of a scalar stat. The type of stat is determined by the
630 template <class Derived, class Stor>
631 class ScalarBase : public DataWrap<Derived, ScalarInfoProxy>
634 typedef Stor Storage;
635 typedef typename Stor::Params Params;
638 /** The storage of this stat. */
639 char storage[sizeof(Storage)] __attribute__ ((aligned (8)));
643 * Retrieve the storage.
644 * @param index The vector index to access.
645 * @return The storage object at the given index.
650 return reinterpret_cast<Storage *>(storage);
654 * Retrieve a const pointer to the storage.
655 * for the given index.
656 * @param index The vector index to access.
657 * @return A const pointer to the storage object at the given index.
662 return reinterpret_cast<const Storage *>(storage);
668 new (storage) Storage(this->info());
674 * Return the current value of this stat as its base type.
675 * @return The current value.
677 Counter value() const { return data()->value(); }
686 // Common operators for stats
688 * Increment the stat by 1. This calls the associated storage object inc
691 void operator++() { data()->inc(1); }
693 * Decrement the stat by 1. This calls the associated storage object dec
696 void operator--() { data()->dec(1); }
698 /** Increment the stat by 1. */
699 void operator++(int) { ++*this; }
700 /** Decrement the stat by 1. */
701 void operator--(int) { --*this; }
704 * Set the data value to the given value. This calls the associated storage
705 * object set function.
706 * @param v The new value.
708 template <typename U>
709 void operator=(const U &v) { data()->set(v); }
712 * Increment the stat by the given value. This calls the associated
713 * storage object inc function.
714 * @param v The value to add.
716 template <typename U>
717 void operator+=(const U &v) { data()->inc(v); }
720 * Decrement the stat by the given value. This calls the associated
721 * storage object dec function.
722 * @param v The value to substract.
724 template <typename U>
725 void operator-=(const U &v) { data()->dec(v); }
728 * Return the number of elements, always 1 for a scalar.
731 size_type size() const { return 1; }
733 Counter value() { return data()->value(); }
735 Result result() { return data()->result(); }
737 Result total() { return result(); }
739 bool zero() { return result() == 0.0; }
741 void reset() { data()->reset(this->info()); }
742 void prepare() { data()->prepare(this->info()); }
745 class ProxyInfo : public ScalarInfo
748 std::string str() const { return std::to_string(value()); }
749 size_type size() const { return 1; }
750 bool check() const { return true; }
753 bool zero() const { return value() == 0; }
755 void visit(Output &visitor) { visitor.visit(*this); }
759 class ValueProxy : public ProxyInfo
765 ValueProxy(T &val) : scalar(&val) {}
766 Counter value() const { return *scalar; }
767 Result result() const { return *scalar; }
768 Result total() const { return *scalar; }
772 class FunctorProxy : public ProxyInfo
778 FunctorProxy(T &func) : functor(&func) {}
779 Counter value() const { return (*functor)(); }
780 Result result() const { return (*functor)(); }
781 Result total() const { return (*functor)(); }
785 * A proxy similar to the FunctorProxy, but allows calling a method of a bound
786 * object, instead of a global free-standing function.
788 template <class T, class V>
789 class MethodProxy : public ProxyInfo
793 typedef V (T::*MethodPointer) () const;
794 MethodPointer method;
797 MethodProxy(T *obj, MethodPointer meth) : object(obj), method(meth) {}
798 Counter value() const { return (object->*method)(); }
799 Result result() const { return (object->*method)(); }
800 Result total() const { return (object->*method)(); }
803 template <class Derived>
804 class ValueBase : public DataWrap<Derived, ScalarInfoProxy>
810 ValueBase() : proxy(NULL) { }
811 ~ValueBase() { if (proxy) delete proxy; }
817 proxy = new ValueProxy<T>(value);
826 proxy = new FunctorProxy<T>(func);
832 * Extended functor that calls the specified method of the provided object.
834 * @param obj Pointer to the object whose method should be called.
835 * @param method Pointer of the function / method of the object.
836 * @return Updated stats item.
838 template <class T, class V>
840 method(T *obj, V (T::*method)() const)
842 proxy = new MethodProxy<T,V>(obj, method);
847 Counter value() { return proxy->value(); }
848 Result result() const { return proxy->result(); }
849 Result total() const { return proxy->total(); };
850 size_type size() const { return proxy->size(); }
852 std::string str() const { return proxy->str(); }
853 bool zero() const { return proxy->zero(); }
854 bool check() const { return proxy != NULL; }
859 //////////////////////////////////////////////////////////////////////
863 //////////////////////////////////////////////////////////////////////
866 * A proxy class to access the stat at a given index in a VectorBase stat.
867 * Behaves like a ScalarBase.
869 template <class Stat>
873 /** Pointer to the parent Vector. */
876 /** The index to access in the parent VectorBase. */
881 * Return the current value of this stat as its base type.
882 * @return The current value.
884 Counter value() const { return stat.data(index)->value(); }
887 * Return the current value of this statas a result type.
888 * @return The current value.
890 Result result() const { return stat.data(index)->result(); }
894 * Create and initialize this proxy, do not register it with the database.
895 * @param i The index to access.
897 ScalarProxy(Stat &s, off_type i)
903 * Create a copy of the provided ScalarProxy.
904 * @param sp The proxy to copy.
906 ScalarProxy(const ScalarProxy &sp)
907 : stat(sp.stat), index(sp.index)
911 * Set this proxy equal to the provided one.
912 * @param sp The proxy to copy.
913 * @return A reference to this proxy.
916 operator=(const ScalarProxy &sp)
924 // Common operators for stats
926 * Increment the stat by 1. This calls the associated storage object inc
929 void operator++() { stat.data(index)->inc(1); }
931 * Decrement the stat by 1. This calls the associated storage object dec
934 void operator--() { stat.data(index)->dec(1); }
936 /** Increment the stat by 1. */
937 void operator++(int) { ++*this; }
938 /** Decrement the stat by 1. */
939 void operator--(int) { --*this; }
942 * Set the data value to the given value. This calls the associated storage
943 * object set function.
944 * @param v The new value.
946 template <typename U>
948 operator=(const U &v)
950 stat.data(index)->set(v);
954 * Increment the stat by the given value. This calls the associated
955 * storage object inc function.
956 * @param v The value to add.
958 template <typename U>
960 operator+=(const U &v)
962 stat.data(index)->inc(v);
966 * Decrement the stat by the given value. This calls the associated
967 * storage object dec function.
968 * @param v The value to substract.
970 template <typename U>
972 operator-=(const U &v)
974 stat.data(index)->dec(v);
978 * Return the number of elements, always 1 for a scalar.
981 size_type size() const { return 1; }
987 return csprintf("%s[%d]", stat.info()->name, index);
992 * Implementation of a vector of stats. The type of stat is determined by the
993 * Storage class. @sa ScalarBase
995 template <class Derived, class Stor>
996 class VectorBase : public DataWrapVec<Derived, VectorInfoProxy>
999 typedef Stor Storage;
1000 typedef typename Stor::Params Params;
1003 typedef ScalarProxy<Derived> Proxy;
1004 friend class ScalarProxy<Derived>;
1005 friend class DataWrapVec<Derived, VectorInfoProxy>;
1008 /** The storage of this stat. */
1014 * Retrieve the storage.
1015 * @param index The vector index to access.
1016 * @return The storage object at the given index.
1018 Storage *data(off_type index) { return &storage[index]; }
1021 * Retrieve a const pointer to the storage.
1022 * @param index The vector index to access.
1023 * @return A const pointer to the storage object at the given index.
1025 const Storage *data(off_type index) const { return &storage[index]; }
1030 assert(s > 0 && "size must be positive!");
1031 assert(!storage && "already initialized");
1034 char *ptr = new char[_size * sizeof(Storage)];
1035 storage = reinterpret_cast<Storage *>(ptr);
1037 for (off_type i = 0; i < _size; ++i)
1038 new (&storage[i]) Storage(this->info());
1045 value(VCounter &vec) const
1048 for (off_type i = 0; i < size(); ++i)
1049 vec[i] = data(i)->value();
1053 * Copy the values to a local vector and return a reference to it.
1054 * @return A reference to a vector of the stat values.
1057 result(VResult &vec) const
1060 for (off_type i = 0; i < size(); ++i)
1061 vec[i] = data(i)->result();
1065 * Return a total of all entries in this vector.
1066 * @return The total of all vector entries.
1072 for (off_type i = 0; i < size(); ++i)
1073 total += data(i)->result();
1078 * @return the number of elements in this vector.
1080 size_type size() const { return _size; }
1085 for (off_type i = 0; i < size(); ++i)
1086 if (data(i)->zero())
1094 return storage != NULL;
1099 : storage(nullptr), _size(0)
1107 for (off_type i = 0; i < _size; ++i)
1108 data(i)->~Storage();
1109 delete [] reinterpret_cast<char *>(storage);
1113 * Set this vector to have the given size.
1114 * @param size The new size.
1115 * @return A reference to this stat.
1118 init(size_type size)
1120 Derived &self = this->self();
1126 * Return a reference (ScalarProxy) to the stat at the given index.
1127 * @param index The vector index to access.
1128 * @return A reference of the stat.
1131 operator[](off_type index)
1133 assert (index >= 0 && index < size());
1134 return Proxy(this->self(), index);
1138 template <class Stat>
1147 mutable VResult vec;
1149 typename Stat::Storage *
1150 data(off_type index)
1152 assert(index < len);
1153 return stat.data(offset + index);
1156 const typename Stat::Storage *
1157 data(off_type index) const
1159 assert(index < len);
1160 return stat.data(offset + index);
1169 for (off_type i = 0; i < size(); ++i)
1170 vec[i] = data(i)->result();
1179 for (off_type i = 0; i < size(); ++i)
1180 total += data(i)->result();
1185 VectorProxy(Stat &s, off_type o, size_type l)
1186 : stat(s), offset(o), len(l)
1190 VectorProxy(const VectorProxy &sp)
1191 : stat(sp.stat), offset(sp.offset), len(sp.len)
1196 operator=(const VectorProxy &sp)
1205 operator[](off_type index)
1207 assert (index >= 0 && index < size());
1208 return ScalarProxy<Stat>(stat, offset + index);
1211 size_type size() const { return len; }
1214 template <class Derived, class Stor>
1215 class Vector2dBase : public DataWrapVec2d<Derived, Vector2dInfoProxy>
1218 typedef Vector2dInfoProxy<Derived> Info;
1219 typedef Stor Storage;
1220 typedef typename Stor::Params Params;
1221 typedef VectorProxy<Derived> Proxy;
1222 friend class ScalarProxy<Derived>;
1223 friend class VectorProxy<Derived>;
1224 friend class DataWrapVec<Derived, Vector2dInfoProxy>;
1225 friend class DataWrapVec2d<Derived, Vector2dInfoProxy>;
1234 Storage *data(off_type index) { return &storage[index]; }
1235 const Storage *data(off_type index) const { return &storage[index]; }
1239 : x(0), y(0), _size(0), storage(nullptr)
1247 for (off_type i = 0; i < _size; ++i)
1248 data(i)->~Storage();
1249 delete [] reinterpret_cast<char *>(storage);
1253 init(size_type _x, size_type _y)
1255 assert(_x > 0 && _y > 0 && "sizes must be positive!");
1256 assert(!storage && "already initialized");
1258 Derived &self = this->self();
1259 Info *info = this->info();
1267 char *ptr = new char[_size * sizeof(Storage)];
1268 storage = reinterpret_cast<Storage *>(ptr);
1270 for (off_type i = 0; i < _size; ++i)
1271 new (&storage[i]) Storage(info);
1279 operator[](off_type index)
1281 off_type offset = index * y;
1282 assert (index >= 0 && offset + y <= size());
1283 return Proxy(this->self(), offset, y);
1296 return data(0)->zero();
1298 for (off_type i = 0; i < size(); ++i)
1299 if (!data(i)->zero())
1306 * Return a total of all entries in this vector.
1307 * @return The total of all vector entries.
1313 for (off_type i = 0; i < size(); ++i)
1314 total += data(i)->result();
1321 Info *info = this->info();
1322 size_type size = this->size();
1324 for (off_type i = 0; i < size; ++i)
1325 data(i)->prepare(info);
1327 info->cvec.resize(size);
1328 for (off_type i = 0; i < size; ++i)
1329 info->cvec[i] = data(i)->value();
1333 * Reset stat value to default
1338 Info *info = this->info();
1339 size_type size = this->size();
1340 for (off_type i = 0; i < size; ++i)
1341 data(i)->reset(info);
1347 return storage != NULL;
1351 //////////////////////////////////////////////////////////////////////
1353 // Non formula statistics
1355 //////////////////////////////////////////////////////////////////////
1356 /** The parameters for a distribution stat. */
1357 struct DistParams : public StorageParams
1359 const DistType type;
1360 DistParams(DistType t) : type(t) {}
1364 * Templatized storage and interface for a distribution stat.
1369 /** The parameters for a distribution stat. */
1370 struct Params : public DistParams
1372 /** The minimum value to track. */
1374 /** The maximum value to track. */
1376 /** The number of entries in each bucket. */
1377 Counter bucket_size;
1378 /** The number of buckets. Equal to (max-min)/bucket_size. */
1381 Params() : DistParams(Dist), min(0), max(0), bucket_size(0),
1386 /** The minimum value to track. */
1388 /** The maximum value to track. */
1390 /** The number of entries in each bucket. */
1391 Counter bucket_size;
1393 /** The smallest value sampled. */
1395 /** The largest value sampled. */
1397 /** The number of values sampled less than min. */
1399 /** The number of values sampled more than max. */
1401 /** The current sum. */
1403 /** The sum of squares. */
1405 /** The number of samples. */
1407 /** Counter for each bucket. */
1411 DistStor(Info *info)
1412 : cvec(safe_cast<const Params *>(info->storageParams)->buckets)
1418 * Add a value to the distribution for the given number of times.
1419 * @param val The value to add.
1420 * @param number The number of times to add the value.
1423 sample(Counter val, int number)
1425 if (val < min_track)
1426 underflow += number;
1427 else if (val > max_track)
1431 (size_type)std::floor((val - min_track) / bucket_size);
1432 assert(index < size());
1433 cvec[index] += number;
1442 sum += val * number;
1443 squares += val * val * number;
1448 * Return the number of buckets in this distribution.
1449 * @return the number of buckets.
1451 size_type size() const { return cvec.size(); }
1454 * Returns true if any calls to sample have been made.
1455 * @return True if any values have been sampled.
1460 return samples == Counter();
1464 prepare(Info *info, DistData &data)
1466 const Params *params = safe_cast<const Params *>(info->storageParams);
1468 assert(params->type == Dist);
1469 data.type = params->type;
1470 data.min = params->min;
1471 data.max = params->max;
1472 data.bucket_size = params->bucket_size;
1474 data.min_val = (min_val == CounterLimits::max()) ? 0 : min_val;
1475 data.max_val = (max_val == CounterLimits::min()) ? 0 : max_val;
1476 data.underflow = underflow;
1477 data.overflow = overflow;
1479 data.cvec.resize(params->buckets);
1480 for (off_type i = 0; i < params->buckets; ++i)
1481 data.cvec[i] = cvec[i];
1484 data.squares = squares;
1485 data.samples = samples;
1489 * Reset stat value to default
1494 const Params *params = safe_cast<const Params *>(info->storageParams);
1495 min_track = params->min;
1496 max_track = params->max;
1497 bucket_size = params->bucket_size;
1499 min_val = CounterLimits::max();
1500 max_val = CounterLimits::min();
1501 underflow = Counter();
1502 overflow = Counter();
1504 size_type size = cvec.size();
1505 for (off_type i = 0; i < size; ++i)
1506 cvec[i] = Counter();
1509 squares = Counter();
1510 samples = Counter();
1515 * Templatized storage and interface for a histogram stat.
1520 /** The parameters for a distribution stat. */
1521 struct Params : public DistParams
1523 /** The number of buckets.. */
1526 Params() : DistParams(Hist), buckets(0) {}
1530 /** The minimum value to track. */
1532 /** The maximum value to track. */
1534 /** The number of entries in each bucket. */
1535 Counter bucket_size;
1537 /** The current sum. */
1539 /** The sum of logarithm of each sample, used to compute geometric mean. */
1541 /** The sum of squares. */
1543 /** The number of samples. */
1545 /** Counter for each bucket. */
1549 HistStor(Info *info)
1550 : cvec(safe_cast<const Params *>(info->storageParams)->buckets)
1557 void grow_convert();
1558 void add(HistStor *);
1561 * Add a value to the distribution for the given number of times.
1562 * @param val The value to add.
1563 * @param number The number of times to add the value.
1566 sample(Counter val, int number)
1568 assert(min_bucket < max_bucket);
1569 if (val < min_bucket) {
1570 if (min_bucket == 0)
1573 while (val < min_bucket)
1575 } else if (val >= max_bucket + bucket_size) {
1576 if (min_bucket == 0) {
1577 while (val >= max_bucket + bucket_size)
1580 while (val >= max_bucket + bucket_size)
1586 (int64_t)std::floor((val - min_bucket) / bucket_size);
1588 assert(index < size());
1589 cvec[index] += number;
1591 sum += val * number;
1592 squares += val * val * number;
1593 logs += log(val) * number;
1598 * Return the number of buckets in this distribution.
1599 * @return the number of buckets.
1601 size_type size() const { return cvec.size(); }
1604 * Returns true if any calls to sample have been made.
1605 * @return True if any values have been sampled.
1610 return samples == Counter();
1614 prepare(Info *info, DistData &data)
1616 const Params *params = safe_cast<const Params *>(info->storageParams);
1618 assert(params->type == Hist);
1619 data.type = params->type;
1620 data.min = min_bucket;
1621 data.max = max_bucket + bucket_size - 1;
1622 data.bucket_size = bucket_size;
1624 data.min_val = min_bucket;
1625 data.max_val = max_bucket;
1627 int buckets = params->buckets;
1628 data.cvec.resize(buckets);
1629 for (off_type i = 0; i < buckets; ++i)
1630 data.cvec[i] = cvec[i];
1634 data.squares = squares;
1635 data.samples = samples;
1639 * Reset stat value to default
1644 const Params *params = safe_cast<const Params *>(info->storageParams);
1646 max_bucket = params->buckets - 1;
1649 size_type size = cvec.size();
1650 for (off_type i = 0; i < size; ++i)
1651 cvec[i] = Counter();
1654 squares = Counter();
1655 samples = Counter();
1661 * Templatized storage and interface for a distribution that calculates mean
1667 struct Params : public DistParams
1669 Params() : DistParams(Deviation) {}
1673 /** The current sum. */
1675 /** The sum of squares. */
1677 /** The number of samples. */
1682 * Create and initialize this storage.
1684 SampleStor(Info *info)
1685 : sum(Counter()), squares(Counter()), samples(Counter())
1689 * Add a value the given number of times to this running average.
1690 * Update the running sum and sum of squares, increment the number of
1691 * values seen by the given number.
1692 * @param val The value to add.
1693 * @param number The number of times to add the value.
1696 sample(Counter val, int number)
1698 Counter value = val * number;
1700 squares += value * value;
1705 * Return the number of entries in this stat, 1
1708 size_type size() const { return 1; }
1711 * Return true if no samples have been added.
1712 * @return True if no samples have been added.
1714 bool zero() const { return samples == Counter(); }
1717 prepare(Info *info, DistData &data)
1719 const Params *params = safe_cast<const Params *>(info->storageParams);
1721 assert(params->type == Deviation);
1722 data.type = params->type;
1724 data.squares = squares;
1725 data.samples = samples;
1729 * Reset stat value to default
1735 squares = Counter();
1736 samples = Counter();
1741 * Templatized storage for distribution that calculates per tick mean and
1747 struct Params : public DistParams
1749 Params() : DistParams(Deviation) {}
1753 /** Current total. */
1755 /** Current sum of squares. */
1760 * Create and initialize this storage.
1762 AvgSampleStor(Info *info)
1763 : sum(Counter()), squares(Counter())
1767 * Add a value to the distribution for the given number of times.
1768 * Update the running sum and sum of squares.
1769 * @param val The value to add.
1770 * @param number The number of times to add the value.
1773 sample(Counter val, int number)
1775 Counter value = val * number;
1777 squares += value * value;
1781 * Return the number of entries, in this case 1.
1784 size_type size() const { return 1; }
1787 * Return true if no samples have been added.
1788 * @return True if the sum is zero.
1790 bool zero() const { return sum == Counter(); }
1793 prepare(Info *info, DistData &data)
1795 const Params *params = safe_cast<const Params *>(info->storageParams);
1797 assert(params->type == Deviation);
1798 data.type = params->type;
1800 data.squares = squares;
1801 data.samples = curTick();
1805 * Reset stat value to default
1811 squares = Counter();
1816 * Implementation of a distribution stat. The type of distribution is
1817 * determined by the Storage template. @sa ScalarBase
1819 template <class Derived, class Stor>
1820 class DistBase : public DataWrap<Derived, DistInfoProxy>
1823 typedef DistInfoProxy<Derived> Info;
1824 typedef Stor Storage;
1825 typedef typename Stor::Params Params;
1828 /** The storage for this stat. */
1829 char storage[sizeof(Storage)] __attribute__ ((aligned (8)));
1833 * Retrieve the storage.
1834 * @return The storage object for this stat.
1839 return reinterpret_cast<Storage *>(storage);
1843 * Retrieve a const pointer to the storage.
1844 * @return A const pointer to the storage object for this stat.
1849 return reinterpret_cast<const Storage *>(storage);
1855 new (storage) Storage(this->info());
1863 * Add a value to the distribtion n times. Calls sample on the storage
1865 * @param v The value to add.
1866 * @param n The number of times to add it, defaults to 1.
1868 template <typename U>
1869 void sample(const U &v, int n = 1) { data()->sample(v, n); }
1872 * Return the number of entries in this stat.
1873 * @return The number of entries.
1875 size_type size() const { return data()->size(); }
1877 * Return true if no samples have been added.
1878 * @return True if there haven't been any samples.
1880 bool zero() const { return data()->zero(); }
1885 Info *info = this->info();
1886 data()->prepare(info, info->data);
1890 * Reset stat value to default
1895 data()->reset(this->info());
1899 * Add the argument distribution to the this distribution.
1901 void add(DistBase &d) { data()->add(d.data()); }
1905 template <class Stat>
1908 template <class Derived, class Stor>
1909 class VectorDistBase : public DataWrapVec<Derived, VectorDistInfoProxy>
1912 typedef VectorDistInfoProxy<Derived> Info;
1913 typedef Stor Storage;
1914 typedef typename Stor::Params Params;
1915 typedef DistProxy<Derived> Proxy;
1916 friend class DistProxy<Derived>;
1917 friend class DataWrapVec<Derived, VectorDistInfoProxy>;
1925 data(off_type index)
1927 return &storage[index];
1931 data(off_type index) const
1933 return &storage[index];
1939 assert(s > 0 && "size must be positive!");
1940 assert(!storage && "already initialized");
1943 char *ptr = new char[_size * sizeof(Storage)];
1944 storage = reinterpret_cast<Storage *>(ptr);
1946 Info *info = this->info();
1947 for (off_type i = 0; i < _size; ++i)
1948 new (&storage[i]) Storage(info);
1963 for (off_type i = 0; i < _size; ++i)
1964 data(i)->~Storage();
1965 delete [] reinterpret_cast<char *>(storage);
1968 Proxy operator[](off_type index)
1970 assert(index >= 0 && index < size());
1971 return Proxy(this->self(), index);
1983 for (off_type i = 0; i < size(); ++i)
1984 if (!data(i)->zero())
1992 Info *info = this->info();
1993 size_type size = this->size();
1994 info->data.resize(size);
1995 for (off_type i = 0; i < size; ++i)
1996 data(i)->prepare(info, info->data[i]);
2002 return storage != NULL;
2006 template <class Stat>
2014 typename Stat::Storage *data() { return stat.data(index); }
2015 const typename Stat::Storage *data() const { return stat.data(index); }
2018 DistProxy(Stat &s, off_type i)
2022 DistProxy(const DistProxy &sp)
2023 : stat(sp.stat), index(sp.index)
2027 operator=(const DistProxy &sp)
2035 template <typename U>
2037 sample(const U &v, int n = 1)
2039 data()->sample(v, n);
2051 return data()->zero();
2055 * Proxy has no state. Nothing to reset.
2060 //////////////////////////////////////////////////////////////////////
2064 //////////////////////////////////////////////////////////////////////
2067 * Base class for formula statistic node. These nodes are used to build a tree
2068 * that represents the formula.
2074 * Return the number of nodes in the subtree starting at this node.
2075 * @return the number of nodes in this subtree.
2077 virtual size_type size() const = 0;
2079 * Return the result vector of this subtree.
2080 * @return The result vector of this subtree.
2082 virtual const VResult &result() const = 0;
2084 * Return the total of the result vector.
2085 * @return The total of the result vector.
2087 virtual Result total() const = 0;
2092 virtual std::string str() const = 0;
2097 /** Shared pointer to a function Node. */
2098 typedef std::shared_ptr<Node> NodePtr;
2100 class ScalarStatNode : public Node
2103 const ScalarInfo *data;
2104 mutable VResult vresult;
2107 ScalarStatNode(const ScalarInfo *d) : data(d), vresult(1) {}
2112 vresult[0] = data->result();
2116 Result total() const { return data->result(); };
2118 size_type size() const { return 1; }
2123 std::string str() const { return data->name; }
2126 template <class Stat>
2127 class ScalarProxyNode : public Node
2130 const ScalarProxy<Stat> proxy;
2131 mutable VResult vresult;
2134 ScalarProxyNode(const ScalarProxy<Stat> &p)
2135 : proxy(p), vresult(1)
2141 vresult[0] = proxy.result();
2148 return proxy.result();
2167 class VectorStatNode : public Node
2170 const VectorInfo *data;
2173 VectorStatNode(const VectorInfo *d) : data(d) { }
2174 const VResult &result() const { return data->result(); }
2175 Result total() const { return data->total(); };
2177 size_type size() const { return data->size(); }
2179 std::string str() const { return data->name; }
2183 class ConstNode : public Node
2189 ConstNode(T s) : vresult(1, (Result)s) {}
2190 const VResult &result() const { return vresult; }
2191 Result total() const { return vresult[0]; };
2192 size_type size() const { return 1; }
2193 std::string str() const { return std::to_string(vresult[0]); }
2197 class ConstVectorNode : public Node
2203 ConstVectorNode(const T &s) : vresult(s.begin(), s.end()) {}
2204 const VResult &result() const { return vresult; }
2209 size_type size = this->size();
2211 for (off_type i = 0; i < size; i++)
2216 size_type size() const { return vresult.size(); }
2220 size_type size = this->size();
2221 std::string tmp = "(";
2222 for (off_type i = 0; i < size; i++)
2223 tmp += csprintf("%s ", std::to_string(vresult[i]));
2233 struct OpString<std::plus<Result> >
2235 static std::string str() { return "+"; }
2239 struct OpString<std::minus<Result> >
2241 static std::string str() { return "-"; }
2245 struct OpString<std::multiplies<Result> >
2247 static std::string str() { return "*"; }
2251 struct OpString<std::divides<Result> >
2253 static std::string str() { return "/"; }
2257 struct OpString<std::modulus<Result> >
2259 static std::string str() { return "%"; }
2263 struct OpString<std::negate<Result> >
2265 static std::string str() { return "-"; }
2269 class UnaryNode : public Node
2273 mutable VResult vresult;
2276 UnaryNode(NodePtr &p) : l(p) {}
2281 const VResult &lvec = l->result();
2282 size_type size = lvec.size();
2286 vresult.resize(size);
2288 for (off_type i = 0; i < size; ++i)
2289 vresult[i] = op(lvec[i]);
2297 const VResult &vec = this->result();
2299 for (off_type i = 0; i < size(); i++)
2304 size_type size() const { return l->size(); }
2309 return OpString<Op>::str() + l->str();
2314 class BinaryNode : public Node
2319 mutable VResult vresult;
2322 BinaryNode(NodePtr &a, NodePtr &b) : l(a), r(b) {}
2325 result() const override
2328 const VResult &lvec = l->result();
2329 const VResult &rvec = r->result();
2331 assert(lvec.size() > 0 && rvec.size() > 0);
2333 if (lvec.size() == 1 && rvec.size() == 1) {
2335 vresult[0] = op(lvec[0], rvec[0]);
2336 } else if (lvec.size() == 1) {
2337 size_type size = rvec.size();
2338 vresult.resize(size);
2339 for (off_type i = 0; i < size; ++i)
2340 vresult[i] = op(lvec[0], rvec[i]);
2341 } else if (rvec.size() == 1) {
2342 size_type size = lvec.size();
2343 vresult.resize(size);
2344 for (off_type i = 0; i < size; ++i)
2345 vresult[i] = op(lvec[i], rvec[0]);
2346 } else if (rvec.size() == lvec.size()) {
2347 size_type size = rvec.size();
2348 vresult.resize(size);
2349 for (off_type i = 0; i < size; ++i)
2350 vresult[i] = op(lvec[i], rvec[i]);
2357 total() const override
2359 const VResult &vec = this->result();
2360 const VResult &lvec = l->result();
2361 const VResult &rvec = r->result();
2367 assert(lvec.size() > 0 && rvec.size() > 0);
2368 assert(lvec.size() == rvec.size() ||
2369 lvec.size() == 1 || rvec.size() == 1);
2371 /** If vectors are the same divide their sums (x0+x1)/(y0+y1) */
2372 if (lvec.size() == rvec.size() && lvec.size() > 1) {
2373 for (off_type i = 0; i < size(); ++i) {
2377 return op(lsum, rsum);
2380 /** Otherwise divide each item by the divisor */
2381 for (off_type i = 0; i < size(); ++i) {
2389 size() const override
2391 size_type ls = l->size();
2392 size_type rs = r->size();
2395 } else if (rs == 1) {
2398 assert(ls == rs && "Node vector sizes are not equal");
2404 str() const override
2406 return csprintf("(%s %s %s)", l->str(), OpString<Op>::str(), r->str());
2411 class SumNode : public Node
2415 mutable VResult vresult;
2418 SumNode(NodePtr &p) : l(p), vresult(1) {}
2423 const VResult &lvec = l->result();
2424 size_type size = lvec.size();
2430 for (off_type i = 0; i < size; ++i)
2431 vresult[0] = op(vresult[0], lvec[i]);
2439 const VResult &lvec = l->result();
2440 size_type size = lvec.size();
2443 Result result = 0.0;
2446 for (off_type i = 0; i < size; ++i)
2447 result = op(result, lvec[i]);
2452 size_type size() const { return 1; }
2457 return csprintf("total(%s)", l->str());
2462 //////////////////////////////////////////////////////////////////////
2464 // Visible Statistics Types
2466 //////////////////////////////////////////////////////////////////////
2468 * @defgroup VisibleStats "Statistic Types"
2469 * These are the statistics that are used in the simulator.
2474 * This is a simple scalar statistic, like a counter.
2475 * @sa Stat, ScalarBase, StatStor
2477 class Scalar : public ScalarBase<Scalar, StatStor>
2480 using ScalarBase<Scalar, StatStor>::operator=;
2484 * A stat that calculates the per tick average of a value.
2485 * @sa Stat, ScalarBase, AvgStor
2487 class Average : public ScalarBase<Average, AvgStor>
2490 using ScalarBase<Average, AvgStor>::operator=;
2493 class Value : public ValueBase<Value>
2498 * A vector of scalar stats.
2499 * @sa Stat, VectorBase, StatStor
2501 class Vector : public VectorBase<Vector, StatStor>
2506 * A vector of Average stats.
2507 * @sa Stat, VectorBase, AvgStor
2509 class AverageVector : public VectorBase<AverageVector, AvgStor>
2514 * A 2-Dimensional vecto of scalar stats.
2515 * @sa Stat, Vector2dBase, StatStor
2517 class Vector2d : public Vector2dBase<Vector2d, StatStor>
2522 * A simple distribution stat.
2523 * @sa Stat, DistBase, DistStor
2525 class Distribution : public DistBase<Distribution, DistStor>
2529 * Set the parameters of this distribution. @sa DistStor::Params
2530 * @param min The minimum value of the distribution.
2531 * @param max The maximum value of the distribution.
2532 * @param bkt The number of values in each bucket.
2533 * @return A reference to this distribution.
2536 init(Counter min, Counter max, Counter bkt)
2538 DistStor::Params *params = new DistStor::Params;
2541 params->bucket_size = bkt;
2542 params->buckets = (size_type)ceil((max - min + 1.0) / bkt);
2543 this->setParams(params);
2545 return this->self();
2550 * A simple histogram stat.
2551 * @sa Stat, DistBase, HistStor
2553 class Histogram : public DistBase<Histogram, HistStor>
2557 * Set the parameters of this histogram. @sa HistStor::Params
2558 * @param size The number of buckets in the histogram
2559 * @return A reference to this histogram.
2562 init(size_type size)
2564 HistStor::Params *params = new HistStor::Params;
2565 params->buckets = size;
2566 this->setParams(params);
2568 return this->self();
2573 * Calculates the mean and variance of all the samples.
2574 * @sa DistBase, SampleStor
2576 class StandardDeviation : public DistBase<StandardDeviation, SampleStor>
2580 * Construct and initialize this distribution.
2584 SampleStor::Params *params = new SampleStor::Params;
2586 this->setParams(params);
2591 * Calculates the per tick mean and variance of the samples.
2592 * @sa DistBase, AvgSampleStor
2594 class AverageDeviation : public DistBase<AverageDeviation, AvgSampleStor>
2598 * Construct and initialize this distribution.
2602 AvgSampleStor::Params *params = new AvgSampleStor::Params;
2604 this->setParams(params);
2609 * A vector of distributions.
2610 * @sa VectorDistBase, DistStor
2612 class VectorDistribution : public VectorDistBase<VectorDistribution, DistStor>
2616 * Initialize storage and parameters for this distribution.
2617 * @param size The size of the vector (the number of distributions).
2618 * @param min The minimum value of the distribution.
2619 * @param max The maximum value of the distribution.
2620 * @param bkt The number of values in each bucket.
2621 * @return A reference to this distribution.
2623 VectorDistribution &
2624 init(size_type size, Counter min, Counter max, Counter bkt)
2626 DistStor::Params *params = new DistStor::Params;
2629 params->bucket_size = bkt;
2630 params->buckets = (size_type)ceil((max - min + 1.0) / bkt);
2631 this->setParams(params);
2633 return this->self();
2638 * This is a vector of StandardDeviation stats.
2639 * @sa VectorDistBase, SampleStor
2641 class VectorStandardDeviation
2642 : public VectorDistBase<VectorStandardDeviation, SampleStor>
2646 * Initialize storage for this distribution.
2647 * @param size The size of the vector.
2648 * @return A reference to this distribution.
2650 VectorStandardDeviation &
2651 init(size_type size)
2653 SampleStor::Params *params = new SampleStor::Params;
2655 this->setParams(params);
2656 return this->self();
2661 * This is a vector of AverageDeviation stats.
2662 * @sa VectorDistBase, AvgSampleStor
2664 class VectorAverageDeviation
2665 : public VectorDistBase<VectorAverageDeviation, AvgSampleStor>
2669 * Initialize storage for this distribution.
2670 * @param size The size of the vector.
2671 * @return A reference to this distribution.
2673 VectorAverageDeviation &
2674 init(size_type size)
2676 AvgSampleStor::Params *params = new AvgSampleStor::Params;
2678 this->setParams(params);
2679 return this->self();
2683 template <class Stat>
2684 class FormulaInfoProxy : public InfoProxy<Stat, FormulaInfo>
2687 mutable VResult vec;
2688 mutable VCounter cvec;
2691 FormulaInfoProxy(Stat &stat) : InfoProxy<Stat, FormulaInfo>(stat) {}
2693 size_type size() const { return this->s.size(); }
2698 this->s.result(vec);
2701 Result total() const { return this->s.total(); }
2702 VCounter &value() const { return cvec; }
2704 std::string str() const { return this->s.str(); }
2707 template <class Stat>
2708 class SparseHistInfoProxy : public InfoProxy<Stat, SparseHistInfo>
2711 SparseHistInfoProxy(Stat &stat) : InfoProxy<Stat, SparseHistInfo>(stat) {}
2715 * Implementation of a sparse histogram stat. The storage class is
2716 * determined by the Storage template.
2718 template <class Derived, class Stor>
2719 class SparseHistBase : public DataWrap<Derived, SparseHistInfoProxy>
2722 typedef SparseHistInfoProxy<Derived> Info;
2723 typedef Stor Storage;
2724 typedef typename Stor::Params Params;
2727 /** The storage for this stat. */
2728 char storage[sizeof(Storage)];
2732 * Retrieve the storage.
2733 * @return The storage object for this stat.
2738 return reinterpret_cast<Storage *>(storage);
2742 * Retrieve a const pointer to the storage.
2743 * @return A const pointer to the storage object for this stat.
2748 return reinterpret_cast<const Storage *>(storage);
2754 new (storage) Storage(this->info());
2759 SparseHistBase() { }
2762 * Add a value to the distribtion n times. Calls sample on the storage
2764 * @param v The value to add.
2765 * @param n The number of times to add it, defaults to 1.
2767 template <typename U>
2768 void sample(const U &v, int n = 1) { data()->sample(v, n); }
2771 * Return the number of entries in this stat.
2772 * @return The number of entries.
2774 size_type size() const { return data()->size(); }
2776 * Return true if no samples have been added.
2777 * @return True if there haven't been any samples.
2779 bool zero() const { return data()->zero(); }
2784 Info *info = this->info();
2785 data()->prepare(info, info->data);
2789 * Reset stat value to default
2794 data()->reset(this->info());
2799 * Templatized storage and interface for a sparse histogram stat.
2801 class SparseHistStor
2804 /** The parameters for a sparse histogram stat. */
2805 struct Params : public DistParams
2807 Params() : DistParams(Hist) {}
2811 /** Counter for number of samples */
2813 /** Counter for each bucket. */
2817 SparseHistStor(Info *info)
2823 * Add a value to the distribution for the given number of times.
2824 * @param val The value to add.
2825 * @param number The number of times to add the value.
2828 sample(Counter val, int number)
2830 cmap[val] += number;
2835 * Return the number of buckets in this distribution.
2836 * @return the number of buckets.
2838 size_type size() const { return cmap.size(); }
2841 * Returns true if any calls to sample have been made.
2842 * @return True if any values have been sampled.
2847 return samples == Counter();
2851 prepare(Info *info, SparseHistData &data)
2853 MCounter::iterator it;
2855 for (it = cmap.begin(); it != cmap.end(); it++) {
2856 data.cmap[(*it).first] = (*it).second;
2859 data.samples = samples;
2863 * Reset stat value to default
2873 class SparseHistogram : public SparseHistBase<SparseHistogram, SparseHistStor>
2877 * Set the parameters of this histogram. @sa HistStor::Params
2878 * @param size The number of buckets in the histogram
2879 * @return A reference to this histogram.
2882 init(size_type size)
2884 SparseHistStor::Params *params = new SparseHistStor::Params;
2885 this->setParams(params);
2887 return this->self();
2893 * A formula for statistics that is calculated when printed. A formula is
2894 * stored as a tree of Nodes that represent the equation to calculate.
2895 * @sa Stat, ScalarStat, VectorStat, Node, Temp
2897 class Formula : public DataWrapVec<Formula, FormulaInfoProxy>
2900 /** The root of the tree which represents the Formula */
2906 * Create and initialize thie formula, and register it with the database.
2911 * Create a formula with the given root node, register it with the
2913 * @param r The root of the expression tree.
2918 * Set an unitialized Formula to the given root.
2919 * @param r The root of the expression tree.
2920 * @return a reference to this formula.
2922 const Formula &operator=(Temp r);
2925 * Add the given tree to the existing one.
2926 * @param r The root of the expression tree.
2927 * @return a reference to this formula.
2929 const Formula &operator+=(Temp r);
2932 * Divide the existing tree by the given one.
2933 * @param r The root of the expression tree.
2934 * @return a reference to this formula.
2936 const Formula &operator/=(Temp r);
2939 * Return the result of the Fomula in a vector. If there were no Vector
2940 * components to the Formula, then the vector is size 1. If there were,
2941 * like x/y with x being a vector of size 3, then the result returned will
2942 * be x[0]/y, x[1]/y, x[2]/y, respectively.
2943 * @return The result vector.
2945 void result(VResult &vec) const;
2948 * Return the total Formula result. If there is a Vector
2949 * component to this Formula, then this is the result of the
2950 * Formula if the formula is applied after summing all the
2951 * components of the Vector. For example, if Formula is x/y where
2952 * x is size 3, then total() will return (x[1]+x[2]+x[3])/y. If
2953 * there is no Vector component, total() returns the same value as
2954 * the first entry in the VResult val() returns.
2955 * @return The total of the result vector.
2957 Result total() const;
2960 * Return the number of elements in the tree.
2962 size_type size() const;
2967 * Formulas don't need to be reset
2976 std::string str() const;
2979 class FormulaNode : public Node
2982 const Formula &formula;
2983 mutable VResult vec;
2986 FormulaNode(const Formula &f) : formula(f) {}
2988 size_type size() const { return formula.size(); }
2989 const VResult &result() const { formula.result(vec); return vec; }
2990 Result total() const { return formula.total(); }
2992 std::string str() const { return formula.str(); }
2996 * Helper class to construct formula node trees.
3002 * Pointer to a Node object.
3008 * Copy the given pointer to this class.
3009 * @param n A pointer to a Node object to copy.
3011 Temp(const NodePtr &n) : node(n) { }
3013 Temp(NodePtr &&n) : node(std::move(n)) { }
3016 * Return the node pointer.
3017 * @return the node pointer.
3019 operator NodePtr&() { return node; }
3022 * Makde gcc < 4.6.3 happy and explicitly get the underlying node.
3024 NodePtr getNodePtr() const { return node; }
3028 * Create a new ScalarStatNode.
3029 * @param s The ScalarStat to place in a node.
3031 Temp(const Scalar &s)
3032 : node(new ScalarStatNode(s.info()))
3036 * Create a new ScalarStatNode.
3037 * @param s The ScalarStat to place in a node.
3039 Temp(const Value &s)
3040 : node(new ScalarStatNode(s.info()))
3044 * Create a new ScalarStatNode.
3045 * @param s The ScalarStat to place in a node.
3047 Temp(const Average &s)
3048 : node(new ScalarStatNode(s.info()))
3052 * Create a new VectorStatNode.
3053 * @param s The VectorStat to place in a node.
3055 Temp(const Vector &s)
3056 : node(new VectorStatNode(s.info()))
3059 Temp(const AverageVector &s)
3060 : node(new VectorStatNode(s.info()))
3066 Temp(const Formula &f)
3067 : node(new FormulaNode(f))
3071 * Create a new ScalarProxyNode.
3072 * @param p The ScalarProxy to place in a node.
3074 template <class Stat>
3075 Temp(const ScalarProxy<Stat> &p)
3076 : node(new ScalarProxyNode<Stat>(p))
3080 * Create a ConstNode
3081 * @param value The value of the const node.
3083 Temp(signed char value)
3084 : node(new ConstNode<signed char>(value))
3088 * Create a ConstNode
3089 * @param value The value of the const node.
3091 Temp(unsigned char value)
3092 : node(new ConstNode<unsigned char>(value))
3096 * Create a ConstNode
3097 * @param value The value of the const node.
3099 Temp(signed short value)
3100 : node(new ConstNode<signed short>(value))
3104 * Create a ConstNode
3105 * @param value The value of the const node.
3107 Temp(unsigned short value)
3108 : node(new ConstNode<unsigned short>(value))
3112 * Create a ConstNode
3113 * @param value The value of the const node.
3115 Temp(signed int value)
3116 : node(new ConstNode<signed int>(value))
3120 * Create a ConstNode
3121 * @param value The value of the const node.
3123 Temp(unsigned int value)
3124 : node(new ConstNode<unsigned int>(value))
3128 * Create a ConstNode
3129 * @param value The value of the const node.
3131 Temp(signed long value)
3132 : node(new ConstNode<signed long>(value))
3136 * Create a ConstNode
3137 * @param value The value of the const node.
3139 Temp(unsigned long value)
3140 : node(new ConstNode<unsigned long>(value))
3144 * Create a ConstNode
3145 * @param value The value of the const node.
3147 Temp(signed long long value)
3148 : node(new ConstNode<signed long long>(value))
3152 * Create a ConstNode
3153 * @param value The value of the const node.
3155 Temp(unsigned long long value)
3156 : node(new ConstNode<unsigned long long>(value))
3160 * Create a ConstNode
3161 * @param value The value of the const node.
3164 : node(new ConstNode<float>(value))
3168 * Create a ConstNode
3169 * @param value The value of the const node.
3172 : node(new ConstNode<double>(value))
3182 operator+(Temp l, Temp r)
3184 return Temp(std::make_shared<BinaryNode<std::plus<Result> > >(l, r));
3188 operator-(Temp l, Temp r)
3190 return Temp(std::make_shared<BinaryNode<std::minus<Result> > >(l, r));
3194 operator*(Temp l, Temp r)
3196 return Temp(std::make_shared<BinaryNode<std::multiplies<Result> > >(l, r));
3200 operator/(Temp l, Temp r)
3202 return Temp(std::make_shared<BinaryNode<std::divides<Result> > >(l, r));
3208 return Temp(std::make_shared<UnaryNode<std::negate<Result> > >(l));
3211 template <typename T>
3215 return Temp(std::make_shared<ConstNode<T> >(val));
3218 template <typename T>
3220 constantVector(T val)
3222 return Temp(std::make_shared<ConstVectorNode<T> >(val));
3228 return Temp(std::make_shared<SumNode<std::plus<Result> > >(val));
3231 /** Dump all statistics data to the registered outputs */
3238 * Register reset and dump handlers. These are the functions which
3239 * will actually perform the whole statistics reset/dump actions
3240 * including processing the reset/dump callbacks
3242 typedef void (*Handler)();
3244 void registerHandlers(Handler reset_handler, Handler dump_handler);
3247 * Register a callback that should be called whenever statistics are
3250 void registerResetCallback(Callback *cb);
3253 * Register a callback that should be called whenever statistics are
3254 * about to be dumped
3256 void registerDumpCallback(Callback *cb);
3259 * Process all the callbacks in the reset callbacks queue
3261 void processResetQueue();
3264 * Process all the callbacks in the dump callbacks queue
3266 void processDumpQueue();
3268 std::list<Info *> &statsList();
3270 typedef std::map<const void *, Info *> MapType;
3271 MapType &statsMap();
3273 typedef std::map<std::string, Info *> NameMapType;
3274 NameMapType &nameMap();
3276 bool validateStatName(const std::string &name);
3278 } // namespace Stats
3280 void debugDumpStats();
3282 #endif // __BASE_STATISTICS_HH__