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