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