iew_impl.hh revision 1681
16313Sgblack@eecs.umich.edu// @todo: Fix the instantaneous communication among all the stages within
210844Sandreas.sandberg@arm.com// iew.  There's a clear delay between issue and execute, yet backwards
37093Sgblack@eecs.umich.edu// communication happens simultaneously.  Might not be that bad really...
47093Sgblack@eecs.umich.edu// it might skew stats a bit though.  Issue would otherwise try to issue
57093Sgblack@eecs.umich.edu// instructions that would never be executed if there were a delay; without
67093Sgblack@eecs.umich.edu// it issue will simply squash.  Make this stage block properly.
77093Sgblack@eecs.umich.edu// Update the statuses for each stage.
87093Sgblack@eecs.umich.edu// Actually read instructions out of the skid buffer.
97093Sgblack@eecs.umich.edu
107093Sgblack@eecs.umich.edu#include <queue>
117093Sgblack@eecs.umich.edu
127093Sgblack@eecs.umich.edu#include "base/timebuf.hh"
137093Sgblack@eecs.umich.edu#include "cpu/beta_cpu/iew.hh"
146313Sgblack@eecs.umich.edu
156313Sgblack@eecs.umich.edutemplate<class Impl>
166313Sgblack@eecs.umich.eduSimpleIEW<Impl>::WritebackEvent::WritebackEvent(DynInstPtr &_inst,
176313Sgblack@eecs.umich.edu                                                SimpleIEW<Impl> *_iew)
186313Sgblack@eecs.umich.edu    : Event(&mainEventQueue, CPU_Tick_Pri), inst(_inst), iewStage(_iew)
196313Sgblack@eecs.umich.edu{
206313Sgblack@eecs.umich.edu    this->setFlags(Event::AutoDelete);
216313Sgblack@eecs.umich.edu}
226313Sgblack@eecs.umich.edu
236313Sgblack@eecs.umich.edutemplate<class Impl>
246313Sgblack@eecs.umich.eduvoid
256313Sgblack@eecs.umich.eduSimpleIEW<Impl>::WritebackEvent::process()
266313Sgblack@eecs.umich.edu{
276313Sgblack@eecs.umich.edu    DPRINTF(IEW, "IEW: WRITEBACK EVENT!!!!\n");
286313Sgblack@eecs.umich.edu
296313Sgblack@eecs.umich.edu    // Need to insert instruction into queue to commit
306313Sgblack@eecs.umich.edu    iewStage->instToCommit(inst);
316313Sgblack@eecs.umich.edu    // Need to execute second half of the instruction, do actual writing to
326313Sgblack@eecs.umich.edu    // registers and such
336313Sgblack@eecs.umich.edu    inst->execute();
346313Sgblack@eecs.umich.edu}
356313Sgblack@eecs.umich.edu
366313Sgblack@eecs.umich.edutemplate<class Impl>
376313Sgblack@eecs.umich.educonst char *
386313Sgblack@eecs.umich.eduSimpleIEW<Impl>::WritebackEvent::description()
396313Sgblack@eecs.umich.edu{
406313Sgblack@eecs.umich.edu    return "LSQ writeback event";
416313Sgblack@eecs.umich.edu}
426313Sgblack@eecs.umich.edu
436313Sgblack@eecs.umich.edutemplate<class Impl>
447404SAli.Saidi@ARM.comSimpleIEW<Impl>::SimpleIEW(Params &params)
456313Sgblack@eecs.umich.edu    : // Just make this time buffer really big for now
4610461SAndreas.Sandberg@ARM.com      issueToExecQueue(5, 5),
476333Sgblack@eecs.umich.edu      instQueue(params),
4810037SARM gem5 Developers      ldstQueue(params),
497404SAli.Saidi@ARM.com      commitToIEWDelay(params.commitToIEWDelay),
506313Sgblack@eecs.umich.edu      renameToIEWDelay(params.renameToIEWDelay),
518232Snate@binkert.org      issueToExecuteDelay(params.issueToExecuteDelay),
529384SAndreas.Sandberg@arm.com      issueReadWidth(params.issueWidth),
5311165SRekai.GonzalezAlberquilla@arm.com      issueWidth(params.issueWidth),
546313Sgblack@eecs.umich.edu      executeWidth(params.executeWidth)
559384SAndreas.Sandberg@arm.com{
5610461SAndreas.Sandberg@ARM.com    DPRINTF(IEW, "IEW: executeIntWidth: %i.\n", params.executeIntWidth);
576333Sgblack@eecs.umich.edu    _status = Idle;
586313Sgblack@eecs.umich.edu    _issueStatus = Idle;
596313Sgblack@eecs.umich.edu    _exeStatus = Idle;
606313Sgblack@eecs.umich.edu    _wbStatus = Idle;
616313Sgblack@eecs.umich.edu
626313Sgblack@eecs.umich.edu    // Setup wire to read instructions coming from issue.
6310037SARM gem5 Developers    fromIssue = issueToExecQueue.getWire(-issueToExecuteDelay);
6410037SARM gem5 Developers
6510037SARM gem5 Developers    // Instruction queue needs the queue between issue and execute.
6610037SARM gem5 Developers    instQueue.setIssueToExecuteQueue(&issueToExecQueue);
6710037SARM gem5 Developers
6810037SARM gem5 Developers    ldstQueue.setIEW(this);
6910037SARM gem5 Developers}
7010037SARM gem5 Developers
7110037SARM gem5 Developerstemplate <class Impl>
7210037SARM gem5 Developersvoid
7310037SARM gem5 DevelopersSimpleIEW<Impl>::regStats()
7410037SARM gem5 Developers{
7510037SARM gem5 Developers    instQueue.regStats();
7610037SARM gem5 Developers
7710037SARM gem5 Developers    iewIdleCycles
7810037SARM gem5 Developers        .name(name() + ".iewIdleCycles")
7910037SARM gem5 Developers        .desc("Number of cycles IEW is idle");
8010037SARM gem5 Developers
8110037SARM gem5 Developers    iewSquashCycles
8210037SARM gem5 Developers        .name(name() + ".iewSquashCycles")
8310037SARM gem5 Developers        .desc("Number of cycles IEW is squashing");
8410037SARM gem5 Developers
8510037SARM gem5 Developers    iewBlockCycles
8610037SARM gem5 Developers        .name(name() + ".iewBlockCycles")
8710037SARM gem5 Developers        .desc("Number of cycles IEW is blocking");
8810037SARM gem5 Developers
8910037SARM gem5 Developers    iewUnblockCycles
9010037SARM gem5 Developers        .name(name() + ".iewUnblockCycles")
9110037SARM gem5 Developers        .desc("Number of cycles IEW is unblocking");
9210037SARM gem5 Developers
9310037SARM gem5 Developers//    iewWBInsts;
9410037SARM gem5 Developers
9510037SARM gem5 Developers    iewDispatchedInsts
9610037SARM gem5 Developers        .name(name() + ".iewDispatchedInsts")
9710037SARM gem5 Developers        .desc("Number of instructions dispatched to IQ");
9810037SARM gem5 Developers
9910037SARM gem5 Developers    iewDispSquashedInsts
10010037SARM gem5 Developers        .name(name() + ".iewDispSquashedInsts")
10110037SARM gem5 Developers        .desc("Number of squashed instructions skipped by dispatch");
10210037SARM gem5 Developers
10310037SARM gem5 Developers    iewDispLoadInsts
10410037SARM gem5 Developers        .name(name() + ".iewDispLoadInsts")
10510037SARM gem5 Developers        .desc("Number of dispatched load instructions");
10610037SARM gem5 Developers
10710037SARM gem5 Developers    iewDispStoreInsts
10810037SARM gem5 Developers        .name(name() + ".iewDispStoreInsts")
10910037SARM gem5 Developers        .desc("Number of dispatched store instructions");
11010037SARM gem5 Developers
11110037SARM gem5 Developers    iewDispNonSpecInsts
11210037SARM gem5 Developers        .name(name() + ".iewDispNonSpecInsts")
11310037SARM gem5 Developers        .desc("Number of dispatched non-speculative instructions");
11410037SARM gem5 Developers
11510037SARM gem5 Developers    iewIQFullEvents
11610037SARM gem5 Developers        .name(name() + ".iewIQFullEvents")
11710037SARM gem5 Developers        .desc("Number of times the IQ has become full, causing a stall");
11810037SARM gem5 Developers
11910037SARM gem5 Developers    iewExecutedInsts
12010037SARM gem5 Developers        .name(name() + ".iewExecutedInsts")
12110037SARM gem5 Developers        .desc("Number of executed instructions");
12210037SARM gem5 Developers
12310037SARM gem5 Developers    iewExecLoadInsts
12410037SARM gem5 Developers        .name(name() + ".iewExecLoadInsts")
12510037SARM gem5 Developers        .desc("Number of load instructions executed");
12610037SARM gem5 Developers
12710037SARM gem5 Developers    iewExecStoreInsts
12810037SARM gem5 Developers        .name(name() + ".iewExecStoreInsts")
12910037SARM gem5 Developers        .desc("Number of store instructions executed");
1309384SAndreas.Sandberg@arm.com
1316313Sgblack@eecs.umich.edu    iewExecSquashedInsts
1326313Sgblack@eecs.umich.edu        .name(name() + ".iewExecSquashedInsts")
13310037SARM gem5 Developers        .desc("Number of squashed instructions skipped in execute");
13410037SARM gem5 Developers
13510037SARM gem5 Developers    memOrderViolationEvents
13611165SRekai.GonzalezAlberquilla@arm.com        .name(name() + ".memOrderViolationEvents")
13711165SRekai.GonzalezAlberquilla@arm.com        .desc("Number of memory order violations");
13811165SRekai.GonzalezAlberquilla@arm.com
13910461SAndreas.Sandberg@ARM.com    predictedTakenIncorrect
14010461SAndreas.Sandberg@ARM.com        .name(name() + ".predictedTakenIncorrect")
14110461SAndreas.Sandberg@ARM.com        .desc("Number of branches that were predicted taken incorrectly");
14210461SAndreas.Sandberg@ARM.com}
14310461SAndreas.Sandberg@ARM.com
14410461SAndreas.Sandberg@ARM.comtemplate<class Impl>
14510844Sandreas.sandberg@arm.comvoid
14610844Sandreas.sandberg@arm.comSimpleIEW<Impl>::setCPU(FullCPU *cpu_ptr)
14710844Sandreas.sandberg@arm.com{
14810037SARM gem5 Developers    DPRINTF(IEW, "IEW: Setting CPU pointer.\n");
14910037SARM gem5 Developers    cpu = cpu_ptr;
15010037SARM gem5 Developers
15110037SARM gem5 Developers    instQueue.setCPU(cpu_ptr);
15210037SARM gem5 Developers    ldstQueue.setCPU(cpu_ptr);
15310037SARM gem5 Developers}
15410037SARM gem5 Developers
15510037SARM gem5 Developerstemplate<class Impl>
15610037SARM gem5 Developersvoid
15710037SARM gem5 DevelopersSimpleIEW<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
15810037SARM gem5 Developers{
15910037SARM gem5 Developers    DPRINTF(IEW, "IEW: Setting time buffer pointer.\n");
16010037SARM gem5 Developers    timeBuffer = tb_ptr;
16110037SARM gem5 Developers
16210037SARM gem5 Developers    // Setup wire to read information from time buffer, from commit.
16310037SARM gem5 Developers    fromCommit = timeBuffer->getWire(-commitToIEWDelay);
16410037SARM gem5 Developers
16510037SARM gem5 Developers    // Setup wire to write information back to previous stages.
16610037SARM gem5 Developers    toRename = timeBuffer->getWire(0);
16710037SARM gem5 Developers
16810037SARM gem5 Developers    // Instruction queue also needs main time buffer.
16910037SARM gem5 Developers    instQueue.setTimeBuffer(tb_ptr);
17010037SARM gem5 Developers}
17110037SARM gem5 Developers
17210037SARM gem5 Developerstemplate<class Impl>
1736333Sgblack@eecs.umich.eduvoid
1746718Sgblack@eecs.umich.eduSimpleIEW<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
1756718Sgblack@eecs.umich.edu{
1766718Sgblack@eecs.umich.edu    DPRINTF(IEW, "IEW: Setting rename queue pointer.\n");
1776718Sgblack@eecs.umich.edu    renameQueue = rq_ptr;
1786718Sgblack@eecs.umich.edu
17910037SARM gem5 Developers    // Setup wire to read information from rename queue.
18010037SARM gem5 Developers    fromRename = renameQueue->getWire(-renameToIEWDelay);
18110037SARM gem5 Developers}
18210037SARM gem5 Developers
18310037SARM gem5 Developerstemplate<class Impl>
18410037SARM gem5 Developersvoid
18510037SARM gem5 DevelopersSimpleIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
18610037SARM gem5 Developers{
18710037SARM gem5 Developers    DPRINTF(IEW, "IEW: Setting IEW queue pointer.\n");
18810037SARM gem5 Developers    iewQueue = iq_ptr;
18910037SARM gem5 Developers
19010037SARM gem5 Developers    // Setup wire to write instructions to commit.
19110037SARM gem5 Developers    toCommit = iewQueue->getWire(0);
19210037SARM gem5 Developers}
19310037SARM gem5 Developers
19410037SARM gem5 Developerstemplate<class Impl>
19510037SARM gem5 Developersvoid
19610037SARM gem5 DevelopersSimpleIEW<Impl>::setRenameMap(RenameMap *rm_ptr)
19710037SARM gem5 Developers{
19810037SARM gem5 Developers    DPRINTF(IEW, "IEW: Setting rename map pointer.\n");
19910037SARM gem5 Developers    renameMap = rm_ptr;
20010037SARM gem5 Developers}
20110037SARM gem5 Developers
20210037SARM gem5 Developerstemplate<class Impl>
20310037SARM gem5 Developersvoid
20410037SARM gem5 DevelopersSimpleIEW<Impl>::squash()
20510037SARM gem5 Developers{
20610037SARM gem5 Developers    DPRINTF(IEW, "IEW: Squashing all instructions.\n");
20710037SARM gem5 Developers    _status = Squashing;
20810037SARM gem5 Developers
20910037SARM gem5 Developers    // Tell the IQ to start squashing.
21010037SARM gem5 Developers    instQueue.squash();
2116718Sgblack@eecs.umich.edu
2126718Sgblack@eecs.umich.edu    // Tell the LDSTQ to start squashing.
2136313Sgblack@eecs.umich.edu    ldstQueue.squash(fromCommit->commitInfo.doneSeqNum);
21410844Sandreas.sandberg@arm.com}
21510037SARM gem5 Developers
21610037SARM gem5 Developerstemplate<class Impl>
21710037SARM gem5 Developersvoid
21810037SARM gem5 DevelopersSimpleIEW<Impl>::squashDueToBranch(DynInstPtr &inst)
21910037SARM gem5 Developers{
22010037SARM gem5 Developers    DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n",
22110037SARM gem5 Developers            inst->PC);
22210037SARM gem5 Developers    // Perhaps leave the squashing up to the ROB stage to tell it when to
22310037SARM gem5 Developers    // squash?
22410037SARM gem5 Developers    _status = Squashing;
22510037SARM gem5 Developers
22610037SARM gem5 Developers    // Tell rename to squash through the time buffer.
22710037SARM gem5 Developers    toCommit->squash = true;
22810709SAndreas.Sandberg@ARM.com    // Also send PC update information back to prior stages.
22910037SARM gem5 Developers    toCommit->squashedSeqNum = inst->seqNum;
23010037SARM gem5 Developers    toCommit->mispredPC = inst->readPC();
23110037SARM gem5 Developers    toCommit->nextPC = inst->readNextPC();
23210037SARM gem5 Developers    toCommit->branchMispredict = true;
23310037SARM gem5 Developers    // Prediction was incorrect, so send back inverse.
23410037SARM gem5 Developers    toCommit->branchTaken = inst->readNextPC() !=
23510037SARM gem5 Developers        (inst->readPC() + sizeof(MachInst));
23610037SARM gem5 Developers}
23710037SARM gem5 Developers
2386313Sgblack@eecs.umich.edutemplate<class Impl>
2397427Sgblack@eecs.umich.eduvoid
24010037SARM gem5 DevelopersSimpleIEW<Impl>::squashDueToMem(DynInstPtr &inst)
2416313Sgblack@eecs.umich.edu{
24210035Sandreas.hansson@arm.com    DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n",
2437405SAli.Saidi@ARM.com            inst->PC);
2447405SAli.Saidi@ARM.com    // Perhaps leave the squashing up to the ROB stage to tell it when to
2457405SAli.Saidi@ARM.com    // squash?
2466313Sgblack@eecs.umich.edu    _status = Squashing;
2476313Sgblack@eecs.umich.edu
24810035Sandreas.hansson@arm.com    // Tell rename to squash through the time buffer.
2496313Sgblack@eecs.umich.edu    toCommit->squash = true;
2506718Sgblack@eecs.umich.edu    // Also send PC update information back to prior stages.
2516718Sgblack@eecs.umich.edu    toCommit->squashedSeqNum = inst->seqNum;
2526718Sgblack@eecs.umich.edu    toCommit->nextPC = inst->readNextPC();
2536726Sgblack@eecs.umich.edu}
2546726Sgblack@eecs.umich.edu
25510037SARM gem5 Developerstemplate<class Impl>
25610037SARM gem5 Developersvoid
25710037SARM gem5 DevelopersSimpleIEW<Impl>::block()
25810037SARM gem5 Developers{
25910037SARM gem5 Developers    DPRINTF(IEW, "IEW: Blocking.\n");
26010037SARM gem5 Developers    // Set the status to Blocked.
26110037SARM gem5 Developers    _status = Blocked;
26210037SARM gem5 Developers
26310037SARM gem5 Developers    // Add the current inputs to the skid buffer so they can be
26410037SARM gem5 Developers    // reprocessed when this stage unblocks.
26510037SARM gem5 Developers    skidBuffer.push(*fromRename);
26610037SARM gem5 Developers
26710037SARM gem5 Developers    // Note that this stage only signals previous stages to stall when
26810037SARM gem5 Developers    // it is the cause of the stall originates at this stage.  Otherwise
26910037SARM gem5 Developers    // the previous stages are expected to check all possible stall signals.
27010037SARM gem5 Developers}
27110037SARM gem5 Developers
27210037SARM gem5 Developerstemplate<class Impl>
27310037SARM gem5 Developersinline void
27410037SARM gem5 DevelopersSimpleIEW<Impl>::unblock()
2756718Sgblack@eecs.umich.edu{
27610037SARM gem5 Developers    // Check if there's information in the skid buffer.  If there is, then
2776718Sgblack@eecs.umich.edu    // set status to unblocking, otherwise set it directly to running.
2786313Sgblack@eecs.umich.edu    DPRINTF(IEW, "IEW: Reading instructions out of the skid "
2796313Sgblack@eecs.umich.edu            "buffer.\n");
2806313Sgblack@eecs.umich.edu    // Remove the now processed instructions from the skid buffer.
28110035Sandreas.hansson@arm.com    skidBuffer.pop();
2826313Sgblack@eecs.umich.edu
28310338SCurtis.Dunham@arm.com    // If there's still information in the skid buffer, then
2846313Sgblack@eecs.umich.edu    // continue to tell previous stages to stall.  They will be
2856313Sgblack@eecs.umich.edu    // able to restart once the skid buffer is empty.
2866313Sgblack@eecs.umich.edu    if (!skidBuffer.empty()) {
2879920Syasuko.eckert@amd.com        toRename->iewInfo.stall = true;
28810035Sandreas.hansson@arm.com    } else {
2899920Syasuko.eckert@amd.com        DPRINTF(IEW, "IEW: Stage is done unblocking.\n");
29010338SCurtis.Dunham@arm.com        _status = Running;
2919920Syasuko.eckert@amd.com    }
2929920Syasuko.eckert@amd.com}
2939920Syasuko.eckert@amd.com
2947614Sminkyu.jeong@arm.comtemplate<class Impl>
29510035Sandreas.hansson@arm.comvoid
2967614Sminkyu.jeong@arm.comSimpleIEW<Impl>::wakeDependents(DynInstPtr &inst)
29710338SCurtis.Dunham@arm.com{
29810037SARM gem5 Developers    instQueue.wakeDependents(inst);
29910037SARM gem5 Developers}
3007614Sminkyu.jeong@arm.com
3017614Sminkyu.jeong@arm.com
3027614Sminkyu.jeong@arm.comtemplate<class Impl>
30310037SARM gem5 Developersvoid
30410037SARM gem5 DevelopersSimpleIEW<Impl>::instToCommit(DynInstPtr &inst)
30510037SARM gem5 Developers{
30610037SARM gem5 Developers
30710037SARM gem5 Developers}
30810037SARM gem5 Developers
30910037SARM gem5 Developerstemplate <class Impl>
31010037SARM gem5 Developersvoid
31110037SARM gem5 DevelopersSimpleIEW<Impl>::dispatchInsts()
31210037SARM gem5 Developers{
31310037SARM gem5 Developers    ////////////////////////////////////////
31410037SARM gem5 Developers    // DISPATCH/ISSUE stage
31510037SARM gem5 Developers    ////////////////////////////////////////
31610037SARM gem5 Developers
31710037SARM gem5 Developers    //Put into its own function?
31810037SARM gem5 Developers    //Add instructions to IQ if there are any instructions there
3197614Sminkyu.jeong@arm.com
3207614Sminkyu.jeong@arm.com    // Check if there are any instructions coming from rename, and we're.
32110037SARM gem5 Developers    // not squashing.
3227614Sminkyu.jeong@arm.com    if (fromRename->size > 0) {
3237614Sminkyu.jeong@arm.com        int insts_to_add = fromRename->size;
32410037SARM gem5 Developers
3257614Sminkyu.jeong@arm.com        // Loop through the instructions, putting them in the instruction
3267614Sminkyu.jeong@arm.com        // queue.
32710037SARM gem5 Developers        for (int inst_num = 0; inst_num < insts_to_add; ++inst_num)
3287614Sminkyu.jeong@arm.com        {
3297614Sminkyu.jeong@arm.com            DynInstPtr inst = fromRename->insts[inst_num];
33010037SARM gem5 Developers
3317614Sminkyu.jeong@arm.com            // Make sure there's a valid instruction there.
3327614Sminkyu.jeong@arm.com            assert(inst);
33310037SARM gem5 Developers
3347614Sminkyu.jeong@arm.com            DPRINTF(IEW, "IEW: Issue: Adding PC %#x to IQ.\n",
3357614Sminkyu.jeong@arm.com                    inst->readPC());
33610037SARM gem5 Developers
33710037SARM gem5 Developers            // Be sure to mark these instructions as ready so that the
33810037SARM gem5 Developers            // commit stage can go ahead and execute them, and mark
33910037SARM gem5 Developers            // them as issued so the IQ doesn't reprocess them.
3407614Sminkyu.jeong@arm.com            if (inst->isSquashed()) {
3417614Sminkyu.jeong@arm.com                ++iewDispSquashedInsts;
34210037SARM gem5 Developers                continue;
3437614Sminkyu.jeong@arm.com            } else if (instQueue.isFull()) {
3447614Sminkyu.jeong@arm.com                DPRINTF(IEW, "IEW: Issue: IQ has become full.\n");
3457614Sminkyu.jeong@arm.com                // Call function to start blocking.
3467614Sminkyu.jeong@arm.com                block();
34710037SARM gem5 Developers                // Tell previous stage to stall.
3487614Sminkyu.jeong@arm.com                toRename->iewInfo.stall = true;
3497614Sminkyu.jeong@arm.com
35010037SARM gem5 Developers                ++iewIQFullEvents;
35110037SARM gem5 Developers                break;
35210037SARM gem5 Developers            } else if (inst->isLoad()) {
35310037SARM gem5 Developers                DPRINTF(IEW, "IEW: Issue: Memory instruction "
35410037SARM gem5 Developers                        "encountered, adding to LDSTQ.\n");
35510037SARM gem5 Developers
35610037SARM gem5 Developers                // Reserve a spot in the load store queue for this
35710037SARM gem5 Developers                // memory access.
35810037SARM gem5 Developers                ldstQueue.insertLoad(inst);
35910037SARM gem5 Developers
36010037SARM gem5 Developers                ++iewDispLoadInsts;
36110037SARM gem5 Developers            } else if (inst->isStore()) {
36210037SARM gem5 Developers                ldstQueue.insertStore(inst);
36310037SARM gem5 Developers
36410037SARM gem5 Developers                // A bit of a hack.  Set that it can commit so that
36510037SARM gem5 Developers                // the commit stage will try committing it, and then
36610037SARM gem5 Developers                // once commit realizes it's a store it will send back
36710037SARM gem5 Developers                // a signal to this stage to issue and execute that
36810037SARM gem5 Developers                // store.  Change to be a bit that says the instruction
36910037SARM gem5 Developers                // has extra work to do at commit.
37010037SARM gem5 Developers//                inst->setCanCommit();
37110037SARM gem5 Developers
37210037SARM gem5 Developers//                instQueue.insertNonSpec(inst);
37310037SARM gem5 Developers
37410037SARM gem5 Developers                ++iewDispStoreInsts;
37510037SARM gem5 Developers//                ++iewDispNonSpecInsts;
37610037SARM gem5 Developers
37710037SARM gem5 Developers//                continue;
37810037SARM gem5 Developers            } else if (inst->isNonSpeculative()) {
37910037SARM gem5 Developers                DPRINTF(IEW, "IEW: Issue: Nonspeculative instruction "
38010037SARM gem5 Developers                        "encountered, skipping.\n");
38110037SARM gem5 Developers
38210037SARM gem5 Developers                // Same hack as with stores.
38310037SARM gem5 Developers                inst->setCanCommit();
38410037SARM gem5 Developers
38510037SARM gem5 Developers                // Specificall insert it as nonspeculative.
38610037SARM gem5 Developers                instQueue.insertNonSpec(inst);
38710037SARM gem5 Developers
38810037SARM gem5 Developers                ++iewDispNonSpecInsts;
38910037SARM gem5 Developers
39010037SARM gem5 Developers                continue;
39110037SARM gem5 Developers            } else if (inst->isNop()) {
39210037SARM gem5 Developers                DPRINTF(IEW, "IEW: Issue: Nop instruction encountered "
39310037SARM gem5 Developers                        ", skipping.\n");
39410037SARM gem5 Developers
39510037SARM gem5 Developers                inst->setIssued();
39610037SARM gem5 Developers                inst->setExecuted();
39710037SARM gem5 Developers                inst->setCanCommit();
39810037SARM gem5 Developers
39910037SARM gem5 Developers                instQueue.advanceTail(inst);
40010037SARM gem5 Developers
40110037SARM gem5 Developers                continue;
40210037SARM gem5 Developers            } else if (inst->isExecuted()) {
40310037SARM gem5 Developers                assert(0 && "Instruction shouldn't be executed.\n");
40410037SARM gem5 Developers                DPRINTF(IEW, "IEW: Issue: Executed branch encountered, "
4057614Sminkyu.jeong@arm.com                        "skipping.\n");
40610037SARM gem5 Developers
4077614Sminkyu.jeong@arm.com//                assert(inst->isDirectCtrl());
4087614Sminkyu.jeong@arm.com
40910905Sandreas.sandberg@arm.com                inst->setIssued();
4107733SAli.Saidi@ARM.com                inst->setCanCommit();
4117733SAli.Saidi@ARM.com
4127733SAli.Saidi@ARM.com                instQueue.advanceTail(inst);
41310037SARM gem5 Developers
41410037SARM gem5 Developers                continue;
41510037SARM gem5 Developers            }
41610037SARM gem5 Developers
41710037SARM gem5 Developers            // If the instruction queue is not full, then add the
41810037SARM gem5 Developers            // instruction.
4197733SAli.Saidi@ARM.com            instQueue.insert(fromRename->insts[inst_num]);
42010905Sandreas.sandberg@arm.com
4217733SAli.Saidi@ARM.com            ++iewDispatchedInsts;
4227733SAli.Saidi@ARM.com        }
4237733SAli.Saidi@ARM.com    }
4247733SAli.Saidi@ARM.com}
4257733SAli.Saidi@ARM.com
42610037SARM gem5 Developerstemplate <class Impl>
42710037SARM gem5 Developersvoid
42810037SARM gem5 DevelopersSimpleIEW<Impl>::executeInsts()
42910037SARM gem5 Developers{
43010037SARM gem5 Developers    ////////////////////////////////////////
43110037SARM gem5 Developers    //EXECUTE/WRITEBACK stage
4327733SAli.Saidi@ARM.com    ////////////////////////////////////////
4336313Sgblack@eecs.umich.edu
4349461Snilay@cs.wisc.edu    //Put into its own function?
4359461Snilay@cs.wisc.edu    //Similarly should probably have separate execution for int vs FP.
43611165SRekai.GonzalezAlberquilla@arm.com    // Above comment is handled by the issue queue only issuing a valid
43711165SRekai.GonzalezAlberquilla@arm.com    // mix of int/fp instructions.
4389553Sandreas.hansson@arm.com    //Actually okay to just have one execution, buuuuuut will need
4399553Sandreas.hansson@arm.com    //somewhere that defines the execution latency of all instructions.
4409553Sandreas.hansson@arm.com    // @todo: Move to the FU pool used in the current full cpu.
4419384SAndreas.Sandberg@arm.com
4427400SAli.Saidi@ARM.com    int fu_usage = 0;
4439384SAndreas.Sandberg@arm.com    bool fetch_redirect = false;
4449384SAndreas.Sandberg@arm.com    int inst_slot = 0;
4459384SAndreas.Sandberg@arm.com    int time_slot = 0;
4466313Sgblack@eecs.umich.edu
4476313Sgblack@eecs.umich.edu    // Execute/writeback any instructions that are available.
4486313Sgblack@eecs.umich.edu    for (int inst_num = 0;
4496313Sgblack@eecs.umich.edu         fu_usage < executeWidth && /* Haven't exceeded available FU's. */
450             inst_num < issueWidth &&
451             fromIssue->insts[inst_num];
452         ++inst_num) {
453
454        DPRINTF(IEW, "IEW: Execute: Executing instructions from IQ.\n");
455
456        // Get instruction from issue's queue.
457        DynInstPtr inst = fromIssue->insts[inst_num];
458
459        DPRINTF(IEW, "IEW: Execute: Processing PC %#x.\n", inst->readPC());
460
461        // Check if the instruction is squashed; if so then skip it
462        // and don't count it towards the FU usage.
463        if (inst->isSquashed()) {
464            DPRINTF(IEW, "IEW: Execute: Instruction was squashed.\n");
465
466            // Consider this instruction executed so that commit can go
467            // ahead and retire the instruction.
468            inst->setExecuted();
469
470            toCommit->insts[inst_num] = inst;
471
472            ++iewExecSquashedInsts;
473
474            continue;
475        }
476
477        inst->setExecuted();
478
479        // If an instruction is executed, then count it towards FU usage.
480        ++fu_usage;
481
482        // Execute instruction.
483        // Note that if the instruction faults, it will be handled
484        // at the commit stage.
485        if (inst->isMemRef()) {
486            DPRINTF(IEW, "IEW: Execute: Calculating address for memory "
487                    "reference.\n");
488
489            // Tell the LDSTQ to execute this instruction (if it is a load).
490            if (inst->isLoad()) {
491                ldstQueue.executeLoad(inst);
492
493                ++iewExecLoadInsts;
494            } else if (inst->isStore()) {
495                ldstQueue.executeStore(inst);
496
497                ++iewExecStoreInsts;
498            } else {
499                panic("IEW: Unexpected memory type!\n");
500            }
501
502        } else {
503            inst->execute();
504
505            ++iewExecutedInsts;
506        }
507
508        // First check the time slot that this instruction will write
509        // to.  If there are free write ports at the time, then go ahead
510        // and write the instruction to that time.  If there are not,
511        // keep looking back to see where's the first time there's a
512        // free slot.  What happens if you run out of free spaces?
513        // For now naively assume that all instructions take one cycle.
514        // Otherwise would have to look into the time buffer based on the
515        // latency of the instruction.
516        (*iewQueue)[time_slot].insts[inst_slot];
517        while ((*iewQueue)[time_slot].insts[inst_slot]) {
518            if (inst_slot < issueWidth) {
519                ++inst_slot;
520            } else {
521                ++time_slot;
522                inst_slot = 0;
523            }
524
525            assert(time_slot < 5);
526        }
527
528        // May actually have to work this out, especially with loads and stores
529
530        // Add finished instruction to queue to commit.
531        (*iewQueue)[time_slot].insts[inst_slot] = inst;
532        (*iewQueue)[time_slot].size++;
533
534        // Check if branch was correct.  This check happens after the
535        // instruction is added to the queue because even if the branch
536        // is mispredicted, the branch instruction itself is still valid.
537        // Only handle this if there hasn't already been something that
538        // redirects fetch in this group of instructions.
539        if (!fetch_redirect) {
540            if (inst->mispredicted()) {
541                fetch_redirect = true;
542
543                DPRINTF(IEW, "IEW: Execute: Branch mispredict detected.\n");
544                DPRINTF(IEW, "IEW: Execute: Redirecting fetch to PC: %#x.\n",
545                        inst->nextPC);
546
547                // If incorrect, then signal the ROB that it must be squashed.
548                squashDueToBranch(inst);
549
550                if (inst->predTaken()) {
551                    predictedTakenIncorrect++;
552                }
553            } else if (ldstQueue.violation()) {
554                fetch_redirect = true;
555
556                // Get the DynInst that caused the violation.
557                DynInstPtr violator = ldstQueue.getMemDepViolator();
558
559                DPRINTF(IEW, "IEW: LDSTQ detected a violation.  Violator PC: "
560                        "%#x, inst PC: %#x.  Addr is: %#x.\n",
561                        violator->readPC(), inst->readPC(), inst->physEffAddr);
562
563                // Tell the instruction queue that a violation has occured.
564                instQueue.violation(inst, violator);
565
566                // Squash.
567                squashDueToMem(inst);
568
569                ++memOrderViolationEvents;
570            }
571        }
572    }
573}
574
575template<class Impl>
576void
577SimpleIEW<Impl>::tick()
578{
579    // Considering putting all the state-determining stuff in this section.
580
581    // Try to fill up issue queue with as many instructions as bandwidth
582    // allows.
583    // Decode should try to execute as many instructions as its bandwidth
584    // will allow, as long as it is not currently blocked.
585
586    // Check if the stage is in a running status.
587    if (_status != Blocked && _status != Squashing) {
588        DPRINTF(IEW, "IEW: Status is not blocked, attempting to run "
589                     "stage.\n");
590        iew();
591
592        // If it's currently unblocking, check to see if it should switch
593        // to running.
594        if (_status == Unblocking) {
595            unblock();
596
597            ++iewUnblockCycles;
598        }
599    } else if (_status == Squashing) {
600
601        DPRINTF(IEW, "IEW: Still squashing.\n");
602
603        // Check if stage should remain squashing.  Stop squashing if the
604        // squash signal clears.
605        if (!fromCommit->commitInfo.squash &&
606            !fromCommit->commitInfo.robSquashing) {
607            DPRINTF(IEW, "IEW: Done squashing, changing status to "
608                    "running.\n");
609
610            _status = Running;
611            instQueue.stopSquash();
612        } else {
613            instQueue.doSquash();
614        }
615
616        ++iewSquashCycles;
617
618        // Also should advance its own time buffers if the stage ran.
619        // Not sure about this...
620//        issueToExecQueue.advance();
621    } else if (_status == Blocked) {
622        // Continue to tell previous stage to stall.
623        toRename->iewInfo.stall = true;
624
625        // Check if possible stall conditions have cleared.
626        if (!fromCommit->commitInfo.stall &&
627            !instQueue.isFull()) {
628            DPRINTF(IEW, "IEW: Stall signals cleared, going to unblock.\n");
629            _status = Unblocking;
630        }
631
632        // If there's still instructions coming from rename, continue to
633        // put them on the skid buffer.
634        if (fromRename->size == 0) {
635            block();
636        }
637
638        if (fromCommit->commitInfo.squash ||
639            fromCommit->commitInfo.robSquashing) {
640            squash();
641        }
642
643        ++iewBlockCycles;
644    }
645
646    // @todo: Maybe put these at the beginning, so if it's idle it can
647    // return early.
648    // Write back number of free IQ entries here.
649    toRename->iewInfo.freeIQEntries = instQueue.numFreeEntries();
650
651    ldstQueue.writebackStores();
652
653    // Check the committed load/store signals to see if there's a load
654    // or store to commit.  Also check if it's being told to execute a
655    // nonspeculative instruction.
656    // This is pretty inefficient...
657//    if (0/*fromCommit->commitInfo.commitIsStore*/) {
658    if (!fromCommit->commitInfo.squash &&
659        !fromCommit->commitInfo.robSquashing) {
660        ldstQueue.commitStores(fromCommit->commitInfo.doneSeqNum);
661//    } else if (fromCommit->commitInfo.commitIsLoad) {
662        ldstQueue.commitLoads(fromCommit->commitInfo.doneSeqNum);
663    }
664//    }
665
666    if (fromCommit->commitInfo.nonSpecSeqNum != 0) {
667        instQueue.scheduleNonSpec(fromCommit->commitInfo.nonSpecSeqNum);
668    }
669
670    DPRINTF(IEW, "IEW: IQ has %i free entries.\n",
671            instQueue.numFreeEntries());
672}
673
674template<class Impl>
675void
676SimpleIEW<Impl>::iew()
677{
678    // Might want to put all state checks in the tick() function.
679    // Check if being told to stall from commit.
680    if (fromCommit->commitInfo.stall) {
681        block();
682        return;
683    } else if (fromCommit->commitInfo.squash ||
684               fromCommit->commitInfo.robSquashing) {
685        // Also check if commit is telling this stage to squash.
686        squash();
687        return;
688    }
689
690    dispatchInsts();
691
692    // Have the instruction queue try to schedule any ready instructions.
693    instQueue.scheduleReadyInsts();
694
695    executeInsts();
696
697    // Loop through the head of the time buffer and wake any dependents.
698    // These instructions are about to write back.  In the simple model
699    // this loop can really happen within the previous loop, but when
700    // instructions have actual latencies, this loop must be separate.
701    // Also mark scoreboard that this instruction is finally complete.
702    // Either have IEW have direct access to rename map, or have this as
703    // part of backwards communication.
704    for (int inst_num = 0; inst_num < issueWidth &&
705             toCommit->insts[inst_num]; inst_num++)
706    {
707        DynInstPtr inst = toCommit->insts[inst_num];
708
709        DPRINTF(IEW, "IEW: Sending instructions to commit, PC %#x.\n",
710                inst->readPC());
711
712        if(!inst->isSquashed()) {
713            instQueue.wakeDependents(inst);
714
715            for (int i = 0; i < inst->numDestRegs(); i++)
716            {
717                renameMap->markAsReady(inst->renamedDestRegIdx(i));
718            }
719        }
720    }
721
722    // Also should advance its own time buffers if the stage ran.
723    // Not the best place for it, but this works (hopefully).
724    issueToExecQueue.advance();
725}
726
727#ifndef FULL_SYSTEM
728template<class Impl>
729void
730SimpleIEW<Impl>::lsqWriteback()
731{
732    ldstQueue.writebackAllInsts();
733}
734#endif
735