iew_impl.hh revision 1681
16313Sgblack@eecs.umich.edu// @todo: Fix the instantaneous communication among all the stages within 210844Sandreas.sandberg@arm.com// iew. There's a clear delay between issue and execute, yet backwards 37093Sgblack@eecs.umich.edu// communication happens simultaneously. Might not be that bad really... 47093Sgblack@eecs.umich.edu// it might skew stats a bit though. Issue would otherwise try to issue 57093Sgblack@eecs.umich.edu// instructions that would never be executed if there were a delay; without 67093Sgblack@eecs.umich.edu// it issue will simply squash. Make this stage block properly. 77093Sgblack@eecs.umich.edu// Update the statuses for each stage. 87093Sgblack@eecs.umich.edu// Actually read instructions out of the skid buffer. 97093Sgblack@eecs.umich.edu 107093Sgblack@eecs.umich.edu#include <queue> 117093Sgblack@eecs.umich.edu 127093Sgblack@eecs.umich.edu#include "base/timebuf.hh" 137093Sgblack@eecs.umich.edu#include "cpu/beta_cpu/iew.hh" 146313Sgblack@eecs.umich.edu 156313Sgblack@eecs.umich.edutemplate<class Impl> 166313Sgblack@eecs.umich.eduSimpleIEW<Impl>::WritebackEvent::WritebackEvent(DynInstPtr &_inst, 176313Sgblack@eecs.umich.edu SimpleIEW<Impl> *_iew) 186313Sgblack@eecs.umich.edu : Event(&mainEventQueue, CPU_Tick_Pri), inst(_inst), iewStage(_iew) 196313Sgblack@eecs.umich.edu{ 206313Sgblack@eecs.umich.edu this->setFlags(Event::AutoDelete); 216313Sgblack@eecs.umich.edu} 226313Sgblack@eecs.umich.edu 236313Sgblack@eecs.umich.edutemplate<class Impl> 246313Sgblack@eecs.umich.eduvoid 256313Sgblack@eecs.umich.eduSimpleIEW<Impl>::WritebackEvent::process() 266313Sgblack@eecs.umich.edu{ 276313Sgblack@eecs.umich.edu DPRINTF(IEW, "IEW: WRITEBACK EVENT!!!!\n"); 286313Sgblack@eecs.umich.edu 296313Sgblack@eecs.umich.edu // Need to insert instruction into queue to commit 306313Sgblack@eecs.umich.edu iewStage->instToCommit(inst); 316313Sgblack@eecs.umich.edu // Need to execute second half of the instruction, do actual writing to 326313Sgblack@eecs.umich.edu // registers and such 336313Sgblack@eecs.umich.edu inst->execute(); 346313Sgblack@eecs.umich.edu} 356313Sgblack@eecs.umich.edu 366313Sgblack@eecs.umich.edutemplate<class Impl> 376313Sgblack@eecs.umich.educonst char * 386313Sgblack@eecs.umich.eduSimpleIEW<Impl>::WritebackEvent::description() 396313Sgblack@eecs.umich.edu{ 406313Sgblack@eecs.umich.edu return "LSQ writeback event"; 416313Sgblack@eecs.umich.edu} 426313Sgblack@eecs.umich.edu 436313Sgblack@eecs.umich.edutemplate<class Impl> 447404SAli.Saidi@ARM.comSimpleIEW<Impl>::SimpleIEW(Params ¶ms) 456313Sgblack@eecs.umich.edu : // Just make this time buffer really big for now 4610461SAndreas.Sandberg@ARM.com issueToExecQueue(5, 5), 476333Sgblack@eecs.umich.edu instQueue(params), 4810037SARM gem5 Developers ldstQueue(params), 497404SAli.Saidi@ARM.com commitToIEWDelay(params.commitToIEWDelay), 506313Sgblack@eecs.umich.edu renameToIEWDelay(params.renameToIEWDelay), 518232Snate@binkert.org issueToExecuteDelay(params.issueToExecuteDelay), 529384SAndreas.Sandberg@arm.com issueReadWidth(params.issueWidth), 5311165SRekai.GonzalezAlberquilla@arm.com issueWidth(params.issueWidth), 546313Sgblack@eecs.umich.edu executeWidth(params.executeWidth) 559384SAndreas.Sandberg@arm.com{ 5610461SAndreas.Sandberg@ARM.com DPRINTF(IEW, "IEW: executeIntWidth: %i.\n", params.executeIntWidth); 576333Sgblack@eecs.umich.edu _status = Idle; 586313Sgblack@eecs.umich.edu _issueStatus = Idle; 596313Sgblack@eecs.umich.edu _exeStatus = Idle; 606313Sgblack@eecs.umich.edu _wbStatus = Idle; 616313Sgblack@eecs.umich.edu 626313Sgblack@eecs.umich.edu // Setup wire to read instructions coming from issue. 6310037SARM gem5 Developers fromIssue = issueToExecQueue.getWire(-issueToExecuteDelay); 6410037SARM gem5 Developers 6510037SARM gem5 Developers // Instruction queue needs the queue between issue and execute. 6610037SARM gem5 Developers instQueue.setIssueToExecuteQueue(&issueToExecQueue); 6710037SARM gem5 Developers 6810037SARM gem5 Developers ldstQueue.setIEW(this); 6910037SARM gem5 Developers} 7010037SARM gem5 Developers 7110037SARM gem5 Developerstemplate <class Impl> 7210037SARM gem5 Developersvoid 7310037SARM gem5 DevelopersSimpleIEW<Impl>::regStats() 7410037SARM gem5 Developers{ 7510037SARM gem5 Developers instQueue.regStats(); 7610037SARM gem5 Developers 7710037SARM gem5 Developers iewIdleCycles 7810037SARM gem5 Developers .name(name() + ".iewIdleCycles") 7910037SARM gem5 Developers .desc("Number of cycles IEW is idle"); 8010037SARM gem5 Developers 8110037SARM gem5 Developers iewSquashCycles 8210037SARM gem5 Developers .name(name() + ".iewSquashCycles") 8310037SARM gem5 Developers .desc("Number of cycles IEW is squashing"); 8410037SARM gem5 Developers 8510037SARM gem5 Developers iewBlockCycles 8610037SARM gem5 Developers .name(name() + ".iewBlockCycles") 8710037SARM gem5 Developers .desc("Number of cycles IEW is blocking"); 8810037SARM gem5 Developers 8910037SARM gem5 Developers iewUnblockCycles 9010037SARM gem5 Developers .name(name() + ".iewUnblockCycles") 9110037SARM gem5 Developers .desc("Number of cycles IEW is unblocking"); 9210037SARM gem5 Developers 9310037SARM gem5 Developers// iewWBInsts; 9410037SARM gem5 Developers 9510037SARM gem5 Developers iewDispatchedInsts 9610037SARM gem5 Developers .name(name() + ".iewDispatchedInsts") 9710037SARM gem5 Developers .desc("Number of instructions dispatched to IQ"); 9810037SARM gem5 Developers 9910037SARM gem5 Developers iewDispSquashedInsts 10010037SARM gem5 Developers .name(name() + ".iewDispSquashedInsts") 10110037SARM gem5 Developers .desc("Number of squashed instructions skipped by dispatch"); 10210037SARM gem5 Developers 10310037SARM gem5 Developers iewDispLoadInsts 10410037SARM gem5 Developers .name(name() + ".iewDispLoadInsts") 10510037SARM gem5 Developers .desc("Number of dispatched load instructions"); 10610037SARM gem5 Developers 10710037SARM gem5 Developers iewDispStoreInsts 10810037SARM gem5 Developers .name(name() + ".iewDispStoreInsts") 10910037SARM gem5 Developers .desc("Number of dispatched store instructions"); 11010037SARM gem5 Developers 11110037SARM gem5 Developers iewDispNonSpecInsts 11210037SARM gem5 Developers .name(name() + ".iewDispNonSpecInsts") 11310037SARM gem5 Developers .desc("Number of dispatched non-speculative instructions"); 11410037SARM gem5 Developers 11510037SARM gem5 Developers iewIQFullEvents 11610037SARM gem5 Developers .name(name() + ".iewIQFullEvents") 11710037SARM gem5 Developers .desc("Number of times the IQ has become full, causing a stall"); 11810037SARM gem5 Developers 11910037SARM gem5 Developers iewExecutedInsts 12010037SARM gem5 Developers .name(name() + ".iewExecutedInsts") 12110037SARM gem5 Developers .desc("Number of executed instructions"); 12210037SARM gem5 Developers 12310037SARM gem5 Developers iewExecLoadInsts 12410037SARM gem5 Developers .name(name() + ".iewExecLoadInsts") 12510037SARM gem5 Developers .desc("Number of load instructions executed"); 12610037SARM gem5 Developers 12710037SARM gem5 Developers iewExecStoreInsts 12810037SARM gem5 Developers .name(name() + ".iewExecStoreInsts") 12910037SARM gem5 Developers .desc("Number of store instructions executed"); 1309384SAndreas.Sandberg@arm.com 1316313Sgblack@eecs.umich.edu iewExecSquashedInsts 1326313Sgblack@eecs.umich.edu .name(name() + ".iewExecSquashedInsts") 13310037SARM gem5 Developers .desc("Number of squashed instructions skipped in execute"); 13410037SARM gem5 Developers 13510037SARM gem5 Developers memOrderViolationEvents 13611165SRekai.GonzalezAlberquilla@arm.com .name(name() + ".memOrderViolationEvents") 13711165SRekai.GonzalezAlberquilla@arm.com .desc("Number of memory order violations"); 13811165SRekai.GonzalezAlberquilla@arm.com 13910461SAndreas.Sandberg@ARM.com predictedTakenIncorrect 14010461SAndreas.Sandberg@ARM.com .name(name() + ".predictedTakenIncorrect") 14110461SAndreas.Sandberg@ARM.com .desc("Number of branches that were predicted taken incorrectly"); 14210461SAndreas.Sandberg@ARM.com} 14310461SAndreas.Sandberg@ARM.com 14410461SAndreas.Sandberg@ARM.comtemplate<class Impl> 14510844Sandreas.sandberg@arm.comvoid 14610844Sandreas.sandberg@arm.comSimpleIEW<Impl>::setCPU(FullCPU *cpu_ptr) 14710844Sandreas.sandberg@arm.com{ 14810037SARM gem5 Developers DPRINTF(IEW, "IEW: Setting CPU pointer.\n"); 14910037SARM gem5 Developers cpu = cpu_ptr; 15010037SARM gem5 Developers 15110037SARM gem5 Developers instQueue.setCPU(cpu_ptr); 15210037SARM gem5 Developers ldstQueue.setCPU(cpu_ptr); 15310037SARM gem5 Developers} 15410037SARM gem5 Developers 15510037SARM gem5 Developerstemplate<class Impl> 15610037SARM gem5 Developersvoid 15710037SARM gem5 DevelopersSimpleIEW<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) 15810037SARM gem5 Developers{ 15910037SARM gem5 Developers DPRINTF(IEW, "IEW: Setting time buffer pointer.\n"); 16010037SARM gem5 Developers timeBuffer = tb_ptr; 16110037SARM gem5 Developers 16210037SARM gem5 Developers // Setup wire to read information from time buffer, from commit. 16310037SARM gem5 Developers fromCommit = timeBuffer->getWire(-commitToIEWDelay); 16410037SARM gem5 Developers 16510037SARM gem5 Developers // Setup wire to write information back to previous stages. 16610037SARM gem5 Developers toRename = timeBuffer->getWire(0); 16710037SARM gem5 Developers 16810037SARM gem5 Developers // Instruction queue also needs main time buffer. 16910037SARM gem5 Developers instQueue.setTimeBuffer(tb_ptr); 17010037SARM gem5 Developers} 17110037SARM gem5 Developers 17210037SARM gem5 Developerstemplate<class Impl> 1736333Sgblack@eecs.umich.eduvoid 1746718Sgblack@eecs.umich.eduSimpleIEW<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr) 1756718Sgblack@eecs.umich.edu{ 1766718Sgblack@eecs.umich.edu DPRINTF(IEW, "IEW: Setting rename queue pointer.\n"); 1776718Sgblack@eecs.umich.edu renameQueue = rq_ptr; 1786718Sgblack@eecs.umich.edu 17910037SARM gem5 Developers // Setup wire to read information from rename queue. 18010037SARM gem5 Developers fromRename = renameQueue->getWire(-renameToIEWDelay); 18110037SARM gem5 Developers} 18210037SARM gem5 Developers 18310037SARM gem5 Developerstemplate<class Impl> 18410037SARM gem5 Developersvoid 18510037SARM gem5 DevelopersSimpleIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr) 18610037SARM gem5 Developers{ 18710037SARM gem5 Developers DPRINTF(IEW, "IEW: Setting IEW queue pointer.\n"); 18810037SARM gem5 Developers iewQueue = iq_ptr; 18910037SARM gem5 Developers 19010037SARM gem5 Developers // Setup wire to write instructions to commit. 19110037SARM gem5 Developers toCommit = iewQueue->getWire(0); 19210037SARM gem5 Developers} 19310037SARM gem5 Developers 19410037SARM gem5 Developerstemplate<class Impl> 19510037SARM gem5 Developersvoid 19610037SARM gem5 DevelopersSimpleIEW<Impl>::setRenameMap(RenameMap *rm_ptr) 19710037SARM gem5 Developers{ 19810037SARM gem5 Developers DPRINTF(IEW, "IEW: Setting rename map pointer.\n"); 19910037SARM gem5 Developers renameMap = rm_ptr; 20010037SARM gem5 Developers} 20110037SARM gem5 Developers 20210037SARM gem5 Developerstemplate<class Impl> 20310037SARM gem5 Developersvoid 20410037SARM gem5 DevelopersSimpleIEW<Impl>::squash() 20510037SARM gem5 Developers{ 20610037SARM gem5 Developers DPRINTF(IEW, "IEW: Squashing all instructions.\n"); 20710037SARM gem5 Developers _status = Squashing; 20810037SARM gem5 Developers 20910037SARM gem5 Developers // Tell the IQ to start squashing. 21010037SARM gem5 Developers instQueue.squash(); 2116718Sgblack@eecs.umich.edu 2126718Sgblack@eecs.umich.edu // Tell the LDSTQ to start squashing. 2136313Sgblack@eecs.umich.edu ldstQueue.squash(fromCommit->commitInfo.doneSeqNum); 21410844Sandreas.sandberg@arm.com} 21510037SARM gem5 Developers 21610037SARM gem5 Developerstemplate<class Impl> 21710037SARM gem5 Developersvoid 21810037SARM gem5 DevelopersSimpleIEW<Impl>::squashDueToBranch(DynInstPtr &inst) 21910037SARM gem5 Developers{ 22010037SARM gem5 Developers DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n", 22110037SARM gem5 Developers inst->PC); 22210037SARM gem5 Developers // Perhaps leave the squashing up to the ROB stage to tell it when to 22310037SARM gem5 Developers // squash? 22410037SARM gem5 Developers _status = Squashing; 22510037SARM gem5 Developers 22610037SARM gem5 Developers // Tell rename to squash through the time buffer. 22710037SARM gem5 Developers toCommit->squash = true; 22810709SAndreas.Sandberg@ARM.com // Also send PC update information back to prior stages. 22910037SARM gem5 Developers toCommit->squashedSeqNum = inst->seqNum; 23010037SARM gem5 Developers toCommit->mispredPC = inst->readPC(); 23110037SARM gem5 Developers toCommit->nextPC = inst->readNextPC(); 23210037SARM gem5 Developers toCommit->branchMispredict = true; 23310037SARM gem5 Developers // Prediction was incorrect, so send back inverse. 23410037SARM gem5 Developers toCommit->branchTaken = inst->readNextPC() != 23510037SARM gem5 Developers (inst->readPC() + sizeof(MachInst)); 23610037SARM gem5 Developers} 23710037SARM gem5 Developers 2386313Sgblack@eecs.umich.edutemplate<class Impl> 2397427Sgblack@eecs.umich.eduvoid 24010037SARM gem5 DevelopersSimpleIEW<Impl>::squashDueToMem(DynInstPtr &inst) 2416313Sgblack@eecs.umich.edu{ 24210035Sandreas.hansson@arm.com DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n", 2437405SAli.Saidi@ARM.com inst->PC); 2447405SAli.Saidi@ARM.com // Perhaps leave the squashing up to the ROB stage to tell it when to 2457405SAli.Saidi@ARM.com // squash? 2466313Sgblack@eecs.umich.edu _status = Squashing; 2476313Sgblack@eecs.umich.edu 24810035Sandreas.hansson@arm.com // Tell rename to squash through the time buffer. 2496313Sgblack@eecs.umich.edu toCommit->squash = true; 2506718Sgblack@eecs.umich.edu // Also send PC update information back to prior stages. 2516718Sgblack@eecs.umich.edu toCommit->squashedSeqNum = inst->seqNum; 2526718Sgblack@eecs.umich.edu toCommit->nextPC = inst->readNextPC(); 2536726Sgblack@eecs.umich.edu} 2546726Sgblack@eecs.umich.edu 25510037SARM gem5 Developerstemplate<class Impl> 25610037SARM gem5 Developersvoid 25710037SARM gem5 DevelopersSimpleIEW<Impl>::block() 25810037SARM gem5 Developers{ 25910037SARM gem5 Developers DPRINTF(IEW, "IEW: Blocking.\n"); 26010037SARM gem5 Developers // Set the status to Blocked. 26110037SARM gem5 Developers _status = Blocked; 26210037SARM gem5 Developers 26310037SARM gem5 Developers // Add the current inputs to the skid buffer so they can be 26410037SARM gem5 Developers // reprocessed when this stage unblocks. 26510037SARM gem5 Developers skidBuffer.push(*fromRename); 26610037SARM gem5 Developers 26710037SARM gem5 Developers // Note that this stage only signals previous stages to stall when 26810037SARM gem5 Developers // it is the cause of the stall originates at this stage. Otherwise 26910037SARM gem5 Developers // the previous stages are expected to check all possible stall signals. 27010037SARM gem5 Developers} 27110037SARM gem5 Developers 27210037SARM gem5 Developerstemplate<class Impl> 27310037SARM gem5 Developersinline void 27410037SARM gem5 DevelopersSimpleIEW<Impl>::unblock() 2756718Sgblack@eecs.umich.edu{ 27610037SARM gem5 Developers // Check if there's information in the skid buffer. If there is, then 2776718Sgblack@eecs.umich.edu // set status to unblocking, otherwise set it directly to running. 2786313Sgblack@eecs.umich.edu DPRINTF(IEW, "IEW: Reading instructions out of the skid " 2796313Sgblack@eecs.umich.edu "buffer.\n"); 2806313Sgblack@eecs.umich.edu // Remove the now processed instructions from the skid buffer. 28110035Sandreas.hansson@arm.com skidBuffer.pop(); 2826313Sgblack@eecs.umich.edu 28310338SCurtis.Dunham@arm.com // If there's still information in the skid buffer, then 2846313Sgblack@eecs.umich.edu // continue to tell previous stages to stall. They will be 2856313Sgblack@eecs.umich.edu // able to restart once the skid buffer is empty. 2866313Sgblack@eecs.umich.edu if (!skidBuffer.empty()) { 2879920Syasuko.eckert@amd.com toRename->iewInfo.stall = true; 28810035Sandreas.hansson@arm.com } else { 2899920Syasuko.eckert@amd.com DPRINTF(IEW, "IEW: Stage is done unblocking.\n"); 29010338SCurtis.Dunham@arm.com _status = Running; 2919920Syasuko.eckert@amd.com } 2929920Syasuko.eckert@amd.com} 2939920Syasuko.eckert@amd.com 2947614Sminkyu.jeong@arm.comtemplate<class Impl> 29510035Sandreas.hansson@arm.comvoid 2967614Sminkyu.jeong@arm.comSimpleIEW<Impl>::wakeDependents(DynInstPtr &inst) 29710338SCurtis.Dunham@arm.com{ 29810037SARM gem5 Developers instQueue.wakeDependents(inst); 29910037SARM gem5 Developers} 3007614Sminkyu.jeong@arm.com 3017614Sminkyu.jeong@arm.com 3027614Sminkyu.jeong@arm.comtemplate<class Impl> 30310037SARM gem5 Developersvoid 30410037SARM gem5 DevelopersSimpleIEW<Impl>::instToCommit(DynInstPtr &inst) 30510037SARM gem5 Developers{ 30610037SARM gem5 Developers 30710037SARM gem5 Developers} 30810037SARM gem5 Developers 30910037SARM gem5 Developerstemplate <class Impl> 31010037SARM gem5 Developersvoid 31110037SARM gem5 DevelopersSimpleIEW<Impl>::dispatchInsts() 31210037SARM gem5 Developers{ 31310037SARM gem5 Developers //////////////////////////////////////// 31410037SARM gem5 Developers // DISPATCH/ISSUE stage 31510037SARM gem5 Developers //////////////////////////////////////// 31610037SARM gem5 Developers 31710037SARM gem5 Developers //Put into its own function? 31810037SARM gem5 Developers //Add instructions to IQ if there are any instructions there 3197614Sminkyu.jeong@arm.com 3207614Sminkyu.jeong@arm.com // Check if there are any instructions coming from rename, and we're. 32110037SARM gem5 Developers // not squashing. 3227614Sminkyu.jeong@arm.com if (fromRename->size > 0) { 3237614Sminkyu.jeong@arm.com int insts_to_add = fromRename->size; 32410037SARM gem5 Developers 3257614Sminkyu.jeong@arm.com // Loop through the instructions, putting them in the instruction 3267614Sminkyu.jeong@arm.com // queue. 32710037SARM gem5 Developers for (int inst_num = 0; inst_num < insts_to_add; ++inst_num) 3287614Sminkyu.jeong@arm.com { 3297614Sminkyu.jeong@arm.com DynInstPtr inst = fromRename->insts[inst_num]; 33010037SARM gem5 Developers 3317614Sminkyu.jeong@arm.com // Make sure there's a valid instruction there. 3327614Sminkyu.jeong@arm.com assert(inst); 33310037SARM gem5 Developers 3347614Sminkyu.jeong@arm.com DPRINTF(IEW, "IEW: Issue: Adding PC %#x to IQ.\n", 3357614Sminkyu.jeong@arm.com inst->readPC()); 33610037SARM gem5 Developers 33710037SARM gem5 Developers // Be sure to mark these instructions as ready so that the 33810037SARM gem5 Developers // commit stage can go ahead and execute them, and mark 33910037SARM gem5 Developers // them as issued so the IQ doesn't reprocess them. 3407614Sminkyu.jeong@arm.com if (inst->isSquashed()) { 3417614Sminkyu.jeong@arm.com ++iewDispSquashedInsts; 34210037SARM gem5 Developers continue; 3437614Sminkyu.jeong@arm.com } else if (instQueue.isFull()) { 3447614Sminkyu.jeong@arm.com DPRINTF(IEW, "IEW: Issue: IQ has become full.\n"); 3457614Sminkyu.jeong@arm.com // Call function to start blocking. 3467614Sminkyu.jeong@arm.com block(); 34710037SARM gem5 Developers // Tell previous stage to stall. 3487614Sminkyu.jeong@arm.com toRename->iewInfo.stall = true; 3497614Sminkyu.jeong@arm.com 35010037SARM gem5 Developers ++iewIQFullEvents; 35110037SARM gem5 Developers break; 35210037SARM gem5 Developers } else if (inst->isLoad()) { 35310037SARM gem5 Developers DPRINTF(IEW, "IEW: Issue: Memory instruction " 35410037SARM gem5 Developers "encountered, adding to LDSTQ.\n"); 35510037SARM gem5 Developers 35610037SARM gem5 Developers // Reserve a spot in the load store queue for this 35710037SARM gem5 Developers // memory access. 35810037SARM gem5 Developers ldstQueue.insertLoad(inst); 35910037SARM gem5 Developers 36010037SARM gem5 Developers ++iewDispLoadInsts; 36110037SARM gem5 Developers } else if (inst->isStore()) { 36210037SARM gem5 Developers ldstQueue.insertStore(inst); 36310037SARM gem5 Developers 36410037SARM gem5 Developers // A bit of a hack. Set that it can commit so that 36510037SARM gem5 Developers // the commit stage will try committing it, and then 36610037SARM gem5 Developers // once commit realizes it's a store it will send back 36710037SARM gem5 Developers // a signal to this stage to issue and execute that 36810037SARM gem5 Developers // store. Change to be a bit that says the instruction 36910037SARM gem5 Developers // has extra work to do at commit. 37010037SARM gem5 Developers// inst->setCanCommit(); 37110037SARM gem5 Developers 37210037SARM gem5 Developers// instQueue.insertNonSpec(inst); 37310037SARM gem5 Developers 37410037SARM gem5 Developers ++iewDispStoreInsts; 37510037SARM gem5 Developers// ++iewDispNonSpecInsts; 37610037SARM gem5 Developers 37710037SARM gem5 Developers// continue; 37810037SARM gem5 Developers } else if (inst->isNonSpeculative()) { 37910037SARM gem5 Developers DPRINTF(IEW, "IEW: Issue: Nonspeculative instruction " 38010037SARM gem5 Developers "encountered, skipping.\n"); 38110037SARM gem5 Developers 38210037SARM gem5 Developers // Same hack as with stores. 38310037SARM gem5 Developers inst->setCanCommit(); 38410037SARM gem5 Developers 38510037SARM gem5 Developers // Specificall insert it as nonspeculative. 38610037SARM gem5 Developers instQueue.insertNonSpec(inst); 38710037SARM gem5 Developers 38810037SARM gem5 Developers ++iewDispNonSpecInsts; 38910037SARM gem5 Developers 39010037SARM gem5 Developers continue; 39110037SARM gem5 Developers } else if (inst->isNop()) { 39210037SARM gem5 Developers DPRINTF(IEW, "IEW: Issue: Nop instruction encountered " 39310037SARM gem5 Developers ", skipping.\n"); 39410037SARM gem5 Developers 39510037SARM gem5 Developers inst->setIssued(); 39610037SARM gem5 Developers inst->setExecuted(); 39710037SARM gem5 Developers inst->setCanCommit(); 39810037SARM gem5 Developers 39910037SARM gem5 Developers instQueue.advanceTail(inst); 40010037SARM gem5 Developers 40110037SARM gem5 Developers continue; 40210037SARM gem5 Developers } else if (inst->isExecuted()) { 40310037SARM gem5 Developers assert(0 && "Instruction shouldn't be executed.\n"); 40410037SARM gem5 Developers DPRINTF(IEW, "IEW: Issue: Executed branch encountered, " 4057614Sminkyu.jeong@arm.com "skipping.\n"); 40610037SARM gem5 Developers 4077614Sminkyu.jeong@arm.com// assert(inst->isDirectCtrl()); 4087614Sminkyu.jeong@arm.com 40910905Sandreas.sandberg@arm.com inst->setIssued(); 4107733SAli.Saidi@ARM.com inst->setCanCommit(); 4117733SAli.Saidi@ARM.com 4127733SAli.Saidi@ARM.com instQueue.advanceTail(inst); 41310037SARM gem5 Developers 41410037SARM gem5 Developers continue; 41510037SARM gem5 Developers } 41610037SARM gem5 Developers 41710037SARM gem5 Developers // If the instruction queue is not full, then add the 41810037SARM gem5 Developers // instruction. 4197733SAli.Saidi@ARM.com instQueue.insert(fromRename->insts[inst_num]); 42010905Sandreas.sandberg@arm.com 4217733SAli.Saidi@ARM.com ++iewDispatchedInsts; 4227733SAli.Saidi@ARM.com } 4237733SAli.Saidi@ARM.com } 4247733SAli.Saidi@ARM.com} 4257733SAli.Saidi@ARM.com 42610037SARM gem5 Developerstemplate <class Impl> 42710037SARM gem5 Developersvoid 42810037SARM gem5 DevelopersSimpleIEW<Impl>::executeInsts() 42910037SARM gem5 Developers{ 43010037SARM gem5 Developers //////////////////////////////////////// 43110037SARM gem5 Developers //EXECUTE/WRITEBACK stage 4327733SAli.Saidi@ARM.com //////////////////////////////////////// 4336313Sgblack@eecs.umich.edu 4349461Snilay@cs.wisc.edu //Put into its own function? 4359461Snilay@cs.wisc.edu //Similarly should probably have separate execution for int vs FP. 43611165SRekai.GonzalezAlberquilla@arm.com // Above comment is handled by the issue queue only issuing a valid 43711165SRekai.GonzalezAlberquilla@arm.com // mix of int/fp instructions. 4389553Sandreas.hansson@arm.com //Actually okay to just have one execution, buuuuuut will need 4399553Sandreas.hansson@arm.com //somewhere that defines the execution latency of all instructions. 4409553Sandreas.hansson@arm.com // @todo: Move to the FU pool used in the current full cpu. 4419384SAndreas.Sandberg@arm.com 4427400SAli.Saidi@ARM.com int fu_usage = 0; 4439384SAndreas.Sandberg@arm.com bool fetch_redirect = false; 4449384SAndreas.Sandberg@arm.com int inst_slot = 0; 4459384SAndreas.Sandberg@arm.com int time_slot = 0; 4466313Sgblack@eecs.umich.edu 4476313Sgblack@eecs.umich.edu // Execute/writeback any instructions that are available. 4486313Sgblack@eecs.umich.edu for (int inst_num = 0; 4496313Sgblack@eecs.umich.edu fu_usage < executeWidth && /* Haven't exceeded available FU's. */ 450 inst_num < issueWidth && 451 fromIssue->insts[inst_num]; 452 ++inst_num) { 453 454 DPRINTF(IEW, "IEW: Execute: Executing instructions from IQ.\n"); 455 456 // Get instruction from issue's queue. 457 DynInstPtr inst = fromIssue->insts[inst_num]; 458 459 DPRINTF(IEW, "IEW: Execute: Processing PC %#x.\n", inst->readPC()); 460 461 // Check if the instruction is squashed; if so then skip it 462 // and don't count it towards the FU usage. 463 if (inst->isSquashed()) { 464 DPRINTF(IEW, "IEW: Execute: Instruction was squashed.\n"); 465 466 // Consider this instruction executed so that commit can go 467 // ahead and retire the instruction. 468 inst->setExecuted(); 469 470 toCommit->insts[inst_num] = inst; 471 472 ++iewExecSquashedInsts; 473 474 continue; 475 } 476 477 inst->setExecuted(); 478 479 // If an instruction is executed, then count it towards FU usage. 480 ++fu_usage; 481 482 // Execute instruction. 483 // Note that if the instruction faults, it will be handled 484 // at the commit stage. 485 if (inst->isMemRef()) { 486 DPRINTF(IEW, "IEW: Execute: Calculating address for memory " 487 "reference.\n"); 488 489 // Tell the LDSTQ to execute this instruction (if it is a load). 490 if (inst->isLoad()) { 491 ldstQueue.executeLoad(inst); 492 493 ++iewExecLoadInsts; 494 } else if (inst->isStore()) { 495 ldstQueue.executeStore(inst); 496 497 ++iewExecStoreInsts; 498 } else { 499 panic("IEW: Unexpected memory type!\n"); 500 } 501 502 } else { 503 inst->execute(); 504 505 ++iewExecutedInsts; 506 } 507 508 // First check the time slot that this instruction will write 509 // to. If there are free write ports at the time, then go ahead 510 // and write the instruction to that time. If there are not, 511 // keep looking back to see where's the first time there's a 512 // free slot. What happens if you run out of free spaces? 513 // For now naively assume that all instructions take one cycle. 514 // Otherwise would have to look into the time buffer based on the 515 // latency of the instruction. 516 (*iewQueue)[time_slot].insts[inst_slot]; 517 while ((*iewQueue)[time_slot].insts[inst_slot]) { 518 if (inst_slot < issueWidth) { 519 ++inst_slot; 520 } else { 521 ++time_slot; 522 inst_slot = 0; 523 } 524 525 assert(time_slot < 5); 526 } 527 528 // May actually have to work this out, especially with loads and stores 529 530 // Add finished instruction to queue to commit. 531 (*iewQueue)[time_slot].insts[inst_slot] = inst; 532 (*iewQueue)[time_slot].size++; 533 534 // Check if branch was correct. This check happens after the 535 // instruction is added to the queue because even if the branch 536 // is mispredicted, the branch instruction itself is still valid. 537 // Only handle this if there hasn't already been something that 538 // redirects fetch in this group of instructions. 539 if (!fetch_redirect) { 540 if (inst->mispredicted()) { 541 fetch_redirect = true; 542 543 DPRINTF(IEW, "IEW: Execute: Branch mispredict detected.\n"); 544 DPRINTF(IEW, "IEW: Execute: Redirecting fetch to PC: %#x.\n", 545 inst->nextPC); 546 547 // If incorrect, then signal the ROB that it must be squashed. 548 squashDueToBranch(inst); 549 550 if (inst->predTaken()) { 551 predictedTakenIncorrect++; 552 } 553 } else if (ldstQueue.violation()) { 554 fetch_redirect = true; 555 556 // Get the DynInst that caused the violation. 557 DynInstPtr violator = ldstQueue.getMemDepViolator(); 558 559 DPRINTF(IEW, "IEW: LDSTQ detected a violation. Violator PC: " 560 "%#x, inst PC: %#x. Addr is: %#x.\n", 561 violator->readPC(), inst->readPC(), inst->physEffAddr); 562 563 // Tell the instruction queue that a violation has occured. 564 instQueue.violation(inst, violator); 565 566 // Squash. 567 squashDueToMem(inst); 568 569 ++memOrderViolationEvents; 570 } 571 } 572 } 573} 574 575template<class Impl> 576void 577SimpleIEW<Impl>::tick() 578{ 579 // Considering putting all the state-determining stuff in this section. 580 581 // Try to fill up issue queue with as many instructions as bandwidth 582 // allows. 583 // Decode should try to execute as many instructions as its bandwidth 584 // will allow, as long as it is not currently blocked. 585 586 // Check if the stage is in a running status. 587 if (_status != Blocked && _status != Squashing) { 588 DPRINTF(IEW, "IEW: Status is not blocked, attempting to run " 589 "stage.\n"); 590 iew(); 591 592 // If it's currently unblocking, check to see if it should switch 593 // to running. 594 if (_status == Unblocking) { 595 unblock(); 596 597 ++iewUnblockCycles; 598 } 599 } else if (_status == Squashing) { 600 601 DPRINTF(IEW, "IEW: Still squashing.\n"); 602 603 // Check if stage should remain squashing. Stop squashing if the 604 // squash signal clears. 605 if (!fromCommit->commitInfo.squash && 606 !fromCommit->commitInfo.robSquashing) { 607 DPRINTF(IEW, "IEW: Done squashing, changing status to " 608 "running.\n"); 609 610 _status = Running; 611 instQueue.stopSquash(); 612 } else { 613 instQueue.doSquash(); 614 } 615 616 ++iewSquashCycles; 617 618 // Also should advance its own time buffers if the stage ran. 619 // Not sure about this... 620// issueToExecQueue.advance(); 621 } else if (_status == Blocked) { 622 // Continue to tell previous stage to stall. 623 toRename->iewInfo.stall = true; 624 625 // Check if possible stall conditions have cleared. 626 if (!fromCommit->commitInfo.stall && 627 !instQueue.isFull()) { 628 DPRINTF(IEW, "IEW: Stall signals cleared, going to unblock.\n"); 629 _status = Unblocking; 630 } 631 632 // If there's still instructions coming from rename, continue to 633 // put them on the skid buffer. 634 if (fromRename->size == 0) { 635 block(); 636 } 637 638 if (fromCommit->commitInfo.squash || 639 fromCommit->commitInfo.robSquashing) { 640 squash(); 641 } 642 643 ++iewBlockCycles; 644 } 645 646 // @todo: Maybe put these at the beginning, so if it's idle it can 647 // return early. 648 // Write back number of free IQ entries here. 649 toRename->iewInfo.freeIQEntries = instQueue.numFreeEntries(); 650 651 ldstQueue.writebackStores(); 652 653 // Check the committed load/store signals to see if there's a load 654 // or store to commit. Also check if it's being told to execute a 655 // nonspeculative instruction. 656 // This is pretty inefficient... 657// if (0/*fromCommit->commitInfo.commitIsStore*/) { 658 if (!fromCommit->commitInfo.squash && 659 !fromCommit->commitInfo.robSquashing) { 660 ldstQueue.commitStores(fromCommit->commitInfo.doneSeqNum); 661// } else if (fromCommit->commitInfo.commitIsLoad) { 662 ldstQueue.commitLoads(fromCommit->commitInfo.doneSeqNum); 663 } 664// } 665 666 if (fromCommit->commitInfo.nonSpecSeqNum != 0) { 667 instQueue.scheduleNonSpec(fromCommit->commitInfo.nonSpecSeqNum); 668 } 669 670 DPRINTF(IEW, "IEW: IQ has %i free entries.\n", 671 instQueue.numFreeEntries()); 672} 673 674template<class Impl> 675void 676SimpleIEW<Impl>::iew() 677{ 678 // Might want to put all state checks in the tick() function. 679 // Check if being told to stall from commit. 680 if (fromCommit->commitInfo.stall) { 681 block(); 682 return; 683 } else if (fromCommit->commitInfo.squash || 684 fromCommit->commitInfo.robSquashing) { 685 // Also check if commit is telling this stage to squash. 686 squash(); 687 return; 688 } 689 690 dispatchInsts(); 691 692 // Have the instruction queue try to schedule any ready instructions. 693 instQueue.scheduleReadyInsts(); 694 695 executeInsts(); 696 697 // Loop through the head of the time buffer and wake any dependents. 698 // These instructions are about to write back. In the simple model 699 // this loop can really happen within the previous loop, but when 700 // instructions have actual latencies, this loop must be separate. 701 // Also mark scoreboard that this instruction is finally complete. 702 // Either have IEW have direct access to rename map, or have this as 703 // part of backwards communication. 704 for (int inst_num = 0; inst_num < issueWidth && 705 toCommit->insts[inst_num]; inst_num++) 706 { 707 DynInstPtr inst = toCommit->insts[inst_num]; 708 709 DPRINTF(IEW, "IEW: Sending instructions to commit, PC %#x.\n", 710 inst->readPC()); 711 712 if(!inst->isSquashed()) { 713 instQueue.wakeDependents(inst); 714 715 for (int i = 0; i < inst->numDestRegs(); i++) 716 { 717 renameMap->markAsReady(inst->renamedDestRegIdx(i)); 718 } 719 } 720 } 721 722 // Also should advance its own time buffers if the stage ran. 723 // Not the best place for it, but this works (hopefully). 724 issueToExecQueue.advance(); 725} 726 727#ifndef FULL_SYSTEM 728template<class Impl> 729void 730SimpleIEW<Impl>::lsqWriteback() 731{ 732 ldstQueue.writebackAllInsts(); 733} 734#endif 735