The Sparta Modeling Framework
Loading...
Searching...
No Matches
ExpressionNodeTypes.hpp
1// <ExpressionNodeTypes> -*- C++ -*-
2
3#pragma once
4
5#include <vector>
6#include <memory>
7
8#include "sparta/statistics/ExpressionNode.hpp"
9
10namespace sparta {
11
12 class StatisticInstance;
13
14 namespace statistics {
15 namespace expression {
16
21{
26
30 std::vector<std::unique_ptr<ExpressionNode>> operands_;
31
36 : type_(OP_NULL)
37 { }
38
42 Operation(const Operation& rhp) :
44 type_(rhp.type_)
45 {
46 for(auto& item : rhp.operands_){
47 ExpressionNode* clone = item->clone();
48 operands_.emplace_back(clone);
49 }
50 }
51
60 ExpressionNode * op1,
61 ExpressionNode * op2=nullptr,
62 ExpressionNode * op3=nullptr) :
63 type_(type)
64 {
65 sparta_assert(op1 != nullptr);
66 operands_.emplace_back(op1);
67
68 if(op2 != nullptr){
69 operands_.emplace_back(op2);
70 }
71 if(op3 != nullptr){
72 operands_.emplace_back(op3);
73 }
74 }
75
76 virtual ~Operation()
77 { }
78
79 virtual Operation* clone_() const override {
80 return new Operation(*this);
81 }
82
87 operands_.emplace_back(op);
88 }
89
90 virtual double evaluate_() const override {
91 switch(type_){
92 case OP_NULL:
93 throw SpartaException("Cannot compute value of a NULL op");
94 case OP_ADD:
95 return operands_.at(0)->evaluate() + operands_.at(1)->evaluate();
96 case OP_SUB:
97 return operands_.at(0)->evaluate() - operands_.at(1)->evaluate();
98 case OP_MUL:
99 return operands_.at(0)->evaluate() * operands_.at(1)->evaluate();
100 case OP_DIV:
101 return operands_.at(0)->evaluate() / operands_.at(1)->evaluate();
102 case OP_NEGATE:
103 return -(operands_.at(0)->evaluate());
104 case OP_PROMOTE:
105 return +(operands_.at(0)->evaluate());
106 case OP_FORWARD:
107 return operands_.at(0)->evaluate();
108 default:
109 throw SpartaException("Unknown operation type: ") << type_;
110 }
111 }
112
142 virtual bool supportsCompression() const override {
143 switch (type_) {
144 case OP_NULL:
145 return false;
146 case OP_ADD:
147 case OP_SUB:
148 case OP_MUL: {
149 bool supports_compression = true;
150 for (const auto & op : operands_) {
151 supports_compression &= op->supportsCompression();
152 }
153 return supports_compression;
154 }
155 case OP_DIV:
156 return false;
157 case OP_NEGATE:
158 case OP_PROMOTE:
159 case OP_FORWARD:
160 return operands_.at(0)->supportsCompression();
161 default:
162 throw SpartaException("Unknown operation type: ") << type_;
163 }
164
165 sparta_assert(!"Unreachable");
166 return false;
167 }
168
169 virtual void start() override {
170 for(auto& op : operands_){
171 op->start();
172 }
173 }
174 virtual void end() override {
175 for(auto& op : operands_){
176 op->end();
177 }
178 }
179
180 virtual void dump(std::ostream& o,
181 bool show_range=true,
182 bool resolve_subexprs=true) const override {
183
184 if(operands_.size() == 2){
185 o << "(";
186 operands_.at(0)->dump(o, show_range, resolve_subexprs);
187 o << "" << (char)(type_ & 0xff);
188 operands_.at(1)->dump(o, show_range, resolve_subexprs);
189 o << ')';
190 }else{
191 if((uint32_t)type_ > 255){
192 o << "op" << type_ << "(" ;
193 }else{
194 o << "op" << (char)(type_ & 0xff) << "(" ;
195 }
196
197 uint32_t idx = 0;
198 for(auto& op : operands_){
199 if(idx != 0){
200 o << ", ";
201 }
202 op->dump(o, show_range, resolve_subexprs);
203 ++idx;
204 }
205 o << ')';
206 }
207 }
208
209 virtual void getClocks(std::vector<const Clock*>& clocks) const override {
210 for(auto& op : operands_){
211 op->getClocks(clocks);
212 }
213 }
214
215private:
216
217 virtual uint32_t getStats_(std::vector<const StatisticInstance*>& results) const override {
218 uint32_t added = 0;
219 for(auto& op : operands_){
220 added += op->getStats(results);
221 }
222 return added;
223 }
224}; // class Operation
225
227{
228 double value_;
229
230 Constant(const Constant& rhp) :
232 value_(rhp.value_)
233 { }
234
235 Constant(double val) :
236 value_(val)
237 {
238 //std::cout << "Constant at " << this << std::endl;
239 }
240
241 virtual Constant* clone_() const override {
242 return new Constant(*this);
243 }
244
245 virtual double evaluate_() const override {
246 return value_;
247 }
248
250 virtual bool supportsCompression() const override {
251 return true;
252 }
253
254 virtual void start() override {
255 }
256
257 virtual void end() override {
258 }
259
260 virtual void dump(std::ostream& o,
261 bool show_range=true,
262 bool resolve_subexprs=true) const override {
263 (void) show_range;
264 (void) resolve_subexprs;
265 o << value_;
266 }
267
268 virtual void getClocks(std::vector<const Clock*>& clocks) const override {
269 (void) clocks;
270 // No clocks in a constant
271 }
272
273private:
274
275 virtual uint32_t getStats_(std::vector<const StatisticInstance*>& results) const override {
276 (void) results;
277 return 0;
278 }
279};
280
285template <typename RetT=double, typename ArgT=double, typename fxn_t = RetT (* const)(ArgT)>
287{
291 const std::string name_;
292
296 const fxn_t fxn_;
297
301 std::unique_ptr<ExpressionNode> operand_;
302
303
307 UnaryFunction() = delete;
308
309 UnaryFunction(const UnaryFunction& rhp) :
311 name_(rhp.name_),
312 fxn_(rhp.fxn_)
313 {
314 sparta_assert(rhp.operand_ != nullptr); // Should not be possible
315 operand_.reset(rhp.operand_->clone());
316 }
317
324 UnaryFunction(const std::string& name,
325 fxn_t fxn,
326 ExpressionNode* op) :
327 name_(name),
328 fxn_(fxn),
329 operand_(op)
330 {
331 sparta_assert(operand_ != nullptr,
332 "operand of unary function \"" << name << "\" cannot be nullptr");
333 }
334
339
340 virtual UnaryFunction* clone_() const override {
341 return new UnaryFunction(*this);
342 }
343
344 virtual double evaluate_() const override {
345 return (double)fxn_(operand_->evaluate());
346 }
347
352 virtual bool supportsCompression() const override {
353 return false;
354 }
355
356 virtual void start() override {
357 operand_->start();
358 }
359
360 virtual void end() override {
361 operand_->end();
362 }
363
364 virtual void dump(std::ostream& o,
365 bool show_range=true,
366 bool resolve_subexprs=true) const override {
367 o << name_ << "(";
368 operand_->dump(o, show_range, resolve_subexprs);
369 o << ")";
370 }
371
372 virtual void getClocks(std::vector<const Clock*>& clocks) const override {
373 operand_->getClocks(clocks);
374 }
375
376private:
377
378 virtual uint32_t getStats_(std::vector<const StatisticInstance*>& results) const override {
379 return operand_->getStats(results);
380 }
381
382}; // class UnaryFunction
383
390template <typename RetT=double, typename ArgT=double>
392{
396 using fxn_t = typename std::conditional<
397 std::is_class<RetT>::value,
398 RetT,
399 RetT(* const)(ArgT, ArgT)>::type;
400
404 const std::string name_;
405
409 const fxn_t fxn_;
410
414 std::unique_ptr<ExpressionNode> operand_1_;
415
419 std::unique_ptr<ExpressionNode> operand_2_;
420
421
425 BinaryFunction() = delete;
426
427 BinaryFunction(const BinaryFunction& rhp) :
429 name_(rhp.name_),
430 fxn_(rhp.fxn_)
431 {
432 sparta_assert(rhp.operand_1_ != nullptr); // Should not be possible
433 sparta_assert(rhp.operand_2_ != nullptr); // Should not be possible
434 operand_1_.reset(rhp.operand_1_->clone());
435 operand_2_.reset(rhp.operand_2_->clone());
436 }
437
445 BinaryFunction(const std::string& name,
446 fxn_t fxn,
447 ExpressionNode* op1,
448 ExpressionNode* op2) :
449 name_(name),
450 fxn_(fxn),
451 operand_1_(op1),
452 operand_2_(op2)
453 {
454 sparta_assert(operand_1_ != nullptr,
455 "operand 1 of binary function \"" << name << "\" cannot be nullptr");
456 sparta_assert(operand_2_ != nullptr,
457 "operand 2 of binary function \"" << name << "\" cannot be nullptr");
458 }
459
464
465 virtual BinaryFunction* clone_() const override {
466 return new BinaryFunction(*this);
467 }
468
469 virtual double evaluate_() const override {
470 auto x = operand_1_->evaluate();
471 auto y = operand_2_->evaluate();
472 return (double)fxn_(x, y);
473 }
474
479 virtual bool supportsCompression() const override {
480 return false;
481 }
482
483 virtual void start() override {
484 operand_1_->start();
485 operand_2_->start();
486 }
487
488 virtual void end() override {
489 operand_1_->end();
490 operand_2_->end();
491 }
492
493 virtual void dump(std::ostream& o,
494 bool show_range=true,
495 bool resolve_subexprs=true) const override {
496 o << name_ << "(";
497 operand_1_->dump(o, show_range, resolve_subexprs);
498 o << ", ";
499 operand_2_->dump(o, show_range, resolve_subexprs);
500 o << ")";
501 }
502
503 virtual void getClocks(std::vector<const Clock*>& clocks) const override {
504 operand_1_->getClocks(clocks);
505 operand_2_->getClocks(clocks);
506 }
507
508private:
509
510 virtual uint32_t getStats_(std::vector<const StatisticInstance*>& results) const override {
511 return operand_1_->getStats(results) + operand_2_->getStats(results);
512 }
513
514}; // class BinaryFunction
515
522template <typename RetT=double, typename ArgT=double>
524{
528 typedef RetT(* const fxn_t)(ArgT, ArgT, ArgT);
529
533 const std::string name_;
534
538 const fxn_t fxn_;
539
543 std::unique_ptr<ExpressionNode> operand_1_;
544
548 std::unique_ptr<ExpressionNode> operand_2_;
549
553 std::unique_ptr<ExpressionNode> operand_3_;
554
555
559 TernaryFunction() = delete;
560
561 TernaryFunction(const TernaryFunction& rhp) :
563 name_(rhp.name_),
564 fxn_(rhp.fxn_)
565 {
566 sparta_assert(rhp.operand_1_ != nullptr); // Should not be possible
567 sparta_assert(rhp.operand_2_ != nullptr); // Should not be possible
568 sparta_assert(rhp.operand_3_ != nullptr); // Should not be possible
569 operand_1_.reset(rhp.operand_1_->clone());
570 operand_2_.reset(rhp.operand_2_->clone());
571 operand_3_.reset(rhp.operand_3_->clone());
572 }
573
581 TernaryFunction(const std::string& name,
582 fxn_t fxn,
583 ExpressionNode* op1,
584 ExpressionNode* op2,
585 ExpressionNode* op3) :
586 name_(name),
587 fxn_(fxn),
588 operand_1_(op1),
589 operand_2_(op2),
590 operand_3_(op3)
591 {
592 sparta_assert(operand_1_ != nullptr,
593 "operand 1 of ternary function \"" << name << "\" cannot be nullptr");
594 sparta_assert(operand_2_ != nullptr,
595 "operand 2 of ternary function \"" << name << "\" cannot be nullptr");
596 sparta_assert(operand_3_ != nullptr,
597 "operand 3 of ternary function \"" << name << "\" cannot be nullptr");
598 }
599
604
605 virtual TernaryFunction* clone_() const override {
606 return new TernaryFunction(*this);
607 }
608
609 virtual double evaluate_() const override {
610 return (double)fxn_(operand_1_->evaluate(), operand_2_->evaluate(), operand_3_->evaluate());
611 }
612
617 virtual bool supportsCompression() const override {
618 return false;
619 }
620
621 virtual void start() override {
622 operand_1_->start();
623 operand_2_->start();
624 operand_3_->start();
625 }
626
627 virtual void end() override {
628 operand_1_->end();
629 operand_2_->end();
630 operand_3_->end();
631 }
632
633 virtual void dump(std::ostream& o,
634 bool show_range=true,
635 bool resolve_subexprs=true) const override {
636 o << name_ << "(";
637 operand_1_->dump(o, show_range, resolve_subexprs);
638 o << ", ";
639 operand_2_->dump(o, show_range, resolve_subexprs);
640 o << ", ";
641 operand_3_->dump(o, show_range, resolve_subexprs);
642 o << ")";
643 }
644
645 virtual void getClocks(std::vector<const Clock*>& clocks) const override {
646 operand_1_->getClocks(clocks);
647 operand_2_->getClocks(clocks);
648 operand_3_->getClocks(clocks);
649 }
650
651private:
652
653 virtual uint32_t getStats_(std::vector<const StatisticInstance*>& results) const override {
654 return operand_1_->getStats(results) + operand_2_->getStats(results) + operand_3_->getStats(results);
655 }
656
657}; // class TernaryFunction
658
659 } // namespace expression
660 } // namespace statistics
661} // namespace sparta
#define sparta_assert(...)
Simple variadic assertion that will throw a sparta_exception if the condition fails.
Used to construct and throw a standard C++ exception. Inherits from std::exception.
Abstract interface class for an item in an expression. Subclasses can contain other ExpressionNodes.
operation_t
Types of operations supported.
Macros for handling exponential backoff.
std::unique_ptr< ExpressionNode > operand_2_
Operand 2 of the unary function fxn_.
virtual BinaryFunction * clone_() const override
Deep copy of the content of this item.
typename std::conditional< std::is_class< RetT >::value, RetT, RetT(*const)(ArgT, ArgT)>::type fxn_t
Function evaluation handler type.
std::unique_ptr< ExpressionNode > operand_1_
Operand 1 of the unary function fxn_.
const fxn_t fxn_
Binary function to invoke.
virtual void dump(std::ostream &o, bool show_range=true, bool resolve_subexprs=true) const override
Dump the content of this expression item.
virtual double evaluate_() const override
Compute value of this item in simulation.
BinaryFunction(const std::string &name, fxn_t fxn, ExpressionNode *op1, ExpressionNode *op2)
BinaryFunction & operator=(const BinaryFunction &)=delete
Non-assignable.
BinaryFunction()=delete
No default construction.
const std::string name_
Name of this binary function.
virtual void getClocks(std::vector< const Clock * > &clocks) const override
Populates a vector with the clocks found in this subexpression node.
virtual bool supportsCompression() const override
Constants are always good candidates for compression.
virtual void dump(std::ostream &o, bool show_range=true, bool resolve_subexprs=true) const override
Dump the content of this expression item.
virtual double evaluate_() const override
Compute value of this item in simulation.
virtual void getClocks(std::vector< const Clock * > &clocks) const override
Populates a vector with the clocks found in this subexpression node.
virtual Constant * clone_() const override
Deep copy of the content of this item.
Operation(const Operation &rhp)
Copy constructor. Deep copies the operands of the operation.
std::vector< std::unique_ptr< ExpressionNode > > operands_
All operands (subexpressions) in this node.
virtual bool supportsCompression() const override
virtual double evaluate_() const override
Compute value of this item in simulation.
virtual Operation * clone_() const override
Deep copy of the content of this item.
void addOperand(ExpressionNode *op)
Manually add an operand.
virtual void dump(std::ostream &o, bool show_range=true, bool resolve_subexprs=true) const override
Dump the content of this expression item.
operation_t type_
Type of operation to perform.
Operation()
Default constructor with null operations and no type.
Operation(operation_t type, ExpressionNode *op1, ExpressionNode *op2=nullptr, ExpressionNode *op3=nullptr)
Contruct with operation type and operands.
virtual void getClocks(std::vector< const Clock * > &clocks) const override
Populates a vector with the clocks found in this subexpression node.
TernaryFunction(const std::string &name, fxn_t fxn, ExpressionNode *op1, ExpressionNode *op2, ExpressionNode *op3)
TernaryFunction & operator=(const TernaryFunction &)=delete
Non-assignable.
RetT(*const fxn_t)(ArgT, ArgT, ArgT)
Function evaluation handler type.
std::unique_ptr< ExpressionNode > operand_3_
Operand 2 of the unary function fxn_.
virtual TernaryFunction * clone_() const override
Deep copy of the content of this item.
TernaryFunction()=delete
No default construction.
std::unique_ptr< ExpressionNode > operand_2_
Operand 2 of the unary function fxn_.
virtual void getClocks(std::vector< const Clock * > &clocks) const override
Populates a vector with the clocks found in this subexpression node.
std::unique_ptr< ExpressionNode > operand_1_
Operand 1 of the unary function fxn_.
const fxn_t fxn_
Ternary function to invoke.
virtual void dump(std::ostream &o, bool show_range=true, bool resolve_subexprs=true) const override
Dump the content of this expression item.
const std::string name_
Name of this ternary function.
virtual double evaluate_() const override
Compute value of this item in simulation.
std::unique_ptr< ExpressionNode > operand_
Operand of the unary function fxn_.
UnaryFunction & operator=(const UnaryFunction &)=delete
Non-assignable.
virtual void dump(std::ostream &o, bool show_range=true, bool resolve_subexprs=true) const override
Dump the content of this expression item.
virtual void getClocks(std::vector< const Clock * > &clocks) const override
Populates a vector with the clocks found in this subexpression node.
const std::string name_
Name of this unary function.
virtual UnaryFunction * clone_() const override
Deep copy of the content of this item.
virtual double evaluate_() const override
Compute value of this item in simulation.
UnaryFunction()=delete
No default construction.
const fxn_t fxn_
Unary function to invoke.
UnaryFunction(const std::string &name, fxn_t fxn, ExpressionNode *op)