inst_queue_impl.hh revision 1684
1// Todo:
2// Current ordering allows for 0 cycle added-to-scheduled.  Could maybe fake
3// it; either do in reverse order, or have added instructions put into a
4// different ready queue that, in scheduleRreadyInsts(), gets put onto the
5// normal ready queue.  This would however give only a one cycle delay,
6// but probably is more flexible to actually add in a delay parameter than
7// just running it backwards.
8
9#include <vector>
10
11#include "sim/universe.hh"
12#include "cpu/beta_cpu/inst_queue.hh"
13
14// Either compile error or max int due to sign extension.
15// Blatant hack to avoid compile warnings.
16const InstSeqNum MaxInstSeqNum = 0 - 1;
17
18template <class Impl>
19InstructionQueue<Impl>::InstructionQueue(Params &params)
20    : memDepUnit(params),
21      numEntries(params.numIQEntries),
22      intWidth(params.executeIntWidth),
23      floatWidth(params.executeFloatWidth),
24      branchWidth(params.executeBranchWidth),
25      memoryWidth(params.executeMemoryWidth),
26      totalWidth(params.issueWidth),
27      numPhysIntRegs(params.numPhysIntRegs),
28      numPhysFloatRegs(params.numPhysFloatRegs),
29      commitToIEWDelay(params.commitToIEWDelay)
30{
31    // Initialize the number of free IQ entries.
32    freeEntries = numEntries;
33
34    // Set the number of physical registers as the number of int + float
35    numPhysRegs = numPhysIntRegs + numPhysFloatRegs;
36
37    DPRINTF(IQ, "IQ: There are %i physical registers.\n", numPhysRegs);
38
39    //Create an entry for each physical register within the
40    //dependency graph.
41    dependGraph = new DependencyEntry[numPhysRegs];
42
43    // Resize the register scoreboard.
44    regScoreboard.resize(numPhysRegs);
45
46    // Initialize all the head pointers to point to NULL, and all the
47    // entries as unready.
48    // Note that in actuality, the registers corresponding to the logical
49    // registers start off as ready.  However this doesn't matter for the
50    // IQ as the instruction should have been correctly told if those
51    // registers are ready in rename.  Thus it can all be initialized as
52    // unready.
53    for (int i = 0; i < numPhysRegs; ++i)
54    {
55        dependGraph[i].next = NULL;
56        dependGraph[i].inst = NULL;
57        regScoreboard[i] = false;
58    }
59
60}
61
62template <class Impl>
63void
64InstructionQueue<Impl>::regStats()
65{
66    iqInstsAdded
67        .name(name() + ".iqInstsAdded")
68        .desc("Number of instructions added to the IQ (excludes non-spec)")
69        .prereq(iqInstsAdded);
70
71    iqNonSpecInstsAdded
72        .name(name() + ".iqNonSpecInstsAdded")
73        .desc("Number of non-speculative instructions added to the IQ")
74        .prereq(iqNonSpecInstsAdded);
75
76//    iqIntInstsAdded;
77
78    iqIntInstsIssued
79        .name(name() + ".iqIntInstsIssued")
80        .desc("Number of integer instructions issued")
81        .prereq(iqIntInstsIssued);
82
83//    iqFloatInstsAdded;
84
85    iqFloatInstsIssued
86        .name(name() + ".iqFloatInstsIssued")
87        .desc("Number of float instructions issued")
88        .prereq(iqFloatInstsIssued);
89
90//    iqBranchInstsAdded;
91
92    iqBranchInstsIssued
93        .name(name() + ".iqBranchInstsIssued")
94        .desc("Number of branch instructions issued")
95        .prereq(iqBranchInstsIssued);
96
97//    iqMemInstsAdded;
98
99    iqMemInstsIssued
100        .name(name() + ".iqMemInstsIssued")
101        .desc("Number of memory instructions issued")
102        .prereq(iqMemInstsIssued);
103
104//    iqMiscInstsAdded;
105
106    iqMiscInstsIssued
107        .name(name() + ".iqMiscInstsIssued")
108        .desc("Number of miscellaneous instructions issued")
109        .prereq(iqMiscInstsIssued);
110
111    iqSquashedInstsIssued
112        .name(name() + ".iqSquashedInstsIssued")
113        .desc("Number of squashed instructions issued")
114        .prereq(iqSquashedInstsIssued);
115
116    iqLoopSquashStalls
117        .name(name() + ".iqLoopSquashStalls")
118        .desc("Number of times issue loop had to restart due to squashed "
119              "inst; mainly for profiling")
120        .prereq(iqLoopSquashStalls);
121
122    iqSquashedInstsExamined
123        .name(name() + ".iqSquashedInstsExamined")
124        .desc("Number of squashed instructions iterated over during squash;"
125              " mainly for profiling")
126        .prereq(iqSquashedInstsExamined);
127
128    iqSquashedOperandsExamined
129        .name(name() + ".iqSquashedOperandsExamined")
130        .desc("Number of squashed operands that are examined and possibly "
131              "removed from graph")
132        .prereq(iqSquashedOperandsExamined);
133
134    iqSquashedNonSpecRemoved
135        .name(name() + ".iqSquashedNonSpecRemoved")
136        .desc("Number of squashed non-spec instructions that were removed")
137        .prereq(iqSquashedNonSpecRemoved);
138
139    // Tell mem dependence unit to reg stats as well.
140    memDepUnit.regStats();
141}
142
143template <class Impl>
144void
145InstructionQueue<Impl>::setCPU(FullCPU *cpu_ptr)
146{
147    cpu = cpu_ptr;
148
149    tail = cpu->instList.begin();
150}
151
152template <class Impl>
153void
154InstructionQueue<Impl>::setIssueToExecuteQueue(
155                        TimeBuffer<IssueStruct> *i2e_ptr)
156{
157    DPRINTF(IQ, "IQ: Set the issue to execute queue.\n");
158    issueToExecuteQueue = i2e_ptr;
159}
160
161template <class Impl>
162void
163InstructionQueue<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
164{
165    DPRINTF(IQ, "IQ: Set the time buffer.\n");
166    timeBuffer = tb_ptr;
167
168    fromCommit = timeBuffer->getWire(-commitToIEWDelay);
169}
170
171template <class Impl>
172unsigned
173InstructionQueue<Impl>::numFreeEntries()
174{
175    return freeEntries;
176}
177
178// Might want to do something more complex if it knows how many instructions
179// will be issued this cycle.
180template <class Impl>
181bool
182InstructionQueue<Impl>::isFull()
183{
184    if (freeEntries == 0) {
185        return(true);
186    } else {
187        return(false);
188    }
189}
190
191template <class Impl>
192void
193InstructionQueue<Impl>::insert(DynInstPtr &new_inst)
194{
195    // Make sure the instruction is valid
196    assert(new_inst);
197
198    DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n",
199            new_inst->readPC());
200
201    // Check if there are any free entries.  Panic if there are none.
202    // Might want to have this return a fault in the future instead of
203    // panicing.
204    assert(freeEntries != 0);
205
206    // If the IQ currently has nothing in it, then there's a possibility
207    // that the tail iterator is invalid (might have been pointing at an
208    // instruction that was retired).  Reset the tail iterator.
209    if (freeEntries == numEntries) {
210        tail = cpu->instList.begin();
211    }
212
213    // Move the tail iterator.  Instructions may not have been issued
214    // to the IQ, so we may have to increment the iterator more than once.
215    while ((*tail) != new_inst) {
216        tail++;
217
218        // Make sure the tail iterator points at something legal.
219        assert(tail != cpu->instList.end());
220    }
221
222
223    // Decrease the number of free entries.
224    --freeEntries;
225
226    // Look through its source registers (physical regs), and mark any
227    // dependencies.
228    addToDependents(new_inst);
229
230    // Have this instruction set itself as the producer of its destination
231    // register(s).
232    createDependency(new_inst);
233
234    // If it's a memory instruction, add it to the memory dependency
235    // unit.
236    if (new_inst->isMemRef()) {
237        memDepUnit.insert(new_inst);
238        // Uh..forgot to look it up and put it on the proper dependency list
239        // if the instruction should not go yet.
240    } else {
241        // If the instruction is ready then add it to the ready list.
242        addIfReady(new_inst);
243    }
244
245    ++iqInstsAdded;
246
247    assert(freeEntries == (numEntries - countInsts()));
248}
249
250template <class Impl>
251void
252InstructionQueue<Impl>::insertNonSpec(DynInstPtr &inst)
253{
254    nonSpecInsts[inst->seqNum] = inst;
255
256    // @todo: Clean up this code; can do it by setting inst as unable
257    // to issue, then calling normal insert on the inst.
258
259    // Make sure the instruction is valid
260    assert(inst);
261
262    DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n",
263            inst->readPC());
264
265    // Check if there are any free entries.  Panic if there are none.
266    // Might want to have this return a fault in the future instead of
267    // panicing.
268    assert(freeEntries != 0);
269
270    // If the IQ currently has nothing in it, then there's a possibility
271    // that the tail iterator is invalid (might have been pointing at an
272    // instruction that was retired).  Reset the tail iterator.
273    if (freeEntries == numEntries) {
274        tail = cpu->instList.begin();
275    }
276
277    // Move the tail iterator.  Instructions may not have been issued
278    // to the IQ, so we may have to increment the iterator more than once.
279    while ((*tail) != inst) {
280        tail++;
281
282        // Make sure the tail iterator points at something legal.
283        assert(tail != cpu->instList.end());
284    }
285
286    // Decrease the number of free entries.
287    --freeEntries;
288
289    // Have this instruction set itself as the producer of its destination
290    // register(s).
291    createDependency(inst);
292
293    // If it's a memory instruction, add it to the memory dependency
294    // unit.
295    if (inst->isMemRef()) {
296        memDepUnit.insertNonSpec(inst);
297    }
298
299    ++iqNonSpecInstsAdded;
300}
301
302// Slightly hack function to advance the tail iterator in the case that
303// the IEW stage issues an instruction that is not added to the IQ.  This
304// is needed in case a long chain of such instructions occurs.
305// I don't think this is used anymore.
306template <class Impl>
307void
308InstructionQueue<Impl>::advanceTail(DynInstPtr &inst)
309{
310    // Make sure the instruction is valid
311    assert(inst);
312
313    DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n",
314            inst->readPC());
315
316    // Check if there are any free entries.  Panic if there are none.
317    // Might want to have this return a fault in the future instead of
318    // panicing.
319    assert(freeEntries != 0);
320
321    // If the IQ currently has nothing in it, then there's a possibility
322    // that the tail iterator is invalid (might have been pointing at an
323    // instruction that was retired).  Reset the tail iterator.
324    if (freeEntries == numEntries) {
325        tail = cpu->instList.begin();
326    }
327
328    // Move the tail iterator.  Instructions may not have been issued
329    // to the IQ, so we may have to increment the iterator more than once.
330    while ((*tail) != inst) {
331        tail++;
332
333        // Make sure the tail iterator points at something legal.
334        assert(tail != cpu->instList.end());
335    }
336
337    assert(freeEntries <= numEntries);
338
339    // Have this instruction set itself as the producer of its destination
340    // register(s).
341    createDependency(inst);
342}
343
344// Need to make sure the number of float and integer instructions
345// issued does not exceed the total issue bandwidth.
346// @todo: Figure out a better way to remove the squashed items from the
347// lists.  Checking the top item of each list to see if it's squashed
348// wastes time and forces jumps.
349template <class Impl>
350void
351InstructionQueue<Impl>::scheduleReadyInsts()
352{
353    DPRINTF(IQ, "IQ: Attempting to schedule ready instructions from "
354                "the IQ.\n");
355
356    int int_issued = 0;
357    int float_issued = 0;
358    int branch_issued = 0;
359    int memory_issued = 0;
360    int squashed_issued = 0;
361    int total_issued = 0;
362
363    IssueStruct *i2e_info = issueToExecuteQueue->access(0);
364
365    bool insts_available = !readyBranchInsts.empty() ||
366        !readyIntInsts.empty() ||
367        !readyFloatInsts.empty() ||
368        !memDepUnit.empty() ||
369        !readyMiscInsts.empty() ||
370        !squashedInsts.empty();
371
372    // Note: Requires a globally defined constant.
373    InstSeqNum oldest_inst = MaxInstSeqNum;
374    InstList list_with_oldest = None;
375
376    // Temporary values.
377    DynInstPtr int_head_inst;
378    DynInstPtr float_head_inst;
379    DynInstPtr branch_head_inst;
380    DynInstPtr mem_head_inst;
381    DynInstPtr misc_head_inst;
382    DynInstPtr squashed_head_inst;
383
384    // Somewhat nasty code to look at all of the lists where issuable
385    // instructions are located, and choose the oldest instruction among
386    // those lists.  Consider a rewrite in the future.
387    while (insts_available && total_issued < totalWidth)
388    {
389        // Set this to false.  Each if-block is required to set it to true
390        // if there were instructions available this check.  This will cause
391        // this loop to run once more than necessary, but avoids extra calls.
392        insts_available = false;
393
394        oldest_inst = MaxInstSeqNum;
395
396        list_with_oldest = None;
397
398        if (!readyIntInsts.empty() &&
399            int_issued < intWidth) {
400
401            insts_available = true;
402
403            int_head_inst = readyIntInsts.top();
404
405            if (int_head_inst->isSquashed()) {
406                readyIntInsts.pop();
407
408                ++iqLoopSquashStalls;
409
410                continue;
411            }
412
413            oldest_inst = int_head_inst->seqNum;
414
415            list_with_oldest = Int;
416        }
417
418        if (!readyFloatInsts.empty() &&
419            float_issued < floatWidth) {
420
421            insts_available = true;
422
423            float_head_inst = readyFloatInsts.top();
424
425            if (float_head_inst->isSquashed()) {
426                readyFloatInsts.pop();
427
428                ++iqLoopSquashStalls;
429
430                continue;
431            } else if (float_head_inst->seqNum < oldest_inst) {
432                oldest_inst = float_head_inst->seqNum;
433
434                list_with_oldest = Float;
435            }
436        }
437
438        if (!readyBranchInsts.empty() &&
439            branch_issued < branchWidth) {
440
441            insts_available = true;
442
443            branch_head_inst = readyBranchInsts.top();
444
445            if (branch_head_inst->isSquashed()) {
446                readyBranchInsts.pop();
447
448                ++iqLoopSquashStalls;
449
450                continue;
451            } else if (branch_head_inst->seqNum < oldest_inst) {
452                oldest_inst = branch_head_inst->seqNum;
453
454                list_with_oldest = Branch;
455            }
456
457        }
458
459        if (!memDepUnit.empty() &&
460            memory_issued < memoryWidth) {
461
462            insts_available = true;
463
464            mem_head_inst = memDepUnit.top();
465
466            if (mem_head_inst->isSquashed()) {
467                memDepUnit.pop();
468
469                ++iqLoopSquashStalls;
470
471                continue;
472            } else if (mem_head_inst->seqNum < oldest_inst) {
473                oldest_inst = mem_head_inst->seqNum;
474
475                list_with_oldest = Memory;
476            }
477        }
478
479        if (!readyMiscInsts.empty()) {
480
481            insts_available = true;
482
483            misc_head_inst = readyMiscInsts.top();
484
485            if (misc_head_inst->isSquashed()) {
486                readyMiscInsts.pop();
487
488                ++iqLoopSquashStalls;
489
490                continue;
491            } else if (misc_head_inst->seqNum < oldest_inst) {
492                oldest_inst = misc_head_inst->seqNum;
493
494                list_with_oldest = Misc;
495            }
496        }
497
498        if (!squashedInsts.empty()) {
499
500            insts_available = true;
501
502            squashed_head_inst = squashedInsts.top();
503
504            if (squashed_head_inst->seqNum < oldest_inst) {
505                list_with_oldest = Squashed;
506            }
507
508        }
509
510        DynInstPtr issuing_inst = NULL;
511
512        switch (list_with_oldest) {
513          case None:
514            DPRINTF(IQ, "IQ: Not able to schedule any instructions. Issuing "
515                    "inst is %#x.\n", issuing_inst);
516            break;
517
518          case Int:
519            issuing_inst = int_head_inst;
520            readyIntInsts.pop();
521            ++int_issued;
522            DPRINTF(IQ, "IQ: Issuing integer instruction PC %#x.\n",
523                    issuing_inst->readPC());
524            break;
525
526          case Float:
527            issuing_inst = float_head_inst;
528            readyFloatInsts.pop();
529            ++float_issued;
530            DPRINTF(IQ, "IQ: Issuing float instruction PC %#x.\n",
531                    issuing_inst->readPC());
532            break;
533
534          case Branch:
535            issuing_inst = branch_head_inst;
536            readyBranchInsts.pop();
537            ++branch_issued;
538            DPRINTF(IQ, "IQ: Issuing branch instruction PC %#x.\n",
539                    issuing_inst->readPC());
540            break;
541
542          case Memory:
543            issuing_inst = mem_head_inst;
544
545            memDepUnit.pop();
546            ++memory_issued;
547            DPRINTF(IQ, "IQ: Issuing memory instruction PC %#x.\n",
548                    issuing_inst->readPC());
549            break;
550
551          case Misc:
552            issuing_inst = misc_head_inst;
553            readyMiscInsts.pop();
554
555            ++iqMiscInstsIssued;
556
557            DPRINTF(IQ, "IQ: Issuing a miscellaneous instruction PC %#x.\n",
558                    issuing_inst->readPC());
559            break;
560
561          case Squashed:
562            assert(0 && "Squashed insts should not issue any more!");
563            squashedInsts.pop();
564            // Set the squashed instruction as able to commit so that commit
565            // can just drop it from the ROB.  This is a bit faked.
566            ++squashed_issued;
567            ++freeEntries;
568
569            DPRINTF(IQ, "IQ: Issuing squashed instruction PC %#x.\n",
570                    squashed_head_inst->readPC());
571            break;
572        }
573
574        if (list_with_oldest != None && list_with_oldest != Squashed) {
575            i2e_info->insts[total_issued] = issuing_inst;
576            i2e_info->size++;
577
578            issuing_inst->setIssued();
579
580            ++freeEntries;
581            ++total_issued;
582        }
583
584        assert(freeEntries == (numEntries - countInsts()));
585    }
586
587    iqIntInstsIssued += int_issued;
588    iqFloatInstsIssued += float_issued;
589    iqBranchInstsIssued += branch_issued;
590    iqMemInstsIssued += memory_issued;
591    iqSquashedInstsIssued += squashed_issued;
592}
593
594template <class Impl>
595void
596InstructionQueue<Impl>::scheduleNonSpec(const InstSeqNum &inst)
597{
598    DPRINTF(IQ, "IQ: Marking nonspeculative instruction with sequence "
599            "number %i as ready to execute.\n", inst);
600
601    non_spec_it_t inst_it = nonSpecInsts.find(inst);
602
603    assert(inst_it != nonSpecInsts.end());
604
605    // Mark this instruction as ready to issue.
606    (*inst_it).second->setCanIssue();
607
608    // Now schedule the instruction.
609    if (!(*inst_it).second->isMemRef()) {
610        addIfReady((*inst_it).second);
611    } else {
612        memDepUnit.nonSpecInstReady((*inst_it).second);
613    }
614
615    nonSpecInsts.erase(inst_it);
616}
617
618template <class Impl>
619void
620InstructionQueue<Impl>::wakeDependents(DynInstPtr &completed_inst)
621{
622    DPRINTF(IQ, "IQ: Waking dependents of completed instruction.\n");
623    //Look at the physical destination register of the DynInst
624    //and look it up on the dependency graph.  Then mark as ready
625    //any instructions within the instruction queue.
626    DependencyEntry *curr;
627
628    // Tell the memory dependence unit to wake any dependents on this
629    // instruction if it is a memory instruction.
630
631    if (completed_inst->isMemRef()) {
632        memDepUnit.wakeDependents(completed_inst);
633    }
634
635    for (int dest_reg_idx = 0;
636         dest_reg_idx < completed_inst->numDestRegs();
637         dest_reg_idx++)
638    {
639        PhysRegIndex dest_reg =
640            completed_inst->renamedDestRegIdx(dest_reg_idx);
641
642        // Special case of uniq or control registers.  They are not
643        // handled by the IQ and thus have no dependency graph entry.
644        // @todo Figure out a cleaner way to handle this.
645        if (dest_reg >= numPhysRegs) {
646            continue;
647        }
648
649        DPRINTF(IQ, "IQ: Waking any dependents on register %i.\n",
650                (int) dest_reg);
651
652        //Maybe abstract this part into a function.
653        //Go through the dependency chain, marking the registers as ready
654        //within the waiting instructions.
655        while (dependGraph[dest_reg].next) {
656
657            curr = dependGraph[dest_reg].next;
658
659            DPRINTF(IQ, "IQ: Waking up a dependent instruction, PC%#x.\n",
660                    curr->inst->readPC());
661
662            // Might want to give more information to the instruction
663            // so that it knows which of its source registers is ready.
664            // However that would mean that the dependency graph entries
665            // would need to hold the src_reg_idx.
666            curr->inst->markSrcRegReady();
667
668            addIfReady(curr->inst);
669
670            dependGraph[dest_reg].next = curr->next;
671
672            DependencyEntry::mem_alloc_counter--;
673
674            curr->inst = NULL;
675
676            delete curr;
677        }
678
679        // Reset the head node now that all of its dependents have been woken
680        // up.
681        dependGraph[dest_reg].next = NULL;
682        dependGraph[dest_reg].inst = NULL;
683
684        // Mark the scoreboard as having that register ready.
685        regScoreboard[dest_reg] = true;
686    }
687}
688
689template <class Impl>
690void
691InstructionQueue<Impl>::violation(DynInstPtr &store,
692                                  DynInstPtr &faulting_load)
693{
694    memDepUnit.violation(store, faulting_load);
695}
696
697template <class Impl>
698void
699InstructionQueue<Impl>::squash()
700{
701    DPRINTF(IQ, "IQ: Starting to squash instructions in the IQ.\n");
702
703    // Read instruction sequence number of last instruction out of the
704    // time buffer.
705    squashedSeqNum = fromCommit->commitInfo.doneSeqNum;
706
707    // Setup the squash iterator to point to the tail.
708    squashIt = tail;
709
710    // Call doSquash if there are insts in the IQ
711    if (freeEntries != numEntries) {
712        doSquash();
713    }
714
715    // Also tell the memory dependence unit to squash.
716    memDepUnit.squash(squashedSeqNum);
717}
718
719template <class Impl>
720void
721InstructionQueue<Impl>::doSquash()
722{
723    // Make sure the squash iterator isn't pointing to nothing.
724    assert(squashIt != cpu->instList.end());
725    // Make sure the squashed sequence number is valid.
726    assert(squashedSeqNum != 0);
727
728    DPRINTF(IQ, "IQ: Squashing instructions in the IQ.\n");
729
730    // Squash any instructions younger than the squashed sequence number
731    // given.
732    while ((*squashIt)->seqNum > squashedSeqNum) {
733        DynInstPtr squashed_inst = (*squashIt);
734
735        // Only handle the instruction if it actually is in the IQ and
736        // hasn't already been squashed in the IQ.
737        if (!squashed_inst->isIssued() &&
738            !squashed_inst->isSquashedInIQ()) {
739
740            // Remove the instruction from the dependency list.
741            // Hack for now: These below don't add themselves to the
742            // dependency list, so don't try to remove them.
743            if (!squashed_inst->isNonSpeculative()/* &&
744                                                     !squashed_inst->isStore()*/
745                ) {
746
747                for (int src_reg_idx = 0;
748                     src_reg_idx < squashed_inst->numSrcRegs();
749                     src_reg_idx++)
750                {
751                    PhysRegIndex src_reg =
752                        squashed_inst->renamedSrcRegIdx(src_reg_idx);
753
754                    // Only remove it from the dependency graph if it was
755                    // placed there in the first place.
756                    // HACK: This assumes that instructions woken up from the
757                    // dependency chain aren't informed that a specific src
758                    // register has become ready.  This may not always be true
759                    // in the future.
760                    if (!squashed_inst->isReadySrcRegIdx(src_reg_idx) &&
761                        src_reg < numPhysRegs) {
762                        dependGraph[src_reg].remove(squashed_inst);
763                    }
764
765                    ++iqSquashedOperandsExamined;
766                }
767
768                // Might want to remove producers as well.
769            } else {
770                nonSpecInsts[squashed_inst->seqNum] = NULL;
771
772                nonSpecInsts.erase(squashed_inst->seqNum);
773
774                ++iqSquashedNonSpecRemoved;
775            }
776
777            // Might want to also clear out the head of the dependency graph.
778
779            // Mark it as squashed within the IQ.
780            squashed_inst->setSquashedInIQ();
781
782//            squashedInsts.push(squashed_inst);
783            squashed_inst->setIssued();
784            squashed_inst->setCanCommit();
785
786            ++freeEntries;
787
788            DPRINTF(IQ, "IQ: Instruction PC %#x squashed.\n",
789                    squashed_inst->readPC());
790        }
791
792        --squashIt;
793        ++iqSquashedInstsExamined;
794    }
795
796    assert(freeEntries <= numEntries);
797
798    if (freeEntries == numEntries) {
799        tail = cpu->instList.end();
800    }
801
802}
803
804template <class Impl>
805void
806InstructionQueue<Impl>::stopSquash()
807{
808    // Clear up the squash variables to ensure that squashing doesn't
809    // get called improperly.
810    squashedSeqNum = 0;
811
812    squashIt = cpu->instList.end();
813}
814
815template <class Impl>
816void
817InstructionQueue<Impl>::DependencyEntry::insert(DynInstPtr &new_inst)
818{
819    //Add this new, dependent instruction at the head of the dependency
820    //chain.
821
822    // First create the entry that will be added to the head of the
823    // dependency chain.
824    DependencyEntry *new_entry = new DependencyEntry;
825    new_entry->next = this->next;
826    new_entry->inst = new_inst;
827
828    // Then actually add it to the chain.
829    this->next = new_entry;
830
831    ++mem_alloc_counter;
832}
833
834template <class Impl>
835void
836InstructionQueue<Impl>::DependencyEntry::remove(DynInstPtr &inst_to_remove)
837{
838    DependencyEntry *prev = this;
839    DependencyEntry *curr = this->next;
840
841    // Make sure curr isn't NULL.  Because this instruction is being
842    // removed from a dependency list, it must have been placed there at
843    // an earlier time.  The dependency chain should not be empty,
844    // unless the instruction dependent upon it is already ready.
845    if (curr == NULL) {
846        return;
847    }
848
849    // Find the instruction to remove within the dependency linked list.
850    while(curr->inst != inst_to_remove)
851    {
852        prev = curr;
853        curr = curr->next;
854
855        assert(curr != NULL);
856    }
857
858    // Now remove this instruction from the list.
859    prev->next = curr->next;
860
861    --mem_alloc_counter;
862
863    // Could push this off to the destructor of DependencyEntry
864    curr->inst = NULL;
865
866    delete curr;
867}
868
869template <class Impl>
870bool
871InstructionQueue<Impl>::addToDependents(DynInstPtr &new_inst)
872{
873    // Loop through the instruction's source registers, adding
874    // them to the dependency list if they are not ready.
875    int8_t total_src_regs = new_inst->numSrcRegs();
876    bool return_val = false;
877
878    for (int src_reg_idx = 0;
879         src_reg_idx < total_src_regs;
880         src_reg_idx++)
881    {
882        // Only add it to the dependency graph if it's not ready.
883        if (!new_inst->isReadySrcRegIdx(src_reg_idx)) {
884            PhysRegIndex src_reg = new_inst->renamedSrcRegIdx(src_reg_idx);
885
886            // Check the IQ's scoreboard to make sure the register
887            // hasn't become ready while the instruction was in flight
888            // between stages.  Only if it really isn't ready should
889            // it be added to the dependency graph.
890            if (src_reg >= numPhysRegs) {
891                continue;
892            } else if (regScoreboard[src_reg] == false) {
893                DPRINTF(IQ, "IQ: Instruction PC %#x has src reg %i that "
894                        "is being added to the dependency chain.\n",
895                        new_inst->readPC(), src_reg);
896
897                dependGraph[src_reg].insert(new_inst);
898
899                // Change the return value to indicate that something
900                // was added to the dependency graph.
901                return_val = true;
902            } else {
903                DPRINTF(IQ, "IQ: Instruction PC %#x has src reg %i that "
904                        "became ready before it reached the IQ.\n",
905                        new_inst->readPC(), src_reg);
906                // Mark a register ready within the instruction.
907                new_inst->markSrcRegReady();
908            }
909        }
910    }
911
912    return return_val;
913}
914
915template <class Impl>
916void
917InstructionQueue<Impl>::createDependency(DynInstPtr &new_inst)
918{
919    //Actually nothing really needs to be marked when an
920    //instruction becomes the producer of a register's value,
921    //but for convenience a ptr to the producing instruction will
922    //be placed in the head node of the dependency links.
923    int8_t total_dest_regs = new_inst->numDestRegs();
924
925    for (int dest_reg_idx = 0;
926         dest_reg_idx < total_dest_regs;
927         dest_reg_idx++)
928    {
929        PhysRegIndex dest_reg = new_inst->renamedDestRegIdx(dest_reg_idx);
930
931        // Instructions that use the misc regs will have a reg number
932        // higher than the normal physical registers.  In this case these
933        // registers are not renamed, and there is no need to track
934        // dependencies as these instructions must be executed at commit.
935        if (dest_reg >= numPhysRegs) {
936            continue;
937        }
938
939        dependGraph[dest_reg].inst = new_inst;
940
941        if (dependGraph[dest_reg].next) {
942            dumpDependGraph();
943            panic("IQ: Dependency graph not empty!");
944        }
945
946        // Mark the scoreboard to say it's not yet ready.
947        regScoreboard[dest_reg] = false;
948    }
949}
950
951template <class Impl>
952void
953InstructionQueue<Impl>::addIfReady(DynInstPtr &inst)
954{
955    //If the instruction now has all of its source registers
956    // available, then add it to the list of ready instructions.
957    if (inst->readyToIssue()) {
958
959        //Add the instruction to the proper ready list.
960        if (inst->isControl()) {
961
962            DPRINTF(IQ, "IQ: Branch instruction is ready to issue, "
963                    "putting it onto the ready list, PC %#x.\n",
964                    inst->readPC());
965            readyBranchInsts.push(inst);
966
967        } else if (inst->isMemRef()) {
968
969            DPRINTF(IQ, "IQ: Checking if memory instruction can issue.\n");
970
971            // Message to the mem dependence unit that this instruction has
972            // its registers ready.
973
974            memDepUnit.regsReady(inst);
975
976#if 0
977            if (memDepUnit.readyToIssue(inst)) {
978                DPRINTF(IQ, "IQ: Memory instruction is ready to issue, "
979                        "putting it onto the ready list, PC %#x.\n",
980                        inst->readPC());
981                readyMemInsts.push(inst);
982            } else {
983                // Make dependent on the store.
984                // Will need some way to get the store instruction it should
985                // be dependent upon; then when the store issues it can
986                // put the instruction on the ready list.
987                // Yet another tree?
988                assert(0 && "Instruction has no way to actually issue");
989            }
990#endif
991
992        } else if (inst->isInteger()) {
993
994            DPRINTF(IQ, "IQ: Integer instruction is ready to issue, "
995                    "putting it onto the ready list, PC %#x.\n",
996                    inst->readPC());
997            readyIntInsts.push(inst);
998
999        } else if (inst->isFloating()) {
1000
1001            DPRINTF(IQ, "IQ: Floating instruction is ready to issue, "
1002                    "putting it onto the ready list, PC %#x.\n",
1003                    inst->readPC());
1004            readyFloatInsts.push(inst);
1005
1006        } else {
1007            DPRINTF(IQ, "IQ: Miscellaneous instruction is ready to issue, "
1008                    "putting it onto the ready list, PC %#x..\n",
1009                    inst->readPC());
1010
1011            readyMiscInsts.push(inst);
1012        }
1013    }
1014}
1015
1016/*
1017 * Caution, this function must not be called prior to tail being updated at
1018 * least once, otherwise it will fail the assertion.  This is because
1019 * instList.begin() actually changes upon the insertion of an element into the
1020 * list when the list is empty.
1021 */
1022template <class Impl>
1023int
1024InstructionQueue<Impl>::countInsts()
1025{
1026    ListIt count_it = cpu->instList.begin();
1027    int total_insts = 0;
1028
1029    if (tail == cpu->instList.end())
1030        return 0;
1031
1032    while (count_it != tail) {
1033        if (!(*count_it)->isIssued()) {
1034            ++total_insts;
1035        }
1036
1037        ++count_it;
1038
1039        assert(count_it != cpu->instList.end());
1040    }
1041
1042    // Need to count the tail iterator as well.
1043    if (count_it != cpu->instList.end() &&
1044        (*count_it) &&
1045        !(*count_it)->isIssued()) {
1046        ++total_insts;
1047    }
1048
1049    return total_insts;
1050}
1051
1052template <class Impl>
1053void
1054InstructionQueue<Impl>::dumpDependGraph()
1055{
1056    DependencyEntry *curr;
1057
1058    for (int i = 0; i < numPhysRegs; ++i)
1059    {
1060        curr = &dependGraph[i];
1061
1062        if (curr->inst) {
1063            cprintf("dependGraph[%i]: producer: %#x consumer: ", i,
1064                    curr->inst->readPC());
1065        } else {
1066            cprintf("dependGraph[%i]: No producer. consumer: ", i);
1067        }
1068
1069        while (curr->next != NULL) {
1070            curr = curr->next;
1071
1072            cprintf("%#x ", curr->inst->readPC());
1073        }
1074
1075        cprintf("\n");
1076    }
1077}
1078
1079template <class Impl>
1080void
1081InstructionQueue<Impl>::dumpLists()
1082{
1083    cprintf("Ready integer list size: %i\n", readyIntInsts.size());
1084
1085    cprintf("Ready float list size: %i\n", readyFloatInsts.size());
1086
1087    cprintf("Ready branch list size: %i\n", readyBranchInsts.size());
1088
1089    cprintf("Ready misc list size: %i\n", readyMiscInsts.size());
1090
1091    cprintf("Squashed list size: %i\n", squashedInsts.size());
1092
1093    cprintf("Non speculative list size: %i\n", nonSpecInsts.size());
1094
1095    non_spec_it_t non_spec_it = nonSpecInsts.begin();
1096
1097    cprintf("Non speculative list: ");
1098
1099    while (non_spec_it != nonSpecInsts.end()) {
1100        cprintf("%#x ", (*non_spec_it).second->readPC());
1101        ++non_spec_it;
1102    }
1103
1104    cprintf("\n");
1105
1106}
1107