rob_impl.hh revision 1689
11689SN/A/* 22329SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan 31689SN/A * All rights reserved. 41689SN/A * 51689SN/A * Redistribution and use in source and binary forms, with or without 61689SN/A * modification, are permitted provided that the following conditions are 71689SN/A * met: redistributions of source code must retain the above copyright 81689SN/A * notice, this list of conditions and the following disclaimer; 91689SN/A * redistributions in binary form must reproduce the above copyright 101689SN/A * notice, this list of conditions and the following disclaimer in the 111689SN/A * documentation and/or other materials provided with the distribution; 121689SN/A * neither the name of the copyright holders nor the names of its 131689SN/A * contributors may be used to endorse or promote products derived from 141689SN/A * this software without specific prior written permission. 151689SN/A * 161689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 181689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 191689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 201689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 211689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 221689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 231689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 241689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 251689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 261689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu */ 282665Ssaidi@eecs.umich.edu 292831Sksewell@umich.edu#ifndef __CPU_BETA_CPU_ROB_IMPL_HH__ 301689SN/A#define __CPU_BETA_CPU_ROB_IMPL_HH__ 311689SN/A 321858SN/A#include "cpu/beta_cpu/rob.hh" 331717SN/A 341060SN/Atemplate <class Impl> 352292SN/AROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth) 362292SN/A : numEntries(_numEntries), 371061SN/A squashWidth(_squashWidth), 382292SN/A numInstsInROB(0), 392292SN/A squashedSeqNum(0) 402292SN/A{ 411060SN/A doneSquashing = true; 421060SN/A} 431060SN/A 442292SN/Atemplate <class Impl> 451060SN/Avoid 462292SN/AROB<Impl>::setCPU(FullCPU *cpu_ptr) 472877Sksewell@umich.edu{ 482292SN/A cpu = cpu_ptr; 492292SN/A 502292SN/A // Set the tail to the beginning of the CPU instruction list so that 512292SN/A // upon the first instruction being inserted into the ROB, the tail 522292SN/A // iterator can simply be incremented. 532292SN/A tail = cpu->instList.begin(); 542292SN/A 552292SN/A // Set the squash iterator to the end of the instruction list. 562292SN/A squashIt = cpu->instList.end(); 572292SN/A} 582292SN/A 592292SN/Atemplate <class Impl> 602292SN/Aint 612292SN/AROB<Impl>::countInsts() 622292SN/A{ 632292SN/A // Start at 1; if the tail matches cpu->instList.begin(), then there is 642292SN/A // one inst in the ROB. 652292SN/A int return_val = 1; 662292SN/A 672292SN/A // There are quite a few special cases. Do not use this function other 682292SN/A // than for debugging purposes. 692292SN/A if (cpu->instList.begin() == cpu->instList.end()) { 702292SN/A // In this case there are no instructions in the list. The ROB 712292SN/A // must be empty. 722292SN/A return 0; 732292SN/A } else if (tail == cpu->instList.end()) { 742292SN/A // In this case, the tail is not yet pointing to anything valid. 752292SN/A // The ROB must be empty. 762292SN/A return 0; 772292SN/A } 782292SN/A 792292SN/A // Iterate through the ROB from the head to the tail, counting the 802292SN/A // entries. 812292SN/A for (InstIt_t i = cpu->instList.begin(); i != tail; ++i) 822292SN/A { 832292SN/A assert(i != cpu->instList.end()); 842292SN/A ++return_val; 852292SN/A } 862292SN/A 872292SN/A return return_val; 882292SN/A 892292SN/A // Because the head won't be tracked properly until the ROB gets the 902292SN/A // first instruction, and any time that the ROB is empty and has not 912292SN/A // yet gotten the instruction, this function doesn't work. 922292SN/A// return numInstsInROB; 932292SN/A} 942292SN/A 952292SN/Atemplate <class Impl> 962292SN/Avoid 972292SN/AROB<Impl>::insertInst(DynInstPtr &inst) 982292SN/A{ 992292SN/A // Make sure we have the right number of instructions. 1001060SN/A assert(numInstsInROB == countInsts()); 1011060SN/A // Make sure the instruction is valid. 1021061SN/A assert(inst); 1031060SN/A 1042733Sktlim@umich.edu DPRINTF(ROB, "ROB: Adding inst PC %#x to the ROB.\n", inst->readPC()); 1051060SN/A 1061060SN/A // If the ROB is full then exit. 1071060SN/A assert(numInstsInROB != numEntries); 1082292SN/A 1092292SN/A ++numInstsInROB; 1102292SN/A 1112292SN/A // Increment the tail iterator, moving it one instruction back. 1121060SN/A // There is a special case if the ROB was empty prior to this insertion, 1132292SN/A // in which case the tail will be pointing at instList.end(). If that 1142292SN/A // happens, then reset the tail to the beginning of the list. 1152292SN/A if (tail != cpu->instList.end()) { 1162292SN/A ++tail; 1172292SN/A } else { 1182292SN/A tail = cpu->instList.begin(); 1192292SN/A } 1202292SN/A 1212292SN/A // Make sure the tail iterator is actually pointing at the instruction 1222292SN/A // added. 1232292SN/A assert((*tail) == inst); 1242292SN/A 1252292SN/A DPRINTF(ROB, "ROB: Now has %d instructions.\n", numInstsInROB); 1262292SN/A 1272307SN/A} 1282307SN/A 1292307SN/A// Whatever calls this function needs to ensure that it properly frees up 1302307SN/A// registers prior to this function. 1312307SN/Atemplate <class Impl> 1322307SN/Avoid 1332307SN/AROB<Impl>::retireHead() 1342307SN/A{ 1352307SN/A assert(numInstsInROB == countInsts()); 1362307SN/A assert(numInstsInROB > 0); 1372307SN/A 1382307SN/A // Get the head ROB instruction. 1392307SN/A DynInstPtr head_inst = cpu->instList.front(); 1402307SN/A 1412307SN/A // Make certain this can retire. 1422307SN/A assert(head_inst->readyToCommit()); 1432307SN/A 1442307SN/A DPRINTF(ROB, "ROB: Retiring head instruction of the ROB, " 1452307SN/A "instruction PC %#x, seq num %i\n", head_inst->readPC(), 1462307SN/A head_inst->seqNum); 1472307SN/A 1482307SN/A // Keep track of how many instructions are in the ROB. 1492307SN/A --numInstsInROB; 1502307SN/A 1512307SN/A // Tell CPU to remove the instruction from the list of instructions. 1522292SN/A // A special case is needed if the instruction being retired is the 1532292SN/A // only instruction in the ROB; otherwise the tail iterator will become 1542292SN/A // invalidated. 1552292SN/A cpu->removeFrontInst(head_inst); 1562292SN/A 1572292SN/A if (numInstsInROB == 0) { 1582292SN/A tail = cpu->instList.end(); 1592292SN/A } 1602292SN/A} 1612292SN/A 1622292SN/Atemplate <class Impl> 1632292SN/Abool 1642292SN/AROB<Impl>::isHeadReady() 1652292SN/A{ 1662292SN/A if (numInstsInROB != 0) { 1672292SN/A return cpu->instList.front()->readyToCommit(); 1682292SN/A } 1692292SN/A 1702292SN/A return false; 1712292SN/A} 1722292SN/A 1732292SN/Atemplate <class Impl> 1742292SN/Aunsigned 1752292SN/AROB<Impl>::numFreeEntries() 1762292SN/A{ 1772292SN/A assert(numInstsInROB == countInsts()); 1782292SN/A 1792292SN/A return numEntries - numInstsInROB; 1802292SN/A} 1812292SN/A 1821060SN/Atemplate <class Impl> 1831060SN/Avoid 1841061SN/AROB<Impl>::doSquash() 1851060SN/A{ 1861060SN/A DPRINTF(ROB, "ROB: Squashing instructions.\n"); 1871060SN/A 1882292SN/A assert(squashIt != cpu->instList.end()); 1891061SN/A 1902292SN/A for (int numSquashed = 0; 1912292SN/A numSquashed < squashWidth && (*squashIt)->seqNum != squashedSeqNum; 1921060SN/A ++numSquashed) 1932292SN/A { 1942292SN/A // Ensure that the instruction is younger. 1951060SN/A assert((*squashIt)->seqNum > squashedSeqNum); 1962292SN/A 1972292SN/A DPRINTF(ROB, "ROB: Squashing instruction PC %#x, seq num %i.\n", 1982292SN/A (*squashIt)->readPC(), (*squashIt)->seqNum); 1992292SN/A 2002292SN/A // Mark the instruction as squashed, and ready to commit so that 2011060SN/A // it can drain out of the pipeline. 2021060SN/A (*squashIt)->setSquashed(); 2031061SN/A 2041060SN/A (*squashIt)->setCanCommit(); 2051061SN/A 2061060SN/A // Special case for when squashing due to a syscall. It's possible 2072292SN/A // that the squash happened after the head instruction was already 2081060SN/A // committed, meaning that (*squashIt)->seqNum != squashedSeqNum 2091060SN/A // will never be false. Normally the squash would never be able 2102292SN/A // to go past the head of the ROB; in this case it might, so it 2111060SN/A // must be handled otherwise it will segfault. 2121060SN/A#ifndef FULL_SYSTEM 2131060SN/A if (squashIt == cpu->instList.begin()) { 2142292SN/A DPRINTF(ROB, "ROB: Reached head of instruction list while " 2151060SN/A "squashing.\n"); 2162292SN/A 2172292SN/A squashIt = cpu->instList.end(); 2182292SN/A 2192292SN/A doneSquashing = true; 2202292SN/A 2212292SN/A return; 2221060SN/A } 2231060SN/A#endif 2242292SN/A 2252292SN/A // Move the tail iterator to the next instruction. 2262292SN/A squashIt--; 2272292SN/A } 2282292SN/A 2292292SN/A 2302292SN/A // Check if ROB is done squashing. 2312292SN/A if ((*squashIt)->seqNum == squashedSeqNum) { 2322292SN/A DPRINTF(ROB, "ROB: Done squashing instructions.\n"); 2332292SN/A 2341060SN/A squashIt = cpu->instList.end(); 2351060SN/A 2362292SN/A doneSquashing = true; 2371060SN/A } 2381060SN/A} 2391060SN/A 2401060SN/Atemplate <class Impl> 2412329SN/Avoid 2421061SN/AROB<Impl>::squash(InstSeqNum squash_num) 2431060SN/A{ 2441060SN/A DPRINTF(ROB, "ROB: Starting to squash within the ROB.\n"); 2451060SN/A doneSquashing = false; 2462292SN/A 2472292SN/A squashedSeqNum = squash_num; 2482292SN/A 2492292SN/A assert(tail != cpu->instList.end()); 2502292SN/A 2512292SN/A squashIt = tail; 2522292SN/A 2532292SN/A doSquash(); 2542292SN/A} 2552292SN/A 2562292SN/Atemplate <class Impl> 2572329SN/Auint64_t 2582292SN/AROB<Impl>::readHeadPC() 2592292SN/A{ 2602292SN/A assert(numInstsInROB == countInsts()); 2612292SN/A 2622292SN/A DynInstPtr head_inst = cpu->instList.front(); 2632292SN/A 2641061SN/A return head_inst->readPC(); 2651060SN/A} 2661060SN/A 2672292SN/Atemplate <class Impl> 2681060SN/Auint64_t 2692292SN/AROB<Impl>::readHeadNextPC() 2701858SN/A{ 2711060SN/A assert(numInstsInROB == countInsts()); 2721060SN/A 2732292SN/A DynInstPtr head_inst = cpu->instList.front(); 2742292SN/A 2751060SN/A return head_inst->readNextPC(); 2761060SN/A} 2771060SN/A 2782292SN/Atemplate <class Impl> 2791060SN/AInstSeqNum 2802731Sktlim@umich.eduROB<Impl>::readHeadSeqNum() 2812292SN/A{ 2822292SN/A // Return the last sequence number that has not been squashed. Other 2832292SN/A // stages can use it to squash any instructions younger than the current 2842292SN/A // tail. 2852292SN/A DynInstPtr head_inst = cpu->instList.front(); 2862292SN/A 2872292SN/A return head_inst->seqNum; 2882329SN/A} 2892329SN/A 2902329SN/Atemplate <class Impl> 2911681SN/Auint64_t 2921060SN/AROB<Impl>::readTailPC() 2932329SN/A{ 2941061SN/A assert(numInstsInROB == countInsts()); 2951060SN/A 2961060SN/A assert(tail != cpu->instList.end()); 2971060SN/A 2981060SN/A return (*tail)->readPC(); 2992292SN/A} 3002292SN/A 3012292SN/Atemplate <class Impl> 3022292SN/AInstSeqNum 3032292SN/AROB<Impl>::readTailSeqNum() 3042329SN/A{ 3052292SN/A // Return the last sequence number that has not been squashed. Other 3062292SN/A // stages can use it to squash any instructions younger than the current 3072292SN/A // tail. 3082292SN/A return (*tail)->seqNum; 3092292SN/A} 3102292SN/A 3112292SN/A#endif // __CPU_BETA_CPU_ROB_IMPL_HH__ 3122292SN/A