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