commit_impl.hh revision 1681
112391Sjason@lowepower.com// @todo: Bug when something reaches execute, and mispredicts, but is never
212391Sjason@lowepower.com// put into the ROB because the ROB is full.  Need rename stage to predict
312391Sjason@lowepower.com// the free ROB entries better.
412391Sjason@lowepower.com
512391Sjason@lowepower.com#ifndef __COMMIT_IMPL_HH__
612391Sjason@lowepower.com#define __COMMIT_IMPL_HH__
712391Sjason@lowepower.com
812391Sjason@lowepower.com#include "base/timebuf.hh"
912391Sjason@lowepower.com#include "cpu/beta_cpu/commit.hh"
1012391Sjason@lowepower.com#include "cpu/exetrace.hh"
1112391Sjason@lowepower.com
1212391Sjason@lowepower.comtemplate <class Impl>
1312391Sjason@lowepower.comSimpleCommit<Impl>::SimpleCommit(Params &params)
1412391Sjason@lowepower.com    : dcacheInterface(params.dcacheInterface),
1512391Sjason@lowepower.com      iewToCommitDelay(params.iewToCommitDelay),
1612391Sjason@lowepower.com      renameToROBDelay(params.renameToROBDelay),
1712391Sjason@lowepower.com      renameWidth(params.renameWidth),
1812391Sjason@lowepower.com      iewWidth(params.executeWidth),
1912391Sjason@lowepower.com      commitWidth(params.commitWidth)
2012391Sjason@lowepower.com{
2112391Sjason@lowepower.com    _status = Idle;
2212391Sjason@lowepower.com}
2312391Sjason@lowepower.com
2412391Sjason@lowepower.comtemplate <class Impl>
2512391Sjason@lowepower.comvoid
2612391Sjason@lowepower.comSimpleCommit<Impl>::regStats()
2712391Sjason@lowepower.com{
2812391Sjason@lowepower.com    commitCommittedInsts
2912391Sjason@lowepower.com        .name(name() + ".commitCommittedInsts")
3012391Sjason@lowepower.com        .desc("The number of committed instructions")
3112391Sjason@lowepower.com        .prereq(commitCommittedInsts);
3212391Sjason@lowepower.com    commitSquashedInsts
3312391Sjason@lowepower.com        .name(name() + ".commitSquashedInsts")
3412391Sjason@lowepower.com        .desc("The number of squashed insts skipped by commit")
3512391Sjason@lowepower.com        .prereq(commitSquashedInsts);
3612391Sjason@lowepower.com    commitSquashEvents
3712391Sjason@lowepower.com        .name(name() + ".commitSquashEvents")
3812391Sjason@lowepower.com        .desc("The number of times commit is told to squash")
3912391Sjason@lowepower.com        .prereq(commitSquashEvents);
4012391Sjason@lowepower.com    commitNonSpecStalls
4112391Sjason@lowepower.com        .name(name() + ".commitNonSpecStalls")
4212391Sjason@lowepower.com        .desc("The number of times commit has been forced to stall to "
4312391Sjason@lowepower.com              "communicate backwards")
4412391Sjason@lowepower.com        .prereq(commitNonSpecStalls);
4512391Sjason@lowepower.com    commitCommittedBranches
4612391Sjason@lowepower.com        .name(name() + ".commitCommittedBranches")
4712391Sjason@lowepower.com        .desc("The number of committed branches")
4812391Sjason@lowepower.com        .prereq(commitCommittedBranches);
4912391Sjason@lowepower.com    commitCommittedLoads
5012391Sjason@lowepower.com        .name(name() + ".commitCommittedLoads")
5112391Sjason@lowepower.com        .desc("The number of committed loads")
5212391Sjason@lowepower.com        .prereq(commitCommittedLoads);
5312391Sjason@lowepower.com    commitCommittedMemRefs
5412391Sjason@lowepower.com        .name(name() + ".commitCommittedMemRefs")
5512391Sjason@lowepower.com        .desc("The number of committed memory references")
5612391Sjason@lowepower.com        .prereq(commitCommittedMemRefs);
5712391Sjason@lowepower.com    branchMispredicts
5812391Sjason@lowepower.com        .name(name() + ".branchMispredicts")
5912391Sjason@lowepower.com        .desc("The number of times a branch was mispredicted")
6012391Sjason@lowepower.com        .prereq(branchMispredicts);
6112391Sjason@lowepower.com    n_committed_dist
6212391Sjason@lowepower.com        .init(0,commitWidth,1)
6312391Sjason@lowepower.com        .name(name() + ".COM:committed_per_cycle")
6412391Sjason@lowepower.com        .desc("Number of insts commited each cycle")
6512391Sjason@lowepower.com        .flags(Stats::pdf)
6612391Sjason@lowepower.com        ;
6712391Sjason@lowepower.com}
6812391Sjason@lowepower.com
6912391Sjason@lowepower.comtemplate <class Impl>
7012391Sjason@lowepower.comvoid
7112391Sjason@lowepower.comSimpleCommit<Impl>::setCPU(FullCPU *cpu_ptr)
7212391Sjason@lowepower.com{
7312391Sjason@lowepower.com    DPRINTF(Commit, "Commit: Setting CPU pointer.\n");
7412391Sjason@lowepower.com    cpu = cpu_ptr;
7512391Sjason@lowepower.com}
7612391Sjason@lowepower.com
7712391Sjason@lowepower.comtemplate <class Impl>
7812391Sjason@lowepower.comvoid
7912391Sjason@lowepower.comSimpleCommit<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
8012391Sjason@lowepower.com{
8112391Sjason@lowepower.com    DPRINTF(Commit, "Commit: Setting time buffer pointer.\n");
8212391Sjason@lowepower.com    timeBuffer = tb_ptr;
8312391Sjason@lowepower.com
8412391Sjason@lowepower.com    // Setup wire to send information back to IEW.
8512391Sjason@lowepower.com    toIEW = timeBuffer->getWire(0);
8612391Sjason@lowepower.com
8712391Sjason@lowepower.com    // Setup wire to read data from IEW (for the ROB).
8812391Sjason@lowepower.com    robInfoFromIEW = timeBuffer->getWire(-iewToCommitDelay);
8912391Sjason@lowepower.com}
9012391Sjason@lowepower.com
9112391Sjason@lowepower.comtemplate <class Impl>
9212391Sjason@lowepower.comvoid
9312391Sjason@lowepower.comSimpleCommit<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
9412391Sjason@lowepower.com{
9512391Sjason@lowepower.com    DPRINTF(Commit, "Commit: Setting rename queue pointer.\n");
9612391Sjason@lowepower.com    renameQueue = rq_ptr;
9712391Sjason@lowepower.com
9812391Sjason@lowepower.com    // Setup wire to get instructions from rename (for the ROB).
9912391Sjason@lowepower.com    fromRename = renameQueue->getWire(-renameToROBDelay);
10012391Sjason@lowepower.com}
10112391Sjason@lowepower.com
10212391Sjason@lowepower.comtemplate <class Impl>
10312391Sjason@lowepower.comvoid
10412391Sjason@lowepower.comSimpleCommit<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
10512391Sjason@lowepower.com{
10612391Sjason@lowepower.com    DPRINTF(Commit, "Commit: Setting IEW queue pointer.\n");
10712391Sjason@lowepower.com    iewQueue = iq_ptr;
10812391Sjason@lowepower.com
10912391Sjason@lowepower.com    // Setup wire to get instructions from IEW.
11012391Sjason@lowepower.com    fromIEW = iewQueue->getWire(-iewToCommitDelay);
11112391Sjason@lowepower.com}
11212391Sjason@lowepower.com
11312391Sjason@lowepower.comtemplate <class Impl>
11412391Sjason@lowepower.comvoid
11512391Sjason@lowepower.comSimpleCommit<Impl>::setROB(ROB *rob_ptr)
11612391Sjason@lowepower.com{
11712391Sjason@lowepower.com    DPRINTF(Commit, "Commit: Setting ROB pointer.\n");
11812391Sjason@lowepower.com    rob = rob_ptr;
11912391Sjason@lowepower.com}
12012391Sjason@lowepower.com
12112391Sjason@lowepower.comtemplate <class Impl>
12212391Sjason@lowepower.comvoid
12312391Sjason@lowepower.comSimpleCommit<Impl>::tick()
12412391Sjason@lowepower.com{
12512391Sjason@lowepower.com    // If the ROB is currently in its squash sequence, then continue
12612391Sjason@lowepower.com    // to squash.  In this case, commit does not do anything.  Otherwise
12712391Sjason@lowepower.com    // run commit.
12812391Sjason@lowepower.com    if (_status == ROBSquashing) {
12912391Sjason@lowepower.com        if (rob->isDoneSquashing()) {
13012391Sjason@lowepower.com            _status = Running;
13112391Sjason@lowepower.com        } else {
13212391Sjason@lowepower.com            rob->doSquash();
13312391Sjason@lowepower.com
13412391Sjason@lowepower.com            // Send back sequence number of tail of ROB, so other stages
13512391Sjason@lowepower.com            // can squash younger instructions.  Note that really the only
13612391Sjason@lowepower.com            // stage that this is important for is the IEW stage; other
13712391Sjason@lowepower.com            // stages can just clear all their state as long as selective
13812391Sjason@lowepower.com            // replay isn't used.
13912391Sjason@lowepower.com            toIEW->commitInfo.doneSeqNum = rob->readTailSeqNum();
14012391Sjason@lowepower.com            toIEW->commitInfo.robSquashing = true;
14112391Sjason@lowepower.com        }
14212391Sjason@lowepower.com    } else {
14312391Sjason@lowepower.com        commit();
14412391Sjason@lowepower.com    }
14512391Sjason@lowepower.com
14612391Sjason@lowepower.com    markCompletedInsts();
14712391Sjason@lowepower.com
14812391Sjason@lowepower.com    // Writeback number of free ROB entries here.
14912391Sjason@lowepower.com    DPRINTF(Commit, "Commit: ROB has %d free entries.\n",
15012391Sjason@lowepower.com            rob->numFreeEntries());
15112391Sjason@lowepower.com    toIEW->commitInfo.freeROBEntries = rob->numFreeEntries();
15212391Sjason@lowepower.com}
15312391Sjason@lowepower.com
15412391Sjason@lowepower.comtemplate <class Impl>
15512391Sjason@lowepower.comvoid
15612391Sjason@lowepower.comSimpleCommit<Impl>::commit()
15712391Sjason@lowepower.com{
15812391Sjason@lowepower.com    //////////////////////////////////////
15912391Sjason@lowepower.com    // Check for interrupts
16012391Sjason@lowepower.com    //////////////////////////////////////
16112391Sjason@lowepower.com
16212391Sjason@lowepower.com    // Process interrupts if interrupts are enabled and not in PAL mode.
16312391Sjason@lowepower.com    // Take the PC from commit and write it to the IPR, then squash.  The
16412391Sjason@lowepower.com    // interrupt completing will take care of restoring the PC from that value
16512391Sjason@lowepower.com    // in the IPR.  Look at IPR[EXC_ADDR];
16612391Sjason@lowepower.com    // hwrei() is what resets the PC to the place where instruction execution
16712391Sjason@lowepower.com    // beings again.
16812391Sjason@lowepower.com#ifdef FULL_SYSTEM
16912391Sjason@lowepower.com    if (//checkInterrupts &&
17012391Sjason@lowepower.com        cpu->check_interrupts() &&
17112391Sjason@lowepower.com        !cpu->inPalMode(readCommitPC())) {
17212391Sjason@lowepower.com        // Will need to squash all instructions currently in flight and have
17312391Sjason@lowepower.com        // the interrupt handler restart at the last non-committed inst.
17412391Sjason@lowepower.com        // Most of that can be handled through the trap() function.  The
17512391Sjason@lowepower.com        // processInterrupts() function really just checks for interrupts
17612391Sjason@lowepower.com        // and then calls trap() if there is an interrupt present.
17712391Sjason@lowepower.com
17812391Sjason@lowepower.com        // CPU will handle implementation of the interrupt.
17912391Sjason@lowepower.com        cpu->processInterrupts();
18012391Sjason@lowepower.com    }
18112391Sjason@lowepower.com#endif // FULL_SYSTEM
18212391Sjason@lowepower.com
18312391Sjason@lowepower.com    ////////////////////////////////////
18412391Sjason@lowepower.com    // Check for squash signal, handle that first
18512391Sjason@lowepower.com    ////////////////////////////////////
18612391Sjason@lowepower.com
18712391Sjason@lowepower.com    // Want to mainly check if the IEW stage is telling the ROB to squash.
18812391Sjason@lowepower.com    // Should I also check if the commit stage is telling the ROB to squah?
18912391Sjason@lowepower.com    // This might be necessary to keep the same timing between the IQ and
19012391Sjason@lowepower.com    // the ROB...
19112391Sjason@lowepower.com    if (fromIEW->squash) {
19212391Sjason@lowepower.com        DPRINTF(Commit, "Commit: Squashing instructions in the ROB.\n");
19312391Sjason@lowepower.com
19412391Sjason@lowepower.com        _status = ROBSquashing;
19512391Sjason@lowepower.com
19612391Sjason@lowepower.com        InstSeqNum squashed_inst = fromIEW->squashedSeqNum;
19712391Sjason@lowepower.com
19812391Sjason@lowepower.com        rob->squash(squashed_inst);
19912391Sjason@lowepower.com
20012391Sjason@lowepower.com        // Send back the sequence number of the squashed instruction.
20112391Sjason@lowepower.com        toIEW->commitInfo.doneSeqNum = squashed_inst;
20212391Sjason@lowepower.com
20312391Sjason@lowepower.com        // Send back the squash signal to tell stages that they should squash.
20412391Sjason@lowepower.com        toIEW->commitInfo.squash = true;
20512391Sjason@lowepower.com
20612391Sjason@lowepower.com        // Send back the rob squashing signal so other stages know that the
20712391Sjason@lowepower.com        // ROB is in the process of squashing.
20812391Sjason@lowepower.com        toIEW->commitInfo.robSquashing = true;
20912391Sjason@lowepower.com
21012391Sjason@lowepower.com        toIEW->commitInfo.branchMispredict = fromIEW->branchMispredict;
21112391Sjason@lowepower.com
21212391Sjason@lowepower.com        toIEW->commitInfo.branchTaken = fromIEW->branchTaken;
21312391Sjason@lowepower.com
21412391Sjason@lowepower.com        toIEW->commitInfo.nextPC = fromIEW->nextPC;
21512391Sjason@lowepower.com
21612391Sjason@lowepower.com        toIEW->commitInfo.mispredPC = fromIEW->mispredPC;
21712391Sjason@lowepower.com
21812391Sjason@lowepower.com        if (toIEW->commitInfo.branchMispredict) {
21912391Sjason@lowepower.com            ++branchMispredicts;
22012391Sjason@lowepower.com        }
22112391Sjason@lowepower.com    }
22212391Sjason@lowepower.com
22312391Sjason@lowepower.com    if (_status != ROBSquashing) {
22412391Sjason@lowepower.com        // If we're not currently squashing, then get instructions.
22512391Sjason@lowepower.com        getInsts();
22612391Sjason@lowepower.com
22712391Sjason@lowepower.com        // Try to commit any instructions.
22812391Sjason@lowepower.com        commitInsts();
22912391Sjason@lowepower.com    }
23012391Sjason@lowepower.com
23112391Sjason@lowepower.com    // If the ROB is empty, we can set this stage to idle.  Use this
23212391Sjason@lowepower.com    // in the future when the Idle status will actually be utilized.
23312391Sjason@lowepower.com#if 0
23412391Sjason@lowepower.com    if (rob->isEmpty()) {
23512391Sjason@lowepower.com        DPRINTF(Commit, "Commit: ROB is empty.  Status changed to idle.\n");
23612391Sjason@lowepower.com        _status = Idle;
23712391Sjason@lowepower.com        // Schedule an event so that commit will actually wake up
23812391Sjason@lowepower.com        // once something gets put in the ROB.
23912391Sjason@lowepower.com    }
24012391Sjason@lowepower.com#endif
24112391Sjason@lowepower.com}
24212391Sjason@lowepower.com
24312391Sjason@lowepower.com// Loop that goes through as many instructions in the ROB as possible and
24412391Sjason@lowepower.com// tries to commit them.  The actual work for committing is done by the
24512391Sjason@lowepower.com// commitHead() function.
24612391Sjason@lowepower.comtemplate <class Impl>
24712391Sjason@lowepower.comvoid
24812391Sjason@lowepower.comSimpleCommit<Impl>::commitInsts()
24912391Sjason@lowepower.com{
25012391Sjason@lowepower.com    ////////////////////////////////////
25112391Sjason@lowepower.com    // Handle commit
25212391Sjason@lowepower.com    // Note that commit will be handled prior to the ROB so that the ROB
25312391Sjason@lowepower.com    // only tries to commit instructions it has in this current cycle, and
25412391Sjason@lowepower.com    // not instructions it is writing in during this cycle.
25512391Sjason@lowepower.com    // Can't commit and squash things at the same time...
25612391Sjason@lowepower.com    ////////////////////////////////////
25712391Sjason@lowepower.com
25812391Sjason@lowepower.com    if (rob->isEmpty())
25912391Sjason@lowepower.com        return;
26012391Sjason@lowepower.com
26112391Sjason@lowepower.com    DynInstPtr head_inst = rob->readHeadInst();
26212391Sjason@lowepower.com
26312391Sjason@lowepower.com    unsigned num_committed = 0;
26412391Sjason@lowepower.com
26512391Sjason@lowepower.com    // Commit as many instructions as possible until the commit bandwidth
26612391Sjason@lowepower.com    // limit is reached, or it becomes impossible to commit any more.
26712391Sjason@lowepower.com    while (!rob->isEmpty() &&
26812391Sjason@lowepower.com           head_inst->readyToCommit() &&
26912391Sjason@lowepower.com           num_committed < commitWidth)
27012391Sjason@lowepower.com    {
27112391Sjason@lowepower.com        DPRINTF(Commit, "Commit: Trying to commit head instruction.\n");
27212391Sjason@lowepower.com
27312391Sjason@lowepower.com        // If the head instruction is squashed, it is ready to retire at any
27412391Sjason@lowepower.com        // time.  However, we need to avoid updating any other state
27512391Sjason@lowepower.com        // incorrectly if it's already been squashed.
27612391Sjason@lowepower.com        if (head_inst->isSquashed()) {
27712391Sjason@lowepower.com            // Hack to avoid the instruction being retired (and deleted) if
27812391Sjason@lowepower.com            // it hasn't been through the IEW stage yet.
27912391Sjason@lowepower.com/*
28012391Sjason@lowepower.com            if (!head_inst->isExecuted()) {
28112391Sjason@lowepower.com                break;
28212391Sjason@lowepower.com            }
28312391Sjason@lowepower.com*/
28412391Sjason@lowepower.com
28512391Sjason@lowepower.com            DPRINTF(Commit, "Commit: Retiring squashed instruction from "
28612391Sjason@lowepower.com                    "ROB.\n");
28712391Sjason@lowepower.com
28812391Sjason@lowepower.com            // Tell ROB to retire head instruction.  This retires the head
28912391Sjason@lowepower.com            // inst in the ROB without affecting any other stages.
29012391Sjason@lowepower.com            rob->retireHead();
29112391Sjason@lowepower.com
29212391Sjason@lowepower.com            ++commitSquashedInsts;
29312391Sjason@lowepower.com
29412391Sjason@lowepower.com        } else {
29512391Sjason@lowepower.com            // Increment the total number of non-speculative instructions
29612391Sjason@lowepower.com            // executed.
29712391Sjason@lowepower.com            // Hack for now: it really shouldn't happen until after the
29812391Sjason@lowepower.com            // commit is deemed to be successful, but this count is needed
29912391Sjason@lowepower.com            // for syscalls.
30012391Sjason@lowepower.com            cpu->funcExeInst++;
30112391Sjason@lowepower.com
30212391Sjason@lowepower.com            // Try to commit the head instruction.
30312391Sjason@lowepower.com            bool commit_success = commitHead(head_inst, num_committed);
30412391Sjason@lowepower.com
30512391Sjason@lowepower.com            // Update what instruction we are looking at if the commit worked.
30612391Sjason@lowepower.com            if (commit_success) {
30712391Sjason@lowepower.com                ++num_committed;
30812391Sjason@lowepower.com
30912391Sjason@lowepower.com                // Send back which instruction has been committed.
31012391Sjason@lowepower.com                // @todo: Update this later when a wider pipeline is used.
31112391Sjason@lowepower.com                // Hmm, can't really give a pointer here...perhaps the
31212391Sjason@lowepower.com                // sequence number instead (copy).
31312391Sjason@lowepower.com                toIEW->commitInfo.doneSeqNum = head_inst->seqNum;
31412391Sjason@lowepower.com
31512391Sjason@lowepower.com                ++commitCommittedInsts;
31612391Sjason@lowepower.com
31712391Sjason@lowepower.com                if (!head_inst->isNop()) {
31812391Sjason@lowepower.com                    cpu->instDone();
31912391Sjason@lowepower.com                }
32012391Sjason@lowepower.com            } else {
32112391Sjason@lowepower.com                break;
32212391Sjason@lowepower.com            }
32312391Sjason@lowepower.com        }
32412391Sjason@lowepower.com
32512391Sjason@lowepower.com        // Update the pointer to read the next instruction in the ROB.
32612391Sjason@lowepower.com        head_inst = rob->readHeadInst();
32712391Sjason@lowepower.com    }
32812391Sjason@lowepower.com
32912391Sjason@lowepower.com    DPRINTF(CommitRate, "%i\n", num_committed);
33012391Sjason@lowepower.com    n_committed_dist.sample(num_committed);
33112391Sjason@lowepower.com}
33212391Sjason@lowepower.com
33312391Sjason@lowepower.comtemplate <class Impl>
33412391Sjason@lowepower.combool
33512391Sjason@lowepower.comSimpleCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
33612391Sjason@lowepower.com{
33712391Sjason@lowepower.com    // Make sure instruction is valid
33812391Sjason@lowepower.com    assert(head_inst);
33912391Sjason@lowepower.com
34012391Sjason@lowepower.com    // If the instruction is not executed yet, then it is a non-speculative
34112391Sjason@lowepower.com    // or store inst.  Signal backwards that it should be executed.
34212391Sjason@lowepower.com    if (!head_inst->isExecuted()) {
34312391Sjason@lowepower.com        // Keep this number correct.  We have not yet actually executed
34412391Sjason@lowepower.com        // and committed this instruction.
34512391Sjason@lowepower.com        cpu->funcExeInst--;
34612391Sjason@lowepower.com
34712391Sjason@lowepower.com        if (head_inst->isNonSpeculative()) {
34812391Sjason@lowepower.com            DPRINTF(Commit, "Commit: Encountered a store or non-speculative "
34912391Sjason@lowepower.com                    "instruction at the head of the ROB, PC %#x.\n",
35012391Sjason@lowepower.com                    head_inst->readPC());
35112391Sjason@lowepower.com
35212391Sjason@lowepower.com            toIEW->commitInfo.nonSpecSeqNum = head_inst->seqNum;
35312391Sjason@lowepower.com
35412391Sjason@lowepower.com            // Change the instruction so it won't try to commit again until
35512391Sjason@lowepower.com            // it is executed.
35612391Sjason@lowepower.com            head_inst->clearCanCommit();
35712391Sjason@lowepower.com
35812391Sjason@lowepower.com            ++commitNonSpecStalls;
35912391Sjason@lowepower.com
36012391Sjason@lowepower.com            return false;
36112391Sjason@lowepower.com        } else {
36212391Sjason@lowepower.com            panic("Commit: Trying to commit un-executed instruction "
36312391Sjason@lowepower.com                  "of unknown type!\n");
36412391Sjason@lowepower.com        }
36512391Sjason@lowepower.com    }
36612391Sjason@lowepower.com
36712391Sjason@lowepower.com    // Now check if it's one of the special trap or barrier or
36812391Sjason@lowepower.com    // serializing instructions.
36912391Sjason@lowepower.com    if (head_inst->isThreadSync()  ||
37012391Sjason@lowepower.com        head_inst->isSerializing() ||
37112391Sjason@lowepower.com        head_inst->isMemBarrier()  ||
37212391Sjason@lowepower.com        head_inst->isWriteBarrier() )
37312391Sjason@lowepower.com    {
37412391Sjason@lowepower.com        // Not handled for now.  Mem barriers and write barriers are safe
37512391Sjason@lowepower.com        // to simply let commit as memory accesses only happen once they
37612391Sjason@lowepower.com        // reach the head of commit.  Not sure about the other two.
37712391Sjason@lowepower.com        panic("Serializing or barrier instructions"
37812391Sjason@lowepower.com              " are not handled yet.\n");
37912391Sjason@lowepower.com    }
38012391Sjason@lowepower.com
38112391Sjason@lowepower.com    // Check if the instruction caused a fault.  If so, trap.
38212391Sjason@lowepower.com    Fault inst_fault = head_inst->getFault();
38312391Sjason@lowepower.com
38412391Sjason@lowepower.com    if (inst_fault != No_Fault && inst_fault != Fake_Mem_Fault) {
38512391Sjason@lowepower.com        if (!head_inst->isNop()) {
38612391Sjason@lowepower.com#ifdef FULL_SYSTEM
38712391Sjason@lowepower.com            cpu->trap(inst_fault);
38812391Sjason@lowepower.com#else // !FULL_SYSTEM
38912391Sjason@lowepower.com            panic("fault (%d) detected @ PC %08p", inst_fault,
39012391Sjason@lowepower.com                  head_inst->PC);
39112391Sjason@lowepower.com#endif // FULL_SYSTEM
39212391Sjason@lowepower.com        }
39312391Sjason@lowepower.com    }
39412391Sjason@lowepower.com
39512391Sjason@lowepower.com    // Check if we're really ready to commit.  If not then return false.
39612391Sjason@lowepower.com    // I'm pretty sure all instructions should be able to commit if they've
39712391Sjason@lowepower.com    // reached this far.  For now leave this in as a check.
39812391Sjason@lowepower.com    if (!rob->isHeadReady()) {
39912391Sjason@lowepower.com        panic("Commit: Unable to commit head instruction!\n");
40012391Sjason@lowepower.com        return false;
40112391Sjason@lowepower.com    }
40212391Sjason@lowepower.com
40312391Sjason@lowepower.com    // If it's a branch, then send back branch prediction update info
40412391Sjason@lowepower.com    // to the fetch stage.
40512391Sjason@lowepower.com    // This should be handled in the iew stage if a mispredict happens...
40612391Sjason@lowepower.com
40712391Sjason@lowepower.com    if (head_inst->isControl()) {
40812391Sjason@lowepower.com
40912391Sjason@lowepower.com#if 0
41012391Sjason@lowepower.com        toIEW->nextPC = head_inst->readPC();
41112391Sjason@lowepower.com        //Maybe switch over to BTB incorrect.
41212391Sjason@lowepower.com        toIEW->btbMissed = head_inst->btbMiss();
41312391Sjason@lowepower.com        toIEW->target = head_inst->nextPC;
41412391Sjason@lowepower.com        //Maybe also include global history information.
41512391Sjason@lowepower.com        //This simple version will have no branch prediction however.
41612391Sjason@lowepower.com#endif
41712391Sjason@lowepower.com
41812391Sjason@lowepower.com        ++commitCommittedBranches;
41912391Sjason@lowepower.com    }
42012391Sjason@lowepower.com
42112391Sjason@lowepower.com#if 0
42212391Sjason@lowepower.com    // Explicit communication back to the LDSTQ that a load has been committed
42312391Sjason@lowepower.com    // and can be removed from the LDSTQ.  Stores don't need this because
42412391Sjason@lowepower.com    // the LDSTQ will already have been told that a store has reached the head
42512391Sjason@lowepower.com    // of the ROB.  Consider including communication if it's a store as well
42612391Sjason@lowepower.com    // to keep things orthagonal.
42712391Sjason@lowepower.com    if (head_inst->isMemRef()) {
42812391Sjason@lowepower.com        ++commitCommittedMemRefs;
42912391Sjason@lowepower.com        if (head_inst->isLoad()) {
43012391Sjason@lowepower.com            toIEW->commitInfo.commitIsLoad = true;
43112391Sjason@lowepower.com            ++commitCommittedLoads;
43212391Sjason@lowepower.com        }
43312391Sjason@lowepower.com    }
43412391Sjason@lowepower.com#endif
43512391Sjason@lowepower.com
43612391Sjason@lowepower.com    // Now that the instruction is going to be committed, finalize its
43712391Sjason@lowepower.com    // trace data.
43812391Sjason@lowepower.com    if (head_inst->traceData) {
43912391Sjason@lowepower.com        head_inst->traceData->finalize();
44012391Sjason@lowepower.com    }
44112391Sjason@lowepower.com
44212391Sjason@lowepower.com    //Finally clear the head ROB entry.
44312391Sjason@lowepower.com    rob->retireHead();
44412391Sjason@lowepower.com
44512391Sjason@lowepower.com    // Return true to indicate that we have committed an instruction.
44612391Sjason@lowepower.com    return true;
44712391Sjason@lowepower.com}
44812391Sjason@lowepower.com
44912391Sjason@lowepower.comtemplate <class Impl>
45012391Sjason@lowepower.comvoid
45112391Sjason@lowepower.comSimpleCommit<Impl>::getInsts()
45212391Sjason@lowepower.com{
45312391Sjason@lowepower.com    //////////////////////////////////////
45412391Sjason@lowepower.com    // Handle ROB functions
45512391Sjason@lowepower.com    //////////////////////////////////////
45612391Sjason@lowepower.com
45712391Sjason@lowepower.com    // Read any issued instructions and place them into the ROB.  Do this
45812391Sjason@lowepower.com    // prior to squashing to avoid having instructions in the ROB that
45912391Sjason@lowepower.com    // don't get squashed properly.
460    int insts_to_process = min((int)renameWidth, fromRename->size);
461
462    for (int inst_num = 0;
463         inst_num < insts_to_process;
464         ++inst_num)
465    {
466        if (!fromRename->insts[inst_num]->isSquashed()) {
467            DPRINTF(Commit, "Commit: Inserting PC %#x into ROB.\n",
468                    fromRename->insts[inst_num]->readPC());
469            rob->insertInst(fromRename->insts[inst_num]);
470        } else {
471            DPRINTF(Commit, "Commit: Instruction %i PC %#x was "
472                    "squashed, skipping.\n",
473                    fromRename->insts[inst_num]->seqNum,
474                    fromRename->insts[inst_num]->readPC());
475        }
476    }
477}
478
479template <class Impl>
480void
481SimpleCommit<Impl>::markCompletedInsts()
482{
483    // Grab completed insts out of the IEW instruction queue, and mark
484    // instructions completed within the ROB.
485    for (int inst_num = 0;
486         inst_num < fromIEW->size && fromIEW->insts[inst_num];
487         ++inst_num)
488    {
489        DPRINTF(Commit, "Commit: Marking PC %#x, SN %i ready within ROB.\n",
490                fromIEW->insts[inst_num]->readPC(),
491                fromIEW->insts[inst_num]->seqNum);
492
493        // Mark the instruction as ready to commit.
494        fromIEW->insts[inst_num]->setCanCommit();
495    }
496}
497
498template <class Impl>
499uint64_t
500SimpleCommit<Impl>::readCommitPC()
501{
502    return rob->readHeadPC();
503}
504
505#endif // __COMMIT_IMPL_HH__
506