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 /** The current simulated tick. */
86 extern Tick curTick();
88 /* A namespace for all of the Statistics */
91 template <class Stat, class Base>
92 class InfoProxy : public Base
98 InfoProxy(Stat &stat) : s(stat) {}
100 bool check() const { return s.check(); }
101 void prepare() { s.prepare(); }
102 void reset() { s.reset(); }
104 visit(Output &visitor)
106 visitor.visit(*static_cast<Base *>(this));
108 bool zero() const { return s.zero(); }
111 template <class Stat>
112 class ScalarInfoProxy : public InfoProxy<Stat, ScalarInfo>
115 ScalarInfoProxy(Stat &stat) : InfoProxy<Stat, ScalarInfo>(stat) {}
117 Counter value() const { return this->s.value(); }
118 Result result() const { return this->s.result(); }
119 Result total() const { return this->s.total(); }
122 template <class Stat>
123 class VectorInfoProxy : public InfoProxy<Stat, VectorInfo>
126 mutable VCounter cvec;
127 mutable VResult rvec;
130 VectorInfoProxy(Stat &stat) : InfoProxy<Stat, VectorInfo>(stat) {}
132 size_type size() const { return this->s.size(); }
144 this->s.result(rvec);
148 Result total() const { return this->s.total(); }
151 template <class Stat>
152 class DistInfoProxy : public InfoProxy<Stat, DistInfo>
155 DistInfoProxy(Stat &stat) : InfoProxy<Stat, DistInfo>(stat) {}
158 template <class Stat>
159 class VectorDistInfoProxy : public InfoProxy<Stat, VectorDistInfo>
162 VectorDistInfoProxy(Stat &stat) : InfoProxy<Stat, VectorDistInfo>(stat) {}
164 size_type size() const { return this->s.size(); }
167 template <class Stat>
168 class Vector2dInfoProxy : public InfoProxy<Stat, Vector2dInfo>
171 Vector2dInfoProxy(Stat &stat) : InfoProxy<Stat, Vector2dInfo>(stat) {}
173 Result total() const { return this->s.total(); }
178 virtual ~StorageParams();
187 /** Set up an info class for this statistic */
188 void setInfo(Group *parent, Info *info);
189 /** Save Storage class parameters if any */
190 void setParams(const StorageParams *params);
191 /** Save Storage class parameters if any */
194 /** Grab the information class for this statistic */
196 /** Grab the information class for this statistic */
197 const Info *info() const;
204 * Reset the stat to the default state.
209 * @return true if this stat has a value and satisfies its
210 * requirement as a prereq
212 bool zero() const { return true; }
215 * Check that this stat has been set up properly and is ready for
217 * @return true for success
219 bool check() const { return true; }
222 template <class Derived, template <class> class InfoProxyType>
223 class DataWrap : public InfoAccess
226 typedef InfoProxyType<Derived> Info;
229 Derived &self() { return *static_cast<Derived *>(this); }
235 return safe_cast<Info *>(InfoAccess::info());
242 return safe_cast<const Info *>(InfoAccess::info());
247 DataWrap(const DataWrap &) = delete;
248 DataWrap &operator=(const DataWrap &) = delete;
251 DataWrap(Group *parent, const char *name, const char *desc)
253 auto info = new Info(self());
254 this->setInfo(parent, info);
257 parent->addStat(info);
260 info->setName(parent, name);
261 info->flags.set(display);
269 * Set the name and marks this stat to print at the end of simulation.
270 * @param name The new name.
271 * @return A reference to this stat.
274 name(const std::string &name)
276 Info *info = this->info();
278 info->flags.set(display);
281 const std::string &name() const { return this->info()->name; }
284 * Set the character(s) used between the name and vector number
285 * on vectors, dist, etc.
286 * @param _sep The new separator string
287 * @return A reference to this stat.
290 setSeparator(const std::string &_sep)
292 this->info()->setSeparator(_sep);
295 const std::string &setSeparator() const
297 return this->info()->separatorString;
301 * Set the description and marks this stat to print at the end of
303 * @param desc The new description.
304 * @return A reference to this stat.
307 desc(const std::string &_desc)
309 this->info()->desc = _desc;
314 * Set the precision and marks this stat to print at the end of simulation.
315 * @param _precision The new precision
316 * @return A reference to this stat.
319 precision(int _precision)
321 this->info()->precision = _precision;
326 * Set the flags and marks this stat to print at the end of simulation.
327 * @param f The new flags.
328 * @return A reference to this stat.
333 this->info()->flags.set(_flags);
338 * Set the prerequisite stat and marks this stat to print at the end of
340 * @param prereq The prerequisite stat.
341 * @return A reference to this stat.
343 template <class Stat>
345 prereq(const Stat &prereq)
347 this->info()->prereq = prereq.info();
352 template <class Derived, template <class> class InfoProxyType>
353 class DataWrapVec : public DataWrap<Derived, InfoProxyType>
356 typedef InfoProxyType<Derived> Info;
358 DataWrapVec(Group *parent = nullptr, const char *name = nullptr,
359 const char *desc = nullptr)
360 : DataWrap<Derived, InfoProxyType>(parent, name, desc)
363 // The following functions are specific to vectors. If you use them
364 // in a non vector context, you will get a nice compiler error!
367 * Set the subfield name for the given index, and marks this stat to print
368 * at the end of simulation.
369 * @param index The subfield index.
370 * @param name The new name of the subfield.
371 * @return A reference to this stat.
374 subname(off_type index, const std::string &name)
376 Derived &self = this->self();
377 Info *info = self.info();
379 std::vector<std::string> &subn = info->subnames;
380 if (subn.size() <= index)
381 subn.resize(index + 1);
386 // The following functions are specific to 2d vectors. If you use
387 // them in a non vector context, you will get a nice compiler
388 // error because info doesn't have the right variables.
391 * Set the subfield description for the given index and marks this stat to
392 * print at the end of simulation.
393 * @param index The subfield index.
394 * @param desc The new description of the subfield
395 * @return A reference to this stat.
398 subdesc(off_type index, const std::string &desc)
400 Info *info = this->info();
402 std::vector<std::string> &subd = info->subdescs;
403 if (subd.size() <= index)
404 subd.resize(index + 1);
413 Derived &self = this->self();
414 Info *info = this->info();
416 size_t size = self.size();
417 for (off_type i = 0; i < size; ++i)
418 self.data(i)->prepare(info);
424 Derived &self = this->self();
425 Info *info = this->info();
427 size_t size = self.size();
428 for (off_type i = 0; i < size; ++i)
429 self.data(i)->reset(info);
433 template <class Derived, template <class> class InfoProxyType>
434 class DataWrapVec2d : public DataWrapVec<Derived, InfoProxyType>
437 typedef InfoProxyType<Derived> Info;
439 DataWrapVec2d(Group *parent, const char *name, const char *desc)
440 : DataWrapVec<Derived, InfoProxyType>(parent, name, desc)
445 * @warning This makes the assumption that if you're gonna subnames a 2d
446 * vector, you're subnaming across all y
449 ysubnames(const char **names)
451 Derived &self = this->self();
452 Info *info = this->info();
454 info->y_subnames.resize(self.y);
455 for (off_type i = 0; i < self.y; ++i)
456 info->y_subnames[i] = names[i];
461 ysubname(off_type index, const std::string &subname)
463 Derived &self = this->self();
464 Info *info = this->info();
466 assert(index < self.y);
467 info->y_subnames.resize(self.y);
468 info->y_subnames[index] = subname.c_str();
473 ysubname(off_type i) const
475 return this->info()->y_subnames[i];
480 //////////////////////////////////////////////////////////////////////
484 //////////////////////////////////////////////////////////////////////
487 * Templatized storage and interface for a simple scalar stat.
492 /** The statistic value. */
496 struct Params : public StorageParams {};
500 * Builds this storage element and calls the base constructor of the
508 * The the stat to the given value.
509 * @param val The new value.
511 void set(Counter val) { data = val; }
513 * Increment the stat by the given value.
514 * @param val The new value.
516 void inc(Counter val) { data += val; }
518 * Decrement the stat by the given value.
519 * @param val The new value.
521 void dec(Counter val) { data -= val; }
523 * Return the value of this stat as its base type.
524 * @return The value of this stat.
526 Counter value() const { return data; }
528 * Return the value of this stat as a result type.
529 * @return The value of this stat.
531 Result result() const { return (Result)data; }
533 * Prepare stat data for dumping or serialization
535 void prepare(Info *info) { }
537 * Reset stat value to default
539 void reset(Info *info) { data = Counter(); }
542 * @return true if zero value
544 bool zero() const { return data == Counter(); }
548 * Templatized storage and interface to a per-tick average stat. This keeps
549 * a current count and updates a total (count * ticks) when this count
550 * changes. This allows the quick calculation of a per tick count of the item
551 * being watched. This is good for keeping track of residencies in structures
552 * among other things.
557 /** The current count. */
559 /** The tick of the last reset */
561 /** The total count for all tick. */
562 mutable Result total;
563 /** The tick that current last changed. */
567 struct Params : public StorageParams {};
571 * Build and initializes this stat storage.
574 : current(0), lastReset(0), total(0), last(0)
578 * Set the current count to the one provided, update the total and last
580 * @param val The new count.
585 total += current * (curTick() - last);
591 * Increment the current count by the provided value, calls set.
592 * @param val The amount to increment.
594 void inc(Counter val) { set(current + val); }
597 * Deccrement the current count by the provided value, calls set.
598 * @param val The amount to decrement.
600 void dec(Counter val) { set(current - val); }
603 * Return the current count.
604 * @return The current count.
606 Counter value() const { return current; }
609 * Return the current average.
610 * @return The current average.
615 assert(last == curTick());
616 return (Result)(total + current) / (Result)(curTick() - lastReset + 1);
620 * @return true if zero value
622 bool zero() const { return total == 0.0; }
625 * Prepare stat data for dumping or serialization
630 total += current * (curTick() - last);
635 * Reset stat value to default
642 lastReset = curTick();
648 * Implementation of a scalar stat. The type of stat is determined by the
651 template <class Derived, class Stor>
652 class ScalarBase : public DataWrap<Derived, ScalarInfoProxy>
655 typedef Stor Storage;
656 typedef typename Stor::Params Params;
659 /** The storage of this stat. */
660 M5_ALIGNED(8) char storage[sizeof(Storage)];
664 * Retrieve the storage.
665 * @param index The vector index to access.
666 * @return The storage object at the given index.
671 return reinterpret_cast<Storage *>(storage);
675 * Retrieve a const pointer to the storage.
676 * for the given index.
677 * @param index The vector index to access.
678 * @return A const pointer to the storage object at the given index.
683 return reinterpret_cast<const Storage *>(storage);
689 new (storage) Storage(this->info());
695 * Return the current value of this stat as its base type.
696 * @return The current value.
698 Counter value() const { return data()->value(); }
701 ScalarBase(Group *parent = nullptr, const char *name = nullptr,
702 const char *desc = nullptr)
703 : DataWrap<Derived, ScalarInfoProxy>(parent, name, desc)
709 // Common operators for stats
711 * Increment the stat by 1. This calls the associated storage object inc
714 void operator++() { data()->inc(1); }
716 * Decrement the stat by 1. This calls the associated storage object dec
719 void operator--() { data()->dec(1); }
721 /** Increment the stat by 1. */
722 void operator++(int) { ++*this; }
723 /** Decrement the stat by 1. */
724 void operator--(int) { --*this; }
727 * Set the data value to the given value. This calls the associated storage
728 * object set function.
729 * @param v The new value.
731 template <typename U>
732 void operator=(const U &v) { data()->set(v); }
735 * Increment the stat by the given value. This calls the associated
736 * storage object inc function.
737 * @param v The value to add.
739 template <typename U>
740 void operator+=(const U &v) { data()->inc(v); }
743 * Decrement the stat by the given value. This calls the associated
744 * storage object dec function.
745 * @param v The value to substract.
747 template <typename U>
748 void operator-=(const U &v) { data()->dec(v); }
751 * Return the number of elements, always 1 for a scalar.
754 size_type size() const { return 1; }
756 Counter value() { return data()->value(); }
758 Result result() { return data()->result(); }
760 Result total() { return result(); }
762 bool zero() { return result() == 0.0; }
764 void reset() { data()->reset(this->info()); }
765 void prepare() { data()->prepare(this->info()); }
768 class ProxyInfo : public ScalarInfo
771 std::string str() const { return std::to_string(value()); }
772 size_type size() const { return 1; }
773 bool check() const { return true; }
776 bool zero() const { return value() == 0; }
778 void visit(Output &visitor) { visitor.visit(*this); }
782 class ValueProxy : public ProxyInfo
788 ValueProxy(T &val) : scalar(&val) {}
789 Counter value() const { return *scalar; }
790 Result result() const { return *scalar; }
791 Result total() const { return *scalar; }
794 template <class T, class Enabled=void>
795 class FunctorProxy : public ProxyInfo
801 FunctorProxy(T &func) : functor(&func) {}
802 Counter value() const { return (*functor)(); }
803 Result result() const { return (*functor)(); }
804 Result total() const { return (*functor)(); }
808 * Template specialization for type std::function<Result()> which holds a copy
809 * of its target instead of a pointer to it. This makes it possible to use a
810 * lambda or other type inline without having to keep track of an instance
814 class FunctorProxy<T,
815 typename std::enable_if<std::is_constructible<std::function<Result()>,
816 const T &>::value>::type> : public ProxyInfo
819 std::function<Result()> functor;
822 FunctorProxy(const T &func) : functor(func) {}
823 Counter value() const { return functor(); }
824 Result result() const { return functor(); }
825 Result total() const { return functor(); }
829 * A proxy similar to the FunctorProxy, but allows calling a method of a bound
830 * object, instead of a global free-standing function.
832 template <class T, class V>
833 class MethodProxy : public ProxyInfo
837 typedef V (T::*MethodPointer) () const;
838 MethodPointer method;
841 MethodProxy(T *obj, MethodPointer meth) : object(obj), method(meth) {}
842 Counter value() const { return (object->*method)(); }
843 Result result() const { return (object->*method)(); }
844 Result total() const { return (object->*method)(); }
847 template <class Derived>
848 class ValueBase : public DataWrap<Derived, ScalarInfoProxy>
854 ValueBase(Group *parent, const char *name, const char *desc)
855 : DataWrap<Derived, ScalarInfoProxy>(parent, name, desc),
860 ~ValueBase() { if (proxy) delete proxy; }
866 proxy = new ValueProxy<T>(value);
873 functor(const T &func)
875 proxy = new FunctorProxy<T>(func);
884 proxy = new FunctorProxy<T>(func);
890 * Extended functor that calls the specified method of the provided object.
892 * @param obj Pointer to the object whose method should be called.
893 * @param method Pointer of the function / method of the object.
894 * @return Updated stats item.
896 template <class T, class V>
898 method(T *obj, V (T::*method)() const)
900 proxy = new MethodProxy<T,V>(obj, method);
905 Counter value() { return proxy->value(); }
906 Result result() const { return proxy->result(); }
907 Result total() const { return proxy->total(); };
908 size_type size() const { return proxy->size(); }
910 std::string str() const { return proxy->str(); }
911 bool zero() const { return proxy->zero(); }
912 bool check() const { return proxy != NULL; }
917 //////////////////////////////////////////////////////////////////////
921 //////////////////////////////////////////////////////////////////////
924 * A proxy class to access the stat at a given index in a VectorBase stat.
925 * Behaves like a ScalarBase.
927 template <class Stat>
931 /** Pointer to the parent Vector. */
934 /** The index to access in the parent VectorBase. */
939 * Return the current value of this stat as its base type.
940 * @return The current value.
942 Counter value() const { return stat.data(index)->value(); }
945 * Return the current value of this statas a result type.
946 * @return The current value.
948 Result result() const { return stat.data(index)->result(); }
952 * Create and initialize this proxy, do not register it with the database.
953 * @param i The index to access.
955 ScalarProxy(Stat &s, off_type i)
961 * Create a copy of the provided ScalarProxy.
962 * @param sp The proxy to copy.
964 ScalarProxy(const ScalarProxy &sp)
965 : stat(sp.stat), index(sp.index)
969 * Set this proxy equal to the provided one.
970 * @param sp The proxy to copy.
971 * @return A reference to this proxy.
974 operator=(const ScalarProxy &sp)
982 // Common operators for stats
984 * Increment the stat by 1. This calls the associated storage object inc
987 void operator++() { stat.data(index)->inc(1); }
989 * Decrement the stat by 1. This calls the associated storage object dec
992 void operator--() { stat.data(index)->dec(1); }
994 /** Increment the stat by 1. */
995 void operator++(int) { ++*this; }
996 /** Decrement the stat by 1. */
997 void operator--(int) { --*this; }
1000 * Set the data value to the given value. This calls the associated storage
1001 * object set function.
1002 * @param v The new value.
1004 template <typename U>
1006 operator=(const U &v)
1008 stat.data(index)->set(v);
1012 * Increment the stat by the given value. This calls the associated
1013 * storage object inc function.
1014 * @param v The value to add.
1016 template <typename U>
1018 operator+=(const U &v)
1020 stat.data(index)->inc(v);
1024 * Decrement the stat by the given value. This calls the associated
1025 * storage object dec function.
1026 * @param v The value to substract.
1028 template <typename U>
1030 operator-=(const U &v)
1032 stat.data(index)->dec(v);
1036 * Return the number of elements, always 1 for a scalar.
1039 size_type size() const { return 1; }
1045 return csprintf("%s[%d]", stat.info()->name, index);
1050 * Implementation of a vector of stats. The type of stat is determined by the
1051 * Storage class. @sa ScalarBase
1053 template <class Derived, class Stor>
1054 class VectorBase : public DataWrapVec<Derived, VectorInfoProxy>
1057 typedef Stor Storage;
1058 typedef typename Stor::Params Params;
1061 typedef ScalarProxy<Derived> Proxy;
1062 friend class ScalarProxy<Derived>;
1063 friend class DataWrapVec<Derived, VectorInfoProxy>;
1066 /** The storage of this stat. */
1072 * Retrieve the storage.
1073 * @param index The vector index to access.
1074 * @return The storage object at the given index.
1076 Storage *data(off_type index) { return &storage[index]; }
1079 * Retrieve a const pointer to the storage.
1080 * @param index The vector index to access.
1081 * @return A const pointer to the storage object at the given index.
1083 const Storage *data(off_type index) const { return &storage[index]; }
1088 assert(s > 0 && "size must be positive!");
1089 assert(!storage && "already initialized");
1092 char *ptr = new char[_size * sizeof(Storage)];
1093 storage = reinterpret_cast<Storage *>(ptr);
1095 for (off_type i = 0; i < _size; ++i)
1096 new (&storage[i]) Storage(this->info());
1103 value(VCounter &vec) const
1106 for (off_type i = 0; i < size(); ++i)
1107 vec[i] = data(i)->value();
1111 * Copy the values to a local vector and return a reference to it.
1112 * @return A reference to a vector of the stat values.
1115 result(VResult &vec) const
1118 for (off_type i = 0; i < size(); ++i)
1119 vec[i] = data(i)->result();
1123 * Return a total of all entries in this vector.
1124 * @return The total of all vector entries.
1130 for (off_type i = 0; i < size(); ++i)
1131 total += data(i)->result();
1136 * @return the number of elements in this vector.
1138 size_type size() const { return _size; }
1143 for (off_type i = 0; i < size(); ++i)
1144 if (data(i)->zero())
1152 return storage != NULL;
1156 VectorBase(Group *parent, const char *name, const char *desc)
1157 : DataWrapVec<Derived, VectorInfoProxy>(parent, name, desc),
1158 storage(nullptr), _size(0)
1166 for (off_type i = 0; i < _size; ++i)
1167 data(i)->~Storage();
1168 delete [] reinterpret_cast<char *>(storage);
1172 * Set this vector to have the given size.
1173 * @param size The new size.
1174 * @return A reference to this stat.
1177 init(size_type size)
1179 Derived &self = this->self();
1185 * Return a reference (ScalarProxy) to the stat at the given index.
1186 * @param index The vector index to access.
1187 * @return A reference of the stat.
1190 operator[](off_type index)
1192 assert (index < size());
1193 return Proxy(this->self(), index);
1197 template <class Stat>
1206 mutable VResult vec;
1208 typename Stat::Storage *
1209 data(off_type index)
1211 assert(index < len);
1212 return stat.data(offset + index);
1215 const typename Stat::Storage *
1216 data(off_type index) const
1218 assert(index < len);
1219 return stat.data(offset + index);
1228 for (off_type i = 0; i < size(); ++i)
1229 vec[i] = data(i)->result();
1238 for (off_type i = 0; i < size(); ++i)
1239 total += data(i)->result();
1244 VectorProxy(Stat &s, off_type o, size_type l)
1245 : stat(s), offset(o), len(l)
1249 VectorProxy(const VectorProxy &sp)
1250 : stat(sp.stat), offset(sp.offset), len(sp.len)
1255 operator=(const VectorProxy &sp)
1264 operator[](off_type index)
1266 assert (index < size());
1267 return ScalarProxy<Stat>(stat, offset + index);
1270 size_type size() const { return len; }
1273 template <class Derived, class Stor>
1274 class Vector2dBase : public DataWrapVec2d<Derived, Vector2dInfoProxy>
1277 typedef Vector2dInfoProxy<Derived> Info;
1278 typedef Stor Storage;
1279 typedef typename Stor::Params Params;
1280 typedef VectorProxy<Derived> Proxy;
1281 friend class ScalarProxy<Derived>;
1282 friend class VectorProxy<Derived>;
1283 friend class DataWrapVec<Derived, Vector2dInfoProxy>;
1284 friend class DataWrapVec2d<Derived, Vector2dInfoProxy>;
1293 Storage *data(off_type index) { return &storage[index]; }
1294 const Storage *data(off_type index) const { return &storage[index]; }
1297 Vector2dBase(Group *parent, const char *name, const char *desc)
1298 : DataWrapVec2d<Derived, Vector2dInfoProxy>(parent, name, desc),
1299 x(0), y(0), _size(0), storage(nullptr)
1307 for (off_type i = 0; i < _size; ++i)
1308 data(i)->~Storage();
1309 delete [] reinterpret_cast<char *>(storage);
1313 init(size_type _x, size_type _y)
1315 assert(_x > 0 && _y > 0 && "sizes must be positive!");
1316 assert(!storage && "already initialized");
1318 Derived &self = this->self();
1319 Info *info = this->info();
1327 char *ptr = new char[_size * sizeof(Storage)];
1328 storage = reinterpret_cast<Storage *>(ptr);
1330 for (off_type i = 0; i < _size; ++i)
1331 new (&storage[i]) Storage(info);
1339 operator[](off_type index)
1341 off_type offset = index * y;
1342 assert (offset + y <= size());
1343 return Proxy(this->self(), offset, y);
1356 return data(0)->zero();
1360 * Return a total of all entries in this vector.
1361 * @return The total of all vector entries.
1367 for (off_type i = 0; i < size(); ++i)
1368 total += data(i)->result();
1375 Info *info = this->info();
1376 size_type size = this->size();
1378 for (off_type i = 0; i < size; ++i)
1379 data(i)->prepare(info);
1381 info->cvec.resize(size);
1382 for (off_type i = 0; i < size; ++i)
1383 info->cvec[i] = data(i)->value();
1387 * Reset stat value to default
1392 Info *info = this->info();
1393 size_type size = this->size();
1394 for (off_type i = 0; i < size; ++i)
1395 data(i)->reset(info);
1401 return storage != NULL;
1405 //////////////////////////////////////////////////////////////////////
1407 // Non formula statistics
1409 //////////////////////////////////////////////////////////////////////
1410 /** The parameters for a distribution stat. */
1411 struct DistParams : public StorageParams
1413 const DistType type;
1414 DistParams(DistType t) : type(t) {}
1418 * Templatized storage and interface for a distribution stat.
1423 /** The parameters for a distribution stat. */
1424 struct Params : public DistParams
1426 /** The minimum value to track. */
1428 /** The maximum value to track. */
1430 /** The number of entries in each bucket. */
1431 Counter bucket_size;
1432 /** The number of buckets. Equal to (max-min)/bucket_size. */
1435 Params() : DistParams(Dist), min(0), max(0), bucket_size(0),
1440 /** The minimum value to track. */
1442 /** The maximum value to track. */
1444 /** The number of entries in each bucket. */
1445 Counter bucket_size;
1447 /** The smallest value sampled. */
1449 /** The largest value sampled. */
1451 /** The number of values sampled less than min. */
1453 /** The number of values sampled more than max. */
1455 /** The current sum. */
1457 /** The sum of squares. */
1459 /** The number of samples. */
1461 /** Counter for each bucket. */
1465 DistStor(Info *info)
1466 : cvec(safe_cast<const Params *>(info->storageParams)->buckets)
1472 * Add a value to the distribution for the given number of times.
1473 * @param val The value to add.
1474 * @param number The number of times to add the value.
1477 sample(Counter val, int number)
1479 if (val < min_track)
1480 underflow += number;
1481 else if (val > max_track)
1485 (size_type)std::floor((val - min_track) / bucket_size);
1486 assert(index < size());
1487 cvec[index] += number;
1496 sum += val * number;
1497 squares += val * val * number;
1502 * Return the number of buckets in this distribution.
1503 * @return the number of buckets.
1505 size_type size() const { return cvec.size(); }
1508 * Returns true if any calls to sample have been made.
1509 * @return True if any values have been sampled.
1514 return samples == Counter();
1518 prepare(Info *info, DistData &data)
1520 const Params *params = safe_cast<const Params *>(info->storageParams);
1522 assert(params->type == Dist);
1523 data.type = params->type;
1524 data.min = params->min;
1525 data.max = params->max;
1526 data.bucket_size = params->bucket_size;
1528 data.min_val = (min_val == CounterLimits::max()) ? 0 : min_val;
1529 data.max_val = (max_val == CounterLimits::min()) ? 0 : max_val;
1530 data.underflow = underflow;
1531 data.overflow = overflow;
1533 data.cvec.resize(params->buckets);
1534 for (off_type i = 0; i < params->buckets; ++i)
1535 data.cvec[i] = cvec[i];
1538 data.squares = squares;
1539 data.samples = samples;
1543 * Reset stat value to default
1548 const Params *params = safe_cast<const Params *>(info->storageParams);
1549 min_track = params->min;
1550 max_track = params->max;
1551 bucket_size = params->bucket_size;
1553 min_val = CounterLimits::max();
1554 max_val = CounterLimits::min();
1555 underflow = Counter();
1556 overflow = Counter();
1558 size_type size = cvec.size();
1559 for (off_type i = 0; i < size; ++i)
1560 cvec[i] = Counter();
1563 squares = Counter();
1564 samples = Counter();
1569 * Templatized storage and interface for a histogram stat.
1574 /** The parameters for a distribution stat. */
1575 struct Params : public DistParams
1577 /** The number of buckets.. */
1580 Params() : DistParams(Hist), buckets(0) {}
1584 /** The minimum value to track. */
1586 /** The maximum value to track. */
1588 /** The number of entries in each bucket. */
1589 Counter bucket_size;
1591 /** The current sum. */
1593 /** The sum of logarithm of each sample, used to compute geometric mean. */
1595 /** The sum of squares. */
1597 /** The number of samples. */
1599 /** Counter for each bucket. */
1603 HistStor(Info *info)
1604 : cvec(safe_cast<const Params *>(info->storageParams)->buckets)
1611 void grow_convert();
1612 void add(HistStor *);
1615 * Add a value to the distribution for the given number of times.
1616 * @param val The value to add.
1617 * @param number The number of times to add the value.
1620 sample(Counter val, int number)
1622 assert(min_bucket < max_bucket);
1623 if (val < min_bucket) {
1624 if (min_bucket == 0)
1627 while (val < min_bucket)
1629 } else if (val >= max_bucket + bucket_size) {
1630 if (min_bucket == 0) {
1631 while (val >= max_bucket + bucket_size)
1634 while (val >= max_bucket + bucket_size)
1640 (int64_t)std::floor((val - min_bucket) / bucket_size);
1642 assert(index < size());
1643 cvec[index] += number;
1645 sum += val * number;
1646 squares += val * val * number;
1647 logs += log(val) * number;
1652 * Return the number of buckets in this distribution.
1653 * @return the number of buckets.
1655 size_type size() const { return cvec.size(); }
1658 * Returns true if any calls to sample have been made.
1659 * @return True if any values have been sampled.
1664 return samples == Counter();
1668 prepare(Info *info, DistData &data)
1670 const Params *params = safe_cast<const Params *>(info->storageParams);
1672 assert(params->type == Hist);
1673 data.type = params->type;
1674 data.min = min_bucket;
1675 data.max = max_bucket + bucket_size - 1;
1676 data.bucket_size = bucket_size;
1678 data.min_val = min_bucket;
1679 data.max_val = max_bucket;
1681 int buckets = params->buckets;
1682 data.cvec.resize(buckets);
1683 for (off_type i = 0; i < buckets; ++i)
1684 data.cvec[i] = cvec[i];
1688 data.squares = squares;
1689 data.samples = samples;
1693 * Reset stat value to default
1698 const Params *params = safe_cast<const Params *>(info->storageParams);
1700 max_bucket = params->buckets - 1;
1703 size_type size = cvec.size();
1704 for (off_type i = 0; i < size; ++i)
1705 cvec[i] = Counter();
1708 squares = Counter();
1709 samples = Counter();
1715 * Templatized storage and interface for a distribution that calculates mean
1721 struct Params : public DistParams
1723 Params() : DistParams(Deviation) {}
1727 /** The current sum. */
1729 /** The sum of squares. */
1731 /** The number of samples. */
1736 * Create and initialize this storage.
1738 SampleStor(Info *info)
1739 : sum(Counter()), squares(Counter()), samples(Counter())
1743 * Add a value the given number of times to this running average.
1744 * Update the running sum and sum of squares, increment the number of
1745 * values seen by the given number.
1746 * @param val The value to add.
1747 * @param number The number of times to add the value.
1750 sample(Counter val, int number)
1752 sum += val * number;
1753 squares += val * val * number;
1758 * Return the number of entries in this stat, 1
1761 size_type size() const { return 1; }
1764 * Return true if no samples have been added.
1765 * @return True if no samples have been added.
1767 bool zero() const { return samples == Counter(); }
1770 prepare(Info *info, DistData &data)
1772 const Params *params = safe_cast<const Params *>(info->storageParams);
1774 assert(params->type == Deviation);
1775 data.type = params->type;
1777 data.squares = squares;
1778 data.samples = samples;
1782 * Reset stat value to default
1788 squares = Counter();
1789 samples = Counter();
1794 * Templatized storage for distribution that calculates per tick mean and
1800 struct Params : public DistParams
1802 Params() : DistParams(Deviation) {}
1806 /** Current total. */
1808 /** Current sum of squares. */
1813 * Create and initialize this storage.
1815 AvgSampleStor(Info *info)
1816 : sum(Counter()), squares(Counter())
1820 * Add a value to the distribution for the given number of times.
1821 * Update the running sum and sum of squares.
1822 * @param val The value to add.
1823 * @param number The number of times to add the value.
1826 sample(Counter val, int number)
1828 sum += val * number;
1829 squares += val * val * number;
1833 * Return the number of entries, in this case 1.
1836 size_type size() const { return 1; }
1839 * Return true if no samples have been added.
1840 * @return True if the sum is zero.
1842 bool zero() const { return sum == Counter(); }
1845 prepare(Info *info, DistData &data)
1847 const Params *params = safe_cast<const Params *>(info->storageParams);
1849 assert(params->type == Deviation);
1850 data.type = params->type;
1852 data.squares = squares;
1853 data.samples = curTick();
1857 * Reset stat value to default
1863 squares = Counter();
1868 * Implementation of a distribution stat. The type of distribution is
1869 * determined by the Storage template. @sa ScalarBase
1871 template <class Derived, class Stor>
1872 class DistBase : public DataWrap<Derived, DistInfoProxy>
1875 typedef DistInfoProxy<Derived> Info;
1876 typedef Stor Storage;
1877 typedef typename Stor::Params Params;
1880 /** The storage for this stat. */
1881 M5_ALIGNED(8) char storage[sizeof(Storage)];
1885 * Retrieve the storage.
1886 * @return The storage object for this stat.
1891 return reinterpret_cast<Storage *>(storage);
1895 * Retrieve a const pointer to the storage.
1896 * @return A const pointer to the storage object for this stat.
1901 return reinterpret_cast<const Storage *>(storage);
1907 new (storage) Storage(this->info());
1912 DistBase(Group *parent, const char *name, const char *desc)
1913 : DataWrap<Derived, DistInfoProxy>(parent, name, desc)
1918 * Add a value to the distribtion n times. Calls sample on the storage
1920 * @param v The value to add.
1921 * @param n The number of times to add it, defaults to 1.
1923 template <typename U>
1924 void sample(const U &v, int n = 1) { data()->sample(v, n); }
1927 * Return the number of entries in this stat.
1928 * @return The number of entries.
1930 size_type size() const { return data()->size(); }
1932 * Return true if no samples have been added.
1933 * @return True if there haven't been any samples.
1935 bool zero() const { return data()->zero(); }
1940 Info *info = this->info();
1941 data()->prepare(info, info->data);
1945 * Reset stat value to default
1950 data()->reset(this->info());
1954 * Add the argument distribution to the this distribution.
1956 void add(DistBase &d) { data()->add(d.data()); }
1960 template <class Stat>
1963 template <class Derived, class Stor>
1964 class VectorDistBase : public DataWrapVec<Derived, VectorDistInfoProxy>
1967 typedef VectorDistInfoProxy<Derived> Info;
1968 typedef Stor Storage;
1969 typedef typename Stor::Params Params;
1970 typedef DistProxy<Derived> Proxy;
1971 friend class DistProxy<Derived>;
1972 friend class DataWrapVec<Derived, VectorDistInfoProxy>;
1980 data(off_type index)
1982 return &storage[index];
1986 data(off_type index) const
1988 return &storage[index];
1994 assert(s > 0 && "size must be positive!");
1995 assert(!storage && "already initialized");
1998 char *ptr = new char[_size * sizeof(Storage)];
1999 storage = reinterpret_cast<Storage *>(ptr);
2001 Info *info = this->info();
2002 for (off_type i = 0; i < _size; ++i)
2003 new (&storage[i]) Storage(info);
2009 VectorDistBase(Group *parent, const char *name, const char *desc)
2010 : DataWrapVec<Derived, VectorDistInfoProxy>(parent, name, desc),
2019 for (off_type i = 0; i < _size; ++i)
2020 data(i)->~Storage();
2021 delete [] reinterpret_cast<char *>(storage);
2024 Proxy operator[](off_type index)
2026 assert(index < size());
2027 return Proxy(this->self(), index);
2039 for (off_type i = 0; i < size(); ++i)
2040 if (!data(i)->zero())
2048 Info *info = this->info();
2049 size_type size = this->size();
2050 info->data.resize(size);
2051 for (off_type i = 0; i < size; ++i)
2052 data(i)->prepare(info, info->data[i]);
2058 return storage != NULL;
2062 template <class Stat>
2070 typename Stat::Storage *data() { return stat.data(index); }
2071 const typename Stat::Storage *data() const { return stat.data(index); }
2074 DistProxy(Stat &s, off_type i)
2078 DistProxy(const DistProxy &sp)
2079 : stat(sp.stat), index(sp.index)
2083 operator=(const DistProxy &sp)
2091 template <typename U>
2093 sample(const U &v, int n = 1)
2095 data()->sample(v, n);
2107 return data()->zero();
2111 * Proxy has no state. Nothing to reset.
2116 //////////////////////////////////////////////////////////////////////
2120 //////////////////////////////////////////////////////////////////////
2123 * Base class for formula statistic node. These nodes are used to build a tree
2124 * that represents the formula.
2130 * Return the number of nodes in the subtree starting at this node.
2131 * @return the number of nodes in this subtree.
2133 virtual size_type size() const = 0;
2135 * Return the result vector of this subtree.
2136 * @return The result vector of this subtree.
2138 virtual const VResult &result() const = 0;
2140 * Return the total of the result vector.
2141 * @return The total of the result vector.
2143 virtual Result total() const = 0;
2148 virtual std::string str() const = 0;
2153 /** Shared pointer to a function Node. */
2154 typedef std::shared_ptr<Node> NodePtr;
2156 class ScalarStatNode : public Node
2159 const ScalarInfo *data;
2160 mutable VResult vresult;
2163 ScalarStatNode(const ScalarInfo *d) : data(d), vresult(1) {}
2168 vresult[0] = data->result();
2172 Result total() const { return data->result(); };
2174 size_type size() const { return 1; }
2179 std::string str() const { return data->name; }
2182 template <class Stat>
2183 class ScalarProxyNode : public Node
2186 const ScalarProxy<Stat> proxy;
2187 mutable VResult vresult;
2190 ScalarProxyNode(const ScalarProxy<Stat> &p)
2191 : proxy(p), vresult(1)
2197 vresult[0] = proxy.result();
2204 return proxy.result();
2223 class VectorStatNode : public Node
2226 const VectorInfo *data;
2229 VectorStatNode(const VectorInfo *d) : data(d) { }
2230 const VResult &result() const { return data->result(); }
2231 Result total() const { return data->total(); };
2233 size_type size() const { return data->size(); }
2235 std::string str() const { return data->name; }
2239 class ConstNode : public Node
2245 ConstNode(T s) : vresult(1, (Result)s) {}
2246 const VResult &result() const { return vresult; }
2247 Result total() const { return vresult[0]; };
2248 size_type size() const { return 1; }
2249 std::string str() const { return std::to_string(vresult[0]); }
2253 class ConstVectorNode : public Node
2259 ConstVectorNode(const T &s) : vresult(s.begin(), s.end()) {}
2260 const VResult &result() const { return vresult; }
2265 size_type size = this->size();
2267 for (off_type i = 0; i < size; i++)
2272 size_type size() const { return vresult.size(); }
2276 size_type size = this->size();
2277 std::string tmp = "(";
2278 for (off_type i = 0; i < size; i++)
2279 tmp += csprintf("%s ", std::to_string(vresult[i]));
2289 struct OpString<std::plus<Result> >
2291 static std::string str() { return "+"; }
2295 struct OpString<std::minus<Result> >
2297 static std::string str() { return "-"; }
2301 struct OpString<std::multiplies<Result> >
2303 static std::string str() { return "*"; }
2307 struct OpString<std::divides<Result> >
2309 static std::string str() { return "/"; }
2313 struct OpString<std::modulus<Result> >
2315 static std::string str() { return "%"; }
2319 struct OpString<std::negate<Result> >
2321 static std::string str() { return "-"; }
2325 class UnaryNode : public Node
2329 mutable VResult vresult;
2332 UnaryNode(NodePtr &p) : l(p) {}
2337 const VResult &lvec = l->result();
2338 size_type size = lvec.size();
2342 vresult.resize(size);
2344 for (off_type i = 0; i < size; ++i)
2345 vresult[i] = op(lvec[i]);
2353 const VResult &vec = this->result();
2355 for (off_type i = 0; i < size(); i++)
2360 size_type size() const { return l->size(); }
2365 return OpString<Op>::str() + l->str();
2370 class BinaryNode : public Node
2375 mutable VResult vresult;
2378 BinaryNode(NodePtr &a, NodePtr &b) : l(a), r(b) {}
2381 result() const override
2384 const VResult &lvec = l->result();
2385 const VResult &rvec = r->result();
2387 assert(lvec.size() > 0 && rvec.size() > 0);
2389 if (lvec.size() == 1 && rvec.size() == 1) {
2391 vresult[0] = op(lvec[0], rvec[0]);
2392 } else if (lvec.size() == 1) {
2393 size_type size = rvec.size();
2394 vresult.resize(size);
2395 for (off_type i = 0; i < size; ++i)
2396 vresult[i] = op(lvec[0], rvec[i]);
2397 } else if (rvec.size() == 1) {
2398 size_type size = lvec.size();
2399 vresult.resize(size);
2400 for (off_type i = 0; i < size; ++i)
2401 vresult[i] = op(lvec[i], rvec[0]);
2402 } else if (rvec.size() == lvec.size()) {
2403 size_type size = rvec.size();
2404 vresult.resize(size);
2405 for (off_type i = 0; i < size; ++i)
2406 vresult[i] = op(lvec[i], rvec[i]);
2413 total() const override
2415 const VResult &vec = this->result();
2416 const VResult &lvec = l->result();
2417 const VResult &rvec = r->result();
2423 assert(lvec.size() > 0 && rvec.size() > 0);
2424 assert(lvec.size() == rvec.size() ||
2425 lvec.size() == 1 || rvec.size() == 1);
2427 /** If vectors are the same divide their sums (x0+x1)/(y0+y1) */
2428 if (lvec.size() == rvec.size() && lvec.size() > 1) {
2429 for (off_type i = 0; i < size(); ++i) {
2433 return op(lsum, rsum);
2436 /** Otherwise divide each item by the divisor */
2437 for (off_type i = 0; i < size(); ++i) {
2445 size() const override
2447 size_type ls = l->size();
2448 size_type rs = r->size();
2451 } else if (rs == 1) {
2454 assert(ls == rs && "Node vector sizes are not equal");
2460 str() const override
2462 return csprintf("(%s %s %s)", l->str(), OpString<Op>::str(), r->str());
2467 class SumNode : public Node
2471 mutable VResult vresult;
2474 SumNode(NodePtr &p) : l(p), vresult(1) {}
2479 const VResult &lvec = l->result();
2480 size_type size = lvec.size();
2486 for (off_type i = 0; i < size; ++i)
2487 vresult[0] = op(vresult[0], lvec[i]);
2495 const VResult &lvec = l->result();
2496 size_type size = lvec.size();
2499 Result result = 0.0;
2502 for (off_type i = 0; i < size; ++i)
2503 result = op(result, lvec[i]);
2508 size_type size() const { return 1; }
2513 return csprintf("total(%s)", l->str());
2518 //////////////////////////////////////////////////////////////////////
2520 // Visible Statistics Types
2522 //////////////////////////////////////////////////////////////////////
2524 * @defgroup VisibleStats "Statistic Types"
2525 * These are the statistics that are used in the simulator.
2530 * This is a simple scalar statistic, like a counter.
2531 * @sa Stat, ScalarBase, StatStor
2533 class Scalar : public ScalarBase<Scalar, StatStor>
2536 using ScalarBase<Scalar, StatStor>::operator=;
2538 Scalar(Group *parent = nullptr, const char *name = nullptr,
2539 const char *desc = nullptr)
2540 : ScalarBase<Scalar, StatStor>(parent, name, desc)
2546 * A stat that calculates the per tick average of a value.
2547 * @sa Stat, ScalarBase, AvgStor
2549 class Average : public ScalarBase<Average, AvgStor>
2552 using ScalarBase<Average, AvgStor>::operator=;
2554 Average(Group *parent = nullptr, const char *name = nullptr,
2555 const char *desc = nullptr)
2556 : ScalarBase<Average, AvgStor>(parent, name, desc)
2561 class Value : public ValueBase<Value>
2564 Value(Group *parent = nullptr, const char *name = nullptr,
2565 const char *desc = nullptr)
2566 : ValueBase<Value>(parent, name, desc)
2572 * A vector of scalar stats.
2573 * @sa Stat, VectorBase, StatStor
2575 class Vector : public VectorBase<Vector, StatStor>
2578 Vector(Group *parent = nullptr, const char *name = nullptr,
2579 const char *desc = nullptr)
2580 : VectorBase<Vector, StatStor>(parent, name, desc)
2586 * A vector of Average stats.
2587 * @sa Stat, VectorBase, AvgStor
2589 class AverageVector : public VectorBase<AverageVector, AvgStor>
2592 AverageVector(Group *parent = nullptr, const char *name = nullptr,
2593 const char *desc = nullptr)
2594 : VectorBase<AverageVector, AvgStor>(parent, name, desc)
2600 * A 2-Dimensional vecto of scalar stats.
2601 * @sa Stat, Vector2dBase, StatStor
2603 class Vector2d : public Vector2dBase<Vector2d, StatStor>
2606 Vector2d(Group *parent = nullptr, const char *name = nullptr,
2607 const char *desc = nullptr)
2608 : Vector2dBase<Vector2d, StatStor>(parent, name, desc)
2614 * A simple distribution stat.
2615 * @sa Stat, DistBase, DistStor
2617 class Distribution : public DistBase<Distribution, DistStor>
2620 Distribution(Group *parent = nullptr, const char *name = nullptr,
2621 const char *desc = nullptr)
2622 : DistBase<Distribution, DistStor>(parent, name, desc)
2627 * Set the parameters of this distribution. @sa DistStor::Params
2628 * @param min The minimum value of the distribution.
2629 * @param max The maximum value of the distribution.
2630 * @param bkt The number of values in each bucket.
2631 * @return A reference to this distribution.
2634 init(Counter min, Counter max, Counter bkt)
2636 DistStor::Params *params = new DistStor::Params;
2639 params->bucket_size = bkt;
2640 // Division by zero is especially serious in an Aarch64 host,
2641 // where it gets rounded to allocate 32GiB RAM.
2643 params->buckets = (size_type)ceil((max - min + 1.0) / bkt);
2644 this->setParams(params);
2646 return this->self();
2651 * A simple histogram stat.
2652 * @sa Stat, DistBase, HistStor
2654 class Histogram : public DistBase<Histogram, HistStor>
2657 Histogram(Group *parent = nullptr, const char *name = nullptr,
2658 const char *desc = nullptr)
2659 : DistBase<Histogram, HistStor>(parent, name, desc)
2664 * Set the parameters of this histogram. @sa HistStor::Params
2665 * @param size The number of buckets in the histogram
2666 * @return A reference to this histogram.
2669 init(size_type size)
2671 HistStor::Params *params = new HistStor::Params;
2672 params->buckets = size;
2673 this->setParams(params);
2675 return this->self();
2680 * Calculates the mean and variance of all the samples.
2681 * @sa DistBase, SampleStor
2683 class StandardDeviation : public DistBase<StandardDeviation, SampleStor>
2687 * Construct and initialize this distribution.
2689 StandardDeviation(Group *parent = nullptr, const char *name = nullptr,
2690 const char *desc = nullptr)
2691 : DistBase<StandardDeviation, SampleStor>(parent, name, desc)
2693 SampleStor::Params *params = new SampleStor::Params;
2695 this->setParams(params);
2700 * Calculates the per tick mean and variance of the samples.
2701 * @sa DistBase, AvgSampleStor
2703 class AverageDeviation : public DistBase<AverageDeviation, AvgSampleStor>
2707 * Construct and initialize this distribution.
2709 AverageDeviation(Group *parent = nullptr, const char *name = nullptr,
2710 const char *desc = nullptr)
2711 : DistBase<AverageDeviation, AvgSampleStor>(parent, name, desc)
2713 AvgSampleStor::Params *params = new AvgSampleStor::Params;
2715 this->setParams(params);
2720 * A vector of distributions.
2721 * @sa VectorDistBase, DistStor
2723 class VectorDistribution : public VectorDistBase<VectorDistribution, DistStor>
2726 VectorDistribution(Group *parent = nullptr, const char *name = nullptr,
2727 const char *desc = nullptr)
2728 : VectorDistBase<VectorDistribution, DistStor>(parent, name, desc)
2733 * Initialize storage and parameters for this distribution.
2734 * @param size The size of the vector (the number of distributions).
2735 * @param min The minimum value of the distribution.
2736 * @param max The maximum value of the distribution.
2737 * @param bkt The number of values in each bucket.
2738 * @return A reference to this distribution.
2740 VectorDistribution &
2741 init(size_type size, Counter min, Counter max, Counter bkt)
2743 DistStor::Params *params = new DistStor::Params;
2746 params->bucket_size = bkt;
2747 params->buckets = (size_type)ceil((max - min + 1.0) / bkt);
2748 this->setParams(params);
2750 return this->self();
2755 * This is a vector of StandardDeviation stats.
2756 * @sa VectorDistBase, SampleStor
2758 class VectorStandardDeviation
2759 : public VectorDistBase<VectorStandardDeviation, SampleStor>
2762 VectorStandardDeviation(Group *parent = nullptr, const char *name = nullptr,
2763 const char *desc = nullptr)
2764 : VectorDistBase<VectorStandardDeviation, SampleStor>(parent, name,
2770 * Initialize storage for this distribution.
2771 * @param size The size of the vector.
2772 * @return A reference to this distribution.
2774 VectorStandardDeviation &
2775 init(size_type size)
2777 SampleStor::Params *params = new SampleStor::Params;
2779 this->setParams(params);
2780 return this->self();
2785 * This is a vector of AverageDeviation stats.
2786 * @sa VectorDistBase, AvgSampleStor
2788 class VectorAverageDeviation
2789 : public VectorDistBase<VectorAverageDeviation, AvgSampleStor>
2792 VectorAverageDeviation(Group *parent = nullptr, const char *name = nullptr,
2793 const char *desc = nullptr)
2794 : VectorDistBase<VectorAverageDeviation, AvgSampleStor>(parent, name,
2800 * Initialize storage for this distribution.
2801 * @param size The size of the vector.
2802 * @return A reference to this distribution.
2804 VectorAverageDeviation &
2805 init(size_type size)
2807 AvgSampleStor::Params *params = new AvgSampleStor::Params;
2809 this->setParams(params);
2810 return this->self();
2814 template <class Stat>
2815 class FormulaInfoProxy : public InfoProxy<Stat, FormulaInfo>
2818 mutable VResult vec;
2819 mutable VCounter cvec;
2822 FormulaInfoProxy(Stat &stat) : InfoProxy<Stat, FormulaInfo>(stat) {}
2824 size_type size() const { return this->s.size(); }
2829 this->s.result(vec);
2832 Result total() const { return this->s.total(); }
2833 VCounter &value() const { return cvec; }
2835 std::string str() const { return this->s.str(); }
2838 template <class Stat>
2839 class SparseHistInfoProxy : public InfoProxy<Stat, SparseHistInfo>
2842 SparseHistInfoProxy(Stat &stat) : InfoProxy<Stat, SparseHistInfo>(stat) {}
2846 * Implementation of a sparse histogram stat. The storage class is
2847 * determined by the Storage template.
2849 template <class Derived, class Stor>
2850 class SparseHistBase : public DataWrap<Derived, SparseHistInfoProxy>
2853 typedef SparseHistInfoProxy<Derived> Info;
2854 typedef Stor Storage;
2855 typedef typename Stor::Params Params;
2858 /** The storage for this stat. */
2859 char storage[sizeof(Storage)];
2863 * Retrieve the storage.
2864 * @return The storage object for this stat.
2869 return reinterpret_cast<Storage *>(storage);
2873 * Retrieve a const pointer to the storage.
2874 * @return A const pointer to the storage object for this stat.
2879 return reinterpret_cast<const Storage *>(storage);
2885 new (storage) Storage(this->info());
2890 SparseHistBase(Group *parent, const char *name, const char *desc)
2891 : DataWrap<Derived, SparseHistInfoProxy>(parent, name, desc)
2896 * Add a value to the distribtion n times. Calls sample on the storage
2898 * @param v The value to add.
2899 * @param n The number of times to add it, defaults to 1.
2901 template <typename U>
2902 void sample(const U &v, int n = 1) { data()->sample(v, n); }
2905 * Return the number of entries in this stat.
2906 * @return The number of entries.
2908 size_type size() const { return data()->size(); }
2910 * Return true if no samples have been added.
2911 * @return True if there haven't been any samples.
2913 bool zero() const { return data()->zero(); }
2918 Info *info = this->info();
2919 data()->prepare(info, info->data);
2923 * Reset stat value to default
2928 data()->reset(this->info());
2933 * Templatized storage and interface for a sparse histogram stat.
2935 class SparseHistStor
2938 /** The parameters for a sparse histogram stat. */
2939 struct Params : public DistParams
2941 Params() : DistParams(Hist) {}
2945 /** Counter for number of samples */
2947 /** Counter for each bucket. */
2951 SparseHistStor(Info *info)
2957 * Add a value to the distribution for the given number of times.
2958 * @param val The value to add.
2959 * @param number The number of times to add the value.
2962 sample(Counter val, int number)
2964 cmap[val] += number;
2969 * Return the number of buckets in this distribution.
2970 * @return the number of buckets.
2972 size_type size() const { return cmap.size(); }
2975 * Returns true if any calls to sample have been made.
2976 * @return True if any values have been sampled.
2981 return samples == Counter();
2985 prepare(Info *info, SparseHistData &data)
2987 MCounter::iterator it;
2989 for (it = cmap.begin(); it != cmap.end(); it++) {
2990 data.cmap[(*it).first] = (*it).second;
2993 data.samples = samples;
2997 * Reset stat value to default
3007 class SparseHistogram : public SparseHistBase<SparseHistogram, SparseHistStor>
3010 SparseHistogram(Group *parent = nullptr, const char *name = nullptr,
3011 const char *desc = nullptr)
3012 : SparseHistBase<SparseHistogram, SparseHistStor>(parent, name, desc)
3017 * Set the parameters of this histogram. @sa HistStor::Params
3018 * @param size The number of buckets in the histogram
3019 * @return A reference to this histogram.
3022 init(size_type size)
3024 SparseHistStor::Params *params = new SparseHistStor::Params;
3025 this->setParams(params);
3027 return this->self();
3033 * A formula for statistics that is calculated when printed. A formula is
3034 * stored as a tree of Nodes that represent the equation to calculate.
3035 * @sa Stat, ScalarStat, VectorStat, Node, Temp
3037 class Formula : public DataWrapVec<Formula, FormulaInfoProxy>
3040 /** The root of the tree which represents the Formula */
3046 * Create and initialize thie formula, and register it with the database.
3048 Formula(Group *parent = nullptr, const char *name = nullptr,
3049 const char *desc = nullptr);
3051 Formula(Group *parent, const char *name, const char *desc,
3055 * Set an unitialized Formula to the given root.
3056 * @param r The root of the expression tree.
3057 * @return a reference to this formula.
3059 const Formula &operator=(const Temp &r);
3061 template<typename T>
3062 const Formula &operator=(const T &v)
3069 * Add the given tree to the existing one.
3070 * @param r The root of the expression tree.
3071 * @return a reference to this formula.
3073 const Formula &operator+=(Temp r);
3076 * Divide the existing tree by the given one.
3077 * @param r The root of the expression tree.
3078 * @return a reference to this formula.
3080 const Formula &operator/=(Temp r);
3083 * Return the result of the Fomula in a vector. If there were no Vector
3084 * components to the Formula, then the vector is size 1. If there were,
3085 * like x/y with x being a vector of size 3, then the result returned will
3086 * be x[0]/y, x[1]/y, x[2]/y, respectively.
3087 * @return The result vector.
3089 void result(VResult &vec) const;
3092 * Return the total Formula result. If there is a Vector
3093 * component to this Formula, then this is the result of the
3094 * Formula if the formula is applied after summing all the
3095 * components of the Vector. For example, if Formula is x/y where
3096 * x is size 3, then total() will return (x[1]+x[2]+x[3])/y. If
3097 * there is no Vector component, total() returns the same value as
3098 * the first entry in the VResult val() returns.
3099 * @return The total of the result vector.
3101 Result total() const;
3104 * Return the number of elements in the tree.
3106 size_type size() const;
3111 * Formulas don't need to be reset
3120 std::string str() const;
3123 class FormulaNode : public Node
3126 const Formula &formula;
3127 mutable VResult vec;
3130 FormulaNode(const Formula &f) : formula(f) {}
3132 size_type size() const { return formula.size(); }
3133 const VResult &result() const { formula.result(vec); return vec; }
3134 Result total() const { return formula.total(); }
3136 std::string str() const { return formula.str(); }
3140 * Helper class to construct formula node trees.
3146 * Pointer to a Node object.
3152 * Copy the given pointer to this class.
3153 * @param n A pointer to a Node object to copy.
3155 Temp(const NodePtr &n) : node(n) { }
3157 Temp(NodePtr &&n) : node(std::move(n)) { }
3160 * Return the node pointer.
3161 * @return the node pointer.
3163 operator NodePtr&() { return node; }
3166 * Makde gcc < 4.6.3 happy and explicitly get the underlying node.
3168 NodePtr getNodePtr() const { return node; }
3172 * Create a new ScalarStatNode.
3173 * @param s The ScalarStat to place in a node.
3175 Temp(const Scalar &s)
3176 : node(new ScalarStatNode(s.info()))
3180 * Create a new ScalarStatNode.
3181 * @param s The ScalarStat to place in a node.
3183 Temp(const Value &s)
3184 : node(new ScalarStatNode(s.info()))
3188 * Create a new ScalarStatNode.
3189 * @param s The ScalarStat to place in a node.
3191 Temp(const Average &s)
3192 : node(new ScalarStatNode(s.info()))
3196 * Create a new VectorStatNode.
3197 * @param s The VectorStat to place in a node.
3199 Temp(const Vector &s)
3200 : node(new VectorStatNode(s.info()))
3203 Temp(const AverageVector &s)
3204 : node(new VectorStatNode(s.info()))
3210 Temp(const Formula &f)
3211 : node(new FormulaNode(f))
3215 * Create a new ScalarProxyNode.
3216 * @param p The ScalarProxy to place in a node.
3218 template <class Stat>
3219 Temp(const ScalarProxy<Stat> &p)
3220 : node(new ScalarProxyNode<Stat>(p))
3224 * Create a ConstNode
3225 * @param value The value of the const node.
3227 Temp(signed char value)
3228 : node(new ConstNode<signed char>(value))
3232 * Create a ConstNode
3233 * @param value The value of the const node.
3235 Temp(unsigned char value)
3236 : node(new ConstNode<unsigned char>(value))
3240 * Create a ConstNode
3241 * @param value The value of the const node.
3243 Temp(signed short value)
3244 : node(new ConstNode<signed short>(value))
3248 * Create a ConstNode
3249 * @param value The value of the const node.
3251 Temp(unsigned short value)
3252 : node(new ConstNode<unsigned short>(value))
3256 * Create a ConstNode
3257 * @param value The value of the const node.
3259 Temp(signed int value)
3260 : node(new ConstNode<signed int>(value))
3264 * Create a ConstNode
3265 * @param value The value of the const node.
3267 Temp(unsigned int value)
3268 : node(new ConstNode<unsigned int>(value))
3272 * Create a ConstNode
3273 * @param value The value of the const node.
3275 Temp(signed long value)
3276 : node(new ConstNode<signed long>(value))
3280 * Create a ConstNode
3281 * @param value The value of the const node.
3283 Temp(unsigned long value)
3284 : node(new ConstNode<unsigned long>(value))
3288 * Create a ConstNode
3289 * @param value The value of the const node.
3291 Temp(signed long long value)
3292 : node(new ConstNode<signed long long>(value))
3296 * Create a ConstNode
3297 * @param value The value of the const node.
3299 Temp(unsigned long long value)
3300 : node(new ConstNode<unsigned long long>(value))
3304 * Create a ConstNode
3305 * @param value The value of the const node.
3308 : node(new ConstNode<float>(value))
3312 * Create a ConstNode
3313 * @param value The value of the const node.
3316 : node(new ConstNode<double>(value))
3326 operator+(Temp l, Temp r)
3328 return Temp(std::make_shared<BinaryNode<std::plus<Result> > >(l, r));
3332 operator-(Temp l, Temp r)
3334 return Temp(std::make_shared<BinaryNode<std::minus<Result> > >(l, r));
3338 operator*(Temp l, Temp r)
3340 return Temp(std::make_shared<BinaryNode<std::multiplies<Result> > >(l, r));
3344 operator/(Temp l, Temp r)
3346 return Temp(std::make_shared<BinaryNode<std::divides<Result> > >(l, r));
3352 return Temp(std::make_shared<UnaryNode<std::negate<Result> > >(l));
3355 template <typename T>
3359 return Temp(std::make_shared<ConstNode<T> >(val));
3362 template <typename T>
3364 constantVector(T val)
3366 return Temp(std::make_shared<ConstVectorNode<T> >(val));
3372 return Temp(std::make_shared<SumNode<std::plus<Result> > >(val));
3375 /** Dump all statistics data to the registered outputs */
3380 const Info* resolve(const std::string &name);
3383 * Register reset and dump handlers. These are the functions which
3384 * will actually perform the whole statistics reset/dump actions
3385 * including processing the reset/dump callbacks
3387 typedef void (*Handler)();
3389 void registerHandlers(Handler reset_handler, Handler dump_handler);
3392 * Register a callback that should be called whenever statistics are
3395 void registerResetCallback(const std::function<void()> &callback);
3398 * Register a callback that should be called whenever statistics are
3399 * about to be dumped
3401 void registerDumpCallback(const std::function<void()> &callback);
3404 * Process all the callbacks in the reset callbacks queue
3406 void processResetQueue();
3409 * Process all the callbacks in the dump callbacks queue
3411 void processDumpQueue();
3413 std::list<Info *> &statsList();
3415 typedef std::map<const void *, Info *> MapType;
3416 MapType &statsMap();
3418 typedef std::map<std::string, Info *> NameMapType;
3419 NameMapType &nameMap();
3421 bool validateStatName(const std::string &name);
3423 } // namespace Stats
3425 void debugDumpStats();
3427 #endif // __BASE_STATISTICS_HH__