Deleted Added
sdiff udiff text old ( 6125:3bbbdd324a60 ) new ( 6126:5f32f9e3c65a )
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#if defined(__sun)
36#include <math.h>
37#endif
38
39#include <iostream>
40#include <sstream>
41#include <fstream>
42#include <string>
43
44#include "base/misc.hh"
45#include "base/statistics.hh"
46#include "base/stats/text.hh"
47#include "base/stats/visit.hh"
48
49using namespace std;
50
51#ifndef NAN
52float __nan();
53/** Define Not a number. */
54#define NAN (__nan())
55/** Need to define __nan() */
56#define __M5_NAN
57#endif
58
59#ifdef __M5_NAN
60float
61__nan()
62{
63 union {
64 uint32_t ui;
65 float f;
66 } nan;
67
68 nan.ui = 0x7fc00000;
69 return nan.f;
70}
71#endif
72
73namespace Stats {
74
75Text::Text()
76 : mystream(false), stream(NULL), descriptions(false)
77{
78}
79
80Text::Text(std::ostream &stream)
81 : mystream(false), stream(NULL), descriptions(false)
82{
83 open(stream);
84}
85
86Text::Text(const std::string &file)
87 : mystream(false), stream(NULL), descriptions(false)
88{
89 open(file);
90}
91
92
93Text::~Text()
94{
95 if (mystream) {
96 assert(stream);
97 delete stream;
98 }
99}
100
101void
102Text::open(std::ostream &_stream)
103{
104 if (stream)
105 panic("stream already set!");
106
107 mystream = false;
108 stream = &_stream;
109 if (!valid())
110 fatal("Unable to open output stream for writing\n");
111}
112
113void
114Text::open(const std::string &file)
115{
116 if (stream)
117 panic("stream already set!");
118
119 mystream = true;
120 stream = new ofstream(file.c_str(), ios::trunc);
121 if (!valid())
122 fatal("Unable to open statistics file for writing\n");
123}
124
125bool
126Text::valid() const
127{
128 return stream != NULL && stream->good();
129}
130
131void
132Text::output()
133{
134 ccprintf(*stream, "\n---------- Begin Simulation Statistics ----------\n");
135 list<Info *>::const_iterator i, end = statsList().end();
136 for (i = statsList().begin(); i != end; ++i)
137 (*i)->visit(*this);
138 ccprintf(*stream, "\n---------- End Simulation Statistics ----------\n");
139 stream->flush();
140}
141
142bool
143Text::noOutput(const Info &info)
144{
145 if (!(info.flags & print))
146 return true;
147
148 if (info.prereq && info.prereq->zero())
149 return true;
150
151 return false;
152}
153
154string
155ValueToString(Result value, int precision)
156{
157 stringstream val;
158
159 if (!isnan(value)) {
160 if (precision != -1)
161 val.precision(precision);
162 else if (value == rint(value))
163 val.precision(0);
164
165 val.unsetf(ios::showpoint);
166 val.setf(ios::fixed);
167 val << value;
168 } else {
169 val << "no_value";
170 }
171
172 return val.str();
173}
174
175struct ScalarPrint
176{
177 Result value;
178 string name;
179 string desc;
180 StatFlags flags;
181 bool descriptions;
182 int precision;
183 Result pdf;
184 Result cdf;
185
186 void operator()(ostream &stream) const;
187};
188
189void
190ScalarPrint::operator()(ostream &stream) const
191{
192 if ((flags & nozero && value == 0.0) ||
193 (flags & nonan && isnan(value)))
194 return;
195
196 stringstream pdfstr, cdfstr;
197
198 if (!isnan(pdf))
199 ccprintf(pdfstr, "%.2f%%", pdf * 100.0);
200
201 if (!isnan(cdf))
202 ccprintf(cdfstr, "%.2f%%", cdf * 100.0);
203
204 ccprintf(stream, "%-40s %12s %10s %10s", name,
205 ValueToString(value, precision), pdfstr, cdfstr);
206
207 if (descriptions) {
208 if (!desc.empty())
209 ccprintf(stream, " # %s", desc);
210 }
211 stream << endl;
212}
213
214struct VectorPrint
215{
216 string name;
217 string desc;
218 vector<string> subnames;
219 vector<string> subdescs;
220 StatFlags flags;
221 bool descriptions;
222 int precision;
223 VResult vec;
224 Result total;
225
226 void operator()(ostream &stream) const;
227};
228
229void
230VectorPrint::operator()(std::ostream &stream) const
231{
232 size_type _size = vec.size();
233 Result _total = 0.0;
234
235 if (flags & (pdf | cdf)) {
236 for (off_type i = 0; i < _size; ++i) {
237 _total += vec[i];
238 }
239 }
240
241 string base = name + "::";
242
243 ScalarPrint print;
244 print.name = name;
245 print.desc = desc;
246 print.precision = precision;
247 print.descriptions = descriptions;
248 print.flags = flags;
249 print.pdf = NAN;
250 print.cdf = NAN;
251
252 bool havesub = !subnames.empty();
253
254 if (_size == 1) {
255 print.value = vec[0];
256 print(stream);
257 return;
258 }
259
260 for (off_type i = 0; i < _size; ++i) {
261 if (havesub && (i >= subnames.size() || subnames[i].empty()))
262 continue;
263
264 print.name = base + (havesub ? subnames[i] : to_string(i));
265 print.desc = subdescs.empty() ? desc : subdescs[i];
266 print.value = vec[i];
267
268 if (_total && flags & pdf) {
269 print.pdf = vec[i] / _total;
270 print.cdf += print.pdf;
271 }
272
273 print(stream);
274 }
275
276 if (flags & ::Stats::total) {
277 print.pdf = NAN;
278 print.cdf = NAN;
279 print.name = base + "total";
280 print.desc = desc;
281 print.value = total;
282 print(stream);
283 }
284}
285
286struct DistPrint
287{
288 string name;
289 string desc;
290 StatFlags flags;
291 bool descriptions;
292 int precision;
293
294 Counter min;
295 Counter max;
296 Counter bucket_size;
297 size_type size;
298 bool fancy;
299
300 const DistData &data;
301
302 DistPrint(const Text *text, const DistInfoBase &info);
303 DistPrint(const Text *text, const VectorDistInfoBase &info, int i);
304 void init(const Text *text, const Info &info, const DistParams *params);
305 void operator()(ostream &stream) const;
306};
307
308DistPrint::DistPrint(const Text *text, const DistInfoBase &info)
309 : data(info.data)
310{
311 init(text, info, safe_cast<const DistParams *>(info.storageParams));
312}
313
314DistPrint::DistPrint(const Text *text, const VectorDistInfoBase &info, int i)
315 : data(info.data[i])
316{
317 init(text, info, safe_cast<const DistParams *>(info.storageParams));
318
319 name = info.name + "_" +
320 (info.subnames[i].empty() ? (to_string(i)) : info.subnames[i]);
321
322 if (!info.subdescs[i].empty())
323 desc = info.subdescs[i];
324}
325
326void
327DistPrint::init(const Text *text, const Info &info, const DistParams *params)
328{
329 name = info.name;
330 desc = info.desc;
331 flags = info.flags;
332 precision = info.precision;
333 descriptions = text->descriptions;
334
335 fancy = params->fancy;
336 min = params->min;
337 max = params->max;
338 bucket_size = params->bucket_size;
339 size = params->buckets;
340}
341
342void
343DistPrint::operator()(ostream &stream) const
344{
345 Result stdev = NAN;
346 if (data.samples)
347 stdev = sqrt((data.samples * data.squares - data.sum * data.sum) /
348 (data.samples * (data.samples - 1.0)));
349
350 if (fancy) {
351 ScalarPrint print;
352 string base = name + "::";
353
354 print.precision = precision;
355 print.flags = flags;
356 print.descriptions = descriptions;
357 print.desc = desc;
358 print.pdf = NAN;
359 print.cdf = NAN;
360
361 print.name = base + "mean";
362 print.value = data.samples ? data.sum / data.samples : NAN;
363 print(stream);
364
365 print.name = base + "stdev";
366 print.value = stdev;
367 print(stream);
368
369 print.name = "**Ignore: " + base + "TOT";
370 print.value = data.samples;
371 print(stream);
372 return;
373 }
374
375 assert(size == data.cvec.size());
376
377 Result total = 0.0;
378
379 total += data.underflow;
380 for (off_type i = 0; i < size; ++i)
381 total += data.cvec[i];
382 total += data.overflow;
383
384 string base = name + "::";
385
386 ScalarPrint print;
387 print.desc = desc;
388 print.flags = flags;
389 print.descriptions = descriptions;
390 print.precision = precision;
391 print.pdf = NAN;
392 print.cdf = NAN;
393
394 print.name = base + "samples";
395 print.value = data.samples;
396 print(stream);
397
398 print.name = base + "min_value";
399 print.value = data.min_val;
400 print(stream);
401
402 print.name = base + "underflows";
403 print.value = data.underflow;
404 if (total) {
405 print.pdf = data.underflow / total;
406 print.cdf += print.pdf;
407 }
408 print(stream);
409
410 for (off_type i = 0; i < size; ++i) {
411 stringstream namestr;
412 namestr << base;
413
414 Counter low = i * bucket_size + min;
415 Counter high = ::min(low + bucket_size, max);
416 namestr << low;
417 if (low < high)
418 namestr << "-" << high;
419
420 print.name = namestr.str();
421 print.value = data.cvec[i];
422 if (total) {
423 print.pdf = data.cvec[i] / total;
424 print.cdf += print.pdf;
425 }
426 print(stream);
427 }
428
429 print.name = base + "overflows";
430 print.value = data.overflow;
431 if (total) {
432 print.pdf = data.overflow / total;
433 print.cdf += print.pdf;
434 } else {
435 print.pdf = NAN;
436 print.cdf = NAN;
437 }
438 print(stream);
439
440 print.pdf = NAN;
441 print.cdf = NAN;
442
443 print.name = base + "total";
444 print.value = total;
445 print(stream);
446
447 print.name = base + "max_value";
448 print.value = data.max_val;
449 print(stream);
450
451 print.name = base + "mean";
452 print.value = data.sum / data.samples;
453 print(stream);
454
455 print.name = base + "stdev";
456 print.value = stdev;
457 print(stream);
458}
459
460void
461Text::visit(const ScalarInfoBase &info)
462{
463 if (noOutput(info))
464 return;
465
466 ScalarPrint print;
467 print.value = info.result();
468 print.name = info.name;
469 print.desc = info.desc;
470 print.flags = info.flags;
471 print.descriptions = descriptions;
472 print.precision = info.precision;
473 print.pdf = NAN;
474 print.cdf = NAN;
475
476 print(*stream);
477}
478
479void
480Text::visit(const VectorInfoBase &info)
481{
482 if (noOutput(info))
483 return;
484
485 size_type size = info.size();
486 VectorPrint print;
487
488 print.name = info.name;
489 print.desc = info.desc;
490 print.flags = info.flags;
491 print.descriptions = descriptions;
492 print.precision = info.precision;
493 print.vec = info.result();
494 print.total = info.total();
495
496 if (!info.subnames.empty()) {
497 for (off_type i = 0; i < size; ++i) {
498 if (!info.subnames[i].empty()) {
499 print.subnames = info.subnames;
500 print.subnames.resize(size);
501 for (off_type i = 0; i < size; ++i) {
502 if (!info.subnames[i].empty() &&
503 !info.subdescs[i].empty()) {
504 print.subdescs = info.subdescs;
505 print.subdescs.resize(size);
506 break;
507 }
508 }
509 break;
510 }
511 }
512 }
513
514 print(*stream);
515}
516
517void
518Text::visit(const Vector2dInfoBase &info)
519{
520 if (noOutput(info))
521 return;
522
523 bool havesub = false;
524 VectorPrint print;
525
526 print.subnames = info.y_subnames;
527 print.flags = info.flags;
528 print.descriptions = descriptions;
529 print.precision = info.precision;
530
531 if (!info.subnames.empty()) {
532 for (off_type i = 0; i < info.x; ++i)
533 if (!info.subnames[i].empty())
534 havesub = true;
535 }
536
537 VResult tot_vec(info.y);
538 Result super_total = 0.0;
539 for (off_type i = 0; i < info.x; ++i) {
540 if (havesub && (i >= info.subnames.size() || info.subnames[i].empty()))
541 continue;
542
543 off_type iy = i * info.y;
544 VResult yvec(info.y);
545
546 Result total = 0.0;
547 for (off_type j = 0; j < info.y; ++j) {
548 yvec[j] = info.cvec[iy + j];
549 tot_vec[j] += yvec[j];
550 total += yvec[j];
551 super_total += yvec[j];
552 }
553
554 print.name = info.name + "_" +
555 (havesub ? info.subnames[i] : to_string(i));
556 print.desc = info.desc;
557 print.vec = yvec;
558 print.total = total;
559 print(*stream);
560 }
561
562 if ((info.flags & ::Stats::total) && (info.x > 1)) {
563 print.name = info.name;
564 print.desc = info.desc;
565 print.vec = tot_vec;
566 print.total = super_total;
567 print(*stream);
568 }
569}
570
571void
572Text::visit(const DistInfoBase &info)
573{
574 if (noOutput(info))
575 return;
576
577 DistPrint print(this, info);
578 print(*stream);
579}
580
581void
582Text::visit(const VectorDistInfoBase &info)
583{
584 if (noOutput(info))
585 return;
586
587 for (off_type i = 0; i < info.size(); ++i) {
588 DistPrint print(this, info, i);
589 print(*stream);
590 }
591}
592
593void
594Text::visit(const FormulaInfoBase &info)
595{
596 visit((const VectorInfoBase &)info);
597}
598
599bool
600initText(const string &filename, bool desc)
601{
602 static Text text;
603 static bool connected = false;
604
605 if (connected)
606 return false;
607
608 extern list<Output *> OutputList;
609
610 text.open(*simout.find(filename));
611 text.descriptions = desc;
612 OutputList.push_back(&text);
613 connected = true;
614
615 return true;
616}
617
618/* namespace Stats */ }