mem: Add support for writing back and flushing caches
This patch adds support for the following optional drain methods in the classical memory system's cache model: memWriteback() - Write back all dirty cache lines to memory using functional accesses. memInvalidate() - Invalidate all cache lines. Dirty cache lines are lost unless a writeback is requested. Since memWriteback() is called when checkpointing systems, this patch adds support for checkpointing systems with caches. The serialization code now checks whether there are any dirty lines in the cache. If there are dirty lines in the cache, the checkpoint is flagged as bad and a warning is printed.
This commit is contained in:
parent
050f24c796
commit
ddd6af414c
11 changed files with 355 additions and 14 deletions
3
src/mem/cache/base.cc
vendored
3
src/mem/cache/base.cc
vendored
|
@ -751,7 +751,8 @@ BaseCache::regStats()
|
|||
unsigned int
|
||||
BaseCache::drain(DrainManager *dm)
|
||||
{
|
||||
int count = memSidePort->drain(dm) + cpuSidePort->drain(dm);
|
||||
int count = memSidePort->drain(dm) + cpuSidePort->drain(dm) +
|
||||
mshrQueue.drain(dm) + writeBuffer.drain(dm);
|
||||
|
||||
// Set status
|
||||
if (count != 0) {
|
||||
|
|
19
src/mem/cache/base.hh
vendored
19
src/mem/cache/base.hh
vendored
|
@ -223,6 +223,25 @@ class BaseCache : public MemObject
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write back dirty blocks in the cache using functional accesses.
|
||||
*/
|
||||
virtual void memWriteback() = 0;
|
||||
/**
|
||||
* Invalidates all blocks in the cache.
|
||||
*
|
||||
* @warn Dirty cache lines will not be written back to
|
||||
* memory. Make sure to call functionalWriteback() first if you
|
||||
* want the to write them to memory.
|
||||
*/
|
||||
virtual void memInvalidate() = 0;
|
||||
/**
|
||||
* Determine if there are any dirty blocks in the cache.
|
||||
*
|
||||
* \return true if at least one block is dirty, false otherwise.
|
||||
*/
|
||||
virtual bool isDirty() const = 0;
|
||||
|
||||
/** Block size of this cache */
|
||||
const unsigned blkSize;
|
||||
|
||||
|
|
71
src/mem/cache/blk.hh
vendored
71
src/mem/cache/blk.hh
vendored
|
@ -1,4 +1,16 @@
|
|||
/*
|
||||
* Copyright (c) 2012 ARM Limited
|
||||
* All rights reserved.
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2003-2005 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
|
@ -26,6 +38,7 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Erik Hallnor
|
||||
* Andreas Sandberg
|
||||
*/
|
||||
|
||||
/** @file
|
||||
|
@ -297,6 +310,64 @@ class CacheBlkPrintWrapper : public Printable
|
|||
const std::string &prefix = "") const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Wrap a method and present it as a cache block visitor.
|
||||
*
|
||||
* For example the forEachBlk method in the tag arrays expects a
|
||||
* callable object/function as their parameter. This class wraps a
|
||||
* method in an object and presents callable object that adheres to
|
||||
* the cache block visitor protocol.
|
||||
*/
|
||||
template <typename T, typename BlkType>
|
||||
class CacheBlkVisitorWrapper
|
||||
{
|
||||
public:
|
||||
typedef bool (T::*visitorPtr)(BlkType &blk);
|
||||
|
||||
CacheBlkVisitorWrapper(T &_obj, visitorPtr _visitor)
|
||||
: obj(_obj), visitor(_visitor) {}
|
||||
|
||||
bool operator()(BlkType &blk) {
|
||||
return (obj.*visitor)(blk);
|
||||
}
|
||||
|
||||
private:
|
||||
T &obj;
|
||||
visitorPtr visitor;
|
||||
};
|
||||
|
||||
/**
|
||||
* Cache block visitor that determines if there are dirty blocks in a
|
||||
* cache.
|
||||
*
|
||||
* Use with the forEachBlk method in the tag array to determine if the
|
||||
* array contains dirty blocks.
|
||||
*/
|
||||
template <typename BlkType>
|
||||
class CacheBlkIsDirtyVisitor
|
||||
{
|
||||
public:
|
||||
CacheBlkIsDirtyVisitor()
|
||||
: _isDirty(false) {}
|
||||
|
||||
bool operator()(BlkType &blk) {
|
||||
if (blk.isDirty()) {
|
||||
_isDirty = true;
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the array contain a dirty line?
|
||||
*
|
||||
* \return true if yes, false otherwise.
|
||||
*/
|
||||
bool isDirty() const { return _isDirty; };
|
||||
|
||||
private:
|
||||
bool _isDirty;
|
||||
};
|
||||
|
||||
#endif //__CACHE_BLK_HH__
|
||||
|
|
22
src/mem/cache/cache.hh
vendored
22
src/mem/cache/cache.hh
vendored
|
@ -76,6 +76,7 @@ class Cache : public BaseCache
|
|||
typedef typename TagStore::BlkList BlkList;
|
||||
|
||||
protected:
|
||||
typedef CacheBlkVisitorWrapper<Cache<TagStore>, BlkType> WrappedBlkVisitor;
|
||||
|
||||
/**
|
||||
* The CPU-side port extends the base cache slave port with access
|
||||
|
@ -256,6 +257,27 @@ class Cache : public BaseCache
|
|||
*/
|
||||
PacketPtr writebackBlk(BlkType *blk);
|
||||
|
||||
|
||||
void memWriteback();
|
||||
void memInvalidate();
|
||||
bool isDirty() const;
|
||||
|
||||
/**
|
||||
* Cache block visitor that writes back dirty cache blocks using
|
||||
* functional writes.
|
||||
*
|
||||
* \return Always returns true.
|
||||
*/
|
||||
bool writebackVisitor(BlkType &blk);
|
||||
/**
|
||||
* Cache block visitor that invalidates all blocks in the cache.
|
||||
*
|
||||
* @warn Dirty cache lines will not be written back to memory.
|
||||
*
|
||||
* \return Always returns true.
|
||||
*/
|
||||
bool invalidateVisitor(BlkType &blk);
|
||||
|
||||
public:
|
||||
/** Instantiates a basic cache object. */
|
||||
Cache(const Params *p, TagStore *tags);
|
||||
|
|
90
src/mem/cache/cache_impl.hh
vendored
90
src/mem/cache/cache_impl.hh
vendored
|
@ -43,6 +43,7 @@
|
|||
* Nathan Binkert
|
||||
* Steve Reinhardt
|
||||
* Ron Dreslinski
|
||||
* Andreas Sandberg
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -1035,6 +1036,69 @@ Cache<TagStore>::writebackBlk(BlkType *blk)
|
|||
return writeback;
|
||||
}
|
||||
|
||||
template<class TagStore>
|
||||
void
|
||||
Cache<TagStore>::memWriteback()
|
||||
{
|
||||
WrappedBlkVisitor visitor(*this, &Cache<TagStore>::writebackVisitor);
|
||||
tags->forEachBlk(visitor);
|
||||
}
|
||||
|
||||
template<class TagStore>
|
||||
void
|
||||
Cache<TagStore>::memInvalidate()
|
||||
{
|
||||
WrappedBlkVisitor visitor(*this, &Cache<TagStore>::invalidateVisitor);
|
||||
tags->forEachBlk(visitor);
|
||||
}
|
||||
|
||||
template<class TagStore>
|
||||
bool
|
||||
Cache<TagStore>::isDirty() const
|
||||
{
|
||||
CacheBlkIsDirtyVisitor<BlkType> visitor;
|
||||
tags->forEachBlk(visitor);
|
||||
|
||||
return visitor.isDirty();
|
||||
}
|
||||
|
||||
template<class TagStore>
|
||||
bool
|
||||
Cache<TagStore>::writebackVisitor(BlkType &blk)
|
||||
{
|
||||
if (blk.isDirty()) {
|
||||
assert(blk.isValid());
|
||||
|
||||
Request request(tags->regenerateBlkAddr(blk.tag, blk.set),
|
||||
blkSize, 0, Request::funcMasterId);
|
||||
|
||||
Packet packet(&request, MemCmd::WriteReq);
|
||||
packet.dataStatic(blk.data);
|
||||
|
||||
memSidePort->sendFunctional(&packet);
|
||||
|
||||
blk.status &= ~BlkDirty;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class TagStore>
|
||||
bool
|
||||
Cache<TagStore>::invalidateVisitor(BlkType &blk)
|
||||
{
|
||||
|
||||
if (blk.isDirty())
|
||||
warn_once("Invalidating dirty cache lines. Expect things to break.\n");
|
||||
|
||||
if (blk.isValid()) {
|
||||
assert(!blk.isDirty());
|
||||
tags->invalidate(dynamic_cast< BlkType *>(&blk));
|
||||
blk.invalidate();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class TagStore>
|
||||
typename Cache<TagStore>::BlkType*
|
||||
|
@ -1565,16 +1629,20 @@ template<class TagStore>
|
|||
void
|
||||
Cache<TagStore>::serialize(std::ostream &os)
|
||||
{
|
||||
warn("*** Creating checkpoints with caches is not supported. ***\n");
|
||||
warn(" Remove any caches before taking checkpoints\n");
|
||||
warn(" This checkpoint will not restore correctly and dirty data in "
|
||||
"the cache will be lost!\n");
|
||||
bool dirty(isDirty());
|
||||
|
||||
// Since we don't write back the data dirty in the caches to the physical
|
||||
// memory if caches exist in the system we won't be able to restore
|
||||
// from the checkpoint as any data dirty in the caches will be lost.
|
||||
if (dirty) {
|
||||
warn("*** The cache still contains dirty data. ***\n");
|
||||
warn(" Make sure to drain the system using the correct flags.\n");
|
||||
warn(" This checkpoint will not restore correctly and dirty data in "
|
||||
"the cache will be lost!\n");
|
||||
}
|
||||
|
||||
bool bad_checkpoint = true;
|
||||
// Since we don't checkpoint the data in the cache, any dirty data
|
||||
// will be lost when restoring from a checkpoint of a system that
|
||||
// wasn't drained properly. Flag the checkpoint as invalid if the
|
||||
// cache contains dirty data.
|
||||
bool bad_checkpoint(dirty);
|
||||
SERIALIZE_SCALAR(bad_checkpoint);
|
||||
}
|
||||
|
||||
|
@ -1585,9 +1653,9 @@ Cache<TagStore>::unserialize(Checkpoint *cp, const std::string §ion)
|
|||
bool bad_checkpoint;
|
||||
UNSERIALIZE_SCALAR(bad_checkpoint);
|
||||
if (bad_checkpoint) {
|
||||
fatal("Restoring from checkpoints with caches is not supported in the "
|
||||
"classic memory system. Please remove any caches before taking "
|
||||
"checkpoints.\n");
|
||||
fatal("Restoring from checkpoints with dirty caches is not supported "
|
||||
"in the classic memory system. Please remove any caches or "
|
||||
" drain them properly before taking checkpoints.\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
35
src/mem/cache/mshr_queue.cc
vendored
35
src/mem/cache/mshr_queue.cc
vendored
|
@ -1,4 +1,16 @@
|
|||
/*
|
||||
* Copyright (c) 2012 ARM Limited
|
||||
* All rights reserved.
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2003-2005 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
|
@ -26,6 +38,7 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Erik Hallnor
|
||||
* Andreas Sandberg
|
||||
*/
|
||||
|
||||
/** @file
|
||||
|
@ -40,7 +53,7 @@ MSHRQueue::MSHRQueue(const std::string &_label,
|
|||
int num_entries, int reserve, int _index)
|
||||
: label(_label),
|
||||
numEntries(num_entries + reserve - 1), numReserve(reserve),
|
||||
index(_index)
|
||||
drainManager(NULL), index(_index)
|
||||
{
|
||||
allocated = 0;
|
||||
inServiceEntries = 0;
|
||||
|
@ -183,6 +196,13 @@ MSHRQueue::deallocateOne(MSHR *mshr)
|
|||
readyList.erase(mshr->readyIter);
|
||||
}
|
||||
mshr->deallocate();
|
||||
if (drainManager && allocated == 0) {
|
||||
// Notify the drain manager that we have completed draining if
|
||||
// there are no other outstanding requests in this MSHR queue.
|
||||
drainManager->signalDrainDone();
|
||||
drainManager = NULL;
|
||||
setDrainState(Drainable::Drained);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -245,3 +265,16 @@ MSHRQueue::squash(int threadNum)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int
|
||||
MSHRQueue::drain(DrainManager *dm)
|
||||
{
|
||||
if (allocated == 0) {
|
||||
setDrainState(Drainable::Drained);
|
||||
return 0;
|
||||
} else {
|
||||
drainManager = dm;
|
||||
setDrainState(Drainable::Draining);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
21
src/mem/cache/mshr_queue.hh
vendored
21
src/mem/cache/mshr_queue.hh
vendored
|
@ -1,4 +1,16 @@
|
|||
/*
|
||||
* Copyright (c) 2012 ARM Limited
|
||||
* All rights reserved.
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2003-2005 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
|
@ -26,6 +38,7 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Erik Hallnor
|
||||
* Andreas Sandberg
|
||||
*/
|
||||
|
||||
/** @file
|
||||
|
@ -39,11 +52,12 @@
|
|||
|
||||
#include "mem/cache/mshr.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "sim/drain.hh"
|
||||
|
||||
/**
|
||||
* A Class for maintaining a list of pending and allocated memory requests.
|
||||
*/
|
||||
class MSHRQueue
|
||||
class MSHRQueue : public Drainable
|
||||
{
|
||||
private:
|
||||
/** Local label (for functional print requests) */
|
||||
|
@ -72,6 +86,9 @@ class MSHRQueue
|
|||
*/
|
||||
const int numReserve;
|
||||
|
||||
/** Drain manager to inform of a completed drain */
|
||||
DrainManager *drainManager;
|
||||
|
||||
MSHR::Iterator addToReadyList(MSHR *mshr);
|
||||
|
||||
|
||||
|
@ -209,6 +226,8 @@ class MSHRQueue
|
|||
{
|
||||
return readyList.empty() ? MaxTick : readyList.front()->readyTime;
|
||||
}
|
||||
|
||||
unsigned int drain(DrainManager *dm);
|
||||
};
|
||||
|
||||
#endif //__MEM__CACHE__MISS__MSHR_QUEUE_HH__
|
||||
|
|
12
src/mem/cache/tags/base.hh
vendored
12
src/mem/cache/tags/base.hh
vendored
|
@ -1,4 +1,16 @@
|
|||
/*
|
||||
* Copyright (c) 2012 ARM Limited
|
||||
* All rights reserved.
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2003-2005 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
|
|
32
src/mem/cache/tags/fa_lru.hh
vendored
32
src/mem/cache/tags/fa_lru.hh
vendored
|
@ -1,4 +1,16 @@
|
|||
/*
|
||||
* Copyright (c) 2012 ARM Limited
|
||||
* All rights reserved.
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2003-2005 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
|
@ -287,6 +299,26 @@ public:
|
|||
*Needed to clear all lock tracking at once
|
||||
*/
|
||||
virtual void clearLocks();
|
||||
|
||||
/**
|
||||
* Visit each block in the tag store and apply a visitor to the
|
||||
* block.
|
||||
*
|
||||
* The visitor should be a function (or object that behaves like a
|
||||
* function) that takes a cache block reference as its parameter
|
||||
* and returns a bool. A visitor can request the traversal to be
|
||||
* stopped by returning false, returning true causes it to be
|
||||
* called for the next block in the tag store.
|
||||
*
|
||||
* \param visitor Visitor to call on each block.
|
||||
*/
|
||||
template <typename V>
|
||||
void forEachBlk(V &visitor) {
|
||||
for (int i = 0; i < numBlocks; i++) {
|
||||
if (!visitor(blks[i]))
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __MEM_CACHE_TAGS_FA_LRU_HH__
|
||||
|
|
32
src/mem/cache/tags/iic.hh
vendored
32
src/mem/cache/tags/iic.hh
vendored
|
@ -1,4 +1,16 @@
|
|||
/*
|
||||
* Copyright (c) 2012 ARM Limited
|
||||
* All rights reserved.
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2002-2005 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
|
@ -450,6 +462,26 @@ class IIC : public BaseTags
|
|||
*/
|
||||
virtual void cleanupRefs();
|
||||
|
||||
/**
|
||||
* Visit each block in the tag store and apply a visitor to the
|
||||
* block.
|
||||
*
|
||||
* The visitor should be a function (or object that behaves like a
|
||||
* function) that takes a cache block reference as its parameter
|
||||
* and returns a bool. A visitor can request the traversal to be
|
||||
* stopped by returning false, returning true causes it to be
|
||||
* called for the next block in the tag store.
|
||||
*
|
||||
* \param visitor Visitor to call on each block.
|
||||
*/
|
||||
template <typename V>
|
||||
void forEachBlk(V &visitor) {
|
||||
for (unsigned i = 0; i < numTags; ++i) {
|
||||
if (!visitor(tagStore[i]))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Return the hash of the address.
|
||||
|
|
32
src/mem/cache/tags/lru.hh
vendored
32
src/mem/cache/tags/lru.hh
vendored
|
@ -1,4 +1,16 @@
|
|||
/*
|
||||
* Copyright (c) 2012 ARM Limited
|
||||
* All rights reserved.
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2003-2005 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
|
@ -235,6 +247,26 @@ public:
|
|||
* Called at end of simulation to complete average block reference stats.
|
||||
*/
|
||||
virtual void cleanupRefs();
|
||||
|
||||
/**
|
||||
* Visit each block in the tag store and apply a visitor to the
|
||||
* block.
|
||||
*
|
||||
* The visitor should be a function (or object that behaves like a
|
||||
* function) that takes a cache block reference as its parameter
|
||||
* and returns a bool. A visitor can request the traversal to be
|
||||
* stopped by returning false, returning true causes it to be
|
||||
* called for the next block in the tag store.
|
||||
*
|
||||
* \param visitor Visitor to call on each block.
|
||||
*/
|
||||
template <typename V>
|
||||
void forEachBlk(V &visitor) {
|
||||
for (unsigned i = 0; i < numSets * assoc; ++i) {
|
||||
if (!visitor(blks[i]))
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __MEM_CACHE_TAGS_LRU_HH__
|
||||
|
|
Loading…
Reference in a new issue