2 * Copyright (c) 2004-2006 The Regents of The University of Michigan
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include "config/use_checker.hh"
37 #include "arch/isa_traits.hh"
38 #include "arch/utility.hh"
39 #include "cpu/checker/cpu.hh"
40 #include "cpu/exetrace.hh"
41 #include "cpu/o3/fetch.hh"
42 #include "mem/packet.hh"
43 #include "mem/request.hh"
44 #include "sim/byteswap.hh"
45 #include "sim/host.hh"
46 #include "sim/core.hh"
49 #include "arch/tlb.hh"
50 #include "arch/vtophys.hh"
51 #include "sim/system.hh"
54 #include "params/DerivO3CPU.hh"
58 DefaultFetch<Impl>::IcachePort::setPeer(Port *port)
67 DefaultFetch<Impl>::IcachePort::recvAtomic(PacketPtr pkt)
69 panic("DefaultFetch doesn't expect recvAtomic callback!");
75 DefaultFetch<Impl>::IcachePort::recvFunctional(PacketPtr pkt)
77 DPRINTF(Fetch, "DefaultFetch doesn't update its state from a "
83 DefaultFetch<Impl>::IcachePort::recvStatusChange(Status status)
85 if (status == RangeChange) {
86 if (!snoopRangeSent) {
87 snoopRangeSent = true;
88 sendStatusChange(Port::RangeChange);
93 panic("DefaultFetch doesn't expect recvStatusChange callback!");
98 DefaultFetch<Impl>::IcachePort::recvTiming(PacketPtr pkt)
100 DPRINTF(Fetch, "Received timing\n");
101 if (pkt->isResponse()) {
102 fetch->processCacheCompletion(pkt);
104 //else Snooped a coherence request, just return
110 DefaultFetch<Impl>::IcachePort::recvRetry()
116 DefaultFetch<Impl>::DefaultFetch(O3CPU *_cpu, DerivO3CPUParams *params)
120 decodeToFetchDelay(params->decodeToFetchDelay),
121 renameToFetchDelay(params->renameToFetchDelay),
122 iewToFetchDelay(params->iewToFetchDelay),
123 commitToFetchDelay(params->commitToFetchDelay),
124 fetchWidth(params->fetchWidth),
128 numThreads(params->numThreads),
129 numFetchingThreads(params->smtNumFetchingThreads),
130 interruptPending(false),
134 if (numThreads > Impl::MaxThreads)
135 fatal("numThreads is not a valid value\n");
137 // Set fetch stage's status to inactive.
140 std::string policy = params->smtFetchPolicy;
142 // Convert string to lowercase
143 std::transform(policy.begin(), policy.end(), policy.begin(),
144 (int(*)(int)) tolower);
146 // Figure out fetch policy
147 if (policy == "singlethread") {
148 fetchPolicy = SingleThread;
150 panic("Invalid Fetch Policy for a SMT workload.");
151 } else if (policy == "roundrobin") {
152 fetchPolicy = RoundRobin;
153 DPRINTF(Fetch, "Fetch policy set to Round Robin\n");
154 } else if (policy == "branch") {
155 fetchPolicy = Branch;
156 DPRINTF(Fetch, "Fetch policy set to Branch Count\n");
157 } else if (policy == "iqcount") {
159 DPRINTF(Fetch, "Fetch policy set to IQ count\n");
160 } else if (policy == "lsqcount") {
162 DPRINTF(Fetch, "Fetch policy set to LSQ count\n");
164 fatal("Invalid Fetch Policy. Options Are: {SingleThread,"
165 " RoundRobin,LSQcount,IQcount}\n");
168 // Get the size of an instruction.
169 instSize = sizeof(TheISA::MachInst);
171 // Name is finally available, so create the port.
172 icachePort = new IcachePort(this);
174 icachePort->snoopRangeSent = false;
178 cpu->checker->setIcachePort(icachePort);
183 template <class Impl>
185 DefaultFetch<Impl>::name() const
187 return cpu->name() + ".fetch";
190 template <class Impl>
192 DefaultFetch<Impl>::regStats()
195 .name(name() + ".icacheStallCycles")
196 .desc("Number of cycles fetch is stalled on an Icache miss")
197 .prereq(icacheStallCycles);
200 .name(name() + ".Insts")
201 .desc("Number of instructions fetch has processed")
202 .prereq(fetchedInsts);
205 .name(name() + ".Branches")
206 .desc("Number of branches that fetch encountered")
207 .prereq(fetchedBranches);
210 .name(name() + ".predictedBranches")
211 .desc("Number of branches that fetch has predicted taken")
212 .prereq(predictedBranches);
215 .name(name() + ".Cycles")
216 .desc("Number of cycles fetch has run and was not squashing or"
218 .prereq(fetchCycles);
221 .name(name() + ".SquashCycles")
222 .desc("Number of cycles fetch has spent squashing")
223 .prereq(fetchSquashCycles);
226 .name(name() + ".IdleCycles")
227 .desc("Number of cycles fetch was idle")
228 .prereq(fetchIdleCycles);
231 .name(name() + ".BlockedCycles")
232 .desc("Number of cycles fetch has spent blocked")
233 .prereq(fetchBlockedCycles);
236 .name(name() + ".CacheLines")
237 .desc("Number of cache lines fetched")
238 .prereq(fetchedCacheLines);
241 .name(name() + ".MiscStallCycles")
242 .desc("Number of cycles fetch has spent waiting on interrupts, or "
243 "bad addresses, or out of MSHRs")
244 .prereq(fetchMiscStallCycles);
247 .name(name() + ".IcacheSquashes")
248 .desc("Number of outstanding Icache misses that were squashed")
249 .prereq(fetchIcacheSquashes);
252 .init(/* base value */ 0,
253 /* last value */ fetchWidth,
255 .name(name() + ".rateDist")
256 .desc("Number of instructions fetched each cycle (Total)")
260 .name(name() + ".idleRate")
261 .desc("Percent of cycles fetch was idle")
263 idleRate = fetchIdleCycles * 100 / cpu->numCycles;
266 .name(name() + ".branchRate")
267 .desc("Number of branch fetches per cycle")
268 .flags(Stats::total);
269 branchRate = fetchedBranches / cpu->numCycles;
272 .name(name() + ".rate")
273 .desc("Number of inst fetches per cycle")
274 .flags(Stats::total);
275 fetchRate = fetchedInsts / cpu->numCycles;
277 branchPred.regStats();
282 DefaultFetch<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *time_buffer)
284 timeBuffer = time_buffer;
286 // Create wires to get information from proper places in time buffer.
287 fromDecode = timeBuffer->getWire(-decodeToFetchDelay);
288 fromRename = timeBuffer->getWire(-renameToFetchDelay);
289 fromIEW = timeBuffer->getWire(-iewToFetchDelay);
290 fromCommit = timeBuffer->getWire(-commitToFetchDelay);
295 DefaultFetch<Impl>::setActiveThreads(std::list<unsigned> *at_ptr)
297 activeThreads = at_ptr;
302 DefaultFetch<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr)
306 // Create wire to write information to proper place in fetch queue.
307 toDecode = fetchQueue->getWire(0);
312 DefaultFetch<Impl>::initStage()
314 // Setup PC and nextPC with initial state.
315 for (int tid = 0; tid < numThreads; tid++) {
316 PC[tid] = cpu->readPC(tid);
317 nextPC[tid] = cpu->readNextPC(tid);
318 microPC[tid] = cpu->readMicroPC(tid);
321 for (int tid=0; tid < numThreads; tid++) {
323 fetchStatus[tid] = Running;
325 priorityList.push_back(tid);
329 stalls[tid].decode = false;
330 stalls[tid].rename = false;
331 stalls[tid].iew = false;
332 stalls[tid].commit = false;
335 // Schedule fetch to get the correct PC from the CPU
336 // scheduleFetchStartupEvent(1);
338 // Fetch needs to start fetching instructions at the very beginning,
339 // so it must start up in active state.
345 DefaultFetch<Impl>::setIcache()
347 // Size of cache block.
348 cacheBlkSize = icachePort->peerBlockSize();
350 // Create mask to get rid of offset bits.
351 cacheBlkMask = (cacheBlkSize - 1);
353 for (int tid=0; tid < numThreads; tid++) {
354 // Create space to store a cache line.
355 cacheData[tid] = new uint8_t[cacheBlkSize];
356 cacheDataPC[tid] = 0;
357 cacheDataValid[tid] = false;
363 DefaultFetch<Impl>::processCacheCompletion(PacketPtr pkt)
365 unsigned tid = pkt->req->getThreadNum();
367 DPRINTF(Fetch, "[tid:%u] Waking up from cache miss.\n",tid);
369 assert(!pkt->wasNacked());
371 // Only change the status if it's still waiting on the icache access
373 if (fetchStatus[tid] != IcacheWaitResponse ||
374 pkt->req != memReq[tid] ||
376 ++fetchIcacheSquashes;
382 memcpy(cacheData[tid], pkt->getPtr<uint8_t>(), cacheBlkSize);
383 cacheDataValid[tid] = true;
386 // Wake up the CPU (if it went to sleep and was waiting on
387 // this completion event).
390 DPRINTF(Activity, "[tid:%u] Activating fetch due to cache completion\n",
396 // Only switch to IcacheAccessComplete if we're not stalled as well.
397 if (checkStall(tid)) {
398 fetchStatus[tid] = Blocked;
400 fetchStatus[tid] = IcacheAccessComplete;
403 // Reset the mem req to NULL.
409 template <class Impl>
411 DefaultFetch<Impl>::drain()
413 // Fetch is ready to drain at any time.
414 cpu->signalDrained();
419 template <class Impl>
421 DefaultFetch<Impl>::resume()
423 drainPending = false;
426 template <class Impl>
428 DefaultFetch<Impl>::switchOut()
431 // Branch predictor needs to have its state cleared.
432 branchPred.switchOut();
435 template <class Impl>
437 DefaultFetch<Impl>::takeOverFrom()
440 for (int i = 0; i < Impl::MaxThreads; ++i) {
441 stalls[i].decode = 0;
442 stalls[i].rename = 0;
444 stalls[i].commit = 0;
445 PC[i] = cpu->readPC(i);
446 nextPC[i] = cpu->readNextPC(i);
447 microPC[i] = cpu->readMicroPC(i);
448 fetchStatus[i] = Running;
451 wroteToTimeBuffer = false;
454 interruptPending = false;
455 branchPred.takeOverFrom();
458 template <class Impl>
460 DefaultFetch<Impl>::wakeFromQuiesce()
462 DPRINTF(Fetch, "Waking up from quiesce\n");
463 // Hopefully this is safe
464 // @todo: Allow other threads to wake from quiesce.
465 fetchStatus[0] = Running;
468 template <class Impl>
470 DefaultFetch<Impl>::switchToActive()
472 if (_status == Inactive) {
473 DPRINTF(Activity, "Activating stage.\n");
475 cpu->activateStage(O3CPU::FetchIdx);
481 template <class Impl>
483 DefaultFetch<Impl>::switchToInactive()
485 if (_status == Active) {
486 DPRINTF(Activity, "Deactivating stage.\n");
488 cpu->deactivateStage(O3CPU::FetchIdx);
494 template <class Impl>
496 DefaultFetch<Impl>::lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC,
497 Addr &next_NPC, Addr &next_MicroPC)
499 // Do branch prediction check here.
500 // A bit of a misnomer...next_PC is actually the current PC until
501 // this function updates it.
504 if (!inst->isControl()) {
505 if (inst->isMicroop() && !inst->isLastMicroop()) {
509 next_NPC = next_NPC + instSize;
512 inst->setPredTarg(next_PC, next_NPC, next_MicroPC);
513 inst->setPredTaken(false);
517 //Assume for now that all control flow is to a different macroop which
518 //would reset the micro pc to 0.
521 int tid = inst->threadNumber;
522 Addr pred_PC = next_PC;
523 predict_taken = branchPred.predict(inst, pred_PC, tid);
525 /* if (predict_taken) {
526 DPRINTF(Fetch, "[tid:%i]: Branch predicted to be taken to %#x.\n",
529 DPRINTF(Fetch, "[tid:%i]: Branch predicted to be not taken.\n", tid);
532 #if ISA_HAS_DELAY_SLOT
537 next_NPC += instSize;
543 next_NPC = next_PC + instSize;
545 /* DPRINTF(Fetch, "[tid:%i]: Branch predicted to go to %#x and then %#x.\n",
546 tid, next_PC, next_NPC);*/
547 inst->setPredTarg(next_PC, next_NPC, next_MicroPC);
548 inst->setPredTaken(predict_taken);
556 return predict_taken;
559 template <class Impl>
561 DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid)
563 Fault fault = NoFault;
567 DPRINTF(Fetch, "[tid:%i] Can't fetch cache line, cache blocked\n",
570 } else if (isSwitchedOut()) {
571 DPRINTF(Fetch, "[tid:%i] Can't fetch cache line, switched out\n",
574 } else if (interruptPending && !(fetch_PC & 0x3)) {
575 // Hold off fetch from getting new instructions when:
576 // Cache is blocked, or
577 // while an interrupt is pending and we're not in PAL mode, or
578 // fetch is switched out.
579 DPRINTF(Fetch, "[tid:%i] Can't fetch cache line, interrupt pending\n",
584 // Align the fetch PC so it's at the start of a cache block.
585 Addr block_PC = icacheBlockAlignPC(fetch_PC);
587 // If we've already got the block, no need to try to fetch it again.
588 if (cacheDataValid[tid] && block_PC == cacheDataPC[tid]) {
592 // Setup the memReq to do a read of the first instruction's address.
593 // Set the appropriate read size and flags as well.
594 // Build request here.
595 RequestPtr mem_req = new Request(tid, block_PC, cacheBlkSize, 0,
596 fetch_PC, cpu->readCpuId(), tid);
598 memReq[tid] = mem_req;
600 // Translate the instruction request.
601 fault = cpu->translateInstReq(mem_req, cpu->thread[tid]);
603 // In the case of faults, the fetch stage may need to stall and wait
604 // for the ITB miss to be handled.
606 // If translation was successful, attempt to read the first
608 if (fault == NoFault) {
610 if (cpu->system->memctrl->badaddr(memReq[tid]->paddr) ||
611 memReq[tid]->isUncacheable()) {
612 DPRINTF(Fetch, "Fetch: Bad address %#x (hopefully on a "
613 "misspeculating path)!",
615 ret_fault = TheISA::genMachineCheckFault();
620 // Build packet here.
621 PacketPtr data_pkt = new Packet(mem_req,
622 MemCmd::ReadReq, Packet::Broadcast);
623 data_pkt->dataDynamicArray(new uint8_t[cacheBlkSize]);
625 cacheDataPC[tid] = block_PC;
626 cacheDataValid[tid] = false;
628 DPRINTF(Fetch, "Fetch: Doing instruction read.\n");
632 // Now do the timing access to see whether or not the instruction
633 // exists within the cache.
634 if (!icachePort->sendTiming(data_pkt)) {
635 assert(retryPkt == NULL);
636 assert(retryTid == -1);
637 DPRINTF(Fetch, "[tid:%i] Out of MSHRs!\n", tid);
638 fetchStatus[tid] = IcacheWaitRetry;
645 DPRINTF(Fetch, "[tid:%i]: Doing cache access.\n", tid);
647 lastIcacheStall[tid] = curTick;
649 DPRINTF(Activity, "[tid:%i]: Activity: Waiting on I-cache "
652 fetchStatus[tid] = IcacheWaitResponse;
662 template <class Impl>
664 DefaultFetch<Impl>::doSquash(const Addr &new_PC,
665 const Addr &new_NPC, const Addr &new_microPC, unsigned tid)
667 DPRINTF(Fetch, "[tid:%i]: Squashing, setting PC to: %#x, NPC to: %#x.\n",
668 tid, new_PC, new_NPC);
671 nextPC[tid] = new_NPC;
672 microPC[tid] = new_microPC;
674 // Clear the icache miss if it's outstanding.
675 if (fetchStatus[tid] == IcacheWaitResponse) {
676 DPRINTF(Fetch, "[tid:%i]: Squashing outstanding Icache miss.\n",
681 // Get rid of the retrying packet if it was from this thread.
682 if (retryTid == tid) {
683 assert(cacheBlocked);
685 delete retryPkt->req;
692 fetchStatus[tid] = Squashing;
699 DefaultFetch<Impl>::squashFromDecode(const Addr &new_PC, const Addr &new_NPC,
700 const Addr &new_MicroPC,
701 const InstSeqNum &seq_num, unsigned tid)
703 DPRINTF(Fetch, "[tid:%i]: Squashing from decode.\n",tid);
705 doSquash(new_PC, new_NPC, new_MicroPC, tid);
707 // Tell the CPU to remove any instructions that are in flight between
709 cpu->removeInstsUntil(seq_num, tid);
714 DefaultFetch<Impl>::checkStall(unsigned tid) const
716 bool ret_val = false;
718 if (cpu->contextSwitch) {
719 DPRINTF(Fetch,"[tid:%i]: Stalling for a context switch.\n",tid);
721 } else if (stalls[tid].decode) {
722 DPRINTF(Fetch,"[tid:%i]: Stall from Decode stage detected.\n",tid);
724 } else if (stalls[tid].rename) {
725 DPRINTF(Fetch,"[tid:%i]: Stall from Rename stage detected.\n",tid);
727 } else if (stalls[tid].iew) {
728 DPRINTF(Fetch,"[tid:%i]: Stall from IEW stage detected.\n",tid);
730 } else if (stalls[tid].commit) {
731 DPRINTF(Fetch,"[tid:%i]: Stall from Commit stage detected.\n",tid);
739 typename DefaultFetch<Impl>::FetchStatus
740 DefaultFetch<Impl>::updateFetchStatus()
743 std::list<unsigned>::iterator threads = activeThreads->begin();
744 std::list<unsigned>::iterator end = activeThreads->end();
746 while (threads != end) {
747 unsigned tid = *threads++;
749 if (fetchStatus[tid] == Running ||
750 fetchStatus[tid] == Squashing ||
751 fetchStatus[tid] == IcacheAccessComplete) {
753 if (_status == Inactive) {
754 DPRINTF(Activity, "[tid:%i]: Activating stage.\n",tid);
756 if (fetchStatus[tid] == IcacheAccessComplete) {
757 DPRINTF(Activity, "[tid:%i]: Activating fetch due to cache"
761 cpu->activateStage(O3CPU::FetchIdx);
768 // Stage is switching from active to inactive, notify CPU of it.
769 if (_status == Active) {
770 DPRINTF(Activity, "Deactivating stage.\n");
772 cpu->deactivateStage(O3CPU::FetchIdx);
778 template <class Impl>
780 DefaultFetch<Impl>::squash(const Addr &new_PC, const Addr &new_NPC,
781 const Addr &new_MicroPC,
782 const InstSeqNum &seq_num, unsigned tid)
784 DPRINTF(Fetch, "[tid:%u]: Squash from commit.\n",tid);
786 doSquash(new_PC, new_NPC, new_MicroPC, tid);
788 // Tell the CPU to remove any instructions that are not in the ROB.
789 cpu->removeInstsNotInROB(tid);
792 template <class Impl>
794 DefaultFetch<Impl>::tick()
796 std::list<unsigned>::iterator threads = activeThreads->begin();
797 std::list<unsigned>::iterator end = activeThreads->end();
798 bool status_change = false;
800 wroteToTimeBuffer = false;
802 while (threads != end) {
803 unsigned tid = *threads++;
805 // Check the signals for each thread to determine the proper status
807 bool updated_status = checkSignalsAndUpdate(tid);
808 status_change = status_change || updated_status;
811 DPRINTF(Fetch, "Running stage.\n");
813 // Reset the number of the instruction we're fetching.
817 if (fromCommit->commitInfo[0].interruptPending) {
818 interruptPending = true;
821 if (fromCommit->commitInfo[0].clearInterrupt) {
822 interruptPending = false;
826 for (threadFetched = 0; threadFetched < numFetchingThreads;
828 // Fetch each of the actively fetching threads.
829 fetch(status_change);
832 // Record number of instructions fetched this cycle for distribution.
833 fetchNisnDist.sample(numInst);
836 // Change the fetch stage status if there was a status change.
837 _status = updateFetchStatus();
840 // If there was activity this cycle, inform the CPU of it.
841 if (wroteToTimeBuffer || cpu->contextSwitch) {
842 DPRINTF(Activity, "Activity this cycle.\n");
844 cpu->activityThisCycle();
848 template <class Impl>
850 DefaultFetch<Impl>::checkSignalsAndUpdate(unsigned tid)
852 // Update the per thread stall statuses.
853 if (fromDecode->decodeBlock[tid]) {
854 stalls[tid].decode = true;
857 if (fromDecode->decodeUnblock[tid]) {
858 assert(stalls[tid].decode);
859 assert(!fromDecode->decodeBlock[tid]);
860 stalls[tid].decode = false;
863 if (fromRename->renameBlock[tid]) {
864 stalls[tid].rename = true;
867 if (fromRename->renameUnblock[tid]) {
868 assert(stalls[tid].rename);
869 assert(!fromRename->renameBlock[tid]);
870 stalls[tid].rename = false;
873 if (fromIEW->iewBlock[tid]) {
874 stalls[tid].iew = true;
877 if (fromIEW->iewUnblock[tid]) {
878 assert(stalls[tid].iew);
879 assert(!fromIEW->iewBlock[tid]);
880 stalls[tid].iew = false;
883 if (fromCommit->commitBlock[tid]) {
884 stalls[tid].commit = true;
887 if (fromCommit->commitUnblock[tid]) {
888 assert(stalls[tid].commit);
889 assert(!fromCommit->commitBlock[tid]);
890 stalls[tid].commit = false;
893 // Check squash signals from commit.
894 if (fromCommit->commitInfo[tid].squash) {
896 DPRINTF(Fetch, "[tid:%u]: Squashing instructions due to squash "
897 "from commit.\n",tid);
898 // In any case, squash.
899 squash(fromCommit->commitInfo[tid].nextPC,
900 fromCommit->commitInfo[tid].nextNPC,
901 fromCommit->commitInfo[tid].nextMicroPC,
902 fromCommit->commitInfo[tid].doneSeqNum,
905 // Also check if there's a mispredict that happened.
906 if (fromCommit->commitInfo[tid].branchMispredict) {
907 branchPred.squash(fromCommit->commitInfo[tid].doneSeqNum,
908 fromCommit->commitInfo[tid].nextPC,
909 fromCommit->commitInfo[tid].branchTaken,
912 branchPred.squash(fromCommit->commitInfo[tid].doneSeqNum,
917 } else if (fromCommit->commitInfo[tid].doneSeqNum) {
918 // Update the branch predictor if it wasn't a squashed instruction
919 // that was broadcasted.
920 branchPred.update(fromCommit->commitInfo[tid].doneSeqNum, tid);
923 // Check ROB squash signals from commit.
924 if (fromCommit->commitInfo[tid].robSquashing) {
925 DPRINTF(Fetch, "[tid:%u]: ROB is still squashing.\n", tid);
927 // Continue to squash.
928 fetchStatus[tid] = Squashing;
933 // Check squash signals from decode.
934 if (fromDecode->decodeInfo[tid].squash) {
935 DPRINTF(Fetch, "[tid:%u]: Squashing instructions due to squash "
936 "from decode.\n",tid);
938 // Update the branch predictor.
939 if (fromDecode->decodeInfo[tid].branchMispredict) {
940 branchPred.squash(fromDecode->decodeInfo[tid].doneSeqNum,
941 fromDecode->decodeInfo[tid].nextPC,
942 fromDecode->decodeInfo[tid].branchTaken,
945 branchPred.squash(fromDecode->decodeInfo[tid].doneSeqNum,
949 if (fetchStatus[tid] != Squashing) {
951 DPRINTF(Fetch, "Squashing from decode with PC = %#x, NPC = %#x\n",
952 fromDecode->decodeInfo[tid].nextPC,
953 fromDecode->decodeInfo[tid].nextNPC);
954 // Squash unless we're already squashing
955 squashFromDecode(fromDecode->decodeInfo[tid].nextPC,
956 fromDecode->decodeInfo[tid].nextNPC,
957 fromDecode->decodeInfo[tid].nextMicroPC,
958 fromDecode->decodeInfo[tid].doneSeqNum,
965 if (checkStall(tid) &&
966 fetchStatus[tid] != IcacheWaitResponse &&
967 fetchStatus[tid] != IcacheWaitRetry) {
968 DPRINTF(Fetch, "[tid:%i]: Setting to blocked\n",tid);
970 fetchStatus[tid] = Blocked;
975 if (fetchStatus[tid] == Blocked ||
976 fetchStatus[tid] == Squashing) {
977 // Switch status to running if fetch isn't being told to block or
978 // squash this cycle.
979 DPRINTF(Fetch, "[tid:%i]: Done squashing, switching to running.\n",
982 fetchStatus[tid] = Running;
987 // If we've reached this point, we have not gotten any signals that
988 // cause fetch to change its status. Fetch remains the same as before.
994 DefaultFetch<Impl>::fetch(bool &status_change)
996 //////////////////////////////////////////
997 // Start actual fetch
998 //////////////////////////////////////////
999 int tid = getFetchingThread(fetchPolicy);
1001 if (tid == -1 || drainPending) {
1002 DPRINTF(Fetch,"There are no more threads available to fetch from.\n");
1004 // Breaks looping condition in tick()
1005 threadFetched = numFetchingThreads;
1009 DPRINTF(Fetch, "Attempting to fetch from [tid:%i]\n", tid);
1012 Addr fetch_PC = PC[tid];
1013 Addr fetch_NPC = nextPC[tid];
1014 Addr fetch_MicroPC = microPC[tid];
1016 // Fault code for memory access.
1017 Fault fault = NoFault;
1019 // If returning from the delay of a cache miss, then update the status
1020 // to running, otherwise do the cache access. Possibly move this up
1021 // to tick() function.
1022 if (fetchStatus[tid] == IcacheAccessComplete) {
1023 DPRINTF(Fetch, "[tid:%i]: Icache miss is complete.\n",
1026 fetchStatus[tid] = Running;
1027 status_change = true;
1028 } else if (fetchStatus[tid] == Running) {
1029 DPRINTF(Fetch, "[tid:%i]: Attempting to translate and read "
1030 "instruction, starting at PC %08p.\n",
1033 bool fetch_success = fetchCacheLine(fetch_PC, fault, tid);
1034 if (!fetch_success) {
1036 ++icacheStallCycles;
1038 ++fetchMiscStallCycles;
1043 if (fetchStatus[tid] == Idle) {
1045 DPRINTF(Fetch, "[tid:%i]: Fetch is idle!\n", tid);
1046 } else if (fetchStatus[tid] == Blocked) {
1047 ++fetchBlockedCycles;
1048 DPRINTF(Fetch, "[tid:%i]: Fetch is blocked!\n", tid);
1049 } else if (fetchStatus[tid] == Squashing) {
1050 ++fetchSquashCycles;
1051 DPRINTF(Fetch, "[tid:%i]: Fetch is squashing!\n", tid);
1052 } else if (fetchStatus[tid] == IcacheWaitResponse) {
1053 ++icacheStallCycles;
1054 DPRINTF(Fetch, "[tid:%i]: Fetch is waiting cache response!\n", tid);
1057 // Status is Idle, Squashing, Blocked, or IcacheWaitResponse, so
1058 // fetch should do nothing.
1064 // If we had a stall due to an icache miss, then return.
1065 if (fetchStatus[tid] == IcacheWaitResponse) {
1066 ++icacheStallCycles;
1067 status_change = true;
1071 Addr next_PC = fetch_PC;
1072 Addr next_NPC = fetch_NPC;
1073 Addr next_MicroPC = fetch_MicroPC;
1075 InstSeqNum inst_seq;
1077 ExtMachInst ext_inst;
1078 // @todo: Fix this hack.
1079 unsigned offset = (fetch_PC & cacheBlkMask) & ~3;
1081 StaticInstPtr staticInst = NULL;
1082 StaticInstPtr macroop = NULL;
1084 if (fault == NoFault) {
1085 // If the read of the first instruction was successful, then grab the
1086 // instructions from the rest of the cache line and put them into the
1087 // queue heading to decode.
1089 DPRINTF(Fetch, "[tid:%i]: Adding instructions to queue to "
1092 // Need to keep track of whether or not a predicted branch
1093 // ended this fetch block.
1094 bool predicted_branch = false;
1096 while (offset < cacheBlkSize &&
1097 numInst < fetchWidth &&
1098 !predicted_branch) {
1100 // If we're branching after this instruction, quite fetching
1101 // from the same block then.
1103 (fetch_PC + sizeof(TheISA::MachInst) != fetch_NPC);
1104 if (predicted_branch) {
1105 DPRINTF(Fetch, "Branch detected with PC = %#x, NPC = %#x\n",
1106 fetch_PC, fetch_NPC);
1109 // Make sure this is a valid index.
1110 assert(offset <= cacheBlkSize - instSize);
1113 // Get the instruction from the array of the cache line.
1114 inst = TheISA::gtoh(*reinterpret_cast<TheISA::MachInst *>
1115 (&cacheData[tid][offset]));
1117 predecoder.setTC(cpu->thread[tid]->getTC());
1118 predecoder.moreBytes(fetch_PC, fetch_PC, inst);
1120 ext_inst = predecoder.getExtMachInst();
1121 staticInst = StaticInstPtr(ext_inst, fetch_PC);
1122 if (staticInst->isMacroop())
1123 macroop = staticInst;
1127 staticInst = macroop->fetchMicroop(fetch_MicroPC);
1128 if (staticInst->isLastMicroop())
1132 // Get a sequence number.
1133 inst_seq = cpu->getAndIncrementInstSeq();
1135 // Create a new DynInst from the instruction fetched.
1136 DynInstPtr instruction = new DynInst(staticInst,
1137 fetch_PC, fetch_NPC, fetch_MicroPC,
1138 next_PC, next_NPC, next_MicroPC,
1140 instruction->setTid(tid);
1142 instruction->setASID(tid);
1144 instruction->setThreadState(cpu->thread[tid]);
1146 DPRINTF(Fetch, "[tid:%i]: Instruction PC %#x created "
1148 tid, instruction->readPC(), inst_seq);
1150 //DPRINTF(Fetch, "[tid:%i]: MachInst is %#x\n", tid, ext_inst);
1152 DPRINTF(Fetch, "[tid:%i]: Instruction is: %s\n",
1153 tid, instruction->staticInst->disassemble(fetch_PC));
1156 instruction->traceData =
1157 cpu->getTracer()->getInstRecord(curTick, cpu->tcBase(tid),
1158 instruction->staticInst, instruction->readPC());
1160 instruction->traceData = NULL;
1163 ///FIXME This needs to be more robust in dealing with delay slots
1165 lookupAndUpdateNextPC(instruction, next_PC, next_NPC, next_MicroPC);
1167 // Add instruction to the CPU's list of instructions.
1168 instruction->setInstListIt(cpu->addInst(instruction));
1170 // Write the instruction to the first slot in the queue
1171 // that heads to decode.
1172 toDecode->insts[numInst] = instruction;
1176 // Increment stat of fetched instructions.
1179 // Move to the next instruction, unless we have a branch.
1181 fetch_NPC = next_NPC;
1182 fetch_MicroPC = next_MicroPC;
1184 if (instruction->isQuiesce()) {
1185 DPRINTF(Fetch, "Quiesce instruction encountered, halting fetch!",
1187 fetchStatus[tid] = QuiescePending;
1189 status_change = true;
1194 } while (staticInst->isMicroop() &&
1195 !staticInst->isLastMicroop() &&
1196 numInst < fetchWidth);
1200 if (predicted_branch) {
1201 DPRINTF(Fetch, "[tid:%i]: Done fetching, predicted branch "
1202 "instruction encountered.\n", tid);
1203 } else if (numInst >= fetchWidth) {
1204 DPRINTF(Fetch, "[tid:%i]: Done fetching, reached fetch bandwidth "
1205 "for this cycle.\n", tid);
1206 } else if (offset >= cacheBlkSize) {
1207 DPRINTF(Fetch, "[tid:%i]: Done fetching, reached the end of cache "
1213 wroteToTimeBuffer = true;
1216 // Now that fetching is completed, update the PC to signify what the next
1218 if (fault == NoFault) {
1220 nextPC[tid] = next_NPC;
1221 microPC[tid] = next_MicroPC;
1222 DPRINTF(Fetch, "[tid:%i]: Setting PC to %08p.\n", tid, next_PC);
1224 // We shouldn't be in an icache miss and also have a fault (an ITB
1226 if (fetchStatus[tid] == IcacheWaitResponse) {
1227 panic("Fetch should have exited prior to this!");
1230 // Send the fault to commit. This thread will not do anything
1231 // until commit handles the fault. The only other way it can
1232 // wake up is if a squash comes along and changes the PC.
1233 assert(numInst < fetchWidth);
1234 // Get a sequence number.
1235 inst_seq = cpu->getAndIncrementInstSeq();
1236 // We will use a nop in order to carry the fault.
1237 ext_inst = TheISA::NoopMachInst;
1239 // Create a new DynInst from the dummy nop.
1240 DynInstPtr instruction = new DynInst(ext_inst,
1241 fetch_PC, fetch_NPC, fetch_MicroPC,
1242 next_PC, next_NPC, next_MicroPC,
1244 instruction->setPredTarg(next_NPC, next_NPC + instSize, 0);
1245 instruction->setTid(tid);
1247 instruction->setASID(tid);
1249 instruction->setThreadState(cpu->thread[tid]);
1251 instruction->traceData = NULL;
1253 instruction->setInstListIt(cpu->addInst(instruction));
1255 instruction->fault = fault;
1257 toDecode->insts[numInst] = instruction;
1260 DPRINTF(Fetch, "[tid:%i]: Blocked, need to handle the trap.\n",tid);
1262 fetchStatus[tid] = TrapPending;
1263 status_change = true;
1265 DPRINTF(Fetch, "[tid:%i]: fault (%s) detected @ PC %08p",
1266 tid, fault->name(), PC[tid]);
1270 template<class Impl>
1272 DefaultFetch<Impl>::recvRetry()
1274 if (retryPkt != NULL) {
1275 assert(cacheBlocked);
1276 assert(retryTid != -1);
1277 assert(fetchStatus[retryTid] == IcacheWaitRetry);
1279 if (icachePort->sendTiming(retryPkt)) {
1280 fetchStatus[retryTid] = IcacheWaitResponse;
1283 cacheBlocked = false;
1286 assert(retryTid == -1);
1287 // Access has been squashed since it was sent out. Just clear
1288 // the cache being blocked.
1289 cacheBlocked = false;
1293 ///////////////////////////////////////
1295 // SMT FETCH POLICY MAINTAINED HERE //
1297 ///////////////////////////////////////
1298 template<class Impl>
1300 DefaultFetch<Impl>::getFetchingThread(FetchPriority &fetch_priority)
1302 if (numThreads > 1) {
1303 switch (fetch_priority) {
1309 return roundRobin();
1318 return branchCount();
1324 std::list<unsigned>::iterator thread = activeThreads->begin();
1325 assert(thread != activeThreads->end());
1328 if (fetchStatus[tid] == Running ||
1329 fetchStatus[tid] == IcacheAccessComplete ||
1330 fetchStatus[tid] == Idle) {
1340 template<class Impl>
1342 DefaultFetch<Impl>::roundRobin()
1344 std::list<unsigned>::iterator pri_iter = priorityList.begin();
1345 std::list<unsigned>::iterator end = priorityList.end();
1349 while (pri_iter != end) {
1350 high_pri = *pri_iter;
1352 assert(high_pri <= numThreads);
1354 if (fetchStatus[high_pri] == Running ||
1355 fetchStatus[high_pri] == IcacheAccessComplete ||
1356 fetchStatus[high_pri] == Idle) {
1358 priorityList.erase(pri_iter);
1359 priorityList.push_back(high_pri);
1370 template<class Impl>
1372 DefaultFetch<Impl>::iqCount()
1374 std::priority_queue<unsigned> PQ;
1376 std::list<unsigned>::iterator threads = activeThreads->begin();
1377 std::list<unsigned>::iterator end = activeThreads->end();
1379 while (threads != end) {
1380 unsigned tid = *threads++;
1382 PQ.push(fromIEW->iewInfo[tid].iqCount);
1385 while (!PQ.empty()) {
1387 unsigned high_pri = PQ.top();
1389 if (fetchStatus[high_pri] == Running ||
1390 fetchStatus[high_pri] == IcacheAccessComplete ||
1391 fetchStatus[high_pri] == Idle)
1401 template<class Impl>
1403 DefaultFetch<Impl>::lsqCount()
1405 std::priority_queue<unsigned> PQ;
1407 std::list<unsigned>::iterator threads = activeThreads->begin();
1408 std::list<unsigned>::iterator end = activeThreads->end();
1410 while (threads != end) {
1411 unsigned tid = *threads++;
1413 PQ.push(fromIEW->iewInfo[tid].ldstqCount);
1416 while (!PQ.empty()) {
1418 unsigned high_pri = PQ.top();
1420 if (fetchStatus[high_pri] == Running ||
1421 fetchStatus[high_pri] == IcacheAccessComplete ||
1422 fetchStatus[high_pri] == Idle)
1432 template<class Impl>
1434 DefaultFetch<Impl>::branchCount()
1436 std::list<unsigned>::iterator thread = activeThreads->begin();
1437 assert(thread != activeThreads->end());
1438 unsigned tid = *thread;
1440 panic("Branch Count Fetch policy unimplemented\n");