The Sparta Modeling Framework
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
MemoryObject.hpp
Go to the documentation of this file.
1
7#pragma once
8
11#include "sparta/memory/AddressTypes.hpp"
13#include "sparta/memory/DMIBlockingMemoryIF.hpp"
14#include "sparta/functional/ArchData.hpp"
15#include "sparta/utils/Utils.hpp"
16
17namespace sparta
18{
19 namespace memory
20 {
38 class MemoryObject : public ArchData
39 {
40 public:
41
45
46 MemoryObject() = delete;
47
77 addr_t block_size,
78 addr_t total_size,
79 uint64_t fill=0xcc,
80 uint16_t fill_val_size=1) :
81 ArchData(owner_node, block_size, fill, fill_val_size)
82 {
83 // ArchData ctor validates block_size as power of 2
84 if(block_size == 0){
85 throw SpartaException("Cannot construct a Memoryobject with a block size of 0. Must be a power of 2 and greater than 0");
86 }
87
88 if(total_size == 0){
89 throw SpartaException("Cannot construct a Memoryobject with a total size of 0. Must be a multiple of block_size and greater than 0");
90 }
91
92 if(total_size % block_size != 0){
93 throw SpartaException("Cannot construct a MemoryObject with total_size = ")
94 << total_size << " which is not an even muliple of block_size (" << block_size << ")";
95 }
96
97 // Perform the layout. At this point, no further resizing can be done
98 ArchData::layoutRange(total_size);
99 }
100
101 virtual ~MemoryObject() {}
102
109 virtual std::string stringize(bool pretty=false) const {
110 (void) pretty;
111 std::stringstream ss;
112 ss << "<MemoryObject size:0x" << std::hex << getSize() << " bytes, "
113 << std::dec << getNumBlocks() << " blocks, "
114 << getNumAllocatedLines() << " blocks realized>";
115 return ss.str();
116 }
117
120
124
132 void read(addr_t addr,
133 addr_t size,
134 uint8_t *buf) const {
135 // Address validation performed in tryGetLine
136 const ArchData::Line* l = ArchData::tryGetLine(addr);
137 if(!l){
138 checkCanAccess(addr, size); // Acts as if performing a read/write and throws on failure
140 size,
141 getFill(), // Initialze val with default fill
143 (addr % getBlockSize()) % getFillPatternSize()); // Adjust for misalignment with fill pattern. block size is power of 2.
144 }else{
145 // Size validation performed in read
146 l->read(addr - l->getOffset(), size, buf);
147 }
148 }
149
157 void write(addr_t addr,
158 addr_t size,
159 const uint8_t *buf) {
160 // Address validation performed in getLine
162
163 // Access size validation performed in write
164 l.write(addr - l.getOffset(), size, buf);
165 }
166
169
173
177 addr_t size,
178 uint8_t *buf) const {
179 (void) buf;
180 const ArchData::Line* l = ArchData::tryGetLine(addr);
181 (void) l;
182 checkCanAccess(addr, size); // Acts as if performing a read/write and throws on failure
183 }
184
187
189 addr_t size,
190 uint8_t *buf) const {
191 (void) buf;
192 checkCanAccess(addr, size);
193 }
194
197
201
208
209 addr_t getBlockSize() const {
210 return ArchData::getLineSize();
211 }
212
217 uint64_t getFill() const {
218 return ArchData::getInitial();
219 }
220
224 uint16_t getFillPatternSize() const {
226 }
227
228 }; // class DebugMemoryIF
229
230
250 {
251 MemoryObject& binding_;
252
253 public:
254
261 const std::string& name,
262 const std::string& group,
264 const std::string& desc,
265 TranslationIF* transif,
266 MemoryObject& binding) :
267 BlockingMemoryIFNode(parent, name, group, group_idx, desc,
268 binding.getBlockSize(),
269 DebugMemoryIF::AccessWindow(0,binding.getSize()),
270 transif),
271 binding_(binding)
272 { }
273
285 const std::string& name,
286 const std::string& desc,
287 TranslationIF* transif,
288 MemoryObject& binding) :
290 name,
293 desc,
294 transif,
295 binding)
296 { }
297
298 virtual ~BlockingMemoryObjectIFNode() {}
299
301 MemoryObject* getMemObj() { return &binding_; }
302
324 addr_t size) override
325 {
326 if(doesAccessSpan(addr, size)) {
327 return nullptr;
328 }
329 const auto aligned_addr = addr & block_mask_;
330 if(auto it = dmi_ifs_.find(aligned_addr); it != dmi_ifs_.end()) {
331 return it->second.get();
332 }
333
334 auto & line = binding_.getLine(aligned_addr);
335 dmi_ifs_.insert({aligned_addr,
336 std::unique_ptr<DMIBlockingMemoryIF>
337 (new DMIBlockingMemoryIF(line.getRawDataPtr(0),
338 line.getOffset(),
339 line.getLayoutSize()))});
340 return dmi_ifs_[aligned_addr].get();
341 }
342
349 void invalidateAllDMI() override {
350 for (auto & dmi_if : dmi_ifs_) {
351 dmi_if.second->clearValid();
352 }
353 }
354
355 protected:
357 virtual bool tryPeek_(addr_t addr,
358 addr_t size,
359 uint8_t *buf) const override {
360 binding_.read(addr,size,buf);
361 return true;
362 }
363
365 virtual bool tryPoke_(addr_t addr,
366 addr_t size,
367 const uint8_t *buf) override {
368 binding_.write(addr,size,buf);
369 return true;
370 }
371
372 private:
373
377 virtual bool tryRead_(addr_t addr,
378 addr_t size,
379 uint8_t *buf,
380 const void *in_supplement,
381 void *out_supplement) override {
382 (void) in_supplement;
383 (void) out_supplement;
384 binding_.read(addr, size, buf);
385 return true;
386 }
387
391 virtual bool tryWrite_(addr_t addr,
392 addr_t size,
393 const uint8_t *buf,
394 const void *in_supplement,
395 void *out_supplement) override {
396 (void) in_supplement;
397 (void) out_supplement;
398 binding_.write(addr, size, buf);
399 return true;
400 }
401
402 std::map<addr_t, std::unique_ptr<DMIBlockingMemoryIF>> dmi_ifs_;
403
404 }; // class BlockingMemoryIF
405
406 } // namespace memory
407} // namespace sparta
408
410inline std::ostream& operator<<(std::ostream& out, const sparta::memory::MemoryObject& mo) {
411 out << mo.stringize();
412 return out;
413}
414
416inline std::ostream& operator<<(std::ostream& out, const sparta::memory::MemoryObject* mo) {
417 if(nullptr == mo){
418 out << "null";
419 }else{
420 out << mo->stringize();
421 }
422 return out;
423}
File that contains BlockingMemoryIFNode.
File that contains some exception types related to memory interfaces.
std::ostream & operator<<(std::ostream &out, const sparta::memory::MemoryObject &mo)
MemoryObject stream operator.
Exception class for all of Sparta.
Line object which composes part of an entire ArchData.
Definition ArchData.hpp:158
void write(offset_type offset, const T &t, uint32_t idx=0)
Write to this line, reordering bytes based on byte order if required.
Definition ArchData.hpp:354
T read(offset_type offset, uint32_t idx=0) const
Read from this line, reordering bytes based on byte order if required.
Definition ArchData.hpp:316
offset_type getOffset() const
Offset into the owning ArchData.
Definition ArchData.hpp:279
Contains a set of contiguous line of architectural data which can be referred to by any architected o...
Definition ArchData.hpp:39
uint64_t getInitial() const
Gets the value used to initialize unwritten memory.
line_idx_type getNumAllocatedLines() const
Gets the number of lines with allocated data;.
Definition ArchData.hpp:786
uint32_t getInitialValSize() const
Gets the size of the initial value.
line_idx_type getLineIndex(offset_type offset) const
Gets Index of a line containing the specified offset.
Definition ArchData.hpp:796
void layoutRange(offset_type size)
Lays out the archdata to contain a range of addresses without specifying any segments.
Definition ArchData.hpp:634
static void fillValue(uint8_t *buf, uint32_t size, uint64_t fill, uint16_t fill_val_size, uint16_t fill_pattern_offset=0)
Fill a buffer with a fill pattern.
Definition ArchData.hpp:127
void checkCanAccess(offset_type offset, offset_type bytes) const
Determines if an access of size 'bytes' can be performed at the given offset based only on the size o...
Definition ArchData.hpp:846
const Line * tryGetLine(offset_type offset) const
Gets the line associated with this offset only if it already exists.
Definition ArchData.hpp:697
offset_type getLineSize() const
Gets the size of a line within this ArchData instance.
Definition ArchData.hpp:778
offset_type getSize() const
Gets the current size of the layout for this ArchData.
Line & getLine(offset_type offset)
Gets the line associated with this offset, allocating a new line if necessary.
Definition ArchData.hpp:663
Used to construct and throw a standard C++ exception. Inherits from std::exception.
Node in a composite tree representing a sparta Tree item.
Definition TreeNode.hpp:205
static const group_idx_type GROUP_IDX_NONE
GroupIndex indicating that a node has no group index because it belongs to no group.
Definition TreeNode.hpp:303
static constexpr char GROUP_NAME_NONE[]
Group name indicating that a node belongs to no group.
Definition TreeNode.hpp:314
uint32_t group_idx_type
Index within a group.
Definition TreeNode.hpp:261
Pure-virtual memory interface that builds on the BlockingMemoryIF, acting as a TreeNode in the SPARTA...
BlockingMemoryIFNode implementation with binding to a MemoryObject instantiated separately and specif...
BlockingMemoryObjectIFNode(sparta::TreeNode *parent, const std::string &name, const std::string &group, sparta::TreeNode::group_idx_type group_idx, const std::string &desc, TranslationIF *transif, MemoryObject &binding)
Constructs a BlockingMemoryIFNode bound to a MemoryObject.
void invalidateAllDMI() override
Invalidate all DMI pointers.
virtual bool tryPoke_(addr_t addr, addr_t size, const uint8_t *buf) override
Override of DebugMemoryIF::tryPoke_.
DMIBlockingMemoryIF * getDMI(addr_t addr, addr_t size) override
Return a DMIBlockingMemoryIF for the given address and size.
BlockingMemoryObjectIFNode(sparta::TreeNode *parent, const std::string &name, const std::string &desc, TranslationIF *transif, MemoryObject &binding)
Constructor for single window without TreeNode group information.
virtual bool tryPeek_(addr_t addr, addr_t size, uint8_t *buf) const override
Override of DebugMemoryIF::tryPeek_.
Class that provides a BlockingMemoryIF over a raw pointer.
Memory interface which represents a simple, immediately accessible (blocking) address-space with supp...
bool doesAccessSpan(addr_t addr, addr_t size) const noexcept
Determines if the given address spans block boundaries defined for this interface....
addr_t block_mask_
Mask applied to an address to get only bits representing the block ID.
addr_t getBlockSize() const
Returns the block size of memory represented by this interface. Read and write accesses must not span...
Memory object with sparse storage for large memory representations. Has direct read/write interface w...
void write(addr_t addr, addr_t size, const uint8_t *buf)
Writes memory.
MemoryObject(TreeNode *owner_node, addr_t block_size, addr_t total_size, uint64_t fill=0xcc, uint16_t fill_val_size=1)
Construct a Memory object with sparse storage.
void _lookupAndValidate(addr_t addr, addr_t size, uint8_t *buf) const
virtual std::string stringize(bool pretty=false) const
Render description of this MemoryObject as a string.
uint16_t getFillPatternSize() const
Get the number of bytes in the fill pattern.
void _canAccess(addr_t addr, addr_t size, uint8_t *buf) const
uint64_t getFill() const
Get the fill pattern. Fewer than 8 bytes may be used. See getFillPatternSize.
addr_t getNumBlocks() const
Returns the number of blocks in this memory object.
void read(addr_t addr, addr_t size, uint8_t *buf) const
Reads memory.
Blocking translation interface with 1:1 translation unless subclassed.
uint64_t addr_t
Type for generic address representation in generic interfaces, errors and printouts within SPARTA.
Macros for handling exponential backoff.
Defines an access window within this interface. Accesses through a memory interface are constrained t...