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