iew_impl.hh revision 1061
112276Sanouk.vanlaer@arm.com// @todo: Fix the instantaneous communication among all the stages within 28839Sandreas.hansson@arm.com// iew. There's a clear delay between issue and execute, yet backwards 38839Sandreas.hansson@arm.com// communication happens simultaneously. Might not be that bad really... 48839Sandreas.hansson@arm.com// it might skew stats a bit though. Issue would otherwise try to issue 58839Sandreas.hansson@arm.com// instructions that would never be executed if there were a delay; without 68839Sandreas.hansson@arm.com// it issue will simply squash. Make this stage block properly. 78839Sandreas.hansson@arm.com// Update the statuses for each stage. 88839Sandreas.hansson@arm.com// Actually read instructions out of the skid buffer. 98839Sandreas.hansson@arm.com 108839Sandreas.hansson@arm.com#include <queue> 118839Sandreas.hansson@arm.com 128839Sandreas.hansson@arm.com#include "base/timebuf.hh" 135335Shines@cs.fsu.edu#include "cpu/beta_cpu/iew.hh" 147897Shestness@cs.utexas.edu 154486Sbinkertn@umich.edutemplate<class Impl, class IQ> 164486Sbinkertn@umich.eduSimpleIEW<Impl, IQ>::SimpleIEW(Params ¶ms) 174486Sbinkertn@umich.edu : // Just make this time buffer really big for now 184486Sbinkertn@umich.edu issueToExecQueue(5, 5), 194486Sbinkertn@umich.edu instQueue(params), 204486Sbinkertn@umich.edu ldstQueue(params), 214486Sbinkertn@umich.edu commitToIEWDelay(params.commitToIEWDelay), 224486Sbinkertn@umich.edu renameToIEWDelay(params.renameToIEWDelay), 234486Sbinkertn@umich.edu issueToExecuteDelay(params.issueToExecuteDelay), 244486Sbinkertn@umich.edu issueReadWidth(params.issueWidth), 254486Sbinkertn@umich.edu issueWidth(params.issueWidth), 264486Sbinkertn@umich.edu executeWidth(params.executeWidth) 274486Sbinkertn@umich.edu{ 284486Sbinkertn@umich.edu DPRINTF(IEW, "IEW: executeIntWidth: %i.\n", params.executeIntWidth); 294486Sbinkertn@umich.edu _status = Idle; 304486Sbinkertn@umich.edu _issueStatus = Idle; 314486Sbinkertn@umich.edu _exeStatus = Idle; 324486Sbinkertn@umich.edu _wbStatus = Idle; 334486Sbinkertn@umich.edu 344486Sbinkertn@umich.edu // Setup wire to read instructions coming from issue. 354486Sbinkertn@umich.edu fromIssue = issueToExecQueue.getWire(-issueToExecuteDelay); 364486Sbinkertn@umich.edu 374486Sbinkertn@umich.edu // Instruction queue needs the queue between issue and execute. 384486Sbinkertn@umich.edu instQueue.setIssueToExecuteQueue(&issueToExecQueue); 394486Sbinkertn@umich.edu} 404486Sbinkertn@umich.edu 417897Shestness@cs.utexas.edutemplate<class Impl, class IQ> 428839Sandreas.hansson@arm.comvoid 434486Sbinkertn@umich.eduSimpleIEW<Impl, IQ>::setCPU(FullCPU *cpu_ptr) 446654Snate@binkert.org{ 456654Snate@binkert.org DPRINTF(IEW, "IEW: Setting CPU pointer.\n"); 4611988Sandreas.sandberg@arm.com cpu = cpu_ptr; 476654Snate@binkert.org 483102SN/A instQueue.setCPU(cpu_ptr); 493102SN/A ldstQueue.setCPU(cpu_ptr); 506654Snate@binkert.org} 5110720Sandreas.hansson@arm.com 524776Sgblack@eecs.umich.edutemplate<class Impl, class IQ> 5310663SAli.Saidi@ARM.comvoid 546654Snate@binkert.orgSimpleIEW<Impl, IQ>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) 559793Sakash.bagdia@arm.com{ 562667SN/A DPRINTF(IEW, "IEW: Setting time buffer pointer.\n"); 574776Sgblack@eecs.umich.edu timeBuffer = tb_ptr; 584776Sgblack@eecs.umich.edu 596654Snate@binkert.org // Setup wire to read information from time buffer, from commit. 6012434Sgabeblack@google.com fromCommit = timeBuffer->getWire(-commitToIEWDelay); 618745Sgblack@eecs.umich.edu 629384SAndreas.Sandberg@arm.com // Setup wire to write information back to previous stages. 6312325Sandreas.sandberg@arm.com toRename = timeBuffer->getWire(0); 646654Snate@binkert.org 6512434Sgabeblack@google.com // Instruction queue also needs main time buffer. 668745Sgblack@eecs.umich.edu instQueue.setTimeBuffer(tb_ptr); 679384SAndreas.Sandberg@arm.com} 6812325Sandreas.sandberg@arm.com 696654Snate@binkert.orgtemplate<class Impl, class IQ> 7012434Sgabeblack@google.comvoid 718745Sgblack@eecs.umich.eduSimpleIEW<Impl, IQ>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr) 729384SAndreas.Sandberg@arm.com{ 7312325Sandreas.sandberg@arm.com DPRINTF(IEW, "IEW: Setting rename queue pointer.\n"); 746654Snate@binkert.org renameQueue = rq_ptr; 7512434Sgabeblack@google.com 768745Sgblack@eecs.umich.edu // Setup wire to read information from rename queue. 779384SAndreas.Sandberg@arm.com fromRename = renameQueue->getWire(-renameToIEWDelay); 7812325Sandreas.sandberg@arm.com} 796654Snate@binkert.org 8012434Sgabeblack@google.comtemplate<class Impl, class IQ> 8112434Sgabeblack@google.comvoid 828745Sgblack@eecs.umich.eduSimpleIEW<Impl, IQ>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr) 839384SAndreas.Sandberg@arm.com{ 8412325Sandreas.sandberg@arm.com DPRINTF(IEW, "IEW: Setting IEW queue pointer.\n"); 856691Stjones1@inf.ed.ac.uk iewQueue = iq_ptr; 8612434Sgabeblack@google.com 878745Sgblack@eecs.umich.edu // Setup wire to write instructions to commit. 889384SAndreas.Sandberg@arm.com toCommit = iewQueue->getWire(0); 8912325Sandreas.sandberg@arm.com} 9011723Sar4jc@virginia.edu 9112434Sgabeblack@google.comtemplate<class Impl, class IQ> 9211723Sar4jc@virginia.eduvoid 9311723Sar4jc@virginia.eduSimpleIEW<Impl, IQ>::setRenameMap(RenameMap *rm_ptr) 9412325Sandreas.sandberg@arm.com{ 954486Sbinkertn@umich.edu DPRINTF(IEW, "IEW: Setting rename map pointer.\n"); 965529Snate@binkert.org renameMap = rm_ptr; 971366SN/A} 981310SN/A 999338SAndreas.Sandberg@arm.comtemplate<class Impl, class IQ> 1009254SAndreas.Sandberg@arm.comvoid 10111988Sandreas.sandberg@arm.comSimpleIEW<Impl, IQ>::wakeDependents(DynInstPtr &inst) 10211988Sandreas.sandberg@arm.com{ 10311988Sandreas.sandberg@arm.com instQueue.wakeDependents(inst); 10411988Sandreas.sandberg@arm.com} 10511988Sandreas.sandberg@arm.com 10611988Sandreas.sandberg@arm.comtemplate<class Impl, class IQ> 10711988Sandreas.sandberg@arm.comvoid 10811988Sandreas.sandberg@arm.comSimpleIEW<Impl, IQ>::block() 10911988Sandreas.sandberg@arm.com{ 11011988Sandreas.sandberg@arm.com DPRINTF(IEW, "IEW: Blocking.\n"); 1119254SAndreas.Sandberg@arm.com // Set the status to Blocked. 1129518SAndreas.Sandberg@ARM.com _status = Blocked; 1139518SAndreas.Sandberg@ARM.com 1149518SAndreas.Sandberg@ARM.com // Add the current inputs to the skid buffer so they can be 1159518SAndreas.Sandberg@ARM.com // reprocessed when this stage unblocks. 1169518SAndreas.Sandberg@ARM.com skidBuffer.push(*fromRename); 1179518SAndreas.Sandberg@ARM.com 1189518SAndreas.Sandberg@ARM.com // Note that this stage only signals previous stages to stall when 1199518SAndreas.Sandberg@ARM.com // it is the cause of the stall originates at this stage. Otherwise 1209518SAndreas.Sandberg@ARM.com // the previous stages are expected to check all possible stall signals. 1219518SAndreas.Sandberg@ARM.com} 1229518SAndreas.Sandberg@ARM.com 1239518SAndreas.Sandberg@ARM.comtemplate<class Impl, class IQ> 1249518SAndreas.Sandberg@ARM.cominline void 1259518SAndreas.Sandberg@ARM.comSimpleIEW<Impl, IQ>::unblock() 1269518SAndreas.Sandberg@ARM.com{ 1279518SAndreas.Sandberg@ARM.com // Check if there's information in the skid buffer. If there is, then 1289518SAndreas.Sandberg@ARM.com // set status to unblocking, otherwise set it directly to running. 1299518SAndreas.Sandberg@ARM.com DPRINTF(IEW, "IEW: Reading instructions out of the skid " 1309518SAndreas.Sandberg@ARM.com "buffer.\n"); 1319254SAndreas.Sandberg@arm.com // Remove the now processed instructions from the skid buffer. 1329254SAndreas.Sandberg@arm.com skidBuffer.pop(); 1339254SAndreas.Sandberg@arm.com 1349254SAndreas.Sandberg@arm.com // If there's still information in the skid buffer, then 1352901SN/A // continue to tell previous stages to stall. They will be 1365712Shsul@eecs.umich.edu // able to restart once the skid buffer is empty. 13710190Sakash.bagdia@arm.com if (!skidBuffer.empty()) { 1385529Snate@binkert.org toRename->iewInfo.stall = true; 13912276Sanouk.vanlaer@arm.com } else { 14012276Sanouk.vanlaer@arm.com DPRINTF(IEW, "IEW: Stage is done unblocking.\n"); 1415529Snate@binkert.org _status = Running; 14212277Sjose.marinho@arm.com } 14312277Sjose.marinho@arm.com} 14412277Sjose.marinho@arm.com 14512277Sjose.marinho@arm.comtemplate<class Impl, class IQ> 1465529Snate@binkert.orgvoid 1479161Sandreas.hansson@arm.comSimpleIEW<Impl, IQ>::squash() 1485529Snate@binkert.org{ 1495821Ssaidi@eecs.umich.edu DPRINTF(IEW, "IEW: Squashing all instructions.\n"); 1503170SN/A _status = Squashing; 15111877Sbrandon.potter@amd.com 15211877Sbrandon.potter@amd.com // Tell the IQ to start squashing. 1535780Ssteve.reinhardt@amd.com instQueue.squash(); 1545780Ssteve.reinhardt@amd.com 1555780Ssteve.reinhardt@amd.com // Tell the LDSTQ to start squashing. 1565780Ssteve.reinhardt@amd.com ldstQueue.squash(fromCommit->commitInfo.doneSeqNum); 1575780Ssteve.reinhardt@amd.com} 1588784Sgblack@eecs.umich.edu 1598784Sgblack@eecs.umich.edutemplate<class Impl, class IQ> 1608784Sgblack@eecs.umich.eduvoid 16112122Sjose.marinho@arm.comSimpleIEW<Impl, IQ>::squash(DynInstPtr &inst) 16212122Sjose.marinho@arm.com{ 16312122Sjose.marinho@arm.com DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n", 1648793Sgblack@eecs.umich.edu inst->PC); 1651310SN/A // Perhaps leave the squashing up to the ROB stage to tell it when to 16612434Sgabeblack@google.com // squash? 16712434Sgabeblack@google.com _status = Squashing; 1686654Snate@binkert.org 16911150Smitch.hayenga@arm.com // Tell rename to squash through the time buffer. 17011150Smitch.hayenga@arm.com toRename->iewInfo.squash = true; 17112325Sandreas.sandberg@arm.com // Also send PC update information back to prior stages. 1726654Snate@binkert.org toRename->iewInfo.squashedSeqNum = inst->seqNum; 17311150Smitch.hayenga@arm.com toRename->iewInfo.mispredPC = inst->readPC(); 17411150Smitch.hayenga@arm.com toRename->iewInfo.nextPC = inst->readCalcTarg(); 17512325Sandreas.sandberg@arm.com toRename->iewInfo.branchMispredict = true; 1766654Snate@binkert.org // Prediction was incorrect, so send back inverse. 17711150Smitch.hayenga@arm.com toRename->iewInfo.branchTaken = !(inst->predTaken()); 17812325Sandreas.sandberg@arm.com} 1796654Snate@binkert.org 18011150Smitch.hayenga@arm.comtemplate<class Impl, class IQ> 18111150Smitch.hayenga@arm.comvoid 18212325Sandreas.sandberg@arm.comSimpleIEW<Impl, IQ>::tick() 1836654Snate@binkert.org{ 18410037SARM gem5 Developers // Considering putting all the state-determining stuff in this section. 18510037SARM gem5 Developers 18611150Smitch.hayenga@arm.com // Try to fill up issue queue with as many instructions as bandwidth 18711150Smitch.hayenga@arm.com // allows. 18812325Sandreas.sandberg@arm.com // Decode should try to execute as many instructions as its bandwidth 1896691Stjones1@inf.ed.ac.uk // will allow, as long as it is not currently blocked. 1906691Stjones1@inf.ed.ac.uk 19111150Smitch.hayenga@arm.com // Check if the stage is in a running status. 19211150Smitch.hayenga@arm.com if (_status != Blocked && _status != Squashing) { 19312325Sandreas.sandberg@arm.com DPRINTF(IEW, "IEW: Status is not blocked, attempting to run " 19411723Sar4jc@virginia.edu "stage.\n"); 19511723Sar4jc@virginia.edu iew(); 19611723Sar4jc@virginia.edu 19712325Sandreas.sandberg@arm.com // If it's currently unblocking, check to see if it should switch 1984997Sgblack@eecs.umich.edu // to running. 1994997Sgblack@eecs.umich.edu if (_status == Unblocking) { 2006654Snate@binkert.org unblock(); 2014997Sgblack@eecs.umich.edu } 2024997Sgblack@eecs.umich.edu } else if (_status == Squashing) { 2031310SN/A 2041310SN/A DPRINTF(IEW, "IEW: Still squashing.\n"); 2051310SN/A 2061310SN/A // Check if stage should remain squashing. Stop squashing if the 2079647Sdam.sunwoo@arm.com // squash signal clears. 2089647Sdam.sunwoo@arm.com if (!fromCommit->commitInfo.squash && 2091310SN/A !fromCommit->commitInfo.robSquashing) { 2101310SN/A DPRINTF(IEW, "IEW: Done squashing, changing status to " 2111310SN/A "running.\n"); 2121310SN/A 2139180Sandreas.hansson@arm.com _status = Running; 2149180Sandreas.hansson@arm.com instQueue.stopSquash(); 2151310SN/A } else { 2169433SAndreas.Sandberg@ARM.com instQueue.doSquash(); 2179433SAndreas.Sandberg@ARM.com } 2189433SAndreas.Sandberg@ARM.com 2191634SN/A // Also should advance its own time buffers if the stage ran. 2204776Sgblack@eecs.umich.edu // Not sure about this... 2214776Sgblack@eecs.umich.edu// issueToExecQueue.advance(); 2228839Sandreas.hansson@arm.com } else if (_status == Blocked) { 2238839Sandreas.hansson@arm.com // Continue to tell previous stage to stall. 2248707Sandreas.hansson@arm.com toRename->iewInfo.stall = true; 2258707Sandreas.hansson@arm.com 2268756Sgblack@eecs.umich.edu // Check if possible stall conditions have cleared. 2278707Sandreas.hansson@arm.com if (!fromCommit->commitInfo.stall && 2287876Sgblack@eecs.umich.edu !instQueue.isFull()) { 2298839Sandreas.hansson@arm.com DPRINTF(IEW, "IEW: Stall signals cleared, going to unblock.\n"); 2308839Sandreas.hansson@arm.com _status = Unblocking; 2318745Sgblack@eecs.umich.edu } 23211150Smitch.hayenga@arm.com 23311150Smitch.hayenga@arm.com // If there's still instructions coming from rename, continue to 23411150Smitch.hayenga@arm.com // put them on the skid buffer. 2352998SN/A if (fromRename->insts[0]) { 2368863Snilay@cs.wisc.edu block(); 2378863Snilay@cs.wisc.edu } 23811150Smitch.hayenga@arm.com 2398863Snilay@cs.wisc.edu if (fromCommit->commitInfo.squash || 24011150Smitch.hayenga@arm.com fromCommit->commitInfo.robSquashing) { 2418863Snilay@cs.wisc.edu squash(); 2429793Sakash.bagdia@arm.com } 2439793Sakash.bagdia@arm.com } 2449793Sakash.bagdia@arm.com 24511150Smitch.hayenga@arm.com // @todo: Maybe put these at the beginning, so if it's idle it can 2469544Sandreas.hansson@arm.com // return early. 24711150Smitch.hayenga@arm.com // Write back number of free IQ entries here. 2489544Sandreas.hansson@arm.com toRename->iewInfo.freeIQEntries = instQueue.numFreeEntries(); 2498863Snilay@cs.wisc.edu 25011150Smitch.hayenga@arm.com // Check the committed load/store signals to see if there's a load 2518863Snilay@cs.wisc.edu // or store to commit. Also check if it's being told to execute a 25211150Smitch.hayenga@arm.com // nonspeculative instruction. 2538863Snilay@cs.wisc.edu if (fromCommit->commitInfo.commitIsStore) { 25411150Smitch.hayenga@arm.com ldstQueue.commitStores(fromCommit->commitInfo.doneSeqNum); 25511723Sar4jc@virginia.edu } else if (fromCommit->commitInfo.commitIsLoad) { 25611723Sar4jc@virginia.edu ldstQueue.commitLoads(fromCommit->commitInfo.doneSeqNum); 25711723Sar4jc@virginia.edu } 2588863Snilay@cs.wisc.edu 2598863Snilay@cs.wisc.edu if (fromCommit->commitInfo.nonSpecSeqNum != 0) { 2608863Snilay@cs.wisc.edu instQueue.scheduleNonSpec(fromCommit->commitInfo.nonSpecSeqNum); 2618863Snilay@cs.wisc.edu } 2628863Snilay@cs.wisc.edu 2637876Sgblack@eecs.umich.edu DPRINTF(IEW, "IEW: IQ has %i free entries.\n", 2647876Sgblack@eecs.umich.edu instQueue.numFreeEntries()); 2658839Sandreas.hansson@arm.com} 2667404SAli.Saidi@ARM.com 2677876Sgblack@eecs.umich.edutemplate<class Impl, class IQ> 2688839Sandreas.hansson@arm.comvoid 2698839Sandreas.hansson@arm.comSimpleIEW<Impl, IQ>::iew() 2708839Sandreas.hansson@arm.com{ 2718839Sandreas.hansson@arm.com // Might want to put all state checks in the tick() function. 2727876Sgblack@eecs.umich.edu // Check if being told to stall from commit. 2737876Sgblack@eecs.umich.edu if (fromCommit->commitInfo.stall) { 2747876Sgblack@eecs.umich.edu block(); 2757876Sgblack@eecs.umich.edu return; 2767876Sgblack@eecs.umich.edu } else if (fromCommit->commitInfo.squash || 2777876Sgblack@eecs.umich.edu fromCommit->commitInfo.robSquashing) { 2782998SN/A // Also check if commit is telling this stage to squash. 2797868Sgblack@eecs.umich.edu squash(); 2802998SN/A return; 2812998SN/A } 2822998SN/A 2832998SN/A //////////////////////////////////////// 2847876Sgblack@eecs.umich.edu // DISPATCH/ISSUE stage 2858796Sgblack@eecs.umich.edu //////////////////////////////////////// 2868796Sgblack@eecs.umich.edu 2878796Sgblack@eecs.umich.edu //Put into its own function? 2888796Sgblack@eecs.umich.edu //Add instructions to IQ if there are any instructions there 28910717Sandreas.hansson@arm.com 29010717Sandreas.hansson@arm.com // Check if there are any instructions coming from rename, and we're. 2918796Sgblack@eecs.umich.edu // not squashing. 2928796Sgblack@eecs.umich.edu if (fromRename->insts[0] && _status != Squashing) { 2938796Sgblack@eecs.umich.edu 2948796Sgblack@eecs.umich.edu // Loop through the instructions, putting them in the instruction 2958887Sgeoffrey.blake@arm.com // queue. 2968809Sgblack@eecs.umich.edu for (int inst_num = 0; inst_num < issueReadWidth; ++inst_num) 2978809Sgblack@eecs.umich.edu { 2988887Sgeoffrey.blake@arm.com DynInstPtr inst = fromRename->insts[inst_num]; 2998809Sgblack@eecs.umich.edu 3008809Sgblack@eecs.umich.edu // Make sure there's a valid instruction there. 3012998SN/A if (!inst) 30212440Sxiaoyuma@google.com break; 30312440Sxiaoyuma@google.com 3047868Sgblack@eecs.umich.edu DPRINTF(IEW, "IEW: Issue: Adding PC %#x to IQ.\n", 30512440Sxiaoyuma@google.com inst->readPC()); 3067876Sgblack@eecs.umich.edu 3072998SN/A // If it's a memory reference, don't put it in the 3088839Sandreas.hansson@arm.com // instruction queue. These will only be executed at commit. 3097876Sgblack@eecs.umich.edu // Do the same for nonspeculative instructions and nops. 3108887Sgeoffrey.blake@arm.com // Be sure to mark these instructions as ready so that the 3119384SAndreas.Sandberg@arm.com // commit stage can go ahead and execute them, and mark 31212325Sandreas.sandberg@arm.com // them as issued so the IQ doesn't reprocess them. 31312325Sandreas.sandberg@arm.com if (inst->isSquashed()) { 31412325Sandreas.sandberg@arm.com continue; 31512325Sandreas.sandberg@arm.com } else if (inst->isLoad()) { 31612325Sandreas.sandberg@arm.com DPRINTF(IEW, "IEW: Issue: Memory instruction " 31712325Sandreas.sandberg@arm.com "encountered, adding to LDSTQ.\n"); 31812325Sandreas.sandberg@arm.com 31912325Sandreas.sandberg@arm.com // Reserve a spot in the load store queue for this 3209384SAndreas.Sandberg@arm.com // memory access. 3219384SAndreas.Sandberg@arm.com ldstQueue.insertLoad(inst); 3229384SAndreas.Sandberg@arm.com 3238887Sgeoffrey.blake@arm.com } else if (inst->isStore()) { 3248887Sgeoffrey.blake@arm.com ldstQueue.insertStore(inst); 325 326 // A bit of a hack. Set that it can commit so that 327 // the commit stage will try committing it, and then 328 // once commit realizes it's a store it will send back 329 // a signal to this stage to issue and execute that 330 // store. 331 inst->setCanCommit(); 332 333 instQueue.insertNonSpec(inst); 334 continue; 335 } else if (inst->isNonSpeculative()) { 336 DPRINTF(IEW, "IEW: Issue: Nonspeculative instruction " 337 "encountered, skipping.\n"); 338 339 // Same hack as with stores. 340 inst->setCanCommit(); 341 342 // Specificall insert it as nonspeculative. 343 instQueue.insertNonSpec(inst); 344 345 continue; 346 } else if (inst->isNop()) { 347 DPRINTF(IEW, "IEW: Issue: Nop instruction encountered " 348 ", skipping.\n"); 349 350 inst->setIssued(); 351 inst->setExecuted(); 352 inst->setCanCommit(); 353 354 instQueue.advanceTail(inst); 355 continue; 356 } else if (instQueue.isFull()) { 357 DPRINTF(IEW, "IEW: Issue: IQ has become full.\n"); 358 // Call function to start blocking. 359 block(); 360 // Tell previous stage to stall. 361 toRename->iewInfo.stall = true; 362 break; 363 } 364 365 // If the instruction queue is not full, then add the 366 // instruction. 367 instQueue.insert(fromRename->insts[inst_num]); 368 } 369 } 370 371 // Have the instruction queue try to schedule any ready instructions. 372 instQueue.scheduleReadyInsts(); 373 374 //////////////////////////////////////// 375 //EXECUTE/WRITEBACK stage 376 //////////////////////////////////////// 377 378 //Put into its own function? 379 //Similarly should probably have separate execution for int vs FP. 380 // Above comment is handled by the issue queue only issuing a valid 381 // mix of int/fp instructions. 382 //Actually okay to just have one execution, buuuuuut will need 383 //somewhere that defines the execution latency of all instructions. 384 // @todo: Move to the FU pool used in the current full cpu. 385 386 int fu_usage = 0; 387 bool fetch_redirect = false; 388 389 // Execute/writeback any instructions that are available. 390 for (int inst_num = 0; 391 fu_usage < executeWidth && /* Haven't exceeded available FU's. */ 392 inst_num < issueWidth && /* Haven't exceeded issue width. */ 393 fromIssue->insts[inst_num]; /* There are available instructions. */ 394 ++inst_num) { 395 DPRINTF(IEW, "IEW: Execute: Executing instructions from IQ.\n"); 396 397 // Get instruction from issue's queue. 398 DynInstPtr inst = fromIssue->insts[inst_num]; 399 400 DPRINTF(IEW, "IEW: Execute: Processing PC %#x.\n", inst->readPC()); 401 402 // Check if the instruction is squashed; if so then skip it 403 // and don't count it towards the FU usage. 404 if (inst->isSquashed()) { 405 DPRINTF(IEW, "IEW: Execute: Instruction was squashed.\n"); 406 407 // Consider this instruction executed so that commit can go 408 // ahead and retire the instruction. 409 inst->setExecuted(); 410 411 toCommit->insts[inst_num] = inst; 412 413 continue; 414 } 415 416 inst->setExecuted(); 417 418 // If an instruction is executed, then count it towards FU usage. 419 ++fu_usage; 420 421 // Execute instruction. 422 // Note that if the instruction faults, it will be handled 423 // at the commit stage. 424 if (inst->isMemRef()) { 425 DPRINTF(IEW, "IEW: Execute: Calculating address for memory " 426 "reference.\n"); 427 428 // Tell the LDSTQ to execute this instruction (if it is a load). 429 if (inst->isLoad()) { 430 ldstQueue.executeLoad(inst); 431 } else if (inst->isStore()) { 432 ldstQueue.executeStore(); 433 } else { 434 panic("IEW: Unexpected memory type!\n"); 435 } 436 437 } else { 438 inst->execute(); 439 } 440 441 // First check the time slot that this instruction will write 442 // to. If there are free write ports at the time, then go ahead 443 // and write the instruction to that time. If there are not, 444 // keep looking back to see where's the first time there's a 445 // free slot. What happens if you run out of free spaces? 446 // For now naively assume that all instructions take one cycle. 447 // Otherwise would have to look into the time buffer based on the 448 // latency of the instruction. 449 450 // Add finished instruction to queue to commit. 451 toCommit->insts[inst_num] = inst; 452 453 // Check if branch was correct. This check happens after the 454 // instruction is added to the queue because even if the branch 455 // is mispredicted, the branch instruction itself is still valid. 456 // Only handle this if there hasn't already been something that 457 // redirects fetch in this group of instructions. 458 if (!fetch_redirect) { 459 if (inst->mispredicted()) { 460 fetch_redirect = true; 461 462 DPRINTF(IEW, "IEW: Execute: Branch mispredict detected.\n"); 463 DPRINTF(IEW, "IEW: Execute: Redirecting fetch to PC: %#x.\n", 464 inst->nextPC); 465 466 // If incorrect, then signal the ROB that it must be squashed. 467 squash(inst); 468 } else if (ldstQueue.violation()) { 469 fetch_redirect = true; 470 471 DynInstPtr violator = ldstQueue.getMemDepViolator(); 472 473 DPRINTF(IEW, "IEW: LDSTQ detected a violation. Violator PC: " 474 "%#x, inst PC: %#x. Addr is: %#x.\n", 475 violator->readPC(), inst->readPC(), inst->physEffAddr); 476 477 instQueue.violation(inst, violator); 478 479 squash(inst); 480 // Otherwise check if there was a memory ordering violation. 481 // If there was, then signal ROB that it must be squashed. Also 482 // signal IQ that there was a violation. 483 } 484 } 485 } 486 487 // Loop through the head of the time buffer and wake any dependents. 488 // These instructions are about to write back. In the simple model 489 // this loop can really happen within the previous loop, but when 490 // instructions have actual latencies, this loop must be separate. 491 // Also mark scoreboard that this instruction is finally complete. 492 // Either have IEW have direct access to rename map, or have this as 493 // part of backwards communication. 494 for (int inst_num = 0; inst_num < executeWidth && 495 toCommit->insts[inst_num]; inst_num++) 496 { 497 DynInstPtr inst = toCommit->insts[inst_num]; 498 499 DPRINTF(IEW, "IEW: Sending instructions to commit, PC %#x.\n", 500 inst->readPC()); 501 502 if(!inst->isSquashed()) { 503 instQueue.wakeDependents(inst); 504 505 for (int i = 0; i < inst->numDestRegs(); i++) 506 { 507 renameMap->markAsReady(inst->renamedDestRegIdx(i)); 508 } 509 } 510 } 511 512 // Also should advance its own time buffers if the stage ran. 513 // Not the best place for it, but this works (hopefully). 514 issueToExecQueue.advance(); 515} 516