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 &params)
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