iew_impl.hh revision 2665
13560SN/A/*
23560SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan
33560SN/A * All rights reserved.
43560SN/A *
53560SN/A * Redistribution and use in source and binary forms, with or without
63560SN/A * modification, are permitted provided that the following conditions are
73560SN/A * met: redistributions of source code must retain the above copyright
83560SN/A * notice, this list of conditions and the following disclaimer;
93560SN/A * redistributions in binary form must reproduce the above copyright
103560SN/A * notice, this list of conditions and the following disclaimer in the
113560SN/A * documentation and/or other materials provided with the distribution;
123560SN/A * neither the name of the copyright holders nor the names of its
133560SN/A * contributors may be used to endorse or promote products derived from
143560SN/A * this software without specific prior written permission.
153560SN/A *
163560SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
173560SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
183560SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
193560SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
203560SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
213560SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
223560SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
233560SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
243560SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
253560SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
263560SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273560SN/A *
283560SN/A * Authors: Kevin Lim
293560SN/A */
303560SN/A
313560SN/A// @todo: Fix the instantaneous communication among all the stages within
3211793Sbrandon.potter@amd.com// iew.  There's a clear delay between issue and execute, yet backwards
3311793Sbrandon.potter@amd.com// communication happens simultaneously.
343560SN/A// Update the statuses for each stage.
353560SN/A
363560SN/A#include <queue>
373560SN/A
3811793Sbrandon.potter@amd.com#include "base/timebuf.hh"
399329Sdam.sunwoo@arm.com#include "cpu/o3/iew.hh"
403560SN/A
413560SN/Atemplate<class Impl>
428232Snate@binkert.orgSimpleIEW<Impl>::WritebackEvent::WritebackEvent(DynInstPtr &_inst,
433560SN/A                                                SimpleIEW<Impl> *_iew)
443560SN/A    : Event(&mainEventQueue, CPU_Tick_Pri), inst(_inst), iewStage(_iew)
453560SN/A{
463560SN/A    this->setFlags(Event::AutoDelete);
473560SN/A}
483560SN/A
493560SN/Atemplate<class Impl>
503560SN/Avoid
513560SN/ASimpleIEW<Impl>::WritebackEvent::process()
523560SN/A{
533560SN/A    DPRINTF(IEW, "IEW: WRITEBACK EVENT!!!!\n");
543560SN/A
553560SN/A    // Need to insert instruction into queue to commit
563560SN/A    iewStage->instToCommit(inst);
573560SN/A    // Need to execute second half of the instruction, do actual writing to
583560SN/A    // registers and such
593560SN/A    inst->execute();
603560SN/A}
613560SN/A
623560SN/Atemplate<class Impl>
633560SN/Aconst char *
643560SN/ASimpleIEW<Impl>::WritebackEvent::description()
653560SN/A{
663560SN/A    return "LSQ writeback event";
673560SN/A}
683560SN/A
693560SN/Atemplate<class Impl>
703560SN/ASimpleIEW<Impl>::SimpleIEW(Params &params)
713560SN/A    : // Just make this time buffer really big for now
723560SN/A      issueToExecQueue(5, 5),
733560SN/A      instQueue(params),
743560SN/A      ldstQueue(params),
753560SN/A      commitToIEWDelay(params.commitToIEWDelay),
763560SN/A      renameToIEWDelay(params.renameToIEWDelay),
773560SN/A      issueToExecuteDelay(params.issueToExecuteDelay),
783560SN/A      issueReadWidth(params.issueWidth),
793560SN/A      issueWidth(params.issueWidth),
803560SN/A      executeWidth(params.executeWidth)
813560SN/A{
823560SN/A    DPRINTF(IEW, "IEW: executeIntWidth: %i.\n", params.executeIntWidth);
833560SN/A    _status = Idle;
843560SN/A    _issueStatus = Idle;
853560SN/A    _exeStatus = Idle;
863560SN/A    _wbStatus = Idle;
873560SN/A
883560SN/A    // Setup wire to read instructions coming from issue.
893560SN/A    fromIssue = issueToExecQueue.getWire(-issueToExecuteDelay);
903560SN/A
913560SN/A    // Instruction queue needs the queue between issue and execute.
923560SN/A    instQueue.setIssueToExecuteQueue(&issueToExecQueue);
933560SN/A
943560SN/A    ldstQueue.setIEW(this);
953560SN/A}
963560SN/A
973560SN/Atemplate <class Impl>
983560SN/Avoid
993560SN/ASimpleIEW<Impl>::regStats()
1003560SN/A{
1013560SN/A    instQueue.regStats();
1023560SN/A
1033560SN/A    iewIdleCycles
1043560SN/A        .name(name() + ".iewIdleCycles")
1053560SN/A        .desc("Number of cycles IEW is idle");
1063560SN/A
1073560SN/A    iewSquashCycles
1083560SN/A        .name(name() + ".iewSquashCycles")
1093560SN/A        .desc("Number of cycles IEW is squashing");
1103560SN/A
1113560SN/A    iewBlockCycles
1123560SN/A        .name(name() + ".iewBlockCycles")
1133560SN/A        .desc("Number of cycles IEW is blocking");
1143560SN/A
1153560SN/A    iewUnblockCycles
1163560SN/A        .name(name() + ".iewUnblockCycles")
1173560SN/A        .desc("Number of cycles IEW is unblocking");
1183560SN/A
1193560SN/A//    iewWBInsts;
1203560SN/A
1213560SN/A    iewDispatchedInsts
1223560SN/A        .name(name() + ".iewDispatchedInsts")
1233560SN/A        .desc("Number of instructions dispatched to IQ");
1243560SN/A
1253560SN/A    iewDispSquashedInsts
1263560SN/A        .name(name() + ".iewDispSquashedInsts")
1273560SN/A        .desc("Number of squashed instructions skipped by dispatch");
1283560SN/A
1293560SN/A    iewDispLoadInsts
1303560SN/A        .name(name() + ".iewDispLoadInsts")
1313560SN/A        .desc("Number of dispatched load instructions");
1323560SN/A
1333560SN/A    iewDispStoreInsts
1343560SN/A        .name(name() + ".iewDispStoreInsts")
1353560SN/A        .desc("Number of dispatched store instructions");
1363560SN/A
1373560SN/A    iewDispNonSpecInsts
1383560SN/A        .name(name() + ".iewDispNonSpecInsts")
1393560SN/A        .desc("Number of dispatched non-speculative instructions");
1403560SN/A
1413560SN/A    iewIQFullEvents
1425191Ssaidi@eecs.umich.edu        .name(name() + ".iewIQFullEvents")
1435191Ssaidi@eecs.umich.edu        .desc("Number of times the IQ has become full, causing a stall");
1445191Ssaidi@eecs.umich.edu
1453560SN/A    iewExecutedInsts
1463560SN/A        .name(name() + ".iewExecutedInsts")
1477823Ssteve.reinhardt@amd.com        .desc("Number of executed instructions");
1483560SN/A
1497823Ssteve.reinhardt@amd.com    iewExecLoadInsts
1503560SN/A        .name(name() + ".iewExecLoadInsts")
1513560SN/A        .desc("Number of load instructions executed");
1523560SN/A
1533560SN/A    iewExecStoreInsts
1543560SN/A        .name(name() + ".iewExecStoreInsts")
1553560SN/A        .desc("Number of store instructions executed");
1565568Snate@binkert.org
1573560SN/A    iewExecSquashedInsts
1583560SN/A        .name(name() + ".iewExecSquashedInsts")
1593560SN/A        .desc("Number of squashed instructions skipped in execute");
1603560SN/A
1613560SN/A    memOrderViolationEvents
1623560SN/A        .name(name() + ".memOrderViolationEvents")
1633560SN/A        .desc("Number of memory order violations");
1643560SN/A
1653560SN/A    predictedTakenIncorrect
1663560SN/A        .name(name() + ".predictedTakenIncorrect")
1673560SN/A        .desc("Number of branches that were predicted taken incorrectly");
1683560SN/A}
1693560SN/A
1703560SN/Atemplate<class Impl>
1715191Ssaidi@eecs.umich.eduvoid
1725191Ssaidi@eecs.umich.eduSimpleIEW<Impl>::setCPU(FullCPU *cpu_ptr)
1735191Ssaidi@eecs.umich.edu{
1745191Ssaidi@eecs.umich.edu    DPRINTF(IEW, "IEW: Setting CPU pointer.\n");
1753560SN/A    cpu = cpu_ptr;
1763560SN/A
1773560SN/A    instQueue.setCPU(cpu_ptr);
1783560SN/A    ldstQueue.setCPU(cpu_ptr);
1793560SN/A}
1803560SN/A
1813560SN/Atemplate<class Impl>
1823560SN/Avoid
1833560SN/ASimpleIEW<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
1843560SN/A{
1853560SN/A    DPRINTF(IEW, "IEW: Setting time buffer pointer.\n");
1863560SN/A    timeBuffer = tb_ptr;
18710905Sandreas.sandberg@arm.com
1883560SN/A    // Setup wire to read information from time buffer, from commit.
18910905Sandreas.sandberg@arm.com    fromCommit = timeBuffer->getWire(-commitToIEWDelay);
1903560SN/A
1913560SN/A    // Setup wire to write information back to previous stages.
1923560SN/A    toRename = timeBuffer->getWire(0);
1933560SN/A
1943560SN/A    // Instruction queue also needs main time buffer.
1953560SN/A    instQueue.setTimeBuffer(tb_ptr);
1963560SN/A}
19710905Sandreas.sandberg@arm.com
1983560SN/Atemplate<class Impl>
19910905Sandreas.sandberg@arm.comvoid
2003560SN/ASimpleIEW<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
2013560SN/A{
2023560SN/A    DPRINTF(IEW, "IEW: Setting rename queue pointer.\n");
2033560SN/A    renameQueue = rq_ptr;
2043560SN/A
2053560SN/A    // Setup wire to read information from rename queue.
2063560SN/A    fromRename = renameQueue->getWire(-renameToIEWDelay);
2075568Snate@binkert.org}
2085568Snate@binkert.org
209template<class Impl>
210void
211SimpleIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
212{
213    DPRINTF(IEW, "IEW: Setting IEW queue pointer.\n");
214    iewQueue = iq_ptr;
215
216    // Setup wire to write instructions to commit.
217    toCommit = iewQueue->getWire(0);
218}
219
220template<class Impl>
221void
222SimpleIEW<Impl>::setRenameMap(RenameMap *rm_ptr)
223{
224    DPRINTF(IEW, "IEW: Setting rename map pointer.\n");
225    renameMap = rm_ptr;
226}
227
228template<class Impl>
229void
230SimpleIEW<Impl>::squash()
231{
232    DPRINTF(IEW, "IEW: Squashing all instructions.\n");
233    _status = Squashing;
234
235    // Tell the IQ to start squashing.
236    instQueue.squash();
237
238    // Tell the LDSTQ to start squashing.
239    ldstQueue.squash(fromCommit->commitInfo.doneSeqNum);
240}
241
242template<class Impl>
243void
244SimpleIEW<Impl>::squashDueToBranch(DynInstPtr &inst)
245{
246    DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n",
247            inst->PC);
248    // Perhaps leave the squashing up to the ROB stage to tell it when to
249    // squash?
250    _status = Squashing;
251
252    // Tell rename to squash through the time buffer.
253    toCommit->squash = true;
254    // Also send PC update information back to prior stages.
255    toCommit->squashedSeqNum = inst->seqNum;
256    toCommit->mispredPC = inst->readPC();
257    toCommit->nextPC = inst->readNextPC();
258    toCommit->branchMispredict = true;
259    // Prediction was incorrect, so send back inverse.
260    toCommit->branchTaken = inst->readNextPC() !=
261        (inst->readPC() + sizeof(TheISA::MachInst));
262}
263
264template<class Impl>
265void
266SimpleIEW<Impl>::squashDueToMem(DynInstPtr &inst)
267{
268    DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n",
269            inst->PC);
270    // Perhaps leave the squashing up to the ROB stage to tell it when to
271    // squash?
272    _status = Squashing;
273
274    // Tell rename to squash through the time buffer.
275    toCommit->squash = true;
276    // Also send PC update information back to prior stages.
277    toCommit->squashedSeqNum = inst->seqNum;
278    toCommit->nextPC = inst->readNextPC();
279}
280
281template<class Impl>
282void
283SimpleIEW<Impl>::block()
284{
285    DPRINTF(IEW, "IEW: Blocking.\n");
286    // Set the status to Blocked.
287    _status = Blocked;
288
289    // Add the current inputs to the skid buffer so they can be
290    // reprocessed when this stage unblocks.
291    skidBuffer.push(*fromRename);
292
293    // Note that this stage only signals previous stages to stall when
294    // it is the cause of the stall originates at this stage.  Otherwise
295    // the previous stages are expected to check all possible stall signals.
296}
297
298template<class Impl>
299inline void
300SimpleIEW<Impl>::unblock()
301{
302    // Check if there's information in the skid buffer.  If there is, then
303    // set status to unblocking, otherwise set it directly to running.
304    DPRINTF(IEW, "IEW: Reading instructions out of the skid "
305            "buffer.\n");
306    // Remove the now processed instructions from the skid buffer.
307    skidBuffer.pop();
308
309    // If there's still information in the skid buffer, then
310    // continue to tell previous stages to stall.  They will be
311    // able to restart once the skid buffer is empty.
312    if (!skidBuffer.empty()) {
313        toRename->iewInfo.stall = true;
314    } else {
315        DPRINTF(IEW, "IEW: Stage is done unblocking.\n");
316        _status = Running;
317    }
318}
319
320template<class Impl>
321void
322SimpleIEW<Impl>::wakeDependents(DynInstPtr &inst)
323{
324    instQueue.wakeDependents(inst);
325}
326
327
328template<class Impl>
329void
330SimpleIEW<Impl>::instToCommit(DynInstPtr &inst)
331{
332
333}
334
335template <class Impl>
336void
337SimpleIEW<Impl>::dispatchInsts()
338{
339    ////////////////////////////////////////
340    // DISPATCH/ISSUE stage
341    ////////////////////////////////////////
342
343    //Put into its own function?
344    //Add instructions to IQ if there are any instructions there
345
346    // Check if there are any instructions coming from rename, and we're.
347    // not squashing.
348    if (fromRename->size > 0) {
349        int insts_to_add = fromRename->size;
350
351        // Loop through the instructions, putting them in the instruction
352        // queue.
353        for (int inst_num = 0; inst_num < insts_to_add; ++inst_num)
354        {
355            DynInstPtr inst = fromRename->insts[inst_num];
356
357            // Make sure there's a valid instruction there.
358            assert(inst);
359
360            DPRINTF(IEW, "IEW: Issue: Adding PC %#x to IQ.\n",
361                    inst->readPC());
362
363            // Be sure to mark these instructions as ready so that the
364            // commit stage can go ahead and execute them, and mark
365            // them as issued so the IQ doesn't reprocess them.
366            if (inst->isSquashed()) {
367                ++iewDispSquashedInsts;
368                continue;
369            } else if (instQueue.isFull()) {
370                DPRINTF(IEW, "IEW: Issue: IQ has become full.\n");
371                // Call function to start blocking.
372                block();
373                // Tell previous stage to stall.
374                toRename->iewInfo.stall = true;
375
376                ++iewIQFullEvents;
377                break;
378            } else if (inst->isLoad()) {
379                DPRINTF(IEW, "IEW: Issue: Memory instruction "
380                        "encountered, adding to LDSTQ.\n");
381
382                // Reserve a spot in the load store queue for this
383                // memory access.
384                ldstQueue.insertLoad(inst);
385
386                ++iewDispLoadInsts;
387            } else if (inst->isStore()) {
388                ldstQueue.insertStore(inst);
389
390                ++iewDispStoreInsts;
391            } else if (inst->isNonSpeculative()) {
392                DPRINTF(IEW, "IEW: Issue: Nonspeculative instruction "
393                        "encountered, skipping.\n");
394
395                // Same hack as with stores.
396                inst->setCanCommit();
397
398                // Specificall insert it as nonspeculative.
399                instQueue.insertNonSpec(inst);
400
401                ++iewDispNonSpecInsts;
402
403                continue;
404            } else if (inst->isNop()) {
405                DPRINTF(IEW, "IEW: Issue: Nop instruction encountered "
406                        ", skipping.\n");
407
408                inst->setIssued();
409                inst->setExecuted();
410                inst->setCanCommit();
411
412                instQueue.advanceTail(inst);
413
414                continue;
415            } else if (inst->isExecuted()) {
416                assert(0 && "Instruction shouldn't be executed.\n");
417                DPRINTF(IEW, "IEW: Issue: Executed branch encountered, "
418                        "skipping.\n");
419
420                inst->setIssued();
421                inst->setCanCommit();
422
423                instQueue.advanceTail(inst);
424
425                continue;
426            }
427
428            // If the instruction queue is not full, then add the
429            // instruction.
430            instQueue.insert(fromRename->insts[inst_num]);
431
432            ++iewDispatchedInsts;
433        }
434    }
435}
436
437template <class Impl>
438void
439SimpleIEW<Impl>::executeInsts()
440{
441    ////////////////////////////////////////
442    //EXECUTE/WRITEBACK stage
443    ////////////////////////////////////////
444
445    //Put into its own function?
446    //Similarly should probably have separate execution for int vs FP.
447    // Above comment is handled by the issue queue only issuing a valid
448    // mix of int/fp instructions.
449    //Actually okay to just have one execution, buuuuuut will need
450    //somewhere that defines the execution latency of all instructions.
451    // @todo: Move to the FU pool used in the current full cpu.
452
453    int fu_usage = 0;
454    bool fetch_redirect = false;
455    int inst_slot = 0;
456    int time_slot = 0;
457
458    // Execute/writeback any instructions that are available.
459    for (int inst_num = 0;
460         fu_usage < executeWidth && /* Haven't exceeded available FU's. */
461             inst_num < issueWidth &&
462             fromIssue->insts[inst_num];
463         ++inst_num) {
464
465        DPRINTF(IEW, "IEW: Execute: Executing instructions from IQ.\n");
466
467        // Get instruction from issue's queue.
468        DynInstPtr inst = fromIssue->insts[inst_num];
469
470        DPRINTF(IEW, "IEW: Execute: Processing PC %#x.\n", inst->readPC());
471
472        // Check if the instruction is squashed; if so then skip it
473        // and don't count it towards the FU usage.
474        if (inst->isSquashed()) {
475            DPRINTF(IEW, "IEW: Execute: Instruction was squashed.\n");
476
477            // Consider this instruction executed so that commit can go
478            // ahead and retire the instruction.
479            inst->setExecuted();
480
481            toCommit->insts[inst_num] = inst;
482
483            ++iewExecSquashedInsts;
484
485            continue;
486        }
487
488        inst->setExecuted();
489
490        // If an instruction is executed, then count it towards FU usage.
491        ++fu_usage;
492
493        // Execute instruction.
494        // Note that if the instruction faults, it will be handled
495        // at the commit stage.
496        if (inst->isMemRef()) {
497            DPRINTF(IEW, "IEW: Execute: Calculating address for memory "
498                    "reference.\n");
499
500            // Tell the LDSTQ to execute this instruction (if it is a load).
501            if (inst->isLoad()) {
502                ldstQueue.executeLoad(inst);
503
504                ++iewExecLoadInsts;
505            } else if (inst->isStore()) {
506                ldstQueue.executeStore(inst);
507
508                ++iewExecStoreInsts;
509            } else {
510                panic("IEW: Unexpected memory type!\n");
511            }
512
513        } else {
514            inst->execute();
515
516            ++iewExecutedInsts;
517        }
518
519        // First check the time slot that this instruction will write
520        // to.  If there are free write ports at the time, then go ahead
521        // and write the instruction to that time.  If there are not,
522        // keep looking back to see where's the first time there's a
523        // free slot.  What happens if you run out of free spaces?
524        // For now naively assume that all instructions take one cycle.
525        // Otherwise would have to look into the time buffer based on the
526        // latency of the instruction.
527        (*iewQueue)[time_slot].insts[inst_slot];
528        while ((*iewQueue)[time_slot].insts[inst_slot]) {
529            if (inst_slot < issueWidth) {
530                ++inst_slot;
531            } else {
532                ++time_slot;
533                inst_slot = 0;
534            }
535
536            assert(time_slot < 5);
537        }
538
539        // May actually have to work this out, especially with loads and stores
540
541        // Add finished instruction to queue to commit.
542        (*iewQueue)[time_slot].insts[inst_slot] = inst;
543        (*iewQueue)[time_slot].size++;
544
545        // Check if branch was correct.  This check happens after the
546        // instruction is added to the queue because even if the branch
547        // is mispredicted, the branch instruction itself is still valid.
548        // Only handle this if there hasn't already been something that
549        // redirects fetch in this group of instructions.
550        if (!fetch_redirect) {
551            if (inst->mispredicted()) {
552                fetch_redirect = true;
553
554                DPRINTF(IEW, "IEW: Execute: Branch mispredict detected.\n");
555                DPRINTF(IEW, "IEW: Execute: Redirecting fetch to PC: %#x.\n",
556                        inst->nextPC);
557
558                // If incorrect, then signal the ROB that it must be squashed.
559                squashDueToBranch(inst);
560
561                if (inst->predTaken()) {
562                    predictedTakenIncorrect++;
563                }
564            } else if (ldstQueue.violation()) {
565                fetch_redirect = true;
566
567                // Get the DynInst that caused the violation.
568                DynInstPtr violator = ldstQueue.getMemDepViolator();
569
570                DPRINTF(IEW, "IEW: LDSTQ detected a violation.  Violator PC: "
571                        "%#x, inst PC: %#x.  Addr is: %#x.\n",
572                        violator->readPC(), inst->readPC(), inst->physEffAddr);
573
574                // Tell the instruction queue that a violation has occured.
575                instQueue.violation(inst, violator);
576
577                // Squash.
578                squashDueToMem(inst);
579
580                ++memOrderViolationEvents;
581            }
582        }
583    }
584}
585
586template<class Impl>
587void
588SimpleIEW<Impl>::tick()
589{
590    // Considering putting all the state-determining stuff in this section.
591
592    // Try to fill up issue queue with as many instructions as bandwidth
593    // allows.
594    // Decode should try to execute as many instructions as its bandwidth
595    // will allow, as long as it is not currently blocked.
596
597    // Check if the stage is in a running status.
598    if (_status != Blocked && _status != Squashing) {
599        DPRINTF(IEW, "IEW: Status is not blocked, attempting to run "
600                     "stage.\n");
601        iew();
602
603        // If it's currently unblocking, check to see if it should switch
604        // to running.
605        if (_status == Unblocking) {
606            unblock();
607
608            ++iewUnblockCycles;
609        }
610    } else if (_status == Squashing) {
611
612        DPRINTF(IEW, "IEW: Still squashing.\n");
613
614        // Check if stage should remain squashing.  Stop squashing if the
615        // squash signal clears.
616        if (!fromCommit->commitInfo.squash &&
617            !fromCommit->commitInfo.robSquashing) {
618            DPRINTF(IEW, "IEW: Done squashing, changing status to "
619                    "running.\n");
620
621            _status = Running;
622            instQueue.stopSquash();
623        } else {
624            instQueue.doSquash();
625        }
626
627        ++iewSquashCycles;
628    } else if (_status == Blocked) {
629        // Continue to tell previous stage to stall.
630        toRename->iewInfo.stall = true;
631
632        // Check if possible stall conditions have cleared.
633        if (!fromCommit->commitInfo.stall &&
634            !instQueue.isFull()) {
635            DPRINTF(IEW, "IEW: Stall signals cleared, going to unblock.\n");
636            _status = Unblocking;
637        }
638
639        // If there's still instructions coming from rename, continue to
640        // put them on the skid buffer.
641        if (fromRename->size == 0) {
642            block();
643        }
644
645        if (fromCommit->commitInfo.squash ||
646            fromCommit->commitInfo.robSquashing) {
647            squash();
648        }
649
650        ++iewBlockCycles;
651    }
652
653    // @todo: Maybe put these at the beginning, so if it's idle it can
654    // return early.
655    // Write back number of free IQ entries here.
656    toRename->iewInfo.freeIQEntries = instQueue.numFreeEntries();
657
658    ldstQueue.writebackStores();
659
660    // Check the committed load/store signals to see if there's a load
661    // or store to commit.  Also check if it's being told to execute a
662    // nonspeculative instruction.
663    // This is pretty inefficient...
664    if (!fromCommit->commitInfo.squash &&
665        !fromCommit->commitInfo.robSquashing) {
666        ldstQueue.commitStores(fromCommit->commitInfo.doneSeqNum);
667        ldstQueue.commitLoads(fromCommit->commitInfo.doneSeqNum);
668    }
669
670    if (fromCommit->commitInfo.nonSpecSeqNum != 0) {
671        instQueue.scheduleNonSpec(fromCommit->commitInfo.nonSpecSeqNum);
672    }
673
674    DPRINTF(IEW, "IEW: IQ has %i free entries.\n",
675            instQueue.numFreeEntries());
676}
677
678template<class Impl>
679void
680SimpleIEW<Impl>::iew()
681{
682    // Might want to put all state checks in the tick() function.
683    // Check if being told to stall from commit.
684    if (fromCommit->commitInfo.stall) {
685        block();
686        return;
687    } else if (fromCommit->commitInfo.squash ||
688               fromCommit->commitInfo.robSquashing) {
689        // Also check if commit is telling this stage to squash.
690        squash();
691        return;
692    }
693
694    dispatchInsts();
695
696    // Have the instruction queue try to schedule any ready instructions.
697    instQueue.scheduleReadyInsts();
698
699    executeInsts();
700
701    // Loop through the head of the time buffer and wake any dependents.
702    // These instructions are about to write back.  In the simple model
703    // this loop can really happen within the previous loop, but when
704    // instructions have actual latencies, this loop must be separate.
705    // Also mark scoreboard that this instruction is finally complete.
706    // Either have IEW have direct access to rename map, or have this as
707    // part of backwards communication.
708    for (int inst_num = 0; inst_num < issueWidth &&
709             toCommit->insts[inst_num]; inst_num++)
710    {
711        DynInstPtr inst = toCommit->insts[inst_num];
712
713        DPRINTF(IEW, "IEW: Sending instructions to commit, PC %#x.\n",
714                inst->readPC());
715
716        if(!inst->isSquashed()) {
717            instQueue.wakeDependents(inst);
718
719            for (int i = 0; i < inst->numDestRegs(); i++)
720            {
721                renameMap->markAsReady(inst->renamedDestRegIdx(i));
722            }
723        }
724    }
725
726    // Also should advance its own time buffers if the stage ran.
727    // Not the best place for it, but this works (hopefully).
728    issueToExecQueue.advance();
729}
730
731#if !FULL_SYSTEM
732template<class Impl>
733void
734SimpleIEW<Impl>::lsqWriteback()
735{
736    ldstQueue.writebackAllInsts();
737}
738#endif
739