iew_impl.hh revision 2292
11689SN/A/*
29444SAndreas.Sandberg@ARM.com * Copyright (c) 2004-2005 The Regents of The University of Michigan
37598Sminkyu.jeong@arm.com * All rights reserved.
47598Sminkyu.jeong@arm.com *
57598Sminkyu.jeong@arm.com * Redistribution and use in source and binary forms, with or without
67598Sminkyu.jeong@arm.com * modification, are permitted provided that the following conditions are
77598Sminkyu.jeong@arm.com * met: redistributions of source code must retain the above copyright
87598Sminkyu.jeong@arm.com * notice, this list of conditions and the following disclaimer;
97598Sminkyu.jeong@arm.com * redistributions in binary form must reproduce the above copyright
107598Sminkyu.jeong@arm.com * notice, this list of conditions and the following disclaimer in the
117598Sminkyu.jeong@arm.com * documentation and/or other materials provided with the distribution;
127598Sminkyu.jeong@arm.com * neither the name of the copyright holders nor the names of its
137598Sminkyu.jeong@arm.com * contributors may be used to endorse or promote products derived from
142326SN/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.
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
331689SN/A#include <queue>
341689SN/A
351689SN/A#include "base/timebuf.hh"
361689SN/A#include "cpu/o3/fu_pool.hh"
371689SN/A#include "cpu/o3/iew.hh"
381689SN/A
392665Ssaidi@eecs.umich.eduusing namespace std;
402665Ssaidi@eecs.umich.edu
411689SN/Atemplate<class Impl>
421689SN/ADefaultIEW<Impl>::LdWritebackEvent::LdWritebackEvent(DynInstPtr &_inst,
431060SN/A                                                     DefaultIEW<Impl> *_iew)
441060SN/A    : Event(&mainEventQueue), inst(_inst), iewStage(_iew)
451689SN/A{
461060SN/A    this->setFlags(Event::AutoDelete);
471060SN/A}
481060SN/A
498230Snate@binkert.orgtemplate<class Impl>
506658Snate@binkert.orgvoid
518887Sgeoffrey.blake@arm.comDefaultIEW<Impl>::LdWritebackEvent::process()
522292SN/A{
531717SN/A    DPRINTF(IEW, "Load writeback event [sn:%lli]\n", inst->seqNum);
548229Snate@binkert.org    DPRINTF(Activity, "Activity: Ld Writeback event [sn:%lli]\n", inst->seqNum);
558232Snate@binkert.org
568232Snate@binkert.org    //iewStage->ldstQueue.removeMSHR(inst->threadNumber,inst->seqNum);
579444SAndreas.Sandberg@ARM.com
588232Snate@binkert.org    iewStage->wakeCPU();
599527SMatt.Horsnell@arm.com
605529Snate@binkert.org    if (inst->isSquashed()) {
611060SN/A        inst = NULL;
626221Snate@binkert.org        return;
636221Snate@binkert.org    }
641681SN/A
655529Snate@binkert.org    if (!inst->isExecuted()) {
662873Sktlim@umich.edu        inst->setExecuted();
674329Sktlim@umich.edu
684329Sktlim@umich.edu        // Execute again to copy data to proper place.
694329Sktlim@umich.edu        if (inst->isStore()) {
702292SN/A            inst->completeAcc();
712292SN/A        }
722292SN/A    }
732292SN/A
742820Sktlim@umich.edu    // Need to insert instruction into queue to commit
752292SN/A    iewStage->instToCommit(inst);
762820Sktlim@umich.edu
772820Sktlim@umich.edu    //wroteToTimeBuffer = true;
789444SAndreas.Sandberg@ARM.com    iewStage->activityThisCycle();
791060SN/A
802292SN/A    inst = NULL;
812292SN/A}
822292SN/A
831060SN/Atemplate<class Impl>
841060SN/Aconst char *
851060SN/ADefaultIEW<Impl>::LdWritebackEvent::description()
861060SN/A{
871060SN/A    return "Load writeback event";
881060SN/A}
891681SN/A
906221Snate@binkert.orgtemplate<class Impl>
916221Snate@binkert.orgDefaultIEW<Impl>::DefaultIEW(Params *params)
926221Snate@binkert.org    : // Just make this time buffer really big for now
936221Snate@binkert.org    // @todo: Make this into a parameter.
942292SN/A      issueToExecQueue(5, 5),
952292SN/A      instQueue(params),
962820Sktlim@umich.edu      ldstQueue(params),
972820Sktlim@umich.edu      fuPool(params->fuPool),
982292SN/A      commitToIEWDelay(params->commitToIEWDelay),
992292SN/A      renameToIEWDelay(params->renameToIEWDelay),
1002820Sktlim@umich.edu      issueToExecuteDelay(params->issueToExecuteDelay),
1012820Sktlim@umich.edu      issueReadWidth(params->issueWidth),
1022292SN/A      issueWidth(params->issueWidth),
1032292SN/A      executeWidth(params->executeWidth),
1042292SN/A      numThreads(params->numberOfThreads)
1052292SN/A{
1062292SN/A    DPRINTF(IEW, "executeIntWidth: %i.\n", params->executeIntWidth);
1072292SN/A    _status = Active;
1082292SN/A    exeStatus = Running;
1092292SN/A    wbStatus = Idle;
1101060SN/A
1111060SN/A    // Setup wire to read instructions coming from issue.
1121681SN/A    fromIssue = issueToExecQueue.getWire(-issueToExecuteDelay);
1131062SN/A
1142292SN/A    // Instruction queue needs the queue between issue and execute.
1151062SN/A    instQueue.setIssueToExecuteQueue(&issueToExecQueue);
1162301SN/A
1172301SN/A    instQueue.setIEW(this);
1181062SN/A    ldstQueue.setIEW(this);
1192727Sktlim@umich.edu
1201062SN/A    for (int i=0; i < numThreads; i++) {
1211062SN/A        dispatchStatus[i] = Running;
1221062SN/A        stalls[i].commit = false;
1231062SN/A        fetchRedirect[i] = false;
1241062SN/A    }
1251062SN/A
1261062SN/A    updateLSQNextCycle = false;
1271062SN/A
1281062SN/A    // @todo: Make into a parameter
1291062SN/A    skidBufferMax = (3 * (renameToIEWDelay * params->renameWidth)) + issueWidth;
1301062SN/A}
1311062SN/A
1321062SN/Atemplate <class Impl>
1331062SN/Astd::string
1341062SN/ADefaultIEW<Impl>::name() const
1351062SN/A{
1361062SN/A    return cpu->name() + ".iew";
1371062SN/A}
1381062SN/A
1391062SN/Atemplate <class Impl>
1401062SN/Avoid
1411062SN/ADefaultIEW<Impl>::regStats()
1421062SN/A{
1431062SN/A    instQueue.regStats();
1441062SN/A
1451062SN/A    //ldstQueue.regStats();
1461062SN/A
1471062SN/A    iewIdleCycles
1481062SN/A        .name(name() + ".iewIdleCycles")
1491062SN/A        .desc("Number of cycles IEW is idle");
1501062SN/A
1511062SN/A    iewSquashCycles
1521062SN/A        .name(name() + ".iewSquashCycles")
1531062SN/A        .desc("Number of cycles IEW is squashing");
1541062SN/A
1551062SN/A    iewBlockCycles
1561062SN/A        .name(name() + ".iewBlockCycles")
1571062SN/A        .desc("Number of cycles IEW is blocking");
1581062SN/A
1591062SN/A    iewUnblockCycles
1601062SN/A        .name(name() + ".iewUnblockCycles")
1612292SN/A        .desc("Number of cycles IEW is unblocking");
1622292SN/A
1632292SN/A//    iewWBInsts;
1642292SN/A
1651062SN/A    iewDispatchedInsts
1661062SN/A        .name(name() + ".iewDispatchedInsts")
1671062SN/A        .desc("Number of instructions dispatched to IQ");
1681062SN/A
1691062SN/A    iewDispSquashedInsts
1701062SN/A        .name(name() + ".iewDispSquashedInsts")
1711062SN/A        .desc("Number of squashed instructions skipped by dispatch");
1722292SN/A
1732292SN/A    iewDispLoadInsts
1742292SN/A        .name(name() + ".iewDispLoadInsts")
1752292SN/A        .desc("Number of dispatched load instructions");
1762292SN/A
1772292SN/A    iewDispStoreInsts
1782292SN/A        .name(name() + ".iewDispStoreInsts")
1792292SN/A        .desc("Number of dispatched store instructions");
1802292SN/A
1812292SN/A    iewDispNonSpecInsts
1822301SN/A        .name(name() + ".iewDispNonSpecInsts")
1832727Sktlim@umich.edu        .desc("Number of dispatched non-speculative instructions");
1842353SN/A
1852727Sktlim@umich.edu    iewIQFullEvents
1862727Sktlim@umich.edu        .name(name() + ".iewIQFullEvents")
1872727Sktlim@umich.edu        .desc("Number of times the IQ has become full, causing a stall");
1886221Snate@binkert.org
1892353SN/A    iewLSQFullEvents
1902727Sktlim@umich.edu        .name(name() + ".iewLSQFullEvents")
1912727Sktlim@umich.edu        .desc("Number of times the LSQ has become full, causing a stall");
1922727Sktlim@umich.edu
1932727Sktlim@umich.edu    iewExecutedInsts
1942353SN/A        .name(name() + ".iewExecutedInsts")
1952727Sktlim@umich.edu        .desc("Number of executed instructions");
1962727Sktlim@umich.edu
1972727Sktlim@umich.edu    iewExecLoadInsts
1986221Snate@binkert.org        .name(name() + ".iewExecLoadInsts")
1998240Snate@binkert.org        .desc("Number of load instructions executed");
2002301SN/A
2012727Sktlim@umich.edu    iewExecStoreInsts
2022301SN/A        .name(name() + ".iewExecStoreInsts")
2032727Sktlim@umich.edu        .desc("Number of store instructions executed");
2046221Snate@binkert.org
2058240Snate@binkert.org    iewExecSquashedInsts
2062301SN/A        .name(name() + ".iewExecSquashedInsts")
2072727Sktlim@umich.edu        .desc("Number of squashed instructions skipped in execute");
2082301SN/A
2092727Sktlim@umich.edu    memOrderViolationEvents
2106221Snate@binkert.org        .name(name() + ".memOrderViolationEvents")
2118240Snate@binkert.org        .desc("Number of memory order violations");
2122301SN/A
2132727Sktlim@umich.edu    predictedTakenIncorrect
2142301SN/A        .name(name() + ".predictedTakenIncorrect")
2152727Sktlim@umich.edu        .desc("Number of branches that were predicted taken incorrectly");
2166221Snate@binkert.org
2178240Snate@binkert.org    predictedNotTakenIncorrect
2182301SN/A        .name(name() + ".predictedNotTakenIncorrect")
2192727Sktlim@umich.edu        .desc("Number of branches that were predicted not taken incorrectly");
2202301SN/A
2212301SN/A    branchMispredicts
2228240Snate@binkert.org        .name(name() + ".branchMispredicts")
2232301SN/A        .desc("Number of branch mispredicts detected at execute");
2242727Sktlim@umich.edu
2252727Sktlim@umich.edu    branchMispredicts = predictedTakenIncorrect + predictedNotTakenIncorrect;
2262727Sktlim@umich.edu}
2272727Sktlim@umich.edu
2288240Snate@binkert.orgtemplate<class Impl>
2292727Sktlim@umich.eduvoid
2302727Sktlim@umich.eduDefaultIEW<Impl>::initStage()
2312727Sktlim@umich.edu{
2322727Sktlim@umich.edu    for (int tid=0; tid < numThreads; tid++) {
2332301SN/A        toRename->iewInfo[tid].usedIQ = true;
2342301SN/A        toRename->iewInfo[tid].freeIQEntries =
2356221Snate@binkert.org            instQueue.numFreeEntries(tid);
2368240Snate@binkert.org
2372301SN/A        toRename->iewInfo[tid].usedLSQ = true;
2382727Sktlim@umich.edu        toRename->iewInfo[tid].freeLSQEntries =
2392301SN/A            ldstQueue.numFreeEntries(tid);
2402326SN/A    }
2416221Snate@binkert.org}
2428240Snate@binkert.org
2432301SN/Atemplate<class Impl>
2442727Sktlim@umich.eduvoid
2452301SN/ADefaultIEW<Impl>::setCPU(FullCPU *cpu_ptr)
2462326SN/A{
2476221Snate@binkert.org    DPRINTF(IEW, "Setting CPU pointer.\n");
2488240Snate@binkert.org    cpu = cpu_ptr;
2492301SN/A
2502727Sktlim@umich.edu    instQueue.setCPU(cpu_ptr);
2512301SN/A    ldstQueue.setCPU(cpu_ptr);
2522326SN/A
2536221Snate@binkert.org    cpu->activateStage(FullCPU::IEWIdx);
2548240Snate@binkert.org}
2552301SN/A
2562727Sktlim@umich.edutemplate<class Impl>
2572301SN/Avoid
2582326SN/ADefaultIEW<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
2596221Snate@binkert.org{
2608240Snate@binkert.org    DPRINTF(IEW, "Setting time buffer pointer.\n");
2612301SN/A    timeBuffer = tb_ptr;
2622727Sktlim@umich.edu
2632301SN/A    // Setup wire to read information from time buffer, from commit.
2642326SN/A    fromCommit = timeBuffer->getWire(-commitToIEWDelay);
2658240Snate@binkert.org
2662301SN/A    // Setup wire to write information back to previous stages.
2672727Sktlim@umich.edu    toRename = timeBuffer->getWire(0);
2682301SN/A
2692326SN/A    toFetch = timeBuffer->getWire(0);
2702301SN/A
2712326SN/A    // Instruction queue also needs main time buffer.
2728240Snate@binkert.org    instQueue.setTimeBuffer(tb_ptr);
2732301SN/A}
2742727Sktlim@umich.edu
2752301SN/Atemplate<class Impl>
2762326SN/Avoid
2772301SN/ADefaultIEW<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
2782326SN/A{
2798240Snate@binkert.org    DPRINTF(IEW, "Setting rename queue pointer.\n");
2802301SN/A    renameQueue = rq_ptr;
2812727Sktlim@umich.edu
2822326SN/A    // Setup wire to read information from rename queue.
2831062SN/A    fromRename = renameQueue->getWire(-renameToIEWDelay);
2841062SN/A}
2851681SN/A
2861060SN/Atemplate<class Impl>
2879427SAndreas.Sandberg@ARM.comvoid
2881060SN/ADefaultIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
2896221Snate@binkert.org{
2902292SN/A    DPRINTF(IEW, "Setting IEW queue pointer.\n");
2912292SN/A    iewQueue = iq_ptr;
2922292SN/A
2932292SN/A    // Setup wire to write instructions to commit.
2942292SN/A    toCommit = iewQueue->getWire(0);
2952292SN/A}
2962292SN/A
2972292SN/Atemplate<class Impl>
2982292SN/Avoid
2998887Sgeoffrey.blake@arm.comDefaultIEW<Impl>::setActiveThreads(list<unsigned> *at_ptr)
3008733Sgeoffrey.blake@arm.com{
3018850Sandreas.hansson@arm.com    DPRINTF(IEW, "Setting active threads list pointer.\n");
3028887Sgeoffrey.blake@arm.com    activeThreads = at_ptr;
3038733Sgeoffrey.blake@arm.com
3042733Sktlim@umich.edu    ldstQueue.setActiveThreads(at_ptr);
3051060SN/A    instQueue.setActiveThreads(at_ptr);
3061060SN/A}
3071681SN/A
3081060SN/Atemplate<class Impl>
3092292SN/Avoid
3101060SN/ADefaultIEW<Impl>::setScoreboard(Scoreboard *sb_ptr)
3111060SN/A{
3121060SN/A    DPRINTF(IEW, "Setting scoreboard pointer.\n");
3131060SN/A    scoreboard = sb_ptr;
3141060SN/A}
3151060SN/A
3161060SN/A#if 0
3171060SN/Atemplate<class Impl>
3181060SN/Avoid
3192292SN/ADefaultIEW<Impl>::setPageTable(PageTable *pt_ptr)
3202292SN/A{
3211060SN/A    ldstQueue.setPageTable(pt_ptr);
3221060SN/A}
3231060SN/A#endif
3241060SN/A
3251681SN/Atemplate<class Impl>
3261060SN/Avoid
3272292SN/ADefaultIEW<Impl>::squash(unsigned tid)
3281060SN/A{
3291060SN/A    DPRINTF(IEW, "[tid:%i]: Squashing all instructions.\n",
3301060SN/A            tid);
3311060SN/A
3321060SN/A    // Tell the IQ to start squashing.
3331060SN/A    instQueue.squash(tid);
3341060SN/A
3351681SN/A    // Tell the LDSTQ to start squashing.
3361060SN/A    ldstQueue.squash(fromCommit->commitInfo[tid].doneSeqNum,tid);
3372292SN/A
3381060SN/A    updatedQueues = true;
3391060SN/A
3401060SN/A    // Clear the skid buffer in case it has any data in it.
3411060SN/A    while (!skidBuffer[tid].empty()) {
3421060SN/A
3431060SN/A        if (skidBuffer[tid].front()->isLoad() ||
3441060SN/A            skidBuffer[tid].front()->isStore() ) {
3451681SN/A            toRename->iewInfo[tid].dispatchedToLSQ++;
3461060SN/A        }
3476221Snate@binkert.org
3481060SN/A        toRename->iewInfo[tid].dispatched++;
3492292SN/A
3502292SN/A        skidBuffer[tid].pop();
3512292SN/A    }
3522292SN/A
3531060SN/A    while (!insts[tid].empty()) {
3541060SN/A        if (insts[tid].front()->isLoad() ||
3551681SN/A            insts[tid].front()->isStore() ) {
3561060SN/A            toRename->iewInfo[tid].dispatchedToLSQ++;
3572292SN/A        }
3581060SN/A
3592292SN/A        toRename->iewInfo[tid].dispatched++;
3601060SN/A
3611060SN/A        insts[tid].pop();
3622307SN/A    }
3632863Sktlim@umich.edu}
3649444SAndreas.Sandberg@ARM.com
3652307SN/Atemplate<class Impl>
3669444SAndreas.Sandberg@ARM.comvoid
3679444SAndreas.Sandberg@ARM.comDefaultIEW<Impl>::squashDueToBranch(DynInstPtr &inst, unsigned tid)
3689444SAndreas.Sandberg@ARM.com{
3699444SAndreas.Sandberg@ARM.com    DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, PC: %#x "
3709444SAndreas.Sandberg@ARM.com            "[sn:%i].\n", tid, inst->readPC(), inst->seqNum);
3719444SAndreas.Sandberg@ARM.com
3729444SAndreas.Sandberg@ARM.com    // Tell rename to squash through the time buffer.
3739444SAndreas.Sandberg@ARM.com    toCommit->squash[tid] = true;
3749444SAndreas.Sandberg@ARM.com    toCommit->squashedSeqNum[tid] = inst->seqNum;
3759444SAndreas.Sandberg@ARM.com    toCommit->mispredPC[tid] = inst->readPC();
3769444SAndreas.Sandberg@ARM.com    toCommit->nextPC[tid] = inst->readNextPC();
3779444SAndreas.Sandberg@ARM.com    toCommit->branchMispredict[tid] = true;
3789444SAndreas.Sandberg@ARM.com    // Prediction was incorrect, so send back inverse.
3799444SAndreas.Sandberg@ARM.com    toCommit->branchTaken[tid] = inst->readNextPC() !=
3801681SN/A        (inst->readPC() + sizeof(TheISA::MachInst));
3811681SN/A
3822316SN/A    toCommit->includeSquashInst[tid] = false;
3831681SN/A    //toCommit->iewSquashNum[tid] = inst->seqNum;
3849444SAndreas.Sandberg@ARM.com
3852843Sktlim@umich.edu    wroteToTimeBuffer = true;
3869444SAndreas.Sandberg@ARM.com}
3872843Sktlim@umich.edu
3889444SAndreas.Sandberg@ARM.comtemplate<class Impl>
3899444SAndreas.Sandberg@ARM.comvoid
3909444SAndreas.Sandberg@ARM.comDefaultIEW<Impl>::squashDueToMemOrder(DynInstPtr &inst, unsigned tid)
3911681SN/A{
3921681SN/A    DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, "
3932307SN/A            "PC: %#x [sn:%i].\n", tid, inst->readPC(), inst->seqNum);
3941681SN/A
3952307SN/A    // Tell rename to squash through the time buffer.
3961060SN/A    toCommit->squash[tid] = true;
3972348SN/A    toCommit->squashedSeqNum[tid] = inst->seqNum;
3982307SN/A    toCommit->nextPC[tid] = inst->readNextPC();
3992307SN/A
4002307SN/A    toCommit->includeSquashInst[tid] = false;
4011060SN/A    //toCommit->iewSquashNum[tid] = inst->seqNum;
4022307SN/A
4032307SN/A    wroteToTimeBuffer = true;
4049444SAndreas.Sandberg@ARM.com}
4051060SN/A
4069427SAndreas.Sandberg@ARM.comtemplate<class Impl>
4072307SN/Avoid
4081060SN/ADefaultIEW<Impl>::squashDueToMemBlocked(DynInstPtr &inst, unsigned tid)
4096221Snate@binkert.org{
4106221Snate@binkert.org    DPRINTF(IEW, "[tid:%i]: Memory blocked, squashing load and younger insts, "
4116221Snate@binkert.org            "PC: %#x [sn:%i].\n", tid, inst->readPC(), inst->seqNum);
4126221Snate@binkert.org
4132307SN/A    toCommit->squash[tid] = true;
4141060SN/A    toCommit->squashedSeqNum[tid] = inst->seqNum;
4152307SN/A    toCommit->nextPC[tid] = inst->readPC();
4162307SN/A
4172873Sktlim@umich.edu    toCommit->includeSquashInst[tid] = true;
4182307SN/A
4191060SN/A    ldstQueue.setLoadBlockedHandled(tid);
4201060SN/A
4211060SN/A    wroteToTimeBuffer = true;
4221681SN/A}
4231060SN/A
4246221Snate@binkert.orgtemplate<class Impl>
4252107SN/Avoid
4266221Snate@binkert.orgDefaultIEW<Impl>::block(unsigned tid)
4272107SN/A{
4282292SN/A    DPRINTF(IEW, "[tid:%u]: Blocking.\n", tid);
4292292SN/A
4302107SN/A    if (dispatchStatus[tid] != Blocked &&
4312292SN/A        dispatchStatus[tid] != Unblocking) {
4322326SN/A        toRename->iewBlock[tid] = true;
4332292SN/A        wroteToTimeBuffer = true;
4342107SN/A    }
4352292SN/A
4362935Sksewell@umich.edu    // Add the current inputs to the skid buffer so they can be
4374632Sgblack@eecs.umich.edu    // reprocessed when this stage unblocks.
4382935Sksewell@umich.edu    skidInsert(tid);
4392292SN/A
4402292SN/A    // Set the status to Blocked.
4412292SN/A    dispatchStatus[tid] = Blocked;
4422292SN/A}
4432292SN/A
4442107SN/Atemplate<class Impl>
4452292SN/Avoid
4462107SN/ADefaultIEW<Impl>::unblock(unsigned tid)
4472292SN/A{
4482292SN/A    DPRINTF(IEW, "[tid:%i]: Reading instructions out of the skid "
4492107SN/A            "buffer %u.\n",tid, tid);
4502702Sktlim@umich.edu
4512107SN/A    // If the skid bufffer is empty, signal back to previous stages to unblock.
4522107SN/A    // Also switch status to running.
4532107SN/A    if (skidBuffer[tid].empty()) {
4542107SN/A        toRename->iewUnblock[tid] = true;
4556221Snate@binkert.org        wroteToTimeBuffer = true;
4562292SN/A        DPRINTF(IEW, "[tid:%i]: Done unblocking.\n",tid);
4577720Sgblack@eecs.umich.edu        dispatchStatus[tid] = Running;
4587720Sgblack@eecs.umich.edu    }
4592292SN/A}
4607852SMatt.Horsnell@arm.com
4617852SMatt.Horsnell@arm.comtemplate<class Impl>
4627852SMatt.Horsnell@arm.comvoid
4637852SMatt.Horsnell@arm.comDefaultIEW<Impl>::wakeDependents(DynInstPtr &inst)
4647852SMatt.Horsnell@arm.com{
4652935Sksewell@umich.edu    instQueue.wakeDependents(inst);
4667852SMatt.Horsnell@arm.com}
4677852SMatt.Horsnell@arm.com
4682292SN/Atemplate<class Impl>
4697852SMatt.Horsnell@arm.comvoid
4707852SMatt.Horsnell@arm.comDefaultIEW<Impl>::rescheduleMemInst(DynInstPtr &inst)
4717852SMatt.Horsnell@arm.com{
4722292SN/A    instQueue.rescheduleMemInst(inst);
4737852SMatt.Horsnell@arm.com}
4747852SMatt.Horsnell@arm.com
4757852SMatt.Horsnell@arm.comtemplate<class Impl>
4762292SN/Avoid
4772292SN/ADefaultIEW<Impl>::replayMemInst(DynInstPtr &inst)
4782292SN/A{
4792292SN/A    instQueue.replayMemInst(inst);
4806221Snate@binkert.org}
4812292SN/A
4828513SGiacomo.Gabrielli@arm.comtemplate<class Impl>
4838513SGiacomo.Gabrielli@arm.comvoid
4848513SGiacomo.Gabrielli@arm.comDefaultIEW<Impl>::instToCommit(DynInstPtr &inst)
4858513SGiacomo.Gabrielli@arm.com{
4868513SGiacomo.Gabrielli@arm.com    // First check the time slot that this instruction will write
4878513SGiacomo.Gabrielli@arm.com    // to.  If there are free write ports at the time, then go ahead
4888513SGiacomo.Gabrielli@arm.com    // and write the instruction to that time.  If there are not,
4898513SGiacomo.Gabrielli@arm.com    // keep looking back to see where's the first time there's a
4908513SGiacomo.Gabrielli@arm.com    // free slot.  What happens if you run out of free spaces?
4918513SGiacomo.Gabrielli@arm.com    // For now naively assume that all instructions take one cycle.
4928513SGiacomo.Gabrielli@arm.com    // Otherwise would have to look into the time buffer based on the
4932292SN/A    // latency of the instruction.
4947852SMatt.Horsnell@arm.com    while ((*iewQueue)[wbCycle].insts[wbNumInst]) {
4958513SGiacomo.Gabrielli@arm.com        ++wbNumInst;
4968137SAli.Saidi@ARM.com        if (wbNumInst == issueWidth) {
4972292SN/A            ++wbCycle;
4988513SGiacomo.Gabrielli@arm.com            wbNumInst = 0;
4998513SGiacomo.Gabrielli@arm.com        }
5002292SN/A
5017852SMatt.Horsnell@arm.com        assert(wbCycle < 5);
5027852SMatt.Horsnell@arm.com    }
5032292SN/A
5042292SN/A    // Add finished instruction to queue to commit.
5052292SN/A    (*iewQueue)[wbCycle].insts[wbNumInst] = inst;
5062292SN/A    (*iewQueue)[wbCycle].size++;
5076221Snate@binkert.org}
5082292SN/A
5092292SN/Atemplate <class Impl>
5107720Sgblack@eecs.umich.eduunsigned
5117852SMatt.Horsnell@arm.comDefaultIEW<Impl>::validInstsFromRename()
5127852SMatt.Horsnell@arm.com{
5137852SMatt.Horsnell@arm.com    unsigned inst_count = 0;
5142292SN/A
5157852SMatt.Horsnell@arm.com    for (int i=0; i<fromRename->size; i++) {
5167852SMatt.Horsnell@arm.com        if (!fromRename->insts[i]->squashed)
5178137SAli.Saidi@ARM.com            inst_count++;
5182292SN/A    }
5197852SMatt.Horsnell@arm.com
5207852SMatt.Horsnell@arm.com    return inst_count;
5212292SN/A}
5227852SMatt.Horsnell@arm.com
5232292SN/Atemplate<class Impl>
5247852SMatt.Horsnell@arm.comvoid
5257852SMatt.Horsnell@arm.comDefaultIEW<Impl>::skidInsert(unsigned tid)
5262292SN/A{
5272292SN/A    DynInstPtr inst = NULL;
5282292SN/A
5292292SN/A    while (!insts[tid].empty()) {
5306221Snate@binkert.org        inst = insts[tid].front();
5312292SN/A
5322292SN/A        insts[tid].pop();
5332292SN/A
5342292SN/A        DPRINTF(Decode,"[tid:%i]: Inserting [sn:%lli] PC:%#x into "
5352292SN/A                "dispatch skidBuffer %i\n",tid, inst->seqNum,
5362292SN/A                inst->readPC(),tid);
5372292SN/A
5382292SN/A        skidBuffer[tid].push(inst);
5392292SN/A    }
5402292SN/A
5412292SN/A    assert(skidBuffer[tid].size() <= skidBufferMax &&
5422292SN/A           "Skidbuffer Exceeded Max Size");
5432292SN/A}
5442292SN/A
5452292SN/Atemplate<class Impl>
5462292SN/Aint
5472292SN/ADefaultIEW<Impl>::skidCount()
5482292SN/A{
5496221Snate@binkert.org    int max=0;
5502292SN/A
5512292SN/A    list<unsigned>::iterator threads = (*activeThreads).begin();
5522292SN/A
5532292SN/A    while (threads != (*activeThreads).end()) {
5542292SN/A        unsigned thread_count = skidBuffer[*threads++].size();
5552292SN/A        if (max < thread_count)
5562292SN/A            max = thread_count;
5572292SN/A    }
5582292SN/A
5592292SN/A    return max;
5602292SN/A}
5612292SN/A
5622292SN/Atemplate<class Impl>
5632292SN/Abool
5642292SN/ADefaultIEW<Impl>::skidsEmpty()
5652292SN/A{
5662292SN/A    list<unsigned>::iterator threads = (*activeThreads).begin();
5671060SN/A
5681681SN/A    while (threads != (*activeThreads).end()) {
5691060SN/A        if (!skidBuffer[*threads++].empty())
5701060SN/A            return false;
5712292SN/A    }
5722292SN/A
5732292SN/A    return true;
5742292SN/A}
5752292SN/A
5762292SN/Atemplate <class Impl>
5771681SN/Avoid
5781681SN/ADefaultIEW<Impl>::updateStatus()
5791060SN/A{
5802292SN/A    bool any_unblocking = false;
5811060SN/A
5822292SN/A    list<unsigned>::iterator threads = (*activeThreads).begin();
5832292SN/A
5841060SN/A    threads = (*activeThreads).begin();
5852292SN/A
5862292SN/A    while (threads != (*activeThreads).end()) {
5872292SN/A        unsigned tid = *threads++;
5882292SN/A
5893221Sktlim@umich.edu        if (dispatchStatus[tid] == Unblocking) {
5903221Sktlim@umich.edu            any_unblocking = true;
5913221Sktlim@umich.edu            break;
5923221Sktlim@umich.edu        }
5933221Sktlim@umich.edu    }
5942292SN/A
5952292SN/A    // If there are no ready instructions waiting to be scheduled by the IQ,
5962292SN/A    // and there's no stores waiting to write back, and dispatch is not
5972292SN/A    // unblocking, then there is no internal activity for the IEW stage.
5982326SN/A    if (_status == Active && !instQueue.hasReadyInsts() &&
5992292SN/A        !ldstQueue.willWB() && !any_unblocking) {
6002292SN/A        DPRINTF(IEW, "IEW switching to idle\n");
6012820Sktlim@umich.edu
6022292SN/A        deactivateStage();
6032292SN/A
6042292SN/A        _status = Inactive;
6052292SN/A    } else if (_status == Inactive && (instQueue.hasReadyInsts() ||
6062353SN/A                                       ldstQueue.willWB() ||
6072292SN/A                                       any_unblocking)) {
6082292SN/A        // Otherwise there is internal activity.  Set to active.
6092353SN/A        DPRINTF(IEW, "IEW switching to active\n");
6102353SN/A
6112292SN/A        activateStage();
6122292SN/A
6132292SN/A        _status = Active;
6142292SN/A    }
6152292SN/A}
6162292SN/A
6172292SN/Atemplate <class Impl>
6182292SN/Avoid
6192292SN/ADefaultIEW<Impl>::resetEntries()
6202292SN/A{
6212292SN/A    instQueue.resetEntries();
6222292SN/A    ldstQueue.resetEntries();
6232731Sktlim@umich.edu}
6242292SN/A
6252292SN/Atemplate <class Impl>
6262292SN/Avoid
6272292SN/ADefaultIEW<Impl>::readStallSignals(unsigned tid)
6282292SN/A{
6292292SN/A    if (fromCommit->commitBlock[tid]) {
6302292SN/A        stalls[tid].commit = true;
6312292SN/A    }
6326221Snate@binkert.org
6332292SN/A    if (fromCommit->commitUnblock[tid]) {
6342292SN/A        assert(stalls[tid].commit);
6352292SN/A        stalls[tid].commit = false;
6362292SN/A    }
6372292SN/A}
6382292SN/A
6392292SN/Atemplate <class Impl>
6402292SN/Abool
6417720Sgblack@eecs.umich.eduDefaultIEW<Impl>::checkStall(unsigned tid)
6422292SN/A{
6437720Sgblack@eecs.umich.edu    bool ret_val(false);
6442292SN/A
6452292SN/A    if (stalls[tid].commit) {
6462292SN/A        DPRINTF(IEW,"[tid:%i]: Stall from Commit stage detected.\n",tid);
6472292SN/A        ret_val = true;
6482292SN/A    } else if (instQueue.isFull(tid)) {
6492292SN/A        DPRINTF(IEW,"[tid:%i]: Stall: IQ  is full.\n",tid);
6502292SN/A        ret_val = true;
6512292SN/A    } else if (ldstQueue.isFull(tid)) {
6522292SN/A        DPRINTF(IEW,"[tid:%i]: Stall: LSQ is full\n",tid);
6532292SN/A
6542292SN/A        if (ldstQueue.numLoads(tid) > 0 ) {
6552292SN/A
6562292SN/A            DPRINTF(IEW,"[tid:%i]: LSQ oldest load: [sn:%i] \n",
6572292SN/A                    tid,ldstQueue.getLoadHeadSeqNum(tid));
6586221Snate@binkert.org        }
6596221Snate@binkert.org
6602292SN/A        if (ldstQueue.numStores(tid) > 0) {
6613867Sbinkertn@umich.edu
6626221Snate@binkert.org            DPRINTF(IEW,"[tid:%i]: LSQ oldest store: [sn:%i] \n",
6633867Sbinkertn@umich.edu                    tid,ldstQueue.getStoreHeadSeqNum(tid));
6642292SN/A        }
6652292SN/A
6662292SN/A        ret_val = true;
6672292SN/A    } else if (ldstQueue.isStalled(tid)) {
6682292SN/A        DPRINTF(IEW,"[tid:%i]: Stall: LSQ stall detected.\n",tid);
6692292SN/A        ret_val = true;
6702292SN/A    }
6712292SN/A
6722292SN/A    return ret_val;
6732292SN/A}
6742292SN/A
6756221Snate@binkert.orgtemplate <class Impl>
6766221Snate@binkert.orgvoid
6772292SN/ADefaultIEW<Impl>::checkSignalsAndUpdate(unsigned tid)
6783867Sbinkertn@umich.edu{
6796221Snate@binkert.org    // Check if there's a squash signal, squash if there is
6803867Sbinkertn@umich.edu    // Check stall signals, block if there is.
6813867Sbinkertn@umich.edu    // If status was Blocked
6822292SN/A    //     if so then go to unblocking
6832292SN/A    // If status was Squashing
6842292SN/A    //     check if squashing is not high.  Switch to running this cycle.
6852292SN/A
6861062SN/A    readStallSignals(tid);
6871062SN/A
6881681SN/A    if (fromCommit->commitInfo[tid].squash) {
6891062SN/A        squash(tid);
6902292SN/A
6911062SN/A        if (dispatchStatus[tid] == Blocked ||
6922292SN/A            dispatchStatus[tid] == Unblocking) {
6931062SN/A            toRename->iewUnblock[tid] = true;
6946221Snate@binkert.org            wroteToTimeBuffer = true;
6956221Snate@binkert.org        }
6961062SN/A
6973867Sbinkertn@umich.edu        dispatchStatus[tid] = Squashing;
6986221Snate@binkert.org
6991062SN/A        fetchRedirect[tid] = false;
7002292SN/A        return;
7012292SN/A    }
7022292SN/A
7032292SN/A    if (fromCommit->commitInfo[tid].robSquashing) {
7042292SN/A        DPRINTF(IEW, "[tid:%i]: ROB is still squashing.\n");
7051062SN/A
7062292SN/A        dispatchStatus[tid] = Squashing;
7072292SN/A
7082292SN/A        return;
7097897Shestness@cs.utexas.edu    }
7102292SN/A
7112292SN/A    if (checkStall(tid)) {
7122292SN/A        block(tid);
7131062SN/A        dispatchStatus[tid] = Blocked;
7142292SN/A        return;
7151062SN/A    }
7162292SN/A
7172292SN/A    if (dispatchStatus[tid] == Blocked) {
7182292SN/A        // Status from previous cycle was blocked, but there are no more stall
7192292SN/A        // conditions.  Switch over to unblocking.
7202292SN/A        DPRINTF(IEW, "[tid:%i]: Done blocking, switching to unblocking.\n",
7212292SN/A                tid);
7221062SN/A
7232292SN/A        dispatchStatus[tid] = Unblocking;
7241062SN/A
7252292SN/A        unblock(tid);
7261062SN/A
7271062SN/A        return;
7281062SN/A    }
7291681SN/A
7301062SN/A    if (dispatchStatus[tid] == Squashing) {
7312292SN/A        // Switch status to running if rename isn't being told to block or
7321062SN/A        // squash this cycle.
7332292SN/A        DPRINTF(IEW, "[tid:%i]: Done squashing, switching to running.\n",
7342292SN/A                tid);
7352292SN/A
7361062SN/A        dispatchStatus[tid] = Running;
7372292SN/A
7382292SN/A        return;
7396221Snate@binkert.org    }
7402292SN/A}
7412292SN/A
7422292SN/Atemplate <class Impl>
7432292SN/Avoid
7441062SN/ADefaultIEW<Impl>::sortInsts()
7452292SN/A{
7462292SN/A    int insts_from_rename = fromRename->size;
7472292SN/A
7482292SN/A    for (int i = 0; i < numThreads; i++)
7492292SN/A        assert(insts[i].empty());
7502292SN/A
7512292SN/A    for (int i = 0; i < insts_from_rename; ++i) {
7522292SN/A        insts[fromRename->insts[i]->threadNumber].push(fromRename->insts[i]);
7536221Snate@binkert.org    }
7542292SN/A}
7552292SN/A
7562292SN/Atemplate <class Impl>
7572292SN/Avoid
7582292SN/ADefaultIEW<Impl>::wakeCPU()
7592292SN/A{
7602292SN/A    cpu->wakeCPU();
7612292SN/A}
7622292SN/A
7632292SN/Atemplate <class Impl>
7642292SN/Avoid
7652292SN/ADefaultIEW<Impl>::activityThisCycle()
7662292SN/A{
7672292SN/A    DPRINTF(Activity, "Activity this cycle.\n");
7682292SN/A    cpu->activityThisCycle();
7692292SN/A}
7702292SN/A
7712292SN/Atemplate <class Impl>
7722292SN/Ainline void
7732292SN/ADefaultIEW<Impl>::activateStage()
7742292SN/A{
7752292SN/A    DPRINTF(Activity, "Activating stage.\n");
7762292SN/A    cpu->activateStage(FullCPU::IEWIdx);
7772292SN/A}
7782292SN/A
7792292SN/Atemplate <class Impl>
7802292SN/Ainline void
7812292SN/ADefaultIEW<Impl>::deactivateStage()
7822292SN/A{
7832292SN/A    DPRINTF(Activity, "Deactivating stage.\n");
7842292SN/A    cpu->deactivateStage(FullCPU::IEWIdx);
7852292SN/A}
7862292SN/A
7872292SN/Atemplate<class Impl>
7882292SN/Avoid
7896221Snate@binkert.orgDefaultIEW<Impl>::dispatch(unsigned tid)
7902292SN/A{
7912292SN/A    // If status is Running or idle,
7922292SN/A    //     call dispatchInsts()
7932292SN/A    // If status is Unblocking,
7942292SN/A    //     buffer any instructions coming from rename
7952292SN/A    //     continue trying to empty skid buffer
7962292SN/A    //     check if stall conditions have passed
7972292SN/A
7982292SN/A    if (dispatchStatus[tid] == Blocked) {
7992292SN/A        ++iewBlockCycles;
8002292SN/A
8012292SN/A    } else if (dispatchStatus[tid] == Squashing) {
8022292SN/A        ++iewSquashCycles;
8032292SN/A    }
8042292SN/A
8052292SN/A    // Dispatch should try to dispatch as many instructions as its bandwidth
8062292SN/A    // will allow, as long as it is not currently blocked.
8072292SN/A    if (dispatchStatus[tid] == Running ||
8082292SN/A        dispatchStatus[tid] == Idle) {
8092292SN/A        DPRINTF(IEW, "[tid:%i] Not blocked, so attempting to run "
8102292SN/A                "dispatch.\n", tid);
8112292SN/A
8122292SN/A        dispatchInsts(tid);
8132292SN/A    } else if (dispatchStatus[tid] == Unblocking) {
8142292SN/A        // Make sure that the skid buffer has something in it if the
8152702Sktlim@umich.edu        // status is unblocking.
8162292SN/A        assert(!skidsEmpty());
8172292SN/A
8182702Sktlim@umich.edu        // If the status was unblocking, then instructions from the skid
8192702Sktlim@umich.edu        // buffer were used.  Remove those instructions and handle
8202292SN/A        // the rest of unblocking.
8212292SN/A        dispatchInsts(tid);
8222292SN/A
8232292SN/A        ++iewUnblockCycles;
8242292SN/A
8252292SN/A        if (validInstsFromRename() && dispatchedAllInsts) {
8262292SN/A            // Add the current inputs to the skid buffer so they can be
8272292SN/A            // reprocessed when this stage unblocks.
8282292SN/A            skidInsert(tid);
8292292SN/A        }
8302292SN/A
8312292SN/A        unblock(tid);
8322292SN/A    }
8332292SN/A}
8342292SN/A
8352292SN/Atemplate <class Impl>
8362292SN/Avoid
8372292SN/ADefaultIEW<Impl>::dispatchInsts(unsigned tid)
8382292SN/A{
8392292SN/A    dispatchedAllInsts = true;
8402292SN/A
8412292SN/A    // Obtain instructions from skid buffer if unblocking, or queue from rename
8422292SN/A    // otherwise.
8432292SN/A    std::queue<DynInstPtr> &insts_to_dispatch =
8442292SN/A        dispatchStatus[tid] == Unblocking ?
8452292SN/A        skidBuffer[tid] : insts[tid];
8462292SN/A
8472292SN/A    int insts_to_add = insts_to_dispatch.size();
8482292SN/A
8492292SN/A    DynInstPtr inst;
8502292SN/A    bool add_to_iq = false;
8512292SN/A    int dis_num_inst = 0;
8522292SN/A
8532292SN/A    // Loop through the instructions, putting them in the instruction
8542292SN/A    // queue.
8552292SN/A    for ( ; dis_num_inst < insts_to_add &&
8562292SN/A              dis_num_inst < issueReadWidth;
8572292SN/A          ++dis_num_inst)
8582292SN/A    {
8592326SN/A        inst = insts_to_dispatch.front();
8606221Snate@binkert.org
8616221Snate@binkert.org        if (dispatchStatus[tid] == Unblocking) {
8622326SN/A            DPRINTF(IEW, "[tid:%i]: Issue: Examining instruction from skid "
8632292SN/A                    "buffer\n", tid);
8642292SN/A        }
8652292SN/A
8662292SN/A        // Make sure there's a valid instruction there.
8672292SN/A        assert(inst);
8682292SN/A
8692292SN/A        DPRINTF(IEW, "[tid:%i]: Issue: Adding PC %#x [sn:%lli] [tid:%i] to "
8706221Snate@binkert.org                "IQ.\n",
8712702Sktlim@umich.edu                tid, inst->readPC(), inst->seqNum, inst->threadNumber);
8724632Sgblack@eecs.umich.edu
8732935Sksewell@umich.edu        // Be sure to mark these instructions as ready so that the
8742702Sktlim@umich.edu        // commit stage can go ahead and execute them, and mark
8752935Sksewell@umich.edu        // them as issued so the IQ doesn't reprocess them.
8762702Sktlim@umich.edu        // -------------
8772702Sktlim@umich.edu        // @TODO: What happens if the ldstqueue is full?
8782702Sktlim@umich.edu        //        Do we process the other instructions?
8792702Sktlim@umich.edu
8802702Sktlim@umich.edu        // Check for squashed instructions.
8812702Sktlim@umich.edu        if (inst->isSquashed()) {
8822702Sktlim@umich.edu            DPRINTF(IEW, "[tid:%i]: Issue: Squashed instruction encountered, "
8832702Sktlim@umich.edu                    "not adding to IQ.\n", tid);
8842702Sktlim@umich.edu
8852702Sktlim@umich.edu            ++iewDispSquashedInsts;
8862702Sktlim@umich.edu
8872702Sktlim@umich.edu            insts_to_dispatch.pop();
8882702Sktlim@umich.edu
8892292SN/A            //Tell Rename That An Instruction has been processed
8902292SN/A            if (inst->isLoad() || inst->isStore()) {
8912292SN/A                toRename->iewInfo[tid].dispatchedToLSQ++;
8922292SN/A            }
8932292SN/A            toRename->iewInfo[tid].dispatched++;
8942292SN/A
8952292SN/A            continue;
8962292SN/A        }
8972292SN/A
8982292SN/A        // Check for full conditions.
8992292SN/A        if (instQueue.isFull(tid)) {
9002292SN/A            DPRINTF(IEW, "[tid:%i]: Issue: IQ has become full.\n", tid);
9012292SN/A
9022292SN/A            // Call function to start blocking.
9032292SN/A            block(tid);
9042292SN/A
9052292SN/A            // Set unblock to false. Special case where we are using
9062292SN/A            // skidbuffer (unblocking) instructions but then we still
9072733Sktlim@umich.edu            // get full in the IQ.
9082292SN/A            toRename->iewUnblock[tid] = false;
9092292SN/A
9102292SN/A            dispatchedAllInsts = false;
9112292SN/A
9122292SN/A            ++iewIQFullEvents;
9132292SN/A            break;
9142292SN/A        } else if (ldstQueue.isFull(tid)) {
9152733Sktlim@umich.edu            DPRINTF(IEW, "[tid:%i]: Issue: LSQ has become full.\n",tid);
9162292SN/A
9172292SN/A            // Call function to start blocking.
9182292SN/A            block(tid);
9192292SN/A
9206221Snate@binkert.org            // Set unblock to false. Special case where we are using
9212292SN/A            // skidbuffer (unblocking) instructions but then we still
9222292SN/A            // get full in the IQ.
9232292SN/A            toRename->iewUnblock[tid] = false;
9242292SN/A
9252292SN/A            dispatchedAllInsts = false;
9262292SN/A
9272292SN/A            ++iewLSQFullEvents;
9282292SN/A            break;
9292292SN/A        }
9302292SN/A
9312292SN/A        // Otherwise issue the instruction just fine.
9322292SN/A        if (inst->isLoad()) {
9332292SN/A            DPRINTF(IEW, "[tid:%i]: Issue: Memory instruction "
9342292SN/A                    "encountered, adding to LSQ.\n", tid);
9352292SN/A
9362292SN/A            // Reserve a spot in the load store queue for this
9372292SN/A            // memory access.
9382292SN/A            ldstQueue.insertLoad(inst);
9392292SN/A
9402292SN/A            ++iewDispLoadInsts;
9412292SN/A
9422292SN/A            add_to_iq = true;
9432292SN/A
9442292SN/A            toRename->iewInfo[tid].dispatchedToLSQ++;
9452292SN/A        } else if (inst->isStore()) {
9462292SN/A            DPRINTF(IEW, "[tid:%i]: Issue: Memory instruction "
9472292SN/A                    "encountered, adding to LSQ.\n", tid);
9482292SN/A
9492292SN/A            ldstQueue.insertStore(inst);
9502292SN/A
9512292SN/A            ++iewDispStoreInsts;
9522292SN/A
9532292SN/A            if (inst->isNonSpeculative()) {
9542292SN/A                inst->setCanCommit();
9552292SN/A                instQueue.insertNonSpec(inst);
9565215Sgblack@eecs.umich.edu                add_to_iq = false;
9572292SN/A
9582292SN/A                ++iewDispNonSpecInsts;
9592292SN/A            } else {
9602292SN/A                add_to_iq = true;
9612292SN/A            }
9622292SN/A
9632292SN/A            toRename->iewInfo[tid].dispatchedToLSQ++;
9642292SN/A#if FULL_SYSTEM
9652292SN/A        } else if (inst->isMemBarrier() || inst->isWriteBarrier()) {
9662292SN/A            inst->setCanCommit();
9672292SN/A            instQueue.insertBarrier(inst);
9686221Snate@binkert.org            add_to_iq = false;
9692292SN/A#endif
9702292SN/A        } else if (inst->isNonSpeculative()) {
9712292SN/A            DPRINTF(IEW, "[tid:%i]: Issue: Nonspeculative instruction "
9722292SN/A                    "encountered, skipping.\n", tid);
9732292SN/A
9742292SN/A            // Same hack as with stores.
9752292SN/A            inst->setCanCommit();
9762292SN/A
9772292SN/A            // Specifically insert it as nonspeculative.
9782292SN/A            instQueue.insertNonSpec(inst);
9792292SN/A
9802292SN/A            ++iewDispNonSpecInsts;
9812292SN/A
9822292SN/A            add_to_iq = false;
9832292SN/A        } else if (inst->isNop()) {
9842292SN/A            DPRINTF(IEW, "[tid:%i]: Issue: Nop instruction encountered, "
9852820Sktlim@umich.edu                    "skipping.\n", tid);
9862292SN/A
9872292SN/A            inst->setIssued();
9882292SN/A            inst->setExecuted();
9892292SN/A            inst->setCanCommit();
9902292SN/A
9912292SN/A            instQueue.advanceTail(inst);
9922292SN/A
9932292SN/A            add_to_iq = false;
9942292SN/A        } else if (inst->isExecuted()) {
9952292SN/A            assert(0 && "Instruction shouldn't be executed.\n");
9962292SN/A            DPRINTF(IEW, "Issue: Executed branch encountered, "
9972292SN/A                    "skipping.\n");
9987720Sgblack@eecs.umich.edu
9992292SN/A            inst->setIssued();
10007720Sgblack@eecs.umich.edu            inst->setCanCommit();
10012292SN/A
10022292SN/A            instQueue.advanceTail(inst);
10032292SN/A
10042292SN/A            add_to_iq = false;
10052292SN/A        } else {
10062292SN/A            add_to_iq = true;
10072292SN/A        }
10082292SN/A
10092292SN/A        // If the instruction queue is not full, then add the
10102292SN/A        // instruction.
10112292SN/A        if (add_to_iq) {
10122292SN/A            instQueue.insert(inst);
10132292SN/A        }
10142292SN/A
10152292SN/A        insts_to_dispatch.pop();
10162292SN/A
10172292SN/A        toRename->iewInfo[tid].dispatched++;
10182292SN/A
10192292SN/A        ++iewDispatchedInsts;
10202292SN/A    }
10212292SN/A
10222292SN/A    if (!insts_to_dispatch.empty()) {
10232292SN/A        DPRINTF(IEW,"[tid:%i]: Issue: Bandwidth Full. Blocking.\n");
10242292SN/A        block(tid);
10252292SN/A        toRename->iewUnblock[tid] = false;
10262292SN/A    }
10272292SN/A
10282292SN/A    if (dispatchStatus[tid] == Idle && dis_num_inst) {
10292292SN/A        dispatchStatus[tid] = Running;
10302292SN/A
10312292SN/A        updatedQueues = true;
10322292SN/A    }
10332292SN/A
10342292SN/A    dis_num_inst = 0;
10352292SN/A}
10362292SN/A
10372292SN/Atemplate <class Impl>
10382292SN/Avoid
10392292SN/ADefaultIEW<Impl>::printAvailableInsts()
10402292SN/A{
10412292SN/A    int inst = 0;
10422292SN/A
10432292SN/A    cout << "Available Instructions: ";
10442292SN/A
10452292SN/A    while (fromIssue->insts[inst]) {
10462292SN/A
10472292SN/A        if (inst%3==0) cout << "\n\t";
10482292SN/A
10492292SN/A        cout << "PC: " << fromIssue->insts[inst]->readPC()
10502292SN/A             << " TN: " << fromIssue->insts[inst]->threadNumber
10512292SN/A             << " SN: " << fromIssue->insts[inst]->seqNum << " | ";
10522292SN/A
10532292SN/A        inst++;
10542292SN/A
10552292SN/A    }
10562292SN/A
10572292SN/A    cout << "\n";
10582292SN/A}
10592292SN/A
10602292SN/Atemplate <class Impl>
10612292SN/Avoid
10622292SN/ADefaultIEW<Impl>::executeInsts()
10632292SN/A{
10642292SN/A    //bool fetch_redirect[(*activeThreads).size()];
10652292SN/A    wbNumInst = 0;
10662292SN/A    wbCycle = 0;
10672292SN/A
10682292SN/A    list<unsigned>::iterator threads = (*activeThreads).begin();
10692292SN/A
10702292SN/A    while (threads != (*activeThreads).end()) {
10712292SN/A        unsigned tid = *threads++;
10722292SN/A        fetchRedirect[tid] = false;
10732292SN/A    }
10742292SN/A
10752336SN/A#if 0
10762336SN/A    printAvailableInsts();
10772336SN/A#endif
10782336SN/A
10792348SN/A    // Execute/writeback any instructions that are available.
10802292SN/A    int inst_num = 0;
10812292SN/A    for ( ; inst_num < issueWidth &&  /* Haven't exceeded issue bandwidth */
10822292SN/A              fromIssue->insts[inst_num];
10832292SN/A         ++inst_num) {
10842292SN/A
10852292SN/A        DPRINTF(IEW, "Execute: Executing instructions from IQ.\n");
10862292SN/A
10872292SN/A        // Get instruction from issue's queue.
10882292SN/A        DynInstPtr inst = fromIssue->insts[inst_num];
10892292SN/A
10902292SN/A        DPRINTF(IEW, "Execute: Processing PC %#x, [tid:%i] [sn:%i].\n",
10912326SN/A                inst->readPC(), inst->threadNumber,inst->seqNum);
10922292SN/A
10932292SN/A        // Check if the instruction is squashed; if so then skip it
10942292SN/A        // and don't count it towards the FU usage.
10952292SN/A        if (inst->isSquashed()) {
10962292SN/A            DPRINTF(IEW, "Execute: Instruction was squashed.\n");
10972292SN/A
10982292SN/A            // Consider this instruction executed so that commit can go
10992292SN/A            // ahead and retire the instruction.
11002292SN/A            inst->setExecuted();
11012292SN/A
11022292SN/A            // Not sure if I should set this here or just let commit try to
11032326SN/A            // commit any squashed instructions.  I like the latter a bit more.
11042292SN/A            inst->setCanCommit();
11052727Sktlim@umich.edu
11062301SN/A            ++iewExecSquashedInsts;
11072292SN/A
11082292SN/A            continue;
11092292SN/A        }
11102292SN/A
11112292SN/A        Fault fault = NoFault;
11122292SN/A
11132292SN/A        // Execute instruction.
11142292SN/A        // Note that if the instruction faults, it will be handled
11152292SN/A        // at the commit stage.
11162326SN/A        if (inst->isMemRef() &&
11172292SN/A            (!inst->isDataPrefetch() && !inst->isInstPrefetch())) {
11182292SN/A            DPRINTF(IEW, "Execute: Calculating address for memory "
11192292SN/A                    "reference.\n");
11202292SN/A
11212292SN/A            // Tell the LDSTQ to execute this instruction (if it is a load).
11224033Sktlim@umich.edu            if (inst->isLoad()) {
11234033Sktlim@umich.edu                // Loads will mark themselves as executed, and their writeback
11244033Sktlim@umich.edu                // event adds the instruction to the queue to commit
11254033Sktlim@umich.edu                fault = ldstQueue.executeLoad(inst);
11264033Sktlim@umich.edu
11274033Sktlim@umich.edu                ++iewExecLoadInsts;
11284033Sktlim@umich.edu            } else if (inst->isStore()) {
11294033Sktlim@umich.edu                ldstQueue.executeStore(inst);
11304033Sktlim@umich.edu
11314033Sktlim@umich.edu                ++iewExecStoreInsts;
11324033Sktlim@umich.edu
11334033Sktlim@umich.edu                // If the store had a fault then it may not have a mem req
11344033Sktlim@umich.edu                if (inst->req && !(inst->req->flags & LOCKED)) {
11354033Sktlim@umich.edu                    inst->setExecuted();
11362292SN/A
11372292SN/A                    instToCommit(inst);
11382292SN/A                }
11392292SN/A                // Store conditionals will mark themselves as executed, and
11402292SN/A                // their writeback event will add the instruction to the queue
11412292SN/A                // to commit.
11422292SN/A            } else {
11432292SN/A                panic("Unexpected memory type!\n");
11442292SN/A            }
11452292SN/A
11462292SN/A        } else {
11472292SN/A            inst->execute();
11488471SGiacomo.Gabrielli@arm.com
11498471SGiacomo.Gabrielli@arm.com            ++iewExecutedInsts;
11509046SAli.Saidi@ARM.com
11518471SGiacomo.Gabrielli@arm.com            inst->setExecuted();
11522292SN/A
11532292SN/A            instToCommit(inst);
11542292SN/A        }
11552935Sksewell@umich.edu
11562292SN/A        // Check if branch was correct.  This check happens after the
11572292SN/A        // instruction is added to the queue because even if the branch
11582292SN/A        // is mispredicted, the branch instruction itself is still valid.
11592292SN/A        // Only handle this if there hasn't already been something that
11602292SN/A        // redirects fetch in this group of instructions.
11612292SN/A
11622292SN/A        // This probably needs to prioritize the redirects if a different
11632292SN/A        // scheduler is used.  Currently the scheduler schedules the oldest
11642292SN/A        // instruction first, so the branch resolution order will be correct.
11652292SN/A        unsigned tid = inst->threadNumber;
11662292SN/A
11672292SN/A        if (!fetchRedirect[tid]) {
11682292SN/A
11692292SN/A            if (inst->mispredicted()) {
11702292SN/A                fetchRedirect[tid] = true;
11712292SN/A
11722292SN/A                DPRINTF(IEW, "Execute: Branch mispredict detected.\n");
11732292SN/A                DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x.\n",
11742292SN/A                        inst->nextPC);
11752980Sgblack@eecs.umich.edu
11762292SN/A                // If incorrect, then signal the ROB that it must be squashed.
11772292SN/A                squashDueToBranch(inst, tid);
11782292SN/A
11792980Sgblack@eecs.umich.edu                if (inst->predTaken()) {
11802292SN/A                    predictedTakenIncorrect++;
11817720Sgblack@eecs.umich.edu                } else {
11822292SN/A                    predictedNotTakenIncorrect++;
11832292SN/A                }
11842292SN/A            } else if (ldstQueue.violation(tid)) {
11852292SN/A                fetchRedirect[tid] = true;
11862292SN/A
11872292SN/A                // Get the DynInst that caused the violation.  Note that this
11882292SN/A                // clears the violation signal.
11892980Sgblack@eecs.umich.edu                DynInstPtr violator;
11902292SN/A                violator = ldstQueue.getMemDepViolator(tid);
11912292SN/A
11922292SN/A                DPRINTF(IEW, "LDSTQ detected a violation.  Violator PC: "
11932292SN/A                        "%#x, inst PC: %#x.  Addr is: %#x.\n",
11942292SN/A                        violator->readPC(), inst->readPC(), inst->physEffAddr);
11952292SN/A
11962292SN/A                // Tell the instruction queue that a violation has occured.
11972292SN/A                instQueue.violation(inst, violator);
11982292SN/A
11996221Snate@binkert.org                // Squash.
12006221Snate@binkert.org                squashDueToMemOrder(inst,tid);
12012292SN/A
12023867Sbinkertn@umich.edu                ++memOrderViolationEvents;
12036221Snate@binkert.org            } else if (ldstQueue.loadBlocked(tid) &&
12042292SN/A                       !ldstQueue.isLoadBlockedHandled(tid)) {
12052292SN/A                fetchRedirect[tid] = true;
12062292SN/A
12072698Sktlim@umich.edu                DPRINTF(IEW, "Load operation couldn't execute because the "
12087599Sminkyu.jeong@arm.com                        "memory system is blocked.  PC: %#x [sn:%lli]\n",
12092698Sktlim@umich.edu                        inst->readPC(), inst->seqNum);
12101062SN/A
12111062SN/A                squashDueToMemBlocked(inst, tid);
12122333SN/A            }
12132292SN/A        }
12142333SN/A    }
12152326SN/A
12161062SN/A    if (inst_num) {
12172292SN/A        if (exeStatus == Idle) {
12181062SN/A            exeStatus = Running;
12192333SN/A        }
12201062SN/A
12217720Sgblack@eecs.umich.edu        updatedQueues = true;
12227720Sgblack@eecs.umich.edu
12231062SN/A        cpu->activityThisCycle();
12241062SN/A    }
12251062SN/A
12268315Sgeoffrey.blake@arm.com    // Need to reset this in case a writeback event needs to write into the
12278315Sgeoffrey.blake@arm.com    // iew queue.  That way the writeback event will write into the correct
12288315Sgeoffrey.blake@arm.com    // spot in the queue.
12291062SN/A    wbNumInst = 0;
12301062SN/A}
12311062SN/A
12321062SN/Atemplate <class Impl>
12331062SN/Avoid
12342292SN/ADefaultIEW<Impl>::writebackInsts()
12352292SN/A{
12362292SN/A    // Loop through the head of the time buffer and wake any dependents.
12371062SN/A    // These instructions are about to write back.  In the simple model
12381062SN/A    // this loop can really happen within the previous loop, but when
12391062SN/A    // instructions have actual latencies, this loop must be separate.
12402820Sktlim@umich.edu    // Also mark scoreboard that this instruction is finally complete.
12411062SN/A    // Either have IEW have direct access to rename map, or have this as
12421062SN/A    // part of backwards communication.
12431062SN/A    for (int inst_num = 0; inst_num < issueWidth &&
12442292SN/A             toCommit->insts[inst_num]; inst_num++) {
12451062SN/A        DynInstPtr inst = toCommit->insts[inst_num];
12461062SN/A
12471062SN/A        DPRINTF(IEW, "Sending instructions to commit, PC %#x.\n",
12481062SN/A                inst->readPC());
12497850SMatt.Horsnell@arm.com
12502292SN/A        // Some instructions will be sent to commit without having
12511062SN/A        // executed because they need commit to handle them.
12521062SN/A        // E.g. Uncached loads have not actually executed when they
12531062SN/A        // are first sent to commit.  Instead commit must tell the LSQ
12541062SN/A        // when it's ready to execute the uncached load.
12552292SN/A        if (!inst->isSquashed() && inst->isExecuted()) {
12562292SN/A            instQueue.wakeDependents(inst);
12572292SN/A
12587944SGiacomo.Gabrielli@arm.com            for (int i = 0; i < inst->numDestRegs(); i++) {
12597944SGiacomo.Gabrielli@arm.com                //mark as Ready
12607944SGiacomo.Gabrielli@arm.com                DPRINTF(IEW,"Setting Destination Register %i\n",
12617944SGiacomo.Gabrielli@arm.com                        inst->renamedDestRegIdx(i));
12627944SGiacomo.Gabrielli@arm.com                scoreboard->setReg(inst->renamedDestRegIdx(i));
12637944SGiacomo.Gabrielli@arm.com            }
12647944SGiacomo.Gabrielli@arm.com        }
12657944SGiacomo.Gabrielli@arm.com    }
12667944SGiacomo.Gabrielli@arm.com}
12677944SGiacomo.Gabrielli@arm.com
12687944SGiacomo.Gabrielli@arm.comtemplate<class Impl>
12697850SMatt.Horsnell@arm.comvoid
12708073SAli.Saidi@ARM.comDefaultIEW<Impl>::tick()
12717850SMatt.Horsnell@arm.com{
12721062SN/A    // Try to fill up issue queue with as many instructions as bandwidth
12732367SN/A    // allows.
12741062SN/A    wbNumInst = 0;
12757944SGiacomo.Gabrielli@arm.com    wbCycle = 0;
12767944SGiacomo.Gabrielli@arm.com
12777944SGiacomo.Gabrielli@arm.com    wroteToTimeBuffer = false;
12787944SGiacomo.Gabrielli@arm.com    updatedQueues = false;
12797944SGiacomo.Gabrielli@arm.com
12807944SGiacomo.Gabrielli@arm.com    sortInsts();
12817944SGiacomo.Gabrielli@arm.com
12827944SGiacomo.Gabrielli@arm.com    list<unsigned>::iterator threads = (*activeThreads).begin();
12837944SGiacomo.Gabrielli@arm.com
12847944SGiacomo.Gabrielli@arm.com    // Check stall and squash signals.
12852292SN/A    while (threads != (*activeThreads).end()) {
12867782Sminkyu.jeong@arm.com           unsigned tid = *threads++;
12877782Sminkyu.jeong@arm.com
12887782Sminkyu.jeong@arm.com        DPRINTF(IEW,"Issue: Processing [tid:%i]\n",tid);
12897782Sminkyu.jeong@arm.com
12902367SN/A        checkSignalsAndUpdate(tid);
12912367SN/A        dispatch(tid);
12922367SN/A
12932367SN/A    }
12942367SN/A
12952292SN/A    if (exeStatus != Squashing) {
12962326SN/A        executeInsts();
12972326SN/A
12982326SN/A        writebackInsts();
12992326SN/A
13001062SN/A        // Have the instruction queue try to schedule any ready instructions.
13012292SN/A        // (In actuality, this scheduling is for instructions that will
13021062SN/A        // be executed next cycle.)
13031062SN/A        instQueue.scheduleReadyInsts();
13041062SN/A
13057847Sminkyu.jeong@arm.com        // Also should advance its own time buffers if the stage ran.
13067847Sminkyu.jeong@arm.com        // Not the best place for it, but this works (hopefully).
13077847Sminkyu.jeong@arm.com        issueToExecQueue.advance();
13087847Sminkyu.jeong@arm.com    }
13097847Sminkyu.jeong@arm.com
13107847Sminkyu.jeong@arm.com    bool broadcast_free_entries = false;
13117848SAli.Saidi@ARM.com
13127848SAli.Saidi@ARM.com    if (updatedQueues || exeStatus == Running || updateLSQNextCycle) {
13137847Sminkyu.jeong@arm.com        exeStatus = Idle;
13141062SN/A        updateLSQNextCycle = false;
13152292SN/A
13162292SN/A        broadcast_free_entries = true;
13172292SN/A    }
13181062SN/A
13191062SN/A    // Writeback any stores using any leftover bandwidth.
13202301SN/A    ldstQueue.writebackStores();
13211681SN/A
13222326SN/A    // Free function units marked as being freed this cycle.
13232326SN/A    fuPool->processFreeUnits();
13242326SN/A
13252107SN/A    // Check the committed load/store signals to see if there's a load
13261681SN/A    // or store to commit.  Also check if it's being told to execute a
13272292SN/A    // nonspeculative instruction.
13282292SN/A    // This is pretty inefficient...
13292292SN/A
13306221Snate@binkert.org    threads = (*activeThreads).begin();
13311062SN/A    while (threads != (*activeThreads).end()) {
13323732Sktlim@umich.edu        unsigned tid = (*threads++);
13337852SMatt.Horsnell@arm.com
13343732Sktlim@umich.edu        DPRINTF(IEW,"Processing [tid:%i]\n",tid);
13351062SN/A
13367856SMatt.Horsnell@arm.com        if (fromCommit->commitInfo[tid].doneSeqNum != 0 &&
13377856SMatt.Horsnell@arm.com            !fromCommit->commitInfo[tid].squash &&
13387856SMatt.Horsnell@arm.com            !fromCommit->commitInfo[tid].robSquashing) {
13397856SMatt.Horsnell@arm.com
13407856SMatt.Horsnell@arm.com            ldstQueue.commitStores(fromCommit->commitInfo[tid].doneSeqNum,tid);
13412292SN/A
13421062SN/A            ldstQueue.commitLoads(fromCommit->commitInfo[tid].doneSeqNum,tid);
13432292SN/A
13448674Snilay@cs.wisc.edu            updateLSQNextCycle = true;
13458674Snilay@cs.wisc.edu            instQueue.commit(fromCommit->commitInfo[tid].doneSeqNum,tid);
13467720Sgblack@eecs.umich.edu        }
13478674Snilay@cs.wisc.edu
13481062SN/A        if (fromCommit->commitInfo[tid].nonSpecSeqNum != 0) {
13492292SN/A
13501062SN/A            //DPRINTF(IEW,"NonspecInst from thread %i",tid);
13513795Sgblack@eecs.umich.edu            if (fromCommit->commitInfo[tid].uncached) {
13521062SN/A                instQueue.replayMemInst(fromCommit->commitInfo[tid].uncachedLoad);
13532292SN/A            } else {
13542292SN/A                instQueue.scheduleNonSpec(
13551062SN/A                    fromCommit->commitInfo[tid].nonSpecSeqNum);
13562292SN/A            }
13574033Sktlim@umich.edu        }
13582326SN/A
13592326SN/A        if (broadcast_free_entries) {
13602292SN/A            toFetch->iewInfo[tid].iqCount =
13612292SN/A                instQueue.getCount(tid);
13622292SN/A            toFetch->iewInfo[tid].ldstqCount =
13631062SN/A                ldstQueue.getCount(tid);
13647720Sgblack@eecs.umich.edu
13657720Sgblack@eecs.umich.edu            toRename->iewInfo[tid].usedIQ = true;
13667720Sgblack@eecs.umich.edu            toRename->iewInfo[tid].freeIQEntries =
13677720Sgblack@eecs.umich.edu                instQueue.numFreeEntries();
13687720Sgblack@eecs.umich.edu            toRename->iewInfo[tid].usedLSQ = true;
13693732Sktlim@umich.edu            toRename->iewInfo[tid].freeLSQEntries =
13703732Sktlim@umich.edu                ldstQueue.numFreeEntries(tid);
13711062SN/A
13721062SN/A            wroteToTimeBuffer = true;
13731062SN/A        }
13741062SN/A
13758513SGiacomo.Gabrielli@arm.com        DPRINTF(IEW, "[tid:%i], Dispatch dispatched %i instructions.\n",
13761062SN/A                tid, toRename->iewInfo[tid].dispatched);
13771062SN/A
13782292SN/A        //thread_queue.pop();
13792292SN/A    }
13802292SN/A
13812292SN/A    DPRINTF(IEW, "IQ has %i free entries (Can schedule: %i).  "
13822292SN/A            "LSQ has %i free entries.\n",
13837720Sgblack@eecs.umich.edu            instQueue.numFreeEntries(), instQueue.hasReadyInsts(),
13847720Sgblack@eecs.umich.edu            ldstQueue.numFreeEntries());
13852292SN/A
13862292SN/A    updateStatus();
13871062SN/A
13884033Sktlim@umich.edu    if (wroteToTimeBuffer) {
13894033Sktlim@umich.edu        DPRINTF(Activity, "Activity this cycle.\n");
13904033Sktlim@umich.edu        cpu->activityThisCycle();
13914033Sktlim@umich.edu    }
13924033Sktlim@umich.edu}
13934033Sktlim@umich.edu