statistics.cc revision 2665
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"
39441SN/A#include "base/hostinfo.hh"
4056SN/A#include "base/misc.hh"
4156SN/A#include "base/statistics.hh"
4256SN/A#include "base/str.hh"
43441SN/A#include "base/time.hh"
44433SN/A#include "base/trace.hh"
45695SN/A#include "base/stats/statdb.hh"
461858SN/A#include "config/stats_binning.hh"
472SN/A
482SN/Ausing namespace std;
492SN/A
50729SN/Anamespace Stats {
51388SN/A
52388SN/AStatData *
53388SN/ADataAccess::find() const
54388SN/A{
55695SN/A    return Database::find(const_cast<void *>((const void *)this));
56388SN/A}
57388SN/A
58441SN/Aconst StatData *
59441SN/AgetStatData(const void *stat)
60441SN/A{
61695SN/A    return Database::find(const_cast<void *>(stat));
62441SN/A}
63441SN/A
64388SN/Avoid
65388SN/ADataAccess::map(StatData *data)
66388SN/A{
67695SN/A    Database::regStat(this, data);
68388SN/A}
69388SN/A
70388SN/AStatData *
71388SN/ADataAccess::statData()
72388SN/A{
73388SN/A    StatData *ptr = find();
74388SN/A    assert(ptr);
75388SN/A    return ptr;
76388SN/A}
77388SN/A
78388SN/Aconst StatData *
79388SN/ADataAccess::statData() const
80388SN/A{
81388SN/A    const StatData *ptr = find();
82388SN/A    assert(ptr);
83388SN/A    return ptr;
84388SN/A}
85388SN/A
86388SN/Avoid
87388SN/ADataAccess::setInit()
88388SN/A{
89434SN/A    statData()->flags |= init;
90388SN/A}
91388SN/A
92388SN/Avoid
93388SN/ADataAccess::setPrint()
94388SN/A{
95695SN/A    Database::regPrint(this);
96388SN/A}
97388SN/A
98582SN/AStatData::StatData()
99582SN/A    : flags(none), precision(-1), prereq(0)
100582SN/A{
101695SN/A    static int count = 0;
102695SN/A    id = count++;
103582SN/A}
104582SN/A
105388SN/AStatData::~StatData()
106388SN/A{
107388SN/A}
108388SN/A
1092SN/Abool
110388SN/AStatData::less(StatData *stat1, StatData *stat2)
1112SN/A{
112388SN/A    const string &name1 = stat1->name;
113388SN/A    const string &name2 = stat2->name;
1142SN/A
1152SN/A    vector<string> v1;
1162SN/A    vector<string> v2;
1172SN/A
1182SN/A    tokenize(v1, name1, '.');
1192SN/A    tokenize(v2, name2, '.');
1202SN/A
1212SN/A    int last = min(v1.size(), v2.size()) - 1;
1222SN/A    for (int i = 0; i < last; ++i)
1232SN/A        if (v1[i] != v2[i])
1242SN/A            return v1[i] < v2[i];
1252SN/A
1262SN/A    // Special compare for last element.
1272SN/A    if (v1[last] == v2[last])
1282SN/A        return v1.size() < v2.size();
1292SN/A    else
1302SN/A        return v1[last] < v2[last];
1312SN/A
1322SN/A    return false;
1332SN/A}
1342SN/A
135388SN/Abool
136414SN/AStatData::baseCheck() const
1372SN/A{
138434SN/A    if (!(flags & init)) {
139582SN/A#ifdef DEBUG
140695SN/A        cprintf("this is stat number %d\n", id);
141388SN/A#endif
142388SN/A        panic("Not all stats have been initialized");
143388SN/A        return false;
144388SN/A    }
1452SN/A
146434SN/A    if ((flags & print) && name.empty()) {
147388SN/A        panic("all printable stats must be named");
148388SN/A        return false;
149388SN/A    }
1502SN/A
151388SN/A    return true;
1522SN/A}
1532SN/A
154695SN/A
155695SN/Avoid
156695SN/AFormulaBase::result(VResult &vec) const
1572SN/A{
158695SN/A    if (root)
159695SN/A        vec = root->result();
1602SN/A}
1612SN/A
162695SN/AResult
163388SN/AFormulaBase::total() const
164388SN/A{
165456SN/A    return root ? root->total() : 0.0;
166388SN/A}
167388SN/A
168388SN/Asize_t
169388SN/AFormulaBase::size() const
170388SN/A{
171388SN/A    if (!root)
172388SN/A        return 0;
173388SN/A    else
174388SN/A        return root->size();
175388SN/A}
176388SN/A
177388SN/Abool
178388SN/AFormulaBase::binned() const
179388SN/A{
180436SN/A    return root && root->binned();
181388SN/A}
182388SN/A
183388SN/Avoid
184388SN/AFormulaBase::reset()
185388SN/A{
186388SN/A}
187388SN/A
188388SN/Abool
189388SN/AFormulaBase::zero() const
190388SN/A{
191695SN/A    VResult vec;
192695SN/A    result(vec);
193388SN/A    for (int i = 0; i < vec.size(); ++i)
194388SN/A        if (vec[i] != 0.0)
195388SN/A            return false;
196388SN/A    return true;
197388SN/A}
198388SN/A
199388SN/Avoid
200388SN/AFormulaBase::update(StatData *)
201388SN/A{
202388SN/A}
203388SN/A
204441SN/Astring
205441SN/AFormulaBase::str() const
206441SN/A{
207441SN/A    return root ? root->str() : "";
208441SN/A}
209441SN/A
210388SN/AFormula::Formula()
211388SN/A{
212388SN/A    setInit();
213388SN/A}
214388SN/A
215388SN/AFormula::Formula(Temp r)
216388SN/A{
217388SN/A    root = r;
218388SN/A    assert(size());
219388SN/A}
220388SN/A
221388SN/Aconst Formula &
222388SN/AFormula::operator=(Temp r)
223388SN/A{
224388SN/A    assert(!root && "Can't change formulas");
225388SN/A    root = r;
226388SN/A    assert(size());
227388SN/A    return *this;
228388SN/A}
229388SN/A
230388SN/Aconst Formula &
231388SN/AFormula::operator+=(Temp r)
232388SN/A{
233388SN/A    if (root)
234695SN/A        root = NodePtr(new BinaryNode<std::plus<Result> >(root, r));
235388SN/A    else
236388SN/A        root = r;
237388SN/A    assert(size());
238388SN/A    return *this;
239388SN/A}
240388SN/A
241388SN/AMainBin::MainBin(const string &name)
242365SN/A    : _name(name), mem(NULL), memsize(-1)
2432SN/A{
244695SN/A    Database::regBin(this, name);
2452SN/A}
2462SN/A
247365SN/AMainBin::~MainBin()
2482SN/A{
2492SN/A    if (mem)
2502SN/A        delete [] mem;
2512SN/A}
2522SN/A
2532SN/Achar *
254365SN/AMainBin::memory(off_t off)
2552SN/A{
256388SN/A    if (memsize == -1)
2572020SN/A        memsize = ceilPow2((size_t) offset());
258388SN/A
2592SN/A    if (!mem) {
2602SN/A        mem = new char[memsize];
2612SN/A        memset(mem, 0, memsize);
2622SN/A    }
2632SN/A
264365SN/A    assert(offset() <= size());
265365SN/A    return mem + off;
2662SN/A}
2672SN/A
268142SN/Avoid
2692SN/Acheck()
2702SN/A{
271695SN/A    typedef Database::stat_list_t::iterator iter_t;
272695SN/A
273695SN/A    iter_t i, end = Database::stats().end();
274695SN/A    for (i = Database::stats().begin(); i != end; ++i) {
275695SN/A        StatData *data = *i;
276695SN/A        assert(data);
2771014SN/A        if (!data->check() || !data->baseCheck())
2781014SN/A            panic("stat check failed for %s\n", data->name);
279695SN/A    }
280695SN/A
281695SN/A    int j = 0;
282695SN/A    for (i = Database::stats().begin(); i != end; ++i) {
283695SN/A        StatData *data = *i;
284695SN/A        if (!(data->flags & print))
285695SN/A            data->name = "__Stat" + to_string(j++);
286695SN/A    }
287695SN/A
288695SN/A    Database::stats().sort(StatData::less);
289695SN/A
2901858SN/A#if STATS_BINNING
2911395SN/A    if (MainBin::curBin() == NULL) {
2921395SN/A        static MainBin mainBin("main bin");
2931395SN/A        mainBin.activate();
2941395SN/A    }
2951395SN/A#endif
2961395SN/A
297695SN/A    if (i == end)
298695SN/A        return;
299695SN/A
300695SN/A    iter_t last = i;
301695SN/A    ++i;
302695SN/A
303695SN/A    for (i = Database::stats().begin(); i != end; ++i) {
304695SN/A        if ((*i)->name == (*last)->name)
305695SN/A            panic("same name used twice! name=%s\n", (*i)->name);
306695SN/A
307695SN/A        last = i;
308695SN/A    }
3092SN/A}
3102SN/A
311695SN/ACallbackQueue resetQueue;
3122SN/A
313456SN/Avoid
314695SN/Areset()
315456SN/A{
316695SN/A    // reset non-binned stats
317695SN/A    Database::stat_list_t::iterator i = Database::stats().begin();
318695SN/A    Database::stat_list_t::iterator end = Database::stats().end();
319695SN/A    while (i != end) {
320695SN/A        StatData *data = *i;
321695SN/A        if (!data->binned())
322695SN/A            data->reset();
323695SN/A        ++i;
324695SN/A    }
325695SN/A
326695SN/A    // save the bin so we can go back to where we were
327695SN/A    MainBin *orig = MainBin::curBin();
328695SN/A
329695SN/A    // reset binned stats
330695SN/A    Database::bin_list_t::iterator bi = Database::bins().begin();
331695SN/A    Database::bin_list_t::iterator be = Database::bins().end();
332695SN/A    while (bi != be) {
333695SN/A        MainBin *bin = *bi;
334695SN/A        bin->activate();
335695SN/A
336695SN/A        i = Database::stats().begin();
337695SN/A        while (i != end) {
338695SN/A            StatData *data = *i;
339695SN/A            if (data->binned())
340695SN/A                data->reset();
341695SN/A            ++i;
342695SN/A        }
343695SN/A        ++bi;
344695SN/A    }
345695SN/A
346695SN/A    // restore bin
347695SN/A    MainBin::curBin() = orig;
348695SN/A
349695SN/A    resetQueue.process();
350456SN/A}
351456SN/A
352456SN/Avoid
353394SN/AregisterResetCallback(Callback *cb)
354148SN/A{
355148SN/A    resetQueue.add(cb);
356148SN/A}
357148SN/A
358729SN/A/* namespace Stats */ }
359