From 792d5b9e5ee40e58b922ae32e5a6ee9aa9586cbc Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Fri, 18 May 2007 22:35:04 -0700 Subject: First set of changes for reorganized cache coherence support. Compiles but doesn't work... committing just so I can merge (stupid bk!). src/mem/bridge.cc: Get rid of SNOOP_COMMIT. src/mem/bus.cc: src/mem/packet.hh: Get rid of SNOOP_COMMIT & two-pass snoop. First bits of EXPRESS_SNOOP support. src/mem/cache/base_cache.cc: src/mem/cache/base_cache.hh: src/mem/cache/cache.hh: src/mem/cache/cache_impl.hh: src/mem/cache/miss/blocking_buffer.cc: src/mem/cache/miss/miss_queue.cc: src/mem/cache/prefetch/base_prefetcher.cc: Big reorg of ports and port-related functions & events. src/mem/cache/cache.cc: src/mem/cache/cache_builder.cc: src/mem/cache/coherence/SConscript: Get rid of UniCoherence object. --HG-- extra : convert_revision : 7672434fa3115c9b1c94686f497e57e90413b7c3 --- src/mem/cache/cache_impl.hh | 278 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 220 insertions(+), 58 deletions(-) (limited to 'src/mem/cache/cache_impl.hh') diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index 9b094c1e3..6b9eac865 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -28,6 +28,8 @@ * Authors: Erik Hallnor * Dave Greene * Nathan Binkert + * Steve Reinhardt + * Ron Dreslinski */ /** @@ -57,18 +59,8 @@ bool SIGNAL_NACK_HACK; template -void -Cache:: -recvStatusChange(Port::Status status, bool isCpuSide) -{ - -} - - -template -Cache:: -Cache(const std::string &_name, - Cache::Params ¶ms) +Cache::Cache(const std::string &_name, + Cache::Params ¶ms) : BaseCache(_name, params.baseParams), prefetchAccess(params.prefetchAccess), tags(params.tags), missQueue(params.missQueue), @@ -84,6 +76,11 @@ Cache(const std::string &_name, adaptiveCompression(params.adaptiveCompression), writebackCompressed(params.writebackCompressed) { + cpuSidePort = new CpuSidePort(_name + "-cpu_side_port", this); + memSidePort = new MemSidePort(_name + "-mem_side_port", this); + cpuSidePort->setOtherPort(memSidePort); + memSidePort->setOtherPort(cpuSidePort); + tags->setCache(this); missQueue->setCache(this); missQueue->setPrefetcher(prefetcher); @@ -406,7 +403,11 @@ Cache::handleFill(BlkType *blk, MSHR * mshr, // mshr->pkt = pkt; break; } - respondToMiss(target, completion_time); + if (!target->req->isUncacheable()) { + missLatency[target->cmdToIndex()][0/*pkt->req->getThreadNum()*/] += + completion_time - target->time; + } + respond(target, completion_time); mshr->popTarget(); } @@ -688,7 +689,7 @@ Cache::getPacket() } } - assert(!doMasterRequest() || missQueue->havePending()); + assert(!isMemSideBusRequested() || missQueue->havePending()); assert(!pkt || pkt->time <= curTick); SIGNAL_NACK_HACK = false; return pkt; @@ -727,7 +728,6 @@ Cache::sendResult(PacketPtr &pkt, MSHR* mshr, pkt->flags &= ~NACKED_LINE; SIGNAL_NACK_HACK = false; pkt->flags &= ~SATISFIED; - pkt->flags &= ~SNOOP_COMMIT; //Rmove copy from mshr delete mshr->pkt; @@ -783,22 +783,6 @@ Cache::handleResponse(PacketPtr &pkt) } } -template -PacketPtr -Cache::getCoherencePacket() -{ - return coherence->getPacket(); -} - -template -void -Cache::sendCoherenceResult(PacketPtr &pkt, - MSHR *cshr, - bool success) -{ - coherence->sendResult(pkt, cshr, success); -} - template void @@ -1146,27 +1130,15 @@ template Port * Cache::getPort(const std::string &if_name, int idx) { - if (if_name == "" || if_name == "cpu_side") - { - if (cpuSidePort == NULL) { - cpuSidePort = new CpuSidePort(name() + "-cpu_side_port", this); - sendEvent = new ResponseEvent(cpuSidePort); - } + if (if_name == "" || if_name == "cpu_side") { return cpuSidePort; - } - else if (if_name == "functional") - { - return new CpuSidePort(name() + "-cpu_side_funcport", this); - } - else if (if_name == "mem_side") - { - if (memSidePort != NULL) - panic("Already have a mem side for this cache\n"); - memSidePort = new MemSidePort(name() + "-mem_side_port", this); - memSendEvent = new ResponseEvent(memSidePort); + } else if (if_name == "mem_side") { return memSidePort; + } else if (if_name == "functional") { + return new CpuSidePort(name() + "-cpu_side_funcport", this); + } else { + panic("Port name %s unrecognized\n", if_name); } - else panic("Port name %s unrecognized\n", if_name); } template @@ -1213,6 +1185,68 @@ Cache::CpuSidePort::recvTiming(PacketPtr pkt) return true; } + +template +void +Cache::CpuSidePort::recvRetry() +{ + recvRetryCommon(); +} + + +template +void +Cache::CpuSidePort::processRequestEvent() +{ + if (waitingOnRetry) + return; + //We have some responses to drain first + if (!drainList.empty()) { + if (!drainResponse()) { + // more responses to drain... re-request bus + scheduleRequestEvent(curTick + 1); + } + } +} + + +template +void +Cache::CpuSidePort::processResponseEvent() +{ + assert(transmitList.size()); + assert(transmitList.front().first <= curTick); + PacketPtr pkt = transmitList.front().second; + transmitList.pop_front(); + if (!transmitList.empty()) { + Tick time = transmitList.front().first; + responseEvent->schedule(time <= curTick ? curTick+1 : time); + } + + if (pkt->flags & NACKED_LINE) + pkt->result = Packet::Nacked; + else + pkt->result = Packet::Success; + pkt->makeTimingResponse(); + DPRINTF(CachePort, "%s attempting to send a response\n", name()); + if (!drainList.empty() || waitingOnRetry) { + //Already have a list, just append + drainList.push_back(pkt); + DPRINTF(CachePort, "%s appending response onto drain list\n", name()); + } + else if (!sendTiming(pkt)) { + //It failed, save it to list of drain events + DPRINTF(CachePort, "%s now waiting for a retry\n", name()); + drainList.push_back(pkt); + waitingOnRetry = true; + } + + // Check if we're done draining once this list is empty + if (drainList.empty() && transmitList.empty()) + myCache()->checkDrain(); +} + + template Tick Cache::CpuSidePort::recvAtomic(PacketPtr pkt) @@ -1249,23 +1283,149 @@ Cache::MemSidePort::recvTiming(PacketPtr pkt) if (pkt->result == Packet::Nacked) panic("Need to implement cache resending nacked packets!\n"); - if (pkt->isRequest() && blocked) - { + if (pkt->isRequest() && blocked) { DPRINTF(Cache,"Scheduling a retry while blocked\n"); mustSendRetry = true; return false; } - if (pkt->isResponse()) + if (pkt->isResponse()) { myCache()->handleResponse(pkt); - else { - //Check if we should do the snoop - if (pkt->flags & SNOOP_COMMIT) - myCache()->snoop(pkt); + } else { + myCache()->snoop(pkt); } return true; } +template +void +Cache::MemSidePort::recvRetry() +{ + if (recvRetryCommon()) { + return; + } + + DPRINTF(CachePort, "%s attempting to send a retry for MSHR\n", name()); + if (!cache->isMemSideBusRequested()) { + //This can happen if I am the owner of a block and see an upgrade + //while the block was in my WB Buffers. I just remove the + //wb and de-assert the masterRequest + waitingOnRetry = false; + return; + } + PacketPtr pkt = myCache()->getPacket(); + MSHR* mshr = (MSHR*) pkt->senderState; + //Copy the packet, it may be modified/destroyed elsewhere + PacketPtr copyPkt = new Packet(*pkt); + copyPkt->dataStatic(pkt->getPtr()); + mshr->pkt = copyPkt; + + bool success = sendTiming(pkt); + DPRINTF(Cache, "Address %x was %s in sending the timing request\n", + pkt->getAddr(), success ? "succesful" : "unsuccesful"); + + waitingOnRetry = !success; + if (waitingOnRetry) { + DPRINTF(CachePort, "%s now waiting on a retry\n", name()); + } + + myCache()->sendResult(pkt, mshr, success); + + if (success && cache->isMemSideBusRequested()) + { + DPRINTF(CachePort, "%s has more requests\n", name()); + //Still more to issue, rerequest in 1 cycle + new RequestEvent(this, curTick + 1); + } +} + + +template +void +Cache::MemSidePort::processRequestEvent() +{ + if (waitingOnRetry) + return; + //We have some responses to drain first + if (!drainList.empty()) { + if (!drainResponse()) { + // more responses to drain... re-request bus + scheduleRequestEvent(curTick + 1); + } + return; + } + + DPRINTF(CachePort, "%s trying to send a MSHR request\n", name()); + if (!isBusRequested()) { + //This can happen if I am the owner of a block and see an upgrade + //while the block was in my WB Buffers. I just remove the + //wb and de-assert the masterRequest + return; + } + + PacketPtr pkt = myCache()->getPacket(); + MSHR* mshr = (MSHR*) pkt->senderState; + //Copy the packet, it may be modified/destroyed elsewhere + PacketPtr copyPkt = new Packet(*pkt); + copyPkt->dataStatic(pkt->getPtr()); + mshr->pkt = copyPkt; + + bool success = sendTiming(pkt); + DPRINTF(Cache, "Address %x was %s in sending the timing request\n", + pkt->getAddr(), success ? "succesful" : "unsuccesful"); + + waitingOnRetry = !success; + if (waitingOnRetry) { + DPRINTF(CachePort, "%s now waiting on a retry\n", name()); + } + + myCache()->sendResult(pkt, mshr, success); + if (success && isBusRequested()) + { + DPRINTF(CachePort, "%s still more MSHR requests to send\n", name()); + //Still more to issue, rerequest in 1 cycle + scheduleRequestEvent(curTick+1); + } +} + + +template +void +Cache::MemSidePort::processResponseEvent() +{ + assert(transmitList.size()); + assert(transmitList.front().first <= curTick); + PacketPtr pkt = transmitList.front().second; + transmitList.pop_front(); + if (!transmitList.empty()) { + Tick time = transmitList.front().first; + responseEvent->schedule(time <= curTick ? curTick+1 : time); + } + + if (pkt->flags & NACKED_LINE) + pkt->result = Packet::Nacked; + else + pkt->result = Packet::Success; + pkt->makeTimingResponse(); + DPRINTF(CachePort, "%s attempting to send a response\n", name()); + if (!drainList.empty() || waitingOnRetry) { + //Already have a list, just append + drainList.push_back(pkt); + DPRINTF(CachePort, "%s appending response onto drain list\n", name()); + } + else if (!sendTiming(pkt)) { + //It failed, save it to list of drain events + DPRINTF(CachePort, "%s now waiting for a retry\n", name()); + drainList.push_back(pkt); + waitingOnRetry = true; + } + + // Check if we're done draining once this list is empty + if (drainList.empty() && transmitList.empty()) + myCache()->checkDrain(); +} + + template Tick Cache::MemSidePort::recvAtomic(PacketPtr pkt) @@ -1292,15 +1452,17 @@ template Cache:: CpuSidePort::CpuSidePort(const std::string &_name, Cache *_cache) - : BaseCache::CachePort(_name, _cache, true) + : BaseCache::CachePort(_name, _cache) { + responseEvent = new ResponseEvent(this); } template Cache:: MemSidePort::MemSidePort(const std::string &_name, Cache *_cache) - : BaseCache::CachePort(_name, _cache, false) + : BaseCache::CachePort(_name, _cache) { + responseEvent = new ResponseEvent(this); } -- cgit v1.2.3