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