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