iew_impl.hh revision 2316
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
334486Sbinkertn@umich.edu#include <queue>
344486Sbinkertn@umich.edu
354486Sbinkertn@umich.edu#include "base/timebuf.hh"
364486Sbinkertn@umich.edu#include "cpu/o3/fu_pool.hh"
374486Sbinkertn@umich.edu#include "cpu/o3/iew.hh"
384486Sbinkertn@umich.edu
394486Sbinkertn@umich.eduusing namespace std;
404486Sbinkertn@umich.edu
417897Shestness@cs.utexas.edutemplate<class Impl>
428839Sandreas.hansson@arm.comDefaultIEW<Impl>::LdWritebackEvent::LdWritebackEvent(DynInstPtr &_inst,
434486Sbinkertn@umich.edu                                                     DefaultIEW<Impl> *_iew)
446654Snate@binkert.org    : Event(&mainEventQueue), inst(_inst), iewStage(_iew)
456654Snate@binkert.org{
466654Snate@binkert.org    this->setFlags(Event::AutoDelete);
473102SN/A}
483102SN/A
496654Snate@binkert.orgtemplate<class Impl>
502998SN/Avoid
514776Sgblack@eecs.umich.eduDefaultIEW<Impl>::LdWritebackEvent::process()
524776Sgblack@eecs.umich.edu{
536654Snate@binkert.org    DPRINTF(IEW, "Load writeback event [sn:%lli]\n", inst->seqNum);
542667SN/A    DPRINTF(Activity, "Activity: Ld Writeback event [sn:%lli]\n", inst->seqNum);
554776Sgblack@eecs.umich.edu
564776Sgblack@eecs.umich.edu    //iewStage->ldstQueue.removeMSHR(inst->threadNumber,inst->seqNum);
576654Snate@binkert.org
586023Snate@binkert.org    if (iewStage->isSwitchedOut()) {
598745Sgblack@eecs.umich.edu        inst = NULL;
606654Snate@binkert.org        return;
616022Sgblack@eecs.umich.edu    } else if (inst->isSquashed()) {
628745Sgblack@eecs.umich.edu        iewStage->wakeCPU();
636654Snate@binkert.org        inst = NULL;
646022Sgblack@eecs.umich.edu        return;
658745Sgblack@eecs.umich.edu    }
666654Snate@binkert.org
676022Sgblack@eecs.umich.edu    iewStage->wakeCPU();
688745Sgblack@eecs.umich.edu
696654Snate@binkert.org    if (!inst->isExecuted()) {
706116Snate@binkert.org        inst->setExecuted();
718745Sgblack@eecs.umich.edu
726691Stjones1@inf.ed.ac.uk        // Execute again to copy data to proper place.
736691Stjones1@inf.ed.ac.uk        if (inst->isStore()) {
748745Sgblack@eecs.umich.edu            inst->completeAcc();
754486Sbinkertn@umich.edu        }
765529Snate@binkert.org    }
771366SN/A
781310SN/A    // Need to insert instruction into queue to commit
791310SN/A    iewStage->instToCommit(inst);
802901SN/A
815712Shsul@eecs.umich.edu    //wroteToTimeBuffer = true;
825529Snate@binkert.org    iewStage->activityThisCycle();
835529Snate@binkert.org
845529Snate@binkert.org    inst = NULL;
855529Snate@binkert.org}
865529Snate@binkert.org
875821Ssaidi@eecs.umich.edutemplate<class Impl>
883170SN/Aconst char *
895780Ssteve.reinhardt@amd.comDefaultIEW<Impl>::LdWritebackEvent::description()
905780Ssteve.reinhardt@amd.com{
915780Ssteve.reinhardt@amd.com    return "Load writeback event";
925780Ssteve.reinhardt@amd.com}
935780Ssteve.reinhardt@amd.com
948784Sgblack@eecs.umich.edutemplate<class Impl>
958784Sgblack@eecs.umich.eduDefaultIEW<Impl>::DefaultIEW(Params *params)
968784Sgblack@eecs.umich.edu    : // Just make this time buffer really big for now
978793Sgblack@eecs.umich.edu    // @todo: Make this into a parameter.
981310SN/A      issueToExecQueue(5, 5),
996654Snate@binkert.org      instQueue(params),
1006022Sgblack@eecs.umich.edu      ldstQueue(params),
1016022Sgblack@eecs.umich.edu      fuPool(params->fuPool),
1028745Sgblack@eecs.umich.edu      commitToIEWDelay(params->commitToIEWDelay),
1035647Sgblack@eecs.umich.edu      renameToIEWDelay(params->renameToIEWDelay),
1046654Snate@binkert.org      issueToExecuteDelay(params->issueToExecuteDelay),
1056023Snate@binkert.org      issueReadWidth(params->issueWidth),
1066023Snate@binkert.org      issueWidth(params->issueWidth),
1078745Sgblack@eecs.umich.edu      executeWidth(params->executeWidth),
1085647Sgblack@eecs.umich.edu      numThreads(params->numberOfThreads),
1096654Snate@binkert.org      switchedOut(false)
1106022Sgblack@eecs.umich.edu{
1116022Sgblack@eecs.umich.edu    DPRINTF(IEW, "executeIntWidth: %i.\n", params->executeIntWidth);
1128745Sgblack@eecs.umich.edu    _status = Active;
1138745Sgblack@eecs.umich.edu    exeStatus = Running;
1146654Snate@binkert.org    wbStatus = Idle;
1156022Sgblack@eecs.umich.edu
1166022Sgblack@eecs.umich.edu    // Setup wire to read instructions coming from issue.
1178745Sgblack@eecs.umich.edu    fromIssue = issueToExecQueue.getWire(-issueToExecuteDelay);
1188745Sgblack@eecs.umich.edu
1196654Snate@binkert.org    // Instruction queue needs the queue between issue and execute.
1206116Snate@binkert.org    instQueue.setIssueToExecuteQueue(&issueToExecQueue);
1216116Snate@binkert.org
1228745Sgblack@eecs.umich.edu    instQueue.setIEW(this);
1238745Sgblack@eecs.umich.edu    ldstQueue.setIEW(this);
1246691Stjones1@inf.ed.ac.uk
1256691Stjones1@inf.ed.ac.uk    for (int i=0; i < numThreads; i++) {
1266691Stjones1@inf.ed.ac.uk        dispatchStatus[i] = Running;
1276691Stjones1@inf.ed.ac.uk        stalls[i].commit = false;
1288745Sgblack@eecs.umich.edu        fetchRedirect[i] = false;
1298745Sgblack@eecs.umich.edu    }
1304997Sgblack@eecs.umich.edu
1314997Sgblack@eecs.umich.edu    updateLSQNextCycle = false;
1326654Snate@binkert.org
1334997Sgblack@eecs.umich.edu    // @todo: Make into a parameter
1344997Sgblack@eecs.umich.edu    skidBufferMax = (3 * (renameToIEWDelay * params->renameWidth)) + issueWidth;
1351310SN/A}
1361310SN/A
1371310SN/Atemplate <class Impl>
1381310SN/Astd::string
1391310SN/ADefaultIEW<Impl>::name() const
1401310SN/A{
1411310SN/A    return cpu->name() + ".iew";
1421310SN/A}
1433878SN/A
1443878SN/Atemplate <class Impl>
1451310SN/Avoid
1461369SN/ADefaultIEW<Impl>::regStats()
1471310SN/A{
1481634SN/A    using namespace Stats;
1494167SN/A
1504167SN/A    instQueue.regStats();
1512998SN/A
1524776Sgblack@eecs.umich.edu    //ldstQueue.regStats();
1534776Sgblack@eecs.umich.edu
1548839Sandreas.hansson@arm.com    iewIdleCycles
1558839Sandreas.hansson@arm.com        .name(name() + ".iewIdleCycles")
1568707Sandreas.hansson@arm.com        .desc("Number of cycles IEW is idle");
1578707Sandreas.hansson@arm.com
1588756Sgblack@eecs.umich.edu    iewSquashCycles
1598707Sandreas.hansson@arm.com        .name(name() + ".iewSquashCycles")
1607876Sgblack@eecs.umich.edu        .desc("Number of cycles IEW is squashing");
1618839Sandreas.hansson@arm.com
1628839Sandreas.hansson@arm.com    iewBlockCycles
1638745Sgblack@eecs.umich.edu        .name(name() + ".iewBlockCycles")
1648839Sandreas.hansson@arm.com        .desc("Number of cycles IEW is blocking");
1658839Sandreas.hansson@arm.com
1662998SN/A    iewUnblockCycles
1677876Sgblack@eecs.umich.edu        .name(name() + ".iewUnblockCycles")
1687876Sgblack@eecs.umich.edu        .desc("Number of cycles IEW is unblocking");
1698839Sandreas.hansson@arm.com
1707404SAli.Saidi@ARM.com//    iewWBInsts;
1717876Sgblack@eecs.umich.edu
1728839Sandreas.hansson@arm.com    iewDispatchedInsts
1738839Sandreas.hansson@arm.com        .name(name() + ".iewDispatchedInsts")
1748839Sandreas.hansson@arm.com        .desc("Number of instructions dispatched to IQ");
1758839Sandreas.hansson@arm.com
1767876Sgblack@eecs.umich.edu    iewDispSquashedInsts
1777876Sgblack@eecs.umich.edu        .name(name() + ".iewDispSquashedInsts")
1787876Sgblack@eecs.umich.edu        .desc("Number of squashed instructions skipped by dispatch");
1797876Sgblack@eecs.umich.edu
1807876Sgblack@eecs.umich.edu    iewDispLoadInsts
1817876Sgblack@eecs.umich.edu        .name(name() + ".iewDispLoadInsts")
1822998SN/A        .desc("Number of dispatched load instructions");
1837868Sgblack@eecs.umich.edu
1842998SN/A    iewDispStoreInsts
1852998SN/A        .name(name() + ".iewDispStoreInsts")
1862998SN/A        .desc("Number of dispatched store instructions");
1872998SN/A
1887876Sgblack@eecs.umich.edu    iewDispNonSpecInsts
1898796Sgblack@eecs.umich.edu        .name(name() + ".iewDispNonSpecInsts")
1908796Sgblack@eecs.umich.edu        .desc("Number of dispatched non-speculative instructions");
1918796Sgblack@eecs.umich.edu
1928796Sgblack@eecs.umich.edu    iewIQFullEvents
1938796Sgblack@eecs.umich.edu        .name(name() + ".iewIQFullEvents")
1948796Sgblack@eecs.umich.edu        .desc("Number of times the IQ has become full, causing a stall");
1958796Sgblack@eecs.umich.edu
1968796Sgblack@eecs.umich.edu    iewLSQFullEvents
1978796Sgblack@eecs.umich.edu        .name(name() + ".iewLSQFullEvents")
1988796Sgblack@eecs.umich.edu        .desc("Number of times the LSQ has become full, causing a stall");
1998809Sgblack@eecs.umich.edu
2008809Sgblack@eecs.umich.edu    iewExecutedInsts
2018809Sgblack@eecs.umich.edu        .name(name() + ".iewExecutedInsts")
2028809Sgblack@eecs.umich.edu        .desc("Number of executed instructions");
2038809Sgblack@eecs.umich.edu
2042998SN/A    iewExecLoadInsts
2057868Sgblack@eecs.umich.edu        .init(cpu->number_of_threads)
2067868Sgblack@eecs.umich.edu        .name(name() + ".iewExecLoadInsts")
2072998SN/A        .desc("Number of load instructions executed")
2087876Sgblack@eecs.umich.edu        .flags(total);
2092998SN/A/*
2108839Sandreas.hansson@arm.com    iewExecStoreInsts
2117876Sgblack@eecs.umich.edu        .name(name() + ".iewExecStoreInsts")
212        .desc("Number of store instructions executed");
213*/
214    iewExecSquashedInsts
215        .name(name() + ".iewExecSquashedInsts")
216        .desc("Number of squashed instructions skipped in execute");
217
218    memOrderViolationEvents
219        .name(name() + ".memOrderViolationEvents")
220        .desc("Number of memory order violations");
221
222    predictedTakenIncorrect
223        .name(name() + ".predictedTakenIncorrect")
224        .desc("Number of branches that were predicted taken incorrectly");
225
226    predictedNotTakenIncorrect
227        .name(name() + ".predictedNotTakenIncorrect")
228        .desc("Number of branches that were predicted not taken incorrectly");
229
230    branchMispredicts
231        .name(name() + ".branchMispredicts")
232        .desc("Number of branch mispredicts detected at execute");
233
234    branchMispredicts = predictedTakenIncorrect + predictedNotTakenIncorrect;
235
236    exe_swp
237        .init(cpu->number_of_threads)
238        .name(name() + ".EXEC:swp")
239        .desc("number of swp insts executed")
240        .flags(total)
241        ;
242
243    exe_nop
244        .init(cpu->number_of_threads)
245        .name(name() + ".EXEC:nop")
246        .desc("number of nop insts executed")
247        .flags(total)
248        ;
249
250    exe_refs
251        .init(cpu->number_of_threads)
252        .name(name() + ".EXEC:refs")
253        .desc("number of memory reference insts executed")
254        .flags(total)
255        ;
256
257    exe_branches
258        .init(cpu->number_of_threads)
259        .name(name() + ".EXEC:branches")
260        .desc("Number of branches executed")
261        .flags(total)
262        ;
263
264    issue_rate
265        .name(name() + ".EXEC:rate")
266        .desc("Inst execution rate")
267        .flags(total)
268        ;
269    issue_rate = iewExecutedInsts / cpu->numCycles;
270
271    iewExecStoreInsts
272        .name(name() + ".EXEC:stores")
273        .desc("Number of stores executed")
274        .flags(total)
275        ;
276    iewExecStoreInsts = exe_refs - iewExecLoadInsts;
277/*
278    for (int i=0; i<Num_OpClasses; ++i) {
279        stringstream subname;
280        subname << opClassStrings[i] << "_delay";
281        issue_delay_dist.subname(i, subname.str());
282    }
283*/
284    //
285    //  Other stats
286    //
287
288    iewInstsToCommit
289        .init(cpu->number_of_threads)
290        .name(name() + ".WB:sent")
291        .desc("cumulative count of insts sent to commit")
292        .flags(total)
293        ;
294
295    writeback_count
296        .init(cpu->number_of_threads)
297        .name(name() + ".WB:count")
298        .desc("cumulative count of insts written-back")
299        .flags(total)
300        ;
301
302    producer_inst
303        .init(cpu->number_of_threads)
304        .name(name() + ".WB:producers")
305        .desc("num instructions producing a value")
306        .flags(total)
307        ;
308
309    consumer_inst
310        .init(cpu->number_of_threads)
311        .name(name() + ".WB:consumers")
312        .desc("num instructions consuming a value")
313        .flags(total)
314        ;
315
316    wb_penalized
317        .init(cpu->number_of_threads)
318        .name(name() + ".WB:penalized")
319        .desc("number of instrctions required to write to 'other' IQ")
320        .flags(total)
321        ;
322
323    wb_penalized_rate
324        .name(name() + ".WB:penalized_rate")
325        .desc ("fraction of instructions written-back that wrote to 'other' IQ")
326        .flags(total)
327        ;
328
329    wb_penalized_rate = wb_penalized / writeback_count;
330
331    wb_fanout
332        .name(name() + ".WB:fanout")
333        .desc("average fanout of values written-back")
334        .flags(total)
335        ;
336
337    wb_fanout = producer_inst / consumer_inst;
338
339    wb_rate
340        .name(name() + ".WB:rate")
341        .desc("insts written-back per cycle")
342        .flags(total)
343        ;
344    wb_rate = writeback_count / cpu->numCycles;
345}
346
347template<class Impl>
348void
349DefaultIEW<Impl>::initStage()
350{
351    for (int tid=0; tid < numThreads; tid++) {
352        toRename->iewInfo[tid].usedIQ = true;
353        toRename->iewInfo[tid].freeIQEntries =
354            instQueue.numFreeEntries(tid);
355
356        toRename->iewInfo[tid].usedLSQ = true;
357        toRename->iewInfo[tid].freeLSQEntries =
358            ldstQueue.numFreeEntries(tid);
359    }
360}
361
362template<class Impl>
363void
364DefaultIEW<Impl>::setCPU(FullCPU *cpu_ptr)
365{
366    DPRINTF(IEW, "Setting CPU pointer.\n");
367    cpu = cpu_ptr;
368
369    instQueue.setCPU(cpu_ptr);
370    ldstQueue.setCPU(cpu_ptr);
371
372    cpu->activateStage(FullCPU::IEWIdx);
373}
374
375template<class Impl>
376void
377DefaultIEW<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
378{
379    DPRINTF(IEW, "Setting time buffer pointer.\n");
380    timeBuffer = tb_ptr;
381
382    // Setup wire to read information from time buffer, from commit.
383    fromCommit = timeBuffer->getWire(-commitToIEWDelay);
384
385    // Setup wire to write information back to previous stages.
386    toRename = timeBuffer->getWire(0);
387
388    toFetch = timeBuffer->getWire(0);
389
390    // Instruction queue also needs main time buffer.
391    instQueue.setTimeBuffer(tb_ptr);
392}
393
394template<class Impl>
395void
396DefaultIEW<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
397{
398    DPRINTF(IEW, "Setting rename queue pointer.\n");
399    renameQueue = rq_ptr;
400
401    // Setup wire to read information from rename queue.
402    fromRename = renameQueue->getWire(-renameToIEWDelay);
403}
404
405template<class Impl>
406void
407DefaultIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
408{
409    DPRINTF(IEW, "Setting IEW queue pointer.\n");
410    iewQueue = iq_ptr;
411
412    // Setup wire to write instructions to commit.
413    toCommit = iewQueue->getWire(0);
414}
415
416template<class Impl>
417void
418DefaultIEW<Impl>::setActiveThreads(list<unsigned> *at_ptr)
419{
420    DPRINTF(IEW, "Setting active threads list pointer.\n");
421    activeThreads = at_ptr;
422
423    ldstQueue.setActiveThreads(at_ptr);
424    instQueue.setActiveThreads(at_ptr);
425}
426
427template<class Impl>
428void
429DefaultIEW<Impl>::setScoreboard(Scoreboard *sb_ptr)
430{
431    DPRINTF(IEW, "Setting scoreboard pointer.\n");
432    scoreboard = sb_ptr;
433}
434
435#if 0
436template<class Impl>
437void
438DefaultIEW<Impl>::setPageTable(PageTable *pt_ptr)
439{
440    ldstQueue.setPageTable(pt_ptr);
441}
442#endif
443
444template <class Impl>
445void
446DefaultIEW<Impl>::switchOut()
447{
448    cpu->signalSwitched();
449}
450
451template <class Impl>
452void
453DefaultIEW<Impl>::doSwitchOut()
454{
455    switchedOut = true;
456
457    instQueue.switchOut();
458    ldstQueue.switchOut();
459    fuPool->switchOut();
460
461    for (int i = 0; i < numThreads; i++) {
462        while (!insts[i].empty())
463            insts[i].pop();
464        while (!skidBuffer[i].empty())
465            skidBuffer[i].pop();
466    }
467}
468
469template <class Impl>
470void
471DefaultIEW<Impl>::takeOverFrom()
472{
473    _status = Active;
474    exeStatus = Running;
475    wbStatus = Idle;
476    switchedOut = false;
477
478    instQueue.takeOverFrom();
479    ldstQueue.takeOverFrom();
480    fuPool->takeOverFrom();
481
482    initStage();
483    cpu->activityThisCycle();
484
485    for (int i=0; i < numThreads; i++) {
486        dispatchStatus[i] = Running;
487        stalls[i].commit = false;
488        fetchRedirect[i] = false;
489    }
490
491    updateLSQNextCycle = false;
492
493    // @todo: Fix hardcoded number
494    for (int i = 0; i < 6; ++i) {
495        issueToExecQueue.advance();
496    }
497}
498
499template<class Impl>
500void
501DefaultIEW<Impl>::squash(unsigned tid)
502{
503    DPRINTF(IEW, "[tid:%i]: Squashing all instructions.\n",
504            tid);
505
506    // Tell the IQ to start squashing.
507    instQueue.squash(tid);
508
509    // Tell the LDSTQ to start squashing.
510    ldstQueue.squash(fromCommit->commitInfo[tid].doneSeqNum,tid);
511
512    updatedQueues = true;
513
514    // Clear the skid buffer in case it has any data in it.
515    while (!skidBuffer[tid].empty()) {
516
517        if (skidBuffer[tid].front()->isLoad() ||
518            skidBuffer[tid].front()->isStore() ) {
519            toRename->iewInfo[tid].dispatchedToLSQ++;
520        }
521
522        toRename->iewInfo[tid].dispatched++;
523
524        skidBuffer[tid].pop();
525    }
526
527    while (!insts[tid].empty()) {
528        if (insts[tid].front()->isLoad() ||
529            insts[tid].front()->isStore() ) {
530            toRename->iewInfo[tid].dispatchedToLSQ++;
531        }
532
533        toRename->iewInfo[tid].dispatched++;
534
535        insts[tid].pop();
536    }
537}
538
539template<class Impl>
540void
541DefaultIEW<Impl>::squashDueToBranch(DynInstPtr &inst, unsigned tid)
542{
543    DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, PC: %#x "
544            "[sn:%i].\n", tid, inst->readPC(), inst->seqNum);
545
546    // Tell rename to squash through the time buffer.
547    toCommit->squash[tid] = true;
548    toCommit->squashedSeqNum[tid] = inst->seqNum;
549    toCommit->mispredPC[tid] = inst->readPC();
550    toCommit->nextPC[tid] = inst->readNextPC();
551    toCommit->branchMispredict[tid] = true;
552    // Prediction was incorrect, so send back inverse.
553    toCommit->branchTaken[tid] = inst->readNextPC() !=
554        (inst->readPC() + sizeof(TheISA::MachInst));
555
556    toCommit->includeSquashInst[tid] = false;
557    //toCommit->iewSquashNum[tid] = inst->seqNum;
558
559    wroteToTimeBuffer = true;
560}
561
562template<class Impl>
563void
564DefaultIEW<Impl>::squashDueToMemOrder(DynInstPtr &inst, unsigned tid)
565{
566    DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, "
567            "PC: %#x [sn:%i].\n", tid, inst->readPC(), inst->seqNum);
568
569    // Tell rename to squash through the time buffer.
570    toCommit->squash[tid] = true;
571    toCommit->squashedSeqNum[tid] = inst->seqNum;
572    toCommit->nextPC[tid] = inst->readNextPC();
573
574    toCommit->includeSquashInst[tid] = false;
575    //toCommit->iewSquashNum[tid] = inst->seqNum;
576
577    wroteToTimeBuffer = true;
578}
579
580template<class Impl>
581void
582DefaultIEW<Impl>::squashDueToMemBlocked(DynInstPtr &inst, unsigned tid)
583{
584    DPRINTF(IEW, "[tid:%i]: Memory blocked, squashing load and younger insts, "
585            "PC: %#x [sn:%i].\n", tid, inst->readPC(), inst->seqNum);
586
587    toCommit->squash[tid] = true;
588    toCommit->squashedSeqNum[tid] = inst->seqNum;
589    toCommit->nextPC[tid] = inst->readPC();
590
591    toCommit->includeSquashInst[tid] = true;
592
593    ldstQueue.setLoadBlockedHandled(tid);
594
595    wroteToTimeBuffer = true;
596}
597
598template<class Impl>
599void
600DefaultIEW<Impl>::block(unsigned tid)
601{
602    DPRINTF(IEW, "[tid:%u]: Blocking.\n", tid);
603
604    if (dispatchStatus[tid] != Blocked &&
605        dispatchStatus[tid] != Unblocking) {
606        toRename->iewBlock[tid] = true;
607        wroteToTimeBuffer = true;
608    }
609
610    // Add the current inputs to the skid buffer so they can be
611    // reprocessed when this stage unblocks.
612    skidInsert(tid);
613
614    // Set the status to Blocked.
615    dispatchStatus[tid] = Blocked;
616}
617
618template<class Impl>
619void
620DefaultIEW<Impl>::unblock(unsigned tid)
621{
622    DPRINTF(IEW, "[tid:%i]: Reading instructions out of the skid "
623            "buffer %u.\n",tid, tid);
624
625    // If the skid bufffer is empty, signal back to previous stages to unblock.
626    // Also switch status to running.
627    if (skidBuffer[tid].empty()) {
628        toRename->iewUnblock[tid] = true;
629        wroteToTimeBuffer = true;
630        DPRINTF(IEW, "[tid:%i]: Done unblocking.\n",tid);
631        dispatchStatus[tid] = Running;
632    }
633}
634
635template<class Impl>
636void
637DefaultIEW<Impl>::wakeDependents(DynInstPtr &inst)
638{
639    instQueue.wakeDependents(inst);
640}
641
642template<class Impl>
643void
644DefaultIEW<Impl>::rescheduleMemInst(DynInstPtr &inst)
645{
646    instQueue.rescheduleMemInst(inst);
647}
648
649template<class Impl>
650void
651DefaultIEW<Impl>::replayMemInst(DynInstPtr &inst)
652{
653    instQueue.replayMemInst(inst);
654}
655
656template<class Impl>
657void
658DefaultIEW<Impl>::instToCommit(DynInstPtr &inst)
659{
660    // First check the time slot that this instruction will write
661    // to.  If there are free write ports at the time, then go ahead
662    // and write the instruction to that time.  If there are not,
663    // keep looking back to see where's the first time there's a
664    // free slot.  What happens if you run out of free spaces?
665    // For now naively assume that all instructions take one cycle.
666    // Otherwise would have to look into the time buffer based on the
667    // latency of the instruction.
668    while ((*iewQueue)[wbCycle].insts[wbNumInst]) {
669        ++wbNumInst;
670        if (wbNumInst == issueWidth) {
671            ++wbCycle;
672            wbNumInst = 0;
673        }
674
675        assert(wbCycle < 5);
676    }
677
678    // Add finished instruction to queue to commit.
679    (*iewQueue)[wbCycle].insts[wbNumInst] = inst;
680    (*iewQueue)[wbCycle].size++;
681}
682
683template <class Impl>
684unsigned
685DefaultIEW<Impl>::validInstsFromRename()
686{
687    unsigned inst_count = 0;
688
689    for (int i=0; i<fromRename->size; i++) {
690        if (!fromRename->insts[i]->squashed)
691            inst_count++;
692    }
693
694    return inst_count;
695}
696
697template<class Impl>
698void
699DefaultIEW<Impl>::skidInsert(unsigned tid)
700{
701    DynInstPtr inst = NULL;
702
703    while (!insts[tid].empty()) {
704        inst = insts[tid].front();
705
706        insts[tid].pop();
707
708        DPRINTF(Decode,"[tid:%i]: Inserting [sn:%lli] PC:%#x into "
709                "dispatch skidBuffer %i\n",tid, inst->seqNum,
710                inst->readPC(),tid);
711
712        skidBuffer[tid].push(inst);
713    }
714
715    assert(skidBuffer[tid].size() <= skidBufferMax &&
716           "Skidbuffer Exceeded Max Size");
717}
718
719template<class Impl>
720int
721DefaultIEW<Impl>::skidCount()
722{
723    int max=0;
724
725    list<unsigned>::iterator threads = (*activeThreads).begin();
726
727    while (threads != (*activeThreads).end()) {
728        unsigned thread_count = skidBuffer[*threads++].size();
729        if (max < thread_count)
730            max = thread_count;
731    }
732
733    return max;
734}
735
736template<class Impl>
737bool
738DefaultIEW<Impl>::skidsEmpty()
739{
740    list<unsigned>::iterator threads = (*activeThreads).begin();
741
742    while (threads != (*activeThreads).end()) {
743        if (!skidBuffer[*threads++].empty())
744            return false;
745    }
746
747    return true;
748}
749
750template <class Impl>
751void
752DefaultIEW<Impl>::updateStatus()
753{
754    bool any_unblocking = false;
755
756    list<unsigned>::iterator threads = (*activeThreads).begin();
757
758    threads = (*activeThreads).begin();
759
760    while (threads != (*activeThreads).end()) {
761        unsigned tid = *threads++;
762
763        if (dispatchStatus[tid] == Unblocking) {
764            any_unblocking = true;
765            break;
766        }
767    }
768
769    // If there are no ready instructions waiting to be scheduled by the IQ,
770    // and there's no stores waiting to write back, and dispatch is not
771    // unblocking, then there is no internal activity for the IEW stage.
772    if (_status == Active && !instQueue.hasReadyInsts() &&
773        !ldstQueue.willWB() && !any_unblocking) {
774        DPRINTF(IEW, "IEW switching to idle\n");
775
776        deactivateStage();
777
778        _status = Inactive;
779    } else if (_status == Inactive && (instQueue.hasReadyInsts() ||
780                                       ldstQueue.willWB() ||
781                                       any_unblocking)) {
782        // Otherwise there is internal activity.  Set to active.
783        DPRINTF(IEW, "IEW switching to active\n");
784
785        activateStage();
786
787        _status = Active;
788    }
789}
790
791template <class Impl>
792void
793DefaultIEW<Impl>::resetEntries()
794{
795    instQueue.resetEntries();
796    ldstQueue.resetEntries();
797}
798
799template <class Impl>
800void
801DefaultIEW<Impl>::readStallSignals(unsigned tid)
802{
803    if (fromCommit->commitBlock[tid]) {
804        stalls[tid].commit = true;
805    }
806
807    if (fromCommit->commitUnblock[tid]) {
808        assert(stalls[tid].commit);
809        stalls[tid].commit = false;
810    }
811}
812
813template <class Impl>
814bool
815DefaultIEW<Impl>::checkStall(unsigned tid)
816{
817    bool ret_val(false);
818
819    if (stalls[tid].commit) {
820        DPRINTF(IEW,"[tid:%i]: Stall from Commit stage detected.\n",tid);
821        ret_val = true;
822    } else if (instQueue.isFull(tid)) {
823        DPRINTF(IEW,"[tid:%i]: Stall: IQ  is full.\n",tid);
824        ret_val = true;
825    } else if (ldstQueue.isFull(tid)) {
826        DPRINTF(IEW,"[tid:%i]: Stall: LSQ is full\n",tid);
827
828        if (ldstQueue.numLoads(tid) > 0 ) {
829
830            DPRINTF(IEW,"[tid:%i]: LSQ oldest load: [sn:%i] \n",
831                    tid,ldstQueue.getLoadHeadSeqNum(tid));
832        }
833
834        if (ldstQueue.numStores(tid) > 0) {
835
836            DPRINTF(IEW,"[tid:%i]: LSQ oldest store: [sn:%i] \n",
837                    tid,ldstQueue.getStoreHeadSeqNum(tid));
838        }
839
840        ret_val = true;
841    } else if (ldstQueue.isStalled(tid)) {
842        DPRINTF(IEW,"[tid:%i]: Stall: LSQ stall detected.\n",tid);
843        ret_val = true;
844    }
845
846    return ret_val;
847}
848
849template <class Impl>
850void
851DefaultIEW<Impl>::checkSignalsAndUpdate(unsigned tid)
852{
853    // Check if there's a squash signal, squash if there is
854    // Check stall signals, block if there is.
855    // If status was Blocked
856    //     if so then go to unblocking
857    // If status was Squashing
858    //     check if squashing is not high.  Switch to running this cycle.
859
860    readStallSignals(tid);
861
862    if (fromCommit->commitInfo[tid].squash) {
863        squash(tid);
864
865        if (dispatchStatus[tid] == Blocked ||
866            dispatchStatus[tid] == Unblocking) {
867            toRename->iewUnblock[tid] = true;
868            wroteToTimeBuffer = true;
869        }
870
871        dispatchStatus[tid] = Squashing;
872
873        fetchRedirect[tid] = false;
874        return;
875    }
876
877    if (fromCommit->commitInfo[tid].robSquashing) {
878        DPRINTF(IEW, "[tid:%i]: ROB is still squashing.\n");
879
880        dispatchStatus[tid] = Squashing;
881
882        return;
883    }
884
885    if (checkStall(tid)) {
886        block(tid);
887        dispatchStatus[tid] = Blocked;
888        return;
889    }
890
891    if (dispatchStatus[tid] == Blocked) {
892        // Status from previous cycle was blocked, but there are no more stall
893        // conditions.  Switch over to unblocking.
894        DPRINTF(IEW, "[tid:%i]: Done blocking, switching to unblocking.\n",
895                tid);
896
897        dispatchStatus[tid] = Unblocking;
898
899        unblock(tid);
900
901        return;
902    }
903
904    if (dispatchStatus[tid] == Squashing) {
905        // Switch status to running if rename isn't being told to block or
906        // squash this cycle.
907        DPRINTF(IEW, "[tid:%i]: Done squashing, switching to running.\n",
908                tid);
909
910        dispatchStatus[tid] = Running;
911
912        return;
913    }
914}
915
916template <class Impl>
917void
918DefaultIEW<Impl>::sortInsts()
919{
920    int insts_from_rename = fromRename->size;
921
922    for (int i = 0; i < numThreads; i++)
923        assert(insts[i].empty());
924
925    for (int i = 0; i < insts_from_rename; ++i) {
926        insts[fromRename->insts[i]->threadNumber].push(fromRename->insts[i]);
927    }
928}
929
930template <class Impl>
931void
932DefaultIEW<Impl>::wakeCPU()
933{
934    cpu->wakeCPU();
935}
936
937template <class Impl>
938void
939DefaultIEW<Impl>::activityThisCycle()
940{
941    DPRINTF(Activity, "Activity this cycle.\n");
942    cpu->activityThisCycle();
943}
944
945template <class Impl>
946inline void
947DefaultIEW<Impl>::activateStage()
948{
949    DPRINTF(Activity, "Activating stage.\n");
950    cpu->activateStage(FullCPU::IEWIdx);
951}
952
953template <class Impl>
954inline void
955DefaultIEW<Impl>::deactivateStage()
956{
957    DPRINTF(Activity, "Deactivating stage.\n");
958    cpu->deactivateStage(FullCPU::IEWIdx);
959}
960
961template<class Impl>
962void
963DefaultIEW<Impl>::dispatch(unsigned tid)
964{
965    // If status is Running or idle,
966    //     call dispatchInsts()
967    // If status is Unblocking,
968    //     buffer any instructions coming from rename
969    //     continue trying to empty skid buffer
970    //     check if stall conditions have passed
971
972    if (dispatchStatus[tid] == Blocked) {
973        ++iewBlockCycles;
974
975    } else if (dispatchStatus[tid] == Squashing) {
976        ++iewSquashCycles;
977    }
978
979    // Dispatch should try to dispatch as many instructions as its bandwidth
980    // will allow, as long as it is not currently blocked.
981    if (dispatchStatus[tid] == Running ||
982        dispatchStatus[tid] == Idle) {
983        DPRINTF(IEW, "[tid:%i] Not blocked, so attempting to run "
984                "dispatch.\n", tid);
985
986        dispatchInsts(tid);
987    } else if (dispatchStatus[tid] == Unblocking) {
988        // Make sure that the skid buffer has something in it if the
989        // status is unblocking.
990        assert(!skidsEmpty());
991
992        // If the status was unblocking, then instructions from the skid
993        // buffer were used.  Remove those instructions and handle
994        // the rest of unblocking.
995        dispatchInsts(tid);
996
997        ++iewUnblockCycles;
998
999        if (validInstsFromRename() && dispatchedAllInsts) {
1000            // Add the current inputs to the skid buffer so they can be
1001            // reprocessed when this stage unblocks.
1002            skidInsert(tid);
1003        }
1004
1005        unblock(tid);
1006    }
1007}
1008
1009template <class Impl>
1010void
1011DefaultIEW<Impl>::dispatchInsts(unsigned tid)
1012{
1013    dispatchedAllInsts = true;
1014
1015    // Obtain instructions from skid buffer if unblocking, or queue from rename
1016    // otherwise.
1017    std::queue<DynInstPtr> &insts_to_dispatch =
1018        dispatchStatus[tid] == Unblocking ?
1019        skidBuffer[tid] : insts[tid];
1020
1021    int insts_to_add = insts_to_dispatch.size();
1022
1023    DynInstPtr inst;
1024    bool add_to_iq = false;
1025    int dis_num_inst = 0;
1026
1027    // Loop through the instructions, putting them in the instruction
1028    // queue.
1029    for ( ; dis_num_inst < insts_to_add &&
1030              dis_num_inst < issueReadWidth;
1031          ++dis_num_inst)
1032    {
1033        inst = insts_to_dispatch.front();
1034
1035        if (dispatchStatus[tid] == Unblocking) {
1036            DPRINTF(IEW, "[tid:%i]: Issue: Examining instruction from skid "
1037                    "buffer\n", tid);
1038        }
1039
1040        // Make sure there's a valid instruction there.
1041        assert(inst);
1042
1043        DPRINTF(IEW, "[tid:%i]: Issue: Adding PC %#x [sn:%lli] [tid:%i] to "
1044                "IQ.\n",
1045                tid, inst->readPC(), inst->seqNum, inst->threadNumber);
1046
1047        // Be sure to mark these instructions as ready so that the
1048        // commit stage can go ahead and execute them, and mark
1049        // them as issued so the IQ doesn't reprocess them.
1050        // -------------
1051        // @TODO: What happens if the ldstqueue is full?
1052        //        Do we process the other instructions?
1053
1054        // Check for squashed instructions.
1055        if (inst->isSquashed()) {
1056            DPRINTF(IEW, "[tid:%i]: Issue: Squashed instruction encountered, "
1057                    "not adding to IQ.\n", tid);
1058
1059            ++iewDispSquashedInsts;
1060
1061            insts_to_dispatch.pop();
1062
1063            //Tell Rename That An Instruction has been processed
1064            if (inst->isLoad() || inst->isStore()) {
1065                toRename->iewInfo[tid].dispatchedToLSQ++;
1066            }
1067            toRename->iewInfo[tid].dispatched++;
1068
1069            continue;
1070        }
1071
1072        // Check for full conditions.
1073        if (instQueue.isFull(tid)) {
1074            DPRINTF(IEW, "[tid:%i]: Issue: IQ has become full.\n", tid);
1075
1076            // Call function to start blocking.
1077            block(tid);
1078
1079            // Set unblock to false. Special case where we are using
1080            // skidbuffer (unblocking) instructions but then we still
1081            // get full in the IQ.
1082            toRename->iewUnblock[tid] = false;
1083
1084            dispatchedAllInsts = false;
1085
1086            ++iewIQFullEvents;
1087            break;
1088        } else if (ldstQueue.isFull(tid)) {
1089            DPRINTF(IEW, "[tid:%i]: Issue: LSQ has become full.\n",tid);
1090
1091            // Call function to start blocking.
1092            block(tid);
1093
1094            // Set unblock to false. Special case where we are using
1095            // skidbuffer (unblocking) instructions but then we still
1096            // get full in the IQ.
1097            toRename->iewUnblock[tid] = false;
1098
1099            dispatchedAllInsts = false;
1100
1101            ++iewLSQFullEvents;
1102            break;
1103        }
1104
1105        // Otherwise issue the instruction just fine.
1106        if (inst->isLoad()) {
1107            DPRINTF(IEW, "[tid:%i]: Issue: Memory instruction "
1108                    "encountered, adding to LSQ.\n", tid);
1109
1110            // Reserve a spot in the load store queue for this
1111            // memory access.
1112            ldstQueue.insertLoad(inst);
1113
1114            ++iewDispLoadInsts;
1115
1116            add_to_iq = true;
1117
1118            toRename->iewInfo[tid].dispatchedToLSQ++;
1119        } else if (inst->isStore()) {
1120            DPRINTF(IEW, "[tid:%i]: Issue: Memory instruction "
1121                    "encountered, adding to LSQ.\n", tid);
1122
1123            ldstQueue.insertStore(inst);
1124
1125            ++iewDispStoreInsts;
1126
1127            if (inst->isNonSpeculative()) {
1128                inst->setCanCommit();
1129                instQueue.insertNonSpec(inst);
1130                add_to_iq = false;
1131
1132                ++iewDispNonSpecInsts;
1133            } else {
1134                add_to_iq = true;
1135            }
1136
1137            toRename->iewInfo[tid].dispatchedToLSQ++;
1138#if FULL_SYSTEM
1139        } else if (inst->isMemBarrier() || inst->isWriteBarrier()) {
1140            inst->setCanCommit();
1141            instQueue.insertBarrier(inst);
1142            add_to_iq = false;
1143#endif
1144        } else if (inst->isNonSpeculative()) {
1145            DPRINTF(IEW, "[tid:%i]: Issue: Nonspeculative instruction "
1146                    "encountered, skipping.\n", tid);
1147
1148            // Same hack as with stores.
1149            inst->setCanCommit();
1150
1151            // Specifically insert it as nonspeculative.
1152            instQueue.insertNonSpec(inst);
1153
1154            ++iewDispNonSpecInsts;
1155
1156            add_to_iq = false;
1157        } else if (inst->isNop()) {
1158            DPRINTF(IEW, "[tid:%i]: Issue: Nop instruction encountered, "
1159                    "skipping.\n", tid);
1160
1161            inst->setIssued();
1162            inst->setExecuted();
1163            inst->setCanCommit();
1164
1165            instQueue.advanceTail(inst);
1166
1167            exe_nop[tid]++;
1168
1169            add_to_iq = false;
1170        } else if (inst->isExecuted()) {
1171            assert(0 && "Instruction shouldn't be executed.\n");
1172            DPRINTF(IEW, "Issue: Executed branch encountered, "
1173                    "skipping.\n");
1174
1175            inst->setIssued();
1176            inst->setCanCommit();
1177
1178            instQueue.advanceTail(inst);
1179
1180            add_to_iq = false;
1181        } else {
1182            add_to_iq = true;
1183        }
1184
1185        // If the instruction queue is not full, then add the
1186        // instruction.
1187        if (add_to_iq) {
1188            instQueue.insert(inst);
1189        }
1190
1191        insts_to_dispatch.pop();
1192
1193        toRename->iewInfo[tid].dispatched++;
1194
1195        ++iewDispatchedInsts;
1196    }
1197
1198    if (!insts_to_dispatch.empty()) {
1199        DPRINTF(IEW,"[tid:%i]: Issue: Bandwidth Full. Blocking.\n");
1200        block(tid);
1201        toRename->iewUnblock[tid] = false;
1202    }
1203
1204    if (dispatchStatus[tid] == Idle && dis_num_inst) {
1205        dispatchStatus[tid] = Running;
1206
1207        updatedQueues = true;
1208    }
1209
1210    dis_num_inst = 0;
1211}
1212
1213template <class Impl>
1214void
1215DefaultIEW<Impl>::printAvailableInsts()
1216{
1217    int inst = 0;
1218
1219    cout << "Available Instructions: ";
1220
1221    while (fromIssue->insts[inst]) {
1222
1223        if (inst%3==0) cout << "\n\t";
1224
1225        cout << "PC: " << fromIssue->insts[inst]->readPC()
1226             << " TN: " << fromIssue->insts[inst]->threadNumber
1227             << " SN: " << fromIssue->insts[inst]->seqNum << " | ";
1228
1229        inst++;
1230
1231    }
1232
1233    cout << "\n";
1234}
1235
1236template <class Impl>
1237void
1238DefaultIEW<Impl>::executeInsts()
1239{
1240    //bool fetch_redirect[(*activeThreads).size()];
1241    wbNumInst = 0;
1242    wbCycle = 0;
1243
1244    list<unsigned>::iterator threads = (*activeThreads).begin();
1245
1246    while (threads != (*activeThreads).end()) {
1247        unsigned tid = *threads++;
1248        fetchRedirect[tid] = false;
1249    }
1250
1251#if 0
1252    printAvailableInsts();
1253#endif
1254
1255    // Execute/writeback any instructions that are available.
1256    int inst_num = 0;
1257    for ( ; inst_num < issueWidth &&  /* Haven't exceeded issue bandwidth */
1258              fromIssue->insts[inst_num];
1259         ++inst_num) {
1260
1261        DPRINTF(IEW, "Execute: Executing instructions from IQ.\n");
1262
1263        // Get instruction from issue's queue.
1264        DynInstPtr inst = fromIssue->insts[inst_num];
1265
1266        DPRINTF(IEW, "Execute: Processing PC %#x, [tid:%i] [sn:%i].\n",
1267                inst->readPC(), inst->threadNumber,inst->seqNum);
1268
1269        // Check if the instruction is squashed; if so then skip it
1270        // and don't count it towards the FU usage.
1271        if (inst->isSquashed()) {
1272            DPRINTF(IEW, "Execute: Instruction was squashed.\n");
1273
1274            // Consider this instruction executed so that commit can go
1275            // ahead and retire the instruction.
1276            inst->setExecuted();
1277
1278            // Not sure if I should set this here or just let commit try to
1279            // commit any squashed instructions.  I like the latter a bit more.
1280            inst->setCanCommit();
1281
1282            ++iewExecSquashedInsts;
1283
1284            continue;
1285        }
1286
1287        Fault fault = NoFault;
1288
1289        // Execute instruction.
1290        // Note that if the instruction faults, it will be handled
1291        // at the commit stage.
1292        if (inst->isMemRef() &&
1293            (!inst->isDataPrefetch() && !inst->isInstPrefetch())) {
1294            DPRINTF(IEW, "Execute: Calculating address for memory "
1295                    "reference.\n");
1296
1297            // Tell the LDSTQ to execute this instruction (if it is a load).
1298            if (inst->isLoad()) {
1299                // Loads will mark themselves as executed, and their writeback
1300                // event adds the instruction to the queue to commit
1301                fault = ldstQueue.executeLoad(inst);
1302
1303//                ++iewExecLoadInsts;
1304            } else if (inst->isStore()) {
1305                ldstQueue.executeStore(inst);
1306
1307//                ++iewExecStoreInsts;
1308
1309                // If the store had a fault then it may not have a mem req
1310                if (inst->req && !(inst->req->flags & LOCKED)) {
1311                    inst->setExecuted();
1312
1313                    instToCommit(inst);
1314                }
1315                // Store conditionals will mark themselves as executed, and
1316                // their writeback event will add the instruction to the queue
1317                // to commit.
1318            } else {
1319                panic("Unexpected memory type!\n");
1320            }
1321
1322        } else {
1323            inst->execute();
1324
1325            inst->setExecuted();
1326
1327            instToCommit(inst);
1328        }
1329
1330        updateExeInstStats(inst);
1331
1332        // Check if branch was correct.  This check happens after the
1333        // instruction is added to the queue because even if the branch
1334        // is mispredicted, the branch instruction itself is still valid.
1335        // Only handle this if there hasn't already been something that
1336        // redirects fetch in this group of instructions.
1337
1338        // This probably needs to prioritize the redirects if a different
1339        // scheduler is used.  Currently the scheduler schedules the oldest
1340        // instruction first, so the branch resolution order will be correct.
1341        unsigned tid = inst->threadNumber;
1342
1343        if (!fetchRedirect[tid]) {
1344
1345            if (inst->mispredicted()) {
1346                fetchRedirect[tid] = true;
1347
1348                DPRINTF(IEW, "Execute: Branch mispredict detected.\n");
1349                DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x.\n",
1350                        inst->nextPC);
1351
1352                // If incorrect, then signal the ROB that it must be squashed.
1353                squashDueToBranch(inst, tid);
1354
1355                if (inst->predTaken()) {
1356                    predictedTakenIncorrect++;
1357                } else {
1358                    predictedNotTakenIncorrect++;
1359                }
1360            } else if (ldstQueue.violation(tid)) {
1361                fetchRedirect[tid] = true;
1362
1363                // Get the DynInst that caused the violation.  Note that this
1364                // clears the violation signal.
1365                DynInstPtr violator;
1366                violator = ldstQueue.getMemDepViolator(tid);
1367
1368                DPRINTF(IEW, "LDSTQ detected a violation.  Violator PC: "
1369                        "%#x, inst PC: %#x.  Addr is: %#x.\n",
1370                        violator->readPC(), inst->readPC(), inst->physEffAddr);
1371
1372                // Tell the instruction queue that a violation has occured.
1373                instQueue.violation(inst, violator);
1374
1375                // Squash.
1376                squashDueToMemOrder(inst,tid);
1377
1378                ++memOrderViolationEvents;
1379            } else if (ldstQueue.loadBlocked(tid) &&
1380                       !ldstQueue.isLoadBlockedHandled(tid)) {
1381                fetchRedirect[tid] = true;
1382
1383                DPRINTF(IEW, "Load operation couldn't execute because the "
1384                        "memory system is blocked.  PC: %#x [sn:%lli]\n",
1385                        inst->readPC(), inst->seqNum);
1386
1387                squashDueToMemBlocked(inst, tid);
1388            }
1389        }
1390    }
1391
1392    if (inst_num) {
1393        if (exeStatus == Idle) {
1394            exeStatus = Running;
1395        }
1396
1397        updatedQueues = true;
1398
1399        cpu->activityThisCycle();
1400    }
1401
1402    // Need to reset this in case a writeback event needs to write into the
1403    // iew queue.  That way the writeback event will write into the correct
1404    // spot in the queue.
1405    wbNumInst = 0;
1406}
1407
1408template <class Impl>
1409void
1410DefaultIEW<Impl>::writebackInsts()
1411{
1412    // Loop through the head of the time buffer and wake any dependents.
1413    // These instructions are about to write back.  In the simple model
1414    // this loop can really happen within the previous loop, but when
1415    // instructions have actual latencies, this loop must be separate.
1416    // Also mark scoreboard that this instruction is finally complete.
1417    // Either have IEW have direct access to rename map, or have this as
1418    // part of backwards communication.
1419    for (int inst_num = 0; inst_num < issueWidth &&
1420             toCommit->insts[inst_num]; inst_num++) {
1421        DynInstPtr inst = toCommit->insts[inst_num];
1422        int tid = inst->threadNumber;
1423
1424        DPRINTF(IEW, "Sending instructions to commit, PC %#x.\n",
1425                inst->readPC());
1426
1427        iewInstsToCommit[tid]++;
1428
1429        // Some instructions will be sent to commit without having
1430        // executed because they need commit to handle them.
1431        // E.g. Uncached loads have not actually executed when they
1432        // are first sent to commit.  Instead commit must tell the LSQ
1433        // when it's ready to execute the uncached load.
1434        if (!inst->isSquashed() && inst->isExecuted()) {
1435            int dependents = instQueue.wakeDependents(inst);
1436
1437            for (int i = 0; i < inst->numDestRegs(); i++) {
1438                //mark as Ready
1439                DPRINTF(IEW,"Setting Destination Register %i\n",
1440                        inst->renamedDestRegIdx(i));
1441                scoreboard->setReg(inst->renamedDestRegIdx(i));
1442            }
1443
1444            producer_inst[tid]++;
1445            consumer_inst[tid]+= dependents;
1446            writeback_count[tid]++;
1447        }
1448    }
1449}
1450
1451template<class Impl>
1452void
1453DefaultIEW<Impl>::tick()
1454{
1455    // Try to fill up issue queue with as many instructions as bandwidth
1456    // allows.
1457    wbNumInst = 0;
1458    wbCycle = 0;
1459
1460    wroteToTimeBuffer = false;
1461    updatedQueues = false;
1462
1463    sortInsts();
1464
1465    list<unsigned>::iterator threads = (*activeThreads).begin();
1466
1467    // Check stall and squash signals.
1468    while (threads != (*activeThreads).end()) {
1469           unsigned tid = *threads++;
1470
1471        DPRINTF(IEW,"Issue: Processing [tid:%i]\n",tid);
1472
1473        checkSignalsAndUpdate(tid);
1474        dispatch(tid);
1475
1476    }
1477
1478    if (exeStatus != Squashing) {
1479        executeInsts();
1480
1481        writebackInsts();
1482
1483        // Have the instruction queue try to schedule any ready instructions.
1484        // (In actuality, this scheduling is for instructions that will
1485        // be executed next cycle.)
1486        instQueue.scheduleReadyInsts();
1487
1488        // Also should advance its own time buffers if the stage ran.
1489        // Not the best place for it, but this works (hopefully).
1490        issueToExecQueue.advance();
1491    }
1492
1493    bool broadcast_free_entries = false;
1494
1495    if (updatedQueues || exeStatus == Running || updateLSQNextCycle) {
1496        exeStatus = Idle;
1497        updateLSQNextCycle = false;
1498
1499        broadcast_free_entries = true;
1500    }
1501
1502    // Writeback any stores using any leftover bandwidth.
1503    ldstQueue.writebackStores();
1504
1505    // Free function units marked as being freed this cycle.
1506    fuPool->processFreeUnits();
1507
1508    // Check the committed load/store signals to see if there's a load
1509    // or store to commit.  Also check if it's being told to execute a
1510    // nonspeculative instruction.
1511    // This is pretty inefficient...
1512
1513    threads = (*activeThreads).begin();
1514    while (threads != (*activeThreads).end()) {
1515        unsigned tid = (*threads++);
1516
1517        DPRINTF(IEW,"Processing [tid:%i]\n",tid);
1518
1519        if (fromCommit->commitInfo[tid].doneSeqNum != 0 &&
1520            !fromCommit->commitInfo[tid].squash &&
1521            !fromCommit->commitInfo[tid].robSquashing) {
1522
1523            ldstQueue.commitStores(fromCommit->commitInfo[tid].doneSeqNum,tid);
1524
1525            ldstQueue.commitLoads(fromCommit->commitInfo[tid].doneSeqNum,tid);
1526
1527            updateLSQNextCycle = true;
1528            instQueue.commit(fromCommit->commitInfo[tid].doneSeqNum,tid);
1529        }
1530
1531        if (fromCommit->commitInfo[tid].nonSpecSeqNum != 0) {
1532
1533            //DPRINTF(IEW,"NonspecInst from thread %i",tid);
1534            if (fromCommit->commitInfo[tid].uncached) {
1535                instQueue.replayMemInst(fromCommit->commitInfo[tid].uncachedLoad);
1536            } else {
1537                instQueue.scheduleNonSpec(
1538                    fromCommit->commitInfo[tid].nonSpecSeqNum);
1539            }
1540        }
1541
1542        if (broadcast_free_entries) {
1543            toFetch->iewInfo[tid].iqCount =
1544                instQueue.getCount(tid);
1545            toFetch->iewInfo[tid].ldstqCount =
1546                ldstQueue.getCount(tid);
1547
1548            toRename->iewInfo[tid].usedIQ = true;
1549            toRename->iewInfo[tid].freeIQEntries =
1550                instQueue.numFreeEntries();
1551            toRename->iewInfo[tid].usedLSQ = true;
1552            toRename->iewInfo[tid].freeLSQEntries =
1553                ldstQueue.numFreeEntries(tid);
1554
1555            wroteToTimeBuffer = true;
1556        }
1557
1558        DPRINTF(IEW, "[tid:%i], Dispatch dispatched %i instructions.\n",
1559                tid, toRename->iewInfo[tid].dispatched);
1560
1561        //thread_queue.pop();
1562    }
1563
1564    DPRINTF(IEW, "IQ has %i free entries (Can schedule: %i).  "
1565            "LSQ has %i free entries.\n",
1566            instQueue.numFreeEntries(), instQueue.hasReadyInsts(),
1567            ldstQueue.numFreeEntries());
1568
1569    updateStatus();
1570
1571    if (wroteToTimeBuffer) {
1572        DPRINTF(Activity, "Activity this cycle.\n");
1573        cpu->activityThisCycle();
1574    }
1575}
1576
1577template <class Impl>
1578void
1579DefaultIEW<Impl>::updateExeInstStats(DynInstPtr &inst)
1580{
1581    int thread_number = inst->threadNumber;
1582
1583    //
1584    //  Pick off the software prefetches
1585    //
1586#ifdef TARGET_ALPHA
1587    if (inst->isDataPrefetch())
1588        exe_swp[thread_number]++;
1589    else
1590        iewExecutedInsts++;
1591#else
1592    iewExecutedInsts[thread_number]++;
1593#endif
1594
1595    //
1596    //  Control operations
1597    //
1598    if (inst->isControl())
1599        exe_branches[thread_number]++;
1600
1601    //
1602    //  Memory operations
1603    //
1604    if (inst->isMemRef()) {
1605        exe_refs[thread_number]++;
1606
1607        if (inst->isLoad()) {
1608            iewExecLoadInsts[thread_number]++;
1609        }
1610    }
1611}
1612