rob_impl.hh revision 1689
111988Sandreas.sandberg@arm.com/* 211988Sandreas.sandberg@arm.com * Copyright (c) 2004-2005 The Regents of The University of Michigan 311988Sandreas.sandberg@arm.com * All rights reserved. 411988Sandreas.sandberg@arm.com * 511988Sandreas.sandberg@arm.com * Redistribution and use in source and binary forms, with or without 611988Sandreas.sandberg@arm.com * modification, are permitted provided that the following conditions are 711988Sandreas.sandberg@arm.com * met: redistributions of source code must retain the above copyright 811988Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer; 911988Sandreas.sandberg@arm.com * redistributions in binary form must reproduce the above copyright 1011988Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer in the 1111988Sandreas.sandberg@arm.com * documentation and/or other materials provided with the distribution; 1211988Sandreas.sandberg@arm.com * neither the name of the copyright holders nor the names of its 1311988Sandreas.sandberg@arm.com * contributors may be used to endorse or promote products derived from 1411988Sandreas.sandberg@arm.com * this software without specific prior written permission. 1511988Sandreas.sandberg@arm.com * 1611988Sandreas.sandberg@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1711988Sandreas.sandberg@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1811988Sandreas.sandberg@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1911988Sandreas.sandberg@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2011988Sandreas.sandberg@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2111988Sandreas.sandberg@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2211988Sandreas.sandberg@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2311988Sandreas.sandberg@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2411988Sandreas.sandberg@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2511988Sandreas.sandberg@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2611988Sandreas.sandberg@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2711988Sandreas.sandberg@arm.com */ 2811988Sandreas.sandberg@arm.com 2911988Sandreas.sandberg@arm.com#ifndef __CPU_BETA_CPU_ROB_IMPL_HH__ 3011988Sandreas.sandberg@arm.com#define __CPU_BETA_CPU_ROB_IMPL_HH__ 3111988Sandreas.sandberg@arm.com 3211988Sandreas.sandberg@arm.com#include "cpu/beta_cpu/rob.hh" 3311988Sandreas.sandberg@arm.com 3411988Sandreas.sandberg@arm.comtemplate <class Impl> 3511988Sandreas.sandberg@arm.comROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth) 3611988Sandreas.sandberg@arm.com : numEntries(_numEntries), 3711988Sandreas.sandberg@arm.com squashWidth(_squashWidth), 3811988Sandreas.sandberg@arm.com numInstsInROB(0), 3911988Sandreas.sandberg@arm.com squashedSeqNum(0) 4011988Sandreas.sandberg@arm.com{ 4111988Sandreas.sandberg@arm.com doneSquashing = true; 4211988Sandreas.sandberg@arm.com} 4311988Sandreas.sandberg@arm.com 4411988Sandreas.sandberg@arm.comtemplate <class Impl> 4511988Sandreas.sandberg@arm.comvoid 4611988Sandreas.sandberg@arm.comROB<Impl>::setCPU(FullCPU *cpu_ptr) 4711988Sandreas.sandberg@arm.com{ 4811988Sandreas.sandberg@arm.com cpu = cpu_ptr; 4912035Sandreas.sandberg@arm.com 5012035Sandreas.sandberg@arm.com // Set the tail to the beginning of the CPU instruction list so that 5111988Sandreas.sandberg@arm.com // upon the first instruction being inserted into the ROB, the tail 5211988Sandreas.sandberg@arm.com // iterator can simply be incremented. 5311988Sandreas.sandberg@arm.com tail = cpu->instList.begin(); 5411988Sandreas.sandberg@arm.com 5512334Sgabeblack@google.com // Set the squash iterator to the end of the instruction list. 5611988Sandreas.sandberg@arm.com squashIt = cpu->instList.end(); 5711988Sandreas.sandberg@arm.com} 5811988Sandreas.sandberg@arm.com 5911988Sandreas.sandberg@arm.comtemplate <class Impl> 6011988Sandreas.sandberg@arm.comint 6111988Sandreas.sandberg@arm.comROB<Impl>::countInsts() 6211988Sandreas.sandberg@arm.com{ 6311988Sandreas.sandberg@arm.com // Start at 1; if the tail matches cpu->instList.begin(), then there is 6411988Sandreas.sandberg@arm.com // one inst in the ROB. 6511988Sandreas.sandberg@arm.com int return_val = 1; 6611988Sandreas.sandberg@arm.com 6711988Sandreas.sandberg@arm.com // There are quite a few special cases. Do not use this function other 6811988Sandreas.sandberg@arm.com // than for debugging purposes. 6911988Sandreas.sandberg@arm.com if (cpu->instList.begin() == cpu->instList.end()) { 7011988Sandreas.sandberg@arm.com // In this case there are no instructions in the list. The ROB 7111988Sandreas.sandberg@arm.com // must be empty. 7211988Sandreas.sandberg@arm.com return 0; 7311988Sandreas.sandberg@arm.com } else if (tail == cpu->instList.end()) { 7411988Sandreas.sandberg@arm.com // In this case, the tail is not yet pointing to anything valid. 7511988Sandreas.sandberg@arm.com // The ROB must be empty. 7611988Sandreas.sandberg@arm.com return 0; 7711988Sandreas.sandberg@arm.com } 7811988Sandreas.sandberg@arm.com 7911988Sandreas.sandberg@arm.com // Iterate through the ROB from the head to the tail, counting the 8011988Sandreas.sandberg@arm.com // entries. 8111988Sandreas.sandberg@arm.com for (InstIt_t i = cpu->instList.begin(); i != tail; ++i) 8211988Sandreas.sandberg@arm.com { 8311988Sandreas.sandberg@arm.com assert(i != cpu->instList.end()); 8411988Sandreas.sandberg@arm.com ++return_val; 8511988Sandreas.sandberg@arm.com } 8611988Sandreas.sandberg@arm.com 8711988Sandreas.sandberg@arm.com return return_val; 8811988Sandreas.sandberg@arm.com 8911988Sandreas.sandberg@arm.com // Because the head won't be tracked properly until the ROB gets the 9011988Sandreas.sandberg@arm.com // first instruction, and any time that the ROB is empty and has not 9111988Sandreas.sandberg@arm.com // yet gotten the instruction, this function doesn't work. 9211988Sandreas.sandberg@arm.com// return numInstsInROB; 9311988Sandreas.sandberg@arm.com} 9411988Sandreas.sandberg@arm.com 9511988Sandreas.sandberg@arm.comtemplate <class Impl> 9611988Sandreas.sandberg@arm.comvoid 9711988Sandreas.sandberg@arm.comROB<Impl>::insertInst(DynInstPtr &inst) 9811988Sandreas.sandberg@arm.com{ 9911988Sandreas.sandberg@arm.com // Make sure we have the right number of instructions. 10011988Sandreas.sandberg@arm.com assert(numInstsInROB == countInsts()); 10111988Sandreas.sandberg@arm.com // Make sure the instruction is valid. 10211988Sandreas.sandberg@arm.com assert(inst); 10311988Sandreas.sandberg@arm.com 10411988Sandreas.sandberg@arm.com DPRINTF(ROB, "ROB: Adding inst PC %#x to the ROB.\n", inst->readPC()); 10511988Sandreas.sandberg@arm.com 10611988Sandreas.sandberg@arm.com // If the ROB is full then exit. 10711988Sandreas.sandberg@arm.com assert(numInstsInROB != numEntries); 10811988Sandreas.sandberg@arm.com 10911988Sandreas.sandberg@arm.com ++numInstsInROB; 11011988Sandreas.sandberg@arm.com 11111988Sandreas.sandberg@arm.com // Increment the tail iterator, moving it one instruction back. 11211988Sandreas.sandberg@arm.com // There is a special case if the ROB was empty prior to this insertion, 11311988Sandreas.sandberg@arm.com // in which case the tail will be pointing at instList.end(). If that 11411988Sandreas.sandberg@arm.com // happens, then reset the tail to the beginning of the list. 11511988Sandreas.sandberg@arm.com if (tail != cpu->instList.end()) { 11611988Sandreas.sandberg@arm.com ++tail; 11711988Sandreas.sandberg@arm.com } else { 11811988Sandreas.sandberg@arm.com tail = cpu->instList.begin(); 11911988Sandreas.sandberg@arm.com } 12011988Sandreas.sandberg@arm.com 12111988Sandreas.sandberg@arm.com // Make sure the tail iterator is actually pointing at the instruction 12211988Sandreas.sandberg@arm.com // added. 12311988Sandreas.sandberg@arm.com assert((*tail) == inst); 12411988Sandreas.sandberg@arm.com 12511988Sandreas.sandberg@arm.com DPRINTF(ROB, "ROB: Now has %d instructions.\n", numInstsInROB); 12611988Sandreas.sandberg@arm.com 12711988Sandreas.sandberg@arm.com} 12811988Sandreas.sandberg@arm.com 12911988Sandreas.sandberg@arm.com// Whatever calls this function needs to ensure that it properly frees up 13011988Sandreas.sandberg@arm.com// registers prior to this function. 13111988Sandreas.sandberg@arm.comtemplate <class Impl> 13211988Sandreas.sandberg@arm.comvoid 13311988Sandreas.sandberg@arm.comROB<Impl>::retireHead() 13411988Sandreas.sandberg@arm.com{ 13512036Sandreas.sandberg@arm.com assert(numInstsInROB == countInsts()); 13612036Sandreas.sandberg@arm.com assert(numInstsInROB > 0); 13711988Sandreas.sandberg@arm.com 13811988Sandreas.sandberg@arm.com // Get the head ROB instruction. 13911988Sandreas.sandberg@arm.com DynInstPtr head_inst = cpu->instList.front(); 14011988Sandreas.sandberg@arm.com 14111988Sandreas.sandberg@arm.com // Make certain this can retire. 14211988Sandreas.sandberg@arm.com assert(head_inst->readyToCommit()); 14311988Sandreas.sandberg@arm.com 14411988Sandreas.sandberg@arm.com DPRINTF(ROB, "ROB: Retiring head instruction of the ROB, " 14511988Sandreas.sandberg@arm.com "instruction PC %#x, seq num %i\n", head_inst->readPC(), 14611988Sandreas.sandberg@arm.com head_inst->seqNum); 14711988Sandreas.sandberg@arm.com 14811988Sandreas.sandberg@arm.com // Keep track of how many instructions are in the ROB. 14911988Sandreas.sandberg@arm.com --numInstsInROB; 15011988Sandreas.sandberg@arm.com 15111988Sandreas.sandberg@arm.com // Tell CPU to remove the instruction from the list of instructions. 15211988Sandreas.sandberg@arm.com // A special case is needed if the instruction being retired is the 15311988Sandreas.sandberg@arm.com // only instruction in the ROB; otherwise the tail iterator will become 15411988Sandreas.sandberg@arm.com // invalidated. 15511988Sandreas.sandberg@arm.com cpu->removeFrontInst(head_inst); 15611988Sandreas.sandberg@arm.com 15711988Sandreas.sandberg@arm.com if (numInstsInROB == 0) { 15811988Sandreas.sandberg@arm.com tail = cpu->instList.end(); 15911988Sandreas.sandberg@arm.com } 16011988Sandreas.sandberg@arm.com} 16111988Sandreas.sandberg@arm.com 16211988Sandreas.sandberg@arm.comtemplate <class Impl> 16311988Sandreas.sandberg@arm.combool 16411988Sandreas.sandberg@arm.comROB<Impl>::isHeadReady() 16511988Sandreas.sandberg@arm.com{ 16611988Sandreas.sandberg@arm.com if (numInstsInROB != 0) { 16711988Sandreas.sandberg@arm.com return cpu->instList.front()->readyToCommit(); 16811988Sandreas.sandberg@arm.com } 16912036Sandreas.sandberg@arm.com 17012035Sandreas.sandberg@arm.com return false; 17112035Sandreas.sandberg@arm.com} 17212035Sandreas.sandberg@arm.com 17311988Sandreas.sandberg@arm.comtemplate <class Impl> 17411988Sandreas.sandberg@arm.comunsigned 17511988Sandreas.sandberg@arm.comROB<Impl>::numFreeEntries() 17611988Sandreas.sandberg@arm.com{ 17711988Sandreas.sandberg@arm.com assert(numInstsInROB == countInsts()); 17811988Sandreas.sandberg@arm.com 17911988Sandreas.sandberg@arm.com return numEntries - numInstsInROB; 18011988Sandreas.sandberg@arm.com} 18111988Sandreas.sandberg@arm.com 18211988Sandreas.sandberg@arm.comtemplate <class Impl> 18311988Sandreas.sandberg@arm.comvoid 18411988Sandreas.sandberg@arm.comROB<Impl>::doSquash() 18511988Sandreas.sandberg@arm.com{ 18611988Sandreas.sandberg@arm.com DPRINTF(ROB, "ROB: Squashing instructions.\n"); 18711988Sandreas.sandberg@arm.com 18811988Sandreas.sandberg@arm.com assert(squashIt != cpu->instList.end()); 18911988Sandreas.sandberg@arm.com 19011988Sandreas.sandberg@arm.com for (int numSquashed = 0; 19111988Sandreas.sandberg@arm.com numSquashed < squashWidth && (*squashIt)->seqNum != squashedSeqNum; 19211988Sandreas.sandberg@arm.com ++numSquashed) 19311988Sandreas.sandberg@arm.com { 19411988Sandreas.sandberg@arm.com // Ensure that the instruction is younger. 19511988Sandreas.sandberg@arm.com assert((*squashIt)->seqNum > squashedSeqNum); 19611988Sandreas.sandberg@arm.com 19711988Sandreas.sandberg@arm.com DPRINTF(ROB, "ROB: Squashing instruction PC %#x, seq num %i.\n", 19811988Sandreas.sandberg@arm.com (*squashIt)->readPC(), (*squashIt)->seqNum); 19911988Sandreas.sandberg@arm.com 20011988Sandreas.sandberg@arm.com // Mark the instruction as squashed, and ready to commit so that 20111988Sandreas.sandberg@arm.com // it can drain out of the pipeline. 20211988Sandreas.sandberg@arm.com (*squashIt)->setSquashed(); 20311988Sandreas.sandberg@arm.com 20411988Sandreas.sandberg@arm.com (*squashIt)->setCanCommit(); 20511988Sandreas.sandberg@arm.com 20611988Sandreas.sandberg@arm.com // Special case for when squashing due to a syscall. It's possible 20711988Sandreas.sandberg@arm.com // that the squash happened after the head instruction was already 20811988Sandreas.sandberg@arm.com // committed, meaning that (*squashIt)->seqNum != squashedSeqNum 20911988Sandreas.sandberg@arm.com // will never be false. Normally the squash would never be able 21011988Sandreas.sandberg@arm.com // to go past the head of the ROB; in this case it might, so it 21111988Sandreas.sandberg@arm.com // must be handled otherwise it will segfault. 21211988Sandreas.sandberg@arm.com#ifndef FULL_SYSTEM 21311988Sandreas.sandberg@arm.com if (squashIt == cpu->instList.begin()) { 21411988Sandreas.sandberg@arm.com DPRINTF(ROB, "ROB: Reached head of instruction list while " 21511988Sandreas.sandberg@arm.com "squashing.\n"); 21611988Sandreas.sandberg@arm.com 21711988Sandreas.sandberg@arm.com squashIt = cpu->instList.end(); 21811988Sandreas.sandberg@arm.com 21911988Sandreas.sandberg@arm.com doneSquashing = true; 22011988Sandreas.sandberg@arm.com 22111988Sandreas.sandberg@arm.com return; 22211988Sandreas.sandberg@arm.com } 22311988Sandreas.sandberg@arm.com#endif 22411988Sandreas.sandberg@arm.com 22511988Sandreas.sandberg@arm.com // Move the tail iterator to the next instruction. 22611988Sandreas.sandberg@arm.com squashIt--; 22711988Sandreas.sandberg@arm.com } 22811988Sandreas.sandberg@arm.com 22911988Sandreas.sandberg@arm.com 23011988Sandreas.sandberg@arm.com // Check if ROB is done squashing. 23111988Sandreas.sandberg@arm.com if ((*squashIt)->seqNum == squashedSeqNum) { 23211988Sandreas.sandberg@arm.com DPRINTF(ROB, "ROB: Done squashing instructions.\n"); 23311988Sandreas.sandberg@arm.com 23411988Sandreas.sandberg@arm.com squashIt = cpu->instList.end(); 23511988Sandreas.sandberg@arm.com 23611988Sandreas.sandberg@arm.com doneSquashing = true; 23711988Sandreas.sandberg@arm.com } 23811988Sandreas.sandberg@arm.com} 23911988Sandreas.sandberg@arm.com 24011988Sandreas.sandberg@arm.comtemplate <class Impl> 24111988Sandreas.sandberg@arm.comvoid 24211988Sandreas.sandberg@arm.comROB<Impl>::squash(InstSeqNum squash_num) 24311988Sandreas.sandberg@arm.com{ 24412011Sgabeblack@google.com DPRINTF(ROB, "ROB: Starting to squash within the ROB.\n"); 24511988Sandreas.sandberg@arm.com doneSquashing = false; 24611988Sandreas.sandberg@arm.com 24711988Sandreas.sandberg@arm.com squashedSeqNum = squash_num; 24811988Sandreas.sandberg@arm.com 24911988Sandreas.sandberg@arm.com assert(tail != cpu->instList.end()); 25011988Sandreas.sandberg@arm.com 25111988Sandreas.sandberg@arm.com squashIt = tail; 25211988Sandreas.sandberg@arm.com 25311988Sandreas.sandberg@arm.com doSquash(); 25411988Sandreas.sandberg@arm.com} 25511988Sandreas.sandberg@arm.com 25611988Sandreas.sandberg@arm.comtemplate <class Impl> 25711988Sandreas.sandberg@arm.comuint64_t 25811988Sandreas.sandberg@arm.comROB<Impl>::readHeadPC() 25911988Sandreas.sandberg@arm.com{ 26011988Sandreas.sandberg@arm.com assert(numInstsInROB == countInsts()); 26111988Sandreas.sandberg@arm.com 26211988Sandreas.sandberg@arm.com DynInstPtr head_inst = cpu->instList.front(); 26311988Sandreas.sandberg@arm.com 26411988Sandreas.sandberg@arm.com return head_inst->readPC(); 26511988Sandreas.sandberg@arm.com} 26611988Sandreas.sandberg@arm.com 26711988Sandreas.sandberg@arm.comtemplate <class Impl> 26811988Sandreas.sandberg@arm.comuint64_t 26911988Sandreas.sandberg@arm.comROB<Impl>::readHeadNextPC() 27011988Sandreas.sandberg@arm.com{ 27111988Sandreas.sandberg@arm.com assert(numInstsInROB == countInsts()); 27211988Sandreas.sandberg@arm.com 27311988Sandreas.sandberg@arm.com DynInstPtr head_inst = cpu->instList.front(); 27411988Sandreas.sandberg@arm.com 27511988Sandreas.sandberg@arm.com return head_inst->readNextPC(); 27611988Sandreas.sandberg@arm.com} 27711988Sandreas.sandberg@arm.com 27811988Sandreas.sandberg@arm.comtemplate <class Impl> 27911988Sandreas.sandberg@arm.comInstSeqNum 28011988Sandreas.sandberg@arm.comROB<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