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