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