17#include "sparta/collection/IterableCollector.hpp"
56 template<
class DataT, ArrayType ArrayT = ArrayType::AGED>
67 explicit ArrayPosition(U && data) :
68 data(std::forward<U>(data)){}
73 std::list<uint32_t>::iterator list_pointer;
74 uint64_t age_abs_id = 0;
75 uint32_t age_rel_id = 0;
79 typedef std::vector<ArrayPosition> ArrayVector;
109 template<
bool is_const_iterator = true>
114 typedef typename std::conditional<is_const_iterator,
116 value_type &>::type DataReferenceType;
118 typedef typename std::conditional<is_const_iterator,
125 uint32_t start_index,
132 is_circular_(is_circular),
133 is_aged_walk_(is_aged_walk)
138 operator uint32_t()
const {
143 DataReferenceType getAccess_(std::false_type) {
144 return array_->access(index_);
148 DataReferenceType getAccess_(std::true_type)
const {
149 return array_->read(index_);
166 index_(other.index_),
167 array_(other.array_),
168 is_aged_(other.is_aged_),
169 is_circular_(other.is_circular_),
170 is_aged_walk_(other.is_aged_walk_)
178 index_(other.index_),
179 array_(other.array_),
180 is_aged_(other.is_aged_),
181 is_circular_(other.is_circular_),
182 is_aged_walk_(other.is_aged_walk_)
206 "Cannot operate on an unitialized iterator.");
213 return (array_ !=
nullptr) &&
214 (index_ != array_->invalid_entry_) &&
215 (array_->isValid(index_));
228 "Cannot operate on an uninitialized iterator.");
229 return array_->isOlder(index_, idx);
251 "Cannot operate on an uninitialized iterator.");
269 return (rhs.index_ == index_) && (rhs.array_ == array_);
272 bool operator==(
const uint32_t & rhs)
const
274 return (rhs == index_);
279 return (rhs.index_ != index_) || (rhs.array_ != array_);
285 "Cannot operate on an uninitialized iterator.");
287 return getAccess_(std::integral_constant<bool, is_const_iterator>());
293 "Cannot operate on an uninitialized iterator.");
295 return getAccess_(std::integral_constant<bool, is_const_iterator>());
302 "Cannot operate on an uninitialized iterator.");
303 return std::addressof(getAccess_(std::integral_constant<bool, is_const_iterator>()));
309 "Cannot operate on an uninitialized iterator.");
310 return std::addressof(getAccess_(std::integral_constant<bool, is_const_iterator>()));
317 "Cannot operate on an uninitialized iterator.");
329 if(is_circular_) {
return *
this; }
368 uint32_t index_ = std::numeric_limits<uint32_t>::max();
369 ArrayPointerType array_ =
nullptr;
370 bool is_aged_ =
false;
371 bool is_circular_ =
false;
372 bool is_aged_walk_ =
false;
388 constexpr bool is_aged =
false;
389 constexpr bool is_circular =
true;
390 constexpr bool is_aged_walk =
false;
391 return iterator(
this, idx, is_aged, is_circular, is_aged_walk);
397 constexpr bool is_aged =
false;
398 constexpr bool is_circular =
false;
399 constexpr bool is_aged_walk =
false;
400 return iterator(
this, invalid_entry_, is_aged, is_circular, is_aged_walk);
406 constexpr bool is_aged =
false;
407 constexpr bool is_circular =
false;
408 constexpr bool is_aged_walk =
false;
409 return iterator(
this, 0, is_aged, is_circular, is_aged_walk);
415 constexpr bool is_aged =
false;
416 constexpr bool is_circular =
false;
417 constexpr bool is_aged_walk =
false;
418 return const_iterator(
this, 0, is_aged, is_circular, is_aged_walk);
424 constexpr bool is_aged =
false;
425 constexpr bool is_circular =
false;
426 constexpr bool is_aged_walk =
false;
427 return iterator(
this, invalid_entry_, is_aged, is_circular, is_aged_walk);
433 constexpr bool is_aged =
false;
434 constexpr bool is_circular =
false;
435 constexpr bool is_aged_walk =
false;
436 return const_iterator(
this, invalid_entry_, is_aged, is_circular, is_aged_walk);
442 constexpr bool is_aged =
true;
443 constexpr bool is_circular =
false;
444 constexpr bool is_aged_walk =
true;
448 return iterator(
this, invalid_entry_, is_aged, is_circular, is_aged_walk);
455 constexpr bool is_aged =
true;
456 constexpr bool is_circular =
false;
457 constexpr bool is_aged_walk =
true;;
461 return const_iterator(
this, invalid_entry_, is_aged, is_circular, is_aged_walk);
467 constexpr bool is_aged =
true;
468 constexpr bool is_circular =
false;
469 constexpr bool is_aged_walk =
true;
470 return iterator(
this, invalid_entry_, is_aged, is_circular, is_aged_walk);
476 constexpr bool is_aged =
true;
477 constexpr bool is_circular =
false;
478 constexpr bool is_aged_walk =
true;
479 return const_iterator(
this, invalid_entry_, is_aged, is_circular, is_aged_walk);
518 Array(
const std::string& name, uint32_t num_entries,
const Clock* clk,
542 return valid_index_set_.find(idx) != valid_index_set_.end();
550 const DataT&
read(
const uint32_t idx)
const {
552 <<
" Cannot read from an invalid index. Idx:" << idx);
553 return array_[idx].data;
562 <<
" Cannot read from an invalid index. Idx:" << idx);
563 return (array_[idx].data);
581 "Only AgedArray types have public member function getOldestIndex");
583 "The array does not have enough elements to find the nth oldest index");
585 constexpr bool is_aged =
true;
586 constexpr bool is_circular =
false;
587 constexpr bool is_aged_walk =
true;
593 auto it = aged_list_.rbegin();
594 uint32_t idx = invalid_entry_;
595 for(uint32_t i = 0; i <= nth; ++i)
603 return const_iterator(
this, idx, is_aged, is_circular, is_aged_walk);
619 "Only AgedArray types provide access to public member"
620 " function getYoungestIndex");
622 "The array does not have enough elements to find the nth youngest index");
623 constexpr bool is_aged =
true;
624 constexpr bool is_circular =
false;
625 constexpr bool is_aged_walk =
true;
628 uint32_t idx = invalid_entry_;
629 auto it = aged_list_.begin();
630 for(uint32_t i = 0; i <= nth; ++i)
637 return const_iterator(
this, idx, is_aged, is_circular, is_aged_walk);
646 auto it = std::find(aged_list_.begin(), aged_list_.end(), prev_idx);
647 if(it == aged_list_.begin()) {
659 uint32_t
getAge(
const uint32_t idx)
const {
661 "Only AgedArray types provides age information");
663 return array_[idx].age_rel_id;
703 return num_entries_ - num_valid_;
725 array_[idx].valid =
false;
731 aged_list_.erase(array_[idx].list_pointer);
733 updateRelativeAge_();
739 utilization_->setValue(num_valid_);
741 array_[idx].~ArrayPosition();
742 valid_index_set_.erase(idx);
750 std::for_each(valid_index_set_.begin(), valid_index_set_.end(), [
this](
const auto index){
751 array_[index].~ArrayPosition();
753 valid_index_set_.clear();
758 utilization_->setValue(num_valid_);
770 void write(
const uint32_t idx,
const DataT& dat)
772 writeImpl_(idx, dat);
783 void write(
const uint32_t idx, DataT&& dat)
785 writeImpl_(idx, std::move(dat));
825 "Cannot compare age on an index outside the bounds of the array");
826 return array_[lhs].age_abs_id > array_[rhs].age_abs_id;
840 "Cannot compare age on an index outside the bounds of the array");
841 return array_[lhs].age_abs_id < array_[rhs].age_abs_id;
859 (parent, name_ +
"_age_ordered",
866 class AgedArrayCollectorProxy
870 typedef uint32_t size_type;
872 AgedArrayCollectorProxy(FullArrayType * array) : array_(array) { }
877 return array_->abegin();
881 return array_->aend();
884 uint32_t size()
const {
885 return array_->size();
889 FullArrayType * array_ =
nullptr;
896 const AgedList & getInternalAgedList_()
const
908 void updateRelativeAge_()
916 auto it = aged_list_.rbegin();
917 uint32_t idx = invalid_entry_;
918 const uint32_t
size = aged_list_.size();
919 for(uint32_t i = 0; i <
size; ++i)
926 array_[idx].age_rel_id = i;
931 void writeImpl_(
const uint32_t idx, U&& dat)
934 "Cannot write to an index outside the bounds of the array.");
941 aged_list_.erase(array_[idx].list_pointer);
947 new (array_.get() + idx) ArrayPosition(std::forward<U>(dat));
948 valid_index_set_.insert(idx);
951 array_[idx].age_abs_id = next_age_abs_id_;
955 array_[idx].valid =
true;
963 aged_list_.push_front(idx);
964 array_[idx].list_pointer = aged_list_.begin();
966 updateRelativeAge_();
972 utilization_->setValue(num_valid_);
976 const std::string name_;
978 struct DeleteToFree_{
979 void operator()(
void * x){
986 const uint32_t invalid_entry_{num_entries_ + 1};
993 std::unique_ptr<ArrayPosition[], DeleteToFree_> array_ =
nullptr;
996 std::unordered_set<uint32_t> valid_index_set_ {};
1000 AgedArrayCollectorProxy aged_array_col_{
this};
1005 uint64_t next_age_abs_id_;
1009 std::unique_ptr<sparta::CycleHistogramStandalone> utilization_;
1013 std::unique_ptr<collection::IterableCollector<FullArrayType,
1016 std::unique_ptr<collection::IterableCollector<AgedArrayCollectorProxy> > age_collector_;
1019 template<
class DataT, ArrayType ArrayT>
1021 uint32_t num_entries,
1029 num_entries_(num_entries),
1035 array_.reset(
static_cast<ArrayPosition *
>(malloc(
sizeof(ArrayPosition) * num_entries_)));
1037 if((num_entries > 0) && statset)
1040 name +
"_utilization",
1041 name +
" occupancy histogram",
1042 0, num_entries_, 1, 0,
CycleHistogram implementation using sparta CycleCounter.
Defines a few handy (and now deprecated) C++ iterator traits.
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.
Array is essentially a fixed size vector, maintains a concept of validity of its indexes,...
void erase(const uint32_t &idx)
Invalidate the entry at a certain index.
size_type capacity() const
Return the maximum number of elements this Array can hold.
void write(const iterator &iter, const DataT &dat)
Write data at an iterator position.
iterator end()
STL-like end operation.
iterator abegin()
STL-like begin operation, starts at the oldest valid index.
bool getNextOldestIndex(uint32_t &prev_idx) const
Sets the input argument to the index containing the location of the next oldest item after input argu...
ArrayIterator< true > const_iterator
Typedef for constant iterator.
const std::string & getName() const
Name of this resource.
const AgedList & getAgedList() const
Provide access to our aged_list_ internals.
void write(const uint32_t idx, const DataT &dat)
Write data to the array.
size_type numFree() const
The number of free entries.
DataT & access(const uint32_t idx)
Access (writeable) the data at a position.
Array(const std::string &name, 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 an array.
const_iterator getYoungestIndex(const uint32_t nth=0) const
provide access the youngest index in the array.
bool isValid(const uint32_t idx) const
Determine whether an index is currently valid.
iterator aend()
STL-like end operation.
const_iterator getOldestIndex(const uint32_t nth=0) const
Return the oldest index in the array.
uint32_t getAge(const uint32_t idx) const
Provide the age information of the given entry index.
const_iterator aend() const
STL-like end operation, const.
const DataT & read(const uint32_t idx) const
Read (only) the data at an index.
DataT DataType
Expected typedef for the data that will be stored in this structure.
const_iterator abegin() const
STL-like begin operation, const, starts at the oldest valid index.
iterator begin()
STL-like begin operation, starts at index 0 (ignores valid bit).
std::list< uint32_t > AgedList
Typedef for a list of indexes in age order.
ArrayIterator< false > iterator
Typedef for regular iterator.
uint32_t size_type
Typedef for size_type.
void write(const iterator &iter, DataT &&dat)
Write data at an iterator position.
void enableCollection(TreeNode *parent)
Set up a auto-collector for this Array.
iterator getUnitializedIterator()
Provide a method to get an uninitialized iterator.
bool isYounger(uint32_t lhs, uint32_t rhs)
Determine if an index was written (using write()) to the Array after another index.
DataT value_type
The data type, STL style.
const_iterator begin() const
STL-like begin operation, const, starts at index 0 (ignores valid bit).
iterator getCircularIterator(uint32_t idx=0)
Get an iterator that is circular on the Array (has no end())
bool isOlder(uint32_t lhs, uint32_t rhs)
Determine if an index was written (using write()) to the Array before another index.
size_type numValid() const
The number of valid entries contained.
virtual ~Array()
Virtual destructor.
const_iterator end() const
STL-like end operation, const.
void erase(const iterator &iter)
Invalidate data at an iterator position.
void clear()
Clear the array of all data.
void write(const uint32_t idx, DataT &&dat)
Write data to the array.
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 ...
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.
ArrayType
Defines how a sparta::Array should behave. The array will have different features depending on the ty...
T * notNull(T *p)
Ensures that a pointer is not null.
@ Collection
Pipeline collection occurs here.
An iterator struct for this array.
ArrayIterator operator++(int)
post-increment operator.
ArrayIterator & operator++()
pre-increment operator.
bool isYounger(const ArrayIterator &other) const
Overload isYounger to accept another iterator instead of index.
bool isIndexValid() const
Determine whether this iterator has been initialized with a valid index.
DataReferenceType operator*() const
support the dereference operator, const
DataReferenceType operator*()
support the dereference operator, non-const
bool isValid() const
Determine whether this array entry pointed to by this iterator is valid.
ArrayIterator()=default
Default constructor.
ArrayIterator & operator=(const ArrayIterator &other)=default
Assignment operator.
bool isOlder(const ArrayIterator &other) const
Overload isOlder to accept another iterator instead of an index.
ArrayIterator(const ArrayIterator< true > &other)
a copy constructor that allows for implicit conversion from a const_iterator to a regular iterator.
bool isYounger(const uint32_t idx) const
determine if the data at this iterator was written to more recently than another index.
value_type * operator->()
support -> operator.
bool operator<(const ArrayIterator &rhs) const
ArrayIterator(const ArrayIterator< false > &other)
a copy constructor that allows for implicit conversion from a regular iterator to a const_iterator.
uint32_t getIndex() const
What index does our iterator currently represent.
bool isOlder(const uint32_t idx) const
determine if the data at this iterator was written before the data at another index.
void reset()
Reset the iterator to an invalid value.