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