--- /dev/null
+/*
+ * 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__
{
return new MemTest(this);
}
+
+
+void
+MemTest::printAddr(Addr a)
+{
+ cachePort.printAddr(a);
+}
virtual Port *getPort(const std::string &if_name, int idx = -1);
+ void printAddr(Addr a);
+
protected:
class TickEvent : public Event
{
#include "cpu/checker/cpu.hh"
#endif
-using namespace std;
using namespace TheISA;
BaseO3CPU::BaseO3CPU(Params *params)
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);
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);
// 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
{
//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;
{
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);
}
Source('base_cache.cc')
Source('cache.cc')
+Source('cache_blk.cc')
Source('cache_builder.cc')
TraceFlag('Cache')
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)
{
}
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),
}
}
-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();
}
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);
typedef EventWrapper<Port, &Port::sendRetry>
SendRetryEvent;
+ const std::string label;
+
public:
void setOtherPort(CachePort *_otherPort) { otherPort = _otherPort; }
void clearBlocked();
- void checkAndSendFunctional(PacketPtr pkt);
+ bool checkFunctional(PacketPtr pkt);
CachePort *otherPort;
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
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
* @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.
--- /dev/null
+/*
+ * 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' : '-');
+}
+
#include <list>
+#include "base/printable.hh"
#include "sim/core.hh" // for Tick
#include "arch/isa_traits.hh" // for Addr
#include "mem/packet.hh"
}
};
+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__
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);
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);
}
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());
+
+ 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);
}
}
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)
{
}
void
Cache<TagStore>::MemSidePort::recvFunctional(PacketPtr pkt)
{
- if (!checkFunctional(pkt)) {
- myCache()->functionalAccess(pkt, cache->cpuSidePort);
- }
+ myCache()->functionalAccess(pkt, this, otherPort);
}
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;
}
+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)
}
+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()
#include <list>
+#include "base/printable.hh"
#include "mem/packet.hh"
class CacheBlk;
* 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:
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),
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;
void replaceUpgrades();
void clearDownstreamPending();
bool checkFunctional(PacketPtr pkt);
+ void print(std::ostream &os, int verbosity,
+ const std::string &prefix) const;
};
/** A list of MSHRs. */
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;
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__
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;
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;
}
class MSHRQueue
{
private:
+ /** Local label (for functional print requests) */
+ const std::string label;
+
/** MSHR storage. */
MSHR *registers;
/** Holds pointers to all allocated entries. */
* @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();
#include <iostream>
#include <cstring>
+#include "base/cprintf.hh"
#include "base/misc.hh"
#include "base/trace.hh"
#include "mem/packet.hh"
/* 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" }
};
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;
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;
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;
+}
+
+
+void
+Packet::print(std::ostream &o, const int verbosity,
+ const std::string &prefix) const
+{
+ 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)
+{
}
-std::ostream &
-operator<<(std::ostream &o, const Packet &p)
+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());
+}
- 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;
+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());
+}
#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"
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
};
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
};
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;
* 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:
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;
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; }
* 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);
}
-};
-std::ostream & operator<<(std::ostream &o, const Packet &p);
+ 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;
+};
#endif //__MEM_PACKET_HH
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();
}
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
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);
+}
*/
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().
{
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;
+}
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);
};