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