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