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 ¶ms) 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