gem5  [DEVELOP-FOR-23.0]
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
base.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012-2013, 2018-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) 2003-2005 The Regents of The University of Michigan
15  * All rights reserved.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions are
19  * met: redistributions of source code must retain the above copyright
20  * notice, this list of conditions and the following disclaimer;
21  * redistributions in binary form must reproduce the above copyright
22  * notice, this list of conditions and the following disclaimer in the
23  * documentation and/or other materials provided with the distribution;
24  * neither the name of the copyright holders nor the names of its
25  * contributors may be used to endorse or promote products derived from
26  * this software without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39  */
40 
46 #include "mem/cache/base.hh"
47 
48 #include "base/compiler.hh"
49 #include "base/logging.hh"
50 #include "debug/Cache.hh"
51 #include "debug/CacheComp.hh"
52 #include "debug/CachePort.hh"
53 #include "debug/CacheRepl.hh"
54 #include "debug/CacheVerbose.hh"
55 #include "debug/HWPrefetch.hh"
57 #include "mem/cache/mshr.hh"
59 #include "mem/cache/queue_entry.hh"
62 #include "params/BaseCache.hh"
63 #include "params/WriteAllocator.hh"
64 #include "sim/cur_tick.hh"
65 
66 namespace gem5
67 {
68 
70  BaseCache& _cache,
71  const std::string &_label)
72  : QueuedResponsePort(_name, queue),
73  cache{_cache},
74  queue(_cache, *this, true, _label),
75  blocked(false), mustSendRetry(false),
76  sendRetryEvent([this]{ processSendRetry(); }, _name)
77 {
78 }
79 
80 BaseCache::BaseCache(const BaseCacheParams &p, unsigned blk_size)
81  : ClockedObject(p),
82  cpuSidePort (p.name + ".cpu_side_port", *this, "CpuSidePort"),
83  memSidePort(p.name + ".mem_side_port", this, "MemSidePort"),
84  mshrQueue("MSHRs", p.mshrs, 0, p.demand_mshr_reserve, p.name),
85  writeBuffer("write buffer", p.write_buffers, p.mshrs, p.name),
86  tags(p.tags),
89  writeAllocator(p.write_allocator),
90  writebackClean(p.writeback_clean),
91  tempBlockWriteback(nullptr),
93  name(), false,
95  blkSize(blk_size),
96  lookupLatency(p.tag_latency),
97  dataLatency(p.data_latency),
98  forwardLatency(p.tag_latency),
99  fillLatency(p.data_latency),
100  responseLatency(p.response_latency),
101  sequentialAccess(p.sequential_access),
102  numTarget(p.tgts_per_mshr),
103  forwardSnoops(true),
104  clusivity(p.clusivity),
105  isReadOnly(p.is_read_only),
106  replaceExpansions(p.replace_expansions),
107  moveContractions(p.move_contractions),
108  blocked(0),
109  order(0),
110  noTargetMSHR(nullptr),
111  missCount(p.max_miss_count),
112  addrRanges(p.addr_ranges.begin(), p.addr_ranges.end()),
113  system(p.system),
114  stats(*this)
115 {
116  // the MSHR queue has no reserve entries as we check the MSHR
117  // queue on every single allocation, whereas the write queue has
118  // as many reserve entries as we have MSHRs, since every MSHR may
119  // eventually require a writeback, and we do not check the write
120  // buffer before committing to an MSHR
121 
122  // forward snoops is overridden in init() once we can query
123  // whether the connected requestor is actually snooping or not
124 
125  tempBlock = new TempCacheBlk(blkSize);
126 
127  tags->tagsInit();
128  if (prefetcher)
129  prefetcher->setCache(this);
130 
131  fatal_if(compressor && !dynamic_cast<CompressedTags*>(tags),
132  "The tags of compressed cache %s must derive from CompressedTags",
133  name());
134  warn_if(!compressor && dynamic_cast<CompressedTags*>(tags),
135  "Compressed cache %s does not have a compression algorithm", name());
136  if (compressor)
137  compressor->setCache(this);
138 }
139 
141 {
142  delete tempBlock;
143 }
144 
145 void
147 {
148  assert(!blocked);
149  DPRINTF(CachePort, "Port is blocking new requests\n");
150  blocked = true;
151  // if we already scheduled a retry in this cycle, but it has not yet
152  // happened, cancel it
153  if (sendRetryEvent.scheduled()) {
155  DPRINTF(CachePort, "Port descheduled retry\n");
156  mustSendRetry = true;
157  }
158 }
159 
160 void
162 {
163  assert(blocked);
164  DPRINTF(CachePort, "Port is accepting new requests\n");
165  blocked = false;
166  if (mustSendRetry) {
167  // @TODO: need to find a better time (next cycle?)
168  cache.schedule(sendRetryEvent, curTick() + 1);
169  }
170 }
171 
172 void
174 {
175  DPRINTF(CachePort, "Port is sending retry\n");
176 
177  // reset the flag and call retry
178  mustSendRetry = false;
179  sendRetryReq();
180 }
181 
182 Addr
184 {
185  if (blk != tempBlock) {
186  return tags->regenerateBlkAddr(blk);
187  } else {
188  return tempBlock->getAddr();
189  }
190 }
191 
192 void
194 {
196  fatal("Cache ports on %s are not connected\n", name());
199 }
200 
201 Port &
202 BaseCache::getPort(const std::string &if_name, PortID idx)
203 {
204  if (if_name == "mem_side") {
205  return memSidePort;
206  } else if (if_name == "cpu_side") {
207  return cpuSidePort;
208  } else {
209  return ClockedObject::getPort(if_name, idx);
210  }
211 }
212 
213 bool
215 {
216  for (const auto& r : addrRanges) {
217  if (r.contains(addr)) {
218  return true;
219  }
220  }
221  return false;
222 }
223 
224 void
226 {
227 
228  // handle special cases for LockedRMW transactions
229  if (pkt->isLockedRMW()) {
230  Addr blk_addr = pkt->getBlockAddr(blkSize);
231 
232  if (pkt->isRead()) {
233  // Read hit for LockedRMW. Since it requires exclusive
234  // permissions, there should be no outstanding access.
235  assert(!mshrQueue.findMatch(blk_addr, pkt->isSecure()));
236  // The keys to LockedRMW are that (1) we always have an MSHR
237  // allocated during the RMW interval to catch snoops and
238  // defer them until after the RMW completes, and (2) we
239  // clear permissions on the block to turn any upstream
240  // access other than the matching write into a miss, causing
241  // it to append to the MSHR as well.
242 
243  // Because we hit in the cache, we have to fake an MSHR to
244  // achieve part (1). If the read had missed, this MSHR
245  // would get allocated as part of normal miss processing.
246  // Basically we need to get the MSHR in the same state as if
247  // we had missed and just received the response.
248  // Request *req2 = new Request(*(pkt->req));
249  RequestPtr req2 = std::make_shared<Request>(*(pkt->req));
250  PacketPtr pkt2 = new Packet(req2, pkt->cmd);
251  MSHR *mshr = allocateMissBuffer(pkt2, curTick(), true);
252  // Mark the MSHR "in service" (even though it's not) to prevent
253  // the cache from sending out a request.
254  mshrQueue.markInService(mshr, false);
255  // Part (2): mark block inaccessible
256  assert(blk);
259  } else {
260  assert(pkt->isWrite());
261  // All LockedRMW writes come here, as they cannot miss.
262  // Need to undo the two things described above. Block
263  // permissions were already restored earlier in this
264  // function, prior to the access() call. Now we just need
265  // to clear out the MSHR.
266 
267  // Read should have already allocated MSHR.
268  MSHR *mshr = mshrQueue.findMatch(blk_addr, pkt->isSecure());
269  assert(mshr);
270  // Fake up a packet and "respond" to the still-pending
271  // LockedRMWRead, to process any pending targets and clear
272  // out the MSHR
273  PacketPtr resp_pkt =
275  resp_pkt->senderState = mshr;
276  recvTimingResp(resp_pkt);
277  }
278  }
279 
280  if (pkt->needsResponse()) {
281  // These delays should have been consumed by now
282  assert(pkt->headerDelay == 0);
283  assert(pkt->payloadDelay == 0);
284 
285  pkt->makeTimingResponse();
286 
287  // In this case we are considering request_time that takes
288  // into account the delay of the xbar, if any, and just
289  // lat, neglecting responseLatency, modelling hit latency
290  // just as the value of lat overriden by access(), which calls
291  // the calculateAccessLatency() function.
292  cpuSidePort.schedTimingResp(pkt, request_time);
293  } else {
294  DPRINTF(Cache, "%s satisfied %s, no response needed\n", __func__,
295  pkt->print());
296 
297  // queue the packet for deletion, as the sending cache is
298  // still relying on it; if the block is found in access(),
299  // CleanEvict and Writeback messages will be deleted
300  // here as well
301  pendingDelete.reset(pkt);
302  }
303 }
304 
305 void
307  Tick forward_time, Tick request_time)
308 {
309  if (writeAllocator &&
310  pkt && pkt->isWrite() && !pkt->req->isUncacheable()) {
311  writeAllocator->updateMode(pkt->getAddr(), pkt->getSize(),
312  pkt->getBlockAddr(blkSize));
313  }
314 
315  if (mshr) {
319 
320  //@todo remove hw_pf here
321 
322  // Coalesce unless it was a software prefetch (see above).
323  if (pkt) {
324  assert(!pkt->isWriteback());
325  // CleanEvicts corresponding to blocks which have
326  // outstanding requests in MSHRs are simply sunk here
327  if (pkt->cmd == MemCmd::CleanEvict) {
328  pendingDelete.reset(pkt);
329  } else if (pkt->cmd == MemCmd::WriteClean) {
330  // A WriteClean should never coalesce with any
331  // outstanding cache maintenance requests.
332 
333  // We use forward_time here because there is an
334  // uncached memory write, forwarded to WriteBuffer.
335  allocateWriteBuffer(pkt, forward_time);
336  } else {
337  DPRINTF(Cache, "%s coalescing MSHR for %s\n", __func__,
338  pkt->print());
339 
340  assert(pkt->req->requestorId() < system->maxRequestors());
341  stats.cmdStats(pkt).mshrHits[pkt->req->requestorId()]++;
342 
343  // We use forward_time here because it is the same
344  // considering new targets. We have multiple
345  // requests for the same address here. It
346  // specifies the latency to allocate an internal
347  // buffer and to schedule an event to the queued
348  // port and also takes into account the additional
349  // delay of the xbar.
350  mshr->allocateTarget(pkt, forward_time, order++,
351  allocOnFill(pkt->cmd));
352  if (mshr->getNumTargets() >= numTarget) {
353  noTargetMSHR = mshr;
355  // need to be careful with this... if this mshr isn't
356  // ready yet (i.e. time > curTick()), we don't want to
357  // move it ahead of mshrs that are ready
358  // mshrQueue.moveToFront(mshr);
359  }
360  }
361  }
362  } else {
363  // no MSHR
364  assert(pkt->req->requestorId() < system->maxRequestors());
365  stats.cmdStats(pkt).mshrMisses[pkt->req->requestorId()]++;
366  if (prefetcher && pkt->isDemand())
368 
369  if (pkt->isEviction() || pkt->cmd == MemCmd::WriteClean) {
370  // We use forward_time here because there is an
371  // writeback or writeclean, forwarded to WriteBuffer.
372  allocateWriteBuffer(pkt, forward_time);
373  } else {
374  if (blk && blk->isValid()) {
375  // If we have a write miss to a valid block, we
376  // need to mark the block non-readable. Otherwise
377  // if we allow reads while there's an outstanding
378  // write miss, the read could return stale data
379  // out of the cache block... a more aggressive
380  // system could detect the overlap (if any) and
381  // forward data out of the MSHRs, but we don't do
382  // that yet. Note that we do need to leave the
383  // block valid so that it stays in the cache, in
384  // case we get an upgrade response (and hence no
385  // new data) when the write miss completes.
386  // As long as CPUs do proper store/load forwarding
387  // internally, and have a sufficiently weak memory
388  // model, this is probably unnecessary, but at some
389  // point it must have seemed like we needed it...
390  assert((pkt->needsWritable() &&
391  !blk->isSet(CacheBlk::WritableBit)) ||
392  pkt->req->isCacheMaintenance());
394  }
395  // Here we are using forward_time, modelling the latency of
396  // a miss (outbound) just as forwardLatency, neglecting the
397  // lookupLatency component.
398  allocateMissBuffer(pkt, forward_time);
399  }
400  }
401 }
402 
403 void
405 {
406  // anything that is merely forwarded pays for the forward latency and
407  // the delay provided by the crossbar
408  Tick forward_time = clockEdge(forwardLatency) + pkt->headerDelay;
409 
410  if (pkt->cmd == MemCmd::LockedRMWWriteReq) {
411  // For LockedRMW accesses, we mark the block inaccessible after the
412  // read (see below), to make sure no one gets in before the write.
413  // Now that the write is here, mark it accessible again, so the
414  // write will succeed. LockedRMWReadReq brings the block in in
415  // exclusive mode, so we know it was previously writable.
416  CacheBlk *blk = tags->findBlock(pkt->getAddr(), pkt->isSecure());
417  assert(blk && blk->isValid());
418  assert(!blk->isSet(CacheBlk::WritableBit) &&
422  }
423 
424  Cycles lat;
425  CacheBlk *blk = nullptr;
426  bool satisfied = false;
427  {
428  PacketList writebacks;
429  // Note that lat is passed by reference here. The function
430  // access() will set the lat value.
431  satisfied = access(pkt, blk, lat, writebacks);
432 
433  // After the evicted blocks are selected, they must be forwarded
434  // to the write buffer to ensure they logically precede anything
435  // happening below
436  doWritebacks(writebacks, clockEdge(lat + forwardLatency));
437  }
438 
439  // Here we charge the headerDelay that takes into account the latencies
440  // of the bus, if the packet comes from it.
441  // The latency charged is just the value set by the access() function.
442  // In case of a hit we are neglecting response latency.
443  // In case of a miss we are neglecting forward latency.
444  Tick request_time = clockEdge(lat);
445  // Here we reset the timing of the packet.
446  pkt->headerDelay = pkt->payloadDelay = 0;
447 
448  if (satisfied) {
449  // notify before anything else as later handleTimingReqHit might turn
450  // the packet in a response
451  ppHit->notify(pkt);
452 
453  if (prefetcher && blk && blk->wasPrefetched()) {
454  DPRINTF(Cache, "Hit on prefetch for addr %#x (%s)\n",
455  pkt->getAddr(), pkt->isSecure() ? "s" : "ns");
456  blk->clearPrefetched();
457  }
458 
459  handleTimingReqHit(pkt, blk, request_time);
460  } else {
461  handleTimingReqMiss(pkt, blk, forward_time, request_time);
462 
463  ppMiss->notify(pkt);
464  }
465 
466  if (prefetcher) {
467  // track time of availability of next prefetch, if any
468  Tick next_pf_time = std::max(
470  if (next_pf_time != MaxTick) {
471  schedMemSideSendEvent(next_pf_time);
472  }
473  }
474 }
475 
476 void
478 {
479  Tick completion_time = clockEdge(responseLatency) +
480  pkt->headerDelay + pkt->payloadDelay;
481 
482  // Reset the bus additional time as it is now accounted for
483  pkt->headerDelay = pkt->payloadDelay = 0;
484 
485  cpuSidePort.schedTimingResp(pkt, completion_time);
486 }
487 
488 void
490 {
491  assert(pkt->isResponse());
492 
493  // all header delay should be paid for by the crossbar, unless
494  // this is a prefetch response from above
495  panic_if(pkt->headerDelay != 0 && pkt->cmd != MemCmd::HardPFResp,
496  "%s saw a non-zero packet delay\n", name());
497 
498  const bool is_error = pkt->isError();
499 
500  if (is_error) {
501  DPRINTF(Cache, "%s: Cache received %s with error\n", __func__,
502  pkt->print());
503  }
504 
505  DPRINTF(Cache, "%s: Handling response %s\n", __func__,
506  pkt->print());
507 
508  // if this is a write, we should be looking at an uncacheable
509  // write
510  if (pkt->isWrite() && pkt->cmd != MemCmd::LockedRMWWriteResp) {
511  assert(pkt->req->isUncacheable());
513  return;
514  }
515 
516  // we have dealt with any (uncacheable) writes above, from here on
517  // we know we are dealing with an MSHR due to a miss or a prefetch
518  MSHR *mshr = dynamic_cast<MSHR*>(pkt->popSenderState());
519  assert(mshr);
520 
521  if (mshr == noTargetMSHR) {
522  // we always clear at least one target
524  noTargetMSHR = nullptr;
525  }
526 
527  // Initial target is used just for stats
528  const QueueEntry::Target *initial_tgt = mshr->getTarget();
529  const Tick miss_latency = curTick() - initial_tgt->recvTime;
530  if (pkt->req->isUncacheable()) {
531  assert(pkt->req->requestorId() < system->maxRequestors());
532  stats.cmdStats(initial_tgt->pkt)
533  .mshrUncacheableLatency[pkt->req->requestorId()] += miss_latency;
534  } else {
535  assert(pkt->req->requestorId() < system->maxRequestors());
536  stats.cmdStats(initial_tgt->pkt)
537  .mshrMissLatency[pkt->req->requestorId()] += miss_latency;
538  }
539 
540  PacketList writebacks;
541 
542  bool is_fill = !mshr->isForward &&
543  (pkt->isRead() || pkt->cmd == MemCmd::UpgradeResp ||
544  mshr->wasWholeLineWrite);
545 
546  // make sure that if the mshr was due to a whole line write then
547  // the response is an invalidation
548  assert(!mshr->wasWholeLineWrite || pkt->isInvalidate());
549 
550  CacheBlk *blk = tags->findBlock(pkt->getAddr(), pkt->isSecure());
551 
552  if (is_fill && !is_error) {
553  DPRINTF(Cache, "Block for addr %#llx being updated in Cache\n",
554  pkt->getAddr());
555 
556  const bool allocate = (writeAllocator && mshr->wasWholeLineWrite) ?
557  writeAllocator->allocate() : mshr->allocOnFill();
558  blk = handleFill(pkt, blk, writebacks, allocate);
559  assert(blk != nullptr);
560  ppFill->notify(pkt);
561  }
562 
563  // Don't want to promote the Locked RMW Read until
564  // the locked write comes in
565  if (!mshr->hasLockedRMWReadTarget()) {
566  if (blk && blk->isValid() && pkt->isClean() && !pkt->isInvalidate()) {
567  // The block was marked not readable while there was a pending
568  // cache maintenance operation, restore its flag.
570 
571  // This was a cache clean operation (without invalidate)
572  // and we have a copy of the block already. Since there
573  // is no invalidation, we can promote targets that don't
574  // require a writable copy
575  mshr->promoteReadable();
576  }
577 
578  if (blk && blk->isSet(CacheBlk::WritableBit) &&
579  !pkt->req->isCacheInvalidate()) {
580  // If at this point the referenced block is writable and the
581  // response is not a cache invalidate, we promote targets that
582  // were deferred as we couldn't guarrantee a writable copy
583  mshr->promoteWritable();
584  }
585  }
586 
587  serviceMSHRTargets(mshr, pkt, blk);
588  // We are stopping servicing targets early for the Locked RMW Read until
589  // the write comes.
590  if (!mshr->hasLockedRMWReadTarget()) {
591  if (mshr->promoteDeferredTargets()) {
592  // avoid later read getting stale data while write miss is
593  // outstanding.. see comment in timingAccess()
594  if (blk) {
596  }
597  mshrQueue.markPending(mshr);
599  } else {
600  // while we deallocate an mshr from the queue we still have to
601  // check the isFull condition before and after as we might
602  // have been using the reserved entries already
603  const bool was_full = mshrQueue.isFull();
604  mshrQueue.deallocate(mshr);
605  if (was_full && !mshrQueue.isFull()) {
607  }
608 
609  // Request the bus for a prefetch if this deallocation freed enough
610  // MSHRs for a prefetch to take place
611  if (prefetcher && mshrQueue.canPrefetch() && !isBlocked()) {
612  Tick next_pf_time = std::max(
614  if (next_pf_time != MaxTick)
615  schedMemSideSendEvent(next_pf_time);
616  }
617  }
618 
619  // if we used temp block, check to see if its valid and then clear it
620  if (blk == tempBlock && tempBlock->isValid()) {
621  evictBlock(blk, writebacks);
622  }
623  }
624 
625  const Tick forward_time = clockEdge(forwardLatency) + pkt->headerDelay;
626  // copy writebacks to write buffer
627  doWritebacks(writebacks, forward_time);
628 
629  DPRINTF(CacheVerbose, "%s: Leaving with %s\n", __func__, pkt->print());
630  delete pkt;
631 }
632 
633 
634 Tick
636 {
637  // should assert here that there are no outstanding MSHRs or
638  // writebacks... that would mean that someone used an atomic
639  // access in timing mode
640 
641  // We use lookupLatency here because it is used to specify the latency
642  // to access.
643  Cycles lat = lookupLatency;
644 
645  CacheBlk *blk = nullptr;
646  PacketList writebacks;
647  bool satisfied = access(pkt, blk, lat, writebacks);
648 
649  if (pkt->isClean() && blk && blk->isSet(CacheBlk::DirtyBit)) {
650  // A cache clean opearation is looking for a dirty
651  // block. If a dirty block is encountered a WriteClean
652  // will update any copies to the path to the memory
653  // until the point of reference.
654  DPRINTF(CacheVerbose, "%s: packet %s found block: %s\n",
655  __func__, pkt->print(), blk->print());
656  PacketPtr wb_pkt = writecleanBlk(blk, pkt->req->getDest(), pkt->id);
657  writebacks.push_back(wb_pkt);
658  pkt->setSatisfied();
659  }
660 
661  // handle writebacks resulting from the access here to ensure they
662  // logically precede anything happening below
663  doWritebacksAtomic(writebacks);
664  assert(writebacks.empty());
665 
666  if (!satisfied) {
667  lat += handleAtomicReqMiss(pkt, blk, writebacks);
668  }
669 
670  // Note that we don't invoke the prefetcher at all in atomic mode.
671  // It's not clear how to do it properly, particularly for
672  // prefetchers that aggressively generate prefetch candidates and
673  // rely on bandwidth contention to throttle them; these will tend
674  // to pollute the cache in atomic mode since there is no bandwidth
675  // contention. If we ever do want to enable prefetching in atomic
676  // mode, though, this is the place to do it... see timingAccess()
677  // for an example (though we'd want to issue the prefetch(es)
678  // immediately rather than calling requestMemSideBus() as we do
679  // there).
680 
681  // do any writebacks resulting from the response handling
682  doWritebacksAtomic(writebacks);
683 
684  // if we used temp block, check to see if its valid and if so
685  // clear it out, but only do so after the call to recvAtomic is
686  // finished so that any downstream observers (such as a snoop
687  // filter), first see the fill, and only then see the eviction
688  if (blk == tempBlock && tempBlock->isValid()) {
689  // the atomic CPU calls recvAtomic for fetch and load/store
690  // sequentuially, and we may already have a tempBlock
691  // writeback from the fetch that we have not yet sent
692  if (tempBlockWriteback) {
693  // if that is the case, write the prevoius one back, and
694  // do not schedule any new event
696  } else {
697  // the writeback/clean eviction happens after the call to
698  // recvAtomic has finished (but before any successive
699  // calls), so that the response handling from the fill is
700  // allowed to happen first
702  }
703 
705  }
706 
707  if (pkt->needsResponse()) {
708  pkt->makeAtomicResponse();
709  }
710 
711  return lat * clockPeriod();
712 }
713 
714 void
715 BaseCache::functionalAccess(PacketPtr pkt, bool from_cpu_side)
716 {
717  Addr blk_addr = pkt->getBlockAddr(blkSize);
718  bool is_secure = pkt->isSecure();
719  CacheBlk *blk = tags->findBlock(pkt->getAddr(), is_secure);
720  MSHR *mshr = mshrQueue.findMatch(blk_addr, is_secure);
721 
722  pkt->pushLabel(name());
723 
724  CacheBlkPrintWrapper cbpw(blk);
725 
726  // Note that just because an L2/L3 has valid data doesn't mean an
727  // L1 doesn't have a more up-to-date modified copy that still
728  // needs to be found. As a result we always update the request if
729  // we have it, but only declare it satisfied if we are the owner.
730 
731  // see if we have data at all (owned or otherwise)
732  bool have_data = blk && blk->isValid()
733  && pkt->trySatisfyFunctional(&cbpw, blk_addr, is_secure, blkSize,
734  blk->data);
735 
736  // data we have is dirty if marked as such or if we have an
737  // in-service MSHR that is pending a modified line
738  bool have_dirty =
739  have_data && (blk->isSet(CacheBlk::DirtyBit) ||
740  (mshr && mshr->inService && mshr->isPendingModified()));
741 
742  bool done = have_dirty ||
747 
748  DPRINTF(CacheVerbose, "%s: %s %s%s%s\n", __func__, pkt->print(),
749  (blk && blk->isValid()) ? "valid " : "",
750  have_data ? "data " : "", done ? "done " : "");
751 
752  // We're leaving the cache, so pop cache->name() label
753  pkt->popLabel();
754 
755  if (done) {
756  pkt->makeResponse();
757  } else {
758  // if it came as a request from the CPU side then make sure it
759  // continues towards the memory side
760  if (from_cpu_side) {
762  } else if (cpuSidePort.isSnooping()) {
763  // if it came from the memory side, it must be a snoop request
764  // and we should only forward it if we are forwarding snoops
766  }
767  }
768 }
769 
770 void
772  bool has_old_data)
773 {
774  DataUpdate data_update(regenerateBlkAddr(blk), blk->isSecure());
775  if (ppDataUpdate->hasListeners()) {
776  if (has_old_data) {
777  data_update.oldData = std::vector<uint64_t>(blk->data,
778  blk->data + (blkSize / sizeof(uint64_t)));
779  }
780  }
781 
782  // Actually perform the data update
783  if (cpkt) {
784  cpkt->writeDataToBlock(blk->data, blkSize);
785  }
786 
787  if (ppDataUpdate->hasListeners()) {
788  if (cpkt) {
789  data_update.newData = std::vector<uint64_t>(blk->data,
790  blk->data + (blkSize / sizeof(uint64_t)));
791  }
792  ppDataUpdate->notify(data_update);
793  }
794 }
795 
796 void
798 {
799  assert(pkt->isRequest());
800 
801  uint64_t overwrite_val;
802  bool overwrite_mem;
803  uint64_t condition_val64;
804  uint32_t condition_val32;
805 
806  int offset = pkt->getOffset(blkSize);
807  uint8_t *blk_data = blk->data + offset;
808 
809  assert(sizeof(uint64_t) >= pkt->getSize());
810 
811  // Get a copy of the old block's contents for the probe before the update
812  DataUpdate data_update(regenerateBlkAddr(blk), blk->isSecure());
813  if (ppDataUpdate->hasListeners()) {
814  data_update.oldData = std::vector<uint64_t>(blk->data,
815  blk->data + (blkSize / sizeof(uint64_t)));
816  }
817 
818  overwrite_mem = true;
819  // keep a copy of our possible write value, and copy what is at the
820  // memory address into the packet
821  pkt->writeData((uint8_t *)&overwrite_val);
822  pkt->setData(blk_data);
823 
824  if (pkt->req->isCondSwap()) {
825  if (pkt->getSize() == sizeof(uint64_t)) {
826  condition_val64 = pkt->req->getExtraData();
827  overwrite_mem = !std::memcmp(&condition_val64, blk_data,
828  sizeof(uint64_t));
829  } else if (pkt->getSize() == sizeof(uint32_t)) {
830  condition_val32 = (uint32_t)pkt->req->getExtraData();
831  overwrite_mem = !std::memcmp(&condition_val32, blk_data,
832  sizeof(uint32_t));
833  } else
834  panic("Invalid size for conditional read/write\n");
835  }
836 
837  if (overwrite_mem) {
838  std::memcpy(blk_data, &overwrite_val, pkt->getSize());
840 
841  if (ppDataUpdate->hasListeners()) {
842  data_update.newData = std::vector<uint64_t>(blk->data,
843  blk->data + (blkSize / sizeof(uint64_t)));
844  ppDataUpdate->notify(data_update);
845  }
846  }
847 }
848 
849 QueueEntry*
851 {
852  // Check both MSHR queue and write buffer for potential requests,
853  // note that null does not mean there is no request, it could
854  // simply be that it is not ready
855  MSHR *miss_mshr = mshrQueue.getNext();
856  WriteQueueEntry *wq_entry = writeBuffer.getNext();
857 
858  // If we got a write buffer request ready, first priority is a
859  // full write buffer, otherwise we favour the miss requests
860  if (wq_entry && (writeBuffer.isFull() || !miss_mshr)) {
861  // need to search MSHR queue for conflicting earlier miss.
862  MSHR *conflict_mshr = mshrQueue.findPending(wq_entry);
863 
864  if (conflict_mshr && conflict_mshr->order < wq_entry->order) {
865  // Service misses in order until conflict is cleared.
866  return conflict_mshr;
867 
868  // @todo Note that we ignore the ready time of the conflict here
869  }
870 
871  // No conflicts; issue write
872  return wq_entry;
873  } else if (miss_mshr) {
874  // need to check for conflicting earlier writeback
875  WriteQueueEntry *conflict_mshr = writeBuffer.findPending(miss_mshr);
876  if (conflict_mshr) {
877  // not sure why we don't check order here... it was in the
878  // original code but commented out.
879 
880  // The only way this happens is if we are
881  // doing a write and we didn't have permissions
882  // then subsequently saw a writeback (owned got evicted)
883  // We need to make sure to perform the writeback first
884  // To preserve the dirty data, then we can issue the write
885 
886  // should we return wq_entry here instead? I.e. do we
887  // have to flush writes in order? I don't think so... not
888  // for Alpha anyway. Maybe for x86?
889  return conflict_mshr;
890 
891  // @todo Note that we ignore the ready time of the conflict here
892  }
893 
894  // No conflicts; issue read
895  return miss_mshr;
896  }
897 
898  // fall through... no pending requests. Try a prefetch.
899  assert(!miss_mshr && !wq_entry);
900  if (prefetcher && mshrQueue.canPrefetch() && !isBlocked()) {
901  // If we have a miss queue slot, we can try a prefetch
902  PacketPtr pkt = prefetcher->getPacket();
903  if (pkt) {
904  Addr pf_addr = pkt->getBlockAddr(blkSize);
905  if (tags->findBlock(pf_addr, pkt->isSecure())) {
906  DPRINTF(HWPrefetch, "Prefetch %#x has hit in cache, "
907  "dropped.\n", pf_addr);
909  // free the request and packet
910  delete pkt;
911  } else if (mshrQueue.findMatch(pf_addr, pkt->isSecure())) {
912  DPRINTF(HWPrefetch, "Prefetch %#x has hit in a MSHR, "
913  "dropped.\n", pf_addr);
915  // free the request and packet
916  delete pkt;
917  } else if (writeBuffer.findMatch(pf_addr, pkt->isSecure())) {
918  DPRINTF(HWPrefetch, "Prefetch %#x has hit in the "
919  "Write Buffer, dropped.\n", pf_addr);
921  // free the request and packet
922  delete pkt;
923  } else {
924  // Update statistic on number of prefetches issued
925  // (hwpf_mshr_misses)
926  assert(pkt->req->requestorId() < system->maxRequestors());
927  stats.cmdStats(pkt).mshrMisses[pkt->req->requestorId()]++;
928 
929  // allocate an MSHR and return it, note
930  // that we send the packet straight away, so do not
931  // schedule the send
932  return allocateMissBuffer(pkt, curTick(), false);
933  }
934  }
935  }
936 
937  return nullptr;
938 }
939 
940 bool
942  PacketList &writebacks)
943 {
944  bool replacement = false;
945  for (const auto& blk : evict_blks) {
946  if (blk->isValid()) {
947  replacement = true;
948 
949  const MSHR* mshr =
950  mshrQueue.findMatch(regenerateBlkAddr(blk), blk->isSecure());
951  if (mshr) {
952  // Must be an outstanding upgrade or clean request on a block
953  // we're about to replace
954  assert((!blk->isSet(CacheBlk::WritableBit) &&
955  mshr->needsWritable()) || mshr->isCleaning());
956  return false;
957  }
958  }
959  }
960 
961  // The victim will be replaced by a new entry, so increase the replacement
962  // counter if a valid block is being replaced
963  if (replacement) {
965 
966  // Evict valid blocks associated to this victim block
967  for (auto& blk : evict_blks) {
968  if (blk->isValid()) {
969  evictBlock(blk, writebacks);
970  }
971  }
972  }
973 
974  return true;
975 }
976 
977 bool
979  PacketList &writebacks)
980 {
981  // tempBlock does not exist in the tags, so don't do anything for it.
982  if (blk == tempBlock) {
983  return true;
984  }
985 
986  // The compressor is called to compress the updated data, so that its
987  // metadata can be updated.
988  Cycles compression_lat = Cycles(0);
989  Cycles decompression_lat = Cycles(0);
990  const auto comp_data =
991  compressor->compress(data, compression_lat, decompression_lat);
992  std::size_t compression_size = comp_data->getSizeBits();
993 
994  // Get previous compressed size
995  CompressionBlk* compression_blk = static_cast<CompressionBlk*>(blk);
996  [[maybe_unused]] const std::size_t prev_size =
997  compression_blk->getSizeBits();
998 
999  // If compressed size didn't change enough to modify its co-allocatability
1000  // there is nothing to do. Otherwise we may be facing a data expansion
1001  // (block passing from more compressed to less compressed state), or a
1002  // data contraction (less to more).
1003  bool is_data_expansion = false;
1004  bool is_data_contraction = false;
1005  const CompressionBlk::OverwriteType overwrite_type =
1006  compression_blk->checkExpansionContraction(compression_size);
1007  std::string op_name = "";
1008  if (overwrite_type == CompressionBlk::DATA_EXPANSION) {
1009  op_name = "expansion";
1010  is_data_expansion = true;
1011  } else if ((overwrite_type == CompressionBlk::DATA_CONTRACTION) &&
1012  moveContractions) {
1013  op_name = "contraction";
1014  is_data_contraction = true;
1015  }
1016 
1017  // If block changed compression state, it was possibly co-allocated with
1018  // other blocks and cannot be co-allocated anymore, so one or more blocks
1019  // must be evicted to make room for the expanded/contracted block
1020  std::vector<CacheBlk*> evict_blks;
1021  if (is_data_expansion || is_data_contraction) {
1022  std::vector<CacheBlk*> evict_blks;
1023  bool victim_itself = false;
1024  CacheBlk *victim = nullptr;
1025  if (replaceExpansions || is_data_contraction) {
1026  victim = tags->findVictim(regenerateBlkAddr(blk),
1027  blk->isSecure(), compression_size, evict_blks);
1028 
1029  // It is valid to return nullptr if there is no victim
1030  if (!victim) {
1031  return false;
1032  }
1033 
1034  // If the victim block is itself the block won't need to be moved,
1035  // and the victim should not be evicted
1036  if (blk == victim) {
1037  victim_itself = true;
1038  auto it = std::find_if(evict_blks.begin(), evict_blks.end(),
1039  [&blk](CacheBlk* evict_blk){ return evict_blk == blk; });
1040  evict_blks.erase(it);
1041  }
1042 
1043  // Print victim block's information
1044  DPRINTF(CacheRepl, "Data %s replacement victim: %s\n",
1045  op_name, victim->print());
1046  } else {
1047  // If we do not move the expanded block, we must make room for
1048  // the expansion to happen, so evict every co-allocated block
1049  const SuperBlk* superblock = static_cast<const SuperBlk*>(
1050  compression_blk->getSectorBlock());
1051  for (auto& sub_blk : superblock->blks) {
1052  if (sub_blk->isValid() && (blk != sub_blk)) {
1053  evict_blks.push_back(sub_blk);
1054  }
1055  }
1056  }
1057 
1058  // Try to evict blocks; if it fails, give up on update
1059  if (!handleEvictions(evict_blks, writebacks)) {
1060  return false;
1061  }
1062 
1063  DPRINTF(CacheComp, "Data %s: [%s] from %d to %d bits\n",
1064  op_name, blk->print(), prev_size, compression_size);
1065 
1066  if (!victim_itself && (replaceExpansions || is_data_contraction)) {
1067  // Move the block's contents to the invalid block so that it now
1068  // co-allocates with the other existing superblock entry
1069  tags->moveBlock(blk, victim);
1070  blk = victim;
1071  compression_blk = static_cast<CompressionBlk*>(blk);
1072  }
1073  }
1074 
1075  // Update the number of data expansions/contractions
1076  if (is_data_expansion) {
1078  } else if (is_data_contraction) {
1080  }
1081 
1082  compression_blk->setSizeBits(compression_size);
1083  compression_blk->setDecompressionLatency(decompression_lat);
1084 
1085  return true;
1086 }
1087 
1088 void
1090 {
1091  assert(pkt->isRequest());
1092 
1093  assert(blk && blk->isValid());
1094  // Occasionally this is not true... if we are a lower-level cache
1095  // satisfying a string of Read and ReadEx requests from
1096  // upper-level caches, a Read will mark the block as shared but we
1097  // can satisfy a following ReadEx anyway since we can rely on the
1098  // Read requestor(s) to have buffered the ReadEx snoop and to
1099  // invalidate their blocks after receiving them.
1100  // assert(!pkt->needsWritable() || blk->isSet(CacheBlk::WritableBit));
1101  assert(pkt->getOffset(blkSize) + pkt->getSize() <= blkSize);
1102 
1103  // Check RMW operations first since both isRead() and
1104  // isWrite() will be true for them
1105  if (pkt->cmd == MemCmd::SwapReq) {
1106  if (pkt->isAtomicOp()) {
1107  // Get a copy of the old block's contents for the probe before
1108  // the update
1109  DataUpdate data_update(regenerateBlkAddr(blk), blk->isSecure());
1110  if (ppDataUpdate->hasListeners()) {
1111  data_update.oldData = std::vector<uint64_t>(blk->data,
1112  blk->data + (blkSize / sizeof(uint64_t)));
1113  }
1114 
1115  // extract data from cache and save it into the data field in
1116  // the packet as a return value from this atomic op
1117  int offset = tags->extractBlkOffset(pkt->getAddr());
1118  uint8_t *blk_data = blk->data + offset;
1119  pkt->setData(blk_data);
1120 
1121  // execute AMO operation
1122  (*(pkt->getAtomicOp()))(blk_data);
1123 
1124  // Inform of this block's data contents update
1125  if (ppDataUpdate->hasListeners()) {
1126  data_update.newData = std::vector<uint64_t>(blk->data,
1127  blk->data + (blkSize / sizeof(uint64_t)));
1128  ppDataUpdate->notify(data_update);
1129  }
1130 
1131  // set block status to dirty
1133  } else {
1134  cmpAndSwap(blk, pkt);
1135  }
1136  } else if (pkt->isWrite()) {
1137  // we have the block in a writable state and can go ahead,
1138  // note that the line may be also be considered writable in
1139  // downstream caches along the path to memory, but always
1140  // Exclusive, and never Modified
1141  assert(blk->isSet(CacheBlk::WritableBit));
1142  // Write or WriteLine at the first cache with block in writable state
1143  if (blk->checkWrite(pkt)) {
1144  updateBlockData(blk, pkt, true);
1145  }
1146  // Always mark the line as dirty (and thus transition to the
1147  // Modified state) even if we are a failed StoreCond so we
1148  // supply data to any snoops that have appended themselves to
1149  // this cache before knowing the store will fail.
1151  DPRINTF(CacheVerbose, "%s for %s (write)\n", __func__, pkt->print());
1152  } else if (pkt->isRead()) {
1153  if (pkt->isLLSC()) {
1154  blk->trackLoadLocked(pkt);
1155  }
1156 
1157  // all read responses have a data payload
1158  assert(pkt->hasRespData());
1159  pkt->setDataFromBlock(blk->data, blkSize);
1160  } else if (pkt->isUpgrade()) {
1161  // sanity check
1162  assert(!pkt->hasSharers());
1163 
1164  if (blk->isSet(CacheBlk::DirtyBit)) {
1165  // we were in the Owned state, and a cache above us that
1166  // has the line in Shared state needs to be made aware
1167  // that the data it already has is in fact dirty
1168  pkt->setCacheResponding();
1170  }
1171  } else if (pkt->isClean()) {
1173  } else {
1174  assert(pkt->isInvalidate());
1175  invalidateBlock(blk);
1176  DPRINTF(CacheVerbose, "%s for %s (invalidation)\n", __func__,
1177  pkt->print());
1178  }
1179 }
1180 
1182 //
1183 // Access path: requests coming in from the CPU side
1184 //
1186 Cycles
1188  const Cycles lookup_lat) const
1189 {
1190  // A tag-only access has to wait for the packet to arrive in order to
1191  // perform the tag lookup.
1192  return ticksToCycles(delay) + lookup_lat;
1193 }
1194 
1195 Cycles
1196 BaseCache::calculateAccessLatency(const CacheBlk* blk, const uint32_t delay,
1197  const Cycles lookup_lat) const
1198 {
1199  Cycles lat(0);
1200 
1201  if (blk != nullptr) {
1202  // As soon as the access arrives, for sequential accesses first access
1203  // tags, then the data entry. In the case of parallel accesses the
1204  // latency is dictated by the slowest of tag and data latencies.
1205  if (sequentialAccess) {
1206  lat = ticksToCycles(delay) + lookup_lat + dataLatency;
1207  } else {
1208  lat = ticksToCycles(delay) + std::max(lookup_lat, dataLatency);
1209  }
1210 
1211  // Check if the block to be accessed is available. If not, apply the
1212  // access latency on top of when the block is ready to be accessed.
1213  const Tick tick = curTick() + delay;
1214  const Tick when_ready = blk->getWhenReady();
1215  if (when_ready > tick &&
1216  ticksToCycles(when_ready - tick) > lat) {
1217  lat += ticksToCycles(when_ready - tick);
1218  }
1219  } else {
1220  // In case of a miss, we neglect the data access in a parallel
1221  // configuration (i.e., the data access will be stopped as soon as
1222  // we find out it is a miss), and use the tag-only latency.
1223  lat = calculateTagOnlyLatency(delay, lookup_lat);
1224  }
1225 
1226  return lat;
1227 }
1228 
1229 bool
1231  PacketList &writebacks)
1232 {
1233  // sanity check
1234  assert(pkt->isRequest());
1235 
1236  gem5_assert(!(isReadOnly && pkt->isWrite()),
1237  "Should never see a write in a read-only cache %s\n",
1238  name());
1239 
1240  // Access block in the tags
1241  Cycles tag_latency(0);
1242  blk = tags->accessBlock(pkt, tag_latency);
1243 
1244  DPRINTF(Cache, "%s for %s %s\n", __func__, pkt->print(),
1245  blk ? "hit " + blk->print() : "miss");
1246 
1247  if (pkt->req->isCacheMaintenance()) {
1248  // A cache maintenance operation is always forwarded to the
1249  // memory below even if the block is found in dirty state.
1250 
1251  // We defer any changes to the state of the block until we
1252  // create and mark as in service the mshr for the downstream
1253  // packet.
1254 
1255  // Calculate access latency on top of when the packet arrives. This
1256  // takes into account the bus delay.
1257  lat = calculateTagOnlyLatency(pkt->headerDelay, tag_latency);
1258 
1259  return false;
1260  }
1261 
1262  if (pkt->isEviction()) {
1263  // We check for presence of block in above caches before issuing
1264  // Writeback or CleanEvict to write buffer. Therefore the only
1265  // possible cases can be of a CleanEvict packet coming from above
1266  // encountering a Writeback generated in this cache peer cache and
1267  // waiting in the write buffer. Cases of upper level peer caches
1268  // generating CleanEvict and Writeback or simply CleanEvict and
1269  // CleanEvict almost simultaneously will be caught by snoops sent out
1270  // by crossbar.
1271  WriteQueueEntry *wb_entry = writeBuffer.findMatch(pkt->getAddr(),
1272  pkt->isSecure());
1273  if (wb_entry) {
1274  assert(wb_entry->getNumTargets() == 1);
1275  PacketPtr wbPkt = wb_entry->getTarget()->pkt;
1276  assert(wbPkt->isWriteback());
1277 
1278  if (pkt->isCleanEviction()) {
1279  // The CleanEvict and WritebackClean snoops into other
1280  // peer caches of the same level while traversing the
1281  // crossbar. If a copy of the block is found, the
1282  // packet is deleted in the crossbar. Hence, none of
1283  // the other upper level caches connected to this
1284  // cache have the block, so we can clear the
1285  // BLOCK_CACHED flag in the Writeback if set and
1286  // discard the CleanEvict by returning true.
1287  wbPkt->clearBlockCached();
1288 
1289  // A clean evict does not need to access the data array
1290  lat = calculateTagOnlyLatency(pkt->headerDelay, tag_latency);
1291 
1292  return true;
1293  } else {
1294  assert(pkt->cmd == MemCmd::WritebackDirty);
1295  // Dirty writeback from above trumps our clean
1296  // writeback... discard here
1297  // Note: markInService will remove entry from writeback buffer.
1298  markInService(wb_entry);
1299  delete wbPkt;
1300  }
1301  }
1302  }
1303 
1304  // The critical latency part of a write depends only on the tag access
1305  if (pkt->isWrite()) {
1306  lat = calculateTagOnlyLatency(pkt->headerDelay, tag_latency);
1307  }
1308 
1309  // Writeback handling is special case. We can write the block into
1310  // the cache without having a writeable copy (or any copy at all).
1311  if (pkt->isWriteback()) {
1312  assert(blkSize == pkt->getSize());
1313 
1314  // we could get a clean writeback while we are having
1315  // outstanding accesses to a block, do the simple thing for
1316  // now and drop the clean writeback so that we do not upset
1317  // any ordering/decisions about ownership already taken
1318  if (pkt->cmd == MemCmd::WritebackClean &&
1319  mshrQueue.findMatch(pkt->getAddr(), pkt->isSecure())) {
1320  DPRINTF(Cache, "Clean writeback %#llx to block with MSHR, "
1321  "dropping\n", pkt->getAddr());
1322 
1323  // A writeback searches for the block, then writes the data.
1324  // As the writeback is being dropped, the data is not touched,
1325  // and we just had to wait for the time to find a match in the
1326  // MSHR. As of now assume a mshr queue search takes as long as
1327  // a tag lookup for simplicity.
1328  return true;
1329  }
1330 
1331  const bool has_old_data = blk && blk->isValid();
1332  if (!blk) {
1333  // need to do a replacement
1334  blk = allocateBlock(pkt, writebacks);
1335  if (!blk) {
1336  // no replaceable block available: give up, fwd to next level.
1337  incMissCount(pkt);
1338  return false;
1339  }
1340 
1342  } else if (compressor) {
1343  // This is an overwrite to an existing block, therefore we need
1344  // to check for data expansion (i.e., block was compressed with
1345  // a smaller size, and now it doesn't fit the entry anymore).
1346  // If that is the case we might need to evict blocks.
1347  if (!updateCompressionData(blk, pkt->getConstPtr<uint64_t>(),
1348  writebacks)) {
1349  invalidateBlock(blk);
1350  return false;
1351  }
1352  }
1353 
1354  // only mark the block dirty if we got a writeback command,
1355  // and leave it as is for a clean writeback
1356  if (pkt->cmd == MemCmd::WritebackDirty) {
1357  // TODO: the coherent cache can assert that the dirty bit is set
1359  }
1360  // if the packet does not have sharers, it is passing
1361  // writable, and we got the writeback in Modified or Exclusive
1362  // state, if not we are in the Owned or Shared state
1363  if (!pkt->hasSharers()) {
1365  }
1366  // nothing else to do; writeback doesn't expect response
1367  assert(!pkt->needsResponse());
1368 
1369  updateBlockData(blk, pkt, has_old_data);
1370  DPRINTF(Cache, "%s new state is %s\n", __func__, blk->print());
1371  incHitCount(pkt);
1372 
1373  // When the packet metadata arrives, the tag lookup will be done while
1374  // the payload is arriving. Then the block will be ready to access as
1375  // soon as the fill is done
1377  std::max(cyclesToTicks(tag_latency), (uint64_t)pkt->payloadDelay));
1378 
1379  return true;
1380  } else if (pkt->cmd == MemCmd::CleanEvict) {
1381  // A CleanEvict does not need to access the data array
1382  lat = calculateTagOnlyLatency(pkt->headerDelay, tag_latency);
1383 
1384  if (blk) {
1385  // Found the block in the tags, need to stop CleanEvict from
1386  // propagating further down the hierarchy. Returning true will
1387  // treat the CleanEvict like a satisfied write request and delete
1388  // it.
1389  return true;
1390  }
1391  // We didn't find the block here, propagate the CleanEvict further
1392  // down the memory hierarchy. Returning false will treat the CleanEvict
1393  // like a Writeback which could not find a replaceable block so has to
1394  // go to next level.
1395  return false;
1396  } else if (pkt->cmd == MemCmd::WriteClean) {
1397  // WriteClean handling is a special case. We can allocate a
1398  // block directly if it doesn't exist and we can update the
1399  // block immediately. The WriteClean transfers the ownership
1400  // of the block as well.
1401  assert(blkSize == pkt->getSize());
1402 
1403  const bool has_old_data = blk && blk->isValid();
1404  if (!blk) {
1405  if (pkt->writeThrough()) {
1406  // if this is a write through packet, we don't try to
1407  // allocate if the block is not present
1408  return false;
1409  } else {
1410  // a writeback that misses needs to allocate a new block
1411  blk = allocateBlock(pkt, writebacks);
1412  if (!blk) {
1413  // no replaceable block available: give up, fwd to
1414  // next level.
1415  incMissCount(pkt);
1416  return false;
1417  }
1418 
1420  }
1421  } else if (compressor) {
1422  // This is an overwrite to an existing block, therefore we need
1423  // to check for data expansion (i.e., block was compressed with
1424  // a smaller size, and now it doesn't fit the entry anymore).
1425  // If that is the case we might need to evict blocks.
1426  if (!updateCompressionData(blk, pkt->getConstPtr<uint64_t>(),
1427  writebacks)) {
1428  invalidateBlock(blk);
1429  return false;
1430  }
1431  }
1432 
1433  // at this point either this is a writeback or a write-through
1434  // write clean operation and the block is already in this
1435  // cache, we need to update the data and the block flags
1436  assert(blk);
1437  // TODO: the coherent cache can assert that the dirty bit is set
1438  if (!pkt->writeThrough()) {
1440  }
1441  // nothing else to do; writeback doesn't expect response
1442  assert(!pkt->needsResponse());
1443 
1444  updateBlockData(blk, pkt, has_old_data);
1445  DPRINTF(Cache, "%s new state is %s\n", __func__, blk->print());
1446 
1447  incHitCount(pkt);
1448 
1449  // When the packet metadata arrives, the tag lookup will be done while
1450  // the payload is arriving. Then the block will be ready to access as
1451  // soon as the fill is done
1453  std::max(cyclesToTicks(tag_latency), (uint64_t)pkt->payloadDelay));
1454 
1455  // If this a write-through packet it will be sent to cache below
1456  return !pkt->writeThrough();
1457  } else if (blk && (pkt->needsWritable() ?
1459  blk->isSet(CacheBlk::ReadableBit))) {
1460  // OK to satisfy access
1461  incHitCount(pkt);
1462 
1463  // Calculate access latency based on the need to access the data array
1464  if (pkt->isRead()) {
1465  lat = calculateAccessLatency(blk, pkt->headerDelay, tag_latency);
1466 
1467  // When a block is compressed, it must first be decompressed
1468  // before being read. This adds to the access latency.
1469  if (compressor) {
1470  lat += compressor->getDecompressionLatency(blk);
1471  }
1472  } else {
1473  lat = calculateTagOnlyLatency(pkt->headerDelay, tag_latency);
1474  }
1475 
1476  satisfyRequest(pkt, blk);
1477  maintainClusivity(pkt->fromCache(), blk);
1478 
1479  return true;
1480  }
1481 
1482  // Can't satisfy access normally... either no block (blk == nullptr)
1483  // or have block but need writable
1484 
1485  incMissCount(pkt);
1486 
1487  lat = calculateAccessLatency(blk, pkt->headerDelay, tag_latency);
1488 
1489  if (!blk && pkt->isLLSC() && pkt->isWrite()) {
1490  // complete miss on store conditional... just give up now
1491  pkt->req->setExtraData(0);
1492  return true;
1493  }
1494 
1495  return false;
1496 }
1497 
1498 void
1500 {
1501  if (from_cache && blk && blk->isValid() &&
1502  !blk->isSet(CacheBlk::DirtyBit) && clusivity == enums::mostly_excl) {
1503  // if we have responded to a cache, and our block is still
1504  // valid, but not dirty, and this cache is mostly exclusive
1505  // with respect to the cache above, drop the block
1506  invalidateBlock(blk);
1507  }
1508 }
1509 
1510 CacheBlk*
1512  bool allocate)
1513 {
1514  assert(pkt->isResponse());
1515  Addr addr = pkt->getAddr();
1516  bool is_secure = pkt->isSecure();
1517  const bool has_old_data = blk && blk->isValid();
1518  const std::string old_state = (debug::Cache && blk) ? blk->print() : "";
1519 
1520  // When handling a fill, we should have no writes to this line.
1521  assert(addr == pkt->getBlockAddr(blkSize));
1522  assert(!writeBuffer.findMatch(addr, is_secure));
1523 
1524  if (!blk) {
1525  // better have read new data...
1526  assert(pkt->hasData() || pkt->cmd == MemCmd::InvalidateResp);
1527 
1528  // need to do a replacement if allocating, otherwise we stick
1529  // with the temporary storage
1530  blk = allocate ? allocateBlock(pkt, writebacks) : nullptr;
1531 
1532  if (!blk) {
1533  // No replaceable block or a mostly exclusive
1534  // cache... just use temporary storage to complete the
1535  // current request and then get rid of it
1536  blk = tempBlock;
1537  tempBlock->insert(addr, is_secure);
1538  DPRINTF(Cache, "using temp block for %#llx (%s)\n", addr,
1539  is_secure ? "s" : "ns");
1540  }
1541  } else {
1542  // existing block... probably an upgrade
1543  // don't clear block status... if block is already dirty we
1544  // don't want to lose that
1545  }
1546 
1547  // Block is guaranteed to be valid at this point
1548  assert(blk->isValid());
1549  assert(blk->isSecure() == is_secure);
1550  assert(regenerateBlkAddr(blk) == addr);
1551 
1553 
1554  // sanity check for whole-line writes, which should always be
1555  // marked as writable as part of the fill, and then later marked
1556  // dirty as part of satisfyRequest
1557  if (pkt->cmd == MemCmd::InvalidateResp) {
1558  assert(!pkt->hasSharers());
1559  }
1560 
1561  // here we deal with setting the appropriate state of the line,
1562  // and we start by looking at the hasSharers flag, and ignore the
1563  // cacheResponding flag (normally signalling dirty data) if the
1564  // packet has sharers, thus the line is never allocated as Owned
1565  // (dirty but not writable), and always ends up being either
1566  // Shared, Exclusive or Modified, see Packet::setCacheResponding
1567  // for more details
1568  if (!pkt->hasSharers()) {
1569  // we could get a writable line from memory (rather than a
1570  // cache) even in a read-only cache, note that we set this bit
1571  // even for a read-only cache, possibly revisit this decision
1573 
1574  // check if we got this via cache-to-cache transfer (i.e., from a
1575  // cache that had the block in Modified or Owned state)
1576  if (pkt->cacheResponding()) {
1577  // we got the block in Modified state, and invalidated the
1578  // owners copy
1580 
1581  gem5_assert(!isReadOnly, "Should never see dirty snoop response "
1582  "in read-only cache %s\n", name());
1583 
1584  }
1585  }
1586 
1587  DPRINTF(Cache, "Block addr %#llx (%s) moving from %s to %s\n",
1588  addr, is_secure ? "s" : "ns", old_state, blk->print());
1589 
1590  // if we got new data, copy it in (checking for a read response
1591  // and a response that has data is the same in the end)
1592  if (pkt->isRead()) {
1593  // sanity checks
1594  assert(pkt->hasData());
1595  assert(pkt->getSize() == blkSize);
1596 
1597  updateBlockData(blk, pkt, has_old_data);
1598  }
1599  // The block will be ready when the payload arrives and the fill is done
1601  pkt->payloadDelay);
1602 
1603  return blk;
1604 }
1605 
1606 CacheBlk*
1608 {
1609  // Get address
1610  const Addr addr = pkt->getAddr();
1611 
1612  // Get secure bit
1613  const bool is_secure = pkt->isSecure();
1614 
1615  // Block size and compression related access latency. Only relevant if
1616  // using a compressor, otherwise there is no extra delay, and the block
1617  // is fully sized
1618  std::size_t blk_size_bits = blkSize*8;
1619  Cycles compression_lat = Cycles(0);
1620  Cycles decompression_lat = Cycles(0);
1621 
1622  // If a compressor is being used, it is called to compress data before
1623  // insertion. Although in Gem5 the data is stored uncompressed, even if a
1624  // compressor is used, the compression/decompression methods are called to
1625  // calculate the amount of extra cycles needed to read or write compressed
1626  // blocks.
1627  if (compressor && pkt->hasData()) {
1628  const auto comp_data = compressor->compress(
1629  pkt->getConstPtr<uint64_t>(), compression_lat, decompression_lat);
1630  blk_size_bits = comp_data->getSizeBits();
1631  }
1632 
1633  // Find replacement victim
1634  std::vector<CacheBlk*> evict_blks;
1635  CacheBlk *victim = tags->findVictim(addr, is_secure, blk_size_bits,
1636  evict_blks);
1637 
1638  // It is valid to return nullptr if there is no victim
1639  if (!victim)
1640  return nullptr;
1641 
1642  // Print victim block's information
1643  DPRINTF(CacheRepl, "Replacement victim: %s\n", victim->print());
1644 
1645  // Try to evict blocks; if it fails, give up on allocation
1646  if (!handleEvictions(evict_blks, writebacks)) {
1647  return nullptr;
1648  }
1649 
1650  // Insert new block at victimized entry
1651  tags->insertBlock(pkt, victim);
1652 
1653  // If using a compressor, set compression data. This must be done after
1654  // insertion, as the compression bit may be set.
1655  if (compressor) {
1656  compressor->setSizeBits(victim, blk_size_bits);
1657  compressor->setDecompressionLatency(victim, decompression_lat);
1658  }
1659 
1660  return victim;
1661 }
1662 
1663 void
1665 {
1666  // If block is still marked as prefetched, then it hasn't been used
1667  if (blk->wasPrefetched()) {
1669  }
1670 
1671  // Notify that the data contents for this address are no longer present
1672  updateBlockData(blk, nullptr, blk->isValid());
1673 
1674  // If handling a block present in the Tags, let it do its invalidation
1675  // process, which will update stats and invalidate the block itself
1676  if (blk != tempBlock) {
1677  tags->invalidate(blk);
1678  } else {
1679  tempBlock->invalidate();
1680  }
1681 }
1682 
1683 void
1685 {
1686  PacketPtr pkt = evictBlock(blk);
1687  if (pkt) {
1688  writebacks.push_back(pkt);
1689  }
1690 }
1691 
1692 PacketPtr
1694 {
1696  "Writeback from read-only cache");
1697  assert(blk && blk->isValid() &&
1699 
1701 
1702  RequestPtr req = std::make_shared<Request>(
1704 
1705  if (blk->isSecure())
1706  req->setFlags(Request::SECURE);
1707 
1708  req->taskId(blk->getTaskId());
1709 
1710  PacketPtr pkt =
1711  new Packet(req, blk->isSet(CacheBlk::DirtyBit) ?
1713 
1714  DPRINTF(Cache, "Create Writeback %s writable: %d, dirty: %d\n",
1715  pkt->print(), blk->isSet(CacheBlk::WritableBit),
1716  blk->isSet(CacheBlk::DirtyBit));
1717 
1718  if (blk->isSet(CacheBlk::WritableBit)) {
1719  // not asserting shared means we pass the block in modified
1720  // state, mark our own block non-writeable
1722  } else {
1723  // we are in the Owned state, tell the receiver
1724  pkt->setHasSharers();
1725  }
1726 
1727  // make sure the block is not marked dirty
1729 
1730  pkt->allocate();
1731  pkt->setDataFromBlock(blk->data, blkSize);
1732 
1733  // When a block is compressed, it must first be decompressed before being
1734  // sent for writeback.
1735  if (compressor) {
1737  }
1738 
1739  return pkt;
1740 }
1741 
1742 PacketPtr
1744 {
1745  RequestPtr req = std::make_shared<Request>(
1747 
1748  if (blk->isSecure()) {
1749  req->setFlags(Request::SECURE);
1750  }
1751  req->taskId(blk->getTaskId());
1752 
1753  PacketPtr pkt = new Packet(req, MemCmd::WriteClean, blkSize, id);
1754 
1755  if (dest) {
1756  req->setFlags(dest);
1757  pkt->setWriteThrough();
1758  }
1759 
1760  DPRINTF(Cache, "Create %s writable: %d, dirty: %d\n", pkt->print(),
1762 
1763  if (blk->isSet(CacheBlk::WritableBit)) {
1764  // not asserting shared means we pass the block in modified
1765  // state, mark our own block non-writeable
1767  } else {
1768  // we are in the Owned state, tell the receiver
1769  pkt->setHasSharers();
1770  }
1771 
1772  // make sure the block is not marked dirty
1774 
1775  pkt->allocate();
1776  pkt->setDataFromBlock(blk->data, blkSize);
1777 
1778  // When a block is compressed, it must first be decompressed before being
1779  // sent for writeback.
1780  if (compressor) {
1782  }
1783 
1784  return pkt;
1785 }
1786 
1787 
1788 void
1790 {
1791  tags->forEachBlk([this](CacheBlk &blk) { writebackVisitor(blk); });
1792 }
1793 
1794 void
1796 {
1797  tags->forEachBlk([this](CacheBlk &blk) { invalidateVisitor(blk); });
1798 }
1799 
1800 bool
1802 {
1803  return tags->anyBlk([](CacheBlk &blk) {
1804  return blk.isSet(CacheBlk::DirtyBit); });
1805 }
1806 
1807 bool
1809 {
1810  return writeAllocator && writeAllocator->coalesce();
1811 }
1812 
1813 void
1815 {
1816  if (blk.isSet(CacheBlk::DirtyBit)) {
1817  assert(blk.isValid());
1818 
1819  RequestPtr request = std::make_shared<Request>(
1821 
1822  request->taskId(blk.getTaskId());
1823  if (blk.isSecure()) {
1824  request->setFlags(Request::SECURE);
1825  }
1826 
1827  Packet packet(request, MemCmd::WriteReq);
1828  packet.dataStatic(blk.data);
1829 
1830  memSidePort.sendFunctional(&packet);
1831 
1833  }
1834 }
1835 
1836 void
1838 {
1839  if (blk.isSet(CacheBlk::DirtyBit))
1840  warn_once("Invalidating dirty cache lines. " \
1841  "Expect things to break.\n");
1842 
1843  if (blk.isValid()) {
1844  assert(!blk.isSet(CacheBlk::DirtyBit));
1845  invalidateBlock(&blk);
1846  }
1847 }
1848 
1849 Tick
1851 {
1852  Tick nextReady = std::min(mshrQueue.nextReadyTime(),
1854 
1855  // Don't signal prefetch ready time if no MSHRs available
1856  // Will signal once enoguh MSHRs are deallocated
1857  if (prefetcher && mshrQueue.canPrefetch() && !isBlocked()) {
1858  nextReady = std::min(nextReady,
1860  }
1861 
1862  return nextReady;
1863 }
1864 
1865 
1866 bool
1868 {
1869  assert(mshr);
1870 
1871  // use request from 1st target
1872  PacketPtr tgt_pkt = mshr->getTarget()->pkt;
1873 
1874  DPRINTF(Cache, "%s: MSHR %s\n", __func__, tgt_pkt->print());
1875 
1876  // if the cache is in write coalescing mode or (additionally) in
1877  // no allocation mode, and we have a write packet with an MSHR
1878  // that is not a whole-line write (due to incompatible flags etc),
1879  // then reset the write mode
1880  if (writeAllocator && writeAllocator->coalesce() && tgt_pkt->isWrite()) {
1881  if (!mshr->isWholeLineWrite()) {
1882  // if we are currently write coalescing, hold on the
1883  // MSHR as many cycles extra as we need to completely
1884  // write a cache line
1885  if (writeAllocator->delay(mshr->blkAddr)) {
1886  Tick delay = blkSize / tgt_pkt->getSize() * clockPeriod();
1887  DPRINTF(CacheVerbose, "Delaying pkt %s %llu ticks to allow "
1888  "for write coalescing\n", tgt_pkt->print(), delay);
1889  mshrQueue.delay(mshr, delay);
1890  return false;
1891  } else {
1892  writeAllocator->reset();
1893  }
1894  } else {
1896  }
1897  }
1898 
1899  CacheBlk *blk = tags->findBlock(mshr->blkAddr, mshr->isSecure);
1900 
1901  // either a prefetch that is not present upstream, or a normal
1902  // MSHR request, proceed to get the packet to send downstream
1903  PacketPtr pkt = createMissPacket(tgt_pkt, blk, mshr->needsWritable(),
1904  mshr->isWholeLineWrite());
1905 
1906  mshr->isForward = (pkt == nullptr);
1907 
1908  if (mshr->isForward) {
1909  // not a cache block request, but a response is expected
1910  // make copy of current packet to forward, keep current
1911  // copy for response handling
1912  pkt = new Packet(tgt_pkt, false, true);
1913  assert(!pkt->isWrite());
1914  }
1915 
1916  // play it safe and append (rather than set) the sender state,
1917  // as forwarded packets may already have existing state
1918  pkt->pushSenderState(mshr);
1919 
1920  if (pkt->isClean() && blk && blk->isSet(CacheBlk::DirtyBit)) {
1921  // A cache clean opearation is looking for a dirty block. Mark
1922  // the packet so that the destination xbar can determine that
1923  // there will be a follow-up write packet as well.
1924  pkt->setSatisfied();
1925  }
1926 
1927  if (!memSidePort.sendTimingReq(pkt)) {
1928  // we are awaiting a retry, but we
1929  // delete the packet and will be creating a new packet
1930  // when we get the opportunity
1931  delete pkt;
1932 
1933  // note that we have now masked any requestBus and
1934  // schedSendEvent (we will wait for a retry before
1935  // doing anything), and this is so even if we do not
1936  // care about this packet and might override it before
1937  // it gets retried
1938  return true;
1939  } else {
1940  // As part of the call to sendTimingReq the packet is
1941  // forwarded to all neighbouring caches (and any caches
1942  // above them) as a snoop. Thus at this point we know if
1943  // any of the neighbouring caches are responding, and if
1944  // so, we know it is dirty, and we can determine if it is
1945  // being passed as Modified, making our MSHR the ordering
1946  // point
1947  bool pending_modified_resp = !pkt->hasSharers() &&
1948  pkt->cacheResponding();
1949  markInService(mshr, pending_modified_resp);
1950 
1951  if (pkt->isClean() && blk && blk->isSet(CacheBlk::DirtyBit)) {
1952  // A cache clean opearation is looking for a dirty
1953  // block. If a dirty block is encountered a WriteClean
1954  // will update any copies to the path to the memory
1955  // until the point of reference.
1956  DPRINTF(CacheVerbose, "%s: packet %s found block: %s\n",
1957  __func__, pkt->print(), blk->print());
1958  PacketPtr wb_pkt = writecleanBlk(blk, pkt->req->getDest(),
1959  pkt->id);
1960  PacketList writebacks;
1961  writebacks.push_back(wb_pkt);
1962  doWritebacks(writebacks, 0);
1963  }
1964 
1965  return false;
1966  }
1967 }
1968 
1969 bool
1971 {
1972  assert(wq_entry);
1973 
1974  // always a single target for write queue entries
1975  PacketPtr tgt_pkt = wq_entry->getTarget()->pkt;
1976 
1977  DPRINTF(Cache, "%s: write %s\n", __func__, tgt_pkt->print());
1978 
1979  // forward as is, both for evictions and uncacheable writes
1980  if (!memSidePort.sendTimingReq(tgt_pkt)) {
1981  // note that we have now masked any requestBus and
1982  // schedSendEvent (we will wait for a retry before
1983  // doing anything), and this is so even if we do not
1984  // care about this packet and might override it before
1985  // it gets retried
1986  return true;
1987  } else {
1988  markInService(wq_entry);
1989  return false;
1990  }
1991 }
1992 
1993 void
1995 {
1996  bool dirty(isDirty());
1997 
1998  if (dirty) {
1999  warn("*** The cache still contains dirty data. ***\n");
2000  warn(" Make sure to drain the system using the correct flags.\n");
2001  warn(" This checkpoint will not restore correctly " \
2002  "and dirty data in the cache will be lost!\n");
2003  }
2004 
2005  // Since we don't checkpoint the data in the cache, any dirty data
2006  // will be lost when restoring from a checkpoint of a system that
2007  // wasn't drained properly. Flag the checkpoint as invalid if the
2008  // cache contains dirty data.
2009  bool bad_checkpoint(dirty);
2010  SERIALIZE_SCALAR(bad_checkpoint);
2011 }
2012 
2013 void
2015 {
2016  bool bad_checkpoint;
2017  UNSERIALIZE_SCALAR(bad_checkpoint);
2018  if (bad_checkpoint) {
2019  fatal("Restoring from checkpoints with dirty caches is not "
2020  "supported in the classic memory system. Please remove any "
2021  "caches or drain them properly before taking checkpoints.\n");
2022  }
2023 }
2024 
2025 
2027  const std::string &name)
2028  : statistics::Group(&c, name.c_str()), cache(c),
2029  ADD_STAT(hits, statistics::units::Count::get(),
2030  ("number of " + name + " hits").c_str()),
2031  ADD_STAT(misses, statistics::units::Count::get(),
2032  ("number of " + name + " misses").c_str()),
2033  ADD_STAT(hitLatency, statistics::units::Tick::get(),
2034  ("number of " + name + " hit ticks").c_str()),
2035  ADD_STAT(missLatency, statistics::units::Tick::get(),
2036  ("number of " + name + " miss ticks").c_str()),
2037  ADD_STAT(accesses, statistics::units::Count::get(),
2038  ("number of " + name + " accesses(hits+misses)").c_str()),
2039  ADD_STAT(missRate, statistics::units::Ratio::get(),
2040  ("miss rate for " + name + " accesses").c_str()),
2041  ADD_STAT(avgMissLatency, statistics::units::Rate<
2042  statistics::units::Tick, statistics::units::Count>::get(),
2043  ("average " + name + " miss latency").c_str()),
2044  ADD_STAT(mshrHits, statistics::units::Count::get(),
2045  ("number of " + name + " MSHR hits").c_str()),
2046  ADD_STAT(mshrMisses, statistics::units::Count::get(),
2047  ("number of " + name + " MSHR misses").c_str()),
2048  ADD_STAT(mshrUncacheable, statistics::units::Count::get(),
2049  ("number of " + name + " MSHR uncacheable").c_str()),
2050  ADD_STAT(mshrMissLatency, statistics::units::Tick::get(),
2051  ("number of " + name + " MSHR miss ticks").c_str()),
2052  ADD_STAT(mshrUncacheableLatency, statistics::units::Tick::get(),
2053  ("number of " + name + " MSHR uncacheable ticks").c_str()),
2054  ADD_STAT(mshrMissRate, statistics::units::Ratio::get(),
2055  ("mshr miss rate for " + name + " accesses").c_str()),
2056  ADD_STAT(avgMshrMissLatency, statistics::units::Rate<
2057  statistics::units::Tick, statistics::units::Count>::get(),
2058  ("average " + name + " mshr miss latency").c_str()),
2059  ADD_STAT(avgMshrUncacheableLatency, statistics::units::Rate<
2060  statistics::units::Tick, statistics::units::Count>::get(),
2061  ("average " + name + " mshr uncacheable latency").c_str())
2062 {
2063 }
2064 
2065 void
2067 {
2068  using namespace statistics;
2069 
2071  System *system = cache.system;
2072  const auto max_requestors = system->maxRequestors();
2073 
2074  hits
2075  .init(max_requestors)
2076  .flags(total | nozero | nonan)
2077  ;
2078  for (int i = 0; i < max_requestors; i++) {
2079  hits.subname(i, system->getRequestorName(i));
2080  }
2081 
2082  // Miss statistics
2083  misses
2084  .init(max_requestors)
2085  .flags(total | nozero | nonan)
2086  ;
2087  for (int i = 0; i < max_requestors; i++) {
2088  misses.subname(i, system->getRequestorName(i));
2089  }
2090 
2091  // Hit latency statistics
2092  hitLatency
2093  .init(max_requestors)
2094  .flags(total | nozero | nonan)
2095  ;
2096  for (int i = 0; i < max_requestors; i++) {
2097  hitLatency.subname(i, system->getRequestorName(i));
2098  }
2099 
2100  // Miss latency statistics
2101  missLatency
2102  .init(max_requestors)
2103  .flags(total | nozero | nonan)
2104  ;
2105  for (int i = 0; i < max_requestors; i++) {
2106  missLatency.subname(i, system->getRequestorName(i));
2107  }
2108 
2109  // access formulas
2110  accesses.flags(total | nozero | nonan);
2111  accesses = hits + misses;
2112  for (int i = 0; i < max_requestors; i++) {
2113  accesses.subname(i, system->getRequestorName(i));
2114  }
2115 
2116  // miss rate formulas
2117  missRate.flags(total | nozero | nonan);
2118  missRate = misses / accesses;
2119  for (int i = 0; i < max_requestors; i++) {
2120  missRate.subname(i, system->getRequestorName(i));
2121  }
2122 
2123  // miss latency formulas
2124  avgMissLatency.flags(total | nozero | nonan);
2125  avgMissLatency = missLatency / misses;
2126  for (int i = 0; i < max_requestors; i++) {
2127  avgMissLatency.subname(i, system->getRequestorName(i));
2128  }
2129 
2130  // MSHR statistics
2131  // MSHR hit statistics
2132  mshrHits
2133  .init(max_requestors)
2134  .flags(total | nozero | nonan)
2135  ;
2136  for (int i = 0; i < max_requestors; i++) {
2137  mshrHits.subname(i, system->getRequestorName(i));
2138  }
2139 
2140  // MSHR miss statistics
2141  mshrMisses
2142  .init(max_requestors)
2143  .flags(total | nozero | nonan)
2144  ;
2145  for (int i = 0; i < max_requestors; i++) {
2146  mshrMisses.subname(i, system->getRequestorName(i));
2147  }
2148 
2149  // MSHR miss latency statistics
2150  mshrMissLatency
2151  .init(max_requestors)
2152  .flags(total | nozero | nonan)
2153  ;
2154  for (int i = 0; i < max_requestors; i++) {
2155  mshrMissLatency.subname(i, system->getRequestorName(i));
2156  }
2157 
2158  // MSHR uncacheable statistics
2159  mshrUncacheable
2160  .init(max_requestors)
2161  .flags(total | nozero | nonan)
2162  ;
2163  for (int i = 0; i < max_requestors; i++) {
2164  mshrUncacheable.subname(i, system->getRequestorName(i));
2165  }
2166 
2167  // MSHR miss latency statistics
2168  mshrUncacheableLatency
2169  .init(max_requestors)
2170  .flags(total | nozero | nonan)
2171  ;
2172  for (int i = 0; i < max_requestors; i++) {
2173  mshrUncacheableLatency.subname(i, system->getRequestorName(i));
2174  }
2175 
2176  // MSHR miss rate formulas
2177  mshrMissRate.flags(total | nozero | nonan);
2178  mshrMissRate = mshrMisses / accesses;
2179 
2180  for (int i = 0; i < max_requestors; i++) {
2181  mshrMissRate.subname(i, system->getRequestorName(i));
2182  }
2183 
2184  // mshrMiss latency formulas
2185  avgMshrMissLatency.flags(total | nozero | nonan);
2186  avgMshrMissLatency = mshrMissLatency / mshrMisses;
2187  for (int i = 0; i < max_requestors; i++) {
2188  avgMshrMissLatency.subname(i, system->getRequestorName(i));
2189  }
2190 
2191  // mshrUncacheable latency formulas
2192  avgMshrUncacheableLatency.flags(total | nozero | nonan);
2193  avgMshrUncacheableLatency = mshrUncacheableLatency / mshrUncacheable;
2194  for (int i = 0; i < max_requestors; i++) {
2195  avgMshrUncacheableLatency.subname(i, system->getRequestorName(i));
2196  }
2197 }
2198 
2200  : statistics::Group(&c), cache(c),
2201 
2202  ADD_STAT(demandHits, statistics::units::Count::get(),
2203  "number of demand (read+write) hits"),
2204  ADD_STAT(overallHits, statistics::units::Count::get(),
2205  "number of overall hits"),
2206  ADD_STAT(demandHitLatency, statistics::units::Tick::get(),
2207  "number of demand (read+write) hit ticks"),
2208  ADD_STAT(overallHitLatency, statistics::units::Tick::get(),
2209  "number of overall hit ticks"),
2210  ADD_STAT(demandMisses, statistics::units::Count::get(),
2211  "number of demand (read+write) misses"),
2212  ADD_STAT(overallMisses, statistics::units::Count::get(),
2213  "number of overall misses"),
2214  ADD_STAT(demandMissLatency, statistics::units::Tick::get(),
2215  "number of demand (read+write) miss ticks"),
2216  ADD_STAT(overallMissLatency, statistics::units::Tick::get(),
2217  "number of overall miss ticks"),
2218  ADD_STAT(demandAccesses, statistics::units::Count::get(),
2219  "number of demand (read+write) accesses"),
2220  ADD_STAT(overallAccesses, statistics::units::Count::get(),
2221  "number of overall (read+write) accesses"),
2222  ADD_STAT(demandMissRate, statistics::units::Ratio::get(),
2223  "miss rate for demand accesses"),
2224  ADD_STAT(overallMissRate, statistics::units::Ratio::get(),
2225  "miss rate for overall accesses"),
2226  ADD_STAT(demandAvgMissLatency, statistics::units::Rate<
2227  statistics::units::Tick, statistics::units::Count>::get(),
2228  "average overall miss latency in ticks"),
2229  ADD_STAT(overallAvgMissLatency, statistics::units::Rate<
2230  statistics::units::Tick, statistics::units::Count>::get(),
2231  "average overall miss latency"),
2232  ADD_STAT(blockedCycles, statistics::units::Cycle::get(),
2233  "number of cycles access was blocked"),
2234  ADD_STAT(blockedCauses, statistics::units::Count::get(),
2235  "number of times access was blocked"),
2236  ADD_STAT(avgBlocked, statistics::units::Rate<
2237  statistics::units::Cycle, statistics::units::Count>::get(),
2238  "average number of cycles each access was blocked"),
2239  ADD_STAT(writebacks, statistics::units::Count::get(),
2240  "number of writebacks"),
2241  ADD_STAT(demandMshrHits, statistics::units::Count::get(),
2242  "number of demand (read+write) MSHR hits"),
2243  ADD_STAT(overallMshrHits, statistics::units::Count::get(),
2244  "number of overall MSHR hits"),
2245  ADD_STAT(demandMshrMisses, statistics::units::Count::get(),
2246  "number of demand (read+write) MSHR misses"),
2247  ADD_STAT(overallMshrMisses, statistics::units::Count::get(),
2248  "number of overall MSHR misses"),
2249  ADD_STAT(overallMshrUncacheable, statistics::units::Count::get(),
2250  "number of overall MSHR uncacheable misses"),
2251  ADD_STAT(demandMshrMissLatency, statistics::units::Tick::get(),
2252  "number of demand (read+write) MSHR miss ticks"),
2253  ADD_STAT(overallMshrMissLatency, statistics::units::Tick::get(),
2254  "number of overall MSHR miss ticks"),
2255  ADD_STAT(overallMshrUncacheableLatency, statistics::units::Tick::get(),
2256  "number of overall MSHR uncacheable ticks"),
2257  ADD_STAT(demandMshrMissRate, statistics::units::Ratio::get(),
2258  "mshr miss ratio for demand accesses"),
2259  ADD_STAT(overallMshrMissRate, statistics::units::Ratio::get(),
2260  "mshr miss ratio for overall accesses"),
2261  ADD_STAT(demandAvgMshrMissLatency, statistics::units::Rate<
2262  statistics::units::Tick, statistics::units::Count>::get(),
2263  "average overall mshr miss latency"),
2264  ADD_STAT(overallAvgMshrMissLatency, statistics::units::Rate<
2265  statistics::units::Tick, statistics::units::Count>::get(),
2266  "average overall mshr miss latency"),
2267  ADD_STAT(overallAvgMshrUncacheableLatency, statistics::units::Rate<
2268  statistics::units::Tick, statistics::units::Count>::get(),
2269  "average overall mshr uncacheable latency"),
2270  ADD_STAT(replacements, statistics::units::Count::get(),
2271  "number of replacements"),
2272  ADD_STAT(dataExpansions, statistics::units::Count::get(),
2273  "number of data expansions"),
2274  ADD_STAT(dataContractions, statistics::units::Count::get(),
2275  "number of data contractions"),
2276  cmd(MemCmd::NUM_MEM_CMDS)
2277 {
2278  for (int idx = 0; idx < MemCmd::NUM_MEM_CMDS; ++idx)
2279  cmd[idx].reset(new CacheCmdStats(c, MemCmd(idx).toString()));
2280 }
2281 
2282 void
2284 {
2285  using namespace statistics;
2286 
2288 
2289  System *system = cache.system;
2290  const auto max_requestors = system->maxRequestors();
2291 
2292  for (auto &cs : cmd)
2293  cs->regStatsFromParent();
2294 
2295 // These macros make it easier to sum the right subset of commands and
2296 // to change the subset of commands that are considered "demand" vs
2297 // "non-demand"
2298 #define SUM_DEMAND(s) \
2299  (cmd[MemCmd::ReadReq]->s + cmd[MemCmd::WriteReq]->s + \
2300  cmd[MemCmd::WriteLineReq]->s + cmd[MemCmd::ReadExReq]->s + \
2301  cmd[MemCmd::ReadCleanReq]->s + cmd[MemCmd::ReadSharedReq]->s)
2302 
2303 // should writebacks be included here? prior code was inconsistent...
2304 #define SUM_NON_DEMAND(s) \
2305  (cmd[MemCmd::SoftPFReq]->s + cmd[MemCmd::HardPFReq]->s + \
2306  cmd[MemCmd::SoftPFExReq]->s)
2307 
2308  demandHits.flags(total | nozero | nonan);
2309  demandHits = SUM_DEMAND(hits);
2310  for (int i = 0; i < max_requestors; i++) {
2311  demandHits.subname(i, system->getRequestorName(i));
2312  }
2313 
2314  overallHits.flags(total | nozero | nonan);
2315  overallHits = demandHits + SUM_NON_DEMAND(hits);
2316  for (int i = 0; i < max_requestors; i++) {
2317  overallHits.subname(i, system->getRequestorName(i));
2318  }
2319 
2320  demandMisses.flags(total | nozero | nonan);
2321  demandMisses = SUM_DEMAND(misses);
2322  for (int i = 0; i < max_requestors; i++) {
2323  demandMisses.subname(i, system->getRequestorName(i));
2324  }
2325 
2326  overallMisses.flags(total | nozero | nonan);
2327  overallMisses = demandMisses + SUM_NON_DEMAND(misses);
2328  for (int i = 0; i < max_requestors; i++) {
2329  overallMisses.subname(i, system->getRequestorName(i));
2330  }
2331 
2332  demandMissLatency.flags(total | nozero | nonan);
2333  demandMissLatency = SUM_DEMAND(missLatency);
2334  for (int i = 0; i < max_requestors; i++) {
2335  demandMissLatency.subname(i, system->getRequestorName(i));
2336  }
2337 
2338  overallMissLatency.flags(total | nozero | nonan);
2339  overallMissLatency = demandMissLatency + SUM_NON_DEMAND(missLatency);
2340  for (int i = 0; i < max_requestors; i++) {
2341  overallMissLatency.subname(i, system->getRequestorName(i));
2342  }
2343 
2344  demandHitLatency.flags(total | nozero | nonan);
2345  demandHitLatency = SUM_DEMAND(hitLatency);
2346  for (int i = 0; i < max_requestors; i++) {
2347  demandHitLatency.subname(i, system->getRequestorName(i));
2348  }
2349  overallHitLatency.flags(total | nozero | nonan);
2350  overallHitLatency = demandHitLatency + SUM_NON_DEMAND(hitLatency);
2351  for (int i = 0; i < max_requestors; i++) {
2352  overallHitLatency.subname(i, system->getRequestorName(i));
2353  }
2354 
2355  demandAccesses.flags(total | nozero | nonan);
2356  demandAccesses = demandHits + demandMisses;
2357  for (int i = 0; i < max_requestors; i++) {
2358  demandAccesses.subname(i, system->getRequestorName(i));
2359  }
2360 
2361  overallAccesses.flags(total | nozero | nonan);
2362  overallAccesses = overallHits + overallMisses;
2363  for (int i = 0; i < max_requestors; i++) {
2364  overallAccesses.subname(i, system->getRequestorName(i));
2365  }
2366 
2367  demandMissRate.flags(total | nozero | nonan);
2368  demandMissRate = demandMisses / demandAccesses;
2369  for (int i = 0; i < max_requestors; i++) {
2370  demandMissRate.subname(i, system->getRequestorName(i));
2371  }
2372 
2373  overallMissRate.flags(total | nozero | nonan);
2374  overallMissRate = overallMisses / overallAccesses;
2375  for (int i = 0; i < max_requestors; i++) {
2376  overallMissRate.subname(i, system->getRequestorName(i));
2377  }
2378 
2379  demandAvgMissLatency.flags(total | nozero | nonan);
2380  demandAvgMissLatency = demandMissLatency / demandMisses;
2381  for (int i = 0; i < max_requestors; i++) {
2382  demandAvgMissLatency.subname(i, system->getRequestorName(i));
2383  }
2384 
2385  overallAvgMissLatency.flags(total | nozero | nonan);
2386  overallAvgMissLatency = overallMissLatency / overallMisses;
2387  for (int i = 0; i < max_requestors; i++) {
2388  overallAvgMissLatency.subname(i, system->getRequestorName(i));
2389  }
2390 
2391  blockedCycles.init(NUM_BLOCKED_CAUSES);
2392  blockedCycles
2393  .subname(Blocked_NoMSHRs, "no_mshrs")
2394  .subname(Blocked_NoTargets, "no_targets")
2395  ;
2396 
2397 
2398  blockedCauses.init(NUM_BLOCKED_CAUSES);
2399  blockedCauses
2400  .subname(Blocked_NoMSHRs, "no_mshrs")
2401  .subname(Blocked_NoTargets, "no_targets")
2402  ;
2403 
2404  avgBlocked
2405  .subname(Blocked_NoMSHRs, "no_mshrs")
2406  .subname(Blocked_NoTargets, "no_targets")
2407  ;
2408  avgBlocked = blockedCycles / blockedCauses;
2409 
2410  writebacks
2411  .init(max_requestors)
2412  .flags(total | nozero | nonan)
2413  ;
2414  for (int i = 0; i < max_requestors; i++) {
2415  writebacks.subname(i, system->getRequestorName(i));
2416  }
2417 
2418  demandMshrHits.flags(total | nozero | nonan);
2419  demandMshrHits = SUM_DEMAND(mshrHits);
2420  for (int i = 0; i < max_requestors; i++) {
2421  demandMshrHits.subname(i, system->getRequestorName(i));
2422  }
2423 
2424  overallMshrHits.flags(total | nozero | nonan);
2425  overallMshrHits = demandMshrHits + SUM_NON_DEMAND(mshrHits);
2426  for (int i = 0; i < max_requestors; i++) {
2427  overallMshrHits.subname(i, system->getRequestorName(i));
2428  }
2429 
2430  demandMshrMisses.flags(total | nozero | nonan);
2431  demandMshrMisses = SUM_DEMAND(mshrMisses);
2432  for (int i = 0; i < max_requestors; i++) {
2433  demandMshrMisses.subname(i, system->getRequestorName(i));
2434  }
2435 
2436  overallMshrMisses.flags(total | nozero | nonan);
2437  overallMshrMisses = demandMshrMisses + SUM_NON_DEMAND(mshrMisses);
2438  for (int i = 0; i < max_requestors; i++) {
2439  overallMshrMisses.subname(i, system->getRequestorName(i));
2440  }
2441 
2442  demandMshrMissLatency.flags(total | nozero | nonan);
2443  demandMshrMissLatency = SUM_DEMAND(mshrMissLatency);
2444  for (int i = 0; i < max_requestors; i++) {
2445  demandMshrMissLatency.subname(i, system->getRequestorName(i));
2446  }
2447 
2448  overallMshrMissLatency.flags(total | nozero | nonan);
2449  overallMshrMissLatency =
2450  demandMshrMissLatency + SUM_NON_DEMAND(mshrMissLatency);
2451  for (int i = 0; i < max_requestors; i++) {
2452  overallMshrMissLatency.subname(i, system->getRequestorName(i));
2453  }
2454 
2455  overallMshrUncacheable.flags(total | nozero | nonan);
2456  overallMshrUncacheable =
2457  SUM_DEMAND(mshrUncacheable) + SUM_NON_DEMAND(mshrUncacheable);
2458  for (int i = 0; i < max_requestors; i++) {
2459  overallMshrUncacheable.subname(i, system->getRequestorName(i));
2460  }
2461 
2462 
2463  overallMshrUncacheableLatency.flags(total | nozero | nonan);
2464  overallMshrUncacheableLatency =
2465  SUM_DEMAND(mshrUncacheableLatency) +
2466  SUM_NON_DEMAND(mshrUncacheableLatency);
2467  for (int i = 0; i < max_requestors; i++) {
2468  overallMshrUncacheableLatency.subname(i, system->getRequestorName(i));
2469  }
2470 
2471  demandMshrMissRate.flags(total | nozero | nonan);
2472  demandMshrMissRate = demandMshrMisses / demandAccesses;
2473  for (int i = 0; i < max_requestors; i++) {
2474  demandMshrMissRate.subname(i, system->getRequestorName(i));
2475  }
2476 
2477  overallMshrMissRate.flags(total | nozero | nonan);
2478  overallMshrMissRate = overallMshrMisses / overallAccesses;
2479  for (int i = 0; i < max_requestors; i++) {
2480  overallMshrMissRate.subname(i, system->getRequestorName(i));
2481  }
2482 
2483  demandAvgMshrMissLatency.flags(total | nozero | nonan);
2484  demandAvgMshrMissLatency = demandMshrMissLatency / demandMshrMisses;
2485  for (int i = 0; i < max_requestors; i++) {
2486  demandAvgMshrMissLatency.subname(i, system->getRequestorName(i));
2487  }
2488 
2489  overallAvgMshrMissLatency.flags(total | nozero | nonan);
2490  overallAvgMshrMissLatency = overallMshrMissLatency / overallMshrMisses;
2491  for (int i = 0; i < max_requestors; i++) {
2492  overallAvgMshrMissLatency.subname(i, system->getRequestorName(i));
2493  }
2494 
2495  overallAvgMshrUncacheableLatency.flags(total | nozero | nonan);
2496  overallAvgMshrUncacheableLatency =
2497  overallMshrUncacheableLatency / overallMshrUncacheable;
2498  for (int i = 0; i < max_requestors; i++) {
2499  overallAvgMshrUncacheableLatency.subname(i,
2501  }
2502 
2503  dataExpansions.flags(nozero | nonan);
2504  dataContractions.flags(nozero | nonan);
2505 }
2506 
2507 void
2509 {
2510  ppHit = new ProbePointArg<PacketPtr>(this->getProbeManager(), "Hit");
2511  ppMiss = new ProbePointArg<PacketPtr>(this->getProbeManager(), "Miss");
2512  ppFill = new ProbePointArg<PacketPtr>(this->getProbeManager(), "Fill");
2513  ppDataUpdate =
2514  new ProbePointArg<DataUpdate>(this->getProbeManager(), "Data Update");
2515 }
2516 
2518 //
2519 // CpuSidePort
2520 //
2522 bool
2524 {
2525  // Snoops shouldn't happen when bypassing caches
2526  assert(!cache.system->bypassCaches());
2527 
2528  assert(pkt->isResponse());
2529 
2530  // Express snoop responses from requestor to responder, e.g., from L1 to L2
2531  cache.recvTimingSnoopResp(pkt);
2532  return true;
2533 }
2534 
2535 
2536 bool
2538 {
2539  if (cache.system->bypassCaches() || pkt->isExpressSnoop()) {
2540  // always let express snoop packets through even if blocked
2541  return true;
2542  } else if (blocked || mustSendRetry) {
2543  // either already committed to send a retry, or blocked
2544  mustSendRetry = true;
2545  return false;
2546  }
2547  mustSendRetry = false;
2548  return true;
2549 }
2550 
2551 bool
2553 {
2554  assert(pkt->isRequest());
2555 
2556  if (cache.system->bypassCaches()) {
2557  // Just forward the packet if caches are disabled.
2558  // @todo This should really enqueue the packet rather
2559  [[maybe_unused]] bool success = cache.memSidePort.sendTimingReq(pkt);
2560  assert(success);
2561  return true;
2562  } else if (tryTiming(pkt)) {
2563  cache.recvTimingReq(pkt);
2564  return true;
2565  }
2566  return false;
2567 }
2568 
2569 Tick
2571 {
2572  if (cache.system->bypassCaches()) {
2573  // Forward the request if the system is in cache bypass mode.
2574  return cache.memSidePort.sendAtomic(pkt);
2575  } else {
2576  return cache.recvAtomic(pkt);
2577  }
2578 }
2579 
2580 void
2582 {
2583  if (cache.system->bypassCaches()) {
2584  // The cache should be flushed if we are in cache bypass mode,
2585  // so we don't need to check if we need to update anything.
2586  cache.memSidePort.sendFunctional(pkt);
2587  return;
2588  }
2589 
2590  // functional request
2591  cache.functionalAccess(pkt, true);
2592 }
2593 
2596 {
2597  return cache.getAddrRanges();
2598 }
2599 
2600 
2602 CpuSidePort::CpuSidePort(const std::string &_name, BaseCache& _cache,
2603  const std::string &_label)
2604  : CacheResponsePort(_name, _cache, _label)
2605 {
2606 }
2607 
2609 //
2610 // MemSidePort
2611 //
2613 bool
2615 {
2616  cache->recvTimingResp(pkt);
2617  return true;
2618 }
2619 
2620 // Express snooping requests to memside port
2621 void
2623 {
2624  // Snoops shouldn't happen when bypassing caches
2625  assert(!cache->system->bypassCaches());
2626 
2627  // handle snooping requests
2628  cache->recvTimingSnoopReq(pkt);
2629 }
2630 
2631 Tick
2633 {
2634  // Snoops shouldn't happen when bypassing caches
2635  assert(!cache->system->bypassCaches());
2636 
2637  return cache->recvAtomicSnoop(pkt);
2638 }
2639 
2640 void
2642 {
2643  // Snoops shouldn't happen when bypassing caches
2644  assert(!cache->system->bypassCaches());
2645 
2646  // functional snoop (note that in contrast to atomic we don't have
2647  // a specific functionalSnoop method, as they have the same
2648  // behaviour regardless)
2649  cache->functionalAccess(pkt, false);
2650 }
2651 
2652 void
2654 {
2655  // sanity check
2656  assert(!waitingOnRetry);
2657 
2658  // there should never be any deferred request packets in the
2659  // queue, instead we resly on the cache to provide the packets
2660  // from the MSHR queue or write queue
2661  assert(deferredPacketReadyTime() == MaxTick);
2662 
2663  // check for request packets (requests & writebacks)
2664  QueueEntry* entry = cache.getNextQueueEntry();
2665 
2666  if (!entry) {
2667  // can happen if e.g. we attempt a writeback and fail, but
2668  // before the retry, the writeback is eliminated because
2669  // we snoop another cache's ReadEx.
2670  } else {
2671  // let our snoop responses go first if there are responses to
2672  // the same addresses
2673  if (checkConflictingSnoop(entry->getTarget()->pkt)) {
2674  return;
2675  }
2676  waitingOnRetry = entry->sendPacket(cache);
2677  }
2678 
2679  // if we succeeded and are not waiting for a retry, schedule the
2680  // next send considering when the next queue is ready, note that
2681  // snoop responses have their own packet queue and thus schedule
2682  // their own events
2683  if (!waitingOnRetry) {
2684  schedSendEvent(cache.nextQueueReadyTime());
2685  }
2686 }
2687 
2689  BaseCache *_cache,
2690  const std::string &_label)
2691  : CacheRequestPort(_name, _reqQueue, _snoopRespQueue),
2692  _reqQueue(*_cache, *this, _snoopRespQueue, _label),
2693  _snoopRespQueue(*_cache, *this, true, _label), cache(_cache)
2694 {
2695 }
2696 
2697 void
2698 WriteAllocator::updateMode(Addr write_addr, unsigned write_size,
2699  Addr blk_addr)
2700 {
2701  // check if we are continuing where the last write ended
2702  if (nextAddr == write_addr) {
2703  delayCtr[blk_addr] = delayThreshold;
2704  // stop if we have already saturated
2705  if (mode != WriteMode::NO_ALLOCATE) {
2706  byteCount += write_size;
2707  // switch to streaming mode if we have passed the lower
2708  // threshold
2709  if (mode == WriteMode::ALLOCATE &&
2710  byteCount > coalesceLimit) {
2711  mode = WriteMode::COALESCE;
2712  DPRINTF(Cache, "Switched to write coalescing\n");
2713  } else if (mode == WriteMode::COALESCE &&
2714  byteCount > noAllocateLimit) {
2715  // and continue and switch to non-allocating mode if we
2716  // pass the upper threshold
2717  mode = WriteMode::NO_ALLOCATE;
2718  DPRINTF(Cache, "Switched to write-no-allocate\n");
2719  }
2720  }
2721  } else {
2722  // we did not see a write matching the previous one, start
2723  // over again
2724  byteCount = write_size;
2725  mode = WriteMode::ALLOCATE;
2726  resetDelay(blk_addr);
2727  }
2728  nextAddr = write_addr + write_size;
2729 }
2730 
2731 } // namespace gem5
gem5::Packet::getBlockAddr
Addr getBlockAddr(unsigned int blk_size) const
Definition: packet.hh:831
gem5::BaseCache::memWriteback
virtual void memWriteback() override
Write back dirty blocks in the cache using functional accesses.
Definition: base.cc:1789
gem5::curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
fatal
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:200
gem5::PortID
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:245
gem5::Request::funcRequestorId
@ funcRequestorId
This requestor id is used for functional requests that don't come from a particular device.
Definition: request.hh:279
gem5::MSHR
Miss Status and handling Register.
Definition: mshr.hh:74
gem5::SimObject::getPort
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
Definition: sim_object.cc:123
gem5::Packet::isAtomicOp
bool isAtomicOp() const
Definition: packet.hh:846
gem5::BaseCache::MemSidePort::MemSidePort
MemSidePort(const std::string &_name, BaseCache *_cache, const std::string &_label)
Definition: base.cc:2688
gem5::BaseCache::incMissCount
void incMissCount(PacketPtr pkt)
Definition: base.hh:1292
gem5::BaseCache::cpuSidePort
CpuSidePort cpuSidePort
Definition: base.hh:334
queue_entry.hh
gem5::RequestPort::sendTimingReq
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the responder port by calling its corresponding receive function.
Definition: port.hh:587
gem5::BaseCache::handleTimingReqMiss
virtual void handleTimingReqMiss(PacketPtr pkt, CacheBlk *blk, Tick forward_time, Tick request_time)=0
gem5::Packet::isRequest
bool isRequest() const
Definition: packet.hh:597
gem5::BaseCache::CacheCmdStats::regStatsFromParent
void regStatsFromParent()
Callback to register stats from parent CacheStats::regStats().
Definition: base.cc:2066
warn
#define warn(...)
Definition: logging.hh:256
gem5::WriteAllocator::reset
void reset()
Reset the write allocator state, meaning that it allocates for writes and has not recorded any inform...
Definition: base.hh:1411
compressed_tags.hh
gem5::BaseCache::~BaseCache
~BaseCache()
Definition: base.cc:140
base.hh
gem5::BaseCache::invalidateBlock
void invalidateBlock(CacheBlk *blk)
Invalidate a cache block.
Definition: base.cc:1664
gem5::MemCmd::LockedRMWWriteReq
@ LockedRMWWriteReq
Definition: packet.hh:118
gem5::MemCmd::WriteClean
@ WriteClean
Definition: packet.hh:95
gem5::BaseCache::DataUpdate::oldData
std::vector< uint64_t > oldData
The stale data contents.
Definition: base.hh:130
gem5::Packet::getOffset
Addr getOffset(unsigned int blk_size) const
Definition: packet.hh:826
gem5::MemCmd::CleanEvict
@ CleanEvict
Definition: packet.hh:96
gem5::BaseCache::CacheStats::replacements
statistics::Scalar replacements
Number of replacements of valid blocks.
Definition: base.hh:1130
gem5::ResponsePort::sendFunctionalSnoop
void sendFunctionalSnoop(PacketPtr pkt) const
Send a functional snoop request packet, where the data is instantly updated everywhere in the memory ...
Definition: port.hh:414
gem5::CacheBlk::clearPrefetched
void clearPrefetched()
Clear the prefetching bit.
Definition: cache_blk.hh:255
gem5::BaseCache::cmpAndSwap
void cmpAndSwap(CacheBlk *blk, PacketPtr pkt)
Handle doing the Compare and Swap function for SPARC.
Definition: base.cc:797
gem5::MipsISA::misc_reg::Count
@ Count
Definition: misc.hh:94
gem5::BaseCache::NUM_BLOCKED_CAUSES
@ NUM_BLOCKED_CAUSES
Definition: base.hh:115
data
const char data[]
Definition: circlebuf.test.cc:48
gem5::BaseCache::ppDataUpdate
ProbePointArg< DataUpdate > * ppDataUpdate
To probe when the contents of a block are updated.
Definition: base.hh:368
gem5::MemCmd::SwapReq
@ SwapReq
Definition: packet.hh:120
UNSERIALIZE_SCALAR
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:575
gem5::BaseCache::CacheRequestPort
A cache request port is used for the memory-side port of the cache, and in addition to the basic timi...
Definition: base.hh:151
gem5::BaseCache::access
virtual bool access(PacketPtr pkt, CacheBlk *&blk, Cycles &lat, PacketList &writebacks)
Does all the processing necessary to perform the provided request.
Definition: base.cc:1230
gem5::BaseCache::forwardSnoops
bool forwardSnoops
Do we forward snoops from mem side port through to cpu side port?
Definition: base.hh:924
gem5::Packet::isCleanEviction
bool isCleanEviction() const
Is this packet a clean eviction, including both actual clean evict packets, but also clean writebacks...
Definition: packet.hh:1435
gem5::BaseCache::CacheCmdStats::mshrHits
statistics::Vector mshrHits
Number of misses that hit in the MSHRs per command and thread.
Definition: base.hh:1021
gem5::TempCacheBlk::invalidate
void invalidate() override
Invalidate the block and clear all state.
Definition: cache_blk.hh:524
gem5::BaseCache::CacheResponsePort::processSendRetry
void processSendRetry()
Definition: base.cc:173
gem5::BaseCache::writeBuffer
WriteQueue writeBuffer
Write/writeback buffer.
Definition: base.hh:343
warn_once
#define warn_once(...)
Definition: logging.hh:260
gem5::Packet::setData
void setData(const uint8_t *p)
Copy data into the packet from the provided pointer.
Definition: packet.hh:1293
gem5::BaseCache::moveContractions
const bool moveContractions
Similar to data expansions, after a block improves its compression, it may need to be moved elsewhere...
Definition: base.hh:955
gem5::Packet::pushSenderState
void pushSenderState(SenderState *sender_state)
Push a new sender state to the packet and make the current sender state the predecessor of the new on...
Definition: packet.cc:334
gem5::BaseCache::recvTimingResp
virtual void recvTimingResp(PacketPtr pkt)
Handles a response (cache line fill/write ack) from the bus.
Definition: base.cc:489
mshr.hh
gem5::Packet::req
RequestPtr req
A pointer to the original request.
Definition: packet.hh:377
gem5::MSHR::allocOnFill
bool allocOnFill() const
Definition: mshr.hh:340
gem5::MSHR::isForward
bool isForward
True if the entry is just a simple forward from an upper level.
Definition: mshr.hh:127
gem5::BaseCache::MemSidePort::recvFunctionalSnoop
virtual void recvFunctionalSnoop(PacketPtr pkt)
Receive a functional snoop request packet from the peer.
Definition: base.cc:2641
gem5::BaseCache::coalesce
bool coalesce() const
Checks if the cache is coalescing writes.
Definition: base.cc:1808
base.hh
gem5::CheckpointIn
Definition: serialize.hh:68
gem5::compression::Base::getDecompressionLatency
Cycles getDecompressionLatency(const CacheBlk *blk)
Get the decompression latency if the block is compressed.
Definition: base.cc:196
gem5::CompressionBlk::setSizeBits
void setSizeBits(const std::size_t size)
Set size, in bits, of this compressed block's data.
Definition: super_blk.cc:99
gem5::EventBase::Delayed_Writeback_Pri
static const Priority Delayed_Writeback_Pri
For some reason "delayed" inter-cluster writebacks are scheduled before regular writebacks (which hav...
Definition: eventq.hh:175
gem5::MSHRQueue::canPrefetch
bool canPrefetch() const
Returns true if sufficient mshrs for prefetch.
Definition: mshr_queue.hh:158
SUM_NON_DEMAND
#define SUM_NON_DEMAND(s)
gem5::Packet::writeThrough
bool writeThrough() const
Definition: packet.hh:742
gem5::statistics::nozero
const FlagsType nozero
Don't print if this is zero.
Definition: info.hh:67
gem5::BaseCache::getPort
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
Definition: base.cc:202
cur_tick.hh
gem5::BaseCache::markInService
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:404
gem5::Packet::setCacheResponding
void setCacheResponding()
Snoop flags.
Definition: packet.hh:653
gem5::Packet::isWriteback
bool isWriteback() const
Definition: packet.hh:613
gem5::MSHR::promoteDeferredTargets
bool promoteDeferredTargets()
Definition: mshr.cc:597
gem5::MSHR::promoteWritable
void promoteWritable()
Promotes deferred targets that do not require writable.
Definition: mshr.cc:680
gem5::Packet::cacheResponding
bool cacheResponding() const
Definition: packet.hh:659
gem5::WriteQueueEntry::getTarget
Target * getTarget() override
Returns a reference to the first target.
Definition: write_queue_entry.hh:155
gem5::prefetch::Base::prefetchUnused
void prefetchUnused()
Definition: base.hh:390
gem5::TempCacheBlk
Special instance of CacheBlk for use with tempBlk that deals with its block address regeneration.
Definition: cache_blk.hh:500
gem5::Packet::isUpgrade
bool isUpgrade() const
Definition: packet.hh:596
gem5::MaxTick
const Tick MaxTick
Definition: types.hh:60
gem5::Packet::isWrite
bool isWrite() const
Definition: packet.hh:594
gem5::CacheBlk::clearCoherenceBits
void clearCoherenceBits(unsigned bits)
Clear the corresponding coherence bits.
Definition: cache_blk.hh:231
gem5::Packet::isSecure
bool isSecure() const
Definition: packet.hh:836
gem5::MSHRQueue::delay
void delay(MSHR *mshr, Tick delay_ticks)
Adds a delay to the provided MSHR and moves MSHRs that will be ready earlier than this entry to the t...
Definition: mshr_queue.cc:104
gem5::MemCmd::NUM_MEM_CMDS
@ NUM_MEM_CMDS
Definition: packet.hh:152
gem5::Packet::setWriteThrough
void setWriteThrough()
A writeback/writeclean cmd gets propagated further downstream by the receiver when the flag is set.
Definition: packet.hh:735
gem5::BaseCache::clearBlocked
void clearBlocked(BlockedCause cause)
Marks the cache as unblocked for the given cause.
Definition: base.hh:1251
gem5::BaseCache::dataLatency
const Cycles dataLatency
The latency of data access of a cache.
Definition: base.hh:896
gem5::Packet::hasSharers
bool hasSharers() const
Definition: packet.hh:686
gem5::BaseCache::updateCompressionData
bool updateCompressionData(CacheBlk *&blk, const uint64_t *data, PacketList &writebacks)
When a block is overwriten, its compression information must be updated, and it may need to be recomp...
Definition: base.cc:978
gem5::BaseCache::CacheCmdStats::mshrMisses
statistics::Vector mshrMisses
Number of misses that miss in the MSHRs, per command and thread.
Definition: base.hh:1023
gem5::X86ISA::system
Bitfield< 15 > system
Definition: misc.hh:1004
gem5::CompressionBlk::getSizeBits
std::size_t getSizeBits() const
Definition: super_blk.cc:93
gem5::BaseCache::replaceExpansions
const bool replaceExpansions
when a data expansion of a compressed block happens it will not be able to co-allocate where it is at...
Definition: base.hh:947
gem5::BaseCache::blocked
uint8_t blocked
Bit vector of the blocking reasons for the access path.
Definition: base.hh:961
gem5::QueueEntry::Target
A queue entry is holding packets that will be serviced as soon as resources are available.
Definition: queue_entry.hh:87
gem5::EventManager::schedule
void schedule(Event &event, Tick when)
Definition: eventq.hh:1012
std::vector< uint64_t >
gem5::WriteAllocator::updateMode
void updateMode(Addr write_addr, unsigned write_size, Addr blk_addr)
Update the write mode based on the current write packet.
Definition: base.cc:2698
gem5::statistics::nonan
const FlagsType nonan
Don't print if this is NAN.
Definition: info.hh:69
gem5::CacheBlk::checkWrite
bool checkWrite(PacketPtr pkt)
Handle interaction of load-locked operations and stores.
Definition: cache_blk.hh:412
gem5::BaseCache::sequentialAccess
const bool sequentialAccess
Whether tags and data are accessed sequentially.
Definition: base.hh:918
gem5::BaseCache::BaseCache
BaseCache(const BaseCacheParams &p, unsigned blk_size)
Definition: base.cc:80
gem5::BaseCache::updateBlockData
void updateBlockData(CacheBlk *blk, const PacketPtr cpkt, bool has_old_data)
Update the data contents of a block.
Definition: base.cc:771
gem5::Packet::makeAtomicResponse
void makeAtomicResponse()
Definition: packet.hh:1074
gem5::Packet::setDataFromBlock
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:1312
gem5::VegaISA::r
Bitfield< 5 > r
Definition: pagetable.hh:60
gem5::MSHRQueue::markInService
void markInService(MSHR *mshr, bool pending_modified_resp)
Mark the given MSHR as in service.
Definition: mshr_queue.cc:115
gem5::BaseCache::pendingDelete
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:398
gem5::BaseCache::CacheResponsePort
A cache response port is used for the CPU-side port of the cache, and it is basically a simple timing...
Definition: base.hh:273
gem5::BaseTags::moveBlock
virtual void moveBlock(CacheBlk *src_blk, CacheBlk *dest_blk)
Move a block's metadata to another location decided by the replacement policy.
Definition: base.cc:130
gem5::CacheBlk::WritableBit
@ WritableBit
write permission
Definition: cache_blk.hh:80
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:67
gem5::Packet::headerDelay
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
Definition: packet.hh:431
gem5::SectorSubBlk::getSectorBlock
SectorBlk * getSectorBlock() const
Get sector block associated to this block.
Definition: sector_blk.cc:52
gem5::Packet::setSatisfied
void setSatisfied()
Set when a request hits in a cache and the cache is not going to respond.
Definition: packet.hh:749
gem5::QueueEntry::blkAddr
Addr blkAddr
Block aligned address.
Definition: queue_entry.hh:116
gem5::SectorBlk::blks
std::vector< SectorSubBlk * > blks
List of blocks associated to this sector.
Definition: sector_blk.hh:147
gem5::QueueEntry::order
Counter order
Order number assigned to disambiguate writes and misses.
Definition: queue_entry.hh:113
gem5::CompressionBlk::DATA_EXPANSION
@ DATA_EXPANSION
New data contents are considered larger than previous contents.
Definition: super_blk.hh:81
gem5::CacheBlk
A Basic Cache block.
Definition: cache_blk.hh:70
gem5::BaseCache::tempBlock
TempCacheBlk * tempBlock
Temporary cache block for occasional transitory use.
Definition: base.hh:392
gem5::BaseCache::handleAtomicReqMiss
virtual Cycles handleAtomicReqMiss(PacketPtr pkt, CacheBlk *&blk, PacketList &writebacks)=0
Handle a request in atomic mode that missed in this cache.
gem5::QueueEntry::Target::pkt
PacketPtr pkt
Pending request packet.
Definition: queue_entry.hh:93
gem5::BaseCache::sendWriteQueuePacket
bool sendWriteQueuePacket(WriteQueueEntry *wq_entry)
Similar to sendMSHR, but for a write-queue entry instead.
Definition: base.cc:1970
gem5::BaseCache::CacheCmdStats::mshrMissLatency
statistics::Vector mshrMissLatency
Total tick latency of each MSHR miss, per command and thread.
Definition: base.hh:1027
gem5::BaseCache::CpuSidePort::recvTimingReq
virtual bool recvTimingReq(PacketPtr pkt) override
Receive a timing request from the peer.
Definition: base.cc:2552
gem5::BaseCache::CacheResponsePort::setBlocked
void setBlocked()
Do not accept any new requests.
Definition: base.cc:146
gem5::BaseCache::isBlocked
bool isBlocked() const
Returns true if the cache is blocked for accesses.
Definition: base.hh:1222
gem5::Cycles
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:78
gem5::BaseCache::writeAllocator
WriteAllocator *const writeAllocator
The writeAllocator drive optimizations for streaming writes.
Definition: base.hh:384
gem5::TempCacheBlk::getAddr
Addr getAddr() const
Get block's address.
Definition: cache_blk.hh:542
gem5::MemCmd::WritebackDirty
@ WritebackDirty
Definition: packet.hh:93
gem5::BaseCache::inRange
bool inRange(Addr addr) const
Determine if an address is in the ranges covered by this cache.
Definition: base.cc:214
gem5::Packet::hasData
bool hasData() const
Definition: packet.hh:614
gem5::MemCmd
Definition: packet.hh:76
gem5::BaseCache::DataUpdate::newData
std::vector< uint64_t > newData
The new data contents.
Definition: base.hh:132
gem5::Packet::getAtomicOp
AtomicOpFunctor * getAtomicOp() const
Accessor function to atomic op.
Definition: packet.hh:845
gem5::BaseCache::writebackTempBlockAtomicEvent
EventFunctionWrapper writebackTempBlockAtomicEvent
An event to writeback the tempBlock after recvAtomic finishes.
Definition: base.hh:699
gem5::Packet::payloadDelay
uint32_t payloadDelay
The extra pipelining delay from seeing the packet until the end of payload is transmitted by the comp...
Definition: packet.hh:449
gem5::BaseCache::Blocked_NoTargets
@ Blocked_NoTargets
Definition: base.hh:114
gem5::BaseCache::CpuSidePort::CpuSidePort
CpuSidePort(const std::string &_name, BaseCache &_cache, const std::string &_label)
Definition: base.cc:2602
gem5::Packet::dataStatic
void dataStatic(T *p)
Set the data pointer to the following value that should not be freed.
Definition: packet.hh:1175
gem5::BaseCache::DataUpdate
A data contents update is composed of the updated block's address, the old contents,...
Definition: base.hh:123
gem5::QueueEntry::Target::recvTime
const Tick recvTime
Time when request was received (for stats)
Definition: queue_entry.hh:90
gem5::VegaISA::c
Bitfield< 2 > c
Definition: pagetable.hh:63
gem5::BaseCache::order
uint64_t order
Increasing order number assigned to each incoming request.
Definition: base.hh:964
gem5::CacheBlk::getTaskId
uint32_t getTaskId() const
Get the task id associated to this block.
Definition: cache_blk.hh:285
gem5::Flags< FlagsType >
gem5::BaseCache::serialize
void serialize(CheckpointOut &cp) const override
Serialize the state of the caches.
Definition: base.cc:1994
gem5::BaseCache::ppMiss
ProbePointArg< PacketPtr > * ppMiss
To probe when a cache miss occurs.
Definition: base.hh:358
gem5::System::maxRequestors
RequestorID maxRequestors()
Get the number of requestors registered in the system.
Definition: system.hh:495
gem5::RequestPort::sendFunctional
void sendFunctional(PacketPtr pkt) const
Send a functional request packet, where the data is instantly updated everywhere in the memory system...
Definition: port.hh:563
gem5::CacheBlk::setWhenReady
void setWhenReady(const Tick tick)
Set tick at which block's data will be available for access.
Definition: cache_blk.hh:278
gem5::Packet::isRead
bool isRead() const
Definition: packet.hh:593
gem5::BaseCache::prefetcher
prefetch::Base * prefetcher
Prefetcher.
Definition: base.hh:352
base.hh
gem5::System
Definition: system.hh:74
gem5::BaseCache::tags
BaseTags * tags
Tag and data Storage.
Definition: base.hh:346
gem5::WriteAllocator::allocate
bool allocate() const
Should writes allocate?
Definition: base.hh:1401
gem5::Queue::isFull
bool isFull() const
Definition: queue.hh:150
gem5::BaseCache::CacheStats::regStats
void regStats() override
Callback to set stat parameters.
Definition: base.cc:2283
gem5::Packet::needsWritable
bool needsWritable() const
Definition: packet.hh:599
gem5::BaseCache::ppFill
ProbePointArg< PacketPtr > * ppFill
To probe when a cache fill occurs.
Definition: base.hh:361
gem5::Queue::nextReadyTime
Tick nextReadyTime() const
Definition: queue.hh:229
gem5::MSHR::allocateTarget
void allocateTarget(PacketPtr target, Tick when, Counter order, bool alloc_on_fill)
Add a request to the list of targets.
Definition: mshr.cc:377
gem5::BaseCache::CacheStats::cmd
std::vector< std::unique_ptr< CacheCmdStats > > cmd
Per-command statistics.
Definition: base.hh:1142
gem5::BaseCache::allocateWriteBuffer
void allocateWriteBuffer(PacketPtr pkt, Tick time)
Definition: base.hh:1187
gem5::prefetch::Base::pfHitInMSHR
void pfHitInMSHR()
Definition: base.hh:408
gem5::Named::name
virtual std::string name() const
Definition: named.hh:47
gem5::VegaISA::p
Bitfield< 54 > p
Definition: pagetable.hh:70
gem5::MSHR::needsWritable
bool needsWritable() const
The pending* and post* flags are only valid if inService is true.
Definition: mshr.hh:319
gem5::BaseCache::MemSidePort::recvTimingResp
virtual bool recvTimingResp(PacketPtr pkt)
Receive a timing response from the peer.
Definition: base.cc:2614
gem5::Packet::print
void print(std::ostream &o, int verbosity=0, const std::string &prefix="") const
Definition: packet.cc:368
gem5::BaseCache::stats
gem5::BaseCache::CacheStats stats
gem5::SuperBlk
A basic compression superblock.
Definition: super_blk.hh:170
gem5::Clocked::cyclesToTicks
Tick cyclesToTicks(Cycles c) const
Definition: clocked_object.hh:227
gem5::BaseCache::CacheResponsePort::CacheResponsePort
CacheResponsePort(const std::string &_name, BaseCache &_cache, const std::string &_label)
Definition: base.cc:69
gem5::BaseCache
A basic cache interface.
Definition: base.hh:94
gem5::QueuedResponsePort
A queued port is a port that has an infinite queue for outgoing packets and thus decouples the module...
Definition: qport.hh:61
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:210
ADD_STAT
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition: group.hh:75
gem5::PacketId
uint64_t PacketId
Definition: packet.hh:74
gem5::Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:294
gem5::BaseCache::calculateTagOnlyLatency
Cycles calculateTagOnlyLatency(const uint32_t delay, const Cycles lookup_lat) const
Calculate latency of accesses that only touch the tag array.
Definition: base.cc:1187
gem5::MemCmd::UpgradeResp
@ UpgradeResp
Definition: packet.hh:105
gem5::BaseCache::sendMSHRQueuePacket
virtual bool sendMSHRQueuePacket(MSHR *mshr)
Take an MSHR, turn it into a suitable downstream packet, and send it out.
Definition: base.cc:1867
gem5::MSHR::isPendingModified
bool isPendingModified() const
Definition: mshr.hh:326
gem5::Request::wbRequestorId
@ wbRequestorId
This requestor id is used for writeback requests by the caches.
Definition: request.hh:274
gem5::BaseCache::writecleanBlk
PacketPtr writecleanBlk(CacheBlk *blk, Request::Flags dest, PacketId id)
Create a writeclean request for the given block.
Definition: base.cc:1743
gem5::probing::Packet
ProbePointArg< PacketInfo > Packet
Packet probe point.
Definition: mem.hh:108
gem5::BaseCache::CacheResponsePort::cache
BaseCache & cache
Definition: base.hh:291
gem5::BaseCache::blkSize
const unsigned blkSize
Block size of this cache.
Definition: base.hh:884
gem5::Tick
uint64_t Tick
Tick count type.
Definition: types.hh:58
gem5::Queue::getNext
Entry * getNext() const
Returns the WriteQueueEntry at the head of the readyList.
Definition: queue.hh:221
gem5::BaseCache::regenerateBlkAddr
Addr regenerateBlkAddr(CacheBlk *blk)
Regenerate block address using tags.
Definition: base.cc:183
gem5::ResponsePort::isSnooping
bool isSnooping() const
Find out if the peer request port is snooping or not.
Definition: port.hh:359
gem5::BaseCache::ppHit
ProbePointArg< PacketPtr > * ppHit
To probe when a cache hit occurs.
Definition: base.hh:355
gem5::QueueEntry::isSecure
bool isSecure
True if the entry targets the secure memory space.
Definition: queue_entry.hh:122
gem5::BaseCache::CacheResponsePort::clearBlocked
void clearBlocked()
Return to normal operation and accept new requests.
Definition: base.cc:161
gem5::BaseCache::recvAtomic
virtual Tick recvAtomic(PacketPtr pkt)
Performs the access specified by the request.
Definition: base.cc:635
gem5::System::getRequestorName
std::string getRequestorName(RequestorID requestor_id)
Get the name of an object for a given request id.
Definition: system.cc:526
gem5::BaseCache::CpuSidePort::recvTimingSnoopResp
virtual bool recvTimingSnoopResp(PacketPtr pkt) override
Receive a timing snoop response from the peer.
Definition: base.cc:2523
gem5::RequestPtr
std::shared_ptr< Request > RequestPtr
Definition: request.hh:92
gem5::BaseTags::regenerateBlkAddr
virtual Addr regenerateBlkAddr(const CacheBlk *blk) const =0
Regenerate the block address.
gem5::Packet::getConstPtr
const T * getConstPtr() const
Definition: packet.hh:1234
gem5::statistics::reset
void reset()
Definition: statistics.cc:309
gem5::BaseTags::accessBlock
virtual CacheBlk * accessBlock(const PacketPtr pkt, Cycles &lat)=0
Access block and update replacement data.
gem5::CacheBlk::setCoherenceBits
void setCoherenceBits(unsigned bits)
Sets the corresponding coherence bits.
Definition: cache_blk.hh:220
gem5::BaseCache::CacheStats::writebacks
statistics::Vector writebacks
Number of blocks written back per thread.
Definition: base.hh:1093
gem5::CompressedTags
A CompressedTags cache tag store.
Definition: compressed_tags.hh:70
gem5::compression::Base::setSizeBits
static void setSizeBits(CacheBlk *blk, const std::size_t size_bits)
Set the size of the compressed block, in bits.
Definition: base.cc:224
gem5::Packet::isLLSC
bool isLLSC() const
Definition: packet.hh:620
gem5::MemCmd::WritebackClean
@ WritebackClean
Definition: packet.hh:94
gem5::BaseCache::init
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: base.cc:193
gem5::CacheBlk::print
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:364
gem5::Queue::findMatch
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:168
gem5::Packet::clearBlockCached
void clearBlockCached()
Definition: packet.hh:761
gem5::ArmISA::offset
Bitfield< 23, 0 > offset
Definition: types.hh:144
gem5::Port::isConnected
bool isConnected() const
Is this port currently connected to a peer?
Definition: port.hh:133
gem5::BaseCache::CacheStats::dataExpansions
statistics::Scalar dataExpansions
Number of data expansions.
Definition: base.hh:1133
gem5::BaseCache::CacheResponsePort::mustSendRetry
bool mustSendRetry
Definition: base.hh:298
compiler.hh
gem5::Packet::id
const PacketId id
Definition: packet.hh:374
gem5::MSHR::isWholeLineWrite
bool isWholeLineWrite() const
Check if this MSHR contains only compatible writes, and if they span the entire cache line.
Definition: mshr.hh:406
gem5::BaseCache::unserialize
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: base.cc:2014
gem5::BaseCache::allocOnFill
bool allocOnFill(MemCmd cmd) const
Determine whether we should allocate on a fill or not.
Definition: base.hh:437
gem5::BaseCache::incHitCount
void incHitCount(PacketPtr pkt)
Definition: base.hh:1303
gem5::Queue::trySatisfyFunctional
bool trySatisfyFunctional(PacketPtr pkt)
Definition: queue.hh:186
gem5::Packet::pushLabel
void pushLabel(const std::string &lbl)
Push label for PrintReq (safe to call unconditionally).
Definition: packet.hh:1461
gem5::Packet::cmd
MemCmd cmd
The command field of the packet.
Definition: packet.hh:372
gem5::Packet::popLabel
void popLabel()
Pop label for PrintReq (safe to call unconditionally).
Definition: packet.hh:1471
gem5::BaseCache::Blocked_NoMSHRs
@ Blocked_NoMSHRs
Definition: base.hh:112
gem5::BaseCache::CpuSidePort::recvFunctional
virtual void recvFunctional(PacketPtr pkt) override
Receive a functional request packet from the peer.
Definition: base.cc:2581
gem5::Packet::needsResponse
bool needsResponse() const
Definition: packet.hh:608
gem5::Packet::writeData
void writeData(uint8_t *p) const
Copy data from the packet to the memory at the provided pointer.
Definition: packet.hh:1322
gem5::MSHR::wasWholeLineWrite
bool wasWholeLineWrite
Track if we sent this as a whole line write or not.
Definition: mshr.hh:124
gem5::Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
gem5::Packet::isError
bool isError() const
Definition: packet.hh:622
gem5::Packet::isLockedRMW
bool isLockedRMW() const
Definition: packet.hh:621
gem5::Packet::senderState
SenderState * senderState
This packet's sender state.
Definition: packet.hh:545
gem5::BaseCache::doWritebacksAtomic
virtual void doWritebacksAtomic(PacketList &writebacks)=0
Send writebacks down the memory hierarchy in atomic mode.
gem5::prefetch::Base::pfHitInWB
void pfHitInWB()
Definition: base.hh:414
name
const std::string & name()
Definition: trace.cc:48
gem5::prefetch::Base::pfHitInCache
void pfHitInCache()
Definition: base.hh:402
SERIALIZE_SCALAR
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:568
gem5::BaseCache::tempBlockWriteback
PacketPtr tempBlockWriteback
Writebacks from the tempBlock, resulting on the response path in atomic mode, must happen after the c...
Definition: base.hh:680
gem5::CacheBlk::DirtyBit
@ DirtyBit
dirty (modified)
Definition: cache_blk.hh:87
gem5::statistics::Group::regStats
virtual void regStats()
Callback to set stat parameters.
Definition: group.cc:68
gem5::ClockedObject
The ClockedObject class extends the SimObject with a clock and accessor functions to relate ticks to ...
Definition: clocked_object.hh:234
gem5::Clocked::clockEdge
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...
Definition: clocked_object.hh:177
gem5::BaseCache::recvTimingReq
virtual void recvTimingReq(PacketPtr pkt)
Performs the access specified by the request.
Definition: base.cc:404
gem5::ResponsePort::sendRangeChange
void sendRangeChange() const
Called by the owner to send a range change.
Definition: port.hh:364
gem5::MSHRQueue::markPending
void markPending(MSHR *mshr)
Mark an in service entry as pending, used to resend a request.
Definition: mshr_queue.cc:123
gem5::BaseCache::MemSidePort::recvTimingSnoopReq
virtual void recvTimingSnoopReq(PacketPtr pkt)
Receive a timing snoop request from the peer.
Definition: base.cc:2622
gem5::EventManager::deschedule
void deschedule(Event &event)
Definition: eventq.hh:1021
gem5::prefetch::Base::nextPrefetchReadyTime
virtual Tick nextPrefetchReadyTime() const =0
gem5::Packet::popSenderState
SenderState * popSenderState()
Pop the top of the state stack and return a pointer to it.
Definition: packet.cc:342
gem5::MemCmd::InvalidateResp
@ InvalidateResp
Definition: packet.hh:145
gem5::Cache
A coherent cache that can be arranged in flexible topologies.
Definition: cache.hh:67
gem5::BaseCache::MemSidePort::recvAtomicSnoop
virtual Tick recvAtomicSnoop(PacketPtr pkt)
Receive an atomic snoop request packet from our peer.
Definition: base.cc:2632
gem5::WriteQueueEntry
Write queue entry.
Definition: write_queue_entry.hh:67
gem5::BaseCache::schedMemSideSendEvent
void schedMemSideSendEvent(Tick time)
Schedule a send event for the memory-side port.
Definition: base.hh:1270
gem5::ProbePointArg
ProbePointArg generates a point for the class of Arg.
Definition: thermal_domain.hh:54
gem5::CacheBlk::data
uint8_t * data
Contains a copy of the data in this block for easy access.
Definition: cache_blk.hh:103
gem5::BaseCache::maintainClusivity
void maintainClusivity(bool from_cache, CacheBlk *blk)
Maintain the clusivity of this cache by potentially invalidating a block.
Definition: base.cc:1499
gem5::CacheBlk::getWhenReady
Tick getWhenReady() const
Get tick at which block's data will be available for access.
Definition: cache_blk.hh:265
gem5::MSHRQueue::deallocate
void deallocate(MSHR *mshr) override
Deallocate a MSHR and its targets.
Definition: mshr_queue.cc:83
gem5::Packet::isClean
bool isClean() const
Definition: packet.hh:611
gem5::BaseCache::isReadOnly
const bool isReadOnly
Is this cache read only, for example the instruction cache, or table-walker cache.
Definition: base.hh:939
gem5::BaseCache::CacheReqPacketQueue::sendDeferredPacket
virtual void sendDeferredPacket()
Override the normal sendDeferredPacket and do not only consider the transmit list (used for responses...
Definition: base.cc:2653
gem5::Packet::setHasSharers
void setHasSharers()
On fills, the hasSharers flag is used by the caches in combination with the cacheResponding flag,...
Definition: packet.hh:685
gem5::BaseCache::noTargetMSHR
MSHR * noTargetMSHR
Pointer to the MSHR that has no targets.
Definition: base.hh:970
gem5::SimObject::getProbeManager
ProbeManager * getProbeManager()
Get the probe manager for this object.
Definition: sim_object.cc:117
gem5::BaseCache::clusivity
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:931
warn_if
#define warn_if(cond,...)
Conditional warning macro that checks the supplied condition and only prints a warning if the conditi...
Definition: logging.hh:283
super_blk.hh
Copyright (c) 2018 Inria All rights reserved.
panic_if
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:214
gem5::BaseTags::insertBlock
virtual void insertBlock(const PacketPtr pkt, CacheBlk *blk)
Insert the new block into the cache and update stats.
Definition: base.cc:102
gem5::BaseCache::memInvalidate
virtual void memInvalidate() override
Invalidates all blocks in the cache.
Definition: base.cc:1795
gem5::BaseCache::CacheCmdStats::CacheCmdStats
CacheCmdStats(BaseCache &c, const std::string &name)
Definition: base.cc:2026
gem5::Packet::makeTimingResponse
void makeTimingResponse()
Definition: packet.hh:1080
gem5::BaseTags::anyBlk
virtual bool anyBlk(std::function< bool(CacheBlk &)> visitor)=0
Find if any of the blocks satisfies a condition.
gem5::BaseCache::regProbePoints
void regProbePoints() override
Registers probes.
Definition: base.cc:2508
gem5::Packet::allocate
void allocate()
Allocate memory for the packet.
Definition: packet.hh:1367
gem5::Port
Ports are used to interface objects to each other.
Definition: port.hh:61
gem5::BaseCache::isDirty
bool isDirty() const
Determine if there are any dirty blocks in the cache.
Definition: base.cc:1801
gem5::BaseCache::CacheStats::cmdStats
CacheCmdStats & cmdStats(const PacketPtr p)
Definition: base.hh:1044
gem5::CompressionBlk
A superblock is composed of sub-blocks, and each sub-block has information regarding its superblock a...
Definition: super_blk.hh:51
gem5::BaseCache::allocateBlock
CacheBlk * allocateBlock(const PacketPtr pkt, PacketList &writebacks)
Allocate a new block and perform any necessary writebacks.
Definition: base.cc:1607
gem5::BaseCache::CacheStats::dataContractions
statistics::Scalar dataContractions
Number of data contractions (blocks that had their compression factor improved).
Definition: base.hh:1139
gem5::compression::Base::compress
virtual std::unique_ptr< CompressionData > compress(const std::vector< Chunk > &chunks, Cycles &comp_lat, Cycles &decomp_lat)=0
Apply the compression process to the cache line.
gem5::MSHR::getNumTargets
int getNumTargets() const
Returns the current number of allocated targets.
Definition: mshr.hh:446
gem5::Packet::writeDataToBlock
void writeDataToBlock(uint8_t *blk_data, int blkSize) const
Copy data from the packet to the provided block pointer, which is aligned to the given block size.
Definition: packet.hh:1346
gem5::MSHR::isCleaning
bool isCleaning() const
Definition: mshr.hh:321
gem5::BaseCache::fillLatency
const Cycles fillLatency
The latency to fill a cache block.
Definition: base.hh:906
gem5::Packet::makeResponse
void makeResponse()
Take a request packet and modify it in place to be suitable for returning as a response to that reque...
Definition: packet.hh:1062
gem5::BaseCache::handleTimingReqHit
virtual void handleTimingReqHit(PacketPtr pkt, CacheBlk *blk, Tick request_time)
Definition: base.cc:225
gem5::BaseCache::evictBlock
virtual PacketPtr evictBlock(CacheBlk *blk)=0
Evict a cache block.
gem5::Clocked::tick
Tick tick
Definition: clocked_object.hh:68
gem5::BaseCache::addrRanges
const AddrRangeList addrRanges
The address range to which the cache responds on the CPU side.
Definition: base.hh:978
gem5::BaseCache::system
System * system
System we are currently operating in.
Definition: base.hh:982
gem5::WriteAllocator::delay
bool delay(Addr blk_addr)
Access whether we need to delay the current write.
Definition: base.hh:1423
gem5::BaseCache::mshrQueue
MSHRQueue mshrQueue
Miss status registers.
Definition: base.hh:340
gem5::BaseCache::memSidePort
MemSidePort memSidePort
Definition: base.hh:335
gem5::CacheBlk::wasPrefetched
bool wasPrefetched() const
Check if this block was the result of a hardware prefetch, yet to be touched.
Definition: cache_blk.hh:249
gem5::Request::SECURE
@ SECURE
The request targets the secure memory space.
Definition: request.hh:186
gem5::BaseCache::handleUncacheableWriteResp
void handleUncacheableWriteResp(PacketPtr pkt)
Handling the special case of uncacheable write responses to make recvTimingResp less cluttered.
Definition: base.cc:477
gem5::BaseCache::writebackClean
const bool writebackClean
Determine if clean lines should be written back or not.
Definition: base.hh:671
gem5::QueuedResponsePort::trySatisfyFunctional
bool trySatisfyFunctional(PacketPtr pkt)
Check the list of buffered packets against the supplied functional request.
Definition: qport.hh:99
gem5::MemCmd::WriteReq
@ WriteReq
Definition: packet.hh:90
gem5::CompressionBlk::checkExpansionContraction
OverwriteType checkExpansionContraction(const std::size_t size) const
Determines if changing the size of the block will cause a data expansion (new size is bigger) or cont...
Definition: super_blk.cc:148
gem5::CacheBlk::trackLoadLocked
void trackLoadLocked(PacketPtr pkt)
Track the fact that a local locked was issued to the block.
Definition: cache_blk.hh:327
gem5::TaggedEntry::isSecure
bool isSecure() const
Check if this block holds data from the secure memory space.
Definition: tagged_entry.hh:64
gem5::CacheBlk::isSet
bool isSet(unsigned bits) const
Checks the given coherence bits are set.
Definition: cache_blk.hh:239
gem5::MSHR::promoteReadable
void promoteReadable()
Promotes deferred targets that do not require writable.
Definition: mshr.cc:659
gem5::BaseCache::CacheCmdStats::mshrUncacheableLatency
statistics::Vector mshrUncacheableLatency
Total tick latency of each MSHR miss, per command and thread.
Definition: base.hh:1029
logging.hh
gem5::QueueEntry
A queue entry base class, to be used by both the MSHRs and write-queue entries.
Definition: queue_entry.hh:62
gem5::statistics::Group
Statistics container.
Definition: group.hh:92
gem5::BaseCache::CacheResponsePort::blocked
bool blocked
Definition: base.hh:296
gem5::TempCacheBlk::insert
void insert(const Addr addr, const bool is_secure) override
Insert the block by assigning it a tag and marking it valid.
Definition: cache_blk.hh:531
gem5::BaseCache::invalidateVisitor
void invalidateVisitor(CacheBlk &blk)
Cache block visitor that invalidates all blocks in the cache.
Definition: base.cc:1837
gem5::Packet::fromCache
bool fromCache() const
Definition: packet.hh:612
gem5::BaseCache::writebackTempBlockAtomic
void writebackTempBlockAtomic()
Send the outstanding tempBlock writeback.
Definition: base.hh:687
gem5::BaseCache::getNextQueueEntry
QueueEntry * getNextQueueEntry()
Return the next queue entry to service, either a pending miss from the MSHR queue,...
Definition: base.cc:850
gem5::Packet::trySatisfyFunctional
bool trySatisfyFunctional(PacketPtr other)
Check a functional request against a memory value stored in another packet (i.e.
Definition: packet.hh:1399
gem5::QueuedRequestPort::trySatisfyFunctional
bool trySatisfyFunctional(PacketPtr pkt)
Check the list of buffered packets against the supplied functional request.
Definition: qport.hh:164
gem5::BaseCache::serviceMSHRTargets
virtual void serviceMSHRTargets(MSHR *mshr, const PacketPtr pkt, CacheBlk *blk)=0
Service non-deferred MSHR targets using the received response.
gem5::BaseCache::lookupLatency
const Cycles lookupLatency
The latency of tag lookup of a cache.
Definition: base.hh:890
SUM_DEMAND
#define SUM_DEMAND(s)
gem5::WriteQueueEntry::getNumTargets
int getNumTargets() const
Returns the current number of allocated targets.
Definition: write_queue_entry.hh:142
gem5::prefetch::Base::incrDemandMhsrMisses
void incrDemandMhsrMisses()
Definition: base.hh:396
gem5::CheckpointOut
std::ostream CheckpointOut
Definition: serialize.hh:66
gem5::BaseCache::allocateMissBuffer
MSHR * allocateMissBuffer(PacketPtr pkt, Tick time, bool sched_send=true)
Definition: base.hh:1169
gem5::WriteAllocator::coalesce
bool coalesce() const
Should writes be coalesced? This is true if the mode is set to NO_ALLOCATE.
Definition: base.hh:1392
gem5::CacheBlkPrintWrapper
Simple class to provide virtual print() method on cache blocks without allocating a vtable pointer fo...
Definition: cache_blk.hh:554
gem5::CompressionBlk::DATA_CONTRACTION
@ DATA_CONTRACTION
New data contents are considered smaller than previous contents.
Definition: super_blk.hh:77
gem5::BaseTags::findBlock
virtual CacheBlk * findBlock(Addr addr, bool is_secure) const
Finds the block in the cache without touching it.
Definition: base.cc:80
gem5::Packet::isExpressSnoop
bool isExpressSnoop() const
Definition: packet.hh:702
gem5::BaseCache::doWritebacks
virtual void doWritebacks(PacketList &writebacks, Tick forward_time)=0
Insert writebacks into the write buffer.
gem5::BaseCache::setBlocked
void setBlocked(BlockedCause cause)
Marks the access path of the cache as blocked for the given cause.
Definition: base.hh:1232
gem5::BaseTags::invalidate
virtual void invalidate(CacheBlk *blk)
This function updates the tags when a block is invalidated.
Definition: base.hh:254
gem5::MSHR::hasLockedRMWReadTarget
bool hasLockedRMWReadTarget()
Determine if there are any LockedRMWReads in the Targets list.
Definition: mshr.cc:794
gem5_assert
#define gem5_assert(cond,...)
The assert macro will function like a normal assert, but will use panic instead of straight abort().
Definition: logging.hh:317
gem5::Clocked::ticksToCycles
Cycles ticksToCycles(Tick t) const
Definition: clocked_object.hh:222
std::list
STL list class.
Definition: stl.hh:51
gem5::Packet::getAddr
Addr getAddr() const
Definition: packet.hh:807
gem5::BaseCache::writebackVisitor
void writebackVisitor(CacheBlk &blk)
Cache block visitor that writes back dirty cache blocks using functional writes.
Definition: base.cc:1814
gem5::BaseCache::CacheCmdStats
Definition: base.hh:984
gem5::BaseCache::numTarget
const int numTarget
The number of targets for each MSHR.
Definition: base.hh:921
gem5::BaseCache::createMissPacket
virtual PacketPtr createMissPacket(PacketPtr cpu_pkt, CacheBlk *blk, bool needs_writable, bool is_whole_line_write) const =0
Create an appropriate downstream bus request packet.
gem5::BaseTags::extractBlkOffset
int extractBlkOffset(Addr addr) const
Calculate the block offset of an address.
Definition: base.hh:225
gem5::CompressionBlk::OverwriteType
OverwriteType
When an overwrite happens, the data size may change an not fit in its current container any longer.
Definition: super_blk.hh:74
gem5::CompressionBlk::setDecompressionLatency
void setDecompressionLatency(const Cycles lat)
Set number of cycles needed to decompress this block.
Definition: super_blk.cc:135
gem5::QueuedResponsePort::schedTimingResp
void schedTimingResp(PacketPtr pkt, Tick when)
Schedule the sending of a timing response.
Definition: qport.hh:94
gem5::compression::Base::setDecompressionLatency
static void setDecompressionLatency(CacheBlk *blk, const Cycles lat)
Set the decompression latency of compressed block.
Definition: base.cc:214
fatal_if
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition: logging.hh:236
gem5::BaseCache::functionalAccess
virtual void functionalAccess(PacketPtr pkt, bool from_cpu_side)
Performs the access specified by the request.
Definition: base.cc:715
gem5::prefetch::Base::getPacket
virtual PacketPtr getPacket()=0
gem5::BaseCache::CacheResponsePort::sendRetryEvent
EventFunctionWrapper sendRetryEvent
Definition: base.hh:304
gem5::BaseCache::handleEvictions
bool handleEvictions(std::vector< CacheBlk * > &evict_blks, PacketList &writebacks)
Try to evict the given blocks.
Definition: base.cc:941
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: gpu_translation_state.hh:37
gem5::QueueEntry::sendPacket
virtual bool sendPacket(BaseCache &cache)=0
Send this queue entry as a downstream packet, with the exact behaviour depending on the specific entr...
gem5::statistics::total
const FlagsType total
Print the total.
Definition: info.hh:59
gem5::BaseCache::forwardLatency
const Cycles forwardLatency
This is the forward latency of the cache.
Definition: base.hh:903
gem5::BaseTags::forEachBlk
void forEachBlk(std::function< void(CacheBlk &)> visitor)
Visit each block in the tags and apply a visitor.
Definition: base.cc:219
gem5::BaseCache::nextQueueReadyTime
Tick nextQueueReadyTime() const
Find next request ready time from among possible sources.
Definition: base.cc:1850
gem5::MSHR::getTarget
QueueEntry::Target * getTarget() override
Returns a reference to the first target.
Definition: mshr.hh:473
gem5::BaseCache::CpuSidePort::getAddrRanges
virtual AddrRangeList getAddrRanges() const override
Get a list of the non-overlapping address ranges the owner is responsible for.
Definition: base.cc:2595
gem5::QueueEntry::inService
bool inService
True if the entry has been sent downstream.
Definition: queue_entry.hh:110
gem5::BaseCache::CpuSidePort::recvAtomic
virtual Tick recvAtomic(PacketPtr pkt) override
Receive an atomic request packet from the peer.
Definition: base.cc:2570
gem5::Packet::isResponse
bool isResponse() const
Definition: packet.hh:598
gem5::BaseTags::findVictim
virtual CacheBlk * findVictim(Addr addr, const bool is_secure, const std::size_t size, std::vector< CacheBlk * > &evict_blks)=0
Find replacement victim based on address.
gem5::BaseCache::handleFill
CacheBlk * handleFill(PacketPtr pkt, CacheBlk *blk, PacketList &writebacks, bool allocate)
Handle a fill operation caused by a received packet.
Definition: base.cc:1511
gem5::Packet::getSize
unsigned getSize() const
Definition: packet.hh:817
gem5::Named::_name
const std::string _name
Definition: named.hh:41
gem5::BaseCache::CacheStats::CacheStats
CacheStats(BaseCache &c)
Definition: base.cc:2199
gem5::Queue::findPending
Entry * findPending(const QueueEntry *entry) const
Find any pending requests that overlap the given request of a different queue.
Definition: queue.hh:207
gem5::BaseCache::calculateAccessLatency
Cycles calculateAccessLatency(const CacheBlk *blk, const uint32_t delay, const Cycles lookup_lat) const
Calculate access latency in ticks given a tag lookup latency, and whether access was a hit or miss.
Definition: base.cc:1196
gem5::Packet::hasRespData
bool hasRespData() const
Definition: packet.hh:615
gem5::QueueEntry::getTarget
virtual Target * getTarget()=0
Returns a pointer to the first target.
gem5::Event::scheduled
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:458
gem5::BaseCache::writebackBlk
PacketPtr writebackBlk(CacheBlk *blk)
Create a writeback request for the given block.
Definition: base.cc:1693
gem5::BaseCache::CpuSidePort::tryTiming
virtual bool tryTiming(PacketPtr pkt) override
Availability request from the peer.
Definition: base.cc:2537
gem5::TaggedEntry::isValid
virtual bool isValid() const
Checks if the entry is valid.
Definition: tagged_entry.hh:57
gem5::WriteAllocator::resetDelay
void resetDelay(Addr blk_addr)
Clear delay counter for the input block.
Definition: base.hh:1437
gem5::Packet::isEviction
bool isEviction() const
Definition: packet.hh:610
gem5::Packet::isInvalidate
bool isInvalidate() const
Definition: packet.hh:609
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:188
gem5::BaseCache::satisfyRequest
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:1089
gem5::MemCmd::HardPFResp
@ HardPFResp
Definition: packet.hh:101
gem5::Clocked::clockPeriod
Tick clockPeriod() const
Definition: clocked_object.hh:217
gem5::MemCmd::LockedRMWWriteResp
@ LockedRMWWriteResp
Definition: packet.hh:119
gem5::ArmISA::mode
Bitfield< 4, 0 > mode
Definition: misc_types.hh:74
gem5::X86ISA::addr
Bitfield< 3 > addr
Definition: types.hh:84
gem5::Packet::isDemand
bool isDemand() const
Definition: packet.hh:595
gem5::CacheBlk::ReadableBit
@ ReadableBit
Read permission.
Definition: cache_blk.hh:85
gem5::BaseCache::responseLatency
const Cycles responseLatency
The latency of sending reponse to its upper level cache/core on a linefill.
Definition: base.hh:913
gem5::BaseCache::compressor
compression::Base * compressor
Compression method being used.
Definition: base.hh:349

Generated on Sun Jul 30 2023 01:56:52 for gem5 by doxygen 1.8.17