12SN/A/*
214205Sandreas.sandberg@arm.com * Copyright (c) 2019 Arm Limited
314205Sandreas.sandberg@arm.com * All rights reserved.
414205Sandreas.sandberg@arm.com *
514205Sandreas.sandberg@arm.com * The license below extends only to copyright in the software and shall
614205Sandreas.sandberg@arm.com * not be construed as granting a license to any other intellectual
714205Sandreas.sandberg@arm.com * property including but not limited to intellectual property relating
814205Sandreas.sandberg@arm.com * to a hardware implementation of the functionality of the software
914205Sandreas.sandberg@arm.com * licensed hereunder.  You may use the software subject to the license
1014205Sandreas.sandberg@arm.com * terms below provided that you ensure that this notice is replicated
1114205Sandreas.sandberg@arm.com * unmodified and in its entirety in all distributions of the software,
1214205Sandreas.sandberg@arm.com * modified or unmodified, in source code or in binary form.
1314205Sandreas.sandberg@arm.com *
141762SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan
152SN/A * All rights reserved.
162SN/A *
172SN/A * Redistribution and use in source and binary forms, with or without
182SN/A * modification, are permitted provided that the following conditions are
192SN/A * met: redistributions of source code must retain the above copyright
202SN/A * notice, this list of conditions and the following disclaimer;
212SN/A * redistributions in binary form must reproduce the above copyright
222SN/A * notice, this list of conditions and the following disclaimer in the
232SN/A * documentation and/or other materials provided with the distribution;
242SN/A * neither the name of the copyright holders nor the names of its
252SN/A * contributors may be used to endorse or promote products derived from
262SN/A * this software without specific prior written permission.
272SN/A *
282SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
292SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
302SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
312SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
322SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
332SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
342SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
352SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
362SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
372SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
382SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
392665Ssaidi@eecs.umich.edu *
402665Ssaidi@eecs.umich.edu * Authors: Nathan Binkert
412SN/A */
422SN/A
4311793Sbrandon.potter@amd.com#include "base/statistics.hh"
4411793Sbrandon.potter@amd.com
458229Snate@binkert.org#include <fstream>
462SN/A#include <iomanip>
472SN/A#include <list>
482SN/A#include <map>
492SN/A#include <string>
502SN/A
51148SN/A#include "base/callback.hh"
5256SN/A#include "base/cprintf.hh"
535889Snate@binkert.org#include "base/debug.hh"
54441SN/A#include "base/hostinfo.hh"
5512334Sgabeblack@google.com#include "base/logging.hh"
5656SN/A#include "base/str.hh"
57441SN/A#include "base/time.hh"
58433SN/A#include "base/trace.hh"
592SN/A
602SN/Ausing namespace std;
612SN/A
62729SN/Anamespace Stats {
63388SN/A
648243Sbradley.danofsky@amd.comstd::string Info::separatorString = "::";
655887Snate@binkert.org
665887Snate@binkert.org// We wrap these in a function to make sure they're built in time.
675887Snate@binkert.orglist<Info *> &
685887Snate@binkert.orgstatsList()
69388SN/A{
705887Snate@binkert.org    static list<Info *> the_list;
715887Snate@binkert.org    return the_list;
72388SN/A}
73388SN/A
745887Snate@binkert.orgMapType &
755887Snate@binkert.orgstatsMap()
76441SN/A{
775887Snate@binkert.org    static MapType the_map;
785887Snate@binkert.org    return the_map;
79441SN/A}
80441SN/A
81388SN/Avoid
8214205Sandreas.sandberg@arm.comInfoAccess::setInfo(Group *parent, Info *info)
83388SN/A{
8414205Sandreas.sandberg@arm.com    panic_if(statsMap().find(this) != statsMap().end() ||
8514205Sandreas.sandberg@arm.com             _info != nullptr,
8614205Sandreas.sandberg@arm.com             "shouldn't register stat twice!");
8714205Sandreas.sandberg@arm.com
8814205Sandreas.sandberg@arm.com    // New-style stats are reachable through the hierarchy and
8914205Sandreas.sandberg@arm.com    // shouldn't be added to the global lists.
9014205Sandreas.sandberg@arm.com    if (parent) {
9114205Sandreas.sandberg@arm.com        _info = info;
9214205Sandreas.sandberg@arm.com        return;
9314205Sandreas.sandberg@arm.com    }
945887Snate@binkert.org
955887Snate@binkert.org    statsList().push_back(info);
965887Snate@binkert.org
975887Snate@binkert.org#ifndef NDEBUG
985887Snate@binkert.org    pair<MapType::iterator, bool> result =
995887Snate@binkert.org#endif
1005887Snate@binkert.org        statsMap().insert(make_pair(this, info));
1015887Snate@binkert.org    assert(result.second && "this should never fail");
1025887Snate@binkert.org    assert(statsMap().find(this) != statsMap().end());
103388SN/A}
104388SN/A
105388SN/Avoid
1065889Snate@binkert.orgInfoAccess::setParams(const StorageParams *params)
1075889Snate@binkert.org{
1085889Snate@binkert.org    info()->storageParams = params;
1095889Snate@binkert.org}
1105889Snate@binkert.org
1115889Snate@binkert.orgvoid
1125886Snate@binkert.orgInfoAccess::setInit()
113388SN/A{
1146130Snate@binkert.org    info()->flags.set(init);
115388SN/A}
116388SN/A
1175886Snate@binkert.orgInfo *
1185886Snate@binkert.orgInfoAccess::info()
119388SN/A{
12014205Sandreas.sandberg@arm.com    if (_info) {
12114205Sandreas.sandberg@arm.com        // New-style stats
12214205Sandreas.sandberg@arm.com        return _info;
12314205Sandreas.sandberg@arm.com    } else {
12414205Sandreas.sandberg@arm.com        // Legacy stats
12514205Sandreas.sandberg@arm.com        MapType::const_iterator i = statsMap().find(this);
12614205Sandreas.sandberg@arm.com        assert(i != statsMap().end());
12714205Sandreas.sandberg@arm.com        return (*i).second;
12814205Sandreas.sandberg@arm.com    }
129388SN/A}
130388SN/A
1315886Snate@binkert.orgconst Info *
1325886Snate@binkert.orgInfoAccess::info() const
1335886Snate@binkert.org{
13414205Sandreas.sandberg@arm.com    if (_info) {
13514205Sandreas.sandberg@arm.com        // New-style stats
13614205Sandreas.sandberg@arm.com        return _info;
13714205Sandreas.sandberg@arm.com    } else {
13814205Sandreas.sandberg@arm.com        // Legacy stats
13914205Sandreas.sandberg@arm.com        MapType::const_iterator i = statsMap().find(this);
14014205Sandreas.sandberg@arm.com        assert(i != statsMap().end());
14114205Sandreas.sandberg@arm.com        return (*i).second;
14214205Sandreas.sandberg@arm.com    }
1435886Snate@binkert.org}
1445886Snate@binkert.org
1455889Snate@binkert.orgStorageParams::~StorageParams()
1465889Snate@binkert.org{
1475889Snate@binkert.org}
1485889Snate@binkert.org
1496026Snate@binkert.orgNameMapType &
1506026Snate@binkert.orgnameMap()
1516026Snate@binkert.org{
1526026Snate@binkert.org    static NameMapType the_map;
1536026Snate@binkert.org    return the_map;
1546026Snate@binkert.org}
1556026Snate@binkert.org
1565889Snate@binkert.orgint Info::id_count = 0;
1575889Snate@binkert.org
1585889Snate@binkert.orgint debug_break_id = -1;
1595889Snate@binkert.org
1605886Snate@binkert.orgInfo::Info()
1615889Snate@binkert.org    : flags(none), precision(-1), prereq(0), storageParams(NULL)
162582SN/A{
1635889Snate@binkert.org    id = id_count++;
1645889Snate@binkert.org    if (debug_break_id >= 0 and debug_break_id == id)
1658231Snate@binkert.org        Debug::breakpoint();
166582SN/A}
167582SN/A
1685886Snate@binkert.orgInfo::~Info()
169388SN/A{
170388SN/A}
171388SN/A
1728248Snate@binkert.orgbool
1738248Snate@binkert.orgvalidateStatName(const string &name)
1748248Snate@binkert.org{
1758248Snate@binkert.org    if (name.empty())
1768248Snate@binkert.org        return false;
1778248Snate@binkert.org
1788248Snate@binkert.org    vector<string> vec;
1798248Snate@binkert.org    tokenize(vec, name, '.');
1808248Snate@binkert.org    vector<string>::const_iterator item = vec.begin();
1818248Snate@binkert.org    while (item != vec.end()) {
1828248Snate@binkert.org        if (item->empty())
1838248Snate@binkert.org            return false;
1848248Snate@binkert.org
1858248Snate@binkert.org        string::const_iterator c = item->begin();
1868248Snate@binkert.org
1878248Snate@binkert.org        // The first character is different
1888248Snate@binkert.org        if (!isalpha(*c) && *c != '_')
1898248Snate@binkert.org            return false;
1908248Snate@binkert.org
1918248Snate@binkert.org        // The rest of the characters have different rules.
1928248Snate@binkert.org        while (++c != item->end()) {
1938248Snate@binkert.org            if (!isalnum(*c) && *c != '_')
1948248Snate@binkert.org                return false;
1958248Snate@binkert.org        }
1968248Snate@binkert.org
1978248Snate@binkert.org        ++item;
1988248Snate@binkert.org    }
1998248Snate@binkert.org
2008248Snate@binkert.org    return true;
2018248Snate@binkert.org}
2028248Snate@binkert.org
2036026Snate@binkert.orgvoid
2046026Snate@binkert.orgInfo::setName(const string &name)
2056026Snate@binkert.org{
20614266Sandreas.sandberg@arm.com    setName(nullptr, name);
20714266Sandreas.sandberg@arm.com}
20814266Sandreas.sandberg@arm.com
20914266Sandreas.sandberg@arm.comvoid
21014266Sandreas.sandberg@arm.comInfo::setName(const Group *parent, const string &name)
21114266Sandreas.sandberg@arm.com{
2128248Snate@binkert.org    if (!validateStatName(name))
2138248Snate@binkert.org        panic("invalid stat name '%s'", name);
2148248Snate@binkert.org
21514266Sandreas.sandberg@arm.com    // We only register the stat with the nameMap() if we are using
21614266Sandreas.sandberg@arm.com    // old-style stats without a parent group. New-style stats should
21714266Sandreas.sandberg@arm.com    // be unique since their names should correspond to a member
21814266Sandreas.sandberg@arm.com    // variable.
21914266Sandreas.sandberg@arm.com    if (!parent) {
22014266Sandreas.sandberg@arm.com        auto p = nameMap().insert(make_pair(name, this));
2216026Snate@binkert.org
22214266Sandreas.sandberg@arm.com        if (!p.second)
22314266Sandreas.sandberg@arm.com            panic("same statistic name used twice! name=%s\n",
22414266Sandreas.sandberg@arm.com                  name);
2256026Snate@binkert.org    }
2266026Snate@binkert.org
2276026Snate@binkert.org    this->name = name;
2286026Snate@binkert.org}
2296026Snate@binkert.org
2302SN/Abool
2315886Snate@binkert.orgInfo::less(Info *stat1, Info *stat2)
2322SN/A{
233388SN/A    const string &name1 = stat1->name;
234388SN/A    const string &name2 = stat2->name;
2352SN/A
2362SN/A    vector<string> v1;
2372SN/A    vector<string> v2;
2382SN/A
2392SN/A    tokenize(v1, name1, '.');
2402SN/A    tokenize(v2, name2, '.');
2412SN/A
2425599Snate@binkert.org    size_type last = min(v1.size(), v2.size()) - 1;
2435599Snate@binkert.org    for (off_type i = 0; i < last; ++i)
2442SN/A        if (v1[i] != v2[i])
2452SN/A            return v1[i] < v2[i];
2462SN/A
2472SN/A    // Special compare for last element.
2482SN/A    if (v1[last] == v2[last])
2492SN/A        return v1.size() < v2.size();
2502SN/A    else
2512SN/A        return v1[last] < v2[last];
2522SN/A
2532SN/A    return false;
2542SN/A}
2552SN/A
256388SN/Abool
2575886Snate@binkert.orgInfo::baseCheck() const
2582SN/A{
2596000Snate@binkert.org    if (!(flags & Stats::init)) {
260582SN/A#ifdef DEBUG
261695SN/A        cprintf("this is stat number %d\n", id);
262388SN/A#endif
26311681Spowerjg@cs.wisc.edu        panic("Not all stats have been initialized.\n"
26411681Spowerjg@cs.wisc.edu              "You may need to add <ParentClass>::regStats() to a"
26514205Sandreas.sandberg@arm.com              " new SimObject's regStats() function. Name: %s",
26614205Sandreas.sandberg@arm.com              name);
267388SN/A        return false;
268388SN/A    }
2692SN/A
2707462Snate@binkert.org    if ((flags & display) && name.empty()) {
271388SN/A        panic("all printable stats must be named");
272388SN/A        return false;
273388SN/A    }
2742SN/A
275388SN/A    return true;
2762SN/A}
2772SN/A
2786001Snate@binkert.orgvoid
2796001Snate@binkert.orgInfo::enable()
2806001Snate@binkert.org{
2816001Snate@binkert.org}
2826001Snate@binkert.org
2836001Snate@binkert.orgvoid
2846128Snate@binkert.orgVectorInfo::enable()
2856001Snate@binkert.org{
2866001Snate@binkert.org    size_type s = size();
2876001Snate@binkert.org    if (subnames.size() < s)
2886001Snate@binkert.org        subnames.resize(s);
2896001Snate@binkert.org    if (subdescs.size() < s)
2906001Snate@binkert.org        subdescs.resize(s);
2916001Snate@binkert.org}
2926001Snate@binkert.org
2936001Snate@binkert.orgvoid
2946128Snate@binkert.orgVectorDistInfo::enable()
2956001Snate@binkert.org{
2966001Snate@binkert.org    size_type s = size();
2976001Snate@binkert.org    if (subnames.size() < s)
2986001Snate@binkert.org        subnames.resize(s);
2996001Snate@binkert.org    if (subdescs.size() < s)
3006001Snate@binkert.org        subdescs.resize(s);
3016001Snate@binkert.org}
3026001Snate@binkert.org
3036001Snate@binkert.orgvoid
3046128Snate@binkert.orgVector2dInfo::enable()
3056001Snate@binkert.org{
3066001Snate@binkert.org    if (subnames.size() < x)
3076001Snate@binkert.org        subnames.resize(x);
3086001Snate@binkert.org    if (subdescs.size() < x)
3096001Snate@binkert.org        subdescs.resize(x);
3106001Snate@binkert.org    if (y_subnames.size() < y)
3116001Snate@binkert.org        y_subnames.resize(y);
3126001Snate@binkert.org}
313695SN/A
3147831Snate@binkert.orgvoid
3157831Snate@binkert.orgHistStor::grow_out()
3167831Snate@binkert.org{
3177831Snate@binkert.org    int size = cvec.size();
3187831Snate@binkert.org    int zero = size / 2; // round down!
3197831Snate@binkert.org    int top_half = zero + (size - zero + 1) / 2; // round up!
3207831Snate@binkert.org    int bottom_half = (size - zero) / 2; // round down!
3217831Snate@binkert.org
3227831Snate@binkert.org    // grow down
3237831Snate@binkert.org    int low_pair = zero - 1;
3247831Snate@binkert.org    for (int i = zero - 1; i >= bottom_half; i--) {
3257831Snate@binkert.org        cvec[i] = cvec[low_pair];
3267831Snate@binkert.org        if (low_pair - 1 >= 0)
3277831Snate@binkert.org            cvec[i] += cvec[low_pair - 1];
3287831Snate@binkert.org        low_pair -= 2;
3297831Snate@binkert.org    }
3307831Snate@binkert.org    assert(low_pair == 0 || low_pair == -1 || low_pair == -2);
3317831Snate@binkert.org
3327831Snate@binkert.org    for (int i = bottom_half - 1; i >= 0; i--)
3337831Snate@binkert.org        cvec[i] = Counter();
3347831Snate@binkert.org
3357831Snate@binkert.org    // grow up
3367831Snate@binkert.org    int high_pair = zero;
3377831Snate@binkert.org    for (int i = zero; i < top_half; i++) {
3387831Snate@binkert.org        cvec[i] = cvec[high_pair];
3397831Snate@binkert.org        if (high_pair + 1 < size)
3407831Snate@binkert.org            cvec[i] += cvec[high_pair + 1];
3417831Snate@binkert.org        high_pair += 2;
3427831Snate@binkert.org    }
3437831Snate@binkert.org    assert(high_pair == size || high_pair == size + 1);
3447831Snate@binkert.org
3457831Snate@binkert.org    for (int i = top_half; i < size; i++)
3467831Snate@binkert.org        cvec[i] = Counter();
3477831Snate@binkert.org
3487831Snate@binkert.org    max_bucket *= 2;
3497831Snate@binkert.org    min_bucket *= 2;
3507831Snate@binkert.org    bucket_size *= 2;
3517831Snate@binkert.org}
3527831Snate@binkert.org
3537831Snate@binkert.orgvoid
3547831Snate@binkert.orgHistStor::grow_convert()
3557831Snate@binkert.org{
3567831Snate@binkert.org    int size = cvec.size();
3577831Snate@binkert.org    int half = (size + 1) / 2; // round up!
3587831Snate@binkert.org    //bool even = (size & 1) == 0;
3597831Snate@binkert.org
3607831Snate@binkert.org    int pair = size - 1;
3617831Snate@binkert.org    for (int i = size - 1; i >= half; --i) {
3627831Snate@binkert.org        cvec[i] = cvec[pair];
3637831Snate@binkert.org        if (pair - 1 >= 0)
3647831Snate@binkert.org            cvec[i] += cvec[pair - 1];
3657831Snate@binkert.org        pair -= 2;
3667831Snate@binkert.org    }
3677831Snate@binkert.org
3687831Snate@binkert.org    for (int i = half - 1; i >= 0; i--)
3697831Snate@binkert.org        cvec[i] = Counter();
3707831Snate@binkert.org
3717831Snate@binkert.org    min_bucket = -max_bucket;// - (even ? bucket_size : 0);
3727831Snate@binkert.org    bucket_size *= 2;
3737831Snate@binkert.org}
3747831Snate@binkert.org
3757831Snate@binkert.orgvoid
3767831Snate@binkert.orgHistStor::grow_up()
3777831Snate@binkert.org{
3787831Snate@binkert.org    int size = cvec.size();
3797831Snate@binkert.org    int half = (size + 1) / 2; // round up!
3807831Snate@binkert.org
3817831Snate@binkert.org    int pair = 0;
3827831Snate@binkert.org    for (int i = 0; i < half; i++) {
3837831Snate@binkert.org        cvec[i] = cvec[pair];
3847831Snate@binkert.org        if (pair + 1 < size)
3857831Snate@binkert.org            cvec[i] += cvec[pair + 1];
3867831Snate@binkert.org        pair += 2;
3877831Snate@binkert.org    }
3887831Snate@binkert.org    assert(pair == size || pair == size + 1);
3897831Snate@binkert.org
3907831Snate@binkert.org    for (int i = half; i < size; i++)
3917831Snate@binkert.org        cvec[i] = Counter();
3927831Snate@binkert.org
3937831Snate@binkert.org    max_bucket *= 2;
3947831Snate@binkert.org    bucket_size *= 2;
3957831Snate@binkert.org}
3967831Snate@binkert.org
39710011Snilay@cs.wisc.eduvoid
39810011Snilay@cs.wisc.eduHistStor::add(HistStor *hs)
39910011Snilay@cs.wisc.edu{
40010011Snilay@cs.wisc.edu    int b_size = hs->size();
40110011Snilay@cs.wisc.edu    assert(size() == b_size);
40210011Snilay@cs.wisc.edu    assert(min_bucket == hs->min_bucket);
40310011Snilay@cs.wisc.edu
40410011Snilay@cs.wisc.edu    sum += hs->sum;
40510011Snilay@cs.wisc.edu    logs += hs->logs;
40610011Snilay@cs.wisc.edu    squares += hs->squares;
40710011Snilay@cs.wisc.edu    samples += hs->samples;
40810011Snilay@cs.wisc.edu
40911321Ssteve.reinhardt@amd.com    while (bucket_size > hs->bucket_size)
41010011Snilay@cs.wisc.edu        hs->grow_up();
41111321Ssteve.reinhardt@amd.com    while (bucket_size < hs->bucket_size)
41210011Snilay@cs.wisc.edu        grow_up();
41310011Snilay@cs.wisc.edu
41410011Snilay@cs.wisc.edu    for (uint32_t i = 0; i < b_size; i++)
41510011Snilay@cs.wisc.edu        cvec[i] += hs->cvec[i];
41610011Snilay@cs.wisc.edu}
41710011Snilay@cs.wisc.edu
41814205Sandreas.sandberg@arm.comFormula::Formula(Group *parent, const char *name, const char *desc)
41914205Sandreas.sandberg@arm.com    : DataWrapVec<Formula, FormulaInfoProxy>(parent, name, desc)
42014205Sandreas.sandberg@arm.com
421388SN/A{
422388SN/A}
423388SN/A
42414205Sandreas.sandberg@arm.com
42514205Sandreas.sandberg@arm.com
42614205Sandreas.sandberg@arm.comFormula::Formula(Group *parent, const char *name, const char *desc,
42714205Sandreas.sandberg@arm.com                 const Temp &r)
42814205Sandreas.sandberg@arm.com    : DataWrapVec<Formula, FormulaInfoProxy>(parent, name, desc)
429388SN/A{
43014205Sandreas.sandberg@arm.com    *this = r;
431388SN/A}
432388SN/A
433388SN/Aconst Formula &
43414205Sandreas.sandberg@arm.comFormula::operator=(const Temp &r)
435388SN/A{
436388SN/A    assert(!root && "Can't change formulas");
43710491Sandreas.hansson@arm.com    root = r.getNodePtr();
4387461Snate@binkert.org    setInit();
439388SN/A    assert(size());
440388SN/A    return *this;
441388SN/A}
442388SN/A
443388SN/Aconst Formula &
444388SN/AFormula::operator+=(Temp r)
445388SN/A{
446388SN/A    if (root)
447695SN/A        root = NodePtr(new BinaryNode<std::plus<Result> >(root, r));
4487461Snate@binkert.org    else {
44910491Sandreas.hansson@arm.com        root = r.getNodePtr();
4507461Snate@binkert.org        setInit();
4517461Snate@binkert.org    }
4527461Snate@binkert.org
453388SN/A    assert(size());
454388SN/A    return *this;
455388SN/A}
456388SN/A
4579857Snilay@cs.wisc.educonst Formula &
4589857Snilay@cs.wisc.eduFormula::operator/=(Temp r)
4599857Snilay@cs.wisc.edu{
4609857Snilay@cs.wisc.edu    assert (root);
4619857Snilay@cs.wisc.edu    root = NodePtr(new BinaryNode<std::divides<Result> >(root, r));
4629857Snilay@cs.wisc.edu
4639857Snilay@cs.wisc.edu    assert(size());
4649857Snilay@cs.wisc.edu    return *this;
4659857Snilay@cs.wisc.edu}
4669857Snilay@cs.wisc.edu
46714205Sandreas.sandberg@arm.com
468142SN/Avoid
4696000Snate@binkert.orgFormula::result(VResult &vec) const
4706000Snate@binkert.org{
4716000Snate@binkert.org    if (root)
4726000Snate@binkert.org        vec = root->result();
4736000Snate@binkert.org}
4746000Snate@binkert.org
4756000Snate@binkert.orgResult
4766000Snate@binkert.orgFormula::total() const
4776000Snate@binkert.org{
4786000Snate@binkert.org    return root ? root->total() : 0.0;
4796000Snate@binkert.org}
4806000Snate@binkert.org
4816000Snate@binkert.orgsize_type
4826000Snate@binkert.orgFormula::size() const
4836000Snate@binkert.org{
4846000Snate@binkert.org    if (!root)
4856000Snate@binkert.org        return 0;
4866000Snate@binkert.org    else
4876000Snate@binkert.org        return root->size();
4886000Snate@binkert.org}
4896000Snate@binkert.org
4906000Snate@binkert.orgvoid
4916000Snate@binkert.orgFormula::reset()
4926000Snate@binkert.org{
4936000Snate@binkert.org}
4946000Snate@binkert.org
4956000Snate@binkert.orgbool
4966000Snate@binkert.orgFormula::zero() const
4976000Snate@binkert.org{
4986000Snate@binkert.org    VResult vec;
4996000Snate@binkert.org    result(vec);
5006227Snate@binkert.org    for (VResult::size_type i = 0; i < vec.size(); ++i)
5016000Snate@binkert.org        if (vec[i] != 0.0)
5026000Snate@binkert.org            return false;
5036000Snate@binkert.org    return true;
5046000Snate@binkert.org}
5056000Snate@binkert.org
5066000Snate@binkert.orgstring
5076000Snate@binkert.orgFormula::str() const
5086000Snate@binkert.org{
5096000Snate@binkert.org    return root ? root->str() : "";
5106000Snate@binkert.org}
5116000Snate@binkert.org
51210453SAndrew.Bardsley@arm.comHandler resetHandler = NULL;
51310453SAndrew.Bardsley@arm.comHandler dumpHandler = NULL;
51410453SAndrew.Bardsley@arm.com
51510453SAndrew.Bardsley@arm.comvoid
51610453SAndrew.Bardsley@arm.comregisterHandlers(Handler reset_handler, Handler dump_handler)
51710453SAndrew.Bardsley@arm.com{
51810453SAndrew.Bardsley@arm.com    resetHandler = reset_handler;
51910453SAndrew.Bardsley@arm.com    dumpHandler = dump_handler;
52010453SAndrew.Bardsley@arm.com}
52110453SAndrew.Bardsley@arm.com
5229042SMitchell.Hayenga@ARM.comCallbackQueue dumpQueue;
523695SN/ACallbackQueue resetQueue;
5242SN/A
525456SN/Avoid
52610453SAndrew.Bardsley@arm.comprocessResetQueue()
52710453SAndrew.Bardsley@arm.com{
52810453SAndrew.Bardsley@arm.com    resetQueue.process();
52910453SAndrew.Bardsley@arm.com}
53010453SAndrew.Bardsley@arm.com
53110453SAndrew.Bardsley@arm.comvoid
53210453SAndrew.Bardsley@arm.comprocessDumpQueue()
53310453SAndrew.Bardsley@arm.com{
53410453SAndrew.Bardsley@arm.com    dumpQueue.process();
53510453SAndrew.Bardsley@arm.com}
53610453SAndrew.Bardsley@arm.com
53710453SAndrew.Bardsley@arm.comvoid
538394SN/AregisterResetCallback(Callback *cb)
539148SN/A{
540148SN/A    resetQueue.add(cb);
541148SN/A}
542148SN/A
5438986SAli.Saidi@ARM.combool _enabled = false;
5448986SAli.Saidi@ARM.com
5458986SAli.Saidi@ARM.combool
5468986SAli.Saidi@ARM.comenabled()
5478986SAli.Saidi@ARM.com{
5488986SAli.Saidi@ARM.com    return _enabled;
5498986SAli.Saidi@ARM.com}
5508986SAli.Saidi@ARM.com
5518986SAli.Saidi@ARM.comvoid
5528986SAli.Saidi@ARM.comenable()
5538986SAli.Saidi@ARM.com{
5548986SAli.Saidi@ARM.com    if (_enabled)
5558986SAli.Saidi@ARM.com        fatal("Stats are already enabled");
5568986SAli.Saidi@ARM.com
5578986SAli.Saidi@ARM.com    _enabled = true;
5588986SAli.Saidi@ARM.com}
5598986SAli.Saidi@ARM.com
5609042SMitchell.Hayenga@ARM.comvoid
56110453SAndrew.Bardsley@arm.comdump()
56210453SAndrew.Bardsley@arm.com{
56310453SAndrew.Bardsley@arm.com    if (dumpHandler)
56410453SAndrew.Bardsley@arm.com        dumpHandler();
56510453SAndrew.Bardsley@arm.com    else
56610453SAndrew.Bardsley@arm.com        fatal("No registered Stats::dump handler");
56710453SAndrew.Bardsley@arm.com}
56810453SAndrew.Bardsley@arm.com
56910453SAndrew.Bardsley@arm.comvoid
57010453SAndrew.Bardsley@arm.comreset()
57110453SAndrew.Bardsley@arm.com{
57210453SAndrew.Bardsley@arm.com    if (resetHandler)
57310453SAndrew.Bardsley@arm.com        resetHandler();
57410453SAndrew.Bardsley@arm.com    else
57510453SAndrew.Bardsley@arm.com        fatal("No registered Stats::reset handler");
57610453SAndrew.Bardsley@arm.com}
57710453SAndrew.Bardsley@arm.com
57810453SAndrew.Bardsley@arm.comvoid
5799042SMitchell.Hayenga@ARM.comregisterDumpCallback(Callback *cb)
5809042SMitchell.Hayenga@ARM.com{
5819042SMitchell.Hayenga@ARM.com    dumpQueue.add(cb);
5829042SMitchell.Hayenga@ARM.com}
5839042SMitchell.Hayenga@ARM.com
5847811Ssteve.reinhardt@amd.com} // namespace Stats
5858296Snate@binkert.org
5868296Snate@binkert.orgvoid
5878296Snate@binkert.orgdebugDumpStats()
5888296Snate@binkert.org{
5898296Snate@binkert.org    Stats::dump();
5908296Snate@binkert.org}
591