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