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