Merge ehallnor@zizzer:/bk/m5
[gem5.git] / base / statistics.hh
1 /*
2 * Copyright (c) 2003 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /** @file
30 * Declaration of Statistics objects.
31 */
32
33 /**
34 * @todo
35 *
36 * Generalized N-dimensinal vector
37 * documentation
38 * fix AvgStor
39 * key stats
40 * interval stats
41 * -- these both can use the same function that prints out a
42 * specific set of stats
43 * VectorStandardDeviation totals
44 * Document Namespaces
45 */
46 #ifndef __STATISTICS_HH__
47 #define __STATISTICS_HH__
48
49 #include <algorithm>
50 #include <functional>
51 #include <iosfwd>
52 #include <sstream>
53 #include <string>
54 #include <vector>
55
56 #include <assert.h>
57
58 #include "base/refcnt.hh"
59 #include "base/str.hh"
60
61 #include "sim/host.hh"
62
63 #ifndef NAN
64 float __nan();
65 /** Define Not a number. */
66 #define NAN (__nan())
67 /** Need to define __nan() */
68 #define __M5_NAN
69 #endif
70
71 /** Print stats out in SS format. */
72 #define STAT_DISPLAY_COMPAT
73
74 /** The current simulated cycle. */
75 extern Tick curTick;
76
77 /* A namespace for all of the Statistics */
78 namespace Statistics {
79 /** All results are doubles. */
80 typedef double result_t;
81 /** A vector to hold results. */
82 typedef std::vector<result_t> rvec_t;
83
84 /**
85 * Define the storage for format flags.
86 * @todo Can probably shrink this.
87 */
88 typedef u_int32_t FormatFlags;
89 /** Nothing extra to print. */
90 const FormatFlags none = 0x0000;
91 /** Print the total. */
92 const FormatFlags total = 0x0001;
93 /** Print the percent of the total that this entry represents. */
94 const FormatFlags pdf = 0x0002;
95 /** Don't print if this is zero. */
96 const FormatFlags nozero = 0x0004;
97 /** Don't print if this is NAN */
98 const FormatFlags nonan = 0x0008;
99 /** Print the cumulative percentage of total upto this entry. */
100 const FormatFlags cdf = 0x0010;
101 /** Print the distribution. */
102 const FormatFlags dist = 0x0020;
103 /** Used for SS compatability. */
104 const FormatFlags __substat = 0x8000;
105 /** Mask of flags that can't be set directly */
106 const FormatFlags __reserved = __substat;
107
108 /* Contains the statistic implementation details */
109 namespace Detail {
110 //////////////////////////////////////////////////////////////////////
111 //
112 // Statistics Framework Base classes
113 //
114 //////////////////////////////////////////////////////////////////////
115 struct StatData;
116 struct SubData;
117
118 /**
119 * Common base class for all statistics, used to maintain a list and print.
120 * This class holds no data itself but is used to find the associated
121 * StatData in the stat database @sa Statistics::Database.
122 */
123 class Stat
124 {
125 protected:
126 /** Mark this statistics as initialized. */
127 void setInit();
128 /**
129 * Finds and returns the associated StatData from the database.
130 * @return The formatting and output data of this statistic.
131 */
132 StatData *mydata();
133 /**
134 * Finds and returns a const pointer to the associated StatData.
135 * @return The formatting and output data of this statistic.
136 */
137 const StatData *mydata() const;
138 /**
139 * Mark this stat for output at the end of simulation.
140 * @return The formatting and output data of this statistic.
141 */
142 StatData *print();
143 /**
144 * Finds and returns the SubData at the given index.
145 * @param index The index of the SubData to find.
146 * @return The name and description of the given index.
147 */
148 const SubData *mysubdata(int index) const;
149 /**
150 * Create and return a new SubData field for the given index.
151 * @param index The index to create a SubData for.
152 * @return A pointer to the created SubData.
153 */
154 SubData *mysubdata_create(int index);
155
156 public:
157 /**
158 * Return the name of this stat.
159 * @return the name of the stat.
160 */
161 virtual std::string myname() const;
162 /**
163 * Return the name of the sub field at the given index.
164 * @param index the subfield index.
165 * @return the name of the subfield.
166 */
167 virtual std::string mysubname(int index) const;
168 /**
169 * Return the description of this stat.
170 * @return the description of this stat.
171 */
172 virtual std::string mydesc() const;
173 /**
174 * Return the description of the subfield at the given index.
175 * @param index The subfield index.
176 * @return the description of the subfield.
177 */
178 virtual std::string mysubdesc(int index) const;
179 /**
180 * Return the format flags of this stat.
181 * @return the format flags.
182 */
183 virtual FormatFlags myflags() const;
184 /**
185 * Return true if this stat's prereqs have been satisfied (they are non
186 * zero).
187 * @return true if the prerequisite stats aren't zero.
188 */
189 virtual bool dodisplay() const;
190 /**
191 * Return the display percision.
192 * @return The display precision.
193 */
194 virtual int myprecision() const;
195
196 public:
197 /**
198 * Create this stat and register it if reg is true.
199 * @param reg Register this stat in the database?
200 */
201 Stat(bool reg);
202 /**
203 * Destructor
204 */
205 virtual ~Stat() {}
206
207 /**
208 * Print this stat to the given ostream.
209 * @param stream The stream to print to.
210 */
211 virtual void display(std::ostream &stream) const = 0;
212 /**
213 * Return the number of entries in this stat.
214 * @return The number of entries.
215 */
216 virtual size_t size() const = 0;
217 /**
218 * Return true if the stat has value zero.
219 * @return True if the stat is zero.
220 */
221 virtual bool zero() const = 0;
222
223
224 /**
225 * Set the name and marks this stat to print at the end of simulation.
226 * @param name The new name.
227 * @return A reference to this stat.
228 */
229 Stat &name(const std::string &name);
230 /**
231 * Set the description and marks this stat to print at the end of
232 * simulation.
233 * @param desc The new description.
234 * @return A reference to this stat.
235 */
236 Stat &desc(const std::string &desc);
237 /**
238 * Set the precision and marks this stat to print at the end of simulation.
239 * @param p The new precision
240 * @return A reference to this stat.
241 */
242 Stat &precision(int p);
243 /**
244 * Set the flags and marks this stat to print at the end of simulation.
245 * @param f The new flags.
246 * @return A reference to this stat.
247 */
248 Stat &flags(FormatFlags f);
249 /**
250 * Set the prerequisite stat and marks this stat to print at the end of
251 * simulation.
252 * @param prereq The prerequisite stat.
253 * @return A reference to this stat.
254 */
255 Stat &prereq(const Stat &prereq);
256 /**
257 * Set the subfield name for the given index, and marks this stat to print
258 * at the end of simulation.
259 * @param index The subfield index.
260 * @param name The new name of the subfield.
261 * @return A reference to this stat.
262 */
263 Stat &subname(int index, const std::string &name);
264 /**
265 * Set the subfield description for the given index and marks this stat to
266 * print at the end of simulation.
267 * @param index The subfield index.
268 * @param desc The new description of the subfield
269 * @return A reference to this stat.
270 */
271 Stat &subdesc(int index, const std::string &desc);
272
273 public:
274 /**
275 * Checks if the first stat's name is alphabetically less than the second.
276 * This function breaks names up at periods and considers each subname
277 * separately.
278 * @param stat1 The first stat.
279 * @param stat2 The second stat.
280 * @return stat1's name is alphabetically before stat2's
281 */
282 static bool less(Stat *stat1, Stat *stat2);
283
284 #ifdef STAT_DEBUG
285 /** A unique ID used for debugging. */
286 int number;
287 #endif
288 };
289
290 // Scalar stats involved in formulas
291 class ScalarStat : public Stat
292 {
293 public:
294 ScalarStat(bool reg) : Stat(reg) {}
295 virtual result_t val() const = 0;
296 virtual bool zero() const;
297 virtual void display(std::ostream &stream) const;
298 };
299
300 void
301 VectorDisplay(std::ostream &stream, const std::string &myname,
302 const std::vector<std::string> *mysubnames,
303 const std::string &mydesc,
304 const std::vector<std::string> *mysubdescs,
305 int myprecision, FormatFlags myflags, const rvec_t &vec,
306 result_t mytotal);
307
308 // Vector stats involved in formulas
309 class VectorStat : public Stat
310 {
311 public:
312 VectorStat(bool reg) : Stat(reg) {}
313 virtual const rvec_t &val() const = 0;
314 virtual result_t total() const = 0;
315 virtual bool zero() const;
316 virtual void display(std::ostream &stream) const;
317 };
318
319 //////////////////////////////////////////////////////////////////////
320 //
321 // Simple Statistics
322 //
323 //////////////////////////////////////////////////////////////////////
324 template <typename T>
325 struct StatStor
326 {
327 public:
328 struct Params { };
329
330 private:
331 T data;
332
333 public:
334 StatStor(const Params &) : data(T()) {}
335
336 void set(T val, const Params &p) { data = val; }
337 void inc(T val, const Params &p) { data += val; }
338 void dec(T val, const Params &p) { data -= val; }
339 result_t val(const Params &p) const { return (result_t)data; }
340 T value(const Params &p) const { return data; }
341 };
342
343 template <typename T>
344 struct AvgStor
345 {
346 public:
347 struct Params { };
348
349 private:
350 T current;
351 mutable result_t total;
352 mutable Tick last;
353
354 public:
355 AvgStor(const Params &) : current(T()), total(0), last(0) { }
356
357 void set(T val, const Params &p) {
358 total += current * (curTick - last);
359 last = curTick;
360 current = val;
361 }
362 void inc(T val, const Params &p) { set(current + val, p); }
363 void dec(T val, const Params &p) { set(current - val, p); }
364 result_t val(const Params &p) const {
365 total += current * (curTick - last);
366 last = curTick;
367 return (result_t)(total + current) / (result_t)(curTick + 1);
368 }
369 T value(const Params &p) const { return current; }
370 };
371
372 template <typename T, template <typename T> class Storage, class Bin>
373 class ScalarBase : public ScalarStat
374 {
375 protected:
376 typedef Storage<T> storage_t;
377 typedef typename storage_t::Params params_t;
378 typedef typename Bin::Bin<storage_t> bin_t;
379
380 protected:
381 bin_t bin;
382 params_t params;
383
384 protected:
385 storage_t *data() { return bin.data(params); }
386 const storage_t *data() const {
387 return (const_cast<bin_t *>(&bin))->data(params);
388 }
389
390 protected:
391 // Copying stats is not allowed
392 ScalarBase(const ScalarBase &stat);
393 const ScalarBase &operator=(const ScalarBase &);
394
395 public:
396 result_t val() const { return data()->val(params); }
397 T value() const { return data()->value(params); }
398
399 public:
400 ScalarBase() : ScalarStat(true) {
401 bin.init(params);
402 setInit();
403 }
404
405 public:
406 // Common operators for stats
407 void operator++() { data()->inc(1, params); }
408 void operator--() { data()->dec(1, params); }
409
410 void operator++(int) { ++*this; }
411 void operator--(int) { --*this; }
412
413 template <typename U>
414 void operator=(const U& v) { data()->set(v, params); }
415
416 template <typename U>
417 void operator+=(const U& v) { data()->inc(v, params); }
418
419 template <typename U>
420 void operator-=(const U& v) { data()->dec(v, params); }
421
422 virtual size_t size() const { return 1; }
423 };
424
425 //////////////////////////////////////////////////////////////////////
426 //
427 // Vector Statistics
428 //
429 //////////////////////////////////////////////////////////////////////
430 template <typename T, template <typename T> class Storage, class Bin>
431 class ScalarProxy;
432
433 template <typename T, template <typename T> class Storage, class Bin>
434 class VectorBase : public VectorStat
435 {
436 protected:
437 typedef Storage<T> storage_t;
438 typedef typename storage_t::Params params_t;
439 typedef typename Bin::VectorBin<storage_t> bin_t;
440
441 private:
442 mutable rvec_t *vec;
443
444 protected:
445 bin_t bin;
446 params_t params;
447
448 protected:
449 storage_t *data(int index) { return bin.data(index, params); }
450 const storage_t *data(int index) const {
451 return (const_cast<bin_t *>(&bin))->data(index, params);
452 }
453
454 protected:
455 // Copying stats is not allowed
456 VectorBase(const VectorBase &stat);
457 const VectorBase &operator=(const VectorBase &);
458
459 public:
460 const rvec_t &val() const {
461 if (vec)
462 vec->resize(size());
463 else
464 vec = new rvec_t(size());
465
466 for (int i = 0; i < size(); ++i)
467 (*vec)[i] = data(i)->val(params);
468
469 return *vec;
470 }
471
472 result_t total() const {
473 result_t total = 0.0;
474 for (int i = 0; i < size(); ++i)
475 total += data(i)->val(params);
476 return total;
477 }
478
479 public:
480 VectorBase() : VectorStat(true), vec(NULL) {}
481 ~VectorBase() { if (vec) delete vec; }
482
483 VectorBase &init(size_t size) {
484 bin.init(size, params);
485 setInit();
486
487 return *this;
488 }
489
490 friend class ScalarProxy<T, Storage, Bin>;
491 ScalarProxy<T, Storage, Bin> operator[](int index);
492
493 virtual size_t size() const { return bin.size(); }
494 };
495
496 template <typename T, template <typename T> class Storage, class Bin>
497 class ScalarProxy : public ScalarStat
498 {
499 protected:
500 typedef Storage<T> storage_t;
501 typedef typename storage_t::Params params_t;
502 typedef typename Bin::VectorBin<storage_t> bin_t;
503
504 private:
505 bin_t *bin;
506 params_t *params;
507 int index;
508
509 protected:
510 storage_t *data() { return bin->data(index, *params); }
511 const storage_t *data() const { return bin->data(index, *params); }
512
513 public:
514 result_t val() const { return data()->val(*params); }
515 T value() const { return data()->value(*params); }
516
517 public:
518 ScalarProxy(bin_t &b, params_t &p, int i)
519 : ScalarStat(false), bin(&b), params(&p), index(i) {}
520 ScalarProxy(const ScalarProxy &sp)
521 : ScalarStat(false), bin(sp.bin), params(sp.params), index(sp.index) {}
522 const ScalarProxy &operator=(const ScalarProxy &sp) {
523 bin = sp.bin;
524 params = sp.params;
525 index = sp.index;
526 return *this;
527 }
528
529 public:
530 // Common operators for stats
531 void operator++() { data()->inc(1, *params); }
532 void operator--() { data()->dec(1, *params); }
533
534 void operator++(int) { ++*this; }
535 void operator--(int) { --*this; }
536
537 template <typename U>
538 void operator=(const U& v) { data()->set(v, *params); }
539
540 template <typename U>
541 void operator+=(const U& v) { data()->inc(v, *params); }
542
543 template <typename U>
544 void operator-=(const U& v) { data()->dec(v, *params); }
545
546 virtual size_t size() const { return 1; }
547 };
548
549 template <typename T, template <typename T> class Storage, class Bin>
550 inline ScalarProxy<T, Storage, Bin>
551 VectorBase<T, Storage, Bin>::operator[](int index)
552 {
553 assert (index >= 0 && index < size());
554 return ScalarProxy<T, Storage, Bin>(bin, params, index);
555 }
556
557 template <typename T, template <typename T> class Storage, class Bin>
558 class VectorProxy;
559
560 template <typename T, template <typename T> class Storage, class Bin>
561 class Vector2dBase : public Stat
562 {
563 protected:
564 typedef Storage<T> storage_t;
565 typedef typename storage_t::Params params_t;
566 typedef typename Bin::VectorBin<storage_t> bin_t;
567
568 protected:
569 size_t x;
570 size_t y;
571 bin_t bin;
572 params_t params;
573 std::vector<std::string> *y_subnames;
574
575 protected:
576 storage_t *data(int index) { return bin.data(index, params); }
577 const storage_t *data(int index) const {
578 return (const_cast<bin_t *>(&bin))->data(index, params);
579 }
580
581 protected:
582 // Copying stats is not allowed
583 Vector2dBase(const Vector2dBase &stat);
584 const Vector2dBase &operator=(const Vector2dBase &);
585
586 public:
587 Vector2dBase() : Stat(true) {}
588 ~Vector2dBase() { }
589
590 Vector2dBase &init(size_t _x, size_t _y) {
591 x = _x;
592 y = _y;
593 bin.init(x * y, params);
594 setInit();
595 y_subnames = new std::vector<std::string>(y);
596
597 return *this;
598 }
599
600 /**
601 * This makes the assumption that if you're gonna subnames a 2d vector,
602 * you're subnaming across all y
603 */
604 Vector2dBase &ysubnames(const char **names)
605 {
606 for (int i=0; i < y; ++i) {
607 (*y_subnames)[i] = names[i];
608 }
609 return *this;
610 }
611 Vector2dBase &ysubname(int index, const std::string subname)
612 {
613 (*y_subnames)[i] = subname.c_str();
614 return *this;
615 }
616 std::string ysubname(int i) const { return (*y_subnames)[i]; }
617
618 friend class VectorProxy<T, Storage, Bin>;
619 VectorProxy<T, Storage, Bin> operator[](int index);
620
621 virtual size_t size() const { return bin.size(); }
622 virtual bool zero() const { return data(0)->value(params) == 0.0; }
623
624 virtual void
625 display(std::ostream &out) const
626 {
627 bool have_subname = false;
628 for (int i = 0; i < x; ++i) {
629 if (!mysubname(i).empty())
630 have_subname = true;
631 }
632
633 rvec_t tot_vec(y);
634 result_t super_total = 0.0;
635 for (int i = 0; i < x; ++i) {
636 std::string subname;
637 if (have_subname) {
638 subname = mysubname(i);
639 if (subname.empty())
640 continue;
641 } else
642 subname = to_string(i);
643
644 int iy = i * y;
645 rvec_t vec(y);
646
647 result_t total = 0.0;
648 for (int j = 0; j < y; ++j) {
649 vec[j] = data(iy + j)->val(params);
650 tot_vec[j] += vec[j];
651 total += vec[j];
652 super_total += vec[j];
653 }
654
655 std::string desc;
656 if (mysubdesc(i).empty()) {
657 desc = mydesc();
658 } else {
659 desc = mysubdesc(i);
660 }
661
662 VectorDisplay(out, myname() + "_" + subname, y_subnames, desc, 0,
663 myprecision(), myflags(), vec, total);
664
665 }
666 if ((myflags() & ::Statistics::total) && (x > 1)) {
667 VectorDisplay(out, myname(), y_subnames, mydesc(), 0,
668 myprecision(), myflags(), tot_vec, super_total);
669
670 }
671 }
672 };
673
674 template <typename T, template <typename T> class Storage, class Bin>
675 class VectorProxy : public VectorStat
676 {
677 protected:
678 typedef Storage<T> storage_t;
679 typedef typename storage_t::Params params_t;
680 typedef typename Bin::VectorBin<storage_t> bin_t;
681
682 private:
683 bin_t *bin;
684 params_t *params;
685 int offset;
686 int len;
687
688 private:
689 mutable rvec_t *vec;
690
691 storage_t *data(int index) {
692 assert(index < len);
693 return bin->data(offset + index, *params);
694 }
695
696 const storage_t *data(int index) const {
697 return (const_cast<bin_t *>(bin))->data(offset + index, *params);
698 }
699
700 public:
701 const rvec_t &val() const {
702 if (vec)
703 vec->resize(size());
704 else
705 vec = new rvec_t(size());
706
707 for (int i = 0; i < size(); ++i)
708 (*vec)[i] = data(i)->val(*params);
709
710 return *vec;
711 }
712
713 result_t total() const {
714 result_t total = 0.0;
715 for (int i = 0; i < size(); ++i)
716 total += data(i)->val(*params);
717 return total;
718 }
719
720 public:
721 VectorProxy(bin_t &b, params_t &p, int o, int l)
722 : VectorStat(false), bin(&b), params(&p), offset(o), len(l), vec(NULL)
723 { }
724 VectorProxy(const VectorProxy &sp)
725 : VectorStat(false), bin(sp.bin), params(sp.params), offset(sp.offset),
726 len(sp.len), vec(NULL)
727 { }
728 ~VectorProxy() {
729 if (vec)
730 delete vec;
731 }
732
733 const VectorProxy &operator=(const VectorProxy &sp) {
734 bin = sp.bin;
735 params = sp.params;
736 offset = sp.offset;
737 len = sp.len;
738 if (vec)
739 delete vec;
740 vec = NULL;
741 return *this;
742 }
743
744 virtual size_t size() const { return len; }
745
746 ScalarProxy<T, Storage, Bin> operator[](int index) {
747 assert (index >= 0 && index < size());
748 return ScalarProxy<T, Storage, Bin>(*bin, *params, offset + index);
749 }
750 };
751
752 template <typename T, template <typename T> class Storage, class Bin>
753 inline VectorProxy<T, Storage, Bin>
754 Vector2dBase<T, Storage, Bin>::operator[](int index)
755 {
756 int offset = index * y;
757 assert (index >= 0 && offset < size());
758 return VectorProxy<T, Storage, Bin>(bin, params, offset, y);
759 }
760
761 //////////////////////////////////////////////////////////////////////
762 //
763 // Non formula statistics
764 //
765 //////////////////////////////////////////////////////////////////////
766
767 void DistDisplay(std::ostream &stream, const std::string &name,
768 const std::string &desc, int precision, FormatFlags flags,
769 result_t min_val, result_t max_val,
770 result_t underflow, result_t overflow,
771 const rvec_t &vec, int min, int max, int bucket_size,
772 int size);
773
774 template <typename T>
775 struct DistStor
776 {
777 public:
778 struct Params
779 {
780 int min;
781 int max;
782 int bucket_size;
783 int size;
784 };
785
786 private:
787 T min_val;
788 T max_val;
789 T underflow;
790 T overflow;
791 std::vector<T> vec;
792
793 public:
794 DistStor(const Params &params)
795 : min_val(INT_MAX), max_val(INT_MIN), underflow(0), overflow(0),
796 vec(params.size) {
797 }
798 void sample(T val, int number, const Params &params) {
799 if (val < params.min)
800 underflow += number;
801 else if (val > params.max)
802 overflow += number;
803 else {
804 int index = (val - params.min) / params.bucket_size;
805 assert(index < size(params));
806 vec[index] += number;
807 }
808
809 if (val < min_val)
810 min_val = val;
811
812 if (val > max_val)
813 max_val = val;
814 }
815
816 size_t size(const Params &) const { return vec.size(); }
817
818 bool zero(const Params &params) const {
819 if (underflow != 0 || overflow != 0)
820 return true;
821
822 int s = size(params);
823 for (int i = 0; i < s; i++)
824 if (vec[i] != 0)
825 return true;
826
827 return false;
828 }
829
830 void display(std::ostream &stream, const std::string &name,
831 const std::string &desc, int precision, FormatFlags flags,
832 const Params &params) const {
833
834 #ifdef STAT_DISPLAY_COMPAT
835 result_t min = params.min;
836 #else
837 result_t min = (min_val == INT_MAX) ? params.min : min_val;
838 #endif
839 result_t max = (max_val == INT_MIN) ? 0 : max_val;
840
841 rvec_t rvec(params.size);
842 for (int i = 0; i < params.size; ++i)
843 rvec[i] = vec[i];
844
845 DistDisplay(stream, name, desc, precision, flags,
846 (result_t)min, (result_t)max,
847 (result_t)underflow, (result_t)overflow,
848 rvec, params.min, params.max, params.bucket_size,
849 params.size);
850 }
851 };
852
853 void FancyDisplay(std::ostream &stream, const std::string &name,
854 const std::string &desc, int precision, FormatFlags flags,
855 result_t mean, result_t variance);
856 template <typename T>
857 struct FancyStor
858 {
859 public:
860 struct Params {};
861
862 private:
863 T sum;
864 T squares;
865 int total;
866
867 public:
868 FancyStor(const Params &) : sum(0), squares(0), total(0) {}
869
870 void sample(T val, int number, const Params &) {
871 T value = val * number;
872 sum += value;
873 squares += value * value;
874 total += number;
875 }
876 void display(std::ostream &stream, const std::string &name,
877 const std::string &desc, int precision, FormatFlags flags,
878 const Params &) const {
879
880 result_t mean = NAN;
881 result_t variance = NAN;
882
883 if (total != 0) {
884 result_t fsum = sum;
885 result_t fsq = squares;
886 result_t ftot = total;
887
888 mean = fsum / ftot;
889 variance = (ftot * fsq - (fsum * fsum)) / (ftot * (ftot - 1.0));
890 }
891
892 FancyDisplay(stream, name, desc, precision, flags, mean, variance);
893 }
894
895 size_t size(const Params &) const { return 1; }
896 bool zero(const Params &) const { return total == 0; }
897 };
898
899 template <typename T>
900 struct AvgFancy
901 {
902 public:
903 struct Params {};
904
905 private:
906 T sum;
907 T squares;
908
909 public:
910 AvgFancy(const Params &) : sum(0), squares(0) {}
911
912 void sample(T val, int number, const Params& p) {
913 T value = val * number;
914 sum += value;
915 squares += value * value;
916 }
917 void display(std::ostream &stream, const std::string &name,
918 const std::string &desc, int precision, FormatFlags flags,
919 const Params &params) const {
920 result_t mean = sum / curTick;
921 result_t variance = (squares - sum * sum) / curTick;
922
923 FancyDisplay(stream, name, desc, precision, flags, mean, variance);
924 }
925
926 size_t size(const Params &params) const { return 1; }
927 bool zero(const Params &params) const { return sum == 0; }
928 };
929
930 template <typename T, template <typename T> class Storage, class Bin>
931 class DistBase : public Stat
932 {
933 protected:
934 typedef Storage<T> storage_t;
935 typedef typename storage_t::Params params_t;
936 typedef typename Bin::Bin<storage_t> bin_t;
937
938 protected:
939 bin_t bin;
940 params_t params;
941
942 protected:
943 storage_t *data() { return bin.data(params); }
944 const storage_t *data() const {
945 return (const_cast<bin_t *>(&bin))->data(params);
946 }
947
948 protected:
949 // Copying stats is not allowed
950 DistBase(const DistBase &stat);
951 const DistBase &operator=(const DistBase &);
952
953 public:
954 DistBase() : Stat(true) { }
955 ~DistBase() { }
956
957 template <typename U>
958 void sample(const U& v, int n = 1) { data()->sample(v, n, params); }
959
960 virtual size_t size() const { return data()->size(params); }
961 virtual bool zero() const { return data()->zero(params); }
962 virtual void display(std::ostream &stream) const {
963 data()->display(stream, myname(), mydesc(), myprecision(), myflags(),
964 params);
965 }
966 };
967
968 template <typename T, template <typename T> class Storage, class Bin>
969 class VectorDistProxy;
970
971 template <typename T, template <typename T> class Storage, class Bin>
972 class VectorDistBase : public Stat
973 {
974 protected:
975 typedef Storage<T> storage_t;
976 typedef typename storage_t::Params params_t;
977 typedef typename Bin::VectorBin<storage_t> bin_t;
978
979 protected:
980 bin_t bin;
981 params_t params;
982
983 protected:
984 storage_t *data(int index) { return bin.data(index, params); }
985 const storage_t *data(int index) const {
986 return (const_cast<bin_t *>(&bin))->data(index, params);
987 }
988
989 protected:
990 // Copying stats is not allowed
991 VectorDistBase(const VectorDistBase &stat);
992 const VectorDistBase &operator=(const VectorDistBase &);
993
994 public:
995 VectorDistBase() : Stat(true) { }
996 ~VectorDistBase() { }
997
998 friend class VectorDistProxy<T, Storage, Bin>;
999 VectorDistProxy<T, Storage, Bin> operator[](int index);
1000 const VectorDistProxy<T, Storage, Bin> operator[](int index) const;
1001
1002 virtual size_t size() const { return bin.size(); }
1003 virtual bool zero() const { return false; }
1004 virtual void display(std::ostream &stream) const;
1005 };
1006
1007 template <typename T, template <typename T> class Storage, class Bin>
1008 class VectorDistProxy : public Stat
1009 {
1010 protected:
1011 typedef Storage<T> storage_t;
1012 typedef typename storage_t::Params params_t;
1013 typedef typename Bin::Bin<storage_t> bin_t;
1014 typedef VectorDistBase<T, Storage, Bin> base_t;
1015
1016 private:
1017 union {
1018 base_t *stat;
1019 const base_t *cstat;
1020 };
1021 int index;
1022
1023 protected:
1024 storage_t *data() { return stat->data(index); }
1025 const storage_t *data() const { return cstat->data(index); }
1026
1027 public:
1028 VectorDistProxy(const VectorDistBase<T, Storage, Bin> &s, int i)
1029 : Stat(false), cstat(&s), index(i) {}
1030 VectorDistProxy(const VectorDistProxy &sp)
1031 : Stat(false), cstat(sp.cstat), index(sp.index) {}
1032 const VectorDistProxy &operator=(const VectorDistProxy &sp) {
1033 cstat = sp.cstat; index = sp.index; return *this;
1034 }
1035
1036 public:
1037 template <typename U>
1038 void sample(const U& v, int n = 1) { data()->sample(v, n, cstat->params); }
1039
1040 virtual size_t size() const { return 1; }
1041 virtual bool zero() const {
1042 return data()->zero(cstat->params);
1043 }
1044 virtual void display(std::ostream &stream) const {
1045 std::stringstream name, desc;
1046
1047 if (!(cstat->mysubname(index).empty())) {
1048 name << cstat->myname() << cstat->mysubname(index);
1049 } else {
1050 name << cstat->myname() << "_" << index;
1051 }
1052 if (!(cstat->mysubdesc(index).empty())) {
1053 desc << cstat->mysubdesc(index);
1054 } else {
1055 desc << cstat->mydesc();
1056 }
1057
1058 data()->display(stream, name.str(), desc.str(),
1059 cstat->myprecision(), cstat->myflags(), cstat->params);
1060 }
1061 };
1062
1063 template <typename T, template <typename T> class Storage, class Bin>
1064 inline VectorDistProxy<T, Storage, Bin>
1065 VectorDistBase<T, Storage, Bin>::operator[](int index)
1066 {
1067 assert (index >= 0 && index < size());
1068 return VectorDistProxy<T, Storage, Bin>(*this, index);
1069 }
1070
1071 template <typename T, template <typename T> class Storage, class Bin>
1072 inline const VectorDistProxy<T, Storage, Bin>
1073 VectorDistBase<T, Storage, Bin>::operator[](int index) const
1074 {
1075 assert (index >= 0 && index < size());
1076 return VectorDistProxy<T, Storage, Bin>(*this, index);
1077 }
1078
1079 /**
1080 * @todo Need a way to print Distribution totals across the Vector
1081 */
1082 template <typename T, template <typename T> class Storage, class Bin>
1083 void
1084 VectorDistBase<T, Storage, Bin>::display(std::ostream &stream) const
1085 {
1086 for (int i = 0; i < size(); ++i) {
1087 VectorDistProxy<T, Storage, Bin> proxy(*this, i);
1088 proxy.display(stream);
1089 }
1090 }
1091
1092 #if 0
1093 result_t
1094 VectorDistBase<T, Storage, Bin>::total(int index) const
1095 {
1096 int total = 0;
1097 for (int i=0; i < x_size(); ++i) {
1098 total += data(i)->val(*params);
1099 }
1100 }
1101 #endif
1102
1103 //////////////////////////////////////////////////////////////////////
1104 //
1105 // Formula Details
1106 //
1107 //////////////////////////////////////////////////////////////////////
1108 class Node : public RefCounted
1109 {
1110 public:
1111 virtual size_t size() const = 0;
1112 virtual const rvec_t &val() const = 0;
1113 virtual result_t total() const = 0;
1114 };
1115
1116 typedef RefCountingPtr<Node> NodePtr;
1117
1118 class ScalarStatNode : public Node
1119 {
1120 private:
1121 const ScalarStat &stat;
1122 mutable rvec_t result;
1123
1124 public:
1125 ScalarStatNode(const ScalarStat &s) : stat(s), result(1) {}
1126 const rvec_t &val() const { result[0] = stat.val(); return result; }
1127 virtual result_t total() const { return stat.val(); };
1128
1129 virtual size_t size() const { return 1; }
1130 };
1131
1132 template <typename T, template <typename T> class Storage, class Bin>
1133 class ScalarProxyNode : public Node
1134 {
1135 private:
1136 const ScalarProxy<T, Storage, Bin> proxy;
1137 mutable rvec_t result;
1138
1139 public:
1140 ScalarProxyNode(const ScalarProxy<T, Storage, Bin> &p)
1141 : proxy(p), result(1) { }
1142 const rvec_t &val() const { result[0] = proxy.val(); return result; }
1143 virtual result_t total() const { return proxy.val(); };
1144
1145 virtual size_t size() const { return 1; }
1146 };
1147
1148 class VectorStatNode : public Node
1149 {
1150 private:
1151 const VectorStat &stat;
1152
1153 public:
1154 VectorStatNode(const VectorStat &s) : stat(s) {}
1155 const rvec_t &val() const { return stat.val(); }
1156 virtual result_t total() const { return stat.total(); };
1157
1158 virtual size_t size() const { return stat.size(); }
1159 };
1160
1161 template <typename T>
1162 class ConstNode : public Node
1163 {
1164 private:
1165 rvec_t data;
1166
1167 public:
1168 ConstNode(T s) : data(1, (result_t)s) {}
1169 const rvec_t &val() const { return data; }
1170 virtual result_t total() const { return data[0]; };
1171
1172 virtual size_t size() const { return 1; }
1173 };
1174
1175 template <typename T>
1176 class FunctorNode : public Node
1177 {
1178 private:
1179 T &functor;
1180 mutable rvec_t result;
1181
1182 public:
1183 FunctorNode(T &f) : functor(f) { result.resize(1); }
1184 const rvec_t &val() const {
1185 result[0] = (result_t)functor();
1186 return result;
1187 }
1188 virtual result_t total() const { return (result_t)functor(); };
1189
1190 virtual size_t size() const { return 1; }
1191 };
1192
1193 template <typename T>
1194 class ScalarNode : public Node
1195 {
1196 private:
1197 T &scalar;
1198 mutable rvec_t result;
1199
1200 public:
1201 ScalarNode(T &s) : scalar(s) { result.resize(1); }
1202 const rvec_t &val() const {
1203 result[0] = (result_t)scalar;
1204 return result;
1205 }
1206 virtual result_t total() const { return (result_t)scalar; };
1207
1208 virtual size_t size() const { return 1; }
1209 };
1210
1211 template <class Op>
1212 class UnaryNode : public Node
1213 {
1214 public:
1215 NodePtr l;
1216 mutable rvec_t result;
1217
1218 public:
1219 UnaryNode(NodePtr p) : l(p) {}
1220
1221 const rvec_t &val() const {
1222 const rvec_t &lvec = l->val();
1223 int size = lvec.size();
1224
1225 assert(size > 0);
1226
1227 result.resize(size);
1228 Op op;
1229 for (int i = 0; i < size; ++i)
1230 result[i] = op(lvec[i]);
1231
1232 return result;
1233 }
1234
1235 result_t total() const {
1236 Op op;
1237 return op(l->total());
1238 }
1239
1240 virtual size_t size() const { return l->size(); }
1241 };
1242
1243 template <class Op>
1244 class BinaryNode : public Node
1245 {
1246 public:
1247 NodePtr l;
1248 NodePtr r;
1249 mutable rvec_t result;
1250
1251 public:
1252 BinaryNode(NodePtr a, NodePtr b) : l(a), r(b) {}
1253
1254 const rvec_t &val() const {
1255 Op op;
1256 const rvec_t &lvec = l->val();
1257 const rvec_t &rvec = r->val();
1258
1259 assert(lvec.size() > 0 && rvec.size() > 0);
1260
1261 if (lvec.size() == 1 && rvec.size() == 1) {
1262 result.resize(1);
1263 result[0] = op(lvec[0], rvec[0]);
1264 } else if (lvec.size() == 1) {
1265 int size = rvec.size();
1266 result.resize(size);
1267 for (int i = 0; i < size; ++i)
1268 result[i] = op(lvec[0], rvec[i]);
1269 } else if (rvec.size() == 1) {
1270 int size = lvec.size();
1271 result.resize(size);
1272 for (int i = 0; i < size; ++i)
1273 result[i] = op(lvec[i], rvec[0]);
1274 } else if (rvec.size() == lvec.size()) {
1275 int size = rvec.size();
1276 result.resize(size);
1277 for (int i = 0; i < size; ++i)
1278 result[i] = op(lvec[i], rvec[i]);
1279 }
1280
1281 return result;
1282 }
1283
1284 result_t total() const {
1285 Op op;
1286 return op(l->total(), r->total());
1287 }
1288
1289 virtual size_t size() const {
1290 int ls = l->size();
1291 int rs = r->size();
1292 if (ls == 1)
1293 return rs;
1294 else if (rs == 1)
1295 return ls;
1296 else {
1297 assert(ls == rs && "Node vector sizes are not equal");
1298 return ls;
1299 }
1300 }
1301 };
1302
1303 template <class Op>
1304 class SumNode : public Node
1305 {
1306 public:
1307 NodePtr l;
1308 mutable rvec_t result;
1309
1310 public:
1311 SumNode(NodePtr p) : l(p), result(1) {}
1312
1313 const rvec_t &val() const {
1314 const rvec_t &lvec = l->val();
1315 int size = lvec.size();
1316 assert(size > 0);
1317
1318 result[0] = 0.0;
1319
1320 Op op;
1321 for (int i = 0; i < size; ++i)
1322 result[0] = op(result[0], lvec[i]);
1323
1324 return result;
1325 }
1326
1327 result_t total() const {
1328 const rvec_t &lvec = l->val();
1329 int size = lvec.size();
1330 assert(size > 0);
1331
1332 result_t result = 0.0;
1333
1334 Op op;
1335 for (int i = 0; i < size; ++i)
1336 result = op(result, lvec[i]);
1337
1338 return result;
1339 }
1340
1341 virtual size_t size() const { return 1; }
1342 };
1343
1344 class Temp
1345 {
1346 private:
1347 NodePtr node;
1348
1349 public:
1350 Temp(NodePtr n) : node(n) {}
1351 Temp(const ScalarStat &s) : node(new ScalarStatNode(s)) {}
1352 template <typename T, template <typename T> class Storage, class Bin>
1353 Temp(const ScalarProxy<T, Storage, Bin> &p)
1354 : node(new ScalarProxyNode<T, Storage, Bin>(p)) {}
1355 Temp(const VectorStat &s) : node(new VectorStatNode(s)) {}
1356
1357 #define TempSCALAR(T) \
1358 Temp(T value) : node(new ConstNode<T>(value)) {}
1359
1360 TempSCALAR( signed char);
1361 TempSCALAR(unsigned char);
1362 TempSCALAR( signed short);
1363 TempSCALAR(unsigned short);
1364 TempSCALAR( signed int);
1365 TempSCALAR(unsigned int);
1366 TempSCALAR( signed long);
1367 TempSCALAR(unsigned long);
1368 TempSCALAR( signed long long);
1369 TempSCALAR(unsigned long long);
1370 TempSCALAR(float);
1371 TempSCALAR(double);
1372 #undef TempSCALAR
1373
1374 operator NodePtr() { return node;}
1375 };
1376
1377
1378 //////////////////////////////////////////////////////////////////////
1379 //
1380 // Binning Interface
1381 //
1382 //////////////////////////////////////////////////////////////////////
1383
1384 class BinBase
1385 {
1386 private:
1387 off_t memsize;
1388 char *mem;
1389
1390 protected:
1391 off_t size() const { return memsize; }
1392 char *memory();
1393
1394 public:
1395 BinBase(size_t size);
1396 ~BinBase();
1397 };
1398
1399 } // namespace Detail
1400
1401 template <class BinType>
1402 struct StatBin : public Detail::BinBase
1403 {
1404 static StatBin *&curBin() {
1405 static StatBin *current = NULL;
1406 return current;
1407 }
1408
1409 static void setCurBin(StatBin *bin) { curBin() = bin; }
1410 static StatBin *current() { assert(curBin()); return curBin(); }
1411
1412 static off_t &offset() {
1413 static off_t offset = 0;
1414 return offset;
1415 }
1416
1417 static off_t new_offset(size_t size) {
1418 size_t mask = sizeof(u_int64_t) - 1;
1419 off_t off = offset();
1420
1421 // That one is for the last trailing flags byte.
1422 offset() += (size + 1 + mask) & ~mask;
1423
1424 return off;
1425 }
1426
1427 explicit StatBin(size_t size = 1024) : Detail::BinBase(size) {}
1428
1429 char *memory(off_t off) {
1430 assert(offset() <= size());
1431 return Detail::BinBase::memory() + off;
1432 }
1433
1434 static void activate(StatBin &bin) { setCurBin(&bin); }
1435
1436 class BinBase
1437 {
1438 private:
1439 int offset;
1440
1441 public:
1442 BinBase() : offset(-1) {}
1443 void allocate(size_t size) {
1444 offset = new_offset(size);
1445 }
1446 char *access() {
1447 assert(offset != -1);
1448 return current()->memory(offset);
1449 }
1450 };
1451
1452 template <class Storage>
1453 class Bin : public BinBase
1454 {
1455 public:
1456 typedef typename Storage::Params Params;
1457
1458 public:
1459 Bin() { allocate(sizeof(Storage)); }
1460 bool initialized() const { return true; }
1461 void init(const Params &params) { }
1462
1463 int size() const { return 1; }
1464
1465 Storage *data(const Params &params) {
1466 assert(initialized());
1467 char *ptr = access();
1468 char *flags = ptr + sizeof(Storage);
1469 if (!(*flags & 0x1)) {
1470 *flags |= 0x1;
1471 new (ptr) Storage(params);
1472 }
1473 return reinterpret_cast<Storage *>(ptr);
1474 }
1475 };
1476
1477 template <class Storage>
1478 class VectorBin : public BinBase
1479 {
1480 public:
1481 typedef typename Storage::Params Params;
1482
1483 private:
1484 int _size;
1485
1486 public:
1487 VectorBin() : _size(0) {}
1488
1489 bool initialized() const { return _size > 0; }
1490 void init(int s, const Params &params) {
1491 assert(!initialized());
1492 assert(s > 0);
1493 _size = s;
1494 allocate(_size * sizeof(Storage));
1495 }
1496
1497 int size() const { return _size; }
1498
1499 Storage *data(int index, const Params &params) {
1500 assert(initialized());
1501 assert(index >= 0 && index < size());
1502 char *ptr = access();
1503 char *flags = ptr + size() * sizeof(Storage);
1504 if (!(*flags & 0x1)) {
1505 *flags |= 0x1;
1506 for (int i = 0; i < size(); ++i)
1507 new (ptr + i * sizeof(Storage)) Storage(params);
1508 }
1509 return reinterpret_cast<Storage *>(ptr + index * sizeof(Storage));
1510 }
1511 };
1512 };
1513
1514 class MainBinType {};
1515 typedef StatBin<MainBinType> MainBin;
1516
1517 struct NoBin
1518 {
1519 template <class Storage>
1520 struct Bin
1521 {
1522 public:
1523 typedef typename Storage::Params Params;
1524
1525 private:
1526 char ptr[sizeof(Storage)];
1527
1528 public:
1529 bool initialized() const { return true; }
1530 void init(const Params &params) {
1531 new (ptr) Storage(params);
1532 }
1533 int size() const{ return 1; }
1534 Storage *data(const Params &params) {
1535 assert(initialized());
1536 return reinterpret_cast<Storage *>(ptr);
1537 }
1538 };
1539
1540 template <class Storage>
1541 struct VectorBin
1542 {
1543 public:
1544 typedef typename Storage::Params Params;
1545
1546 private:
1547 char *ptr;
1548 int _size;
1549
1550 public:
1551 VectorBin() : ptr(NULL) { }
1552 ~VectorBin() {
1553 if (initialized())
1554 delete [] ptr;
1555 }
1556 bool initialized() const { return ptr != NULL; }
1557 void init(int s, const Params &params) {
1558 assert(s > 0 && "size must be positive!");
1559 assert(!initialized());
1560 _size = s;
1561 ptr = new char[_size * sizeof(Storage)];
1562 for (int i = 0; i < _size; ++i)
1563 new (ptr + i * sizeof(Storage)) Storage(params);
1564 }
1565
1566 int size() const { return _size; }
1567
1568 Storage *data(int index, const Params &params) {
1569 assert(initialized());
1570 assert(index >= 0 && index < size());
1571 return reinterpret_cast<Storage *>(ptr + index * sizeof(Storage));
1572 }
1573 };
1574 };
1575
1576 //////////////////////////////////////////////////////////////////////
1577 //
1578 // Visible Statistics Types
1579 //
1580 //////////////////////////////////////////////////////////////////////
1581 /**@defgroup VStats VisibleStatTypes
1582 */
1583
1584 /** @ingroup VStats
1585 *This is the simplest counting stat. Default type is Counter, but can be
1586 *anything (like double, int, etc). To bin, just designate the name of the bin
1587 * when declaring. It can be used like a regular Counter.
1588 *Example: Stat<> foo;
1589 *foo += num_foos;
1590 */
1591 template <typename T = Counter, class Bin = NoBin>
1592 class Scalar : public Detail::ScalarBase<T, Detail::StatStor, Bin>
1593 {
1594 public:
1595 typedef Detail::ScalarBase<T, Detail::StatStor, Bin> Base;
1596
1597 /** sets Stat equal to value of type U */
1598 template <typename U>
1599 void operator=(const U& v) { Base::operator=(v); }
1600 };
1601
1602 /** @ingroup VStats
1603 *This calculates averages over number of cycles. Additionally, the update per
1604 *cycle is implicit if there is no change. In other words, if you want to know
1605 *the average number of instructions in the IQ per cycle, then you can use this
1606 * stat and not have to update it on cycles where there is no change.
1607 */
1608 template <typename T = Counter, class Bin = NoBin>
1609 class Average : public Detail::ScalarBase<T, Detail::AvgStor, Bin>
1610 {
1611 public:
1612 typedef Detail::ScalarBase<T, Detail::AvgStor, Bin> Base;
1613
1614 /** sets Average equalt to value of type U*/
1615 template <typename U>
1616 void operator=(const U& v) { Base::operator=(v); }
1617 };
1618
1619 /** @ingroup VStats
1620 *This is a vector of type T, ideally suited to track stats across something like
1621 * SMT threads.
1622 */
1623 template <typename T = Counter, class Bin = NoBin>
1624 class Vector : public Detail::VectorBase<T, Detail::StatStor, Bin>
1625 { };
1626
1627 /** @ingroup VStats
1628 *This is a vector of Averages of type T
1629 */
1630 template <typename T = Counter, class Bin = NoBin>
1631 class AverageVector : public Detail::VectorBase<T, Detail::AvgStor, Bin>
1632 { };
1633
1634 /** @ingroup VStats
1635 *This is a 2-dimensional vector. Intended usage is for something like tracking a
1636 * Vector stat across another Vector like SMT threads.
1637 */
1638 template <typename T = Counter, class Bin = NoBin>
1639 class Vector2d : public Detail::Vector2dBase<T, Detail::StatStor, Bin>
1640 { };
1641
1642 /** @ingroup VStats
1643 * This is essentially a Vector, but with minor differences. Where a
1644 * Vector's index maps directly to what it's tracking, a Distribution's index can
1645 * map to an arbitrary bucket type. For example, you could map 1-8 to bucket 0
1646 * of a Distribution, and if ever there are 1-8 instructions within an IQ, increment
1647 * bucket 0.
1648 */
1649 template <typename T = Counter, class Bin = NoBin>
1650 class Distribution : public Detail::DistBase<T, Detail::DistStor, Bin>
1651 {
1652 private:
1653 typedef Detail::DistBase<T, Detail::DistStor, Bin> Base;
1654 typedef typename Detail::DistStor<T>::Params Params;
1655
1656 public:
1657 /**
1658 *This must be called to set some data members of the distribution
1659 *as well as to allocate the appropriate storage size.
1660 *@param min The minimum value of the Distribution
1661 *@param max The maximum value of the Distribution (NOT the size!)
1662 *@param bkt The size of the buckets to indicate mapping. I.e. if you have
1663 *min=0, max=15, bkt=8, you will have two buckets, and anything from 0-7
1664 *will go into bucket 0, and anything from 8-15 be in bucket 1.
1665 *@return the Distribution itself.
1666 */
1667 Distribution &init(T min, T max, int bkt) {
1668 params.min = min;
1669 params.max = max;
1670 params.bucket_size = bkt;
1671 params.size = (max - min) / bkt + 1;
1672 bin.init(params);
1673 setInit();
1674
1675 return *this;
1676 }
1677 };
1678
1679 /** @ingroup VStats
1680 *This has the functionality of a standard deviation built into it. Update it
1681 *every cycle, and at the end you will have the standard deviation.
1682 */
1683 template <typename T = Counter, class Bin = NoBin>
1684 class StandardDeviation : public Detail::DistBase<T, Detail::FancyStor, Bin>
1685 {
1686 private:
1687 typedef Detail::DistBase<T, Detail::DistStor, Bin> Base;
1688 typedef typename Detail::DistStor<T>::Params Params;
1689
1690 public:
1691 StandardDeviation() {
1692 bin.init(params);
1693 setInit();
1694 }
1695 };
1696
1697 /** @ingroup VStats
1698 *This also calculates standard deviations, but there is no need to
1699 *update every cycle if there is no change, the stat will update for you.
1700 */
1701 template <typename T = Counter, class Bin = NoBin>
1702 class AverageDeviation : public Detail::DistBase<T, Detail::AvgFancy, Bin>
1703 {
1704 private:
1705 typedef Detail::DistBase<T, Detail::DistStor, Bin> Base;
1706 typedef typename Detail::DistStor<T>::Params Params;
1707
1708 public:
1709 AverageDeviation() {
1710 bin.init(params);
1711 setInit();
1712 }
1713 };
1714
1715 /** @ingroup VStats
1716 *This is a vector of Distributions. (The complexity increases!). Intended usage
1717 * is for something like tracking a distribution across a vector like SMT threads.
1718 */
1719 template <typename T = Counter, class Bin = NoBin>
1720 class VectorDistribution
1721 : public Detail::VectorDistBase<T, Detail::DistStor, Bin>
1722 {
1723 private:
1724 typedef Detail::VectorDistBase<T, Detail::DistStor, Bin> Base;
1725 typedef typename Detail::DistStor<T>::Params Params;
1726
1727 public:
1728 /**
1729 *This must be called to set some data members and allocate storage space.
1730 *@param size The size of the Vector
1731 *@param min The minumum value of the Distribution
1732 *@param max The maximum value of the Distribution (NOT the size)
1733 *@param bkt The range of the bucket. I.e if min=0, max=15, and bkt=8,
1734 *then 0-7 will be bucket 0, and 8-15 will be bucket 1.
1735 *@return return the VectorDistribution itself.
1736 */
1737 VectorDistribution &init(int size, T min, T max, int bkt) {
1738 params.min = min;
1739 params.max = max;
1740 params.bucket_size = bkt;
1741 params.size = (max - min) / bkt + 1;
1742 bin.init(size, params);
1743 setInit();
1744
1745 return *this;
1746 }
1747 };
1748
1749 /** @ingroup VStats
1750 *This is a vector of Standard Deviations. Intended usage is for tracking
1751 *Standard Deviations across a vector like SMT threads.
1752 */
1753 template <typename T = Counter, class Bin = NoBin>
1754 class VectorStandardDeviation
1755 : public Detail::VectorDistBase<T, Detail::FancyStor, Bin>
1756 {
1757 private:
1758 typedef Detail::VectorDistBase<T, Detail::FancyStor, Bin> Base;
1759 typedef typename Detail::DistStor<T>::Params Params;
1760
1761 public:
1762 /** This must be called to initialize some data members and allocate
1763 * approprate storage space for the stat.
1764 *@param size The size of the Vector
1765 * @return the VectorStandardDeviation itself.
1766 */
1767 VectorStandardDeviation &init(int size) {
1768 bin.init(size, params);
1769 setInit();
1770
1771 return *this;
1772 }
1773 };
1774
1775 /** @ingroup VStats
1776 * This is a vector of Average Deviations. Intended usage is for tracking
1777 *Average Deviations across a vector like SMT threads.
1778 */
1779 template <typename T = Counter, class Bin = NoBin>
1780 class VectorAverageDeviation
1781 : public Detail::VectorDistBase<T, Detail::AvgFancy, Bin>
1782 {
1783 private:
1784 typedef Detail::VectorDistBase<T, Detail::AvgFancy, Bin> Base;
1785 typedef typename Detail::DistStor<T>::Params Params;
1786
1787 public:
1788 /** This must be called to initialize some data members and allocate
1789 * approprate storage space for the stat.
1790 *@param size The size of the Vector
1791 * @return The VectorAverageDeviation itself.
1792 */
1793 VectorAverageDeviation &init(int size) {
1794 bin.init(size, params);
1795 setInit();
1796
1797 return *this;
1798 }
1799 };
1800
1801 /** @ingroup VStats
1802 *This is a formula type. When defining it, you can just say:
1803 *Formula foo = manchu + 3 / bar;
1804 *The calculations for Formulas are all done at the end of the simulation, this
1805 *really is just a definition of how to calculate at the end.
1806 */
1807 class Formula : public Detail::VectorStat
1808 {
1809 private:
1810 /** The root of the tree which represents the Formula */
1811 Detail::NodePtr root;
1812 friend class Detail::Temp;
1813
1814 public:
1815 Formula() : VectorStat(true) { setInit(); }
1816 Formula(Detail::Temp r) : VectorStat(true) {
1817 root = r;
1818 assert(size());
1819 }
1820
1821 const Formula &operator=(Detail::Temp r) {
1822 assert(!root && "Can't change formulas");
1823 root = r;
1824 assert(size());
1825 return *this;
1826 }
1827
1828 const Formula &operator+=(Detail::Temp r) {
1829 using namespace Detail;
1830 if (root)
1831 root = NodePtr(new BinaryNode<std::plus<result_t> >(root, r));
1832 else
1833 root = r;
1834 assert(size());
1835 return *this;
1836 }
1837
1838 const rvec_t &val() const { return root->val(); }
1839 result_t total() const { return root->total(); }
1840
1841 size_t size() const {
1842 if (!root)
1843 return 0;
1844 else
1845 return root->size();
1846 }
1847 };
1848
1849 void check();
1850 void dump(std::ostream &stream);
1851
1852 inline Detail::Temp
1853 operator+(Detail::Temp l, Detail::Temp r)
1854 {
1855 using namespace Detail;
1856 return NodePtr(new BinaryNode<std::plus<result_t> >(l, r));
1857 }
1858
1859 inline Detail::Temp
1860 operator-(Detail::Temp l, Detail::Temp r)
1861 {
1862 using namespace Detail;
1863 return NodePtr(new BinaryNode<std::minus<result_t> >(l, r));
1864 }
1865
1866 inline Detail::Temp
1867 operator*(Detail::Temp l, Detail::Temp r)
1868 {
1869 using namespace Detail;
1870 return NodePtr(new BinaryNode<std::multiplies<result_t> >(l, r));
1871 }
1872
1873 inline Detail::Temp
1874 operator/(Detail::Temp l, Detail::Temp r)
1875 {
1876 using namespace Detail;
1877 return NodePtr(new BinaryNode<std::divides<result_t> >(l, r));
1878 }
1879
1880 inline Detail::Temp
1881 operator%(Detail::Temp l, Detail::Temp r)
1882 {
1883 using namespace Detail;
1884 return NodePtr(new BinaryNode<std::modulus<result_t> >(l, r));
1885 }
1886
1887 inline Detail::Temp
1888 operator-(Detail::Temp l)
1889 {
1890 using namespace Detail;
1891 return NodePtr(new UnaryNode<std::negate<result_t> >(l));
1892 }
1893
1894 template <typename T>
1895 inline Detail::Temp
1896 constant(T val)
1897 {
1898 using namespace Detail;
1899 return NodePtr(new ConstNode<T>(val));
1900 }
1901
1902 template <typename T>
1903 inline Detail::Temp
1904 functor(T &val)
1905 {
1906 using namespace Detail;
1907 return NodePtr(new FunctorNode<T>(val));
1908 }
1909
1910 template <typename T>
1911 inline Detail::Temp
1912 scalar(T &val)
1913 {
1914 using namespace Detail;
1915 return NodePtr(new ScalarNode<T>(val));
1916 }
1917
1918 inline Detail::Temp
1919 sum(Detail::Temp val)
1920 {
1921 using namespace Detail;
1922 return NodePtr(new SumNode<std::plus<result_t> >(val));
1923 }
1924
1925 extern bool PrintDescriptions;
1926
1927 } // namespace statistics
1928
1929 #endif // __STATISTICS_HH__