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 ---