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