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