diff options
Diffstat (limited to 'src/mem/cache/cache.cc')
-rw-r--r-- | src/mem/cache/cache.cc | 146 |
1 files changed, 79 insertions, 67 deletions
diff --git a/src/mem/cache/cache.cc b/src/mem/cache/cache.cc index b72ff4261..bded74643 100644 --- a/src/mem/cache/cache.cc +++ b/src/mem/cache/cache.cc @@ -161,7 +161,8 @@ Cache::satisfyRequest(PacketPtr pkt, CacheBlk *blk, ///////////////////////////////////////////////////// bool -Cache::access(PacketPtr pkt, CacheBlk *&blk, Cycles &lat) +Cache::access(PacketPtr pkt, CacheBlk *&blk, Cycles &lat, + PacketList &writebacks) { if (pkt->req->isUncacheable()) { @@ -173,91 +174,98 @@ Cache::access(PacketPtr pkt, CacheBlk *&blk, Cycles &lat) DPRINTF(Cache, "%s for %s\n", __func__, pkt->print()); - // lookupLatency is the latency in case the request is uncacheable. - lat = lookupLatency; - // flush and invalidate any existing block CacheBlk *old_blk(tags->findBlock(pkt->getAddr(), pkt->isSecure())); if (old_blk && old_blk->isValid()) { - BaseCache::evictBlock(old_blk, clockEdge(lat + forwardLatency)); + BaseCache::evictBlock(old_blk, writebacks); } blk = nullptr; + // lookupLatency is the latency in case the request is uncacheable. + lat = lookupLatency; return false; } - return BaseCache::access(pkt, blk, lat); + return BaseCache::access(pkt, blk, lat, writebacks); } void -Cache::doWritebacks(PacketPtr pkt, Tick forward_time) +Cache::doWritebacks(PacketList& writebacks, Tick forward_time) { - // We use forwardLatency here because we are copying writebacks to - // write buffer. - - // Call isCachedAbove for Writebacks, CleanEvicts and - // WriteCleans to discover if the block is cached above. - if (isCachedAbove(pkt)) { - if (pkt->cmd == MemCmd::CleanEvict) { - // Delete CleanEvict because cached copies exist above. The - // packet destructor will delete the request object because - // this is a non-snoop request packet which does not require a - // response. - delete pkt; - } else if (pkt->cmd == MemCmd::WritebackClean) { - // clean writeback, do not send since the block is - // still cached above - assert(writebackClean); - delete pkt; + while (!writebacks.empty()) { + PacketPtr wbPkt = writebacks.front(); + // We use forwardLatency here because we are copying writebacks to + // write buffer. + + // Call isCachedAbove for Writebacks, CleanEvicts and + // WriteCleans to discover if the block is cached above. + if (isCachedAbove(wbPkt)) { + if (wbPkt->cmd == MemCmd::CleanEvict) { + // Delete CleanEvict because cached copies exist above. The + // packet destructor will delete the request object because + // this is a non-snoop request packet which does not require a + // response. + delete wbPkt; + } else if (wbPkt->cmd == MemCmd::WritebackClean) { + // clean writeback, do not send since the block is + // still cached above + assert(writebackClean); + delete wbPkt; + } else { + assert(wbPkt->cmd == MemCmd::WritebackDirty || + wbPkt->cmd == MemCmd::WriteClean); + // Set BLOCK_CACHED flag in Writeback and send below, so that + // the Writeback does not reset the bit corresponding to this + // address in the snoop filter below. + wbPkt->setBlockCached(); + allocateWriteBuffer(wbPkt, forward_time); + } } else { - assert(pkt->cmd == MemCmd::WritebackDirty || - pkt->cmd == MemCmd::WriteClean); - // Set BLOCK_CACHED flag in Writeback and send below, so that - // the Writeback does not reset the bit corresponding to this - // address in the snoop filter below. - pkt->setBlockCached(); - allocateWriteBuffer(pkt, forward_time); + // If the block is not cached above, send packet below. Both + // CleanEvict and Writeback with BLOCK_CACHED flag cleared will + // reset the bit corresponding to this address in the snoop filter + // below. + allocateWriteBuffer(wbPkt, forward_time); } - } else { - // If the block is not cached above, send packet below. Both - // CleanEvict and Writeback with BLOCK_CACHED flag cleared will - // reset the bit corresponding to this address in the snoop filter - // below. - allocateWriteBuffer(pkt, forward_time); + writebacks.pop_front(); } } void -Cache::doWritebacksAtomic(PacketPtr pkt) +Cache::doWritebacksAtomic(PacketList& writebacks) { - // Call isCachedAbove for both Writebacks and CleanEvicts. If - // isCachedAbove returns true we set BLOCK_CACHED flag in Writebacks - // and discard CleanEvicts. - if (isCachedAbove(pkt, false)) { - if (pkt->cmd == MemCmd::WritebackDirty || - pkt->cmd == MemCmd::WriteClean) { - // Set BLOCK_CACHED flag in Writeback and send below, - // so that the Writeback does not reset the bit - // corresponding to this address in the snoop filter - // below. We can discard CleanEvicts because cached - // copies exist above. Atomic mode isCachedAbove - // modifies packet to set BLOCK_CACHED flag - memSidePort.sendAtomic(pkt); + while (!writebacks.empty()) { + PacketPtr wbPkt = writebacks.front(); + // Call isCachedAbove for both Writebacks and CleanEvicts. If + // isCachedAbove returns true we set BLOCK_CACHED flag in Writebacks + // and discard CleanEvicts. + if (isCachedAbove(wbPkt, false)) { + if (wbPkt->cmd == MemCmd::WritebackDirty || + wbPkt->cmd == MemCmd::WriteClean) { + // Set BLOCK_CACHED flag in Writeback and send below, + // so that the Writeback does not reset the bit + // corresponding to this address in the snoop filter + // below. We can discard CleanEvicts because cached + // copies exist above. Atomic mode isCachedAbove + // modifies packet to set BLOCK_CACHED flag + memSidePort.sendAtomic(wbPkt); + } + } else { + // If the block is not cached above, send packet below. Both + // CleanEvict and Writeback with BLOCK_CACHED flag cleared will + // reset the bit corresponding to this address in the snoop filter + // below. + memSidePort.sendAtomic(wbPkt); } - } else { - // If the block is not cached above, send packet below. Both - // CleanEvict and Writeback with BLOCK_CACHED flag cleared will - // reset the bit corresponding to this address in the snoop filter - // below. - memSidePort.sendAtomic(pkt); + writebacks.pop_front(); + // In case of CleanEvicts, the packet destructor will delete the + // request object because this is a non-snoop request packet which + // does not require a response. + delete wbPkt; } - - // In case of CleanEvicts, the packet destructor will delete the - // request object because this is a non-snoop request packet which - // does not require a response. - delete pkt; } + void Cache::recvTimingSnoopResp(PacketPtr pkt) { @@ -555,7 +563,8 @@ Cache::createMissPacket(PacketPtr cpu_pkt, CacheBlk *blk, Cycles -Cache::handleAtomicReqMiss(PacketPtr pkt, CacheBlk *&blk) +Cache::handleAtomicReqMiss(PacketPtr pkt, CacheBlk *&blk, + PacketList &writebacks) { // deal with the packets that go through the write path of // the cache, i.e. any evictions and writes @@ -617,7 +626,7 @@ Cache::handleAtomicReqMiss(PacketPtr pkt, CacheBlk *&blk) // the write to a whole line const bool allocate = allocOnFill(pkt->cmd) && (!writeAllocator || writeAllocator->allocate()); - blk = handleFill(bus_pkt, blk, allocate); + blk = handleFill(bus_pkt, blk, writebacks, allocate); assert(blk != NULL); is_invalidate = false; satisfyRequest(pkt, blk); @@ -625,7 +634,8 @@ Cache::handleAtomicReqMiss(PacketPtr pkt, CacheBlk *&blk) bus_pkt->cmd == MemCmd::UpgradeResp) { // we're updating cache state to allow us to // satisfy the upstream request from the cache - blk = handleFill(bus_pkt, blk, allocOnFill(pkt->cmd)); + blk = handleFill(bus_pkt, blk, writebacks, + allocOnFill(pkt->cmd)); satisfyRequest(pkt, blk); maintainClusivity(pkt->fromCache(), blk); } else { @@ -1011,15 +1021,17 @@ Cache::handleSnoop(PacketPtr pkt, CacheBlk *blk, bool is_timing, DPRINTF(CacheVerbose, "%s: packet (snoop) %s found block: %s\n", __func__, pkt->print(), blk->print()); PacketPtr wb_pkt = writecleanBlk(blk, pkt->req->getDest(), pkt->id); + PacketList writebacks; + writebacks.push_back(wb_pkt); if (is_timing) { // anything that is merely forwarded pays for the forward // latency and the delay provided by the crossbar Tick forward_time = clockEdge(forwardLatency) + pkt->headerDelay; - doWritebacks(wb_pkt, forward_time); + doWritebacks(writebacks, forward_time); } else { - doWritebacksAtomic(wb_pkt); + doWritebacksAtomic(writebacks); } pkt->setSatisfied(); } |