10#include "sparta/functional/ArchDataSegment.hpp"
11#include "sparta/functional/ArchData.hpp"
69 const uint8_t* initial_buf_le=
nullptr) :
71 adata_(data), offset_(0),
73 initial_buf_le_(initial_buf_le)
76 static_assert(
sizeof(uint64_t) >
sizeof(
index_type),
77 "Must have a type larger than index_type in order to "
78 "perform bounds checking on index values which must "
79 "support the entire range from 0 to the maximum value");
86 if(subset_of ==
INVALID_ID && subset_offset != 0){
87 throw SpartaException(
"Cannot construct DataView with a valid identifier and nonzero offset: 0x")
88 << std::hex << subset_offset <<
". Change subset_offset to 0 or set subset_of to INVALID_ID";
141 template <
typename T, ByteOrder BO=LE>
144 "read index " << idx <<
" and type " <<
demangle(
typeid(T).name())
145 <<
" (size " <<
sizeof(T) <<
") is invalid for this DataView of size " <<
getSize());
146 return readUnsafe<T, BO>(idx);
154 template <
typename T, ByteOrder BO=LE>
156 sparta_assert(line_,
"There is no line pointer set for this DataView. ArchData likely has not been laid out yet. Tree probably needs to be finalized first.");
157 return line_->
read<T, BO>(offset_, idx);
171 template <
typename T, ByteOrder BO=LE>
174 "readPadded index " << idx <<
" and type " <<
demangle(
typeid(T).name())
175 <<
" (size " <<
sizeof(T) <<
") is invalid for this DataView of size " <<
getSize());
176 return readPaddedUnsafe<T, BO>(idx);
185 template <
typename T, ByteOrder BO=LE>
187 sparta_assert(line_,
"There is no line pointer set for this DataView. ArchData likely has not been laid out yet. Tree probably needs to be finalized first.");
193 result = line_->
read<uint64_t, BO>(offset_, idx);
194 }
else if(max_bytes == 4){
195 result = line_->
read<uint32_t, BO>(offset_, idx);
196 }
else if(max_bytes == 2){
197 result = line_->
read<uint16_t, BO>(offset_, idx);
198 }
else if(max_bytes == 1){
199 result = line_->
read<uint8_t, BO>(offset_, idx);
236 template <
typename T, ByteOrder BO=LE>
239 "write index " << idx <<
" and type " <<
demangle(
typeid(T).name())
240 <<
" (size " <<
sizeof(T) <<
") is invalid for this DataView of size " <<
getSize());
242 writeUnsafe<T, BO>(val, idx);
251 template <
typename T, ByteOrder BO=LE>
253 sparta_assert(line_,
"There is no line pointer set for this DataView. ArchData likely has not been laid out yet. Tree probably needs to be finalized first.");
255 line_->
write<T, BO>(offset_, val, idx);
274 template <
typename T, ByteOrder BO=LE>
277 "writeTruncated index " << idx <<
" and type " <<
demangle(
typeid(T).name())
278 <<
" (size " <<
sizeof(T) <<
") is invalid for this DataView of size " <<
getSize());
280 writeTruncatedUnsafe<T, BO>(val, idx);
291 template <
typename T, ByteOrder BO=LE>
293 sparta_assert(line_,
"There is no line pointer set for this DataView. ArchData likely has not been laid out yet. Tree probably needs to be finalized first.");
298 line_->
write<uint64_t, BO>(offset_, (uint64_t)val, idx);
299 }
else if(max_bytes == 4){
300 line_->
write<uint32_t, BO>(offset_, (uint32_t)val, idx);
301 }
else if(max_bytes == 2){
302 line_->
write<uint16_t, BO>(offset_, (uint16_t)val, idx);
303 }
else if(max_bytes == 1){
304 line_->
write<uint8_t, BO>(offset_, (uint8_t)val, idx);
321 throw SpartaException(
"Cannot copy data between DataViews using operator= because the sizes differ");
323 if(rhp.line_ ==
nullptr){
324 throw SpartaException(
"Cannot copy data between DataViews using operator= because the right-hand operand is not laid out");
326 if(line_ ==
nullptr){
327 throw SpartaException(
"Cannot copy data between DataViews using operator= because the left-hand operand is not laid out");
330 const uint8_t*
const src = rhp.line_->
getDataPointer(rhp.offset_);
353 o << std::setw(2) << std::hex << (uint16_t)read<uint8_t, LE>(i) <<
' ';
366 template <ByteOrder BO=LE>
370 std::stringstream ss;
371 ss <<
"0x" << std::hex << std::setw(
getSize()*2) << std::setfill(
'0');
374 ss << (uint32_t)read<uint8_t, BO>();
377 ss << (uint32_t)read<uint16_t, BO>();
380 ss << read<uint32_t, BO>();
383 assembleIndexedReadsToValue_<BO>(ss);
402 line_ = &adata_->
getLine(offset);
413#if __BYTE_ORDER == __LITTLE_ENDIAN
415 write<uint8_t>(initial_buf_le_[i], i);
419 write<uint8_t>(initial_buf_le_[i], i);
434 template <ByteOrder BO=LE>
435 void assembleIndexedReadsToValue_(std::stringstream& ss)
const {
436 ss <<
"<unknown byte-order: " << BO <<
">";
439 ArchData*
const adata_;
441 ArchData::Line* line_;
447 const uint8_t*
const initial_buf_le_;
451 inline void DataView::assembleIndexedReadsToValue_<LE>(std::stringstream& ss)
const {
453 ss << std::setw(16) << read<uint64_t, LE>(i-1);
458 inline void DataView::assembleIndexedReadsToValue_<BE>(std::stringstream& ss)
const {
460 ss << std::setw(16) << read<uint64_t, BE>(i);
467#define SPARTA_DATAVIEW_BODY \
468 const std::string sparta::DataView::DATAVIEW_UNPLACED_STR = "dataview-unplaced";
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.
Exception class for all of Sparta.
static const ident_type INVALID_ID
Indicates an invalid ID for an ArchDataSegment or any refinement.
ident_type getLayoutID() const
Gets the layout Identifier of this segment.
offset_type getLayoutSize() const
Gets the layout size of this segment (number of bytes)
bool isPlaced() const
Has this segment been placed yet.
Line object which composes part of an entire ArchData.
void write(offset_type offset, const T &t, uint32_t idx=0)
Write to this line, reordering bytes based on byte order if required.
T read(offset_type offset, uint32_t idx=0) const
Read from this line, reordering bytes based on byte order if required.
const uint8_t * getDataPointer(offset_type offset) const
Gets a pointer to data within this line for direct read access.
offset_type getOffset() const
Offset into the owning ArchData.
Contains a set of contiguous line of architectural data which can be referred to by any architected o...
void registerSegment(ArchDataSegment *seg)
All constructed segments must register themselves through this method to be laid out within the ArchD...
void checkSegment(offset_type offset, offset_type size) const
Checks that a segment is valid within this archdata by its given offset and size.
Line & getLine(offset_type offset)
Gets the line associated with this offset, allocating a new line if necessary.
View into a backend block of memory in an ArchData.
static const ident_type INVALID_ID
Invalid Identifier constant for a DataView.
std::string getValueAsString() const
Reads the value of this DataView and renders as a string in the specified Byte-Order as a prefixed he...
uint32_t index_type
Type used for specifying index into this DataView during a read or write.
ArchData::Line * getLine() const
Get already-placed line.
ArchDataSegment::offset_type offset_type
Represents offset into ArchData.
T read(index_type idx=0) const
Reads a value from this DataView at the specific index.
void writeTruncatedUnsafe(T val, uint32_t idx=0)
Same behavior as writeTruncated bout without checking access bounds.
offset_type getOffset() const
ArchData * getArchData() const
ArchDataSegment::ident_type ident_type
DataView identifiers (distinguishes views in the same ArchData)
T readUnsafe(index_type idx=0) const
Same behavior as read but without checking access bounds.
std::string getByteString() const
Dump data in this DataView as hex bytes in address order with a space between each pair.
void writeTruncated(T val, uint32_t idx=0)
Writes value from this DataView using a type T which might be larger than the size of the DataView.
virtual void place_(offset_type offset) override
Places this DataView within its ArchData.
offset_type getSize() const
DataView(ArchData *data, ident_type id, offset_type size, ident_type subset_of=INVALID_ID, offset_type subset_offset=0, const uint8_t *initial_buf_le=nullptr)
Construct a DataView.
virtual void writeInitial_() override
Writes the initial value of this DataView into memory. This is guaranteed to be called after placemen...
static const std::string DATAVIEW_UNPLACED_STR
String to show instead of a value when representing an unplaced dataview.
void write(T val, index_type idx=0)
Writes a value to this DataView at the specific index.
void writeUnsafe(T val, index_type idx=0)
Same behavior as write but without checking access bounds.
T readPadded(index_type idx=0) const
Reads a value from this DataView using a type T which might be larger than the dataview.
T readPaddedUnsafe(index_type idx=0) const
Same behavior as readPadded but without checking access bounds.
DataView & operator=(const DataView &rhp)
Reads data from another dataview and writes that value to this DataView.
Used to construct and throw a standard C++ exception. Inherits from std::exception.
Macros for handling exponential backoff.
std::string demangle(const std::string &name) noexcept
Demangles a C++ symbol.
bool isPowerOf2(uint64_t x)
Determines if input is 0 or a power of 2.