1/* 2 * Copyright (c) 2010-2019 ARM Limited 3 * All rights reserved. 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software --- 147 unchanged lines hidden (view full) --- 156 157///////////////////////////////////////////////////// 158// 159// Access path: requests coming in from the CPU side 160// 161///////////////////////////////////////////////////// 162 163bool |
164Cache::access(PacketPtr pkt, CacheBlk *&blk, Cycles &lat, 165 PacketList &writebacks) |
166{ 167 168 if (pkt->req->isUncacheable()) { 169 assert(pkt->isRequest()); 170 171 chatty_assert(!(isReadOnly && pkt->isWrite()), 172 "Should never see a write in a read-only cache %s\n", 173 name()); 174 175 DPRINTF(Cache, "%s for %s\n", __func__, pkt->print()); 176 |
177 // flush and invalidate any existing block 178 CacheBlk *old_blk(tags->findBlock(pkt->getAddr(), pkt->isSecure())); 179 if (old_blk && old_blk->isValid()) { |
180 BaseCache::evictBlock(old_blk, writebacks); |
181 } 182 183 blk = nullptr; |
184 // lookupLatency is the latency in case the request is uncacheable. 185 lat = lookupLatency; |
186 return false; 187 } 188 |
189 return BaseCache::access(pkt, blk, lat, writebacks); |
190} 191 192void |
193Cache::doWritebacks(PacketList& writebacks, Tick forward_time) |
194{ |
195 while (!writebacks.empty()) { 196 PacketPtr wbPkt = writebacks.front(); 197 // We use forwardLatency here because we are copying writebacks to 198 // write buffer. |
199 |
200 // Call isCachedAbove for Writebacks, CleanEvicts and 201 // WriteCleans to discover if the block is cached above. 202 if (isCachedAbove(wbPkt)) { 203 if (wbPkt->cmd == MemCmd::CleanEvict) { 204 // Delete CleanEvict because cached copies exist above. The 205 // packet destructor will delete the request object because 206 // this is a non-snoop request packet which does not require a 207 // response. 208 delete wbPkt; 209 } else if (wbPkt->cmd == MemCmd::WritebackClean) { 210 // clean writeback, do not send since the block is 211 // still cached above 212 assert(writebackClean); 213 delete wbPkt; 214 } else { 215 assert(wbPkt->cmd == MemCmd::WritebackDirty || 216 wbPkt->cmd == MemCmd::WriteClean); 217 // Set BLOCK_CACHED flag in Writeback and send below, so that 218 // the Writeback does not reset the bit corresponding to this 219 // address in the snoop filter below. 220 wbPkt->setBlockCached(); 221 allocateWriteBuffer(wbPkt, forward_time); 222 } |
223 } else { |
224 // If the block is not cached above, send packet below. Both 225 // CleanEvict and Writeback with BLOCK_CACHED flag cleared will 226 // reset the bit corresponding to this address in the snoop filter 227 // below. 228 allocateWriteBuffer(wbPkt, forward_time); |
229 } |
230 writebacks.pop_front(); |
231 } 232} 233 234void |
235Cache::doWritebacksAtomic(PacketList& writebacks) |
236{ |
237 while (!writebacks.empty()) { 238 PacketPtr wbPkt = writebacks.front(); 239 // Call isCachedAbove for both Writebacks and CleanEvicts. If 240 // isCachedAbove returns true we set BLOCK_CACHED flag in Writebacks 241 // and discard CleanEvicts. 242 if (isCachedAbove(wbPkt, false)) { 243 if (wbPkt->cmd == MemCmd::WritebackDirty || 244 wbPkt->cmd == MemCmd::WriteClean) { 245 // Set BLOCK_CACHED flag in Writeback and send below, 246 // so that the Writeback does not reset the bit 247 // corresponding to this address in the snoop filter 248 // below. We can discard CleanEvicts because cached 249 // copies exist above. Atomic mode isCachedAbove 250 // modifies packet to set BLOCK_CACHED flag 251 memSidePort.sendAtomic(wbPkt); 252 } 253 } else { 254 // If the block is not cached above, send packet below. Both 255 // CleanEvict and Writeback with BLOCK_CACHED flag cleared will 256 // reset the bit corresponding to this address in the snoop filter 257 // below. 258 memSidePort.sendAtomic(wbPkt); |
259 } |
260 writebacks.pop_front(); 261 // In case of CleanEvicts, the packet destructor will delete the 262 // request object because this is a non-snoop request packet which 263 // does not require a response. 264 delete wbPkt; |
265 } |
266} 267 |
268 |
269void 270Cache::recvTimingSnoopResp(PacketPtr pkt) 271{ 272 DPRINTF(Cache, "%s for %s\n", __func__, pkt->print()); 273 274 // determine if the response is from a snoop request we created 275 // (in which case it should be in the outstandingSnoop), or if we 276 // merely forwarded someone else's snoop request --- 281 unchanged lines hidden (view full) --- 558 pkt->allocate(); 559 DPRINTF(Cache, "%s: created %s from %s\n", __func__, pkt->print(), 560 cpu_pkt->print()); 561 return pkt; 562} 563 564 565Cycles |
566Cache::handleAtomicReqMiss(PacketPtr pkt, CacheBlk *&blk, 567 PacketList &writebacks) |
568{ 569 // deal with the packets that go through the write path of 570 // the cache, i.e. any evictions and writes 571 if (pkt->isEviction() || pkt->cmd == MemCmd::WriteClean || 572 (pkt->req->isUncacheable() && pkt->isWrite())) { 573 Cycles latency = ticksToCycles(memSidePort.sendAtomic(pkt)); 574 575 // at this point, if the request was an uncacheable write --- 45 unchanged lines hidden (view full) --- 621 pkt->copyError(bus_pkt); 622 } else if (pkt->isWholeLineWrite(blkSize)) { 623 // note the use of pkt, not bus_pkt here. 624 625 // write-line request to the cache that promoted 626 // the write to a whole line 627 const bool allocate = allocOnFill(pkt->cmd) && 628 (!writeAllocator || writeAllocator->allocate()); |
629 blk = handleFill(bus_pkt, blk, writebacks, allocate); |
630 assert(blk != NULL); 631 is_invalidate = false; 632 satisfyRequest(pkt, blk); 633 } else if (bus_pkt->isRead() || 634 bus_pkt->cmd == MemCmd::UpgradeResp) { 635 // we're updating cache state to allow us to 636 // satisfy the upstream request from the cache |
637 blk = handleFill(bus_pkt, blk, writebacks, 638 allocOnFill(pkt->cmd)); |
639 satisfyRequest(pkt, blk); 640 maintainClusivity(pkt->fromCache(), blk); 641 } else { 642 // we're satisfying the upstream request without 643 // modifying cache state, e.g., a write-through 644 pkt->makeAtomicResponse(); 645 } 646 } --- 369 unchanged lines hidden (view full) --- 1016 1017 bool respond = false; 1018 bool blk_valid = blk && blk->isValid(); 1019 if (pkt->isClean()) { 1020 if (blk_valid && blk->isDirty()) { 1021 DPRINTF(CacheVerbose, "%s: packet (snoop) %s found block: %s\n", 1022 __func__, pkt->print(), blk->print()); 1023 PacketPtr wb_pkt = writecleanBlk(blk, pkt->req->getDest(), pkt->id); |
1024 PacketList writebacks; 1025 writebacks.push_back(wb_pkt); |
1026 1027 if (is_timing) { 1028 // anything that is merely forwarded pays for the forward 1029 // latency and the delay provided by the crossbar 1030 Tick forward_time = clockEdge(forwardLatency) + 1031 pkt->headerDelay; |
1032 doWritebacks(writebacks, forward_time); |
1033 } else { |
1034 doWritebacksAtomic(writebacks); |
1035 } 1036 pkt->setSatisfied(); 1037 } 1038 } else if (!blk_valid) { 1039 DPRINTF(CacheVerbose, "%s: snoop miss for %s\n", __func__, 1040 pkt->print()); 1041 if (is_deferred) { 1042 // we no longer have the block, and will not respond, but a --- 359 unchanged lines hidden --- |