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