statistics.cc revision 388
110391SAndreas.Sandberg@ARM.com/*
212187Sanouk.vanlaer@arm.com * Copyright (c) 2003 The Regents of The University of Michigan
310391SAndreas.Sandberg@ARM.com * All rights reserved.
410391SAndreas.Sandberg@ARM.com *
510391SAndreas.Sandberg@ARM.com * Redistribution and use in source and binary forms, with or without
610391SAndreas.Sandberg@ARM.com * modification, are permitted provided that the following conditions are
710391SAndreas.Sandberg@ARM.com * met: redistributions of source code must retain the above copyright
810391SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer;
910391SAndreas.Sandberg@ARM.com * redistributions in binary form must reproduce the above copyright
1010391SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer in the
1110391SAndreas.Sandberg@ARM.com * documentation and/or other materials provided with the distribution;
1210391SAndreas.Sandberg@ARM.com * neither the name of the copyright holders nor the names of its
1310391SAndreas.Sandberg@ARM.com * contributors may be used to endorse or promote products derived from
1410391SAndreas.Sandberg@ARM.com * this software without specific prior written permission.
1510391SAndreas.Sandberg@ARM.com *
1610391SAndreas.Sandberg@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1710391SAndreas.Sandberg@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1810391SAndreas.Sandberg@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1910391SAndreas.Sandberg@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2010391SAndreas.Sandberg@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2110391SAndreas.Sandberg@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2210391SAndreas.Sandberg@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2310391SAndreas.Sandberg@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2410391SAndreas.Sandberg@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2510391SAndreas.Sandberg@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2610391SAndreas.Sandberg@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2710391SAndreas.Sandberg@ARM.com */
2810391SAndreas.Sandberg@ARM.com
2910391SAndreas.Sandberg@ARM.com#include <iomanip>
3010391SAndreas.Sandberg@ARM.com#include <iostream>
3110391SAndreas.Sandberg@ARM.com#include <list>
3210391SAndreas.Sandberg@ARM.com#include <map>
3310391SAndreas.Sandberg@ARM.com#include <string>
3410391SAndreas.Sandberg@ARM.com#include <sstream>
3510391SAndreas.Sandberg@ARM.com
3610391SAndreas.Sandberg@ARM.com#include "base/callback.hh"
3710391SAndreas.Sandberg@ARM.com#include "base/cprintf.hh"
3810391SAndreas.Sandberg@ARM.com#include "base/misc.hh"
3910391SAndreas.Sandberg@ARM.com#include "base/statistics.hh"
4010391SAndreas.Sandberg@ARM.com#include "base/str.hh"
4110391SAndreas.Sandberg@ARM.com#include "sim/universe.hh"
4210391SAndreas.Sandberg@ARM.com
4310391SAndreas.Sandberg@ARM.com#ifdef __M5_NAN
4410391SAndreas.Sandberg@ARM.comfloat
4510391SAndreas.Sandberg@ARM.com__nan()
4610391SAndreas.Sandberg@ARM.com{
4710391SAndreas.Sandberg@ARM.com    union {
4810391SAndreas.Sandberg@ARM.com        uint32_t ui;
4910391SAndreas.Sandberg@ARM.com        float f;
5010391SAndreas.Sandberg@ARM.com    } nan;
5110391SAndreas.Sandberg@ARM.com
5210391SAndreas.Sandberg@ARM.com    nan.ui = 0x7fc00000;
5310391SAndreas.Sandberg@ARM.com    return nan.f;
5410391SAndreas.Sandberg@ARM.com}
5510391SAndreas.Sandberg@ARM.com#endif
5610391SAndreas.Sandberg@ARM.com
5710391SAndreas.Sandberg@ARM.com#ifdef STAT_DEBUG
5810391SAndreas.Sandberg@ARM.comstatic int total_stats = 0;
5910391SAndreas.Sandberg@ARM.com#endif
6010391SAndreas.Sandberg@ARM.com
6110391SAndreas.Sandberg@ARM.comusing namespace std;
6210391SAndreas.Sandberg@ARM.com
6310391SAndreas.Sandberg@ARM.com// This is a hack to get this parameter from the old stats package.
6410391SAndreas.Sandberg@ARM.comnamespace Statistics {
6510391SAndreas.Sandberg@ARM.combool PrintDescriptions = true;
6610391SAndreas.Sandberg@ARM.comDisplayMode default_mode = mode_simplescalar;
6710391SAndreas.Sandberg@ARM.com
6810391SAndreas.Sandberg@ARM.comnamespace Database
6910391SAndreas.Sandberg@ARM.com{
7010391SAndreas.Sandberg@ARM.com    class Data
7110391SAndreas.Sandberg@ARM.com    {
7210391SAndreas.Sandberg@ARM.com      private:
7310391SAndreas.Sandberg@ARM.com        typedef list<StatData *> list_t;
7410391SAndreas.Sandberg@ARM.com        typedef map<void *, StatData *> map_t;
7510391SAndreas.Sandberg@ARM.com
7610391SAndreas.Sandberg@ARM.com        list<MainBin *> bins;
7710391SAndreas.Sandberg@ARM.com        map<const MainBin *, string > bin_names;
7810391SAndreas.Sandberg@ARM.com        list_t binnedStats;
7910391SAndreas.Sandberg@ARM.com
8010391SAndreas.Sandberg@ARM.com        list_t allStats;
8110391SAndreas.Sandberg@ARM.com        list_t printStats;
8210391SAndreas.Sandberg@ARM.com        map_t statMap;
8310391SAndreas.Sandberg@ARM.com
8410391SAndreas.Sandberg@ARM.com      public:
8510391SAndreas.Sandberg@ARM.com        void dump(ostream &stream);
8610391SAndreas.Sandberg@ARM.com
8710391SAndreas.Sandberg@ARM.com        StatData *find(void *stat);
8810391SAndreas.Sandberg@ARM.com        void mapStat(void *stat, StatData *data);
8910391SAndreas.Sandberg@ARM.com
9010391SAndreas.Sandberg@ARM.com        void check();
9110391SAndreas.Sandberg@ARM.com        void reset();
9210391SAndreas.Sandberg@ARM.com        void regBin(MainBin *bin, string name);
9310391SAndreas.Sandberg@ARM.com        void regPrint(void *stat);
9410391SAndreas.Sandberg@ARM.com    };
9510391SAndreas.Sandberg@ARM.com
9610391SAndreas.Sandberg@ARM.com
9710391SAndreas.Sandberg@ARM.comvoid
9810391SAndreas.Sandberg@ARM.comData::dump(ostream &stream)
9910391SAndreas.Sandberg@ARM.com{
10010391SAndreas.Sandberg@ARM.com#ifndef FS_MEASURE
10110391SAndreas.Sandberg@ARM.com    list_t::iterator i = printStats.begin();
10210391SAndreas.Sandberg@ARM.com    list_t::iterator end = printStats.end();
10310391SAndreas.Sandberg@ARM.com    while (i != end) {
10410391SAndreas.Sandberg@ARM.com        StatData *stat = *i;
10510391SAndreas.Sandberg@ARM.com        if (stat->binned())
10610391SAndreas.Sandberg@ARM.com            binnedStats.push_back(stat);
10710391SAndreas.Sandberg@ARM.com        ++i;
10810391SAndreas.Sandberg@ARM.com    }
10910391SAndreas.Sandberg@ARM.com#endif //FS_MEASURE
11010391SAndreas.Sandberg@ARM.com
11110391SAndreas.Sandberg@ARM.com    list<MainBin *>::iterator j = bins.begin();
11210391SAndreas.Sandberg@ARM.com    list<MainBin *>::iterator bins_end=bins.end();
11310391SAndreas.Sandberg@ARM.com
11410391SAndreas.Sandberg@ARM.com    if (!bins.empty()) {
11510391SAndreas.Sandberg@ARM.com        ccprintf(stream, "PRINTING BINNED STATS\n");
11610391SAndreas.Sandberg@ARM.com        while (j != bins_end) {
11710391SAndreas.Sandberg@ARM.com            (*j)->activate();
11810391SAndreas.Sandberg@ARM.com            map<const MainBin  *, string>::const_iterator iter;
11910391SAndreas.Sandberg@ARM.com            iter = bin_names.find(*j);
12010391SAndreas.Sandberg@ARM.com            if (iter == bin_names.end())
12110391SAndreas.Sandberg@ARM.com                panic("a binned stat not found in names map!");
12210391SAndreas.Sandberg@ARM.com            ccprintf(stream,"---%s Bin------------\n", (*iter).second);
12310391SAndreas.Sandberg@ARM.com
12410391SAndreas.Sandberg@ARM.com#ifdef FS_MEASURE
12510391SAndreas.Sandberg@ARM.com            list_t::iterator i = printStats.begin();
12610391SAndreas.Sandberg@ARM.com            list_t::iterator end = printStats.end();
12710391SAndreas.Sandberg@ARM.com#else
12810391SAndreas.Sandberg@ARM.com            list_t::iterator i = binnedStats.begin();
12910391SAndreas.Sandberg@ARM.com            list_t::iterator end = binnedStats.end();
13010391SAndreas.Sandberg@ARM.com#endif
13110391SAndreas.Sandberg@ARM.com            while (i != end) {
13210391SAndreas.Sandberg@ARM.com                StatData *stat = *i;
13310391SAndreas.Sandberg@ARM.com                if (stat->dodisplay())
13410391SAndreas.Sandberg@ARM.com                    stat->display(stream);
13510391SAndreas.Sandberg@ARM.com                ++i;
13610391SAndreas.Sandberg@ARM.com            }
13710391SAndreas.Sandberg@ARM.com            ++j;
13810391SAndreas.Sandberg@ARM.com            ccprintf(stream, "---------------------------------\n");
13910391SAndreas.Sandberg@ARM.com        }
14010391SAndreas.Sandberg@ARM.com#ifndef FS_MEASURE
14110391SAndreas.Sandberg@ARM.com        ccprintf(stream, "**************ALL STATS************\n");
14210391SAndreas.Sandberg@ARM.com#endif
14310391SAndreas.Sandberg@ARM.com    }
14410391SAndreas.Sandberg@ARM.com
14510391SAndreas.Sandberg@ARM.com/**
14610391SAndreas.Sandberg@ARM.com * get bin totals working, then print the stat here (as total), even if
14710391SAndreas.Sandberg@ARM.com * its' binned.  (this is only for the case you selectively bin a few stats
14810391SAndreas.Sandberg@ARM.com */
14910391SAndreas.Sandberg@ARM.com#ifndef FS_MEASURE
15010391SAndreas.Sandberg@ARM.com    list_t::iterator k = printStats.begin();
15110391SAndreas.Sandberg@ARM.com    list_t::iterator endprint = printStats.end();
15210391SAndreas.Sandberg@ARM.com    while (k != endprint) {
15310391SAndreas.Sandberg@ARM.com        StatData *stat = *k;
15410391SAndreas.Sandberg@ARM.com        if (stat->dodisplay() /*&& !stat->binned()*/)
15510391SAndreas.Sandberg@ARM.com            stat->display(stream);
15610391SAndreas.Sandberg@ARM.com        ++k;
15710391SAndreas.Sandberg@ARM.com    }
15810391SAndreas.Sandberg@ARM.com#endif
15910391SAndreas.Sandberg@ARM.com}
16010391SAndreas.Sandberg@ARM.com
16110391SAndreas.Sandberg@ARM.comStatData *
16210391SAndreas.Sandberg@ARM.comData::find(void *stat)
16310391SAndreas.Sandberg@ARM.com{
16410391SAndreas.Sandberg@ARM.com    map_t::const_iterator i = statMap.find(stat);
16510391SAndreas.Sandberg@ARM.com
16610391SAndreas.Sandberg@ARM.com    if (i == statMap.end())
16710391SAndreas.Sandberg@ARM.com        return NULL;
16810391SAndreas.Sandberg@ARM.com
16910391SAndreas.Sandberg@ARM.com    return (*i).second;
17010391SAndreas.Sandberg@ARM.com}
17110391SAndreas.Sandberg@ARM.com
17210391SAndreas.Sandberg@ARM.comvoid
17310391SAndreas.Sandberg@ARM.comData::check()
17410391SAndreas.Sandberg@ARM.com{
17510391SAndreas.Sandberg@ARM.com    list_t::iterator i = allStats.begin();
17610391SAndreas.Sandberg@ARM.com    list_t::iterator end = allStats.end();
17710391SAndreas.Sandberg@ARM.com
17810391SAndreas.Sandberg@ARM.com    while (i != end) {
17910391SAndreas.Sandberg@ARM.com        StatData *stat = *i;
18010391SAndreas.Sandberg@ARM.com        assert(stat);
18110391SAndreas.Sandberg@ARM.com        stat->check();
18210391SAndreas.Sandberg@ARM.com        ++i;
18310391SAndreas.Sandberg@ARM.com    }
18410391SAndreas.Sandberg@ARM.com}
18510391SAndreas.Sandberg@ARM.com
18610391SAndreas.Sandberg@ARM.comvoid
18710391SAndreas.Sandberg@ARM.comData::reset()
18810391SAndreas.Sandberg@ARM.com{
18910391SAndreas.Sandberg@ARM.com    list_t::iterator i = allStats.begin();
19010391SAndreas.Sandberg@ARM.com    list_t::iterator end = allStats.end();
19110391SAndreas.Sandberg@ARM.com    while (i != end) {
19210391SAndreas.Sandberg@ARM.com        StatData *stat = *i;
19310391SAndreas.Sandberg@ARM.com        stat->reset();
19410391SAndreas.Sandberg@ARM.com        ++i;
19510391SAndreas.Sandberg@ARM.com    }
19610391SAndreas.Sandberg@ARM.com
19710391SAndreas.Sandberg@ARM.com    MainBin *orig = MainBin::curBin();
19810391SAndreas.Sandberg@ARM.com
19910391SAndreas.Sandberg@ARM.com    list<MainBin *>::iterator bi = bins.begin();
20010391SAndreas.Sandberg@ARM.com    list<MainBin *>::iterator be = bins.end();
20110391SAndreas.Sandberg@ARM.com    while (bi != be) {
20210391SAndreas.Sandberg@ARM.com        MainBin *bin = *bi;
20310391SAndreas.Sandberg@ARM.com        bin->activate();
20410391SAndreas.Sandberg@ARM.com
20510391SAndreas.Sandberg@ARM.com        i = allStats.begin();
20610391SAndreas.Sandberg@ARM.com        while (i != end) {
20710391SAndreas.Sandberg@ARM.com            StatData *stat = *i;
20810391SAndreas.Sandberg@ARM.com            stat->reset();
20910391SAndreas.Sandberg@ARM.com            ++i;
21010391SAndreas.Sandberg@ARM.com        }
21110391SAndreas.Sandberg@ARM.com        ++bi;
21210391SAndreas.Sandberg@ARM.com    }
21310391SAndreas.Sandberg@ARM.com
21410391SAndreas.Sandberg@ARM.com    if (orig)
21510391SAndreas.Sandberg@ARM.com        orig->activate();
21610391SAndreas.Sandberg@ARM.com}
21710391SAndreas.Sandberg@ARM.com
21810391SAndreas.Sandberg@ARM.comvoid
21911168Sandreas.hansson@arm.comData::mapStat(void *stat, StatData *data)
22011168Sandreas.hansson@arm.com{
22110391SAndreas.Sandberg@ARM.com    if (statMap.find(stat) != statMap.end())
22210391SAndreas.Sandberg@ARM.com        panic("shouldn't register stat twice!");
22311169Sandreas.hansson@arm.com
22411169Sandreas.hansson@arm.com    allStats.push_back(data);
22510391SAndreas.Sandberg@ARM.com
22610391SAndreas.Sandberg@ARM.com    bool success = (statMap.insert(make_pair(stat, data))).second;
22710391SAndreas.Sandberg@ARM.com    assert(statMap.find(stat) != statMap.end());
22810391SAndreas.Sandberg@ARM.com    assert(success && "this should never fail");
22910391SAndreas.Sandberg@ARM.com}
23010391SAndreas.Sandberg@ARM.com
23110391SAndreas.Sandberg@ARM.comvoid
23210391SAndreas.Sandberg@ARM.comData::regBin(MainBin *bin, string name)
23310391SAndreas.Sandberg@ARM.com{
23410391SAndreas.Sandberg@ARM.com    if (bin_names.find(bin) != bin_names.end())
23510391SAndreas.Sandberg@ARM.com        panic("shouldn't register bin twice");
23610391SAndreas.Sandberg@ARM.com
23710391SAndreas.Sandberg@ARM.com    bins.push_back(bin);
23810391SAndreas.Sandberg@ARM.com
23910391SAndreas.Sandberg@ARM.com    bool success = (bin_names.insert(make_pair(bin,name))).second;
24010391SAndreas.Sandberg@ARM.com    assert(bin_names.find(bin) != bin_names.end());
24110391SAndreas.Sandberg@ARM.com    assert(success && "this should not fail");
24210391SAndreas.Sandberg@ARM.com
24310391SAndreas.Sandberg@ARM.com    cprintf("registering %s\n", name);
24410391SAndreas.Sandberg@ARM.com}
24510391SAndreas.Sandberg@ARM.com
24610391SAndreas.Sandberg@ARM.comvoid
24710391SAndreas.Sandberg@ARM.comData::regPrint(void *stat)
24810391SAndreas.Sandberg@ARM.com{
24910391SAndreas.Sandberg@ARM.com    StatData *data = find(stat);
25010391SAndreas.Sandberg@ARM.com
25110391SAndreas.Sandberg@ARM.com    if (!data->print) {
25210391SAndreas.Sandberg@ARM.com        data->print = true;
25310391SAndreas.Sandberg@ARM.com
25410391SAndreas.Sandberg@ARM.com        list_t::iterator j = printStats.insert(printStats.end(), data);
25510391SAndreas.Sandberg@ARM.com        inplace_merge(printStats.begin(), j,
25610391SAndreas.Sandberg@ARM.com                      printStats.end(), StatData::less);
25710391SAndreas.Sandberg@ARM.com    }
25810391SAndreas.Sandberg@ARM.com
25910391SAndreas.Sandberg@ARM.com}
26010391SAndreas.Sandberg@ARM.com
26110391SAndreas.Sandberg@ARM.comData &
26210391SAndreas.Sandberg@ARM.comStatDB()
26310391SAndreas.Sandberg@ARM.com{
26410391SAndreas.Sandberg@ARM.com    static Data db;
26510391SAndreas.Sandberg@ARM.com    return db;
26610391SAndreas.Sandberg@ARM.com}
26710391SAndreas.Sandberg@ARM.com
26810391SAndreas.Sandberg@ARM.com}
26910391SAndreas.Sandberg@ARM.com
27010391SAndreas.Sandberg@ARM.comStatData *
27110391SAndreas.Sandberg@ARM.comDataAccess::find() const
27211204Ssascha.bischoff@ARM.com{
27311204Ssascha.bischoff@ARM.com    return Database::StatDB().find(const_cast<void *>((const void *)this));
27411204Ssascha.bischoff@ARM.com}
27511204Ssascha.bischoff@ARM.com
27611204Ssascha.bischoff@ARM.comvoid
27711204Ssascha.bischoff@ARM.comDataAccess::map(StatData *data)
27811204Ssascha.bischoff@ARM.com{
27911204Ssascha.bischoff@ARM.com    Database::StatDB().mapStat(this, data);
28011204Ssascha.bischoff@ARM.com}
28111204Ssascha.bischoff@ARM.com
28211204Ssascha.bischoff@ARM.comStatData *
28310391SAndreas.Sandberg@ARM.comDataAccess::statData()
28410391SAndreas.Sandberg@ARM.com{
28510391SAndreas.Sandberg@ARM.com    StatData *ptr = find();
28610391SAndreas.Sandberg@ARM.com    assert(ptr);
28710391SAndreas.Sandberg@ARM.com    return ptr;
28810391SAndreas.Sandberg@ARM.com}
28910391SAndreas.Sandberg@ARM.com
29010391SAndreas.Sandberg@ARM.comconst StatData *
29110391SAndreas.Sandberg@ARM.comDataAccess::statData() const
29210391SAndreas.Sandberg@ARM.com{
29310391SAndreas.Sandberg@ARM.com    const StatData *ptr = find();
29410391SAndreas.Sandberg@ARM.com    assert(ptr);
29510391SAndreas.Sandberg@ARM.com    return ptr;
29610391SAndreas.Sandberg@ARM.com}
29710391SAndreas.Sandberg@ARM.com
29810391SAndreas.Sandberg@ARM.comvoid
29910391SAndreas.Sandberg@ARM.comDataAccess::setInit()
30010391SAndreas.Sandberg@ARM.com{
30110391SAndreas.Sandberg@ARM.com    statData()->init = true;
30210391SAndreas.Sandberg@ARM.com}
30310391SAndreas.Sandberg@ARM.com
30410391SAndreas.Sandberg@ARM.comvoid
30510391SAndreas.Sandberg@ARM.comDataAccess::setPrint()
30610391SAndreas.Sandberg@ARM.com{
30710391SAndreas.Sandberg@ARM.com    Database::StatDB().regPrint(this);
30812187Sanouk.vanlaer@arm.com}
30912187Sanouk.vanlaer@arm.com
31010391SAndreas.Sandberg@ARM.comStatData::~StatData()
31110391SAndreas.Sandberg@ARM.com{
31210391SAndreas.Sandberg@ARM.com}
31310391SAndreas.Sandberg@ARM.com
31410391SAndreas.Sandberg@ARM.combool
31510391SAndreas.Sandberg@ARM.comStatData::less(StatData *stat1, StatData *stat2)
31610391SAndreas.Sandberg@ARM.com{
31710391SAndreas.Sandberg@ARM.com    const string &name1 = stat1->name;
31810391SAndreas.Sandberg@ARM.com    const string &name2 = stat2->name;
31910391SAndreas.Sandberg@ARM.com
32010391SAndreas.Sandberg@ARM.com    vector<string> v1;
32110391SAndreas.Sandberg@ARM.com    vector<string> v2;
32210391SAndreas.Sandberg@ARM.com
32310391SAndreas.Sandberg@ARM.com    tokenize(v1, name1, '.');
32410391SAndreas.Sandberg@ARM.com    tokenize(v2, name2, '.');
32510391SAndreas.Sandberg@ARM.com
32610391SAndreas.Sandberg@ARM.com    int last = min(v1.size(), v2.size()) - 1;
32710391SAndreas.Sandberg@ARM.com    for (int i = 0; i < last; ++i)
32810391SAndreas.Sandberg@ARM.com        if (v1[i] != v2[i])
32910391SAndreas.Sandberg@ARM.com            return v1[i] < v2[i];
33010391SAndreas.Sandberg@ARM.com
33110391SAndreas.Sandberg@ARM.com    // Special compare for last element.
33210391SAndreas.Sandberg@ARM.com    if (v1[last] == v2[last])
33310391SAndreas.Sandberg@ARM.com        return v1.size() < v2.size();
33410391SAndreas.Sandberg@ARM.com    else
33510391SAndreas.Sandberg@ARM.com        return v1[last] < v2[last];
33610391SAndreas.Sandberg@ARM.com
33710391SAndreas.Sandberg@ARM.com    return false;
33810391SAndreas.Sandberg@ARM.com}
33910391SAndreas.Sandberg@ARM.com
34010391SAndreas.Sandberg@ARM.combool
34110391SAndreas.Sandberg@ARM.comStatData::check() const
34210391SAndreas.Sandberg@ARM.com{
34310391SAndreas.Sandberg@ARM.com    if (!init) {
34410391SAndreas.Sandberg@ARM.com#ifdef STAT_DEBUG
34510391SAndreas.Sandberg@ARM.com        cprintf("this is stat number %d\n",(*i)->number);
34610391SAndreas.Sandberg@ARM.com#endif
34710391SAndreas.Sandberg@ARM.com        panic("Not all stats have been initialized");
34810391SAndreas.Sandberg@ARM.com        return false;
34910391SAndreas.Sandberg@ARM.com    }
35010391SAndreas.Sandberg@ARM.com
35110391SAndreas.Sandberg@ARM.com    if (print && name.empty()) {
35210391SAndreas.Sandberg@ARM.com        panic("all printable stats must be named");
35310391SAndreas.Sandberg@ARM.com        return false;
35410391SAndreas.Sandberg@ARM.com    }
35510391SAndreas.Sandberg@ARM.com
35610391SAndreas.Sandberg@ARM.com    return true;
35710391SAndreas.Sandberg@ARM.com}
35810391SAndreas.Sandberg@ARM.com
35910391SAndreas.Sandberg@ARM.comstring
36010391SAndreas.Sandberg@ARM.comValueToString(result_t value, DisplayMode mode, int precision)
36110391SAndreas.Sandberg@ARM.com{
36210391SAndreas.Sandberg@ARM.com    stringstream val;
36310391SAndreas.Sandberg@ARM.com
36410391SAndreas.Sandberg@ARM.com    if (!isnan(value)) {
36510391SAndreas.Sandberg@ARM.com        if (precision != -1)
36610391SAndreas.Sandberg@ARM.com            val.precision(precision);
36710391SAndreas.Sandberg@ARM.com        else if (value == rint(value))
36810391SAndreas.Sandberg@ARM.com            val.precision(0);
36910391SAndreas.Sandberg@ARM.com
37010391SAndreas.Sandberg@ARM.com        val.unsetf(ios::showpoint);
37110391SAndreas.Sandberg@ARM.com        val.setf(ios::fixed);
37210391SAndreas.Sandberg@ARM.com        val << value;
37310391SAndreas.Sandberg@ARM.com    } else {
37410391SAndreas.Sandberg@ARM.com        val << (mode == mode_m5 ? "no value" : "<err: div-0>");
37510391SAndreas.Sandberg@ARM.com    }
37610391SAndreas.Sandberg@ARM.com
37710391SAndreas.Sandberg@ARM.com    return val.str();
37810391SAndreas.Sandberg@ARM.com}
37910391SAndreas.Sandberg@ARM.com
38010391SAndreas.Sandberg@ARM.comstruct ScalarPrint
38110391SAndreas.Sandberg@ARM.com{
38210391SAndreas.Sandberg@ARM.com    result_t value;
38310391SAndreas.Sandberg@ARM.com    string name;
38410391SAndreas.Sandberg@ARM.com    string desc;
38510391SAndreas.Sandberg@ARM.com    int precision;
386    DisplayMode mode;
387    FormatFlags flags;
388    result_t pdf;
389    result_t cdf;
390
391    ScalarPrint()
392        : value(0.0), precision(0), mode(default_mode), flags(0),
393          pdf(NAN), cdf(NAN)
394    {}
395
396    void operator()(ostream &stream) const;
397};
398
399void
400ScalarPrint::operator()(ostream &stream) const
401{
402    if (flags & nozero && value == 0.0 ||
403        flags & nonan && isnan(value))
404        return;
405
406    stringstream pdfstr, cdfstr;
407
408    if (!isnan(pdf))
409        ccprintf(pdfstr, "%.2f%%", pdf * 100.0);
410
411    if (!isnan(cdf))
412        ccprintf(cdfstr, "%.2f%%", cdf * 100.0);
413
414    if (mode == mode_simplescalar && flags & __substat) {
415        ccprintf(stream, "%32s %12s %10s %10s", name,
416                 ValueToString(value, mode, precision),
417                 pdfstr, cdfstr);
418    } else {
419        ccprintf(stream, "%-40s %12s %10s %10s", name,
420                 ValueToString(value, mode, precision), pdfstr, cdfstr);
421    }
422
423    if (PrintDescriptions) {
424        if (!desc.empty())
425            ccprintf(stream, " # %s", desc);
426    }
427    stream << endl;
428}
429
430struct VectorPrint
431{
432    string name;
433    string desc;
434    vector<string> subnames;
435    vector<string> subdescs;
436    int precision;
437    DisplayMode mode;
438    FormatFlags flags;
439    rvec_t vec;
440    result_t total;
441
442    VectorPrint()
443        : subnames(0), subdescs(0), precision(-1), mode(default_mode),
444          flags(0), total(NAN)
445    {}
446
447    void operator()(ostream &stream) const;
448};
449
450void
451VectorPrint::operator()(std::ostream &stream) const
452{
453    int _size = vec.size();
454    result_t _total = 0.0;
455
456    if (flags & (pdf | cdf)) {
457        for (int i = 0; i < _size; ++i) {
458            _total += vec[i];
459        }
460    }
461
462    string base = name + ((mode == mode_simplescalar) ? "_" : "::");
463
464    ScalarPrint print;
465    print.name = name;
466    print.desc = desc;
467    print.precision = precision;
468    print.flags = flags;
469
470    bool havesub = !subnames.empty();
471
472    if (_size == 1) {
473        print.value = vec[0];
474        print(stream);
475    } else if (mode == mode_m5) {
476        for (int i = 0; i < _size; ++i) {
477            if (havesub && (i >= subnames.size() || subnames[i].empty()))
478                continue;
479
480            print.name = base + (havesub ? subnames[i] : to_string(i));
481            print.desc = subdescs.empty() ? desc : subdescs[i];
482            print.value = vec[i];
483
484            if (_total && (flags & pdf)) {
485                print.pdf = vec[i] / _total;
486                print.cdf += print.pdf;
487            }
488
489            print(stream);
490        }
491
492        if (flags & ::Statistics::total) {
493            print.name = base + "total";
494            print.desc = desc;
495            print.value = total;
496            print(stream);
497        }
498    } else {
499        if (flags & ::Statistics::total) {
500            print.value = total;
501            print(stream);
502        }
503
504        result_t _pdf = 0.0;
505        result_t _cdf = 0.0;
506        if (flags & dist) {
507            ccprintf(stream, "%s.start_dist\n", name);
508            for (int i = 0; i < _size; ++i) {
509                print.name = havesub ? subnames[i] : to_string(i);
510                print.desc = subdescs.empty() ? desc : subdescs[i];
511                print.flags |= __substat;
512                print.value = vec[i];
513
514                if (_total) {
515                    _pdf = vec[i] / _total;
516                    _cdf += _pdf;
517                }
518
519                if (flags & pdf)
520                    print.pdf = _pdf;
521                if (flags & cdf)
522                    print.cdf = _cdf;
523
524                print(stream);
525            }
526            ccprintf(stream, "%s.end_dist\n", name);
527        } else {
528            for (int i = 0; i < _size; ++i) {
529                if (havesub && subnames[i].empty())
530                    continue;
531
532                print.name = base;
533                print.name += havesub ? subnames[i] : to_string(i);
534                print.desc = subdescs.empty() ? desc : subdescs[i];
535                print.value = vec[i];
536
537                if (_total) {
538                    _pdf = vec[i] / _total;
539                    _cdf += _pdf;
540                } else {
541                    _pdf = _cdf = NAN;
542                }
543
544                if (flags & pdf) {
545                    print.pdf = _pdf;
546                    print.cdf = _cdf;
547                }
548
549                print(stream);
550            }
551        }
552    }
553}
554
555struct DistPrint
556{
557    string name;
558    string desc;
559    int precision;
560    DisplayMode mode;
561    FormatFlags flags;
562
563    result_t min_val;
564    result_t max_val;
565    result_t underflow;
566    result_t overflow;
567    rvec_t vec;
568    result_t sum;
569    result_t squares;
570    result_t samples;
571
572    int min;
573    int max;
574    int bucket_size;
575    int size;
576    bool fancy;
577
578    void operator()(ostream &stream) const;
579};
580
581void
582DistPrint::operator()(ostream &stream) const
583{
584    if (fancy) {
585        ScalarPrint print;
586        string base = name + ((mode == mode_m5) ? "::" : "_");
587
588        print.precision = precision;
589        print.flags = flags;
590        print.desc = desc;
591
592        print.name = base + "mean";
593        print.value = samples ? sum / samples : NAN;
594        print(stream);
595
596        print.name = base + "stdev";
597        print.value = samples ? sqrt((samples * squares - sum * sum) /
598                                     (samples * (samples - 1.0))) : NAN;
599        print(stream);
600
601        print.name = "**Ignore: " + base + "TOT";
602        print.value = samples;
603        print(stream);
604        return;
605    }
606
607    assert(size == vec.size());
608
609    result_t total = 0.0;
610
611    total += underflow;
612    for (int i = 0; i < size; ++i)
613        total += vec[i];
614    total += overflow;
615
616    string base = name + (mode == mode_m5 ? "::" : ".");
617
618    ScalarPrint print;
619    print.desc = (mode == mode_m5) ? desc : "";
620    print.precision = precision;
621    print.mode = mode;
622    print.flags = flags;
623
624    if (mode == mode_simplescalar) {
625        ccprintf(stream, "%-42s", base + "start_dist");
626        if (PrintDescriptions && !desc.empty())
627            ccprintf(stream, "                     # %s", desc);
628        stream << endl;
629    }
630
631    print.name = base + "samples";
632    print.value = samples;
633    print(stream);
634
635    print.name = base + "min_value";
636    print.value = min_val;
637    print(stream);
638
639    if (mode == mode_m5 || underflow > 0.0) {
640        print.name = base + "underflows";
641        print.value = underflow;
642        if (mode == mode_m5 && total) {
643            print.pdf = underflow / total;
644            print.cdf += print.pdf;
645        }
646        print(stream);
647    }
648
649
650    if (mode == mode_m5) {
651        for (int i = 0; i < size; ++i) {
652            stringstream namestr;
653            namestr << name;
654
655            int low = i * bucket_size + min;
656            int high = ::min((i + 1) * bucket_size + min - 1, max);
657            namestr << low;
658            if (low < high)
659                namestr << "-" << high;
660
661            print.name = namestr.str();
662            print.value = vec[i];
663            if (total) {
664                print.pdf = vec[i] / total;
665                print.cdf += print.pdf;
666            }
667            print(stream);
668        }
669
670    } else {
671        int _min;
672        result_t _pdf;
673        result_t _cdf = 0.0;
674
675        print.flags = flags | __substat;
676
677        for (int i = 0; i < size; ++i) {
678            if (flags & nozero && vec[i] == 0.0 ||
679                flags & nonan && isnan(vec[i]))
680                continue;
681
682            _min = i * bucket_size + min;
683            _pdf = vec[i] / total * 100.0;
684            _cdf += _pdf;
685
686
687            print.name = ValueToString(_min, mode, 0);
688            print.value = vec[i];
689            print.pdf = (flags & pdf) ? _pdf : NAN;
690            print.cdf = (flags & cdf) ? _cdf : NAN;
691            print(stream);
692        }
693
694        print.flags = flags;
695        if (flags & (pdf || cdf)) {
696            print.pdf = NAN;
697            print.cdf = NAN;
698        }
699    }
700
701    if (mode == mode_m5 || overflow > 0.0) {
702        print.name = base + "overflows";
703        print.value = overflow;
704        if (mode == mode_m5 && total) {
705            print.pdf = overflow / total;
706            print.cdf += print.pdf;
707        }
708        print(stream);
709    }
710
711    print.pdf = NAN;
712    print.cdf = NAN;
713
714    if (mode != mode_simplescalar) {
715        print.name = base + "total";
716        print.value = total;
717        print(stream);
718    }
719
720    print.name = base + "max_value";
721    print.value = max_val;
722    print(stream);
723
724    if (mode != mode_simplescalar && samples != 0) {
725        print.name = base + "mean";
726        print.value = sum / samples;
727        print(stream);
728
729        print.name = base + "stdev";
730        print.value = sqrt((samples * squares - sum * sum) /
731                           (samples * (samples - 1.0)));
732        print(stream);
733    }
734
735    if (mode == mode_simplescalar)
736        ccprintf(stream, "%send_dist\n\n", base);
737}
738
739void
740ScalarDataBase::display(ostream &stream) const
741{
742    ScalarPrint print;
743    print.value = val();
744    print.name = name;
745    print.desc = desc;
746    print.precision = precision;
747    print.flags = flags;
748
749    print(stream);
750}
751
752void
753VectorDataBase::display(ostream &stream) const
754{
755    int size = this->size();
756    const_cast<VectorDataBase *>(this)->update();
757
758    VectorPrint print;
759
760    print.name = name;
761    print.desc = desc;
762    print.mode = mode;
763    print.flags = flags;
764    print.precision = precision;
765    print.vec = val();
766    print.total = total();
767
768    for (int i = 0; i < size; ++i) {
769        if (!subnames[i].empty()) {
770            print.subnames = subnames;
771            print.subnames.resize(size);
772            for (int i = 0; i < size; ++i) {
773                if (!subnames[i].empty() && !subdescs[i].empty()) {
774                    print.subdescs = subdescs;
775                    print.subdescs.resize(size);
776                    break;
777                }
778            }
779            break;
780        }
781    }
782
783
784    print(stream);
785}
786
787void
788Vector2dDataBase::display(ostream &stream) const
789{
790    const_cast<Vector2dDataBase *>(this)->update();
791
792    bool havesub = false;
793    VectorPrint print;
794
795    print.subnames = y_subnames;
796    print.mode = mode;
797    print.flags = flags;
798    print.precision = precision;
799
800    if (!subnames.empty()) {
801        for (int i = 0; i < x; ++i)
802            if (!subnames[i].empty())
803                havesub = true;
804    }
805
806    rvec_t tot_vec(y);
807    result_t super_total = 0.0;
808    for (int i = 0; i < x; ++i) {
809        if (havesub && (i >= subnames.size() || subnames[i].empty()))
810            continue;
811
812        int iy = i * y;
813        rvec_t yvec(y);
814
815        result_t total = 0.0;
816        for (int j = 0; j < y; ++j) {
817            yvec[j] = vec[iy + j];
818            tot_vec[j] += yvec[j];
819            total += yvec[j];
820            super_total += yvec[j];
821        }
822
823        print.name = name + "_" + (havesub ? subnames[i] : to_string(i));
824        print.desc = desc;
825        print.vec = yvec;
826        print.total = total;
827        print(stream);
828    }
829
830    if ((flags & ::Statistics::total) && (x > 1)) {
831        print.name = name;
832        print.desc = desc;
833        print.vec = tot_vec;
834        print.total = super_total;
835        print(stream);
836    }
837}
838
839void
840DistDataBase::display(ostream &stream) const
841{
842    const_cast<DistDataBase *>(this)->update();
843
844    DistPrint print;
845
846    print.name = name;
847    print.desc = desc;
848    print.precision = precision;
849    print.mode = mode;
850    print.flags = flags;
851
852    print.min_val = data.min_val;
853    print.max_val = data.max_val;
854    print.underflow = data.underflow;
855    print.overflow = data.overflow;
856    print.vec = data.vec;
857    print.sum = data.sum;
858    print.squares = data.squares;
859    print.samples = data.samples;
860
861    print.min = data.min;
862    print.max = data.max;
863    print.bucket_size = data.bucket_size;
864    print.size = data.size;
865    print.fancy = data.fancy;
866
867    print(stream);
868}
869
870void
871VectorDistDataBase::display(ostream &stream) const
872{
873    const_cast<VectorDistDataBase *>(this)->update();
874
875    for (int i = 0; i < size(); ++i) {
876        DistPrint print;
877
878        print.name = name +
879            (subnames[i].empty() ? ("_" + to_string(i)) : subnames[i]);
880        print.desc = subdescs[i].empty() ? desc : subdescs[i];
881        print.precision = precision;
882        print.mode = mode;
883        print.flags = flags;
884
885        print.min_val = data[i].min_val;
886        print.max_val = data[i].max_val;
887        print.underflow = data[i].underflow;
888        print.overflow = data[i].overflow;
889        print.vec = data[i].vec;
890        print.sum = data[i].sum;
891        print.squares = data[i].squares;
892        print.samples = data[i].samples;
893
894        print.min = data[i].min;
895        print.max = data[i].max;
896        print.bucket_size = data[i].bucket_size;
897        print.size = data[i].size;
898        print.fancy = data[i].fancy;
899
900        print(stream);
901    }
902}
903
904void
905FormulaBase::val(rvec_t &vec) const
906{
907    vec = root->val();
908}
909
910result_t
911FormulaBase::total() const
912{
913    return root->total();
914}
915
916size_t
917FormulaBase::size() const
918{
919    if (!root)
920        return 0;
921    else
922        return root->size();
923}
924
925bool
926FormulaBase::binned() const
927{
928    return root->binned();
929}
930
931void
932FormulaBase::reset()
933{
934}
935
936bool
937FormulaBase::zero() const
938{
939    rvec_t vec;
940    val(vec);
941    for (int i = 0; i < vec.size(); ++i)
942        if (vec[i] != 0.0)
943            return false;
944    return true;
945}
946
947void
948FormulaBase::update(StatData *)
949{
950}
951
952Formula::Formula()
953{
954    setInit();
955}
956
957Formula::Formula(Temp r)
958{
959    root = r;
960    assert(size());
961}
962
963const Formula &
964Formula::operator=(Temp r)
965{
966    assert(!root && "Can't change formulas");
967    root = r;
968    assert(size());
969    return *this;
970}
971
972const Formula &
973Formula::operator+=(Temp r)
974{
975    if (root)
976        root = NodePtr(new BinaryNode<std::plus<result_t> >(root, r));
977    else
978        root = r;
979    assert(size());
980    return *this;
981}
982
983MainBin::MainBin(const string &name)
984    : _name(name), mem(NULL), memsize(-1)
985{
986    Database::StatDB().regBin(this, name);
987}
988
989MainBin::~MainBin()
990{
991    if (mem)
992        delete [] mem;
993}
994
995char *
996MainBin::memory(off_t off)
997{
998    if (memsize == -1)
999        memsize = CeilPow2((size_t) offset());
1000
1001    if (!mem) {
1002        mem = new char[memsize];
1003        memset(mem, 0, memsize);
1004    }
1005
1006    assert(offset() <= size());
1007    return mem + off;
1008}
1009
1010void
1011check()
1012{
1013    Database::StatDB().check();
1014}
1015
1016void
1017dump(ostream &stream)
1018{
1019    Database::StatDB().dump(stream);
1020}
1021
1022CallbackQueue resetQueue;
1023
1024void
1025RegResetCallback(Callback *cb)
1026{
1027    resetQueue.add(cb);
1028}
1029
1030void
1031reset()
1032{
1033    Database::StatDB().reset();
1034    resetQueue.process();
1035}
1036
1037} // namespace Statistics
1038