commit_impl.hh revision 7720
12381SN/A/*
213732Snikos.nikoleris@arm.com * Copyright (c) 2004-2006 The Regents of The University of Michigan
38949Sandreas.hansson@arm.com * All rights reserved.
48949Sandreas.hansson@arm.com *
58949Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
68949Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are
78949Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
88949Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
98949Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
108949Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
118949Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
128949Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its
138949Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from
142592SN/A * this software without specific prior written permission.
1510975Sdavid.hashe@amd.com *
162381SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172381SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182381SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192381SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202381SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212381SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222381SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232381SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242381SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252381SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262381SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272381SN/A *
282381SN/A * Authors: Kevin Lim
292381SN/A *          Korey Sewell
302381SN/A */
312381SN/A
322381SN/A#include <algorithm>
332381SN/A#include <string>
342381SN/A
352381SN/A#include "arch/utility.hh"
362381SN/A#include "base/cp_annotate.hh"
372381SN/A#include "base/loader/symtab.hh"
382381SN/A#include "base/timebuf.hh"
392381SN/A#include "config/full_system.hh"
402665Ssaidi@eecs.umich.edu#include "config/the_isa.hh"
412665Ssaidi@eecs.umich.edu#include "config/use_checker.hh"
422665Ssaidi@eecs.umich.edu#include "cpu/exetrace.hh"
432665Ssaidi@eecs.umich.edu#include "cpu/o3/commit.hh"
449031Sandreas.hansson@arm.com#include "cpu/o3/thread_state.hh"
4512349Snikos.nikoleris@arm.com#include "params/DerivO3CPU.hh"
462381SN/A
472381SN/A#if USE_CHECKER
482381SN/A#include "cpu/checker/cpu.hh"
492381SN/A#endif
502662Sstever@eecs.umich.edu
512381SN/Ausing namespace std;
522381SN/A
532381SN/Atemplate <class Impl>
542381SN/ADefaultCommit<Impl>::TrapEvent::TrapEvent(DefaultCommit<Impl> *_commit,
552381SN/A                                          ThreadID _tid)
568229Snate@binkert.org    : Event(CPU_Tick_Pri), commit(_commit), tid(_tid)
573348Sbinkertn@umich.edu{
583348Sbinkertn@umich.edu    this->setFlags(AutoDelete);
593348Sbinkertn@umich.edu}
6013856Sodanrc@yahoo.com.br
615735Snate@binkert.orgtemplate <class Impl>
624024Sbinkertn@umich.eduvoid
635735Snate@binkert.orgDefaultCommit<Impl>::TrapEvent::process()
6412334Sgabeblack@google.com{
655314Sstever@gmail.com    // This will get reset by commit if it was switched out at the
666216Snate@binkert.org    // time of this event processing.
6713347Sgabeblack@google.com    commit->trapSquash[tid] = true;
682392SN/A}
694167Sbinkertn@umich.edu
702394SN/Atemplate <class Impl>
718737Skoansin.tan@gmail.comconst char *
723349Sbinkertn@umich.eduDefaultCommit<Impl>::TrapEvent::description() const
732394SN/A{
742812Srdreslin@umich.edu    return "Trap";
7512351Snikos.nikoleris@arm.com}
762812Srdreslin@umich.edu
774022Sstever@eecs.umich.edutemplate <class Impl>
784022Sstever@eecs.umich.eduDefaultCommit<Impl>::DefaultCommit(O3CPU *_cpu, DerivO3CPUParams *params)
795735Snate@binkert.org    : cpu(_cpu),
805735Snate@binkert.org      squashCounter(0),
814022Sstever@eecs.umich.edu      iewToCommitDelay(params->iewToCommitDelay),
825735Snate@binkert.org      commitToIEWDelay(params->commitToIEWDelay),
835735Snate@binkert.org      renameToROBDelay(params->renameToROBDelay),
845735Snate@binkert.org      fetchToCommitDelay(params->commitToFetchDelay),
854022Sstever@eecs.umich.edu      renameWidth(params->renameWidth),
864022Sstever@eecs.umich.edu      commitWidth(params->commitWidth),
874022Sstever@eecs.umich.edu      numThreads(params->numThreads),
884022Sstever@eecs.umich.edu      drainPending(false),
894473Sstever@eecs.umich.edu      switchedOut(false),
905319Sstever@gmail.com      trapLatency(params->trapLatency)
914022Sstever@eecs.umich.edu{
924022Sstever@eecs.umich.edu    _status = Active;
9311199Sandreas.hansson@arm.com    _nextStatus = Inactive;
9411199Sandreas.hansson@arm.com    std::string policy = params->smtCommitPolicy;
9512344Snikos.nikoleris@arm.com
9610883Sali.jafri@arm.com    //Convert string to lowercase
974022Sstever@eecs.umich.edu    std::transform(policy.begin(), policy.end(), policy.begin(),
9813367Syuetsu.kodama@riken.jp                   (int(*)(int)) tolower);
994022Sstever@eecs.umich.edu
1004022Sstever@eecs.umich.edu    //Assign commit policy
1014022Sstever@eecs.umich.edu    if (policy == "aggressive"){
10210886Sandreas.hansson@arm.com        commitPolicy = Aggressive;
1034022Sstever@eecs.umich.edu
1047465Ssteve.reinhardt@amd.com        DPRINTF(Commit,"Commit Policy set to Aggressive.");
1054628Sstever@eecs.umich.edu    } else if (policy == "roundrobin"){
1067465Ssteve.reinhardt@amd.com        commitPolicy = RoundRobin;
1077465Ssteve.reinhardt@amd.com
1084022Sstever@eecs.umich.edu        //Set-Up Priority List
1094022Sstever@eecs.umich.edu        for (ThreadID tid = 0; tid < numThreads; tid++) {
11010885Sandreas.hansson@arm.com            priority_list.push_back(tid);
11110885Sandreas.hansson@arm.com        }
1124626Sstever@eecs.umich.edu
1134626Sstever@eecs.umich.edu        DPRINTF(Commit,"Commit Policy set to Round Robin.");
1147669Ssteve.reinhardt@amd.com    } else if (policy == "oldestready"){
1154626Sstever@eecs.umich.edu        commitPolicy = OldestReady;
1164040Ssaidi@eecs.umich.edu
1174040Ssaidi@eecs.umich.edu        DPRINTF(Commit,"Commit Policy set to Oldest Ready.");
1185650Sgblack@eecs.umich.edu    } else {
1195650Sgblack@eecs.umich.edu        assert(0 && "Invalid SMT Commit Policy. Options Are: {Aggressive,"
12011256Santhony.gutierrez@amd.com               "RoundRobin,OldestReady}");
12111256Santhony.gutierrez@amd.com    }
12212347Snikos.nikoleris@arm.com
12312347Snikos.nikoleris@arm.com    for (ThreadID tid = 0; tid < numThreads; tid++) {
12412347Snikos.nikoleris@arm.com        commitStatus[tid] = Idle;
12512347Snikos.nikoleris@arm.com        changedROBNumEntries[tid] = false;
1264870Sstever@eecs.umich.edu        checkEmptyROB[tid] = false;
1274870Sstever@eecs.umich.edu        trapInFlight[tid] = false;
1284870Sstever@eecs.umich.edu        committedStores[tid] = false;
1294870Sstever@eecs.umich.edu        trapSquash[tid] = false;
1304870Sstever@eecs.umich.edu        tcSquash[tid] = false;
1314870Sstever@eecs.umich.edu        pc[tid].set(0);
1328436SBrad.Beckmann@amd.com    }
1338436SBrad.Beckmann@amd.com#if FULL_SYSTEM
1345314Sstever@gmail.com    interrupt = NoFault;
1355314Sstever@gmail.com#endif
1368184Ssomayeh@cs.wisc.edu}
13710886Sandreas.hansson@arm.com
13810886Sandreas.hansson@arm.comtemplate <class Impl>
1394022Sstever@eecs.umich.edustd::string
1404022Sstever@eecs.umich.eduDefaultCommit<Impl>::name() const
1414022Sstever@eecs.umich.edu{
1424022Sstever@eecs.umich.edu    return cpu->name() + ".commit";
1435735Snate@binkert.org}
1445735Snate@binkert.org
1455735Snate@binkert.orgtemplate <class Impl>
1464022Sstever@eecs.umich.eduvoid
1474022Sstever@eecs.umich.eduDefaultCommit<Impl>::regStats()
1484626Sstever@eecs.umich.edu{
1494626Sstever@eecs.umich.edu    using namespace Stats;
1507465Ssteve.reinhardt@amd.com    commitCommittedInsts
1514022Sstever@eecs.umich.edu        .name(name() + ".commitCommittedInsts")
15212347Snikos.nikoleris@arm.com        .desc("The number of committed instructions")
15311284Sandreas.hansson@arm.com        .prereq(commitCommittedInsts);
1544626Sstever@eecs.umich.edu    commitSquashedInsts
1554626Sstever@eecs.umich.edu        .name(name() + ".commitSquashedInsts")
1564626Sstever@eecs.umich.edu        .desc("The number of squashed insts skipped by commit")
15711199Sandreas.hansson@arm.com        .prereq(commitSquashedInsts);
1584022Sstever@eecs.umich.edu    commitSquashEvents
1594022Sstever@eecs.umich.edu        .name(name() + ".commitSquashEvents")
1606076Sgblack@eecs.umich.edu        .desc("The number of times commit is told to squash")
1614626Sstever@eecs.umich.edu        .prereq(commitSquashEvents);
1624870Sstever@eecs.umich.edu    commitNonSpecStalls
1635314Sstever@gmail.com        .name(name() + ".commitNonSpecStalls")
1648184Ssomayeh@cs.wisc.edu        .desc("The number of times commit has been forced to stall to "
16511600Sandreas.hansson@arm.com              "communicate backwards")
1664022Sstever@eecs.umich.edu        .prereq(commitNonSpecStalls);
1674022Sstever@eecs.umich.edu    branchMispredicts
1684022Sstever@eecs.umich.edu        .name(name() + ".branchMispredicts")
1695735Snate@binkert.org        .desc("The number of times a branch was mispredicted")
1705735Snate@binkert.org        .prereq(branchMispredicts);
1715735Snate@binkert.org    numCommittedDist
1725735Snate@binkert.org        .init(0,commitWidth,1)
1735735Snate@binkert.org        .name(name() + ".COM:committed_per_cycle")
1745735Snate@binkert.org        .desc("Number of insts commited each cycle")
1755735Snate@binkert.org        .flags(Stats::pdf)
1764022Sstever@eecs.umich.edu        ;
1775735Snate@binkert.org
1785735Snate@binkert.org    statComInst
1794022Sstever@eecs.umich.edu        .init(cpu->numThreads)
1805735Snate@binkert.org        .name(name() + ".COM:count")
1814022Sstever@eecs.umich.edu        .desc("Number of instructions committed")
1824022Sstever@eecs.umich.edu        .flags(total)
1834022Sstever@eecs.umich.edu        ;
1845735Snate@binkert.org
1854022Sstever@eecs.umich.edu    statComSwp
1864022Sstever@eecs.umich.edu        .init(cpu->numThreads)
1874022Sstever@eecs.umich.edu        .name(name() + ".COM:swp_count")
1884022Sstever@eecs.umich.edu        .desc("Number of s/w prefetches committed")
1894022Sstever@eecs.umich.edu        .flags(total)
1904022Sstever@eecs.umich.edu        ;
1915735Snate@binkert.org
1925735Snate@binkert.org    statComRefs
1935735Snate@binkert.org        .init(cpu->numThreads)
1944022Sstever@eecs.umich.edu        .name(name() +  ".COM:refs")
1954022Sstever@eecs.umich.edu        .desc("Number of memory references committed")
1964022Sstever@eecs.umich.edu        .flags(total)
1974022Sstever@eecs.umich.edu        ;
1984022Sstever@eecs.umich.edu
19910583SCurtis.Dunham@arm.com    statComLoads
20010583SCurtis.Dunham@arm.com        .init(cpu->numThreads)
20110583SCurtis.Dunham@arm.com        .name(name() +  ".COM:loads")
20210583SCurtis.Dunham@arm.com        .desc("Number of loads committed")
20310583SCurtis.Dunham@arm.com        .flags(total)
20411284Sandreas.hansson@arm.com        ;
20510583SCurtis.Dunham@arm.com
20610583SCurtis.Dunham@arm.com    statComMembars
20711199Sandreas.hansson@arm.com        .init(cpu->numThreads)
20812347Snikos.nikoleris@arm.com        .name(name() +  ".COM:membars")
20911600Sandreas.hansson@arm.com        .desc("Number of memory barriers committed")
21011199Sandreas.hansson@arm.com        .flags(total)
21111199Sandreas.hansson@arm.com        ;
21211199Sandreas.hansson@arm.com
21311199Sandreas.hansson@arm.com    statComBranches
21411199Sandreas.hansson@arm.com        .init(cpu->numThreads)
21511199Sandreas.hansson@arm.com        .name(name() + ".COM:branches")
21610570Sandreas.hansson@arm.com        .desc("Number of branches committed")
21710570Sandreas.hansson@arm.com        .flags(total)
21810570Sandreas.hansson@arm.com        ;
21910570Sandreas.hansson@arm.com
22010570Sandreas.hansson@arm.com    commitEligible
22110570Sandreas.hansson@arm.com        .init(cpu->numThreads)
2224022Sstever@eecs.umich.edu        .name(name() + ".COM:bw_limited")
2236102Sgblack@eecs.umich.edu        .desc("number of insts not committed due to BW limits")
22410343SCurtis.Dunham@arm.com        .flags(total)
22510343SCurtis.Dunham@arm.com        ;
22610343SCurtis.Dunham@arm.com
22710343SCurtis.Dunham@arm.com    commitEligibleSamples
2284870Sstever@eecs.umich.edu        .name(name() + ".COM:bw_lim_events")
2295314Sstever@gmail.com        .desc("number cycles where commit BW limit reached")
2308184Ssomayeh@cs.wisc.edu        ;
2314022Sstever@eecs.umich.edu}
23211294Sandreas.hansson@arm.com
2335735Snate@binkert.orgtemplate <class Impl>
2345735Snate@binkert.orgvoid
2354022Sstever@eecs.umich.eduDefaultCommit<Impl>::setThreads(std::vector<Thread *> &threads)
2364022Sstever@eecs.umich.edu{
2374022Sstever@eecs.umich.edu    thread = threads;
2385735Snate@binkert.org}
2395735Snate@binkert.org
2404022Sstever@eecs.umich.edutemplate <class Impl>
2414022Sstever@eecs.umich.eduvoid
2425735Snate@binkert.orgDefaultCommit<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
2435735Snate@binkert.org{
2445735Snate@binkert.org    timeBuffer = tb_ptr;
2454022Sstever@eecs.umich.edu
2465735Snate@binkert.org    // Setup wire to send information back to IEW.
2475735Snate@binkert.org    toIEW = timeBuffer->getWire(0);
2484022Sstever@eecs.umich.edu
2494022Sstever@eecs.umich.edu    // Setup wire to read data from IEW (for the ROB).
2502381SN/A    robInfoFromIEW = timeBuffer->getWire(-iewToCommitDelay);
2512662Sstever@eecs.umich.edu}
2522662Sstever@eecs.umich.edu
2532662Sstever@eecs.umich.edutemplate <class Impl>
2542662Sstever@eecs.umich.eduvoid
2552662Sstever@eecs.umich.eduDefaultCommit<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr)
2562381SN/A{
2579044SAli.Saidi@ARM.com    fetchQueue = fq_ptr;
2582381SN/A
2592813Srdreslin@umich.edu    // Setup wire to get instructions from rename (for the ROB).
2605735Snate@binkert.org    fromFetch = fetchQueue->getWire(-fetchToCommitDelay);
2615735Snate@binkert.org}
2624022Sstever@eecs.umich.edu
2635735Snate@binkert.orgtemplate <class Impl>
2645735Snate@binkert.orgvoid
26510938Sandreas.hansson@arm.comDefaultCommit<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
26610938Sandreas.hansson@arm.com{
26712349Snikos.nikoleris@arm.com    renameQueue = rq_ptr;
26810938Sandreas.hansson@arm.com
26913732Snikos.nikoleris@arm.com    // Setup wire to get instructions from rename (for the ROB).
27013732Snikos.nikoleris@arm.com    fromRename = renameQueue->getWire(-renameToROBDelay);
27113732Snikos.nikoleris@arm.com}
27211284Sandreas.hansson@arm.com
27311284Sandreas.hansson@arm.comtemplate <class Impl>
27411284Sandreas.hansson@arm.comvoid
27511284Sandreas.hansson@arm.comDefaultCommit<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
27610938Sandreas.hansson@arm.com{
27710938Sandreas.hansson@arm.com    iewQueue = iq_ptr;
27810938Sandreas.hansson@arm.com
27911284Sandreas.hansson@arm.com    // Setup wire to get instructions from IEW.
28011284Sandreas.hansson@arm.com    fromIEW = iewQueue->getWire(-iewToCommitDelay);
28111284Sandreas.hansson@arm.com}
28211284Sandreas.hansson@arm.com
28311284Sandreas.hansson@arm.comtemplate <class Impl>
28411284Sandreas.hansson@arm.comvoid
28511284Sandreas.hansson@arm.comDefaultCommit<Impl>::setIEWStage(IEW *iew_stage)
28611284Sandreas.hansson@arm.com{
28711284Sandreas.hansson@arm.com    iewStage = iew_stage;
28810938Sandreas.hansson@arm.com}
28912346Snikos.nikoleris@arm.com
29012346Snikos.nikoleris@arm.comtemplate<class Impl>
29112346Snikos.nikoleris@arm.comvoid
29212346Snikos.nikoleris@arm.comDefaultCommit<Impl>::setActiveThreads(list<ThreadID> *at_ptr)
29312349Snikos.nikoleris@arm.com{
29412349Snikos.nikoleris@arm.com    activeThreads = at_ptr;
29512349Snikos.nikoleris@arm.com}
29612349Snikos.nikoleris@arm.com
29711057Sandreas.hansson@arm.comtemplate <class Impl>
29811057Sandreas.hansson@arm.comvoid
29911057Sandreas.hansson@arm.comDefaultCommit<Impl>::setRenameMap(RenameMap rm_ptr[])
30011057Sandreas.hansson@arm.com{
30110938Sandreas.hansson@arm.com    for (ThreadID tid = 0; tid < numThreads; tid++)
30210938Sandreas.hansson@arm.com        renameMap[tid] = &rm_ptr[tid];
30310938Sandreas.hansson@arm.com}
30410938Sandreas.hansson@arm.com
30510938Sandreas.hansson@arm.comtemplate <class Impl>
30610938Sandreas.hansson@arm.comvoid
30710938Sandreas.hansson@arm.comDefaultCommit<Impl>::setROB(ROB *rob_ptr)
30810938Sandreas.hansson@arm.com{
30910938Sandreas.hansson@arm.com    rob = rob_ptr;
31010938Sandreas.hansson@arm.com}
31110938Sandreas.hansson@arm.com
31210938Sandreas.hansson@arm.comtemplate <class Impl>
31310938Sandreas.hansson@arm.comvoid
31410938Sandreas.hansson@arm.comDefaultCommit<Impl>::initStage()
31510938Sandreas.hansson@arm.com{
31610938Sandreas.hansson@arm.com    rob->setActiveThreads(activeThreads);
3175735Snate@binkert.org    rob->resetEntries();
3185735Snate@binkert.org
3195735Snate@binkert.org    // Broadcast the number of free entries.
3205735Snate@binkert.org    for (ThreadID tid = 0; tid < numThreads; tid++) {
3214022Sstever@eecs.umich.edu        toIEW->commitInfo[tid].usedROB = true;
3224022Sstever@eecs.umich.edu        toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid);
3235735Snate@binkert.org        toIEW->commitInfo[tid].emptyROB = true;
3244870Sstever@eecs.umich.edu    }
3254870Sstever@eecs.umich.edu
32612351Snikos.nikoleris@arm.com    // Commit must broadcast the number of free entries it has at the
32712351Snikos.nikoleris@arm.com    // start of the simulation, so it starts as active.
3285735Snate@binkert.org    cpu->activateStage(O3CPU::CommitIdx);
32912749Sgiacomo.travaglini@arm.com
3304870Sstever@eecs.umich.edu    cpu->activityThisCycle();
3312566SN/A    trapLatency = cpu->ticks(trapLatency);
3325735Snate@binkert.org}
33312633Sodanrc@yahoo.com.br
33412633Sodanrc@yahoo.com.brtemplate <class Impl>
3355735Snate@binkert.orgbool
33612633Sodanrc@yahoo.com.brDefaultCommit<Impl>::drain()
3375735Snate@binkert.org{
3382566SN/A    drainPending = true;
3392566SN/A
3402566SN/A    return false;
3415735Snate@binkert.org}
3425735Snate@binkert.org
3432381SN/Atemplate <class Impl>
3442381SN/Avoid
34510028SGiacomo.Gabrielli@arm.comDefaultCommit<Impl>::switchOut()
34610028SGiacomo.Gabrielli@arm.com{
34710028SGiacomo.Gabrielli@arm.com    switchedOut = true;
3485735Snate@binkert.org    drainPending = false;
3496227Snate@binkert.org    rob->switchOut();
3502381SN/A}
3515735Snate@binkert.org
35210723Sandreas.hansson@arm.comtemplate <class Impl>
3538668Sgeoffrey.blake@arm.comvoid
35410723Sandreas.hansson@arm.comDefaultCommit<Impl>::resume()
3558668Sgeoffrey.blake@arm.com{
35612966SMatteo.Andreozzi@arm.com    drainPending = false;
35712966SMatteo.Andreozzi@arm.com}
35812966SMatteo.Andreozzi@arm.com
3592641Sstever@eecs.umich.edutemplate <class Impl>
3602811Srdreslin@umich.eduvoid
3619547Sandreas.hansson@arm.comDefaultCommit<Impl>::takeOverFrom()
36210694SMarco.Balboni@ARM.com{
36310405Sandreas.hansson@arm.com    switchedOut = false;
36410405Sandreas.hansson@arm.com    _status = Active;
36510405Sandreas.hansson@arm.com    _nextStatus = Inactive;
36610405Sandreas.hansson@arm.com    for (ThreadID tid = 0; tid < numThreads; tid++) {
3679547Sandreas.hansson@arm.com        commitStatus[tid] = Idle;
36810694SMarco.Balboni@ARM.com        changedROBNumEntries[tid] = false;
3693218Sgblack@eecs.umich.edu        trapSquash[tid] = false;
3709547Sandreas.hansson@arm.com        tcSquash[tid] = false;
37111127Sandreas.hansson@arm.com    }
37211127Sandreas.hansson@arm.com    squashCounter = 0;
37311127Sandreas.hansson@arm.com    rob->takeOverFrom();
37411127Sandreas.hansson@arm.com}
37511127Sandreas.hansson@arm.com
37611127Sandreas.hansson@arm.comtemplate <class Impl>
37711127Sandreas.hansson@arm.comvoid
37811127Sandreas.hansson@arm.comDefaultCommit<Impl>::updateStatus()
37910694SMarco.Balboni@ARM.com{
38010694SMarco.Balboni@ARM.com    // reset ROB changed variable
38110694SMarco.Balboni@ARM.com    list<ThreadID>::iterator threads = activeThreads->begin();
38210694SMarco.Balboni@ARM.com    list<ThreadID>::iterator end = activeThreads->end();
38310405Sandreas.hansson@arm.com
38410405Sandreas.hansson@arm.com    while (threads != end) {
3859547Sandreas.hansson@arm.com        ThreadID tid = *threads++;
38610694SMarco.Balboni@ARM.com
3873218Sgblack@eecs.umich.edu        changedROBNumEntries[tid] = false;
3885735Snate@binkert.org
3895735Snate@binkert.org        // Also check if any of the threads has a trap pending
3909542Sandreas.hansson@arm.com        if (commitStatus[tid] == TrapPending ||
3919542Sandreas.hansson@arm.com            commitStatus[tid] == FetchTrapPending) {
3929542Sandreas.hansson@arm.com            _nextStatus = Active;
3939542Sandreas.hansson@arm.com        }
3949542Sandreas.hansson@arm.com    }
3959542Sandreas.hansson@arm.com
3969542Sandreas.hansson@arm.com    if (_nextStatus == Inactive && _status == Active) {
3979542Sandreas.hansson@arm.com        DPRINTF(Activity, "Deactivating stage.\n");
3989542Sandreas.hansson@arm.com        cpu->deactivateStage(O3CPU::CommitIdx);
3999542Sandreas.hansson@arm.com    } else if (_nextStatus == Active && _status == Inactive) {
4009542Sandreas.hansson@arm.com        DPRINTF(Activity, "Activating stage.\n");
4019542Sandreas.hansson@arm.com        cpu->activateStage(O3CPU::CommitIdx);
4029542Sandreas.hansson@arm.com    }
4039542Sandreas.hansson@arm.com
4045735Snate@binkert.org    _status = _nextStatus;
4055735Snate@binkert.org}
4065735Snate@binkert.org
4079542Sandreas.hansson@arm.comtemplate <class Impl>
4089542Sandreas.hansson@arm.comvoid
4092641Sstever@eecs.umich.eduDefaultCommit<Impl>::setNextStatus()
4102641Sstever@eecs.umich.edu{
4112641Sstever@eecs.umich.edu    int squashes = 0;
4125315Sstever@gmail.com
4135315Sstever@gmail.com    list<ThreadID>::iterator threads = activeThreads->begin();
4145315Sstever@gmail.com    list<ThreadID>::iterator end = activeThreads->end();
4155315Sstever@gmail.com
4169044SAli.Saidi@ARM.com    while (threads != end) {
4175735Snate@binkert.org        ThreadID tid = *threads++;
4185735Snate@binkert.org
4195735Snate@binkert.org        if (commitStatus[tid] == ROBSquashing) {
4205735Snate@binkert.org            squashes++;
4215735Snate@binkert.org        }
4225735Snate@binkert.org    }
4235735Snate@binkert.org
4245314Sstever@gmail.com    squashCounter = squashes;
4255314Sstever@gmail.com
4265314Sstever@gmail.com    // If commit is currently squashing, then it will have activity for the
4275735Snate@binkert.org    // next cycle. Set its next status as active.
4285314Sstever@gmail.com    if (squashCounter) {
4295314Sstever@gmail.com        _nextStatus = Active;
4305314Sstever@gmail.com    }
4315314Sstever@gmail.com}
4325314Sstever@gmail.com
4335314Sstever@gmail.comtemplate <class Impl>
4345314Sstever@gmail.combool
4355314Sstever@gmail.comDefaultCommit<Impl>::changedROBEntries()
4365314Sstever@gmail.com{
4375314Sstever@gmail.com    list<ThreadID>::iterator threads = activeThreads->begin();
4385314Sstever@gmail.com    list<ThreadID>::iterator end = activeThreads->end();
4395314Sstever@gmail.com
4405314Sstever@gmail.com    while (threads != end) {
4415314Sstever@gmail.com        ThreadID tid = *threads++;
4425735Snate@binkert.org
4435735Snate@binkert.org        if (changedROBNumEntries[tid]) {
4445735Snate@binkert.org            return true;
4455314Sstever@gmail.com        }
4465315Sstever@gmail.com    }
4475735Snate@binkert.org
4485735Snate@binkert.org    return false;
4495315Sstever@gmail.com}
4505735Snate@binkert.org
4515735Snate@binkert.orgtemplate <class Impl>
4525314Sstever@gmail.comsize_t
4535314Sstever@gmail.comDefaultCommit<Impl>::numROBFreeEntries(ThreadID tid)
4545735Snate@binkert.org{
4555735Snate@binkert.org    return rob->numFreeEntries(tid);
4565735Snate@binkert.org}
4575735Snate@binkert.org
4585314Sstever@gmail.comtemplate <class Impl>
4595735Snate@binkert.orgvoid
4605735Snate@binkert.orgDefaultCommit<Impl>::generateTrapEvent(ThreadID tid)
4615735Snate@binkert.org{
4625315Sstever@gmail.com    DPRINTF(Commit, "Generating trap event for [tid:%i]\n", tid);
4635735Snate@binkert.org
4645735Snate@binkert.org    TrapEvent *trap = new TrapEvent(this, tid);
4655314Sstever@gmail.com
4665735Snate@binkert.org    cpu->schedule(trap, curTick + trapLatency);
4675735Snate@binkert.org    trapInFlight[tid] = true;
4685735Snate@binkert.org}
4695735Snate@binkert.org
4705735Snate@binkert.orgtemplate <class Impl>
4715314Sstever@gmail.comvoid
4725314Sstever@gmail.comDefaultCommit<Impl>::generateTCEvent(ThreadID tid)
4735314Sstever@gmail.com{
4745735Snate@binkert.org    assert(!trapInFlight[tid]);
4755735Snate@binkert.org    DPRINTF(Commit, "Generating TC squash event for [tid:%i]\n", tid);
4765735Snate@binkert.org
4775735Snate@binkert.org    tcSquash[tid] = true;
4789542Sandreas.hansson@arm.com}
4795735Snate@binkert.org
4805735Snate@binkert.orgtemplate <class Impl>
4815735Snate@binkert.orgvoid
4822662Sstever@eecs.umich.eduDefaultCommit<Impl>::squashAll(ThreadID tid)
4832641Sstever@eecs.umich.edu{
4849542Sandreas.hansson@arm.com    // If we want to include the squashing instruction in the squash,
4859542Sandreas.hansson@arm.com    // then use one older sequence number.
4869542Sandreas.hansson@arm.com    // Hopefully this doesn't mess things up.  Basically I want to squash
4879542Sandreas.hansson@arm.com    // all instructions of this thread.
4889542Sandreas.hansson@arm.com    InstSeqNum squashed_inst = rob->isEmpty() ?
4899542Sandreas.hansson@arm.com        0 : rob->readHeadInst(tid)->seqNum - 1;
4909542Sandreas.hansson@arm.com
4919542Sandreas.hansson@arm.com    // All younger instructions will be squashed. Set the sequence
4929542Sandreas.hansson@arm.com    // number as the youngest instruction in the ROB (0 in this case.
4939542Sandreas.hansson@arm.com    // Hopefully nothing breaks.)
4949542Sandreas.hansson@arm.com    youngestSeqNum[tid] = 0;
4959542Sandreas.hansson@arm.com
4969542Sandreas.hansson@arm.com    rob->squash(squashed_inst, tid);
4979542Sandreas.hansson@arm.com    changedROBNumEntries[tid] = true;
4989542Sandreas.hansson@arm.com
4999542Sandreas.hansson@arm.com    // Send back the sequence number of the squashed instruction.
5009542Sandreas.hansson@arm.com    toIEW->commitInfo[tid].doneSeqNum = squashed_inst;
5019542Sandreas.hansson@arm.com
5029542Sandreas.hansson@arm.com    // Send back the squash signal to tell stages that they should
5039542Sandreas.hansson@arm.com    // squash.
5049543Ssascha.bischoff@arm.com    toIEW->commitInfo[tid].squash = true;
5059543Ssascha.bischoff@arm.com
5069543Ssascha.bischoff@arm.com    // Send back the rob squashing signal so other stages know that
5079543Ssascha.bischoff@arm.com    // the ROB is in the process of squashing.
5089543Ssascha.bischoff@arm.com    toIEW->commitInfo[tid].robSquashing = true;
5099543Ssascha.bischoff@arm.com
5109543Ssascha.bischoff@arm.com    toIEW->commitInfo[tid].branchMispredict = false;
5119543Ssascha.bischoff@arm.com
5129543Ssascha.bischoff@arm.com    toIEW->commitInfo[tid].pc = pc[tid];
5139543Ssascha.bischoff@arm.com}
5149543Ssascha.bischoff@arm.com
5159543Ssascha.bischoff@arm.comtemplate <class Impl>
5169543Ssascha.bischoff@arm.comvoid
5179543Ssascha.bischoff@arm.comDefaultCommit<Impl>::squashFromTrap(ThreadID tid)
5189543Ssascha.bischoff@arm.com{
5199543Ssascha.bischoff@arm.com    squashAll(tid);
5209543Ssascha.bischoff@arm.com
5219543Ssascha.bischoff@arm.com    DPRINTF(Commit, "Squashing from trap, restarting at PC %s\n", pc[tid]);
5229543Ssascha.bischoff@arm.com
5235735Snate@binkert.org    thread[tid]->trapPending = false;
5245735Snate@binkert.org    thread[tid]->inSyscall = false;
5254022Sstever@eecs.umich.edu    trapInFlight[tid] = false;
5262811Srdreslin@umich.edu
5275735Snate@binkert.org    trapSquash[tid] = false;
5284022Sstever@eecs.umich.edu
5292811Srdreslin@umich.edu    commitStatus[tid] = ROBSquashing;
53010583SCurtis.Dunham@arm.com    cpu->activityThisCycle();
53110583SCurtis.Dunham@arm.com}
53210583SCurtis.Dunham@arm.com
53310583SCurtis.Dunham@arm.comtemplate <class Impl>
53410583SCurtis.Dunham@arm.comvoid
53511287Sandreas.hansson@arm.comDefaultCommit<Impl>::squashFromTC(ThreadID tid)
53611287Sandreas.hansson@arm.com{
53711287Sandreas.hansson@arm.com    squashAll(tid);
53811287Sandreas.hansson@arm.com
53911287Sandreas.hansson@arm.com    DPRINTF(Commit, "Squashing from TC, restarting at PC %s\n", pc[tid]);
54011287Sandreas.hansson@arm.com
54111287Sandreas.hansson@arm.com    thread[tid]->inSyscall = false;
54211287Sandreas.hansson@arm.com    assert(!thread[tid]->trapPending);
54311287Sandreas.hansson@arm.com
54410583SCurtis.Dunham@arm.com    commitStatus[tid] = ROBSquashing;
54510583SCurtis.Dunham@arm.com    cpu->activityThisCycle();
54611199Sandreas.hansson@arm.com
54712347Snikos.nikoleris@arm.com    tcSquash[tid] = false;
54811600Sandreas.hansson@arm.com}
54911199Sandreas.hansson@arm.com
55010583SCurtis.Dunham@arm.comtemplate <class Impl>
55111286Sandreas.hansson@arm.comvoid
55211286Sandreas.hansson@arm.comDefaultCommit<Impl>::tick()
55311286Sandreas.hansson@arm.com{
55411286Sandreas.hansson@arm.com    wroteToTimeBuffer = false;
55511286Sandreas.hansson@arm.com    _nextStatus = Inactive;
55610583SCurtis.Dunham@arm.com
55710583SCurtis.Dunham@arm.com    if (drainPending && rob->isEmpty() && !iewStage->hasStoresToWB()) {
55810583SCurtis.Dunham@arm.com        cpu->signalDrained();
55910583SCurtis.Dunham@arm.com        drainPending = false;
5602812Srdreslin@umich.edu        return;
56113350Snikos.nikoleris@arm.com    }
56213350Snikos.nikoleris@arm.com
56313350Snikos.nikoleris@arm.com    if (activeThreads->empty())
56413350Snikos.nikoleris@arm.com        return;
56513350Snikos.nikoleris@arm.com
56613350Snikos.nikoleris@arm.com    list<ThreadID>::iterator threads = activeThreads->begin();
56711284Sandreas.hansson@arm.com    list<ThreadID>::iterator end = activeThreads->end();
56811284Sandreas.hansson@arm.com
56911284Sandreas.hansson@arm.com    // Check if any of the threads are done squashing.  Change the
57011284Sandreas.hansson@arm.com    // status if they are done.
57111284Sandreas.hansson@arm.com    while (threads != end) {
57211284Sandreas.hansson@arm.com        ThreadID tid = *threads++;
57311284Sandreas.hansson@arm.com
57411284Sandreas.hansson@arm.com        // Clear the bit saying if the thread has committed stores
57511284Sandreas.hansson@arm.com        // this cycle.
57611284Sandreas.hansson@arm.com        committedStores[tid] = false;
57711284Sandreas.hansson@arm.com
57811284Sandreas.hansson@arm.com        if (commitStatus[tid] == ROBSquashing) {
57911284Sandreas.hansson@arm.com
58011284Sandreas.hansson@arm.com            if (rob->isDoneSquashing(tid)) {
58111284Sandreas.hansson@arm.com                commitStatus[tid] = Running;
58211284Sandreas.hansson@arm.com            } else {
58311284Sandreas.hansson@arm.com                DPRINTF(Commit,"[tid:%u]: Still Squashing, cannot commit any"
58411284Sandreas.hansson@arm.com                        " insts this cycle.\n", tid);
58511284Sandreas.hansson@arm.com                rob->doSquash(tid);
58611284Sandreas.hansson@arm.com                toIEW->commitInfo[tid].robSquashing = true;
58711284Sandreas.hansson@arm.com                wroteToTimeBuffer = true;
58810567Sandreas.hansson@arm.com            }
58910567Sandreas.hansson@arm.com        }
59011284Sandreas.hansson@arm.com    }
59111284Sandreas.hansson@arm.com
59210567Sandreas.hansson@arm.com    commit();
59311284Sandreas.hansson@arm.com
59411284Sandreas.hansson@arm.com    markCompletedInsts();
59511284Sandreas.hansson@arm.com
59611284Sandreas.hansson@arm.com    threads = activeThreads->begin();
59711284Sandreas.hansson@arm.com
59811284Sandreas.hansson@arm.com    while (threads != end) {
59911284Sandreas.hansson@arm.com        ThreadID tid = *threads++;
60011284Sandreas.hansson@arm.com
60111284Sandreas.hansson@arm.com        if (!rob->isEmpty(tid) && rob->readHeadInst(tid)->readyToCommit()) {
60211284Sandreas.hansson@arm.com            // The ROB has more instructions it can commit. Its next status
60311284Sandreas.hansson@arm.com            // will be active.
60411284Sandreas.hansson@arm.com            _nextStatus = Active;
60511284Sandreas.hansson@arm.com
60611284Sandreas.hansson@arm.com            DynInstPtr inst = rob->readHeadInst(tid);
60711284Sandreas.hansson@arm.com
60811284Sandreas.hansson@arm.com            DPRINTF(Commit,"[tid:%i]: Instruction [sn:%lli] PC %s is head of"
60911284Sandreas.hansson@arm.com                    " ROB and ready to commit\n",
61011284Sandreas.hansson@arm.com                    tid, inst->seqNum, inst->pcState());
61111284Sandreas.hansson@arm.com
61211284Sandreas.hansson@arm.com        } else if (!rob->isEmpty(tid)) {
61311284Sandreas.hansson@arm.com            DynInstPtr inst = rob->readHeadInst(tid);
61411284Sandreas.hansson@arm.com
61511284Sandreas.hansson@arm.com            DPRINTF(Commit,"[tid:%i]: Can't commit, Instruction [sn:%lli] PC "
61611284Sandreas.hansson@arm.com                    "%s is head of ROB and not ready\n",
61711284Sandreas.hansson@arm.com                    tid, inst->seqNum, inst->pcState());
61811284Sandreas.hansson@arm.com        }
61911284Sandreas.hansson@arm.com
62011284Sandreas.hansson@arm.com        DPRINTF(Commit, "[tid:%i]: ROB has %d insts & %d free entries.\n",
62111284Sandreas.hansson@arm.com                tid, rob->countInsts(tid), rob->numFreeEntries(tid));
6224870Sstever@eecs.umich.edu    }
62311284Sandreas.hansson@arm.com
62411284Sandreas.hansson@arm.com
62511284Sandreas.hansson@arm.com    if (wroteToTimeBuffer) {
62611284Sandreas.hansson@arm.com        DPRINTF(Activity, "Activity This Cycle.\n");
62711284Sandreas.hansson@arm.com        cpu->activityThisCycle();
62811284Sandreas.hansson@arm.com    }
62911284Sandreas.hansson@arm.com
63011284Sandreas.hansson@arm.com    updateStatus();
63111284Sandreas.hansson@arm.com}
63211284Sandreas.hansson@arm.com
63311284Sandreas.hansson@arm.com#if FULL_SYSTEM
63411284Sandreas.hansson@arm.comtemplate <class Impl>
63511284Sandreas.hansson@arm.comvoid
63611284Sandreas.hansson@arm.comDefaultCommit<Impl>::handleInterrupt()
63711284Sandreas.hansson@arm.com{
63811284Sandreas.hansson@arm.com    if (interrupt != NoFault) {
63911284Sandreas.hansson@arm.com        // Wait until the ROB is empty and all stores have drained in
64011284Sandreas.hansson@arm.com        // order to enter the interrupt.
64111284Sandreas.hansson@arm.com        if (rob->isEmpty() && !iewStage->hasStoresToWB()) {
64211284Sandreas.hansson@arm.com            // Squash or record that I need to squash this cycle if
64311284Sandreas.hansson@arm.com            // an interrupt needed to be handled.
64411284Sandreas.hansson@arm.com            DPRINTF(Commit, "Interrupt detected.\n");
64511284Sandreas.hansson@arm.com
64611284Sandreas.hansson@arm.com            // Clear the interrupt now that it's going to be handled
64711284Sandreas.hansson@arm.com            toIEW->commitInfo[0].clearInterrupt = true;
64811284Sandreas.hansson@arm.com
64911284Sandreas.hansson@arm.com            assert(!thread[0]->inSyscall);
65011746Snikos.nikoleris@arm.com            thread[0]->inSyscall = true;
65111284Sandreas.hansson@arm.com
65211284Sandreas.hansson@arm.com            // CPU will handle interrupt.
65311284Sandreas.hansson@arm.com            cpu->processInterrupts(interrupt);
65411284Sandreas.hansson@arm.com
65511284Sandreas.hansson@arm.com            thread[0]->inSyscall = false;
65612346Snikos.nikoleris@arm.com
65713732Snikos.nikoleris@arm.com            commitStatus[0] = TrapPending;
65813732Snikos.nikoleris@arm.com
65913732Snikos.nikoleris@arm.com            // Generate trap squash event.
66013732Snikos.nikoleris@arm.com            generateTrapEvent(0);
66113732Snikos.nikoleris@arm.com
66213732Snikos.nikoleris@arm.com            interrupt = NoFault;
66313732Snikos.nikoleris@arm.com        } else {
66413732Snikos.nikoleris@arm.com            DPRINTF(Commit, "Interrupt pending, waiting for ROB to empty.\n");
66513732Snikos.nikoleris@arm.com        }
66612346Snikos.nikoleris@arm.com    } else if (commitStatus[0] != TrapPending &&
66712346Snikos.nikoleris@arm.com               cpu->checkInterrupts(cpu->tcBase(0)) &&
66812346Snikos.nikoleris@arm.com               !trapSquash[0] &&
66912346Snikos.nikoleris@arm.com               !tcSquash[0]) {
67012346Snikos.nikoleris@arm.com        // Process interrupts if interrupts are enabled, not in PAL
67112346Snikos.nikoleris@arm.com        // mode, and no other traps or external squashes are currently
67212346Snikos.nikoleris@arm.com        // pending.
67312346Snikos.nikoleris@arm.com        // @todo: Allow other threads to handle interrupts.
67412346Snikos.nikoleris@arm.com
67512346Snikos.nikoleris@arm.com        // Get any interrupt that happened
67612346Snikos.nikoleris@arm.com        interrupt = cpu->getInterrupts();
67712346Snikos.nikoleris@arm.com
67812349Snikos.nikoleris@arm.com        if (interrupt != NoFault) {
67912349Snikos.nikoleris@arm.com            // Tell fetch that there is an interrupt pending.  This
68012349Snikos.nikoleris@arm.com            // will make fetch wait until it sees a non PAL-mode PC,
68112349Snikos.nikoleris@arm.com            // at which point it stops fetching instructions.
68212349Snikos.nikoleris@arm.com            toIEW->commitInfo[0].interruptPending = true;
68312349Snikos.nikoleris@arm.com        }
68412349Snikos.nikoleris@arm.com    }
68512349Snikos.nikoleris@arm.com}
68612349Snikos.nikoleris@arm.com#endif // FULL_SYSTEM
68712349Snikos.nikoleris@arm.com
68812349Snikos.nikoleris@arm.comtemplate <class Impl>
68912349Snikos.nikoleris@arm.comvoid
69012349Snikos.nikoleris@arm.comDefaultCommit<Impl>::commit()
6919951Sstephan.diestelhorst@arm.com{
6929951Sstephan.diestelhorst@arm.com
69310763Sali.jafri@arm.com#if FULL_SYSTEM
69410763Sali.jafri@arm.com    // Check for any interrupt, and start processing it.  Or if we
69510883Sali.jafri@arm.com    // have an outstanding interrupt and are at a point when it is
6964895Sstever@eecs.umich.edu    // valid to take an interrupt, process it.
69712966SMatteo.Andreozzi@arm.com    if (cpu->checkInterrupts(cpu->tcBase(0))) {
69812966SMatteo.Andreozzi@arm.com        handleInterrupt();
69912966SMatteo.Andreozzi@arm.com    }
70012966SMatteo.Andreozzi@arm.com#endif // FULL_SYSTEM
70112966SMatteo.Andreozzi@arm.com
70212966SMatteo.Andreozzi@arm.com    ////////////////////////////////////
70312966SMatteo.Andreozzi@arm.com    // Check for any possible squashes, handle them first
70412966SMatteo.Andreozzi@arm.com    ////////////////////////////////////
70512966SMatteo.Andreozzi@arm.com    list<ThreadID>::iterator threads = activeThreads->begin();
70612966SMatteo.Andreozzi@arm.com    list<ThreadID>::iterator end = activeThreads->end();
70712966SMatteo.Andreozzi@arm.com
70812966SMatteo.Andreozzi@arm.com    while (threads != end) {
70912966SMatteo.Andreozzi@arm.com        ThreadID tid = *threads++;
71012966SMatteo.Andreozzi@arm.com
71112966SMatteo.Andreozzi@arm.com        // Not sure which one takes priority.  I think if we have
71212966SMatteo.Andreozzi@arm.com        // both, that's a bad sign.
71312966SMatteo.Andreozzi@arm.com        if (trapSquash[tid] == true) {
71412966SMatteo.Andreozzi@arm.com            assert(!tcSquash[tid]);
71512966SMatteo.Andreozzi@arm.com            squashFromTrap(tid);
7164870Sstever@eecs.umich.edu        } else if (tcSquash[tid] == true) {
7174870Sstever@eecs.umich.edu            assert(commitStatus[tid] != TrapPending);
7184870Sstever@eecs.umich.edu            squashFromTC(tid);
7195735Snate@binkert.org        }
7205735Snate@binkert.org
7215735Snate@binkert.org        // Squashed sequence number must be older than youngest valid
7225735Snate@binkert.org        // instruction in the ROB. This prevents squashes from younger
7235735Snate@binkert.org        // instructions overriding squashes from older instructions.
7245735Snate@binkert.org        if (fromIEW->squash[tid] &&
7255735Snate@binkert.org            commitStatus[tid] != TrapPending &&
7264986Ssaidi@eecs.umich.edu            fromIEW->squashedSeqNum[tid] <= youngestSeqNum[tid]) {
7272814Srdreslin@umich.edu
72811057Sandreas.hansson@arm.com            DPRINTF(Commit, "[tid:%i]: Squashing due to PC %#x [sn:%i]\n",
7299259SAli.Saidi@ARM.com                    tid,
7309259SAli.Saidi@ARM.com                    fromIEW->mispredPC[tid],
7319259SAli.Saidi@ARM.com                    fromIEW->squashedSeqNum[tid]);
7329259SAli.Saidi@ARM.com
7339259SAli.Saidi@ARM.com            DPRINTF(Commit, "[tid:%i]: Redirecting to PC %#x\n",
7349259SAli.Saidi@ARM.com                    tid,
7359259SAli.Saidi@ARM.com                    fromIEW->pc[tid].nextInstAddr());
73611057Sandreas.hansson@arm.com
7379259SAli.Saidi@ARM.com            commitStatus[tid] = ROBSquashing;
73811057Sandreas.hansson@arm.com
73910938Sandreas.hansson@arm.com            // If we want to include the squashing instruction in the squash,
74013856Sodanrc@yahoo.com.br            // then use one older sequence number.
74113856Sodanrc@yahoo.com.br            InstSeqNum squashed_inst = fromIEW->squashedSeqNum[tid];
74213856Sodanrc@yahoo.com.br
74313856Sodanrc@yahoo.com.br            if (fromIEW->includeSquashInst[tid] == true) {
74413856Sodanrc@yahoo.com.br                squashed_inst--;
74513856Sodanrc@yahoo.com.br            }
74613856Sodanrc@yahoo.com.br
74710938Sandreas.hansson@arm.com            // All younger instructions will be squashed. Set the sequence
74810938Sandreas.hansson@arm.com            // number as the youngest instruction in the ROB.
74910938Sandreas.hansson@arm.com            youngestSeqNum[tid] = squashed_inst;
75010938Sandreas.hansson@arm.com
75110938Sandreas.hansson@arm.com            rob->squash(squashed_inst, tid);
75210938Sandreas.hansson@arm.com            changedROBNumEntries[tid] = true;
75310938Sandreas.hansson@arm.com
75410938Sandreas.hansson@arm.com            toIEW->commitInfo[tid].doneSeqNum = squashed_inst;
75510938Sandreas.hansson@arm.com
7562549SN/A            toIEW->commitInfo[tid].squash = true;
75711057Sandreas.hansson@arm.com
75811057Sandreas.hansson@arm.com            // Send back the rob squashing signal so other stages know that
75911057Sandreas.hansson@arm.com            // the ROB is in the process of squashing.
76011057Sandreas.hansson@arm.com            toIEW->commitInfo[tid].robSquashing = true;
76111057Sandreas.hansson@arm.com
76210028SGiacomo.Gabrielli@arm.com            toIEW->commitInfo[tid].branchMispredict =
7635735Snate@binkert.org                fromIEW->branchMispredict[tid];
76411306Santhony.gutierrez@amd.com
76511306Santhony.gutierrez@amd.com            toIEW->commitInfo[tid].branchTaken =
76611306Santhony.gutierrez@amd.com                fromIEW->branchTaken[tid];
76711306Santhony.gutierrez@amd.com
76811306Santhony.gutierrez@amd.com            toIEW->commitInfo[tid].pc = fromIEW->pc[tid];
76911306Santhony.gutierrez@amd.com
7707550SBrad.Beckmann@amd.com            toIEW->commitInfo[tid].mispredPC = fromIEW->mispredPC[tid];
77110938Sandreas.hansson@arm.com
7727550SBrad.Beckmann@amd.com            if (toIEW->commitInfo[tid].branchMispredict) {
7737550SBrad.Beckmann@amd.com                ++branchMispredicts;
7747550SBrad.Beckmann@amd.com            }
7757550SBrad.Beckmann@amd.com        }
7767550SBrad.Beckmann@amd.com
7777550SBrad.Beckmann@amd.com    }
7787550SBrad.Beckmann@amd.com
7797550SBrad.Beckmann@amd.com    setNextStatus();
7807550SBrad.Beckmann@amd.com
7817550SBrad.Beckmann@amd.com    if (squashCounter != numThreads) {
78210938Sandreas.hansson@arm.com        // If we're not currently squashing, then get instructions.
78310938Sandreas.hansson@arm.com        getInsts();
7847550SBrad.Beckmann@amd.com
7857550SBrad.Beckmann@amd.com        // Try to commit any instructions.
7867550SBrad.Beckmann@amd.com        commitInsts();
7877550SBrad.Beckmann@amd.com    }
7887550SBrad.Beckmann@amd.com
7897550SBrad.Beckmann@amd.com    //Check for any activity
7907550SBrad.Beckmann@amd.com    threads = activeThreads->begin();
7917550SBrad.Beckmann@amd.com
7927550SBrad.Beckmann@amd.com    while (threads != end) {
7937550SBrad.Beckmann@amd.com        ThreadID tid = *threads++;
79410938Sandreas.hansson@arm.com
79511057Sandreas.hansson@arm.com        if (changedROBNumEntries[tid]) {
79611057Sandreas.hansson@arm.com            toIEW->commitInfo[tid].usedROB = true;
7975735Snate@binkert.org            toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid);
79812749Sgiacomo.travaglini@arm.com
79912966SMatteo.Andreozzi@arm.com            wroteToTimeBuffer = true;
80012966SMatteo.Andreozzi@arm.com            changedROBNumEntries[tid] = false;
80112966SMatteo.Andreozzi@arm.com            if (rob->isEmpty(tid))
80212351Snikos.nikoleris@arm.com                checkEmptyROB[tid] = true;
80311057Sandreas.hansson@arm.com        }
80411057Sandreas.hansson@arm.com
80511057Sandreas.hansson@arm.com        // ROB is only considered "empty" for previous stages if: a)
80611057Sandreas.hansson@arm.com        // ROB is empty, b) there are no outstanding stores, c) IEW
80711057Sandreas.hansson@arm.com        // stage has received any information regarding stores that
80811057Sandreas.hansson@arm.com        // committed.
80911057Sandreas.hansson@arm.com        // c) is checked by making sure to not consider the ROB empty
81011057Sandreas.hansson@arm.com        // on the same cycle as when stores have been committed.
81111057Sandreas.hansson@arm.com        // @todo: Make this handle multi-cycle communication between
81211057Sandreas.hansson@arm.com        // commit and IEW.
81311057Sandreas.hansson@arm.com        if (checkEmptyROB[tid] && rob->isEmpty(tid) &&
81411057Sandreas.hansson@arm.com            !iewStage->hasStoresToWB(tid) && !committedStores[tid]) {
81511057Sandreas.hansson@arm.com            checkEmptyROB[tid] = false;
81611057Sandreas.hansson@arm.com            toIEW->commitInfo[tid].usedROB = true;
81711057Sandreas.hansson@arm.com            toIEW->commitInfo[tid].emptyROB = true;
81811057Sandreas.hansson@arm.com            toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid);
81911057Sandreas.hansson@arm.com            wroteToTimeBuffer = true;
82012749Sgiacomo.travaglini@arm.com        }
82112749Sgiacomo.travaglini@arm.com
82212966SMatteo.Andreozzi@arm.com    }
82312966SMatteo.Andreozzi@arm.com}
82412749Sgiacomo.travaglini@arm.com
82511057Sandreas.hansson@arm.comtemplate <class Impl>
82611057Sandreas.hansson@arm.comvoid
82711057Sandreas.hansson@arm.comDefaultCommit<Impl>::commitInsts()
82811057Sandreas.hansson@arm.com{
82911057Sandreas.hansson@arm.com    ////////////////////////////////////
83011057Sandreas.hansson@arm.com    // Handle commit
83111057Sandreas.hansson@arm.com    // Note that commit will be handled prior to putting new
83211057Sandreas.hansson@arm.com    // instructions in the ROB so that the ROB only tries to commit
83311057Sandreas.hansson@arm.com    // instructions it has in this current cycle, and not instructions
8344626Sstever@eecs.umich.edu    // it is writing in during this cycle.  Can't commit and squash
8355735Snate@binkert.org    // things at the same time...
8365735Snate@binkert.org    ////////////////////////////////////
8374887Sstever@eecs.umich.edu
8384887Sstever@eecs.umich.edu    DPRINTF(Commit, "Trying to commit instructions in the ROB.\n");
8394887Sstever@eecs.umich.edu
8405735Snate@binkert.org    unsigned num_committed = 0;
8415735Snate@binkert.org
84210896Snilay@cs.wisc.edu    DynInstPtr head_inst;
84312351Snikos.nikoleris@arm.com
84410571Sandreas.hansson@arm.com    // Commit as many instructions as possible until the commit bandwidth
84510028SGiacomo.Gabrielli@arm.com    // limit is reached, or it becomes impossible to commit any more.
84610723Sandreas.hansson@arm.com    while (num_committed < commitWidth) {
84712966SMatteo.Andreozzi@arm.com        int commit_thread = getCommittingThread();
84810694SMarco.Balboni@ARM.com
84911127Sandreas.hansson@arm.com        if (commit_thread == -1 || !rob->isHeadReady(commit_thread))
85010694SMarco.Balboni@ARM.com            break;
8519546Sandreas.hansson@arm.com
8524626Sstever@eecs.umich.edu        head_inst = rob->readHeadInst(commit_thread);
85310571Sandreas.hansson@arm.com
8545735Snate@binkert.org        ThreadID tid = head_inst->threadNumber;
8555735Snate@binkert.org
85611057Sandreas.hansson@arm.com        assert(tid == commit_thread);
85711057Sandreas.hansson@arm.com
85810571Sandreas.hansson@arm.com        DPRINTF(Commit, "Trying to commit head instruction, [sn:%i] [tid:%i]\n",
85910571Sandreas.hansson@arm.com                head_inst->seqNum, tid);
86010571Sandreas.hansson@arm.com
86110571Sandreas.hansson@arm.com        // If the head instruction is squashed, it is ready to retire
86210571Sandreas.hansson@arm.com        // (be removed from the ROB) at any time.
86310571Sandreas.hansson@arm.com        if (head_inst->isSquashed()) {
86410571Sandreas.hansson@arm.com
86510571Sandreas.hansson@arm.com            DPRINTF(Commit, "Retiring squashed instruction from "
86610571Sandreas.hansson@arm.com                    "ROB.\n");
86710571Sandreas.hansson@arm.com
86810571Sandreas.hansson@arm.com            rob->retireHead(commit_thread);
86910571Sandreas.hansson@arm.com
87010571Sandreas.hansson@arm.com            ++commitSquashedInsts;
87110571Sandreas.hansson@arm.com
87210571Sandreas.hansson@arm.com            // Record that the number of ROB entries has changed.
87310342SCurtis.Dunham@arm.com            changedROBNumEntries[tid] = true;
8748668Sgeoffrey.blake@arm.com        } else {
87510342SCurtis.Dunham@arm.com            pc[tid] = head_inst->pcState();
87610739Ssteve.reinhardt@amd.com
87710342SCurtis.Dunham@arm.com            // Increment the total number of non-speculative instructions
87810739Ssteve.reinhardt@amd.com            // executed.
87912749Sgiacomo.travaglini@arm.com            // Hack for now: it really shouldn't happen until after the
88010342SCurtis.Dunham@arm.com            // commit is deemed to be successful, but this count is needed
88110739Ssteve.reinhardt@amd.com            // for syscalls.
88210739Ssteve.reinhardt@amd.com            thread[tid]->funcExeInst++;
88313367Syuetsu.kodama@riken.jp
88413367Syuetsu.kodama@riken.jp            // Try to commit the head instruction.
88510739Ssteve.reinhardt@amd.com            bool commit_success = commitHead(head_inst, num_committed);
88610739Ssteve.reinhardt@amd.com
88710739Ssteve.reinhardt@amd.com            if (commit_success) {
88810739Ssteve.reinhardt@amd.com                ++num_committed;
88910739Ssteve.reinhardt@amd.com
89010739Ssteve.reinhardt@amd.com                changedROBNumEntries[tid] = true;
89110739Ssteve.reinhardt@amd.com
89210739Ssteve.reinhardt@amd.com                // Set the doneSeqNum to the youngest committed instruction.
89310739Ssteve.reinhardt@amd.com                toIEW->commitInfo[tid].doneSeqNum = head_inst->seqNum;
89410739Ssteve.reinhardt@amd.com
89512749Sgiacomo.travaglini@arm.com                ++commitCommittedInsts;
89610739Ssteve.reinhardt@amd.com
89710739Ssteve.reinhardt@amd.com                // To match the old model, don't count nops and instruction
89810739Ssteve.reinhardt@amd.com                // prefetches towards the total commit count.
89912766Sqtt2@cornell.edu                if (!head_inst->isNop() && !head_inst->isInstPrefetch()) {
90010739Ssteve.reinhardt@amd.com                    cpu->instDone(tid);
90112347Snikos.nikoleris@arm.com                }
90212347Snikos.nikoleris@arm.com
90312347Snikos.nikoleris@arm.com                TheISA::advancePC(pc[tid], head_inst->staticInst);
90412347Snikos.nikoleris@arm.com
90512347Snikos.nikoleris@arm.com                int count = 0;
90612347Snikos.nikoleris@arm.com                Addr oldpc;
90710739Ssteve.reinhardt@amd.com                // Debug statement.  Checks to make sure we're not
90810342SCurtis.Dunham@arm.com                // currently updating state while handling PC events.
90910342SCurtis.Dunham@arm.com                assert(!thread[tid]->inSyscall && !thread[tid]->trapPending);
91010342SCurtis.Dunham@arm.com                do {
91110342SCurtis.Dunham@arm.com                    oldpc = pc[tid].instAddr();
91210739Ssteve.reinhardt@amd.com                    cpu->system->pcEventQueue.service(thread[tid]->getTC());
91310342SCurtis.Dunham@arm.com                    count++;
91410342SCurtis.Dunham@arm.com                } while (oldpc != pc[tid].instAddr());
91512749Sgiacomo.travaglini@arm.com                if (count > 1) {
91610342SCurtis.Dunham@arm.com                    DPRINTF(Commit,
91710739Ssteve.reinhardt@amd.com                            "PC skip function event, stopping commit\n");
91810342SCurtis.Dunham@arm.com                    break;
91910342SCurtis.Dunham@arm.com                }
92010342SCurtis.Dunham@arm.com            } else {
92112749Sgiacomo.travaglini@arm.com                DPRINTF(Commit, "Unable to commit head instruction PC:%s "
92210342SCurtis.Dunham@arm.com                        "[tid:%i] [sn:%i].\n",
92310739Ssteve.reinhardt@amd.com                        head_inst->pcState(), tid ,head_inst->seqNum);
9242641Sstever@eecs.umich.edu                break;
9252549SN/A            }
9265735Snate@binkert.org        }
9275735Snate@binkert.org    }
9285735Snate@binkert.org
9292566SN/A    DPRINTF(CommitRate, "%i\n", num_committed);
9305387Sstever@gmail.com    numCommittedDist.sample(num_committed);
9315735Snate@binkert.org
9325387Sstever@gmail.com    if (num_committed == commitWidth) {
9332566SN/A        commitEligibleSamples++;
9345735Snate@binkert.org    }
9354626Sstever@eecs.umich.edu}
93610660Sandreas.hansson@arm.com
9374626Sstever@eecs.umich.edutemplate <class Impl>
9385735Snate@binkert.orgbool
9395735Snate@binkert.orgDefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
9404626Sstever@eecs.umich.edu{
9412662Sstever@eecs.umich.edu    assert(head_inst);
9422855Srdreslin@umich.edu
9434022Sstever@eecs.umich.edu    ThreadID tid = head_inst->threadNumber;
9445745Snate@binkert.org
9457464Ssteve.reinhardt@amd.com    // If the instruction is not executed yet, then it will need extra
9467464Ssteve.reinhardt@amd.com    // handling.  Signal backwards that it should be executed.
9477464Ssteve.reinhardt@amd.com    if (!head_inst->isExecuted()) {
9482641Sstever@eecs.umich.edu        // Keep this number correct.  We have not yet actually executed
9492641Sstever@eecs.umich.edu        // and committed this instruction.
9505735Snate@binkert.org        thread[tid]->funcExeInst--;
9515735Snate@binkert.org
9524870Sstever@eecs.umich.edu        if (head_inst->isNonSpeculative() ||
9534870Sstever@eecs.umich.edu            head_inst->isStoreConditional() ||
9544870Sstever@eecs.umich.edu            head_inst->isMemBarrier() ||
9554870Sstever@eecs.umich.edu            head_inst->isWriteBarrier()) {
9565735Snate@binkert.org
9575735Snate@binkert.org            DPRINTF(Commit, "Encountered a barrier or non-speculative "
9583348Sbinkertn@umich.edu                    "instruction [sn:%lli] at the head of the ROB, PC %s.\n",
9594870Sstever@eecs.umich.edu                    head_inst->seqNum, head_inst->pcState());
9603135Srdreslin@umich.edu
9613135Srdreslin@umich.edu            if (inst_num > 0 || iewStage->hasStoresToWB(tid)) {
9628436SBrad.Beckmann@amd.com                DPRINTF(Commit, "Waiting for all stores to writeback.\n");
9638436SBrad.Beckmann@amd.com                return false;
9648436SBrad.Beckmann@amd.com            }
9658436SBrad.Beckmann@amd.com
9668436SBrad.Beckmann@amd.com            toIEW->commitInfo[tid].nonSpecSeqNum = head_inst->seqNum;
9678436SBrad.Beckmann@amd.com
9688436SBrad.Beckmann@amd.com            // Change the instruction so it won't try to commit again until
9698436SBrad.Beckmann@amd.com            // it is executed.
9708436SBrad.Beckmann@amd.com            head_inst->clearCanCommit();
9718436SBrad.Beckmann@amd.com
9728436SBrad.Beckmann@amd.com            ++commitNonSpecStalls;
9738436SBrad.Beckmann@amd.com
97411057Sandreas.hansson@arm.com            return false;
97511057Sandreas.hansson@arm.com        } else if (head_inst->isLoad()) {
97611057Sandreas.hansson@arm.com            if (inst_num > 0 || iewStage->hasStoresToWB(tid)) {
97711057Sandreas.hansson@arm.com                DPRINTF(Commit, "Waiting for all stores to writeback.\n");
97811057Sandreas.hansson@arm.com                return false;
97911057Sandreas.hansson@arm.com            }
98011057Sandreas.hansson@arm.com
98111057Sandreas.hansson@arm.com            assert(head_inst->uncacheable());
98211057Sandreas.hansson@arm.com            DPRINTF(Commit, "[sn:%lli]: Uncached load, PC %s.\n",
98313860Sodanrc@yahoo.com.br                    head_inst->seqNum, head_inst->pcState());
98413860Sodanrc@yahoo.com.br
98513860Sodanrc@yahoo.com.br            // Send back the non-speculative instruction's sequence
98613860Sodanrc@yahoo.com.br            // number.  Tell the lsq to re-execute the load.
98713860Sodanrc@yahoo.com.br            toIEW->commitInfo[tid].nonSpecSeqNum = head_inst->seqNum;
98813860Sodanrc@yahoo.com.br            toIEW->commitInfo[tid].uncached = true;
98913860Sodanrc@yahoo.com.br            toIEW->commitInfo[tid].uncachedLoad = head_inst;
99013860Sodanrc@yahoo.com.br
99113860Sodanrc@yahoo.com.br            head_inst->clearCanCommit();
99213860Sodanrc@yahoo.com.br
99313860Sodanrc@yahoo.com.br            return false;
99413860Sodanrc@yahoo.com.br        } else {
99513860Sodanrc@yahoo.com.br            panic("Trying to commit un-executed instruction "
99613860Sodanrc@yahoo.com.br                  "of unknown type!\n");
99713860Sodanrc@yahoo.com.br        }
99813860Sodanrc@yahoo.com.br    }
99913860Sodanrc@yahoo.com.br
100013860Sodanrc@yahoo.com.br    if (head_inst->isThreadSync()) {
100113860Sodanrc@yahoo.com.br        // Not handled for now.
100213860Sodanrc@yahoo.com.br        panic("Thread sync instructions are not handled yet.\n");
100313860Sodanrc@yahoo.com.br    }
100413860Sodanrc@yahoo.com.br
100513860Sodanrc@yahoo.com.br    // Check if the instruction caused a fault.  If so, trap.
100613860Sodanrc@yahoo.com.br    Fault inst_fault = head_inst->getFault();
100713860Sodanrc@yahoo.com.br
100813860Sodanrc@yahoo.com.br    // Stores mark themselves as completed.
100913860Sodanrc@yahoo.com.br    if (!head_inst->isStore() && inst_fault == NoFault) {
101013860Sodanrc@yahoo.com.br        head_inst->setCompleted();
101113860Sodanrc@yahoo.com.br    }
101213860Sodanrc@yahoo.com.br
101313860Sodanrc@yahoo.com.br#if USE_CHECKER
101413860Sodanrc@yahoo.com.br    // Use checker prior to updating anything due to traps or PC
101513860Sodanrc@yahoo.com.br    // based events.
101613860Sodanrc@yahoo.com.br    if (cpu->checker) {
101713860Sodanrc@yahoo.com.br        cpu->checker->verify(head_inst);
101813860Sodanrc@yahoo.com.br    }
101913860Sodanrc@yahoo.com.br#endif
102013860Sodanrc@yahoo.com.br
102113860Sodanrc@yahoo.com.br    if (inst_fault != NoFault) {
102211057Sandreas.hansson@arm.com        DPRINTF(Commit, "Inst [sn:%lli] PC %s has a fault\n",
102311013Sandreas.sandberg@arm.com                head_inst->seqNum, head_inst->pcState());
102411013Sandreas.sandberg@arm.com
102511013Sandreas.sandberg@arm.com        if (iewStage->hasStoresToWB(tid) || inst_num > 0) {
102611013Sandreas.sandberg@arm.com            DPRINTF(Commit, "Stores outstanding, fault must wait.\n");
102711013Sandreas.sandberg@arm.com            return false;
102811013Sandreas.sandberg@arm.com        }
10293348Sbinkertn@umich.edu
10303348Sbinkertn@umich.edu        head_inst->setCompleted();
103110571Sandreas.hansson@arm.com
103210571Sandreas.hansson@arm.com#if USE_CHECKER
103310571Sandreas.hansson@arm.com        if (cpu->checker && head_inst->isStore()) {
103410571Sandreas.hansson@arm.com            cpu->checker->verify(head_inst);
103510571Sandreas.hansson@arm.com        }
103610571Sandreas.hansson@arm.com#endif
103710571Sandreas.hansson@arm.com
103810571Sandreas.hansson@arm.com        assert(!thread[tid]->inSyscall);
10392566SN/A
10402566SN/A        // Mark that we're in state update mode so that the trap's
10413348Sbinkertn@umich.edu        // execution doesn't generate extra squashes.
10423348Sbinkertn@umich.edu        thread[tid]->inSyscall = true;
10433348Sbinkertn@umich.edu
104410566Sandreas.hansson@arm.com        // Execute the trap.  Although it's slightly unrealistic in
10453348Sbinkertn@umich.edu        // terms of timing (as it doesn't wait for the full timing of
10465735Snate@binkert.org        // the trap event to complete before updating state), it's
10473348Sbinkertn@umich.edu        // needed to update the state as soon as possible.  This
10482566SN/A        // prevents external agents from changing any specific state
10493348Sbinkertn@umich.edu        // that the trap need.
105010564Sandreas.hansson@arm.com        cpu->trap(inst_fault, tid, head_inst->staticInst);
105110564Sandreas.hansson@arm.com
105210564Sandreas.hansson@arm.com        // Exit state update mode to avoid accidental updating.
105310564Sandreas.hansson@arm.com        thread[tid]->inSyscall = false;
105410564Sandreas.hansson@arm.com
105510564Sandreas.hansson@arm.com        commitStatus[tid] = TrapPending;
105610564Sandreas.hansson@arm.com
105710564Sandreas.hansson@arm.com        if (head_inst->traceData) {
105810564Sandreas.hansson@arm.com            if (DTRACE(ExecFaulting)) {
105910564Sandreas.hansson@arm.com                head_inst->traceData->setFetchSeq(head_inst->seqNum);
106010564Sandreas.hansson@arm.com                head_inst->traceData->setCPSeq(thread[tid]->numInst);
106110566Sandreas.hansson@arm.com                head_inst->traceData->dump();
106210564Sandreas.hansson@arm.com            }
106310564Sandreas.hansson@arm.com            delete head_inst->traceData;
106410564Sandreas.hansson@arm.com            head_inst->traceData = NULL;
106510564Sandreas.hansson@arm.com        }
106610564Sandreas.hansson@arm.com
10673348Sbinkertn@umich.edu        // Generate trap squash event.
106810571Sandreas.hansson@arm.com        generateTrapEvent(tid);
106910571Sandreas.hansson@arm.com        return false;
107010571Sandreas.hansson@arm.com    }
107110571Sandreas.hansson@arm.com
107210571Sandreas.hansson@arm.com    updateComInstStats(head_inst);
107310571Sandreas.hansson@arm.com
107410571Sandreas.hansson@arm.com#if FULL_SYSTEM
107510571Sandreas.hansson@arm.com    if (thread[tid]->profile) {
107610571Sandreas.hansson@arm.com        thread[tid]->profilePC = head_inst->instAddr();
10773348Sbinkertn@umich.edu        ProfileNode *node = thread[tid]->profile->consume(thread[tid]->getTC(),
10782566SN/A                                                          head_inst->staticInst);
10793348Sbinkertn@umich.edu
10803348Sbinkertn@umich.edu        if (node)
10813348Sbinkertn@umich.edu            thread[tid]->profileNode = node;
108210566Sandreas.hansson@arm.com    }
10833348Sbinkertn@umich.edu    if (CPA::available()) {
10845735Snate@binkert.org        if (head_inst->isControl()) {
10853348Sbinkertn@umich.edu            ThreadContext *tc = thread[tid]->getTC();
10863348Sbinkertn@umich.edu            CPA::cpa()->swAutoBegin(tc, head_inst->nextInstAddr());
10875735Snate@binkert.org        }
10885735Snate@binkert.org    }
10895735Snate@binkert.org#endif
10903348Sbinkertn@umich.edu
10913348Sbinkertn@umich.edu    if (head_inst->traceData) {
109210562Sandreas.hansson@arm.com        head_inst->traceData->setFetchSeq(head_inst->seqNum);
10933348Sbinkertn@umich.edu        head_inst->traceData->setCPSeq(thread[tid]->numInst);
109410562Sandreas.hansson@arm.com        head_inst->traceData->dump();
10953348Sbinkertn@umich.edu        delete head_inst->traceData;
10963348Sbinkertn@umich.edu        head_inst->traceData = NULL;
10972566SN/A    }
109810563Sandreas.hansson@arm.com
109910563Sandreas.hansson@arm.com    // Update the commit rename map
110010563Sandreas.hansson@arm.com    for (int i = 0; i < head_inst->numDestRegs(); i++) {
110110563Sandreas.hansson@arm.com        renameMap[tid]->setEntry(head_inst->flattenedDestRegIdx(i),
110210563Sandreas.hansson@arm.com                                 head_inst->renamedDestRegIdx(i));
110310563Sandreas.hansson@arm.com    }
110410563Sandreas.hansson@arm.com
110510563Sandreas.hansson@arm.com    if (head_inst->isCopy())
11065735Snate@binkert.org        panic("Should not commit any copy instructions!");
110711013Sandreas.sandberg@arm.com
110811013Sandreas.sandberg@arm.com    // Finally clear the head ROB entry.
110911013Sandreas.sandberg@arm.com    rob->retireHead(tid);
111011013Sandreas.sandberg@arm.com
111111013Sandreas.sandberg@arm.com    // If this was a store, record it for this cycle.
111211013Sandreas.sandberg@arm.com    if (head_inst->isStore())
111311013Sandreas.sandberg@arm.com        committedStores[tid] = true;
111411013Sandreas.sandberg@arm.com
111511013Sandreas.sandberg@arm.com    // Return true to indicate that we have committed an instruction.
111611013Sandreas.sandberg@arm.com    return true;
111711013Sandreas.sandberg@arm.com}
111811013Sandreas.sandberg@arm.com
111911013Sandreas.sandberg@arm.comtemplate <class Impl>
112011013Sandreas.sandberg@arm.comvoid
112111013Sandreas.sandberg@arm.comDefaultCommit<Impl>::getInsts()
112211013Sandreas.sandberg@arm.com{
112311013Sandreas.sandberg@arm.com    DPRINTF(Commit, "Getting instructions from Rename stage.\n");
112411013Sandreas.sandberg@arm.com
112511013Sandreas.sandberg@arm.com    // Read any renamed instructions and place them into the ROB.
112611013Sandreas.sandberg@arm.com    int insts_to_process = std::min((int)renameWidth, fromRename->size);
112713347Sgabeblack@google.com
112811013Sandreas.sandberg@arm.com    for (int inst_num = 0; inst_num < insts_to_process; ++inst_num) {
112911013Sandreas.sandberg@arm.com        DynInstPtr inst;
113011013Sandreas.sandberg@arm.com
11315735Snate@binkert.org        inst = fromRename->insts[inst_num];
11322566SN/A        ThreadID tid = inst->threadNumber;
113313348Sgabeblack@google.com
113413348Sgabeblack@google.com        if (!inst->isSquashed() &&
113513347Sgabeblack@google.com            commitStatus[tid] != ROBSquashing &&
11362566SN/A            commitStatus[tid] != TrapPending) {
113711013Sandreas.sandberg@arm.com            changedROBNumEntries[tid] = true;
113811013Sandreas.sandberg@arm.com
113911013Sandreas.sandberg@arm.com            DPRINTF(Commit, "Inserting PC %s [sn:%i] [tid:%i] into ROB.\n",
114011013Sandreas.sandberg@arm.com                    inst->pcState(), inst->seqNum, tid);
114111013Sandreas.sandberg@arm.com
114211013Sandreas.sandberg@arm.com            rob->insertInst(inst);
114311013Sandreas.sandberg@arm.com
114411013Sandreas.sandberg@arm.com            assert(rob->getThreadEntries(tid) <= rob->getMaxEntries(tid));
11455735Snate@binkert.org
114611013Sandreas.sandberg@arm.com            youngestSeqNum[tid] = inst->seqNum;
114711013Sandreas.sandberg@arm.com        } else {
11485735Snate@binkert.org            DPRINTF(Commit, "Instruction PC %s [sn:%i] [tid:%i] was "
11492566SN/A                    "squashed, skipping.\n",
115011013Sandreas.sandberg@arm.com                    inst->pcState(), inst->seqNum, tid);
115111013Sandreas.sandberg@arm.com        }
115213347Sgabeblack@google.com    }
115311013Sandreas.sandberg@arm.com}
115411013Sandreas.sandberg@arm.com
115513348Sgabeblack@google.comtemplate <class Impl>
115613348Sgabeblack@google.comvoid
115713347Sgabeblack@google.comDefaultCommit<Impl>::skidInsert()
11582566SN/A{
115912652Sandreas.sandberg@arm.com    DPRINTF(Commit, "Attempting to any instructions from rename into "
116012652Sandreas.sandberg@arm.com            "skidBuffer.\n");
116112652Sandreas.sandberg@arm.com
116212652Sandreas.sandberg@arm.com    for (int inst_num = 0; inst_num < fromRename->size; ++inst_num) {
116312652Sandreas.sandberg@arm.com        DynInstPtr inst = fromRename->insts[inst_num];
116412652Sandreas.sandberg@arm.com
116512652Sandreas.sandberg@arm.com        if (!inst->isSquashed()) {
116612652Sandreas.sandberg@arm.com            DPRINTF(Commit, "Inserting PC %s [sn:%i] [tid:%i] into ",
116712652Sandreas.sandberg@arm.com                    "skidBuffer.\n", inst->pcState(), inst->seqNum,
116812652Sandreas.sandberg@arm.com                    inst->threadNumber);
116912652Sandreas.sandberg@arm.com            skidBuffer.push(inst);
117012652Sandreas.sandberg@arm.com        } else {
117112652Sandreas.sandberg@arm.com            DPRINTF(Commit, "Instruction PC %s [sn:%i] [tid:%i] was "
11723348Sbinkertn@umich.edu                    "squashed, skipping.\n",
11734626Sstever@eecs.umich.edu                    inst->pcState(), inst->seqNum, inst->threadNumber);
11744626Sstever@eecs.umich.edu        }
11755735Snate@binkert.org    }
117610563Sandreas.hansson@arm.com}
11774626Sstever@eecs.umich.edu
117810571Sandreas.hansson@arm.comtemplate <class Impl>
117910571Sandreas.hansson@arm.comvoid
118010571Sandreas.hansson@arm.comDefaultCommit<Impl>::markCompletedInsts()
118110571Sandreas.hansson@arm.com{
118210571Sandreas.hansson@arm.com    // Grab completed insts out of the IEW instruction queue, and mark
11837691SAli.Saidi@ARM.com    // instructions completed within the ROB.
118410571Sandreas.hansson@arm.com    for (int inst_num = 0;
118510571Sandreas.hansson@arm.com         inst_num < fromIEW->size && fromIEW->insts[inst_num];
11867691SAli.Saidi@ARM.com         ++inst_num)
11874626Sstever@eecs.umich.edu    {
11884626Sstever@eecs.umich.edu        if (!fromIEW->insts[inst_num]->isSquashed()) {
11894626Sstever@eecs.umich.edu            DPRINTF(Commit, "[tid:%i]: Marking PC %s, [sn:%lli] ready "
11904626Sstever@eecs.umich.edu                    "within ROB.\n",
11914626Sstever@eecs.umich.edu                    fromIEW->insts[inst_num]->threadNumber,
11924626Sstever@eecs.umich.edu                    fromIEW->insts[inst_num]->pcState(),
11935735Snate@binkert.org                    fromIEW->insts[inst_num]->seqNum);
119410563Sandreas.hansson@arm.com
11954626Sstever@eecs.umich.edu            // Mark the instruction as ready to commit.
11964626Sstever@eecs.umich.edu            fromIEW->insts[inst_num]->setCanCommit();
11974626Sstever@eecs.umich.edu        }
11984626Sstever@eecs.umich.edu    }
11994626Sstever@eecs.umich.edu}
120012633Sodanrc@yahoo.com.br
120112633Sodanrc@yahoo.com.brtemplate <class Impl>
12024626Sstever@eecs.umich.edubool
12035735Snate@binkert.orgDefaultCommit<Impl>::robDoneSquashing()
120410563Sandreas.hansson@arm.com{
12054626Sstever@eecs.umich.edu    list<ThreadID>::iterator threads = activeThreads->begin();
120610563Sandreas.hansson@arm.com    list<ThreadID>::iterator end = activeThreads->end();
12074626Sstever@eecs.umich.edu
12084626Sstever@eecs.umich.edu    while (threads != end) {
12094626Sstever@eecs.umich.edu        ThreadID tid = *threads++;
121012633Sodanrc@yahoo.com.br
121112633Sodanrc@yahoo.com.br        if (!rob->isDoneSquashing(tid))
121212633Sodanrc@yahoo.com.br            return false;
121312633Sodanrc@yahoo.com.br    }
12144626Sstever@eecs.umich.edu
12155735Snate@binkert.org    return true;
121610563Sandreas.hansson@arm.com}
12174626Sstever@eecs.umich.edu
12184626Sstever@eecs.umich.edutemplate <class Impl>
12194626Sstever@eecs.umich.eduvoid
12204626Sstever@eecs.umich.eduDefaultCommit<Impl>::updateComInstStats(DynInstPtr &inst)
12214626Sstever@eecs.umich.edu{
12223348Sbinkertn@umich.edu    ThreadID tid = inst->threadNumber;
12233348Sbinkertn@umich.edu
12243348Sbinkertn@umich.edu    //
12255735Snate@binkert.org    //  Pick off the software prefetches
12265735Snate@binkert.org    //
12275735Snate@binkert.org#ifdef TARGET_ALPHA
122810566Sandreas.hansson@arm.com    if (inst->isDataPrefetch()) {
12295735Snate@binkert.org        statComSwp[tid]++;
12305735Snate@binkert.org    } else {
123110566Sandreas.hansson@arm.com        statComInst[tid]++;
12325735Snate@binkert.org    }
12335735Snate@binkert.org#else
12342566SN/A    statComInst[tid]++;
123510565Sandreas.hansson@arm.com#endif
12365735Snate@binkert.org
12375735Snate@binkert.org    //
12385735Snate@binkert.org    //  Control Instructions
123911286Sandreas.hansson@arm.com    //
124011286Sandreas.hansson@arm.com    if (inst->isControl())
124111286Sandreas.hansson@arm.com        statComBranches[tid]++;
124211286Sandreas.hansson@arm.com
124311286Sandreas.hansson@arm.com    //
124411286Sandreas.hansson@arm.com    //  Memory references
124511286Sandreas.hansson@arm.com    //
12465735Snate@binkert.org    if (inst->isMemRef()) {
12475735Snate@binkert.org        statComRefs[tid]++;
124811013Sandreas.sandberg@arm.com
124911013Sandreas.sandberg@arm.com        if (inst->isLoad()) {
125011013Sandreas.sandberg@arm.com            statComLoads[tid]++;
125111013Sandreas.sandberg@arm.com        }
125211013Sandreas.sandberg@arm.com    }
125311013Sandreas.sandberg@arm.com
125411013Sandreas.sandberg@arm.com    if (inst->isMemBarrier()) {
125511013Sandreas.sandberg@arm.com        statComMembars[tid]++;
125611013Sandreas.sandberg@arm.com    }
125711013Sandreas.sandberg@arm.com}
125811013Sandreas.sandberg@arm.com
12594626Sstever@eecs.umich.edu////////////////////////////////////////
126010570Sandreas.hansson@arm.com//                                    //
126110570Sandreas.hansson@arm.com//  SMT COMMIT POLICY MAINTAINED HERE //
126210570Sandreas.hansson@arm.com//                                    //
126310570Sandreas.hansson@arm.com////////////////////////////////////////
126410570Sandreas.hansson@arm.comtemplate <class Impl>
126510570Sandreas.hansson@arm.comThreadID
126610570Sandreas.hansson@arm.comDefaultCommit<Impl>::getCommittingThread()
126710570Sandreas.hansson@arm.com{
126810570Sandreas.hansson@arm.com    if (numThreads > 1) {
126912823Srmk35@cl.cam.ac.uk        switch (commitPolicy) {
127010570Sandreas.hansson@arm.com
127110570Sandreas.hansson@arm.com          case Aggressive:
127210570Sandreas.hansson@arm.com            //If Policy is Aggressive, commit will call
127312823Srmk35@cl.cam.ac.uk            //this function multiple times per
127412823Srmk35@cl.cam.ac.uk            //cycle
127512823Srmk35@cl.cam.ac.uk            return oldestReady();
127612823Srmk35@cl.cam.ac.uk
127710570Sandreas.hansson@arm.com          case RoundRobin:
127810570Sandreas.hansson@arm.com            return roundRobin();
127910570Sandreas.hansson@arm.com
128010883Sali.jafri@arm.com          case OldestReady:
128110883Sali.jafri@arm.com            return oldestReady();
128210883Sali.jafri@arm.com
128310883Sali.jafri@arm.com          default:
128410883Sali.jafri@arm.com            return InvalidThreadID;
128510883Sali.jafri@arm.com        }
128611199Sandreas.hansson@arm.com    } else {
128711199Sandreas.hansson@arm.com        assert(!activeThreads->empty());
128811199Sandreas.hansson@arm.com        ThreadID tid = activeThreads->front();
128911199Sandreas.hansson@arm.com
129011199Sandreas.hansson@arm.com        if (commitStatus[tid] == Running ||
129111199Sandreas.hansson@arm.com            commitStatus[tid] == Idle ||
129211199Sandreas.hansson@arm.com            commitStatus[tid] == FetchTrapPending) {
129311199Sandreas.hansson@arm.com            return tid;
129411199Sandreas.hansson@arm.com        } else {
129511199Sandreas.hansson@arm.com            return InvalidThreadID;
129611199Sandreas.hansson@arm.com        }
129710883Sali.jafri@arm.com    }
129810883Sali.jafri@arm.com}
129910883Sali.jafri@arm.com
13004626Sstever@eecs.umich.edutemplate<class Impl>
130110570Sandreas.hansson@arm.comThreadID
130210570Sandreas.hansson@arm.comDefaultCommit<Impl>::roundRobin()
130310570Sandreas.hansson@arm.com{
13044626Sstever@eecs.umich.edu    list<ThreadID>::iterator pri_iter = priority_list.begin();
13054626Sstever@eecs.umich.edu    list<ThreadID>::iterator end      = priority_list.end();
13065735Snate@binkert.org
130712823Srmk35@cl.cam.ac.uk    while (pri_iter != end) {
130812823Srmk35@cl.cam.ac.uk        ThreadID tid = *pri_iter;
13095314Sstever@gmail.com
13105315Sstever@gmail.com        if (commitStatus[tid] == Running ||
13115315Sstever@gmail.com            commitStatus[tid] == Idle ||
13125315Sstever@gmail.com            commitStatus[tid] == FetchTrapPending) {
13135735Snate@binkert.org
13145735Snate@binkert.org            if (rob->isHeadReady(tid)) {
13155735Snate@binkert.org                priority_list.erase(pri_iter);
13165735Snate@binkert.org                priority_list.push_back(tid);
13175735Snate@binkert.org
13185314Sstever@gmail.com                return tid;
13195314Sstever@gmail.com            }
13205315Sstever@gmail.com        }
13215315Sstever@gmail.com
13225315Sstever@gmail.com        pri_iter++;
13235735Snate@binkert.org    }
13245735Snate@binkert.org
13255735Snate@binkert.org    return InvalidThreadID;
13265735Snate@binkert.org}
13275735Snate@binkert.org
13285314Sstever@gmail.comtemplate<class Impl>
13295314Sstever@gmail.comThreadID
13305314Sstever@gmail.comDefaultCommit<Impl>::oldestReady()
13315314Sstever@gmail.com{
13329663Suri.wiener@arm.com    unsigned oldest = 0;
13339663Suri.wiener@arm.com    bool first = true;
13349663Suri.wiener@arm.com
13359663Suri.wiener@arm.com    list<ThreadID>::iterator threads = activeThreads->begin();
13369663Suri.wiener@arm.com    list<ThreadID>::iterator end = activeThreads->end();
13379663Suri.wiener@arm.com
13389663Suri.wiener@arm.com    while (threads != end) {
13399663Suri.wiener@arm.com        ThreadID tid = *threads++;
13402381SN/A
13412381SN/A        if (!rob->isEmpty(tid) &&
13422381SN/A            (commitStatus[tid] == Running ||
1343             commitStatus[tid] == Idle ||
1344             commitStatus[tid] == FetchTrapPending)) {
1345
1346            if (rob->isHeadReady(tid)) {
1347
1348                DynInstPtr head_inst = rob->readHeadInst(tid);
1349
1350                if (first) {
1351                    oldest = tid;
1352                    first = false;
1353                } else if (head_inst->seqNum < oldest) {
1354                    oldest = tid;
1355                }
1356            }
1357        }
1358    }
1359
1360    if (!first) {
1361        return oldest;
1362    } else {
1363        return InvalidThreadID;
1364    }
1365}
1366