iew_impl.hh revision 2107
11689SN/A/* 210333Smitch.hayenga@arm.com * Copyright (c) 2004-2005 The Regents of The University of Michigan 39920Syasuko.eckert@amd.com * All rights reserved. 47944SGiacomo.Gabrielli@arm.com * 57944SGiacomo.Gabrielli@arm.com * Redistribution and use in source and binary forms, with or without 67944SGiacomo.Gabrielli@arm.com * modification, are permitted provided that the following conditions are 77944SGiacomo.Gabrielli@arm.com * met: redistributions of source code must retain the above copyright 87944SGiacomo.Gabrielli@arm.com * notice, this list of conditions and the following disclaimer; 97944SGiacomo.Gabrielli@arm.com * redistributions in binary form must reproduce the above copyright 107944SGiacomo.Gabrielli@arm.com * notice, this list of conditions and the following disclaimer in the 117944SGiacomo.Gabrielli@arm.com * documentation and/or other materials provided with the distribution; 127944SGiacomo.Gabrielli@arm.com * neither the name of the copyright holders nor the names of its 137944SGiacomo.Gabrielli@arm.com * contributors may be used to endorse or promote products derived from 147944SGiacomo.Gabrielli@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) 422831Sksewell@umich.edu : Event(&mainEventQueue, CPU_Tick_Pri), inst(_inst), iewStage(_iew) 431689SN/A{ 441689SN/A this->setFlags(Event::AutoDelete); 459944Smatt.horsnell@ARM.com} 469944Smatt.horsnell@ARM.com 479944Smatt.horsnell@ARM.comtemplate<class Impl> 482064SN/Avoid 491060SN/ASimpleIEW<Impl>::WritebackEvent::process() 501060SN/A{ 512292SN/A DPRINTF(IEW, "IEW: WRITEBACK EVENT!!!!\n"); 521717SN/A 538232Snate@binkert.org // Need to insert instruction into queue to commit 544762Snate@binkert.org iewStage->instToCommit(inst); 556221Snate@binkert.org // Need to execute second half of the instruction, do actual writing to 564762Snate@binkert.org // registers and such 571060SN/A inst->execute(); 588737Skoansin.tan@gmail.com} 598737Skoansin.tan@gmail.com 608737Skoansin.tan@gmail.comtemplate<class Impl> 615529Snate@binkert.orgconst char * 621061SN/ASimpleIEW<Impl>::WritebackEvent::description() 632292SN/A{ 645606Snate@binkert.org return "LSQ writeback event"; 658581Ssteve.reinhardt@amd.com} 668581Ssteve.reinhardt@amd.com 671060SN/Atemplate<class Impl> 682292SN/ASimpleIEW<Impl>::SimpleIEW(Params ¶ms) 692292SN/A : // Just make this time buffer really big for now 702292SN/A issueToExecQueue(5, 5), 712292SN/A instQueue(params), 722292SN/A ldstQueue(params), 732292SN/A commitToIEWDelay(params.commitToIEWDelay), 742326SN/A renameToIEWDelay(params.renameToIEWDelay), 752292SN/A issueToExecuteDelay(params.issueToExecuteDelay), 762292SN/A issueReadWidth(params.issueWidth), 772292SN/A issueWidth(params.issueWidth), 782292SN/A executeWidth(params.executeWidth) 792292SN/A{ 802292SN/A DPRINTF(IEW, "IEW: executeIntWidth: %i.\n", params.executeIntWidth); 815336Shines@cs.fsu.edu _status = Idle; 822292SN/A _issueStatus = Idle; 834873Sstever@eecs.umich.edu _exeStatus = Idle; 842292SN/A _wbStatus = Idle; 852292SN/A 862292SN/A // Setup wire to read instructions coming from issue. 874329Sktlim@umich.edu fromIssue = issueToExecQueue.getWire(-issueToExecuteDelay); 885529Snate@binkert.org 894329Sktlim@umich.edu // Instruction queue needs the queue between issue and execute. 904329Sktlim@umich.edu instQueue.setIssueToExecuteQueue(&issueToExecQueue); 914329Sktlim@umich.edu 922292SN/A ldstQueue.setIEW(this); 932292SN/A} 942292SN/A 952292SN/Atemplate <class Impl> 962292SN/Avoid 972292SN/ASimpleIEW<Impl>::regStats() 985529Snate@binkert.org{ 991060SN/A instQueue.regStats(); 1009920Syasuko.eckert@amd.com 1019920Syasuko.eckert@amd.com iewIdleCycles 1029920Syasuko.eckert@amd.com .name(name() + ".iewIdleCycles") 1031060SN/A .desc("Number of cycles IEW is idle"); 1041060SN/A 1051060SN/A iewSquashCycles 1062326SN/A .name(name() + ".iewSquashCycles") 1071060SN/A .desc("Number of cycles IEW is squashing"); 1081060SN/A 1091060SN/A iewBlockCycles 1101060SN/A .name(name() + ".iewBlockCycles") 1112292SN/A .desc("Number of cycles IEW is blocking"); 1126221Snate@binkert.org 1136221Snate@binkert.org iewUnblockCycles 1146221Snate@binkert.org .name(name() + ".iewUnblockCycles") 1151060SN/A .desc("Number of cycles IEW is unblocking"); 1161060SN/A 1172307SN/A// iewWBInsts; 1182292SN/A 1192980Sgblack@eecs.umich.edu 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"); 1262292SN/A 1272292SN/A iewDispLoadInsts 1282292SN/A .name(name() + ".iewDispLoadInsts") 1292292SN/A .desc("Number of dispatched load instructions"); 1306221Snate@binkert.org 1316221Snate@binkert.org iewDispStoreInsts 1322292SN/A .name(name() + ".iewDispStoreInsts") 1332292SN/A .desc("Number of dispatched store instructions"); 1342292SN/A 1352292SN/A iewDispNonSpecInsts 1362292SN/A .name(name() + ".iewDispNonSpecInsts") 1372292SN/A .desc("Number of dispatched non-speculative instructions"); 1382292SN/A 1392292SN/A iewIQFullEvents 1402292SN/A .name(name() + ".iewIQFullEvents") 1416221Snate@binkert.org .desc("Number of times the IQ has become full, causing a stall"); 1426221Snate@binkert.org 1432292SN/A iewExecutedInsts 1442292SN/A .name(name() + ".iewExecutedInsts") 1452831Sksewell@umich.edu .desc("Number of executed instructions"); 1462292SN/A 1472292SN/A iewExecLoadInsts 1482292SN/A .name(name() + ".iewExecLoadInsts") 1492292SN/A .desc("Number of load instructions executed"); 1502292SN/A 1512292SN/A iewExecStoreInsts 1522292SN/A .name(name() + ".iewExecStoreInsts") 1532292SN/A .desc("Number of store instructions executed"); 1542292SN/A 1556221Snate@binkert.org iewExecSquashedInsts 1566221Snate@binkert.org .name(name() + ".iewExecSquashedInsts") 1572292SN/A .desc("Number of squashed instructions skipped in execute"); 1582292SN/A 1592831Sksewell@umich.edu memOrderViolationEvents 1602292SN/A .name(name() + ".memOrderViolationEvents") 1612292SN/A .desc("Number of memory order violations"); 1622292SN/A 1632292SN/A predictedTakenIncorrect 1642292SN/A .name(name() + ".predictedTakenIncorrect") 1652292SN/A .desc("Number of branches that were predicted taken incorrectly"); 1662292SN/A} 1672292SN/A 1682292SN/Atemplate<class Impl> 1692292SN/Avoid 1702326SN/ASimpleIEW<Impl>::setCPU(FullCPU *cpu_ptr) 1712348SN/A{ 1722326SN/A DPRINTF(IEW, "IEW: Setting CPU pointer.\n"); 1732326SN/A cpu = cpu_ptr; 1742348SN/A 1752292SN/A instQueue.setCPU(cpu_ptr); 1762292SN/A ldstQueue.setCPU(cpu_ptr); 1772292SN/A} 1782292SN/A 1792292SN/Atemplate<class Impl> 1802292SN/Avoid 1812292SN/ASimpleIEW<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) 1821060SN/A{ 1831060SN/A DPRINTF(IEW, "IEW: Setting time buffer pointer.\n"); 1841061SN/A timeBuffer = tb_ptr; 1851060SN/A 1861062SN/A // Setup wire to read information from time buffer, from commit. 1871062SN/A fromCommit = timeBuffer->getWire(-commitToIEWDelay); 1882301SN/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 1961062SN/Atemplate<class Impl> 1971062SN/Avoid 1981062SN/ASimpleIEW<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr) 1992301SN/A{ 2002301SN/A DPRINTF(IEW, "IEW: Setting rename queue pointer.\n"); 2012301SN/A renameQueue = rq_ptr; 2022301SN/A 2031062SN/A // Setup wire to read information from rename queue. 2041062SN/A fromRename = renameQueue->getWire(-renameToIEWDelay); 2051062SN/A} 2061062SN/A 2071062SN/Atemplate<class Impl> 2081062SN/Avoid 2091062SN/ASimpleIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr) 2101062SN/A{ 2111062SN/A DPRINTF(IEW, "IEW: Setting IEW queue pointer.\n"); 2121062SN/A iewQueue = iq_ptr; 2131062SN/A 2141062SN/A // Setup wire to write instructions to commit. 2151062SN/A toCommit = iewQueue->getWire(0); 2161062SN/A} 2171062SN/A 2181062SN/Atemplate<class Impl> 2191062SN/Avoid 2201062SN/ASimpleIEW<Impl>::setRenameMap(RenameMap *rm_ptr) 2211062SN/A{ 2221062SN/A DPRINTF(IEW, "IEW: Setting rename map pointer.\n"); 2231062SN/A renameMap = rm_ptr; 2241062SN/A} 2251062SN/A 2261062SN/Atemplate<class Impl> 2271062SN/Avoid 2281062SN/ASimpleIEW<Impl>::squash() 2291062SN/A{ 2301062SN/A DPRINTF(IEW, "IEW: Squashing all instructions.\n"); 2311062SN/A _status = Squashing; 2321062SN/A 2331062SN/A // Tell the IQ to start squashing. 2341062SN/A instQueue.squash(); 2351062SN/A 2361062SN/A // Tell the LDSTQ to start squashing. 2371062SN/A ldstQueue.squash(fromCommit->commitInfo.doneSeqNum); 2381062SN/A} 2391062SN/A 2401062SN/Atemplate<class Impl> 2411062SN/Avoid 2421062SN/ASimpleIEW<Impl>::squashDueToBranch(DynInstPtr &inst) 2431062SN/A{ 2441062SN/A DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n", 2451062SN/A inst->PC); 2461062SN/A // Perhaps leave the squashing up to the ROB stage to tell it when to 2471062SN/A // squash? 2481062SN/A _status = Squashing; 2491062SN/A 2502361SN/A // Tell rename to squash through the time buffer. 2512326SN/A toCommit->squash = true; 2522301SN/A // Also send PC update information back to prior stages. 2532301SN/A toCommit->squashedSeqNum = inst->seqNum; 2542301SN/A toCommit->mispredPC = inst->readPC(); 2552301SN/A toCommit->nextPC = inst->readNextPC(); 2562301SN/A toCommit->branchMispredict = true; 2572301SN/A // Prediction was incorrect, so send back inverse. 2582326SN/A toCommit->branchTaken = inst->readNextPC() != 2592301SN/A (inst->readPC() + sizeof(TheISA::MachInst)); 2602361SN/A} 2612326SN/A 2622307SN/Atemplate<class Impl> 2638240Snate@binkert.orgvoid 2642301SN/ASimpleIEW<Impl>::squashDueToMem(DynInstPtr &inst) 2652307SN/A{ 2662301SN/A DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n", 2672301SN/A inst->PC); 2682301SN/A // Perhaps leave the squashing up to the ROB stage to tell it when to 2692301SN/A // squash? 2708240Snate@binkert.org _status = Squashing; 2712301SN/A 2722301SN/A // Tell rename to squash through the time buffer. 2732301SN/A toCommit->squash = true; 2742301SN/A // Also send PC update information back to prior stages. 2752301SN/A toCommit->squashedSeqNum = inst->seqNum; 2762301SN/A toCommit->nextPC = inst->readNextPC(); 2772301SN/A} 2782326SN/A 2794762Snate@binkert.orgtemplate<class Impl> 2808240Snate@binkert.orgvoid 2812301SN/ASimpleIEW<Impl>::block() 2822301SN/A{ 2832301SN/A DPRINTF(IEW, "IEW: Blocking.\n"); 2844762Snate@binkert.org // Set the status to Blocked. 2852301SN/A _status = Blocked; 2862301SN/A 2872301SN/A // Add the current inputs to the skid buffer so they can be 2882301SN/A // reprocessed when this stage unblocks. 2892361SN/A skidBuffer.push(*fromRename); 2902326SN/A 2912301SN/A // Note that this stage only signals previous stages to stall when 2928240Snate@binkert.org // it is the cause of the stall originates at this stage. Otherwise 2932301SN/A // the previous stages are expected to check all possible stall signals. 2942301SN/A} 2952301SN/A 2962301SN/Atemplate<class Impl> 2972301SN/Ainline void 2982980Sgblack@eecs.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. 3022361SN/A DPRINTF(IEW, "IEW: Reading instructions out of the skid " 3032326SN/A "buffer.\n"); 3048240Snate@binkert.org // Remove the now processed instructions from the skid buffer. 3052301SN/A skidBuffer.pop(); 3062301SN/A 3072301SN/A // If there's still information in the skid buffer, then 3082326SN/A // continue to tell previous stages to stall. They will be 3092727Sktlim@umich.edu // able to restart once the skid buffer is empty. 3102326SN/A if (!skidBuffer.empty()) { 3112301SN/A toRename->iewInfo.stall = true; 3128240Snate@binkert.org } else { 3132301SN/A DPRINTF(IEW, "IEW: Stage is done unblocking.\n"); 3142301SN/A _status = Running; 3152301SN/A } 3162301SN/A} 3174762Snate@binkert.org 3182301SN/Atemplate<class Impl> 3192301SN/Avoid 3202326SN/ASimpleIEW<Impl>::wakeDependents(DynInstPtr &inst) 3212301SN/A{ 3228240Snate@binkert.org instQueue.wakeDependents(inst); 3232301SN/A} 3242301SN/A 3252301SN/A 3262301SN/Atemplate<class Impl> 3272326SN/Avoid 3288240Snate@binkert.orgSimpleIEW<Impl>::instToCommit(DynInstPtr &inst) 3292301SN/A{ 3302301SN/A 3312301SN/A} 3322326SN/A 3332301SN/Atemplate <class Impl> 3346221Snate@binkert.orgvoid 3352292SN/ASimpleIEW<Impl>::dispatchInsts() 3366221Snate@binkert.org{ 3372292SN/A //////////////////////////////////////// 3387897Shestness@cs.utexas.edu // DISPATCH/ISSUE stage 3397897Shestness@cs.utexas.edu //////////////////////////////////////// 3407897Shestness@cs.utexas.edu 3417897Shestness@cs.utexas.edu //Put into its own function? 3427897Shestness@cs.utexas.edu //Add instructions to IQ if there are any instructions there 3437897Shestness@cs.utexas.edu 3447897Shestness@cs.utexas.edu // Check if there are any instructions coming from rename, and we're. 3457897Shestness@cs.utexas.edu // not squashing. 3467897Shestness@cs.utexas.edu if (fromRename->size > 0) { 3477897Shestness@cs.utexas.edu int insts_to_add = fromRename->size; 3487897Shestness@cs.utexas.edu 3497897Shestness@cs.utexas.edu // Loop through the instructions, putting them in the instruction 3507897Shestness@cs.utexas.edu // queue. 3517897Shestness@cs.utexas.edu for (int inst_num = 0; inst_num < insts_to_add; ++inst_num) 3527897Shestness@cs.utexas.edu { 3537897Shestness@cs.utexas.edu DynInstPtr inst = fromRename->insts[inst_num]; 3547897Shestness@cs.utexas.edu 3557897Shestness@cs.utexas.edu // Make sure there's a valid instruction there. 3567897Shestness@cs.utexas.edu assert(inst); 3577897Shestness@cs.utexas.edu 3587897Shestness@cs.utexas.edu DPRINTF(IEW, "IEW: Issue: Adding PC %#x to IQ.\n", 3597897Shestness@cs.utexas.edu inst->readPC()); 3607897Shestness@cs.utexas.edu 3617897Shestness@cs.utexas.edu // Be sure to mark these instructions as ready so that the 3627897Shestness@cs.utexas.edu // commit stage can go ahead and execute them, and mark 3637897Shestness@cs.utexas.edu // them as issued so the IQ doesn't reprocess them. 3647897Shestness@cs.utexas.edu if (inst->isSquashed()) { 3657897Shestness@cs.utexas.edu ++iewDispSquashedInsts; 3667897Shestness@cs.utexas.edu continue; 3677897Shestness@cs.utexas.edu } else if (instQueue.isFull()) { 3687897Shestness@cs.utexas.edu DPRINTF(IEW, "IEW: Issue: IQ has become full.\n"); 3697897Shestness@cs.utexas.edu // Call function to start blocking. 3707897Shestness@cs.utexas.edu block(); 3717897Shestness@cs.utexas.edu // Tell previous stage to stall. 3727897Shestness@cs.utexas.edu toRename->iewInfo.stall = true; 3737897Shestness@cs.utexas.edu 3747897Shestness@cs.utexas.edu ++iewIQFullEvents; 3757897Shestness@cs.utexas.edu break; 3767897Shestness@cs.utexas.edu } else if (inst->isLoad()) { 3777897Shestness@cs.utexas.edu DPRINTF(IEW, "IEW: Issue: Memory instruction " 3787897Shestness@cs.utexas.edu "encountered, adding to LDSTQ.\n"); 3791062SN/A 3801062SN/A // Reserve a spot in the load store queue for this 3811062SN/A // memory access. 3821062SN/A ldstQueue.insertLoad(inst); 3832307SN/A 3841060SN/A ++iewDispLoadInsts; 3852307SN/A } else if (inst->isStore()) { 3866221Snate@binkert.org ldstQueue.insertStore(inst); 3876221Snate@binkert.org 3886221Snate@binkert.org ++iewDispStoreInsts; 3892307SN/A } else if (inst->isNonSpeculative()) { 3901060SN/A DPRINTF(IEW, "IEW: Issue: Nonspeculative instruction " 3912307SN/A "encountered, skipping.\n"); 3922307SN/A 3932307SN/A // Same hack as with stores. 3942307SN/A inst->setCanCommit(); 3952307SN/A 3962307SN/A // Specificall insert it as nonspeculative. 3972307SN/A instQueue.insertNonSpec(inst); 3982307SN/A 3992307SN/A ++iewDispNonSpecInsts; 4002307SN/A 4012307SN/A continue; 4022307SN/A } else if (inst->isNop()) { 4036221Snate@binkert.org DPRINTF(IEW, "IEW: Issue: Nop instruction encountered " 4046221Snate@binkert.org ", skipping.\n"); 4052307SN/A 4062307SN/A inst->setIssued(); 4072307SN/A inst->setExecuted(); 4082307SN/A inst->setCanCommit(); 4092307SN/A 4102307SN/A instQueue.advanceTail(inst); 4112307SN/A 4122307SN/A continue; 4132307SN/A } else if (inst->isExecuted()) { 4142307SN/A assert(0 && "Instruction shouldn't be executed.\n"); 4157944SGiacomo.Gabrielli@arm.com DPRINTF(IEW, "IEW: Issue: Executed branch encountered, " 41610333Smitch.hayenga@arm.com "skipping.\n"); 41710333Smitch.hayenga@arm.com 41810511Smitch.hayenga@arm.com inst->setIssued(); 4191060SN/A inst->setCanCommit(); 4201060SN/A 4211061SN/A instQueue.advanceTail(inst); 4221060SN/A 4236221Snate@binkert.org continue; 4241060SN/A } 4252292SN/A 4262064SN/A // If the instruction queue is not full, then add the 4272064SN/A // instruction. 4282064SN/A instQueue.insert(fromRename->insts[inst_num]); 4292064SN/A 4302292SN/A ++iewDispatchedInsts; 4312064SN/A } 4324318Sktlim@umich.edu } 4331060SN/A} 4341060SN/A 4351061SN/Atemplate <class Impl> 4361060SN/Avoid 4371060SN/ASimpleIEW<Impl>::executeInsts() 4381060SN/A{ 4391060SN/A //////////////////////////////////////// 4401060SN/A //EXECUTE/WRITEBACK stage 4411060SN/A //////////////////////////////////////// 4421060SN/A 4431060SN/A //Put into its own function? 4441684SN/A //Similarly should probably have separate execution for int vs FP. 44510510Smitch.hayenga@arm.com // Above comment is handled by the issue queue only issuing a valid 44610510Smitch.hayenga@arm.com // mix of int/fp instructions. 44710510Smitch.hayenga@arm.com //Actually okay to just have one execution, buuuuuut will need 44810511Smitch.hayenga@arm.com //somewhere that defines the execution latency of all instructions. 44910511Smitch.hayenga@arm.com // @todo: Move to the FU pool used in the current full cpu. 45010511Smitch.hayenga@arm.com 45110510Smitch.hayenga@arm.com int fu_usage = 0; 45210510Smitch.hayenga@arm.com bool fetch_redirect = false; 45310510Smitch.hayenga@arm.com int inst_slot = 0; 45410510Smitch.hayenga@arm.com int time_slot = 0; 45510510Smitch.hayenga@arm.com 45610510Smitch.hayenga@arm.com // Execute/writeback any instructions that are available. 45710510Smitch.hayenga@arm.com for (int inst_num = 0; 4582307SN/A fu_usage < executeWidth && /* Haven't exceeded available FU's. */ 4599444SAndreas.Sandberg@ARM.com inst_num < issueWidth && 4602307SN/A fromIssue->insts[inst_num]; 4619444SAndreas.Sandberg@ARM.com ++inst_num) { 4629444SAndreas.Sandberg@ARM.com 4639444SAndreas.Sandberg@ARM.com DPRINTF(IEW, "IEW: Execute: Executing instructions from IQ.\n"); 4649444SAndreas.Sandberg@ARM.com 4652307SN/A // Get instruction from issue's queue. 4662307SN/A DynInstPtr inst = fromIssue->insts[inst_num]; 4672307SN/A 4682307SN/A DPRINTF(IEW, "IEW: Execute: Processing PC %#x.\n", inst->readPC()); 4692307SN/A 4702307SN/A // Check if the instruction is squashed; if so then skip it 4719444SAndreas.Sandberg@ARM.com // and don't count it towards the FU usage. 4722307SN/A if (inst->isSquashed()) { 4732307SN/A DPRINTF(IEW, "IEW: Execute: Instruction was squashed.\n"); 4742307SN/A 4752292SN/A // Consider this instruction executed so that commit can go 4766221Snate@binkert.org // ahead and retire the instruction. 4772292SN/A inst->setExecuted(); 4782292SN/A 4792292SN/A toCommit->insts[inst_num] = inst; 4802292SN/A 4812292SN/A ++iewExecSquashedInsts; 4822292SN/A 4832292SN/A continue; 4842292SN/A } 4852292SN/A 4862292SN/A inst->setExecuted(); 4872292SN/A 4882292SN/A // If an instruction is executed, then count it towards FU usage. 4892292SN/A ++fu_usage; 4902292SN/A 4913867Sbinkertn@umich.edu // Execute instruction. 4922292SN/A // Note that if the instruction faults, it will be handled 4936221Snate@binkert.org // at the commit stage. 4946221Snate@binkert.org if (inst->isMemRef()) { 4952292SN/A DPRINTF(IEW, "IEW: Execute: Calculating address for memory " 4963867Sbinkertn@umich.edu "reference.\n"); 4976221Snate@binkert.org 4983867Sbinkertn@umich.edu // Tell the LDSTQ to execute this instruction (if it is a load). 4992292SN/A if (inst->isLoad()) { 5003867Sbinkertn@umich.edu ldstQueue.executeLoad(inst); 5012292SN/A 5023867Sbinkertn@umich.edu ++iewExecLoadInsts; 5032292SN/A } else if (inst->isStore()) { 5042292SN/A ldstQueue.executeStore(inst); 5052292SN/A 5062292SN/A ++iewExecStoreInsts; 5072292SN/A } else { 5082292SN/A panic("IEW: Unexpected memory type!\n"); 5091684SN/A } 5101684SN/A 5111684SN/A } else { 5121684SN/A inst->execute(); 5131684SN/A 5141684SN/A ++iewExecutedInsts; 5152292SN/A } 5162292SN/A 5176221Snate@binkert.org // First check the time slot that this instruction will write 5182292SN/A // to. If there are free write ports at the time, then go ahead 5192292SN/A // and write the instruction to that time. If there are not, 5202292SN/A // keep looking back to see where's the first time there's a 5212292SN/A // free slot. What happens if you run out of free spaces? 5221060SN/A // For now naively assume that all instructions take one cycle. 5231060SN/A // Otherwise would have to look into the time buffer based on the 5241061SN/A // latency of the instruction. 5251060SN/A (*iewQueue)[time_slot].insts[inst_slot]; 5261060SN/A while ((*iewQueue)[time_slot].insts[inst_slot]) { 5271060SN/A if (inst_slot < issueWidth) { 5281060SN/A ++inst_slot; 5291060SN/A } else { 5301060SN/A ++time_slot; 5311060SN/A inst_slot = 0; 5321060SN/A } 5331060SN/A 5341060SN/A assert(time_slot < 5); 5351061SN/A } 5362292SN/A 5376221Snate@binkert.org // May actually have to work this out, especially with loads and stores 5382292SN/A 5392292SN/A // Add finished instruction to queue to commit. 5402292SN/A (*iewQueue)[time_slot].insts[inst_slot] = inst; 5412292SN/A (*iewQueue)[time_slot].size++; 5422292SN/A 5432292SN/A // Check if branch was correct. This check happens after the 5442292SN/A // instruction is added to the queue because even if the branch 5452292SN/A // is mispredicted, the branch instruction itself is still valid. 5462292SN/A // Only handle this if there hasn't already been something that 5472292SN/A // redirects fetch in this group of instructions. 5482292SN/A if (!fetch_redirect) { 5492292SN/A if (inst->mispredicted()) { 5502292SN/A fetch_redirect = true; 5512292SN/A 5522292SN/A DPRINTF(IEW, "IEW: Execute: Branch mispredict detected.\n"); 5532292SN/A DPRINTF(IEW, "IEW: Execute: Redirecting fetch to PC: %#x.\n", 5542292SN/A inst->nextPC); 5552292SN/A 5562292SN/A // If incorrect, then signal the ROB that it must be squashed. 5572292SN/A squashDueToBranch(inst); 5582292SN/A 5592292SN/A if (inst->predTaken()) { 5602292SN/A predictedTakenIncorrect++; 5612292SN/A } 5622292SN/A } else if (ldstQueue.violation()) { 5632292SN/A fetch_redirect = true; 5641060SN/A 5651061SN/A // Get the DynInst that caused the violation. 5661060SN/A DynInstPtr violator = ldstQueue.getMemDepViolator(); 5677897Shestness@cs.utexas.edu 5681060SN/A DPRINTF(IEW, "IEW: LDSTQ detected a violation. Violator PC: " 5691060SN/A "%#x, inst PC: %#x. Addr is: %#x.\n", 5701060SN/A violator->readPC(), inst->readPC(), inst->physEffAddr); 5717720Sgblack@eecs.umich.edu 5727720Sgblack@eecs.umich.edu // Tell the instruction queue that a violation has occured. 5731060SN/A instQueue.violation(inst, violator); 5741060SN/A 5751060SN/A // Squash. 5762292SN/A squashDueToMem(inst); 5771060SN/A 5782064SN/A ++memOrderViolationEvents; 5791060SN/A } 5802292SN/A } 5811060SN/A } 5821060SN/A} 5831060SN/A 5841060SN/Atemplate<class Impl> 5851060SN/Avoid 5861060SN/ASimpleIEW<Impl>::tick() 5871060SN/A{ 5882326SN/A // Considering putting all the state-determining stuff in this section. 5891060SN/A 5901061SN/A // Try to fill up issue queue with as many instructions as bandwidth 5912292SN/A // allows. 5921062SN/A // Decode should try to execute as many instructions as its bandwidth 5931062SN/A // will allow, as long as it is not currently blocked. 5941061SN/A 5951061SN/A // Check if the stage is in a running status. 5961062SN/A if (_status != Blocked && _status != Squashing) { 5971060SN/A DPRINTF(IEW, "IEW: Status is not blocked, attempting to run " 5982292SN/A "stage.\n"); 5992292SN/A iew(); 6001060SN/A 6011060SN/A // If it's currently unblocking, check to see if it should switch 6021060SN/A // to running. 6031061SN/A if (_status == Unblocking) { 6041061SN/A unblock(); 6052292SN/A 6061061SN/A ++iewUnblockCycles; 6071061SN/A } 6081061SN/A } else if (_status == Squashing) { 6097897Shestness@cs.utexas.edu 6101061SN/A DPRINTF(IEW, "IEW: Still squashing.\n"); 6112292SN/A 6121061SN/A // Check if stage should remain squashing. Stop squashing if the 6132292SN/A // squash signal clears. 6141061SN/A if (!fromCommit->commitInfo.squash && 6157720Sgblack@eecs.umich.edu !fromCommit->commitInfo.robSquashing) { 6162326SN/A DPRINTF(IEW, "IEW: Done squashing, changing status to " 6177720Sgblack@eecs.umich.edu "running.\n"); 6182064SN/A 6191061SN/A _status = Running; 6201061SN/A instQueue.stopSquash(); 6212292SN/A } else { 6221061SN/A instQueue.doSquash(); 6232064SN/A } 6241061SN/A 6252292SN/A ++iewSquashCycles; 6261061SN/A } else if (_status == Blocked) { 6271061SN/A // Continue to tell previous stage to stall. 6281061SN/A toRename->iewInfo.stall = true; 6292326SN/A 6301061SN/A // Check if possible stall conditions have cleared. 6311061SN/A if (!fromCommit->commitInfo.stall && 6321061SN/A !instQueue.isFull()) { 6332292SN/A DPRINTF(IEW, "IEW: Stall signals cleared, going to unblock.\n"); 6342292SN/A _status = Unblocking; 6351061SN/A } 6361062SN/A 6371062SN/A // If there's still instructions coming from rename, continue to 6382292SN/A // put them on the skid buffer. 6392292SN/A if (fromRename->size == 0) { 6402292SN/A block(); 6412292SN/A } 6421061SN/A 6431061SN/A if (fromCommit->commitInfo.squash || 6441061SN/A fromCommit->commitInfo.robSquashing) { 6451060SN/A squash(); 6462292SN/A } 6471060SN/A 6482292SN/A ++iewBlockCycles; 6491060SN/A } 6502292SN/A 6512292SN/A // @todo: Maybe put these at the beginning, so if it's idle it can 6521060SN/A // return early. 6532064SN/A // Write back number of free IQ entries here. 6542333SN/A toRename->iewInfo.freeIQEntries = instQueue.numFreeEntries(); 6552333SN/A 6562333SN/A ldstQueue.writebackStores(); 6572333SN/A 6582333SN/A // Check the committed load/store signals to see if there's a load 6592333SN/A // or store to commit. Also check if it's being told to execute a 6607897Shestness@cs.utexas.edu // nonspeculative instruction. 6617897Shestness@cs.utexas.edu // This is pretty inefficient... 6627897Shestness@cs.utexas.edu if (!fromCommit->commitInfo.squash && 6637897Shestness@cs.utexas.edu !fromCommit->commitInfo.robSquashing) { 6647897Shestness@cs.utexas.edu ldstQueue.commitStores(fromCommit->commitInfo.doneSeqNum); 6652333SN/A ldstQueue.commitLoads(fromCommit->commitInfo.doneSeqNum); 6662333SN/A } 6671060SN/A 6682333SN/A if (fromCommit->commitInfo.nonSpecSeqNum != 0) { 6692064SN/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()); 6742292SN/A} 6752292SN/A 6762292SN/Atemplate<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(); 6891060SN/A return; 6901060SN/A } 6912292SN/A 6922292SN/A dispatchInsts(); 6932292SN/A 6941060SN/A // Have the instruction queue try to schedule any ready instructions. 6952292SN/A instQueue.scheduleReadyInsts(); 6962292SN/A 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++) 7082292SN/A { 7092292SN/A DynInstPtr inst = toCommit->insts[inst_num]; 7102292SN/A 7112292SN/A DPRINTF(IEW, "IEW: Sending instructions to commit, PC %#x.\n", 7122292SN/A inst->readPC()); 7132292SN/A 7142292SN/A if(!inst->isSquashed()) { 7152292SN/A instQueue.wakeDependents(inst); 7161060SN/A 7171060SN/A for (int i = 0; i < inst->numDestRegs(); i++) 7182292SN/A { 7191060SN/A renameMap->markAsReady(inst->renamedDestRegIdx(i)); 7201060SN/A } 7212292SN/A } 7222292SN/A } 7232292SN/A 7242292SN/A // Also should advance its own time buffers if the stage ran. 7252367SN/A // Not the best place for it, but this works (hopefully). 7269444SAndreas.Sandberg@ARM.com issueToExecQueue.advance(); 7272292SN/A} 7282292SN/A 72910511Smitch.hayenga@arm.com#if !FULL_SYSTEM 7302292SN/Atemplate<class Impl> 7312292SN/Avoid 7322326SN/ASimpleIEW<Impl>::lsqWriteback() 7332326SN/A{ 7342292SN/A ldstQueue.writebackAllInsts(); 7352326SN/A} 7362326SN/A#endif 7372326SN/A