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