rob_impl.hh revision 1689
112634Sodanrc@yahoo.com.br/* 212634Sodanrc@yahoo.com.br * Copyright (c) 2004-2005 The Regents of The University of Michigan 312634Sodanrc@yahoo.com.br * All rights reserved. 412634Sodanrc@yahoo.com.br * 512634Sodanrc@yahoo.com.br * Redistribution and use in source and binary forms, with or without 612634Sodanrc@yahoo.com.br * modification, are permitted provided that the following conditions are 712634Sodanrc@yahoo.com.br * met: redistributions of source code must retain the above copyright 812634Sodanrc@yahoo.com.br * notice, this list of conditions and the following disclaimer; 912634Sodanrc@yahoo.com.br * redistributions in binary form must reproduce the above copyright 1012634Sodanrc@yahoo.com.br * notice, this list of conditions and the following disclaimer in the 1112634Sodanrc@yahoo.com.br * documentation and/or other materials provided with the distribution; 1212634Sodanrc@yahoo.com.br * neither the name of the copyright holders nor the names of its 1312634Sodanrc@yahoo.com.br * contributors may be used to endorse or promote products derived from 1412634Sodanrc@yahoo.com.br * this software without specific prior written permission. 1512634Sodanrc@yahoo.com.br * 1612634Sodanrc@yahoo.com.br * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1712634Sodanrc@yahoo.com.br * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1812634Sodanrc@yahoo.com.br * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1912634Sodanrc@yahoo.com.br * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2012634Sodanrc@yahoo.com.br * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2112634Sodanrc@yahoo.com.br * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2212634Sodanrc@yahoo.com.br * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2312634Sodanrc@yahoo.com.br * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2412634Sodanrc@yahoo.com.br * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2512634Sodanrc@yahoo.com.br * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2612634Sodanrc@yahoo.com.br * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2712634Sodanrc@yahoo.com.br */ 2812634Sodanrc@yahoo.com.br 2912634Sodanrc@yahoo.com.br#ifndef __CPU_BETA_CPU_ROB_IMPL_HH__ 3012634Sodanrc@yahoo.com.br#define __CPU_BETA_CPU_ROB_IMPL_HH__ 3112634Sodanrc@yahoo.com.br 3212634Sodanrc@yahoo.com.br#include "cpu/beta_cpu/rob.hh" 3312634Sodanrc@yahoo.com.br 3412684Sodanrc@yahoo.com.brtemplate <class Impl> 3512634Sodanrc@yahoo.com.brROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth) 3612634Sodanrc@yahoo.com.br : numEntries(_numEntries), 3712634Sodanrc@yahoo.com.br squashWidth(_squashWidth), 3812634Sodanrc@yahoo.com.br numInstsInROB(0), 3912634Sodanrc@yahoo.com.br squashedSeqNum(0) 4012634Sodanrc@yahoo.com.br{ 4112634Sodanrc@yahoo.com.br doneSquashing = true; 4212634Sodanrc@yahoo.com.br} 4312634Sodanrc@yahoo.com.br 4412684Sodanrc@yahoo.com.brtemplate <class Impl> 4512684Sodanrc@yahoo.com.brvoid 4612634Sodanrc@yahoo.com.brROB<Impl>::setCPU(FullCPU *cpu_ptr) 4712634Sodanrc@yahoo.com.br{ 4812727Snikos.nikoleris@arm.com cpu = cpu_ptr; 4912727Snikos.nikoleris@arm.com 5012634Sodanrc@yahoo.com.br // Set the tail to the beginning of the CPU instruction list so that 5112634Sodanrc@yahoo.com.br // upon the first instruction being inserted into the ROB, the tail 5212634Sodanrc@yahoo.com.br // iterator can simply be incremented. 5312634Sodanrc@yahoo.com.br tail = cpu->instList.begin(); 5412634Sodanrc@yahoo.com.br 5512634Sodanrc@yahoo.com.br // Set the squash iterator to the end of the instruction list. 5612684Sodanrc@yahoo.com.br squashIt = cpu->instList.end(); 5712634Sodanrc@yahoo.com.br} 5812634Sodanrc@yahoo.com.br 5912634Sodanrc@yahoo.com.brtemplate <class Impl> 6012634Sodanrc@yahoo.com.brint 6112634Sodanrc@yahoo.com.brROB<Impl>::countInsts() 6212634Sodanrc@yahoo.com.br{ 6312634Sodanrc@yahoo.com.br // Start at 1; if the tail matches cpu->instList.begin(), then there is 6412634Sodanrc@yahoo.com.br // one inst in the ROB. 6512634Sodanrc@yahoo.com.br int return_val = 1; 6612634Sodanrc@yahoo.com.br 6712634Sodanrc@yahoo.com.br // There are quite a few special cases. Do not use this function other 6812634Sodanrc@yahoo.com.br // than for debugging purposes. 6912634Sodanrc@yahoo.com.br if (cpu->instList.begin() == cpu->instList.end()) { 7012634Sodanrc@yahoo.com.br // In this case there are no instructions in the list. The ROB 7112634Sodanrc@yahoo.com.br // must be empty. 7212634Sodanrc@yahoo.com.br return 0; 7312634Sodanrc@yahoo.com.br } else if (tail == cpu->instList.end()) { 7412634Sodanrc@yahoo.com.br // In this case, the tail is not yet pointing to anything valid. 7512684Sodanrc@yahoo.com.br // The ROB must be empty. 7612684Sodanrc@yahoo.com.br return 0; 7712634Sodanrc@yahoo.com.br } 7812634Sodanrc@yahoo.com.br 7912684Sodanrc@yahoo.com.br // Iterate through the ROB from the head to the tail, counting the 8012634Sodanrc@yahoo.com.br // entries. 8112684Sodanrc@yahoo.com.br for (InstIt_t i = cpu->instList.begin(); i != tail; ++i) 8212684Sodanrc@yahoo.com.br { 8312634Sodanrc@yahoo.com.br assert(i != cpu->instList.end()); 8412634Sodanrc@yahoo.com.br ++return_val; 8512684Sodanrc@yahoo.com.br } 86 87 return return_val; 88 89 // Because the head won't be tracked properly until the ROB gets the 90 // first instruction, and any time that the ROB is empty and has not 91 // yet gotten the instruction, this function doesn't work. 92// return numInstsInROB; 93} 94 95template <class Impl> 96void 97ROB<Impl>::insertInst(DynInstPtr &inst) 98{ 99 // Make sure we have the right number of instructions. 100 assert(numInstsInROB == countInsts()); 101 // Make sure the instruction is valid. 102 assert(inst); 103 104 DPRINTF(ROB, "ROB: Adding inst PC %#x to the ROB.\n", inst->readPC()); 105 106 // If the ROB is full then exit. 107 assert(numInstsInROB != numEntries); 108 109 ++numInstsInROB; 110 111 // Increment the tail iterator, moving it one instruction back. 112 // There is a special case if the ROB was empty prior to this insertion, 113 // in which case the tail will be pointing at instList.end(). If that 114 // happens, then reset the tail to the beginning of the list. 115 if (tail != cpu->instList.end()) { 116 ++tail; 117 } else { 118 tail = cpu->instList.begin(); 119 } 120 121 // Make sure the tail iterator is actually pointing at the instruction 122 // added. 123 assert((*tail) == inst); 124 125 DPRINTF(ROB, "ROB: Now has %d instructions.\n", numInstsInROB); 126 127} 128 129// Whatever calls this function needs to ensure that it properly frees up 130// registers prior to this function. 131template <class Impl> 132void 133ROB<Impl>::retireHead() 134{ 135 assert(numInstsInROB == countInsts()); 136 assert(numInstsInROB > 0); 137 138 // Get the head ROB instruction. 139 DynInstPtr head_inst = cpu->instList.front(); 140 141 // Make certain this can retire. 142 assert(head_inst->readyToCommit()); 143 144 DPRINTF(ROB, "ROB: Retiring head instruction of the ROB, " 145 "instruction PC %#x, seq num %i\n", head_inst->readPC(), 146 head_inst->seqNum); 147 148 // Keep track of how many instructions are in the ROB. 149 --numInstsInROB; 150 151 // Tell CPU to remove the instruction from the list of instructions. 152 // A special case is needed if the instruction being retired is the 153 // only instruction in the ROB; otherwise the tail iterator will become 154 // invalidated. 155 cpu->removeFrontInst(head_inst); 156 157 if (numInstsInROB == 0) { 158 tail = cpu->instList.end(); 159 } 160} 161 162template <class Impl> 163bool 164ROB<Impl>::isHeadReady() 165{ 166 if (numInstsInROB != 0) { 167 return cpu->instList.front()->readyToCommit(); 168 } 169 170 return false; 171} 172 173template <class Impl> 174unsigned 175ROB<Impl>::numFreeEntries() 176{ 177 assert(numInstsInROB == countInsts()); 178 179 return numEntries - numInstsInROB; 180} 181 182template <class Impl> 183void 184ROB<Impl>::doSquash() 185{ 186 DPRINTF(ROB, "ROB: Squashing instructions.\n"); 187 188 assert(squashIt != cpu->instList.end()); 189 190 for (int numSquashed = 0; 191 numSquashed < squashWidth && (*squashIt)->seqNum != squashedSeqNum; 192 ++numSquashed) 193 { 194 // Ensure that the instruction is younger. 195 assert((*squashIt)->seqNum > squashedSeqNum); 196 197 DPRINTF(ROB, "ROB: Squashing instruction PC %#x, seq num %i.\n", 198 (*squashIt)->readPC(), (*squashIt)->seqNum); 199 200 // Mark the instruction as squashed, and ready to commit so that 201 // it can drain out of the pipeline. 202 (*squashIt)->setSquashed(); 203 204 (*squashIt)->setCanCommit(); 205 206 // Special case for when squashing due to a syscall. It's possible 207 // that the squash happened after the head instruction was already 208 // committed, meaning that (*squashIt)->seqNum != squashedSeqNum 209 // will never be false. Normally the squash would never be able 210 // to go past the head of the ROB; in this case it might, so it 211 // must be handled otherwise it will segfault. 212#ifndef FULL_SYSTEM 213 if (squashIt == cpu->instList.begin()) { 214 DPRINTF(ROB, "ROB: Reached head of instruction list while " 215 "squashing.\n"); 216 217 squashIt = cpu->instList.end(); 218 219 doneSquashing = true; 220 221 return; 222 } 223#endif 224 225 // Move the tail iterator to the next instruction. 226 squashIt--; 227 } 228 229 230 // Check if ROB is done squashing. 231 if ((*squashIt)->seqNum == squashedSeqNum) { 232 DPRINTF(ROB, "ROB: Done squashing instructions.\n"); 233 234 squashIt = cpu->instList.end(); 235 236 doneSquashing = true; 237 } 238} 239 240template <class Impl> 241void 242ROB<Impl>::squash(InstSeqNum squash_num) 243{ 244 DPRINTF(ROB, "ROB: Starting to squash within the ROB.\n"); 245 doneSquashing = false; 246 247 squashedSeqNum = squash_num; 248 249 assert(tail != cpu->instList.end()); 250 251 squashIt = tail; 252 253 doSquash(); 254} 255 256template <class Impl> 257uint64_t 258ROB<Impl>::readHeadPC() 259{ 260 assert(numInstsInROB == countInsts()); 261 262 DynInstPtr head_inst = cpu->instList.front(); 263 264 return head_inst->readPC(); 265} 266 267template <class Impl> 268uint64_t 269ROB<Impl>::readHeadNextPC() 270{ 271 assert(numInstsInROB == countInsts()); 272 273 DynInstPtr head_inst = cpu->instList.front(); 274 275 return head_inst->readNextPC(); 276} 277 278template <class Impl> 279InstSeqNum 280ROB<Impl>::readHeadSeqNum() 281{ 282 // Return the last sequence number that has not been squashed. Other 283 // stages can use it to squash any instructions younger than the current 284 // tail. 285 DynInstPtr head_inst = cpu->instList.front(); 286 287 return head_inst->seqNum; 288} 289 290template <class Impl> 291uint64_t 292ROB<Impl>::readTailPC() 293{ 294 assert(numInstsInROB == countInsts()); 295 296 assert(tail != cpu->instList.end()); 297 298 return (*tail)->readPC(); 299} 300 301template <class Impl> 302InstSeqNum 303ROB<Impl>::readTailSeqNum() 304{ 305 // Return the last sequence number that has not been squashed. Other 306 // stages can use it to squash any instructions younger than the current 307 // tail. 308 return (*tail)->seqNum; 309} 310 311#endif // __CPU_BETA_CPU_ROB_IMPL_HH__ 312