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