diff options
-rw-r--r-- | src/mem/cache/base.cc | 3 | ||||
-rw-r--r-- | src/mem/cache/base.hh | 19 | ||||
-rw-r--r-- | src/mem/cache/blk.hh | 71 | ||||
-rw-r--r-- | src/mem/cache/cache.hh | 22 | ||||
-rw-r--r-- | src/mem/cache/cache_impl.hh | 90 | ||||
-rw-r--r-- | src/mem/cache/mshr_queue.cc | 35 | ||||
-rw-r--r-- | src/mem/cache/mshr_queue.hh | 21 | ||||
-rw-r--r-- | src/mem/cache/tags/base.hh | 12 | ||||
-rw-r--r-- | src/mem/cache/tags/fa_lru.hh | 32 | ||||
-rw-r--r-- | src/mem/cache/tags/iic.hh | 32 | ||||
-rw-r--r-- | src/mem/cache/tags/lru.hh | 32 |
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 §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"); } } 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__ |