commit_impl.hh revision 7720:65d338a8dba4
114039Sstacze01@arm.com/*
214039Sstacze01@arm.com * Copyright (c) 2004-2006 The Regents of The University of Michigan
314039Sstacze01@arm.com * All rights reserved.
414039Sstacze01@arm.com *
514039Sstacze01@arm.com * Redistribution and use in source and binary forms, with or without
614039Sstacze01@arm.com * modification, are permitted provided that the following conditions are
714039Sstacze01@arm.com * met: redistributions of source code must retain the above copyright
814039Sstacze01@arm.com * notice, this list of conditions and the following disclaimer;
914039Sstacze01@arm.com * redistributions in binary form must reproduce the above copyright
1014039Sstacze01@arm.com * notice, this list of conditions and the following disclaimer in the
1114039Sstacze01@arm.com * documentation and/or other materials provided with the distribution;
1214039Sstacze01@arm.com * neither the name of the copyright holders nor the names of its
1314039Sstacze01@arm.com * contributors may be used to endorse or promote products derived from
1414039Sstacze01@arm.com * this software without specific prior written permission.
1514039Sstacze01@arm.com *
1614039Sstacze01@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1714039Sstacze01@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1814039Sstacze01@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1914039Sstacze01@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2014039Sstacze01@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2114039Sstacze01@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2214039Sstacze01@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2314039Sstacze01@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2414039Sstacze01@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2514039Sstacze01@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2614039Sstacze01@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2714039Sstacze01@arm.com *
2814039Sstacze01@arm.com * Authors: Kevin Lim
2914039Sstacze01@arm.com *          Korey Sewell
3014039Sstacze01@arm.com */
3114039Sstacze01@arm.com
3214039Sstacze01@arm.com#include <algorithm>
3314039Sstacze01@arm.com#include <string>
3414039Sstacze01@arm.com
3514039Sstacze01@arm.com#include "arch/utility.hh"
3614039Sstacze01@arm.com#include "base/cp_annotate.hh"
3714039Sstacze01@arm.com#include "base/loader/symtab.hh"
3814039Sstacze01@arm.com#include "base/timebuf.hh"
3914039Sstacze01@arm.com#include "config/full_system.hh"
4014039Sstacze01@arm.com#include "config/the_isa.hh"
4114039Sstacze01@arm.com#include "config/use_checker.hh"
4214039Sstacze01@arm.com#include "cpu/exetrace.hh"
4314039Sstacze01@arm.com#include "cpu/o3/commit.hh"
4414039Sstacze01@arm.com#include "cpu/o3/thread_state.hh"
4514039Sstacze01@arm.com#include "params/DerivO3CPU.hh"
4614039Sstacze01@arm.com
4714039Sstacze01@arm.com#if USE_CHECKER
4814039Sstacze01@arm.com#include "cpu/checker/cpu.hh"
4914039Sstacze01@arm.com#endif
5014039Sstacze01@arm.com
5114039Sstacze01@arm.comusing namespace std;
5214039Sstacze01@arm.com
5314039Sstacze01@arm.comtemplate <class Impl>
5414039Sstacze01@arm.comDefaultCommit<Impl>::TrapEvent::TrapEvent(DefaultCommit<Impl> *_commit,
5514039Sstacze01@arm.com                                          ThreadID _tid)
5614039Sstacze01@arm.com    : Event(CPU_Tick_Pri), commit(_commit), tid(_tid)
5714039Sstacze01@arm.com{
5814039Sstacze01@arm.com    this->setFlags(AutoDelete);
5914039Sstacze01@arm.com}
6014039Sstacze01@arm.com
6114039Sstacze01@arm.comtemplate <class Impl>
6214039Sstacze01@arm.comvoid
6314039Sstacze01@arm.comDefaultCommit<Impl>::TrapEvent::process()
6414039Sstacze01@arm.com{
6514039Sstacze01@arm.com    // This will get reset by commit if it was switched out at the
6614039Sstacze01@arm.com    // time of this event processing.
6714039Sstacze01@arm.com    commit->trapSquash[tid] = true;
6814039Sstacze01@arm.com}
6914039Sstacze01@arm.com
7014039Sstacze01@arm.comtemplate <class Impl>
7114039Sstacze01@arm.comconst char *
7214039Sstacze01@arm.comDefaultCommit<Impl>::TrapEvent::description() const
7314039Sstacze01@arm.com{
7414039Sstacze01@arm.com    return "Trap";
7514039Sstacze01@arm.com}
7614039Sstacze01@arm.com
7714039Sstacze01@arm.comtemplate <class Impl>
7814039Sstacze01@arm.comDefaultCommit<Impl>::DefaultCommit(O3CPU *_cpu, DerivO3CPUParams *params)
7914039Sstacze01@arm.com    : cpu(_cpu),
8014039Sstacze01@arm.com      squashCounter(0),
8114063Sadrian.herrera@arm.com      iewToCommitDelay(params->iewToCommitDelay),
8214063Sadrian.herrera@arm.com      commitToIEWDelay(params->commitToIEWDelay),
8314063Sadrian.herrera@arm.com      renameToROBDelay(params->renameToROBDelay),
8414063Sadrian.herrera@arm.com      fetchToCommitDelay(params->commitToFetchDelay),
8514063Sadrian.herrera@arm.com      renameWidth(params->renameWidth),
8614063Sadrian.herrera@arm.com      commitWidth(params->commitWidth),
8714063Sadrian.herrera@arm.com      numThreads(params->numThreads),
8814063Sadrian.herrera@arm.com      drainPending(false),
8914063Sadrian.herrera@arm.com      switchedOut(false),
9014063Sadrian.herrera@arm.com      trapLatency(params->trapLatency)
9114063Sadrian.herrera@arm.com{
9214063Sadrian.herrera@arm.com    _status = Active;
9314063Sadrian.herrera@arm.com    _nextStatus = Inactive;
9414063Sadrian.herrera@arm.com    std::string policy = params->smtCommitPolicy;
9514063Sadrian.herrera@arm.com
9614063Sadrian.herrera@arm.com    //Convert string to lowercase
9714063Sadrian.herrera@arm.com    std::transform(policy.begin(), policy.end(), policy.begin(),
9814063Sadrian.herrera@arm.com                   (int(*)(int)) tolower);
9914039Sstacze01@arm.com
10014039Sstacze01@arm.com    //Assign commit policy
10114039Sstacze01@arm.com    if (policy == "aggressive"){
10214039Sstacze01@arm.com        commitPolicy = Aggressive;
10314039Sstacze01@arm.com
10414039Sstacze01@arm.com        DPRINTF(Commit,"Commit Policy set to Aggressive.");
10514039Sstacze01@arm.com    } else if (policy == "roundrobin"){
10614039Sstacze01@arm.com        commitPolicy = RoundRobin;
10714039Sstacze01@arm.com
10814039Sstacze01@arm.com        //Set-Up Priority List
10914039Sstacze01@arm.com        for (ThreadID tid = 0; tid < numThreads; tid++) {
11014039Sstacze01@arm.com            priority_list.push_back(tid);
11114039Sstacze01@arm.com        }
11214039Sstacze01@arm.com
11314039Sstacze01@arm.com        DPRINTF(Commit,"Commit Policy set to Round Robin.");
11414039Sstacze01@arm.com    } else if (policy == "oldestready"){
11514039Sstacze01@arm.com        commitPolicy = OldestReady;
11614039Sstacze01@arm.com
11714039Sstacze01@arm.com        DPRINTF(Commit,"Commit Policy set to Oldest Ready.");
11814039Sstacze01@arm.com    } else {
11914039Sstacze01@arm.com        assert(0 && "Invalid SMT Commit Policy. Options Are: {Aggressive,"
12014039Sstacze01@arm.com               "RoundRobin,OldestReady}");
12114039Sstacze01@arm.com    }
12214039Sstacze01@arm.com
12314039Sstacze01@arm.com    for (ThreadID tid = 0; tid < numThreads; tid++) {
12414039Sstacze01@arm.com        commitStatus[tid] = Idle;
12514039Sstacze01@arm.com        changedROBNumEntries[tid] = false;
12614039Sstacze01@arm.com        checkEmptyROB[tid] = false;
12714039Sstacze01@arm.com        trapInFlight[tid] = false;
12814039Sstacze01@arm.com        committedStores[tid] = false;
12914039Sstacze01@arm.com        trapSquash[tid] = false;
13014039Sstacze01@arm.com        tcSquash[tid] = false;
13114039Sstacze01@arm.com        pc[tid].set(0);
13214039Sstacze01@arm.com    }
13314039Sstacze01@arm.com#if FULL_SYSTEM
13414039Sstacze01@arm.com    interrupt = NoFault;
13514039Sstacze01@arm.com#endif
13614039Sstacze01@arm.com}
13714039Sstacze01@arm.com
13814039Sstacze01@arm.comtemplate <class Impl>
13914039Sstacze01@arm.comstd::string
14014039Sstacze01@arm.comDefaultCommit<Impl>::name() const
14114039Sstacze01@arm.com{
14214039Sstacze01@arm.com    return cpu->name() + ".commit";
14314039Sstacze01@arm.com}
14414039Sstacze01@arm.com
14514039Sstacze01@arm.comtemplate <class Impl>
14614039Sstacze01@arm.comvoid
14714039Sstacze01@arm.comDefaultCommit<Impl>::regStats()
14814039Sstacze01@arm.com{
14914039Sstacze01@arm.com    using namespace Stats;
15014039Sstacze01@arm.com    commitCommittedInsts
15114039Sstacze01@arm.com        .name(name() + ".commitCommittedInsts")
15214039Sstacze01@arm.com        .desc("The number of committed instructions")
15314039Sstacze01@arm.com        .prereq(commitCommittedInsts);
15414039Sstacze01@arm.com    commitSquashedInsts
15514039Sstacze01@arm.com        .name(name() + ".commitSquashedInsts")
15614039Sstacze01@arm.com        .desc("The number of squashed insts skipped by commit")
15714039Sstacze01@arm.com        .prereq(commitSquashedInsts);
15814039Sstacze01@arm.com    commitSquashEvents
15914039Sstacze01@arm.com        .name(name() + ".commitSquashEvents")
16014039Sstacze01@arm.com        .desc("The number of times commit is told to squash")
16114039Sstacze01@arm.com        .prereq(commitSquashEvents);
16214039Sstacze01@arm.com    commitNonSpecStalls
16314039Sstacze01@arm.com        .name(name() + ".commitNonSpecStalls")
16414039Sstacze01@arm.com        .desc("The number of times commit has been forced to stall to "
16514039Sstacze01@arm.com              "communicate backwards")
16614039Sstacze01@arm.com        .prereq(commitNonSpecStalls);
16714039Sstacze01@arm.com    branchMispredicts
16814039Sstacze01@arm.com        .name(name() + ".branchMispredicts")
16914039Sstacze01@arm.com        .desc("The number of times a branch was mispredicted")
17014039Sstacze01@arm.com        .prereq(branchMispredicts);
17114039Sstacze01@arm.com    numCommittedDist
17214039Sstacze01@arm.com        .init(0,commitWidth,1)
17314039Sstacze01@arm.com        .name(name() + ".COM:committed_per_cycle")
17414039Sstacze01@arm.com        .desc("Number of insts commited each cycle")
17514039Sstacze01@arm.com        .flags(Stats::pdf)
17614039Sstacze01@arm.com        ;
17714039Sstacze01@arm.com
17814039Sstacze01@arm.com    statComInst
17914039Sstacze01@arm.com        .init(cpu->numThreads)
18014039Sstacze01@arm.com        .name(name() + ".COM:count")
18114039Sstacze01@arm.com        .desc("Number of instructions committed")
18214039Sstacze01@arm.com        .flags(total)
18314039Sstacze01@arm.com        ;
18414039Sstacze01@arm.com
18514039Sstacze01@arm.com    statComSwp
18614039Sstacze01@arm.com        .init(cpu->numThreads)
18714039Sstacze01@arm.com        .name(name() + ".COM:swp_count")
18814039Sstacze01@arm.com        .desc("Number of s/w prefetches committed")
18914039Sstacze01@arm.com        .flags(total)
19014039Sstacze01@arm.com        ;
19114039Sstacze01@arm.com
19214039Sstacze01@arm.com    statComRefs
19314039Sstacze01@arm.com        .init(cpu->numThreads)
19414039Sstacze01@arm.com        .name(name() +  ".COM:refs")
19514039Sstacze01@arm.com        .desc("Number of memory references committed")
19614039Sstacze01@arm.com        .flags(total)
19714039Sstacze01@arm.com        ;
19814039Sstacze01@arm.com
19914039Sstacze01@arm.com    statComLoads
20014039Sstacze01@arm.com        .init(cpu->numThreads)
20114039Sstacze01@arm.com        .name(name() +  ".COM:loads")
20214039Sstacze01@arm.com        .desc("Number of loads committed")
20314039Sstacze01@arm.com        .flags(total)
20414039Sstacze01@arm.com        ;
20514039Sstacze01@arm.com
20614039Sstacze01@arm.com    statComMembars
20714039Sstacze01@arm.com        .init(cpu->numThreads)
20814039Sstacze01@arm.com        .name(name() +  ".COM:membars")
20914039Sstacze01@arm.com        .desc("Number of memory barriers committed")
21014039Sstacze01@arm.com        .flags(total)
21114039Sstacze01@arm.com        ;
21214039Sstacze01@arm.com
21314039Sstacze01@arm.com    statComBranches
21414039Sstacze01@arm.com        .init(cpu->numThreads)
21514039Sstacze01@arm.com        .name(name() + ".COM:branches")
21614039Sstacze01@arm.com        .desc("Number of branches committed")
21714039Sstacze01@arm.com        .flags(total)
21814039Sstacze01@arm.com        ;
21914039Sstacze01@arm.com
22014039Sstacze01@arm.com    commitEligible
22114039Sstacze01@arm.com        .init(cpu->numThreads)
22214039Sstacze01@arm.com        .name(name() + ".COM:bw_limited")
22314039Sstacze01@arm.com        .desc("number of insts not committed due to BW limits")
22414039Sstacze01@arm.com        .flags(total)
22514039Sstacze01@arm.com        ;
22614039Sstacze01@arm.com
22714039Sstacze01@arm.com    commitEligibleSamples
22814039Sstacze01@arm.com        .name(name() + ".COM:bw_lim_events")
22914039Sstacze01@arm.com        .desc("number cycles where commit BW limit reached")
23014039Sstacze01@arm.com        ;
23114039Sstacze01@arm.com}
23214039Sstacze01@arm.com
23314039Sstacze01@arm.comtemplate <class Impl>
23414039Sstacze01@arm.comvoid
23514039Sstacze01@arm.comDefaultCommit<Impl>::setThreads(std::vector<Thread *> &threads)
23614039Sstacze01@arm.com{
23714039Sstacze01@arm.com    thread = threads;
23814039Sstacze01@arm.com}
23914039Sstacze01@arm.com
24014039Sstacze01@arm.comtemplate <class Impl>
24114039Sstacze01@arm.comvoid
24214039Sstacze01@arm.comDefaultCommit<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
24314039Sstacze01@arm.com{
24414039Sstacze01@arm.com    timeBuffer = tb_ptr;
24514039Sstacze01@arm.com
24614039Sstacze01@arm.com    // Setup wire to send information back to IEW.
24714039Sstacze01@arm.com    toIEW = timeBuffer->getWire(0);
24814039Sstacze01@arm.com
24914039Sstacze01@arm.com    // Setup wire to read data from IEW (for the ROB).
25014039Sstacze01@arm.com    robInfoFromIEW = timeBuffer->getWire(-iewToCommitDelay);
25114039Sstacze01@arm.com}
25214039Sstacze01@arm.com
25314039Sstacze01@arm.comtemplate <class Impl>
25414039Sstacze01@arm.comvoid
25514039Sstacze01@arm.comDefaultCommit<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr)
25614039Sstacze01@arm.com{
25714039Sstacze01@arm.com    fetchQueue = fq_ptr;
25814039Sstacze01@arm.com
25914039Sstacze01@arm.com    // Setup wire to get instructions from rename (for the ROB).
26014039Sstacze01@arm.com    fromFetch = fetchQueue->getWire(-fetchToCommitDelay);
26114039Sstacze01@arm.com}
26214039Sstacze01@arm.com
26314039Sstacze01@arm.comtemplate <class Impl>
26414039Sstacze01@arm.comvoid
26514039Sstacze01@arm.comDefaultCommit<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
26614039Sstacze01@arm.com{
26714039Sstacze01@arm.com    renameQueue = rq_ptr;
26814039Sstacze01@arm.com
26914039Sstacze01@arm.com    // Setup wire to get instructions from rename (for the ROB).
27014039Sstacze01@arm.com    fromRename = renameQueue->getWire(-renameToROBDelay);
27114039Sstacze01@arm.com}
27214039Sstacze01@arm.com
27314039Sstacze01@arm.comtemplate <class Impl>
27414039Sstacze01@arm.comvoid
27514039Sstacze01@arm.comDefaultCommit<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
27614039Sstacze01@arm.com{
27714039Sstacze01@arm.com    iewQueue = iq_ptr;
27814039Sstacze01@arm.com
27914039Sstacze01@arm.com    // Setup wire to get instructions from IEW.
28014039Sstacze01@arm.com    fromIEW = iewQueue->getWire(-iewToCommitDelay);
28114039Sstacze01@arm.com}
28214039Sstacze01@arm.com
28314039Sstacze01@arm.comtemplate <class Impl>
28414039Sstacze01@arm.comvoid
28514039Sstacze01@arm.comDefaultCommit<Impl>::setIEWStage(IEW *iew_stage)
28614039Sstacze01@arm.com{
28714039Sstacze01@arm.com    iewStage = iew_stage;
28814039Sstacze01@arm.com}
28914039Sstacze01@arm.com
29014039Sstacze01@arm.comtemplate<class Impl>
29114039Sstacze01@arm.comvoid
29214039Sstacze01@arm.comDefaultCommit<Impl>::setActiveThreads(list<ThreadID> *at_ptr)
29314039Sstacze01@arm.com{
29414039Sstacze01@arm.com    activeThreads = at_ptr;
29514039Sstacze01@arm.com}
29614039Sstacze01@arm.com
29714039Sstacze01@arm.comtemplate <class Impl>
29814039Sstacze01@arm.comvoid
29914039Sstacze01@arm.comDefaultCommit<Impl>::setRenameMap(RenameMap rm_ptr[])
30014039Sstacze01@arm.com{
30114039Sstacze01@arm.com    for (ThreadID tid = 0; tid < numThreads; tid++)
30214039Sstacze01@arm.com        renameMap[tid] = &rm_ptr[tid];
30314039Sstacze01@arm.com}
30414039Sstacze01@arm.com
30514039Sstacze01@arm.comtemplate <class Impl>
30614039Sstacze01@arm.comvoid
30714039Sstacze01@arm.comDefaultCommit<Impl>::setROB(ROB *rob_ptr)
30814039Sstacze01@arm.com{
30914039Sstacze01@arm.com    rob = rob_ptr;
31014039Sstacze01@arm.com}
31114039Sstacze01@arm.com
31214039Sstacze01@arm.comtemplate <class Impl>
31314039Sstacze01@arm.comvoid
31414039Sstacze01@arm.comDefaultCommit<Impl>::initStage()
31514039Sstacze01@arm.com{
31614039Sstacze01@arm.com    rob->setActiveThreads(activeThreads);
31714039Sstacze01@arm.com    rob->resetEntries();
31814039Sstacze01@arm.com
31914039Sstacze01@arm.com    // Broadcast the number of free entries.
32014039Sstacze01@arm.com    for (ThreadID tid = 0; tid < numThreads; tid++) {
32114039Sstacze01@arm.com        toIEW->commitInfo[tid].usedROB = true;
32214039Sstacze01@arm.com        toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid);
32314039Sstacze01@arm.com        toIEW->commitInfo[tid].emptyROB = true;
32414039Sstacze01@arm.com    }
32514039Sstacze01@arm.com
32614039Sstacze01@arm.com    // Commit must broadcast the number of free entries it has at the
32714039Sstacze01@arm.com    // start of the simulation, so it starts as active.
32814039Sstacze01@arm.com    cpu->activateStage(O3CPU::CommitIdx);
32914039Sstacze01@arm.com
33014039Sstacze01@arm.com    cpu->activityThisCycle();
33114039Sstacze01@arm.com    trapLatency = cpu->ticks(trapLatency);
33214039Sstacze01@arm.com}
33314039Sstacze01@arm.com
33414039Sstacze01@arm.comtemplate <class Impl>
33514039Sstacze01@arm.combool
33614039Sstacze01@arm.comDefaultCommit<Impl>::drain()
33714039Sstacze01@arm.com{
33814039Sstacze01@arm.com    drainPending = true;
33914039Sstacze01@arm.com
34014039Sstacze01@arm.com    return false;
34114039Sstacze01@arm.com}
34214039Sstacze01@arm.com
34314039Sstacze01@arm.comtemplate <class Impl>
34414039Sstacze01@arm.comvoid
34514039Sstacze01@arm.comDefaultCommit<Impl>::switchOut()
34614039Sstacze01@arm.com{
34714039Sstacze01@arm.com    switchedOut = true;
34814039Sstacze01@arm.com    drainPending = false;
34914039Sstacze01@arm.com    rob->switchOut();
35014039Sstacze01@arm.com}
35114039Sstacze01@arm.com
35214039Sstacze01@arm.comtemplate <class Impl>
35314039Sstacze01@arm.comvoid
35414039Sstacze01@arm.comDefaultCommit<Impl>::resume()
35514039Sstacze01@arm.com{
35614039Sstacze01@arm.com    drainPending = false;
35714039Sstacze01@arm.com}
35814039Sstacze01@arm.com
35914039Sstacze01@arm.comtemplate <class Impl>
36014039Sstacze01@arm.comvoid
36114039Sstacze01@arm.comDefaultCommit<Impl>::takeOverFrom()
36214039Sstacze01@arm.com{
36314039Sstacze01@arm.com    switchedOut = false;
36414039Sstacze01@arm.com    _status = Active;
36514039Sstacze01@arm.com    _nextStatus = Inactive;
36614039Sstacze01@arm.com    for (ThreadID tid = 0; tid < numThreads; tid++) {
36714039Sstacze01@arm.com        commitStatus[tid] = Idle;
36814039Sstacze01@arm.com        changedROBNumEntries[tid] = false;
36914039Sstacze01@arm.com        trapSquash[tid] = false;
37014039Sstacze01@arm.com        tcSquash[tid] = false;
37114039Sstacze01@arm.com    }
37214039Sstacze01@arm.com    squashCounter = 0;
37314039Sstacze01@arm.com    rob->takeOverFrom();
37414039Sstacze01@arm.com}
37514039Sstacze01@arm.com
37614039Sstacze01@arm.comtemplate <class Impl>
37714039Sstacze01@arm.comvoid
37814039Sstacze01@arm.comDefaultCommit<Impl>::updateStatus()
37914039Sstacze01@arm.com{
38014039Sstacze01@arm.com    // reset ROB changed variable
38114039Sstacze01@arm.com    list<ThreadID>::iterator threads = activeThreads->begin();
38214039Sstacze01@arm.com    list<ThreadID>::iterator end = activeThreads->end();
38314039Sstacze01@arm.com
38414039Sstacze01@arm.com    while (threads != end) {
38514039Sstacze01@arm.com        ThreadID tid = *threads++;
38614039Sstacze01@arm.com
38714039Sstacze01@arm.com        changedROBNumEntries[tid] = false;
38814039Sstacze01@arm.com
38914039Sstacze01@arm.com        // Also check if any of the threads has a trap pending
39014039Sstacze01@arm.com        if (commitStatus[tid] == TrapPending ||
39114039Sstacze01@arm.com            commitStatus[tid] == FetchTrapPending) {
39214039Sstacze01@arm.com            _nextStatus = Active;
39314039Sstacze01@arm.com        }
39414039Sstacze01@arm.com    }
39514039Sstacze01@arm.com
39614039Sstacze01@arm.com    if (_nextStatus == Inactive && _status == Active) {
39714039Sstacze01@arm.com        DPRINTF(Activity, "Deactivating stage.\n");
39814039Sstacze01@arm.com        cpu->deactivateStage(O3CPU::CommitIdx);
39914039Sstacze01@arm.com    } else if (_nextStatus == Active && _status == Inactive) {
40014039Sstacze01@arm.com        DPRINTF(Activity, "Activating stage.\n");
40114039Sstacze01@arm.com        cpu->activateStage(O3CPU::CommitIdx);
40214039Sstacze01@arm.com    }
40314039Sstacze01@arm.com
40414039Sstacze01@arm.com    _status = _nextStatus;
40514039Sstacze01@arm.com}
40614039Sstacze01@arm.com
40714039Sstacze01@arm.comtemplate <class Impl>
40814039Sstacze01@arm.comvoid
40914039Sstacze01@arm.comDefaultCommit<Impl>::setNextStatus()
41014039Sstacze01@arm.com{
41114039Sstacze01@arm.com    int squashes = 0;
41214039Sstacze01@arm.com
41314039Sstacze01@arm.com    list<ThreadID>::iterator threads = activeThreads->begin();
41414039Sstacze01@arm.com    list<ThreadID>::iterator end = activeThreads->end();
41514039Sstacze01@arm.com
41614039Sstacze01@arm.com    while (threads != end) {
41714039Sstacze01@arm.com        ThreadID tid = *threads++;
41814039Sstacze01@arm.com
41914039Sstacze01@arm.com        if (commitStatus[tid] == ROBSquashing) {
42014039Sstacze01@arm.com            squashes++;
42114039Sstacze01@arm.com        }
42214039Sstacze01@arm.com    }
42314039Sstacze01@arm.com
42414039Sstacze01@arm.com    squashCounter = squashes;
42514039Sstacze01@arm.com
42614039Sstacze01@arm.com    // If commit is currently squashing, then it will have activity for the
42714039Sstacze01@arm.com    // next cycle. Set its next status as active.
42814039Sstacze01@arm.com    if (squashCounter) {
42914039Sstacze01@arm.com        _nextStatus = Active;
43014039Sstacze01@arm.com    }
43114039Sstacze01@arm.com}
43214039Sstacze01@arm.com
43314039Sstacze01@arm.comtemplate <class Impl>
43414039Sstacze01@arm.combool
43514039Sstacze01@arm.comDefaultCommit<Impl>::changedROBEntries()
43614039Sstacze01@arm.com{
43714039Sstacze01@arm.com    list<ThreadID>::iterator threads = activeThreads->begin();
43814039Sstacze01@arm.com    list<ThreadID>::iterator end = activeThreads->end();
43914039Sstacze01@arm.com
44014039Sstacze01@arm.com    while (threads != end) {
44114039Sstacze01@arm.com        ThreadID tid = *threads++;
44214039Sstacze01@arm.com
44314039Sstacze01@arm.com        if (changedROBNumEntries[tid]) {
44414039Sstacze01@arm.com            return true;
44514039Sstacze01@arm.com        }
44614039Sstacze01@arm.com    }
44714039Sstacze01@arm.com
44814039Sstacze01@arm.com    return false;
44914039Sstacze01@arm.com}
45014039Sstacze01@arm.com
45114039Sstacze01@arm.comtemplate <class Impl>
45214039Sstacze01@arm.comsize_t
45314039Sstacze01@arm.comDefaultCommit<Impl>::numROBFreeEntries(ThreadID tid)
45414039Sstacze01@arm.com{
45514039Sstacze01@arm.com    return rob->numFreeEntries(tid);
45614039Sstacze01@arm.com}
45714039Sstacze01@arm.com
45814039Sstacze01@arm.comtemplate <class Impl>
45914039Sstacze01@arm.comvoid
46014039Sstacze01@arm.comDefaultCommit<Impl>::generateTrapEvent(ThreadID tid)
46114039Sstacze01@arm.com{
46214039Sstacze01@arm.com    DPRINTF(Commit, "Generating trap event for [tid:%i]\n", tid);
46314039Sstacze01@arm.com
46414039Sstacze01@arm.com    TrapEvent *trap = new TrapEvent(this, tid);
46514039Sstacze01@arm.com
46614039Sstacze01@arm.com    cpu->schedule(trap, curTick + trapLatency);
46714039Sstacze01@arm.com    trapInFlight[tid] = true;
46814039Sstacze01@arm.com}
46914039Sstacze01@arm.com
47014039Sstacze01@arm.comtemplate <class Impl>
47114039Sstacze01@arm.comvoid
47214039Sstacze01@arm.comDefaultCommit<Impl>::generateTCEvent(ThreadID tid)
47314039Sstacze01@arm.com{
47414039Sstacze01@arm.com    assert(!trapInFlight[tid]);
47514039Sstacze01@arm.com    DPRINTF(Commit, "Generating TC squash event for [tid:%i]\n", tid);
47614039Sstacze01@arm.com
47714039Sstacze01@arm.com    tcSquash[tid] = true;
47814039Sstacze01@arm.com}
47914039Sstacze01@arm.com
48014039Sstacze01@arm.comtemplate <class Impl>
48114039Sstacze01@arm.comvoid
48214039Sstacze01@arm.comDefaultCommit<Impl>::squashAll(ThreadID tid)
48314039Sstacze01@arm.com{
48414039Sstacze01@arm.com    // If we want to include the squashing instruction in the squash,
48514039Sstacze01@arm.com    // then use one older sequence number.
48614039Sstacze01@arm.com    // Hopefully this doesn't mess things up.  Basically I want to squash
48714039Sstacze01@arm.com    // all instructions of this thread.
48814039Sstacze01@arm.com    InstSeqNum squashed_inst = rob->isEmpty() ?
48914039Sstacze01@arm.com        0 : rob->readHeadInst(tid)->seqNum - 1;
49014039Sstacze01@arm.com
49114039Sstacze01@arm.com    // All younger instructions will be squashed. Set the sequence
49214039Sstacze01@arm.com    // number as the youngest instruction in the ROB (0 in this case.
49314039Sstacze01@arm.com    // Hopefully nothing breaks.)
49414039Sstacze01@arm.com    youngestSeqNum[tid] = 0;
49514039Sstacze01@arm.com
49614039Sstacze01@arm.com    rob->squash(squashed_inst, tid);
49714039Sstacze01@arm.com    changedROBNumEntries[tid] = true;
49814039Sstacze01@arm.com
49914039Sstacze01@arm.com    // Send back the sequence number of the squashed instruction.
50014039Sstacze01@arm.com    toIEW->commitInfo[tid].doneSeqNum = squashed_inst;
50114039Sstacze01@arm.com
50214039Sstacze01@arm.com    // Send back the squash signal to tell stages that they should
50314039Sstacze01@arm.com    // squash.
50414039Sstacze01@arm.com    toIEW->commitInfo[tid].squash = true;
50514039Sstacze01@arm.com
50614039Sstacze01@arm.com    // Send back the rob squashing signal so other stages know that
50714039Sstacze01@arm.com    // the ROB is in the process of squashing.
50814039Sstacze01@arm.com    toIEW->commitInfo[tid].robSquashing = true;
50914039Sstacze01@arm.com
51014039Sstacze01@arm.com    toIEW->commitInfo[tid].branchMispredict = false;
51114039Sstacze01@arm.com
51214039Sstacze01@arm.com    toIEW->commitInfo[tid].pc = pc[tid];
51314039Sstacze01@arm.com}
51414039Sstacze01@arm.com
51514039Sstacze01@arm.comtemplate <class Impl>
51614039Sstacze01@arm.comvoid
51714039Sstacze01@arm.comDefaultCommit<Impl>::squashFromTrap(ThreadID tid)
51814039Sstacze01@arm.com{
51914039Sstacze01@arm.com    squashAll(tid);
52014039Sstacze01@arm.com
52114039Sstacze01@arm.com    DPRINTF(Commit, "Squashing from trap, restarting at PC %s\n", pc[tid]);
52214039Sstacze01@arm.com
52314039Sstacze01@arm.com    thread[tid]->trapPending = false;
52414039Sstacze01@arm.com    thread[tid]->inSyscall = false;
52514039Sstacze01@arm.com    trapInFlight[tid] = false;
52614039Sstacze01@arm.com
52714039Sstacze01@arm.com    trapSquash[tid] = false;
52814039Sstacze01@arm.com
52914039Sstacze01@arm.com    commitStatus[tid] = ROBSquashing;
53014039Sstacze01@arm.com    cpu->activityThisCycle();
53114039Sstacze01@arm.com}
53214039Sstacze01@arm.com
53314039Sstacze01@arm.comtemplate <class Impl>
53414039Sstacze01@arm.comvoid
53514039Sstacze01@arm.comDefaultCommit<Impl>::squashFromTC(ThreadID tid)
53614039Sstacze01@arm.com{
53714039Sstacze01@arm.com    squashAll(tid);
53814039Sstacze01@arm.com
53914039Sstacze01@arm.com    DPRINTF(Commit, "Squashing from TC, restarting at PC %s\n", pc[tid]);
54014039Sstacze01@arm.com
54114039Sstacze01@arm.com    thread[tid]->inSyscall = false;
54214039Sstacze01@arm.com    assert(!thread[tid]->trapPending);
54314039Sstacze01@arm.com
54414039Sstacze01@arm.com    commitStatus[tid] = ROBSquashing;
54514039Sstacze01@arm.com    cpu->activityThisCycle();
54614039Sstacze01@arm.com
54714039Sstacze01@arm.com    tcSquash[tid] = false;
54814039Sstacze01@arm.com}
54914039Sstacze01@arm.com
55014039Sstacze01@arm.comtemplate <class Impl>
55114039Sstacze01@arm.comvoid
55214039Sstacze01@arm.comDefaultCommit<Impl>::tick()
55314039Sstacze01@arm.com{
55414039Sstacze01@arm.com    wroteToTimeBuffer = false;
55514039Sstacze01@arm.com    _nextStatus = Inactive;
55614039Sstacze01@arm.com
55714039Sstacze01@arm.com    if (drainPending && rob->isEmpty() && !iewStage->hasStoresToWB()) {
55814039Sstacze01@arm.com        cpu->signalDrained();
55914039Sstacze01@arm.com        drainPending = false;
56014039Sstacze01@arm.com        return;
56114039Sstacze01@arm.com    }
56214039Sstacze01@arm.com
56314039Sstacze01@arm.com    if (activeThreads->empty())
56414039Sstacze01@arm.com        return;
56514039Sstacze01@arm.com
56614039Sstacze01@arm.com    list<ThreadID>::iterator threads = activeThreads->begin();
56714039Sstacze01@arm.com    list<ThreadID>::iterator end = activeThreads->end();
56814039Sstacze01@arm.com
56914039Sstacze01@arm.com    // Check if any of the threads are done squashing.  Change the
57014039Sstacze01@arm.com    // status if they are done.
57114039Sstacze01@arm.com    while (threads != end) {
57214039Sstacze01@arm.com        ThreadID tid = *threads++;
57314039Sstacze01@arm.com
57414039Sstacze01@arm.com        // Clear the bit saying if the thread has committed stores
57514039Sstacze01@arm.com        // this cycle.
57614039Sstacze01@arm.com        committedStores[tid] = false;
57714039Sstacze01@arm.com
57814039Sstacze01@arm.com        if (commitStatus[tid] == ROBSquashing) {
57914039Sstacze01@arm.com
58014039Sstacze01@arm.com            if (rob->isDoneSquashing(tid)) {
58114039Sstacze01@arm.com                commitStatus[tid] = Running;
58214039Sstacze01@arm.com            } else {
58314039Sstacze01@arm.com                DPRINTF(Commit,"[tid:%u]: Still Squashing, cannot commit any"
58414039Sstacze01@arm.com                        " insts this cycle.\n", tid);
58514039Sstacze01@arm.com                rob->doSquash(tid);
58614039Sstacze01@arm.com                toIEW->commitInfo[tid].robSquashing = true;
58714039Sstacze01@arm.com                wroteToTimeBuffer = true;
58814039Sstacze01@arm.com            }
58914039Sstacze01@arm.com        }
59014039Sstacze01@arm.com    }
59114039Sstacze01@arm.com
59214039Sstacze01@arm.com    commit();
59314039Sstacze01@arm.com
59414039Sstacze01@arm.com    markCompletedInsts();
59514039Sstacze01@arm.com
59614039Sstacze01@arm.com    threads = activeThreads->begin();
59714039Sstacze01@arm.com
59814039Sstacze01@arm.com    while (threads != end) {
59914039Sstacze01@arm.com        ThreadID tid = *threads++;
60014039Sstacze01@arm.com
60114039Sstacze01@arm.com        if (!rob->isEmpty(tid) && rob->readHeadInst(tid)->readyToCommit()) {
60214039Sstacze01@arm.com            // The ROB has more instructions it can commit. Its next status
60314039Sstacze01@arm.com            // will be active.
60414039Sstacze01@arm.com            _nextStatus = Active;
60514039Sstacze01@arm.com
60614039Sstacze01@arm.com            DynInstPtr inst = rob->readHeadInst(tid);
60714039Sstacze01@arm.com
60814039Sstacze01@arm.com            DPRINTF(Commit,"[tid:%i]: Instruction [sn:%lli] PC %s is head of"
60914039Sstacze01@arm.com                    " ROB and ready to commit\n",
61014039Sstacze01@arm.com                    tid, inst->seqNum, inst->pcState());
61114039Sstacze01@arm.com
61214039Sstacze01@arm.com        } else if (!rob->isEmpty(tid)) {
61314039Sstacze01@arm.com            DynInstPtr inst = rob->readHeadInst(tid);
61414039Sstacze01@arm.com
61514039Sstacze01@arm.com            DPRINTF(Commit,"[tid:%i]: Can't commit, Instruction [sn:%lli] PC "
61614039Sstacze01@arm.com                    "%s is head of ROB and not ready\n",
61714039Sstacze01@arm.com                    tid, inst->seqNum, inst->pcState());
61814039Sstacze01@arm.com        }
61914039Sstacze01@arm.com
62014039Sstacze01@arm.com        DPRINTF(Commit, "[tid:%i]: ROB has %d insts & %d free entries.\n",
62114039Sstacze01@arm.com                tid, rob->countInsts(tid), rob->numFreeEntries(tid));
62214039Sstacze01@arm.com    }
62314039Sstacze01@arm.com
62414039Sstacze01@arm.com
62514039Sstacze01@arm.com    if (wroteToTimeBuffer) {
62614039Sstacze01@arm.com        DPRINTF(Activity, "Activity This Cycle.\n");
62714039Sstacze01@arm.com        cpu->activityThisCycle();
62814039Sstacze01@arm.com    }
62914039Sstacze01@arm.com
63014039Sstacze01@arm.com    updateStatus();
63114039Sstacze01@arm.com}
63214039Sstacze01@arm.com
63314039Sstacze01@arm.com#if FULL_SYSTEM
63414039Sstacze01@arm.comtemplate <class Impl>
63514039Sstacze01@arm.comvoid
63614039Sstacze01@arm.comDefaultCommit<Impl>::handleInterrupt()
63714039Sstacze01@arm.com{
63814039Sstacze01@arm.com    if (interrupt != NoFault) {
63914039Sstacze01@arm.com        // Wait until the ROB is empty and all stores have drained in
64014039Sstacze01@arm.com        // order to enter the interrupt.
64114039Sstacze01@arm.com        if (rob->isEmpty() && !iewStage->hasStoresToWB()) {
64214039Sstacze01@arm.com            // Squash or record that I need to squash this cycle if
64314039Sstacze01@arm.com            // an interrupt needed to be handled.
64414039Sstacze01@arm.com            DPRINTF(Commit, "Interrupt detected.\n");
64514039Sstacze01@arm.com
64614039Sstacze01@arm.com            // Clear the interrupt now that it's going to be handled
64714039Sstacze01@arm.com            toIEW->commitInfo[0].clearInterrupt = true;
64814039Sstacze01@arm.com
64914039Sstacze01@arm.com            assert(!thread[0]->inSyscall);
65014039Sstacze01@arm.com            thread[0]->inSyscall = true;
65114039Sstacze01@arm.com
65214039Sstacze01@arm.com            // CPU will handle interrupt.
65314039Sstacze01@arm.com            cpu->processInterrupts(interrupt);
65414039Sstacze01@arm.com
65514039Sstacze01@arm.com            thread[0]->inSyscall = false;
65614039Sstacze01@arm.com
65714039Sstacze01@arm.com            commitStatus[0] = TrapPending;
65814039Sstacze01@arm.com
65914039Sstacze01@arm.com            // Generate trap squash event.
66014039Sstacze01@arm.com            generateTrapEvent(0);
66114039Sstacze01@arm.com
66214039Sstacze01@arm.com            interrupt = NoFault;
66314039Sstacze01@arm.com        } else {
66414039Sstacze01@arm.com            DPRINTF(Commit, "Interrupt pending, waiting for ROB to empty.\n");
66514039Sstacze01@arm.com        }
66614039Sstacze01@arm.com    } else if (commitStatus[0] != TrapPending &&
66714039Sstacze01@arm.com               cpu->checkInterrupts(cpu->tcBase(0)) &&
66814039Sstacze01@arm.com               !trapSquash[0] &&
66914039Sstacze01@arm.com               !tcSquash[0]) {
67014039Sstacze01@arm.com        // Process interrupts if interrupts are enabled, not in PAL
67114039Sstacze01@arm.com        // mode, and no other traps or external squashes are currently
67214039Sstacze01@arm.com        // pending.
67314039Sstacze01@arm.com        // @todo: Allow other threads to handle interrupts.
67414039Sstacze01@arm.com
67514039Sstacze01@arm.com        // Get any interrupt that happened
67614039Sstacze01@arm.com        interrupt = cpu->getInterrupts();
67714039Sstacze01@arm.com
67814039Sstacze01@arm.com        if (interrupt != NoFault) {
67914039Sstacze01@arm.com            // Tell fetch that there is an interrupt pending.  This
68014039Sstacze01@arm.com            // will make fetch wait until it sees a non PAL-mode PC,
68114039Sstacze01@arm.com            // at which point it stops fetching instructions.
68214039Sstacze01@arm.com            toIEW->commitInfo[0].interruptPending = true;
68314039Sstacze01@arm.com        }
68414039Sstacze01@arm.com    }
68514039Sstacze01@arm.com}
68614039Sstacze01@arm.com#endif // FULL_SYSTEM
68714039Sstacze01@arm.com
68814039Sstacze01@arm.comtemplate <class Impl>
68914039Sstacze01@arm.comvoid
69014039Sstacze01@arm.comDefaultCommit<Impl>::commit()
69114039Sstacze01@arm.com{
69214039Sstacze01@arm.com
69314039Sstacze01@arm.com#if FULL_SYSTEM
69414039Sstacze01@arm.com    // Check for any interrupt, and start processing it.  Or if we
69514039Sstacze01@arm.com    // have an outstanding interrupt and are at a point when it is
69614039Sstacze01@arm.com    // valid to take an interrupt, process it.
69714039Sstacze01@arm.com    if (cpu->checkInterrupts(cpu->tcBase(0))) {
69814039Sstacze01@arm.com        handleInterrupt();
69914039Sstacze01@arm.com    }
70014039Sstacze01@arm.com#endif // FULL_SYSTEM
70114039Sstacze01@arm.com
70214039Sstacze01@arm.com    ////////////////////////////////////
70314039Sstacze01@arm.com    // Check for any possible squashes, handle them first
70414039Sstacze01@arm.com    ////////////////////////////////////
70514039Sstacze01@arm.com    list<ThreadID>::iterator threads = activeThreads->begin();
70614039Sstacze01@arm.com    list<ThreadID>::iterator end = activeThreads->end();
70714039Sstacze01@arm.com
70814039Sstacze01@arm.com    while (threads != end) {
70914039Sstacze01@arm.com        ThreadID tid = *threads++;
71014039Sstacze01@arm.com
71114039Sstacze01@arm.com        // Not sure which one takes priority.  I think if we have
71214039Sstacze01@arm.com        // both, that's a bad sign.
71314039Sstacze01@arm.com        if (trapSquash[tid] == true) {
71414039Sstacze01@arm.com            assert(!tcSquash[tid]);
71514039Sstacze01@arm.com            squashFromTrap(tid);
71614039Sstacze01@arm.com        } else if (tcSquash[tid] == true) {
71714039Sstacze01@arm.com            assert(commitStatus[tid] != TrapPending);
71814039Sstacze01@arm.com            squashFromTC(tid);
71914039Sstacze01@arm.com        }
72014039Sstacze01@arm.com
72114039Sstacze01@arm.com        // Squashed sequence number must be older than youngest valid
72214039Sstacze01@arm.com        // instruction in the ROB. This prevents squashes from younger
72314039Sstacze01@arm.com        // instructions overriding squashes from older instructions.
72414039Sstacze01@arm.com        if (fromIEW->squash[tid] &&
72514039Sstacze01@arm.com            commitStatus[tid] != TrapPending &&
72614039Sstacze01@arm.com            fromIEW->squashedSeqNum[tid] <= youngestSeqNum[tid]) {
72714039Sstacze01@arm.com
72814039Sstacze01@arm.com            DPRINTF(Commit, "[tid:%i]: Squashing due to PC %#x [sn:%i]\n",
72914039Sstacze01@arm.com                    tid,
73014039Sstacze01@arm.com                    fromIEW->mispredPC[tid],
73114039Sstacze01@arm.com                    fromIEW->squashedSeqNum[tid]);
73214039Sstacze01@arm.com
73314039Sstacze01@arm.com            DPRINTF(Commit, "[tid:%i]: Redirecting to PC %#x\n",
73414039Sstacze01@arm.com                    tid,
73514039Sstacze01@arm.com                    fromIEW->pc[tid].nextInstAddr());
73614039Sstacze01@arm.com
73714039Sstacze01@arm.com            commitStatus[tid] = ROBSquashing;
73814039Sstacze01@arm.com
73914039Sstacze01@arm.com            // If we want to include the squashing instruction in the squash,
74014039Sstacze01@arm.com            // then use one older sequence number.
74114039Sstacze01@arm.com            InstSeqNum squashed_inst = fromIEW->squashedSeqNum[tid];
74214039Sstacze01@arm.com
74314039Sstacze01@arm.com            if (fromIEW->includeSquashInst[tid] == true) {
74414039Sstacze01@arm.com                squashed_inst--;
74514039Sstacze01@arm.com            }
74614039Sstacze01@arm.com
74714039Sstacze01@arm.com            // All younger instructions will be squashed. Set the sequence
74814039Sstacze01@arm.com            // number as the youngest instruction in the ROB.
74914039Sstacze01@arm.com            youngestSeqNum[tid] = squashed_inst;
75014039Sstacze01@arm.com
75114039Sstacze01@arm.com            rob->squash(squashed_inst, tid);
75214039Sstacze01@arm.com            changedROBNumEntries[tid] = true;
75314039Sstacze01@arm.com
75414039Sstacze01@arm.com            toIEW->commitInfo[tid].doneSeqNum = squashed_inst;
75514039Sstacze01@arm.com
75614039Sstacze01@arm.com            toIEW->commitInfo[tid].squash = true;
75714039Sstacze01@arm.com
75814039Sstacze01@arm.com            // Send back the rob squashing signal so other stages know that
75914039Sstacze01@arm.com            // the ROB is in the process of squashing.
76014039Sstacze01@arm.com            toIEW->commitInfo[tid].robSquashing = true;
76114039Sstacze01@arm.com
76214039Sstacze01@arm.com            toIEW->commitInfo[tid].branchMispredict =
76314039Sstacze01@arm.com                fromIEW->branchMispredict[tid];
76414039Sstacze01@arm.com
76514039Sstacze01@arm.com            toIEW->commitInfo[tid].branchTaken =
76614039Sstacze01@arm.com                fromIEW->branchTaken[tid];
76714039Sstacze01@arm.com
76814039Sstacze01@arm.com            toIEW->commitInfo[tid].pc = fromIEW->pc[tid];
76914039Sstacze01@arm.com
77014039Sstacze01@arm.com            toIEW->commitInfo[tid].mispredPC = fromIEW->mispredPC[tid];
77114039Sstacze01@arm.com
77214039Sstacze01@arm.com            if (toIEW->commitInfo[tid].branchMispredict) {
77314039Sstacze01@arm.com                ++branchMispredicts;
77414039Sstacze01@arm.com            }
77514039Sstacze01@arm.com        }
77614039Sstacze01@arm.com
77714039Sstacze01@arm.com    }
77814039Sstacze01@arm.com
77914039Sstacze01@arm.com    setNextStatus();
78014039Sstacze01@arm.com
78114039Sstacze01@arm.com    if (squashCounter != numThreads) {
78214039Sstacze01@arm.com        // If we're not currently squashing, then get instructions.
78314039Sstacze01@arm.com        getInsts();
78414039Sstacze01@arm.com
78514039Sstacze01@arm.com        // Try to commit any instructions.
78614039Sstacze01@arm.com        commitInsts();
78714039Sstacze01@arm.com    }
78814039Sstacze01@arm.com
78914039Sstacze01@arm.com    //Check for any activity
79014039Sstacze01@arm.com    threads = activeThreads->begin();
79114039Sstacze01@arm.com
79214039Sstacze01@arm.com    while (threads != end) {
79314039Sstacze01@arm.com        ThreadID tid = *threads++;
79414039Sstacze01@arm.com
79514039Sstacze01@arm.com        if (changedROBNumEntries[tid]) {
79614039Sstacze01@arm.com            toIEW->commitInfo[tid].usedROB = true;
79714039Sstacze01@arm.com            toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid);
79814039Sstacze01@arm.com
79914039Sstacze01@arm.com            wroteToTimeBuffer = true;
80014039Sstacze01@arm.com            changedROBNumEntries[tid] = false;
80114039Sstacze01@arm.com            if (rob->isEmpty(tid))
80214039Sstacze01@arm.com                checkEmptyROB[tid] = true;
80314039Sstacze01@arm.com        }
80414039Sstacze01@arm.com
80514039Sstacze01@arm.com        // ROB is only considered "empty" for previous stages if: a)
80614039Sstacze01@arm.com        // ROB is empty, b) there are no outstanding stores, c) IEW
80714039Sstacze01@arm.com        // stage has received any information regarding stores that
80814039Sstacze01@arm.com        // committed.
80914039Sstacze01@arm.com        // c) is checked by making sure to not consider the ROB empty
81014039Sstacze01@arm.com        // on the same cycle as when stores have been committed.
81114039Sstacze01@arm.com        // @todo: Make this handle multi-cycle communication between
81214039Sstacze01@arm.com        // commit and IEW.
81314039Sstacze01@arm.com        if (checkEmptyROB[tid] && rob->isEmpty(tid) &&
81414039Sstacze01@arm.com            !iewStage->hasStoresToWB(tid) && !committedStores[tid]) {
81514039Sstacze01@arm.com            checkEmptyROB[tid] = false;
81614039Sstacze01@arm.com            toIEW->commitInfo[tid].usedROB = true;
81714039Sstacze01@arm.com            toIEW->commitInfo[tid].emptyROB = true;
81814039Sstacze01@arm.com            toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid);
81914039Sstacze01@arm.com            wroteToTimeBuffer = true;
82014039Sstacze01@arm.com        }
82114039Sstacze01@arm.com
82214039Sstacze01@arm.com    }
82314039Sstacze01@arm.com}
82414039Sstacze01@arm.com
82514039Sstacze01@arm.comtemplate <class Impl>
82614039Sstacze01@arm.comvoid
82714039Sstacze01@arm.comDefaultCommit<Impl>::commitInsts()
82814039Sstacze01@arm.com{
82914039Sstacze01@arm.com    ////////////////////////////////////
83014039Sstacze01@arm.com    // Handle commit
83114039Sstacze01@arm.com    // Note that commit will be handled prior to putting new
83214039Sstacze01@arm.com    // instructions in the ROB so that the ROB only tries to commit
83314039Sstacze01@arm.com    // instructions it has in this current cycle, and not instructions
83414039Sstacze01@arm.com    // it is writing in during this cycle.  Can't commit and squash
83514039Sstacze01@arm.com    // things at the same time...
83614039Sstacze01@arm.com    ////////////////////////////////////
83714039Sstacze01@arm.com
83814039Sstacze01@arm.com    DPRINTF(Commit, "Trying to commit instructions in the ROB.\n");
83914039Sstacze01@arm.com
84014039Sstacze01@arm.com    unsigned num_committed = 0;
84114039Sstacze01@arm.com
84214039Sstacze01@arm.com    DynInstPtr head_inst;
84314039Sstacze01@arm.com
84414039Sstacze01@arm.com    // Commit as many instructions as possible until the commit bandwidth
84514039Sstacze01@arm.com    // limit is reached, or it becomes impossible to commit any more.
84614039Sstacze01@arm.com    while (num_committed < commitWidth) {
84714039Sstacze01@arm.com        int commit_thread = getCommittingThread();
84814039Sstacze01@arm.com
84914039Sstacze01@arm.com        if (commit_thread == -1 || !rob->isHeadReady(commit_thread))
85014039Sstacze01@arm.com            break;
85114039Sstacze01@arm.com
85214039Sstacze01@arm.com        head_inst = rob->readHeadInst(commit_thread);
85314039Sstacze01@arm.com
85414039Sstacze01@arm.com        ThreadID tid = head_inst->threadNumber;
85514039Sstacze01@arm.com
85614039Sstacze01@arm.com        assert(tid == commit_thread);
85714039Sstacze01@arm.com
85814039Sstacze01@arm.com        DPRINTF(Commit, "Trying to commit head instruction, [sn:%i] [tid:%i]\n",
85914039Sstacze01@arm.com                head_inst->seqNum, tid);
86014039Sstacze01@arm.com
86114039Sstacze01@arm.com        // If the head instruction is squashed, it is ready to retire
86214039Sstacze01@arm.com        // (be removed from the ROB) at any time.
86314039Sstacze01@arm.com        if (head_inst->isSquashed()) {
86414039Sstacze01@arm.com
86514039Sstacze01@arm.com            DPRINTF(Commit, "Retiring squashed instruction from "
86614039Sstacze01@arm.com                    "ROB.\n");
86714039Sstacze01@arm.com
86814039Sstacze01@arm.com            rob->retireHead(commit_thread);
86914039Sstacze01@arm.com
87014039Sstacze01@arm.com            ++commitSquashedInsts;
87114039Sstacze01@arm.com
87214039Sstacze01@arm.com            // Record that the number of ROB entries has changed.
87314039Sstacze01@arm.com            changedROBNumEntries[tid] = true;
87414039Sstacze01@arm.com        } else {
87514039Sstacze01@arm.com            pc[tid] = head_inst->pcState();
87614039Sstacze01@arm.com
87714039Sstacze01@arm.com            // Increment the total number of non-speculative instructions
87814039Sstacze01@arm.com            // executed.
87914039Sstacze01@arm.com            // Hack for now: it really shouldn't happen until after the
88014039Sstacze01@arm.com            // commit is deemed to be successful, but this count is needed
88114039Sstacze01@arm.com            // for syscalls.
88214039Sstacze01@arm.com            thread[tid]->funcExeInst++;
88314039Sstacze01@arm.com
88414039Sstacze01@arm.com            // Try to commit the head instruction.
88514039Sstacze01@arm.com            bool commit_success = commitHead(head_inst, num_committed);
88614039Sstacze01@arm.com
88714039Sstacze01@arm.com            if (commit_success) {
88814039Sstacze01@arm.com                ++num_committed;
88914039Sstacze01@arm.com
89014039Sstacze01@arm.com                changedROBNumEntries[tid] = true;
89114039Sstacze01@arm.com
89214039Sstacze01@arm.com                // Set the doneSeqNum to the youngest committed instruction.
89314039Sstacze01@arm.com                toIEW->commitInfo[tid].doneSeqNum = head_inst->seqNum;
89414039Sstacze01@arm.com
89514039Sstacze01@arm.com                ++commitCommittedInsts;
89614039Sstacze01@arm.com
89714039Sstacze01@arm.com                // To match the old model, don't count nops and instruction
89814039Sstacze01@arm.com                // prefetches towards the total commit count.
89914039Sstacze01@arm.com                if (!head_inst->isNop() && !head_inst->isInstPrefetch()) {
90014039Sstacze01@arm.com                    cpu->instDone(tid);
90114039Sstacze01@arm.com                }
90214039Sstacze01@arm.com
90314039Sstacze01@arm.com                TheISA::advancePC(pc[tid], head_inst->staticInst);
90414039Sstacze01@arm.com
90514039Sstacze01@arm.com                int count = 0;
90614039Sstacze01@arm.com                Addr oldpc;
90714039Sstacze01@arm.com                // Debug statement.  Checks to make sure we're not
90814039Sstacze01@arm.com                // currently updating state while handling PC events.
90914039Sstacze01@arm.com                assert(!thread[tid]->inSyscall && !thread[tid]->trapPending);
91014039Sstacze01@arm.com                do {
91114039Sstacze01@arm.com                    oldpc = pc[tid].instAddr();
91214039Sstacze01@arm.com                    cpu->system->pcEventQueue.service(thread[tid]->getTC());
91314039Sstacze01@arm.com                    count++;
91414039Sstacze01@arm.com                } while (oldpc != pc[tid].instAddr());
91514039Sstacze01@arm.com                if (count > 1) {
91614039Sstacze01@arm.com                    DPRINTF(Commit,
91714039Sstacze01@arm.com                            "PC skip function event, stopping commit\n");
91814039Sstacze01@arm.com                    break;
91914039Sstacze01@arm.com                }
92014039Sstacze01@arm.com            } else {
92114039Sstacze01@arm.com                DPRINTF(Commit, "Unable to commit head instruction PC:%s "
92214039Sstacze01@arm.com                        "[tid:%i] [sn:%i].\n",
92314039Sstacze01@arm.com                        head_inst->pcState(), tid ,head_inst->seqNum);
92414039Sstacze01@arm.com                break;
92514039Sstacze01@arm.com            }
92614039Sstacze01@arm.com        }
92714039Sstacze01@arm.com    }
92814039Sstacze01@arm.com
92914039Sstacze01@arm.com    DPRINTF(CommitRate, "%i\n", num_committed);
93014039Sstacze01@arm.com    numCommittedDist.sample(num_committed);
93114039Sstacze01@arm.com
93214039Sstacze01@arm.com    if (num_committed == commitWidth) {
93314039Sstacze01@arm.com        commitEligibleSamples++;
93414039Sstacze01@arm.com    }
93514039Sstacze01@arm.com}
93614039Sstacze01@arm.com
93714039Sstacze01@arm.comtemplate <class Impl>
93814039Sstacze01@arm.combool
93914039Sstacze01@arm.comDefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
94014039Sstacze01@arm.com{
94114039Sstacze01@arm.com    assert(head_inst);
94214039Sstacze01@arm.com
94314039Sstacze01@arm.com    ThreadID tid = head_inst->threadNumber;
94414039Sstacze01@arm.com
94514039Sstacze01@arm.com    // If the instruction is not executed yet, then it will need extra
94614039Sstacze01@arm.com    // handling.  Signal backwards that it should be executed.
94714039Sstacze01@arm.com    if (!head_inst->isExecuted()) {
94814039Sstacze01@arm.com        // Keep this number correct.  We have not yet actually executed
94914039Sstacze01@arm.com        // and committed this instruction.
95014039Sstacze01@arm.com        thread[tid]->funcExeInst--;
95114039Sstacze01@arm.com
95214039Sstacze01@arm.com        if (head_inst->isNonSpeculative() ||
95314039Sstacze01@arm.com            head_inst->isStoreConditional() ||
95414039Sstacze01@arm.com            head_inst->isMemBarrier() ||
95514039Sstacze01@arm.com            head_inst->isWriteBarrier()) {
95614039Sstacze01@arm.com
95714039Sstacze01@arm.com            DPRINTF(Commit, "Encountered a barrier or non-speculative "
95814039Sstacze01@arm.com                    "instruction [sn:%lli] at the head of the ROB, PC %s.\n",
95914039Sstacze01@arm.com                    head_inst->seqNum, head_inst->pcState());
96014039Sstacze01@arm.com
96114039Sstacze01@arm.com            if (inst_num > 0 || iewStage->hasStoresToWB(tid)) {
96214039Sstacze01@arm.com                DPRINTF(Commit, "Waiting for all stores to writeback.\n");
96314039Sstacze01@arm.com                return false;
96414039Sstacze01@arm.com            }
96514039Sstacze01@arm.com
96614039Sstacze01@arm.com            toIEW->commitInfo[tid].nonSpecSeqNum = head_inst->seqNum;
96714039Sstacze01@arm.com
96814039Sstacze01@arm.com            // Change the instruction so it won't try to commit again until
96914039Sstacze01@arm.com            // it is executed.
97014039Sstacze01@arm.com            head_inst->clearCanCommit();
97114039Sstacze01@arm.com
97214039Sstacze01@arm.com            ++commitNonSpecStalls;
97314039Sstacze01@arm.com
97414039Sstacze01@arm.com            return false;
97514039Sstacze01@arm.com        } else if (head_inst->isLoad()) {
97614039Sstacze01@arm.com            if (inst_num > 0 || iewStage->hasStoresToWB(tid)) {
97714039Sstacze01@arm.com                DPRINTF(Commit, "Waiting for all stores to writeback.\n");
97814039Sstacze01@arm.com                return false;
97914039Sstacze01@arm.com            }
98014039Sstacze01@arm.com
98114039Sstacze01@arm.com            assert(head_inst->uncacheable());
98214039Sstacze01@arm.com            DPRINTF(Commit, "[sn:%lli]: Uncached load, PC %s.\n",
98314039Sstacze01@arm.com                    head_inst->seqNum, head_inst->pcState());
98414039Sstacze01@arm.com
98514039Sstacze01@arm.com            // Send back the non-speculative instruction's sequence
98614039Sstacze01@arm.com            // number.  Tell the lsq to re-execute the load.
98714039Sstacze01@arm.com            toIEW->commitInfo[tid].nonSpecSeqNum = head_inst->seqNum;
98814039Sstacze01@arm.com            toIEW->commitInfo[tid].uncached = true;
98914039Sstacze01@arm.com            toIEW->commitInfo[tid].uncachedLoad = head_inst;
99014039Sstacze01@arm.com
99114039Sstacze01@arm.com            head_inst->clearCanCommit();
99214039Sstacze01@arm.com
99314039Sstacze01@arm.com            return false;
99414039Sstacze01@arm.com        } else {
99514039Sstacze01@arm.com            panic("Trying to commit un-executed instruction "
99614039Sstacze01@arm.com                  "of unknown type!\n");
99714039Sstacze01@arm.com        }
99814039Sstacze01@arm.com    }
99914039Sstacze01@arm.com
100014039Sstacze01@arm.com    if (head_inst->isThreadSync()) {
100114039Sstacze01@arm.com        // Not handled for now.
100214039Sstacze01@arm.com        panic("Thread sync instructions are not handled yet.\n");
100314039Sstacze01@arm.com    }
100414039Sstacze01@arm.com
100514039Sstacze01@arm.com    // Check if the instruction caused a fault.  If so, trap.
100614039Sstacze01@arm.com    Fault inst_fault = head_inst->getFault();
100714039Sstacze01@arm.com
100814039Sstacze01@arm.com    // Stores mark themselves as completed.
100914039Sstacze01@arm.com    if (!head_inst->isStore() && inst_fault == NoFault) {
101014039Sstacze01@arm.com        head_inst->setCompleted();
101114039Sstacze01@arm.com    }
101214039Sstacze01@arm.com
101314039Sstacze01@arm.com#if USE_CHECKER
101414039Sstacze01@arm.com    // Use checker prior to updating anything due to traps or PC
101514039Sstacze01@arm.com    // based events.
101614039Sstacze01@arm.com    if (cpu->checker) {
101714039Sstacze01@arm.com        cpu->checker->verify(head_inst);
101814039Sstacze01@arm.com    }
101914039Sstacze01@arm.com#endif
102014039Sstacze01@arm.com
102114039Sstacze01@arm.com    if (inst_fault != NoFault) {
102214039Sstacze01@arm.com        DPRINTF(Commit, "Inst [sn:%lli] PC %s has a fault\n",
102314039Sstacze01@arm.com                head_inst->seqNum, head_inst->pcState());
102414039Sstacze01@arm.com
102514039Sstacze01@arm.com        if (iewStage->hasStoresToWB(tid) || inst_num > 0) {
102614039Sstacze01@arm.com            DPRINTF(Commit, "Stores outstanding, fault must wait.\n");
102714039Sstacze01@arm.com            return false;
102814039Sstacze01@arm.com        }
102914039Sstacze01@arm.com
103014039Sstacze01@arm.com        head_inst->setCompleted();
103114039Sstacze01@arm.com
103214039Sstacze01@arm.com#if USE_CHECKER
103314039Sstacze01@arm.com        if (cpu->checker && head_inst->isStore()) {
103414039Sstacze01@arm.com            cpu->checker->verify(head_inst);
103514039Sstacze01@arm.com        }
103614039Sstacze01@arm.com#endif
103714039Sstacze01@arm.com
103814039Sstacze01@arm.com        assert(!thread[tid]->inSyscall);
103914039Sstacze01@arm.com
104014039Sstacze01@arm.com        // Mark that we're in state update mode so that the trap's
104114039Sstacze01@arm.com        // execution doesn't generate extra squashes.
104214039Sstacze01@arm.com        thread[tid]->inSyscall = true;
104314039Sstacze01@arm.com
104414039Sstacze01@arm.com        // Execute the trap.  Although it's slightly unrealistic in
104514039Sstacze01@arm.com        // terms of timing (as it doesn't wait for the full timing of
104614039Sstacze01@arm.com        // the trap event to complete before updating state), it's
104714039Sstacze01@arm.com        // needed to update the state as soon as possible.  This
104814039Sstacze01@arm.com        // prevents external agents from changing any specific state
104914039Sstacze01@arm.com        // that the trap need.
105014039Sstacze01@arm.com        cpu->trap(inst_fault, tid, head_inst->staticInst);
105114039Sstacze01@arm.com
105214039Sstacze01@arm.com        // Exit state update mode to avoid accidental updating.
105314039Sstacze01@arm.com        thread[tid]->inSyscall = false;
105414039Sstacze01@arm.com
105514039Sstacze01@arm.com        commitStatus[tid] = TrapPending;
105614039Sstacze01@arm.com
105714039Sstacze01@arm.com        if (head_inst->traceData) {
105814039Sstacze01@arm.com            if (DTRACE(ExecFaulting)) {
105914039Sstacze01@arm.com                head_inst->traceData->setFetchSeq(head_inst->seqNum);
106014039Sstacze01@arm.com                head_inst->traceData->setCPSeq(thread[tid]->numInst);
106114039Sstacze01@arm.com                head_inst->traceData->dump();
106214039Sstacze01@arm.com            }
106314039Sstacze01@arm.com            delete head_inst->traceData;
106414039Sstacze01@arm.com            head_inst->traceData = NULL;
106514039Sstacze01@arm.com        }
106614039Sstacze01@arm.com
106714039Sstacze01@arm.com        // Generate trap squash event.
106814039Sstacze01@arm.com        generateTrapEvent(tid);
106914039Sstacze01@arm.com        return false;
107014039Sstacze01@arm.com    }
107114039Sstacze01@arm.com
107214039Sstacze01@arm.com    updateComInstStats(head_inst);
107314039Sstacze01@arm.com
107414039Sstacze01@arm.com#if FULL_SYSTEM
107514039Sstacze01@arm.com    if (thread[tid]->profile) {
107614039Sstacze01@arm.com        thread[tid]->profilePC = head_inst->instAddr();
107714039Sstacze01@arm.com        ProfileNode *node = thread[tid]->profile->consume(thread[tid]->getTC(),
107814039Sstacze01@arm.com                                                          head_inst->staticInst);
107914039Sstacze01@arm.com
108014039Sstacze01@arm.com        if (node)
108114039Sstacze01@arm.com            thread[tid]->profileNode = node;
108214039Sstacze01@arm.com    }
108314039Sstacze01@arm.com    if (CPA::available()) {
108414039Sstacze01@arm.com        if (head_inst->isControl()) {
108514039Sstacze01@arm.com            ThreadContext *tc = thread[tid]->getTC();
108614039Sstacze01@arm.com            CPA::cpa()->swAutoBegin(tc, head_inst->nextInstAddr());
108714039Sstacze01@arm.com        }
108814039Sstacze01@arm.com    }
108914039Sstacze01@arm.com#endif
109014039Sstacze01@arm.com
109114039Sstacze01@arm.com    if (head_inst->traceData) {
109214039Sstacze01@arm.com        head_inst->traceData->setFetchSeq(head_inst->seqNum);
109314039Sstacze01@arm.com        head_inst->traceData->setCPSeq(thread[tid]->numInst);
109414039Sstacze01@arm.com        head_inst->traceData->dump();
109514039Sstacze01@arm.com        delete head_inst->traceData;
109614039Sstacze01@arm.com        head_inst->traceData = NULL;
109714039Sstacze01@arm.com    }
109814039Sstacze01@arm.com
109914039Sstacze01@arm.com    // Update the commit rename map
110014039Sstacze01@arm.com    for (int i = 0; i < head_inst->numDestRegs(); i++) {
110114039Sstacze01@arm.com        renameMap[tid]->setEntry(head_inst->flattenedDestRegIdx(i),
110214039Sstacze01@arm.com                                 head_inst->renamedDestRegIdx(i));
110314039Sstacze01@arm.com    }
110414039Sstacze01@arm.com
110514039Sstacze01@arm.com    if (head_inst->isCopy())
110614039Sstacze01@arm.com        panic("Should not commit any copy instructions!");
110714039Sstacze01@arm.com
110814039Sstacze01@arm.com    // Finally clear the head ROB entry.
110914039Sstacze01@arm.com    rob->retireHead(tid);
111014039Sstacze01@arm.com
111114039Sstacze01@arm.com    // If this was a store, record it for this cycle.
111214039Sstacze01@arm.com    if (head_inst->isStore())
111314039Sstacze01@arm.com        committedStores[tid] = true;
111414039Sstacze01@arm.com
111514039Sstacze01@arm.com    // Return true to indicate that we have committed an instruction.
111614039Sstacze01@arm.com    return true;
111714039Sstacze01@arm.com}
111814039Sstacze01@arm.com
111914039Sstacze01@arm.comtemplate <class Impl>
112014039Sstacze01@arm.comvoid
112114039Sstacze01@arm.comDefaultCommit<Impl>::getInsts()
112214039Sstacze01@arm.com{
112314039Sstacze01@arm.com    DPRINTF(Commit, "Getting instructions from Rename stage.\n");
112414039Sstacze01@arm.com
112514039Sstacze01@arm.com    // Read any renamed instructions and place them into the ROB.
112614039Sstacze01@arm.com    int insts_to_process = std::min((int)renameWidth, fromRename->size);
112714039Sstacze01@arm.com
112814039Sstacze01@arm.com    for (int inst_num = 0; inst_num < insts_to_process; ++inst_num) {
112914039Sstacze01@arm.com        DynInstPtr inst;
113014039Sstacze01@arm.com
113114039Sstacze01@arm.com        inst = fromRename->insts[inst_num];
113214039Sstacze01@arm.com        ThreadID tid = inst->threadNumber;
113314039Sstacze01@arm.com
113414039Sstacze01@arm.com        if (!inst->isSquashed() &&
113514039Sstacze01@arm.com            commitStatus[tid] != ROBSquashing &&
113614039Sstacze01@arm.com            commitStatus[tid] != TrapPending) {
113714039Sstacze01@arm.com            changedROBNumEntries[tid] = true;
113814039Sstacze01@arm.com
113914039Sstacze01@arm.com            DPRINTF(Commit, "Inserting PC %s [sn:%i] [tid:%i] into ROB.\n",
114014039Sstacze01@arm.com                    inst->pcState(), inst->seqNum, tid);
114114039Sstacze01@arm.com
114214039Sstacze01@arm.com            rob->insertInst(inst);
114314039Sstacze01@arm.com
114414039Sstacze01@arm.com            assert(rob->getThreadEntries(tid) <= rob->getMaxEntries(tid));
114514039Sstacze01@arm.com
114614039Sstacze01@arm.com            youngestSeqNum[tid] = inst->seqNum;
114714039Sstacze01@arm.com        } else {
114814039Sstacze01@arm.com            DPRINTF(Commit, "Instruction PC %s [sn:%i] [tid:%i] was "
114914039Sstacze01@arm.com                    "squashed, skipping.\n",
115014039Sstacze01@arm.com                    inst->pcState(), inst->seqNum, tid);
115114039Sstacze01@arm.com        }
115214039Sstacze01@arm.com    }
115314039Sstacze01@arm.com}
115414039Sstacze01@arm.com
115514039Sstacze01@arm.comtemplate <class Impl>
115614039Sstacze01@arm.comvoid
115714039Sstacze01@arm.comDefaultCommit<Impl>::skidInsert()
115814039Sstacze01@arm.com{
115914039Sstacze01@arm.com    DPRINTF(Commit, "Attempting to any instructions from rename into "
116014039Sstacze01@arm.com            "skidBuffer.\n");
116114039Sstacze01@arm.com
116214039Sstacze01@arm.com    for (int inst_num = 0; inst_num < fromRename->size; ++inst_num) {
116314039Sstacze01@arm.com        DynInstPtr inst = fromRename->insts[inst_num];
116414039Sstacze01@arm.com
116514039Sstacze01@arm.com        if (!inst->isSquashed()) {
116614039Sstacze01@arm.com            DPRINTF(Commit, "Inserting PC %s [sn:%i] [tid:%i] into ",
116714039Sstacze01@arm.com                    "skidBuffer.\n", inst->pcState(), inst->seqNum,
116814039Sstacze01@arm.com                    inst->threadNumber);
116914039Sstacze01@arm.com            skidBuffer.push(inst);
117014039Sstacze01@arm.com        } else {
117114039Sstacze01@arm.com            DPRINTF(Commit, "Instruction PC %s [sn:%i] [tid:%i] was "
117214039Sstacze01@arm.com                    "squashed, skipping.\n",
117314039Sstacze01@arm.com                    inst->pcState(), inst->seqNum, inst->threadNumber);
117414039Sstacze01@arm.com        }
117514039Sstacze01@arm.com    }
117614039Sstacze01@arm.com}
117714039Sstacze01@arm.com
117814039Sstacze01@arm.comtemplate <class Impl>
117914039Sstacze01@arm.comvoid
118014039Sstacze01@arm.comDefaultCommit<Impl>::markCompletedInsts()
118114039Sstacze01@arm.com{
118214039Sstacze01@arm.com    // Grab completed insts out of the IEW instruction queue, and mark
118314039Sstacze01@arm.com    // instructions completed within the ROB.
118414039Sstacze01@arm.com    for (int inst_num = 0;
118514039Sstacze01@arm.com         inst_num < fromIEW->size && fromIEW->insts[inst_num];
118614039Sstacze01@arm.com         ++inst_num)
118714039Sstacze01@arm.com    {
118814039Sstacze01@arm.com        if (!fromIEW->insts[inst_num]->isSquashed()) {
118914039Sstacze01@arm.com            DPRINTF(Commit, "[tid:%i]: Marking PC %s, [sn:%lli] ready "
119014039Sstacze01@arm.com                    "within ROB.\n",
119114039Sstacze01@arm.com                    fromIEW->insts[inst_num]->threadNumber,
119214039Sstacze01@arm.com                    fromIEW->insts[inst_num]->pcState(),
119314039Sstacze01@arm.com                    fromIEW->insts[inst_num]->seqNum);
119414039Sstacze01@arm.com
119514039Sstacze01@arm.com            // Mark the instruction as ready to commit.
119614039Sstacze01@arm.com            fromIEW->insts[inst_num]->setCanCommit();
119714039Sstacze01@arm.com        }
119814039Sstacze01@arm.com    }
119914039Sstacze01@arm.com}
120014039Sstacze01@arm.com
120114039Sstacze01@arm.comtemplate <class Impl>
120214039Sstacze01@arm.combool
120314039Sstacze01@arm.comDefaultCommit<Impl>::robDoneSquashing()
120414039Sstacze01@arm.com{
120514039Sstacze01@arm.com    list<ThreadID>::iterator threads = activeThreads->begin();
120614039Sstacze01@arm.com    list<ThreadID>::iterator end = activeThreads->end();
120714039Sstacze01@arm.com
120814039Sstacze01@arm.com    while (threads != end) {
120914039Sstacze01@arm.com        ThreadID tid = *threads++;
121014039Sstacze01@arm.com
121114039Sstacze01@arm.com        if (!rob->isDoneSquashing(tid))
121214039Sstacze01@arm.com            return false;
121314039Sstacze01@arm.com    }
121414039Sstacze01@arm.com
121514039Sstacze01@arm.com    return true;
121614039Sstacze01@arm.com}
121714039Sstacze01@arm.com
121814039Sstacze01@arm.comtemplate <class Impl>
121914039Sstacze01@arm.comvoid
122014039Sstacze01@arm.comDefaultCommit<Impl>::updateComInstStats(DynInstPtr &inst)
122114039Sstacze01@arm.com{
122214039Sstacze01@arm.com    ThreadID tid = inst->threadNumber;
122314039Sstacze01@arm.com
122414039Sstacze01@arm.com    //
122514039Sstacze01@arm.com    //  Pick off the software prefetches
122614039Sstacze01@arm.com    //
122714039Sstacze01@arm.com#ifdef TARGET_ALPHA
122814039Sstacze01@arm.com    if (inst->isDataPrefetch()) {
122914039Sstacze01@arm.com        statComSwp[tid]++;
123014039Sstacze01@arm.com    } else {
123114039Sstacze01@arm.com        statComInst[tid]++;
123214039Sstacze01@arm.com    }
123314039Sstacze01@arm.com#else
123414039Sstacze01@arm.com    statComInst[tid]++;
123514039Sstacze01@arm.com#endif
123614039Sstacze01@arm.com
123714039Sstacze01@arm.com    //
123814039Sstacze01@arm.com    //  Control Instructions
123914039Sstacze01@arm.com    //
124014039Sstacze01@arm.com    if (inst->isControl())
124114039Sstacze01@arm.com        statComBranches[tid]++;
124214039Sstacze01@arm.com
124314039Sstacze01@arm.com    //
124414039Sstacze01@arm.com    //  Memory references
124514039Sstacze01@arm.com    //
124614039Sstacze01@arm.com    if (inst->isMemRef()) {
124714039Sstacze01@arm.com        statComRefs[tid]++;
124814039Sstacze01@arm.com
124914039Sstacze01@arm.com        if (inst->isLoad()) {
125014039Sstacze01@arm.com            statComLoads[tid]++;
125114039Sstacze01@arm.com        }
125214039Sstacze01@arm.com    }
125314039Sstacze01@arm.com
125414039Sstacze01@arm.com    if (inst->isMemBarrier()) {
125514039Sstacze01@arm.com        statComMembars[tid]++;
125614039Sstacze01@arm.com    }
125714039Sstacze01@arm.com}
125814039Sstacze01@arm.com
125914039Sstacze01@arm.com////////////////////////////////////////
126014039Sstacze01@arm.com//                                    //
126114039Sstacze01@arm.com//  SMT COMMIT POLICY MAINTAINED HERE //
126214039Sstacze01@arm.com//                                    //
126314039Sstacze01@arm.com////////////////////////////////////////
126414039Sstacze01@arm.comtemplate <class Impl>
126514039Sstacze01@arm.comThreadID
126614039Sstacze01@arm.comDefaultCommit<Impl>::getCommittingThread()
126714039Sstacze01@arm.com{
126814039Sstacze01@arm.com    if (numThreads > 1) {
126914039Sstacze01@arm.com        switch (commitPolicy) {
127014039Sstacze01@arm.com
127114039Sstacze01@arm.com          case Aggressive:
127214039Sstacze01@arm.com            //If Policy is Aggressive, commit will call
127314039Sstacze01@arm.com            //this function multiple times per
127414039Sstacze01@arm.com            //cycle
127514039Sstacze01@arm.com            return oldestReady();
127614039Sstacze01@arm.com
127714039Sstacze01@arm.com          case RoundRobin:
127814039Sstacze01@arm.com            return roundRobin();
127914039Sstacze01@arm.com
128014039Sstacze01@arm.com          case OldestReady:
128114039Sstacze01@arm.com            return oldestReady();
128214039Sstacze01@arm.com
128314039Sstacze01@arm.com          default:
128414039Sstacze01@arm.com            return InvalidThreadID;
128514039Sstacze01@arm.com        }
128614039Sstacze01@arm.com    } else {
128714039Sstacze01@arm.com        assert(!activeThreads->empty());
128814039Sstacze01@arm.com        ThreadID tid = activeThreads->front();
128914039Sstacze01@arm.com
129014039Sstacze01@arm.com        if (commitStatus[tid] == Running ||
129114039Sstacze01@arm.com            commitStatus[tid] == Idle ||
129214039Sstacze01@arm.com            commitStatus[tid] == FetchTrapPending) {
129314039Sstacze01@arm.com            return tid;
129414039Sstacze01@arm.com        } else {
129514039Sstacze01@arm.com            return InvalidThreadID;
129614039Sstacze01@arm.com        }
129714039Sstacze01@arm.com    }
129814039Sstacze01@arm.com}
129914039Sstacze01@arm.com
130014039Sstacze01@arm.comtemplate<class Impl>
130114039Sstacze01@arm.comThreadID
130214039Sstacze01@arm.comDefaultCommit<Impl>::roundRobin()
130314039Sstacze01@arm.com{
130414039Sstacze01@arm.com    list<ThreadID>::iterator pri_iter = priority_list.begin();
130514039Sstacze01@arm.com    list<ThreadID>::iterator end      = priority_list.end();
130614039Sstacze01@arm.com
130714039Sstacze01@arm.com    while (pri_iter != end) {
130814039Sstacze01@arm.com        ThreadID tid = *pri_iter;
130914039Sstacze01@arm.com
131014039Sstacze01@arm.com        if (commitStatus[tid] == Running ||
131114039Sstacze01@arm.com            commitStatus[tid] == Idle ||
131214039Sstacze01@arm.com            commitStatus[tid] == FetchTrapPending) {
131314039Sstacze01@arm.com
131414039Sstacze01@arm.com            if (rob->isHeadReady(tid)) {
131514039Sstacze01@arm.com                priority_list.erase(pri_iter);
131614039Sstacze01@arm.com                priority_list.push_back(tid);
131714039Sstacze01@arm.com
131814039Sstacze01@arm.com                return tid;
131914039Sstacze01@arm.com            }
132014039Sstacze01@arm.com        }
132114039Sstacze01@arm.com
132214039Sstacze01@arm.com        pri_iter++;
132314039Sstacze01@arm.com    }
132414039Sstacze01@arm.com
132514039Sstacze01@arm.com    return InvalidThreadID;
132614039Sstacze01@arm.com}
132714039Sstacze01@arm.com
132814039Sstacze01@arm.comtemplate<class Impl>
132914039Sstacze01@arm.comThreadID
133014039Sstacze01@arm.comDefaultCommit<Impl>::oldestReady()
133114039Sstacze01@arm.com{
133214039Sstacze01@arm.com    unsigned oldest = 0;
133314039Sstacze01@arm.com    bool first = true;
133414039Sstacze01@arm.com
133514039Sstacze01@arm.com    list<ThreadID>::iterator threads = activeThreads->begin();
133614039Sstacze01@arm.com    list<ThreadID>::iterator end = activeThreads->end();
133714039Sstacze01@arm.com
133814039Sstacze01@arm.com    while (threads != end) {
133914039Sstacze01@arm.com        ThreadID tid = *threads++;
134014039Sstacze01@arm.com
134114039Sstacze01@arm.com        if (!rob->isEmpty(tid) &&
134214039Sstacze01@arm.com            (commitStatus[tid] == Running ||
134314039Sstacze01@arm.com             commitStatus[tid] == Idle ||
134414039Sstacze01@arm.com             commitStatus[tid] == FetchTrapPending)) {
134514039Sstacze01@arm.com
134614039Sstacze01@arm.com            if (rob->isHeadReady(tid)) {
134714039Sstacze01@arm.com
134814039Sstacze01@arm.com                DynInstPtr head_inst = rob->readHeadInst(tid);
134914039Sstacze01@arm.com
135014039Sstacze01@arm.com                if (first) {
135114039Sstacze01@arm.com                    oldest = tid;
135214039Sstacze01@arm.com                    first = false;
135314039Sstacze01@arm.com                } else if (head_inst->seqNum < oldest) {
135414039Sstacze01@arm.com                    oldest = tid;
135514039Sstacze01@arm.com                }
135614039Sstacze01@arm.com            }
135714039Sstacze01@arm.com        }
135814039Sstacze01@arm.com    }
135914039Sstacze01@arm.com
136014039Sstacze01@arm.com    if (!first) {
136114039Sstacze01@arm.com        return oldest;
136214039Sstacze01@arm.com    } else {
136314039Sstacze01@arm.com        return InvalidThreadID;
136414039Sstacze01@arm.com    }
136514039Sstacze01@arm.com}
136614039Sstacze01@arm.com