1695SN/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) 2004-2005 The Regents of The University of Michigan
15695SN/A * All rights reserved.
16695SN/A *
17695SN/A * Redistribution and use in source and binary forms, with or without
18695SN/A * modification, are permitted provided that the following conditions are
19695SN/A * met: redistributions of source code must retain the above copyright
20695SN/A * notice, this list of conditions and the following disclaimer;
21695SN/A * redistributions in binary form must reproduce the above copyright
22695SN/A * notice, this list of conditions and the following disclaimer in the
23695SN/A * documentation and/or other materials provided with the distribution;
24695SN/A * neither the name of the copyright holders nor the names of its
25695SN/A * contributors may be used to endorse or promote products derived from
26695SN/A * this software without specific prior written permission.
27695SN/A *
28695SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29695SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30695SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31695SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32695SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33695SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34695SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35695SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36695SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37695SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38695SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
392665Ssaidi@eecs.umich.edu *
402665Ssaidi@eecs.umich.edu * Authors: Nathan Binkert
41695SN/A */
42695SN/A
43873SN/A#if defined(__APPLE__)
44873SN/A#define _GLIBCPP_USE_C99 1
45873SN/A#endif
46873SN/A
473918Ssaidi@eecs.umich.edu#if defined(__sun)
4811793Sbrandon.potter@amd.com#include <cmath>
4911793Sbrandon.potter@amd.com
503918Ssaidi@eecs.umich.edu#endif
513918Ssaidi@eecs.umich.edu
526129Snate@binkert.org#include <cassert>
5311793Sbrandon.potter@amd.com
546129Snate@binkert.org#ifdef __SUNPRO_CC
5511793Sbrandon.potter@amd.com#include <cmath>
5611793Sbrandon.potter@amd.com
576129Snate@binkert.org#endif
5811793Sbrandon.potter@amd.com#include "base/stats/text.hh"
5911793Sbrandon.potter@amd.com
606129Snate@binkert.org#include <cmath>
618229Snate@binkert.org#include <fstream>
62695SN/A#include <iostream>
632621SN/A#include <sstream>
64695SN/A#include <string>
65695SN/A
666129Snate@binkert.org#include "base/cast.hh"
6712334Sgabeblack@google.com#include "base/logging.hh"
6811793Sbrandon.potter@amd.com#include "base/stats/info.hh"
696129Snate@binkert.org#include "base/str.hh"
70695SN/A
71695SN/Ausing namespace std;
72695SN/A
73695SN/A#ifndef NAN
74695SN/Afloat __nan();
75695SN/A/** Define Not a number. */
76695SN/A#define NAN (__nan())
77695SN/A/** Need to define __nan() */
78695SN/A#define __M5_NAN
79695SN/A#endif
80695SN/A
81695SN/A#ifdef __M5_NAN
82695SN/Afloat
83695SN/A__nan()
84695SN/A{
85695SN/A    union {
86695SN/A        uint32_t ui;
87695SN/A        float f;
88695SN/A    } nan;
89695SN/A
90695SN/A    nan.ui = 0x7fc00000;
91695SN/A    return nan.f;
92695SN/A}
93695SN/A#endif
94695SN/A
95729SN/Anamespace Stats {
96695SN/A
976129Snate@binkert.orgstd::list<Info *> &statsList();
986129Snate@binkert.org
99695SN/AText::Text()
1006126Snate@binkert.org    : mystream(false), stream(NULL), descriptions(false)
101695SN/A{
102695SN/A}
103695SN/A
104695SN/AText::Text(std::ostream &stream)
1056126Snate@binkert.org    : mystream(false), stream(NULL), descriptions(false)
106695SN/A{
107695SN/A    open(stream);
108695SN/A}
109695SN/A
110695SN/AText::Text(const std::string &file)
1116126Snate@binkert.org    : mystream(false), stream(NULL), descriptions(false)
112695SN/A{
113695SN/A    open(file);
114695SN/A}
115695SN/A
116695SN/A
117695SN/AText::~Text()
118695SN/A{
119695SN/A    if (mystream) {
120695SN/A        assert(stream);
121695SN/A        delete stream;
122695SN/A    }
123695SN/A}
124695SN/A
125695SN/Avoid
126695SN/AText::open(std::ostream &_stream)
127695SN/A{
128695SN/A    if (stream)
129695SN/A        panic("stream already set!");
130695SN/A
131695SN/A    mystream = false;
132695SN/A    stream = &_stream;
1335581Ssaidi@eecs.umich.edu    if (!valid())
1345581Ssaidi@eecs.umich.edu        fatal("Unable to open output stream for writing\n");
135695SN/A}
136695SN/A
137695SN/Avoid
138695SN/AText::open(const std::string &file)
139695SN/A{
140695SN/A    if (stream)
141695SN/A        panic("stream already set!");
142695SN/A
143695SN/A    mystream = true;
144695SN/A    stream = new ofstream(file.c_str(), ios::trunc);
1455581Ssaidi@eecs.umich.edu    if (!valid())
1465581Ssaidi@eecs.umich.edu        fatal("Unable to open statistics file for writing\n");
147695SN/A}
148695SN/A
149695SN/Abool
150695SN/AText::valid() const
151695SN/A{
1525581Ssaidi@eecs.umich.edu    return stream != NULL && stream->good();
153695SN/A}
154695SN/A
155695SN/Avoid
1568296Snate@binkert.orgText::begin()
157695SN/A{
158695SN/A    ccprintf(*stream, "\n---------- Begin Simulation Statistics ----------\n");
1598296Snate@binkert.org}
1608296Snate@binkert.org
1618296Snate@binkert.orgvoid
1628296Snate@binkert.orgText::end()
1638296Snate@binkert.org{
164695SN/A    ccprintf(*stream, "\n---------- End Simulation Statistics   ----------\n");
165695SN/A    stream->flush();
166695SN/A}
167695SN/A
16814205Sandreas.sandberg@arm.comstd::string
16914205Sandreas.sandberg@arm.comText::statName(const std::string &name) const
17014205Sandreas.sandberg@arm.com{
17114205Sandreas.sandberg@arm.com    if (path.empty())
17214205Sandreas.sandberg@arm.com        return name;
17314205Sandreas.sandberg@arm.com    else
17414205Sandreas.sandberg@arm.com        return csprintf("%s.%s", path.top(), name);
17514205Sandreas.sandberg@arm.com}
17614205Sandreas.sandberg@arm.com
17714205Sandreas.sandberg@arm.comvoid
17814205Sandreas.sandberg@arm.comText::beginGroup(const char *name)
17914205Sandreas.sandberg@arm.com{
18014205Sandreas.sandberg@arm.com    if (path.empty()) {
18114205Sandreas.sandberg@arm.com        path.push(name);
18214205Sandreas.sandberg@arm.com    } else {
18314205Sandreas.sandberg@arm.com        path.push(csprintf("%s.%s", path.top(), name));
18414205Sandreas.sandberg@arm.com    }
18514205Sandreas.sandberg@arm.com}
18614205Sandreas.sandberg@arm.com
18714205Sandreas.sandberg@arm.comvoid
18814205Sandreas.sandberg@arm.comText::endGroup()
18914205Sandreas.sandberg@arm.com{
19014205Sandreas.sandberg@arm.com    assert(!path.empty());
19114205Sandreas.sandberg@arm.com    path.pop();
19214205Sandreas.sandberg@arm.com}
19314205Sandreas.sandberg@arm.com
194695SN/Abool
1955886Snate@binkert.orgText::noOutput(const Info &info)
196695SN/A{
1977462Snate@binkert.org    if (!info.flags.isSet(display))
198695SN/A        return true;
199695SN/A
2005886Snate@binkert.org    if (info.prereq && info.prereq->zero())
201695SN/A        return true;
202695SN/A
203695SN/A    return false;
204695SN/A}
205695SN/A
206695SN/Astring
2076126Snate@binkert.orgValueToString(Result value, int precision)
208695SN/A{
209695SN/A    stringstream val;
210695SN/A
2118946Sandreas.hansson@arm.com    if (!std::isnan(value)) {
212695SN/A        if (precision != -1)
213695SN/A            val.precision(precision);
214695SN/A        else if (value == rint(value))
215695SN/A            val.precision(0);
216695SN/A
217695SN/A        val.unsetf(ios::showpoint);
218695SN/A        val.setf(ios::fixed);
219695SN/A        val << value;
220695SN/A    } else {
2218982Snate@binkert.org        val << "nan";
222695SN/A    }
223695SN/A
224695SN/A    return val.str();
225695SN/A}
226695SN/A
227695SN/Astruct ScalarPrint
228695SN/A{
229695SN/A    Result value;
230695SN/A    string name;
231695SN/A    string desc;
2326130Snate@binkert.org    Flags flags;
233695SN/A    bool descriptions;
234695SN/A    int precision;
235695SN/A    Result pdf;
236695SN/A    Result cdf;
237695SN/A
2386211Snate@binkert.org    void update(Result val, Result total);
2399743Snilay@cs.wisc.edu    void operator()(ostream &stream, bool oneLine = false) const;
240695SN/A};
241695SN/A
242695SN/Avoid
2436211Snate@binkert.orgScalarPrint::update(Result val, Result total)
2446211Snate@binkert.org{
2456211Snate@binkert.org    value = val;
2466211Snate@binkert.org    if (total) {
2476211Snate@binkert.org        pdf = val / total;
2486211Snate@binkert.org        cdf += pdf;
2496211Snate@binkert.org    }
2506211Snate@binkert.org}
2516211Snate@binkert.org
2526211Snate@binkert.orgvoid
2539743Snilay@cs.wisc.eduScalarPrint::operator()(ostream &stream, bool oneLine) const
254695SN/A{
25510011Snilay@cs.wisc.edu    if ((flags.isSet(nozero) && (!oneLine) && value == 0.0) ||
2568946Sandreas.hansson@arm.com        (flags.isSet(nonan) && std::isnan(value)))
257695SN/A        return;
258695SN/A
259695SN/A    stringstream pdfstr, cdfstr;
260695SN/A
2618946Sandreas.hansson@arm.com    if (!std::isnan(pdf))
262695SN/A        ccprintf(pdfstr, "%.2f%%", pdf * 100.0);
263695SN/A
2648946Sandreas.hansson@arm.com    if (!std::isnan(cdf))
265695SN/A        ccprintf(cdfstr, "%.2f%%", cdf * 100.0);
266695SN/A
2679743Snilay@cs.wisc.edu    if (oneLine) {
2689743Snilay@cs.wisc.edu        ccprintf(stream, " |%12s %10s %10s",
2699743Snilay@cs.wisc.edu                 ValueToString(value, precision), pdfstr.str(), cdfstr.str());
2709743Snilay@cs.wisc.edu    } else {
2719743Snilay@cs.wisc.edu        ccprintf(stream, "%-40s %12s %10s %10s", name,
2729743Snilay@cs.wisc.edu                 ValueToString(value, precision), pdfstr.str(), cdfstr.str());
273695SN/A
2749743Snilay@cs.wisc.edu        if (descriptions) {
2759743Snilay@cs.wisc.edu            if (!desc.empty())
2769743Snilay@cs.wisc.edu                ccprintf(stream, " # %s", desc);
2779743Snilay@cs.wisc.edu        }
2789743Snilay@cs.wisc.edu        stream << endl;
279695SN/A    }
280695SN/A}
281695SN/A
282695SN/Astruct VectorPrint
283695SN/A{
284695SN/A    string name;
2858243Sbradley.danofsky@amd.com    string separatorString;
286695SN/A    string desc;
287695SN/A    vector<string> subnames;
288695SN/A    vector<string> subdescs;
2896130Snate@binkert.org    Flags flags;
290695SN/A    bool descriptions;
291695SN/A    int precision;
292695SN/A    VResult vec;
293695SN/A    Result total;
2949839Sandreas.hansson@arm.com    bool forceSubnames;
295695SN/A
296695SN/A    void operator()(ostream &stream) const;
297695SN/A};
298695SN/A
299695SN/Avoid
300695SN/AVectorPrint::operator()(std::ostream &stream) const
301695SN/A{
3025599Snate@binkert.org    size_type _size = vec.size();
303695SN/A    Result _total = 0.0;
304695SN/A
3056130Snate@binkert.org    if (flags.isSet(pdf | cdf)) {
3065599Snate@binkert.org        for (off_type i = 0; i < _size; ++i) {
307695SN/A            _total += vec[i];
308695SN/A        }
309695SN/A    }
310695SN/A
3118243Sbradley.danofsky@amd.com    string base = name + separatorString;
312695SN/A
313695SN/A    ScalarPrint print;
314695SN/A    print.name = name;
315695SN/A    print.desc = desc;
316695SN/A    print.precision = precision;
317695SN/A    print.descriptions = descriptions;
318695SN/A    print.flags = flags;
3196211Snate@binkert.org    print.pdf = _total ? 0.0 : NAN;
3206211Snate@binkert.org    print.cdf = _total ? 0.0 : NAN;
321695SN/A
322695SN/A    bool havesub = !subnames.empty();
323695SN/A
324695SN/A    if (_size == 1) {
3259828Ssascha.bischoff@arm.com        // If forceSubnames is set, get the first subname (or index in
3269828Ssascha.bischoff@arm.com        // the case where there are no subnames) and append it to the
3279828Ssascha.bischoff@arm.com        // base name.
3289828Ssascha.bischoff@arm.com        if (forceSubnames)
32910386Sandreas.hansson@arm.com            print.name = base + (havesub ? subnames[0] : std::to_string(0));
330695SN/A        print.value = vec[0];
331695SN/A        print(stream);
3326126Snate@binkert.org        return;
3336126Snate@binkert.org    }
334695SN/A
3359743Snilay@cs.wisc.edu    if ((!flags.isSet(nozero)) || (total != 0)) {
3369743Snilay@cs.wisc.edu        if (flags.isSet(oneline)) {
3379743Snilay@cs.wisc.edu            ccprintf(stream, "%-40s", name);
3389743Snilay@cs.wisc.edu            print.flags = print.flags & (~nozero);
3399743Snilay@cs.wisc.edu        }
340695SN/A
3419743Snilay@cs.wisc.edu        for (off_type i = 0; i < _size; ++i) {
3429743Snilay@cs.wisc.edu            if (havesub && (i >= subnames.size() || subnames[i].empty()))
3439743Snilay@cs.wisc.edu                continue;
344695SN/A
34510386Sandreas.hansson@arm.com            print.name = base + (havesub ? subnames[i] : std::to_string(i));
3469743Snilay@cs.wisc.edu            print.desc = subdescs.empty() ? desc : subdescs[i];
3479743Snilay@cs.wisc.edu
3489743Snilay@cs.wisc.edu            print.update(vec[i], _total);
3499743Snilay@cs.wisc.edu            print(stream, flags.isSet(oneline));
3509743Snilay@cs.wisc.edu        }
3519743Snilay@cs.wisc.edu
3529743Snilay@cs.wisc.edu        if (flags.isSet(oneline)) {
3539743Snilay@cs.wisc.edu            if (descriptions) {
3549743Snilay@cs.wisc.edu                if (!desc.empty())
3559743Snilay@cs.wisc.edu                    ccprintf(stream, " # %s", desc);
3569743Snilay@cs.wisc.edu            }
3579743Snilay@cs.wisc.edu            stream << endl;
3589743Snilay@cs.wisc.edu        }
3596126Snate@binkert.org    }
360695SN/A
3616130Snate@binkert.org    if (flags.isSet(::Stats::total)) {
3626126Snate@binkert.org        print.pdf = NAN;
3636126Snate@binkert.org        print.cdf = NAN;
3646126Snate@binkert.org        print.name = base + "total";
3656126Snate@binkert.org        print.desc = desc;
3666126Snate@binkert.org        print.value = total;
3676126Snate@binkert.org        print(stream);
368695SN/A    }
369695SN/A}
370695SN/A
371695SN/Astruct DistPrint
372695SN/A{
373695SN/A    string name;
3748243Sbradley.danofsky@amd.com    string separatorString;
375695SN/A    string desc;
3766130Snate@binkert.org    Flags flags;
377695SN/A    bool descriptions;
378695SN/A    int precision;
379695SN/A
3806004Snate@binkert.org    const DistData &data;
3816004Snate@binkert.org
3826128Snate@binkert.org    DistPrint(const Text *text, const DistInfo &info);
3836128Snate@binkert.org    DistPrint(const Text *text, const VectorDistInfo &info, int i);
3847505Snate@binkert.org    void init(const Text *text, const Info &info);
385695SN/A    void operator()(ostream &stream) const;
386695SN/A};
387695SN/A
3886128Snate@binkert.orgDistPrint::DistPrint(const Text *text, const DistInfo &info)
3896004Snate@binkert.org    : data(info.data)
3906004Snate@binkert.org{
3917505Snate@binkert.org    init(text, info);
3926004Snate@binkert.org}
3936004Snate@binkert.org
3946128Snate@binkert.orgDistPrint::DistPrint(const Text *text, const VectorDistInfo &info, int i)
3956004Snate@binkert.org    : data(info.data[i])
3966004Snate@binkert.org{
3977505Snate@binkert.org    init(text, info);
3986004Snate@binkert.org
3996004Snate@binkert.org    name = info.name + "_" +
40010386Sandreas.hansson@arm.com        (info.subnames[i].empty() ? (std::to_string(i)) : info.subnames[i]);
4016004Snate@binkert.org
4026004Snate@binkert.org    if (!info.subdescs[i].empty())
4036004Snate@binkert.org        desc = info.subdescs[i];
4046004Snate@binkert.org}
4056004Snate@binkert.org
4066004Snate@binkert.orgvoid
4077505Snate@binkert.orgDistPrint::init(const Text *text, const Info &info)
4086004Snate@binkert.org{
40914205Sandreas.sandberg@arm.com    name = text->statName(info.name);
4108243Sbradley.danofsky@amd.com    separatorString = info.separatorString;
4116004Snate@binkert.org    desc = info.desc;
4126004Snate@binkert.org    flags = info.flags;
4136004Snate@binkert.org    precision = info.precision;
4146125Snate@binkert.org    descriptions = text->descriptions;
4156004Snate@binkert.org}
4166004Snate@binkert.org
417695SN/Avoid
418695SN/ADistPrint::operator()(ostream &stream) const
419695SN/A{
42010011Snilay@cs.wisc.edu    if (flags.isSet(nozero) && data.samples == 0) return;
4218243Sbradley.danofsky@amd.com    string base = name + separatorString;
422695SN/A
423695SN/A    ScalarPrint print;
4246211Snate@binkert.org    print.precision = precision;
425695SN/A    print.flags = flags;
426695SN/A    print.descriptions = descriptions;
4276211Snate@binkert.org    print.desc = desc;
428695SN/A    print.pdf = NAN;
429695SN/A    print.cdf = NAN;
430695SN/A
43110011Snilay@cs.wisc.edu    if (flags.isSet(oneline)) {
43210011Snilay@cs.wisc.edu        print.name = base + "bucket_size";
43310011Snilay@cs.wisc.edu        print.value = data.bucket_size;
43410011Snilay@cs.wisc.edu        print(stream);
43510011Snilay@cs.wisc.edu
43610011Snilay@cs.wisc.edu        print.name = base + "min_bucket";
43710011Snilay@cs.wisc.edu        print.value = data.min;
43810011Snilay@cs.wisc.edu        print(stream);
43910011Snilay@cs.wisc.edu
44010011Snilay@cs.wisc.edu        print.name = base + "max_bucket";
44110011Snilay@cs.wisc.edu        print.value = data.max;
44210011Snilay@cs.wisc.edu        print(stream);
44310011Snilay@cs.wisc.edu    }
44410011Snilay@cs.wisc.edu
445695SN/A    print.name = base + "samples";
4466004Snate@binkert.org    print.value = data.samples;
447695SN/A    print(stream);
448695SN/A
4496211Snate@binkert.org    print.name = base + "mean";
4506211Snate@binkert.org    print.value = data.samples ? data.sum / data.samples : NAN;
451695SN/A    print(stream);
452695SN/A
4538666SPrakash.Ramrakhyani@arm.com    if (data.type == Hist) {
4548666SPrakash.Ramrakhyani@arm.com        print.name = base + "gmean";
4558666SPrakash.Ramrakhyani@arm.com        print.value = data.samples ? exp(data.logs / data.samples) : NAN;
4568666SPrakash.Ramrakhyani@arm.com        print(stream);
4578666SPrakash.Ramrakhyani@arm.com    }
4588666SPrakash.Ramrakhyani@arm.com
4596211Snate@binkert.org    Result stdev = NAN;
4606211Snate@binkert.org    if (data.samples)
4616211Snate@binkert.org        stdev = sqrt((data.samples * data.squares - data.sum * data.sum) /
4626211Snate@binkert.org                     (data.samples * (data.samples - 1.0)));
4636211Snate@binkert.org    print.name = base + "stdev";
4646211Snate@binkert.org    print.value = stdev;
4656211Snate@binkert.org    print(stream);
4666211Snate@binkert.org
4677505Snate@binkert.org    if (data.type == Deviation)
4686211Snate@binkert.org        return;
4696211Snate@binkert.org
4707505Snate@binkert.org    size_t size = data.cvec.size();
4716211Snate@binkert.org
4726211Snate@binkert.org    Result total = 0.0;
4737831Snate@binkert.org    if (data.type == Dist && data.underflow != NAN)
4746211Snate@binkert.org        total += data.underflow;
4756211Snate@binkert.org    for (off_type i = 0; i < size; ++i)
4766211Snate@binkert.org        total += data.cvec[i];
4777831Snate@binkert.org    if (data.type == Dist && data.overflow != NAN)
4786211Snate@binkert.org        total += data.overflow;
4796211Snate@binkert.org
4806126Snate@binkert.org    if (total) {
4816211Snate@binkert.org        print.pdf = 0.0;
4826211Snate@binkert.org        print.cdf = 0.0;
4836126Snate@binkert.org    }
4846211Snate@binkert.org
4857831Snate@binkert.org    if (data.type == Dist && data.underflow != NAN) {
4866211Snate@binkert.org        print.name = base + "underflows";
4876211Snate@binkert.org        print.update(data.underflow, total);
4886211Snate@binkert.org        print(stream);
4896211Snate@binkert.org    }
4906126Snate@binkert.org
49110011Snilay@cs.wisc.edu    if (flags.isSet(oneline)) {
49210011Snilay@cs.wisc.edu        ccprintf(stream, "%-40s", name);
49310011Snilay@cs.wisc.edu    }
49410011Snilay@cs.wisc.edu
4956126Snate@binkert.org    for (off_type i = 0; i < size; ++i) {
4966126Snate@binkert.org        stringstream namestr;
4976126Snate@binkert.org        namestr << base;
4986126Snate@binkert.org
4997505Snate@binkert.org        Counter low = i * data.bucket_size + data.min;
5007505Snate@binkert.org        Counter high = ::min(low + data.bucket_size - 1.0, data.max);
5016126Snate@binkert.org        namestr << low;
5026126Snate@binkert.org        if (low < high)
5036126Snate@binkert.org            namestr << "-" << high;
5046126Snate@binkert.org
5056126Snate@binkert.org        print.name = namestr.str();
5066211Snate@binkert.org        print.update(data.cvec[i], total);
50710011Snilay@cs.wisc.edu        print(stream, flags.isSet(oneline));
50810011Snilay@cs.wisc.edu    }
50910011Snilay@cs.wisc.edu
51010011Snilay@cs.wisc.edu    if (flags.isSet(oneline)) {
51110011Snilay@cs.wisc.edu        if (descriptions) {
51210011Snilay@cs.wisc.edu            if (!desc.empty())
51310011Snilay@cs.wisc.edu                ccprintf(stream, " # %s", desc);
51410011Snilay@cs.wisc.edu        }
51510011Snilay@cs.wisc.edu        stream << endl;
516695SN/A    }
517695SN/A
5187831Snate@binkert.org    if (data.type == Dist && data.overflow != NAN) {
5196211Snate@binkert.org        print.name = base + "overflows";
5206211Snate@binkert.org        print.update(data.overflow, total);
5216211Snate@binkert.org        print(stream);
522695SN/A    }
523695SN/A
524695SN/A    print.pdf = NAN;
525695SN/A    print.cdf = NAN;
526695SN/A
5277831Snate@binkert.org    if (data.type == Dist && data.min_val != NAN) {
5286211Snate@binkert.org        print.name = base + "min_value";
5296211Snate@binkert.org        print.value = data.min_val;
5306211Snate@binkert.org        print(stream);
5316211Snate@binkert.org    }
5326211Snate@binkert.org
5337831Snate@binkert.org    if (data.type == Dist && data.max_val != NAN) {
5346211Snate@binkert.org        print.name = base + "max_value";
5356211Snate@binkert.org        print.value = data.max_val;
5366211Snate@binkert.org        print(stream);
5376211Snate@binkert.org    }
5386211Snate@binkert.org
5396126Snate@binkert.org    print.name = base + "total";
5406126Snate@binkert.org    print.value = total;
5416126Snate@binkert.org    print(stream);
542695SN/A}
543695SN/A
544695SN/Avoid
5456128Snate@binkert.orgText::visit(const ScalarInfo &info)
546695SN/A{
5475886Snate@binkert.org    if (noOutput(info))
548695SN/A        return;
549695SN/A
550695SN/A    ScalarPrint print;
5515886Snate@binkert.org    print.value = info.result();
55214205Sandreas.sandberg@arm.com    print.name = statName(info.name);
5535886Snate@binkert.org    print.desc = info.desc;
5545886Snate@binkert.org    print.flags = info.flags;
555695SN/A    print.descriptions = descriptions;
5565886Snate@binkert.org    print.precision = info.precision;
557695SN/A    print.pdf = NAN;
558695SN/A    print.cdf = NAN;
559695SN/A
560695SN/A    print(*stream);
561695SN/A}
562695SN/A
563695SN/Avoid
5646128Snate@binkert.orgText::visit(const VectorInfo &info)
565695SN/A{
5665886Snate@binkert.org    if (noOutput(info))
567695SN/A        return;
568695SN/A
5695886Snate@binkert.org    size_type size = info.size();
570695SN/A    VectorPrint print;
571695SN/A
57214205Sandreas.sandberg@arm.com    print.name = statName(info.name);
5738243Sbradley.danofsky@amd.com    print.separatorString = info.separatorString;
5745886Snate@binkert.org    print.desc = info.desc;
5755886Snate@binkert.org    print.flags = info.flags;
576695SN/A    print.descriptions = descriptions;
5775886Snate@binkert.org    print.precision = info.precision;
5785886Snate@binkert.org    print.vec = info.result();
5795886Snate@binkert.org    print.total = info.total();
5809839Sandreas.hansson@arm.com    print.forceSubnames = false;
581695SN/A
5825886Snate@binkert.org    if (!info.subnames.empty()) {
5835599Snate@binkert.org        for (off_type i = 0; i < size; ++i) {
5845886Snate@binkert.org            if (!info.subnames[i].empty()) {
5855886Snate@binkert.org                print.subnames = info.subnames;
586695SN/A                print.subnames.resize(size);
5875599Snate@binkert.org                for (off_type i = 0; i < size; ++i) {
5885886Snate@binkert.org                    if (!info.subnames[i].empty() &&
5895886Snate@binkert.org                        !info.subdescs[i].empty()) {
5905886Snate@binkert.org                        print.subdescs = info.subdescs;
591695SN/A                        print.subdescs.resize(size);
592695SN/A                        break;
593695SN/A                    }
594695SN/A                }
595695SN/A                break;
596695SN/A            }
597695SN/A        }
598695SN/A    }
599695SN/A
600695SN/A    print(*stream);
601695SN/A}
602695SN/A
603695SN/Avoid
6046128Snate@binkert.orgText::visit(const Vector2dInfo &info)
605695SN/A{
6065886Snate@binkert.org    if (noOutput(info))
607695SN/A        return;
608695SN/A
609695SN/A    bool havesub = false;
610695SN/A    VectorPrint print;
611695SN/A
6128667Sdam.sunwoo@arm.com    if (!info.y_subnames.empty()) {
6138667Sdam.sunwoo@arm.com        for (off_type i = 0; i < info.y; ++i) {
6148667Sdam.sunwoo@arm.com            if (!info.y_subnames[i].empty()) {
6158667Sdam.sunwoo@arm.com                print.subnames = info.y_subnames;
61610374Sandreas.hansson@arm.com                break;
6178667Sdam.sunwoo@arm.com            }
6188667Sdam.sunwoo@arm.com        }
6198667Sdam.sunwoo@arm.com    }
6205886Snate@binkert.org    print.flags = info.flags;
6218243Sbradley.danofsky@amd.com    print.separatorString = info.separatorString;
622695SN/A    print.descriptions = descriptions;
6235886Snate@binkert.org    print.precision = info.precision;
6249828Ssascha.bischoff@arm.com    print.forceSubnames = true;
625695SN/A
6265886Snate@binkert.org    if (!info.subnames.empty()) {
6275886Snate@binkert.org        for (off_type i = 0; i < info.x; ++i)
6285886Snate@binkert.org            if (!info.subnames[i].empty())
629695SN/A                havesub = true;
630695SN/A    }
631695SN/A
6325886Snate@binkert.org    VResult tot_vec(info.y);
6335886Snate@binkert.org    for (off_type i = 0; i < info.x; ++i) {
6345886Snate@binkert.org        if (havesub && (i >= info.subnames.size() || info.subnames[i].empty()))
635695SN/A            continue;
636695SN/A
6375886Snate@binkert.org        off_type iy = i * info.y;
6385886Snate@binkert.org        VResult yvec(info.y);
639695SN/A
640695SN/A        Result total = 0.0;
6415886Snate@binkert.org        for (off_type j = 0; j < info.y; ++j) {
6425886Snate@binkert.org            yvec[j] = info.cvec[iy + j];
643695SN/A            tot_vec[j] += yvec[j];
644695SN/A            total += yvec[j];
645695SN/A        }
646695SN/A
64714205Sandreas.sandberg@arm.com        print.name = statName(
64814205Sandreas.sandberg@arm.com            info.name + "_" +
64914205Sandreas.sandberg@arm.com            (havesub ? info.subnames[i] : std::to_string(i)));
6505886Snate@binkert.org        print.desc = info.desc;
651695SN/A        print.vec = yvec;
652695SN/A        print.total = total;
653695SN/A        print(*stream);
654695SN/A    }
655695SN/A
6569828Ssascha.bischoff@arm.com    // Create a subname for printing the total
6579828Ssascha.bischoff@arm.com    vector<string> total_subname;
6589828Ssascha.bischoff@arm.com    total_subname.push_back("total");
6599828Ssascha.bischoff@arm.com
6606130Snate@binkert.org    if (info.flags.isSet(::Stats::total) && (info.x > 1)) {
66114205Sandreas.sandberg@arm.com        print.name = statName(info.name);
6629828Ssascha.bischoff@arm.com        print.subnames = total_subname;
6635886Snate@binkert.org        print.desc = info.desc;
66411565Sdavid.guillen@arm.com        print.vec = VResult(1, info.total());
6659828Ssascha.bischoff@arm.com        print.flags = print.flags & ~total;
666695SN/A        print(*stream);
667695SN/A    }
668695SN/A}
669695SN/A
670695SN/Avoid
6716128Snate@binkert.orgText::visit(const DistInfo &info)
672695SN/A{
6735886Snate@binkert.org    if (noOutput(info))
674695SN/A        return;
675695SN/A
6766125Snate@binkert.org    DistPrint print(this, info);
677695SN/A    print(*stream);
678695SN/A}
679695SN/A
680695SN/Avoid
6816128Snate@binkert.orgText::visit(const VectorDistInfo &info)
682695SN/A{
6835886Snate@binkert.org    if (noOutput(info))
684695SN/A        return;
685695SN/A
6865886Snate@binkert.org    for (off_type i = 0; i < info.size(); ++i) {
6876125Snate@binkert.org        DistPrint print(this, info, i);
688695SN/A        print(*stream);
689695SN/A    }
690695SN/A}
691695SN/A
692695SN/Avoid
6936128Snate@binkert.orgText::visit(const FormulaInfo &info)
694695SN/A{
6956128Snate@binkert.org    visit((const VectorInfo &)info);
696695SN/A}
697695SN/A
6988514SThomas.Grass@ARM.com/*
6998514SThomas.Grass@ARM.com  This struct implements the output methods for the sparse
7008514SThomas.Grass@ARM.com  histogram stat
7018514SThomas.Grass@ARM.com*/
7028514SThomas.Grass@ARM.comstruct SparseHistPrint
7038514SThomas.Grass@ARM.com{
7048514SThomas.Grass@ARM.com    string name;
7058514SThomas.Grass@ARM.com    string separatorString;
7068514SThomas.Grass@ARM.com    string desc;
7078514SThomas.Grass@ARM.com    Flags flags;
7088514SThomas.Grass@ARM.com    bool descriptions;
7098514SThomas.Grass@ARM.com    int precision;
7108514SThomas.Grass@ARM.com
7118514SThomas.Grass@ARM.com    const SparseHistData &data;
7128514SThomas.Grass@ARM.com
7138514SThomas.Grass@ARM.com    SparseHistPrint(const Text *text, const SparseHistInfo &info);
7148514SThomas.Grass@ARM.com    void init(const Text *text, const Info &info);
7158514SThomas.Grass@ARM.com    void operator()(ostream &stream) const;
7168514SThomas.Grass@ARM.com};
7178514SThomas.Grass@ARM.com
7188514SThomas.Grass@ARM.com/* Call initialization function */
7198514SThomas.Grass@ARM.comSparseHistPrint::SparseHistPrint(const Text *text, const SparseHistInfo &info)
7208514SThomas.Grass@ARM.com    : data(info.data)
7218514SThomas.Grass@ARM.com{
7228514SThomas.Grass@ARM.com    init(text, info);
7238514SThomas.Grass@ARM.com}
7248514SThomas.Grass@ARM.com
7258514SThomas.Grass@ARM.com/* Initialization function */
7268514SThomas.Grass@ARM.comvoid
7278514SThomas.Grass@ARM.comSparseHistPrint::init(const Text *text, const Info &info)
7288514SThomas.Grass@ARM.com{
72914205Sandreas.sandberg@arm.com    name = text->statName(info.name);
7308514SThomas.Grass@ARM.com    separatorString = info.separatorString;
7318514SThomas.Grass@ARM.com    desc = info.desc;
7328514SThomas.Grass@ARM.com    flags = info.flags;
7338514SThomas.Grass@ARM.com    precision = info.precision;
7348514SThomas.Grass@ARM.com    descriptions = text->descriptions;
7358514SThomas.Grass@ARM.com}
7368514SThomas.Grass@ARM.com
7378514SThomas.Grass@ARM.com/* Grab data from map and write to output stream */
7388514SThomas.Grass@ARM.comvoid
7398514SThomas.Grass@ARM.comSparseHistPrint::operator()(ostream &stream) const
7408514SThomas.Grass@ARM.com{
7418514SThomas.Grass@ARM.com    string base = name + separatorString;
7428514SThomas.Grass@ARM.com
7438514SThomas.Grass@ARM.com    ScalarPrint print;
7448514SThomas.Grass@ARM.com    print.precision = precision;
7458514SThomas.Grass@ARM.com    print.flags = flags;
7468514SThomas.Grass@ARM.com    print.descriptions = descriptions;
7478514SThomas.Grass@ARM.com    print.desc = desc;
7488514SThomas.Grass@ARM.com    print.pdf = NAN;
7498514SThomas.Grass@ARM.com    print.cdf = NAN;
7508514SThomas.Grass@ARM.com
7518514SThomas.Grass@ARM.com    print.name = base + "samples";
7528514SThomas.Grass@ARM.com    print.value = data.samples;
7538514SThomas.Grass@ARM.com    print(stream);
7548514SThomas.Grass@ARM.com
7558514SThomas.Grass@ARM.com    MCounter::const_iterator it;
7568514SThomas.Grass@ARM.com    for (it = data.cmap.begin(); it != data.cmap.end(); it++) {
7578514SThomas.Grass@ARM.com        stringstream namestr;
7588514SThomas.Grass@ARM.com        namestr << base;
7598514SThomas.Grass@ARM.com
7608514SThomas.Grass@ARM.com        namestr <<(*it).first;
7618514SThomas.Grass@ARM.com        print.name = namestr.str();
7628514SThomas.Grass@ARM.com        print.value = (*it).second;
7638514SThomas.Grass@ARM.com        print(stream);
7648514SThomas.Grass@ARM.com    }
7658514SThomas.Grass@ARM.com}
7668514SThomas.Grass@ARM.com
7678514SThomas.Grass@ARM.comvoid
7688514SThomas.Grass@ARM.comText::visit(const SparseHistInfo &info)
7698514SThomas.Grass@ARM.com{
7708514SThomas.Grass@ARM.com    if (noOutput(info))
7718514SThomas.Grass@ARM.com        return;
7728514SThomas.Grass@ARM.com
7738514SThomas.Grass@ARM.com    SparseHistPrint print(this, info);
7748514SThomas.Grass@ARM.com    print(*stream);
7758514SThomas.Grass@ARM.com}
7768514SThomas.Grass@ARM.com
7778296Snate@binkert.orgOutput *
7786126Snate@binkert.orginitText(const string &filename, bool desc)
7794078Sbinkertn@umich.edu{
7804078Sbinkertn@umich.edu    static Text text;
7814078Sbinkertn@umich.edu    static bool connected = false;
7824078Sbinkertn@umich.edu
7838296Snate@binkert.org    if (!connected) {
78411359Sandreas@sandberg.pp.se        text.open(*simout.findOrCreate(filename)->stream());
7858296Snate@binkert.org        text.descriptions = desc;
7868296Snate@binkert.org        connected = true;
7878296Snate@binkert.org    }
7884078Sbinkertn@umich.edu
7898296Snate@binkert.org    return &text;
7904078Sbinkertn@umich.edu}
7914078Sbinkertn@umich.edu
7927811Ssteve.reinhardt@amd.com} // namespace Stats
793