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