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