rob_impl.hh revision 2831
11689SN/A/* 22329SN/A * Copyright (c) 2004-2006 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 * Authors: Kevin Lim 292831Sksewell@umich.edu * Korey Sewell 301689SN/A */ 311689SN/A 321858SN/A#include "config/full_system.hh" 331717SN/A#include "cpu/o3/rob.hh" 341060SN/A 352292SN/Ausing namespace std; 362292SN/A 371061SN/Atemplate <class Impl> 382292SN/AROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth, 392292SN/A string _smtROBPolicy, unsigned _smtROBThreshold, 402292SN/A unsigned _numThreads) 411060SN/A : numEntries(_numEntries), 421060SN/A squashWidth(_squashWidth), 431060SN/A numInstsInROB(0), 442292SN/A squashedSeqNum(0), 452292SN/A numThreads(_numThreads) 461060SN/A{ 472292SN/A for (int tid=0; tid < numThreads; tid++) { 482292SN/A doneSquashing[tid] = true; 492292SN/A threadEntries[tid] = 0; 502292SN/A } 512292SN/A 522292SN/A string policy = _smtROBPolicy; 532292SN/A 542292SN/A //Convert string to lowercase 552292SN/A std::transform(policy.begin(), policy.end(), policy.begin(), 562292SN/A (int(*)(int)) tolower); 572292SN/A 582292SN/A //Figure out rob policy 592292SN/A if (policy == "dynamic") { 602292SN/A robPolicy = Dynamic; 612292SN/A 622292SN/A //Set Max Entries to Total ROB Capacity 632292SN/A for (int i = 0; i < numThreads; i++) { 642292SN/A maxEntries[i]=numEntries; 652292SN/A } 662292SN/A 672292SN/A } else if (policy == "partitioned") { 682292SN/A robPolicy = Partitioned; 692292SN/A DPRINTF(Fetch, "ROB sharing policy set to Partitioned\n"); 702292SN/A 712292SN/A //@todo:make work if part_amt doesnt divide evenly. 722292SN/A int part_amt = numEntries / numThreads; 732292SN/A 742292SN/A //Divide ROB up evenly 752292SN/A for (int i = 0; i < numThreads; i++) { 762292SN/A maxEntries[i]=part_amt; 772292SN/A } 782292SN/A 792292SN/A } else if (policy == "threshold") { 802292SN/A robPolicy = Threshold; 812292SN/A DPRINTF(Fetch, "ROB sharing policy set to Threshold\n"); 822292SN/A 832292SN/A int threshold = _smtROBThreshold;; 842292SN/A 852292SN/A //Divide up by threshold amount 862292SN/A for (int i = 0; i < numThreads; i++) { 872292SN/A maxEntries[i]=threshold; 882292SN/A } 892292SN/A } else { 902292SN/A assert(0 && "Invalid ROB Sharing Policy.Options Are:{Dynamic," 912292SN/A "Partitioned, Threshold}"); 922292SN/A } 932292SN/A} 942292SN/A 952292SN/Atemplate <class Impl> 962292SN/Astd::string 972292SN/AROB<Impl>::name() const 982292SN/A{ 992292SN/A return cpu->name() + ".rob"; 1001060SN/A} 1011060SN/A 1021061SN/Atemplate <class Impl> 1031060SN/Avoid 1042733Sktlim@umich.eduROB<Impl>::setCPU(O3CPU *cpu_ptr) 1051060SN/A{ 1061060SN/A cpu = cpu_ptr; 1071060SN/A 1082292SN/A // Set the per-thread iterators to the end of the instruction list. 1092292SN/A for (int i=0; i < numThreads;i++) { 1102292SN/A squashIt[i] = instList[i].end(); 1112292SN/A } 1121060SN/A 1132292SN/A // Initialize the "universal" ROB head & tail point to invalid 1142292SN/A // pointers 1152292SN/A head = instList[0].end(); 1162292SN/A tail = instList[0].end(); 1172292SN/A} 1182292SN/A 1192292SN/Atemplate <class Impl> 1202292SN/Avoid 1212292SN/AROB<Impl>::setActiveThreads(list<unsigned> *at_ptr) 1222292SN/A{ 1232292SN/A DPRINTF(ROB, "Setting active threads list pointer.\n"); 1242292SN/A activeThreads = at_ptr; 1252292SN/A} 1262292SN/A 1272307SN/Atemplate <class Impl> 1282307SN/Avoid 1292307SN/AROB<Impl>::switchOut() 1302307SN/A{ 1312307SN/A for (int tid = 0; tid < numThreads; tid++) { 1322307SN/A instList[tid].clear(); 1332307SN/A } 1342307SN/A} 1352307SN/A 1362307SN/Atemplate <class Impl> 1372307SN/Avoid 1382307SN/AROB<Impl>::takeOverFrom() 1392307SN/A{ 1402307SN/A for (int tid=0; tid < numThreads; tid++) { 1412307SN/A doneSquashing[tid] = true; 1422307SN/A threadEntries[tid] = 0; 1432307SN/A squashIt[tid] = instList[tid].end(); 1442307SN/A } 1452307SN/A numInstsInROB = 0; 1462307SN/A 1472307SN/A // Initialize the "universal" ROB head & tail point to invalid 1482307SN/A // pointers 1492307SN/A head = instList[0].end(); 1502307SN/A tail = instList[0].end(); 1512307SN/A} 1522292SN/A 1532292SN/Atemplate <class Impl> 1542292SN/Avoid 1552292SN/AROB<Impl>::resetEntries() 1562292SN/A{ 1572292SN/A if (robPolicy != Dynamic || numThreads > 1) { 1582292SN/A int active_threads = (*activeThreads).size(); 1592292SN/A 1602292SN/A list<unsigned>::iterator threads = (*activeThreads).begin(); 1612292SN/A list<unsigned>::iterator list_end = (*activeThreads).end(); 1622292SN/A 1632292SN/A while (threads != list_end) { 1642292SN/A if (robPolicy == Partitioned) { 1652292SN/A maxEntries[*threads++] = numEntries / active_threads; 1662292SN/A } else if (robPolicy == Threshold && active_threads == 1) { 1672292SN/A maxEntries[*threads++] = numEntries; 1682292SN/A } 1692292SN/A } 1702292SN/A } 1712292SN/A} 1722292SN/A 1732292SN/Atemplate <class Impl> 1742292SN/Aint 1752292SN/AROB<Impl>::entryAmount(int num_threads) 1762292SN/A{ 1772292SN/A if (robPolicy == Partitioned) { 1782292SN/A return numEntries / num_threads; 1792292SN/A } else { 1802292SN/A return 0; 1812292SN/A } 1821060SN/A} 1831060SN/A 1841061SN/Atemplate <class Impl> 1851060SN/Aint 1861060SN/AROB<Impl>::countInsts() 1871060SN/A{ 1882292SN/A int total=0; 1891061SN/A 1902292SN/A for (int i=0;i < numThreads;i++) 1912292SN/A total += countInsts(i); 1921060SN/A 1932292SN/A return total; 1942292SN/A} 1951060SN/A 1962292SN/Atemplate <class Impl> 1972292SN/Aint 1982292SN/AROB<Impl>::countInsts(unsigned tid) 1992292SN/A{ 2002292SN/A return instList[tid].size(); 2011060SN/A} 2021060SN/A 2031061SN/Atemplate <class Impl> 2041060SN/Avoid 2051061SN/AROB<Impl>::insertInst(DynInstPtr &inst) 2061060SN/A{ 2072292SN/A //assert(numInstsInROB == countInsts()); 2081060SN/A assert(inst); 2091060SN/A 2102292SN/A DPRINTF(ROB, "Adding inst PC %#x to the ROB.\n", inst->readPC()); 2111060SN/A 2121060SN/A assert(numInstsInROB != numEntries); 2131060SN/A 2142292SN/A int tid = inst->threadNumber; 2151060SN/A 2162292SN/A instList[tid].push_back(inst); 2172292SN/A 2182292SN/A //Set Up head iterator if this is the 1st instruction in the ROB 2192292SN/A if (numInstsInROB == 0) { 2202292SN/A head = instList[tid].begin(); 2212292SN/A assert((*head) == inst); 2221060SN/A } 2231060SN/A 2242292SN/A //Must Decrement for iterator to actually be valid since __.end() 2252292SN/A //actually points to 1 after the last inst 2262292SN/A tail = instList[tid].end(); 2272292SN/A tail--; 2282292SN/A 2292292SN/A inst->setInROB(); 2302292SN/A 2312292SN/A ++numInstsInROB; 2322292SN/A ++threadEntries[tid]; 2332292SN/A 2341060SN/A assert((*tail) == inst); 2351060SN/A 2362292SN/A DPRINTF(ROB, "[tid:%i] Now has %d instructions.\n", tid, threadEntries[tid]); 2371060SN/A} 2381060SN/A 2391060SN/A// Whatever calls this function needs to ensure that it properly frees up 2401060SN/A// registers prior to this function. 2412329SN/A/* 2421061SN/Atemplate <class Impl> 2431060SN/Avoid 2441060SN/AROB<Impl>::retireHead() 2451060SN/A{ 2462292SN/A //assert(numInstsInROB == countInsts()); 2472292SN/A assert(numInstsInROB > 0); 2482292SN/A 2492292SN/A int tid = (*head)->threadNumber; 2502292SN/A 2512292SN/A retireHead(tid); 2522292SN/A 2532292SN/A if (numInstsInROB == 0) { 2542292SN/A tail = instList[tid].end(); 2552292SN/A } 2562292SN/A} 2572329SN/A*/ 2582292SN/A 2592292SN/Atemplate <class Impl> 2602292SN/Avoid 2612292SN/AROB<Impl>::retireHead(unsigned tid) 2622292SN/A{ 2632292SN/A //assert(numInstsInROB == countInsts()); 2641061SN/A assert(numInstsInROB > 0); 2651060SN/A 2661060SN/A // Get the head ROB instruction. 2672292SN/A InstIt head_it = instList[tid].begin(); 2681060SN/A 2692292SN/A DynInstPtr head_inst = (*head_it); 2701858SN/A 2711060SN/A assert(head_inst->readyToCommit()); 2721060SN/A 2732292SN/A DPRINTF(ROB, "[tid:%u]: Retiring head instruction, " 2742292SN/A "instruction PC %#x,[sn:%lli]\n", tid, head_inst->readPC(), 2751060SN/A head_inst->seqNum); 2761060SN/A 2771060SN/A --numInstsInROB; 2782292SN/A --threadEntries[tid]; 2791060SN/A 2802731Sktlim@umich.edu head_inst->clearInROB(); 2812292SN/A head_inst->setCommitted(); 2822292SN/A 2832292SN/A instList[tid].erase(head_it); 2842292SN/A 2852292SN/A //Update "Global" Head of ROB 2862292SN/A updateHead(); 2872292SN/A 2882329SN/A // @todo: A special case is needed if the instruction being 2892329SN/A // retired is the only instruction in the ROB; otherwise the tail 2902329SN/A // iterator will become invalidated. 2911681SN/A cpu->removeFrontInst(head_inst); 2921060SN/A} 2932329SN/A/* 2941061SN/Atemplate <class Impl> 2951060SN/Abool 2961060SN/AROB<Impl>::isHeadReady() 2971060SN/A{ 2981060SN/A if (numInstsInROB != 0) { 2992292SN/A return (*head)->readyToCommit(); 3002292SN/A } 3012292SN/A 3022292SN/A return false; 3032292SN/A} 3042329SN/A*/ 3052292SN/Atemplate <class Impl> 3062292SN/Abool 3072292SN/AROB<Impl>::isHeadReady(unsigned tid) 3082292SN/A{ 3092292SN/A if (threadEntries[tid] != 0) { 3102292SN/A return instList[tid].front()->readyToCommit(); 3112292SN/A } 3122292SN/A 3132292SN/A return false; 3142292SN/A} 3152292SN/A 3162292SN/Atemplate <class Impl> 3172292SN/Abool 3182292SN/AROB<Impl>::canCommit() 3192292SN/A{ 3202292SN/A //@todo: set ActiveThreads through ROB or CPU 3212292SN/A list<unsigned>::iterator threads = (*activeThreads).begin(); 3222292SN/A 3232292SN/A while (threads != (*activeThreads).end()) { 3242292SN/A unsigned tid = *threads++; 3252292SN/A 3262292SN/A if (isHeadReady(tid)) { 3272292SN/A return true; 3282292SN/A } 3291060SN/A } 3301060SN/A 3311060SN/A return false; 3321060SN/A} 3331060SN/A 3341061SN/Atemplate <class Impl> 3351060SN/Aunsigned 3361060SN/AROB<Impl>::numFreeEntries() 3371060SN/A{ 3382292SN/A //assert(numInstsInROB == countInsts()); 3391060SN/A 3401060SN/A return numEntries - numInstsInROB; 3411060SN/A} 3421060SN/A 3431061SN/Atemplate <class Impl> 3442292SN/Aunsigned 3452292SN/AROB<Impl>::numFreeEntries(unsigned tid) 3461060SN/A{ 3472292SN/A return maxEntries[tid] - threadEntries[tid]; 3481060SN/A} 3491060SN/A 3501061SN/Atemplate <class Impl> 3511060SN/Avoid 3522292SN/AROB<Impl>::doSquash(unsigned tid) 3531060SN/A{ 3542292SN/A DPRINTF(ROB, "[tid:%u]: Squashing instructions until [sn:%i].\n", 3552292SN/A tid, squashedSeqNum); 3561858SN/A 3572292SN/A assert(squashIt[tid] != instList[tid].end()); 3582292SN/A 3592292SN/A if ((*squashIt[tid])->seqNum < squashedSeqNum) { 3602292SN/A DPRINTF(ROB, "[tid:%u]: Done squashing instructions.\n", 3612292SN/A tid); 3622292SN/A 3632292SN/A squashIt[tid] = instList[tid].end(); 3642292SN/A 3652292SN/A doneSquashing[tid] = true; 3662292SN/A return; 3672292SN/A } 3682292SN/A 3692292SN/A bool robTailUpdate = false; 3701858SN/A 3711858SN/A for (int numSquashed = 0; 3722292SN/A numSquashed < squashWidth && 3732292SN/A squashIt[tid] != instList[tid].end() && 3742292SN/A (*squashIt[tid])->seqNum > squashedSeqNum; 3751858SN/A ++numSquashed) 3761858SN/A { 3772292SN/A DPRINTF(ROB, "[tid:%u]: Squashing instruction PC %#x, seq num %i.\n", 3782292SN/A (*squashIt[tid])->threadNumber, 3792292SN/A (*squashIt[tid])->readPC(), 3802292SN/A (*squashIt[tid])->seqNum); 3811858SN/A 3821858SN/A // Mark the instruction as squashed, and ready to commit so that 3831858SN/A // it can drain out of the pipeline. 3842292SN/A (*squashIt[tid])->setSquashed(); 3851858SN/A 3862292SN/A (*squashIt[tid])->setCanCommit(); 3871858SN/A 3882292SN/A 3892292SN/A if (squashIt[tid] == instList[tid].begin()) { 3902292SN/A DPRINTF(ROB, "Reached head of instruction list while " 3911858SN/A "squashing.\n"); 3921858SN/A 3932292SN/A squashIt[tid] = instList[tid].end(); 3941858SN/A 3952292SN/A doneSquashing[tid] = true; 3961858SN/A 3971858SN/A return; 3981858SN/A } 3991858SN/A 4002292SN/A InstIt tail_thread = instList[tid].end(); 4012292SN/A tail_thread--; 4022292SN/A 4032292SN/A if ((*squashIt[tid]) == (*tail_thread)) 4042292SN/A robTailUpdate = true; 4052292SN/A 4062292SN/A squashIt[tid]--; 4071858SN/A } 4081858SN/A 4091858SN/A 4101858SN/A // Check if ROB is done squashing. 4112292SN/A if ((*squashIt[tid])->seqNum <= squashedSeqNum) { 4122292SN/A DPRINTF(ROB, "[tid:%u]: Done squashing instructions.\n", 4132292SN/A tid); 4141858SN/A 4152292SN/A squashIt[tid] = instList[tid].end(); 4161858SN/A 4172292SN/A doneSquashing[tid] = true; 4182292SN/A } 4192292SN/A 4202292SN/A if (robTailUpdate) { 4212292SN/A updateTail(); 4222292SN/A } 4232292SN/A} 4242292SN/A 4252292SN/A 4262292SN/Atemplate <class Impl> 4272292SN/Avoid 4282292SN/AROB<Impl>::updateHead() 4292292SN/A{ 4302292SN/A DynInstPtr head_inst; 4312292SN/A InstSeqNum lowest_num = 0; 4322292SN/A bool first_valid = true; 4332292SN/A 4342292SN/A // @todo: set ActiveThreads through ROB or CPU 4352292SN/A list<unsigned>::iterator threads = (*activeThreads).begin(); 4362292SN/A 4372292SN/A while (threads != (*activeThreads).end()) { 4382292SN/A unsigned thread_num = *threads++; 4392292SN/A 4402292SN/A if (instList[thread_num].empty()) 4412292SN/A continue; 4422292SN/A 4432292SN/A if (first_valid) { 4442292SN/A head = instList[thread_num].begin(); 4452292SN/A lowest_num = (*head)->seqNum; 4462292SN/A first_valid = false; 4472292SN/A continue; 4482292SN/A } 4492292SN/A 4502292SN/A InstIt head_thread = instList[thread_num].begin(); 4512292SN/A 4522292SN/A DynInstPtr head_inst = (*head_thread); 4532292SN/A 4542292SN/A assert(head_inst != 0); 4552292SN/A 4562292SN/A if (head_inst->seqNum < lowest_num) { 4572292SN/A head = head_thread; 4582292SN/A lowest_num = head_inst->seqNum; 4592292SN/A } 4602292SN/A } 4612292SN/A 4622292SN/A if (first_valid) { 4632292SN/A head = instList[0].end(); 4642292SN/A } 4652292SN/A 4662292SN/A} 4672292SN/A 4682292SN/Atemplate <class Impl> 4692292SN/Avoid 4702292SN/AROB<Impl>::updateTail() 4712292SN/A{ 4722292SN/A tail = instList[0].end(); 4732292SN/A bool first_valid = true; 4742292SN/A 4752292SN/A list<unsigned>::iterator threads = (*activeThreads).begin(); 4762292SN/A 4772292SN/A while (threads != (*activeThreads).end()) { 4782292SN/A unsigned tid = *threads++; 4792292SN/A 4802292SN/A if (instList[tid].empty()) { 4812292SN/A continue; 4822292SN/A } 4832292SN/A 4842292SN/A // If this is the first valid then assign w/out 4852292SN/A // comparison 4862292SN/A if (first_valid) { 4872292SN/A tail = instList[tid].end(); 4882292SN/A tail--; 4892292SN/A first_valid = false; 4902292SN/A continue; 4912292SN/A } 4922292SN/A 4932292SN/A // Assign new tail if this thread's tail is younger 4942292SN/A // than our current "tail high" 4952292SN/A InstIt tail_thread = instList[tid].end(); 4962292SN/A tail_thread--; 4972292SN/A 4982292SN/A if ((*tail_thread)->seqNum > (*tail)->seqNum) { 4992292SN/A tail = tail_thread; 5002292SN/A } 5012292SN/A } 5022292SN/A} 5032292SN/A 5042292SN/A 5052292SN/Atemplate <class Impl> 5062292SN/Avoid 5072292SN/AROB<Impl>::squash(InstSeqNum squash_num,unsigned tid) 5082292SN/A{ 5092292SN/A if (isEmpty()) { 5102292SN/A DPRINTF(ROB, "Does not need to squash due to being empty " 5112292SN/A "[sn:%i]\n", 5122292SN/A squash_num); 5132292SN/A 5142292SN/A return; 5152292SN/A } 5162292SN/A 5172292SN/A DPRINTF(ROB, "Starting to squash within the ROB.\n"); 5182292SN/A 5192292SN/A robStatus[tid] = ROBSquashing; 5202292SN/A 5212292SN/A doneSquashing[tid] = false; 5221060SN/A 5231060SN/A squashedSeqNum = squash_num; 5241060SN/A 5252292SN/A if (!instList[tid].empty()) { 5262292SN/A InstIt tail_thread = instList[tid].end(); 5272292SN/A tail_thread--; 5281060SN/A 5292292SN/A squashIt[tid] = tail_thread; 5301060SN/A 5312292SN/A doSquash(tid); 5321858SN/A } 5331060SN/A} 5342329SN/A/* 5351858SN/Atemplate <class Impl> 5362292SN/Atypename Impl::DynInstPtr 5372292SN/AROB<Impl>::readHeadInst() 5381858SN/A{ 5392292SN/A if (numInstsInROB != 0) { 5402292SN/A assert((*head)->isInROB()==true); 5412292SN/A return *head; 5422292SN/A } else { 5432292SN/A return dummyInst; 5442292SN/A } 5452292SN/A} 5462329SN/A*/ 5472292SN/Atemplate <class Impl> 5482292SN/Atypename Impl::DynInstPtr 5492292SN/AROB<Impl>::readHeadInst(unsigned tid) 5502292SN/A{ 5512292SN/A if (threadEntries[tid] != 0) { 5522292SN/A InstIt head_thread = instList[tid].begin(); 5531060SN/A 5542292SN/A assert((*head_thread)->isInROB()==true); 5551858SN/A 5562292SN/A return *head_thread; 5572292SN/A } else { 5582292SN/A return dummyInst; 5592292SN/A } 5601858SN/A} 5612329SN/A/* 5621061SN/Atemplate <class Impl> 5631060SN/Auint64_t 5641060SN/AROB<Impl>::readHeadPC() 5651060SN/A{ 5662292SN/A //assert(numInstsInROB == countInsts()); 5671060SN/A 5682292SN/A DynInstPtr head_inst = *head; 5691060SN/A 5701060SN/A return head_inst->readPC(); 5711060SN/A} 5721060SN/A 5731061SN/Atemplate <class Impl> 5741060SN/Auint64_t 5752292SN/AROB<Impl>::readHeadPC(unsigned tid) 5762292SN/A{ 5772292SN/A //assert(numInstsInROB == countInsts()); 5782292SN/A InstIt head_thread = instList[tid].begin(); 5792292SN/A 5802292SN/A return (*head_thread)->readPC(); 5812292SN/A} 5822292SN/A 5832292SN/A 5842292SN/Atemplate <class Impl> 5852292SN/Auint64_t 5861060SN/AROB<Impl>::readHeadNextPC() 5871060SN/A{ 5882292SN/A //assert(numInstsInROB == countInsts()); 5891060SN/A 5902292SN/A DynInstPtr head_inst = *head; 5911060SN/A 5921060SN/A return head_inst->readNextPC(); 5931060SN/A} 5941060SN/A 5951061SN/Atemplate <class Impl> 5962292SN/Auint64_t 5972292SN/AROB<Impl>::readHeadNextPC(unsigned tid) 5982292SN/A{ 5992292SN/A //assert(numInstsInROB == countInsts()); 6002292SN/A InstIt head_thread = instList[tid].begin(); 6012292SN/A 6022292SN/A return (*head_thread)->readNextPC(); 6032292SN/A} 6042292SN/A 6052292SN/Atemplate <class Impl> 6061060SN/AInstSeqNum 6071060SN/AROB<Impl>::readHeadSeqNum() 6081060SN/A{ 6092292SN/A //assert(numInstsInROB == countInsts()); 6102292SN/A DynInstPtr head_inst = *head; 6111060SN/A 6121060SN/A return head_inst->seqNum; 6131060SN/A} 6141060SN/A 6151061SN/Atemplate <class Impl> 6162292SN/AInstSeqNum 6172292SN/AROB<Impl>::readHeadSeqNum(unsigned tid) 6182292SN/A{ 6192292SN/A InstIt head_thread = instList[tid].begin(); 6202292SN/A 6212292SN/A return ((*head_thread)->seqNum); 6222292SN/A} 6232292SN/A 6242292SN/Atemplate <class Impl> 6252292SN/Atypename Impl::DynInstPtr 6262292SN/AROB<Impl>::readTailInst() 6272292SN/A{ 6282292SN/A //assert(numInstsInROB == countInsts()); 6292292SN/A //assert(tail != instList[0].end()); 6302292SN/A 6312292SN/A return (*tail); 6322292SN/A} 6332329SN/A*/ 6342292SN/Atemplate <class Impl> 6352292SN/Atypename Impl::DynInstPtr 6362292SN/AROB<Impl>::readTailInst(unsigned tid) 6372292SN/A{ 6382292SN/A //assert(tail_thread[tid] != instList[tid].end()); 6392292SN/A 6402292SN/A InstIt tail_thread = instList[tid].end(); 6412292SN/A tail_thread--; 6422292SN/A 6432292SN/A return *tail_thread; 6442292SN/A} 6452292SN/A 6462329SN/A/* 6472292SN/Atemplate <class Impl> 6481060SN/Auint64_t 6491060SN/AROB<Impl>::readTailPC() 6501060SN/A{ 6512292SN/A //assert(numInstsInROB == countInsts()); 6521060SN/A 6532292SN/A //assert(tail != instList[0].end()); 6541060SN/A 6551060SN/A return (*tail)->readPC(); 6561060SN/A} 6571060SN/A 6581061SN/Atemplate <class Impl> 6592292SN/Auint64_t 6602292SN/AROB<Impl>::readTailPC(unsigned tid) 6612292SN/A{ 6622292SN/A //assert(tail_thread[tid] != instList[tid].end()); 6632292SN/A 6642292SN/A InstIt tail_thread = instList[tid].end(); 6652292SN/A tail_thread--; 6662292SN/A 6672292SN/A return (*tail_thread)->readPC(); 6682292SN/A} 6692292SN/A 6702292SN/Atemplate <class Impl> 6711060SN/AInstSeqNum 6721060SN/AROB<Impl>::readTailSeqNum() 6731060SN/A{ 6741060SN/A // Return the last sequence number that has not been squashed. Other 6751060SN/A // stages can use it to squash any instructions younger than the current 6761060SN/A // tail. 6771060SN/A return (*tail)->seqNum; 6781060SN/A} 6791060SN/A 6802292SN/Atemplate <class Impl> 6812292SN/AInstSeqNum 6822292SN/AROB<Impl>::readTailSeqNum(unsigned tid) 6832292SN/A{ 6842292SN/A // Return the last sequence number that has not been squashed. Other 6852292SN/A // stages can use it to squash any instructions younger than the current 6862292SN/A // tail. 6872292SN/A // assert(tail_thread[tid] != instList[tid].end()); 6882292SN/A 6892292SN/A InstIt tail_thread = instList[tid].end(); 6902292SN/A tail_thread--; 6912292SN/A 6922292SN/A return (*tail_thread)->seqNum; 6932292SN/A} 6942329SN/A*/ 695