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