rob_impl.hh revision 1717
12SN/A/* 211071SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan 311071SN/A * All rights reserved. 411071SN/A * 511071SN/A * Redistribution and use in source and binary forms, with or without 611071SN/A * modification, are permitted provided that the following conditions are 711071SN/A * met: redistributions of source code must retain the above copyright 811071SN/A * notice, this list of conditions and the following disclaimer; 911071SN/A * redistributions in binary form must reproduce the above copyright 1011071SN/A * notice, this list of conditions and the following disclaimer in the 1111071SN/A * documentation and/or other materials provided with the distribution; 1211071SN/A * neither the name of the copyright holders nor the names of its 1311071SN/A * contributors may be used to endorse or promote products derived from 141762SN/A * this software without specific prior written permission. 152SN/A * 162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272SN/A */ 282SN/A 292SN/A#ifndef __CPU_BETA_CPU_ROB_IMPL_HH__ 302SN/A#define __CPU_BETA_CPU_ROB_IMPL_HH__ 312SN/A 322SN/A#include "cpu/o3/rob.hh" 332SN/A 342SN/Atemplate <class Impl> 352SN/AROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth) 362SN/A : numEntries(_numEntries), 372SN/A squashWidth(_squashWidth), 382SN/A numInstsInROB(0), 392665SN/A squashedSeqNum(0) 402665SN/A{ 412665SN/A doneSquashing = true; 422SN/A} 432SN/A 442SN/Atemplate <class Impl> 452SN/Avoid 462SN/AROB<Impl>::setCPU(FullCPU *cpu_ptr) 472SN/A{ 4811263Sandreas.sandberg@arm.com cpu = cpu_ptr; 4911263Sandreas.sandberg@arm.com 50146SN/A // Set the tail to the beginning of the CPU instruction list so that 512SN/A // upon the first instruction being inserted into the ROB, the tail 522SN/A // iterator can simply be incremented. 532SN/A tail = cpu->instList.begin(); 542SN/A 551954SN/A // Set the squash iterator to the end of the instruction list. 56146SN/A squashIt = cpu->instList.end(); 578232SN/A} 588232SN/A 5911263Sandreas.sandberg@arm.comtemplate <class Impl> 6011263Sandreas.sandberg@arm.comint 6111263Sandreas.sandberg@arm.comROB<Impl>::countInsts() 624762SN/A{ 638229SN/A // Start at 1; if the tail matches cpu->instList.begin(), then there is 641078SN/A // one inst in the ROB. 651078SN/A int return_val = 1; 662SN/A 672SN/A // There are quite a few special cases. Do not use this function other 682SN/A // than for debugging purposes. 694981SN/A if (cpu->instList.begin() == cpu->instList.end()) { 704981SN/A // In this case there are no instructions in the list. The ROB 712SN/A // must be empty. 725034SN/A return 0; 735034SN/A } else if (tail == cpu->instList.end()) { 745034SN/A // In this case, the tail is not yet pointing to anything valid. 755034SN/A // The ROB must be empty. 762SN/A return 0; 774981SN/A } 784981SN/A 794981SN/A // Iterate through the ROB from the head to the tail, counting the 802SN/A // entries. 812SN/A for (InstIt_t i = cpu->instList.begin(); i != tail; ++i) 822SN/A { 832SN/A assert(i != cpu->instList.end()); 841435SN/A ++return_val; 851435SN/A } 862SN/A 871435SN/A return return_val; 881435SN/A 892SN/A // Because the head won't be tracked properly until the ROB gets the 902SN/A // first instruction, and any time that the ROB is empty and has not 914981SN/A // yet gotten the instruction, this function doesn't work. 924981SN/A// return numInstsInROB; 934981SN/A} 944981SN/A 954981SN/Atemplate <class Impl> 964981SN/Avoid 974981SN/AROB<Impl>::insertInst(DynInstPtr &inst) 984981SN/A{ 994981SN/A // Make sure we have the right number of instructions. 1004981SN/A assert(numInstsInROB == countInsts()); 1014981SN/A // Make sure the instruction is valid. 1024981SN/A assert(inst); 1034981SN/A 1044981SN/A DPRINTF(ROB, "ROB: Adding inst PC %#x to the ROB.\n", inst->readPC()); 1054981SN/A 1064981SN/A // If the ROB is full then exit. 1074981SN/A assert(numInstsInROB != numEntries); 108633SN/A 1092SN/A ++numInstsInROB; 1102SN/A 1112SN/A // Increment the tail iterator, moving it one instruction back. 1122SN/A // There is a special case if the ROB was empty prior to this insertion, 1132SN/A // in which case the tail will be pointing at instList.end(). If that 1142SN/A // happens, then reset the tail to the beginning of the list. 1151435SN/A if (tail != cpu->instList.end()) { 1161954SN/A ++tail; 1171435SN/A } else { 1181954SN/A tail = cpu->instList.begin(); 11911071SN/A } 1201435SN/A 1212SN/A // Make sure the tail iterator is actually pointing at the instruction 1222SN/A // added. 12310905SN/A assert((*tail) == inst); 124558SN/A 12510905SN/A DPRINTF(ROB, "ROB: Now has %d instructions.\n", numInstsInROB); 12610905SN/A 127558SN/A} 128558SN/A 129558SN/A// Whatever calls this function needs to ensure that it properly frees up 13010905SN/A// registers prior to this function. 131558SN/Atemplate <class Impl> 13210905SN/Avoid 13310905SN/AROB<Impl>::retireHead() 134558SN/A{ 135558SN/A assert(numInstsInROB == countInsts()); 136558SN/A assert(numInstsInROB > 0); 1372566SN/A 138633SN/A // Get the head ROB instruction. 139633SN/A DynInstPtr head_inst = cpu->instList.front(); 140633SN/A 141633SN/A // Make certain this can retire. 142633SN/A assert(head_inst->readyToCommit()); 143633SN/A 144633SN/A DPRINTF(ROB, "ROB: Retiring head instruction of the ROB, " 1452SN/A "instruction PC %#x, seq num %i\n", head_inst->readPC(), 1462SN/A head_inst->seqNum); 1472SN/A 1482SN/A // Keep track of how many instructions are in the ROB. 1492SN/A --numInstsInROB; 150633SN/A 151633SN/A // Tell CPU to remove the instruction from the list of instructions. 15211071SN/A // A special case is needed if the instruction being retired is the 15311071SN/A // only instruction in the ROB; otherwise the tail iterator will become 15411071SN/A // invalidated. 155633SN/A cpu->removeFrontInst(head_inst); 15611071SN/A 157633SN/A if (numInstsInROB == 0) { 158633SN/A tail = cpu->instList.end(); 159195SN/A } 1602SN/A} 1612SN/A 1622SN/Atemplate <class Impl> 1632SN/Abool 1642SN/AROB<Impl>::isHeadReady() 1652SN/A{ 16611071SN/A if (numInstsInROB != 0) { 16711071SN/A return cpu->instList.front()->readyToCommit(); 16811071SN/A } 16911071SN/A 17011071SN/A return false; 17111071SN/A} 17211071SN/A 17311071SN/Atemplate <class Impl> 17411071SN/Aunsigned 17511071SN/AROB<Impl>::numFreeEntries() 17611071SN/A{ 17711071SN/A assert(numInstsInROB == countInsts()); 17811071SN/A 17911071SN/A return numEntries - numInstsInROB; 18011071SN/A} 18111071SN/A 18211071SN/Atemplate <class Impl> 1832SN/Avoid 1842566SN/AROB<Impl>::doSquash() 1852SN/A{ 1862SN/A DPRINTF(ROB, "ROB: Squashing instructions.\n"); 187633SN/A 1882SN/A assert(squashIt != cpu->instList.end()); 1892SN/A 1902SN/A for (int numSquashed = 0; 191633SN/A numSquashed < squashWidth && (*squashIt)->seqNum != squashedSeqNum; 1922SN/A ++numSquashed) 1932SN/A { 1942SN/A // Ensure that the instruction is younger. 1951961SN/A assert((*squashIt)->seqNum > squashedSeqNum); 1965190SN/A 1975190SN/A DPRINTF(ROB, "ROB: Squashing instruction PC %#x, seq num %i.\n", 1985190SN/A (*squashIt)->readPC(), (*squashIt)->seqNum); 199633SN/A 200633SN/A // Mark the instruction as squashed, and ready to commit so that 2017823SN/A // it can drain out of the pipeline. 2022SN/A (*squashIt)->setSquashed(); 2032SN/A 2042SN/A (*squashIt)->setCanCommit(); 2052SN/A 206558SN/A // Special case for when squashing due to a syscall. It's possible 20710905SN/A // that the squash happened after the head instruction was already 208558SN/A // committed, meaning that (*squashIt)->seqNum != squashedSeqNum 20910469SN/A // will never be false. Normally the squash would never be able 21010905SN/A // to go past the head of the ROB; in this case it might, so it 2111435SN/A // must be handled otherwise it will segfault. 21210905SN/A#ifndef FULL_SYSTEM 213558SN/A if (squashIt == cpu->instList.begin()) { 214633SN/A DPRINTF(ROB, "ROB: Reached head of instruction list while " 21510905SN/A "squashing.\n"); 216558SN/A 217633SN/A squashIt = cpu->instList.end(); 21810905SN/A 219574SN/A doneSquashing = true; 220574SN/A 22111071SN/A return; 22211071SN/A } 22311071SN/A#endif 22411071SN/A 22511071SN/A // Move the tail iterator to the next instruction. 22611071SN/A squashIt--; 22711071SN/A } 22811071SN/A 22911071SN/A 230558SN/A // Check if ROB is done squashing. 231558SN/A if ((*squashIt)->seqNum == squashedSeqNum) { 232558SN/A DPRINTF(ROB, "ROB: Done squashing instructions.\n"); 23310905SN/A 234558SN/A squashIt = cpu->instList.end(); 235574SN/A 23610905SN/A doneSquashing = true; 237574SN/A } 23810469SN/A} 23910905SN/A 240558SN/Atemplate <class Impl> 241558SN/Avoid 242574SN/AROB<Impl>::squash(InstSeqNum squash_num) 24310905SN/A{ 244558SN/A DPRINTF(ROB, "ROB: Starting to squash within the ROB.\n"); 245574SN/A doneSquashing = false; 24610905SN/A 2475606SN/A squashedSeqNum = squash_num; 248558SN/A 24911071SN/A assert(tail != cpu->instList.end()); 25011071SN/A 25111071SN/A squashIt = tail; 25211071SN/A 25311071SN/A doSquash(); 25411071SN/A} 25511071SN/A 25611071SN/Atemplate <class Impl> 25711071SN/Auint64_t 25811071SN/AROB<Impl>::readHeadPC() 25911071SN/A{ 26011071SN/A assert(numInstsInROB == countInsts()); 26111071SN/A 26211071SN/A DynInstPtr head_inst = cpu->instList.front(); 26311071SN/A 26411071SN/A return head_inst->readPC(); 26511071SN/A} 26611071SN/A 26711071SN/Atemplate <class Impl> 26811071SN/Auint64_t 26911071SN/AROB<Impl>::readHeadNextPC() 27011071SN/A{ 27111071SN/A assert(numInstsInROB == countInsts()); 27211071SN/A 27311071SN/A DynInstPtr head_inst = cpu->instList.front(); 274558SN/A 275558SN/A return head_inst->readNextPC(); 2764762SN/A} 2774762SN/A 2782SN/Atemplate <class Impl> 2794981SN/AInstSeqNum 2802SN/AROB<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