Add functional PrintReq command for memory-system debugging.
--HG-- extra : convert_revision : 73b753e57c355b7e6873f047ddc8cb371c3136b7
This commit is contained in:
50
src/base/printable.hh
Normal file
50
src/base/printable.hh
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* @file
|
||||
* Printable Object Base Class Declaration
|
||||
*/
|
||||
|
||||
#ifndef __PRINTABLE_HH__
|
||||
#define __PRINTABLE_HH__
|
||||
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
class Printable
|
||||
{
|
||||
public:
|
||||
Printable() {}
|
||||
virtual ~Printable() {}
|
||||
|
||||
virtual void print(std::ostream &os,
|
||||
int verbosity = 0,
|
||||
const std::string &prefix = "") const = 0;
|
||||
};
|
||||
|
||||
#endif // __PRINTABLE_HH__
|
||||
@@ -399,3 +399,10 @@ MemTestParams::create()
|
||||
{
|
||||
return new MemTest(this);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MemTest::printAddr(Addr a)
|
||||
{
|
||||
cachePort.printAddr(a);
|
||||
}
|
||||
|
||||
@@ -62,6 +62,8 @@ class MemTest : public MemObject
|
||||
|
||||
virtual Port *getPort(const std::string &if_name, int idx = -1);
|
||||
|
||||
void printAddr(Addr a);
|
||||
|
||||
protected:
|
||||
class TickEvent : public Event
|
||||
{
|
||||
|
||||
@@ -52,7 +52,6 @@
|
||||
#include "cpu/checker/cpu.hh"
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
using namespace TheISA;
|
||||
|
||||
BaseO3CPU::BaseO3CPU(Params *params)
|
||||
@@ -521,8 +520,8 @@ template <class Impl>
|
||||
void
|
||||
FullO3CPU<Impl>::activateThread(unsigned tid)
|
||||
{
|
||||
list<unsigned>::iterator isActive = find(
|
||||
activeThreads.begin(), activeThreads.end(), tid);
|
||||
std::list<unsigned>::iterator isActive =
|
||||
std::find(activeThreads.begin(), activeThreads.end(), tid);
|
||||
|
||||
DPRINTF(O3CPU, "[tid:%i]: Calling activate thread.\n", tid);
|
||||
|
||||
@@ -539,8 +538,8 @@ void
|
||||
FullO3CPU<Impl>::deactivateThread(unsigned tid)
|
||||
{
|
||||
//Remove From Active List, if Active
|
||||
list<unsigned>::iterator thread_it =
|
||||
find(activeThreads.begin(), activeThreads.end(), tid);
|
||||
std::list<unsigned>::iterator thread_it =
|
||||
std::find(activeThreads.begin(), activeThreads.end(), tid);
|
||||
|
||||
DPRINTF(O3CPU, "[tid:%i]: Calling deactivate thread.\n", tid);
|
||||
|
||||
@@ -959,8 +958,8 @@ FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
|
||||
// the active threads list.
|
||||
int tid = 0;
|
||||
|
||||
list<unsigned>::iterator isActive = find(
|
||||
activeThreads.begin(), activeThreads.end(), tid);
|
||||
std::list<unsigned>::iterator isActive =
|
||||
std::find(activeThreads.begin(), activeThreads.end(), tid);
|
||||
|
||||
if (isActive == activeThreads.end()) {
|
||||
//May Need to Re-code this if the delay variable is the delay
|
||||
@@ -1454,8 +1453,8 @@ FullO3CPU<Impl>::updateThreadPriority()
|
||||
{
|
||||
//DEFAULT TO ROUND ROBIN SCHEME
|
||||
//e.g. Move highest priority to end of thread list
|
||||
list<unsigned>::iterator list_begin = activeThreads.begin();
|
||||
list<unsigned>::iterator list_end = activeThreads.end();
|
||||
std::list<unsigned>::iterator list_begin = activeThreads.begin();
|
||||
std::list<unsigned>::iterator list_end = activeThreads.end();
|
||||
|
||||
unsigned high_thread = *list_begin;
|
||||
|
||||
|
||||
@@ -319,11 +319,15 @@ Bridge::BridgePort::recvFunctional(PacketPtr pkt)
|
||||
{
|
||||
std::list<PacketBuffer*>::iterator i;
|
||||
|
||||
pkt->pushLabel(name());
|
||||
|
||||
for (i = sendQueue.begin(); i != sendQueue.end(); ++i) {
|
||||
if (pkt->checkFunctional((*i)->pkt))
|
||||
return;
|
||||
}
|
||||
|
||||
pkt->popLabel();
|
||||
|
||||
// fall through if pkt still not satisfied
|
||||
otherPort->sendFunctional(pkt);
|
||||
}
|
||||
|
||||
1
src/mem/cache/SConscript
vendored
1
src/mem/cache/SConscript
vendored
@@ -34,6 +34,7 @@ SimObject('BaseCache.py')
|
||||
|
||||
Source('base_cache.cc')
|
||||
Source('cache.cc')
|
||||
Source('cache_blk.cc')
|
||||
Source('cache_builder.cc')
|
||||
|
||||
TraceFlag('Cache')
|
||||
|
||||
30
src/mem/cache/base_cache.cc
vendored
30
src/mem/cache/base_cache.cc
vendored
@@ -41,8 +41,10 @@
|
||||
using namespace std;
|
||||
|
||||
BaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache,
|
||||
std::vector<Range<Addr> > filter_ranges)
|
||||
: SimpleTimingPort(_name, _cache), cache(_cache), otherPort(NULL),
|
||||
const std::string &_label,
|
||||
std::vector<Range<Addr> > 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,6 +73,17 @@ BaseCache::CachePort::recvStatusChange(Port::Status status)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BaseCache::CachePort::checkFunctional(PacketPtr pkt)
|
||||
{
|
||||
pkt->pushLabel(label);
|
||||
bool done = SimpleTimingPort::checkFunctional(pkt);
|
||||
pkt->popLabel();
|
||||
return done;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
BaseCache::CachePort::deviceBlockSize()
|
||||
{
|
||||
@@ -78,15 +91,6 @@ BaseCache::CachePort::deviceBlockSize()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BaseCache::CachePort::checkAndSendFunctional(PacketPtr pkt)
|
||||
{
|
||||
if (!checkFunctional(pkt)) {
|
||||
sendFunctional(pkt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BaseCache::CachePort::recvRetryCommon()
|
||||
{
|
||||
|
||||
7
src/mem/cache/base_cache.hh
vendored
7
src/mem/cache/base_cache.hh
vendored
@@ -100,7 +100,8 @@ class BaseCache : public MemObject
|
||||
|
||||
protected:
|
||||
CachePort(const std::string &_name, BaseCache *_cache,
|
||||
std::vector<Range<Addr> > filter_ranges);
|
||||
const std::string &_label,
|
||||
std::vector<Range<Addr> > filter_ranges);
|
||||
|
||||
virtual void recvStatusChange(Status status);
|
||||
|
||||
@@ -111,6 +112,8 @@ class BaseCache : public MemObject
|
||||
typedef EventWrapper<Port, &Port::sendRetry>
|
||||
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;
|
||||
|
||||
|
||||
5
src/mem/cache/cache.hh
vendored
5
src/mem/cache/cache.hh
vendored
@@ -73,6 +73,7 @@ class Cache : public BaseCache
|
||||
public:
|
||||
CpuSidePort(const std::string &_name,
|
||||
Cache<TagStore> *_cache,
|
||||
const std::string &_label,
|
||||
std::vector<Range<Addr> > filterRanges);
|
||||
|
||||
// BaseCache::CachePort just has a BaseCache *; this function
|
||||
@@ -97,6 +98,7 @@ class Cache : public BaseCache
|
||||
public:
|
||||
MemSidePort(const std::string &_name,
|
||||
Cache<TagStore> *_cache,
|
||||
const std::string &_label,
|
||||
std::vector<Range<Addr> > 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.
|
||||
|
||||
41
src/mem/cache/cache_blk.cc
vendored
Normal file
41
src/mem/cache/cache_blk.cc
vendored
Normal file
@@ -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' : '-');
|
||||
}
|
||||
|
||||
13
src/mem/cache/cache_blk.hh
vendored
13
src/mem/cache/cache_blk.hh
vendored
@@ -37,6 +37,7 @@
|
||||
|
||||
#include <list>
|
||||
|
||||
#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__
|
||||
|
||||
54
src/mem/cache/cache_impl.hh
vendored
54
src/mem/cache/cache_impl.hh
vendored
@@ -62,9 +62,11 @@ Cache<TagStore>::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<TagStore>::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<Range<Addr> >());
|
||||
"CpuSideFuncPort",
|
||||
std::vector<Range<Addr> >());
|
||||
} else {
|
||||
panic("Port name %s unrecognized\n", if_name);
|
||||
}
|
||||
@@ -640,21 +643,27 @@ Cache<TagStore>::atomicAccess(PacketPtr pkt)
|
||||
template<class TagStore>
|
||||
void
|
||||
Cache<TagStore>::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());
|
||||
|
||||
// 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);
|
||||
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);
|
||||
|
||||
// We're leaving the cache, so pop cache->name() label
|
||||
pkt->popLabel();
|
||||
|
||||
if (!done) {
|
||||
otherSidePort->sendFunctional(pkt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1275,18 +1284,16 @@ template<class TagStore>
|
||||
void
|
||||
Cache<TagStore>::CpuSidePort::recvFunctional(PacketPtr pkt)
|
||||
{
|
||||
if (!checkFunctional(pkt)) {
|
||||
myCache()->functionalAccess(pkt, cache->memSidePort);
|
||||
}
|
||||
myCache()->functionalAccess(pkt, this, otherPort);
|
||||
}
|
||||
|
||||
|
||||
template<class TagStore>
|
||||
Cache<TagStore>::
|
||||
CpuSidePort::CpuSidePort(const std::string &_name,
|
||||
Cache<TagStore> *_cache, std::vector<Range<Addr> >
|
||||
filterRanges)
|
||||
: BaseCache::CachePort(_name, _cache, filterRanges)
|
||||
CpuSidePort::CpuSidePort(const std::string &_name, Cache<TagStore> *_cache,
|
||||
const std::string &_label,
|
||||
std::vector<Range<Addr> > filterRanges)
|
||||
: BaseCache::CachePort(_name, _cache, _label, filterRanges)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1352,9 +1359,7 @@ template<class TagStore>
|
||||
void
|
||||
Cache<TagStore>::MemSidePort::recvFunctional(PacketPtr pkt)
|
||||
{
|
||||
if (!checkFunctional(pkt)) {
|
||||
myCache()->functionalAccess(pkt, cache->cpuSidePort);
|
||||
}
|
||||
myCache()->functionalAccess(pkt, this, otherPort);
|
||||
}
|
||||
|
||||
|
||||
@@ -1439,8 +1444,9 @@ Cache<TagStore>::MemSidePort::processSendEvent()
|
||||
template<class TagStore>
|
||||
Cache<TagStore>::
|
||||
MemSidePort::MemSidePort(const std::string &_name, Cache<TagStore> *_cache,
|
||||
std::vector<Range<Addr> > filterRanges)
|
||||
: BaseCache::CachePort(_name, _cache, filterRanges)
|
||||
const std::string &_label,
|
||||
std::vector<Range<Addr> > filterRanges)
|
||||
: BaseCache::CachePort(_name, _cache, _label, filterRanges)
|
||||
{
|
||||
// override default send event from SimpleTimingPort
|
||||
delete sendEvent;
|
||||
|
||||
63
src/mem/cache/miss/mshr.cc
vendored
63
src/mem/cache/miss/mshr.cc
vendored
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MSHR::dump()
|
||||
bool
|
||||
MSHR::checkFunctional(PacketPtr pkt)
|
||||
{
|
||||
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++;
|
||||
// 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::print(std::ostream &os, int verbosity, const std::string &prefix) const
|
||||
{
|
||||
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()
|
||||
|
||||
21
src/mem/cache/miss/mshr.hh
vendored
21
src/mem/cache/miss/mshr.hh
vendored
@@ -38,6 +38,7 @@
|
||||
|
||||
#include <list>
|
||||
|
||||
#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> {
|
||||
/** Target list iterator. */
|
||||
typedef std::list<Target>::iterator Iterator;
|
||||
typedef std::list<Target>::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__
|
||||
|
||||
9
src/mem/cache/miss/mshr_queue.cc
vendored
9
src/mem/cache/miss/mshr_queue.cc
vendored
@@ -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<MSHR*>& 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;
|
||||
}
|
||||
|
||||
|
||||
6
src/mem/cache/miss/mshr_queue.hh
vendored
6
src/mem/cache/miss/mshr_queue.hh
vendored
@@ -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();
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include "base/cprintf.hh"
|
||||
#include "base/misc.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "mem/packet.hh"
|
||||
@@ -121,7 +122,9 @@ MemCmd::commandInfo[] =
|
||||
/* InvalidDestError -- packet dest field invalid */
|
||||
{ SET2(IsResponse, IsError), InvalidCmd, "InvalidDestError" },
|
||||
/* BadAddressError -- memory address invalid */
|
||||
{ SET2(IsResponse, IsError), InvalidCmd, "BadAddressError" }
|
||||
{ SET2(IsResponse, IsError), InvalidCmd, "BadAddressError" },
|
||||
/* PrintReq */
|
||||
{ SET2(IsRequest, IsPrint), InvalidCmd, "PrintReq" }
|
||||
};
|
||||
|
||||
|
||||
@@ -154,7 +157,7 @@ Packet::allocate()
|
||||
|
||||
|
||||
bool
|
||||
Packet::checkFunctional(Addr addr, int size, uint8_t *data)
|
||||
Packet::checkFunctional(Printable *obj, Addr addr, int size, uint8_t *data)
|
||||
{
|
||||
Addr func_start = getAddr();
|
||||
Addr func_end = getAddr() + getSize() - 1;
|
||||
@@ -166,6 +169,17 @@ Packet::checkFunctional(Addr addr, int size, uint8_t *data)
|
||||
return false;
|
||||
}
|
||||
|
||||
// check print first since it doesn't require data
|
||||
if (isPrint()) {
|
||||
dynamic_cast<PrintReqState*>(senderState)->printObj(obj);
|
||||
return false;
|
||||
}
|
||||
|
||||
// if there's no data, there's no need to look further
|
||||
if (!data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// offset of functional request into supplied value (could be
|
||||
// negative if partial overlap)
|
||||
int offset = func_start - val_start;
|
||||
@@ -194,40 +208,85 @@ Packet::checkFunctional(Addr addr, int size, uint8_t *data)
|
||||
std::memcpy(data, getPtr<uint8_t>() - offset,
|
||||
(std::min(func_end, val_end) - val_start) + 1);
|
||||
}
|
||||
// we always want to keep going with a write
|
||||
return false;
|
||||
} else
|
||||
} else {
|
||||
panic("Don't know how to handle command %s\n", cmdString());
|
||||
}
|
||||
|
||||
// keep going with request by default
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
std::ostream &
|
||||
operator<<(std::ostream &o, const Packet &p)
|
||||
void
|
||||
Packet::print(std::ostream &o, const int verbosity,
|
||||
const std::string &prefix) const
|
||||
{
|
||||
|
||||
o << "[0x";
|
||||
o.setf(std::ios_base::hex, std::ios_base::showbase);
|
||||
o << p.getAddr();
|
||||
o.unsetf(std::ios_base::hex| std::ios_base::showbase);
|
||||
o << ":";
|
||||
o.setf(std::ios_base::hex, std::ios_base::showbase);
|
||||
o << p.getAddr() + p.getSize() - 1 << "] ";
|
||||
o.unsetf(std::ios_base::hex| std::ios_base::showbase);
|
||||
|
||||
if (p.isRead())
|
||||
o << "Read ";
|
||||
if (p.isWrite())
|
||||
o << "Write ";
|
||||
if (p.isInvalidate())
|
||||
o << "Invalidate ";
|
||||
if (p.isRequest())
|
||||
o << "Request ";
|
||||
if (p.isResponse())
|
||||
o << "Response ";
|
||||
if (p.hasData())
|
||||
o << "w/Data ";
|
||||
|
||||
o << std::endl;
|
||||
return o;
|
||||
ccprintf(o, "%s[%x:%x] %s\n", prefix,
|
||||
getAddr(), getAddr() + getSize() - 1, cmdString());
|
||||
}
|
||||
|
||||
|
||||
Packet::PrintReqState::PrintReqState(std::ostream &_os, int _verbosity)
|
||||
: curPrefixPtr(new std::string("")), os(_os), verbosity(_verbosity)
|
||||
{
|
||||
labelStack.push_back(LabelStackEntry("", curPrefixPtr));
|
||||
}
|
||||
|
||||
|
||||
Packet::PrintReqState::~PrintReqState()
|
||||
{
|
||||
labelStack.pop_back();
|
||||
assert(labelStack.empty());
|
||||
delete curPrefixPtr;
|
||||
}
|
||||
|
||||
|
||||
Packet::PrintReqState::
|
||||
LabelStackEntry::LabelStackEntry(const std::string &_label,
|
||||
std::string *_prefix)
|
||||
: label(_label), prefix(_prefix), labelPrinted(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Packet::PrintReqState::pushLabel(const std::string &lbl,
|
||||
const std::string &prefix)
|
||||
{
|
||||
labelStack.push_back(LabelStackEntry(lbl, curPrefixPtr));
|
||||
curPrefixPtr = new std::string(*curPrefixPtr);
|
||||
*curPrefixPtr += prefix;
|
||||
}
|
||||
|
||||
void
|
||||
Packet::PrintReqState::popLabel()
|
||||
{
|
||||
delete curPrefixPtr;
|
||||
curPrefixPtr = labelStack.back().prefix;
|
||||
labelStack.pop_back();
|
||||
assert(!labelStack.empty());
|
||||
}
|
||||
|
||||
void
|
||||
Packet::PrintReqState::printLabels()
|
||||
{
|
||||
if (!labelStack.back().labelPrinted) {
|
||||
LabelStack::iterator i = labelStack.begin();
|
||||
LabelStack::iterator end = labelStack.end();
|
||||
while (i != end) {
|
||||
if (!i->labelPrinted) {
|
||||
ccprintf(os, "%s%s\n", *(i->prefix), i->label);
|
||||
i->labelPrinted = true;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Packet::PrintReqState::printObj(Printable *obj)
|
||||
{
|
||||
printLabels();
|
||||
obj->print(os, verbosity, curPrefix());
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "base/compiler.hh"
|
||||
#include "base/fast_alloc.hh"
|
||||
#include "base/misc.hh"
|
||||
#include "base/printable.hh"
|
||||
#include "mem/request.hh"
|
||||
#include "sim/host.hh"
|
||||
#include "sim/core.hh"
|
||||
@@ -91,6 +92,8 @@ class MemCmd
|
||||
NetworkNackError, // nacked at network layer (not by protocol)
|
||||
InvalidDestError, // packet dest field invalid
|
||||
BadAddressError, // memory address invalid
|
||||
// Fake simulator-only commands
|
||||
PrintReq, // Print state matching address
|
||||
NUM_MEM_CMDS
|
||||
};
|
||||
|
||||
@@ -111,6 +114,7 @@ class MemCmd
|
||||
IsLocked, //!< Alpha/MIPS LL or SC access
|
||||
HasData, //!< There is an associated payload
|
||||
IsError, //!< Error response
|
||||
IsPrint, //!< Print state matching address (for debugging)
|
||||
NUM_COMMAND_ATTRIBUTES
|
||||
};
|
||||
|
||||
@@ -150,6 +154,7 @@ class MemCmd
|
||||
bool isReadWrite() const { return isRead() && isWrite(); }
|
||||
bool isLocked() const { return testCmdAttrib(IsLocked); }
|
||||
bool isError() const { return testCmdAttrib(IsError); }
|
||||
bool isPrint() const { return testCmdAttrib(IsPrint); }
|
||||
|
||||
const Command responseCommand() const {
|
||||
return commandInfo[cmd].response;
|
||||
@@ -187,7 +192,7 @@ class MemCmd
|
||||
* ultimate destination and back, possibly being conveyed by several
|
||||
* different Packets along the way.)
|
||||
*/
|
||||
class Packet : public FastAlloc
|
||||
class Packet : public FastAlloc, public Printable
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -294,6 +299,36 @@ class Packet : public FastAlloc
|
||||
virtual ~SenderState() {}
|
||||
};
|
||||
|
||||
class PrintReqState : public SenderState {
|
||||
class LabelStackEntry {
|
||||
public:
|
||||
const std::string label;
|
||||
std::string *prefix;
|
||||
bool labelPrinted;
|
||||
LabelStackEntry(const std::string &_label,
|
||||
std::string *_prefix);
|
||||
};
|
||||
|
||||
typedef std::list<LabelStackEntry> LabelStack;
|
||||
LabelStack labelStack;
|
||||
|
||||
std::string *curPrefixPtr;
|
||||
|
||||
public:
|
||||
std::ostream &os;
|
||||
const int verbosity;
|
||||
|
||||
PrintReqState(std::ostream &os, int verbosity = 0);
|
||||
~PrintReqState();
|
||||
|
||||
const std::string &curPrefix() { return *curPrefixPtr; }
|
||||
void pushLabel(const std::string &lbl,
|
||||
const std::string &prefix = " ");
|
||||
void popLabel();
|
||||
void printLabels();
|
||||
void printObj(Printable *obj);
|
||||
};
|
||||
|
||||
/** This packet's sender state. Devices should use dynamic_cast<>
|
||||
* to cast to the state appropriate to the sender. */
|
||||
SenderState *senderState;
|
||||
@@ -316,6 +351,7 @@ class Packet : public FastAlloc
|
||||
bool isReadWrite() const { return cmd.isReadWrite(); }
|
||||
bool isLocked() const { return cmd.isLocked(); }
|
||||
bool isError() const { return cmd.isError(); }
|
||||
bool isPrint() const { return cmd.isPrint(); }
|
||||
|
||||
// Snoop flags
|
||||
void assertMemInhibit() { flags[MemInhibit] = true; }
|
||||
@@ -573,19 +609,39 @@ class Packet : public FastAlloc
|
||||
* value. If the functional request is a write, it may update the
|
||||
* memory value.
|
||||
*/
|
||||
bool checkFunctional(Addr base, int size, uint8_t *data);
|
||||
bool checkFunctional(Printable *obj, Addr base, int size, uint8_t *data);
|
||||
|
||||
/**
|
||||
* Check a functional request against a memory value stored in
|
||||
* another packet (i.e. an in-transit request or response).
|
||||
* another packet (i.e. an in-transit request or response). If
|
||||
* possible, the request will be satisfied and transformed
|
||||
* in-place into a response (at which point no further checking
|
||||
* need be done).
|
||||
*
|
||||
* @return True if the memory location addressed by the request
|
||||
* overlaps with the location addressed by otherPkt.
|
||||
*/
|
||||
bool checkFunctional(PacketPtr otherPkt) {
|
||||
return (otherPkt->hasData() &&
|
||||
checkFunctional(otherPkt->getAddr(), otherPkt->getSize(),
|
||||
otherPkt->getPtr<uint8_t>()));
|
||||
return checkFunctional(otherPkt,
|
||||
otherPkt->getAddr(), otherPkt->getSize(),
|
||||
otherPkt->hasData() ?
|
||||
otherPkt->getPtr<uint8_t>() : NULL);
|
||||
}
|
||||
|
||||
void pushLabel(const std::string &lbl) {
|
||||
if (isPrint()) {
|
||||
dynamic_cast<PrintReqState*>(senderState)->pushLabel(lbl);
|
||||
}
|
||||
}
|
||||
|
||||
void popLabel() {
|
||||
if (isPrint()) {
|
||||
dynamic_cast<PrintReqState*>(senderState)->popLabel();
|
||||
}
|
||||
}
|
||||
|
||||
void print(std::ostream &o, int verbosity = 0,
|
||||
const std::string &prefix = "") const;
|
||||
};
|
||||
|
||||
std::ostream & operator<<(std::ostream &o, const Packet &p);
|
||||
|
||||
#endif //__MEM_PACKET_HH
|
||||
|
||||
@@ -314,18 +314,22 @@ PhysicalMemory::doFunctionalAccess(PacketPtr pkt)
|
||||
|
||||
uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start();
|
||||
|
||||
if (pkt->cmd == MemCmd::ReadReq) {
|
||||
if (pkt->isRead()) {
|
||||
memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
|
||||
TRACE_PACKET("Read");
|
||||
} else if (pkt->cmd == MemCmd::WriteReq) {
|
||||
pkt->makeAtomicResponse();
|
||||
} else if (pkt->isWrite()) {
|
||||
memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize());
|
||||
TRACE_PACKET("Write");
|
||||
pkt->makeAtomicResponse();
|
||||
} else if (pkt->isPrint()) {
|
||||
Packet::PrintReqState *prs = dynamic_cast<Packet::PrintReqState*>(pkt->senderState);
|
||||
prs->printLabels();
|
||||
ccprintf(prs->os, "%s%#x\n", prs->curPrefix(), *hostAddr);
|
||||
} else {
|
||||
panic("PhysicalMemory: unimplemented functional command %s",
|
||||
pkt->cmdString());
|
||||
}
|
||||
|
||||
pkt->makeAtomicResponse();
|
||||
}
|
||||
|
||||
|
||||
@@ -405,12 +409,16 @@ PhysicalMemory::MemoryPort::recvAtomic(PacketPtr pkt)
|
||||
void
|
||||
PhysicalMemory::MemoryPort::recvFunctional(PacketPtr pkt)
|
||||
{
|
||||
pkt->pushLabel(memory->name());
|
||||
|
||||
if (!checkFunctional(pkt)) {
|
||||
// Default implementation of SimpleTimingPort::recvFunctional()
|
||||
// calls recvAtomic() and throws away the latency; we can save a
|
||||
// little here by just not calculating the latency.
|
||||
memory->doFunctionalAccess(pkt);
|
||||
}
|
||||
|
||||
pkt->popLabel();
|
||||
}
|
||||
|
||||
unsigned int
|
||||
|
||||
@@ -150,3 +150,15 @@ Port::memsetBlob(Addr addr, uint8_t val, int size)
|
||||
|
||||
delete [] buf;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Port::printAddr(Addr a)
|
||||
{
|
||||
Request req(a, 1, 0);
|
||||
Packet pkt(&req, MemCmd::PrintReq, Packet::Broadcast);
|
||||
Packet::PrintReqState prs(std::cerr);
|
||||
pkt.senderState = &prs;
|
||||
|
||||
sendFunctional(&pkt);
|
||||
}
|
||||
|
||||
@@ -243,6 +243,11 @@ class Port
|
||||
*/
|
||||
virtual void memsetBlob(Addr addr, uint8_t val, int size);
|
||||
|
||||
/** Inject a PrintReq for the given address to print the state of
|
||||
* that address throughout the memory system. For debugging.
|
||||
*/
|
||||
void printAddr(Addr a);
|
||||
|
||||
private:
|
||||
|
||||
/** Internal helper function for read/writeBlob().
|
||||
|
||||
@@ -264,3 +264,19 @@ SimObject::takeOverFrom(BaseCPU *cpu)
|
||||
{
|
||||
panic("Unimplemented!");
|
||||
}
|
||||
|
||||
|
||||
SimObject *
|
||||
SimObject::find(const char *name)
|
||||
{
|
||||
SimObjectList::const_iterator i = simObjectList.begin();
|
||||
SimObjectList::const_iterator end = simObjectList.end();
|
||||
|
||||
for (; i != end; ++i) {
|
||||
SimObject *obj = *i;
|
||||
if (obj->name() == name)
|
||||
return obj;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -131,6 +131,13 @@ class SimObject : public Serializable, protected StartupCallback
|
||||
static void debugObjectBreak(const std::string &objs);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Find the SimObject with the given name and return a pointer to
|
||||
* it. Priarily used for interactive debugging. Argument is
|
||||
* char* rather than std::string to make it callable from gdb.
|
||||
*/
|
||||
static SimObject *find(const char *name);
|
||||
|
||||
public:
|
||||
void recordEvent(const std::string &stat);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user