rob_impl.hh revision 1060
1#ifndef __ROB_IMPL_HH__ 2#define __ROB_IMPL_HH__ 3 4#include "cpu/beta_cpu/rob.hh" 5 6template<class Impl> 7ROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth) 8 : numEntries(_numEntries), 9 squashWidth(_squashWidth), 10 numInstsInROB(0), 11 squashedSeqNum(0) 12{ 13 doneSquashing = true; 14} 15 16template<class Impl> 17void 18ROB<Impl>::setCPU(FullCPU *cpu_ptr) 19{ 20 cpu = cpu_ptr; 21 22 tail = cpu->instList.begin(); 23 24 squashIt = cpu->instList.end(); 25} 26 27template<class Impl> 28int 29ROB<Impl>::countInsts() 30{ 31/* 32 int return_val = 0; 33 34 // Iterate through the ROB from the head to the tail, counting the 35 // entries. 36 for (InstIt i = cpu->instList.begin(); i != tail; i++) 37 { 38 assert(i != cpu->instList.end()); 39 return_val++; 40 } 41 42 return return_val; 43*/ 44 // Because the head won't be tracked properly until the ROB gets the 45 // first instruction, and any time that the ROB is empty and has not 46 // yet gotten the instruction, this function doesn't work. 47 return numInstsInROB; 48} 49 50template<class Impl> 51void 52ROB<Impl>::insertInst(DynInst *inst) 53{ 54 // Make sure we have the right number of instructions. 55 assert(numInstsInROB == countInsts()); 56 // Make sure the instruction is valid. 57 assert(inst); 58 59 DPRINTF(ROB, "ROB: Adding inst PC %#x to the ROB.\n", inst->readPC()); 60 61 // If the ROB is full then exit. 62 assert(numInstsInROB != numEntries); 63 64 ++numInstsInROB; 65 66 // Increment the tail iterator, moving it one instruction back. 67 // There is a special case if the ROB was empty prior to this insertion, 68 // in which case the tail will be pointing at instList.end(). If that 69 // happens, then reset the tail to the beginning of the list. 70 if (tail != cpu->instList.end()) { 71 tail++; 72 } else { 73 tail = cpu->instList.begin(); 74 } 75 76 // Make sure the tail iterator is actually pointing at the instruction 77 // added. 78 assert((*tail) == inst); 79 80 DPRINTF(ROB, "ROB: Now has %d instructions.\n", numInstsInROB); 81 82} 83 84// Whatever calls this function needs to ensure that it properly frees up 85// registers prior to this function. 86template<class Impl> 87void 88ROB<Impl>::retireHead() 89{ 90 assert(numInstsInROB == countInsts()); 91 92 DynInst *head_inst; 93 94 // Get the head ROB instruction. 95 head_inst = cpu->instList.front(); 96 97 // Make certain this can retire. 98 assert(head_inst->readyToCommit()); 99 100 DPRINTF(ROB, "ROB: Retiring head instruction of the ROB, " 101 "instruction PC %#x, seq num %i\n", head_inst->readPC(), 102 head_inst->seqNum); 103 104 // Keep track of how many instructions are in the ROB. 105 --numInstsInROB; 106 107 // Tell CPU to remove the instruction from the list of instructions. 108 // A special case is needed if the instruction being retired is the 109 // only instruction in the ROB; otherwise the tail iterator will become 110 // invalidated. 111 if (tail == cpu->instList.begin()) { 112 cpu->removeFrontInst(head_inst); 113 tail = cpu->instList.end(); 114 } else { 115 cpu->removeFrontInst(head_inst); 116 } 117} 118 119template<class Impl> 120bool 121ROB<Impl>::isHeadReady() 122{ 123 if (numInstsInROB != 0) { 124 DynInst *head_inst = cpu->instList.front(); 125 126 return head_inst->readyToCommit(); 127 } 128 129 return false; 130} 131 132template<class Impl> 133unsigned 134ROB<Impl>::numFreeEntries() 135{ 136 assert(numInstsInROB == countInsts()); 137 138 return numEntries - numInstsInROB; 139} 140 141template<class Impl> 142void 143ROB<Impl>::doSquash() 144{ 145 DPRINTF(ROB, "ROB: Squashing instructions.\n"); 146 147 assert(squashIt != cpu->instList.end()); 148 149 for (int numSquashed = 0; 150 numSquashed < squashWidth && (*squashIt)->seqNum != squashedSeqNum; 151 ++numSquashed) 152 { 153 // Ensure that the instruction is younger. 154 assert((*squashIt)->seqNum > squashedSeqNum); 155 156 DPRINTF(ROB, "ROB: Squashing instruction PC %#x, seq num %i.\n", 157 (*squashIt)->readPC(), (*squashIt)->seqNum); 158 159 // Mark the instruction as squashed, and ready to commit so that 160 // it can drain out of the pipeline. 161 (*squashIt)->setSquashed(); 162 163 (*squashIt)->setCanCommit(); 164 165#ifndef FULL_SYSTEM 166 if (squashIt == cpu->instList.begin()) { 167 DPRINTF(ROB, "ROB: Reached head of instruction list while " 168 "squashing.\n"); 169 170 squashIt = cpu->instList.end(); 171 172 doneSquashing = true; 173 174 return; 175 } 176#endif 177 178 // Move the tail iterator to the next instruction. 179 squashIt--; 180 } 181 182 183 // Check if ROB is done squashing. 184 if ((*squashIt)->seqNum == squashedSeqNum) { 185 DPRINTF(ROB, "ROB: Done squashing instructions.\n"); 186 187 squashIt = cpu->instList.end(); 188 189 doneSquashing = true; 190 } 191} 192 193template<class Impl> 194void 195ROB<Impl>::squash(InstSeqNum squash_num) 196{ 197 DPRINTF(ROB, "ROB: Starting to squash within the ROB.\n"); 198 doneSquashing = false; 199 200 squashedSeqNum = squash_num; 201 202 assert(tail != cpu->instList.end()); 203 204 squashIt = tail; 205 206 doSquash(); 207} 208 209template<class Impl> 210uint64_t 211ROB<Impl>::readHeadPC() 212{ 213 assert(numInstsInROB == countInsts()); 214 215 DynInst *head_inst = cpu->instList.front(); 216 217 return head_inst->readPC(); 218} 219 220template<class Impl> 221uint64_t 222ROB<Impl>::readHeadNextPC() 223{ 224 assert(numInstsInROB == countInsts()); 225 226 DynInst *head_inst = cpu->instList.front(); 227 228 return head_inst->readNextPC(); 229} 230 231template<class Impl> 232InstSeqNum 233ROB<Impl>::readHeadSeqNum() 234{ 235 // Return the last sequence number that has not been squashed. Other 236 // stages can use it to squash any instructions younger than the current 237 // tail. 238 DynInst *head_inst = cpu->instList.front(); 239 240 return head_inst->seqNum; 241} 242 243template<class Impl> 244uint64_t 245ROB<Impl>::readTailPC() 246{ 247 assert(numInstsInROB == countInsts()); 248 249 assert(tail != cpu->instList.end()); 250 251 return (*tail)->readPC(); 252} 253 254template<class Impl> 255InstSeqNum 256ROB<Impl>::readTailSeqNum() 257{ 258 // Return the last sequence number that has not been squashed. Other 259 // stages can use it to squash any instructions younger than the current 260 // tail. 261 return (*tail)->seqNum; 262} 263 264#endif // __ROB_IMPL_HH__ 265