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