17#include "sparta/utils/MetaStructs.hpp"
38 class PhasedPayloadEvent :
public EventNode
43 using ProxyAllocation = std::vector<std::unique_ptr<PayloadDeliveringProxy>>;
44 using ProxyFreeList = std::vector<PayloadDeliveringProxy *>;
45 using ProxyInflightList = sparta::utils::FastList <PayloadDeliveringProxy *>;
49 static constexpr size_t INITIAL_OUTSTANDING = 16;
63 "This Payload handle is already scheduled or was previously cancelled. "
64 "To schedule again, you must create a new one");
71 PhasedPayloadEvent<DataT> * parent) :
74 target_consumer_event_handler_(prototype.
getHandler()),
75 loc_(parent_->inflight_pl_.end())
86 friend class PhasedPayloadEvent;
93 void reclaim_()
override {
95 parent_->reclaimProxy_(loc_);
102 void eventCancelled_()
override {
109 void setPayload_(
const DataT & pl) {
111 payload_ =
new (&payload_storage_) DataT(pl);
115 void destroyPayload_() {
117 std::destroy_at(payload_);
121 const DataT & getPayload_()
const {
134 void deliverPayload_() {
136 "Some construct is trying to deliver a payload twice: "
137 << parent_->name_ <<
" to handler: "
138 << target_consumer_event_handler_.getName());
140 target_consumer_event_handler_((
const void*)payload_);
144 PhasedPayloadEvent<DataT> * parent_ =
nullptr;
145 const SpartaHandler target_consumer_event_handler_;
147 alignas(DataT) std::byte payload_storage_[
sizeof(DataT)];
149 bool scheduled_ =
false;
150 bool cancelled_ =
false;
155 ScheduleableHandle allocateProxy_(
const DataT & dat)
160 proxy = free_pl_[free_idx_];
164 if(allocation_idx_ == allocated_proxies_.size()) {
169 proxy = allocated_proxies_[allocation_idx_].get();
174 "' has allocated over " << inflight_pl_.
max_size() <<
175 " outstanding events -- does that seem right?");
177 proxy->setInFlightLocation_(inflight_pl_.
emplace_back(proxy));
178 proxy->setPayload_(dat);
184 friend class PayloadDeliveringProxy;
192 (*pl_location)->destroyPayload_();
193 free_pl_[free_idx_++] = *pl_location;
194 inflight_pl_.
erase(pl_location);
195 pl_location = inflight_pl_.
end();
217 const std::string & name,
219 const SpartaHandler & consumer_event_handler,
220 Clock::Cycle delay = 0,
223 name_(name +
"[" + consumer_event_handler.
getName() +
"]"),
224 prototype_(consumer_event_handler, delay, sched_phase),
225 inflight_pl_(INITIAL_OUTSTANDING, max_outstanding)
228 "You must assign a PhasedPayloadEvent a consumer handler "
229 "that takes exactly one argument");
236 for(PayloadDeliveringProxy * proxy : inflight_pl_) {
237 std::destroy_at(proxy->payload_);
262 return allocateProxy_(payload);
269 prototype_ >> consumer;
299 return inflight_pl_.
size();
308 for(
auto * proxy : inflight_pl_) {
309 if(proxy->isScheduled(rel_cycle)) {
328 const uint32_t cancel_cnt = inflight_pl_.
size();
331 auto bit = inflight_pl_.
begin();
332 while(bit != inflight_pl_.
end()) {
347 uint32_t
cancel(Clock::Cycle rel_cycle) {
348 const uint32_t cancel_cnt = inflight_pl_.
size();
349 auto bit = inflight_pl_.
begin();
350 while(bit != inflight_pl_.
end()) {
355 proxy->cancel(rel_cycle);
371 uint32_t cancel_cnt = 0;
374 auto bit = inflight_pl_.
begin();
375 while(bit != inflight_pl_.
end()) {
378 if(proxy->getPayload_() == criteria) {
397 std::vector<Scheduleable*> ple_vector;
398 for(
auto * proxy : inflight_pl_)
400 if(proxy->getPayload_() == criteria) {
401 ple_vector.push_back(proxy);
417 for(
auto * proxy : inflight_pl_)
419 if(proxy->getPayload_() == criteria) {
462 uint32_t
cancelIf(std::function<
bool(
const DataT &)> compare) {
463 uint32_t cancel_cnt = 0;
466 auto bit = inflight_pl_.
begin();
467 while(bit != inflight_pl_.
end()) {
470 if(compare(proxy->getPayload_())) {
517 std::vector<Scheduleable*>
getHandleIf(std::function<
bool(
const DataT &)> compare) {
518 std::vector<Scheduleable*> ple_vector;
519 for(
auto * proxy : inflight_pl_) {
520 if(compare(proxy->getPayload_())) {
521 ple_vector.push_back(proxy);
563 uint32_t
confirmIf(std::function<
bool(
const DataT &)> compare) {
564 for(
auto * proxy : inflight_pl_)
566 if(compare(proxy->getPayload_())) {
592 const std::string & name,
594 const SpartaHandler & consumer_event_handler,
595 Clock::Cycle delay = 0,
598 name_(name +
"[" + consumer_event_handler.
getName() +
"]"),
599 prototype_(consumer_event_handler, delay, sched_phase),
600 inflight_pl_(INITIAL_OUTSTANDING, max_outstanding)
604 "You must assign a PhasedPayloadEvent a consumer handler ""that takes exactly one argument");
611 void createResource_()
override {
622 const uint32_t old_size = allocated_proxies_.size();
623 const uint32_t new_size = payload_proxy_allocation_cadence_ + old_size;
624 allocated_proxies_.resize(new_size);
625 for(uint32_t i = old_size; i < new_size; ++i) {
628 free_pl_.resize(new_size,
nullptr);
635 Scheduleable prototype_;
637 ProxyAllocation allocated_proxies_;
638 ProxyFreeList free_pl_;
639 ProxyInflightList inflight_pl_;
644 const uint32_t payload_proxy_allocation_cadence_ = 16;
645 uint32_t free_idx_ = 0;
646 uint32_t allocation_idx_ = 0;
File that defines the EventNode class.
File that defines the FastList class – an alternative to std::list when the user knows the size of th...
File that defines the Scheduleable class.
File that defines the phases used in simulation.
#define sparta_assert(...)
Simple variadic assertion that will throw a sparta_exception if the condition fails.
#define SPARTA_EXPECT_TRUE(x)
A macro for hinting to the compiler a particular condition should be considered most likely true.
#define SPARTA_EXPECT_FALSE(x)
A macro for hinting to the compiler a particular condition should be considered most likely false.
#define CREATE_SPARTA_HANDLER(clname, meth)
File that defines the StartupEvent class.
File that defines a ValidValue.
EventNode is the base class for all event types in SPARTA. Not to be used by the modeler....
static Scheduler * determineScheduler(const Clock *clk)
Center point of Scheduler location.
Class to schedule a Scheduleable in the future with a payload, but the class itself is not typed on t...
virtual ~PhasedPayloadEvent()
Destroy!
uint32_t getNumOutstandingEvents() const
Return the number of unfired/unscheduled Payloads.
ScheduleableHandle preparePayload(const DataT &payload)
Prepare a Scheduleable Payload for scheduling either now or later.
uint32_t cancel(Clock::Cycle rel_cycle)
Cancel inflight PayloadEvents at the given relative cycle.
bool isScheduled() const
Is this PhasedPayloadEvent have anything scheduled?
PhasedPayloadEvent< DataT > & operator=(const PhasedPayloadEvent< DataT > &)=delete
No assignments, no copies.
void setContinuing(bool continuing)
This event, if continuing == true, will keep the simulation running.
uint32_t cancelIf(const DataT &criteria)
Cancel any scheduled Payload that matches the given criteria.
uint32_t confirmIf(std::function< bool(const DataT &)> compare)
Confirm if any scheduled payload matches the given criteria.
friend class PayloadDeliveringProxy
Allow the proxy to reclaim itself.
std::vector< Scheduleable * > getHandleIf(std::function< bool(const DataT &)> compare)
Return a vector of scheduleable handles that match the given function.
bool isScheduled(Clock::Cycle rel_cycle) const
Determine if this PhasedPayloadEvent is driven on the given cycle.
uint32_t cancel()
Cancel all inflight PayloadEvents.
PhasedPayloadEvent(const PhasedPayloadEvent< DataT > &)=delete
No assignments, no copies.
Scheduleable & operator>>(Scheduleable &consumer)
uint32_t cancelIf(std::function< bool(const DataT &)> compare)
Cancel any scheduled Payload that matches the given function.
static constexpr size_t DEFAULT_MAX_OUTSTANDING
std::vector< Scheduleable * > getHandleIf(const DataT &criteria)
Return a vector of scheduleable handles that match the given criteria.
Scheduleable & getScheduleable() override
Get the scheduleable associated with this event node.
bool confirmIf(const DataT &criteria)
Confirm if any scheduled payload matches the given criteria.
PhasedPayloadEvent(PhasedPayloadEvent< DataT > &&)=delete
No assignments, no copies.
A light-weight reference counting handle for Scheduleables – DOES NOT delete.
A class that defines the basic scheduling interface to the Scheduler. Not intended to be used by mode...
void setContinuing(bool continuing)
This event, if continuing == true, will keep the simulation running.
void setScheduler(Scheduler *sched)
Set the Scheduler of this Scheduleable, and set the local vertex_ to a new vertex from the Vertex Fac...
virtual void scheduleRelativeTick(const Scheduler::Tick rel_tick, Scheduler *const scheduler)
Schedule this event on a relative scheduler tick.
const SpartaHandler & getHandler() const
Get the consumer handler/callback associated with this event.
void setScheduleableClock(const Clock *clk)
Set the clock and scheduler of this Scheduleable.
uint32_t getScheduleableHandleCount_() const
SpartaHandler consumer_event_handler_
The Consumer callback registered with the Event.
Scheduleable(const SpartaHandler &consumer_event_handler, Clock::Cycle delay, SchedulingPhase sched_phase, bool is_unique_event=false)
Construct a Scheduleable object.
A class that lets you schedule events now and in the future.
uint64_t Tick
Typedef for our unit of time.
Node in a composite tree representing a sparta Tree item.
std::string getLocation() const override final
const std::string & getName() const override
Gets the name of this node.
const Clock * getClock() override
Walks up parents (starting with self) until a parent with an associated local clock is found,...
iterator end()
Obtain an end iterator.
iterator begin()
Obtain a beginning iterator.
iterator emplace_back(ArgsT &&...args)
emplace an object at the back
NodeIterator< false > iterator
iterator erase(const const_iterator &entry)
Erase an element with the given iterator.
Macros for handling exponential backoff.
SchedulingPhase
The SchedulingPhases used for events (Tick, Update, PortUpdate, etc)