From 3952e41ab1f1dfaa2f97a6a486528e4ea0bfc5a1 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Wed, 2 Jan 2008 12:20:15 -0800 Subject: Add functional PrintReq command for memory-system debugging. --HG-- extra : convert_revision : 73b753e57c355b7e6873f047ddc8cb371c3136b7 --- src/mem/cache/SConscript | 1 + src/mem/cache/base_cache.cc | 28 ++++++++++-------- src/mem/cache/base_cache.hh | 7 +++-- src/mem/cache/cache.hh | 5 +++- src/mem/cache/cache_blk.cc | 41 +++++++++++++++++++++++++++ src/mem/cache/cache_blk.hh | 13 +++++++++ src/mem/cache/cache_impl.hh | 54 +++++++++++++++++++---------------- src/mem/cache/miss/mshr.cc | 61 +++++++++++++++++++++++++++++----------- src/mem/cache/miss/mshr.hh | 21 ++++++++------ src/mem/cache/miss/mshr_queue.cc | 9 ++++-- src/mem/cache/miss/mshr_queue.hh | 6 +++- 11 files changed, 178 insertions(+), 68 deletions(-) create mode 100644 src/mem/cache/cache_blk.cc (limited to 'src/mem/cache') diff --git a/src/mem/cache/SConscript b/src/mem/cache/SConscript index 5ac7e34ad..d5899b623 100644 --- a/src/mem/cache/SConscript +++ b/src/mem/cache/SConscript @@ -34,6 +34,7 @@ SimObject('BaseCache.py') Source('base_cache.cc') Source('cache.cc') +Source('cache_blk.cc') Source('cache_builder.cc') TraceFlag('Cache') diff --git a/src/mem/cache/base_cache.cc b/src/mem/cache/base_cache.cc index c5632e89f..9fa9e2d29 100644 --- a/src/mem/cache/base_cache.cc +++ b/src/mem/cache/base_cache.cc @@ -41,8 +41,10 @@ using namespace std; BaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache, - std::vector > filter_ranges) - : SimpleTimingPort(_name, _cache), cache(_cache), otherPort(NULL), + const std::string &_label, + std::vector > filter_ranges) + : SimpleTimingPort(_name, _cache), cache(_cache), + label(_label), otherPort(NULL), blocked(false), mustSendRetry(false), filterRanges(filter_ranges) { } @@ -50,8 +52,8 @@ BaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache, BaseCache::BaseCache(const Params *p) : MemObject(p), - mshrQueue(p->mshrs, 4, MSHRQueue_MSHRs), - writeBuffer(p->write_buffers, p->mshrs+1000, + mshrQueue("MSHRs", p->mshrs, 4, MSHRQueue_MSHRs), + writeBuffer("write buffer", p->write_buffers, p->mshrs+1000, MSHRQueue_WriteBuffer), blkSize(p->block_size), hitLatency(p->latency), @@ -71,19 +73,21 @@ BaseCache::CachePort::recvStatusChange(Port::Status status) } } -int -BaseCache::CachePort::deviceBlockSize() + +bool +BaseCache::CachePort::checkFunctional(PacketPtr pkt) { - return cache->getBlockSize(); + pkt->pushLabel(label); + bool done = SimpleTimingPort::checkFunctional(pkt); + pkt->popLabel(); + return done; } -void -BaseCache::CachePort::checkAndSendFunctional(PacketPtr pkt) +int +BaseCache::CachePort::deviceBlockSize() { - if (!checkFunctional(pkt)) { - sendFunctional(pkt); - } + return cache->getBlockSize(); } diff --git a/src/mem/cache/base_cache.hh b/src/mem/cache/base_cache.hh index 5049f68f1..604474524 100644 --- a/src/mem/cache/base_cache.hh +++ b/src/mem/cache/base_cache.hh @@ -100,7 +100,8 @@ class BaseCache : public MemObject protected: CachePort(const std::string &_name, BaseCache *_cache, - std::vector > filter_ranges); + const std::string &_label, + std::vector > filter_ranges); virtual void recvStatusChange(Status status); @@ -111,6 +112,8 @@ class BaseCache : public MemObject typedef EventWrapper SendRetryEvent; + const std::string label; + public: void setOtherPort(CachePort *_otherPort) { otherPort = _otherPort; } @@ -118,7 +121,7 @@ class BaseCache : public MemObject void clearBlocked(); - void checkAndSendFunctional(PacketPtr pkt); + bool checkFunctional(PacketPtr pkt); CachePort *otherPort; diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh index 037afd6ac..4602fd835 100644 --- a/src/mem/cache/cache.hh +++ b/src/mem/cache/cache.hh @@ -73,6 +73,7 @@ class Cache : public BaseCache public: CpuSidePort(const std::string &_name, Cache *_cache, + const std::string &_label, std::vector > filterRanges); // BaseCache::CachePort just has a BaseCache *; this function @@ -97,6 +98,7 @@ class Cache : public BaseCache public: MemSidePort(const std::string &_name, Cache *_cache, + const std::string &_label, std::vector > filterRanges); // BaseCache::CachePort just has a BaseCache *; this function @@ -229,7 +231,8 @@ class Cache : public BaseCache * @param pkt The request to perform. * @return The result of the access. */ - void functionalAccess(PacketPtr pkt, CachePort *otherSidePort); + void functionalAccess(PacketPtr pkt, CachePort *incomingPort, + CachePort *otherSidePort); /** * Handles a response (cache line fill/write ack) from the bus. diff --git a/src/mem/cache/cache_blk.cc b/src/mem/cache/cache_blk.cc new file mode 100644 index 000000000..d4a2eaee8 --- /dev/null +++ b/src/mem/cache/cache_blk.cc @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2007 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "base/cprintf.hh" +#include "mem/cache/cache_blk.hh" + +void +CacheBlkPrintWrapper::print(std::ostream &os, int verbosity, + const std::string &prefix) const +{ + ccprintf(os, "%sblk %c%c%c\n", prefix, + blk->isValid() ? 'V' : '-', + blk->isWritable() ? 'E' : '-', + blk->isDirty() ? 'M' : '-'); +} + diff --git a/src/mem/cache/cache_blk.hh b/src/mem/cache/cache_blk.hh index d2aba9480..e7c2d1a02 100644 --- a/src/mem/cache/cache_blk.hh +++ b/src/mem/cache/cache_blk.hh @@ -37,6 +37,7 @@ #include +#include "base/printable.hh" #include "sim/core.hh" // for Tick #include "arch/isa_traits.hh" // for Addr #include "mem/packet.hh" @@ -252,4 +253,16 @@ class CacheBlk } }; +class CacheBlkPrintWrapper : public Printable +{ + CacheBlk *blk; + public: + CacheBlkPrintWrapper(CacheBlk *_blk) : blk(_blk) {} + virtual ~CacheBlkPrintWrapper() {} + void print(std::ostream &o, int verbosity = 0, + const std::string &prefix = "") const; +}; + + + #endif //__CACHE_BLK_HH__ diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index 55301ecb5..257b3ef33 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -62,9 +62,11 @@ Cache::Cache(const Params *p, TagStore *tags, BasePrefetcher *pf) tempBlock->data = new uint8_t[blkSize]; cpuSidePort = new CpuSidePort(p->name + "-cpu_side_port", this, - p->cpu_side_filter_ranges); + "CpuSidePort", + p->cpu_side_filter_ranges); memSidePort = new MemSidePort(p->name + "-mem_side_port", this, - p->mem_side_filter_ranges); + "MemSidePort", + p->mem_side_filter_ranges); cpuSidePort->setOtherPort(memSidePort); memSidePort->setOtherPort(cpuSidePort); @@ -91,7 +93,8 @@ Cache::getPort(const std::string &if_name, int idx) return memSidePort; } else if (if_name == "functional") { return new CpuSidePort(name() + "-cpu_side_funcport", this, - std::vector >()); + "CpuSideFuncPort", + std::vector >()); } else { panic("Port name %s unrecognized\n", if_name); } @@ -640,21 +643,27 @@ Cache::atomicAccess(PacketPtr pkt) template void Cache::functionalAccess(PacketPtr pkt, + CachePort *incomingPort, CachePort *otherSidePort) { Addr blk_addr = pkt->getAddr() & ~(blkSize - 1); BlkType *blk = tags->findBlock(pkt->getAddr()); - if (blk && pkt->checkFunctional(blk_addr, blkSize, blk->data)) { - // request satisfied from block - return; - } + pkt->pushLabel(name()); + + CacheBlkPrintWrapper cbpw(blk); + bool done = + (blk && pkt->checkFunctional(&cbpw, blk_addr, blkSize, blk->data)) + || incomingPort->checkFunctional(pkt) + || mshrQueue.checkFunctional(pkt, blk_addr) + || writeBuffer.checkFunctional(pkt, blk_addr) + || otherSidePort->checkFunctional(pkt); - // Need to check for outstanding misses and writes; if neither one - // satisfies, then forward to other side of cache. - if (!(mshrQueue.checkFunctional(pkt, blk_addr) || - writeBuffer.checkFunctional(pkt, blk_addr))) { - otherSidePort->checkAndSendFunctional(pkt); + // We're leaving the cache, so pop cache->name() label + pkt->popLabel(); + + if (!done) { + otherSidePort->sendFunctional(pkt); } } @@ -1275,18 +1284,16 @@ template void Cache::CpuSidePort::recvFunctional(PacketPtr pkt) { - if (!checkFunctional(pkt)) { - myCache()->functionalAccess(pkt, cache->memSidePort); - } + myCache()->functionalAccess(pkt, this, otherPort); } template Cache:: -CpuSidePort::CpuSidePort(const std::string &_name, - Cache *_cache, std::vector > - filterRanges) - : BaseCache::CachePort(_name, _cache, filterRanges) +CpuSidePort::CpuSidePort(const std::string &_name, Cache *_cache, + const std::string &_label, + std::vector > filterRanges) + : BaseCache::CachePort(_name, _cache, _label, filterRanges) { } @@ -1352,9 +1359,7 @@ template void Cache::MemSidePort::recvFunctional(PacketPtr pkt) { - if (!checkFunctional(pkt)) { - myCache()->functionalAccess(pkt, cache->cpuSidePort); - } + myCache()->functionalAccess(pkt, this, otherPort); } @@ -1439,8 +1444,9 @@ Cache::MemSidePort::processSendEvent() template Cache:: MemSidePort::MemSidePort(const std::string &_name, Cache *_cache, - std::vector > filterRanges) - : BaseCache::CachePort(_name, _cache, filterRanges) + const std::string &_label, + std::vector > filterRanges) + : BaseCache::CachePort(_name, _cache, _label, filterRanges) { // override default send event from SimpleTimingPort delete sendEvent; diff --git a/src/mem/cache/miss/mshr.cc b/src/mem/cache/miss/mshr.cc index e2ff444d5..88d2acea0 100644 --- a/src/mem/cache/miss/mshr.cc +++ b/src/mem/cache/miss/mshr.cc @@ -132,6 +132,18 @@ MSHR::TargetList::checkFunctional(PacketPtr pkt) } +void +MSHR::TargetList:: +print(std::ostream &os, int verbosity, const std::string &prefix) const +{ + ConstIterator end_i = end(); + for (ConstIterator i = begin(); i != end_i; ++i) { + ccprintf(os, "%s%s: ", prefix, i->isCpuSide() ? "cpu" : "mem"); + i->pkt->print(os, verbosity, ""); + } +} + + void MSHR::allocate(Addr _addr, int _size, PacketPtr target, Tick whenReady, Counter _order) @@ -350,26 +362,41 @@ MSHR::handleFill(Packet *pkt, CacheBlk *blk) } +bool +MSHR::checkFunctional(PacketPtr pkt) +{ + // For printing, we treat the MSHR as a whole as single entity. + // For other requests, we iterate over the individual targets + // since that's where the actual data lies. + if (pkt->isPrint()) { + pkt->checkFunctional(this, addr, size, NULL); + return false; + } else { + return (targets->checkFunctional(pkt) || + deferredTargets->checkFunctional(pkt)); + } +} + + void -MSHR::dump() +MSHR::print(std::ostream &os, int verbosity, const std::string &prefix) const { - ccprintf(cerr, - "inService: %d thread: %d\n" - "Addr: %x ntargets %d\n" - "Targets:\n", - inService, threadNum, addr, ntargets); -#if 0 - TargetListIterator tar_it = targets->begin(); - for (int i = 0; i < ntargets; i++) { - assert(tar_it != targets->end()); - - ccprintf(cerr, "\t%d: Addr: %x cmd: %s\n", - i, tar_it->pkt->getAddr(), tar_it->pkt->cmdString()); - - tar_it++; + ccprintf(os, "%s[%x:%x] %s %s %s state: %s %s %s %s\n", + prefix, addr, addr+size-1, + isCacheFill ? "Fill" : "", + needsExclusive() ? "Excl" : "", + _isUncacheable ? "Unc" : "", + inService ? "InSvc" : "", + downstreamPending ? "DwnPend" : "", + pendingInvalidate ? "PendInv" : "", + pendingShared ? "PendShared" : ""); + + ccprintf(os, "%s Targets:\n", prefix); + targets->print(os, verbosity, prefix + " "); + if (!deferredTargets->empty()) { + ccprintf(os, "%s Deferred Targets:\n", prefix); + deferredTargets->print(os, verbosity, prefix + " "); } -#endif - ccprintf(cerr, "\n"); } MSHR::~MSHR() diff --git a/src/mem/cache/miss/mshr.hh b/src/mem/cache/miss/mshr.hh index c865ca3ac..0bc3c4480 100644 --- a/src/mem/cache/miss/mshr.hh +++ b/src/mem/cache/miss/mshr.hh @@ -38,6 +38,7 @@ #include +#include "base/printable.hh" #include "mem/packet.hh" class CacheBlk; @@ -47,7 +48,7 @@ class MSHRQueue; * Miss Status and handling Register. This class keeps all the information * needed to handle a cache miss including a list of target requests. */ -class MSHR : public Packet::SenderState +class MSHR : public Packet::SenderState, public Printable { public: @@ -60,7 +61,7 @@ class MSHR : public Packet::SenderState PacketPtr pkt; //!< Pending request packet. bool cpuSide; //!< Did request come from cpu side or mem side? - bool isCpuSide() { return cpuSide; } + bool isCpuSide() const { return cpuSide; } Target(PacketPtr _pkt, Tick _readyTime, Counter _order, bool _cpuSide) : recvTime(curTick), readyTime(_readyTime), order(_order), @@ -71,6 +72,7 @@ class MSHR : public Packet::SenderState class TargetList : public std::list { /** Target list iterator. */ typedef std::list::iterator Iterator; + typedef std::list::const_iterator ConstIterator; public: bool needsExclusive; @@ -83,6 +85,8 @@ class MSHR : public Packet::SenderState void replaceUpgrades(); void clearDownstreamPending(); bool checkFunctional(PacketPtr pkt); + void print(std::ostream &os, int verbosity, + const std::string &prefix) const; }; /** A list of MSHRs. */ @@ -114,7 +118,7 @@ class MSHR : public Packet::SenderState bool isCacheFill; /** True if we need to get an exclusive copy of the block. */ - bool needsExclusive() { return targets->needsExclusive; } + bool needsExclusive() const { return targets->needsExclusive; } /** True if the request is uncacheable */ bool _isUncacheable; @@ -231,15 +235,14 @@ public: void handleFill(Packet *pkt, CacheBlk *blk); - bool checkFunctional(PacketPtr pkt) { - return (targets->checkFunctional(pkt) || - deferredTargets->checkFunctional(pkt)); - } + bool checkFunctional(PacketPtr pkt); /** - * Prints the contents of this MSHR to stderr. + * Prints the contents of this MSHR for debugging. */ - void dump(); + void print(std::ostream &os, + int verbosity = 0, + const std::string &prefix = "") const; }; #endif //__MSHR_HH__ diff --git a/src/mem/cache/miss/mshr_queue.cc b/src/mem/cache/miss/mshr_queue.cc index 911329e0c..71da7e4c1 100644 --- a/src/mem/cache/miss/mshr_queue.cc +++ b/src/mem/cache/miss/mshr_queue.cc @@ -36,8 +36,10 @@ using namespace std; -MSHRQueue::MSHRQueue(int num_entries, int reserve, int _index) - : numEntries(num_entries + reserve - 1), numReserve(reserve), +MSHRQueue::MSHRQueue(const std::string &_label, + int num_entries, int reserve, int _index) + : label(_label), + numEntries(num_entries + reserve - 1), numReserve(reserve), index(_index) { allocated = 0; @@ -90,14 +92,17 @@ MSHRQueue::findMatches(Addr addr, vector& matches) const bool MSHRQueue::checkFunctional(PacketPtr pkt, Addr blk_addr) { + pkt->pushLabel(label); MSHR::ConstIterator i = allocatedList.begin(); MSHR::ConstIterator end = allocatedList.end(); for (; i != end; ++i) { MSHR *mshr = *i; if (mshr->addr == blk_addr && mshr->checkFunctional(pkt)) { + pkt->popLabel(); return true; } } + pkt->popLabel(); return false; } diff --git a/src/mem/cache/miss/mshr_queue.hh b/src/mem/cache/miss/mshr_queue.hh index 447ebfc5a..e04745087 100644 --- a/src/mem/cache/miss/mshr_queue.hh +++ b/src/mem/cache/miss/mshr_queue.hh @@ -46,6 +46,9 @@ class MSHRQueue { private: + /** Local label (for functional print requests) */ + const std::string label; + /** MSHR storage. */ MSHR *registers; /** Holds pointers to all allocated entries. */ @@ -87,7 +90,8 @@ class MSHRQueue * @param reserve The minimum number of entries needed to satisfy * any access. */ - MSHRQueue(int num_entries, int reserve, int index); + MSHRQueue(const std::string &_label, int num_entries, int reserve, + int index); /** Destructor */ ~MSHRQueue(); -- cgit v1.2.3