statistics.cc revision 5886:12431dc9a30a
1/*
2 * Copyright (c) 2003-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Nathan Binkert
29 */
30
31#include <iomanip>
32#include <fstream>
33#include <list>
34#include <map>
35#include <string>
36
37#include "base/callback.hh"
38#include "base/cprintf.hh"
39#include "base/hostinfo.hh"
40#include "base/misc.hh"
41#include "base/statistics.hh"
42#include "base/str.hh"
43#include "base/time.hh"
44#include "base/trace.hh"
45#include "base/stats/statdb.hh"
46
47using namespace std;
48
49namespace Stats {
50
51Info *
52InfoAccess::find() const
53{
54    return Database::find(const_cast<void *>((const void *)this));
55}
56
57const Info *
58getInfo(const void *stat)
59{
60    return Database::find(const_cast<void *>(stat));
61}
62
63void
64InfoAccess::setInfo(Info *info)
65{
66    Database::regStat(this, info);
67}
68
69void
70InfoAccess::setInit()
71{
72    info()->flags |= init;
73}
74
75Info *
76InfoAccess::info()
77{
78    Info *info = find();
79    assert(info);
80    return info;
81}
82
83const Info *
84InfoAccess::info() const
85{
86    const Info *info = find();
87    assert(info);
88    return info;
89}
90
91Info::Info()
92    : flags(none), precision(-1), prereq(0)
93{
94    static int count = 0;
95    id = count++;
96}
97
98Info::~Info()
99{
100}
101
102bool
103Info::less(Info *stat1, Info *stat2)
104{
105    const string &name1 = stat1->name;
106    const string &name2 = stat2->name;
107
108    vector<string> v1;
109    vector<string> v2;
110
111    tokenize(v1, name1, '.');
112    tokenize(v2, name2, '.');
113
114    size_type last = min(v1.size(), v2.size()) - 1;
115    for (off_type i = 0; i < last; ++i)
116        if (v1[i] != v2[i])
117            return v1[i] < v2[i];
118
119    // Special compare for last element.
120    if (v1[last] == v2[last])
121        return v1.size() < v2.size();
122    else
123        return v1[last] < v2[last];
124
125    return false;
126}
127
128bool
129Info::baseCheck() const
130{
131    if (!(flags & init)) {
132#ifdef DEBUG
133        cprintf("this is stat number %d\n", id);
134#endif
135        panic("Not all stats have been initialized");
136        return false;
137    }
138
139    if ((flags & print) && name.empty()) {
140        panic("all printable stats must be named");
141        return false;
142    }
143
144    return true;
145}
146
147
148void
149FormulaBase::result(VResult &vec) const
150{
151    if (root)
152        vec = root->result();
153}
154
155Result
156FormulaBase::total() const
157{
158    return root ? root->total() : 0.0;
159}
160
161size_type
162FormulaBase::size() const
163{
164    if (!root)
165        return 0;
166    else
167        return root->size();
168}
169
170void
171FormulaBase::reset()
172{
173}
174
175bool
176FormulaBase::zero() const
177{
178    VResult vec;
179    result(vec);
180    for (off_t i = 0; i < vec.size(); ++i)
181        if (vec[i] != 0.0)
182            return false;
183    return true;
184}
185
186void
187FormulaBase::update(Info *)
188{
189}
190
191string
192FormulaBase::str() const
193{
194    return root ? root->str() : "";
195}
196
197Formula::Formula()
198{
199    setInit();
200}
201
202Formula::Formula(Temp r)
203{
204    root = r;
205    assert(size());
206}
207
208const Formula &
209Formula::operator=(Temp r)
210{
211    assert(!root && "Can't change formulas");
212    root = r;
213    assert(size());
214    return *this;
215}
216
217const Formula &
218Formula::operator+=(Temp r)
219{
220    if (root)
221        root = NodePtr(new BinaryNode<std::plus<Result> >(root, r));
222    else
223        root = r;
224    assert(size());
225    return *this;
226}
227
228void
229check()
230{
231    typedef Database::stat_list_t::iterator iter_t;
232
233    iter_t i, end = Database::stats().end();
234    for (i = Database::stats().begin(); i != end; ++i) {
235        Info *info = *i;
236        assert(info);
237        if (!info->check() || !info->baseCheck())
238            panic("stat check failed for %s\n", info->name);
239    }
240
241    off_t j = 0;
242    for (i = Database::stats().begin(); i != end; ++i) {
243        Info *info = *i;
244        if (!(info->flags & print))
245            info->name = "__Stat" + to_string(j++);
246    }
247
248    Database::stats().sort(Info::less);
249
250    if (i == end)
251        return;
252
253    iter_t last = i;
254    ++i;
255
256    for (i = Database::stats().begin(); i != end; ++i) {
257        if ((*i)->name == (*last)->name)
258            panic("same name used twice! name=%s\n", (*i)->name);
259
260        last = i;
261    }
262}
263
264CallbackQueue resetQueue;
265
266void
267reset()
268{
269    Database::stat_list_t::iterator i = Database::stats().begin();
270    Database::stat_list_t::iterator end = Database::stats().end();
271    while (i != end) {
272        Info *info = *i;
273        info->reset();
274        ++i;
275    }
276
277    resetQueue.process();
278}
279
280void
281registerResetCallback(Callback *cb)
282{
283    resetQueue.add(cb);
284}
285
286/* namespace Stats */ }
287