iew_impl.hh revision 2665
11689SN/A/* 21689SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan 31689SN/A * All rights reserved. 41689SN/A * 51689SN/A * Redistribution and use in source and binary forms, with or without 61689SN/A * modification, are permitted provided that the following conditions are 71689SN/A * met: redistributions of source code must retain the above copyright 81689SN/A * notice, this list of conditions and the following disclaimer; 91689SN/A * redistributions in binary form must reproduce the above copyright 101689SN/A * notice, this list of conditions and the following disclaimer in the 111689SN/A * documentation and/or other materials provided with the distribution; 121689SN/A * neither the name of the copyright holders nor the names of its 131689SN/A * contributors may be used to endorse or promote products derived from 141689SN/A * this software without specific prior written permission. 151689SN/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. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Kevin Lim 291689SN/A */ 301689SN/A 311060SN/A// @todo: Fix the instantaneous communication among all the stages within 321060SN/A// iew. There's a clear delay between issue and execute, yet backwards 331689SN/A// communication happens simultaneously. 341061SN/A// Update the statuses for each stage. 351060SN/A 361060SN/A#include <queue> 371060SN/A 381060SN/A#include "base/timebuf.hh" 391717SN/A#include "cpu/o3/iew.hh" 401060SN/A 411681SN/Atemplate<class Impl> 421681SN/ASimpleIEW<Impl>::WritebackEvent::WritebackEvent(DynInstPtr &_inst, 431681SN/A SimpleIEW<Impl> *_iew) 441681SN/A : Event(&mainEventQueue, CPU_Tick_Pri), inst(_inst), iewStage(_iew) 451681SN/A{ 461681SN/A this->setFlags(Event::AutoDelete); 471681SN/A} 481681SN/A 491681SN/Atemplate<class Impl> 501681SN/Avoid 511681SN/ASimpleIEW<Impl>::WritebackEvent::process() 521681SN/A{ 531681SN/A DPRINTF(IEW, "IEW: WRITEBACK EVENT!!!!\n"); 541681SN/A 551681SN/A // Need to insert instruction into queue to commit 561681SN/A iewStage->instToCommit(inst); 571681SN/A // Need to execute second half of the instruction, do actual writing to 581681SN/A // registers and such 591681SN/A inst->execute(); 601681SN/A} 611681SN/A 621681SN/Atemplate<class Impl> 631681SN/Aconst char * 641681SN/ASimpleIEW<Impl>::WritebackEvent::description() 651681SN/A{ 661681SN/A return "LSQ writeback event"; 671681SN/A} 681681SN/A 691681SN/Atemplate<class Impl> 701681SN/ASimpleIEW<Impl>::SimpleIEW(Params ¶ms) 711060SN/A : // Just make this time buffer really big for now 721061SN/A issueToExecQueue(5, 5), 731060SN/A instQueue(params), 741061SN/A ldstQueue(params), 751060SN/A commitToIEWDelay(params.commitToIEWDelay), 761060SN/A renameToIEWDelay(params.renameToIEWDelay), 771060SN/A issueToExecuteDelay(params.issueToExecuteDelay), 781060SN/A issueReadWidth(params.issueWidth), 791060SN/A issueWidth(params.issueWidth), 801060SN/A executeWidth(params.executeWidth) 811060SN/A{ 821060SN/A DPRINTF(IEW, "IEW: executeIntWidth: %i.\n", params.executeIntWidth); 831060SN/A _status = Idle; 841060SN/A _issueStatus = Idle; 851060SN/A _exeStatus = Idle; 861060SN/A _wbStatus = Idle; 871060SN/A 881060SN/A // Setup wire to read instructions coming from issue. 891060SN/A fromIssue = issueToExecQueue.getWire(-issueToExecuteDelay); 901060SN/A 911060SN/A // Instruction queue needs the queue between issue and execute. 921060SN/A instQueue.setIssueToExecuteQueue(&issueToExecQueue); 931681SN/A 941681SN/A ldstQueue.setIEW(this); 951060SN/A} 961060SN/A 971681SN/Atemplate <class Impl> 981062SN/Avoid 991681SN/ASimpleIEW<Impl>::regStats() 1001062SN/A{ 1011062SN/A instQueue.regStats(); 1021062SN/A 1031062SN/A iewIdleCycles 1041062SN/A .name(name() + ".iewIdleCycles") 1051062SN/A .desc("Number of cycles IEW is idle"); 1061062SN/A 1071062SN/A iewSquashCycles 1081062SN/A .name(name() + ".iewSquashCycles") 1091062SN/A .desc("Number of cycles IEW is squashing"); 1101062SN/A 1111062SN/A iewBlockCycles 1121062SN/A .name(name() + ".iewBlockCycles") 1131062SN/A .desc("Number of cycles IEW is blocking"); 1141062SN/A 1151062SN/A iewUnblockCycles 1161062SN/A .name(name() + ".iewUnblockCycles") 1171062SN/A .desc("Number of cycles IEW is unblocking"); 1181062SN/A 1191062SN/A// iewWBInsts; 1201062SN/A 1211062SN/A iewDispatchedInsts 1221062SN/A .name(name() + ".iewDispatchedInsts") 1231062SN/A .desc("Number of instructions dispatched to IQ"); 1241062SN/A 1251062SN/A iewDispSquashedInsts 1261062SN/A .name(name() + ".iewDispSquashedInsts") 1271062SN/A .desc("Number of squashed instructions skipped by dispatch"); 1281062SN/A 1291062SN/A iewDispLoadInsts 1301062SN/A .name(name() + ".iewDispLoadInsts") 1311062SN/A .desc("Number of dispatched load instructions"); 1321062SN/A 1331062SN/A iewDispStoreInsts 1341062SN/A .name(name() + ".iewDispStoreInsts") 1351062SN/A .desc("Number of dispatched store instructions"); 1361062SN/A 1371062SN/A iewDispNonSpecInsts 1381062SN/A .name(name() + ".iewDispNonSpecInsts") 1391062SN/A .desc("Number of dispatched non-speculative instructions"); 1401062SN/A 1411062SN/A iewIQFullEvents 1421062SN/A .name(name() + ".iewIQFullEvents") 1431062SN/A .desc("Number of times the IQ has become full, causing a stall"); 1441062SN/A 1451062SN/A iewExecutedInsts 1461062SN/A .name(name() + ".iewExecutedInsts") 1471062SN/A .desc("Number of executed instructions"); 1481062SN/A 1491062SN/A iewExecLoadInsts 1501062SN/A .name(name() + ".iewExecLoadInsts") 1511062SN/A .desc("Number of load instructions executed"); 1521062SN/A 1531062SN/A iewExecStoreInsts 1541062SN/A .name(name() + ".iewExecStoreInsts") 1551062SN/A .desc("Number of store instructions executed"); 1561062SN/A 1571062SN/A iewExecSquashedInsts 1581062SN/A .name(name() + ".iewExecSquashedInsts") 1591062SN/A .desc("Number of squashed instructions skipped in execute"); 1601062SN/A 1611062SN/A memOrderViolationEvents 1621062SN/A .name(name() + ".memOrderViolationEvents") 1631062SN/A .desc("Number of memory order violations"); 1641062SN/A 1651062SN/A predictedTakenIncorrect 1661062SN/A .name(name() + ".predictedTakenIncorrect") 1671062SN/A .desc("Number of branches that were predicted taken incorrectly"); 1681062SN/A} 1691062SN/A 1701681SN/Atemplate<class Impl> 1711060SN/Avoid 1721681SN/ASimpleIEW<Impl>::setCPU(FullCPU *cpu_ptr) 1731060SN/A{ 1741060SN/A DPRINTF(IEW, "IEW: Setting CPU pointer.\n"); 1751060SN/A cpu = cpu_ptr; 1761060SN/A 1771060SN/A instQueue.setCPU(cpu_ptr); 1781061SN/A ldstQueue.setCPU(cpu_ptr); 1791060SN/A} 1801060SN/A 1811681SN/Atemplate<class Impl> 1821060SN/Avoid 1831681SN/ASimpleIEW<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) 1841060SN/A{ 1851060SN/A DPRINTF(IEW, "IEW: Setting time buffer pointer.\n"); 1861060SN/A timeBuffer = tb_ptr; 1871060SN/A 1881060SN/A // Setup wire to read information from time buffer, from commit. 1891060SN/A fromCommit = timeBuffer->getWire(-commitToIEWDelay); 1901060SN/A 1911060SN/A // Setup wire to write information back to previous stages. 1921060SN/A toRename = timeBuffer->getWire(0); 1931060SN/A 1941060SN/A // Instruction queue also needs main time buffer. 1951060SN/A instQueue.setTimeBuffer(tb_ptr); 1961060SN/A} 1971060SN/A 1981681SN/Atemplate<class Impl> 1991060SN/Avoid 2001681SN/ASimpleIEW<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr) 2011060SN/A{ 2021060SN/A DPRINTF(IEW, "IEW: Setting rename queue pointer.\n"); 2031060SN/A renameQueue = rq_ptr; 2041060SN/A 2051060SN/A // Setup wire to read information from rename queue. 2061060SN/A fromRename = renameQueue->getWire(-renameToIEWDelay); 2071060SN/A} 2081060SN/A 2091681SN/Atemplate<class Impl> 2101060SN/Avoid 2111681SN/ASimpleIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr) 2121060SN/A{ 2131060SN/A DPRINTF(IEW, "IEW: Setting IEW queue pointer.\n"); 2141060SN/A iewQueue = iq_ptr; 2151060SN/A 2161060SN/A // Setup wire to write instructions to commit. 2171060SN/A toCommit = iewQueue->getWire(0); 2181060SN/A} 2191060SN/A 2201681SN/Atemplate<class Impl> 2211060SN/Avoid 2221681SN/ASimpleIEW<Impl>::setRenameMap(RenameMap *rm_ptr) 2231060SN/A{ 2241060SN/A DPRINTF(IEW, "IEW: Setting rename map pointer.\n"); 2251060SN/A renameMap = rm_ptr; 2261060SN/A} 2271060SN/A 2281681SN/Atemplate<class Impl> 2291060SN/Avoid 2301681SN/ASimpleIEW<Impl>::squash() 2311060SN/A{ 2321681SN/A DPRINTF(IEW, "IEW: Squashing all instructions.\n"); 2331681SN/A _status = Squashing; 2341681SN/A 2351681SN/A // Tell the IQ to start squashing. 2361681SN/A instQueue.squash(); 2371681SN/A 2381681SN/A // Tell the LDSTQ to start squashing. 2391681SN/A ldstQueue.squash(fromCommit->commitInfo.doneSeqNum); 2401060SN/A} 2411060SN/A 2421681SN/Atemplate<class Impl> 2431060SN/Avoid 2441681SN/ASimpleIEW<Impl>::squashDueToBranch(DynInstPtr &inst) 2451681SN/A{ 2461681SN/A DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n", 2471681SN/A inst->PC); 2481681SN/A // Perhaps leave the squashing up to the ROB stage to tell it when to 2491681SN/A // squash? 2501681SN/A _status = Squashing; 2511681SN/A 2521681SN/A // Tell rename to squash through the time buffer. 2531681SN/A toCommit->squash = true; 2541681SN/A // Also send PC update information back to prior stages. 2551681SN/A toCommit->squashedSeqNum = inst->seqNum; 2561681SN/A toCommit->mispredPC = inst->readPC(); 2571681SN/A toCommit->nextPC = inst->readNextPC(); 2581681SN/A toCommit->branchMispredict = true; 2591681SN/A // Prediction was incorrect, so send back inverse. 2601681SN/A toCommit->branchTaken = inst->readNextPC() != 2612107SN/A (inst->readPC() + sizeof(TheISA::MachInst)); 2621681SN/A} 2631681SN/A 2641681SN/Atemplate<class Impl> 2651681SN/Avoid 2661681SN/ASimpleIEW<Impl>::squashDueToMem(DynInstPtr &inst) 2671681SN/A{ 2681681SN/A DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n", 2691681SN/A inst->PC); 2701681SN/A // Perhaps leave the squashing up to the ROB stage to tell it when to 2711681SN/A // squash? 2721681SN/A _status = Squashing; 2731681SN/A 2741681SN/A // Tell rename to squash through the time buffer. 2751681SN/A toCommit->squash = true; 2761681SN/A // Also send PC update information back to prior stages. 2771681SN/A toCommit->squashedSeqNum = inst->seqNum; 2781681SN/A toCommit->nextPC = inst->readNextPC(); 2791681SN/A} 2801681SN/A 2811681SN/Atemplate<class Impl> 2821681SN/Avoid 2831681SN/ASimpleIEW<Impl>::block() 2841060SN/A{ 2851060SN/A DPRINTF(IEW, "IEW: Blocking.\n"); 2861060SN/A // Set the status to Blocked. 2871060SN/A _status = Blocked; 2881060SN/A 2891060SN/A // Add the current inputs to the skid buffer so they can be 2901060SN/A // reprocessed when this stage unblocks. 2911060SN/A skidBuffer.push(*fromRename); 2921060SN/A 2931060SN/A // Note that this stage only signals previous stages to stall when 2941060SN/A // it is the cause of the stall originates at this stage. Otherwise 2951060SN/A // the previous stages are expected to check all possible stall signals. 2961060SN/A} 2971060SN/A 2981681SN/Atemplate<class Impl> 2991060SN/Ainline void 3001681SN/ASimpleIEW<Impl>::unblock() 3011060SN/A{ 3021060SN/A // Check if there's information in the skid buffer. If there is, then 3031060SN/A // set status to unblocking, otherwise set it directly to running. 3041060SN/A DPRINTF(IEW, "IEW: Reading instructions out of the skid " 3051060SN/A "buffer.\n"); 3061060SN/A // Remove the now processed instructions from the skid buffer. 3071060SN/A skidBuffer.pop(); 3081060SN/A 3091060SN/A // If there's still information in the skid buffer, then 3101060SN/A // continue to tell previous stages to stall. They will be 3111060SN/A // able to restart once the skid buffer is empty. 3121060SN/A if (!skidBuffer.empty()) { 3131060SN/A toRename->iewInfo.stall = true; 3141060SN/A } else { 3151060SN/A DPRINTF(IEW, "IEW: Stage is done unblocking.\n"); 3161060SN/A _status = Running; 3171060SN/A } 3181060SN/A} 3191060SN/A 3201681SN/Atemplate<class Impl> 3211060SN/Avoid 3221681SN/ASimpleIEW<Impl>::wakeDependents(DynInstPtr &inst) 3231060SN/A{ 3241681SN/A instQueue.wakeDependents(inst); 3251060SN/A} 3261060SN/A 3271681SN/A 3281681SN/Atemplate<class Impl> 3291060SN/Avoid 3301681SN/ASimpleIEW<Impl>::instToCommit(DynInstPtr &inst) 3311060SN/A{ 3321060SN/A 3331062SN/A} 3341062SN/A 3351681SN/Atemplate <class Impl> 3361062SN/Avoid 3371681SN/ASimpleIEW<Impl>::dispatchInsts() 3381062SN/A{ 3391062SN/A //////////////////////////////////////// 3401062SN/A // DISPATCH/ISSUE stage 3411062SN/A //////////////////////////////////////// 3421062SN/A 3431062SN/A //Put into its own function? 3441062SN/A //Add instructions to IQ if there are any instructions there 3451062SN/A 3461062SN/A // Check if there are any instructions coming from rename, and we're. 3471062SN/A // not squashing. 3481062SN/A if (fromRename->size > 0) { 3491062SN/A int insts_to_add = fromRename->size; 3501062SN/A 3511062SN/A // Loop through the instructions, putting them in the instruction 3521062SN/A // queue. 3531062SN/A for (int inst_num = 0; inst_num < insts_to_add; ++inst_num) 3541062SN/A { 3551062SN/A DynInstPtr inst = fromRename->insts[inst_num]; 3561062SN/A 3571062SN/A // Make sure there's a valid instruction there. 3581062SN/A assert(inst); 3591062SN/A 3601062SN/A DPRINTF(IEW, "IEW: Issue: Adding PC %#x to IQ.\n", 3611062SN/A inst->readPC()); 3621062SN/A 3631062SN/A // Be sure to mark these instructions as ready so that the 3641062SN/A // commit stage can go ahead and execute them, and mark 3651062SN/A // them as issued so the IQ doesn't reprocess them. 3661062SN/A if (inst->isSquashed()) { 3671062SN/A ++iewDispSquashedInsts; 3681062SN/A continue; 3691062SN/A } else if (instQueue.isFull()) { 3701062SN/A DPRINTF(IEW, "IEW: Issue: IQ has become full.\n"); 3711062SN/A // Call function to start blocking. 3721062SN/A block(); 3731062SN/A // Tell previous stage to stall. 3741062SN/A toRename->iewInfo.stall = true; 3751062SN/A 3761062SN/A ++iewIQFullEvents; 3771062SN/A break; 3781062SN/A } else if (inst->isLoad()) { 3791062SN/A DPRINTF(IEW, "IEW: Issue: Memory instruction " 3801062SN/A "encountered, adding to LDSTQ.\n"); 3811062SN/A 3821062SN/A // Reserve a spot in the load store queue for this 3831062SN/A // memory access. 3841062SN/A ldstQueue.insertLoad(inst); 3851062SN/A 3861062SN/A ++iewDispLoadInsts; 3871062SN/A } else if (inst->isStore()) { 3881062SN/A ldstQueue.insertStore(inst); 3891062SN/A 3901062SN/A ++iewDispStoreInsts; 3911062SN/A } else if (inst->isNonSpeculative()) { 3921062SN/A DPRINTF(IEW, "IEW: Issue: Nonspeculative instruction " 3931062SN/A "encountered, skipping.\n"); 3941062SN/A 3951062SN/A // Same hack as with stores. 3961062SN/A inst->setCanCommit(); 3971062SN/A 3981062SN/A // Specificall insert it as nonspeculative. 3991062SN/A instQueue.insertNonSpec(inst); 4001062SN/A 4011062SN/A ++iewDispNonSpecInsts; 4021062SN/A 4031062SN/A continue; 4041062SN/A } else if (inst->isNop()) { 4051062SN/A DPRINTF(IEW, "IEW: Issue: Nop instruction encountered " 4061062SN/A ", skipping.\n"); 4071062SN/A 4081062SN/A inst->setIssued(); 4091062SN/A inst->setExecuted(); 4101062SN/A inst->setCanCommit(); 4111062SN/A 4121062SN/A instQueue.advanceTail(inst); 4131062SN/A 4141062SN/A continue; 4151062SN/A } else if (inst->isExecuted()) { 4161063SN/A assert(0 && "Instruction shouldn't be executed.\n"); 4171062SN/A DPRINTF(IEW, "IEW: Issue: Executed branch encountered, " 4181062SN/A "skipping.\n"); 4191062SN/A 4201062SN/A inst->setIssued(); 4211062SN/A inst->setCanCommit(); 4221062SN/A 4231062SN/A instQueue.advanceTail(inst); 4241062SN/A 4251062SN/A continue; 4261062SN/A } 4271062SN/A 4281062SN/A // If the instruction queue is not full, then add the 4291062SN/A // instruction. 4301062SN/A instQueue.insert(fromRename->insts[inst_num]); 4311062SN/A 4321062SN/A ++iewDispatchedInsts; 4331062SN/A } 4341062SN/A } 4351062SN/A} 4361062SN/A 4371681SN/Atemplate <class Impl> 4381062SN/Avoid 4391681SN/ASimpleIEW<Impl>::executeInsts() 4401062SN/A{ 4411062SN/A //////////////////////////////////////// 4421062SN/A //EXECUTE/WRITEBACK stage 4431062SN/A //////////////////////////////////////// 4441062SN/A 4451062SN/A //Put into its own function? 4461062SN/A //Similarly should probably have separate execution for int vs FP. 4471062SN/A // Above comment is handled by the issue queue only issuing a valid 4481062SN/A // mix of int/fp instructions. 4491062SN/A //Actually okay to just have one execution, buuuuuut will need 4501062SN/A //somewhere that defines the execution latency of all instructions. 4511062SN/A // @todo: Move to the FU pool used in the current full cpu. 4521062SN/A 4531062SN/A int fu_usage = 0; 4541062SN/A bool fetch_redirect = false; 4551681SN/A int inst_slot = 0; 4561681SN/A int time_slot = 0; 4571062SN/A 4581062SN/A // Execute/writeback any instructions that are available. 4591062SN/A for (int inst_num = 0; 4601062SN/A fu_usage < executeWidth && /* Haven't exceeded available FU's. */ 4611062SN/A inst_num < issueWidth && 4621062SN/A fromIssue->insts[inst_num]; 4631062SN/A ++inst_num) { 4641062SN/A 4651062SN/A DPRINTF(IEW, "IEW: Execute: Executing instructions from IQ.\n"); 4661062SN/A 4671062SN/A // Get instruction from issue's queue. 4681062SN/A DynInstPtr inst = fromIssue->insts[inst_num]; 4691062SN/A 4701062SN/A DPRINTF(IEW, "IEW: Execute: Processing PC %#x.\n", inst->readPC()); 4711062SN/A 4721062SN/A // Check if the instruction is squashed; if so then skip it 4731062SN/A // and don't count it towards the FU usage. 4741062SN/A if (inst->isSquashed()) { 4751062SN/A DPRINTF(IEW, "IEW: Execute: Instruction was squashed.\n"); 4761062SN/A 4771062SN/A // Consider this instruction executed so that commit can go 4781062SN/A // ahead and retire the instruction. 4791062SN/A inst->setExecuted(); 4801062SN/A 4811062SN/A toCommit->insts[inst_num] = inst; 4821062SN/A 4831062SN/A ++iewExecSquashedInsts; 4841062SN/A 4851062SN/A continue; 4861062SN/A } 4871062SN/A 4881062SN/A inst->setExecuted(); 4891062SN/A 4901062SN/A // If an instruction is executed, then count it towards FU usage. 4911062SN/A ++fu_usage; 4921062SN/A 4931062SN/A // Execute instruction. 4941062SN/A // Note that if the instruction faults, it will be handled 4951062SN/A // at the commit stage. 4961062SN/A if (inst->isMemRef()) { 4971062SN/A DPRINTF(IEW, "IEW: Execute: Calculating address for memory " 4981062SN/A "reference.\n"); 4991062SN/A 5001062SN/A // Tell the LDSTQ to execute this instruction (if it is a load). 5011062SN/A if (inst->isLoad()) { 5021062SN/A ldstQueue.executeLoad(inst); 5031062SN/A 5041062SN/A ++iewExecLoadInsts; 5051062SN/A } else if (inst->isStore()) { 5061681SN/A ldstQueue.executeStore(inst); 5071062SN/A 5081062SN/A ++iewExecStoreInsts; 5091062SN/A } else { 5101062SN/A panic("IEW: Unexpected memory type!\n"); 5111062SN/A } 5121062SN/A 5131062SN/A } else { 5141062SN/A inst->execute(); 5151062SN/A 5161062SN/A ++iewExecutedInsts; 5171062SN/A } 5181062SN/A 5191062SN/A // First check the time slot that this instruction will write 5201062SN/A // to. If there are free write ports at the time, then go ahead 5211062SN/A // and write the instruction to that time. If there are not, 5221062SN/A // keep looking back to see where's the first time there's a 5231062SN/A // free slot. What happens if you run out of free spaces? 5241062SN/A // For now naively assume that all instructions take one cycle. 5251062SN/A // Otherwise would have to look into the time buffer based on the 5261062SN/A // latency of the instruction. 5271681SN/A (*iewQueue)[time_slot].insts[inst_slot]; 5281681SN/A while ((*iewQueue)[time_slot].insts[inst_slot]) { 5291681SN/A if (inst_slot < issueWidth) { 5301681SN/A ++inst_slot; 5311681SN/A } else { 5321681SN/A ++time_slot; 5331681SN/A inst_slot = 0; 5341681SN/A } 5351681SN/A 5361681SN/A assert(time_slot < 5); 5371681SN/A } 5381681SN/A 5391681SN/A // May actually have to work this out, especially with loads and stores 5401062SN/A 5411062SN/A // Add finished instruction to queue to commit. 5421681SN/A (*iewQueue)[time_slot].insts[inst_slot] = inst; 5431681SN/A (*iewQueue)[time_slot].size++; 5441062SN/A 5451062SN/A // Check if branch was correct. This check happens after the 5461062SN/A // instruction is added to the queue because even if the branch 5471062SN/A // is mispredicted, the branch instruction itself is still valid. 5481062SN/A // Only handle this if there hasn't already been something that 5491062SN/A // redirects fetch in this group of instructions. 5501062SN/A if (!fetch_redirect) { 5511062SN/A if (inst->mispredicted()) { 5521062SN/A fetch_redirect = true; 5531062SN/A 5541062SN/A DPRINTF(IEW, "IEW: Execute: Branch mispredict detected.\n"); 5551062SN/A DPRINTF(IEW, "IEW: Execute: Redirecting fetch to PC: %#x.\n", 5561062SN/A inst->nextPC); 5571062SN/A 5581062SN/A // If incorrect, then signal the ROB that it must be squashed. 5591062SN/A squashDueToBranch(inst); 5601062SN/A 5611062SN/A if (inst->predTaken()) { 5621062SN/A predictedTakenIncorrect++; 5631062SN/A } 5641062SN/A } else if (ldstQueue.violation()) { 5651062SN/A fetch_redirect = true; 5661062SN/A 5671062SN/A // Get the DynInst that caused the violation. 5681062SN/A DynInstPtr violator = ldstQueue.getMemDepViolator(); 5691062SN/A 5701062SN/A DPRINTF(IEW, "IEW: LDSTQ detected a violation. Violator PC: " 5711062SN/A "%#x, inst PC: %#x. Addr is: %#x.\n", 5721062SN/A violator->readPC(), inst->readPC(), inst->physEffAddr); 5731062SN/A 5741062SN/A // Tell the instruction queue that a violation has occured. 5751062SN/A instQueue.violation(inst, violator); 5761062SN/A 5771062SN/A // Squash. 5781062SN/A squashDueToMem(inst); 5791062SN/A 5801062SN/A ++memOrderViolationEvents; 5811062SN/A } 5821062SN/A } 5831062SN/A } 5841060SN/A} 5851060SN/A 5861681SN/Atemplate<class Impl> 5871060SN/Avoid 5881681SN/ASimpleIEW<Impl>::tick() 5891060SN/A{ 5901060SN/A // Considering putting all the state-determining stuff in this section. 5911060SN/A 5921060SN/A // Try to fill up issue queue with as many instructions as bandwidth 5931060SN/A // allows. 5941060SN/A // Decode should try to execute as many instructions as its bandwidth 5951060SN/A // will allow, as long as it is not currently blocked. 5961060SN/A 5971060SN/A // Check if the stage is in a running status. 5981060SN/A if (_status != Blocked && _status != Squashing) { 5991060SN/A DPRINTF(IEW, "IEW: Status is not blocked, attempting to run " 6001060SN/A "stage.\n"); 6011060SN/A iew(); 6021060SN/A 6031060SN/A // If it's currently unblocking, check to see if it should switch 6041060SN/A // to running. 6051060SN/A if (_status == Unblocking) { 6061060SN/A unblock(); 6071062SN/A 6081062SN/A ++iewUnblockCycles; 6091060SN/A } 6101060SN/A } else if (_status == Squashing) { 6111060SN/A 6121060SN/A DPRINTF(IEW, "IEW: Still squashing.\n"); 6131060SN/A 6141060SN/A // Check if stage should remain squashing. Stop squashing if the 6151060SN/A // squash signal clears. 6161060SN/A if (!fromCommit->commitInfo.squash && 6171060SN/A !fromCommit->commitInfo.robSquashing) { 6181060SN/A DPRINTF(IEW, "IEW: Done squashing, changing status to " 6191060SN/A "running.\n"); 6201060SN/A 6211060SN/A _status = Running; 6221060SN/A instQueue.stopSquash(); 6231060SN/A } else { 6241060SN/A instQueue.doSquash(); 6251060SN/A } 6261060SN/A 6271062SN/A ++iewSquashCycles; 6281060SN/A } else if (_status == Blocked) { 6291060SN/A // Continue to tell previous stage to stall. 6301060SN/A toRename->iewInfo.stall = true; 6311060SN/A 6321060SN/A // Check if possible stall conditions have cleared. 6331060SN/A if (!fromCommit->commitInfo.stall && 6341060SN/A !instQueue.isFull()) { 6351060SN/A DPRINTF(IEW, "IEW: Stall signals cleared, going to unblock.\n"); 6361060SN/A _status = Unblocking; 6371060SN/A } 6381060SN/A 6391060SN/A // If there's still instructions coming from rename, continue to 6401060SN/A // put them on the skid buffer. 6411062SN/A if (fromRename->size == 0) { 6421060SN/A block(); 6431060SN/A } 6441060SN/A 6451060SN/A if (fromCommit->commitInfo.squash || 6461060SN/A fromCommit->commitInfo.robSquashing) { 6471060SN/A squash(); 6481060SN/A } 6491062SN/A 6501062SN/A ++iewBlockCycles; 6511060SN/A } 6521060SN/A 6531060SN/A // @todo: Maybe put these at the beginning, so if it's idle it can 6541060SN/A // return early. 6551060SN/A // Write back number of free IQ entries here. 6561060SN/A toRename->iewInfo.freeIQEntries = instQueue.numFreeEntries(); 6571060SN/A 6581681SN/A ldstQueue.writebackStores(); 6591681SN/A 6601061SN/A // Check the committed load/store signals to see if there's a load 6611061SN/A // or store to commit. Also check if it's being told to execute a 6621061SN/A // nonspeculative instruction. 6631681SN/A // This is pretty inefficient... 6641681SN/A if (!fromCommit->commitInfo.squash && 6651681SN/A !fromCommit->commitInfo.robSquashing) { 6661061SN/A ldstQueue.commitStores(fromCommit->commitInfo.doneSeqNum); 6671061SN/A ldstQueue.commitLoads(fromCommit->commitInfo.doneSeqNum); 6681061SN/A } 6691061SN/A 6701061SN/A if (fromCommit->commitInfo.nonSpecSeqNum != 0) { 6711061SN/A instQueue.scheduleNonSpec(fromCommit->commitInfo.nonSpecSeqNum); 6721061SN/A } 6731061SN/A 6741060SN/A DPRINTF(IEW, "IEW: IQ has %i free entries.\n", 6751060SN/A instQueue.numFreeEntries()); 6761060SN/A} 6771060SN/A 6781681SN/Atemplate<class Impl> 6791060SN/Avoid 6801681SN/ASimpleIEW<Impl>::iew() 6811060SN/A{ 6821060SN/A // Might want to put all state checks in the tick() function. 6831060SN/A // Check if being told to stall from commit. 6841060SN/A if (fromCommit->commitInfo.stall) { 6851060SN/A block(); 6861060SN/A return; 6871060SN/A } else if (fromCommit->commitInfo.squash || 6881060SN/A fromCommit->commitInfo.robSquashing) { 6891060SN/A // Also check if commit is telling this stage to squash. 6901060SN/A squash(); 6911060SN/A return; 6921060SN/A } 6931060SN/A 6941062SN/A dispatchInsts(); 6951060SN/A 6961060SN/A // Have the instruction queue try to schedule any ready instructions. 6971060SN/A instQueue.scheduleReadyInsts(); 6981060SN/A 6991062SN/A executeInsts(); 7001060SN/A 7011060SN/A // Loop through the head of the time buffer and wake any dependents. 7021060SN/A // These instructions are about to write back. In the simple model 7031060SN/A // this loop can really happen within the previous loop, but when 7041060SN/A // instructions have actual latencies, this loop must be separate. 7051060SN/A // Also mark scoreboard that this instruction is finally complete. 7061060SN/A // Either have IEW have direct access to rename map, or have this as 7071060SN/A // part of backwards communication. 7081062SN/A for (int inst_num = 0; inst_num < issueWidth && 7091061SN/A toCommit->insts[inst_num]; inst_num++) 7101060SN/A { 7111061SN/A DynInstPtr inst = toCommit->insts[inst_num]; 7121060SN/A 7131060SN/A DPRINTF(IEW, "IEW: Sending instructions to commit, PC %#x.\n", 7141060SN/A inst->readPC()); 7151060SN/A 7161061SN/A if(!inst->isSquashed()) { 7171061SN/A instQueue.wakeDependents(inst); 7181060SN/A 7191061SN/A for (int i = 0; i < inst->numDestRegs(); i++) 7201061SN/A { 7211061SN/A renameMap->markAsReady(inst->renamedDestRegIdx(i)); 7221061SN/A } 7231060SN/A } 7241060SN/A } 7251060SN/A 7261060SN/A // Also should advance its own time buffers if the stage ran. 7271060SN/A // Not the best place for it, but this works (hopefully). 7281060SN/A issueToExecQueue.advance(); 7291060SN/A} 7301681SN/A 7311858SN/A#if !FULL_SYSTEM 7321681SN/Atemplate<class Impl> 7331681SN/Avoid 7341681SN/ASimpleIEW<Impl>::lsqWriteback() 7351681SN/A{ 7361681SN/A ldstQueue.writebackAllInsts(); 7371681SN/A} 7381681SN/A#endif 739