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