gem5  v19.0.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
cache.cc
Go to the documentation of this file.
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
9  * licensed hereunder. You may use the software subject to the license
10  * terms below provided that you ensure that this notice is replicated
11  * unmodified and in its entirety in all distributions of the software,
12  * modified or unmodified, in source code or in binary form.
13  *
14  * Copyright (c) 2002-2005 The Regents of The University of Michigan
15  * Copyright (c) 2010,2015 Advanced Micro Devices, Inc.
16  * All rights reserved.
17  *
18  * Redistribution and use in source and binary forms, with or without
19  * modification, are permitted provided that the following conditions are
20  * met: redistributions of source code must retain the above copyright
21  * notice, this list of conditions and the following disclaimer;
22  * redistributions in binary form must reproduce the above copyright
23  * notice, this list of conditions and the following disclaimer in the
24  * documentation and/or other materials provided with the distribution;
25  * neither the name of the copyright holders nor the names of its
26  * contributors may be used to endorse or promote products derived from
27  * this software without specific prior written permission.
28  *
29  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40  *
41  * Authors: Erik Hallnor
42  * Dave Greene
43  * Nathan Binkert
44  * Steve Reinhardt
45  * Ron Dreslinski
46  * Andreas Sandberg
47  * Nikos Nikoleris
48  */
49 
55 #include "mem/cache/cache.hh"
56 
57 #include <cassert>
58 
59 #include "base/compiler.hh"
60 #include "base/logging.hh"
61 #include "base/trace.hh"
62 #include "base/types.hh"
63 #include "debug/Cache.hh"
64 #include "debug/CacheTags.hh"
65 #include "debug/CacheVerbose.hh"
66 #include "enums/Clusivity.hh"
67 #include "mem/cache/cache_blk.hh"
68 #include "mem/cache/mshr.hh"
69 #include "mem/cache/tags/base.hh"
71 #include "mem/request.hh"
72 #include "params/Cache.hh"
73 
75  : BaseCache(p, p->system->cacheLineSize()),
76  doFastWrites(true)
77 {
78 }
79 
80 void
82  bool deferred_response, bool pending_downgrade)
83 {
84  BaseCache::satisfyRequest(pkt, blk);
85 
86  if (pkt->isRead()) {
87  // determine if this read is from a (coherent) cache or not
88  if (pkt->fromCache()) {
89  assert(pkt->getSize() == blkSize);
90  // special handling for coherent block requests from
91  // upper-level caches
92  if (pkt->needsWritable()) {
93  // sanity check
94  assert(pkt->cmd == MemCmd::ReadExReq ||
96  assert(!pkt->hasSharers());
97 
98  // if we have a dirty copy, make sure the recipient
99  // keeps it marked dirty (in the modified state)
100  if (blk->isDirty()) {
101  pkt->setCacheResponding();
102  blk->status &= ~BlkDirty;
103  }
104  } else if (blk->isWritable() && !pending_downgrade &&
105  !pkt->hasSharers() &&
106  pkt->cmd != MemCmd::ReadCleanReq) {
107  // we can give the requester a writable copy on a read
108  // request if:
109  // - we have a writable copy at this level (& below)
110  // - we don't have a pending snoop from below
111  // signaling another read request
112  // - no other cache above has a copy (otherwise it
113  // would have set hasSharers flag when
114  // snooping the packet)
115  // - the read has explicitly asked for a clean
116  // copy of the line
117  if (blk->isDirty()) {
118  // special considerations if we're owner:
119  if (!deferred_response) {
120  // respond with the line in Modified state
121  // (cacheResponding set, hasSharers not set)
122  pkt->setCacheResponding();
123 
124  // if this cache is mostly inclusive, we
125  // keep the block in the Exclusive state,
126  // and pass it upwards as Modified
127  // (writable and dirty), hence we have
128  // multiple caches, all on the same path
129  // towards memory, all considering the
130  // same block writable, but only one
131  // considering it Modified
132 
133  // we get away with multiple caches (on
134  // the same path to memory) considering
135  // the block writeable as we always enter
136  // the cache hierarchy through a cache,
137  // and first snoop upwards in all other
138  // branches
139  blk->status &= ~BlkDirty;
140  } else {
141  // if we're responding after our own miss,
142  // there's a window where the recipient didn't
143  // know it was getting ownership and may not
144  // have responded to snoops correctly, so we
145  // have to respond with a shared line
146  pkt->setHasSharers();
147  }
148  }
149  } else {
150  // otherwise only respond with a shared copy
151  pkt->setHasSharers();
152  }
153  }
154  }
155 }
156 
158 //
159 // Access path: requests coming in from the CPU side
160 //
162 
163 bool
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 
192 void
193 Cache::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 
234 void
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 
269 void
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
277  const bool forwardAsSnoop = outstandingSnoop.find(pkt->req) ==
278  outstandingSnoop.end();
279 
280  if (!forwardAsSnoop) {
281  // the packet came from this cache, so sink it here and do not
282  // forward it
283  assert(pkt->cmd == MemCmd::HardPFResp);
284 
285  outstandingSnoop.erase(pkt->req);
286 
287  DPRINTF(Cache, "Got prefetch response from above for addr "
288  "%#llx (%s)\n", pkt->getAddr(), pkt->isSecure() ? "s" : "ns");
289  recvTimingResp(pkt);
290  return;
291  }
292 
293  // forwardLatency is set here because there is a response from an
294  // upper level cache.
295  // To pay the delay that occurs if the packet comes from the bus,
296  // we charge also headerDelay.
297  Tick snoop_resp_time = clockEdge(forwardLatency) + pkt->headerDelay;
298  // Reset the timing of the packet.
299  pkt->headerDelay = pkt->payloadDelay = 0;
300  memSidePort.schedTimingSnoopResp(pkt, snoop_resp_time);
301 }
302 
303 void
305 {
306  // Cache line clearing instructions
307  if (doFastWrites && (pkt->cmd == MemCmd::WriteReq) &&
308  (pkt->getSize() == blkSize) && (pkt->getOffset(blkSize) == 0) &&
309  !pkt->isMaskedWrite()) {
310  pkt->cmd = MemCmd::WriteLineReq;
311  DPRINTF(Cache, "packet promoted from Write to WriteLineReq\n");
312  }
313 }
314 
315 void
317 {
318  // should never be satisfying an uncacheable access as we
319  // flush and invalidate any existing block as part of the
320  // lookup
321  assert(!pkt->req->isUncacheable());
322 
323  BaseCache::handleTimingReqHit(pkt, blk, request_time);
324 }
325 
326 void
328  Tick request_time)
329 {
330  if (pkt->req->isUncacheable()) {
331  // ignore any existing MSHR if we are dealing with an
332  // uncacheable request
333 
334  // should have flushed and have no valid block
335  assert(!blk || !blk->isValid());
336 
337  stats.cmdStats(pkt).mshr_uncacheable[pkt->req->masterId()]++;
338 
339  if (pkt->isWrite()) {
340  allocateWriteBuffer(pkt, forward_time);
341  } else {
342  assert(pkt->isRead());
343 
344  // uncacheable accesses always allocate a new MSHR
345 
346  // Here we are using forward_time, modelling the latency of
347  // a miss (outbound) just as forwardLatency, neglecting the
348  // lookupLatency component.
349  allocateMissBuffer(pkt, forward_time);
350  }
351 
352  return;
353  }
354 
355  Addr blk_addr = pkt->getBlockAddr(blkSize);
356 
357  MSHR *mshr = mshrQueue.findMatch(blk_addr, pkt->isSecure());
358 
359  // Software prefetch handling:
360  // To keep the core from waiting on data it won't look at
361  // anyway, send back a response with dummy data. Miss handling
362  // will continue asynchronously. Unfortunately, the core will
363  // insist upon freeing original Packet/Request, so we have to
364  // create a new pair with a different lifecycle. Note that this
365  // processing happens before any MSHR munging on the behalf of
366  // this request because this new Request will be the one stored
367  // into the MSHRs, not the original.
368  if (pkt->cmd.isSWPrefetch()) {
369  assert(pkt->needsResponse());
370  assert(pkt->req->hasPaddr());
371  assert(!pkt->req->isUncacheable());
372 
373  // There's no reason to add a prefetch as an additional target
374  // to an existing MSHR. If an outstanding request is already
375  // in progress, there is nothing for the prefetch to do.
376  // If this is the case, we don't even create a request at all.
377  PacketPtr pf = nullptr;
378 
379  if (!mshr) {
380  // copy the request and create a new SoftPFReq packet
381  RequestPtr req = std::make_shared<Request>(pkt->req->getPaddr(),
382  pkt->req->getSize(),
383  pkt->req->getFlags(),
384  pkt->req->masterId());
385  pf = new Packet(req, pkt->cmd);
386  pf->allocate();
387  assert(pf->matchAddr(pkt));
388  assert(pf->getSize() == pkt->getSize());
389  }
390 
391  pkt->makeTimingResponse();
392 
393  // request_time is used here, taking into account lat and the delay
394  // charged if the packet comes from the xbar.
395  cpuSidePort.schedTimingResp(pkt, request_time);
396 
397  // If an outstanding request is in progress (we found an
398  // MSHR) this is set to null
399  pkt = pf;
400  }
401 
402  BaseCache::handleTimingReqMiss(pkt, mshr, blk, forward_time, request_time);
403 }
404 
405 void
407 {
408  DPRINTF(CacheTags, "%s tags:\n%s\n", __func__, tags->print());
409 
411 
412  if (pkt->cacheResponding()) {
413  // a cache above us (but not where the packet came from) is
414  // responding to the request, in other words it has the line
415  // in Modified or Owned state
416  DPRINTF(Cache, "Cache above responding to %s: not responding\n",
417  pkt->print());
418 
419  // if the packet needs the block to be writable, and the cache
420  // that has promised to respond (setting the cache responding
421  // flag) is not providing writable (it is in Owned rather than
422  // the Modified state), we know that there may be other Shared
423  // copies in the system; go out and invalidate them all
424  assert(pkt->needsWritable() && !pkt->responderHadWritable());
425 
426  // an upstream cache that had the line in Owned state
427  // (dirty, but not writable), is responding and thus
428  // transferring the dirty line from one branch of the
429  // cache hierarchy to another
430 
431  // send out an express snoop and invalidate all other
432  // copies (snooping a packet that needs writable is the
433  // same as an invalidation), thus turning the Owned line
434  // into a Modified line, note that we don't invalidate the
435  // block in the current cache or any other cache on the
436  // path to memory
437 
438  // create a downstream express snoop with cleared packet
439  // flags, there is no need to allocate any data as the
440  // packet is merely used to co-ordinate state transitions
441  Packet *snoop_pkt = new Packet(pkt, true, false);
442 
443  // also reset the bus time that the original packet has
444  // not yet paid for
445  snoop_pkt->headerDelay = snoop_pkt->payloadDelay = 0;
446 
447  // make this an instantaneous express snoop, and let the
448  // other caches in the system know that the another cache
449  // is responding, because we have found the authorative
450  // copy (Modified or Owned) that will supply the right
451  // data
452  snoop_pkt->setExpressSnoop();
453  snoop_pkt->setCacheResponding();
454 
455  // this express snoop travels towards the memory, and at
456  // every crossbar it is snooped upwards thus reaching
457  // every cache in the system
458  bool M5_VAR_USED success = memSidePort.sendTimingReq(snoop_pkt);
459  // express snoops always succeed
460  assert(success);
461 
462  // main memory will delete the snoop packet
463 
464  // queue for deletion, as opposed to immediate deletion, as
465  // the sending cache is still relying on the packet
466  pendingDelete.reset(pkt);
467 
468  // no need to take any further action in this particular cache
469  // as an upstram cache has already committed to responding,
470  // and we have already sent out any express snoops in the
471  // section above to ensure all other copies in the system are
472  // invalidated
473  return;
474  }
475 
477 }
478 
479 PacketPtr
481  bool needsWritable,
482  bool is_whole_line_write) const
483 {
484  // should never see evictions here
485  assert(!cpu_pkt->isEviction());
486 
487  bool blkValid = blk && blk->isValid();
488 
489  if (cpu_pkt->req->isUncacheable() ||
490  (!blkValid && cpu_pkt->isUpgrade()) ||
491  cpu_pkt->cmd == MemCmd::InvalidateReq || cpu_pkt->isClean()) {
492  // uncacheable requests and upgrades from upper-level caches
493  // that missed completely just go through as is
494  return nullptr;
495  }
496 
497  assert(cpu_pkt->needsResponse());
498 
499  MemCmd cmd;
500  // @TODO make useUpgrades a parameter.
501  // Note that ownership protocols require upgrade, otherwise a
502  // write miss on a shared owned block will generate a ReadExcl,
503  // which will clobber the owned copy.
504  const bool useUpgrades = true;
505  assert(cpu_pkt->cmd != MemCmd::WriteLineReq || is_whole_line_write);
506  if (is_whole_line_write) {
507  assert(!blkValid || !blk->isWritable());
508  // forward as invalidate to all other caches, this gives us
509  // the line in Exclusive state, and invalidates all other
510  // copies
511  cmd = MemCmd::InvalidateReq;
512  } else if (blkValid && useUpgrades) {
513  // only reason to be here is that blk is read only and we need
514  // it to be writable
515  assert(needsWritable);
516  assert(!blk->isWritable());
517  cmd = cpu_pkt->isLLSC() ? MemCmd::SCUpgradeReq : MemCmd::UpgradeReq;
518  } else if (cpu_pkt->cmd == MemCmd::SCUpgradeFailReq ||
519  cpu_pkt->cmd == MemCmd::StoreCondFailReq) {
520  // Even though this SC will fail, we still need to send out the
521  // request and get the data to supply it to other snoopers in the case
522  // where the determination the StoreCond fails is delayed due to
523  // all caches not being on the same local bus.
525  } else {
526  // block is invalid
527 
528  // If the request does not need a writable there are two cases
529  // where we need to ensure the response will not fetch the
530  // block in dirty state:
531  // * this cache is read only and it does not perform
532  // writebacks,
533  // * this cache is mostly exclusive and will not fill (since
534  // it does not fill it will have to writeback the dirty data
535  // immediately which generates uneccesary writebacks).
536  bool force_clean_rsp = isReadOnly || clusivity == Enums::mostly_excl;
537  cmd = needsWritable ? MemCmd::ReadExReq :
538  (force_clean_rsp ? MemCmd::ReadCleanReq : MemCmd::ReadSharedReq);
539  }
540  PacketPtr pkt = new Packet(cpu_pkt->req, cmd, blkSize);
541 
542  // if there are upstream caches that have already marked the
543  // packet as having sharers (not passing writable), pass that info
544  // downstream
545  if (cpu_pkt->hasSharers() && !needsWritable) {
546  // note that cpu_pkt may have spent a considerable time in the
547  // MSHR queue and that the information could possibly be out
548  // of date, however, there is no harm in conservatively
549  // assuming the block has sharers
550  pkt->setHasSharers();
551  DPRINTF(Cache, "%s: passing hasSharers from %s to %s\n",
552  __func__, cpu_pkt->print(), pkt->print());
553  }
554 
555  // the packet should be block aligned
556  assert(pkt->getAddr() == pkt->getBlockAddr(blkSize));
557 
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 
565 Cycles
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
576  // request, it has been satisfied by a memory below and the
577  // packet carries the response back
578  assert(!(pkt->req->isUncacheable() && pkt->isWrite()) ||
579  pkt->isResponse());
580 
581  return latency;
582  }
583 
584  // only misses left
585 
586  PacketPtr bus_pkt = createMissPacket(pkt, blk, pkt->needsWritable(),
587  pkt->isWholeLineWrite(blkSize));
588 
589  bool is_forward = (bus_pkt == nullptr);
590 
591  if (is_forward) {
592  // just forwarding the same request to the next level
593  // no local cache operation involved
594  bus_pkt = pkt;
595  }
596 
597  DPRINTF(Cache, "%s: Sending an atomic %s\n", __func__,
598  bus_pkt->print());
599 
600 #if TRACING_ON
601  CacheBlk::State old_state = blk ? blk->status : 0;
602 #endif
603 
604  Cycles latency = ticksToCycles(memSidePort.sendAtomic(bus_pkt));
605 
606  bool is_invalidate = bus_pkt->isInvalidate();
607 
608  // We are now dealing with the response handling
609  DPRINTF(Cache, "%s: Receive response: %s in state %i\n", __func__,
610  bus_pkt->print(), old_state);
611 
612  // If packet was a forward, the response (if any) is already
613  // in place in the bus_pkt == pkt structure, so we don't need
614  // to do anything. Otherwise, use the separate bus_pkt to
615  // generate response to pkt and then delete it.
616  if (!is_forward) {
617  if (pkt->needsResponse()) {
618  assert(bus_pkt->isResponse());
619  if (bus_pkt->isError()) {
620  pkt->makeAtomicResponse();
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) &&
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  }
647  delete bus_pkt;
648  }
649 
650  if (is_invalidate && blk && blk->isValid()) {
651  invalidateBlock(blk);
652  }
653 
654  return latency;
655 }
656 
657 Tick
659 {
661 
662  // follow the same flow as in recvTimingReq, and check if a cache
663  // above us is responding
664  if (pkt->cacheResponding()) {
665  assert(!pkt->req->isCacheInvalidate());
666  DPRINTF(Cache, "Cache above responding to %s: not responding\n",
667  pkt->print());
668 
669  // if a cache is responding, and it had the line in Owned
670  // rather than Modified state, we need to invalidate any
671  // copies that are not on the same path to memory
672  assert(pkt->needsWritable() && !pkt->responderHadWritable());
673 
674  return memSidePort.sendAtomic(pkt);
675  }
676 
677  return BaseCache::recvAtomic(pkt);
678 }
679 
680 
682 //
683 // Response handling: responses from the memory side
684 //
686 
687 
688 void
690 {
691  QueueEntry::Target *initial_tgt = mshr->getTarget();
692  // First offset for critical word first calculations
693  const int initial_offset = initial_tgt->pkt->getOffset(blkSize);
694 
695  const bool is_error = pkt->isError();
696  // allow invalidation responses originating from write-line
697  // requests to be discarded
698  bool is_invalidate = pkt->isInvalidate() &&
699  !mshr->wasWholeLineWrite;
700 
701  MSHR::TargetList targets = mshr->extractServiceableTargets(pkt);
702  for (auto &target: targets) {
703  Packet *tgt_pkt = target.pkt;
704  switch (target.source) {
706  Tick completion_time;
707  // Here we charge on completion_time the delay of the xbar if the
708  // packet comes from it, charged on headerDelay.
709  completion_time = pkt->headerDelay;
710 
711  // Software prefetch handling for cache closest to core
712  if (tgt_pkt->cmd.isSWPrefetch()) {
713  if (tgt_pkt->needsWritable()) {
714  // All other copies of the block were invalidated and we
715  // have an exclusive copy.
716 
717  // The coherence protocol assumes that if we fetched an
718  // exclusive copy of the block, we have the intention to
719  // modify it. Therefore the MSHR for the PrefetchExReq has
720  // been the point of ordering and this cache has commited
721  // to respond to snoops for the block.
722  //
723  // In most cases this is true anyway - a PrefetchExReq
724  // will be followed by a WriteReq. However, if that
725  // doesn't happen, the block is not marked as dirty and
726  // the cache doesn't respond to snoops that has committed
727  // to do so.
728  //
729  // To avoid deadlocks in cases where there is a snoop
730  // between the PrefetchExReq and the expected WriteReq, we
731  // proactively mark the block as Dirty.
732  assert(blk);
733  blk->status |= BlkDirty;
734 
735  panic_if(isReadOnly, "Prefetch exclusive requests from "
736  "read-only cache %s\n", name());
737  }
738 
739  // a software prefetch would have already been ack'd
740  // immediately with dummy data so the core would be able to
741  // retire it. This request completes right here, so we
742  // deallocate it.
743  delete tgt_pkt;
744  break; // skip response
745  }
746 
747  // unlike the other packet flows, where data is found in other
748  // caches or memory and brought back, write-line requests always
749  // have the data right away, so the above check for "is fill?"
750  // cannot actually be determined until examining the stored MSHR
751  // state. We "catch up" with that logic here, which is duplicated
752  // from above.
753  if (tgt_pkt->cmd == MemCmd::WriteLineReq) {
754  assert(!is_error);
755  assert(blk);
756  assert(blk->isWritable());
757  }
758 
759  // Here we decide whether we will satisfy the target using
760  // data from the block or from the response. We use the
761  // block data to satisfy the request when the block is
762  // present and valid and in addition the response in not
763  // forwarding data to the cache above (we didn't fill
764  // either); otherwise we use the packet data.
765  if (blk && blk->isValid() &&
766  (!mshr->isForward || !pkt->hasData())) {
767  satisfyRequest(tgt_pkt, blk, true, mshr->hasPostDowngrade());
768 
769  // How many bytes past the first request is this one
770  int transfer_offset =
771  tgt_pkt->getOffset(blkSize) - initial_offset;
772  if (transfer_offset < 0) {
773  transfer_offset += blkSize;
774  }
775 
776  // If not critical word (offset) return payloadDelay.
777  // responseLatency is the latency of the return path
778  // from lower level caches/memory to an upper level cache or
779  // the core.
780  completion_time += clockEdge(responseLatency) +
781  (transfer_offset ? pkt->payloadDelay : 0);
782 
783  assert(!tgt_pkt->req->isUncacheable());
784 
785  assert(tgt_pkt->req->masterId() < system->maxMasters());
786  stats.cmdStats(tgt_pkt)
787  .missLatency[tgt_pkt->req->masterId()] +=
788  completion_time - target.recvTime;
789  } else if (pkt->cmd == MemCmd::UpgradeFailResp) {
790  // failed StoreCond upgrade
791  assert(tgt_pkt->cmd == MemCmd::StoreCondReq ||
792  tgt_pkt->cmd == MemCmd::StoreCondFailReq ||
793  tgt_pkt->cmd == MemCmd::SCUpgradeFailReq);
794  // responseLatency is the latency of the return path
795  // from lower level caches/memory to an upper level cache or
796  // the core.
797  completion_time += clockEdge(responseLatency) +
798  pkt->payloadDelay;
799  tgt_pkt->req->setExtraData(0);
800  } else {
801  if (is_invalidate && blk && blk->isValid()) {
802  // We are about to send a response to a cache above
803  // that asked for an invalidation; we need to
804  // invalidate our copy immediately as the most
805  // up-to-date copy of the block will now be in the
806  // cache above. It will also prevent this cache from
807  // responding (if the block was previously dirty) to
808  // snoops as they should snoop the caches above where
809  // they will get the response from.
810  invalidateBlock(blk);
811  }
812  // not a cache fill, just forwarding response
813  // responseLatency is the latency of the return path
814  // from lower level cahces/memory to the core.
815  completion_time += clockEdge(responseLatency) +
816  pkt->payloadDelay;
817  if (!is_error) {
818  if (pkt->isRead()) {
819  // sanity check
820  assert(pkt->matchAddr(tgt_pkt));
821  assert(pkt->getSize() >= tgt_pkt->getSize());
822 
823  tgt_pkt->setData(pkt->getConstPtr<uint8_t>());
824  } else {
825  // MSHR targets can read data either from the
826  // block or the response pkt. If we can't get data
827  // from the block (i.e., invalid or has old data)
828  // or the response (did not bring in any data)
829  // then make sure that the target didn't expect
830  // any.
831  assert(!tgt_pkt->hasRespData());
832  }
833  }
834 
835  // this response did not allocate here and therefore
836  // it was not consumed, make sure that any flags are
837  // carried over to cache above
838  tgt_pkt->copyResponderFlags(pkt);
839  }
840  tgt_pkt->makeTimingResponse();
841  // if this packet is an error copy that to the new packet
842  if (is_error)
843  tgt_pkt->copyError(pkt);
844  if (tgt_pkt->cmd == MemCmd::ReadResp &&
845  (is_invalidate || mshr->hasPostInvalidate())) {
846  // If intermediate cache got ReadRespWithInvalidate,
847  // propagate that. Response should not have
848  // isInvalidate() set otherwise.
850  DPRINTF(Cache, "%s: updated cmd to %s\n", __func__,
851  tgt_pkt->print());
852  }
853  // Reset the bus additional time as it is now accounted for
854  tgt_pkt->headerDelay = tgt_pkt->payloadDelay = 0;
855  cpuSidePort.schedTimingResp(tgt_pkt, completion_time);
856  break;
857 
859  assert(tgt_pkt->cmd == MemCmd::HardPFReq);
860  if (blk)
861  blk->status |= BlkHWPrefetched;
862  delete tgt_pkt;
863  break;
864 
866  // I don't believe that a snoop can be in an error state
867  assert(!is_error);
868  // response to snoop request
869  DPRINTF(Cache, "processing deferred snoop...\n");
870  // If the response is invalidating, a snooping target can
871  // be satisfied if it is also invalidating. If the reponse is, not
872  // only invalidating, but more specifically an InvalidateResp and
873  // the MSHR was created due to an InvalidateReq then a cache above
874  // is waiting to satisfy a WriteLineReq. In this case even an
875  // non-invalidating snoop is added as a target here since this is
876  // the ordering point. When the InvalidateResp reaches this cache,
877  // the snooping target will snoop further the cache above with the
878  // WriteLineReq.
879  assert(!is_invalidate || pkt->cmd == MemCmd::InvalidateResp ||
880  pkt->req->isCacheMaintenance() ||
881  mshr->hasPostInvalidate());
882  handleSnoop(tgt_pkt, blk, true, true, mshr->hasPostInvalidate());
883  break;
884 
885  default:
886  panic("Illegal target->source enum %d\n", target.source);
887  }
888  }
889 
890  maintainClusivity(targets.hasFromCache, blk);
891 
892  if (blk && blk->isValid()) {
893  // an invalidate response stemming from a write line request
894  // should not invalidate the block, so check if the
895  // invalidation should be discarded
896  if (is_invalidate || mshr->hasPostInvalidate()) {
897  invalidateBlock(blk);
898  } else if (mshr->hasPostDowngrade()) {
899  blk->status &= ~BlkWritable;
900  }
901  }
902 }
903 
904 PacketPtr
906 {
907  PacketPtr pkt = (blk->isDirty() || writebackClean) ?
908  writebackBlk(blk) : cleanEvictBlk(blk);
909 
910  invalidateBlock(blk);
911 
912  return pkt;
913 }
914 
915 PacketPtr
917 {
918  assert(!writebackClean);
919  assert(blk && blk->isValid() && !blk->isDirty());
920 
921  // Creating a zero sized write, a message to the snoop filter
922  RequestPtr req = std::make_shared<Request>(
924 
925  if (blk->isSecure())
926  req->setFlags(Request::SECURE);
927 
928  req->taskId(blk->task_id);
929 
930  PacketPtr pkt = new Packet(req, MemCmd::CleanEvict);
931  pkt->allocate();
932  DPRINTF(Cache, "Create CleanEvict %s\n", pkt->print());
933 
934  return pkt;
935 }
936 
938 //
939 // Snoop path: requests coming in from the memory side
940 //
942 
943 void
944 Cache::doTimingSupplyResponse(PacketPtr req_pkt, const uint8_t *blk_data,
945  bool already_copied, bool pending_inval)
946 {
947  // sanity check
948  assert(req_pkt->isRequest());
949  assert(req_pkt->needsResponse());
950 
951  DPRINTF(Cache, "%s: for %s\n", __func__, req_pkt->print());
952  // timing-mode snoop responses require a new packet, unless we
953  // already made a copy...
954  PacketPtr pkt = req_pkt;
955  if (!already_copied)
956  // do not clear flags, and allocate space for data if the
957  // packet needs it (the only packets that carry data are read
958  // responses)
959  pkt = new Packet(req_pkt, false, req_pkt->isRead());
960 
961  assert(req_pkt->req->isUncacheable() || req_pkt->isInvalidate() ||
962  pkt->hasSharers());
963  pkt->makeTimingResponse();
964  if (pkt->isRead()) {
965  pkt->setDataFromBlock(blk_data, blkSize);
966  }
967  if (pkt->cmd == MemCmd::ReadResp && pending_inval) {
968  // Assume we defer a response to a read from a far-away cache
969  // A, then later defer a ReadExcl from a cache B on the same
970  // bus as us. We'll assert cacheResponding in both cases, but
971  // in the latter case cacheResponding will keep the
972  // invalidation from reaching cache A. This special response
973  // tells cache A that it gets the block to satisfy its read,
974  // but must immediately invalidate it.
976  }
977  // Here we consider forward_time, paying for just forward latency and
978  // also charging the delay provided by the xbar.
979  // forward_time is used as send_time in next allocateWriteBuffer().
980  Tick forward_time = clockEdge(forwardLatency) + pkt->headerDelay;
981  // Here we reset the timing of the packet.
982  pkt->headerDelay = pkt->payloadDelay = 0;
983  DPRINTF(CacheVerbose, "%s: created response: %s tick: %lu\n", __func__,
984  pkt->print(), forward_time);
985  memSidePort.schedTimingSnoopResp(pkt, forward_time);
986 }
987 
988 uint32_t
989 Cache::handleSnoop(PacketPtr pkt, CacheBlk *blk, bool is_timing,
990  bool is_deferred, bool pending_inval)
991 {
992  DPRINTF(CacheVerbose, "%s: for %s\n", __func__, pkt->print());
993  // deferred snoops can only happen in timing mode
994  assert(!(is_deferred && !is_timing));
995  // pending_inval only makes sense on deferred snoops
996  assert(!(pending_inval && !is_deferred));
997  assert(pkt->isRequest());
998 
999  // the packet may get modified if we or a forwarded snooper
1000  // responds in atomic mode, so remember a few things about the
1001  // original packet up front
1002  bool invalidate = pkt->isInvalidate();
1003  bool M5_VAR_USED needs_writable = pkt->needsWritable();
1004 
1005  // at the moment we could get an uncacheable write which does not
1006  // have the invalidate flag, and we need a suitable way of dealing
1007  // with this case
1008  panic_if(invalidate && pkt->req->isUncacheable(),
1009  "%s got an invalidating uncacheable snoop request %s",
1010  name(), pkt->print());
1011 
1012  uint32_t snoop_delay = 0;
1013 
1014  if (forwardSnoops) {
1015  // first propagate snoop upward to see if anyone above us wants to
1016  // handle it. save & restore packet src since it will get
1017  // rewritten to be relative to cpu-side bus (if any)
1018  if (is_timing) {
1019  // copy the packet so that we can clear any flags before
1020  // forwarding it upwards, we also allocate data (passing
1021  // the pointer along in case of static data), in case
1022  // there is a snoop hit in upper levels
1023  Packet snoopPkt(pkt, true, true);
1024  snoopPkt.setExpressSnoop();
1025  // the snoop packet does not need to wait any additional
1026  // time
1027  snoopPkt.headerDelay = snoopPkt.payloadDelay = 0;
1028  cpuSidePort.sendTimingSnoopReq(&snoopPkt);
1029 
1030  // add the header delay (including crossbar and snoop
1031  // delays) of the upward snoop to the snoop delay for this
1032  // cache
1033  snoop_delay += snoopPkt.headerDelay;
1034 
1035  // If this request is a prefetch or clean evict and an upper level
1036  // signals block present, make sure to propagate the block
1037  // presence to the requester.
1038  if (snoopPkt.isBlockCached()) {
1039  pkt->setBlockCached();
1040  }
1041  // If the request was satisfied by snooping the cache
1042  // above, mark the original packet as satisfied too.
1043  if (snoopPkt.satisfied()) {
1044  pkt->setSatisfied();
1045  }
1046 
1047  // Copy over flags from the snoop response to make sure we
1048  // inform the final destination
1049  pkt->copyResponderFlags(&snoopPkt);
1050  } else {
1051  bool already_responded = pkt->cacheResponding();
1053  if (!already_responded && pkt->cacheResponding()) {
1054  // cache-to-cache response from some upper cache:
1055  // forward response to original requester
1056  assert(pkt->isResponse());
1057  }
1058  }
1059  }
1060 
1061  bool respond = false;
1062  bool blk_valid = blk && blk->isValid();
1063  if (pkt->isClean()) {
1064  if (blk_valid && blk->isDirty()) {
1065  DPRINTF(CacheVerbose, "%s: packet (snoop) %s found block: %s\n",
1066  __func__, pkt->print(), blk->print());
1067  PacketPtr wb_pkt = writecleanBlk(blk, pkt->req->getDest(), pkt->id);
1068  PacketList writebacks;
1069  writebacks.push_back(wb_pkt);
1070 
1071  if (is_timing) {
1072  // anything that is merely forwarded pays for the forward
1073  // latency and the delay provided by the crossbar
1074  Tick forward_time = clockEdge(forwardLatency) +
1075  pkt->headerDelay;
1076  doWritebacks(writebacks, forward_time);
1077  } else {
1078  doWritebacksAtomic(writebacks);
1079  }
1080  pkt->setSatisfied();
1081  }
1082  } else if (!blk_valid) {
1083  DPRINTF(CacheVerbose, "%s: snoop miss for %s\n", __func__,
1084  pkt->print());
1085  if (is_deferred) {
1086  // we no longer have the block, and will not respond, but a
1087  // packet was allocated in MSHR::handleSnoop and we have
1088  // to delete it
1089  assert(pkt->needsResponse());
1090 
1091  // we have passed the block to a cache upstream, that
1092  // cache should be responding
1093  assert(pkt->cacheResponding());
1094 
1095  delete pkt;
1096  }
1097  return snoop_delay;
1098  } else {
1099  DPRINTF(Cache, "%s: snoop hit for %s, old state is %s\n", __func__,
1100  pkt->print(), blk->print());
1101 
1102  // We may end up modifying both the block state and the packet (if
1103  // we respond in atomic mode), so just figure out what to do now
1104  // and then do it later. We respond to all snoops that need
1105  // responses provided we have the block in dirty state. The
1106  // invalidation itself is taken care of below. We don't respond to
1107  // cache maintenance operations as this is done by the destination
1108  // xbar.
1109  respond = blk->isDirty() && pkt->needsResponse();
1110 
1111  chatty_assert(!(isReadOnly && blk->isDirty()), "Should never have "
1112  "a dirty block in a read-only cache %s\n", name());
1113  }
1114 
1115  // Invalidate any prefetch's from below that would strip write permissions
1116  // MemCmd::HardPFReq is only observed by upstream caches. After missing
1117  // above and in it's own cache, a new MemCmd::ReadReq is created that
1118  // downstream caches observe.
1119  if (pkt->mustCheckAbove()) {
1120  DPRINTF(Cache, "Found addr %#llx in upper level cache for snoop %s "
1121  "from lower cache\n", pkt->getAddr(), pkt->print());
1122  pkt->setBlockCached();
1123  return snoop_delay;
1124  }
1125 
1126  if (pkt->isRead() && !invalidate) {
1127  // reading without requiring the line in a writable state
1128  assert(!needs_writable);
1129  pkt->setHasSharers();
1130 
1131  // if the requesting packet is uncacheable, retain the line in
1132  // the current state, otherwhise unset the writable flag,
1133  // which means we go from Modified to Owned (and will respond
1134  // below), remain in Owned (and will respond below), from
1135  // Exclusive to Shared, or remain in Shared
1136  if (!pkt->req->isUncacheable())
1137  blk->status &= ~BlkWritable;
1138  DPRINTF(Cache, "new state is %s\n", blk->print());
1139  }
1140 
1141  if (respond) {
1142  // prevent anyone else from responding, cache as well as
1143  // memory, and also prevent any memory from even seeing the
1144  // request
1145  pkt->setCacheResponding();
1146  if (!pkt->isClean() && blk->isWritable()) {
1147  // inform the cache hierarchy that this cache had the line
1148  // in the Modified state so that we avoid unnecessary
1149  // invalidations (see Packet::setResponderHadWritable)
1150  pkt->setResponderHadWritable();
1151 
1152  // in the case of an uncacheable request there is no point
1153  // in setting the responderHadWritable flag, but since the
1154  // recipient does not care there is no harm in doing so
1155  } else {
1156  // if the packet has needsWritable set we invalidate our
1157  // copy below and all other copies will be invalidates
1158  // through express snoops, and if needsWritable is not set
1159  // we already called setHasSharers above
1160  }
1161 
1162  // if we are returning a writable and dirty (Modified) line,
1163  // we should be invalidating the line
1164  panic_if(!invalidate && !pkt->hasSharers(),
1165  "%s is passing a Modified line through %s, "
1166  "but keeping the block", name(), pkt->print());
1167 
1168  if (is_timing) {
1169  doTimingSupplyResponse(pkt, blk->data, is_deferred, pending_inval);
1170  } else {
1171  pkt->makeAtomicResponse();
1172  // packets such as upgrades do not actually have any data
1173  // payload
1174  if (pkt->hasData())
1175  pkt->setDataFromBlock(blk->data, blkSize);
1176  }
1177 
1178  // When a block is compressed, it must first be decompressed before
1179  // being read, and this increases the snoop delay.
1180  if (compressor && pkt->isRead()) {
1181  snoop_delay += compressor->getDecompressionLatency(blk);
1182  }
1183  }
1184 
1185  if (!respond && is_deferred) {
1186  assert(pkt->needsResponse());
1187  delete pkt;
1188  }
1189 
1190  // Do this last in case it deallocates block data or something
1191  // like that
1192  if (blk_valid && invalidate) {
1193  invalidateBlock(blk);
1194  DPRINTF(Cache, "new state is %s\n", blk->print());
1195  }
1196 
1197  return snoop_delay;
1198 }
1199 
1200 
1201 void
1203 {
1204  DPRINTF(CacheVerbose, "%s: for %s\n", __func__, pkt->print());
1205 
1206  // no need to snoop requests that are not in range
1207  if (!inRange(pkt->getAddr())) {
1208  return;
1209  }
1210 
1211  bool is_secure = pkt->isSecure();
1212  CacheBlk *blk = tags->findBlock(pkt->getAddr(), is_secure);
1213 
1214  Addr blk_addr = pkt->getBlockAddr(blkSize);
1215  MSHR *mshr = mshrQueue.findMatch(blk_addr, is_secure);
1216 
1217  // Update the latency cost of the snoop so that the crossbar can
1218  // account for it. Do not overwrite what other neighbouring caches
1219  // have already done, rather take the maximum. The update is
1220  // tentative, for cases where we return before an upward snoop
1221  // happens below.
1222  pkt->snoopDelay = std::max<uint32_t>(pkt->snoopDelay,
1224 
1225  // Inform request(Prefetch, CleanEvict or Writeback) from below of
1226  // MSHR hit, set setBlockCached.
1227  if (mshr && pkt->mustCheckAbove()) {
1228  DPRINTF(Cache, "Setting block cached for %s from lower cache on "
1229  "mshr hit\n", pkt->print());
1230  pkt->setBlockCached();
1231  return;
1232  }
1233 
1234  // Let the MSHR itself track the snoop and decide whether we want
1235  // to go ahead and do the regular cache snoop
1236  if (mshr && mshr->handleSnoop(pkt, order++)) {
1237  DPRINTF(Cache, "Deferring snoop on in-service MSHR to blk %#llx (%s)."
1238  "mshrs: %s\n", blk_addr, is_secure ? "s" : "ns",
1239  mshr->print());
1240 
1241  if (mshr->getNumTargets() > numTarget)
1242  warn("allocating bonus target for snoop"); //handle later
1243  return;
1244  }
1245 
1246  //We also need to check the writeback buffers and handle those
1247  WriteQueueEntry *wb_entry = writeBuffer.findMatch(blk_addr, is_secure);
1248  if (wb_entry) {
1249  DPRINTF(Cache, "Snoop hit in writeback to addr %#llx (%s)\n",
1250  pkt->getAddr(), is_secure ? "s" : "ns");
1251  // Expect to see only Writebacks and/or CleanEvicts here, both of
1252  // which should not be generated for uncacheable data.
1253  assert(!wb_entry->isUncacheable());
1254  // There should only be a single request responsible for generating
1255  // Writebacks/CleanEvicts.
1256  assert(wb_entry->getNumTargets() == 1);
1257  PacketPtr wb_pkt = wb_entry->getTarget()->pkt;
1258  assert(wb_pkt->isEviction() || wb_pkt->cmd == MemCmd::WriteClean);
1259 
1260  if (pkt->isEviction()) {
1261  // if the block is found in the write queue, set the BLOCK_CACHED
1262  // flag for Writeback/CleanEvict snoop. On return the snoop will
1263  // propagate the BLOCK_CACHED flag in Writeback packets and prevent
1264  // any CleanEvicts from travelling down the memory hierarchy.
1265  pkt->setBlockCached();
1266  DPRINTF(Cache, "%s: Squashing %s from lower cache on writequeue "
1267  "hit\n", __func__, pkt->print());
1268  return;
1269  }
1270 
1271  // conceptually writebacks are no different to other blocks in
1272  // this cache, so the behaviour is modelled after handleSnoop,
1273  // the difference being that instead of querying the block
1274  // state to determine if it is dirty and writable, we use the
1275  // command and fields of the writeback packet
1276  bool respond = wb_pkt->cmd == MemCmd::WritebackDirty &&
1277  pkt->needsResponse();
1278  bool have_writable = !wb_pkt->hasSharers();
1279  bool invalidate = pkt->isInvalidate();
1280 
1281  if (!pkt->req->isUncacheable() && pkt->isRead() && !invalidate) {
1282  assert(!pkt->needsWritable());
1283  pkt->setHasSharers();
1284  wb_pkt->setHasSharers();
1285  }
1286 
1287  if (respond) {
1288  pkt->setCacheResponding();
1289 
1290  if (have_writable) {
1291  pkt->setResponderHadWritable();
1292  }
1293 
1294  doTimingSupplyResponse(pkt, wb_pkt->getConstPtr<uint8_t>(),
1295  false, false);
1296  }
1297 
1298  if (invalidate && wb_pkt->cmd != MemCmd::WriteClean) {
1299  // Invalidation trumps our writeback... discard here
1300  // Note: markInService will remove entry from writeback buffer.
1301  markInService(wb_entry);
1302  delete wb_pkt;
1303  }
1304  }
1305 
1306  // If this was a shared writeback, there may still be
1307  // other shared copies above that require invalidation.
1308  // We could be more selective and return here if the
1309  // request is non-exclusive or if the writeback is
1310  // exclusive.
1311  uint32_t snoop_delay = handleSnoop(pkt, blk, true, false, false);
1312 
1313  // Override what we did when we first saw the snoop, as we now
1314  // also have the cost of the upwards snoops to account for
1315  pkt->snoopDelay = std::max<uint32_t>(pkt->snoopDelay, snoop_delay +
1317 }
1318 
1319 Tick
1321 {
1322  // no need to snoop requests that are not in range.
1323  if (!inRange(pkt->getAddr())) {
1324  return 0;
1325  }
1326 
1327  CacheBlk *blk = tags->findBlock(pkt->getAddr(), pkt->isSecure());
1328  uint32_t snoop_delay = handleSnoop(pkt, blk, false, false, false);
1329  return snoop_delay + lookupLatency * clockPeriod();
1330 }
1331 
1332 bool
1333 Cache::isCachedAbove(PacketPtr pkt, bool is_timing)
1334 {
1335  if (!forwardSnoops)
1336  return false;
1337  // Mirroring the flow of HardPFReqs, the cache sends CleanEvict and
1338  // Writeback snoops into upper level caches to check for copies of the
1339  // same block. Using the BLOCK_CACHED flag with the Writeback/CleanEvict
1340  // packet, the cache can inform the crossbar below of presence or absence
1341  // of the block.
1342  if (is_timing) {
1343  Packet snoop_pkt(pkt, true, false);
1344  snoop_pkt.setExpressSnoop();
1345  // Assert that packet is either Writeback or CleanEvict and not a
1346  // prefetch request because prefetch requests need an MSHR and may
1347  // generate a snoop response.
1348  assert(pkt->isEviction() || pkt->cmd == MemCmd::WriteClean);
1349  snoop_pkt.senderState = nullptr;
1350  cpuSidePort.sendTimingSnoopReq(&snoop_pkt);
1351  // Writeback/CleanEvict snoops do not generate a snoop response.
1352  assert(!(snoop_pkt.cacheResponding()));
1353  return snoop_pkt.isBlockCached();
1354  } else {
1356  return pkt->isBlockCached();
1357  }
1358 }
1359 
1360 bool
1362 {
1363  assert(mshr);
1364 
1365  // use request from 1st target
1366  PacketPtr tgt_pkt = mshr->getTarget()->pkt;
1367 
1368  if (tgt_pkt->cmd == MemCmd::HardPFReq && forwardSnoops) {
1369  DPRINTF(Cache, "%s: MSHR %s\n", __func__, tgt_pkt->print());
1370 
1371  // we should never have hardware prefetches to allocated
1372  // blocks
1373  assert(!tags->findBlock(mshr->blkAddr, mshr->isSecure));
1374 
1375  // We need to check the caches above us to verify that
1376  // they don't have a copy of this block in the dirty state
1377  // at the moment. Without this check we could get a stale
1378  // copy from memory that might get used in place of the
1379  // dirty one.
1380  Packet snoop_pkt(tgt_pkt, true, false);
1381  snoop_pkt.setExpressSnoop();
1382  // We are sending this packet upwards, but if it hits we will
1383  // get a snoop response that we end up treating just like a
1384  // normal response, hence it needs the MSHR as its sender
1385  // state
1386  snoop_pkt.senderState = mshr;
1387  cpuSidePort.sendTimingSnoopReq(&snoop_pkt);
1388 
1389  // Check to see if the prefetch was squashed by an upper cache (to
1390  // prevent us from grabbing the line) or if a Check to see if a
1391  // writeback arrived between the time the prefetch was placed in
1392  // the MSHRs and when it was selected to be sent or if the
1393  // prefetch was squashed by an upper cache.
1394 
1395  // It is important to check cacheResponding before
1396  // prefetchSquashed. If another cache has committed to
1397  // responding, it will be sending a dirty response which will
1398  // arrive at the MSHR allocated for this request. Checking the
1399  // prefetchSquash first may result in the MSHR being
1400  // prematurely deallocated.
1401  if (snoop_pkt.cacheResponding()) {
1402  auto M5_VAR_USED r = outstandingSnoop.insert(snoop_pkt.req);
1403  assert(r.second);
1404 
1405  // if we are getting a snoop response with no sharers it
1406  // will be allocated as Modified
1407  bool pending_modified_resp = !snoop_pkt.hasSharers();
1408  markInService(mshr, pending_modified_resp);
1409 
1410  DPRINTF(Cache, "Upward snoop of prefetch for addr"
1411  " %#x (%s) hit\n",
1412  tgt_pkt->getAddr(), tgt_pkt->isSecure()? "s": "ns");
1413  return false;
1414  }
1415 
1416  if (snoop_pkt.isBlockCached()) {
1417  DPRINTF(Cache, "Block present, prefetch squashed by cache. "
1418  "Deallocating mshr target %#x.\n",
1419  mshr->blkAddr);
1420 
1421  // Deallocate the mshr target
1422  if (mshrQueue.forceDeallocateTarget(mshr)) {
1423  // Clear block if this deallocation resulted freed an
1424  // mshr when all had previously been utilized
1426  }
1427 
1428  // given that no response is expected, delete Request and Packet
1429  delete tgt_pkt;
1430 
1431  return false;
1432  }
1433  }
1434 
1435  return BaseCache::sendMSHRQueuePacket(mshr);
1436 }
1437 
1438 Cache*
1439 CacheParams::create()
1440 {
1441  assert(tags);
1442  assert(replacement_policy);
1443 
1444  return new Cache(this);
1445 }
Miss Status and Handling Register (MSHR) declaration.
virtual bool access(PacketPtr pkt, CacheBlk *&blk, Cycles &lat, PacketList &writebacks)
Does all the processing necessary to perform the provided request.
Definition: base.cc:1033
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:167
#define DPRINTF(x,...)
Definition: trace.hh:229
virtual CacheBlk * findBlock(Addr addr, bool is_secure) const
Finds the block in the cache without touching it.
Definition: base.cc:80
void doWritebacks(PacketList &writebacks, Tick forward_time) override
Insert writebacks into the write buffer.
Definition: cache.cc:193
bool forwardSnoops
Do we forward snoops from mem side port through to cpu side port?
Definition: base.hh:883
const PacketId id
Definition: packet.hh:324
bool isSecure
True if the entry targets the secure memory space.
Definition: queue_entry.hh:120
void setResponderHadWritable()
On responding to a snoop request (which only happens for Modified or Owned lines), make sure that we can transform an Owned response to a Modified one.
Definition: packet.hh:645
bool hasPostInvalidate() const
Definition: mshr.hh:325
PacketPtr writebackBlk(CacheBlk *blk)
Create a writeback request for the given block.
Definition: base.cc:1488
void setHasSharers()
On fills, the hasSharers flag is used by the caches in combination with the cacheResponding flag...
Definition: packet.hh:617
bool mustCheckAbove() const
Does the request need to check for cached copies of the same block in the memory hierarchy above...
Definition: packet.hh:1290
void recvTimingSnoopReq(PacketPtr pkt) override
Snoops bus transactions to maintain coherence.
Definition: cache.cc:1202
State status
The current status of this block.
Definition: cache_blk.hh:108
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:83
void serviceMSHRTargets(MSHR *mshr, const PacketPtr pkt, CacheBlk *blk) override
Service non-deferred MSHR targets using the received response.
Definition: cache.cc:689
Definition: packet.hh:76
Tick recvAtomic(PacketPtr pkt) override
Performs the access specified by the request.
Definition: cache.cc:658
Stats::Vector missLatency
Total number of cycles per thread/command spent waiting for a miss.
Definition: base.hh:951
bool isValid() const
Checks that a block is valid.
Definition: cache_blk.hh:206
CpuSidePort cpuSidePort
Definition: base.hh:312
bool isWritable() const
Checks the write permissions of this block.
Definition: cache_blk.hh:184
WriteQueue writeBuffer
Write/writeback buffer.
Definition: base.hh:321
std::string print() const override
Pretty-print tag, set and way, and interpret state bits to readable form including mapping to a MOESI...
Definition: cache_blk.hh:349
Write queue entry.
uint32_t snoopDelay
Keep track of the extra delay incurred by snooping upwards before sending a request down the memory s...
Definition: packet.hh:374
void makeTimingResponse()
Definition: packet.hh:955
bool isUpgrade() const
Definition: packet.hh:530
bool forceDeallocateTarget(MSHR *mshr)
Deallocate top target, possibly freeing the MSHR.
Definition: mshr_queue.cc:120
int getNumTargets() const
Returns the current number of allocated targets.
Definition: mshr.hh:425
const Cycles lookupLatency
The latency of tag lookup of a cache.
Definition: base.hh:849
Declaration of a request, the overall memory request consisting of the parts of the request that are ...
std::shared_ptr< Request > RequestPtr
Definition: request.hh:83
bool hasPostDowngrade() const
Definition: mshr.hh:329
const Enums::Clusivity clusivity
Clusivity with respect to the upstream cache, determining if we fill into both this cache and the cac...
Definition: base.hh:890
bool isSWPrefetch() const
Definition: packet.hh:222
Tick sendAtomicSnoop(PacketPtr pkt)
Send an atomic snoop request packet, where the data is moved and the state is updated in zero time...
Definition: port.hh:321
bool isClean() const
Definition: packet.hh:545
System * system
System we are currently operating in.
Definition: base.hh:925
bool cacheResponding() const
Definition: packet.hh:591
void handleTimingReqHit(PacketPtr pkt, CacheBlk *blk, Tick request_time) override
Definition: cache.cc:316
const bool isReadOnly
Is this cache read only, for example the instruction cache, or table-walker cache.
Definition: base.hh:898
virtual void handleTimingReqMiss(PacketPtr pkt, CacheBlk *blk, Tick forward_time, Tick request_time)=0
BaseCache::CacheStats stats
void invalidateBlock(CacheBlk *blk)
Invalidate a cache block.
Definition: base.cc:1462
The request targets the secure memory space.
Definition: request.hh:176
void doWritebacksAtomic(PacketList &writebacks) override
Send writebacks down the memory hierarchy in atomic mode.
Definition: cache.cc:235
MSHR * allocateMissBuffer(PacketPtr pkt, Tick time, bool sched_send=true)
Definition: base.hh:1101
bool allocate() const
Should writes allocate?
Definition: base.hh:1332
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the slave port by calling its corresponding receive function...
Definition: port.hh:445
M5_NODISCARD PacketPtr evictBlock(CacheBlk *blk) override
Evict a cache block.
Definition: cache.cc:905
WriteAllocator *const writeAllocator
The writeAllocator drive optimizations for streaming writes.
Definition: base.hh:355
Tick clockPeriod() const
bool isWrite() const
Definition: packet.hh:529
bool isInvalidate() const
Definition: packet.hh:543
void setSatisfied()
Set when a request hits in a cache and the cache is not going to respond.
Definition: packet.hh:681
bool isRead() const
Definition: packet.hh:528
#define chatty_assert(cond,...)
The chatty assert macro will function like a normal assert, but will allow the specification of addit...
Definition: logging.hh:252
This master id is used for writeback requests by the caches.
Definition: request.hh:207
void handleTimingReqMiss(PacketPtr pkt, CacheBlk *blk, Tick forward_time, Tick request_time) override
Definition: cache.cc:327
MemSidePort memSidePort
Definition: base.hh:313
block was a hardware prefetch yet unaccessed
Definition: cache_blk.hh:76
CacheCmdStats & cmdStats(const PacketPtr p)
Definition: base.hh:982
void schedTimingSnoopResp(PacketPtr pkt, Tick when)
Schedule the sending of a timing snoop response.
Definition: qport.hh:157
bool needsWritable() const
Definition: packet.hh:533
Addr getBlockAddr(unsigned int blk_size) const
Definition: packet.hh:750
bool isUncacheable() const
Definition: queue_entry.hh:127
RequestPtr req
A pointer to the original request.
Definition: packet.hh:327
const Cycles responseLatency
The latency of sending reponse to its upper level cache/core on a linefill.
Definition: base.hh:872
bool isBlockCached() const
Definition: packet.hh:692
Declaration of a common base class for cache tagstore objects.
unsigned getSize() const
Definition: packet.hh:736
virtual void recvTimingReq(PacketPtr pkt)
Performs the access specified by the request.
Definition: base.cc:337
A coherent cache that can be arranged in flexible topologies.
Definition: cache.hh:69
virtual Tick recvAtomic(PacketPtr pkt)
Performs the access specified by the request.
Definition: base.cc:543
bool isRequest() const
Definition: packet.hh:531
A Basic Cache block.
Definition: cache_blk.hh:87
void satisfyRequest(PacketPtr pkt, CacheBlk *blk, bool deferred_response=false, bool pending_downgrade=false) override
Perform any necessary updates to the block and perform any data exchange between the packet and the b...
Definition: cache.cc:81
bool needsResponse() const
Definition: packet.hh:542
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
Definition: packet.hh:366
bool isError() const
Definition: packet.hh:555
Addr getOffset(unsigned int blk_size) const
Definition: packet.hh:745
bool inRange(Addr addr) const
Determine if an address is in the ranges covered by this cache.
Definition: base.cc:203
void schedTimingResp(PacketPtr pkt, Tick when)
Schedule the sending of a timing response.
Definition: qport.hh:92
void setData(const uint8_t *p)
Copy data into the packet from the provided pointer.
Definition: packet.hh:1158
void makeAtomicResponse()
Definition: packet.hh:949
PacketPtr cleanEvictBlk(CacheBlk *blk)
Create a CleanEvict request for the given block.
Definition: cache.cc:916
bool sendMSHRQueuePacket(MSHR *mshr) override
Take an MSHR, turn it into a suitable downstream packet, and send it out.
Definition: cache.cc:1361
uint64_t Tick
Tick count type.
Definition: types.hh:63
Target * getTarget() override
Returns a reference to the first target.
bool isResponse() const
Definition: packet.hh:532
PacketPtr writecleanBlk(CacheBlk *blk, Request::Flags dest, PacketId id)
Create a writeclean request for the given block.
Definition: base.cc:1536
dirty (modified)
Definition: cache_blk.hh:74
unsigned State
block state: OR of CacheBlkStatusBit
Definition: cache_blk.hh:105
bool isSecure() const
Check if this block holds data from the secure memory space.
Definition: cache_blk.hh:248
Miss Status and handling Register.
Definition: mshr.hh:72
virtual void recvTimingResp(PacketPtr pkt)
Handles a response (cache line fill/write ack) from the bus.
Definition: base.cc:405
void recvTimingSnoopResp(PacketPtr pkt) override
Handle a snoop response.
Definition: cache.cc:270
QueueEntry::Target * getTarget() override
Returns a reference to the first target.
Definition: mshr.hh:452
bool isCachedAbove(PacketPtr pkt, bool is_timing=true)
Send up a snoop request and find cached copies.
Definition: cache.cc:1333
void copyResponderFlags(const PacketPtr pkt)
Copy the reponse flags from an input packet to this packet.
Definition: packet.cc:309
Addr getAddr() const
Definition: packet.hh:726
void recvTimingReq(PacketPtr pkt) override
Performs the access specified by the request.
Definition: cache.cc:406
std::unique_ptr< Packet > pendingDelete
Upstream caches need this packet until true is returned, so hold it for deletion until a subsequent c...
Definition: base.hh:369
void allocateWriteBuffer(PacketPtr pkt, Tick time)
Definition: base.hh:1119
A basic cache interface.
Definition: base.hh:93
bool hasData() const
Definition: packet.hh:548
virtual void handleTimingReqHit(PacketPtr pkt, CacheBlk *blk, Tick request_time)
Definition: base.cc:214
STL list class.
Definition: stl.hh:54
void promoteWholeLineWrites(PacketPtr pkt)
Turn line-sized writes into WriteInvalidate transactions.
Definition: cache.cc:304
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,16,32,64}_t.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
uint32_t payloadDelay
The extra pipelining delay from seeing the packet until the end of payload is transmitted by the comp...
Definition: packet.hh:384
Tick recvAtomicSnoop(PacketPtr pkt) override
Snoop for the provided request in the cache and return the estimated time taken.
Definition: cache.cc:1320
CacheBlk * handleFill(PacketPtr pkt, CacheBlk *blk, PacketList &writebacks, bool allocate)
Handle a fill operation caused by a received packet.
Definition: base.cc:1309
virtual const std::string name() const
Definition: sim_object.hh:120
const bool writebackClean
Determine if clean lines should be written back or not.
Definition: base.hh:630
const unsigned blkSize
Block size of this cache.
Definition: base.hh:843
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:255
Entry * findMatch(Addr blk_addr, bool is_secure, bool ignore_uncacheable=true) const
Find the first entry that matches the provided address.
Definition: queue.hh:166
Tick clockEdge(Cycles cycles=Cycles(0)) const
Determine the tick when a cycle begins, by default the current one, but the argument also enables the...
void setDataFromBlock(const uint8_t *blk_data, int blkSize)
Copy data into the packet from the provided block pointer, which is aligned to the given block size...
Definition: packet.hh:1177
uint64_t order
Increasing order number assigned to each incoming request.
Definition: base.hh:907
bool responderHadWritable() const
Definition: packet.hh:651
Bitfield< 15 > system
Definition: misc.hh:999
A queue entry is holding packets that will be serviced as soon as resources are available.
Definition: queue_entry.hh:86
virtual M5_NODISCARD PacketPtr evictBlock(CacheBlk *blk)=0
Evict a cache block.
MasterID maxMasters()
Get the number of masters registered in the system.
Definition: system.hh:412
bool hasSharers() const
Definition: packet.hh:618
bool satisfied() const
Definition: packet.hh:687
write permission
Definition: cache_blk.hh:70
bool access(PacketPtr pkt, CacheBlk *&blk, Cycles &lat, PacketList &writebacks) override
Does all the processing necessary to perform the provided request.
Definition: cache.cc:164
bool isMaskedWrite() const
Definition: packet.hh:1306
bool isLLSC() const
Definition: packet.hh:554
Definitions of a simple cache block class.
virtual void satisfyRequest(PacketPtr pkt, CacheBlk *blk, bool deferred_response=false, bool pending_downgrade=false)
Perform any necessary updates to the block and perform any data exchange between the packet and the b...
Definition: base.cc:907
void markInService(MSHR *mshr, bool pending_modified_resp)
Mark a request as in service (sent downstream in the memory system), effectively making this MSHR the...
Definition: base.hh:375
bool fromCache() const
Definition: packet.hh:546
bool wasWholeLineWrite
Track if we sent this as a whole line write or not.
Definition: mshr.hh:122
bool allocOnFill(MemCmd cmd) const
Determine whether we should allocate on a fill or not.
Definition: base.hh:408
Cycles ticksToCycles(Tick t) const
bool hasRespData() const
Definition: packet.hh:549
Addr blkAddr
Block aligned address.
Definition: queue_entry.hh:114
bool handleSnoop(PacketPtr target, Counter order)
Definition: mshr.cc:417
Cache(const CacheParams *p)
Instantiates a basic cache object.
Definition: cache.cc:74
void doTimingSupplyResponse(PacketPtr req_pkt, const uint8_t *blk_data, bool already_copied, bool pending_inval)
Definition: cache.cc:944
SenderState * senderState
This packet&#39;s sender state.
Definition: packet.hh:480
void print(std::ostream &o, int verbosity=0, const std::string &prefix="") const
Definition: packet.cc:376
MemCmd cmd
The command field of the packet.
Definition: packet.hh:322
TargetList extractServiceableTargets(PacketPtr pkt)
Extracts the subset of the targets that can be serviced given a received response.
Definition: mshr.cc:541
bool isEviction() const
Definition: packet.hh:544
bool isForward
True if the entry is just a simple forward from an upper level.
Definition: mshr.hh:125
int getNumTargets() const
Returns the current number of allocated targets.
uint32_t handleSnoop(PacketPtr pkt, CacheBlk *blk, bool is_timing, bool is_deferred, bool pending_inval)
Perform an upward snoop if needed, and update the block state (possibly invalidating the block)...
Definition: cache.cc:989
Cycles getDecompressionLatency(const CacheBlk *blk)
Get the decompression latency if the block is compressed.
Definition: base.cc:123
const bool doFastWrites
This cache should allocate a block on a line-sized write miss.
Definition: cache.hh:75
PacketPtr createMissPacket(PacketPtr cpu_pkt, CacheBlk *blk, bool needs_writable, bool is_whole_line_write) const override
Create an appropriate downstream bus request packet.
Definition: cache.cc:480
void sendTimingSnoopReq(PacketPtr pkt)
Attempt to send a timing snoop request packet to the master port by calling its corresponding receive...
Definition: port.hh:370
Cycles handleAtomicReqMiss(PacketPtr pkt, CacheBlk *&blk, PacketList &writebacks) override
Handle a request in atomic mode that missed in this cache.
Definition: cache.cc:566
const PacketPtr pkt
Pending request packet.
Definition: queue_entry.hh:91
void print(std::ostream &os, int verbosity=0, const std::string &prefix="") const override
Prints the contents of this MSHR for debugging.
Definition: mshr.cc:706
const int numTarget
The number of targets for each MSHR.
Definition: base.hh:880
const T * getConstPtr() const
Definition: packet.hh:1099
virtual bool sendMSHRQueuePacket(MSHR *mshr)
Take an MSHR, turn it into a suitable downstream packet, and send it out.
Definition: base.cc:1659
uint32_t task_id
Task Id associated with this block.
Definition: cache_blk.hh:91
const Cycles forwardLatency
This is the forward latency of the cache.
Definition: base.hh:862
void setBlockCached()
Definition: packet.hh:691
bool isSecure() const
Definition: packet.hh:755
std::unordered_set< RequestPtr > outstandingSnoop
Store the outstanding requests that we are expecting snoop responses from so we can determine which s...
Definition: cache.hh:82
void copyError(Packet *pkt)
Definition: packet.hh:724
#define warn(...)
Definition: logging.hh:212
void setExpressSnoop()
The express snoop flag is used for two purposes.
Definition: packet.hh:633
Addr regenerateBlkAddr(CacheBlk *blk)
Regenerate block address using tags.
Definition: base.cc:172
static const int NumArgumentRegs M5_VAR_USED
Definition: process.cc:84
Bitfield< 2 > pf
Definition: misc.hh:552
Write queue entry.
bool isWholeLineWrite(unsigned blk_size)
Definition: packet.hh:559
BaseCacheCompressor * compressor
Compression method being used.
Definition: base.hh:327
Tick sendAtomic(PacketPtr pkt)
Send an atomic request packet, where the data is moved and the state is updated in zero time...
Definition: port.hh:427
Bitfield< 0 > p
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:185
Describes a cache.
bool matchAddr(const Addr addr, const bool is_secure) const
Check if packet corresponds to a given address and address space.
Definition: packet.cc:411
uint8_t * data
Contains a copy of the data in this block for easy access.
Definition: cache_blk.hh:102
BaseTags * tags
Tag and data Storage.
Definition: base.hh:324
void allocate()
Allocate memory for the packet.
Definition: packet.hh:1232
Stats::Vector mshr_uncacheable
Number of misses that miss in the MSHRs, per command and thread.
Definition: base.hh:963
void clearBlocked(BlockedCause cause)
Marks the cache as unblocked for the given cause.
Definition: base.hh:1183
ProbePointArg< PacketInfo > Packet
Packet probe point.
Definition: mem.hh:104
MSHRQueue mshrQueue
Miss status registers.
Definition: base.hh:318
void maintainClusivity(bool from_cache, CacheBlk *blk)
Maintain the clusivity of this cache by potentially invalidating a block.
Definition: base.cc:1297
std::string print()
Print all tags used.
Definition: base.cc:190
bool isDirty() const
Check to see if a block has been written.
Definition: cache_blk.hh:229
void setCacheResponding()
Snoop flags.
Definition: packet.hh:585

Generated on Fri Feb 28 2020 16:27:01 for gem5 by doxygen 1.8.13