65 const void * in_supplement,
66 void * out_supplement) :
74 (void) out_supplement;
77 ::memcpy(stored_value_.data(), data, size);
102 const uint64_t write_id_;
105 std::vector<uint8_t> stored_value_;
106 std::vector<uint8_t> prev_value_;
109 inline std::ostream &
operator<<(std::ostream & os,
const StoreData & mstore)
111 os << std::hex <<
"wid:" << mstore.getWriteID() <<
" pa:" << mstore.getPAddr()
112 << std::dec <<
" size:" << mstore.getSize();
163 template<
class MemoryWriteType = StoreData>
179 uint32_t outstanding_writes_watermark,
195 return outstanding_writes_;
224 void commitWrite(
const MemoryWriteType & write_to_commit);
243 void dropWrite(
const MemoryWriteType & write_to_drop);
251 return outstanding_writes_.rbegin()->second;
257 const uint64_t write_id_;
258 const uint32_t outstanding_writes_watermark_;
259 std::map<uint64_t, MemoryWriteType> outstanding_writes_;
260 uint64_t write_uid_ = 0;
265 const void *in_supplement,
void *out_supplement)
override final;
266 bool tryWrite_(
addr_t paddr,
addr_t size,
const uint8_t *buf,
267 const void *in_supplement,
void *out_supplement)
override final;
269 uint8_t *buf)
const override final;
270 bool tryPoke_(
addr_t paddr,
addr_t size,
const uint8_t *buf)
override final;
279 template<
class MemoryWriteType>
282 uint32_t outstanding_writes_watermark,
289 outstanding_writes_watermark_(outstanding_writes_watermark),
291 write_uid_(uint64_t(write_id_) << ((sizeof(write_uid_) - 1) * 8)),
292 downstream_memory_(downstream_memory),
293 cached_memory_(nullptr, block_size, total_size, 0)
300 template<
class MemoryWriteType>
302 const void *in_supplement,
void *out_supplement)
304 if(cached_memory_.tryGetLine(paddr) ==
nullptr) {
305 downstream_memory_->peek(paddr, size, buf);
308 cached_memory_.read(paddr, size, buf);
315 template<
class MemoryWriteType>
316 bool CachedMemory<MemoryWriteType>::tryWrite_ (
addr_t paddr,
addr_t size,
const uint8_t *buf,
317 const void *in_supplement,
void *out_supplement)
319 sparta_assert(outstanding_writes_.size() != outstanding_writes_watermark_,
320 "Watermark of outstanding writes reached. "
321 "Writes need to be committed or dropped via the CoSim API");
323 if(cached_memory_.tryGetLine(paddr) ==
nullptr) {
326 const auto aligned_paddr = paddr & block_mask_;
327 uint8_t * cached_mem_block_ptr = cached_memory_.getLine(aligned_paddr).getRawDataPtr(0);
328 downstream_memory_->peek(aligned_paddr, block_size_, cached_mem_block_ptr);
334 MemoryWriteType outstanding_write(write_uid_, paddr, size, buf, in_supplement, out_supplement);
335 auto * prev_data_store = outstanding_write.getPrevDataPtr();
338 cached_memory_.read(paddr, size, prev_data_store);
341 cached_memory_.write(paddr, size, buf);
344 outstanding_writes_.emplace(std::make_pair(write_uid_, outstanding_write));
351 template<
class MemoryWriteType>
352 bool CachedMemory<MemoryWriteType>::tryPeek_(
addr_t paddr,
addr_t size, uint8_t *buf)
const
355 if(cached_memory_.tryGetLine(paddr) ==
nullptr) {
356 downstream_memory_->peek(paddr, size, buf);
359 cached_memory_.read(paddr, size, buf);
365 template<
class MemoryWriteType>
366 bool CachedMemory<MemoryWriteType>::tryPoke_(
addr_t paddr,
addr_t size,
const uint8_t *buf)
368 if(cached_memory_.tryGetLine(paddr) ==
nullptr) {
370 const auto aligned_paddr = paddr & block_mask_;
371 uint8_t * cached_mem_block_ptr = cached_memory_.getLine(aligned_paddr).getRawDataPtr(0);
372 downstream_memory_->poke(aligned_paddr, block_size_, cached_mem_block_ptr);
374 cached_memory_.write(paddr, size, buf);
375 downstream_memory_->poke(paddr, size, buf);
379 template<
class MemoryWriteType>
380 std::vector<MemoryWriteType>
383 std::vector<MemoryWriteType> matching_stores;
384 for(
const auto & [wuid, maw] : outstanding_writes_) {
385 if((paddr >= maw.getPAddr()) && (paddr < (maw.getPAddr() + maw.getSize()))) {
387 matching_stores.emplace_back(maw);
390 return matching_stores;
393 template<
class MemoryWriteType>
397 "there are no outstanding writes for commit");
399 const auto & mem_write_access = outstanding_writes_.begin()->second;
403 std::stringstream msg;
404 msg << __FUNCTION__ <<
": error: attempting to commit write out of order: " << write_to_commit
405 <<
" expected to commit write: " << mem_write_access;
406 msg <<
"\nOutstanding writes for write ID " << write_id_ <<
" (oldest to newest):\n";
407 for(
const auto & outstanding_write : outstanding_writes_) {
408 msg <<
"\t" << outstanding_write <<
"\n";
414 downstream_memory_->tryWrite(mem_write_access.getPAddr(),
415 mem_write_access.getSize(),
416 mem_write_access.getStoreDataPtr(), (
void*)
this);
417 outstanding_writes_.erase(outstanding_writes_.begin());
420 template<
class MemoryWriteType>
424 "There are no outstanding writes for dropping");
426 if(
SPARTA_EXPECT_FALSE(outstanding_writes_.find(write_to_drop.getWriteID()) == outstanding_writes_.end()))
428 std::stringstream msg;
429 msg << __FUNCTION__ <<
": error: attempting to drop a write that is not known by this CachedMemory: "
431 msg <<
"\nOutstanding writes for write ID " << write_id_ <<
" (oldest to newest):\n";
432 for(
const auto & outstanding_writes : outstanding_writes_) {
433 msg <<
"\t" << outstanding_writes <<
"\n";
440 auto currently_flushing_write = outstanding_writes_.rbegin();
441 while(currently_flushing_write != outstanding_writes_.rend())
443 const uint64_t current_flushed_wuid = currently_flushing_write->first;
444 const auto & current_flushed_maw = currently_flushing_write->second;
445 cached_memory_.write(current_flushed_maw.getPAddr(),
446 current_flushed_maw.getSize(),
447 current_flushed_maw.getPrevDataPtr());
450 outstanding_writes_.erase((++currently_flushing_write).base());
452 if(current_flushed_wuid == write_to_drop.getWriteID()) {
456 currently_flushing_write = outstanding_writes_.rbegin();
460 template<
class MemoryWriteType>
463 if(getNumOutstandingWrites() > 0) {
468 for(
addr_t byte = 0;
byte < size; ++byte)
470 const auto paddr_offset = paddr + byte;
471 bool collision =
false;
472 for(
auto & [wuid, maw] : outstanding_writes_)
474 const auto maw_start_paddr = maw.getPAddr();
475 const auto maw_size = maw.getSize();
476 if((paddr_offset >= maw_start_paddr) && (paddr_offset < (maw_start_paddr + maw_size)))
481 const uint32_t maw_byte = paddr_offset - maw_start_paddr;
482 maw.getPrevDataPtr()[maw_byte] = *(buf + byte);
488 cached_memory_.write(paddr_offset, 1, buf +
byte);
493 cached_memory_.write(paddr, size, buf);
File that contains BlockingMemoryIF.
File that contains MemoryObject.
#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.
Exception class for all of Sparta.
Used to construct and throw a standard C++ exception. Inherits from std::exception.
Pure-virtual memory interface which represents a simple, immediately accessible (blocking) address-sp...
Memory that can be used as a cache for core models.
const MemoryWriteType & getLastOutstandingWrite() const
Return the latest outstanding store access.
std::vector< MemoryWriteType > getOutstandingWritesForAddr(addr_t paddr) const
Given address, find outstanding writes that are not merged/committed.
uint64_t getWriteID() const
Get the write ID for this cache.
CachedMemory(const std::string &name, uint64_t write_id, uint32_t outstanding_writes_watermark, addr_t block_size, addr_t total_size, sparta::memory::BlockingMemoryIF *downstream_memory)
Create a CachedMemory object.
void dropWrite(const MemoryWriteType &write_to_drop)
Drop the outstanding write that matches the given MemoryWriteType.
void commitWrite(const MemoryWriteType &write_to_commit)
Commit the write that matches the given MemoryWriteType.
uint32_t getNumOutstandingWrites() const
Return the number of uncomitted writes.
void mergeWrite(addr_t paddr, addr_t size, const uint8_t *buf)
Merge an incoming write from system memory.
const std::map< uint64_t, MemoryWriteType > & getOutstandingWrites() const
Get all outstanding writes.
Memory interface which represents a simple, immediately accessible (blocking) address-space with supp...
Memory object with sparse storage for large memory representations. Has direct read/write interface w...
size_t getSize() const
Get the size of the write data (in bytes)
const uint8_t * getStoreDataPtr() const
Const methods of above methods.
uint8_t * getPrevDataPtr()
Get the previous data at the address (for restore)
const uint8_t * getPrevDataPtr() const
Const methods of above methods.
uint64_t getWriteID() const
Get the write ID, unique to each write performed.
addr_t getPAddr() const
Get the physical address this write corresponds to.
uint8_t * getStoreDataPtr()
Get the stored data.
StoreData(uint64_t write_id, addr_t paddr, size_t size, const uint8_t *data, const void *in_supplement, void *out_supplement)
Construct a StoreData object.
Namespace containing memory interfaces, types, and storage objects.
uint64_t addr_t
Type for generic address representation in generic interfaces, errors and printouts within SPARTA.
Macros for handling exponential backoff.
std::ostream & operator<<(std::ostream &o, const SimulationInfo &info)
ostream insertion operator for SimulationInfo
Defines an access window within this interface. Accesses through a memory interface are constrained t...