statistics.cc revision 8243
12SN/A/*
21762SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan
32SN/A * All rights reserved.
42SN/A *
52SN/A * Redistribution and use in source and binary forms, with or without
62SN/A * modification, are permitted provided that the following conditions are
72SN/A * met: redistributions of source code must retain the above copyright
82SN/A * notice, this list of conditions and the following disclaimer;
92SN/A * redistributions in binary form must reproduce the above copyright
102SN/A * notice, this list of conditions and the following disclaimer in the
112SN/A * documentation and/or other materials provided with the distribution;
122SN/A * neither the name of the copyright holders nor the names of its
132SN/A * contributors may be used to endorse or promote products derived from
142SN/A * this software without specific prior written permission.
152SN/A *
162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * Authors: Nathan Binkert
292SN/A */
302SN/A
318229Snate@binkert.org#include <fstream>
322SN/A#include <iomanip>
332SN/A#include <list>
342SN/A#include <map>
352SN/A#include <string>
362SN/A
37148SN/A#include "base/callback.hh"
3856SN/A#include "base/cprintf.hh"
395889Snate@binkert.org#include "base/debug.hh"
40441SN/A#include "base/hostinfo.hh"
4156SN/A#include "base/misc.hh"
4256SN/A#include "base/statistics.hh"
4356SN/A#include "base/str.hh"
44441SN/A#include "base/time.hh"
45433SN/A#include "base/trace.hh"
462SN/A
472SN/Ausing namespace std;
482SN/A
49729SN/Anamespace Stats {
50388SN/A
518243Sbradley.danofsky@amd.comstd::string Info::separatorString = "::";
525887Snate@binkert.orgtypedef map<const void *, Info *> MapType;
535887Snate@binkert.org
545887Snate@binkert.org// We wrap these in a function to make sure they're built in time.
555887Snate@binkert.orglist<Info *> &
565887Snate@binkert.orgstatsList()
57388SN/A{
585887Snate@binkert.org    static list<Info *> the_list;
595887Snate@binkert.org    return the_list;
60388SN/A}
61388SN/A
625887Snate@binkert.orgMapType &
635887Snate@binkert.orgstatsMap()
64441SN/A{
655887Snate@binkert.org    static MapType the_map;
665887Snate@binkert.org    return the_map;
67441SN/A}
68441SN/A
69388SN/Avoid
705886Snate@binkert.orgInfoAccess::setInfo(Info *info)
71388SN/A{
725887Snate@binkert.org    if (statsMap().find(this) != statsMap().end())
735887Snate@binkert.org        panic("shouldn't register stat twice!");
745887Snate@binkert.org
755887Snate@binkert.org    statsList().push_back(info);
765887Snate@binkert.org
775887Snate@binkert.org#ifndef NDEBUG
785887Snate@binkert.org    pair<MapType::iterator, bool> result =
795887Snate@binkert.org#endif
805887Snate@binkert.org        statsMap().insert(make_pair(this, info));
815887Snate@binkert.org    assert(result.second && "this should never fail");
825887Snate@binkert.org    assert(statsMap().find(this) != statsMap().end());
83388SN/A}
84388SN/A
85388SN/Avoid
865889Snate@binkert.orgInfoAccess::setParams(const StorageParams *params)
875889Snate@binkert.org{
885889Snate@binkert.org    info()->storageParams = params;
895889Snate@binkert.org}
905889Snate@binkert.org
915889Snate@binkert.orgvoid
925886Snate@binkert.orgInfoAccess::setInit()
93388SN/A{
946130Snate@binkert.org    info()->flags.set(init);
95388SN/A}
96388SN/A
975886Snate@binkert.orgInfo *
985886Snate@binkert.orgInfoAccess::info()
99388SN/A{
1005887Snate@binkert.org    MapType::const_iterator i = statsMap().find(this);
1015887Snate@binkert.org    assert(i != statsMap().end());
1025887Snate@binkert.org    return (*i).second;
103388SN/A}
104388SN/A
1055886Snate@binkert.orgconst Info *
1065886Snate@binkert.orgInfoAccess::info() const
1075886Snate@binkert.org{
1085887Snate@binkert.org    MapType::const_iterator i = statsMap().find(this);
1095887Snate@binkert.org    assert(i != statsMap().end());
1105887Snate@binkert.org    return (*i).second;
1115886Snate@binkert.org}
1125886Snate@binkert.org
1135889Snate@binkert.orgStorageParams::~StorageParams()
1145889Snate@binkert.org{
1155889Snate@binkert.org}
1165889Snate@binkert.org
1176026Snate@binkert.orgtypedef map<std::string, Info *> NameMapType;
1186026Snate@binkert.orgNameMapType &
1196026Snate@binkert.orgnameMap()
1206026Snate@binkert.org{
1216026Snate@binkert.org    static NameMapType the_map;
1226026Snate@binkert.org    return the_map;
1236026Snate@binkert.org}
1246026Snate@binkert.org
1255889Snate@binkert.orgint Info::id_count = 0;
1265889Snate@binkert.org
1275889Snate@binkert.orgint debug_break_id = -1;
1285889Snate@binkert.org
1295886Snate@binkert.orgInfo::Info()
1305889Snate@binkert.org    : flags(none), precision(-1), prereq(0), storageParams(NULL)
131582SN/A{
1325889Snate@binkert.org    id = id_count++;
1335889Snate@binkert.org    if (debug_break_id >= 0 and debug_break_id == id)
1348231Snate@binkert.org        Debug::breakpoint();
135582SN/A}
136582SN/A
1375886Snate@binkert.orgInfo::~Info()
138388SN/A{
139388SN/A}
140388SN/A
1416026Snate@binkert.orgvoid
1426026Snate@binkert.orgInfo::setName(const string &name)
1436026Snate@binkert.org{
1446026Snate@binkert.org    pair<NameMapType::iterator, bool> p =
1456026Snate@binkert.org        nameMap().insert(make_pair(name, this));
1466026Snate@binkert.org
1476026Snate@binkert.org    Info *other = p.first->second;
1486026Snate@binkert.org    bool result = p.second;
1496026Snate@binkert.org
1506026Snate@binkert.org    if (!result) {
1516026Snate@binkert.org        // using other->name instead of just name to avoid a compiler
1526026Snate@binkert.org        // warning.  They should be the same.
1536026Snate@binkert.org        panic("same statistic name used twice! name=%s\n", other->name);
1546026Snate@binkert.org    }
1556026Snate@binkert.org
1566026Snate@binkert.org    this->name = name;
1576026Snate@binkert.org}
1586026Snate@binkert.org
1592SN/Abool
1605886Snate@binkert.orgInfo::less(Info *stat1, Info *stat2)
1612SN/A{
162388SN/A    const string &name1 = stat1->name;
163388SN/A    const string &name2 = stat2->name;
1642SN/A
1652SN/A    vector<string> v1;
1662SN/A    vector<string> v2;
1672SN/A
1682SN/A    tokenize(v1, name1, '.');
1692SN/A    tokenize(v2, name2, '.');
1702SN/A
1715599Snate@binkert.org    size_type last = min(v1.size(), v2.size()) - 1;
1725599Snate@binkert.org    for (off_type i = 0; i < last; ++i)
1732SN/A        if (v1[i] != v2[i])
1742SN/A            return v1[i] < v2[i];
1752SN/A
1762SN/A    // Special compare for last element.
1772SN/A    if (v1[last] == v2[last])
1782SN/A        return v1.size() < v2.size();
1792SN/A    else
1802SN/A        return v1[last] < v2[last];
1812SN/A
1822SN/A    return false;
1832SN/A}
1842SN/A
185388SN/Abool
1865886Snate@binkert.orgInfo::baseCheck() const
1872SN/A{
1886000Snate@binkert.org    if (!(flags & Stats::init)) {
189582SN/A#ifdef DEBUG
190695SN/A        cprintf("this is stat number %d\n", id);
191388SN/A#endif
192388SN/A        panic("Not all stats have been initialized");
193388SN/A        return false;
194388SN/A    }
1952SN/A
1967462Snate@binkert.org    if ((flags & display) && name.empty()) {
197388SN/A        panic("all printable stats must be named");
198388SN/A        return false;
199388SN/A    }
2002SN/A
201388SN/A    return true;
2022SN/A}
2032SN/A
2046001Snate@binkert.orgvoid
2056001Snate@binkert.orgInfo::enable()
2066001Snate@binkert.org{
2076001Snate@binkert.org}
2086001Snate@binkert.org
2096001Snate@binkert.orgvoid
2106128Snate@binkert.orgVectorInfo::enable()
2116001Snate@binkert.org{
2126001Snate@binkert.org    size_type s = size();
2136001Snate@binkert.org    if (subnames.size() < s)
2146001Snate@binkert.org        subnames.resize(s);
2156001Snate@binkert.org    if (subdescs.size() < s)
2166001Snate@binkert.org        subdescs.resize(s);
2176001Snate@binkert.org}
2186001Snate@binkert.org
2196001Snate@binkert.orgvoid
2206128Snate@binkert.orgVectorDistInfo::enable()
2216001Snate@binkert.org{
2226001Snate@binkert.org    size_type s = size();
2236001Snate@binkert.org    if (subnames.size() < s)
2246001Snate@binkert.org        subnames.resize(s);
2256001Snate@binkert.org    if (subdescs.size() < s)
2266001Snate@binkert.org        subdescs.resize(s);
2276001Snate@binkert.org}
2286001Snate@binkert.org
2296001Snate@binkert.orgvoid
2306128Snate@binkert.orgVector2dInfo::enable()
2316001Snate@binkert.org{
2326001Snate@binkert.org    if (subnames.size() < x)
2336001Snate@binkert.org        subnames.resize(x);
2346001Snate@binkert.org    if (subdescs.size() < x)
2356001Snate@binkert.org        subdescs.resize(x);
2366001Snate@binkert.org    if (y_subnames.size() < y)
2376001Snate@binkert.org        y_subnames.resize(y);
2386001Snate@binkert.org}
239695SN/A
2407831Snate@binkert.orgvoid
2417831Snate@binkert.orgHistStor::grow_out()
2427831Snate@binkert.org{
2437831Snate@binkert.org    int size = cvec.size();
2447831Snate@binkert.org    int zero = size / 2; // round down!
2457831Snate@binkert.org    int top_half = zero + (size - zero + 1) / 2; // round up!
2467831Snate@binkert.org    int bottom_half = (size - zero) / 2; // round down!
2477831Snate@binkert.org
2487831Snate@binkert.org    // grow down
2497831Snate@binkert.org    int low_pair = zero - 1;
2507831Snate@binkert.org    for (int i = zero - 1; i >= bottom_half; i--) {
2517831Snate@binkert.org        cvec[i] = cvec[low_pair];
2527831Snate@binkert.org        if (low_pair - 1 >= 0)
2537831Snate@binkert.org            cvec[i] += cvec[low_pair - 1];
2547831Snate@binkert.org        low_pair -= 2;
2557831Snate@binkert.org    }
2567831Snate@binkert.org    assert(low_pair == 0 || low_pair == -1 || low_pair == -2);
2577831Snate@binkert.org
2587831Snate@binkert.org    for (int i = bottom_half - 1; i >= 0; i--)
2597831Snate@binkert.org        cvec[i] = Counter();
2607831Snate@binkert.org
2617831Snate@binkert.org    // grow up
2627831Snate@binkert.org    int high_pair = zero;
2637831Snate@binkert.org    for (int i = zero; i < top_half; i++) {
2647831Snate@binkert.org        cvec[i] = cvec[high_pair];
2657831Snate@binkert.org        if (high_pair + 1 < size)
2667831Snate@binkert.org            cvec[i] += cvec[high_pair + 1];
2677831Snate@binkert.org        high_pair += 2;
2687831Snate@binkert.org    }
2697831Snate@binkert.org    assert(high_pair == size || high_pair == size + 1);
2707831Snate@binkert.org
2717831Snate@binkert.org    for (int i = top_half; i < size; i++)
2727831Snate@binkert.org        cvec[i] = Counter();
2737831Snate@binkert.org
2747831Snate@binkert.org    max_bucket *= 2;
2757831Snate@binkert.org    min_bucket *= 2;
2767831Snate@binkert.org    bucket_size *= 2;
2777831Snate@binkert.org}
2787831Snate@binkert.org
2797831Snate@binkert.orgvoid
2807831Snate@binkert.orgHistStor::grow_convert()
2817831Snate@binkert.org{
2827831Snate@binkert.org    int size = cvec.size();
2837831Snate@binkert.org    int half = (size + 1) / 2; // round up!
2847831Snate@binkert.org    //bool even = (size & 1) == 0;
2857831Snate@binkert.org
2867831Snate@binkert.org    int pair = size - 1;
2877831Snate@binkert.org    for (int i = size - 1; i >= half; --i) {
2887831Snate@binkert.org        cvec[i] = cvec[pair];
2897831Snate@binkert.org        if (pair - 1 >= 0)
2907831Snate@binkert.org            cvec[i] += cvec[pair - 1];
2917831Snate@binkert.org        pair -= 2;
2927831Snate@binkert.org    }
2937831Snate@binkert.org
2947831Snate@binkert.org    for (int i = half - 1; i >= 0; i--)
2957831Snate@binkert.org        cvec[i] = Counter();
2967831Snate@binkert.org
2977831Snate@binkert.org    min_bucket = -max_bucket;// - (even ? bucket_size : 0);
2987831Snate@binkert.org    bucket_size *= 2;
2997831Snate@binkert.org}
3007831Snate@binkert.org
3017831Snate@binkert.orgvoid
3027831Snate@binkert.orgHistStor::grow_up()
3037831Snate@binkert.org{
3047831Snate@binkert.org    int size = cvec.size();
3057831Snate@binkert.org    int half = (size + 1) / 2; // round up!
3067831Snate@binkert.org
3077831Snate@binkert.org    int pair = 0;
3087831Snate@binkert.org    for (int i = 0; i < half; i++) {
3097831Snate@binkert.org        cvec[i] = cvec[pair];
3107831Snate@binkert.org        if (pair + 1 < size)
3117831Snate@binkert.org            cvec[i] += cvec[pair + 1];
3127831Snate@binkert.org        pair += 2;
3137831Snate@binkert.org    }
3147831Snate@binkert.org    assert(pair == size || pair == size + 1);
3157831Snate@binkert.org
3167831Snate@binkert.org    for (int i = half; i < size; i++)
3177831Snate@binkert.org        cvec[i] = Counter();
3187831Snate@binkert.org
3197831Snate@binkert.org    max_bucket *= 2;
3207831Snate@binkert.org    bucket_size *= 2;
3217831Snate@binkert.org}
3227831Snate@binkert.org
323388SN/AFormula::Formula()
324388SN/A{
325388SN/A}
326388SN/A
327388SN/AFormula::Formula(Temp r)
328388SN/A{
329388SN/A    root = r;
3307461Snate@binkert.org    setInit();
331388SN/A    assert(size());
332388SN/A}
333388SN/A
334388SN/Aconst Formula &
335388SN/AFormula::operator=(Temp r)
336388SN/A{
337388SN/A    assert(!root && "Can't change formulas");
338388SN/A    root = r;
3397461Snate@binkert.org    setInit();
340388SN/A    assert(size());
341388SN/A    return *this;
342388SN/A}
343388SN/A
344388SN/Aconst Formula &
345388SN/AFormula::operator+=(Temp r)
346388SN/A{
347388SN/A    if (root)
348695SN/A        root = NodePtr(new BinaryNode<std::plus<Result> >(root, r));
3497461Snate@binkert.org    else {
350388SN/A        root = r;
3517461Snate@binkert.org        setInit();
3527461Snate@binkert.org    }
3537461Snate@binkert.org
354388SN/A    assert(size());
355388SN/A    return *this;
356388SN/A}
357388SN/A
358142SN/Avoid
3596000Snate@binkert.orgFormula::result(VResult &vec) const
3606000Snate@binkert.org{
3616000Snate@binkert.org    if (root)
3626000Snate@binkert.org        vec = root->result();
3636000Snate@binkert.org}
3646000Snate@binkert.org
3656000Snate@binkert.orgResult
3666000Snate@binkert.orgFormula::total() const
3676000Snate@binkert.org{
3686000Snate@binkert.org    return root ? root->total() : 0.0;
3696000Snate@binkert.org}
3706000Snate@binkert.org
3716000Snate@binkert.orgsize_type
3726000Snate@binkert.orgFormula::size() const
3736000Snate@binkert.org{
3746000Snate@binkert.org    if (!root)
3756000Snate@binkert.org        return 0;
3766000Snate@binkert.org    else
3776000Snate@binkert.org        return root->size();
3786000Snate@binkert.org}
3796000Snate@binkert.org
3806000Snate@binkert.orgvoid
3816000Snate@binkert.orgFormula::reset()
3826000Snate@binkert.org{
3836000Snate@binkert.org}
3846000Snate@binkert.org
3856000Snate@binkert.orgbool
3866000Snate@binkert.orgFormula::zero() const
3876000Snate@binkert.org{
3886000Snate@binkert.org    VResult vec;
3896000Snate@binkert.org    result(vec);
3906227Snate@binkert.org    for (VResult::size_type i = 0; i < vec.size(); ++i)
3916000Snate@binkert.org        if (vec[i] != 0.0)
3926000Snate@binkert.org            return false;
3936000Snate@binkert.org    return true;
3946000Snate@binkert.org}
3956000Snate@binkert.org
3966000Snate@binkert.orgstring
3976000Snate@binkert.orgFormula::str() const
3986000Snate@binkert.org{
3996000Snate@binkert.org    return root ? root->str() : "";
4006000Snate@binkert.org}
4016000Snate@binkert.org
4026000Snate@binkert.orgvoid
4036001Snate@binkert.orgenable()
4042SN/A{
4055887Snate@binkert.org    typedef list<Info *>::iterator iter_t;
406695SN/A
4075887Snate@binkert.org    iter_t i, end = statsList().end();
4085887Snate@binkert.org    for (i = statsList().begin(); i != end; ++i) {
4095886Snate@binkert.org        Info *info = *i;
4105886Snate@binkert.org        assert(info);
4115886Snate@binkert.org        if (!info->check() || !info->baseCheck())
4125889Snate@binkert.org            panic("stat check failed for '%s' %d\n", info->name, info->id);
413695SN/A    }
414695SN/A
4155599Snate@binkert.org    off_t j = 0;
4165887Snate@binkert.org    for (i = statsList().begin(); i != end; ++i) {
4175886Snate@binkert.org        Info *info = *i;
4187462Snate@binkert.org        if (!(info->flags & display))
4195886Snate@binkert.org            info->name = "__Stat" + to_string(j++);
420695SN/A    }
421695SN/A
4225887Snate@binkert.org    statsList().sort(Info::less);
423695SN/A
4246001Snate@binkert.org    for (i = statsList().begin(); i != end; ++i) {
4256001Snate@binkert.org        Info *info = *i;
4266001Snate@binkert.org        info->enable();
4276001Snate@binkert.org    }
4286001Snate@binkert.org}
429695SN/A
4306001Snate@binkert.orgvoid
4316001Snate@binkert.orgprepare()
4326001Snate@binkert.org{
4336001Snate@binkert.org    list<Info *>::iterator i = statsList().begin();
4346001Snate@binkert.org    list<Info *>::iterator end = statsList().end();
4356001Snate@binkert.org    while (i != end) {
4366001Snate@binkert.org        Info *info = *i;
4376001Snate@binkert.org        info->prepare();
4386001Snate@binkert.org        ++i;
439695SN/A    }
4402SN/A}
4412SN/A
442695SN/ACallbackQueue resetQueue;
4432SN/A
444456SN/Avoid
445695SN/Areset()
446456SN/A{
4475887Snate@binkert.org    list<Info *>::iterator i = statsList().begin();
4485887Snate@binkert.org    list<Info *>::iterator end = statsList().end();
449695SN/A    while (i != end) {
4505886Snate@binkert.org        Info *info = *i;
4515886Snate@binkert.org        info->reset();
452695SN/A        ++i;
453695SN/A    }
454695SN/A
455695SN/A    resetQueue.process();
456456SN/A}
457456SN/A
458456SN/Avoid
459394SN/AregisterResetCallback(Callback *cb)
460148SN/A{
461148SN/A    resetQueue.add(cb);
462148SN/A}
463148SN/A
4647811Ssteve.reinhardt@amd.com} // namespace Stats
465