cache.cc (13223:081299f403fe) | cache.cc (13350:247e4108a5e8) |
---|---|
1/* 2 * Copyright (c) 2010-2018 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 --- 463 unchanged lines hidden (view full) --- 472 return; 473 } 474 475 BaseCache::recvTimingReq(pkt); 476} 477 478PacketPtr 479Cache::createMissPacket(PacketPtr cpu_pkt, CacheBlk *blk, | 1/* 2 * Copyright (c) 2010-2018 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 --- 463 unchanged lines hidden (view full) --- 472 return; 473 } 474 475 BaseCache::recvTimingReq(pkt); 476} 477 478PacketPtr 479Cache::createMissPacket(PacketPtr cpu_pkt, CacheBlk *blk, |
480 bool needsWritable) const | 480 bool needsWritable, 481 bool is_whole_line_write) const |
481{ 482 // should never see evictions here 483 assert(!cpu_pkt->isEviction()); 484 485 bool blkValid = blk && blk->isValid(); 486 487 if (cpu_pkt->req->isUncacheable() || 488 (!blkValid && cpu_pkt->isUpgrade()) || --- 6 unchanged lines hidden (view full) --- 495 assert(cpu_pkt->needsResponse()); 496 497 MemCmd cmd; 498 // @TODO make useUpgrades a parameter. 499 // Note that ownership protocols require upgrade, otherwise a 500 // write miss on a shared owned block will generate a ReadExcl, 501 // which will clobber the owned copy. 502 const bool useUpgrades = true; | 482{ 483 // should never see evictions here 484 assert(!cpu_pkt->isEviction()); 485 486 bool blkValid = blk && blk->isValid(); 487 488 if (cpu_pkt->req->isUncacheable() || 489 (!blkValid && cpu_pkt->isUpgrade()) || --- 6 unchanged lines hidden (view full) --- 496 assert(cpu_pkt->needsResponse()); 497 498 MemCmd cmd; 499 // @TODO make useUpgrades a parameter. 500 // Note that ownership protocols require upgrade, otherwise a 501 // write miss on a shared owned block will generate a ReadExcl, 502 // which will clobber the owned copy. 503 const bool useUpgrades = true; |
503 if (cpu_pkt->cmd == MemCmd::WriteLineReq) { | 504 assert(cpu_pkt->cmd != MemCmd::WriteLineReq || is_whole_line_write); 505 if (is_whole_line_write) { |
504 assert(!blkValid || !blk->isWritable()); 505 // forward as invalidate to all other caches, this gives us 506 // the line in Exclusive state, and invalidates all other 507 // copies 508 cmd = MemCmd::InvalidateReq; 509 } else if (blkValid && useUpgrades) { 510 // only reason to be here is that blk is read only and we need 511 // it to be writable --- 63 unchanged lines hidden (view full) --- 575 assert(!(pkt->req->isUncacheable() && pkt->isWrite()) || 576 pkt->isResponse()); 577 578 return latency; 579 } 580 581 // only misses left 582 | 506 assert(!blkValid || !blk->isWritable()); 507 // forward as invalidate to all other caches, this gives us 508 // the line in Exclusive state, and invalidates all other 509 // copies 510 cmd = MemCmd::InvalidateReq; 511 } else if (blkValid && useUpgrades) { 512 // only reason to be here is that blk is read only and we need 513 // it to be writable --- 63 unchanged lines hidden (view full) --- 577 assert(!(pkt->req->isUncacheable() && pkt->isWrite()) || 578 pkt->isResponse()); 579 580 return latency; 581 } 582 583 // only misses left 584 |
583 PacketPtr bus_pkt = createMissPacket(pkt, blk, pkt->needsWritable()); | 585 PacketPtr bus_pkt = createMissPacket(pkt, blk, pkt->needsWritable(), 586 pkt->isWholeLineWrite(blkSize)); |
584 585 bool is_forward = (bus_pkt == nullptr); 586 587 if (is_forward) { 588 // just forwarding the same request to the next level 589 // no local cache operation involved 590 bus_pkt = pkt; 591 } --- 18 unchanged lines hidden (view full) --- 610 // to do anything. Otherwise, use the separate bus_pkt to 611 // generate response to pkt and then delete it. 612 if (!is_forward) { 613 if (pkt->needsResponse()) { 614 assert(bus_pkt->isResponse()); 615 if (bus_pkt->isError()) { 616 pkt->makeAtomicResponse(); 617 pkt->copyError(bus_pkt); | 587 588 bool is_forward = (bus_pkt == nullptr); 589 590 if (is_forward) { 591 // just forwarding the same request to the next level 592 // no local cache operation involved 593 bus_pkt = pkt; 594 } --- 18 unchanged lines hidden (view full) --- 613 // to do anything. Otherwise, use the separate bus_pkt to 614 // generate response to pkt and then delete it. 615 if (!is_forward) { 616 if (pkt->needsResponse()) { 617 assert(bus_pkt->isResponse()); 618 if (bus_pkt->isError()) { 619 pkt->makeAtomicResponse(); 620 pkt->copyError(bus_pkt); |
618 } else if (pkt->cmd == MemCmd::WriteLineReq) { | 621 } else if (pkt->isWholeLineWrite(blkSize)) { |
619 // note the use of pkt, not bus_pkt here. 620 621 // write-line request to the cache that promoted 622 // the write to a whole line | 622 // note the use of pkt, not bus_pkt here. 623 624 // write-line request to the cache that promoted 625 // the write to a whole line |
623 blk = handleFill(pkt, blk, writebacks, | 626 blk = handleFill(bus_pkt, blk, writebacks, |
624 allocOnFill(pkt->cmd)); 625 assert(blk != NULL); 626 is_invalidate = false; 627 satisfyRequest(pkt, blk); 628 } else if (bus_pkt->isRead() || 629 bus_pkt->cmd == MemCmd::UpgradeResp) { 630 // we're updating cache state to allow us to 631 // satisfy the upstream request from the cache --- 39 unchanged lines hidden (view full) --- 671{ 672 MSHR::Target *initial_tgt = mshr->getTarget(); 673 // First offset for critical word first calculations 674 const int initial_offset = initial_tgt->pkt->getOffset(blkSize); 675 676 const bool is_error = pkt->isError(); 677 // allow invalidation responses originating from write-line 678 // requests to be discarded | 627 allocOnFill(pkt->cmd)); 628 assert(blk != NULL); 629 is_invalidate = false; 630 satisfyRequest(pkt, blk); 631 } else if (bus_pkt->isRead() || 632 bus_pkt->cmd == MemCmd::UpgradeResp) { 633 // we're updating cache state to allow us to 634 // satisfy the upstream request from the cache --- 39 unchanged lines hidden (view full) --- 674{ 675 MSHR::Target *initial_tgt = mshr->getTarget(); 676 // First offset for critical word first calculations 677 const int initial_offset = initial_tgt->pkt->getOffset(blkSize); 678 679 const bool is_error = pkt->isError(); 680 // allow invalidation responses originating from write-line 681 // requests to be discarded |
679 bool is_invalidate = pkt->isInvalidate(); | 682 bool is_invalidate = pkt->isInvalidate() && 683 !mshr->wasWholeLineWrite; |
680 681 MSHR::TargetList targets = mshr->extractServiceableTargets(pkt); 682 for (auto &target: targets) { 683 Packet *tgt_pkt = target.pkt; 684 switch (target.source) { 685 case MSHR::Target::FromCPU: 686 Tick completion_time; 687 // Here we charge on completion_time the delay of the xbar if the --- 13 unchanged lines hidden (view full) --- 701 // unlike the other packet flows, where data is found in other 702 // caches or memory and brought back, write-line requests always 703 // have the data right away, so the above check for "is fill?" 704 // cannot actually be determined until examining the stored MSHR 705 // state. We "catch up" with that logic here, which is duplicated 706 // from above. 707 if (tgt_pkt->cmd == MemCmd::WriteLineReq) { 708 assert(!is_error); | 684 685 MSHR::TargetList targets = mshr->extractServiceableTargets(pkt); 686 for (auto &target: targets) { 687 Packet *tgt_pkt = target.pkt; 688 switch (target.source) { 689 case MSHR::Target::FromCPU: 690 Tick completion_time; 691 // Here we charge on completion_time the delay of the xbar if the --- 13 unchanged lines hidden (view full) --- 705 // unlike the other packet flows, where data is found in other 706 // caches or memory and brought back, write-line requests always 707 // have the data right away, so the above check for "is fill?" 708 // cannot actually be determined until examining the stored MSHR 709 // state. We "catch up" with that logic here, which is duplicated 710 // from above. 711 if (tgt_pkt->cmd == MemCmd::WriteLineReq) { 712 assert(!is_error); |
709 // we got the block in a writable state, so promote 710 // any deferred targets if possible 711 mshr->promoteWritable(); 712 // NB: we use the original packet here and not the response! 713 blk = handleFill(tgt_pkt, blk, writebacks, 714 targets.allocOnFill); | |
715 assert(blk); | 713 assert(blk); |
716 717 // discard the invalidation response 718 is_invalidate = false; | 714 assert(blk->isWritable()); |
719 } 720 721 if (blk && blk->isValid() && !mshr->isForward) { 722 satisfyRequest(tgt_pkt, blk, true, mshr->hasPostDowngrade()); 723 724 // How many bytes past the first request is this one 725 int transfer_offset = 726 tgt_pkt->getOffset(blkSize) - initial_offset; --- 674 unchanged lines hidden --- | 715 } 716 717 if (blk && blk->isValid() && !mshr->isForward) { 718 satisfyRequest(tgt_pkt, blk, true, mshr->hasPostDowngrade()); 719 720 // How many bytes past the first request is this one 721 int transfer_offset = 722 tgt_pkt->getOffset(blkSize) - initial_offset; --- 674 unchanged lines hidden --- |