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