iew_impl.hh revision 2307
16313Sgblack@eecs.umich.edu/* 211574SCurtis.Dunham@arm.com * Copyright (c) 2004-2005 The Regents of The University of Michigan 37093Sgblack@eecs.umich.edu * All rights reserved. 47093Sgblack@eecs.umich.edu * 57093Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 67093Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 77093Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 87093Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 97093Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 107093Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 117093Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 127093Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 137093Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 146313Sgblack@eecs.umich.edu * this software without specific prior written permission. 156313Sgblack@eecs.umich.edu * 166313Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176313Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186313Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196313Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206313Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216313Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226313Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236313Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246313Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256313Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266313Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276313Sgblack@eecs.umich.edu */ 286313Sgblack@eecs.umich.edu 296313Sgblack@eecs.umich.edu// @todo: Fix the instantaneous communication among all the stages within 306313Sgblack@eecs.umich.edu// iew. There's a clear delay between issue and execute, yet backwards 316313Sgblack@eecs.umich.edu// communication happens simultaneously. 326313Sgblack@eecs.umich.edu 336313Sgblack@eecs.umich.edu#include <queue> 346313Sgblack@eecs.umich.edu 356313Sgblack@eecs.umich.edu#include "base/timebuf.hh" 366313Sgblack@eecs.umich.edu#include "cpu/o3/fu_pool.hh" 376313Sgblack@eecs.umich.edu#include "cpu/o3/iew.hh" 386313Sgblack@eecs.umich.edu 396313Sgblack@eecs.umich.eduusing namespace std; 406313Sgblack@eecs.umich.edu 416313Sgblack@eecs.umich.edutemplate<class Impl> 426313Sgblack@eecs.umich.eduDefaultIEW<Impl>::LdWritebackEvent::LdWritebackEvent(DynInstPtr &_inst, 436313Sgblack@eecs.umich.edu DefaultIEW<Impl> *_iew) 447404SAli.Saidi@ARM.com : Event(&mainEventQueue), inst(_inst), iewStage(_iew) 456313Sgblack@eecs.umich.edu{ 4610461SAndreas.Sandberg@ARM.com this->setFlags(Event::AutoDelete); 476333Sgblack@eecs.umich.edu} 4810037SARM gem5 Developers 497404SAli.Saidi@ARM.comtemplate<class Impl> 506313Sgblack@eecs.umich.eduvoid 5112109SRekai.GonzalezAlberquilla@arm.comDefaultIEW<Impl>::LdWritebackEvent::process() 528232Snate@binkert.org{ 5312109SRekai.GonzalezAlberquilla@arm.com DPRINTF(IEW, "Load writeback event [sn:%lli]\n", inst->seqNum); 549384SAndreas.Sandberg@arm.com DPRINTF(Activity, "Activity: Ld Writeback event [sn:%lli]\n", inst->seqNum); 5511165SRekai.GonzalezAlberquilla@arm.com 566313Sgblack@eecs.umich.edu //iewStage->ldstQueue.removeMSHR(inst->threadNumber,inst->seqNum); 579384SAndreas.Sandberg@arm.com 5810461SAndreas.Sandberg@ARM.com if (inst->isSquashed() || iewStage->isSwitchedOut()) { 596333Sgblack@eecs.umich.edu inst = NULL; 606313Sgblack@eecs.umich.edu return; 616313Sgblack@eecs.umich.edu } 626313Sgblack@eecs.umich.edu 636313Sgblack@eecs.umich.edu iewStage->wakeCPU(); 646313Sgblack@eecs.umich.edu 659384SAndreas.Sandberg@arm.com if (!inst->isExecuted()) { 666313Sgblack@eecs.umich.edu inst->setExecuted(); 676313Sgblack@eecs.umich.edu 6810037SARM gem5 Developers // Execute again to copy data to proper place. 6910037SARM gem5 Developers if (inst->isStore()) { 7010037SARM gem5 Developers inst->completeAcc(); 7111165SRekai.GonzalezAlberquilla@arm.com } 7211165SRekai.GonzalezAlberquilla@arm.com } 7312109SRekai.GonzalezAlberquilla@arm.com 7411165SRekai.GonzalezAlberquilla@arm.com // Need to insert instruction into queue to commit 7510461SAndreas.Sandberg@ARM.com iewStage->instToCommit(inst); 7610461SAndreas.Sandberg@ARM.com 7710461SAndreas.Sandberg@ARM.com //wroteToTimeBuffer = true; 7810461SAndreas.Sandberg@ARM.com iewStage->activityThisCycle(); 7910461SAndreas.Sandberg@ARM.com 8010461SAndreas.Sandberg@ARM.com inst = NULL; 8110844Sandreas.sandberg@arm.com} 8210844Sandreas.sandberg@arm.com 8310844Sandreas.sandberg@arm.comtemplate<class Impl> 8410037SARM gem5 Developersconst char * 8511771SCurtis.Dunham@arm.comDefaultIEW<Impl>::LdWritebackEvent::description() 8610037SARM gem5 Developers{ 8710037SARM gem5 Developers return "Load writeback event"; 8810037SARM gem5 Developers} 8910037SARM gem5 Developers 9010037SARM gem5 Developerstemplate<class Impl> 9110037SARM gem5 DevelopersDefaultIEW<Impl>::DefaultIEW(Params *params) 9210037SARM gem5 Developers : // Just make this time buffer really big for now 9310037SARM gem5 Developers // @todo: Make this into a parameter. 9410037SARM gem5 Developers issueToExecQueue(5, 5), 9510037SARM gem5 Developers instQueue(params), 9610037SARM gem5 Developers ldstQueue(params), 9710037SARM gem5 Developers fuPool(params->fuPool), 9810037SARM gem5 Developers commitToIEWDelay(params->commitToIEWDelay), 9910037SARM gem5 Developers renameToIEWDelay(params->renameToIEWDelay), 10010037SARM gem5 Developers issueToExecuteDelay(params->issueToExecuteDelay), 10110037SARM gem5 Developers issueReadWidth(params->issueWidth), 10210037SARM gem5 Developers issueWidth(params->issueWidth), 10310037SARM gem5 Developers executeWidth(params->executeWidth), 10411768SCurtis.Dunham@arm.com numThreads(params->numberOfThreads), 10510037SARM gem5 Developers switchedOut(false) 10610037SARM gem5 Developers{ 10710037SARM gem5 Developers DPRINTF(IEW, "executeIntWidth: %i.\n", params->executeIntWidth); 10810037SARM gem5 Developers _status = Active; 1096333Sgblack@eecs.umich.edu exeStatus = Running; 1106718Sgblack@eecs.umich.edu wbStatus = Idle; 1116718Sgblack@eecs.umich.edu 1126718Sgblack@eecs.umich.edu // Setup wire to read instructions coming from issue. 1136718Sgblack@eecs.umich.edu fromIssue = issueToExecQueue.getWire(-issueToExecuteDelay); 1146718Sgblack@eecs.umich.edu 11510037SARM gem5 Developers // Instruction queue needs the queue between issue and execute. 11610037SARM gem5 Developers instQueue.setIssueToExecuteQueue(&issueToExecQueue); 11710037SARM gem5 Developers 11810037SARM gem5 Developers instQueue.setIEW(this); 11910037SARM gem5 Developers ldstQueue.setIEW(this); 12010037SARM gem5 Developers 12110037SARM gem5 Developers for (int i=0; i < numThreads; i++) { 12210037SARM gem5 Developers dispatchStatus[i] = Running; 12310037SARM gem5 Developers stalls[i].commit = false; 12410037SARM gem5 Developers fetchRedirect[i] = false; 12510037SARM gem5 Developers } 12610037SARM gem5 Developers 12710037SARM gem5 Developers updateLSQNextCycle = false; 12810037SARM gem5 Developers 12910037SARM gem5 Developers // @todo: Make into a parameter 13010037SARM gem5 Developers skidBufferMax = (3 * (renameToIEWDelay * params->renameWidth)) + issueWidth; 13110037SARM gem5 Developers} 13210037SARM gem5 Developers 13310037SARM gem5 Developerstemplate <class Impl> 13410037SARM gem5 Developersstd::string 13510037SARM gem5 DevelopersDefaultIEW<Impl>::name() const 13610037SARM gem5 Developers{ 13710037SARM gem5 Developers return cpu->name() + ".iew"; 13810037SARM gem5 Developers} 13910037SARM gem5 Developers 14010037SARM gem5 Developerstemplate <class Impl> 14110037SARM gem5 Developersvoid 14210037SARM gem5 DevelopersDefaultIEW<Impl>::regStats() 14310037SARM gem5 Developers{ 14410037SARM gem5 Developers using namespace Stats; 14510037SARM gem5 Developers 14610037SARM gem5 Developers instQueue.regStats(); 1476718Sgblack@eecs.umich.edu 1486718Sgblack@eecs.umich.edu //ldstQueue.regStats(); 1496313Sgblack@eecs.umich.edu 15010844Sandreas.sandberg@arm.com iewIdleCycles 15110037SARM gem5 Developers .name(name() + ".iewIdleCycles") 15210037SARM gem5 Developers .desc("Number of cycles IEW is idle"); 15310037SARM gem5 Developers 15410037SARM gem5 Developers iewSquashCycles 15510037SARM gem5 Developers .name(name() + ".iewSquashCycles") 15610037SARM gem5 Developers .desc("Number of cycles IEW is squashing"); 15710037SARM gem5 Developers 15810037SARM gem5 Developers iewBlockCycles 15910037SARM gem5 Developers .name(name() + ".iewBlockCycles") 16010037SARM gem5 Developers .desc("Number of cycles IEW is blocking"); 16110037SARM gem5 Developers 16210037SARM gem5 Developers iewUnblockCycles 16310037SARM gem5 Developers .name(name() + ".iewUnblockCycles") 16410709SAndreas.Sandberg@ARM.com .desc("Number of cycles IEW is unblocking"); 16510037SARM gem5 Developers 16610037SARM gem5 Developers// iewWBInsts; 16710037SARM gem5 Developers 16810037SARM gem5 Developers iewDispatchedInsts 16910037SARM gem5 Developers .name(name() + ".iewDispatchedInsts") 17010037SARM gem5 Developers .desc("Number of instructions dispatched to IQ"); 17110037SARM gem5 Developers 17210037SARM gem5 Developers iewDispSquashedInsts 17310037SARM gem5 Developers .name(name() + ".iewDispSquashedInsts") 1746313Sgblack@eecs.umich.edu .desc("Number of squashed instructions skipped by dispatch"); 1757427Sgblack@eecs.umich.edu 17610037SARM gem5 Developers iewDispLoadInsts 1776313Sgblack@eecs.umich.edu .name(name() + ".iewDispLoadInsts") 17810035Sandreas.hansson@arm.com .desc("Number of dispatched load instructions"); 1797405SAli.Saidi@ARM.com 1807405SAli.Saidi@ARM.com iewDispStoreInsts 1817405SAli.Saidi@ARM.com .name(name() + ".iewDispStoreInsts") 1826313Sgblack@eecs.umich.edu .desc("Number of dispatched store instructions"); 18312106SRekai.GonzalezAlberquilla@arm.com 18412106SRekai.GonzalezAlberquilla@arm.com iewDispNonSpecInsts 18512106SRekai.GonzalezAlberquilla@arm.com .name(name() + ".iewDispNonSpecInsts") 18612106SRekai.GonzalezAlberquilla@arm.com .desc("Number of dispatched non-speculative instructions"); 18712106SRekai.GonzalezAlberquilla@arm.com 18812106SRekai.GonzalezAlberquilla@arm.com iewIQFullEvents 18912106SRekai.GonzalezAlberquilla@arm.com .name(name() + ".iewIQFullEvents") 19012106SRekai.GonzalezAlberquilla@arm.com .desc("Number of times the IQ has become full, causing a stall"); 19112109SRekai.GonzalezAlberquilla@arm.com 19212109SRekai.GonzalezAlberquilla@arm.com iewLSQFullEvents 19312109SRekai.GonzalezAlberquilla@arm.com .name(name() + ".iewLSQFullEvents") 19412109SRekai.GonzalezAlberquilla@arm.com .desc("Number of times the LSQ has become full, causing a stall"); 19512106SRekai.GonzalezAlberquilla@arm.com 19612106SRekai.GonzalezAlberquilla@arm.com iewExecutedInsts 19712106SRekai.GonzalezAlberquilla@arm.com .name(name() + ".iewExecutedInsts") 19812106SRekai.GonzalezAlberquilla@arm.com .desc("Number of executed instructions"); 19912106SRekai.GonzalezAlberquilla@arm.com 20012106SRekai.GonzalezAlberquilla@arm.com iewExecLoadInsts 20112106SRekai.GonzalezAlberquilla@arm.com .init(cpu->number_of_threads) 20212106SRekai.GonzalezAlberquilla@arm.com .name(name() + ".iewExecLoadInsts") 2036313Sgblack@eecs.umich.edu .desc("Number of load instructions executed") 20410035Sandreas.hansson@arm.com .flags(total); 2056313Sgblack@eecs.umich.edu/* 2066718Sgblack@eecs.umich.edu iewExecStoreInsts 2076718Sgblack@eecs.umich.edu .name(name() + ".iewExecStoreInsts") 2086718Sgblack@eecs.umich.edu .desc("Number of store instructions executed"); 2096726Sgblack@eecs.umich.edu*/ 2106726Sgblack@eecs.umich.edu iewExecSquashedInsts 21110037SARM gem5 Developers .name(name() + ".iewExecSquashedInsts") 21210037SARM gem5 Developers .desc("Number of squashed instructions skipped in execute"); 21310037SARM gem5 Developers 21410037SARM gem5 Developers memOrderViolationEvents 21510037SARM gem5 Developers .name(name() + ".memOrderViolationEvents") 21610037SARM gem5 Developers .desc("Number of memory order violations"); 21710037SARM gem5 Developers 21810037SARM gem5 Developers predictedTakenIncorrect 21910037SARM gem5 Developers .name(name() + ".predictedTakenIncorrect") 22011574SCurtis.Dunham@arm.com .desc("Number of branches that were predicted taken incorrectly"); 22111574SCurtis.Dunham@arm.com 22210037SARM gem5 Developers predictedNotTakenIncorrect 22310037SARM gem5 Developers .name(name() + ".predictedNotTakenIncorrect") 22410037SARM gem5 Developers .desc("Number of branches that were predicted not taken incorrectly"); 22510037SARM gem5 Developers 22610037SARM gem5 Developers branchMispredicts 22710037SARM gem5 Developers .name(name() + ".branchMispredicts") 22810037SARM gem5 Developers .desc("Number of branch mispredicts detected at execute"); 22910037SARM gem5 Developers 2306718Sgblack@eecs.umich.edu branchMispredicts = predictedTakenIncorrect + predictedNotTakenIncorrect; 23110037SARM gem5 Developers 2326718Sgblack@eecs.umich.edu exe_swp 2336313Sgblack@eecs.umich.edu .init(cpu->number_of_threads) 2346313Sgblack@eecs.umich.edu .name(name() + ".EXEC:swp") 2356313Sgblack@eecs.umich.edu .desc("number of swp insts executed") 23610035Sandreas.hansson@arm.com .flags(total) 2376313Sgblack@eecs.umich.edu ; 23810338SCurtis.Dunham@arm.com 2396313Sgblack@eecs.umich.edu exe_nop 2406313Sgblack@eecs.umich.edu .init(cpu->number_of_threads) 2416313Sgblack@eecs.umich.edu .name(name() + ".EXEC:nop") 2429920Syasuko.eckert@amd.com .desc("number of nop insts executed") 24312109SRekai.GonzalezAlberquilla@arm.com .flags(total) 24412109SRekai.GonzalezAlberquilla@arm.com ; 24512109SRekai.GonzalezAlberquilla@arm.com 24612109SRekai.GonzalezAlberquilla@arm.com exe_refs 24712109SRekai.GonzalezAlberquilla@arm.com .init(cpu->number_of_threads) 24812109SRekai.GonzalezAlberquilla@arm.com .name(name() + ".EXEC:refs") 24912109SRekai.GonzalezAlberquilla@arm.com .desc("number of memory reference insts executed") 25012109SRekai.GonzalezAlberquilla@arm.com .flags(total) 25112109SRekai.GonzalezAlberquilla@arm.com ; 25212109SRekai.GonzalezAlberquilla@arm.com 25312109SRekai.GonzalezAlberquilla@arm.com exe_branches 25412109SRekai.GonzalezAlberquilla@arm.com .init(cpu->number_of_threads) 25512109SRekai.GonzalezAlberquilla@arm.com .name(name() + ".EXEC:branches") 25612109SRekai.GonzalezAlberquilla@arm.com .desc("Number of branches executed") 25710035Sandreas.hansson@arm.com .flags(total) 2589920Syasuko.eckert@amd.com ; 25910338SCurtis.Dunham@arm.com 2609920Syasuko.eckert@amd.com issue_rate 2619920Syasuko.eckert@amd.com .name(name() + ".EXEC:rate") 2629920Syasuko.eckert@amd.com .desc("Inst execution rate") 2637614Sminkyu.jeong@arm.com .flags(total) 26410035Sandreas.hansson@arm.com ; 2657614Sminkyu.jeong@arm.com issue_rate = iewExecutedInsts / cpu->numCycles; 26610338SCurtis.Dunham@arm.com 26710037SARM gem5 Developers iewExecStoreInsts 26810037SARM gem5 Developers .name(name() + ".EXEC:stores") 2697614Sminkyu.jeong@arm.com .desc("Number of stores executed") 2707614Sminkyu.jeong@arm.com .flags(total) 2717614Sminkyu.jeong@arm.com ; 27210037SARM gem5 Developers iewExecStoreInsts = exe_refs - iewExecLoadInsts; 27310037SARM gem5 Developers/* 27410037SARM gem5 Developers for (int i=0; i<Num_OpClasses; ++i) { 27510037SARM gem5 Developers stringstream subname; 27610037SARM gem5 Developers subname << opClassStrings[i] << "_delay"; 27710037SARM gem5 Developers issue_delay_dist.subname(i, subname.str()); 27810037SARM gem5 Developers } 27910037SARM gem5 Developers*/ 28010037SARM gem5 Developers // 28110037SARM gem5 Developers // Other stats 28210037SARM gem5 Developers // 28310037SARM gem5 Developers 28410037SARM gem5 Developers iewInstsToCommit 28510037SARM gem5 Developers .init(cpu->number_of_threads) 28610037SARM gem5 Developers .name(name() + ".WB:sent") 28710037SARM gem5 Developers .desc("cumulative count of insts sent to commit") 2887614Sminkyu.jeong@arm.com .flags(total) 2897614Sminkyu.jeong@arm.com ; 29010037SARM gem5 Developers 2917614Sminkyu.jeong@arm.com writeback_count 2927614Sminkyu.jeong@arm.com .init(cpu->number_of_threads) 29310037SARM gem5 Developers .name(name() + ".WB:count") 2947614Sminkyu.jeong@arm.com .desc("cumulative count of insts written-back") 2957614Sminkyu.jeong@arm.com .flags(total) 29610037SARM gem5 Developers ; 2977614Sminkyu.jeong@arm.com 2987614Sminkyu.jeong@arm.com producer_inst 29910037SARM gem5 Developers .init(cpu->number_of_threads) 3007614Sminkyu.jeong@arm.com .name(name() + ".WB:producers") 3017614Sminkyu.jeong@arm.com .desc("num instructions producing a value") 30210037SARM gem5 Developers .flags(total) 3037614Sminkyu.jeong@arm.com ; 3047614Sminkyu.jeong@arm.com 30510037SARM gem5 Developers consumer_inst 30610037SARM gem5 Developers .init(cpu->number_of_threads) 30710037SARM gem5 Developers .name(name() + ".WB:consumers") 30810037SARM gem5 Developers .desc("num instructions consuming a value") 3097614Sminkyu.jeong@arm.com .flags(total) 3107614Sminkyu.jeong@arm.com ; 31110037SARM gem5 Developers 3127614Sminkyu.jeong@arm.com wb_penalized 3137614Sminkyu.jeong@arm.com .init(cpu->number_of_threads) 3147614Sminkyu.jeong@arm.com .name(name() + ".WB:penalized") 3157614Sminkyu.jeong@arm.com .desc("number of instrctions required to write to 'other' IQ") 31610037SARM gem5 Developers .flags(total) 3177614Sminkyu.jeong@arm.com ; 3187614Sminkyu.jeong@arm.com 31910037SARM gem5 Developers wb_penalized_rate 32010037SARM gem5 Developers .name(name() + ".WB:penalized_rate") 32110037SARM gem5 Developers .desc ("fraction of instructions written-back that wrote to 'other' IQ") 32210037SARM gem5 Developers .flags(total) 32310037SARM gem5 Developers ; 32410037SARM gem5 Developers 32510037SARM gem5 Developers wb_penalized_rate = wb_penalized / writeback_count; 32610037SARM gem5 Developers 32710037SARM gem5 Developers wb_fanout 32810037SARM gem5 Developers .name(name() + ".WB:fanout") 32910037SARM gem5 Developers .desc("average fanout of values written-back") 33010037SARM gem5 Developers .flags(total) 33110037SARM gem5 Developers ; 33210037SARM gem5 Developers 33310037SARM gem5 Developers wb_fanout = producer_inst / consumer_inst; 33410037SARM gem5 Developers 33510037SARM gem5 Developers wb_rate 33610037SARM gem5 Developers .name(name() + ".WB:rate") 33710037SARM gem5 Developers .desc("insts written-back per cycle") 33810037SARM gem5 Developers .flags(total) 33910037SARM gem5 Developers ; 34010037SARM gem5 Developers wb_rate = writeback_count / cpu->numCycles; 34110037SARM gem5 Developers} 34210037SARM gem5 Developers 34310037SARM gem5 Developerstemplate<class Impl> 34410037SARM gem5 Developersvoid 34510037SARM gem5 DevelopersDefaultIEW<Impl>::initStage() 34610037SARM gem5 Developers{ 34710037SARM gem5 Developers for (int tid=0; tid < numThreads; tid++) { 34810037SARM gem5 Developers toRename->iewInfo[tid].usedIQ = true; 34910037SARM gem5 Developers toRename->iewInfo[tid].freeIQEntries = 35010037SARM gem5 Developers instQueue.numFreeEntries(tid); 35110037SARM gem5 Developers 35210037SARM gem5 Developers toRename->iewInfo[tid].usedLSQ = true; 35310037SARM gem5 Developers toRename->iewInfo[tid].freeLSQEntries = 35410037SARM gem5 Developers ldstQueue.numFreeEntries(tid); 35510037SARM gem5 Developers } 35610037SARM gem5 Developers} 35710037SARM gem5 Developers 35810037SARM gem5 Developerstemplate<class Impl> 35910037SARM gem5 Developersvoid 36010037SARM gem5 DevelopersDefaultIEW<Impl>::setCPU(FullCPU *cpu_ptr) 36110037SARM gem5 Developers{ 36210037SARM gem5 Developers DPRINTF(IEW, "Setting CPU pointer.\n"); 36310037SARM gem5 Developers cpu = cpu_ptr; 36410037SARM gem5 Developers 36510037SARM gem5 Developers instQueue.setCPU(cpu_ptr); 36610037SARM gem5 Developers ldstQueue.setCPU(cpu_ptr); 36710037SARM gem5 Developers 36810037SARM gem5 Developers cpu->activateStage(FullCPU::IEWIdx); 36911771SCurtis.Dunham@arm.com} 37010037SARM gem5 Developers 37110037SARM gem5 Developerstemplate<class Impl> 37210037SARM gem5 Developersvoid 37310037SARM gem5 DevelopersDefaultIEW<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) 3747614Sminkyu.jeong@arm.com{ 37510037SARM gem5 Developers DPRINTF(IEW, "Setting time buffer pointer.\n"); 3767614Sminkyu.jeong@arm.com timeBuffer = tb_ptr; 3777614Sminkyu.jeong@arm.com 37811771SCurtis.Dunham@arm.com // Setup wire to read information from time buffer, from commit. 37911771SCurtis.Dunham@arm.com fromCommit = timeBuffer->getWire(-commitToIEWDelay); 38011771SCurtis.Dunham@arm.com 38111771SCurtis.Dunham@arm.com // Setup wire to write information back to previous stages. 38211771SCurtis.Dunham@arm.com toRename = timeBuffer->getWire(0); 38311771SCurtis.Dunham@arm.com 38411771SCurtis.Dunham@arm.com toFetch = timeBuffer->getWire(0); 38511771SCurtis.Dunham@arm.com 38611771SCurtis.Dunham@arm.com // Instruction queue also needs main time buffer. 38711771SCurtis.Dunham@arm.com instQueue.setTimeBuffer(tb_ptr); 38811771SCurtis.Dunham@arm.com} 38911771SCurtis.Dunham@arm.com 39011771SCurtis.Dunham@arm.comtemplate<class Impl> 39111771SCurtis.Dunham@arm.comvoid 39211771SCurtis.Dunham@arm.comDefaultIEW<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr) 39311771SCurtis.Dunham@arm.com{ 39411771SCurtis.Dunham@arm.com DPRINTF(IEW, "Setting rename queue pointer.\n"); 39511771SCurtis.Dunham@arm.com renameQueue = rq_ptr; 39611771SCurtis.Dunham@arm.com 39711771SCurtis.Dunham@arm.com // Setup wire to read information from rename queue. 39811771SCurtis.Dunham@arm.com fromRename = renameQueue->getWire(-renameToIEWDelay); 39910905Sandreas.sandberg@arm.com} 4007733SAli.Saidi@ARM.com 4017733SAli.Saidi@ARM.comtemplate<class Impl> 4027733SAli.Saidi@ARM.comvoid 40310037SARM gem5 DevelopersDefaultIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr) 40411771SCurtis.Dunham@arm.com{ 40510037SARM gem5 Developers DPRINTF(IEW, "Setting IEW queue pointer.\n"); 40610037SARM gem5 Developers iewQueue = iq_ptr; 40710037SARM gem5 Developers 40810037SARM gem5 Developers // Setup wire to write instructions to commit. 40910037SARM gem5 Developers toCommit = iewQueue->getWire(0); 4107733SAli.Saidi@ARM.com} 41110905Sandreas.sandberg@arm.com 4127733SAli.Saidi@ARM.comtemplate<class Impl> 4137733SAli.Saidi@ARM.comvoid 4147733SAli.Saidi@ARM.comDefaultIEW<Impl>::setActiveThreads(list<unsigned> *at_ptr) 4157733SAli.Saidi@ARM.com{ 4167733SAli.Saidi@ARM.com DPRINTF(IEW, "Setting active threads list pointer.\n"); 41710037SARM gem5 Developers activeThreads = at_ptr; 41811771SCurtis.Dunham@arm.com 41910037SARM gem5 Developers ldstQueue.setActiveThreads(at_ptr); 42010037SARM gem5 Developers instQueue.setActiveThreads(at_ptr); 42110037SARM gem5 Developers} 42210037SARM gem5 Developers 42310037SARM gem5 Developerstemplate<class Impl> 4247733SAli.Saidi@ARM.comvoid 4256313Sgblack@eecs.umich.eduDefaultIEW<Impl>::setScoreboard(Scoreboard *sb_ptr) 4269461Snilay@cs.wisc.edu{ 4279461Snilay@cs.wisc.edu DPRINTF(IEW, "Setting scoreboard pointer.\n"); 42811165SRekai.GonzalezAlberquilla@arm.com scoreboard = sb_ptr; 42911165SRekai.GonzalezAlberquilla@arm.com} 43012109SRekai.GonzalezAlberquilla@arm.com 43112109SRekai.GonzalezAlberquilla@arm.com#if 0 43212109SRekai.GonzalezAlberquilla@arm.comtemplate<class Impl> 43312109SRekai.GonzalezAlberquilla@arm.comvoid 43412109SRekai.GonzalezAlberquilla@arm.comDefaultIEW<Impl>::setPageTable(PageTable *pt_ptr) 43512109SRekai.GonzalezAlberquilla@arm.com{ 4369553Sandreas.hansson@arm.com ldstQueue.setPageTable(pt_ptr); 4379553Sandreas.hansson@arm.com} 4389553Sandreas.hansson@arm.com#endif 4399384SAndreas.Sandberg@arm.com 4407400SAli.Saidi@ARM.comtemplate <class Impl> 4419384SAndreas.Sandberg@arm.comvoid 4429384SAndreas.Sandberg@arm.comDefaultIEW<Impl>::switchOut() 4439384SAndreas.Sandberg@arm.com{ 4446313Sgblack@eecs.umich.edu switchedOut = true; 4456313Sgblack@eecs.umich.edu instQueue.switchOut(); 4466313Sgblack@eecs.umich.edu ldstQueue.switchOut(); 44712109SRekai.GonzalezAlberquilla@arm.com fuPool->switchOut(); 44812109SRekai.GonzalezAlberquilla@arm.com 44912109SRekai.GonzalezAlberquilla@arm.com for (int i = 0; i < numThreads; i++) { 45012109SRekai.GonzalezAlberquilla@arm.com while (!insts[i].empty()) 45112109SRekai.GonzalezAlberquilla@arm.com insts[i].pop(); 45212109SRekai.GonzalezAlberquilla@arm.com while (!skidBuffer[i].empty()) 45312109SRekai.GonzalezAlberquilla@arm.com skidBuffer[i].pop(); 45412109SRekai.GonzalezAlberquilla@arm.com } 45512109SRekai.GonzalezAlberquilla@arm.com} 45612109SRekai.GonzalezAlberquilla@arm.com 45712109SRekai.GonzalezAlberquilla@arm.comtemplate <class Impl> 45812109SRekai.GonzalezAlberquilla@arm.comvoid 45912109SRekai.GonzalezAlberquilla@arm.comDefaultIEW<Impl>::takeOverFrom() 4606313Sgblack@eecs.umich.edu{ 461 _status = Active; 462 exeStatus = Running; 463 wbStatus = Idle; 464 switchedOut = false; 465 466 instQueue.takeOverFrom(); 467 ldstQueue.takeOverFrom(); 468 fuPool->takeOverFrom(); 469 470 initStage(); 471 cpu->activityThisCycle(); 472 473 for (int i=0; i < numThreads; i++) { 474 dispatchStatus[i] = Running; 475 stalls[i].commit = false; 476 fetchRedirect[i] = false; 477 } 478 479 updateLSQNextCycle = false; 480 481 // @todo: Fix hardcoded number 482 for (int i = 0; i < 6; ++i) { 483 issueToExecQueue.advance(); 484 } 485} 486 487template<class Impl> 488void 489DefaultIEW<Impl>::squash(unsigned tid) 490{ 491 DPRINTF(IEW, "[tid:%i]: Squashing all instructions.\n", 492 tid); 493 494 // Tell the IQ to start squashing. 495 instQueue.squash(tid); 496 497 // Tell the LDSTQ to start squashing. 498 ldstQueue.squash(fromCommit->commitInfo[tid].doneSeqNum,tid); 499 500 updatedQueues = true; 501 502 // Clear the skid buffer in case it has any data in it. 503 while (!skidBuffer[tid].empty()) { 504 505 if (skidBuffer[tid].front()->isLoad() || 506 skidBuffer[tid].front()->isStore() ) { 507 toRename->iewInfo[tid].dispatchedToLSQ++; 508 } 509 510 toRename->iewInfo[tid].dispatched++; 511 512 skidBuffer[tid].pop(); 513 } 514 515 while (!insts[tid].empty()) { 516 if (insts[tid].front()->isLoad() || 517 insts[tid].front()->isStore() ) { 518 toRename->iewInfo[tid].dispatchedToLSQ++; 519 } 520 521 toRename->iewInfo[tid].dispatched++; 522 523 insts[tid].pop(); 524 } 525} 526 527template<class Impl> 528void 529DefaultIEW<Impl>::squashDueToBranch(DynInstPtr &inst, unsigned tid) 530{ 531 DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, PC: %#x " 532 "[sn:%i].\n", tid, inst->readPC(), inst->seqNum); 533 534 // Tell rename to squash through the time buffer. 535 toCommit->squash[tid] = true; 536 toCommit->squashedSeqNum[tid] = inst->seqNum; 537 toCommit->mispredPC[tid] = inst->readPC(); 538 toCommit->nextPC[tid] = inst->readNextPC(); 539 toCommit->branchMispredict[tid] = true; 540 // Prediction was incorrect, so send back inverse. 541 toCommit->branchTaken[tid] = inst->readNextPC() != 542 (inst->readPC() + sizeof(TheISA::MachInst)); 543 544 toCommit->includeSquashInst[tid] = false; 545 //toCommit->iewSquashNum[tid] = inst->seqNum; 546 547 wroteToTimeBuffer = true; 548} 549 550template<class Impl> 551void 552DefaultIEW<Impl>::squashDueToMemOrder(DynInstPtr &inst, unsigned tid) 553{ 554 DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, " 555 "PC: %#x [sn:%i].\n", tid, inst->readPC(), inst->seqNum); 556 557 // Tell rename to squash through the time buffer. 558 toCommit->squash[tid] = true; 559 toCommit->squashedSeqNum[tid] = inst->seqNum; 560 toCommit->nextPC[tid] = inst->readNextPC(); 561 562 toCommit->includeSquashInst[tid] = false; 563 //toCommit->iewSquashNum[tid] = inst->seqNum; 564 565 wroteToTimeBuffer = true; 566} 567 568template<class Impl> 569void 570DefaultIEW<Impl>::squashDueToMemBlocked(DynInstPtr &inst, unsigned tid) 571{ 572 DPRINTF(IEW, "[tid:%i]: Memory blocked, squashing load and younger insts, " 573 "PC: %#x [sn:%i].\n", tid, inst->readPC(), inst->seqNum); 574 575 toCommit->squash[tid] = true; 576 toCommit->squashedSeqNum[tid] = inst->seqNum; 577 toCommit->nextPC[tid] = inst->readPC(); 578 579 toCommit->includeSquashInst[tid] = true; 580 581 ldstQueue.setLoadBlockedHandled(tid); 582 583 wroteToTimeBuffer = true; 584} 585 586template<class Impl> 587void 588DefaultIEW<Impl>::block(unsigned tid) 589{ 590 DPRINTF(IEW, "[tid:%u]: Blocking.\n", tid); 591 592 if (dispatchStatus[tid] != Blocked && 593 dispatchStatus[tid] != Unblocking) { 594 toRename->iewBlock[tid] = true; 595 wroteToTimeBuffer = true; 596 } 597 598 // Add the current inputs to the skid buffer so they can be 599 // reprocessed when this stage unblocks. 600 skidInsert(tid); 601 602 // Set the status to Blocked. 603 dispatchStatus[tid] = Blocked; 604} 605 606template<class Impl> 607void 608DefaultIEW<Impl>::unblock(unsigned tid) 609{ 610 DPRINTF(IEW, "[tid:%i]: Reading instructions out of the skid " 611 "buffer %u.\n",tid, tid); 612 613 // If the skid bufffer is empty, signal back to previous stages to unblock. 614 // Also switch status to running. 615 if (skidBuffer[tid].empty()) { 616 toRename->iewUnblock[tid] = true; 617 wroteToTimeBuffer = true; 618 DPRINTF(IEW, "[tid:%i]: Done unblocking.\n",tid); 619 dispatchStatus[tid] = Running; 620 } 621} 622 623template<class Impl> 624void 625DefaultIEW<Impl>::wakeDependents(DynInstPtr &inst) 626{ 627 instQueue.wakeDependents(inst); 628} 629 630template<class Impl> 631void 632DefaultIEW<Impl>::rescheduleMemInst(DynInstPtr &inst) 633{ 634 instQueue.rescheduleMemInst(inst); 635} 636 637template<class Impl> 638void 639DefaultIEW<Impl>::replayMemInst(DynInstPtr &inst) 640{ 641 instQueue.replayMemInst(inst); 642} 643 644template<class Impl> 645void 646DefaultIEW<Impl>::instToCommit(DynInstPtr &inst) 647{ 648 // First check the time slot that this instruction will write 649 // to. If there are free write ports at the time, then go ahead 650 // and write the instruction to that time. If there are not, 651 // keep looking back to see where's the first time there's a 652 // free slot. What happens if you run out of free spaces? 653 // For now naively assume that all instructions take one cycle. 654 // Otherwise would have to look into the time buffer based on the 655 // latency of the instruction. 656 while ((*iewQueue)[wbCycle].insts[wbNumInst]) { 657 ++wbNumInst; 658 if (wbNumInst == issueWidth) { 659 ++wbCycle; 660 wbNumInst = 0; 661 } 662 663 assert(wbCycle < 5); 664 } 665 666 // Add finished instruction to queue to commit. 667 (*iewQueue)[wbCycle].insts[wbNumInst] = inst; 668 (*iewQueue)[wbCycle].size++; 669} 670 671template <class Impl> 672unsigned 673DefaultIEW<Impl>::validInstsFromRename() 674{ 675 unsigned inst_count = 0; 676 677 for (int i=0; i<fromRename->size; i++) { 678 if (!fromRename->insts[i]->squashed) 679 inst_count++; 680 } 681 682 return inst_count; 683} 684 685template<class Impl> 686void 687DefaultIEW<Impl>::skidInsert(unsigned tid) 688{ 689 DynInstPtr inst = NULL; 690 691 while (!insts[tid].empty()) { 692 inst = insts[tid].front(); 693 694 insts[tid].pop(); 695 696 DPRINTF(Decode,"[tid:%i]: Inserting [sn:%lli] PC:%#x into " 697 "dispatch skidBuffer %i\n",tid, inst->seqNum, 698 inst->readPC(),tid); 699 700 skidBuffer[tid].push(inst); 701 } 702 703 assert(skidBuffer[tid].size() <= skidBufferMax && 704 "Skidbuffer Exceeded Max Size"); 705} 706 707template<class Impl> 708int 709DefaultIEW<Impl>::skidCount() 710{ 711 int max=0; 712 713 list<unsigned>::iterator threads = (*activeThreads).begin(); 714 715 while (threads != (*activeThreads).end()) { 716 unsigned thread_count = skidBuffer[*threads++].size(); 717 if (max < thread_count) 718 max = thread_count; 719 } 720 721 return max; 722} 723 724template<class Impl> 725bool 726DefaultIEW<Impl>::skidsEmpty() 727{ 728 list<unsigned>::iterator threads = (*activeThreads).begin(); 729 730 while (threads != (*activeThreads).end()) { 731 if (!skidBuffer[*threads++].empty()) 732 return false; 733 } 734 735 return true; 736} 737 738template <class Impl> 739void 740DefaultIEW<Impl>::updateStatus() 741{ 742 bool any_unblocking = false; 743 744 list<unsigned>::iterator threads = (*activeThreads).begin(); 745 746 threads = (*activeThreads).begin(); 747 748 while (threads != (*activeThreads).end()) { 749 unsigned tid = *threads++; 750 751 if (dispatchStatus[tid] == Unblocking) { 752 any_unblocking = true; 753 break; 754 } 755 } 756 757 // If there are no ready instructions waiting to be scheduled by the IQ, 758 // and there's no stores waiting to write back, and dispatch is not 759 // unblocking, then there is no internal activity for the IEW stage. 760 if (_status == Active && !instQueue.hasReadyInsts() && 761 !ldstQueue.willWB() && !any_unblocking) { 762 DPRINTF(IEW, "IEW switching to idle\n"); 763 764 deactivateStage(); 765 766 _status = Inactive; 767 } else if (_status == Inactive && (instQueue.hasReadyInsts() || 768 ldstQueue.willWB() || 769 any_unblocking)) { 770 // Otherwise there is internal activity. Set to active. 771 DPRINTF(IEW, "IEW switching to active\n"); 772 773 activateStage(); 774 775 _status = Active; 776 } 777} 778 779template <class Impl> 780void 781DefaultIEW<Impl>::resetEntries() 782{ 783 instQueue.resetEntries(); 784 ldstQueue.resetEntries(); 785} 786 787template <class Impl> 788void 789DefaultIEW<Impl>::readStallSignals(unsigned tid) 790{ 791 if (fromCommit->commitBlock[tid]) { 792 stalls[tid].commit = true; 793 } 794 795 if (fromCommit->commitUnblock[tid]) { 796 assert(stalls[tid].commit); 797 stalls[tid].commit = false; 798 } 799} 800 801template <class Impl> 802bool 803DefaultIEW<Impl>::checkStall(unsigned tid) 804{ 805 bool ret_val(false); 806 807 if (stalls[tid].commit) { 808 DPRINTF(IEW,"[tid:%i]: Stall from Commit stage detected.\n",tid); 809 ret_val = true; 810 } else if (instQueue.isFull(tid)) { 811 DPRINTF(IEW,"[tid:%i]: Stall: IQ is full.\n",tid); 812 ret_val = true; 813 } else if (ldstQueue.isFull(tid)) { 814 DPRINTF(IEW,"[tid:%i]: Stall: LSQ is full\n",tid); 815 816 if (ldstQueue.numLoads(tid) > 0 ) { 817 818 DPRINTF(IEW,"[tid:%i]: LSQ oldest load: [sn:%i] \n", 819 tid,ldstQueue.getLoadHeadSeqNum(tid)); 820 } 821 822 if (ldstQueue.numStores(tid) > 0) { 823 824 DPRINTF(IEW,"[tid:%i]: LSQ oldest store: [sn:%i] \n", 825 tid,ldstQueue.getStoreHeadSeqNum(tid)); 826 } 827 828 ret_val = true; 829 } else if (ldstQueue.isStalled(tid)) { 830 DPRINTF(IEW,"[tid:%i]: Stall: LSQ stall detected.\n",tid); 831 ret_val = true; 832 } 833 834 return ret_val; 835} 836 837template <class Impl> 838void 839DefaultIEW<Impl>::checkSignalsAndUpdate(unsigned tid) 840{ 841 // Check if there's a squash signal, squash if there is 842 // Check stall signals, block if there is. 843 // If status was Blocked 844 // if so then go to unblocking 845 // If status was Squashing 846 // check if squashing is not high. Switch to running this cycle. 847 848 readStallSignals(tid); 849 850 if (fromCommit->commitInfo[tid].squash) { 851 squash(tid); 852 853 if (dispatchStatus[tid] == Blocked || 854 dispatchStatus[tid] == Unblocking) { 855 toRename->iewUnblock[tid] = true; 856 wroteToTimeBuffer = true; 857 } 858 859 dispatchStatus[tid] = Squashing; 860 861 fetchRedirect[tid] = false; 862 return; 863 } 864 865 if (fromCommit->commitInfo[tid].robSquashing) { 866 DPRINTF(IEW, "[tid:%i]: ROB is still squashing.\n"); 867 868 dispatchStatus[tid] = Squashing; 869 870 return; 871 } 872 873 if (checkStall(tid)) { 874 block(tid); 875 dispatchStatus[tid] = Blocked; 876 return; 877 } 878 879 if (dispatchStatus[tid] == Blocked) { 880 // Status from previous cycle was blocked, but there are no more stall 881 // conditions. Switch over to unblocking. 882 DPRINTF(IEW, "[tid:%i]: Done blocking, switching to unblocking.\n", 883 tid); 884 885 dispatchStatus[tid] = Unblocking; 886 887 unblock(tid); 888 889 return; 890 } 891 892 if (dispatchStatus[tid] == Squashing) { 893 // Switch status to running if rename isn't being told to block or 894 // squash this cycle. 895 DPRINTF(IEW, "[tid:%i]: Done squashing, switching to running.\n", 896 tid); 897 898 dispatchStatus[tid] = Running; 899 900 return; 901 } 902} 903 904template <class Impl> 905void 906DefaultIEW<Impl>::sortInsts() 907{ 908 int insts_from_rename = fromRename->size; 909 910 for (int i = 0; i < numThreads; i++) 911 assert(insts[i].empty()); 912 913 for (int i = 0; i < insts_from_rename; ++i) { 914 insts[fromRename->insts[i]->threadNumber].push(fromRename->insts[i]); 915 } 916} 917 918template <class Impl> 919void 920DefaultIEW<Impl>::wakeCPU() 921{ 922 cpu->wakeCPU(); 923} 924 925template <class Impl> 926void 927DefaultIEW<Impl>::activityThisCycle() 928{ 929 DPRINTF(Activity, "Activity this cycle.\n"); 930 cpu->activityThisCycle(); 931} 932 933template <class Impl> 934inline void 935DefaultIEW<Impl>::activateStage() 936{ 937 DPRINTF(Activity, "Activating stage.\n"); 938 cpu->activateStage(FullCPU::IEWIdx); 939} 940 941template <class Impl> 942inline void 943DefaultIEW<Impl>::deactivateStage() 944{ 945 DPRINTF(Activity, "Deactivating stage.\n"); 946 cpu->deactivateStage(FullCPU::IEWIdx); 947} 948 949template<class Impl> 950void 951DefaultIEW<Impl>::dispatch(unsigned tid) 952{ 953 // If status is Running or idle, 954 // call dispatchInsts() 955 // If status is Unblocking, 956 // buffer any instructions coming from rename 957 // continue trying to empty skid buffer 958 // check if stall conditions have passed 959 960 if (dispatchStatus[tid] == Blocked) { 961 ++iewBlockCycles; 962 963 } else if (dispatchStatus[tid] == Squashing) { 964 ++iewSquashCycles; 965 } 966 967 // Dispatch should try to dispatch as many instructions as its bandwidth 968 // will allow, as long as it is not currently blocked. 969 if (dispatchStatus[tid] == Running || 970 dispatchStatus[tid] == Idle) { 971 DPRINTF(IEW, "[tid:%i] Not blocked, so attempting to run " 972 "dispatch.\n", tid); 973 974 dispatchInsts(tid); 975 } else if (dispatchStatus[tid] == Unblocking) { 976 // Make sure that the skid buffer has something in it if the 977 // status is unblocking. 978 assert(!skidsEmpty()); 979 980 // If the status was unblocking, then instructions from the skid 981 // buffer were used. Remove those instructions and handle 982 // the rest of unblocking. 983 dispatchInsts(tid); 984 985 ++iewUnblockCycles; 986 987 if (validInstsFromRename() && dispatchedAllInsts) { 988 // Add the current inputs to the skid buffer so they can be 989 // reprocessed when this stage unblocks. 990 skidInsert(tid); 991 } 992 993 unblock(tid); 994 } 995} 996 997template <class Impl> 998void 999DefaultIEW<Impl>::dispatchInsts(unsigned tid) 1000{ 1001 dispatchedAllInsts = true; 1002 1003 // Obtain instructions from skid buffer if unblocking, or queue from rename 1004 // otherwise. 1005 std::queue<DynInstPtr> &insts_to_dispatch = 1006 dispatchStatus[tid] == Unblocking ? 1007 skidBuffer[tid] : insts[tid]; 1008 1009 int insts_to_add = insts_to_dispatch.size(); 1010 1011 DynInstPtr inst; 1012 bool add_to_iq = false; 1013 int dis_num_inst = 0; 1014 1015 // Loop through the instructions, putting them in the instruction 1016 // queue. 1017 for ( ; dis_num_inst < insts_to_add && 1018 dis_num_inst < issueReadWidth; 1019 ++dis_num_inst) 1020 { 1021 inst = insts_to_dispatch.front(); 1022 1023 if (dispatchStatus[tid] == Unblocking) { 1024 DPRINTF(IEW, "[tid:%i]: Issue: Examining instruction from skid " 1025 "buffer\n", tid); 1026 } 1027 1028 // Make sure there's a valid instruction there. 1029 assert(inst); 1030 1031 DPRINTF(IEW, "[tid:%i]: Issue: Adding PC %#x [sn:%lli] [tid:%i] to " 1032 "IQ.\n", 1033 tid, inst->readPC(), inst->seqNum, inst->threadNumber); 1034 1035 // Be sure to mark these instructions as ready so that the 1036 // commit stage can go ahead and execute them, and mark 1037 // them as issued so the IQ doesn't reprocess them. 1038 // ------------- 1039 // @TODO: What happens if the ldstqueue is full? 1040 // Do we process the other instructions? 1041 1042 // Check for squashed instructions. 1043 if (inst->isSquashed()) { 1044 DPRINTF(IEW, "[tid:%i]: Issue: Squashed instruction encountered, " 1045 "not adding to IQ.\n", tid); 1046 1047 ++iewDispSquashedInsts; 1048 1049 insts_to_dispatch.pop(); 1050 1051 //Tell Rename That An Instruction has been processed 1052 if (inst->isLoad() || inst->isStore()) { 1053 toRename->iewInfo[tid].dispatchedToLSQ++; 1054 } 1055 toRename->iewInfo[tid].dispatched++; 1056 1057 continue; 1058 } 1059 1060 // Check for full conditions. 1061 if (instQueue.isFull(tid)) { 1062 DPRINTF(IEW, "[tid:%i]: Issue: IQ has become full.\n", tid); 1063 1064 // Call function to start blocking. 1065 block(tid); 1066 1067 // Set unblock to false. Special case where we are using 1068 // skidbuffer (unblocking) instructions but then we still 1069 // get full in the IQ. 1070 toRename->iewUnblock[tid] = false; 1071 1072 dispatchedAllInsts = false; 1073 1074 ++iewIQFullEvents; 1075 break; 1076 } else if (ldstQueue.isFull(tid)) { 1077 DPRINTF(IEW, "[tid:%i]: Issue: LSQ has become full.\n",tid); 1078 1079 // Call function to start blocking. 1080 block(tid); 1081 1082 // Set unblock to false. Special case where we are using 1083 // skidbuffer (unblocking) instructions but then we still 1084 // get full in the IQ. 1085 toRename->iewUnblock[tid] = false; 1086 1087 dispatchedAllInsts = false; 1088 1089 ++iewLSQFullEvents; 1090 break; 1091 } 1092 1093 // Otherwise issue the instruction just fine. 1094 if (inst->isLoad()) { 1095 DPRINTF(IEW, "[tid:%i]: Issue: Memory instruction " 1096 "encountered, adding to LSQ.\n", tid); 1097 1098 // Reserve a spot in the load store queue for this 1099 // memory access. 1100 ldstQueue.insertLoad(inst); 1101 1102 ++iewDispLoadInsts; 1103 1104 add_to_iq = true; 1105 1106 toRename->iewInfo[tid].dispatchedToLSQ++; 1107 } else if (inst->isStore()) { 1108 DPRINTF(IEW, "[tid:%i]: Issue: Memory instruction " 1109 "encountered, adding to LSQ.\n", tid); 1110 1111 ldstQueue.insertStore(inst); 1112 1113 ++iewDispStoreInsts; 1114 1115 if (inst->isNonSpeculative()) { 1116 inst->setCanCommit(); 1117 instQueue.insertNonSpec(inst); 1118 add_to_iq = false; 1119 1120 ++iewDispNonSpecInsts; 1121 } else { 1122 add_to_iq = true; 1123 } 1124 1125 toRename->iewInfo[tid].dispatchedToLSQ++; 1126#if FULL_SYSTEM 1127 } else if (inst->isMemBarrier() || inst->isWriteBarrier()) { 1128 inst->setCanCommit(); 1129 instQueue.insertBarrier(inst); 1130 add_to_iq = false; 1131#endif 1132 } else if (inst->isNonSpeculative()) { 1133 DPRINTF(IEW, "[tid:%i]: Issue: Nonspeculative instruction " 1134 "encountered, skipping.\n", tid); 1135 1136 // Same hack as with stores. 1137 inst->setCanCommit(); 1138 1139 // Specifically insert it as nonspeculative. 1140 instQueue.insertNonSpec(inst); 1141 1142 ++iewDispNonSpecInsts; 1143 1144 add_to_iq = false; 1145 } else if (inst->isNop()) { 1146 DPRINTF(IEW, "[tid:%i]: Issue: Nop instruction encountered, " 1147 "skipping.\n", tid); 1148 1149 inst->setIssued(); 1150 inst->setExecuted(); 1151 inst->setCanCommit(); 1152 1153 instQueue.advanceTail(inst); 1154 1155 exe_nop[tid]++; 1156 1157 add_to_iq = false; 1158 } else if (inst->isExecuted()) { 1159 assert(0 && "Instruction shouldn't be executed.\n"); 1160 DPRINTF(IEW, "Issue: Executed branch encountered, " 1161 "skipping.\n"); 1162 1163 inst->setIssued(); 1164 inst->setCanCommit(); 1165 1166 instQueue.advanceTail(inst); 1167 1168 add_to_iq = false; 1169 } else { 1170 add_to_iq = true; 1171 } 1172 1173 // If the instruction queue is not full, then add the 1174 // instruction. 1175 if (add_to_iq) { 1176 instQueue.insert(inst); 1177 } 1178 1179 insts_to_dispatch.pop(); 1180 1181 toRename->iewInfo[tid].dispatched++; 1182 1183 ++iewDispatchedInsts; 1184 } 1185 1186 if (!insts_to_dispatch.empty()) { 1187 DPRINTF(IEW,"[tid:%i]: Issue: Bandwidth Full. Blocking.\n"); 1188 block(tid); 1189 toRename->iewUnblock[tid] = false; 1190 } 1191 1192 if (dispatchStatus[tid] == Idle && dis_num_inst) { 1193 dispatchStatus[tid] = Running; 1194 1195 updatedQueues = true; 1196 } 1197 1198 dis_num_inst = 0; 1199} 1200 1201template <class Impl> 1202void 1203DefaultIEW<Impl>::printAvailableInsts() 1204{ 1205 int inst = 0; 1206 1207 cout << "Available Instructions: "; 1208 1209 while (fromIssue->insts[inst]) { 1210 1211 if (inst%3==0) cout << "\n\t"; 1212 1213 cout << "PC: " << fromIssue->insts[inst]->readPC() 1214 << " TN: " << fromIssue->insts[inst]->threadNumber 1215 << " SN: " << fromIssue->insts[inst]->seqNum << " | "; 1216 1217 inst++; 1218 1219 } 1220 1221 cout << "\n"; 1222} 1223 1224template <class Impl> 1225void 1226DefaultIEW<Impl>::executeInsts() 1227{ 1228 //bool fetch_redirect[(*activeThreads).size()]; 1229 wbNumInst = 0; 1230 wbCycle = 0; 1231 1232 list<unsigned>::iterator threads = (*activeThreads).begin(); 1233 1234 while (threads != (*activeThreads).end()) { 1235 unsigned tid = *threads++; 1236 fetchRedirect[tid] = false; 1237 } 1238 1239#if 0 1240 printAvailableInsts(); 1241#endif 1242 1243 // Execute/writeback any instructions that are available. 1244 int inst_num = 0; 1245 for ( ; inst_num < issueWidth && /* Haven't exceeded issue bandwidth */ 1246 fromIssue->insts[inst_num]; 1247 ++inst_num) { 1248 1249 DPRINTF(IEW, "Execute: Executing instructions from IQ.\n"); 1250 1251 // Get instruction from issue's queue. 1252 DynInstPtr inst = fromIssue->insts[inst_num]; 1253 1254 DPRINTF(IEW, "Execute: Processing PC %#x, [tid:%i] [sn:%i].\n", 1255 inst->readPC(), inst->threadNumber,inst->seqNum); 1256 1257 // Check if the instruction is squashed; if so then skip it 1258 // and don't count it towards the FU usage. 1259 if (inst->isSquashed()) { 1260 DPRINTF(IEW, "Execute: Instruction was squashed.\n"); 1261 1262 // Consider this instruction executed so that commit can go 1263 // ahead and retire the instruction. 1264 inst->setExecuted(); 1265 1266 // Not sure if I should set this here or just let commit try to 1267 // commit any squashed instructions. I like the latter a bit more. 1268 inst->setCanCommit(); 1269 1270 ++iewExecSquashedInsts; 1271 1272 continue; 1273 } 1274 1275 Fault fault = NoFault; 1276 1277 // Execute instruction. 1278 // Note that if the instruction faults, it will be handled 1279 // at the commit stage. 1280 if (inst->isMemRef() && 1281 (!inst->isDataPrefetch() && !inst->isInstPrefetch())) { 1282 DPRINTF(IEW, "Execute: Calculating address for memory " 1283 "reference.\n"); 1284 1285 // Tell the LDSTQ to execute this instruction (if it is a load). 1286 if (inst->isLoad()) { 1287 // Loads will mark themselves as executed, and their writeback 1288 // event adds the instruction to the queue to commit 1289 fault = ldstQueue.executeLoad(inst); 1290 1291// ++iewExecLoadInsts; 1292 } else if (inst->isStore()) { 1293 ldstQueue.executeStore(inst); 1294 1295// ++iewExecStoreInsts; 1296 1297 // If the store had a fault then it may not have a mem req 1298 if (inst->req && !(inst->req->flags & LOCKED)) { 1299 inst->setExecuted(); 1300 1301 instToCommit(inst); 1302 } 1303 // Store conditionals will mark themselves as executed, and 1304 // their writeback event will add the instruction to the queue 1305 // to commit. 1306 } else { 1307 panic("Unexpected memory type!\n"); 1308 } 1309 1310 } else { 1311 inst->execute(); 1312 1313 inst->setExecuted(); 1314 1315 instToCommit(inst); 1316 } 1317 1318 updateExeInstStats(inst); 1319 1320 // Check if branch was correct. This check happens after the 1321 // instruction is added to the queue because even if the branch 1322 // is mispredicted, the branch instruction itself is still valid. 1323 // Only handle this if there hasn't already been something that 1324 // redirects fetch in this group of instructions. 1325 1326 // This probably needs to prioritize the redirects if a different 1327 // scheduler is used. Currently the scheduler schedules the oldest 1328 // instruction first, so the branch resolution order will be correct. 1329 unsigned tid = inst->threadNumber; 1330 1331 if (!fetchRedirect[tid]) { 1332 1333 if (inst->mispredicted()) { 1334 fetchRedirect[tid] = true; 1335 1336 DPRINTF(IEW, "Execute: Branch mispredict detected.\n"); 1337 DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x.\n", 1338 inst->nextPC); 1339 1340 // If incorrect, then signal the ROB that it must be squashed. 1341 squashDueToBranch(inst, tid); 1342 1343 if (inst->predTaken()) { 1344 predictedTakenIncorrect++; 1345 } else { 1346 predictedNotTakenIncorrect++; 1347 } 1348 } else if (ldstQueue.violation(tid)) { 1349 fetchRedirect[tid] = true; 1350 1351 // Get the DynInst that caused the violation. Note that this 1352 // clears the violation signal. 1353 DynInstPtr violator; 1354 violator = ldstQueue.getMemDepViolator(tid); 1355 1356 DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: " 1357 "%#x, inst PC: %#x. Addr is: %#x.\n", 1358 violator->readPC(), inst->readPC(), inst->physEffAddr); 1359 1360 // Tell the instruction queue that a violation has occured. 1361 instQueue.violation(inst, violator); 1362 1363 // Squash. 1364 squashDueToMemOrder(inst,tid); 1365 1366 ++memOrderViolationEvents; 1367 } else if (ldstQueue.loadBlocked(tid) && 1368 !ldstQueue.isLoadBlockedHandled(tid)) { 1369 fetchRedirect[tid] = true; 1370 1371 DPRINTF(IEW, "Load operation couldn't execute because the " 1372 "memory system is blocked. PC: %#x [sn:%lli]\n", 1373 inst->readPC(), inst->seqNum); 1374 1375 squashDueToMemBlocked(inst, tid); 1376 } 1377 } 1378 } 1379 1380 if (inst_num) { 1381 if (exeStatus == Idle) { 1382 exeStatus = Running; 1383 } 1384 1385 updatedQueues = true; 1386 1387 cpu->activityThisCycle(); 1388 } 1389 1390 // Need to reset this in case a writeback event needs to write into the 1391 // iew queue. That way the writeback event will write into the correct 1392 // spot in the queue. 1393 wbNumInst = 0; 1394} 1395 1396template <class Impl> 1397void 1398DefaultIEW<Impl>::writebackInsts() 1399{ 1400 // Loop through the head of the time buffer and wake any dependents. 1401 // These instructions are about to write back. In the simple model 1402 // this loop can really happen within the previous loop, but when 1403 // instructions have actual latencies, this loop must be separate. 1404 // Also mark scoreboard that this instruction is finally complete. 1405 // Either have IEW have direct access to rename map, or have this as 1406 // part of backwards communication. 1407 for (int inst_num = 0; inst_num < issueWidth && 1408 toCommit->insts[inst_num]; inst_num++) { 1409 DynInstPtr inst = toCommit->insts[inst_num]; 1410 int tid = inst->threadNumber; 1411 1412 DPRINTF(IEW, "Sending instructions to commit, PC %#x.\n", 1413 inst->readPC()); 1414 1415 iewInstsToCommit[tid]++; 1416 1417 // Some instructions will be sent to commit without having 1418 // executed because they need commit to handle them. 1419 // E.g. Uncached loads have not actually executed when they 1420 // are first sent to commit. Instead commit must tell the LSQ 1421 // when it's ready to execute the uncached load. 1422 if (!inst->isSquashed() && inst->isExecuted()) { 1423 int dependents = instQueue.wakeDependents(inst); 1424 1425 for (int i = 0; i < inst->numDestRegs(); i++) { 1426 //mark as Ready 1427 DPRINTF(IEW,"Setting Destination Register %i\n", 1428 inst->renamedDestRegIdx(i)); 1429 scoreboard->setReg(inst->renamedDestRegIdx(i)); 1430 } 1431 1432 producer_inst[tid]++; 1433 consumer_inst[tid]+= dependents; 1434 writeback_count[tid]++; 1435 } 1436 } 1437} 1438 1439template<class Impl> 1440void 1441DefaultIEW<Impl>::tick() 1442{ 1443 // Try to fill up issue queue with as many instructions as bandwidth 1444 // allows. 1445 wbNumInst = 0; 1446 wbCycle = 0; 1447 1448 wroteToTimeBuffer = false; 1449 updatedQueues = false; 1450 1451 sortInsts(); 1452 1453 list<unsigned>::iterator threads = (*activeThreads).begin(); 1454 1455 // Check stall and squash signals. 1456 while (threads != (*activeThreads).end()) { 1457 unsigned tid = *threads++; 1458 1459 DPRINTF(IEW,"Issue: Processing [tid:%i]\n",tid); 1460 1461 checkSignalsAndUpdate(tid); 1462 dispatch(tid); 1463 1464 } 1465 1466 if (exeStatus != Squashing) { 1467 executeInsts(); 1468 1469 writebackInsts(); 1470 1471 // Have the instruction queue try to schedule any ready instructions. 1472 // (In actuality, this scheduling is for instructions that will 1473 // be executed next cycle.) 1474 instQueue.scheduleReadyInsts(); 1475 1476 // Also should advance its own time buffers if the stage ran. 1477 // Not the best place for it, but this works (hopefully). 1478 issueToExecQueue.advance(); 1479 } 1480 1481 bool broadcast_free_entries = false; 1482 1483 if (updatedQueues || exeStatus == Running || updateLSQNextCycle) { 1484 exeStatus = Idle; 1485 updateLSQNextCycle = false; 1486 1487 broadcast_free_entries = true; 1488 } 1489 1490 // Writeback any stores using any leftover bandwidth. 1491 ldstQueue.writebackStores(); 1492 1493 // Free function units marked as being freed this cycle. 1494 fuPool->processFreeUnits(); 1495 1496 // Check the committed load/store signals to see if there's a load 1497 // or store to commit. Also check if it's being told to execute a 1498 // nonspeculative instruction. 1499 // This is pretty inefficient... 1500 1501 threads = (*activeThreads).begin(); 1502 while (threads != (*activeThreads).end()) { 1503 unsigned tid = (*threads++); 1504 1505 DPRINTF(IEW,"Processing [tid:%i]\n",tid); 1506 1507 if (fromCommit->commitInfo[tid].doneSeqNum != 0 && 1508 !fromCommit->commitInfo[tid].squash && 1509 !fromCommit->commitInfo[tid].robSquashing) { 1510 1511 ldstQueue.commitStores(fromCommit->commitInfo[tid].doneSeqNum,tid); 1512 1513 ldstQueue.commitLoads(fromCommit->commitInfo[tid].doneSeqNum,tid); 1514 1515 updateLSQNextCycle = true; 1516 instQueue.commit(fromCommit->commitInfo[tid].doneSeqNum,tid); 1517 } 1518 1519 if (fromCommit->commitInfo[tid].nonSpecSeqNum != 0) { 1520 1521 //DPRINTF(IEW,"NonspecInst from thread %i",tid); 1522 if (fromCommit->commitInfo[tid].uncached) { 1523 instQueue.replayMemInst(fromCommit->commitInfo[tid].uncachedLoad); 1524 } else { 1525 instQueue.scheduleNonSpec( 1526 fromCommit->commitInfo[tid].nonSpecSeqNum); 1527 } 1528 } 1529 1530 if (broadcast_free_entries) { 1531 toFetch->iewInfo[tid].iqCount = 1532 instQueue.getCount(tid); 1533 toFetch->iewInfo[tid].ldstqCount = 1534 ldstQueue.getCount(tid); 1535 1536 toRename->iewInfo[tid].usedIQ = true; 1537 toRename->iewInfo[tid].freeIQEntries = 1538 instQueue.numFreeEntries(); 1539 toRename->iewInfo[tid].usedLSQ = true; 1540 toRename->iewInfo[tid].freeLSQEntries = 1541 ldstQueue.numFreeEntries(tid); 1542 1543 wroteToTimeBuffer = true; 1544 } 1545 1546 DPRINTF(IEW, "[tid:%i], Dispatch dispatched %i instructions.\n", 1547 tid, toRename->iewInfo[tid].dispatched); 1548 1549 //thread_queue.pop(); 1550 } 1551 1552 DPRINTF(IEW, "IQ has %i free entries (Can schedule: %i). " 1553 "LSQ has %i free entries.\n", 1554 instQueue.numFreeEntries(), instQueue.hasReadyInsts(), 1555 ldstQueue.numFreeEntries()); 1556 1557 updateStatus(); 1558 1559 if (wroteToTimeBuffer) { 1560 DPRINTF(Activity, "Activity this cycle.\n"); 1561 cpu->activityThisCycle(); 1562 } 1563} 1564 1565template <class Impl> 1566void 1567DefaultIEW<Impl>::updateExeInstStats(DynInstPtr &inst) 1568{ 1569 int thread_number = inst->threadNumber; 1570 1571 // 1572 // Pick off the software prefetches 1573 // 1574#ifdef TARGET_ALPHA 1575 if (inst->isDataPrefetch()) 1576 exe_swp[thread_number]++; 1577 else 1578 iewExecutedInsts++; 1579#else 1580 iewExecutedInsts[thread_number]++; 1581#endif 1582 1583 // 1584 // Control operations 1585 // 1586 if (inst->isControl()) 1587 exe_branches[thread_number]++; 1588 1589 // 1590 // Memory operations 1591 // 1592 if (inst->isMemRef()) { 1593 exe_refs[thread_number]++; 1594 1595 if (inst->isLoad()) { 1596 iewExecLoadInsts[thread_number]++; 1597 } 1598 } 1599} 1600