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

Generated on Mon Oct 27 2025 04:13:00 for gem5 by doxygen 1.14.0