fetch_impl.hh revision 2871:7ed5c9ef3eb6
1/*
2 * Copyright (c) 2004-2006 The Regents of The University of Michigan
3 * All rights reserved.
4 *
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.
15 *
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.
27 *
28 * Authors: Kevin Lim
29 *          Korey Sewell
30 */
31
32#include "config/use_checker.hh"
33
34#include "arch/isa_traits.hh"
35#include "arch/utility.hh"
36#include "cpu/checker/cpu.hh"
37#include "cpu/exetrace.hh"
38#include "cpu/o3/fetch.hh"
39#include "mem/packet.hh"
40#include "mem/request.hh"
41#include "sim/byteswap.hh"
42#include "sim/host.hh"
43#include "sim/root.hh"
44
45#if FULL_SYSTEM
46#include "arch/tlb.hh"
47#include "arch/vtophys.hh"
48#include "base/remote_gdb.hh"
49#include "sim/system.hh"
50#endif // FULL_SYSTEM
51
52#include <algorithm>
53
54using namespace std;
55using namespace TheISA;
56
57template<class Impl>
58Tick
59DefaultFetch<Impl>::IcachePort::recvAtomic(PacketPtr pkt)
60{
61    panic("DefaultFetch doesn't expect recvAtomic callback!");
62    return curTick;
63}
64
65template<class Impl>
66void
67DefaultFetch<Impl>::IcachePort::recvFunctional(PacketPtr pkt)
68{
69    panic("DefaultFetch doesn't expect recvFunctional callback!");
70}
71
72template<class Impl>
73void
74DefaultFetch<Impl>::IcachePort::recvStatusChange(Status status)
75{
76    if (status == RangeChange)
77        return;
78
79    panic("DefaultFetch doesn't expect recvStatusChange callback!");
80}
81
82template<class Impl>
83bool
84DefaultFetch<Impl>::IcachePort::recvTiming(Packet *pkt)
85{
86    fetch->processCacheCompletion(pkt);
87    return true;
88}
89
90template<class Impl>
91void
92DefaultFetch<Impl>::IcachePort::recvRetry()
93{
94    fetch->recvRetry();
95}
96
97template<class Impl>
98DefaultFetch<Impl>::DefaultFetch(Params *params)
99    : mem(params->mem),
100      branchPred(params),
101      decodeToFetchDelay(params->decodeToFetchDelay),
102      renameToFetchDelay(params->renameToFetchDelay),
103      iewToFetchDelay(params->iewToFetchDelay),
104      commitToFetchDelay(params->commitToFetchDelay),
105      fetchWidth(params->fetchWidth),
106      cacheBlocked(false),
107      retryPkt(NULL),
108      retryTid(-1),
109      numThreads(params->numberOfThreads),
110      numFetchingThreads(params->smtNumFetchingThreads),
111      interruptPending(false),
112      drainPending(false),
113      switchedOut(false)
114{
115    if (numThreads > Impl::MaxThreads)
116        fatal("numThreads is not a valid value\n");
117
118    // Set fetch stage's status to inactive.
119    _status = Inactive;
120
121    string policy = params->smtFetchPolicy;
122
123    // Convert string to lowercase
124    std::transform(policy.begin(), policy.end(), policy.begin(),
125                   (int(*)(int)) tolower);
126
127    // Figure out fetch policy
128    if (policy == "singlethread") {
129        fetchPolicy = SingleThread;
130        if (numThreads > 1)
131            panic("Invalid Fetch Policy for a SMT workload.");
132    } else if (policy == "roundrobin") {
133        fetchPolicy = RoundRobin;
134        DPRINTF(Fetch, "Fetch policy set to Round Robin\n");
135    } else if (policy == "branch") {
136        fetchPolicy = Branch;
137        DPRINTF(Fetch, "Fetch policy set to Branch Count\n");
138    } else if (policy == "iqcount") {
139        fetchPolicy = IQ;
140        DPRINTF(Fetch, "Fetch policy set to IQ count\n");
141    } else if (policy == "lsqcount") {
142        fetchPolicy = LSQ;
143        DPRINTF(Fetch, "Fetch policy set to LSQ count\n");
144    } else {
145        fatal("Invalid Fetch Policy. Options Are: {SingleThread,"
146              " RoundRobin,LSQcount,IQcount}\n");
147    }
148
149    // Size of cache block.
150    cacheBlkSize = 64;
151
152    // Create mask to get rid of offset bits.
153    cacheBlkMask = (cacheBlkSize - 1);
154
155    for (int tid=0; tid < numThreads; tid++) {
156
157        fetchStatus[tid] = Running;
158
159        priorityList.push_back(tid);
160
161        memReq[tid] = NULL;
162
163        // Create space to store a cache line.
164        cacheData[tid] = new uint8_t[cacheBlkSize];
165
166        stalls[tid].decode = 0;
167        stalls[tid].rename = 0;
168        stalls[tid].iew = 0;
169        stalls[tid].commit = 0;
170    }
171
172    // Get the size of an instruction.
173    instSize = sizeof(MachInst);
174}
175
176template <class Impl>
177std::string
178DefaultFetch<Impl>::name() const
179{
180    return cpu->name() + ".fetch";
181}
182
183template <class Impl>
184void
185DefaultFetch<Impl>::regStats()
186{
187    icacheStallCycles
188        .name(name() + ".icacheStallCycles")
189        .desc("Number of cycles fetch is stalled on an Icache miss")
190        .prereq(icacheStallCycles);
191
192    fetchedInsts
193        .name(name() + ".Insts")
194        .desc("Number of instructions fetch has processed")
195        .prereq(fetchedInsts);
196
197    fetchedBranches
198        .name(name() + ".Branches")
199        .desc("Number of branches that fetch encountered")
200        .prereq(fetchedBranches);
201
202    predictedBranches
203        .name(name() + ".predictedBranches")
204        .desc("Number of branches that fetch has predicted taken")
205        .prereq(predictedBranches);
206
207    fetchCycles
208        .name(name() + ".Cycles")
209        .desc("Number of cycles fetch has run and was not squashing or"
210              " blocked")
211        .prereq(fetchCycles);
212
213    fetchSquashCycles
214        .name(name() + ".SquashCycles")
215        .desc("Number of cycles fetch has spent squashing")
216        .prereq(fetchSquashCycles);
217
218    fetchIdleCycles
219        .name(name() + ".IdleCycles")
220        .desc("Number of cycles fetch was idle")
221        .prereq(fetchIdleCycles);
222
223    fetchBlockedCycles
224        .name(name() + ".BlockedCycles")
225        .desc("Number of cycles fetch has spent blocked")
226        .prereq(fetchBlockedCycles);
227
228    fetchedCacheLines
229        .name(name() + ".CacheLines")
230        .desc("Number of cache lines fetched")
231        .prereq(fetchedCacheLines);
232
233    fetchMiscStallCycles
234        .name(name() + ".MiscStallCycles")
235        .desc("Number of cycles fetch has spent waiting on interrupts, or "
236              "bad addresses, or out of MSHRs")
237        .prereq(fetchMiscStallCycles);
238
239    fetchIcacheSquashes
240        .name(name() + ".IcacheSquashes")
241        .desc("Number of outstanding Icache misses that were squashed")
242        .prereq(fetchIcacheSquashes);
243
244    fetchNisnDist
245        .init(/* base value */ 0,
246              /* last value */ fetchWidth,
247              /* bucket size */ 1)
248        .name(name() + ".rateDist")
249        .desc("Number of instructions fetched each cycle (Total)")
250        .flags(Stats::pdf);
251
252    idleRate
253        .name(name() + ".idleRate")
254        .desc("Percent of cycles fetch was idle")
255        .prereq(idleRate);
256    idleRate = fetchIdleCycles * 100 / cpu->numCycles;
257
258    branchRate
259        .name(name() + ".branchRate")
260        .desc("Number of branch fetches per cycle")
261        .flags(Stats::total);
262    branchRate = fetchedBranches / cpu->numCycles;
263
264    fetchRate
265        .name(name() + ".rate")
266        .desc("Number of inst fetches per cycle")
267        .flags(Stats::total);
268    fetchRate = fetchedInsts / cpu->numCycles;
269
270    branchPred.regStats();
271}
272
273template<class Impl>
274void
275DefaultFetch<Impl>::setCPU(O3CPU *cpu_ptr)
276{
277    DPRINTF(Fetch, "Setting the CPU pointer.\n");
278    cpu = cpu_ptr;
279
280    // Name is finally available, so create the port.
281    icachePort = new IcachePort(this);
282
283#if USE_CHECKER
284    if (cpu->checker) {
285        cpu->checker->setIcachePort(icachePort);
286    }
287#endif
288
289    // Fetch needs to start fetching instructions at the very beginning,
290    // so it must start up in active state.
291    switchToActive();
292}
293
294template<class Impl>
295void
296DefaultFetch<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *time_buffer)
297{
298    DPRINTF(Fetch, "Setting the time buffer pointer.\n");
299    timeBuffer = time_buffer;
300
301    // Create wires to get information from proper places in time buffer.
302    fromDecode = timeBuffer->getWire(-decodeToFetchDelay);
303    fromRename = timeBuffer->getWire(-renameToFetchDelay);
304    fromIEW = timeBuffer->getWire(-iewToFetchDelay);
305    fromCommit = timeBuffer->getWire(-commitToFetchDelay);
306}
307
308template<class Impl>
309void
310DefaultFetch<Impl>::setActiveThreads(list<unsigned> *at_ptr)
311{
312    DPRINTF(Fetch, "Setting active threads list pointer.\n");
313    activeThreads = at_ptr;
314}
315
316template<class Impl>
317void
318DefaultFetch<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr)
319{
320    DPRINTF(Fetch, "Setting the fetch queue pointer.\n");
321    fetchQueue = fq_ptr;
322
323    // Create wire to write information to proper place in fetch queue.
324    toDecode = fetchQueue->getWire(0);
325}
326
327template<class Impl>
328void
329DefaultFetch<Impl>::initStage()
330{
331    // Setup PC and nextPC with initial state.
332    for (int tid = 0; tid < numThreads; tid++) {
333        PC[tid] = cpu->readPC(tid);
334        nextPC[tid] = cpu->readNextPC(tid);
335#if THE_ISA != ALPHA_ISA
336        nextNPC[tid] = cpu->readNextNPC(tid);
337#endif
338    }
339}
340
341template<class Impl>
342void
343DefaultFetch<Impl>::processCacheCompletion(PacketPtr pkt)
344{
345    unsigned tid = pkt->req->getThreadNum();
346
347    DPRINTF(Fetch, "[tid:%u] Waking up from cache miss.\n",tid);
348
349    // Only change the status if it's still waiting on the icache access
350    // to return.
351    if (fetchStatus[tid] != IcacheWaitResponse ||
352        pkt->req != memReq[tid] ||
353        isSwitchedOut()) {
354        ++fetchIcacheSquashes;
355        delete pkt->req;
356        delete pkt;
357        return;
358    }
359
360    if (!drainPending) {
361        // Wake up the CPU (if it went to sleep and was waiting on
362        // this completion event).
363        cpu->wakeCPU();
364
365        DPRINTF(Activity, "[tid:%u] Activating fetch due to cache completion\n",
366                tid);
367
368        switchToActive();
369    }
370
371    // Only switch to IcacheAccessComplete if we're not stalled as well.
372    if (checkStall(tid)) {
373        fetchStatus[tid] = Blocked;
374    } else {
375        fetchStatus[tid] = IcacheAccessComplete;
376    }
377
378    // Reset the mem req to NULL.
379    delete pkt->req;
380    delete pkt;
381    memReq[tid] = NULL;
382}
383
384template <class Impl>
385bool
386DefaultFetch<Impl>::drain()
387{
388    // Fetch is ready to drain at any time.
389    cpu->signalDrained();
390    drainPending = true;
391    return true;
392}
393
394template <class Impl>
395void
396DefaultFetch<Impl>::resume()
397{
398    drainPending = false;
399}
400
401template <class Impl>
402void
403DefaultFetch<Impl>::switchOut()
404{
405    switchedOut = true;
406    // Branch predictor needs to have its state cleared.
407    branchPred.switchOut();
408}
409
410template <class Impl>
411void
412DefaultFetch<Impl>::takeOverFrom()
413{
414    // Reset all state
415    for (int i = 0; i < Impl::MaxThreads; ++i) {
416        stalls[i].decode = 0;
417        stalls[i].rename = 0;
418        stalls[i].iew = 0;
419        stalls[i].commit = 0;
420        PC[i] = cpu->readPC(i);
421        nextPC[i] = cpu->readNextPC(i);
422#if THE_ISA != ALPHA_ISA
423        nextNPC[i] = cpu->readNextNPC(i);
424#endif
425        fetchStatus[i] = Running;
426    }
427    numInst = 0;
428    wroteToTimeBuffer = false;
429    _status = Inactive;
430    switchedOut = false;
431    branchPred.takeOverFrom();
432}
433
434template <class Impl>
435void
436DefaultFetch<Impl>::wakeFromQuiesce()
437{
438    DPRINTF(Fetch, "Waking up from quiesce\n");
439    // Hopefully this is safe
440    // @todo: Allow other threads to wake from quiesce.
441    fetchStatus[0] = Running;
442}
443
444template <class Impl>
445inline void
446DefaultFetch<Impl>::switchToActive()
447{
448    if (_status == Inactive) {
449        DPRINTF(Activity, "Activating stage.\n");
450
451        cpu->activateStage(O3CPU::FetchIdx);
452
453        _status = Active;
454    }
455}
456
457template <class Impl>
458inline void
459DefaultFetch<Impl>::switchToInactive()
460{
461    if (_status == Active) {
462        DPRINTF(Activity, "Deactivating stage.\n");
463
464        cpu->deactivateStage(O3CPU::FetchIdx);
465
466        _status = Inactive;
467    }
468}
469
470template <class Impl>
471bool
472DefaultFetch<Impl>::lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC)
473{
474    // Do branch prediction check here.
475    // A bit of a misnomer...next_PC is actually the current PC until
476    // this function updates it.
477    bool predict_taken;
478
479    if (!inst->isControl()) {
480        next_PC = next_PC + instSize;
481        inst->setPredTarg(next_PC);
482        return false;
483    }
484
485    predict_taken = branchPred.predict(inst, next_PC, inst->threadNumber);
486
487    ++fetchedBranches;
488
489    if (predict_taken) {
490        ++predictedBranches;
491    }
492
493    return predict_taken;
494}
495
496template <class Impl>
497bool
498DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid)
499{
500    Fault fault = NoFault;
501
502#if FULL_SYSTEM
503    // Flag to say whether or not address is physical addr.
504    unsigned flags = cpu->inPalMode(fetch_PC) ? PHYSICAL : 0;
505#else
506    unsigned flags = 0;
507#endif // FULL_SYSTEM
508
509    if (cacheBlocked || (interruptPending && flags == 0)) {
510        // Hold off fetch from getting new instructions when:
511        // Cache is blocked, or
512        // while an interrupt is pending and we're not in PAL mode, or
513        // fetch is switched out.
514        return false;
515    }
516
517    // Align the fetch PC so it's at the start of a cache block.
518    fetch_PC = icacheBlockAlignPC(fetch_PC);
519
520    // Setup the memReq to do a read of the first instruction's address.
521    // Set the appropriate read size and flags as well.
522    // Build request here.
523    RequestPtr mem_req = new Request(tid, fetch_PC, cacheBlkSize, flags,
524                                     fetch_PC, cpu->readCpuId(), tid);
525
526    memReq[tid] = mem_req;
527
528    // Translate the instruction request.
529    fault = cpu->translateInstReq(mem_req, cpu->thread[tid]);
530
531    // In the case of faults, the fetch stage may need to stall and wait
532    // for the ITB miss to be handled.
533
534    // If translation was successful, attempt to read the first
535    // instruction.
536    if (fault == NoFault) {
537#if 0
538        if (cpu->system->memctrl->badaddr(memReq[tid]->paddr) ||
539            memReq[tid]->flags & UNCACHEABLE) {
540            DPRINTF(Fetch, "Fetch: Bad address %#x (hopefully on a "
541                    "misspeculating path)!",
542                    memReq[tid]->paddr);
543            ret_fault = TheISA::genMachineCheckFault();
544            return false;
545        }
546#endif
547
548        // Build packet here.
549        PacketPtr data_pkt = new Packet(mem_req,
550                                        Packet::ReadReq, Packet::Broadcast);
551        data_pkt->dataStatic(cacheData[tid]);
552
553        DPRINTF(Fetch, "Fetch: Doing instruction read.\n");
554
555        fetchedCacheLines++;
556
557        // Now do the timing access to see whether or not the instruction
558        // exists within the cache.
559        if (!icachePort->sendTiming(data_pkt)) {
560            assert(retryPkt == NULL);
561            assert(retryTid == -1);
562            DPRINTF(Fetch, "[tid:%i] Out of MSHRs!\n", tid);
563            fetchStatus[tid] = IcacheWaitRetry;
564            retryPkt = data_pkt;
565            retryTid = tid;
566            cacheBlocked = true;
567            return false;
568        }
569
570        DPRINTF(Fetch, "[tid:%i]: Doing cache access.\n", tid);
571
572        lastIcacheStall[tid] = curTick;
573
574        DPRINTF(Activity, "[tid:%i]: Activity: Waiting on I-cache "
575                "response.\n", tid);
576
577        fetchStatus[tid] = IcacheWaitResponse;
578    } else {
579        delete mem_req;
580        memReq[tid] = NULL;
581    }
582
583    ret_fault = fault;
584    return true;
585}
586
587template <class Impl>
588inline void
589DefaultFetch<Impl>::doSquash(const Addr &new_PC, unsigned tid)
590{
591    DPRINTF(Fetch, "[tid:%i]: Squashing, setting PC to: %#x.\n",
592            tid, new_PC);
593
594    PC[tid] = new_PC;
595    nextPC[tid] = new_PC + instSize;
596
597    // Clear the icache miss if it's outstanding.
598    if (fetchStatus[tid] == IcacheWaitResponse) {
599        DPRINTF(Fetch, "[tid:%i]: Squashing outstanding Icache miss.\n",
600                tid);
601        memReq[tid] = NULL;
602    }
603
604    // Get rid of the retrying packet if it was from this thread.
605    if (retryTid == tid) {
606        assert(cacheBlocked);
607        cacheBlocked = false;
608        retryTid = -1;
609        retryPkt = NULL;
610        delete retryPkt->req;
611        delete retryPkt;
612    }
613
614    fetchStatus[tid] = Squashing;
615
616    ++fetchSquashCycles;
617}
618
619template<class Impl>
620void
621DefaultFetch<Impl>::squashFromDecode(const Addr &new_PC,
622                                     const InstSeqNum &seq_num,
623                                     unsigned tid)
624{
625    DPRINTF(Fetch, "[tid:%i]: Squashing from decode.\n",tid);
626
627    doSquash(new_PC, tid);
628
629    // Tell the CPU to remove any instructions that are in flight between
630    // fetch and decode.
631    cpu->removeInstsUntil(seq_num, tid);
632}
633
634template<class Impl>
635bool
636DefaultFetch<Impl>::checkStall(unsigned tid) const
637{
638    bool ret_val = false;
639
640    if (cpu->contextSwitch) {
641        DPRINTF(Fetch,"[tid:%i]: Stalling for a context switch.\n",tid);
642        ret_val = true;
643    } else if (stalls[tid].decode) {
644        DPRINTF(Fetch,"[tid:%i]: Stall from Decode stage detected.\n",tid);
645        ret_val = true;
646    } else if (stalls[tid].rename) {
647        DPRINTF(Fetch,"[tid:%i]: Stall from Rename stage detected.\n",tid);
648        ret_val = true;
649    } else if (stalls[tid].iew) {
650        DPRINTF(Fetch,"[tid:%i]: Stall from IEW stage detected.\n",tid);
651        ret_val = true;
652    } else if (stalls[tid].commit) {
653        DPRINTF(Fetch,"[tid:%i]: Stall from Commit stage detected.\n",tid);
654        ret_val = true;
655    }
656
657    return ret_val;
658}
659
660template<class Impl>
661typename DefaultFetch<Impl>::FetchStatus
662DefaultFetch<Impl>::updateFetchStatus()
663{
664    //Check Running
665    list<unsigned>::iterator threads = (*activeThreads).begin();
666
667    while (threads != (*activeThreads).end()) {
668
669        unsigned tid = *threads++;
670
671        if (fetchStatus[tid] == Running ||
672            fetchStatus[tid] == Squashing ||
673            fetchStatus[tid] == IcacheAccessComplete) {
674
675            if (_status == Inactive) {
676                DPRINTF(Activity, "[tid:%i]: Activating stage.\n",tid);
677
678                if (fetchStatus[tid] == IcacheAccessComplete) {
679                    DPRINTF(Activity, "[tid:%i]: Activating fetch due to cache"
680                            "completion\n",tid);
681                }
682
683                cpu->activateStage(O3CPU::FetchIdx);
684            }
685
686            return Active;
687        }
688    }
689
690    // Stage is switching from active to inactive, notify CPU of it.
691    if (_status == Active) {
692        DPRINTF(Activity, "Deactivating stage.\n");
693
694        cpu->deactivateStage(O3CPU::FetchIdx);
695    }
696
697    return Inactive;
698}
699
700template <class Impl>
701void
702DefaultFetch<Impl>::squash(const Addr &new_PC, unsigned tid)
703{
704    DPRINTF(Fetch, "[tid:%u]: Squash from commit.\n",tid);
705
706    doSquash(new_PC, tid);
707
708    // Tell the CPU to remove any instructions that are not in the ROB.
709    cpu->removeInstsNotInROB(tid);
710}
711
712template <class Impl>
713void
714DefaultFetch<Impl>::tick()
715{
716    list<unsigned>::iterator threads = (*activeThreads).begin();
717    bool status_change = false;
718
719    wroteToTimeBuffer = false;
720
721    while (threads != (*activeThreads).end()) {
722        unsigned tid = *threads++;
723
724        // Check the signals for each thread to determine the proper status
725        // for each thread.
726        bool updated_status = checkSignalsAndUpdate(tid);
727        status_change =  status_change || updated_status;
728    }
729
730    DPRINTF(Fetch, "Running stage.\n");
731
732    // Reset the number of the instruction we're fetching.
733    numInst = 0;
734
735#if FULL_SYSTEM
736    if (fromCommit->commitInfo[0].interruptPending) {
737        interruptPending = true;
738    }
739
740    if (fromCommit->commitInfo[0].clearInterrupt) {
741        interruptPending = false;
742    }
743#endif
744
745    for (threadFetched = 0; threadFetched < numFetchingThreads;
746         threadFetched++) {
747        // Fetch each of the actively fetching threads.
748        fetch(status_change);
749    }
750
751    // Record number of instructions fetched this cycle for distribution.
752    fetchNisnDist.sample(numInst);
753
754    if (status_change) {
755        // Change the fetch stage status if there was a status change.
756        _status = updateFetchStatus();
757    }
758
759    // If there was activity this cycle, inform the CPU of it.
760    if (wroteToTimeBuffer || cpu->contextSwitch) {
761        DPRINTF(Activity, "Activity this cycle.\n");
762
763        cpu->activityThisCycle();
764    }
765}
766
767template <class Impl>
768bool
769DefaultFetch<Impl>::checkSignalsAndUpdate(unsigned tid)
770{
771    // Update the per thread stall statuses.
772    if (fromDecode->decodeBlock[tid]) {
773        stalls[tid].decode = true;
774    }
775
776    if (fromDecode->decodeUnblock[tid]) {
777        assert(stalls[tid].decode);
778        assert(!fromDecode->decodeBlock[tid]);
779        stalls[tid].decode = false;
780    }
781
782    if (fromRename->renameBlock[tid]) {
783        stalls[tid].rename = true;
784    }
785
786    if (fromRename->renameUnblock[tid]) {
787        assert(stalls[tid].rename);
788        assert(!fromRename->renameBlock[tid]);
789        stalls[tid].rename = false;
790    }
791
792    if (fromIEW->iewBlock[tid]) {
793        stalls[tid].iew = true;
794    }
795
796    if (fromIEW->iewUnblock[tid]) {
797        assert(stalls[tid].iew);
798        assert(!fromIEW->iewBlock[tid]);
799        stalls[tid].iew = false;
800    }
801
802    if (fromCommit->commitBlock[tid]) {
803        stalls[tid].commit = true;
804    }
805
806    if (fromCommit->commitUnblock[tid]) {
807        assert(stalls[tid].commit);
808        assert(!fromCommit->commitBlock[tid]);
809        stalls[tid].commit = false;
810    }
811
812    // Check squash signals from commit.
813    if (fromCommit->commitInfo[tid].squash) {
814
815        DPRINTF(Fetch, "[tid:%u]: Squashing instructions due to squash "
816                "from commit.\n",tid);
817
818        // In any case, squash.
819        squash(fromCommit->commitInfo[tid].nextPC,tid);
820
821        // Also check if there's a mispredict that happened.
822        if (fromCommit->commitInfo[tid].branchMispredict) {
823            branchPred.squash(fromCommit->commitInfo[tid].doneSeqNum,
824                              fromCommit->commitInfo[tid].nextPC,
825                              fromCommit->commitInfo[tid].branchTaken,
826                              tid);
827        } else {
828            branchPred.squash(fromCommit->commitInfo[tid].doneSeqNum,
829                              tid);
830        }
831
832        return true;
833    } else if (fromCommit->commitInfo[tid].doneSeqNum) {
834        // Update the branch predictor if it wasn't a squashed instruction
835        // that was broadcasted.
836        branchPred.update(fromCommit->commitInfo[tid].doneSeqNum, tid);
837    }
838
839    // Check ROB squash signals from commit.
840    if (fromCommit->commitInfo[tid].robSquashing) {
841        DPRINTF(Fetch, "[tid:%u]: ROB is still squashing.\n", tid);
842
843        // Continue to squash.
844        fetchStatus[tid] = Squashing;
845
846        return true;
847    }
848
849    // Check squash signals from decode.
850    if (fromDecode->decodeInfo[tid].squash) {
851        DPRINTF(Fetch, "[tid:%u]: Squashing instructions due to squash "
852                "from decode.\n",tid);
853
854        // Update the branch predictor.
855        if (fromDecode->decodeInfo[tid].branchMispredict) {
856            branchPred.squash(fromDecode->decodeInfo[tid].doneSeqNum,
857                              fromDecode->decodeInfo[tid].nextPC,
858                              fromDecode->decodeInfo[tid].branchTaken,
859                              tid);
860        } else {
861            branchPred.squash(fromDecode->decodeInfo[tid].doneSeqNum,
862                              tid);
863        }
864
865        if (fetchStatus[tid] != Squashing) {
866            // Squash unless we're already squashing
867            squashFromDecode(fromDecode->decodeInfo[tid].nextPC,
868                             fromDecode->decodeInfo[tid].doneSeqNum,
869                             tid);
870
871            return true;
872        }
873    }
874
875    if (checkStall(tid) && fetchStatus[tid] != IcacheWaitResponse) {
876        DPRINTF(Fetch, "[tid:%i]: Setting to blocked\n",tid);
877
878        fetchStatus[tid] = Blocked;
879
880        return true;
881    }
882
883    if (fetchStatus[tid] == Blocked ||
884        fetchStatus[tid] == Squashing) {
885        // Switch status to running if fetch isn't being told to block or
886        // squash this cycle.
887        DPRINTF(Fetch, "[tid:%i]: Done squashing, switching to running.\n",
888                tid);
889
890        fetchStatus[tid] = Running;
891
892        return true;
893    }
894
895    // If we've reached this point, we have not gotten any signals that
896    // cause fetch to change its status.  Fetch remains the same as before.
897    return false;
898}
899
900template<class Impl>
901void
902DefaultFetch<Impl>::fetch(bool &status_change)
903{
904    //////////////////////////////////////////
905    // Start actual fetch
906    //////////////////////////////////////////
907    int tid = getFetchingThread(fetchPolicy);
908
909    if (tid == -1 || drainPending) {
910        DPRINTF(Fetch,"There are no more threads available to fetch from.\n");
911
912        // Breaks looping condition in tick()
913        threadFetched = numFetchingThreads;
914        return;
915    }
916
917    DPRINTF(Fetch, "Attempting to fetch from [tid:%i]\n", tid);
918
919    // The current PC.
920    Addr &fetch_PC = PC[tid];
921
922    // Fault code for memory access.
923    Fault fault = NoFault;
924
925    // If returning from the delay of a cache miss, then update the status
926    // to running, otherwise do the cache access.  Possibly move this up
927    // to tick() function.
928    if (fetchStatus[tid] == IcacheAccessComplete) {
929        DPRINTF(Fetch, "[tid:%i]: Icache miss is complete.\n",
930                tid);
931
932        fetchStatus[tid] = Running;
933        status_change = true;
934    } else if (fetchStatus[tid] == Running) {
935        DPRINTF(Fetch, "[tid:%i]: Attempting to translate and read "
936                "instruction, starting at PC %08p.\n",
937                tid, fetch_PC);
938
939        bool fetch_success = fetchCacheLine(fetch_PC, fault, tid);
940        if (!fetch_success) {
941            if (cacheBlocked) {
942                ++icacheStallCycles;
943            } else {
944                ++fetchMiscStallCycles;
945            }
946            return;
947        }
948    } else {
949        if (fetchStatus[tid] == Idle) {
950            ++fetchIdleCycles;
951        } else if (fetchStatus[tid] == Blocked) {
952            ++fetchBlockedCycles;
953        } else if (fetchStatus[tid] == Squashing) {
954            ++fetchSquashCycles;
955        } else if (fetchStatus[tid] == IcacheWaitResponse) {
956            ++icacheStallCycles;
957        }
958
959        // Status is Idle, Squashing, Blocked, or IcacheWaitResponse, so
960        // fetch should do nothing.
961        return;
962    }
963
964    ++fetchCycles;
965
966    // If we had a stall due to an icache miss, then return.
967    if (fetchStatus[tid] == IcacheWaitResponse) {
968        ++icacheStallCycles;
969        status_change = true;
970        return;
971    }
972
973    Addr next_PC = fetch_PC;
974    InstSeqNum inst_seq;
975    MachInst inst;
976    ExtMachInst ext_inst;
977    // @todo: Fix this hack.
978    unsigned offset = (fetch_PC & cacheBlkMask) & ~3;
979
980    if (fault == NoFault) {
981        // If the read of the first instruction was successful, then grab the
982        // instructions from the rest of the cache line and put them into the
983        // queue heading to decode.
984
985        DPRINTF(Fetch, "[tid:%i]: Adding instructions to queue to "
986                "decode.\n",tid);
987
988        // Need to keep track of whether or not a predicted branch
989        // ended this fetch block.
990        bool predicted_branch = false;
991
992        for (;
993             offset < cacheBlkSize &&
994                 numInst < fetchWidth &&
995                 !predicted_branch;
996             ++numInst) {
997
998            // Get a sequence number.
999            inst_seq = cpu->getAndIncrementInstSeq();
1000
1001            // Make sure this is a valid index.
1002            assert(offset <= cacheBlkSize - instSize);
1003
1004            // Get the instruction from the array of the cache line.
1005            inst = gtoh(*reinterpret_cast<MachInst *>
1006                        (&cacheData[tid][offset]));
1007
1008            ext_inst = TheISA::makeExtMI(inst, fetch_PC);
1009
1010            // Create a new DynInst from the instruction fetched.
1011            DynInstPtr instruction = new DynInst(ext_inst, fetch_PC,
1012                                                 next_PC,
1013                                                 inst_seq, cpu);
1014            instruction->setTid(tid);
1015
1016            instruction->setASID(tid);
1017
1018            instruction->setThreadState(cpu->thread[tid]);
1019
1020            DPRINTF(Fetch, "[tid:%i]: Instruction PC %#x created "
1021                    "[sn:%lli]\n",
1022                    tid, instruction->readPC(), inst_seq);
1023
1024            DPRINTF(Fetch, "[tid:%i]: Instruction is: %s\n",
1025                    tid, instruction->staticInst->disassemble(fetch_PC));
1026
1027            instruction->traceData =
1028                Trace::getInstRecord(curTick, cpu->tcBase(tid), cpu,
1029                                     instruction->staticInst,
1030                                     instruction->readPC(),tid);
1031
1032            predicted_branch = lookupAndUpdateNextPC(instruction, next_PC);
1033
1034            // Add instruction to the CPU's list of instructions.
1035            instruction->setInstListIt(cpu->addInst(instruction));
1036
1037            // Write the instruction to the first slot in the queue
1038            // that heads to decode.
1039            toDecode->insts[numInst] = instruction;
1040
1041            toDecode->size++;
1042
1043            // Increment stat of fetched instructions.
1044            ++fetchedInsts;
1045
1046            // Move to the next instruction, unless we have a branch.
1047            fetch_PC = next_PC;
1048
1049            if (instruction->isQuiesce()) {
1050                warn("cycle %lli: Quiesce instruction encountered, halting fetch!",
1051                     curTick);
1052                fetchStatus[tid] = QuiescePending;
1053                ++numInst;
1054                status_change = true;
1055                break;
1056            }
1057
1058            offset+= instSize;
1059        }
1060    }
1061
1062    if (numInst > 0) {
1063        wroteToTimeBuffer = true;
1064    }
1065
1066    // Now that fetching is completed, update the PC to signify what the next
1067    // cycle will be.
1068    if (fault == NoFault) {
1069        DPRINTF(Fetch, "[tid:%i]: Setting PC to %08p.\n",tid, next_PC);
1070
1071#if THE_ISA == ALPHA_ISA
1072        PC[tid] = next_PC;
1073        nextPC[tid] = next_PC + instSize;
1074#else
1075        PC[tid] = next_PC;
1076        nextPC[tid] = next_PC + instSize;
1077        nextPC[tid] = next_PC + instSize;
1078
1079        thread->setNextPC(thread->readNextNPC());
1080        thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst));
1081#endif
1082    } else {
1083        // We shouldn't be in an icache miss and also have a fault (an ITB
1084        // miss)
1085        if (fetchStatus[tid] == IcacheWaitResponse) {
1086            panic("Fetch should have exited prior to this!");
1087        }
1088
1089        // Send the fault to commit.  This thread will not do anything
1090        // until commit handles the fault.  The only other way it can
1091        // wake up is if a squash comes along and changes the PC.
1092#if FULL_SYSTEM
1093        assert(numInst != fetchWidth);
1094        // Get a sequence number.
1095        inst_seq = cpu->getAndIncrementInstSeq();
1096        // We will use a nop in order to carry the fault.
1097        ext_inst = TheISA::NoopMachInst;
1098
1099        // Create a new DynInst from the dummy nop.
1100        DynInstPtr instruction = new DynInst(ext_inst, fetch_PC,
1101                                             next_PC,
1102                                             inst_seq, cpu);
1103        instruction->setPredTarg(next_PC + instSize);
1104        instruction->setTid(tid);
1105
1106        instruction->setASID(tid);
1107
1108        instruction->setThreadState(cpu->thread[tid]);
1109
1110        instruction->traceData = NULL;
1111
1112        instruction->setInstListIt(cpu->addInst(instruction));
1113
1114        instruction->fault = fault;
1115
1116        toDecode->insts[numInst] = instruction;
1117        toDecode->size++;
1118
1119        DPRINTF(Fetch, "[tid:%i]: Blocked, need to handle the trap.\n",tid);
1120
1121        fetchStatus[tid] = TrapPending;
1122        status_change = true;
1123
1124        warn("cycle %lli: fault (%d) detected @ PC %08p", curTick, fault, PC[tid]);
1125#else // !FULL_SYSTEM
1126        warn("cycle %lli: fault (%d) detected @ PC %08p", curTick, fault, PC[tid]);
1127#endif // FULL_SYSTEM
1128    }
1129}
1130
1131template<class Impl>
1132void
1133DefaultFetch<Impl>::recvRetry()
1134{
1135    assert(cacheBlocked);
1136    if (retryPkt != NULL) {
1137        assert(retryTid != -1);
1138        assert(fetchStatus[retryTid] == IcacheWaitRetry);
1139
1140        if (icachePort->sendTiming(retryPkt)) {
1141            fetchStatus[retryTid] = IcacheWaitResponse;
1142            retryPkt = NULL;
1143            retryTid = -1;
1144            cacheBlocked = false;
1145        }
1146    } else {
1147        assert(retryTid == -1);
1148        // Access has been squashed since it was sent out.  Just clear
1149        // the cache being blocked.
1150        cacheBlocked = false;
1151    }
1152}
1153
1154///////////////////////////////////////
1155//                                   //
1156//  SMT FETCH POLICY MAINTAINED HERE //
1157//                                   //
1158///////////////////////////////////////
1159template<class Impl>
1160int
1161DefaultFetch<Impl>::getFetchingThread(FetchPriority &fetch_priority)
1162{
1163    if (numThreads > 1) {
1164        switch (fetch_priority) {
1165
1166          case SingleThread:
1167            return 0;
1168
1169          case RoundRobin:
1170            return roundRobin();
1171
1172          case IQ:
1173            return iqCount();
1174
1175          case LSQ:
1176            return lsqCount();
1177
1178          case Branch:
1179            return branchCount();
1180
1181          default:
1182            return -1;
1183        }
1184    } else {
1185        int tid = *((*activeThreads).begin());
1186
1187        if (fetchStatus[tid] == Running ||
1188            fetchStatus[tid] == IcacheAccessComplete ||
1189            fetchStatus[tid] == Idle) {
1190            return tid;
1191        } else {
1192            return -1;
1193        }
1194    }
1195
1196}
1197
1198
1199template<class Impl>
1200int
1201DefaultFetch<Impl>::roundRobin()
1202{
1203    list<unsigned>::iterator pri_iter = priorityList.begin();
1204    list<unsigned>::iterator end      = priorityList.end();
1205
1206    int high_pri;
1207
1208    while (pri_iter != end) {
1209        high_pri = *pri_iter;
1210
1211        assert(high_pri <= numThreads);
1212
1213        if (fetchStatus[high_pri] == Running ||
1214            fetchStatus[high_pri] == IcacheAccessComplete ||
1215            fetchStatus[high_pri] == Idle) {
1216
1217            priorityList.erase(pri_iter);
1218            priorityList.push_back(high_pri);
1219
1220            return high_pri;
1221        }
1222
1223        pri_iter++;
1224    }
1225
1226    return -1;
1227}
1228
1229template<class Impl>
1230int
1231DefaultFetch<Impl>::iqCount()
1232{
1233    priority_queue<unsigned> PQ;
1234
1235    list<unsigned>::iterator threads = (*activeThreads).begin();
1236
1237    while (threads != (*activeThreads).end()) {
1238        unsigned tid = *threads++;
1239
1240        PQ.push(fromIEW->iewInfo[tid].iqCount);
1241    }
1242
1243    while (!PQ.empty()) {
1244
1245        unsigned high_pri = PQ.top();
1246
1247        if (fetchStatus[high_pri] == Running ||
1248            fetchStatus[high_pri] == IcacheAccessComplete ||
1249            fetchStatus[high_pri] == Idle)
1250            return high_pri;
1251        else
1252            PQ.pop();
1253
1254    }
1255
1256    return -1;
1257}
1258
1259template<class Impl>
1260int
1261DefaultFetch<Impl>::lsqCount()
1262{
1263    priority_queue<unsigned> PQ;
1264
1265
1266    list<unsigned>::iterator threads = (*activeThreads).begin();
1267
1268    while (threads != (*activeThreads).end()) {
1269        unsigned tid = *threads++;
1270
1271        PQ.push(fromIEW->iewInfo[tid].ldstqCount);
1272    }
1273
1274    while (!PQ.empty()) {
1275
1276        unsigned high_pri = PQ.top();
1277
1278        if (fetchStatus[high_pri] == Running ||
1279            fetchStatus[high_pri] == IcacheAccessComplete ||
1280            fetchStatus[high_pri] == Idle)
1281            return high_pri;
1282        else
1283            PQ.pop();
1284
1285    }
1286
1287    return -1;
1288}
1289
1290template<class Impl>
1291int
1292DefaultFetch<Impl>::branchCount()
1293{
1294    list<unsigned>::iterator threads = (*activeThreads).begin();
1295    panic("Branch Count Fetch policy unimplemented\n");
1296    return *threads;
1297}
1298