iew_impl.hh revision 1689
18839Sandreas.hansson@arm.com/*
28839Sandreas.hansson@arm.com * Copyright (c) 2004-2005 The Regents of The University of Michigan
38839Sandreas.hansson@arm.com * All rights reserved.
48839Sandreas.hansson@arm.com *
58839Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
68839Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are
78839Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
88839Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
98839Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
108839Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
118839Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
128839Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its
135335Shines@cs.fsu.edu * contributors may be used to endorse or promote products derived from
147897Shestness@cs.utexas.edu * this software without specific prior written permission.
154486Sbinkertn@umich.edu *
164486Sbinkertn@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
174486Sbinkertn@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
184486Sbinkertn@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
194486Sbinkertn@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
204486Sbinkertn@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
214486Sbinkertn@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
224486Sbinkertn@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
234486Sbinkertn@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
244486Sbinkertn@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
254486Sbinkertn@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
264486Sbinkertn@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
274486Sbinkertn@umich.edu */
284486Sbinkertn@umich.edu
294486Sbinkertn@umich.edu// @todo: Fix the instantaneous communication among all the stages within
304486Sbinkertn@umich.edu// iew.  There's a clear delay between issue and execute, yet backwards
314486Sbinkertn@umich.edu// communication happens simultaneously.
324486Sbinkertn@umich.edu// Update the statuses for each stage.
334486Sbinkertn@umich.edu
344486Sbinkertn@umich.edu#include <queue>
354486Sbinkertn@umich.edu
364486Sbinkertn@umich.edu#include "base/timebuf.hh"
374486Sbinkertn@umich.edu#include "cpu/beta_cpu/iew.hh"
384486Sbinkertn@umich.edu
394486Sbinkertn@umich.edutemplate<class Impl>
404486Sbinkertn@umich.eduSimpleIEW<Impl>::WritebackEvent::WritebackEvent(DynInstPtr &_inst,
417897Shestness@cs.utexas.edu                                                SimpleIEW<Impl> *_iew)
428839Sandreas.hansson@arm.com    : Event(&mainEventQueue, CPU_Tick_Pri), inst(_inst), iewStage(_iew)
434486Sbinkertn@umich.edu{
446654Snate@binkert.org    this->setFlags(Event::AutoDelete);
456654Snate@binkert.org}
466654Snate@binkert.org
473102SN/Atemplate<class Impl>
483102SN/Avoid
496654Snate@binkert.orgSimpleIEW<Impl>::WritebackEvent::process()
502998SN/A{
514776Sgblack@eecs.umich.edu    DPRINTF(IEW, "IEW: WRITEBACK EVENT!!!!\n");
524776Sgblack@eecs.umich.edu
536654Snate@binkert.org    // Need to insert instruction into queue to commit
542667SN/A    iewStage->instToCommit(inst);
554776Sgblack@eecs.umich.edu    // Need to execute second half of the instruction, do actual writing to
564776Sgblack@eecs.umich.edu    // registers and such
576654Snate@binkert.org    inst->execute();
586023Snate@binkert.org}
598745Sgblack@eecs.umich.edu
606654Snate@binkert.orgtemplate<class Impl>
616022Sgblack@eecs.umich.educonst char *
628745Sgblack@eecs.umich.eduSimpleIEW<Impl>::WritebackEvent::description()
636654Snate@binkert.org{
646022Sgblack@eecs.umich.edu    return "LSQ writeback event";
658745Sgblack@eecs.umich.edu}
666654Snate@binkert.org
676022Sgblack@eecs.umich.edutemplate<class Impl>
688745Sgblack@eecs.umich.eduSimpleIEW<Impl>::SimpleIEW(Params &params)
696654Snate@binkert.org    : // Just make this time buffer really big for now
706116Snate@binkert.org      issueToExecQueue(5, 5),
718745Sgblack@eecs.umich.edu      instQueue(params),
726691Stjones1@inf.ed.ac.uk      ldstQueue(params),
736691Stjones1@inf.ed.ac.uk      commitToIEWDelay(params.commitToIEWDelay),
748745Sgblack@eecs.umich.edu      renameToIEWDelay(params.renameToIEWDelay),
754486Sbinkertn@umich.edu      issueToExecuteDelay(params.issueToExecuteDelay),
765529Snate@binkert.org      issueReadWidth(params.issueWidth),
771366SN/A      issueWidth(params.issueWidth),
781310SN/A      executeWidth(params.executeWidth)
791310SN/A{
802901SN/A    DPRINTF(IEW, "IEW: executeIntWidth: %i.\n", params.executeIntWidth);
815712Shsul@eecs.umich.edu    _status = Idle;
825529Snate@binkert.org    _issueStatus = Idle;
835529Snate@binkert.org    _exeStatus = Idle;
845529Snate@binkert.org    _wbStatus = Idle;
855529Snate@binkert.org
865529Snate@binkert.org    // Setup wire to read instructions coming from issue.
875821Ssaidi@eecs.umich.edu    fromIssue = issueToExecQueue.getWire(-issueToExecuteDelay);
883170SN/A
895780Ssteve.reinhardt@amd.com    // Instruction queue needs the queue between issue and execute.
905780Ssteve.reinhardt@amd.com    instQueue.setIssueToExecuteQueue(&issueToExecQueue);
915780Ssteve.reinhardt@amd.com
925780Ssteve.reinhardt@amd.com    ldstQueue.setIEW(this);
935780Ssteve.reinhardt@amd.com}
948784Sgblack@eecs.umich.edu
958784Sgblack@eecs.umich.edutemplate <class Impl>
968784Sgblack@eecs.umich.eduvoid
978793Sgblack@eecs.umich.eduSimpleIEW<Impl>::regStats()
981310SN/A{
996654Snate@binkert.org    instQueue.regStats();
1006022Sgblack@eecs.umich.edu
1016022Sgblack@eecs.umich.edu    iewIdleCycles
1028745Sgblack@eecs.umich.edu        .name(name() + ".iewIdleCycles")
1038863Snilay@cs.wisc.edu        .desc("Number of cycles IEW is idle");
1046654Snate@binkert.org
1056023Snate@binkert.org    iewSquashCycles
1066023Snate@binkert.org        .name(name() + ".iewSquashCycles")
1078745Sgblack@eecs.umich.edu        .desc("Number of cycles IEW is squashing");
1088863Snilay@cs.wisc.edu
1096654Snate@binkert.org    iewBlockCycles
1106022Sgblack@eecs.umich.edu        .name(name() + ".iewBlockCycles")
1116022Sgblack@eecs.umich.edu        .desc("Number of cycles IEW is blocking");
1128863Snilay@cs.wisc.edu
1136654Snate@binkert.org    iewUnblockCycles
1146022Sgblack@eecs.umich.edu        .name(name() + ".iewUnblockCycles")
1156022Sgblack@eecs.umich.edu        .desc("Number of cycles IEW is unblocking");
1168745Sgblack@eecs.umich.edu
1178863Snilay@cs.wisc.edu//    iewWBInsts;
1186654Snate@binkert.org
1196116Snate@binkert.org    iewDispatchedInsts
1206116Snate@binkert.org        .name(name() + ".iewDispatchedInsts")
1218745Sgblack@eecs.umich.edu        .desc("Number of instructions dispatched to IQ");
1228863Snilay@cs.wisc.edu
1236691Stjones1@inf.ed.ac.uk    iewDispSquashedInsts
1246691Stjones1@inf.ed.ac.uk        .name(name() + ".iewDispSquashedInsts")
1256691Stjones1@inf.ed.ac.uk        .desc("Number of squashed instructions skipped by dispatch");
1266691Stjones1@inf.ed.ac.uk
1278745Sgblack@eecs.umich.edu    iewDispLoadInsts
1288863Snilay@cs.wisc.edu        .name(name() + ".iewDispLoadInsts")
1294997Sgblack@eecs.umich.edu        .desc("Number of dispatched load instructions");
1304997Sgblack@eecs.umich.edu
1316654Snate@binkert.org    iewDispStoreInsts
1324997Sgblack@eecs.umich.edu        .name(name() + ".iewDispStoreInsts")
1334997Sgblack@eecs.umich.edu        .desc("Number of dispatched store instructions");
1341310SN/A
1351310SN/A    iewDispNonSpecInsts
1361310SN/A        .name(name() + ".iewDispNonSpecInsts")
1371310SN/A        .desc("Number of dispatched non-speculative instructions");
1381310SN/A
1391310SN/A    iewIQFullEvents
1401310SN/A        .name(name() + ".iewIQFullEvents")
1411310SN/A        .desc("Number of times the IQ has become full, causing a stall");
1423878SN/A
1433878SN/A    iewExecutedInsts
1441310SN/A        .name(name() + ".iewExecutedInsts")
1451369SN/A        .desc("Number of executed instructions");
1461310SN/A
1471634SN/A    iewExecLoadInsts
1484167SN/A        .name(name() + ".iewExecLoadInsts")
1494167SN/A        .desc("Number of load instructions executed");
1502998SN/A
1514776Sgblack@eecs.umich.edu    iewExecStoreInsts
1524776Sgblack@eecs.umich.edu        .name(name() + ".iewExecStoreInsts")
1538839Sandreas.hansson@arm.com        .desc("Number of store instructions executed");
1548839Sandreas.hansson@arm.com
1558707Sandreas.hansson@arm.com    iewExecSquashedInsts
1568707Sandreas.hansson@arm.com        .name(name() + ".iewExecSquashedInsts")
1578756Sgblack@eecs.umich.edu        .desc("Number of squashed instructions skipped in execute");
1588707Sandreas.hansson@arm.com
1597876Sgblack@eecs.umich.edu    memOrderViolationEvents
1608839Sandreas.hansson@arm.com        .name(name() + ".memOrderViolationEvents")
1618839Sandreas.hansson@arm.com        .desc("Number of memory order violations");
1628745Sgblack@eecs.umich.edu
1638839Sandreas.hansson@arm.com    predictedTakenIncorrect
1648839Sandreas.hansson@arm.com        .name(name() + ".predictedTakenIncorrect")
1652998SN/A        .desc("Number of branches that were predicted taken incorrectly");
1668863Snilay@cs.wisc.edu}
1678863Snilay@cs.wisc.edu
1688863Snilay@cs.wisc.edutemplate<class Impl>
1698863Snilay@cs.wisc.eduvoid
1708863Snilay@cs.wisc.eduSimpleIEW<Impl>::setCPU(FullCPU *cpu_ptr)
1718863Snilay@cs.wisc.edu{
1728863Snilay@cs.wisc.edu    DPRINTF(IEW, "IEW: Setting CPU pointer.\n");
1738863Snilay@cs.wisc.edu    cpu = cpu_ptr;
1748863Snilay@cs.wisc.edu
1758863Snilay@cs.wisc.edu    instQueue.setCPU(cpu_ptr);
1768863Snilay@cs.wisc.edu    ldstQueue.setCPU(cpu_ptr);
1778863Snilay@cs.wisc.edu}
1788863Snilay@cs.wisc.edu
1798863Snilay@cs.wisc.edutemplate<class Impl>
1808863Snilay@cs.wisc.eduvoid
1818863Snilay@cs.wisc.eduSimpleIEW<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
1828863Snilay@cs.wisc.edu{
1838863Snilay@cs.wisc.edu    DPRINTF(IEW, "IEW: Setting time buffer pointer.\n");
1848863Snilay@cs.wisc.edu    timeBuffer = tb_ptr;
1857876Sgblack@eecs.umich.edu
1867876Sgblack@eecs.umich.edu    // Setup wire to read information from time buffer, from commit.
1878839Sandreas.hansson@arm.com    fromCommit = timeBuffer->getWire(-commitToIEWDelay);
1887404SAli.Saidi@ARM.com
1897876Sgblack@eecs.umich.edu    // Setup wire to write information back to previous stages.
1908839Sandreas.hansson@arm.com    toRename = timeBuffer->getWire(0);
1918839Sandreas.hansson@arm.com
1928839Sandreas.hansson@arm.com    // Instruction queue also needs main time buffer.
1938839Sandreas.hansson@arm.com    instQueue.setTimeBuffer(tb_ptr);
1947876Sgblack@eecs.umich.edu}
1957876Sgblack@eecs.umich.edu
1967876Sgblack@eecs.umich.edutemplate<class Impl>
1977876Sgblack@eecs.umich.eduvoid
1987876Sgblack@eecs.umich.eduSimpleIEW<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
1997876Sgblack@eecs.umich.edu{
2002998SN/A    DPRINTF(IEW, "IEW: Setting rename queue pointer.\n");
2017868Sgblack@eecs.umich.edu    renameQueue = rq_ptr;
2022998SN/A
2032998SN/A    // Setup wire to read information from rename queue.
2042998SN/A    fromRename = renameQueue->getWire(-renameToIEWDelay);
2052998SN/A}
2067876Sgblack@eecs.umich.edu
2078796Sgblack@eecs.umich.edutemplate<class Impl>
2088796Sgblack@eecs.umich.eduvoid
2098796Sgblack@eecs.umich.eduSimpleIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
2108796Sgblack@eecs.umich.edu{
2118796Sgblack@eecs.umich.edu    DPRINTF(IEW, "IEW: Setting IEW queue pointer.\n");
2128796Sgblack@eecs.umich.edu    iewQueue = iq_ptr;
2138796Sgblack@eecs.umich.edu
2148796Sgblack@eecs.umich.edu    // Setup wire to write instructions to commit.
2158796Sgblack@eecs.umich.edu    toCommit = iewQueue->getWire(0);
2168796Sgblack@eecs.umich.edu}
2178809Sgblack@eecs.umich.edu
2188809Sgblack@eecs.umich.edutemplate<class Impl>
2198809Sgblack@eecs.umich.eduvoid
2208809Sgblack@eecs.umich.eduSimpleIEW<Impl>::setRenameMap(RenameMap *rm_ptr)
2218809Sgblack@eecs.umich.edu{
2222998SN/A    DPRINTF(IEW, "IEW: Setting rename map pointer.\n");
2237868Sgblack@eecs.umich.edu    renameMap = rm_ptr;
2247868Sgblack@eecs.umich.edu}
2252998SN/A
2267876Sgblack@eecs.umich.edutemplate<class Impl>
2272998SN/Avoid
2288839Sandreas.hansson@arm.comSimpleIEW<Impl>::squash()
2297876Sgblack@eecs.umich.edu{
230    DPRINTF(IEW, "IEW: Squashing all instructions.\n");
231    _status = Squashing;
232
233    // Tell the IQ to start squashing.
234    instQueue.squash();
235
236    // Tell the LDSTQ to start squashing.
237    ldstQueue.squash(fromCommit->commitInfo.doneSeqNum);
238}
239
240template<class Impl>
241void
242SimpleIEW<Impl>::squashDueToBranch(DynInstPtr &inst)
243{
244    DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n",
245            inst->PC);
246    // Perhaps leave the squashing up to the ROB stage to tell it when to
247    // squash?
248    _status = Squashing;
249
250    // Tell rename to squash through the time buffer.
251    toCommit->squash = true;
252    // Also send PC update information back to prior stages.
253    toCommit->squashedSeqNum = inst->seqNum;
254    toCommit->mispredPC = inst->readPC();
255    toCommit->nextPC = inst->readNextPC();
256    toCommit->branchMispredict = true;
257    // Prediction was incorrect, so send back inverse.
258    toCommit->branchTaken = inst->readNextPC() !=
259        (inst->readPC() + sizeof(MachInst));
260}
261
262template<class Impl>
263void
264SimpleIEW<Impl>::squashDueToMem(DynInstPtr &inst)
265{
266    DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n",
267            inst->PC);
268    // Perhaps leave the squashing up to the ROB stage to tell it when to
269    // squash?
270    _status = Squashing;
271
272    // Tell rename to squash through the time buffer.
273    toCommit->squash = true;
274    // Also send PC update information back to prior stages.
275    toCommit->squashedSeqNum = inst->seqNum;
276    toCommit->nextPC = inst->readNextPC();
277}
278
279template<class Impl>
280void
281SimpleIEW<Impl>::block()
282{
283    DPRINTF(IEW, "IEW: Blocking.\n");
284    // Set the status to Blocked.
285    _status = Blocked;
286
287    // Add the current inputs to the skid buffer so they can be
288    // reprocessed when this stage unblocks.
289    skidBuffer.push(*fromRename);
290
291    // Note that this stage only signals previous stages to stall when
292    // it is the cause of the stall originates at this stage.  Otherwise
293    // the previous stages are expected to check all possible stall signals.
294}
295
296template<class Impl>
297inline void
298SimpleIEW<Impl>::unblock()
299{
300    // Check if there's information in the skid buffer.  If there is, then
301    // set status to unblocking, otherwise set it directly to running.
302    DPRINTF(IEW, "IEW: Reading instructions out of the skid "
303            "buffer.\n");
304    // Remove the now processed instructions from the skid buffer.
305    skidBuffer.pop();
306
307    // If there's still information in the skid buffer, then
308    // continue to tell previous stages to stall.  They will be
309    // able to restart once the skid buffer is empty.
310    if (!skidBuffer.empty()) {
311        toRename->iewInfo.stall = true;
312    } else {
313        DPRINTF(IEW, "IEW: Stage is done unblocking.\n");
314        _status = Running;
315    }
316}
317
318template<class Impl>
319void
320SimpleIEW<Impl>::wakeDependents(DynInstPtr &inst)
321{
322    instQueue.wakeDependents(inst);
323}
324
325
326template<class Impl>
327void
328SimpleIEW<Impl>::instToCommit(DynInstPtr &inst)
329{
330
331}
332
333template <class Impl>
334void
335SimpleIEW<Impl>::dispatchInsts()
336{
337    ////////////////////////////////////////
338    // DISPATCH/ISSUE stage
339    ////////////////////////////////////////
340
341    //Put into its own function?
342    //Add instructions to IQ if there are any instructions there
343
344    // Check if there are any instructions coming from rename, and we're.
345    // not squashing.
346    if (fromRename->size > 0) {
347        int insts_to_add = fromRename->size;
348
349        // Loop through the instructions, putting them in the instruction
350        // queue.
351        for (int inst_num = 0; inst_num < insts_to_add; ++inst_num)
352        {
353            DynInstPtr inst = fromRename->insts[inst_num];
354
355            // Make sure there's a valid instruction there.
356            assert(inst);
357
358            DPRINTF(IEW, "IEW: Issue: Adding PC %#x to IQ.\n",
359                    inst->readPC());
360
361            // Be sure to mark these instructions as ready so that the
362            // commit stage can go ahead and execute them, and mark
363            // them as issued so the IQ doesn't reprocess them.
364            if (inst->isSquashed()) {
365                ++iewDispSquashedInsts;
366                continue;
367            } else if (instQueue.isFull()) {
368                DPRINTF(IEW, "IEW: Issue: IQ has become full.\n");
369                // Call function to start blocking.
370                block();
371                // Tell previous stage to stall.
372                toRename->iewInfo.stall = true;
373
374                ++iewIQFullEvents;
375                break;
376            } else if (inst->isLoad()) {
377                DPRINTF(IEW, "IEW: Issue: Memory instruction "
378                        "encountered, adding to LDSTQ.\n");
379
380                // Reserve a spot in the load store queue for this
381                // memory access.
382                ldstQueue.insertLoad(inst);
383
384                ++iewDispLoadInsts;
385            } else if (inst->isStore()) {
386                ldstQueue.insertStore(inst);
387
388                ++iewDispStoreInsts;
389            } else if (inst->isNonSpeculative()) {
390                DPRINTF(IEW, "IEW: Issue: Nonspeculative instruction "
391                        "encountered, skipping.\n");
392
393                // Same hack as with stores.
394                inst->setCanCommit();
395
396                // Specificall insert it as nonspeculative.
397                instQueue.insertNonSpec(inst);
398
399                ++iewDispNonSpecInsts;
400
401                continue;
402            } else if (inst->isNop()) {
403                DPRINTF(IEW, "IEW: Issue: Nop instruction encountered "
404                        ", skipping.\n");
405
406                inst->setIssued();
407                inst->setExecuted();
408                inst->setCanCommit();
409
410                instQueue.advanceTail(inst);
411
412                continue;
413            } else if (inst->isExecuted()) {
414                assert(0 && "Instruction shouldn't be executed.\n");
415                DPRINTF(IEW, "IEW: Issue: Executed branch encountered, "
416                        "skipping.\n");
417
418                inst->setIssued();
419                inst->setCanCommit();
420
421                instQueue.advanceTail(inst);
422
423                continue;
424            }
425
426            // If the instruction queue is not full, then add the
427            // instruction.
428            instQueue.insert(fromRename->insts[inst_num]);
429
430            ++iewDispatchedInsts;
431        }
432    }
433}
434
435template <class Impl>
436void
437SimpleIEW<Impl>::executeInsts()
438{
439    ////////////////////////////////////////
440    //EXECUTE/WRITEBACK stage
441    ////////////////////////////////////////
442
443    //Put into its own function?
444    //Similarly should probably have separate execution for int vs FP.
445    // Above comment is handled by the issue queue only issuing a valid
446    // mix of int/fp instructions.
447    //Actually okay to just have one execution, buuuuuut will need
448    //somewhere that defines the execution latency of all instructions.
449    // @todo: Move to the FU pool used in the current full cpu.
450
451    int fu_usage = 0;
452    bool fetch_redirect = false;
453    int inst_slot = 0;
454    int time_slot = 0;
455
456    // Execute/writeback any instructions that are available.
457    for (int inst_num = 0;
458         fu_usage < executeWidth && /* Haven't exceeded available FU's. */
459             inst_num < issueWidth &&
460             fromIssue->insts[inst_num];
461         ++inst_num) {
462
463        DPRINTF(IEW, "IEW: Execute: Executing instructions from IQ.\n");
464
465        // Get instruction from issue's queue.
466        DynInstPtr inst = fromIssue->insts[inst_num];
467
468        DPRINTF(IEW, "IEW: Execute: Processing PC %#x.\n", inst->readPC());
469
470        // Check if the instruction is squashed; if so then skip it
471        // and don't count it towards the FU usage.
472        if (inst->isSquashed()) {
473            DPRINTF(IEW, "IEW: Execute: Instruction was squashed.\n");
474
475            // Consider this instruction executed so that commit can go
476            // ahead and retire the instruction.
477            inst->setExecuted();
478
479            toCommit->insts[inst_num] = inst;
480
481            ++iewExecSquashedInsts;
482
483            continue;
484        }
485
486        inst->setExecuted();
487
488        // If an instruction is executed, then count it towards FU usage.
489        ++fu_usage;
490
491        // Execute instruction.
492        // Note that if the instruction faults, it will be handled
493        // at the commit stage.
494        if (inst->isMemRef()) {
495            DPRINTF(IEW, "IEW: Execute: Calculating address for memory "
496                    "reference.\n");
497
498            // Tell the LDSTQ to execute this instruction (if it is a load).
499            if (inst->isLoad()) {
500                ldstQueue.executeLoad(inst);
501
502                ++iewExecLoadInsts;
503            } else if (inst->isStore()) {
504                ldstQueue.executeStore(inst);
505
506                ++iewExecStoreInsts;
507            } else {
508                panic("IEW: Unexpected memory type!\n");
509            }
510
511        } else {
512            inst->execute();
513
514            ++iewExecutedInsts;
515        }
516
517        // First check the time slot that this instruction will write
518        // to.  If there are free write ports at the time, then go ahead
519        // and write the instruction to that time.  If there are not,
520        // keep looking back to see where's the first time there's a
521        // free slot.  What happens if you run out of free spaces?
522        // For now naively assume that all instructions take one cycle.
523        // Otherwise would have to look into the time buffer based on the
524        // latency of the instruction.
525        (*iewQueue)[time_slot].insts[inst_slot];
526        while ((*iewQueue)[time_slot].insts[inst_slot]) {
527            if (inst_slot < issueWidth) {
528                ++inst_slot;
529            } else {
530                ++time_slot;
531                inst_slot = 0;
532            }
533
534            assert(time_slot < 5);
535        }
536
537        // May actually have to work this out, especially with loads and stores
538
539        // Add finished instruction to queue to commit.
540        (*iewQueue)[time_slot].insts[inst_slot] = inst;
541        (*iewQueue)[time_slot].size++;
542
543        // Check if branch was correct.  This check happens after the
544        // instruction is added to the queue because even if the branch
545        // is mispredicted, the branch instruction itself is still valid.
546        // Only handle this if there hasn't already been something that
547        // redirects fetch in this group of instructions.
548        if (!fetch_redirect) {
549            if (inst->mispredicted()) {
550                fetch_redirect = true;
551
552                DPRINTF(IEW, "IEW: Execute: Branch mispredict detected.\n");
553                DPRINTF(IEW, "IEW: Execute: Redirecting fetch to PC: %#x.\n",
554                        inst->nextPC);
555
556                // If incorrect, then signal the ROB that it must be squashed.
557                squashDueToBranch(inst);
558
559                if (inst->predTaken()) {
560                    predictedTakenIncorrect++;
561                }
562            } else if (ldstQueue.violation()) {
563                fetch_redirect = true;
564
565                // Get the DynInst that caused the violation.
566                DynInstPtr violator = ldstQueue.getMemDepViolator();
567
568                DPRINTF(IEW, "IEW: LDSTQ detected a violation.  Violator PC: "
569                        "%#x, inst PC: %#x.  Addr is: %#x.\n",
570                        violator->readPC(), inst->readPC(), inst->physEffAddr);
571
572                // Tell the instruction queue that a violation has occured.
573                instQueue.violation(inst, violator);
574
575                // Squash.
576                squashDueToMem(inst);
577
578                ++memOrderViolationEvents;
579            }
580        }
581    }
582}
583
584template<class Impl>
585void
586SimpleIEW<Impl>::tick()
587{
588    // Considering putting all the state-determining stuff in this section.
589
590    // Try to fill up issue queue with as many instructions as bandwidth
591    // allows.
592    // Decode should try to execute as many instructions as its bandwidth
593    // will allow, as long as it is not currently blocked.
594
595    // Check if the stage is in a running status.
596    if (_status != Blocked && _status != Squashing) {
597        DPRINTF(IEW, "IEW: Status is not blocked, attempting to run "
598                     "stage.\n");
599        iew();
600
601        // If it's currently unblocking, check to see if it should switch
602        // to running.
603        if (_status == Unblocking) {
604            unblock();
605
606            ++iewUnblockCycles;
607        }
608    } else if (_status == Squashing) {
609
610        DPRINTF(IEW, "IEW: Still squashing.\n");
611
612        // Check if stage should remain squashing.  Stop squashing if the
613        // squash signal clears.
614        if (!fromCommit->commitInfo.squash &&
615            !fromCommit->commitInfo.robSquashing) {
616            DPRINTF(IEW, "IEW: Done squashing, changing status to "
617                    "running.\n");
618
619            _status = Running;
620            instQueue.stopSquash();
621        } else {
622            instQueue.doSquash();
623        }
624
625        ++iewSquashCycles;
626    } else if (_status == Blocked) {
627        // Continue to tell previous stage to stall.
628        toRename->iewInfo.stall = true;
629
630        // Check if possible stall conditions have cleared.
631        if (!fromCommit->commitInfo.stall &&
632            !instQueue.isFull()) {
633            DPRINTF(IEW, "IEW: Stall signals cleared, going to unblock.\n");
634            _status = Unblocking;
635        }
636
637        // If there's still instructions coming from rename, continue to
638        // put them on the skid buffer.
639        if (fromRename->size == 0) {
640            block();
641        }
642
643        if (fromCommit->commitInfo.squash ||
644            fromCommit->commitInfo.robSquashing) {
645            squash();
646        }
647
648        ++iewBlockCycles;
649    }
650
651    // @todo: Maybe put these at the beginning, so if it's idle it can
652    // return early.
653    // Write back number of free IQ entries here.
654    toRename->iewInfo.freeIQEntries = instQueue.numFreeEntries();
655
656    ldstQueue.writebackStores();
657
658    // Check the committed load/store signals to see if there's a load
659    // or store to commit.  Also check if it's being told to execute a
660    // nonspeculative instruction.
661    // This is pretty inefficient...
662    if (!fromCommit->commitInfo.squash &&
663        !fromCommit->commitInfo.robSquashing) {
664        ldstQueue.commitStores(fromCommit->commitInfo.doneSeqNum);
665        ldstQueue.commitLoads(fromCommit->commitInfo.doneSeqNum);
666    }
667
668    if (fromCommit->commitInfo.nonSpecSeqNum != 0) {
669        instQueue.scheduleNonSpec(fromCommit->commitInfo.nonSpecSeqNum);
670    }
671
672    DPRINTF(IEW, "IEW: IQ has %i free entries.\n",
673            instQueue.numFreeEntries());
674}
675
676template<class Impl>
677void
678SimpleIEW<Impl>::iew()
679{
680    // Might want to put all state checks in the tick() function.
681    // Check if being told to stall from commit.
682    if (fromCommit->commitInfo.stall) {
683        block();
684        return;
685    } else if (fromCommit->commitInfo.squash ||
686               fromCommit->commitInfo.robSquashing) {
687        // Also check if commit is telling this stage to squash.
688        squash();
689        return;
690    }
691
692    dispatchInsts();
693
694    // Have the instruction queue try to schedule any ready instructions.
695    instQueue.scheduleReadyInsts();
696
697    executeInsts();
698
699    // Loop through the head of the time buffer and wake any dependents.
700    // These instructions are about to write back.  In the simple model
701    // this loop can really happen within the previous loop, but when
702    // instructions have actual latencies, this loop must be separate.
703    // Also mark scoreboard that this instruction is finally complete.
704    // Either have IEW have direct access to rename map, or have this as
705    // part of backwards communication.
706    for (int inst_num = 0; inst_num < issueWidth &&
707             toCommit->insts[inst_num]; inst_num++)
708    {
709        DynInstPtr inst = toCommit->insts[inst_num];
710
711        DPRINTF(IEW, "IEW: Sending instructions to commit, PC %#x.\n",
712                inst->readPC());
713
714        if(!inst->isSquashed()) {
715            instQueue.wakeDependents(inst);
716
717            for (int i = 0; i < inst->numDestRegs(); i++)
718            {
719                renameMap->markAsReady(inst->renamedDestRegIdx(i));
720            }
721        }
722    }
723
724    // Also should advance its own time buffers if the stage ran.
725    // Not the best place for it, but this works (hopefully).
726    issueToExecQueue.advance();
727}
728
729#ifndef FULL_SYSTEM
730template<class Impl>
731void
732SimpleIEW<Impl>::lsqWriteback()
733{
734    ldstQueue.writebackAllInsts();
735}
736#endif
737