summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mem/cache/base.cc3
-rw-r--r--src/mem/cache/base.hh19
-rw-r--r--src/mem/cache/blk.hh71
-rw-r--r--src/mem/cache/cache.hh22
-rw-r--r--src/mem/cache/cache_impl.hh90
-rw-r--r--src/mem/cache/mshr_queue.cc35
-rw-r--r--src/mem/cache/mshr_queue.hh21
-rw-r--r--src/mem/cache/tags/base.hh12
-rw-r--r--src/mem/cache/tags/fa_lru.hh32
-rw-r--r--src/mem/cache/tags/iic.hh32
-rw-r--r--src/mem/cache/tags/lru.hh32
11 files changed, 355 insertions, 14 deletions
diff --git a/src/mem/cache/base.cc b/src/mem/cache/base.cc
index ad1c751bc..262573663 100644
--- a/src/mem/cache/base.cc
+++ b/src/mem/cache/base.cc
@@ -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) {
diff --git a/src/mem/cache/base.hh b/src/mem/cache/base.hh
index ab13be771..e8adacfa1 100644
--- a/src/mem/cache/base.hh
+++ b/src/mem/cache/base.hh
@@ -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;
diff --git a/src/mem/cache/blk.hh b/src/mem/cache/blk.hh
index 73f569e6a..3557bc489 100644
--- a/src/mem/cache/blk.hh
+++ b/src/mem/cache/blk.hh
@@ -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__
diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh
index be81736aa..5df725683 100644
--- a/src/mem/cache/cache.hh
+++ b/src/mem/cache/cache.hh
@@ -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);
diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh
index 44acaef5b..a7c9a4a55 100644
--- a/src/mem/cache/cache_impl.hh
+++ b/src/mem/cache/cache_impl.hh
@@ -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 &section)
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");
}
}
diff --git a/src/mem/cache/mshr_queue.cc b/src/mem/cache/mshr_queue.cc
index b412891d9..af13d12d3 100644
--- a/src/mem/cache/mshr_queue.cc
+++ b/src/mem/cache/mshr_queue.cc
@@ -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;
+ }
+}
diff --git a/src/mem/cache/mshr_queue.hh b/src/mem/cache/mshr_queue.hh
index 89dd87fb4..44e1c5bd3 100644
--- a/src/mem/cache/mshr_queue.hh
+++ b/src/mem/cache/mshr_queue.hh
@@ -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__
diff --git a/src/mem/cache/tags/base.hh b/src/mem/cache/tags/base.hh
index 576b512e5..3539f2bfd 100644
--- a/src/mem/cache/tags/base.hh
+++ b/src/mem/cache/tags/base.hh
@@ -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.
*
diff --git a/src/mem/cache/tags/fa_lru.hh b/src/mem/cache/tags/fa_lru.hh
index 19e21688c..7604d8d43 100644
--- a/src/mem/cache/tags/fa_lru.hh
+++ b/src/mem/cache/tags/fa_lru.hh
@@ -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__
diff --git a/src/mem/cache/tags/iic.hh b/src/mem/cache/tags/iic.hh
index 91e947704..a41af8612 100644
--- a/src/mem/cache/tags/iic.hh
+++ b/src/mem/cache/tags/iic.hh
@@ -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.
diff --git a/src/mem/cache/tags/lru.hh b/src/mem/cache/tags/lru.hh
index 427dba667..431e3eb1e 100644
--- a/src/mem/cache/tags/lru.hh
+++ b/src/mem/cache/tags/lru.hh
@@ -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__