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