statistics.cc revision 11793:ef606668d247
12100SN/A/*
22083SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan
35268Sksewell@umich.edu * All rights reserved.
45268Sksewell@umich.edu *
55268Sksewell@umich.edu * Redistribution and use in source and binary forms, with or without
65268Sksewell@umich.edu * modification, are permitted provided that the following conditions are
75268Sksewell@umich.edu * met: redistributions of source code must retain the above copyright
85268Sksewell@umich.edu * notice, this list of conditions and the following disclaimer;
95268Sksewell@umich.edu * redistributions in binary form must reproduce the above copyright
105268Sksewell@umich.edu * notice, this list of conditions and the following disclaimer in the
115268Sksewell@umich.edu * documentation and/or other materials provided with the distribution;
125268Sksewell@umich.edu * neither the name of the copyright holders nor the names of its
135268Sksewell@umich.edu * contributors may be used to endorse or promote products derived from
145268Sksewell@umich.edu * this software without specific prior written permission.
155268Sksewell@umich.edu *
165268Sksewell@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
175268Sksewell@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
185268Sksewell@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
195268Sksewell@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
205268Sksewell@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
215268Sksewell@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
225268Sksewell@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235268Sksewell@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245268Sksewell@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255268Sksewell@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265268Sksewell@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275268Sksewell@umich.edu *
285268Sksewell@umich.edu * Authors: Nathan Binkert
295268Sksewell@umich.edu */
302706Sksewell@umich.edu
312089SN/A#include "base/statistics.hh"
322022SN/A
332089SN/A#include <fstream>
342022SN/A#include <iomanip>
352022SN/A#include <list>
362022SN/A#include <map>
372083SN/A#include <string>
382239SN/A
394661Sksewell@umich.edu#include "base/callback.hh"
402239SN/A#include "base/cprintf.hh"
412083SN/A#include "base/debug.hh"
422083SN/A#include "base/hostinfo.hh"
432083SN/A#include "base/misc.hh"
442083SN/A#include "base/str.hh"
452083SN/A#include "base/time.hh"
462083SN/A#include "base/trace.hh"
472083SN/A
482083SN/Ausing namespace std;
492083SN/A
502089SN/Anamespace Stats {
512083SN/A
522083SN/Astd::string Info::separatorString = "::";
532083SN/A
542083SN/A// We wrap these in a function to make sure they're built in time.
552089SN/Alist<Info *> &
562083SN/AstatsList()
572083SN/A{
582083SN/A    static list<Info *> the_list;
592083SN/A    return the_list;
602083SN/A}
612083SN/A
622089SN/AMapType &
632083SN/AstatsMap()
642022SN/A{
652083SN/A    static MapType the_map;
662022SN/A    return the_map;
672083SN/A}
682083SN/A
692083SN/Avoid
702022SN/AInfoAccess::setInfo(Info *info)
712083SN/A{
722083SN/A    if (statsMap().find(this) != statsMap().end())
732083SN/A        panic("shouldn't register stat twice!");
742083SN/A
752083SN/A    statsList().push_back(info);
762083SN/A
772083SN/A#ifndef NDEBUG
782089SN/A    pair<MapType::iterator, bool> result =
792104SN/A#endif
802083SN/A        statsMap().insert(make_pair(this, info));
812083SN/A    assert(result.second && "this should never fail");
822083SN/A    assert(statsMap().find(this) != statsMap().end());
832083SN/A}
842104SN/A
852089SN/Avoid
862239SN/AInfoAccess::setParams(const StorageParams *params)
872239SN/A{
882239SN/A    info()->storageParams = params;
892239SN/A}
902089SN/A
912089SN/Avoid
922089SN/AInfoAccess::setInit()
932089SN/A{
942089SN/A    info()->flags.set(init);
952089SN/A}
962089SN/A
972089SN/AInfo *
982089SN/AInfoAccess::info()
992083SN/A{
1002089SN/A    MapType::const_iterator i = statsMap().find(this);
1012083SN/A    assert(i != statsMap().end());
1022083SN/A    return (*i).second;
1032083SN/A}
1042083SN/A
1052083SN/Aconst Info *
1062083SN/AInfoAccess::info() const
1072083SN/A{
1082083SN/A    MapType::const_iterator i = statsMap().find(this);
1092239SN/A    assert(i != statsMap().end());
1102239SN/A    return (*i).second;
1112083SN/A}
1122083SN/A
1132083SN/AStorageParams::~StorageParams()
1142083SN/A{
1152239SN/A}
1162083SN/A
1172083SN/ANameMapType &
1182083SN/AnameMap()
1192687Sksewell@umich.edu{
1202083SN/A    static NameMapType the_map;
1212083SN/A    return the_map;
1222083SN/A}
1232083SN/A
1242022SN/Aint Info::id_count = 0;
1252022SN/A
1262022SN/Aint debug_break_id = -1;
1272083SN/A
1282083SN/AInfo::Info()
1292083SN/A    : flags(none), precision(-1), prereq(0), storageParams(NULL)
1302083SN/A{
1312083SN/A    id = id_count++;
1322083SN/A    if (debug_break_id >= 0 and debug_break_id == id)
1332083SN/A        Debug::breakpoint();
1342687Sksewell@umich.edu}
1352083SN/A
1365222Sksewell@umich.eduInfo::~Info()
1375222Sksewell@umich.edu{
1382083SN/A}
1392083SN/A
1402083SN/Abool
1412083SN/AvalidateStatName(const string &name)
1422083SN/A{
1432083SN/A    if (name.empty())
1442083SN/A        return false;
1452083SN/A
1462022SN/A    vector<string> vec;
1472083SN/A    tokenize(vec, name, '.');
1482083SN/A    vector<string>::const_iterator item = vec.begin();
1492083SN/A    while (item != vec.end()) {
1502083SN/A        if (item->empty())
1512083SN/A            return false;
1522083SN/A
1532083SN/A        string::const_iterator c = item->begin();
1542022SN/A
1552083SN/A        // The first character is different
1562083SN/A        if (!isalpha(*c) && *c != '_')
1572083SN/A            return false;
1582083SN/A
1592083SN/A        // The rest of the characters have different rules.
1602083SN/A        while (++c != item->end()) {
1612083SN/A            if (!isalnum(*c) && *c != '_')
1622083SN/A                return false;
1632083SN/A        }
1642083SN/A
1652083SN/A        ++item;
1662083SN/A    }
1672083SN/A
1682083SN/A    return true;
1692083SN/A}
1702239SN/A
1712083SN/Avoid
1722686Sksewell@umich.eduInfo::setName(const string &name)
1732239SN/A{
1742239SN/A    if (!validateStatName(name))
1752686Sksewell@umich.edu        panic("invalid stat name '%s'", name);
1762239SN/A
1772686Sksewell@umich.edu    pair<NameMapType::iterator, bool> p =
1782103SN/A        nameMap().insert(make_pair(name, this));
1792103SN/A
1802103SN/A    Info *other = p.first->second;
1812103SN/A    bool result = p.second;
1822103SN/A
1832103SN/A    if (!result) {
1842103SN/A      // using other->name instead of just name to avoid a compiler
1852103SN/A      // warning.  They should be the same.
1862103SN/A        panic("same statistic name used twice! name=%s\n", other->name);
1872103SN/A    }
1882103SN/A
1892103SN/A    this->name = name;
1902103SN/A}
1912103SN/A
1922083SN/Abool
1932083SN/AInfo::less(Info *stat1, Info *stat2)
1942083SN/A{
1952083SN/A    const string &name1 = stat1->name;
1962083SN/A    const string &name2 = stat2->name;
1972083SN/A
1985269Sksewell@umich.edu    vector<string> v1;
1992239SN/A    vector<string> v2;
2002239SN/A
2012239SN/A    tokenize(v1, name1, '.');
2022239SN/A    tokenize(v2, name2, '.');
2032239SN/A
2042239SN/A    size_type last = min(v1.size(), v2.size()) - 1;
2052239SN/A    for (off_type i = 0; i < last; ++i)
2062239SN/A        if (v1[i] != v2[i])
2072239SN/A            return v1[i] < v2[i];
2082239SN/A
2092239SN/A    // Special compare for last element.
2102239SN/A    if (v1[last] == v2[last])
2112686Sksewell@umich.edu        return v1.size() < v2.size();
2122239SN/A    else
2132083SN/A        return v1[last] < v2[last];
2142083SN/A
2152083SN/A    return false;
2162083SN/A}
2172022SN/A
2182022SN/Abool
2194661Sksewell@umich.eduInfo::baseCheck() const
2202686Sksewell@umich.edu{
2212686Sksewell@umich.edu    if (!(flags & Stats::init)) {
2222686Sksewell@umich.edu#ifdef DEBUG
2232686Sksewell@umich.edu        cprintf("this is stat number %d\n", id);
2242686Sksewell@umich.edu#endif
2252686Sksewell@umich.edu        panic("Not all stats have been initialized.\n"
2262686Sksewell@umich.edu              "You may need to add <ParentClass>::regStats() to a"
2272686Sksewell@umich.edu              " new SimObject's regStats() function.");
2282686Sksewell@umich.edu        return false;
2292686Sksewell@umich.edu    }
2302686Sksewell@umich.edu
2312686Sksewell@umich.edu    if ((flags & display) && name.empty()) {
2322686Sksewell@umich.edu        panic("all printable stats must be named");
2334661Sksewell@umich.edu        return false;
2342686Sksewell@umich.edu    }
2352686Sksewell@umich.edu
2362686Sksewell@umich.edu    return true;
2372935Sksewell@umich.edu}
2384661Sksewell@umich.edu
2394661Sksewell@umich.eduvoid
2402935Sksewell@umich.eduInfo::enable()
2412686Sksewell@umich.edu{
2422101SN/A}
2432123SN/A
2442123SN/Avoid
2452123SN/AVectorInfo::enable()
2462123SN/A{
2472239SN/A    size_type s = size();
2482686Sksewell@umich.edu    if (subnames.size() < s)
2492101SN/A        subnames.resize(s);
2503951Sgblack@eecs.umich.edu    if (subdescs.size() < s)
2512047SN/A        subdescs.resize(s);
2522047SN/A}
2532047SN/A
2542047SN/Avoid
2552022SN/AVectorDistInfo::enable()
2562047SN/A{
2574661Sksewell@umich.edu    size_type s = size();
2584661Sksewell@umich.edu    if (subnames.size() < s)
2594661Sksewell@umich.edu        subnames.resize(s);
2604661Sksewell@umich.edu    if (subdescs.size() < s)
2614661Sksewell@umich.edu        subdescs.resize(s);
2624661Sksewell@umich.edu}
2634661Sksewell@umich.edu
2644661Sksewell@umich.eduvoid
2654661Sksewell@umich.eduVector2dInfo::enable()
2664661Sksewell@umich.edu{
2674661Sksewell@umich.edu    if (subnames.size() < x)
2684661Sksewell@umich.edu        subnames.resize(x);
2694661Sksewell@umich.edu    if (subdescs.size() < x)
2704661Sksewell@umich.edu        subdescs.resize(x);
2714661Sksewell@umich.edu    if (y_subnames.size() < y)
2724661Sksewell@umich.edu        y_subnames.resize(y);
2734661Sksewell@umich.edu}
2744661Sksewell@umich.edu
2754661Sksewell@umich.eduvoid
2764661Sksewell@umich.eduHistStor::grow_out()
2774661Sksewell@umich.edu{
2784661Sksewell@umich.edu    int size = cvec.size();
2794661Sksewell@umich.edu    int zero = size / 2; // round down!
2804661Sksewell@umich.edu    int top_half = zero + (size - zero + 1) / 2; // round up!
2814661Sksewell@umich.edu    int bottom_half = (size - zero) / 2; // round down!
2824661Sksewell@umich.edu
2834661Sksewell@umich.edu    // grow down
2844661Sksewell@umich.edu    int low_pair = zero - 1;
2854661Sksewell@umich.edu    for (int i = zero - 1; i >= bottom_half; i--) {
2864661Sksewell@umich.edu        cvec[i] = cvec[low_pair];
2874661Sksewell@umich.edu        if (low_pair - 1 >= 0)
2884661Sksewell@umich.edu            cvec[i] += cvec[low_pair - 1];
2894661Sksewell@umich.edu        low_pair -= 2;
2904661Sksewell@umich.edu    }
2914661Sksewell@umich.edu    assert(low_pair == 0 || low_pair == -1 || low_pair == -2);
2924661Sksewell@umich.edu
2934661Sksewell@umich.edu    for (int i = bottom_half - 1; i >= 0; i--)
2944661Sksewell@umich.edu        cvec[i] = Counter();
2954661Sksewell@umich.edu
2964661Sksewell@umich.edu    // grow up
2974661Sksewell@umich.edu    int high_pair = zero;
2984661Sksewell@umich.edu    for (int i = zero; i < top_half; i++) {
2994661Sksewell@umich.edu        cvec[i] = cvec[high_pair];
3004661Sksewell@umich.edu        if (high_pair + 1 < size)
3014661Sksewell@umich.edu            cvec[i] += cvec[high_pair + 1];
3022686Sksewell@umich.edu        high_pair += 2;
3032686Sksewell@umich.edu    }
3042686Sksewell@umich.edu    assert(high_pair == size || high_pair == size + 1);
3052686Sksewell@umich.edu
3062686Sksewell@umich.edu    for (int i = top_half; i < size; i++)
3072686Sksewell@umich.edu        cvec[i] = Counter();
3082686Sksewell@umich.edu
3092686Sksewell@umich.edu    max_bucket *= 2;
3102686Sksewell@umich.edu    min_bucket *= 2;
3112686Sksewell@umich.edu    bucket_size *= 2;
3122686Sksewell@umich.edu}
3132104SN/A
3143951Sgblack@eecs.umich.eduvoid
3152089SN/AHistStor::grow_convert()
3162089SN/A{
3172089SN/A    int size = cvec.size();
3182089SN/A    int half = (size + 1) / 2; // round up!
3192089SN/A    //bool even = (size & 1) == 0;
3202083SN/A
3212239SN/A    int pair = size - 1;
3222123SN/A    for (int i = size - 1; i >= half; --i) {
3232123SN/A        cvec[i] = cvec[pair];
324        if (pair - 1 >= 0)
325            cvec[i] += cvec[pair - 1];
326        pair -= 2;
327    }
328
329    for (int i = half - 1; i >= 0; i--)
330        cvec[i] = Counter();
331
332    min_bucket = -max_bucket;// - (even ? bucket_size : 0);
333    bucket_size *= 2;
334}
335
336void
337HistStor::grow_up()
338{
339    int size = cvec.size();
340    int half = (size + 1) / 2; // round up!
341
342    int pair = 0;
343    for (int i = 0; i < half; i++) {
344        cvec[i] = cvec[pair];
345        if (pair + 1 < size)
346            cvec[i] += cvec[pair + 1];
347        pair += 2;
348    }
349    assert(pair == size || pair == size + 1);
350
351    for (int i = half; i < size; i++)
352        cvec[i] = Counter();
353
354    max_bucket *= 2;
355    bucket_size *= 2;
356}
357
358void
359HistStor::add(HistStor *hs)
360{
361    int b_size = hs->size();
362    assert(size() == b_size);
363    assert(min_bucket == hs->min_bucket);
364
365    sum += hs->sum;
366    logs += hs->logs;
367    squares += hs->squares;
368    samples += hs->samples;
369
370    while (bucket_size > hs->bucket_size)
371        hs->grow_up();
372    while (bucket_size < hs->bucket_size)
373        grow_up();
374
375    for (uint32_t i = 0; i < b_size; i++)
376        cvec[i] += hs->cvec[i];
377}
378
379Formula::Formula()
380{
381}
382
383Formula::Formula(Temp r)
384{
385    root = r.getNodePtr();
386    setInit();
387    assert(size());
388}
389
390const Formula &
391Formula::operator=(Temp r)
392{
393    assert(!root && "Can't change formulas");
394    root = r.getNodePtr();
395    setInit();
396    assert(size());
397    return *this;
398}
399
400const Formula &
401Formula::operator+=(Temp r)
402{
403    if (root)
404        root = NodePtr(new BinaryNode<std::plus<Result> >(root, r));
405    else {
406        root = r.getNodePtr();
407        setInit();
408    }
409
410    assert(size());
411    return *this;
412}
413
414const Formula &
415Formula::operator/=(Temp r)
416{
417    assert (root);
418    root = NodePtr(new BinaryNode<std::divides<Result> >(root, r));
419
420    assert(size());
421    return *this;
422}
423
424void
425Formula::result(VResult &vec) const
426{
427    if (root)
428        vec = root->result();
429}
430
431Result
432Formula::total() const
433{
434    return root ? root->total() : 0.0;
435}
436
437size_type
438Formula::size() const
439{
440    if (!root)
441        return 0;
442    else
443        return root->size();
444}
445
446void
447Formula::reset()
448{
449}
450
451bool
452Formula::zero() const
453{
454    VResult vec;
455    result(vec);
456    for (VResult::size_type i = 0; i < vec.size(); ++i)
457        if (vec[i] != 0.0)
458            return false;
459    return true;
460}
461
462string
463Formula::str() const
464{
465    return root ? root->str() : "";
466}
467
468Handler resetHandler = NULL;
469Handler dumpHandler = NULL;
470
471void
472registerHandlers(Handler reset_handler, Handler dump_handler)
473{
474    resetHandler = reset_handler;
475    dumpHandler = dump_handler;
476}
477
478CallbackQueue dumpQueue;
479CallbackQueue resetQueue;
480
481void
482processResetQueue()
483{
484    resetQueue.process();
485}
486
487void
488processDumpQueue()
489{
490    dumpQueue.process();
491}
492
493void
494registerResetCallback(Callback *cb)
495{
496    resetQueue.add(cb);
497}
498
499bool _enabled = false;
500
501bool
502enabled()
503{
504    return _enabled;
505}
506
507void
508enable()
509{
510    if (_enabled)
511        fatal("Stats are already enabled");
512
513    _enabled = true;
514}
515
516void
517dump()
518{
519    if (dumpHandler)
520        dumpHandler();
521    else
522        fatal("No registered Stats::dump handler");
523}
524
525void
526reset()
527{
528    if (resetHandler)
529        resetHandler();
530    else
531        fatal("No registered Stats::reset handler");
532}
533
534void
535registerDumpCallback(Callback *cb)
536{
537    dumpQueue.add(cb);
538}
539
540} // namespace Stats
541
542void
543debugDumpStats()
544{
545    Stats::dump();
546}
547