56#include <cmath> 57#include <functional> 58#include <iosfwd> 59#include <string> 60#include <vector> 61 62#include "base/cprintf.hh" 63#include "base/intmath.hh" 64#include "base/refcnt.hh" 65#include "base/str.hh" 66#include "base/stats/flags.hh" 67#include "base/stats/visit.hh" 68#include "base/stats/types.hh" 69#include "sim/host.hh" 70 71class Callback; 72 73/** The current simulated cycle. */ 74extern Tick curTick; 75 76/* A namespace for all of the Statistics */ 77namespace Stats { 78 79/* Contains the statistic implementation details */ 80////////////////////////////////////////////////////////////////////// 81// 82// Statistics Framework Base classes 83// 84////////////////////////////////////////////////////////////////////// 85struct StatData 86{ 87 /** The name of the stat. */ 88 std::string name; 89 /** The description of the stat. */ 90 std::string desc; 91 /** The formatting flags. */ 92 StatFlags flags; 93 /** The display precision. */ 94 int precision; 95 /** A pointer to a prerequisite Stat. */ 96 const StatData *prereq; 97 /** 98 * A unique stat ID for each stat in the simulator. 99 * Can be used externally for lookups as well as for debugging. 100 */ 101 int id; 102 103 StatData(); 104 virtual ~StatData(); 105 106 /** 107 * Reset the corresponding stat to the default state. 108 */ 109 virtual void reset() = 0; 110 111 /** 112 * @return true if this stat has a value and satisfies its 113 * requirement as a prereq 114 */ 115 virtual bool zero() const = 0; 116 117 /** 118 * Check that this stat has been set up properly and is ready for 119 * use 120 * @return true for success 121 */ 122 virtual bool check() const = 0; 123 bool baseCheck() const; 124 125 /** 126 * Visitor entry for outputing statistics data 127 */ 128 virtual void visit(Visit &visitor) = 0; 129 130 /** 131 * Checks if the first stat's name is alphabetically less than the second. 132 * This function breaks names up at periods and considers each subname 133 * separately. 134 * @param stat1 The first stat. 135 * @param stat2 The second stat. 136 * @return stat1's name is alphabetically before stat2's 137 */ 138 static bool less(StatData *stat1, StatData *stat2); 139}; 140 141class ScalarData : public StatData 142{ 143 public: 144 virtual Counter value() const = 0; 145 virtual Result result() const = 0; 146 virtual Result total() const = 0; 147 virtual void visit(Visit &visitor) { visitor.visit(*this); } 148}; 149 150template <class Stat> 151class ScalarStatData : public ScalarData 152{ 153 protected: 154 Stat &s; 155 156 public: 157 ScalarStatData(Stat &stat) : s(stat) {} 158 159 virtual bool check() const { return s.check(); } 160 virtual Counter value() const { return s.value(); } 161 virtual Result result() const { return s.result(); } 162 virtual Result total() const { return s.total(); } 163 virtual void reset() { s.reset(); } 164 virtual bool zero() const { return s.zero(); } 165}; 166 167struct VectorData : public StatData 168{ 169 /** Names and descriptions of subfields. */ 170 mutable std::vector<std::string> subnames; 171 mutable std::vector<std::string> subdescs; 172 173 virtual size_t size() const = 0; 174 virtual const VCounter &value() const = 0; 175 virtual const VResult &result() const = 0; 176 virtual Result total() const = 0; 177 void update() 178 { 179 if (!subnames.empty()) { 180 int s = size(); 181 if (subnames.size() < s) 182 subnames.resize(s); 183 184 if (subdescs.size() < s) 185 subdescs.resize(s); 186 } 187 } 188}; 189 190template <class Stat> 191class VectorStatData : public VectorData 192{ 193 protected: 194 Stat &s; 195 mutable VCounter cvec; 196 mutable VResult rvec; 197 198 public: 199 VectorStatData(Stat &stat) : s(stat) {} 200 201 virtual bool check() const { return s.check(); } 202 virtual bool zero() const { return s.zero(); } 203 virtual void reset() { s.reset(); } 204 205 virtual size_t size() const { return s.size(); } 206 virtual VCounter &value() const 207 { 208 s.value(cvec); 209 return cvec; 210 } 211 virtual const VResult &result() const 212 { 213 s.result(rvec); 214 return rvec; 215 } 216 virtual Result total() const { return s.total(); } 217 virtual void visit(Visit &visitor) 218 { 219 update(); 220 s.update(this); 221 visitor.visit(*this); 222 } 223}; 224 225struct DistDataData 226{ 227 Counter min_val; 228 Counter max_val; 229 Counter underflow; 230 Counter overflow; 231 VCounter cvec; 232 Counter sum; 233 Counter squares; 234 Counter samples; 235 236 Counter min; 237 Counter max; 238 Counter bucket_size; 239 int size; 240 bool fancy; 241}; 242 243struct DistData : public StatData 244{ 245 /** Local storage for the entry values, used for printing. */ 246 DistDataData data; 247}; 248 249template <class Stat> 250class DistStatData : public DistData 251{ 252 protected: 253 Stat &s; 254 255 public: 256 DistStatData(Stat &stat) : s(stat) {} 257 258 virtual bool check() const { return s.check(); } 259 virtual void reset() { s.reset(); } 260 virtual bool zero() const { return s.zero(); } 261 virtual void visit(Visit &visitor) 262 { 263 s.update(this); 264 visitor.visit(*this); 265 } 266}; 267 268struct VectorDistData : public StatData 269{ 270 std::vector<DistDataData> data; 271 272 /** Names and descriptions of subfields. */ 273 mutable std::vector<std::string> subnames; 274 mutable std::vector<std::string> subdescs; 275 276 /** Local storage for the entry values, used for printing. */ 277 mutable VResult rvec; 278 279 virtual size_t size() const = 0; 280 void update() 281 { 282 int s = size(); 283 if (subnames.size() < s) 284 subnames.resize(s); 285 286 if (subdescs.size() < s) 287 subdescs.resize(s); 288 } 289}; 290 291template <class Stat> 292class VectorDistStatData : public VectorDistData 293{ 294 protected: 295 Stat &s; 296 297 public: 298 VectorDistStatData(Stat &stat) : s(stat) {} 299 300 virtual bool check() const { return s.check(); } 301 virtual void reset() { s.reset(); } 302 virtual size_t size() const { return s.size(); } 303 virtual bool zero() const { return s.zero(); } 304 virtual void visit(Visit &visitor) 305 { 306 update(); 307 s.update(this); 308 visitor.visit(*this); 309 } 310}; 311 312struct Vector2dData : public StatData 313{ 314 /** Names and descriptions of subfields. */ 315 std::vector<std::string> subnames; 316 std::vector<std::string> subdescs; 317 std::vector<std::string> y_subnames; 318 319 /** Local storage for the entry values, used for printing. */ 320 mutable VCounter cvec; 321 mutable int x; 322 mutable int y; 323 324 void update() 325 { 326 if (subnames.size() < x) 327 subnames.resize(x); 328 } 329}; 330 331template <class Stat> 332class Vector2dStatData : public Vector2dData 333{ 334 protected: 335 Stat &s; 336 337 public: 338 Vector2dStatData(Stat &stat) : s(stat) {} 339 340 virtual bool check() const { return s.check(); } 341 virtual void reset() { s.reset(); } 342 virtual bool zero() const { return s.zero(); } 343 virtual void visit(Visit &visitor) 344 { 345 update(); 346 s.update(this); 347 visitor.visit(*this); 348 } 349}; 350 351class DataAccess 352{ 353 protected: 354 StatData *find() const; 355 void map(StatData *data); 356 357 StatData *statData(); 358 const StatData *statData() const; 359 360 void setInit(); 361 void setPrint(); 362}; 363 364template <class Parent, class Child, template <class> class Data> 365class Wrap : public Child 366{ 367 protected: 368 Parent &self() { return *reinterpret_cast<Parent *>(this); } 369 370 protected: 371 Data<Child> *statData() 372 { 373 StatData *__data = DataAccess::statData(); 374 Data<Child> *ptr = dynamic_cast<Data<Child> *>(__data); 375 assert(ptr); 376 return ptr; 377 } 378 379 public: 380 const Data<Child> *statData() const 381 { 382 const StatData *__data = DataAccess::statData(); 383 const Data<Child> *ptr = dynamic_cast<const Data<Child> *>(__data); 384 assert(ptr); 385 return ptr; 386 } 387 388 protected: 389 /** 390 * Copy constructor, copies are not allowed. 391 */ 392 Wrap(const Wrap &stat); 393 /** 394 * Can't copy stats. 395 */ 396 void operator=(const Wrap &); 397 398 public: 399 Wrap() 400 { 401 map(new Data<Child>(*this)); 402 } 403 404 /** 405 * Set the name and marks this stat to print at the end of simulation. 406 * @param name The new name. 407 * @return A reference to this stat. 408 */ 409 Parent &name(const std::string &_name) 410 { 411 Data<Child> *data = this->statData(); 412 data->name = _name; 413 this->setPrint(); 414 return this->self(); 415 } 416 417 /** 418 * Set the description and marks this stat to print at the end of 419 * simulation. 420 * @param desc The new description. 421 * @return A reference to this stat. 422 */ 423 Parent &desc(const std::string &_desc) 424 { 425 this->statData()->desc = _desc; 426 return this->self(); 427 } 428 429 /** 430 * Set the precision and marks this stat to print at the end of simulation. 431 * @param p The new precision 432 * @return A reference to this stat. 433 */ 434 Parent &precision(int _precision) 435 { 436 this->statData()->precision = _precision; 437 return this->self(); 438 } 439 440 /** 441 * Set the flags and marks this stat to print at the end of simulation. 442 * @param f The new flags. 443 * @return A reference to this stat. 444 */ 445 Parent &flags(StatFlags _flags) 446 { 447 this->statData()->flags |= _flags; 448 return this->self(); 449 } 450 451 /** 452 * Set the prerequisite stat and marks this stat to print at the end of 453 * simulation. 454 * @param prereq The prerequisite stat. 455 * @return A reference to this stat. 456 */ 457 template <class Stat> 458 Parent &prereq(const Stat &prereq) 459 { 460 this->statData()->prereq = prereq.statData(); 461 return this->self(); 462 } 463}; 464 465template <class Parent, class Child, template <class Child> class Data> 466class WrapVec : public Wrap<Parent, Child, Data> 467{ 468 public: 469 // The following functions are specific to vectors. If you use them 470 // in a non vector context, you will get a nice compiler error! 471 472 /** 473 * Set the subfield name for the given index, and marks this stat to print 474 * at the end of simulation. 475 * @param index The subfield index. 476 * @param name The new name of the subfield. 477 * @return A reference to this stat. 478 */ 479 Parent &subname(int index, const std::string &name) 480 { 481 std::vector<std::string> &subn = this->statData()->subnames; 482 if (subn.size() <= index) 483 subn.resize(index + 1); 484 subn[index] = name; 485 return this->self(); 486 } 487 488 /** 489 * Set the subfield description for the given index and marks this stat to 490 * print at the end of simulation. 491 * @param index The subfield index. 492 * @param desc The new description of the subfield 493 * @return A reference to this stat. 494 */ 495 Parent &subdesc(int index, const std::string &desc) 496 { 497 std::vector<std::string> &subd = this->statData()->subdescs; 498 if (subd.size() <= index) 499 subd.resize(index + 1); 500 subd[index] = desc; 501 502 return this->self(); 503 } 504 505}; 506 507template <class Parent, class Child, template <class Child> class Data> 508class WrapVec2d : public WrapVec<Parent, Child, Data> 509{ 510 public: 511 /** 512 * @warning This makes the assumption that if you're gonna subnames a 2d 513 * vector, you're subnaming across all y 514 */ 515 Parent &ysubnames(const char **names) 516 { 517 Data<Child> *data = this->statData(); 518 data->y_subnames.resize(this->y); 519 for (int i = 0; i < this->y; ++i) 520 data->y_subnames[i] = names[i]; 521 return this->self(); 522 } 523 Parent &ysubname(int index, const std::string subname) 524 { 525 Data<Child> *data = this->statData(); 526 assert(index < this->y); 527 data->y_subnames.resize(this->y); 528 data->y_subnames[index] = subname.c_str(); 529 return this->self(); 530 } 531}; 532 533////////////////////////////////////////////////////////////////////// 534// 535// Simple Statistics 536// 537////////////////////////////////////////////////////////////////////// 538 539/** 540 * Templatized storage and interface for a simple scalar stat. 541 */ 542struct StatStor 543{ 544 public: 545 /** The paramaters for this storage type, none for a scalar. */ 546 struct Params { }; 547 548 private: 549 /** The statistic value. */ 550 Counter data; 551 552 public: 553 /** 554 * Builds this storage element and calls the base constructor of the 555 * datatype. 556 */ 557 StatStor(const Params &) : data(Counter()) {} 558 559 /** 560 * The the stat to the given value. 561 * @param val The new value. 562 * @param p The paramters of this storage type. 563 */ 564 void set(Counter val, const Params &p) { data = val; } 565 /** 566 * Increment the stat by the given value. 567 * @param val The new value. 568 * @param p The paramters of this storage type. 569 */ 570 void inc(Counter val, const Params &p) { data += val; } 571 /** 572 * Decrement the stat by the given value. 573 * @param val The new value. 574 * @param p The paramters of this storage type. 575 */ 576 void dec(Counter val, const Params &p) { data -= val; } 577 /** 578 * Return the value of this stat as its base type. 579 * @param p The params of this storage type. 580 * @return The value of this stat. 581 */ 582 Counter value(const Params &p) const { return data; } 583 /** 584 * Return the value of this stat as a result type. 585 * @param p The parameters of this storage type. 586 * @return The value of this stat. 587 */ 588 Result result(const Params &p) const { return (Result)data; } 589 /** 590 * Reset stat value to default 591 */ 592 void reset() { data = Counter(); } 593 594 /** 595 * @return true if zero value 596 */ 597 bool zero() const { return data == Counter(); } 598}; 599 600/** 601 * Templatized storage and interface to a per-cycle average stat. This keeps 602 * a current count and updates a total (count * cycles) when this count 603 * changes. This allows the quick calculation of a per cycle count of the item 604 * being watched. This is good for keeping track of residencies in structures 605 * among other things. 606 */ 607struct AvgStor 608{ 609 public: 610 /** The paramaters for this storage type */ 611 struct Params { }; 612 613 private: 614 /** The current count. */ 615 Counter current; 616 /** The total count for all cycles. */ 617 mutable Result total; 618 /** The cycle that current last changed. */ 619 mutable Tick last; 620 621 public: 622 /** 623 * Build and initializes this stat storage. 624 */ 625 AvgStor(Params &p) : current(0), total(0), last(0) { } 626 627 /** 628 * Set the current count to the one provided, update the total and last 629 * set values. 630 * @param val The new count. 631 * @param p The parameters for this storage. 632 */ 633 void set(Counter val, Params &p) { 634 total += current * (curTick - last); 635 last = curTick; 636 current = val; 637 } 638 639 /** 640 * Increment the current count by the provided value, calls set. 641 * @param val The amount to increment. 642 * @param p The parameters for this storage. 643 */ 644 void inc(Counter val, Params &p) { set(current + val, p); } 645 646 /** 647 * Deccrement the current count by the provided value, calls set. 648 * @param val The amount to decrement. 649 * @param p The parameters for this storage. 650 */ 651 void dec(Counter val, Params &p) { set(current - val, p); } 652 653 /** 654 * Return the current count. 655 * @param p The parameters for this storage. 656 * @return The current count. 657 */ 658 Counter value(const Params &p) const { return current; } 659 660 /** 661 * Return the current average. 662 * @param p The parameters for this storage. 663 * @return The current average. 664 */ 665 Result result(const Params &p) const 666 { 667 total += current * (curTick - last); 668 last = curTick; 669 return (Result)(total + current) / (Result)(curTick + 1); 670 } 671 672 /** 673 * Reset stat value to default 674 */ 675 void reset() 676 { 677 total = 0; 678 last = curTick; 679 } 680 681 /** 682 * @return true if zero value 683 */ 684 bool zero() const { return total == 0.0; } 685}; 686 687/** 688 * Implementation of a scalar stat. The type of stat is determined by the 689 * Storage template. 690 */ 691template <class Stor> 692class ScalarBase : public DataAccess 693{ 694 public: 695 typedef Stor Storage; 696 697 /** Define the params of the storage class. */ 698 typedef typename Storage::Params Params; 699 700 protected: 701 /** The storage of this stat. */ 702 char storage[sizeof(Storage)] __attribute__ ((aligned (8))); 703 704 /** The parameters for this stat. */ 705 Params params; 706 707 protected: 708 /** 709 * Retrieve the storage. 710 * @param index The vector index to access. 711 * @return The storage object at the given index. 712 */ 713 Storage * 714 data() 715 { 716 return reinterpret_cast<Storage *>(storage); 717 } 718 719 /** 720 * Retrieve a const pointer to the storage. 721 * for the given index. 722 * @param index The vector index to access. 723 * @return A const pointer to the storage object at the given index. 724 */ 725 const Storage * 726 data() const 727 { 728 return reinterpret_cast<const Storage *>(storage); 729 } 730 731 void 732 doInit() 733 { 734 new (storage) Storage(params); 735 setInit(); 736 } 737 738 public: 739 /** 740 * Return the current value of this stat as its base type. 741 * @return The current value. 742 */ 743 Counter value() const { return data()->value(params); } 744 745 public: 746 /** 747 * Create and initialize this stat, register it with the database. 748 */ 749 ScalarBase() 750 { } 751 752 public: 753 // Common operators for stats 754 /** 755 * Increment the stat by 1. This calls the associated storage object inc 756 * function. 757 */ 758 void operator++() { data()->inc(1, params); } 759 /** 760 * Decrement the stat by 1. This calls the associated storage object dec 761 * function. 762 */ 763 void operator--() { data()->dec(1, params); } 764 765 /** Increment the stat by 1. */ 766 void operator++(int) { ++*this; } 767 /** Decrement the stat by 1. */ 768 void operator--(int) { --*this; } 769 770 /** 771 * Set the data value to the given value. This calls the associated storage 772 * object set function. 773 * @param v The new value. 774 */ 775 template <typename U> 776 void operator=(const U &v) { data()->set(v, params); } 777 778 /** 779 * Increment the stat by the given value. This calls the associated 780 * storage object inc function. 781 * @param v The value to add. 782 */ 783 template <typename U> 784 void operator+=(const U &v) { data()->inc(v, params); } 785 786 /** 787 * Decrement the stat by the given value. This calls the associated 788 * storage object dec function. 789 * @param v The value to substract. 790 */ 791 template <typename U> 792 void operator-=(const U &v) { data()->dec(v, params); } 793 794 /** 795 * Return the number of elements, always 1 for a scalar. 796 * @return 1. 797 */ 798 size_t size() const { return 1; } 799 800 bool check() const { return true; } 801 802 /** 803 * Reset stat value to default 804 */ 805 void reset() { data()->reset(); } 806 807 Counter value() { return data()->value(params); } 808 809 Result result() { return data()->result(params); } 810 811 Result total() { return result(); } 812 813 bool zero() { return result() == 0.0; } 814 815}; 816 817class ProxyData : public ScalarData 818{ 819 public: 820 virtual void visit(Visit &visitor) { visitor.visit(*this); } 821 virtual std::string str() const { return to_string(value()); } 822 virtual size_t size() const { return 1; } 823 virtual bool zero() const { return value() == 0; } 824 virtual bool check() const { return true; } 825 virtual void reset() { } 826}; 827 828template <class T> 829class ValueProxy : public ProxyData 830{ 831 private: 832 T *scalar; 833 834 public: 835 ValueProxy(T &val) : scalar(&val) {} 836 virtual Counter value() const { return *scalar; } 837 virtual Result result() const { return *scalar; } 838 virtual Result total() const { return *scalar; } 839}; 840 841template <class T> 842class FunctorProxy : public ProxyData 843{ 844 private: 845 T *functor; 846 847 public: 848 FunctorProxy(T &func) : functor(&func) {} 849 virtual Counter value() const { return (*functor)(); } 850 virtual Result result() const { return (*functor)(); } 851 virtual Result total() const { return (*functor)(); } 852}; 853 854class ValueBase : public DataAccess 855{ 856 private: 857 ProxyData *proxy; 858 859 public: 860 ValueBase() : proxy(NULL) { } 861 ~ValueBase() { if (proxy) delete proxy; } 862 863 template <class T> 864 void scalar(T &value) 865 { 866 proxy = new ValueProxy<T>(value); 867 setInit(); 868 } 869 870 template <class T> 871 void functor(T &func) 872 { 873 proxy = new FunctorProxy<T>(func); 874 setInit(); 875 } 876 877 Counter value() { return proxy->value(); } 878 Result result() const { return proxy->result(); } 879 Result total() const { return proxy->total(); }; 880 size_t size() const { return proxy->size(); } 881 882 std::string str() const { return proxy->str(); } 883 bool zero() const { return proxy->zero(); } 884 bool check() const { return proxy != NULL; } 885 void reset() { } 886}; 887 888////////////////////////////////////////////////////////////////////// 889// 890// Vector Statistics 891// 892////////////////////////////////////////////////////////////////////// 893 894/** 895 * A proxy class to access the stat at a given index in a VectorBase stat. 896 * Behaves like a ScalarBase. 897 */ 898template <class Stat> 899class ScalarProxy 900{ 901 private: 902 /** Pointer to the parent Vector. */ 903 Stat *stat; 904 905 /** The index to access in the parent VectorBase. */ 906 int index; 907 908 public: 909 /** 910 * Return the current value of this stat as its base type. 911 * @return The current value. 912 */ 913 Counter value() const { return stat->data(index)->value(stat->params); } 914 915 /** 916 * Return the current value of this statas a result type. 917 * @return The current value. 918 */ 919 Result result() const { return stat->data(index)->result(stat->params); } 920 921 public: 922 /** 923 * Create and initialize this proxy, do not register it with the database. 924 * @param p The params to use. 925 * @param i The index to access. 926 */ 927 ScalarProxy(Stat *s, int i) 928 : stat(s), index(i) 929 { 930 assert(stat); 931 } 932 933 /** 934 * Create a copy of the provided ScalarProxy. 935 * @param sp The proxy to copy. 936 */ 937 ScalarProxy(const ScalarProxy &sp) 938 : stat(sp.stat), index(sp.index) 939 {} 940 941 /** 942 * Set this proxy equal to the provided one. 943 * @param sp The proxy to copy. 944 * @return A reference to this proxy. 945 */ 946 const ScalarProxy &operator=(const ScalarProxy &sp) { 947 stat = sp.stat; 948 index = sp.index; 949 return *this; 950 } 951 952 public: 953 // Common operators for stats 954 /** 955 * Increment the stat by 1. This calls the associated storage object inc 956 * function. 957 */ 958 void operator++() { stat->data(index)->inc(1, stat->params); } 959 /** 960 * Decrement the stat by 1. This calls the associated storage object dec 961 * function. 962 */ 963 void operator--() { stat->data(index)->dec(1, stat->params); } 964 965 /** Increment the stat by 1. */ 966 void operator++(int) { ++*this; } 967 /** Decrement the stat by 1. */ 968 void operator--(int) { --*this; } 969 970 /** 971 * Set the data value to the given value. This calls the associated storage 972 * object set function. 973 * @param v The new value. 974 */ 975 template <typename U> 976 void operator=(const U &v) { stat->data(index)->set(v, stat->params); } 977 978 /** 979 * Increment the stat by the given value. This calls the associated 980 * storage object inc function. 981 * @param v The value to add. 982 */ 983 template <typename U> 984 void operator+=(const U &v) { stat->data(index)->inc(v, stat->params); } 985 986 /** 987 * Decrement the stat by the given value. This calls the associated 988 * storage object dec function. 989 * @param v The value to substract. 990 */ 991 template <typename U> 992 void operator-=(const U &v) { stat->data(index)->dec(v, stat->params); } 993 994 /** 995 * Return the number of elements, always 1 for a scalar. 996 * @return 1. 997 */ 998 size_t size() const { return 1; } 999 1000 /** 1001 * This stat has no state. Nothing to reset 1002 */ 1003 void reset() { } 1004 1005 public: 1006 std::string 1007 str() const 1008 { 1009 return csprintf("%s[%d]", stat->str(), index); 1010 1011 } 1012}; 1013 1014/** 1015 * Implementation of a vector of stats. The type of stat is determined by the 1016 * Storage class. @sa ScalarBase 1017 */ 1018template <class Stor> 1019class VectorBase : public DataAccess 1020{ 1021 public: 1022 typedef Stor Storage; 1023 1024 /** Define the params of the storage class. */ 1025 typedef typename Storage::Params Params; 1026 1027 /** Proxy type */ 1028 typedef ScalarProxy<VectorBase<Storage> > Proxy; 1029 1030 friend class ScalarProxy<VectorBase<Storage> >; 1031 1032 protected: 1033 /** The storage of this stat. */ 1034 Storage *storage; 1035 size_t _size; 1036 1037 /** The parameters for this stat. */ 1038 Params params; 1039 1040 protected: 1041 /** 1042 * Retrieve the storage. 1043 * @param index The vector index to access. 1044 * @return The storage object at the given index. 1045 */ 1046 Storage *data(int index) { return &storage[index]; } 1047 1048 /** 1049 * Retrieve a const pointer to the storage. 1050 * @param index The vector index to access. 1051 * @return A const pointer to the storage object at the given index. 1052 */ 1053 const Storage *data(int index) const { return &storage[index]; } 1054 1055 void 1056 doInit(int s) 1057 { 1058 assert(s > 0 && "size must be positive!"); 1059 assert(!storage && "already initialized"); 1060 _size = s; 1061 1062 char *ptr = new char[_size * sizeof(Storage)]; 1063 storage = reinterpret_cast<Storage *>(ptr); 1064 1065 for (int i = 0; i < _size; ++i) 1066 new (&storage[i]) Storage(params); 1067 1068 setInit(); 1069 } 1070 1071 public: 1072 void value(VCounter &vec) const 1073 { 1074 vec.resize(size()); 1075 for (int i = 0; i < size(); ++i) 1076 vec[i] = data(i)->value(params); 1077 } 1078 1079 /** 1080 * Copy the values to a local vector and return a reference to it. 1081 * @return A reference to a vector of the stat values. 1082 */ 1083 void result(VResult &vec) const 1084 { 1085 vec.resize(size()); 1086 for (int i = 0; i < size(); ++i) 1087 vec[i] = data(i)->result(params); 1088 } 1089 1090 /** 1091 * Return a total of all entries in this vector. 1092 * @return The total of all vector entries. 1093 */ 1094 Result total() const { 1095 Result total = 0.0; 1096 for (int i = 0; i < size(); ++i) 1097 total += data(i)->result(params); 1098 return total; 1099 } 1100 1101 /** 1102 * @return the number of elements in this vector. 1103 */ 1104 size_t size() const { return _size; } 1105 1106 bool 1107 zero() const 1108 { 1109 for (int i = 0; i < size(); ++i) 1110 if (data(i)->zero()) 1111 return false; 1112 return true; 1113 } 1114 1115 bool 1116 check() const 1117 { 1118 return storage != NULL; 1119 } 1120 1121 void 1122 reset() 1123 { 1124 for (int i = 0; i < size(); ++i) 1125 data(i)->reset(); 1126 } 1127 1128 public: 1129 VectorBase() 1130 : storage(NULL) 1131 {} 1132 1133 ~VectorBase() 1134 { 1135 if (!storage) 1136 return; 1137 1138 for (int i = 0; i < _size; ++i) 1139 data(i)->~Storage(); 1140 delete [] reinterpret_cast<char *>(storage); 1141 } 1142 1143 /** 1144 * Return a reference (ScalarProxy) to the stat at the given index. 1145 * @param index The vector index to access. 1146 * @return A reference of the stat. 1147 */ 1148 Proxy 1149 operator[](int index) 1150 { 1151 assert (index >= 0 && index < size()); 1152 return Proxy(this, index); 1153 } 1154 1155 void update(StatData *data) {} 1156}; 1157 1158template <class Stat> 1159class VectorProxy 1160{ 1161 private: 1162 Stat *stat; 1163 int offset; 1164 int len; 1165 1166 private: 1167 mutable VResult vec; 1168 1169 typename Stat::Storage * 1170 data(int index) 1171 { 1172 assert(index < len); 1173 return stat->data(offset + index); 1174 } 1175 1176 const typename Stat::Storage * 1177 data(int index) const 1178 { 1179 assert(index < len); 1180 return const_cast<Stat *>(stat)->data(offset + index); 1181 } 1182 1183 public: 1184 const VResult & 1185 result() const 1186 { 1187 vec.resize(size()); 1188 1189 for (int i = 0; i < size(); ++i) 1190 vec[i] = data(i)->result(stat->params); 1191 1192 return vec; 1193 } 1194 1195 Result 1196 total() const 1197 { 1198 Result total = 0; 1199 for (int i = 0; i < size(); ++i) 1200 total += data(i)->result(stat->params); 1201 return total; 1202 } 1203 1204 public: 1205 VectorProxy(Stat *s, int o, int l) 1206 : stat(s), offset(o), len(l) 1207 { 1208 } 1209 1210 VectorProxy(const VectorProxy &sp) 1211 : stat(sp.stat), offset(sp.offset), len(sp.len) 1212 { 1213 } 1214 1215 const VectorProxy & 1216 operator=(const VectorProxy &sp) 1217 { 1218 stat = sp.stat; 1219 offset = sp.offset; 1220 len = sp.len; 1221 return *this; 1222 } 1223 1224 ScalarProxy<Stat> operator[](int index) 1225 { 1226 assert (index >= 0 && index < size()); 1227 return ScalarProxy<Stat>(stat, offset + index); 1228 } 1229 1230 size_t size() const { return len; } 1231 1232 /** 1233 * This stat has no state. Nothing to reset. 1234 */ 1235 void reset() { } 1236}; 1237 1238template <class Stor> 1239class Vector2dBase : public DataAccess 1240{ 1241 public: 1242 typedef Stor Storage; 1243 typedef typename Storage::Params Params; 1244 typedef VectorProxy<Vector2dBase<Storage> > Proxy; 1245 friend class ScalarProxy<Vector2dBase<Storage> >; 1246 friend class VectorProxy<Vector2dBase<Storage> >; 1247 1248 protected: 1249 size_t x; 1250 size_t y; 1251 size_t _size; 1252 Storage *storage; 1253 Params params; 1254 1255 protected: 1256 Storage *data(int index) { return &storage[index]; } 1257 const Storage *data(int index) const { return &storage[index]; } 1258 1259 void 1260 doInit(int _x, int _y) 1261 { 1262 assert(_x > 0 && _y > 0 && "sizes must be positive!"); 1263 assert(!storage && "already initialized"); 1264 1265 Vector2dData *statdata = dynamic_cast<Vector2dData *>(find()); 1266 1267 x = _x; 1268 y = _y; 1269 statdata->x = _x; 1270 statdata->y = _y; 1271 _size = x * y; 1272 1273 char *ptr = new char[_size * sizeof(Storage)]; 1274 storage = reinterpret_cast<Storage *>(ptr); 1275 1276 for (int i = 0; i < _size; ++i) 1277 new (&storage[i]) Storage(params); 1278 1279 setInit(); 1280 } 1281 1282 public: 1283 Vector2dBase() 1284 : storage(NULL) 1285 {} 1286 1287 ~Vector2dBase() 1288 { 1289 if (!storage) 1290 return; 1291 1292 for (int i = 0; i < _size; ++i) 1293 data(i)->~Storage(); 1294 delete [] reinterpret_cast<char *>(storage); 1295 } 1296 1297 void 1298 update(Vector2dData *newdata) 1299 { 1300 int size = this->size(); 1301 newdata->cvec.resize(size); 1302 for (int i = 0; i < size; ++i) 1303 newdata->cvec[i] = data(i)->value(params); 1304 } 1305 1306 std::string ysubname(int i) const { return (*this->y_subnames)[i]; } 1307 1308 Proxy 1309 operator[](int index) 1310 { 1311 int offset = index * y; 1312 assert (index >= 0 && offset + index < size()); 1313 return Proxy(this, offset, y); 1314 } 1315 1316 1317 size_t 1318 size() const 1319 { 1320 return _size; 1321 } 1322 1323 bool 1324 zero() const 1325 { 1326 return data(0)->zero(); 1327#if 0 1328 for (int i = 0; i < size(); ++i) 1329 if (!data(i)->zero()) 1330 return false; 1331 return true; 1332#endif 1333 } 1334 1335 /** 1336 * Reset stat value to default 1337 */ 1338 void 1339 reset() 1340 { 1341 for (int i = 0; i < size(); ++i) 1342 data(i)->reset(); 1343 } 1344 1345 bool 1346 check() 1347 { 1348 return storage != NULL; 1349 } 1350}; 1351 1352////////////////////////////////////////////////////////////////////// 1353// 1354// Non formula statistics 1355// 1356////////////////////////////////////////////////////////////////////// 1357 1358/** 1359 * Templatized storage and interface for a distrbution stat. 1360 */ 1361struct DistStor 1362{ 1363 public: 1364 /** The parameters for a distribution stat. */ 1365 struct Params 1366 { 1367 /** The minimum value to track. */ 1368 Counter min; 1369 /** The maximum value to track. */ 1370 Counter max; 1371 /** The number of entries in each bucket. */ 1372 Counter bucket_size; 1373 /** The number of buckets. Equal to (max-min)/bucket_size. */ 1374 int size; 1375 }; 1376 enum { fancy = false }; 1377 1378 private: 1379 /** The smallest value sampled. */ 1380 Counter min_val; 1381 /** The largest value sampled. */ 1382 Counter max_val; 1383 /** The number of values sampled less than min. */ 1384 Counter underflow; 1385 /** The number of values sampled more than max. */ 1386 Counter overflow; 1387 /** The current sum. */ 1388 Counter sum; 1389 /** The sum of squares. */ 1390 Counter squares; 1391 /** The number of samples. */ 1392 Counter samples; 1393 /** Counter for each bucket. */ 1394 VCounter cvec; 1395 1396 public: 1397 DistStor(const Params ¶ms) 1398 : cvec(params.size) 1399 { 1400 reset(); 1401 } 1402 1403 /** 1404 * Add a value to the distribution for the given number of times. 1405 * @param val The value to add. 1406 * @param number The number of times to add the value. 1407 * @param params The paramters of the distribution. 1408 */ 1409 void sample(Counter val, int number, const Params ¶ms) 1410 { 1411 if (val < params.min) 1412 underflow += number; 1413 else if (val > params.max) 1414 overflow += number; 1415 else {
|
1417 assert(index < size(params)); 1418 cvec[index] += number; 1419 } 1420 1421 if (val < min_val) 1422 min_val = val; 1423 1424 if (val > max_val) 1425 max_val = val; 1426 1427 Counter sample = val * number; 1428 sum += sample; 1429 squares += sample * sample; 1430 samples += number; 1431 } 1432 1433 /** 1434 * Return the number of buckets in this distribution. 1435 * @return the number of buckets. 1436 * @todo Is it faster to return the size from the parameters? 1437 */ 1438 size_t size(const Params &) const { return cvec.size(); } 1439 1440 /** 1441 * Returns true if any calls to sample have been made. 1442 * @param params The paramters of the distribution. 1443 * @return True if any values have been sampled. 1444 */ 1445 bool zero(const Params ¶ms) const 1446 { 1447 return samples == Counter(); 1448 } 1449 1450 void update(DistDataData *data, const Params ¶ms) 1451 { 1452 data->min = params.min; 1453 data->max = params.max; 1454 data->bucket_size = params.bucket_size; 1455 data->size = params.size; 1456 1457 data->min_val = (min_val == INT_MAX) ? 0 : min_val; 1458 data->max_val = (max_val == INT_MIN) ? 0 : max_val; 1459 data->underflow = underflow; 1460 data->overflow = overflow; 1461 data->cvec.resize(params.size); 1462 for (int i = 0; i < params.size; ++i) 1463 data->cvec[i] = cvec[i]; 1464 1465 data->sum = sum; 1466 data->squares = squares; 1467 data->samples = samples; 1468 } 1469 1470 /** 1471 * Reset stat value to default 1472 */ 1473 void reset() 1474 { 1475 min_val = INT_MAX; 1476 max_val = INT_MIN; 1477 underflow = 0; 1478 overflow = 0; 1479 1480 int size = cvec.size(); 1481 for (int i = 0; i < size; ++i) 1482 cvec[i] = Counter(); 1483 1484 sum = Counter(); 1485 squares = Counter(); 1486 samples = Counter(); 1487 } 1488}; 1489 1490/** 1491 * Templatized storage and interface for a distribution that calculates mean 1492 * and variance. 1493 */ 1494struct FancyStor 1495{ 1496 public: 1497 /** 1498 * No paramters for this storage. 1499 */ 1500 struct Params {}; 1501 enum { fancy = true }; 1502 1503 private: 1504 /** The current sum. */ 1505 Counter sum; 1506 /** The sum of squares. */ 1507 Counter squares; 1508 /** The number of samples. */ 1509 Counter samples; 1510 1511 public: 1512 /** 1513 * Create and initialize this storage. 1514 */ 1515 FancyStor(const Params &) 1516 : sum(Counter()), squares(Counter()), samples(Counter()) 1517 { } 1518 1519 /** 1520 * Add a value the given number of times to this running average. 1521 * Update the running sum and sum of squares, increment the number of 1522 * values seen by the given number. 1523 * @param val The value to add. 1524 * @param number The number of times to add the value. 1525 * @param p The parameters of this stat. 1526 */ 1527 void sample(Counter val, int number, const Params &p) 1528 { 1529 Counter value = val * number; 1530 sum += value; 1531 squares += value * value; 1532 samples += number; 1533 } 1534 1535 void update(DistDataData *data, const Params ¶ms) 1536 { 1537 data->sum = sum; 1538 data->squares = squares; 1539 data->samples = samples; 1540 } 1541 1542 /** 1543 * Return the number of entries in this stat, 1 1544 * @return 1. 1545 */ 1546 size_t size(const Params &) const { return 1; } 1547 1548 /** 1549 * Return true if no samples have been added. 1550 * @return True if no samples have been added. 1551 */ 1552 bool zero(const Params &) const { return samples == Counter(); } 1553 1554 /** 1555 * Reset stat value to default 1556 */ 1557 void reset() 1558 { 1559 sum = Counter(); 1560 squares = Counter(); 1561 samples = Counter(); 1562 } 1563}; 1564 1565/** 1566 * Templatized storage for distribution that calculates per cycle mean and 1567 * variance. 1568 */ 1569struct AvgFancy 1570{ 1571 public: 1572 /** No parameters for this storage. */ 1573 struct Params {}; 1574 enum { fancy = true }; 1575 1576 private: 1577 /** Current total. */ 1578 Counter sum; 1579 /** Current sum of squares. */ 1580 Counter squares; 1581 1582 public: 1583 /** 1584 * Create and initialize this storage. 1585 */ 1586 AvgFancy(const Params &) : sum(Counter()), squares(Counter()) {} 1587 1588 /** 1589 * Add a value to the distribution for the given number of times. 1590 * Update the running sum and sum of squares. 1591 * @param val The value to add. 1592 * @param number The number of times to add the value. 1593 * @param p The paramters of the distribution. 1594 */ 1595 void sample(Counter val, int number, const Params &p) 1596 { 1597 Counter value = val * number; 1598 sum += value; 1599 squares += value * value; 1600 } 1601 1602 void update(DistDataData *data, const Params ¶ms) 1603 { 1604 data->sum = sum; 1605 data->squares = squares; 1606 data->samples = curTick; 1607 } 1608 1609 /** 1610 * Return the number of entries, in this case 1. 1611 * @return 1. 1612 */ 1613 size_t size(const Params ¶ms) const { return 1; } 1614 /** 1615 * Return true if no samples have been added. 1616 * @return True if the sum is zero. 1617 */ 1618 bool zero(const Params ¶ms) const { return sum == Counter(); } 1619 /** 1620 * Reset stat value to default 1621 */ 1622 void reset() 1623 { 1624 sum = Counter(); 1625 squares = Counter(); 1626 } 1627}; 1628 1629/** 1630 * Implementation of a distribution stat. The type of distribution is 1631 * determined by the Storage template. @sa ScalarBase 1632 */ 1633template <class Stor> 1634class DistBase : public DataAccess 1635{ 1636 public: 1637 typedef Stor Storage; 1638 /** Define the params of the storage class. */ 1639 typedef typename Storage::Params Params; 1640 1641 protected: 1642 /** The storage for this stat. */ 1643 char storage[sizeof(Storage)] __attribute__ ((aligned (8))); 1644 1645 /** The parameters for this stat. */ 1646 Params params; 1647 1648 protected: 1649 /** 1650 * Retrieve the storage. 1651 * @return The storage object for this stat. 1652 */ 1653 Storage *data() 1654 { 1655 return reinterpret_cast<Storage *>(storage); 1656 } 1657 1658 /** 1659 * Retrieve a const pointer to the storage. 1660 * @return A const pointer to the storage object for this stat. 1661 */ 1662 const Storage * 1663 data() const 1664 { 1665 return reinterpret_cast<const Storage *>(storage); 1666 } 1667 1668 void 1669 doInit() 1670 { 1671 new (storage) Storage(params); 1672 setInit(); 1673 } 1674 1675 public: 1676 DistBase() { } 1677 1678 /** 1679 * Add a value to the distribtion n times. Calls sample on the storage 1680 * class. 1681 * @param v The value to add. 1682 * @param n The number of times to add it, defaults to 1. 1683 */ 1684 template <typename U> 1685 void sample(const U &v, int n = 1) { data()->sample(v, n, params); } 1686 1687 /** 1688 * Return the number of entries in this stat. 1689 * @return The number of entries. 1690 */ 1691 size_t size() const { return data()->size(params); } 1692 /** 1693 * Return true if no samples have been added. 1694 * @return True if there haven't been any samples. 1695 */ 1696 bool zero() const { return data()->zero(params); } 1697 1698 void update(DistData *base) 1699 { 1700 base->data.fancy = Storage::fancy; 1701 data()->update(&(base->data), params); 1702 } 1703 1704 /** 1705 * Reset stat value to default 1706 */ 1707 void 1708 reset() 1709 { 1710 data()->reset(); 1711 } 1712 1713 bool 1714 check() 1715 { 1716 return true; 1717 } 1718}; 1719 1720template <class Stat> 1721class DistProxy; 1722 1723template <class Stor> 1724class VectorDistBase : public DataAccess 1725{ 1726 public: 1727 typedef Stor Storage; 1728 typedef typename Storage::Params Params; 1729 typedef DistProxy<VectorDistBase<Storage> > Proxy; 1730 friend class DistProxy<VectorDistBase<Storage> >; 1731 1732 protected: 1733 Storage *storage; 1734 size_t _size; 1735 Params params; 1736 1737 protected: 1738 Storage * 1739 data(int index) 1740 { 1741 return &storage[index]; 1742 } 1743 1744 const Storage * 1745 data(int index) const 1746 { 1747 return &storage[index]; 1748 } 1749 1750 void 1751 doInit(int s) 1752 { 1753 assert(s > 0 && "size must be positive!"); 1754 assert(!storage && "already initialized"); 1755 _size = s; 1756 1757 char *ptr = new char[_size * sizeof(Storage)]; 1758 storage = reinterpret_cast<Storage *>(ptr); 1759 1760 for (int i = 0; i < _size; ++i) 1761 new (&storage[i]) Storage(params); 1762 1763 setInit(); 1764 } 1765 1766 public: 1767 VectorDistBase() 1768 : storage(NULL) 1769 {} 1770 1771 ~VectorDistBase() 1772 { 1773 if (!storage) 1774 return ; 1775 1776 for (int i = 0; i < _size; ++i) 1777 data(i)->~Storage(); 1778 delete [] reinterpret_cast<char *>(storage); 1779 } 1780 1781 Proxy operator[](int index); 1782 1783 size_t 1784 size() const 1785 { 1786 return _size; 1787 } 1788 1789 bool 1790 zero() const 1791 { 1792 return false; 1793#if 0 1794 for (int i = 0; i < size(); ++i) 1795 if (!data(i)->zero(params)) 1796 return false; 1797 return true; 1798#endif 1799 } 1800 1801 /** 1802 * Reset stat value to default 1803 */ 1804 void 1805 reset() 1806 { 1807 for (int i = 0; i < size(); ++i) 1808 data(i)->reset(); 1809 } 1810 1811 bool 1812 check() 1813 { 1814 return storage != NULL; 1815 } 1816 1817 void 1818 update(VectorDistData *base) 1819 { 1820 int size = this->size(); 1821 base->data.resize(size); 1822 for (int i = 0; i < size; ++i) { 1823 base->data[i].fancy = Storage::fancy; 1824 data(i)->update(&(base->data[i]), params); 1825 } 1826 } 1827}; 1828 1829template <class Stat> 1830class DistProxy 1831{ 1832 private: 1833 Stat *stat; 1834 int index; 1835 1836 protected: 1837 typename Stat::Storage *data() { return stat->data(index); } 1838 const typename Stat::Storage *data() const { return stat->data(index); } 1839 1840 public: 1841 DistProxy(Stat *s, int i) 1842 : stat(s), index(i) 1843 {} 1844 1845 DistProxy(const DistProxy &sp) 1846 : stat(sp.stat), index(sp.index) 1847 {} 1848 1849 const DistProxy &operator=(const DistProxy &sp) 1850 { 1851 stat = sp.stat; 1852 index = sp.index; 1853 return *this; 1854 } 1855 1856 public: 1857 template <typename U> 1858 void 1859 sample(const U &v, int n = 1) 1860 { 1861 data()->sample(v, n, stat->params); 1862 } 1863 1864 size_t 1865 size() const 1866 { 1867 return 1; 1868 } 1869 1870 bool 1871 zero() const 1872 { 1873 return data()->zero(stat->params); 1874 } 1875 1876 /** 1877 * Proxy has no state. Nothing to reset. 1878 */ 1879 void reset() { } 1880}; 1881 1882template <class Storage> 1883inline typename VectorDistBase<Storage>::Proxy 1884VectorDistBase<Storage>::operator[](int index) 1885{ 1886 assert (index >= 0 && index < size()); 1887 return typename VectorDistBase<Storage>::Proxy(this, index); 1888} 1889 1890#if 0 1891template <class Storage> 1892Result 1893VectorDistBase<Storage>::total(int index) const 1894{ 1895 int total = 0; 1896 for (int i = 0; i < x_size(); ++i) { 1897 total += data(i)->result(stat->params); 1898 } 1899} 1900#endif 1901 1902////////////////////////////////////////////////////////////////////// 1903// 1904// Formula Details 1905// 1906////////////////////////////////////////////////////////////////////// 1907 1908/** 1909 * Base class for formula statistic node. These nodes are used to build a tree 1910 * that represents the formula. 1911 */ 1912class Node : public RefCounted 1913{ 1914 public: 1915 /** 1916 * Return the number of nodes in the subtree starting at this node. 1917 * @return the number of nodes in this subtree. 1918 */ 1919 virtual size_t size() const = 0; 1920 /** 1921 * Return the result vector of this subtree. 1922 * @return The result vector of this subtree. 1923 */ 1924 virtual const VResult &result() const = 0; 1925 /** 1926 * Return the total of the result vector. 1927 * @return The total of the result vector. 1928 */ 1929 virtual Result total() const = 0; 1930 1931 /** 1932 * 1933 */ 1934 virtual std::string str() const = 0; 1935}; 1936 1937/** Reference counting pointer to a function Node. */ 1938typedef RefCountingPtr<Node> NodePtr; 1939 1940class ScalarStatNode : public Node 1941{ 1942 private: 1943 const ScalarData *data; 1944 mutable VResult vresult; 1945 1946 public: 1947 ScalarStatNode(const ScalarData *d) : data(d), vresult(1) {} 1948 virtual const VResult &result() const 1949 { 1950 vresult[0] = data->result(); 1951 return vresult; 1952 } 1953 virtual Result total() const { return data->result(); }; 1954 1955 virtual size_t size() const { return 1; } 1956 1957 /** 1958 * 1959 */ 1960 virtual std::string str() const { return data->name; } 1961}; 1962 1963template <class Stat> 1964class ScalarProxyNode : public Node 1965{ 1966 private: 1967 const ScalarProxy<Stat> proxy; 1968 mutable VResult vresult; 1969 1970 public: 1971 ScalarProxyNode(const ScalarProxy<Stat> &p) 1972 : proxy(p), vresult(1) 1973 { } 1974 1975 virtual const VResult & 1976 result() const 1977 { 1978 vresult[0] = proxy.result(); 1979 return vresult; 1980 } 1981 1982 virtual Result 1983 total() const 1984 { 1985 return proxy.result(); 1986 } 1987 1988 virtual size_t 1989 size() const 1990 { 1991 return 1; 1992 } 1993 1994 /** 1995 * 1996 */ 1997 virtual std::string 1998 str() const 1999 { 2000 return proxy.str(); 2001 } 2002}; 2003 2004class VectorStatNode : public Node 2005{ 2006 private: 2007 const VectorData *data; 2008 2009 public: 2010 VectorStatNode(const VectorData *d) : data(d) { } 2011 virtual const VResult &result() const { return data->result(); } 2012 virtual Result total() const { return data->total(); }; 2013 2014 virtual size_t size() const { return data->size(); } 2015 2016 virtual std::string str() const { return data->name; } 2017}; 2018 2019template <class T> 2020class ConstNode : public Node 2021{ 2022 private: 2023 VResult vresult; 2024 2025 public: 2026 ConstNode(T s) : vresult(1, (Result)s) {} 2027 const VResult &result() const { return vresult; } 2028 virtual Result total() const { return vresult[0]; }; 2029 virtual size_t size() const { return 1; } 2030 virtual std::string str() const { return to_string(vresult[0]); } 2031}; 2032 2033template <class Op> 2034struct OpString; 2035 2036template<> 2037struct OpString<std::plus<Result> > 2038{ 2039 static std::string str() { return "+"; } 2040}; 2041 2042template<> 2043struct OpString<std::minus<Result> > 2044{ 2045 static std::string str() { return "-"; } 2046}; 2047 2048template<> 2049struct OpString<std::multiplies<Result> > 2050{ 2051 static std::string str() { return "*"; } 2052}; 2053 2054template<> 2055struct OpString<std::divides<Result> > 2056{ 2057 static std::string str() { return "/"; } 2058}; 2059 2060template<> 2061struct OpString<std::modulus<Result> > 2062{ 2063 static std::string str() { return "%"; } 2064}; 2065 2066template<> 2067struct OpString<std::negate<Result> > 2068{ 2069 static std::string str() { return "-"; } 2070}; 2071 2072template <class Op> 2073class UnaryNode : public Node 2074{ 2075 public: 2076 NodePtr l; 2077 mutable VResult vresult; 2078 2079 public: 2080 UnaryNode(NodePtr &p) : l(p) {} 2081 2082 const VResult &result() const 2083 { 2084 const VResult &lvec = l->result(); 2085 int size = lvec.size(); 2086 2087 assert(size > 0); 2088 2089 vresult.resize(size); 2090 Op op; 2091 for (int i = 0; i < size; ++i) 2092 vresult[i] = op(lvec[i]); 2093 2094 return vresult; 2095 } 2096 2097 Result total() const { 2098 Op op; 2099 return op(l->total()); 2100 } 2101 2102 virtual size_t size() const { return l->size(); } 2103 2104 virtual std::string str() const 2105 { 2106 return OpString<Op>::str() + l->str(); 2107 } 2108}; 2109 2110template <class Op> 2111class BinaryNode : public Node 2112{ 2113 public: 2114 NodePtr l; 2115 NodePtr r; 2116 mutable VResult vresult; 2117 2118 public: 2119 BinaryNode(NodePtr &a, NodePtr &b) : l(a), r(b) {} 2120 2121 const VResult &result() const 2122 { 2123 Op op; 2124 const VResult &lvec = l->result(); 2125 const VResult &rvec = r->result(); 2126 2127 assert(lvec.size() > 0 && rvec.size() > 0); 2128 2129 if (lvec.size() == 1 && rvec.size() == 1) { 2130 vresult.resize(1); 2131 vresult[0] = op(lvec[0], rvec[0]); 2132 } else if (lvec.size() == 1) { 2133 int size = rvec.size(); 2134 vresult.resize(size); 2135 for (int i = 0; i < size; ++i) 2136 vresult[i] = op(lvec[0], rvec[i]); 2137 } else if (rvec.size() == 1) { 2138 int size = lvec.size(); 2139 vresult.resize(size); 2140 for (int i = 0; i < size; ++i) 2141 vresult[i] = op(lvec[i], rvec[0]); 2142 } else if (rvec.size() == lvec.size()) { 2143 int size = rvec.size(); 2144 vresult.resize(size); 2145 for (int i = 0; i < size; ++i) 2146 vresult[i] = op(lvec[i], rvec[i]); 2147 } 2148 2149 return vresult; 2150 } 2151 2152 Result total() const { 2153 Op op; 2154 return op(l->total(), r->total()); 2155 } 2156 2157 virtual size_t size() const { 2158 int ls = l->size(); 2159 int rs = r->size(); 2160 if (ls == 1) 2161 return rs; 2162 else if (rs == 1) 2163 return ls; 2164 else { 2165 assert(ls == rs && "Node vector sizes are not equal"); 2166 return ls; 2167 } 2168 } 2169 2170 virtual std::string str() const 2171 { 2172 return csprintf("(%s %s %s)", l->str(), OpString<Op>::str(), r->str()); 2173 } 2174}; 2175 2176template <class Op> 2177class SumNode : public Node 2178{ 2179 public: 2180 NodePtr l; 2181 mutable VResult vresult; 2182 2183 public: 2184 SumNode(NodePtr &p) : l(p), vresult(1) {} 2185 2186 const VResult &result() const 2187 { 2188 const VResult &lvec = l->result(); 2189 int size = lvec.size(); 2190 assert(size > 0); 2191 2192 vresult[0] = 0.0; 2193 2194 Op op; 2195 for (int i = 0; i < size; ++i) 2196 vresult[0] = op(vresult[0], lvec[i]); 2197 2198 return vresult; 2199 } 2200 2201 Result total() const 2202 { 2203 const VResult &lvec = l->result(); 2204 int size = lvec.size(); 2205 assert(size > 0); 2206 2207 Result vresult = 0.0; 2208 2209 Op op; 2210 for (int i = 0; i < size; ++i) 2211 vresult = op(vresult, lvec[i]); 2212 2213 return vresult; 2214 } 2215 2216 virtual size_t size() const { return 1; } 2217 2218 virtual std::string str() const 2219 { 2220 return csprintf("total(%s)", l->str()); 2221 } 2222}; 2223 2224 2225////////////////////////////////////////////////////////////////////// 2226// 2227// Visible Statistics Types 2228// 2229////////////////////////////////////////////////////////////////////// 2230/** 2231 * @defgroup VisibleStats "Statistic Types" 2232 * These are the statistics that are used in the simulator. 2233 * @{ 2234 */ 2235 2236/** 2237 * This is a simple scalar statistic, like a counter. 2238 * @sa Stat, ScalarBase, StatStor 2239 */ 2240template<int N = 0> 2241class Scalar : public Wrap<Scalar<N>, ScalarBase<StatStor>, ScalarStatData> 2242{ 2243 public: 2244 /** The base implementation. */ 2245 typedef ScalarBase<StatStor> Base; 2246 2247 Scalar() 2248 { 2249 this->doInit(); 2250 } 2251 2252 /** 2253 * Sets the stat equal to the given value. Calls the base implementation 2254 * of operator= 2255 * @param v The new value. 2256 */ 2257 template <typename U> 2258 void operator=(const U &v) { Base::operator=(v); } 2259}; 2260 2261class Value : public Wrap<Value, ValueBase, ScalarStatData> 2262{ 2263 public: 2264 /** The base implementation. */ 2265 typedef ValueBase Base; 2266 2267 template <class T> 2268 Value &scalar(T &value) 2269 { 2270 Base::scalar(value); 2271 return *this; 2272 } 2273 2274 template <class T> 2275 Value &functor(T &func) 2276 { 2277 Base::functor(func); 2278 return *this; 2279 } 2280}; 2281 2282/** 2283 * A stat that calculates the per cycle average of a value. 2284 * @sa Stat, ScalarBase, AvgStor 2285 */ 2286template<int N = 0> 2287class Average : public Wrap<Average<N>, ScalarBase<AvgStor>, ScalarStatData> 2288{ 2289 public: 2290 /** The base implementation. */ 2291 typedef ScalarBase<AvgStor> Base; 2292 2293 Average() 2294 { 2295 this->doInit(); 2296 } 2297 2298 /** 2299 * Sets the stat equal to the given value. Calls the base implementation 2300 * of operator= 2301 * @param v The new value. 2302 */ 2303 template <typename U> 2304 void operator=(const U &v) { Base::operator=(v); } 2305}; 2306 2307/** 2308 * A vector of scalar stats. 2309 * @sa Stat, VectorBase, StatStor 2310 */ 2311template<int N = 0> 2312class Vector : public WrapVec<Vector<N>, VectorBase<StatStor>, VectorStatData> 2313{ 2314 public: 2315 /** The base implementation. */ 2316 typedef ScalarBase<StatStor> Base; 2317 2318 /** 2319 * Set this vector to have the given size. 2320 * @param size The new size. 2321 * @return A reference to this stat. 2322 */ 2323 Vector &init(size_t size) { 2324 this->doInit(size); 2325 return *this; 2326 } 2327}; 2328 2329/** 2330 * A vector of Average stats. 2331 * @sa Stat, VectorBase, AvgStor 2332 */ 2333template<int N = 0> 2334class AverageVector 2335 : public WrapVec<AverageVector<N>, VectorBase<AvgStor>, VectorStatData> 2336{ 2337 public: 2338 /** 2339 * Set this vector to have the given size. 2340 * @param size The new size. 2341 * @return A reference to this stat. 2342 */ 2343 AverageVector &init(size_t size) { 2344 this->doInit(size); 2345 return *this; 2346 } 2347}; 2348 2349/** 2350 * A 2-Dimensional vecto of scalar stats. 2351 * @sa Stat, Vector2dBase, StatStor 2352 */ 2353template<int N = 0> 2354class Vector2d 2355 : public WrapVec2d<Vector2d<N>, Vector2dBase<StatStor>, Vector2dStatData> 2356{ 2357 public: 2358 Vector2d &init(size_t x, size_t y) { 2359 this->doInit(x, y); 2360 return *this; 2361 } 2362}; 2363 2364/** 2365 * A simple distribution stat. 2366 * @sa Stat, DistBase, DistStor 2367 */ 2368template<int N = 0> 2369class Distribution 2370 : public Wrap<Distribution<N>, DistBase<DistStor>, DistStatData> 2371{ 2372 public: 2373 /** Base implementation. */ 2374 typedef DistBase<DistStor> Base; 2375 /** The Parameter type. */ 2376 typedef DistStor::Params Params; 2377 2378 public: 2379 /** 2380 * Set the parameters of this distribution. @sa DistStor::Params 2381 * @param min The minimum value of the distribution. 2382 * @param max The maximum value of the distribution. 2383 * @param bkt The number of values in each bucket. 2384 * @return A reference to this distribution. 2385 */ 2386 Distribution &init(Counter min, Counter max, Counter bkt) { 2387 this->params.min = min; 2388 this->params.max = max; 2389 this->params.bucket_size = bkt; 2390 this->params.size = (int)rint((max - min) / bkt + 1.0); 2391 this->doInit(); 2392 return *this; 2393 } 2394}; 2395 2396/** 2397 * Calculates the mean and variance of all the samples. 2398 * @sa Stat, DistBase, FancyStor 2399 */ 2400template<int N = 0> 2401class StandardDeviation 2402 : public Wrap<StandardDeviation<N>, DistBase<FancyStor>, DistStatData> 2403{ 2404 public: 2405 /** The base implementation */ 2406 typedef DistBase<DistStor> Base; 2407 /** The parameter type. */ 2408 typedef DistStor::Params Params; 2409 2410 public: 2411 /** 2412 * Construct and initialize this distribution. 2413 */ 2414 StandardDeviation() { 2415 this->doInit(); 2416 } 2417}; 2418 2419/** 2420 * Calculates the per cycle mean and variance of the samples. 2421 * @sa Stat, DistBase, AvgFancy 2422 */ 2423template<int N = 0> 2424class AverageDeviation 2425 : public Wrap<AverageDeviation<N>, DistBase<AvgFancy>, DistStatData> 2426{ 2427 public: 2428 /** The base implementation */ 2429 typedef DistBase<DistStor> Base; 2430 /** The parameter type. */ 2431 typedef DistStor::Params Params; 2432 2433 public: 2434 /** 2435 * Construct and initialize this distribution. 2436 */ 2437 AverageDeviation() 2438 { 2439 this->doInit(); 2440 } 2441}; 2442 2443/** 2444 * A vector of distributions. 2445 * @sa Stat, VectorDistBase, DistStor 2446 */ 2447template<int N = 0> 2448class VectorDistribution 2449 : public WrapVec<VectorDistribution<N>, 2450 VectorDistBase<DistStor>, 2451 VectorDistStatData> 2452{ 2453 public: 2454 /** The base implementation */ 2455 typedef VectorDistBase<DistStor> Base; 2456 /** The parameter type. */ 2457 typedef DistStor::Params Params; 2458 2459 public: 2460 /** 2461 * Initialize storage and parameters for this distribution. 2462 * @param size The size of the vector (the number of distributions). 2463 * @param min The minimum value of the distribution. 2464 * @param max The maximum value of the distribution. 2465 * @param bkt The number of values in each bucket. 2466 * @return A reference to this distribution. 2467 */ 2468 VectorDistribution &init(int size, Counter min, Counter max, Counter bkt) { 2469 this->params.min = min; 2470 this->params.max = max; 2471 this->params.bucket_size = bkt; 2472 this->params.size = (int)rint((max - min) / bkt + 1.0); 2473 this->doInit(size); 2474 return *this; 2475 } 2476}; 2477 2478/** 2479 * This is a vector of StandardDeviation stats. 2480 * @sa Stat, VectorDistBase, FancyStor 2481 */ 2482template<int N = 0> 2483class VectorStandardDeviation 2484 : public WrapVec<VectorStandardDeviation<N>, 2485 VectorDistBase<FancyStor>, 2486 VectorDistStatData> 2487{ 2488 public: 2489 /** The base implementation */ 2490 typedef VectorDistBase<FancyStor> Base; 2491 /** The parameter type. */ 2492 typedef DistStor::Params Params; 2493 2494 public: 2495 /** 2496 * Initialize storage for this distribution. 2497 * @param size The size of the vector. 2498 * @return A reference to this distribution. 2499 */ 2500 VectorStandardDeviation &init(int size) { 2501 this->doInit(size); 2502 return *this; 2503 } 2504}; 2505 2506/** 2507 * This is a vector of AverageDeviation stats. 2508 * @sa Stat, VectorDistBase, AvgFancy 2509 */ 2510template<int N = 0> 2511class VectorAverageDeviation 2512 : public WrapVec<VectorAverageDeviation<N>, 2513 VectorDistBase<AvgFancy>, 2514 VectorDistStatData> 2515{ 2516 public: 2517 /** The base implementation */ 2518 typedef VectorDistBase<AvgFancy> Base; 2519 /** The parameter type. */ 2520 typedef DistStor::Params Params; 2521 2522 public: 2523 /** 2524 * Initialize storage for this distribution. 2525 * @param size The size of the vector. 2526 * @return A reference to this distribution. 2527 */ 2528 VectorAverageDeviation &init(int size) { 2529 this->doInit(size); 2530 return *this; 2531 } 2532}; 2533 2534/** 2535 * A formula for statistics that is calculated when printed. A formula is 2536 * stored as a tree of Nodes that represent the equation to calculate. 2537 * @sa Stat, ScalarStat, VectorStat, Node, Temp 2538 */ 2539class FormulaBase : public DataAccess 2540{ 2541 protected: 2542 /** The root of the tree which represents the Formula */ 2543 NodePtr root; 2544 friend class Temp; 2545 2546 public: 2547 /** 2548 * Return the result of the Fomula in a vector. If there were no Vector 2549 * components to the Formula, then the vector is size 1. If there were, 2550 * like x/y with x being a vector of size 3, then the result returned will 2551 * be x[0]/y, x[1]/y, x[2]/y, respectively. 2552 * @return The result vector. 2553 */ 2554 void result(VResult &vec) const; 2555 2556 /** 2557 * Return the total Formula result. If there is a Vector 2558 * component to this Formula, then this is the result of the 2559 * Formula if the formula is applied after summing all the 2560 * components of the Vector. For example, if Formula is x/y where 2561 * x is size 3, then total() will return (x[1]+x[2]+x[3])/y. If 2562 * there is no Vector component, total() returns the same value as 2563 * the first entry in the VResult val() returns. 2564 * @return The total of the result vector. 2565 */ 2566 Result total() const; 2567 2568 /** 2569 * Return the number of elements in the tree. 2570 */ 2571 size_t size() const; 2572 2573 bool check() const { return true; } 2574 2575 /** 2576 * Formulas don't need to be reset 2577 */ 2578 void reset(); 2579 2580 /** 2581 * 2582 */ 2583 bool zero() const; 2584 2585 /** 2586 * 2587 */ 2588 void update(StatData *); 2589 2590 std::string str() const; 2591}; 2592 2593class FormulaData : public VectorData 2594{ 2595 public: 2596 virtual std::string str() const = 0; 2597 virtual bool check() const { return true; } 2598}; 2599 2600template <class Stat> 2601class FormulaStatData : public FormulaData 2602{ 2603 protected: 2604 Stat &s; 2605 mutable VResult vec; 2606 mutable VCounter cvec; 2607 2608 public: 2609 FormulaStatData(Stat &stat) : s(stat) {} 2610 2611 virtual bool zero() const { return s.zero(); } 2612 virtual void reset() { s.reset(); } 2613 2614 virtual size_t size() const { return s.size(); } 2615 virtual const VResult &result() const 2616 { 2617 s.result(vec); 2618 return vec; 2619 } 2620 virtual Result total() const { return s.total(); } 2621 virtual VCounter &value() const { return cvec; } 2622 virtual void visit(Visit &visitor) 2623 { 2624 update(); 2625 s.update(this); 2626 visitor.visit(*this); 2627 } 2628 virtual std::string str() const { return s.str(); } 2629}; 2630 2631class Temp; 2632class Formula 2633 : public WrapVec<Formula, 2634 FormulaBase, 2635 FormulaStatData> 2636{ 2637 public: 2638 /** 2639 * Create and initialize thie formula, and register it with the database. 2640 */ 2641 Formula(); 2642 2643 /** 2644 * Create a formula with the given root node, register it with the 2645 * database. 2646 * @param r The root of the expression tree. 2647 */ 2648 Formula(Temp r); 2649 2650 /** 2651 * Set an unitialized Formula to the given root. 2652 * @param r The root of the expression tree. 2653 * @return a reference to this formula. 2654 */ 2655 const Formula &operator=(Temp r); 2656 2657 /** 2658 * Add the given tree to the existing one. 2659 * @param r The root of the expression tree. 2660 * @return a reference to this formula. 2661 */ 2662 const Formula &operator+=(Temp r); 2663}; 2664 2665class FormulaNode : public Node 2666{ 2667 private: 2668 const Formula &formula; 2669 mutable VResult vec; 2670 2671 public: 2672 FormulaNode(const Formula &f) : formula(f) {} 2673 2674 virtual size_t size() const { return formula.size(); } 2675 virtual const VResult &result() const { formula.result(vec); return vec; } 2676 virtual Result total() const { return formula.total(); } 2677 2678 virtual std::string str() const { return formula.str(); } 2679}; 2680 2681/** 2682 * Helper class to construct formula node trees. 2683 */ 2684class Temp 2685{ 2686 protected: 2687 /** 2688 * Pointer to a Node object. 2689 */ 2690 NodePtr node; 2691 2692 public: 2693 /** 2694 * Copy the given pointer to this class. 2695 * @param n A pointer to a Node object to copy. 2696 */ 2697 Temp(NodePtr n) : node(n) { } 2698 2699 /** 2700 * Return the node pointer. 2701 * @return the node pointer. 2702 */ 2703 operator NodePtr&() { return node;} 2704 2705 public: 2706 /** 2707 * Create a new ScalarStatNode. 2708 * @param s The ScalarStat to place in a node. 2709 */ 2710 template <int N> 2711 Temp(const Scalar<N> &s) 2712 : node(new ScalarStatNode(s.statData())) { } 2713 2714 /** 2715 * Create a new ScalarStatNode. 2716 * @param s The ScalarStat to place in a node. 2717 */ 2718 Temp(const Value &s) 2719 : node(new ScalarStatNode(s.statData())) { } 2720 2721 /** 2722 * Create a new ScalarStatNode. 2723 * @param s The ScalarStat to place in a node. 2724 */ 2725 template <int N> 2726 Temp(const Average<N> &s) 2727 : node(new ScalarStatNode(s.statData())) { } 2728 2729 /** 2730 * Create a new VectorStatNode. 2731 * @param s The VectorStat to place in a node. 2732 */ 2733 template <int N> 2734 Temp(const Vector<N> &s) 2735 : node(new VectorStatNode(s.statData())) { } 2736 2737 /** 2738 * 2739 */ 2740 Temp(const Formula &f) 2741 : node(new FormulaNode(f)) { } 2742 2743 /** 2744 * Create a new ScalarProxyNode. 2745 * @param p The ScalarProxy to place in a node. 2746 */ 2747 template <class Stat> 2748 Temp(const ScalarProxy<Stat> &p) 2749 : node(new ScalarProxyNode<Stat>(p)) { } 2750 2751 /** 2752 * Create a ConstNode 2753 * @param value The value of the const node. 2754 */ 2755 Temp(signed char value) 2756 : node(new ConstNode<signed char>(value)) {} 2757 2758 /** 2759 * Create a ConstNode 2760 * @param value The value of the const node. 2761 */ 2762 Temp(unsigned char value) 2763 : node(new ConstNode<unsigned char>(value)) {} 2764 2765 /** 2766 * Create a ConstNode 2767 * @param value The value of the const node. 2768 */ 2769 Temp(signed short value) 2770 : node(new ConstNode<signed short>(value)) {} 2771 2772 /** 2773 * Create a ConstNode 2774 * @param value The value of the const node. 2775 */ 2776 Temp(unsigned short value) 2777 : node(new ConstNode<unsigned short>(value)) {} 2778 2779 /** 2780 * Create a ConstNode 2781 * @param value The value of the const node. 2782 */ 2783 Temp(signed int value) 2784 : node(new ConstNode<signed int>(value)) {} 2785 2786 /** 2787 * Create a ConstNode 2788 * @param value The value of the const node. 2789 */ 2790 Temp(unsigned int value) 2791 : node(new ConstNode<unsigned int>(value)) {} 2792 2793 /** 2794 * Create a ConstNode 2795 * @param value The value of the const node. 2796 */ 2797 Temp(signed long value) 2798 : node(new ConstNode<signed long>(value)) {} 2799 2800 /** 2801 * Create a ConstNode 2802 * @param value The value of the const node. 2803 */ 2804 Temp(unsigned long value) 2805 : node(new ConstNode<unsigned long>(value)) {} 2806 2807 /** 2808 * Create a ConstNode 2809 * @param value The value of the const node. 2810 */ 2811 Temp(signed long long value) 2812 : node(new ConstNode<signed long long>(value)) {} 2813 2814 /** 2815 * Create a ConstNode 2816 * @param value The value of the const node. 2817 */ 2818 Temp(unsigned long long value) 2819 : node(new ConstNode<unsigned long long>(value)) {} 2820 2821 /** 2822 * Create a ConstNode 2823 * @param value The value of the const node. 2824 */ 2825 Temp(float value) 2826 : node(new ConstNode<float>(value)) {} 2827 2828 /** 2829 * Create a ConstNode 2830 * @param value The value of the const node. 2831 */ 2832 Temp(double value) 2833 : node(new ConstNode<double>(value)) {} 2834}; 2835 2836 2837/** 2838 * @} 2839 */ 2840 2841void check(); 2842void reset(); 2843void registerResetCallback(Callback *cb); 2844 2845inline Temp 2846operator+(Temp l, Temp r) 2847{ 2848 return NodePtr(new BinaryNode<std::plus<Result> >(l, r)); 2849} 2850 2851inline Temp 2852operator-(Temp l, Temp r) 2853{ 2854 return NodePtr(new BinaryNode<std::minus<Result> >(l, r)); 2855} 2856 2857inline Temp 2858operator*(Temp l, Temp r) 2859{ 2860 return NodePtr(new BinaryNode<std::multiplies<Result> >(l, r)); 2861} 2862 2863inline Temp 2864operator/(Temp l, Temp r) 2865{ 2866 return NodePtr(new BinaryNode<std::divides<Result> >(l, r)); 2867} 2868 2869inline Temp 2870operator-(Temp l) 2871{ 2872 return NodePtr(new UnaryNode<std::negate<Result> >(l)); 2873} 2874 2875template <typename T> 2876inline Temp 2877constant(T val) 2878{ 2879 return NodePtr(new ConstNode<T>(val)); 2880} 2881 2882inline Temp 2883sum(Temp val) 2884{ 2885 return NodePtr(new SumNode<std::plus<Result> >(val)); 2886} 2887 2888/* namespace Stats */ } 2889 2890#endif // __BASE_STATISTICS_HH__
|