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