statistics.cc revision 5887
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"
452SN/A
462SN/Ausing namespace std;
472SN/A
48729SN/Anamespace Stats {
49388SN/A
505887Snate@binkert.orgtypedef map<const void *, Info *> MapType;
515887Snate@binkert.org
525887Snate@binkert.org// We wrap these in a function to make sure they're built in time.
535887Snate@binkert.orglist<Info *> &
545887Snate@binkert.orgstatsList()
55388SN/A{
565887Snate@binkert.org    static list<Info *> the_list;
575887Snate@binkert.org    return the_list;
58388SN/A}
59388SN/A
605887Snate@binkert.orgMapType &
615887Snate@binkert.orgstatsMap()
62441SN/A{
635887Snate@binkert.org    static MapType the_map;
645887Snate@binkert.org    return the_map;
65441SN/A}
66441SN/A
67388SN/Avoid
685886Snate@binkert.orgInfoAccess::setInfo(Info *info)
69388SN/A{
705887Snate@binkert.org    if (statsMap().find(this) != statsMap().end())
715887Snate@binkert.org        panic("shouldn't register stat twice!");
725887Snate@binkert.org
735887Snate@binkert.org    statsList().push_back(info);
745887Snate@binkert.org
755887Snate@binkert.org#ifndef NDEBUG
765887Snate@binkert.org    pair<MapType::iterator, bool> result =
775887Snate@binkert.org#endif
785887Snate@binkert.org        statsMap().insert(make_pair(this, info));
795887Snate@binkert.org    assert(result.second && "this should never fail");
805887Snate@binkert.org    assert(statsMap().find(this) != statsMap().end());
81388SN/A}
82388SN/A
83388SN/Avoid
845886Snate@binkert.orgInfoAccess::setInit()
85388SN/A{
865886Snate@binkert.org    info()->flags |= init;
87388SN/A}
88388SN/A
895886Snate@binkert.orgInfo *
905886Snate@binkert.orgInfoAccess::info()
91388SN/A{
925887Snate@binkert.org    MapType::const_iterator i = statsMap().find(this);
935887Snate@binkert.org    assert(i != statsMap().end());
945887Snate@binkert.org    return (*i).second;
95388SN/A}
96388SN/A
975886Snate@binkert.orgconst Info *
985886Snate@binkert.orgInfoAccess::info() const
995886Snate@binkert.org{
1005887Snate@binkert.org    MapType::const_iterator i = statsMap().find(this);
1015887Snate@binkert.org    assert(i != statsMap().end());
1025887Snate@binkert.org    return (*i).second;
1035886Snate@binkert.org}
1045886Snate@binkert.org
1055886Snate@binkert.orgInfo::Info()
106582SN/A    : flags(none), precision(-1), prereq(0)
107582SN/A{
108695SN/A    static int count = 0;
109695SN/A    id = count++;
110582SN/A}
111582SN/A
1125886Snate@binkert.orgInfo::~Info()
113388SN/A{
114388SN/A}
115388SN/A
1162SN/Abool
1175886Snate@binkert.orgInfo::less(Info *stat1, Info *stat2)
1182SN/A{
119388SN/A    const string &name1 = stat1->name;
120388SN/A    const string &name2 = stat2->name;
1212SN/A
1222SN/A    vector<string> v1;
1232SN/A    vector<string> v2;
1242SN/A
1252SN/A    tokenize(v1, name1, '.');
1262SN/A    tokenize(v2, name2, '.');
1272SN/A
1285599Snate@binkert.org    size_type last = min(v1.size(), v2.size()) - 1;
1295599Snate@binkert.org    for (off_type i = 0; i < last; ++i)
1302SN/A        if (v1[i] != v2[i])
1312SN/A            return v1[i] < v2[i];
1322SN/A
1332SN/A    // Special compare for last element.
1342SN/A    if (v1[last] == v2[last])
1352SN/A        return v1.size() < v2.size();
1362SN/A    else
1372SN/A        return v1[last] < v2[last];
1382SN/A
1392SN/A    return false;
1402SN/A}
1412SN/A
142388SN/Abool
1435886Snate@binkert.orgInfo::baseCheck() const
1442SN/A{
145434SN/A    if (!(flags & init)) {
146582SN/A#ifdef DEBUG
147695SN/A        cprintf("this is stat number %d\n", id);
148388SN/A#endif
149388SN/A        panic("Not all stats have been initialized");
150388SN/A        return false;
151388SN/A    }
1522SN/A
153434SN/A    if ((flags & print) && name.empty()) {
154388SN/A        panic("all printable stats must be named");
155388SN/A        return false;
156388SN/A    }
1572SN/A
158388SN/A    return true;
1592SN/A}
1602SN/A
161695SN/A
162695SN/Avoid
163695SN/AFormulaBase::result(VResult &vec) const
1642SN/A{
165695SN/A    if (root)
166695SN/A        vec = root->result();
1672SN/A}
1682SN/A
169695SN/AResult
170388SN/AFormulaBase::total() const
171388SN/A{
172456SN/A    return root ? root->total() : 0.0;
173388SN/A}
174388SN/A
1755599Snate@binkert.orgsize_type
176388SN/AFormulaBase::size() const
177388SN/A{
178388SN/A    if (!root)
179388SN/A        return 0;
180388SN/A    else
181388SN/A        return root->size();
182388SN/A}
183388SN/A
184388SN/Avoid
185388SN/AFormulaBase::reset()
186388SN/A{
187388SN/A}
188388SN/A
189388SN/Abool
190388SN/AFormulaBase::zero() const
191388SN/A{
192695SN/A    VResult vec;
193695SN/A    result(vec);
1945599Snate@binkert.org    for (off_t i = 0; i < vec.size(); ++i)
195388SN/A        if (vec[i] != 0.0)
196388SN/A            return false;
197388SN/A    return true;
198388SN/A}
199388SN/A
200388SN/Avoid
2015886Snate@binkert.orgFormulaBase::update(Info *)
202388SN/A{
203388SN/A}
204388SN/A
205441SN/Astring
206441SN/AFormulaBase::str() const
207441SN/A{
208441SN/A    return root ? root->str() : "";
209441SN/A}
210441SN/A
211388SN/AFormula::Formula()
212388SN/A{
213388SN/A    setInit();
214388SN/A}
215388SN/A
216388SN/AFormula::Formula(Temp r)
217388SN/A{
218388SN/A    root = r;
219388SN/A    assert(size());
220388SN/A}
221388SN/A
222388SN/Aconst Formula &
223388SN/AFormula::operator=(Temp r)
224388SN/A{
225388SN/A    assert(!root && "Can't change formulas");
226388SN/A    root = r;
227388SN/A    assert(size());
228388SN/A    return *this;
229388SN/A}
230388SN/A
231388SN/Aconst Formula &
232388SN/AFormula::operator+=(Temp r)
233388SN/A{
234388SN/A    if (root)
235695SN/A        root = NodePtr(new BinaryNode<std::plus<Result> >(root, r));
236388SN/A    else
237388SN/A        root = r;
238388SN/A    assert(size());
239388SN/A    return *this;
240388SN/A}
241388SN/A
242142SN/Avoid
2432SN/Acheck()
2442SN/A{
2455887Snate@binkert.org    typedef list<Info *>::iterator iter_t;
246695SN/A
2475887Snate@binkert.org    iter_t i, end = statsList().end();
2485887Snate@binkert.org    for (i = statsList().begin(); i != end; ++i) {
2495886Snate@binkert.org        Info *info = *i;
2505886Snate@binkert.org        assert(info);
2515886Snate@binkert.org        if (!info->check() || !info->baseCheck())
2525886Snate@binkert.org            panic("stat check failed for %s\n", info->name);
253695SN/A    }
254695SN/A
2555599Snate@binkert.org    off_t j = 0;
2565887Snate@binkert.org    for (i = statsList().begin(); i != end; ++i) {
2575886Snate@binkert.org        Info *info = *i;
2585886Snate@binkert.org        if (!(info->flags & print))
2595886Snate@binkert.org            info->name = "__Stat" + to_string(j++);
260695SN/A    }
261695SN/A
2625887Snate@binkert.org    statsList().sort(Info::less);
263695SN/A
264695SN/A    if (i == end)
265695SN/A        return;
266695SN/A
267695SN/A    iter_t last = i;
268695SN/A    ++i;
269695SN/A
2705887Snate@binkert.org    for (i = statsList().begin(); i != end; ++i) {
271695SN/A        if ((*i)->name == (*last)->name)
272695SN/A            panic("same name used twice! name=%s\n", (*i)->name);
273695SN/A
274695SN/A        last = i;
275695SN/A    }
2762SN/A}
2772SN/A
278695SN/ACallbackQueue resetQueue;
2792SN/A
280456SN/Avoid
281695SN/Areset()
282456SN/A{
2835887Snate@binkert.org    list<Info *>::iterator i = statsList().begin();
2845887Snate@binkert.org    list<Info *>::iterator end = statsList().end();
285695SN/A    while (i != end) {
2865886Snate@binkert.org        Info *info = *i;
2875886Snate@binkert.org        info->reset();
288695SN/A        ++i;
289695SN/A    }
290695SN/A
291695SN/A    resetQueue.process();
292456SN/A}
293456SN/A
294456SN/Avoid
295394SN/AregisterResetCallback(Callback *cb)
296148SN/A{
297148SN/A    resetQueue.add(cb);
298148SN/A}
299148SN/A
300729SN/A/* namespace Stats */ }
301