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