statistics.cc revision 12334:e0ab29a34764
112239Sandreas.sandberg@arm.com/*
214249Sgiacomo.travaglini@arm.com * Copyright (c) 2003-2005 The Regents of The University of Michigan
314249Sgiacomo.travaglini@arm.com * All rights reserved.
414249Sgiacomo.travaglini@arm.com *
514249Sgiacomo.travaglini@arm.com * Redistribution and use in source and binary forms, with or without
614249Sgiacomo.travaglini@arm.com * modification, are permitted provided that the following conditions are
714249Sgiacomo.travaglini@arm.com * met: redistributions of source code must retain the above copyright
814249Sgiacomo.travaglini@arm.com * notice, this list of conditions and the following disclaimer;
914249Sgiacomo.travaglini@arm.com * redistributions in binary form must reproduce the above copyright
1014249Sgiacomo.travaglini@arm.com * notice, this list of conditions and the following disclaimer in the
1114249Sgiacomo.travaglini@arm.com * documentation and/or other materials provided with the distribution;
1214249Sgiacomo.travaglini@arm.com * neither the name of the copyright holders nor the names of its
1314249Sgiacomo.travaglini@arm.com * contributors may be used to endorse or promote products derived from
1412239Sandreas.sandberg@arm.com * this software without specific prior written permission.
1512239Sandreas.sandberg@arm.com *
1612239Sandreas.sandberg@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1712239Sandreas.sandberg@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1812239Sandreas.sandberg@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1912239Sandreas.sandberg@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2012239Sandreas.sandberg@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2112239Sandreas.sandberg@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2212239Sandreas.sandberg@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2312239Sandreas.sandberg@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2412239Sandreas.sandberg@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2512239Sandreas.sandberg@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2612239Sandreas.sandberg@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2712239Sandreas.sandberg@arm.com *
2812239Sandreas.sandberg@arm.com * Authors: Nathan Binkert
2912239Sandreas.sandberg@arm.com */
3012239Sandreas.sandberg@arm.com
3112239Sandreas.sandberg@arm.com#include "base/statistics.hh"
3212239Sandreas.sandberg@arm.com
3312239Sandreas.sandberg@arm.com#include <fstream>
3412239Sandreas.sandberg@arm.com#include <iomanip>
3512239Sandreas.sandberg@arm.com#include <list>
3612239Sandreas.sandberg@arm.com#include <map>
3712239Sandreas.sandberg@arm.com#include <string>
3812239Sandreas.sandberg@arm.com
3912239Sandreas.sandberg@arm.com#include "base/callback.hh"
4012239Sandreas.sandberg@arm.com#include "base/cprintf.hh"
4112239Sandreas.sandberg@arm.com#include "base/debug.hh"
4212239Sandreas.sandberg@arm.com#include "base/hostinfo.hh"
4312239Sandreas.sandberg@arm.com#include "base/logging.hh"
4412239Sandreas.sandberg@arm.com#include "base/str.hh"
4512239Sandreas.sandberg@arm.com#include "base/time.hh"
4612239Sandreas.sandberg@arm.com#include "base/trace.hh"
4712239Sandreas.sandberg@arm.com
4812239Sandreas.sandberg@arm.comusing namespace std;
4912239Sandreas.sandberg@arm.com
5012239Sandreas.sandberg@arm.comnamespace Stats {
5112239Sandreas.sandberg@arm.com
5212239Sandreas.sandberg@arm.comstd::string Info::separatorString = "::";
5312239Sandreas.sandberg@arm.com
5412239Sandreas.sandberg@arm.com// We wrap these in a function to make sure they're built in time.
5512239Sandreas.sandberg@arm.comlist<Info *> &
5612239Sandreas.sandberg@arm.comstatsList()
5712239Sandreas.sandberg@arm.com{
5812239Sandreas.sandberg@arm.com    static list<Info *> the_list;
5912239Sandreas.sandberg@arm.com    return the_list;
6012239Sandreas.sandberg@arm.com}
6112239Sandreas.sandberg@arm.com
6212239Sandreas.sandberg@arm.comMapType &
6312239Sandreas.sandberg@arm.comstatsMap()
6412239Sandreas.sandberg@arm.com{
6512239Sandreas.sandberg@arm.com    static MapType the_map;
6612239Sandreas.sandberg@arm.com    return the_map;
6712239Sandreas.sandberg@arm.com}
6812239Sandreas.sandberg@arm.com
6912239Sandreas.sandberg@arm.comvoid
7012334Sgabeblack@google.comInfoAccess::setInfo(Info *info)
7112239Sandreas.sandberg@arm.com{
7212239Sandreas.sandberg@arm.com    if (statsMap().find(this) != statsMap().end())
7312239Sandreas.sandberg@arm.com        panic("shouldn't register stat twice!");
7412239Sandreas.sandberg@arm.com
7512239Sandreas.sandberg@arm.com    statsList().push_back(info);
7612239Sandreas.sandberg@arm.com
7712239Sandreas.sandberg@arm.com#ifndef NDEBUG
7812239Sandreas.sandberg@arm.com    pair<MapType::iterator, bool> result =
7912239Sandreas.sandberg@arm.com#endif
8012239Sandreas.sandberg@arm.com        statsMap().insert(make_pair(this, info));
8112239Sandreas.sandberg@arm.com    assert(result.second && "this should never fail");
8212239Sandreas.sandberg@arm.com    assert(statsMap().find(this) != statsMap().end());
8312239Sandreas.sandberg@arm.com}
8412239Sandreas.sandberg@arm.com
8512239Sandreas.sandberg@arm.comvoid
8612239Sandreas.sandberg@arm.comInfoAccess::setParams(const StorageParams *params)
8712239Sandreas.sandberg@arm.com{
8812239Sandreas.sandberg@arm.com    info()->storageParams = params;
8912239Sandreas.sandberg@arm.com}
9012239Sandreas.sandberg@arm.com
9112239Sandreas.sandberg@arm.comvoid
9212239Sandreas.sandberg@arm.comInfoAccess::setInit()
9312239Sandreas.sandberg@arm.com{
9412239Sandreas.sandberg@arm.com    info()->flags.set(init);
9512239Sandreas.sandberg@arm.com}
9612239Sandreas.sandberg@arm.com
9712239Sandreas.sandberg@arm.comInfo *
9812239Sandreas.sandberg@arm.comInfoAccess::info()
9912239Sandreas.sandberg@arm.com{
10012239Sandreas.sandberg@arm.com    MapType::const_iterator i = statsMap().find(this);
10112239Sandreas.sandberg@arm.com    assert(i != statsMap().end());
10212239Sandreas.sandberg@arm.com    return (*i).second;
10312239Sandreas.sandberg@arm.com}
10412239Sandreas.sandberg@arm.com
10512239Sandreas.sandberg@arm.comconst Info *
10612239Sandreas.sandberg@arm.comInfoAccess::info() const
10712239Sandreas.sandberg@arm.com{
10812239Sandreas.sandberg@arm.com    MapType::const_iterator i = statsMap().find(this);
10912239Sandreas.sandberg@arm.com    assert(i != statsMap().end());
11012239Sandreas.sandberg@arm.com    return (*i).second;
11112239Sandreas.sandberg@arm.com}
11212239Sandreas.sandberg@arm.com
11312239Sandreas.sandberg@arm.comStorageParams::~StorageParams()
11412239Sandreas.sandberg@arm.com{
11512239Sandreas.sandberg@arm.com}
11612239Sandreas.sandberg@arm.com
11712239Sandreas.sandberg@arm.comNameMapType &
11812239Sandreas.sandberg@arm.comnameMap()
11912239Sandreas.sandberg@arm.com{
12012239Sandreas.sandberg@arm.com    static NameMapType the_map;
12112239Sandreas.sandberg@arm.com    return the_map;
12212239Sandreas.sandberg@arm.com}
12312239Sandreas.sandberg@arm.com
12414249Sgiacomo.travaglini@arm.comint Info::id_count = 0;
12512239Sandreas.sandberg@arm.com
12612239Sandreas.sandberg@arm.comint debug_break_id = -1;
12712239Sandreas.sandberg@arm.com
12812239Sandreas.sandberg@arm.comInfo::Info()
12912239Sandreas.sandberg@arm.com    : flags(none), precision(-1), prereq(0), storageParams(NULL)
13012239Sandreas.sandberg@arm.com{
13112239Sandreas.sandberg@arm.com    id = id_count++;
13212239Sandreas.sandberg@arm.com    if (debug_break_id >= 0 and debug_break_id == id)
13312239Sandreas.sandberg@arm.com        Debug::breakpoint();
13412239Sandreas.sandberg@arm.com}
13512239Sandreas.sandberg@arm.com
13612239Sandreas.sandberg@arm.comInfo::~Info()
13712239Sandreas.sandberg@arm.com{
13812239Sandreas.sandberg@arm.com}
13912239Sandreas.sandberg@arm.com
14012239Sandreas.sandberg@arm.combool
14112239Sandreas.sandberg@arm.comvalidateStatName(const string &name)
14212239Sandreas.sandberg@arm.com{
14312239Sandreas.sandberg@arm.com    if (name.empty())
14412239Sandreas.sandberg@arm.com        return false;
14512239Sandreas.sandberg@arm.com
14612239Sandreas.sandberg@arm.com    vector<string> vec;
14712239Sandreas.sandberg@arm.com    tokenize(vec, name, '.');
14814249Sgiacomo.travaglini@arm.com    vector<string>::const_iterator item = vec.begin();
14914249Sgiacomo.travaglini@arm.com    while (item != vec.end()) {
15014249Sgiacomo.travaglini@arm.com        if (item->empty())
15114249Sgiacomo.travaglini@arm.com            return false;
15214249Sgiacomo.travaglini@arm.com
15314249Sgiacomo.travaglini@arm.com        string::const_iterator c = item->begin();
15414288SAndrea.Mondelli@ucf.edu
15514249Sgiacomo.travaglini@arm.com        // The first character is different
15614288SAndrea.Mondelli@ucf.edu        if (!isalpha(*c) && *c != '_')
15714249Sgiacomo.travaglini@arm.com            return false;
15814249Sgiacomo.travaglini@arm.com
15914249Sgiacomo.travaglini@arm.com        // The rest of the characters have different rules.
16014249Sgiacomo.travaglini@arm.com        while (++c != item->end()) {
16114249Sgiacomo.travaglini@arm.com            if (!isalnum(*c) && *c != '_')
16214249Sgiacomo.travaglini@arm.com                return false;
16314249Sgiacomo.travaglini@arm.com        }
16412239Sandreas.sandberg@arm.com
16512239Sandreas.sandberg@arm.com        ++item;
16612239Sandreas.sandberg@arm.com    }
16712239Sandreas.sandberg@arm.com
16812239Sandreas.sandberg@arm.com    return true;
16912239Sandreas.sandberg@arm.com}
17012239Sandreas.sandberg@arm.com
17112239Sandreas.sandberg@arm.comvoid
17212239Sandreas.sandberg@arm.comInfo::setName(const string &name)
17312239Sandreas.sandberg@arm.com{
17412239Sandreas.sandberg@arm.com    if (!validateStatName(name))
17512239Sandreas.sandberg@arm.com        panic("invalid stat name '%s'", name);
17612239Sandreas.sandberg@arm.com
17712239Sandreas.sandberg@arm.com    pair<NameMapType::iterator, bool> p =
17812239Sandreas.sandberg@arm.com        nameMap().insert(make_pair(name, this));
17912239Sandreas.sandberg@arm.com
18012239Sandreas.sandberg@arm.com    Info *other = p.first->second;
18112239Sandreas.sandberg@arm.com    bool result = p.second;
18212239Sandreas.sandberg@arm.com
18312239Sandreas.sandberg@arm.com    if (!result) {
18412693Sandreas.sandberg@arm.com      // using other->name instead of just name to avoid a compiler
18512693Sandreas.sandberg@arm.com      // warning.  They should be the same.
18612239Sandreas.sandberg@arm.com        panic("same statistic name used twice! name=%s\n", other->name);
18712239Sandreas.sandberg@arm.com    }
18812239Sandreas.sandberg@arm.com
18912239Sandreas.sandberg@arm.com    this->name = name;
19012239Sandreas.sandberg@arm.com}
19112239Sandreas.sandberg@arm.com
19212239Sandreas.sandberg@arm.combool
19312239Sandreas.sandberg@arm.comInfo::less(Info *stat1, Info *stat2)
19412239Sandreas.sandberg@arm.com{
19512239Sandreas.sandberg@arm.com    const string &name1 = stat1->name;
19612239Sandreas.sandberg@arm.com    const string &name2 = stat2->name;
19712239Sandreas.sandberg@arm.com
19812239Sandreas.sandberg@arm.com    vector<string> v1;
19912239Sandreas.sandberg@arm.com    vector<string> v2;
20012239Sandreas.sandberg@arm.com
20112239Sandreas.sandberg@arm.com    tokenize(v1, name1, '.');
20212239Sandreas.sandberg@arm.com    tokenize(v2, name2, '.');
20312239Sandreas.sandberg@arm.com
20412239Sandreas.sandberg@arm.com    size_type last = min(v1.size(), v2.size()) - 1;
20512239Sandreas.sandberg@arm.com    for (off_type i = 0; i < last; ++i)
20612239Sandreas.sandberg@arm.com        if (v1[i] != v2[i])
20712239Sandreas.sandberg@arm.com            return v1[i] < v2[i];
20812239Sandreas.sandberg@arm.com
20912239Sandreas.sandberg@arm.com    // Special compare for last element.
21012239Sandreas.sandberg@arm.com    if (v1[last] == v2[last])
21112239Sandreas.sandberg@arm.com        return v1.size() < v2.size();
21212239Sandreas.sandberg@arm.com    else
21312239Sandreas.sandberg@arm.com        return v1[last] < v2[last];
21412239Sandreas.sandberg@arm.com
21512239Sandreas.sandberg@arm.com    return false;
21612239Sandreas.sandberg@arm.com}
21712239Sandreas.sandberg@arm.com
21812239Sandreas.sandberg@arm.combool
21912239Sandreas.sandberg@arm.comInfo::baseCheck() const
22012239Sandreas.sandberg@arm.com{
22112239Sandreas.sandberg@arm.com    if (!(flags & Stats::init)) {
22212239Sandreas.sandberg@arm.com#ifdef DEBUG
22312239Sandreas.sandberg@arm.com        cprintf("this is stat number %d\n", id);
22412239Sandreas.sandberg@arm.com#endif
22512239Sandreas.sandberg@arm.com        panic("Not all stats have been initialized.\n"
22612239Sandreas.sandberg@arm.com              "You may need to add <ParentClass>::regStats() to a"
22712239Sandreas.sandberg@arm.com              " new SimObject's regStats() function.");
22812239Sandreas.sandberg@arm.com        return false;
22912239Sandreas.sandberg@arm.com    }
23012239Sandreas.sandberg@arm.com
23112239Sandreas.sandberg@arm.com    if ((flags & display) && name.empty()) {
23212239Sandreas.sandberg@arm.com        panic("all printable stats must be named");
23312239Sandreas.sandberg@arm.com        return false;
23412239Sandreas.sandberg@arm.com    }
23512239Sandreas.sandberg@arm.com
23612239Sandreas.sandberg@arm.com    return true;
23712239Sandreas.sandberg@arm.com}
23812239Sandreas.sandberg@arm.com
23912239Sandreas.sandberg@arm.comvoid
24012239Sandreas.sandberg@arm.comInfo::enable()
24112239Sandreas.sandberg@arm.com{
24212239Sandreas.sandberg@arm.com}
24312239Sandreas.sandberg@arm.com
24412239Sandreas.sandberg@arm.comvoid
24512239Sandreas.sandberg@arm.comVectorInfo::enable()
24612239Sandreas.sandberg@arm.com{
24712239Sandreas.sandberg@arm.com    size_type s = size();
24812239Sandreas.sandberg@arm.com    if (subnames.size() < s)
24912239Sandreas.sandberg@arm.com        subnames.resize(s);
25012239Sandreas.sandberg@arm.com    if (subdescs.size() < s)
25112239Sandreas.sandberg@arm.com        subdescs.resize(s);
25212239Sandreas.sandberg@arm.com}
25312239Sandreas.sandberg@arm.com
25412239Sandreas.sandberg@arm.comvoid
25512239Sandreas.sandberg@arm.comVectorDistInfo::enable()
25612239Sandreas.sandberg@arm.com{
25712239Sandreas.sandberg@arm.com    size_type s = size();
25812239Sandreas.sandberg@arm.com    if (subnames.size() < s)
25912239Sandreas.sandberg@arm.com        subnames.resize(s);
26012239Sandreas.sandberg@arm.com    if (subdescs.size() < s)
26112239Sandreas.sandberg@arm.com        subdescs.resize(s);
26212239Sandreas.sandberg@arm.com}
26312239Sandreas.sandberg@arm.com
26412239Sandreas.sandberg@arm.comvoid
26512239Sandreas.sandberg@arm.comVector2dInfo::enable()
26612239Sandreas.sandberg@arm.com{
26712239Sandreas.sandberg@arm.com    if (subnames.size() < x)
26812239Sandreas.sandberg@arm.com        subnames.resize(x);
26912239Sandreas.sandberg@arm.com    if (subdescs.size() < x)
27012239Sandreas.sandberg@arm.com        subdescs.resize(x);
27112239Sandreas.sandberg@arm.com    if (y_subnames.size() < y)
27212239Sandreas.sandberg@arm.com        y_subnames.resize(y);
27312239Sandreas.sandberg@arm.com}
27412239Sandreas.sandberg@arm.com
27512239Sandreas.sandberg@arm.comvoid
27612239Sandreas.sandberg@arm.comHistStor::grow_out()
27712239Sandreas.sandberg@arm.com{
27812239Sandreas.sandberg@arm.com    int size = cvec.size();
27912239Sandreas.sandberg@arm.com    int zero = size / 2; // round down!
28012239Sandreas.sandberg@arm.com    int top_half = zero + (size - zero + 1) / 2; // round up!
28112239Sandreas.sandberg@arm.com    int bottom_half = (size - zero) / 2; // round down!
28212239Sandreas.sandberg@arm.com
28312239Sandreas.sandberg@arm.com    // grow down
28412239Sandreas.sandberg@arm.com    int low_pair = zero - 1;
28512239Sandreas.sandberg@arm.com    for (int i = zero - 1; i >= bottom_half; i--) {
28612239Sandreas.sandberg@arm.com        cvec[i] = cvec[low_pair];
28712239Sandreas.sandberg@arm.com        if (low_pair - 1 >= 0)
28812239Sandreas.sandberg@arm.com            cvec[i] += cvec[low_pair - 1];
28912239Sandreas.sandberg@arm.com        low_pair -= 2;
29012239Sandreas.sandberg@arm.com    }
29112239Sandreas.sandberg@arm.com    assert(low_pair == 0 || low_pair == -1 || low_pair == -2);
29212239Sandreas.sandberg@arm.com
29312239Sandreas.sandberg@arm.com    for (int i = bottom_half - 1; i >= 0; i--)
29412239Sandreas.sandberg@arm.com        cvec[i] = Counter();
29512239Sandreas.sandberg@arm.com
29612239Sandreas.sandberg@arm.com    // grow up
29712239Sandreas.sandberg@arm.com    int high_pair = zero;
29812239Sandreas.sandberg@arm.com    for (int i = zero; i < top_half; i++) {
29912239Sandreas.sandberg@arm.com        cvec[i] = cvec[high_pair];
30012239Sandreas.sandberg@arm.com        if (high_pair + 1 < size)
30112239Sandreas.sandberg@arm.com            cvec[i] += cvec[high_pair + 1];
30212239Sandreas.sandberg@arm.com        high_pair += 2;
30312239Sandreas.sandberg@arm.com    }
30412239Sandreas.sandberg@arm.com    assert(high_pair == size || high_pair == size + 1);
30512239Sandreas.sandberg@arm.com
30612239Sandreas.sandberg@arm.com    for (int i = top_half; i < size; i++)
30712239Sandreas.sandberg@arm.com        cvec[i] = Counter();
30812239Sandreas.sandberg@arm.com
30912239Sandreas.sandberg@arm.com    max_bucket *= 2;
31012239Sandreas.sandberg@arm.com    min_bucket *= 2;
31112239Sandreas.sandberg@arm.com    bucket_size *= 2;
31212239Sandreas.sandberg@arm.com}
31312239Sandreas.sandberg@arm.com
31412239Sandreas.sandberg@arm.comvoid
31512239Sandreas.sandberg@arm.comHistStor::grow_convert()
31612239Sandreas.sandberg@arm.com{
31712239Sandreas.sandberg@arm.com    int size = cvec.size();
31812239Sandreas.sandberg@arm.com    int half = (size + 1) / 2; // round up!
31912239Sandreas.sandberg@arm.com    //bool even = (size & 1) == 0;
32012239Sandreas.sandberg@arm.com
32112239Sandreas.sandberg@arm.com    int pair = size - 1;
32212239Sandreas.sandberg@arm.com    for (int i = size - 1; i >= half; --i) {
32312239Sandreas.sandberg@arm.com        cvec[i] = cvec[pair];
32412239Sandreas.sandberg@arm.com        if (pair - 1 >= 0)
32512239Sandreas.sandberg@arm.com            cvec[i] += cvec[pair - 1];
32612239Sandreas.sandberg@arm.com        pair -= 2;
32712239Sandreas.sandberg@arm.com    }
32812239Sandreas.sandberg@arm.com
32912239Sandreas.sandberg@arm.com    for (int i = half - 1; i >= 0; i--)
33012239Sandreas.sandberg@arm.com        cvec[i] = Counter();
33112239Sandreas.sandberg@arm.com
33212239Sandreas.sandberg@arm.com    min_bucket = -max_bucket;// - (even ? bucket_size : 0);
33312239Sandreas.sandberg@arm.com    bucket_size *= 2;
33412239Sandreas.sandberg@arm.com}
33512239Sandreas.sandberg@arm.com
33612239Sandreas.sandberg@arm.comvoid
33712239Sandreas.sandberg@arm.comHistStor::grow_up()
33812239Sandreas.sandberg@arm.com{
33912239Sandreas.sandberg@arm.com    int size = cvec.size();
34012239Sandreas.sandberg@arm.com    int half = (size + 1) / 2; // round up!
34112239Sandreas.sandberg@arm.com
34212239Sandreas.sandberg@arm.com    int pair = 0;
34312239Sandreas.sandberg@arm.com    for (int i = 0; i < half; i++) {
34412239Sandreas.sandberg@arm.com        cvec[i] = cvec[pair];
34512239Sandreas.sandberg@arm.com        if (pair + 1 < size)
34612239Sandreas.sandberg@arm.com            cvec[i] += cvec[pair + 1];
34712239Sandreas.sandberg@arm.com        pair += 2;
34812239Sandreas.sandberg@arm.com    }
34912239Sandreas.sandberg@arm.com    assert(pair == size || pair == size + 1);
35012239Sandreas.sandberg@arm.com
35112239Sandreas.sandberg@arm.com    for (int i = half; i < size; i++)
35212239Sandreas.sandberg@arm.com        cvec[i] = Counter();
35312239Sandreas.sandberg@arm.com
35412239Sandreas.sandberg@arm.com    max_bucket *= 2;
35512239Sandreas.sandberg@arm.com    bucket_size *= 2;
35612239Sandreas.sandberg@arm.com}
35712239Sandreas.sandberg@arm.com
35812239Sandreas.sandberg@arm.comvoid
35912239Sandreas.sandberg@arm.comHistStor::add(HistStor *hs)
36012239Sandreas.sandberg@arm.com{
36112239Sandreas.sandberg@arm.com    int b_size = hs->size();
36212239Sandreas.sandberg@arm.com    assert(size() == b_size);
36312239Sandreas.sandberg@arm.com    assert(min_bucket == hs->min_bucket);
36412239Sandreas.sandberg@arm.com
36512239Sandreas.sandberg@arm.com    sum += hs->sum;
36612239Sandreas.sandberg@arm.com    logs += hs->logs;
36712239Sandreas.sandberg@arm.com    squares += hs->squares;
36812239Sandreas.sandberg@arm.com    samples += hs->samples;
36912239Sandreas.sandberg@arm.com
37012239Sandreas.sandberg@arm.com    while (bucket_size > hs->bucket_size)
371        hs->grow_up();
372    while (bucket_size < hs->bucket_size)
373        grow_up();
374
375    for (uint32_t i = 0; i < b_size; i++)
376        cvec[i] += hs->cvec[i];
377}
378
379Formula::Formula()
380{
381}
382
383Formula::Formula(Temp r)
384{
385    root = r.getNodePtr();
386    setInit();
387    assert(size());
388}
389
390const Formula &
391Formula::operator=(Temp r)
392{
393    assert(!root && "Can't change formulas");
394    root = r.getNodePtr();
395    setInit();
396    assert(size());
397    return *this;
398}
399
400const Formula &
401Formula::operator+=(Temp r)
402{
403    if (root)
404        root = NodePtr(new BinaryNode<std::plus<Result> >(root, r));
405    else {
406        root = r.getNodePtr();
407        setInit();
408    }
409
410    assert(size());
411    return *this;
412}
413
414const Formula &
415Formula::operator/=(Temp r)
416{
417    assert (root);
418    root = NodePtr(new BinaryNode<std::divides<Result> >(root, r));
419
420    assert(size());
421    return *this;
422}
423
424void
425Formula::result(VResult &vec) const
426{
427    if (root)
428        vec = root->result();
429}
430
431Result
432Formula::total() const
433{
434    return root ? root->total() : 0.0;
435}
436
437size_type
438Formula::size() const
439{
440    if (!root)
441        return 0;
442    else
443        return root->size();
444}
445
446void
447Formula::reset()
448{
449}
450
451bool
452Formula::zero() const
453{
454    VResult vec;
455    result(vec);
456    for (VResult::size_type i = 0; i < vec.size(); ++i)
457        if (vec[i] != 0.0)
458            return false;
459    return true;
460}
461
462string
463Formula::str() const
464{
465    return root ? root->str() : "";
466}
467
468Handler resetHandler = NULL;
469Handler dumpHandler = NULL;
470
471void
472registerHandlers(Handler reset_handler, Handler dump_handler)
473{
474    resetHandler = reset_handler;
475    dumpHandler = dump_handler;
476}
477
478CallbackQueue dumpQueue;
479CallbackQueue resetQueue;
480
481void
482processResetQueue()
483{
484    resetQueue.process();
485}
486
487void
488processDumpQueue()
489{
490    dumpQueue.process();
491}
492
493void
494registerResetCallback(Callback *cb)
495{
496    resetQueue.add(cb);
497}
498
499bool _enabled = false;
500
501bool
502enabled()
503{
504    return _enabled;
505}
506
507void
508enable()
509{
510    if (_enabled)
511        fatal("Stats are already enabled");
512
513    _enabled = true;
514}
515
516void
517dump()
518{
519    if (dumpHandler)
520        dumpHandler();
521    else
522        fatal("No registered Stats::dump handler");
523}
524
525void
526reset()
527{
528    if (resetHandler)
529        resetHandler();
530    else
531        fatal("No registered Stats::reset handler");
532}
533
534void
535registerDumpCallback(Callback *cb)
536{
537    dumpQueue.add(cb);
538}
539
540} // namespace Stats
541
542void
543debugDumpStats()
544{
545    Stats::dump();
546}
547