dev-arm: Set ICV_IGRPEN<n>_EL1-ICH_VMCR_EL2 mapping on reads
[gem5.git] / src / base / statistics.hh
1 /*
2 * Copyright (c) 2003-2005 The Regents of The University of Michigan
3 * Copyright (c) 2017, Centre National de la Recherche Scientifique
4 * All rights reserved.
5 *
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.
16 *
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.
28 *
29 * Authors: Nathan Binkert
30 * Pierre-Yves Peneau
31 */
32
33 /** @file
34 * Declaration of Statistics objects.
35 */
36
37 /**
38 * @todo
39 *
40 * Generalized N-dimensinal vector
41 * documentation
42 * key stats
43 * interval stats
44 * -- these both can use the same function that prints out a
45 * specific set of stats
46 * VectorStandardDeviation totals
47 * Document Namespaces
48 */
49 #ifndef __BASE_STATISTICS_HH__
50 #define __BASE_STATISTICS_HH__
51
52 #include <algorithm>
53 #include <cassert>
54 #ifdef __SUNPRO_CC
55 #include <math.h>
56 #endif
57 #include <cmath>
58 #include <functional>
59 #include <iosfwd>
60 #include <list>
61 #include <map>
62 #include <memory>
63 #include <string>
64 #include <vector>
65
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"
74
75 class Callback;
76
77 /** The current simulated tick. */
78 extern Tick curTick();
79
80 /* A namespace for all of the Statistics */
81 namespace Stats {
82
83 template <class Stat, class Base>
84 class InfoProxy : public Base
85 {
86 protected:
87 Stat &s;
88
89 public:
90 InfoProxy(Stat &stat) : s(stat) {}
91
92 bool check() const { return s.check(); }
93 void prepare() { s.prepare(); }
94 void reset() { s.reset(); }
95 void
96 visit(Output &visitor)
97 {
98 visitor.visit(*static_cast<Base *>(this));
99 }
100 bool zero() const { return s.zero(); }
101 };
102
103 template <class Stat>
104 class ScalarInfoProxy : public InfoProxy<Stat, ScalarInfo>
105 {
106 public:
107 ScalarInfoProxy(Stat &stat) : InfoProxy<Stat, ScalarInfo>(stat) {}
108
109 Counter value() const { return this->s.value(); }
110 Result result() const { return this->s.result(); }
111 Result total() const { return this->s.total(); }
112 };
113
114 template <class Stat>
115 class VectorInfoProxy : public InfoProxy<Stat, VectorInfo>
116 {
117 protected:
118 mutable VCounter cvec;
119 mutable VResult rvec;
120
121 public:
122 VectorInfoProxy(Stat &stat) : InfoProxy<Stat, VectorInfo>(stat) {}
123
124 size_type size() const { return this->s.size(); }
125
126 VCounter &
127 value() const
128 {
129 this->s.value(cvec);
130 return cvec;
131 }
132
133 const VResult &
134 result() const
135 {
136 this->s.result(rvec);
137 return rvec;
138 }
139
140 Result total() const { return this->s.total(); }
141 };
142
143 template <class Stat>
144 class DistInfoProxy : public InfoProxy<Stat, DistInfo>
145 {
146 public:
147 DistInfoProxy(Stat &stat) : InfoProxy<Stat, DistInfo>(stat) {}
148 };
149
150 template <class Stat>
151 class VectorDistInfoProxy : public InfoProxy<Stat, VectorDistInfo>
152 {
153 public:
154 VectorDistInfoProxy(Stat &stat) : InfoProxy<Stat, VectorDistInfo>(stat) {}
155
156 size_type size() const { return this->s.size(); }
157 };
158
159 template <class Stat>
160 class Vector2dInfoProxy : public InfoProxy<Stat, Vector2dInfo>
161 {
162 public:
163 Vector2dInfoProxy(Stat &stat) : InfoProxy<Stat, Vector2dInfo>(stat) {}
164
165 Result total() const { return this->s.total(); }
166 };
167
168 struct StorageParams
169 {
170 virtual ~StorageParams();
171 };
172
173 class InfoAccess
174 {
175 protected:
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 */
181 void setInit();
182
183 /** Grab the information class for this statistic */
184 Info *info();
185 /** Grab the information class for this statistic */
186 const Info *info() const;
187
188 public:
189 /**
190 * Reset the stat to the default state.
191 */
192 void reset() { }
193
194 /**
195 * @return true if this stat has a value and satisfies its
196 * requirement as a prereq
197 */
198 bool zero() const { return true; }
199
200 /**
201 * Check that this stat has been set up properly and is ready for
202 * use
203 * @return true for success
204 */
205 bool check() const { return true; }
206 };
207
208 template <class Derived, template <class> class InfoProxyType>
209 class DataWrap : public InfoAccess
210 {
211 public:
212 typedef InfoProxyType<Derived> Info;
213
214 protected:
215 Derived &self() { return *static_cast<Derived *>(this); }
216
217 protected:
218 Info *
219 info()
220 {
221 return safe_cast<Info *>(InfoAccess::info());
222 }
223
224 public:
225 const Info *
226 info() const
227 {
228 return safe_cast<const Info *>(InfoAccess::info());
229 }
230
231 protected:
232 /**
233 * Copy constructor, copies are not allowed.
234 */
235 DataWrap(const DataWrap &stat) = delete;
236
237 /**
238 * Can't copy stats.
239 */
240 void operator=(const DataWrap &) {}
241
242 public:
243 DataWrap()
244 {
245 this->setInfo(new Info(self()));
246 }
247
248 /**
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.
252 */
253 Derived &
254 name(const std::string &name)
255 {
256 Info *info = this->info();
257 info->setName(name);
258 info->flags.set(display);
259 return this->self();
260 }
261 const std::string &name() const { return this->info()->name; }
262
263 /**
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.
268 */
269 Derived &
270 setSeparator(const std::string &_sep)
271 {
272 this->info()->setSeparator(_sep);
273 return this->self();
274 }
275 const std::string &setSeparator() const
276 {
277 return this->info()->separatorString;
278 }
279
280 /**
281 * Set the description and marks this stat to print at the end of
282 * simulation.
283 * @param desc The new description.
284 * @return A reference to this stat.
285 */
286 Derived &
287 desc(const std::string &_desc)
288 {
289 this->info()->desc = _desc;
290 return this->self();
291 }
292
293 /**
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.
297 */
298 Derived &
299 precision(int _precision)
300 {
301 this->info()->precision = _precision;
302 return this->self();
303 }
304
305 /**
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.
309 */
310 Derived &
311 flags(Flags _flags)
312 {
313 this->info()->flags.set(_flags);
314 return this->self();
315 }
316
317 /**
318 * Set the prerequisite stat and marks this stat to print at the end of
319 * simulation.
320 * @param prereq The prerequisite stat.
321 * @return A reference to this stat.
322 */
323 template <class Stat>
324 Derived &
325 prereq(const Stat &prereq)
326 {
327 this->info()->prereq = prereq.info();
328 return this->self();
329 }
330 };
331
332 template <class Derived, template <class> class InfoProxyType>
333 class DataWrapVec : public DataWrap<Derived, InfoProxyType>
334 {
335 public:
336 typedef InfoProxyType<Derived> Info;
337
338 DataWrapVec()
339 {}
340
341 DataWrapVec(const DataWrapVec &ref)
342 {}
343
344 void operator=(const DataWrapVec &)
345 {}
346
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!
349
350 /**
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.
356 */
357 Derived &
358 subname(off_type index, const std::string &name)
359 {
360 Derived &self = this->self();
361 Info *info = self.info();
362
363 std::vector<std::string> &subn = info->subnames;
364 if (subn.size() <= index)
365 subn.resize(index + 1);
366 subn[index] = name;
367 return self;
368 }
369
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.
373
374 /**
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.
380 */
381 Derived &
382 subdesc(off_type index, const std::string &desc)
383 {
384 Info *info = this->info();
385
386 std::vector<std::string> &subd = info->subdescs;
387 if (subd.size() <= index)
388 subd.resize(index + 1);
389 subd[index] = desc;
390
391 return this->self();
392 }
393
394 void
395 prepare()
396 {
397 Derived &self = this->self();
398 Info *info = this->info();
399
400 size_t size = self.size();
401 for (off_type i = 0; i < size; ++i)
402 self.data(i)->prepare(info);
403 }
404
405 void
406 reset()
407 {
408 Derived &self = this->self();
409 Info *info = this->info();
410
411 size_t size = self.size();
412 for (off_type i = 0; i < size; ++i)
413 self.data(i)->reset(info);
414 }
415 };
416
417 template <class Derived, template <class> class InfoProxyType>
418 class DataWrapVec2d : public DataWrapVec<Derived, InfoProxyType>
419 {
420 public:
421 typedef InfoProxyType<Derived> Info;
422
423 /**
424 * @warning This makes the assumption that if you're gonna subnames a 2d
425 * vector, you're subnaming across all y
426 */
427 Derived &
428 ysubnames(const char **names)
429 {
430 Derived &self = this->self();
431 Info *info = this->info();
432
433 info->y_subnames.resize(self.y);
434 for (off_type i = 0; i < self.y; ++i)
435 info->y_subnames[i] = names[i];
436 return self;
437 }
438
439 Derived &
440 ysubname(off_type index, const std::string &subname)
441 {
442 Derived &self = this->self();
443 Info *info = this->info();
444
445 assert(index < self.y);
446 info->y_subnames.resize(self.y);
447 info->y_subnames[index] = subname.c_str();
448 return self;
449 }
450
451 std::string
452 ysubname(off_type i) const
453 {
454 return this->info()->y_subnames[i];
455 }
456
457 };
458
459 //////////////////////////////////////////////////////////////////////
460 //
461 // Simple Statistics
462 //
463 //////////////////////////////////////////////////////////////////////
464
465 /**
466 * Templatized storage and interface for a simple scalar stat.
467 */
468 class StatStor
469 {
470 private:
471 /** The statistic value. */
472 Counter data;
473
474 public:
475 struct Params : public StorageParams {};
476
477 public:
478 /**
479 * Builds this storage element and calls the base constructor of the
480 * datatype.
481 */
482 StatStor(Info *info)
483 : data(Counter())
484 { }
485
486 /**
487 * The the stat to the given value.
488 * @param val The new value.
489 */
490 void set(Counter val) { data = val; }
491 /**
492 * Increment the stat by the given value.
493 * @param val The new value.
494 */
495 void inc(Counter val) { data += val; }
496 /**
497 * Decrement the stat by the given value.
498 * @param val The new value.
499 */
500 void dec(Counter val) { data -= val; }
501 /**
502 * Return the value of this stat as its base type.
503 * @return The value of this stat.
504 */
505 Counter value() const { return data; }
506 /**
507 * Return the value of this stat as a result type.
508 * @return The value of this stat.
509 */
510 Result result() const { return (Result)data; }
511 /**
512 * Prepare stat data for dumping or serialization
513 */
514 void prepare(Info *info) { }
515 /**
516 * Reset stat value to default
517 */
518 void reset(Info *info) { data = Counter(); }
519
520 /**
521 * @return true if zero value
522 */
523 bool zero() const { return data == Counter(); }
524 };
525
526 /**
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.
532 */
533 class AvgStor
534 {
535 private:
536 /** The current count. */
537 Counter current;
538 /** The tick of the last reset */
539 Tick lastReset;
540 /** The total count for all tick. */
541 mutable Result total;
542 /** The tick that current last changed. */
543 mutable Tick last;
544
545 public:
546 struct Params : public StorageParams {};
547
548 public:
549 /**
550 * Build and initializes this stat storage.
551 */
552 AvgStor(Info *info)
553 : current(0), lastReset(0), total(0), last(0)
554 { }
555
556 /**
557 * Set the current count to the one provided, update the total and last
558 * set values.
559 * @param val The new count.
560 */
561 void
562 set(Counter val)
563 {
564 total += current * (curTick() - last);
565 last = curTick();
566 current = val;
567 }
568
569 /**
570 * Increment the current count by the provided value, calls set.
571 * @param val The amount to increment.
572 */
573 void inc(Counter val) { set(current + val); }
574
575 /**
576 * Deccrement the current count by the provided value, calls set.
577 * @param val The amount to decrement.
578 */
579 void dec(Counter val) { set(current - val); }
580
581 /**
582 * Return the current count.
583 * @return The current count.
584 */
585 Counter value() const { return current; }
586
587 /**
588 * Return the current average.
589 * @return The current average.
590 */
591 Result
592 result() const
593 {
594 assert(last == curTick());
595 return (Result)(total + current) / (Result)(curTick() - lastReset + 1);
596 }
597
598 /**
599 * @return true if zero value
600 */
601 bool zero() const { return total == 0.0; }
602
603 /**
604 * Prepare stat data for dumping or serialization
605 */
606 void
607 prepare(Info *info)
608 {
609 total += current * (curTick() - last);
610 last = curTick();
611 }
612
613 /**
614 * Reset stat value to default
615 */
616 void
617 reset(Info *info)
618 {
619 total = 0.0;
620 last = curTick();
621 lastReset = curTick();
622 }
623
624 };
625
626 /**
627 * Implementation of a scalar stat. The type of stat is determined by the
628 * Storage template.
629 */
630 template <class Derived, class Stor>
631 class ScalarBase : public DataWrap<Derived, ScalarInfoProxy>
632 {
633 public:
634 typedef Stor Storage;
635 typedef typename Stor::Params Params;
636
637 protected:
638 /** The storage of this stat. */
639 char storage[sizeof(Storage)] __attribute__ ((aligned (8)));
640
641 protected:
642 /**
643 * Retrieve the storage.
644 * @param index The vector index to access.
645 * @return The storage object at the given index.
646 */
647 Storage *
648 data()
649 {
650 return reinterpret_cast<Storage *>(storage);
651 }
652
653 /**
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.
658 */
659 const Storage *
660 data() const
661 {
662 return reinterpret_cast<const Storage *>(storage);
663 }
664
665 void
666 doInit()
667 {
668 new (storage) Storage(this->info());
669 this->setInit();
670 }
671
672 public:
673 /**
674 * Return the current value of this stat as its base type.
675 * @return The current value.
676 */
677 Counter value() const { return data()->value(); }
678
679 public:
680 ScalarBase()
681 {
682 this->doInit();
683 }
684
685 public:
686 // Common operators for stats
687 /**
688 * Increment the stat by 1. This calls the associated storage object inc
689 * function.
690 */
691 void operator++() { data()->inc(1); }
692 /**
693 * Decrement the stat by 1. This calls the associated storage object dec
694 * function.
695 */
696 void operator--() { data()->dec(1); }
697
698 /** Increment the stat by 1. */
699 void operator++(int) { ++*this; }
700 /** Decrement the stat by 1. */
701 void operator--(int) { --*this; }
702
703 /**
704 * Set the data value to the given value. This calls the associated storage
705 * object set function.
706 * @param v The new value.
707 */
708 template <typename U>
709 void operator=(const U &v) { data()->set(v); }
710
711 /**
712 * Increment the stat by the given value. This calls the associated
713 * storage object inc function.
714 * @param v The value to add.
715 */
716 template <typename U>
717 void operator+=(const U &v) { data()->inc(v); }
718
719 /**
720 * Decrement the stat by the given value. This calls the associated
721 * storage object dec function.
722 * @param v The value to substract.
723 */
724 template <typename U>
725 void operator-=(const U &v) { data()->dec(v); }
726
727 /**
728 * Return the number of elements, always 1 for a scalar.
729 * @return 1.
730 */
731 size_type size() const { return 1; }
732
733 Counter value() { return data()->value(); }
734
735 Result result() { return data()->result(); }
736
737 Result total() { return result(); }
738
739 bool zero() { return result() == 0.0; }
740
741 void reset() { data()->reset(this->info()); }
742 void prepare() { data()->prepare(this->info()); }
743 };
744
745 class ProxyInfo : public ScalarInfo
746 {
747 public:
748 std::string str() const { return std::to_string(value()); }
749 size_type size() const { return 1; }
750 bool check() const { return true; }
751 void prepare() { }
752 void reset() { }
753 bool zero() const { return value() == 0; }
754
755 void visit(Output &visitor) { visitor.visit(*this); }
756 };
757
758 template <class T>
759 class ValueProxy : public ProxyInfo
760 {
761 private:
762 T *scalar;
763
764 public:
765 ValueProxy(T &val) : scalar(&val) {}
766 Counter value() const { return *scalar; }
767 Result result() const { return *scalar; }
768 Result total() const { return *scalar; }
769 };
770
771 template <class T>
772 class FunctorProxy : public ProxyInfo
773 {
774 private:
775 T *functor;
776
777 public:
778 FunctorProxy(T &func) : functor(&func) {}
779 Counter value() const { return (*functor)(); }
780 Result result() const { return (*functor)(); }
781 Result total() const { return (*functor)(); }
782 };
783
784 /**
785 * A proxy similar to the FunctorProxy, but allows calling a method of a bound
786 * object, instead of a global free-standing function.
787 */
788 template <class T, class V>
789 class MethodProxy : public ProxyInfo
790 {
791 private:
792 T *object;
793 typedef V (T::*MethodPointer) () const;
794 MethodPointer method;
795
796 public:
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)(); }
801 };
802
803 template <class Derived>
804 class ValueBase : public DataWrap<Derived, ScalarInfoProxy>
805 {
806 private:
807 ProxyInfo *proxy;
808
809 public:
810 ValueBase() : proxy(NULL) { }
811 ~ValueBase() { if (proxy) delete proxy; }
812
813 template <class T>
814 Derived &
815 scalar(T &value)
816 {
817 proxy = new ValueProxy<T>(value);
818 this->setInit();
819 return this->self();
820 }
821
822 template <class T>
823 Derived &
824 functor(T &func)
825 {
826 proxy = new FunctorProxy<T>(func);
827 this->setInit();
828 return this->self();
829 }
830
831 /**
832 * Extended functor that calls the specified method of the provided object.
833 *
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.
837 */
838 template <class T, class V>
839 Derived &
840 method(T *obj, V (T::*method)() const)
841 {
842 proxy = new MethodProxy<T,V>(obj, method);
843 this->setInit();
844 return this->self();
845 }
846
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(); }
851
852 std::string str() const { return proxy->str(); }
853 bool zero() const { return proxy->zero(); }
854 bool check() const { return proxy != NULL; }
855 void prepare() { }
856 void reset() { }
857 };
858
859 //////////////////////////////////////////////////////////////////////
860 //
861 // Vector Statistics
862 //
863 //////////////////////////////////////////////////////////////////////
864
865 /**
866 * A proxy class to access the stat at a given index in a VectorBase stat.
867 * Behaves like a ScalarBase.
868 */
869 template <class Stat>
870 class ScalarProxy
871 {
872 private:
873 /** Pointer to the parent Vector. */
874 Stat &stat;
875
876 /** The index to access in the parent VectorBase. */
877 off_type index;
878
879 public:
880 /**
881 * Return the current value of this stat as its base type.
882 * @return The current value.
883 */
884 Counter value() const { return stat.data(index)->value(); }
885
886 /**
887 * Return the current value of this statas a result type.
888 * @return The current value.
889 */
890 Result result() const { return stat.data(index)->result(); }
891
892 public:
893 /**
894 * Create and initialize this proxy, do not register it with the database.
895 * @param i The index to access.
896 */
897 ScalarProxy(Stat &s, off_type i)
898 : stat(s), index(i)
899 {
900 }
901
902 /**
903 * Create a copy of the provided ScalarProxy.
904 * @param sp The proxy to copy.
905 */
906 ScalarProxy(const ScalarProxy &sp)
907 : stat(sp.stat), index(sp.index)
908 {}
909
910 /**
911 * Set this proxy equal to the provided one.
912 * @param sp The proxy to copy.
913 * @return A reference to this proxy.
914 */
915 const ScalarProxy &
916 operator=(const ScalarProxy &sp)
917 {
918 stat = sp.stat;
919 index = sp.index;
920 return *this;
921 }
922
923 public:
924 // Common operators for stats
925 /**
926 * Increment the stat by 1. This calls the associated storage object inc
927 * function.
928 */
929 void operator++() { stat.data(index)->inc(1); }
930 /**
931 * Decrement the stat by 1. This calls the associated storage object dec
932 * function.
933 */
934 void operator--() { stat.data(index)->dec(1); }
935
936 /** Increment the stat by 1. */
937 void operator++(int) { ++*this; }
938 /** Decrement the stat by 1. */
939 void operator--(int) { --*this; }
940
941 /**
942 * Set the data value to the given value. This calls the associated storage
943 * object set function.
944 * @param v The new value.
945 */
946 template <typename U>
947 void
948 operator=(const U &v)
949 {
950 stat.data(index)->set(v);
951 }
952
953 /**
954 * Increment the stat by the given value. This calls the associated
955 * storage object inc function.
956 * @param v The value to add.
957 */
958 template <typename U>
959 void
960 operator+=(const U &v)
961 {
962 stat.data(index)->inc(v);
963 }
964
965 /**
966 * Decrement the stat by the given value. This calls the associated
967 * storage object dec function.
968 * @param v The value to substract.
969 */
970 template <typename U>
971 void
972 operator-=(const U &v)
973 {
974 stat.data(index)->dec(v);
975 }
976
977 /**
978 * Return the number of elements, always 1 for a scalar.
979 * @return 1.
980 */
981 size_type size() const { return 1; }
982
983 public:
984 std::string
985 str() const
986 {
987 return csprintf("%s[%d]", stat.info()->name, index);
988 }
989 };
990
991 /**
992 * Implementation of a vector of stats. The type of stat is determined by the
993 * Storage class. @sa ScalarBase
994 */
995 template <class Derived, class Stor>
996 class VectorBase : public DataWrapVec<Derived, VectorInfoProxy>
997 {
998 public:
999 typedef Stor Storage;
1000 typedef typename Stor::Params Params;
1001
1002 /** Proxy type */
1003 typedef ScalarProxy<Derived> Proxy;
1004 friend class ScalarProxy<Derived>;
1005 friend class DataWrapVec<Derived, VectorInfoProxy>;
1006
1007 protected:
1008 /** The storage of this stat. */
1009 Storage *storage;
1010 size_type _size;
1011
1012 protected:
1013 /**
1014 * Retrieve the storage.
1015 * @param index The vector index to access.
1016 * @return The storage object at the given index.
1017 */
1018 Storage *data(off_type index) { return &storage[index]; }
1019
1020 /**
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.
1024 */
1025 const Storage *data(off_type index) const { return &storage[index]; }
1026
1027 void
1028 doInit(size_type s)
1029 {
1030 assert(s > 0 && "size must be positive!");
1031 assert(!storage && "already initialized");
1032 _size = s;
1033
1034 char *ptr = new char[_size * sizeof(Storage)];
1035 storage = reinterpret_cast<Storage *>(ptr);
1036
1037 for (off_type i = 0; i < _size; ++i)
1038 new (&storage[i]) Storage(this->info());
1039
1040 this->setInit();
1041 }
1042
1043 public:
1044 void
1045 value(VCounter &vec) const
1046 {
1047 vec.resize(size());
1048 for (off_type i = 0; i < size(); ++i)
1049 vec[i] = data(i)->value();
1050 }
1051
1052 /**
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.
1055 */
1056 void
1057 result(VResult &vec) const
1058 {
1059 vec.resize(size());
1060 for (off_type i = 0; i < size(); ++i)
1061 vec[i] = data(i)->result();
1062 }
1063
1064 /**
1065 * Return a total of all entries in this vector.
1066 * @return The total of all vector entries.
1067 */
1068 Result
1069 total() const
1070 {
1071 Result total = 0.0;
1072 for (off_type i = 0; i < size(); ++i)
1073 total += data(i)->result();
1074 return total;
1075 }
1076
1077 /**
1078 * @return the number of elements in this vector.
1079 */
1080 size_type size() const { return _size; }
1081
1082 bool
1083 zero() const
1084 {
1085 for (off_type i = 0; i < size(); ++i)
1086 if (data(i)->zero())
1087 return false;
1088 return true;
1089 }
1090
1091 bool
1092 check() const
1093 {
1094 return storage != NULL;
1095 }
1096
1097 public:
1098 VectorBase()
1099 : storage(nullptr), _size(0)
1100 {}
1101
1102 ~VectorBase()
1103 {
1104 if (!storage)
1105 return;
1106
1107 for (off_type i = 0; i < _size; ++i)
1108 data(i)->~Storage();
1109 delete [] reinterpret_cast<char *>(storage);
1110 }
1111
1112 /**
1113 * Set this vector to have the given size.
1114 * @param size The new size.
1115 * @return A reference to this stat.
1116 */
1117 Derived &
1118 init(size_type size)
1119 {
1120 Derived &self = this->self();
1121 self.doInit(size);
1122 return self;
1123 }
1124
1125 /**
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.
1129 */
1130 Proxy
1131 operator[](off_type index)
1132 {
1133 assert (index >= 0 && index < size());
1134 return Proxy(this->self(), index);
1135 }
1136 };
1137
1138 template <class Stat>
1139 class VectorProxy
1140 {
1141 private:
1142 Stat &stat;
1143 off_type offset;
1144 size_type len;
1145
1146 private:
1147 mutable VResult vec;
1148
1149 typename Stat::Storage *
1150 data(off_type index)
1151 {
1152 assert(index < len);
1153 return stat.data(offset + index);
1154 }
1155
1156 const typename Stat::Storage *
1157 data(off_type index) const
1158 {
1159 assert(index < len);
1160 return stat.data(offset + index);
1161 }
1162
1163 public:
1164 const VResult &
1165 result() const
1166 {
1167 vec.resize(size());
1168
1169 for (off_type i = 0; i < size(); ++i)
1170 vec[i] = data(i)->result();
1171
1172 return vec;
1173 }
1174
1175 Result
1176 total() const
1177 {
1178 Result total = 0.0;
1179 for (off_type i = 0; i < size(); ++i)
1180 total += data(i)->result();
1181 return total;
1182 }
1183
1184 public:
1185 VectorProxy(Stat &s, off_type o, size_type l)
1186 : stat(s), offset(o), len(l)
1187 {
1188 }
1189
1190 VectorProxy(const VectorProxy &sp)
1191 : stat(sp.stat), offset(sp.offset), len(sp.len)
1192 {
1193 }
1194
1195 const VectorProxy &
1196 operator=(const VectorProxy &sp)
1197 {
1198 stat = sp.stat;
1199 offset = sp.offset;
1200 len = sp.len;
1201 return *this;
1202 }
1203
1204 ScalarProxy<Stat>
1205 operator[](off_type index)
1206 {
1207 assert (index >= 0 && index < size());
1208 return ScalarProxy<Stat>(stat, offset + index);
1209 }
1210
1211 size_type size() const { return len; }
1212 };
1213
1214 template <class Derived, class Stor>
1215 class Vector2dBase : public DataWrapVec2d<Derived, Vector2dInfoProxy>
1216 {
1217 public:
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>;
1226
1227 protected:
1228 size_type x;
1229 size_type y;
1230 size_type _size;
1231 Storage *storage;
1232
1233 protected:
1234 Storage *data(off_type index) { return &storage[index]; }
1235 const Storage *data(off_type index) const { return &storage[index]; }
1236
1237 public:
1238 Vector2dBase()
1239 : x(0), y(0), _size(0), storage(nullptr)
1240 {}
1241
1242 ~Vector2dBase()
1243 {
1244 if (!storage)
1245 return;
1246
1247 for (off_type i = 0; i < _size; ++i)
1248 data(i)->~Storage();
1249 delete [] reinterpret_cast<char *>(storage);
1250 }
1251
1252 Derived &
1253 init(size_type _x, size_type _y)
1254 {
1255 assert(_x > 0 && _y > 0 && "sizes must be positive!");
1256 assert(!storage && "already initialized");
1257
1258 Derived &self = this->self();
1259 Info *info = this->info();
1260
1261 x = _x;
1262 y = _y;
1263 info->x = _x;
1264 info->y = _y;
1265 _size = x * y;
1266
1267 char *ptr = new char[_size * sizeof(Storage)];
1268 storage = reinterpret_cast<Storage *>(ptr);
1269
1270 for (off_type i = 0; i < _size; ++i)
1271 new (&storage[i]) Storage(info);
1272
1273 this->setInit();
1274
1275 return self;
1276 }
1277
1278 Proxy
1279 operator[](off_type index)
1280 {
1281 off_type offset = index * y;
1282 assert (index >= 0 && offset + y <= size());
1283 return Proxy(this->self(), offset, y);
1284 }
1285
1286
1287 size_type
1288 size() const
1289 {
1290 return _size;
1291 }
1292
1293 bool
1294 zero() const
1295 {
1296 return data(0)->zero();
1297 #if 0
1298 for (off_type i = 0; i < size(); ++i)
1299 if (!data(i)->zero())
1300 return false;
1301 return true;
1302 #endif
1303 }
1304
1305 /**
1306 * Return a total of all entries in this vector.
1307 * @return The total of all vector entries.
1308 */
1309 Result
1310 total() const
1311 {
1312 Result total = 0.0;
1313 for (off_type i = 0; i < size(); ++i)
1314 total += data(i)->result();
1315 return total;
1316 }
1317
1318 void
1319 prepare()
1320 {
1321 Info *info = this->info();
1322 size_type size = this->size();
1323
1324 for (off_type i = 0; i < size; ++i)
1325 data(i)->prepare(info);
1326
1327 info->cvec.resize(size);
1328 for (off_type i = 0; i < size; ++i)
1329 info->cvec[i] = data(i)->value();
1330 }
1331
1332 /**
1333 * Reset stat value to default
1334 */
1335 void
1336 reset()
1337 {
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);
1342 }
1343
1344 bool
1345 check() const
1346 {
1347 return storage != NULL;
1348 }
1349 };
1350
1351 //////////////////////////////////////////////////////////////////////
1352 //
1353 // Non formula statistics
1354 //
1355 //////////////////////////////////////////////////////////////////////
1356 /** The parameters for a distribution stat. */
1357 struct DistParams : public StorageParams
1358 {
1359 const DistType type;
1360 DistParams(DistType t) : type(t) {}
1361 };
1362
1363 /**
1364 * Templatized storage and interface for a distribution stat.
1365 */
1366 class DistStor
1367 {
1368 public:
1369 /** The parameters for a distribution stat. */
1370 struct Params : public DistParams
1371 {
1372 /** The minimum value to track. */
1373 Counter min;
1374 /** The maximum value to track. */
1375 Counter max;
1376 /** The number of entries in each bucket. */
1377 Counter bucket_size;
1378 /** The number of buckets. Equal to (max-min)/bucket_size. */
1379 size_type buckets;
1380
1381 Params() : DistParams(Dist), min(0), max(0), bucket_size(0),
1382 buckets(0) {}
1383 };
1384
1385 private:
1386 /** The minimum value to track. */
1387 Counter min_track;
1388 /** The maximum value to track. */
1389 Counter max_track;
1390 /** The number of entries in each bucket. */
1391 Counter bucket_size;
1392
1393 /** The smallest value sampled. */
1394 Counter min_val;
1395 /** The largest value sampled. */
1396 Counter max_val;
1397 /** The number of values sampled less than min. */
1398 Counter underflow;
1399 /** The number of values sampled more than max. */
1400 Counter overflow;
1401 /** The current sum. */
1402 Counter sum;
1403 /** The sum of squares. */
1404 Counter squares;
1405 /** The number of samples. */
1406 Counter samples;
1407 /** Counter for each bucket. */
1408 VCounter cvec;
1409
1410 public:
1411 DistStor(Info *info)
1412 : cvec(safe_cast<const Params *>(info->storageParams)->buckets)
1413 {
1414 reset(info);
1415 }
1416
1417 /**
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.
1421 */
1422 void
1423 sample(Counter val, int number)
1424 {
1425 if (val < min_track)
1426 underflow += number;
1427 else if (val > max_track)
1428 overflow += number;
1429 else {
1430 size_type index =
1431 (size_type)std::floor((val - min_track) / bucket_size);
1432 assert(index < size());
1433 cvec[index] += number;
1434 }
1435
1436 if (val < min_val)
1437 min_val = val;
1438
1439 if (val > max_val)
1440 max_val = val;
1441
1442 sum += val * number;
1443 squares += val * val * number;
1444 samples += number;
1445 }
1446
1447 /**
1448 * Return the number of buckets in this distribution.
1449 * @return the number of buckets.
1450 */
1451 size_type size() const { return cvec.size(); }
1452
1453 /**
1454 * Returns true if any calls to sample have been made.
1455 * @return True if any values have been sampled.
1456 */
1457 bool
1458 zero() const
1459 {
1460 return samples == Counter();
1461 }
1462
1463 void
1464 prepare(Info *info, DistData &data)
1465 {
1466 const Params *params = safe_cast<const Params *>(info->storageParams);
1467
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;
1473
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;
1478
1479 data.cvec.resize(params->buckets);
1480 for (off_type i = 0; i < params->buckets; ++i)
1481 data.cvec[i] = cvec[i];
1482
1483 data.sum = sum;
1484 data.squares = squares;
1485 data.samples = samples;
1486 }
1487
1488 /**
1489 * Reset stat value to default
1490 */
1491 void
1492 reset(Info *info)
1493 {
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;
1498
1499 min_val = CounterLimits::max();
1500 max_val = CounterLimits::min();
1501 underflow = Counter();
1502 overflow = Counter();
1503
1504 size_type size = cvec.size();
1505 for (off_type i = 0; i < size; ++i)
1506 cvec[i] = Counter();
1507
1508 sum = Counter();
1509 squares = Counter();
1510 samples = Counter();
1511 }
1512 };
1513
1514 /**
1515 * Templatized storage and interface for a histogram stat.
1516 */
1517 class HistStor
1518 {
1519 public:
1520 /** The parameters for a distribution stat. */
1521 struct Params : public DistParams
1522 {
1523 /** The number of buckets.. */
1524 size_type buckets;
1525
1526 Params() : DistParams(Hist), buckets(0) {}
1527 };
1528
1529 private:
1530 /** The minimum value to track. */
1531 Counter min_bucket;
1532 /** The maximum value to track. */
1533 Counter max_bucket;
1534 /** The number of entries in each bucket. */
1535 Counter bucket_size;
1536
1537 /** The current sum. */
1538 Counter sum;
1539 /** The sum of logarithm of each sample, used to compute geometric mean. */
1540 Counter logs;
1541 /** The sum of squares. */
1542 Counter squares;
1543 /** The number of samples. */
1544 Counter samples;
1545 /** Counter for each bucket. */
1546 VCounter cvec;
1547
1548 public:
1549 HistStor(Info *info)
1550 : cvec(safe_cast<const Params *>(info->storageParams)->buckets)
1551 {
1552 reset(info);
1553 }
1554
1555 void grow_up();
1556 void grow_out();
1557 void grow_convert();
1558 void add(HistStor *);
1559
1560 /**
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.
1564 */
1565 void
1566 sample(Counter val, int number)
1567 {
1568 assert(min_bucket < max_bucket);
1569 if (val < min_bucket) {
1570 if (min_bucket == 0)
1571 grow_convert();
1572
1573 while (val < min_bucket)
1574 grow_out();
1575 } else if (val >= max_bucket + bucket_size) {
1576 if (min_bucket == 0) {
1577 while (val >= max_bucket + bucket_size)
1578 grow_up();
1579 } else {
1580 while (val >= max_bucket + bucket_size)
1581 grow_out();
1582 }
1583 }
1584
1585 size_type index =
1586 (int64_t)std::floor((val - min_bucket) / bucket_size);
1587
1588 assert(index < size());
1589 cvec[index] += number;
1590
1591 sum += val * number;
1592 squares += val * val * number;
1593 logs += log(val) * number;
1594 samples += number;
1595 }
1596
1597 /**
1598 * Return the number of buckets in this distribution.
1599 * @return the number of buckets.
1600 */
1601 size_type size() const { return cvec.size(); }
1602
1603 /**
1604 * Returns true if any calls to sample have been made.
1605 * @return True if any values have been sampled.
1606 */
1607 bool
1608 zero() const
1609 {
1610 return samples == Counter();
1611 }
1612
1613 void
1614 prepare(Info *info, DistData &data)
1615 {
1616 const Params *params = safe_cast<const Params *>(info->storageParams);
1617
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;
1623
1624 data.min_val = min_bucket;
1625 data.max_val = max_bucket;
1626
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];
1631
1632 data.sum = sum;
1633 data.logs = logs;
1634 data.squares = squares;
1635 data.samples = samples;
1636 }
1637
1638 /**
1639 * Reset stat value to default
1640 */
1641 void
1642 reset(Info *info)
1643 {
1644 const Params *params = safe_cast<const Params *>(info->storageParams);
1645 min_bucket = 0;
1646 max_bucket = params->buckets - 1;
1647 bucket_size = 1;
1648
1649 size_type size = cvec.size();
1650 for (off_type i = 0; i < size; ++i)
1651 cvec[i] = Counter();
1652
1653 sum = Counter();
1654 squares = Counter();
1655 samples = Counter();
1656 logs = Counter();
1657 }
1658 };
1659
1660 /**
1661 * Templatized storage and interface for a distribution that calculates mean
1662 * and variance.
1663 */
1664 class SampleStor
1665 {
1666 public:
1667 struct Params : public DistParams
1668 {
1669 Params() : DistParams(Deviation) {}
1670 };
1671
1672 private:
1673 /** The current sum. */
1674 Counter sum;
1675 /** The sum of squares. */
1676 Counter squares;
1677 /** The number of samples. */
1678 Counter samples;
1679
1680 public:
1681 /**
1682 * Create and initialize this storage.
1683 */
1684 SampleStor(Info *info)
1685 : sum(Counter()), squares(Counter()), samples(Counter())
1686 { }
1687
1688 /**
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.
1694 */
1695 void
1696 sample(Counter val, int number)
1697 {
1698 Counter value = val * number;
1699 sum += value;
1700 squares += value * value;
1701 samples += number;
1702 }
1703
1704 /**
1705 * Return the number of entries in this stat, 1
1706 * @return 1.
1707 */
1708 size_type size() const { return 1; }
1709
1710 /**
1711 * Return true if no samples have been added.
1712 * @return True if no samples have been added.
1713 */
1714 bool zero() const { return samples == Counter(); }
1715
1716 void
1717 prepare(Info *info, DistData &data)
1718 {
1719 const Params *params = safe_cast<const Params *>(info->storageParams);
1720
1721 assert(params->type == Deviation);
1722 data.type = params->type;
1723 data.sum = sum;
1724 data.squares = squares;
1725 data.samples = samples;
1726 }
1727
1728 /**
1729 * Reset stat value to default
1730 */
1731 void
1732 reset(Info *info)
1733 {
1734 sum = Counter();
1735 squares = Counter();
1736 samples = Counter();
1737 }
1738 };
1739
1740 /**
1741 * Templatized storage for distribution that calculates per tick mean and
1742 * variance.
1743 */
1744 class AvgSampleStor
1745 {
1746 public:
1747 struct Params : public DistParams
1748 {
1749 Params() : DistParams(Deviation) {}
1750 };
1751
1752 private:
1753 /** Current total. */
1754 Counter sum;
1755 /** Current sum of squares. */
1756 Counter squares;
1757
1758 public:
1759 /**
1760 * Create and initialize this storage.
1761 */
1762 AvgSampleStor(Info *info)
1763 : sum(Counter()), squares(Counter())
1764 {}
1765
1766 /**
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.
1771 */
1772 void
1773 sample(Counter val, int number)
1774 {
1775 Counter value = val * number;
1776 sum += value;
1777 squares += value * value;
1778 }
1779
1780 /**
1781 * Return the number of entries, in this case 1.
1782 * @return 1.
1783 */
1784 size_type size() const { return 1; }
1785
1786 /**
1787 * Return true if no samples have been added.
1788 * @return True if the sum is zero.
1789 */
1790 bool zero() const { return sum == Counter(); }
1791
1792 void
1793 prepare(Info *info, DistData &data)
1794 {
1795 const Params *params = safe_cast<const Params *>(info->storageParams);
1796
1797 assert(params->type == Deviation);
1798 data.type = params->type;
1799 data.sum = sum;
1800 data.squares = squares;
1801 data.samples = curTick();
1802 }
1803
1804 /**
1805 * Reset stat value to default
1806 */
1807 void
1808 reset(Info *info)
1809 {
1810 sum = Counter();
1811 squares = Counter();
1812 }
1813 };
1814
1815 /**
1816 * Implementation of a distribution stat. The type of distribution is
1817 * determined by the Storage template. @sa ScalarBase
1818 */
1819 template <class Derived, class Stor>
1820 class DistBase : public DataWrap<Derived, DistInfoProxy>
1821 {
1822 public:
1823 typedef DistInfoProxy<Derived> Info;
1824 typedef Stor Storage;
1825 typedef typename Stor::Params Params;
1826
1827 protected:
1828 /** The storage for this stat. */
1829 char storage[sizeof(Storage)] __attribute__ ((aligned (8)));
1830
1831 protected:
1832 /**
1833 * Retrieve the storage.
1834 * @return The storage object for this stat.
1835 */
1836 Storage *
1837 data()
1838 {
1839 return reinterpret_cast<Storage *>(storage);
1840 }
1841
1842 /**
1843 * Retrieve a const pointer to the storage.
1844 * @return A const pointer to the storage object for this stat.
1845 */
1846 const Storage *
1847 data() const
1848 {
1849 return reinterpret_cast<const Storage *>(storage);
1850 }
1851
1852 void
1853 doInit()
1854 {
1855 new (storage) Storage(this->info());
1856 this->setInit();
1857 }
1858
1859 public:
1860 DistBase() { }
1861
1862 /**
1863 * Add a value to the distribtion n times. Calls sample on the storage
1864 * class.
1865 * @param v The value to add.
1866 * @param n The number of times to add it, defaults to 1.
1867 */
1868 template <typename U>
1869 void sample(const U &v, int n = 1) { data()->sample(v, n); }
1870
1871 /**
1872 * Return the number of entries in this stat.
1873 * @return The number of entries.
1874 */
1875 size_type size() const { return data()->size(); }
1876 /**
1877 * Return true if no samples have been added.
1878 * @return True if there haven't been any samples.
1879 */
1880 bool zero() const { return data()->zero(); }
1881
1882 void
1883 prepare()
1884 {
1885 Info *info = this->info();
1886 data()->prepare(info, info->data);
1887 }
1888
1889 /**
1890 * Reset stat value to default
1891 */
1892 void
1893 reset()
1894 {
1895 data()->reset(this->info());
1896 }
1897
1898 /**
1899 * Add the argument distribution to the this distribution.
1900 */
1901 void add(DistBase &d) { data()->add(d.data()); }
1902
1903 };
1904
1905 template <class Stat>
1906 class DistProxy;
1907
1908 template <class Derived, class Stor>
1909 class VectorDistBase : public DataWrapVec<Derived, VectorDistInfoProxy>
1910 {
1911 public:
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>;
1918
1919 protected:
1920 Storage *storage;
1921 size_type _size;
1922
1923 protected:
1924 Storage *
1925 data(off_type index)
1926 {
1927 return &storage[index];
1928 }
1929
1930 const Storage *
1931 data(off_type index) const
1932 {
1933 return &storage[index];
1934 }
1935
1936 void
1937 doInit(size_type s)
1938 {
1939 assert(s > 0 && "size must be positive!");
1940 assert(!storage && "already initialized");
1941 _size = s;
1942
1943 char *ptr = new char[_size * sizeof(Storage)];
1944 storage = reinterpret_cast<Storage *>(ptr);
1945
1946 Info *info = this->info();
1947 for (off_type i = 0; i < _size; ++i)
1948 new (&storage[i]) Storage(info);
1949
1950 this->setInit();
1951 }
1952
1953 public:
1954 VectorDistBase()
1955 : storage(NULL)
1956 {}
1957
1958 ~VectorDistBase()
1959 {
1960 if (!storage)
1961 return ;
1962
1963 for (off_type i = 0; i < _size; ++i)
1964 data(i)->~Storage();
1965 delete [] reinterpret_cast<char *>(storage);
1966 }
1967
1968 Proxy operator[](off_type index)
1969 {
1970 assert(index >= 0 && index < size());
1971 return Proxy(this->self(), index);
1972 }
1973
1974 size_type
1975 size() const
1976 {
1977 return _size;
1978 }
1979
1980 bool
1981 zero() const
1982 {
1983 for (off_type i = 0; i < size(); ++i)
1984 if (!data(i)->zero())
1985 return false;
1986 return true;
1987 }
1988
1989 void
1990 prepare()
1991 {
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]);
1997 }
1998
1999 bool
2000 check() const
2001 {
2002 return storage != NULL;
2003 }
2004 };
2005
2006 template <class Stat>
2007 class DistProxy
2008 {
2009 private:
2010 Stat &stat;
2011 off_type index;
2012
2013 protected:
2014 typename Stat::Storage *data() { return stat.data(index); }
2015 const typename Stat::Storage *data() const { return stat.data(index); }
2016
2017 public:
2018 DistProxy(Stat &s, off_type i)
2019 : stat(s), index(i)
2020 {}
2021
2022 DistProxy(const DistProxy &sp)
2023 : stat(sp.stat), index(sp.index)
2024 {}
2025
2026 const DistProxy &
2027 operator=(const DistProxy &sp)
2028 {
2029 stat = sp.stat;
2030 index = sp.index;
2031 return *this;
2032 }
2033
2034 public:
2035 template <typename U>
2036 void
2037 sample(const U &v, int n = 1)
2038 {
2039 data()->sample(v, n);
2040 }
2041
2042 size_type
2043 size() const
2044 {
2045 return 1;
2046 }
2047
2048 bool
2049 zero() const
2050 {
2051 return data()->zero();
2052 }
2053
2054 /**
2055 * Proxy has no state. Nothing to reset.
2056 */
2057 void reset() { }
2058 };
2059
2060 //////////////////////////////////////////////////////////////////////
2061 //
2062 // Formula Details
2063 //
2064 //////////////////////////////////////////////////////////////////////
2065
2066 /**
2067 * Base class for formula statistic node. These nodes are used to build a tree
2068 * that represents the formula.
2069 */
2070 class Node
2071 {
2072 public:
2073 /**
2074 * Return the number of nodes in the subtree starting at this node.
2075 * @return the number of nodes in this subtree.
2076 */
2077 virtual size_type size() const = 0;
2078 /**
2079 * Return the result vector of this subtree.
2080 * @return The result vector of this subtree.
2081 */
2082 virtual const VResult &result() const = 0;
2083 /**
2084 * Return the total of the result vector.
2085 * @return The total of the result vector.
2086 */
2087 virtual Result total() const = 0;
2088
2089 /**
2090 *
2091 */
2092 virtual std::string str() const = 0;
2093
2094 virtual ~Node() {};
2095 };
2096
2097 /** Shared pointer to a function Node. */
2098 typedef std::shared_ptr<Node> NodePtr;
2099
2100 class ScalarStatNode : public Node
2101 {
2102 private:
2103 const ScalarInfo *data;
2104 mutable VResult vresult;
2105
2106 public:
2107 ScalarStatNode(const ScalarInfo *d) : data(d), vresult(1) {}
2108
2109 const VResult &
2110 result() const
2111 {
2112 vresult[0] = data->result();
2113 return vresult;
2114 }
2115
2116 Result total() const { return data->result(); };
2117
2118 size_type size() const { return 1; }
2119
2120 /**
2121 *
2122 */
2123 std::string str() const { return data->name; }
2124 };
2125
2126 template <class Stat>
2127 class ScalarProxyNode : public Node
2128 {
2129 private:
2130 const ScalarProxy<Stat> proxy;
2131 mutable VResult vresult;
2132
2133 public:
2134 ScalarProxyNode(const ScalarProxy<Stat> &p)
2135 : proxy(p), vresult(1)
2136 { }
2137
2138 const VResult &
2139 result() const
2140 {
2141 vresult[0] = proxy.result();
2142 return vresult;
2143 }
2144
2145 Result
2146 total() const
2147 {
2148 return proxy.result();
2149 }
2150
2151 size_type
2152 size() const
2153 {
2154 return 1;
2155 }
2156
2157 /**
2158 *
2159 */
2160 std::string
2161 str() const
2162 {
2163 return proxy.str();
2164 }
2165 };
2166
2167 class VectorStatNode : public Node
2168 {
2169 private:
2170 const VectorInfo *data;
2171
2172 public:
2173 VectorStatNode(const VectorInfo *d) : data(d) { }
2174 const VResult &result() const { return data->result(); }
2175 Result total() const { return data->total(); };
2176
2177 size_type size() const { return data->size(); }
2178
2179 std::string str() const { return data->name; }
2180 };
2181
2182 template <class T>
2183 class ConstNode : public Node
2184 {
2185 private:
2186 VResult vresult;
2187
2188 public:
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]); }
2194 };
2195
2196 template <class T>
2197 class ConstVectorNode : public Node
2198 {
2199 private:
2200 VResult vresult;
2201
2202 public:
2203 ConstVectorNode(const T &s) : vresult(s.begin(), s.end()) {}
2204 const VResult &result() const { return vresult; }
2205
2206 Result
2207 total() const
2208 {
2209 size_type size = this->size();
2210 Result tmp = 0;
2211 for (off_type i = 0; i < size; i++)
2212 tmp += vresult[i];
2213 return tmp;
2214 }
2215
2216 size_type size() const { return vresult.size(); }
2217 std::string
2218 str() const
2219 {
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]));
2224 tmp += ")";
2225 return tmp;
2226 }
2227 };
2228
2229 template <class Op>
2230 struct OpString;
2231
2232 template<>
2233 struct OpString<std::plus<Result> >
2234 {
2235 static std::string str() { return "+"; }
2236 };
2237
2238 template<>
2239 struct OpString<std::minus<Result> >
2240 {
2241 static std::string str() { return "-"; }
2242 };
2243
2244 template<>
2245 struct OpString<std::multiplies<Result> >
2246 {
2247 static std::string str() { return "*"; }
2248 };
2249
2250 template<>
2251 struct OpString<std::divides<Result> >
2252 {
2253 static std::string str() { return "/"; }
2254 };
2255
2256 template<>
2257 struct OpString<std::modulus<Result> >
2258 {
2259 static std::string str() { return "%"; }
2260 };
2261
2262 template<>
2263 struct OpString<std::negate<Result> >
2264 {
2265 static std::string str() { return "-"; }
2266 };
2267
2268 template <class Op>
2269 class UnaryNode : public Node
2270 {
2271 public:
2272 NodePtr l;
2273 mutable VResult vresult;
2274
2275 public:
2276 UnaryNode(NodePtr &p) : l(p) {}
2277
2278 const VResult &
2279 result() const
2280 {
2281 const VResult &lvec = l->result();
2282 size_type size = lvec.size();
2283
2284 assert(size > 0);
2285
2286 vresult.resize(size);
2287 Op op;
2288 for (off_type i = 0; i < size; ++i)
2289 vresult[i] = op(lvec[i]);
2290
2291 return vresult;
2292 }
2293
2294 Result
2295 total() const
2296 {
2297 const VResult &vec = this->result();
2298 Result total = 0.0;
2299 for (off_type i = 0; i < size(); i++)
2300 total += vec[i];
2301 return total;
2302 }
2303
2304 size_type size() const { return l->size(); }
2305
2306 std::string
2307 str() const
2308 {
2309 return OpString<Op>::str() + l->str();
2310 }
2311 };
2312
2313 template <class Op>
2314 class BinaryNode : public Node
2315 {
2316 public:
2317 NodePtr l;
2318 NodePtr r;
2319 mutable VResult vresult;
2320
2321 public:
2322 BinaryNode(NodePtr &a, NodePtr &b) : l(a), r(b) {}
2323
2324 const VResult &
2325 result() const override
2326 {
2327 Op op;
2328 const VResult &lvec = l->result();
2329 const VResult &rvec = r->result();
2330
2331 assert(lvec.size() > 0 && rvec.size() > 0);
2332
2333 if (lvec.size() == 1 && rvec.size() == 1) {
2334 vresult.resize(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]);
2351 }
2352
2353 return vresult;
2354 }
2355
2356 Result
2357 total() const override
2358 {
2359 const VResult &vec = this->result();
2360 const VResult &lvec = l->result();
2361 const VResult &rvec = r->result();
2362 Result total = 0.0;
2363 Result lsum = 0.0;
2364 Result rsum = 0.0;
2365 Op op;
2366
2367 assert(lvec.size() > 0 && rvec.size() > 0);
2368 assert(lvec.size() == rvec.size() ||
2369 lvec.size() == 1 || rvec.size() == 1);
2370
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) {
2374 lsum += lvec[i];
2375 rsum += rvec[i];
2376 }
2377 return op(lsum, rsum);
2378 }
2379
2380 /** Otherwise divide each item by the divisor */
2381 for (off_type i = 0; i < size(); ++i) {
2382 total += vec[i];
2383 }
2384
2385 return total;
2386 }
2387
2388 size_type
2389 size() const override
2390 {
2391 size_type ls = l->size();
2392 size_type rs = r->size();
2393 if (ls == 1) {
2394 return rs;
2395 } else if (rs == 1) {
2396 return ls;
2397 } else {
2398 assert(ls == rs && "Node vector sizes are not equal");
2399 return ls;
2400 }
2401 }
2402
2403 std::string
2404 str() const override
2405 {
2406 return csprintf("(%s %s %s)", l->str(), OpString<Op>::str(), r->str());
2407 }
2408 };
2409
2410 template <class Op>
2411 class SumNode : public Node
2412 {
2413 public:
2414 NodePtr l;
2415 mutable VResult vresult;
2416
2417 public:
2418 SumNode(NodePtr &p) : l(p), vresult(1) {}
2419
2420 const VResult &
2421 result() const
2422 {
2423 const VResult &lvec = l->result();
2424 size_type size = lvec.size();
2425 assert(size > 0);
2426
2427 vresult[0] = 0.0;
2428
2429 Op op;
2430 for (off_type i = 0; i < size; ++i)
2431 vresult[0] = op(vresult[0], lvec[i]);
2432
2433 return vresult;
2434 }
2435
2436 Result
2437 total() const
2438 {
2439 const VResult &lvec = l->result();
2440 size_type size = lvec.size();
2441 assert(size > 0);
2442
2443 Result result = 0.0;
2444
2445 Op op;
2446 for (off_type i = 0; i < size; ++i)
2447 result = op(result, lvec[i]);
2448
2449 return result;
2450 }
2451
2452 size_type size() const { return 1; }
2453
2454 std::string
2455 str() const
2456 {
2457 return csprintf("total(%s)", l->str());
2458 }
2459 };
2460
2461
2462 //////////////////////////////////////////////////////////////////////
2463 //
2464 // Visible Statistics Types
2465 //
2466 //////////////////////////////////////////////////////////////////////
2467 /**
2468 * @defgroup VisibleStats "Statistic Types"
2469 * These are the statistics that are used in the simulator.
2470 * @{
2471 */
2472
2473 /**
2474 * This is a simple scalar statistic, like a counter.
2475 * @sa Stat, ScalarBase, StatStor
2476 */
2477 class Scalar : public ScalarBase<Scalar, StatStor>
2478 {
2479 public:
2480 using ScalarBase<Scalar, StatStor>::operator=;
2481 };
2482
2483 /**
2484 * A stat that calculates the per tick average of a value.
2485 * @sa Stat, ScalarBase, AvgStor
2486 */
2487 class Average : public ScalarBase<Average, AvgStor>
2488 {
2489 public:
2490 using ScalarBase<Average, AvgStor>::operator=;
2491 };
2492
2493 class Value : public ValueBase<Value>
2494 {
2495 };
2496
2497 /**
2498 * A vector of scalar stats.
2499 * @sa Stat, VectorBase, StatStor
2500 */
2501 class Vector : public VectorBase<Vector, StatStor>
2502 {
2503 };
2504
2505 /**
2506 * A vector of Average stats.
2507 * @sa Stat, VectorBase, AvgStor
2508 */
2509 class AverageVector : public VectorBase<AverageVector, AvgStor>
2510 {
2511 };
2512
2513 /**
2514 * A 2-Dimensional vecto of scalar stats.
2515 * @sa Stat, Vector2dBase, StatStor
2516 */
2517 class Vector2d : public Vector2dBase<Vector2d, StatStor>
2518 {
2519 };
2520
2521 /**
2522 * A simple distribution stat.
2523 * @sa Stat, DistBase, DistStor
2524 */
2525 class Distribution : public DistBase<Distribution, DistStor>
2526 {
2527 public:
2528 /**
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.
2534 */
2535 Distribution &
2536 init(Counter min, Counter max, Counter bkt)
2537 {
2538 DistStor::Params *params = new DistStor::Params;
2539 params->min = min;
2540 params->max = max;
2541 params->bucket_size = bkt;
2542 params->buckets = (size_type)ceil((max - min + 1.0) / bkt);
2543 this->setParams(params);
2544 this->doInit();
2545 return this->self();
2546 }
2547 };
2548
2549 /**
2550 * A simple histogram stat.
2551 * @sa Stat, DistBase, HistStor
2552 */
2553 class Histogram : public DistBase<Histogram, HistStor>
2554 {
2555 public:
2556 /**
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.
2560 */
2561 Histogram &
2562 init(size_type size)
2563 {
2564 HistStor::Params *params = new HistStor::Params;
2565 params->buckets = size;
2566 this->setParams(params);
2567 this->doInit();
2568 return this->self();
2569 }
2570 };
2571
2572 /**
2573 * Calculates the mean and variance of all the samples.
2574 * @sa DistBase, SampleStor
2575 */
2576 class StandardDeviation : public DistBase<StandardDeviation, SampleStor>
2577 {
2578 public:
2579 /**
2580 * Construct and initialize this distribution.
2581 */
2582 StandardDeviation()
2583 {
2584 SampleStor::Params *params = new SampleStor::Params;
2585 this->doInit();
2586 this->setParams(params);
2587 }
2588 };
2589
2590 /**
2591 * Calculates the per tick mean and variance of the samples.
2592 * @sa DistBase, AvgSampleStor
2593 */
2594 class AverageDeviation : public DistBase<AverageDeviation, AvgSampleStor>
2595 {
2596 public:
2597 /**
2598 * Construct and initialize this distribution.
2599 */
2600 AverageDeviation()
2601 {
2602 AvgSampleStor::Params *params = new AvgSampleStor::Params;
2603 this->doInit();
2604 this->setParams(params);
2605 }
2606 };
2607
2608 /**
2609 * A vector of distributions.
2610 * @sa VectorDistBase, DistStor
2611 */
2612 class VectorDistribution : public VectorDistBase<VectorDistribution, DistStor>
2613 {
2614 public:
2615 /**
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.
2622 */
2623 VectorDistribution &
2624 init(size_type size, Counter min, Counter max, Counter bkt)
2625 {
2626 DistStor::Params *params = new DistStor::Params;
2627 params->min = min;
2628 params->max = max;
2629 params->bucket_size = bkt;
2630 params->buckets = (size_type)ceil((max - min + 1.0) / bkt);
2631 this->setParams(params);
2632 this->doInit(size);
2633 return this->self();
2634 }
2635 };
2636
2637 /**
2638 * This is a vector of StandardDeviation stats.
2639 * @sa VectorDistBase, SampleStor
2640 */
2641 class VectorStandardDeviation
2642 : public VectorDistBase<VectorStandardDeviation, SampleStor>
2643 {
2644 public:
2645 /**
2646 * Initialize storage for this distribution.
2647 * @param size The size of the vector.
2648 * @return A reference to this distribution.
2649 */
2650 VectorStandardDeviation &
2651 init(size_type size)
2652 {
2653 SampleStor::Params *params = new SampleStor::Params;
2654 this->doInit(size);
2655 this->setParams(params);
2656 return this->self();
2657 }
2658 };
2659
2660 /**
2661 * This is a vector of AverageDeviation stats.
2662 * @sa VectorDistBase, AvgSampleStor
2663 */
2664 class VectorAverageDeviation
2665 : public VectorDistBase<VectorAverageDeviation, AvgSampleStor>
2666 {
2667 public:
2668 /**
2669 * Initialize storage for this distribution.
2670 * @param size The size of the vector.
2671 * @return A reference to this distribution.
2672 */
2673 VectorAverageDeviation &
2674 init(size_type size)
2675 {
2676 AvgSampleStor::Params *params = new AvgSampleStor::Params;
2677 this->doInit(size);
2678 this->setParams(params);
2679 return this->self();
2680 }
2681 };
2682
2683 template <class Stat>
2684 class FormulaInfoProxy : public InfoProxy<Stat, FormulaInfo>
2685 {
2686 protected:
2687 mutable VResult vec;
2688 mutable VCounter cvec;
2689
2690 public:
2691 FormulaInfoProxy(Stat &stat) : InfoProxy<Stat, FormulaInfo>(stat) {}
2692
2693 size_type size() const { return this->s.size(); }
2694
2695 const VResult &
2696 result() const
2697 {
2698 this->s.result(vec);
2699 return vec;
2700 }
2701 Result total() const { return this->s.total(); }
2702 VCounter &value() const { return cvec; }
2703
2704 std::string str() const { return this->s.str(); }
2705 };
2706
2707 template <class Stat>
2708 class SparseHistInfoProxy : public InfoProxy<Stat, SparseHistInfo>
2709 {
2710 public:
2711 SparseHistInfoProxy(Stat &stat) : InfoProxy<Stat, SparseHistInfo>(stat) {}
2712 };
2713
2714 /**
2715 * Implementation of a sparse histogram stat. The storage class is
2716 * determined by the Storage template.
2717 */
2718 template <class Derived, class Stor>
2719 class SparseHistBase : public DataWrap<Derived, SparseHistInfoProxy>
2720 {
2721 public:
2722 typedef SparseHistInfoProxy<Derived> Info;
2723 typedef Stor Storage;
2724 typedef typename Stor::Params Params;
2725
2726 protected:
2727 /** The storage for this stat. */
2728 char storage[sizeof(Storage)];
2729
2730 protected:
2731 /**
2732 * Retrieve the storage.
2733 * @return The storage object for this stat.
2734 */
2735 Storage *
2736 data()
2737 {
2738 return reinterpret_cast<Storage *>(storage);
2739 }
2740
2741 /**
2742 * Retrieve a const pointer to the storage.
2743 * @return A const pointer to the storage object for this stat.
2744 */
2745 const Storage *
2746 data() const
2747 {
2748 return reinterpret_cast<const Storage *>(storage);
2749 }
2750
2751 void
2752 doInit()
2753 {
2754 new (storage) Storage(this->info());
2755 this->setInit();
2756 }
2757
2758 public:
2759 SparseHistBase() { }
2760
2761 /**
2762 * Add a value to the distribtion n times. Calls sample on the storage
2763 * class.
2764 * @param v The value to add.
2765 * @param n The number of times to add it, defaults to 1.
2766 */
2767 template <typename U>
2768 void sample(const U &v, int n = 1) { data()->sample(v, n); }
2769
2770 /**
2771 * Return the number of entries in this stat.
2772 * @return The number of entries.
2773 */
2774 size_type size() const { return data()->size(); }
2775 /**
2776 * Return true if no samples have been added.
2777 * @return True if there haven't been any samples.
2778 */
2779 bool zero() const { return data()->zero(); }
2780
2781 void
2782 prepare()
2783 {
2784 Info *info = this->info();
2785 data()->prepare(info, info->data);
2786 }
2787
2788 /**
2789 * Reset stat value to default
2790 */
2791 void
2792 reset()
2793 {
2794 data()->reset(this->info());
2795 }
2796 };
2797
2798 /**
2799 * Templatized storage and interface for a sparse histogram stat.
2800 */
2801 class SparseHistStor
2802 {
2803 public:
2804 /** The parameters for a sparse histogram stat. */
2805 struct Params : public DistParams
2806 {
2807 Params() : DistParams(Hist) {}
2808 };
2809
2810 private:
2811 /** Counter for number of samples */
2812 Counter samples;
2813 /** Counter for each bucket. */
2814 MCounter cmap;
2815
2816 public:
2817 SparseHistStor(Info *info)
2818 {
2819 reset(info);
2820 }
2821
2822 /**
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.
2826 */
2827 void
2828 sample(Counter val, int number)
2829 {
2830 cmap[val] += number;
2831 samples += number;
2832 }
2833
2834 /**
2835 * Return the number of buckets in this distribution.
2836 * @return the number of buckets.
2837 */
2838 size_type size() const { return cmap.size(); }
2839
2840 /**
2841 * Returns true if any calls to sample have been made.
2842 * @return True if any values have been sampled.
2843 */
2844 bool
2845 zero() const
2846 {
2847 return samples == Counter();
2848 }
2849
2850 void
2851 prepare(Info *info, SparseHistData &data)
2852 {
2853 MCounter::iterator it;
2854 data.cmap.clear();
2855 for (it = cmap.begin(); it != cmap.end(); it++) {
2856 data.cmap[(*it).first] = (*it).second;
2857 }
2858
2859 data.samples = samples;
2860 }
2861
2862 /**
2863 * Reset stat value to default
2864 */
2865 void
2866 reset(Info *info)
2867 {
2868 cmap.clear();
2869 samples = 0;
2870 }
2871 };
2872
2873 class SparseHistogram : public SparseHistBase<SparseHistogram, SparseHistStor>
2874 {
2875 public:
2876 /**
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.
2880 */
2881 SparseHistogram &
2882 init(size_type size)
2883 {
2884 SparseHistStor::Params *params = new SparseHistStor::Params;
2885 this->setParams(params);
2886 this->doInit();
2887 return this->self();
2888 }
2889 };
2890
2891 class Temp;
2892 /**
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
2896 */
2897 class Formula : public DataWrapVec<Formula, FormulaInfoProxy>
2898 {
2899 protected:
2900 /** The root of the tree which represents the Formula */
2901 NodePtr root;
2902 friend class Temp;
2903
2904 public:
2905 /**
2906 * Create and initialize thie formula, and register it with the database.
2907 */
2908 Formula();
2909
2910 /**
2911 * Create a formula with the given root node, register it with the
2912 * database.
2913 * @param r The root of the expression tree.
2914 */
2915 Formula(Temp r);
2916
2917 /**
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.
2921 */
2922 const Formula &operator=(Temp r);
2923
2924 /**
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.
2928 */
2929 const Formula &operator+=(Temp r);
2930
2931 /**
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.
2935 */
2936 const Formula &operator/=(Temp r);
2937
2938 /**
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.
2944 */
2945 void result(VResult &vec) const;
2946
2947 /**
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.
2956 */
2957 Result total() const;
2958
2959 /**
2960 * Return the number of elements in the tree.
2961 */
2962 size_type size() const;
2963
2964 void prepare() { }
2965
2966 /**
2967 * Formulas don't need to be reset
2968 */
2969 void reset();
2970
2971 /**
2972 *
2973 */
2974 bool zero() const;
2975
2976 std::string str() const;
2977 };
2978
2979 class FormulaNode : public Node
2980 {
2981 private:
2982 const Formula &formula;
2983 mutable VResult vec;
2984
2985 public:
2986 FormulaNode(const Formula &f) : formula(f) {}
2987
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(); }
2991
2992 std::string str() const { return formula.str(); }
2993 };
2994
2995 /**
2996 * Helper class to construct formula node trees.
2997 */
2998 class Temp
2999 {
3000 protected:
3001 /**
3002 * Pointer to a Node object.
3003 */
3004 NodePtr node;
3005
3006 public:
3007 /**
3008 * Copy the given pointer to this class.
3009 * @param n A pointer to a Node object to copy.
3010 */
3011 Temp(const NodePtr &n) : node(n) { }
3012
3013 Temp(NodePtr &&n) : node(std::move(n)) { }
3014
3015 /**
3016 * Return the node pointer.
3017 * @return the node pointer.
3018 */
3019 operator NodePtr&() { return node; }
3020
3021 /**
3022 * Makde gcc < 4.6.3 happy and explicitly get the underlying node.
3023 */
3024 NodePtr getNodePtr() const { return node; }
3025
3026 public:
3027 /**
3028 * Create a new ScalarStatNode.
3029 * @param s The ScalarStat to place in a node.
3030 */
3031 Temp(const Scalar &s)
3032 : node(new ScalarStatNode(s.info()))
3033 { }
3034
3035 /**
3036 * Create a new ScalarStatNode.
3037 * @param s The ScalarStat to place in a node.
3038 */
3039 Temp(const Value &s)
3040 : node(new ScalarStatNode(s.info()))
3041 { }
3042
3043 /**
3044 * Create a new ScalarStatNode.
3045 * @param s The ScalarStat to place in a node.
3046 */
3047 Temp(const Average &s)
3048 : node(new ScalarStatNode(s.info()))
3049 { }
3050
3051 /**
3052 * Create a new VectorStatNode.
3053 * @param s The VectorStat to place in a node.
3054 */
3055 Temp(const Vector &s)
3056 : node(new VectorStatNode(s.info()))
3057 { }
3058
3059 Temp(const AverageVector &s)
3060 : node(new VectorStatNode(s.info()))
3061 { }
3062
3063 /**
3064 *
3065 */
3066 Temp(const Formula &f)
3067 : node(new FormulaNode(f))
3068 { }
3069
3070 /**
3071 * Create a new ScalarProxyNode.
3072 * @param p The ScalarProxy to place in a node.
3073 */
3074 template <class Stat>
3075 Temp(const ScalarProxy<Stat> &p)
3076 : node(new ScalarProxyNode<Stat>(p))
3077 { }
3078
3079 /**
3080 * Create a ConstNode
3081 * @param value The value of the const node.
3082 */
3083 Temp(signed char value)
3084 : node(new ConstNode<signed char>(value))
3085 { }
3086
3087 /**
3088 * Create a ConstNode
3089 * @param value The value of the const node.
3090 */
3091 Temp(unsigned char value)
3092 : node(new ConstNode<unsigned char>(value))
3093 { }
3094
3095 /**
3096 * Create a ConstNode
3097 * @param value The value of the const node.
3098 */
3099 Temp(signed short value)
3100 : node(new ConstNode<signed short>(value))
3101 { }
3102
3103 /**
3104 * Create a ConstNode
3105 * @param value The value of the const node.
3106 */
3107 Temp(unsigned short value)
3108 : node(new ConstNode<unsigned short>(value))
3109 { }
3110
3111 /**
3112 * Create a ConstNode
3113 * @param value The value of the const node.
3114 */
3115 Temp(signed int value)
3116 : node(new ConstNode<signed int>(value))
3117 { }
3118
3119 /**
3120 * Create a ConstNode
3121 * @param value The value of the const node.
3122 */
3123 Temp(unsigned int value)
3124 : node(new ConstNode<unsigned int>(value))
3125 { }
3126
3127 /**
3128 * Create a ConstNode
3129 * @param value The value of the const node.
3130 */
3131 Temp(signed long value)
3132 : node(new ConstNode<signed long>(value))
3133 { }
3134
3135 /**
3136 * Create a ConstNode
3137 * @param value The value of the const node.
3138 */
3139 Temp(unsigned long value)
3140 : node(new ConstNode<unsigned long>(value))
3141 { }
3142
3143 /**
3144 * Create a ConstNode
3145 * @param value The value of the const node.
3146 */
3147 Temp(signed long long value)
3148 : node(new ConstNode<signed long long>(value))
3149 { }
3150
3151 /**
3152 * Create a ConstNode
3153 * @param value The value of the const node.
3154 */
3155 Temp(unsigned long long value)
3156 : node(new ConstNode<unsigned long long>(value))
3157 { }
3158
3159 /**
3160 * Create a ConstNode
3161 * @param value The value of the const node.
3162 */
3163 Temp(float value)
3164 : node(new ConstNode<float>(value))
3165 { }
3166
3167 /**
3168 * Create a ConstNode
3169 * @param value The value of the const node.
3170 */
3171 Temp(double value)
3172 : node(new ConstNode<double>(value))
3173 { }
3174 };
3175
3176
3177 /**
3178 * @}
3179 */
3180
3181 inline Temp
3182 operator+(Temp l, Temp r)
3183 {
3184 return Temp(std::make_shared<BinaryNode<std::plus<Result> > >(l, r));
3185 }
3186
3187 inline Temp
3188 operator-(Temp l, Temp r)
3189 {
3190 return Temp(std::make_shared<BinaryNode<std::minus<Result> > >(l, r));
3191 }
3192
3193 inline Temp
3194 operator*(Temp l, Temp r)
3195 {
3196 return Temp(std::make_shared<BinaryNode<std::multiplies<Result> > >(l, r));
3197 }
3198
3199 inline Temp
3200 operator/(Temp l, Temp r)
3201 {
3202 return Temp(std::make_shared<BinaryNode<std::divides<Result> > >(l, r));
3203 }
3204
3205 inline Temp
3206 operator-(Temp l)
3207 {
3208 return Temp(std::make_shared<UnaryNode<std::negate<Result> > >(l));
3209 }
3210
3211 template <typename T>
3212 inline Temp
3213 constant(T val)
3214 {
3215 return Temp(std::make_shared<ConstNode<T> >(val));
3216 }
3217
3218 template <typename T>
3219 inline Temp
3220 constantVector(T val)
3221 {
3222 return Temp(std::make_shared<ConstVectorNode<T> >(val));
3223 }
3224
3225 inline Temp
3226 sum(Temp val)
3227 {
3228 return Temp(std::make_shared<SumNode<std::plus<Result> > >(val));
3229 }
3230
3231 /** Dump all statistics data to the registered outputs */
3232 void dump();
3233 void reset();
3234 void enable();
3235 bool enabled();
3236
3237 /**
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
3241 */
3242 typedef void (*Handler)();
3243
3244 void registerHandlers(Handler reset_handler, Handler dump_handler);
3245
3246 /**
3247 * Register a callback that should be called whenever statistics are
3248 * reset
3249 */
3250 void registerResetCallback(Callback *cb);
3251
3252 /**
3253 * Register a callback that should be called whenever statistics are
3254 * about to be dumped
3255 */
3256 void registerDumpCallback(Callback *cb);
3257
3258 /**
3259 * Process all the callbacks in the reset callbacks queue
3260 */
3261 void processResetQueue();
3262
3263 /**
3264 * Process all the callbacks in the dump callbacks queue
3265 */
3266 void processDumpQueue();
3267
3268 std::list<Info *> &statsList();
3269
3270 typedef std::map<const void *, Info *> MapType;
3271 MapType &statsMap();
3272
3273 typedef std::map<std::string, Info *> NameMapType;
3274 NameMapType &nameMap();
3275
3276 bool validateStatName(const std::string &name);
3277
3278 } // namespace Stats
3279
3280 void debugDumpStats();
3281
3282 #endif // __BASE_STATISTICS_HH__