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