Deleted Added
sdiff udiff text old ( 2632:1bb2f91485ea ) new ( 2665:a124942bacb8 )
full compact
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 */ }