10#include "sparta/functional/ArchDataSegment.hpp"
11#include "sparta/functional/ArchData.hpp"
77 const uint8_t* initial_buf_le=
nullptr) :
79 adata_(data), offset_(0),
81 initial_buf_le_(initial_buf_le)
84 static_assert(
sizeof(uint64_t) >
sizeof(
index_type),
85 "Must have a type larger than index_type in order to "
86 "perform bounds checking on index values which must "
87 "support the entire range from 0 to the maximum value");
94 if(subset_of ==
INVALID_ID && subset_offset != 0){
95 throw SpartaException(
"Cannot construct DataView with a valid identifier and nonzero offset: 0x")
96 << std::hex << subset_offset <<
". Change subset_offset to 0 or set subset_of to INVALID_ID";
149 template <
typename T, ByteOrder BO=LE>
152 "read index " << idx <<
" and type " <<
demangle(
typeid(T).name())
153 <<
" (size " <<
sizeof(T) <<
") is invalid for this DataView of size " <<
getSize());
162 template <
typename T, ByteOrder BO=LE>
164 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.");
165 return line_->
read<T, BO>(offset_, idx);
179 template <
typename T, ByteOrder BO=LE>
182 "readPadded index " << idx <<
" and type " <<
demangle(
typeid(T).name())
183 <<
" (size " <<
sizeof(T) <<
") is invalid for this DataView of size " <<
getSize());
193 template <
typename T, ByteOrder BO=LE>
195 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.");
201 result = line_->
read<uint64_t, BO>(offset_, idx);
202 }
else if(max_bytes == 4){
203 result = line_->
read<uint32_t, BO>(offset_, idx);
204 }
else if(max_bytes == 2){
205 result = line_->
read<uint16_t, BO>(offset_, idx);
206 }
else if(max_bytes == 1){
207 result = line_->
read<uint8_t, BO>(offset_, idx);
244 template <
typename T, ByteOrder BO=LE>
247 "write index " << idx <<
" and type " <<
demangle(
typeid(T).name())
248 <<
" (size " <<
sizeof(T) <<
") is invalid for this DataView of size " <<
getSize());
259 template <
typename T, ByteOrder BO=LE>
261 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.");
263 line_->
write<T, BO>(offset_, val, idx);
282 template <
typename T, ByteOrder BO=LE>
285 "writeTruncated index " << idx <<
" and type " <<
demangle(
typeid(T).name())
286 <<
" (size " <<
sizeof(T) <<
") is invalid for this DataView of size " <<
getSize());
299 template <
typename T, ByteOrder BO=LE>
301 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.");
306 line_->
write<uint64_t, BO>(offset_, (uint64_t)val, idx);
307 }
else if(max_bytes == 4){
308 line_->
write<uint32_t, BO>(offset_, (uint32_t)val, idx);
309 }
else if(max_bytes == 2){
310 line_->
write<uint16_t, BO>(offset_, (uint16_t)val, idx);
311 }
else if(max_bytes == 1){
312 line_->
write<uint8_t, BO>(offset_, (uint8_t)val, idx);
329 throw SpartaException(
"Cannot copy data between DataViews using operator= because the sizes differ");
331 if(rhp.line_ ==
nullptr){
332 throw SpartaException(
"Cannot copy data between DataViews using operator= because the right-hand operand is not laid out");
334 if(line_ ==
nullptr){
335 throw SpartaException(
"Cannot copy data between DataViews using operator= because the left-hand operand is not laid out");
338 const uint8_t*
const src = rhp.line_->
getDataPointer(rhp.offset_);
361 o << std::setw(2) << std::hex << (uint16_t)read<uint8_t, LE>(i) <<
' ';
374 template <ByteOrder BO=LE>
378 std::stringstream ss;
379 ss <<
"0x" << std::hex << std::setw(
getSize()*2) << std::setfill(
'0');
382 ss << (uint32_t)read<uint8_t, BO>();
385 ss << (uint32_t)read<uint16_t, BO>();
388 ss << read<uint32_t, BO>();
391 assembleIndexedReadsToValue_<BO>(ss);
410 line_ = &adata_->
getLine(offset);
421#if __BYTE_ORDER == __LITTLE_ENDIAN
442 template <ByteOrder BO=LE>
443 void assembleIndexedReadsToValue_(std::stringstream& ss)
const {
444 ss <<
"<unknown byte-order: " << BO <<
">";
447 ArchData*
const adata_;
449 ArchData::Line* line_;
455 const uint8_t*
const initial_buf_le_;
459 inline void DataView::assembleIndexedReadsToValue_<LE>(std::stringstream& ss)
const {
461 ss << std::setw(16) << read<uint64_t, LE>(i-1);
466 inline void DataView::assembleIndexedReadsToValue_<BE>(std::stringstream& ss)
const {
468 ss << std::setw(16) << read<uint64_t, BE>(i);
475#define SPARTA_DATAVIEW_BODY \
476 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...
ArchData::Line * getLine() const
Get already-placed line.
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
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.
ArchDataSegment::ident_type ident_type
DataView identifiers (distinguishes views in the same ArchData)
void writeUnsafe(T val, index_type idx=0)
Same behavior as write but without checking access bounds.
ArchDataSegment::offset_type offset_type
Represents offset into ArchData.
T readPadded(index_type idx=0) const
Reads a value from this DataView using a type T which might be larger than the dataview.
uint32_t index_type
Type used for specifying index into this DataView during a read or write.
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.