2 * Copyright (c) 2002-2005 The Regents of The University of Michigan
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * Authors: Erik Hallnor
40 #include "sim/host.hh"
41 #include "base/misc.hh"
43 #include "mem/cache/cache.hh"
44 #include "mem/cache/cache_blk.hh"
45 #include "mem/cache/miss/mshr.hh"
46 #include "mem/cache/prefetch/base_prefetcher.hh"
48 #include "sim/sim_exit.hh" // for SimExitEvent
51 template<class TagStore>
52 Cache<TagStore>::Cache(const std::string &_name,
53 Cache<TagStore>::Params ¶ms)
54 : BaseCache(_name, params.baseParams),
55 prefetchAccess(params.prefetchAccess),
57 prefetcher(params.prefetcher),
58 doFastWrites(params.doFastWrites),
59 prefetchMiss(params.prefetchMiss)
61 tempBlock = new BlkType();
62 tempBlock->data = new uint8_t[blkSize];
64 cpuSidePort = new CpuSidePort(_name + "-cpu_side_port", this);
65 memSidePort = new MemSidePort(_name + "-mem_side_port", this);
66 cpuSidePort->setOtherPort(memSidePort);
67 memSidePort->setOtherPort(cpuSidePort);
70 prefetcher->setCache(this);
73 template<class TagStore>
75 Cache<TagStore>::regStats()
77 BaseCache::regStats();
78 tags->regStats(name());
79 prefetcher->regStats(name());
82 template<class TagStore>
84 Cache<TagStore>::getPort(const std::string &if_name, int idx)
86 if (if_name == "" || if_name == "cpu_side") {
88 } else if (if_name == "mem_side") {
90 } else if (if_name == "functional") {
91 return new CpuSidePort(name() + "-cpu_side_funcport", this);
93 panic("Port name %s unrecognized\n", if_name);
97 template<class TagStore>
99 Cache<TagStore>::deletePortRefs(Port *p)
101 if (cpuSidePort == p || memSidePort == p)
102 panic("Can only delete functional ports\n");
108 template<class TagStore>
110 Cache<TagStore>::cmpAndSwap(BlkType *blk, PacketPtr pkt)
112 uint64_t overwrite_val;
114 uint64_t condition_val64;
115 uint32_t condition_val32;
117 int offset = tags->extractBlkOffset(pkt->getAddr());
118 uint8_t *blk_data = blk->data + offset;
120 assert(sizeof(uint64_t) >= pkt->getSize());
122 overwrite_mem = true;
123 // keep a copy of our possible write value, and copy what is at the
124 // memory address into the packet
125 pkt->writeData((uint8_t *)&overwrite_val);
126 pkt->setData(blk_data);
128 if (pkt->req->isCondSwap()) {
129 if (pkt->getSize() == sizeof(uint64_t)) {
130 condition_val64 = pkt->req->getExtraData();
131 overwrite_mem = !std::memcmp(&condition_val64, blk_data,
133 } else if (pkt->getSize() == sizeof(uint32_t)) {
134 condition_val32 = (uint32_t)pkt->req->getExtraData();
135 overwrite_mem = !std::memcmp(&condition_val32, blk_data,
138 panic("Invalid size for conditional read/write\n");
142 std::memcpy(blk_data, &overwrite_val, pkt->getSize());
146 template<class TagStore>
148 Cache<TagStore>::satisfyCpuSideRequest(PacketPtr pkt, BlkType *blk)
151 assert(pkt->needsExclusive() ? blk->isWritable() : blk->isValid());
152 assert(pkt->getOffset(blkSize) + pkt->getSize() <= blkSize);
154 // Check RMW operations first since both isRead() and
155 // isWrite() will be true for them
156 if (pkt->cmd == MemCmd::SwapReq) {
157 cmpAndSwap(blk, pkt);
158 } else if (pkt->isWrite()) {
159 if (blk->checkWrite(pkt)) {
160 blk->status |= BlkDirty;
161 pkt->writeDataToBlock(blk->data, blkSize);
163 } else if (pkt->isRead()) {
164 if (pkt->isLocked()) {
165 blk->trackLoadLocked(pkt);
167 pkt->setDataFromBlock(blk->data, blkSize);
169 // Not a read or write... must be an upgrade. it's OK
170 // to just ack those as long as we have an exclusive
171 // copy at this level.
172 assert(pkt->cmd == MemCmd::UpgradeReq);
177 /////////////////////////////////////////////////////
179 // MSHR helper functions
181 /////////////////////////////////////////////////////
184 template<class TagStore>
186 Cache<TagStore>::markInService(MSHR *mshr)
188 markInServiceInternal(mshr);
190 if (mshr->originalCmd == MemCmd::HardPFReq) {
191 DPRINTF(HWPrefetch, "%s:Marking a HW_PF in service\n",
193 //Also clear pending if need be
194 if (!prefetcher->havePending())
196 deassertMemSideBusRequest(Request_PF);
203 template<class TagStore>
205 Cache<TagStore>::squash(int threadNum)
207 bool unblock = false;
208 BlockedCause cause = NUM_BLOCKED_CAUSES;
210 if (noTargetMSHR && noTargetMSHR->threadNum == threadNum) {
213 cause = Blocked_NoTargets;
215 if (mshrQueue.isFull()) {
217 cause = Blocked_NoMSHRs;
219 mshrQueue.squash(threadNum);
220 if (unblock && !mshrQueue.isFull()) {
225 /////////////////////////////////////////////////////
227 // Access path: requests coming in from the CPU side
229 /////////////////////////////////////////////////////
231 template<class TagStore>
233 Cache<TagStore>::access(PacketPtr pkt, BlkType *&blk, int &lat)
235 if (pkt->req->isUncacheable()) {
241 bool satisfied = false; // assume the worst
242 blk = tags->findBlock(pkt->getAddr(), lat);
244 if (prefetchAccess) {
245 //We are determining prefetches on access stream, call prefetcher
246 prefetcher->handleMiss(pkt, curTick);
249 DPRINTF(Cache, "%s %x %s\n", pkt->cmdString(), pkt->getAddr(),
250 (blk) ? "hit" : "miss");
254 if (blk->isPrefetch()) {
255 //Signal that this was a hit under prefetch (no need for
256 //use prefetch (only can get here if true)
257 DPRINTF(HWPrefetch, "Hit a block that was prefetched\n");
258 blk->status &= ~BlkHWPrefetched;
260 //If we are using the miss stream, signal the
261 //prefetcher otherwise the access stream would have
262 //already signaled this hit
263 prefetcher->handleMiss(pkt, curTick);
267 if (pkt->needsExclusive() ? blk->isWritable() : blk->isValid()) {
268 // OK to satisfy access
269 hits[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++;
271 satisfyCpuSideRequest(pkt, blk);
273 // permission violation... nothing to do here, leave unsatisfied
274 // for statistics purposes this counts like a complete miss
278 // complete miss (no matching block)
281 if (pkt->isLocked() && pkt->isWrite()) {
282 // miss on store conditional... just give up now
283 pkt->req->setExtraData(0);
292 template<class TagStore>
294 Cache<TagStore>::timingAccess(PacketPtr pkt)
296 //@todo Add back in MemDebug Calls
297 // MemDebug::cacheAccess(pkt);
299 // we charge hitLatency for doing just about anything here
300 Tick time = curTick + hitLatency;
302 if (pkt->memInhibitAsserted()) {
303 DPRINTF(Cache, "mem inhibited on 0x%x: not responding\n",
305 assert(!pkt->req->isUncacheable());
309 if (pkt->req->isUncacheable()) {
310 allocateBuffer(pkt, time, true);
311 assert(pkt->needsResponse()); // else we should delete it here??
315 int lat = hitLatency;
316 bool satisfied = false;
318 Addr blk_addr = pkt->getAddr() & ~(Addr(blkSize-1));
319 MSHR *mshr = mshrQueue.findMatch(blk_addr);
322 // no outstanding access to this block, look up in cache
323 // (otherwise if we allow reads while there's an outstanding
324 // write miss, the read could return stale data out of the
325 // cache block... a more aggressive system could detect the
326 // overlap (if any) and forward data out of the MSHRs, but we
327 // don't do that yet)
329 satisfied = access(pkt, blk, lat);
333 PacketList writebacks;
335 // If this is a block size write/hint (WH64) allocate the block here
336 // if the coherence protocol allows it.
337 /** @todo make the fast write alloc (wh64) work with coherence. */
338 /** @todo Do we want to do fast writes for writebacks as well? */
339 if (!blk && pkt->getSize() >= blkSize && coherence->allowFastWrites() &&
340 (pkt->cmd == MemCmd::WriteReq
341 || pkt->cmd == MemCmd::WriteInvalidateReq) ) {
342 // not outstanding misses, can do this
343 MSHR *outstanding_miss = mshrQueue.findMatch(pkt->getAddr());
344 if (pkt->cmd == MemCmd::WriteInvalidateReq || !outstanding_miss) {
345 if (outstanding_miss) {
346 warn("WriteInv doing a fastallocate"
347 "with an outstanding miss to the same address\n");
349 blk = handleFill(NULL, pkt, BlkValid | BlkWritable,
355 // copy writebacks to write buffer
356 while (!writebacks.empty()) {
357 PacketPtr wbPkt = writebacks.front();
358 allocateBuffer(wbPkt, time, true);
359 writebacks.pop_front();
363 bool needsResponse = pkt->needsResponse();
366 assert(needsResponse);
367 pkt->makeTimingResponse();
368 cpuSidePort->respond(pkt, curTick+lat);
372 prefetcher->handleMiss(pkt, time);
376 //@todo remove hw_pf here
377 mshr_hits[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++;
378 if (mshr->threadNum != 0/*pkt->req->getThreadNum()*/) {
379 mshr->threadNum = -1;
381 mshr->allocateTarget(pkt, time, order++);
382 if (mshr->getNumTargets() == numTarget) {
384 setBlocked(Blocked_NoTargets);
385 // need to be careful with this... if this mshr isn't
386 // ready yet (i.e. time > curTick_, we don't want to
387 // move it ahead of mshrs that are ready
388 // mshrQueue.moveToFront(mshr);
392 mshr_misses[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++;
393 // always mark as cache fill for now... if we implement
394 // no-write-allocate or bypass accesses this will have to
396 allocateMissBuffer(pkt, time, true);
400 if (!needsResponse) {
401 // Need to clean up the packet on a writeback miss, but leave
402 // the request for the next level.
410 template<class TagStore>
412 Cache<TagStore>::getBusPacket(PacketPtr cpu_pkt, BlkType *blk,
415 bool blkValid = blk && blk->isValid();
417 if (cpu_pkt->req->isUncacheable()) {
423 (cpu_pkt->cmd == MemCmd::Writeback ||
424 cpu_pkt->cmd == MemCmd::UpgradeReq)) {
425 // For now, writebacks from upper-level caches that
426 // completely miss in the cache just go through. If we had
427 // "fast write" support (where we could write the whole
428 // block w/o fetching new data) we might want to allocate
429 // on writeback misses instead.
433 assert(cpu_pkt->needsResponse());
436 const bool useUpgrades = true;
437 if (blkValid && useUpgrades) {
438 // only reason to be here is that blk is shared
439 // (read-only) and we need exclusive
440 assert(needsExclusive && !blk->isWritable());
441 cmd = MemCmd::UpgradeReq;
444 cmd = needsExclusive ? MemCmd::ReadExReq : MemCmd::ReadReq;
446 PacketPtr pkt = new Packet(cpu_pkt->req, cmd, Packet::Broadcast, blkSize);
453 template<class TagStore>
455 Cache<TagStore>::atomicAccess(PacketPtr pkt)
457 int lat = hitLatency;
459 if (pkt->memInhibitAsserted()) {
460 DPRINTF(Cache, "mem inhibited on 0x%x: not responding\n",
462 assert(!pkt->req->isUncacheable());
466 // should assert here that there are no outstanding MSHRs or
467 // writebacks... that would mean that someone used an atomic
468 // access in timing mode
472 if (!access(pkt, blk, lat)) {
474 PacketPtr busPkt = getBusPacket(pkt, blk, pkt->needsExclusive());
476 bool isCacheFill = (busPkt != NULL);
478 if (busPkt == NULL) {
479 // just forwarding the same request to the next level
480 // no local cache operation involved
484 DPRINTF(Cache, "Sending an atomic %s for %x\n",
485 busPkt->cmdString(), busPkt->getAddr());
488 CacheBlk::State old_state = blk ? blk->status : 0;
491 lat += memSidePort->sendAtomic(busPkt);
493 DPRINTF(Cache, "Receive response: %s for addr %x in state %i\n",
494 busPkt->cmdString(), busPkt->getAddr(), old_state);
497 PacketList writebacks;
498 blk = handleFill(busPkt, blk, writebacks);
499 satisfyCpuSideRequest(pkt, blk);
502 // Handle writebacks if needed
503 while (!writebacks.empty()){
504 PacketPtr wbPkt = writebacks.front();
505 memSidePort->sendAtomic(wbPkt);
506 writebacks.pop_front();
512 // We now have the block one way or another (hit or completed miss)
514 if (pkt->needsResponse()) {
515 pkt->makeAtomicResponse();
522 template<class TagStore>
524 Cache<TagStore>::functionalAccess(PacketPtr pkt,
525 CachePort *otherSidePort)
527 Addr blk_addr = pkt->getAddr() & ~(blkSize - 1);
528 BlkType *blk = tags->findBlock(pkt->getAddr());
530 if (blk && pkt->checkFunctional(blk_addr, blkSize, blk->data)) {
531 // request satisfied from block
535 // Need to check for outstanding misses and writes
537 // There can only be one matching outstanding miss.
538 MSHR *mshr = mshrQueue.findMatch(blk_addr);
540 MSHR::TargetList *targets = mshr->getTargetList();
541 MSHR::TargetList::iterator i = targets->begin();
542 MSHR::TargetList::iterator end = targets->end();
543 for (; i != end; ++i) {
544 PacketPtr targetPkt = i->pkt;
545 if (pkt->checkFunctional(targetPkt))
550 // There can be many matching outstanding writes.
551 std::vector<MSHR*> writes;
552 assert(!writeBuffer.findMatches(blk_addr, writes));
553 /* Need to change this to iterate through targets in mshr??
554 for (int i = 0; i < writes.size(); ++i) {
555 MSHR *mshr = writes[i];
556 if (pkt->checkFunctional(mshr->addr, mshr->size, mshr->writeData))
561 otherSidePort->checkAndSendFunctional(pkt);
565 /////////////////////////////////////////////////////
567 // Response handling: responses from the memory side
569 /////////////////////////////////////////////////////
572 template<class TagStore>
574 Cache<TagStore>::satisfyMSHR(MSHR *mshr, PacketPtr pkt,
577 // respond to MSHR targets, if any
579 // First offset for critical word first calculations
580 int initial_offset = 0;
582 if (mshr->hasTargets()) {
583 initial_offset = mshr->getTarget()->pkt->getOffset(blkSize);
586 while (mshr->hasTargets()) {
587 MSHR::Target *target = mshr->getTarget();
589 if (target->isCpuSide()) {
590 satisfyCpuSideRequest(target->pkt, blk);
591 // How many bytes pass the first request is this one
592 int transfer_offset =
593 target->pkt->getOffset(blkSize) - initial_offset;
594 if (transfer_offset < 0) {
595 transfer_offset += blkSize;
598 // If critical word (no offset) return first word time
599 Tick completion_time = tags->getHitLatency() +
600 transfer_offset ? pkt->finishTime : pkt->firstWordTime;
602 if (!target->pkt->req->isUncacheable()) {
603 missLatency[target->pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/] +=
604 completion_time - target->recvTime;
606 target->pkt->makeTimingResponse();
607 cpuSidePort->respond(target->pkt, completion_time);
609 // response to snoop request
610 DPRINTF(Cache, "processing deferred snoop...\n");
611 handleSnoop(target->pkt, blk, true, true);
617 if (mshr->promoteDeferredTargets()) {
618 MSHRQueue *mq = mshr->queue;
619 mq->markPending(mshr);
620 requestMemSideBus((RequestCause)mq->index, pkt->finishTime);
628 template<class TagStore>
630 Cache<TagStore>::handleResponse(PacketPtr pkt)
632 Tick time = curTick + hitLatency;
633 MSHR *mshr = dynamic_cast<MSHR*>(pkt->senderState);
636 if (pkt->wasNacked()) {
637 //pkt->reinitFromRequest();
638 warn("NACKs from devices not connected to the same bus "
639 "not implemented\n");
642 assert(!pkt->isError());
643 DPRINTF(Cache, "Handling response to %x\n", pkt->getAddr());
645 MSHRQueue *mq = mshr->queue;
646 bool wasFull = mq->isFull();
648 if (mshr == noTargetMSHR) {
649 // we always clear at least one target
650 clearBlocked(Blocked_NoTargets);
654 // Can we deallocate MSHR when done?
655 bool deallocate = false;
657 // Initial target is used just for stats
658 MSHR::Target *initial_tgt = mshr->getTarget();
659 int stats_cmd_idx = initial_tgt->pkt->cmdToIndex();
660 Tick miss_latency = curTick - initial_tgt->recvTime;
662 if (mshr->isCacheFill) {
663 mshr_miss_latency[stats_cmd_idx][0/*pkt->req->getThreadNum()*/] +=
665 DPRINTF(Cache, "Block for addr %x being updated in Cache\n",
667 BlkType *blk = tags->findBlock(pkt->getAddr());
669 // give mshr a chance to do some dirty work
670 mshr->handleFill(pkt, blk);
672 PacketList writebacks;
673 blk = handleFill(pkt, blk, writebacks);
674 deallocate = satisfyMSHR(mshr, pkt, blk);
675 // copy writebacks to write buffer
676 while (!writebacks.empty()) {
677 PacketPtr wbPkt = writebacks.front();
678 allocateBuffer(wbPkt, time, true);
679 writebacks.pop_front();
681 // if we used temp block, clear it out
682 if (blk == tempBlock) {
683 if (blk->isDirty()) {
684 allocateBuffer(writebackBlk(blk), time, true);
686 tags->invalidateBlk(blk);
689 if (pkt->req->isUncacheable()) {
690 mshr_uncacheable_lat[stats_cmd_idx][0/*pkt->req->getThreadNum()*/] +=
694 while (mshr->hasTargets()) {
695 MSHR::Target *target = mshr->getTarget();
696 assert(target->isCpuSide());
699 target->pkt->setData(pkt->getPtr<uint8_t>());
701 target->pkt->makeTimingResponse();
702 cpuSidePort->respond(target->pkt, time);
704 assert(!mshr->hasTargets());
711 mq->deallocate(mshr);
712 if (wasFull && !mq->isFull()) {
713 clearBlocked((BlockedCause)mq->index);
721 template<class TagStore>
723 Cache<TagStore>::writebackBlk(BlkType *blk)
725 assert(blk && blk->isValid() && blk->isDirty());
727 writebacks[0/*pkt->req->getThreadNum()*/]++;
729 Request *writebackReq =
730 new Request(tags->regenerateBlkAddr(blk->tag, blk->set), blkSize, 0);
731 PacketPtr writeback = new Packet(writebackReq, MemCmd::Writeback, -1);
732 writeback->allocate();
733 std::memcpy(writeback->getPtr<uint8_t>(), blk->data, blkSize);
735 blk->status &= ~BlkDirty;
740 // Note that the reason we return a list of writebacks rather than
741 // inserting them directly in the write buffer is that this function
742 // is called by both atomic and timing-mode accesses, and in atomic
743 // mode we don't mess with the write buffer (we just perform the
744 // writebacks atomically once the original request is complete).
745 template<class TagStore>
746 typename Cache<TagStore>::BlkType*
747 Cache<TagStore>::handleFill(PacketPtr pkt, BlkType *blk,
748 PacketList &writebacks)
750 Addr addr = pkt->getAddr();
751 CacheBlk::State old_state = blk ? blk->status : 0;
754 // better have read new data...
755 assert(pkt->isRead());
757 // need to do a replacement
758 blk = tags->findReplacement(addr, writebacks);
759 if (blk->isValid()) {
760 Addr repl_addr = tags->regenerateBlkAddr(blk->tag, blk->set);
761 MSHR *repl_mshr = mshrQueue.findMatch(repl_addr);
763 // must be an outstanding upgrade request on block
764 // we're about to replace...
765 assert(!blk->isWritable());
766 assert(repl_mshr->needsExclusive);
767 // too hard to replace block with transient state;
768 // just use temporary storage to complete the current
769 // request and then get rid of it
770 assert(!tempBlock->isValid());
772 tempBlock->set = tags->extractSet(addr);
773 DPRINTF(Cache, "using temp block for %x\n", addr);
775 DPRINTF(Cache, "replacement: replacing %x with %x: %s\n",
777 blk->isDirty() ? "writeback" : "clean");
779 if (blk->isDirty()) {
780 // Save writeback packet for handling by caller
781 writebacks.push_back(writebackBlk(blk));
786 blk->tag = tags->extractTag(addr);
788 // existing block... probably an upgrade
789 assert(blk->tag == tags->extractTag(addr));
790 // either we're getting new data or the block should already be valid
791 assert(pkt->isRead() || blk->isValid());
794 if (pkt->needsExclusive()) {
795 blk->status = BlkValid | BlkWritable | BlkDirty;
796 } else if (!pkt->sharedAsserted()) {
797 blk->status = BlkValid | BlkWritable;
799 blk->status = BlkValid;
802 DPRINTF(Cache, "Block addr %x moving from state %i to %i\n",
803 addr, old_state, blk->status);
805 // if we got new data, copy it in
807 std::memcpy(blk->data, pkt->getPtr<uint8_t>(), blkSize);
810 blk->whenReady = pkt->finishTime;
816 /////////////////////////////////////////////////////
818 // Snoop path: requests coming in from the memory side
820 /////////////////////////////////////////////////////
822 template<class TagStore>
824 Cache<TagStore>::doTimingSupplyResponse(PacketPtr req_pkt,
828 // timing-mode snoop responses require a new packet, unless we
829 // already made a copy...
830 PacketPtr pkt = already_copied ? req_pkt : new Packet(req_pkt);
832 pkt->makeTimingResponse();
833 pkt->setDataFromBlock(blk_data, blkSize);
834 memSidePort->respond(pkt, curTick + hitLatency);
837 template<class TagStore>
839 Cache<TagStore>::handleSnoop(PacketPtr pkt, BlkType *blk,
840 bool is_timing, bool is_deferred)
842 if (!blk || !blk->isValid()) {
846 // we may end up modifying both the block state and the packet (if
847 // we respond in atomic mode), so just figure out what to do now
848 // and then do it later
849 bool supply = blk->isDirty() && pkt->isRead();
850 bool invalidate = pkt->isInvalidate();
852 if (pkt->isRead() && !pkt->isInvalidate()) {
853 assert(!pkt->needsExclusive());
855 int bits_to_clear = BlkWritable;
856 const bool haveOwnershipState = true; // for now
857 if (!haveOwnershipState) {
858 // if we don't support pure ownership (dirty && !writable),
859 // have to clear dirty bit here, assume memory snarfs data
860 // on cache-to-cache xfer
861 bits_to_clear |= BlkDirty;
863 blk->status &= ~bits_to_clear;
867 assert(!pkt->memInhibitAsserted());
868 pkt->assertMemInhibit();
870 doTimingSupplyResponse(pkt, blk->data, is_deferred);
872 pkt->makeAtomicResponse();
873 pkt->setDataFromBlock(blk->data, blkSize);
877 // Do this last in case it deallocates block data or something
880 tags->invalidateBlk(blk);
883 DPRINTF(Cache, "snooped a %s request for addr %x, %snew state is %i\n",
884 pkt->cmdString(), blockAlign(pkt->getAddr()),
885 supply ? "supplying data, " : "", blk->status);
889 template<class TagStore>
891 Cache<TagStore>::snoopTiming(PacketPtr pkt)
893 if (pkt->req->isUncacheable()) {
894 //Can't get a hit on an uncacheable address
895 //Revisit this for multi level coherence
899 BlkType *blk = tags->findBlock(pkt->getAddr());
901 Addr blk_addr = pkt->getAddr() & ~(Addr(blkSize-1));
902 MSHR *mshr = mshrQueue.findMatch(blk_addr);
903 // better not be snooping a request that conflicts with something
904 // we have outstanding...
905 if (mshr && mshr->inService) {
906 DPRINTF(Cache, "Deferring snoop on in-service MSHR to blk %x\n",
908 mshr->allocateSnoopTarget(pkt, curTick, order++);
909 if (mshr->getNumTargets() > numTarget)
910 warn("allocating bonus target for snoop"); //handle later
914 //We also need to check the writeback buffers and handle those
915 std::vector<MSHR *> writebacks;
916 if (writeBuffer.findMatches(blk_addr, writebacks)) {
917 DPRINTF(Cache, "Snoop hit in writeback to addr: %x\n",
920 //Look through writebacks for any non-uncachable writes, use that
921 for (int i=0; i<writebacks.size(); i++) {
922 mshr = writebacks[i];
923 assert(!mshr->isUncacheable());
924 assert(mshr->getNumTargets() == 1);
925 PacketPtr wb_pkt = mshr->getTarget()->pkt;
926 assert(wb_pkt->cmd == MemCmd::Writeback);
929 assert(!pkt->memInhibitAsserted());
930 pkt->assertMemInhibit();
931 if (!pkt->needsExclusive()) {
934 // if we're not asserting the shared line, we need to
935 // invalidate our copy. we'll do that below as long as
936 // the packet's invalidate flag is set...
937 assert(pkt->isInvalidate());
939 doTimingSupplyResponse(pkt, wb_pkt->getPtr<uint8_t>(), false);
942 if (pkt->isInvalidate()) {
943 // Invalidation trumps our writeback... discard here
950 handleSnoop(pkt, blk, true, false);
954 template<class TagStore>
956 Cache<TagStore>::snoopAtomic(PacketPtr pkt)
958 if (pkt->req->isUncacheable()) {
959 // Can't get a hit on an uncacheable address
960 // Revisit this for multi level coherence
964 BlkType *blk = tags->findBlock(pkt->getAddr());
965 handleSnoop(pkt, blk, false, false);
970 template<class TagStore>
972 Cache<TagStore>::getNextMSHR()
974 // Check both MSHR queue and write buffer for potential requests
975 MSHR *miss_mshr = mshrQueue.getNextMSHR();
976 MSHR *write_mshr = writeBuffer.getNextMSHR();
978 // Now figure out which one to send... some cases are easy
979 if (miss_mshr && !write_mshr) {
982 if (write_mshr && !miss_mshr) {
986 if (miss_mshr && write_mshr) {
987 // We have one of each... normally we favor the miss request
988 // unless the write buffer is full
989 if (writeBuffer.isFull() && writeBuffer.inServiceEntries == 0) {
990 // Write buffer is full, so we'd like to issue a write;
991 // need to search MSHR queue for conflicting earlier miss.
992 MSHR *conflict_mshr =
993 mshrQueue.findPending(write_mshr->addr, write_mshr->size);
995 if (conflict_mshr && conflict_mshr->order < write_mshr->order) {
996 // Service misses in order until conflict is cleared.
997 return conflict_mshr;
1000 // No conflicts; issue write
1004 // Write buffer isn't full, but need to check it for
1005 // conflicting earlier writeback
1006 MSHR *conflict_mshr =
1007 writeBuffer.findPending(miss_mshr->addr, miss_mshr->size);
1008 if (conflict_mshr) {
1009 // not sure why we don't check order here... it was in the
1010 // original code but commented out.
1012 // The only way this happens is if we are
1013 // doing a write and we didn't have permissions
1014 // then subsequently saw a writeback (owned got evicted)
1015 // We need to make sure to perform the writeback first
1016 // To preserve the dirty data, then we can issue the write
1018 // should we return write_mshr here instead? I.e. do we
1019 // have to flush writes in order? I don't think so... not
1020 // for Alpha anyway. Maybe for x86?
1021 return conflict_mshr;
1024 // No conflicts; issue read
1028 // fall through... no pending requests. Try a prefetch.
1029 assert(!miss_mshr && !write_mshr);
1030 if (!mshrQueue.isFull()) {
1031 // If we have a miss queue slot, we can try a prefetch
1032 PacketPtr pkt = prefetcher->getPacket();
1034 // Update statistic on number of prefetches issued
1035 // (hwpf_mshr_misses)
1036 mshr_misses[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++;
1037 // Don't request bus, since we already have it
1038 return allocateMissBuffer(pkt, curTick, false);
1046 template<class TagStore>
1048 Cache<TagStore>::getTimingPacket()
1050 MSHR *mshr = getNextMSHR();
1056 // use request from 1st target
1057 PacketPtr tgt_pkt = mshr->getTarget()->pkt;
1058 PacketPtr pkt = NULL;
1060 if (mshr->isSimpleForward()) {
1061 // no response expected, just forward packet as it is
1062 assert(tags->findBlock(mshr->addr) == NULL);
1065 BlkType *blk = tags->findBlock(mshr->addr);
1066 pkt = getBusPacket(tgt_pkt, blk, mshr->needsExclusive);
1068 mshr->isCacheFill = (pkt != NULL);
1071 // not a cache block request, but a response is expected
1072 assert(!mshr->isSimpleForward());
1073 // make copy of current packet to forward, keep current
1074 // copy for response handling
1075 pkt = new Packet(tgt_pkt);
1077 if (pkt->isWrite()) {
1078 pkt->setData(tgt_pkt->getPtr<uint8_t>());
1083 assert(pkt != NULL);
1084 pkt->senderState = mshr;
1095 template<class TagStore>
1097 Cache<TagStore>::CpuSidePort::
1098 getDeviceAddressRanges(AddrRangeList &resp, bool &snoop)
1100 // CPU side port doesn't snoop; it's a target only.
1102 otherPort->getPeerAddressRanges(resp, dummy);
1107 template<class TagStore>
1109 Cache<TagStore>::CpuSidePort::recvTiming(PacketPtr pkt)
1111 if (pkt->isRequest() && blocked) {
1112 DPRINTF(Cache,"Scheduling a retry while blocked\n");
1113 mustSendRetry = true;
1117 myCache()->timingAccess(pkt);
1122 template<class TagStore>
1124 Cache<TagStore>::CpuSidePort::recvAtomic(PacketPtr pkt)
1126 return myCache()->atomicAccess(pkt);
1130 template<class TagStore>
1132 Cache<TagStore>::CpuSidePort::recvFunctional(PacketPtr pkt)
1134 checkFunctional(pkt);
1135 if (!pkt->isResponse())
1136 myCache()->functionalAccess(pkt, cache->memSidePort);
1140 template<class TagStore>
1142 CpuSidePort::CpuSidePort(const std::string &_name,
1143 Cache<TagStore> *_cache)
1144 : BaseCache::CachePort(_name, _cache)
1154 template<class TagStore>
1156 Cache<TagStore>::MemSidePort::
1157 getDeviceAddressRanges(AddrRangeList &resp, bool &snoop)
1159 otherPort->getPeerAddressRanges(resp, snoop);
1160 // Memory-side port always snoops, so unconditionally set flag for
1166 template<class TagStore>
1168 Cache<TagStore>::MemSidePort::recvTiming(PacketPtr pkt)
1170 // this needs to be fixed so that the cache updates the mshr and sends the
1171 // packet back out on the link, but it probably won't happen so until this
1172 // gets fixed, just panic when it does
1173 if (pkt->wasNacked())
1174 panic("Need to implement cache resending nacked packets!\n");
1176 if (pkt->isRequest() && blocked) {
1177 DPRINTF(Cache,"Scheduling a retry while blocked\n");
1178 mustSendRetry = true;
1182 if (pkt->isResponse()) {
1183 myCache()->handleResponse(pkt);
1185 myCache()->snoopTiming(pkt);
1191 template<class TagStore>
1193 Cache<TagStore>::MemSidePort::recvAtomic(PacketPtr pkt)
1195 // in atomic mode, responses go back to the sender via the
1196 // function return from sendAtomic(), not via a separate
1197 // sendAtomic() from the responder. Thus we should never see a
1198 // response packet in recvAtomic() (anywhere, not just here).
1199 assert(!pkt->isResponse());
1200 return myCache()->snoopAtomic(pkt);
1204 template<class TagStore>
1206 Cache<TagStore>::MemSidePort::recvFunctional(PacketPtr pkt)
1208 checkFunctional(pkt);
1209 if (!pkt->isResponse())
1210 myCache()->functionalAccess(pkt, cache->cpuSidePort);
1215 template<class TagStore>
1217 Cache<TagStore>::MemSidePort::sendPacket()
1219 // if we have responses that are ready, they take precedence
1220 if (deferredPacketReady()) {
1221 bool success = sendTiming(transmitList.front().pkt);
1224 //send successful, remove packet
1225 transmitList.pop_front();
1228 waitingOnRetry = !success;
1230 // check for non-response packets (requests & writebacks)
1231 PacketPtr pkt = myCache()->getTimingPacket();
1233 // can happen if e.g. we attempt a writeback and fail, but
1234 // before the retry, the writeback is eliminated because
1235 // we snoop another cache's ReadEx.
1236 waitingOnRetry = false;
1238 MSHR *mshr = dynamic_cast<MSHR*>(pkt->senderState);
1240 bool success = sendTiming(pkt);
1242 "Address %x was %s in sending the timing request\n",
1243 pkt->getAddr(), success ? "successful" : "unsuccessful");
1245 waitingOnRetry = !success;
1246 if (waitingOnRetry) {
1247 DPRINTF(CachePort, "now waiting on a retry\n");
1248 if (!mshr->isSimpleForward()) {
1252 myCache()->markInService(mshr);
1258 // tried to send packet... if it was successful (no retry), see if
1259 // we need to rerequest bus or not
1260 if (!waitingOnRetry) {
1261 Tick nextReady = std::min(deferredPacketReadyTime(),
1262 myCache()->nextMSHRReadyTime());
1263 // @TODO: need to facotr in prefetch requests here somehow
1264 if (nextReady != MaxTick) {
1265 DPRINTF(CachePort, "more packets to send @ %d\n", nextReady);
1266 sendEvent->schedule(std::max(nextReady, curTick + 1));
1268 // no more to send right now: if we're draining, we may be done
1270 drainEvent->process();
1277 template<class TagStore>
1279 Cache<TagStore>::MemSidePort::recvRetry()
1281 assert(waitingOnRetry);
1286 template<class TagStore>
1288 Cache<TagStore>::MemSidePort::processSendEvent()
1290 assert(!waitingOnRetry);
1295 template<class TagStore>
1297 MemSidePort::MemSidePort(const std::string &_name, Cache<TagStore> *_cache)
1298 : BaseCache::CachePort(_name, _cache)
1300 // override default send event from SimpleTimingPort
1302 sendEvent = new SendEvent(this);