rob_impl.hh revision 2980
17259Sgblack@eecs.umich.edu/* 211574SCurtis.Dunham@arm.com * Copyright (c) 2004-2006 The Regents of The University of Michigan 37259Sgblack@eecs.umich.edu * All rights reserved. 47259Sgblack@eecs.umich.edu * 57259Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 67259Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 77259Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 87259Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 97259Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 107259Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 117259Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 127259Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 137259Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 147259Sgblack@eecs.umich.edu * this software without specific prior written permission. 157259Sgblack@eecs.umich.edu * 167259Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177259Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187259Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197259Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207259Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217259Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 227259Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237259Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 247259Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 257259Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 267259Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 277259Sgblack@eecs.umich.edu * 287259Sgblack@eecs.umich.edu * Authors: Kevin Lim 297259Sgblack@eecs.umich.edu * Korey Sewell 307259Sgblack@eecs.umich.edu */ 317259Sgblack@eecs.umich.edu 327259Sgblack@eecs.umich.edu#include "config/full_system.hh" 337259Sgblack@eecs.umich.edu#include "cpu/o3/rob.hh" 347259Sgblack@eecs.umich.edu 357259Sgblack@eecs.umich.edu#include <list> 367259Sgblack@eecs.umich.edu 377259Sgblack@eecs.umich.edutemplate <class Impl> 387405SAli.Saidi@ARM.comROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth, 3910037SARM gem5 Developers std::string _smtROBPolicy, unsigned _smtROBThreshold, 407259Sgblack@eecs.umich.edu unsigned _numThreads) 417259Sgblack@eecs.umich.edu : numEntries(_numEntries), 427405SAli.Saidi@ARM.com squashWidth(_squashWidth), 437259Sgblack@eecs.umich.edu numInstsInROB(0), 447404SAli.Saidi@ARM.com numThreads(_numThreads) 4510037SARM gem5 Developers{ 4610828SGiacomo.Gabrielli@arm.com for (int tid=0; tid < numThreads; tid++) { 477259Sgblack@eecs.umich.edu squashedSeqNum[tid] = 0; 487259Sgblack@eecs.umich.edu doneSquashing[tid] = true; 497259Sgblack@eecs.umich.edu threadEntries[tid] = 0; 507259Sgblack@eecs.umich.edu } 517259Sgblack@eecs.umich.edu 528868SMatt.Horsnell@arm.com std::string policy = _smtROBPolicy; 538868SMatt.Horsnell@arm.com 548868SMatt.Horsnell@arm.com //Convert string to lowercase 558868SMatt.Horsnell@arm.com std::transform(policy.begin(), policy.end(), policy.begin(), 5610037SARM gem5 Developers (int(*)(int)) tolower); 578868SMatt.Horsnell@arm.com 5810037SARM gem5 Developers //Figure out rob policy 598868SMatt.Horsnell@arm.com if (policy == "dynamic") { 6010037SARM gem5 Developers robPolicy = Dynamic; 6110037SARM gem5 Developers 6210037SARM gem5 Developers //Set Max Entries to Total ROB Capacity 6310037SARM gem5 Developers for (int i = 0; i < numThreads; i++) { 6410037SARM gem5 Developers maxEntries[i]=numEntries; 6510037SARM gem5 Developers } 6610037SARM gem5 Developers 678868SMatt.Horsnell@arm.com } else if (policy == "partitioned") { 6810037SARM gem5 Developers robPolicy = Partitioned; 6910037SARM gem5 Developers DPRINTF(Fetch, "ROB sharing policy set to Partitioned\n"); 7010037SARM gem5 Developers 7110037SARM gem5 Developers //@todo:make work if part_amt doesnt divide evenly. 7210037SARM gem5 Developers int part_amt = numEntries / numThreads; 7310037SARM gem5 Developers 7410037SARM gem5 Developers //Divide ROB up evenly 7510037SARM gem5 Developers for (int i = 0; i < numThreads; i++) { 7610037SARM gem5 Developers maxEntries[i]=part_amt; 7710037SARM gem5 Developers } 7810037SARM gem5 Developers 799959Schander.sudanthi@arm.com } else if (policy == "threshold") { 8010037SARM gem5 Developers robPolicy = Threshold; 819959Schander.sudanthi@arm.com DPRINTF(Fetch, "ROB sharing policy set to Threshold\n"); 829959Schander.sudanthi@arm.com 839959Schander.sudanthi@arm.com int threshold = _smtROBThreshold;; 849959Schander.sudanthi@arm.com 859959Schander.sudanthi@arm.com //Divide up by threshold amount 869959Schander.sudanthi@arm.com for (int i = 0; i < numThreads; i++) { 879959Schander.sudanthi@arm.com maxEntries[i]=threshold; 889959Schander.sudanthi@arm.com } 899959Schander.sudanthi@arm.com } else { 9010037SARM gem5 Developers assert(0 && "Invalid ROB Sharing Policy.Options Are:{Dynamic," 919959Schander.sudanthi@arm.com "Partitioned, Threshold}"); 9210037SARM gem5 Developers } 9310037SARM gem5 Developers} 9410037SARM gem5 Developers 9510037SARM gem5 Developerstemplate <class Impl> 9610037SARM gem5 Developersstd::string 9710037SARM gem5 DevelopersROB<Impl>::name() const 9810037SARM gem5 Developers{ 9910037SARM gem5 Developers return cpu->name() + ".rob"; 10010037SARM gem5 Developers} 10110037SARM gem5 Developers 10210037SARM gem5 Developerstemplate <class Impl> 1038868SMatt.Horsnell@arm.comvoid 10410037SARM gem5 DevelopersROB<Impl>::setCPU(O3CPU *cpu_ptr) 10510037SARM gem5 Developers{ 10610037SARM gem5 Developers cpu = cpu_ptr; 10710037SARM gem5 Developers 10810037SARM gem5 Developers // Set the per-thread iterators to the end of the instruction list. 10910037SARM gem5 Developers for (int i=0; i < numThreads;i++) { 11010037SARM gem5 Developers squashIt[i] = instList[i].end(); 11110037SARM gem5 Developers } 11210037SARM gem5 Developers 11310037SARM gem5 Developers // Initialize the "universal" ROB head & tail point to invalid 11410037SARM gem5 Developers // pointers 11510037SARM gem5 Developers head = instList[0].end(); 11610037SARM gem5 Developers tail = instList[0].end(); 11710037SARM gem5 Developers} 11810037SARM gem5 Developers 1198868SMatt.Horsnell@arm.comtemplate <class Impl> 12010037SARM gem5 Developersvoid 12110037SARM gem5 DevelopersROB<Impl>::setActiveThreads(std::list<unsigned> *at_ptr) 12210037SARM gem5 Developers{ 12310037SARM gem5 Developers DPRINTF(ROB, "Setting active threads list pointer.\n"); 12410037SARM gem5 Developers activeThreads = at_ptr; 1258868SMatt.Horsnell@arm.com} 12610037SARM gem5 Developers 12710037SARM gem5 Developerstemplate <class Impl> 12810037SARM gem5 Developersvoid 12910037SARM gem5 DevelopersROB<Impl>::switchOut() 13010506SAli.Saidi@ARM.com{ 13110037SARM gem5 Developers for (int tid = 0; tid < numThreads; tid++) { 13210506SAli.Saidi@ARM.com instList[tid].clear(); 13310037SARM gem5 Developers } 13410506SAli.Saidi@ARM.com} 13510037SARM gem5 Developers 13610506SAli.Saidi@ARM.comtemplate <class Impl> 13710037SARM gem5 Developersvoid 13810506SAli.Saidi@ARM.comROB<Impl>::takeOverFrom() 13910037SARM gem5 Developers{ 14010506SAli.Saidi@ARM.com for (int tid=0; tid < numThreads; tid++) { 14110037SARM gem5 Developers doneSquashing[tid] = true; 14210506SAli.Saidi@ARM.com threadEntries[tid] = 0; 14310037SARM gem5 Developers squashIt[tid] = instList[tid].end(); 14410506SAli.Saidi@ARM.com } 14510037SARM gem5 Developers numInstsInROB = 0; 14610506SAli.Saidi@ARM.com 14710037SARM gem5 Developers // Initialize the "universal" ROB head & tail point to invalid 14810506SAli.Saidi@ARM.com // pointers 14910037SARM gem5 Developers head = instList[0].end(); 15010506SAli.Saidi@ARM.com tail = instList[0].end(); 15110037SARM gem5 Developers} 15210506SAli.Saidi@ARM.com 15310037SARM gem5 Developerstemplate <class Impl> 15410506SAli.Saidi@ARM.comvoid 15510037SARM gem5 DevelopersROB<Impl>::resetEntries() 15610506SAli.Saidi@ARM.com{ 15710037SARM gem5 Developers if (robPolicy != Dynamic || numThreads > 1) { 15810506SAli.Saidi@ARM.com int active_threads = (*activeThreads).size(); 15910037SARM gem5 Developers 16010037SARM gem5 Developers std::list<unsigned>::iterator threads = (*activeThreads).begin(); 16110037SARM gem5 Developers std::list<unsigned>::iterator list_end = (*activeThreads).end(); 16210506SAli.Saidi@ARM.com 16310037SARM gem5 Developers while (threads != list_end) { 16410506SAli.Saidi@ARM.com if (robPolicy == Partitioned) { 16510037SARM gem5 Developers maxEntries[*threads++] = numEntries / active_threads; 16610506SAli.Saidi@ARM.com } else if (robPolicy == Threshold && active_threads == 1) { 16710037SARM gem5 Developers maxEntries[*threads++] = numEntries; 16810506SAli.Saidi@ARM.com } 16910037SARM gem5 Developers } 17010506SAli.Saidi@ARM.com } 17110037SARM gem5 Developers} 17210506SAli.Saidi@ARM.com 17310037SARM gem5 Developerstemplate <class Impl> 17410506SAli.Saidi@ARM.comint 17510037SARM gem5 DevelopersROB<Impl>::entryAmount(int num_threads) 17610506SAli.Saidi@ARM.com{ 17710037SARM gem5 Developers if (robPolicy == Partitioned) { 17810506SAli.Saidi@ARM.com return numEntries / num_threads; 17910037SARM gem5 Developers } else { 18010506SAli.Saidi@ARM.com return 0; 18110037SARM gem5 Developers } 18210506SAli.Saidi@ARM.com} 18310037SARM gem5 Developers 18410506SAli.Saidi@ARM.comtemplate <class Impl> 18510037SARM gem5 Developersint 18610506SAli.Saidi@ARM.comROB<Impl>::countInsts() 18710037SARM gem5 Developers{ 18810506SAli.Saidi@ARM.com int total=0; 18910037SARM gem5 Developers 19010506SAli.Saidi@ARM.com for (int i=0;i < numThreads;i++) 19110037SARM gem5 Developers total += countInsts(i); 19210037SARM gem5 Developers 19310037SARM gem5 Developers return total; 19410506SAli.Saidi@ARM.com} 19510037SARM gem5 Developers 19610506SAli.Saidi@ARM.comtemplate <class Impl> 19710037SARM gem5 Developersint 19810506SAli.Saidi@ARM.comROB<Impl>::countInsts(unsigned tid) 19910037SARM gem5 Developers{ 20010506SAli.Saidi@ARM.com return instList[tid].size(); 20110037SARM gem5 Developers} 20210506SAli.Saidi@ARM.com 20310037SARM gem5 Developerstemplate <class Impl> 20410506SAli.Saidi@ARM.comvoid 20510037SARM gem5 DevelopersROB<Impl>::insertInst(DynInstPtr &inst) 20610506SAli.Saidi@ARM.com{ 20710037SARM gem5 Developers //assert(numInstsInROB == countInsts()); 20810506SAli.Saidi@ARM.com assert(inst); 20910037SARM gem5 Developers 21010506SAli.Saidi@ARM.com DPRINTF(ROB, "Adding inst PC %#x to the ROB.\n", inst->readPC()); 21110037SARM gem5 Developers 21210506SAli.Saidi@ARM.com assert(numInstsInROB != numEntries); 21310037SARM gem5 Developers 21410506SAli.Saidi@ARM.com int tid = inst->threadNumber; 21510037SARM gem5 Developers 21610506SAli.Saidi@ARM.com instList[tid].push_back(inst); 21710037SARM gem5 Developers 21810506SAli.Saidi@ARM.com //Set Up head iterator if this is the 1st instruction in the ROB 21910037SARM gem5 Developers if (numInstsInROB == 0) { 22010506SAli.Saidi@ARM.com head = instList[tid].begin(); 22110037SARM gem5 Developers assert((*head) == inst); 22210506SAli.Saidi@ARM.com } 22310037SARM gem5 Developers 22410506SAli.Saidi@ARM.com //Must Decrement for iterator to actually be valid since __.end() 22510037SARM gem5 Developers //actually points to 1 after the last inst 22610506SAli.Saidi@ARM.com tail = instList[tid].end(); 22710037SARM gem5 Developers tail--; 22810506SAli.Saidi@ARM.com 22910037SARM gem5 Developers inst->setInROB(); 23010506SAli.Saidi@ARM.com 23110037SARM gem5 Developers ++numInstsInROB; 23210506SAli.Saidi@ARM.com ++threadEntries[tid]; 23310037SARM gem5 Developers 23410506SAli.Saidi@ARM.com assert((*tail) == inst); 23510037SARM gem5 Developers 23610506SAli.Saidi@ARM.com DPRINTF(ROB, "[tid:%i] Now has %d instructions.\n", tid, threadEntries[tid]); 23710037SARM gem5 Developers} 23810506SAli.Saidi@ARM.com 23910037SARM gem5 Developers// Whatever calls this function needs to ensure that it properly frees up 24010506SAli.Saidi@ARM.com// registers prior to this function. 24110037SARM gem5 Developers/* 24210506SAli.Saidi@ARM.comtemplate <class Impl> 24310037SARM gem5 Developersvoid 24410506SAli.Saidi@ARM.comROB<Impl>::retireHead() 24510037SARM gem5 Developers{ 24610506SAli.Saidi@ARM.com //assert(numInstsInROB == countInsts()); 24710037SARM gem5 Developers assert(numInstsInROB > 0); 24810506SAli.Saidi@ARM.com 24910037SARM gem5 Developers int tid = (*head)->threadNumber; 25010506SAli.Saidi@ARM.com 25110037SARM gem5 Developers retireHead(tid); 25210506SAli.Saidi@ARM.com 25310037SARM gem5 Developers if (numInstsInROB == 0) { 25410506SAli.Saidi@ARM.com tail = instList[tid].end(); 25510037SARM gem5 Developers } 25610506SAli.Saidi@ARM.com} 25710037SARM gem5 Developers*/ 25810506SAli.Saidi@ARM.com 25910037SARM gem5 Developerstemplate <class Impl> 26010506SAli.Saidi@ARM.comvoid 26110037SARM gem5 DevelopersROB<Impl>::retireHead(unsigned tid) 26210506SAli.Saidi@ARM.com{ 26310037SARM gem5 Developers //assert(numInstsInROB == countInsts()); 26410506SAli.Saidi@ARM.com assert(numInstsInROB > 0); 26510037SARM gem5 Developers 26610506SAli.Saidi@ARM.com // Get the head ROB instruction. 26710037SARM gem5 Developers InstIt head_it = instList[tid].begin(); 26810506SAli.Saidi@ARM.com 26910037SARM gem5 Developers DynInstPtr head_inst = (*head_it); 27010506SAli.Saidi@ARM.com 27110037SARM gem5 Developers assert(head_inst->readyToCommit()); 27210506SAli.Saidi@ARM.com 27310037SARM gem5 Developers DPRINTF(ROB, "[tid:%u]: Retiring head instruction, " 27410506SAli.Saidi@ARM.com "instruction PC %#x,[sn:%lli]\n", tid, head_inst->readPC(), 27510037SARM gem5 Developers head_inst->seqNum); 27610506SAli.Saidi@ARM.com 27710037SARM gem5 Developers --numInstsInROB; 27810506SAli.Saidi@ARM.com --threadEntries[tid]; 27910037SARM gem5 Developers 28010506SAli.Saidi@ARM.com head_inst->clearInROB(); 28110037SARM gem5 Developers head_inst->setCommitted(); 28210506SAli.Saidi@ARM.com 28310037SARM gem5 Developers instList[tid].erase(head_it); 28410506SAli.Saidi@ARM.com 28510037SARM gem5 Developers //Update "Global" Head of ROB 28610506SAli.Saidi@ARM.com updateHead(); 28710037SARM gem5 Developers 28810506SAli.Saidi@ARM.com // @todo: A special case is needed if the instruction being 28910037SARM gem5 Developers // retired is the only instruction in the ROB; otherwise the tail 29010506SAli.Saidi@ARM.com // iterator will become invalidated. 29110037SARM gem5 Developers cpu->removeFrontInst(head_inst); 29210506SAli.Saidi@ARM.com} 29310037SARM gem5 Developers/* 29410037SARM gem5 Developerstemplate <class Impl> 29510037SARM gem5 Developersbool 29610506SAli.Saidi@ARM.comROB<Impl>::isHeadReady() 29710037SARM gem5 Developers{ 29810506SAli.Saidi@ARM.com if (numInstsInROB != 0) { 29910037SARM gem5 Developers return (*head)->readyToCommit(); 30010506SAli.Saidi@ARM.com } 30110037SARM gem5 Developers 30210506SAli.Saidi@ARM.com return false; 30310037SARM gem5 Developers} 30410506SAli.Saidi@ARM.com*/ 30510037SARM gem5 Developerstemplate <class Impl> 30610506SAli.Saidi@ARM.combool 30710037SARM gem5 DevelopersROB<Impl>::isHeadReady(unsigned tid) 30810506SAli.Saidi@ARM.com{ 30910037SARM gem5 Developers if (threadEntries[tid] != 0) { 31010506SAli.Saidi@ARM.com return instList[tid].front()->readyToCommit(); 31110037SARM gem5 Developers } 31210506SAli.Saidi@ARM.com 31310037SARM gem5 Developers return false; 31410506SAli.Saidi@ARM.com} 31510037SARM gem5 Developers 31610506SAli.Saidi@ARM.comtemplate <class Impl> 31710037SARM gem5 Developersbool 31810506SAli.Saidi@ARM.comROB<Impl>::canCommit() 31910037SARM gem5 Developers{ 32010506SAli.Saidi@ARM.com //@todo: set ActiveThreads through ROB or CPU 32110037SARM gem5 Developers std::list<unsigned>::iterator threads = (*activeThreads).begin(); 32210506SAli.Saidi@ARM.com 32310037SARM gem5 Developers while (threads != (*activeThreads).end()) { 32410506SAli.Saidi@ARM.com unsigned tid = *threads++; 32510037SARM gem5 Developers 32610506SAli.Saidi@ARM.com if (isHeadReady(tid)) { 32710037SARM gem5 Developers return true; 32810506SAli.Saidi@ARM.com } 32910037SARM gem5 Developers } 33010506SAli.Saidi@ARM.com 33110037SARM gem5 Developers return false; 33210506SAli.Saidi@ARM.com} 33310037SARM gem5 Developers 33410506SAli.Saidi@ARM.comtemplate <class Impl> 33510037SARM gem5 Developersunsigned 33610506SAli.Saidi@ARM.comROB<Impl>::numFreeEntries() 33710037SARM gem5 Developers{ 33810506SAli.Saidi@ARM.com //assert(numInstsInROB == countInsts()); 33910037SARM gem5 Developers 34010506SAli.Saidi@ARM.com return numEntries - numInstsInROB; 34110037SARM gem5 Developers} 34210506SAli.Saidi@ARM.com 34310037SARM gem5 Developerstemplate <class Impl> 34410506SAli.Saidi@ARM.comunsigned 34510037SARM gem5 DevelopersROB<Impl>::numFreeEntries(unsigned tid) 34610506SAli.Saidi@ARM.com{ 34710037SARM gem5 Developers return maxEntries[tid] - threadEntries[tid]; 34810506SAli.Saidi@ARM.com} 34910037SARM gem5 Developers 35010506SAli.Saidi@ARM.comtemplate <class Impl> 35110037SARM gem5 Developersvoid 35210506SAli.Saidi@ARM.comROB<Impl>::doSquash(unsigned tid) 35310037SARM gem5 Developers{ 35410506SAli.Saidi@ARM.com DPRINTF(ROB, "[tid:%u]: Squashing instructions until [sn:%i].\n", 35510037SARM gem5 Developers tid, squashedSeqNum[tid]); 35610506SAli.Saidi@ARM.com 35710037SARM gem5 Developers assert(squashIt[tid] != instList[tid].end()); 35810506SAli.Saidi@ARM.com 35910037SARM gem5 Developers if ((*squashIt[tid])->seqNum < squashedSeqNum[tid]) { 36010506SAli.Saidi@ARM.com DPRINTF(ROB, "[tid:%u]: Done squashing instructions.\n", 36110037SARM gem5 Developers tid); 36210506SAli.Saidi@ARM.com 36310037SARM gem5 Developers squashIt[tid] = instList[tid].end(); 36410506SAli.Saidi@ARM.com 36510037SARM gem5 Developers doneSquashing[tid] = true; 36610506SAli.Saidi@ARM.com return; 36710037SARM gem5 Developers } 36810506SAli.Saidi@ARM.com 36910037SARM gem5 Developers bool robTailUpdate = false; 37010506SAli.Saidi@ARM.com 37110037SARM gem5 Developers for (int numSquashed = 0; 37210506SAli.Saidi@ARM.com numSquashed < squashWidth && 37310037SARM gem5 Developers squashIt[tid] != instList[tid].end() && 37410506SAli.Saidi@ARM.com (*squashIt[tid])->seqNum > squashedSeqNum[tid]; 37510037SARM gem5 Developers ++numSquashed) 37610506SAli.Saidi@ARM.com { 37710037SARM gem5 Developers DPRINTF(ROB, "[tid:%u]: Squashing instruction PC %#x, seq num %i.\n", 37810506SAli.Saidi@ARM.com (*squashIt[tid])->threadNumber, 37910037SARM gem5 Developers (*squashIt[tid])->readPC(), 38010506SAli.Saidi@ARM.com (*squashIt[tid])->seqNum); 38110037SARM gem5 Developers 38210506SAli.Saidi@ARM.com // Mark the instruction as squashed, and ready to commit so that 38310037SARM gem5 Developers // it can drain out of the pipeline. 38410506SAli.Saidi@ARM.com (*squashIt[tid])->setSquashed(); 38510037SARM gem5 Developers 38610506SAli.Saidi@ARM.com (*squashIt[tid])->setCanCommit(); 38710037SARM gem5 Developers 38810506SAli.Saidi@ARM.com 38910037SARM gem5 Developers if (squashIt[tid] == instList[tid].begin()) { 39010506SAli.Saidi@ARM.com DPRINTF(ROB, "Reached head of instruction list while " 39110037SARM gem5 Developers "squashing.\n"); 39210506SAli.Saidi@ARM.com 39310037SARM gem5 Developers squashIt[tid] = instList[tid].end(); 39410506SAli.Saidi@ARM.com 39510037SARM gem5 Developers doneSquashing[tid] = true; 39610506SAli.Saidi@ARM.com 39710037SARM gem5 Developers return; 39810506SAli.Saidi@ARM.com } 39910037SARM gem5 Developers 40010506SAli.Saidi@ARM.com InstIt tail_thread = instList[tid].end(); 40110037SARM gem5 Developers tail_thread--; 40210506SAli.Saidi@ARM.com 40310037SARM gem5 Developers if ((*squashIt[tid]) == (*tail_thread)) 40410506SAli.Saidi@ARM.com robTailUpdate = true; 40510037SARM gem5 Developers 40610506SAli.Saidi@ARM.com squashIt[tid]--; 40710037SARM gem5 Developers } 40810506SAli.Saidi@ARM.com 40910037SARM gem5 Developers 41010506SAli.Saidi@ARM.com // Check if ROB is done squashing. 41110037SARM gem5 Developers if ((*squashIt[tid])->seqNum <= squashedSeqNum[tid]) { 41210506SAli.Saidi@ARM.com DPRINTF(ROB, "[tid:%u]: Done squashing instructions.\n", 41310037SARM gem5 Developers tid); 41410506SAli.Saidi@ARM.com 41510037SARM gem5 Developers squashIt[tid] = instList[tid].end(); 41610506SAli.Saidi@ARM.com 41710037SARM gem5 Developers doneSquashing[tid] = true; 41810506SAli.Saidi@ARM.com } 41910037SARM gem5 Developers 42010506SAli.Saidi@ARM.com if (robTailUpdate) { 42110037SARM gem5 Developers updateTail(); 42210506SAli.Saidi@ARM.com } 42310037SARM gem5 Developers} 42410506SAli.Saidi@ARM.com 42510037SARM gem5 Developers 42610506SAli.Saidi@ARM.comtemplate <class Impl> 42710037SARM gem5 Developersvoid 42810506SAli.Saidi@ARM.comROB<Impl>::updateHead() 42910037SARM gem5 Developers{ 43010506SAli.Saidi@ARM.com DynInstPtr head_inst; 43110037SARM gem5 Developers InstSeqNum lowest_num = 0; 43210506SAli.Saidi@ARM.com bool first_valid = true; 43310037SARM gem5 Developers 43410506SAli.Saidi@ARM.com // @todo: set ActiveThreads through ROB or CPU 43510037SARM gem5 Developers std::list<unsigned>::iterator threads = (*activeThreads).begin(); 43610506SAli.Saidi@ARM.com 43710037SARM gem5 Developers while (threads != (*activeThreads).end()) { 43810506SAli.Saidi@ARM.com unsigned thread_num = *threads++; 43910037SARM gem5 Developers 44010506SAli.Saidi@ARM.com if (instList[thread_num].empty()) 44110037SARM gem5 Developers continue; 44210506SAli.Saidi@ARM.com 44310037SARM gem5 Developers if (first_valid) { 44410506SAli.Saidi@ARM.com head = instList[thread_num].begin(); 44510037SARM gem5 Developers lowest_num = (*head)->seqNum; 44610506SAli.Saidi@ARM.com first_valid = false; 44710037SARM gem5 Developers continue; 44810506SAli.Saidi@ARM.com } 44910037SARM gem5 Developers 45010506SAli.Saidi@ARM.com InstIt head_thread = instList[thread_num].begin(); 45110037SARM gem5 Developers 45210506SAli.Saidi@ARM.com DynInstPtr head_inst = (*head_thread); 45310037SARM gem5 Developers 45410506SAli.Saidi@ARM.com assert(head_inst != 0); 45510037SARM gem5 Developers 45610506SAli.Saidi@ARM.com if (head_inst->seqNum < lowest_num) { 45710037SARM gem5 Developers head = head_thread; 45810506SAli.Saidi@ARM.com lowest_num = head_inst->seqNum; 45910037SARM gem5 Developers } 46010506SAli.Saidi@ARM.com } 46110037SARM gem5 Developers 46210506SAli.Saidi@ARM.com if (first_valid) { 46310037SARM gem5 Developers head = instList[0].end(); 46410506SAli.Saidi@ARM.com } 46510037SARM gem5 Developers 46610506SAli.Saidi@ARM.com} 46710037SARM gem5 Developers 46810506SAli.Saidi@ARM.comtemplate <class Impl> 46910037SARM gem5 Developersvoid 47010506SAli.Saidi@ARM.comROB<Impl>::updateTail() 47110037SARM gem5 Developers{ 47210506SAli.Saidi@ARM.com tail = instList[0].end(); 47310037SARM gem5 Developers bool first_valid = true; 47410506SAli.Saidi@ARM.com 47510037SARM gem5 Developers std::list<unsigned>::iterator threads = (*activeThreads).begin(); 47610506SAli.Saidi@ARM.com 47710037SARM gem5 Developers while (threads != (*activeThreads).end()) { 47810506SAli.Saidi@ARM.com unsigned tid = *threads++; 47910037SARM gem5 Developers 48010506SAli.Saidi@ARM.com if (instList[tid].empty()) { 48110037SARM gem5 Developers continue; 48210506SAli.Saidi@ARM.com } 48310037SARM gem5 Developers 48410506SAli.Saidi@ARM.com // If this is the first valid then assign w/out 48510037SARM gem5 Developers // comparison 48610506SAli.Saidi@ARM.com if (first_valid) { 48710037SARM gem5 Developers tail = instList[tid].end(); 48810506SAli.Saidi@ARM.com tail--; 48910037SARM gem5 Developers first_valid = false; 49010506SAli.Saidi@ARM.com continue; 49110037SARM gem5 Developers } 49210506SAli.Saidi@ARM.com 49310037SARM gem5 Developers // Assign new tail if this thread's tail is younger 49410506SAli.Saidi@ARM.com // than our current "tail high" 49510037SARM gem5 Developers InstIt tail_thread = instList[tid].end(); 49610506SAli.Saidi@ARM.com tail_thread--; 49710037SARM gem5 Developers 49810506SAli.Saidi@ARM.com if ((*tail_thread)->seqNum > (*tail)->seqNum) { 49910037SARM gem5 Developers tail = tail_thread; 50010506SAli.Saidi@ARM.com } 50110037SARM gem5 Developers } 50210506SAli.Saidi@ARM.com} 50310037SARM gem5 Developers 50410506SAli.Saidi@ARM.com 50510037SARM gem5 Developerstemplate <class Impl> 50610506SAli.Saidi@ARM.comvoid 50710037SARM gem5 DevelopersROB<Impl>::squash(InstSeqNum squash_num,unsigned tid) 50810506SAli.Saidi@ARM.com{ 50910037SARM gem5 Developers if (isEmpty()) { 51010506SAli.Saidi@ARM.com DPRINTF(ROB, "Does not need to squash due to being empty " 51110037SARM gem5 Developers "[sn:%i]\n", 51210506SAli.Saidi@ARM.com squash_num); 51310037SARM gem5 Developers 51410506SAli.Saidi@ARM.com return; 51510037SARM gem5 Developers } 51610506SAli.Saidi@ARM.com 51710037SARM gem5 Developers DPRINTF(ROB, "Starting to squash within the ROB.\n"); 51810506SAli.Saidi@ARM.com 51910037SARM gem5 Developers robStatus[tid] = ROBSquashing; 52010506SAli.Saidi@ARM.com 52110037SARM gem5 Developers doneSquashing[tid] = false; 52210506SAli.Saidi@ARM.com 52310037SARM gem5 Developers squashedSeqNum[tid] = squash_num; 52410506SAli.Saidi@ARM.com 52510037SARM gem5 Developers if (!instList[tid].empty()) { 52610506SAli.Saidi@ARM.com InstIt tail_thread = instList[tid].end(); 52710037SARM gem5 Developers tail_thread--; 52810506SAli.Saidi@ARM.com 52910037SARM gem5 Developers squashIt[tid] = tail_thread; 53010506SAli.Saidi@ARM.com 53110037SARM gem5 Developers doSquash(tid); 53210506SAli.Saidi@ARM.com } 53310037SARM gem5 Developers} 53410506SAli.Saidi@ARM.com/* 53510037SARM gem5 Developerstemplate <class Impl> 53610506SAli.Saidi@ARM.comtypename Impl::DynInstPtr 53710037SARM gem5 DevelopersROB<Impl>::readHeadInst() 53810506SAli.Saidi@ARM.com{ 53910037SARM gem5 Developers if (numInstsInROB != 0) { 54010506SAli.Saidi@ARM.com assert((*head)->isInROB()==true); 54110037SARM gem5 Developers return *head; 54210506SAli.Saidi@ARM.com } else { 54310037SARM gem5 Developers return dummyInst; 54410506SAli.Saidi@ARM.com } 54510037SARM gem5 Developers} 54610506SAli.Saidi@ARM.com*/ 54710037SARM gem5 Developers 54810506SAli.Saidi@ARM.comtemplate <class Impl> 54910037SARM gem5 Developerstypename Impl::DynInstPtr 55010506SAli.Saidi@ARM.comROB<Impl>::readHeadInst(unsigned tid) 55110037SARM gem5 Developers{ 55210506SAli.Saidi@ARM.com if (threadEntries[tid] != 0) { 55310037SARM gem5 Developers InstIt head_thread = instList[tid].begin(); 55410506SAli.Saidi@ARM.com 55510037SARM gem5 Developers assert((*head_thread)->isInROB()==true); 55610506SAli.Saidi@ARM.com 55710037SARM gem5 Developers return *head_thread; 55810506SAli.Saidi@ARM.com } else { 55910037SARM gem5 Developers return dummyInst; 56010506SAli.Saidi@ARM.com } 56110037SARM gem5 Developers} 56210506SAli.Saidi@ARM.com 56310037SARM gem5 Developers/* 56410506SAli.Saidi@ARM.comtemplate <class Impl> 56510037SARM gem5 Developersuint64_t 56610506SAli.Saidi@ARM.comROB<Impl>::readHeadPC() 56710037SARM gem5 Developers{ 56810506SAli.Saidi@ARM.com //assert(numInstsInROB == countInsts()); 56910037SARM gem5 Developers 57010506SAli.Saidi@ARM.com DynInstPtr head_inst = *head; 57110037SARM gem5 Developers 57210506SAli.Saidi@ARM.com return head_inst->readPC(); 57310037SARM gem5 Developers} 57410506SAli.Saidi@ARM.com 57510037SARM gem5 Developerstemplate <class Impl> 57610506SAli.Saidi@ARM.comuint64_t 57710037SARM gem5 DevelopersROB<Impl>::readHeadPC(unsigned tid) 57810506SAli.Saidi@ARM.com{ 57910037SARM gem5 Developers //assert(numInstsInROB == countInsts()); 58010506SAli.Saidi@ARM.com InstIt head_thread = instList[tid].begin(); 58110037SARM gem5 Developers 58210506SAli.Saidi@ARM.com return (*head_thread)->readPC(); 58310037SARM gem5 Developers} 58410506SAli.Saidi@ARM.com 58510037SARM gem5 Developers 58610506SAli.Saidi@ARM.comtemplate <class Impl> 58710037SARM gem5 Developersuint64_t 58810506SAli.Saidi@ARM.comROB<Impl>::readHeadNextPC() 58910037SARM gem5 Developers{ 59010506SAli.Saidi@ARM.com //assert(numInstsInROB == countInsts()); 59110037SARM gem5 Developers 59210506SAli.Saidi@ARM.com DynInstPtr head_inst = *head; 59310037SARM gem5 Developers 59410506SAli.Saidi@ARM.com return head_inst->readNextPC(); 59510037SARM gem5 Developers} 59610506SAli.Saidi@ARM.com 59710037SARM gem5 Developerstemplate <class Impl> 59810506SAli.Saidi@ARM.comuint64_t 59910037SARM gem5 DevelopersROB<Impl>::readHeadNextPC(unsigned tid) 60010506SAli.Saidi@ARM.com{ 60110037SARM gem5 Developers //assert(numInstsInROB == countInsts()); 60210506SAli.Saidi@ARM.com InstIt head_thread = instList[tid].begin(); 60310037SARM gem5 Developers 60410506SAli.Saidi@ARM.com return (*head_thread)->readNextPC(); 60510037SARM gem5 Developers} 60610506SAli.Saidi@ARM.com 60710037SARM gem5 Developerstemplate <class Impl> 60810506SAli.Saidi@ARM.comInstSeqNum 60910037SARM gem5 DevelopersROB<Impl>::readHeadSeqNum() 61010506SAli.Saidi@ARM.com{ 61110037SARM gem5 Developers //assert(numInstsInROB == countInsts()); 61210506SAli.Saidi@ARM.com DynInstPtr head_inst = *head; 61310037SARM gem5 Developers 61410506SAli.Saidi@ARM.com return head_inst->seqNum; 61510037SARM gem5 Developers} 61610506SAli.Saidi@ARM.com 61710037SARM gem5 Developerstemplate <class Impl> 61810506SAli.Saidi@ARM.comInstSeqNum 61910037SARM gem5 DevelopersROB<Impl>::readHeadSeqNum(unsigned tid) 62010506SAli.Saidi@ARM.com{ 62110037SARM gem5 Developers InstIt head_thread = instList[tid].begin(); 62210506SAli.Saidi@ARM.com 62310037SARM gem5 Developers return ((*head_thread)->seqNum); 62410506SAli.Saidi@ARM.com} 62510037SARM gem5 Developers 62610506SAli.Saidi@ARM.comtemplate <class Impl> 62710037SARM gem5 Developerstypename Impl::DynInstPtr 62810506SAli.Saidi@ARM.comROB<Impl>::readTailInst() 62910037SARM gem5 Developers{ 63010506SAli.Saidi@ARM.com //assert(numInstsInROB == countInsts()); 63110037SARM gem5 Developers //assert(tail != instList[0].end()); 63210506SAli.Saidi@ARM.com 63310037SARM gem5 Developers return (*tail); 63410506SAli.Saidi@ARM.com} 63510037SARM gem5 Developers*/ 63610506SAli.Saidi@ARM.comtemplate <class Impl> 63710037SARM gem5 Developerstypename Impl::DynInstPtr 63810506SAli.Saidi@ARM.comROB<Impl>::readTailInst(unsigned tid) 63910037SARM gem5 Developers{ 64010506SAli.Saidi@ARM.com //assert(tail_thread[tid] != instList[tid].end()); 64110037SARM gem5 Developers 64210506SAli.Saidi@ARM.com InstIt tail_thread = instList[tid].end(); 64310037SARM gem5 Developers tail_thread--; 64410506SAli.Saidi@ARM.com 64510037SARM gem5 Developers return *tail_thread; 64610506SAli.Saidi@ARM.com} 64710037SARM gem5 Developers 64810506SAli.Saidi@ARM.com/* 64910037SARM gem5 Developerstemplate <class Impl> 65010506SAli.Saidi@ARM.comuint64_t 65110037SARM gem5 DevelopersROB<Impl>::readTailPC() 65210506SAli.Saidi@ARM.com{ 65310037SARM gem5 Developers //assert(numInstsInROB == countInsts()); 65410506SAli.Saidi@ARM.com 65510037SARM gem5 Developers //assert(tail != instList[0].end()); 65610506SAli.Saidi@ARM.com 65710037SARM gem5 Developers return (*tail)->readPC(); 65810506SAli.Saidi@ARM.com} 65910037SARM gem5 Developers 66010506SAli.Saidi@ARM.comtemplate <class Impl> 66110037SARM gem5 Developersuint64_t 66210506SAli.Saidi@ARM.comROB<Impl>::readTailPC(unsigned tid) 66310037SARM gem5 Developers{ 66410506SAli.Saidi@ARM.com //assert(tail_thread[tid] != instList[tid].end()); 66510037SARM gem5 Developers 66610506SAli.Saidi@ARM.com InstIt tail_thread = instList[tid].end(); 66710037SARM gem5 Developers tail_thread--; 66810506SAli.Saidi@ARM.com 66910037SARM gem5 Developers return (*tail_thread)->readPC(); 67010506SAli.Saidi@ARM.com} 67110037SARM gem5 Developers 67210506SAli.Saidi@ARM.comtemplate <class Impl> 67310037SARM gem5 DevelopersInstSeqNum 67410506SAli.Saidi@ARM.comROB<Impl>::readTailSeqNum() 67510037SARM gem5 Developers{ 67610506SAli.Saidi@ARM.com // Return the last sequence number that has not been squashed. Other 67710037SARM gem5 Developers // stages can use it to squash any instructions younger than the current 67810506SAli.Saidi@ARM.com // tail. 67910037SARM gem5 Developers return (*tail)->seqNum; 68010506SAli.Saidi@ARM.com} 68110037SARM gem5 Developers 68210506SAli.Saidi@ARM.comtemplate <class Impl> 68310037SARM gem5 DevelopersInstSeqNum 68410506SAli.Saidi@ARM.comROB<Impl>::readTailSeqNum(unsigned tid) 68510037SARM gem5 Developers{ 68610506SAli.Saidi@ARM.com // Return the last sequence number that has not been squashed. Other 68710037SARM gem5 Developers // stages can use it to squash any instructions younger than the current 68810506SAli.Saidi@ARM.com // tail. 68910037SARM gem5 Developers // assert(tail_thread[tid] != instList[tid].end()); 69010506SAli.Saidi@ARM.com 69110037SARM gem5 Developers InstIt tail_thread = instList[tid].end(); 69210506SAli.Saidi@ARM.com tail_thread--; 69310037SARM gem5 Developers 69410506SAli.Saidi@ARM.com return (*tail_thread)->seqNum; 69510037SARM gem5 Developers} 69610506SAli.Saidi@ARM.com*/ 69710037SARM gem5 Developers