commit_impl.hh revision 3221
111507SCurtis.Dunham@arm.com/*
211507SCurtis.Dunham@arm.com * Copyright (c) 2004-2006 The Regents of The University of Michigan
311570SCurtis.Dunham@arm.com * All rights reserved.
411570SCurtis.Dunham@arm.com *
511570SCurtis.Dunham@arm.com * Redistribution and use in source and binary forms, with or without
611507SCurtis.Dunham@arm.com * modification, are permitted provided that the following conditions are
711570SCurtis.Dunham@arm.com * met: redistributions of source code must retain the above copyright
811570SCurtis.Dunham@arm.com * notice, this list of conditions and the following disclaimer;
911570SCurtis.Dunham@arm.com * redistributions in binary form must reproduce the above copyright
1011570SCurtis.Dunham@arm.com * notice, this list of conditions and the following disclaimer in the
1111570SCurtis.Dunham@arm.com * documentation and/or other materials provided with the distribution;
1211507SCurtis.Dunham@arm.com * neither the name of the copyright holders nor the names of its
1311507SCurtis.Dunham@arm.com * contributors may be used to endorse or promote products derived from
1411507SCurtis.Dunham@arm.com * this software without specific prior written permission.
1511507SCurtis.Dunham@arm.com *
1611570SCurtis.Dunham@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1711570SCurtis.Dunham@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1811507SCurtis.Dunham@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1911570SCurtis.Dunham@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2011570SCurtis.Dunham@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2111570SCurtis.Dunham@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2211570SCurtis.Dunham@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2311570SCurtis.Dunham@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2411570SCurtis.Dunham@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2511507SCurtis.Dunham@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2611570SCurtis.Dunham@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2711570SCurtis.Dunham@arm.com *
2811570SCurtis.Dunham@arm.com * Authors: Kevin Lim
2911570SCurtis.Dunham@arm.com *          Korey Sewell
3011570SCurtis.Dunham@arm.com */
3111570SCurtis.Dunham@arm.com
3211570SCurtis.Dunham@arm.com#include "config/full_system.hh"
3311570SCurtis.Dunham@arm.com#include "config/use_checker.hh"
3411570SCurtis.Dunham@arm.com
3511570SCurtis.Dunham@arm.com#include <algorithm>
3611570SCurtis.Dunham@arm.com#include <string>
3711570SCurtis.Dunham@arm.com
3811570SCurtis.Dunham@arm.com#include "base/loader/symtab.hh"
3911570SCurtis.Dunham@arm.com#include "base/timebuf.hh"
4011570SCurtis.Dunham@arm.com#include "cpu/exetrace.hh"
4111570SCurtis.Dunham@arm.com#include "cpu/o3/commit.hh"
4211570SCurtis.Dunham@arm.com#include "cpu/o3/thread_state.hh"
4311570SCurtis.Dunham@arm.com
4411570SCurtis.Dunham@arm.com#if USE_CHECKER
4511507SCurtis.Dunham@arm.com#include "cpu/checker/cpu.hh"
4611570SCurtis.Dunham@arm.com#endif
4711570SCurtis.Dunham@arm.com
4811570SCurtis.Dunham@arm.comtemplate <class Impl>
4911507SCurtis.Dunham@arm.comDefaultCommit<Impl>::TrapEvent::TrapEvent(DefaultCommit<Impl> *_commit,
5011507SCurtis.Dunham@arm.com                                          unsigned _tid)
5111507SCurtis.Dunham@arm.com    : Event(&mainEventQueue, CPU_Tick_Pri), commit(_commit), tid(_tid)
5211570SCurtis.Dunham@arm.com{
5311570SCurtis.Dunham@arm.com    this->setFlags(Event::AutoDelete);
5411570SCurtis.Dunham@arm.com}
5511507SCurtis.Dunham@arm.com
5611507SCurtis.Dunham@arm.comtemplate <class Impl>
5711570SCurtis.Dunham@arm.comvoid
5811570SCurtis.Dunham@arm.comDefaultCommit<Impl>::TrapEvent::process()
5911570SCurtis.Dunham@arm.com{
6011507SCurtis.Dunham@arm.com    // This will get reset by commit if it was switched out at the
6111570SCurtis.Dunham@arm.com    // time of this event processing.
6211507SCurtis.Dunham@arm.com    commit->trapSquash[tid] = true;
6311570SCurtis.Dunham@arm.com}
6411507SCurtis.Dunham@arm.com
6511570SCurtis.Dunham@arm.comtemplate <class Impl>
6611570SCurtis.Dunham@arm.comconst char *
6711507SCurtis.Dunham@arm.comDefaultCommit<Impl>::TrapEvent::description()
6811507SCurtis.Dunham@arm.com{
6911507SCurtis.Dunham@arm.com    return "Trap event";
7011507SCurtis.Dunham@arm.com}
7111507SCurtis.Dunham@arm.com
7211570SCurtis.Dunham@arm.comtemplate <class Impl>
7311570SCurtis.Dunham@arm.comDefaultCommit<Impl>::DefaultCommit(Params *params)
7411570SCurtis.Dunham@arm.com    : squashCounter(0),
7511570SCurtis.Dunham@arm.com      iewToCommitDelay(params->iewToCommitDelay),
7611507SCurtis.Dunham@arm.com      commitToIEWDelay(params->commitToIEWDelay),
7711570SCurtis.Dunham@arm.com      renameToROBDelay(params->renameToROBDelay),
7811570SCurtis.Dunham@arm.com      fetchToCommitDelay(params->commitToFetchDelay),
7911507SCurtis.Dunham@arm.com      renameWidth(params->renameWidth),
8011507SCurtis.Dunham@arm.com      commitWidth(params->commitWidth),
8111507SCurtis.Dunham@arm.com      numThreads(params->numberOfThreads),
8211507SCurtis.Dunham@arm.com      drainPending(false),
8311570SCurtis.Dunham@arm.com      switchedOut(false),
8411507SCurtis.Dunham@arm.com      trapLatency(params->trapLatency)
8511507SCurtis.Dunham@arm.com{
8611570SCurtis.Dunham@arm.com    _status = Active;
8711507SCurtis.Dunham@arm.com    _nextStatus = Inactive;
8811507SCurtis.Dunham@arm.com    std::string policy = params->smtCommitPolicy;
8911507SCurtis.Dunham@arm.com
9011507SCurtis.Dunham@arm.com    //Convert string to lowercase
9111507SCurtis.Dunham@arm.com    std::transform(policy.begin(), policy.end(), policy.begin(),
9211507SCurtis.Dunham@arm.com                   (int(*)(int)) tolower);
9311570SCurtis.Dunham@arm.com
9411507SCurtis.Dunham@arm.com    //Assign commit policy
9511507SCurtis.Dunham@arm.com    if (policy == "aggressive"){
9611507SCurtis.Dunham@arm.com        commitPolicy = Aggressive;
9711507SCurtis.Dunham@arm.com
9811507SCurtis.Dunham@arm.com        DPRINTF(Commit,"Commit Policy set to Aggressive.");
9911507SCurtis.Dunham@arm.com    } else if (policy == "roundrobin"){
10011570SCurtis.Dunham@arm.com        commitPolicy = RoundRobin;
10111570SCurtis.Dunham@arm.com
10211570SCurtis.Dunham@arm.com        //Set-Up Priority List
10311570SCurtis.Dunham@arm.com        for (int tid=0; tid < numThreads; tid++) {
10411507SCurtis.Dunham@arm.com            priority_list.push_back(tid);
10511507SCurtis.Dunham@arm.com        }
10611507SCurtis.Dunham@arm.com
10711507SCurtis.Dunham@arm.com        DPRINTF(Commit,"Commit Policy set to Round Robin.");
10811507SCurtis.Dunham@arm.com    } else if (policy == "oldestready"){
10911507SCurtis.Dunham@arm.com        commitPolicy = OldestReady;
11011507SCurtis.Dunham@arm.com
11111507SCurtis.Dunham@arm.com        DPRINTF(Commit,"Commit Policy set to Oldest Ready.");
11211507SCurtis.Dunham@arm.com    } else {
11311507SCurtis.Dunham@arm.com        assert(0 && "Invalid SMT Commit Policy. Options Are: {Aggressive,"
11411507SCurtis.Dunham@arm.com               "RoundRobin,OldestReady}");
11511507SCurtis.Dunham@arm.com    }
11611507SCurtis.Dunham@arm.com
11711507SCurtis.Dunham@arm.com    for (int i=0; i < numThreads; i++) {
11811507SCurtis.Dunham@arm.com        commitStatus[i] = Idle;
11911507SCurtis.Dunham@arm.com        changedROBNumEntries[i] = false;
12011507SCurtis.Dunham@arm.com        trapSquash[i] = false;
12111507SCurtis.Dunham@arm.com        tcSquash[i] = false;
12211507SCurtis.Dunham@arm.com        PC[i] = nextPC[i] = nextNPC[i] = 0;
12311507SCurtis.Dunham@arm.com    }
12411507SCurtis.Dunham@arm.com}
12511507SCurtis.Dunham@arm.com
12611507SCurtis.Dunham@arm.comtemplate <class Impl>
12711507SCurtis.Dunham@arm.comstd::string
12811507SCurtis.Dunham@arm.comDefaultCommit<Impl>::name() const
12911507SCurtis.Dunham@arm.com{
13011507SCurtis.Dunham@arm.com    return cpu->name() + ".commit";
13111507SCurtis.Dunham@arm.com}
13211507SCurtis.Dunham@arm.com
13311507SCurtis.Dunham@arm.comtemplate <class Impl>
13411507SCurtis.Dunham@arm.comvoid
13511507SCurtis.Dunham@arm.comDefaultCommit<Impl>::regStats()
13611507SCurtis.Dunham@arm.com{
13711507SCurtis.Dunham@arm.com    using namespace Stats;
13811507SCurtis.Dunham@arm.com    commitCommittedInsts
13911507SCurtis.Dunham@arm.com        .name(name() + ".commitCommittedInsts")
14011507SCurtis.Dunham@arm.com        .desc("The number of committed instructions")
14111507SCurtis.Dunham@arm.com        .prereq(commitCommittedInsts);
14211507SCurtis.Dunham@arm.com    commitSquashedInsts
14311507SCurtis.Dunham@arm.com        .name(name() + ".commitSquashedInsts")
14411507SCurtis.Dunham@arm.com        .desc("The number of squashed insts skipped by commit")
14511507SCurtis.Dunham@arm.com        .prereq(commitSquashedInsts);
14611507SCurtis.Dunham@arm.com    commitSquashEvents
14711507SCurtis.Dunham@arm.com        .name(name() + ".commitSquashEvents")
14811570SCurtis.Dunham@arm.com        .desc("The number of times commit is told to squash")
14911570SCurtis.Dunham@arm.com        .prereq(commitSquashEvents);
15011570SCurtis.Dunham@arm.com    commitNonSpecStalls
15111570SCurtis.Dunham@arm.com        .name(name() + ".commitNonSpecStalls")
15211570SCurtis.Dunham@arm.com        .desc("The number of times commit has been forced to stall to "
15311570SCurtis.Dunham@arm.com              "communicate backwards")
15411570SCurtis.Dunham@arm.com        .prereq(commitNonSpecStalls);
15511570SCurtis.Dunham@arm.com    branchMispredicts
15611570SCurtis.Dunham@arm.com        .name(name() + ".branchMispredicts")
15711570SCurtis.Dunham@arm.com        .desc("The number of times a branch was mispredicted")
15811570SCurtis.Dunham@arm.com        .prereq(branchMispredicts);
15911570SCurtis.Dunham@arm.com    numCommittedDist
16011570SCurtis.Dunham@arm.com        .init(0,commitWidth,1)
16111570SCurtis.Dunham@arm.com        .name(name() + ".COM:committed_per_cycle")
16211570SCurtis.Dunham@arm.com        .desc("Number of insts commited each cycle")
16311570SCurtis.Dunham@arm.com        .flags(Stats::pdf)
16411570SCurtis.Dunham@arm.com        ;
16511570SCurtis.Dunham@arm.com
16611570SCurtis.Dunham@arm.com    statComInst
16711507SCurtis.Dunham@arm.com        .init(cpu->number_of_threads)
16811507SCurtis.Dunham@arm.com        .name(name() + ".COM:count")
16911570SCurtis.Dunham@arm.com        .desc("Number of instructions committed")
17011570SCurtis.Dunham@arm.com        .flags(total)
17111570SCurtis.Dunham@arm.com        ;
17211570SCurtis.Dunham@arm.com
17311570SCurtis.Dunham@arm.com    statComSwp
17411570SCurtis.Dunham@arm.com        .init(cpu->number_of_threads)
17511570SCurtis.Dunham@arm.com        .name(name() + ".COM:swp_count")
17611507SCurtis.Dunham@arm.com        .desc("Number of s/w prefetches committed")
17711507SCurtis.Dunham@arm.com        .flags(total)
17811507SCurtis.Dunham@arm.com        ;
17911507SCurtis.Dunham@arm.com
18011507SCurtis.Dunham@arm.com    statComRefs
18111507SCurtis.Dunham@arm.com        .init(cpu->number_of_threads)
18211507SCurtis.Dunham@arm.com        .name(name() +  ".COM:refs")
18311507SCurtis.Dunham@arm.com        .desc("Number of memory references committed")
18411507SCurtis.Dunham@arm.com        .flags(total)
18511507SCurtis.Dunham@arm.com        ;
18611507SCurtis.Dunham@arm.com
18711507SCurtis.Dunham@arm.com    statComLoads
18811507SCurtis.Dunham@arm.com        .init(cpu->number_of_threads)
18911507SCurtis.Dunham@arm.com        .name(name() +  ".COM:loads")
19011507SCurtis.Dunham@arm.com        .desc("Number of loads committed")
19111507SCurtis.Dunham@arm.com        .flags(total)
19211507SCurtis.Dunham@arm.com        ;
19311507SCurtis.Dunham@arm.com
19411507SCurtis.Dunham@arm.com    statComMembars
19511507SCurtis.Dunham@arm.com        .init(cpu->number_of_threads)
19611507SCurtis.Dunham@arm.com        .name(name() +  ".COM:membars")
19711570SCurtis.Dunham@arm.com        .desc("Number of memory barriers committed")
19811570SCurtis.Dunham@arm.com        .flags(total)
19911570SCurtis.Dunham@arm.com        ;
20011570SCurtis.Dunham@arm.com
20111570SCurtis.Dunham@arm.com    statComBranches
20211570SCurtis.Dunham@arm.com        .init(cpu->number_of_threads)
20311570SCurtis.Dunham@arm.com        .name(name() + ".COM:branches")
20411570SCurtis.Dunham@arm.com        .desc("Number of branches committed")
20511570SCurtis.Dunham@arm.com        .flags(total)
20611570SCurtis.Dunham@arm.com        ;
20711570SCurtis.Dunham@arm.com
20811570SCurtis.Dunham@arm.com    commitEligible
20911570SCurtis.Dunham@arm.com        .init(cpu->number_of_threads)
21011570SCurtis.Dunham@arm.com        .name(name() + ".COM:bw_limited")
21111570SCurtis.Dunham@arm.com        .desc("number of insts not committed due to BW limits")
21211570SCurtis.Dunham@arm.com        .flags(total)
21311570SCurtis.Dunham@arm.com        ;
21411570SCurtis.Dunham@arm.com
21511507SCurtis.Dunham@arm.com    commitEligibleSamples
21611507SCurtis.Dunham@arm.com        .name(name() + ".COM:bw_lim_events")
21711507SCurtis.Dunham@arm.com        .desc("number cycles where commit BW limit reached")
21811570SCurtis.Dunham@arm.com        ;
21911570SCurtis.Dunham@arm.com}
22011570SCurtis.Dunham@arm.com
22111570SCurtis.Dunham@arm.comtemplate <class Impl>
22211570SCurtis.Dunham@arm.comvoid
22311570SCurtis.Dunham@arm.comDefaultCommit<Impl>::setCPU(O3CPU *cpu_ptr)
22411570SCurtis.Dunham@arm.com{
22511570SCurtis.Dunham@arm.com    DPRINTF(Commit, "Commit: Setting CPU pointer.\n");
22611570SCurtis.Dunham@arm.com    cpu = cpu_ptr;
22711570SCurtis.Dunham@arm.com
22811570SCurtis.Dunham@arm.com    // Commit must broadcast the number of free entries it has at the start of
22911570SCurtis.Dunham@arm.com    // the simulation, so it starts as active.
23011570SCurtis.Dunham@arm.com    cpu->activateStage(O3CPU::CommitIdx);
23111570SCurtis.Dunham@arm.com
23211570SCurtis.Dunham@arm.com    trapLatency = cpu->cycles(trapLatency);
23311570SCurtis.Dunham@arm.com}
23411570SCurtis.Dunham@arm.com
23511507SCurtis.Dunham@arm.comtemplate <class Impl>
23611570SCurtis.Dunham@arm.comvoid
23711570SCurtis.Dunham@arm.comDefaultCommit<Impl>::setThreads(std::vector<Thread *> &threads)
23811570SCurtis.Dunham@arm.com{
23911570SCurtis.Dunham@arm.com    thread = threads;
24011570SCurtis.Dunham@arm.com}
24111507SCurtis.Dunham@arm.com
24211570SCurtis.Dunham@arm.comtemplate <class Impl>
24311570SCurtis.Dunham@arm.comvoid
24411570SCurtis.Dunham@arm.comDefaultCommit<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
24511507SCurtis.Dunham@arm.com{
24611570SCurtis.Dunham@arm.com    DPRINTF(Commit, "Commit: Setting time buffer pointer.\n");
24711570SCurtis.Dunham@arm.com    timeBuffer = tb_ptr;
24811570SCurtis.Dunham@arm.com
24911570SCurtis.Dunham@arm.com    // Setup wire to send information back to IEW.
25011570SCurtis.Dunham@arm.com    toIEW = timeBuffer->getWire(0);
25111570SCurtis.Dunham@arm.com
25211570SCurtis.Dunham@arm.com    // Setup wire to read data from IEW (for the ROB).
25311570SCurtis.Dunham@arm.com    robInfoFromIEW = timeBuffer->getWire(-iewToCommitDelay);
25411570SCurtis.Dunham@arm.com}
25511570SCurtis.Dunham@arm.com
25611570SCurtis.Dunham@arm.comtemplate <class Impl>
25711570SCurtis.Dunham@arm.comvoid
25811570SCurtis.Dunham@arm.comDefaultCommit<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr)
25911570SCurtis.Dunham@arm.com{
26011570SCurtis.Dunham@arm.com    DPRINTF(Commit, "Commit: Setting fetch queue pointer.\n");
26111570SCurtis.Dunham@arm.com    fetchQueue = fq_ptr;
26211570SCurtis.Dunham@arm.com
26311570SCurtis.Dunham@arm.com    // Setup wire to get instructions from rename (for the ROB).
26411507SCurtis.Dunham@arm.com    fromFetch = fetchQueue->getWire(-fetchToCommitDelay);
26511570SCurtis.Dunham@arm.com}
26611507SCurtis.Dunham@arm.com
26711570SCurtis.Dunham@arm.comtemplate <class Impl>
26811570SCurtis.Dunham@arm.comvoid
26911570SCurtis.Dunham@arm.comDefaultCommit<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
27011570SCurtis.Dunham@arm.com{
27111570SCurtis.Dunham@arm.com    DPRINTF(Commit, "Commit: Setting rename queue pointer.\n");
27211570SCurtis.Dunham@arm.com    renameQueue = rq_ptr;
27311570SCurtis.Dunham@arm.com
27411570SCurtis.Dunham@arm.com    // Setup wire to get instructions from rename (for the ROB).
27511570SCurtis.Dunham@arm.com    fromRename = renameQueue->getWire(-renameToROBDelay);
27611570SCurtis.Dunham@arm.com}
27711570SCurtis.Dunham@arm.com
27811507SCurtis.Dunham@arm.comtemplate <class Impl>
27911570SCurtis.Dunham@arm.comvoid
28011507SCurtis.Dunham@arm.comDefaultCommit<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
28111570SCurtis.Dunham@arm.com{
28211570SCurtis.Dunham@arm.com    DPRINTF(Commit, "Commit: Setting IEW queue pointer.\n");
28311570SCurtis.Dunham@arm.com    iewQueue = iq_ptr;
28411570SCurtis.Dunham@arm.com
28511570SCurtis.Dunham@arm.com    // Setup wire to get instructions from IEW.
28611570SCurtis.Dunham@arm.com    fromIEW = iewQueue->getWire(-iewToCommitDelay);
28711507SCurtis.Dunham@arm.com}
28811570SCurtis.Dunham@arm.com
28911570SCurtis.Dunham@arm.comtemplate <class Impl>
29011507SCurtis.Dunham@arm.comvoid
29111570SCurtis.Dunham@arm.comDefaultCommit<Impl>::setIEWStage(IEW *iew_stage)
29211570SCurtis.Dunham@arm.com{
29311570SCurtis.Dunham@arm.com    iewStage = iew_stage;
29411570SCurtis.Dunham@arm.com}
29511507SCurtis.Dunham@arm.com
29611570SCurtis.Dunham@arm.comtemplate<class Impl>
29711507SCurtis.Dunham@arm.comvoid
29811507SCurtis.Dunham@arm.comDefaultCommit<Impl>::setActiveThreads(std::list<unsigned> *at_ptr)
29911507SCurtis.Dunham@arm.com{
30011507SCurtis.Dunham@arm.com    DPRINTF(Commit, "Commit: Setting active threads list pointer.\n");
30111507SCurtis.Dunham@arm.com    activeThreads = at_ptr;
30211507SCurtis.Dunham@arm.com}
30311507SCurtis.Dunham@arm.com
30411507SCurtis.Dunham@arm.comtemplate <class Impl>
30511507SCurtis.Dunham@arm.comvoid
30611507SCurtis.Dunham@arm.comDefaultCommit<Impl>::setRenameMap(RenameMap rm_ptr[])
30711507SCurtis.Dunham@arm.com{
30811507SCurtis.Dunham@arm.com    DPRINTF(Commit, "Setting rename map pointers.\n");
30911507SCurtis.Dunham@arm.com
31011507SCurtis.Dunham@arm.com    for (int i=0; i < numThreads; i++) {
31111507SCurtis.Dunham@arm.com        renameMap[i] = &rm_ptr[i];
31211507SCurtis.Dunham@arm.com    }
31311507SCurtis.Dunham@arm.com}
31411507SCurtis.Dunham@arm.com
31511507SCurtis.Dunham@arm.comtemplate <class Impl>
31611507SCurtis.Dunham@arm.comvoid
31711507SCurtis.Dunham@arm.comDefaultCommit<Impl>::setROB(ROB *rob_ptr)
31811507SCurtis.Dunham@arm.com{
31911507SCurtis.Dunham@arm.com    DPRINTF(Commit, "Commit: Setting ROB pointer.\n");
32011507SCurtis.Dunham@arm.com    rob = rob_ptr;
32111507SCurtis.Dunham@arm.com}
32211507SCurtis.Dunham@arm.com
32311507SCurtis.Dunham@arm.comtemplate <class Impl>
32411507SCurtis.Dunham@arm.comvoid
32511507SCurtis.Dunham@arm.comDefaultCommit<Impl>::initStage()
32611570SCurtis.Dunham@arm.com{
32711507SCurtis.Dunham@arm.com    rob->setActiveThreads(activeThreads);
32811507SCurtis.Dunham@arm.com    rob->resetEntries();
32911507SCurtis.Dunham@arm.com
33011507SCurtis.Dunham@arm.com    // Broadcast the number of free entries.
33111507SCurtis.Dunham@arm.com    for (int i=0; i < numThreads; i++) {
33211507SCurtis.Dunham@arm.com        toIEW->commitInfo[i].usedROB = true;
33311507SCurtis.Dunham@arm.com        toIEW->commitInfo[i].freeROBEntries = rob->numFreeEntries(i);
33411507SCurtis.Dunham@arm.com    }
33511507SCurtis.Dunham@arm.com
33611507SCurtis.Dunham@arm.com    cpu->activityThisCycle();
33711507SCurtis.Dunham@arm.com}
33811507SCurtis.Dunham@arm.com
33911507SCurtis.Dunham@arm.comtemplate <class Impl>
34011507SCurtis.Dunham@arm.combool
34111507SCurtis.Dunham@arm.comDefaultCommit<Impl>::drain()
34211507SCurtis.Dunham@arm.com{
34311507SCurtis.Dunham@arm.com    drainPending = true;
34411507SCurtis.Dunham@arm.com
34511507SCurtis.Dunham@arm.com    return false;
34611507SCurtis.Dunham@arm.com}
34711507SCurtis.Dunham@arm.com
34811507SCurtis.Dunham@arm.comtemplate <class Impl>
34911507SCurtis.Dunham@arm.comvoid
35011507SCurtis.Dunham@arm.comDefaultCommit<Impl>::switchOut()
35111507SCurtis.Dunham@arm.com{
35211507SCurtis.Dunham@arm.com    switchedOut = true;
35311507SCurtis.Dunham@arm.com    drainPending = false;
35411507SCurtis.Dunham@arm.com    rob->switchOut();
35511507SCurtis.Dunham@arm.com}
35611570SCurtis.Dunham@arm.com
35711507SCurtis.Dunham@arm.comtemplate <class Impl>
35811507SCurtis.Dunham@arm.comvoid
35911507SCurtis.Dunham@arm.comDefaultCommit<Impl>::resume()
36011507SCurtis.Dunham@arm.com{
36111507SCurtis.Dunham@arm.com    drainPending = false;
36211507SCurtis.Dunham@arm.com}
36311507SCurtis.Dunham@arm.com
36411507SCurtis.Dunham@arm.comtemplate <class Impl>
36511507SCurtis.Dunham@arm.comvoid
36611507SCurtis.Dunham@arm.comDefaultCommit<Impl>::takeOverFrom()
36711507SCurtis.Dunham@arm.com{
36811507SCurtis.Dunham@arm.com    switchedOut = false;
36911507SCurtis.Dunham@arm.com    _status = Active;
37011507SCurtis.Dunham@arm.com    _nextStatus = Inactive;
37111507SCurtis.Dunham@arm.com    for (int i=0; i < numThreads; i++) {
37211507SCurtis.Dunham@arm.com        commitStatus[i] = Idle;
37311507SCurtis.Dunham@arm.com        changedROBNumEntries[i] = false;
37411507SCurtis.Dunham@arm.com        trapSquash[i] = false;
37511507SCurtis.Dunham@arm.com        tcSquash[i] = false;
37611507SCurtis.Dunham@arm.com    }
37711507SCurtis.Dunham@arm.com    squashCounter = 0;
37811507SCurtis.Dunham@arm.com    rob->takeOverFrom();
37911507SCurtis.Dunham@arm.com}
38011507SCurtis.Dunham@arm.com
38111507SCurtis.Dunham@arm.comtemplate <class Impl>
38211507SCurtis.Dunham@arm.comvoid
38311507SCurtis.Dunham@arm.comDefaultCommit<Impl>::updateStatus()
38411507SCurtis.Dunham@arm.com{
38511507SCurtis.Dunham@arm.com    // reset ROB changed variable
38611570SCurtis.Dunham@arm.com    std::list<unsigned>::iterator threads = (*activeThreads).begin();
38711507SCurtis.Dunham@arm.com    while (threads != (*activeThreads).end()) {
38811507SCurtis.Dunham@arm.com        unsigned tid = *threads++;
38911507SCurtis.Dunham@arm.com        changedROBNumEntries[tid] = false;
39011507SCurtis.Dunham@arm.com
39111507SCurtis.Dunham@arm.com        // Also check if any of the threads has a trap pending
39211507SCurtis.Dunham@arm.com        if (commitStatus[tid] == TrapPending ||
39311507SCurtis.Dunham@arm.com            commitStatus[tid] == FetchTrapPending) {
39411507SCurtis.Dunham@arm.com            _nextStatus = Active;
39511507SCurtis.Dunham@arm.com        }
39611507SCurtis.Dunham@arm.com    }
39711507SCurtis.Dunham@arm.com
39811507SCurtis.Dunham@arm.com    if (_nextStatus == Inactive && _status == Active) {
39911507SCurtis.Dunham@arm.com        DPRINTF(Activity, "Deactivating stage.\n");
40011507SCurtis.Dunham@arm.com        cpu->deactivateStage(O3CPU::CommitIdx);
40111507SCurtis.Dunham@arm.com    } else if (_nextStatus == Active && _status == Inactive) {
40211507SCurtis.Dunham@arm.com        DPRINTF(Activity, "Activating stage.\n");
40311507SCurtis.Dunham@arm.com        cpu->activateStage(O3CPU::CommitIdx);
40411507SCurtis.Dunham@arm.com    }
40511507SCurtis.Dunham@arm.com
40611507SCurtis.Dunham@arm.com    _status = _nextStatus;
40711507SCurtis.Dunham@arm.com}
40811507SCurtis.Dunham@arm.com
40911507SCurtis.Dunham@arm.comtemplate <class Impl>
41011507SCurtis.Dunham@arm.comvoid
41111507SCurtis.Dunham@arm.comDefaultCommit<Impl>::setNextStatus()
41211507SCurtis.Dunham@arm.com{
41311507SCurtis.Dunham@arm.com    int squashes = 0;
41411507SCurtis.Dunham@arm.com
41511507SCurtis.Dunham@arm.com    std::list<unsigned>::iterator threads = (*activeThreads).begin();
41611507SCurtis.Dunham@arm.com
41711570SCurtis.Dunham@arm.com    while (threads != (*activeThreads).end()) {
41811570SCurtis.Dunham@arm.com        unsigned tid = *threads++;
41911507SCurtis.Dunham@arm.com
42011507SCurtis.Dunham@arm.com        if (commitStatus[tid] == ROBSquashing) {
42111507SCurtis.Dunham@arm.com            squashes++;
42211507SCurtis.Dunham@arm.com        }
42311570SCurtis.Dunham@arm.com    }
42411507SCurtis.Dunham@arm.com
42511570SCurtis.Dunham@arm.com    squashCounter = squashes;
42611570SCurtis.Dunham@arm.com
42711507SCurtis.Dunham@arm.com    // If commit is currently squashing, then it will have activity for the
42811507SCurtis.Dunham@arm.com    // next cycle. Set its next status as active.
42911507SCurtis.Dunham@arm.com    if (squashCounter) {
43011507SCurtis.Dunham@arm.com        _nextStatus = Active;
43111507SCurtis.Dunham@arm.com    }
43211507SCurtis.Dunham@arm.com}
43311507SCurtis.Dunham@arm.com
43411507SCurtis.Dunham@arm.comtemplate <class Impl>
43511507SCurtis.Dunham@arm.combool
43611507SCurtis.Dunham@arm.comDefaultCommit<Impl>::changedROBEntries()
43711507SCurtis.Dunham@arm.com{
43811507SCurtis.Dunham@arm.com    std::list<unsigned>::iterator threads = (*activeThreads).begin();
43911507SCurtis.Dunham@arm.com
44011507SCurtis.Dunham@arm.com    while (threads != (*activeThreads).end()) {
44111507SCurtis.Dunham@arm.com        unsigned tid = *threads++;
44211507SCurtis.Dunham@arm.com
44311507SCurtis.Dunham@arm.com        if (changedROBNumEntries[tid]) {
44411507SCurtis.Dunham@arm.com            return true;
44511507SCurtis.Dunham@arm.com        }
44611507SCurtis.Dunham@arm.com    }
44711507SCurtis.Dunham@arm.com
44811507SCurtis.Dunham@arm.com    return false;
44911507SCurtis.Dunham@arm.com}
45011507SCurtis.Dunham@arm.com
45111507SCurtis.Dunham@arm.comtemplate <class Impl>
45211507SCurtis.Dunham@arm.comunsigned
45311507SCurtis.Dunham@arm.comDefaultCommit<Impl>::numROBFreeEntries(unsigned tid)
45411507SCurtis.Dunham@arm.com{
45511507SCurtis.Dunham@arm.com    return rob->numFreeEntries(tid);
45611507SCurtis.Dunham@arm.com}
45711507SCurtis.Dunham@arm.com
45811507SCurtis.Dunham@arm.comtemplate <class Impl>
45911507SCurtis.Dunham@arm.comvoid
46011507SCurtis.Dunham@arm.comDefaultCommit<Impl>::generateTrapEvent(unsigned tid)
46111507SCurtis.Dunham@arm.com{
46211570SCurtis.Dunham@arm.com    DPRINTF(Commit, "Generating trap event for [tid:%i]\n", tid);
46311570SCurtis.Dunham@arm.com
46411570SCurtis.Dunham@arm.com    TrapEvent *trap = new TrapEvent(this, tid);
46511570SCurtis.Dunham@arm.com
46611570SCurtis.Dunham@arm.com    trap->schedule(curTick + trapLatency);
46711570SCurtis.Dunham@arm.com
46811570SCurtis.Dunham@arm.com    thread[tid]->trapPending = true;
46911570SCurtis.Dunham@arm.com}
47011570SCurtis.Dunham@arm.com
47111570SCurtis.Dunham@arm.comtemplate <class Impl>
47211570SCurtis.Dunham@arm.comvoid
47311570SCurtis.Dunham@arm.comDefaultCommit<Impl>::generateTCEvent(unsigned tid)
47411507SCurtis.Dunham@arm.com{
47511507SCurtis.Dunham@arm.com    DPRINTF(Commit, "Generating TC squash event for [tid:%i]\n", tid);
47611570SCurtis.Dunham@arm.com
47711570SCurtis.Dunham@arm.com    tcSquash[tid] = true;
47811507SCurtis.Dunham@arm.com}
47911570SCurtis.Dunham@arm.com
48011570SCurtis.Dunham@arm.comtemplate <class Impl>
48111570SCurtis.Dunham@arm.comvoid
48211570SCurtis.Dunham@arm.comDefaultCommit<Impl>::squashAll(unsigned tid)
48311570SCurtis.Dunham@arm.com{
48411570SCurtis.Dunham@arm.com    // If we want to include the squashing instruction in the squash,
48511570SCurtis.Dunham@arm.com    // then use one older sequence number.
48611570SCurtis.Dunham@arm.com    // Hopefully this doesn't mess things up.  Basically I want to squash
48711570SCurtis.Dunham@arm.com    // all instructions of this thread.
48811507SCurtis.Dunham@arm.com    InstSeqNum squashed_inst = rob->isEmpty() ?
48911507SCurtis.Dunham@arm.com        0 : rob->readHeadInst(tid)->seqNum - 1;;
49011507SCurtis.Dunham@arm.com
49111507SCurtis.Dunham@arm.com    // All younger instructions will be squashed. Set the sequence
49211570SCurtis.Dunham@arm.com    // number as the youngest instruction in the ROB (0 in this case.
49311570SCurtis.Dunham@arm.com    // Hopefully nothing breaks.)
49411570SCurtis.Dunham@arm.com    youngestSeqNum[tid] = 0;
49511570SCurtis.Dunham@arm.com
49611570SCurtis.Dunham@arm.com    rob->squash(squashed_inst, tid);
49711570SCurtis.Dunham@arm.com    changedROBNumEntries[tid] = true;
49811570SCurtis.Dunham@arm.com
49911570SCurtis.Dunham@arm.com    // Send back the sequence number of the squashed instruction.
50011570SCurtis.Dunham@arm.com    toIEW->commitInfo[tid].doneSeqNum = squashed_inst;
50111570SCurtis.Dunham@arm.com
50211570SCurtis.Dunham@arm.com    // Send back the squash signal to tell stages that they should
50311570SCurtis.Dunham@arm.com    // squash.
50411570SCurtis.Dunham@arm.com    toIEW->commitInfo[tid].squash = true;
50511570SCurtis.Dunham@arm.com
50611570SCurtis.Dunham@arm.com    // Send back the rob squashing signal so other stages know that
50711570SCurtis.Dunham@arm.com    // the ROB is in the process of squashing.
50811570SCurtis.Dunham@arm.com    toIEW->commitInfo[tid].robSquashing = true;
50911570SCurtis.Dunham@arm.com
51011570SCurtis.Dunham@arm.com    toIEW->commitInfo[tid].branchMispredict = false;
51111570SCurtis.Dunham@arm.com
51211570SCurtis.Dunham@arm.com    toIEW->commitInfo[tid].nextPC = PC[tid];
51311570SCurtis.Dunham@arm.com}
51411570SCurtis.Dunham@arm.com
51511570SCurtis.Dunham@arm.comtemplate <class Impl>
51611507SCurtis.Dunham@arm.comvoid
51711507SCurtis.Dunham@arm.comDefaultCommit<Impl>::squashFromTrap(unsigned tid)
51811570SCurtis.Dunham@arm.com{
51911570SCurtis.Dunham@arm.com    squashAll(tid);
52011507SCurtis.Dunham@arm.com
52111507SCurtis.Dunham@arm.com    DPRINTF(Commit, "Squashing from trap, restarting at PC %#x\n", PC[tid]);
52211507SCurtis.Dunham@arm.com
52311507SCurtis.Dunham@arm.com    thread[tid]->trapPending = false;
52411570SCurtis.Dunham@arm.com    thread[tid]->inSyscall = false;
52511570SCurtis.Dunham@arm.com
52611570SCurtis.Dunham@arm.com    trapSquash[tid] = false;
52711570SCurtis.Dunham@arm.com
52811570SCurtis.Dunham@arm.com    commitStatus[tid] = ROBSquashing;
52911570SCurtis.Dunham@arm.com    cpu->activityThisCycle();
53011570SCurtis.Dunham@arm.com}
53111570SCurtis.Dunham@arm.com
53211570SCurtis.Dunham@arm.comtemplate <class Impl>
53311570SCurtis.Dunham@arm.comvoid
53411570SCurtis.Dunham@arm.comDefaultCommit<Impl>::squashFromTC(unsigned tid)
53511570SCurtis.Dunham@arm.com{
53611570SCurtis.Dunham@arm.com    squashAll(tid);
53711570SCurtis.Dunham@arm.com
53811570SCurtis.Dunham@arm.com    DPRINTF(Commit, "Squashing from TC, restarting at PC %#x\n", PC[tid]);
53911570SCurtis.Dunham@arm.com
54011570SCurtis.Dunham@arm.com    thread[tid]->inSyscall = false;
54111570SCurtis.Dunham@arm.com    assert(!thread[tid]->trapPending);
54211570SCurtis.Dunham@arm.com
54311570SCurtis.Dunham@arm.com    commitStatus[tid] = ROBSquashing;
54411570SCurtis.Dunham@arm.com    cpu->activityThisCycle();
54511570SCurtis.Dunham@arm.com
54611507SCurtis.Dunham@arm.com    tcSquash[tid] = false;
54711507SCurtis.Dunham@arm.com}
54811507SCurtis.Dunham@arm.com
54911507SCurtis.Dunham@arm.comtemplate <class Impl>
55011507SCurtis.Dunham@arm.comvoid
55111507SCurtis.Dunham@arm.comDefaultCommit<Impl>::tick()
55211570SCurtis.Dunham@arm.com{
55311570SCurtis.Dunham@arm.com    wroteToTimeBuffer = false;
55411570SCurtis.Dunham@arm.com    _nextStatus = Inactive;
55511570SCurtis.Dunham@arm.com
55611570SCurtis.Dunham@arm.com    if (drainPending && rob->isEmpty() && !iewStage->hasStoresToWB()) {
55711570SCurtis.Dunham@arm.com        cpu->signalDrained();
55811570SCurtis.Dunham@arm.com        drainPending = false;
55911570SCurtis.Dunham@arm.com        return;
56011570SCurtis.Dunham@arm.com    }
56111570SCurtis.Dunham@arm.com
56211570SCurtis.Dunham@arm.com    if ((*activeThreads).size() <= 0)
56311570SCurtis.Dunham@arm.com        return;
56411570SCurtis.Dunham@arm.com
56511570SCurtis.Dunham@arm.com    std::list<unsigned>::iterator threads = (*activeThreads).begin();
56611570SCurtis.Dunham@arm.com
56711570SCurtis.Dunham@arm.com    // Check if any of the threads are done squashing.  Change the
56811570SCurtis.Dunham@arm.com    // status if they are done.
56911570SCurtis.Dunham@arm.com    while (threads != (*activeThreads).end()) {
57011570SCurtis.Dunham@arm.com        unsigned tid = *threads++;
57111570SCurtis.Dunham@arm.com
57211570SCurtis.Dunham@arm.com        if (commitStatus[tid] == ROBSquashing) {
57311570SCurtis.Dunham@arm.com
57411570SCurtis.Dunham@arm.com            if (rob->isDoneSquashing(tid)) {
57511570SCurtis.Dunham@arm.com                commitStatus[tid] = Running;
57611570SCurtis.Dunham@arm.com            } else {
57711570SCurtis.Dunham@arm.com                DPRINTF(Commit,"[tid:%u]: Still Squashing, cannot commit any"
57811570SCurtis.Dunham@arm.com                        " insts this cycle.\n", tid);
57911570SCurtis.Dunham@arm.com                rob->doSquash(tid);
58011570SCurtis.Dunham@arm.com                toIEW->commitInfo[tid].robSquashing = true;
58111570SCurtis.Dunham@arm.com                wroteToTimeBuffer = true;
58211507SCurtis.Dunham@arm.com            }
58311507SCurtis.Dunham@arm.com        }
58411507SCurtis.Dunham@arm.com    }
58511507SCurtis.Dunham@arm.com
58611570SCurtis.Dunham@arm.com    commit();
58711570SCurtis.Dunham@arm.com
58811570SCurtis.Dunham@arm.com    markCompletedInsts();
58911570SCurtis.Dunham@arm.com
59011570SCurtis.Dunham@arm.com    threads = (*activeThreads).begin();
59111570SCurtis.Dunham@arm.com
59211570SCurtis.Dunham@arm.com    while (threads != (*activeThreads).end()) {
59311570SCurtis.Dunham@arm.com        unsigned tid = *threads++;
59411570SCurtis.Dunham@arm.com
59511570SCurtis.Dunham@arm.com        if (!rob->isEmpty(tid) && rob->readHeadInst(tid)->readyToCommit()) {
59611570SCurtis.Dunham@arm.com            // The ROB has more instructions it can commit. Its next status
59711570SCurtis.Dunham@arm.com            // will be active.
59811570SCurtis.Dunham@arm.com            _nextStatus = Active;
59911570SCurtis.Dunham@arm.com
60011570SCurtis.Dunham@arm.com            DynInstPtr inst = rob->readHeadInst(tid);
60111570SCurtis.Dunham@arm.com
60211570SCurtis.Dunham@arm.com            DPRINTF(Commit,"[tid:%i]: Instruction [sn:%lli] PC %#x is head of"
60311570SCurtis.Dunham@arm.com                    " ROB and ready to commit\n",
60411570SCurtis.Dunham@arm.com                    tid, inst->seqNum, inst->readPC());
60511570SCurtis.Dunham@arm.com
60611570SCurtis.Dunham@arm.com        } else if (!rob->isEmpty(tid)) {
60711570SCurtis.Dunham@arm.com            DynInstPtr inst = rob->readHeadInst(tid);
60811507SCurtis.Dunham@arm.com
60911570SCurtis.Dunham@arm.com            DPRINTF(Commit,"[tid:%i]: Can't commit, Instruction [sn:%lli] PC "
61011570SCurtis.Dunham@arm.com                    "%#x is head of ROB and not ready\n",
61111570SCurtis.Dunham@arm.com                    tid, inst->seqNum, inst->readPC());
61211507SCurtis.Dunham@arm.com        }
61311570SCurtis.Dunham@arm.com
61411570SCurtis.Dunham@arm.com        DPRINTF(Commit, "[tid:%i]: ROB has %d insts & %d free entries.\n",
61511570SCurtis.Dunham@arm.com                tid, rob->countInsts(tid), rob->numFreeEntries(tid));
61611570SCurtis.Dunham@arm.com    }
61711570SCurtis.Dunham@arm.com
61811507SCurtis.Dunham@arm.com
61911570SCurtis.Dunham@arm.com    if (wroteToTimeBuffer) {
62011570SCurtis.Dunham@arm.com        DPRINTF(Activity, "Activity This Cycle.\n");
62111570SCurtis.Dunham@arm.com        cpu->activityThisCycle();
62211570SCurtis.Dunham@arm.com    }
62311570SCurtis.Dunham@arm.com
62411570SCurtis.Dunham@arm.com    updateStatus();
62511570SCurtis.Dunham@arm.com}
62611570SCurtis.Dunham@arm.com
62711570SCurtis.Dunham@arm.comtemplate <class Impl>
62811570SCurtis.Dunham@arm.comvoid
62911570SCurtis.Dunham@arm.comDefaultCommit<Impl>::commit()
63011570SCurtis.Dunham@arm.com{
63111570SCurtis.Dunham@arm.com
63211570SCurtis.Dunham@arm.com    //////////////////////////////////////
63311570SCurtis.Dunham@arm.com    // Check for interrupts
63411570SCurtis.Dunham@arm.com    //////////////////////////////////////
63511570SCurtis.Dunham@arm.com
63611570SCurtis.Dunham@arm.com#if FULL_SYSTEM
63711570SCurtis.Dunham@arm.com    // Process interrupts if interrupts are enabled, not in PAL mode,
63811570SCurtis.Dunham@arm.com    // and no other traps or external squashes are currently pending.
63911570SCurtis.Dunham@arm.com    // @todo: Allow other threads to handle interrupts.
64011570SCurtis.Dunham@arm.com    if (cpu->checkInterrupts &&
64111570SCurtis.Dunham@arm.com        cpu->check_interrupts() &&
64211570SCurtis.Dunham@arm.com        !cpu->inPalMode(readPC()) &&
64311570SCurtis.Dunham@arm.com        !trapSquash[0] &&
64411570SCurtis.Dunham@arm.com        !tcSquash[0]) {
64511570SCurtis.Dunham@arm.com        // Tell fetch that there is an interrupt pending.  This will
64611570SCurtis.Dunham@arm.com        // make fetch wait until it sees a non PAL-mode PC, at which
64711570SCurtis.Dunham@arm.com        // point it stops fetching instructions.
64811570SCurtis.Dunham@arm.com        toIEW->commitInfo[0].interruptPending = true;
64911570SCurtis.Dunham@arm.com
65011570SCurtis.Dunham@arm.com        // Wait until the ROB is empty and all stores have drained in
65111570SCurtis.Dunham@arm.com        // order to enter the interrupt.
65211570SCurtis.Dunham@arm.com        if (rob->isEmpty() && !iewStage->hasStoresToWB()) {
65311570SCurtis.Dunham@arm.com            // Not sure which thread should be the one to interrupt.  For now
65411570SCurtis.Dunham@arm.com            // always do thread 0.
65511570SCurtis.Dunham@arm.com            assert(!thread[0]->inSyscall);
65611570SCurtis.Dunham@arm.com            thread[0]->inSyscall = true;
65711570SCurtis.Dunham@arm.com
65811507SCurtis.Dunham@arm.com            // CPU will handle implementation of the interrupt.
65911507SCurtis.Dunham@arm.com            cpu->processInterrupts();
66011507SCurtis.Dunham@arm.com
66111507SCurtis.Dunham@arm.com            // Now squash or record that I need to squash this cycle.
66211507SCurtis.Dunham@arm.com            commitStatus[0] = TrapPending;
66311507SCurtis.Dunham@arm.com
66411570SCurtis.Dunham@arm.com            // Exit state update mode to avoid accidental updating.
66511570SCurtis.Dunham@arm.com            thread[0]->inSyscall = false;
66611570SCurtis.Dunham@arm.com
66711570SCurtis.Dunham@arm.com            // Generate trap squash event.
66811570SCurtis.Dunham@arm.com            generateTrapEvent(0);
66911570SCurtis.Dunham@arm.com
67011570SCurtis.Dunham@arm.com            toIEW->commitInfo[0].clearInterrupt = true;
67111570SCurtis.Dunham@arm.com
67211570SCurtis.Dunham@arm.com            DPRINTF(Commit, "Interrupt detected.\n");
67311570SCurtis.Dunham@arm.com        } else {
67411570SCurtis.Dunham@arm.com            DPRINTF(Commit, "Interrupt pending, waiting for ROB to empty.\n");
67511570SCurtis.Dunham@arm.com        }
67611570SCurtis.Dunham@arm.com    }
67711570SCurtis.Dunham@arm.com#endif // FULL_SYSTEM
67811570SCurtis.Dunham@arm.com
67911570SCurtis.Dunham@arm.com    ////////////////////////////////////
68011570SCurtis.Dunham@arm.com    // Check for any possible squashes, handle them first
68111570SCurtis.Dunham@arm.com    ////////////////////////////////////
68211570SCurtis.Dunham@arm.com
68311570SCurtis.Dunham@arm.com    std::list<unsigned>::iterator threads = (*activeThreads).begin();
68411570SCurtis.Dunham@arm.com
68511570SCurtis.Dunham@arm.com    while (threads != (*activeThreads).end()) {
68611570SCurtis.Dunham@arm.com        unsigned tid = *threads++;
68711570SCurtis.Dunham@arm.com
68811570SCurtis.Dunham@arm.com        // Not sure which one takes priority.  I think if we have
68911570SCurtis.Dunham@arm.com        // both, that's a bad sign.
69011570SCurtis.Dunham@arm.com        if (trapSquash[tid] == true) {
69111570SCurtis.Dunham@arm.com            assert(!tcSquash[tid]);
69211570SCurtis.Dunham@arm.com            squashFromTrap(tid);
69311570SCurtis.Dunham@arm.com        } else if (tcSquash[tid] == true) {
69411570SCurtis.Dunham@arm.com            squashFromTC(tid);
69511570SCurtis.Dunham@arm.com        }
69611507SCurtis.Dunham@arm.com
69711570SCurtis.Dunham@arm.com        // Squashed sequence number must be older than youngest valid
69811570SCurtis.Dunham@arm.com        // instruction in the ROB. This prevents squashes from younger
69911570SCurtis.Dunham@arm.com        // instructions overriding squashes from older instructions.
70011570SCurtis.Dunham@arm.com        if (fromIEW->squash[tid] &&
70111570SCurtis.Dunham@arm.com            commitStatus[tid] != TrapPending &&
70211570SCurtis.Dunham@arm.com            fromIEW->squashedSeqNum[tid] <= youngestSeqNum[tid]) {
70311570SCurtis.Dunham@arm.com
70411570SCurtis.Dunham@arm.com            DPRINTF(Commit, "[tid:%i]: Squashing due to PC %#x [sn:%i]\n",
70511570SCurtis.Dunham@arm.com                    tid,
70611507SCurtis.Dunham@arm.com                    fromIEW->mispredPC[tid],
70711570SCurtis.Dunham@arm.com                    fromIEW->squashedSeqNum[tid]);
70811570SCurtis.Dunham@arm.com
70911570SCurtis.Dunham@arm.com            DPRINTF(Commit, "[tid:%i]: Redirecting to PC %#x\n",
71011570SCurtis.Dunham@arm.com                    tid,
71111570SCurtis.Dunham@arm.com                    fromIEW->nextPC[tid]);
71211570SCurtis.Dunham@arm.com
71311570SCurtis.Dunham@arm.com            commitStatus[tid] = ROBSquashing;
71411570SCurtis.Dunham@arm.com
71511570SCurtis.Dunham@arm.com            // If we want to include the squashing instruction in the squash,
71611570SCurtis.Dunham@arm.com            // then use one older sequence number.
71711570SCurtis.Dunham@arm.com            InstSeqNum squashed_inst = fromIEW->squashedSeqNum[tid];
71811570SCurtis.Dunham@arm.com
71911570SCurtis.Dunham@arm.com#if ISA_HAS_DELAY_SLOT
72011570SCurtis.Dunham@arm.com            InstSeqNum bdelay_done_seq_num;
72111570SCurtis.Dunham@arm.com            bool squash_bdelay_slot;
72211570SCurtis.Dunham@arm.com
72311570SCurtis.Dunham@arm.com            if (fromIEW->branchMispredict[tid]) {
72411570SCurtis.Dunham@arm.com                if (fromIEW->branchTaken[tid] &&
72511570SCurtis.Dunham@arm.com                    fromIEW->condDelaySlotBranch[tid]) {
72611570SCurtis.Dunham@arm.com                    DPRINTF(Commit, "[tid:%i]: Cond. delay slot branch"
72711570SCurtis.Dunham@arm.com                            "mispredicted as taken. Squashing after previous "
72811570SCurtis.Dunham@arm.com                            "inst, [sn:%i]\n",
72911570SCurtis.Dunham@arm.com                            tid, squashed_inst);
73011570SCurtis.Dunham@arm.com                     bdelay_done_seq_num = squashed_inst;
73111570SCurtis.Dunham@arm.com                     squash_bdelay_slot = true;
73211570SCurtis.Dunham@arm.com                } else {
73311570SCurtis.Dunham@arm.com                    DPRINTF(Commit, "[tid:%i]: Branch Mispredict. Squashing "
73411507SCurtis.Dunham@arm.com                            "after delay slot [sn:%i]\n", tid, squashed_inst+1);
73511507SCurtis.Dunham@arm.com                    bdelay_done_seq_num = squashed_inst + 1;
73611570SCurtis.Dunham@arm.com                    squash_bdelay_slot = false;
73711570SCurtis.Dunham@arm.com                }
73811570SCurtis.Dunham@arm.com            } else {
73911570SCurtis.Dunham@arm.com                bdelay_done_seq_num = squashed_inst;
74011570SCurtis.Dunham@arm.com            }
74111570SCurtis.Dunham@arm.com#endif
74211570SCurtis.Dunham@arm.com
74311570SCurtis.Dunham@arm.com            if (fromIEW->includeSquashInst[tid] == true) {
74411570SCurtis.Dunham@arm.com                squashed_inst--;
74511570SCurtis.Dunham@arm.com#if ISA_HAS_DELAY_SLOT
74611570SCurtis.Dunham@arm.com                bdelay_done_seq_num--;
74711570SCurtis.Dunham@arm.com#endif
74811570SCurtis.Dunham@arm.com            }
74911570SCurtis.Dunham@arm.com            // All younger instructions will be squashed. Set the sequence
75011570SCurtis.Dunham@arm.com            // number as the youngest instruction in the ROB.
75111570SCurtis.Dunham@arm.com            youngestSeqNum[tid] = squashed_inst;
75211570SCurtis.Dunham@arm.com
75311570SCurtis.Dunham@arm.com#if ISA_HAS_DELAY_SLOT
75411570SCurtis.Dunham@arm.com            rob->squash(bdelay_done_seq_num, tid);
75511570SCurtis.Dunham@arm.com            toIEW->commitInfo[tid].squashDelaySlot = squash_bdelay_slot;
75611570SCurtis.Dunham@arm.com            toIEW->commitInfo[tid].bdelayDoneSeqNum = bdelay_done_seq_num;
75711570SCurtis.Dunham@arm.com#else
75811570SCurtis.Dunham@arm.com            rob->squash(squashed_inst, tid);
75911570SCurtis.Dunham@arm.com            toIEW->commitInfo[tid].squashDelaySlot = true;
76011570SCurtis.Dunham@arm.com#endif
76111570SCurtis.Dunham@arm.com            changedROBNumEntries[tid] = true;
76211570SCurtis.Dunham@arm.com
76311570SCurtis.Dunham@arm.com            toIEW->commitInfo[tid].doneSeqNum = squashed_inst;
76411570SCurtis.Dunham@arm.com
76511570SCurtis.Dunham@arm.com            toIEW->commitInfo[tid].squash = true;
76611570SCurtis.Dunham@arm.com
76711570SCurtis.Dunham@arm.com            // Send back the rob squashing signal so other stages know that
76811570SCurtis.Dunham@arm.com            // the ROB is in the process of squashing.
76911570SCurtis.Dunham@arm.com            toIEW->commitInfo[tid].robSquashing = true;
77011570SCurtis.Dunham@arm.com
77111570SCurtis.Dunham@arm.com            toIEW->commitInfo[tid].branchMispredict =
77211570SCurtis.Dunham@arm.com                fromIEW->branchMispredict[tid];
77311570SCurtis.Dunham@arm.com
77411570SCurtis.Dunham@arm.com            toIEW->commitInfo[tid].branchTaken =
77511570SCurtis.Dunham@arm.com                fromIEW->branchTaken[tid];
77611570SCurtis.Dunham@arm.com
77711570SCurtis.Dunham@arm.com            toIEW->commitInfo[tid].nextPC = fromIEW->nextPC[tid];
77811570SCurtis.Dunham@arm.com
77911570SCurtis.Dunham@arm.com            toIEW->commitInfo[tid].mispredPC = fromIEW->mispredPC[tid];
78011570SCurtis.Dunham@arm.com
78111570SCurtis.Dunham@arm.com            if (toIEW->commitInfo[tid].branchMispredict) {
78211570SCurtis.Dunham@arm.com                ++branchMispredicts;
78311570SCurtis.Dunham@arm.com            }
78411570SCurtis.Dunham@arm.com        }
78511570SCurtis.Dunham@arm.com
78611570SCurtis.Dunham@arm.com    }
78711570SCurtis.Dunham@arm.com
78811570SCurtis.Dunham@arm.com    setNextStatus();
78911570SCurtis.Dunham@arm.com
79011570SCurtis.Dunham@arm.com    if (squashCounter != numThreads) {
79111570SCurtis.Dunham@arm.com        // If we're not currently squashing, then get instructions.
79211570SCurtis.Dunham@arm.com        getInsts();
79311570SCurtis.Dunham@arm.com
79411507SCurtis.Dunham@arm.com        // Try to commit any instructions.
79511507SCurtis.Dunham@arm.com        commitInsts();
79611507SCurtis.Dunham@arm.com    } else {
79711507SCurtis.Dunham@arm.com#if ISA_HAS_DELAY_SLOT
79811507SCurtis.Dunham@arm.com        skidInsert();
79911507SCurtis.Dunham@arm.com#endif
80011570SCurtis.Dunham@arm.com    }
80111570SCurtis.Dunham@arm.com
80211570SCurtis.Dunham@arm.com    //Check for any activity
80311570SCurtis.Dunham@arm.com    threads = (*activeThreads).begin();
80411570SCurtis.Dunham@arm.com
80511570SCurtis.Dunham@arm.com    while (threads != (*activeThreads).end()) {
80611570SCurtis.Dunham@arm.com        unsigned tid = *threads++;
80711570SCurtis.Dunham@arm.com
80811570SCurtis.Dunham@arm.com        if (changedROBNumEntries[tid]) {
80911570SCurtis.Dunham@arm.com            toIEW->commitInfo[tid].usedROB = true;
81011570SCurtis.Dunham@arm.com            toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid);
81111570SCurtis.Dunham@arm.com
81211507SCurtis.Dunham@arm.com            if (rob->isEmpty(tid)) {
81311507SCurtis.Dunham@arm.com                toIEW->commitInfo[tid].emptyROB = true;
81411570SCurtis.Dunham@arm.com            }
81511570SCurtis.Dunham@arm.com
81611570SCurtis.Dunham@arm.com            wroteToTimeBuffer = true;
81711570SCurtis.Dunham@arm.com            changedROBNumEntries[tid] = false;
81811570SCurtis.Dunham@arm.com        }
81911570SCurtis.Dunham@arm.com    }
82011570SCurtis.Dunham@arm.com}
82111507SCurtis.Dunham@arm.com
82211570SCurtis.Dunham@arm.comtemplate <class Impl>
82311570SCurtis.Dunham@arm.comvoid
82411507SCurtis.Dunham@arm.comDefaultCommit<Impl>::commitInsts()
82511570SCurtis.Dunham@arm.com{
82611570SCurtis.Dunham@arm.com    ////////////////////////////////////
82711570SCurtis.Dunham@arm.com    // Handle commit
82811570SCurtis.Dunham@arm.com    // Note that commit will be handled prior to putting new
82911570SCurtis.Dunham@arm.com    // instructions in the ROB so that the ROB only tries to commit
83011570SCurtis.Dunham@arm.com    // instructions it has in this current cycle, and not instructions
83111570SCurtis.Dunham@arm.com    // it is writing in during this cycle.  Can't commit and squash
83211570SCurtis.Dunham@arm.com    // things at the same time...
83311570SCurtis.Dunham@arm.com    ////////////////////////////////////
83411570SCurtis.Dunham@arm.com
83511570SCurtis.Dunham@arm.com    DPRINTF(Commit, "Trying to commit instructions in the ROB.\n");
83611570SCurtis.Dunham@arm.com
83711570SCurtis.Dunham@arm.com    unsigned num_committed = 0;
83811507SCurtis.Dunham@arm.com
83911507SCurtis.Dunham@arm.com    DynInstPtr head_inst;
84011570SCurtis.Dunham@arm.com
84111570SCurtis.Dunham@arm.com    // Commit as many instructions as possible until the commit bandwidth
84211570SCurtis.Dunham@arm.com    // limit is reached, or it becomes impossible to commit any more.
84311570SCurtis.Dunham@arm.com    while (num_committed < commitWidth) {
84411570SCurtis.Dunham@arm.com        int commit_thread = getCommittingThread();
84511570SCurtis.Dunham@arm.com
84611570SCurtis.Dunham@arm.com        if (commit_thread == -1 || !rob->isHeadReady(commit_thread))
84711570SCurtis.Dunham@arm.com            break;
84811570SCurtis.Dunham@arm.com
84911570SCurtis.Dunham@arm.com        head_inst = rob->readHeadInst(commit_thread);
85011570SCurtis.Dunham@arm.com
85111570SCurtis.Dunham@arm.com        int tid = head_inst->threadNumber;
85211570SCurtis.Dunham@arm.com
85311570SCurtis.Dunham@arm.com        assert(tid == commit_thread);
85411570SCurtis.Dunham@arm.com
85511570SCurtis.Dunham@arm.com        DPRINTF(Commit, "Trying to commit head instruction, [sn:%i] [tid:%i]\n",
85611570SCurtis.Dunham@arm.com                head_inst->seqNum, tid);
85711570SCurtis.Dunham@arm.com
85811570SCurtis.Dunham@arm.com        // If the head instruction is squashed, it is ready to retire
85911570SCurtis.Dunham@arm.com        // (be removed from the ROB) at any time.
86011570SCurtis.Dunham@arm.com        if (head_inst->isSquashed()) {
86111570SCurtis.Dunham@arm.com
86211570SCurtis.Dunham@arm.com            DPRINTF(Commit, "Retiring squashed instruction from "
86311570SCurtis.Dunham@arm.com                    "ROB.\n");
86411570SCurtis.Dunham@arm.com
86511570SCurtis.Dunham@arm.com            rob->retireHead(commit_thread);
86611570SCurtis.Dunham@arm.com
86711570SCurtis.Dunham@arm.com            ++commitSquashedInsts;
86811570SCurtis.Dunham@arm.com
86911507SCurtis.Dunham@arm.com            // Record that the number of ROB entries has changed.
87011570SCurtis.Dunham@arm.com            changedROBNumEntries[tid] = true;
87111570SCurtis.Dunham@arm.com        } else {
87211570SCurtis.Dunham@arm.com            PC[tid] = head_inst->readPC();
87311570SCurtis.Dunham@arm.com            nextPC[tid] = head_inst->readNextPC();
87411570SCurtis.Dunham@arm.com            nextNPC[tid] = head_inst->readNextNPC();
87511570SCurtis.Dunham@arm.com
87611570SCurtis.Dunham@arm.com            // Increment the total number of non-speculative instructions
87711570SCurtis.Dunham@arm.com            // executed.
87811570SCurtis.Dunham@arm.com            // Hack for now: it really shouldn't happen until after the
87911570SCurtis.Dunham@arm.com            // commit is deemed to be successful, but this count is needed
88011570SCurtis.Dunham@arm.com            // for syscalls.
88111570SCurtis.Dunham@arm.com            thread[tid]->funcExeInst++;
88211570SCurtis.Dunham@arm.com
88311570SCurtis.Dunham@arm.com            // Try to commit the head instruction.
88411570SCurtis.Dunham@arm.com            bool commit_success = commitHead(head_inst, num_committed);
88511570SCurtis.Dunham@arm.com
88611570SCurtis.Dunham@arm.com            if (commit_success) {
88711570SCurtis.Dunham@arm.com                ++num_committed;
88811570SCurtis.Dunham@arm.com
88911570SCurtis.Dunham@arm.com                changedROBNumEntries[tid] = true;
89011507SCurtis.Dunham@arm.com
89111570SCurtis.Dunham@arm.com                // Set the doneSeqNum to the youngest committed instruction.
89211570SCurtis.Dunham@arm.com                toIEW->commitInfo[tid].doneSeqNum = head_inst->seqNum;
89311507SCurtis.Dunham@arm.com
89411507SCurtis.Dunham@arm.com                ++commitCommittedInsts;
89511507SCurtis.Dunham@arm.com
89611507SCurtis.Dunham@arm.com                // To match the old model, don't count nops and instruction
89711570SCurtis.Dunham@arm.com                // prefetches towards the total commit count.
89811570SCurtis.Dunham@arm.com                if (!head_inst->isNop() && !head_inst->isInstPrefetch()) {
89911570SCurtis.Dunham@arm.com                    cpu->instDone(tid);
90011570SCurtis.Dunham@arm.com                }
90111507SCurtis.Dunham@arm.com
90211570SCurtis.Dunham@arm.com                PC[tid] = nextPC[tid];
90311507SCurtis.Dunham@arm.com#if ISA_HAS_DELAY_SLOT
90411570SCurtis.Dunham@arm.com                nextPC[tid] = nextNPC[tid];
90511570SCurtis.Dunham@arm.com                nextNPC[tid] = nextNPC[tid] + sizeof(TheISA::MachInst);
90611570SCurtis.Dunham@arm.com#else
90711570SCurtis.Dunham@arm.com                nextPC[tid] = nextPC[tid] + sizeof(TheISA::MachInst);
90811570SCurtis.Dunham@arm.com#endif
90911570SCurtis.Dunham@arm.com
91011570SCurtis.Dunham@arm.com#if FULL_SYSTEM
91111570SCurtis.Dunham@arm.com                int count = 0;
91211570SCurtis.Dunham@arm.com                Addr oldpc;
91311570SCurtis.Dunham@arm.com                do {
91411570SCurtis.Dunham@arm.com                    // Debug statement.  Checks to make sure we're not
91511507SCurtis.Dunham@arm.com                    // currently updating state while handling PC events.
91611570SCurtis.Dunham@arm.com                    if (count == 0)
91711570SCurtis.Dunham@arm.com                        assert(!thread[tid]->inSyscall &&
91811507SCurtis.Dunham@arm.com                               !thread[tid]->trapPending);
91911507SCurtis.Dunham@arm.com                    oldpc = PC[tid];
92011507SCurtis.Dunham@arm.com                    cpu->system->pcEventQueue.service(
92111570SCurtis.Dunham@arm.com                        thread[tid]->getTC());
92211507SCurtis.Dunham@arm.com                    count++;
92311507SCurtis.Dunham@arm.com                } while (oldpc != PC[tid]);
92411507SCurtis.Dunham@arm.com                if (count > 1) {
92511507SCurtis.Dunham@arm.com                    DPRINTF(Commit, "PC skip function event, stopping commit\n");
92611570SCurtis.Dunham@arm.com                    break;
92711570SCurtis.Dunham@arm.com                }
92811507SCurtis.Dunham@arm.com#endif
92911570SCurtis.Dunham@arm.com            } else {
93011507SCurtis.Dunham@arm.com                DPRINTF(Commit, "Unable to commit head instruction PC:%#x "
93111507SCurtis.Dunham@arm.com                        "[tid:%i] [sn:%i].\n",
93211507SCurtis.Dunham@arm.com                        head_inst->readPC(), tid ,head_inst->seqNum);
933                break;
934            }
935        }
936    }
937
938    DPRINTF(CommitRate, "%i\n", num_committed);
939    numCommittedDist.sample(num_committed);
940
941    if (num_committed == commitWidth) {
942        commitEligibleSamples++;
943    }
944}
945
946template <class Impl>
947bool
948DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
949{
950    assert(head_inst);
951
952    int tid = head_inst->threadNumber;
953
954    // If the instruction is not executed yet, then it will need extra
955    // handling.  Signal backwards that it should be executed.
956    if (!head_inst->isExecuted()) {
957        // Keep this number correct.  We have not yet actually executed
958        // and committed this instruction.
959        thread[tid]->funcExeInst--;
960
961        head_inst->setAtCommit();
962
963        if (head_inst->isNonSpeculative() ||
964            head_inst->isStoreConditional() ||
965            head_inst->isMemBarrier() ||
966            head_inst->isWriteBarrier()) {
967
968            DPRINTF(Commit, "Encountered a barrier or non-speculative "
969                    "instruction [sn:%lli] at the head of the ROB, PC %#x.\n",
970                    head_inst->seqNum, head_inst->readPC());
971
972#if !FULL_SYSTEM
973            // Hack to make sure syscalls/memory barriers/quiesces
974            // aren't executed until all stores write back their data.
975            // This direct communication shouldn't be used for
976            // anything other than this.
977            if (inst_num > 0 || iewStage->hasStoresToWB())
978#else
979            if ((head_inst->isMemBarrier() || head_inst->isWriteBarrier() ||
980                    head_inst->isQuiesce()) &&
981                iewStage->hasStoresToWB())
982#endif
983            {
984                DPRINTF(Commit, "Waiting for all stores to writeback.\n");
985                return false;
986            }
987
988            toIEW->commitInfo[tid].nonSpecSeqNum = head_inst->seqNum;
989
990            // Change the instruction so it won't try to commit again until
991            // it is executed.
992            head_inst->clearCanCommit();
993
994            ++commitNonSpecStalls;
995
996            return false;
997        } else if (head_inst->isLoad()) {
998            DPRINTF(Commit, "[sn:%lli]: Uncached load, PC %#x.\n",
999                    head_inst->seqNum, head_inst->readPC());
1000
1001            // Send back the non-speculative instruction's sequence
1002            // number.  Tell the lsq to re-execute the load.
1003            toIEW->commitInfo[tid].nonSpecSeqNum = head_inst->seqNum;
1004            toIEW->commitInfo[tid].uncached = true;
1005            toIEW->commitInfo[tid].uncachedLoad = head_inst;
1006
1007            head_inst->clearCanCommit();
1008
1009            return false;
1010        } else {
1011            panic("Trying to commit un-executed instruction "
1012                  "of unknown type!\n");
1013        }
1014    }
1015
1016    if (head_inst->isThreadSync()) {
1017        // Not handled for now.
1018        panic("Thread sync instructions are not handled yet.\n");
1019    }
1020
1021    // Stores mark themselves as completed.
1022    if (!head_inst->isStore()) {
1023        head_inst->setCompleted();
1024    }
1025
1026#if USE_CHECKER
1027    // Use checker prior to updating anything due to traps or PC
1028    // based events.
1029    if (cpu->checker) {
1030        cpu->checker->verify(head_inst);
1031    }
1032#endif
1033
1034    // Check if the instruction caused a fault.  If so, trap.
1035    Fault inst_fault = head_inst->getFault();
1036
1037    // DTB will sometimes need the machine instruction for when
1038    // faults happen.  So we will set it here, prior to the DTB
1039    // possibly needing it for its fault.
1040    thread[tid]->setInst(
1041        static_cast<TheISA::MachInst>(head_inst->staticInst->machInst));
1042
1043    if (inst_fault != NoFault) {
1044        head_inst->setCompleted();
1045        DPRINTF(Commit, "Inst [sn:%lli] PC %#x has a fault\n",
1046                head_inst->seqNum, head_inst->readPC());
1047
1048        if (iewStage->hasStoresToWB() || inst_num > 0) {
1049            DPRINTF(Commit, "Stores outstanding, fault must wait.\n");
1050            return false;
1051        }
1052
1053#if USE_CHECKER
1054        if (cpu->checker && head_inst->isStore()) {
1055            cpu->checker->verify(head_inst);
1056        }
1057#endif
1058
1059        assert(!thread[tid]->inSyscall);
1060
1061        // Mark that we're in state update mode so that the trap's
1062        // execution doesn't generate extra squashes.
1063        thread[tid]->inSyscall = true;
1064
1065        // Execute the trap.  Although it's slightly unrealistic in
1066        // terms of timing (as it doesn't wait for the full timing of
1067        // the trap event to complete before updating state), it's
1068        // needed to update the state as soon as possible.  This
1069        // prevents external agents from changing any specific state
1070        // that the trap need.
1071        cpu->trap(inst_fault, tid);
1072
1073        // Exit state update mode to avoid accidental updating.
1074        thread[tid]->inSyscall = false;
1075
1076        commitStatus[tid] = TrapPending;
1077
1078        // Generate trap squash event.
1079        generateTrapEvent(tid);
1080//        warn("%lli fault (%d) handled @ PC %08p", curTick, inst_fault->name(), head_inst->readPC());
1081        return false;
1082    }
1083
1084    updateComInstStats(head_inst);
1085
1086#if FULL_SYSTEM
1087    if (thread[tid]->profile) {
1088//        bool usermode =
1089//            (cpu->readMiscReg(AlphaISA::IPR_DTB_CM, tid) & 0x18) != 0;
1090//        thread[tid]->profilePC = usermode ? 1 : head_inst->readPC();
1091        thread[tid]->profilePC = head_inst->readPC();
1092        ProfileNode *node = thread[tid]->profile->consume(thread[tid]->getTC(),
1093                                                          head_inst->staticInst);
1094
1095        if (node)
1096            thread[tid]->profileNode = node;
1097    }
1098#endif
1099
1100    if (head_inst->traceData) {
1101        head_inst->traceData->setFetchSeq(head_inst->seqNum);
1102        head_inst->traceData->setCPSeq(thread[tid]->numInst);
1103        head_inst->traceData->finalize();
1104        head_inst->traceData = NULL;
1105    }
1106
1107    // Update the commit rename map
1108    for (int i = 0; i < head_inst->numDestRegs(); i++) {
1109        renameMap[tid]->setEntry(head_inst->destRegIdx(i),
1110                                 head_inst->renamedDestRegIdx(i));
1111    }
1112
1113    if (head_inst->isCopy())
1114        panic("Should not commit any copy instructions!");
1115
1116    // Finally clear the head ROB entry.
1117    rob->retireHead(tid);
1118
1119    // Return true to indicate that we have committed an instruction.
1120    return true;
1121}
1122
1123template <class Impl>
1124void
1125DefaultCommit<Impl>::getInsts()
1126{
1127    DPRINTF(Commit, "Getting instructions from Rename stage.\n");
1128
1129#if ISA_HAS_DELAY_SLOT
1130    // Read any renamed instructions and place them into the ROB.
1131    int insts_to_process = std::min((int)renameWidth,
1132                               (int)(fromRename->size + skidBuffer.size()));
1133    int rename_idx = 0;
1134
1135    DPRINTF(Commit, "%i insts available to process. Rename Insts:%i "
1136            "SkidBuffer Insts:%i\n", insts_to_process, fromRename->size,
1137            skidBuffer.size());
1138#else
1139    // Read any renamed instructions and place them into the ROB.
1140    int insts_to_process = std::min((int)renameWidth, fromRename->size);
1141#endif
1142
1143
1144    for (int inst_num = 0; inst_num < insts_to_process; ++inst_num) {
1145        DynInstPtr inst;
1146
1147#if ISA_HAS_DELAY_SLOT
1148        // Get insts from skidBuffer or from Rename
1149        if (skidBuffer.size() > 0) {
1150            DPRINTF(Commit, "Grabbing skidbuffer inst.\n");
1151            inst = skidBuffer.front();
1152            skidBuffer.pop();
1153        } else {
1154            DPRINTF(Commit, "Grabbing rename inst.\n");
1155            inst = fromRename->insts[rename_idx++];
1156        }
1157#else
1158        inst = fromRename->insts[inst_num];
1159#endif
1160        int tid = inst->threadNumber;
1161
1162        if (!inst->isSquashed() &&
1163            commitStatus[tid] != ROBSquashing) {
1164            changedROBNumEntries[tid] = true;
1165
1166            DPRINTF(Commit, "Inserting PC %#x [sn:%i] [tid:%i] into ROB.\n",
1167                    inst->readPC(), inst->seqNum, tid);
1168
1169            rob->insertInst(inst);
1170
1171            assert(rob->getThreadEntries(tid) <= rob->getMaxEntries(tid));
1172
1173            youngestSeqNum[tid] = inst->seqNum;
1174        } else {
1175            DPRINTF(Commit, "Instruction PC %#x [sn:%i] [tid:%i] was "
1176                    "squashed, skipping.\n",
1177                    inst->readPC(), inst->seqNum, tid);
1178        }
1179    }
1180
1181#if ISA_HAS_DELAY_SLOT
1182    if (rename_idx < fromRename->size) {
1183        DPRINTF(Commit,"Placing Rename Insts into skidBuffer.\n");
1184
1185        for (;
1186             rename_idx < fromRename->size;
1187             rename_idx++) {
1188            DynInstPtr inst = fromRename->insts[rename_idx];
1189            int tid = inst->threadNumber;
1190
1191            if (!inst->isSquashed()) {
1192                DPRINTF(Commit, "Inserting PC %#x [sn:%i] [tid:%i] into ",
1193                        "skidBuffer.\n", inst->readPC(), inst->seqNum, tid);
1194                skidBuffer.push(inst);
1195            } else {
1196                DPRINTF(Commit, "Instruction PC %#x [sn:%i] [tid:%i] was "
1197                        "squashed, skipping.\n",
1198                        inst->readPC(), inst->seqNum, tid);
1199            }
1200        }
1201    }
1202#endif
1203
1204}
1205
1206template <class Impl>
1207void
1208DefaultCommit<Impl>::skidInsert()
1209{
1210    DPRINTF(Commit, "Attempting to any instructions from rename into "
1211            "skidBuffer.\n");
1212
1213    for (int inst_num = 0; inst_num < fromRename->size; ++inst_num) {
1214        DynInstPtr inst = fromRename->insts[inst_num];
1215
1216        if (!inst->isSquashed()) {
1217            DPRINTF(Commit, "Inserting PC %#x [sn:%i] [tid:%i] into ",
1218                    "skidBuffer.\n", inst->readPC(), inst->seqNum,
1219                    inst->threadNumber);
1220            skidBuffer.push(inst);
1221        } else {
1222            DPRINTF(Commit, "Instruction PC %#x [sn:%i] [tid:%i] was "
1223                    "squashed, skipping.\n",
1224                    inst->readPC(), inst->seqNum, inst->threadNumber);
1225        }
1226    }
1227}
1228
1229template <class Impl>
1230void
1231DefaultCommit<Impl>::markCompletedInsts()
1232{
1233    // Grab completed insts out of the IEW instruction queue, and mark
1234    // instructions completed within the ROB.
1235    for (int inst_num = 0;
1236         inst_num < fromIEW->size && fromIEW->insts[inst_num];
1237         ++inst_num)
1238    {
1239        if (!fromIEW->insts[inst_num]->isSquashed()) {
1240            DPRINTF(Commit, "[tid:%i]: Marking PC %#x, [sn:%lli] ready "
1241                    "within ROB.\n",
1242                    fromIEW->insts[inst_num]->threadNumber,
1243                    fromIEW->insts[inst_num]->readPC(),
1244                    fromIEW->insts[inst_num]->seqNum);
1245
1246            // Mark the instruction as ready to commit.
1247            fromIEW->insts[inst_num]->setCanCommit();
1248        }
1249    }
1250}
1251
1252template <class Impl>
1253bool
1254DefaultCommit<Impl>::robDoneSquashing()
1255{
1256    std::list<unsigned>::iterator threads = (*activeThreads).begin();
1257
1258    while (threads != (*activeThreads).end()) {
1259        unsigned tid = *threads++;
1260
1261        if (!rob->isDoneSquashing(tid))
1262            return false;
1263    }
1264
1265    return true;
1266}
1267
1268template <class Impl>
1269void
1270DefaultCommit<Impl>::updateComInstStats(DynInstPtr &inst)
1271{
1272    unsigned thread = inst->threadNumber;
1273
1274    //
1275    //  Pick off the software prefetches
1276    //
1277#ifdef TARGET_ALPHA
1278    if (inst->isDataPrefetch()) {
1279        statComSwp[thread]++;
1280    } else {
1281        statComInst[thread]++;
1282    }
1283#else
1284    statComInst[thread]++;
1285#endif
1286
1287    //
1288    //  Control Instructions
1289    //
1290    if (inst->isControl())
1291        statComBranches[thread]++;
1292
1293    //
1294    //  Memory references
1295    //
1296    if (inst->isMemRef()) {
1297        statComRefs[thread]++;
1298
1299        if (inst->isLoad()) {
1300            statComLoads[thread]++;
1301        }
1302    }
1303
1304    if (inst->isMemBarrier()) {
1305        statComMembars[thread]++;
1306    }
1307}
1308
1309////////////////////////////////////////
1310//                                    //
1311//  SMT COMMIT POLICY MAINTAINED HERE //
1312//                                    //
1313////////////////////////////////////////
1314template <class Impl>
1315int
1316DefaultCommit<Impl>::getCommittingThread()
1317{
1318    if (numThreads > 1) {
1319        switch (commitPolicy) {
1320
1321          case Aggressive:
1322            //If Policy is Aggressive, commit will call
1323            //this function multiple times per
1324            //cycle
1325            return oldestReady();
1326
1327          case RoundRobin:
1328            return roundRobin();
1329
1330          case OldestReady:
1331            return oldestReady();
1332
1333          default:
1334            return -1;
1335        }
1336    } else {
1337        int tid = (*activeThreads).front();
1338
1339        if (commitStatus[tid] == Running ||
1340            commitStatus[tid] == Idle ||
1341            commitStatus[tid] == FetchTrapPending) {
1342            return tid;
1343        } else {
1344            return -1;
1345        }
1346    }
1347}
1348
1349template<class Impl>
1350int
1351DefaultCommit<Impl>::roundRobin()
1352{
1353    std::list<unsigned>::iterator pri_iter = priority_list.begin();
1354    std::list<unsigned>::iterator end      = priority_list.end();
1355
1356    while (pri_iter != end) {
1357        unsigned tid = *pri_iter;
1358
1359        if (commitStatus[tid] == Running ||
1360            commitStatus[tid] == Idle ||
1361            commitStatus[tid] == FetchTrapPending) {
1362
1363            if (rob->isHeadReady(tid)) {
1364                priority_list.erase(pri_iter);
1365                priority_list.push_back(tid);
1366
1367                return tid;
1368            }
1369        }
1370
1371        pri_iter++;
1372    }
1373
1374    return -1;
1375}
1376
1377template<class Impl>
1378int
1379DefaultCommit<Impl>::oldestReady()
1380{
1381    unsigned oldest = 0;
1382    bool first = true;
1383
1384    std::list<unsigned>::iterator threads = (*activeThreads).begin();
1385
1386    while (threads != (*activeThreads).end()) {
1387        unsigned tid = *threads++;
1388
1389        if (!rob->isEmpty(tid) &&
1390            (commitStatus[tid] == Running ||
1391             commitStatus[tid] == Idle ||
1392             commitStatus[tid] == FetchTrapPending)) {
1393
1394            if (rob->isHeadReady(tid)) {
1395
1396                DynInstPtr head_inst = rob->readHeadInst(tid);
1397
1398                if (first) {
1399                    oldest = tid;
1400                    first = false;
1401                } else if (head_inst->seqNum < oldest) {
1402                    oldest = tid;
1403                }
1404            }
1405        }
1406    }
1407
1408    if (!first) {
1409        return oldest;
1410    } else {
1411        return -1;
1412    }
1413}
1414