2 * Copyright (c) 2003 The Regents of The University of Michigan
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.
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.
30 * Declaration of Statistics objects.
36 * Generalized N-dimensinal vector
40 * -- these both can use the same function that prints out a
41 * specific set of stats
42 * VectorStandardDeviation totals
45 #ifndef __STATISTICS_HH__
46 #define __STATISTICS_HH__
57 #include "base/refcnt.hh"
58 #include "base/str.hh"
59 #include "base/intmath.hh"
61 #include "sim/host.hh"
64 #include "base/trace.hh"
67 // Un-comment this to enable weirdo-stat debugging
74 /** Define Not a number. */
76 /** Need to define __nan() */
80 /** Print stats out in SS format. */
81 #define STAT_DISPLAY_COMPAT
85 /** The current simulated cycle. */
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;
96 * Define the storage for format flags.
97 * @todo Can probably shrink this.
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;
119 /* Contains the statistic implementation details */
121 //////////////////////////////////////////////////////////////////////
123 // Statistics Framework Base classes
125 //////////////////////////////////////////////////////////////////////
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.
137 /** Mark this statistics as initialized. */
140 * Finds and returns the associated StatData from the database.
141 * @return The formatting and output data of this statistic.
145 * Finds and returns a const pointer to the associated StatData.
146 * @return The formatting and output data of this statistic.
148 const StatData *mydata() const;
150 * Mark this stat for output at the end of simulation.
151 * @return The formatting and output data of this statistic.
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.
159 const SubData *mysubdata(int index) const;
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.
165 SubData *mysubdata_create(int index);
169 * Return the name of this stat.
170 * @return the name of the stat.
172 virtual std::string myname() const;
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.
178 virtual std::string mysubname(int index) const;
180 * Return the description of this stat.
181 * @return the description of this stat.
183 virtual std::string mydesc() const;
185 * Return the description of the subfield at the given index.
186 * @param index The subfield index.
187 * @return the description of the subfield.
189 virtual std::string mysubdesc(int index) const;
191 * Return the format flags of this stat.
192 * @return the format flags.
194 virtual FormatFlags myflags() const;
196 * Return true if this stat's prereqs have been satisfied (they are non
198 * @return true if the prerequisite stats aren't zero.
200 virtual bool dodisplay() const;
202 * Return the display percision.
203 * @return The display precision.
205 virtual int myprecision() const;
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.
220 * Print this stat to the given ostream.
221 * @param stream The stream to print to.
223 virtual void display(std::ostream &stream) const = 0;
225 * Reset this stat to the default state.
227 virtual void reset() = 0;
229 * Return the number of entries in this stat.
230 * @return The number of entries.
232 virtual size_t size() const = 0;
234 * Return true if the stat has value zero.
235 * @return True if the stat is zero.
237 virtual bool zero() const = 0;
240 * Return true if stat is binned.
241 *@return True is stat is binned.
243 virtual bool binned() const = 0;
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.
250 Stat &name(const std::string &name);
252 * Set the description and marks this stat to print at the end of
254 * @param desc The new description.
255 * @return A reference to this stat.
257 Stat &desc(const std::string &desc);
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.
263 Stat &precision(int p);
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.
269 Stat &flags(FormatFlags f);
271 * Set the prerequisite stat and marks this stat to print at the end of
273 * @param prereq The prerequisite stat.
274 * @return A reference to this stat.
276 Stat &prereq(const Stat &prereq);
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.
284 Stat &subname(int index, const std::string &name);
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.
292 Stat &subdesc(int index, const std::string &desc);
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
299 * @param stat1 The first stat.
300 * @param stat2 The second stat.
301 * @return stat1's name is alphabetically before stat2's
303 static bool less(Stat *stat1, Stat *stat2);
306 /** A unique ID used for debugging. */
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.
315 class ScalarStat : public Stat
319 * Create and perhaps register this stat with the database.
320 * @param reg If true, register this stat with the database.
322 ScalarStat(bool reg) : Stat(reg) {}
324 * Return the current value of this statistic as a result type.
325 * @return The current value of this statistic.
327 virtual result_t val() const = 0;
329 * Return true if this stat has value zero.
330 * @return True if this stat is zero.
332 virtual bool zero() const;
334 * Print this stat to the provided ostream.
335 * @param stream The output stream.
337 virtual void display(std::ostream &stream) const;
340 * Return true if stat is binned.
341 *@return True is stat is binned.
343 virtual bool binned() const = 0;
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,
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
359 class VectorStat : public Stat
363 * Create and perhaps register this stat with the database.
364 * @param reg If true, register this stat with the database.
366 VectorStat(bool reg) : Stat(reg) {}
368 * Return a vector of result typesd of all the values in the vector.
369 * @return The values of the vector.
371 virtual const rvec_t &val() const = 0;
373 * Return the total of all the entries in the vector.
374 * @return The total of the vector.
376 virtual result_t total() const = 0;
378 * Return true if this stat has value zero.
379 * @return True if this stat is zero.
381 virtual bool zero() const;
383 * Print this stat to the provided ostream.
384 * @param stream The output stream.
386 virtual void display(std::ostream &stream) const;
389 * Return true if stat is binned.
390 *@return True is stat is binned.
392 virtual bool binned() const = 0;
395 //////////////////////////////////////////////////////////////////////
399 //////////////////////////////////////////////////////////////////////
402 * Templatized storage and interface for a simple scalar stat.
404 template <typename T>
408 /** The paramaters for this storage type, none for a scalar. */
412 /** The statistic value. */
417 * Builds this storage element and calls the base constructor of the
420 StatStor(const Params &) : data(T()) {}
423 * The the stat to the given value.
424 * @param val The new value.
425 * @param p The paramters of this storage type.
427 void set(T val, const Params &p) { data = val; }
429 * Increment the stat by the given value.
430 * @param val The new value.
431 * @param p The paramters of this storage type.
433 void inc(T val, const Params &p) { data += val; }
435 * Decrement the stat by the given value.
436 * @param val The new value.
437 * @param p The paramters of this storage type.
439 void dec(T val, const Params &p) { data -= val; }
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.
445 result_t val(const Params &p) const { return (result_t)data; }
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.
451 T value(const Params &p) const { return data; }
453 * Reset stat value to default
455 void reset() { data = T(); }
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.
466 template <typename T>
470 /** The paramaters for this storage type */
474 * The current count. We stash this here because the current
475 * value is not a binned value.
481 /** The total count for all cycles. */
482 mutable result_t total;
483 /** The cycle that current last changed. */
488 * Build and initializes this stat storage.
490 AvgStor(Params &p) : total(0), last(0) { p.current = T(); }
493 * Set the current count to the one provided, update the total and last
495 * @param val The new count.
496 * @param p The parameters for this storage.
498 void set(T val, Params &p) {
499 total += p.current * (curTick - last);
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.
509 void inc(T val, Params &p) { set(p.current + val, p); }
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.
516 void dec(T val, Params &p) { set(p.current - val, p); }
519 * Return the current average.
520 * @param p The parameters for this storage.
521 * @return The current average.
523 result_t val(const Params &p) const {
524 total += p.current * (curTick - last);
526 return (result_t)(total + p.current) / (result_t)(curTick + 1);
530 * Return the current count.
531 * @param p The parameters for this storage.
532 * @return The current count.
534 T value(const Params &p) const { return p.current; }
537 * Reset stat value to default
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.
551 template <typename T, template <typename T> class Storage, class Bin>
552 class ScalarBase : public ScalarStat
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;
563 /** The bin of this stat. */
565 /** The parameters for this stat. */
570 * Retrieve the storage from the bin.
571 * @return The storage object for this stat.
573 storage_t *data() { return bin.data(params); }
575 * Retrieve a const pointer to the storage from the bin.
576 * @return A const pointer to the storage object for this stat.
578 const storage_t *data() const
580 bin_t *_bin = const_cast<bin_t *>(&bin);
581 params_t *_params = const_cast<params_t *>(¶ms);
582 return _bin->data(*_params);
587 * Copy constructor, copies are not allowed.
589 ScalarBase(const ScalarBase &stat);
593 const ScalarBase &operator=(const ScalarBase &);
597 * Return the current value of this stat as a result type.
598 * @return The current value.
600 result_t val() const { return data()->val(params); }
602 * Return the current value of this stat as its base type.
603 * @return The current value.
605 T value() const { return data()->value(params); }
609 * Create and initialize this stat, register it with the database.
611 ScalarBase() : ScalarStat(true) {
617 // Common operators for stats
619 * Increment the stat by 1. This calls the associated storage object inc
622 void operator++() { data()->inc(1, params); }
624 * Decrement the stat by 1. This calls the associated storage object dec
627 void operator--() { data()->dec(1, params); }
629 /** Increment the stat by 1. */
630 void operator++(int) { ++*this; }
631 /** Decrement the stat by 1. */
632 void operator--(int) { --*this; }
635 * Set the data value to the given value. This calls the associated storage
636 * object set function.
637 * @param v The new value.
639 template <typename U>
640 void operator=(const U& v) { data()->set(v, params); }
643 * Increment the stat by the given value. This calls the associated
644 * storage object inc function.
645 * @param v The value to add.
647 template <typename U>
648 void operator+=(const U& v) { data()->inc(v, params); }
651 * Decrement the stat by the given value. This calls the associated
652 * storage object dec function.
653 * @param v The value to substract.
655 template <typename U>
656 void operator-=(const U& v) { data()->dec(v, params); }
659 * Return the number of elements, always 1 for a scalar.
662 virtual size_t size() const { return 1; }
664 * Return true if stat is binned.
665 *@return True is stat is binned.
667 virtual bool binned() const { return bin_t::binned; }
670 * Reset stat value to default
672 void reset() { bin.reset(); }
675 //////////////////////////////////////////////////////////////////////
679 //////////////////////////////////////////////////////////////////////
680 template <typename T, template <typename T> class Storage, class Bin>
684 * Implementation of a vector of stats. The type of stat is determined by the
685 * Storage class. @sa ScalarBase
687 template <typename T, template <typename T> class Storage, class Bin>
688 class VectorBase : public VectorStat
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;
699 /** Local storage for the entry values, used for printing. */
703 /** The bin of this stat. */
705 /** The parameters for this stat. */
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.
714 storage_t *data(int index) { return bin.data(index, params); }
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.
721 const storage_t *data(int index) const
723 bin_t *_bin = const_cast<bin_t *>(&bin);
724 params_t *_params = const_cast<params_t *>(¶ms);
725 return _bin->data(index, *_params);
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 &);
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.
740 const rvec_t &val() const {
744 vec = new rvec_t(size());
746 for (int i = 0; i < size(); ++i)
747 (*vec)[i] = data(i)->val(params);
753 * Return a total of all entries in this vector.
754 * @return The total of all vector entries.
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);
765 * Create this vector and register it with the database.
767 VectorBase() : VectorStat(true), vec(NULL) {}
771 ~VectorBase() { if (vec) delete vec; }
774 * Set this vector to have the given size.
775 * @param size The new size.
776 * @return A reference to this stat.
778 VectorBase &init(size_t size) {
779 bin.init(size, params);
785 /** Friend this class with the associated scalar proxy. */
786 friend class ScalarProxy<T, Storage, Bin>;
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.
793 ScalarProxy<T, Storage, Bin> operator[](int index);
796 * Return the number of elements in this vector.
797 * @return The size of the vector.
799 virtual size_t size() const { return bin.size(); }
801 * Return true if stat is binned.
802 *@return True is stat is binned.
804 virtual bool binned() const { return bin_t::binned; }
806 * Reset stat value to default
808 virtual void reset() { bin.reset(); }
812 * A proxy class to access the stat at a given index in a VectorBase stat.
813 * Behaves like a ScalarBase.
815 template <typename T, template <typename T> class Storage, class Bin>
816 class ScalarProxy : public ScalarStat
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;
827 /** Pointer to the bin in the parent VectorBase. */
829 /** Pointer to the params in the parent VectorBase. */
831 /** The index to access in the parent VectorBase. */
836 * Retrieve the storage from the bin.
837 * @return The storage from the bin for this stat.
839 storage_t *data() { return bin->data(index, *params); }
841 * Retrieve a const pointer to the storage from the bin.
842 * @return A const pointer to the storage for this stat.
844 const storage_t *data() const
846 bin_t *_bin = const_cast<bin_t *>(bin);
847 params_t *_params = const_cast<params_t *>(params);
848 return _bin->data(index, *_params);
853 * Return the current value of this statas a result type.
854 * @return The current value.
856 result_t val() const { return data()->val(*params); }
858 * Return the current value of this stat as its base type.
859 * @return The current value.
861 T value() const { return data()->value(*params); }
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.
870 ScalarProxy(bin_t &b, params_t &p, int i)
871 : ScalarStat(false), bin(&b), params(&p), index(i) {}
873 * Create a copy of the provided ScalarProxy.
874 * @param sp The proxy to copy.
876 ScalarProxy(const ScalarProxy &sp)
877 : ScalarStat(false), bin(sp.bin), params(sp.params), index(sp.index) {}
879 * Set this proxy equal to the provided one.
880 * @param sp The proxy to copy.
881 * @return A reference to this proxy.
883 const ScalarProxy &operator=(const ScalarProxy &sp) {
891 // Common operators for stats
893 * Increment the stat by 1. This calls the associated storage object inc
896 void operator++() { data()->inc(1, *params); }
898 * Decrement the stat by 1. This calls the associated storage object dec
901 void operator--() { data()->dec(1, *params); }
903 /** Increment the stat by 1. */
904 void operator++(int) { ++*this; }
905 /** Decrement the stat by 1. */
906 void operator--(int) { --*this; }
909 * Set the data value to the given value. This calls the associated storage
910 * object set function.
911 * @param v The new value.
913 template <typename U>
914 void operator=(const U& v) { data()->set(v, *params); }
917 * Increment the stat by the given value. This calls the associated
918 * storage object inc function.
919 * @param v The value to add.
921 template <typename U>
922 void operator+=(const U& v) { data()->inc(v, *params); }
925 * Decrement the stat by the given value. This calls the associated
926 * storage object dec function.
927 * @param v The value to substract.
929 template <typename U>
930 void operator-=(const U& v) { data()->dec(v, *params); }
933 * Return the number of elements, always 1 for a scalar.
936 virtual size_t size() const { return 1; }
938 * Return true if stat is binned.
939 *@return false since Proxies aren't printed/binned
941 virtual bool binned() const { return false; }
943 * This stat has no state. Nothing to reset
945 virtual void reset() { }
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)
952 assert (index >= 0 && index < size());
953 return ScalarProxy<T, Storage, Bin>(bin, params, index);
956 template <typename T, template <typename T> class Storage, class Bin>
959 template <typename T, template <typename T> class Storage, class Bin>
960 class Vector2dBase : public Stat
963 typedef Storage<T> storage_t;
964 typedef typename storage_t::Params params_t;
965 typedef typename Bin::VectorBin<storage_t> bin_t;
972 std::vector<std::string> *y_subnames;
975 storage_t *data(int index) { return bin.data(index, params); }
976 const storage_t *data(int index) const
978 bin_t *_bin = const_cast<bin_t *>(&bin);
979 params_t *_params = const_cast<params_t *>(¶ms);
980 return _bin->data(index, *_params);
984 // Copying stats is not allowed
985 Vector2dBase(const Vector2dBase &stat);
986 const Vector2dBase &operator=(const Vector2dBase &);
989 Vector2dBase() : Stat(true) {}
992 Vector2dBase &init(size_t _x, size_t _y) {
995 bin.init(x * y, params);
997 y_subnames = new std::vector<std::string>(y);
1003 * @warning This makes the assumption that if you're gonna subnames a 2d
1004 * vector, you're subnaming across all y
1006 Vector2dBase &ysubnames(const char **names)
1008 for (int i=0; i < y; ++i) {
1009 (*y_subnames)[i] = names[i];
1013 Vector2dBase &ysubname(int index, const std::string subname)
1015 (*y_subnames)[i] = subname.c_str();
1018 std::string ysubname(int i) const { return (*y_subnames)[i]; }
1020 friend class VectorProxy<T, Storage, Bin>;
1021 VectorProxy<T, Storage, Bin> operator[](int index);
1023 virtual size_t size() const { return bin.size(); }
1024 virtual bool zero() const { return data(0)->value(params) == 0.0; }
1026 * Return true if stat is binned.
1027 *@return True is stat is binned.
1029 virtual bool binned() const { return bin_t::binned; }
1032 display(std::ostream &out) const
1034 bool have_subname = false;
1035 for (int i = 0; i < x; ++i) {
1036 if (!mysubname(i).empty())
1037 have_subname = true;
1041 result_t super_total = 0.0;
1042 for (int i = 0; i < x; ++i) {
1043 std::string subname;
1045 subname = mysubname(i);
1046 if (subname.empty())
1049 subname = to_string(i);
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];
1059 super_total += vec[j];
1063 if (mysubdesc(i).empty()) {
1066 desc = mysubdesc(i);
1069 VectorDisplay(out, myname() + "_" + subname, y_subnames, desc, 0,
1070 myprecision(), myflags(), vec, total);
1073 if ((myflags() & ::Statistics::total) && (x > 1)) {
1074 VectorDisplay(out, myname(), y_subnames, mydesc(), 0,
1075 myprecision(), myflags(), tot_vec, super_total);
1080 * Reset stat value to default
1082 virtual void reset() { bin.reset(); }
1085 template <typename T, template <typename T> class Storage, class Bin>
1086 class VectorProxy : public VectorStat
1089 typedef Storage<T> storage_t;
1090 typedef typename storage_t::Params params_t;
1091 typedef typename Bin::VectorBin<storage_t> bin_t;
1100 mutable rvec_t *vec;
1102 storage_t *data(int index) {
1103 assert(index < len);
1104 return bin->data(offset + index, *params);
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);
1114 const rvec_t &val() const {
1116 vec->resize(size());
1118 vec = new rvec_t(size());
1120 for (int i = 0; i < size(); ++i)
1121 (*vec)[i] = data(i)->val(*params);
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);
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)
1137 VectorProxy(const VectorProxy &sp)
1138 : VectorStat(false), bin(sp.bin), params(sp.params), offset(sp.offset),
1139 len(sp.len), vec(NULL)
1146 const VectorProxy &operator=(const VectorProxy &sp) {
1157 virtual size_t size() const { return len; }
1159 ScalarProxy<T, Storage, Bin> operator[](int index) {
1160 assert (index >= 0 && index < size());
1161 return ScalarProxy<T, Storage, Bin>(*bin, *params, offset + index);
1164 * Return true if stat is binned.
1165 *@return false since Proxies aren't printed/binned
1167 virtual bool binned() const { return false; }
1170 * This stat has no state. Nothing to reset.
1172 virtual void reset() { }
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)
1179 int offset = index * y;
1180 assert (index >= 0 && offset < size());
1181 return VectorProxy<T, Storage, Bin>(bin, params, offset, y);
1184 //////////////////////////////////////////////////////////////////////
1186 // Non formula statistics
1188 //////////////////////////////////////////////////////////////////////
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,
1197 * Templatized storage and interface for a distrbution stat.
1199 template <typename T>
1203 /** The parameters for a distribution stat. */
1206 /** The minimum value to track. */
1208 /** The maximum value to track. */
1210 /** The number of entries in each bucket. */
1212 /** The number of buckets. Equal to (max-min)/bucket_size. */
1217 /** The smallest value sampled. */
1219 /** The largest value sampled. */
1221 /** The number of values sampled less than min. */
1223 /** The number of values sampled more than max. */
1225 /** Counter for each bucket. */
1230 * Construct this storage with the supplied params.
1231 * @param params The parameters.
1233 DistStor(const Params ¶ms)
1234 : min_val(INT_MAX), max_val(INT_MIN), underflow(0), overflow(0),
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.
1246 void sample(T val, int number, const Params ¶ms) {
1247 if (val < params.min)
1248 underflow += number;
1249 else if (val > params.max)
1252 int index = (val - params.min) / params.bucket_size;
1253 assert(index < size(params));
1254 vec[index] += number;
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?
1269 size_t size(const Params &) const { return vec.size(); }
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.
1276 bool zero(const Params ¶ms) const {
1277 if (underflow != 0 || overflow != 0)
1280 int s = size(params);
1281 for (int i = 0; i < s; i++)
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.
1297 void display(std::ostream &stream, const std::string &name,
1298 const std::string &desc, int precision, FormatFlags flags,
1299 const Params ¶ms) const {
1301 #ifdef STAT_DISPLAY_COMPAT
1302 result_t min = params.min;
1304 result_t min = (min_val == INT_MAX) ? params.min : min_val;
1306 result_t max = (max_val == INT_MIN) ? 0 : max_val;
1308 rvec_t rvec(params.size);
1309 for (int i = 0; i < params.size; ++i)
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,
1319 * Reset stat value to default
1328 int size = vec.size();
1329 for (int i = 0; i < size; ++i)
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);
1340 * Templatized storage and interface for a distribution that calculates mean
1343 template <typename T>
1348 * No paramters for this storage.
1353 /** The current sum. */
1355 /** The sum of squares. */
1357 /** The total number of samples. */
1362 * Create and initialize this storage.
1364 FancyStor(const Params &) : sum(T()), squares(T()), total(0) {}
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.
1374 void sample(T val, int number, const Params &p) {
1375 T value = val * number;
1377 squares += value * value;
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.
1390 void display(std::ostream &stream, const std::string &name,
1391 const std::string &desc, int precision, FormatFlags flags,
1392 const Params ¶ms) const {
1394 result_t mean = NAN;
1395 result_t variance = NAN;
1397 result_t ftot = total;
1399 result_t fsum = sum;
1400 result_t fsq = squares;
1403 variance = (ftot * fsq - (fsum * fsum)) / (ftot * (ftot - 1.0));
1406 FancyDisplay(stream, name, desc, precision, flags, mean, variance, ftot);
1410 * Return the number of entries in this stat, 1
1413 size_t size(const Params &) const { return 1; }
1415 * Return true if no samples have been added.
1416 * @return True if no samples have been added.
1418 bool zero(const Params &) const { return total == 0; }
1420 * Reset stat value to default
1422 virtual void reset()
1431 * Templatized storage for distribution that calculates per cycle mean and
1434 template <typename T>
1438 /** No parameters for this storage. */
1442 /** Current total. */
1444 /** Current sum of squares. */
1449 * Create and initialize this storage.
1451 AvgFancy(const Params &) : sum(T()), squares(T()) {}
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.
1460 void sample(T val, int number, const Params& p) {
1461 T value = val * number;
1463 squares += value * value;
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.
1475 void display(std::ostream &stream, const std::string &name,
1476 const std::string &desc, int precision, FormatFlags flags,
1477 const Params ¶ms) const {
1478 result_t mean = sum / curTick;
1479 result_t variance = (squares - sum * sum) / curTick;
1481 FancyDisplay(stream, name, desc, precision, flags, mean, variance);
1485 * Return the number of entries, in this case 1.
1488 size_t size(const Params ¶ms) const { return 1; }
1490 * Return true if no samples have been added.
1491 * @return True if the sum is zero.
1493 bool zero(const Params ¶ms) const { return sum == 0; }
1495 * Reset stat value to default
1497 virtual void reset()
1505 * Implementation of a distribution stat. The type of distribution is
1506 * determined by the Storage template. @sa ScalarBase
1508 template <typename T, template <typename T> class Storage, class Bin>
1509 class DistBase : public Stat
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;
1520 /** The bin of this stat. */
1522 /** The parameters for this stat. */
1527 * Retrieve the storage from the bin.
1528 * @return The storage object for this stat.
1530 storage_t *data() { return bin.data(params); }
1532 * Retrieve a const pointer to the storage from the bin.
1533 * @return A const pointer to the storage object for this stat.
1535 const storage_t *data() const
1537 bin_t *_bin = const_cast<bin_t *>(&bin);
1538 params_t *_params = const_cast<params_t *>(¶ms);
1539 return _bin->data(*_params);
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 &);
1551 * Create this distrubition and register it with the database.
1553 DistBase() : Stat(true) { }
1560 * Add a value to the distribtion n times. Calls sample on the storage
1562 * @param v The value to add.
1563 * @param n The number of times to add it, defaults to 1.
1565 template <typename U>
1566 void sample(const U& v, int n = 1) { data()->sample(v, n, params); }
1569 * Return the number of entries in this stat.
1570 * @return The number of entries.
1572 virtual size_t size() const { return data()->size(params); }
1574 * Return true if no samples have been added.
1575 * @return True if there haven't been any samples.
1577 virtual bool zero() const { return data()->zero(params); }
1579 * Print this distribution to the given ostream.
1580 * @param stream The output stream.
1582 virtual void display(std::ostream &stream) const {
1583 data()->display(stream, myname(), mydesc(), myprecision(), myflags(),
1587 * Return true if stat is binned.
1588 *@return True is stat is binned.
1590 virtual bool binned() const { return bin_t::binned; }
1592 * Reset stat value to default
1594 virtual void reset()
1600 template <typename T, template <typename T> class Storage, class Bin>
1603 template <typename T, template <typename T> class Storage, class Bin>
1604 class VectorDistBase : public Stat
1607 typedef Storage<T> storage_t;
1608 typedef typename storage_t::Params params_t;
1609 typedef typename Bin::VectorBin<storage_t> bin_t;
1616 storage_t *data(int index) { return bin.data(index, params); }
1617 const storage_t *data(int index) const
1619 bin_t *_bin = const_cast<bin_t *>(&bin);
1620 params_t *_params = const_cast<params_t *>(¶ms);
1621 return _bin->data(index, *_params);
1625 // Copying stats is not allowed
1626 VectorDistBase(const VectorDistBase &stat);
1627 const VectorDistBase &operator=(const VectorDistBase &);
1630 VectorDistBase() : Stat(true) { }
1631 ~VectorDistBase() { }
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;
1637 virtual size_t size() const { return bin.size(); }
1638 virtual bool zero() const { return false; }
1639 virtual void display(std::ostream &stream) const;
1641 * Return true if stat is binned.
1642 *@return True is stat is binned.
1644 virtual bool binned() const { return bin_t::binned; }
1646 * Reset stat value to default
1648 virtual void reset()
1654 template <typename T, template <typename T> class Storage, class Bin>
1655 class DistProxy : public Stat
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;
1666 const base_t *cstat;
1671 storage_t *data() { return stat->data(index); }
1672 const storage_t *data() const { return cstat->data(index); }
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;
1684 template <typename U>
1685 void sample(const U& v, int n = 1) { data()->sample(v, n, cstat->params); }
1687 virtual size_t size() const { return 1; }
1688 virtual bool zero() const {
1689 return data()->zero(cstat->params);
1691 virtual void display(std::ostream &stream) const {
1692 std::stringstream name, desc;
1694 if (!(cstat->mysubname(index).empty())) {
1695 name << cstat->myname() << cstat->mysubname(index);
1697 name << cstat->myname() << "_" << index;
1699 if (!(cstat->mysubdesc(index).empty())) {
1700 desc << cstat->mysubdesc(index);
1702 desc << cstat->mydesc();
1705 data()->display(stream, name.str(), desc.str(),
1706 cstat->myprecision(), cstat->myflags(), cstat->params);
1709 * Return true if stat is binned.
1710 *@return false since Proxies are not binned/printed.
1712 virtual bool binned() const { return false; }
1714 * Proxy has no state. Nothing to reset.
1716 virtual void reset() { }
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)
1723 assert (index >= 0 && index < size());
1724 return DistProxy<T, Storage, Bin>(*this, index);
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
1731 assert (index >= 0 && index < size());
1732 return DistProxy<T, Storage, Bin>(*this, index);
1736 * @todo Need a way to print Distribution totals across the Vector
1738 template <typename T, template <typename T> class Storage, class Bin>
1740 VectorDistBase<T, Storage, Bin>::display(std::ostream &stream) const
1742 for (int i = 0; i < size(); ++i) {
1743 DistProxy<T, Storage, Bin> proxy(*this, i);
1744 proxy.display(stream);
1750 VectorDistBase<T, Storage, Bin>::total(int index) const
1753 for (int i=0; i < x_size(); ++i) {
1754 total += data(i)->val(*params);
1759 //////////////////////////////////////////////////////////////////////
1763 //////////////////////////////////////////////////////////////////////
1766 * Base class for formula statistic node. These nodes are used to build a tree
1767 * that represents the formula.
1769 class Node : public RefCounted
1773 * Return the number of nodes in the subtree starting at this node.
1774 * @return the number of nodes in this subtree.
1776 virtual size_t size() const = 0;
1778 * Return the result vector of this subtree.
1779 * @return The result vector of this subtree.
1781 virtual const rvec_t &val() const = 0;
1783 * Return the total of the result vector.
1784 * @return The total of the result vector.
1786 virtual result_t total() const = 0;
1788 * Return true if stat is binned.
1789 *@return True is stat is binned.
1791 virtual bool binned() const = 0;
1794 /** Reference counting pointer to a function Node. */
1795 typedef RefCountingPtr<Node> NodePtr;
1797 class ScalarStatNode : public Node
1800 const ScalarStat &stat;
1801 mutable rvec_t result;
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(); };
1808 virtual size_t size() const { return 1; }
1810 * Return true if stat is binned.
1811 *@return True is stat is binned.
1813 virtual bool binned() const { return stat.binned(); }
1816 template <typename T, template <typename T> class Storage, class Bin>
1817 class ScalarProxyNode : public Node
1820 const ScalarProxy<T, Storage, Bin> proxy;
1821 mutable rvec_t result;
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(); };
1829 virtual size_t size() const { return 1; }
1831 * Return true if stat is binned.
1832 *@return True is stat is binned.
1834 virtual bool binned() const { return proxy.binned(); }
1837 class VectorStatNode : public Node
1840 const VectorStat &stat;
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(); };
1847 virtual size_t size() const { return stat.size(); }
1849 * Return true if stat is binned.
1850 *@return True is stat is binned.
1852 virtual bool binned() const { return stat.binned(); }
1855 template <typename T>
1856 class ConstNode : public Node
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]; };
1866 virtual size_t size() const { return 1; }
1868 * Return true if stat is binned.
1869 *@return False since constants aren't binned.
1871 virtual bool binned() const { return false; }
1874 template <typename T>
1875 class FunctorNode : public Node
1879 mutable rvec_t result;
1882 FunctorNode(T &f) : functor(f) { result.resize(1); }
1883 const rvec_t &val() const {
1884 result[0] = (result_t)functor();
1887 virtual result_t total() const { return (result_t)functor(); };
1889 virtual size_t size() const { return 1; }
1891 * Return true if stat is binned.
1892 *@return False since Functors aren't binned
1894 virtual bool binned() const { return false; }
1897 template <typename T>
1898 class ScalarNode : public Node
1902 mutable rvec_t result;
1905 ScalarNode(T &s) : scalar(s) { result.resize(1); }
1906 const rvec_t &val() const {
1907 result[0] = (result_t)scalar;
1910 virtual result_t total() const { return (result_t)scalar; };
1912 virtual size_t size() const { return 1; }
1914 * Return true if stat is binned.
1915 *@return False since Scalar's aren't binned
1917 virtual bool binned() const { return false; }
1921 class UnaryNode : public Node
1925 mutable rvec_t result;
1928 UnaryNode(NodePtr p) : l(p) {}
1930 const rvec_t &val() const {
1931 const rvec_t &lvec = l->val();
1932 int size = lvec.size();
1936 result.resize(size);
1938 for (int i = 0; i < size; ++i)
1939 result[i] = op(lvec[i]);
1944 result_t total() const {
1946 return op(l->total());
1949 virtual size_t size() const { return l->size(); }
1951 * Return true if child of node is binned.
1952 *@return True if child of node is binned.
1954 virtual bool binned() const { return l->binned(); }
1958 class BinaryNode : public Node
1963 mutable rvec_t result;
1966 BinaryNode(NodePtr a, NodePtr b) : l(a), r(b) {}
1968 const rvec_t &val() const {
1970 const rvec_t &lvec = l->val();
1971 const rvec_t &rvec = r->val();
1973 assert(lvec.size() > 0 && rvec.size() > 0);
1975 if (lvec.size() == 1 && rvec.size() == 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]);
1998 result_t total() const {
2000 return op(l->total(), r->total());
2003 virtual size_t size() const {
2011 assert(ls == rs && "Node vector sizes are not equal");
2016 * Return true if any children of node are binned
2017 *@return True if either child of node is binned.
2019 virtual bool binned() const { return (l->binned() || r->binned()); }
2023 class SumNode : public Node
2027 mutable rvec_t result;
2030 SumNode(NodePtr p) : l(p), result(1) {}
2032 const rvec_t &val() const {
2033 const rvec_t &lvec = l->val();
2034 int size = lvec.size();
2040 for (int i = 0; i < size; ++i)
2041 result[0] = op(result[0], lvec[i]);
2046 result_t total() const {
2047 const rvec_t &lvec = l->val();
2048 int size = lvec.size();
2051 result_t result = 0.0;
2054 for (int i = 0; i < size; ++i)
2055 result = op(result, lvec[i]);
2060 virtual size_t size() const { return 1; }
2062 * Return true if child of node is binned.
2063 *@return True if child of node is binned.
2065 virtual bool binned() const { return l->binned(); }
2069 * Helper class to construct formula node trees.
2075 * Pointer to a Node object.
2081 * Copy the given pointer to this class.
2082 * @param n A pointer to a Node object to copy.
2084 Temp(NodePtr n) : node(n) {}
2086 * Create a new ScalarStatNode.
2087 * @param s The ScalarStat to place in a node.
2089 Temp(const ScalarStat &s) : node(new ScalarStatNode(s)) {}
2091 * Create a new ScalarProxyNode.
2092 * @param p The ScalarProxy to place in a node.
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)) {}
2098 * Create a new VectorStatNode.
2099 * @param s The VectorStat to place in a node.
2101 Temp(const VectorStat &s) : node(new VectorStatNode(s)) {}
2104 * Create a ConstNode
2105 * @param value The value of the const node.
2107 Temp(signed char value) : node(new ConstNode<signed char>(value)) {}
2109 * Create a ConstNode
2110 * @param value The value of the const node.
2112 Temp(unsigned char value) : node(new ConstNode<unsigned char>(value)) {}
2114 * Create a ConstNode
2115 * @param value The value of the const node.
2117 Temp(signed short value) : node(new ConstNode<signed short>(value)) {}
2119 * Create a ConstNode
2120 * @param value The value of the const node.
2122 Temp(unsigned short value) : node(new ConstNode<unsigned short>(value)) {}
2124 * Create a ConstNode
2125 * @param value The value of the const node.
2127 Temp(signed int value) : node(new ConstNode<signed int>(value)) {}
2129 * Create a ConstNode
2130 * @param value The value of the const node.
2132 Temp(unsigned int value) : node(new ConstNode<unsigned int>(value)) {}
2134 * Create a ConstNode
2135 * @param value The value of the const node.
2137 Temp(signed long value) : node(new ConstNode<signed long>(value)) {}
2139 * Create a ConstNode
2140 * @param value The value of the const node.
2142 Temp(unsigned long value) : node(new ConstNode<unsigned long>(value)) {}
2144 * Create a ConstNode
2145 * @param value The value of the const node.
2147 Temp(signed long long value)
2148 : node(new ConstNode<signed long long>(value)) {}
2150 * Create a ConstNode
2151 * @param value The value of the const node.
2153 Temp(unsigned long long value)
2154 : node(new ConstNode<unsigned long long>(value)) {}
2156 * Create a ConstNode
2157 * @param value The value of the const node.
2159 Temp(float value) : node(new ConstNode<float>(value)) {}
2161 * Create a ConstNode
2162 * @param value The value of the const node.
2164 Temp(double value) : node(new ConstNode<double>(value)) {}
2167 * Return the node pointer.
2168 * @return the node pointer.
2170 operator NodePtr() { return node;}
2174 //////////////////////////////////////////////////////////////////////
2176 // Binning Interface
2178 //////////////////////////////////////////////////////////////////////
2187 off_t size() const { return memsize; }
2195 } // namespace Detail
2197 class GenBin : public Detail::BinBase
2200 GenBin() : BinBase() {}
2201 virtual ~GenBin() {};
2203 virtual void activate() = 0;
2204 virtual std::string name() const = 0;
2205 void regBin(GenBin *bin, std::string name);
2208 template <class BinType>
2209 struct StatBin : public GenBin
2215 std::string name() const { return _name;}
2217 static StatBin *&curBin() {
2218 static StatBin *current = NULL;
2222 static void setCurBin(StatBin *bin) { curBin() = bin; }
2223 static StatBin *current() { assert(curBin()); return curBin(); }
2225 static off_t &offset() {
2226 static off_t offset = 0;
2230 static off_t new_offset(size_t size) {
2231 size_t mask = sizeof(u_int64_t) - 1;
2232 off_t off = offset();
2234 // That one is for the last trailing flags byte.
2235 offset() += (size + 1 + mask) & ~mask;
2239 explicit StatBin(std::string name) : GenBin() { _name = name; this->regBin(this, name); }
2241 char *memory(off_t off) {
2242 if (memsize == -1) {
2243 memsize = CeilPow2((size_t) offset());
2245 assert(offset() <= size());
2246 return Detail::BinBase::memory() + off;
2249 virtual void activate() {
2252 DPRINTF(TCPIP, "activating %s Bin\n", name());
2255 static void activate(StatBin &bin) { setCurBin(&bin); }
2263 BinBase() : offset(-1) {}
2264 void allocate(size_t size) {
2265 offset = new_offset(size);
2268 assert(offset != -1);
2269 return current()->memory(offset);
2273 template <class Storage>
2274 class Bin : public BinBase
2277 typedef typename Storage::Params Params;
2280 enum { binned = true };
2281 Bin() { allocate(sizeof(Storage)); }
2282 bool initialized() const { return true; }
2283 void init(Params ¶ms) { }
2285 int size() const { return 1; }
2287 Storage *data(Params ¶ms) {
2288 assert(initialized());
2289 char *ptr = access();
2290 char *flags = ptr + sizeof(Storage);
2291 if (!(*flags & 0x1)) {
2293 new (ptr) Storage(params);
2295 return reinterpret_cast<Storage *>(ptr);
2299 char *ptr = access();
2300 char *flags = ptr + size() * sizeof(Storage);
2301 if (!(*flags & 0x1))
2304 Storage *s = reinterpret_cast<Storage *>(ptr);
2309 template <class Storage>
2310 class VectorBin : public BinBase
2313 typedef typename Storage::Params Params;
2319 enum { binned = true };
2320 VectorBin() : _size(0) {}
2322 bool initialized() const { return _size > 0; }
2323 void init(int s, Params ¶ms) {
2324 assert(!initialized());
2327 allocate(_size * sizeof(Storage));
2330 int size() const { return _size; }
2332 Storage *data(int index, Params ¶ms) {
2333 assert(initialized());
2334 assert(index >= 0 && index < size());
2335 char *ptr = access();
2336 char *flags = ptr + size() * sizeof(Storage);
2337 if (!(*flags & 0x1)) {
2339 for (int i = 0; i < size(); ++i)
2340 new (ptr + i * sizeof(Storage)) Storage(params);
2342 return reinterpret_cast<Storage *>(ptr + index * sizeof(Storage));
2346 char *ptr = access();
2347 char *flags = ptr + size() * sizeof(Storage);
2348 if (!(*flags & 0x1))
2351 for (int i = 0; i < _size; ++i) {
2352 char *p = ptr + i * sizeof(Storage);
2353 Storage *s = reinterpret_cast<Storage *>(p);
2360 class MainBinType {};
2361 typedef StatBin<MainBinType> MainBin;
2365 template <class Storage>
2369 typedef typename Storage::Params Params;
2370 enum { binned = false };
2373 char ptr[sizeof(Storage)];
2378 reinterpret_cast<Storage *>(ptr)->~Storage();
2381 bool initialized() const { return true; }
2382 void init(Params ¶ms) {
2383 new (ptr) Storage(params);
2385 int size() const{ return 1; }
2386 Storage *data(Params ¶ms) {
2387 assert(initialized());
2388 return reinterpret_cast<Storage *>(ptr);
2392 Storage *s = reinterpret_cast<Storage *>(ptr);
2397 template <class Storage>
2401 typedef typename Storage::Params Params;
2402 enum { binned = false };
2409 VectorBin() : ptr(NULL) { }
2415 for (int i = 0; i < _size; ++i) {
2416 char *p = ptr + i * sizeof(Storage);
2417 reinterpret_cast<Storage *>(p)->~Storage();
2422 bool initialized() const { return ptr != NULL; }
2423 void init(int s, Params ¶ms) {
2424 assert(s > 0 && "size must be positive!");
2425 assert(!initialized());
2427 ptr = new char[_size * sizeof(Storage)];
2428 for (int i = 0; i < _size; ++i)
2429 new (ptr + i * sizeof(Storage)) Storage(params);
2432 int size() const { return _size; }
2434 Storage *data(int index, Params ¶ms) {
2435 assert(initialized());
2436 assert(index >= 0 && index < size());
2437 return reinterpret_cast<Storage *>(ptr + index * sizeof(Storage));
2441 for (int i = 0; i < _size; ++i) {
2442 char *p = ptr + i * sizeof(Storage);
2443 Storage *s = reinterpret_cast<Storage *>(p);
2450 //////////////////////////////////////////////////////////////////////
2452 // Visible Statistics Types
2454 //////////////////////////////////////////////////////////////////////
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.
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
2469 typedef MainBin DefaultBin;
2471 typedef NoBin DefaultBin;
2475 * This is a simple scalar statistic, like a counter.
2476 * @sa Stat, ScalarBase, StatStor
2478 template <typename T = Counter, class Bin = DefaultBin>
2479 class Scalar : public Detail::ScalarBase<T, Detail::StatStor, Bin>
2482 /** The base implementation. */
2483 typedef Detail::ScalarBase<T, Detail::StatStor, Bin> Base;
2486 * Sets the stat equal to the given value. Calls the base implementation
2488 * @param v The new value.
2490 template <typename U>
2491 void operator=(const U& v) { Base::operator=(v); }
2495 * A stat that calculates the per cycle average of a value.
2496 * @sa Stat, ScalarBase, AvgStor
2498 template <typename T = Counter, class Bin = DefaultBin>
2499 class Average : public Detail::ScalarBase<T, Detail::AvgStor, Bin>
2502 /** The base implementation. */
2503 typedef Detail::ScalarBase<T, Detail::AvgStor, Bin> Base;
2506 * Sets the stat equal to the given value. Calls the base implementation
2508 * @param v The new value.
2510 template <typename U>
2511 void operator=(const U& v) { Base::operator=(v); }
2515 * A vector of scalar stats.
2516 * @sa Stat, VectorBase, StatStor
2518 template <typename T = Counter, class Bin = DefaultBin>
2519 class Vector : public Detail::VectorBase<T, Detail::StatStor, Bin>
2523 * A vector of Average stats.
2524 * @sa Stat, VectorBase, AvgStor
2526 template <typename T = Counter, class Bin = DefaultBin>
2527 class AverageVector : public Detail::VectorBase<T, Detail::AvgStor, Bin>
2531 * A 2-Dimensional vecto of scalar stats.
2532 * @sa Stat, Vector2dBase, StatStor
2534 template <typename T = Counter, class Bin = DefaultBin>
2535 class Vector2d : public Detail::Vector2dBase<T, Detail::StatStor, Bin>
2539 * A simple distribution stat.
2540 * @sa Stat, DistBase, DistStor
2542 template <typename T = Counter, class Bin = DefaultBin>
2543 class Distribution : public Detail::DistBase<T, Detail::DistStor, Bin>
2546 /** Base implementation. */
2547 typedef Detail::DistBase<T, Detail::DistStor, Bin> Base;
2548 /** The Parameter type. */
2549 typedef typename Detail::DistStor<T>::Params Params;
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.
2559 Distribution &init(T min, T max, int bkt) {
2562 params.bucket_size = bkt;
2563 params.size = (max - min) / bkt + 1;
2572 * Calculates the mean and variance of all the samples.
2573 * @sa Stat, DistBase, FancyStor
2575 template <typename T = Counter, class Bin = DefaultBin>
2576 class StandardDeviation : public Detail::DistBase<T, Detail::FancyStor, Bin>
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;
2586 * Construct and initialize this distribution.
2588 StandardDeviation() {
2595 * Calculates the per cycle mean and variance of the samples.
2596 * @sa Stat, DistBase, AvgFancy
2598 template <typename T = Counter, class Bin = DefaultBin>
2599 class AverageDeviation : public Detail::DistBase<T, Detail::AvgFancy, Bin>
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;
2609 * Construct and initialize this distribution.
2611 AverageDeviation() {
2618 * A vector of distributions.
2619 * @sa Stat, VectorDistBase, DistStor
2621 template <typename T = Counter, class Bin = DefaultBin>
2622 class VectorDistribution
2623 : public Detail::VectorDistBase<T, Detail::DistStor, Bin>
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;
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.
2640 VectorDistribution &init(int size, T min, T max, int bkt) {
2643 params.bucket_size = bkt;
2644 params.size = (max - min) / bkt + 1;
2645 bin.init(size, params);
2653 * This is a vector of StandardDeviation stats.
2654 * @sa Stat, VectorDistBase, FancyStor
2656 template <typename T = Counter, class Bin = DefaultBin>
2657 class VectorStandardDeviation
2658 : public Detail::VectorDistBase<T, Detail::FancyStor, Bin>
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;
2668 * Initialize storage for this distribution.
2669 * @param size The size of the vector.
2670 * @return A reference to this distribution.
2672 VectorStandardDeviation &init(int size) {
2673 bin.init(size, params);
2681 * This is a vector of AverageDeviation stats.
2682 * @sa Stat, VectorDistBase, AvgFancy
2684 template <typename T = Counter, class Bin = DefaultBin>
2685 class VectorAverageDeviation
2686 : public Detail::VectorDistBase<T, Detail::AvgFancy, Bin>
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;
2696 * Initialize storage for this distribution.
2697 * @param size The size of the vector.
2698 * @return A reference to this distribution.
2700 VectorAverageDeviation &init(int size) {
2701 bin.init(size, params);
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
2713 class Formula : public Detail::VectorStat
2716 /** The root of the tree which represents the Formula */
2717 Detail::NodePtr root;
2718 friend class Statistics::Detail::Temp;
2722 * Create and initialize thie formula, and register it with the database.
2724 Formula() : VectorStat(true) { setInit(); }
2726 * Create a formula with the given root node, register it with the
2728 * @param r The root of the expression tree.
2730 Formula(Detail::Temp r) : VectorStat(true) {
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.
2740 const Formula &operator=(Detail::Temp r) {
2741 assert(!root && "Can't change formulas");
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.
2752 const Formula &operator+=(Detail::Temp r) {
2753 using namespace Detail;
2755 root = NodePtr(new BinaryNode<std::plus<result_t> >(root, r));
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.
2769 const rvec_t &val() const { return root->val(); }
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
2777 * @return The total of the result vector.
2779 result_t total() const { return root->total(); }
2782 * Return the number of elements in the tree.
2784 size_t size() const {
2788 return root->size();
2791 * Return true if Formula is binned. i.e. any of its children nodes are binned
2792 *@return True if Formula is binned.
2794 virtual bool binned() const { return root->binned(); }
2797 * Formulas don't need to be reset
2799 virtual void reset() {}
2807 void dump(std::ostream &stream);
2809 void RegResetCallback(Callback *cb);
2812 operator+(Detail::Temp l, Detail::Temp r)
2814 using namespace Detail;
2815 return NodePtr(new BinaryNode<std::plus<result_t> >(l, r));
2819 operator-(Detail::Temp l, Detail::Temp r)
2821 using namespace Detail;
2822 return NodePtr(new BinaryNode<std::minus<result_t> >(l, r));
2826 operator*(Detail::Temp l, Detail::Temp r)
2828 using namespace Detail;
2829 return NodePtr(new BinaryNode<std::multiplies<result_t> >(l, r));
2833 operator/(Detail::Temp l, Detail::Temp r)
2835 using namespace Detail;
2836 return NodePtr(new BinaryNode<std::divides<result_t> >(l, r));
2840 operator%(Detail::Temp l, Detail::Temp r)
2842 using namespace Detail;
2843 return NodePtr(new BinaryNode<std::modulus<result_t> >(l, r));
2847 operator-(Detail::Temp l)
2849 using namespace Detail;
2850 return NodePtr(new UnaryNode<std::negate<result_t> >(l));
2853 template <typename T>
2857 using namespace Detail;
2858 return NodePtr(new ConstNode<T>(val));
2861 template <typename T>
2865 using namespace Detail;
2866 return NodePtr(new FunctorNode<T>(val));
2869 template <typename T>
2873 using namespace Detail;
2874 return NodePtr(new ScalarNode<T>(val));
2878 sum(Detail::Temp val)
2880 using namespace Detail;
2881 return NodePtr(new SumNode<std::plus<result_t> >(val));
2884 extern bool PrintDescriptions;
2886 } // namespace statistics
2888 #endif // __STATISTICS_HH__