statistics.cc revision 9554:406fbcf60223
16876Ssteve.reinhardt@amd.com/*
210089Sandreas.hansson@arm.com * Copyright (c) 2003-2005 The Regents of The University of Michigan
38922Swilliam.wang@arm.com * All rights reserved.
48922Swilliam.wang@arm.com *
58922Swilliam.wang@arm.com * Redistribution and use in source and binary forms, with or without
68922Swilliam.wang@arm.com * modification, are permitted provided that the following conditions are
78922Swilliam.wang@arm.com * met: redistributions of source code must retain the above copyright
88922Swilliam.wang@arm.com * notice, this list of conditions and the following disclaimer;
98922Swilliam.wang@arm.com * redistributions in binary form must reproduce the above copyright
108922Swilliam.wang@arm.com * notice, this list of conditions and the following disclaimer in the
118922Swilliam.wang@arm.com * documentation and/or other materials provided with the distribution;
128922Swilliam.wang@arm.com * neither the name of the copyright holders nor the names of its
138922Swilliam.wang@arm.com * contributors may be used to endorse or promote products derived from
146876Ssteve.reinhardt@amd.com * this software without specific prior written permission.
158717Snilay@cs.wisc.edu *
166876Ssteve.reinhardt@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176876Ssteve.reinhardt@amd.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186876Ssteve.reinhardt@amd.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196876Ssteve.reinhardt@amd.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206876Ssteve.reinhardt@amd.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216876Ssteve.reinhardt@amd.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226876Ssteve.reinhardt@amd.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236876Ssteve.reinhardt@amd.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246876Ssteve.reinhardt@amd.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256876Ssteve.reinhardt@amd.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266876Ssteve.reinhardt@amd.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276876Ssteve.reinhardt@amd.com *
286876Ssteve.reinhardt@amd.com * Authors: Nathan Binkert
296876Ssteve.reinhardt@amd.com */
306876Ssteve.reinhardt@amd.com
316876Ssteve.reinhardt@amd.com#include <fstream>
326876Ssteve.reinhardt@amd.com#include <iomanip>
336876Ssteve.reinhardt@amd.com#include <list>
346876Ssteve.reinhardt@amd.com#include <map>
356876Ssteve.reinhardt@amd.com#include <string>
366876Ssteve.reinhardt@amd.com
376876Ssteve.reinhardt@amd.com#include "base/callback.hh"
386876Ssteve.reinhardt@amd.com#include "base/cprintf.hh"
396876Ssteve.reinhardt@amd.com#include "base/debug.hh"
406876Ssteve.reinhardt@amd.com#include "base/hostinfo.hh"
416876Ssteve.reinhardt@amd.com#include "base/misc.hh"
427039Snate@binkert.org#include "base/statistics.hh"
437039Snate@binkert.org#include "base/str.hh"
446285Snate@binkert.org#include "base/time.hh"
457039Snate@binkert.org#include "base/trace.hh"
466285Snate@binkert.org
476285Snate@binkert.orgusing namespace std;
486922SBrad.Beckmann@amd.com
4910301Snilay@cs.wisc.edunamespace Stats {
507909Shestness@cs.utexas.edu
518229Snate@binkert.orgstd::string Info::separatorString = "::";
527039Snate@binkert.org
536876Ssteve.reinhardt@amd.com// We wrap these in a function to make sure they're built in time.
546876Ssteve.reinhardt@amd.comlist<Info *> &
556876Ssteve.reinhardt@amd.comstatsList()
566876Ssteve.reinhardt@amd.com{
577039Snate@binkert.org    static list<Info *> the_list;
587039Snate@binkert.org    return the_list;
597039Snate@binkert.org}
6010090Snilay@cs.wisc.edu
6110090Snilay@cs.wisc.eduMapType &
6210090Snilay@cs.wisc.edustatsMap()
6310713Sandreas.hansson@arm.com{
6410713Sandreas.hansson@arm.com    static MapType the_map;
6510090Snilay@cs.wisc.edu    return the_map;
6610090Snilay@cs.wisc.edu}
6710090Snilay@cs.wisc.edu
6810090Snilay@cs.wisc.eduvoid
6910090Snilay@cs.wisc.eduInfoAccess::setInfo(Info *info)
7010090Snilay@cs.wisc.edu{
7110090Snilay@cs.wisc.edu    if (statsMap().find(this) != statsMap().end())
7210090Snilay@cs.wisc.edu        panic("shouldn't register stat twice!");
7310090Snilay@cs.wisc.edu
7410090Snilay@cs.wisc.edu    statsList().push_back(info);
756882SBrad.Beckmann@amd.com
767039Snate@binkert.org#ifndef NDEBUG
7710713Sandreas.hansson@arm.com    pair<MapType::iterator, bool> result =
788436SBrad.Beckmann@amd.com#endif
7910525Snilay@cs.wisc.edu        statsMap().insert(make_pair(this, info));
806882SBrad.Beckmann@amd.com    assert(result.second && "this should never fail");
816882SBrad.Beckmann@amd.com    assert(statsMap().find(this) != statsMap().end());
8210090Snilay@cs.wisc.edu}
8310525Snilay@cs.wisc.edu
846882SBrad.Beckmann@amd.comvoid
858717Snilay@cs.wisc.eduInfoAccess::setParams(const StorageParams *params)
866882SBrad.Beckmann@amd.com{
876882SBrad.Beckmann@amd.com    info()->storageParams = params;
8810089Sandreas.hansson@arm.com}
8910090Snilay@cs.wisc.edu
9010090Snilay@cs.wisc.eduvoid
9110090Snilay@cs.wisc.eduInfoAccess::setInit()
9210090Snilay@cs.wisc.edu{
9310089Sandreas.hansson@arm.com    info()->flags.set(init);
9410090Snilay@cs.wisc.edu}
9510090Snilay@cs.wisc.edu
9610090Snilay@cs.wisc.eduInfo *
976882SBrad.Beckmann@amd.comInfoAccess::info()
986882SBrad.Beckmann@amd.com{
9910089Sandreas.hansson@arm.com    MapType::const_iterator i = statsMap().find(this);
1006882SBrad.Beckmann@amd.com    assert(i != statsMap().end());
1016882SBrad.Beckmann@amd.com    return (*i).second;
10210090Snilay@cs.wisc.edu}
1036882SBrad.Beckmann@amd.com
1047039Snate@binkert.orgconst Info *
10510713Sandreas.hansson@arm.comInfoAccess::info() const
10610713Sandreas.hansson@arm.com{
1078914Sandreas.hansson@arm.com    MapType::const_iterator i = statsMap().find(this);
1086882SBrad.Beckmann@amd.com    assert(i != statsMap().end());
10910090Snilay@cs.wisc.edu    return (*i).second;
1106882SBrad.Beckmann@amd.com}
1116882SBrad.Beckmann@amd.com
11210090Snilay@cs.wisc.eduStorageParams::~StorageParams()
11310090Snilay@cs.wisc.edu{
1146882SBrad.Beckmann@amd.com}
1156882SBrad.Beckmann@amd.com
11610090Snilay@cs.wisc.eduNameMapType &
11710090Snilay@cs.wisc.edunameMap()
11810090Snilay@cs.wisc.edu{
11910713Sandreas.hansson@arm.com    static NameMapType the_map;
12010090Snilay@cs.wisc.edu    return the_map;
12110090Snilay@cs.wisc.edu}
12210090Snilay@cs.wisc.edu
12310090Snilay@cs.wisc.eduint Info::id_count = 0;
12410090Snilay@cs.wisc.edu
12510090Snilay@cs.wisc.eduint debug_break_id = -1;
12610090Snilay@cs.wisc.edu
12710090Snilay@cs.wisc.eduInfo::Info()
12810090Snilay@cs.wisc.edu    : flags(none), precision(-1), prereq(0), storageParams(NULL)
12910090Snilay@cs.wisc.edu{
13010090Snilay@cs.wisc.edu    id = id_count++;
13110090Snilay@cs.wisc.edu    if (debug_break_id >= 0 and debug_break_id == id)
13210090Snilay@cs.wisc.edu        Debug::breakpoint();
13310090Snilay@cs.wisc.edu}
13410090Snilay@cs.wisc.edu
13510090Snilay@cs.wisc.eduInfo::~Info()
13610090Snilay@cs.wisc.edu{
13710090Snilay@cs.wisc.edu}
13810090Snilay@cs.wisc.edu
13910090Snilay@cs.wisc.edubool
14010090Snilay@cs.wisc.eduvalidateStatName(const string &name)
14110090Snilay@cs.wisc.edu{
14210090Snilay@cs.wisc.edu    if (name.empty())
1436876Ssteve.reinhardt@amd.com        return false;
1446876Ssteve.reinhardt@amd.com
1456882SBrad.Beckmann@amd.com    vector<string> vec;
1466882SBrad.Beckmann@amd.com    tokenize(vec, name, '.');
1476882SBrad.Beckmann@amd.com    vector<string>::const_iterator item = vec.begin();
1486285Snate@binkert.org    while (item != vec.end()) {
1499294Sandreas.hansson@arm.com        if (item->empty())
1509294Sandreas.hansson@arm.com            return false;
1519294Sandreas.hansson@arm.com
1529294Sandreas.hansson@arm.com        string::const_iterator c = item->begin();
1536876Ssteve.reinhardt@amd.com
1548615Snilay@cs.wisc.edu        // The first character is different
1558688Snilay@cs.wisc.edu        if (!isalpha(*c) && *c != '_')
1568688Snilay@cs.wisc.edu            return false;
1578688Snilay@cs.wisc.edu
1586882SBrad.Beckmann@amd.com        // The rest of the characters have different rules.
1596882SBrad.Beckmann@amd.com        while (++c != item->end()) {
1606882SBrad.Beckmann@amd.com            if (!isalnum(*c) && *c != '_')
1616882SBrad.Beckmann@amd.com                return false;
1626882SBrad.Beckmann@amd.com        }
1636882SBrad.Beckmann@amd.com
16410012Snilay@cs.wisc.edu        ++item;
1659342SAndreas.Sandberg@arm.com    }
1666285Snate@binkert.org
1677039Snate@binkert.org    return true;
1687039Snate@binkert.org}
1698688Snilay@cs.wisc.edu
1708717Snilay@cs.wisc.eduvoid
1716285Snate@binkert.orgInfo::setName(const string &name)
17210089Sandreas.hansson@arm.com{
17310089Sandreas.hansson@arm.com    if (!validateStatName(name))
17410089Sandreas.hansson@arm.com        panic("invalid stat name '%s'", name);
17510089Sandreas.hansson@arm.com
17610089Sandreas.hansson@arm.com    pair<NameMapType::iterator, bool> p =
17710089Sandreas.hansson@arm.com        nameMap().insert(make_pair(name, this));
17810089Sandreas.hansson@arm.com
17910089Sandreas.hansson@arm.com    Info *other = p.first->second;
18010089Sandreas.hansson@arm.com    bool result = p.second;
18110089Sandreas.hansson@arm.com
18210012Snilay@cs.wisc.edu    if (!result) {
1837039Snate@binkert.org        // using other->name instead of just name to avoid a compiler
1847039Snate@binkert.org        // warning.  They should be the same.
1857910SBrad.Beckmann@amd.com        panic("same statistic name used twice! name=%s\n", other->name);
18610467Sandreas.hansson@arm.com    }
1876876Ssteve.reinhardt@amd.com
1887039Snate@binkert.org    this->name = name;
18910090Snilay@cs.wisc.edu}
1907910SBrad.Beckmann@amd.com
19110089Sandreas.hansson@arm.combool
19210089Sandreas.hansson@arm.comInfo::less(Info *stat1, Info *stat2)
19310089Sandreas.hansson@arm.com{
1947910SBrad.Beckmann@amd.com    const string &name1 = stat1->name;
1957910SBrad.Beckmann@amd.com    const string &name2 = stat2->name;
1969342SAndreas.Sandberg@arm.com
1978688Snilay@cs.wisc.edu    vector<string> v1;
19810090Snilay@cs.wisc.edu    vector<string> v2;
19910090Snilay@cs.wisc.edu
20010090Snilay@cs.wisc.edu    tokenize(v1, name1, '.');
20110090Snilay@cs.wisc.edu    tokenize(v2, name2, '.');
20210090Snilay@cs.wisc.edu
20310090Snilay@cs.wisc.edu    size_type last = min(v1.size(), v2.size()) - 1;
2048922Swilliam.wang@arm.com    for (off_type i = 0; i < last; ++i)
20510090Snilay@cs.wisc.edu        if (v1[i] != v2[i])
20610090Snilay@cs.wisc.edu            return v1[i] < v2[i];
20710090Snilay@cs.wisc.edu
2088686Snilay@cs.wisc.edu    // Special compare for last element.
2099342SAndreas.Sandberg@arm.com    if (v1[last] == v2[last])
2107910SBrad.Beckmann@amd.com        return v1.size() < v2.size();
2117910SBrad.Beckmann@amd.com    else
2127910SBrad.Beckmann@amd.com        return v1[last] < v2[last];
2137910SBrad.Beckmann@amd.com
2147910SBrad.Beckmann@amd.com    return false;
21510090Snilay@cs.wisc.edu}
2166285Snate@binkert.org
2176285Snate@binkert.orgbool
2187039Snate@binkert.orgInfo::baseCheck() const
219{
220    if (!(flags & Stats::init)) {
221#ifdef DEBUG
222        cprintf("this is stat number %d\n", id);
223#endif
224        panic("Not all stats have been initialized");
225        return false;
226    }
227
228    if ((flags & display) && name.empty()) {
229        panic("all printable stats must be named");
230        return false;
231    }
232
233    return true;
234}
235
236void
237Info::enable()
238{
239}
240
241void
242VectorInfo::enable()
243{
244    size_type s = size();
245    if (subnames.size() < s)
246        subnames.resize(s);
247    if (subdescs.size() < s)
248        subdescs.resize(s);
249}
250
251void
252VectorDistInfo::enable()
253{
254    size_type s = size();
255    if (subnames.size() < s)
256        subnames.resize(s);
257    if (subdescs.size() < s)
258        subdescs.resize(s);
259}
260
261void
262Vector2dInfo::enable()
263{
264    if (subnames.size() < x)
265        subnames.resize(x);
266    if (subdescs.size() < x)
267        subdescs.resize(x);
268    if (y_subnames.size() < y)
269        y_subnames.resize(y);
270}
271
272void
273HistStor::grow_out()
274{
275    int size = cvec.size();
276    int zero = size / 2; // round down!
277    int top_half = zero + (size - zero + 1) / 2; // round up!
278    int bottom_half = (size - zero) / 2; // round down!
279
280    // grow down
281    int low_pair = zero - 1;
282    for (int i = zero - 1; i >= bottom_half; i--) {
283        cvec[i] = cvec[low_pair];
284        if (low_pair - 1 >= 0)
285            cvec[i] += cvec[low_pair - 1];
286        low_pair -= 2;
287    }
288    assert(low_pair == 0 || low_pair == -1 || low_pair == -2);
289
290    for (int i = bottom_half - 1; i >= 0; i--)
291        cvec[i] = Counter();
292
293    // grow up
294    int high_pair = zero;
295    for (int i = zero; i < top_half; i++) {
296        cvec[i] = cvec[high_pair];
297        if (high_pair + 1 < size)
298            cvec[i] += cvec[high_pair + 1];
299        high_pair += 2;
300    }
301    assert(high_pair == size || high_pair == size + 1);
302
303    for (int i = top_half; i < size; i++)
304        cvec[i] = Counter();
305
306    max_bucket *= 2;
307    min_bucket *= 2;
308    bucket_size *= 2;
309}
310
311void
312HistStor::grow_convert()
313{
314    int size = cvec.size();
315    int half = (size + 1) / 2; // round up!
316    //bool even = (size & 1) == 0;
317
318    int pair = size - 1;
319    for (int i = size - 1; i >= half; --i) {
320        cvec[i] = cvec[pair];
321        if (pair - 1 >= 0)
322            cvec[i] += cvec[pair - 1];
323        pair -= 2;
324    }
325
326    for (int i = half - 1; i >= 0; i--)
327        cvec[i] = Counter();
328
329    min_bucket = -max_bucket;// - (even ? bucket_size : 0);
330    bucket_size *= 2;
331}
332
333void
334HistStor::grow_up()
335{
336    int size = cvec.size();
337    int half = (size + 1) / 2; // round up!
338
339    int pair = 0;
340    for (int i = 0; i < half; i++) {
341        cvec[i] = cvec[pair];
342        if (pair + 1 < size)
343            cvec[i] += cvec[pair + 1];
344        pair += 2;
345    }
346    assert(pair == size || pair == size + 1);
347
348    for (int i = half; i < size; i++)
349        cvec[i] = Counter();
350
351    max_bucket *= 2;
352    bucket_size *= 2;
353}
354
355Formula::Formula()
356{
357}
358
359Formula::Formula(Temp r)
360{
361    root = r;
362    setInit();
363    assert(size());
364}
365
366const Formula &
367Formula::operator=(Temp r)
368{
369    assert(!root && "Can't change formulas");
370    root = r;
371    setInit();
372    assert(size());
373    return *this;
374}
375
376const Formula &
377Formula::operator+=(Temp r)
378{
379    if (root)
380        root = NodePtr(new BinaryNode<std::plus<Result> >(root, r));
381    else {
382        root = r;
383        setInit();
384    }
385
386    assert(size());
387    return *this;
388}
389
390void
391Formula::result(VResult &vec) const
392{
393    if (root)
394        vec = root->result();
395}
396
397Result
398Formula::total() const
399{
400    return root ? root->total() : 0.0;
401}
402
403size_type
404Formula::size() const
405{
406    if (!root)
407        return 0;
408    else
409        return root->size();
410}
411
412void
413Formula::reset()
414{
415}
416
417bool
418Formula::zero() const
419{
420    VResult vec;
421    result(vec);
422    for (VResult::size_type i = 0; i < vec.size(); ++i)
423        if (vec[i] != 0.0)
424            return false;
425    return true;
426}
427
428string
429Formula::str() const
430{
431    return root ? root->str() : "";
432}
433
434CallbackQueue dumpQueue;
435CallbackQueue resetQueue;
436
437void
438registerResetCallback(Callback *cb)
439{
440    resetQueue.add(cb);
441}
442
443bool _enabled = false;
444
445bool
446enabled()
447{
448    return _enabled;
449}
450
451void
452enable()
453{
454    if (_enabled)
455        fatal("Stats are already enabled");
456
457    _enabled = true;
458}
459
460void
461registerDumpCallback(Callback *cb)
462{
463    dumpQueue.add(cb);
464}
465
466} // namespace Stats
467
468void
469debugDumpStats()
470{
471    Stats::dump();
472}
473