text.cc revision 2632:1bb2f91485ea
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 */ } 737