statistics.cc revision 7811
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
312SN/A#include <iomanip>
32456SN/A#include <fstream>
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
515887Snate@binkert.orgtypedef map<const void *, Info *> MapType;
525887Snate@binkert.org
535887Snate@binkert.org// We wrap these in a function to make sure they're built in time.
545887Snate@binkert.orglist<Info *> &
555887Snate@binkert.orgstatsList()
56388SN/A{
575887Snate@binkert.org    static list<Info *> the_list;
585887Snate@binkert.org    return the_list;
59388SN/A}
60388SN/A
615887Snate@binkert.orgMapType &
625887Snate@binkert.orgstatsMap()
63441SN/A{
645887Snate@binkert.org    static MapType the_map;
655887Snate@binkert.org    return the_map;
66441SN/A}
67441SN/A
68388SN/Avoid
695886Snate@binkert.orgInfoAccess::setInfo(Info *info)
70388SN/A{
715887Snate@binkert.org    if (statsMap().find(this) != statsMap().end())
725887Snate@binkert.org        panic("shouldn't register stat twice!");
735887Snate@binkert.org
745887Snate@binkert.org    statsList().push_back(info);
755887Snate@binkert.org
765887Snate@binkert.org#ifndef NDEBUG
775887Snate@binkert.org    pair<MapType::iterator, bool> result =
785887Snate@binkert.org#endif
795887Snate@binkert.org        statsMap().insert(make_pair(this, info));
805887Snate@binkert.org    assert(result.second && "this should never fail");
815887Snate@binkert.org    assert(statsMap().find(this) != statsMap().end());
82388SN/A}
83388SN/A
84388SN/Avoid
855889Snate@binkert.orgInfoAccess::setParams(const StorageParams *params)
865889Snate@binkert.org{
875889Snate@binkert.org    info()->storageParams = params;
885889Snate@binkert.org}
895889Snate@binkert.org
905889Snate@binkert.orgvoid
915886Snate@binkert.orgInfoAccess::setInit()
92388SN/A{
936130Snate@binkert.org    info()->flags.set(init);
94388SN/A}
95388SN/A
965886Snate@binkert.orgInfo *
975886Snate@binkert.orgInfoAccess::info()
98388SN/A{
995887Snate@binkert.org    MapType::const_iterator i = statsMap().find(this);
1005887Snate@binkert.org    assert(i != statsMap().end());
1015887Snate@binkert.org    return (*i).second;
102388SN/A}
103388SN/A
1045886Snate@binkert.orgconst Info *
1055886Snate@binkert.orgInfoAccess::info() const
1065886Snate@binkert.org{
1075887Snate@binkert.org    MapType::const_iterator i = statsMap().find(this);
1085887Snate@binkert.org    assert(i != statsMap().end());
1095887Snate@binkert.org    return (*i).second;
1105886Snate@binkert.org}
1115886Snate@binkert.org
1125889Snate@binkert.orgStorageParams::~StorageParams()
1135889Snate@binkert.org{
1145889Snate@binkert.org}
1155889Snate@binkert.org
1166026Snate@binkert.orgtypedef map<std::string, Info *> NameMapType;
1176026Snate@binkert.orgNameMapType &
1186026Snate@binkert.orgnameMap()
1196026Snate@binkert.org{
1206026Snate@binkert.org    static NameMapType the_map;
1216026Snate@binkert.org    return the_map;
1226026Snate@binkert.org}
1236026Snate@binkert.org
1245889Snate@binkert.orgint Info::id_count = 0;
1255889Snate@binkert.org
1265889Snate@binkert.orgint debug_break_id = -1;
1275889Snate@binkert.org
1285886Snate@binkert.orgInfo::Info()
1295889Snate@binkert.org    : flags(none), precision(-1), prereq(0), storageParams(NULL)
130582SN/A{
1315889Snate@binkert.org    id = id_count++;
1325889Snate@binkert.org    if (debug_break_id >= 0 and debug_break_id == id)
1335889Snate@binkert.org        debug_break();
134582SN/A}
135582SN/A
1365886Snate@binkert.orgInfo::~Info()
137388SN/A{
138388SN/A}
139388SN/A
1406026Snate@binkert.orgvoid
1416026Snate@binkert.orgInfo::setName(const string &name)
1426026Snate@binkert.org{
1436026Snate@binkert.org    pair<NameMapType::iterator, bool> p =
1446026Snate@binkert.org        nameMap().insert(make_pair(name, this));
1456026Snate@binkert.org
1466026Snate@binkert.org    Info *other = p.first->second;
1476026Snate@binkert.org    bool result = p.second;
1486026Snate@binkert.org
1496026Snate@binkert.org    if (!result) {
1506026Snate@binkert.org        // using other->name instead of just name to avoid a compiler
1516026Snate@binkert.org        // warning.  They should be the same.
1526026Snate@binkert.org        panic("same statistic name used twice! name=%s\n", other->name);
1536026Snate@binkert.org    }
1546026Snate@binkert.org
1556026Snate@binkert.org    this->name = name;
1566026Snate@binkert.org}
1576026Snate@binkert.org
1582SN/Abool
1595886Snate@binkert.orgInfo::less(Info *stat1, Info *stat2)
1602SN/A{
161388SN/A    const string &name1 = stat1->name;
162388SN/A    const string &name2 = stat2->name;
1632SN/A
1642SN/A    vector<string> v1;
1652SN/A    vector<string> v2;
1662SN/A
1672SN/A    tokenize(v1, name1, '.');
1682SN/A    tokenize(v2, name2, '.');
1692SN/A
1705599Snate@binkert.org    size_type last = min(v1.size(), v2.size()) - 1;
1715599Snate@binkert.org    for (off_type i = 0; i < last; ++i)
1722SN/A        if (v1[i] != v2[i])
1732SN/A            return v1[i] < v2[i];
1742SN/A
1752SN/A    // Special compare for last element.
1762SN/A    if (v1[last] == v2[last])
1772SN/A        return v1.size() < v2.size();
1782SN/A    else
1792SN/A        return v1[last] < v2[last];
1802SN/A
1812SN/A    return false;
1822SN/A}
1832SN/A
184388SN/Abool
1855886Snate@binkert.orgInfo::baseCheck() const
1862SN/A{
1876000Snate@binkert.org    if (!(flags & Stats::init)) {
188582SN/A#ifdef DEBUG
189695SN/A        cprintf("this is stat number %d\n", id);
190388SN/A#endif
191388SN/A        panic("Not all stats have been initialized");
192388SN/A        return false;
193388SN/A    }
1942SN/A
1957462Snate@binkert.org    if ((flags & display) && name.empty()) {
196388SN/A        panic("all printable stats must be named");
197388SN/A        return false;
198388SN/A    }
1992SN/A
200388SN/A    return true;
2012SN/A}
2022SN/A
2036001Snate@binkert.orgvoid
2046001Snate@binkert.orgInfo::enable()
2056001Snate@binkert.org{
2066001Snate@binkert.org}
2076001Snate@binkert.org
2086001Snate@binkert.orgvoid
2096128Snate@binkert.orgVectorInfo::enable()
2106001Snate@binkert.org{
2116001Snate@binkert.org    size_type s = size();
2126001Snate@binkert.org    if (subnames.size() < s)
2136001Snate@binkert.org        subnames.resize(s);
2146001Snate@binkert.org    if (subdescs.size() < s)
2156001Snate@binkert.org        subdescs.resize(s);
2166001Snate@binkert.org}
2176001Snate@binkert.org
2186001Snate@binkert.orgvoid
2196128Snate@binkert.orgVectorDistInfo::enable()
2206001Snate@binkert.org{
2216001Snate@binkert.org    size_type s = size();
2226001Snate@binkert.org    if (subnames.size() < s)
2236001Snate@binkert.org        subnames.resize(s);
2246001Snate@binkert.org    if (subdescs.size() < s)
2256001Snate@binkert.org        subdescs.resize(s);
2266001Snate@binkert.org}
2276001Snate@binkert.org
2286001Snate@binkert.orgvoid
2296128Snate@binkert.orgVector2dInfo::enable()
2306001Snate@binkert.org{
2316001Snate@binkert.org    if (subnames.size() < x)
2326001Snate@binkert.org        subnames.resize(x);
2336001Snate@binkert.org    if (subdescs.size() < x)
2346001Snate@binkert.org        subdescs.resize(x);
2356001Snate@binkert.org    if (y_subnames.size() < y)
2366001Snate@binkert.org        y_subnames.resize(y);
2376001Snate@binkert.org}
238695SN/A
239388SN/AFormula::Formula()
240388SN/A{
241388SN/A}
242388SN/A
243388SN/AFormula::Formula(Temp r)
244388SN/A{
245388SN/A    root = r;
2467461Snate@binkert.org    setInit();
247388SN/A    assert(size());
248388SN/A}
249388SN/A
250388SN/Aconst Formula &
251388SN/AFormula::operator=(Temp r)
252388SN/A{
253388SN/A    assert(!root && "Can't change formulas");
254388SN/A    root = r;
2557461Snate@binkert.org    setInit();
256388SN/A    assert(size());
257388SN/A    return *this;
258388SN/A}
259388SN/A
260388SN/Aconst Formula &
261388SN/AFormula::operator+=(Temp r)
262388SN/A{
263388SN/A    if (root)
264695SN/A        root = NodePtr(new BinaryNode<std::plus<Result> >(root, r));
2657461Snate@binkert.org    else {
266388SN/A        root = r;
2677461Snate@binkert.org        setInit();
2687461Snate@binkert.org    }
2697461Snate@binkert.org
270388SN/A    assert(size());
271388SN/A    return *this;
272388SN/A}
273388SN/A
274142SN/Avoid
2756000Snate@binkert.orgFormula::result(VResult &vec) const
2766000Snate@binkert.org{
2776000Snate@binkert.org    if (root)
2786000Snate@binkert.org        vec = root->result();
2796000Snate@binkert.org}
2806000Snate@binkert.org
2816000Snate@binkert.orgResult
2826000Snate@binkert.orgFormula::total() const
2836000Snate@binkert.org{
2846000Snate@binkert.org    return root ? root->total() : 0.0;
2856000Snate@binkert.org}
2866000Snate@binkert.org
2876000Snate@binkert.orgsize_type
2886000Snate@binkert.orgFormula::size() const
2896000Snate@binkert.org{
2906000Snate@binkert.org    if (!root)
2916000Snate@binkert.org        return 0;
2926000Snate@binkert.org    else
2936000Snate@binkert.org        return root->size();
2946000Snate@binkert.org}
2956000Snate@binkert.org
2966000Snate@binkert.orgvoid
2976000Snate@binkert.orgFormula::reset()
2986000Snate@binkert.org{
2996000Snate@binkert.org}
3006000Snate@binkert.org
3016000Snate@binkert.orgbool
3026000Snate@binkert.orgFormula::zero() const
3036000Snate@binkert.org{
3046000Snate@binkert.org    VResult vec;
3056000Snate@binkert.org    result(vec);
3066227Snate@binkert.org    for (VResult::size_type i = 0; i < vec.size(); ++i)
3076000Snate@binkert.org        if (vec[i] != 0.0)
3086000Snate@binkert.org            return false;
3096000Snate@binkert.org    return true;
3106000Snate@binkert.org}
3116000Snate@binkert.org
3126000Snate@binkert.orgstring
3136000Snate@binkert.orgFormula::str() const
3146000Snate@binkert.org{
3156000Snate@binkert.org    return root ? root->str() : "";
3166000Snate@binkert.org}
3176000Snate@binkert.org
3186000Snate@binkert.orgvoid
3196001Snate@binkert.orgenable()
3202SN/A{
3215887Snate@binkert.org    typedef list<Info *>::iterator iter_t;
322695SN/A
3235887Snate@binkert.org    iter_t i, end = statsList().end();
3245887Snate@binkert.org    for (i = statsList().begin(); i != end; ++i) {
3255886Snate@binkert.org        Info *info = *i;
3265886Snate@binkert.org        assert(info);
3275886Snate@binkert.org        if (!info->check() || !info->baseCheck())
3285889Snate@binkert.org            panic("stat check failed for '%s' %d\n", info->name, info->id);
329695SN/A    }
330695SN/A
3315599Snate@binkert.org    off_t j = 0;
3325887Snate@binkert.org    for (i = statsList().begin(); i != end; ++i) {
3335886Snate@binkert.org        Info *info = *i;
3347462Snate@binkert.org        if (!(info->flags & display))
3355886Snate@binkert.org            info->name = "__Stat" + to_string(j++);
336695SN/A    }
337695SN/A
3385887Snate@binkert.org    statsList().sort(Info::less);
339695SN/A
3406001Snate@binkert.org    for (i = statsList().begin(); i != end; ++i) {
3416001Snate@binkert.org        Info *info = *i;
3426001Snate@binkert.org        info->enable();
3436001Snate@binkert.org    }
3446001Snate@binkert.org}
345695SN/A
3466001Snate@binkert.orgvoid
3476001Snate@binkert.orgprepare()
3486001Snate@binkert.org{
3496001Snate@binkert.org    list<Info *>::iterator i = statsList().begin();
3506001Snate@binkert.org    list<Info *>::iterator end = statsList().end();
3516001Snate@binkert.org    while (i != end) {
3526001Snate@binkert.org        Info *info = *i;
3536001Snate@binkert.org        info->prepare();
3546001Snate@binkert.org        ++i;
355695SN/A    }
3562SN/A}
3572SN/A
358695SN/ACallbackQueue resetQueue;
3592SN/A
360456SN/Avoid
361695SN/Areset()
362456SN/A{
3635887Snate@binkert.org    list<Info *>::iterator i = statsList().begin();
3645887Snate@binkert.org    list<Info *>::iterator end = statsList().end();
365695SN/A    while (i != end) {
3665886Snate@binkert.org        Info *info = *i;
3675886Snate@binkert.org        info->reset();
368695SN/A        ++i;
369695SN/A    }
370695SN/A
371695SN/A    resetQueue.process();
372456SN/A}
373456SN/A
374456SN/Avoid
375394SN/AregisterResetCallback(Callback *cb)
376148SN/A{
377148SN/A    resetQueue.add(cb);
378148SN/A}
379148SN/A
3807811Ssteve.reinhardt@amd.com} // namespace Stats
381