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