commit_impl.hh revision 9179
11689SN/A/* 28842Smrinmoy.ghosh@arm.com * Copyright (c) 2010-2011 ARM Limited 37783SGiacomo.Gabrielli@arm.com * All rights reserved 47783SGiacomo.Gabrielli@arm.com * 57783SGiacomo.Gabrielli@arm.com * The license below extends only to copyright in the software and shall 67783SGiacomo.Gabrielli@arm.com * not be construed as granting a license to any other intellectual 77783SGiacomo.Gabrielli@arm.com * property including but not limited to intellectual property relating 87783SGiacomo.Gabrielli@arm.com * to a hardware implementation of the functionality of the software 97783SGiacomo.Gabrielli@arm.com * licensed hereunder. You may use the software subject to the license 107783SGiacomo.Gabrielli@arm.com * terms below provided that you ensure that this notice is replicated 117783SGiacomo.Gabrielli@arm.com * unmodified and in its entirety in all distributions of the software, 127783SGiacomo.Gabrielli@arm.com * modified or unmodified, in source code or in binary form. 137783SGiacomo.Gabrielli@arm.com * 142316SN/A * Copyright (c) 2004-2006 The Regents of The University of Michigan 151689SN/A * All rights reserved. 161689SN/A * 171689SN/A * Redistribution and use in source and binary forms, with or without 181689SN/A * modification, are permitted provided that the following conditions are 191689SN/A * met: redistributions of source code must retain the above copyright 201689SN/A * notice, this list of conditions and the following disclaimer; 211689SN/A * redistributions in binary form must reproduce the above copyright 221689SN/A * notice, this list of conditions and the following disclaimer in the 231689SN/A * documentation and/or other materials provided with the distribution; 241689SN/A * neither the name of the copyright holders nor the names of its 251689SN/A * contributors may be used to endorse or promote products derived from 261689SN/A * this software without specific prior written permission. 271689SN/A * 281689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 291689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 301689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 311689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 321689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 331689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 341689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 351689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 361689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 371689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 381689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 392665Ssaidi@eecs.umich.edu * 402665Ssaidi@eecs.umich.edu * Authors: Kevin Lim 412965Sksewell@umich.edu * Korey Sewell 421689SN/A */ 431689SN/A 442292SN/A#include <algorithm> 452329SN/A#include <string> 462292SN/A 473577Sgblack@eecs.umich.edu#include "arch/utility.hh" 488229Snate@binkert.org#include "base/loader/symtab.hh" 495953Ssaidi@eecs.umich.edu#include "base/cp_annotate.hh" 506658Snate@binkert.org#include "config/the_isa.hh" 518887Sgeoffrey.blake@arm.com#include "cpu/checker/cpu.hh" 521717SN/A#include "cpu/o3/commit.hh" 532292SN/A#include "cpu/o3/thread_state.hh" 548662SAli.Saidi@ARM.com#include "cpu/base.hh" 558229Snate@binkert.org#include "cpu/exetrace.hh" 568229Snate@binkert.org#include "cpu/timebuf.hh" 578232Snate@binkert.org#include "debug/Activity.hh" 588232Snate@binkert.org#include "debug/Commit.hh" 598232Snate@binkert.org#include "debug/CommitRate.hh" 608232Snate@binkert.org#include "debug/ExecFaulting.hh" 618471SGiacomo.Gabrielli@arm.com#include "debug/O3PipeView.hh" 626221Snate@binkert.org#include "params/DerivO3CPU.hh" 638230Snate@binkert.org#include "sim/faults.hh" 648793Sgblack@eecs.umich.edu#include "sim/full_system.hh" 652292SN/A 666221Snate@binkert.orgusing namespace std; 675529Snate@binkert.org 681061SN/Atemplate <class Impl> 692292SN/ADefaultCommit<Impl>::TrapEvent::TrapEvent(DefaultCommit<Impl> *_commit, 706221Snate@binkert.org ThreadID _tid) 718581Ssteve.reinhardt@amd.com : Event(CPU_Tick_Pri, AutoDelete), commit(_commit), tid(_tid) 721060SN/A{ 731060SN/A} 741060SN/A 751061SN/Atemplate <class Impl> 761060SN/Avoid 772292SN/ADefaultCommit<Impl>::TrapEvent::process() 781062SN/A{ 792316SN/A // This will get reset by commit if it was switched out at the 802316SN/A // time of this event processing. 812292SN/A commit->trapSquash[tid] = true; 822292SN/A} 832292SN/A 842292SN/Atemplate <class Impl> 852292SN/Aconst char * 865336Shines@cs.fsu.eduDefaultCommit<Impl>::TrapEvent::description() const 872292SN/A{ 884873Sstever@eecs.umich.edu return "Trap"; 892292SN/A} 902292SN/A 912292SN/Atemplate <class Impl> 925529Snate@binkert.orgDefaultCommit<Impl>::DefaultCommit(O3CPU *_cpu, DerivO3CPUParams *params) 934329Sktlim@umich.edu : cpu(_cpu), 944329Sktlim@umich.edu squashCounter(0), 952292SN/A iewToCommitDelay(params->iewToCommitDelay), 962292SN/A commitToIEWDelay(params->commitToIEWDelay), 972292SN/A renameToROBDelay(params->renameToROBDelay), 982292SN/A fetchToCommitDelay(params->commitToFetchDelay), 992292SN/A renameWidth(params->renameWidth), 1002292SN/A commitWidth(params->commitWidth), 1015529Snate@binkert.org numThreads(params->numThreads), 1022843Sktlim@umich.edu drainPending(false), 1032316SN/A switchedOut(false), 1048823Snilay@cs.wisc.edu trapLatency(params->trapLatency), 1058823Snilay@cs.wisc.edu canHandleInterrupts(true) 1062292SN/A{ 1072292SN/A _status = Active; 1082292SN/A _nextStatus = Inactive; 1092980Sgblack@eecs.umich.edu std::string policy = params->smtCommitPolicy; 1102292SN/A 1112292SN/A //Convert string to lowercase 1122292SN/A std::transform(policy.begin(), policy.end(), policy.begin(), 1132292SN/A (int(*)(int)) tolower); 1142292SN/A 1152292SN/A //Assign commit policy 1162292SN/A if (policy == "aggressive"){ 1172292SN/A commitPolicy = Aggressive; 1182292SN/A 1198346Sksewell@umich.edu DPRINTF(Commit,"Commit Policy set to Aggressive.\n"); 1202292SN/A } else if (policy == "roundrobin"){ 1212292SN/A commitPolicy = RoundRobin; 1222292SN/A 1232292SN/A //Set-Up Priority List 1246221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; tid++) { 1252292SN/A priority_list.push_back(tid); 1262292SN/A } 1272292SN/A 1288346Sksewell@umich.edu DPRINTF(Commit,"Commit Policy set to Round Robin.\n"); 1292292SN/A } else if (policy == "oldestready"){ 1302292SN/A commitPolicy = OldestReady; 1312292SN/A 1324329Sktlim@umich.edu DPRINTF(Commit,"Commit Policy set to Oldest Ready."); 1332292SN/A } else { 1342292SN/A assert(0 && "Invalid SMT Commit Policy. Options Are: {Aggressive," 1352292SN/A "RoundRobin,OldestReady}"); 1362292SN/A } 1372292SN/A 1386221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; tid++) { 1396221Snate@binkert.org commitStatus[tid] = Idle; 1406221Snate@binkert.org changedROBNumEntries[tid] = false; 1416221Snate@binkert.org checkEmptyROB[tid] = false; 1426221Snate@binkert.org trapInFlight[tid] = false; 1436221Snate@binkert.org committedStores[tid] = false; 1446221Snate@binkert.org trapSquash[tid] = false; 1456221Snate@binkert.org tcSquash[tid] = false; 1467720Sgblack@eecs.umich.edu pc[tid].set(0); 1477855SAli.Saidi@ARM.com lastCommitedSeqNum[tid] = 0; 1482292SN/A } 1493640Sktlim@umich.edu interrupt = NoFault; 1502292SN/A} 1512292SN/A 1522292SN/Atemplate <class Impl> 1532292SN/Astd::string 1542292SN/ADefaultCommit<Impl>::name() const 1552292SN/A{ 1562292SN/A return cpu->name() + ".commit"; 1572292SN/A} 1582292SN/A 1592292SN/Atemplate <class Impl> 1602292SN/Avoid 1612292SN/ADefaultCommit<Impl>::regStats() 1622132SN/A{ 1632301SN/A using namespace Stats; 1641062SN/A commitCommittedInsts 1651062SN/A .name(name() + ".commitCommittedInsts") 1661062SN/A .desc("The number of committed instructions") 1671062SN/A .prereq(commitCommittedInsts); 1688834Satgutier@umich.edu commitCommittedOps 1698834Satgutier@umich.edu .name(name() + ".commitCommittedOps") 1708834Satgutier@umich.edu .desc("The number of committed instructions") 1718834Satgutier@umich.edu .prereq(commitCommittedInsts); 1721062SN/A commitSquashedInsts 1731062SN/A .name(name() + ".commitSquashedInsts") 1741062SN/A .desc("The number of squashed insts skipped by commit") 1751062SN/A .prereq(commitSquashedInsts); 1761062SN/A commitSquashEvents 1771062SN/A .name(name() + ".commitSquashEvents") 1781062SN/A .desc("The number of times commit is told to squash") 1791062SN/A .prereq(commitSquashEvents); 1801062SN/A commitNonSpecStalls 1811062SN/A .name(name() + ".commitNonSpecStalls") 1821062SN/A .desc("The number of times commit has been forced to stall to " 1831062SN/A "communicate backwards") 1841062SN/A .prereq(commitNonSpecStalls); 1851062SN/A branchMispredicts 1861062SN/A .name(name() + ".branchMispredicts") 1871062SN/A .desc("The number of times a branch was mispredicted") 1881062SN/A .prereq(branchMispredicts); 1892292SN/A numCommittedDist 1901062SN/A .init(0,commitWidth,1) 1918240Snate@binkert.org .name(name() + ".committed_per_cycle") 1921062SN/A .desc("Number of insts commited each cycle") 1931062SN/A .flags(Stats::pdf) 1941062SN/A ; 1952301SN/A 1968834Satgutier@umich.edu instsCommitted 1976221Snate@binkert.org .init(cpu->numThreads) 1988834Satgutier@umich.edu .name(name() + ".committedInsts") 1992301SN/A .desc("Number of instructions committed") 2002301SN/A .flags(total) 2012301SN/A ; 2022301SN/A 2038834Satgutier@umich.edu opsCommitted 2048834Satgutier@umich.edu .init(cpu->numThreads) 2058834Satgutier@umich.edu .name(name() + ".committedOps") 2068834Satgutier@umich.edu .desc("Number of ops (including micro ops) committed") 2078834Satgutier@umich.edu .flags(total) 2088834Satgutier@umich.edu ; 2098834Satgutier@umich.edu 2102316SN/A statComSwp 2116221Snate@binkert.org .init(cpu->numThreads) 2128240Snate@binkert.org .name(name() + ".swp_count") 2132301SN/A .desc("Number of s/w prefetches committed") 2142301SN/A .flags(total) 2152301SN/A ; 2162301SN/A 2172316SN/A statComRefs 2186221Snate@binkert.org .init(cpu->numThreads) 2198240Snate@binkert.org .name(name() + ".refs") 2202301SN/A .desc("Number of memory references committed") 2212301SN/A .flags(total) 2222301SN/A ; 2232301SN/A 2242316SN/A statComLoads 2256221Snate@binkert.org .init(cpu->numThreads) 2268240Snate@binkert.org .name(name() + ".loads") 2272301SN/A .desc("Number of loads committed") 2282301SN/A .flags(total) 2292301SN/A ; 2302301SN/A 2312316SN/A statComMembars 2326221Snate@binkert.org .init(cpu->numThreads) 2338240Snate@binkert.org .name(name() + ".membars") 2342301SN/A .desc("Number of memory barriers committed") 2352301SN/A .flags(total) 2362301SN/A ; 2372301SN/A 2382316SN/A statComBranches 2396221Snate@binkert.org .init(cpu->numThreads) 2408240Snate@binkert.org .name(name() + ".branches") 2412301SN/A .desc("Number of branches committed") 2422301SN/A .flags(total) 2432301SN/A ; 2442301SN/A 2457897Shestness@cs.utexas.edu statComFloating 2467897Shestness@cs.utexas.edu .init(cpu->numThreads) 2478240Snate@binkert.org .name(name() + ".fp_insts") 2487897Shestness@cs.utexas.edu .desc("Number of committed floating point instructions.") 2497897Shestness@cs.utexas.edu .flags(total) 2507897Shestness@cs.utexas.edu ; 2517897Shestness@cs.utexas.edu 2527897Shestness@cs.utexas.edu statComInteger 2537897Shestness@cs.utexas.edu .init(cpu->numThreads) 2548240Snate@binkert.org .name(name()+".int_insts") 2557897Shestness@cs.utexas.edu .desc("Number of committed integer instructions.") 2567897Shestness@cs.utexas.edu .flags(total) 2577897Shestness@cs.utexas.edu ; 2587897Shestness@cs.utexas.edu 2597897Shestness@cs.utexas.edu statComFunctionCalls 2607897Shestness@cs.utexas.edu .init(cpu->numThreads) 2618240Snate@binkert.org .name(name()+".function_calls") 2627897Shestness@cs.utexas.edu .desc("Number of function calls committed.") 2637897Shestness@cs.utexas.edu .flags(total) 2647897Shestness@cs.utexas.edu ; 2657897Shestness@cs.utexas.edu 2662316SN/A commitEligible 2676221Snate@binkert.org .init(cpu->numThreads) 2688240Snate@binkert.org .name(name() + ".bw_limited") 2692301SN/A .desc("number of insts not committed due to BW limits") 2702301SN/A .flags(total) 2712301SN/A ; 2722301SN/A 2732316SN/A commitEligibleSamples 2748240Snate@binkert.org .name(name() + ".bw_lim_events") 2752301SN/A .desc("number cycles where commit BW limit reached") 2762301SN/A ; 2771062SN/A} 2781062SN/A 2791062SN/Atemplate <class Impl> 2801062SN/Avoid 2812980Sgblack@eecs.umich.eduDefaultCommit<Impl>::setThreads(std::vector<Thread *> &threads) 2822292SN/A{ 2832292SN/A thread = threads; 2842292SN/A} 2852292SN/A 2862292SN/Atemplate <class Impl> 2872292SN/Avoid 2882292SN/ADefaultCommit<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) 2891060SN/A{ 2901060SN/A timeBuffer = tb_ptr; 2911060SN/A 2921060SN/A // Setup wire to send information back to IEW. 2931060SN/A toIEW = timeBuffer->getWire(0); 2941060SN/A 2951060SN/A // Setup wire to read data from IEW (for the ROB). 2961060SN/A robInfoFromIEW = timeBuffer->getWire(-iewToCommitDelay); 2971060SN/A} 2981060SN/A 2991061SN/Atemplate <class Impl> 3001060SN/Avoid 3012292SN/ADefaultCommit<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr) 3022292SN/A{ 3032292SN/A fetchQueue = fq_ptr; 3042292SN/A 3052292SN/A // Setup wire to get instructions from rename (for the ROB). 3062292SN/A fromFetch = fetchQueue->getWire(-fetchToCommitDelay); 3072292SN/A} 3082292SN/A 3092292SN/Atemplate <class Impl> 3102292SN/Avoid 3112292SN/ADefaultCommit<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr) 3121060SN/A{ 3131060SN/A renameQueue = rq_ptr; 3141060SN/A 3151060SN/A // Setup wire to get instructions from rename (for the ROB). 3161060SN/A fromRename = renameQueue->getWire(-renameToROBDelay); 3171060SN/A} 3181060SN/A 3191061SN/Atemplate <class Impl> 3201060SN/Avoid 3212292SN/ADefaultCommit<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr) 3221060SN/A{ 3231060SN/A iewQueue = iq_ptr; 3241060SN/A 3251060SN/A // Setup wire to get instructions from IEW. 3261060SN/A fromIEW = iewQueue->getWire(-iewToCommitDelay); 3271060SN/A} 3281060SN/A 3291061SN/Atemplate <class Impl> 3301060SN/Avoid 3312292SN/ADefaultCommit<Impl>::setIEWStage(IEW *iew_stage) 3322292SN/A{ 3332292SN/A iewStage = iew_stage; 3342292SN/A} 3352292SN/A 3362292SN/Atemplate<class Impl> 3372292SN/Avoid 3386221Snate@binkert.orgDefaultCommit<Impl>::setActiveThreads(list<ThreadID> *at_ptr) 3392292SN/A{ 3402292SN/A activeThreads = at_ptr; 3412292SN/A} 3422292SN/A 3432292SN/Atemplate <class Impl> 3442292SN/Avoid 3452292SN/ADefaultCommit<Impl>::setRenameMap(RenameMap rm_ptr[]) 3462292SN/A{ 3476221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; tid++) 3486221Snate@binkert.org renameMap[tid] = &rm_ptr[tid]; 3492292SN/A} 3502292SN/A 3512292SN/Atemplate <class Impl> 3522292SN/Avoid 3532292SN/ADefaultCommit<Impl>::setROB(ROB *rob_ptr) 3541060SN/A{ 3551060SN/A rob = rob_ptr; 3561060SN/A} 3571060SN/A 3581061SN/Atemplate <class Impl> 3591060SN/Avoid 3602292SN/ADefaultCommit<Impl>::initStage() 3611060SN/A{ 3622292SN/A rob->setActiveThreads(activeThreads); 3632292SN/A rob->resetEntries(); 3641060SN/A 3652292SN/A // Broadcast the number of free entries. 3666221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; tid++) { 3676221Snate@binkert.org toIEW->commitInfo[tid].usedROB = true; 3686221Snate@binkert.org toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid); 3696221Snate@binkert.org toIEW->commitInfo[tid].emptyROB = true; 3701060SN/A } 3711060SN/A 3724329Sktlim@umich.edu // Commit must broadcast the number of free entries it has at the 3734329Sktlim@umich.edu // start of the simulation, so it starts as active. 3744329Sktlim@umich.edu cpu->activateStage(O3CPU::CommitIdx); 3754329Sktlim@umich.edu 3762292SN/A cpu->activityThisCycle(); 3771060SN/A} 3781060SN/A 3791061SN/Atemplate <class Impl> 3802863Sktlim@umich.edubool 3812843Sktlim@umich.eduDefaultCommit<Impl>::drain() 3821060SN/A{ 3832843Sktlim@umich.edu drainPending = true; 3842863Sktlim@umich.edu 3852863Sktlim@umich.edu return false; 3862316SN/A} 3872316SN/A 3882316SN/Atemplate <class Impl> 3892316SN/Avoid 3902843Sktlim@umich.eduDefaultCommit<Impl>::switchOut() 3912316SN/A{ 3922316SN/A switchedOut = true; 3932843Sktlim@umich.edu drainPending = false; 3942307SN/A rob->switchOut(); 3952307SN/A} 3962307SN/A 3972307SN/Atemplate <class Impl> 3982307SN/Avoid 3992843Sktlim@umich.eduDefaultCommit<Impl>::resume() 4002843Sktlim@umich.edu{ 4012864Sktlim@umich.edu drainPending = false; 4022843Sktlim@umich.edu} 4032843Sktlim@umich.edu 4042843Sktlim@umich.edutemplate <class Impl> 4052843Sktlim@umich.eduvoid 4062307SN/ADefaultCommit<Impl>::takeOverFrom() 4072307SN/A{ 4082316SN/A switchedOut = false; 4092307SN/A _status = Active; 4102307SN/A _nextStatus = Inactive; 4116221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; tid++) { 4126221Snate@binkert.org commitStatus[tid] = Idle; 4136221Snate@binkert.org changedROBNumEntries[tid] = false; 4146221Snate@binkert.org trapSquash[tid] = false; 4156221Snate@binkert.org tcSquash[tid] = false; 4162307SN/A } 4172307SN/A squashCounter = 0; 4182307SN/A rob->takeOverFrom(); 4192307SN/A} 4202307SN/A 4212307SN/Atemplate <class Impl> 4222307SN/Avoid 4232292SN/ADefaultCommit<Impl>::updateStatus() 4242132SN/A{ 4252316SN/A // reset ROB changed variable 4266221Snate@binkert.org list<ThreadID>::iterator threads = activeThreads->begin(); 4276221Snate@binkert.org list<ThreadID>::iterator end = activeThreads->end(); 4283867Sbinkertn@umich.edu 4293867Sbinkertn@umich.edu while (threads != end) { 4306221Snate@binkert.org ThreadID tid = *threads++; 4313867Sbinkertn@umich.edu 4322316SN/A changedROBNumEntries[tid] = false; 4332316SN/A 4342316SN/A // Also check if any of the threads has a trap pending 4352316SN/A if (commitStatus[tid] == TrapPending || 4362316SN/A commitStatus[tid] == FetchTrapPending) { 4372316SN/A _nextStatus = Active; 4382316SN/A } 4392292SN/A } 4402292SN/A 4412292SN/A if (_nextStatus == Inactive && _status == Active) { 4422292SN/A DPRINTF(Activity, "Deactivating stage.\n"); 4432733Sktlim@umich.edu cpu->deactivateStage(O3CPU::CommitIdx); 4442292SN/A } else if (_nextStatus == Active && _status == Inactive) { 4452292SN/A DPRINTF(Activity, "Activating stage.\n"); 4462733Sktlim@umich.edu cpu->activateStage(O3CPU::CommitIdx); 4472292SN/A } 4482292SN/A 4492292SN/A _status = _nextStatus; 4502292SN/A} 4512292SN/A 4522292SN/Atemplate <class Impl> 4532292SN/Avoid 4542292SN/ADefaultCommit<Impl>::setNextStatus() 4552292SN/A{ 4562292SN/A int squashes = 0; 4572292SN/A 4586221Snate@binkert.org list<ThreadID>::iterator threads = activeThreads->begin(); 4596221Snate@binkert.org list<ThreadID>::iterator end = activeThreads->end(); 4602292SN/A 4613867Sbinkertn@umich.edu while (threads != end) { 4626221Snate@binkert.org ThreadID tid = *threads++; 4632292SN/A 4642292SN/A if (commitStatus[tid] == ROBSquashing) { 4652292SN/A squashes++; 4662292SN/A } 4672292SN/A } 4682292SN/A 4692702Sktlim@umich.edu squashCounter = squashes; 4702292SN/A 4712292SN/A // If commit is currently squashing, then it will have activity for the 4722292SN/A // next cycle. Set its next status as active. 4732292SN/A if (squashCounter) { 4742292SN/A _nextStatus = Active; 4752292SN/A } 4762292SN/A} 4772292SN/A 4782292SN/Atemplate <class Impl> 4792292SN/Abool 4802292SN/ADefaultCommit<Impl>::changedROBEntries() 4812292SN/A{ 4826221Snate@binkert.org list<ThreadID>::iterator threads = activeThreads->begin(); 4836221Snate@binkert.org list<ThreadID>::iterator end = activeThreads->end(); 4842292SN/A 4853867Sbinkertn@umich.edu while (threads != end) { 4866221Snate@binkert.org ThreadID tid = *threads++; 4872292SN/A 4882292SN/A if (changedROBNumEntries[tid]) { 4892292SN/A return true; 4902292SN/A } 4912292SN/A } 4922292SN/A 4932292SN/A return false; 4942292SN/A} 4952292SN/A 4962292SN/Atemplate <class Impl> 4976221Snate@binkert.orgsize_t 4986221Snate@binkert.orgDefaultCommit<Impl>::numROBFreeEntries(ThreadID tid) 4992292SN/A{ 5002292SN/A return rob->numFreeEntries(tid); 5012292SN/A} 5022292SN/A 5032292SN/Atemplate <class Impl> 5042292SN/Avoid 5056221Snate@binkert.orgDefaultCommit<Impl>::generateTrapEvent(ThreadID tid) 5062292SN/A{ 5072292SN/A DPRINTF(Commit, "Generating trap event for [tid:%i]\n", tid); 5082292SN/A 5092292SN/A TrapEvent *trap = new TrapEvent(this, tid); 5102292SN/A 5119179Sandreas.hansson@arm.com cpu->schedule(trap, cpu->clockEdge(trapLatency)); 5124035Sktlim@umich.edu trapInFlight[tid] = true; 5138518Sgeoffrey.blake@arm.com thread[tid]->trapPending = true; 5142292SN/A} 5152292SN/A 5162292SN/Atemplate <class Impl> 5172292SN/Avoid 5186221Snate@binkert.orgDefaultCommit<Impl>::generateTCEvent(ThreadID tid) 5192292SN/A{ 5204035Sktlim@umich.edu assert(!trapInFlight[tid]); 5212680Sktlim@umich.edu DPRINTF(Commit, "Generating TC squash event for [tid:%i]\n", tid); 5222292SN/A 5232680Sktlim@umich.edu tcSquash[tid] = true; 5242292SN/A} 5252292SN/A 5262292SN/Atemplate <class Impl> 5272292SN/Avoid 5286221Snate@binkert.orgDefaultCommit<Impl>::squashAll(ThreadID tid) 5292292SN/A{ 5302292SN/A // If we want to include the squashing instruction in the squash, 5312292SN/A // then use one older sequence number. 5322292SN/A // Hopefully this doesn't mess things up. Basically I want to squash 5332292SN/A // all instructions of this thread. 5342292SN/A InstSeqNum squashed_inst = rob->isEmpty() ? 5357855SAli.Saidi@ARM.com lastCommitedSeqNum[tid] : rob->readHeadInst(tid)->seqNum - 1; 5362292SN/A 5372292SN/A // All younger instructions will be squashed. Set the sequence 5382292SN/A // number as the youngest instruction in the ROB (0 in this case. 5392292SN/A // Hopefully nothing breaks.) 5407855SAli.Saidi@ARM.com youngestSeqNum[tid] = lastCommitedSeqNum[tid]; 5412292SN/A 5422292SN/A rob->squash(squashed_inst, tid); 5432292SN/A changedROBNumEntries[tid] = true; 5442292SN/A 5452292SN/A // Send back the sequence number of the squashed instruction. 5462292SN/A toIEW->commitInfo[tid].doneSeqNum = squashed_inst; 5472292SN/A 5482292SN/A // Send back the squash signal to tell stages that they should 5492292SN/A // squash. 5502292SN/A toIEW->commitInfo[tid].squash = true; 5512292SN/A 5522292SN/A // Send back the rob squashing signal so other stages know that 5532292SN/A // the ROB is in the process of squashing. 5542292SN/A toIEW->commitInfo[tid].robSquashing = true; 5552292SN/A 5567851SMatt.Horsnell@arm.com toIEW->commitInfo[tid].mispredictInst = NULL; 5578137SAli.Saidi@ARM.com toIEW->commitInfo[tid].squashInst = NULL; 5582292SN/A 5597720Sgblack@eecs.umich.edu toIEW->commitInfo[tid].pc = pc[tid]; 5602316SN/A} 5612292SN/A 5622316SN/Atemplate <class Impl> 5632316SN/Avoid 5646221Snate@binkert.orgDefaultCommit<Impl>::squashFromTrap(ThreadID tid) 5652316SN/A{ 5662316SN/A squashAll(tid); 5672316SN/A 5687720Sgblack@eecs.umich.edu DPRINTF(Commit, "Squashing from trap, restarting at PC %s\n", pc[tid]); 5692316SN/A 5702316SN/A thread[tid]->trapPending = false; 5712316SN/A thread[tid]->inSyscall = false; 5724035Sktlim@umich.edu trapInFlight[tid] = false; 5732316SN/A 5742316SN/A trapSquash[tid] = false; 5752316SN/A 5762316SN/A commitStatus[tid] = ROBSquashing; 5772316SN/A cpu->activityThisCycle(); 5782316SN/A} 5792316SN/A 5802316SN/Atemplate <class Impl> 5812316SN/Avoid 5826221Snate@binkert.orgDefaultCommit<Impl>::squashFromTC(ThreadID tid) 5832316SN/A{ 5842316SN/A squashAll(tid); 5852292SN/A 5867720Sgblack@eecs.umich.edu DPRINTF(Commit, "Squashing from TC, restarting at PC %s\n", pc[tid]); 5872292SN/A 5882292SN/A thread[tid]->inSyscall = false; 5892292SN/A assert(!thread[tid]->trapPending); 5902316SN/A 5912292SN/A commitStatus[tid] = ROBSquashing; 5922292SN/A cpu->activityThisCycle(); 5932292SN/A 5942680Sktlim@umich.edu tcSquash[tid] = false; 5952292SN/A} 5962292SN/A 5972292SN/Atemplate <class Impl> 5982292SN/Avoid 5998137SAli.Saidi@ARM.comDefaultCommit<Impl>::squashAfter(ThreadID tid, DynInstPtr &head_inst, 6008137SAli.Saidi@ARM.com uint64_t squash_after_seq_num) 6017784SAli.Saidi@ARM.com{ 6027784SAli.Saidi@ARM.com youngestSeqNum[tid] = squash_after_seq_num; 6037784SAli.Saidi@ARM.com 6047784SAli.Saidi@ARM.com rob->squash(squash_after_seq_num, tid); 6057784SAli.Saidi@ARM.com changedROBNumEntries[tid] = true; 6067784SAli.Saidi@ARM.com 6077784SAli.Saidi@ARM.com // Send back the sequence number of the squashed instruction. 6087784SAli.Saidi@ARM.com toIEW->commitInfo[tid].doneSeqNum = squash_after_seq_num; 6097784SAli.Saidi@ARM.com 6108137SAli.Saidi@ARM.com toIEW->commitInfo[tid].squashInst = head_inst; 6117784SAli.Saidi@ARM.com // Send back the squash signal to tell stages that they should squash. 6127784SAli.Saidi@ARM.com toIEW->commitInfo[tid].squash = true; 6137784SAli.Saidi@ARM.com 6147784SAli.Saidi@ARM.com // Send back the rob squashing signal so other stages know that 6157784SAli.Saidi@ARM.com // the ROB is in the process of squashing. 6167784SAli.Saidi@ARM.com toIEW->commitInfo[tid].robSquashing = true; 6177784SAli.Saidi@ARM.com 6188137SAli.Saidi@ARM.com toIEW->commitInfo[tid].mispredictInst = NULL; 6197784SAli.Saidi@ARM.com 6207784SAli.Saidi@ARM.com toIEW->commitInfo[tid].pc = pc[tid]; 6217784SAli.Saidi@ARM.com DPRINTF(Commit, "Executing squash after for [tid:%i] inst [sn:%lli]\n", 6227784SAli.Saidi@ARM.com tid, squash_after_seq_num); 6237784SAli.Saidi@ARM.com commitStatus[tid] = ROBSquashing; 6247784SAli.Saidi@ARM.com} 6257784SAli.Saidi@ARM.com 6267784SAli.Saidi@ARM.comtemplate <class Impl> 6277784SAli.Saidi@ARM.comvoid 6282292SN/ADefaultCommit<Impl>::tick() 6292292SN/A{ 6302292SN/A wroteToTimeBuffer = false; 6312292SN/A _nextStatus = Inactive; 6322292SN/A 6339152Satgutier@umich.edu if (drainPending && cpu->instList.empty() && !iewStage->hasStoresToWB() && 6349152Satgutier@umich.edu interrupt == NoFault) { 6352843Sktlim@umich.edu cpu->signalDrained(); 6362843Sktlim@umich.edu drainPending = false; 6372316SN/A return; 6382316SN/A } 6392316SN/A 6403867Sbinkertn@umich.edu if (activeThreads->empty()) 6412875Sksewell@umich.edu return; 6422875Sksewell@umich.edu 6436221Snate@binkert.org list<ThreadID>::iterator threads = activeThreads->begin(); 6446221Snate@binkert.org list<ThreadID>::iterator end = activeThreads->end(); 6452292SN/A 6462316SN/A // Check if any of the threads are done squashing. Change the 6472316SN/A // status if they are done. 6483867Sbinkertn@umich.edu while (threads != end) { 6496221Snate@binkert.org ThreadID tid = *threads++; 6502292SN/A 6514035Sktlim@umich.edu // Clear the bit saying if the thread has committed stores 6524035Sktlim@umich.edu // this cycle. 6534035Sktlim@umich.edu committedStores[tid] = false; 6544035Sktlim@umich.edu 6552292SN/A if (commitStatus[tid] == ROBSquashing) { 6562292SN/A 6572292SN/A if (rob->isDoneSquashing(tid)) { 6582292SN/A commitStatus[tid] = Running; 6592292SN/A } else { 6602292SN/A DPRINTF(Commit,"[tid:%u]: Still Squashing, cannot commit any" 6612877Sksewell@umich.edu " insts this cycle.\n", tid); 6622702Sktlim@umich.edu rob->doSquash(tid); 6632702Sktlim@umich.edu toIEW->commitInfo[tid].robSquashing = true; 6642702Sktlim@umich.edu wroteToTimeBuffer = true; 6652292SN/A } 6662292SN/A } 6672292SN/A } 6682292SN/A 6692292SN/A commit(); 6702292SN/A 6712292SN/A markCompletedInsts(); 6722292SN/A 6733867Sbinkertn@umich.edu threads = activeThreads->begin(); 6742292SN/A 6753867Sbinkertn@umich.edu while (threads != end) { 6766221Snate@binkert.org ThreadID tid = *threads++; 6772292SN/A 6782292SN/A if (!rob->isEmpty(tid) && rob->readHeadInst(tid)->readyToCommit()) { 6792292SN/A // The ROB has more instructions it can commit. Its next status 6802292SN/A // will be active. 6812292SN/A _nextStatus = Active; 6822292SN/A 6832292SN/A DynInstPtr inst = rob->readHeadInst(tid); 6842292SN/A 6857720Sgblack@eecs.umich.edu DPRINTF(Commit,"[tid:%i]: Instruction [sn:%lli] PC %s is head of" 6862292SN/A " ROB and ready to commit\n", 6877720Sgblack@eecs.umich.edu tid, inst->seqNum, inst->pcState()); 6882292SN/A 6892292SN/A } else if (!rob->isEmpty(tid)) { 6902292SN/A DynInstPtr inst = rob->readHeadInst(tid); 6912292SN/A 6922292SN/A DPRINTF(Commit,"[tid:%i]: Can't commit, Instruction [sn:%lli] PC " 6937720Sgblack@eecs.umich.edu "%s is head of ROB and not ready\n", 6947720Sgblack@eecs.umich.edu tid, inst->seqNum, inst->pcState()); 6952292SN/A } 6962292SN/A 6972292SN/A DPRINTF(Commit, "[tid:%i]: ROB has %d insts & %d free entries.\n", 6982292SN/A tid, rob->countInsts(tid), rob->numFreeEntries(tid)); 6992292SN/A } 7002292SN/A 7012292SN/A 7022292SN/A if (wroteToTimeBuffer) { 7032316SN/A DPRINTF(Activity, "Activity This Cycle.\n"); 7042292SN/A cpu->activityThisCycle(); 7052292SN/A } 7062292SN/A 7072292SN/A updateStatus(); 7082292SN/A} 7092292SN/A 7102292SN/Atemplate <class Impl> 7112292SN/Avoid 7124035Sktlim@umich.eduDefaultCommit<Impl>::handleInterrupt() 7132292SN/A{ 7147847Sminkyu.jeong@arm.com // Verify that we still have an interrupt to handle 7157847Sminkyu.jeong@arm.com if (!cpu->checkInterrupts(cpu->tcBase(0))) { 7167847Sminkyu.jeong@arm.com DPRINTF(Commit, "Pending interrupt is cleared by master before " 7177847Sminkyu.jeong@arm.com "it got handled. Restart fetching from the orig path.\n"); 7187847Sminkyu.jeong@arm.com toIEW->commitInfo[0].clearInterrupt = true; 7197847Sminkyu.jeong@arm.com interrupt = NoFault; 7207847Sminkyu.jeong@arm.com return; 7217847Sminkyu.jeong@arm.com } 7223633Sktlim@umich.edu 7238493Sgblack@eecs.umich.edu // Wait until all in flight instructions are finished before enterring 7248493Sgblack@eecs.umich.edu // the interrupt. 7258823Snilay@cs.wisc.edu if (canHandleInterrupts && cpu->instList.empty()) { 7267847Sminkyu.jeong@arm.com // Squash or record that I need to squash this cycle if 7277847Sminkyu.jeong@arm.com // an interrupt needed to be handled. 7287847Sminkyu.jeong@arm.com DPRINTF(Commit, "Interrupt detected.\n"); 7294035Sktlim@umich.edu 7307847Sminkyu.jeong@arm.com // Clear the interrupt now that it's going to be handled 7317847Sminkyu.jeong@arm.com toIEW->commitInfo[0].clearInterrupt = true; 7322292SN/A 7337847Sminkyu.jeong@arm.com assert(!thread[0]->inSyscall); 7347847Sminkyu.jeong@arm.com thread[0]->inSyscall = true; 7352292SN/A 7368733Sgeoffrey.blake@arm.com if (cpu->checker) { 7378733Sgeoffrey.blake@arm.com cpu->checker->handlePendingInt(); 7388733Sgeoffrey.blake@arm.com } 7398733Sgeoffrey.blake@arm.com 7407847Sminkyu.jeong@arm.com // CPU will handle interrupt. 7417847Sminkyu.jeong@arm.com cpu->processInterrupts(interrupt); 7423633Sktlim@umich.edu 7437847Sminkyu.jeong@arm.com thread[0]->inSyscall = false; 7442292SN/A 7457847Sminkyu.jeong@arm.com commitStatus[0] = TrapPending; 7462292SN/A 7477847Sminkyu.jeong@arm.com // Generate trap squash event. 7487847Sminkyu.jeong@arm.com generateTrapEvent(0); 7493640Sktlim@umich.edu 7507847Sminkyu.jeong@arm.com interrupt = NoFault; 7517847Sminkyu.jeong@arm.com } else { 7528823Snilay@cs.wisc.edu DPRINTF(Commit, "Interrupt pending: instruction is %sin " 7538823Snilay@cs.wisc.edu "flight, ROB is %sempty\n", 7548823Snilay@cs.wisc.edu canHandleInterrupts ? "not " : "", 7558823Snilay@cs.wisc.edu cpu->instList.empty() ? "" : "not " ); 7561060SN/A } 7574035Sktlim@umich.edu} 7587847Sminkyu.jeong@arm.com 7597847Sminkyu.jeong@arm.comtemplate <class Impl> 7607847Sminkyu.jeong@arm.comvoid 7617847Sminkyu.jeong@arm.comDefaultCommit<Impl>::propagateInterrupt() 7627847Sminkyu.jeong@arm.com{ 7637847Sminkyu.jeong@arm.com if (commitStatus[0] == TrapPending || interrupt || trapSquash[0] || 7647847Sminkyu.jeong@arm.com tcSquash[0]) 7657847Sminkyu.jeong@arm.com return; 7667847Sminkyu.jeong@arm.com 7677847Sminkyu.jeong@arm.com // Process interrupts if interrupts are enabled, not in PAL 7687847Sminkyu.jeong@arm.com // mode, and no other traps or external squashes are currently 7697847Sminkyu.jeong@arm.com // pending. 7707847Sminkyu.jeong@arm.com // @todo: Allow other threads to handle interrupts. 7717847Sminkyu.jeong@arm.com 7727847Sminkyu.jeong@arm.com // Get any interrupt that happened 7737847Sminkyu.jeong@arm.com interrupt = cpu->getInterrupts(); 7747847Sminkyu.jeong@arm.com 7757847Sminkyu.jeong@arm.com // Tell fetch that there is an interrupt pending. This 7767847Sminkyu.jeong@arm.com // will make fetch wait until it sees a non PAL-mode PC, 7777847Sminkyu.jeong@arm.com // at which point it stops fetching instructions. 7787847Sminkyu.jeong@arm.com if (interrupt != NoFault) 7797847Sminkyu.jeong@arm.com toIEW->commitInfo[0].interruptPending = true; 7807847Sminkyu.jeong@arm.com} 7817847Sminkyu.jeong@arm.com 7824035Sktlim@umich.edutemplate <class Impl> 7834035Sktlim@umich.eduvoid 7844035Sktlim@umich.eduDefaultCommit<Impl>::commit() 7854035Sktlim@umich.edu{ 7868793Sgblack@eecs.umich.edu if (FullSystem) { 7878793Sgblack@eecs.umich.edu // Check if we have a interrupt and get read to handle it 7888793Sgblack@eecs.umich.edu if (cpu->checkInterrupts(cpu->tcBase(0))) 7898793Sgblack@eecs.umich.edu propagateInterrupt(); 7908793Sgblack@eecs.umich.edu } 7911060SN/A 7921060SN/A //////////////////////////////////// 7932316SN/A // Check for any possible squashes, handle them first 7941060SN/A //////////////////////////////////// 7956221Snate@binkert.org list<ThreadID>::iterator threads = activeThreads->begin(); 7966221Snate@binkert.org list<ThreadID>::iterator end = activeThreads->end(); 7971060SN/A 7983867Sbinkertn@umich.edu while (threads != end) { 7996221Snate@binkert.org ThreadID tid = *threads++; 8001060SN/A 8012292SN/A // Not sure which one takes priority. I think if we have 8022292SN/A // both, that's a bad sign. 8032292SN/A if (trapSquash[tid] == true) { 8042680Sktlim@umich.edu assert(!tcSquash[tid]); 8052292SN/A squashFromTrap(tid); 8062680Sktlim@umich.edu } else if (tcSquash[tid] == true) { 8074035Sktlim@umich.edu assert(commitStatus[tid] != TrapPending); 8082680Sktlim@umich.edu squashFromTC(tid); 8092292SN/A } 8101061SN/A 8112292SN/A // Squashed sequence number must be older than youngest valid 8122292SN/A // instruction in the ROB. This prevents squashes from younger 8132292SN/A // instructions overriding squashes from older instructions. 8142292SN/A if (fromIEW->squash[tid] && 8152292SN/A commitStatus[tid] != TrapPending && 8162292SN/A fromIEW->squashedSeqNum[tid] <= youngestSeqNum[tid]) { 8171061SN/A 8188137SAli.Saidi@ARM.com if (fromIEW->mispredictInst[tid]) { 8198137SAli.Saidi@ARM.com DPRINTF(Commit, 8208137SAli.Saidi@ARM.com "[tid:%i]: Squashing due to branch mispred PC:%#x [sn:%i]\n", 8212292SN/A tid, 8228137SAli.Saidi@ARM.com fromIEW->mispredictInst[tid]->instAddr(), 8232292SN/A fromIEW->squashedSeqNum[tid]); 8248137SAli.Saidi@ARM.com } else { 8258137SAli.Saidi@ARM.com DPRINTF(Commit, 8268137SAli.Saidi@ARM.com "[tid:%i]: Squashing due to order violation [sn:%i]\n", 8278137SAli.Saidi@ARM.com tid, fromIEW->squashedSeqNum[tid]); 8288137SAli.Saidi@ARM.com } 8291061SN/A 8302292SN/A DPRINTF(Commit, "[tid:%i]: Redirecting to PC %#x\n", 8312292SN/A tid, 8327720Sgblack@eecs.umich.edu fromIEW->pc[tid].nextInstAddr()); 8331061SN/A 8342292SN/A commitStatus[tid] = ROBSquashing; 8351061SN/A 8362292SN/A // If we want to include the squashing instruction in the squash, 8372292SN/A // then use one older sequence number. 8382292SN/A InstSeqNum squashed_inst = fromIEW->squashedSeqNum[tid]; 8391062SN/A 8402935Sksewell@umich.edu if (fromIEW->includeSquashInst[tid] == true) { 8412292SN/A squashed_inst--; 8422935Sksewell@umich.edu } 8434035Sktlim@umich.edu 8442292SN/A // All younger instructions will be squashed. Set the sequence 8452292SN/A // number as the youngest instruction in the ROB. 8462292SN/A youngestSeqNum[tid] = squashed_inst; 8472292SN/A 8483093Sksewell@umich.edu rob->squash(squashed_inst, tid); 8492292SN/A changedROBNumEntries[tid] = true; 8502292SN/A 8512292SN/A toIEW->commitInfo[tid].doneSeqNum = squashed_inst; 8522292SN/A 8532292SN/A toIEW->commitInfo[tid].squash = true; 8542292SN/A 8552292SN/A // Send back the rob squashing signal so other stages know that 8562292SN/A // the ROB is in the process of squashing. 8572292SN/A toIEW->commitInfo[tid].robSquashing = true; 8582292SN/A 8597851SMatt.Horsnell@arm.com toIEW->commitInfo[tid].mispredictInst = 8607851SMatt.Horsnell@arm.com fromIEW->mispredictInst[tid]; 8612292SN/A toIEW->commitInfo[tid].branchTaken = 8622292SN/A fromIEW->branchTaken[tid]; 8638822Snilay@cs.wisc.edu toIEW->commitInfo[tid].squashInst = 8648822Snilay@cs.wisc.edu rob->findInst(tid, squashed_inst); 8658842Smrinmoy.ghosh@arm.com if (toIEW->commitInfo[tid].mispredictInst) { 8668842Smrinmoy.ghosh@arm.com if (toIEW->commitInfo[tid].mispredictInst->isUncondCtrl()) { 8678842Smrinmoy.ghosh@arm.com toIEW->commitInfo[tid].branchTaken = true; 8688842Smrinmoy.ghosh@arm.com } 8698842Smrinmoy.ghosh@arm.com } 8702292SN/A 8717720Sgblack@eecs.umich.edu toIEW->commitInfo[tid].pc = fromIEW->pc[tid]; 8722292SN/A 8738137SAli.Saidi@ARM.com if (toIEW->commitInfo[tid].mispredictInst) { 8742292SN/A ++branchMispredicts; 8752292SN/A } 8761062SN/A } 8772292SN/A 8781060SN/A } 8791060SN/A 8802292SN/A setNextStatus(); 8812292SN/A 8822292SN/A if (squashCounter != numThreads) { 8831061SN/A // If we're not currently squashing, then get instructions. 8841060SN/A getInsts(); 8851060SN/A 8861061SN/A // Try to commit any instructions. 8871060SN/A commitInsts(); 8881060SN/A } 8891060SN/A 8902292SN/A //Check for any activity 8913867Sbinkertn@umich.edu threads = activeThreads->begin(); 8922292SN/A 8933867Sbinkertn@umich.edu while (threads != end) { 8946221Snate@binkert.org ThreadID tid = *threads++; 8952292SN/A 8962292SN/A if (changedROBNumEntries[tid]) { 8972292SN/A toIEW->commitInfo[tid].usedROB = true; 8982292SN/A toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid); 8992292SN/A 9002292SN/A wroteToTimeBuffer = true; 9012292SN/A changedROBNumEntries[tid] = false; 9024035Sktlim@umich.edu if (rob->isEmpty(tid)) 9034035Sktlim@umich.edu checkEmptyROB[tid] = true; 9042292SN/A } 9054035Sktlim@umich.edu 9064035Sktlim@umich.edu // ROB is only considered "empty" for previous stages if: a) 9074035Sktlim@umich.edu // ROB is empty, b) there are no outstanding stores, c) IEW 9084035Sktlim@umich.edu // stage has received any information regarding stores that 9094035Sktlim@umich.edu // committed. 9104035Sktlim@umich.edu // c) is checked by making sure to not consider the ROB empty 9114035Sktlim@umich.edu // on the same cycle as when stores have been committed. 9124035Sktlim@umich.edu // @todo: Make this handle multi-cycle communication between 9134035Sktlim@umich.edu // commit and IEW. 9144035Sktlim@umich.edu if (checkEmptyROB[tid] && rob->isEmpty(tid) && 9155557Sktlim@umich.edu !iewStage->hasStoresToWB(tid) && !committedStores[tid]) { 9164035Sktlim@umich.edu checkEmptyROB[tid] = false; 9174035Sktlim@umich.edu toIEW->commitInfo[tid].usedROB = true; 9184035Sktlim@umich.edu toIEW->commitInfo[tid].emptyROB = true; 9194035Sktlim@umich.edu toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid); 9204035Sktlim@umich.edu wroteToTimeBuffer = true; 9214035Sktlim@umich.edu } 9224035Sktlim@umich.edu 9231060SN/A } 9241060SN/A} 9251060SN/A 9261061SN/Atemplate <class Impl> 9271060SN/Avoid 9282292SN/ADefaultCommit<Impl>::commitInsts() 9291060SN/A{ 9301060SN/A //////////////////////////////////// 9311060SN/A // Handle commit 9322316SN/A // Note that commit will be handled prior to putting new 9332316SN/A // instructions in the ROB so that the ROB only tries to commit 9342316SN/A // instructions it has in this current cycle, and not instructions 9352316SN/A // it is writing in during this cycle. Can't commit and squash 9362316SN/A // things at the same time... 9371060SN/A //////////////////////////////////// 9381060SN/A 9392292SN/A DPRINTF(Commit, "Trying to commit instructions in the ROB.\n"); 9401060SN/A 9411060SN/A unsigned num_committed = 0; 9421060SN/A 9432292SN/A DynInstPtr head_inst; 9442316SN/A 9451060SN/A // Commit as many instructions as possible until the commit bandwidth 9461060SN/A // limit is reached, or it becomes impossible to commit any more. 9472292SN/A while (num_committed < commitWidth) { 9488823Snilay@cs.wisc.edu // Check for any interrupt that we've already squashed for 9498823Snilay@cs.wisc.edu // and start processing it. 9508823Snilay@cs.wisc.edu if (interrupt != NoFault) 9518823Snilay@cs.wisc.edu handleInterrupt(); 9528823Snilay@cs.wisc.edu 9532292SN/A int commit_thread = getCommittingThread(); 9541060SN/A 9552292SN/A if (commit_thread == -1 || !rob->isHeadReady(commit_thread)) 9562292SN/A break; 9572292SN/A 9582292SN/A head_inst = rob->readHeadInst(commit_thread); 9592292SN/A 9606221Snate@binkert.org ThreadID tid = head_inst->threadNumber; 9612292SN/A 9622292SN/A assert(tid == commit_thread); 9632292SN/A 9642292SN/A DPRINTF(Commit, "Trying to commit head instruction, [sn:%i] [tid:%i]\n", 9652292SN/A head_inst->seqNum, tid); 9662132SN/A 9672316SN/A // If the head instruction is squashed, it is ready to retire 9682316SN/A // (be removed from the ROB) at any time. 9691060SN/A if (head_inst->isSquashed()) { 9701060SN/A 9712292SN/A DPRINTF(Commit, "Retiring squashed instruction from " 9721060SN/A "ROB.\n"); 9731060SN/A 9742292SN/A rob->retireHead(commit_thread); 9751060SN/A 9761062SN/A ++commitSquashedInsts; 9771062SN/A 9782292SN/A // Record that the number of ROB entries has changed. 9792292SN/A changedROBNumEntries[tid] = true; 9801060SN/A } else { 9817720Sgblack@eecs.umich.edu pc[tid] = head_inst->pcState(); 9822292SN/A 9831060SN/A // Increment the total number of non-speculative instructions 9841060SN/A // executed. 9851060SN/A // Hack for now: it really shouldn't happen until after the 9861061SN/A // commit is deemed to be successful, but this count is needed 9871061SN/A // for syscalls. 9882292SN/A thread[tid]->funcExeInst++; 9891060SN/A 9901060SN/A // Try to commit the head instruction. 9911060SN/A bool commit_success = commitHead(head_inst, num_committed); 9921060SN/A 9931062SN/A if (commit_success) { 9941060SN/A ++num_committed; 9951060SN/A 9962292SN/A changedROBNumEntries[tid] = true; 9972292SN/A 9982292SN/A // Set the doneSeqNum to the youngest committed instruction. 9992292SN/A toIEW->commitInfo[tid].doneSeqNum = head_inst->seqNum; 10001060SN/A 10018834Satgutier@umich.edu if (!head_inst->isMicroop() || head_inst->isLastMicroop()) 10028834Satgutier@umich.edu ++commitCommittedInsts; 10038834Satgutier@umich.edu ++commitCommittedOps; 10041062SN/A 10052292SN/A // To match the old model, don't count nops and instruction 10062292SN/A // prefetches towards the total commit count. 10072292SN/A if (!head_inst->isNop() && !head_inst->isInstPrefetch()) { 10088834Satgutier@umich.edu cpu->instDone(tid, head_inst); 10091062SN/A } 10102292SN/A 10118823Snilay@cs.wisc.edu if (tid == 0) { 10128823Snilay@cs.wisc.edu canHandleInterrupts = (!head_inst->isDelayedCommit()) && 10138823Snilay@cs.wisc.edu ((THE_ISA != ALPHA_ISA) || 10148823Snilay@cs.wisc.edu (!(pc[0].instAddr() & 0x3))); 10158823Snilay@cs.wisc.edu } 10168823Snilay@cs.wisc.edu 10177783SGiacomo.Gabrielli@arm.com // Updates misc. registers. 10187783SGiacomo.Gabrielli@arm.com head_inst->updateMiscRegs(); 10197783SGiacomo.Gabrielli@arm.com 10208662SAli.Saidi@ARM.com cpu->traceFunctions(pc[tid].instAddr()); 10218662SAli.Saidi@ARM.com 10227720Sgblack@eecs.umich.edu TheISA::advancePC(pc[tid], head_inst->staticInst); 10232935Sksewell@umich.edu 10247855SAli.Saidi@ARM.com // Keep track of the last sequence number commited 10257855SAli.Saidi@ARM.com lastCommitedSeqNum[tid] = head_inst->seqNum; 10267855SAli.Saidi@ARM.com 10277784SAli.Saidi@ARM.com // If this is an instruction that doesn't play nicely with 10287784SAli.Saidi@ARM.com // others squash everything and restart fetch 10297784SAli.Saidi@ARM.com if (head_inst->isSquashAfter()) 10308137SAli.Saidi@ARM.com squashAfter(tid, head_inst, head_inst->seqNum); 10317784SAli.Saidi@ARM.com 10322292SN/A int count = 0; 10332292SN/A Addr oldpc; 10345108Sgblack@eecs.umich.edu // Debug statement. Checks to make sure we're not 10355108Sgblack@eecs.umich.edu // currently updating state while handling PC events. 10365108Sgblack@eecs.umich.edu assert(!thread[tid]->inSyscall && !thread[tid]->trapPending); 10372292SN/A do { 10387720Sgblack@eecs.umich.edu oldpc = pc[tid].instAddr(); 10395108Sgblack@eecs.umich.edu cpu->system->pcEventQueue.service(thread[tid]->getTC()); 10402292SN/A count++; 10417720Sgblack@eecs.umich.edu } while (oldpc != pc[tid].instAddr()); 10422292SN/A if (count > 1) { 10435108Sgblack@eecs.umich.edu DPRINTF(Commit, 10445108Sgblack@eecs.umich.edu "PC skip function event, stopping commit\n"); 10452292SN/A break; 10462292SN/A } 10471060SN/A } else { 10487720Sgblack@eecs.umich.edu DPRINTF(Commit, "Unable to commit head instruction PC:%s " 10492292SN/A "[tid:%i] [sn:%i].\n", 10507720Sgblack@eecs.umich.edu head_inst->pcState(), tid ,head_inst->seqNum); 10511060SN/A break; 10521060SN/A } 10531060SN/A } 10541060SN/A } 10551062SN/A 10561063SN/A DPRINTF(CommitRate, "%i\n", num_committed); 10572292SN/A numCommittedDist.sample(num_committed); 10582307SN/A 10592307SN/A if (num_committed == commitWidth) { 10602349SN/A commitEligibleSamples++; 10612307SN/A } 10621060SN/A} 10631060SN/A 10641061SN/Atemplate <class Impl> 10651060SN/Abool 10662292SN/ADefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num) 10671060SN/A{ 10681060SN/A assert(head_inst); 10691060SN/A 10706221Snate@binkert.org ThreadID tid = head_inst->threadNumber; 10712292SN/A 10722316SN/A // If the instruction is not executed yet, then it will need extra 10732316SN/A // handling. Signal backwards that it should be executed. 10741061SN/A if (!head_inst->isExecuted()) { 10751061SN/A // Keep this number correct. We have not yet actually executed 10761061SN/A // and committed this instruction. 10772292SN/A thread[tid]->funcExeInst--; 10781062SN/A 10792292SN/A if (head_inst->isNonSpeculative() || 10802348SN/A head_inst->isStoreConditional() || 10812292SN/A head_inst->isMemBarrier() || 10822292SN/A head_inst->isWriteBarrier()) { 10832316SN/A 10842316SN/A DPRINTF(Commit, "Encountered a barrier or non-speculative " 10857720Sgblack@eecs.umich.edu "instruction [sn:%lli] at the head of the ROB, PC %s.\n", 10867720Sgblack@eecs.umich.edu head_inst->seqNum, head_inst->pcState()); 10872316SN/A 10885557Sktlim@umich.edu if (inst_num > 0 || iewStage->hasStoresToWB(tid)) { 10892292SN/A DPRINTF(Commit, "Waiting for all stores to writeback.\n"); 10902292SN/A return false; 10912292SN/A } 10922292SN/A 10932292SN/A toIEW->commitInfo[tid].nonSpecSeqNum = head_inst->seqNum; 10941061SN/A 10951061SN/A // Change the instruction so it won't try to commit again until 10961061SN/A // it is executed. 10971061SN/A head_inst->clearCanCommit(); 10981061SN/A 10991062SN/A ++commitNonSpecStalls; 11001062SN/A 11011061SN/A return false; 11022292SN/A } else if (head_inst->isLoad()) { 11035557Sktlim@umich.edu if (inst_num > 0 || iewStage->hasStoresToWB(tid)) { 11044035Sktlim@umich.edu DPRINTF(Commit, "Waiting for all stores to writeback.\n"); 11054035Sktlim@umich.edu return false; 11064035Sktlim@umich.edu } 11074035Sktlim@umich.edu 11084035Sktlim@umich.edu assert(head_inst->uncacheable()); 11097720Sgblack@eecs.umich.edu DPRINTF(Commit, "[sn:%lli]: Uncached load, PC %s.\n", 11107720Sgblack@eecs.umich.edu head_inst->seqNum, head_inst->pcState()); 11112292SN/A 11122292SN/A // Send back the non-speculative instruction's sequence 11132316SN/A // number. Tell the lsq to re-execute the load. 11142292SN/A toIEW->commitInfo[tid].nonSpecSeqNum = head_inst->seqNum; 11152292SN/A toIEW->commitInfo[tid].uncached = true; 11162292SN/A toIEW->commitInfo[tid].uncachedLoad = head_inst; 11172292SN/A 11182292SN/A head_inst->clearCanCommit(); 11192292SN/A 11202292SN/A return false; 11211061SN/A } else { 11222292SN/A panic("Trying to commit un-executed instruction " 11231061SN/A "of unknown type!\n"); 11241061SN/A } 11251060SN/A } 11261060SN/A 11272316SN/A if (head_inst->isThreadSync()) { 11282292SN/A // Not handled for now. 11292316SN/A panic("Thread sync instructions are not handled yet.\n"); 11302132SN/A } 11312132SN/A 11324035Sktlim@umich.edu // Check if the instruction caused a fault. If so, trap. 11334035Sktlim@umich.edu Fault inst_fault = head_inst->getFault(); 11344035Sktlim@umich.edu 11352316SN/A // Stores mark themselves as completed. 11364035Sktlim@umich.edu if (!head_inst->isStore() && inst_fault == NoFault) { 11372310SN/A head_inst->setCompleted(); 11382310SN/A } 11392310SN/A 11402316SN/A // Use checker prior to updating anything due to traps or PC 11412316SN/A // based events. 11422316SN/A if (cpu->checker) { 11432732Sktlim@umich.edu cpu->checker->verify(head_inst); 11441060SN/A } 11451060SN/A 11462112SN/A if (inst_fault != NoFault) { 11477720Sgblack@eecs.umich.edu DPRINTF(Commit, "Inst [sn:%lli] PC %s has a fault\n", 11487720Sgblack@eecs.umich.edu head_inst->seqNum, head_inst->pcState()); 11492292SN/A 11505557Sktlim@umich.edu if (iewStage->hasStoresToWB(tid) || inst_num > 0) { 11512316SN/A DPRINTF(Commit, "Stores outstanding, fault must wait.\n"); 11522316SN/A return false; 11532316SN/A } 11542310SN/A 11554035Sktlim@umich.edu head_inst->setCompleted(); 11564035Sktlim@umich.edu 11578733Sgeoffrey.blake@arm.com if (cpu->checker) { 11588733Sgeoffrey.blake@arm.com // Need to check the instruction before its fault is processed 11592732Sktlim@umich.edu cpu->checker->verify(head_inst); 11602316SN/A } 11612292SN/A 11622316SN/A assert(!thread[tid]->inSyscall); 11632292SN/A 11642316SN/A // Mark that we're in state update mode so that the trap's 11652316SN/A // execution doesn't generate extra squashes. 11662316SN/A thread[tid]->inSyscall = true; 11672292SN/A 11682316SN/A // Execute the trap. Although it's slightly unrealistic in 11692316SN/A // terms of timing (as it doesn't wait for the full timing of 11702316SN/A // the trap event to complete before updating state), it's 11712316SN/A // needed to update the state as soon as possible. This 11722316SN/A // prevents external agents from changing any specific state 11732316SN/A // that the trap need. 11747684Sgblack@eecs.umich.edu cpu->trap(inst_fault, tid, head_inst->staticInst); 11752292SN/A 11762316SN/A // Exit state update mode to avoid accidental updating. 11772316SN/A thread[tid]->inSyscall = false; 11782292SN/A 11792316SN/A commitStatus[tid] = TrapPending; 11802292SN/A 11818067SAli.Saidi@ARM.com DPRINTF(Commit, "Committing instruction with fault [sn:%lli]\n", 11828067SAli.Saidi@ARM.com head_inst->seqNum); 11834035Sktlim@umich.edu if (head_inst->traceData) { 11846667Ssteve.reinhardt@amd.com if (DTRACE(ExecFaulting)) { 11856667Ssteve.reinhardt@amd.com head_inst->traceData->setFetchSeq(head_inst->seqNum); 11868834Satgutier@umich.edu head_inst->traceData->setCPSeq(thread[tid]->numOp); 11876667Ssteve.reinhardt@amd.com head_inst->traceData->dump(); 11886667Ssteve.reinhardt@amd.com } 11894288Sktlim@umich.edu delete head_inst->traceData; 11904035Sktlim@umich.edu head_inst->traceData = NULL; 11914035Sktlim@umich.edu } 11924035Sktlim@umich.edu 11932316SN/A // Generate trap squash event. 11942316SN/A generateTrapEvent(tid); 11952316SN/A return false; 11961060SN/A } 11971060SN/A 11982301SN/A updateComInstStats(head_inst); 11992132SN/A 12008793Sgblack@eecs.umich.edu if (FullSystem) { 12018793Sgblack@eecs.umich.edu if (thread[tid]->profile) { 12028793Sgblack@eecs.umich.edu thread[tid]->profilePC = head_inst->instAddr(); 12038793Sgblack@eecs.umich.edu ProfileNode *node = thread[tid]->profile->consume( 12048793Sgblack@eecs.umich.edu thread[tid]->getTC(), head_inst->staticInst); 12052362SN/A 12068793Sgblack@eecs.umich.edu if (node) 12078793Sgblack@eecs.umich.edu thread[tid]->profileNode = node; 12088793Sgblack@eecs.umich.edu } 12098793Sgblack@eecs.umich.edu if (CPA::available()) { 12108793Sgblack@eecs.umich.edu if (head_inst->isControl()) { 12118793Sgblack@eecs.umich.edu ThreadContext *tc = thread[tid]->getTC(); 12128793Sgblack@eecs.umich.edu CPA::cpa()->swAutoBegin(tc, head_inst->nextInstAddr()); 12138793Sgblack@eecs.umich.edu } 12145953Ssaidi@eecs.umich.edu } 12155953Ssaidi@eecs.umich.edu } 12168516SMrinmoy.Ghosh@arm.com DPRINTF(Commit, "Committing instruction with [sn:%lli] PC %s\n", 12178516SMrinmoy.Ghosh@arm.com head_inst->seqNum, head_inst->pcState()); 12182132SN/A if (head_inst->traceData) { 12192292SN/A head_inst->traceData->setFetchSeq(head_inst->seqNum); 12208834Satgutier@umich.edu head_inst->traceData->setCPSeq(thread[tid]->numOp); 12214046Sbinkertn@umich.edu head_inst->traceData->dump(); 12224046Sbinkertn@umich.edu delete head_inst->traceData; 12232292SN/A head_inst->traceData = NULL; 12241060SN/A } 12258843Smrinmoy.ghosh@arm.com if (head_inst->isReturn()) { 12268843Smrinmoy.ghosh@arm.com DPRINTF(Commit,"Return Instruction Committed [sn:%lli] PC %s \n", 12278843Smrinmoy.ghosh@arm.com head_inst->seqNum, head_inst->pcState()); 12288843Smrinmoy.ghosh@arm.com } 12291060SN/A 12302292SN/A // Update the commit rename map 12312292SN/A for (int i = 0; i < head_inst->numDestRegs(); i++) { 12323771Sgblack@eecs.umich.edu renameMap[tid]->setEntry(head_inst->flattenedDestRegIdx(i), 12332292SN/A head_inst->renamedDestRegIdx(i)); 12341060SN/A } 12351062SN/A 12362292SN/A // Finally clear the head ROB entry. 12372292SN/A rob->retireHead(tid); 12381060SN/A 12398471SGiacomo.Gabrielli@arm.com#if TRACING_ON 12408471SGiacomo.Gabrielli@arm.com // Print info needed by the pipeline activity viewer. 12418471SGiacomo.Gabrielli@arm.com DPRINTFR(O3PipeView, "O3PipeView:fetch:%llu:0x%08llx:%d:%llu:%s\n", 12428471SGiacomo.Gabrielli@arm.com head_inst->fetchTick, 12438471SGiacomo.Gabrielli@arm.com head_inst->instAddr(), 12448471SGiacomo.Gabrielli@arm.com head_inst->microPC(), 12458471SGiacomo.Gabrielli@arm.com head_inst->seqNum, 12468471SGiacomo.Gabrielli@arm.com head_inst->staticInst->disassemble(head_inst->instAddr())); 12479046SAli.Saidi@ARM.com DPRINTFR(O3PipeView, "O3PipeView:decode:%llu\n", head_inst->fetchTick + head_inst->decodeTick); 12489046SAli.Saidi@ARM.com DPRINTFR(O3PipeView, "O3PipeView:rename:%llu\n", head_inst->fetchTick + head_inst->renameTick); 12499046SAli.Saidi@ARM.com DPRINTFR(O3PipeView, "O3PipeView:dispatch:%llu\n", head_inst->fetchTick + head_inst->dispatchTick); 12509046SAli.Saidi@ARM.com DPRINTFR(O3PipeView, "O3PipeView:issue:%llu\n", head_inst->fetchTick + head_inst->issueTick); 12519046SAli.Saidi@ARM.com DPRINTFR(O3PipeView, "O3PipeView:complete:%llu\n", head_inst->fetchTick + head_inst->completeTick); 12528471SGiacomo.Gabrielli@arm.com DPRINTFR(O3PipeView, "O3PipeView:retire:%llu\n", curTick()); 12538471SGiacomo.Gabrielli@arm.com#endif 12548471SGiacomo.Gabrielli@arm.com 12554035Sktlim@umich.edu // If this was a store, record it for this cycle. 12564035Sktlim@umich.edu if (head_inst->isStore()) 12574035Sktlim@umich.edu committedStores[tid] = true; 12584035Sktlim@umich.edu 12591060SN/A // Return true to indicate that we have committed an instruction. 12601060SN/A return true; 12611060SN/A} 12621060SN/A 12631061SN/Atemplate <class Impl> 12641060SN/Avoid 12652292SN/ADefaultCommit<Impl>::getInsts() 12661060SN/A{ 12672935Sksewell@umich.edu DPRINTF(Commit, "Getting instructions from Rename stage.\n"); 12682935Sksewell@umich.edu 12693093Sksewell@umich.edu // Read any renamed instructions and place them into the ROB. 12703093Sksewell@umich.edu int insts_to_process = std::min((int)renameWidth, fromRename->size); 12712965Sksewell@umich.edu 12722965Sksewell@umich.edu for (int inst_num = 0; inst_num < insts_to_process; ++inst_num) { 12732965Sksewell@umich.edu DynInstPtr inst; 12742965Sksewell@umich.edu 12753093Sksewell@umich.edu inst = fromRename->insts[inst_num]; 12766221Snate@binkert.org ThreadID tid = inst->threadNumber; 12772292SN/A 12782292SN/A if (!inst->isSquashed() && 12794035Sktlim@umich.edu commitStatus[tid] != ROBSquashing && 12804035Sktlim@umich.edu commitStatus[tid] != TrapPending) { 12812292SN/A changedROBNumEntries[tid] = true; 12822292SN/A 12837720Sgblack@eecs.umich.edu DPRINTF(Commit, "Inserting PC %s [sn:%i] [tid:%i] into ROB.\n", 12847720Sgblack@eecs.umich.edu inst->pcState(), inst->seqNum, tid); 12852292SN/A 12862292SN/A rob->insertInst(inst); 12872292SN/A 12882292SN/A assert(rob->getThreadEntries(tid) <= rob->getMaxEntries(tid)); 12892292SN/A 12902292SN/A youngestSeqNum[tid] = inst->seqNum; 12911061SN/A } else { 12927720Sgblack@eecs.umich.edu DPRINTF(Commit, "Instruction PC %s [sn:%i] [tid:%i] was " 12931061SN/A "squashed, skipping.\n", 12947720Sgblack@eecs.umich.edu inst->pcState(), inst->seqNum, tid); 12951061SN/A } 12961060SN/A } 12972965Sksewell@umich.edu} 12982965Sksewell@umich.edu 12992965Sksewell@umich.edutemplate <class Impl> 13002965Sksewell@umich.eduvoid 13012965Sksewell@umich.eduDefaultCommit<Impl>::skidInsert() 13022965Sksewell@umich.edu{ 13032965Sksewell@umich.edu DPRINTF(Commit, "Attempting to any instructions from rename into " 13042965Sksewell@umich.edu "skidBuffer.\n"); 13052965Sksewell@umich.edu 13062965Sksewell@umich.edu for (int inst_num = 0; inst_num < fromRename->size; ++inst_num) { 13072965Sksewell@umich.edu DynInstPtr inst = fromRename->insts[inst_num]; 13082965Sksewell@umich.edu 13092965Sksewell@umich.edu if (!inst->isSquashed()) { 13107720Sgblack@eecs.umich.edu DPRINTF(Commit, "Inserting PC %s [sn:%i] [tid:%i] into ", 13117720Sgblack@eecs.umich.edu "skidBuffer.\n", inst->pcState(), inst->seqNum, 13123221Sktlim@umich.edu inst->threadNumber); 13132965Sksewell@umich.edu skidBuffer.push(inst); 13142965Sksewell@umich.edu } else { 13157720Sgblack@eecs.umich.edu DPRINTF(Commit, "Instruction PC %s [sn:%i] [tid:%i] was " 13162965Sksewell@umich.edu "squashed, skipping.\n", 13177720Sgblack@eecs.umich.edu inst->pcState(), inst->seqNum, inst->threadNumber); 13182965Sksewell@umich.edu } 13192965Sksewell@umich.edu } 13201060SN/A} 13211060SN/A 13221061SN/Atemplate <class Impl> 13231060SN/Avoid 13242292SN/ADefaultCommit<Impl>::markCompletedInsts() 13251060SN/A{ 13261060SN/A // Grab completed insts out of the IEW instruction queue, and mark 13271060SN/A // instructions completed within the ROB. 13281060SN/A for (int inst_num = 0; 13291681SN/A inst_num < fromIEW->size && fromIEW->insts[inst_num]; 13301060SN/A ++inst_num) 13311060SN/A { 13322292SN/A if (!fromIEW->insts[inst_num]->isSquashed()) { 13337720Sgblack@eecs.umich.edu DPRINTF(Commit, "[tid:%i]: Marking PC %s, [sn:%lli] ready " 13342316SN/A "within ROB.\n", 13352292SN/A fromIEW->insts[inst_num]->threadNumber, 13367720Sgblack@eecs.umich.edu fromIEW->insts[inst_num]->pcState(), 13372292SN/A fromIEW->insts[inst_num]->seqNum); 13381060SN/A 13392292SN/A // Mark the instruction as ready to commit. 13402292SN/A fromIEW->insts[inst_num]->setCanCommit(); 13412292SN/A } 13421060SN/A } 13431060SN/A} 13441060SN/A 13451061SN/Atemplate <class Impl> 13462292SN/Abool 13472292SN/ADefaultCommit<Impl>::robDoneSquashing() 13481060SN/A{ 13496221Snate@binkert.org list<ThreadID>::iterator threads = activeThreads->begin(); 13506221Snate@binkert.org list<ThreadID>::iterator end = activeThreads->end(); 13512292SN/A 13523867Sbinkertn@umich.edu while (threads != end) { 13536221Snate@binkert.org ThreadID tid = *threads++; 13542292SN/A 13552292SN/A if (!rob->isDoneSquashing(tid)) 13562292SN/A return false; 13572292SN/A } 13582292SN/A 13592292SN/A return true; 13601060SN/A} 13612292SN/A 13622301SN/Atemplate <class Impl> 13632301SN/Avoid 13642301SN/ADefaultCommit<Impl>::updateComInstStats(DynInstPtr &inst) 13652301SN/A{ 13666221Snate@binkert.org ThreadID tid = inst->threadNumber; 13672301SN/A 13688834Satgutier@umich.edu if (!inst->isMicroop() || inst->isLastMicroop()) 13698834Satgutier@umich.edu instsCommitted[tid]++; 13708834Satgutier@umich.edu opsCommitted[tid]++; 13712301SN/A 13722301SN/A // 13732301SN/A // Control Instructions 13742301SN/A // 13752301SN/A if (inst->isControl()) 13766221Snate@binkert.org statComBranches[tid]++; 13772301SN/A 13782301SN/A // 13792301SN/A // Memory references 13802301SN/A // 13812301SN/A if (inst->isMemRef()) { 13826221Snate@binkert.org statComRefs[tid]++; 13832301SN/A 13842301SN/A if (inst->isLoad()) { 13856221Snate@binkert.org statComLoads[tid]++; 13862301SN/A } 13872301SN/A } 13882301SN/A 13892301SN/A if (inst->isMemBarrier()) { 13906221Snate@binkert.org statComMembars[tid]++; 13912301SN/A } 13927897Shestness@cs.utexas.edu 13937897Shestness@cs.utexas.edu // Integer Instruction 13947897Shestness@cs.utexas.edu if (inst->isInteger()) 13957897Shestness@cs.utexas.edu statComInteger[tid]++; 13967897Shestness@cs.utexas.edu 13977897Shestness@cs.utexas.edu // Floating Point Instruction 13987897Shestness@cs.utexas.edu if (inst->isFloating()) 13997897Shestness@cs.utexas.edu statComFloating[tid]++; 14007897Shestness@cs.utexas.edu 14017897Shestness@cs.utexas.edu // Function Calls 14027897Shestness@cs.utexas.edu if (inst->isCall()) 14037897Shestness@cs.utexas.edu statComFunctionCalls[tid]++; 14047897Shestness@cs.utexas.edu 14052301SN/A} 14062301SN/A 14072292SN/A//////////////////////////////////////// 14082292SN/A// // 14092316SN/A// SMT COMMIT POLICY MAINTAINED HERE // 14102292SN/A// // 14112292SN/A//////////////////////////////////////// 14122292SN/Atemplate <class Impl> 14136221Snate@binkert.orgThreadID 14142292SN/ADefaultCommit<Impl>::getCommittingThread() 14152292SN/A{ 14162292SN/A if (numThreads > 1) { 14172292SN/A switch (commitPolicy) { 14182292SN/A 14192292SN/A case Aggressive: 14202292SN/A //If Policy is Aggressive, commit will call 14212292SN/A //this function multiple times per 14222292SN/A //cycle 14232292SN/A return oldestReady(); 14242292SN/A 14252292SN/A case RoundRobin: 14262292SN/A return roundRobin(); 14272292SN/A 14282292SN/A case OldestReady: 14292292SN/A return oldestReady(); 14302292SN/A 14312292SN/A default: 14326221Snate@binkert.org return InvalidThreadID; 14332292SN/A } 14342292SN/A } else { 14353867Sbinkertn@umich.edu assert(!activeThreads->empty()); 14366221Snate@binkert.org ThreadID tid = activeThreads->front(); 14372292SN/A 14382292SN/A if (commitStatus[tid] == Running || 14392292SN/A commitStatus[tid] == Idle || 14402292SN/A commitStatus[tid] == FetchTrapPending) { 14412292SN/A return tid; 14422292SN/A } else { 14436221Snate@binkert.org return InvalidThreadID; 14442292SN/A } 14452292SN/A } 14462292SN/A} 14472292SN/A 14482292SN/Atemplate<class Impl> 14496221Snate@binkert.orgThreadID 14502292SN/ADefaultCommit<Impl>::roundRobin() 14512292SN/A{ 14526221Snate@binkert.org list<ThreadID>::iterator pri_iter = priority_list.begin(); 14536221Snate@binkert.org list<ThreadID>::iterator end = priority_list.end(); 14542292SN/A 14552292SN/A while (pri_iter != end) { 14566221Snate@binkert.org ThreadID tid = *pri_iter; 14572292SN/A 14582292SN/A if (commitStatus[tid] == Running || 14592831Sksewell@umich.edu commitStatus[tid] == Idle || 14602831Sksewell@umich.edu commitStatus[tid] == FetchTrapPending) { 14612292SN/A 14622292SN/A if (rob->isHeadReady(tid)) { 14632292SN/A priority_list.erase(pri_iter); 14642292SN/A priority_list.push_back(tid); 14652292SN/A 14662292SN/A return tid; 14672292SN/A } 14682292SN/A } 14692292SN/A 14702292SN/A pri_iter++; 14712292SN/A } 14722292SN/A 14736221Snate@binkert.org return InvalidThreadID; 14742292SN/A} 14752292SN/A 14762292SN/Atemplate<class Impl> 14776221Snate@binkert.orgThreadID 14782292SN/ADefaultCommit<Impl>::oldestReady() 14792292SN/A{ 14802292SN/A unsigned oldest = 0; 14812292SN/A bool first = true; 14822292SN/A 14836221Snate@binkert.org list<ThreadID>::iterator threads = activeThreads->begin(); 14846221Snate@binkert.org list<ThreadID>::iterator end = activeThreads->end(); 14852292SN/A 14863867Sbinkertn@umich.edu while (threads != end) { 14876221Snate@binkert.org ThreadID tid = *threads++; 14882292SN/A 14892292SN/A if (!rob->isEmpty(tid) && 14902292SN/A (commitStatus[tid] == Running || 14912292SN/A commitStatus[tid] == Idle || 14922292SN/A commitStatus[tid] == FetchTrapPending)) { 14932292SN/A 14942292SN/A if (rob->isHeadReady(tid)) { 14952292SN/A 14962292SN/A DynInstPtr head_inst = rob->readHeadInst(tid); 14972292SN/A 14982292SN/A if (first) { 14992292SN/A oldest = tid; 15002292SN/A first = false; 15012292SN/A } else if (head_inst->seqNum < oldest) { 15022292SN/A oldest = tid; 15032292SN/A } 15042292SN/A } 15052292SN/A } 15062292SN/A } 15072292SN/A 15082292SN/A if (!first) { 15092292SN/A return oldest; 15102292SN/A } else { 15116221Snate@binkert.org return InvalidThreadID; 15122292SN/A } 15132292SN/A} 1514