commit_impl.hh revision 7720
12381SN/A/* 213732Snikos.nikoleris@arm.com * Copyright (c) 2004-2006 The Regents of The University of Michigan 38949Sandreas.hansson@arm.com * All rights reserved. 48949Sandreas.hansson@arm.com * 58949Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 68949Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are 78949Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright 88949Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer; 98949Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright 108949Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the 118949Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution; 128949Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its 138949Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from 142592SN/A * this software without specific prior written permission. 1510975Sdavid.hashe@amd.com * 162381SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172381SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182381SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192381SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202381SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212381SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222381SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232381SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242381SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252381SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262381SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272381SN/A * 282381SN/A * Authors: Kevin Lim 292381SN/A * Korey Sewell 302381SN/A */ 312381SN/A 322381SN/A#include <algorithm> 332381SN/A#include <string> 342381SN/A 352381SN/A#include "arch/utility.hh" 362381SN/A#include "base/cp_annotate.hh" 372381SN/A#include "base/loader/symtab.hh" 382381SN/A#include "base/timebuf.hh" 392381SN/A#include "config/full_system.hh" 402665Ssaidi@eecs.umich.edu#include "config/the_isa.hh" 412665Ssaidi@eecs.umich.edu#include "config/use_checker.hh" 422665Ssaidi@eecs.umich.edu#include "cpu/exetrace.hh" 432665Ssaidi@eecs.umich.edu#include "cpu/o3/commit.hh" 449031Sandreas.hansson@arm.com#include "cpu/o3/thread_state.hh" 4512349Snikos.nikoleris@arm.com#include "params/DerivO3CPU.hh" 462381SN/A 472381SN/A#if USE_CHECKER 482381SN/A#include "cpu/checker/cpu.hh" 492381SN/A#endif 502662Sstever@eecs.umich.edu 512381SN/Ausing namespace std; 522381SN/A 532381SN/Atemplate <class Impl> 542381SN/ADefaultCommit<Impl>::TrapEvent::TrapEvent(DefaultCommit<Impl> *_commit, 552381SN/A ThreadID _tid) 568229Snate@binkert.org : Event(CPU_Tick_Pri), commit(_commit), tid(_tid) 573348Sbinkertn@umich.edu{ 583348Sbinkertn@umich.edu this->setFlags(AutoDelete); 593348Sbinkertn@umich.edu} 6013856Sodanrc@yahoo.com.br 615735Snate@binkert.orgtemplate <class Impl> 624024Sbinkertn@umich.eduvoid 635735Snate@binkert.orgDefaultCommit<Impl>::TrapEvent::process() 6412334Sgabeblack@google.com{ 655314Sstever@gmail.com // This will get reset by commit if it was switched out at the 666216Snate@binkert.org // time of this event processing. 6713347Sgabeblack@google.com commit->trapSquash[tid] = true; 682392SN/A} 694167Sbinkertn@umich.edu 702394SN/Atemplate <class Impl> 718737Skoansin.tan@gmail.comconst char * 723349Sbinkertn@umich.eduDefaultCommit<Impl>::TrapEvent::description() const 732394SN/A{ 742812Srdreslin@umich.edu return "Trap"; 7512351Snikos.nikoleris@arm.com} 762812Srdreslin@umich.edu 774022Sstever@eecs.umich.edutemplate <class Impl> 784022Sstever@eecs.umich.eduDefaultCommit<Impl>::DefaultCommit(O3CPU *_cpu, DerivO3CPUParams *params) 795735Snate@binkert.org : cpu(_cpu), 805735Snate@binkert.org squashCounter(0), 814022Sstever@eecs.umich.edu iewToCommitDelay(params->iewToCommitDelay), 825735Snate@binkert.org commitToIEWDelay(params->commitToIEWDelay), 835735Snate@binkert.org renameToROBDelay(params->renameToROBDelay), 845735Snate@binkert.org fetchToCommitDelay(params->commitToFetchDelay), 854022Sstever@eecs.umich.edu renameWidth(params->renameWidth), 864022Sstever@eecs.umich.edu commitWidth(params->commitWidth), 874022Sstever@eecs.umich.edu numThreads(params->numThreads), 884022Sstever@eecs.umich.edu drainPending(false), 894473Sstever@eecs.umich.edu switchedOut(false), 905319Sstever@gmail.com trapLatency(params->trapLatency) 914022Sstever@eecs.umich.edu{ 924022Sstever@eecs.umich.edu _status = Active; 9311199Sandreas.hansson@arm.com _nextStatus = Inactive; 9411199Sandreas.hansson@arm.com std::string policy = params->smtCommitPolicy; 9512344Snikos.nikoleris@arm.com 9610883Sali.jafri@arm.com //Convert string to lowercase 974022Sstever@eecs.umich.edu std::transform(policy.begin(), policy.end(), policy.begin(), 9813367Syuetsu.kodama@riken.jp (int(*)(int)) tolower); 994022Sstever@eecs.umich.edu 1004022Sstever@eecs.umich.edu //Assign commit policy 1014022Sstever@eecs.umich.edu if (policy == "aggressive"){ 10210886Sandreas.hansson@arm.com commitPolicy = Aggressive; 1034022Sstever@eecs.umich.edu 1047465Ssteve.reinhardt@amd.com DPRINTF(Commit,"Commit Policy set to Aggressive."); 1054628Sstever@eecs.umich.edu } else if (policy == "roundrobin"){ 1067465Ssteve.reinhardt@amd.com commitPolicy = RoundRobin; 1077465Ssteve.reinhardt@amd.com 1084022Sstever@eecs.umich.edu //Set-Up Priority List 1094022Sstever@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; tid++) { 11010885Sandreas.hansson@arm.com priority_list.push_back(tid); 11110885Sandreas.hansson@arm.com } 1124626Sstever@eecs.umich.edu 1134626Sstever@eecs.umich.edu DPRINTF(Commit,"Commit Policy set to Round Robin."); 1147669Ssteve.reinhardt@amd.com } else if (policy == "oldestready"){ 1154626Sstever@eecs.umich.edu commitPolicy = OldestReady; 1164040Ssaidi@eecs.umich.edu 1174040Ssaidi@eecs.umich.edu DPRINTF(Commit,"Commit Policy set to Oldest Ready."); 1185650Sgblack@eecs.umich.edu } else { 1195650Sgblack@eecs.umich.edu assert(0 && "Invalid SMT Commit Policy. Options Are: {Aggressive," 12011256Santhony.gutierrez@amd.com "RoundRobin,OldestReady}"); 12111256Santhony.gutierrez@amd.com } 12212347Snikos.nikoleris@arm.com 12312347Snikos.nikoleris@arm.com for (ThreadID tid = 0; tid < numThreads; tid++) { 12412347Snikos.nikoleris@arm.com commitStatus[tid] = Idle; 12512347Snikos.nikoleris@arm.com changedROBNumEntries[tid] = false; 1264870Sstever@eecs.umich.edu checkEmptyROB[tid] = false; 1274870Sstever@eecs.umich.edu trapInFlight[tid] = false; 1284870Sstever@eecs.umich.edu committedStores[tid] = false; 1294870Sstever@eecs.umich.edu trapSquash[tid] = false; 1304870Sstever@eecs.umich.edu tcSquash[tid] = false; 1314870Sstever@eecs.umich.edu pc[tid].set(0); 1328436SBrad.Beckmann@amd.com } 1338436SBrad.Beckmann@amd.com#if FULL_SYSTEM 1345314Sstever@gmail.com interrupt = NoFault; 1355314Sstever@gmail.com#endif 1368184Ssomayeh@cs.wisc.edu} 13710886Sandreas.hansson@arm.com 13810886Sandreas.hansson@arm.comtemplate <class Impl> 1394022Sstever@eecs.umich.edustd::string 1404022Sstever@eecs.umich.eduDefaultCommit<Impl>::name() const 1414022Sstever@eecs.umich.edu{ 1424022Sstever@eecs.umich.edu return cpu->name() + ".commit"; 1435735Snate@binkert.org} 1445735Snate@binkert.org 1455735Snate@binkert.orgtemplate <class Impl> 1464022Sstever@eecs.umich.eduvoid 1474022Sstever@eecs.umich.eduDefaultCommit<Impl>::regStats() 1484626Sstever@eecs.umich.edu{ 1494626Sstever@eecs.umich.edu using namespace Stats; 1507465Ssteve.reinhardt@amd.com commitCommittedInsts 1514022Sstever@eecs.umich.edu .name(name() + ".commitCommittedInsts") 15212347Snikos.nikoleris@arm.com .desc("The number of committed instructions") 15311284Sandreas.hansson@arm.com .prereq(commitCommittedInsts); 1544626Sstever@eecs.umich.edu commitSquashedInsts 1554626Sstever@eecs.umich.edu .name(name() + ".commitSquashedInsts") 1564626Sstever@eecs.umich.edu .desc("The number of squashed insts skipped by commit") 15711199Sandreas.hansson@arm.com .prereq(commitSquashedInsts); 1584022Sstever@eecs.umich.edu commitSquashEvents 1594022Sstever@eecs.umich.edu .name(name() + ".commitSquashEvents") 1606076Sgblack@eecs.umich.edu .desc("The number of times commit is told to squash") 1614626Sstever@eecs.umich.edu .prereq(commitSquashEvents); 1624870Sstever@eecs.umich.edu commitNonSpecStalls 1635314Sstever@gmail.com .name(name() + ".commitNonSpecStalls") 1648184Ssomayeh@cs.wisc.edu .desc("The number of times commit has been forced to stall to " 16511600Sandreas.hansson@arm.com "communicate backwards") 1664022Sstever@eecs.umich.edu .prereq(commitNonSpecStalls); 1674022Sstever@eecs.umich.edu branchMispredicts 1684022Sstever@eecs.umich.edu .name(name() + ".branchMispredicts") 1695735Snate@binkert.org .desc("The number of times a branch was mispredicted") 1705735Snate@binkert.org .prereq(branchMispredicts); 1715735Snate@binkert.org numCommittedDist 1725735Snate@binkert.org .init(0,commitWidth,1) 1735735Snate@binkert.org .name(name() + ".COM:committed_per_cycle") 1745735Snate@binkert.org .desc("Number of insts commited each cycle") 1755735Snate@binkert.org .flags(Stats::pdf) 1764022Sstever@eecs.umich.edu ; 1775735Snate@binkert.org 1785735Snate@binkert.org statComInst 1794022Sstever@eecs.umich.edu .init(cpu->numThreads) 1805735Snate@binkert.org .name(name() + ".COM:count") 1814022Sstever@eecs.umich.edu .desc("Number of instructions committed") 1824022Sstever@eecs.umich.edu .flags(total) 1834022Sstever@eecs.umich.edu ; 1845735Snate@binkert.org 1854022Sstever@eecs.umich.edu statComSwp 1864022Sstever@eecs.umich.edu .init(cpu->numThreads) 1874022Sstever@eecs.umich.edu .name(name() + ".COM:swp_count") 1884022Sstever@eecs.umich.edu .desc("Number of s/w prefetches committed") 1894022Sstever@eecs.umich.edu .flags(total) 1904022Sstever@eecs.umich.edu ; 1915735Snate@binkert.org 1925735Snate@binkert.org statComRefs 1935735Snate@binkert.org .init(cpu->numThreads) 1944022Sstever@eecs.umich.edu .name(name() + ".COM:refs") 1954022Sstever@eecs.umich.edu .desc("Number of memory references committed") 1964022Sstever@eecs.umich.edu .flags(total) 1974022Sstever@eecs.umich.edu ; 1984022Sstever@eecs.umich.edu 19910583SCurtis.Dunham@arm.com statComLoads 20010583SCurtis.Dunham@arm.com .init(cpu->numThreads) 20110583SCurtis.Dunham@arm.com .name(name() + ".COM:loads") 20210583SCurtis.Dunham@arm.com .desc("Number of loads committed") 20310583SCurtis.Dunham@arm.com .flags(total) 20411284Sandreas.hansson@arm.com ; 20510583SCurtis.Dunham@arm.com 20610583SCurtis.Dunham@arm.com statComMembars 20711199Sandreas.hansson@arm.com .init(cpu->numThreads) 20812347Snikos.nikoleris@arm.com .name(name() + ".COM:membars") 20911600Sandreas.hansson@arm.com .desc("Number of memory barriers committed") 21011199Sandreas.hansson@arm.com .flags(total) 21111199Sandreas.hansson@arm.com ; 21211199Sandreas.hansson@arm.com 21311199Sandreas.hansson@arm.com statComBranches 21411199Sandreas.hansson@arm.com .init(cpu->numThreads) 21511199Sandreas.hansson@arm.com .name(name() + ".COM:branches") 21610570Sandreas.hansson@arm.com .desc("Number of branches committed") 21710570Sandreas.hansson@arm.com .flags(total) 21810570Sandreas.hansson@arm.com ; 21910570Sandreas.hansson@arm.com 22010570Sandreas.hansson@arm.com commitEligible 22110570Sandreas.hansson@arm.com .init(cpu->numThreads) 2224022Sstever@eecs.umich.edu .name(name() + ".COM:bw_limited") 2236102Sgblack@eecs.umich.edu .desc("number of insts not committed due to BW limits") 22410343SCurtis.Dunham@arm.com .flags(total) 22510343SCurtis.Dunham@arm.com ; 22610343SCurtis.Dunham@arm.com 22710343SCurtis.Dunham@arm.com commitEligibleSamples 2284870Sstever@eecs.umich.edu .name(name() + ".COM:bw_lim_events") 2295314Sstever@gmail.com .desc("number cycles where commit BW limit reached") 2308184Ssomayeh@cs.wisc.edu ; 2314022Sstever@eecs.umich.edu} 23211294Sandreas.hansson@arm.com 2335735Snate@binkert.orgtemplate <class Impl> 2345735Snate@binkert.orgvoid 2354022Sstever@eecs.umich.eduDefaultCommit<Impl>::setThreads(std::vector<Thread *> &threads) 2364022Sstever@eecs.umich.edu{ 2374022Sstever@eecs.umich.edu thread = threads; 2385735Snate@binkert.org} 2395735Snate@binkert.org 2404022Sstever@eecs.umich.edutemplate <class Impl> 2414022Sstever@eecs.umich.eduvoid 2425735Snate@binkert.orgDefaultCommit<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) 2435735Snate@binkert.org{ 2445735Snate@binkert.org timeBuffer = tb_ptr; 2454022Sstever@eecs.umich.edu 2465735Snate@binkert.org // Setup wire to send information back to IEW. 2475735Snate@binkert.org toIEW = timeBuffer->getWire(0); 2484022Sstever@eecs.umich.edu 2494022Sstever@eecs.umich.edu // Setup wire to read data from IEW (for the ROB). 2502381SN/A robInfoFromIEW = timeBuffer->getWire(-iewToCommitDelay); 2512662Sstever@eecs.umich.edu} 2522662Sstever@eecs.umich.edu 2532662Sstever@eecs.umich.edutemplate <class Impl> 2542662Sstever@eecs.umich.eduvoid 2552662Sstever@eecs.umich.eduDefaultCommit<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr) 2562381SN/A{ 2579044SAli.Saidi@ARM.com fetchQueue = fq_ptr; 2582381SN/A 2592813Srdreslin@umich.edu // Setup wire to get instructions from rename (for the ROB). 2605735Snate@binkert.org fromFetch = fetchQueue->getWire(-fetchToCommitDelay); 2615735Snate@binkert.org} 2624022Sstever@eecs.umich.edu 2635735Snate@binkert.orgtemplate <class Impl> 2645735Snate@binkert.orgvoid 26510938Sandreas.hansson@arm.comDefaultCommit<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr) 26610938Sandreas.hansson@arm.com{ 26712349Snikos.nikoleris@arm.com renameQueue = rq_ptr; 26810938Sandreas.hansson@arm.com 26913732Snikos.nikoleris@arm.com // Setup wire to get instructions from rename (for the ROB). 27013732Snikos.nikoleris@arm.com fromRename = renameQueue->getWire(-renameToROBDelay); 27113732Snikos.nikoleris@arm.com} 27211284Sandreas.hansson@arm.com 27311284Sandreas.hansson@arm.comtemplate <class Impl> 27411284Sandreas.hansson@arm.comvoid 27511284Sandreas.hansson@arm.comDefaultCommit<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr) 27610938Sandreas.hansson@arm.com{ 27710938Sandreas.hansson@arm.com iewQueue = iq_ptr; 27810938Sandreas.hansson@arm.com 27911284Sandreas.hansson@arm.com // Setup wire to get instructions from IEW. 28011284Sandreas.hansson@arm.com fromIEW = iewQueue->getWire(-iewToCommitDelay); 28111284Sandreas.hansson@arm.com} 28211284Sandreas.hansson@arm.com 28311284Sandreas.hansson@arm.comtemplate <class Impl> 28411284Sandreas.hansson@arm.comvoid 28511284Sandreas.hansson@arm.comDefaultCommit<Impl>::setIEWStage(IEW *iew_stage) 28611284Sandreas.hansson@arm.com{ 28711284Sandreas.hansson@arm.com iewStage = iew_stage; 28810938Sandreas.hansson@arm.com} 28912346Snikos.nikoleris@arm.com 29012346Snikos.nikoleris@arm.comtemplate<class Impl> 29112346Snikos.nikoleris@arm.comvoid 29212346Snikos.nikoleris@arm.comDefaultCommit<Impl>::setActiveThreads(list<ThreadID> *at_ptr) 29312349Snikos.nikoleris@arm.com{ 29412349Snikos.nikoleris@arm.com activeThreads = at_ptr; 29512349Snikos.nikoleris@arm.com} 29612349Snikos.nikoleris@arm.com 29711057Sandreas.hansson@arm.comtemplate <class Impl> 29811057Sandreas.hansson@arm.comvoid 29911057Sandreas.hansson@arm.comDefaultCommit<Impl>::setRenameMap(RenameMap rm_ptr[]) 30011057Sandreas.hansson@arm.com{ 30110938Sandreas.hansson@arm.com for (ThreadID tid = 0; tid < numThreads; tid++) 30210938Sandreas.hansson@arm.com renameMap[tid] = &rm_ptr[tid]; 30310938Sandreas.hansson@arm.com} 30410938Sandreas.hansson@arm.com 30510938Sandreas.hansson@arm.comtemplate <class Impl> 30610938Sandreas.hansson@arm.comvoid 30710938Sandreas.hansson@arm.comDefaultCommit<Impl>::setROB(ROB *rob_ptr) 30810938Sandreas.hansson@arm.com{ 30910938Sandreas.hansson@arm.com rob = rob_ptr; 31010938Sandreas.hansson@arm.com} 31110938Sandreas.hansson@arm.com 31210938Sandreas.hansson@arm.comtemplate <class Impl> 31310938Sandreas.hansson@arm.comvoid 31410938Sandreas.hansson@arm.comDefaultCommit<Impl>::initStage() 31510938Sandreas.hansson@arm.com{ 31610938Sandreas.hansson@arm.com rob->setActiveThreads(activeThreads); 3175735Snate@binkert.org rob->resetEntries(); 3185735Snate@binkert.org 3195735Snate@binkert.org // Broadcast the number of free entries. 3205735Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; tid++) { 3214022Sstever@eecs.umich.edu toIEW->commitInfo[tid].usedROB = true; 3224022Sstever@eecs.umich.edu toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid); 3235735Snate@binkert.org toIEW->commitInfo[tid].emptyROB = true; 3244870Sstever@eecs.umich.edu } 3254870Sstever@eecs.umich.edu 32612351Snikos.nikoleris@arm.com // Commit must broadcast the number of free entries it has at the 32712351Snikos.nikoleris@arm.com // start of the simulation, so it starts as active. 3285735Snate@binkert.org cpu->activateStage(O3CPU::CommitIdx); 32912749Sgiacomo.travaglini@arm.com 3304870Sstever@eecs.umich.edu cpu->activityThisCycle(); 3312566SN/A trapLatency = cpu->ticks(trapLatency); 3325735Snate@binkert.org} 33312633Sodanrc@yahoo.com.br 33412633Sodanrc@yahoo.com.brtemplate <class Impl> 3355735Snate@binkert.orgbool 33612633Sodanrc@yahoo.com.brDefaultCommit<Impl>::drain() 3375735Snate@binkert.org{ 3382566SN/A drainPending = true; 3392566SN/A 3402566SN/A return false; 3415735Snate@binkert.org} 3425735Snate@binkert.org 3432381SN/Atemplate <class Impl> 3442381SN/Avoid 34510028SGiacomo.Gabrielli@arm.comDefaultCommit<Impl>::switchOut() 34610028SGiacomo.Gabrielli@arm.com{ 34710028SGiacomo.Gabrielli@arm.com switchedOut = true; 3485735Snate@binkert.org drainPending = false; 3496227Snate@binkert.org rob->switchOut(); 3502381SN/A} 3515735Snate@binkert.org 35210723Sandreas.hansson@arm.comtemplate <class Impl> 3538668Sgeoffrey.blake@arm.comvoid 35410723Sandreas.hansson@arm.comDefaultCommit<Impl>::resume() 3558668Sgeoffrey.blake@arm.com{ 35612966SMatteo.Andreozzi@arm.com drainPending = false; 35712966SMatteo.Andreozzi@arm.com} 35812966SMatteo.Andreozzi@arm.com 3592641Sstever@eecs.umich.edutemplate <class Impl> 3602811Srdreslin@umich.eduvoid 3619547Sandreas.hansson@arm.comDefaultCommit<Impl>::takeOverFrom() 36210694SMarco.Balboni@ARM.com{ 36310405Sandreas.hansson@arm.com switchedOut = false; 36410405Sandreas.hansson@arm.com _status = Active; 36510405Sandreas.hansson@arm.com _nextStatus = Inactive; 36610405Sandreas.hansson@arm.com for (ThreadID tid = 0; tid < numThreads; tid++) { 3679547Sandreas.hansson@arm.com commitStatus[tid] = Idle; 36810694SMarco.Balboni@ARM.com changedROBNumEntries[tid] = false; 3693218Sgblack@eecs.umich.edu trapSquash[tid] = false; 3709547Sandreas.hansson@arm.com tcSquash[tid] = false; 37111127Sandreas.hansson@arm.com } 37211127Sandreas.hansson@arm.com squashCounter = 0; 37311127Sandreas.hansson@arm.com rob->takeOverFrom(); 37411127Sandreas.hansson@arm.com} 37511127Sandreas.hansson@arm.com 37611127Sandreas.hansson@arm.comtemplate <class Impl> 37711127Sandreas.hansson@arm.comvoid 37811127Sandreas.hansson@arm.comDefaultCommit<Impl>::updateStatus() 37910694SMarco.Balboni@ARM.com{ 38010694SMarco.Balboni@ARM.com // reset ROB changed variable 38110694SMarco.Balboni@ARM.com list<ThreadID>::iterator threads = activeThreads->begin(); 38210694SMarco.Balboni@ARM.com list<ThreadID>::iterator end = activeThreads->end(); 38310405Sandreas.hansson@arm.com 38410405Sandreas.hansson@arm.com while (threads != end) { 3859547Sandreas.hansson@arm.com ThreadID tid = *threads++; 38610694SMarco.Balboni@ARM.com 3873218Sgblack@eecs.umich.edu changedROBNumEntries[tid] = false; 3885735Snate@binkert.org 3895735Snate@binkert.org // Also check if any of the threads has a trap pending 3909542Sandreas.hansson@arm.com if (commitStatus[tid] == TrapPending || 3919542Sandreas.hansson@arm.com commitStatus[tid] == FetchTrapPending) { 3929542Sandreas.hansson@arm.com _nextStatus = Active; 3939542Sandreas.hansson@arm.com } 3949542Sandreas.hansson@arm.com } 3959542Sandreas.hansson@arm.com 3969542Sandreas.hansson@arm.com if (_nextStatus == Inactive && _status == Active) { 3979542Sandreas.hansson@arm.com DPRINTF(Activity, "Deactivating stage.\n"); 3989542Sandreas.hansson@arm.com cpu->deactivateStage(O3CPU::CommitIdx); 3999542Sandreas.hansson@arm.com } else if (_nextStatus == Active && _status == Inactive) { 4009542Sandreas.hansson@arm.com DPRINTF(Activity, "Activating stage.\n"); 4019542Sandreas.hansson@arm.com cpu->activateStage(O3CPU::CommitIdx); 4029542Sandreas.hansson@arm.com } 4039542Sandreas.hansson@arm.com 4045735Snate@binkert.org _status = _nextStatus; 4055735Snate@binkert.org} 4065735Snate@binkert.org 4079542Sandreas.hansson@arm.comtemplate <class Impl> 4089542Sandreas.hansson@arm.comvoid 4092641Sstever@eecs.umich.eduDefaultCommit<Impl>::setNextStatus() 4102641Sstever@eecs.umich.edu{ 4112641Sstever@eecs.umich.edu int squashes = 0; 4125315Sstever@gmail.com 4135315Sstever@gmail.com list<ThreadID>::iterator threads = activeThreads->begin(); 4145315Sstever@gmail.com list<ThreadID>::iterator end = activeThreads->end(); 4155315Sstever@gmail.com 4169044SAli.Saidi@ARM.com while (threads != end) { 4175735Snate@binkert.org ThreadID tid = *threads++; 4185735Snate@binkert.org 4195735Snate@binkert.org if (commitStatus[tid] == ROBSquashing) { 4205735Snate@binkert.org squashes++; 4215735Snate@binkert.org } 4225735Snate@binkert.org } 4235735Snate@binkert.org 4245314Sstever@gmail.com squashCounter = squashes; 4255314Sstever@gmail.com 4265314Sstever@gmail.com // If commit is currently squashing, then it will have activity for the 4275735Snate@binkert.org // next cycle. Set its next status as active. 4285314Sstever@gmail.com if (squashCounter) { 4295314Sstever@gmail.com _nextStatus = Active; 4305314Sstever@gmail.com } 4315314Sstever@gmail.com} 4325314Sstever@gmail.com 4335314Sstever@gmail.comtemplate <class Impl> 4345314Sstever@gmail.combool 4355314Sstever@gmail.comDefaultCommit<Impl>::changedROBEntries() 4365314Sstever@gmail.com{ 4375314Sstever@gmail.com list<ThreadID>::iterator threads = activeThreads->begin(); 4385314Sstever@gmail.com list<ThreadID>::iterator end = activeThreads->end(); 4395314Sstever@gmail.com 4405314Sstever@gmail.com while (threads != end) { 4415314Sstever@gmail.com ThreadID tid = *threads++; 4425735Snate@binkert.org 4435735Snate@binkert.org if (changedROBNumEntries[tid]) { 4445735Snate@binkert.org return true; 4455314Sstever@gmail.com } 4465315Sstever@gmail.com } 4475735Snate@binkert.org 4485735Snate@binkert.org return false; 4495315Sstever@gmail.com} 4505735Snate@binkert.org 4515735Snate@binkert.orgtemplate <class Impl> 4525314Sstever@gmail.comsize_t 4535314Sstever@gmail.comDefaultCommit<Impl>::numROBFreeEntries(ThreadID tid) 4545735Snate@binkert.org{ 4555735Snate@binkert.org return rob->numFreeEntries(tid); 4565735Snate@binkert.org} 4575735Snate@binkert.org 4585314Sstever@gmail.comtemplate <class Impl> 4595735Snate@binkert.orgvoid 4605735Snate@binkert.orgDefaultCommit<Impl>::generateTrapEvent(ThreadID tid) 4615735Snate@binkert.org{ 4625315Sstever@gmail.com DPRINTF(Commit, "Generating trap event for [tid:%i]\n", tid); 4635735Snate@binkert.org 4645735Snate@binkert.org TrapEvent *trap = new TrapEvent(this, tid); 4655314Sstever@gmail.com 4665735Snate@binkert.org cpu->schedule(trap, curTick + trapLatency); 4675735Snate@binkert.org trapInFlight[tid] = true; 4685735Snate@binkert.org} 4695735Snate@binkert.org 4705735Snate@binkert.orgtemplate <class Impl> 4715314Sstever@gmail.comvoid 4725314Sstever@gmail.comDefaultCommit<Impl>::generateTCEvent(ThreadID tid) 4735314Sstever@gmail.com{ 4745735Snate@binkert.org assert(!trapInFlight[tid]); 4755735Snate@binkert.org DPRINTF(Commit, "Generating TC squash event for [tid:%i]\n", tid); 4765735Snate@binkert.org 4775735Snate@binkert.org tcSquash[tid] = true; 4789542Sandreas.hansson@arm.com} 4795735Snate@binkert.org 4805735Snate@binkert.orgtemplate <class Impl> 4815735Snate@binkert.orgvoid 4822662Sstever@eecs.umich.eduDefaultCommit<Impl>::squashAll(ThreadID tid) 4832641Sstever@eecs.umich.edu{ 4849542Sandreas.hansson@arm.com // If we want to include the squashing instruction in the squash, 4859542Sandreas.hansson@arm.com // then use one older sequence number. 4869542Sandreas.hansson@arm.com // Hopefully this doesn't mess things up. Basically I want to squash 4879542Sandreas.hansson@arm.com // all instructions of this thread. 4889542Sandreas.hansson@arm.com InstSeqNum squashed_inst = rob->isEmpty() ? 4899542Sandreas.hansson@arm.com 0 : rob->readHeadInst(tid)->seqNum - 1; 4909542Sandreas.hansson@arm.com 4919542Sandreas.hansson@arm.com // All younger instructions will be squashed. Set the sequence 4929542Sandreas.hansson@arm.com // number as the youngest instruction in the ROB (0 in this case. 4939542Sandreas.hansson@arm.com // Hopefully nothing breaks.) 4949542Sandreas.hansson@arm.com youngestSeqNum[tid] = 0; 4959542Sandreas.hansson@arm.com 4969542Sandreas.hansson@arm.com rob->squash(squashed_inst, tid); 4979542Sandreas.hansson@arm.com changedROBNumEntries[tid] = true; 4989542Sandreas.hansson@arm.com 4999542Sandreas.hansson@arm.com // Send back the sequence number of the squashed instruction. 5009542Sandreas.hansson@arm.com toIEW->commitInfo[tid].doneSeqNum = squashed_inst; 5019542Sandreas.hansson@arm.com 5029542Sandreas.hansson@arm.com // Send back the squash signal to tell stages that they should 5039542Sandreas.hansson@arm.com // squash. 5049543Ssascha.bischoff@arm.com toIEW->commitInfo[tid].squash = true; 5059543Ssascha.bischoff@arm.com 5069543Ssascha.bischoff@arm.com // Send back the rob squashing signal so other stages know that 5079543Ssascha.bischoff@arm.com // the ROB is in the process of squashing. 5089543Ssascha.bischoff@arm.com toIEW->commitInfo[tid].robSquashing = true; 5099543Ssascha.bischoff@arm.com 5109543Ssascha.bischoff@arm.com toIEW->commitInfo[tid].branchMispredict = false; 5119543Ssascha.bischoff@arm.com 5129543Ssascha.bischoff@arm.com toIEW->commitInfo[tid].pc = pc[tid]; 5139543Ssascha.bischoff@arm.com} 5149543Ssascha.bischoff@arm.com 5159543Ssascha.bischoff@arm.comtemplate <class Impl> 5169543Ssascha.bischoff@arm.comvoid 5179543Ssascha.bischoff@arm.comDefaultCommit<Impl>::squashFromTrap(ThreadID tid) 5189543Ssascha.bischoff@arm.com{ 5199543Ssascha.bischoff@arm.com squashAll(tid); 5209543Ssascha.bischoff@arm.com 5219543Ssascha.bischoff@arm.com DPRINTF(Commit, "Squashing from trap, restarting at PC %s\n", pc[tid]); 5229543Ssascha.bischoff@arm.com 5235735Snate@binkert.org thread[tid]->trapPending = false; 5245735Snate@binkert.org thread[tid]->inSyscall = false; 5254022Sstever@eecs.umich.edu trapInFlight[tid] = false; 5262811Srdreslin@umich.edu 5275735Snate@binkert.org trapSquash[tid] = false; 5284022Sstever@eecs.umich.edu 5292811Srdreslin@umich.edu commitStatus[tid] = ROBSquashing; 53010583SCurtis.Dunham@arm.com cpu->activityThisCycle(); 53110583SCurtis.Dunham@arm.com} 53210583SCurtis.Dunham@arm.com 53310583SCurtis.Dunham@arm.comtemplate <class Impl> 53410583SCurtis.Dunham@arm.comvoid 53511287Sandreas.hansson@arm.comDefaultCommit<Impl>::squashFromTC(ThreadID tid) 53611287Sandreas.hansson@arm.com{ 53711287Sandreas.hansson@arm.com squashAll(tid); 53811287Sandreas.hansson@arm.com 53911287Sandreas.hansson@arm.com DPRINTF(Commit, "Squashing from TC, restarting at PC %s\n", pc[tid]); 54011287Sandreas.hansson@arm.com 54111287Sandreas.hansson@arm.com thread[tid]->inSyscall = false; 54211287Sandreas.hansson@arm.com assert(!thread[tid]->trapPending); 54311287Sandreas.hansson@arm.com 54410583SCurtis.Dunham@arm.com commitStatus[tid] = ROBSquashing; 54510583SCurtis.Dunham@arm.com cpu->activityThisCycle(); 54611199Sandreas.hansson@arm.com 54712347Snikos.nikoleris@arm.com tcSquash[tid] = false; 54811600Sandreas.hansson@arm.com} 54911199Sandreas.hansson@arm.com 55010583SCurtis.Dunham@arm.comtemplate <class Impl> 55111286Sandreas.hansson@arm.comvoid 55211286Sandreas.hansson@arm.comDefaultCommit<Impl>::tick() 55311286Sandreas.hansson@arm.com{ 55411286Sandreas.hansson@arm.com wroteToTimeBuffer = false; 55511286Sandreas.hansson@arm.com _nextStatus = Inactive; 55610583SCurtis.Dunham@arm.com 55710583SCurtis.Dunham@arm.com if (drainPending && rob->isEmpty() && !iewStage->hasStoresToWB()) { 55810583SCurtis.Dunham@arm.com cpu->signalDrained(); 55910583SCurtis.Dunham@arm.com drainPending = false; 5602812Srdreslin@umich.edu return; 56113350Snikos.nikoleris@arm.com } 56213350Snikos.nikoleris@arm.com 56313350Snikos.nikoleris@arm.com if (activeThreads->empty()) 56413350Snikos.nikoleris@arm.com return; 56513350Snikos.nikoleris@arm.com 56613350Snikos.nikoleris@arm.com list<ThreadID>::iterator threads = activeThreads->begin(); 56711284Sandreas.hansson@arm.com list<ThreadID>::iterator end = activeThreads->end(); 56811284Sandreas.hansson@arm.com 56911284Sandreas.hansson@arm.com // Check if any of the threads are done squashing. Change the 57011284Sandreas.hansson@arm.com // status if they are done. 57111284Sandreas.hansson@arm.com while (threads != end) { 57211284Sandreas.hansson@arm.com ThreadID tid = *threads++; 57311284Sandreas.hansson@arm.com 57411284Sandreas.hansson@arm.com // Clear the bit saying if the thread has committed stores 57511284Sandreas.hansson@arm.com // this cycle. 57611284Sandreas.hansson@arm.com committedStores[tid] = false; 57711284Sandreas.hansson@arm.com 57811284Sandreas.hansson@arm.com if (commitStatus[tid] == ROBSquashing) { 57911284Sandreas.hansson@arm.com 58011284Sandreas.hansson@arm.com if (rob->isDoneSquashing(tid)) { 58111284Sandreas.hansson@arm.com commitStatus[tid] = Running; 58211284Sandreas.hansson@arm.com } else { 58311284Sandreas.hansson@arm.com DPRINTF(Commit,"[tid:%u]: Still Squashing, cannot commit any" 58411284Sandreas.hansson@arm.com " insts this cycle.\n", tid); 58511284Sandreas.hansson@arm.com rob->doSquash(tid); 58611284Sandreas.hansson@arm.com toIEW->commitInfo[tid].robSquashing = true; 58711284Sandreas.hansson@arm.com wroteToTimeBuffer = true; 58810567Sandreas.hansson@arm.com } 58910567Sandreas.hansson@arm.com } 59011284Sandreas.hansson@arm.com } 59111284Sandreas.hansson@arm.com 59210567Sandreas.hansson@arm.com commit(); 59311284Sandreas.hansson@arm.com 59411284Sandreas.hansson@arm.com markCompletedInsts(); 59511284Sandreas.hansson@arm.com 59611284Sandreas.hansson@arm.com threads = activeThreads->begin(); 59711284Sandreas.hansson@arm.com 59811284Sandreas.hansson@arm.com while (threads != end) { 59911284Sandreas.hansson@arm.com ThreadID tid = *threads++; 60011284Sandreas.hansson@arm.com 60111284Sandreas.hansson@arm.com if (!rob->isEmpty(tid) && rob->readHeadInst(tid)->readyToCommit()) { 60211284Sandreas.hansson@arm.com // The ROB has more instructions it can commit. Its next status 60311284Sandreas.hansson@arm.com // will be active. 60411284Sandreas.hansson@arm.com _nextStatus = Active; 60511284Sandreas.hansson@arm.com 60611284Sandreas.hansson@arm.com DynInstPtr inst = rob->readHeadInst(tid); 60711284Sandreas.hansson@arm.com 60811284Sandreas.hansson@arm.com DPRINTF(Commit,"[tid:%i]: Instruction [sn:%lli] PC %s is head of" 60911284Sandreas.hansson@arm.com " ROB and ready to commit\n", 61011284Sandreas.hansson@arm.com tid, inst->seqNum, inst->pcState()); 61111284Sandreas.hansson@arm.com 61211284Sandreas.hansson@arm.com } else if (!rob->isEmpty(tid)) { 61311284Sandreas.hansson@arm.com DynInstPtr inst = rob->readHeadInst(tid); 61411284Sandreas.hansson@arm.com 61511284Sandreas.hansson@arm.com DPRINTF(Commit,"[tid:%i]: Can't commit, Instruction [sn:%lli] PC " 61611284Sandreas.hansson@arm.com "%s is head of ROB and not ready\n", 61711284Sandreas.hansson@arm.com tid, inst->seqNum, inst->pcState()); 61811284Sandreas.hansson@arm.com } 61911284Sandreas.hansson@arm.com 62011284Sandreas.hansson@arm.com DPRINTF(Commit, "[tid:%i]: ROB has %d insts & %d free entries.\n", 62111284Sandreas.hansson@arm.com tid, rob->countInsts(tid), rob->numFreeEntries(tid)); 6224870Sstever@eecs.umich.edu } 62311284Sandreas.hansson@arm.com 62411284Sandreas.hansson@arm.com 62511284Sandreas.hansson@arm.com if (wroteToTimeBuffer) { 62611284Sandreas.hansson@arm.com DPRINTF(Activity, "Activity This Cycle.\n"); 62711284Sandreas.hansson@arm.com cpu->activityThisCycle(); 62811284Sandreas.hansson@arm.com } 62911284Sandreas.hansson@arm.com 63011284Sandreas.hansson@arm.com updateStatus(); 63111284Sandreas.hansson@arm.com} 63211284Sandreas.hansson@arm.com 63311284Sandreas.hansson@arm.com#if FULL_SYSTEM 63411284Sandreas.hansson@arm.comtemplate <class Impl> 63511284Sandreas.hansson@arm.comvoid 63611284Sandreas.hansson@arm.comDefaultCommit<Impl>::handleInterrupt() 63711284Sandreas.hansson@arm.com{ 63811284Sandreas.hansson@arm.com if (interrupt != NoFault) { 63911284Sandreas.hansson@arm.com // Wait until the ROB is empty and all stores have drained in 64011284Sandreas.hansson@arm.com // order to enter the interrupt. 64111284Sandreas.hansson@arm.com if (rob->isEmpty() && !iewStage->hasStoresToWB()) { 64211284Sandreas.hansson@arm.com // Squash or record that I need to squash this cycle if 64311284Sandreas.hansson@arm.com // an interrupt needed to be handled. 64411284Sandreas.hansson@arm.com DPRINTF(Commit, "Interrupt detected.\n"); 64511284Sandreas.hansson@arm.com 64611284Sandreas.hansson@arm.com // Clear the interrupt now that it's going to be handled 64711284Sandreas.hansson@arm.com toIEW->commitInfo[0].clearInterrupt = true; 64811284Sandreas.hansson@arm.com 64911284Sandreas.hansson@arm.com assert(!thread[0]->inSyscall); 65011746Snikos.nikoleris@arm.com thread[0]->inSyscall = true; 65111284Sandreas.hansson@arm.com 65211284Sandreas.hansson@arm.com // CPU will handle interrupt. 65311284Sandreas.hansson@arm.com cpu->processInterrupts(interrupt); 65411284Sandreas.hansson@arm.com 65511284Sandreas.hansson@arm.com thread[0]->inSyscall = false; 65612346Snikos.nikoleris@arm.com 65713732Snikos.nikoleris@arm.com commitStatus[0] = TrapPending; 65813732Snikos.nikoleris@arm.com 65913732Snikos.nikoleris@arm.com // Generate trap squash event. 66013732Snikos.nikoleris@arm.com generateTrapEvent(0); 66113732Snikos.nikoleris@arm.com 66213732Snikos.nikoleris@arm.com interrupt = NoFault; 66313732Snikos.nikoleris@arm.com } else { 66413732Snikos.nikoleris@arm.com DPRINTF(Commit, "Interrupt pending, waiting for ROB to empty.\n"); 66513732Snikos.nikoleris@arm.com } 66612346Snikos.nikoleris@arm.com } else if (commitStatus[0] != TrapPending && 66712346Snikos.nikoleris@arm.com cpu->checkInterrupts(cpu->tcBase(0)) && 66812346Snikos.nikoleris@arm.com !trapSquash[0] && 66912346Snikos.nikoleris@arm.com !tcSquash[0]) { 67012346Snikos.nikoleris@arm.com // Process interrupts if interrupts are enabled, not in PAL 67112346Snikos.nikoleris@arm.com // mode, and no other traps or external squashes are currently 67212346Snikos.nikoleris@arm.com // pending. 67312346Snikos.nikoleris@arm.com // @todo: Allow other threads to handle interrupts. 67412346Snikos.nikoleris@arm.com 67512346Snikos.nikoleris@arm.com // Get any interrupt that happened 67612346Snikos.nikoleris@arm.com interrupt = cpu->getInterrupts(); 67712346Snikos.nikoleris@arm.com 67812349Snikos.nikoleris@arm.com if (interrupt != NoFault) { 67912349Snikos.nikoleris@arm.com // Tell fetch that there is an interrupt pending. This 68012349Snikos.nikoleris@arm.com // will make fetch wait until it sees a non PAL-mode PC, 68112349Snikos.nikoleris@arm.com // at which point it stops fetching instructions. 68212349Snikos.nikoleris@arm.com toIEW->commitInfo[0].interruptPending = true; 68312349Snikos.nikoleris@arm.com } 68412349Snikos.nikoleris@arm.com } 68512349Snikos.nikoleris@arm.com} 68612349Snikos.nikoleris@arm.com#endif // FULL_SYSTEM 68712349Snikos.nikoleris@arm.com 68812349Snikos.nikoleris@arm.comtemplate <class Impl> 68912349Snikos.nikoleris@arm.comvoid 69012349Snikos.nikoleris@arm.comDefaultCommit<Impl>::commit() 6919951Sstephan.diestelhorst@arm.com{ 6929951Sstephan.diestelhorst@arm.com 69310763Sali.jafri@arm.com#if FULL_SYSTEM 69410763Sali.jafri@arm.com // Check for any interrupt, and start processing it. Or if we 69510883Sali.jafri@arm.com // have an outstanding interrupt and are at a point when it is 6964895Sstever@eecs.umich.edu // valid to take an interrupt, process it. 69712966SMatteo.Andreozzi@arm.com if (cpu->checkInterrupts(cpu->tcBase(0))) { 69812966SMatteo.Andreozzi@arm.com handleInterrupt(); 69912966SMatteo.Andreozzi@arm.com } 70012966SMatteo.Andreozzi@arm.com#endif // FULL_SYSTEM 70112966SMatteo.Andreozzi@arm.com 70212966SMatteo.Andreozzi@arm.com //////////////////////////////////// 70312966SMatteo.Andreozzi@arm.com // Check for any possible squashes, handle them first 70412966SMatteo.Andreozzi@arm.com //////////////////////////////////// 70512966SMatteo.Andreozzi@arm.com list<ThreadID>::iterator threads = activeThreads->begin(); 70612966SMatteo.Andreozzi@arm.com list<ThreadID>::iterator end = activeThreads->end(); 70712966SMatteo.Andreozzi@arm.com 70812966SMatteo.Andreozzi@arm.com while (threads != end) { 70912966SMatteo.Andreozzi@arm.com ThreadID tid = *threads++; 71012966SMatteo.Andreozzi@arm.com 71112966SMatteo.Andreozzi@arm.com // Not sure which one takes priority. I think if we have 71212966SMatteo.Andreozzi@arm.com // both, that's a bad sign. 71312966SMatteo.Andreozzi@arm.com if (trapSquash[tid] == true) { 71412966SMatteo.Andreozzi@arm.com assert(!tcSquash[tid]); 71512966SMatteo.Andreozzi@arm.com squashFromTrap(tid); 7164870Sstever@eecs.umich.edu } else if (tcSquash[tid] == true) { 7174870Sstever@eecs.umich.edu assert(commitStatus[tid] != TrapPending); 7184870Sstever@eecs.umich.edu squashFromTC(tid); 7195735Snate@binkert.org } 7205735Snate@binkert.org 7215735Snate@binkert.org // Squashed sequence number must be older than youngest valid 7225735Snate@binkert.org // instruction in the ROB. This prevents squashes from younger 7235735Snate@binkert.org // instructions overriding squashes from older instructions. 7245735Snate@binkert.org if (fromIEW->squash[tid] && 7255735Snate@binkert.org commitStatus[tid] != TrapPending && 7264986Ssaidi@eecs.umich.edu fromIEW->squashedSeqNum[tid] <= youngestSeqNum[tid]) { 7272814Srdreslin@umich.edu 72811057Sandreas.hansson@arm.com DPRINTF(Commit, "[tid:%i]: Squashing due to PC %#x [sn:%i]\n", 7299259SAli.Saidi@ARM.com tid, 7309259SAli.Saidi@ARM.com fromIEW->mispredPC[tid], 7319259SAli.Saidi@ARM.com fromIEW->squashedSeqNum[tid]); 7329259SAli.Saidi@ARM.com 7339259SAli.Saidi@ARM.com DPRINTF(Commit, "[tid:%i]: Redirecting to PC %#x\n", 7349259SAli.Saidi@ARM.com tid, 7359259SAli.Saidi@ARM.com fromIEW->pc[tid].nextInstAddr()); 73611057Sandreas.hansson@arm.com 7379259SAli.Saidi@ARM.com commitStatus[tid] = ROBSquashing; 73811057Sandreas.hansson@arm.com 73910938Sandreas.hansson@arm.com // If we want to include the squashing instruction in the squash, 74013856Sodanrc@yahoo.com.br // then use one older sequence number. 74113856Sodanrc@yahoo.com.br InstSeqNum squashed_inst = fromIEW->squashedSeqNum[tid]; 74213856Sodanrc@yahoo.com.br 74313856Sodanrc@yahoo.com.br if (fromIEW->includeSquashInst[tid] == true) { 74413856Sodanrc@yahoo.com.br squashed_inst--; 74513856Sodanrc@yahoo.com.br } 74613856Sodanrc@yahoo.com.br 74710938Sandreas.hansson@arm.com // All younger instructions will be squashed. Set the sequence 74810938Sandreas.hansson@arm.com // number as the youngest instruction in the ROB. 74910938Sandreas.hansson@arm.com youngestSeqNum[tid] = squashed_inst; 75010938Sandreas.hansson@arm.com 75110938Sandreas.hansson@arm.com rob->squash(squashed_inst, tid); 75210938Sandreas.hansson@arm.com changedROBNumEntries[tid] = true; 75310938Sandreas.hansson@arm.com 75410938Sandreas.hansson@arm.com toIEW->commitInfo[tid].doneSeqNum = squashed_inst; 75510938Sandreas.hansson@arm.com 7562549SN/A toIEW->commitInfo[tid].squash = true; 75711057Sandreas.hansson@arm.com 75811057Sandreas.hansson@arm.com // Send back the rob squashing signal so other stages know that 75911057Sandreas.hansson@arm.com // the ROB is in the process of squashing. 76011057Sandreas.hansson@arm.com toIEW->commitInfo[tid].robSquashing = true; 76111057Sandreas.hansson@arm.com 76210028SGiacomo.Gabrielli@arm.com toIEW->commitInfo[tid].branchMispredict = 7635735Snate@binkert.org fromIEW->branchMispredict[tid]; 76411306Santhony.gutierrez@amd.com 76511306Santhony.gutierrez@amd.com toIEW->commitInfo[tid].branchTaken = 76611306Santhony.gutierrez@amd.com fromIEW->branchTaken[tid]; 76711306Santhony.gutierrez@amd.com 76811306Santhony.gutierrez@amd.com toIEW->commitInfo[tid].pc = fromIEW->pc[tid]; 76911306Santhony.gutierrez@amd.com 7707550SBrad.Beckmann@amd.com toIEW->commitInfo[tid].mispredPC = fromIEW->mispredPC[tid]; 77110938Sandreas.hansson@arm.com 7727550SBrad.Beckmann@amd.com if (toIEW->commitInfo[tid].branchMispredict) { 7737550SBrad.Beckmann@amd.com ++branchMispredicts; 7747550SBrad.Beckmann@amd.com } 7757550SBrad.Beckmann@amd.com } 7767550SBrad.Beckmann@amd.com 7777550SBrad.Beckmann@amd.com } 7787550SBrad.Beckmann@amd.com 7797550SBrad.Beckmann@amd.com setNextStatus(); 7807550SBrad.Beckmann@amd.com 7817550SBrad.Beckmann@amd.com if (squashCounter != numThreads) { 78210938Sandreas.hansson@arm.com // If we're not currently squashing, then get instructions. 78310938Sandreas.hansson@arm.com getInsts(); 7847550SBrad.Beckmann@amd.com 7857550SBrad.Beckmann@amd.com // Try to commit any instructions. 7867550SBrad.Beckmann@amd.com commitInsts(); 7877550SBrad.Beckmann@amd.com } 7887550SBrad.Beckmann@amd.com 7897550SBrad.Beckmann@amd.com //Check for any activity 7907550SBrad.Beckmann@amd.com threads = activeThreads->begin(); 7917550SBrad.Beckmann@amd.com 7927550SBrad.Beckmann@amd.com while (threads != end) { 7937550SBrad.Beckmann@amd.com ThreadID tid = *threads++; 79410938Sandreas.hansson@arm.com 79511057Sandreas.hansson@arm.com if (changedROBNumEntries[tid]) { 79611057Sandreas.hansson@arm.com toIEW->commitInfo[tid].usedROB = true; 7975735Snate@binkert.org toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid); 79812749Sgiacomo.travaglini@arm.com 79912966SMatteo.Andreozzi@arm.com wroteToTimeBuffer = true; 80012966SMatteo.Andreozzi@arm.com changedROBNumEntries[tid] = false; 80112966SMatteo.Andreozzi@arm.com if (rob->isEmpty(tid)) 80212351Snikos.nikoleris@arm.com checkEmptyROB[tid] = true; 80311057Sandreas.hansson@arm.com } 80411057Sandreas.hansson@arm.com 80511057Sandreas.hansson@arm.com // ROB is only considered "empty" for previous stages if: a) 80611057Sandreas.hansson@arm.com // ROB is empty, b) there are no outstanding stores, c) IEW 80711057Sandreas.hansson@arm.com // stage has received any information regarding stores that 80811057Sandreas.hansson@arm.com // committed. 80911057Sandreas.hansson@arm.com // c) is checked by making sure to not consider the ROB empty 81011057Sandreas.hansson@arm.com // on the same cycle as when stores have been committed. 81111057Sandreas.hansson@arm.com // @todo: Make this handle multi-cycle communication between 81211057Sandreas.hansson@arm.com // commit and IEW. 81311057Sandreas.hansson@arm.com if (checkEmptyROB[tid] && rob->isEmpty(tid) && 81411057Sandreas.hansson@arm.com !iewStage->hasStoresToWB(tid) && !committedStores[tid]) { 81511057Sandreas.hansson@arm.com checkEmptyROB[tid] = false; 81611057Sandreas.hansson@arm.com toIEW->commitInfo[tid].usedROB = true; 81711057Sandreas.hansson@arm.com toIEW->commitInfo[tid].emptyROB = true; 81811057Sandreas.hansson@arm.com toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid); 81911057Sandreas.hansson@arm.com wroteToTimeBuffer = true; 82012749Sgiacomo.travaglini@arm.com } 82112749Sgiacomo.travaglini@arm.com 82212966SMatteo.Andreozzi@arm.com } 82312966SMatteo.Andreozzi@arm.com} 82412749Sgiacomo.travaglini@arm.com 82511057Sandreas.hansson@arm.comtemplate <class Impl> 82611057Sandreas.hansson@arm.comvoid 82711057Sandreas.hansson@arm.comDefaultCommit<Impl>::commitInsts() 82811057Sandreas.hansson@arm.com{ 82911057Sandreas.hansson@arm.com //////////////////////////////////// 83011057Sandreas.hansson@arm.com // Handle commit 83111057Sandreas.hansson@arm.com // Note that commit will be handled prior to putting new 83211057Sandreas.hansson@arm.com // instructions in the ROB so that the ROB only tries to commit 83311057Sandreas.hansson@arm.com // instructions it has in this current cycle, and not instructions 8344626Sstever@eecs.umich.edu // it is writing in during this cycle. Can't commit and squash 8355735Snate@binkert.org // things at the same time... 8365735Snate@binkert.org //////////////////////////////////// 8374887Sstever@eecs.umich.edu 8384887Sstever@eecs.umich.edu DPRINTF(Commit, "Trying to commit instructions in the ROB.\n"); 8394887Sstever@eecs.umich.edu 8405735Snate@binkert.org unsigned num_committed = 0; 8415735Snate@binkert.org 84210896Snilay@cs.wisc.edu DynInstPtr head_inst; 84312351Snikos.nikoleris@arm.com 84410571Sandreas.hansson@arm.com // Commit as many instructions as possible until the commit bandwidth 84510028SGiacomo.Gabrielli@arm.com // limit is reached, or it becomes impossible to commit any more. 84610723Sandreas.hansson@arm.com while (num_committed < commitWidth) { 84712966SMatteo.Andreozzi@arm.com int commit_thread = getCommittingThread(); 84810694SMarco.Balboni@ARM.com 84911127Sandreas.hansson@arm.com if (commit_thread == -1 || !rob->isHeadReady(commit_thread)) 85010694SMarco.Balboni@ARM.com break; 8519546Sandreas.hansson@arm.com 8524626Sstever@eecs.umich.edu head_inst = rob->readHeadInst(commit_thread); 85310571Sandreas.hansson@arm.com 8545735Snate@binkert.org ThreadID tid = head_inst->threadNumber; 8555735Snate@binkert.org 85611057Sandreas.hansson@arm.com assert(tid == commit_thread); 85711057Sandreas.hansson@arm.com 85810571Sandreas.hansson@arm.com DPRINTF(Commit, "Trying to commit head instruction, [sn:%i] [tid:%i]\n", 85910571Sandreas.hansson@arm.com head_inst->seqNum, tid); 86010571Sandreas.hansson@arm.com 86110571Sandreas.hansson@arm.com // If the head instruction is squashed, it is ready to retire 86210571Sandreas.hansson@arm.com // (be removed from the ROB) at any time. 86310571Sandreas.hansson@arm.com if (head_inst->isSquashed()) { 86410571Sandreas.hansson@arm.com 86510571Sandreas.hansson@arm.com DPRINTF(Commit, "Retiring squashed instruction from " 86610571Sandreas.hansson@arm.com "ROB.\n"); 86710571Sandreas.hansson@arm.com 86810571Sandreas.hansson@arm.com rob->retireHead(commit_thread); 86910571Sandreas.hansson@arm.com 87010571Sandreas.hansson@arm.com ++commitSquashedInsts; 87110571Sandreas.hansson@arm.com 87210571Sandreas.hansson@arm.com // Record that the number of ROB entries has changed. 87310342SCurtis.Dunham@arm.com changedROBNumEntries[tid] = true; 8748668Sgeoffrey.blake@arm.com } else { 87510342SCurtis.Dunham@arm.com pc[tid] = head_inst->pcState(); 87610739Ssteve.reinhardt@amd.com 87710342SCurtis.Dunham@arm.com // Increment the total number of non-speculative instructions 87810739Ssteve.reinhardt@amd.com // executed. 87912749Sgiacomo.travaglini@arm.com // Hack for now: it really shouldn't happen until after the 88010342SCurtis.Dunham@arm.com // commit is deemed to be successful, but this count is needed 88110739Ssteve.reinhardt@amd.com // for syscalls. 88210739Ssteve.reinhardt@amd.com thread[tid]->funcExeInst++; 88313367Syuetsu.kodama@riken.jp 88413367Syuetsu.kodama@riken.jp // Try to commit the head instruction. 88510739Ssteve.reinhardt@amd.com bool commit_success = commitHead(head_inst, num_committed); 88610739Ssteve.reinhardt@amd.com 88710739Ssteve.reinhardt@amd.com if (commit_success) { 88810739Ssteve.reinhardt@amd.com ++num_committed; 88910739Ssteve.reinhardt@amd.com 89010739Ssteve.reinhardt@amd.com changedROBNumEntries[tid] = true; 89110739Ssteve.reinhardt@amd.com 89210739Ssteve.reinhardt@amd.com // Set the doneSeqNum to the youngest committed instruction. 89310739Ssteve.reinhardt@amd.com toIEW->commitInfo[tid].doneSeqNum = head_inst->seqNum; 89410739Ssteve.reinhardt@amd.com 89512749Sgiacomo.travaglini@arm.com ++commitCommittedInsts; 89610739Ssteve.reinhardt@amd.com 89710739Ssteve.reinhardt@amd.com // To match the old model, don't count nops and instruction 89810739Ssteve.reinhardt@amd.com // prefetches towards the total commit count. 89912766Sqtt2@cornell.edu if (!head_inst->isNop() && !head_inst->isInstPrefetch()) { 90010739Ssteve.reinhardt@amd.com cpu->instDone(tid); 90112347Snikos.nikoleris@arm.com } 90212347Snikos.nikoleris@arm.com 90312347Snikos.nikoleris@arm.com TheISA::advancePC(pc[tid], head_inst->staticInst); 90412347Snikos.nikoleris@arm.com 90512347Snikos.nikoleris@arm.com int count = 0; 90612347Snikos.nikoleris@arm.com Addr oldpc; 90710739Ssteve.reinhardt@amd.com // Debug statement. Checks to make sure we're not 90810342SCurtis.Dunham@arm.com // currently updating state while handling PC events. 90910342SCurtis.Dunham@arm.com assert(!thread[tid]->inSyscall && !thread[tid]->trapPending); 91010342SCurtis.Dunham@arm.com do { 91110342SCurtis.Dunham@arm.com oldpc = pc[tid].instAddr(); 91210739Ssteve.reinhardt@amd.com cpu->system->pcEventQueue.service(thread[tid]->getTC()); 91310342SCurtis.Dunham@arm.com count++; 91410342SCurtis.Dunham@arm.com } while (oldpc != pc[tid].instAddr()); 91512749Sgiacomo.travaglini@arm.com if (count > 1) { 91610342SCurtis.Dunham@arm.com DPRINTF(Commit, 91710739Ssteve.reinhardt@amd.com "PC skip function event, stopping commit\n"); 91810342SCurtis.Dunham@arm.com break; 91910342SCurtis.Dunham@arm.com } 92010342SCurtis.Dunham@arm.com } else { 92112749Sgiacomo.travaglini@arm.com DPRINTF(Commit, "Unable to commit head instruction PC:%s " 92210342SCurtis.Dunham@arm.com "[tid:%i] [sn:%i].\n", 92310739Ssteve.reinhardt@amd.com head_inst->pcState(), tid ,head_inst->seqNum); 9242641Sstever@eecs.umich.edu break; 9252549SN/A } 9265735Snate@binkert.org } 9275735Snate@binkert.org } 9285735Snate@binkert.org 9292566SN/A DPRINTF(CommitRate, "%i\n", num_committed); 9305387Sstever@gmail.com numCommittedDist.sample(num_committed); 9315735Snate@binkert.org 9325387Sstever@gmail.com if (num_committed == commitWidth) { 9332566SN/A commitEligibleSamples++; 9345735Snate@binkert.org } 9354626Sstever@eecs.umich.edu} 93610660Sandreas.hansson@arm.com 9374626Sstever@eecs.umich.edutemplate <class Impl> 9385735Snate@binkert.orgbool 9395735Snate@binkert.orgDefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num) 9404626Sstever@eecs.umich.edu{ 9412662Sstever@eecs.umich.edu assert(head_inst); 9422855Srdreslin@umich.edu 9434022Sstever@eecs.umich.edu ThreadID tid = head_inst->threadNumber; 9445745Snate@binkert.org 9457464Ssteve.reinhardt@amd.com // If the instruction is not executed yet, then it will need extra 9467464Ssteve.reinhardt@amd.com // handling. Signal backwards that it should be executed. 9477464Ssteve.reinhardt@amd.com if (!head_inst->isExecuted()) { 9482641Sstever@eecs.umich.edu // Keep this number correct. We have not yet actually executed 9492641Sstever@eecs.umich.edu // and committed this instruction. 9505735Snate@binkert.org thread[tid]->funcExeInst--; 9515735Snate@binkert.org 9524870Sstever@eecs.umich.edu if (head_inst->isNonSpeculative() || 9534870Sstever@eecs.umich.edu head_inst->isStoreConditional() || 9544870Sstever@eecs.umich.edu head_inst->isMemBarrier() || 9554870Sstever@eecs.umich.edu head_inst->isWriteBarrier()) { 9565735Snate@binkert.org 9575735Snate@binkert.org DPRINTF(Commit, "Encountered a barrier or non-speculative " 9583348Sbinkertn@umich.edu "instruction [sn:%lli] at the head of the ROB, PC %s.\n", 9594870Sstever@eecs.umich.edu head_inst->seqNum, head_inst->pcState()); 9603135Srdreslin@umich.edu 9613135Srdreslin@umich.edu if (inst_num > 0 || iewStage->hasStoresToWB(tid)) { 9628436SBrad.Beckmann@amd.com DPRINTF(Commit, "Waiting for all stores to writeback.\n"); 9638436SBrad.Beckmann@amd.com return false; 9648436SBrad.Beckmann@amd.com } 9658436SBrad.Beckmann@amd.com 9668436SBrad.Beckmann@amd.com toIEW->commitInfo[tid].nonSpecSeqNum = head_inst->seqNum; 9678436SBrad.Beckmann@amd.com 9688436SBrad.Beckmann@amd.com // Change the instruction so it won't try to commit again until 9698436SBrad.Beckmann@amd.com // it is executed. 9708436SBrad.Beckmann@amd.com head_inst->clearCanCommit(); 9718436SBrad.Beckmann@amd.com 9728436SBrad.Beckmann@amd.com ++commitNonSpecStalls; 9738436SBrad.Beckmann@amd.com 97411057Sandreas.hansson@arm.com return false; 97511057Sandreas.hansson@arm.com } else if (head_inst->isLoad()) { 97611057Sandreas.hansson@arm.com if (inst_num > 0 || iewStage->hasStoresToWB(tid)) { 97711057Sandreas.hansson@arm.com DPRINTF(Commit, "Waiting for all stores to writeback.\n"); 97811057Sandreas.hansson@arm.com return false; 97911057Sandreas.hansson@arm.com } 98011057Sandreas.hansson@arm.com 98111057Sandreas.hansson@arm.com assert(head_inst->uncacheable()); 98211057Sandreas.hansson@arm.com DPRINTF(Commit, "[sn:%lli]: Uncached load, PC %s.\n", 98313860Sodanrc@yahoo.com.br head_inst->seqNum, head_inst->pcState()); 98413860Sodanrc@yahoo.com.br 98513860Sodanrc@yahoo.com.br // Send back the non-speculative instruction's sequence 98613860Sodanrc@yahoo.com.br // number. Tell the lsq to re-execute the load. 98713860Sodanrc@yahoo.com.br toIEW->commitInfo[tid].nonSpecSeqNum = head_inst->seqNum; 98813860Sodanrc@yahoo.com.br toIEW->commitInfo[tid].uncached = true; 98913860Sodanrc@yahoo.com.br toIEW->commitInfo[tid].uncachedLoad = head_inst; 99013860Sodanrc@yahoo.com.br 99113860Sodanrc@yahoo.com.br head_inst->clearCanCommit(); 99213860Sodanrc@yahoo.com.br 99313860Sodanrc@yahoo.com.br return false; 99413860Sodanrc@yahoo.com.br } else { 99513860Sodanrc@yahoo.com.br panic("Trying to commit un-executed instruction " 99613860Sodanrc@yahoo.com.br "of unknown type!\n"); 99713860Sodanrc@yahoo.com.br } 99813860Sodanrc@yahoo.com.br } 99913860Sodanrc@yahoo.com.br 100013860Sodanrc@yahoo.com.br if (head_inst->isThreadSync()) { 100113860Sodanrc@yahoo.com.br // Not handled for now. 100213860Sodanrc@yahoo.com.br panic("Thread sync instructions are not handled yet.\n"); 100313860Sodanrc@yahoo.com.br } 100413860Sodanrc@yahoo.com.br 100513860Sodanrc@yahoo.com.br // Check if the instruction caused a fault. If so, trap. 100613860Sodanrc@yahoo.com.br Fault inst_fault = head_inst->getFault(); 100713860Sodanrc@yahoo.com.br 100813860Sodanrc@yahoo.com.br // Stores mark themselves as completed. 100913860Sodanrc@yahoo.com.br if (!head_inst->isStore() && inst_fault == NoFault) { 101013860Sodanrc@yahoo.com.br head_inst->setCompleted(); 101113860Sodanrc@yahoo.com.br } 101213860Sodanrc@yahoo.com.br 101313860Sodanrc@yahoo.com.br#if USE_CHECKER 101413860Sodanrc@yahoo.com.br // Use checker prior to updating anything due to traps or PC 101513860Sodanrc@yahoo.com.br // based events. 101613860Sodanrc@yahoo.com.br if (cpu->checker) { 101713860Sodanrc@yahoo.com.br cpu->checker->verify(head_inst); 101813860Sodanrc@yahoo.com.br } 101913860Sodanrc@yahoo.com.br#endif 102013860Sodanrc@yahoo.com.br 102113860Sodanrc@yahoo.com.br if (inst_fault != NoFault) { 102211057Sandreas.hansson@arm.com DPRINTF(Commit, "Inst [sn:%lli] PC %s has a fault\n", 102311013Sandreas.sandberg@arm.com head_inst->seqNum, head_inst->pcState()); 102411013Sandreas.sandberg@arm.com 102511013Sandreas.sandberg@arm.com if (iewStage->hasStoresToWB(tid) || inst_num > 0) { 102611013Sandreas.sandberg@arm.com DPRINTF(Commit, "Stores outstanding, fault must wait.\n"); 102711013Sandreas.sandberg@arm.com return false; 102811013Sandreas.sandberg@arm.com } 10293348Sbinkertn@umich.edu 10303348Sbinkertn@umich.edu head_inst->setCompleted(); 103110571Sandreas.hansson@arm.com 103210571Sandreas.hansson@arm.com#if USE_CHECKER 103310571Sandreas.hansson@arm.com if (cpu->checker && head_inst->isStore()) { 103410571Sandreas.hansson@arm.com cpu->checker->verify(head_inst); 103510571Sandreas.hansson@arm.com } 103610571Sandreas.hansson@arm.com#endif 103710571Sandreas.hansson@arm.com 103810571Sandreas.hansson@arm.com assert(!thread[tid]->inSyscall); 10392566SN/A 10402566SN/A // Mark that we're in state update mode so that the trap's 10413348Sbinkertn@umich.edu // execution doesn't generate extra squashes. 10423348Sbinkertn@umich.edu thread[tid]->inSyscall = true; 10433348Sbinkertn@umich.edu 104410566Sandreas.hansson@arm.com // Execute the trap. Although it's slightly unrealistic in 10453348Sbinkertn@umich.edu // terms of timing (as it doesn't wait for the full timing of 10465735Snate@binkert.org // the trap event to complete before updating state), it's 10473348Sbinkertn@umich.edu // needed to update the state as soon as possible. This 10482566SN/A // prevents external agents from changing any specific state 10493348Sbinkertn@umich.edu // that the trap need. 105010564Sandreas.hansson@arm.com cpu->trap(inst_fault, tid, head_inst->staticInst); 105110564Sandreas.hansson@arm.com 105210564Sandreas.hansson@arm.com // Exit state update mode to avoid accidental updating. 105310564Sandreas.hansson@arm.com thread[tid]->inSyscall = false; 105410564Sandreas.hansson@arm.com 105510564Sandreas.hansson@arm.com commitStatus[tid] = TrapPending; 105610564Sandreas.hansson@arm.com 105710564Sandreas.hansson@arm.com if (head_inst->traceData) { 105810564Sandreas.hansson@arm.com if (DTRACE(ExecFaulting)) { 105910564Sandreas.hansson@arm.com head_inst->traceData->setFetchSeq(head_inst->seqNum); 106010564Sandreas.hansson@arm.com head_inst->traceData->setCPSeq(thread[tid]->numInst); 106110566Sandreas.hansson@arm.com head_inst->traceData->dump(); 106210564Sandreas.hansson@arm.com } 106310564Sandreas.hansson@arm.com delete head_inst->traceData; 106410564Sandreas.hansson@arm.com head_inst->traceData = NULL; 106510564Sandreas.hansson@arm.com } 106610564Sandreas.hansson@arm.com 10673348Sbinkertn@umich.edu // Generate trap squash event. 106810571Sandreas.hansson@arm.com generateTrapEvent(tid); 106910571Sandreas.hansson@arm.com return false; 107010571Sandreas.hansson@arm.com } 107110571Sandreas.hansson@arm.com 107210571Sandreas.hansson@arm.com updateComInstStats(head_inst); 107310571Sandreas.hansson@arm.com 107410571Sandreas.hansson@arm.com#if FULL_SYSTEM 107510571Sandreas.hansson@arm.com if (thread[tid]->profile) { 107610571Sandreas.hansson@arm.com thread[tid]->profilePC = head_inst->instAddr(); 10773348Sbinkertn@umich.edu ProfileNode *node = thread[tid]->profile->consume(thread[tid]->getTC(), 10782566SN/A head_inst->staticInst); 10793348Sbinkertn@umich.edu 10803348Sbinkertn@umich.edu if (node) 10813348Sbinkertn@umich.edu thread[tid]->profileNode = node; 108210566Sandreas.hansson@arm.com } 10833348Sbinkertn@umich.edu if (CPA::available()) { 10845735Snate@binkert.org if (head_inst->isControl()) { 10853348Sbinkertn@umich.edu ThreadContext *tc = thread[tid]->getTC(); 10863348Sbinkertn@umich.edu CPA::cpa()->swAutoBegin(tc, head_inst->nextInstAddr()); 10875735Snate@binkert.org } 10885735Snate@binkert.org } 10895735Snate@binkert.org#endif 10903348Sbinkertn@umich.edu 10913348Sbinkertn@umich.edu if (head_inst->traceData) { 109210562Sandreas.hansson@arm.com head_inst->traceData->setFetchSeq(head_inst->seqNum); 10933348Sbinkertn@umich.edu head_inst->traceData->setCPSeq(thread[tid]->numInst); 109410562Sandreas.hansson@arm.com head_inst->traceData->dump(); 10953348Sbinkertn@umich.edu delete head_inst->traceData; 10963348Sbinkertn@umich.edu head_inst->traceData = NULL; 10972566SN/A } 109810563Sandreas.hansson@arm.com 109910563Sandreas.hansson@arm.com // Update the commit rename map 110010563Sandreas.hansson@arm.com for (int i = 0; i < head_inst->numDestRegs(); i++) { 110110563Sandreas.hansson@arm.com renameMap[tid]->setEntry(head_inst->flattenedDestRegIdx(i), 110210563Sandreas.hansson@arm.com head_inst->renamedDestRegIdx(i)); 110310563Sandreas.hansson@arm.com } 110410563Sandreas.hansson@arm.com 110510563Sandreas.hansson@arm.com if (head_inst->isCopy()) 11065735Snate@binkert.org panic("Should not commit any copy instructions!"); 110711013Sandreas.sandberg@arm.com 110811013Sandreas.sandberg@arm.com // Finally clear the head ROB entry. 110911013Sandreas.sandberg@arm.com rob->retireHead(tid); 111011013Sandreas.sandberg@arm.com 111111013Sandreas.sandberg@arm.com // If this was a store, record it for this cycle. 111211013Sandreas.sandberg@arm.com if (head_inst->isStore()) 111311013Sandreas.sandberg@arm.com committedStores[tid] = true; 111411013Sandreas.sandberg@arm.com 111511013Sandreas.sandberg@arm.com // Return true to indicate that we have committed an instruction. 111611013Sandreas.sandberg@arm.com return true; 111711013Sandreas.sandberg@arm.com} 111811013Sandreas.sandberg@arm.com 111911013Sandreas.sandberg@arm.comtemplate <class Impl> 112011013Sandreas.sandberg@arm.comvoid 112111013Sandreas.sandberg@arm.comDefaultCommit<Impl>::getInsts() 112211013Sandreas.sandberg@arm.com{ 112311013Sandreas.sandberg@arm.com DPRINTF(Commit, "Getting instructions from Rename stage.\n"); 112411013Sandreas.sandberg@arm.com 112511013Sandreas.sandberg@arm.com // Read any renamed instructions and place them into the ROB. 112611013Sandreas.sandberg@arm.com int insts_to_process = std::min((int)renameWidth, fromRename->size); 112713347Sgabeblack@google.com 112811013Sandreas.sandberg@arm.com for (int inst_num = 0; inst_num < insts_to_process; ++inst_num) { 112911013Sandreas.sandberg@arm.com DynInstPtr inst; 113011013Sandreas.sandberg@arm.com 11315735Snate@binkert.org inst = fromRename->insts[inst_num]; 11322566SN/A ThreadID tid = inst->threadNumber; 113313348Sgabeblack@google.com 113413348Sgabeblack@google.com if (!inst->isSquashed() && 113513347Sgabeblack@google.com commitStatus[tid] != ROBSquashing && 11362566SN/A commitStatus[tid] != TrapPending) { 113711013Sandreas.sandberg@arm.com changedROBNumEntries[tid] = true; 113811013Sandreas.sandberg@arm.com 113911013Sandreas.sandberg@arm.com DPRINTF(Commit, "Inserting PC %s [sn:%i] [tid:%i] into ROB.\n", 114011013Sandreas.sandberg@arm.com inst->pcState(), inst->seqNum, tid); 114111013Sandreas.sandberg@arm.com 114211013Sandreas.sandberg@arm.com rob->insertInst(inst); 114311013Sandreas.sandberg@arm.com 114411013Sandreas.sandberg@arm.com assert(rob->getThreadEntries(tid) <= rob->getMaxEntries(tid)); 11455735Snate@binkert.org 114611013Sandreas.sandberg@arm.com youngestSeqNum[tid] = inst->seqNum; 114711013Sandreas.sandberg@arm.com } else { 11485735Snate@binkert.org DPRINTF(Commit, "Instruction PC %s [sn:%i] [tid:%i] was " 11492566SN/A "squashed, skipping.\n", 115011013Sandreas.sandberg@arm.com inst->pcState(), inst->seqNum, tid); 115111013Sandreas.sandberg@arm.com } 115213347Sgabeblack@google.com } 115311013Sandreas.sandberg@arm.com} 115411013Sandreas.sandberg@arm.com 115513348Sgabeblack@google.comtemplate <class Impl> 115613348Sgabeblack@google.comvoid 115713347Sgabeblack@google.comDefaultCommit<Impl>::skidInsert() 11582566SN/A{ 115912652Sandreas.sandberg@arm.com DPRINTF(Commit, "Attempting to any instructions from rename into " 116012652Sandreas.sandberg@arm.com "skidBuffer.\n"); 116112652Sandreas.sandberg@arm.com 116212652Sandreas.sandberg@arm.com for (int inst_num = 0; inst_num < fromRename->size; ++inst_num) { 116312652Sandreas.sandberg@arm.com DynInstPtr inst = fromRename->insts[inst_num]; 116412652Sandreas.sandberg@arm.com 116512652Sandreas.sandberg@arm.com if (!inst->isSquashed()) { 116612652Sandreas.sandberg@arm.com DPRINTF(Commit, "Inserting PC %s [sn:%i] [tid:%i] into ", 116712652Sandreas.sandberg@arm.com "skidBuffer.\n", inst->pcState(), inst->seqNum, 116812652Sandreas.sandberg@arm.com inst->threadNumber); 116912652Sandreas.sandberg@arm.com skidBuffer.push(inst); 117012652Sandreas.sandberg@arm.com } else { 117112652Sandreas.sandberg@arm.com DPRINTF(Commit, "Instruction PC %s [sn:%i] [tid:%i] was " 11723348Sbinkertn@umich.edu "squashed, skipping.\n", 11734626Sstever@eecs.umich.edu inst->pcState(), inst->seqNum, inst->threadNumber); 11744626Sstever@eecs.umich.edu } 11755735Snate@binkert.org } 117610563Sandreas.hansson@arm.com} 11774626Sstever@eecs.umich.edu 117810571Sandreas.hansson@arm.comtemplate <class Impl> 117910571Sandreas.hansson@arm.comvoid 118010571Sandreas.hansson@arm.comDefaultCommit<Impl>::markCompletedInsts() 118110571Sandreas.hansson@arm.com{ 118210571Sandreas.hansson@arm.com // Grab completed insts out of the IEW instruction queue, and mark 11837691SAli.Saidi@ARM.com // instructions completed within the ROB. 118410571Sandreas.hansson@arm.com for (int inst_num = 0; 118510571Sandreas.hansson@arm.com inst_num < fromIEW->size && fromIEW->insts[inst_num]; 11867691SAli.Saidi@ARM.com ++inst_num) 11874626Sstever@eecs.umich.edu { 11884626Sstever@eecs.umich.edu if (!fromIEW->insts[inst_num]->isSquashed()) { 11894626Sstever@eecs.umich.edu DPRINTF(Commit, "[tid:%i]: Marking PC %s, [sn:%lli] ready " 11904626Sstever@eecs.umich.edu "within ROB.\n", 11914626Sstever@eecs.umich.edu fromIEW->insts[inst_num]->threadNumber, 11924626Sstever@eecs.umich.edu fromIEW->insts[inst_num]->pcState(), 11935735Snate@binkert.org fromIEW->insts[inst_num]->seqNum); 119410563Sandreas.hansson@arm.com 11954626Sstever@eecs.umich.edu // Mark the instruction as ready to commit. 11964626Sstever@eecs.umich.edu fromIEW->insts[inst_num]->setCanCommit(); 11974626Sstever@eecs.umich.edu } 11984626Sstever@eecs.umich.edu } 11994626Sstever@eecs.umich.edu} 120012633Sodanrc@yahoo.com.br 120112633Sodanrc@yahoo.com.brtemplate <class Impl> 12024626Sstever@eecs.umich.edubool 12035735Snate@binkert.orgDefaultCommit<Impl>::robDoneSquashing() 120410563Sandreas.hansson@arm.com{ 12054626Sstever@eecs.umich.edu list<ThreadID>::iterator threads = activeThreads->begin(); 120610563Sandreas.hansson@arm.com list<ThreadID>::iterator end = activeThreads->end(); 12074626Sstever@eecs.umich.edu 12084626Sstever@eecs.umich.edu while (threads != end) { 12094626Sstever@eecs.umich.edu ThreadID tid = *threads++; 121012633Sodanrc@yahoo.com.br 121112633Sodanrc@yahoo.com.br if (!rob->isDoneSquashing(tid)) 121212633Sodanrc@yahoo.com.br return false; 121312633Sodanrc@yahoo.com.br } 12144626Sstever@eecs.umich.edu 12155735Snate@binkert.org return true; 121610563Sandreas.hansson@arm.com} 12174626Sstever@eecs.umich.edu 12184626Sstever@eecs.umich.edutemplate <class Impl> 12194626Sstever@eecs.umich.eduvoid 12204626Sstever@eecs.umich.eduDefaultCommit<Impl>::updateComInstStats(DynInstPtr &inst) 12214626Sstever@eecs.umich.edu{ 12223348Sbinkertn@umich.edu ThreadID tid = inst->threadNumber; 12233348Sbinkertn@umich.edu 12243348Sbinkertn@umich.edu // 12255735Snate@binkert.org // Pick off the software prefetches 12265735Snate@binkert.org // 12275735Snate@binkert.org#ifdef TARGET_ALPHA 122810566Sandreas.hansson@arm.com if (inst->isDataPrefetch()) { 12295735Snate@binkert.org statComSwp[tid]++; 12305735Snate@binkert.org } else { 123110566Sandreas.hansson@arm.com statComInst[tid]++; 12325735Snate@binkert.org } 12335735Snate@binkert.org#else 12342566SN/A statComInst[tid]++; 123510565Sandreas.hansson@arm.com#endif 12365735Snate@binkert.org 12375735Snate@binkert.org // 12385735Snate@binkert.org // Control Instructions 123911286Sandreas.hansson@arm.com // 124011286Sandreas.hansson@arm.com if (inst->isControl()) 124111286Sandreas.hansson@arm.com statComBranches[tid]++; 124211286Sandreas.hansson@arm.com 124311286Sandreas.hansson@arm.com // 124411286Sandreas.hansson@arm.com // Memory references 124511286Sandreas.hansson@arm.com // 12465735Snate@binkert.org if (inst->isMemRef()) { 12475735Snate@binkert.org statComRefs[tid]++; 124811013Sandreas.sandberg@arm.com 124911013Sandreas.sandberg@arm.com if (inst->isLoad()) { 125011013Sandreas.sandberg@arm.com statComLoads[tid]++; 125111013Sandreas.sandberg@arm.com } 125211013Sandreas.sandberg@arm.com } 125311013Sandreas.sandberg@arm.com 125411013Sandreas.sandberg@arm.com if (inst->isMemBarrier()) { 125511013Sandreas.sandberg@arm.com statComMembars[tid]++; 125611013Sandreas.sandberg@arm.com } 125711013Sandreas.sandberg@arm.com} 125811013Sandreas.sandberg@arm.com 12594626Sstever@eecs.umich.edu//////////////////////////////////////// 126010570Sandreas.hansson@arm.com// // 126110570Sandreas.hansson@arm.com// SMT COMMIT POLICY MAINTAINED HERE // 126210570Sandreas.hansson@arm.com// // 126310570Sandreas.hansson@arm.com//////////////////////////////////////// 126410570Sandreas.hansson@arm.comtemplate <class Impl> 126510570Sandreas.hansson@arm.comThreadID 126610570Sandreas.hansson@arm.comDefaultCommit<Impl>::getCommittingThread() 126710570Sandreas.hansson@arm.com{ 126810570Sandreas.hansson@arm.com if (numThreads > 1) { 126912823Srmk35@cl.cam.ac.uk switch (commitPolicy) { 127010570Sandreas.hansson@arm.com 127110570Sandreas.hansson@arm.com case Aggressive: 127210570Sandreas.hansson@arm.com //If Policy is Aggressive, commit will call 127312823Srmk35@cl.cam.ac.uk //this function multiple times per 127412823Srmk35@cl.cam.ac.uk //cycle 127512823Srmk35@cl.cam.ac.uk return oldestReady(); 127612823Srmk35@cl.cam.ac.uk 127710570Sandreas.hansson@arm.com case RoundRobin: 127810570Sandreas.hansson@arm.com return roundRobin(); 127910570Sandreas.hansson@arm.com 128010883Sali.jafri@arm.com case OldestReady: 128110883Sali.jafri@arm.com return oldestReady(); 128210883Sali.jafri@arm.com 128310883Sali.jafri@arm.com default: 128410883Sali.jafri@arm.com return InvalidThreadID; 128510883Sali.jafri@arm.com } 128611199Sandreas.hansson@arm.com } else { 128711199Sandreas.hansson@arm.com assert(!activeThreads->empty()); 128811199Sandreas.hansson@arm.com ThreadID tid = activeThreads->front(); 128911199Sandreas.hansson@arm.com 129011199Sandreas.hansson@arm.com if (commitStatus[tid] == Running || 129111199Sandreas.hansson@arm.com commitStatus[tid] == Idle || 129211199Sandreas.hansson@arm.com commitStatus[tid] == FetchTrapPending) { 129311199Sandreas.hansson@arm.com return tid; 129411199Sandreas.hansson@arm.com } else { 129511199Sandreas.hansson@arm.com return InvalidThreadID; 129611199Sandreas.hansson@arm.com } 129710883Sali.jafri@arm.com } 129810883Sali.jafri@arm.com} 129910883Sali.jafri@arm.com 13004626Sstever@eecs.umich.edutemplate<class Impl> 130110570Sandreas.hansson@arm.comThreadID 130210570Sandreas.hansson@arm.comDefaultCommit<Impl>::roundRobin() 130310570Sandreas.hansson@arm.com{ 13044626Sstever@eecs.umich.edu list<ThreadID>::iterator pri_iter = priority_list.begin(); 13054626Sstever@eecs.umich.edu list<ThreadID>::iterator end = priority_list.end(); 13065735Snate@binkert.org 130712823Srmk35@cl.cam.ac.uk while (pri_iter != end) { 130812823Srmk35@cl.cam.ac.uk ThreadID tid = *pri_iter; 13095314Sstever@gmail.com 13105315Sstever@gmail.com if (commitStatus[tid] == Running || 13115315Sstever@gmail.com commitStatus[tid] == Idle || 13125315Sstever@gmail.com commitStatus[tid] == FetchTrapPending) { 13135735Snate@binkert.org 13145735Snate@binkert.org if (rob->isHeadReady(tid)) { 13155735Snate@binkert.org priority_list.erase(pri_iter); 13165735Snate@binkert.org priority_list.push_back(tid); 13175735Snate@binkert.org 13185314Sstever@gmail.com return tid; 13195314Sstever@gmail.com } 13205315Sstever@gmail.com } 13215315Sstever@gmail.com 13225315Sstever@gmail.com pri_iter++; 13235735Snate@binkert.org } 13245735Snate@binkert.org 13255735Snate@binkert.org return InvalidThreadID; 13265735Snate@binkert.org} 13275735Snate@binkert.org 13285314Sstever@gmail.comtemplate<class Impl> 13295314Sstever@gmail.comThreadID 13305314Sstever@gmail.comDefaultCommit<Impl>::oldestReady() 13315314Sstever@gmail.com{ 13329663Suri.wiener@arm.com unsigned oldest = 0; 13339663Suri.wiener@arm.com bool first = true; 13349663Suri.wiener@arm.com 13359663Suri.wiener@arm.com list<ThreadID>::iterator threads = activeThreads->begin(); 13369663Suri.wiener@arm.com list<ThreadID>::iterator end = activeThreads->end(); 13379663Suri.wiener@arm.com 13389663Suri.wiener@arm.com while (threads != end) { 13399663Suri.wiener@arm.com ThreadID tid = *threads++; 13402381SN/A 13412381SN/A if (!rob->isEmpty(tid) && 13422381SN/A (commitStatus[tid] == Running || 1343 commitStatus[tid] == Idle || 1344 commitStatus[tid] == FetchTrapPending)) { 1345 1346 if (rob->isHeadReady(tid)) { 1347 1348 DynInstPtr head_inst = rob->readHeadInst(tid); 1349 1350 if (first) { 1351 oldest = tid; 1352 first = false; 1353 } else if (head_inst->seqNum < oldest) { 1354 oldest = tid; 1355 } 1356 } 1357 } 1358 } 1359 1360 if (!first) { 1361 return oldest; 1362 } else { 1363 return InvalidThreadID; 1364 } 1365} 1366