commit_impl.hh revision 1681
110780SCurtis.Dunham@arm.com// @todo: Bug when something reaches execute, and mispredicts, but is never
27090SN/A// put into the ROB because the ROB is full.  Need rename stage to predict
37090SN/A// the free ROB entries better.
47090SN/A
57090SN/A#ifndef __COMMIT_IMPL_HH__
67090SN/A#define __COMMIT_IMPL_HH__
77090SN/A
87090SN/A#include "base/timebuf.hh"
97090SN/A#include "cpu/beta_cpu/commit.hh"
107090SN/A#include "cpu/exetrace.hh"
117090SN/A
127090SN/Atemplate <class Impl>
134486SN/ASimpleCommit<Impl>::SimpleCommit(Params &params)
144486SN/A    : dcacheInterface(params.dcacheInterface),
154486SN/A      iewToCommitDelay(params.iewToCommitDelay),
164486SN/A      renameToROBDelay(params.renameToROBDelay),
174486SN/A      renameWidth(params.renameWidth),
184486SN/A      iewWidth(params.executeWidth),
194486SN/A      commitWidth(params.commitWidth)
204486SN/A{
214486SN/A    _status = Idle;
224486SN/A}
234486SN/A
244486SN/Atemplate <class Impl>
254486SN/Avoid
264486SN/ASimpleCommit<Impl>::regStats()
274486SN/A{
284486SN/A    commitCommittedInsts
294486SN/A        .name(name() + ".commitCommittedInsts")
304486SN/A        .desc("The number of committed instructions")
314486SN/A        .prereq(commitCommittedInsts);
324486SN/A    commitSquashedInsts
334486SN/A        .name(name() + ".commitSquashedInsts")
344486SN/A        .desc("The number of squashed insts skipped by commit")
354486SN/A        .prereq(commitSquashedInsts);
364486SN/A    commitSquashEvents
374486SN/A        .name(name() + ".commitSquashEvents")
384486SN/A        .desc("The number of times commit is told to squash")
397584SAli.Saidi@arm.com        .prereq(commitSquashEvents);
407584SAli.Saidi@arm.com    commitNonSpecStalls
417754SWilliam.Wang@arm.com        .name(name() + ".commitNonSpecStalls")
424486SN/A        .desc("The number of times commit has been forced to stall to "
433630SN/A              "communicate backwards")
443630SN/A        .prereq(commitNonSpecStalls);
4511011SAndreas.Sandberg@ARM.com    commitCommittedBranches
4611011SAndreas.Sandberg@ARM.com        .name(name() + ".commitCommittedBranches")
477587SAli.Saidi@arm.com        .desc("The number of committed branches")
4811244Sandreas.sandberg@arm.com        .prereq(commitCommittedBranches);
4910353SGeoffrey.Blake@arm.com    commitCommittedLoads
508212SAli.Saidi@ARM.com        .name(name() + ".commitCommittedLoads")
515478SN/A        .desc("The number of committed loads")
525478SN/A        .prereq(commitCommittedLoads);
537584SAli.Saidi@arm.com    commitCommittedMemRefs
548931Sandreas.hansson@arm.com        .name(name() + ".commitCommittedMemRefs")
559525SAndreas.Sandberg@ARM.com        .desc("The number of committed memory references")
5610397Sstephan.diestelhorst@arm.com        .prereq(commitCommittedMemRefs);
5711090Sandreas.sandberg@arm.com    branchMispredicts
5811236Sandreas.sandberg@arm.com        .name(name() + ".branchMispredicts")
593630SN/A        .desc("The number of times a branch was mispredicted")
609806Sstever@gmail.com        .prereq(branchMispredicts);
619806Sstever@gmail.com    n_committed_dist
627584SAli.Saidi@arm.com        .init(0,commitWidth,1)
639338SAndreas.Sandberg@arm.com        .name(name() + ".COM:committed_per_cycle")
647584SAli.Saidi@arm.com        .desc("Number of insts commited each cycle")
653898SN/A        .flags(Stats::pdf)
669806Sstever@gmail.com        ;
677950SAli.Saidi@ARM.com}
687950SAli.Saidi@ARM.com
699338SAndreas.Sandberg@arm.comtemplate <class Impl>
709525SAndreas.Sandberg@ARM.comvoid
717950SAli.Saidi@ARM.comSimpleCommit<Impl>::setCPU(FullCPU *cpu_ptr)
727950SAli.Saidi@ARM.com{
737950SAli.Saidi@ARM.com    DPRINTF(Commit, "Commit: Setting CPU pointer.\n");
747950SAli.Saidi@ARM.com    cpu = cpu_ptr;
757587SAli.Saidi@arm.com}
767587SAli.Saidi@arm.com
777587SAli.Saidi@arm.comtemplate <class Impl>
789338SAndreas.Sandberg@arm.comvoid
797753SWilliam.Wang@arm.comSimpleCommit<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
807753SWilliam.Wang@arm.com{
819525SAndreas.Sandberg@ARM.com    DPRINTF(Commit, "Commit: Setting time buffer pointer.\n");
827753SWilliam.Wang@arm.com    timeBuffer = tb_ptr;
837587SAli.Saidi@arm.com
847587SAli.Saidi@arm.com    // Setup wire to send information back to IEW.
858282SAli.Saidi@ARM.com    toIEW = timeBuffer->getWire(0);
868282SAli.Saidi@ARM.com
879338SAndreas.Sandberg@arm.com    // Setup wire to read data from IEW (for the ROB).
888282SAli.Saidi@ARM.com    robInfoFromIEW = timeBuffer->getWire(-iewToCommitDelay);
8911296Sandreas.sandberg@arm.com}
9011296Sandreas.sandberg@arm.com
9111296Sandreas.sandberg@arm.comtemplate <class Impl>
9211296Sandreas.sandberg@arm.comvoid
9311296Sandreas.sandberg@arm.comSimpleCommit<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
9411296Sandreas.sandberg@arm.com{
9511296Sandreas.sandberg@arm.com    DPRINTF(Commit, "Commit: Setting rename queue pointer.\n");
9611296Sandreas.sandberg@arm.com    renameQueue = rq_ptr;
9711296Sandreas.sandberg@arm.com
9811296Sandreas.sandberg@arm.com    // Setup wire to get instructions from rename (for the ROB).
9911296Sandreas.sandberg@arm.com    fromRename = renameQueue->getWire(-renameToROBDelay);
10011296Sandreas.sandberg@arm.com}
10111296Sandreas.sandberg@arm.com
10211296Sandreas.sandberg@arm.comtemplate <class Impl>
1037584SAli.Saidi@arm.comvoid
1047584SAli.Saidi@arm.comSimpleCommit<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
1059338SAndreas.Sandberg@arm.com{
1068524SAli.Saidi@ARM.com    DPRINTF(Commit, "Commit: Setting IEW queue pointer.\n");
1078524SAli.Saidi@ARM.com    iewQueue = iq_ptr;
1088299Schander.sudanthi@arm.com
1097584SAli.Saidi@arm.com    // Setup wire to get instructions from IEW.
11011011SAndreas.Sandberg@ARM.com    fromIEW = iewQueue->getWire(-iewToCommitDelay);
11111011SAndreas.Sandberg@ARM.com}
11211011SAndreas.Sandberg@ARM.com
11311011SAndreas.Sandberg@ARM.comtemplate <class Impl>
11411011SAndreas.Sandberg@ARM.comvoid
11511011SAndreas.Sandberg@ARM.comSimpleCommit<Impl>::setROB(ROB *rob_ptr)
11611011SAndreas.Sandberg@ARM.com{
11711011SAndreas.Sandberg@ARM.com    DPRINTF(Commit, "Commit: Setting ROB pointer.\n");
11811011SAndreas.Sandberg@ARM.com    rob = rob_ptr;
11911011SAndreas.Sandberg@ARM.com}
12011011SAndreas.Sandberg@ARM.com
12111011SAndreas.Sandberg@ARM.comtemplate <class Impl>
12211011SAndreas.Sandberg@ARM.comvoid
12311011SAndreas.Sandberg@ARM.comSimpleCommit<Impl>::tick()
12411011SAndreas.Sandberg@ARM.com{
12511011SAndreas.Sandberg@ARM.com    // If the ROB is currently in its squash sequence, then continue
12611011SAndreas.Sandberg@ARM.com    // to squash.  In this case, commit does not do anything.  Otherwise
12711011SAndreas.Sandberg@ARM.com    // run commit.
12811011SAndreas.Sandberg@ARM.com    if (_status == ROBSquashing) {
12911011SAndreas.Sandberg@ARM.com        if (rob->isDoneSquashing()) {
13011011SAndreas.Sandberg@ARM.com            _status = Running;
13111011SAndreas.Sandberg@ARM.com        } else {
13211421Sdavid.guillen@arm.com            rob->doSquash();
13311421Sdavid.guillen@arm.com
13411421Sdavid.guillen@arm.com            // Send back sequence number of tail of ROB, so other stages
13511421Sdavid.guillen@arm.com            // can squash younger instructions.  Note that really the only
13611421Sdavid.guillen@arm.com            // stage that this is important for is the IEW stage; other
13711421Sdavid.guillen@arm.com            // stages can just clear all their state as long as selective
13811421Sdavid.guillen@arm.com            // replay isn't used.
13911421Sdavid.guillen@arm.com            toIEW->commitInfo.doneSeqNum = rob->readTailSeqNum();
14011421Sdavid.guillen@arm.com            toIEW->commitInfo.robSquashing = true;
14111421Sdavid.guillen@arm.com        }
14211421Sdavid.guillen@arm.com    } else {
14311421Sdavid.guillen@arm.com        commit();
14411421Sdavid.guillen@arm.com    }
14511421Sdavid.guillen@arm.com
14611421Sdavid.guillen@arm.com    markCompletedInsts();
14711421Sdavid.guillen@arm.com
14811236Sandreas.sandberg@arm.com    // Writeback number of free ROB entries here.
14911236Sandreas.sandberg@arm.com    DPRINTF(Commit, "Commit: ROB has %d free entries.\n",
15011236Sandreas.sandberg@arm.com            rob->numFreeEntries());
15111236Sandreas.sandberg@arm.com    toIEW->commitInfo.freeROBEntries = rob->numFreeEntries();
15211236Sandreas.sandberg@arm.com}
15311236Sandreas.sandberg@arm.com
15411236Sandreas.sandberg@arm.comtemplate <class Impl>
15511236Sandreas.sandberg@arm.comvoid
15611236Sandreas.sandberg@arm.comSimpleCommit<Impl>::commit()
15711011SAndreas.Sandberg@ARM.com{
15811011SAndreas.Sandberg@ARM.com    //////////////////////////////////////
15911421Sdavid.guillen@arm.com    // Check for interrupts
16011421Sdavid.guillen@arm.com    //////////////////////////////////////
16111421Sdavid.guillen@arm.com
16211236Sandreas.sandberg@arm.com    // Process interrupts if interrupts are enabled and not in PAL mode.
16311236Sandreas.sandberg@arm.com    // Take the PC from commit and write it to the IPR, then squash.  The
16411236Sandreas.sandberg@arm.com    // interrupt completing will take care of restoring the PC from that value
16511236Sandreas.sandberg@arm.com    // in the IPR.  Look at IPR[EXC_ADDR];
16611236Sandreas.sandberg@arm.com    // hwrei() is what resets the PC to the place where instruction execution
16711421Sdavid.guillen@arm.com    // beings again.
16811421Sdavid.guillen@arm.com#ifdef FULL_SYSTEM
16911421Sdavid.guillen@arm.com    if (//checkInterrupts &&
17011236Sandreas.sandberg@arm.com        cpu->check_interrupts() &&
17111236Sandreas.sandberg@arm.com        !cpu->inPalMode(readCommitPC())) {
17211236Sandreas.sandberg@arm.com        // Will need to squash all instructions currently in flight and have
17311236Sandreas.sandberg@arm.com        // the interrupt handler restart at the last non-committed inst.
17411236Sandreas.sandberg@arm.com        // Most of that can be handled through the trap() function.  The
17511236Sandreas.sandberg@arm.com        // processInterrupts() function really just checks for interrupts
17611236Sandreas.sandberg@arm.com        // and then calls trap() if there is an interrupt present.
17711236Sandreas.sandberg@arm.com
17811236Sandreas.sandberg@arm.com        // CPU will handle implementation of the interrupt.
17911011SAndreas.Sandberg@ARM.com        cpu->processInterrupts();
18011011SAndreas.Sandberg@ARM.com    }
18111236Sandreas.sandberg@arm.com#endif // FULL_SYSTEM
18211236Sandreas.sandberg@arm.com
18311236Sandreas.sandberg@arm.com    ////////////////////////////////////
18411236Sandreas.sandberg@arm.com    // Check for squash signal, handle that first
18511236Sandreas.sandberg@arm.com    ////////////////////////////////////
18611236Sandreas.sandberg@arm.com
18711236Sandreas.sandberg@arm.com    // Want to mainly check if the IEW stage is telling the ROB to squash.
18811011SAndreas.Sandberg@ARM.com    // Should I also check if the commit stage is telling the ROB to squah?
18910037SARM gem5 Developers    // This might be necessary to keep the same timing between the IQ and
19010037SARM gem5 Developers    // the ROB...
19110037SARM gem5 Developers    if (fromIEW->squash) {
19210037SARM gem5 Developers        DPRINTF(Commit, "Commit: Squashing instructions in the ROB.\n");
19310037SARM gem5 Developers
19410037SARM gem5 Developers        _status = ROBSquashing;
19510037SARM gem5 Developers
19610037SARM gem5 Developers        InstSeqNum squashed_inst = fromIEW->squashedSeqNum;
19710037SARM gem5 Developers
19810037SARM gem5 Developers        rob->squash(squashed_inst);
19910037SARM gem5 Developers
2009806Sstever@gmail.com        // Send back the sequence number of the squashed instruction.
2017584SAli.Saidi@arm.com        toIEW->commitInfo.doneSeqNum = squashed_inst;
2029338SAndreas.Sandberg@arm.com
2037584SAli.Saidi@arm.com        // Send back the squash signal to tell stages that they should squash.
2047584SAli.Saidi@arm.com        toIEW->commitInfo.squash = true;
2057584SAli.Saidi@arm.com
2067584SAli.Saidi@arm.com        // Send back the rob squashing signal so other stages know that the
2077584SAli.Saidi@arm.com        // ROB is in the process of squashing.
2089338SAndreas.Sandberg@arm.com        toIEW->commitInfo.robSquashing = true;
2099525SAndreas.Sandberg@ARM.com
2107584SAli.Saidi@arm.com        toIEW->commitInfo.branchMispredict = fromIEW->branchMispredict;
2117584SAli.Saidi@arm.com
2127584SAli.Saidi@arm.com        toIEW->commitInfo.branchTaken = fromIEW->branchTaken;
2137584SAli.Saidi@arm.com
2149806Sstever@gmail.com        toIEW->commitInfo.nextPC = fromIEW->nextPC;
2157584SAli.Saidi@arm.com
2169338SAndreas.Sandberg@arm.com        toIEW->commitInfo.mispredPC = fromIEW->mispredPC;
2179525SAndreas.Sandberg@ARM.com
2187584SAli.Saidi@arm.com        if (toIEW->commitInfo.branchMispredict) {
2197584SAli.Saidi@arm.com            ++branchMispredicts;
2207584SAli.Saidi@arm.com        }
2217584SAli.Saidi@arm.com    }
2227584SAli.Saidi@arm.com
2237584SAli.Saidi@arm.com    if (_status != ROBSquashing) {
2248512Sgeoffrey.blake@arm.com        // If we're not currently squashing, then get instructions.
2258512Sgeoffrey.blake@arm.com        getInsts();
2269338SAndreas.Sandberg@arm.com
2279525SAndreas.Sandberg@ARM.com        // Try to commit any instructions.
2288512Sgeoffrey.blake@arm.com        commitInsts();
2298512Sgeoffrey.blake@arm.com    }
2308512Sgeoffrey.blake@arm.com
23110037SARM gem5 Developers    // If the ROB is empty, we can set this stage to idle.  Use this
23210037SARM gem5 Developers    // in the future when the Idle status will actually be utilized.
23310037SARM gem5 Developers#if 0
23410037SARM gem5 Developers    if (rob->isEmpty()) {
23510037SARM gem5 Developers        DPRINTF(Commit, "Commit: ROB is empty.  Status changed to idle.\n");
23610845Sandreas.sandberg@arm.com        _status = Idle;
23710845Sandreas.sandberg@arm.com        // Schedule an event so that commit will actually wake up
23810845Sandreas.sandberg@arm.com        // once something gets put in the ROB.
23910845Sandreas.sandberg@arm.com    }
24010037SARM gem5 Developers#endif
24110847Sandreas.sandberg@arm.com}
24210847Sandreas.sandberg@arm.com
24310847Sandreas.sandberg@arm.com// Loop that goes through as many instructions in the ROB as possible and
24410847Sandreas.sandberg@arm.com// tries to commit them.  The actual work for committing is done by the
24510847Sandreas.sandberg@arm.com// commitHead() function.
24610847Sandreas.sandberg@arm.comtemplate <class Impl>
24710847Sandreas.sandberg@arm.comvoid
24810847Sandreas.sandberg@arm.comSimpleCommit<Impl>::commitInsts()
24910847Sandreas.sandberg@arm.com{
25010847Sandreas.sandberg@arm.com    ////////////////////////////////////
2518870SAli.Saidi@ARM.com    // Handle commit
2528870SAli.Saidi@ARM.com    // Note that commit will be handled prior to the ROB so that the ROB
2539338SAndreas.Sandberg@arm.com    // only tries to commit instructions it has in this current cycle, and
2548870SAli.Saidi@ARM.com    // not instructions it is writing in during this cycle.
2558870SAli.Saidi@ARM.com    // Can't commit and squash things at the same time...
2568870SAli.Saidi@ARM.com    ////////////////////////////////////
2577950SAli.Saidi@ARM.com
2587754SWilliam.Wang@arm.com    if (rob->isEmpty())
2599338SAndreas.Sandberg@arm.com        return;
2609330Schander.sudanthi@arm.com
2617950SAli.Saidi@ARM.com    DynInstPtr head_inst = rob->readHeadInst();
2627950SAli.Saidi@ARM.com
2637754SWilliam.Wang@arm.com    unsigned num_committed = 0;
2647754SWilliam.Wang@arm.com
2657753SWilliam.Wang@arm.com    // Commit as many instructions as possible until the commit bandwidth
2667753SWilliam.Wang@arm.com    // limit is reached, or it becomes impossible to commit any more.
2679338SAndreas.Sandberg@arm.com    while (!rob->isEmpty() &&
2689394Sandreas.hansson@arm.com           head_inst->readyToCommit() &&
2699330Schander.sudanthi@arm.com           num_committed < commitWidth)
2707753SWilliam.Wang@arm.com    {
2719939Sdam.sunwoo@arm.com        DPRINTF(Commit, "Commit: Trying to commit head instruction.\n");
2729939Sdam.sunwoo@arm.com
2739646SChris.Emmons@arm.com        // If the head instruction is squashed, it is ready to retire at any
2749646SChris.Emmons@arm.com        // time.  However, we need to avoid updating any other state
2759646SChris.Emmons@arm.com        // incorrectly if it's already been squashed.
2769646SChris.Emmons@arm.com        if (head_inst->isSquashed()) {
2779646SChris.Emmons@arm.com            // Hack to avoid the instruction being retired (and deleted) if
2789646SChris.Emmons@arm.com            // it hasn't been through the IEW stage yet.
27911237Sandreas.sandberg@arm.com/*
28010840Sandreas.sandberg@arm.com            if (!head_inst->isExecuted()) {
28111090Sandreas.sandberg@arm.com                break;
28211090Sandreas.sandberg@arm.com            }
2839939Sdam.sunwoo@arm.com*/
2849646SChris.Emmons@arm.com
28511090Sandreas.sandberg@arm.com            DPRINTF(Commit, "Commit: Retiring squashed instruction from "
28611090Sandreas.sandberg@arm.com                    "ROB.\n");
28711090Sandreas.sandberg@arm.com
28811090Sandreas.sandberg@arm.com            // Tell ROB to retire head instruction.  This retires the head
28911090Sandreas.sandberg@arm.com            // inst in the ROB without affecting any other stages.
2907584SAli.Saidi@arm.com            rob->retireHead();
2917584SAli.Saidi@arm.com
2929338SAndreas.Sandberg@arm.com            ++commitSquashedInsts;
2933630SN/A
29410358SAli.Saidi@ARM.com        } else {
2958870SAli.Saidi@ARM.com            // Increment the total number of non-speculative instructions
29611297Sandreas.sandberg@arm.com            // executed.
29711297Sandreas.sandberg@arm.com            // Hack for now: it really shouldn't happen until after the
29811297Sandreas.sandberg@arm.com            // commit is deemed to be successful, but this count is needed
29911297Sandreas.sandberg@arm.com            // for syscalls.
30011297Sandreas.sandberg@arm.com            cpu->funcExeInst++;
30111297Sandreas.sandberg@arm.com
30211297Sandreas.sandberg@arm.com            // Try to commit the head instruction.
30311297Sandreas.sandberg@arm.com            bool commit_success = commitHead(head_inst, num_committed);
30411297Sandreas.sandberg@arm.com
30511297Sandreas.sandberg@arm.com            // Update what instruction we are looking at if the commit worked.
30611297Sandreas.sandberg@arm.com            if (commit_success) {
30711297Sandreas.sandberg@arm.com                ++num_committed;
30811297Sandreas.sandberg@arm.com
30911297Sandreas.sandberg@arm.com                // Send back which instruction has been committed.
31011297Sandreas.sandberg@arm.com                // @todo: Update this later when a wider pipeline is used.
31111297Sandreas.sandberg@arm.com                // Hmm, can't really give a pointer here...perhaps the
31211297Sandreas.sandberg@arm.com                // sequence number instead (copy).
31311297Sandreas.sandberg@arm.com                toIEW->commitInfo.doneSeqNum = head_inst->seqNum;
31411297Sandreas.sandberg@arm.com
31511297Sandreas.sandberg@arm.com                ++commitCommittedInsts;
31610353SGeoffrey.Blake@arm.com
31710353SGeoffrey.Blake@arm.com                if (!head_inst->isNop()) {
31810353SGeoffrey.Blake@arm.com                    cpu->instDone();
31910353SGeoffrey.Blake@arm.com                }
32010353SGeoffrey.Blake@arm.com            } else {
32110353SGeoffrey.Blake@arm.com                break;
32210353SGeoffrey.Blake@arm.com            }
32311297Sandreas.sandberg@arm.com        }
32410353SGeoffrey.Blake@arm.com
32510353SGeoffrey.Blake@arm.com        // Update the pointer to read the next instruction in the ROB.
32611297Sandreas.sandberg@arm.com        head_inst = rob->readHeadInst();
32711297Sandreas.sandberg@arm.com    }
32811297Sandreas.sandberg@arm.com
32911297Sandreas.sandberg@arm.com    DPRINTF(CommitRate, "%i\n", num_committed);
33011297Sandreas.sandberg@arm.com    n_committed_dist.sample(num_committed);
33111297Sandreas.sandberg@arm.com}
33211297Sandreas.sandberg@arm.com
33311297Sandreas.sandberg@arm.comtemplate <class Impl>
33411297Sandreas.sandberg@arm.combool
33511297Sandreas.sandberg@arm.comSimpleCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
33610353SGeoffrey.Blake@arm.com{
3378870SAli.Saidi@ARM.com    // Make sure instruction is valid
3389835Sandreas.hansson@arm.com    assert(head_inst);
3399835Sandreas.hansson@arm.com
3408870SAli.Saidi@ARM.com    // If the instruction is not executed yet, then it is a non-speculative
3418870SAli.Saidi@ARM.com    // or store inst.  Signal backwards that it should be executed.
34210037SARM gem5 Developers    if (!head_inst->isExecuted()) {
34310037SARM gem5 Developers        // Keep this number correct.  We have not yet actually executed
34410037SARM gem5 Developers        // and committed this instruction.
3458870SAli.Saidi@ARM.com        cpu->funcExeInst--;
3463630SN/A
3477753SWilliam.Wang@arm.com        if (head_inst->isNonSpeculative()) {
3487753SWilliam.Wang@arm.com            DPRINTF(Commit, "Commit: Encountered a store or non-speculative "
3497753SWilliam.Wang@arm.com                    "instruction at the head of the ROB, PC %#x.\n",
3507584SAli.Saidi@arm.com                    head_inst->readPC());
3517584SAli.Saidi@arm.com
35211236Sandreas.sandberg@arm.com            toIEW->commitInfo.nonSpecSeqNum = head_inst->seqNum;
35311236Sandreas.sandberg@arm.com
35411236Sandreas.sandberg@arm.com            // Change the instruction so it won't try to commit again until
3559525SAndreas.Sandberg@ARM.com            // it is executed.
35611244Sandreas.sandberg@arm.com            head_inst->clearCanCommit();
35711244Sandreas.sandberg@arm.com
35811244Sandreas.sandberg@arm.com            ++commitNonSpecStalls;
3597584SAli.Saidi@arm.com
3607584SAli.Saidi@arm.com            return false;
3618512Sgeoffrey.blake@arm.com        } else {
3627753SWilliam.Wang@arm.com            panic("Commit: Trying to commit un-executed instruction "
3637754SWilliam.Wang@arm.com                  "of unknown type!\n");
3647950SAli.Saidi@ARM.com        }
3658282SAli.Saidi@ARM.com    }
3668525SAli.Saidi@ARM.com
3678212SAli.Saidi@ARM.com    // Now check if it's one of the special trap or barrier or
3688212SAli.Saidi@ARM.com    // serializing instructions.
3698212SAli.Saidi@ARM.com    if (head_inst->isThreadSync()  ||
3708212SAli.Saidi@ARM.com        head_inst->isSerializing() ||
3718212SAli.Saidi@ARM.com        head_inst->isMemBarrier()  ||
3727584SAli.Saidi@arm.com        head_inst->isWriteBarrier() )
3737731SAli.Saidi@ARM.com    {
3748461SAli.Saidi@ARM.com        // Not handled for now.  Mem barriers and write barriers are safe
3758461SAli.Saidi@ARM.com        // to simply let commit as memory accesses only happen once they
3767696SAli.Saidi@ARM.com        // reach the head of commit.  Not sure about the other two.
3777696SAli.Saidi@ARM.com        panic("Serializing or barrier instructions"
3787696SAli.Saidi@ARM.com              " are not handled yet.\n");
3797696SAli.Saidi@ARM.com    }
3807696SAli.Saidi@ARM.com
3817696SAli.Saidi@ARM.com    // Check if the instruction caused a fault.  If so, trap.
3827696SAli.Saidi@ARM.com    Fault inst_fault = head_inst->getFault();
3837696SAli.Saidi@ARM.com
3847696SAli.Saidi@ARM.com    if (inst_fault != No_Fault && inst_fault != Fake_Mem_Fault) {
3857696SAli.Saidi@ARM.com        if (!head_inst->isNop()) {
3867696SAli.Saidi@ARM.com#ifdef FULL_SYSTEM
3877696SAli.Saidi@ARM.com            cpu->trap(inst_fault);
3887696SAli.Saidi@ARM.com#else // !FULL_SYSTEM
3897696SAli.Saidi@ARM.com            panic("fault (%d) detected @ PC %08p", inst_fault,
3908906Skoansin.tan@gmail.com                  head_inst->PC);
39110397Sstephan.diestelhorst@arm.com#endif // FULL_SYSTEM
3927696SAli.Saidi@ARM.com        }
3937696SAli.Saidi@ARM.com    }
3948713Sandreas.hansson@arm.com
3958713Sandreas.hansson@arm.com    // Check if we're really ready to commit.  If not then return false.
3968713Sandreas.hansson@arm.com    // I'm pretty sure all instructions should be able to commit if they've
3978839Sandreas.hansson@arm.com    // reached this far.  For now leave this in as a check.
3988839Sandreas.hansson@arm.com    if (!rob->isHeadReady()) {
3998839Sandreas.hansson@arm.com        panic("Commit: Unable to commit head instruction!\n");
4008839Sandreas.hansson@arm.com        return false;
4018713Sandreas.hansson@arm.com    }
4028713Sandreas.hansson@arm.com
4038713Sandreas.hansson@arm.com    // If it's a branch, then send back branch prediction update info
4048713Sandreas.hansson@arm.com    // to the fetch stage.
4058870SAli.Saidi@ARM.com    // This should be handled in the iew stage if a mispredict happens...
4068870SAli.Saidi@ARM.com
4078870SAli.Saidi@ARM.com    if (head_inst->isControl()) {
4087696SAli.Saidi@ARM.com
40910353SGeoffrey.Blake@arm.com#if 0
41010353SGeoffrey.Blake@arm.com        toIEW->nextPC = head_inst->readPC();
41110353SGeoffrey.Blake@arm.com        //Maybe switch over to BTB incorrect.
41210353SGeoffrey.Blake@arm.com        toIEW->btbMissed = head_inst->btbMiss();
41310353SGeoffrey.Blake@arm.com        toIEW->target = head_inst->nextPC;
41410353SGeoffrey.Blake@arm.com        //Maybe also include global history information.
41510353SGeoffrey.Blake@arm.com        //This simple version will have no branch prediction however.
41610353SGeoffrey.Blake@arm.com#endif
4177696SAli.Saidi@ARM.com
4187696SAli.Saidi@ARM.com        ++commitCommittedBranches;
4197696SAli.Saidi@ARM.com    }
4207696SAli.Saidi@ARM.com
4218839Sandreas.hansson@arm.com#if 0
4228839Sandreas.hansson@arm.com    // Explicit communication back to the LDSTQ that a load has been committed
42311244Sandreas.sandberg@arm.com    // and can be removed from the LDSTQ.  Stores don't need this because
4248839Sandreas.hansson@arm.com    // the LDSTQ will already have been told that a store has reached the head
4258839Sandreas.hansson@arm.com    // of the ROB.  Consider including communication if it's a store as well
4268839Sandreas.hansson@arm.com    // to keep things orthagonal.
4278839Sandreas.hansson@arm.com    if (head_inst->isMemRef()) {
4288839Sandreas.hansson@arm.com        ++commitCommittedMemRefs;
4298839Sandreas.hansson@arm.com        if (head_inst->isLoad()) {
4308839Sandreas.hansson@arm.com            toIEW->commitInfo.commitIsLoad = true;
4318839Sandreas.hansson@arm.com            ++commitCommittedLoads;
4328839Sandreas.hansson@arm.com        }
4338839Sandreas.hansson@arm.com    }
4348839Sandreas.hansson@arm.com#endif
4358839Sandreas.hansson@arm.com
4368839Sandreas.hansson@arm.com    // Now that the instruction is going to be committed, finalize its
4378839Sandreas.hansson@arm.com    // trace data.
4388839Sandreas.hansson@arm.com    if (head_inst->traceData) {
4398839Sandreas.hansson@arm.com        head_inst->traceData->finalize();
4408839Sandreas.hansson@arm.com    }
4418839Sandreas.hansson@arm.com
4428839Sandreas.hansson@arm.com    //Finally clear the head ROB entry.
4438839Sandreas.hansson@arm.com    rob->retireHead();
4448839Sandreas.hansson@arm.com
4458839Sandreas.hansson@arm.com    // Return true to indicate that we have committed an instruction.
4468906Skoansin.tan@gmail.com    return true;
4478839Sandreas.hansson@arm.com}
44810397Sstephan.diestelhorst@arm.com
4497696SAli.Saidi@ARM.comtemplate <class Impl>
45010353SGeoffrey.Blake@arm.comvoid
45110353SGeoffrey.Blake@arm.comSimpleCommit<Impl>::getInsts()
45210353SGeoffrey.Blake@arm.com{
45310353SGeoffrey.Blake@arm.com    //////////////////////////////////////
45410353SGeoffrey.Blake@arm.com    // Handle ROB functions
45510353SGeoffrey.Blake@arm.com    //////////////////////////////////////
45610353SGeoffrey.Blake@arm.com
45710353SGeoffrey.Blake@arm.com    // Read any issued instructions and place them into the ROB.  Do this
45810353SGeoffrey.Blake@arm.com    // prior to squashing to avoid having instructions in the ROB that
45910353SGeoffrey.Blake@arm.com    // don't get squashed properly.
46010353SGeoffrey.Blake@arm.com    int insts_to_process = min((int)renameWidth, fromRename->size);
46110353SGeoffrey.Blake@arm.com
46210353SGeoffrey.Blake@arm.com    for (int inst_num = 0;
46310353SGeoffrey.Blake@arm.com         inst_num < insts_to_process;
46410353SGeoffrey.Blake@arm.com         ++inst_num)
46510353SGeoffrey.Blake@arm.com    {
46610353SGeoffrey.Blake@arm.com        if (!fromRename->insts[inst_num]->isSquashed()) {
46710353SGeoffrey.Blake@arm.com            DPRINTF(Commit, "Commit: Inserting PC %#x into ROB.\n",
46810353SGeoffrey.Blake@arm.com                    fromRename->insts[inst_num]->readPC());
46910353SGeoffrey.Blake@arm.com            rob->insertInst(fromRename->insts[inst_num]);
47010353SGeoffrey.Blake@arm.com        } else {
47110353SGeoffrey.Blake@arm.com            DPRINTF(Commit, "Commit: Instruction %i PC %#x was "
47210353SGeoffrey.Blake@arm.com                    "squashed, skipping.\n",
47310353SGeoffrey.Blake@arm.com                    fromRename->insts[inst_num]->seqNum,
47410353SGeoffrey.Blake@arm.com                    fromRename->insts[inst_num]->readPC());
47510353SGeoffrey.Blake@arm.com        }
47610353SGeoffrey.Blake@arm.com    }
47710397Sstephan.diestelhorst@arm.com}
47810353SGeoffrey.Blake@arm.com
4797754SWilliam.Wang@arm.comtemplate <class Impl>
4807754SWilliam.Wang@arm.comvoid
4817754SWilliam.Wang@arm.comSimpleCommit<Impl>::markCompletedInsts()
4827696SAli.Saidi@ARM.com{
4837696SAli.Saidi@ARM.com    // Grab completed insts out of the IEW instruction queue, and mark
48411236Sandreas.sandberg@arm.com    // instructions completed within the ROB.
48511236Sandreas.sandberg@arm.com    for (int inst_num = 0;
48611236Sandreas.sandberg@arm.com         inst_num < fromIEW->size && fromIEW->insts[inst_num];
4879525SAndreas.Sandberg@ARM.com         ++inst_num)
4887696SAli.Saidi@ARM.com    {
4897696SAli.Saidi@ARM.com        DPRINTF(Commit, "Commit: Marking PC %#x, SN %i ready within ROB.\n",
4907754SWilliam.Wang@arm.com                fromIEW->insts[inst_num]->readPC(),
4917754SWilliam.Wang@arm.com                fromIEW->insts[inst_num]->seqNum);
4927950SAli.Saidi@ARM.com
4937696SAli.Saidi@ARM.com        // Mark the instruction as ready to commit.
4947696SAli.Saidi@ARM.com        fromIEW->insts[inst_num]->setCanCommit();
4958461SAli.Saidi@ARM.com    }
4968461SAli.Saidi@ARM.com}
4977584SAli.Saidi@arm.com
4987584SAli.Saidi@arm.comtemplate <class Impl>
4997584SAli.Saidi@arm.comuint64_t
5007584SAli.Saidi@arm.comSimpleCommit<Impl>::readCommitPC()
5018299Schander.sudanthi@arm.com{
5027584SAli.Saidi@arm.com    return rob->readHeadPC();
5037584SAli.Saidi@arm.com}
5047584SAli.Saidi@arm.com
5057584SAli.Saidi@arm.com#endif // __COMMIT_IMPL_HH__
5067584SAli.Saidi@arm.com