rob_impl.hh revision 14016
15132Sgblack@eecs.umich.edu/* 25132Sgblack@eecs.umich.edu * Copyright (c) 2012 ARM Limited 35132Sgblack@eecs.umich.edu * All rights reserved 45132Sgblack@eecs.umich.edu * 57087Snate@binkert.org * The license below extends only to copyright in the software and shall 67087Snate@binkert.org * not be construed as granting a license to any other intellectual 77087Snate@binkert.org * property including but not limited to intellectual property relating 87087Snate@binkert.org * to a hardware implementation of the functionality of the software 97087Snate@binkert.org * licensed hereunder. You may use the software subject to the license 107087Snate@binkert.org * terms below provided that you ensure that this notice is replicated 117087Snate@binkert.org * unmodified and in its entirety in all distributions of the software, 127087Snate@binkert.org * modified or unmodified, in source code or in binary form. 135132Sgblack@eecs.umich.edu * 147087Snate@binkert.org * Copyright (c) 2004-2006 The Regents of The University of Michigan 157087Snate@binkert.org * All rights reserved. 167087Snate@binkert.org * 177087Snate@binkert.org * Redistribution and use in source and binary forms, with or without 187087Snate@binkert.org * modification, are permitted provided that the following conditions are 197087Snate@binkert.org * met: redistributions of source code must retain the above copyright 207087Snate@binkert.org * notice, this list of conditions and the following disclaimer; 217087Snate@binkert.org * redistributions in binary form must reproduce the above copyright 225132Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 237087Snate@binkert.org * documentation and/or other materials provided with the distribution; 245132Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 255132Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 265132Sgblack@eecs.umich.edu * this software without specific prior written permission. 275132Sgblack@eecs.umich.edu * 285132Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 295132Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 305132Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 315132Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 325132Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 335132Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 345132Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 355132Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 365132Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 375132Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 385132Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 395132Sgblack@eecs.umich.edu * 4011793Sbrandon.potter@amd.com * Authors: Kevin Lim 4111793Sbrandon.potter@amd.com * Korey Sewell 4211793Sbrandon.potter@amd.com */ 438229Snate@binkert.org 445612Sgblack@eecs.umich.edu#ifndef __CPU_O3_ROB_IMPL_HH__ 4511793Sbrandon.potter@amd.com#define __CPU_O3_ROB_IMPL_HH__ 468229Snate@binkert.org 4711793Sbrandon.potter@amd.com#include <list> 485132Sgblack@eecs.umich.edu 495132Sgblack@eecs.umich.edu#include "base/logging.hh" 505132Sgblack@eecs.umich.edu#include "cpu/o3/rob.hh" 515299Sgblack@eecs.umich.edu#include "debug/Fetch.hh" 528706Sandreas.hansson@arm.com#include "debug/ROB.hh" 535132Sgblack@eecs.umich.edu#include "params/DerivO3CPU.hh" 545132Sgblack@eecs.umich.edu 555132Sgblack@eecs.umich.eduusing namespace std; 565299Sgblack@eecs.umich.edu 575299Sgblack@eecs.umich.edutemplate <class Impl> 585132Sgblack@eecs.umich.eduROB<Impl>::ROB(O3CPU *_cpu, DerivO3CPUParams *params) 595625Sgblack@eecs.umich.edu : robPolicy(params->smtROBPolicy), 605625Sgblack@eecs.umich.edu cpu(_cpu), 615625Sgblack@eecs.umich.edu numEntries(params->numROBEntries), 625627Sgblack@eecs.umich.edu squashWidth(params->squashWidth), 635627Sgblack@eecs.umich.edu numInstsInROB(0), 647704Sgblack@eecs.umich.edu numThreads(params->numThreads) 657704Sgblack@eecs.umich.edu{ 665132Sgblack@eecs.umich.edu //Figure out rob policy 6710554Salexandru.dutu@amd.com if (robPolicy == SMTQueuePolicy::Dynamic) { 6810554Salexandru.dutu@amd.com //Set Max Entries to Total ROB Capacity 696220Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; tid++) { 706220Sgblack@eecs.umich.edu maxEntries[tid] = numEntries; 716220Sgblack@eecs.umich.edu } 726220Sgblack@eecs.umich.edu 736220Sgblack@eecs.umich.edu } else if (robPolicy == SMTQueuePolicy::Partitioned) { 746220Sgblack@eecs.umich.edu DPRINTF(Fetch, "ROB sharing policy set to Partitioned\n"); 756220Sgblack@eecs.umich.edu 766220Sgblack@eecs.umich.edu //@todo:make work if part_amt doesnt divide evenly. 776220Sgblack@eecs.umich.edu int part_amt = numEntries / numThreads; 786220Sgblack@eecs.umich.edu 796222Sgblack@eecs.umich.edu //Divide ROB up evenly 806222Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; tid++) { 816222Sgblack@eecs.umich.edu maxEntries[tid] = part_amt; 826222Sgblack@eecs.umich.edu } 836222Sgblack@eecs.umich.edu 846222Sgblack@eecs.umich.edu } else if (robPolicy == SMTQueuePolicy::Threshold) { 856222Sgblack@eecs.umich.edu DPRINTF(Fetch, "ROB sharing policy set to Threshold\n"); 866222Sgblack@eecs.umich.edu 876222Sgblack@eecs.umich.edu int threshold = params->smtROBThreshold;; 886222Sgblack@eecs.umich.edu 896220Sgblack@eecs.umich.edu //Divide up by threshold amount 906220Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; tid++) { 916220Sgblack@eecs.umich.edu maxEntries[tid] = threshold; 926222Sgblack@eecs.umich.edu } 936220Sgblack@eecs.umich.edu } 946222Sgblack@eecs.umich.edu 956220Sgblack@eecs.umich.edu for (ThreadID tid = numThreads; tid < Impl::MaxThreads; tid++) { 966220Sgblack@eecs.umich.edu maxEntries[tid] = 0; 976222Sgblack@eecs.umich.edu } 986220Sgblack@eecs.umich.edu 996220Sgblack@eecs.umich.edu resetState(); 1006220Sgblack@eecs.umich.edu} 1016220Sgblack@eecs.umich.edu 1026222Sgblack@eecs.umich.edutemplate <class Impl> 1036220Sgblack@eecs.umich.eduvoid 1046220Sgblack@eecs.umich.eduROB<Impl>::resetState() 1056220Sgblack@eecs.umich.edu{ 1066220Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < Impl::MaxThreads; tid++) { 1076220Sgblack@eecs.umich.edu threadEntries[tid] = 0; 1086220Sgblack@eecs.umich.edu squashIt[tid] = instList[tid].end(); 1096220Sgblack@eecs.umich.edu squashedSeqNum[tid] = 0; 1106220Sgblack@eecs.umich.edu doneSquashing[tid] = true; 1116220Sgblack@eecs.umich.edu } 1126220Sgblack@eecs.umich.edu numInstsInROB = 0; 1135299Sgblack@eecs.umich.edu 1147532Ssteve.reinhardt@amd.com // Initialize the "universal" ROB head & tail point to invalid 1155299Sgblack@eecs.umich.edu // pointers 1167532Ssteve.reinhardt@amd.com head = instList[0].end(); 1177532Ssteve.reinhardt@amd.com tail = instList[0].end(); 1188958Sgblack@eecs.umich.edu} 1198958Sgblack@eecs.umich.edu 1208958Sgblack@eecs.umich.edutemplate <class Impl> 1218706Sandreas.hansson@arm.comstd::string 1228706Sandreas.hansson@arm.comROB<Impl>::name() const 1238706Sandreas.hansson@arm.com{ 1246220Sgblack@eecs.umich.edu return cpu->name() + ".rob"; 1255299Sgblack@eecs.umich.edu} 1265299Sgblack@eecs.umich.edu 1275299Sgblack@eecs.umich.edutemplate <class Impl> 1285299Sgblack@eecs.umich.eduvoid 1295299Sgblack@eecs.umich.eduROB<Impl>::setActiveThreads(list<ThreadID> *at_ptr) 1305299Sgblack@eecs.umich.edu{ 1315299Sgblack@eecs.umich.edu DPRINTF(ROB, "Setting active threads list pointer.\n"); 1325299Sgblack@eecs.umich.edu activeThreads = at_ptr; 1335299Sgblack@eecs.umich.edu} 1345299Sgblack@eecs.umich.edu 1355299Sgblack@eecs.umich.edutemplate <class Impl> 1365299Sgblack@eecs.umich.eduvoid 1375299Sgblack@eecs.umich.eduROB<Impl>::drainSanityCheck() const 1385299Sgblack@eecs.umich.edu{ 1395299Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; tid++) 1405299Sgblack@eecs.umich.edu assert(instList[tid].empty()); 1415299Sgblack@eecs.umich.edu assert(isEmpty()); 1425299Sgblack@eecs.umich.edu} 1435299Sgblack@eecs.umich.edu 1445299Sgblack@eecs.umich.edutemplate <class Impl> 1455299Sgblack@eecs.umich.eduvoid 1465299Sgblack@eecs.umich.eduROB<Impl>::takeOverFrom() 1475299Sgblack@eecs.umich.edu{ 1486220Sgblack@eecs.umich.edu resetState(); 1495299Sgblack@eecs.umich.edu} 1505299Sgblack@eecs.umich.edu 1518852Sandreas.hansson@arm.comtemplate <class Impl> 1528852Sandreas.hansson@arm.comvoid 1536220Sgblack@eecs.umich.eduROB<Impl>::resetEntries() 1545299Sgblack@eecs.umich.edu{ 15510554Salexandru.dutu@amd.com if (robPolicy != SMTQueuePolicy::Dynamic || numThreads > 1) { 15610554Salexandru.dutu@amd.com auto active_threads = activeThreads->size(); 15710554Salexandru.dutu@amd.com 15810554Salexandru.dutu@amd.com list<ThreadID>::iterator threads = activeThreads->begin(); 15910554Salexandru.dutu@amd.com list<ThreadID>::iterator end = activeThreads->end(); 16010554Salexandru.dutu@amd.com 16110554Salexandru.dutu@amd.com while (threads != end) { 16210554Salexandru.dutu@amd.com ThreadID tid = *threads++; 16310554Salexandru.dutu@amd.com 16410554Salexandru.dutu@amd.com if (robPolicy == SMTQueuePolicy::Partitioned) { 16510554Salexandru.dutu@amd.com maxEntries[tid] = numEntries / active_threads; 16610554Salexandru.dutu@amd.com } else if (robPolicy == SMTQueuePolicy::Threshold && 16710554Salexandru.dutu@amd.com active_threads == 1) { 16810554Salexandru.dutu@amd.com maxEntries[tid] = numEntries; 16910554Salexandru.dutu@amd.com } 1705299Sgblack@eecs.umich.edu } 17110554Salexandru.dutu@amd.com } 1726220Sgblack@eecs.umich.edu} 17310554Salexandru.dutu@amd.com 1745299Sgblack@eecs.umich.edutemplate <class Impl> 1755299Sgblack@eecs.umich.eduint 1765299Sgblack@eecs.umich.eduROB<Impl>::entryAmount(ThreadID num_threads) 1775299Sgblack@eecs.umich.edu{ 1785299Sgblack@eecs.umich.edu if (robPolicy == SMTQueuePolicy::Partitioned) { 1798852Sandreas.hansson@arm.com return numEntries / num_threads; 1808852Sandreas.hansson@arm.com } else { 1815299Sgblack@eecs.umich.edu return 0; 1826220Sgblack@eecs.umich.edu } 1836220Sgblack@eecs.umich.edu} 1846220Sgblack@eecs.umich.edu 1856220Sgblack@eecs.umich.edutemplate <class Impl> 1866220Sgblack@eecs.umich.eduint 1876220Sgblack@eecs.umich.eduROB<Impl>::countInsts() 1886220Sgblack@eecs.umich.edu{ 1896220Sgblack@eecs.umich.edu int total = 0; 19010554Salexandru.dutu@amd.com 1916220Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; tid++) 1928852Sandreas.hansson@arm.com total += countInsts(tid); 1938852Sandreas.hansson@arm.com 1946220Sgblack@eecs.umich.edu return total; 1956220Sgblack@eecs.umich.edu} 1966220Sgblack@eecs.umich.edu 1976712Snate@binkert.orgtemplate <class Impl> 1986220Sgblack@eecs.umich.edusize_t 1996220Sgblack@eecs.umich.eduROB<Impl>::countInsts(ThreadID tid) 2006220Sgblack@eecs.umich.edu{ 2016220Sgblack@eecs.umich.edu return instList[tid].size(); 2026220Sgblack@eecs.umich.edu} 2036220Sgblack@eecs.umich.edu 2046220Sgblack@eecs.umich.edutemplate <class Impl> 2056220Sgblack@eecs.umich.eduvoid 2066220Sgblack@eecs.umich.eduROB<Impl>::insertInst(const DynInstPtr &inst) 2076220Sgblack@eecs.umich.edu{ 2086220Sgblack@eecs.umich.edu assert(inst); 2096220Sgblack@eecs.umich.edu 21010554Salexandru.dutu@amd.com robWrites++; 2116220Sgblack@eecs.umich.edu 2128852Sandreas.hansson@arm.com DPRINTF(ROB, "Adding inst PC %s to the ROB.\n", inst->pcState()); 2138852Sandreas.hansson@arm.com 2146220Sgblack@eecs.umich.edu assert(numInstsInROB != numEntries); 2156220Sgblack@eecs.umich.edu 2166220Sgblack@eecs.umich.edu ThreadID tid = inst->threadNumber; 2176220Sgblack@eecs.umich.edu 2186220Sgblack@eecs.umich.edu instList[tid].push_back(inst); 2196220Sgblack@eecs.umich.edu 2206220Sgblack@eecs.umich.edu //Set Up head iterator if this is the 1st instruction in the ROB 2216220Sgblack@eecs.umich.edu if (numInstsInROB == 0) { 2225299Sgblack@eecs.umich.edu head = instList[tid].begin(); 2235299Sgblack@eecs.umich.edu assert((*head) == inst); 2245299Sgblack@eecs.umich.edu } 2255299Sgblack@eecs.umich.edu 2265299Sgblack@eecs.umich.edu //Must Decrement for iterator to actually be valid since __.end() 2275299Sgblack@eecs.umich.edu //actually points to 1 after the last inst 2285299Sgblack@eecs.umich.edu tail = instList[tid].end(); 2295299Sgblack@eecs.umich.edu tail--; 2305299Sgblack@eecs.umich.edu 2315299Sgblack@eecs.umich.edu inst->setInROB(); 2325299Sgblack@eecs.umich.edu 2335299Sgblack@eecs.umich.edu ++numInstsInROB; 2345299Sgblack@eecs.umich.edu ++threadEntries[tid]; 2355299Sgblack@eecs.umich.edu 2365299Sgblack@eecs.umich.edu assert((*tail) == inst); 2375299Sgblack@eecs.umich.edu 2385299Sgblack@eecs.umich.edu DPRINTF(ROB, "[tid:%i] Now has %d instructions.\n", tid, threadEntries[tid]); 2395299Sgblack@eecs.umich.edu} 2405299Sgblack@eecs.umich.edu 2415299Sgblack@eecs.umich.edutemplate <class Impl> 2428852Sandreas.hansson@arm.comvoid 2435299Sgblack@eecs.umich.eduROB<Impl>::retireHead(ThreadID tid) 2445299Sgblack@eecs.umich.edu{ 2455299Sgblack@eecs.umich.edu robWrites++; 2468852Sandreas.hansson@arm.com 2475299Sgblack@eecs.umich.edu assert(numInstsInROB > 0); 2485299Sgblack@eecs.umich.edu 2495299Sgblack@eecs.umich.edu // Get the head ROB instruction by copying it and remove it from the list 2505299Sgblack@eecs.umich.edu InstIt head_it = instList[tid].begin(); 2515299Sgblack@eecs.umich.edu 2525299Sgblack@eecs.umich.edu DynInstPtr head_inst = std::move(*head_it); 2538852Sandreas.hansson@arm.com instList[tid].erase(head_it); 2548852Sandreas.hansson@arm.com 2555299Sgblack@eecs.umich.edu assert(head_inst->readyToCommit()); 2565299Sgblack@eecs.umich.edu 2575299Sgblack@eecs.umich.edu DPRINTF(ROB, "[tid:%i] Retiring head instruction, " 2585299Sgblack@eecs.umich.edu "instruction PC %s, [sn:%llu]\n", tid, head_inst->pcState(), 2598852Sandreas.hansson@arm.com head_inst->seqNum); 2608852Sandreas.hansson@arm.com 2615299Sgblack@eecs.umich.edu --numInstsInROB; 2625299Sgblack@eecs.umich.edu --threadEntries[tid]; 2635299Sgblack@eecs.umich.edu 2645299Sgblack@eecs.umich.edu head_inst->clearInROB(); 2655299Sgblack@eecs.umich.edu head_inst->setCommitted(); 2665299Sgblack@eecs.umich.edu 2675299Sgblack@eecs.umich.edu //Update "Global" Head of ROB 2685299Sgblack@eecs.umich.edu updateHead(); 2695299Sgblack@eecs.umich.edu 2705299Sgblack@eecs.umich.edu // @todo: A special case is needed if the instruction being 2718852Sandreas.hansson@arm.com // retired is the only instruction in the ROB; otherwise the tail 2728852Sandreas.hansson@arm.com // iterator will become invalidated. 2735299Sgblack@eecs.umich.edu cpu->removeFrontInst(head_inst); 2745299Sgblack@eecs.umich.edu} 2755299Sgblack@eecs.umich.edu 2765299Sgblack@eecs.umich.edutemplate <class Impl> 2775299Sgblack@eecs.umich.edubool 2785299Sgblack@eecs.umich.eduROB<Impl>::isHeadReady(ThreadID tid) 2795299Sgblack@eecs.umich.edu{ 2806220Sgblack@eecs.umich.edu robReads++; 2815299Sgblack@eecs.umich.edu if (threadEntries[tid] != 0) { 2825299Sgblack@eecs.umich.edu return instList[tid].front()->readyToCommit(); 2836220Sgblack@eecs.umich.edu } 2845299Sgblack@eecs.umich.edu 2855299Sgblack@eecs.umich.edu return false; 2866220Sgblack@eecs.umich.edu} 2875299Sgblack@eecs.umich.edu 2886220Sgblack@eecs.umich.edutemplate <class Impl> 2895299Sgblack@eecs.umich.edubool 2905299Sgblack@eecs.umich.eduROB<Impl>::canCommit() 2916220Sgblack@eecs.umich.edu{ 2925299Sgblack@eecs.umich.edu //@todo: set ActiveThreads through ROB or CPU 2935299Sgblack@eecs.umich.edu list<ThreadID>::iterator threads = activeThreads->begin(); 2946220Sgblack@eecs.umich.edu list<ThreadID>::iterator end = activeThreads->end(); 2955299Sgblack@eecs.umich.edu 2966220Sgblack@eecs.umich.edu while (threads != end) { 2975299Sgblack@eecs.umich.edu ThreadID tid = *threads++; 2985299Sgblack@eecs.umich.edu 2996220Sgblack@eecs.umich.edu if (isHeadReady(tid)) { 3006220Sgblack@eecs.umich.edu return true; 3016220Sgblack@eecs.umich.edu } 3026220Sgblack@eecs.umich.edu } 3036220Sgblack@eecs.umich.edu 3046220Sgblack@eecs.umich.edu return false; 3056220Sgblack@eecs.umich.edu} 3066220Sgblack@eecs.umich.edu 3076220Sgblack@eecs.umich.edutemplate <class Impl> 3085299Sgblack@eecs.umich.eduunsigned 3095299Sgblack@eecs.umich.eduROB<Impl>::numFreeEntries() 3105299Sgblack@eecs.umich.edu{ 3116220Sgblack@eecs.umich.edu return numEntries - numInstsInROB; 3125299Sgblack@eecs.umich.edu} 3137720Sgblack@eecs.umich.edu 3145299Sgblack@eecs.umich.edutemplate <class Impl> 3155299Sgblack@eecs.umich.eduunsigned 3165334Sgblack@eecs.umich.eduROB<Impl>::numFreeEntries(ThreadID tid) 3175615Sgblack@eecs.umich.edu{ 3185625Sgblack@eecs.umich.edu return maxEntries[tid] - threadEntries[tid]; 3195615Sgblack@eecs.umich.edu} 3205334Sgblack@eecs.umich.edu 3215625Sgblack@eecs.umich.edutemplate <class Impl> 3225625Sgblack@eecs.umich.eduvoid 3235625Sgblack@eecs.umich.eduROB<Impl>::doSquash(ThreadID tid) 3245625Sgblack@eecs.umich.edu{ 3255625Sgblack@eecs.umich.edu robWrites++; 3265625Sgblack@eecs.umich.edu DPRINTF(ROB, "[tid:%i] Squashing instructions until [sn:%llu].\n", 3275625Sgblack@eecs.umich.edu tid, squashedSeqNum[tid]); 3285299Sgblack@eecs.umich.edu 3295299Sgblack@eecs.umich.edu assert(squashIt[tid] != instList[tid].end()); 3305334Sgblack@eecs.umich.edu 3315615Sgblack@eecs.umich.edu if ((*squashIt[tid])->seqNum < squashedSeqNum[tid]) { 3325615Sgblack@eecs.umich.edu DPRINTF(ROB, "[tid:%i] Done squashing instructions.\n", 3335334Sgblack@eecs.umich.edu tid); 3345334Sgblack@eecs.umich.edu 3355334Sgblack@eecs.umich.edu squashIt[tid] = instList[tid].end(); 3365615Sgblack@eecs.umich.edu 3375615Sgblack@eecs.umich.edu doneSquashing[tid] = true; 3385615Sgblack@eecs.umich.edu return; 3395334Sgblack@eecs.umich.edu } 3408706Sandreas.hansson@arm.com 3415615Sgblack@eecs.umich.edu bool robTailUpdate = false; 3425615Sgblack@eecs.umich.edu 3435615Sgblack@eecs.umich.edu for (int numSquashed = 0; 3445615Sgblack@eecs.umich.edu numSquashed < squashWidth && 3455615Sgblack@eecs.umich.edu squashIt[tid] != instList[tid].end() && 3465334Sgblack@eecs.umich.edu (*squashIt[tid])->seqNum > squashedSeqNum[tid]; 3475334Sgblack@eecs.umich.edu ++numSquashed) 3485625Sgblack@eecs.umich.edu { 3495625Sgblack@eecs.umich.edu DPRINTF(ROB, "[tid:%i] Squashing instruction PC %s, seq num %i.\n", 3505625Sgblack@eecs.umich.edu (*squashIt[tid])->threadNumber, 3515625Sgblack@eecs.umich.edu (*squashIt[tid])->pcState(), 3525625Sgblack@eecs.umich.edu (*squashIt[tid])->seqNum); 3535625Sgblack@eecs.umich.edu 3545625Sgblack@eecs.umich.edu // Mark the instruction as squashed, and ready to commit so that 3555625Sgblack@eecs.umich.edu // it can drain out of the pipeline. 3565625Sgblack@eecs.umich.edu (*squashIt[tid])->setSquashed(); 3575625Sgblack@eecs.umich.edu 3585625Sgblack@eecs.umich.edu (*squashIt[tid])->setCanCommit(); 3595625Sgblack@eecs.umich.edu 3605625Sgblack@eecs.umich.edu 3618706Sandreas.hansson@arm.com if (squashIt[tid] == instList[tid].begin()) { 3625625Sgblack@eecs.umich.edu DPRINTF(ROB, "Reached head of instruction list while " 3638706Sandreas.hansson@arm.com "squashing.\n"); 3645625Sgblack@eecs.umich.edu 3655625Sgblack@eecs.umich.edu squashIt[tid] = instList[tid].end(); 3665625Sgblack@eecs.umich.edu 3675625Sgblack@eecs.umich.edu doneSquashing[tid] = true; 3685625Sgblack@eecs.umich.edu 3695625Sgblack@eecs.umich.edu return; 3705625Sgblack@eecs.umich.edu } 3715625Sgblack@eecs.umich.edu 3725625Sgblack@eecs.umich.edu InstIt tail_thread = instList[tid].end(); 3735625Sgblack@eecs.umich.edu tail_thread--; 3745334Sgblack@eecs.umich.edu 3755132Sgblack@eecs.umich.edu if ((*squashIt[tid]) == (*tail_thread)) 3765132Sgblack@eecs.umich.edu robTailUpdate = true; 3775334Sgblack@eecs.umich.edu 3785132Sgblack@eecs.umich.edu squashIt[tid]--; 3795132Sgblack@eecs.umich.edu } 3805132Sgblack@eecs.umich.edu 3815132Sgblack@eecs.umich.edu 3825132Sgblack@eecs.umich.edu // Check if ROB is done squashing. 3835132Sgblack@eecs.umich.edu if ((*squashIt[tid])->seqNum <= squashedSeqNum[tid]) { 3845132Sgblack@eecs.umich.edu DPRINTF(ROB, "[tid:%i] Done squashing instructions.\n", 385 tid); 386 387 squashIt[tid] = instList[tid].end(); 388 389 doneSquashing[tid] = true; 390 } 391 392 if (robTailUpdate) { 393 updateTail(); 394 } 395} 396 397 398template <class Impl> 399void 400ROB<Impl>::updateHead() 401{ 402 InstSeqNum lowest_num = 0; 403 bool first_valid = true; 404 405 // @todo: set ActiveThreads through ROB or CPU 406 list<ThreadID>::iterator threads = activeThreads->begin(); 407 list<ThreadID>::iterator end = activeThreads->end(); 408 409 while (threads != end) { 410 ThreadID tid = *threads++; 411 412 if (instList[tid].empty()) 413 continue; 414 415 if (first_valid) { 416 head = instList[tid].begin(); 417 lowest_num = (*head)->seqNum; 418 first_valid = false; 419 continue; 420 } 421 422 InstIt head_thread = instList[tid].begin(); 423 424 DynInstPtr head_inst = (*head_thread); 425 426 assert(head_inst != 0); 427 428 if (head_inst->seqNum < lowest_num) { 429 head = head_thread; 430 lowest_num = head_inst->seqNum; 431 } 432 } 433 434 if (first_valid) { 435 head = instList[0].end(); 436 } 437 438} 439 440template <class Impl> 441void 442ROB<Impl>::updateTail() 443{ 444 tail = instList[0].end(); 445 bool first_valid = true; 446 447 list<ThreadID>::iterator threads = activeThreads->begin(); 448 list<ThreadID>::iterator end = activeThreads->end(); 449 450 while (threads != end) { 451 ThreadID tid = *threads++; 452 453 if (instList[tid].empty()) { 454 continue; 455 } 456 457 // If this is the first valid then assign w/out 458 // comparison 459 if (first_valid) { 460 tail = instList[tid].end(); 461 tail--; 462 first_valid = false; 463 continue; 464 } 465 466 // Assign new tail if this thread's tail is younger 467 // than our current "tail high" 468 InstIt tail_thread = instList[tid].end(); 469 tail_thread--; 470 471 if ((*tail_thread)->seqNum > (*tail)->seqNum) { 472 tail = tail_thread; 473 } 474 } 475} 476 477 478template <class Impl> 479void 480ROB<Impl>::squash(InstSeqNum squash_num, ThreadID tid) 481{ 482 if (isEmpty(tid)) { 483 DPRINTF(ROB, "Does not need to squash due to being empty " 484 "[sn:%llu]\n", 485 squash_num); 486 487 return; 488 } 489 490 DPRINTF(ROB, "Starting to squash within the ROB.\n"); 491 492 robStatus[tid] = ROBSquashing; 493 494 doneSquashing[tid] = false; 495 496 squashedSeqNum[tid] = squash_num; 497 498 if (!instList[tid].empty()) { 499 InstIt tail_thread = instList[tid].end(); 500 tail_thread--; 501 502 squashIt[tid] = tail_thread; 503 504 doSquash(tid); 505 } 506} 507 508template <class Impl> 509const typename Impl::DynInstPtr& 510ROB<Impl>::readHeadInst(ThreadID tid) 511{ 512 if (threadEntries[tid] != 0) { 513 InstIt head_thread = instList[tid].begin(); 514 515 assert((*head_thread)->isInROB()); 516 517 return *head_thread; 518 } else { 519 return dummyInst; 520 } 521} 522 523template <class Impl> 524typename Impl::DynInstPtr 525ROB<Impl>::readTailInst(ThreadID tid) 526{ 527 InstIt tail_thread = instList[tid].end(); 528 tail_thread--; 529 530 return *tail_thread; 531} 532 533template <class Impl> 534void 535ROB<Impl>::regStats() 536{ 537 using namespace Stats; 538 robReads 539 .name(name() + ".rob_reads") 540 .desc("The number of ROB reads"); 541 542 robWrites 543 .name(name() + ".rob_writes") 544 .desc("The number of ROB writes"); 545} 546 547template <class Impl> 548typename Impl::DynInstPtr 549ROB<Impl>::findInst(ThreadID tid, InstSeqNum squash_inst) 550{ 551 for (InstIt it = instList[tid].begin(); it != instList[tid].end(); it++) { 552 if ((*it)->seqNum == squash_inst) { 553 return *it; 554 } 555 } 556 return NULL; 557} 558 559#endif//__CPU_O3_ROB_IMPL_HH__ 560