statistics.cc revision 7462:0c61c3cf7639
113511Sgabeblack@google.com/*
213511Sgabeblack@google.com * Copyright (c) 2003-2005 The Regents of The University of Michigan
313511Sgabeblack@google.com * All rights reserved.
413511Sgabeblack@google.com *
513511Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
613511Sgabeblack@google.com * modification, are permitted provided that the following conditions are
713511Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
813511Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
913511Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
1013511Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
1113511Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
1213511Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
1313511Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
1413511Sgabeblack@google.com * this software without specific prior written permission.
1513511Sgabeblack@google.com *
1613511Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1713511Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1813511Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1913511Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2013513Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2113513Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2213511Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2313513Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2413511Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2513586Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2613586Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2713586Sgabeblack@google.com *
2813586Sgabeblack@google.com * Authors: Nathan Binkert
2913586Sgabeblack@google.com */
3013586Sgabeblack@google.com
3113513Sgabeblack@google.com#include <iomanip>
3213513Sgabeblack@google.com#include <fstream>
3313511Sgabeblack@google.com#include <list>
3413511Sgabeblack@google.com#include <map>
3513511Sgabeblack@google.com#include <string>
3613511Sgabeblack@google.com
3713513Sgabeblack@google.com#include "base/callback.hh"
3813513Sgabeblack@google.com#include "base/cprintf.hh"
3913513Sgabeblack@google.com#include "base/debug.hh"
4013513Sgabeblack@google.com#include "base/hostinfo.hh"
4113513Sgabeblack@google.com#include "base/misc.hh"
4213513Sgabeblack@google.com#include "base/statistics.hh"
4313513Sgabeblack@google.com#include "base/str.hh"
4413513Sgabeblack@google.com#include "base/time.hh"
4513513Sgabeblack@google.com#include "base/trace.hh"
4613513Sgabeblack@google.com
4713513Sgabeblack@google.comusing namespace std;
4813513Sgabeblack@google.com
4913511Sgabeblack@google.comnamespace Stats {
5013513Sgabeblack@google.com
5113513Sgabeblack@google.comtypedef map<const void *, Info *> MapType;
5213513Sgabeblack@google.com
5313513Sgabeblack@google.com// We wrap these in a function to make sure they're built in time.
5413511Sgabeblack@google.comlist<Info *> &
5513513Sgabeblack@google.comstatsList()
5613513Sgabeblack@google.com{
5713513Sgabeblack@google.com    static list<Info *> the_list;
5813511Sgabeblack@google.com    return the_list;
5913513Sgabeblack@google.com}
6013513Sgabeblack@google.com
6113513Sgabeblack@google.comMapType &
6213513Sgabeblack@google.comstatsMap()
6313513Sgabeblack@google.com{
6413513Sgabeblack@google.com    static MapType the_map;
6513513Sgabeblack@google.com    return the_map;
6613513Sgabeblack@google.com}
6713513Sgabeblack@google.com
6813511Sgabeblack@google.comvoid
6913511Sgabeblack@google.comInfoAccess::setInfo(Info *info)
7013513Sgabeblack@google.com{
7113513Sgabeblack@google.com    if (statsMap().find(this) != statsMap().end())
7213513Sgabeblack@google.com        panic("shouldn't register stat twice!");
7313513Sgabeblack@google.com
7413513Sgabeblack@google.com    statsList().push_back(info);
7513513Sgabeblack@google.com
7613513Sgabeblack@google.com#ifndef NDEBUG
7713511Sgabeblack@google.com    pair<MapType::iterator, bool> result =
7813513Sgabeblack@google.com#endif
7913513Sgabeblack@google.com        statsMap().insert(make_pair(this, info));
8013513Sgabeblack@google.com    assert(result.second && "this should never fail");
8113513Sgabeblack@google.com    assert(statsMap().find(this) != statsMap().end());
8213513Sgabeblack@google.com}
8313513Sgabeblack@google.com
8413513Sgabeblack@google.comvoid
8513513Sgabeblack@google.comInfoAccess::setParams(const StorageParams *params)
8613513Sgabeblack@google.com{
8713513Sgabeblack@google.com    info()->storageParams = params;
8813513Sgabeblack@google.com}
8913513Sgabeblack@google.com
9013513Sgabeblack@google.comvoid
9113513Sgabeblack@google.comInfoAccess::setInit()
9213513Sgabeblack@google.com{
9313513Sgabeblack@google.com    info()->flags.set(init);
9413513Sgabeblack@google.com}
9513513Sgabeblack@google.com
9613513Sgabeblack@google.comInfo *
9713513Sgabeblack@google.comInfoAccess::info()
9813513Sgabeblack@google.com{
9913513Sgabeblack@google.com    MapType::const_iterator i = statsMap().find(this);
10013513Sgabeblack@google.com    assert(i != statsMap().end());
10113513Sgabeblack@google.com    return (*i).second;
10213513Sgabeblack@google.com}
10313513Sgabeblack@google.com
10413513Sgabeblack@google.comconst Info *
10513513Sgabeblack@google.comInfoAccess::info() const
10613511Sgabeblack@google.com{
10713513Sgabeblack@google.com    MapType::const_iterator i = statsMap().find(this);
10813513Sgabeblack@google.com    assert(i != statsMap().end());
10913513Sgabeblack@google.com    return (*i).second;
11013513Sgabeblack@google.com}
11113513Sgabeblack@google.com
11213513Sgabeblack@google.comStorageParams::~StorageParams()
11313513Sgabeblack@google.com{
11413513Sgabeblack@google.com}
11513513Sgabeblack@google.com
11613513Sgabeblack@google.comtypedef map<std::string, Info *> NameMapType;
11713513Sgabeblack@google.comNameMapType &
11813511Sgabeblack@google.comnameMap()
11913511Sgabeblack@google.com{
12013513Sgabeblack@google.com    static NameMapType the_map;
12113513Sgabeblack@google.com    return the_map;
12213513Sgabeblack@google.com}
12313513Sgabeblack@google.com
12413513Sgabeblack@google.comint Info::id_count = 0;
12513511Sgabeblack@google.com
12613511Sgabeblack@google.comint debug_break_id = -1;
12713511Sgabeblack@google.com
12813511Sgabeblack@google.comInfo::Info()
12913511Sgabeblack@google.com    : flags(none), precision(-1), prereq(0), storageParams(NULL)
13013511Sgabeblack@google.com{
13113511Sgabeblack@google.com    id = id_count++;
13213511Sgabeblack@google.com    if (debug_break_id >= 0 and debug_break_id == id)
13313513Sgabeblack@google.com        debug_break();
13413513Sgabeblack@google.com}
13513511Sgabeblack@google.com
13613513Sgabeblack@google.comInfo::~Info()
13713513Sgabeblack@google.com{
13813513Sgabeblack@google.com}
13913513Sgabeblack@google.com
14013511Sgabeblack@google.comvoid
14113513Sgabeblack@google.comInfo::setName(const string &name)
14213513Sgabeblack@google.com{
14313513Sgabeblack@google.com    pair<NameMapType::iterator, bool> p =
14413513Sgabeblack@google.com        nameMap().insert(make_pair(name, this));
14513513Sgabeblack@google.com
14613513Sgabeblack@google.com    Info *other = p.first->second;
14713513Sgabeblack@google.com    bool result = p.second;
14813513Sgabeblack@google.com
14913511Sgabeblack@google.com    if (!result) {
15013513Sgabeblack@google.com        // using other->name instead of just name to avoid a compiler
15113513Sgabeblack@google.com        // warning.  They should be the same.
15213513Sgabeblack@google.com        panic("same statistic name used twice! name=%s\n", other->name);
15313513Sgabeblack@google.com    }
15413513Sgabeblack@google.com
15513513Sgabeblack@google.com    this->name = name;
15613513Sgabeblack@google.com}
15713513Sgabeblack@google.com
15813513Sgabeblack@google.combool
15913513Sgabeblack@google.comInfo::less(Info *stat1, Info *stat2)
16013513Sgabeblack@google.com{
16113513Sgabeblack@google.com    const string &name1 = stat1->name;
16213513Sgabeblack@google.com    const string &name2 = stat2->name;
16313513Sgabeblack@google.com
16413513Sgabeblack@google.com    vector<string> v1;
16513513Sgabeblack@google.com    vector<string> v2;
16613513Sgabeblack@google.com
16713513Sgabeblack@google.com    tokenize(v1, name1, '.');
16813513Sgabeblack@google.com    tokenize(v2, name2, '.');
16913513Sgabeblack@google.com
17013513Sgabeblack@google.com    size_type last = min(v1.size(), v2.size()) - 1;
17113513Sgabeblack@google.com    for (off_type i = 0; i < last; ++i)
17213513Sgabeblack@google.com        if (v1[i] != v2[i])
17313513Sgabeblack@google.com            return v1[i] < v2[i];
17413513Sgabeblack@google.com
17513513Sgabeblack@google.com    // Special compare for last element.
17613511Sgabeblack@google.com    if (v1[last] == v2[last])
17713513Sgabeblack@google.com        return v1.size() < v2.size();
17813513Sgabeblack@google.com    else
17913513Sgabeblack@google.com        return v1[last] < v2[last];
18013513Sgabeblack@google.com
18113513Sgabeblack@google.com    return false;
18213513Sgabeblack@google.com}
18313513Sgabeblack@google.com
18413513Sgabeblack@google.combool
18513513Sgabeblack@google.comInfo::baseCheck() const
18613513Sgabeblack@google.com{
18713513Sgabeblack@google.com    if (!(flags & Stats::init)) {
18813511Sgabeblack@google.com#ifdef DEBUG
18913511Sgabeblack@google.com        cprintf("this is stat number %d\n", id);
19013513Sgabeblack@google.com#endif
19113513Sgabeblack@google.com        panic("Not all stats have been initialized");
19213513Sgabeblack@google.com        return false;
19313513Sgabeblack@google.com    }
19413513Sgabeblack@google.com
19513513Sgabeblack@google.com    if ((flags & display) && name.empty()) {
19613513Sgabeblack@google.com        panic("all printable stats must be named");
19713513Sgabeblack@google.com        return false;
19813513Sgabeblack@google.com    }
19913511Sgabeblack@google.com
20013511Sgabeblack@google.com    return true;
20113513Sgabeblack@google.com}
20213513Sgabeblack@google.com
20313513Sgabeblack@google.comvoid
20413513Sgabeblack@google.comInfo::enable()
20513513Sgabeblack@google.com{
20613513Sgabeblack@google.com}
20713513Sgabeblack@google.com
20813513Sgabeblack@google.comvoid
20913513Sgabeblack@google.comVectorInfo::enable()
21013513Sgabeblack@google.com{
21113513Sgabeblack@google.com    size_type s = size();
21213513Sgabeblack@google.com    if (subnames.size() < s)
21313513Sgabeblack@google.com        subnames.resize(s);
21413513Sgabeblack@google.com    if (subdescs.size() < s)
21513513Sgabeblack@google.com        subdescs.resize(s);
21613513Sgabeblack@google.com}
21713513Sgabeblack@google.com
21813513Sgabeblack@google.comvoid
21913513Sgabeblack@google.comVectorDistInfo::enable()
22013513Sgabeblack@google.com{
22113511Sgabeblack@google.com    size_type s = size();
22213511Sgabeblack@google.com    if (subnames.size() < s)
22313513Sgabeblack@google.com        subnames.resize(s);
22413513Sgabeblack@google.com    if (subdescs.size() < s)
22513513Sgabeblack@google.com        subdescs.resize(s);
22613513Sgabeblack@google.com}
22713513Sgabeblack@google.com
22813511Sgabeblack@google.comvoid
22913511Sgabeblack@google.comVector2dInfo::enable()
23013513Sgabeblack@google.com{
23113513Sgabeblack@google.com    if (subnames.size() < x)
23213513Sgabeblack@google.com        subnames.resize(x);
23313513Sgabeblack@google.com    if (subdescs.size() < x)
23413513Sgabeblack@google.com        subdescs.resize(x);
23513513Sgabeblack@google.com    if (y_subnames.size() < y)
23613513Sgabeblack@google.com        y_subnames.resize(y);
23713513Sgabeblack@google.com}
23813513Sgabeblack@google.com
23913511Sgabeblack@google.comFormula::Formula()
24013511Sgabeblack@google.com{
24113513Sgabeblack@google.com}
24213513Sgabeblack@google.com
24313513Sgabeblack@google.comFormula::Formula(Temp r)
24413513Sgabeblack@google.com{
24513513Sgabeblack@google.com    root = r;
24613513Sgabeblack@google.com    setInit();
24713513Sgabeblack@google.com    assert(size());
24813513Sgabeblack@google.com}
24913513Sgabeblack@google.com
25013513Sgabeblack@google.comconst Formula &
25113511Sgabeblack@google.comFormula::operator=(Temp r)
25213513Sgabeblack@google.com{
25313513Sgabeblack@google.com    assert(!root && "Can't change formulas");
25413513Sgabeblack@google.com    root = r;
25513513Sgabeblack@google.com    setInit();
25613513Sgabeblack@google.com    assert(size());
25713513Sgabeblack@google.com    return *this;
25813513Sgabeblack@google.com}
25913513Sgabeblack@google.com
26013513Sgabeblack@google.comconst Formula &
26113513Sgabeblack@google.comFormula::operator+=(Temp r)
26213513Sgabeblack@google.com{
26313513Sgabeblack@google.com    if (root)
26413513Sgabeblack@google.com        root = NodePtr(new BinaryNode<std::plus<Result> >(root, r));
26513513Sgabeblack@google.com    else {
26613513Sgabeblack@google.com        root = r;
26713513Sgabeblack@google.com        setInit();
26813513Sgabeblack@google.com    }
26913513Sgabeblack@google.com
27013513Sgabeblack@google.com    assert(size());
27113513Sgabeblack@google.com    return *this;
27213513Sgabeblack@google.com}
27313511Sgabeblack@google.com
27413513Sgabeblack@google.comvoid
27513513Sgabeblack@google.comFormula::result(VResult &vec) const
27613513Sgabeblack@google.com{
27713511Sgabeblack@google.com    if (root)
27813513Sgabeblack@google.com        vec = root->result();
27913513Sgabeblack@google.com}
28013513Sgabeblack@google.com
28113513Sgabeblack@google.comResult
28213513Sgabeblack@google.comFormula::total() const
28313513Sgabeblack@google.com{
28413513Sgabeblack@google.com    return root ? root->total() : 0.0;
28513513Sgabeblack@google.com}
28613513Sgabeblack@google.com
28713513Sgabeblack@google.comsize_type
28813513Sgabeblack@google.comFormula::size() const
28913513Sgabeblack@google.com{
29013513Sgabeblack@google.com    if (!root)
29113513Sgabeblack@google.com        return 0;
29213513Sgabeblack@google.com    else
29313513Sgabeblack@google.com        return root->size();
29413513Sgabeblack@google.com}
29513513Sgabeblack@google.com
29613513Sgabeblack@google.comvoid
29713513Sgabeblack@google.comFormula::reset()
29813513Sgabeblack@google.com{
29913511Sgabeblack@google.com}
30013511Sgabeblack@google.com
30113513Sgabeblack@google.combool
30213511Sgabeblack@google.comFormula::zero() const
30313513Sgabeblack@google.com{
304    VResult vec;
305    result(vec);
306    for (VResult::size_type i = 0; i < vec.size(); ++i)
307        if (vec[i] != 0.0)
308            return false;
309    return true;
310}
311
312string
313Formula::str() const
314{
315    return root ? root->str() : "";
316}
317
318void
319enable()
320{
321    typedef list<Info *>::iterator iter_t;
322
323    iter_t i, end = statsList().end();
324    for (i = statsList().begin(); i != end; ++i) {
325        Info *info = *i;
326        assert(info);
327        if (!info->check() || !info->baseCheck())
328            panic("stat check failed for '%s' %d\n", info->name, info->id);
329    }
330
331    off_t j = 0;
332    for (i = statsList().begin(); i != end; ++i) {
333        Info *info = *i;
334        if (!(info->flags & display))
335            info->name = "__Stat" + to_string(j++);
336    }
337
338    statsList().sort(Info::less);
339
340    for (i = statsList().begin(); i != end; ++i) {
341        Info *info = *i;
342        info->enable();
343    }
344}
345
346void
347prepare()
348{
349    list<Info *>::iterator i = statsList().begin();
350    list<Info *>::iterator end = statsList().end();
351    while (i != end) {
352        Info *info = *i;
353        info->prepare();
354        ++i;
355    }
356}
357
358CallbackQueue resetQueue;
359
360void
361reset()
362{
363    list<Info *>::iterator i = statsList().begin();
364    list<Info *>::iterator end = statsList().end();
365    while (i != end) {
366        Info *info = *i;
367        info->reset();
368        ++i;
369    }
370
371    resetQueue.process();
372}
373
374void
375registerResetCallback(Callback *cb)
376{
377    resetQueue.add(cb);
378}
379
380/* namespace Stats */ }
381