iew_impl.hh revision 1717
11689SN/A/*
29783Sandreas.hansson@arm.com * Copyright (c) 2004-2005 The Regents of The University of Michigan
310239Sbinhpham@cs.rutgers.edu * 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
147598Sminkyu.jeong@arm.com * this software without specific prior written permission.
152326SN/A *
161689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
181689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
191689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
201689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
211689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
221689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
231689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
241689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
251689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
261689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
271689SN/A */
281689SN/A
291689SN/A// @todo: Fix the instantaneous communication among all the stages within
301689SN/A// iew.  There's a clear delay between issue and execute, yet backwards
311689SN/A// communication happens simultaneously.
321689SN/A// Update the statuses for each stage.
331689SN/A
341689SN/A#include <queue>
351689SN/A
361689SN/A#include "base/timebuf.hh"
371689SN/A#include "cpu/o3/iew.hh"
381689SN/A
391689SN/Atemplate<class Impl>
402665Ssaidi@eecs.umich.eduSimpleIEW<Impl>::WritebackEvent::WritebackEvent(DynInstPtr &_inst,
412665Ssaidi@eecs.umich.edu                                                SimpleIEW<Impl> *_iew)
421689SN/A    : Event(&mainEventQueue, CPU_Tick_Pri), inst(_inst), iewStage(_iew)
431689SN/A{
449944Smatt.horsnell@ARM.com    this->setFlags(Event::AutoDelete);
459944Smatt.horsnell@ARM.com}
469944Smatt.horsnell@ARM.com
471060SN/Atemplate<class Impl>
481060SN/Avoid
491689SN/ASimpleIEW<Impl>::WritebackEvent::process()
501060SN/A{
511060SN/A    DPRINTF(IEW, "IEW: WRITEBACK EVENT!!!!\n");
521060SN/A
538230Snate@binkert.org    // Need to insert instruction into queue to commit
546658Snate@binkert.org    iewStage->instToCommit(inst);
558887Sgeoffrey.blake@arm.com    // Need to execute second half of the instruction, do actual writing to
562292SN/A    // registers and such
571717SN/A    inst->execute();
588229Snate@binkert.org}
598232Snate@binkert.org
609444SAndreas.Sandberg@ARM.comtemplate<class Impl>
618232Snate@binkert.orgconst char *
629527SMatt.Horsnell@arm.comSimpleIEW<Impl>::WritebackEvent::description()
635529Snate@binkert.org{
641060SN/A    return "LSQ writeback event";
656221Snate@binkert.org}
666221Snate@binkert.org
671681SN/Atemplate<class Impl>
685529Snate@binkert.orgSimpleIEW<Impl>::SimpleIEW(Params &params)
692873Sktlim@umich.edu    : // Just make this time buffer really big for now
704329Sktlim@umich.edu      issueToExecQueue(5, 5),
714329Sktlim@umich.edu      instQueue(params),
724329Sktlim@umich.edu      ldstQueue(params),
732292SN/A      commitToIEWDelay(params.commitToIEWDelay),
742292SN/A      renameToIEWDelay(params.renameToIEWDelay),
752292SN/A      issueToExecuteDelay(params.issueToExecuteDelay),
762292SN/A      issueReadWidth(params.issueWidth),
772820Sktlim@umich.edu      issueWidth(params.issueWidth),
782292SN/A      executeWidth(params.executeWidth)
792820Sktlim@umich.edu{
802820Sktlim@umich.edu    DPRINTF(IEW, "IEW: executeIntWidth: %i.\n", params.executeIntWidth);
819444SAndreas.Sandberg@ARM.com    _status = Idle;
821060SN/A    _issueStatus = Idle;
8310172Sdam.sunwoo@arm.com    _exeStatus = Idle;
8410172Sdam.sunwoo@arm.com    _wbStatus = Idle;
8510172Sdam.sunwoo@arm.com
8610172Sdam.sunwoo@arm.com    // Setup wire to read instructions coming from issue.
8710172Sdam.sunwoo@arm.com    fromIssue = issueToExecQueue.getWire(-issueToExecuteDelay);
8810172Sdam.sunwoo@arm.com
8910172Sdam.sunwoo@arm.com    // Instruction queue needs the queue between issue and execute.
9010172Sdam.sunwoo@arm.com    instQueue.setIssueToExecuteQueue(&issueToExecQueue);
9110172Sdam.sunwoo@arm.com
9210172Sdam.sunwoo@arm.com    ldstQueue.setIEW(this);
9310172Sdam.sunwoo@arm.com}
9410172Sdam.sunwoo@arm.com
9510172Sdam.sunwoo@arm.comtemplate <class Impl>
962292SN/Avoid
972292SN/ASimpleIEW<Impl>::regStats()
982292SN/A{
991060SN/A    instQueue.regStats();
1001060SN/A
1011060SN/A    iewIdleCycles
1021060SN/A        .name(name() + ".iewIdleCycles")
1031060SN/A        .desc("Number of cycles IEW is idle");
1041060SN/A
1051681SN/A    iewSquashCycles
1066221Snate@binkert.org        .name(name() + ".iewSquashCycles")
1076221Snate@binkert.org        .desc("Number of cycles IEW is squashing");
1086221Snate@binkert.org
1096221Snate@binkert.org    iewBlockCycles
1102292SN/A        .name(name() + ".iewBlockCycles")
1112292SN/A        .desc("Number of cycles IEW is blocking");
1122820Sktlim@umich.edu
1132820Sktlim@umich.edu    iewUnblockCycles
1142292SN/A        .name(name() + ".iewUnblockCycles")
1152292SN/A        .desc("Number of cycles IEW is unblocking");
1162820Sktlim@umich.edu
1172820Sktlim@umich.edu//    iewWBInsts;
1182292SN/A
1192292SN/A    iewDispatchedInsts
1202292SN/A        .name(name() + ".iewDispatchedInsts")
1212292SN/A        .desc("Number of instructions dispatched to IQ");
1222292SN/A
1232292SN/A    iewDispSquashedInsts
1242292SN/A        .name(name() + ".iewDispSquashedInsts")
1252292SN/A        .desc("Number of squashed instructions skipped by dispatch");
1261060SN/A
1271060SN/A    iewDispLoadInsts
1281681SN/A        .name(name() + ".iewDispLoadInsts")
1291062SN/A        .desc("Number of dispatched load instructions");
13010023Smatt.horsnell@ARM.com
13110023Smatt.horsnell@ARM.com    iewDispStoreInsts
13210023Smatt.horsnell@ARM.com        .name(name() + ".iewDispStoreInsts")
13310023Smatt.horsnell@ARM.com        .desc("Number of dispatched store instructions");
13410023Smatt.horsnell@ARM.com
13510023Smatt.horsnell@ARM.com    iewDispNonSpecInsts
13610023Smatt.horsnell@ARM.com        .name(name() + ".iewDispNonSpecInsts")
13710023Smatt.horsnell@ARM.com        .desc("Number of dispatched non-speculative instructions");
1382292SN/A
1391062SN/A    iewIQFullEvents
1402301SN/A        .name(name() + ".iewIQFullEvents")
1412301SN/A        .desc("Number of times the IQ has become full, causing a stall");
1421062SN/A
1432727Sktlim@umich.edu    iewExecutedInsts
1441062SN/A        .name(name() + ".iewExecutedInsts")
1451062SN/A        .desc("Number of executed instructions");
1461062SN/A
1471062SN/A    iewExecLoadInsts
1481062SN/A        .name(name() + ".iewExecLoadInsts")
1491062SN/A        .desc("Number of load instructions executed");
1501062SN/A
1511062SN/A    iewExecStoreInsts
1521062SN/A        .name(name() + ".iewExecStoreInsts")
1531062SN/A        .desc("Number of store instructions executed");
1541062SN/A
1551062SN/A    iewExecSquashedInsts
1561062SN/A        .name(name() + ".iewExecSquashedInsts")
1571062SN/A        .desc("Number of squashed instructions skipped in execute");
1581062SN/A
1591062SN/A    memOrderViolationEvents
1601062SN/A        .name(name() + ".memOrderViolationEvents")
1611062SN/A        .desc("Number of memory order violations");
1621062SN/A
1631062SN/A    predictedTakenIncorrect
1641062SN/A        .name(name() + ".predictedTakenIncorrect")
1651062SN/A        .desc("Number of branches that were predicted taken incorrectly");
1661062SN/A}
1671062SN/A
1681062SN/Atemplate<class Impl>
1691062SN/Avoid
1701062SN/ASimpleIEW<Impl>::setCPU(FullCPU *cpu_ptr)
1711062SN/A{
1721062SN/A    DPRINTF(IEW, "IEW: Setting CPU pointer.\n");
1731062SN/A    cpu = cpu_ptr;
1741062SN/A
1751062SN/A    instQueue.setCPU(cpu_ptr);
1761062SN/A    ldstQueue.setCPU(cpu_ptr);
1771062SN/A}
1781062SN/A
1791062SN/Atemplate<class Impl>
1801062SN/Avoid
1811062SN/ASimpleIEW<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
1821062SN/A{
1831062SN/A    DPRINTF(IEW, "IEW: Setting time buffer pointer.\n");
1841062SN/A    timeBuffer = tb_ptr;
1852292SN/A
1862292SN/A    // Setup wire to read information from time buffer, from commit.
1872292SN/A    fromCommit = timeBuffer->getWire(-commitToIEWDelay);
1882292SN/A
1891062SN/A    // Setup wire to write information back to previous stages.
1901062SN/A    toRename = timeBuffer->getWire(0);
1911062SN/A
1921062SN/A    // Instruction queue also needs main time buffer.
1931062SN/A    instQueue.setTimeBuffer(tb_ptr);
1941062SN/A}
1951062SN/A
1962292SN/Atemplate<class Impl>
1972292SN/Avoid
1982292SN/ASimpleIEW<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
1992292SN/A{
2002292SN/A    DPRINTF(IEW, "IEW: Setting rename queue pointer.\n");
2012292SN/A    renameQueue = rq_ptr;
2022292SN/A
2032292SN/A    // Setup wire to read information from rename queue.
2042292SN/A    fromRename = renameQueue->getWire(-renameToIEWDelay);
2052292SN/A}
2062301SN/A
2072727Sktlim@umich.edutemplate<class Impl>
2082353SN/Avoid
2092727Sktlim@umich.eduSimpleIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
2102727Sktlim@umich.edu{
2112727Sktlim@umich.edu    DPRINTF(IEW, "IEW: Setting IEW queue pointer.\n");
2126221Snate@binkert.org    iewQueue = iq_ptr;
2132353SN/A
2142727Sktlim@umich.edu    // Setup wire to write instructions to commit.
2152727Sktlim@umich.edu    toCommit = iewQueue->getWire(0);
2162727Sktlim@umich.edu}
2172727Sktlim@umich.edu
2182353SN/Atemplate<class Impl>
2192727Sktlim@umich.eduvoid
2202727Sktlim@umich.eduSimpleIEW<Impl>::setRenameMap(RenameMap *rm_ptr)
2212727Sktlim@umich.edu{
2226221Snate@binkert.org    DPRINTF(IEW, "IEW: Setting rename map pointer.\n");
2238240Snate@binkert.org    renameMap = rm_ptr;
2242301SN/A}
2252727Sktlim@umich.edu
2262301SN/Atemplate<class Impl>
2272727Sktlim@umich.eduvoid
2286221Snate@binkert.orgSimpleIEW<Impl>::squash()
2298240Snate@binkert.org{
2302301SN/A    DPRINTF(IEW, "IEW: Squashing all instructions.\n");
2312727Sktlim@umich.edu    _status = Squashing;
2322301SN/A
2332727Sktlim@umich.edu    // Tell the IQ to start squashing.
2346221Snate@binkert.org    instQueue.squash();
2358240Snate@binkert.org
2362301SN/A    // Tell the LDSTQ to start squashing.
2372727Sktlim@umich.edu    ldstQueue.squash(fromCommit->commitInfo.doneSeqNum);
2382301SN/A}
2392727Sktlim@umich.edu
2406221Snate@binkert.orgtemplate<class Impl>
2418240Snate@binkert.orgvoid
2422301SN/ASimpleIEW<Impl>::squashDueToBranch(DynInstPtr &inst)
2432727Sktlim@umich.edu{
2442301SN/A    DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n",
2452301SN/A            inst->PC);
2468240Snate@binkert.org    // Perhaps leave the squashing up to the ROB stage to tell it when to
2472301SN/A    // squash?
2482727Sktlim@umich.edu    _status = Squashing;
2492727Sktlim@umich.edu
2502727Sktlim@umich.edu    // Tell rename to squash through the time buffer.
2512727Sktlim@umich.edu    toCommit->squash = true;
2528240Snate@binkert.org    // Also send PC update information back to prior stages.
2532727Sktlim@umich.edu    toCommit->squashedSeqNum = inst->seqNum;
2542727Sktlim@umich.edu    toCommit->mispredPC = inst->readPC();
2552727Sktlim@umich.edu    toCommit->nextPC = inst->readNextPC();
2562727Sktlim@umich.edu    toCommit->branchMispredict = true;
2572301SN/A    // Prediction was incorrect, so send back inverse.
2582301SN/A    toCommit->branchTaken = inst->readNextPC() !=
2596221Snate@binkert.org        (inst->readPC() + sizeof(MachInst));
2608240Snate@binkert.org}
2612301SN/A
2622727Sktlim@umich.edutemplate<class Impl>
2632301SN/Avoid
2642326SN/ASimpleIEW<Impl>::squashDueToMem(DynInstPtr &inst)
2656221Snate@binkert.org{
2668240Snate@binkert.org    DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n",
2672301SN/A            inst->PC);
2682727Sktlim@umich.edu    // Perhaps leave the squashing up to the ROB stage to tell it when to
2692301SN/A    // squash?
2702326SN/A    _status = Squashing;
2716221Snate@binkert.org
2728240Snate@binkert.org    // Tell rename to squash through the time buffer.
2732301SN/A    toCommit->squash = true;
2742727Sktlim@umich.edu    // Also send PC update information back to prior stages.
2752301SN/A    toCommit->squashedSeqNum = inst->seqNum;
2762326SN/A    toCommit->nextPC = inst->readNextPC();
2776221Snate@binkert.org}
2788240Snate@binkert.org
2792301SN/Atemplate<class Impl>
2802727Sktlim@umich.eduvoid
2812301SN/ASimpleIEW<Impl>::block()
2822326SN/A{
2836221Snate@binkert.org    DPRINTF(IEW, "IEW: Blocking.\n");
2848240Snate@binkert.org    // Set the status to Blocked.
2852301SN/A    _status = Blocked;
2862727Sktlim@umich.edu
2872301SN/A    // Add the current inputs to the skid buffer so they can be
2882326SN/A    // reprocessed when this stage unblocks.
2898240Snate@binkert.org    skidBuffer.push(*fromRename);
2902301SN/A
2912727Sktlim@umich.edu    // Note that this stage only signals previous stages to stall when
2922301SN/A    // it is the cause of the stall originates at this stage.  Otherwise
2932326SN/A    // the previous stages are expected to check all possible stall signals.
2942301SN/A}
2952326SN/A
2968240Snate@binkert.orgtemplate<class Impl>
2972301SN/Ainline void
2982727Sktlim@umich.eduSimpleIEW<Impl>::unblock()
2992301SN/A{
3002326SN/A    // Check if there's information in the skid buffer.  If there is, then
3012301SN/A    // set status to unblocking, otherwise set it directly to running.
3022326SN/A    DPRINTF(IEW, "IEW: Reading instructions out of the skid "
3038240Snate@binkert.org            "buffer.\n");
3042301SN/A    // Remove the now processed instructions from the skid buffer.
3052727Sktlim@umich.edu    skidBuffer.pop();
3062326SN/A
3071062SN/A    // If there's still information in the skid buffer, then
3081062SN/A    // continue to tell previous stages to stall.  They will be
3091681SN/A    // able to restart once the skid buffer is empty.
3101060SN/A    if (!skidBuffer.empty()) {
3119427SAndreas.Sandberg@ARM.com        toRename->iewInfo.stall = true;
3121060SN/A    } else {
3136221Snate@binkert.org        DPRINTF(IEW, "IEW: Stage is done unblocking.\n");
3142292SN/A        _status = Running;
3152292SN/A    }
3162292SN/A}
3172292SN/A
3182292SN/Atemplate<class Impl>
31910239Sbinhpham@cs.rutgers.eduvoid
32010239Sbinhpham@cs.rutgers.eduSimpleIEW<Impl>::wakeDependents(DynInstPtr &inst)
3212292SN/A{
3222292SN/A    instQueue.wakeDependents(inst);
3238887Sgeoffrey.blake@arm.com}
3248733Sgeoffrey.blake@arm.com
3258850Sandreas.hansson@arm.com
3268887Sgeoffrey.blake@arm.comtemplate<class Impl>
3278733Sgeoffrey.blake@arm.comvoid
3282733Sktlim@umich.eduSimpleIEW<Impl>::instToCommit(DynInstPtr &inst)
3291060SN/A{
3301060SN/A
3311681SN/A}
3321060SN/A
3332292SN/Atemplate <class Impl>
3341060SN/Avoid
3351060SN/ASimpleIEW<Impl>::dispatchInsts()
3361060SN/A{
3371060SN/A    ////////////////////////////////////////
3381060SN/A    // DISPATCH/ISSUE stage
3391060SN/A    ////////////////////////////////////////
3401060SN/A
3411060SN/A    //Put into its own function?
3421060SN/A    //Add instructions to IQ if there are any instructions there
3432292SN/A
3442292SN/A    // Check if there are any instructions coming from rename, and we're.
3451060SN/A    // not squashing.
3461060SN/A    if (fromRename->size > 0) {
3471060SN/A        int insts_to_add = fromRename->size;
3481060SN/A
3491681SN/A        // Loop through the instructions, putting them in the instruction
3501060SN/A        // queue.
3512292SN/A        for (int inst_num = 0; inst_num < insts_to_add; ++inst_num)
3521060SN/A        {
3531060SN/A            DynInstPtr inst = fromRename->insts[inst_num];
3541060SN/A
3551060SN/A            // Make sure there's a valid instruction there.
3561060SN/A            assert(inst);
3571060SN/A
3581060SN/A            DPRINTF(IEW, "IEW: Issue: Adding PC %#x to IQ.\n",
3591681SN/A                    inst->readPC());
3601060SN/A
3612292SN/A            // Be sure to mark these instructions as ready so that the
3621060SN/A            // commit stage can go ahead and execute them, and mark
3631060SN/A            // them as issued so the IQ doesn't reprocess them.
3641060SN/A            if (inst->isSquashed()) {
3651060SN/A                ++iewDispSquashedInsts;
3661060SN/A                continue;
3671060SN/A            } else if (instQueue.isFull()) {
3681060SN/A                DPRINTF(IEW, "IEW: Issue: IQ has become full.\n");
3691681SN/A                // Call function to start blocking.
3701060SN/A                block();
3716221Snate@binkert.org                // Tell previous stage to stall.
3721060SN/A                toRename->iewInfo.stall = true;
3732292SN/A
3742292SN/A                ++iewIQFullEvents;
3752292SN/A                break;
3762292SN/A            } else if (inst->isLoad()) {
3771060SN/A                DPRINTF(IEW, "IEW: Issue: Memory instruction "
3781060SN/A                        "encountered, adding to LDSTQ.\n");
3791681SN/A
3801060SN/A                // Reserve a spot in the load store queue for this
3812292SN/A                // memory access.
3821060SN/A                ldstQueue.insertLoad(inst);
3832292SN/A
3841060SN/A                ++iewDispLoadInsts;
3851060SN/A            } else if (inst->isStore()) {
3862307SN/A                ldstQueue.insertStore(inst);
3872863Sktlim@umich.edu
3889444SAndreas.Sandberg@ARM.com                ++iewDispStoreInsts;
3892307SN/A            } else if (inst->isNonSpeculative()) {
3909444SAndreas.Sandberg@ARM.com                DPRINTF(IEW, "IEW: Issue: Nonspeculative instruction "
3919444SAndreas.Sandberg@ARM.com                        "encountered, skipping.\n");
3929444SAndreas.Sandberg@ARM.com
3939444SAndreas.Sandberg@ARM.com                // Same hack as with stores.
3949444SAndreas.Sandberg@ARM.com                inst->setCanCommit();
3959444SAndreas.Sandberg@ARM.com
3969444SAndreas.Sandberg@ARM.com                // Specificall insert it as nonspeculative.
3979444SAndreas.Sandberg@ARM.com                instQueue.insertNonSpec(inst);
3989444SAndreas.Sandberg@ARM.com
3999444SAndreas.Sandberg@ARM.com                ++iewDispNonSpecInsts;
4009444SAndreas.Sandberg@ARM.com
4019444SAndreas.Sandberg@ARM.com                continue;
4029444SAndreas.Sandberg@ARM.com            } else if (inst->isNop()) {
4039783Sandreas.hansson@arm.com                DPRINTF(IEW, "IEW: Issue: Nop instruction encountered "
4049783Sandreas.hansson@arm.com                        ", skipping.\n");
4059783Sandreas.hansson@arm.com
4069783Sandreas.hansson@arm.com                inst->setIssued();
4079783Sandreas.hansson@arm.com                inst->setExecuted();
4089783Sandreas.hansson@arm.com                inst->setCanCommit();
4099783Sandreas.hansson@arm.com
4109783Sandreas.hansson@arm.com                instQueue.advanceTail(inst);
4119444SAndreas.Sandberg@ARM.com
4121681SN/A                continue;
4131681SN/A            } else if (inst->isExecuted()) {
4142316SN/A                assert(0 && "Instruction shouldn't be executed.\n");
4151681SN/A                DPRINTF(IEW, "IEW: Issue: Executed branch encountered, "
4169444SAndreas.Sandberg@ARM.com                        "skipping.\n");
4172843Sktlim@umich.edu
4189444SAndreas.Sandberg@ARM.com                inst->setIssued();
4192843Sktlim@umich.edu                inst->setCanCommit();
4209444SAndreas.Sandberg@ARM.com
4219444SAndreas.Sandberg@ARM.com                instQueue.advanceTail(inst);
4221681SN/A
4231681SN/A                continue;
4242307SN/A            }
4251681SN/A
4262307SN/A            // If the instruction queue is not full, then add the
4271060SN/A            // instruction.
4282348SN/A            instQueue.insert(fromRename->insts[inst_num]);
4292307SN/A
4302307SN/A            ++iewDispatchedInsts;
4312307SN/A        }
4321060SN/A    }
4332307SN/A}
4342307SN/A
4359444SAndreas.Sandberg@ARM.comtemplate <class Impl>
4361060SN/Avoid
4379427SAndreas.Sandberg@ARM.comSimpleIEW<Impl>::executeInsts()
4382307SN/A{
4391060SN/A    ////////////////////////////////////////
4406221Snate@binkert.org    //EXECUTE/WRITEBACK stage
4416221Snate@binkert.org    ////////////////////////////////////////
4426221Snate@binkert.org
4436221Snate@binkert.org    //Put into its own function?
4442307SN/A    //Similarly should probably have separate execution for int vs FP.
4451060SN/A    // Above comment is handled by the issue queue only issuing a valid
4462307SN/A    // mix of int/fp instructions.
4472307SN/A    //Actually okay to just have one execution, buuuuuut will need
4482873Sktlim@umich.edu    //somewhere that defines the execution latency of all instructions.
4492307SN/A    // @todo: Move to the FU pool used in the current full cpu.
4501060SN/A
4511060SN/A    int fu_usage = 0;
4521060SN/A    bool fetch_redirect = false;
4531681SN/A    int inst_slot = 0;
4541060SN/A    int time_slot = 0;
4556221Snate@binkert.org
4562107SN/A    // Execute/writeback any instructions that are available.
4576221Snate@binkert.org    for (int inst_num = 0;
4582107SN/A         fu_usage < executeWidth && /* Haven't exceeded available FU's. */
4592292SN/A             inst_num < issueWidth &&
4602292SN/A             fromIssue->insts[inst_num];
4612107SN/A         ++inst_num) {
4622292SN/A
4632326SN/A        DPRINTF(IEW, "IEW: Execute: Executing instructions from IQ.\n");
4642292SN/A
4652107SN/A        // Get instruction from issue's queue.
4662292SN/A        DynInstPtr inst = fromIssue->insts[inst_num];
4672935Sksewell@umich.edu
4684632Sgblack@eecs.umich.edu        DPRINTF(IEW, "IEW: Execute: Processing PC %#x.\n", inst->readPC());
4692935Sksewell@umich.edu
4702292SN/A        // Check if the instruction is squashed; if so then skip it
47110239Sbinhpham@cs.rutgers.edu        // and don't count it towards the FU usage.
47210239Sbinhpham@cs.rutgers.edu        if (inst->isSquashed()) {
47310239Sbinhpham@cs.rutgers.edu            DPRINTF(IEW, "IEW: Execute: Instruction was squashed.\n");
47410239Sbinhpham@cs.rutgers.edu
47510239Sbinhpham@cs.rutgers.edu            // Consider this instruction executed so that commit can go
4762292SN/A            // ahead and retire the instruction.
4772107SN/A            inst->setExecuted();
4782292SN/A
4792107SN/A            toCommit->insts[inst_num] = inst;
4802292SN/A
4812292SN/A            ++iewExecSquashedInsts;
4822107SN/A
4832702Sktlim@umich.edu            continue;
4842107SN/A        }
4852107SN/A
4862107SN/A        inst->setExecuted();
4872107SN/A
4886221Snate@binkert.org        // If an instruction is executed, then count it towards FU usage.
4892292SN/A        ++fu_usage;
4907720Sgblack@eecs.umich.edu
4917720Sgblack@eecs.umich.edu        // Execute instruction.
4922292SN/A        // Note that if the instruction faults, it will be handled
49310231Ssteve.reinhardt@amd.com        // at the commit stage.
4947852SMatt.Horsnell@arm.com        if (inst->isMemRef()) {
4957852SMatt.Horsnell@arm.com            DPRINTF(IEW, "IEW: Execute: Calculating address for memory "
4967852SMatt.Horsnell@arm.com                    "reference.\n");
4977852SMatt.Horsnell@arm.com
4982935Sksewell@umich.edu            // Tell the LDSTQ to execute this instruction (if it is a load).
4997852SMatt.Horsnell@arm.com            if (inst->isLoad()) {
5007852SMatt.Horsnell@arm.com                ldstQueue.executeLoad(inst);
5012292SN/A
5027852SMatt.Horsnell@arm.com                ++iewExecLoadInsts;
5037852SMatt.Horsnell@arm.com            } else if (inst->isStore()) {
5047852SMatt.Horsnell@arm.com                ldstQueue.executeStore(inst);
5052292SN/A
5067852SMatt.Horsnell@arm.com                ++iewExecStoreInsts;
5077852SMatt.Horsnell@arm.com            } else {
5087852SMatt.Horsnell@arm.com                panic("IEW: Unexpected memory type!\n");
5092292SN/A            }
5102292SN/A
5112292SN/A        } else {
5122292SN/A            inst->execute();
5136221Snate@binkert.org
5142292SN/A            ++iewExecutedInsts;
5158513SGiacomo.Gabrielli@arm.com        }
5168513SGiacomo.Gabrielli@arm.com
5178513SGiacomo.Gabrielli@arm.com        // First check the time slot that this instruction will write
5188513SGiacomo.Gabrielli@arm.com        // to.  If there are free write ports at the time, then go ahead
5198513SGiacomo.Gabrielli@arm.com        // and write the instruction to that time.  If there are not,
5208513SGiacomo.Gabrielli@arm.com        // keep looking back to see where's the first time there's a
5218513SGiacomo.Gabrielli@arm.com        // free slot.  What happens if you run out of free spaces?
5228513SGiacomo.Gabrielli@arm.com        // For now naively assume that all instructions take one cycle.
52310231Ssteve.reinhardt@amd.com        // Otherwise would have to look into the time buffer based on the
5248513SGiacomo.Gabrielli@arm.com        // latency of the instruction.
5258513SGiacomo.Gabrielli@arm.com        (*iewQueue)[time_slot].insts[inst_slot];
5262292SN/A        while ((*iewQueue)[time_slot].insts[inst_slot]) {
5277852SMatt.Horsnell@arm.com            if (inst_slot < issueWidth) {
5288513SGiacomo.Gabrielli@arm.com                ++inst_slot;
5298137SAli.Saidi@ARM.com            } else {
5302292SN/A                ++time_slot;
5318513SGiacomo.Gabrielli@arm.com                inst_slot = 0;
5328513SGiacomo.Gabrielli@arm.com            }
5332292SN/A
5347852SMatt.Horsnell@arm.com            assert(time_slot < 5);
5357852SMatt.Horsnell@arm.com        }
5362292SN/A
5372292SN/A        // May actually have to work this out, especially with loads and stores
5382292SN/A
5392292SN/A        // Add finished instruction to queue to commit.
5406221Snate@binkert.org        (*iewQueue)[time_slot].insts[inst_slot] = inst;
5412292SN/A        (*iewQueue)[time_slot].size++;
5422292SN/A
5437720Sgblack@eecs.umich.edu        // Check if branch was correct.  This check happens after the
54410231Ssteve.reinhardt@amd.com        // instruction is added to the queue because even if the branch
5457852SMatt.Horsnell@arm.com        // is mispredicted, the branch instruction itself is still valid.
5467852SMatt.Horsnell@arm.com        // Only handle this if there hasn't already been something that
5472292SN/A        // redirects fetch in this group of instructions.
5487852SMatt.Horsnell@arm.com        if (!fetch_redirect) {
5497852SMatt.Horsnell@arm.com            if (inst->mispredicted()) {
5508137SAli.Saidi@ARM.com                fetch_redirect = true;
5512292SN/A
5527852SMatt.Horsnell@arm.com                DPRINTF(IEW, "IEW: Execute: Branch mispredict detected.\n");
5537852SMatt.Horsnell@arm.com                DPRINTF(IEW, "IEW: Execute: Redirecting fetch to PC: %#x.\n",
5542292SN/A                        inst->nextPC);
5557852SMatt.Horsnell@arm.com
5562292SN/A                // If incorrect, then signal the ROB that it must be squashed.
5577852SMatt.Horsnell@arm.com                squashDueToBranch(inst);
5587852SMatt.Horsnell@arm.com
5592292SN/A                if (inst->predTaken()) {
5602292SN/A                    predictedTakenIncorrect++;
5612292SN/A                }
5622292SN/A            } else if (ldstQueue.violation()) {
5636221Snate@binkert.org                fetch_redirect = true;
5642292SN/A
5652292SN/A                // Get the DynInst that caused the violation.
5662292SN/A                DynInstPtr violator = ldstQueue.getMemDepViolator();
5672292SN/A
5682292SN/A                DPRINTF(IEW, "IEW: LDSTQ detected a violation.  Violator PC: "
5692292SN/A                        "%#x, inst PC: %#x.  Addr is: %#x.\n",
5702292SN/A                        violator->readPC(), inst->readPC(), inst->physEffAddr);
5712292SN/A
5722292SN/A                // Tell the instruction queue that a violation has occured.
5732292SN/A                instQueue.violation(inst, violator);
5742292SN/A
5752292SN/A                // Squash.
5762292SN/A                squashDueToMem(inst);
5772292SN/A
5782292SN/A                ++memOrderViolationEvents;
5792292SN/A            }
5802292SN/A        }
5812292SN/A    }
5826221Snate@binkert.org}
5832292SN/A
5842292SN/Atemplate<class Impl>
5852292SN/Avoid
5862292SN/ASimpleIEW<Impl>::tick()
5872292SN/A{
5882292SN/A    // Considering putting all the state-determining stuff in this section.
5892292SN/A
5902292SN/A    // Try to fill up issue queue with as many instructions as bandwidth
5912292SN/A    // allows.
5922292SN/A    // Decode should try to execute as many instructions as its bandwidth
5932292SN/A    // will allow, as long as it is not currently blocked.
5942292SN/A
5952292SN/A    // Check if the stage is in a running status.
5962292SN/A    if (_status != Blocked && _status != Squashing) {
5972292SN/A        DPRINTF(IEW, "IEW: Status is not blocked, attempting to run "
5982292SN/A                     "stage.\n");
5992292SN/A        iew();
6001060SN/A
6011681SN/A        // If it's currently unblocking, check to see if it should switch
6021060SN/A        // to running.
6031060SN/A        if (_status == Unblocking) {
6042292SN/A            unblock();
6052292SN/A
6062292SN/A            ++iewUnblockCycles;
6072292SN/A        }
6082292SN/A    } else if (_status == Squashing) {
6092292SN/A
6101681SN/A        DPRINTF(IEW, "IEW: Still squashing.\n");
6111681SN/A
6121060SN/A        // Check if stage should remain squashing.  Stop squashing if the
6132292SN/A        // squash signal clears.
6141060SN/A        if (!fromCommit->commitInfo.squash &&
6152292SN/A            !fromCommit->commitInfo.robSquashing) {
6162292SN/A            DPRINTF(IEW, "IEW: Done squashing, changing status to "
6171060SN/A                    "running.\n");
6182292SN/A
6192292SN/A            _status = Running;
6202292SN/A            instQueue.stopSquash();
6212292SN/A        } else {
6223221Sktlim@umich.edu            instQueue.doSquash();
6233221Sktlim@umich.edu        }
6243221Sktlim@umich.edu
6253221Sktlim@umich.edu        ++iewSquashCycles;
6263221Sktlim@umich.edu    } else if (_status == Blocked) {
6272292SN/A        // Continue to tell previous stage to stall.
6282292SN/A        toRename->iewInfo.stall = true;
6292292SN/A
6302292SN/A        // Check if possible stall conditions have cleared.
6312326SN/A        if (!fromCommit->commitInfo.stall &&
6322292SN/A            !instQueue.isFull()) {
6332292SN/A            DPRINTF(IEW, "IEW: Stall signals cleared, going to unblock.\n");
6342820Sktlim@umich.edu            _status = Unblocking;
6352292SN/A        }
6362292SN/A
6372292SN/A        // If there's still instructions coming from rename, continue to
6382292SN/A        // put them on the skid buffer.
6392353SN/A        if (fromRename->size == 0) {
6402292SN/A            block();
6412292SN/A        }
6422353SN/A
6432353SN/A        if (fromCommit->commitInfo.squash ||
6442292SN/A            fromCommit->commitInfo.robSquashing) {
6452292SN/A            squash();
6462292SN/A        }
6472292SN/A
6482292SN/A        ++iewBlockCycles;
6492292SN/A    }
6502292SN/A
6512292SN/A    // @todo: Maybe put these at the beginning, so if it's idle it can
6522292SN/A    // return early.
6532292SN/A    // Write back number of free IQ entries here.
6542292SN/A    toRename->iewInfo.freeIQEntries = instQueue.numFreeEntries();
6552292SN/A
6562731Sktlim@umich.edu    ldstQueue.writebackStores();
6572292SN/A
6582292SN/A    // Check the committed load/store signals to see if there's a load
6592292SN/A    // or store to commit.  Also check if it's being told to execute a
6602292SN/A    // nonspeculative instruction.
6612292SN/A    // This is pretty inefficient...
6622292SN/A    if (!fromCommit->commitInfo.squash &&
6632292SN/A        !fromCommit->commitInfo.robSquashing) {
6642292SN/A        ldstQueue.commitStores(fromCommit->commitInfo.doneSeqNum);
6656221Snate@binkert.org        ldstQueue.commitLoads(fromCommit->commitInfo.doneSeqNum);
6662292SN/A    }
6672292SN/A
6682292SN/A    if (fromCommit->commitInfo.nonSpecSeqNum != 0) {
6692292SN/A        instQueue.scheduleNonSpec(fromCommit->commitInfo.nonSpecSeqNum);
6702292SN/A    }
6712292SN/A
6722292SN/A    DPRINTF(IEW, "IEW: IQ has %i free entries.\n",
6732292SN/A            instQueue.numFreeEntries());
6749937SFaissal.Sleiman@arm.com}
6752292SN/A
6767720Sgblack@eecs.umich.edutemplate<class Impl>
6772292SN/Avoid
6782292SN/ASimpleIEW<Impl>::iew()
6792292SN/A{
6802292SN/A    // Might want to put all state checks in the tick() function.
6812292SN/A    // Check if being told to stall from commit.
6822292SN/A    if (fromCommit->commitInfo.stall) {
6832292SN/A        block();
6842292SN/A        return;
6852292SN/A    } else if (fromCommit->commitInfo.squash ||
6862292SN/A               fromCommit->commitInfo.robSquashing) {
6872292SN/A        // Also check if commit is telling this stage to squash.
6882292SN/A        squash();
6892292SN/A        return;
6902292SN/A    }
6916221Snate@binkert.org
6926221Snate@binkert.org    dispatchInsts();
6932292SN/A
6943867Sbinkertn@umich.edu    // Have the instruction queue try to schedule any ready instructions.
6956221Snate@binkert.org    instQueue.scheduleReadyInsts();
6963867Sbinkertn@umich.edu
6972292SN/A    executeInsts();
6982292SN/A
6992292SN/A    // Loop through the head of the time buffer and wake any dependents.
7002292SN/A    // These instructions are about to write back.  In the simple model
7012292SN/A    // this loop can really happen within the previous loop, but when
7022292SN/A    // instructions have actual latencies, this loop must be separate.
7032292SN/A    // Also mark scoreboard that this instruction is finally complete.
7042292SN/A    // Either have IEW have direct access to rename map, or have this as
7052292SN/A    // part of backwards communication.
7062292SN/A    for (int inst_num = 0; inst_num < issueWidth &&
7072292SN/A             toCommit->insts[inst_num]; inst_num++)
7086221Snate@binkert.org    {
7096221Snate@binkert.org        DynInstPtr inst = toCommit->insts[inst_num];
7102292SN/A
7113867Sbinkertn@umich.edu        DPRINTF(IEW, "IEW: Sending instructions to commit, PC %#x.\n",
7126221Snate@binkert.org                inst->readPC());
7133867Sbinkertn@umich.edu
7143867Sbinkertn@umich.edu        if(!inst->isSquashed()) {
7152292SN/A            instQueue.wakeDependents(inst);
7162292SN/A
7172292SN/A            for (int i = 0; i < inst->numDestRegs(); i++)
7182292SN/A            {
7191062SN/A                renameMap->markAsReady(inst->renamedDestRegIdx(i));
7201062SN/A            }
7211681SN/A        }
7221062SN/A    }
7232292SN/A
7241062SN/A    // Also should advance its own time buffers if the stage ran.
7252292SN/A    // Not the best place for it, but this works (hopefully).
7261062SN/A    issueToExecQueue.advance();
7276221Snate@binkert.org}
7286221Snate@binkert.org
7291062SN/A#ifndef FULL_SYSTEM
7303867Sbinkertn@umich.edutemplate<class Impl>
7316221Snate@binkert.orgvoid
7321062SN/ASimpleIEW<Impl>::lsqWriteback()
7332292SN/A{
7342292SN/A    ldstQueue.writebackAllInsts();
7352292SN/A}
7362292SN/A#endif
7372292SN/A