iew_impl.hh revision 1717
11689SN/A/* 29783Sandreas.hansson@arm.com * Copyright (c) 2004-2005 The Regents of The University of Michigan 310239Sbinhpham@cs.rutgers.edu * All rights reserved. 47598Sminkyu.jeong@arm.com * 57598Sminkyu.jeong@arm.com * Redistribution and use in source and binary forms, with or without 67598Sminkyu.jeong@arm.com * modification, are permitted provided that the following conditions are 77598Sminkyu.jeong@arm.com * met: redistributions of source code must retain the above copyright 87598Sminkyu.jeong@arm.com * notice, this list of conditions and the following disclaimer; 97598Sminkyu.jeong@arm.com * redistributions in binary form must reproduce the above copyright 107598Sminkyu.jeong@arm.com * notice, this list of conditions and the following disclaimer in the 117598Sminkyu.jeong@arm.com * documentation and/or other materials provided with the distribution; 127598Sminkyu.jeong@arm.com * neither the name of the copyright holders nor the names of its 137598Sminkyu.jeong@arm.com * contributors may be used to endorse or promote products derived from 147598Sminkyu.jeong@arm.com * this software without specific prior written permission. 152326SN/A * 161689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 181689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 191689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 201689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 211689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 221689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 231689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 241689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 251689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 261689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 271689SN/A */ 281689SN/A 291689SN/A// @todo: Fix the instantaneous communication among all the stages within 301689SN/A// iew. There's a clear delay between issue and execute, yet backwards 311689SN/A// communication happens simultaneously. 321689SN/A// Update the statuses for each stage. 331689SN/A 341689SN/A#include <queue> 351689SN/A 361689SN/A#include "base/timebuf.hh" 371689SN/A#include "cpu/o3/iew.hh" 381689SN/A 391689SN/Atemplate<class Impl> 402665Ssaidi@eecs.umich.eduSimpleIEW<Impl>::WritebackEvent::WritebackEvent(DynInstPtr &_inst, 412665Ssaidi@eecs.umich.edu SimpleIEW<Impl> *_iew) 421689SN/A : Event(&mainEventQueue, CPU_Tick_Pri), inst(_inst), iewStage(_iew) 431689SN/A{ 449944Smatt.horsnell@ARM.com this->setFlags(Event::AutoDelete); 459944Smatt.horsnell@ARM.com} 469944Smatt.horsnell@ARM.com 471060SN/Atemplate<class Impl> 481060SN/Avoid 491689SN/ASimpleIEW<Impl>::WritebackEvent::process() 501060SN/A{ 511060SN/A DPRINTF(IEW, "IEW: WRITEBACK EVENT!!!!\n"); 521060SN/A 538230Snate@binkert.org // Need to insert instruction into queue to commit 546658Snate@binkert.org iewStage->instToCommit(inst); 558887Sgeoffrey.blake@arm.com // Need to execute second half of the instruction, do actual writing to 562292SN/A // registers and such 571717SN/A inst->execute(); 588229Snate@binkert.org} 598232Snate@binkert.org 609444SAndreas.Sandberg@ARM.comtemplate<class Impl> 618232Snate@binkert.orgconst char * 629527SMatt.Horsnell@arm.comSimpleIEW<Impl>::WritebackEvent::description() 635529Snate@binkert.org{ 641060SN/A return "LSQ writeback event"; 656221Snate@binkert.org} 666221Snate@binkert.org 671681SN/Atemplate<class Impl> 685529Snate@binkert.orgSimpleIEW<Impl>::SimpleIEW(Params ¶ms) 692873Sktlim@umich.edu : // Just make this time buffer really big for now 704329Sktlim@umich.edu issueToExecQueue(5, 5), 714329Sktlim@umich.edu instQueue(params), 724329Sktlim@umich.edu ldstQueue(params), 732292SN/A commitToIEWDelay(params.commitToIEWDelay), 742292SN/A renameToIEWDelay(params.renameToIEWDelay), 752292SN/A issueToExecuteDelay(params.issueToExecuteDelay), 762292SN/A issueReadWidth(params.issueWidth), 772820Sktlim@umich.edu issueWidth(params.issueWidth), 782292SN/A executeWidth(params.executeWidth) 792820Sktlim@umich.edu{ 802820Sktlim@umich.edu DPRINTF(IEW, "IEW: executeIntWidth: %i.\n", params.executeIntWidth); 819444SAndreas.Sandberg@ARM.com _status = Idle; 821060SN/A _issueStatus = Idle; 8310172Sdam.sunwoo@arm.com _exeStatus = Idle; 8410172Sdam.sunwoo@arm.com _wbStatus = Idle; 8510172Sdam.sunwoo@arm.com 8610172Sdam.sunwoo@arm.com // Setup wire to read instructions coming from issue. 8710172Sdam.sunwoo@arm.com fromIssue = issueToExecQueue.getWire(-issueToExecuteDelay); 8810172Sdam.sunwoo@arm.com 8910172Sdam.sunwoo@arm.com // Instruction queue needs the queue between issue and execute. 9010172Sdam.sunwoo@arm.com instQueue.setIssueToExecuteQueue(&issueToExecQueue); 9110172Sdam.sunwoo@arm.com 9210172Sdam.sunwoo@arm.com ldstQueue.setIEW(this); 9310172Sdam.sunwoo@arm.com} 9410172Sdam.sunwoo@arm.com 9510172Sdam.sunwoo@arm.comtemplate <class Impl> 962292SN/Avoid 972292SN/ASimpleIEW<Impl>::regStats() 982292SN/A{ 991060SN/A instQueue.regStats(); 1001060SN/A 1011060SN/A iewIdleCycles 1021060SN/A .name(name() + ".iewIdleCycles") 1031060SN/A .desc("Number of cycles IEW is idle"); 1041060SN/A 1051681SN/A iewSquashCycles 1066221Snate@binkert.org .name(name() + ".iewSquashCycles") 1076221Snate@binkert.org .desc("Number of cycles IEW is squashing"); 1086221Snate@binkert.org 1096221Snate@binkert.org iewBlockCycles 1102292SN/A .name(name() + ".iewBlockCycles") 1112292SN/A .desc("Number of cycles IEW is blocking"); 1122820Sktlim@umich.edu 1132820Sktlim@umich.edu iewUnblockCycles 1142292SN/A .name(name() + ".iewUnblockCycles") 1152292SN/A .desc("Number of cycles IEW is unblocking"); 1162820Sktlim@umich.edu 1172820Sktlim@umich.edu// iewWBInsts; 1182292SN/A 1192292SN/A iewDispatchedInsts 1202292SN/A .name(name() + ".iewDispatchedInsts") 1212292SN/A .desc("Number of instructions dispatched to IQ"); 1222292SN/A 1232292SN/A iewDispSquashedInsts 1242292SN/A .name(name() + ".iewDispSquashedInsts") 1252292SN/A .desc("Number of squashed instructions skipped by dispatch"); 1261060SN/A 1271060SN/A iewDispLoadInsts 1281681SN/A .name(name() + ".iewDispLoadInsts") 1291062SN/A .desc("Number of dispatched load instructions"); 13010023Smatt.horsnell@ARM.com 13110023Smatt.horsnell@ARM.com iewDispStoreInsts 13210023Smatt.horsnell@ARM.com .name(name() + ".iewDispStoreInsts") 13310023Smatt.horsnell@ARM.com .desc("Number of dispatched store instructions"); 13410023Smatt.horsnell@ARM.com 13510023Smatt.horsnell@ARM.com iewDispNonSpecInsts 13610023Smatt.horsnell@ARM.com .name(name() + ".iewDispNonSpecInsts") 13710023Smatt.horsnell@ARM.com .desc("Number of dispatched non-speculative instructions"); 1382292SN/A 1391062SN/A iewIQFullEvents 1402301SN/A .name(name() + ".iewIQFullEvents") 1412301SN/A .desc("Number of times the IQ has become full, causing a stall"); 1421062SN/A 1432727Sktlim@umich.edu iewExecutedInsts 1441062SN/A .name(name() + ".iewExecutedInsts") 1451062SN/A .desc("Number of executed instructions"); 1461062SN/A 1471062SN/A iewExecLoadInsts 1481062SN/A .name(name() + ".iewExecLoadInsts") 1491062SN/A .desc("Number of load instructions executed"); 1501062SN/A 1511062SN/A iewExecStoreInsts 1521062SN/A .name(name() + ".iewExecStoreInsts") 1531062SN/A .desc("Number of store instructions executed"); 1541062SN/A 1551062SN/A iewExecSquashedInsts 1561062SN/A .name(name() + ".iewExecSquashedInsts") 1571062SN/A .desc("Number of squashed instructions skipped in execute"); 1581062SN/A 1591062SN/A memOrderViolationEvents 1601062SN/A .name(name() + ".memOrderViolationEvents") 1611062SN/A .desc("Number of memory order violations"); 1621062SN/A 1631062SN/A predictedTakenIncorrect 1641062SN/A .name(name() + ".predictedTakenIncorrect") 1651062SN/A .desc("Number of branches that were predicted taken incorrectly"); 1661062SN/A} 1671062SN/A 1681062SN/Atemplate<class Impl> 1691062SN/Avoid 1701062SN/ASimpleIEW<Impl>::setCPU(FullCPU *cpu_ptr) 1711062SN/A{ 1721062SN/A DPRINTF(IEW, "IEW: Setting CPU pointer.\n"); 1731062SN/A cpu = cpu_ptr; 1741062SN/A 1751062SN/A instQueue.setCPU(cpu_ptr); 1761062SN/A ldstQueue.setCPU(cpu_ptr); 1771062SN/A} 1781062SN/A 1791062SN/Atemplate<class Impl> 1801062SN/Avoid 1811062SN/ASimpleIEW<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) 1821062SN/A{ 1831062SN/A DPRINTF(IEW, "IEW: Setting time buffer pointer.\n"); 1841062SN/A timeBuffer = tb_ptr; 1852292SN/A 1862292SN/A // Setup wire to read information from time buffer, from commit. 1872292SN/A fromCommit = timeBuffer->getWire(-commitToIEWDelay); 1882292SN/A 1891062SN/A // Setup wire to write information back to previous stages. 1901062SN/A toRename = timeBuffer->getWire(0); 1911062SN/A 1921062SN/A // Instruction queue also needs main time buffer. 1931062SN/A instQueue.setTimeBuffer(tb_ptr); 1941062SN/A} 1951062SN/A 1962292SN/Atemplate<class Impl> 1972292SN/Avoid 1982292SN/ASimpleIEW<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr) 1992292SN/A{ 2002292SN/A DPRINTF(IEW, "IEW: Setting rename queue pointer.\n"); 2012292SN/A renameQueue = rq_ptr; 2022292SN/A 2032292SN/A // Setup wire to read information from rename queue. 2042292SN/A fromRename = renameQueue->getWire(-renameToIEWDelay); 2052292SN/A} 2062301SN/A 2072727Sktlim@umich.edutemplate<class Impl> 2082353SN/Avoid 2092727Sktlim@umich.eduSimpleIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr) 2102727Sktlim@umich.edu{ 2112727Sktlim@umich.edu DPRINTF(IEW, "IEW: Setting IEW queue pointer.\n"); 2126221Snate@binkert.org iewQueue = iq_ptr; 2132353SN/A 2142727Sktlim@umich.edu // Setup wire to write instructions to commit. 2152727Sktlim@umich.edu toCommit = iewQueue->getWire(0); 2162727Sktlim@umich.edu} 2172727Sktlim@umich.edu 2182353SN/Atemplate<class Impl> 2192727Sktlim@umich.eduvoid 2202727Sktlim@umich.eduSimpleIEW<Impl>::setRenameMap(RenameMap *rm_ptr) 2212727Sktlim@umich.edu{ 2226221Snate@binkert.org DPRINTF(IEW, "IEW: Setting rename map pointer.\n"); 2238240Snate@binkert.org renameMap = rm_ptr; 2242301SN/A} 2252727Sktlim@umich.edu 2262301SN/Atemplate<class Impl> 2272727Sktlim@umich.eduvoid 2286221Snate@binkert.orgSimpleIEW<Impl>::squash() 2298240Snate@binkert.org{ 2302301SN/A DPRINTF(IEW, "IEW: Squashing all instructions.\n"); 2312727Sktlim@umich.edu _status = Squashing; 2322301SN/A 2332727Sktlim@umich.edu // Tell the IQ to start squashing. 2346221Snate@binkert.org instQueue.squash(); 2358240Snate@binkert.org 2362301SN/A // Tell the LDSTQ to start squashing. 2372727Sktlim@umich.edu ldstQueue.squash(fromCommit->commitInfo.doneSeqNum); 2382301SN/A} 2392727Sktlim@umich.edu 2406221Snate@binkert.orgtemplate<class Impl> 2418240Snate@binkert.orgvoid 2422301SN/ASimpleIEW<Impl>::squashDueToBranch(DynInstPtr &inst) 2432727Sktlim@umich.edu{ 2442301SN/A DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n", 2452301SN/A inst->PC); 2468240Snate@binkert.org // Perhaps leave the squashing up to the ROB stage to tell it when to 2472301SN/A // squash? 2482727Sktlim@umich.edu _status = Squashing; 2492727Sktlim@umich.edu 2502727Sktlim@umich.edu // Tell rename to squash through the time buffer. 2512727Sktlim@umich.edu toCommit->squash = true; 2528240Snate@binkert.org // Also send PC update information back to prior stages. 2532727Sktlim@umich.edu toCommit->squashedSeqNum = inst->seqNum; 2542727Sktlim@umich.edu toCommit->mispredPC = inst->readPC(); 2552727Sktlim@umich.edu toCommit->nextPC = inst->readNextPC(); 2562727Sktlim@umich.edu toCommit->branchMispredict = true; 2572301SN/A // Prediction was incorrect, so send back inverse. 2582301SN/A toCommit->branchTaken = inst->readNextPC() != 2596221Snate@binkert.org (inst->readPC() + sizeof(MachInst)); 2608240Snate@binkert.org} 2612301SN/A 2622727Sktlim@umich.edutemplate<class Impl> 2632301SN/Avoid 2642326SN/ASimpleIEW<Impl>::squashDueToMem(DynInstPtr &inst) 2656221Snate@binkert.org{ 2668240Snate@binkert.org DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n", 2672301SN/A inst->PC); 2682727Sktlim@umich.edu // Perhaps leave the squashing up to the ROB stage to tell it when to 2692301SN/A // squash? 2702326SN/A _status = Squashing; 2716221Snate@binkert.org 2728240Snate@binkert.org // Tell rename to squash through the time buffer. 2732301SN/A toCommit->squash = true; 2742727Sktlim@umich.edu // Also send PC update information back to prior stages. 2752301SN/A toCommit->squashedSeqNum = inst->seqNum; 2762326SN/A toCommit->nextPC = inst->readNextPC(); 2776221Snate@binkert.org} 2788240Snate@binkert.org 2792301SN/Atemplate<class Impl> 2802727Sktlim@umich.eduvoid 2812301SN/ASimpleIEW<Impl>::block() 2822326SN/A{ 2836221Snate@binkert.org DPRINTF(IEW, "IEW: Blocking.\n"); 2848240Snate@binkert.org // Set the status to Blocked. 2852301SN/A _status = Blocked; 2862727Sktlim@umich.edu 2872301SN/A // Add the current inputs to the skid buffer so they can be 2882326SN/A // reprocessed when this stage unblocks. 2898240Snate@binkert.org skidBuffer.push(*fromRename); 2902301SN/A 2912727Sktlim@umich.edu // Note that this stage only signals previous stages to stall when 2922301SN/A // it is the cause of the stall originates at this stage. Otherwise 2932326SN/A // the previous stages are expected to check all possible stall signals. 2942301SN/A} 2952326SN/A 2968240Snate@binkert.orgtemplate<class Impl> 2972301SN/Ainline void 2982727Sktlim@umich.eduSimpleIEW<Impl>::unblock() 2992301SN/A{ 3002326SN/A // Check if there's information in the skid buffer. If there is, then 3012301SN/A // set status to unblocking, otherwise set it directly to running. 3022326SN/A DPRINTF(IEW, "IEW: Reading instructions out of the skid " 3038240Snate@binkert.org "buffer.\n"); 3042301SN/A // Remove the now processed instructions from the skid buffer. 3052727Sktlim@umich.edu skidBuffer.pop(); 3062326SN/A 3071062SN/A // If there's still information in the skid buffer, then 3081062SN/A // continue to tell previous stages to stall. They will be 3091681SN/A // able to restart once the skid buffer is empty. 3101060SN/A if (!skidBuffer.empty()) { 3119427SAndreas.Sandberg@ARM.com toRename->iewInfo.stall = true; 3121060SN/A } else { 3136221Snate@binkert.org DPRINTF(IEW, "IEW: Stage is done unblocking.\n"); 3142292SN/A _status = Running; 3152292SN/A } 3162292SN/A} 3172292SN/A 3182292SN/Atemplate<class Impl> 31910239Sbinhpham@cs.rutgers.eduvoid 32010239Sbinhpham@cs.rutgers.eduSimpleIEW<Impl>::wakeDependents(DynInstPtr &inst) 3212292SN/A{ 3222292SN/A instQueue.wakeDependents(inst); 3238887Sgeoffrey.blake@arm.com} 3248733Sgeoffrey.blake@arm.com 3258850Sandreas.hansson@arm.com 3268887Sgeoffrey.blake@arm.comtemplate<class Impl> 3278733Sgeoffrey.blake@arm.comvoid 3282733Sktlim@umich.eduSimpleIEW<Impl>::instToCommit(DynInstPtr &inst) 3291060SN/A{ 3301060SN/A 3311681SN/A} 3321060SN/A 3332292SN/Atemplate <class Impl> 3341060SN/Avoid 3351060SN/ASimpleIEW<Impl>::dispatchInsts() 3361060SN/A{ 3371060SN/A //////////////////////////////////////// 3381060SN/A // DISPATCH/ISSUE stage 3391060SN/A //////////////////////////////////////// 3401060SN/A 3411060SN/A //Put into its own function? 3421060SN/A //Add instructions to IQ if there are any instructions there 3432292SN/A 3442292SN/A // Check if there are any instructions coming from rename, and we're. 3451060SN/A // not squashing. 3461060SN/A if (fromRename->size > 0) { 3471060SN/A int insts_to_add = fromRename->size; 3481060SN/A 3491681SN/A // Loop through the instructions, putting them in the instruction 3501060SN/A // queue. 3512292SN/A for (int inst_num = 0; inst_num < insts_to_add; ++inst_num) 3521060SN/A { 3531060SN/A DynInstPtr inst = fromRename->insts[inst_num]; 3541060SN/A 3551060SN/A // Make sure there's a valid instruction there. 3561060SN/A assert(inst); 3571060SN/A 3581060SN/A DPRINTF(IEW, "IEW: Issue: Adding PC %#x to IQ.\n", 3591681SN/A inst->readPC()); 3601060SN/A 3612292SN/A // Be sure to mark these instructions as ready so that the 3621060SN/A // commit stage can go ahead and execute them, and mark 3631060SN/A // them as issued so the IQ doesn't reprocess them. 3641060SN/A if (inst->isSquashed()) { 3651060SN/A ++iewDispSquashedInsts; 3661060SN/A continue; 3671060SN/A } else if (instQueue.isFull()) { 3681060SN/A DPRINTF(IEW, "IEW: Issue: IQ has become full.\n"); 3691681SN/A // Call function to start blocking. 3701060SN/A block(); 3716221Snate@binkert.org // Tell previous stage to stall. 3721060SN/A toRename->iewInfo.stall = true; 3732292SN/A 3742292SN/A ++iewIQFullEvents; 3752292SN/A break; 3762292SN/A } else if (inst->isLoad()) { 3771060SN/A DPRINTF(IEW, "IEW: Issue: Memory instruction " 3781060SN/A "encountered, adding to LDSTQ.\n"); 3791681SN/A 3801060SN/A // Reserve a spot in the load store queue for this 3812292SN/A // memory access. 3821060SN/A ldstQueue.insertLoad(inst); 3832292SN/A 3841060SN/A ++iewDispLoadInsts; 3851060SN/A } else if (inst->isStore()) { 3862307SN/A ldstQueue.insertStore(inst); 3872863Sktlim@umich.edu 3889444SAndreas.Sandberg@ARM.com ++iewDispStoreInsts; 3892307SN/A } else if (inst->isNonSpeculative()) { 3909444SAndreas.Sandberg@ARM.com DPRINTF(IEW, "IEW: Issue: Nonspeculative instruction " 3919444SAndreas.Sandberg@ARM.com "encountered, skipping.\n"); 3929444SAndreas.Sandberg@ARM.com 3939444SAndreas.Sandberg@ARM.com // Same hack as with stores. 3949444SAndreas.Sandberg@ARM.com inst->setCanCommit(); 3959444SAndreas.Sandberg@ARM.com 3969444SAndreas.Sandberg@ARM.com // Specificall insert it as nonspeculative. 3979444SAndreas.Sandberg@ARM.com instQueue.insertNonSpec(inst); 3989444SAndreas.Sandberg@ARM.com 3999444SAndreas.Sandberg@ARM.com ++iewDispNonSpecInsts; 4009444SAndreas.Sandberg@ARM.com 4019444SAndreas.Sandberg@ARM.com continue; 4029444SAndreas.Sandberg@ARM.com } else if (inst->isNop()) { 4039783Sandreas.hansson@arm.com DPRINTF(IEW, "IEW: Issue: Nop instruction encountered " 4049783Sandreas.hansson@arm.com ", skipping.\n"); 4059783Sandreas.hansson@arm.com 4069783Sandreas.hansson@arm.com inst->setIssued(); 4079783Sandreas.hansson@arm.com inst->setExecuted(); 4089783Sandreas.hansson@arm.com inst->setCanCommit(); 4099783Sandreas.hansson@arm.com 4109783Sandreas.hansson@arm.com instQueue.advanceTail(inst); 4119444SAndreas.Sandberg@ARM.com 4121681SN/A continue; 4131681SN/A } else if (inst->isExecuted()) { 4142316SN/A assert(0 && "Instruction shouldn't be executed.\n"); 4151681SN/A DPRINTF(IEW, "IEW: Issue: Executed branch encountered, " 4169444SAndreas.Sandberg@ARM.com "skipping.\n"); 4172843Sktlim@umich.edu 4189444SAndreas.Sandberg@ARM.com inst->setIssued(); 4192843Sktlim@umich.edu inst->setCanCommit(); 4209444SAndreas.Sandberg@ARM.com 4219444SAndreas.Sandberg@ARM.com instQueue.advanceTail(inst); 4221681SN/A 4231681SN/A continue; 4242307SN/A } 4251681SN/A 4262307SN/A // If the instruction queue is not full, then add the 4271060SN/A // instruction. 4282348SN/A instQueue.insert(fromRename->insts[inst_num]); 4292307SN/A 4302307SN/A ++iewDispatchedInsts; 4312307SN/A } 4321060SN/A } 4332307SN/A} 4342307SN/A 4359444SAndreas.Sandberg@ARM.comtemplate <class Impl> 4361060SN/Avoid 4379427SAndreas.Sandberg@ARM.comSimpleIEW<Impl>::executeInsts() 4382307SN/A{ 4391060SN/A //////////////////////////////////////// 4406221Snate@binkert.org //EXECUTE/WRITEBACK stage 4416221Snate@binkert.org //////////////////////////////////////// 4426221Snate@binkert.org 4436221Snate@binkert.org //Put into its own function? 4442307SN/A //Similarly should probably have separate execution for int vs FP. 4451060SN/A // Above comment is handled by the issue queue only issuing a valid 4462307SN/A // mix of int/fp instructions. 4472307SN/A //Actually okay to just have one execution, buuuuuut will need 4482873Sktlim@umich.edu //somewhere that defines the execution latency of all instructions. 4492307SN/A // @todo: Move to the FU pool used in the current full cpu. 4501060SN/A 4511060SN/A int fu_usage = 0; 4521060SN/A bool fetch_redirect = false; 4531681SN/A int inst_slot = 0; 4541060SN/A int time_slot = 0; 4556221Snate@binkert.org 4562107SN/A // Execute/writeback any instructions that are available. 4576221Snate@binkert.org for (int inst_num = 0; 4582107SN/A fu_usage < executeWidth && /* Haven't exceeded available FU's. */ 4592292SN/A inst_num < issueWidth && 4602292SN/A fromIssue->insts[inst_num]; 4612107SN/A ++inst_num) { 4622292SN/A 4632326SN/A DPRINTF(IEW, "IEW: Execute: Executing instructions from IQ.\n"); 4642292SN/A 4652107SN/A // Get instruction from issue's queue. 4662292SN/A DynInstPtr inst = fromIssue->insts[inst_num]; 4672935Sksewell@umich.edu 4684632Sgblack@eecs.umich.edu DPRINTF(IEW, "IEW: Execute: Processing PC %#x.\n", inst->readPC()); 4692935Sksewell@umich.edu 4702292SN/A // Check if the instruction is squashed; if so then skip it 47110239Sbinhpham@cs.rutgers.edu // and don't count it towards the FU usage. 47210239Sbinhpham@cs.rutgers.edu if (inst->isSquashed()) { 47310239Sbinhpham@cs.rutgers.edu DPRINTF(IEW, "IEW: Execute: Instruction was squashed.\n"); 47410239Sbinhpham@cs.rutgers.edu 47510239Sbinhpham@cs.rutgers.edu // Consider this instruction executed so that commit can go 4762292SN/A // ahead and retire the instruction. 4772107SN/A inst->setExecuted(); 4782292SN/A 4792107SN/A toCommit->insts[inst_num] = inst; 4802292SN/A 4812292SN/A ++iewExecSquashedInsts; 4822107SN/A 4832702Sktlim@umich.edu continue; 4842107SN/A } 4852107SN/A 4862107SN/A inst->setExecuted(); 4872107SN/A 4886221Snate@binkert.org // If an instruction is executed, then count it towards FU usage. 4892292SN/A ++fu_usage; 4907720Sgblack@eecs.umich.edu 4917720Sgblack@eecs.umich.edu // Execute instruction. 4922292SN/A // Note that if the instruction faults, it will be handled 49310231Ssteve.reinhardt@amd.com // at the commit stage. 4947852SMatt.Horsnell@arm.com if (inst->isMemRef()) { 4957852SMatt.Horsnell@arm.com DPRINTF(IEW, "IEW: Execute: Calculating address for memory " 4967852SMatt.Horsnell@arm.com "reference.\n"); 4977852SMatt.Horsnell@arm.com 4982935Sksewell@umich.edu // Tell the LDSTQ to execute this instruction (if it is a load). 4997852SMatt.Horsnell@arm.com if (inst->isLoad()) { 5007852SMatt.Horsnell@arm.com ldstQueue.executeLoad(inst); 5012292SN/A 5027852SMatt.Horsnell@arm.com ++iewExecLoadInsts; 5037852SMatt.Horsnell@arm.com } else if (inst->isStore()) { 5047852SMatt.Horsnell@arm.com ldstQueue.executeStore(inst); 5052292SN/A 5067852SMatt.Horsnell@arm.com ++iewExecStoreInsts; 5077852SMatt.Horsnell@arm.com } else { 5087852SMatt.Horsnell@arm.com panic("IEW: Unexpected memory type!\n"); 5092292SN/A } 5102292SN/A 5112292SN/A } else { 5122292SN/A inst->execute(); 5136221Snate@binkert.org 5142292SN/A ++iewExecutedInsts; 5158513SGiacomo.Gabrielli@arm.com } 5168513SGiacomo.Gabrielli@arm.com 5178513SGiacomo.Gabrielli@arm.com // First check the time slot that this instruction will write 5188513SGiacomo.Gabrielli@arm.com // to. If there are free write ports at the time, then go ahead 5198513SGiacomo.Gabrielli@arm.com // and write the instruction to that time. If there are not, 5208513SGiacomo.Gabrielli@arm.com // keep looking back to see where's the first time there's a 5218513SGiacomo.Gabrielli@arm.com // free slot. What happens if you run out of free spaces? 5228513SGiacomo.Gabrielli@arm.com // For now naively assume that all instructions take one cycle. 52310231Ssteve.reinhardt@amd.com // Otherwise would have to look into the time buffer based on the 5248513SGiacomo.Gabrielli@arm.com // latency of the instruction. 5258513SGiacomo.Gabrielli@arm.com (*iewQueue)[time_slot].insts[inst_slot]; 5262292SN/A while ((*iewQueue)[time_slot].insts[inst_slot]) { 5277852SMatt.Horsnell@arm.com if (inst_slot < issueWidth) { 5288513SGiacomo.Gabrielli@arm.com ++inst_slot; 5298137SAli.Saidi@ARM.com } else { 5302292SN/A ++time_slot; 5318513SGiacomo.Gabrielli@arm.com inst_slot = 0; 5328513SGiacomo.Gabrielli@arm.com } 5332292SN/A 5347852SMatt.Horsnell@arm.com assert(time_slot < 5); 5357852SMatt.Horsnell@arm.com } 5362292SN/A 5372292SN/A // May actually have to work this out, especially with loads and stores 5382292SN/A 5392292SN/A // Add finished instruction to queue to commit. 5406221Snate@binkert.org (*iewQueue)[time_slot].insts[inst_slot] = inst; 5412292SN/A (*iewQueue)[time_slot].size++; 5422292SN/A 5437720Sgblack@eecs.umich.edu // Check if branch was correct. This check happens after the 54410231Ssteve.reinhardt@amd.com // instruction is added to the queue because even if the branch 5457852SMatt.Horsnell@arm.com // is mispredicted, the branch instruction itself is still valid. 5467852SMatt.Horsnell@arm.com // Only handle this if there hasn't already been something that 5472292SN/A // redirects fetch in this group of instructions. 5487852SMatt.Horsnell@arm.com if (!fetch_redirect) { 5497852SMatt.Horsnell@arm.com if (inst->mispredicted()) { 5508137SAli.Saidi@ARM.com fetch_redirect = true; 5512292SN/A 5527852SMatt.Horsnell@arm.com DPRINTF(IEW, "IEW: Execute: Branch mispredict detected.\n"); 5537852SMatt.Horsnell@arm.com DPRINTF(IEW, "IEW: Execute: Redirecting fetch to PC: %#x.\n", 5542292SN/A inst->nextPC); 5557852SMatt.Horsnell@arm.com 5562292SN/A // If incorrect, then signal the ROB that it must be squashed. 5577852SMatt.Horsnell@arm.com squashDueToBranch(inst); 5587852SMatt.Horsnell@arm.com 5592292SN/A if (inst->predTaken()) { 5602292SN/A predictedTakenIncorrect++; 5612292SN/A } 5622292SN/A } else if (ldstQueue.violation()) { 5636221Snate@binkert.org fetch_redirect = true; 5642292SN/A 5652292SN/A // Get the DynInst that caused the violation. 5662292SN/A DynInstPtr violator = ldstQueue.getMemDepViolator(); 5672292SN/A 5682292SN/A DPRINTF(IEW, "IEW: LDSTQ detected a violation. Violator PC: " 5692292SN/A "%#x, inst PC: %#x. Addr is: %#x.\n", 5702292SN/A violator->readPC(), inst->readPC(), inst->physEffAddr); 5712292SN/A 5722292SN/A // Tell the instruction queue that a violation has occured. 5732292SN/A instQueue.violation(inst, violator); 5742292SN/A 5752292SN/A // Squash. 5762292SN/A squashDueToMem(inst); 5772292SN/A 5782292SN/A ++memOrderViolationEvents; 5792292SN/A } 5802292SN/A } 5812292SN/A } 5826221Snate@binkert.org} 5832292SN/A 5842292SN/Atemplate<class Impl> 5852292SN/Avoid 5862292SN/ASimpleIEW<Impl>::tick() 5872292SN/A{ 5882292SN/A // Considering putting all the state-determining stuff in this section. 5892292SN/A 5902292SN/A // Try to fill up issue queue with as many instructions as bandwidth 5912292SN/A // allows. 5922292SN/A // Decode should try to execute as many instructions as its bandwidth 5932292SN/A // will allow, as long as it is not currently blocked. 5942292SN/A 5952292SN/A // Check if the stage is in a running status. 5962292SN/A if (_status != Blocked && _status != Squashing) { 5972292SN/A DPRINTF(IEW, "IEW: Status is not blocked, attempting to run " 5982292SN/A "stage.\n"); 5992292SN/A iew(); 6001060SN/A 6011681SN/A // If it's currently unblocking, check to see if it should switch 6021060SN/A // to running. 6031060SN/A if (_status == Unblocking) { 6042292SN/A unblock(); 6052292SN/A 6062292SN/A ++iewUnblockCycles; 6072292SN/A } 6082292SN/A } else if (_status == Squashing) { 6092292SN/A 6101681SN/A DPRINTF(IEW, "IEW: Still squashing.\n"); 6111681SN/A 6121060SN/A // Check if stage should remain squashing. Stop squashing if the 6132292SN/A // squash signal clears. 6141060SN/A if (!fromCommit->commitInfo.squash && 6152292SN/A !fromCommit->commitInfo.robSquashing) { 6162292SN/A DPRINTF(IEW, "IEW: Done squashing, changing status to " 6171060SN/A "running.\n"); 6182292SN/A 6192292SN/A _status = Running; 6202292SN/A instQueue.stopSquash(); 6212292SN/A } else { 6223221Sktlim@umich.edu instQueue.doSquash(); 6233221Sktlim@umich.edu } 6243221Sktlim@umich.edu 6253221Sktlim@umich.edu ++iewSquashCycles; 6263221Sktlim@umich.edu } else if (_status == Blocked) { 6272292SN/A // Continue to tell previous stage to stall. 6282292SN/A toRename->iewInfo.stall = true; 6292292SN/A 6302292SN/A // Check if possible stall conditions have cleared. 6312326SN/A if (!fromCommit->commitInfo.stall && 6322292SN/A !instQueue.isFull()) { 6332292SN/A DPRINTF(IEW, "IEW: Stall signals cleared, going to unblock.\n"); 6342820Sktlim@umich.edu _status = Unblocking; 6352292SN/A } 6362292SN/A 6372292SN/A // If there's still instructions coming from rename, continue to 6382292SN/A // put them on the skid buffer. 6392353SN/A if (fromRename->size == 0) { 6402292SN/A block(); 6412292SN/A } 6422353SN/A 6432353SN/A if (fromCommit->commitInfo.squash || 6442292SN/A fromCommit->commitInfo.robSquashing) { 6452292SN/A squash(); 6462292SN/A } 6472292SN/A 6482292SN/A ++iewBlockCycles; 6492292SN/A } 6502292SN/A 6512292SN/A // @todo: Maybe put these at the beginning, so if it's idle it can 6522292SN/A // return early. 6532292SN/A // Write back number of free IQ entries here. 6542292SN/A toRename->iewInfo.freeIQEntries = instQueue.numFreeEntries(); 6552292SN/A 6562731Sktlim@umich.edu ldstQueue.writebackStores(); 6572292SN/A 6582292SN/A // Check the committed load/store signals to see if there's a load 6592292SN/A // or store to commit. Also check if it's being told to execute a 6602292SN/A // nonspeculative instruction. 6612292SN/A // This is pretty inefficient... 6622292SN/A if (!fromCommit->commitInfo.squash && 6632292SN/A !fromCommit->commitInfo.robSquashing) { 6642292SN/A ldstQueue.commitStores(fromCommit->commitInfo.doneSeqNum); 6656221Snate@binkert.org ldstQueue.commitLoads(fromCommit->commitInfo.doneSeqNum); 6662292SN/A } 6672292SN/A 6682292SN/A if (fromCommit->commitInfo.nonSpecSeqNum != 0) { 6692292SN/A instQueue.scheduleNonSpec(fromCommit->commitInfo.nonSpecSeqNum); 6702292SN/A } 6712292SN/A 6722292SN/A DPRINTF(IEW, "IEW: IQ has %i free entries.\n", 6732292SN/A instQueue.numFreeEntries()); 6749937SFaissal.Sleiman@arm.com} 6752292SN/A 6767720Sgblack@eecs.umich.edutemplate<class Impl> 6772292SN/Avoid 6782292SN/ASimpleIEW<Impl>::iew() 6792292SN/A{ 6802292SN/A // Might want to put all state checks in the tick() function. 6812292SN/A // Check if being told to stall from commit. 6822292SN/A if (fromCommit->commitInfo.stall) { 6832292SN/A block(); 6842292SN/A return; 6852292SN/A } else if (fromCommit->commitInfo.squash || 6862292SN/A fromCommit->commitInfo.robSquashing) { 6872292SN/A // Also check if commit is telling this stage to squash. 6882292SN/A squash(); 6892292SN/A return; 6902292SN/A } 6916221Snate@binkert.org 6926221Snate@binkert.org dispatchInsts(); 6932292SN/A 6943867Sbinkertn@umich.edu // Have the instruction queue try to schedule any ready instructions. 6956221Snate@binkert.org instQueue.scheduleReadyInsts(); 6963867Sbinkertn@umich.edu 6972292SN/A executeInsts(); 6982292SN/A 6992292SN/A // Loop through the head of the time buffer and wake any dependents. 7002292SN/A // These instructions are about to write back. In the simple model 7012292SN/A // this loop can really happen within the previous loop, but when 7022292SN/A // instructions have actual latencies, this loop must be separate. 7032292SN/A // Also mark scoreboard that this instruction is finally complete. 7042292SN/A // Either have IEW have direct access to rename map, or have this as 7052292SN/A // part of backwards communication. 7062292SN/A for (int inst_num = 0; inst_num < issueWidth && 7072292SN/A toCommit->insts[inst_num]; inst_num++) 7086221Snate@binkert.org { 7096221Snate@binkert.org DynInstPtr inst = toCommit->insts[inst_num]; 7102292SN/A 7113867Sbinkertn@umich.edu DPRINTF(IEW, "IEW: Sending instructions to commit, PC %#x.\n", 7126221Snate@binkert.org inst->readPC()); 7133867Sbinkertn@umich.edu 7143867Sbinkertn@umich.edu if(!inst->isSquashed()) { 7152292SN/A instQueue.wakeDependents(inst); 7162292SN/A 7172292SN/A for (int i = 0; i < inst->numDestRegs(); i++) 7182292SN/A { 7191062SN/A renameMap->markAsReady(inst->renamedDestRegIdx(i)); 7201062SN/A } 7211681SN/A } 7221062SN/A } 7232292SN/A 7241062SN/A // Also should advance its own time buffers if the stage ran. 7252292SN/A // Not the best place for it, but this works (hopefully). 7261062SN/A issueToExecQueue.advance(); 7276221Snate@binkert.org} 7286221Snate@binkert.org 7291062SN/A#ifndef FULL_SYSTEM 7303867Sbinkertn@umich.edutemplate<class Impl> 7316221Snate@binkert.orgvoid 7321062SN/ASimpleIEW<Impl>::lsqWriteback() 7332292SN/A{ 7342292SN/A ldstQueue.writebackAllInsts(); 7352292SN/A} 7362292SN/A#endif 7372292SN/A