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