Add python output support to the statistics package!
[gem5.git] / base / statistics.hh
1 /*
2 * Copyright (c) 2003 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /** @file
30 * Declaration of Statistics objects.
31 */
32
33 /**
34 * @todo
35 *
36 * Generalized N-dimensinal vector
37 * documentation
38 * key stats
39 * interval stats
40 * -- these both can use the same function that prints out a
41 * specific set of stats
42 * VectorStandardDeviation totals
43 * Document Namespaces
44 */
45 #ifndef __STATISTICS_HH__
46 #define __STATISTICS_HH__
47
48 #include <algorithm>
49 #include <cassert>
50 #include <cmath>
51 #include <functional>
52 #include <iosfwd>
53 #include <sstream>
54 #include <string>
55 #include <vector>
56
57 #include "base/cprintf.hh"
58 #include "base/intmath.hh"
59 #include "base/refcnt.hh"
60 #include "base/str.hh"
61 #include "sim/host.hh"
62
63 //
64 // Un-comment this to enable weirdo-stat debugging
65 //
66 // #define STAT_DEBUG
67
68
69 #ifndef NAN
70 float __nan();
71 /** Define Not a number. */
72 #define NAN (__nan())
73 /** Need to define __nan() */
74 #define __M5_NAN
75 #endif
76
77 class Callback;
78 class Python;
79
80 /** The current simulated cycle. */
81 extern Tick curTick;
82
83 /* A namespace for all of the Statistics */
84 namespace Statistics {
85 /** All results are doubles. */
86 typedef double result_t;
87 /** A vector to hold results. */
88 typedef std::vector<result_t> rvec_t;
89
90 /**
91 * Define the storage for format flags.
92 * @todo Can probably shrink this.
93 */
94 typedef u_int32_t StatFlags;
95
96 /** Nothing extra to print. */
97 const StatFlags none = 0x00000000;
98 /** This Stat is Initialized */
99 const StatFlags init = 0x00000001;
100 /** Print this stat. */
101 const StatFlags print = 0x00000002;
102 /** Print the total. */
103 const StatFlags total = 0x00000010;
104 /** Print the percent of the total that this entry represents. */
105 const StatFlags pdf = 0x00000020;
106 /** Print the cumulative percentage of total upto this entry. */
107 const StatFlags cdf = 0x00000040;
108 /** Print the distribution. */
109 const StatFlags dist = 0x00000080;
110 /** Don't print if this is zero. */
111 const StatFlags nozero = 0x00000100;
112 /** Don't print if this is NAN */
113 const StatFlags nonan = 0x00000200;
114 /** Used for SS compatability. */
115 const StatFlags __substat = 0x80000000;
116
117 /** Mask of flags that can't be set directly */
118 const StatFlags __reserved = init | print | __substat;
119
120 enum DisplayMode
121 {
122 mode_m5,
123 mode_simplescalar,
124 mode_python
125 };
126
127 extern DisplayMode DefaultMode;
128
129 /* Contains the statistic implementation details */
130 //////////////////////////////////////////////////////////////////////
131 //
132 // Statistics Framework Base classes
133 //
134 //////////////////////////////////////////////////////////////////////
135 struct StatData
136 {
137 /** The name of the stat. */
138 std::string name;
139 /** The description of the stat. */
140 std::string desc;
141 /** The formatting flags. */
142 StatFlags flags;
143 /** The display precision. */
144 int precision;
145
146
147 /** A pointer to a prerequisite Stat. */
148 const StatData *prereq;
149
150 StatData()
151 : flags(none), precision(-1), prereq(0)
152 {}
153
154 virtual ~StatData();
155
156 /**
157 * @return true if the stat is binned.
158 */
159 virtual bool binned() const = 0;
160
161 /**
162 * Print this stat to the given ostream.
163 * @param stream The stream to print to.
164 */
165 virtual void display(std::ostream &stream, DisplayMode mode) const = 0;
166 virtual void python(Python &py) const = 0;
167 bool dodisplay() const { return !prereq || !prereq->zero(); }
168
169 /**
170 * Reset the corresponding stat to the default state.
171 */
172 virtual void reset() = 0;
173
174 /**
175 * @return true if this stat has a value and satisfies its
176 * requirement as a prereq
177 */
178 virtual bool zero() const = 0;
179
180 /**
181 * Check that this stat has been set up properly and is ready for
182 * use
183 * @return true for success
184 */
185 virtual bool check() const = 0;
186 bool baseCheck() const;
187
188 /**
189 * Checks if the first stat's name is alphabetically less than the second.
190 * This function breaks names up at periods and considers each subname
191 * separately.
192 * @param stat1 The first stat.
193 * @param stat2 The second stat.
194 * @return stat1's name is alphabetically before stat2's
195 */
196 static bool less(StatData *stat1, StatData *stat2);
197 };
198
199 struct ScalarDataBase : public StatData
200 {
201 virtual result_t val() const = 0;
202 virtual result_t total() const = 0;
203
204 virtual void display(std::ostream &stream, DisplayMode mode) const;
205 virtual void python(Python &py) const;
206 };
207
208 template <class T>
209 class ScalarData : public ScalarDataBase
210 {
211 protected:
212 T &s;
213
214 public:
215 ScalarData(T &stat) : s(stat) {}
216
217 virtual bool binned() const { return s.binned(); }
218 virtual bool check() const { return s.check(); }
219 virtual result_t val() const { return s.val(); }
220 virtual result_t total() const { return s.total(); }
221 virtual void reset() { s.reset(); }
222 virtual bool zero() const { return s.zero(); }
223 };
224
225 struct VectorDataBase : public StatData
226 {
227 /** Names and descriptions of subfields. */
228 mutable std::vector<std::string> subnames;
229 mutable std::vector<std::string> subdescs;
230
231 virtual void display(std::ostream &stream, DisplayMode mode) const;
232 virtual void python(Python &py) const;
233
234 virtual size_t size() const = 0;
235 virtual const rvec_t &val() const = 0;
236 virtual result_t total() const = 0;
237 virtual void update()
238 {
239 if (!subnames.empty()) {
240 int s = size();
241 if (subnames.size() < s)
242 subnames.resize(s);
243
244 if (subdescs.size() < s)
245 subdescs.resize(s);
246 }
247 }
248 };
249
250 template <class T>
251 class VectorData : public VectorDataBase
252 {
253 protected:
254 T &s;
255 mutable rvec_t vec;
256
257 public:
258 VectorData(T &stat) : s(stat) {}
259
260 virtual bool binned() const { return s.binned(); }
261 virtual bool check() const { return s.check(); }
262 virtual bool zero() const { return s.zero(); }
263 virtual void reset() { s.reset(); }
264
265 virtual size_t size() const { return s.size(); }
266 virtual const rvec_t &val() const
267 {
268 s.val(vec);
269 return vec;
270 }
271 virtual result_t total() const { return s.total(); }
272 virtual void update()
273 {
274 VectorDataBase::update();
275 s.update(this);
276 }
277 };
278
279 struct DistDataData
280 {
281 result_t min_val;
282 result_t max_val;
283 result_t underflow;
284 result_t overflow;
285 rvec_t vec;
286 result_t sum;
287 result_t squares;
288 result_t samples;
289
290 int min;
291 int max;
292 int bucket_size;
293 int size;
294 bool fancy;
295
296 void python(Python &py, const std::string &name) const;
297 };
298
299 struct DistDataBase : public StatData
300 {
301 /** Local storage for the entry values, used for printing. */
302 DistDataData data;
303
304 virtual void display(std::ostream &stream, DisplayMode mode) const;
305 virtual void python(Python &py) const;
306 virtual void update() = 0;
307 };
308
309 template <class T>
310 class DistData : public DistDataBase
311 {
312 protected:
313 T &s;
314
315 public:
316 DistData(T &stat) : s(stat) {}
317
318 virtual bool binned() const { return s.binned(); }
319 virtual bool check() const { return s.check(); }
320 virtual void reset() { s.reset(); }
321 virtual bool zero() const { return s.zero(); }
322 virtual void update() { return s.update(this); }
323 };
324
325 struct VectorDistDataBase : public StatData
326 {
327 std::vector<DistDataData> data;
328
329 /** Names and descriptions of subfields. */
330 mutable std::vector<std::string> subnames;
331 mutable std::vector<std::string> subdescs;
332
333 /** Local storage for the entry values, used for printing. */
334 mutable rvec_t vec;
335
336 virtual size_t size() const = 0;
337 virtual void display(std::ostream &stream, DisplayMode mode) const;
338 virtual void python(Python &py) const;
339 virtual void update()
340 {
341 int s = size();
342 if (subnames.size() < s)
343 subnames.resize(s);
344
345 if (subdescs.size() < s)
346 subdescs.resize(s);
347 }
348 };
349
350 template <class T>
351 class VectorDistData : public VectorDistDataBase
352 {
353 protected:
354 T &s;
355 typedef typename T::bin_t bin_t;
356
357 public:
358 VectorDistData(T &stat) : s(stat) {}
359
360 virtual bool binned() const { return bin_t::binned; }
361 virtual bool check() const { return s.check(); }
362 virtual void reset() { s.reset(); }
363 virtual size_t size() const { return s.size(); }
364 virtual bool zero() const { return s.zero(); }
365 virtual void update()
366 {
367 VectorDistDataBase::update();
368 return s.update(this);
369 }
370 };
371
372 struct Vector2dDataBase : public StatData
373 {
374 /** Names and descriptions of subfields. */
375 std::vector<std::string> subnames;
376 std::vector<std::string> subdescs;
377 std::vector<std::string> y_subnames;
378
379 /** Local storage for the entry values, used for printing. */
380 mutable rvec_t vec;
381 mutable int x;
382 mutable int y;
383
384 virtual void display(std::ostream &stream, DisplayMode mode) const;
385 virtual void python(Python &py) const;
386 virtual void update()
387 {
388 if (subnames.size() < x)
389 subnames.resize(x);
390 }
391 };
392
393 template <class T>
394 class Vector2dData : public Vector2dDataBase
395 {
396 protected:
397 T &s;
398 typedef typename T::bin_t bin_t;
399
400 public:
401 Vector2dData(T &stat) : s(stat) {}
402
403 virtual bool binned() const { return bin_t::binned; }
404 virtual bool check() const { return s.check(); }
405 virtual void reset() { s.reset(); }
406 virtual bool zero() const { return s.zero(); }
407 virtual void update()
408 {
409 Vector2dDataBase::update();
410 s.update(this);
411 }
412 };
413
414
415 class DataAccess
416 {
417 protected:
418 StatData *find() const;
419 void map(StatData *data);
420
421 StatData *statData();
422 const StatData *statData() const;
423
424 void setInit();
425 void setPrint();
426 };
427
428 template <class Parent, class Child, template <class> class Data>
429 class Wrap : public Child
430 {
431 protected:
432 Parent &self() { return *reinterpret_cast<Parent *>(this); }
433
434 protected:
435 Data<Child> *statData()
436 {
437 StatData *__data = DataAccess::statData();
438 Data<Child> *ptr = dynamic_cast<Data<Child> *>(__data);
439 assert(ptr);
440 return ptr;
441 }
442
443 public:
444 const Data<Child> *statData() const
445 {
446 const StatData *__data = DataAccess::statData();
447 const Data<Child> *ptr = dynamic_cast<const Data<Child> *>(__data);
448 assert(ptr);
449 return ptr;
450 }
451
452 public:
453 Wrap()
454 {
455 map(new Data<Child>(*this));
456 }
457
458 /**
459 * Set the name and marks this stat to print at the end of simulation.
460 * @param name The new name.
461 * @return A reference to this stat.
462 */
463 Parent &name(const std::string &_name)
464 {
465 Data<Child> *data = statData();
466 data->name = _name;
467 setPrint();
468 return self();
469 }
470
471 /**
472 * Set the description and marks this stat to print at the end of
473 * simulation.
474 * @param desc The new description.
475 * @return A reference to this stat.
476 */
477 Parent &desc(const std::string &_desc)
478 {
479 statData()->desc = _desc;
480 return self();
481 }
482
483 /**
484 * Set the precision and marks this stat to print at the end of simulation.
485 * @param p The new precision
486 * @return A reference to this stat.
487 */
488 Parent &precision(int _precision)
489 {
490 statData()->precision = _precision;
491 return self();
492 }
493
494 /**
495 * Set the flags and marks this stat to print at the end of simulation.
496 * @param f The new flags.
497 * @return A reference to this stat.
498 */
499 Parent &flags(StatFlags _flags)
500 {
501 statData()->flags |= _flags;
502 return self();
503 }
504
505 /**
506 * Set the prerequisite stat and marks this stat to print at the end of
507 * simulation.
508 * @param prereq The prerequisite stat.
509 * @return A reference to this stat.
510 */
511 template <class T>
512 Parent &prereq(const T &prereq)
513 {
514 statData()->prereq = prereq.statData();
515 return self();
516 }
517 };
518
519 template <class Parent, class Child, template <class Child> class Data>
520 class WrapVec : public Wrap<Parent, Child, Data>
521 {
522 public:
523 // The following functions are specific to vectors. If you use them
524 // in a non vector context, you will get a nice compiler error!
525
526 /**
527 * Set the subfield name for the given index, and marks this stat to print
528 * at the end of simulation.
529 * @param index The subfield index.
530 * @param name The new name of the subfield.
531 * @return A reference to this stat.
532 */
533 Parent &subname(int index, const std::string &name)
534 {
535 std::vector<std::string> &subn = statData()->subnames;
536 if (subn.size() <= index)
537 subn.resize(index + 1);
538 subn[index] = name;
539 return self();
540 }
541
542 /**
543 * Set the subfield description for the given index and marks this stat to
544 * print at the end of simulation.
545 * @param index The subfield index.
546 * @param desc The new description of the subfield
547 * @return A reference to this stat.
548 */
549 Parent &subdesc(int index, const std::string &desc)
550 {
551 std::vector<std::string> &subd = statData()->subdescs;
552 if (subd.size() <= index)
553 subd.resize(index + 1);
554 subd[index] = desc;
555
556 return self();
557 }
558
559 };
560
561 template <class Parent, class Child, template <class Child> class Data>
562 class WrapVec2d : public WrapVec<Parent, Child, Data>
563 {
564 public:
565 /**
566 * @warning This makes the assumption that if you're gonna subnames a 2d
567 * vector, you're subnaming across all y
568 */
569 Parent &ysubnames(const char **names)
570 {
571 Data<Child> *data = statData();
572 data->y_subnames.resize(y);
573 for (int i = 0; i < y; ++i)
574 data->y_subnames[i] = names[i];
575 return self();
576 }
577 Parent &ysubname(int index, const std::string subname)
578 {
579 Data<Child> *data = statData();
580 assert(i < y);
581 data->y_subnames.resize(y);
582 data->y_subnames[i] = subname.c_str();
583 return self();
584 }
585 };
586
587 //////////////////////////////////////////////////////////////////////
588 //
589 // Simple Statistics
590 //
591 //////////////////////////////////////////////////////////////////////
592
593 /**
594 * Templatized storage and interface for a simple scalar stat.
595 */
596 template <typename T>
597 struct StatStor
598 {
599 public:
600 /** The paramaters for this storage type, none for a scalar. */
601 struct Params { };
602
603 private:
604 /** The statistic value. */
605 T data;
606 static T &Null()
607 {
608 static T __T = T();
609 return __T;
610 }
611
612 public:
613 /**
614 * Builds this storage element and calls the base constructor of the
615 * datatype.
616 */
617 StatStor(const Params &) : data(Null()) {}
618
619 /**
620 * The the stat to the given value.
621 * @param val The new value.
622 * @param p The paramters of this storage type.
623 */
624 void set(T val, const Params &p) { data = val; }
625 /**
626 * Increment the stat by the given value.
627 * @param val The new value.
628 * @param p The paramters of this storage type.
629 */
630 void inc(T val, const Params &p) { data += val; }
631 /**
632 * Decrement the stat by the given value.
633 * @param val The new value.
634 * @param p The paramters of this storage type.
635 */
636 void dec(T val, const Params &p) { data -= val; }
637 /**
638 * Return the value of this stat as a result type.
639 * @param p The parameters of this storage type.
640 * @return The value of this stat.
641 */
642 result_t val(const Params &p) const { return (result_t)data; }
643 /**
644 * Return the value of this stat as its base type.
645 * @param p The params of this storage type.
646 * @return The value of this stat.
647 */
648 T value(const Params &p) const { return data; }
649 /**
650 * Reset stat value to default
651 */
652 void reset() { data = Null(); }
653
654 /**
655 * @return true if zero value
656 */
657 bool zero() const { return data == Null(); }
658 };
659
660 /**
661 * Templatized storage and interface to a per-cycle average stat. This keeps
662 * a current count and updates a total (count * cycles) when this count
663 * changes. This allows the quick calculation of a per cycle count of the item
664 * being watched. This is good for keeping track of residencies in structures
665 * among other things.
666 * @todo add lateny to the stat and fix binning.
667 */
668 template <typename T>
669 struct AvgStor
670 {
671 public:
672 /** The paramaters for this storage type */
673 struct Params
674 {
675 /**
676 * The current count. We stash this here because the current
677 * value is not a binned value.
678 */
679 T current;
680 };
681
682 private:
683 /** The total count for all cycles. */
684 mutable result_t total;
685 /** The cycle that current last changed. */
686 mutable Tick last;
687
688 public:
689 /**
690 * Build and initializes this stat storage.
691 */
692 AvgStor(Params &p) : total(0), last(0) { p.current = T(); }
693
694 /**
695 * Set the current count to the one provided, update the total and last
696 * set values.
697 * @param val The new count.
698 * @param p The parameters for this storage.
699 */
700 void set(T val, Params &p) {
701 total += p.current * (curTick - last);
702 last = curTick;
703 p.current = val;
704 }
705
706 /**
707 * Increment the current count by the provided value, calls set.
708 * @param val The amount to increment.
709 * @param p The parameters for this storage.
710 */
711 void inc(T val, Params &p) { set(p.current + val, p); }
712
713 /**
714 * Deccrement the current count by the provided value, calls set.
715 * @param val The amount to decrement.
716 * @param p The parameters for this storage.
717 */
718 void dec(T val, Params &p) { set(p.current - val, p); }
719
720 /**
721 * Return the current average.
722 * @param p The parameters for this storage.
723 * @return The current average.
724 */
725 result_t val(const Params &p) const {
726 total += p.current * (curTick - last);
727 last = curTick;
728 return (result_t)(total + p.current) / (result_t)(curTick + 1);
729 }
730
731 /**
732 * Return the current count.
733 * @param p The parameters for this storage.
734 * @return The current count.
735 */
736 T value(const Params &p) const { return p.current; }
737
738 /**
739 * Reset stat value to default
740 */
741 void reset()
742 {
743 total = 0;
744 last = curTick;
745 }
746
747 /**
748 * @return true if zero value
749 */
750 bool zero() const { return total == 0.0; }
751 };
752
753 /**
754 * Implementation of a scalar stat. The type of stat is determined by the
755 * Storage template. The storage for this stat is held within the Bin class.
756 * This allows for breaking down statistics across multiple bins easily.
757 */
758 template <typename T, template <typename T> class Storage, class Bin>
759 class ScalarBase : public DataAccess
760 {
761 public:
762 /** Define the type of the storage class. */
763 typedef Storage<T> storage_t;
764 /** Define the params of the storage class. */
765 typedef typename storage_t::Params params_t;
766 /** Define the bin type. */
767 typedef typename Bin::Bin<storage_t> bin_t;
768
769 protected:
770 /** The bin of this stat. */
771 bin_t bin;
772 /** The parameters for this stat. */
773 params_t params;
774
775 protected:
776 /**
777 * Retrieve the storage from the bin.
778 * @return The storage object for this stat.
779 */
780 storage_t *data() { return bin.data(params); }
781 /**
782 * Retrieve a const pointer to the storage from the bin.
783 * @return A const pointer to the storage object for this stat.
784 */
785 const storage_t *data() const
786 {
787 bin_t *_bin = const_cast<bin_t *>(&bin);
788 params_t *_params = const_cast<params_t *>(&params);
789 return _bin->data(*_params);
790 }
791
792 protected:
793 /**
794 * Copy constructor, copies are not allowed.
795 */
796 ScalarBase(const ScalarBase &stat);
797 /**
798 * Can't copy stats.
799 */
800 const ScalarBase &operator=(const ScalarBase &);
801
802 public:
803 /**
804 * Return the current value of this stat as its base type.
805 * @return The current value.
806 */
807 T value() const { return data()->value(params); }
808
809 public:
810 /**
811 * Create and initialize this stat, register it with the database.
812 */
813 ScalarBase()
814 {
815 bin.init(params);
816 }
817
818 public:
819 // Common operators for stats
820 /**
821 * Increment the stat by 1. This calls the associated storage object inc
822 * function.
823 */
824 void operator++() { data()->inc(1, params); }
825 /**
826 * Decrement the stat by 1. This calls the associated storage object dec
827 * function.
828 */
829 void operator--() { data()->dec(1, params); }
830
831 /** Increment the stat by 1. */
832 void operator++(int) { ++*this; }
833 /** Decrement the stat by 1. */
834 void operator--(int) { --*this; }
835
836 /**
837 * Set the data value to the given value. This calls the associated storage
838 * object set function.
839 * @param v The new value.
840 */
841 template <typename U>
842 void operator=(const U& v) { data()->set(v, params); }
843
844 /**
845 * Increment the stat by the given value. This calls the associated
846 * storage object inc function.
847 * @param v The value to add.
848 */
849 template <typename U>
850 void operator+=(const U& v) { data()->inc(v, params); }
851
852 /**
853 * Decrement the stat by the given value. This calls the associated
854 * storage object dec function.
855 * @param v The value to substract.
856 */
857 template <typename U>
858 void operator-=(const U& v) { data()->dec(v, params); }
859
860 /**
861 * Return the number of elements, always 1 for a scalar.
862 * @return 1.
863 */
864 size_t size() const { return 1; }
865 /**
866 * Return true if stat is binned.
867 *@return True is stat is binned.
868 */
869 bool binned() const { return bin_t::binned; }
870
871 bool check() const { return bin.initialized(); }
872
873 /**
874 * Reset stat value to default
875 */
876 void reset() { bin.reset(); }
877
878 result_t val() { return data()->val(params); }
879
880 result_t total() { return val(); }
881
882 bool zero() { return val() == 0.0; }
883 };
884
885 //////////////////////////////////////////////////////////////////////
886 //
887 // Vector Statistics
888 //
889 //////////////////////////////////////////////////////////////////////
890 template <typename T, template <typename T> class Storage, class Bin>
891 class ScalarProxy;
892
893 /**
894 * Implementation of a vector of stats. The type of stat is determined by the
895 * Storage class. @sa ScalarBase
896 */
897 template <typename T, template <typename T> class Storage, class Bin>
898 class VectorBase : public DataAccess
899 {
900 public:
901 /** Define the type of the storage class. */
902 typedef Storage<T> storage_t;
903 /** Define the params of the storage class. */
904 typedef typename storage_t::Params params_t;
905 /** Define the bin type. */
906 typedef typename Bin::VectorBin<storage_t> bin_t;
907
908 protected:
909 /** The bin of this stat. */
910 bin_t bin;
911 /** The parameters for this stat. */
912 params_t params;
913
914 protected:
915 /**
916 * Retrieve the storage from the bin for the given index.
917 * @param index The vector index to access.
918 * @return The storage object at the given index.
919 */
920 storage_t *data(int index) { return bin.data(index, params); }
921 /**
922 * Retrieve a const pointer to the storage from the bin
923 * for the given index.
924 * @param index The vector index to access.
925 * @return A const pointer to the storage object at the given index.
926 */
927 const storage_t *data(int index) const
928 {
929 bin_t *_bin = const_cast<bin_t *>(&bin);
930 params_t *_params = const_cast<params_t *>(&params);
931 return _bin->data(index, *_params);
932 }
933
934 protected:
935 // Copying stats is not allowed
936 /** Copying stats isn't allowed. */
937 VectorBase(const VectorBase &stat);
938 /** Copying stats isn't allowed. */
939 const VectorBase &operator=(const VectorBase &);
940
941 public:
942 /**
943 * Copy the values to a local vector and return a reference to it.
944 * @return A reference to a vector of the stat values.
945 */
946 void val(rvec_t &vec) const
947 {
948 vec.resize(size());
949 for (int i = 0; i < size(); ++i)
950 vec[i] = data(i)->val(params);
951 }
952
953 /**
954 * @return True is stat is binned.
955 */
956 bool binned() const { return bin_t::binned; }
957
958 /**
959 * Return a total of all entries in this vector.
960 * @return The total of all vector entries.
961 */
962 result_t total() const {
963 result_t total = 0.0;
964 for (int i = 0; i < size(); ++i)
965 total += data(i)->val(params);
966 return total;
967 }
968
969 /**
970 * @return the number of elements in this vector.
971 */
972 size_t size() const { return bin.size(); }
973
974 bool zero() const
975 {
976 for (int i = 0; i < size(); ++i)
977 if (data(i)->zero())
978 return true;
979 return false;
980 }
981
982 bool check() const { return bin.initialized(); }
983 void reset() { bin.reset(); }
984
985 public:
986 VectorBase() {}
987
988 /** Friend this class with the associated scalar proxy. */
989 friend class ScalarProxy<T, Storage, Bin>;
990
991 /**
992 * Return a reference (ScalarProxy) to the stat at the given index.
993 * @param index The vector index to access.
994 * @return A reference of the stat.
995 */
996 ScalarProxy<T, Storage, Bin> operator[](int index);
997
998 void update(StatData *data) {}
999 };
1000
1001 const StatData * getStatData(const void *stat);
1002
1003 /**
1004 * A proxy class to access the stat at a given index in a VectorBase stat.
1005 * Behaves like a ScalarBase.
1006 */
1007 template <typename T, template <typename T> class Storage, class Bin>
1008 class ScalarProxy
1009 {
1010 public:
1011 /** Define the type of the storage class. */
1012 typedef Storage<T> storage_t;
1013 /** Define the params of the storage class. */
1014 typedef typename storage_t::Params params_t;
1015 /** Define the bin type. */
1016 typedef typename Bin::VectorBin<storage_t> bin_t;
1017
1018 private:
1019 /** Pointer to the bin in the parent VectorBase. */
1020 bin_t *bin;
1021 /** Pointer to the params in the parent VectorBase. */
1022 params_t *params;
1023 /** The index to access in the parent VectorBase. */
1024 int index;
1025 /** Keep a pointer to the original stat so was can get data */
1026 void *stat;
1027
1028 protected:
1029 /**
1030 * Retrieve the storage from the bin.
1031 * @return The storage from the bin for this stat.
1032 */
1033 storage_t *data() { return bin->data(index, *params); }
1034 /**
1035 * Retrieve a const pointer to the storage from the bin.
1036 * @return A const pointer to the storage for this stat.
1037 */
1038 const storage_t *data() const
1039 {
1040 bin_t *_bin = const_cast<bin_t *>(bin);
1041 params_t *_params = const_cast<params_t *>(params);
1042 return _bin->data(index, *_params);
1043 }
1044
1045 public:
1046 /**
1047 * Return the current value of this statas a result type.
1048 * @return The current value.
1049 */
1050 result_t val() const { return data()->val(*params); }
1051 /**
1052 * Return the current value of this stat as its base type.
1053 * @return The current value.
1054 */
1055 T value() const { return data()->value(*params); }
1056
1057 public:
1058 /**
1059 * Create and initialize this proxy, do not register it with the database.
1060 * @param b The bin to use.
1061 * @param p The params to use.
1062 * @param i The index to access.
1063 */
1064 ScalarProxy(bin_t &b, params_t &p, int i, void *s)
1065 : bin(&b), params(&p), index(i), stat(s) {}
1066 /**
1067 * Create a copy of the provided ScalarProxy.
1068 * @param sp The proxy to copy.
1069 */
1070 ScalarProxy(const ScalarProxy &sp)
1071 : bin(sp.bin), params(sp.params), index(sp.index), stat(sp.stat) {}
1072 /**
1073 * Set this proxy equal to the provided one.
1074 * @param sp The proxy to copy.
1075 * @return A reference to this proxy.
1076 */
1077 const ScalarProxy &operator=(const ScalarProxy &sp) {
1078 bin = sp.bin;
1079 params = sp.params;
1080 index = sp.index;
1081 stat = sp.stat;
1082 return *this;
1083 }
1084
1085 public:
1086 // Common operators for stats
1087 /**
1088 * Increment the stat by 1. This calls the associated storage object inc
1089 * function.
1090 */
1091 void operator++() { data()->inc(1, *params); }
1092 /**
1093 * Decrement the stat by 1. This calls the associated storage object dec
1094 * function.
1095 */
1096 void operator--() { data()->dec(1, *params); }
1097
1098 /** Increment the stat by 1. */
1099 void operator++(int) { ++*this; }
1100 /** Decrement the stat by 1. */
1101 void operator--(int) { --*this; }
1102
1103 /**
1104 * Set the data value to the given value. This calls the associated storage
1105 * object set function.
1106 * @param v The new value.
1107 */
1108 template <typename U>
1109 void operator=(const U& v) { data()->set(v, *params); }
1110
1111 /**
1112 * Increment the stat by the given value. This calls the associated
1113 * storage object inc function.
1114 * @param v The value to add.
1115 */
1116 template <typename U>
1117 void operator+=(const U& v) { data()->inc(v, *params); }
1118
1119 /**
1120 * Decrement the stat by the given value. This calls the associated
1121 * storage object dec function.
1122 * @param v The value to substract.
1123 */
1124 template <typename U>
1125 void operator-=(const U& v) { data()->dec(v, *params); }
1126
1127 /**
1128 * Return the number of elements, always 1 for a scalar.
1129 * @return 1.
1130 */
1131 size_t size() const { return 1; }
1132
1133 /**
1134 * Return true if stat is binned.
1135 *@return false since Proxies aren't printed/binned
1136 */
1137 bool binned() const { return false; }
1138
1139 /**
1140 * This stat has no state. Nothing to reset
1141 */
1142 void reset() { }
1143
1144 public:
1145 const StatData *statData() const { return getStatData(stat); }
1146 std::string str() const
1147 {
1148 return csprintf("%s[%d]", statData()->name, index);
1149
1150 }
1151 };
1152
1153 template <typename T, template <typename T> class Storage, class Bin>
1154 inline ScalarProxy<T, Storage, Bin>
1155 VectorBase<T, Storage, Bin>::operator[](int index)
1156 {
1157 assert (index >= 0 && index < size());
1158 return ScalarProxy<T, Storage, Bin>(bin, params, index, this);
1159 }
1160
1161 template <typename T, template <typename T> class Storage, class Bin>
1162 class VectorProxy;
1163
1164 template <typename T, template <typename T> class Storage, class Bin>
1165 class Vector2dBase : public DataAccess
1166 {
1167 public:
1168 typedef Storage<T> storage_t;
1169 typedef typename storage_t::Params params_t;
1170 typedef typename Bin::VectorBin<storage_t> bin_t;
1171
1172 protected:
1173 size_t x;
1174 size_t y;
1175 bin_t bin;
1176 params_t params;
1177
1178 protected:
1179 storage_t *data(int index) { return bin.data(index, params); }
1180 const storage_t *data(int index) const
1181 {
1182 bin_t *_bin = const_cast<bin_t *>(&bin);
1183 params_t *_params = const_cast<params_t *>(&params);
1184 return _bin->data(index, *_params);
1185 }
1186
1187 protected:
1188 // Copying stats is not allowed
1189 Vector2dBase(const Vector2dBase &stat);
1190 const Vector2dBase &operator=(const Vector2dBase &);
1191
1192 public:
1193 Vector2dBase() {}
1194
1195 void update(Vector2dDataBase *data)
1196 {
1197 int size = this->size();
1198 data->vec.resize(size);
1199 for (int i = 0; i < size; ++i)
1200 data->vec[i] = this->data(i)->val(params);
1201 }
1202
1203 std::string ysubname(int i) const { return (*y_subnames)[i]; }
1204
1205 friend class VectorProxy<T, Storage, Bin>;
1206 VectorProxy<T, Storage, Bin> operator[](int index);
1207
1208 size_t size() const { return bin.size(); }
1209 bool zero() const { return data(0)->value(params) == 0.0; }
1210
1211 /**
1212 * Reset stat value to default
1213 */
1214 void reset() { bin.reset(); }
1215
1216 bool check() { return bin.initialized(); }
1217 };
1218
1219 template <typename T, template <typename T> class Storage, class Bin>
1220 class VectorProxy
1221 {
1222 public:
1223 typedef Storage<T> storage_t;
1224 typedef typename storage_t::Params params_t;
1225 typedef typename Bin::VectorBin<storage_t> bin_t;
1226
1227 private:
1228 bin_t *bin;
1229 params_t *params;
1230 int offset;
1231 int len;
1232 void *stat;
1233
1234 private:
1235 mutable rvec_t *vec;
1236
1237 storage_t *data(int index) {
1238 assert(index < len);
1239 return bin->data(offset + index, *params);
1240 }
1241
1242 const storage_t *data(int index) const {
1243 bin_t *_bin = const_cast<bin_t *>(bin);
1244 params_t *_params = const_cast<params_t *>(params);
1245 return _bin->data(offset + index, *_params);
1246 }
1247
1248 public:
1249 const rvec_t &val() const {
1250 if (vec)
1251 vec->resize(size());
1252 else
1253 vec = new rvec_t(size());
1254
1255 for (int i = 0; i < size(); ++i)
1256 (*vec)[i] = data(i)->val(*params);
1257
1258 return *vec;
1259 }
1260
1261 result_t total() const {
1262 result_t total = 0.0;
1263 for (int i = 0; i < size(); ++i)
1264 total += data(i)->val(*params);
1265 return total;
1266 }
1267
1268 public:
1269 VectorProxy(bin_t &b, params_t &p, int o, int l, void *s)
1270 : bin(&b), params(&p), offset(o), len(l), stat(s), vec(NULL)
1271 {
1272 }
1273
1274 VectorProxy(const VectorProxy &sp)
1275 : bin(sp.bin), params(sp.params), offset(sp.offset), len(sp.len),
1276 stat(sp.stat), vec(NULL)
1277 {
1278 }
1279
1280 ~VectorProxy()
1281 {
1282 if (vec)
1283 delete vec;
1284 }
1285
1286 const VectorProxy &operator=(const VectorProxy &sp)
1287 {
1288 bin = sp.bin;
1289 params = sp.params;
1290 offset = sp.offset;
1291 len = sp.len;
1292 stat = sp.stat;
1293 if (vec)
1294 delete vec;
1295 vec = NULL;
1296 return *this;
1297 }
1298
1299 ScalarProxy<T, Storage, Bin> operator[](int index)
1300 {
1301 assert (index >= 0 && index < size());
1302 return ScalarProxy<T, Storage, Bin>(*bin, *params, offset + index,
1303 stat);
1304 }
1305
1306 size_t size() const { return len; }
1307
1308 /**
1309 * Return true if stat is binned.
1310 *@return false since Proxies aren't printed/binned
1311 */
1312 bool binned() const { return false; }
1313
1314 /**
1315 * This stat has no state. Nothing to reset.
1316 */
1317 void reset() { }
1318 };
1319
1320 template <typename T, template <typename T> class Storage, class Bin>
1321 inline VectorProxy<T, Storage, Bin>
1322 Vector2dBase<T, Storage, Bin>::operator[](int index)
1323 {
1324 int offset = index * y;
1325 assert (index >= 0 && offset < size());
1326 return VectorProxy<T, Storage, Bin>(bin, params, offset, y, this);
1327 }
1328
1329 //////////////////////////////////////////////////////////////////////
1330 //
1331 // Non formula statistics
1332 //
1333 //////////////////////////////////////////////////////////////////////
1334
1335 /**
1336 * Templatized storage and interface for a distrbution stat.
1337 */
1338 template <typename T>
1339 struct DistStor
1340 {
1341 public:
1342 /** The parameters for a distribution stat. */
1343 struct Params
1344 {
1345 /** The minimum value to track. */
1346 int min;
1347 /** The maximum value to track. */
1348 int max;
1349 /** The number of entries in each bucket. */
1350 int bucket_size;
1351 /** The number of buckets. Equal to (max-min)/bucket_size. */
1352 int size;
1353 };
1354 enum { fancy = false };
1355
1356 private:
1357 /** The smallest value sampled. */
1358 T min_val;
1359 /** The largest value sampled. */
1360 T max_val;
1361 /** The number of values sampled less than min. */
1362 T underflow;
1363 /** The number of values sampled more than max. */
1364 T overflow;
1365 /** The current sum. */
1366 T sum;
1367 /** The sum of squares. */
1368 T squares;
1369 /** The number of samples. */
1370 int samples;
1371 /** Counter for each bucket. */
1372 std::vector<T> vec;
1373
1374 public:
1375 /**
1376 * Construct this storage with the supplied params.
1377 * @param params The parameters.
1378 */
1379 DistStor(const Params &params)
1380 : min_val(INT_MAX), max_val(INT_MIN), underflow(0), overflow(0),
1381 sum(T()), squares(T()), samples(0), vec(params.size)
1382 {
1383 reset();
1384 }
1385
1386 /**
1387 * Add a value to the distribution for the given number of times.
1388 * @param val The value to add.
1389 * @param number The number of times to add the value.
1390 * @param params The paramters of the distribution.
1391 */
1392 void sample(T val, int number, const Params &params)
1393 {
1394 if (val < params.min)
1395 underflow += number;
1396 else if (val > params.max)
1397 overflow += number;
1398 else {
1399 int index = (val - params.min) / params.bucket_size;
1400 assert(index < size(params));
1401 vec[index] += number;
1402 }
1403
1404 if (val < min_val)
1405 min_val = val;
1406
1407 if (val > max_val)
1408 max_val = val;
1409
1410 T sample = val * number;
1411 sum += sample;
1412 squares += sample * sample;
1413 samples += number;
1414 }
1415
1416 /**
1417 * Return the number of buckets in this distribution.
1418 * @return the number of buckets.
1419 * @todo Is it faster to return the size from the parameters?
1420 */
1421 size_t size(const Params &) const { return vec.size(); }
1422
1423 /**
1424 * Returns true if any calls to sample have been made.
1425 * @param params The paramters of the distribution.
1426 * @return True if any values have been sampled.
1427 */
1428 bool zero(const Params &params) const
1429 {
1430 return samples == 0;
1431 }
1432
1433 void update(DistDataData *data, const Params &params)
1434 {
1435 data->min = params.min;
1436 data->max = params.max;
1437 data->bucket_size = params.bucket_size;
1438 data->size = params.size;
1439
1440 data->min_val = (min_val == INT_MAX) ? 0 : min_val;
1441 data->max_val = (max_val == INT_MIN) ? 0 : max_val;
1442 data->underflow = underflow;
1443 data->overflow = overflow;
1444 data->vec.resize(params.size);
1445 for (int i = 0; i < params.size; ++i)
1446 data->vec[i] = vec[i];
1447
1448 data->sum = sum;
1449 data->squares = squares;
1450 data->samples = samples;
1451 }
1452
1453 /**
1454 * Reset stat value to default
1455 */
1456 void reset()
1457 {
1458 min_val = INT_MAX;
1459 max_val = INT_MIN;
1460 underflow = 0;
1461 overflow = 0;
1462
1463 int size = vec.size();
1464 for (int i = 0; i < size; ++i)
1465 vec[i] = T();
1466
1467 sum = T();
1468 squares = T();
1469 samples = T();
1470 }
1471 };
1472
1473 /**
1474 * Templatized storage and interface for a distribution that calculates mean
1475 * and variance.
1476 */
1477 template <typename T>
1478 struct FancyStor
1479 {
1480 public:
1481 /**
1482 * No paramters for this storage.
1483 */
1484 struct Params {};
1485 enum { fancy = true };
1486
1487 private:
1488 /** The current sum. */
1489 T sum;
1490 /** The sum of squares. */
1491 T squares;
1492 /** The number of samples. */
1493 int samples;
1494
1495 public:
1496 /**
1497 * Create and initialize this storage.
1498 */
1499 FancyStor(const Params &) : sum(T()), squares(T()), samples(0) {}
1500
1501 /**
1502 * Add a value the given number of times to this running average.
1503 * Update the running sum and sum of squares, increment the number of
1504 * values seen by the given number.
1505 * @param val The value to add.
1506 * @param number The number of times to add the value.
1507 * @param p The parameters of this stat.
1508 */
1509 void sample(T val, int number, const Params &p)
1510 {
1511 T value = val * number;
1512 sum += value;
1513 squares += value * value;
1514 samples += number;
1515 }
1516
1517 void update(DistDataData *data, const Params &params)
1518 {
1519 data->sum = sum;
1520 data->squares = squares;
1521 data->samples = samples;
1522 }
1523
1524 /**
1525 * Return the number of entries in this stat, 1
1526 * @return 1.
1527 */
1528 size_t size(const Params &) const { return 1; }
1529
1530 /**
1531 * Return true if no samples have been added.
1532 * @return True if no samples have been added.
1533 */
1534 bool zero(const Params &) const { return samples == 0; }
1535
1536 /**
1537 * Reset stat value to default
1538 */
1539 void reset()
1540 {
1541 sum = T();
1542 squares = T();
1543 samples = 0;
1544 }
1545 };
1546
1547 /**
1548 * Templatized storage for distribution that calculates per cycle mean and
1549 * variance.
1550 */
1551 template <typename T>
1552 struct AvgFancy
1553 {
1554 public:
1555 /** No parameters for this storage. */
1556 struct Params {};
1557 enum { fancy = true };
1558
1559 private:
1560 /** Current total. */
1561 T sum;
1562 /** Current sum of squares. */
1563 T squares;
1564
1565 public:
1566 /**
1567 * Create and initialize this storage.
1568 */
1569 AvgFancy(const Params &) : sum(T()), squares(T()) {}
1570
1571 /**
1572 * Add a value to the distribution for the given number of times.
1573 * Update the running sum and sum of squares.
1574 * @param val The value to add.
1575 * @param number The number of times to add the value.
1576 * @param p The paramters of the distribution.
1577 */
1578 void sample(T val, int number, const Params& p)
1579 {
1580 T value = val * number;
1581 sum += value;
1582 squares += value * value;
1583 }
1584
1585 void update(DistDataData *data, const Params &params)
1586 {
1587 data->sum = sum;
1588 data->squares = squares;
1589 data->samples = curTick;
1590 }
1591
1592 /**
1593 * Return the number of entries, in this case 1.
1594 * @return 1.
1595 */
1596 size_t size(const Params &params) const { return 1; }
1597 /**
1598 * Return true if no samples have been added.
1599 * @return True if the sum is zero.
1600 */
1601 bool zero(const Params &params) const { return sum == 0; }
1602 /**
1603 * Reset stat value to default
1604 */
1605 void reset()
1606 {
1607 sum = T();
1608 squares = T();
1609 }
1610 };
1611
1612 /**
1613 * Implementation of a distribution stat. The type of distribution is
1614 * determined by the Storage template. @sa ScalarBase
1615 */
1616 template <typename T, template <typename T> class Storage, class Bin>
1617 class DistBase : public DataAccess
1618 {
1619 public:
1620 /** Define the type of the storage class. */
1621 typedef Storage<T> storage_t;
1622 /** Define the params of the storage class. */
1623 typedef typename storage_t::Params params_t;
1624 /** Define the bin type. */
1625 typedef typename Bin::Bin<storage_t> bin_t;
1626
1627 protected:
1628 /** The bin of this stat. */
1629 bin_t bin;
1630 /** The parameters for this stat. */
1631 params_t params;
1632
1633 protected:
1634 /**
1635 * Retrieve the storage from the bin.
1636 * @return The storage object for this stat.
1637 */
1638 storage_t *data() { return bin.data(params); }
1639 /**
1640 * Retrieve a const pointer to the storage from the bin.
1641 * @return A const pointer to the storage object for this stat.
1642 */
1643 const storage_t *data() const
1644 {
1645 bin_t *_bin = const_cast<bin_t *>(&bin);
1646 params_t *_params = const_cast<params_t *>(&params);
1647 return _bin->data(*_params);
1648 }
1649
1650 protected:
1651 // Copying stats is not allowed
1652 /** Copies are not allowed. */
1653 DistBase(const DistBase &stat);
1654 /** Copies are not allowed. */
1655 const DistBase &operator=(const DistBase &);
1656
1657 public:
1658 DistBase() { }
1659
1660 /**
1661 * Add a value to the distribtion n times. Calls sample on the storage
1662 * class.
1663 * @param v The value to add.
1664 * @param n The number of times to add it, defaults to 1.
1665 */
1666 template <typename U>
1667 void sample(const U& v, int n = 1) { data()->sample(v, n, params); }
1668
1669 /**
1670 * Return the number of entries in this stat.
1671 * @return The number of entries.
1672 */
1673 size_t size() const { return data()->size(params); }
1674 /**
1675 * Return true if no samples have been added.
1676 * @return True if there haven't been any samples.
1677 */
1678 bool zero() const { return data()->zero(params); }
1679
1680 void update(DistDataBase *base)
1681 {
1682 base->data.fancy = storage_t::fancy;
1683 data()->update(&(base->data), params);
1684 }
1685 /**
1686 * @return True is stat is binned.
1687 */
1688 bool binned() const { return bin_t::binned; }
1689 /**
1690 * Reset stat value to default
1691 */
1692 void reset()
1693 {
1694 bin.reset();
1695 }
1696
1697 bool check() { return bin.initialized(); }
1698 };
1699
1700 template <typename T, template <typename T> class Storage, class Bin>
1701 class DistProxy;
1702
1703 template <typename T, template <typename T> class Storage, class Bin>
1704 class VectorDistBase : public DataAccess
1705 {
1706 public:
1707 typedef Storage<T> storage_t;
1708 typedef typename storage_t::Params params_t;
1709 typedef typename Bin::VectorBin<storage_t> bin_t;
1710
1711 protected:
1712 bin_t bin;
1713 params_t params;
1714
1715 protected:
1716 storage_t *data(int index) { return bin.data(index, params); }
1717 const storage_t *data(int index) const
1718 {
1719 bin_t *_bin = const_cast<bin_t *>(&bin);
1720 params_t *_params = const_cast<params_t *>(&params);
1721 return _bin->data(index, *_params);
1722 }
1723
1724 protected:
1725 // Copying stats is not allowed
1726 VectorDistBase(const VectorDistBase &stat);
1727 const VectorDistBase &operator=(const VectorDistBase &);
1728
1729 public:
1730 VectorDistBase() {}
1731
1732 friend class DistProxy<T, Storage, Bin>;
1733 DistProxy<T, Storage, Bin> operator[](int index);
1734 const DistProxy<T, Storage, Bin> operator[](int index) const;
1735
1736 size_t size() const { return bin.size(); }
1737 bool zero() const { return false; }
1738 /**
1739 * Return true if stat is binned.
1740 *@return True is stat is binned.
1741 */
1742 bool binned() const { return bin_t::binned; }
1743 /**
1744 * Reset stat value to default
1745 */
1746 void reset() { bin.reset(); }
1747
1748 bool check() { return bin.initialized(); }
1749 void update(VectorDistDataBase *base)
1750 {
1751 int size = this->size();
1752 base->data.resize(size);
1753 for (int i = 0; i < size; ++i) {
1754 base->data[i].fancy = storage_t::fancy;
1755 data(i)->update(&(base->data[i]), params);
1756 }
1757 }
1758 };
1759
1760 template <typename T, template <typename T> class Storage, class Bin>
1761 class DistProxy
1762 {
1763 public:
1764 typedef Storage<T> storage_t;
1765 typedef typename storage_t::Params params_t;
1766 typedef typename Bin::Bin<storage_t> bin_t;
1767 typedef VectorDistBase<T, Storage, Bin> base_t;
1768
1769 private:
1770 union {
1771 base_t *stat;
1772 const base_t *cstat;
1773 };
1774 int index;
1775
1776 protected:
1777 storage_t *data() { return stat->data(index); }
1778 const storage_t *data() const { return cstat->data(index); }
1779
1780 public:
1781 DistProxy(const VectorDistBase<T, Storage, Bin> &s, int i)
1782 : cstat(&s), index(i) {}
1783 DistProxy(const DistProxy &sp)
1784 : cstat(sp.cstat), index(sp.index) {}
1785 const DistProxy &operator=(const DistProxy &sp) {
1786 cstat = sp.cstat; index = sp.index; return *this;
1787 }
1788
1789 public:
1790 template <typename U>
1791 void sample(const U& v, int n = 1) { data()->sample(v, n, cstat->params); }
1792
1793 size_t size() const { return 1; }
1794 bool zero() const { return data()->zero(cstat->params); }
1795 /**
1796 * Return true if stat is binned.
1797 *@return false since Proxies are not binned/printed.
1798 */
1799 bool binned() const { return false; }
1800 /**
1801 * Proxy has no state. Nothing to reset.
1802 */
1803 void reset() { }
1804 };
1805
1806 template <typename T, template <typename T> class Storage, class Bin>
1807 inline DistProxy<T, Storage, Bin>
1808 VectorDistBase<T, Storage, Bin>::operator[](int index)
1809 {
1810 assert (index >= 0 && index < size());
1811 return DistProxy<T, Storage, Bin>(*this, index);
1812 }
1813
1814 template <typename T, template <typename T> class Storage, class Bin>
1815 inline const DistProxy<T, Storage, Bin>
1816 VectorDistBase<T, Storage, Bin>::operator[](int index) const
1817 {
1818 assert (index >= 0 && index < size());
1819 return DistProxy<T, Storage, Bin>(*this, index);
1820 }
1821
1822 #if 0
1823 template <typename T, template <typename T> class Storage, class Bin>
1824 result_t
1825 VectorDistBase<T, Storage, Bin>::total(int index) const
1826 {
1827 int total = 0;
1828 for (int i=0; i < x_size(); ++i) {
1829 total += data(i)->val(*params);
1830 }
1831 }
1832 #endif
1833
1834 //////////////////////////////////////////////////////////////////////
1835 //
1836 // Formula Details
1837 //
1838 //////////////////////////////////////////////////////////////////////
1839
1840 /**
1841 * Base class for formula statistic node. These nodes are used to build a tree
1842 * that represents the formula.
1843 */
1844 class Node : public RefCounted
1845 {
1846 public:
1847 /**
1848 * Return the number of nodes in the subtree starting at this node.
1849 * @return the number of nodes in this subtree.
1850 */
1851 virtual size_t size() const = 0;
1852 /**
1853 * Return the result vector of this subtree.
1854 * @return The result vector of this subtree.
1855 */
1856 virtual const rvec_t &val() const = 0;
1857 /**
1858 * Return the total of the result vector.
1859 * @return The total of the result vector.
1860 */
1861 virtual result_t total() const = 0;
1862 /**
1863 * Return true if stat is binned.
1864 *@return True is stat is binned.
1865 */
1866 virtual bool binned() const = 0;
1867
1868 /**
1869 *
1870 */
1871 virtual std::string str() const = 0;
1872 };
1873
1874 /** Reference counting pointer to a function Node. */
1875 typedef RefCountingPtr<Node> NodePtr;
1876
1877 class ScalarStatNode : public Node
1878 {
1879 private:
1880 const ScalarDataBase *data;
1881 mutable rvec_t result;
1882
1883 public:
1884 ScalarStatNode(const ScalarDataBase *d) : data(d), result(1) {}
1885 virtual const rvec_t &val() const
1886 {
1887 result[0] = data->val();
1888 return result;
1889 }
1890 virtual result_t total() const { return data->val(); };
1891
1892 virtual size_t size() const { return 1; }
1893 /**
1894 * Return true if stat is binned.
1895 *@return True is stat is binned.
1896 */
1897 virtual bool binned() const { return data->binned(); }
1898
1899 /**
1900 *
1901 */
1902 virtual std::string str() const { return data->name; }
1903 };
1904
1905 template <typename T, template <typename T> class Storage, class Bin>
1906 class ScalarProxyNode : public Node
1907 {
1908 private:
1909 const ScalarProxy<T, Storage, Bin> proxy;
1910 mutable rvec_t result;
1911
1912 public:
1913 ScalarProxyNode(const ScalarProxy<T, Storage, Bin> &p)
1914 : proxy(p), result(1) { }
1915 virtual const rvec_t &val() const
1916 {
1917 result[0] = proxy.val();
1918 return result;
1919 }
1920 virtual result_t total() const { return proxy.val(); };
1921
1922 virtual size_t size() const { return 1; }
1923 /**
1924 * Return true if stat is binned.
1925 *@return True is stat is binned.
1926 */
1927 virtual bool binned() const { return proxy.binned(); }
1928
1929 /**
1930 *
1931 */
1932 virtual std::string str() const { return proxy.str(); }
1933 };
1934
1935 class VectorStatNode : public Node
1936 {
1937 private:
1938 const VectorDataBase *data;
1939
1940 public:
1941 VectorStatNode(const VectorDataBase *d) : data(d) { }
1942 virtual const rvec_t &val() const { return data->val(); }
1943 virtual result_t total() const { return data->total(); };
1944
1945 virtual size_t size() const { return data->size(); }
1946 /**
1947 * Return true if stat is binned.
1948 *@return True is stat is binned.
1949 */
1950 virtual bool binned() const { return data->binned(); }
1951
1952 virtual std::string str() const { return data->name; }
1953 };
1954
1955 template <typename T>
1956 class ConstNode : public Node
1957 {
1958 private:
1959 rvec_t data;
1960
1961 public:
1962 ConstNode(T s) : data(1, (result_t)s) {}
1963 const rvec_t &val() const { return data; }
1964 virtual result_t total() const { return data[0]; };
1965
1966 virtual size_t size() const { return 1; }
1967 /**
1968 * Return true if stat is binned.
1969 *@return False since constants aren't binned.
1970 */
1971 virtual bool binned() const { return false; }
1972
1973 virtual std::string str() const { return to_string(data[0]); }
1974 };
1975
1976 template <typename T>
1977 class FunctorNode : public Node
1978 {
1979 private:
1980 T &functor;
1981 mutable rvec_t result;
1982
1983 public:
1984 FunctorNode(T &f) : functor(f) { result.resize(1); }
1985 const rvec_t &val() const {
1986 result[0] = (result_t)functor();
1987 return result;
1988 }
1989 virtual result_t total() const { return (result_t)functor(); };
1990
1991 virtual size_t size() const { return 1; }
1992 /**
1993 * Return true if stat is binned.
1994 *@return False since Functors aren't binned
1995 */
1996 virtual bool binned() const { return false; }
1997 virtual std::string str() const { return to_string(functor()); }
1998 };
1999
2000 template <typename T>
2001 class ScalarNode : public Node
2002 {
2003 private:
2004 T &scalar;
2005 mutable rvec_t result;
2006
2007 public:
2008 ScalarNode(T &s) : scalar(s) { result.resize(1); }
2009 const rvec_t &val() const {
2010 result[0] = (result_t)scalar;
2011 return result;
2012 }
2013 virtual result_t total() const { return (result_t)scalar; };
2014
2015 virtual size_t size() const { return 1; }
2016 /**
2017 * Return true if stat is binned.
2018 *@return False since Scalar's aren't binned
2019 */
2020 virtual bool binned() const { return false; }
2021 virtual std::string str() const { return to_string(scalar); }
2022 };
2023
2024 template <class Op>
2025 struct OpString;
2026
2027 template<>
2028 struct OpString<std::plus<result_t> >
2029 {
2030 static std::string str() { return "+"; }
2031 };
2032
2033 template<>
2034 struct OpString<std::minus<result_t> >
2035 {
2036 static std::string str() { return "-"; }
2037 };
2038
2039 template<>
2040 struct OpString<std::multiplies<result_t> >
2041 {
2042 static std::string str() { return "*"; }
2043 };
2044
2045 template<>
2046 struct OpString<std::divides<result_t> >
2047 {
2048 static std::string str() { return "/"; }
2049 };
2050
2051 template<>
2052 struct OpString<std::modulus<result_t> >
2053 {
2054 static std::string str() { return "%"; }
2055 };
2056
2057 template<>
2058 struct OpString<std::negate<result_t> >
2059 {
2060 static std::string str() { return "-"; }
2061 };
2062
2063 template <class Op>
2064 class UnaryNode : public Node
2065 {
2066 public:
2067 NodePtr l;
2068 mutable rvec_t result;
2069
2070 public:
2071 UnaryNode(NodePtr p) : l(p) {}
2072
2073 const rvec_t &val() const {
2074 const rvec_t &lvec = l->val();
2075 int size = lvec.size();
2076
2077 assert(size > 0);
2078
2079 result.resize(size);
2080 Op op;
2081 for (int i = 0; i < size; ++i)
2082 result[i] = op(lvec[i]);
2083
2084 return result;
2085 }
2086
2087 result_t total() const {
2088 Op op;
2089 return op(l->total());
2090 }
2091
2092 virtual size_t size() const { return l->size(); }
2093 /**
2094 * Return true if child of node is binned.
2095 *@return True if child of node is binned.
2096 */
2097 virtual bool binned() const { return l->binned(); }
2098
2099 virtual std::string str() const
2100 {
2101 return OpString<Op>::str() + l->str();
2102 }
2103 };
2104
2105 template <class Op>
2106 class BinaryNode : public Node
2107 {
2108 public:
2109 NodePtr l;
2110 NodePtr r;
2111 mutable rvec_t result;
2112
2113 public:
2114 BinaryNode(NodePtr a, NodePtr b) : l(a), r(b) {}
2115
2116 const rvec_t &val() const {
2117 Op op;
2118 const rvec_t &lvec = l->val();
2119 const rvec_t &rvec = r->val();
2120
2121 assert(lvec.size() > 0 && rvec.size() > 0);
2122
2123 if (lvec.size() == 1 && rvec.size() == 1) {
2124 result.resize(1);
2125 result[0] = op(lvec[0], rvec[0]);
2126 } else if (lvec.size() == 1) {
2127 int size = rvec.size();
2128 result.resize(size);
2129 for (int i = 0; i < size; ++i)
2130 result[i] = op(lvec[0], rvec[i]);
2131 } else if (rvec.size() == 1) {
2132 int size = lvec.size();
2133 result.resize(size);
2134 for (int i = 0; i < size; ++i)
2135 result[i] = op(lvec[i], rvec[0]);
2136 } else if (rvec.size() == lvec.size()) {
2137 int size = rvec.size();
2138 result.resize(size);
2139 for (int i = 0; i < size; ++i)
2140 result[i] = op(lvec[i], rvec[i]);
2141 }
2142
2143 return result;
2144 }
2145
2146 result_t total() const {
2147 Op op;
2148 return op(l->total(), r->total());
2149 }
2150
2151 virtual size_t size() const {
2152 int ls = l->size();
2153 int rs = r->size();
2154 if (ls == 1)
2155 return rs;
2156 else if (rs == 1)
2157 return ls;
2158 else {
2159 assert(ls == rs && "Node vector sizes are not equal");
2160 return ls;
2161 }
2162 }
2163 /**
2164 * Return true if any children of node are binned
2165 *@return True if either child of node is binned.
2166 */
2167 virtual bool binned() const { return (l->binned() || r->binned()); }
2168
2169 virtual std::string str() const
2170 {
2171 return csprintf("(%s %s %s)", l->str(), OpString<Op>::str(), r->str());
2172 }
2173 };
2174
2175 template <class Op>
2176 class SumNode : public Node
2177 {
2178 public:
2179 NodePtr l;
2180 mutable rvec_t result;
2181
2182 public:
2183 SumNode(NodePtr p) : l(p), result(1) {}
2184
2185 const rvec_t &val() const {
2186 const rvec_t &lvec = l->val();
2187 int size = lvec.size();
2188 assert(size > 0);
2189
2190 result[0] = 0.0;
2191
2192 Op op;
2193 for (int i = 0; i < size; ++i)
2194 result[0] = op(result[0], lvec[i]);
2195
2196 return result;
2197 }
2198
2199 result_t total() const {
2200 const rvec_t &lvec = l->val();
2201 int size = lvec.size();
2202 assert(size > 0);
2203
2204 result_t result = 0.0;
2205
2206 Op op;
2207 for (int i = 0; i < size; ++i)
2208 result = op(result, lvec[i]);
2209
2210 return result;
2211 }
2212
2213 virtual size_t size() const { return 1; }
2214 /**
2215 * Return true if child of node is binned.
2216 *@return True if child of node is binned.
2217 */
2218 virtual bool binned() const { return l->binned(); }
2219
2220 virtual std::string str() const
2221 {
2222 return csprintf("total(%s)", l->str());
2223 }
2224 };
2225
2226 //////////////////////////////////////////////////////////////////////
2227 //
2228 // Binning Interface
2229 //
2230 //////////////////////////////////////////////////////////////////////
2231 struct MainBin
2232 {
2233 class BinBase;
2234 friend class MainBin::BinBase;
2235
2236 private:
2237 std::string _name;
2238 char *mem;
2239
2240 protected:
2241 off_t memsize;
2242 off_t size() const { return memsize; }
2243 char *memory(off_t off);
2244
2245 public:
2246 static MainBin *&curBin()
2247 {
2248 static MainBin *current = NULL;
2249 return current;
2250 }
2251
2252 static void setCurBin(MainBin *bin) { curBin() = bin; }
2253 static MainBin *current() { assert(curBin()); return curBin(); }
2254
2255 static off_t &offset()
2256 {
2257 static off_t offset = 0;
2258 return offset;
2259 }
2260
2261 static off_t new_offset(size_t size)
2262 {
2263 size_t mask = sizeof(u_int64_t) - 1;
2264 off_t off = offset();
2265
2266 // That one is for the last trailing flags byte.
2267 offset() += (size + 1 + mask) & ~mask;
2268 return off;
2269 }
2270
2271 public:
2272 MainBin(const std::string &name);
2273 ~MainBin();
2274
2275 const std::string &
2276 name() const
2277 {
2278 return _name;
2279 }
2280
2281 void
2282 activate()
2283 {
2284 setCurBin(this);
2285 }
2286
2287 class BinBase
2288 {
2289 private:
2290 int offset;
2291
2292 public:
2293 BinBase() : offset(-1) {}
2294 void allocate(size_t size)
2295 {
2296 offset = new_offset(size);
2297 }
2298 char *access()
2299 {
2300 assert(offset != -1);
2301 return current()->memory(offset);
2302 }
2303 };
2304
2305 template <class Storage>
2306 class Bin : public BinBase
2307 {
2308 public:
2309 typedef typename Storage::Params Params;
2310
2311 public:
2312 enum { binned = true };
2313 Bin() { allocate(sizeof(Storage)); }
2314 bool initialized() const { return true; }
2315 void init(Params &params) { }
2316
2317 int size() const { return 1; }
2318
2319 Storage *
2320 data(Params &params)
2321 {
2322 assert(initialized());
2323 char *ptr = access();
2324 char *flags = ptr + sizeof(Storage);
2325 if (!(*flags & 0x1)) {
2326 *flags |= 0x1;
2327 new (ptr) Storage(params);
2328 }
2329 return reinterpret_cast<Storage *>(ptr);
2330 }
2331
2332 void
2333 reset()
2334 {
2335 char *ptr = access();
2336 char *flags = ptr + size() * sizeof(Storage);
2337 if (!(*flags & 0x1))
2338 return;
2339
2340 Storage *s = reinterpret_cast<Storage *>(ptr);
2341 s->reset();
2342 }
2343 };
2344
2345 template <class Storage>
2346 class VectorBin : public BinBase
2347 {
2348 public:
2349 typedef typename Storage::Params Params;
2350
2351 private:
2352 int _size;
2353
2354 public:
2355 enum { binned = true };
2356 VectorBin() : _size(0) {}
2357
2358 bool initialized() const { return _size > 0; }
2359 void init(int s, Params &params)
2360 {
2361 assert(!initialized());
2362 assert(s > 0);
2363 _size = s;
2364 allocate(_size * sizeof(Storage));
2365 }
2366
2367 int size() const { return _size; }
2368
2369 Storage *data(int index, Params &params)
2370 {
2371 assert(initialized());
2372 assert(index >= 0 && index < size());
2373 char *ptr = access();
2374 char *flags = ptr + size() * sizeof(Storage);
2375 if (!(*flags & 0x1)) {
2376 *flags |= 0x1;
2377 for (int i = 0; i < size(); ++i)
2378 new (ptr + i * sizeof(Storage)) Storage(params);
2379 }
2380 return reinterpret_cast<Storage *>(ptr + index * sizeof(Storage));
2381 }
2382 void reset()
2383 {
2384 char *ptr = access();
2385 char *flags = ptr + size() * sizeof(Storage);
2386 if (!(*flags & 0x1))
2387 return;
2388
2389 for (int i = 0; i < _size; ++i) {
2390 char *p = ptr + i * sizeof(Storage);
2391 Storage *s = reinterpret_cast<Storage *>(p);
2392 s->reset();
2393 }
2394 }
2395 };
2396 };
2397
2398 struct NoBin
2399 {
2400 template <class Storage>
2401 struct Bin
2402 {
2403 public:
2404 typedef typename Storage::Params Params;
2405 enum { binned = false };
2406
2407 private:
2408 char ptr[sizeof(Storage)];
2409
2410 public:
2411 ~Bin()
2412 {
2413 reinterpret_cast<Storage *>(ptr)->~Storage();
2414 }
2415
2416 bool initialized() const { return true; }
2417 void init(Params &params)
2418 {
2419 new (ptr) Storage(params);
2420 }
2421 int size() const{ return 1; }
2422 Storage *data(Params &params)
2423 {
2424 assert(initialized());
2425 return reinterpret_cast<Storage *>(ptr);
2426 }
2427 void reset()
2428 {
2429 Storage *s = reinterpret_cast<Storage *>(ptr);
2430 s->reset();
2431 }
2432 };
2433
2434 template <class Storage>
2435 struct VectorBin
2436 {
2437 public:
2438 typedef typename Storage::Params Params;
2439 enum { binned = false };
2440
2441 private:
2442 char *ptr;
2443 int _size;
2444
2445 public:
2446 VectorBin() : ptr(NULL) { }
2447 ~VectorBin()
2448 {
2449 if (!initialized())
2450 return;
2451
2452 for (int i = 0; i < _size; ++i) {
2453 char *p = ptr + i * sizeof(Storage);
2454 reinterpret_cast<Storage *>(p)->~Storage();
2455 }
2456 delete [] ptr;
2457 }
2458
2459 bool initialized() const { return ptr != NULL; }
2460 void init(int s, Params &params)
2461 {
2462 assert(s > 0 && "size must be positive!");
2463 assert(!initialized());
2464 _size = s;
2465 ptr = new char[_size * sizeof(Storage)];
2466 for (int i = 0; i < _size; ++i)
2467 new (ptr + i * sizeof(Storage)) Storage(params);
2468 }
2469
2470 int size() const { return _size; }
2471
2472 Storage *data(int index, Params &params)
2473 {
2474 assert(initialized());
2475 assert(index >= 0 && index < size());
2476 return reinterpret_cast<Storage *>(ptr + index * sizeof(Storage));
2477 }
2478 void reset()
2479 {
2480 for (int i = 0; i < _size; ++i) {
2481 char *p = ptr + i * sizeof(Storage);
2482 Storage *s = reinterpret_cast<Storage *>(p);
2483 s->reset();
2484 }
2485 }
2486 };
2487 };
2488
2489 //////////////////////////////////////////////////////////////////////
2490 //
2491 // Visible Statistics Types
2492 //
2493 //////////////////////////////////////////////////////////////////////
2494 /**
2495 * @defgroup VisibleStats "Statistic Types"
2496 * These are the statistics that are used in the simulator. By default these
2497 * store counters and don't use binning, but are templatized to accept any type
2498 * and any Bin class.
2499 * @{
2500 */
2501
2502 /**
2503 * This is an easy way to assign all your stats to be binned or not
2504 * binned. If the typedef is NoBin, nothing is binned. If it is
2505 * MainBin, then all stats are binned under that Bin.
2506 */
2507 #ifdef FS_MEASURE
2508 typedef MainBin DefaultBin;
2509 #else
2510 typedef NoBin DefaultBin;
2511 #endif
2512
2513 /**
2514 * This is a simple scalar statistic, like a counter.
2515 * @sa Stat, ScalarBase, StatStor
2516 */
2517 template <typename T = Counter, class Bin = DefaultBin>
2518 class Scalar
2519 : public Wrap<Scalar<T, Bin>,
2520 ScalarBase<T, StatStor, Bin>,
2521 ScalarData>
2522 {
2523 public:
2524 /** The base implementation. */
2525 typedef ScalarBase<T, StatStor, Bin> Base;
2526
2527 Scalar()
2528 {
2529 setInit();
2530 }
2531
2532 /**
2533 * Sets the stat equal to the given value. Calls the base implementation
2534 * of operator=
2535 * @param v The new value.
2536 */
2537 template <typename U>
2538 void operator=(const U& v) { Base::operator=(v); }
2539 };
2540
2541 /**
2542 * A stat that calculates the per cycle average of a value.
2543 * @sa Stat, ScalarBase, AvgStor
2544 */
2545 template <typename T = Counter, class Bin = DefaultBin>
2546 class Average
2547 : public Wrap<Average<T, Bin>,
2548 ScalarBase<T, AvgStor, Bin>,
2549 ScalarData>
2550 {
2551 public:
2552 /** The base implementation. */
2553 typedef ScalarBase<T, AvgStor, Bin> Base;
2554
2555 Average()
2556 {
2557 setInit();
2558 }
2559
2560 /**
2561 * Sets the stat equal to the given value. Calls the base implementation
2562 * of operator=
2563 * @param v The new value.
2564 */
2565 template <typename U>
2566 void operator=(const U& v) { Base::operator=(v); }
2567 };
2568
2569 /**
2570 * A vector of scalar stats.
2571 * @sa Stat, VectorBase, StatStor
2572 */
2573 template <typename T = Counter, class Bin = DefaultBin>
2574 class Vector
2575 : public WrapVec<Vector<T, Bin>,
2576 VectorBase<T, StatStor, Bin>,
2577 VectorData>
2578 {
2579 public:
2580 /** The base implementation. */
2581 typedef ScalarBase<T, StatStor, Bin> Base;
2582
2583 /**
2584 * Set this vector to have the given size.
2585 * @param size The new size.
2586 * @return A reference to this stat.
2587 */
2588 Vector &init(size_t size) {
2589 bin.init(size, params);
2590 setInit();
2591
2592 return *this;
2593 }
2594 };
2595
2596 /**
2597 * A vector of Average stats.
2598 * @sa Stat, VectorBase, AvgStor
2599 */
2600 template <typename T = Counter, class Bin = DefaultBin>
2601 class AverageVector
2602 : public WrapVec<AverageVector<T, Bin>,
2603 VectorBase<T, AvgStor, Bin>,
2604 VectorData>
2605 {
2606 public:
2607 /**
2608 * Set this vector to have the given size.
2609 * @param size The new size.
2610 * @return A reference to this stat.
2611 */
2612 AverageVector &init(size_t size) {
2613 bin.init(size, params);
2614 setInit();
2615
2616 return *this;
2617 }
2618 };
2619
2620 /**
2621 * A 2-Dimensional vecto of scalar stats.
2622 * @sa Stat, Vector2dBase, StatStor
2623 */
2624 template <typename T = Counter, class Bin = DefaultBin>
2625 class Vector2d
2626 : public WrapVec2d<Vector2d<T, Bin>,
2627 Vector2dBase<T, StatStor, Bin>,
2628 Vector2dData>
2629 {
2630 public:
2631 Vector2d &init(size_t _x, size_t _y) {
2632 statData()->x = x = _x;
2633 statData()->y = y = _y;
2634 bin.init(x * y, params);
2635 setInit();
2636
2637 return *this;
2638 }
2639 };
2640
2641 /**
2642 * A simple distribution stat.
2643 * @sa Stat, DistBase, DistStor
2644 */
2645 template <typename T = Counter, class Bin = DefaultBin>
2646 class Distribution
2647 : public Wrap<Distribution<T, Bin>,
2648 DistBase<T, DistStor, Bin>,
2649 DistData>
2650 {
2651 public:
2652 /** Base implementation. */
2653 typedef DistBase<T, DistStor, Bin> Base;
2654 /** The Parameter type. */
2655 typedef typename DistStor<T>::Params Params;
2656
2657 public:
2658 /**
2659 * Set the parameters of this distribution. @sa DistStor::Params
2660 * @param min The minimum value of the distribution.
2661 * @param max The maximum value of the distribution.
2662 * @param bkt The number of values in each bucket.
2663 * @return A reference to this distribution.
2664 */
2665 Distribution &init(T min, T max, int bkt) {
2666 params.min = min;
2667 params.max = max;
2668 params.bucket_size = bkt;
2669 params.size = (max - min) / bkt + 1;
2670 bin.init(params);
2671 setInit();
2672
2673 return *this;
2674 }
2675 };
2676
2677 /**
2678 * Calculates the mean and variance of all the samples.
2679 * @sa Stat, DistBase, FancyStor
2680 */
2681 template <typename T = Counter, class Bin = DefaultBin>
2682 class StandardDeviation
2683 : public Wrap<StandardDeviation<T, Bin>,
2684 DistBase<T, FancyStor, Bin>,
2685 DistData>
2686 {
2687 public:
2688 /** The base implementation */
2689 typedef DistBase<T, DistStor, Bin> Base;
2690 /** The parameter type. */
2691 typedef typename DistStor<T>::Params Params;
2692
2693 public:
2694 /**
2695 * Construct and initialize this distribution.
2696 */
2697 StandardDeviation() {
2698 bin.init(params);
2699 setInit();
2700 }
2701 };
2702
2703 /**
2704 * Calculates the per cycle mean and variance of the samples.
2705 * @sa Stat, DistBase, AvgFancy
2706 */
2707 template <typename T = Counter, class Bin = DefaultBin>
2708 class AverageDeviation
2709 : public Wrap<AverageDeviation<T, Bin>,
2710 DistBase<T, AvgFancy, Bin>,
2711 DistData>
2712 {
2713 public:
2714 /** The base implementation */
2715 typedef DistBase<T, DistStor, Bin> Base;
2716 /** The parameter type. */
2717 typedef typename DistStor<T>::Params Params;
2718
2719 public:
2720 /**
2721 * Construct and initialize this distribution.
2722 */
2723 AverageDeviation()
2724 {
2725 bin.init(params);
2726 setInit();
2727 }
2728 };
2729
2730 /**
2731 * A vector of distributions.
2732 * @sa Stat, VectorDistBase, DistStor
2733 */
2734 template <typename T = Counter, class Bin = DefaultBin>
2735 class VectorDistribution
2736 : public WrapVec<VectorDistribution<T, Bin>,
2737 VectorDistBase<T, DistStor, Bin>,
2738 VectorDistData>
2739 {
2740 public:
2741 /** The base implementation */
2742 typedef VectorDistBase<T, DistStor, Bin> Base;
2743 /** The parameter type. */
2744 typedef typename DistStor<T>::Params Params;
2745
2746 public:
2747 /**
2748 * Initialize storage and parameters for this distribution.
2749 * @param size The size of the vector (the number of distributions).
2750 * @param min The minimum value of the distribution.
2751 * @param max The maximum value of the distribution.
2752 * @param bkt The number of values in each bucket.
2753 * @return A reference to this distribution.
2754 */
2755 VectorDistribution &init(int size, T min, T max, int bkt) {
2756 params.min = min;
2757 params.max = max;
2758 params.bucket_size = bkt;
2759 params.size = (max - min) / bkt + 1;
2760 bin.init(size, params);
2761 setInit();
2762
2763 return *this;
2764 }
2765 };
2766
2767 /**
2768 * This is a vector of StandardDeviation stats.
2769 * @sa Stat, VectorDistBase, FancyStor
2770 */
2771 template <typename T = Counter, class Bin = DefaultBin>
2772 class VectorStandardDeviation
2773 : public WrapVec<VectorStandardDeviation<T, Bin>,
2774 VectorDistBase<T, FancyStor, Bin>,
2775 VectorDistData>
2776 {
2777 public:
2778 /** The base implementation */
2779 typedef VectorDistBase<T, FancyStor, Bin> Base;
2780 /** The parameter type. */
2781 typedef typename DistStor<T>::Params Params;
2782
2783 public:
2784 /**
2785 * Initialize storage for this distribution.
2786 * @param size The size of the vector.
2787 * @return A reference to this distribution.
2788 */
2789 VectorStandardDeviation &init(int size) {
2790 bin.init(size, params);
2791 setInit();
2792
2793 return *this;
2794 }
2795 };
2796
2797 /**
2798 * This is a vector of AverageDeviation stats.
2799 * @sa Stat, VectorDistBase, AvgFancy
2800 */
2801 template <typename T = Counter, class Bin = DefaultBin>
2802 class VectorAverageDeviation
2803 : public WrapVec<VectorAverageDeviation<T, Bin>,
2804 VectorDistBase<T, AvgFancy, Bin>,
2805 VectorDistData>
2806 {
2807 public:
2808 /** The base implementation */
2809 typedef VectorDistBase<T, AvgFancy, Bin> Base;
2810 /** The parameter type. */
2811 typedef typename DistStor<T>::Params Params;
2812
2813 public:
2814 /**
2815 * Initialize storage for this distribution.
2816 * @param size The size of the vector.
2817 * @return A reference to this distribution.
2818 */
2819 VectorAverageDeviation &init(int size) {
2820 bin.init(size, params);
2821 setInit();
2822
2823 return *this;
2824 }
2825 };
2826
2827 /**
2828 * A formula for statistics that is calculated when printed. A formula is
2829 * stored as a tree of Nodes that represent the equation to calculate.
2830 * @sa Stat, ScalarStat, VectorStat, Node, Temp
2831 */
2832 class FormulaBase : public DataAccess
2833 {
2834 protected:
2835 /** The root of the tree which represents the Formula */
2836 NodePtr root;
2837 friend class Temp;
2838
2839 public:
2840 /**
2841 * Return the result of the Fomula in a vector. If there were no Vector
2842 * components to the Formula, then the vector is size 1. If there were,
2843 * like x/y with x being a vector of size 3, then the result returned will
2844 * be x[0]/y, x[1]/y, x[2]/y, respectively.
2845 * @return The result vector.
2846 */
2847 void val(rvec_t &vec) const;
2848
2849 /**
2850 * Return the total Formula result. If there is a Vector
2851 * component to this Formula, then this is the result of the
2852 * Formula if the formula is applied after summing all the
2853 * components of the Vector. For example, if Formula is x/y where
2854 * x is size 3, then total() will return (x[1]+x[2]+x[3])/y. If
2855 * there is no Vector component, total() returns the same value as
2856 * the first entry in the rvec_t val() returns.
2857 * @return The total of the result vector.
2858 */
2859 result_t total() const;
2860
2861 /**
2862 * Return the number of elements in the tree.
2863 */
2864 size_t size() const;
2865
2866 /**
2867 * Return true if Formula is binned. i.e. any of its children
2868 * nodes are binned
2869 * @return True if Formula is binned.
2870 */
2871 bool binned() const;
2872
2873 bool check() const { return true; }
2874
2875 /**
2876 * Formulas don't need to be reset
2877 */
2878 void reset();
2879
2880 /**
2881 *
2882 */
2883 bool zero() const;
2884
2885 /**
2886 *
2887 */
2888 void update(StatData *);
2889
2890 std::string str() const;
2891 };
2892
2893 class FormulaDataBase : public VectorDataBase
2894 {
2895 public:
2896 virtual std::string str() const = 0;
2897 virtual bool check() const { return true; }
2898 virtual void python(Python &py) const;
2899 };
2900
2901 template <class T>
2902 class FormulaData : public FormulaDataBase
2903 {
2904 protected:
2905 T &s;
2906 mutable rvec_t vec;
2907
2908 public:
2909 FormulaData(T &stat) : s(stat) {}
2910
2911 virtual bool binned() const { return s.binned(); }
2912 virtual bool zero() const { return s.zero(); }
2913 virtual void reset() { s.reset(); }
2914
2915 virtual size_t size() const { return s.size(); }
2916 virtual const rvec_t &val() const
2917 {
2918 s.val(vec);
2919 return vec;
2920 }
2921 virtual result_t total() const { return s.total(); }
2922 virtual void update()
2923 {
2924 VectorDataBase::update();
2925 s.update(this);
2926 }
2927 virtual std::string str() const { return s.str(); }
2928 };
2929
2930 class Temp;
2931 class Formula
2932 : public WrapVec<Formula,
2933 FormulaBase,
2934 VectorData>
2935 {
2936 public:
2937 /**
2938 * Create and initialize thie formula, and register it with the database.
2939 */
2940 Formula();
2941
2942 /**
2943 * Create a formula with the given root node, register it with the
2944 * database.
2945 * @param r The root of the expression tree.
2946 */
2947 Formula(Temp r);
2948
2949 /**
2950 * Set an unitialized Formula to the given root.
2951 * @param r The root of the expression tree.
2952 * @return a reference to this formula.
2953 */
2954 const Formula &operator=(Temp r);
2955
2956 /**
2957 * Add the given tree to the existing one.
2958 * @param r The root of the expression tree.
2959 * @return a reference to this formula.
2960 */
2961 const Formula &operator+=(Temp r);
2962 };
2963
2964 class FormulaNode : public Node
2965 {
2966 private:
2967 const Formula &formula;
2968 mutable rvec_t vec;
2969
2970 public:
2971 FormulaNode(const Formula &f) : formula(f) {}
2972
2973 virtual size_t size() const { return formula.size(); }
2974 virtual const rvec_t &val() const { formula.val(vec); return vec; }
2975 virtual result_t total() const { return formula.total(); }
2976 virtual bool binned() const { return formula.binned(); }
2977
2978 virtual std::string str() const { return formula.str(); }
2979 };
2980
2981 /**
2982 * Helper class to construct formula node trees.
2983 */
2984 class Temp
2985 {
2986 protected:
2987 /**
2988 * Pointer to a Node object.
2989 */
2990 NodePtr node;
2991
2992 public:
2993 /**
2994 * Copy the given pointer to this class.
2995 * @param n A pointer to a Node object to copy.
2996 */
2997 Temp(NodePtr n) : node(n) { }
2998
2999 /**
3000 * Return the node pointer.
3001 * @return the node pointer.
3002 */
3003 operator NodePtr() { return node;}
3004
3005 public:
3006 /**
3007 * Create a new ScalarStatNode.
3008 * @param s The ScalarStat to place in a node.
3009 */
3010 template <typename T, class Bin>
3011 Temp(const Scalar<T, Bin> &s)
3012 : node(new ScalarStatNode(s.statData())) { }
3013
3014 /**
3015 * Create a new ScalarStatNode.
3016 * @param s The ScalarStat to place in a node.
3017 */
3018 template <typename T, class Bin>
3019 Temp(const Average<T, Bin> &s)
3020 : node(new ScalarStatNode(s.statData())) { }
3021
3022 /**
3023 * Create a new VectorStatNode.
3024 * @param s The VectorStat to place in a node.
3025 */
3026 template <typename T, class Bin>
3027 Temp(const Vector<T, Bin> &s)
3028 : node(new VectorStatNode(s.statData())) { }
3029
3030 /**
3031 *
3032 */
3033 Temp(const Formula &f)
3034 : node(new FormulaNode(f)) { }
3035
3036 /**
3037 * Create a new ScalarProxyNode.
3038 * @param p The ScalarProxy to place in a node.
3039 */
3040 template <typename T, template <typename T> class Storage, class Bin>
3041 Temp(const ScalarProxy<T, Storage, Bin> &p)
3042 : node(new ScalarProxyNode<T, Storage, Bin>(p)) { }
3043
3044 /**
3045 * Create a ConstNode
3046 * @param value The value of the const node.
3047 */
3048 Temp(signed char value)
3049 : node(new ConstNode<signed char>(value)) {}
3050
3051 /**
3052 * Create a ConstNode
3053 * @param value The value of the const node.
3054 */
3055 Temp(unsigned char value)
3056 : node(new ConstNode<unsigned char>(value)) {}
3057
3058 /**
3059 * Create a ConstNode
3060 * @param value The value of the const node.
3061 */
3062 Temp(signed short value)
3063 : node(new ConstNode<signed short>(value)) {}
3064
3065 /**
3066 * Create a ConstNode
3067 * @param value The value of the const node.
3068 */
3069 Temp(unsigned short value)
3070 : node(new ConstNode<unsigned short>(value)) {}
3071
3072 /**
3073 * Create a ConstNode
3074 * @param value The value of the const node.
3075 */
3076 Temp(signed int value)
3077 : node(new ConstNode<signed int>(value)) {}
3078
3079 /**
3080 * Create a ConstNode
3081 * @param value The value of the const node.
3082 */
3083 Temp(unsigned int value)
3084 : node(new ConstNode<unsigned int>(value)) {}
3085
3086 /**
3087 * Create a ConstNode
3088 * @param value The value of the const node.
3089 */
3090 Temp(signed long value)
3091 : node(new ConstNode<signed long>(value)) {}
3092
3093 /**
3094 * Create a ConstNode
3095 * @param value The value of the const node.
3096 */
3097 Temp(unsigned long value)
3098 : node(new ConstNode<unsigned long>(value)) {}
3099
3100 /**
3101 * Create a ConstNode
3102 * @param value The value of the const node.
3103 */
3104 Temp(signed long long value)
3105 : node(new ConstNode<signed long long>(value)) {}
3106
3107 /**
3108 * Create a ConstNode
3109 * @param value The value of the const node.
3110 */
3111 Temp(unsigned long long value)
3112 : node(new ConstNode<unsigned long long>(value)) {}
3113
3114 /**
3115 * Create a ConstNode
3116 * @param value The value of the const node.
3117 */
3118 Temp(float value)
3119 : node(new ConstNode<float>(value)) {}
3120
3121 /**
3122 * Create a ConstNode
3123 * @param value The value of the const node.
3124 */
3125 Temp(double value)
3126 : node(new ConstNode<double>(value)) {}
3127 };
3128
3129
3130 /**
3131 * @}
3132 */
3133
3134 void check();
3135 void dump(std::ostream &stream, const std::string &name = "",
3136 DisplayMode mode = DefaultMode);
3137 void reset();
3138 void registerResetCallback(Callback *cb);
3139
3140 inline Temp
3141 operator+(Temp l, Temp r)
3142 {
3143 return NodePtr(new BinaryNode<std::plus<result_t> >(l, r));
3144 }
3145
3146 inline Temp
3147 operator-(Temp l, Temp r)
3148 {
3149 return NodePtr(new BinaryNode<std::minus<result_t> >(l, r));
3150 }
3151
3152 inline Temp
3153 operator*(Temp l, Temp r)
3154 {
3155 return NodePtr(new BinaryNode<std::multiplies<result_t> >(l, r));
3156 }
3157
3158 inline Temp
3159 operator/(Temp l, Temp r)
3160 {
3161 return NodePtr(new BinaryNode<std::divides<result_t> >(l, r));
3162 }
3163
3164 inline Temp
3165 operator%(Temp l, Temp r)
3166 {
3167 return NodePtr(new BinaryNode<std::modulus<result_t> >(l, r));
3168 }
3169
3170 inline Temp
3171 operator-(Temp l)
3172 {
3173 return NodePtr(new UnaryNode<std::negate<result_t> >(l));
3174 }
3175
3176 template <typename T>
3177 inline Temp
3178 constant(T val)
3179 {
3180 return NodePtr(new ConstNode<T>(val));
3181 }
3182
3183 template <typename T>
3184 inline Temp
3185 functor(T &val)
3186 {
3187 return NodePtr(new FunctorNode<T>(val));
3188 }
3189
3190 template <typename T>
3191 inline Temp
3192 scalar(T &val)
3193 {
3194 return NodePtr(new ScalarNode<T>(val));
3195 }
3196
3197 inline Temp
3198 sum(Temp val)
3199 {
3200 return NodePtr(new SumNode<std::plus<result_t> >(val));
3201 }
3202 extern bool PrintDescriptions;
3203
3204 } // namespace statistics
3205
3206 #endif // __STATISTICS_HH__