* Cache definitions.
*/
-#include "base/fast_alloc.hh"
#include "base/misc.hh"
#include "base/range.hh"
#include "base/types.hh"
if (pkt->req->isUncacheable()) {
if (pkt->req->isClearLL()) {
tags->clearLocks();
- } else {
+ } else if (pkt->isWrite()) {
blk = tags->findBlock(pkt->getAddr());
if (blk != NULL) {
tags->invalidateBlk(blk);
}
-class ForwardResponseRecord : public Packet::SenderState, public FastAlloc
+class ForwardResponseRecord : public Packet::SenderState
{
Packet::SenderState *prevSenderState;
- int prevSrc;
+ PortID prevSrc;
#ifndef NDEBUG
BaseCache *cache;
#endif
//@todo Add back in MemDebug Calls
// MemDebug::cacheAccess(pkt);
+
+ /// @todo temporary hack to deal with memory corruption issue until
+ /// 4-phase transactions are complete
+ for (int x = 0; x < pendingDelete.size(); x++)
+ delete pendingDelete[x];
+ pendingDelete.clear();
+
// we charge hitLatency for doing just about anything here
Tick time = curTick() + hitLatency;
Packet *snoopPkt = new Packet(pkt, true); // clear flags
snoopPkt->setExpressSnoop();
snoopPkt->assertMemInhibit();
- memSidePort->sendTiming(snoopPkt);
+ memSidePort->sendTimingReq(snoopPkt);
// main memory will delete snoopPkt
}
// since we're the official target but we aren't responding,
// delete the packet now.
- delete pkt;
+
+ /// @todo nominally we should just delete the packet here,
+ /// however, until 4-phase stuff we can't because sending
+ /// cache is still relying on it
+ pendingDelete.push_back(pkt);
return true;
}
if (pkt->req->isUncacheable()) {
if (pkt->req->isClearLL()) {
tags->clearLocks();
- } else {
+ } else if (pkt->isWrite()) {
BlkType *blk = tags->findBlock(pkt->getAddr());
if (blk != NULL) {
tags->invalidateBlk(blk);
pkt->makeTimingResponse();
cpuSidePort->respond(pkt, curTick()+lat);
} else {
- delete pkt;
+ /// @todo nominally we should just delete the packet here,
+ /// however, until 4-phase stuff we can't because sending
+ /// cache is still relying on it
+ pendingDelete.push_back(pkt);
}
} else {
// miss
// block is invalid
cmd = needsExclusive ? MemCmd::ReadExReq : MemCmd::ReadReq;
}
- PacketPtr pkt = new Packet(cpu_pkt->req, cmd, Packet::Broadcast, blkSize);
+ PacketPtr pkt = new Packet(cpu_pkt->req, cmd, blkSize);
pkt->allocate();
return pkt;
// continues towards the memory side
if (fromCpuSide) {
memSidePort->sendFunctional(pkt);
- } else if (forwardSnoops && cpuSidePort->getMasterPort().isSnooping()) {
+ } else if (forwardSnoops && cpuSidePort->isSnooping()) {
// if it came from the memory side, it must be a snoop request
// and we should only forward it if we are forwarding snoops
cpuSidePort->sendFunctionalSnoop(pkt);
assert(!target->pkt->req->isUncacheable());
- assert(pkt->req->masterId() < system->maxMasters());
+ assert(target->pkt->req->masterId() < system->maxMasters());
missLatency[target->pkt->cmdToIndex()][target->pkt->req->masterId()] +=
completion_time - target->recvTime;
} else if (pkt->cmd == MemCmd::UpgradeFailResp) {
Request *writebackReq =
new Request(tags->regenerateBlkAddr(blk->tag, blk->set), blkSize, 0,
Request::wbMasterId);
- PacketPtr writeback = new Packet(writebackReq, MemCmd::Writeback, -1);
+ PacketPtr writeback = new Packet(writebackReq, MemCmd::Writeback);
if (blk->isWritable()) {
writeback->setSupplyExclusive();
}
Packet snoopPkt(pkt, true); // clear flags
snoopPkt.setExpressSnoop();
snoopPkt.senderState = new ForwardResponseRecord(pkt, this);
- cpuSidePort->sendTimingSnoop(&snoopPkt);
+ cpuSidePort->sendTimingSnoopReq(&snoopPkt);
if (snoopPkt.memInhibitAsserted()) {
// cache-to-cache response from some upper cache
assert(!alreadyResponded);
pkt->assertShared();
}
} else {
- Packet::NodeID origSrc = pkt->getSrc();
cpuSidePort->sendAtomicSnoop(pkt);
if (!alreadyResponded && pkt->memInhibitAsserted()) {
// cache-to-cache response from some upper cache:
// forward response to original requester
assert(pkt->isResponse());
}
- pkt->setSrc(origSrc);
}
}
pkt->getAddr());
//Look through writebacks for any non-uncachable writes, use that
- for (int i = 0; i < writebacks.size(); i++) {
- mshr = writebacks[i];
+ if (writebacks.size()) {
+ // We should only ever find a single match
+ assert(writebacks.size() == 1);
+ mshr = writebacks[0];
assert(!mshr->isUncacheable());
assert(mshr->getNumTargets() == 1);
PacketPtr wb_pkt = mshr->getTarget()->pkt;
markInService(mshr);
delete wb_pkt;
}
-
- // If this was a shared writeback, there may still be
- // other shared copies above that require invalidation.
- // We could be more selective and return here if the
- // request is non-exclusive or if the writeback is
- // exclusive.
- break;
- }
+ } // writebacks.size()
}
+ // If this was a shared writeback, there may still be
+ // other shared copies above that require invalidation.
+ // We could be more selective and return here if the
+ // request is non-exclusive or if the writeback is
+ // exclusive.
handleSnoop(pkt, blk, true, false, false);
}
template<class TagStore>
bool
-Cache<TagStore>::CpuSidePort::recvTimingSnoop(PacketPtr pkt)
+Cache<TagStore>::CpuSidePort::recvTimingSnoopResp(PacketPtr pkt)
{
// Express snoop responses from master to slave, e.g., from L1 to L2
- assert(pkt->isResponse());
-
cache->timingAccess(pkt);
return true;
}
PacketPtr snoop_pkt = new Packet(tgt_pkt, true);
snoop_pkt->setExpressSnoop();
snoop_pkt->senderState = mshr;
- cpuSidePort->sendTimingSnoop(snoop_pkt);
+ cpuSidePort->sendTimingSnoopReq(snoop_pkt);
if (snoop_pkt->memInhibitAsserted()) {
markInService(mshr, snoop_pkt);
return nextReady;
}
+template<class TagStore>
+void
+Cache<TagStore>::serialize(std::ostream &os)
+{
+ warn("*** Creating checkpoints with caches is not supported. ***\n");
+ warn(" Remove any caches before taking checkpoints\n");
+ warn(" This checkpoint will not restore correctly and dirty data in "
+ "the cache will be lost!\n");
+
+ // 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.
+
+ bool bad_checkpoint = true;
+ SERIALIZE_SCALAR(bad_checkpoint);
+}
+
+template<class TagStore>
+void
+Cache<TagStore>::unserialize(Checkpoint *cp, const std::string §ion)
+{
+ bool bad_checkpoint;
+ UNSERIALIZE_SCALAR(bad_checkpoint);
+ if (bad_checkpoint) {
+ fatal("Restoring from checkpoints with caches is not supported in the "
+ "classic memory system. Please remove any caches before taking "
+ "checkpoints.\n");
+ }
+}
///////////////
//
template<class TagStore>
AddrRangeList
-Cache<TagStore>::CpuSidePort::getAddrRanges()
+Cache<TagStore>::CpuSidePort::getAddrRanges() const
{
return cache->getAddrRanges();
}
template<class TagStore>
bool
-Cache<TagStore>::CpuSidePort::recvTiming(PacketPtr pkt)
+Cache<TagStore>::CpuSidePort::recvTimingReq(PacketPtr pkt)
{
- assert(pkt->isRequest());
// always let inhibited requests through even if blocked
if (!pkt->memInhibitAsserted() && blocked) {
DPRINTF(Cache,"Scheduling a retry while blocked\n");
Tick
Cache<TagStore>::CpuSidePort::recvAtomic(PacketPtr pkt)
{
- assert(pkt->isRequest());
// atomic request
return cache->atomicAccess(pkt);
}
void
Cache<TagStore>::CpuSidePort::recvFunctional(PacketPtr pkt)
{
- assert(pkt->isRequest());
// functional request
cache->functionalAccess(pkt, true);
}
template<class TagStore>
bool
-Cache<TagStore>::MemSidePort::recvTiming(PacketPtr pkt)
+Cache<TagStore>::MemSidePort::recvTimingResp(PacketPtr pkt)
{
// this needs to be fixed so that the cache updates the mshr and sends the
// packet back out on the link, but it probably won't happen so until this
if (pkt->wasNacked())
panic("Need to implement cache resending nacked packets!\n");
- assert(pkt->isResponse());
cache->handleResponse(pkt);
return true;
}
// Express snooping requests to memside port
template<class TagStore>
-bool
-Cache<TagStore>::MemSidePort::recvTimingSnoop(PacketPtr pkt)
+void
+Cache<TagStore>::MemSidePort::recvTimingSnoopReq(PacketPtr pkt)
{
// handle snooping requests
- assert(pkt->isRequest());
cache->snoopTiming(pkt);
- return true;
}
template<class TagStore>
Tick
Cache<TagStore>::MemSidePort::recvAtomicSnoop(PacketPtr pkt)
{
- assert(pkt->isRequest());
// atomic snoop
return cache->snoopAtomic(pkt);
}
void
Cache<TagStore>::MemSidePort::recvFunctionalSnoop(PacketPtr pkt)
{
- assert(pkt->isRequest());
// functional snoop (note that in contrast to atomic we don't have
// a specific functionalSnoop method, as they have the same
// behaviour regardless)
} else {
MSHR *mshr = dynamic_cast<MSHR*>(pkt->senderState);
- waitingOnRetry = !port.sendTiming(pkt);
+ waitingOnRetry = !masterPort.sendTimingReq(pkt);
if (waitingOnRetry) {
DPRINTF(CachePort, "now waiting on a retry\n");