commit_impl.hh revision 8823:ae411fcf4935
1/*
2 * Copyright (c) 2010 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2004-2006 The Regents of The University of Michigan
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Kevin Lim
41 *          Korey Sewell
42 */
43
44#include <algorithm>
45#include <string>
46
47#include "arch/utility.hh"
48#include "base/loader/symtab.hh"
49#include "base/cp_annotate.hh"
50#include "config/the_isa.hh"
51#include "config/use_checker.hh"
52#include "cpu/o3/commit.hh"
53#include "cpu/o3/thread_state.hh"
54#include "cpu/base.hh"
55#include "cpu/exetrace.hh"
56#include "cpu/timebuf.hh"
57#include "debug/Activity.hh"
58#include "debug/Commit.hh"
59#include "debug/CommitRate.hh"
60#include "debug/ExecFaulting.hh"
61#include "debug/O3PipeView.hh"
62#include "params/DerivO3CPU.hh"
63#include "sim/faults.hh"
64#include "sim/full_system.hh"
65
66#if USE_CHECKER
67#include "cpu/checker/cpu.hh"
68#endif
69
70using namespace std;
71
72template <class Impl>
73DefaultCommit<Impl>::TrapEvent::TrapEvent(DefaultCommit<Impl> *_commit,
74                                          ThreadID _tid)
75    : Event(CPU_Tick_Pri, AutoDelete), commit(_commit), tid(_tid)
76{
77}
78
79template <class Impl>
80void
81DefaultCommit<Impl>::TrapEvent::process()
82{
83    // This will get reset by commit if it was switched out at the
84    // time of this event processing.
85    commit->trapSquash[tid] = true;
86}
87
88template <class Impl>
89const char *
90DefaultCommit<Impl>::TrapEvent::description() const
91{
92    return "Trap";
93}
94
95template <class Impl>
96DefaultCommit<Impl>::DefaultCommit(O3CPU *_cpu, DerivO3CPUParams *params)
97    : cpu(_cpu),
98      squashCounter(0),
99      iewToCommitDelay(params->iewToCommitDelay),
100      commitToIEWDelay(params->commitToIEWDelay),
101      renameToROBDelay(params->renameToROBDelay),
102      fetchToCommitDelay(params->commitToFetchDelay),
103      renameWidth(params->renameWidth),
104      commitWidth(params->commitWidth),
105      numThreads(params->numThreads),
106      drainPending(false),
107      switchedOut(false),
108      trapLatency(params->trapLatency),
109      canHandleInterrupts(true)
110{
111    _status = Active;
112    _nextStatus = Inactive;
113    std::string policy = params->smtCommitPolicy;
114
115    //Convert string to lowercase
116    std::transform(policy.begin(), policy.end(), policy.begin(),
117                   (int(*)(int)) tolower);
118
119    //Assign commit policy
120    if (policy == "aggressive"){
121        commitPolicy = Aggressive;
122
123        DPRINTF(Commit,"Commit Policy set to Aggressive.\n");
124    } else if (policy == "roundrobin"){
125        commitPolicy = RoundRobin;
126
127        //Set-Up Priority List
128        for (ThreadID tid = 0; tid < numThreads; tid++) {
129            priority_list.push_back(tid);
130        }
131
132        DPRINTF(Commit,"Commit Policy set to Round Robin.\n");
133    } else if (policy == "oldestready"){
134        commitPolicy = OldestReady;
135
136        DPRINTF(Commit,"Commit Policy set to Oldest Ready.");
137    } else {
138        assert(0 && "Invalid SMT Commit Policy. Options Are: {Aggressive,"
139               "RoundRobin,OldestReady}");
140    }
141
142    for (ThreadID tid = 0; tid < numThreads; tid++) {
143        commitStatus[tid] = Idle;
144        changedROBNumEntries[tid] = false;
145        checkEmptyROB[tid] = false;
146        trapInFlight[tid] = false;
147        committedStores[tid] = false;
148        trapSquash[tid] = false;
149        tcSquash[tid] = false;
150        pc[tid].set(0);
151        lastCommitedSeqNum[tid] = 0;
152    }
153    interrupt = NoFault;
154}
155
156template <class Impl>
157std::string
158DefaultCommit<Impl>::name() const
159{
160    return cpu->name() + ".commit";
161}
162
163template <class Impl>
164void
165DefaultCommit<Impl>::regStats()
166{
167    using namespace Stats;
168    commitCommittedInsts
169        .name(name() + ".commitCommittedInsts")
170        .desc("The number of committed instructions")
171        .prereq(commitCommittedInsts);
172    commitSquashedInsts
173        .name(name() + ".commitSquashedInsts")
174        .desc("The number of squashed insts skipped by commit")
175        .prereq(commitSquashedInsts);
176    commitSquashEvents
177        .name(name() + ".commitSquashEvents")
178        .desc("The number of times commit is told to squash")
179        .prereq(commitSquashEvents);
180    commitNonSpecStalls
181        .name(name() + ".commitNonSpecStalls")
182        .desc("The number of times commit has been forced to stall to "
183              "communicate backwards")
184        .prereq(commitNonSpecStalls);
185    branchMispredicts
186        .name(name() + ".branchMispredicts")
187        .desc("The number of times a branch was mispredicted")
188        .prereq(branchMispredicts);
189    numCommittedDist
190        .init(0,commitWidth,1)
191        .name(name() + ".committed_per_cycle")
192        .desc("Number of insts commited each cycle")
193        .flags(Stats::pdf)
194        ;
195
196    statComInst
197        .init(cpu->numThreads)
198        .name(name() + ".count")
199        .desc("Number of instructions committed")
200        .flags(total)
201        ;
202
203    statComSwp
204        .init(cpu->numThreads)
205        .name(name() + ".swp_count")
206        .desc("Number of s/w prefetches committed")
207        .flags(total)
208        ;
209
210    statComRefs
211        .init(cpu->numThreads)
212        .name(name() +  ".refs")
213        .desc("Number of memory references committed")
214        .flags(total)
215        ;
216
217    statComLoads
218        .init(cpu->numThreads)
219        .name(name() +  ".loads")
220        .desc("Number of loads committed")
221        .flags(total)
222        ;
223
224    statComMembars
225        .init(cpu->numThreads)
226        .name(name() +  ".membars")
227        .desc("Number of memory barriers committed")
228        .flags(total)
229        ;
230
231    statComBranches
232        .init(cpu->numThreads)
233        .name(name() + ".branches")
234        .desc("Number of branches committed")
235        .flags(total)
236        ;
237
238    statComFloating
239        .init(cpu->numThreads)
240        .name(name() + ".fp_insts")
241        .desc("Number of committed floating point instructions.")
242        .flags(total)
243        ;
244
245    statComInteger
246        .init(cpu->numThreads)
247        .name(name()+".int_insts")
248        .desc("Number of committed integer instructions.")
249        .flags(total)
250        ;
251
252    statComFunctionCalls
253        .init(cpu->numThreads)
254        .name(name()+".function_calls")
255        .desc("Number of function calls committed.")
256        .flags(total)
257        ;
258
259    commitEligible
260        .init(cpu->numThreads)
261        .name(name() + ".bw_limited")
262        .desc("number of insts not committed due to BW limits")
263        .flags(total)
264        ;
265
266    commitEligibleSamples
267        .name(name() + ".bw_lim_events")
268        .desc("number cycles where commit BW limit reached")
269        ;
270}
271
272template <class Impl>
273void
274DefaultCommit<Impl>::setThreads(std::vector<Thread *> &threads)
275{
276    thread = threads;
277}
278
279template <class Impl>
280void
281DefaultCommit<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
282{
283    timeBuffer = tb_ptr;
284
285    // Setup wire to send information back to IEW.
286    toIEW = timeBuffer->getWire(0);
287
288    // Setup wire to read data from IEW (for the ROB).
289    robInfoFromIEW = timeBuffer->getWire(-iewToCommitDelay);
290}
291
292template <class Impl>
293void
294DefaultCommit<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr)
295{
296    fetchQueue = fq_ptr;
297
298    // Setup wire to get instructions from rename (for the ROB).
299    fromFetch = fetchQueue->getWire(-fetchToCommitDelay);
300}
301
302template <class Impl>
303void
304DefaultCommit<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
305{
306    renameQueue = rq_ptr;
307
308    // Setup wire to get instructions from rename (for the ROB).
309    fromRename = renameQueue->getWire(-renameToROBDelay);
310}
311
312template <class Impl>
313void
314DefaultCommit<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
315{
316    iewQueue = iq_ptr;
317
318    // Setup wire to get instructions from IEW.
319    fromIEW = iewQueue->getWire(-iewToCommitDelay);
320}
321
322template <class Impl>
323void
324DefaultCommit<Impl>::setIEWStage(IEW *iew_stage)
325{
326    iewStage = iew_stage;
327}
328
329template<class Impl>
330void
331DefaultCommit<Impl>::setActiveThreads(list<ThreadID> *at_ptr)
332{
333    activeThreads = at_ptr;
334}
335
336template <class Impl>
337void
338DefaultCommit<Impl>::setRenameMap(RenameMap rm_ptr[])
339{
340    for (ThreadID tid = 0; tid < numThreads; tid++)
341        renameMap[tid] = &rm_ptr[tid];
342}
343
344template <class Impl>
345void
346DefaultCommit<Impl>::setROB(ROB *rob_ptr)
347{
348    rob = rob_ptr;
349}
350
351template <class Impl>
352void
353DefaultCommit<Impl>::initStage()
354{
355    rob->setActiveThreads(activeThreads);
356    rob->resetEntries();
357
358    // Broadcast the number of free entries.
359    for (ThreadID tid = 0; tid < numThreads; tid++) {
360        toIEW->commitInfo[tid].usedROB = true;
361        toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid);
362        toIEW->commitInfo[tid].emptyROB = true;
363    }
364
365    // Commit must broadcast the number of free entries it has at the
366    // start of the simulation, so it starts as active.
367    cpu->activateStage(O3CPU::CommitIdx);
368
369    cpu->activityThisCycle();
370    trapLatency = cpu->ticks(trapLatency);
371}
372
373template <class Impl>
374bool
375DefaultCommit<Impl>::drain()
376{
377    drainPending = true;
378
379    return false;
380}
381
382template <class Impl>
383void
384DefaultCommit<Impl>::switchOut()
385{
386    switchedOut = true;
387    drainPending = false;
388    rob->switchOut();
389}
390
391template <class Impl>
392void
393DefaultCommit<Impl>::resume()
394{
395    drainPending = false;
396}
397
398template <class Impl>
399void
400DefaultCommit<Impl>::takeOverFrom()
401{
402    switchedOut = false;
403    _status = Active;
404    _nextStatus = Inactive;
405    for (ThreadID tid = 0; tid < numThreads; tid++) {
406        commitStatus[tid] = Idle;
407        changedROBNumEntries[tid] = false;
408        trapSquash[tid] = false;
409        tcSquash[tid] = false;
410    }
411    squashCounter = 0;
412    rob->takeOverFrom();
413}
414
415template <class Impl>
416void
417DefaultCommit<Impl>::updateStatus()
418{
419    // reset ROB changed variable
420    list<ThreadID>::iterator threads = activeThreads->begin();
421    list<ThreadID>::iterator end = activeThreads->end();
422
423    while (threads != end) {
424        ThreadID tid = *threads++;
425
426        changedROBNumEntries[tid] = false;
427
428        // Also check if any of the threads has a trap pending
429        if (commitStatus[tid] == TrapPending ||
430            commitStatus[tid] == FetchTrapPending) {
431            _nextStatus = Active;
432        }
433    }
434
435    if (_nextStatus == Inactive && _status == Active) {
436        DPRINTF(Activity, "Deactivating stage.\n");
437        cpu->deactivateStage(O3CPU::CommitIdx);
438    } else if (_nextStatus == Active && _status == Inactive) {
439        DPRINTF(Activity, "Activating stage.\n");
440        cpu->activateStage(O3CPU::CommitIdx);
441    }
442
443    _status = _nextStatus;
444}
445
446template <class Impl>
447void
448DefaultCommit<Impl>::setNextStatus()
449{
450    int squashes = 0;
451
452    list<ThreadID>::iterator threads = activeThreads->begin();
453    list<ThreadID>::iterator end = activeThreads->end();
454
455    while (threads != end) {
456        ThreadID tid = *threads++;
457
458        if (commitStatus[tid] == ROBSquashing) {
459            squashes++;
460        }
461    }
462
463    squashCounter = squashes;
464
465    // If commit is currently squashing, then it will have activity for the
466    // next cycle. Set its next status as active.
467    if (squashCounter) {
468        _nextStatus = Active;
469    }
470}
471
472template <class Impl>
473bool
474DefaultCommit<Impl>::changedROBEntries()
475{
476    list<ThreadID>::iterator threads = activeThreads->begin();
477    list<ThreadID>::iterator end = activeThreads->end();
478
479    while (threads != end) {
480        ThreadID tid = *threads++;
481
482        if (changedROBNumEntries[tid]) {
483            return true;
484        }
485    }
486
487    return false;
488}
489
490template <class Impl>
491size_t
492DefaultCommit<Impl>::numROBFreeEntries(ThreadID tid)
493{
494    return rob->numFreeEntries(tid);
495}
496
497template <class Impl>
498void
499DefaultCommit<Impl>::generateTrapEvent(ThreadID tid)
500{
501    DPRINTF(Commit, "Generating trap event for [tid:%i]\n", tid);
502
503    TrapEvent *trap = new TrapEvent(this, tid);
504
505    cpu->schedule(trap, curTick() + trapLatency);
506    trapInFlight[tid] = true;
507    thread[tid]->trapPending = true;
508}
509
510template <class Impl>
511void
512DefaultCommit<Impl>::generateTCEvent(ThreadID tid)
513{
514    assert(!trapInFlight[tid]);
515    DPRINTF(Commit, "Generating TC squash event for [tid:%i]\n", tid);
516
517    tcSquash[tid] = true;
518}
519
520template <class Impl>
521void
522DefaultCommit<Impl>::squashAll(ThreadID tid)
523{
524    // If we want to include the squashing instruction in the squash,
525    // then use one older sequence number.
526    // Hopefully this doesn't mess things up.  Basically I want to squash
527    // all instructions of this thread.
528    InstSeqNum squashed_inst = rob->isEmpty() ?
529        lastCommitedSeqNum[tid] : rob->readHeadInst(tid)->seqNum - 1;
530
531    // All younger instructions will be squashed. Set the sequence
532    // number as the youngest instruction in the ROB (0 in this case.
533    // Hopefully nothing breaks.)
534    youngestSeqNum[tid] = lastCommitedSeqNum[tid];
535
536    rob->squash(squashed_inst, tid);
537    changedROBNumEntries[tid] = true;
538
539    // Send back the sequence number of the squashed instruction.
540    toIEW->commitInfo[tid].doneSeqNum = squashed_inst;
541
542    // Send back the squash signal to tell stages that they should
543    // squash.
544    toIEW->commitInfo[tid].squash = true;
545
546    // Send back the rob squashing signal so other stages know that
547    // the ROB is in the process of squashing.
548    toIEW->commitInfo[tid].robSquashing = true;
549
550    toIEW->commitInfo[tid].mispredictInst = NULL;
551    toIEW->commitInfo[tid].squashInst = NULL;
552
553    toIEW->commitInfo[tid].pc = pc[tid];
554}
555
556template <class Impl>
557void
558DefaultCommit<Impl>::squashFromTrap(ThreadID tid)
559{
560    squashAll(tid);
561
562    DPRINTF(Commit, "Squashing from trap, restarting at PC %s\n", pc[tid]);
563
564    thread[tid]->trapPending = false;
565    thread[tid]->inSyscall = false;
566    trapInFlight[tid] = false;
567
568    trapSquash[tid] = false;
569
570    commitStatus[tid] = ROBSquashing;
571    cpu->activityThisCycle();
572}
573
574template <class Impl>
575void
576DefaultCommit<Impl>::squashFromTC(ThreadID tid)
577{
578    squashAll(tid);
579
580    DPRINTF(Commit, "Squashing from TC, restarting at PC %s\n", pc[tid]);
581
582    thread[tid]->inSyscall = false;
583    assert(!thread[tid]->trapPending);
584
585    commitStatus[tid] = ROBSquashing;
586    cpu->activityThisCycle();
587
588    tcSquash[tid] = false;
589}
590
591template <class Impl>
592void
593DefaultCommit<Impl>::squashAfter(ThreadID tid, DynInstPtr &head_inst,
594        uint64_t squash_after_seq_num)
595{
596    youngestSeqNum[tid] = squash_after_seq_num;
597
598    rob->squash(squash_after_seq_num, tid);
599    changedROBNumEntries[tid] = true;
600
601    // Send back the sequence number of the squashed instruction.
602    toIEW->commitInfo[tid].doneSeqNum = squash_after_seq_num;
603
604    toIEW->commitInfo[tid].squashInst = head_inst;
605    // Send back the squash signal to tell stages that they should squash.
606    toIEW->commitInfo[tid].squash = true;
607
608    // Send back the rob squashing signal so other stages know that
609    // the ROB is in the process of squashing.
610    toIEW->commitInfo[tid].robSquashing = true;
611
612    toIEW->commitInfo[tid].mispredictInst = NULL;
613
614    toIEW->commitInfo[tid].pc = pc[tid];
615    DPRINTF(Commit, "Executing squash after for [tid:%i] inst [sn:%lli]\n",
616            tid, squash_after_seq_num);
617    commitStatus[tid] = ROBSquashing;
618}
619
620template <class Impl>
621void
622DefaultCommit<Impl>::tick()
623{
624    wroteToTimeBuffer = false;
625    _nextStatus = Inactive;
626
627    if (drainPending && rob->isEmpty() && !iewStage->hasStoresToWB()) {
628        cpu->signalDrained();
629        drainPending = false;
630        return;
631    }
632
633    if (activeThreads->empty())
634        return;
635
636    list<ThreadID>::iterator threads = activeThreads->begin();
637    list<ThreadID>::iterator end = activeThreads->end();
638
639    // Check if any of the threads are done squashing.  Change the
640    // status if they are done.
641    while (threads != end) {
642        ThreadID tid = *threads++;
643
644        // Clear the bit saying if the thread has committed stores
645        // this cycle.
646        committedStores[tid] = false;
647
648        if (commitStatus[tid] == ROBSquashing) {
649
650            if (rob->isDoneSquashing(tid)) {
651                commitStatus[tid] = Running;
652            } else {
653                DPRINTF(Commit,"[tid:%u]: Still Squashing, cannot commit any"
654                        " insts this cycle.\n", tid);
655                rob->doSquash(tid);
656                toIEW->commitInfo[tid].robSquashing = true;
657                wroteToTimeBuffer = true;
658            }
659        }
660    }
661
662    commit();
663
664    markCompletedInsts();
665
666    threads = activeThreads->begin();
667
668    while (threads != end) {
669        ThreadID tid = *threads++;
670
671        if (!rob->isEmpty(tid) && rob->readHeadInst(tid)->readyToCommit()) {
672            // The ROB has more instructions it can commit. Its next status
673            // will be active.
674            _nextStatus = Active;
675
676            DynInstPtr inst = rob->readHeadInst(tid);
677
678            DPRINTF(Commit,"[tid:%i]: Instruction [sn:%lli] PC %s is head of"
679                    " ROB and ready to commit\n",
680                    tid, inst->seqNum, inst->pcState());
681
682        } else if (!rob->isEmpty(tid)) {
683            DynInstPtr inst = rob->readHeadInst(tid);
684
685            DPRINTF(Commit,"[tid:%i]: Can't commit, Instruction [sn:%lli] PC "
686                    "%s is head of ROB and not ready\n",
687                    tid, inst->seqNum, inst->pcState());
688        }
689
690        DPRINTF(Commit, "[tid:%i]: ROB has %d insts & %d free entries.\n",
691                tid, rob->countInsts(tid), rob->numFreeEntries(tid));
692    }
693
694
695    if (wroteToTimeBuffer) {
696        DPRINTF(Activity, "Activity This Cycle.\n");
697        cpu->activityThisCycle();
698    }
699
700    updateStatus();
701}
702
703template <class Impl>
704void
705DefaultCommit<Impl>::handleInterrupt()
706{
707    // Verify that we still have an interrupt to handle
708    if (!cpu->checkInterrupts(cpu->tcBase(0))) {
709        DPRINTF(Commit, "Pending interrupt is cleared by master before "
710                "it got handled. Restart fetching from the orig path.\n");
711        toIEW->commitInfo[0].clearInterrupt = true;
712        interrupt = NoFault;
713        return;
714    }
715
716    // Wait until all in flight instructions are finished before enterring
717    // the interrupt.
718    if (canHandleInterrupts && cpu->instList.empty()) {
719        // Squash or record that I need to squash this cycle if
720        // an interrupt needed to be handled.
721        DPRINTF(Commit, "Interrupt detected.\n");
722
723        // Clear the interrupt now that it's going to be handled
724        toIEW->commitInfo[0].clearInterrupt = true;
725
726        assert(!thread[0]->inSyscall);
727        thread[0]->inSyscall = true;
728
729#if USE_CHECKER
730        if (cpu->checker) {
731            cpu->checker->handlePendingInt();
732        }
733#endif
734
735        // CPU will handle interrupt.
736        cpu->processInterrupts(interrupt);
737
738        thread[0]->inSyscall = false;
739
740        commitStatus[0] = TrapPending;
741
742        // Generate trap squash event.
743        generateTrapEvent(0);
744
745        interrupt = NoFault;
746    } else {
747        DPRINTF(Commit, "Interrupt pending: instruction is %sin "
748                "flight, ROB is %sempty\n",
749                canHandleInterrupts ? "not " : "",
750                cpu->instList.empty() ? "" : "not " );
751    }
752}
753
754template <class Impl>
755void
756DefaultCommit<Impl>::propagateInterrupt()
757{
758    if (commitStatus[0] == TrapPending || interrupt || trapSquash[0] ||
759            tcSquash[0])
760        return;
761
762    // Process interrupts if interrupts are enabled, not in PAL
763    // mode, and no other traps or external squashes are currently
764    // pending.
765    // @todo: Allow other threads to handle interrupts.
766
767    // Get any interrupt that happened
768    interrupt = cpu->getInterrupts();
769
770    // Tell fetch that there is an interrupt pending.  This
771    // will make fetch wait until it sees a non PAL-mode PC,
772    // at which point it stops fetching instructions.
773    if (interrupt != NoFault)
774        toIEW->commitInfo[0].interruptPending = true;
775}
776
777template <class Impl>
778void
779DefaultCommit<Impl>::commit()
780{
781    if (FullSystem) {
782        // Check if we have a interrupt and get read to handle it
783        if (cpu->checkInterrupts(cpu->tcBase(0)))
784            propagateInterrupt();
785    }
786
787    ////////////////////////////////////
788    // Check for any possible squashes, handle them first
789    ////////////////////////////////////
790    list<ThreadID>::iterator threads = activeThreads->begin();
791    list<ThreadID>::iterator end = activeThreads->end();
792
793    while (threads != end) {
794        ThreadID tid = *threads++;
795
796        // Not sure which one takes priority.  I think if we have
797        // both, that's a bad sign.
798        if (trapSquash[tid] == true) {
799            assert(!tcSquash[tid]);
800            squashFromTrap(tid);
801        } else if (tcSquash[tid] == true) {
802            assert(commitStatus[tid] != TrapPending);
803            squashFromTC(tid);
804        }
805
806        // Squashed sequence number must be older than youngest valid
807        // instruction in the ROB. This prevents squashes from younger
808        // instructions overriding squashes from older instructions.
809        if (fromIEW->squash[tid] &&
810            commitStatus[tid] != TrapPending &&
811            fromIEW->squashedSeqNum[tid] <= youngestSeqNum[tid]) {
812
813            if (fromIEW->mispredictInst[tid]) {
814                DPRINTF(Commit,
815                    "[tid:%i]: Squashing due to branch mispred PC:%#x [sn:%i]\n",
816                    tid,
817                    fromIEW->mispredictInst[tid]->instAddr(),
818                    fromIEW->squashedSeqNum[tid]);
819            } else {
820                DPRINTF(Commit,
821                    "[tid:%i]: Squashing due to order violation [sn:%i]\n",
822                    tid, fromIEW->squashedSeqNum[tid]);
823            }
824
825            DPRINTF(Commit, "[tid:%i]: Redirecting to PC %#x\n",
826                    tid,
827                    fromIEW->pc[tid].nextInstAddr());
828
829            commitStatus[tid] = ROBSquashing;
830
831            // If we want to include the squashing instruction in the squash,
832            // then use one older sequence number.
833            InstSeqNum squashed_inst = fromIEW->squashedSeqNum[tid];
834
835            if (fromIEW->includeSquashInst[tid] == true) {
836                squashed_inst--;
837            }
838
839            // All younger instructions will be squashed. Set the sequence
840            // number as the youngest instruction in the ROB.
841            youngestSeqNum[tid] = squashed_inst;
842
843            rob->squash(squashed_inst, tid);
844            changedROBNumEntries[tid] = true;
845
846            toIEW->commitInfo[tid].doneSeqNum = squashed_inst;
847
848            toIEW->commitInfo[tid].squash = true;
849
850            // Send back the rob squashing signal so other stages know that
851            // the ROB is in the process of squashing.
852            toIEW->commitInfo[tid].robSquashing = true;
853
854            toIEW->commitInfo[tid].mispredictInst =
855                fromIEW->mispredictInst[tid];
856            toIEW->commitInfo[tid].branchTaken =
857                fromIEW->branchTaken[tid];
858            toIEW->commitInfo[tid].squashInst =
859                                    rob->findInst(tid, squashed_inst);
860
861            toIEW->commitInfo[tid].pc = fromIEW->pc[tid];
862
863            if (toIEW->commitInfo[tid].mispredictInst) {
864                ++branchMispredicts;
865            }
866        }
867
868    }
869
870    setNextStatus();
871
872    if (squashCounter != numThreads) {
873        // If we're not currently squashing, then get instructions.
874        getInsts();
875
876        // Try to commit any instructions.
877        commitInsts();
878    }
879
880    //Check for any activity
881    threads = activeThreads->begin();
882
883    while (threads != end) {
884        ThreadID tid = *threads++;
885
886        if (changedROBNumEntries[tid]) {
887            toIEW->commitInfo[tid].usedROB = true;
888            toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid);
889
890            wroteToTimeBuffer = true;
891            changedROBNumEntries[tid] = false;
892            if (rob->isEmpty(tid))
893                checkEmptyROB[tid] = true;
894        }
895
896        // ROB is only considered "empty" for previous stages if: a)
897        // ROB is empty, b) there are no outstanding stores, c) IEW
898        // stage has received any information regarding stores that
899        // committed.
900        // c) is checked by making sure to not consider the ROB empty
901        // on the same cycle as when stores have been committed.
902        // @todo: Make this handle multi-cycle communication between
903        // commit and IEW.
904        if (checkEmptyROB[tid] && rob->isEmpty(tid) &&
905            !iewStage->hasStoresToWB(tid) && !committedStores[tid]) {
906            checkEmptyROB[tid] = false;
907            toIEW->commitInfo[tid].usedROB = true;
908            toIEW->commitInfo[tid].emptyROB = true;
909            toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid);
910            wroteToTimeBuffer = true;
911        }
912
913    }
914}
915
916template <class Impl>
917void
918DefaultCommit<Impl>::commitInsts()
919{
920    ////////////////////////////////////
921    // Handle commit
922    // Note that commit will be handled prior to putting new
923    // instructions in the ROB so that the ROB only tries to commit
924    // instructions it has in this current cycle, and not instructions
925    // it is writing in during this cycle.  Can't commit and squash
926    // things at the same time...
927    ////////////////////////////////////
928
929    DPRINTF(Commit, "Trying to commit instructions in the ROB.\n");
930
931    unsigned num_committed = 0;
932
933    DynInstPtr head_inst;
934
935    // Commit as many instructions as possible until the commit bandwidth
936    // limit is reached, or it becomes impossible to commit any more.
937    while (num_committed < commitWidth) {
938        // Check for any interrupt that we've already squashed for
939        // and start processing it.
940        if (interrupt != NoFault)
941            handleInterrupt();
942
943        int commit_thread = getCommittingThread();
944
945        if (commit_thread == -1 || !rob->isHeadReady(commit_thread))
946            break;
947
948        head_inst = rob->readHeadInst(commit_thread);
949
950        ThreadID tid = head_inst->threadNumber;
951
952        assert(tid == commit_thread);
953
954        DPRINTF(Commit, "Trying to commit head instruction, [sn:%i] [tid:%i]\n",
955                head_inst->seqNum, tid);
956
957        // If the head instruction is squashed, it is ready to retire
958        // (be removed from the ROB) at any time.
959        if (head_inst->isSquashed()) {
960
961            DPRINTF(Commit, "Retiring squashed instruction from "
962                    "ROB.\n");
963
964            rob->retireHead(commit_thread);
965
966            ++commitSquashedInsts;
967
968            // Record that the number of ROB entries has changed.
969            changedROBNumEntries[tid] = true;
970        } else {
971            pc[tid] = head_inst->pcState();
972
973            // Increment the total number of non-speculative instructions
974            // executed.
975            // Hack for now: it really shouldn't happen until after the
976            // commit is deemed to be successful, but this count is needed
977            // for syscalls.
978            thread[tid]->funcExeInst++;
979
980            // Try to commit the head instruction.
981            bool commit_success = commitHead(head_inst, num_committed);
982
983            if (commit_success) {
984                ++num_committed;
985
986                changedROBNumEntries[tid] = true;
987
988                // Set the doneSeqNum to the youngest committed instruction.
989                toIEW->commitInfo[tid].doneSeqNum = head_inst->seqNum;
990
991                ++commitCommittedInsts;
992
993                // To match the old model, don't count nops and instruction
994                // prefetches towards the total commit count.
995                if (!head_inst->isNop() && !head_inst->isInstPrefetch()) {
996                    cpu->instDone(tid);
997                }
998
999                if (tid == 0) {
1000                    canHandleInterrupts =  (!head_inst->isDelayedCommit()) &&
1001                                           ((THE_ISA != ALPHA_ISA) ||
1002                                             (!(pc[0].instAddr() & 0x3)));
1003                }
1004
1005                // Updates misc. registers.
1006                head_inst->updateMiscRegs();
1007
1008                cpu->traceFunctions(pc[tid].instAddr());
1009
1010                TheISA::advancePC(pc[tid], head_inst->staticInst);
1011
1012                // Keep track of the last sequence number commited
1013                lastCommitedSeqNum[tid] = head_inst->seqNum;
1014
1015                // If this is an instruction that doesn't play nicely with
1016                // others squash everything and restart fetch
1017                if (head_inst->isSquashAfter())
1018                    squashAfter(tid, head_inst, head_inst->seqNum);
1019
1020                int count = 0;
1021                Addr oldpc;
1022                // Debug statement.  Checks to make sure we're not
1023                // currently updating state while handling PC events.
1024                assert(!thread[tid]->inSyscall && !thread[tid]->trapPending);
1025                do {
1026                    oldpc = pc[tid].instAddr();
1027                    cpu->system->pcEventQueue.service(thread[tid]->getTC());
1028                    count++;
1029                } while (oldpc != pc[tid].instAddr());
1030                if (count > 1) {
1031                    DPRINTF(Commit,
1032                            "PC skip function event, stopping commit\n");
1033                    break;
1034                }
1035            } else {
1036                DPRINTF(Commit, "Unable to commit head instruction PC:%s "
1037                        "[tid:%i] [sn:%i].\n",
1038                        head_inst->pcState(), tid ,head_inst->seqNum);
1039                break;
1040            }
1041        }
1042    }
1043
1044    DPRINTF(CommitRate, "%i\n", num_committed);
1045    numCommittedDist.sample(num_committed);
1046
1047    if (num_committed == commitWidth) {
1048        commitEligibleSamples++;
1049    }
1050}
1051
1052template <class Impl>
1053bool
1054DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
1055{
1056    assert(head_inst);
1057
1058    ThreadID tid = head_inst->threadNumber;
1059
1060    // If the instruction is not executed yet, then it will need extra
1061    // handling.  Signal backwards that it should be executed.
1062    if (!head_inst->isExecuted()) {
1063        // Keep this number correct.  We have not yet actually executed
1064        // and committed this instruction.
1065        thread[tid]->funcExeInst--;
1066
1067        if (head_inst->isNonSpeculative() ||
1068            head_inst->isStoreConditional() ||
1069            head_inst->isMemBarrier() ||
1070            head_inst->isWriteBarrier()) {
1071
1072            DPRINTF(Commit, "Encountered a barrier or non-speculative "
1073                    "instruction [sn:%lli] at the head of the ROB, PC %s.\n",
1074                    head_inst->seqNum, head_inst->pcState());
1075
1076            if (inst_num > 0 || iewStage->hasStoresToWB(tid)) {
1077                DPRINTF(Commit, "Waiting for all stores to writeback.\n");
1078                return false;
1079            }
1080
1081            toIEW->commitInfo[tid].nonSpecSeqNum = head_inst->seqNum;
1082
1083            // Change the instruction so it won't try to commit again until
1084            // it is executed.
1085            head_inst->clearCanCommit();
1086
1087            ++commitNonSpecStalls;
1088
1089            return false;
1090        } else if (head_inst->isLoad()) {
1091            if (inst_num > 0 || iewStage->hasStoresToWB(tid)) {
1092                DPRINTF(Commit, "Waiting for all stores to writeback.\n");
1093                return false;
1094            }
1095
1096            assert(head_inst->uncacheable());
1097            DPRINTF(Commit, "[sn:%lli]: Uncached load, PC %s.\n",
1098                    head_inst->seqNum, head_inst->pcState());
1099
1100            // Send back the non-speculative instruction's sequence
1101            // number.  Tell the lsq to re-execute the load.
1102            toIEW->commitInfo[tid].nonSpecSeqNum = head_inst->seqNum;
1103            toIEW->commitInfo[tid].uncached = true;
1104            toIEW->commitInfo[tid].uncachedLoad = head_inst;
1105
1106            head_inst->clearCanCommit();
1107
1108            return false;
1109        } else {
1110            panic("Trying to commit un-executed instruction "
1111                  "of unknown type!\n");
1112        }
1113    }
1114
1115    if (head_inst->isThreadSync()) {
1116        // Not handled for now.
1117        panic("Thread sync instructions are not handled yet.\n");
1118    }
1119
1120    // Check if the instruction caused a fault.  If so, trap.
1121    Fault inst_fault = head_inst->getFault();
1122
1123    // Stores mark themselves as completed.
1124    if (!head_inst->isStore() && inst_fault == NoFault) {
1125        head_inst->setCompleted();
1126    }
1127
1128#if USE_CHECKER
1129    // Use checker prior to updating anything due to traps or PC
1130    // based events.
1131    if (cpu->checker) {
1132        cpu->checker->verify(head_inst);
1133    }
1134#endif
1135
1136    if (inst_fault != NoFault) {
1137        DPRINTF(Commit, "Inst [sn:%lli] PC %s has a fault\n",
1138                head_inst->seqNum, head_inst->pcState());
1139
1140        if (iewStage->hasStoresToWB(tid) || inst_num > 0) {
1141            DPRINTF(Commit, "Stores outstanding, fault must wait.\n");
1142            return false;
1143        }
1144
1145        head_inst->setCompleted();
1146
1147#if USE_CHECKER
1148        if (cpu->checker) {
1149            // Need to check the instruction before its fault is processed
1150            cpu->checker->verify(head_inst);
1151        }
1152#endif
1153
1154        assert(!thread[tid]->inSyscall);
1155
1156        // Mark that we're in state update mode so that the trap's
1157        // execution doesn't generate extra squashes.
1158        thread[tid]->inSyscall = true;
1159
1160        // Execute the trap.  Although it's slightly unrealistic in
1161        // terms of timing (as it doesn't wait for the full timing of
1162        // the trap event to complete before updating state), it's
1163        // needed to update the state as soon as possible.  This
1164        // prevents external agents from changing any specific state
1165        // that the trap need.
1166        cpu->trap(inst_fault, tid, head_inst->staticInst);
1167
1168        // Exit state update mode to avoid accidental updating.
1169        thread[tid]->inSyscall = false;
1170
1171        commitStatus[tid] = TrapPending;
1172
1173        DPRINTF(Commit, "Committing instruction with fault [sn:%lli]\n",
1174            head_inst->seqNum);
1175        if (head_inst->traceData) {
1176            if (DTRACE(ExecFaulting)) {
1177                head_inst->traceData->setFetchSeq(head_inst->seqNum);
1178                head_inst->traceData->setCPSeq(thread[tid]->numInst);
1179                head_inst->traceData->dump();
1180            }
1181            delete head_inst->traceData;
1182            head_inst->traceData = NULL;
1183        }
1184
1185        // Generate trap squash event.
1186        generateTrapEvent(tid);
1187        return false;
1188    }
1189
1190    updateComInstStats(head_inst);
1191
1192    if (FullSystem) {
1193        if (thread[tid]->profile) {
1194            thread[tid]->profilePC = head_inst->instAddr();
1195            ProfileNode *node = thread[tid]->profile->consume(
1196                    thread[tid]->getTC(), head_inst->staticInst);
1197
1198            if (node)
1199                thread[tid]->profileNode = node;
1200        }
1201        if (CPA::available()) {
1202            if (head_inst->isControl()) {
1203                ThreadContext *tc = thread[tid]->getTC();
1204                CPA::cpa()->swAutoBegin(tc, head_inst->nextInstAddr());
1205            }
1206        }
1207    }
1208    DPRINTF(Commit, "Committing instruction with [sn:%lli] PC %s\n",
1209            head_inst->seqNum, head_inst->pcState());
1210    if (head_inst->traceData) {
1211        head_inst->traceData->setFetchSeq(head_inst->seqNum);
1212        head_inst->traceData->setCPSeq(thread[tid]->numInst);
1213        head_inst->traceData->dump();
1214        delete head_inst->traceData;
1215        head_inst->traceData = NULL;
1216    }
1217
1218    // Update the commit rename map
1219    for (int i = 0; i < head_inst->numDestRegs(); i++) {
1220        renameMap[tid]->setEntry(head_inst->flattenedDestRegIdx(i),
1221                                 head_inst->renamedDestRegIdx(i));
1222    }
1223
1224    // Finally clear the head ROB entry.
1225    rob->retireHead(tid);
1226
1227#if TRACING_ON
1228    // Print info needed by the pipeline activity viewer.
1229    DPRINTFR(O3PipeView, "O3PipeView:fetch:%llu:0x%08llx:%d:%llu:%s\n",
1230             head_inst->fetchTick,
1231             head_inst->instAddr(),
1232             head_inst->microPC(),
1233             head_inst->seqNum,
1234             head_inst->staticInst->disassemble(head_inst->instAddr()));
1235    DPRINTFR(O3PipeView, "O3PipeView:decode:%llu\n", head_inst->decodeTick);
1236    DPRINTFR(O3PipeView, "O3PipeView:rename:%llu\n", head_inst->renameTick);
1237    DPRINTFR(O3PipeView, "O3PipeView:dispatch:%llu\n", head_inst->dispatchTick);
1238    DPRINTFR(O3PipeView, "O3PipeView:issue:%llu\n", head_inst->issueTick);
1239    DPRINTFR(O3PipeView, "O3PipeView:complete:%llu\n", head_inst->completeTick);
1240    DPRINTFR(O3PipeView, "O3PipeView:retire:%llu\n", curTick());
1241#endif
1242
1243    // If this was a store, record it for this cycle.
1244    if (head_inst->isStore())
1245        committedStores[tid] = true;
1246
1247    // Return true to indicate that we have committed an instruction.
1248    return true;
1249}
1250
1251template <class Impl>
1252void
1253DefaultCommit<Impl>::getInsts()
1254{
1255    DPRINTF(Commit, "Getting instructions from Rename stage.\n");
1256
1257    // Read any renamed instructions and place them into the ROB.
1258    int insts_to_process = std::min((int)renameWidth, fromRename->size);
1259
1260    for (int inst_num = 0; inst_num < insts_to_process; ++inst_num) {
1261        DynInstPtr inst;
1262
1263        inst = fromRename->insts[inst_num];
1264        ThreadID tid = inst->threadNumber;
1265
1266        if (!inst->isSquashed() &&
1267            commitStatus[tid] != ROBSquashing &&
1268            commitStatus[tid] != TrapPending) {
1269            changedROBNumEntries[tid] = true;
1270
1271            DPRINTF(Commit, "Inserting PC %s [sn:%i] [tid:%i] into ROB.\n",
1272                    inst->pcState(), inst->seqNum, tid);
1273
1274            rob->insertInst(inst);
1275
1276            assert(rob->getThreadEntries(tid) <= rob->getMaxEntries(tid));
1277
1278            youngestSeqNum[tid] = inst->seqNum;
1279        } else {
1280            DPRINTF(Commit, "Instruction PC %s [sn:%i] [tid:%i] was "
1281                    "squashed, skipping.\n",
1282                    inst->pcState(), inst->seqNum, tid);
1283        }
1284    }
1285}
1286
1287template <class Impl>
1288void
1289DefaultCommit<Impl>::skidInsert()
1290{
1291    DPRINTF(Commit, "Attempting to any instructions from rename into "
1292            "skidBuffer.\n");
1293
1294    for (int inst_num = 0; inst_num < fromRename->size; ++inst_num) {
1295        DynInstPtr inst = fromRename->insts[inst_num];
1296
1297        if (!inst->isSquashed()) {
1298            DPRINTF(Commit, "Inserting PC %s [sn:%i] [tid:%i] into ",
1299                    "skidBuffer.\n", inst->pcState(), inst->seqNum,
1300                    inst->threadNumber);
1301            skidBuffer.push(inst);
1302        } else {
1303            DPRINTF(Commit, "Instruction PC %s [sn:%i] [tid:%i] was "
1304                    "squashed, skipping.\n",
1305                    inst->pcState(), inst->seqNum, inst->threadNumber);
1306        }
1307    }
1308}
1309
1310template <class Impl>
1311void
1312DefaultCommit<Impl>::markCompletedInsts()
1313{
1314    // Grab completed insts out of the IEW instruction queue, and mark
1315    // instructions completed within the ROB.
1316    for (int inst_num = 0;
1317         inst_num < fromIEW->size && fromIEW->insts[inst_num];
1318         ++inst_num)
1319    {
1320        if (!fromIEW->insts[inst_num]->isSquashed()) {
1321            DPRINTF(Commit, "[tid:%i]: Marking PC %s, [sn:%lli] ready "
1322                    "within ROB.\n",
1323                    fromIEW->insts[inst_num]->threadNumber,
1324                    fromIEW->insts[inst_num]->pcState(),
1325                    fromIEW->insts[inst_num]->seqNum);
1326
1327            // Mark the instruction as ready to commit.
1328            fromIEW->insts[inst_num]->setCanCommit();
1329        }
1330    }
1331}
1332
1333template <class Impl>
1334bool
1335DefaultCommit<Impl>::robDoneSquashing()
1336{
1337    list<ThreadID>::iterator threads = activeThreads->begin();
1338    list<ThreadID>::iterator end = activeThreads->end();
1339
1340    while (threads != end) {
1341        ThreadID tid = *threads++;
1342
1343        if (!rob->isDoneSquashing(tid))
1344            return false;
1345    }
1346
1347    return true;
1348}
1349
1350template <class Impl>
1351void
1352DefaultCommit<Impl>::updateComInstStats(DynInstPtr &inst)
1353{
1354    ThreadID tid = inst->threadNumber;
1355
1356    //
1357    //  Pick off the software prefetches
1358    //
1359#ifdef TARGET_ALPHA
1360    if (inst->isDataPrefetch()) {
1361        statComSwp[tid]++;
1362    } else {
1363        statComInst[tid]++;
1364    }
1365#else
1366    statComInst[tid]++;
1367#endif
1368
1369    //
1370    //  Control Instructions
1371    //
1372    if (inst->isControl())
1373        statComBranches[tid]++;
1374
1375    //
1376    //  Memory references
1377    //
1378    if (inst->isMemRef()) {
1379        statComRefs[tid]++;
1380
1381        if (inst->isLoad()) {
1382            statComLoads[tid]++;
1383        }
1384    }
1385
1386    if (inst->isMemBarrier()) {
1387        statComMembars[tid]++;
1388    }
1389
1390    // Integer Instruction
1391    if (inst->isInteger())
1392        statComInteger[tid]++;
1393
1394    // Floating Point Instruction
1395    if (inst->isFloating())
1396        statComFloating[tid]++;
1397
1398    // Function Calls
1399    if (inst->isCall())
1400        statComFunctionCalls[tid]++;
1401
1402}
1403
1404////////////////////////////////////////
1405//                                    //
1406//  SMT COMMIT POLICY MAINTAINED HERE //
1407//                                    //
1408////////////////////////////////////////
1409template <class Impl>
1410ThreadID
1411DefaultCommit<Impl>::getCommittingThread()
1412{
1413    if (numThreads > 1) {
1414        switch (commitPolicy) {
1415
1416          case Aggressive:
1417            //If Policy is Aggressive, commit will call
1418            //this function multiple times per
1419            //cycle
1420            return oldestReady();
1421
1422          case RoundRobin:
1423            return roundRobin();
1424
1425          case OldestReady:
1426            return oldestReady();
1427
1428          default:
1429            return InvalidThreadID;
1430        }
1431    } else {
1432        assert(!activeThreads->empty());
1433        ThreadID tid = activeThreads->front();
1434
1435        if (commitStatus[tid] == Running ||
1436            commitStatus[tid] == Idle ||
1437            commitStatus[tid] == FetchTrapPending) {
1438            return tid;
1439        } else {
1440            return InvalidThreadID;
1441        }
1442    }
1443}
1444
1445template<class Impl>
1446ThreadID
1447DefaultCommit<Impl>::roundRobin()
1448{
1449    list<ThreadID>::iterator pri_iter = priority_list.begin();
1450    list<ThreadID>::iterator end      = priority_list.end();
1451
1452    while (pri_iter != end) {
1453        ThreadID tid = *pri_iter;
1454
1455        if (commitStatus[tid] == Running ||
1456            commitStatus[tid] == Idle ||
1457            commitStatus[tid] == FetchTrapPending) {
1458
1459            if (rob->isHeadReady(tid)) {
1460                priority_list.erase(pri_iter);
1461                priority_list.push_back(tid);
1462
1463                return tid;
1464            }
1465        }
1466
1467        pri_iter++;
1468    }
1469
1470    return InvalidThreadID;
1471}
1472
1473template<class Impl>
1474ThreadID
1475DefaultCommit<Impl>::oldestReady()
1476{
1477    unsigned oldest = 0;
1478    bool first = true;
1479
1480    list<ThreadID>::iterator threads = activeThreads->begin();
1481    list<ThreadID>::iterator end = activeThreads->end();
1482
1483    while (threads != end) {
1484        ThreadID tid = *threads++;
1485
1486        if (!rob->isEmpty(tid) &&
1487            (commitStatus[tid] == Running ||
1488             commitStatus[tid] == Idle ||
1489             commitStatus[tid] == FetchTrapPending)) {
1490
1491            if (rob->isHeadReady(tid)) {
1492
1493                DynInstPtr head_inst = rob->readHeadInst(tid);
1494
1495                if (first) {
1496                    oldest = tid;
1497                    first = false;
1498                } else if (head_inst->seqNum < oldest) {
1499                    oldest = tid;
1500                }
1501            }
1502        }
1503    }
1504
1505    if (!first) {
1506        return oldest;
1507    } else {
1508        return InvalidThreadID;
1509    }
1510}
1511