The Sparta Modeling Framework
Loading...
Searching...
No Matches
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
69 addr_t block_size,
70 addr_t total_size,
71 uint64_t fill=0xcc,
72 uint16_t fill_val_size=1) :
73 ArchData(owner_node, block_size, fill, fill_val_size)
74 {
75 // ArchData ctor validates block_size as power of 2
76 if(block_size == 0){
77 throw SpartaException("Cannot construct a Memoryobject with a block size of 0. Must be a power of 2 and greater than 0");
78 }
79
80 if(total_size == 0){
81 throw SpartaException("Cannot construct a Memoryobject with a total size of 0. Must be a multiple of block_size and greater than 0");
82 }
83
84 if(total_size % block_size != 0){
85 throw SpartaException("Cannot construct a MemoryObject with total_size = ")
86 << total_size << " which is not an even muliple of block_size (" << block_size << ")";
87 }
88
89 // Perform the layout. At this point, no further resizing can be done
90 ArchData::layoutRange(total_size);
91 }
92
93 virtual ~MemoryObject() {}
94
101 virtual std::string stringize(bool pretty=false) const {
102 (void) pretty;
103 std::stringstream ss;
104 ss << "<MemoryObject size:0x" << std::hex << getSize() << " bytes, "
105 << std::dec << getNumBlocks() << " blocks, "
106 << getNumAllocatedLines() << " blocks realized>";
107 return ss.str();
108 }
109
112
116
124 void read(addr_t addr,
125 addr_t size,
126 uint8_t *buf) const {
127 // Address validation performed in tryGetLine
128 const ArchData::Line* l = ArchData::tryGetLine(addr);
129 if(!l){
130 checkCanAccess(addr, size); // Acts as if performing a read/write and throws on failure
132 size,
133 getFill(), // Initialze val with default fill
135 (addr % getBlockSize()) % getFillPatternSize()); // Adjust for misalignment with fill pattern. block size is power of 2.
136 }else{
137 // Size validation performed in read
138 l->read(addr - l->getOffset(), size, buf);
139 }
140 }
141
149 void write(addr_t addr,
150 addr_t size,
151 const uint8_t *buf) {
152 // Address validation performed in getLine
154
155 // Access size validation performed in write
156 l.write(addr - l.getOffset(), size, buf);
157 }
158
161
165
169 addr_t size,
170 uint8_t *buf) const {
171 (void) buf;
172 const ArchData::Line* l = ArchData::tryGetLine(addr);
173 (void) l;
174 checkCanAccess(addr, size); // Acts as if performing a read/write and throws on failure
175 }
176
179
181 addr_t size,
182 uint8_t *buf) const {
183 (void) buf;
184 checkCanAccess(addr, size);
185 }
186
189
193
200
201 addr_t getBlockSize() const {
202 return ArchData::getLineSize();
203 }
204
209 uint64_t getFill() const {
210 return ArchData::getInitial();
211 }
212
216 uint16_t getFillPatternSize() const {
218 }
219
220 }; // class DebugMemoryIF
221
222
242 {
243 MemoryObject& binding_;
244
245 public:
246
253 const std::string& name,
254 const std::string& group,
256 const std::string& desc,
257 TranslationIF* transif,
258 MemoryObject& binding) :
259 BlockingMemoryIFNode(parent, name, group, group_idx, desc,
260 binding.getBlockSize(),
261 DebugMemoryIF::AccessWindow(0,binding.getSize()),
262 transif),
263 binding_(binding)
264 { }
265
277 const std::string& name,
278 const std::string& desc,
279 TranslationIF* transif,
280 MemoryObject& binding) :
282 name,
285 desc,
286 transif,
287 binding)
288 { }
289
290 virtual ~BlockingMemoryObjectIFNode() {}
291
293 MemoryObject* getMemObj() { return &binding_; }
294
316 addr_t size) override
317 {
318 if(doesAccessSpan(addr, size)) {
319 return nullptr;
320 }
321 const auto aligned_addr = addr & block_mask_;
322 if(auto it = dmi_ifs_.find(aligned_addr); it != dmi_ifs_.end()) {
323 return it->second.get();
324 }
325
326 auto & line = binding_.getLine(aligned_addr);
327 dmi_ifs_.insert({aligned_addr,
328 std::unique_ptr<DMIBlockingMemoryIF>
329 (new DMIBlockingMemoryIF(line.getRawDataPtr(0),
330 line.getOffset(),
331 line.getLayoutSize()))});
332 return dmi_ifs_[aligned_addr].get();
333 }
334
341 void invalidateAllDMI() override {
342 for (auto & dmi_if : dmi_ifs_) {
343 dmi_if.second->clearValid();
344 }
345 }
346
347 protected:
349 virtual bool tryPeek_(addr_t addr,
350 addr_t size,
351 uint8_t *buf) const override {
352 binding_.read(addr,size,buf);
353 return true;
354 }
355
357 virtual bool tryPoke_(addr_t addr,
358 addr_t size,
359 const uint8_t *buf) override {
360 binding_.write(addr,size,buf);
361 return true;
362 }
363
364 private:
365
369 virtual bool tryRead_(addr_t addr,
370 addr_t size,
371 uint8_t *buf,
372 const void *in_supplement,
373 void *out_supplement) override {
374 (void) in_supplement;
375 (void) out_supplement;
376 binding_.read(addr, size, buf);
377 return true;
378 }
379
383 virtual bool tryWrite_(addr_t addr,
384 addr_t size,
385 const uint8_t *buf,
386 const void *in_supplement,
387 void *out_supplement) override {
388 (void) in_supplement;
389 (void) out_supplement;
390 binding_.write(addr, size, buf);
391 return true;
392 }
393
394 std::map<addr_t, std::unique_ptr<DMIBlockingMemoryIF>> dmi_ifs_;
395
396 }; // class BlockingMemoryIF
397
398 } // namespace memory
399} // namespace sparta
400
402inline std::ostream& operator<<(std::ostream& out, const sparta::memory::MemoryObject& mo) {
403 out << mo.stringize();
404 return out;
405}
406
408inline std::ostream& operator<<(std::ostream& out, const sparta::memory::MemoryObject* mo) {
409 if(nullptr == mo){
410 out << "null";
411 }else{
412 out << mo->stringize();
413 }
414 return out;
415}
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...