gem5 [DEVELOP-FOR-25.1]
Loading...
Searching...
No Matches
fetch.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010-2014, 2025 Arm Limited
3 * Copyright (c) 2012-2013 AMD
4 * Copyright (c) 2022-2023 The University of Edinburgh
5 * All rights reserved.
6 *
7 * The license below extends only to copyright in the software and shall
8 * not be construed as granting a license to any other intellectual
9 * property including but not limited to intellectual property relating
10 * to a hardware implementation of the functionality of the software
11 * licensed hereunder. You may use the software subject to the license
12 * terms below provided that you ensure that this notice is replicated
13 * unmodified and in its entirety in all distributions of the software,
14 * modified or unmodified, in source code or in binary form.
15 *
16 * Copyright (c) 2004-2006 The Regents of The University of Michigan
17 * All rights reserved.
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions are
21 * met: redistributions of source code must retain the above copyright
22 * notice, this list of conditions and the following disclaimer;
23 * redistributions in binary form must reproduce the above copyright
24 * notice, this list of conditions and the following disclaimer in the
25 * documentation and/or other materials provided with the distribution;
26 * neither the name of the copyright holders nor the names of its
27 * contributors may be used to endorse or promote products derived from
28 * this software without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
34 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
36 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
40 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 */
42
43#include "cpu/o3/fetch.hh"
44
45#include <algorithm>
46#include <cstring>
47#include <list>
48#include <map>
49#include <queue>
50
51#include "arch/generic/tlb.hh"
52#include "base/types.hh"
53#include "cpu/base.hh"
54#include "cpu/exetrace.hh"
56#include "cpu/o3/cpu.hh"
57#include "cpu/o3/dyn_inst.hh"
58#include "cpu/o3/limits.hh"
59#include "debug/Activity.hh"
60#include "debug/Drain.hh"
61#include "debug/Fetch.hh"
62#include "debug/O3CPU.hh"
63#include "mem/packet.hh"
64#include "params/BaseO3CPU.hh"
65#include "sim/byteswap.hh"
66#include "sim/core.hh"
67#include "sim/eventq.hh"
68#include "sim/full_system.hh"
69#include "sim/system.hh"
70
71namespace gem5
72{
73
74namespace o3
75{
76
78 RequestPort(_cpu->name() + ".icache_port"), fetch(_fetch)
79{}
80
81Fetch::Fetch(CPU *_cpu, const BaseO3CPUParams &params)
82 : fetchPolicy(params.smtFetchPolicy),
83 cpu(_cpu),
84 bac(nullptr),
85 ftq(nullptr),
91 fetchWidth(params.fetchWidth),
93 retryPkt(NULL),
95 cacheBlkSize(cpu->cacheLineSize()),
99 numThreads(params.numThreads),
100 numFetchingThreads(params.smtNumFetchingThreads),
101 icachePort(this, _cpu),
105 fetchStats(_cpu, this)
106{
108 fatal("numThreads (%d) is larger than compiled limit (%d),\n"
109 "\tincrease MaxThreads in src/cpu/o3/limits.hh\n",
110 numThreads, static_cast<int>(MaxThreads));
111 if (fetchWidth > MaxWidth)
112 fatal("fetchWidth (%d) is larger than compiled limit (%d),\n"
113 "\tincrease MaxWidth in src/cpu/o3/limits.hh\n",
114 fetchWidth, static_cast<int>(MaxWidth));
116 fatal("fetch buffer size (%u bytes) is greater than the cache "
117 "block size (%u bytes)\n", fetchBufferSize, cacheBlkSize);
119 fatal("cache block (%u bytes) is not a multiple of the "
120 "fetch buffer (%u bytes)\n", cacheBlkSize, fetchBufferSize);
121 if (decoupledFrontEnd && (numThreads > 1)) {
122 fatal("Decoupled front-end was not tested with multiple threads.");
123 }
124
125 for (int i = 0; i < MaxThreads; i++) {
126 fetchStatus[i] = Idle;
127 decoder[i] = nullptr;
128 pc[i].reset(params.isa[0]->newPCState());
129 fetchOffset[i] = 0;
130 macroop[i] = nullptr;
131 delayedCommit[i] = false;
132 memReq[i] = nullptr;
133 stalls[i] = {false, false};
134 fetchBuffer[i] = NULL;
135 fetchBufferPC[i] = 0;
136 fetchBufferValid[i] = false;
137 lastIcacheStall[i] = 0;
138 issuePipelinedIfetch[i] = false;
139 }
140
141 for (ThreadID tid = 0; tid < numThreads; tid++) {
142 decoder[tid] = params.decoder[tid];
143 // Create space to buffer the cache line data,
144 // which may not hold the entire cache line.
145 fetchBuffer[tid] = new uint8_t[fetchBufferSize];
146 }
147
148 // Get the size of an instruction.
149 instSize = decoder[0]->moreBytesSize();
150}
151
152std::string Fetch::name() const { return cpu->name() + ".fetch"; }
153
154void
156{
157 ppFetch = new ProbePointArg<DynInstPtr>(cpu->getProbeManager(), "Fetch");
158 ppFetchRequestSent = new ProbePointArg<RequestPtr>(cpu->getProbeManager(),
159 "FetchRequest");
160
161}
162
164 : statistics::Group(cpu, "fetch"),
166 "Number of branches that fetch has predicted taken"),
167 ADD_STAT(cycles, statistics::units::Cycle::get(),
168 "Number of cycles fetch has run and was not squashing or "
169 "blocked"),
170 ADD_STAT(squashCycles, statistics::units::Cycle::get(),
171 "Number of cycles fetch has spent squashing"),
172 ADD_STAT(tlbCycles, statistics::units::Cycle::get(),
173 "Number of cycles fetch has spent waiting for tlb"),
174 ADD_STAT(ftqStallCycles, statistics::units::Cycle::get(),
175 "Number of cycles fetch has spent waiting for FTQ to fill."),
176 ADD_STAT(idleCycles, statistics::units::Cycle::get(),
177 "Number of cycles fetch was idle"),
178 ADD_STAT(blockedCycles, statistics::units::Cycle::get(),
179 "Number of cycles fetch has spent blocked"),
180 ADD_STAT(
181 miscStallCycles, statistics::units::Cycle::get(),
182 "Number of cycles fetch has spent waiting on interrupts, or bad "
183 "addresses, or out of MSHRs"),
185 "Number of cycles fetch has spent waiting on pipes to drain"),
187 "Number of stall cycles due to no active thread to fetch from"),
189 "Number of stall cycles due to pending traps"),
191 "Number of stall cycles due to pending quiesce instructions"),
193 "Number of stall cycles due to full MSHR"),
194 ADD_STAT(cacheLines, statistics::units::Count::get(),
195 "Number of cache lines fetched"),
196 ADD_STAT(icacheSquashes, statistics::units::Count::get(),
197 "Number of outstanding Icache misses that were squashed"),
198 ADD_STAT(tlbSquashes, statistics::units::Count::get(),
199 "Number of outstanding ITLB misses that were squashed"),
200 ADD_STAT(nisnDist, statistics::units::Count::get(),
201 "Number of instructions fetched each cycle (Total)"),
202 ADD_STAT(idleRate, statistics::units::Ratio::get(),
203 "Ratio of cycles fetch was idle",
204 idleCycles / cpu->baseStats.numCycles),
205 ADD_STAT(ftNumber, statistics::units::Count::get(),
206 "Number of fetch targets processed each cycle (Total)")
207{
209 .prereq(predictedBranches);
210 cycles
211 .prereq(cycles);
213 .prereq(squashCycles);
215 .prereq(tlbCycles);
218 .prereq(idleCycles);
220 .prereq(blockedCycles);
222 .prereq(cacheLines);
224 .prereq(miscStallCycles);
226 .prereq(pendingDrainCycles);
230 .prereq(pendingTrapStallCycles);
236 .prereq(icacheSquashes);
238 .prereq(tlbSquashes);
239 ftNumber.init(0, fetch->maxFTPerCycle, 1);
241 .init(/* base value */ 0,
242 /* last value */ fetch->fetchWidth,
243 /* bucket size */ 1)
244 .flags(statistics::pdf);
246 .prereq(idleRate);
247}
248void
250{
251 timeBuffer = time_buffer;
252
253 // Create wires to get information from proper places in time buffer.
258
259 // Create a wire to send information to BAC. There is no delay between
260 // the BAC and fetch stage as the BAC stage does the PC updated
261 // functionality and holds the branch predictor.
262 toBAC = timeBuffer->getWire(0);
263}
264
265void
270
271void
272Fetch::setBACandFTQPtr(BAC *bac_ptr, FTQ *ftq_ptr)
273{
274 // Set pointer to the fetch target queue
275 bac = bac_ptr;
276 ftq = ftq_ptr;
277}
278
279void
281{
282 // Create wire to write information to proper place in fetch time buf.
283 toDecode = ftb_ptr->getWire(0);
284}
285
286void
288{
289 assert(bac != nullptr);
290 assert(ftq != nullptr);
291 assert(priorityList.empty());
292 resetStage();
293
294 // Fetch needs to start fetching instructions at the very beginning,
295 // so it must start up in active state.
297}
298
299void
301{
302 fetchStatus[tid] = Running;
303 set(pc[tid], cpu->pcState(tid));
304 fetchOffset[tid] = 0;
305 macroop[tid] = NULL;
306 delayedCommit[tid] = false;
307 memReq[tid] = NULL;
308 stalls[tid].decode = false;
309 stalls[tid].drain = false;
310 fetchBufferPC[tid] = 0;
311 fetchBufferValid[tid] = false;
312 fetchQueue[tid].clear();
313
314 // TODO not sure what to do with priorityList for now
315 // priorityList.push_back(tid);
316
317 // Clear out any of this thread's instructions being sent to decode.
318 for (int i = -cpu->fetchQueue.getPast();
319 i <= cpu->fetchQueue.getFuture(); ++i) {
320 FetchStruct& fetch_struct = cpu->fetchQueue[i];
321 removeCommThreadInsts(tid, fetch_struct);
322 }
323}
324
325void
327{
328 numInst = 0;
329 interruptPending = false;
330 cacheBlocked = false;
331
332 priorityList.clear();
333
334 // Setup PC and nextPC with initial state.
335 for (ThreadID tid = 0; tid < numThreads; ++tid) {
336 fetchStatus[tid] = Running;
337 set(pc[tid], cpu->pcState(tid));
338 fetchOffset[tid] = 0;
339 macroop[tid] = NULL;
340
341 delayedCommit[tid] = false;
342 memReq[tid] = NULL;
343
344 stalls[tid].decode = false;
345 stalls[tid].drain = false;
346
347 fetchBufferPC[tid] = 0;
348 fetchBufferValid[tid] = false;
349
350 fetchQueue[tid].clear();
351
352 priorityList.push_back(tid);
353 }
354
355 wroteToTimeBuffer = false;
357}
358
359void
361{
362 ThreadID tid = cpu->contextToThread(pkt->req->contextId());
363
364 DPRINTF(Fetch, "[tid:%i] Waking up from cache miss.\n", tid);
365 assert(!cpu->switchedOut());
366
367 // Only change the status if it's still waiting on the icache access
368 // to return.
369 if (fetchStatus[tid] != IcacheWaitResponse ||
370 pkt->req != memReq[tid]) {
371 ++fetchStats.icacheSquashes;
372 delete pkt;
373 return;
374 }
375
376 memcpy(fetchBuffer[tid], pkt->getConstPtr<uint8_t>(), fetchBufferSize);
377 fetchBufferValid[tid] = true;
378
379 // Wake up the CPU (if it went to sleep and was waiting on
380 // this completion event).
381 cpu->wakeCPU();
382
383 DPRINTF(Activity, "[tid:%i] Activating fetch due to cache completion\n",
384 tid);
385
387
388 // Only switch to IcacheAccessComplete if we're not stalled as well.
389 if (checkStall(tid)) {
390 fetchStatus[tid] = Blocked;
391 } else {
393 }
394
395 pkt->req->setAccessLatency();
396 cpu->ppInstAccessComplete->notify(pkt);
397 // Reset the mem req to NULL.
398 delete pkt;
399 memReq[tid] = NULL;
400}
401
402void
404{
405 for (ThreadID i = 0; i < numThreads; ++i) {
406 stalls[i].decode = false;
407 stalls[i].drain = false;
408 }
409}
410
411void
413{
414 assert(isDrained());
415 assert(retryPkt == NULL);
416 assert(retryTid == InvalidThreadID);
417 assert(!cacheBlocked);
418 assert(!interruptPending);
419
420 for (ThreadID i = 0; i < numThreads; ++i) {
421 assert(!memReq[i]);
422 assert(fetchStatus[i] == Idle || stalls[i].drain);
423 }
424}
425
426bool
428{
429 /* Make sure that threads are either idle of that the commit stage
430 * has signaled that draining has completed by setting the drain
431 * stall flag. This effectively forces the pipeline to be disabled
432 * until the whole system is drained (simulation may continue to
433 * drain other components).
434 */
435 for (ThreadID i = 0; i < numThreads; ++i) {
436 // Verify fetch queues are drained
437 if (!fetchQueue[i].empty())
438 return false;
439
440 // Return false if not idle or drain stalled
441 if (fetchStatus[i] != Idle) {
442 if (fetchStatus[i] == Blocked && stalls[i].drain)
443 continue;
444 else
445 return false;
446 }
447 }
448
449 /* The pipeline might start up again in the middle of the drain
450 * cycle if the finish translation event is scheduled, so make
451 * sure that's not the case.
452 */
453 return !finishTranslationEvent.scheduled();
454}
455
456void
458{
459 assert(cpu->getInstPort().isConnected());
460 resetStage();
461
462}
463
464void
466{
467 assert(cpu->isDraining());
468 assert(!stalls[tid].drain);
469 DPRINTF(Drain, "%i: Thread drained.\n", tid);
470 stalls[tid].drain = true;
471}
472
473void
475{
476 DPRINTF(Fetch, "Waking up from quiesce\n");
477 // Hopefully this is safe
478 // @todo: Allow other threads to wake from quiesce.
479 fetchStatus[0] = Running;
480}
481
482void
484{
485 if (_status == Inactive) {
486 DPRINTF(Activity, "Activating stage.\n");
487
488 cpu->activateStage(CPU::FetchIdx);
489
490 _status = Active;
491 }
492}
493
494void
496{
497 if (_status == Active) {
498 DPRINTF(Activity, "Deactivating stage.\n");
499
500 cpu->deactivateStage(CPU::FetchIdx);
501
503 }
504}
505
506void
508{
509 // Update priority list
510 auto thread_it = std::find(priorityList.begin(), priorityList.end(), tid);
511 if (thread_it != priorityList.end()) {
512 priorityList.erase(thread_it);
513 }
514}
515
516bool
517Fetch::ftqReady(ThreadID tid, bool &status_change)
518{
519 if (!decoupledFrontEnd) {
520 return true;
521 }
522 // If the FTQ is empty, wait until it is available.
523 // Need at least two cycles for now.
524 if (!ftq->isHeadReady(tid)) {
525 fetchStatus[tid] = FTQEmpty;
526 status_change = true;
527 return false;
528 }
529 return true;
530}
531
532bool
534{
535 Fault fault = NoFault;
536
537 assert(!cpu->switchedOut());
538
539 // @todo: not sure if these should block translation.
540 //AlphaDep
541 if (cacheBlocked) {
542 DPRINTF(Fetch, "[tid:%i] Can't fetch cache line, cache blocked\n",
543 tid);
544 return false;
545 } else if (checkInterrupt(pc) && !delayedCommit[tid]) {
546 // Hold off fetch from getting new instructions when:
547 // Cache is blocked, or
548 // while an interrupt is pending and we're not in PAL mode, or
549 // fetch is switched out.
550 DPRINTF(Fetch, "[tid:%i] Can't fetch cache line, interrupt pending\n",
551 tid);
552 return false;
553 }
554
555 // Align the fetch address to the start of a fetch buffer segment.
556 Addr fetchBufferBlockPC = fetchBufferAlignPC(vaddr);
557
558 DPRINTF(Fetch, "[tid:%i] Fetching cache line %#x for addr %#x\n",
559 tid, fetchBufferBlockPC, vaddr);
560
561 // Setup the memReq to do a read of the first instruction's address.
562 // Set the appropriate read size and flags as well.
563 // Build request here.
564 RequestPtr mem_req = std::make_shared<Request>(
565 fetchBufferBlockPC, fetchBufferSize,
566 Request::INST_FETCH, cpu->instRequestorId(), pc,
567 cpu->thread[tid]->contextId());
568
569 mem_req->taskId(cpu->taskId());
570
571 memReq[tid] = mem_req;
572
573 // Initiate translation of the icache block
574 fetchStatus[tid] = ItlbWait;
575 FetchTranslation *trans = new FetchTranslation(this);
576 cpu->mmu->translateTiming(mem_req, cpu->thread[tid]->getTC(),
577 trans, BaseMMU::Execute);
578 return true;
579}
580
581void
582Fetch::finishTranslation(const Fault &fault, const RequestPtr &mem_req)
583{
584 ThreadID tid = cpu->contextToThread(mem_req->contextId());
585 Addr fetchBufferBlockPC = mem_req->getVaddr();
586
587 assert(!cpu->switchedOut());
588
589 // Wake up CPU if it was idle
590 cpu->wakeCPU();
591
592 if (fetchStatus[tid] != ItlbWait || mem_req != memReq[tid] ||
593 mem_req->getVaddr() != memReq[tid]->getVaddr()) {
594 DPRINTF(Fetch, "[tid:%i] Ignoring itlb completed after squash\n",
595 tid);
596 ++fetchStats.tlbSquashes;
597 return;
598 }
599
600
601 // If translation was successful, attempt to read the icache block.
602 if (fault == NoFault) {
603 // Check that we're not going off into random memory
604 // If we have, just wait around for commit to squash something and put
605 // us on the right track
606 if (!cpu->system->isMemAddr(mem_req->getPaddr())) {
607 warn("Address %#x is outside of physical memory, stopping fetch\n",
608 mem_req->getPaddr());
609 fetchStatus[tid] = NoGoodAddr;
610 memReq[tid] = NULL;
611 return;
612 }
613
614 // Build packet here.
615 PacketPtr data_pkt = new Packet(mem_req, MemCmd::ReadReq);
616 data_pkt->dataDynamic(new uint8_t[fetchBufferSize]);
617
618 fetchBufferPC[tid] = fetchBufferBlockPC;
619 fetchBufferValid[tid] = false;
620 DPRINTF(Fetch, "Fetch: Doing instruction read.\n");
621
622 fetchStats.cacheLines++;
623
624 // Access the cache.
625 if (!icachePort.sendTimingReq(data_pkt)) {
626 assert(retryPkt == NULL);
627 assert(retryTid == InvalidThreadID);
628 DPRINTF(Fetch, "[tid:%i] Out of MSHRs!\n", tid);
629
631 retryPkt = data_pkt;
632 retryTid = tid;
633 cacheBlocked = true;
634 } else {
635 DPRINTF(Fetch, "[tid:%i] Doing Icache access.\n", tid);
636 DPRINTF(Activity, "[tid:%i] Activity: Waiting on I-cache "
637 "response.\n", tid);
638 lastIcacheStall[tid] = curTick();
640 // Notify Fetch Request probe when a packet containing a fetch
641 // request is successfully sent
642 ppFetchRequestSent->notify(mem_req);
643 }
644 } else {
645 // Don't send an instruction to decode if we can't handle it.
646 if (!(numInst < fetchWidth) ||
647 !(fetchQueue[tid].size() < fetchQueueSize)) {
648 assert(!finishTranslationEvent.scheduled());
649 finishTranslationEvent.setFault(fault);
650 finishTranslationEvent.setReq(mem_req);
651 cpu->schedule(finishTranslationEvent,
652 cpu->clockEdge(Cycles(1)));
653 return;
654 }
656 "[tid:%i] Got back req with addr %#x but expected %#x\n",
657 tid, mem_req->getVaddr(), memReq[tid]->getVaddr());
658 // Translation faulted, icache request won't be sent.
659 memReq[tid] = NULL;
660
661 // Send the fault to commit. This thread will not do anything
662 // until commit handles the fault. The only other way it can
663 // wake up is if a squash comes along and changes the PC.
664 const PCStateBase &fetch_pc = *pc[tid];
665
666 DPRINTF(Fetch, "[tid:%i] Translation faulted, building noop.\n", tid);
667 // We will use a nop in order to carry the fault.
668 DynInstPtr instruction = buildInst(tid, nopStaticInstPtr, nullptr,
669 fetch_pc, fetch_pc, false);
670 instruction->setNotAnInst();
671
672 instruction->setPredTarg(fetch_pc);
673 instruction->fault = fault;
674 wroteToTimeBuffer = true;
675
676 DPRINTF(Activity, "Activity this cycle.\n");
677 cpu->activityThisCycle();
678
680
681 DPRINTF(Fetch, "[tid:%i] Blocked, need to handle the trap.\n", tid);
682 DPRINTF(Fetch, "[tid:%i] fault (%s) detected @ PC %s.\n",
683 tid, fault->name(), *pc[tid]);
684 }
686}
687
688void
689Fetch::squashFromDecode(const PCStateBase &new_pc, const DynInstPtr squashInst,
690 const InstSeqNum seq_num, ThreadID tid)
691{
692 DPRINTF(Fetch, "[tid:%i] Squashing from decode.\n", tid);
693
694 doSquash(new_pc, squashInst, tid);
695
696 // Tell the CPU to remove any instructions that are in flight between
697 // fetch and decode.
698 cpu->removeInstsUntil(seq_num, tid);
699}
700
701void
702Fetch::squashFromCommit(const PCStateBase &new_pc, const InstSeqNum seq_num,
703 DynInstPtr squashInst, ThreadID tid)
704{
705 DPRINTF(Fetch, "[tid:%i] Squash from commit.\n", tid);
706
707 doSquash(new_pc, squashInst, tid);
708
709 // Tell the CPU to remove any instructions that are not in the ROB.
710 cpu->removeInstsNotInROB(tid);
711}
712
713void
714Fetch::doSquash(const PCStateBase &new_pc, const DynInstPtr squashInst,
715 ThreadID tid)
716{
717 DPRINTF(Fetch, "[tid:%i] Squashing, setting PC to: %s.\n",
718 tid, new_pc);
719
720 set(pc[tid], new_pc);
721 fetchOffset[tid] = 0;
722 if (squashInst && squashInst->pcState().instAddr() == new_pc.instAddr() &&
723 !squashInst->isLastMicroop())
724 macroop[tid] = squashInst->macroop;
725 else
726 macroop[tid] = NULL;
727 decoder[tid]->reset();
728
729 // Clear the icache miss if it's outstanding.
730 if (fetchStatus[tid] == IcacheWaitResponse) {
731 DPRINTF(Fetch, "[tid:%i] Squashing outstanding Icache miss.\n",
732 tid);
733 memReq[tid] = NULL;
734 } else if (fetchStatus[tid] == ItlbWait) {
735 DPRINTF(Fetch, "[tid:%i] Squashing outstanding ITLB miss.\n",
736 tid);
737 memReq[tid] = NULL;
738 }
739
740 // Get rid of the retrying packet if it was from this thread.
741 if (retryTid == tid) {
742 assert(cacheBlocked);
743 if (retryPkt) {
744 delete retryPkt;
745 }
746 retryPkt = NULL;
748 }
749
750 fetchStatus[tid] = Squashing;
751
752 // Empty fetch queue
753 fetchQueue[tid].clear();
754
755 // microops are being squashed, it is not known wheather the
756 // youngest non-squashed microop was marked delayed commit
757 // or not. Setting the flag to true ensures that the
758 // interrupts are not handled when they cannot be, though
759 // some opportunities to handle interrupts may be missed.
760 delayedCommit[tid] = true;
761
762 ++fetchStats.squashCycles;
763}
764
765void
767{
768 DPRINTF(Fetch, "[tid:%i] Resteer BAC to PC: %s\n", tid, new_pc);
769
770 toBAC->fetchInfo[tid].squash = true;
771 set(toBAC->fetchInfo[tid].nextPC, new_pc);
772 // Also invalidate FTQ. Shall be fixed from BAC.
773 ftq->invalidate(tid);
774}
775
776bool
778{
779 bool ret_val = false;
780
781 if (stalls[tid].drain) {
782 assert(cpu->isDraining());
783 DPRINTF(Fetch,"[tid:%i] Drain stall detected.\n",tid);
784 ret_val = true;
785 }
786
787 return ret_val;
788}
789
792{
793 //Check Running
794 for (ThreadID tid : *activeThreads) {
795 if (fetchStatus[tid] == Running ||
796 fetchStatus[tid] == Squashing ||
798
799 if (_status == Inactive) {
800 DPRINTF(Activity, "[tid:%i] Activating stage.\n",tid);
801
802 if (fetchStatus[tid] == IcacheAccessComplete) {
803 DPRINTF(Activity, "[tid:%i] Activating fetch due to cache"
804 "completion\n",tid);
805 }
806
807 cpu->activateStage(CPU::FetchIdx);
808 }
809
810 return Active;
811 }
812 }
813
814 // Stage is switching from active to inactive, notify CPU of it.
815 if (_status == Active) {
816 DPRINTF(Activity, "Deactivating stage.\n");
817
818 cpu->deactivateStage(CPU::FetchIdx);
819 }
820
821 return Inactive;
822}
823
824void
826{
827 bool status_change = false;
828
829 wroteToTimeBuffer = false;
830
831 for (ThreadID i = 0; i < numThreads; ++i) {
832 issuePipelinedIfetch[i] = false;
833 }
834
835 for (ThreadID tid : *activeThreads) {
836 // Check the signals for each thread to determine the proper status
837 // for each thread.
838 bool updated_status = checkSignalsAndUpdate(tid);
839 status_change = status_change || updated_status;
840 }
841
842 DPRINTF(Fetch, "Running stage.\n");
843
844 if (FullSystem) {
845 if (fromCommit->commitInfo[0].interruptPending) {
846 interruptPending = true;
847 }
848
849 if (fromCommit->commitInfo[0].clearInterrupt) {
850 interruptPending = false;
851 }
852 }
853
855 threadFetched++) {
856 // Fetch each of the actively fetching threads.
857 fetch(status_change);
858 }
859
860 // Record number of instructions fetched this cycle for distribution.
861 fetchStats.nisnDist.sample(numInst);
862
863 if (status_change) {
864 // Change the fetch stage status if there was a status change.
866 }
867
868 // Issue the next I-cache request if possible.
869 for (ThreadID i = 0; i < numThreads; ++i) {
870 if (issuePipelinedIfetch[i]) {
872 }
873 }
874
875 // Send instructions enqueued into the fetch queue to decode.
876 // Limit rate by fetchWidth. Stall if decode is stalled.
877 unsigned insts_to_decode = 0;
878 unsigned available_insts = 0;
879
880 for (auto tid : *activeThreads) {
881 if (!stalls[tid].decode) {
882 available_insts += fetchQueue[tid].size();
883 }
884 }
885
886 // Pick a random thread to start trying to grab instructions from
887 auto tid_itr = activeThreads->begin();
888 std::advance(tid_itr,
889 rng->random<uint8_t>(0, activeThreads->size() - 1));
890
891 while (available_insts != 0 && insts_to_decode < decodeWidth) {
892 ThreadID tid = *tid_itr;
893 if (!stalls[tid].decode && !fetchQueue[tid].empty()) {
894 const auto& inst = fetchQueue[tid].front();
895 toDecode->insts[toDecode->size++] = inst;
896 DPRINTF(Fetch, "[tid:%i] [sn:%llu] Sending instruction to decode "
897 "from fetch queue. Fetch queue size: %i.\n",
898 tid, inst->seqNum, fetchQueue[tid].size());
899
900 wroteToTimeBuffer = true;
901 fetchQueue[tid].pop_front();
902 insts_to_decode++;
903 available_insts--;
904 }
905
906 tid_itr++;
907 // Wrap around if at end of active threads list
908 if (tid_itr == activeThreads->end())
909 tid_itr = activeThreads->begin();
910 }
911
912 // If there was activity this cycle, inform the CPU of it.
913 if (wroteToTimeBuffer) {
914 DPRINTF(Activity, "Activity this cycle.\n");
915 cpu->activityThisCycle();
916 }
917
918 // Reset the number of the instruction we've fetched.
919 numInst = 0;
920}
921
922bool
924{
925 // Update the per thread stall statuses.
926 if (fromDecode->decodeBlock[tid]) {
927 stalls[tid].decode = true;
928 }
929
930 if (fromDecode->decodeUnblock[tid]) {
931 assert(stalls[tid].decode);
932 assert(!fromDecode->decodeBlock[tid]);
933 stalls[tid].decode = false;
934 }
935
936 // Check squash signals from commit.
937 if (fromCommit->commitInfo[tid].squash) {
938 DPRINTF(Fetch, "[tid:%i] Squashing from commit with PC = %s\n", tid,
939 *fromCommit->commitInfo[tid].pc);
940
941 squashFromCommit(*fromCommit->commitInfo[tid].pc,
942 fromCommit->commitInfo[tid].doneSeqNum,
943 fromCommit->commitInfo[tid].squashInst, tid);
944
945 return true;
946 }
947 if (fromCommit->commitInfo[tid].trapPending) {
949
950 return true;
951 }
952
953 // Check squash signals from decode.
954 if (fromDecode->decodeInfo[tid].squash &&
955 (fetchStatus[tid] != Squashing)) {
956 // Squash unless we're already squashing
957
958 DPRINTF(Fetch, "[tid:%i] Squashing from decode with PC = %s\n", tid,
959 *fromDecode->decodeInfo[tid].nextPC);
960
961 squashFromDecode(*fromDecode->decodeInfo[tid].nextPC,
962 fromDecode->decodeInfo[tid].squashInst,
963 fromDecode->decodeInfo[tid].doneSeqNum, tid);
964
965 return true;
966 }
967
968 if (checkStall(tid) && fetchStatus[tid] != IcacheWaitResponse &&
969 fetchStatus[tid] != IcacheWaitRetry && fetchStatus[tid] != ItlbWait &&
970 fetchStatus[tid] != FTQEmpty && fetchStatus[tid] != QuiescePending) {
971 DPRINTF(Fetch, "[tid:%i] Setting to blocked\n",tid);
972
973 fetchStatus[tid] = Blocked;
974
975 return true;
976 }
977
978 if (fetchStatus[tid] == Blocked ||
979 fetchStatus[tid] == Squashing) {
980 // Switch status to running if fetch isn't being told to block or
981 // squash this cycle.
982 // With a decoupled front-end we can only switch to running if the FTQ
983 // is not empty otherwise we need to wait to fillup.
984 if (decoupledFrontEnd && ftq->isEmpty(tid)) {
985 fetchStatus[tid] = FTQEmpty;
986 } else {
987 DPRINTF(Fetch, "[tid:%i] Done squashing, switching to running.\n",
988 tid);
989
990 fetchStatus[tid] = Running;
991 }
992 return true;
993 }
994
995 // Check if the FTQ in has filled up and we can witch to running
996 // otherwise continue waiting to fill up.
997 if (fetchStatus[tid] == FTQEmpty && !ftq->isEmpty(tid)) {
998 DPRINTF(Fetch, "[tid:%i] FTQ is refilled -> running\n", tid);
999 fetchStatus[tid] = Running;
1000 return true;
1001 }
1002
1003 // If we've reached this point, we have not gotten any signals that
1004 // cause fetch to change its status. Fetch remains the same as before.
1005 return false;
1006}
1007
1010 StaticInstPtr curMacroop, const PCStateBase &this_pc,
1011 const PCStateBase &next_pc, bool trace)
1012{
1013 // Get a sequence number.
1014 InstSeqNum seq = cpu->getAndIncrementInstSeq();
1015
1016 DynInst::Arrays arrays;
1017 arrays.numSrcs = staticInst->numSrcRegs();
1018 arrays.numDests = staticInst->numDestRegs();
1019
1020 // Create a new DynInst from the instruction fetched.
1021 DynInstPtr instruction = new (arrays) DynInst(
1022 arrays, staticInst, curMacroop, this_pc, next_pc, seq, cpu);
1023 instruction->setTid(tid);
1024
1025 instruction->setThreadState(cpu->thread[tid]);
1026
1027 DPRINTF(Fetch, "[tid:%i] Instruction PC %s created [sn:%lli].\n",
1028 tid, this_pc, seq);
1029
1030 DPRINTF(Fetch, "[tid:%i] Instruction is: %s\n", tid,
1031 instruction->staticInst->disassemble(this_pc.instAddr()));
1032
1033#if TRACING_ON
1034 if (trace) {
1035 instruction->traceData = cpu->getTracer()->getInstRecord(
1036 curTick(), cpu->tcBase(tid), instruction.get(),
1037 instruction->staticInst, this_pc, curMacroop);
1038 }
1039#else
1040 instruction->traceData = NULL;
1041#endif
1042
1043 // Add instruction to the CPU's list of instructions.
1044 instruction->setInstListIt(cpu->addInst(instruction));
1045
1046 // Write the instruction to the first slot in the queue
1047 // that heads to decode.
1048 assert(numInst < fetchWidth);
1049 fetchQueue[tid].push_back(instruction);
1050 assert(fetchQueue[tid].size() <= fetchQueueSize);
1051 DPRINTF(Fetch, "[tid:%i] Fetch queue entry created (%i/%i).\n",
1052 tid, fetchQueue[tid].size(), fetchQueueSize);
1053 //toDecode->insts[toDecode->size++] = instruction;
1054
1055 // Keep track of if we can take an interrupt at this boundary
1056 delayedCommit[tid] = instruction->isDelayedCommit();
1057
1058 return instruction;
1059}
1060
1061void
1062Fetch::fetch(bool &status_change)
1063{
1065 // Start actual fetch
1068
1069 assert(!cpu->switchedOut());
1070
1071 if (tid == InvalidThreadID) {
1072 // Breaks looping condition in tick()
1074
1075 if (numThreads == 1) { // @todo Per-thread stats
1076 profileStall(0);
1077 }
1078
1079 return;
1080 }
1081
1082 // Check if the FTQ is ready and process the head of the fetch target.
1083 // In the non decoupled front-end ftqReady() will always return true;
1084 if (!ftqReady(tid, status_change)) {
1085 DPRINTF(Fetch, "[tid:%i] FTQ not ready\n", tid);
1086
1087 // No fetch target. We don't know what to fetch.
1088 ++fetchStats.ftqStallCycles;
1089 return;
1090 }
1091
1092 DPRINTF(Fetch, "[tid:%i] Attempting to fetch from\n", tid);
1093
1094 // The current PC.
1095 PCStateBase &this_pc = *pc[tid];
1096 Addr pcOffset = fetchOffset[tid];
1097 Addr fetchAddr = (this_pc.instAddr() + pcOffset) & decoder[tid]->pcMask();
1098
1099 bool inRom = isRomMicroPC(this_pc.microPC());
1100
1101 FetchTargetPtr curFT = ftq->readHead(tid);
1102
1103 if (decoupledFrontEnd) {
1104 assert(ftqReady(tid, status_change));
1105
1106 if (!curFT->inRange(this_pc.instAddr())) {
1107 DPRINTF(Fetch, "[tid:%i] PC:%#x not within fetch target: %s\n",
1108 tid, this_pc, curFT->toString());
1109 bacResteer(this_pc, tid);
1110 ++fetchStats.ftqStallCycles;
1111 return;
1112 }
1113 }
1114
1115 // If returning from the delay of a cache miss, then update the status
1116 // to running, otherwise do the cache access. Possibly move this up
1117 // to tick() function.
1118 if (fetchStatus[tid] == IcacheAccessComplete) {
1119 DPRINTF(Fetch, "[tid:%i] Icache miss is complete.\n", tid);
1120
1121 fetchStatus[tid] = Running;
1122 status_change = true;
1123 } else if (fetchStatus[tid] == Running) {
1124 // Align the fetch PC so its at the start of a fetch buffer segment.
1125 Addr fetchBufferBlockPC = fetchBufferAlignPC(fetchAddr);
1126
1127 // If buffer is no longer valid or fetchAddr has moved to point
1128 // to the next cache block, AND we have no remaining ucode
1129 // from a macro-op, then start fetch from icache.
1130 if (!(fetchBufferValid[tid] && ftqReady(tid, status_change) &&
1131 fetchBufferBlockPC == fetchBufferPC[tid]) &&
1132 !inRom && !macroop[tid]) {
1133 DPRINTF(Fetch, "[tid:%i] Attempting to translate and read "
1134 "instruction, starting at PC %s.\n", tid, this_pc);
1135
1136 fetchCacheLine(fetchAddr, tid, this_pc.instAddr());
1137
1138 if (fetchStatus[tid] == IcacheWaitResponse) {
1139 cpu->fetchStats[tid]->icacheStallCycles++;
1140 }
1141 else if (fetchStatus[tid] == ItlbWait)
1142 ++fetchStats.tlbCycles;
1143 else if (fetchStatus[tid] == FTQEmpty) {
1144 ++fetchStats.ftqStallCycles;
1145 } else {
1146 ++fetchStats.miscStallCycles;
1147 }
1148 return;
1149 } else if (checkInterrupt(this_pc.instAddr()) && !delayedCommit[tid]) {
1150 // Stall CPU if an interrupt is posted and we're not issuing
1151 // an delayed commit micro-op currently (delayed commit
1152 // instructions are not interruptable by interrupts, only faults)
1153 ++fetchStats.miscStallCycles;
1154 DPRINTF(Fetch, "[tid:%i] Fetch is stalled!\n", tid);
1155 return;
1156 }
1157 } else {
1158 if (fetchStatus[tid] == Idle) {
1159 ++fetchStats.idleCycles;
1160 DPRINTF(Fetch, "[tid:%i] Fetch is idle!\n", tid);
1161 }
1162
1163 // Status is Idle, so fetch should do nothing.
1164 return;
1165 }
1166
1167 ++fetchStats.cycles;
1168 std::unique_ptr<PCStateBase> next_pc(this_pc.clone());
1169
1170 StaticInstPtr staticInst = NULL;
1171 StaticInstPtr curMacroop = macroop[tid];
1172
1173 // If the read of the first instruction was successful, then grab the
1174 // instructions from the rest of the cache line and put them into the
1175 // queue heading to decode.
1176
1177 DPRINTF(Fetch, "[tid:%i] Adding instructions to queue to "
1178 "decode.\n", tid);
1179
1180 // Need to keep track of whether or not a predicted branch
1181 // ended this fetch block.
1182 bool predictedBranch = false;
1183 bool mispredict = false;
1184 unsigned num_ft = 0;
1185 unsigned num_taken = 0;
1186
1187 // Need to halt fetch if quiesce instruction detected
1188 bool quiesce = false;
1189
1190 const unsigned numInsts = fetchBufferSize / instSize;
1191 unsigned blkOffset = (fetchAddr - fetchBufferPC[tid]) / instSize;
1192
1193 auto *dec_ptr = decoder[tid];
1194 const Addr pc_mask = dec_ptr->pcMask();
1195
1196 // Loop through instruction memory from the cache.
1197 // Keep issuing while fetchWidth is available and branch is not
1198 // predicted taken
1199 while (numInst < fetchWidth && fetchQueue[tid].size() < fetchQueueSize
1200 && !predictedBranch && !quiesce) {
1201
1202 // For the decoupled front-end also check if the FTQ
1203 // and the fetch target are still valid.
1204 if (decoupledFrontEnd && (!ftq->isReady(tid) || !curFT)) {
1205 break;
1206 }
1207 if (decoupledFrontEnd) {
1208 DPRINTF(Fetch, "Fetch from %s. PC=%s\n", curFT->toString(),
1209 this_pc);
1210 }
1211 assert(!curFT || curFT->inRange(this_pc.instAddr()));
1212
1213 // We need to process more memory if we aren't going to get a
1214 // StaticInst from the rom, the current macroop, or what's already
1215 // in the decoder.
1216 bool needMem = !inRom && !curMacroop && !dec_ptr->instReady();
1217 fetchAddr = (this_pc.instAddr() + pcOffset) & pc_mask;
1218 Addr fetchBufferBlockPC = fetchBufferAlignPC(fetchAddr);
1219
1220 if (needMem) {
1221 // If buffer is no longer valid or fetchAddr has moved to point
1222 // to the next cache block then start fetch from icache.
1223 if (!fetchBufferValid[tid] ||
1224 fetchBufferBlockPC != fetchBufferPC[tid])
1225 break;
1226
1227 if (blkOffset >= numInsts) {
1228 // We need to process more memory, but we've run out of the
1229 // current block.
1230 break;
1231 }
1232
1233 memcpy(dec_ptr->moreBytesPtr(),
1234 fetchBuffer[tid] + blkOffset * instSize, instSize);
1235 decoder[tid]->moreBytes(this_pc, fetchAddr);
1236
1237 if (dec_ptr->needMoreBytes()) {
1238 blkOffset++;
1239 fetchAddr += instSize;
1240 pcOffset += instSize;
1241 }
1242 }
1243
1244 // Extract as many instructions and/or microops as we can from
1245 // the memory we've processed so far.
1246 do {
1247 if (!(curMacroop || inRom)) {
1248 if (dec_ptr->instReady()) {
1249 staticInst = dec_ptr->decode(this_pc);
1250
1251 // Increment stat of fetched instructions.
1252 cpu->fetchStats[tid]->numInsts++;
1253
1254 if (staticInst->isMacroop()) {
1255 curMacroop = staticInst;
1256 } else {
1257 pcOffset = 0;
1258 }
1259 } else {
1260 // We need more bytes for this instruction so blkOffset and
1261 // pcOffset will be updated
1262 break;
1263 }
1264 }
1265 // Whether we're moving to a new macroop because we're at the
1266 // end of the current one, or the branch predictor incorrectly
1267 // thinks we are...
1268 bool newMacro = false;
1269 if (curMacroop || inRom) {
1270 if (inRom) {
1271 staticInst = dec_ptr->fetchRomMicroop(
1272 this_pc.microPC(), curMacroop);
1273 } else {
1274 staticInst = curMacroop->fetchMicroop(this_pc.microPC());
1275 }
1276 newMacro |= staticInst->isLastMicroop();
1277 }
1278
1279 DynInstPtr instruction = buildInst(
1280 tid, staticInst, curMacroop, this_pc, *next_pc, true);
1281
1282 ppFetch->notify(instruction);
1283 numInst++;
1284
1285 instruction->fetchTick = curTick();
1286
1287 set(next_pc, this_pc);
1288
1289 // If we're branching after this instruction, quit fetching
1290 // from the same block.
1291 predictedBranch |= this_pc.branching();
1292
1293 // Get the next PC from the BAC stage.
1294 predictedBranch |= bac->updatePC(instruction, *next_pc, curFT);
1295
1296 if (instruction->isControl()) {
1297 cpu->fetchStats[tid]->numBranches++;
1298 }
1299 if (predictedBranch) {
1300 DPRINTF(Fetch, "Branch detected with PC = %s -> targ: %s, \n",
1301 this_pc, *next_pc);
1302 ++fetchStats.predictedBranches;
1303 }
1304
1305 newMacro |= this_pc.instAddr() != next_pc->instAddr();
1306
1307 // Move to the next instruction, unless we have a branch.
1308 set(this_pc, *next_pc);
1309 inRom = isRomMicroPC(this_pc.microPC());
1310
1311 if (newMacro) {
1312 fetchAddr = this_pc.instAddr() & pc_mask;
1313 blkOffset = (fetchAddr - fetchBufferPC[tid]) / instSize;
1314 pcOffset = 0;
1315 curMacroop = NULL;
1316 }
1317
1318 // Check if the PC exceed the fetch target.
1319 // The pointer is null in the non-decoupled case.
1320 if (curFT && !curFT->inRange(this_pc.instAddr())) {
1321 DPRINTF(Fetch, "Run out of fetch target: %s. Get next one\n",
1322 curFT->toString());
1323 curFT = nullptr;
1324 }
1325
1326 if (instruction->isQuiesce()) {
1327 DPRINTF(Fetch,
1328 "Quiesce instruction encountered, halting fetch!\n");
1330 status_change = true;
1331 quiesce = true;
1332 break;
1333 }
1334 // If the current FT is consumed, try pop the head and read the
1335 // next one until we reach the maximum bandwidth configure.
1336 if (decoupledFrontEnd && !curFT) {
1337 num_ft++;
1338 if (predictedBranch) {
1339 num_taken++;
1340 }
1341
1342 DPRINTF(Fetch, "Update FTQ head\n");
1343 if (ftq->popHead(tid)) {
1344 if ((num_ft < maxFTPerCycle) &&
1345 (num_taken < maxTakenPredPerCycle)) {
1346 curFT = ftq->readHead(tid);
1347 }
1348 } else {
1349 // Poping the head FT was not successful. The BPU predicted
1350 // something wrong. Squash the FTQ.
1351 mispredict = true;
1352 }
1353 break;
1354 }
1355 } while ((curMacroop || dec_ptr->instReady()) &&
1356 numInst < fetchWidth &&
1357 fetchQueue[tid].size() < fetchQueueSize);
1358
1359 // Re-evaluate whether the next instruction to fetch is in micro-op ROM
1360 // or not.
1361 inRom = isRomMicroPC(this_pc.microPC());
1362 }
1363
1364 if (predictedBranch) {
1365 DPRINTF(Fetch, "[tid:%i] Done fetching, predicted branch "
1366 "instruction encountered.\n", tid);
1367 } else if (numInst >= fetchWidth) {
1368 DPRINTF(Fetch, "[tid:%i] Done fetching, reached fetch bandwidth "
1369 "for this cycle.\n", tid);
1370 } else if (blkOffset >= fetchBufferSize) {
1371 DPRINTF(Fetch, "[tid:%i] Done fetching, reached the end of the"
1372 "fetch buffer.\n", tid);
1373 } else if (decoupledFrontEnd && !curFT) {
1374 DPRINTF(Fetch,
1375 "[tid:%i] Done fetching, reached end of the fetch target.\n",
1376 tid);
1377 }
1378 fetchStats.ftNumber.sample(num_ft);
1379
1380 // is mispredict detected, we are squashing the ftq
1381 if (decoupledFrontEnd && mispredict) {
1382 DPRINTF(Fetch, "Mispredict detected, squashing the FTQ.\n");
1383 bacResteer(this_pc, tid);
1384 }
1385
1386 macroop[tid] = curMacroop;
1387 fetchOffset[tid] = pcOffset;
1388
1389 if (numInst > 0) {
1390 wroteToTimeBuffer = true;
1391 }
1392
1393 // pipeline a fetch if we're crossing a fetch buffer boundary and not in
1394 // a state that would preclude fetching
1395 fetchAddr = (this_pc.instAddr() + pcOffset) & pc_mask;
1396 Addr fetchBufferBlockPC = fetchBufferAlignPC(fetchAddr);
1398 fetchBufferBlockPC != fetchBufferPC[tid] &&
1400 fetchStatus[tid] != ItlbWait && fetchStatus[tid] != FTQEmpty &&
1401 fetchStatus[tid] != IcacheWaitRetry &&
1402 fetchStatus[tid] != QuiescePending && !curMacroop;
1403}
1404
1405void
1407{
1408 // If a trap is pending to execute, discard the retry
1409 if (retryPkt != NULL && fetchStatus[retryTid] == TrapPending) {
1410 delete retryPkt;
1411 retryPkt = NULL;
1413 }
1414
1415 if (retryPkt != NULL) {
1416 assert(cacheBlocked);
1417 assert(retryTid != InvalidThreadID);
1419
1420 if (icachePort.sendTimingReq(retryPkt)) {
1422 // Notify Fetch Request probe when a retryPkt is successfully sent.
1423 // Note that notify must be called before retryPkt is set to NULL.
1424 ppFetchRequestSent->notify(retryPkt->req);
1425 retryPkt = NULL;
1427 cacheBlocked = false;
1428 }
1429 } else {
1430 assert(retryTid == InvalidThreadID);
1431 // Access has been squashed since it was sent out. Just clear
1432 // the cache being blocked.
1433 cacheBlocked = false;
1434 }
1435}
1436
1438// //
1439// SMT FETCH POLICY MAINTAINED HERE //
1440// //
1444{
1445 if (numThreads > 1) {
1446 switch (fetchPolicy) {
1447 case SMTFetchPolicy::RoundRobin:
1448 return roundRobin();
1449 case SMTFetchPolicy::IQCount:
1450 return iqCount();
1451 case SMTFetchPolicy::LSQCount:
1452 return lsqCount();
1453 case SMTFetchPolicy::Branch:
1454 return branchCount();
1455 default:
1456 return InvalidThreadID;
1457 }
1458 } else {
1459 auto thread = activeThreads->begin();
1460 if (thread == activeThreads->end()) {
1461 return InvalidThreadID;
1462 }
1463
1464 ThreadID tid = *thread;
1465
1466 if (fetchStatus[tid] == Running ||
1468 fetchStatus[tid] == Idle) {
1469 return tid;
1470 } else {
1471 return InvalidThreadID;
1472 }
1473 }
1474}
1475
1476
1479{
1480 auto pri_iter = priorityList.begin();
1481 auto end = priorityList.end();
1482
1483 ThreadID high_pri;
1484
1485 while (pri_iter != end) {
1486 high_pri = *pri_iter;
1487
1488 assert(high_pri <= numThreads);
1489
1490 if (fetchStatus[high_pri] == Running ||
1491 fetchStatus[high_pri] == IcacheAccessComplete ||
1492 fetchStatus[high_pri] == Idle) {
1493
1494 priorityList.erase(pri_iter);
1495 priorityList.push_back(high_pri);
1496
1497 return high_pri;
1498 }
1499
1500 pri_iter++;
1501 }
1502
1503 return InvalidThreadID;
1504}
1505
1508{
1509 //sorted from lowest->highest
1510 std::priority_queue<unsigned, std::vector<unsigned>,
1511 std::greater<unsigned> > PQ;
1512 std::map<unsigned, ThreadID> threadMap;
1513
1514 for (ThreadID tid : *activeThreads) {
1515 unsigned iqCount = fromIEW->iewInfo[tid].iqCount;
1516
1517 //we can potentially get tid collisions if two threads
1518 //have the same iqCount, but this should be rare.
1519 PQ.push(iqCount);
1520 threadMap[iqCount] = tid;
1521 }
1522
1523 while (!PQ.empty()) {
1524 ThreadID high_pri = threadMap[PQ.top()];
1525
1526 if (fetchStatus[high_pri] == Running ||
1527 fetchStatus[high_pri] == IcacheAccessComplete ||
1528 fetchStatus[high_pri] == Idle)
1529 return high_pri;
1530 else
1531 PQ.pop();
1532
1533 }
1534
1535 return InvalidThreadID;
1536}
1537
1540{
1541 //sorted from lowest->highest
1542 std::priority_queue<unsigned, std::vector<unsigned>,
1543 std::greater<unsigned> > PQ;
1544 std::map<unsigned, ThreadID> threadMap;
1545
1546 for (ThreadID tid : *activeThreads) {
1547 unsigned ldstqCount = fromIEW->iewInfo[tid].ldstqCount;
1548
1549 //we can potentially get tid collisions if two threads
1550 //have the same iqCount, but this should be rare.
1551 PQ.push(ldstqCount);
1552 threadMap[ldstqCount] = tid;
1553 }
1554
1555 while (!PQ.empty()) {
1556 ThreadID high_pri = threadMap[PQ.top()];
1557
1558 if (fetchStatus[high_pri] == Running ||
1559 fetchStatus[high_pri] == IcacheAccessComplete ||
1560 fetchStatus[high_pri] == Idle)
1561 return high_pri;
1562 else
1563 PQ.pop();
1564 }
1565
1566 return InvalidThreadID;
1567}
1568
1571{
1572 panic("Branch Count Fetch policy unimplemented\n");
1573 return InvalidThreadID;
1574}
1575
1576void
1578{
1579 if (!issuePipelinedIfetch[tid]) {
1580 return;
1581 }
1582
1583 // The next PC to access.
1584 const PCStateBase &this_pc = *pc[tid];
1585
1586 if (isRomMicroPC(this_pc.microPC())) {
1587 return;
1588 }
1589
1590 Addr pcOffset = fetchOffset[tid];
1591 Addr fetchAddr = (this_pc.instAddr() + pcOffset) & decoder[tid]->pcMask();
1592
1593 // Align the fetch PC so its at the start of a fetch buffer segment.
1594 Addr fetchBufferBlockPC = fetchBufferAlignPC(fetchAddr);
1595
1596 // Unless buffer already got the block, fetch it from icache.
1597 if (!(fetchBufferValid[tid] && fetchBufferBlockPC == fetchBufferPC[tid])) {
1598 DPRINTF(Fetch, "[tid:%i] Issuing a pipelined I-cache access, "
1599 "starting at PC %s.\n", tid, this_pc);
1600
1601 fetchCacheLine(fetchAddr, tid, this_pc.instAddr());
1602 }
1603}
1604
1605void
1607{
1608 DPRINTF(Fetch,"There are no more threads available to fetch from.\n");
1609
1610 // @todo Per-thread stats
1611
1612 if (stalls[tid].drain) {
1613 ++fetchStats.pendingDrainCycles;
1614 DPRINTF(Fetch, "Fetch is waiting for a drain!\n");
1615 } else if (activeThreads->empty()) {
1616 ++fetchStats.noActiveThreadStallCycles;
1617 DPRINTF(Fetch, "Fetch has no active thread!\n");
1618 } else if (fetchStatus[tid] == Blocked) {
1619 ++fetchStats.blockedCycles;
1620 DPRINTF(Fetch, "[tid:%i] Fetch is blocked!\n", tid);
1621 } else if (fetchStatus[tid] == Squashing) {
1622 ++fetchStats.squashCycles;
1623 DPRINTF(Fetch, "[tid:%i] Fetch is squashing!\n", tid);
1624 } else if (fetchStatus[tid] == IcacheWaitResponse) {
1625 cpu->fetchStats[tid]->icacheStallCycles++;
1626 DPRINTF(Fetch, "[tid:%i] Fetch is waiting cache response!\n",
1627 tid);
1628 } else if (fetchStatus[tid] == ItlbWait) {
1629 ++fetchStats.tlbCycles;
1630 DPRINTF(Fetch, "[tid:%i] Fetch is waiting ITLB walk to "
1631 "finish!\n", tid);
1632 } else if (fetchStatus[tid] == FTQEmpty) {
1633 ++fetchStats.ftqStallCycles;
1634 DPRINTF(Fetch, "[tid:%i] Fetch is waiting for the BPU to fill FTQ!\n",
1635 tid);
1636 } else if (fetchStatus[tid] == TrapPending) {
1637 ++fetchStats.pendingTrapStallCycles;
1638 DPRINTF(Fetch, "[tid:%i] Fetch is waiting for a pending trap!\n",
1639 tid);
1640 } else if (fetchStatus[tid] == QuiescePending) {
1641 ++fetchStats.pendingQuiesceStallCycles;
1642 DPRINTF(Fetch, "[tid:%i] Fetch is waiting for a pending quiesce "
1643 "instruction!\n", tid);
1644 } else if (fetchStatus[tid] == IcacheWaitRetry) {
1645 ++fetchStats.icacheWaitRetryStallCycles;
1646 DPRINTF(Fetch, "[tid:%i] Fetch is waiting for an I-cache retry!\n",
1647 tid);
1648 } else if (fetchStatus[tid] == NoGoodAddr) {
1649 DPRINTF(Fetch, "[tid:%i] Fetch predicted non-executable address\n",
1650 tid);
1651 } else {
1652 DPRINTF(Fetch, "[tid:%i] Unexpected fetch stall reason "
1653 "(Status: %i)\n",
1654 tid, fetchStatus[tid]);
1655 }
1656}
1657
1658bool
1660{
1661 DPRINTF(O3CPU, "Fetch unit received timing\n");
1662 // We shouldn't ever get a cacheable block in Modified state
1663 assert(pkt->req->isUncacheable() ||
1664 !(pkt->cacheResponding() && !pkt->hasSharers()));
1665 fetch->processCacheCompletion(pkt);
1666
1667 return true;
1668}
1669
1670void
1672{
1673 fetch->recvReqRetry();
1674}
1675
1676} // namespace o3
1677} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:209
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,...
Cycles is a wrapper class for representing cycle counts, i.e.
Definition types.hh:79
virtual bool branching() const =0
MicroPC microPC() const
Returns the current micropc.
Definition pcstate.hh:119
Addr instAddr() const
Returns the memory address of the instruction this PC points to.
Definition pcstate.hh:108
virtual PCStateBase * clone() const =0
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition packet.hh:295
RequestPtr req
A pointer to the original request.
Definition packet.hh:377
const T * getConstPtr() const
Definition packet.hh:1234
void dataDynamic(T *p)
Set the data pointer to a value that should have delete [] called on it.
Definition packet.hh:1213
bool cacheResponding() const
Definition packet.hh:659
bool hasSharers() const
Definition packet.hh:686
ProbePointArg generates a point for the class of Arg.
Definition probe.hh:273
T * get() const
Directly access the pointer itself without taking a reference.
Definition refcnt.hh:229
RequestPort(const std::string &name, SimObject *_owner, PortID id=InvalidPortID)
Request port.
Definition port.cc:125
@ INST_FETCH
The request was an instruction fetch.
Definition request.hh:115
uint8_t numSrcRegs() const
Number of source registers.
virtual StaticInstPtr fetchMicroop(MicroPC upc) const
Return the microop that goes with a particular micropc.
uint8_t numDestRegs() const
Number of destination registers.
bool isMacroop() const
bool isLastMicroop() const
wire getWire(int idx)
Definition timebuf.hh:232
O3CPU class, has each of the stages (fetch through commit) within it, as well as all of the time buff...
Definition cpu.hh:97
FTQ class.
Definition ftq.hh:227
Fetch * fetch
Pointer to fetch.
Definition fetch.hh:92
virtual bool recvTimingResp(PacketPtr pkt)
Timing version of receive.
Definition fetch.cc:1659
IcachePort(Fetch *_fetch, CPU *_cpu)
Default constructor.
Definition fetch.cc:77
virtual void recvReqRetry()
Handles doing a retry of a failed fetch.
Definition fetch.cc:1671
gem5::o3::Fetch::FetchStatGroup fetchStats
bool wroteToTimeBuffer
Variable that tracks if fetch has written to the time buffer this cycle.
Definition fetch.hh:441
void deactivateThread(ThreadID tid)
For priority-based fetch policies, need to keep update priorityList.
Definition fetch.cc:507
FetchStatus
Overall fetch status.
Definition fetch.hh:167
std::list< ThreadID > * activeThreads
List of Active Threads.
Definition fetch.hh:519
TimeBuffer< TimeStruct >::wire fromCommit
Wire to get commit's information from backwards time buffer.
Definition fetch.hh:411
StaticInstPtr macroop[MaxThreads]
Definition fetch.hh:430
void fetch(bool &status_change)
Does the actual fetching of instructions and passing them on to the next stage.
Definition fetch.cc:1062
const Cycles renameToFetchDelay
Rename to fetch delay.
Definition fetch.hh:463
void takeOverFrom()
Takes over from another CPU's thread.
Definition fetch.cc:457
uint8_t * fetchBuffer[MaxThreads]
The fetch data that is being fetched and buffered.
Definition fetch.hh:498
void doSquash(const PCStateBase &new_pc, const DynInstPtr squashInst, ThreadID tid)
Squashes a specific thread and resets the PC.
Definition fetch.cc:714
Random::RandomPtr rng
Definition fetch.hh:208
TimeBuffer< FetchStruct >::wire toDecode
Wire used to write any information heading to decode.
Definition fetch.hh:418
void setActiveThreads(std::list< ThreadID > *at_ptr)
Sets pointer to list of active threads.
Definition fetch.cc:266
bool ftqReady(ThreadID tid, bool &status_change)
Checks if the FTQ is ready.
Definition fetch.cc:517
ThreadStatus fetchStatus[MaxThreads]
Per-thread status.
Definition fetch.hh:195
void squashFromCommit(const PCStateBase &new_pc, const InstSeqNum seq_num, DynInstPtr squashInst, ThreadID tid)
Squashes a specific thread and resets the PC.
Definition fetch.cc:702
ThreadID numThreads
Number of threads.
Definition fetch.hh:522
TimeBuffer< TimeStruct >::wire fromDecode
Wire to get decode's information from backwards time buffer.
Definition fetch.hh:402
ProbePointArg< DynInstPtr > * ppFetch
Probe points.
Definition fetch.hh:204
const unsigned maxFTPerCycle
Definition fetch.hh:545
const unsigned decodeWidth
The width of decode in instructions.
Definition fetch.hh:475
TimeBuffer< TimeStruct >::wire fromRename
Wire to get rename's information from backwards time buffer.
Definition fetch.hh:405
const Cycles commitToFetchDelay
Commit to fetch delay.
Definition fetch.hh:469
void squashFromDecode(const PCStateBase &new_pc, const DynInstPtr squashInst, const InstSeqNum seq_num, ThreadID tid)
Squashes a specific thread and resets the PC.
Definition fetch.cc:689
const bool decoupledFrontEnd
Enables the decoupled front-end.
Definition fetch.hh:457
FetchStatus updateFetchStatus()
Updates overall fetch stage status; to be called at the end of each cycle.
Definition fetch.cc:791
ThreadID getFetchingThread()
Returns the appropriate thread to fetch, given the fetch policy.
Definition fetch.cc:1443
bool fetchBufferValid[MaxThreads]
Whether or not the fetch buffer data is valid.
Definition fetch.hh:510
void startupStage()
Initialize stage.
Definition fetch.cc:287
void pipelineIcacheAccesses(ThreadID tid)
Pipeline the next I-cache access to the current one.
Definition fetch.cc:1577
std::string name() const
Returns the name of fetch.
Definition fetch.cc:152
void wakeFromQuiesce()
Tells fetch to wake up from a quiesce instruction.
Definition fetch.cc:474
void switchToActive()
Changes the status of this stage to active, and indicates this to the CPU.
Definition fetch.cc:483
void switchToInactive()
Changes the status of this stage to inactive, and indicates this to the CPU.
Definition fetch.cc:495
int numInst
Tracks how many instructions has been fetched this cycle.
Definition fetch.hh:444
const unsigned fetchWidth
The width of fetch in instructions.
Definition fetch.hh:472
bool fetchCacheLine(Addr vaddr, ThreadID tid, Addr pc)
Fetches the cache line that contains the fetch PC.
Definition fetch.cc:533
bool issuePipelinedIfetch[MaxThreads]
Set to true if a pipelined I-cache request should be issued.
Definition fetch.hh:539
BAC * bac
BPredict.
Definition fetch.hh:421
Addr fetchBufferAlignPC(Addr addr)
Align a PC to the start of a fetch buffer block.
Definition fetch.hh:357
FetchStatus _status
Fetch status.
Definition fetch.hh:192
const unsigned maxTakenPredPerCycle
Definition fetch.hh:546
bool delayedCommit[MaxThreads]
Can the fetch stage redirect from an interrupt on this instruction?
Definition fetch.hh:433
ThreadID threadFetched
Thread ID being fetched.
Definition fetch.hh:528
SMTFetchPolicy fetchPolicy
Fetch policy.
Definition fetch.hh:198
Addr cacheBlkSize
Cache block size.
Definition fetch.hh:487
void drainSanityCheck() const
Perform sanity checks after a drain.
Definition fetch.cc:412
unsigned fetchQueueSize
The size of the fetch queue in micro-ops.
Definition fetch.hh:504
InstDecoder * decoder[MaxThreads]
The decoder.
Definition fetch.hh:363
TimeBuffer< TimeStruct >::wire fromIEW
Wire to get iew's information from backwards time buffer.
Definition fetch.hh:408
const Cycles decodeToFetchDelay
Decode to fetch delay.
Definition fetch.hh:460
void regProbePoints()
Registers probes.
Definition fetch.cc:155
bool checkSignalsAndUpdate(ThreadID tid)
Checks all input signals and updates the status as necessary.
Definition fetch.cc:923
const Cycles iewToFetchDelay
IEW to fetch delay.
Definition fetch.hh:466
bool checkStall(ThreadID tid) const
Checks if a thread is stalled.
Definition fetch.cc:777
void bacResteer(const PCStateBase &new_pc, ThreadID tid)
Signal BAC to redirect.
Definition fetch.cc:766
IcachePort icachePort
Instruction port.
Definition fetch.hh:536
@ IcacheAccessComplete
Definition fetch.hh:185
FTQ * ftq
Fetch Target Queue.
Definition fetch.hh:424
void setTimeBuffer(TimeBuffer< TimeStruct > *time_buffer)
Sets the main backwards communication time buffer pointer.
Definition fetch.cc:249
void processCacheCompletion(PacketPtr pkt)
Processes cache completion event.
Definition fetch.cc:360
ThreadID iqCount()
Returns the appropriate thread to fetch using the IQ count policy.
Definition fetch.cc:1507
Addr fetchBufferMask
Mask to align a fetch address to a fetch buffer boundary.
Definition fetch.hh:495
void recvReqRetry()
Handles retrying the fetch access.
Definition fetch.cc:1406
bool checkInterrupt(Addr pc)
Check if an interrupt is pending and that we need to handle.
Definition fetch.hh:304
void resetStage()
Reset this pipeline stage.
Definition fetch.cc:326
Fetch(CPU *_cpu, const BaseO3CPUParams &params)
Fetch constructor.
Definition fetch.cc:81
void drainStall(ThreadID tid)
Stall the fetch stage after reaching a safe drain point.
Definition fetch.cc:465
Counter lastIcacheStall[MaxThreads]
Icache stall statistics.
Definition fetch.hh:516
int instSize
Size of instructions.
Definition fetch.hh:513
ProbePointArg< RequestPtr > * ppFetchRequestSent
To probe when a fetch request is successfully sent.
Definition fetch.hh:206
RequestPtr memReq[MaxThreads]
Memory request used to access cache.
Definition fetch.hh:436
TimeBuffer< TimeStruct > * timeBuffer
Time buffer interface.
Definition fetch.hh:399
void profileStall(ThreadID tid)
Profile the reasons of fetch stall.
Definition fetch.cc:1606
ThreadID roundRobin()
Returns the appropriate thread to fetch using a round robin policy.
Definition fetch.cc:1478
Addr fetchBufferPC[MaxThreads]
The PC of the first instruction loaded into the fetch buffer.
Definition fetch.hh:501
void drainResume()
Resume after a drain.
Definition fetch.cc:403
void clearStates(ThreadID tid)
Clear all thread-specific states.
Definition fetch.cc:300
void finishTranslation(const Fault &fault, const RequestPtr &mem_req)
Definition fetch.cc:582
bool interruptPending
Checks if there is an interrupt pending.
Definition fetch.hh:533
std::unique_ptr< PCStateBase > pc[MaxThreads]
Definition fetch.hh:426
ThreadID lsqCount()
Returns the appropriate thread to fetch using the LSQ count policy.
Definition fetch.cc:1539
TimeBuffer< TimeStruct >::wire toBAC
Wire used to write any information backward to BAC.
Definition fetch.hh:414
Stalls stalls[MaxThreads]
Tracks which stages are telling fetch to stall.
Definition fetch.hh:454
DynInstPtr buildInst(ThreadID tid, StaticInstPtr staticInst, StaticInstPtr curMacroop, const PCStateBase &this_pc, const PCStateBase &next_pc, bool trace)
Definition fetch.cc:1009
bool isDrained() const
Has the stage drained?
Definition fetch.cc:427
Addr fetchOffset[MaxThreads]
Definition fetch.hh:428
std::deque< DynInstPtr > fetchQueue[MaxThreads]
Queue of fetched instructions.
Definition fetch.hh:507
PacketPtr retryPkt
The packet that is waiting to be retried.
Definition fetch.hh:481
std::list< ThreadID > priorityList
List that has the threads organized by priority.
Definition fetch.hh:201
FinishTranslationEvent finishTranslationEvent
Event used to delay fault generation of translation faults.
Definition fetch.hh:542
ThreadID retryTid
The thread that is waiting on the cache to tell fetch to retry.
Definition fetch.hh:484
void tick()
Ticks the fetch stage, processing all inputs signals and fetching as many instructions as possible.
Definition fetch.cc:825
ThreadID numFetchingThreads
Number of threads that are actively fetching.
Definition fetch.hh:525
unsigned fetchBufferSize
The size of the fetch buffer in bytes.
Definition fetch.hh:492
void setFetchQueue(TimeBuffer< FetchStruct > *fq_ptr)
Sets pointer to time buffer used to communicate to the next stage.
Definition fetch.cc:280
CPU * cpu
Pointer to the O3CPU.
Definition fetch.hh:396
void setBACandFTQPtr(BAC *bac_ptr, FTQ *ftq_ptr)
Sets pointer to branch address calculation stage and FTQ.
Definition fetch.cc:272
bool cacheBlocked
Is the cache blocked?
Definition fetch.hh:478
ThreadID branchCount()
Returns the appropriate thread to fetch using the branch count policy.
Definition fetch.cc:1570
STL list class.
Definition stl.hh:51
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition group.hh:75
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:220
#define fatal(...)
This implements a cprintf based fatal() function.
Definition logging.hh:232
#define warn(...)
Definition logging.hh:288
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 12, 11 > set
std::shared_ptr< FetchTarget > FetchTargetPtr
Definition bac.hh:62
static constexpr int MaxThreads
Definition limits.hh:38
void removeCommThreadInsts(ThreadID tid, CommStruct &comm_struct)
Remove instructions belonging to given thread from the given comm struct's instruction array.
Definition comm.hh:248
RefCountingPtr< DynInst > DynInstPtr
static constexpr int MaxWidth
Definition limits.hh:37
Units for Stats.
Definition units.hh:113
const FlagsType pdf
Print the percent of the total that this entry represents.
Definition info.hh:61
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
std::shared_ptr< FaultBase > Fault
Definition types.hh:249
int16_t ThreadID
Thread index/ID type.
Definition types.hh:235
std::shared_ptr< Request > RequestPtr
Definition request.hh:94
const ThreadID InvalidThreadID
Definition types.hh:236
Tick curTick()
The universal simulation clock.
Definition cur_tick.hh:46
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
Definition root.cc:220
Packet * PacketPtr
RefCountingPtr< StaticInst > StaticInstPtr
static bool isRomMicroPC(MicroPC upc)
Definition types.hh:166
StaticInstPtr nopStaticInstPtr
Pointer to a statically allocated generic "nop" instruction object.
constexpr decltype(nullptr) NoFault
Definition types.hh:253
uint64_t InstSeqNum
Definition inst_seq.hh:40
Declaration of the Packet class.
Struct that defines the information passed from fetch to decode.
Definition comm.hh:63
statistics::Scalar icacheSquashes
Total number of outstanding icache accesses that were dropped due to a squash.
Definition fetch.hh:589
statistics::Distribution ftNumber
Definition fetch.hh:599
statistics::Scalar pendingDrainCycles
Total number of cycles spent in waiting for drains.
Definition fetch.hh:574
statistics::Scalar cacheLines
Stat for total number of fetched cache lines.
Definition fetch.hh:585
statistics::Scalar blockedCycles
Total number of cycles spent blocked.
Definition fetch.hh:570
statistics::Scalar idleCycles
Stat for total number of cycles spent blocked due to other stages in the pipeline.
Definition fetch.hh:568
statistics::Scalar predictedBranches
Stat for total number of predicted branches.
Definition fetch.hh:555
statistics::Scalar noActiveThreadStallCycles
Total number of stall cycles caused by no active threads to run.
Definition fetch.hh:576
statistics::Scalar pendingQuiesceStallCycles
Total number of stall cycles caused by pending quiesce instructions.
Definition fetch.hh:581
statistics::Scalar icacheWaitRetryStallCycles
Total number of stall cycles caused by I-cache wait retrys.
Definition fetch.hh:583
statistics::Scalar pendingTrapStallCycles
Total number of stall cycles caused by pending traps.
Definition fetch.hh:578
statistics::Scalar cycles
Stat for total number of cycles spent fetching.
Definition fetch.hh:557
statistics::Scalar miscStallCycles
Total number of cycles spent in any other state.
Definition fetch.hh:572
statistics::Scalar tlbCycles
Stat for total number of cycles spent waiting for translation.
Definition fetch.hh:561
statistics::Scalar ftqStallCycles
Stat for total number of cycles spent waiting for FTQ to fill.
Definition fetch.hh:563
statistics::Scalar squashCycles
Stat for total number of cycles spent squashing.
Definition fetch.hh:559
FetchStatGroup(CPU *cpu, Fetch *fetch)
Definition fetch.cc:163
statistics::Formula idleRate
Rate of how often fetch was idle.
Definition fetch.hh:597
statistics::Scalar tlbSquashes
Total number of outstanding tlb accesses that were dropped due to a squash.
Definition fetch.hh:593
statistics::Distribution nisnDist
Distribution of number of instructions fetched each cycle.
Definition fetch.hh:595

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