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