The Sparta Modeling Framework
Loading...
Searching...
No Matches
State.hpp
1// <State.hpp> -*- C++ -*-
2#pragma once
3
4#include "sparta/utils/Enum.hpp"
6#include "sparta/simulation/Audience.hpp"
8#include "sparta/simulation/StateTracker.hpp"
11
12namespace sparta
13{
14 namespace app{
15 class Simulation;
16 class SimulationConfiguration;
17 }
18
25 class BoolEnum {
26 public:
27
34 enum class BoolValue : unsigned int {
35 __FIRST,
36 FALSE = __FIRST,
37 TRUE,
38 __LAST
39 };
40
41 // Default constructor.
42 BoolEnum() = default;
43
44 // Constructor to convert any bool instance into an
45 // actual BoolEnum instance. This is important because
46 // users will pass around bool instances for methods
47 // related to sparta::State<bool> instances.
48 BoolEnum(const bool val) :
49 enum_val_(val ? BoolValue::TRUE : BoolValue::FALSE) {}
50
51 // Constructor to convert any BoolValue enum instance
52 // into an actual BoolEnum instance. This is important
53 // because the State constructor can take any enum constant
54 // and convert it into EnumTValueType instance.
55 BoolEnum(const BoolValue& val) :
56 enum_val_(val) {}
57
58 // Copy Constructor.
59 BoolEnum(const BoolEnum& other) :
60 enum_val_(other.enum_val_) {}
61
62 // Move Constructor.
63 BoolEnum(BoolEnum&& other) :
64 enum_val_(std::move(other.enum_val_)) {}
65
66 // Copy Assignment operator.
67 BoolEnum& operator=(const BoolEnum& other) {
68 enum_val_ = other.enum_val_;
69 return *this;
70 }
71
72 // Move Assignment operator.
73 BoolEnum& operator=(BoolEnum&& other) {
74 enum_val_ = std::move(other.enum_val_);
75 return *this;
76 }
77
78 // BoolEnum instances should be implicitly converted
79 // into integers.
80 operator uint32_t() const {
81 return static_cast<uint32_t>(enum_val_);
82 }
83
84 // BoolEnum instances should be implicitly converted
85 // into its internal enum instance type.
86 operator BoolValue() const {
87 return enum_val_;
88 }
89 private:
90
91 // Enum instance which holds the true or false state.
92 BoolValue enum_val_;
93 };
94
121 template<class EnumT, class MetaDataT = void, uint32_t MAX_MARKERS = 15>
122 class State
123 {
125 class MarkerSet;
126
127 public:
129 typedef MetaDataT * MetaDataTPtr;
130
132 typedef typename std::conditional<
133 !std::is_same<EnumT, bool>::value,
135 BoolEnum>::type
137
139 // BoolEnum::BoolValue because there are signatures
140 // which assert on std::is_enum.
141 typedef typename std::conditional<
142 !std::is_same<EnumT, bool>::value,
143 EnumT, BoolEnum::BoolValue>::type
145
149 class Marker
150 {
151 private:
152 friend MarkerSet;
153
155 void reset_() {
156 marked_ = false;
157 }
158
159 // Default constructor only made by MarkerSet
160 Marker() = default;
161
162 // Initialize this Marker
163 void initialize(MarkerSet * marker_set, const EnumTValueType & val) {
164 marker_set_ = marker_set;
165 val_ = val;
166 }
167
168 public:
169
170 // No copies
171 Marker(const Marker &) = default;
172
174 void set(MetaDataTPtr ptr = nullptr) {
175 if(!marked_) {
176 marker_set_->jointSet_(ptr);
177 marked_ = true;
178 }
179 }
180
182 void clear() {
183 if(marked_) {
184 // clear the marker set
185 marker_set_->clearMark_();
186 marked_ = false;
187 }
188 }
189
191 bool isMarked() const {
192 return marked_;
193 }
194
200 return val_;
201 }
202
203 private:
205 MarkerSet * marker_set_ = nullptr;
206
208 bool marked_ = false;
209
211 EnumTValueType val_;
212
213 }; // class Marker
214
228 {
229 public:
230
233
236 virtual void signalSet(const EnumTValueType & val, MetaDataTPtr) = 0;
237
239 virtual ~Monitor() {}
240 }; // class Monitor
241
242 private:
243
248 class MarkerSet
249 {
250 public:
251
253 MarkerSet() {}
254
256 MarkerSet(const MarkerSet&) = default;
257
263 Marker * makeMarker(State * state) {
264 state_ = state;
265 sparta_assert(marker_cnt_ != MAX_MARKERS);
266 markers_[marker_cnt_].initialize(this, transition_val_);
267 return &markers_[marker_cnt_++];
268 }
269
274 uint32_t numMarkers() const {
275 return marker_cnt_;
276 }
277
279 uint32_t numMarks() const {
280 return marked_count_;
281 }
282
287 uint32_t numMarked() const {
288 uint32_t cnt = 0;
289 for(uint32_t i = 0; i < marker_cnt_; ++i) {
290 cnt += markers_[i].isMarked();
291 }
292 return cnt;
293 }
294
296 void reset() {
297 for(uint32_t i = 0; i < marker_cnt_; ++i) {
298 markers_[i].reset_();
299 }
300 marked_count_ = 0;
301 is_set_ = false;
302 }
303
305 void observe(const ScheduleableHandle & ev_hand) {
306 audience_.enroll(ev_hand);
307 }
308
310 void withdraw(const ScheduleableHandle & ev_hand) {
311 audience_.withdraw(ev_hand);
312 }
313
314 void release() {
315 audience_.release();
316 }
317
320 void setThreshold(uint32_t thresh) {
321 marked_thresh_ = thresh;
322 }
323
325 void attachMonitor(Monitor * mon) {
326 monitors_.emplace_back(mon);
327 }
328
330 void detachMonitor(Monitor *mon)
331 {
332 auto i = std::find(monitors_.begin(), monitors_.end(), mon);
333 if (i != monitors_.end()) {
334 monitors_.erase(i);
335 }
336 }
337
341 void notifyObservers() {
342 audience_.notify();
343 is_set_ = true;
344 }
345
348 bool isSet() const {
349 return is_set_;
350 }
351
352 private:
353
355 friend Marker;
356
358 friend State;
359
361 void jointSet_(MetaDataTPtr ptr = nullptr) {
362 ++marked_count_;
363 if (SPARTA_EXPECT_FALSE(!monitors_.empty())) {
364 for (auto& i : monitors_) {
365 i->signalSet(transition_val_, ptr);
366 }
367 //} else if ((markers_.size() - marked_count_) <= marked_thresh_) {
368 } else if ((marker_cnt_ - marked_count_) <= marked_thresh_) {
369 state_->setValue_(transition_val_);
370 notifyObservers();
371 is_set_ = true;
372 }
373
374 }
375
377 void clearMark_() {
378 sparta_assert(marked_count_ != 0);
379 --marked_count_;
380 }
381
382 // MarkerSet privates
383 uint32_t marked_count_ = 0;
384 uint32_t marked_thresh_ = 0;
385 //std::list<Marker> markers_;
386 Marker markers_[MAX_MARKERS];
387 uint32_t marker_cnt_ = 0;
388 State *state_ = nullptr;
389 EnumTValueType transition_val_; //<! The value to transition to
390 Audience audience_;
391 bool is_set_ = false;
392 std::vector<Monitor *> monitors_;
393 }; // class MarkerSet
394
397 friend class MarkerSet;
398
400 void setValue_(const EnumTValueType & val) {
401 current_state_ = val;
402 }
403
405 // construction. There are tests which assert that. So, this method
406 // when called, checks if this current instance is a State<bool> or not,
407 // and depending on that, sets the value to FALSE.
408 template<typename U = EnumT>
409 typename std::enable_if<std::is_same<U, bool>::value, void>::type
410 attemptSetValue_() {
411 setValue(BoolEnum::BoolValue::FALSE);
412 }
413
415 // construction. There are tests which assert that. So, this method
416 // when called, checks if this current instance is a State<bool> or not,
417 // and depending on that, sets the value to FALSE. If the current context
418 // is not tempaltized on bool, then do nothing.
419 template<typename U = EnumT>
420 typename std::enable_if<!std::is_same<U, bool>::value, void>::type
421 attemptSetValue_() {}
422
423 public:
425 // State Class
426
438 State(const EnumTValueType & initial_value = EnumType::__FIRST) :
439 initial_value_(initial_value),
440 current_state_(initial_value),
441
443 // procedure. The sparta::State class asks the StatePoolManager to dispatch
444 // a State Tracker Unit, templatized on the same enum type as itself, by
445 // calling the dispatchNewTracker() API. Inside the dispatchNewTracker() API,
446 // the pool manager looks at all the StatePool template instantiations that it
447 // manages, to check if it has one instantiation which is templated on the same
448 // type as requested right here. If it has, then we go to the second step of
449 // taking that StatePool handle and demand a new StateTrackerUnit out of it.
450 // The StatePool instance looks into its internal Tracker Queue to see if it
451 // has any available, ready-to-go tracker unit for dispatching. If yes, then
452 // it dispatches a std::unique_ptr to a new tracker unit back to the caller's
453 // side, which is sparta::State and sparta::State moves that into it's internal
454 // member variable. If the internal Tracker Queue does not have any tracker
455 // unit to go, the StatePool creates one from heap right then and dispatches
456 // it. If the Pool Manager does not have a StatePool instantiation of the
457 // requested enum type (which happens only on the first call for an enum type),
458 // the pool manager creates a new StatePool template instantiation and pushes it
459 // in its internal map, along with a unique ID, which separates all the different
460 // StatePool instantiations form each other.
461 state_tracker_unit_(std::move(
462 tracker::StatePoolManager::getInstance().
463 dispatchNewTracker<EnumType>()))
464 {
465
466 // If tracking is disabled, this internal
467 // tracker unit will be nullptr. In that case,
468 // we do not track anything.
469 if(state_tracker_unit_) {
470 state_tracker_unit_->startState(initial_value_);
471 }
472
473 for(uint32_t i = 0; i < EnumTValueType(EnumType::__LAST); ++i) {
474 marker_set_[i].transition_val_ = static_cast<EnumType>(i);
475 }
476 static_assert(std::is_enum<EnumType>::value,
477 "ERROR: State classes must be templatized on a valid enum or enum class type");
478 attemptSetValue_();
479 }
480
482 State(const State &other) :
483 initial_value_{other.initial_value_},
484 current_state_{other.current_state_},
485 marker_set_{other.marker_set_},
486 state_tracker_unit_{other.state_tracker_unit_ ? new auto {*other.state_tracker_unit_} : nullptr}
487 {}
488
489
491 State & operator = (const State &) = delete;
492
494 virtual ~State() {}
495
497 const EnumTValueType & getValue() const {
498 return current_state_;
499 }
500
501 const EnumType & getEnumValue() const {
502 return (current_state_.getValue()).getEnum();
503 }
504
509 sparta_assert(state_tracker_unit_ != nullptr,
510 "This method can only be called on this State class with tracking enabled");
511 return state_tracker_unit_->getActiveTime();
512 }
513
518 void setValue(const EnumTValueType & val) {
519
521 // tracker unit will be nullptr. In that case,
522 // we do not track anything.
523 if(state_tracker_unit_) {
524 state_tracker_unit_->startState(val);
525 }
526 setValue_(val);
527
528 // Notify audience members of state change. The observers
529 // are registered with the Audience in the marker set for
530 // that value type
531 marker_set_[val].notifyObservers();
532 }
533
540 void reset() {
541 current_state_ = static_cast<EnumTValueType>(initial_value_);
542 for(auto & ms : marker_set_) {
543 ms.reset();
544 }
545 attemptSetValue_();
546 }
547
555 void reset(const EnumTValueType & val) {
556 current_state_ = val;
557 for(auto & ms : marker_set_) {
558 ms.reset();
559 }
560 }
561
563 // \defgroup Assignment/comparison
565
569 void operator=(const EnumTValueType& val) {
570 setValue(val);
571 }
572
577 bool operator==(const EnumTValueType& rhs_val) const {
578 return (getValue() == rhs_val);
579 }
580
585 bool operator!=(const EnumTValueType& rhs_val) const {
586 return (getValue() != rhs_val);
587 }
588
590
592 // \defgroup Marker methods
594
601 return marker_set_[val].makeMarker(this);
602 }
603
609 uint32_t numMarks(const EnumTValueType & val) const {
610 return marker_set_[val].numMarks();
611 }
612
618 uint32_t numMarkers(const EnumTValueType & val) const {
619 return marker_set_[val].numMarkers();
620 }
621
627 bool complete(const EnumTValueType & val) const {
628 return (numMarks(val) == numMarkers(val));
629 }
630
639 void setMarkedThreshold(const EnumTValueType & val, uint32_t thresh) {
640 marker_set_[val].setThreshold(thresh);
641 }
642
644
646 // \defgroup Condition methods, API
648
654 bool isSet(const EnumTValueType & val = BoolEnum::BoolValue::TRUE) const
655 {
656 return (marker_set_[val].isSet() == true);
657 }
658
664 bool isClear(const EnumTValueType & val = BoolEnum::BoolValue::TRUE) const
665 {
666 return (marker_set_[val].isSet() == false);
667 }
668
670
672 // \defgroup Observation methods
674
681 void observe(const EnumTValueType & val,
682 const ScheduleableHandle & ev_hand)
683 {
684 marker_set_[val].observe(ev_hand);
685 }
686
692 void withdraw(const EnumTValueType & val,
693 const ScheduleableHandle & ev_hand)
694 {
695 marker_set_[val].withdraw(ev_hand);
696 }
697
698 void release(const EnumTValueType & val)
699 {
700 marker_set_[val].release();
701 }
702
704
706 // \defgroup Monitor methods
708
717 void attachMonitor(const EnumTValueType & val, Monitor * mon) {
718 marker_set_[val].attachMonitor(mon);
719 }
720
726 void detachMonitor(const EnumTValueType & val, Monitor *mon)
727 {
728 marker_set_[val].detachMonitor(mon);
729 }
730
732
733#ifndef DO_NOT_DOCUMENT
734 // Debug API for testing only.
735 // This only tests the stats accumulated by a
736 // single sparta::State instance.
737 const std::vector<Scheduler::Tick> & getRawAccumulatedTime() const {
738 sparta_assert(state_tracker_unit_ != nullptr);
739 return state_tracker_unit_->getStateSet().state_delta_set;
740 }
741#endif
742
743 private:
745 // State Privates
746 const EnumType initial_value_;
747 utils::ValidValue<EnumTValueType> current_state_;
748 std::array<MarkerSet, static_cast<uint32_t>(EnumType::__LAST)> marker_set_;
749
751 // This tracker is a unique pointer with its own deleter which
752 // knows what to do, when deleted.
753 tracker::state_tracker_ptr<EnumType> state_tracker_unit_;
754 }; // class State
755
756 // SimulationConfiguration which holds the state tracker
757 // name. The Simulation class contains an instance of this
758 // state template. When Simulation is being torn down,
759 // the destructor of this class is invoked and then in turn
760 // we start doing all the data collection and processing from
761 // each and every state tracker unit ever used, which are all
762 // queued up in their respective queues.
763 template<typename T>
764 class State<T,
765 typename std::enable_if<
766 std::is_same<T, PhasedObject::TreePhase>::value>::type> {
767 public:
768 State(app::Simulation * sim);
769 void configure();
770 ~State();
771
772 private:
773 app::Simulation * sim_ = nullptr;
774 };
775}
File that defines the Scheduleable class.
A simple time-based, event precedence based scheduler.
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.
#define SPARTA_EXPECT_FALSE(x)
A macro for hinting to the compiler a particular condition should be considered most likely false.
Exception class for all of Sparta.
This is the internal enum class which holds the enum values for bool instances. This enum has the sam...
The class responsible for handling State<bool> instances and converts bool instances into actual Enum...
Definition State.hpp:25
A light-weight reference counting handle for Scheduleables – DOES NOT delete.
uint64_t Tick
Typedef for our unit of time.
Class that will mark the state for transition.
Definition State.hpp:150
bool isMarked() const
Is the marker set? true if so.
Definition State.hpp:191
void set(MetaDataTPtr ptr=nullptr)
Set the marker.
Definition State.hpp:174
const EnumTValueType & getMarkerValue() const
Return the marker value for this marker (debug use)
Definition State.hpp:199
void clear()
Clear the marker.
Definition State.hpp:182
Monitor a particular State value and allow the user to determine a full state change.
Definition State.hpp:228
State::EnumTValueType EnumTValueType
Expose the State's EnumTValueType.
Definition State.hpp:232
virtual ~Monitor()
prevent deletion via the base pointer
Definition State.hpp:239
virtual void signalSet(const EnumTValueType &val, MetaDataTPtr)=0
The State class for watching transition between enum states.
Definition State.hpp:123
void reset(const EnumTValueType &val)
Reset this State class to the given value.
Definition State.hpp:555
bool isClear(const EnumTValueType &val=BoolEnum::BoolValue::TRUE) const
Determine if the State value is clear (never set)
Definition State.hpp:664
void detachMonitor(const EnumTValueType &val, Monitor *mon)
Decouple a monitor from a state value.
Definition State.hpp:726
State(const EnumTValueType &initial_value=EnumType::__FIRST)
Construct a State class.
Definition State.hpp:438
Marker * newMarker(const EnumTValueType &val)
Get a new marker for the enum type.
Definition State.hpp:600
State & operator=(const State &)=delete
Deleting default assignment operator to prevent copies.
void reset()
Reset this State class.
Definition State.hpp:540
Scheduler::Tick getTimeInState() const
Definition State.hpp:508
bool operator==(const EnumTValueType &rhs_val) const
Definition State.hpp:577
void withdraw(const EnumTValueType &val, const ScheduleableHandle &ev_hand)
withdraw event from this state
Definition State.hpp:692
bool isSet(const EnumTValueType &val=BoolEnum::BoolValue::TRUE) const
Determine if the State was ever set to value val.
Definition State.hpp:654
MetaDataT * MetaDataTPtr
A peeter to the MetaData.
Definition State.hpp:129
std::conditional<!std::is_same< EnumT, bool >::value, typenameutils::Enum< EnumT >::Value, BoolEnum >::type EnumTValueType
Convert the EnumT to a EnumT::Value or BoolEnum type.
Definition State.hpp:136
void setValue(const EnumTValueType &val)
Set a new enum value explicit and fire observers.
Definition State.hpp:518
void operator=(const EnumTValueType &val)
Assign a new state.
Definition State.hpp:569
bool operator!=(const EnumTValueType &rhs_val) const
Definition State.hpp:585
friend class MarkerSet
Definition State.hpp:397
bool complete(const EnumTValueType &val) const
For a particular value, have all the marks been made.
Definition State.hpp:627
virtual ~State()
Virtual destructor.
Definition State.hpp:494
State(const State &other)
Copy Constructor for State.
Definition State.hpp:482
void setMarkedThreshold(const EnumTValueType &val, uint32_t thresh)
Set the marker set threshold for the given state value.
Definition State.hpp:639
const EnumTValueType & getValue() const
Get the current value of the state.
Definition State.hpp:497
void observe(const EnumTValueType &val, const ScheduleableHandle &ev_hand)
Observe this state, specifically, when it transitions to the given enum val.
Definition State.hpp:681
uint32_t numMarkers(const EnumTValueType &val) const
Get the number of markers for the enum type.
Definition State.hpp:618
void attachMonitor(const EnumTValueType &val, Monitor *mon)
Attach a Monitor to a state value.
Definition State.hpp:717
std::conditional<!std::is_same< EnumT, bool >::value, EnumT, BoolEnum::BoolValue >::type EnumType
If EnumT is not an actual enum, we need to use.
Definition State.hpp:144
uint32_t numMarks(const EnumTValueType &val) const
Get the number of marks for the enum type.
Definition State.hpp:609
Simulator which builds a sparta DeviceTree.
const value_type & getValue() const
Get the value - const version.
Macros for handling exponential backoff.