20#include "sparta/collection/IterableCollector.hpp"
68 template <
class DataT>
80 using size_type = uint32_t;
147 constexpr uint32_t nextPowerOfTwo_(uint32_t val)
const
149 if(val < 2) {
return 1ull; }
150 return 1ull << ((
sizeof(uint64_t) * 8) - __builtin_clzll(val - 1ull));
154 uint32_t rollPhysicalIndex_(
const uint32_t phys_idx)
const {
155 return (vector_size_ - 1) & (phys_idx);
159 uint32_t getPhysicalIndex_(
const uint32_t logical_idx)
const {
160 return rollPhysicalIndex_(logical_idx + current_head_idx_);
166 uint32_t incrementIndexValue_(
const uint32_t val)
const {
167 return rollPhysicalIndex_(val + 1);
173 uint32_t decrementIndexValue_(
const uint32_t val)
const {
174 return rollPhysicalIndex_(val - 1);
179 template<
class DataTRef>
180 QueueData(DataTRef && dat, uint64_t in_obj_id) :
181 data(std::forward<DataTRef>(dat)),
190 const value_type & readPhysical_(
const uint32_t phys_idx)
const
192 return queue_data_[phys_idx].data;
196 value_type & accessPhysical_(
const uint32_t phys_idx)
198 return queue_data_[phys_idx].data;
202 uint32_t physicalToLogical_(
const uint32_t physical_idx)
const {
203 if(physical_idx == invalid_index_) {
return invalid_index_; }
205 return rollPhysicalIndex_(physical_idx - current_head_idx_);
209 bool isValidPhysical_(
const uint32_t physical_idx)
const
211 const auto log_idx = physicalToLogical_(physical_idx);
212 return (log_idx <
size());
226 template <
bool is_const_iterator = true>
230 using DataReferenceType =
typename std::conditional<is_const_iterator,
231 const value_type &, value_type &>::type;
232 using QueuePointerType =
typename std::conditional<is_const_iterator,
240 QueueIterator(QueuePointerType q, uint32_t physical_index, uint32_t obj_id) :
242 physical_index_(physical_index),
247 friend class Queue<DataT>;
250 bool isAttached_()
const {
return nullptr != attached_queue_; }
266 attached_queue_(iter.attached_queue_),
267 physical_index_(iter.physical_index_),
268 obj_id_(iter.obj_id_)
275 attached_queue_(iter.attached_queue_),
276 physical_index_(iter.physical_index_),
277 obj_id_(iter.obj_id_)
284 if(
nullptr == attached_queue_) {
return false; }
285 return attached_queue_->determineIteratorValidity_(
this);
297 "Cannot compare QueueIterators created by different Queues");
305 "Cannot compare QueueIterators created by different Queues");
313 "Cannot compare QueueIterators created by different Queues");
314 return (physical_index_ == rhs.physical_index_) && (obj_id_ == rhs.obj_id_);
319 return !(*
this == rhs);
326 attached_queue_->incrementIterator_(
this);
342 attached_queue_->decrementIterator_(
this);
357 return getAccess_(std::integral_constant<bool, is_const_iterator>());
364 return std::addressof(getAccess_(std::integral_constant<bool, is_const_iterator>()));
370 return std::addressof(getAccess_(std::integral_constant<bool, is_const_iterator>()));
380 return attached_queue_->physicalToLogical_(physical_index_);
385 QueuePointerType attached_queue_ {
nullptr};
386 uint32_t physical_index_ = std::numeric_limits<uint32_t>::max();
387 uint64_t obj_id_ = 0;
390 DataReferenceType getAccess_(std::false_type)
const {
391 return attached_queue_->accessPhysical_(physical_index_);
395 DataReferenceType getAccess_(std::true_type)
const {
396 return attached_queue_->readPhysical_(physical_index_);
441 const uint32_t num_entries,
448 num_entries_(num_entries),
449 vector_size_(nextPowerOfTwo_(num_entries*2)),
454 if((num_entries > 0) && statset)
457 name +
"_utilization",
458 name +
" occupancy histogram",
459 0, num_entries, 1, 0,
469 queue_data_.reset(
static_cast<QueueData *
>(malloc(
sizeof(QueueData) * vector_size_)));
495 return (idx <
size());
505 return readPhysical_(getPhysicalIndex_(idx));
517 return accessPhysical_(getPhysicalIndex_(idx));
525 sparta_assert(
size() != 0, name_ <<
": Trying to get front() on an empty Queue");
526 return queue_data_[current_head_idx_].data;
535 uint32_t index = current_write_idx_;
536 index = decrementIndexValue_(index);
537 return queue_data_[index].data;
572 return (total_valid_ == 0);
582 auto idx = current_head_idx_;
583 while (idx != current_write_idx_)
585 queue_data_[idx].data.~value_type();
586 idx = incrementIndexValue_(idx);
588 current_write_idx_ = 0;
589 current_head_idx_ = 0;
591 updateUtilizationCounters_();
617 return pushImpl_(dat);
629 return pushImpl_(std::move(dat));
638 sparta_assert(total_valid_ != 0, name_ <<
": Trying to pop an empty Queue");
641 queue_data_[current_head_idx_].data.~value_type();
644 current_head_idx_ = incrementIndexValue_(current_head_idx_);
647 processInvalidation_();
656 sparta_assert(total_valid_ != 0, name_ <<
": Trying to pop_back an empty Queue");
659 current_write_idx_ = decrementIndexValue_(current_write_idx_);
662 queue_data_[current_write_idx_].data.~value_type();
665 processInvalidation_();
675 return iterator(
this, current_head_idx_, queue_data_[current_head_idx_].obj_id);
690 return const_iterator(
this, current_head_idx_, queue_data_[current_head_idx_].obj_id);
707 new (queue_data_.get() + current_write_idx_) QueueData(std::forward<U>(dat), ++obj_id_);
710 const uint32_t write_idx = current_write_idx_;
711 current_write_idx_ = incrementIndexValue_(current_write_idx_);
717 updateUtilizationCounters_();
719 return iterator(
this, write_idx, obj_id_);
722 template<
typename IteratorType>
723 bool determineIteratorValidity_(IteratorType * itr)
const
725 const auto physical_index = itr->physical_index_;
727 if(physical_index == invalid_index_) {
732 if(
empty()) {
return false; }
734 if(isValidPhysical_(physical_index)) {
735 return (queue_data_[physical_index].obj_id == itr->obj_id_);
740 template<
typename IteratorType>
741 void decrementIterator_(IteratorType * itr)
const
744 ": Iterator is not valid for decrementing");
746 uint32_t physical_index = itr->physical_index_;
750 const uint32_t phys_idx = decrementIndexValue_(current_write_idx_);
751 itr->physical_index_ = phys_idx;
752 itr->obj_id_ = queue_data_[phys_idx].obj_id;
757 physical_index = decrementIndexValue_(physical_index);
758 if(isValidPhysical_(physical_index)) {
759 itr->physical_index_ = physical_index;
760 itr->obj_id_ = queue_data_[physical_index].obj_id;
763 itr->physical_index_ = invalid_index_;
764 itr->obj_id_ = invalid_index_;
769 template<
typename IteratorType>
770 void incrementIterator_(IteratorType * itr)
const
772 uint32_t physical_index = itr->physical_index_;
777 name_ <<
": Trying to increment an invalid iterator");
779 physical_index = incrementIndexValue_(physical_index);
783 if(isValidPhysical_(physical_index))
786 itr->physical_index_ = physical_index;
787 itr->obj_id_ = queue_data_[physical_index].obj_id;
792 itr->physical_index_ = invalid_index_;
793 itr->obj_id_ = invalid_index_;
797 void updateUtilizationCounters_() {
800 utilization_->setValue(total_valid_);
805 void processInvalidation_()
809 updateUtilizationCounters_();
812 const size_type num_entries_;
813 size_type current_write_idx_ = 0;
814 size_type current_head_idx_ = 0;
815 size_type total_valid_ = 0;
816 const size_type vector_size_;
817 const size_type invalid_index_ {vector_size_ + 1};
818 const std::string name_;
821 uint64_t obj_id_ = 0;
825 std::unique_ptr<sparta::CycleHistogramStandalone> utilization_;
829 std::unique_ptr<collection::IterableCollector<Queue<value_type> > > collector_;
835 struct DeleteToFree_{
836 void operator()(
void * x){
840 std::unique_ptr<QueueData[], DeleteToFree_> queue_data_;
CycleHistogram implementation using sparta CycleCounter.
Virtual interface node for simulator instrumentation (e.g. counters, stats, nontifications).
Defines a few handy (and now deprecated) C++ iterator traits.
File that defines the Port base class.
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.
File that defines the StatisticSet class.
A representation of simulated time.
CycleHistogramStandalone class for uint64_t values.
uint32_t visibility_t
Continuous visibility level. Several key points along continum are indicated within Visibility.
@ VIS_HIDDEN
Hidden hint. Lowest possible visibility.
static constexpr visibility_t AUTO_VISIBILITY
The default sparta resource visibility value that should be used. This is an alias of VIS_MAX at the ...
Class that alows queue elements to be accessed like a normal stl iterator. Queue iterator is a bidire...
DataReferenceType operator*()
Dereferencing operator.
QueueIterator & operator=(const QueueIterator &rhs)=default
Assignment operator.
QueueIterator(const QueueIterator< true > &iter)
QueueIterator()=default
Default constructor.
value_type * operator->()
support -> operator
bool operator<(const QueueIterator &rhs) const
overload the comparison operator.
bool operator==(const QueueIterator &rhs) const
overload the comparison operator.
QueueIterator operator++(int)
Post-Increment iterator.
bool operator!=(const QueueIterator &rhs) const
overload the comparison operator.
QueueIterator(const QueueIterator< false > &iter)
bool operator>(const QueueIterator &rhs) const
overload the comparison operator.
QueueIterator & operator--()
Pre-decrement iterator.
QueueIterator & operator++()
Pre-Increment operator.
uint32_t getIndex() const
A data structure that allows appending at the back and invalidating from the front.
DataT value_type
Typedef for the DataT.
const_iterator begin() const
STL-like begin operation, starts at front (oldest element)
value_type & back() const
Read and return the last pushed in element(newest element), reference.
bool isValid(uint32_t idx) const
Determine if data at the index is valid.
value_type & front() const
Read and return the data at the front(oldest element), reference.
size_type numFree() const
Return the number of free entries.
Queue(const Queue< value_type > &)=delete
No copies, no moves.
const_iterator end() const
STL - like end operation, starts at element one past head.
QueueIterator< false > iterator
Typedef for regular iterator.
size_type size() const
Return the number of valid entries.
bool empty() const
Return if the queue is empty or not.
iterator begin()
STL-like begin operation, starts at front (oldest element)
uint32_t capacity() const
Return the fixed size of this queue.
const value_type & read(uint32_t idx) const
Read and return the data at the given index, const reference.
Queue & operator=(const Queue< value_type > &)=delete
Deleting default assignment operator to prevent copies.
QueueIterator< true > const_iterator
Typedef for constant iterator.
const std::string & getName() const
Name of this resource.
iterator end()
STL - like end operation, starts at element one past head.
void pop_back()
Pops the data at the back of the structure (newest element) After pop iterator always points to the l...
Queue(const std::string &name, const uint32_t num_entries, const Clock *clk, StatisticSet *statset=nullptr, InstrumentationNode::visibility_t stat_vis_general=InstrumentationNode::AUTO_VISIBILITY, InstrumentationNode::visibility_t stat_vis_detailed=InstrumentationNode::VIS_HIDDEN, InstrumentationNode::visibility_t stat_vis_max=InstrumentationNode::AUTO_VISIBILITY, InstrumentationNode::visibility_t stat_vis_avg=InstrumentationNode::AUTO_VISIBILITY)
Construct a queue.
iterator push(const value_type &dat)
push data to the Queue.
value_type & access(uint32_t idx)
Read and return the data at the given index, reference, non-const method.
iterator push(value_type &&dat)
push data to the Queue.
~Queue()
Destroy the Queue, clearing everything out.
void enableCollection(TreeNode *parent)
Request that this queue begin collecting its contents for pipeline collection.
void clear()
Empty the queue.
void pop()
Pops the data at the front of the structure (oldest element) After pop iterator always points to the ...
Set of StatisticDef and CounterBase-derived objects for visiblility through a sparta Tree.
Node in a composite tree representing a sparta Tree item.
A collector of any iterable type (std::vector, std::list, sparta::Buffer, etc)
Macros for handling exponential backoff.