2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
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.
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.
28 * Authors: Nathan Binkert
31 #if defined(__APPLE__)
32 #define _GLIBCPP_USE_C99 1
49 #include "base/cast.hh"
50 #include "base/misc.hh"
51 #include "base/str.hh"
52 #include "base/stats/info.hh"
53 #include "base/stats/text.hh"
54 #include "base/stats/visit.hh"
60 /** Define Not a number. */
62 /** Need to define __nan() */
82 std::list
<Info
*> &statsList();
85 : mystream(false), stream(NULL
), descriptions(false)
89 Text::Text(std::ostream
&stream
)
90 : mystream(false), stream(NULL
), descriptions(false)
95 Text::Text(const std::string
&file
)
96 : mystream(false), stream(NULL
), descriptions(false)
111 Text::open(std::ostream
&_stream
)
114 panic("stream already set!");
119 fatal("Unable to open output stream for writing\n");
123 Text::open(const std::string
&file
)
126 panic("stream already set!");
129 stream
= new ofstream(file
.c_str(), ios::trunc
);
131 fatal("Unable to open statistics file for writing\n");
137 return stream
!= NULL
&& stream
->good();
143 ccprintf(*stream
, "\n---------- Begin Simulation Statistics ----------\n");
144 list
<Info
*>::const_iterator i
, end
= statsList().end();
145 for (i
= statsList().begin(); i
!= end
; ++i
)
147 ccprintf(*stream
, "\n---------- End Simulation Statistics ----------\n");
152 Text::noOutput(const Info
&info
)
154 if (!info
.flags
.isSet(display
))
157 if (info
.prereq
&& info
.prereq
->zero())
164 ValueToString(Result value
, int precision
)
170 val
.precision(precision
);
171 else if (value
== rint(value
))
174 val
.unsetf(ios::showpoint
);
175 val
.setf(ios::fixed
);
195 void update(Result val
, Result total
);
196 void operator()(ostream
&stream
) const;
200 ScalarPrint::update(Result val
, Result total
)
210 ScalarPrint::operator()(ostream
&stream
) const
212 if ((flags
.isSet(nozero
) && value
== 0.0) ||
213 (flags
.isSet(nonan
) && isnan(value
)))
216 stringstream pdfstr
, cdfstr
;
219 ccprintf(pdfstr
, "%.2f%%", pdf
* 100.0);
222 ccprintf(cdfstr
, "%.2f%%", cdf
* 100.0);
224 ccprintf(stream
, "%-40s %12s %10s %10s", name
,
225 ValueToString(value
, precision
), pdfstr
, cdfstr
);
229 ccprintf(stream
, " # %s", desc
);
238 vector
<string
> subnames
;
239 vector
<string
> subdescs
;
246 void operator()(ostream
&stream
) const;
250 VectorPrint::operator()(std::ostream
&stream
) const
252 size_type _size
= vec
.size();
255 if (flags
.isSet(pdf
| cdf
)) {
256 for (off_type i
= 0; i
< _size
; ++i
) {
261 string base
= name
+ "::";
266 print
.precision
= precision
;
267 print
.descriptions
= descriptions
;
269 print
.pdf
= _total
? 0.0 : NAN
;
270 print
.cdf
= _total
? 0.0 : NAN
;
272 bool havesub
= !subnames
.empty();
275 print
.value
= vec
[0];
280 for (off_type i
= 0; i
< _size
; ++i
) {
281 if (havesub
&& (i
>= subnames
.size() || subnames
[i
].empty()))
284 print
.name
= base
+ (havesub
? subnames
[i
] : to_string(i
));
285 print
.desc
= subdescs
.empty() ? desc
: subdescs
[i
];
287 print
.update(vec
[i
], _total
);
291 if (flags
.isSet(::Stats::total
)) {
294 print
.name
= base
+ "total";
309 const DistData
&data
;
311 DistPrint(const Text
*text
, const DistInfo
&info
);
312 DistPrint(const Text
*text
, const VectorDistInfo
&info
, int i
);
313 void init(const Text
*text
, const Info
&info
);
314 void operator()(ostream
&stream
) const;
317 DistPrint::DistPrint(const Text
*text
, const DistInfo
&info
)
323 DistPrint::DistPrint(const Text
*text
, const VectorDistInfo
&info
, int i
)
328 name
= info
.name
+ "_" +
329 (info
.subnames
[i
].empty() ? (to_string(i
)) : info
.subnames
[i
]);
331 if (!info
.subdescs
[i
].empty())
332 desc
= info
.subdescs
[i
];
336 DistPrint::init(const Text
*text
, const Info
&info
)
341 precision
= info
.precision
;
342 descriptions
= text
->descriptions
;
346 DistPrint::operator()(ostream
&stream
) const
348 string base
= name
+ "::";
351 print
.precision
= precision
;
353 print
.descriptions
= descriptions
;
358 print
.name
= base
+ "samples";
359 print
.value
= data
.samples
;
362 print
.name
= base
+ "mean";
363 print
.value
= data
.samples
? data
.sum
/ data
.samples
: NAN
;
368 stdev
= sqrt((data
.samples
* data
.squares
- data
.sum
* data
.sum
) /
369 (data
.samples
* (data
.samples
- 1.0)));
370 print
.name
= base
+ "stdev";
374 if (data
.type
== Deviation
)
377 size_t size
= data
.cvec
.size();
380 if (data
.underflow
!= NAN
)
381 total
+= data
.underflow
;
382 for (off_type i
= 0; i
< size
; ++i
)
383 total
+= data
.cvec
[i
];
384 if (data
.overflow
!= NAN
)
385 total
+= data
.overflow
;
392 if (data
.underflow
!= NAN
) {
393 print
.name
= base
+ "underflows";
394 print
.update(data
.underflow
, total
);
398 for (off_type i
= 0; i
< size
; ++i
) {
399 stringstream namestr
;
402 Counter low
= i
* data
.bucket_size
+ data
.min
;
403 Counter high
= ::min(low
+ data
.bucket_size
- 1.0, data
.max
);
406 namestr
<< "-" << high
;
408 print
.name
= namestr
.str();
409 print
.update(data
.cvec
[i
], total
);
413 if (data
.overflow
!= NAN
) {
414 print
.name
= base
+ "overflows";
415 print
.update(data
.overflow
, total
);
422 if (data
.min_val
!= NAN
) {
423 print
.name
= base
+ "min_value";
424 print
.value
= data
.min_val
;
428 if (data
.max_val
!= NAN
) {
429 print
.name
= base
+ "max_value";
430 print
.value
= data
.max_val
;
434 print
.name
= base
+ "total";
440 Text::visit(const ScalarInfo
&info
)
446 print
.value
= info
.result();
447 print
.name
= info
.name
;
448 print
.desc
= info
.desc
;
449 print
.flags
= info
.flags
;
450 print
.descriptions
= descriptions
;
451 print
.precision
= info
.precision
;
459 Text::visit(const VectorInfo
&info
)
464 size_type size
= info
.size();
467 print
.name
= info
.name
;
468 print
.desc
= info
.desc
;
469 print
.flags
= info
.flags
;
470 print
.descriptions
= descriptions
;
471 print
.precision
= info
.precision
;
472 print
.vec
= info
.result();
473 print
.total
= info
.total();
475 if (!info
.subnames
.empty()) {
476 for (off_type i
= 0; i
< size
; ++i
) {
477 if (!info
.subnames
[i
].empty()) {
478 print
.subnames
= info
.subnames
;
479 print
.subnames
.resize(size
);
480 for (off_type i
= 0; i
< size
; ++i
) {
481 if (!info
.subnames
[i
].empty() &&
482 !info
.subdescs
[i
].empty()) {
483 print
.subdescs
= info
.subdescs
;
484 print
.subdescs
.resize(size
);
497 Text::visit(const Vector2dInfo
&info
)
502 bool havesub
= false;
505 print
.subnames
= info
.y_subnames
;
506 print
.flags
= info
.flags
;
507 print
.descriptions
= descriptions
;
508 print
.precision
= info
.precision
;
510 if (!info
.subnames
.empty()) {
511 for (off_type i
= 0; i
< info
.x
; ++i
)
512 if (!info
.subnames
[i
].empty())
516 VResult
tot_vec(info
.y
);
517 Result super_total
= 0.0;
518 for (off_type i
= 0; i
< info
.x
; ++i
) {
519 if (havesub
&& (i
>= info
.subnames
.size() || info
.subnames
[i
].empty()))
522 off_type iy
= i
* info
.y
;
523 VResult
yvec(info
.y
);
526 for (off_type j
= 0; j
< info
.y
; ++j
) {
527 yvec
[j
] = info
.cvec
[iy
+ j
];
528 tot_vec
[j
] += yvec
[j
];
530 super_total
+= yvec
[j
];
533 print
.name
= info
.name
+ "_" +
534 (havesub
? info
.subnames
[i
] : to_string(i
));
535 print
.desc
= info
.desc
;
541 if (info
.flags
.isSet(::Stats::total
) && (info
.x
> 1)) {
542 print
.name
= info
.name
;
543 print
.desc
= info
.desc
;
545 print
.total
= super_total
;
551 Text::visit(const DistInfo
&info
)
556 DistPrint
print(this, info
);
561 Text::visit(const VectorDistInfo
&info
)
566 for (off_type i
= 0; i
< info
.size(); ++i
) {
567 DistPrint
print(this, info
, i
);
573 Text::visit(const FormulaInfo
&info
)
575 visit((const VectorInfo
&)info
);
579 initText(const string
&filename
, bool desc
)
582 static bool connected
= false;
587 extern list
<Output
*> OutputList
;
589 text
.open(*simout
.find(filename
));
590 text
.descriptions
= desc
;
591 OutputList
.push_back(&text
);