rob_impl.hh revision 1681
113219Sodanrc@yahoo.com.br#ifndef __CPU_BETA_CPU_ROB_IMPL_HH__ 213219Sodanrc@yahoo.com.br#define __CPU_BETA_CPU_ROB_IMPL_HH__ 313219Sodanrc@yahoo.com.br 413219Sodanrc@yahoo.com.br#include "cpu/beta_cpu/rob.hh" 513219Sodanrc@yahoo.com.br 613219Sodanrc@yahoo.com.brtemplate <class Impl> 713219Sodanrc@yahoo.com.brROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth) 813219Sodanrc@yahoo.com.br : numEntries(_numEntries), 913219Sodanrc@yahoo.com.br squashWidth(_squashWidth), 1013219Sodanrc@yahoo.com.br numInstsInROB(0), 1113219Sodanrc@yahoo.com.br squashedSeqNum(0) 1213219Sodanrc@yahoo.com.br{ 1313219Sodanrc@yahoo.com.br doneSquashing = true; 1413219Sodanrc@yahoo.com.br} 1513219Sodanrc@yahoo.com.br 1613219Sodanrc@yahoo.com.brtemplate <class Impl> 1713219Sodanrc@yahoo.com.brvoid 1813219Sodanrc@yahoo.com.brROB<Impl>::setCPU(FullCPU *cpu_ptr) 1913219Sodanrc@yahoo.com.br{ 2013219Sodanrc@yahoo.com.br cpu = cpu_ptr; 2113219Sodanrc@yahoo.com.br 2213219Sodanrc@yahoo.com.br // Set the tail to the beginning of the CPU instruction list so that 2313219Sodanrc@yahoo.com.br // upon the first instruction being inserted into the ROB, the tail 2413219Sodanrc@yahoo.com.br // iterator can simply be incremented. 2513219Sodanrc@yahoo.com.br tail = cpu->instList.begin(); 2613219Sodanrc@yahoo.com.br 2713219Sodanrc@yahoo.com.br // Set the squash iterator to the end of the instruction list. 2813219Sodanrc@yahoo.com.br squashIt = cpu->instList.end(); 2913219Sodanrc@yahoo.com.br} 3013219Sodanrc@yahoo.com.br 3113219Sodanrc@yahoo.com.brtemplate <class Impl> 3213219Sodanrc@yahoo.com.brint 3313219Sodanrc@yahoo.com.brROB<Impl>::countInsts() 3413219Sodanrc@yahoo.com.br{ 3513219Sodanrc@yahoo.com.br // Start at 1; if the tail matches cpu->instList.begin(), then there is 3613219Sodanrc@yahoo.com.br // one inst in the ROB. 3713219Sodanrc@yahoo.com.br int return_val = 1; 3813219Sodanrc@yahoo.com.br 3913219Sodanrc@yahoo.com.br // There are quite a few special cases. Do not use this function other 4013219Sodanrc@yahoo.com.br // than for debugging purposes. 4113219Sodanrc@yahoo.com.br if (cpu->instList.begin() == cpu->instList.end()) { 4213219Sodanrc@yahoo.com.br // In this case there are no instructions in the list. The ROB 4313219Sodanrc@yahoo.com.br // must be empty. 4413219Sodanrc@yahoo.com.br return 0; 4513219Sodanrc@yahoo.com.br } else if (tail == cpu->instList.end()) { 4613219Sodanrc@yahoo.com.br // In this case, the tail is not yet pointing to anything valid. 4713219Sodanrc@yahoo.com.br // The ROB must be empty. 4813219Sodanrc@yahoo.com.br return 0; 4913219Sodanrc@yahoo.com.br } 5013219Sodanrc@yahoo.com.br 5113219Sodanrc@yahoo.com.br // Iterate through the ROB from the head to the tail, counting the 5213219Sodanrc@yahoo.com.br // entries. 5313219Sodanrc@yahoo.com.br for (InstIt_t i = cpu->instList.begin(); i != tail; ++i) 5413219Sodanrc@yahoo.com.br { 5513219Sodanrc@yahoo.com.br assert(i != cpu->instList.end()); 5613219Sodanrc@yahoo.com.br ++return_val; 5713219Sodanrc@yahoo.com.br } 5813219Sodanrc@yahoo.com.br 5913219Sodanrc@yahoo.com.br return return_val; 6013219Sodanrc@yahoo.com.br 6113219Sodanrc@yahoo.com.br // Because the head won't be tracked properly until the ROB gets the 6213219Sodanrc@yahoo.com.br // first instruction, and any time that the ROB is empty and has not 6313219Sodanrc@yahoo.com.br // yet gotten the instruction, this function doesn't work. 6413219Sodanrc@yahoo.com.br// return numInstsInROB; 6513219Sodanrc@yahoo.com.br} 6613219Sodanrc@yahoo.com.br 6713219Sodanrc@yahoo.com.brtemplate <class Impl> 6813219Sodanrc@yahoo.com.brvoid 6913219Sodanrc@yahoo.com.brROB<Impl>::insertInst(DynInstPtr &inst) 7013219Sodanrc@yahoo.com.br{ 7113219Sodanrc@yahoo.com.br // Make sure we have the right number of instructions. 7213219Sodanrc@yahoo.com.br assert(numInstsInROB == countInsts()); 7313219Sodanrc@yahoo.com.br // Make sure the instruction is valid. 7413219Sodanrc@yahoo.com.br assert(inst); 7513219Sodanrc@yahoo.com.br 7613219Sodanrc@yahoo.com.br DPRINTF(ROB, "ROB: Adding inst PC %#x to the ROB.\n", inst->readPC()); 7713219Sodanrc@yahoo.com.br 7813219Sodanrc@yahoo.com.br // If the ROB is full then exit. 7913219Sodanrc@yahoo.com.br assert(numInstsInROB != numEntries); 8013219Sodanrc@yahoo.com.br 8113219Sodanrc@yahoo.com.br ++numInstsInROB; 8213219Sodanrc@yahoo.com.br 8313219Sodanrc@yahoo.com.br // Increment the tail iterator, moving it one instruction back. 8413219Sodanrc@yahoo.com.br // There is a special case if the ROB was empty prior to this insertion, 8513219Sodanrc@yahoo.com.br // in which case the tail will be pointing at instList.end(). If that 8613219Sodanrc@yahoo.com.br // happens, then reset the tail to the beginning of the list. 8713219Sodanrc@yahoo.com.br if (tail != cpu->instList.end()) { 8813219Sodanrc@yahoo.com.br ++tail; 8913219Sodanrc@yahoo.com.br } else { 9013219Sodanrc@yahoo.com.br tail = cpu->instList.begin(); 9113219Sodanrc@yahoo.com.br } 9213219Sodanrc@yahoo.com.br 9313219Sodanrc@yahoo.com.br // Make sure the tail iterator is actually pointing at the instruction 9413219Sodanrc@yahoo.com.br // added. 9513219Sodanrc@yahoo.com.br assert((*tail) == inst); 9613219Sodanrc@yahoo.com.br 9713219Sodanrc@yahoo.com.br DPRINTF(ROB, "ROB: Now has %d instructions.\n", numInstsInROB); 9813219Sodanrc@yahoo.com.br 9913219Sodanrc@yahoo.com.br} 10013219Sodanrc@yahoo.com.br 10113219Sodanrc@yahoo.com.br// Whatever calls this function needs to ensure that it properly frees up 10213219Sodanrc@yahoo.com.br// registers prior to this function. 10313219Sodanrc@yahoo.com.brtemplate <class Impl> 10413219Sodanrc@yahoo.com.brvoid 10513219Sodanrc@yahoo.com.brROB<Impl>::retireHead() 10613219Sodanrc@yahoo.com.br{ 10713219Sodanrc@yahoo.com.br assert(numInstsInROB == countInsts()); 10813219Sodanrc@yahoo.com.br assert(numInstsInROB > 0); 10913219Sodanrc@yahoo.com.br 11013219Sodanrc@yahoo.com.br // Get the head ROB instruction. 11113219Sodanrc@yahoo.com.br DynInstPtr head_inst = cpu->instList.front(); 11213219Sodanrc@yahoo.com.br 11313219Sodanrc@yahoo.com.br // Make certain this can retire. 11413219Sodanrc@yahoo.com.br assert(head_inst->readyToCommit()); 11513219Sodanrc@yahoo.com.br 11613219Sodanrc@yahoo.com.br DPRINTF(ROB, "ROB: Retiring head instruction of the ROB, " 11713219Sodanrc@yahoo.com.br "instruction PC %#x, seq num %i\n", head_inst->readPC(), 11813219Sodanrc@yahoo.com.br head_inst->seqNum); 11913219Sodanrc@yahoo.com.br 12013219Sodanrc@yahoo.com.br // Keep track of how many instructions are in the ROB. 12113219Sodanrc@yahoo.com.br --numInstsInROB; 12213219Sodanrc@yahoo.com.br 12313219Sodanrc@yahoo.com.br // Tell CPU to remove the instruction from the list of instructions. 12413219Sodanrc@yahoo.com.br // A special case is needed if the instruction being retired is the 12513219Sodanrc@yahoo.com.br // only instruction in the ROB; otherwise the tail iterator will become 12613219Sodanrc@yahoo.com.br // invalidated. 12713219Sodanrc@yahoo.com.br cpu->removeFrontInst(head_inst); 12813219Sodanrc@yahoo.com.br 12913219Sodanrc@yahoo.com.br if (numInstsInROB == 0) { 13013219Sodanrc@yahoo.com.br tail = cpu->instList.end(); 13113219Sodanrc@yahoo.com.br } 13213219Sodanrc@yahoo.com.br} 13313219Sodanrc@yahoo.com.br 13413219Sodanrc@yahoo.com.brtemplate <class Impl> 13513219Sodanrc@yahoo.com.brbool 13613219Sodanrc@yahoo.com.brROB<Impl>::isHeadReady() 13713219Sodanrc@yahoo.com.br{ 13813219Sodanrc@yahoo.com.br if (numInstsInROB != 0) { 13913219Sodanrc@yahoo.com.br return cpu->instList.front()->readyToCommit(); 14013219Sodanrc@yahoo.com.br } 14113219Sodanrc@yahoo.com.br 14213219Sodanrc@yahoo.com.br return false; 14313219Sodanrc@yahoo.com.br} 14413219Sodanrc@yahoo.com.br 14513219Sodanrc@yahoo.com.brtemplate <class Impl> 14613219Sodanrc@yahoo.com.brunsigned 14713219Sodanrc@yahoo.com.brROB<Impl>::numFreeEntries() 14813219Sodanrc@yahoo.com.br{ 14913219Sodanrc@yahoo.com.br assert(numInstsInROB == countInsts()); 15013219Sodanrc@yahoo.com.br 15113219Sodanrc@yahoo.com.br return numEntries - numInstsInROB; 15213219Sodanrc@yahoo.com.br} 15313219Sodanrc@yahoo.com.br 15413219Sodanrc@yahoo.com.brtemplate <class Impl> 15513219Sodanrc@yahoo.com.brvoid 15613219Sodanrc@yahoo.com.brROB<Impl>::doSquash() 15713219Sodanrc@yahoo.com.br{ 15813219Sodanrc@yahoo.com.br DPRINTF(ROB, "ROB: Squashing instructions.\n"); 15913219Sodanrc@yahoo.com.br 16013219Sodanrc@yahoo.com.br assert(squashIt != cpu->instList.end()); 16113219Sodanrc@yahoo.com.br 16213219Sodanrc@yahoo.com.br for (int numSquashed = 0; 16313219Sodanrc@yahoo.com.br numSquashed < squashWidth && (*squashIt)->seqNum != squashedSeqNum; 16413219Sodanrc@yahoo.com.br ++numSquashed) 16513219Sodanrc@yahoo.com.br { 16613219Sodanrc@yahoo.com.br // Ensure that the instruction is younger. 16713219Sodanrc@yahoo.com.br assert((*squashIt)->seqNum > squashedSeqNum); 16813219Sodanrc@yahoo.com.br 16913219Sodanrc@yahoo.com.br DPRINTF(ROB, "ROB: Squashing instruction PC %#x, seq num %i.\n", 17013219Sodanrc@yahoo.com.br (*squashIt)->readPC(), (*squashIt)->seqNum); 17113219Sodanrc@yahoo.com.br 17213219Sodanrc@yahoo.com.br // Mark the instruction as squashed, and ready to commit so that 17313219Sodanrc@yahoo.com.br // it can drain out of the pipeline. 17413219Sodanrc@yahoo.com.br (*squashIt)->setSquashed(); 17513219Sodanrc@yahoo.com.br 17613219Sodanrc@yahoo.com.br (*squashIt)->setCanCommit(); 17713219Sodanrc@yahoo.com.br 17813219Sodanrc@yahoo.com.br // Special case for when squashing due to a syscall. It's possible 17913219Sodanrc@yahoo.com.br // that the squash happened after the head instruction was already 18013219Sodanrc@yahoo.com.br // committed, meaning that (*squashIt)->seqNum != squashedSeqNum 18113219Sodanrc@yahoo.com.br // will never be false. Normally the squash would never be able 18213219Sodanrc@yahoo.com.br // to go past the head of the ROB; in this case it might, so it 18313219Sodanrc@yahoo.com.br // must be handled otherwise it will segfault. 18413219Sodanrc@yahoo.com.br#ifndef FULL_SYSTEM 18513219Sodanrc@yahoo.com.br if (squashIt == cpu->instList.begin()) { 18613219Sodanrc@yahoo.com.br DPRINTF(ROB, "ROB: Reached head of instruction list while " 18713219Sodanrc@yahoo.com.br "squashing.\n"); 18813219Sodanrc@yahoo.com.br 18913219Sodanrc@yahoo.com.br squashIt = cpu->instList.end(); 19013219Sodanrc@yahoo.com.br 19113219Sodanrc@yahoo.com.br doneSquashing = true; 19213219Sodanrc@yahoo.com.br 19313219Sodanrc@yahoo.com.br return; 19413219Sodanrc@yahoo.com.br } 19513219Sodanrc@yahoo.com.br#endif 19613219Sodanrc@yahoo.com.br 19713219Sodanrc@yahoo.com.br // Move the tail iterator to the next instruction. 19813219Sodanrc@yahoo.com.br squashIt--; 19913219Sodanrc@yahoo.com.br } 20013219Sodanrc@yahoo.com.br 20113219Sodanrc@yahoo.com.br 20213219Sodanrc@yahoo.com.br // Check if ROB is done squashing. 20313219Sodanrc@yahoo.com.br if ((*squashIt)->seqNum == squashedSeqNum) { 20413219Sodanrc@yahoo.com.br DPRINTF(ROB, "ROB: Done squashing instructions.\n"); 20513219Sodanrc@yahoo.com.br 20613219Sodanrc@yahoo.com.br squashIt = cpu->instList.end(); 20713219Sodanrc@yahoo.com.br 20813219Sodanrc@yahoo.com.br doneSquashing = true; 20913219Sodanrc@yahoo.com.br } 21013219Sodanrc@yahoo.com.br} 21113219Sodanrc@yahoo.com.br 21213219Sodanrc@yahoo.com.brtemplate <class Impl> 21313219Sodanrc@yahoo.com.brvoid 21413219Sodanrc@yahoo.com.brROB<Impl>::squash(InstSeqNum squash_num) 21513219Sodanrc@yahoo.com.br{ 21613219Sodanrc@yahoo.com.br DPRINTF(ROB, "ROB: Starting to squash within the ROB.\n"); 21713219Sodanrc@yahoo.com.br doneSquashing = false; 21813219Sodanrc@yahoo.com.br 21913219Sodanrc@yahoo.com.br squashedSeqNum = squash_num; 22013219Sodanrc@yahoo.com.br 22113219Sodanrc@yahoo.com.br assert(tail != cpu->instList.end()); 22213219Sodanrc@yahoo.com.br 22313219Sodanrc@yahoo.com.br squashIt = tail; 22413219Sodanrc@yahoo.com.br 22513219Sodanrc@yahoo.com.br doSquash(); 22613219Sodanrc@yahoo.com.br} 227 228template <class Impl> 229uint64_t 230ROB<Impl>::readHeadPC() 231{ 232 assert(numInstsInROB == countInsts()); 233 234 DynInstPtr head_inst = cpu->instList.front(); 235 236 return head_inst->readPC(); 237} 238 239template <class Impl> 240uint64_t 241ROB<Impl>::readHeadNextPC() 242{ 243 assert(numInstsInROB == countInsts()); 244 245 DynInstPtr head_inst = cpu->instList.front(); 246 247 return head_inst->readNextPC(); 248} 249 250template <class Impl> 251InstSeqNum 252ROB<Impl>::readHeadSeqNum() 253{ 254 // Return the last sequence number that has not been squashed. Other 255 // stages can use it to squash any instructions younger than the current 256 // tail. 257 DynInstPtr head_inst = cpu->instList.front(); 258 259 return head_inst->seqNum; 260} 261 262template <class Impl> 263uint64_t 264ROB<Impl>::readTailPC() 265{ 266 assert(numInstsInROB == countInsts()); 267 268 assert(tail != cpu->instList.end()); 269 270 return (*tail)->readPC(); 271} 272 273template <class Impl> 274InstSeqNum 275ROB<Impl>::readTailSeqNum() 276{ 277 // Return the last sequence number that has not been squashed. Other 278 // stages can use it to squash any instructions younger than the current 279 // tail. 280 return (*tail)->seqNum; 281} 282 283#endif // __CPU_BETA_CPU_ROB_IMPL_HH__ 284