1/*
2 * Copyright (c) 2011-2014, 2017-2019 ARM Limited
3 * Copyright (c) 2013 Advanced Micro Devices, Inc.
4 * All rights reserved.
5 *
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating
9 * to a hardware implementation of the functionality of the software
10 * licensed hereunder.  You may use the software subject to the license
11 * terms below provided that you ensure that this notice is replicated
12 * unmodified and in its entirety in all distributions of the software,
13 * modified or unmodified, in source code or in binary form.
14 *
15 * Copyright (c) 2004-2006 The Regents of The University of Michigan
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Authors: Kevin Lim
42 *          Korey Sewell
43 */
44
45#ifndef __CPU_O3_INST_QUEUE_IMPL_HH__
46#define __CPU_O3_INST_QUEUE_IMPL_HH__
47
48#include <limits>
49#include <vector>
50
51#include "base/logging.hh"
52#include "cpu/o3/fu_pool.hh"
53#include "cpu/o3/inst_queue.hh"
54#include "debug/IQ.hh"
55#include "enums/OpClass.hh"
56#include "params/DerivO3CPU.hh"
57#include "sim/core.hh"
58
59// clang complains about std::set being overloaded with Packet::set if
60// we open up the entire namespace std
61using std::list;
62
63template <class Impl>
64InstructionQueue<Impl>::FUCompletion::FUCompletion(const DynInstPtr &_inst,
65    int fu_idx, InstructionQueue<Impl> *iq_ptr)
66    : Event(Stat_Event_Pri, AutoDelete),
67      inst(_inst), fuIdx(fu_idx), iqPtr(iq_ptr), freeFU(false)
68{
69}
70
71template <class Impl>
72void
73InstructionQueue<Impl>::FUCompletion::process()
74{
75    iqPtr->processFUCompletion(inst, freeFU ? fuIdx : -1);
76    inst = NULL;
77}
78
79
80template <class Impl>
81const char *
82InstructionQueue<Impl>::FUCompletion::description() const
83{
84    return "Functional unit completion";
85}
86
87template <class Impl>
88InstructionQueue<Impl>::InstructionQueue(O3CPU *cpu_ptr, IEW *iew_ptr,
89                                         DerivO3CPUParams *params)
90    : cpu(cpu_ptr),
91      iewStage(iew_ptr),
92      fuPool(params->fuPool),
93      iqPolicy(params->smtIQPolicy),
94      numEntries(params->numIQEntries),
95      totalWidth(params->issueWidth),
96      commitToIEWDelay(params->commitToIEWDelay)
97{
98    assert(fuPool);
99
100    numThreads = params->numThreads;
101
102    // Set the number of total physical registers
103    // As the vector registers have two addressing modes, they are added twice
104    numPhysRegs = params->numPhysIntRegs + params->numPhysFloatRegs +
105                    params->numPhysVecRegs +
106                    params->numPhysVecRegs * TheISA::NumVecElemPerVecReg +
107                    params->numPhysVecPredRegs +
108                    params->numPhysCCRegs;
109
110    //Create an entry for each physical register within the
111    //dependency graph.
112    dependGraph.resize(numPhysRegs);
113
114    // Resize the register scoreboard.
115    regScoreboard.resize(numPhysRegs);
116
117    //Initialize Mem Dependence Units
118    for (ThreadID tid = 0; tid < Impl::MaxThreads; tid++) {
119        memDepUnit[tid].init(params, tid);
120        memDepUnit[tid].setIQ(this);
121    }
122
123    resetState();
124
125    //Figure out resource sharing policy
126    if (iqPolicy == SMTQueuePolicy::Dynamic) {
127        //Set Max Entries to Total ROB Capacity
128        for (ThreadID tid = 0; tid < numThreads; tid++) {
129            maxEntries[tid] = numEntries;
130        }
131
132    } else if (iqPolicy == SMTQueuePolicy::Partitioned) {
133        //@todo:make work if part_amt doesnt divide evenly.
134        int part_amt = numEntries / numThreads;
135
136        //Divide ROB up evenly
137        for (ThreadID tid = 0; tid < numThreads; tid++) {
138            maxEntries[tid] = part_amt;
139        }
140
141        DPRINTF(IQ, "IQ sharing policy set to Partitioned:"
142                "%i entries per thread.\n",part_amt);
143    } else if (iqPolicy == SMTQueuePolicy::Threshold) {
144        double threshold =  (double)params->smtIQThreshold / 100;
145
146        int thresholdIQ = (int)((double)threshold * numEntries);
147
148        //Divide up by threshold amount
149        for (ThreadID tid = 0; tid < numThreads; tid++) {
150            maxEntries[tid] = thresholdIQ;
151        }
152
153        DPRINTF(IQ, "IQ sharing policy set to Threshold:"
154                "%i entries per thread.\n",thresholdIQ);
155   }
156    for (ThreadID tid = numThreads; tid < Impl::MaxThreads; tid++) {
157        maxEntries[tid] = 0;
158    }
159}
160
161template <class Impl>
162InstructionQueue<Impl>::~InstructionQueue()
163{
164    dependGraph.reset();
165#ifdef DEBUG
166    cprintf("Nodes traversed: %i, removed: %i\n",
167            dependGraph.nodesTraversed, dependGraph.nodesRemoved);
168#endif
169}
170
171template <class Impl>
172std::string
173InstructionQueue<Impl>::name() const
174{
175    return cpu->name() + ".iq";
176}
177
178template <class Impl>
179void
180InstructionQueue<Impl>::regStats()
181{
182    using namespace Stats;
183    iqInstsAdded
184        .name(name() + ".iqInstsAdded")
185        .desc("Number of instructions added to the IQ (excludes non-spec)")
186        .prereq(iqInstsAdded);
187
188    iqNonSpecInstsAdded
189        .name(name() + ".iqNonSpecInstsAdded")
190        .desc("Number of non-speculative instructions added to the IQ")
191        .prereq(iqNonSpecInstsAdded);
192
193    iqInstsIssued
194        .name(name() + ".iqInstsIssued")
195        .desc("Number of instructions issued")
196        .prereq(iqInstsIssued);
197
198    iqIntInstsIssued
199        .name(name() + ".iqIntInstsIssued")
200        .desc("Number of integer instructions issued")
201        .prereq(iqIntInstsIssued);
202
203    iqFloatInstsIssued
204        .name(name() + ".iqFloatInstsIssued")
205        .desc("Number of float instructions issued")
206        .prereq(iqFloatInstsIssued);
207
208    iqBranchInstsIssued
209        .name(name() + ".iqBranchInstsIssued")
210        .desc("Number of branch instructions issued")
211        .prereq(iqBranchInstsIssued);
212
213    iqMemInstsIssued
214        .name(name() + ".iqMemInstsIssued")
215        .desc("Number of memory instructions issued")
216        .prereq(iqMemInstsIssued);
217
218    iqMiscInstsIssued
219        .name(name() + ".iqMiscInstsIssued")
220        .desc("Number of miscellaneous instructions issued")
221        .prereq(iqMiscInstsIssued);
222
223    iqSquashedInstsIssued
224        .name(name() + ".iqSquashedInstsIssued")
225        .desc("Number of squashed instructions issued")
226        .prereq(iqSquashedInstsIssued);
227
228    iqSquashedInstsExamined
229        .name(name() + ".iqSquashedInstsExamined")
230        .desc("Number of squashed instructions iterated over during squash;"
231              " mainly for profiling")
232        .prereq(iqSquashedInstsExamined);
233
234    iqSquashedOperandsExamined
235        .name(name() + ".iqSquashedOperandsExamined")
236        .desc("Number of squashed operands that are examined and possibly "
237              "removed from graph")
238        .prereq(iqSquashedOperandsExamined);
239
240    iqSquashedNonSpecRemoved
241        .name(name() + ".iqSquashedNonSpecRemoved")
242        .desc("Number of squashed non-spec instructions that were removed")
243        .prereq(iqSquashedNonSpecRemoved);
244/*
245    queueResDist
246        .init(Num_OpClasses, 0, 99, 2)
247        .name(name() + ".IQ:residence:")
248        .desc("cycles from dispatch to issue")
249        .flags(total | pdf | cdf )
250        ;
251    for (int i = 0; i < Num_OpClasses; ++i) {
252        queueResDist.subname(i, opClassStrings[i]);
253    }
254*/
255    numIssuedDist
256        .init(0,totalWidth,1)
257        .name(name() + ".issued_per_cycle")
258        .desc("Number of insts issued each cycle")
259        .flags(pdf)
260        ;
261/*
262    dist_unissued
263        .init(Num_OpClasses+2)
264        .name(name() + ".unissued_cause")
265        .desc("Reason ready instruction not issued")
266        .flags(pdf | dist)
267        ;
268    for (int i=0; i < (Num_OpClasses + 2); ++i) {
269        dist_unissued.subname(i, unissued_names[i]);
270    }
271*/
272    statIssuedInstType
273        .init(numThreads,Enums::Num_OpClass)
274        .name(name() + ".FU_type")
275        .desc("Type of FU issued")
276        .flags(total | pdf | dist)
277        ;
278    statIssuedInstType.ysubnames(Enums::OpClassStrings);
279
280    //
281    //  How long did instructions for a particular FU type wait prior to issue
282    //
283/*
284    issueDelayDist
285        .init(Num_OpClasses,0,99,2)
286        .name(name() + ".")
287        .desc("cycles from operands ready to issue")
288        .flags(pdf | cdf)
289        ;
290
291    for (int i=0; i<Num_OpClasses; ++i) {
292        std::stringstream subname;
293        subname << opClassStrings[i] << "_delay";
294        issueDelayDist.subname(i, subname.str());
295    }
296*/
297    issueRate
298        .name(name() + ".rate")
299        .desc("Inst issue rate")
300        .flags(total)
301        ;
302    issueRate = iqInstsIssued / cpu->numCycles;
303
304    statFuBusy
305        .init(Num_OpClasses)
306        .name(name() + ".fu_full")
307        .desc("attempts to use FU when none available")
308        .flags(pdf | dist)
309        ;
310    for (int i=0; i < Num_OpClasses; ++i) {
311        statFuBusy.subname(i, Enums::OpClassStrings[i]);
312    }
313
314    fuBusy
315        .init(numThreads)
316        .name(name() + ".fu_busy_cnt")
317        .desc("FU busy when requested")
318        .flags(total)
319        ;
320
321    fuBusyRate
322        .name(name() + ".fu_busy_rate")
323        .desc("FU busy rate (busy events/executed inst)")
324        .flags(total)
325        ;
326    fuBusyRate = fuBusy / iqInstsIssued;
327
328    for (ThreadID tid = 0; tid < numThreads; tid++) {
329        // Tell mem dependence unit to reg stats as well.
330        memDepUnit[tid].regStats();
331    }
332
333    intInstQueueReads
334        .name(name() + ".int_inst_queue_reads")
335        .desc("Number of integer instruction queue reads")
336        .flags(total);
337
338    intInstQueueWrites
339        .name(name() + ".int_inst_queue_writes")
340        .desc("Number of integer instruction queue writes")
341        .flags(total);
342
343    intInstQueueWakeupAccesses
344        .name(name() + ".int_inst_queue_wakeup_accesses")
345        .desc("Number of integer instruction queue wakeup accesses")
346        .flags(total);
347
348    fpInstQueueReads
349        .name(name() + ".fp_inst_queue_reads")
350        .desc("Number of floating instruction queue reads")
351        .flags(total);
352
353    fpInstQueueWrites
354        .name(name() + ".fp_inst_queue_writes")
355        .desc("Number of floating instruction queue writes")
356        .flags(total);
357
358    fpInstQueueWakeupAccesses
359        .name(name() + ".fp_inst_queue_wakeup_accesses")
360        .desc("Number of floating instruction queue wakeup accesses")
361        .flags(total);
362
363    vecInstQueueReads
364        .name(name() + ".vec_inst_queue_reads")
365        .desc("Number of vector instruction queue reads")
366        .flags(total);
367
368    vecInstQueueWrites
369        .name(name() + ".vec_inst_queue_writes")
370        .desc("Number of vector instruction queue writes")
371        .flags(total);
372
373    vecInstQueueWakeupAccesses
374        .name(name() + ".vec_inst_queue_wakeup_accesses")
375        .desc("Number of vector instruction queue wakeup accesses")
376        .flags(total);
377
378    intAluAccesses
379        .name(name() + ".int_alu_accesses")
380        .desc("Number of integer alu accesses")
381        .flags(total);
382
383    fpAluAccesses
384        .name(name() + ".fp_alu_accesses")
385        .desc("Number of floating point alu accesses")
386        .flags(total);
387
388    vecAluAccesses
389        .name(name() + ".vec_alu_accesses")
390        .desc("Number of vector alu accesses")
391        .flags(total);
392
393}
394
395template <class Impl>
396void
397InstructionQueue<Impl>::resetState()
398{
399    //Initialize thread IQ counts
400    for (ThreadID tid = 0; tid < Impl::MaxThreads; tid++) {
401        count[tid] = 0;
402        instList[tid].clear();
403    }
404
405    // Initialize the number of free IQ entries.
406    freeEntries = numEntries;
407
408    // Note that in actuality, the registers corresponding to the logical
409    // registers start off as ready.  However this doesn't matter for the
410    // IQ as the instruction should have been correctly told if those
411    // registers are ready in rename.  Thus it can all be initialized as
412    // unready.
413    for (int i = 0; i < numPhysRegs; ++i) {
414        regScoreboard[i] = false;
415    }
416
417    for (ThreadID tid = 0; tid < Impl::MaxThreads; ++tid) {
418        squashedSeqNum[tid] = 0;
419    }
420
421    for (int i = 0; i < Num_OpClasses; ++i) {
422        while (!readyInsts[i].empty())
423            readyInsts[i].pop();
424        queueOnList[i] = false;
425        readyIt[i] = listOrder.end();
426    }
427    nonSpecInsts.clear();
428    listOrder.clear();
429    deferredMemInsts.clear();
430    blockedMemInsts.clear();
431    retryMemInsts.clear();
432    wbOutstanding = 0;
433}
434
435template <class Impl>
436void
437InstructionQueue<Impl>::setActiveThreads(list<ThreadID> *at_ptr)
438{
439    activeThreads = at_ptr;
440}
441
442template <class Impl>
443void
444InstructionQueue<Impl>::setIssueToExecuteQueue(TimeBuffer<IssueStruct> *i2e_ptr)
445{
446      issueToExecuteQueue = i2e_ptr;
447}
448
449template <class Impl>
450void
451InstructionQueue<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
452{
453    timeBuffer = tb_ptr;
454
455    fromCommit = timeBuffer->getWire(-commitToIEWDelay);
456}
457
458template <class Impl>
459bool
460InstructionQueue<Impl>::isDrained() const
461{
462    bool drained = dependGraph.empty() &&
463                   instsToExecute.empty() &&
464                   wbOutstanding == 0;
465    for (ThreadID tid = 0; tid < numThreads; ++tid)
466        drained = drained && memDepUnit[tid].isDrained();
467
468    return drained;
469}
470
471template <class Impl>
472void
473InstructionQueue<Impl>::drainSanityCheck() const
474{
475    assert(dependGraph.empty());
476    assert(instsToExecute.empty());
477    for (ThreadID tid = 0; tid < numThreads; ++tid)
478        memDepUnit[tid].drainSanityCheck();
479}
480
481template <class Impl>
482void
483InstructionQueue<Impl>::takeOverFrom()
484{
485    resetState();
486}
487
488template <class Impl>
489int
490InstructionQueue<Impl>::entryAmount(ThreadID num_threads)
491{
492    if (iqPolicy == SMTQueuePolicy::Partitioned) {
493        return numEntries / num_threads;
494    } else {
495        return 0;
496    }
497}
498
499
500template <class Impl>
501void
502InstructionQueue<Impl>::resetEntries()
503{
504    if (iqPolicy != SMTQueuePolicy::Dynamic || numThreads > 1) {
505        int active_threads = activeThreads->size();
506
507        list<ThreadID>::iterator threads = activeThreads->begin();
508        list<ThreadID>::iterator end = activeThreads->end();
509
510        while (threads != end) {
511            ThreadID tid = *threads++;
512
513            if (iqPolicy == SMTQueuePolicy::Partitioned) {
514                maxEntries[tid] = numEntries / active_threads;
515            } else if (iqPolicy == SMTQueuePolicy::Threshold &&
516                       active_threads == 1) {
517                maxEntries[tid] = numEntries;
518            }
519        }
520    }
521}
522
523template <class Impl>
524unsigned
525InstructionQueue<Impl>::numFreeEntries()
526{
527    return freeEntries;
528}
529
530template <class Impl>
531unsigned
532InstructionQueue<Impl>::numFreeEntries(ThreadID tid)
533{
534    return maxEntries[tid] - count[tid];
535}
536
537// Might want to do something more complex if it knows how many instructions
538// will be issued this cycle.
539template <class Impl>
540bool
541InstructionQueue<Impl>::isFull()
542{
543    if (freeEntries == 0) {
544        return(true);
545    } else {
546        return(false);
547    }
548}
549
550template <class Impl>
551bool
552InstructionQueue<Impl>::isFull(ThreadID tid)
553{
554    if (numFreeEntries(tid) == 0) {
555        return(true);
556    } else {
557        return(false);
558    }
559}
560
561template <class Impl>
562bool
563InstructionQueue<Impl>::hasReadyInsts()
564{
565    if (!listOrder.empty()) {
566        return true;
567    }
568
569    for (int i = 0; i < Num_OpClasses; ++i) {
570        if (!readyInsts[i].empty()) {
571            return true;
572        }
573    }
574
575    return false;
576}
577
578template <class Impl>
579void
580InstructionQueue<Impl>::insert(const DynInstPtr &new_inst)
581{
582    if (new_inst->isFloating()) {
583        fpInstQueueWrites++;
584    } else if (new_inst->isVector()) {
585        vecInstQueueWrites++;
586    } else {
587        intInstQueueWrites++;
588    }
589    // Make sure the instruction is valid
590    assert(new_inst);
591
592    DPRINTF(IQ, "Adding instruction [sn:%llu] PC %s to the IQ.\n",
593            new_inst->seqNum, new_inst->pcState());
594
595    assert(freeEntries != 0);
596
597    instList[new_inst->threadNumber].push_back(new_inst);
598
599    --freeEntries;
600
601    new_inst->setInIQ();
602
603    // Look through its source registers (physical regs), and mark any
604    // dependencies.
605    addToDependents(new_inst);
606
607    // Have this instruction set itself as the producer of its destination
608    // register(s).
609    addToProducers(new_inst);
610
611    if (new_inst->isMemRef()) {
612        memDepUnit[new_inst->threadNumber].insert(new_inst);
613    } else {
614        addIfReady(new_inst);
615    }
616
617    ++iqInstsAdded;
618
619    count[new_inst->threadNumber]++;
620
621    assert(freeEntries == (numEntries - countInsts()));
622}
623
624template <class Impl>
625void
626InstructionQueue<Impl>::insertNonSpec(const DynInstPtr &new_inst)
627{
628    // @todo: Clean up this code; can do it by setting inst as unable
629    // to issue, then calling normal insert on the inst.
630    if (new_inst->isFloating()) {
631        fpInstQueueWrites++;
632    } else if (new_inst->isVector()) {
633        vecInstQueueWrites++;
634    } else {
635        intInstQueueWrites++;
636    }
637
638    assert(new_inst);
639
640    nonSpecInsts[new_inst->seqNum] = new_inst;
641
642    DPRINTF(IQ, "Adding non-speculative instruction [sn:%llu] PC %s "
643            "to the IQ.\n",
644            new_inst->seqNum, new_inst->pcState());
645
646    assert(freeEntries != 0);
647
648    instList[new_inst->threadNumber].push_back(new_inst);
649
650    --freeEntries;
651
652    new_inst->setInIQ();
653
654    // Have this instruction set itself as the producer of its destination
655    // register(s).
656    addToProducers(new_inst);
657
658    // If it's a memory instruction, add it to the memory dependency
659    // unit.
660    if (new_inst->isMemRef()) {
661        memDepUnit[new_inst->threadNumber].insertNonSpec(new_inst);
662    }
663
664    ++iqNonSpecInstsAdded;
665
666    count[new_inst->threadNumber]++;
667
668    assert(freeEntries == (numEntries - countInsts()));
669}
670
671template <class Impl>
672void
673InstructionQueue<Impl>::insertBarrier(const DynInstPtr &barr_inst)
674{
675    memDepUnit[barr_inst->threadNumber].insertBarrier(barr_inst);
676
677    insertNonSpec(barr_inst);
678}
679
680template <class Impl>
681typename Impl::DynInstPtr
682InstructionQueue<Impl>::getInstToExecute()
683{
684    assert(!instsToExecute.empty());
685    DynInstPtr inst = std::move(instsToExecute.front());
686    instsToExecute.pop_front();
687    if (inst->isFloating()) {
688        fpInstQueueReads++;
689    } else if (inst->isVector()) {
690        vecInstQueueReads++;
691    } else {
692        intInstQueueReads++;
693    }
694    return inst;
695}
696
697template <class Impl>
698void
699InstructionQueue<Impl>::addToOrderList(OpClass op_class)
700{
701    assert(!readyInsts[op_class].empty());
702
703    ListOrderEntry queue_entry;
704
705    queue_entry.queueType = op_class;
706
707    queue_entry.oldestInst = readyInsts[op_class].top()->seqNum;
708
709    ListOrderIt list_it = listOrder.begin();
710    ListOrderIt list_end_it = listOrder.end();
711
712    while (list_it != list_end_it) {
713        if ((*list_it).oldestInst > queue_entry.oldestInst) {
714            break;
715        }
716
717        list_it++;
718    }
719
720    readyIt[op_class] = listOrder.insert(list_it, queue_entry);
721    queueOnList[op_class] = true;
722}
723
724template <class Impl>
725void
726InstructionQueue<Impl>::moveToYoungerInst(ListOrderIt list_order_it)
727{
728    // Get iterator of next item on the list
729    // Delete the original iterator
730    // Determine if the next item is either the end of the list or younger
731    // than the new instruction.  If so, then add in a new iterator right here.
732    // If not, then move along.
733    ListOrderEntry queue_entry;
734    OpClass op_class = (*list_order_it).queueType;
735    ListOrderIt next_it = list_order_it;
736
737    ++next_it;
738
739    queue_entry.queueType = op_class;
740    queue_entry.oldestInst = readyInsts[op_class].top()->seqNum;
741
742    while (next_it != listOrder.end() &&
743           (*next_it).oldestInst < queue_entry.oldestInst) {
744        ++next_it;
745    }
746
747    readyIt[op_class] = listOrder.insert(next_it, queue_entry);
748}
749
750template <class Impl>
751void
752InstructionQueue<Impl>::processFUCompletion(const DynInstPtr &inst, int fu_idx)
753{
754    DPRINTF(IQ, "Processing FU completion [sn:%llu]\n", inst->seqNum);
755    assert(!cpu->switchedOut());
756    // The CPU could have been sleeping until this op completed (*extremely*
757    // long latency op).  Wake it if it was.  This may be overkill.
758   --wbOutstanding;
759    iewStage->wakeCPU();
760
761    if (fu_idx > -1)
762        fuPool->freeUnitNextCycle(fu_idx);
763
764    // @todo: Ensure that these FU Completions happen at the beginning
765    // of a cycle, otherwise they could add too many instructions to
766    // the queue.
767    issueToExecuteQueue->access(-1)->size++;
768    instsToExecute.push_back(inst);
769}
770
771// @todo: Figure out a better way to remove the squashed items from the
772// lists.  Checking the top item of each list to see if it's squashed
773// wastes time and forces jumps.
774template <class Impl>
775void
776InstructionQueue<Impl>::scheduleReadyInsts()
777{
778    DPRINTF(IQ, "Attempting to schedule ready instructions from "
779            "the IQ.\n");
780
781    IssueStruct *i2e_info = issueToExecuteQueue->access(0);
782
783    DynInstPtr mem_inst;
784    while (mem_inst = std::move(getDeferredMemInstToExecute())) {
785        addReadyMemInst(mem_inst);
786    }
787
788    // See if any cache blocked instructions are able to be executed
789    while (mem_inst = std::move(getBlockedMemInstToExecute())) {
790        addReadyMemInst(mem_inst);
791    }
792
793    // Have iterator to head of the list
794    // While I haven't exceeded bandwidth or reached the end of the list,
795    // Try to get a FU that can do what this op needs.
796    // If successful, change the oldestInst to the new top of the list, put
797    // the queue in the proper place in the list.
798    // Increment the iterator.
799    // This will avoid trying to schedule a certain op class if there are no
800    // FUs that handle it.
801    int total_issued = 0;
802    ListOrderIt order_it = listOrder.begin();
803    ListOrderIt order_end_it = listOrder.end();
804
805    while (total_issued < totalWidth && order_it != order_end_it) {
806        OpClass op_class = (*order_it).queueType;
807
808        assert(!readyInsts[op_class].empty());
809
810        DynInstPtr issuing_inst = readyInsts[op_class].top();
811
812        if (issuing_inst->isFloating()) {
813            fpInstQueueReads++;
814        } else if (issuing_inst->isVector()) {
815            vecInstQueueReads++;
816        } else {
817            intInstQueueReads++;
818        }
819
820        assert(issuing_inst->seqNum == (*order_it).oldestInst);
821
822        if (issuing_inst->isSquashed()) {
823            readyInsts[op_class].pop();
824
825            if (!readyInsts[op_class].empty()) {
826                moveToYoungerInst(order_it);
827            } else {
828                readyIt[op_class] = listOrder.end();
829                queueOnList[op_class] = false;
830            }
831
832            listOrder.erase(order_it++);
833
834            ++iqSquashedInstsIssued;
835
836            continue;
837        }
838
839        int idx = FUPool::NoCapableFU;
840        Cycles op_latency = Cycles(1);
841        ThreadID tid = issuing_inst->threadNumber;
842
843        if (op_class != No_OpClass) {
844            idx = fuPool->getUnit(op_class);
845            if (issuing_inst->isFloating()) {
846                fpAluAccesses++;
847            } else if (issuing_inst->isVector()) {
848                vecAluAccesses++;
849            } else {
850                intAluAccesses++;
851            }
852            if (idx > FUPool::NoFreeFU) {
853                op_latency = fuPool->getOpLatency(op_class);
854            }
855        }
856
857        // If we have an instruction that doesn't require a FU, or a
858        // valid FU, then schedule for execution.
859        if (idx != FUPool::NoFreeFU) {
860            if (op_latency == Cycles(1)) {
861                i2e_info->size++;
862                instsToExecute.push_back(issuing_inst);
863
864                // Add the FU onto the list of FU's to be freed next
865                // cycle if we used one.
866                if (idx >= 0)
867                    fuPool->freeUnitNextCycle(idx);
868            } else {
869                bool pipelined = fuPool->isPipelined(op_class);
870                // Generate completion event for the FU
871                ++wbOutstanding;
872                FUCompletion *execution = new FUCompletion(issuing_inst,
873                                                           idx, this);
874
875                cpu->schedule(execution,
876                              cpu->clockEdge(Cycles(op_latency - 1)));
877
878                if (!pipelined) {
879                    // If FU isn't pipelined, then it must be freed
880                    // upon the execution completing.
881                    execution->setFreeFU();
882                } else {
883                    // Add the FU onto the list of FU's to be freed next cycle.
884                    fuPool->freeUnitNextCycle(idx);
885                }
886            }
887
888            DPRINTF(IQ, "Thread %i: Issuing instruction PC %s "
889                    "[sn:%llu]\n",
890                    tid, issuing_inst->pcState(),
891                    issuing_inst->seqNum);
892
893            readyInsts[op_class].pop();
894
895            if (!readyInsts[op_class].empty()) {
896                moveToYoungerInst(order_it);
897            } else {
898                readyIt[op_class] = listOrder.end();
899                queueOnList[op_class] = false;
900            }
901
902            issuing_inst->setIssued();
903            ++total_issued;
904
905#if TRACING_ON
906            issuing_inst->issueTick = curTick() - issuing_inst->fetchTick;
907#endif
908
909            if (!issuing_inst->isMemRef()) {
910                // Memory instructions can not be freed from the IQ until they
911                // complete.
912                ++freeEntries;
913                count[tid]--;
914                issuing_inst->clearInIQ();
915            } else {
916                memDepUnit[tid].issue(issuing_inst);
917            }
918
919            listOrder.erase(order_it++);
920            statIssuedInstType[tid][op_class]++;
921        } else {
922            statFuBusy[op_class]++;
923            fuBusy[tid]++;
924            ++order_it;
925        }
926    }
927
928    numIssuedDist.sample(total_issued);
929    iqInstsIssued+= total_issued;
930
931    // If we issued any instructions, tell the CPU we had activity.
932    // @todo If the way deferred memory instructions are handeled due to
933    // translation changes then the deferredMemInsts condition should be removed
934    // from the code below.
935    if (total_issued || !retryMemInsts.empty() || !deferredMemInsts.empty()) {
936        cpu->activityThisCycle();
937    } else {
938        DPRINTF(IQ, "Not able to schedule any instructions.\n");
939    }
940}
941
942template <class Impl>
943void
944InstructionQueue<Impl>::scheduleNonSpec(const InstSeqNum &inst)
945{
946    DPRINTF(IQ, "Marking nonspeculative instruction [sn:%llu] as ready "
947            "to execute.\n", inst);
948
949    NonSpecMapIt inst_it = nonSpecInsts.find(inst);
950
951    assert(inst_it != nonSpecInsts.end());
952
953    ThreadID tid = (*inst_it).second->threadNumber;
954
955    (*inst_it).second->setAtCommit();
956
957    (*inst_it).second->setCanIssue();
958
959    if (!(*inst_it).second->isMemRef()) {
960        addIfReady((*inst_it).second);
961    } else {
962        memDepUnit[tid].nonSpecInstReady((*inst_it).second);
963    }
964
965    (*inst_it).second = NULL;
966
967    nonSpecInsts.erase(inst_it);
968}
969
970template <class Impl>
971void
972InstructionQueue<Impl>::commit(const InstSeqNum &inst, ThreadID tid)
973{
974    DPRINTF(IQ, "[tid:%i] Committing instructions older than [sn:%llu]\n",
975            tid,inst);
976
977    ListIt iq_it = instList[tid].begin();
978
979    while (iq_it != instList[tid].end() &&
980           (*iq_it)->seqNum <= inst) {
981        ++iq_it;
982        instList[tid].pop_front();
983    }
984
985    assert(freeEntries == (numEntries - countInsts()));
986}
987
988template <class Impl>
989int
990InstructionQueue<Impl>::wakeDependents(const DynInstPtr &completed_inst)
991{
992    int dependents = 0;
993
994    // The instruction queue here takes care of both floating and int ops
995    if (completed_inst->isFloating()) {
996        fpInstQueueWakeupAccesses++;
997    } else if (completed_inst->isVector()) {
998        vecInstQueueWakeupAccesses++;
999    } else {
1000        intInstQueueWakeupAccesses++;
1001    }
1002
1003    DPRINTF(IQ, "Waking dependents of completed instruction.\n");
1004
1005    assert(!completed_inst->isSquashed());
1006
1007    // Tell the memory dependence unit to wake any dependents on this
1008    // instruction if it is a memory instruction.  Also complete the memory
1009    // instruction at this point since we know it executed without issues.
1010    // @todo: Might want to rename "completeMemInst" to something that
1011    // indicates that it won't need to be replayed, and call this
1012    // earlier.  Might not be a big deal.
1013    if (completed_inst->isMemRef()) {
1014        memDepUnit[completed_inst->threadNumber].wakeDependents(completed_inst);
1015        completeMemInst(completed_inst);
1016    } else if (completed_inst->isMemBarrier() ||
1017               completed_inst->isWriteBarrier()) {
1018        memDepUnit[completed_inst->threadNumber].completeBarrier(completed_inst);
1019    }
1020
1021    for (int dest_reg_idx = 0;
1022         dest_reg_idx < completed_inst->numDestRegs();
1023         dest_reg_idx++)
1024    {
1025        PhysRegIdPtr dest_reg =
1026            completed_inst->renamedDestRegIdx(dest_reg_idx);
1027
1028        // Special case of uniq or control registers.  They are not
1029        // handled by the IQ and thus have no dependency graph entry.
1030        if (dest_reg->isFixedMapping()) {
1031            DPRINTF(IQ, "Reg %d [%s] is part of a fix mapping, skipping\n",
1032                    dest_reg->index(), dest_reg->className());
1033            continue;
1034        }
1035
1036        // Avoid waking up dependents if the register is pinned
1037        dest_reg->decrNumPinnedWritesToComplete();
1038        if (dest_reg->isPinned())
1039            completed_inst->setPinnedRegsWritten();
1040
1041        if (dest_reg->getNumPinnedWritesToComplete() != 0) {
1042            DPRINTF(IQ, "Reg %d [%s] is pinned, skipping\n",
1043                    dest_reg->index(), dest_reg->className());
1044            continue;
1045        }
1046
1047        DPRINTF(IQ, "Waking any dependents on register %i (%s).\n",
1048                dest_reg->index(),
1049                dest_reg->className());
1050
1051        //Go through the dependency chain, marking the registers as
1052        //ready within the waiting instructions.
1053        DynInstPtr dep_inst = dependGraph.pop(dest_reg->flatIndex());
1054
1055        while (dep_inst) {
1056            DPRINTF(IQ, "Waking up a dependent instruction, [sn:%llu] "
1057                    "PC %s.\n", dep_inst->seqNum, dep_inst->pcState());
1058
1059            // Might want to give more information to the instruction
1060            // so that it knows which of its source registers is
1061            // ready.  However that would mean that the dependency
1062            // graph entries would need to hold the src_reg_idx.
1063            dep_inst->markSrcRegReady();
1064
1065            addIfReady(dep_inst);
1066
1067            dep_inst = dependGraph.pop(dest_reg->flatIndex());
1068
1069            ++dependents;
1070        }
1071
1072        // Reset the head node now that all of its dependents have
1073        // been woken up.
1074        assert(dependGraph.empty(dest_reg->flatIndex()));
1075        dependGraph.clearInst(dest_reg->flatIndex());
1076
1077        // Mark the scoreboard as having that register ready.
1078        regScoreboard[dest_reg->flatIndex()] = true;
1079    }
1080    return dependents;
1081}
1082
1083template <class Impl>
1084void
1085InstructionQueue<Impl>::addReadyMemInst(const DynInstPtr &ready_inst)
1086{
1087    OpClass op_class = ready_inst->opClass();
1088
1089    readyInsts[op_class].push(ready_inst);
1090
1091    // Will need to reorder the list if either a queue is not on the list,
1092    // or it has an older instruction than last time.
1093    if (!queueOnList[op_class]) {
1094        addToOrderList(op_class);
1095    } else if (readyInsts[op_class].top()->seqNum  <
1096               (*readyIt[op_class]).oldestInst) {
1097        listOrder.erase(readyIt[op_class]);
1098        addToOrderList(op_class);
1099    }
1100
1101    DPRINTF(IQ, "Instruction is ready to issue, putting it onto "
1102            "the ready list, PC %s opclass:%i [sn:%llu].\n",
1103            ready_inst->pcState(), op_class, ready_inst->seqNum);
1104}
1105
1106template <class Impl>
1107void
1108InstructionQueue<Impl>::rescheduleMemInst(const DynInstPtr &resched_inst)
1109{
1110    DPRINTF(IQ, "Rescheduling mem inst [sn:%llu]\n", resched_inst->seqNum);
1111
1112    // Reset DTB translation state
1113    resched_inst->translationStarted(false);
1114    resched_inst->translationCompleted(false);
1115
1116    resched_inst->clearCanIssue();
1117    memDepUnit[resched_inst->threadNumber].reschedule(resched_inst);
1118}
1119
1120template <class Impl>
1121void
1122InstructionQueue<Impl>::replayMemInst(const DynInstPtr &replay_inst)
1123{
1124    memDepUnit[replay_inst->threadNumber].replay();
1125}
1126
1127template <class Impl>
1128void
1129InstructionQueue<Impl>::completeMemInst(const DynInstPtr &completed_inst)
1130{
1131    ThreadID tid = completed_inst->threadNumber;
1132
1133    DPRINTF(IQ, "Completing mem instruction PC: %s [sn:%llu]\n",
1134            completed_inst->pcState(), completed_inst->seqNum);
1135
1136    ++freeEntries;
1137
1138    completed_inst->memOpDone(true);
1139
1140    memDepUnit[tid].completed(completed_inst);
1141    count[tid]--;
1142}
1143
1144template <class Impl>
1145void
1146InstructionQueue<Impl>::deferMemInst(const DynInstPtr &deferred_inst)
1147{
1148    deferredMemInsts.push_back(deferred_inst);
1149}
1150
1151template <class Impl>
1152void
1153InstructionQueue<Impl>::blockMemInst(const DynInstPtr &blocked_inst)
1154{
1155    blocked_inst->clearIssued();
1156    blocked_inst->clearCanIssue();
1157    blockedMemInsts.push_back(blocked_inst);
1158}
1159
1160template <class Impl>
1161void
1162InstructionQueue<Impl>::cacheUnblocked()
1163{
1164    retryMemInsts.splice(retryMemInsts.end(), blockedMemInsts);
1165    // Get the CPU ticking again
1166    cpu->wakeCPU();
1167}
1168
1169template <class Impl>
1170typename Impl::DynInstPtr
1171InstructionQueue<Impl>::getDeferredMemInstToExecute()
1172{
1173    for (ListIt it = deferredMemInsts.begin(); it != deferredMemInsts.end();
1174         ++it) {
1175        if ((*it)->translationCompleted() || (*it)->isSquashed()) {
1176            DynInstPtr mem_inst = std::move(*it);
1177            deferredMemInsts.erase(it);
1178            return mem_inst;
1179        }
1180    }
1181    return nullptr;
1182}
1183
1184template <class Impl>
1185typename Impl::DynInstPtr
1186InstructionQueue<Impl>::getBlockedMemInstToExecute()
1187{
1188    if (retryMemInsts.empty()) {
1189        return nullptr;
1190    } else {
1191        DynInstPtr mem_inst = std::move(retryMemInsts.front());
1192        retryMemInsts.pop_front();
1193        return mem_inst;
1194    }
1195}
1196
1197template <class Impl>
1198void
1199InstructionQueue<Impl>::violation(const DynInstPtr &store,
1200                                  const DynInstPtr &faulting_load)
1201{
1202    intInstQueueWrites++;
1203    memDepUnit[store->threadNumber].violation(store, faulting_load);
1204}
1205
1206template <class Impl>
1207void
1208InstructionQueue<Impl>::squash(ThreadID tid)
1209{
1210    DPRINTF(IQ, "[tid:%i] Starting to squash instructions in "
1211            "the IQ.\n", tid);
1212
1213    // Read instruction sequence number of last instruction out of the
1214    // time buffer.
1215    squashedSeqNum[tid] = fromCommit->commitInfo[tid].doneSeqNum;
1216
1217    doSquash(tid);
1218
1219    // Also tell the memory dependence unit to squash.
1220    memDepUnit[tid].squash(squashedSeqNum[tid], tid);
1221}
1222
1223template <class Impl>
1224void
1225InstructionQueue<Impl>::doSquash(ThreadID tid)
1226{
1227    // Start at the tail.
1228    ListIt squash_it = instList[tid].end();
1229    --squash_it;
1230
1231    DPRINTF(IQ, "[tid:%i] Squashing until sequence number %i!\n",
1232            tid, squashedSeqNum[tid]);
1233
1234    // Squash any instructions younger than the squashed sequence number
1235    // given.
1236    while (squash_it != instList[tid].end() &&
1237           (*squash_it)->seqNum > squashedSeqNum[tid]) {
1238
1239        DynInstPtr squashed_inst = (*squash_it);
1240        if (squashed_inst->isFloating()) {
1241            fpInstQueueWrites++;
1242        } else if (squashed_inst->isVector()) {
1243            vecInstQueueWrites++;
1244        } else {
1245            intInstQueueWrites++;
1246        }
1247
1248        // Only handle the instruction if it actually is in the IQ and
1249        // hasn't already been squashed in the IQ.
1250        if (squashed_inst->threadNumber != tid ||
1251            squashed_inst->isSquashedInIQ()) {
1252            --squash_it;
1253            continue;
1254        }
1255
1256        if (!squashed_inst->isIssued() ||
1257            (squashed_inst->isMemRef() &&
1258             !squashed_inst->memOpDone())) {
1259
1260            DPRINTF(IQ, "[tid:%i] Instruction [sn:%llu] PC %s squashed.\n",
1261                    tid, squashed_inst->seqNum, squashed_inst->pcState());
1262
1263            bool is_acq_rel = squashed_inst->isMemBarrier() &&
1264                         (squashed_inst->isLoad() ||
1265                          (squashed_inst->isStore() &&
1266                             !squashed_inst->isStoreConditional()));
1267
1268            // Remove the instruction from the dependency list.
1269            if (is_acq_rel ||
1270                (!squashed_inst->isNonSpeculative() &&
1271                 !squashed_inst->isStoreConditional() &&
1272                 !squashed_inst->isAtomic() &&
1273                 !squashed_inst->isMemBarrier() &&
1274                 !squashed_inst->isWriteBarrier())) {
1275
1276                for (int src_reg_idx = 0;
1277                     src_reg_idx < squashed_inst->numSrcRegs();
1278                     src_reg_idx++)
1279                {
1280                    PhysRegIdPtr src_reg =
1281                        squashed_inst->renamedSrcRegIdx(src_reg_idx);
1282
1283                    // Only remove it from the dependency graph if it
1284                    // was placed there in the first place.
1285
1286                    // Instead of doing a linked list traversal, we
1287                    // can just remove these squashed instructions
1288                    // either at issue time, or when the register is
1289                    // overwritten.  The only downside to this is it
1290                    // leaves more room for error.
1291
1292                    if (!squashed_inst->isReadySrcRegIdx(src_reg_idx) &&
1293                        !src_reg->isFixedMapping()) {
1294                        dependGraph.remove(src_reg->flatIndex(),
1295                                           squashed_inst);
1296                    }
1297
1298                    ++iqSquashedOperandsExamined;
1299                }
1300
1301            } else if (!squashed_inst->isStoreConditional() ||
1302                       !squashed_inst->isCompleted()) {
1303                NonSpecMapIt ns_inst_it =
1304                    nonSpecInsts.find(squashed_inst->seqNum);
1305
1306                // we remove non-speculative instructions from
1307                // nonSpecInsts already when they are ready, and so we
1308                // cannot always expect to find them
1309                if (ns_inst_it == nonSpecInsts.end()) {
1310                    // loads that became ready but stalled on a
1311                    // blocked cache are alreayd removed from
1312                    // nonSpecInsts, and have not faulted
1313                    assert(squashed_inst->getFault() != NoFault ||
1314                           squashed_inst->isMemRef());
1315                } else {
1316
1317                    (*ns_inst_it).second = NULL;
1318
1319                    nonSpecInsts.erase(ns_inst_it);
1320
1321                    ++iqSquashedNonSpecRemoved;
1322                }
1323            }
1324
1325            // Might want to also clear out the head of the dependency graph.
1326
1327            // Mark it as squashed within the IQ.
1328            squashed_inst->setSquashedInIQ();
1329
1330            // @todo: Remove this hack where several statuses are set so the
1331            // inst will flow through the rest of the pipeline.
1332            squashed_inst->setIssued();
1333            squashed_inst->setCanCommit();
1334            squashed_inst->clearInIQ();
1335
1336            //Update Thread IQ Count
1337            count[squashed_inst->threadNumber]--;
1338
1339            ++freeEntries;
1340        }
1341
1342        // IQ clears out the heads of the dependency graph only when
1343        // instructions reach writeback stage. If an instruction is squashed
1344        // before writeback stage, its head of dependency graph would not be
1345        // cleared out; it holds the instruction's DynInstPtr. This prevents
1346        // freeing the squashed instruction's DynInst.
1347        // Thus, we need to manually clear out the squashed instructions' heads
1348        // of dependency graph.
1349        for (int dest_reg_idx = 0;
1350             dest_reg_idx < squashed_inst->numDestRegs();
1351             dest_reg_idx++)
1352        {
1353            PhysRegIdPtr dest_reg =
1354                squashed_inst->renamedDestRegIdx(dest_reg_idx);
1355            if (dest_reg->isFixedMapping()){
1356                continue;
1357            }
1358            assert(dependGraph.empty(dest_reg->flatIndex()));
1359            dependGraph.clearInst(dest_reg->flatIndex());
1360        }
1361        instList[tid].erase(squash_it--);
1362        ++iqSquashedInstsExamined;
1363    }
1364}
1365
1366template <class Impl>
1367bool
1368InstructionQueue<Impl>::addToDependents(const DynInstPtr &new_inst)
1369{
1370    // Loop through the instruction's source registers, adding
1371    // them to the dependency list if they are not ready.
1372    int8_t total_src_regs = new_inst->numSrcRegs();
1373    bool return_val = false;
1374
1375    for (int src_reg_idx = 0;
1376         src_reg_idx < total_src_regs;
1377         src_reg_idx++)
1378    {
1379        // Only add it to the dependency graph if it's not ready.
1380        if (!new_inst->isReadySrcRegIdx(src_reg_idx)) {
1381            PhysRegIdPtr src_reg = new_inst->renamedSrcRegIdx(src_reg_idx);
1382
1383            // Check the IQ's scoreboard to make sure the register
1384            // hasn't become ready while the instruction was in flight
1385            // between stages.  Only if it really isn't ready should
1386            // it be added to the dependency graph.
1387            if (src_reg->isFixedMapping()) {
1388                continue;
1389            } else if (!regScoreboard[src_reg->flatIndex()]) {
1390                DPRINTF(IQ, "Instruction PC %s has src reg %i (%s) that "
1391                        "is being added to the dependency chain.\n",
1392                        new_inst->pcState(), src_reg->index(),
1393                        src_reg->className());
1394
1395                dependGraph.insert(src_reg->flatIndex(), new_inst);
1396
1397                // Change the return value to indicate that something
1398                // was added to the dependency graph.
1399                return_val = true;
1400            } else {
1401                DPRINTF(IQ, "Instruction PC %s has src reg %i (%s) that "
1402                        "became ready before it reached the IQ.\n",
1403                        new_inst->pcState(), src_reg->index(),
1404                        src_reg->className());
1405                // Mark a register ready within the instruction.
1406                new_inst->markSrcRegReady(src_reg_idx);
1407            }
1408        }
1409    }
1410
1411    return return_val;
1412}
1413
1414template <class Impl>
1415void
1416InstructionQueue<Impl>::addToProducers(const DynInstPtr &new_inst)
1417{
1418    // Nothing really needs to be marked when an instruction becomes
1419    // the producer of a register's value, but for convenience a ptr
1420    // to the producing instruction will be placed in the head node of
1421    // the dependency links.
1422    int8_t total_dest_regs = new_inst->numDestRegs();
1423
1424    for (int dest_reg_idx = 0;
1425         dest_reg_idx < total_dest_regs;
1426         dest_reg_idx++)
1427    {
1428        PhysRegIdPtr dest_reg = new_inst->renamedDestRegIdx(dest_reg_idx);
1429
1430        // Some registers have fixed mapping, and there is no need to track
1431        // dependencies as these instructions must be executed at commit.
1432        if (dest_reg->isFixedMapping()) {
1433            continue;
1434        }
1435
1436        if (!dependGraph.empty(dest_reg->flatIndex())) {
1437            dependGraph.dump();
1438            panic("Dependency graph %i (%s) (flat: %i) not empty!",
1439                  dest_reg->index(), dest_reg->className(),
1440                  dest_reg->flatIndex());
1441        }
1442
1443        dependGraph.setInst(dest_reg->flatIndex(), new_inst);
1444
1445        // Mark the scoreboard to say it's not yet ready.
1446        regScoreboard[dest_reg->flatIndex()] = false;
1447    }
1448}
1449
1450template <class Impl>
1451void
1452InstructionQueue<Impl>::addIfReady(const DynInstPtr &inst)
1453{
1454    // If the instruction now has all of its source registers
1455    // available, then add it to the list of ready instructions.
1456    if (inst->readyToIssue()) {
1457
1458        //Add the instruction to the proper ready list.
1459        if (inst->isMemRef()) {
1460
1461            DPRINTF(IQ, "Checking if memory instruction can issue.\n");
1462
1463            // Message to the mem dependence unit that this instruction has
1464            // its registers ready.
1465            memDepUnit[inst->threadNumber].regsReady(inst);
1466
1467            return;
1468        }
1469
1470        OpClass op_class = inst->opClass();
1471
1472        DPRINTF(IQ, "Instruction is ready to issue, putting it onto "
1473                "the ready list, PC %s opclass:%i [sn:%llu].\n",
1474                inst->pcState(), op_class, inst->seqNum);
1475
1476        readyInsts[op_class].push(inst);
1477
1478        // Will need to reorder the list if either a queue is not on the list,
1479        // or it has an older instruction than last time.
1480        if (!queueOnList[op_class]) {
1481            addToOrderList(op_class);
1482        } else if (readyInsts[op_class].top()->seqNum  <
1483                   (*readyIt[op_class]).oldestInst) {
1484            listOrder.erase(readyIt[op_class]);
1485            addToOrderList(op_class);
1486        }
1487    }
1488}
1489
1490template <class Impl>
1491int
1492InstructionQueue<Impl>::countInsts()
1493{
1494    return numEntries - freeEntries;
1495}
1496
1497template <class Impl>
1498void
1499InstructionQueue<Impl>::dumpLists()
1500{
1501    for (int i = 0; i < Num_OpClasses; ++i) {
1502        cprintf("Ready list %i size: %i\n", i, readyInsts[i].size());
1503
1504        cprintf("\n");
1505    }
1506
1507    cprintf("Non speculative list size: %i\n", nonSpecInsts.size());
1508
1509    NonSpecMapIt non_spec_it = nonSpecInsts.begin();
1510    NonSpecMapIt non_spec_end_it = nonSpecInsts.end();
1511
1512    cprintf("Non speculative list: ");
1513
1514    while (non_spec_it != non_spec_end_it) {
1515        cprintf("%s [sn:%llu]", (*non_spec_it).second->pcState(),
1516                (*non_spec_it).second->seqNum);
1517        ++non_spec_it;
1518    }
1519
1520    cprintf("\n");
1521
1522    ListOrderIt list_order_it = listOrder.begin();
1523    ListOrderIt list_order_end_it = listOrder.end();
1524    int i = 1;
1525
1526    cprintf("List order: ");
1527
1528    while (list_order_it != list_order_end_it) {
1529        cprintf("%i OpClass:%i [sn:%llu] ", i, (*list_order_it).queueType,
1530                (*list_order_it).oldestInst);
1531
1532        ++list_order_it;
1533        ++i;
1534    }
1535
1536    cprintf("\n");
1537}
1538
1539
1540template <class Impl>
1541void
1542InstructionQueue<Impl>::dumpInsts()
1543{
1544    for (ThreadID tid = 0; tid < numThreads; ++tid) {
1545        int num = 0;
1546        int valid_num = 0;
1547        ListIt inst_list_it = instList[tid].begin();
1548
1549        while (inst_list_it != instList[tid].end()) {
1550            cprintf("Instruction:%i\n", num);
1551            if (!(*inst_list_it)->isSquashed()) {
1552                if (!(*inst_list_it)->isIssued()) {
1553                    ++valid_num;
1554                    cprintf("Count:%i\n", valid_num);
1555                } else if ((*inst_list_it)->isMemRef() &&
1556                           !(*inst_list_it)->memOpDone()) {
1557                    // Loads that have not been marked as executed
1558                    // still count towards the total instructions.
1559                    ++valid_num;
1560                    cprintf("Count:%i\n", valid_num);
1561                }
1562            }
1563
1564            cprintf("PC: %s\n[sn:%llu]\n[tid:%i]\n"
1565                    "Issued:%i\nSquashed:%i\n",
1566                    (*inst_list_it)->pcState(),
1567                    (*inst_list_it)->seqNum,
1568                    (*inst_list_it)->threadNumber,
1569                    (*inst_list_it)->isIssued(),
1570                    (*inst_list_it)->isSquashed());
1571
1572            if ((*inst_list_it)->isMemRef()) {
1573                cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone());
1574            }
1575
1576            cprintf("\n");
1577
1578            inst_list_it++;
1579            ++num;
1580        }
1581    }
1582
1583    cprintf("Insts to Execute list:\n");
1584
1585    int num = 0;
1586    int valid_num = 0;
1587    ListIt inst_list_it = instsToExecute.begin();
1588
1589    while (inst_list_it != instsToExecute.end())
1590    {
1591        cprintf("Instruction:%i\n",
1592                num);
1593        if (!(*inst_list_it)->isSquashed()) {
1594            if (!(*inst_list_it)->isIssued()) {
1595                ++valid_num;
1596                cprintf("Count:%i\n", valid_num);
1597            } else if ((*inst_list_it)->isMemRef() &&
1598                       !(*inst_list_it)->memOpDone()) {
1599                // Loads that have not been marked as executed
1600                // still count towards the total instructions.
1601                ++valid_num;
1602                cprintf("Count:%i\n", valid_num);
1603            }
1604        }
1605
1606        cprintf("PC: %s\n[sn:%llu]\n[tid:%i]\n"
1607                "Issued:%i\nSquashed:%i\n",
1608                (*inst_list_it)->pcState(),
1609                (*inst_list_it)->seqNum,
1610                (*inst_list_it)->threadNumber,
1611                (*inst_list_it)->isIssued(),
1612                (*inst_list_it)->isSquashed());
1613
1614        if ((*inst_list_it)->isMemRef()) {
1615            cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone());
1616        }
1617
1618        cprintf("\n");
1619
1620        inst_list_it++;
1621        ++num;
1622    }
1623}
1624
1625#endif//__CPU_O3_INST_QUEUE_IMPL_HH__
1626