The Sparta Modeling Framework
Loading...
Searching...
No Matches
Expression.hpp
1// <Expression.hpp> -*- C++ -*-
2
3#pragma once
4
5#include <iostream>
6#include <sstream>
7#include <memory>
8#include <string>
9#include <vector>
10
14#include "sparta/statistics/ExpressionNode.hpp"
15#include "sparta/statistics/ExpressionNodeTypes.hpp"
16
17namespace sparta {
18
19class StatisticInstance;
20class Clock;
21
27namespace statistics {
28
32typedef std::pair<std::string, std::unique_ptr<StatisticInstance>> stat_pair_t;
33
37typedef std::vector<stat_pair_t> StatisticPairs;
38
43namespace expression {
44
68{
74 std::unique_ptr<ExpressionNode> content_;
75
76public:
77
81 Expression() = default;
82
87 {
88 //std::cout << "Copying " << this << " <- " << &rhp << std::endl;
89
90 if(rhp.content_ != nullptr){
91 content_.reset(rhp.content_->clone());
92 }
93 }
94
99 content_(std::move(rhp.content_))
100 {
101 //std::cout << "Moving " << this << " <- " << &rhp << std::endl;
102 }
103
110 Expression(const std::string& expression,
111 TreeNode* context);
112
119 Expression(const std::string& expression,
120 TreeNode* context,
121 const StatisticPairs&report_si);
122
131 Expression(const std::string& expression,
132 TreeNode* context,
133 std::vector<const TreeNode*>& already_used);
134
140 Expression()
141 {
142 sparta_assert(item != nullptr);
143 content_.reset(item);
144 }
145
149 Expression(double d);
150
155 ExpressionNode * op1,
156 ExpressionNode * op2=nullptr,
157 ExpressionNode * op3=nullptr);
158
167 std::vector<const TreeNode*>& used);
168
175 template<typename RetT, typename ArgT>
176 Expression(const std::string& name,
177 RetT(*fxn)(ArgT),
178 const Expression& a);
179
186 template<typename RetT, typename ArgT>
187 Expression(const std::string& name,
188 std::function<RetT (ArgT)>&,
189 const Expression& a);
190
197 template<typename RetT, typename ArgT>
198 Expression(const std::string& name,
199 RetT(*fxn)(ArgT, ArgT),
200 const Expression& a,
201 const Expression& b);
202
209 template<typename RetT>
210 Expression(const std::string& name,
211 const RetT& functor,
212 const Expression& a,
213 const Expression& b);
214
221 template<typename RetT, typename ArgT>
222 Expression(const std::string& name,
223 RetT(*fxn)(ArgT, ArgT, ArgT),
224 const Expression& a,
225 const Expression& b,
226 const Expression& c);
227
231 virtual ~Expression();
232
239 {
240 //std::cout << "Assignment " << this << " <- " << &rhp << std::endl;
241
242 if(rhp.content_ != nullptr){
243 content_.reset(rhp.content_->clone());
244 }
245
246 return *this;
247 }
248
255 {
256 //std::cout << "Move " << this << " <- " << &rhp << std::endl;
257
258 content_ = std::move(rhp.content_);
259 return *this;
260 }
261
267 if(content_ == nullptr){
268 throw SpartaException("Cannot clone content of an expression with null content");
269 }
270 return content_->clone();
271 }
272
280 uint32_t getStats(std::vector<const StatisticInstance*>& results) const {
281 return getStats_(results);
282 }
283
289 bool hasContent() const {
290 return content_ != nullptr;
291 }
292
303 template<typename RetT, typename ArgT>
304 Expression ufunc(const std::string& name,
305 RetT(*fxn)(ArgT),
306 const Expression& a) const;
307
318 template<typename RetT, typename ArgT>
319 Expression ufunc(const std::string& name,
320 std::function<RetT (ArgT)>&,
321 const Expression& a) const;
322
334 template<typename RetT, typename ArgT>
335 Expression bfunc(const std::string& name,
336 RetT(*fxn)(ArgT, ArgT),
337 const Expression& a,
338 const Expression& b) const;
339
351 template<typename RetT>
352 Expression bfunc(const std::string& name,
353 const RetT& functor,
354 const Expression& a,
355 const Expression& b) const;
356
369 template<typename RetT, typename ArgT>
370 Expression tfunc(const std::string& name,
371 RetT(*fxn)(ArgT, ArgT, ArgT),
372 const Expression& a,
373 const Expression& b,
374 const Expression& c) const;
375
381 Expression& operator=(double d);
382
386 Expression operator+() const;
387
391 Expression operator-() const;
392
396 Expression operator+(const Expression& rhp) const;
397
401 Expression operator-(const Expression& rhp) const;
402
406 Expression operator*(const Expression& rhp) const;
407
411 Expression operator/(const Expression& rhp) const;
412
416 Expression& operator+=(const Expression& rhp);
417
421 Expression& operator-=(const Expression& rhp);
422
426 Expression& operator*=(const Expression& rhp);
427
431 Expression& operator/=(const Expression& rhp);
432
437 double evaluate() const {
438 if(content_ == nullptr){
439 throw SpartaException("Cannot evaluate expression because it has no content. Test with "
440 "hasContent before blindly evaluating foreign expressions");
441 }
442
443 return content_->evaluate();
444 };
445
453 void start() {
454 if(content_){
455 content_->start();
456 }
457 }
458
466 void end() {
467 if(content_){
468 content_->end();
469 }
470 }
471
482 void dump(std::ostream& o,
483 bool show_range=true,
484 bool resolve_subexprs=true) const {
485 if(!content_){
486 o << "???";
487 }else{
488 content_->dump(o, show_range, resolve_subexprs);
489 }
490 }
491
492 bool supportsCompression() const {
493 if (content_ == nullptr) {
494 return false;
495 }
496 return content_->supportsCompression();
497 }
498
508 std::string stringize(bool show_range=true,
509 bool resolve_subexprs=true) const {
510 std::stringstream ss;
511 dump(ss, show_range, resolve_subexprs);
512 return ss.str();
513 }
514
523 const Clock* getClock() {
524 std::vector<const Clock*> clocks;
525 getClocks(clocks);
526 if(clocks.size() == 0){
527 return nullptr;
528 }
529 const Clock* result = *(clocks.begin());
530 for(auto itr = clocks.begin()+1; itr != clocks.end(); ++itr){
531 if(*itr != result){
532 throw SpartaException("Multiple TreeNodes found with different clocks when "
533 "attempting to determine the clock associated with the "
534 "expression: ") << stringize();
535 }
536 }
537 return result;
538 }
539
545 void getClocks(std::vector<const Clock*>& clocks) const{
546 if(content_){
547 content_->getClocks(clocks);
548 }
549 }
550
551private:
552
556 uint32_t getStats_(std::vector<const StatisticInstance*>& results) const {
557 return content_ ? content_->getStats(results) : 0;
558 }
559
566 void parse_(const std::string& expression,
567 TreeNode* context,
568 std::vector<const TreeNode*>& already_used,
569 const StatisticPairs&report_si);
570};
571
572inline Expression::Expression(double d) :
573 Expression()
574{
575 content_.reset(new Constant(d));
576}
577
579 ExpressionNode * op1,
580 ExpressionNode * op2,
581 ExpressionNode * op3) :
582 Expression()
583{
584 content_.reset(new Operation(type, op1, op2, op3));
585}
586
587template <typename RetT, typename ArgT>
588inline Expression::Expression(const std::string& name,
589 RetT(*fxn)(ArgT),
590 const Expression& a) {
591 sparta_assert(fxn != nullptr,
592 "function pointer of unary function \"" << fxn << "\" must not be nullptr");
593 content_.reset(new UnaryFunction<RetT, ArgT>(name, fxn, a.cloneContent()));
594}
595
596template <typename RetT, typename ArgT>
597inline Expression::Expression(const std::string& name,
598 std::function<RetT (ArgT)>& fxn,
599 const Expression& a) {
600 sparta_assert(fxn,
601 "function pointer of unary function \"" << "\" must not be nullptr");
602 content_.reset(new UnaryFunction<RetT, ArgT, std::function<RetT (ArgT)>>(name, fxn, a.cloneContent()));
603}
604
605template <typename RetT, typename ArgT>
606inline Expression::Expression(const std::string& name,
607 RetT(*fxn)(ArgT, ArgT),
608 const Expression& a,
609 const Expression& b) {
610 sparta_assert(fxn != nullptr,
611 "function pointer of binary function \"" << fxn << "\" must not be nullptr");
612 content_.reset(new BinaryFunction<RetT, ArgT>(name, fxn, a.cloneContent(), b.cloneContent()));
613}
614
615template <typename RetT>
616inline Expression::Expression(const std::string& name,
617 const RetT& functor,
618 const Expression& a,
619 const Expression& b) {
620 content_.reset(new BinaryFunction<RetT>(name, functor, a.cloneContent(), b.cloneContent()));
621}
622
623template <typename RetT, typename ArgT>
624inline Expression::Expression(const std::string& name,
625 RetT(*fxn)(ArgT, ArgT, ArgT),
626 const Expression& a,
627 const Expression& b,
628 const Expression& c) {
629 sparta_assert(fxn != nullptr,
630 "function pointer of ternary function \"" << fxn << "\" must not be nullptr");
631 content_.reset(new TernaryFunction<RetT, ArgT>(name, fxn, a.cloneContent(), b.cloneContent(), c.cloneContent()));
632}
633
634template <typename RetT, typename ArgT>
635inline Expression Expression::ufunc(const std::string& name,
636 RetT(*fxn)(ArgT),
637 const Expression& a) const {
638 sparta_assert(fxn != nullptr,
639 "function pointer of unary function \"" << fxn << "\" must not be nullptr");
640 //std::cout << "unary func \"" << name << "\"" << std::endl;
641 return Expression(new UnaryFunction<RetT, ArgT>(name, fxn, a.cloneContent()));
642}
643
644template <typename RetT, typename ArgT>
645inline Expression Expression::ufunc(const std::string& name,
646 std::function<RetT (ArgT)>& fxn,
647 const Expression& a) const {
648 sparta_assert(fxn,
649 "function pointer of unary function \"" << "\" must not be nullptr");
650 return Expression(new UnaryFunction<RetT, ArgT, std::function<RetT (ArgT)>>(name, fxn, a.cloneContent()));
651}
652
653template <typename RetT, typename ArgT>
654inline Expression Expression::bfunc(const std::string& name,
655 RetT(*fxn)(ArgT, ArgT),
656 const Expression& a,
657 const Expression& b) const {
658 sparta_assert(fxn != nullptr,
659 "function pointer of binary function \"" << fxn << "\" must not be nullptr");
660 return Expression(new BinaryFunction<RetT, ArgT>(name, fxn, a.cloneContent(), b.cloneContent()));
661}
662
663template <typename RetT>
664inline Expression Expression::bfunc(const std::string& name,
665 const RetT& functor,
666 const Expression& a,
667 const Expression& b) const {
668 return Expression(new BinaryFunction<RetT>(name, functor, a.cloneContent(), b.cloneContent()));
669}
670
671template <typename RetT, typename ArgT>
672inline Expression Expression::tfunc(const std::string& name,
673 RetT(*fxn)(ArgT, ArgT, ArgT),
674 const Expression& a,
675 const Expression& b,
676 const Expression& c) const {
677 sparta_assert(fxn != nullptr,
678 "function pointer of ternary function \"" << fxn << "\" must not be nullptr");
680}
681
683{
684 sparta_assert(content_ == nullptr, "Cannot call operator= on an expression which already has an item. Item would ""be discarded");
685 content_.reset(new Constant(d));
686 return *this;
687}
688
690{
691 sparta_assert(content_ != nullptr, "Cannot call operator+() on an expression which has no item. A lhp is ""required in order to promote");
692
694 cloneContent()));
695}
696
698{
699 sparta_assert(content_ != nullptr, "Cannot call operator-() on an expression which has no item. A lhp is ""required in order to negate");
700
701 return Expression(new Operation(OP_NEGATE,
702 cloneContent()));
703}
704
706{
707 sparta_assert(content_ != nullptr, "Cannot call operator+(rhp) on an expression which has no item. A lhp is ""required in order to add");
708
709 return Expression(new Operation(OP_ADD, // Operation
710 cloneContent(), // Takes ownership of content
711 rhp.cloneContent() // Clones content
712 ));
713}
714
716{
717 sparta_assert(content_ != nullptr, "Cannot call operator-(rhp) on an expression which has no item. A lhp is ""required in order to subtract");
718
719 return Expression(new Operation(OP_SUB, // Operation
720 cloneContent(), // Takes ownership of content
721 rhp.cloneContent() // Clones content
722 ));
723}
724
726{
727 sparta_assert(content_ != nullptr, "Cannot call operator*(rhp) on an expression which has no item. A lhp is ""required in order to multiply");
728
729 return Expression(new Operation(OP_MUL, // Operation
730 cloneContent(), // Takes ownership of content
731 rhp.cloneContent() // Clones content
732 ));
733}
734
736{
737 sparta_assert(content_ != nullptr, "Cannot call operator/(rhp) on an expression which has no item. A lhp is ""required in order to divide");
738
739 return Expression(new Operation(OP_DIV, // Operation
740 cloneContent(), // Takes ownership of content
741 rhp.cloneContent() // Clones content
742 ));
743}
744
746{
747 sparta_assert(content_ != nullptr, "Cannot call operator+=(rhp) on an expression which has no item. A lhp is ""required in order to add");
748
749 content_.reset(new Operation(OP_ADD, // Operation
750 cloneContent(), // Takes ownership of content
751 rhp.cloneContent() // Clones content
752 ));
753 return *this;
754}
755
757{
758 sparta_assert(content_ != nullptr, "Cannot call operator-=(rhp) on an expression which has no item. A lhp is ""required in order to subtract");
759
760 content_.reset(new Operation(OP_SUB, // Operation
761 cloneContent(), // Takes ownership of content
762 rhp.cloneContent() // Clones content
763 ));
764 return *this;
765}
766
767
769{
770 sparta_assert(content_ != nullptr, "Cannot call operator*=(rhp) on an expression which has no item. A lhp is ""required in order to divide");
771
772 content_.reset(new Operation(OP_MUL, // Operation
773 cloneContent(), // Takes ownership of content
774 rhp.cloneContent() // Clones content
775 ));
776 return *this;
777}
778
780{
781 sparta_assert(content_ != nullptr, "Cannot call operator/=(rhp) on an expression which has no item. A lhp is ""required in order to divide");
782
783 content_.reset(new Operation(OP_DIV, // Operation
784 cloneContent(), // Takes ownership of content
785 rhp.cloneContent() // Clones content
786 ));
787 return *this;
788}
789
793inline std::ostream& operator<<(std::ostream& o, const sparta::statistics::expression::Expression& ex){
794 ex.dump(o);
795 return o;
796}
797
798 } // namespace expression
799 } // namespace statistics
800} // namespace sparta
Set of macros for Sparta assertions. Caught by the framework.
#define sparta_assert(...)
Simple variadic assertion that will throw a sparta_exception if the condition fails.
Exception class for all of Sparta.
Basic Node framework in sparta device tree composite pattern.
A representation of simulated time.
Definition Clock.hpp:51
Used to construct and throw a standard C++ exception. Inherits from std::exception.
Node in a composite tree representing a sparta Tree item.
Definition TreeNode.hpp:205
Abstract interface class for an item in an expression. Subclasses can contain other ExpressionNodes.
Expression container/builder. Contains a single ExpressionNode representing the root of an expression...
double evaluate() const
Compute value of this operate in simulation for the current computation window.
Expression(const std::string &expression, TreeNode *context, const StatisticPairs &report_si)
Construct with string expression.
void start()
Notify every item in this expression to start a new computation window.
Expression & operator=(Expression &&rhp)
Assignment operator with move. Moves content of rhp and discards current expression content.
Expression(Expression &&rhp)
Move Constructor.
ExpressionNode * cloneContent() const
Makes a clone of the content of this expression.
void getClocks(std::vector< const Clock * > &clocks) const
Gets all clocks associated with this Expression.
Expression & operator*=(const Expression &rhp)
Return this expression with a node multiplying by rhp.
Expression tfunc(const std::string &name, RetT(*fxn)(ArgT, ArgT, ArgT), const Expression &a, const Expression &b, const Expression &c) const
Construct a ternary function having the given name and function.
bool hasContent() const
Does this expression have content.
std::string stringize(bool show_range=true, bool resolve_subexprs=true) const
Return a string representing this expression including any TreeNode dependencies.
Expression & operator+=(const Expression &rhp)
Return this expression with a node adding rhp.
Expression & operator=(const Expression &rhp)
Assignment operator. Clones the content of rhp and discards current expression content.
Expression ufunc(const std::string &name, RetT(*fxn)(ArgT), const Expression &a) const
Construct a unary function having the given name and function.
Expression(const std::string &expression, TreeNode *context, std::vector< const TreeNode * > &already_used)
Construct with string expression.
const Clock * getClock()
Gets the clock associated with the content of this expression. This is done by finding all TreeNodes ...
Expression & operator-=(const Expression &rhp)
Return this expression with a node subtracting rhp.
Expression operator-() const
Return this expression with a negation inserted.
Expression(ExpressionNode *item)
Blind content constructor.
Expression operator/(const Expression &rhp) const
Return a new expression of: *this / rhp.
uint32_t getStats(std::vector< const StatisticInstance * > &results) const
Gets the statistics present in this expression.
Expression bfunc(const std::string &name, RetT(*fxn)(ArgT, ArgT), const Expression &a, const Expression &b) const
Construct a binary function having the given name and function.
Expression(const TreeNode *n, std::vector< const TreeNode * > &used)
Stat/Counter/Parameter construction.
Expression operator+() const
Return this expression with no effect.
Expression operator*(const Expression &rhp) const
Return a new expression of: *this * rhp.
Expression & operator/=(const Expression &rhp)
Return this expression with a node dividing by rhp.
virtual ~Expression()
Virtual destructor.
void end()
Notify every item in this expression to end the current computation window.
void dump(std::ostream &o, bool show_range=true, bool resolve_subexprs=true) const
Write the content of this entire expression to an ostream.
Expression()=default
Constructs an expression containing no content.
Expression(const Expression &rhp)
Copy Constructor.
Expression(const std::string &expression, TreeNode *context)
Construct with string expression.
operation_t
Types of operations supported.
std::ostream & operator<<(std::ostream &o, const sparta::statistics::expression::Expression &ex)
Ostream printing function for Expressions.
std::vector< stat_pair_t > StatisticPairs
Type for storing a list of stat_pair_t.
std::pair< std::string, std::unique_ptr< StatisticInstance > > stat_pair_t
Type for storing each stat added.
Macros for handling exponential backoff.