diff --git a/src/mem/cache/base.cc b/src/mem/cache/base.cc index ad1c751bc7..262573663f 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 ab13be7712..e8adacfa12 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 73f569e6ac..3557bc4899 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 +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 +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 be81736aa6..5df725683e 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, 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 44acaef5b5..a7c9a4a559 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::writebackBlk(BlkType *blk) return writeback; } +template +void +Cache::memWriteback() +{ + WrappedBlkVisitor visitor(*this, &Cache::writebackVisitor); + tags->forEachBlk(visitor); +} + +template +void +Cache::memInvalidate() +{ + WrappedBlkVisitor visitor(*this, &Cache::invalidateVisitor); + tags->forEachBlk(visitor); +} + +template +bool +Cache::isDirty() const +{ + CacheBlkIsDirtyVisitor visitor; + tags->forEachBlk(visitor); + + return visitor.isDirty(); +} + +template +bool +Cache::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 +bool +Cache::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 typename Cache::BlkType* @@ -1565,16 +1629,20 @@ template void Cache::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::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 b412891d93..af13d12d37 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 89dd87fb40..44e1c5bd3c 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 576b512e50..3539f2bfdc 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 19e21688c5..7604d8d433 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 + 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 91e947704e..a41af86127 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 + 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 427dba6676..431e3eb1ef 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 + void forEachBlk(V &visitor) { + for (unsigned i = 0; i < numSets * assoc; ++i) { + if (!visitor(blks[i])) + return; + } + } }; #endif // __MEM_CACHE_TAGS_LRU_HH__