text.cc revision 2665:a124942bacb8
1/*
2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Nathan Binkert
29 */
30
31#if defined(__APPLE__)
32#define _GLIBCPP_USE_C99 1
33#endif
34
35#include <iostream>
36#include <sstream>
37#include <fstream>
38#include <string>
39
40#include "base/misc.hh"
41#include "base/statistics.hh"
42#include "base/stats/statdb.hh"
43#include "base/stats/text.hh"
44#include "base/stats/visit.hh"
45
46using namespace std;
47
48#ifndef NAN
49float __nan();
50/** Define Not a number. */
51#define NAN (__nan())
52/** Need to define __nan() */
53#define __M5_NAN
54#endif
55
56#ifdef __M5_NAN
57float
58__nan()
59{
60    union {
61        uint32_t ui;
62        float f;
63    } nan;
64
65    nan.ui = 0x7fc00000;
66    return nan.f;
67}
68#endif
69
70namespace Stats {
71
72Text::Text()
73    : mystream(false), stream(NULL), compat(false), descriptions(false)
74{
75}
76
77Text::Text(std::ostream &stream)
78    : mystream(false), stream(NULL), compat(false), descriptions(false)
79{
80    open(stream);
81}
82
83Text::Text(const std::string &file)
84    : mystream(false), stream(NULL), compat(false), descriptions(false)
85{
86    open(file);
87}
88
89
90Text::~Text()
91{
92    if (mystream) {
93        assert(stream);
94        delete stream;
95    }
96}
97
98void
99Text::open(std::ostream &_stream)
100{
101    if (stream)
102        panic("stream already set!");
103
104    mystream = false;
105    stream = &_stream;
106    assert(valid());
107}
108
109void
110Text::open(const std::string &file)
111{
112    if (stream)
113        panic("stream already set!");
114
115    mystream = true;
116    stream = new ofstream(file.c_str(), ios::trunc);
117    assert(valid());
118}
119
120bool
121Text::valid() const
122{
123    return stream != NULL;
124}
125
126void
127Text::output()
128{
129    using namespace Database;
130
131    ccprintf(*stream, "\n---------- Begin Simulation Statistics ----------\n");
132    if (bins().empty() || bins().size() == 1) {
133        stat_list_t::const_iterator i, end = stats().end();
134        for (i = stats().begin(); i != end; ++i)
135            (*i)->visit(*this);
136    } else {
137        ccprintf(*stream, "PRINTING BINNED STATS\n");
138        bin_list_t::iterator i, end = bins().end();
139        for (i = bins().begin(); i != end; ++i) {
140            MainBin *bin = *i;
141            bin->activate();
142            ccprintf(*stream,"---%s Bin------------\n", bin->name());
143            stat_list_t::const_iterator i, end = stats().end();
144            for (i = stats().begin(); i != end; ++i)
145                (*i)->visit(*this);
146            ccprintf(*stream, "---------------------------------\n");
147        }
148    }
149    ccprintf(*stream, "\n---------- End Simulation Statistics   ----------\n");
150    stream->flush();
151}
152
153bool
154Text::noOutput(const StatData &data)
155{
156    if (!(data.flags & print))
157        return true;
158
159    if (data.prereq && data.prereq->zero())
160        return true;
161
162    return false;
163}
164
165string
166ValueToString(Result value, int precision, bool compat)
167{
168    stringstream val;
169
170    if (!isnan(value)) {
171        if (precision != -1)
172            val.precision(precision);
173        else if (value == rint(value))
174            val.precision(0);
175
176        val.unsetf(ios::showpoint);
177        val.setf(ios::fixed);
178        val << value;
179    } else {
180        val << (compat ? "<err: div-0>" : "no value");
181    }
182
183    return val.str();
184}
185
186struct ScalarPrint
187{
188    Result value;
189    string name;
190    string desc;
191    StatFlags flags;
192    bool compat;
193    bool descriptions;
194    int precision;
195    Result pdf;
196    Result cdf;
197
198    void operator()(ostream &stream) const;
199};
200
201void
202ScalarPrint::operator()(ostream &stream) const
203{
204    if (flags & nozero && value == 0.0 ||
205        flags & nonan && isnan(value))
206        return;
207
208    stringstream pdfstr, cdfstr;
209
210    if (!isnan(pdf))
211        ccprintf(pdfstr, "%.2f%%", pdf * 100.0);
212
213    if (!isnan(cdf))
214        ccprintf(cdfstr, "%.2f%%", cdf * 100.0);
215
216    if (compat && flags & __substat) {
217        ccprintf(stream, "%32s %12s %10s %10s", name,
218                 ValueToString(value, precision, compat), pdfstr, cdfstr);
219    } else {
220        ccprintf(stream, "%-40s %12s %10s %10s", name,
221                 ValueToString(value, precision, compat), pdfstr, cdfstr);
222    }
223
224    if (descriptions) {
225        if (!desc.empty())
226            ccprintf(stream, " # %s", desc);
227    }
228    stream << endl;
229}
230
231struct VectorPrint
232{
233    string name;
234    string desc;
235    vector<string> subnames;
236    vector<string> subdescs;
237    StatFlags flags;
238    bool compat;
239    bool descriptions;
240    int precision;
241    VResult vec;
242    Result total;
243
244    void operator()(ostream &stream) const;
245};
246
247void
248VectorPrint::operator()(std::ostream &stream) const
249{
250    int _size = vec.size();
251    Result _total = 0.0;
252
253    if (flags & (pdf | cdf)) {
254        for (int i = 0; i < _size; ++i) {
255            _total += vec[i];
256        }
257    }
258
259    string base = name + (compat ? "_" : "::");
260
261    ScalarPrint print;
262    print.name = name;
263    print.desc = desc;
264    print.precision = precision;
265    print.descriptions = descriptions;
266    print.flags = flags;
267    print.pdf = NAN;
268    print.cdf = NAN;
269
270    bool havesub = !subnames.empty();
271
272    if (_size == 1) {
273        print.value = vec[0];
274        print(stream);
275    } else if (!compat) {
276        for (int i = 0; i < _size; ++i) {
277            if (havesub && (i >= subnames.size() || subnames[i].empty()))
278                continue;
279
280            print.name = base + (havesub ? subnames[i] : to_string(i));
281            print.desc = subdescs.empty() ? desc : subdescs[i];
282            print.value = vec[i];
283
284            if (_total && (flags & pdf)) {
285                print.pdf = vec[i] / _total;
286                print.cdf += print.pdf;
287            }
288
289            print(stream);
290        }
291
292        if (flags & ::Stats::total) {
293            print.name = base + "total";
294            print.desc = desc;
295            print.value = total;
296            print(stream);
297        }
298    } else {
299        if (flags & ::Stats::total) {
300            print.value = total;
301            print(stream);
302        }
303
304        Result _pdf = 0.0;
305        Result _cdf = 0.0;
306        if (flags & dist) {
307            ccprintf(stream, "%s.start_dist\n", name);
308            for (int i = 0; i < _size; ++i) {
309                print.name = havesub ? subnames[i] : to_string(i);
310                print.desc = subdescs.empty() ? desc : subdescs[i];
311                print.flags |= __substat;
312                print.value = vec[i];
313
314                if (_total) {
315                    _pdf = vec[i] / _total;
316                    _cdf += _pdf;
317                }
318
319                if (flags & pdf)
320                    print.pdf = _pdf;
321                if (flags & cdf)
322                    print.cdf = _cdf;
323
324                print(stream);
325            }
326            ccprintf(stream, "%s.end_dist\n", name);
327        } else {
328            for (int i = 0; i < _size; ++i) {
329                if (havesub && subnames[i].empty())
330                    continue;
331
332                print.name = base;
333                print.name += havesub ? subnames[i] : to_string(i);
334                print.desc = subdescs.empty() ? desc : subdescs[i];
335                print.value = vec[i];
336
337                if (_total) {
338                    _pdf = vec[i] / _total;
339                    _cdf += _pdf;
340                } else {
341                    _pdf = _cdf = NAN;
342                }
343
344                if (flags & pdf) {
345                    print.pdf = _pdf;
346                    print.cdf = _cdf;
347                }
348
349                print(stream);
350            }
351        }
352    }
353}
354
355struct DistPrint
356{
357    string name;
358    string desc;
359    StatFlags flags;
360    bool compat;
361    bool descriptions;
362    int precision;
363
364    Result min_val;
365    Result max_val;
366    Result underflow;
367    Result overflow;
368    VResult vec;
369    Result sum;
370    Result squares;
371    Result samples;
372
373    Counter min;
374    Counter max;
375    Counter bucket_size;
376    int size;
377    bool fancy;
378
379    void operator()(ostream &stream) const;
380};
381
382void
383DistPrint::operator()(ostream &stream) const
384{
385    if (fancy) {
386        ScalarPrint print;
387        string base = name + (compat ? "_" : "::");
388
389        print.precision = precision;
390        print.flags = flags;
391        print.compat = compat;
392        print.descriptions = descriptions;
393        print.desc = desc;
394        print.pdf = NAN;
395        print.cdf = NAN;
396
397        print.name = base + "mean";
398        print.value = samples ? sum / samples : NAN;
399        print(stream);
400
401        print.name = base + "stdev";
402        print.value = samples ? sqrt((samples * squares - sum * sum) /
403                                     (samples * (samples - 1.0))) : NAN;
404        print(stream);
405
406        print.name = "**Ignore: " + base + "TOT";
407        print.value = samples;
408        print(stream);
409        return;
410    }
411
412    assert(size == vec.size());
413
414    Result total = 0.0;
415
416    total += underflow;
417    for (int i = 0; i < size; ++i)
418        total += vec[i];
419    total += overflow;
420
421    string base = name + (compat ? "." : "::");
422
423    ScalarPrint print;
424    print.desc = compat ? "" : desc;
425    print.flags = flags;
426    print.compat = compat;
427    print.descriptions = descriptions;
428    print.precision = precision;
429    print.pdf = NAN;
430    print.cdf = NAN;
431
432    if (compat) {
433        ccprintf(stream, "%-42s", base + "start_dist");
434        if (descriptions && !desc.empty())
435            ccprintf(stream, "                     # %s", desc);
436        stream << endl;
437    }
438
439    print.name = base + "samples";
440    print.value = samples;
441    print(stream);
442
443    print.name = base + "min_value";
444    print.value = min_val;
445    print(stream);
446
447    if (!compat || underflow > 0.0) {
448        print.name = base + "underflows";
449        print.value = underflow;
450        if (!compat && total) {
451            print.pdf = underflow / total;
452            print.cdf += print.pdf;
453        }
454        print(stream);
455    }
456
457
458    if (!compat) {
459        for (int i = 0; i < size; ++i) {
460            stringstream namestr;
461            namestr << name;
462
463            Counter low = i * bucket_size + min;
464            Counter high = ::min(low + bucket_size, max);
465            namestr << low;
466            if (low < high)
467                namestr << "-" << high;
468
469            print.name = namestr.str();
470            print.value = vec[i];
471            if (total) {
472                print.pdf = vec[i] / total;
473                print.cdf += print.pdf;
474            }
475            print(stream);
476        }
477
478    } else {
479        Counter _min;
480        Result _pdf;
481        Result _cdf = 0.0;
482
483        print.flags = flags | __substat;
484
485        for (int i = 0; i < size; ++i) {
486            if (flags & nozero && vec[i] == 0.0 ||
487                flags & nonan && isnan(vec[i]))
488                continue;
489
490            _min = i * bucket_size + min;
491            _pdf = vec[i] / total * 100.0;
492            _cdf += _pdf;
493
494
495            print.name = ValueToString(_min, 0, compat);
496            print.value = vec[i];
497            print.pdf = (flags & pdf) ? _pdf : NAN;
498            print.cdf = (flags & cdf) ? _cdf : NAN;
499            print(stream);
500        }
501
502        print.flags = flags;
503    }
504
505    if (!compat || overflow > 0.0) {
506        print.name = base + "overflows";
507        print.value = overflow;
508        if (!compat && total) {
509            print.pdf = overflow / total;
510            print.cdf += print.pdf;
511        } else {
512            print.pdf = NAN;
513            print.cdf = NAN;
514        }
515        print(stream);
516    }
517
518    print.pdf = NAN;
519    print.cdf = NAN;
520
521    if (!compat) {
522        print.name = base + "total";
523        print.value = total;
524        print(stream);
525    }
526
527    print.name = base + "max_value";
528    print.value = max_val;
529    print(stream);
530
531    if (!compat && samples != 0) {
532        print.name = base + "mean";
533        print.value = sum / samples;
534        print(stream);
535
536        print.name = base + "stdev";
537        print.value = sqrt((samples * squares - sum * sum) /
538                           (samples * (samples - 1.0)));
539        print(stream);
540    }
541
542    if (compat)
543        ccprintf(stream, "%send_dist\n\n", base);
544}
545
546void
547Text::visit(const ScalarData &data)
548{
549    if (noOutput(data))
550        return;
551
552    ScalarPrint print;
553    print.value = data.result();
554    print.name = data.name;
555    print.desc = data.desc;
556    print.flags = data.flags;
557    print.compat = compat;
558    print.descriptions = descriptions;
559    print.precision = data.precision;
560    print.pdf = NAN;
561    print.cdf = NAN;
562
563    print(*stream);
564}
565
566void
567Text::visit(const VectorData &data)
568{
569    if (noOutput(data))
570        return;
571
572    int size = data.size();
573    VectorPrint print;
574
575    print.name = data.name;
576    print.desc = data.desc;
577    print.flags = data.flags;
578    print.compat = compat;
579    print.descriptions = descriptions;
580    print.precision = data.precision;
581    print.vec = data.result();
582    print.total = data.total();
583
584    if (!data.subnames.empty()) {
585        for (int i = 0; i < size; ++i) {
586            if (!data.subnames[i].empty()) {
587                print.subnames = data.subnames;
588                print.subnames.resize(size);
589                for (int i = 0; i < size; ++i) {
590                    if (!data.subnames[i].empty() &&
591                        !data.subdescs[i].empty()) {
592                        print.subdescs = data.subdescs;
593                        print.subdescs.resize(size);
594                        break;
595                    }
596                }
597                break;
598            }
599        }
600    }
601
602    print(*stream);
603}
604
605void
606Text::visit(const Vector2dData &data)
607{
608    if (noOutput(data))
609        return;
610
611    bool havesub = false;
612    VectorPrint print;
613
614    print.subnames = data.y_subnames;
615    print.flags = data.flags;
616    print.compat = compat;
617    print.descriptions = descriptions;
618    print.precision = data.precision;
619
620    if (!data.subnames.empty()) {
621        for (int i = 0; i < data.x; ++i)
622            if (!data.subnames[i].empty())
623                havesub = true;
624    }
625
626    VResult tot_vec(data.y);
627    Result super_total = 0.0;
628    for (int i = 0; i < data.x; ++i) {
629        if (havesub && (i >= data.subnames.size() || data.subnames[i].empty()))
630            continue;
631
632        int iy = i * data.y;
633        VResult yvec(data.y);
634
635        Result total = 0.0;
636        for (int j = 0; j < data.y; ++j) {
637            yvec[j] = data.cvec[iy + j];
638            tot_vec[j] += yvec[j];
639            total += yvec[j];
640            super_total += yvec[j];
641        }
642
643        print.name = data.name + "_" + (havesub ? data.subnames[i] : to_string(i));
644        print.desc = data.desc;
645        print.vec = yvec;
646        print.total = total;
647        print(*stream);
648    }
649
650    if ((data.flags & ::Stats::total) && (data.x > 1)) {
651        print.name = data.name;
652        print.desc = data.desc;
653        print.vec = tot_vec;
654        print.total = super_total;
655        print(*stream);
656    }
657}
658
659void
660Text::visit(const DistData &data)
661{
662    if (noOutput(data))
663        return;
664
665    DistPrint print;
666
667    print.name = data.name;
668    print.desc = data.desc;
669    print.flags = data.flags;
670    print.compat = compat;
671    print.descriptions = descriptions;
672    print.precision = data.precision;
673
674    print.min_val = data.data.min_val;
675    print.max_val = data.data.max_val;
676    print.underflow = data.data.underflow;
677    print.overflow = data.data.overflow;
678    print.vec.resize(data.data.cvec.size());
679    for (int i = 0; i < print.vec.size(); ++i)
680        print.vec[i] = (Result)data.data.cvec[i];
681    print.sum = data.data.sum;
682    print.squares = data.data.squares;
683    print.samples = data.data.samples;
684
685    print.min = data.data.min;
686    print.max = data.data.max;
687    print.bucket_size = data.data.bucket_size;
688    print.size = data.data.size;
689    print.fancy = data.data.fancy;
690
691    print(*stream);
692}
693
694void
695Text::visit(const VectorDistData &data)
696{
697    if (noOutput(data))
698        return;
699
700    for (int i = 0; i < data.size(); ++i) {
701        DistPrint print;
702
703        print.name = data.name +
704            (data.subnames[i].empty() ? ("_" + to_string(i)) : data.subnames[i]);
705        print.desc = data.subdescs[i].empty() ? data.desc : data.subdescs[i];
706        print.flags = data.flags;
707        print.compat = compat;
708        print.descriptions = descriptions;
709        print.precision = data.precision;
710
711        print.min_val = data.data[i].min_val;
712        print.max_val = data.data[i].max_val;
713        print.underflow = data.data[i].underflow;
714        print.overflow = data.data[i].overflow;
715        print.vec.resize(data.data[i].cvec.size());
716        for (int j = 0; j < print.vec.size(); ++j)
717            print.vec[j] = (Result)data.data[i].cvec[j];
718        print.sum = data.data[i].sum;
719        print.squares = data.data[i].squares;
720        print.samples = data.data[i].samples;
721
722        print.min = data.data[i].min;
723        print.max = data.data[i].max;
724        print.bucket_size = data.data[i].bucket_size;
725        print.size = data.data[i].size;
726        print.fancy = data.data[i].fancy;
727
728        print(*stream);
729    }
730}
731
732void
733Text::visit(const FormulaData &data)
734{
735    visit((const VectorData &)data);
736}
737
738/* namespace Stats */ }
739