cache.cc (11197:f8fdd931e674) | cache.cc (11199:929fd978ab4e) |
---|---|
1/* 2 * Copyright (c) 2010-2015 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 --- 56 unchanged lines hidden (view full) --- 65 66Cache::Cache(const CacheParams *p) 67 : BaseCache(p, p->system->cacheLineSize()), 68 tags(p->tags), 69 prefetcher(p->prefetcher), 70 doFastWrites(true), 71 prefetchOnAccess(p->prefetch_on_access), 72 clusivity(p->clusivity), | 1/* 2 * Copyright (c) 2010-2015 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 --- 56 unchanged lines hidden (view full) --- 65 66Cache::Cache(const CacheParams *p) 67 : BaseCache(p, p->system->cacheLineSize()), 68 tags(p->tags), 69 prefetcher(p->prefetcher), 70 doFastWrites(true), 71 prefetchOnAccess(p->prefetch_on_access), 72 clusivity(p->clusivity), |
73 writebackClean(p->writeback_clean), |
|
73 tempBlockWriteback(nullptr), 74 writebackTempBlockAtomicEvent(this, false, 75 EventBase::Delayed_Writeback_Pri) 76{ 77 tempBlock = new CacheBlk(); 78 tempBlock->data = new uint8_t[blkSize]; 79 80 cpuSidePort = new CpuSidePort(p->name + ".cpu_side", this, --- 231 unchanged lines hidden (view full) --- 312 if (pkt->req->isUncacheable()) { 313 DPRINTF(Cache, "%s%s addr %#llx uncacheable\n", pkt->cmdString(), 314 pkt->req->isInstFetch() ? " (ifetch)" : "", 315 pkt->getAddr()); 316 317 // flush and invalidate any existing block 318 CacheBlk *old_blk(tags->findBlock(pkt->getAddr(), pkt->isSecure())); 319 if (old_blk && old_blk->isValid()) { | 74 tempBlockWriteback(nullptr), 75 writebackTempBlockAtomicEvent(this, false, 76 EventBase::Delayed_Writeback_Pri) 77{ 78 tempBlock = new CacheBlk(); 79 tempBlock->data = new uint8_t[blkSize]; 80 81 cpuSidePort = new CpuSidePort(p->name + ".cpu_side", this, --- 231 unchanged lines hidden (view full) --- 313 if (pkt->req->isUncacheable()) { 314 DPRINTF(Cache, "%s%s addr %#llx uncacheable\n", pkt->cmdString(), 315 pkt->req->isInstFetch() ? " (ifetch)" : "", 316 pkt->getAddr()); 317 318 // flush and invalidate any existing block 319 CacheBlk *old_blk(tags->findBlock(pkt->getAddr(), pkt->isSecure())); 320 if (old_blk && old_blk->isValid()) { |
320 if (old_blk->isDirty()) | 321 if (old_blk->isDirty() || writebackClean) |
321 writebacks.push_back(writebackBlk(old_blk)); 322 else 323 writebacks.push_back(cleanEvictBlk(old_blk)); 324 tags->invalidate(old_blk); 325 old_blk->invalidate(); 326 } 327 328 blk = NULL; --- 9 unchanged lines hidden (view full) --- 338 blk = tags->accessBlock(pkt->getAddr(), pkt->isSecure(), lat, id); 339 340 DPRINTF(Cache, "%s%s addr %#llx size %d (%s) %s\n", pkt->cmdString(), 341 pkt->req->isInstFetch() ? " (ifetch)" : "", 342 pkt->getAddr(), pkt->getSize(), pkt->isSecure() ? "s" : "ns", 343 blk ? "hit " + blk->print() : "miss"); 344 345 | 322 writebacks.push_back(writebackBlk(old_blk)); 323 else 324 writebacks.push_back(cleanEvictBlk(old_blk)); 325 tags->invalidate(old_blk); 326 old_blk->invalidate(); 327 } 328 329 blk = NULL; --- 9 unchanged lines hidden (view full) --- 339 blk = tags->accessBlock(pkt->getAddr(), pkt->isSecure(), lat, id); 340 341 DPRINTF(Cache, "%s%s addr %#llx size %d (%s) %s\n", pkt->cmdString(), 342 pkt->req->isInstFetch() ? " (ifetch)" : "", 343 pkt->getAddr(), pkt->getSize(), pkt->isSecure() ? "s" : "ns", 344 blk ? "hit " + blk->print() : "miss"); 345 346 |
346 if (pkt->evictingBlock()) { | 347 if (pkt->isEviction()) { |
347 // We check for presence of block in above caches before issuing 348 // Writeback or CleanEvict to write buffer. Therefore the only 349 // possible cases can be of a CleanEvict packet coming from above 350 // encountering a Writeback generated in this cache peer cache and 351 // waiting in the write buffer. Cases of upper level peer caches 352 // generating CleanEvict and Writeback or simply CleanEvict and 353 // CleanEvict almost simultaneously will be caught by snoops sent out 354 // by crossbar. 355 std::vector<MSHR *> outgoing; 356 if (writeBuffer.findMatches(pkt->getAddr(), pkt->isSecure(), 357 outgoing)) { 358 assert(outgoing.size() == 1); | 348 // We check for presence of block in above caches before issuing 349 // Writeback or CleanEvict to write buffer. Therefore the only 350 // possible cases can be of a CleanEvict packet coming from above 351 // encountering a Writeback generated in this cache peer cache and 352 // waiting in the write buffer. Cases of upper level peer caches 353 // generating CleanEvict and Writeback or simply CleanEvict and 354 // CleanEvict almost simultaneously will be caught by snoops sent out 355 // by crossbar. 356 std::vector<MSHR *> outgoing; 357 if (writeBuffer.findMatches(pkt->getAddr(), pkt->isSecure(), 358 outgoing)) { 359 assert(outgoing.size() == 1); |
359 PacketPtr wbPkt = outgoing[0]->getTarget()->pkt; 360 assert(pkt->cmd == MemCmd::CleanEvict && 361 wbPkt->cmd == MemCmd::Writeback); 362 // As the CleanEvict is coming from above, it would have snooped 363 // into other peer caches of the same level while traversing the 364 // crossbar. If a copy of the block had been found, the CleanEvict 365 // would have been deleted in the crossbar. Now that the 366 // CleanEvict is here we can be sure none of the other upper level 367 // caches connected to this cache have the block, so we can clear 368 // the BLOCK_CACHED flag in the Writeback if set and discard the 369 // CleanEvict by returning true. 370 wbPkt->clearBlockCached(); 371 return true; | 360 MSHR *wb_entry = outgoing[0]; 361 assert(wb_entry->getNumTargets() == 1); 362 PacketPtr wbPkt = wb_entry->getTarget()->pkt; 363 assert(wbPkt->isWriteback()); 364 365 if (pkt->isCleanEviction()) { 366 // The CleanEvict and WritebackClean snoops into other 367 // peer caches of the same level while traversing the 368 // crossbar. If a copy of the block is found, the 369 // packet is deleted in the crossbar. Hence, none of 370 // the other upper level caches connected to this 371 // cache have the block, so we can clear the 372 // BLOCK_CACHED flag in the Writeback if set and 373 // discard the CleanEvict by returning true. 374 wbPkt->clearBlockCached(); 375 return true; 376 } else { 377 assert(pkt->cmd == MemCmd::WritebackDirty); 378 // Dirty writeback from above trumps our clean 379 // writeback... discard here 380 // Note: markInService will remove entry from writeback buffer. 381 markInService(wb_entry, false); 382 delete wbPkt; 383 } |
372 } 373 } 374 375 // Writeback handling is special case. We can write the block into 376 // the cache without having a writeable copy (or any copy at all). | 384 } 385 } 386 387 // Writeback handling is special case. We can write the block into 388 // the cache without having a writeable copy (or any copy at all). |
377 if (pkt->cmd == MemCmd::Writeback) { | 389 if (pkt->isWriteback()) { |
378 assert(blkSize == pkt->getSize()); | 390 assert(blkSize == pkt->getSize()); |
391 392 // we could get a clean writeback while we are having 393 // outstanding accesses to a block, do the simple thing for 394 // now and drop the clean writeback so that we do not upset 395 // any ordering/decisions about ownership already taken 396 if (pkt->cmd == MemCmd::WritebackClean && 397 mshrQueue.findMatch(pkt->getAddr(), pkt->isSecure())) { 398 DPRINTF(Cache, "Clean writeback %#llx to block with MSHR, " 399 "dropping\n", pkt->getAddr()); 400 return true; 401 } 402 |
|
379 if (blk == NULL) { 380 // need to do a replacement 381 blk = allocateBlock(pkt->getAddr(), pkt->isSecure(), writebacks); 382 if (blk == NULL) { 383 // no replaceable block available: give up, fwd to next level. 384 incMissCount(pkt); 385 return false; 386 } 387 tags->insertBlock(pkt, blk); 388 389 blk->status = (BlkValid | BlkReadable); 390 if (pkt->isSecure()) { 391 blk->status |= BlkSecure; 392 } 393 } | 403 if (blk == NULL) { 404 // need to do a replacement 405 blk = allocateBlock(pkt->getAddr(), pkt->isSecure(), writebacks); 406 if (blk == NULL) { 407 // no replaceable block available: give up, fwd to next level. 408 incMissCount(pkt); 409 return false; 410 } 411 tags->insertBlock(pkt, blk); 412 413 blk->status = (BlkValid | BlkReadable); 414 if (pkt->isSecure()) { 415 blk->status |= BlkSecure; 416 } 417 } |
394 blk->status |= BlkDirty; | 418 // only mark the block dirty if we got a writeback command, 419 // and leave it as is for a clean writeback 420 if (pkt->cmd == MemCmd::WritebackDirty) { 421 blk->status |= BlkDirty; 422 } |
395 // if shared is not asserted we got the writeback in modified 396 // state, if it is asserted we are in the owned state 397 if (!pkt->sharedAsserted()) { 398 blk->status |= BlkWritable; 399 } 400 // nothing else to do; writeback doesn't expect response 401 assert(!pkt->needsResponse()); 402 std::memcpy(blk->data, pkt->getConstPtr<uint8_t>(), blkSize); --- 55 unchanged lines hidden (view full) --- 458 // in Writebacks and discard CleanEvicts. 459 if (isCachedAbove(wbPkt)) { 460 if (wbPkt->cmd == MemCmd::CleanEvict) { 461 // Delete CleanEvict because cached copies exist above. The 462 // packet destructor will delete the request object because 463 // this is a non-snoop request packet which does not require a 464 // response. 465 delete wbPkt; | 423 // if shared is not asserted we got the writeback in modified 424 // state, if it is asserted we are in the owned state 425 if (!pkt->sharedAsserted()) { 426 blk->status |= BlkWritable; 427 } 428 // nothing else to do; writeback doesn't expect response 429 assert(!pkt->needsResponse()); 430 std::memcpy(blk->data, pkt->getConstPtr<uint8_t>(), blkSize); --- 55 unchanged lines hidden (view full) --- 486 // in Writebacks and discard CleanEvicts. 487 if (isCachedAbove(wbPkt)) { 488 if (wbPkt->cmd == MemCmd::CleanEvict) { 489 // Delete CleanEvict because cached copies exist above. The 490 // packet destructor will delete the request object because 491 // this is a non-snoop request packet which does not require a 492 // response. 493 delete wbPkt; |
494 } else if (wbPkt->cmd == MemCmd::WritebackClean) { 495 // clean writeback, do not send since the block is 496 // still cached above 497 assert(writebackClean); 498 delete wbPkt; |
|
466 } else { | 499 } else { |
500 assert(wbPkt->cmd == MemCmd::WritebackDirty); |
|
467 // Set BLOCK_CACHED flag in Writeback and send below, so that 468 // the Writeback does not reset the bit corresponding to this 469 // address in the snoop filter below. 470 wbPkt->setBlockCached(); 471 allocateWriteBuffer(wbPkt, forward_time); 472 } 473 } else { 474 // If the block is not cached above, send packet below. Both --- 10 unchanged lines hidden (view full) --- 485Cache::doWritebacksAtomic(PacketList& writebacks) 486{ 487 while (!writebacks.empty()) { 488 PacketPtr wbPkt = writebacks.front(); 489 // Call isCachedAbove for both Writebacks and CleanEvicts. If 490 // isCachedAbove returns true we set BLOCK_CACHED flag in Writebacks 491 // and discard CleanEvicts. 492 if (isCachedAbove(wbPkt, false)) { | 501 // Set BLOCK_CACHED flag in Writeback and send below, so that 502 // the Writeback does not reset the bit corresponding to this 503 // address in the snoop filter below. 504 wbPkt->setBlockCached(); 505 allocateWriteBuffer(wbPkt, forward_time); 506 } 507 } else { 508 // If the block is not cached above, send packet below. Both --- 10 unchanged lines hidden (view full) --- 519Cache::doWritebacksAtomic(PacketList& writebacks) 520{ 521 while (!writebacks.empty()) { 522 PacketPtr wbPkt = writebacks.front(); 523 // Call isCachedAbove for both Writebacks and CleanEvicts. If 524 // isCachedAbove returns true we set BLOCK_CACHED flag in Writebacks 525 // and discard CleanEvicts. 526 if (isCachedAbove(wbPkt, false)) { |
493 if (wbPkt->cmd == MemCmd::Writeback) { | 527 if (wbPkt->cmd == MemCmd::WritebackDirty) { |
494 // Set BLOCK_CACHED flag in Writeback and send below, 495 // so that the Writeback does not reset the bit 496 // corresponding to this address in the snoop filter 497 // below. We can discard CleanEvicts because cached 498 // copies exist above. Atomic mode isCachedAbove 499 // modifies packet to set BLOCK_CACHED flag 500 memSidePort->sendAtomic(wbPkt); 501 } --- 187 unchanged lines hidden (view full) --- 689 690 // In this case we are considering request_time that takes 691 // into account the delay of the xbar, if any, and just 692 // lat, neglecting responseLatency, modelling hit latency 693 // just as lookupLatency or or the value of lat overriden 694 // by access(), that calls accessBlock() function. 695 cpuSidePort->schedTimingResp(pkt, request_time, true); 696 } else { | 528 // Set BLOCK_CACHED flag in Writeback and send below, 529 // so that the Writeback does not reset the bit 530 // corresponding to this address in the snoop filter 531 // below. We can discard CleanEvicts because cached 532 // copies exist above. Atomic mode isCachedAbove 533 // modifies packet to set BLOCK_CACHED flag 534 memSidePort->sendAtomic(wbPkt); 535 } --- 187 unchanged lines hidden (view full) --- 723 724 // In this case we are considering request_time that takes 725 // into account the delay of the xbar, if any, and just 726 // lat, neglecting responseLatency, modelling hit latency 727 // just as lookupLatency or or the value of lat overriden 728 // by access(), that calls accessBlock() function. 729 cpuSidePort->schedTimingResp(pkt, request_time, true); 730 } else { |
731 DPRINTF(Cache, "%s satisfied %s addr %#llx, no response needed\n", 732 __func__, pkt->cmdString(), pkt->getAddr(), 733 pkt->getSize()); 734 |
|
697 // queue the packet for deletion, as the sending cache is 698 // still relying on it; if the block is found in access(), 699 // CleanEvict and Writeback messages will be deleted 700 // here as well 701 pendingDelete.reset(pkt); 702 } 703 } else { 704 // miss --- 55 unchanged lines hidden (view full) --- 760 /// MSHR hit 761 /// @note writebacks will be checked in getNextMSHR() 762 /// for any conflicting requests to the same block 763 764 //@todo remove hw_pf here 765 766 // Coalesce unless it was a software prefetch (see above). 767 if (pkt) { | 735 // queue the packet for deletion, as the sending cache is 736 // still relying on it; if the block is found in access(), 737 // CleanEvict and Writeback messages will be deleted 738 // here as well 739 pendingDelete.reset(pkt); 740 } 741 } else { 742 // miss --- 55 unchanged lines hidden (view full) --- 798 /// MSHR hit 799 /// @note writebacks will be checked in getNextMSHR() 800 /// for any conflicting requests to the same block 801 802 //@todo remove hw_pf here 803 804 // Coalesce unless it was a software prefetch (see above). 805 if (pkt) { |
768 assert(pkt->cmd != MemCmd::Writeback); 769 // CleanEvicts corresponding to blocks which have outstanding 770 // requests in MSHRs can be deleted here. | 806 assert(!pkt->isWriteback()); 807 // CleanEvicts corresponding to blocks which have 808 // outstanding requests in MSHRs are simply sunk here |
771 if (pkt->cmd == MemCmd::CleanEvict) { 772 pendingDelete.reset(pkt); 773 } else { 774 DPRINTF(Cache, "%s coalescing MSHR for %s addr %#llx size %d\n", 775 __func__, pkt->cmdString(), pkt->getAddr(), 776 pkt->getSize()); 777 778 assert(pkt->req->masterId() < system->maxMasters()); --- 36 unchanged lines hidden (view full) --- 815 // no MSHR 816 assert(pkt->req->masterId() < system->maxMasters()); 817 if (pkt->req->isUncacheable()) { 818 mshr_uncacheable[pkt->cmdToIndex()][pkt->req->masterId()]++; 819 } else { 820 mshr_misses[pkt->cmdToIndex()][pkt->req->masterId()]++; 821 } 822 | 809 if (pkt->cmd == MemCmd::CleanEvict) { 810 pendingDelete.reset(pkt); 811 } else { 812 DPRINTF(Cache, "%s coalescing MSHR for %s addr %#llx size %d\n", 813 __func__, pkt->cmdString(), pkt->getAddr(), 814 pkt->getSize()); 815 816 assert(pkt->req->masterId() < system->maxMasters()); --- 36 unchanged lines hidden (view full) --- 853 // no MSHR 854 assert(pkt->req->masterId() < system->maxMasters()); 855 if (pkt->req->isUncacheable()) { 856 mshr_uncacheable[pkt->cmdToIndex()][pkt->req->masterId()]++; 857 } else { 858 mshr_misses[pkt->cmdToIndex()][pkt->req->masterId()]++; 859 } 860 |
823 if (pkt->evictingBlock() || | 861 if (pkt->isEviction() || |
824 (pkt->req->isUncacheable() && pkt->isWrite())) { 825 // We use forward_time here because there is an 826 // uncached memory write, forwarded to WriteBuffer. 827 allocateWriteBuffer(pkt, forward_time); 828 } else { 829 if (blk && blk->isValid()) { 830 // should have flushed and have no valid block 831 assert(!pkt->req->isUncacheable()); --- 51 unchanged lines hidden (view full) --- 883 // and the cache could have filled again before we actually 884 // send out the forwarded uncacheable request (blk could thus 885 // be non-null) 886 return NULL; 887 } 888 889 if (!blkValid && 890 (cpu_pkt->isUpgrade() || | 862 (pkt->req->isUncacheable() && pkt->isWrite())) { 863 // We use forward_time here because there is an 864 // uncached memory write, forwarded to WriteBuffer. 865 allocateWriteBuffer(pkt, forward_time); 866 } else { 867 if (blk && blk->isValid()) { 868 // should have flushed and have no valid block 869 assert(!pkt->req->isUncacheable()); --- 51 unchanged lines hidden (view full) --- 921 // and the cache could have filled again before we actually 922 // send out the forwarded uncacheable request (blk could thus 923 // be non-null) 924 return NULL; 925 } 926 927 if (!blkValid && 928 (cpu_pkt->isUpgrade() || |
891 cpu_pkt->evictingBlock())) { | 929 cpu_pkt->isEviction())) { |
892 // Writebacks that weren't allocated in access() and upgrades 893 // from upper-level caches that missed completely just go 894 // through. 895 return NULL; 896 } 897 898 assert(cpu_pkt->needsResponse()); 899 --- 203 unchanged lines hidden (view full) --- 1103 } else { 1104 // the writeback/clean eviction happens after the call to 1105 // recvAtomic has finished (but before any successive 1106 // calls), so that the response handling from the fill is 1107 // allowed to happen first 1108 schedule(writebackTempBlockAtomicEvent, curTick()); 1109 } 1110 | 930 // Writebacks that weren't allocated in access() and upgrades 931 // from upper-level caches that missed completely just go 932 // through. 933 return NULL; 934 } 935 936 assert(cpu_pkt->needsResponse()); 937 --- 203 unchanged lines hidden (view full) --- 1141 } else { 1142 // the writeback/clean eviction happens after the call to 1143 // recvAtomic has finished (but before any successive 1144 // calls), so that the response handling from the fill is 1145 // allowed to happen first 1146 schedule(writebackTempBlockAtomicEvent, curTick()); 1147 } 1148 |
1111 tempBlockWriteback = blk->isDirty() ? writebackBlk(blk) : 1112 cleanEvictBlk(blk); | 1149 tempBlockWriteback = (blk->isDirty() || writebackClean) ? 1150 writebackBlk(blk) : cleanEvictBlk(blk); |
1113 blk->invalidate(); 1114 } 1115 1116 if (pkt->needsResponse()) { 1117 pkt->makeAtomicResponse(); 1118 } 1119 1120 return lat * clockPeriod(); --- 332 unchanged lines hidden (view full) --- 1453 doWritebacks(writebacks, forward_time); 1454 1455 // if we used temp block, check to see if its valid and then clear it out 1456 if (blk == tempBlock && tempBlock->isValid()) { 1457 // We use forwardLatency here because we are copying 1458 // Writebacks/CleanEvicts to write buffer. It specifies the latency to 1459 // allocate an internal buffer and to schedule an event to the 1460 // queued port. | 1151 blk->invalidate(); 1152 } 1153 1154 if (pkt->needsResponse()) { 1155 pkt->makeAtomicResponse(); 1156 } 1157 1158 return lat * clockPeriod(); --- 332 unchanged lines hidden (view full) --- 1491 doWritebacks(writebacks, forward_time); 1492 1493 // if we used temp block, check to see if its valid and then clear it out 1494 if (blk == tempBlock && tempBlock->isValid()) { 1495 // We use forwardLatency here because we are copying 1496 // Writebacks/CleanEvicts to write buffer. It specifies the latency to 1497 // allocate an internal buffer and to schedule an event to the 1498 // queued port. |
1461 if (blk->isDirty()) { | 1499 if (blk->isDirty() || writebackClean) { |
1462 PacketPtr wbPkt = writebackBlk(blk); 1463 allocateWriteBuffer(wbPkt, forward_time); 1464 // Set BLOCK_CACHED flag if cached above. 1465 if (isCachedAbove(wbPkt)) 1466 wbPkt->setBlockCached(); 1467 } else { 1468 PacketPtr wcPkt = cleanEvictBlk(blk); 1469 // Check to see if block is cached above. If not allocate --- 9 unchanged lines hidden (view full) --- 1479 DPRINTF(Cache, "Leaving %s with %s for addr %#llx\n", __func__, 1480 pkt->cmdString(), pkt->getAddr()); 1481 delete pkt; 1482} 1483 1484PacketPtr 1485Cache::writebackBlk(CacheBlk *blk) 1486{ | 1500 PacketPtr wbPkt = writebackBlk(blk); 1501 allocateWriteBuffer(wbPkt, forward_time); 1502 // Set BLOCK_CACHED flag if cached above. 1503 if (isCachedAbove(wbPkt)) 1504 wbPkt->setBlockCached(); 1505 } else { 1506 PacketPtr wcPkt = cleanEvictBlk(blk); 1507 // Check to see if block is cached above. If not allocate --- 9 unchanged lines hidden (view full) --- 1517 DPRINTF(Cache, "Leaving %s with %s for addr %#llx\n", __func__, 1518 pkt->cmdString(), pkt->getAddr()); 1519 delete pkt; 1520} 1521 1522PacketPtr 1523Cache::writebackBlk(CacheBlk *blk) 1524{ |
1487 chatty_assert(!isReadOnly, "Writeback from read-only cache"); 1488 assert(blk && blk->isValid() && blk->isDirty()); | 1525 chatty_assert(!isReadOnly || writebackClean, 1526 "Writeback from read-only cache"); 1527 assert(blk && blk->isValid() && (blk->isDirty() || writebackClean)); |
1489 1490 writebacks[Request::wbMasterId]++; 1491 | 1528 1529 writebacks[Request::wbMasterId]++; 1530 |
1492 Request *writebackReq = 1493 new Request(tags->regenerateBlkAddr(blk->tag, blk->set), blkSize, 0, 1494 Request::wbMasterId); | 1531 Request *req = new Request(tags->regenerateBlkAddr(blk->tag, blk->set), 1532 blkSize, 0, Request::wbMasterId); |
1495 if (blk->isSecure()) | 1533 if (blk->isSecure()) |
1496 writebackReq->setFlags(Request::SECURE); | 1534 req->setFlags(Request::SECURE); |
1497 | 1535 |
1498 writebackReq->taskId(blk->task_id); | 1536 req->taskId(blk->task_id); |
1499 blk->task_id= ContextSwitchTaskId::Unknown; 1500 blk->tickInserted = curTick(); 1501 | 1537 blk->task_id= ContextSwitchTaskId::Unknown; 1538 blk->tickInserted = curTick(); 1539 |
1502 PacketPtr writeback = new Packet(writebackReq, MemCmd::Writeback); | 1540 PacketPtr pkt = 1541 new Packet(req, blk->isDirty() ? 1542 MemCmd::WritebackDirty : MemCmd::WritebackClean); 1543 1544 DPRINTF(Cache, "Create Writeback %#llx writable: %d, dirty: %d\n", 1545 pkt->getAddr(), blk->isWritable(), blk->isDirty()); 1546 |
1503 if (blk->isWritable()) { 1504 // not asserting shared means we pass the block in modified 1505 // state, mark our own block non-writeable 1506 blk->status &= ~BlkWritable; 1507 } else { 1508 // we are in the owned state, tell the receiver | 1547 if (blk->isWritable()) { 1548 // not asserting shared means we pass the block in modified 1549 // state, mark our own block non-writeable 1550 blk->status &= ~BlkWritable; 1551 } else { 1552 // we are in the owned state, tell the receiver |
1509 writeback->assertShared(); | 1553 pkt->assertShared(); |
1510 } 1511 | 1554 } 1555 |
1512 writeback->allocate(); 1513 std::memcpy(writeback->getPtr<uint8_t>(), blk->data, blkSize); 1514 | 1556 // make sure the block is not marked dirty |
1515 blk->status &= ~BlkDirty; | 1557 blk->status &= ~BlkDirty; |
1516 return writeback; | 1558 1559 pkt->allocate(); 1560 std::memcpy(pkt->getPtr<uint8_t>(), blk->data, blkSize); 1561 1562 return pkt; |
1517} 1518 1519PacketPtr 1520Cache::cleanEvictBlk(CacheBlk *blk) 1521{ | 1563} 1564 1565PacketPtr 1566Cache::cleanEvictBlk(CacheBlk *blk) 1567{ |
1568 assert(!writebackClean); |
|
1522 assert(blk && blk->isValid() && !blk->isDirty()); 1523 // Creating a zero sized write, a message to the snoop filter 1524 Request *req = 1525 new Request(tags->regenerateBlkAddr(blk->tag, blk->set), blkSize, 0, 1526 Request::wbMasterId); 1527 if (blk->isSecure()) 1528 req->setFlags(Request::SECURE); 1529 --- 93 unchanged lines hidden (view full) --- 1623 } else { 1624 DPRINTF(Cache, "replacement: replacing %#llx (%s) with %#llx (%s): %s\n", 1625 repl_addr, blk->isSecure() ? "s" : "ns", 1626 addr, is_secure ? "s" : "ns", 1627 blk->isDirty() ? "writeback" : "clean"); 1628 1629 // Will send up Writeback/CleanEvict snoops via isCachedAbove 1630 // when pushing this writeback list into the write buffer. | 1569 assert(blk && blk->isValid() && !blk->isDirty()); 1570 // Creating a zero sized write, a message to the snoop filter 1571 Request *req = 1572 new Request(tags->regenerateBlkAddr(blk->tag, blk->set), blkSize, 0, 1573 Request::wbMasterId); 1574 if (blk->isSecure()) 1575 req->setFlags(Request::SECURE); 1576 --- 93 unchanged lines hidden (view full) --- 1670 } else { 1671 DPRINTF(Cache, "replacement: replacing %#llx (%s) with %#llx (%s): %s\n", 1672 repl_addr, blk->isSecure() ? "s" : "ns", 1673 addr, is_secure ? "s" : "ns", 1674 blk->isDirty() ? "writeback" : "clean"); 1675 1676 // Will send up Writeback/CleanEvict snoops via isCachedAbove 1677 // when pushing this writeback list into the write buffer. |
1631 if (blk->isDirty()) { | 1678 if (blk->isDirty() || writebackClean) { |
1632 // Save writeback packet for handling by caller 1633 writebacks.push_back(writebackBlk(blk)); 1634 } else { 1635 writebacks.push_back(cleanEvictBlk(blk)); 1636 } 1637 } 1638 } 1639 --- 406 unchanged lines hidden (view full) --- 2046 MSHR *wb_entry = writebacks[0]; 2047 // Expect to see only Writebacks and/or CleanEvicts here, both of 2048 // which should not be generated for uncacheable data. 2049 assert(!wb_entry->isUncacheable()); 2050 // There should only be a single request responsible for generating 2051 // Writebacks/CleanEvicts. 2052 assert(wb_entry->getNumTargets() == 1); 2053 PacketPtr wb_pkt = wb_entry->getTarget()->pkt; | 1679 // Save writeback packet for handling by caller 1680 writebacks.push_back(writebackBlk(blk)); 1681 } else { 1682 writebacks.push_back(cleanEvictBlk(blk)); 1683 } 1684 } 1685 } 1686 --- 406 unchanged lines hidden (view full) --- 2093 MSHR *wb_entry = writebacks[0]; 2094 // Expect to see only Writebacks and/or CleanEvicts here, both of 2095 // which should not be generated for uncacheable data. 2096 assert(!wb_entry->isUncacheable()); 2097 // There should only be a single request responsible for generating 2098 // Writebacks/CleanEvicts. 2099 assert(wb_entry->getNumTargets() == 1); 2100 PacketPtr wb_pkt = wb_entry->getTarget()->pkt; |
2054 assert(wb_pkt->evictingBlock()); | 2101 assert(wb_pkt->isEviction()); |
2055 | 2102 |
2056 if (pkt->evictingBlock()) { | 2103 if (pkt->isEviction()) { |
2057 // if the block is found in the write queue, set the BLOCK_CACHED 2058 // flag for Writeback/CleanEvict snoop. On return the snoop will 2059 // propagate the BLOCK_CACHED flag in Writeback packets and prevent 2060 // any CleanEvicts from travelling down the memory hierarchy. 2061 pkt->setBlockCached(); 2062 DPRINTF(Cache, "Squashing %s from lower cache on writequeue hit" 2063 " %#x\n", pkt->cmdString(), pkt->getAddr()); 2064 return; 2065 } 2066 | 2104 // if the block is found in the write queue, set the BLOCK_CACHED 2105 // flag for Writeback/CleanEvict snoop. On return the snoop will 2106 // propagate the BLOCK_CACHED flag in Writeback packets and prevent 2107 // any CleanEvicts from travelling down the memory hierarchy. 2108 pkt->setBlockCached(); 2109 DPRINTF(Cache, "Squashing %s from lower cache on writequeue hit" 2110 " %#x\n", pkt->cmdString(), pkt->getAddr()); 2111 return; 2112 } 2113 |
2067 if (wb_pkt->cmd == MemCmd::Writeback) { | 2114 if (wb_pkt->cmd == MemCmd::WritebackDirty) { |
2068 assert(!pkt->memInhibitAsserted()); 2069 pkt->assertMemInhibit(); 2070 if (!pkt->needsExclusive()) { 2071 pkt->assertShared(); 2072 // the writeback is no longer passing exclusivity (the 2073 // receiving cache should consider the block owned 2074 // rather than modified) 2075 wb_pkt->assertShared(); 2076 } else { 2077 // if we're not asserting the shared line, we need to 2078 // invalidate our copy. we'll do that below as long as 2079 // the packet's invalidate flag is set... 2080 assert(pkt->isInvalidate()); 2081 } 2082 doTimingSupplyResponse(pkt, wb_pkt->getConstPtr<uint8_t>(), 2083 false, false); 2084 } else { | 2115 assert(!pkt->memInhibitAsserted()); 2116 pkt->assertMemInhibit(); 2117 if (!pkt->needsExclusive()) { 2118 pkt->assertShared(); 2119 // the writeback is no longer passing exclusivity (the 2120 // receiving cache should consider the block owned 2121 // rather than modified) 2122 wb_pkt->assertShared(); 2123 } else { 2124 // if we're not asserting the shared line, we need to 2125 // invalidate our copy. we'll do that below as long as 2126 // the packet's invalidate flag is set... 2127 assert(pkt->isInvalidate()); 2128 } 2129 doTimingSupplyResponse(pkt, wb_pkt->getConstPtr<uint8_t>(), 2130 false, false); 2131 } else { |
2085 assert(wb_pkt->cmd == MemCmd::CleanEvict); | 2132 // on hitting a clean writeback we play it safe and do not 2133 // provide a response, the block may be dirty somewhere 2134 // else 2135 assert(wb_pkt->isCleanEviction()); |
2086 // The cache technically holds the block until the | 2136 // The cache technically holds the block until the |
2087 // corresponding CleanEvict message reaches the crossbar | 2137 // corresponding message reaches the crossbar |
2088 // below. Therefore when a snoop encounters a CleanEvict | 2138 // below. Therefore when a snoop encounters a CleanEvict |
2089 // message we must set assertShared (just like when it 2090 // encounters a Writeback) to avoid the snoop filter 2091 // prematurely clearing the holder bit in the crossbar 2092 // below 2093 if (!pkt->needsExclusive()) | 2139 // or WritebackClean message we must set assertShared 2140 // (just like when it encounters a Writeback) to avoid the 2141 // snoop filter prematurely clearing the holder bit in the 2142 // crossbar below 2143 if (!pkt->needsExclusive()) { |
2094 pkt->assertShared(); | 2144 pkt->assertShared(); |
2095 else | 2145 // the writeback is no longer passing exclusivity (the 2146 // receiving cache should consider the block owned 2147 // rather than modified) 2148 wb_pkt->assertShared(); 2149 } else { |
2096 assert(pkt->isInvalidate()); | 2150 assert(pkt->isInvalidate()); |
2151 } |
|
2097 } 2098 2099 if (pkt->isInvalidate()) { 2100 // Invalidation trumps our writeback... discard here 2101 // Note: markInService will remove entry from writeback buffer. 2102 markInService(wb_entry, false); 2103 delete wb_pkt; 2104 } --- 133 unchanged lines hidden (view full) --- 2238 // packet, the cache can inform the crossbar below of presence or absence 2239 // of the block. 2240 if (is_timing) { 2241 Packet snoop_pkt(pkt, true, false); 2242 snoop_pkt.setExpressSnoop(); 2243 // Assert that packet is either Writeback or CleanEvict and not a 2244 // prefetch request because prefetch requests need an MSHR and may 2245 // generate a snoop response. | 2152 } 2153 2154 if (pkt->isInvalidate()) { 2155 // Invalidation trumps our writeback... discard here 2156 // Note: markInService will remove entry from writeback buffer. 2157 markInService(wb_entry, false); 2158 delete wb_pkt; 2159 } --- 133 unchanged lines hidden (view full) --- 2293 // packet, the cache can inform the crossbar below of presence or absence 2294 // of the block. 2295 if (is_timing) { 2296 Packet snoop_pkt(pkt, true, false); 2297 snoop_pkt.setExpressSnoop(); 2298 // Assert that packet is either Writeback or CleanEvict and not a 2299 // prefetch request because prefetch requests need an MSHR and may 2300 // generate a snoop response. |
2246 assert(pkt->evictingBlock()); | 2301 assert(pkt->isEviction()); |
2247 snoop_pkt.senderState = NULL; 2248 cpuSidePort->sendTimingSnoopReq(&snoop_pkt); 2249 // Writeback/CleanEvict snoops do not generate a snoop response. 2250 assert(!(snoop_pkt.memInhibitAsserted())); 2251 return snoop_pkt.isBlockCached(); 2252 } else { 2253 cpuSidePort->sendAtomicSnoop(pkt); 2254 return pkt->isBlockCached(); --- 52 unchanged lines hidden (view full) --- 2307 } 2308 2309 if (snoop_pkt.isBlockCached() || blk != NULL) { 2310 DPRINTF(Cache, "Block present, prefetch squashed by cache. " 2311 "Deallocating mshr target %#x.\n", 2312 mshr->blkAddr); 2313 2314 // Deallocate the mshr target | 2302 snoop_pkt.senderState = NULL; 2303 cpuSidePort->sendTimingSnoopReq(&snoop_pkt); 2304 // Writeback/CleanEvict snoops do not generate a snoop response. 2305 assert(!(snoop_pkt.memInhibitAsserted())); 2306 return snoop_pkt.isBlockCached(); 2307 } else { 2308 cpuSidePort->sendAtomicSnoop(pkt); 2309 return pkt->isBlockCached(); --- 52 unchanged lines hidden (view full) --- 2362 } 2363 2364 if (snoop_pkt.isBlockCached() || blk != NULL) { 2365 DPRINTF(Cache, "Block present, prefetch squashed by cache. " 2366 "Deallocating mshr target %#x.\n", 2367 mshr->blkAddr); 2368 2369 // Deallocate the mshr target |
2315 if (tgt_pkt->cmd != MemCmd::Writeback) { | 2370 if (!tgt_pkt->isWriteback()) { |
2316 if (mshr->queue->forceDeallocateTarget(mshr)) { 2317 // Clear block if this deallocation resulted freed an 2318 // mshr when all had previously been utilized 2319 clearBlocked((BlockedCause)(mshr->queue->index)); 2320 } 2321 return NULL; 2322 } else { 2323 // If this is a Writeback, and the snoops indicate that the blk --- 276 unchanged lines hidden --- | 2371 if (mshr->queue->forceDeallocateTarget(mshr)) { 2372 // Clear block if this deallocation resulted freed an 2373 // mshr when all had previously been utilized 2374 clearBlocked((BlockedCause)(mshr->queue->index)); 2375 } 2376 return NULL; 2377 } else { 2378 // If this is a Writeback, and the snoops indicate that the blk --- 276 unchanged lines hidden --- |